From 99980506540d9546dad31223a6eadf126ba68121 Mon Sep 17 00:00:00 2001
From: TTimo <ttimo@ttimo.net>
Date: Sun, 4 Nov 2007 03:34:51 +0000
Subject: [PATCH] set eol-style

git-svn-id: svn://svn.icculus.org/gtkradiant/GtkRadiant/branches/ZeroRadiant@183 8a3a26a2-13c4-0310-b231-cf6edde360e5
---
 Doxygen_files/doxy_mainpage.h                 |    90 +-
 contrib/bkgrnd2d/bkgrnd2d.h                   |   166 +-
 contrib/bkgrnd2d/dialog.h                     |    72 +-
 contrib/bkgrnd2d/plugin.h                     |   160 +-
 contrib/bobtoolz/CPortals.h                   |   126 +-
 contrib/bobtoolz/DBobView.h                   |   144 +-
 contrib/bobtoolz/DBrush.h                     |   202 +-
 contrib/bobtoolz/DEPair.h                     |    90 +-
 contrib/bobtoolz/DEntity.h                    |   230 +-
 contrib/bobtoolz/DListener.h                  |   124 +-
 contrib/bobtoolz/DMap.h                       |   112 +-
 contrib/bobtoolz/DPatch.h                     |   124 +-
 contrib/bobtoolz/DPlane.h                     |   134 +-
 contrib/bobtoolz/DPoint.h                     |    90 +-
 contrib/bobtoolz/DShape.h                     |   120 +-
 contrib/bobtoolz/DTrainDrawer.h               |   164 +-
 contrib/bobtoolz/DTreePlanter.h               |   446 +-
 contrib/bobtoolz/DVisDrawer.h                 |   116 +-
 contrib/bobtoolz/DWinding.h                   |   136 +-
 contrib/bobtoolz/ScriptParser.h               |    82 +-
 contrib/bobtoolz/StdAfx.h                     |   308 +-
 contrib/bobtoolz/bobToolz.h                   |   128 +-
 contrib/bobtoolz/bsploader.h                  |   268 +-
 contrib/bobtoolz/ctfresource_gtk.h            |    68 +-
 contrib/bobtoolz/dialogs/AboutDialog.h        |   128 +-
 contrib/bobtoolz/dialogs/AutoCaulkDialog.h    |   132 +-
 .../bobtoolz/dialogs/AutoCaulkStartDialog.h   |   142 +-
 contrib/bobtoolz/dialogs/BrushCheckDialog.h   |   130 +-
 contrib/bobtoolz/dialogs/DoorDialog.h         |   148 +-
 contrib/bobtoolz/dialogs/IntersectDialog.h    |   140 +-
 .../bobtoolz/dialogs/IntersectInfoDialog.h    |   130 +-
 contrib/bobtoolz/dialogs/PolygonDialog.h      |   148 +-
 contrib/bobtoolz/dialogs/StairDialog.h        |   148 +-
 contrib/bobtoolz/dialogs/TextureResetDialog.h |   146 +-
 contrib/bobtoolz/dialogs/dialogs-gtk.h        |   196 +-
 contrib/bobtoolz/dialogs/pathplotterdialog.h  |   140 +-
 contrib/bobtoolz/funchandlers.h               |   144 +-
 contrib/bobtoolz/interfaces/IScriptParser.h   |    46 +-
 contrib/bobtoolz/lists.h                      |    42 +-
 contrib/bobtoolz/misc.h                       |    96 +-
 contrib/bobtoolz/resource-gtk.h               |    30 +-
 contrib/bobtoolz/resource.h                   |   230 +-
 contrib/bobtoolz/shapes.h                     |    98 +-
 contrib/bobtoolz/visfind.h                    |     2 +-
 contrib/camera/camera.h                       |   324 +-
 contrib/camera/dialogs.h                      |    74 +-
 contrib/camera/funchandlers.h                 |    74 +-
 contrib/camera/listener.h                     |   128 +-
 contrib/camera/misc.h                         |   182 +-
 contrib/camera/renderer.h                     |    92 +-
 contrib/gtkgensurf/gendlgs.h                  |   302 +-
 contrib/gtkgensurf/gensurf.h                  |   790 +-
 contrib/gtkgensurf/triangle.c                 | 26472 ++++++++--------
 contrib/gtkgensurf/triangle.h                 |   576 +-
 contrib/hydratoolz/plugin.h                   |   102 +-
 contrib/prtview/AboutDialog.h                 |   144 +-
 contrib/prtview/ConfigDialog.h                |   214 +-
 contrib/prtview/LoadPortalFileDialog.h        |   154 +-
 contrib/prtview/gtkdlgs.h                     |    54 +-
 contrib/prtview/portals.h                     |   250 +-
 contrib/prtview/prtview.h                     |    58 +-
 contrib/prtview/resource.h                    |    84 +-
 contrib/prtview/stdafx.h                      |   158 +-
 docs/developer/XMLPush/StdAfx.h               |    44 +-
 docs/manual/quake3/Compile_Manual/cfgq3.c     |   156 +-
 include/aboutmsg.h                            |     4 +-
 include/gtkr_list.h                           |    46 +-
 include/gtkr_vector.h                         |    46 +-
 include/ibrush.h                              |   146 +-
 include/ibspfrontend.h                        |   154 +-
 include/icamera.h                             |    90 +-
 include/idata.h                               |   114 +-
 include/idatastream.h                         |   142 +-
 include/ieclass.h                             |   168 +-
 include/ientity.h                             |   232 +-
 include/ifilesystem.h                         |   280 +-
 include/igl.h                                 |   532 +-
 include/iimage.h                              |    80 +-
 include/imap.h                                |   164 +-
 include/imodel.h                              |   212 +-
 include/ipatch.h                              |   106 +-
 include/iplugin.h                             |    82 +-
 include/irefcount.h                           |   124 +-
 include/iscriplib.h                           |   172 +-
 include/iselectedface.h                       |   176 +-
 include/ishaders.h                            |   568 +-
 include/ishadersmanager.h                     |   204 +-
 include/isurfaceplugin.h                      |   316 +-
 include/itoolbar.h                            |   122 +-
 include/iui.h                                 |   316 +-
 include/iui_gtk.h                             |   118 +-
 include/iundo.h                               |   174 +-
 include/misc_def.h                            |   128 +-
 include/qerplugin.h                           |  1574 +-
 include/qertypes.h                            |  1822 +-
 include/qsysprintf.h                          |   134 +-
 include/stl_check.h                           |   120 +-
 include/stream_version.h                      |     6 +-
 include/version.h                             |     8 +-
 install/games/default_project.proj            |    62 +
 install/games/{qz.game => q3.game}            |     6 +-
 libs/bytebool.h                               |    40 +-
 libs/cmdlib.h                                 |   222 +-
 libs/ddslib.h                                 |   500 +-
 libs/ddslib/ddslib.c                          |  1562 +-
 libs/igl_to_qgl.h                             |  1612 +-
 libs/l_net/l_net.c                            |  1254 +-
 libs/l_net/l_net.h                            |   250 +-
 libs/l_net/l_net_berkeley.c                   |  1540 +-
 libs/l_net/l_net_wins.c                       |  1578 +-
 libs/l_net/l_net_wins.h                       |   104 +-
 libs/mathlib.h                                |   610 +-
 libs/mathlib/bbox.c                           |   782 +-
 libs/mathlib/linear.c                         |   200 +-
 libs/mathlib/m4x4.c                           |  1580 +-
 libs/mathlib/mathlib.c                        |  1186 +-
 libs/mathlib/ray.c                            |   270 +-
 libs/md5lib.h                                 |   182 +-
 libs/md5lib/md5lib.c                          |   790 +-
 libs/missing.h                                |   424 +-
 libs/multimon.h                               |   760 +-
 libs/pak/unzip.h                              |   600 +-
 libs/pakstuff.h                               |   300 +-
 libs/picomodel.h                              |   690 +-
 libs/picomodel/lwo/clip.c                     |   498 +-
 libs/picomodel/lwo/envelope.c                 |  1200 +-
 libs/picomodel/lwo/list.c                     |   202 +-
 libs/picomodel/lwo/lwio.c                     |   884 +-
 libs/picomodel/lwo/lwo2.c                     |   616 +-
 libs/picomodel/lwo/lwo2.h                     |  1302 +-
 libs/picomodel/lwo/lwob.c                     |  1446 +-
 libs/picomodel/lwo/pntspols.c                 |  1074 +-
 libs/picomodel/lwo/surface.c                  |  2008 +-
 libs/picomodel/lwo/vecmath.c                  |    74 +-
 libs/picomodel/lwo/vmap.c                     |   486 +-
 libs/picomodel/picointernal.c                 |  2706 +-
 libs/picomodel/picointernal.h                 |   410 +-
 libs/picomodel/picomodel.c                    |  3990 +--
 libs/picomodel/picomodules.c                  |   184 +-
 libs/picomodel/pm_3ds.c                       |  1542 +-
 libs/picomodel/pm_ase.c                       |  2002 +-
 libs/picomodel/pm_fm.c                        |  1340 +-
 libs/picomodel/pm_fm.h                        |   734 +-
 libs/picomodel/pm_lwo.c                       |   860 +-
 libs/picomodel/pm_md2.c                       |  1340 +-
 libs/picomodel/pm_md3.c                       |   850 +-
 libs/picomodel/pm_mdc.c                       |  1500 +-
 libs/picomodel/pm_ms3d.c                      |   988 +-
 libs/picomodel/pm_obj.c                       |  1716 +-
 libs/splines/math_angles.h                    |   390 +-
 libs/splines/math_matrix.h                    |   446 +-
 libs/splines/math_quaternion.h                |   380 +-
 libs/splines/math_vector.h                    |  1148 +-
 libs/splines/q_shared.h                       |  1592 +-
 libs/splines/splines.h                        |  2204 +-
 libs/splines/util_list.h                      |   692 +-
 libs/splines/util_str.h                       |  1634 +-
 libs/str.h                                    |   958 +-
 libs/synapse.h                                |  1322 +-
 plugins/eclassfgd/plugin.h                    |    98 +-
 plugins/entity/entity.h                       |   104 +-
 plugins/entity/entity_entitymodel.h           |   300 +-
 plugins/entity/light.h                        |    52 +-
 plugins/entity/plugin.h                       |   116 +-
 plugins/image/bmp.h                           |   202 +-
 plugins/image/image.h                         |   136 +-
 plugins/image/lbmlib.h                        |    92 +-
 plugins/imagehl/imagehl.h                     |   160 +-
 plugins/imagehl/lbmlib.h                      |    70 +-
 plugins/imagem8/imagem8.h                     |   140 +-
 plugins/imagem8/m32.h                         |   128 +-
 plugins/imagem8/m8.h                          |   122 +-
 plugins/imagepng/plugin.h                     |    62 +-
 plugins/imagewal/imagewal.h                   |   120 +-
 plugins/imagewal/q2_palette.h                 |   132 +-
 plugins/imagewal/wal.h                        |   102 +-
 plugins/map/plugin.h                          |   184 +-
 plugins/mapxml/plugin.h                       |    98 +-
 plugins/model/cpicomodel.h                    |   188 +-
 plugins/model/cpicosurface.h                  |   110 +-
 plugins/model/plugin.h                        |   152 +-
 plugins/model/surface.h                       |    74 +-
 plugins/shaders/plugin.h                      |   138 +-
 plugins/shaders/shaders.h                     |   334 +-
 plugins/spritemodel/plugin.h                  |   156 +-
 plugins/spritemodel/spritemodel.h             |   114 +-
 plugins/surface/surfacedialog.h               |    62 +-
 plugins/surface/surfdlg_plugin.h              |   188 +-
 plugins/surface_heretic2/surfacedialog.h      |    62 +-
 .../surfaceflagsdialog_heretic2.h             |   152 +-
 plugins/surface_heretic2/surfdlg_plugin.h     |   188 +-
 plugins/surface_quake2/surfacedialog.h        |    62 +-
 .../surfaceflagsdialog_quake2.h               |   216 +-
 plugins/surface_quake2/surfdlg_plugin.h       |   188 +-
 plugins/textool/2DView.h                      |   140 +-
 plugins/textool/ControlPointsManager.h        |   266 +-
 plugins/textool/StdAfx.h                      |   308 +-
 plugins/textool/resource.h                    |    46 +-
 plugins/vfspak/vfs.h                          |   104 +-
 plugins/vfspak/vfspak.h                       |   128 +-
 plugins/vfspk3/unzip-vfspk3.h                 |   598 +-
 plugins/vfspk3/vfs.h                          |   136 +-
 plugins/vfspk3/vfspk3.h                       |   126 +-
 plugins/vfswad/unwad.h                        |   222 +-
 plugins/vfswad/vfs.h                          |   138 +-
 plugins/vfswad/vfswad.h                       |   126 +-
 radiant/brush.h                               |   178 +-
 radiant/camera.h                              |   166 +-
 radiant/camwindow.h                           |   342 +-
 radiant/dialog.h                              |   170 +-
 radiant/eclass_def.h                          |    88 +-
 radiant/feedback.h                            |   250 +-
 radiant/file.h                                |   238 +-
 radiant/filters.h                             |    60 +-
 radiant/findtexturedialog.h                   |    98 +-
 radiant/glwidget.h                            |    90 +-
 radiant/glwindow.h                            |   216 +-
 radiant/groupdialog.h                         |   216 +-
 radiant/gtkfilesel-darwin.c                   |  6720 ++--
 radiant/gtkfilesel-darwin.h                   |   258 +-
 radiant/gtkfilesel-linux.c                    |  9974 +++---
 radiant/gtkfilesel-linux.h                    |   286 +-
 radiant/gtkfilesel.c                          |  6674 ++--
 radiant/gtkfilesel.h                          |   286 +-
 radiant/gtkmisc.h                             |   200 +-
 radiant/mainframe.h                           |  1818 +-
 radiant/map.h                                 |   144 +-
 radiant/parse.h                               |    70 +-
 radiant/patchdialog.h                         |   170 +-
 radiant/plugin.h                              |    90 +-
 radiant/pluginmanager.h                       |   424 +-
 radiant/points.h                              |   114 +-
 radiant/preferences.h                         |  1256 +-
 radiant/qe3.h                                 |  1824 +-
 radiant/qedefs.h                              |   256 +-
 radiant/qfiles.h                              |   960 +-
 radiant/qgl-mac.c                             |  3550 +--
 radiant/qgl.c                                 |  3594 +--
 radiant/qgl.h                                 |  1200 +-
 radiant/resource.h                            |    74 +-
 radiant/select.h                              |   164 +-
 radiant/stdafx.h                              |    78 +-
 radiant/surfacedialog.h                       |   138 +-
 radiant/surfaceplugin.h                       |    22 +-
 radiant/texmanip.h                            |    78 +-
 radiant/textures.h                            |   104 +-
 radiant/texwindow.h                           |   124 +-
 radiant/ui.h                                  |   168 +-
 radiant/undo.h                                |   132 +-
 radiant/watchbsp.h                            |   182 +-
 radiant/winding.h                             |   140 +-
 radiant/xmlstuff.h                            |   140 +-
 radiant/xywindow.h                            |   388 +-
 radiant/z.h                                   |    84 +-
 radiant/zwindow.h                             |    92 +-
 tools/quake2/common/bspfile.c                 |  1578 +-
 tools/quake2/common/bspfile.h                 |   256 +-
 tools/quake2/common/cmdlib.c                  |  2442 +-
 tools/quake2/common/cmdlib.h                  |   340 +-
 tools/quake2/common/inout.c                   |   734 +-
 tools/quake2/common/inout.h                   |   126 +-
 tools/quake2/common/l3dslib.c                 |   600 +-
 tools/quake2/common/l3dslib.h                 |    50 +-
 tools/quake2/common/lbmlib.c                  |  1674 +-
 tools/quake2/common/lbmlib.h                  |    76 +-
 tools/quake2/common/mathlib.c                 |   344 +-
 tools/quake2/common/mathlib.h                 |   150 +-
 tools/quake2/common/path_init.c               |   800 +-
 tools/quake2/common/polylib.c                 |  1284 +-
 tools/quake2/common/polylib.h                 |   108 +-
 tools/quake2/common/q2_threads.h              |    68 +-
 tools/quake2/common/qfiles.h                  |  1126 +-
 tools/quake2/common/scriplib.c                |   592 +-
 tools/quake2/common/scriplib.h                |    86 +-
 tools/quake2/common/threads.c                 |  1244 +-
 tools/quake2/common/trilib.c                  |   372 +-
 tools/quake2/common/trilib.h                  |    62 +-
 tools/quake2/q2map/brushbsp.c                 |  2658 +-
 tools/quake2/q2map/csg.c                      |  1268 +-
 tools/quake2/q2map/faces.c                    |  2152 +-
 tools/quake2/q2map/flow.c                     |  1574 +-
 tools/quake2/q2map/gldraw.c                   |   462 +-
 tools/quake2/q2map/glfile.c                   |   296 +-
 tools/quake2/q2map/leakfile.c                 |   360 +-
 tools/quake2/q2map/lightmap.c                 |  2630 +-
 tools/quake2/q2map/main.c                     |  1442 +-
 tools/quake2/q2map/map.c                      |  2034 +-
 tools/quake2/q2map/nodraw.c                   |    92 +-
 tools/quake2/q2map/patches.c                  |  1206 +-
 tools/quake2/q2map/portals.c                  |  2220 +-
 tools/quake2/q2map/prtfile.c                  |   572 +-
 tools/quake2/q2map/q2map.h                    |   100 +-
 tools/quake2/q2map/qbsp.c                     |   852 +-
 tools/quake2/q2map/qbsp.h                     |   780 +-
 tools/quake2/q2map/qrad.c                     |  1294 +-
 tools/quake2/q2map/qrad.h                     |   368 +-
 tools/quake2/q2map/qvis.c                     |  1162 +-
 tools/quake2/q2map/qvis.h                     |   338 +-
 tools/quake2/q2map/textures.c                 |   498 +-
 tools/quake2/q2map/trace.c                    |   596 +-
 tools/quake2/q2map/tree.c                     |   436 +-
 tools/quake2/q2map/writebsp.c                 |  1182 +-
 tools/quake2/qdata/anorms.h                   |   324 +-
 tools/quake2/qdata/images.c                   |  1484 +-
 tools/quake2/qdata/models.c                   |  2264 +-
 tools/quake2/qdata/qdata.c                    |  1052 +-
 tools/quake2/qdata/qdata.h                    |   150 +-
 tools/quake2/qdata/sprites.c                  |   416 +-
 tools/quake2/qdata/tables.c                   |   300 +-
 tools/quake2/qdata/video.c                    |  2476 +-
 tools/quake2/qdata_heretic2/adpcm.h           |    98 +-
 tools/quake2/qdata_heretic2/animcomp.c        |   702 +-
 tools/quake2/qdata_heretic2/animcomp.h        |    86 +-
 tools/quake2/qdata_heretic2/anorms.h          |   364 +-
 tools/quake2/qdata_heretic2/book.c            |   744 +-
 tools/quake2/qdata_heretic2/common/bspfile.c  |  1586 +-
 tools/quake2/qdata_heretic2/common/bspfile.h  |   266 +-
 tools/quake2/qdata_heretic2/common/cmdlib.c   |  2476 +-
 tools/quake2/qdata_heretic2/common/cmdlib.h   |   354 +-
 .../qdata_heretic2/common/her2_threads.h      |    70 +-
 tools/quake2/qdata_heretic2/common/inout.c    |   734 +-
 tools/quake2/qdata_heretic2/common/inout.h    |   126 +-
 tools/quake2/qdata_heretic2/common/l3dslib.c  |   952 +-
 tools/quake2/qdata_heretic2/common/l3dslib.h  |    56 +-
 tools/quake2/qdata_heretic2/common/lbmlib.c   |  2104 +-
 tools/quake2/qdata_heretic2/common/lbmlib.h   |    82 +-
 tools/quake2/qdata_heretic2/common/mathlib.c  |   352 +-
 tools/quake2/qdata_heretic2/common/mathlib.h  |   152 +-
 .../quake2/qdata_heretic2/common/path_init.c  |   808 +-
 tools/quake2/qdata_heretic2/common/polylib.c  |  1312 +-
 tools/quake2/qdata_heretic2/common/polylib.h  |   110 +-
 tools/quake2/qdata_heretic2/common/qfiles.c   |   164 +-
 tools/quake2/qdata_heretic2/common/qfiles.h   |  1238 +-
 tools/quake2/qdata_heretic2/common/scriplib.c |   594 +-
 tools/quake2/qdata_heretic2/common/scriplib.h |    88 +-
 tools/quake2/qdata_heretic2/common/threads.c  |  1240 +-
 tools/quake2/qdata_heretic2/common/token.c    |  1100 +-
 tools/quake2/qdata_heretic2/common/token.h    |   264 +-
 tools/quake2/qdata_heretic2/common/trilib.c   |  2154 +-
 tools/quake2/qdata_heretic2/common/trilib.h   |   112 +-
 tools/quake2/qdata_heretic2/fmodels.c         |  6808 ++--
 tools/quake2/qdata_heretic2/images.c          |  2794 +-
 tools/quake2/qdata_heretic2/jointed.c         |  1144 +-
 tools/quake2/qdata_heretic2/jointed.h         |    70 +-
 tools/quake2/qdata_heretic2/joints.h          |   288 +-
 tools/quake2/qdata_heretic2/models.c          |  4100 +--
 tools/quake2/qdata_heretic2/pics.c            |   396 +-
 tools/quake2/qdata_heretic2/qcommon/angles.h  |   152 +-
 .../qdata_heretic2/qcommon/arrayedlist.h      |   142 +-
 tools/quake2/qdata_heretic2/qcommon/flex.h    |    66 +-
 tools/quake2/qdata_heretic2/qcommon/fmodel.h  |   404 +-
 .../quake2/qdata_heretic2/qcommon/h2common.h  |    52 +-
 .../quake2/qdata_heretic2/qcommon/placement.h |    76 +-
 .../quake2/qdata_heretic2/qcommon/q_typedef.h |   126 +-
 tools/quake2/qdata_heretic2/qcommon/qfiles.h  |  1208 +-
 .../quake2/qdata_heretic2/qcommon/reference.c |   248 +-
 .../quake2/qdata_heretic2/qcommon/reference.h |   252 +-
 .../qdata_heretic2/qcommon/resourcemanager.c  |   318 +-
 .../qdata_heretic2/qcommon/resourcemanager.h  |    94 +-
 .../quake2/qdata_heretic2/qcommon/skeletons.c |   464 +-
 .../quake2/qdata_heretic2/qcommon/skeletons.h |   214 +-
 tools/quake2/qdata_heretic2/qd_fmodel.h       |   122 +-
 tools/quake2/qdata_heretic2/qd_skeletons.c    |  2582 +-
 tools/quake2/qdata_heretic2/qd_skeletons.h    |   168 +-
 tools/quake2/qdata_heretic2/qdata.c           |  1460 +-
 tools/quake2/qdata_heretic2/qdata.h           |   332 +-
 tools/quake2/qdata_heretic2/resource.h        |    36 +-
 tools/quake2/qdata_heretic2/sprites.c         |   698 +-
 tools/quake2/qdata_heretic2/svdcmp.c          |   980 +-
 tools/quake2/qdata_heretic2/tables.c          |   342 +-
 tools/quake2/qdata_heretic2/tmix.c            |  1396 +-
 tools/quake2/qdata_heretic2/video.c           |  2298 +-
 tools/quake3/common/aselib.c                  |  1930 +-
 tools/quake3/common/aselib.h                  |    62 +-
 tools/quake3/common/bspfile.c                 |  1412 +-
 tools/quake3/common/bspfile.h                 |   242 +-
 tools/quake3/common/cmdlib.c                  |  2306 +-
 tools/quake3/common/cmdlib.h                  |   320 +-
 tools/quake3/common/imagelib.c                |  2440 +-
 tools/quake3/common/imagelib.h                |    88 +-
 tools/quake3/common/inout.c                   |   734 +-
 tools/quake3/common/inout.h                   |   122 +-
 tools/quake3/common/l3dslib.c                 |   602 +-
 tools/quake3/common/l3dslib.h                 |    52 +-
 tools/quake3/common/mutex.c                   |   394 +-
 tools/quake3/common/mutex.h                   |    56 +-
 tools/quake3/common/polylib.c                 |  1490 +-
 tools/quake3/common/polylib.h                 |   114 +-
 tools/quake3/common/polyset.h                 |   102 +-
 tools/quake3/common/qfiles.h                  |   978 +-
 tools/quake3/common/qthreads.h                |    62 +-
 tools/quake3/common/scriplib.c                |   818 +-
 tools/quake3/common/scriplib.h                |   110 +-
 tools/quake3/common/surfaceflags.h            |   224 +-
 tools/quake3/common/threads.c                 |  1240 +-
 tools/quake3/common/trilib.c                  |   470 +-
 tools/quake3/common/trilib.h                  |    52 +-
 tools/quake3/common/unzip.c                   |  9192 +++---
 tools/quake3/common/unzip.h                   |   642 +-
 tools/quake3/common/vfs.c                     |   730 +-
 tools/quake3/common/vfs.h                     |    82 +-
 tools/quake3/q3data/3dslib.c                  |  1260 +-
 tools/quake3/q3data/3dslib.h                  |   236 +-
 tools/quake3/q3data/compress.c                |  1500 +-
 tools/quake3/q3data/images.c                  |   930 +-
 tools/quake3/q3data/md3lib.c                  |   386 +-
 tools/quake3/q3data/md3lib.h                  |    14 +-
 tools/quake3/q3data/models.c                  |  4268 +--
 tools/quake3/q3data/oldstuff.c                |   260 +-
 tools/quake3/q3data/p3dlib.c                  |   648 +-
 tools/quake3/q3data/p3dlib.h                  |    16 +-
 tools/quake3/q3data/polyset.c                 |   504 +-
 tools/quake3/q3data/q3data.c                  |  1286 +-
 tools/quake3/q3data/q3data.h                  |   156 +-
 tools/quake3/q3data/stripper.c                |   564 +-
 tools/quake3/q3data/video.c                   |  2264 +-
 tools/quake3/q3map2/brush.c                   |  1964 +-
 tools/quake3/q3map2/brush_primit.c            |   160 +-
 tools/quake3/q3map2/bsp.c                     |  1706 +-
 tools/quake3/q3map2/bspfile_abstract.c        |  1668 +-
 tools/quake3/q3map2/bspfile_ibsp.c            |  1168 +-
 tools/quake3/q3map2/bspfile_rbsp.c            |   678 +-
 tools/quake3/q3map2/convert_ase.c             |   748 +-
 tools/quake3/q3map2/convert_map.c             |   886 +-
 tools/quake3/q3map2/decals.c                  |  1816 +-
 tools/quake3/q3map2/facebsp.c                 |   906 +-
 tools/quake3/q3map2/fog.c                     |  1608 +-
 tools/quake3/q3map2/game_ef.h                 |   372 +-
 tools/quake3/q3map2/game_ja.h                 |   360 +-
 tools/quake3/q3map2/game_jk2.h                |   348 +-
 tools/quake3/q3map2/game_quake3.h             |   368 +-
 tools/quake3/q3map2/game_sof2.h               |   498 +-
 tools/quake3/q3map2/game_t.h                  |    68 +-
 tools/quake3/q3map2/game_tenebrae.h           |   368 +-
 tools/quake3/q3map2/game_wolf.h               |   460 +-
 tools/quake3/q3map2/game_wolfet.h             |   338 +-
 tools/quake3/q3map2/image.c                   |   934 +-
 tools/quake3/q3map2/leakfile.c                |   252 +-
 tools/quake3/q3map2/light.c                   |  4364 +--
 tools/quake3/q3map2/light_bounce.c            |  1908 +-
 tools/quake3/q3map2/light_shadows.c           |   246 +-
 tools/quake3/q3map2/light_trace.c             |  3508 +-
 tools/quake3/q3map2/light_ydnar.c             |  6258 ++--
 tools/quake3/q3map2/lightmaps.c               |   992 +-
 tools/quake3/q3map2/lightmaps_ydnar.c         |  5994 ++--
 tools/quake3/q3map2/main.c                    |   912 +-
 tools/quake3/q3map2/map.c                     |  3298 +-
 tools/quake3/q3map2/mesh.c                    |  1650 +-
 tools/quake3/q3map2/model.c                   |  1412 +-
 tools/quake3/q3map2/patch.c                   |  1048 +-
 tools/quake3/q3map2/path_init.c               |   912 +-
 tools/quake3/q3map2/portals.c                 |  1940 +-
 tools/quake3/q3map2/prtfile.c                 |   582 +-
 tools/quake3/q3map2/q3map2.h                  |  4552 +--
 tools/quake3/q3map2/shaders.c                 |  3852 +--
 tools/quake3/q3map2/surface.c                 |  7066 ++---
 tools/quake3/q3map2/surface_extra.c           |   888 +-
 tools/quake3/q3map2/surface_foliage.c         |   654 +-
 tools/quake3/q3map2/surface_fur.c             |   256 +-
 tools/quake3/q3map2/surface_meta.c            |  3252 +-
 tools/quake3/q3map2/tjunction.c               |  1454 +-
 tools/quake3/q3map2/tree.c                    |   316 +-
 tools/quake3/q3map2/vis.c                     |  2244 +-
 tools/quake3/q3map2/visflow.c                 |  3418 +-
 tools/quake3/q3map2/writebsp.c                |  1292 +-
 465 files changed, 188554 insertions(+), 188492 deletions(-)
 create mode 100644 install/games/default_project.proj
 rename install/games/{qz.game => q3.game} (57%)

diff --git a/Doxygen_files/doxy_mainpage.h b/Doxygen_files/doxy_mainpage.h
index 34e4bc50..34b43d9d 100644
--- a/Doxygen_files/doxy_mainpage.h
+++ b/Doxygen_files/doxy_mainpage.h
@@ -1,45 +1,45 @@
-/*
-** Doxygen index.html generation file
-** 
-*/
-
-/*! \mainpage +project+ Doxygen Index
-		<img src="../images/gtkr_splash.jpg" align="right" hspace="2" vspace="2">
-		\section intro Introduction
-
-		This documentation was generated from GtkRadiant source code using Doxygen.<br>
-		Generated from source in: +target+
-		
-		\section links Links
-		<b>General Links</b><br>
-		<a href="http://www.doxygen.org">Doxygen Homepage</a><br>
-		<a href="http://www.gtkradiant.com">GtkRadiant Homepage</a><br>
-		<a href="http://zerowing.idsoftare.com">Zerowing - GtkRadiant Development</a><br>
-
-		<b>Local Links</b><br>
-		<a href="../reference/index.html">Doxygen Quick Reference (Local)</a><br>
-
-		<p>
-		<b>GtkRadiant FAQ Links</b><br>
-		<a href="http://www.qeradiant.com/faq/fom-serve/cache/115.html">GtkRadiant FAQ</a><br>
-		<a href="http://www.qeradiant.com/faq/fom-serve/cache/181.html">GtkRadiant FAQ: Open Tasks</a><br>
-		<a href="http://www.qeradiant.com/faq/fom-serve/cache/116.html">GtkRadiant FAQ: Compiling instructions</a><br>
-		<a href="http://www.qeradiant.com/faq/fom-serve/cache/116.html">GtkRadiant FAQ: Creating/Submitting patches</a><br>
-		<a href="http://www.qeradiant.com/faq/fom-serve/cache/141.html">GtkRadiant FAQ: Coding Conventions & Guidelines</a><br>
-		</p>
-
-		<b>Misc Links</b><br>
-		<a href="http://www.idsoftware.com">idsoftware.com</a><br>
-		
-		<p>
-		<i>
-		* Note: The content on this page was generated from <a href="doxy__mainpage_8h.html">this</A> file.
-		It is moved into the <target> path when the doxygen documentation is generated, and removed immediately
-		afterwards.
-		</i>
-		</p>
-		
-		<i>This page generated: by <b>+user+</b> on <b>+machine+</b><br>
-    On +date+
-		</i>
-*/
+/*
+** Doxygen index.html generation file
+** 
+*/
+
+/*! \mainpage +project+ Doxygen Index
+		<img src="../images/gtkr_splash.jpg" align="right" hspace="2" vspace="2">
+		\section intro Introduction
+
+		This documentation was generated from GtkRadiant source code using Doxygen.<br>
+		Generated from source in: +target+
+		
+		\section links Links
+		<b>General Links</b><br>
+		<a href="http://www.doxygen.org">Doxygen Homepage</a><br>
+		<a href="http://www.gtkradiant.com">GtkRadiant Homepage</a><br>
+		<a href="http://zerowing.idsoftare.com">Zerowing - GtkRadiant Development</a><br>
+
+		<b>Local Links</b><br>
+		<a href="../reference/index.html">Doxygen Quick Reference (Local)</a><br>
+
+		<p>
+		<b>GtkRadiant FAQ Links</b><br>
+		<a href="http://www.qeradiant.com/faq/fom-serve/cache/115.html">GtkRadiant FAQ</a><br>
+		<a href="http://www.qeradiant.com/faq/fom-serve/cache/181.html">GtkRadiant FAQ: Open Tasks</a><br>
+		<a href="http://www.qeradiant.com/faq/fom-serve/cache/116.html">GtkRadiant FAQ: Compiling instructions</a><br>
+		<a href="http://www.qeradiant.com/faq/fom-serve/cache/116.html">GtkRadiant FAQ: Creating/Submitting patches</a><br>
+		<a href="http://www.qeradiant.com/faq/fom-serve/cache/141.html">GtkRadiant FAQ: Coding Conventions & Guidelines</a><br>
+		</p>
+
+		<b>Misc Links</b><br>
+		<a href="http://www.idsoftware.com">idsoftware.com</a><br>
+		
+		<p>
+		<i>
+		* Note: The content on this page was generated from <a href="doxy__mainpage_8h.html">this</A> file.
+		It is moved into the <target> path when the doxygen documentation is generated, and removed immediately
+		afterwards.
+		</i>
+		</p>
+		
+		<i>This page generated: by <b>+user+</b> on <b>+machine+</b><br>
+    On +date+
+		</i>
+*/
diff --git a/contrib/bkgrnd2d/bkgrnd2d.h b/contrib/bkgrnd2d/bkgrnd2d.h
index bee6e811..bf4771bb 100644
--- a/contrib/bkgrnd2d/bkgrnd2d.h
+++ b/contrib/bkgrnd2d/bkgrnd2d.h
@@ -1,83 +1,83 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// bkgrnd2d Plugin
-//
-// Code by reyalP aka Reed Mideke
-//
-// Based on spritemodel source code by hydra
-//
-
-#include "plugin.h"
-
-class CBackgroundImage {
-private:
-	qtexture_t *m_tex;
-  VIEWTYPE m_vt;
-  
-// which components of a vec3_t correspond to x and y in the image
-  unsigned m_ix,m_iy;
-
-public:
-	CBackgroundImage(VIEWTYPE vt);
-//  ~CBackgroundImage();
-
-	float m_alpha; // vertex alpha
-	bool m_bActive;
-	
-// x and y axis are in relation to the screen, not world, making rendering
-// the same for each view type. Whoever sets them is responsible for 
-// shuffling.
-// units are world units.
-// TODO should be private
-	float m_xmin,m_ymin,m_xmax,m_ymax;
-
-// load file, create new tex, cleanup old tex, set new tex
-	bool Load(const char *filename); 
-	void Cleanup(); // free texture, free tex, set make tex NULL
-	bool SetExtentsMM(); // set extents by ET mapcoordsmaxs/mapcoordsmins
-	bool SetExtentsSel(); // set extents by selection
-	void Render();
-	bool Valid() { return (m_tex && (m_xmin != m_xmax) && (m_ymin != m_ymax)); }
-};
-
-class CBackgroundRender : public IGL2DWindow {
-public:
-
-  CBackgroundRender();
-  virtual ~CBackgroundRender();
-
-protected:
-	int refCount;
-
-public:
-
-  // IGL2DWindow IGL3DWindow interface
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-	void Draw2D( VIEWTYPE vt );
-	void Register();
-};
-
-extern CBackgroundImage backgroundXY,backgroundXZ,backgroundYZ;
-extern CBackgroundRender render;
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// bkgrnd2d Plugin
+//
+// Code by reyalP aka Reed Mideke
+//
+// Based on spritemodel source code by hydra
+//
+
+#include "plugin.h"
+
+class CBackgroundImage {
+private:
+	qtexture_t *m_tex;
+  VIEWTYPE m_vt;
+  
+// which components of a vec3_t correspond to x and y in the image
+  unsigned m_ix,m_iy;
+
+public:
+	CBackgroundImage(VIEWTYPE vt);
+//  ~CBackgroundImage();
+
+	float m_alpha; // vertex alpha
+	bool m_bActive;
+	
+// x and y axis are in relation to the screen, not world, making rendering
+// the same for each view type. Whoever sets them is responsible for 
+// shuffling.
+// units are world units.
+// TODO should be private
+	float m_xmin,m_ymin,m_xmax,m_ymax;
+
+// load file, create new tex, cleanup old tex, set new tex
+	bool Load(const char *filename); 
+	void Cleanup(); // free texture, free tex, set make tex NULL
+	bool SetExtentsMM(); // set extents by ET mapcoordsmaxs/mapcoordsmins
+	bool SetExtentsSel(); // set extents by selection
+	void Render();
+	bool Valid() { return (m_tex && (m_xmin != m_xmax) && (m_ymin != m_ymax)); }
+};
+
+class CBackgroundRender : public IGL2DWindow {
+public:
+
+  CBackgroundRender();
+  virtual ~CBackgroundRender();
+
+protected:
+	int refCount;
+
+public:
+
+  // IGL2DWindow IGL3DWindow interface
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+	void Draw2D( VIEWTYPE vt );
+	void Register();
+};
+
+extern CBackgroundImage backgroundXY,backgroundXZ,backgroundYZ;
+extern CBackgroundRender render;
+
diff --git a/contrib/bkgrnd2d/dialog.h b/contrib/bkgrnd2d/dialog.h
index 7a82cdd6..b6d80430 100644
--- a/contrib/bkgrnd2d/dialog.h
+++ b/contrib/bkgrnd2d/dialog.h
@@ -1,36 +1,36 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// bkgrnd2d Plugin dialog box
-//
-// Code by reyalP aka Reed Mideke
-//
-//
-
-#ifndef _BKGRND2D_DIALOG_H_
-#define _BKGRND2D_DIALOG_H_
-
-void InitBackgroundDialog();
-void ShowBackgroundDialog();
-void ShowBackgroundDialogPG(int page);
-
-#endif // _BKGRND2D_DIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// bkgrnd2d Plugin dialog box
+//
+// Code by reyalP aka Reed Mideke
+//
+//
+
+#ifndef _BKGRND2D_DIALOG_H_
+#define _BKGRND2D_DIALOG_H_
+
+void InitBackgroundDialog();
+void ShowBackgroundDialog();
+void ShowBackgroundDialogPG(int page);
+
+#endif // _BKGRND2D_DIALOG_H_
diff --git a/contrib/bkgrnd2d/plugin.h b/contrib/bkgrnd2d/plugin.h
index 84933ae0..15fe7d62 100644
--- a/contrib/bkgrnd2d/plugin.h
+++ b/contrib/bkgrnd2d/plugin.h
@@ -1,80 +1,80 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// bkgrnd2d Plugin
-//
-// Code by reyalP aka Reed Mideke
-//
-// Based on spritemodel source code by hydra
-//
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-/*!
-\todo need general notice about lib purpose etc.
-and the external dependencies (such as GLib, STL, mathlib etc.)
-*/
-
-#include <stdio.h>
-// for CPtrArray for idata.h
-#include "missing.h"
-
-#include "synapse.h"
-#include "iplugin.h"
-#include "itoolbar.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#include "igl.h"
-#include "ifilesystem.h"
-#include "ientity.h"
-#include "idata.h"
-
-// verbose messages
-#define BKGRND2D_DEBUG
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERQglTable g_QglTable;
-extern _QERFileSystemTable g_FileSystemTable;
-extern _QEREntityTable g_EntityTable;
-extern _QERAppDataTable g_DataTable;
-extern void *g_pMainWidget;
-
-extern CSynapseServer* g_pSynapseServer;
-
-class CSynapseClientBkgrnd2d : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName();
-
-  CSynapseClientBkgrnd2d() { }
-  virtual ~CSynapseClientBkgrnd2d() { }
-};
-#define MSG_PREFIX "bkgrnd2d: "
-#define MSG_WARN "bkgrnd2d WARNING: "
-#define BKGRND2D_MINOR "bkgrnd2d"
-#define FILETYPE_KEY "bkgrnd2d"
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// bkgrnd2d Plugin
+//
+// Code by reyalP aka Reed Mideke
+//
+// Based on spritemodel source code by hydra
+//
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+/*!
+\todo need general notice about lib purpose etc.
+and the external dependencies (such as GLib, STL, mathlib etc.)
+*/
+
+#include <stdio.h>
+// for CPtrArray for idata.h
+#include "missing.h"
+
+#include "synapse.h"
+#include "iplugin.h"
+#include "itoolbar.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#include "igl.h"
+#include "ifilesystem.h"
+#include "ientity.h"
+#include "idata.h"
+
+// verbose messages
+#define BKGRND2D_DEBUG
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERQglTable g_QglTable;
+extern _QERFileSystemTable g_FileSystemTable;
+extern _QEREntityTable g_EntityTable;
+extern _QERAppDataTable g_DataTable;
+extern void *g_pMainWidget;
+
+extern CSynapseServer* g_pSynapseServer;
+
+class CSynapseClientBkgrnd2d : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName();
+
+  CSynapseClientBkgrnd2d() { }
+  virtual ~CSynapseClientBkgrnd2d() { }
+};
+#define MSG_PREFIX "bkgrnd2d: "
+#define MSG_WARN "bkgrnd2d WARNING: "
+#define BKGRND2D_MINOR "bkgrnd2d"
+#define FILETYPE_KEY "bkgrnd2d"
+
+#endif // _PLUGIN_H_
diff --git a/contrib/bobtoolz/CPortals.h b/contrib/bobtoolz/CPortals.h
index bc9d16ac..60506be8 100644
--- a/contrib/bobtoolz/CPortals.h
+++ b/contrib/bobtoolz/CPortals.h
@@ -1,63 +1,63 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "StdAfx.h"	// Added by ClassView
-
-class CBspPoint {
-public:
-	float p[3];
-};
-
-class CBspPortal {
-public:
-	CBspPortal();
-	~CBspPortal();
-
-	unsigned point_count;
-	CBspPoint *point;
-	bool Build(char *def, unsigned int pointCnt, bool bInverse);
-};
-
-
-class CBspNode {
-public:
-	CBspPortal *portal;
-	unsigned int portal_count;
-
-	bool AddPortal(char* def, unsigned int pointCnt, bool bInverse);
-	unsigned int portal_next;
-	CBspNode();
-	~CBspNode();
-};
-
-
-class CPortals {
-public:
-
-	CPortals();
-	~CPortals();
-
-	void Load(); // use filename in fn
-	void Purge();
-
-	char fn[PATH_MAX];
-	CBspNode *node;
-
-	unsigned int node_count;
-};
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "StdAfx.h"	// Added by ClassView
+
+class CBspPoint {
+public:
+	float p[3];
+};
+
+class CBspPortal {
+public:
+	CBspPortal();
+	~CBspPortal();
+
+	unsigned point_count;
+	CBspPoint *point;
+	bool Build(char *def, unsigned int pointCnt, bool bInverse);
+};
+
+
+class CBspNode {
+public:
+	CBspPortal *portal;
+	unsigned int portal_count;
+
+	bool AddPortal(char* def, unsigned int pointCnt, bool bInverse);
+	unsigned int portal_next;
+	CBspNode();
+	~CBspNode();
+};
+
+
+class CPortals {
+public:
+
+	CPortals();
+	~CPortals();
+
+	void Load(); // use filename in fn
+	void Purge();
+
+	char fn[PATH_MAX];
+	CBspNode *node;
+
+	unsigned int node_count;
+};
diff --git a/contrib/bobtoolz/DBobView.h b/contrib/bobtoolz/DBobView.h
index 4259c97a..94902607 100644
--- a/contrib/bobtoolz/DBobView.h
+++ b/contrib/bobtoolz/DBobView.h
@@ -1,72 +1,72 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DBobView.h: interface for the DBobView class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_BOBVIEW_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_BOBVIEW_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_
-
-class DListener;
-
-#define BOUNDS_ALL	0
-#define BOUNDS_APEX	1
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DBobView : 
-	public IGL2DWindow, 
-	public IGL3DWindow  
-{
-public:
-	DBobView();
-	virtual ~DBobView();
-
-protected:
-	vec3_t* path;
-	int refCount;
-public:
-	bool m_bShowExtra;
-	int boundingShow;
-	DListener* eyes;
-	float fVarGravity;
-
-	bool UpdatePath();
-	char entTarget[256];
-	char entTrigger[256];
-	void Begin(const char*, const char*, float, int, float, bool, bool);
-	bool CalculateTrajectory(vec3_t, vec3_t, float, int, float);
-
-	void SetPath(vec3_t* pPath);
-	void UnRegister();
-	void Register();
-	void Draw3D();
-	void Draw2D(VIEWTYPE vt);
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-	float fMultiplier;
-	bool m_bHooked;
-	int nPathCount;
-};
-
-#endif // !defined(AFX_BOBVIEW_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DBobView.h: interface for the DBobView class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_BOBVIEW_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_BOBVIEW_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_
+
+class DListener;
+
+#define BOUNDS_ALL	0
+#define BOUNDS_APEX	1
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DBobView : 
+	public IGL2DWindow, 
+	public IGL3DWindow  
+{
+public:
+	DBobView();
+	virtual ~DBobView();
+
+protected:
+	vec3_t* path;
+	int refCount;
+public:
+	bool m_bShowExtra;
+	int boundingShow;
+	DListener* eyes;
+	float fVarGravity;
+
+	bool UpdatePath();
+	char entTarget[256];
+	char entTrigger[256];
+	void Begin(const char*, const char*, float, int, float, bool, bool);
+	bool CalculateTrajectory(vec3_t, vec3_t, float, int, float);
+
+	void SetPath(vec3_t* pPath);
+	void UnRegister();
+	void Register();
+	void Draw3D();
+	void Draw2D(VIEWTYPE vt);
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+
+	float fMultiplier;
+	bool m_bHooked;
+	int nPathCount;
+};
+
+#endif // !defined(AFX_BOBVIEW_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DBrush.h b/contrib/bobtoolz/DBrush.h
index 7f2485cd..65013dcc 100644
--- a/contrib/bobtoolz/DBrush.h
+++ b/contrib/bobtoolz/DBrush.h
@@ -1,101 +1,101 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DBrush.h: interface for the DBrush class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DBRUSH_H__35B2C522_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DBRUSH_H__35B2C522_F0A7_11D4_ACF7_004095A18133__INCLUDED_
-
-#include "DPlane.h"
-
-#define POINT_IN_BRUSH	0
-#define POINT_ON_BRUSH	1
-#define POINT_OUT_BRUSH	2
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DBrush  
-{
-public:
-	DPlane* AddFace(vec3_t va, vec3_t vb, vec3_t vc, const char* textureName, bool bDetail);
-	void SaveToFile(FILE* pFile);
-
-	void Rotate(vec3_t vOrigin, vec3_t vRotation);
-	void RotateAboutCentre(vec3_t vRotation);
-
-	DPlane* HasPlaneInverted(DPlane* chkPlane);
-	DPlane* HasPlane(DPlane* chkPlane);
-	DPlane* AddFace(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData);
-
-	bool ResetTextures(const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation);
-	bool IsDetail();
-	bool HasTexture(const char* textureName);
-	bool IntersectsWith(DBrush *chkBrush);
-	bool IntersectsWith(DPlane* p1, DPlane* p2, vec3_t v);
-	bool IsCutByPlane(DPlane* cuttingPlane);
-	bool GetBounds(vec3_t min, vec3_t max);	
-	bool HasPoint(vec3_t pnt);
-	bool BBoxCollision(DBrush* chkBrush);
-	bool BBoxTouch(DBrush* chkBrush);
-
-	int BuildPoints();
-	void BuildBounds();
-	void BuildFromWinding(DWinding* w);
-	brush_t* BuildInRadiant(bool allowDestruction, int* changeCnt, entity_t* entity = NULL);
-
-	void ResetChecks(list<Str>* exclusionList);
-
-	void ClearFaces();
-	void ClearPoints();
-	
-	int RemoveRedundantPlanes( void );
-	void RemovePlane( DPlane* plane );
-	int PointPosition(vec3_t pnt);
-	void RemoveFromRadiant( void );
-
-	
-	void CutByPlane(DPlane* cutPlane, DBrush** newBrush1, DBrush** newBrush2);
-
-	void LoadFromBrush_t(brush_t* brush, bool textured);
-	void AddPoint(vec3_t pnt);
-
-	DPlane* FindPlaneWithClosestNormal( vec_t* normal );
-	int FindPointsForPlane( DPlane* plane, DPoint** pnts, int maxpnts );
-
-	DBrush(int ID = -1);
-	virtual ~DBrush();
-
-	bool operator== (DBrush* other);
-
-//	members
-	brush_t* QER_brush;
-	list<DPlane*> faceList;
-	list<DPoint*> pointList;
-	int m_nBrushID;
-	vec3_t bbox_min, bbox_max;
-	bool bBoundsBuilt;
-};
-
-//typedef CList<DBrush*, DBrush*> DBrushList;
-
-#endif // !defined(AFX_DBRUSH_H__35B2C522_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DBrush.h: interface for the DBrush class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DBRUSH_H__35B2C522_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_DBRUSH_H__35B2C522_F0A7_11D4_ACF7_004095A18133__INCLUDED_
+
+#include "DPlane.h"
+
+#define POINT_IN_BRUSH	0
+#define POINT_ON_BRUSH	1
+#define POINT_OUT_BRUSH	2
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DBrush  
+{
+public:
+	DPlane* AddFace(vec3_t va, vec3_t vb, vec3_t vc, const char* textureName, bool bDetail);
+	void SaveToFile(FILE* pFile);
+
+	void Rotate(vec3_t vOrigin, vec3_t vRotation);
+	void RotateAboutCentre(vec3_t vRotation);
+
+	DPlane* HasPlaneInverted(DPlane* chkPlane);
+	DPlane* HasPlane(DPlane* chkPlane);
+	DPlane* AddFace(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData);
+
+	bool ResetTextures(const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation);
+	bool IsDetail();
+	bool HasTexture(const char* textureName);
+	bool IntersectsWith(DBrush *chkBrush);
+	bool IntersectsWith(DPlane* p1, DPlane* p2, vec3_t v);
+	bool IsCutByPlane(DPlane* cuttingPlane);
+	bool GetBounds(vec3_t min, vec3_t max);	
+	bool HasPoint(vec3_t pnt);
+	bool BBoxCollision(DBrush* chkBrush);
+	bool BBoxTouch(DBrush* chkBrush);
+
+	int BuildPoints();
+	void BuildBounds();
+	void BuildFromWinding(DWinding* w);
+	brush_t* BuildInRadiant(bool allowDestruction, int* changeCnt, entity_t* entity = NULL);
+
+	void ResetChecks(list<Str>* exclusionList);
+
+	void ClearFaces();
+	void ClearPoints();
+	
+	int RemoveRedundantPlanes( void );
+	void RemovePlane( DPlane* plane );
+	int PointPosition(vec3_t pnt);
+	void RemoveFromRadiant( void );
+
+	
+	void CutByPlane(DPlane* cutPlane, DBrush** newBrush1, DBrush** newBrush2);
+
+	void LoadFromBrush_t(brush_t* brush, bool textured);
+	void AddPoint(vec3_t pnt);
+
+	DPlane* FindPlaneWithClosestNormal( vec_t* normal );
+	int FindPointsForPlane( DPlane* plane, DPoint** pnts, int maxpnts );
+
+	DBrush(int ID = -1);
+	virtual ~DBrush();
+
+	bool operator== (DBrush* other);
+
+//	members
+	brush_t* QER_brush;
+	list<DPlane*> faceList;
+	list<DPoint*> pointList;
+	int m_nBrushID;
+	vec3_t bbox_min, bbox_max;
+	bool bBoundsBuilt;
+};
+
+//typedef CList<DBrush*, DBrush*> DBrushList;
+
+#endif // !defined(AFX_DBRUSH_H__35B2C522_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DEPair.h b/contrib/bobtoolz/DEPair.h
index e5438af4..11f79045 100644
--- a/contrib/bobtoolz/DEPair.h
+++ b/contrib/bobtoolz/DEPair.h
@@ -1,45 +1,45 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DEPair.h: interface for the DEPair class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DEPAIR_H__35B2C521_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DEPAIR_H__35B2C521_F0A7_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DEPair  
-{
-public:
-	DEPair();
-	virtual ~DEPair();
-
-	void Build(char* pKey, char* pValue);
-
-	Str	key;
-	Str	value;
-};
-
-//typedef CList<DEPair*, DEPair*> DEPairList;
-
-#endif // !defined(AFX_DEPAIR_H__35B2C521_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DEPair.h: interface for the DEPair class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DEPAIR_H__35B2C521_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_DEPAIR_H__35B2C521_F0A7_11D4_ACF7_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DEPair  
+{
+public:
+	DEPair();
+	virtual ~DEPair();
+
+	void Build(char* pKey, char* pValue);
+
+	Str	key;
+	Str	value;
+};
+
+//typedef CList<DEPair*, DEPair*> DEPairList;
+
+#endif // !defined(AFX_DEPAIR_H__35B2C521_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DEntity.h b/contrib/bobtoolz/DEntity.h
index 382e8a0f..63837c84 100644
--- a/contrib/bobtoolz/DEntity.h
+++ b/contrib/bobtoolz/DEntity.h
@@ -1,115 +1,115 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DEntity.h: interface for the DEntity class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DENTITY_H__35B2C523_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DENTITY_H__35B2C523_F0A7_11D4_ACF7_004095A18133__INCLUDED_
-
-#include "DBrush.h"
-#include "DEPair.h"
-#include "DPatch.h"
-#include "StdAfx.h"	// Added by ClassView
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DEntity  
-{
-public:
-	void RemoveFromRadiant();
-	entity_t* QER_Entity;
-	int m_nID;
-
-//	Constrcution/Destruction
-	DEntity(char* classname = "worldspawn", int ID = -1);	// sets classname
-	virtual ~DEntity();
-//	---------------------------------------------
-
-//	epair functions........
-	void LoadEPairList(epair_t* epl);
-	void AddEPair(char* key, char* value);
-	void ClearEPairs();
-	DEPair* FindEPairByKey(const char* keyname);
-//	---------------------------------------------
-
-//	random functions........
-	bool ResetTextures(const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild);
-	void SaveToFile(FILE* pFile);
-	void SetClassname(char* classname);
-	int GetIDMax();
-
-	void BuildInRadiant(bool allowDestruction);
-	void ResetChecks(list<Str>* exclusionList);
-	void RemoveNonCheckBrushes(list<Str>* exclusionList, bool useDetail);
-
-	DPlane* AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID);	// slow, try not to use much
-	int GetBrushCount( void );
-	DBrush* FindBrushByPointer( brush_t* brush );
-//	---------------------------------------------
-
-
-//	bool list functions
-	void SelectBrushes(bool* selectList);
-	bool* BuildDuplicateList();
-	bool* BuildIntersectList();
-//	---------------------------------------------
-	
-
-//	brush operations
-	void ClearBrushes();	// clears brush list and frees memory for brushes
-
-	DBrush* GetBrushForID(int ID);
-	DBrush* NewBrush(int ID = -1);
-//	---------------------------------------------
-
-//	patch operations
-	void ClearPatches();
-
-	DPatch* NewPatch();
-//	---------------------------------------------
-
-//	vars
-	list<DEPair*> epairList;
-	list<DBrush*> brushList;
-	// new patches, wahey!!!
-	list<DPatch*> patchList;
-	Str m_Classname;
-//	---------------------------------------------
-
-
-	int FixBrushes(bool rebuild);
-
-	bool LoadFromEntity(int id,	bool bLoadPatches = FALSE);
-	bool LoadFromEntity(entity_t* ent, bool bLoadPatches = FALSE);
-	void LoadSelectedBrushes();
-	void LoadSelectedPatches();
-
-	bool LoadFromPrt(char* filename);
-//	---------------------------------------------
-	void SpawnString(const char* key, const char* defaultstring, const char** out);
-	void SpawnInt(const char* key, const char* defaultstring, int* out);
-	void SpawnFloat(const char* key, const char* defaultstring, float* out);
-	void SpawnVector(const char* key, const char* defaultstring, vec_t* out);
-};
-
-#endif // !defined(AFX_DENTITY_H__35B2C523_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DEntity.h: interface for the DEntity class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DENTITY_H__35B2C523_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_DENTITY_H__35B2C523_F0A7_11D4_ACF7_004095A18133__INCLUDED_
+
+#include "DBrush.h"
+#include "DEPair.h"
+#include "DPatch.h"
+#include "StdAfx.h"	// Added by ClassView
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DEntity  
+{
+public:
+	void RemoveFromRadiant();
+	entity_t* QER_Entity;
+	int m_nID;
+
+//	Constrcution/Destruction
+	DEntity(char* classname = "worldspawn", int ID = -1);	// sets classname
+	virtual ~DEntity();
+//	---------------------------------------------
+
+//	epair functions........
+	void LoadEPairList(epair_t* epl);
+	void AddEPair(char* key, char* value);
+	void ClearEPairs();
+	DEPair* FindEPairByKey(const char* keyname);
+//	---------------------------------------------
+
+//	random functions........
+	bool ResetTextures(const char* textureName, float fScale[2], float fShift[2], int rotation, const char* newTextureName, int bResetTextureName, int bResetScale[2], int bResetShift[2], int bResetRotation, bool rebuild);
+	void SaveToFile(FILE* pFile);
+	void SetClassname(char* classname);
+	int GetIDMax();
+
+	void BuildInRadiant(bool allowDestruction);
+	void ResetChecks(list<Str>* exclusionList);
+	void RemoveNonCheckBrushes(list<Str>* exclusionList, bool useDetail);
+
+	DPlane* AddFaceToBrush(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* faceData, int ID);	// slow, try not to use much
+	int GetBrushCount( void );
+	DBrush* FindBrushByPointer( brush_t* brush );
+//	---------------------------------------------
+
+
+//	bool list functions
+	void SelectBrushes(bool* selectList);
+	bool* BuildDuplicateList();
+	bool* BuildIntersectList();
+//	---------------------------------------------
+	
+
+//	brush operations
+	void ClearBrushes();	// clears brush list and frees memory for brushes
+
+	DBrush* GetBrushForID(int ID);
+	DBrush* NewBrush(int ID = -1);
+//	---------------------------------------------
+
+//	patch operations
+	void ClearPatches();
+
+	DPatch* NewPatch();
+//	---------------------------------------------
+
+//	vars
+	list<DEPair*> epairList;
+	list<DBrush*> brushList;
+	// new patches, wahey!!!
+	list<DPatch*> patchList;
+	Str m_Classname;
+//	---------------------------------------------
+
+
+	int FixBrushes(bool rebuild);
+
+	bool LoadFromEntity(int id,	bool bLoadPatches = FALSE);
+	bool LoadFromEntity(entity_t* ent, bool bLoadPatches = FALSE);
+	void LoadSelectedBrushes();
+	void LoadSelectedPatches();
+
+	bool LoadFromPrt(char* filename);
+//	---------------------------------------------
+	void SpawnString(const char* key, const char* defaultstring, const char** out);
+	void SpawnInt(const char* key, const char* defaultstring, int* out);
+	void SpawnFloat(const char* key, const char* defaultstring, float* out);
+	void SpawnVector(const char* key, const char* defaultstring, vec_t* out);
+};
+
+#endif // !defined(AFX_DENTITY_H__35B2C523_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DListener.h b/contrib/bobtoolz/DListener.h
index 0ef20577..d2166993 100644
--- a/contrib/bobtoolz/DListener.h
+++ b/contrib/bobtoolz/DListener.h
@@ -1,62 +1,62 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DListener.h: interface for the DListener class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-#include "DBobView.h"
-
-class DListener : public IWindowListener  
-{
-public:
-	DBobView* parent;
-	
-	bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y);
-	bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	bool OnKeyPressed(char *s) { return false; }
-	bool Paint() { return true; }
-	void Close() { }
-	
-	void UnRegister();
-	void Register();
-	DListener();
-	virtual ~DListener();
-
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-private:
-	bool m_bHooked;
-	int refCount;
-};
-
-#endif // !defined(AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DListener.h: interface for the DListener class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+#include "DBobView.h"
+
+class DListener : public IWindowListener  
+{
+public:
+	DBobView* parent;
+	
+	bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y);
+	bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	bool OnKeyPressed(char *s) { return false; }
+	bool Paint() { return true; }
+	void Close() { }
+	
+	void UnRegister();
+	void Register();
+	DListener();
+	virtual ~DListener();
+
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+
+private:
+	bool m_bHooked;
+	int refCount;
+};
+
+#endif // !defined(AFX_DLISTENER_H__53EBE342_F0B2_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DMap.h b/contrib/bobtoolz/DMap.h
index 1f814c23..2d572114 100644
--- a/contrib/bobtoolz/DMap.h
+++ b/contrib/bobtoolz/DMap.h
@@ -1,56 +1,56 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DMap.h: interface for the DMap class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DMAP_H__ACAE597A_D26D_49AD_AA69_EDE743DB54FA__INCLUDED_)
-#define AFX_DMAP_H__ACAE597A_D26D_49AD_AA69_EDE743DB54FA__INCLUDED_
-
-#include "DEntity.h"
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DMap  
-{
-public:
-	static void RebuildEntity(DEntity* ent);
-
-	void ResetTextures( const char* textureName, float fScale[2],      float fShift[2],      int rotation, const char* newTextureName, int bResetTextureName,  int bResetScale[2],  int bResetShift[2],  int bResetRotation);
-	void LoadAll(bool bLoadPatches = FALSE);
-	void BuildInRadiant(bool bAllowDestruction);
-	int m_nNextEntity;
-	DEntity* GetWorldSpawn();
-	void ClearEntities();
-
-	DEntity* DMap::GetEntityForID(int ID);
-	DEntity* AddEntity(char* classname = "worldspawn", int ID = -1);
-
-	list<DEntity*> entityList;
-
-	DMap();
-	virtual ~DMap();
-
-	int FixBrushes(bool rebuild);
-};
-
-#endif // !defined(AFX_DMAP_H__ACAE597A_D26D_49AD_AA69_EDE743DB54FA__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DMap.h: interface for the DMap class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DMAP_H__ACAE597A_D26D_49AD_AA69_EDE743DB54FA__INCLUDED_)
+#define AFX_DMAP_H__ACAE597A_D26D_49AD_AA69_EDE743DB54FA__INCLUDED_
+
+#include "DEntity.h"
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DMap  
+{
+public:
+	static void RebuildEntity(DEntity* ent);
+
+	void ResetTextures( const char* textureName, float fScale[2],      float fShift[2],      int rotation, const char* newTextureName, int bResetTextureName,  int bResetScale[2],  int bResetShift[2],  int bResetRotation);
+	void LoadAll(bool bLoadPatches = FALSE);
+	void BuildInRadiant(bool bAllowDestruction);
+	int m_nNextEntity;
+	DEntity* GetWorldSpawn();
+	void ClearEntities();
+
+	DEntity* DMap::GetEntityForID(int ID);
+	DEntity* AddEntity(char* classname = "worldspawn", int ID = -1);
+
+	list<DEntity*> entityList;
+
+	DMap();
+	virtual ~DMap();
+
+	int FixBrushes(bool rebuild);
+};
+
+#endif // !defined(AFX_DMAP_H__ACAE597A_D26D_49AD_AA69_EDE743DB54FA__INCLUDED_)
diff --git a/contrib/bobtoolz/DPatch.h b/contrib/bobtoolz/DPatch.h
index d04121ea..6bdf8e60 100644
--- a/contrib/bobtoolz/DPatch.h
+++ b/contrib/bobtoolz/DPatch.h
@@ -1,62 +1,62 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DPatch.h: interface for the DPatch class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DPATCH_H__26C6B083_CE5B_420B_836B_1DDA733C04CE__INCLUDED_)
-#define AFX_DPATCH_H__26C6B083_CE5B_420B_836B_1DDA733C04CE__INCLUDED_
-
-#include "StdAfx.h"	// Added by ClassView
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-typedef struct
-{	
-	bool mergable;
-	int pos1;
-	int pos2;
-} patch_merge_t;
-
-class DPatch  
-{
-public:
-	list<DPatch> Split(bool rows, bool cols);
-	void Transpose();
-	void Invert();
-	DPatch* MergePatches(patch_merge_t merge_info, DPatch* p1, DPatch* p2);
-	patch_merge_t IsMergable(DPatch* other);
-  bool ResetTextures(const char *oldTextureName, const char *newTextureName);
-	void RemoveFromRadiant(void);
-	brush_t* QER_brush;
-	void LoadFromBrush_t(brush_t* brush);
-	patchMesh_t* QER_patch;
-	void BuildInRadiant(void* entity = NULL);
-	void SetTexture(const char* textureName);
-	char texture[256];
-	int width, height;
-	drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
-	DPatch();
-	virtual ~DPatch();
-
-};
-
-#endif // !defined(AFX_DPATCH_H__26C6B083_CE5B_420B_836B_1DDA733C04CE__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DPatch.h: interface for the DPatch class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DPATCH_H__26C6B083_CE5B_420B_836B_1DDA733C04CE__INCLUDED_)
+#define AFX_DPATCH_H__26C6B083_CE5B_420B_836B_1DDA733C04CE__INCLUDED_
+
+#include "StdAfx.h"	// Added by ClassView
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+typedef struct
+{	
+	bool mergable;
+	int pos1;
+	int pos2;
+} patch_merge_t;
+
+class DPatch  
+{
+public:
+	list<DPatch> Split(bool rows, bool cols);
+	void Transpose();
+	void Invert();
+	DPatch* MergePatches(patch_merge_t merge_info, DPatch* p1, DPatch* p2);
+	patch_merge_t IsMergable(DPatch* other);
+  bool ResetTextures(const char *oldTextureName, const char *newTextureName);
+	void RemoveFromRadiant(void);
+	brush_t* QER_brush;
+	void LoadFromBrush_t(brush_t* brush);
+	patchMesh_t* QER_patch;
+	void BuildInRadiant(void* entity = NULL);
+	void SetTexture(const char* textureName);
+	char texture[256];
+	int width, height;
+	drawVert_t points[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
+	DPatch();
+	virtual ~DPatch();
+
+};
+
+#endif // !defined(AFX_DPATCH_H__26C6B083_CE5B_420B_836B_1DDA733C04CE__INCLUDED_)
diff --git a/contrib/bobtoolz/DPlane.h b/contrib/bobtoolz/DPlane.h
index 4399b841..f1a84319 100644
--- a/contrib/bobtoolz/DPlane.h
+++ b/contrib/bobtoolz/DPlane.h
@@ -1,67 +1,67 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DPlane.h: interface for the DPlane class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DPLANE_H__FC37C021_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DPLANE_H__FC37C021_F0A1_11D4_ACF7_004095A18133__INCLUDED_
-
-#include "DPoint.h"
-
-#define FACE_DETAIL 0x8000000
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DWinding;
-
-class DPlane  
-{
-public:
-	DPlane(vec3_t va, vec3_t vb, vec3_t vc, const char* textureName, bool bDetail);
-	void ScaleTexture();
-	DWinding* BaseWindingForPlane();
-
-	void Rebuild();
-
-	bool AddToBrush_t(brush_t *brush);
-	bool operator != (DPlane& other);
-	bool operator == (DPlane& other);
-
-	bool IsRedundant(list<DPoint*>& pointList);
-	bool PlaneIntersection(DPlane* pl1, DPlane* pl2, vec3_t out);;
-
-	vec_t DistanceToPoint(vec3_t pnt);
-
-	DPlane(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData);
-	DPlane() { }
-	virtual ~DPlane();
-
-	bool m_bChkOk;
-	_QERFaceData texInfo;
-	vec3_t points[3];		// djbob:do we really need these any more?
-	vec3_t normal;
-	float _d;
-};
-
-//typedef CList<DPlane*, DPlane*> DPlaneList;
-#endif // !defined(AFX_DPLANE_H__FC37C021_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DPlane.h: interface for the DPlane class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DPLANE_H__FC37C021_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_DPLANE_H__FC37C021_F0A1_11D4_ACF7_004095A18133__INCLUDED_
+
+#include "DPoint.h"
+
+#define FACE_DETAIL 0x8000000
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DWinding;
+
+class DPlane  
+{
+public:
+	DPlane(vec3_t va, vec3_t vb, vec3_t vc, const char* textureName, bool bDetail);
+	void ScaleTexture();
+	DWinding* BaseWindingForPlane();
+
+	void Rebuild();
+
+	bool AddToBrush_t(brush_t *brush);
+	bool operator != (DPlane& other);
+	bool operator == (DPlane& other);
+
+	bool IsRedundant(list<DPoint*>& pointList);
+	bool PlaneIntersection(DPlane* pl1, DPlane* pl2, vec3_t out);;
+
+	vec_t DistanceToPoint(vec3_t pnt);
+
+	DPlane(vec3_t va, vec3_t vb, vec3_t vc, _QERFaceData* texData);
+	DPlane() { }
+	virtual ~DPlane();
+
+	bool m_bChkOk;
+	_QERFaceData texInfo;
+	vec3_t points[3];		// djbob:do we really need these any more?
+	vec3_t normal;
+	float _d;
+};
+
+//typedef CList<DPlane*, DPlane*> DPlaneList;
+#endif // !defined(AFX_DPLANE_H__FC37C021_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DPoint.h b/contrib/bobtoolz/DPoint.h
index 22ae70bc..394352cf 100644
--- a/contrib/bobtoolz/DPoint.h
+++ b/contrib/bobtoolz/DPoint.h
@@ -1,45 +1,45 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DPoint.h: interface for the DPoint class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DPOINT_H__FC37C022_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DPOINT_H__FC37C022_F0A1_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DPoint  
-{
-public:
-	DPoint();
-	virtual ~DPoint();
-
-	bool operator ==(vec3_t other);
-
-	vec3_t _pnt;
-	unsigned char m_uData;
-};
-
-//typedef CList<DPoint*, DPoint*> DPointList;
-
-#endif // !defined(AFX_DPOINT_H__FC37C022_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DPoint.h: interface for the DPoint class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DPOINT_H__FC37C022_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_DPOINT_H__FC37C022_F0A1_11D4_ACF7_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DPoint  
+{
+public:
+	DPoint();
+	virtual ~DPoint();
+
+	bool operator ==(vec3_t other);
+
+	vec3_t _pnt;
+	unsigned char m_uData;
+};
+
+//typedef CList<DPoint*, DPoint*> DPointList;
+
+#endif // !defined(AFX_DPOINT_H__FC37C022_F0A1_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DShape.h b/contrib/bobtoolz/DShape.h
index 9564943d..4bc4baa8 100644
--- a/contrib/bobtoolz/DShape.h
+++ b/contrib/bobtoolz/DShape.h
@@ -1,60 +1,60 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DShape.h: interface for the DShape class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DSHAPE_H__0B30B302_9D21_4C2D_836A_61F3C8D4244D__INCLUDED_)
-#define AFX_DSHAPE_H__0B30B302_9D21_4C2D_836A_61F3C8D4244D__INCLUDED_
-
-#include "DMap.h"	// Added by ClassView
-#include "StdAfx.h"	// Added by ClassView
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-// defines for polygon stuff
-#define MAX_POLYGON_FACES	128
-
-extern bool bFacesAll[];
-
-class DShape  
-{
-public:
-	bool BuildPit(vec3_t min, vec3_t max);
-	void BuildBorderedPrism(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop);
-	void BuildInversePrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop);
-	void BuildRegularPrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop);
-	
-	int m_nNextBrush;
-	static DBrush* GetBoundingCube_Ext(vec3_t min, vec3_t max, const char* textureName, bool* bUseFaces = bFacesAll, bool detail = false);
-
-	DShape();
-	virtual ~DShape();
-
-	void Commit();
-private:
-	DBrush* GetBoundingCube(vec3_t min, vec3_t max, const char* textureName, DEntity* ent = NULL, bool* bUseFaces = bFacesAll);
-
-	DMap m_Container;
-};
-
-#endif // !defined(AFX_DSHAPE_H__0B30B302_9D21_4C2D_836A_61F3C8D4244D__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DShape.h: interface for the DShape class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DSHAPE_H__0B30B302_9D21_4C2D_836A_61F3C8D4244D__INCLUDED_)
+#define AFX_DSHAPE_H__0B30B302_9D21_4C2D_836A_61F3C8D4244D__INCLUDED_
+
+#include "DMap.h"	// Added by ClassView
+#include "StdAfx.h"	// Added by ClassView
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+// defines for polygon stuff
+#define MAX_POLYGON_FACES	128
+
+extern bool bFacesAll[];
+
+class DShape  
+{
+public:
+	bool BuildPit(vec3_t min, vec3_t max);
+	void BuildBorderedPrism(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop);
+	void BuildInversePrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop);
+	void BuildRegularPrism(vec3_t min, vec3_t max, int nSides, bool bAlignTop);
+	
+	int m_nNextBrush;
+	static DBrush* GetBoundingCube_Ext(vec3_t min, vec3_t max, const char* textureName, bool* bUseFaces = bFacesAll, bool detail = false);
+
+	DShape();
+	virtual ~DShape();
+
+	void Commit();
+private:
+	DBrush* GetBoundingCube(vec3_t min, vec3_t max, const char* textureName, DEntity* ent = NULL, bool* bUseFaces = bFacesAll);
+
+	DMap m_Container;
+};
+
+#endif // !defined(AFX_DSHAPE_H__0B30B302_9D21_4C2D_836A_61F3C8D4244D__INCLUDED_)
diff --git a/contrib/bobtoolz/DTrainDrawer.h b/contrib/bobtoolz/DTrainDrawer.h
index 5f424068..3c7ac779 100644
--- a/contrib/bobtoolz/DTrainDrawer.h
+++ b/contrib/bobtoolz/DTrainDrawer.h
@@ -1,82 +1,82 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DTrainDrawer.h: interface for the DTrainDrawer class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_TRAINDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_TRAINDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_
-
-#include "DEntity.h"
-
-#if _MSC_VER > 1000
-
-#pragma once
-#endif // _MSC_VER > 1000
-
-typedef struct {
-	char strName[64];
-
-	vec3_t vOrigin;
-} controlPoint_t;
-
-typedef struct {
-	controlPoint_t point;
-
-	char strControl[64];
-	char strTarget[64];
-
-	list<controlPoint_t> m_pointList;
-	list<DPoint> m_vertexList;
-
-	controlPoint_t* pTarget;
-} splinePoint_t;
-
-class DTrainDrawer :
-	public IGL2DWindow,
-	public IGL3DWindow
-{
-private:
-	list<splinePoint_t*> m_splineList;
-	list<controlPoint_t*> m_pointList;
-	int refCount;
-
-	bool m_bHooked;
-	bool m_bDisplay;
-public:
-	void UnRegister();
-	void Register();
-	
-	DTrainDrawer();
-	virtual ~DTrainDrawer(void);
-
-	void Draw3D();
-	void Draw2D(VIEWTYPE vt);
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-	void ClearSplines();
-	void ClearPoints();
-	void BuildPaths();
-	void AddControlPoint(const char* name, vec_t* origin);
-	splinePoint_t* AddSplinePoint(const char* name, const char* target, vec_t* origin);
-	controlPoint_t* FindControlPoint(const char* name);
-};
-
-#endif // !defined(AFX_TRAINDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DTrainDrawer.h: interface for the DTrainDrawer class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_TRAINDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_TRAINDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_
+
+#include "DEntity.h"
+
+#if _MSC_VER > 1000
+
+#pragma once
+#endif // _MSC_VER > 1000
+
+typedef struct {
+	char strName[64];
+
+	vec3_t vOrigin;
+} controlPoint_t;
+
+typedef struct {
+	controlPoint_t point;
+
+	char strControl[64];
+	char strTarget[64];
+
+	list<controlPoint_t> m_pointList;
+	list<DPoint> m_vertexList;
+
+	controlPoint_t* pTarget;
+} splinePoint_t;
+
+class DTrainDrawer :
+	public IGL2DWindow,
+	public IGL3DWindow
+{
+private:
+	list<splinePoint_t*> m_splineList;
+	list<controlPoint_t*> m_pointList;
+	int refCount;
+
+	bool m_bHooked;
+	bool m_bDisplay;
+public:
+	void UnRegister();
+	void Register();
+	
+	DTrainDrawer();
+	virtual ~DTrainDrawer(void);
+
+	void Draw3D();
+	void Draw2D(VIEWTYPE vt);
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+	void ClearSplines();
+	void ClearPoints();
+	void BuildPaths();
+	void AddControlPoint(const char* name, vec_t* origin);
+	splinePoint_t* AddSplinePoint(const char* name, const char* target, vec_t* origin);
+	controlPoint_t* FindControlPoint(const char* name);
+};
+
+#endif // !defined(AFX_TRAINDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DTreePlanter.h b/contrib/bobtoolz/DTreePlanter.h
index ab80abff..9048e60b 100644
--- a/contrib/bobtoolz/DTreePlanter.h
+++ b/contrib/bobtoolz/DTreePlanter.h
@@ -1,223 +1,223 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef __DTREE_H__
-#define __DTREE_H__
-
-#include "../include/igl.h"
-#include "DEntity.h"
-#include "misc.h"
-#include "ScriptParser.h"
-
-#define MAX_QPATH 64
-
-typedef struct treeModel_s {
-	char name[MAX_QPATH];
-} treeModel_t;
-
-#define MAX_TP_MODELS 256
-
-class DTreePlanter : public IWindowListener {
-public:
-	virtual bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y);
-	virtual bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	virtual bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	virtual bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	virtual bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	virtual bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	virtual bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	virtual bool OnKeyPressed(char *s) { return false; }
-	virtual bool Paint() { return true; }
-	virtual void Close() { }
-	
-	DTreePlanter() {
-		m_refCount =	1;
-		m_hooked =		false;
-		m_XYWrapper =	NULL;
-		m_numModels =	0;
-		m_offset =		0;
-		m_maxPitch =	0;
-		m_minPitch =	0;
-		m_maxYaw =		0;
-		m_minYaw =		0;
-		m_setAngles =	false;
-		m_useScale =	false;
-		m_autoLink =	false;
-		m_linkNum =		0;
-
-		Register();
-
-		m_world.LoadSelectedBrushes();
-
-		char buffer[256];
-		GetFilename( buffer, "bt/tp_ent.txt" );
-
-		FILE* file = fopen( buffer, "rb" );
-		if(file) {
-			fseek( file, 0, SEEK_END );
-			int len = ftell( file );
-			fseek( file, 0, SEEK_SET );
-
-			if(len) {
-				char* buf = new char[len+1];
-				buf[len] = '\0';
-				// parser will do the cleanup, dont delete.
-
-				fread( buf, len, 1, file );
-
-				CScriptParser parser;
-				parser.SetScript( buf );
-
-				ReadConfig( &parser );
-			}
-
-			fclose( file );
-		}
-	}
-
-#define MT(t)	!stricmp( pToken, t )
-#define GT		pToken = pScriptParser->GetToken( true )
-#define CT		if(!*pToken) { return; }
-
-	void ReadConfig( CScriptParser* pScriptParser ) {
-		const char* GT;
-		CT;
-
-		do {
-			GT;
-			if(*pToken == '}') {
-				break;
-			}
-
-			if(MT("model")) {
-				if(m_numModels >= MAX_TP_MODELS) {
-					return;
-				}
-
-				GT; CT;
-
-				strncpy( m_trees[m_numModels++].name, pToken, MAX_QPATH );
-			} else if(MT("link")) {
-				GT; CT;
-
-				strncpy( m_linkName, pToken, MAX_QPATH );
-
-				m_autoLink = true;
-			} else if(MT("entity")) {
-				GT; CT;
-
-				strncpy( m_entType, pToken, MAX_QPATH );
-			} else if(MT("offset")) {
-				GT; CT;
-
-				m_offset = atoi(pToken);
-			} else if(MT("pitch")) {
-				GT; CT;
-
-				m_minPitch = atoi(pToken);
-
-				GT; CT;
-
-				m_maxPitch = atoi(pToken);
-
-				m_setAngles = true;
-			} else if(MT("yaw")) {
-				GT; CT;
-
-				m_minYaw = atoi(pToken);
-
-				GT; CT;
-
-				m_maxYaw = atoi(pToken);
-
-				m_setAngles = true;
-			} else if(MT("scale")) {
-				GT; CT;
-
-				m_minScale = static_cast< float >( atof( pToken ) );
-
-				GT; CT;
-
-				m_maxScale = static_cast< float >( atof( pToken ) );
-
-				m_useScale = true;
-			} else if(MT("numlinks")) {
-				GT; CT;
-
-				m_linkNum = atoi( pToken );
-			}
-		} while( true );
-	}
-
-	virtual ~DTreePlanter() {
-		UnRegister();
-	}
-
-	virtual void IncRef() { m_refCount++; }
-	virtual void DecRef() { m_refCount--; if (m_refCount <= 0) delete this; }
-
-	void Register() {
-		if(!m_hooked) {
-			g_MessageTable.m_pfnHookWindow( this );
-			m_XYWrapper = g_MessageTable.m_pfnGetXYWndWrapper();
-			m_hooked = true;
-		}
-	}
-
-	void UnRegister() {
-		if(m_hooked) {
-			g_MessageTable.m_pfnUnHookWindow( this );
-			m_XYWrapper = NULL;
-			m_hooked = false;
-		}
-	}
-
-	bool FindDropPoint(vec3_t in, vec3_t out);
-	void DropEntsToGround( void );
-	void MakeChain( void );
-	void SelectChain( void );
-
-private:
-	IXYWndWrapper*	m_XYWrapper;
-	DEntity			m_world;
-
-	treeModel_t		m_trees[MAX_TP_MODELS];
-
-	int				m_refCount;
-	int				m_numModels;
-	int				m_offset;
-	int				m_maxPitch;
-	int				m_minPitch;
-	int				m_maxYaw;
-	int				m_minYaw;
-
-	char			m_entType[MAX_QPATH];
-	char			m_linkName[MAX_QPATH];
-	int				m_linkNum;
-
-	float			m_minScale;
-	float			m_maxScale;
-
-	bool			m_hooked;
-	bool			m_useScale;
-	bool			m_setAngles;
-	bool			m_autoLink;
-};
-
-#endif
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __DTREE_H__
+#define __DTREE_H__
+
+#include "../include/igl.h"
+#include "DEntity.h"
+#include "misc.h"
+#include "ScriptParser.h"
+
+#define MAX_QPATH 64
+
+typedef struct treeModel_s {
+	char name[MAX_QPATH];
+} treeModel_t;
+
+#define MAX_TP_MODELS 256
+
+class DTreePlanter : public IWindowListener {
+public:
+	virtual bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y);
+	virtual bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	virtual bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	virtual bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	virtual bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	virtual bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	virtual bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	virtual bool OnKeyPressed(char *s) { return false; }
+	virtual bool Paint() { return true; }
+	virtual void Close() { }
+	
+	DTreePlanter() {
+		m_refCount =	1;
+		m_hooked =		false;
+		m_XYWrapper =	NULL;
+		m_numModels =	0;
+		m_offset =		0;
+		m_maxPitch =	0;
+		m_minPitch =	0;
+		m_maxYaw =		0;
+		m_minYaw =		0;
+		m_setAngles =	false;
+		m_useScale =	false;
+		m_autoLink =	false;
+		m_linkNum =		0;
+
+		Register();
+
+		m_world.LoadSelectedBrushes();
+
+		char buffer[256];
+		GetFilename( buffer, "bt/tp_ent.txt" );
+
+		FILE* file = fopen( buffer, "rb" );
+		if(file) {
+			fseek( file, 0, SEEK_END );
+			int len = ftell( file );
+			fseek( file, 0, SEEK_SET );
+
+			if(len) {
+				char* buf = new char[len+1];
+				buf[len] = '\0';
+				// parser will do the cleanup, dont delete.
+
+				fread( buf, len, 1, file );
+
+				CScriptParser parser;
+				parser.SetScript( buf );
+
+				ReadConfig( &parser );
+			}
+
+			fclose( file );
+		}
+	}
+
+#define MT(t)	!stricmp( pToken, t )
+#define GT		pToken = pScriptParser->GetToken( true )
+#define CT		if(!*pToken) { return; }
+
+	void ReadConfig( CScriptParser* pScriptParser ) {
+		const char* GT;
+		CT;
+
+		do {
+			GT;
+			if(*pToken == '}') {
+				break;
+			}
+
+			if(MT("model")) {
+				if(m_numModels >= MAX_TP_MODELS) {
+					return;
+				}
+
+				GT; CT;
+
+				strncpy( m_trees[m_numModels++].name, pToken, MAX_QPATH );
+			} else if(MT("link")) {
+				GT; CT;
+
+				strncpy( m_linkName, pToken, MAX_QPATH );
+
+				m_autoLink = true;
+			} else if(MT("entity")) {
+				GT; CT;
+
+				strncpy( m_entType, pToken, MAX_QPATH );
+			} else if(MT("offset")) {
+				GT; CT;
+
+				m_offset = atoi(pToken);
+			} else if(MT("pitch")) {
+				GT; CT;
+
+				m_minPitch = atoi(pToken);
+
+				GT; CT;
+
+				m_maxPitch = atoi(pToken);
+
+				m_setAngles = true;
+			} else if(MT("yaw")) {
+				GT; CT;
+
+				m_minYaw = atoi(pToken);
+
+				GT; CT;
+
+				m_maxYaw = atoi(pToken);
+
+				m_setAngles = true;
+			} else if(MT("scale")) {
+				GT; CT;
+
+				m_minScale = static_cast< float >( atof( pToken ) );
+
+				GT; CT;
+
+				m_maxScale = static_cast< float >( atof( pToken ) );
+
+				m_useScale = true;
+			} else if(MT("numlinks")) {
+				GT; CT;
+
+				m_linkNum = atoi( pToken );
+			}
+		} while( true );
+	}
+
+	virtual ~DTreePlanter() {
+		UnRegister();
+	}
+
+	virtual void IncRef() { m_refCount++; }
+	virtual void DecRef() { m_refCount--; if (m_refCount <= 0) delete this; }
+
+	void Register() {
+		if(!m_hooked) {
+			g_MessageTable.m_pfnHookWindow( this );
+			m_XYWrapper = g_MessageTable.m_pfnGetXYWndWrapper();
+			m_hooked = true;
+		}
+	}
+
+	void UnRegister() {
+		if(m_hooked) {
+			g_MessageTable.m_pfnUnHookWindow( this );
+			m_XYWrapper = NULL;
+			m_hooked = false;
+		}
+	}
+
+	bool FindDropPoint(vec3_t in, vec3_t out);
+	void DropEntsToGround( void );
+	void MakeChain( void );
+	void SelectChain( void );
+
+private:
+	IXYWndWrapper*	m_XYWrapper;
+	DEntity			m_world;
+
+	treeModel_t		m_trees[MAX_TP_MODELS];
+
+	int				m_refCount;
+	int				m_numModels;
+	int				m_offset;
+	int				m_maxPitch;
+	int				m_minPitch;
+	int				m_maxYaw;
+	int				m_minYaw;
+
+	char			m_entType[MAX_QPATH];
+	char			m_linkName[MAX_QPATH];
+	int				m_linkNum;
+
+	float			m_minScale;
+	float			m_maxScale;
+
+	bool			m_hooked;
+	bool			m_useScale;
+	bool			m_setAngles;
+	bool			m_autoLink;
+};
+
+#endif
diff --git a/contrib/bobtoolz/DVisDrawer.h b/contrib/bobtoolz/DVisDrawer.h
index c0ba1aa9..2f9ac315 100644
--- a/contrib/bobtoolz/DVisDrawer.h
+++ b/contrib/bobtoolz/DVisDrawer.h
@@ -1,58 +1,58 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DBobView.h: interface for the DBobView class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_VISDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_VISDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_
-
-#include "DWinding.h"
-
-#if _MSC_VER > 1000
-
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DVisDrawer : 
-	public IGL2DWindow, 
-	public IGL3DWindow  
-{
-public:
-	DVisDrawer();
-	virtual ~DVisDrawer();
-
-protected:
-	list<DWinding*>* m_list;
-	int refCount;
-public:
-	void ClearPoints();
-	void SetList(list<DWinding*>* pointList);
-	void UnRegister();
-	void Register();
-	void Draw3D();
-	void Draw2D(VIEWTYPE vt);
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-	bool m_bHooked;
-};
-
-#endif // !defined(AFX_VISDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DBobView.h: interface for the DBobView class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_VISDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_VISDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_
+
+#include "DWinding.h"
+
+#if _MSC_VER > 1000
+
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DVisDrawer : 
+	public IGL2DWindow, 
+	public IGL3DWindow  
+{
+public:
+	DVisDrawer();
+	virtual ~DVisDrawer();
+
+protected:
+	list<DWinding*>* m_list;
+	int refCount;
+public:
+	void ClearPoints();
+	void SetList(list<DWinding*>* pointList);
+	void UnRegister();
+	void Register();
+	void Draw3D();
+	void Draw2D(VIEWTYPE vt);
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+
+	bool m_bHooked;
+};
+
+#endif // !defined(AFX_VISDRAWER_H__6E36062A_EF0B_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/DWinding.h b/contrib/bobtoolz/DWinding.h
index d173fbf6..6d58e06e 100644
--- a/contrib/bobtoolz/DWinding.h
+++ b/contrib/bobtoolz/DWinding.h
@@ -1,68 +1,68 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// DWinding.h: interface for the DWinding class.
-//
-//////////////////////////////////////////////////////////////////////
-
-#if !defined(AFX_DWINDING_H__35B2C524_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_DWINDING_H__35B2C524_F0A7_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-class DPlane;
-
-class DWinding  
-{
-public:
-	DWinding();
-	virtual ~DWinding();
-
-	void AllocWinding(int points);
-
-	bool ChopWinding(DPlane* chopPlane);
-	bool ChopWindingInPlace(DPlane* chopPlane, vec_t ON_EPSILON);
-	void ClipWindingEpsilon(DPlane* chopPlane, vec_t epsilon, DWinding** front, DWinding** back);
-
-	void CheckWinding();
-	void WindingCentre(vec3_t centre);
-	void WindingBounds(vec3_t mins, vec3_t maxs);
-	void RemoveColinearPoints();
-
-	DWinding* ReverseWinding();
-	DWinding* CopyWinding();
-	DPlane* WindingPlane();
-
-	int WindingOnPlaneSide(vec3_t normal, vec_t dist);
-
-	vec_t WindingArea();
-
-//	members
-	int		numpoints;
-	vec3_t*	p;
-  vec3_t  clr;
-};
-
-#define	MAX_POINTS_ON_WINDING	64
-
-#define	ON_EPSILON	0.01
-
-#endif // !defined(AFX_DWINDING_H__35B2C524_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// DWinding.h: interface for the DWinding class.
+//
+//////////////////////////////////////////////////////////////////////
+
+#if !defined(AFX_DWINDING_H__35B2C524_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_DWINDING_H__35B2C524_F0A7_11D4_ACF7_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+class DPlane;
+
+class DWinding  
+{
+public:
+	DWinding();
+	virtual ~DWinding();
+
+	void AllocWinding(int points);
+
+	bool ChopWinding(DPlane* chopPlane);
+	bool ChopWindingInPlace(DPlane* chopPlane, vec_t ON_EPSILON);
+	void ClipWindingEpsilon(DPlane* chopPlane, vec_t epsilon, DWinding** front, DWinding** back);
+
+	void CheckWinding();
+	void WindingCentre(vec3_t centre);
+	void WindingBounds(vec3_t mins, vec3_t maxs);
+	void RemoveColinearPoints();
+
+	DWinding* ReverseWinding();
+	DWinding* CopyWinding();
+	DPlane* WindingPlane();
+
+	int WindingOnPlaneSide(vec3_t normal, vec_t dist);
+
+	vec_t WindingArea();
+
+//	members
+	int		numpoints;
+	vec3_t*	p;
+  vec3_t  clr;
+};
+
+#define	MAX_POINTS_ON_WINDING	64
+
+#define	ON_EPSILON	0.01
+
+#endif // !defined(AFX_DWINDING_H__35B2C524_F0A7_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/ScriptParser.h b/contrib/bobtoolz/ScriptParser.h
index 60c92f51..5537401f 100644
--- a/contrib/bobtoolz/ScriptParser.h
+++ b/contrib/bobtoolz/ScriptParser.h
@@ -1,41 +1,41 @@
-
-#ifndef _SCRIPTPARSER_H_
-#define _SCRIPTPARSER_H_
-
-#include "interfaces/IScriptParser.h"
-
-#define SP_MAX_BREAKCHARS 16
-
-class CScriptParser: public IScriptParser {
-public:
-	CScriptParser(void);
-	~CScriptParser(void);
-private:
-	char	m_breakChars[SP_MAX_BREAKCHARS];
-	char*	m_pScript;
-	char*	m_pScriptSection;
-	char*	m_pLastScriptSection;
-	char*	m_pToken;
-
-	void SkipWhitespace(bool* pbNewLines);
-	void ClearBuffer(void);
-	const char* MakeToken(const char* pToken);
-	bool IsBreakChar(char c);
-public:
-	const char* GetToken(bool bAllowLinebreaks);
-	void SkipBracedSection(void);
-	void SkipRestOfLine(void);
-	void UndoGetToken(void);
-	void ResetParseSession(void);
-
-	char* GetBufferCopy(void);
-	int GetTokenOffset(void);
-
-	void LoadScript(const char* pScript);
-	void SetScript(char* pScript);
-
-	void AddBreakChar(char c);
-private:
-};
-
-#endif
+
+#ifndef _SCRIPTPARSER_H_
+#define _SCRIPTPARSER_H_
+
+#include "interfaces/IScriptParser.h"
+
+#define SP_MAX_BREAKCHARS 16
+
+class CScriptParser: public IScriptParser {
+public:
+	CScriptParser(void);
+	~CScriptParser(void);
+private:
+	char	m_breakChars[SP_MAX_BREAKCHARS];
+	char*	m_pScript;
+	char*	m_pScriptSection;
+	char*	m_pLastScriptSection;
+	char*	m_pToken;
+
+	void SkipWhitespace(bool* pbNewLines);
+	void ClearBuffer(void);
+	const char* MakeToken(const char* pToken);
+	bool IsBreakChar(char c);
+public:
+	const char* GetToken(bool bAllowLinebreaks);
+	void SkipBracedSection(void);
+	void SkipRestOfLine(void);
+	void UndoGetToken(void);
+	void ResetParseSession(void);
+
+	char* GetBufferCopy(void);
+	int GetTokenOffset(void);
+
+	void LoadScript(const char* pScript);
+	void SetScript(char* pScript);
+
+	void AddBreakChar(char c);
+private:
+};
+
+#endif
diff --git a/contrib/bobtoolz/StdAfx.h b/contrib/bobtoolz/StdAfx.h
index 88183232..195e3d85 100644
--- a/contrib/bobtoolz/StdAfx.h
+++ b/contrib/bobtoolz/StdAfx.h
@@ -1,154 +1,154 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef __STDAFX_BOBTOOLZ__
-#define __STDAFX_BOBTOOLZ__
-
-#define VC_EXTRALEAN
-
-#ifdef _WIN32
-#pragma warning(disable : 4786)
-#endif
-
-#define BOBTOOLZ_MINOR "bobtoolz"
-
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "time.h"
-
-#if defined (__linux__) || defined (__APPLE__)
-
-// Necessary for proper boolean type declaration
-#include "qertypes.h"
-
-#include <GL/glx.h>
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-//typedef int 	bool;
-
-#define MB_OK                       0x00000000L
-#define MB_OKCANCEL                 0x00000001L
-#define MB_ABORTRETRYIGNORE         0x00000002L
-#define MB_YESNOCANCEL              0x00000003L
-#define MB_YESNO                    0x00000004L
-#define MB_RETRYCANCEL              0x00000005L
- 
- 
-#define MB_ICONHAND                 0x00000010L
-#define MB_ICONQUESTION             0x00000020L
-#define MB_ICONEXCLAMATION          0x00000030L
-#define MB_ICONASTERISK             0x00000040L
- 
-#define MB_USERICON                 0x00000080L
-#define MB_ICONWARNING              MB_ICONEXCLAMATION
-#define MB_ICONERROR                MB_ICONHAND
-#define MB_ICONINFORMATION          MB_ICONASTERISK
-#define MB_ICONSTOP                 MB_ICONHAND
- 
-#define MB_TYPEMASK                 0x0000000FL
-#define MB_ICONMASK                 0x000000F0L
-#define MB_DEFMASK                  0x00000F00L
-#define MB_MODEMASK                 0x00003000L
-#define MB_MISCMASK                 0x0000C000L
- 
-#define IDOK                1
-#define IDCANCEL            2
-#define IDABORT             3
-#define IDRETRY             4
-#define IDIGNORE            5
-#define IDYES               6
-#define IDNO                7
-
-#define WINAPI
-#define APIENTRY
-
-#ifndef GUID_DEFINED
-#define GUID_DEFINED
-typedef struct _GUID
-{
-  unsigned long  Data1;
-  unsigned short Data2;
-  unsigned short Data3;
-  unsigned char  Data4[8];
-} GUID;
-
-#define stricmp strcasecmp
-
-#endif
- 
-#if defined(__cplusplus)
-#ifndef _REFGUID_DEFINED
-#define _REFGUID_DEFINED
-#define REFGUID             const GUID &
-#endif // !_REFGUID_DEFINED
-#endif
-
-typedef struct tagRECT
-{
-    long    left;
-    long    top;
-    long    right;
-    long    bottom;
-} RECT, *PRECT, *LPRECT;
-
-typedef uint UINT;
-
-#endif // __linux__
-
-#include "synapse.h"
-#include "iplugin.h"
-#define USE_QERTABLE_DEFINE
-
-#include "missing.h" // temporary stuff, needs to be removed
-
-#include "str.h"
-#include "qertypes.h"
-#include "qerplugin.h"
-#include "idata.h"
-#include "ibrush.h"
-#include "iselectedface.h"
-#include "ishaders.h"
-#include "ibspfrontend.h"
-#include "iui.h"
-#include "igl.h"
-#include "itoolbar.h"
-#include "ientity.h"
-
-#include "mathlib.h"
-
-extern	_QERFuncTable_1			    g_FuncTable;
-extern  _QERAppDataTable			  g_AppDataTable;
-extern  _QERBrushTable				  g_BrushTable;
-extern	_QERSelectedFaceTable		g_SelectedFaceTable;
-extern	_QERShadersTable		    g_ShadersTable;
-extern	_QERQglTable				    g_QglTable;
-extern	_QERUITable					    g_MessageTable;
-extern	_QEREntityTable				  g_EntityTable;
-
-
-#define MAX_ROUND_ERROR	0.05
-
-#include "gtkr_list.h"
-
-#endif
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __STDAFX_BOBTOOLZ__
+#define __STDAFX_BOBTOOLZ__
+
+#define VC_EXTRALEAN
+
+#ifdef _WIN32
+#pragma warning(disable : 4786)
+#endif
+
+#define BOBTOOLZ_MINOR "bobtoolz"
+
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "time.h"
+
+#if defined (__linux__) || defined (__APPLE__)
+
+// Necessary for proper boolean type declaration
+#include "qertypes.h"
+
+#include <GL/glx.h>
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+//typedef int 	bool;
+
+#define MB_OK                       0x00000000L
+#define MB_OKCANCEL                 0x00000001L
+#define MB_ABORTRETRYIGNORE         0x00000002L
+#define MB_YESNOCANCEL              0x00000003L
+#define MB_YESNO                    0x00000004L
+#define MB_RETRYCANCEL              0x00000005L
+ 
+ 
+#define MB_ICONHAND                 0x00000010L
+#define MB_ICONQUESTION             0x00000020L
+#define MB_ICONEXCLAMATION          0x00000030L
+#define MB_ICONASTERISK             0x00000040L
+ 
+#define MB_USERICON                 0x00000080L
+#define MB_ICONWARNING              MB_ICONEXCLAMATION
+#define MB_ICONERROR                MB_ICONHAND
+#define MB_ICONINFORMATION          MB_ICONASTERISK
+#define MB_ICONSTOP                 MB_ICONHAND
+ 
+#define MB_TYPEMASK                 0x0000000FL
+#define MB_ICONMASK                 0x000000F0L
+#define MB_DEFMASK                  0x00000F00L
+#define MB_MODEMASK                 0x00003000L
+#define MB_MISCMASK                 0x0000C000L
+ 
+#define IDOK                1
+#define IDCANCEL            2
+#define IDABORT             3
+#define IDRETRY             4
+#define IDIGNORE            5
+#define IDYES               6
+#define IDNO                7
+
+#define WINAPI
+#define APIENTRY
+
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+typedef struct _GUID
+{
+  unsigned long  Data1;
+  unsigned short Data2;
+  unsigned short Data3;
+  unsigned char  Data4[8];
+} GUID;
+
+#define stricmp strcasecmp
+
+#endif
+ 
+#if defined(__cplusplus)
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID             const GUID &
+#endif // !_REFGUID_DEFINED
+#endif
+
+typedef struct tagRECT
+{
+    long    left;
+    long    top;
+    long    right;
+    long    bottom;
+} RECT, *PRECT, *LPRECT;
+
+typedef uint UINT;
+
+#endif // __linux__
+
+#include "synapse.h"
+#include "iplugin.h"
+#define USE_QERTABLE_DEFINE
+
+#include "missing.h" // temporary stuff, needs to be removed
+
+#include "str.h"
+#include "qertypes.h"
+#include "qerplugin.h"
+#include "idata.h"
+#include "ibrush.h"
+#include "iselectedface.h"
+#include "ishaders.h"
+#include "ibspfrontend.h"
+#include "iui.h"
+#include "igl.h"
+#include "itoolbar.h"
+#include "ientity.h"
+
+#include "mathlib.h"
+
+extern	_QERFuncTable_1			    g_FuncTable;
+extern  _QERAppDataTable			  g_AppDataTable;
+extern  _QERBrushTable				  g_BrushTable;
+extern	_QERSelectedFaceTable		g_SelectedFaceTable;
+extern	_QERShadersTable		    g_ShadersTable;
+extern	_QERQglTable				    g_QglTable;
+extern	_QERUITable					    g_MessageTable;
+extern	_QEREntityTable				  g_EntityTable;
+
+
+#define MAX_ROUND_ERROR	0.05
+
+#include "gtkr_list.h"
+
+#endif
diff --git a/contrib/bobtoolz/bobToolz.h b/contrib/bobtoolz/bobToolz.h
index d4290099..6101e877 100644
--- a/contrib/bobtoolz/bobToolz.h
+++ b/contrib/bobtoolz/bobToolz.h
@@ -1,64 +1,64 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// plugin.h : main header file for the PLUGIN DLL
-//
-
-#if !defined(AFX_PLUGIN_H__3BA55F6A_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
-#define AFX_PLUGIN_H__3BA55F6A_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-
-#ifndef __AFXWIN_H__
-	#error include 'StdAfx.h' before including this file for PCH
-#endif
-
-#include "resource.h"		// main symbols
-
-/////////////////////////////////////////////////////////////////////////////
-// CPluginApp
-// See plugin.cpp for the implementation of this class
-//
-
-class CPluginApp : public CWinApp
-{
-public:
-	CPluginApp();
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CPluginApp)
-	//}}AFX_VIRTUAL
-
-	//{{AFX_MSG(CPluginApp)
-		// NOTE - the ClassWizard will add and remove member functions here.
-		//    DO NOT EDIT what you see in these blocks of generated code !
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-
-/////////////////////////////////////////////////////////////////////////////
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_PLUGIN_H__3BA55F6A_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// plugin.h : main header file for the PLUGIN DLL
+//
+
+#if !defined(AFX_PLUGIN_H__3BA55F6A_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
+#define AFX_PLUGIN_H__3BA55F6A_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+
+#ifndef __AFXWIN_H__
+	#error include 'StdAfx.h' before including this file for PCH
+#endif
+
+#include "resource.h"		// main symbols
+
+/////////////////////////////////////////////////////////////////////////////
+// CPluginApp
+// See plugin.cpp for the implementation of this class
+//
+
+class CPluginApp : public CWinApp
+{
+public:
+	CPluginApp();
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CPluginApp)
+	//}}AFX_VIRTUAL
+
+	//{{AFX_MSG(CPluginApp)
+		// NOTE - the ClassWizard will add and remove member functions here.
+		//    DO NOT EDIT what you see in these blocks of generated code !
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+
+/////////////////////////////////////////////////////////////////////////////
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PLUGIN_H__3BA55F6A_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
diff --git a/contrib/bobtoolz/bsploader.h b/contrib/bobtoolz/bsploader.h
index 96f7c851..3b98fc27 100644
--- a/contrib/bobtoolz/bsploader.h
+++ b/contrib/bobtoolz/bsploader.h
@@ -1,134 +1,134 @@
-#define	LUMP_ENTITIES		0
-#define	LUMP_SHADERS		1
-#define	LUMP_PLANES			2
-#define	LUMP_NODES			3
-#define	LUMP_LEAFS			4
-#define	LUMP_LEAFSURFACES	5
-#define	LUMP_LEAFBRUSHES	6
-#define	LUMP_MODELS			7
-#define	LUMP_BRUSHES		8
-#define	LUMP_BRUSHSIDES		9
-#define	LUMP_DRAWVERTS		10
-#define	LUMP_DRAWINDEXES	11
-#define	LUMP_FOGS			12
-#define	LUMP_SURFACES		13
-#define	LUMP_LIGHTMAPS		14
-#define	LUMP_LIGHTGRID		15
-#define	LUMP_VISIBILITY		16
-#define	HEADER_LUMPS		17
-
-typedef struct {
-	int		fileofs, filelen;
-} lump_t;
-
-typedef struct {
-	int			ident;
-	int			version;
-
-	lump_t		lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct {
-	float		normal[3];
-	float		dist;
-} dplane_t;
-
-typedef struct {
-	int			planeNum;
-	int			children[2];	// negative numbers are -(leafs+1), not nodes
-	int			mins[3];		// for frustom culling
-	int			maxs[3];
-} dnode_t;
-
-typedef struct {
-	int			cluster;			// -1 = opaque cluster (do I still store these?)
-	int			area;
-
-	int			mins[3];			// for frustum culling
-	int			maxs[3];
-
-	int			firstLeafSurface;
-	int			numLeafSurfaces;
-
-	int			firstLeafBrush;
-	int			numLeafBrushes;
-} dleaf_t;
-
-typedef struct {
-	vec3_t		xyz;
-	float		st[2];
-	float		lightmap[2];
-	vec3_t		normal;
-	byte		color[4];
-} qdrawVert_t;
-
-typedef struct {
-	int			shaderNum;
-	int			fogNum;
-	int			surfaceType;
-
-	int			firstVert;
-	int			numVerts;
-
-	int			firstIndex;
-	int			numIndexes;
-
-	int			lightmapNum;
-	int			lightmapX, lightmapY;
-	int			lightmapWidth, lightmapHeight;
-
-	vec3_t		lightmapOrigin;
-	vec3_t		lightmapVecs[3];	// for patches, [0] and [1] are lodbounds
-
-	int			patchWidth;
-	int			patchHeight;
-} dsurface_t;
-
-typedef struct {
-	int			planeNum;			// positive plane side faces out of the leaf
-	int			shaderNum;
-} dbrushside_t;
-
-typedef struct {
-	int			firstSide;
-	int			numSides;
-	int			shaderNum;		// the shader that determines the contents flags
-} dbrush_t;
-
-typedef enum {
-	MST_BAD,
-	MST_PLANAR,
-	MST_PATCH,
-	MST_TRIANGLE_SOUP,
-	MST_FLARE
-} mapSurfaceType_t;
-
-#define	MAX_MAP_VISIBILITY	0x200000
-#define	MAX_MAP_NODES		0x20000
-#define	MAX_MAP_PLANES		0x20000
-#define	MAX_MAP_LEAFS		0x20000
-
-extern	int			numVisBytes;
-extern	int			numleafs;
-extern	int			numplanes;
-extern	int			numnodes;
-extern	int			numDrawVerts;
-extern	int			numDrawSurfaces;
-extern	int			numleafsurfaces;
-extern	int			numbrushes;
-extern	int			numbrushsides;
-extern	int			numleafbrushes;
-
-extern	dnode_t			*dnodes;
-extern	dplane_t		*dplanes;
-extern	dleaf_t			*dleafs;
-extern	byte			*visBytes;
-extern	qdrawVert_t		*drawVerts;
-extern	dsurface_t		*drawSurfaces;
-extern	int				*dleafsurfaces;
-extern	dbrush_t		*dbrushes;
-extern	dbrushside_t	*dbrushsides;
-extern	int				*dleafbrushes;
-
-qboolean LoadBSPFile( const char *filename );
-void FreeBSPData();
+#define	LUMP_ENTITIES		0
+#define	LUMP_SHADERS		1
+#define	LUMP_PLANES			2
+#define	LUMP_NODES			3
+#define	LUMP_LEAFS			4
+#define	LUMP_LEAFSURFACES	5
+#define	LUMP_LEAFBRUSHES	6
+#define	LUMP_MODELS			7
+#define	LUMP_BRUSHES		8
+#define	LUMP_BRUSHSIDES		9
+#define	LUMP_DRAWVERTS		10
+#define	LUMP_DRAWINDEXES	11
+#define	LUMP_FOGS			12
+#define	LUMP_SURFACES		13
+#define	LUMP_LIGHTMAPS		14
+#define	LUMP_LIGHTGRID		15
+#define	LUMP_VISIBILITY		16
+#define	HEADER_LUMPS		17
+
+typedef struct {
+	int		fileofs, filelen;
+} lump_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct {
+	float		normal[3];
+	float		dist;
+} dplane_t;
+
+typedef struct {
+	int			planeNum;
+	int			children[2];	// negative numbers are -(leafs+1), not nodes
+	int			mins[3];		// for frustom culling
+	int			maxs[3];
+} dnode_t;
+
+typedef struct {
+	int			cluster;			// -1 = opaque cluster (do I still store these?)
+	int			area;
+
+	int			mins[3];			// for frustum culling
+	int			maxs[3];
+
+	int			firstLeafSurface;
+	int			numLeafSurfaces;
+
+	int			firstLeafBrush;
+	int			numLeafBrushes;
+} dleaf_t;
+
+typedef struct {
+	vec3_t		xyz;
+	float		st[2];
+	float		lightmap[2];
+	vec3_t		normal;
+	byte		color[4];
+} qdrawVert_t;
+
+typedef struct {
+	int			shaderNum;
+	int			fogNum;
+	int			surfaceType;
+
+	int			firstVert;
+	int			numVerts;
+
+	int			firstIndex;
+	int			numIndexes;
+
+	int			lightmapNum;
+	int			lightmapX, lightmapY;
+	int			lightmapWidth, lightmapHeight;
+
+	vec3_t		lightmapOrigin;
+	vec3_t		lightmapVecs[3];	// for patches, [0] and [1] are lodbounds
+
+	int			patchWidth;
+	int			patchHeight;
+} dsurface_t;
+
+typedef struct {
+	int			planeNum;			// positive plane side faces out of the leaf
+	int			shaderNum;
+} dbrushside_t;
+
+typedef struct {
+	int			firstSide;
+	int			numSides;
+	int			shaderNum;		// the shader that determines the contents flags
+} dbrush_t;
+
+typedef enum {
+	MST_BAD,
+	MST_PLANAR,
+	MST_PATCH,
+	MST_TRIANGLE_SOUP,
+	MST_FLARE
+} mapSurfaceType_t;
+
+#define	MAX_MAP_VISIBILITY	0x200000
+#define	MAX_MAP_NODES		0x20000
+#define	MAX_MAP_PLANES		0x20000
+#define	MAX_MAP_LEAFS		0x20000
+
+extern	int			numVisBytes;
+extern	int			numleafs;
+extern	int			numplanes;
+extern	int			numnodes;
+extern	int			numDrawVerts;
+extern	int			numDrawSurfaces;
+extern	int			numleafsurfaces;
+extern	int			numbrushes;
+extern	int			numbrushsides;
+extern	int			numleafbrushes;
+
+extern	dnode_t			*dnodes;
+extern	dplane_t		*dplanes;
+extern	dleaf_t			*dleafs;
+extern	byte			*visBytes;
+extern	qdrawVert_t		*drawVerts;
+extern	dsurface_t		*drawSurfaces;
+extern	int				*dleafsurfaces;
+extern	dbrush_t		*dbrushes;
+extern	dbrushside_t	*dbrushsides;
+extern	int				*dleafbrushes;
+
+qboolean LoadBSPFile( const char *filename );
+void FreeBSPData();
diff --git a/contrib/bobtoolz/ctfresource_gtk.h b/contrib/bobtoolz/ctfresource_gtk.h
index e0d51870..3f706a04 100644
--- a/contrib/bobtoolz/ctfresource_gtk.h
+++ b/contrib/bobtoolz/ctfresource_gtk.h
@@ -1,34 +1,34 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by ctfresource_gtk.rc
-//
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        101
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by ctfresource_gtk.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        101
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/contrib/bobtoolz/dialogs/AboutDialog.h b/contrib/bobtoolz/dialogs/AboutDialog.h
index 6467b4a6..54cfd017 100644
--- a/contrib/bobtoolz/dialogs/AboutDialog.h
+++ b/contrib/bobtoolz/dialogs/AboutDialog.h
@@ -1,64 +1,64 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_ABOUTDIALOG_H__3BA55F71_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
-#define AFX_ABOUTDIALOG_H__3BA55F71_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// AboutDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CAboutDialog dialog
-
-class CAboutDialog : public CDialog
-{
-// Construction
-public:
-	CAboutDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CAboutDialog)
-	enum { IDD = IDD_ABOUT };
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CAboutDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CAboutDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_ABOUTDIALOG_H__3BA55F71_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_ABOUTDIALOG_H__3BA55F71_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
+#define AFX_ABOUTDIALOG_H__3BA55F71_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// AboutDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CAboutDialog dialog
+
+class CAboutDialog : public CDialog
+{
+// Construction
+public:
+	CAboutDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CAboutDialog)
+	enum { IDD = IDD_ABOUT };
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CAboutDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CAboutDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ABOUTDIALOG_H__3BA55F71_1D27_11D3_BC7B_F7EFD9765E37__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/AutoCaulkDialog.h b/contrib/bobtoolz/dialogs/AutoCaulkDialog.h
index 313a547b..a8740275 100644
--- a/contrib/bobtoolz/dialogs/AutoCaulkDialog.h
+++ b/contrib/bobtoolz/dialogs/AutoCaulkDialog.h
@@ -1,66 +1,66 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_AUTOCAULKDIALOG_H__C2783D61_DDEB_11D4_ACF6_004095A18133__INCLUDED_)
-#define AFX_AUTOCAULKDIALOG_H__C2783D61_DDEB_11D4_ACF6_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// AutoCaulkDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CAutoCaulkDialog dialog
-
-class CAutoCaulkDialog : public CDialog
-{
-// Construction
-public:
-	CAutoCaulkDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CAutoCaulkDialog)
-	enum { IDD = IDD_AUTOCAULK_DIALOG };
-	CProgressCtrl	m_prog2;
-	CProgressCtrl	m_prog1;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CAutoCaulkDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CAutoCaulkDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_AUTOCAULKDIALOG_H__C2783D61_DDEB_11D4_ACF6_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_AUTOCAULKDIALOG_H__C2783D61_DDEB_11D4_ACF6_004095A18133__INCLUDED_)
+#define AFX_AUTOCAULKDIALOG_H__C2783D61_DDEB_11D4_ACF6_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// AutoCaulkDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CAutoCaulkDialog dialog
+
+class CAutoCaulkDialog : public CDialog
+{
+// Construction
+public:
+	CAutoCaulkDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CAutoCaulkDialog)
+	enum { IDD = IDD_AUTOCAULK_DIALOG };
+	CProgressCtrl	m_prog2;
+	CProgressCtrl	m_prog1;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CAutoCaulkDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CAutoCaulkDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_AUTOCAULKDIALOG_H__C2783D61_DDEB_11D4_ACF6_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h b/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h
index 753b068c..9311c51c 100644
--- a/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h
+++ b/contrib/bobtoolz/dialogs/AutoCaulkStartDialog.h
@@ -1,71 +1,71 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_AUTOCAULKSTARTDIALOG_H__F3DE2E81_E73E_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_AUTOCAULKSTARTDIALOG_H__F3DE2E81_E73E_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// AutoCaulkStartDialog.h : header file
-//
-
-#define MODE_AC_NORMAL			0
-#define MODE_AC_BUILD_MINI_PRT	1
-#define MODE_AC_SUPER			2
-
-/////////////////////////////////////////////////////////////////////////////
-// CAutoCaulkStartDialog dialog
-
-class CAutoCaulkStartDialog : public CDialog
-{
-// Construction
-public:
-	CAutoCaulkStartDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CAutoCaulkStartDialog)
-	enum { IDD = IDD_AUTOCAULKSTART_DIALOG };
-	BOOL	m_bAllowDestruction;
-	CString	m_Warning1;
-	int		m_nMode;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CAutoCaulkStartDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CAutoCaulkStartDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_AUTOCAULKSTARTDIALOG_H__F3DE2E81_E73E_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_AUTOCAULKSTARTDIALOG_H__F3DE2E81_E73E_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_AUTOCAULKSTARTDIALOG_H__F3DE2E81_E73E_11D4_ACF7_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// AutoCaulkStartDialog.h : header file
+//
+
+#define MODE_AC_NORMAL			0
+#define MODE_AC_BUILD_MINI_PRT	1
+#define MODE_AC_SUPER			2
+
+/////////////////////////////////////////////////////////////////////////////
+// CAutoCaulkStartDialog dialog
+
+class CAutoCaulkStartDialog : public CDialog
+{
+// Construction
+public:
+	CAutoCaulkStartDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CAutoCaulkStartDialog)
+	enum { IDD = IDD_AUTOCAULKSTART_DIALOG };
+	BOOL	m_bAllowDestruction;
+	CString	m_Warning1;
+	int		m_nMode;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CAutoCaulkStartDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CAutoCaulkStartDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_AUTOCAULKSTARTDIALOG_H__F3DE2E81_E73E_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/BrushCheckDialog.h b/contrib/bobtoolz/dialogs/BrushCheckDialog.h
index 776c6137..2ccf8e8f 100644
--- a/contrib/bobtoolz/dialogs/BrushCheckDialog.h
+++ b/contrib/bobtoolz/dialogs/BrushCheckDialog.h
@@ -1,65 +1,65 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_BRUSHCHECKDIALOG_H__4BF2C701_D9EF_11D4_ACF6_004095A18133__INCLUDED_)
-#define AFX_BRUSHCHECKDIALOG_H__4BF2C701_D9EF_11D4_ACF6_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// BrushCheckDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CBrushCheckDialog dialog
-
-class CBrushCheckDialog : public CDialog
-{
-// Construction
-public:
-	CBrushCheckDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CBrushCheckDialog)
-	enum { IDD = IDD_BRUSHCHECKER_DIALOG };
-	CProgressCtrl	m_prog1;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CBrushCheckDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CBrushCheckDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_BRUSHCHECKDIALOG_H__4BF2C701_D9EF_11D4_ACF6_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_BRUSHCHECKDIALOG_H__4BF2C701_D9EF_11D4_ACF6_004095A18133__INCLUDED_)
+#define AFX_BRUSHCHECKDIALOG_H__4BF2C701_D9EF_11D4_ACF6_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// BrushCheckDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CBrushCheckDialog dialog
+
+class CBrushCheckDialog : public CDialog
+{
+// Construction
+public:
+	CBrushCheckDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CBrushCheckDialog)
+	enum { IDD = IDD_BRUSHCHECKER_DIALOG };
+	CProgressCtrl	m_prog1;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CBrushCheckDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CBrushCheckDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_BRUSHCHECKDIALOG_H__4BF2C701_D9EF_11D4_ACF6_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/DoorDialog.h b/contrib/bobtoolz/dialogs/DoorDialog.h
index a40fd5b6..4d312cb9 100644
--- a/contrib/bobtoolz/dialogs/DoorDialog.h
+++ b/contrib/bobtoolz/dialogs/DoorDialog.h
@@ -1,74 +1,74 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_DOORDIALOG_H__F36CBE01_D2C4_11D4_AE97_004095A18133__INCLUDED_)
-#define AFX_DOORDIALOG_H__F36CBE01_D2C4_11D4_AE97_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// DoorDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CDoorDialog dialog
-
-class CDoorDialog : public CDialog
-{
-// Construction
-public:
-	CDoorDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CDoorDialog)
-	enum { IDD = IDD_DOOR_DIALOG };
-	CString	m_fbTextureName;
-	BOOL	m_bSclMainHor;
-	BOOL	m_bSclMainVert;
-	BOOL	m_bSclTrimHor;
-	BOOL	m_bSclTrimVert;
-	CString	m_trimTextureName;
-	CString	m_trimTexSetBox;
-	CString	m_mainTexSetBox;
-	int		m_doorDirection;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CDoorDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CDoorDialog)
-	afx_msg void OnSetMaintexBtn();
-	afx_msg void OnSetTrimtexBtn();
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_DOORDIALOG_H__F36CBE01_D2C4_11D4_AE97_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_DOORDIALOG_H__F36CBE01_D2C4_11D4_AE97_004095A18133__INCLUDED_)
+#define AFX_DOORDIALOG_H__F36CBE01_D2C4_11D4_AE97_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// DoorDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CDoorDialog dialog
+
+class CDoorDialog : public CDialog
+{
+// Construction
+public:
+	CDoorDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CDoorDialog)
+	enum { IDD = IDD_DOOR_DIALOG };
+	CString	m_fbTextureName;
+	BOOL	m_bSclMainHor;
+	BOOL	m_bSclMainVert;
+	BOOL	m_bSclTrimHor;
+	BOOL	m_bSclTrimVert;
+	CString	m_trimTextureName;
+	CString	m_trimTexSetBox;
+	CString	m_mainTexSetBox;
+	int		m_doorDirection;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CDoorDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CDoorDialog)
+	afx_msg void OnSetMaintexBtn();
+	afx_msg void OnSetTrimtexBtn();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_DOORDIALOG_H__F36CBE01_D2C4_11D4_AE97_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/IntersectDialog.h b/contrib/bobtoolz/dialogs/IntersectDialog.h
index 79a6e3cb..d1190a6f 100644
--- a/contrib/bobtoolz/dialogs/IntersectDialog.h
+++ b/contrib/bobtoolz/dialogs/IntersectDialog.h
@@ -1,70 +1,70 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_INTERSECTDIALOG_H__03507C01_D3B3_11D4_AE97_004095A18133__INCLUDED_)
-#define AFX_INTERSECTDIALOG_H__03507C01_D3B3_11D4_AE97_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// IntersectDialog.h : header file
-//
-
-#define BRUSH_OPT_WHOLE_MAP	0
-#define BRUSH_OPT_SELECTED	1
-
-/////////////////////////////////////////////////////////////////////////////
-// CIntersectDialog dialog
-
-class CIntersectDialog : public CDialog
-{
-// Construction
-public:
-	CIntersectDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CIntersectDialog)
-	enum { IDD = IDD_INTERSECT_DIALOG };
-	int		m_nBrushOptions;
-	BOOL	m_bUseDetail;
-	BOOL	m_bDuplicateOnly;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CIntersectDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CIntersectDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_INTERSECTDIALOG_H__03507C01_D3B3_11D4_AE97_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_INTERSECTDIALOG_H__03507C01_D3B3_11D4_AE97_004095A18133__INCLUDED_)
+#define AFX_INTERSECTDIALOG_H__03507C01_D3B3_11D4_AE97_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// IntersectDialog.h : header file
+//
+
+#define BRUSH_OPT_WHOLE_MAP	0
+#define BRUSH_OPT_SELECTED	1
+
+/////////////////////////////////////////////////////////////////////////////
+// CIntersectDialog dialog
+
+class CIntersectDialog : public CDialog
+{
+// Construction
+public:
+	CIntersectDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CIntersectDialog)
+	enum { IDD = IDD_INTERSECT_DIALOG };
+	int		m_nBrushOptions;
+	BOOL	m_bUseDetail;
+	BOOL	m_bDuplicateOnly;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CIntersectDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CIntersectDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_INTERSECTDIALOG_H__03507C01_D3B3_11D4_AE97_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/IntersectInfoDialog.h b/contrib/bobtoolz/dialogs/IntersectInfoDialog.h
index 72709ab3..51a4bf75 100644
--- a/contrib/bobtoolz/dialogs/IntersectInfoDialog.h
+++ b/contrib/bobtoolz/dialogs/IntersectInfoDialog.h
@@ -1,65 +1,65 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_INTERSECTINFODIALOG_H__62CDC8CD_D9D2_11D4_ACF6_004095A18133__INCLUDED_)
-#define AFX_INTERSECTINFODIALOG_H__62CDC8CD_D9D2_11D4_ACF6_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// IntersectInfoDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CIntersectInfoDialog dialog
-
-class CIntersectInfoDialog : public CDialog
-{
-// Construction
-public:
-	CIntersectInfoDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CIntersectInfoDialog)
-	enum { IDD = IDD_INTERSECT_INFO_DIALOG };
-	CProgressCtrl	m_prog1;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CIntersectInfoDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CIntersectInfoDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_INTERSECTINFODIALOG_H__62CDC8CD_D9D2_11D4_ACF6_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_INTERSECTINFODIALOG_H__62CDC8CD_D9D2_11D4_ACF6_004095A18133__INCLUDED_)
+#define AFX_INTERSECTINFODIALOG_H__62CDC8CD_D9D2_11D4_ACF6_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// IntersectInfoDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CIntersectInfoDialog dialog
+
+class CIntersectInfoDialog : public CDialog
+{
+// Construction
+public:
+	CIntersectInfoDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CIntersectInfoDialog)
+	enum { IDD = IDD_INTERSECT_INFO_DIALOG };
+	CProgressCtrl	m_prog1;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CIntersectInfoDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CIntersectInfoDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_INTERSECTINFODIALOG_H__62CDC8CD_D9D2_11D4_ACF6_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/PolygonDialog.h b/contrib/bobtoolz/dialogs/PolygonDialog.h
index d556f500..afe5cb87 100644
--- a/contrib/bobtoolz/dialogs/PolygonDialog.h
+++ b/contrib/bobtoolz/dialogs/PolygonDialog.h
@@ -1,74 +1,74 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_POLYGONDIALOG_H__EF7FE400_628A_11D1_B66D_004095A18133__INCLUDED_)
-#define AFX_POLYGONDIALOG_H__EF7FE400_628A_11D1_B66D_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// PolygonDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CPolygonDialog dialog
-
-class CPolygonDialog : public CDialog
-{
-// Construction
-public:
-	BOOL GetChkBool(int nID);
-	void EnableBorderEdit(BOOL bEnable);
-	void EnableBordered(BOOL bEnable);
-	CPolygonDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CPolygonDialog)
-	enum { IDD = IDD_POLYGON_DIALOG };
-	UINT	m_nSideCount;
-	BOOL	m_bInverse;
-	BOOL	m_bBorder;
-	UINT	m_nBorderSize;
-	BOOL	m_bAlignTop;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CPolygonDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CPolygonDialog)
-	virtual BOOL OnInitDialog();
-	afx_msg void OnBorderChkClicked();
-	afx_msg void OnInverseChkClickrd();
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_POLYGONDIALOG_H__EF7FE400_628A_11D1_B66D_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_POLYGONDIALOG_H__EF7FE400_628A_11D1_B66D_004095A18133__INCLUDED_)
+#define AFX_POLYGONDIALOG_H__EF7FE400_628A_11D1_B66D_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// PolygonDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CPolygonDialog dialog
+
+class CPolygonDialog : public CDialog
+{
+// Construction
+public:
+	BOOL GetChkBool(int nID);
+	void EnableBorderEdit(BOOL bEnable);
+	void EnableBordered(BOOL bEnable);
+	CPolygonDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CPolygonDialog)
+	enum { IDD = IDD_POLYGON_DIALOG };
+	UINT	m_nSideCount;
+	BOOL	m_bInverse;
+	BOOL	m_bBorder;
+	UINT	m_nBorderSize;
+	BOOL	m_bAlignTop;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CPolygonDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CPolygonDialog)
+	virtual BOOL OnInitDialog();
+	afx_msg void OnBorderChkClicked();
+	afx_msg void OnInverseChkClickrd();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_POLYGONDIALOG_H__EF7FE400_628A_11D1_B66D_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/StairDialog.h b/contrib/bobtoolz/dialogs/StairDialog.h
index c42959af..0bcdc0ec 100644
--- a/contrib/bobtoolz/dialogs/StairDialog.h
+++ b/contrib/bobtoolz/dialogs/StairDialog.h
@@ -1,74 +1,74 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_STAIRDIALOG_H__942FFF20_5F9E_11D1_B66D_004095A18133__INCLUDED_)
-#define AFX_STAIRDIALOG_H__942FFF20_5F9E_11D1_B66D_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// StairDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CStairDialog dialog
-
-class CStairDialog : public CDialog
-{
-// Construction
-public:
-	CStairDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CStairDialog)
-	enum { IDD = IDD_STAIR_DIALOG };
-	UINT	m_nStairHeight;
-	int		m_StairDir;
-	int		m_StairStyle;
-	CString	m_riserTexture;
-	BOOL	m_bDetail;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CStairDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CStairDialog)
-	afx_msg void OnStyleBobClicked();
-	afx_msg void OnStyleOrigClicked();
-	virtual BOOL OnInitDialog();
-	afx_msg void OnStyleCornerClicked();
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-private:
-	void EnableDetail(BOOL bEnable);
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_STAIRDIALOG_H__942FFF20_5F9E_11D1_B66D_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_STAIRDIALOG_H__942FFF20_5F9E_11D1_B66D_004095A18133__INCLUDED_)
+#define AFX_STAIRDIALOG_H__942FFF20_5F9E_11D1_B66D_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// StairDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CStairDialog dialog
+
+class CStairDialog : public CDialog
+{
+// Construction
+public:
+	CStairDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CStairDialog)
+	enum { IDD = IDD_STAIR_DIALOG };
+	UINT	m_nStairHeight;
+	int		m_StairDir;
+	int		m_StairStyle;
+	CString	m_riserTexture;
+	BOOL	m_bDetail;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CStairDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CStairDialog)
+	afx_msg void OnStyleBobClicked();
+	afx_msg void OnStyleOrigClicked();
+	virtual BOOL OnInitDialog();
+	afx_msg void OnStyleCornerClicked();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+private:
+	void EnableDetail(BOOL bEnable);
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STAIRDIALOG_H__942FFF20_5F9E_11D1_B66D_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/TextureResetDialog.h b/contrib/bobtoolz/dialogs/TextureResetDialog.h
index e0843505..6f041611 100644
--- a/contrib/bobtoolz/dialogs/TextureResetDialog.h
+++ b/contrib/bobtoolz/dialogs/TextureResetDialog.h
@@ -1,73 +1,73 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_TEXTURERESETDIALOG_H__42D665C1_ED84_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_TEXTURERESETDIALOG_H__42D665C1_ED84_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// TextureResetDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CTextureResetDialog dialog
-
-class CTextureResetDialog : public CDialog
-{
-// Construction
-public:
-	CTextureResetDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CTextureResetDialog)
-	enum { IDD = IDD_TEXTURE_RESET_DIALOG };
-	BOOL	m_bAllTextures;
-	CString	m_TextureName;
-	int		m_nRotation;
-	float	m_fScaleHorizontal;
-	float	m_fScaleVertical;
-	int		m_nShiftHorizontal;
-	int		m_nShiftVertical;
-	BOOL	m_bOnlyTexture;
-	CString	m_NewTextureName;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CTextureResetDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CTextureResetDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_TEXTURERESETDIALOG_H__42D665C1_ED84_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_TEXTURERESETDIALOG_H__42D665C1_ED84_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_TEXTURERESETDIALOG_H__42D665C1_ED84_11D4_ACF7_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// TextureResetDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CTextureResetDialog dialog
+
+class CTextureResetDialog : public CDialog
+{
+// Construction
+public:
+	CTextureResetDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CTextureResetDialog)
+	enum { IDD = IDD_TEXTURE_RESET_DIALOG };
+	BOOL	m_bAllTextures;
+	CString	m_TextureName;
+	int		m_nRotation;
+	float	m_fScaleHorizontal;
+	float	m_fScaleVertical;
+	int		m_nShiftHorizontal;
+	int		m_nShiftVertical;
+	BOOL	m_bOnlyTexture;
+	CString	m_NewTextureName;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CTextureResetDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CTextureResetDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_TEXTURERESETDIALOG_H__42D665C1_ED84_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/dialogs/dialogs-gtk.h b/contrib/bobtoolz/dialogs/dialogs-gtk.h
index 589b994e..987f7216 100644
--- a/contrib/bobtoolz/dialogs/dialogs-gtk.h
+++ b/contrib/bobtoolz/dialogs/dialogs-gtk.h
@@ -1,98 +1,98 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-struct BuildStairsRS{
-	char mainTexture[256];
-	char riserTexture[256];
-	int direction;
-	int style;
-	int stairHeight;
-	qboolean bUseDetail;
-};
-
-struct ResetTextureRS {
-	int bResetTextureName;
-	char textureName[256];
-	char newTextureName[256];
-
-	int bResetScale[2];
-	float fScale[2];
-
-	int bResetShift[2];
-	float fShift[2];
-
-	int bResetRotation;
-	int rotation;
-};
-
-struct TrainThingRS {
-	float fRadiusX, fRadiusY;
-	float fStartAngle, fEndAngle;
-	int iNumPoints;
-	float fStartHeight, fEndHeight;
-};
-
-struct IntersectRS{
-	int nBrushOptions;
-	qboolean bUseDetail;
-	qboolean bDuplicateOnly;
-};
-
-struct PolygonRS{
-	qboolean bUseBorder;
-	qboolean bInverse;
-	qboolean bAlignTop;
-	int nSides;
-	int nBorderWidth;
-};
-
-struct DoorRS{
-	char mainTexture[256];
-	char trimTexture[256];
-	qboolean bScaleMainH;
-	qboolean bScaleMainV;
-	qboolean bScaleTrimH;
-	qboolean bScaleTrimV;
-	int nOrientation;
-};
-
-struct PathPlotterRS{
-	int nPoints;
-	float fMultiplier;
-	float fGravity;
-	qboolean bNoUpdate;
-	qboolean bShowExtra;
-};
-
-struct TwinWidget{
-	GtkWidget* one;
-	GtkWidget* two;
-};
-
-int DoMessageBox(const char* lpText, const char* lpCaption, guint32 uType);
-int DoIntersectBox(IntersectRS* rs);
-int DoPolygonBox(PolygonRS* rs);
-int DoResetTextureBox (ResetTextureRS* rs);
-int DoBuildStairsBox(BuildStairsRS* rs);
-int DoDoorsBox(DoorRS* rs);
-int DoPathPlotterBox(PathPlotterRS* rs);
-int DoCTFColourChangeBox();
-int DoTrainThingBox (TrainThingRS* rs);
-
-//GtkWidget* GetProgressWindow(char* title, GtkProgressBar* feedback);
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+struct BuildStairsRS{
+	char mainTexture[256];
+	char riserTexture[256];
+	int direction;
+	int style;
+	int stairHeight;
+	qboolean bUseDetail;
+};
+
+struct ResetTextureRS {
+	int bResetTextureName;
+	char textureName[256];
+	char newTextureName[256];
+
+	int bResetScale[2];
+	float fScale[2];
+
+	int bResetShift[2];
+	float fShift[2];
+
+	int bResetRotation;
+	int rotation;
+};
+
+struct TrainThingRS {
+	float fRadiusX, fRadiusY;
+	float fStartAngle, fEndAngle;
+	int iNumPoints;
+	float fStartHeight, fEndHeight;
+};
+
+struct IntersectRS{
+	int nBrushOptions;
+	qboolean bUseDetail;
+	qboolean bDuplicateOnly;
+};
+
+struct PolygonRS{
+	qboolean bUseBorder;
+	qboolean bInverse;
+	qboolean bAlignTop;
+	int nSides;
+	int nBorderWidth;
+};
+
+struct DoorRS{
+	char mainTexture[256];
+	char trimTexture[256];
+	qboolean bScaleMainH;
+	qboolean bScaleMainV;
+	qboolean bScaleTrimH;
+	qboolean bScaleTrimV;
+	int nOrientation;
+};
+
+struct PathPlotterRS{
+	int nPoints;
+	float fMultiplier;
+	float fGravity;
+	qboolean bNoUpdate;
+	qboolean bShowExtra;
+};
+
+struct TwinWidget{
+	GtkWidget* one;
+	GtkWidget* two;
+};
+
+int DoMessageBox(const char* lpText, const char* lpCaption, guint32 uType);
+int DoIntersectBox(IntersectRS* rs);
+int DoPolygonBox(PolygonRS* rs);
+int DoResetTextureBox (ResetTextureRS* rs);
+int DoBuildStairsBox(BuildStairsRS* rs);
+int DoDoorsBox(DoorRS* rs);
+int DoPathPlotterBox(PathPlotterRS* rs);
+int DoCTFColourChangeBox();
+int DoTrainThingBox (TrainThingRS* rs);
+
+//GtkWidget* GetProgressWindow(char* title, GtkProgressBar* feedback);
diff --git a/contrib/bobtoolz/dialogs/pathplotterdialog.h b/contrib/bobtoolz/dialogs/pathplotterdialog.h
index 749e4da3..6edd8987 100644
--- a/contrib/bobtoolz/dialogs/pathplotterdialog.h
+++ b/contrib/bobtoolz/dialogs/pathplotterdialog.h
@@ -1,70 +1,70 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_PATHPLOTTERDIALOG_H__A0516221_F19B_11D4_ACF7_004095A18133__INCLUDED_)
-#define AFX_PATHPLOTTERDIALOG_H__A0516221_F19B_11D4_ACF7_004095A18133__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-// PathPlotterDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CPathPlotterDialog dialog
-
-class CPathPlotterDialog : public CDialog
-{
-// Construction
-public:
-	CPathPlotterDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CPathPlotterDialog)
-	enum { IDD = IDD_PATHPLOTTER_DIALOG };
-	float	m_fGravity;
-	float	m_fMultiplier;
-	BOOL	m_bNoUpdate;
-	int		m_nPoints;
-	BOOL	m_bShowExtra;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CPathPlotterDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CPathPlotterDialog)
-	afx_msg void OnYes();
-	afx_msg void OnNo();
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_PATHPLOTTERDIALOG_H__A0516221_F19B_11D4_ACF7_004095A18133__INCLUDED_)
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_PATHPLOTTERDIALOG_H__A0516221_F19B_11D4_ACF7_004095A18133__INCLUDED_)
+#define AFX_PATHPLOTTERDIALOG_H__A0516221_F19B_11D4_ACF7_004095A18133__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+// PathPlotterDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CPathPlotterDialog dialog
+
+class CPathPlotterDialog : public CDialog
+{
+// Construction
+public:
+	CPathPlotterDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CPathPlotterDialog)
+	enum { IDD = IDD_PATHPLOTTER_DIALOG };
+	float	m_fGravity;
+	float	m_fMultiplier;
+	BOOL	m_bNoUpdate;
+	int		m_nPoints;
+	BOOL	m_bShowExtra;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CPathPlotterDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CPathPlotterDialog)
+	afx_msg void OnYes();
+	afx_msg void OnNo();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_PATHPLOTTERDIALOG_H__A0516221_F19B_11D4_ACF7_004095A18133__INCLUDED_)
diff --git a/contrib/bobtoolz/funchandlers.h b/contrib/bobtoolz/funchandlers.h
index d8c1e33c..1e3696cb 100644
--- a/contrib/bobtoolz/funchandlers.h
+++ b/contrib/bobtoolz/funchandlers.h
@@ -1,72 +1,72 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#include "DBobView.h"
-#include "DVisDrawer.h"
-#include "DTrainDrawer.h"
-#include "DTreePlanter.h"
-
-extern DBobView* g_PathView;
-extern DVisDrawer* g_VisView;
-extern DTrainDrawer* g_TrainView;
-extern DTreePlanter* g_TreePlanter;
-
-// intersect stuff
-#define BRUSH_OPT_WHOLE_MAP	0
-#define BRUSH_OPT_SELECTED	1
-
-// defines for stairs
-#define	MOVE_NORTH	0
-#define	MOVE_SOUTH	1
-#define	MOVE_EAST	2
-#define	MOVE_WEST	3
-
-#define STYLE_ORIGINAL	0
-#define	STYLE_BOB		1
-#define	STYLE_CORNER	2
-
-// defines for doors
-#define DIRECTION_NS	0
-#define DIRECTION_EW	1
-
-// help
-void LoadLists();
-
-
-// djbob
-void DoIntersect( void );
-void DoPolygonsTB( void );
-void DoPolygons(vec3_t vMin, vec3_t vMax);
-void DoFixBrushes( void );
-void DoResetTextures( void );
-void DoBuildStairs(vec3_t vMin, vec3_t vMax);
-void DoBuildDoors(vec3_t vMin, vec3_t vMax);
-void DoPathPlotter( void );
-void DoPitBuilder(vec3_t vMin, vec3_t vMax);
-void DoCTFColourChanger( void );
-void DoMergePatches( void );
-void DoSplitPatch( void );
-void DoVisAnalyse( void );
-void DoTrainThing( void );
-void DoTrainPathPlot( void );
-void DoCaulkSelection( void );
-void DoTreePlanter( void );
-void DoDropEnts( void );
-void DoMakeChain( void );
-void DoFlipTerrain( void );
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#include "DBobView.h"
+#include "DVisDrawer.h"
+#include "DTrainDrawer.h"
+#include "DTreePlanter.h"
+
+extern DBobView* g_PathView;
+extern DVisDrawer* g_VisView;
+extern DTrainDrawer* g_TrainView;
+extern DTreePlanter* g_TreePlanter;
+
+// intersect stuff
+#define BRUSH_OPT_WHOLE_MAP	0
+#define BRUSH_OPT_SELECTED	1
+
+// defines for stairs
+#define	MOVE_NORTH	0
+#define	MOVE_SOUTH	1
+#define	MOVE_EAST	2
+#define	MOVE_WEST	3
+
+#define STYLE_ORIGINAL	0
+#define	STYLE_BOB		1
+#define	STYLE_CORNER	2
+
+// defines for doors
+#define DIRECTION_NS	0
+#define DIRECTION_EW	1
+
+// help
+void LoadLists();
+
+
+// djbob
+void DoIntersect( void );
+void DoPolygonsTB( void );
+void DoPolygons(vec3_t vMin, vec3_t vMax);
+void DoFixBrushes( void );
+void DoResetTextures( void );
+void DoBuildStairs(vec3_t vMin, vec3_t vMax);
+void DoBuildDoors(vec3_t vMin, vec3_t vMax);
+void DoPathPlotter( void );
+void DoPitBuilder(vec3_t vMin, vec3_t vMax);
+void DoCTFColourChanger( void );
+void DoMergePatches( void );
+void DoSplitPatch( void );
+void DoVisAnalyse( void );
+void DoTrainThing( void );
+void DoTrainPathPlot( void );
+void DoCaulkSelection( void );
+void DoTreePlanter( void );
+void DoDropEnts( void );
+void DoMakeChain( void );
+void DoFlipTerrain( void );
diff --git a/contrib/bobtoolz/interfaces/IScriptParser.h b/contrib/bobtoolz/interfaces/IScriptParser.h
index 934a9671..5d0ee5ba 100644
--- a/contrib/bobtoolz/interfaces/IScriptParser.h
+++ b/contrib/bobtoolz/interfaces/IScriptParser.h
@@ -1,23 +1,23 @@
-#ifndef _ISCRIPTPARSER_H_
-#define _ISCRIPTPARSER_H_
-
-class IScriptParser {
-public:
-	virtual ~IScriptParser() {};
-
-	virtual const char* GetToken		( bool ) = 0;
-	virtual char*		GetBufferCopy	( void ) = 0;
-	virtual int			GetTokenOffset	( void ) = 0;
-
-	virtual void SkipBracedSection	( void ) = 0;
-	virtual void SkipRestOfLine		( void ) = 0;
-	virtual void UndoGetToken		( void ) = 0;
-	virtual void ResetParseSession	( void ) = 0;
-
-	virtual void LoadScript	( const char*	) = 0;
-	virtual void SetScript	( char*			) = 0;
-
-	virtual void AddBreakChar( char ) = 0;
-};
-
-#endif
+#ifndef _ISCRIPTPARSER_H_
+#define _ISCRIPTPARSER_H_
+
+class IScriptParser {
+public:
+	virtual ~IScriptParser() {};
+
+	virtual const char* GetToken		( bool ) = 0;
+	virtual char*		GetBufferCopy	( void ) = 0;
+	virtual int			GetTokenOffset	( void ) = 0;
+
+	virtual void SkipBracedSection	( void ) = 0;
+	virtual void SkipRestOfLine		( void ) = 0;
+	virtual void UndoGetToken		( void ) = 0;
+	virtual void ResetParseSession	( void ) = 0;
+
+	virtual void LoadScript	( const char*	) = 0;
+	virtual void SetScript	( char*			) = 0;
+
+	virtual void AddBreakChar( char ) = 0;
+};
+
+#endif
diff --git a/contrib/bobtoolz/lists.h b/contrib/bobtoolz/lists.h
index d71e7594..6f9774f6 100644
--- a/contrib/bobtoolz/lists.h
+++ b/contrib/bobtoolz/lists.h
@@ -1,21 +1,21 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-bool LoadExclusionList(char* filename, list<Str>* exclusionList);
-bool LoadGList(char* filename, GList** loadlist);
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+bool LoadExclusionList(char* filename, list<Str>* exclusionList);
+bool LoadGList(char* filename, GList** loadlist);
diff --git a/contrib/bobtoolz/misc.h b/contrib/bobtoolz/misc.h
index c02a99e9..81b48879 100644
--- a/contrib/bobtoolz/misc.h
+++ b/contrib/bobtoolz/misc.h
@@ -1,48 +1,48 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-vec_t Min(vec_t a, vec_t b);
-
-epair_t* GetNextChainItem(epair_t* lastItem, char* key, char* value);
-
-// reads current texture into global, returns pointer to it
-const char* GetCurrentTexture();
-
-void FillDefaultTexture(_QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture);
-
-void Sys_ERROR (char* text, ...);
-
-void BuildMiniPrt(list<Str>* exclusionList);
-
-void MoveBlock(int dir, vec3_t min, vec3_t max, float dist);
-void SetInitialStairPos(int dir, vec3_t min, vec3_t max, float width);
-
-entity_s* FindEntityFromTargetname(const char* targetname, int* entNum);
-
-char* UnixToDosPath(char* path);
-
-char* GetFilename(char* buffer, const char* filename);
-char* GetGameFilename(char* buffer, const char* filename);
-
-float Determinant3x3(float a1, float a2, float a3,
-					 float b1, float b2, float b3,
-					 float c1, float c2, float c3);
-
-bool GetEntityCentre(const char* entity, vec3_t centre);
-void MakeNormal( vec_t* va, vec_t* vb, vec_t* vc, vec_t* out );
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+vec_t Min(vec_t a, vec_t b);
+
+epair_t* GetNextChainItem(epair_t* lastItem, char* key, char* value);
+
+// reads current texture into global, returns pointer to it
+const char* GetCurrentTexture();
+
+void FillDefaultTexture(_QERFaceData* faceData, vec3_t va, vec3_t vb, vec3_t vc, const char* texture);
+
+void Sys_ERROR (char* text, ...);
+
+void BuildMiniPrt(list<Str>* exclusionList);
+
+void MoveBlock(int dir, vec3_t min, vec3_t max, float dist);
+void SetInitialStairPos(int dir, vec3_t min, vec3_t max, float width);
+
+entity_s* FindEntityFromTargetname(const char* targetname, int* entNum);
+
+char* UnixToDosPath(char* path);
+
+char* GetFilename(char* buffer, const char* filename);
+char* GetGameFilename(char* buffer, const char* filename);
+
+float Determinant3x3(float a1, float a2, float a3,
+					 float b1, float b2, float b3,
+					 float c1, float c2, float c3);
+
+bool GetEntityCentre(const char* entity, vec3_t centre);
+void MakeNormal( vec_t* va, vec_t* vb, vec_t* vc, vec_t* out );
diff --git a/contrib/bobtoolz/resource-gtk.h b/contrib/bobtoolz/resource-gtk.h
index e4522dff..9297877f 100644
--- a/contrib/bobtoolz/resource-gtk.h
+++ b/contrib/bobtoolz/resource-gtk.h
@@ -1,15 +1,15 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by bobtoolz-gtk.rc
-//
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        102
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by bobtoolz-gtk.rc
+//
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/contrib/bobtoolz/resource.h b/contrib/bobtoolz/resource.h
index 999d639b..2c7f97ed 100644
--- a/contrib/bobtoolz/resource.h
+++ b/contrib/bobtoolz/resource.h
@@ -1,115 +1,115 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by bobToolz.rc
-//
-#define IDD_PATHPLOTTER_DIALOG          101
-#define IDD_ABOUT                       129
-#define IDD_STAIR_DIALOG                130
-#define IDD_POLYGON_DIALOG              131
-#define IDB_BT_BITMAP                   137
-#define IDI_ICON1                       139
-#define IDD_POLYGON_BRD_DIALOG          141
-#define IDD_DOOR_DIALOG                 141
-#define IDD_INTERSECT_DIALOG            143
-#define IDD_INTERSECT_INFO_DIALOG       144
-#define IDD_BRUSHCHECKER_DIALOG         146
-#define IDD_AUTOCAULK_DIALOG            147
-#define IDD_AUTOCAULKSTART_DIALOG       148
-#define IDD_TEXTURE_RESET_DIALOG        149
-#define IDC_EDIT1                       1000
-#define IDC_DIR_N_RADIO                 1001
-#define IDC_TRIMTEXTURE_EDIT            1001
-#define IDC_SCL_VERT_EDIT               1001
-#define IDC_DIR_S_RADIO                 1002
-#define IDC_SCL_HOR_EDIT                1002
-#define IDC_POINTCOUNT_EDIT             1002
-#define IDC_DIR_E_RADIO                 1003
-#define IDC_ROTATION_EDIT               1003
-#define IDC_MULTIPLIER_EDIT             1003
-#define IDC_DIR_W_RADIO                 1004
-#define IDC_SHFT_VER_EDIT               1004
-#define IDC_GRAVITY_EDIT                1004
-#define IDC_STYLE_ORIG_RADIO            1005
-#define IDC_SHFT_HOR_EDIT               1005
-#define IDC_NOUPDATE_CHECK              1005
-#define IDC_STYLE_BOB_RADIO             1006
-#define IDC_SHOWEXTRA_CHECK             1006
-#define IDC_STYLE_CORNER_RADIO          1007
-#define IDC_RISER_EDIT                  1011
-#define IDC_FLAT_EDIT                   1012
-#define IDC_MAX_WALL_WIDTH              1013
-#define IDC_MIN_WALL_WIDTH              1014
-#define IDC_DETAIL_CHK                  1014
-#define IDC_MAX_CLIFF_HEIGHT            1015
-#define IDC_INVERSE_CHK                 1015
-#define IDC_MIN_CLIFF_HEIGHT            1016
-#define IDC_BORDER_CHK                  1016
-#define IDC_ALIGN_CHK                   1017
-#define IDC_BORDER_EDIT                 1018
-#define IDC_MAX_CNR_SIZE                1019
-#define IDC_MIN_CNR_SIZE                1020
-#define IDC_FBTEXTURE_EDIT              1020
-#define IDC_GRID_SNAP                   1021
-#define IDC_TEXSCALE1_CHECK             1021
-#define IDC_MAX_WALL_BREADTH            1022
-#define IDC_TEXSCALE2_CHECK             1022
-#define IDC_MIN_WALL_BREADTH            1023
-#define IDC_MAINTEX_COMBO               1023
-#define IDC_TEXSCALE3_CHECK             1024
-#define IDC_TEXSCALE4_CHECK             1025
-#define IDC_TRIMTEX_COMBO               1026
-#define IDC_SET_MAINTEX_BTN             1027
-#define IDC_SET_TRIMTEX_BTN             1028
-#define IDC_WHOLEMAP_CHECK              1030
-#define IDC_DETAIL_INCLUDE_CHECK        1031
-#define IDC_SKIPBOUNDS_CHECK            1032
-#define IDC_SKIPSIMPLE_CHECK            1033
-#define IDC_SKIPACCURATE_CHECK          1034
-#define IDC_PROGRESS1                   1035
-#define IDC_INTR_PROG1                  1035
-#define IDC_DIR_NS_RADIO                1036
-#define IDC_PROGRESS2                   1036
-#define IDC_DIR_EW_RADIO                1037
-#define IDC_DIR_GROUP                   1038
-#define IDC_WHOLEMAP_RADIO              1040
-#define IDC_SELECTED_RADIO              1041
-#define IDC_KILLBRUSHES_CHECK           1041
-#define IDC_WARNING1_STATIC             1042
-#define IDC_AC_NORMAL_RADIO             1043
-#define IDC_AC_BUILD_MINI_PRT_RADIO     1044
-#define IDC_AC_SUPER_RADIO              1045
-#define IDC_RESET_TEXTURE_EDIT          1046
-#define IDC_RESET_NEW_TEXTURE_EDIT      1047
-#define IDC_ONLYTEXTURE_CHECK           1048
-#define IDC_ALLTEXTURES_CHECK           1049
-#define IDC_DUPLICATEONLY_CHECK         1050
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        102
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1007
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by bobToolz.rc
+//
+#define IDD_PATHPLOTTER_DIALOG          101
+#define IDD_ABOUT                       129
+#define IDD_STAIR_DIALOG                130
+#define IDD_POLYGON_DIALOG              131
+#define IDB_BT_BITMAP                   137
+#define IDI_ICON1                       139
+#define IDD_POLYGON_BRD_DIALOG          141
+#define IDD_DOOR_DIALOG                 141
+#define IDD_INTERSECT_DIALOG            143
+#define IDD_INTERSECT_INFO_DIALOG       144
+#define IDD_BRUSHCHECKER_DIALOG         146
+#define IDD_AUTOCAULK_DIALOG            147
+#define IDD_AUTOCAULKSTART_DIALOG       148
+#define IDD_TEXTURE_RESET_DIALOG        149
+#define IDC_EDIT1                       1000
+#define IDC_DIR_N_RADIO                 1001
+#define IDC_TRIMTEXTURE_EDIT            1001
+#define IDC_SCL_VERT_EDIT               1001
+#define IDC_DIR_S_RADIO                 1002
+#define IDC_SCL_HOR_EDIT                1002
+#define IDC_POINTCOUNT_EDIT             1002
+#define IDC_DIR_E_RADIO                 1003
+#define IDC_ROTATION_EDIT               1003
+#define IDC_MULTIPLIER_EDIT             1003
+#define IDC_DIR_W_RADIO                 1004
+#define IDC_SHFT_VER_EDIT               1004
+#define IDC_GRAVITY_EDIT                1004
+#define IDC_STYLE_ORIG_RADIO            1005
+#define IDC_SHFT_HOR_EDIT               1005
+#define IDC_NOUPDATE_CHECK              1005
+#define IDC_STYLE_BOB_RADIO             1006
+#define IDC_SHOWEXTRA_CHECK             1006
+#define IDC_STYLE_CORNER_RADIO          1007
+#define IDC_RISER_EDIT                  1011
+#define IDC_FLAT_EDIT                   1012
+#define IDC_MAX_WALL_WIDTH              1013
+#define IDC_MIN_WALL_WIDTH              1014
+#define IDC_DETAIL_CHK                  1014
+#define IDC_MAX_CLIFF_HEIGHT            1015
+#define IDC_INVERSE_CHK                 1015
+#define IDC_MIN_CLIFF_HEIGHT            1016
+#define IDC_BORDER_CHK                  1016
+#define IDC_ALIGN_CHK                   1017
+#define IDC_BORDER_EDIT                 1018
+#define IDC_MAX_CNR_SIZE                1019
+#define IDC_MIN_CNR_SIZE                1020
+#define IDC_FBTEXTURE_EDIT              1020
+#define IDC_GRID_SNAP                   1021
+#define IDC_TEXSCALE1_CHECK             1021
+#define IDC_MAX_WALL_BREADTH            1022
+#define IDC_TEXSCALE2_CHECK             1022
+#define IDC_MIN_WALL_BREADTH            1023
+#define IDC_MAINTEX_COMBO               1023
+#define IDC_TEXSCALE3_CHECK             1024
+#define IDC_TEXSCALE4_CHECK             1025
+#define IDC_TRIMTEX_COMBO               1026
+#define IDC_SET_MAINTEX_BTN             1027
+#define IDC_SET_TRIMTEX_BTN             1028
+#define IDC_WHOLEMAP_CHECK              1030
+#define IDC_DETAIL_INCLUDE_CHECK        1031
+#define IDC_SKIPBOUNDS_CHECK            1032
+#define IDC_SKIPSIMPLE_CHECK            1033
+#define IDC_SKIPACCURATE_CHECK          1034
+#define IDC_PROGRESS1                   1035
+#define IDC_INTR_PROG1                  1035
+#define IDC_DIR_NS_RADIO                1036
+#define IDC_PROGRESS2                   1036
+#define IDC_DIR_EW_RADIO                1037
+#define IDC_DIR_GROUP                   1038
+#define IDC_WHOLEMAP_RADIO              1040
+#define IDC_SELECTED_RADIO              1041
+#define IDC_KILLBRUSHES_CHECK           1041
+#define IDC_WARNING1_STATIC             1042
+#define IDC_AC_NORMAL_RADIO             1043
+#define IDC_AC_BUILD_MINI_PRT_RADIO     1044
+#define IDC_AC_SUPER_RADIO              1045
+#define IDC_RESET_TEXTURE_EDIT          1046
+#define IDC_RESET_NEW_TEXTURE_EDIT      1047
+#define IDC_ONLYTEXTURE_CHECK           1048
+#define IDC_ALLTEXTURES_CHECK           1049
+#define IDC_DUPLICATEONLY_CHECK         1050
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1007
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/contrib/bobtoolz/shapes.h b/contrib/bobtoolz/shapes.h
index e5fccd9c..46eae37a 100644
--- a/contrib/bobtoolz/shapes.h
+++ b/contrib/bobtoolz/shapes.h
@@ -1,49 +1,49 @@
-/*
-BobToolz plugin for GtkRadiant
-Copyright (C) 2001 Gordon Biggans
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// TODO: implement all this stuff via DBrush class. started with DShape
-// TODO: Auto Face Scaling, no need to pass parms, calculated via brush.
-
-// Q3MAP stuff
-#define FACE_DETAIL 0x8000000
-
-// defines for polygon stuff
-#define MAX_POLYGON_FACES	128
-
-// generic (detail added 12/01/01, for AC+)
-void AddFaceWithTexture(brush_t* brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail);
-
-// -------------
-// ---caulked---
-// -------------
-void Build_Wedge(int dir, vec3_t min, vec3_t max, bool bUp);
-
-// --------------
-// ---textured---
-// --------------
-void BuildDoorsX2(vec3_t min, vec3_t max, bool bSclMainHor, bool bSclMainVert, bool bSclTrimHor, bool bSclTrimVert, const char* mainTexture, const char* trimTexture, int direction);
-void Build_StairStep(vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction);
-void Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, bool detail);
-void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex);
-// stairs stuff.
-
-//void Build_Prism_Border(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop = FALSE); //moved to DShape
-//void Build_Prism_Ordinary(vec3_t min, vec3_t max, int nSides, bool bAlignTop = FALSE); //moved to DShape
-//void Build_Prism_Efficient(vec3_t min, vec3_t max, int nSides, bool bAlignTop = FALSE); //moved to DShape
-// polygon stuff.
+/*
+BobToolz plugin for GtkRadiant
+Copyright (C) 2001 Gordon Biggans
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// TODO: implement all this stuff via DBrush class. started with DShape
+// TODO: Auto Face Scaling, no need to pass parms, calculated via brush.
+
+// Q3MAP stuff
+#define FACE_DETAIL 0x8000000
+
+// defines for polygon stuff
+#define MAX_POLYGON_FACES	128
+
+// generic (detail added 12/01/01, for AC+)
+void AddFaceWithTexture(brush_t* brush, vec3_t va, vec3_t vb, vec3_t vc, const char* texture, bool detail);
+
+// -------------
+// ---caulked---
+// -------------
+void Build_Wedge(int dir, vec3_t min, vec3_t max, bool bUp);
+
+// --------------
+// ---textured---
+// --------------
+void BuildDoorsX2(vec3_t min, vec3_t max, bool bSclMainHor, bool bSclMainVert, bool bSclTrimHor, bool bSclTrimVert, const char* mainTexture, const char* trimTexture, int direction);
+void Build_StairStep(vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, int direction);
+void Build_StairStep_Wedge(int dir, vec3_t min, vec3_t max, const char* mainTexture, const char* riserTexture, bool detail);
+void BuildCornerStairs(vec3_t vMin, vec3_t vMax, int nSteps, const char* mainTexture, const char* riserTex);
+// stairs stuff.
+
+//void Build_Prism_Border(vec3_t min, vec3_t max, int nSides, int nBorder, bool bAlignTop = FALSE); //moved to DShape
+//void Build_Prism_Ordinary(vec3_t min, vec3_t max, int nSides, bool bAlignTop = FALSE); //moved to DShape
+//void Build_Prism_Efficient(vec3_t min, vec3_t max, int nSides, bool bAlignTop = FALSE); //moved to DShape
+// polygon stuff.
diff --git a/contrib/bobtoolz/visfind.h b/contrib/bobtoolz/visfind.h
index 732f3b6c..0a4b601e 100644
--- a/contrib/bobtoolz/visfind.h
+++ b/contrib/bobtoolz/visfind.h
@@ -1 +1 @@
-list<DWinding*> *BuildTrace(char* filename, vec3_t v_origin);
+list<DWinding*> *BuildTrace(char* filename, vec3_t v_origin);
diff --git a/contrib/camera/camera.h b/contrib/camera/camera.h
index d60783a9..cf1387c2 100644
--- a/contrib/camera/camera.h
+++ b/contrib/camera/camera.h
@@ -1,162 +1,162 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-Camera plugin for GtkRadiant
-Copyright (C) 2002 Splash Damage Ltd.
-*/
-
-#ifndef _CAMERA_H_
-#define _CAMERA_H_
-
-#ifdef _WIN32
-	#pragma warning(disable : 4267)
-#else
-	typedef unsigned char byte;
-#endif
-
-class CCamera;
-
-#include <gtk/gtk.h>
-
-#include "str.h"
-
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-
-#include "igl.h"
-#include "iui.h"
-#include "icamera.h"
-
-#include "misc.h"
-#include "dialogs.h"
-#include "funchandlers.h"
-#include "renderer.h"
-#include "listener.h"
-
-extern _QERFuncTable_1    g_FuncTable;
-extern _QERQglTable       g_QglTable;
-extern _QERUITable        g_UITable;
-extern _QERCameraTable		g_CameraTable;
-
-extern CRenderer          *Renderer;
-extern CListener          *Listener;
-
-// splinelib
-#define CAMERA_PLUGIN
-#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
-
-extern void ( APIENTRY * qglBegin )(GLenum mode);
-extern void ( APIENTRY * qglEnd )(void);
-extern void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
-
-extern "C" void InitIglToQgl( _QERQglTable *g_QglTable );
-
-#include "splines/splines.h"
-
-// this needs to match splines.cpp
-#define MAX_CAMERAS 64
-extern idCameraDef camera[MAX_CAMERAS];
-
-extern "C" qboolean loadCamera(int camNum, const	char *name);
-
-//
-// CCamera
-//
-
-class CCamera {
-public:
-  CCamera( int i ) {
-    cam = &camera[i];
-    camnum = i;
-    Init();
-  }
-  ~CCamera();
-
-  void Init() {
-    next = prev = NULL;
-    fileName[0] = '\0';
-		hasbeensaved = 0;
-  }
-
-  idCameraDef *GetCam() {
-    return( cam );
-  }
-  int GetCamNum() {
-    return( camnum );
-  }
-
-  char *GetFileName() {
-    return( fileName );
-  }
-  void SetFileName( const char *name, bool save ) {
-    strcpy( fileName, name );
-    if( save )
-      hasbeensaved = 1;
-  }
-
-  CCamera *GetNext() {
-    return( next );
-  }
-
-  CCamera *GetPrev() {
-    return( prev );
-  }
-
-  void SetNext( CCamera *camera ) {
-    next = camera;
-  }
-  void SetPrev( CCamera *camera ) {
-    prev = camera;
-  }
-
-	int HasBeenSaved() {
-		return( hasbeensaved );
-	}
-	void HasBeenModified() {
-		if( hasbeensaved )
-			hasbeensaved = 2;
-	}
-
-protected:
-  idCameraDef *cam;
-  int camnum;
-  CCamera *next, *prev;
-  char fileName[PATH_MAX];
-	int hasbeensaved;	// 0:never saved 1:saved 2:saved, but modified
-};
-
-CCamera *AllocCam();
-void FreeCam( CCamera *cam );
-void SetCurrentCam( CCamera *cam );
-CCamera *GetCurrentCam();
-
-// globals
-extern GtkWidget *g_pRadiantWnd;
-extern GtkWidget *g_pCameraInspectorWnd;
-extern CCamera *firstCam;
-extern bool g_bEditOn;
-extern int g_iEditMode;
-extern int g_iActiveTarget;
-extern int g_iPreviewRunning;
-extern CCamera *g_pCurrentEditCam;
-
-#endif // _CAMERA_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Camera plugin for GtkRadiant
+Copyright (C) 2002 Splash Damage Ltd.
+*/
+
+#ifndef _CAMERA_H_
+#define _CAMERA_H_
+
+#ifdef _WIN32
+	#pragma warning(disable : 4267)
+#else
+	typedef unsigned char byte;
+#endif
+
+class CCamera;
+
+#include <gtk/gtk.h>
+
+#include "str.h"
+
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+
+#include "igl.h"
+#include "iui.h"
+#include "icamera.h"
+
+#include "misc.h"
+#include "dialogs.h"
+#include "funchandlers.h"
+#include "renderer.h"
+#include "listener.h"
+
+extern _QERFuncTable_1    g_FuncTable;
+extern _QERQglTable       g_QglTable;
+extern _QERUITable        g_UITable;
+extern _QERCameraTable		g_CameraTable;
+
+extern CRenderer          *Renderer;
+extern CListener          *Listener;
+
+// splinelib
+#define CAMERA_PLUGIN
+#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+
+extern void ( APIENTRY * qglBegin )(GLenum mode);
+extern void ( APIENTRY * qglEnd )(void);
+extern void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+
+extern "C" void InitIglToQgl( _QERQglTable *g_QglTable );
+
+#include "splines/splines.h"
+
+// this needs to match splines.cpp
+#define MAX_CAMERAS 64
+extern idCameraDef camera[MAX_CAMERAS];
+
+extern "C" qboolean loadCamera(int camNum, const	char *name);
+
+//
+// CCamera
+//
+
+class CCamera {
+public:
+  CCamera( int i ) {
+    cam = &camera[i];
+    camnum = i;
+    Init();
+  }
+  ~CCamera();
+
+  void Init() {
+    next = prev = NULL;
+    fileName[0] = '\0';
+		hasbeensaved = 0;
+  }
+
+  idCameraDef *GetCam() {
+    return( cam );
+  }
+  int GetCamNum() {
+    return( camnum );
+  }
+
+  char *GetFileName() {
+    return( fileName );
+  }
+  void SetFileName( const char *name, bool save ) {
+    strcpy( fileName, name );
+    if( save )
+      hasbeensaved = 1;
+  }
+
+  CCamera *GetNext() {
+    return( next );
+  }
+
+  CCamera *GetPrev() {
+    return( prev );
+  }
+
+  void SetNext( CCamera *camera ) {
+    next = camera;
+  }
+  void SetPrev( CCamera *camera ) {
+    prev = camera;
+  }
+
+	int HasBeenSaved() {
+		return( hasbeensaved );
+	}
+	void HasBeenModified() {
+		if( hasbeensaved )
+			hasbeensaved = 2;
+	}
+
+protected:
+  idCameraDef *cam;
+  int camnum;
+  CCamera *next, *prev;
+  char fileName[PATH_MAX];
+	int hasbeensaved;	// 0:never saved 1:saved 2:saved, but modified
+};
+
+CCamera *AllocCam();
+void FreeCam( CCamera *cam );
+void SetCurrentCam( CCamera *cam );
+CCamera *GetCurrentCam();
+
+// globals
+extern GtkWidget *g_pRadiantWnd;
+extern GtkWidget *g_pCameraInspectorWnd;
+extern CCamera *firstCam;
+extern bool g_bEditOn;
+extern int g_iEditMode;
+extern int g_iActiveTarget;
+extern int g_iPreviewRunning;
+extern CCamera *g_pCurrentEditCam;
+
+#endif // _CAMERA_H_
diff --git a/contrib/camera/dialogs.h b/contrib/camera/dialogs.h
index 5ba86c5a..93dbce1d 100644
--- a/contrib/camera/dialogs.h
+++ b/contrib/camera/dialogs.h
@@ -1,37 +1,37 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-Camera plugin for GtkRadiant
-Copyright (C) 2002 Splash Damage Ltd.
-*/
-
-struct TwinWidget {
-  GtkWidget* one;
-  GtkWidget* two;
-};
-
-void dialog_button_callback (GtkWidget *widget, gpointer data);
-gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data);
-//void dialog_button_callback_settex (GtkWidget *widget, gpointer data);
-
-void RefreshCamListCombo( void );
-GtkWidget *CreateCameraInspectorDialog( void );
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Camera plugin for GtkRadiant
+Copyright (C) 2002 Splash Damage Ltd.
+*/
+
+struct TwinWidget {
+  GtkWidget* one;
+  GtkWidget* two;
+};
+
+void dialog_button_callback (GtkWidget *widget, gpointer data);
+gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data);
+//void dialog_button_callback_settex (GtkWidget *widget, gpointer data);
+
+void RefreshCamListCombo( void );
+GtkWidget *CreateCameraInspectorDialog( void );
diff --git a/contrib/camera/funchandlers.h b/contrib/camera/funchandlers.h
index a9419062..ee3b9274 100644
--- a/contrib/camera/funchandlers.h
+++ b/contrib/camera/funchandlers.h
@@ -1,37 +1,37 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-Camera plugin for GtkRadiant
-Copyright (C) 2002 Splash Damage Ltd.
-*/
-
-void DoNewFixedCamera();
-void DoNewInterpolatedCamera();
-void DoNewSplineCamera();
-void DoCameraInspector();
-void DoPreviewCamera();
-void DoLoadCamera();
-void DoSaveCamera();
-void DoUnloadCamera();
-void DoStartEdit( CCamera *cam );
-void DoStopEdit( void );
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Camera plugin for GtkRadiant
+Copyright (C) 2002 Splash Damage Ltd.
+*/
+
+void DoNewFixedCamera();
+void DoNewInterpolatedCamera();
+void DoNewSplineCamera();
+void DoCameraInspector();
+void DoPreviewCamera();
+void DoLoadCamera();
+void DoSaveCamera();
+void DoUnloadCamera();
+void DoStartEdit( CCamera *cam );
+void DoStopEdit( void );
+
diff --git a/contrib/camera/listener.h b/contrib/camera/listener.h
index 13e14b71..6519508f 100644
--- a/contrib/camera/listener.h
+++ b/contrib/camera/listener.h
@@ -1,64 +1,64 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-Camera plugin for GtkRadiant
-Copyright (C) 2002 Splash Damage Ltd.
-*/
-
-class CListener : public IWindowListener  
-{
-public:
-	bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y);
-	bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y);
-	bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y);
-	bool OnKeyPressed(char *s) { return false; }
-	bool Paint() { return true; }
-	void Close() { }
-	
-	void UnRegister();
-	void Register();
-	CListener();
-	virtual ~CListener();
-
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-  void SetViewType( VIEWTYPE vt ) { if( m_vt != vt ) oldValid = false; m_vt = vt; }
-
-private:
-  IXYWndWrapper *g_pXYWndWrapper;
-
-	bool m_bHooked;
-	int refCount;
-  VIEWTYPE m_vt;
-
-  // mouse button status
-  bool m_bLeftMBPressed, m_bRightMBPressed, m_bMiddleMBPressed;
-
-  // old mouse coordinates
-  bool oldValid;
-  gdouble old_x, old_y;
-};
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Camera plugin for GtkRadiant
+Copyright (C) 2002 Splash Damage Ltd.
+*/
+
+class CListener : public IWindowListener  
+{
+public:
+	bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y);
+	bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y);
+	bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y);
+	bool OnKeyPressed(char *s) { return false; }
+	bool Paint() { return true; }
+	void Close() { }
+	
+	void UnRegister();
+	void Register();
+	CListener();
+	virtual ~CListener();
+
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+
+  void SetViewType( VIEWTYPE vt ) { if( m_vt != vt ) oldValid = false; m_vt = vt; }
+
+private:
+  IXYWndWrapper *g_pXYWndWrapper;
+
+	bool m_bHooked;
+	int refCount;
+  VIEWTYPE m_vt;
+
+  // mouse button status
+  bool m_bLeftMBPressed, m_bRightMBPressed, m_bMiddleMBPressed;
+
+  // old mouse coordinates
+  bool oldValid;
+  gdouble old_x, old_y;
+};
diff --git a/contrib/camera/misc.h b/contrib/camera/misc.h
index 6c56dc73..52062c88 100644
--- a/contrib/camera/misc.h
+++ b/contrib/camera/misc.h
@@ -1,91 +1,91 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-Camera plugin for GtkRadiant
-Copyright (C) 2002 Splash Damage Ltd.
-*/
-
-void Sys_ERROR( char* text, ... );
-char* UnixToDosPath( char* path );
-void ExtractFilePath( const char *path, char *dest );
-const char* ExtractFilename( const char* path );
-bool FileExists (const char *filename);
-int Q_stricmp (const char *s1, const char *s2);
-
-typedef int fileHandle_t;
-
-#define qfalse false
-#define qtrue true
-
-extern "C" {
-// command buffer
-void Cbuf_AddText( const char *text );
-void Cbuf_Execute (void);
-
-// common
-#ifndef CDECL
-#ifdef _WIN32
-	#define CDECL __cdecl
-#else
-	#define CDECL
-#endif
-#endif
-
-void CDECL Com_Error( int level, const char *error, ... );
-void CDECL Com_Printf( const char *msg, ... );
-void CDECL Com_DPrintf( const char *msg, ... );
-void *Com_Allocate( int bytes );
-void Com_Dealloc( void *ptr );
-
-// filesystem
-int FS_Read( void *buffer, int len, fileHandle_t f );
-int FS_Write( const void *buffer, int len, fileHandle_t h );
-int FS_ReadFile( const char *qpath, void **buffer );
-void FS_FreeFile( void *buffer );
-int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueFILE );
-fileHandle_t FS_FOpenFileWrite( const char *filename );
-void FS_FCloseFile( fileHandle_t f );
-}
-
-// vectors
-#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
-#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
-#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
-#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
-
-#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
-#define	VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
-#define CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
-
-#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
-#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
-#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
-#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
-#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
-#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
-
-#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0)
-#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
-#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
-#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
-
-#define	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Camera plugin for GtkRadiant
+Copyright (C) 2002 Splash Damage Ltd.
+*/
+
+void Sys_ERROR( char* text, ... );
+char* UnixToDosPath( char* path );
+void ExtractFilePath( const char *path, char *dest );
+const char* ExtractFilename( const char* path );
+bool FileExists (const char *filename);
+int Q_stricmp (const char *s1, const char *s2);
+
+typedef int fileHandle_t;
+
+#define qfalse false
+#define qtrue true
+
+extern "C" {
+// command buffer
+void Cbuf_AddText( const char *text );
+void Cbuf_Execute (void);
+
+// common
+#ifndef CDECL
+#ifdef _WIN32
+	#define CDECL __cdecl
+#else
+	#define CDECL
+#endif
+#endif
+
+void CDECL Com_Error( int level, const char *error, ... );
+void CDECL Com_Printf( const char *msg, ... );
+void CDECL Com_DPrintf( const char *msg, ... );
+void *Com_Allocate( int bytes );
+void Com_Dealloc( void *ptr );
+
+// filesystem
+int FS_Read( void *buffer, int len, fileHandle_t f );
+int FS_Write( const void *buffer, int len, fileHandle_t h );
+int FS_ReadFile( const char *qpath, void **buffer );
+void FS_FreeFile( void *buffer );
+int FS_FOpenFileRead( const char *filename, fileHandle_t *file, qboolean uniqueFILE );
+fileHandle_t FS_FOpenFileWrite( const char *filename );
+void FS_FCloseFile( fileHandle_t f );
+}
+
+// vectors
+#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+
+#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
+#define	VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
+#define CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+
+#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
+#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
+#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
+#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
+#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
+
+#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0)
+#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
+#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
+#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+
+#define	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
diff --git a/contrib/camera/renderer.h b/contrib/camera/renderer.h
index c2ca93bd..989567a1 100644
--- a/contrib/camera/renderer.h
+++ b/contrib/camera/renderer.h
@@ -1,46 +1,46 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-Camera plugin for GtkRadiant
-Copyright (C) 2002 Splash Damage Ltd.
-*/
-
-class CRenderer : public IGL2DWindow, public IGL3DWindow {
-public:
-	CRenderer();
-  virtual ~CRenderer();
-
-protected:
-  int refCount;
-
-public:
-	void Register();
-	void UnRegister();
-	void Initialize();
-  void Draw2D( VIEWTYPE vt );
-	void Draw3D();
-
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-  bool m_bHooked;
-};
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Camera plugin for GtkRadiant
+Copyright (C) 2002 Splash Damage Ltd.
+*/
+
+class CRenderer : public IGL2DWindow, public IGL3DWindow {
+public:
+	CRenderer();
+  virtual ~CRenderer();
+
+protected:
+  int refCount;
+
+public:
+	void Register();
+	void UnRegister();
+	void Initialize();
+  void Draw2D( VIEWTYPE vt );
+	void Draw3D();
+
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+
+  bool m_bHooked;
+};
diff --git a/contrib/gtkgensurf/gendlgs.h b/contrib/gtkgensurf/gendlgs.h
index c6df4866..dd954678 100644
--- a/contrib/gtkgensurf/gendlgs.h
+++ b/contrib/gtkgensurf/gendlgs.h
@@ -1,151 +1,151 @@
-/*
-GenSurf plugin for GtkRadiant
-Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#define DLG_PLANE_XY0							100
-#define DLG_PLANE_XY1							101
-#define DLG_PLANE_YZ0							102
-#define DLG_PLANE_XZ0							103
-#define DLG_PLANE_YZ1							104
-#define DLG_PLANE_XZ1							105
-#define DLG_WAVE_01								106
-#define DLG_WAVE_02								107
-#define DLG_WAVE_03								108
-#define DLG_WAVE_04								109
-#define DLG_WAVE_05								110
-#define DLG_WAVE_06								111
-#define DLG_LAMBDA								112
-#define DLG_LAMBDA_TEXT						113
-#define DLG_AMP										114
-#define DLG_AMP_TEXT							115
-#define DLG_ROUGH									116
-#define DLG_ROUGH_TEXT						117
-#define DLG_LINEARBORDER					118
-#define DLG_FILE									119
-#define DLG_FILE_BROWSE						120
-#define DLG_PREVIEW								121
-#define DLG_GO										122
-#define DLG_ABOUT									123
-#define DLG_NH_TEXT								124
-#define DLG_NH										125
-#define DLG_NH_SPIN								126
-#define DLG_NV_TEXT								127
-#define DLG_NV										128
-#define DLG_NV_SPIN								129
-#define DLG_HMIN_TEXT							130
-#define DLG_HMIN									131
-#define DLG_HMAX_TEXT							132
-#define DLG_HMAX									133
-#define DLG_VMIN_TEXT							134
-#define DLG_VMIN									135
-#define DLG_VMAX_TEXT							136
-#define DLG_VMAX									137
-#define DLG_Z00_TEXT							138
-#define DLG_Z00										139
-#define DLG_Z01_TEXT							140
-#define DLG_Z01										141
-#define DLG_Z10_TEXT							142
-#define DLG_Z10										143
-#define DLG_Z11_TEXT							144
-#define DLG_Z11										145
-#define DLG_TEXTURE								146
-#define DLG_SKYBOX								147
-#define DLG_AUTOOVERWRITE					148
-#define DLG_DETAIL								149
-#define DLG_ARGHRAD2							150
-#define DLG_ARGHRAD2_SPIN					151
-#define DLG_APPEND								152
-#define DLG_REFRESH								153
-#define DLG_TEXOFFSETX						154
-#define DLG_TEXOFFSETY						155
-#define DLG_TEXSCALEX							156
-#define DLG_TEXSCALEY							157
-#define DLG_FIXPOINTS							158
-#define DLG_TEXTURE_BROWSE				159
-#define DLG_AZIMUTH								162
-#define DLG_AZIMUTH_SPIN					163
-#define DLG_ELEVATION							164
-#define DLG_ELEVATION_SPIN				165
-#define DLG_RANDOMSEED						166
-#define DLG_RANDOMSEED_SPIN				167
-#define DLG_BITMAP								168
-#define DLG_SAVE									169
-#define DLG_OPEN									170
-#define DLG_TAB										171
-#define DLG_TEXTURE2							172
-#define DLG_TEXTURE2_BROWSE				173
-#define DLG_LADDER								174
-#define DLG_ARGHRAD2_TEXT					175
-#define DLG_FILE_TEXT							176
-#define DLG_DECIMATE							177
-#define DLG_DECIMATE_TEXT					178
-#define DLG_HIDEBACKFACES					179
-#define DLG_DEFAULTS							180
-#define DLG_ABOUT_APP							200
-#define DLG_ABOUT_ICON						201
-#define DLG_BMP_FILE							202
-#define DLG_BMP_FILE_BROWSE				203
-#define DLG_BMP_BLACK							204
-#define DLG_BMP_WHITE							205
-#define DLG_BMP_TEXT1							206
-#define DLG_BMP_TEXT2							207
-#define DLG_BMP_TEXT3							208
-#define DLG_BMP_NOTE							209
-#define DLG_BMP_RELOAD						210
-#define DLG_ABOUT_URL							211
-#define DLG_ABOUT_BOARD						212
-#define DLG_FIX_FREE							300
-#define DLG_FIX_FREEALL						301
-#define DLG_FIX_VALUE_TEXT				302
-#define DLG_FIX_VALUE							303
-#define DLG_FIX_VALUE_SPIN				304
-#define DLG_FIX_DONE							305
-#define DLG_FIX_RANGE_TEXT				306
-#define DLG_FIX_RANGE							307
-#define DLG_FIX_NOTE							308
-#define DLG_FIX_RATE_TEXT					309
-#define DLG_FIX_RATE							310
-#define DLG_USE_PATCHES						311
-#define DLG_DECIMATE_LABEL				312
-#define DLG_HINT									350
-#define DLG_GAME_00								400
-#define DLG_GAME_01								401
-#define DLG_GAME_02								402
-#define DLG_GAME_03								403
-#define DLG_GAME_04								404
-#define DLG_GAME_05								405
-#define DLG_GAME_06								406
-#define DLG_GAME_07								407
-#define DLG_GAME_08								408
-#define DLG_GAME_09								409
-#define DLG_TEX_USEPAK						420
-#define DLG_TEX_PAK_TEXT					421
-#define DLG_TEX_PAKFILE						422
-#define DLG_TEX_PAK_BROWSE				423
-#define DLG_TEX_LIST1							424
-#define DLG_TEX_LIST2							425
-#define DLG_TEX_LIST3							426
-#define DLG_TEXTURE3							427
-#define DLG_TEXTURE3_BROWSE				428
-#define DLG_TEX_SLANT_TEXT				429
-#define DLG_TEX_SLANT							430
-#define DLG_TEX_SLANT_SPIN			  431
-#define DLG_EXCEL_FUNC						500
-#define DLG_EXCEL_FUNC_TEXT				501
-#define DLG_PREVIEW_ANTIALIASING	502 // ^Fishman - Antializing for the preview window.
-#define DLG_SNAP_TO_GRID					503 // Hydra : snap to grid
+/*
+GenSurf plugin for GtkRadiant
+Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#define DLG_PLANE_XY0							100
+#define DLG_PLANE_XY1							101
+#define DLG_PLANE_YZ0							102
+#define DLG_PLANE_XZ0							103
+#define DLG_PLANE_YZ1							104
+#define DLG_PLANE_XZ1							105
+#define DLG_WAVE_01								106
+#define DLG_WAVE_02								107
+#define DLG_WAVE_03								108
+#define DLG_WAVE_04								109
+#define DLG_WAVE_05								110
+#define DLG_WAVE_06								111
+#define DLG_LAMBDA								112
+#define DLG_LAMBDA_TEXT						113
+#define DLG_AMP										114
+#define DLG_AMP_TEXT							115
+#define DLG_ROUGH									116
+#define DLG_ROUGH_TEXT						117
+#define DLG_LINEARBORDER					118
+#define DLG_FILE									119
+#define DLG_FILE_BROWSE						120
+#define DLG_PREVIEW								121
+#define DLG_GO										122
+#define DLG_ABOUT									123
+#define DLG_NH_TEXT								124
+#define DLG_NH										125
+#define DLG_NH_SPIN								126
+#define DLG_NV_TEXT								127
+#define DLG_NV										128
+#define DLG_NV_SPIN								129
+#define DLG_HMIN_TEXT							130
+#define DLG_HMIN									131
+#define DLG_HMAX_TEXT							132
+#define DLG_HMAX									133
+#define DLG_VMIN_TEXT							134
+#define DLG_VMIN									135
+#define DLG_VMAX_TEXT							136
+#define DLG_VMAX									137
+#define DLG_Z00_TEXT							138
+#define DLG_Z00										139
+#define DLG_Z01_TEXT							140
+#define DLG_Z01										141
+#define DLG_Z10_TEXT							142
+#define DLG_Z10										143
+#define DLG_Z11_TEXT							144
+#define DLG_Z11										145
+#define DLG_TEXTURE								146
+#define DLG_SKYBOX								147
+#define DLG_AUTOOVERWRITE					148
+#define DLG_DETAIL								149
+#define DLG_ARGHRAD2							150
+#define DLG_ARGHRAD2_SPIN					151
+#define DLG_APPEND								152
+#define DLG_REFRESH								153
+#define DLG_TEXOFFSETX						154
+#define DLG_TEXOFFSETY						155
+#define DLG_TEXSCALEX							156
+#define DLG_TEXSCALEY							157
+#define DLG_FIXPOINTS							158
+#define DLG_TEXTURE_BROWSE				159
+#define DLG_AZIMUTH								162
+#define DLG_AZIMUTH_SPIN					163
+#define DLG_ELEVATION							164
+#define DLG_ELEVATION_SPIN				165
+#define DLG_RANDOMSEED						166
+#define DLG_RANDOMSEED_SPIN				167
+#define DLG_BITMAP								168
+#define DLG_SAVE									169
+#define DLG_OPEN									170
+#define DLG_TAB										171
+#define DLG_TEXTURE2							172
+#define DLG_TEXTURE2_BROWSE				173
+#define DLG_LADDER								174
+#define DLG_ARGHRAD2_TEXT					175
+#define DLG_FILE_TEXT							176
+#define DLG_DECIMATE							177
+#define DLG_DECIMATE_TEXT					178
+#define DLG_HIDEBACKFACES					179
+#define DLG_DEFAULTS							180
+#define DLG_ABOUT_APP							200
+#define DLG_ABOUT_ICON						201
+#define DLG_BMP_FILE							202
+#define DLG_BMP_FILE_BROWSE				203
+#define DLG_BMP_BLACK							204
+#define DLG_BMP_WHITE							205
+#define DLG_BMP_TEXT1							206
+#define DLG_BMP_TEXT2							207
+#define DLG_BMP_TEXT3							208
+#define DLG_BMP_NOTE							209
+#define DLG_BMP_RELOAD						210
+#define DLG_ABOUT_URL							211
+#define DLG_ABOUT_BOARD						212
+#define DLG_FIX_FREE							300
+#define DLG_FIX_FREEALL						301
+#define DLG_FIX_VALUE_TEXT				302
+#define DLG_FIX_VALUE							303
+#define DLG_FIX_VALUE_SPIN				304
+#define DLG_FIX_DONE							305
+#define DLG_FIX_RANGE_TEXT				306
+#define DLG_FIX_RANGE							307
+#define DLG_FIX_NOTE							308
+#define DLG_FIX_RATE_TEXT					309
+#define DLG_FIX_RATE							310
+#define DLG_USE_PATCHES						311
+#define DLG_DECIMATE_LABEL				312
+#define DLG_HINT									350
+#define DLG_GAME_00								400
+#define DLG_GAME_01								401
+#define DLG_GAME_02								402
+#define DLG_GAME_03								403
+#define DLG_GAME_04								404
+#define DLG_GAME_05								405
+#define DLG_GAME_06								406
+#define DLG_GAME_07								407
+#define DLG_GAME_08								408
+#define DLG_GAME_09								409
+#define DLG_TEX_USEPAK						420
+#define DLG_TEX_PAK_TEXT					421
+#define DLG_TEX_PAKFILE						422
+#define DLG_TEX_PAK_BROWSE				423
+#define DLG_TEX_LIST1							424
+#define DLG_TEX_LIST2							425
+#define DLG_TEX_LIST3							426
+#define DLG_TEXTURE3							427
+#define DLG_TEXTURE3_BROWSE				428
+#define DLG_TEX_SLANT_TEXT				429
+#define DLG_TEX_SLANT							430
+#define DLG_TEX_SLANT_SPIN			  431
+#define DLG_EXCEL_FUNC						500
+#define DLG_EXCEL_FUNC_TEXT				501
+#define DLG_PREVIEW_ANTIALIASING	502 // ^Fishman - Antializing for the preview window.
+#define DLG_SNAP_TO_GRID					503 // Hydra : snap to grid
diff --git a/contrib/gtkgensurf/gensurf.h b/contrib/gtkgensurf/gensurf.h
index 2c516d4e..8e42ac0d 100644
--- a/contrib/gtkgensurf/gensurf.h
+++ b/contrib/gtkgensurf/gensurf.h
@@ -1,395 +1,395 @@
-/*
-GenSurf plugin for GtkRadiant
-Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef _GENSURF_H_
-#define _GENSURF_H_
-
-#include <gtk/gtk.h>
-
-#include "qerplugin.h"
-//#include "qertypes.h"
-
-#include "igl.h"
-#include "iui_gtk.h"
-#include "ientity.h"
-
-#include "gendlgs.h"
-
-#define PLUGIN
-#define Q3RADIANT
-
-#if defined(__linux__) || defined(__APPLE__)
-template <class T>
-inline T min (T x, T y) { return (x < y) ? x : y; }
-template <class T>
-inline T max (T x, T y) { return (x > y) ? x : y; }
-
-typedef struct { long x, y; } POINT;
-typedef struct { long left, top, right, bottom; } RECT;
-#endif
-inline bool PtInRect (RECT *rc, POINT pt)
-{
-  if (pt.x < rc->left) return false;
-  if (pt.x > rc->right) return false;
-  if (pt.y < rc->bottom) return false;
-  if (pt.y > rc->top) return false;
-  return true;
-}
-
-#define NUMGAMES 7
-
-#define CONTENTS_SOLID  0x00000001
-#define	CONTENTS_DETAIL	0x08000000	// brushes to be added after vis leafs
-#define	CONTENTS_LADDER	0x20000000
-#define	SURF_HINT		0x100	// make a primary bsp splitter
-#define	SURF_SKIP		0x200	// completely ignore, allowing non-closed brushes
-#define HINT_OFFSET 96
-
-#define PI 3.14159265358979224
-#define RadiansToDegrees(a) (floor(a*57.2957795 - 0.5)+1.)
-#define DegreesToRadians(a) (a/57.2957795)
-
-#define	BOGUS_RANGE	65536
-#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
-#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
-#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
-#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
-#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
-#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
-#define XYZVectorSubtract(a,b,c) {c[0]=(float)a[0]-(float)b[0];c[1]=(float)a[1]-(float)b[1];c[2]=(float)a[2]-(float)b[2];}
-#define side(u1,v1,u2,v2,u3,v3) (v3-v1)*(u2-u1) - (u3-u1)*(v2-v1)
-
-#define QUAKE2    0
-#define HALFLIFE  1
-#define SIN       2
-#define HERETIC2  3
-#define KINGPIN   4
-#define GENESIS3D 5
-#define QUAKE3    6
-
-#define MAX_FACES_PER_BRUSH 6
-#define SLIVER_ANGLE DegreesToRadians(20)
-#define MAX_NODES (MAX_ROWS+1)*(MAX_ROWS+1)
-#define MAX_TRIS  (MAX_ROWS)*(MAX_ROWS)
-
-typedef float vec;
-typedef vec vec3[3];
-typedef vec vec2[2];
-
-typedef struct
-{
-	vec3   v[3];
-	char   texture[64];
-	float  Shift[2];
-	float  Rotate;
-	float  Scale[2];
-	int    Contents;
-	int    Surface;
-	int    Value;
-} FACE;
-
-typedef struct
-{
-	vec3 normal;
-	vec  dist;
-} PLANE;
-
-typedef struct
-{
-	int		numpoints;
-	vec3	p[4];		// variable sized
-} MY_WINDING;
-
-typedef struct
-{
-	int  Number;
-	int  NumFaces;
-	FACE face[MAX_FACES_PER_BRUSH];
-} BRUSH;
-
-typedef struct tagXYZ
-{
-	int fixed;
-	int done;
-	double p[3];
-	double pp[3];    // these used only for general 3D projection (not isometric)
-	double fixed_value;
-	double range;
-	double rate;
-} XYZ;
-
-// Q2 PAK file structures
-typedef struct
-{
-	char id[4]; // Should be 'PACK'
-	int dstart; // Offest in the file to the directory
-	int dsize;  // Size in bytes of the directory, same as num_items*64
-} pak_header_t;
-
-typedef struct
-{
-	char name[56]; // The name of the item, normal C string
-	int start; // Offset in .pak file to start of item
-	int size; // Size of item in bytes
-} pak_item_t;
-
-// SiN .SIN structures
-#define SINPAKHEADER		(('K'<<24)+('A'<<16)+('P'<<8)+'S')
-#define MAX_PAK_FILENAME_LENGTH 120
-
-typedef struct
-{
-	char	name[MAX_PAK_FILENAME_LENGTH];
-	int		filepos, filelen;
-} dpackfile_t;
-
-typedef struct
-{
-	int		ident;		// == IDPAKHEADER
-	int		dirofs;
-	int		dirlen;
-} dpackheader_t;
-
-// Half-Life WAD file structures
-typedef struct
-{
-	char		identification[4];		// should be WAD2 or 2DAW
-	int			numlumps;
-	int			infotableofs;
-} wadinfo_t;
-
-typedef struct
-{
-	int			filepos;
-	int			disksize;
-	int			size;					// uncompressed
-	char		type;
-	char		compression;
-	char		pad1, pad2;
-	char		name[16];				// must be null terminated
-} lumpinfo_t;
-
-typedef struct
-{
-	int		signature;
-	short	version;
-	short	bitflag;
-	short	compression_method;
-	short	modfiletime;
-	short	modfiledate;
-	int		crc;
-	int		compressed_size;
-	int		uncompressed_size;
-	short	filename_size;
-	short	extra_size;
-} zipheader_t;
-
-typedef struct
-{
-	double  x[2];
-	double  y[2];
-	double  z[2];
-} bounding_box;
-
-typedef struct
-{
-	float p[3];
-	int   used;
-	int   tri;
-	float error;
-	int   fixed;
-} NODE;
-
-typedef struct
-{
-	int   v[3];
-	int   n[3];    // indices of neighboring triangles
-	PLANE plane;
-	int   flag;
-	float min[3];
-	float max[3];
-} TRI;
-
-//--------------- bitmap.c -----------------------------
-bool OpenBitmap ();
-void GenerateBitmapMapping ();
-//--------------- face.c -------------------------------
-void PlaneFromPoints (float *, float *, float *, PLANE *);
-void CrossProduct (vec3 v1, vec3 v2, vec3 cross);
-vec VectorNormalize (vec3 in, vec3 out);
-//--------------- gendlg.c -----------------------------
-GtkWidget* create_main_dialog ();
-void About (GtkWidget *parent);
-//--------------- genmap.c -----------------------------
-double AtLeast(double,double);
-bool CanEdit(int, int);
-void CloseFuncGroup();
-bool FixedPoint(int,int);
-void GenerateMap();
-void GenerateXYZ();
-double LessThan(double,double);
-void MakeBrush(BRUSH *);
-double MoreThan(double,double);
-double Nearest(double,double);
-double NoMoreThan(double,double);
-void OpenFuncGroup();
-void PlasmaCloud();
-int PlayerStartZ(double,double);
-void SubdividePlasma(int,int,int,int);
-bool ValidSurface();
-void XYZtoV(XYZ *, vec3 *);
-void MakePatch(patchMesh_t *);
-double CalculateSnapValue(double value);
-
-//---------------- gensurf.c ---------------------------
-bool GenSurfInit ();
-void ReadIniFile (const char *);
-void WriteIniFile (const char *);
-void OpenSetup (GtkWidget*,int);
-void SaveSetup (GtkWidget*);
-//---------------- heretic.c ---------------------------
-int GetDefSurfaceProps(char *);
-//---------------- view.c ------------------------------
-void CreateViewWindow ();
-void DrawGrid(RECT);
-void DrawPreview(RECT);
-void evaluate();
-void GetScaleFactor(RECT);
-void project(XYZ *);
-void Scale(RECT,XYZ,POINT *);
-void ShowPreview ();
-void UpdatePreview (bool);
-
-//---------------- plugin.c -----------------------------
-void UseFaceBounds();
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERQglTable g_GLTable;
-extern _QERUIGtkTable g_UIGtkTable;
-extern _QEREntityTable g_EntityTable;
-//#define MAX_ROWS 64
-#define MAX_ROWS 128
-
-#define PLANE_XY0 0
-#define PLANE_XY1 1
-#define PLANE_YZ0 2
-#define PLANE_XZ0 3
-#define PLANE_YZ1 4
-#define PLANE_XZ1 5
-
-#define WAVE_COS_SIN    0
-#define WAVE_HCYLINDER  1
-#define WAVE_VCYLINDER  2
-#define WAVE_BITMAP     3
-#define WAVE_ROUGH_ONLY 4
-#define WAVE_FORMULA    5
-#define WAVE_FIRST      WAVE_COS_SIN
-#define WAVE_LAST       WAVE_FORMULA
-#define DLG_WAVE_LAST   DLG_WAVE_01+WAVE_LAST-WAVE_FIRST
-
-#define MSG_VERTEX_SELECTED WM_USER+1
-
-typedef struct tagMYBITMAP
-{
-  char             name[NAME_MAX];
-  char             defpath[NAME_MAX];
-  double           black_value;
-  double           white_value;
-  int width, height;
-  unsigned char* colors;
-} MYBITMAP;
-
-typedef struct tagELEMENT {
-	int i;
-	int j;
-} ELEMENT;
-
-extern char      gszAppDir[NAME_MAX];
-extern char      gszCaption[64];
-extern char      gszHelpFile[NAME_MAX];
-extern char      gszIni[NAME_MAX];
-extern char      gszMapFile[NAME_MAX];
-extern char      gszVersion[64];
-extern double    Amplitude;
-extern double    Roughness;
-extern double    TexOffset[2];
-extern double    TexScale[2];
-extern double    WaveLength;
-extern double    Hll, Hur, Vll, Vur;
-extern double    Z00, Z01, Z10, Z11;
-extern double    yaw, pitch, roll;
-extern ELEMENT   Vertex[(MAX_ROWS+1)*(MAX_ROWS+1)];
-extern int       AddHints;
-extern int       ArghRad2;
-extern int       AutoOverwrite;
-extern int       Decimate;
-extern int       FileAppend;
-extern int       FixBorders;
-extern int       HideBackFaces;
-extern int       NH, NV;
-extern int       NumVerticesSelected;
-extern int       Plane;
-extern int       Preview;
-extern int       RandomSeed;
-extern int       Skybox;
-extern int       UseDetail;
-extern int       UseLadder;
-extern int       VertexMode;
-extern int       vid_x, vid_y;
-extern int       WaveType;
-extern int       gNumNodes;
-extern int       gNumTris;
-extern int       view_x, view_y;
-extern int       view_cx, view_cy;
-extern int       UsePatches;
-extern int       SlantAngle;
-extern int       GimpHints;
-extern int			 Antialiasing; // ^Fishman - Antializing for the preview window.
-extern int			 AddTerrainKey; // ^Fishman - Add terrain key to func_group.
-extern int			 SnapToGrid; // Hydra : snap to grid
-extern int       SP; // ^Fishman - Snap to grid.
-
-/*extern HCURSOR   ghCursorCurrent;
-extern HCURSOR   ghCursorDefault;
-extern HCURSOR   ghCursorVertex;
-extern HINSTANCE ghInst;*/
-extern GtkWidget *g_pRadiantWnd;
-extern GtkWidget *g_pWnd;
-/*extern HWND      ghwndAngles;
-extern HWND      ghwndFix;
-*/extern GtkWidget     *g_pWndPreview;
-extern GtkWidget *g_pPreviewWidget;
-extern MYBITMAP  gbmp;
-extern NODE      *gNode;
-extern TRI       *gTri;
-extern XYZ       xyz[MAX_ROWS+1][MAX_ROWS+1];
-
-extern int       Game;
-extern bounding_box PlayerBox[NUMGAMES];
-//extern char      gszOutputDir[NUMGAMES][NAME_MAX];
-extern char      Texture[NUMGAMES][3][64];
-//extern char      gszTextureDir[NUMGAMES][NAME_MAX];
-extern char      GameName[NUMGAMES][16];
-//extern char      pakfile[NUMGAMES][NAME_MAX];
-//extern char      lastpakfile[NUMGAMES][NAME_MAX];
-//extern int       UsePak[NUMGAMES];
-//extern char      GameDir[NUMGAMES][NAME_MAX];
-//extern char      ExcelFunc[1024];
-
-#endif // _GENSURF_H_
+/*
+GenSurf plugin for GtkRadiant
+Copyright (C) 2001 David Hyde, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _GENSURF_H_
+#define _GENSURF_H_
+
+#include <gtk/gtk.h>
+
+#include "qerplugin.h"
+//#include "qertypes.h"
+
+#include "igl.h"
+#include "iui_gtk.h"
+#include "ientity.h"
+
+#include "gendlgs.h"
+
+#define PLUGIN
+#define Q3RADIANT
+
+#if defined(__linux__) || defined(__APPLE__)
+template <class T>
+inline T min (T x, T y) { return (x < y) ? x : y; }
+template <class T>
+inline T max (T x, T y) { return (x > y) ? x : y; }
+
+typedef struct { long x, y; } POINT;
+typedef struct { long left, top, right, bottom; } RECT;
+#endif
+inline bool PtInRect (RECT *rc, POINT pt)
+{
+  if (pt.x < rc->left) return false;
+  if (pt.x > rc->right) return false;
+  if (pt.y < rc->bottom) return false;
+  if (pt.y > rc->top) return false;
+  return true;
+}
+
+#define NUMGAMES 7
+
+#define CONTENTS_SOLID  0x00000001
+#define	CONTENTS_DETAIL	0x08000000	// brushes to be added after vis leafs
+#define	CONTENTS_LADDER	0x20000000
+#define	SURF_HINT		0x100	// make a primary bsp splitter
+#define	SURF_SKIP		0x200	// completely ignore, allowing non-closed brushes
+#define HINT_OFFSET 96
+
+#define PI 3.14159265358979224
+#define RadiansToDegrees(a) (floor(a*57.2957795 - 0.5)+1.)
+#define DegreesToRadians(a) (a/57.2957795)
+
+#define	BOGUS_RANGE	65536
+#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
+#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
+#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
+#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
+#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
+#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
+#define XYZVectorSubtract(a,b,c) {c[0]=(float)a[0]-(float)b[0];c[1]=(float)a[1]-(float)b[1];c[2]=(float)a[2]-(float)b[2];}
+#define side(u1,v1,u2,v2,u3,v3) (v3-v1)*(u2-u1) - (u3-u1)*(v2-v1)
+
+#define QUAKE2    0
+#define HALFLIFE  1
+#define SIN       2
+#define HERETIC2  3
+#define KINGPIN   4
+#define GENESIS3D 5
+#define QUAKE3    6
+
+#define MAX_FACES_PER_BRUSH 6
+#define SLIVER_ANGLE DegreesToRadians(20)
+#define MAX_NODES (MAX_ROWS+1)*(MAX_ROWS+1)
+#define MAX_TRIS  (MAX_ROWS)*(MAX_ROWS)
+
+typedef float vec;
+typedef vec vec3[3];
+typedef vec vec2[2];
+
+typedef struct
+{
+	vec3   v[3];
+	char   texture[64];
+	float  Shift[2];
+	float  Rotate;
+	float  Scale[2];
+	int    Contents;
+	int    Surface;
+	int    Value;
+} FACE;
+
+typedef struct
+{
+	vec3 normal;
+	vec  dist;
+} PLANE;
+
+typedef struct
+{
+	int		numpoints;
+	vec3	p[4];		// variable sized
+} MY_WINDING;
+
+typedef struct
+{
+	int  Number;
+	int  NumFaces;
+	FACE face[MAX_FACES_PER_BRUSH];
+} BRUSH;
+
+typedef struct tagXYZ
+{
+	int fixed;
+	int done;
+	double p[3];
+	double pp[3];    // these used only for general 3D projection (not isometric)
+	double fixed_value;
+	double range;
+	double rate;
+} XYZ;
+
+// Q2 PAK file structures
+typedef struct
+{
+	char id[4]; // Should be 'PACK'
+	int dstart; // Offest in the file to the directory
+	int dsize;  // Size in bytes of the directory, same as num_items*64
+} pak_header_t;
+
+typedef struct
+{
+	char name[56]; // The name of the item, normal C string
+	int start; // Offset in .pak file to start of item
+	int size; // Size of item in bytes
+} pak_item_t;
+
+// SiN .SIN structures
+#define SINPAKHEADER		(('K'<<24)+('A'<<16)+('P'<<8)+'S')
+#define MAX_PAK_FILENAME_LENGTH 120
+
+typedef struct
+{
+	char	name[MAX_PAK_FILENAME_LENGTH];
+	int		filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+	int		ident;		// == IDPAKHEADER
+	int		dirofs;
+	int		dirlen;
+} dpackheader_t;
+
+// Half-Life WAD file structures
+typedef struct
+{
+	char		identification[4];		// should be WAD2 or 2DAW
+	int			numlumps;
+	int			infotableofs;
+} wadinfo_t;
+
+typedef struct
+{
+	int			filepos;
+	int			disksize;
+	int			size;					// uncompressed
+	char		type;
+	char		compression;
+	char		pad1, pad2;
+	char		name[16];				// must be null terminated
+} lumpinfo_t;
+
+typedef struct
+{
+	int		signature;
+	short	version;
+	short	bitflag;
+	short	compression_method;
+	short	modfiletime;
+	short	modfiledate;
+	int		crc;
+	int		compressed_size;
+	int		uncompressed_size;
+	short	filename_size;
+	short	extra_size;
+} zipheader_t;
+
+typedef struct
+{
+	double  x[2];
+	double  y[2];
+	double  z[2];
+} bounding_box;
+
+typedef struct
+{
+	float p[3];
+	int   used;
+	int   tri;
+	float error;
+	int   fixed;
+} NODE;
+
+typedef struct
+{
+	int   v[3];
+	int   n[3];    // indices of neighboring triangles
+	PLANE plane;
+	int   flag;
+	float min[3];
+	float max[3];
+} TRI;
+
+//--------------- bitmap.c -----------------------------
+bool OpenBitmap ();
+void GenerateBitmapMapping ();
+//--------------- face.c -------------------------------
+void PlaneFromPoints (float *, float *, float *, PLANE *);
+void CrossProduct (vec3 v1, vec3 v2, vec3 cross);
+vec VectorNormalize (vec3 in, vec3 out);
+//--------------- gendlg.c -----------------------------
+GtkWidget* create_main_dialog ();
+void About (GtkWidget *parent);
+//--------------- genmap.c -----------------------------
+double AtLeast(double,double);
+bool CanEdit(int, int);
+void CloseFuncGroup();
+bool FixedPoint(int,int);
+void GenerateMap();
+void GenerateXYZ();
+double LessThan(double,double);
+void MakeBrush(BRUSH *);
+double MoreThan(double,double);
+double Nearest(double,double);
+double NoMoreThan(double,double);
+void OpenFuncGroup();
+void PlasmaCloud();
+int PlayerStartZ(double,double);
+void SubdividePlasma(int,int,int,int);
+bool ValidSurface();
+void XYZtoV(XYZ *, vec3 *);
+void MakePatch(patchMesh_t *);
+double CalculateSnapValue(double value);
+
+//---------------- gensurf.c ---------------------------
+bool GenSurfInit ();
+void ReadIniFile (const char *);
+void WriteIniFile (const char *);
+void OpenSetup (GtkWidget*,int);
+void SaveSetup (GtkWidget*);
+//---------------- heretic.c ---------------------------
+int GetDefSurfaceProps(char *);
+//---------------- view.c ------------------------------
+void CreateViewWindow ();
+void DrawGrid(RECT);
+void DrawPreview(RECT);
+void evaluate();
+void GetScaleFactor(RECT);
+void project(XYZ *);
+void Scale(RECT,XYZ,POINT *);
+void ShowPreview ();
+void UpdatePreview (bool);
+
+//---------------- plugin.c -----------------------------
+void UseFaceBounds();
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERQglTable g_GLTable;
+extern _QERUIGtkTable g_UIGtkTable;
+extern _QEREntityTable g_EntityTable;
+//#define MAX_ROWS 64
+#define MAX_ROWS 128
+
+#define PLANE_XY0 0
+#define PLANE_XY1 1
+#define PLANE_YZ0 2
+#define PLANE_XZ0 3
+#define PLANE_YZ1 4
+#define PLANE_XZ1 5
+
+#define WAVE_COS_SIN    0
+#define WAVE_HCYLINDER  1
+#define WAVE_VCYLINDER  2
+#define WAVE_BITMAP     3
+#define WAVE_ROUGH_ONLY 4
+#define WAVE_FORMULA    5
+#define WAVE_FIRST      WAVE_COS_SIN
+#define WAVE_LAST       WAVE_FORMULA
+#define DLG_WAVE_LAST   DLG_WAVE_01+WAVE_LAST-WAVE_FIRST
+
+#define MSG_VERTEX_SELECTED WM_USER+1
+
+typedef struct tagMYBITMAP
+{
+  char             name[NAME_MAX];
+  char             defpath[NAME_MAX];
+  double           black_value;
+  double           white_value;
+  int width, height;
+  unsigned char* colors;
+} MYBITMAP;
+
+typedef struct tagELEMENT {
+	int i;
+	int j;
+} ELEMENT;
+
+extern char      gszAppDir[NAME_MAX];
+extern char      gszCaption[64];
+extern char      gszHelpFile[NAME_MAX];
+extern char      gszIni[NAME_MAX];
+extern char      gszMapFile[NAME_MAX];
+extern char      gszVersion[64];
+extern double    Amplitude;
+extern double    Roughness;
+extern double    TexOffset[2];
+extern double    TexScale[2];
+extern double    WaveLength;
+extern double    Hll, Hur, Vll, Vur;
+extern double    Z00, Z01, Z10, Z11;
+extern double    yaw, pitch, roll;
+extern ELEMENT   Vertex[(MAX_ROWS+1)*(MAX_ROWS+1)];
+extern int       AddHints;
+extern int       ArghRad2;
+extern int       AutoOverwrite;
+extern int       Decimate;
+extern int       FileAppend;
+extern int       FixBorders;
+extern int       HideBackFaces;
+extern int       NH, NV;
+extern int       NumVerticesSelected;
+extern int       Plane;
+extern int       Preview;
+extern int       RandomSeed;
+extern int       Skybox;
+extern int       UseDetail;
+extern int       UseLadder;
+extern int       VertexMode;
+extern int       vid_x, vid_y;
+extern int       WaveType;
+extern int       gNumNodes;
+extern int       gNumTris;
+extern int       view_x, view_y;
+extern int       view_cx, view_cy;
+extern int       UsePatches;
+extern int       SlantAngle;
+extern int       GimpHints;
+extern int			 Antialiasing; // ^Fishman - Antializing for the preview window.
+extern int			 AddTerrainKey; // ^Fishman - Add terrain key to func_group.
+extern int			 SnapToGrid; // Hydra : snap to grid
+extern int       SP; // ^Fishman - Snap to grid.
+
+/*extern HCURSOR   ghCursorCurrent;
+extern HCURSOR   ghCursorDefault;
+extern HCURSOR   ghCursorVertex;
+extern HINSTANCE ghInst;*/
+extern GtkWidget *g_pRadiantWnd;
+extern GtkWidget *g_pWnd;
+/*extern HWND      ghwndAngles;
+extern HWND      ghwndFix;
+*/extern GtkWidget     *g_pWndPreview;
+extern GtkWidget *g_pPreviewWidget;
+extern MYBITMAP  gbmp;
+extern NODE      *gNode;
+extern TRI       *gTri;
+extern XYZ       xyz[MAX_ROWS+1][MAX_ROWS+1];
+
+extern int       Game;
+extern bounding_box PlayerBox[NUMGAMES];
+//extern char      gszOutputDir[NUMGAMES][NAME_MAX];
+extern char      Texture[NUMGAMES][3][64];
+//extern char      gszTextureDir[NUMGAMES][NAME_MAX];
+extern char      GameName[NUMGAMES][16];
+//extern char      pakfile[NUMGAMES][NAME_MAX];
+//extern char      lastpakfile[NUMGAMES][NAME_MAX];
+//extern int       UsePak[NUMGAMES];
+//extern char      GameDir[NUMGAMES][NAME_MAX];
+//extern char      ExcelFunc[1024];
+
+#endif // _GENSURF_H_
diff --git a/contrib/gtkgensurf/triangle.c b/contrib/gtkgensurf/triangle.c
index 1462499f..1e155cac 100644
--- a/contrib/gtkgensurf/triangle.c
+++ b/contrib/gtkgensurf/triangle.c
@@ -1,13236 +1,13236 @@
-#define ANSI_DECLARATORS
-/*****************************************************************************/
-/*                                                                           */
-/*      888888888        ,o,                          / 888                  */
-/*         888    88o88o  "    o8888o  88o8888o o88888o 888  o88888o         */
-/*         888    888    888       88b 888  888 888 888 888 d888  88b        */
-/*         888    888    888  o88^o888 888  888 "88888" 888 8888oo888        */
-/*         888    888    888 C888  888 888  888  /      888 q888             */
-/*         888    888    888  "88o^888 888  888 Cb      888  "88oooo"        */
-/*                                              "8oo8D                       */
-/*                                                                           */
-/*  A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.      */
-/*  (triangle.c)                                                             */
-/*                                                                           */
-/*  Version 1.3                                                              */
-/*  July 19, 1996                                                            */
-/*                                                                           */
-/*  Copyright 1996                                                           */
-/*  Jonathan Richard Shewchuk                                                */
-/*  School of Computer Science                                               */
-/*  Carnegie Mellon University                                               */
-/*  5000 Forbes Avenue                                                       */
-/*  Pittsburgh, Pennsylvania  15213-3891                                     */
-/*  jrs@cs.cmu.edu                                                           */
-/*                                                                           */
-/*  This program may be freely redistributed under the condition that the    */
-/*    copyright notices (including this entire header and the copyright      */
-/*    notice printed when the `-h' switch is selected) are not removed, and  */
-/*    no compensation is received.  Private, research, and institutional     */
-/*    use is free.  You may distribute modified versions of this code UNDER  */
-/*    THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE   */
-/*    SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE   */
-/*    AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR    */
-/*    NOTICE IS GIVEN OF THE MODIFICATIONS.  Distribution of this code as    */
-/*    part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT  */
-/*    WITH THE AUTHOR.  (If you are not directly supplying this code to a    */
-/*    customer, and you are instead telling them how they can obtain it for  */
-/*    free, then you are not required to make any arrangement with me.)      */
-/*                                                                           */
-/*  Hypertext instructions for Triangle are available on the Web at          */
-/*                                                                           */
-/*      http://www.cs.cmu.edu/~quake/triangle.html                           */
-/*                                                                           */
-/*  Some of the references listed below are marked [*].  These are available */
-/*    for downloading from the Web page                                      */
-/*                                                                           */
-/*      http://www.cs.cmu.edu/~quake/triangle.research.html                  */
-/*                                                                           */
-/*  A paper discussing some aspects of Triangle is available.  See Jonathan  */
-/*    Richard Shewchuk, "Triangle:  Engineering a 2D Quality Mesh Generator  */
-/*    and Delaunay Triangulator," First Workshop on Applied Computational    */
-/*    Geometry, ACM, May 1996.  [*]                                          */
-/*                                                                           */
-/*  Triangle was created as part of the Archimedes project in the School of  */
-/*    Computer Science at Carnegie Mellon University.  Archimedes is a       */
-/*    system for compiling parallel finite element solvers.  For further     */
-/*    information, see Anja Feldmann, Omar Ghattas, John R. Gilbert, Gary L. */
-/*    Miller, David R. O'Hallaron, Eric J. Schwabe, Jonathan R. Shewchuk,    */
-/*    and Shang-Hua Teng, "Automated Parallel Solution of Unstructured PDE   */
-/*    Problems."  To appear in Communications of the ACM, we hope.           */
-/*                                                                           */
-/*  The quality mesh generation algorithm is due to Jim Ruppert, "A          */
-/*    Delaunay Refinement Algorithm for Quality 2-Dimensional Mesh           */
-/*    Generation," Journal of Algorithms 18(3):548-585, May 1995.  [*]       */
-/*                                                                           */
-/*  My implementation of the divide-and-conquer and incremental Delaunay     */
-/*    triangulation algorithms follows closely the presentation of Guibas    */
-/*    and Stolfi, even though I use a triangle-based data structure instead  */
-/*    of their quad-edge data structure.  (In fact, I originally implemented */
-/*    Triangle using the quad-edge data structure, but switching to a        */
-/*    triangle-based data structure sped Triangle by a factor of two.)  The  */
-/*    mesh manipulation primitives and the two aforementioned Delaunay       */
-/*    triangulation algorithms are described by Leonidas J. Guibas and Jorge */
-/*    Stolfi, "Primitives for the Manipulation of General Subdivisions and   */
-/*    the Computation of Voronoi Diagrams," ACM Transactions on Graphics     */
-/*    4(2):74-123, April 1985.                                               */
-/*                                                                           */
-/*  Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai   */
-/*    Lee and Bruce J. Schachter, "Two Algorithms for Constructing the       */
-/*    Delaunay Triangulation," International Journal of Computer and         */
-/*    Information Science 9(3):219-242, 1980.  The idea to improve the       */
-/*    divide-and-conquer algorithm by alternating between vertical and       */
-/*    horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and-  */
-/*    Conquer Algorithm for Constructing Delaunay Triangulations,"           */
-/*    Algorithmica 2(2):137-151, 1987.                                       */
-/*                                                                           */
-/*  The incremental insertion algorithm was first proposed by C. L. Lawson,  */
-/*    "Software for C1 Surface Interpolation," in Mathematical Software III, */
-/*    John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977.     */
-/*    For point location, I use the algorithm of Ernst P. Mucke, Isaac       */
-/*    Saias, and Binhai Zhu, "Fast Randomized Point Location Without         */
-/*    Preprocessing in Two- and Three-dimensional Delaunay Triangulations,"  */
-/*    Proceedings of the Twelfth Annual Symposium on Computational Geometry, */
-/*    ACM, May 1996.  [*]  If I were to randomize the order of point         */
-/*    insertion (I currently don't bother), their result combined with the   */
-/*    result of Leonidas J. Guibas, Donald E. Knuth, and Micha Sharir,       */
-/*    "Randomized Incremental Construction of Delaunay and Voronoi           */
-/*    Diagrams," Algorithmica 7(4):381-413, 1992, would yield an expected    */
-/*    O(n^{4/3}) bound on running time.                                      */
-/*                                                                           */
-/*  The O(n log n) sweepline Delaunay triangulation algorithm is taken from  */
-/*    Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams",          */
-/*    Algorithmica 2(2):153-174, 1987.  A random sample of edges on the      */
-/*    boundary of the triangulation are maintained in a splay tree for the   */
-/*    purpose of point location.  Splay trees are described by Daniel        */
-/*    Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
-/*    Trees," Journal of the ACM 32(3):652-686, July 1985.                   */
-/*                                                                           */
-/*  The algorithms for exact computation of the signs of determinants are    */
-/*    described in Jonathan Richard Shewchuk, "Adaptive Precision Floating-  */
-/*    Point Arithmetic and Fast Robust Geometric Predicates," Technical      */
-/*    Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon      */
-/*    University, Pittsburgh, Pennsylvania, May 1996.  [*]  (Submitted to    */
-/*    Discrete & Computational Geometry.)  An abbreviated version appears as */
-/*    Jonathan Richard Shewchuk, "Robust Adaptive Floating-Point Geometric   */
-/*    Predicates," Proceedings of the Twelfth Annual Symposium on Computa-   */
-/*    tional Geometry, ACM, May 1996.  [*]  Many of the ideas for my exact   */
-/*    arithmetic routines originate with Douglas M. Priest, "Algorithms for  */
-/*    Arbitrary Precision Floating Point Arithmetic," Tenth Symposium on     */
-/*    Computer Arithmetic, 132-143, IEEE Computer Society Press, 1991.  [*]  */
-/*    Many of the ideas for the correct evaluation of the signs of           */
-/*    determinants are taken from Steven Fortune and Christopher J. Van Wyk, */
-/*    "Efficient Exact Arithmetic for Computational Geometry," Proceedings   */
-/*    of the Ninth Annual Symposium on Computational Geometry, ACM,          */
-/*    pp. 163-172, May 1993, and from Steven Fortune, "Numerical Stability   */
-/*    of Algorithms for 2D Delaunay Triangulations," International Journal   */
-/*    of Computational Geometry & Applications 5(1-2):193-213, March-June    */
-/*    1995.                                                                  */
-/*                                                                           */
-/*  For definitions of and results involving Delaunay triangulations,        */
-/*    constrained and conforming versions thereof, and other aspects of      */
-/*    triangular mesh generation, see the excellent survey by Marshall Bern  */
-/*    and David Eppstein, "Mesh Generation and Optimal Triangulation," in    */
-/*    Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang,         */
-/*    editors, World Scientific, Singapore, pp. 23-90, 1992.                 */
-/*                                                                           */
-/*  The time for incrementally adding PSLG (planar straight line graph)      */
-/*    segments to create a constrained Delaunay triangulation is probably    */
-/*    O(n^2) per segment in the worst case and O(n) per edge in the common   */
-/*    case, where n is the number of triangles that intersect the segment    */
-/*    before it is inserted.  This doesn't count point location, which can   */
-/*    be much more expensive.  (This note does not apply to conforming       */
-/*    Delaunay triangulations, for which a different method is used to       */
-/*    insert segments.)                                                      */
-/*                                                                           */
-/*  The time for adding segments to a conforming Delaunay triangulation is   */
-/*    not clear, but does not depend upon n alone.  In some cases, very      */
-/*    small features (like a point lying next to a segment) can cause a      */
-/*    single segment to be split an arbitrary number of times.  Of course,   */
-/*    floating-point precision is a practical barrier to how much this can   */
-/*    happen.                                                                */
-/*                                                                           */
-/*  The time for deleting a point from a Delaunay triangulation is O(n^2) in */
-/*    the worst case and O(n) in the common case, where n is the degree of   */
-/*    the point being deleted.  I could improve this to expected O(n) time   */
-/*    by "inserting" the neighboring vertices in random order, but n is      */
-/*    usually quite small, so it's not worth the bother.  (The O(n) time     */
-/*    for random insertion follows from L. Paul Chew, "Building Voronoi      */
-/*    Diagrams for Convex Polygons in Linear Expected Time," Technical       */
-/*    Report PCS-TR90-147, Department of Mathematics and Computer Science,   */
-/*    Dartmouth College, 1990.                                               */
-/*                                                                           */
-/*  Ruppert's Delaunay refinement algorithm typically generates triangles    */
-/*    at a linear rate (constant time per triangle) after the initial        */
-/*    triangulation is formed.  There may be pathological cases where more   */
-/*    time is required, but these never arise in practice.                   */
-/*                                                                           */
-/*  The segment intersection formulae are straightforward.  If you want to   */
-/*    see them derived, see Franklin Antonio.  "Faster Line Segment          */
-/*    Intersection."  In Graphics Gems III (David Kirk, editor), pp. 199-    */
-/*    202.  Academic Press, Boston, 1992.                                    */
-/*                                                                           */
-/*  If you make any improvements to this code, please please please let me   */
-/*    know, so that I may obtain the improvements.  Even if you don't change */
-/*    the code, I'd still love to hear what it's being used for.             */
-/*                                                                           */
-/*  Disclaimer:  Neither I nor Carnegie Mellon warrant this code in any way  */
-/*    whatsoever.  This code is provided "as-is".  Use at your own risk.     */
-/*                                                                           */
-/*****************************************************************************/
-
-/* For single precision (which will save some memory and reduce paging),     */
-/*   define the symbol SINGLE by using the -DSINGLE compiler switch or by    */
-/*   writing "#define SINGLE" below.                                         */
-/*                                                                           */
-/* For double precision (which will allow you to refine meshes to a smaller  */
-/*   edge length), leave SINGLE undefined.                                   */
-/*                                                                           */
-/* Double precision uses more memory, but improves the resolution of the     */
-/*   meshes you can generate with Triangle.  It also reduces the likelihood  */
-/*   of a floating exception due to overflow.  Finally, it is much faster    */
-/*   than single precision on 64-bit architectures like the DEC Alpha.  I    */
-/*   recommend double precision unless you want to generate a mesh for which */
-/*   you do not have enough memory.                                          */
-
-#define SINGLE
-
-#ifdef SINGLE
-#define REAL float
-#else /* not SINGLE */
-#define REAL double
-#endif /* not SINGLE */
-
-/* If yours is not a Unix system, define the NO_TIMER compiler switch to     */
-/*   remove the Unix-specific timing code.                                   */
-
-#define NO_TIMER
-
-/* To insert lots of self-checks for internal errors, define the SELF_CHECK  */
-/*   symbol.  This will slow down the program significantly.  It is best to  */
-/*   define the symbol using the -DSELF_CHECK compiler switch, but you could */
-/*   write "#define SELF_CHECK" below.  If you are modifying this code, I    */
-/*   recommend you turn self-checks on.                                      */
-
-/* #define SELF_CHECK */
-
-/* To compile Triangle as a callable object library (triangle.o), define the */
-/*   TRILIBRARY symbol.  Read the file triangle.h for details on how to call */
-/*   the procedure triangulate() that results.                               */
-
-#define TRILIBRARY
-
-/* It is possible to generate a smaller version of Triangle using one or     */
-/*   both of the following symbols.  Define the REDUCED symbol to eliminate  */
-/*   all features that are primarily of research interest; specifically, the */
-/*   -i, -F, -s, and -C switches.  Define the CDT_ONLY symbol to eliminate   */
-/*   all meshing algorithms above and beyond constrained Delaunay            */
-/*   triangulation; specifically, the -r, -q, -a, -S, and -s switches.       */
-/*   These reductions are most likely to be useful when generating an object */
-/*   library (triangle.o) by defining the TRILIBRARY symbol.                 */
-
-#define REDUCED
-#define CDT_ONLY
-
-/* On some machines, the exact arithmetic routines might be defeated by the  */
-/*   use of internal extended precision floating-point registers.  Sometimes */
-/*   this problem can be fixed by defining certain values to be volatile,    */
-/*   thus forcing them to be stored to memory and rounded off.  This isn't   */
-/*   a great solution, though, as it slows Triangle down.                    */
-/*                                                                           */
-/* To try this out, write "#define INEXACT volatile" below.  Normally,       */
-/*   however, INEXACT should be defined to be nothing.  ("#define INEXACT".) */
-
-#define INEXACT /* Nothing */
-/* #define INEXACT volatile */
-
-/* Maximum number of characters in a file name (including the null).         */
-
-#define FILENAMESIZE 512
-
-/* Maximum number of characters in a line read from a file (including the    */
-/*   null).                                                                  */
-
-#define INPUTLINESIZE 512
-
-/* For efficiency, a variety of data structures are allocated in bulk.  The  */
-/*   following constants determine how many of each structure is allocated   */
-/*   at once.                                                                */
-
-#define TRIPERBLOCK 4092           /* Number of triangles allocated at once. */
-#define SHELLEPERBLOCK 508       /* Number of shell edges allocated at once. */
-#define POINTPERBLOCK 4092            /* Number of points allocated at once. */
-#define VIRUSPERBLOCK 1020   /* Number of virus triangles allocated at once. */
-/* Number of encroached segments allocated at once. */
-#define BADSEGMENTPERBLOCK 252
-/* Number of skinny triangles allocated at once. */
-#define BADTRIPERBLOCK 4092
-/* Number of splay tree nodes allocated at once. */
-#define SPLAYNODEPERBLOCK 508
-
-/* The point marker DEADPOINT is an arbitrary number chosen large enough to  */
-/*   (hopefully) not conflict with user boundary markers.  Make sure that it */
-/*   is small enough to fit into your machine's integer size.                */
-
-#define DEADPOINT -1073741824
-
-/* The next line is used to outsmart some very stupid compilers.  If your    */
-/*   compiler is smarter, feel free to replace the "int" with "void".        */
-/*   Not that it matters.                                                    */
-
-#define VOID int
-
-/* Two constants for algorithms based on random sampling.  Both constants    */
-/*   have been chosen empirically to optimize their respective algorithms.   */
-
-/* Used for the point location scheme of Mucke, Saias, and Zhu, to decide    */
-/*   how large a random sample of triangles to inspect.                      */
-#define SAMPLEFACTOR 11
-/* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */
-/*   of boundary edges should be maintained in the splay tree for point      */
-/*   location on the front.                                                  */
-#define SAMPLERATE 10
-
-/* A number that speaks for itself, every kissable digit.                    */
-
-#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
-
-/* Another fave.                                                             */
-
-#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
-
-/* And here's one for those of you who are intimidated by math.              */
-
-#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
-
-#include <stdio.h>
-#include <string.h>
-#include <math.h>
-#ifndef NO_TIMER
-#include <sys/time.h>
-#endif /* NO_TIMER */
-#ifdef TRILIBRARY
-#include "triangle.h"
-#endif /* TRILIBRARY */
-
-/* The following obscenity seems to be necessary to ensure that this program */
-/* will port to Dec Alphas running OSF/1, because their stdio.h file commits */
-/* the unpardonable sin of including stdlib.h.  Hence, malloc(), free(), and */
-/* exit() may or may not already be defined at this point.  I declare these  */
-/* functions explicitly because some non-ANSI C compilers lack stdlib.h.     */
-
-#ifndef _STDLIB_H_
-extern void *malloc();
-extern void free();
-extern void exit();
-extern double strtod();
-extern long strtol();
-#endif /* _STDLIB_H_ */
-
-/* A few forward declarations.                                               */
-
-void poolrestart();
-#ifndef TRILIBRARY
-char *readline();
-char *findfield();
-#endif /* not TRILIBRARY */
-
-/* Labels that signify whether a record consists primarily of pointers or of */
-/*   floating-point words.  Used to make decisions about data alignment.     */
-
-enum wordtype {POINTER, FLOATINGPOINT};
-
-/* Labels that signify the result of point location.  The result of a        */
-/*   search indicates that the point falls in the interior of a triangle, on */
-/*   an edge, on a vertex, or outside the mesh.                              */
-
-enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
-
-/* Labels that signify the result of site insertion.  The result indicates   */
-/*   that the point was inserted with complete success, was inserted but     */
-/*   encroaches on a segment, was not inserted because it lies on a segment, */
-/*   or was not inserted because another point occupies the same location.   */
-
-enum insertsiteresult {SUCCESSFULPOINT, ENCROACHINGPOINT, VIOLATINGPOINT,
-                       DUPLICATEPOINT};
-
-/* Labels that signify the result of direction finding.  The result          */
-/*   indicates that a segment connecting the two query points falls within   */
-/*   the direction triangle, along the left edge of the direction triangle,  */
-/*   or along the right edge of the direction triangle.                      */
-
-enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
-
-/* Labels that signify the result of the circumcenter computation routine.   */
-/*   The return value indicates which edge of the triangle is shortest.      */
-
-enum circumcenterresult {OPPOSITEORG, OPPOSITEDEST, OPPOSITEAPEX};
-
-/*****************************************************************************/
-/*                                                                           */
-/*  The basic mesh data structures                                           */
-/*                                                                           */
-/*  There are three:  points, triangles, and shell edges (abbreviated        */
-/*  `shelle').  These three data structures, linked by pointers, comprise    */
-/*  the mesh.  A point simply represents a point in space and its properties.*/
-/*  A triangle is a triangle.  A shell edge is a special data structure used */
-/*  to represent impenetrable segments in the mesh (including the outer      */
-/*  boundary, boundaries of holes, and internal boundaries separating two    */
-/*  triangulated regions).  Shell edges represent boundaries defined by the  */
-/*  user that triangles may not lie across.                                  */
-/*                                                                           */
-/*  A triangle consists of a list of three vertices, a list of three         */
-/*  adjoining triangles, a list of three adjoining shell edges (when shell   */
-/*  edges are used), an arbitrary number of optional user-defined floating-  */
-/*  point attributes, and an optional area constraint.  The latter is an     */
-/*  upper bound on the permissible area of each triangle in a region, used   */
-/*  for mesh refinement.                                                     */
-/*                                                                           */
-/*  For a triangle on a boundary of the mesh, some or all of the neighboring */
-/*  triangles may not be present.  For a triangle in the interior of the     */
-/*  mesh, often no neighboring shell edges are present.  Such absent         */
-/*  triangles and shell edges are never represented by NULL pointers; they   */
-/*  are represented by two special records:  `dummytri', the triangle that   */
-/*  fills "outer space", and `dummysh', the omnipresent shell edge.          */
-/*  `dummytri' and `dummysh' are used for several reasons; for instance,     */
-/*  they can be dereferenced and their contents examined without causing the */
-/*  memory protection exception that would occur if NULL were dereferenced.  */
-/*                                                                           */
-/*  However, it is important to understand that a triangle includes other    */
-/*  information as well.  The pointers to adjoining vertices, triangles, and */
-/*  shell edges are ordered in a way that indicates their geometric relation */
-/*  to each other.  Furthermore, each of these pointers contains orientation */
-/*  information.  Each pointer to an adjoining triangle indicates which face */
-/*  of that triangle is contacted.  Similarly, each pointer to an adjoining  */
-/*  shell edge indicates which side of that shell edge is contacted, and how */
-/*  the shell edge is oriented relative to the triangle.                     */
-/*                                                                           */
-/*  Shell edges are found abutting edges of triangles; either sandwiched     */
-/*  between two triangles, or resting against one triangle on an exterior    */
-/*  boundary or hole boundary.                                               */
-/*                                                                           */
-/*  A shell edge consists of a list of two vertices, a list of two           */
-/*  adjoining shell edges, and a list of two adjoining triangles.  One of    */
-/*  the two adjoining triangles may not be present (though there should      */
-/*  always be one), and neighboring shell edges might not be present.        */
-/*  Shell edges also store a user-defined integer "boundary marker".         */
-/*  Typically, this integer is used to indicate what sort of boundary        */
-/*  conditions are to be applied at that location in a finite element        */
-/*  simulation.                                                              */
-/*                                                                           */
-/*  Like triangles, shell edges maintain information about the relative      */
-/*  orientation of neighboring objects.                                      */
-/*                                                                           */
-/*  Points are relatively simple.  A point is a list of floating point       */
-/*  numbers, starting with the x, and y coordinates, followed by an          */
-/*  arbitrary number of optional user-defined floating-point attributes,     */
-/*  followed by an integer boundary marker.  During the segment insertion    */
-/*  phase, there is also a pointer from each point to a triangle that may    */
-/*  contain it.  Each pointer is not always correct, but when one is, it     */
-/*  speeds up segment insertion.  These pointers are assigned values once    */
-/*  at the beginning of the segment insertion phase, and are not used or     */
-/*  updated at any other time.  Edge swapping during segment insertion will  */
-/*  render some of them incorrect.  Hence, don't rely upon them for          */
-/*  anything.  For the most part, points do not have any information about   */
-/*  what triangles or shell edges they are linked to.                        */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Handles                                                                  */
-/*                                                                           */
-/*  The oriented triangle (`triedge') and oriented shell edge (`edge') data  */
-/*  structures defined below do not themselves store any part of the mesh.   */
-/*  The mesh itself is made of `triangle's, `shelle's, and `point's.         */
-/*                                                                           */
-/*  Oriented triangles and oriented shell edges will usually be referred to  */
-/*  as "handles".  A handle is essentially a pointer into the mesh; it       */
-/*  allows you to "hold" one particular part of the mesh.  Handles are used  */
-/*  to specify the regions in which one is traversing and modifying the mesh.*/
-/*  A single `triangle' may be held by many handles, or none at all.  (The   */
-/*  latter case is not a memory leak, because the triangle is still          */
-/*  connected to other triangles in the mesh.)                               */
-/*                                                                           */
-/*  A `triedge' is a handle that holds a triangle.  It holds a specific side */
-/*  of the triangle.  An `edge' is a handle that holds a shell edge.  It     */
-/*  holds either the left or right side of the edge.                         */
-/*                                                                           */
-/*  Navigation about the mesh is accomplished through a set of mesh          */
-/*  manipulation primitives, further below.  Many of these primitives take   */
-/*  a handle and produce a new handle that holds the mesh near the first     */
-/*  handle.  Other primitives take two handles and glue the corresponding    */
-/*  parts of the mesh together.  The exact position of the handles is        */
-/*  important.  For instance, when two triangles are glued together by the   */
-/*  bond() primitive, they are glued by the sides on which the handles lie.  */
-/*                                                                           */
-/*  Because points have no information about which triangles they are        */
-/*  attached to, I commonly represent a point by use of a handle whose       */
-/*  origin is the point.  A single handle can simultaneously represent a     */
-/*  triangle, an edge, and a point.                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-/* The triangle data structure.  Each triangle contains three pointers to    */
-/*   adjoining triangles, plus three pointers to vertex points, plus three   */
-/*   pointers to shell edges (defined below; these pointers are usually      */
-/*   `dummysh').  It may or may not also contain user-defined attributes     */
-/*   and/or a floating-point "area constraint".  It may also contain extra   */
-/*   pointers for nodes, when the user asks for high-order elements.         */
-/*   Because the size and structure of a `triangle' is not decided until     */
-/*   runtime, I haven't simply defined the type `triangle' to be a struct.   */
-
-typedef REAL **triangle;            /* Really:  typedef triangle *triangle   */
-
-/* An oriented triangle:  includes a pointer to a triangle and orientation.  */
-/*   The orientation denotes an edge of the triangle.  Hence, there are      */
-/*   three possible orientations.  By convention, each edge is always        */
-/*   directed to point counterclockwise about the corresponding triangle.    */
-
-struct triedge {
-  triangle *tri;
-  int orient;                                         /* Ranges from 0 to 2. */
-};
-
-/* The shell data structure.  Each shell edge contains two pointers to       */
-/*   adjoining shell edges, plus two pointers to vertex points, plus two     */
-/*   pointers to adjoining triangles, plus one shell marker.                 */
-
-typedef REAL **shelle;                  /* Really:  typedef shelle *shelle   */
-
-/* An oriented shell edge:  includes a pointer to a shell edge and an        */
-/*   orientation.  The orientation denotes a side of the edge.  Hence, there */
-/*   are two possible orientations.  By convention, the edge is always       */
-/*   directed so that the "side" denoted is the right side of the edge.      */
-
-struct edge {
-  shelle *sh;
-  int shorient;                                       /* Ranges from 0 to 1. */
-};
-
-/* The point data structure.  Each point is actually an array of REALs.      */
-/*   The number of REALs is unknown until runtime.  An integer boundary      */
-/*   marker, and sometimes a pointer to a triangle, is appended after the    */
-/*   REALs.                                                                  */
-
-typedef REAL *point;
-
-/* A queue used to store encroached segments.  Each segment's vertices are   */
-/*   stored so that one can check whether a segment is still the same.       */
-
-struct badsegment {
-  struct edge encsegment;                          /* An encroached segment. */
-  point segorg, segdest;                                /* The two vertices. */
-  struct badsegment *nextsegment;     /* Pointer to next encroached segment. */
-};
-
-/* A queue used to store bad triangles.  The key is the square of the cosine */
-/*   of the smallest angle of the triangle.  Each triangle's vertices are    */
-/*   stored so that one can check whether a triangle is still the same.      */
-
-struct badface {
-  struct triedge badfacetri;                              /* A bad triangle. */
-  REAL key;                             /* cos^2 of smallest (apical) angle. */
-  point faceorg, facedest, faceapex;                  /* The three vertices. */
-  struct badface *nextface;                 /* Pointer to next bad triangle. */
-};
-
-/* A node in a heap used to store events for the sweepline Delaunay          */
-/*   algorithm.  Nodes do not point directly to their parents or children in */
-/*   the heap.  Instead, each node knows its position in the heap, and can   */
-/*   look up its parent and children in a separate array.  The `eventptr'    */
-/*   points either to a `point' or to a triangle (in encoded format, so that */
-/*   an orientation is included).  In the latter case, the origin of the     */
-/*   oriented triangle is the apex of a "circle event" of the sweepline      */
-/*   algorithm.  To distinguish site events from circle events, all circle   */
-/*   events are given an invalid (smaller than `xmin') x-coordinate `xkey'.  */
-
-struct event {
-  REAL xkey, ykey;                              /* Coordinates of the event. */
-  VOID *eventptr;       /* Can be a point or the location of a circle event. */
-  int heapposition;              /* Marks this event's position in the heap. */
-};
-
-/* A node in the splay tree.  Each node holds an oriented ghost triangle     */
-/*   that represents a boundary edge of the growing triangulation.  When a   */
-/*   circle event covers two boundary edges with a triangle, so that they    */
-/*   are no longer boundary edges, those edges are not immediately deleted   */
-/*   from the tree; rather, they are lazily deleted when they are next       */
-/*   encountered.  (Since only a random sample of boundary edges are kept    */
-/*   in the tree, lazy deletion is faster.)  `keydest' is used to verify     */
-/*   that a triangle is still the same as when it entered the splay tree; if */
-/*   it has been rotated (due to a circle event), it no longer represents a  */
-/*   boundary edge and should be deleted.                                    */
-
-struct splaynode {
-  struct triedge keyedge;                  /* Lprev of an edge on the front. */
-  point keydest;            /* Used to verify that splay node is still live. */
-  struct splaynode *lchild, *rchild;              /* Children in splay tree. */
-};
-
-/* A type used to allocate memory.  firstblock is the first block of items.  */
-/*   nowblock is the block from which items are currently being allocated.   */
-/*   nextitem points to the next slab of free memory for an item.            */
-/*   deaditemstack is the head of a linked list (stack) of deallocated items */
-/*   that can be recycled.  unallocateditems is the number of items that     */
-/*   remain to be allocated from nowblock.                                   */
-/*                                                                           */
-/* Traversal is the process of walking through the entire list of items, and */
-/*   is separate from allocation.  Note that a traversal will visit items on */
-/*   the "deaditemstack" stack as well as live items.  pathblock points to   */
-/*   the block currently being traversed.  pathitem points to the next item  */
-/*   to be traversed.  pathitemsleft is the number of items that remain to   */
-/*   be traversed in pathblock.                                              */
-/*                                                                           */
-/* itemwordtype is set to POINTER or FLOATINGPOINT, and is used to suggest   */
-/*   what sort of word the record is primarily made up of.  alignbytes       */
-/*   determines how new records should be aligned in memory.  itembytes and  */
-/*   itemwords are the length of a record in bytes (after rounding up) and   */
-/*   words.  itemsperblock is the number of items allocated at once in a     */
-/*   single block.  items is the number of currently allocated items.        */
-/*   maxitems is the maximum number of items that have been allocated at     */
-/*   once; it is the current number of items plus the number of records kept */
-/*   on deaditemstack.                                                       */
-
-struct memorypool {
-  VOID **firstblock, **nowblock;
-  VOID *nextitem;
-  VOID *deaditemstack;
-  VOID **pathblock;
-  VOID *pathitem;
-  enum wordtype itemwordtype;
-  int alignbytes;
-  int itembytes, itemwords;
-  int itemsperblock;
-  long items, maxitems;
-  int unallocateditems;
-  int pathitemsleft;
-};
-
-/* Variables used to allocate memory for triangles, shell edges, points,     */
-/*   viri (triangles being eaten), bad (encroached) segments, bad (skinny    */
-/*   or too large) triangles, and splay tree nodes.                          */
-
-static struct memorypool triangles;
-static struct memorypool shelles;
-static struct memorypool points;
-static struct memorypool viri;
-static struct memorypool badsegments;
-static struct memorypool badtriangles;
-static struct memorypool splaynodes;
-
-/* Variables that maintain the bad triangle queues.  The tails are pointers  */
-/*   to the pointers that have to be filled in to enqueue an item.           */
-
-static struct badface *queuefront[64];
-static struct badface **queuetail[64];
-
-static REAL xmin, xmax, ymin, ymax;                              /* x and y bounds. */
-static REAL xminextreme;        /* Nonexistent x value used as a flag in sweepline. */
-static int inpoints;                                     /* Number of input points. */
-static int inelements;                                /* Number of input triangles. */
-static int insegments;                                 /* Number of input segments. */
-static int holes;                                         /* Number of input holes. */
-static int regions;                                     /* Number of input regions. */
-static long edges;                                       /* Number of output edges. */
-static int mesh_dim;                                  /* Dimension (ought to be 2). */
-static int nextras;                              /* Number of attributes per point. */
-static int eextras;                           /* Number of attributes per triangle. */
-static long hullsize;                            /* Number of edges of convex hull. */
-static int triwords;                                   /* Total words per triangle. */
-static int shwords;                                  /* Total words per shell edge. */
-static int pointmarkindex;             /* Index to find boundary marker of a point. */
-static int point2triindex;         /* Index to find a triangle adjacent to a point. */
-static int highorderindex;    /* Index to find extra nodes for high-order elements. */
-static int elemattribindex;              /* Index to find attributes of a triangle. */
-static int areaboundindex;               /* Index to find area bound of a triangle. */
-static int checksegments;           /* Are there segments in the triangulation yet? */
-static int readnodefile;                             /* Has a .node file been read? */
-static long samples;                /* Number of random samples for point location. */
-static unsigned long randomseed;                     /* Current random number seed. */
-
-static REAL splitter;       /* Used to split REAL factors for exact multiplication. */
-static REAL epsilon;                             /* Floating-point machine epsilon. */
-static REAL resulterrbound;
-static REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
-static REAL iccerrboundA, iccerrboundB, iccerrboundC;
-
-static long incirclecount;                   /* Number of incircle tests performed. */
-static long counterclockcount;       /* Number of counterclockwise tests performed. */
-static long hyperbolacount;        /* Number of right-of-hyperbola tests performed. */
-static long circumcentercount;    /* Number of circumcenter calculations performed. */
-static long circletopcount;         /* Number of circle top calculations performed. */
-
-/* Switches for the triangulator.                                            */
-/*   poly: -p switch.  refine: -r switch.                                    */
-/*   quality: -q switch.                                                     */
-/*     minangle: minimum angle bound, specified after -q switch.             */
-/*     goodangle: cosine squared of minangle.                                */
-/*   vararea: -a switch without number.                                      */
-/*   fixedarea: -a switch with number.                                       */
-/*     maxarea: maximum area bound, specified after -a switch.               */
-/*   regionattrib: -A switch.  convex: -c switch.                            */
-/*   firstnumber: inverse of -z switch.  All items are numbered starting     */
-/*     from firstnumber.                                                     */
-/*   edgesout: -e switch.  voronoi: -v switch.                               */
-/*   neighbors: -n switch.  geomview: -g switch.                             */
-/*   nobound: -B switch.  nopolywritten: -P switch.                          */
-/*   nonodewritten: -N switch.  noelewritten: -E switch.                     */
-/*   noiterationnum: -I switch.  noholes: -O switch.                         */
-/*   noexact: -X switch.                                                     */
-/*   order: element order, specified after -o switch.                        */
-/*   nobisect: count of how often -Y switch is selected.                     */
-/*   steiner: maximum number of Steiner points, specified after -S switch.   */
-/*     steinerleft: number of Steiner points not yet used.                   */
-/*   incremental: -i switch.  sweepline: -F switch.                          */
-/*   dwyer: inverse of -l switch.                                            */
-/*   splitseg: -s switch.                                                    */
-/*   docheck: -C switch.                                                     */
-/*   quiet: -Q switch.  verbose: count of how often -V switch is selected.   */
-/*   useshelles: -p, -r, -q, or -c switch; determines whether shell edges    */
-/*     are used at all.                                                      */
-/*                                                                           */
-/* Read the instructions to find out the meaning of these switches.          */
-
-static int poly, refine, quality, vararea, fixedarea, regionattrib, convex;
-static int firstnumber;
-static int edgesout, voronoi, neighbors, geomview;
-static int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
-static int noholes, noexact;
-static int incremental, sweepline, dwyer;
-static int splitseg;
-static int docheck;
-static int quiet, verbose;
-static int useshelles;
-static int order;
-static int nobisect;
-static int steiner, steinerleft;
-static REAL minangle, goodangle;
-static REAL maxarea;
-
-/* Variables for file names.                                                 */
-
-#ifndef TRILIBRARY
-char innodefilename[FILENAMESIZE];
-char inelefilename[FILENAMESIZE];
-char inpolyfilename[FILENAMESIZE];
-char areafilename[FILENAMESIZE];
-char outnodefilename[FILENAMESIZE];
-char outelefilename[FILENAMESIZE];
-char outpolyfilename[FILENAMESIZE];
-char edgefilename[FILENAMESIZE];
-char vnodefilename[FILENAMESIZE];
-char vedgefilename[FILENAMESIZE];
-char neighborfilename[FILENAMESIZE];
-char offfilename[FILENAMESIZE];
-#endif /* not TRILIBRARY */
-
-/* Triangular bounding box points.                                           */
-
-static point infpoint1, infpoint2, infpoint3;
-
-/* Pointer to the `triangle' that occupies all of "outer space".             */
-
-static triangle *dummytri;
-static triangle *dummytribase;      /* Keep base address so we can free() it later. */
-
-/* Pointer to the omnipresent shell edge.  Referenced by any triangle or     */
-/*   shell edge that isn't really connected to a shell edge at that          */
-/*   location.                                                               */
-
-static shelle *dummysh;
-static shelle *dummyshbase;         /* Keep base address so we can free() it later. */
-
-/* Pointer to a recently visited triangle.  Improves point location if       */
-/*   proximate points are inserted sequentially.                             */
-
-static struct triedge recenttri;
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Mesh manipulation primitives.  Each triangle contains three pointers to  */
-/*  other triangles, with orientations.  Each pointer points not to the      */
-/*  first byte of a triangle, but to one of the first three bytes of a       */
-/*  triangle.  It is necessary to extract both the triangle itself and the   */
-/*  orientation.  To save memory, I keep both pieces of information in one   */
-/*  pointer.  To make this possible, I assume that all triangles are aligned */
-/*  to four-byte boundaries.  The `decode' routine below decodes a pointer,  */
-/*  extracting an orientation (in the range 0 to 2) and a pointer to the     */
-/*  beginning of a triangle.  The `encode' routine compresses a pointer to a */
-/*  triangle and an orientation into a single pointer.  My assumptions that  */
-/*  triangles are four-byte-aligned and that the `unsigned long' type is     */
-/*  long enough to hold a pointer are two of the few kludges in this program.*/
-/*                                                                           */
-/*  Shell edges are manipulated similarly.  A pointer to a shell edge        */
-/*  carries both an address and an orientation in the range 0 to 1.          */
-/*                                                                           */
-/*  The other primitives take an oriented triangle or oriented shell edge,   */
-/*  and return an oriented triangle or oriented shell edge or point; or they */
-/*  change the connections in the data structure.                            */
-/*                                                                           */
-/*****************************************************************************/
-
-/********* Mesh manipulation primitives begin here                   *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/* Fast lookup arrays to speed some of the mesh manipulation primitives.     */
-
-int plus1mod3[3] = {1, 2, 0};
-int minus1mod3[3] = {2, 0, 1};
-
-/********* Primitives for triangles                                  *********/
-/*                                                                           */
-/*                                                                           */
-
-/* decode() converts a pointer to an oriented triangle.  The orientation is  */
-/*   extracted from the two least significant bits of the pointer.           */
-
-#define decode(ptr, triedge)                                                  \
-  (triedge).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l);      \
-  (triedge).tri = (triangle *)                                                \
-                  ((unsigned long) (ptr) ^ (unsigned long) (triedge).orient)
-
-/* encode() compresses an oriented triangle into a single pointer.  It       */
-/*   relies on the assumption that all triangles are aligned to four-byte    */
-/*   boundaries, so the two least significant bits of (triedge).tri are zero.*/
-
-#define encode(triedge)                                                       \
-  (triangle) ((unsigned long) (triedge).tri | (unsigned long) (triedge).orient)
-
-/* The following edge manipulation primitives are all described by Guibas    */
-/*   and Stolfi.  However, they use an edge-based data structure, whereas I  */
-/*   am using a triangle-based data structure.                               */
-
-/* sym() finds the abutting triangle, on the same edge.  Note that the       */
-/*   edge direction is necessarily reversed, because triangle/edge handles   */
-/*   are always directed counterclockwise around the triangle.               */
-
-#define sym(triedge1, triedge2)                                               \
-  ptr = (triedge1).tri[(triedge1).orient];                                    \
-  decode(ptr, triedge2);
-
-#define symself(triedge)                                                      \
-  ptr = (triedge).tri[(triedge).orient];                                      \
-  decode(ptr, triedge);
-
-/* lnext() finds the next edge (counterclockwise) of a triangle.             */
-
-#define lnext(triedge1, triedge2)                                             \
-  (triedge2).tri = (triedge1).tri;                                            \
-  (triedge2).orient = plus1mod3[(triedge1).orient]
-
-#define lnextself(triedge)                                                    \
-  (triedge).orient = plus1mod3[(triedge).orient]
-
-/* lprev() finds the previous edge (clockwise) of a triangle.                */
-
-#define lprev(triedge1, triedge2)                                             \
-  (triedge2).tri = (triedge1).tri;                                            \
-  (triedge2).orient = minus1mod3[(triedge1).orient]
-
-#define lprevself(triedge)                                                    \
-  (triedge).orient = minus1mod3[(triedge).orient]
-
-/* onext() spins counterclockwise around a point; that is, it finds the next */
-/*   edge with the same origin in the counterclockwise direction.  This edge */
-/*   will be part of a different triangle.                                   */
-
-#define onext(triedge1, triedge2)                                             \
-  lprev(triedge1, triedge2);                                                  \
-  symself(triedge2);
-
-#define onextself(triedge)                                                    \
-  lprevself(triedge);                                                         \
-  symself(triedge);
-
-/* oprev() spins clockwise around a point; that is, it finds the next edge   */
-/*   with the same origin in the clockwise direction.  This edge will be     */
-/*   part of a different triangle.                                           */
-
-#define oprev(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lnextself(triedge2);
-
-#define oprevself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lnextself(triedge);
-
-/* dnext() spins counterclockwise around a point; that is, it finds the next */
-/*   edge with the same destination in the counterclockwise direction.  This */
-/*   edge will be part of a different triangle.                              */
-
-#define dnext(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lprevself(triedge2);
-
-#define dnextself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lprevself(triedge);
-
-/* dprev() spins clockwise around a point; that is, it finds the next edge   */
-/*   with the same destination in the clockwise direction.  This edge will   */
-/*   be part of a different triangle.                                        */
-
-#define dprev(triedge1, triedge2)                                             \
-  lnext(triedge1, triedge2);                                                  \
-  symself(triedge2);
-
-#define dprevself(triedge)                                                    \
-  lnextself(triedge);                                                         \
-  symself(triedge);
-
-/* rnext() moves one edge counterclockwise about the adjacent triangle.      */
-/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
-/*   changing triangles twice.)                                              */
-
-#define rnext(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lnextself(triedge2);                                                        \
-  symself(triedge2);
-
-#define rnextself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lnextself(triedge);                                                         \
-  symself(triedge);
-
-/* rnext() moves one edge clockwise about the adjacent triangle.             */
-/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
-/*   changing triangles twice.)                                              */
-
-#define rprev(triedge1, triedge2)                                             \
-  sym(triedge1, triedge2);                                                    \
-  lprevself(triedge2);                                                        \
-  symself(triedge2);
-
-#define rprevself(triedge)                                                    \
-  symself(triedge);                                                           \
-  lprevself(triedge);                                                         \
-  symself(triedge);
-
-/* These primitives determine or set the origin, destination, or apex of a   */
-/* triangle.                                                                 */
-
-#define org(triedge, pointptr)                                                \
-  pointptr = (point) (triedge).tri[plus1mod3[(triedge).orient] + 3]
-
-#define dest(triedge, pointptr)                                               \
-  pointptr = (point) (triedge).tri[minus1mod3[(triedge).orient] + 3]
-
-#define apex(triedge, pointptr)                                               \
-  pointptr = (point) (triedge).tri[(triedge).orient + 3]
-
-#define setorg(triedge, pointptr)                                             \
-  (triedge).tri[plus1mod3[(triedge).orient] + 3] = (triangle) pointptr
-
-#define setdest(triedge, pointptr)                                            \
-  (triedge).tri[minus1mod3[(triedge).orient] + 3] = (triangle) pointptr
-
-#define setapex(triedge, pointptr)                                            \
-  (triedge).tri[(triedge).orient + 3] = (triangle) pointptr
-
-#define setvertices2null(triedge)                                             \
-  (triedge).tri[3] = (triangle) NULL;                                         \
-  (triedge).tri[4] = (triangle) NULL;                                         \
-  (triedge).tri[5] = (triangle) NULL;
-
-/* Bond two triangles together.                                              */
-
-#define bond(triedge1, triedge2)                                              \
-  (triedge1).tri[(triedge1).orient] = encode(triedge2);                       \
-  (triedge2).tri[(triedge2).orient] = encode(triedge1)
-
-/* Dissolve a bond (from one side).  Note that the other triangle will still */
-/*   think it's connected to this triangle.  Usually, however, the other     */
-/*   triangle is being deleted entirely, or bonded to another triangle, so   */
-/*   it doesn't matter.                                                      */
-
-#define dissolve(triedge)                                                     \
-  (triedge).tri[(triedge).orient] = (triangle) dummytri
-
-/* Copy a triangle/edge handle.                                              */
-
-#define triedgecopy(triedge1, triedge2)                                       \
-  (triedge2).tri = (triedge1).tri;                                            \
-  (triedge2).orient = (triedge1).orient
-
-/* Test for equality of triangle/edge handles.                               */
-
-#define triedgeequal(triedge1, triedge2)                                      \
-  (((triedge1).tri == (triedge2).tri) &&                                      \
-   ((triedge1).orient == (triedge2).orient))
-
-/* Primitives to infect or cure a triangle with the virus.  These rely on    */
-/*   the assumption that all shell edges are aligned to four-byte boundaries.*/
-
-#define infect(triedge)                                                       \
-  (triedge).tri[6] = (triangle)                                               \
-                     ((unsigned long) (triedge).tri[6] | (unsigned long) 2l)
-
-#define uninfect(triedge)                                                     \
-  (triedge).tri[6] = (triangle)                                               \
-                     ((unsigned long) (triedge).tri[6] & ~ (unsigned long) 2l)
-
-/* Test a triangle for viral infection.                                      */
-
-#define infected(triedge)                                                     \
-  (((unsigned long) (triedge).tri[6] & (unsigned long) 2l) != 0)
-
-/* Check or set a triangle's attributes.                                     */
-
-#define elemattribute(triedge, attnum)                                        \
-  ((REAL *) (triedge).tri)[elemattribindex + (attnum)]
-
-#define setelemattribute(triedge, attnum, value)                              \
-  ((REAL *) (triedge).tri)[elemattribindex + (attnum)] = (REAL)value
-
-/* Check or set a triangle's maximum area bound.                             */
-
-#define areabound(triedge)  ((REAL *) (triedge).tri)[areaboundindex]
-
-#define setareabound(triedge, value)                                          \
-  ((REAL *) (triedge).tri)[areaboundindex] = (REAL)value
-
-/********* Primitives for shell edges                                *********/
-/*                                                                           */
-/*                                                                           */
-
-/* sdecode() converts a pointer to an oriented shell edge.  The orientation  */
-/*   is extracted from the least significant bit of the pointer.  The two    */
-/*   least significant bits (one for orientation, one for viral infection)   */
-/*   are masked out to produce the real pointer.                             */
-
-#define sdecode(sptr, edge)                                                   \
-  (edge).shorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l);      \
-  (edge).sh = (shelle *)                                                      \
-              ((unsigned long) (sptr) & ~ (unsigned long) 3l)
-
-/* sencode() compresses an oriented shell edge into a single pointer.  It    */
-/*   relies on the assumption that all shell edges are aligned to two-byte   */
-/*   boundaries, so the least significant bit of (edge).sh is zero.          */
-
-#define sencode(edge)                                                         \
-  (shelle) ((unsigned long) (edge).sh | (unsigned long) (edge).shorient)
-
-/* ssym() toggles the orientation of a shell edge.                           */
-
-#define ssym(edge1, edge2)                                                    \
-  (edge2).sh = (edge1).sh;                                                    \
-  (edge2).shorient = 1 - (edge1).shorient
-
-#define ssymself(edge)                                                        \
-  (edge).shorient = 1 - (edge).shorient
-
-/* spivot() finds the other shell edge (from the same segment) that shares   */
-/*   the same origin.                                                        */
-
-#define spivot(edge1, edge2)                                                  \
-  sptr = (edge1).sh[(edge1).shorient];                                        \
-  sdecode(sptr, edge2)
-
-#define spivotself(edge)                                                      \
-  sptr = (edge).sh[(edge).shorient];                                          \
-  sdecode(sptr, edge)
-
-/* snext() finds the next shell edge (from the same segment) in sequence;    */
-/*   one whose origin is the input shell edge's destination.                 */
-
-#define snext(edge1, edge2)                                                   \
-  sptr = (edge1).sh[1 - (edge1).shorient];                                    \
-  sdecode(sptr, edge2)
-
-#define snextself(edge)                                                       \
-  sptr = (edge).sh[1 - (edge).shorient];                                      \
-  sdecode(sptr, edge)
-
-/* These primitives determine or set the origin or destination of a shell    */
-/*   edge.                                                                   */
-
-#define sorg(edge, pointptr)                                                  \
-  pointptr = (point) (edge).sh[2 + (edge).shorient]
-
-#define sdest(edge, pointptr)                                                 \
-  pointptr = (point) (edge).sh[3 - (edge).shorient]
-
-#define setsorg(edge, pointptr)                                               \
-  (edge).sh[2 + (edge).shorient] = (shelle) pointptr
-
-#define setsdest(edge, pointptr)                                              \
-  (edge).sh[3 - (edge).shorient] = (shelle) pointptr
-
-/* These primitives read or set a shell marker.  Shell markers are used to   */
-/*   hold user boundary information.                                         */
-
-#define mark(edge)  (* (int *) ((edge).sh + 6))
-
-#define setmark(edge, value)                                                  \
-  * (int *) ((edge).sh + 6) = value
-
-/* Bond two shell edges together.                                            */
-
-#define sbond(edge1, edge2)                                                   \
-  (edge1).sh[(edge1).shorient] = sencode(edge2);                              \
-  (edge2).sh[(edge2).shorient] = sencode(edge1)
-
-/* Dissolve a shell edge bond (from one side).  Note that the other shell    */
-/*   edge will still think it's connected to this shell edge.                */
-
-#define sdissolve(edge)                                                       \
-  (edge).sh[(edge).shorient] = (shelle) dummysh
-
-/* Copy a shell edge.                                                        */
-
-#define shellecopy(edge1, edge2)                                              \
-  (edge2).sh = (edge1).sh;                                                    \
-  (edge2).shorient = (edge1).shorient
-
-/* Test for equality of shell edges.                                         */
-
-#define shelleequal(edge1, edge2)                                             \
-  (((edge1).sh == (edge2).sh) &&                                              \
-   ((edge1).shorient == (edge2).shorient))
-
-/********* Primitives for interacting triangles and shell edges      *********/
-/*                                                                           */
-/*                                                                           */
-
-/* tspivot() finds a shell edge abutting a triangle.                         */
-
-#define tspivot(triedge, edge)                                                \
-  sptr = (shelle) (triedge).tri[6 + (triedge).orient];                        \
-  sdecode(sptr, edge)
-
-/* stpivot() finds a triangle abutting a shell edge.  It requires that the   */
-/*   variable `ptr' of type `triangle' be defined.                           */
-
-#define stpivot(edge, triedge)                                                \
-  ptr = (triangle) (edge).sh[4 + (edge).shorient];                            \
-  decode(ptr, triedge)
-
-/* Bond a triangle to a shell edge.                                          */
-
-#define tsbond(triedge, edge)                                                 \
-  (triedge).tri[6 + (triedge).orient] = (triangle) sencode(edge);             \
-  (edge).sh[4 + (edge).shorient] = (shelle) encode(triedge)
-
-/* Dissolve a bond (from the triangle side).                                 */
-
-#define tsdissolve(triedge)                                                   \
-  (triedge).tri[6 + (triedge).orient] = (triangle) dummysh
-
-/* Dissolve a bond (from the shell edge side).                               */
-
-#define stdissolve(edge)                                                      \
-  (edge).sh[4 + (edge).shorient] = (shelle) dummytri
-
-/********* Primitives for points                                     *********/
-/*                                                                           */
-/*                                                                           */
-
-#define pointmark(pt)  ((int *) (pt))[pointmarkindex]
-
-#define setpointmark(pt, value)                                               \
-  ((int *) (pt))[pointmarkindex] = value
-
-#define point2tri(pt)  ((triangle *) (pt))[point2triindex]
-
-#define setpoint2tri(pt, value)                                               \
-  ((triangle *) (pt))[point2triindex] = value
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Mesh manipulation primitives end here                     *********/
-
-/********* User interaction routines begin here                      *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  syntax()   Print list of command line switches.                          */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-void syntax()
-{
-#ifdef CDT_ONLY
-#ifdef REDUCED
-  printf("triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n");
-#else /* not REDUCED */
-  printf("triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n");
-#endif /* not REDUCED */
-#else /* not CDT_ONLY */
-#ifdef REDUCED
-  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n");
-#else /* not REDUCED */
-  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
-#endif /* not REDUCED */
-#endif /* not CDT_ONLY */
-
-  printf("    -p  Triangulates a Planar Straight Line Graph (.poly file).\n");
-#ifndef CDT_ONLY
-  printf("    -r  Refines a previously generated mesh.\n");
-  printf(
-    "    -q  Quality mesh generation.  A minimum angle may be specified.\n");
-  printf("    -a  Applies a maximum triangle area constraint.\n");
-#endif /* not CDT_ONLY */
-  printf(
-    "    -A  Applies attributes to identify elements in certain regions.\n");
-  printf("    -c  Encloses the convex hull with segments.\n");
-  printf("    -e  Generates an edge list.\n");
-  printf("    -v  Generates a Voronoi diagram.\n");
-  printf("    -n  Generates a list of triangle neighbors.\n");
-  printf("    -g  Generates an .off file for Geomview.\n");
-  printf("    -B  Suppresses output of boundary information.\n");
-  printf("    -P  Suppresses output of .poly file.\n");
-  printf("    -N  Suppresses output of .node file.\n");
-  printf("    -E  Suppresses output of .ele file.\n");
-  printf("    -I  Suppresses mesh iteration numbers.\n");
-  printf("    -O  Ignores holes in .poly file.\n");
-  printf("    -X  Suppresses use of exact arithmetic.\n");
-  printf("    -z  Numbers all items starting from zero (rather than one).\n");
-  printf("    -o2 Generates second-order subparametric elements.\n");
-#ifndef CDT_ONLY
-  printf("    -Y  Suppresses boundary segment splitting.\n");
-  printf("    -S  Specifies maximum number of added Steiner points.\n");
-#endif /* not CDT_ONLY */
-#ifndef REDUCED
-  printf("    -i  Uses incremental method, rather than divide-and-conquer.\n");
-  printf("    -F  Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
-#endif /* not REDUCED */
-  printf("    -l  Uses vertical cuts only, rather than alternating cuts.\n");
-#ifndef REDUCED
-#ifndef CDT_ONLY
-  printf(
-    "    -s  Force segments into mesh by splitting (instead of using CDT).\n");
-#endif /* not CDT_ONLY */
-  printf("    -C  Check consistency of final mesh.\n");
-#endif /* not REDUCED */
-  printf("    -Q  Quiet:  No terminal output except errors.\n");
-  printf("    -V  Verbose:  Detailed information on what I'm doing.\n");
-  printf("    -h  Help:  Detailed instructions for Triangle.\n");
-  exit(0);
-}
-
-#endif /* not TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  info()   Print out complete instructions.                                */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-void info()
-{
-  printf("Triangle\n");
-  printf(
-"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
-  printf("Version 1.3\n\n");
-  printf(
-"Copyright 1996 Jonathan Richard Shewchuk  (bugs/comments to jrs@cs.cmu.edu)\n"
-);
-  printf("School of Computer Science / Carnegie Mellon University\n");
-  printf("5000 Forbes Avenue / Pittsburgh, Pennsylvania  15213-3891\n");
-  printf(
-"Created as part of the Archimedes project (tools for parallel FEM).\n");
-  printf(
-"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
-  printf("There is no warranty whatsoever.  Use at your own risk.\n");
-#ifdef SINGLE
-  printf("This executable is compiled for single precision arithmetic.\n\n\n");
-#else /* not SINGLE */
-  printf("This executable is compiled for double precision arithmetic.\n\n\n");
-#endif /* not SINGLE */
-  printf(
-"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
-  printf(
-"triangulations, and quality conforming Delaunay triangulations.  The latter\n"
-);
-  printf(
-"can be generated with no small angles, and are thus suitable for finite\n");
-  printf(
-"element analysis.  If no command line switches are specified, your .node\n");
-  printf(
-"input file will be read, and the Delaunay triangulation will be returned in\n"
-);
-  printf(".node and .ele output files.  The command syntax is:\n\n");
-#ifdef CDT_ONLY
-#ifdef REDUCED
-  printf("triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n\n");
-#else /* not REDUCED */
-  printf("triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n\n");
-#endif /* not REDUCED */
-#else /* not CDT_ONLY */
-#ifdef REDUCED
-  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n\n");
-#else /* not REDUCED */
-  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
-#endif /* not REDUCED */
-#endif /* not CDT_ONLY */
-  printf(
-"Underscores indicate that numbers may optionally follow certain switches;\n");
-  printf(
-"do not leave any space between a switch and its numeric parameter.\n");
-  printf(
-"input_file must be a file with extension .node, or extension .poly if the\n");
-  printf(
-"-p switch is used.  If -r is used, you must supply .node and .ele files,\n");
-  printf(
-"and possibly a .poly file and .area file as well.  The formats of these\n");
-  printf("files are described below.\n\n");
-  printf("Command Line Switches:\n\n");
-  printf(
-"    -p  Reads a Planar Straight Line Graph (.poly file), which can specify\n"
-);
-  printf(
-"        points, segments, holes, and regional attributes and area\n");
-  printf(
-"        constraints.  Will generate a constrained Delaunay triangulation\n");
-  printf(
-"        fitting the input; or, if -s, -q, or -a is used, a conforming\n");
-  printf(
-"        Delaunay triangulation.  If -p is not used, Triangle reads a .node\n"
-);
-  printf("        file by default.\n");
-  printf(
-"    -r  Refines a previously generated mesh.  The mesh is read from a .node\n"
-);
-  printf(
-"        file and an .ele file.  If -p is also used, a .poly file is read\n");
-  printf(
-"        and used to constrain edges in the mesh.  Further details on\n");
-  printf("        refinement are given below.\n");
-  printf(
-"    -q  Quality mesh generation by Jim Ruppert's Delaunay refinement\n");
-  printf(
-"        algorithm.  Adds points to the mesh to ensure that no angles\n");
-  printf(
-"        smaller than 20 degrees occur.  An alternative minimum angle may be\n"
-);
-  printf(
-"        specified after the `q'.  If the minimum angle is 20.7 degrees or\n");
-  printf(
-"        smaller, the triangulation algorithm is theoretically guaranteed to\n"
-);
-  printf(
-"        terminate (assuming infinite precision arithmetic - Triangle may\n");
-  printf(
-"        fail to terminate if you run out of precision).  In practice, the\n");
-  printf(
-"        algorithm often succeeds for minimum angles up to 33.8 degrees.\n");
-  printf(
-"        For highly refined meshes, however, it may be necessary to reduce\n");
-  printf(
-"        the minimum angle to well below 20 to avoid problems associated\n");
-  printf(
-"        with insufficient floating-point precision.  The specified angle\n");
-  printf("        may include a decimal point.\n");
-  printf(
-"    -a  Imposes a maximum triangle area.  If a number follows the `a', no\n");
-  printf(
-"        triangle will be generated whose area is larger than that number.\n");
-  printf(
-"        If no number is specified, an .area file (if -r is used) or .poly\n");
-  printf(
-"        file (if -r is not used) specifies a number of maximum area\n");
-  printf(
-"        constraints.  An .area file contains a separate area constraint for\n"
-);
-  printf(
-"        each triangle, and is useful for refining a finite element mesh\n");
-  printf(
-"        based on a posteriori error estimates.  A .poly file can optionally\n"
-);
-  printf(
-"        contain an area constraint for each segment-bounded region, thereby\n"
-);
-  printf(
-"        enforcing triangle densities in a first triangulation.  You can\n");
-  printf(
-"        impose both a fixed area constraint and a varying area constraint\n");
-  printf(
-"        by invoking the -a switch twice, once with and once without a\n");
-  printf(
-"        number following.  Each area specified may include a decimal point.\n"
-);
-  printf(
-"    -A  Assigns an additional attribute to each triangle that identifies\n");
-  printf(
-"        what segment-bounded region each triangle belongs to.  Attributes\n");
-  printf(
-"        are assigned to regions by the .poly file.  If a region is not\n");
-  printf(
-"        explicitly marked by the .poly file, triangles in that region are\n");
-  printf(
-"        assigned an attribute of zero.  The -A switch has an effect only\n");
-  printf("        when the -p switch is used and the -r switch is not.\n");
-  printf(
-"    -c  Creates segments on the convex hull of the triangulation.  If you\n");
-  printf(
-"        are triangulating a point set, this switch causes a .poly file to\n");
-  printf(
-"        be written, containing all edges in the convex hull.  (By default,\n"
-);
-  printf(
-"        a .poly file is written only if a .poly file is read.)  If you are\n"
-);
-  printf(
-"        triangulating a PSLG, this switch specifies that the interior of\n");
-  printf(
-"        the convex hull of the PSLG should be triangulated.  If you do not\n"
-);
-  printf(
-"        use this switch when triangulating a PSLG, it is assumed that you\n");
-  printf(
-"        have identified the region to be triangulated by surrounding it\n");
-  printf(
-"        with segments of the input PSLG.  Beware:  if you are not careful,\n"
-);
-  printf(
-"        this switch can cause the introduction of an extremely thin angle\n");
-  printf(
-"        between a PSLG segment and a convex hull segment, which can cause\n");
-  printf(
-"        overrefinement or failure if Triangle runs out of precision.  If\n");
-  printf(
-"        you are refining a mesh, the -c switch works differently; it\n");
-  printf(
-"        generates the set of boundary edges of the mesh, rather than the\n");
-  printf("        convex hull.\n");
-  printf(
-"    -e  Outputs (to an .edge file) a list of edges of the triangulation.\n");
-  printf(
-"    -v  Outputs the Voronoi diagram associated with the triangulation.\n");
-  printf("        Does not attempt to detect degeneracies.\n");
-  printf(
-"    -n  Outputs (to a .neigh file) a list of triangles neighboring each\n");
-  printf("        triangle.\n");
-  printf(
-"    -g  Outputs the mesh to an Object File Format (.off) file, suitable for\n"
-);
-  printf("        viewing with the Geometry Center's Geomview package.\n");
-  printf(
-"    -B  No boundary markers in the output .node, .poly, and .edge output\n");
-  printf(
-"        files.  See the detailed discussion of boundary markers below.\n");
-  printf(
-"    -P  No output .poly file.  Saves disk space, but you lose the ability\n");
-  printf(
-"        to impose segment constraints on later refinements of the mesh.\n");
-  printf("    -N  No output .node file.\n");
-  printf("    -E  No output .ele file.\n");
-  printf(
-"    -I  No iteration numbers.  Suppresses the output of .node and .poly\n");
-  printf(
-"        files, so your input files won't be overwritten.  (If your input is\n"
-);
-  printf(
-"        a .poly file only, a .node file will be written.)  Cannot be used\n");
-  printf(
-"        with the -r switch, because that would overwrite your input .ele\n");
-  printf(
-"        file.  Shouldn't be used with the -s, -q, or -a switch if you are\n");
-  printf(
-"        using a .node file for input, because no .node file will be\n");
-  printf("        written, so there will be no record of any added points.\n");
-  printf("    -O  No holes.  Ignores the holes in the .poly file.\n");
-  printf(
-"    -X  No exact arithmetic.  Normally, Triangle uses exact floating-point\n"
-);
-  printf(
-"        arithmetic for certain tests if it thinks the inexact tests are not\n"
-);
-  printf(
-"        accurate enough.  Exact arithmetic ensures the robustness of the\n");
-  printf(
-"        triangulation algorithms, despite floating-point roundoff error.\n");
-  printf(
-"        Disabling exact arithmetic with the -X switch will cause a small\n");
-  printf(
-"        improvement in speed and create the possibility (albeit small) that\n"
-);
-  printf(
-"        Triangle will fail to produce a valid mesh.  Not recommended.\n");
-  printf(
-"    -z  Numbers all items starting from zero (rather than one).  Note that\n"
-);
-  printf(
-"        this switch is normally overrided by the value used to number the\n");
-  printf(
-"        first point of the input .node or .poly file.  However, this switch\n"
-);
-  printf("        is useful when calling Triangle from another program.\n");
-  printf(
-"    -o2 Generates second-order subparametric elements with six nodes each.\n"
-);
-  printf(
-"    -Y  No new points on the boundary.  This switch is useful when the mesh\n"
-);
-  printf(
-"        boundary must be preserved so that it conforms to some adjacent\n");
-  printf(
-"        mesh.  Be forewarned that you will probably sacrifice some of the\n");
-  printf(
-"        quality of the mesh; Triangle will try, but the resulting mesh may\n"
-);
-  printf(
-"        contain triangles of poor aspect ratio.  Works well if all the\n");
-  printf(
-"        boundary points are closely spaced.  Specify this switch twice\n");
-  printf(
-"        (`-YY') to prevent all segment splitting, including internal\n");
-  printf("        boundaries.\n");
-  printf(
-"    -S  Specifies the maximum number of Steiner points (points that are not\n"
-);
-  printf(
-"        in the input, but are added to meet the constraints of minimum\n");
-  printf(
-"        angle and maximum area).  The default is to allow an unlimited\n");
-  printf(
-"        number.  If you specify this switch with no number after it,\n");
-  printf(
-"        the limit is set to zero.  Triangle always adds points at segment\n");
-  printf(
-"        intersections, even if it needs to use more points than the limit\n");
-  printf(
-"        you set.  When Triangle inserts segments by splitting (-s), it\n");
-  printf(
-"        always adds enough points to ensure that all the segments appear in\n"
-);
-  printf(
-"        the triangulation, again ignoring the limit.  Be forewarned that\n");
-  printf(
-"        the -S switch may result in a conforming triangulation that is not\n"
-);
-  printf(
-"        truly Delaunay, because Triangle may be forced to stop adding\n");
-  printf(
-"        points when the mesh is in a state where a segment is non-Delaunay\n"
-);
-  printf(
-"        and needs to be split.  If so, Triangle will print a warning.\n");
-  printf(
-"    -i  Uses an incremental rather than divide-and-conquer algorithm to\n");
-  printf(
-"        form a Delaunay triangulation.  Try it if the divide-and-conquer\n");
-  printf("        algorithm fails.\n");
-  printf(
-"    -F  Uses Steven Fortune's sweepline algorithm to form a Delaunay\n");
-  printf(
-"        triangulation.  Warning:  does not use exact arithmetic for all\n");
-  printf("        calculations.  An exact result is not guaranteed.\n");
-  printf(
-"    -l  Uses only vertical cuts in the divide-and-conquer algorithm.  By\n");
-  printf(
-"        default, Triangle uses alternating vertical and horizontal cuts,\n");
-  printf(
-"        which usually improve the speed except with point sets that are\n");
-  printf(
-"        small or short and wide.  This switch is primarily of theoretical\n");
-  printf("        interest.\n");
-  printf(
-"    -s  Specifies that segments should be forced into the triangulation by\n"
-);
-  printf(
-"        recursively splitting them at their midpoints, rather than by\n");
-  printf(
-"        generating a constrained Delaunay triangulation.  Segment splitting\n"
-);
-  printf(
-"        is true to Ruppert's original algorithm, but can create needlessly\n"
-);
-  printf("        small triangles near external small features.\n");
-  printf(
-"    -C  Check the consistency of the final mesh.  Uses exact arithmetic for\n"
-);
-  printf(
-"        checking, even if the -X switch is used.  Useful if you suspect\n");
-  printf("        Triangle is buggy.\n");
-  printf(
-"    -Q  Quiet: Suppresses all explanation of what Triangle is doing, unless\n"
-);
-  printf("        an error occurs.\n");
-  printf(
-"    -V  Verbose: Gives detailed information about what Triangle is doing.\n");
-  printf(
-"        Add more `V's for increasing amount of detail.  `-V' gives\n");
-  printf(
-"        information on algorithmic progress and more detailed statistics.\n");
-  printf(
-"        `-VV' gives point-by-point details, and will print so much that\n");
-  printf(
-"        Triangle will run much more slowly.  `-VVV' gives information only\n"
-);
-  printf("        a debugger could love.\n");
-  printf("    -h  Help:  Displays these instructions.\n");
-  printf("\n");
-  printf("Definitions:\n");
-  printf("\n");
-  printf(
-"  A Delaunay triangulation of a point set is a triangulation whose vertices\n"
-);
-  printf(
-"  are the point set, having the property that no point in the point set\n");
-  printf(
-"  falls in the interior of the circumcircle (circle that passes through all\n"
-);
-  printf("  three vertices) of any triangle in the triangulation.\n\n");
-  printf(
-"  A Voronoi diagram of a point set is a subdivision of the plane into\n");
-  printf(
-"  polygonal regions (some of which may be infinite), where each region is\n");
-  printf(
-"  the set of points in the plane that are closer to some input point than\n");
-  printf(
-"  to any other input point.  (The Voronoi diagram is the geometric dual of\n"
-);
-  printf("  the Delaunay triangulation.)\n\n");
-  printf(
-"  A Planar Straight Line Graph (PSLG) is a collection of points and\n");
-  printf(
-"  segments.  Segments are simply edges, whose endpoints are points in the\n");
-  printf(
-"  PSLG.  The file format for PSLGs (.poly files) is described below.\n");
-  printf("\n");
-  printf(
-"  A constrained Delaunay triangulation of a PSLG is similar to a Delaunay\n");
-  printf(
-"  triangulation, but each PSLG segment is present as a single edge in the\n");
-  printf(
-"  triangulation.  (A constrained Delaunay triangulation is not truly a\n");
-  printf("  Delaunay triangulation.)\n\n");
-  printf(
-"  A conforming Delaunay triangulation of a PSLG is a true Delaunay\n");
-  printf(
-"  triangulation in which each PSLG segment may have been subdivided into\n");
-  printf(
-"  several edges by the insertion of additional points.  These inserted\n");
-  printf(
-"  points are necessary to allow the segments to exist in the mesh while\n");
-  printf("  maintaining the Delaunay property.\n\n");
-  printf("File Formats:\n\n");
-  printf(
-"  All files may contain comments prefixed by the character '#'.  Points,\n");
-  printf(
-"  triangles, edges, holes, and maximum area constraints must be numbered\n");
-  printf(
-"  consecutively, starting from either 1 or 0.  Whichever you choose, all\n");
-  printf(
-"  input files must be consistent; if the nodes are numbered from 1, so must\n"
-);
-  printf(
-"  be all other objects.  Triangle automatically detects your choice while\n");
-  printf(
-"  reading the .node (or .poly) file.  (When calling Triangle from another\n");
-  printf(
-"  program, use the -z switch if you wish to number objects from zero.)\n");
-  printf("  Examples of these file formats are given below.\n\n");
-  printf("  .node files:\n");
-  printf(
-"    First line:  <# of points> <dimension (must be 2)> <# of attributes>\n");
-  printf(
-"                                           <# of boundary markers (0 or 1)>\n"
-);
-  printf(
-"    Remaining lines:  <point #> <x> <y> [attributes] [boundary marker]\n");
-  printf("\n");
-  printf(
-"    The attributes, which are typically floating-point values of physical\n");
-  printf(
-"    quantities (such as mass or conductivity) associated with the nodes of\n"
-);
-  printf(
-"    a finite element mesh, are copied unchanged to the output mesh.  If -s,\n"
-);
-  printf(
-"    -q, or -a is selected, each new Steiner point added to the mesh will\n");
-  printf("    have attributes assigned to it by linear interpolation.\n\n");
-  printf(
-"    If the fourth entry of the first line is `1', the last column of the\n");
-  printf(
-"    remainder of the file is assumed to contain boundary markers.  Boundary\n"
-);
-  printf(
-"    markers are used to identify boundary points and points resting on PSLG\n"
-);
-  printf(
-"    segments; a complete description appears in a section below.  The .node\n"
-);
-  printf(
-"    file produced by Triangle will contain boundary markers in the last\n");
-  printf("    column unless they are suppressed by the -B switch.\n\n");
-  printf("  .ele files:\n");
-  printf(
-"    First line:  <# of triangles> <points per triangle> <# of attributes>\n");
-  printf(
-"    Remaining lines:  <triangle #> <point> <point> <point> ... [attributes]\n"
-);
-  printf("\n");
-  printf(
-"    Points are indices into the corresponding .node file.  The first three\n"
-);
-  printf(
-"    points are the corners, and are listed in counterclockwise order around\n"
-);
-  printf(
-"    each triangle.  (The remaining points, if any, depend on the type of\n");
-  printf(
-"    finite element used.)  The attributes are just like those of .node\n");
-  printf(
-"    files.  Because there is no simple mapping from input to output\n");
-  printf(
-"    triangles, an attempt is made to interpolate attributes, which may\n");
-  printf(
-"    result in a good deal of diffusion of attributes among nearby triangles\n"
-);
-  printf(
-"    as the triangulation is refined.  Diffusion does not occur across\n");
-  printf(
-"    segments, so attributes used to identify segment-bounded regions remain\n"
-);
-  printf(
-"    intact.  In output .ele files, all triangles have three points each\n");
-  printf(
-"    unless the -o2 switch is used, in which case they have six, and the\n");
-  printf(
-"    fourth, fifth, and sixth points lie on the midpoints of the edges\n");
-  printf("    opposite the first, second, and third corners.\n\n");
-  printf("  .poly files:\n");
-  printf(
-"    First line:  <# of points> <dimension (must be 2)> <# of attributes>\n");
-  printf(
-"                                           <# of boundary markers (0 or 1)>\n"
-);
-  printf(
-"    Following lines:  <point #> <x> <y> [attributes] [boundary marker]\n");
-  printf("    One line:  <# of segments> <# of boundary markers (0 or 1)>\n");
-  printf(
-"    Following lines:  <segment #> <endpoint> <endpoint> [boundary marker]\n");
-  printf("    One line:  <# of holes>\n");
-  printf("    Following lines:  <hole #> <x> <y>\n");
-  printf(
-"    Optional line:  <# of regional attributes and/or area constraints>\n");
-  printf(
-"    Optional following lines:  <constraint #> <x> <y> <attrib> <max area>\n");
-  printf("\n");
-  printf(
-"    A .poly file represents a PSLG, as well as some additional information.\n"
-);
-  printf(
-"    The first section lists all the points, and is identical to the format\n"
-);
-  printf(
-"    of .node files.  <# of points> may be set to zero to indicate that the\n"
-);
-  printf(
-"    points are listed in a separate .node file; .poly files produced by\n");
-  printf(
-"    Triangle always have this format.  This has the advantage that a point\n"
-);
-  printf(
-"    set may easily be triangulated with or without segments.  (The same\n");
-  printf(
-"    effect can be achieved, albeit using more disk space, by making a copy\n"
-);
-  printf(
-"    of the .poly file with the extension .node; all sections of the file\n");
-  printf("    but the first are ignored.)\n\n");
-  printf(
-"    The second section lists the segments.  Segments are edges whose\n");
-  printf(
-"    presence in the triangulation is enforced.  Each segment is specified\n");
-  printf(
-"    by listing the indices of its two endpoints.  This means that you must\n"
-);
-  printf(
-"    include its endpoints in the point list.  If -s, -q, and -a are not\n");
-  printf(
-"    selected, Triangle will produce a constrained Delaunay triangulation,\n");
-  printf(
-"    in which each segment appears as a single edge in the triangulation.\n");
-  printf(
-"    If -q or -a is selected, Triangle will produce a conforming Delaunay\n");
-  printf(
-"    triangulation, in which segments may be subdivided into smaller edges.\n"
-);
-  printf("    Each segment, like each point, may have a boundary marker.\n\n");
-  printf(
-"    The third section lists holes (and concavities, if -c is selected) in\n");
-  printf(
-"    the triangulation.  Holes are specified by identifying a point inside\n");
-  printf(
-"    each hole.  After the triangulation is formed, Triangle creates holes\n");
-  printf(
-"    by eating triangles, spreading out from each hole point until its\n");
-  printf(
-"    progress is blocked by PSLG segments; you must be careful to enclose\n");
-  printf(
-"    each hole in segments, or your whole triangulation may be eaten away.\n");
-  printf(
-"    If the two triangles abutting a segment are eaten, the segment itself\n");
-  printf(
-"    is also eaten.  Do not place a hole directly on a segment; if you do,\n");
-  printf("    Triangle will choose one side of the segment arbitrarily.\n\n");
-  printf(
-"    The optional fourth section lists regional attributes (to be assigned\n");
-  printf(
-"    to all triangles in a region) and regional constraints on the maximum\n");
-  printf(
-"    triangle area.  Triangle will read this section only if the -A switch\n");
-  printf(
-"    is used or the -a switch is used without a number following it, and the\n"
-);
-  printf(
-"    -r switch is not used.  Regional attributes and area constraints are\n");
-  printf(
-"    propagated in the same manner as holes; you specify a point for each\n");
-  printf(
-"    attribute and/or constraint, and the attribute and/or constraint will\n");
-  printf(
-"    affect the whole region (bounded by segments) containing the point.  If\n"
-);
-  printf(
-"    two values are written on a line after the x and y coordinate, the\n");
-  printf(
-"    former is assumed to be a regional attribute (but will only be applied\n"
-);
-  printf(
-"    if the -A switch is selected), and the latter is assumed to be a\n");
-  printf(
-"    regional area constraint (but will only be applied if the -a switch is\n"
-);
-  printf(
-"    selected).  You may also specify just one value after the coordinates,\n"
-);
-  printf(
-"    which can serve as both an attribute and an area constraint, depending\n"
-);
-  printf(
-"    on the choice of switches.  If you are using the -A and -a switches\n");
-  printf(
-"    simultaneously and wish to assign an attribute to some region without\n");
-  printf("    imposing an area constraint, use a negative maximum area.\n\n");
-  printf(
-"    When a triangulation is created from a .poly file, you must either\n");
-  printf(
-"    enclose the entire region to be triangulated in PSLG segments, or\n");
-  printf(
-"    use the -c switch, which encloses the convex hull of the input point\n");
-  printf(
-"    set.  If you do not use the -c switch, Triangle will eat all triangles\n"
-);
-  printf(
-"    on the outer boundary that are not protected by segments; if you are\n");
-  printf(
-"    not careful, your whole triangulation may be eaten away.  If you do\n");
-  printf(
-"    use the -c switch, you can still produce concavities by appropriate\n");
-  printf("    placement of holes just inside the convex hull.\n\n");
-  printf(
-"    An ideal PSLG has no intersecting segments, nor any points that lie\n");
-  printf(
-"    upon segments (except, of course, the endpoints of each segment.)  You\n"
-);
-  printf(
-"    aren't required to make your .poly files ideal, but you should be aware\n"
-);
-  printf(
-"    of what can go wrong.  Segment intersections are relatively safe -\n");
-  printf(
-"    Triangle will calculate the intersection points for you and add them to\n"
-);
-  printf(
-"    the triangulation - as long as your machine's floating-point precision\n"
-);
-  printf(
-"    doesn't become a problem.  You are tempting the fates if you have three\n"
-);
-  printf(
-"    segments that cross at the same location, and expect Triangle to figure\n"
-);
-  printf(
-"    out where the intersection point is.  Thanks to floating-point roundoff\n"
-);
-  printf(
-"    error, Triangle will probably decide that the three segments intersect\n"
-);
-  printf(
-"    at three different points, and you will find a minuscule triangle in\n");
-  printf(
-"    your output - unless Triangle tries to refine the tiny triangle, uses\n");
-  printf(
-"    up the last bit of machine precision, and fails to terminate at all.\n");
-  printf(
-"    You're better off putting the intersection point in the input files,\n");
-  printf(
-"    and manually breaking up each segment into two.  Similarly, if you\n");
-  printf(
-"    place a point at the middle of a segment, and hope that Triangle will\n");
-  printf(
-"    break up the segment at that point, you might get lucky.  On the other\n"
-);
-  printf(
-"    hand, Triangle might decide that the point doesn't lie precisely on the\n"
-);
-  printf(
-"    line, and you'll have a needle-sharp triangle in your output - or a lot\n"
-);
-  printf("    of tiny triangles if you're generating a quality mesh.\n\n");
-  printf(
-"    When Triangle reads a .poly file, it also writes a .poly file, which\n");
-  printf(
-"    includes all edges that are part of input segments.  If the -c switch\n");
-  printf(
-"    is used, the output .poly file will also include all of the edges on\n");
-  printf(
-"    the convex hull.  Hence, the output .poly file is useful for finding\n");
-  printf(
-"    edges associated with input segments and setting boundary conditions in\n"
-);
-  printf(
-"    finite element simulations.  More importantly, you will need it if you\n"
-);
-  printf(
-"    plan to refine the output mesh, and don't want segments to be missing\n");
-  printf("    in later triangulations.\n\n");
-  printf("  .area files:\n");
-  printf("    First line:  <# of triangles>\n");
-  printf("    Following lines:  <triangle #> <maximum area>\n\n");
-  printf(
-"    An .area file associates with each triangle a maximum area that is used\n"
-);
-  printf(
-"    for mesh refinement.  As with other file formats, every triangle must\n");
-  printf(
-"    be represented, and they must be numbered consecutively.  A triangle\n");
-  printf(
-"    may be left unconstrained by assigning it a negative maximum area.\n");
-  printf("\n");
-  printf("  .edge files:\n");
-  printf("    First line:  <# of edges> <# of boundary markers (0 or 1)>\n");
-  printf(
-"    Following lines:  <edge #> <endpoint> <endpoint> [boundary marker]\n");
-  printf("\n");
-  printf(
-"    Endpoints are indices into the corresponding .node file.  Triangle can\n"
-);
-  printf(
-"    produce .edge files (use the -e switch), but cannot read them.  The\n");
-  printf(
-"    optional column of boundary markers is suppressed by the -B switch.\n");
-  printf("\n");
-  printf(
-"    In Voronoi diagrams, one also finds a special kind of edge that is an\n");
-  printf(
-"    infinite ray with only one endpoint.  For these edges, a different\n");
-  printf("    format is used:\n\n");
-  printf("        <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
-  printf(
-"    The `direction' is a floating-point vector that indicates the direction\n"
-);
-  printf("    of the infinite ray.\n\n");
-  printf("  .neigh files:\n");
-  printf(
-"    First line:  <# of triangles> <# of neighbors per triangle (always 3)>\n"
-);
-  printf(
-"    Following lines:  <triangle #> <neighbor> <neighbor> <neighbor>\n");
-  printf("\n");
-  printf(
-"    Neighbors are indices into the corresponding .ele file.  An index of -1\n"
-);
-  printf(
-"    indicates a mesh boundary, and therefore no neighbor.  Triangle can\n");
-  printf(
-"    produce .neigh files (use the -n switch), but cannot read them.\n");
-  printf("\n");
-  printf(
-"    The first neighbor of triangle i is opposite the first corner of\n");
-  printf("    triangle i, and so on.\n\n");
-  printf("Boundary Markers:\n\n");
-  printf(
-"  Boundary markers are tags used mainly to identify which output points and\n"
-);
-  printf(
-"  edges are associated with which PSLG segment, and to identify which\n");
-  printf(
-"  points and edges occur on a boundary of the triangulation.  A common use\n"
-);
-  printf(
-"  is to determine where boundary conditions should be applied to a finite\n");
-  printf(
-"  element mesh.  You can prevent boundary markers from being written into\n");
-  printf("  files produced by Triangle by using the -B switch.\n\n");
-  printf(
-"  The boundary marker associated with each segment in an output .poly file\n"
-);
-  printf("  or edge in an output .edge file is chosen as follows:\n");
-  printf(
-"    - If an output edge is part or all of a PSLG segment with a nonzero\n");
-  printf(
-"      boundary marker, then the edge is assigned the same marker.\n");
-  printf(
-"    - Otherwise, if the edge occurs on a boundary of the triangulation\n");
-  printf(
-"      (including boundaries of holes), then the edge is assigned the marker\n"
-);
-  printf("      one (1).\n");
-  printf("    - Otherwise, the edge is assigned the marker zero (0).\n");
-  printf(
-"  The boundary marker associated with each point in an output .node file is\n"
-);
-  printf("  chosen as follows:\n");
-  printf(
-"    - If a point is assigned a nonzero boundary marker in the input file,\n");
-  printf(
-"      then it is assigned the same marker in the output .node file.\n");
-  printf(
-"    - Otherwise, if the point lies on a PSLG segment (including the\n");
-  printf(
-"      segment's endpoints) with a nonzero boundary marker, then the point\n");
-  printf(
-"      is assigned the same marker.  If the point lies on several such\n");
-  printf("      segments, one of the markers is chosen arbitrarily.\n");
-  printf(
-"    - Otherwise, if the point occurs on a boundary of the triangulation,\n");
-  printf("      then the point is assigned the marker one (1).\n");
-  printf("    - Otherwise, the point is assigned the marker zero (0).\n");
-  printf("\n");
-  printf(
-"  If you want Triangle to determine for you which points and edges are on\n");
-  printf(
-"  the boundary, assign them the boundary marker zero (or use no markers at\n"
-);
-  printf(
-"  all) in your input files.  Alternatively, you can mark some of them and\n");
-  printf("  leave others marked zero, allowing Triangle to label them.\n\n");
-  printf("Triangulation Iteration Numbers:\n\n");
-  printf(
-"  Because Triangle can read and refine its own triangulations, input\n");
-  printf(
-"  and output files have iteration numbers.  For instance, Triangle might\n");
-  printf(
-"  read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
-  printf(
-"  triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
-  printf("  mesh.4.poly.  Files with no iteration number are treated as if\n");
-  printf(
-"  their iteration number is zero; hence, Triangle might read the file\n");
-  printf(
-"  points.node, triangulate it, and produce the files points.1.node and\n");
-  printf("  points.1.ele.\n\n");
-  printf(
-"  Iteration numbers allow you to create a sequence of successively finer\n");
-  printf(
-"  meshes suitable for multigrid methods.  They also allow you to produce a\n"
-);
-  printf(
-"  sequence of meshes using error estimate-driven mesh refinement.\n");
-  printf("\n");
-  printf(
-"  If you're not using refinement or quality meshing, and you don't like\n");
-  printf(
-"  iteration numbers, use the -I switch to disable them.  This switch will\n");
-  printf(
-"  also disable output of .node and .poly files to prevent your input files\n"
-);
-  printf(
-"  from being overwritten.  (If the input is a .poly file that contains its\n"
-);
-  printf("  own points, a .node file will be written.)\n\n");
-  printf("Examples of How to Use Triangle:\n\n");
-  printf(
-"  `triangle dots' will read points from dots.node, and write their Delaunay\n"
-);
-  printf(
-"  triangulation to dots.1.node and dots.1.ele.  (dots.1.node will be\n");
-  printf(
-"  identical to dots.node.)  `triangle -I dots' writes the triangulation to\n"
-);
-  printf(
-"  dots.ele instead.  (No additional .node file is needed, so none is\n");
-  printf("  written.)\n\n");
-  printf(
-"  `triangle -pe object.1' will read a PSLG from object.1.poly (and possibly\n"
-);
-  printf(
-"  object.1.node, if the points are omitted from object.1.poly) and write\n");
-  printf("  their constrained Delaunay triangulation to object.2.node and\n");
-  printf(
-"  object.2.ele.  The segments will be copied to object.2.poly, and all\n");
-  printf("  edges will be written to object.2.edge.\n\n");
-  printf(
-"  `triangle -pq31.5a.1 object' will read a PSLG from object.poly (and\n");
-  printf(
-"  possibly object.node), generate a mesh whose angles are all greater than\n"
-);
-  printf(
-"  31.5 degrees and whose triangles all have area smaller than 0.1, and\n");
-  printf(
-"  write the mesh to object.1.node and object.1.ele.  Each segment may have\n"
-);
-  printf(
-"  been broken up into multiple edges; the resulting constrained edges are\n");
-  printf("  written to object.1.poly.\n\n");
-  printf(
-"  Here is a sample file `box.poly' describing a square with a square hole:\n"
-);
-  printf("\n");
-  printf(
-"    # A box with eight points in 2D, no attributes, one boundary marker.\n");
-  printf("    8 2 0 1\n");
-  printf("    # Outer box has these vertices:\n");
-  printf("     1   0 0   0\n");
-  printf("     2   0 3   0\n");
-  printf("     3   3 0   0\n");
-  printf("     4   3 3   33     # A special marker for this point.\n");
-  printf("    # Inner square has these vertices:\n");
-  printf("     5   1 1   0\n");
-  printf("     6   1 2   0\n");
-  printf("     7   2 1   0\n");
-  printf("     8   2 2   0\n");
-  printf("    # Five segments with boundary markers.\n");
-  printf("    5 1\n");
-  printf("     1   1 2   5      # Left side of outer box.\n");
-  printf("     2   5 7   0      # Segments 2 through 5 enclose the hole.\n");
-  printf("     3   7 8   0\n");
-  printf("     4   8 6   10\n");
-  printf("     5   6 5   0\n");
-  printf("    # One hole in the middle of the inner square.\n");
-  printf("    1\n");
-  printf("     1   1.5 1.5\n\n");
-  printf(
-"  Note that some segments are missing from the outer square, so one must\n");
-  printf(
-"  use the `-c' switch.  After `triangle -pqc box.poly', here is the output\n"
-);
-  printf(
-"  file `box.1.node', with twelve points.  The last four points were added\n");
-  printf(
-"  to meet the angle constraint.  Points 1, 2, and 9 have markers from\n");
-  printf(
-"  segment 1.  Points 6 and 8 have markers from segment 4.  All the other\n");
-  printf(
-"  points but 4 have been marked to indicate that they lie on a boundary.\n");
-  printf("\n");
-  printf("    12  2  0  1\n");
-  printf("       1    0   0      5\n");
-  printf("       2    0   3      5\n");
-  printf("       3    3   0      1\n");
-  printf("       4    3   3     33\n");
-  printf("       5    1   1      1\n");
-  printf("       6    1   2     10\n");
-  printf("       7    2   1      1\n");
-  printf("       8    2   2     10\n");
-  printf("       9    0   1.5    5\n");
-  printf("      10    1.5   0    1\n");
-  printf("      11    3   1.5    1\n");
-  printf("      12    1.5   3    1\n");
-  printf("    # Generated by triangle -pqc box.poly\n\n");
-  printf("  Here is the output file `box.1.ele', with twelve triangles.\n\n");
-  printf("    12  3  0\n");
-  printf("       1     5   6   9\n");
-  printf("       2    10   3   7\n");
-  printf("       3     6   8  12\n");
-  printf("       4     9   1   5\n");
-  printf("       5     6   2   9\n");
-  printf("       6     7   3  11\n");
-  printf("       7    11   4   8\n");
-  printf("       8     7   5  10\n");
-  printf("       9    12   2   6\n");
-  printf("      10     8   7  11\n");
-  printf("      11     5   1  10\n");
-  printf("      12     8   4  12\n");
-  printf("    # Generated by triangle -pqc box.poly\n\n");
-  printf(
-"  Here is the output file `box.1.poly'.  Note that segments have been added\n"
-);
-  printf(
-"  to represent the convex hull, and some segments have been split by newly\n"
-);
-  printf(
-"  added points.  Note also that <# of points> is set to zero to indicate\n");
-  printf("  that the points should be read from the .node file.\n\n");
-  printf("    0  2  0  1\n");
-  printf("    12  1\n");
-  printf("       1     1   9     5\n");
-  printf("       2     5   7     1\n");
-  printf("       3     8   7     1\n");
-  printf("       4     6   8    10\n");
-  printf("       5     5   6     1\n");
-  printf("       6     3  10     1\n");
-  printf("       7     4  11     1\n");
-  printf("       8     2  12     1\n");
-  printf("       9     9   2     5\n");
-  printf("      10    10   1     1\n");
-  printf("      11    11   3     1\n");
-  printf("      12    12   4     1\n");
-  printf("    1\n");
-  printf("       1   1.5 1.5\n");
-  printf("    # Generated by triangle -pqc box.poly\n\n");
-  printf("Refinement and Area Constraints:\n\n");
-  printf(
-"  The -r switch causes a mesh (.node and .ele files) to be read and\n");
-  printf(
-"  refined.  If the -p switch is also used, a .poly file is read and used to\n"
-);
-  printf(
-"  specify edges that are constrained and cannot be eliminated (although\n");
-  printf(
-"  they can be divided into smaller edges) by the refinement process.\n");
-  printf("\n");
-  printf(
-"  When you refine a mesh, you generally want to impose tighter quality\n");
-  printf(
-"  constraints.  One way to accomplish this is to use -q with a larger\n");
-  printf(
-"  angle, or -a followed by a smaller area than you used to generate the\n");
-  printf(
-"  mesh you are refining.  Another way to do this is to create an .area\n");
-  printf(
-"  file, which specifies a maximum area for each triangle, and use the -a\n");
-  printf(
-"  switch (without a number following).  Each triangle's area constraint is\n"
-);
-  printf(
-"  applied to that triangle.  Area constraints tend to diffuse as the mesh\n");
-  printf(
-"  is refined, so if there are large variations in area constraint between\n");
-  printf("  adjacent triangles, you may not get the results you want.\n\n");
-  printf(
-"  If you are refining a mesh composed of linear (three-node) elements, the\n"
-);
-  printf(
-"  output mesh will contain all the nodes present in the input mesh, in the\n"
-);
-  printf(
-"  same order, with new nodes added at the end of the .node file.  However,\n"
-);
-  printf(
-"  there is no guarantee that each output element is contained in a single\n");
-  printf(
-"  input element.  Often, output elements will overlap two input elements,\n");
-  printf(
-"  and input edges are not present in the output mesh.  Hence, a sequence of\n"
-);
-  printf(
-"  refined meshes will form a hierarchy of nodes, but not a hierarchy of\n");
-  printf(
-"  elements.  If you a refining a mesh of higher-order elements, the\n");
-  printf(
-"  hierarchical property applies only to the nodes at the corners of an\n");
-  printf("  element; other nodes may not be present in the refined mesh.\n\n");
-  printf(
-"  It is important to understand that maximum area constraints in .poly\n");
-  printf(
-"  files are handled differently from those in .area files.  A maximum area\n"
-);
-  printf(
-"  in a .poly file applies to the whole (segment-bounded) region in which a\n"
-);
-  printf(
-"  point falls, whereas a maximum area in an .area file applies to only one\n"
-);
-  printf(
-"  triangle.  Area constraints in .poly files are used only when a mesh is\n");
-  printf(
-"  first generated, whereas area constraints in .area files are used only to\n"
-);
-  printf(
-"  refine an existing mesh, and are typically based on a posteriori error\n");
-  printf(
-"  estimates resulting from a finite element simulation on that mesh.\n");
-  printf("\n");
-  printf(
-"  `triangle -rq25 object.1' will read object.1.node and object.1.ele, then\n"
-);
-  printf(
-"  refine the triangulation to enforce a 25 degree minimum angle, and then\n");
-  printf(
-"  write the refined triangulation to object.2.node and object.2.ele.\n");
-  printf("\n");
-  printf(
-"  `triangle -rpaa6.2 z.3' will read z.3.node, z.3.ele, z.3.poly, and\n");
-  printf(
-"  z.3.area.  After reconstructing the mesh and its segments, Triangle will\n"
-);
-  printf(
-"  refine the mesh so that no triangle has area greater than 6.2, and\n");
-  printf(
-"  furthermore the triangles satisfy the maximum area constraints in\n");
-  printf(
-"  z.3.area.  The output is written to z.4.node, z.4.ele, and z.4.poly.\n");
-  printf("\n");
-  printf(
-"  The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
-  printf(
-"  x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
-  printf("  suitable for multigrid.\n\n");
-  printf("Convex Hulls and Mesh Boundaries:\n\n");
-  printf(
-"  If the input is a point set (rather than a PSLG), Triangle produces its\n");
-  printf(
-"  convex hull as a by-product in the output .poly file if you use the -c\n");
-  printf(
-"  switch.  There are faster algorithms for finding a two-dimensional convex\n"
-);
-  printf(
-"  hull than triangulation, of course, but this one comes for free.  If the\n"
-);
-  printf(
-"  input is an unconstrained mesh (you are using the -r switch but not the\n");
-  printf(
-"  -p switch), Triangle produces a list of its boundary edges (including\n");
-  printf("  hole boundaries) as a by-product if you use the -c switch.\n\n");
-  printf("Voronoi Diagrams:\n\n");
-  printf(
-"  The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
-  printf(
-"  .v.edge.  For example, `triangle -v points' will read points.node,\n");
-  printf(
-"  produce its Delaunay triangulation in points.1.node and points.1.ele,\n");
-  printf(
-"  and produce its Voronoi diagram in points.1.v.node and points.1.v.edge.\n");
-  printf(
-"  The .v.node file contains a list of all Voronoi vertices, and the .v.edge\n"
-);
-  printf(
-"  file contains a list of all Voronoi edges, some of which may be infinite\n"
-);
-  printf(
-"  rays.  (The choice of filenames makes it easy to run the set of Voronoi\n");
-  printf("  vertices through Triangle, if so desired.)\n\n");
-  printf(
-"  This implementation does not use exact arithmetic to compute the Voronoi\n"
-);
-  printf(
-"  vertices, and does not check whether neighboring vertices are identical.\n"
-);
-  printf(
-"  Be forewarned that if the Delaunay triangulation is degenerate or\n");
-  printf(
-"  near-degenerate, the Voronoi diagram may have duplicate points, crossing\n"
-);
-  printf(
-"  edges, or infinite rays whose direction vector is zero.  Also, if you\n");
-  printf(
-"  generate a constrained (as opposed to conforming) Delaunay triangulation,\n"
-);
-  printf(
-"  or if the triangulation has holes, the corresponding Voronoi diagram is\n");
-  printf("  likely to have crossing edges and unlikely to make sense.\n\n");
-  printf("Mesh Topology:\n\n");
-  printf(
-"  You may wish to know which triangles are adjacent to a certain Delaunay\n");
-  printf(
-"  edge in an .edge file, which Voronoi regions are adjacent to a certain\n");
-  printf(
-"  Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to\n"
-);
-  printf(
-"  each other.  All of this information can be found by cross-referencing\n");
-  printf(
-"  output files with the recollection that the Delaunay triangulation and\n");
-  printf("  the Voronoi diagrams are planar duals.\n\n");
-  printf(
-"  Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
-  printf(
-"  the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
-  printf(
-"  wise from the Voronoi edge.  Triangle j of an .ele file is the dual of\n");
-  printf(
-"  vertex j of the corresponding .v.node file; and Voronoi region k is the\n");
-  printf("  dual of point k of the corresponding .node file.\n\n");
-  printf(
-"  Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
-  printf(
-"  vertices of the corresponding Voronoi edge; their dual triangles are on\n");
-  printf(
-"  the left and right of the Delaunay edge, respectively.  To find the\n");
-  printf(
-"  Voronoi regions adjacent to a Voronoi edge, look at the endpoints of the\n"
-);
-  printf(
-"  corresponding Delaunay edge; their dual regions are on the right and left\n"
-);
-  printf(
-"  of the Voronoi edge, respectively.  To find which Voronoi regions are\n");
-  printf("  adjacent to each other, just read the list of Delaunay edges.\n");
-  printf("\n");
-  printf("Statistics:\n");
-  printf("\n");
-  printf(
-"  After generating a mesh, Triangle prints a count of the number of points,\n"
-);
-  printf(
-"  triangles, edges, boundary edges, and segments in the output mesh.  If\n");
-  printf(
-"  you've forgotten the statistics for an existing mesh, the -rNEP switches\n"
-);
-  printf(
-"  (or -rpNEP if you've got a .poly file for the existing mesh) will\n");
-  printf("  regenerate these statistics without writing any output.\n\n");
-  printf(
-"  The -V switch produces extended statistics, including a rough estimate\n");
-  printf(
-"  of memory use and a histogram of triangle aspect ratios and angles in the\n"
-);
-  printf("  mesh.\n\n");
-  printf("Exact Arithmetic:\n\n");
-  printf(
-"  Triangle uses adaptive exact arithmetic to perform what computational\n");
-  printf(
-"  geometers call the `orientation' and `incircle' tests.  If the floating-\n"
-);
-  printf(
-"  point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
-  printf(
-"  most workstations do), and does not use extended precision internal\n");
-  printf(
-"  registers, then your output is guaranteed to be an absolutely true\n");
-  printf("  Delaunay or conforming Delaunay triangulation, roundoff error\n");
-  printf(
-"  notwithstanding.  The word `adaptive' implies that these arithmetic\n");
-  printf(
-"  routines compute the result only to the precision necessary to guarantee\n"
-);
-  printf(
-"  correctness, so they are usually nearly as fast as their approximate\n");
-  printf(
-"  counterparts.  The exact tests can be disabled with the -X switch.  On\n");
-  printf(
-"  most inputs, this switch will reduce the computation time by about eight\n"
-);
-  printf(
-"  percent - it's not worth the risk.  There are rare difficult inputs\n");
-  printf(
-"  (having many collinear and cocircular points), however, for which the\n");
-  printf(
-"  difference could be a factor of two.  These are precisely the inputs most\n"
-);
-  printf("  likely to cause errors if you use the -X switch.\n\n");
-  printf(
-"  Unfortunately, these routines don't solve every numerical problem.  Exact\n"
-);
-  printf(
-"  arithmetic is not used to compute the positions of points, because the\n");
-  printf(
-"  bit complexity of point coordinates would grow without bound.  Hence,\n");
-  printf(
-"  segment intersections aren't computed exactly; in very unusual cases,\n");
-  printf(
-"  roundoff error in computing an intersection point might actually lead to\n"
-);
-  printf(
-"  an inverted triangle and an invalid triangulation.  (This is one reason\n");
-  printf(
-"  to compute your own intersection points in your .poly files.)  Similarly,\n"
-);
-  printf(
-"  exact arithmetic is not used to compute the vertices of the Voronoi\n");
-  printf("  diagram.\n\n");
-  printf(
-"  Underflow and overflow can also cause difficulties; the exact arithmetic\n"
-);
-  printf(
-"  routines do not ameliorate out-of-bounds exponents, which can arise\n");
-  printf(
-"  during the orientation and incircle tests.  As a rule of thumb, you\n");
-  printf(
-"  should ensure that your input values are within a range such that their\n");
-  printf(
-"  third powers can be taken without underflow or overflow.  Underflow can\n");
-  printf(
-"  silently prevent the tests from being performed exactly, while overflow\n");
-  printf("  will typically cause a floating exception.\n\n");
-  printf("Calling Triangle from Another Program:\n\n");
-  printf("  Read the file triangle.h for details.\n\n");
-  printf("Troubleshooting:\n\n");
-  printf("  Please read this section before mailing me bugs.\n\n");
-  printf("  `My output mesh has no triangles!'\n\n");
-  printf(
-"    If you're using a PSLG, you've probably failed to specify a proper set\n"
-);
-  printf(
-"    of bounding segments, or forgotten to use the -c switch.  Or you may\n");
-  printf(
-"    have placed a hole badly.  To test these possibilities, try again with\n"
-);
-  printf(
-"    the -c and -O switches.  Alternatively, all your input points may be\n");
-  printf(
-"    collinear, in which case you can hardly expect to triangulate them.\n");
-  printf("\n");
-  printf("  `Triangle doesn't terminate, or just crashes.'\n");
-  printf("\n");
-  printf(
-"    Bad things can happen when triangles get so small that the distance\n");
-  printf(
-"    between their vertices isn't much larger than the precision of your\n");
-  printf(
-"    machine's arithmetic.  If you've compiled Triangle for single-precision\n"
-);
-  printf(
-"    arithmetic, you might do better by recompiling it for double-precision.\n"
-);
-  printf(
-"    Then again, you might just have to settle for more lenient constraints\n"
-);
-  printf(
-"    on the minimum angle and the maximum area than you had planned.\n");
-  printf("\n");
-  printf(
-"    You can minimize precision problems by ensuring that the origin lies\n");
-  printf(
-"    inside your point set, or even inside the densest part of your\n");
-  printf(
-"    mesh.  On the other hand, if you're triangulating an object whose x\n");
-  printf(
-"    coordinates all fall between 6247133 and 6247134, you're not leaving\n");
-  printf("    much floating-point precision for Triangle to work with.\n\n");
-  printf(
-"    Precision problems can occur covertly if the input PSLG contains two\n");
-  printf(
-"    segments that meet (or intersect) at a very small angle, or if such an\n"
-);
-  printf(
-"    angle is introduced by the -c switch, which may occur if a point lies\n");
-  printf(
-"    ever-so-slightly inside the convex hull, and is connected by a PSLG\n");
-  printf(
-"    segment to a point on the convex hull.  If you don't realize that a\n");
-  printf(
-"    small angle is being formed, you might never discover why Triangle is\n");
-  printf(
-"    crashing.  To check for this possibility, use the -S switch (with an\n");
-  printf(
-"    appropriate limit on the number of Steiner points, found by trial-and-\n"
-);
-  printf(
-"    error) to stop Triangle early, and view the output .poly file with\n");
-  printf(
-"    Show Me (described below).  Look carefully for small angles between\n");
-  printf(
-"    segments; zoom in closely, as such segments might look like a single\n");
-  printf("    segment from a distance.\n\n");
-  printf(
-"    If some of the input values are too large, Triangle may suffer a\n");
-  printf(
-"    floating exception due to overflow when attempting to perform an\n");
-  printf(
-"    orientation or incircle test.  (Read the section on exact arithmetic\n");
-  printf(
-"    above.)  Again, I recommend compiling Triangle for double (rather\n");
-  printf("    than single) precision arithmetic.\n\n");
-  printf(
-"  `The numbering of the output points doesn't match the input points.'\n");
-  printf("\n");
-  printf(
-"    You may have eaten some of your input points with a hole, or by placing\n"
-);
-  printf("    them outside the area enclosed by segments.\n\n");
-  printf(
-"  `Triangle executes without incident, but when I look at the resulting\n");
-  printf(
-"  mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
-  printf("\n");
-  printf(
-"    If you select the -X switch, Triangle's divide-and-conquer Delaunay\n");
-  printf(
-"    triangulation algorithm occasionally makes mistakes due to floating-\n");
-  printf(
-"    point roundoff error.  Although these errors are rare, don't use the -X\n"
-);
-  printf("    switch.  If you still have problems, please report the bug.\n");
-  printf("\n");
-  printf(
-"  Strange things can happen if you've taken liberties with your PSLG.  Do\n");
-  printf(
-"  you have a point lying in the middle of a segment?  Triangle sometimes\n");
-  printf(
-"  copes poorly with that sort of thing.  Do you want to lay out a collinear\n"
-);
-  printf(
-"  row of evenly spaced, segment-connected points?  Have you simply defined\n"
-);
-  printf(
-"  one long segment connecting the leftmost point to the rightmost point,\n");
-  printf(
-"  and a bunch of points lying along it?  This method occasionally works,\n");
-  printf(
-"  especially with horizontal and vertical lines, but often it doesn't, and\n"
-);
-  printf(
-"  you'll have to connect each adjacent pair of points with a separate\n");
-  printf("  segment.  If you don't like it, tough.\n\n");
-  printf(
-"  Furthermore, if you have segments that intersect other than at their\n");
-  printf(
-"  endpoints, try not to let the intersections fall extremely close to PSLG\n"
-);
-  printf("  points or each other.\n\n");
-  printf(
-"  If you have problems refining a triangulation not produced by Triangle:\n");
-  printf(
-"  Are you sure the triangulation is geometrically valid?  Is it formatted\n");
-  printf(
-"  correctly for Triangle?  Are the triangles all listed so the first three\n"
-);
-  printf("  points are their corners in counterclockwise order?\n\n");
-  printf("Show Me:\n\n");
-  printf(
-"  Triangle comes with a separate program named `Show Me', whose primary\n");
-  printf(
-"  purpose is to draw meshes on your screen or in PostScript.  Its secondary\n"
-);
-  printf(
-"  purpose is to check the validity of your input files, and do so more\n");
-  printf(
-"  thoroughly than Triangle does.  Show Me requires that you have the X\n");
-  printf(
-"  Windows system.  If you didn't receive Show Me with Triangle, complain to\n"
-);
-  printf("  whomever you obtained Triangle from, then send me mail.\n\n");
-  printf("Triangle on the Web:\n\n");
-  printf(
-"  To see an illustrated, updated version of these instructions, check out\n");
-  printf("\n");
-  printf("    http://www.cs.cmu.edu/~quake/triangle.html\n");
-  printf("\n");
-  printf("A Brief Plea:\n");
-  printf("\n");
-  printf(
-"  If you use Triangle, and especially if you use it to accomplish real\n");
-  printf(
-"  work, I would like very much to hear from you.  A short letter or email\n");
-  printf(
-"  (to jrs@cs.cmu.edu) describing how you use Triangle will mean a lot to\n");
-  printf(
-"  me.  The more people I know are using this program, the more easily I can\n"
-);
-  printf(
-"  justify spending time on improvements and on the three-dimensional\n");
-  printf(
-"  successor to Triangle, which in turn will benefit you.  Also, I can put\n");
-  printf(
-"  you on a list to receive email whenever a new version of Triangle is\n");
-  printf("  available.\n\n");
-  printf(
-"  If you use a mesh generated by Triangle in a publication, please include\n"
-);
-  printf("  an acknowledgment as well.\n\n");
-  printf("Research credit:\n\n");
-  printf(
-"  Of course, I can take credit for only a fraction of the ideas that made\n");
-  printf(
-"  this mesh generator possible.  Triangle owes its existence to the efforts\n"
-);
-  printf(
-"  of many fine computational geometers and other researchers, including\n");
-  printf(
-"  Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David\n");
-  printf(
-"  Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.\n");
-  printf(
-"  Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,\n");
-  printf(
-"  Isaac Saias, Bruce J. Schachter, Micha Sharir, Jorge Stolfi, Christopher\n"
-);
-  printf(
-"  J. Van Wyk, David F. Watson, and Binhai Zhu.  See the comments at the\n");
-  printf("  beginning of the source code for references.\n\n");
-  exit(0);
-}
-
-#endif /* not TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  internalerror()   Ask the user to send me the defective product.  Exit.  */
-/*                                                                           */
-/*****************************************************************************/
-
-void internalerror()
-{
-  printf("  Please report this bug to jrs@cs.cmu.edu\n");
-  printf("  Include the message above, your input data set, and the exact\n");
-  printf("    command line you used to run Triangle.\n");
-  exit(1);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  parsecommandline()   Read the command line, identify switches, and set   */
-/*                       up options and file names.                          */
-/*                                                                           */
-/*  The effects of this routine are felt entirely through global variables.  */
-/*                                                                           */
-/*****************************************************************************/
-
-void parsecommandline(argc, argv)
-int argc;
-char **argv;
-{
-#ifdef TRILIBRARY
-#define STARTINDEX 0
-#else /* not TRILIBRARY */
-#define STARTINDEX 1
-  int increment;
-  int meshnumber;
-#endif /* not TRILIBRARY */
-  int i, j;
-#ifndef CDT_ONLY
-  int k;
-  char workstring[FILENAMESIZE];
-#endif
-
-  poly = refine = quality = vararea = fixedarea = regionattrib = convex = 0;
-  firstnumber = 1;
-  edgesout = voronoi = neighbors = geomview = 0;
-  nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0;
-  noholes = noexact = 0;
-  incremental = sweepline = 0;
-  dwyer = 1;
-  splitseg = 0;
-  docheck = 0;
-  nobisect = 0;
-  steiner = -1;
-  order = 1;
-  minangle = 0.0;
-  maxarea = -1.0;
-  quiet = verbose = 0;
-#ifndef TRILIBRARY
-  innodefilename[0] = '\0';
-#endif /* not TRILIBRARY */
-
-  for (i = STARTINDEX; i < argc; i++) {
-#ifndef TRILIBRARY
-    if (argv[i][0] == '-') {
-#endif /* not TRILIBRARY */
-      for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
-        if (argv[i][j] == 'p') {
-          poly = 1;
-	}
-#ifndef CDT_ONLY
-        if (argv[i][j] == 'r') {
-          refine = 1;
-	}
-        if (argv[i][j] == 'q') {
-          quality = 1;
-          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-              (argv[i][j + 1] == '.')) {
-            k = 0;
-            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                   (argv[i][j + 1] == '.')) {
-              j++;
-              workstring[k] = argv[i][j];
-              k++;
-            }
-            workstring[k] = '\0';
-            minangle = (REAL) strtod(workstring, (char **) NULL);
-	  } else {
-            minangle = 20.0;
-	  }
-	}
-        if (argv[i][j] == 'a') {
-          quality = 1;
-          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-              (argv[i][j + 1] == '.')) {
-            fixedarea = 1;
-            k = 0;
-            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
-                   (argv[i][j + 1] == '.')) {
-              j++;
-              workstring[k] = argv[i][j];
-              k++;
-            }
-            workstring[k] = '\0';
-            maxarea = (REAL) strtod(workstring, (char **) NULL);
-            if (maxarea <= 0.0) {
-              printf("Error:  Maximum area must be greater than zero.\n");
-              exit(1);
-	    }
-	  } else {
-            vararea = 1;
-	  }
-	}
-#endif /* not CDT_ONLY */
-        if (argv[i][j] == 'A') {
-          regionattrib = 1;
-        }
-        if (argv[i][j] == 'c') {
-          convex = 1;
-        }
-        if (argv[i][j] == 'z') {
-          firstnumber = 0;
-        }
-        if (argv[i][j] == 'e') {
-          edgesout = 1;
-	}
-        if (argv[i][j] == 'v') {
-          voronoi = 1;
-	}
-        if (argv[i][j] == 'n') {
-          neighbors = 1;
-	}
-        if (argv[i][j] == 'g') {
-          geomview = 1;
-	}
-        if (argv[i][j] == 'B') {
-          nobound = 1;
-	}
-        if (argv[i][j] == 'P') {
-          nopolywritten = 1;
-	}
-        if (argv[i][j] == 'N') {
-          nonodewritten = 1;
-	}
-        if (argv[i][j] == 'E') {
-          noelewritten = 1;
-	}
-#ifndef TRILIBRARY
-        if (argv[i][j] == 'I') {
-          noiterationnum = 1;
-	}
-#endif /* not TRILIBRARY */
-        if (argv[i][j] == 'O') {
-          noholes = 1;
-	}
-        if (argv[i][j] == 'X') {
-          noexact = 1;
-	}
-        if (argv[i][j] == 'o') {
-          if (argv[i][j + 1] == '2') {
-            j++;
-            order = 2;
-          }
-	}
-#ifndef CDT_ONLY
-        if (argv[i][j] == 'Y') {
-          nobisect++;
-	}
-        if (argv[i][j] == 'S') {
-          steiner = 0;
-          while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
-            j++;
-            steiner = steiner * 10 + (int) (argv[i][j] - '0');
-          }
-        }
-#endif /* not CDT_ONLY */
-#ifndef REDUCED
-        if (argv[i][j] == 'i') {
-          incremental = 1;
-        }
-        if (argv[i][j] == 'F') {
-          sweepline = 1;
-        }
-#endif /* not REDUCED */
-        if (argv[i][j] == 'l') {
-          dwyer = 0;
-        }
-#ifndef REDUCED
-#ifndef CDT_ONLY
-        if (argv[i][j] == 's') {
-          splitseg = 1;
-        }
-#endif /* not CDT_ONLY */
-        if (argv[i][j] == 'C') {
-          docheck = 1;
-        }
-#endif /* not REDUCED */
-        if (argv[i][j] == 'Q') {
-          quiet = 1;
-        }
-        if (argv[i][j] == 'V') {
-          verbose++;
-        }
-#ifndef TRILIBRARY
-        if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
-            (argv[i][j] == '?')) {
-          info();
-	}
-#endif /* not TRILIBRARY */
-      }
-#ifndef TRILIBRARY
-    } else {
-      strncpy(innodefilename, argv[i], FILENAMESIZE - 1);
-      innodefilename[FILENAMESIZE - 1] = '\0';
-    }
-#endif /* not TRILIBRARY */
-  }
-#ifndef TRILIBRARY
-  if (innodefilename[0] == '\0') {
-    syntax();
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".node")) {
-    innodefilename[strlen(innodefilename) - 5] = '\0';
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".poly")) {
-    innodefilename[strlen(innodefilename) - 5] = '\0';
-    poly = 1;
-  }
-#ifndef CDT_ONLY
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 4], ".ele")) {
-    innodefilename[strlen(innodefilename) - 4] = '\0';
-    refine = 1;
-  }
-  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".area")) {
-    innodefilename[strlen(innodefilename) - 5] = '\0';
-    refine = 1;
-    quality = 1;
-    vararea = 1;
-  }
-#endif /* not CDT_ONLY */
-#endif /* not TRILIBRARY */
-  steinerleft = steiner;
-  useshelles = poly || refine || quality || convex;
-  goodangle = (REAL)cos(minangle * PI / 180.0);
-  goodangle *= goodangle;
-  if (refine && noiterationnum) {
-    printf(
-      "Error:  You cannot use the -I switch when refining a triangulation.\n");
-    exit(1);
-  }
-  /* Be careful not to allocate space for element area constraints that */
-  /*   will never be assigned any value (other than the default -1.0).  */
-  if (!refine && !poly) {
-    vararea = 0;
-  }
-  /* Be careful not to add an extra attribute to each element unless the */
-  /*   input supports it (PSLG in, but not refining a preexisting mesh). */
-  if (refine || !poly) {
-    regionattrib = 0;
-  }
-
-#ifndef TRILIBRARY
-  strcpy(inpolyfilename, innodefilename);
-  strcpy(inelefilename, innodefilename);
-  strcpy(areafilename, innodefilename);
-  increment = 0;
-  strcpy(workstring, innodefilename);
-  j = 1;
-  while (workstring[j] != '\0') {
-    if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
-      increment = j + 1;
-    }
-    j++;
-  }
-  meshnumber = 0;
-  if (increment > 0) {
-    j = increment;
-    do {
-      if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
-        meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
-      } else {
-        increment = 0;
-      }
-      j++;
-    } while (workstring[j] != '\0');
-  }
-  if (noiterationnum) {
-    strcpy(outnodefilename, innodefilename);
-    strcpy(outelefilename, innodefilename);
-    strcpy(edgefilename, innodefilename);
-    strcpy(vnodefilename, innodefilename);
-    strcpy(vedgefilename, innodefilename);
-    strcpy(neighborfilename, innodefilename);
-    strcpy(offfilename, innodefilename);
-    strcat(outnodefilename, ".node");
-    strcat(outelefilename, ".ele");
-    strcat(edgefilename, ".edge");
-    strcat(vnodefilename, ".v.node");
-    strcat(vedgefilename, ".v.edge");
-    strcat(neighborfilename, ".neigh");
-    strcat(offfilename, ".off");
-  } else if (increment == 0) {
-    strcpy(outnodefilename, innodefilename);
-    strcpy(outpolyfilename, innodefilename);
-    strcpy(outelefilename, innodefilename);
-    strcpy(edgefilename, innodefilename);
-    strcpy(vnodefilename, innodefilename);
-    strcpy(vedgefilename, innodefilename);
-    strcpy(neighborfilename, innodefilename);
-    strcpy(offfilename, innodefilename);
-    strcat(outnodefilename, ".1.node");
-    strcat(outpolyfilename, ".1.poly");
-    strcat(outelefilename, ".1.ele");
-    strcat(edgefilename, ".1.edge");
-    strcat(vnodefilename, ".1.v.node");
-    strcat(vedgefilename, ".1.v.edge");
-    strcat(neighborfilename, ".1.neigh");
-    strcat(offfilename, ".1.off");
-  } else {
-    workstring[increment] = '%';
-    workstring[increment + 1] = 'd';
-    workstring[increment + 2] = '\0';
-    sprintf(outnodefilename, workstring, meshnumber + 1);
-    strcpy(outpolyfilename, outnodefilename);
-    strcpy(outelefilename, outnodefilename);
-    strcpy(edgefilename, outnodefilename);
-    strcpy(vnodefilename, outnodefilename);
-    strcpy(vedgefilename, outnodefilename);
-    strcpy(neighborfilename, outnodefilename);
-    strcpy(offfilename, outnodefilename);
-    strcat(outnodefilename, ".node");
-    strcat(outpolyfilename, ".poly");
-    strcat(outelefilename, ".ele");
-    strcat(edgefilename, ".edge");
-    strcat(vnodefilename, ".v.node");
-    strcat(vedgefilename, ".v.edge");
-    strcat(neighborfilename, ".neigh");
-    strcat(offfilename, ".off");
-  }
-  strcat(innodefilename, ".node");
-  strcat(inpolyfilename, ".poly");
-  strcat(inelefilename, ".ele");
-  strcat(areafilename, ".area");
-#endif /* not TRILIBRARY */
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* User interaction routines begin here                      *********/
-
-/********* Debugging routines begin here                             *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  printtriangle()   Print out the details of a triangle/edge handle.       */
-/*                                                                           */
-/*  I originally wrote this procedure to simplify debugging; it can be       */
-/*  called directly from the debugger, and presents information about a      */
-/*  triangle/edge handle in digestible form.  It's also used when the        */
-/*  highest level of verbosity (`-VVV') is specified.                        */
-/*                                                                           */
-/*****************************************************************************/
-
-void printtriangle(t)
-struct triedge *t;
-{
-  struct triedge printtri;
-  struct edge printsh;
-  point printpoint;
-
-  printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
-         t->orient);
-  decode(t->tri[0], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [0] = Outer space\n");
-  } else {
-    printf("    [0] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  decode(t->tri[1], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [1] = Outer space\n");
-  } else {
-    printf("    [1] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  decode(t->tri[2], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [2] = Outer space\n");
-  } else {
-    printf("    [2] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  org(*t, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
-  else
-    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
-           (t->orient + 1) % 3 + 3, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  dest(*t, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Dest  [%d] = NULL\n", (t->orient + 2) % 3 + 3);
-  else
-    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
-           (t->orient + 2) % 3 + 3, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  apex(*t, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Apex  [%d] = NULL\n", t->orient + 3);
-  else
-    printf("    Apex  [%d] = x%lx  (%.12g, %.12g)\n",
-           t->orient + 3, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  if (useshelles) {
-    sdecode(t->tri[6], printsh);
-    if (printsh.sh != dummysh) {
-      printf("    [6] = x%lx  %d\n", (unsigned long) printsh.sh,
-             printsh.shorient);
-    }
-    sdecode(t->tri[7], printsh);
-    if (printsh.sh != dummysh) {
-      printf("    [7] = x%lx  %d\n", (unsigned long) printsh.sh,
-             printsh.shorient);
-    }
-    sdecode(t->tri[8], printsh);
-    if (printsh.sh != dummysh) {
-      printf("    [8] = x%lx  %d\n", (unsigned long) printsh.sh,
-             printsh.shorient);
-    }
-  }
-  if (vararea) {
-    printf("    Area constraint:  %.4g\n", areabound(*t));
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  printshelle()   Print out the details of a shell edge handle.            */
-/*                                                                           */
-/*  I originally wrote this procedure to simplify debugging; it can be       */
-/*  called directly from the debugger, and presents information about a      */
-/*  shell edge handle in digestible form.  It's also used when the highest   */
-/*  level of verbosity (`-VVV') is specified.                                */
-/*                                                                           */
-/*****************************************************************************/
-
-void printshelle(s)
-struct edge *s;
-{
-  struct edge printsh;
-  struct triedge printtri;
-  point printpoint;
-
-  printf("shell edge x%lx with orientation %d and mark %d:\n",
-         (unsigned long) s->sh, s->shorient, mark(*s));
-  sdecode(s->sh[0], printsh);
-  if (printsh.sh == dummysh) {
-    printf("    [0] = No shell\n");
-  } else {
-    printf("    [0] = x%lx  %d\n", (unsigned long) printsh.sh,
-           printsh.shorient);
-  }
-  sdecode(s->sh[1], printsh);
-  if (printsh.sh == dummysh) {
-    printf("    [1] = No shell\n");
-  } else {
-    printf("    [1] = x%lx  %d\n", (unsigned long) printsh.sh,
-           printsh.shorient);
-  }
-  sorg(*s, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Origin[%d] = NULL\n", 2 + s->shorient);
-  else
-    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
-           2 + s->shorient, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  sdest(*s, printpoint);
-  if (printpoint == (point) NULL)
-    printf("    Dest  [%d] = NULL\n", 3 - s->shorient);
-  else
-    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
-           3 - s->shorient, (unsigned long) printpoint,
-           printpoint[0], printpoint[1]);
-  decode(s->sh[4], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [4] = Outer space\n");
-  } else {
-    printf("    [4] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-  decode(s->sh[5], printtri);
-  if (printtri.tri == dummytri) {
-    printf("    [5] = Outer space\n");
-  } else {
-    printf("    [5] = x%lx  %d\n", (unsigned long) printtri.tri,
-           printtri.orient);
-  }
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Debugging routines end here                               *********/
-
-/********* Memory management routines begin here                     *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  poolinit()   Initialize a pool of memory for allocation of items.        */
-/*                                                                           */
-/*  This routine initializes the machinery for allocating items.  A `pool'   */
-/*  is created whose records have size at least `bytecount'.  Items will be  */
-/*  allocated in `itemcount'-item blocks.  Each item is assumed to be a      */
-/*  collection of words, and either pointers or floating-point values are    */
-/*  assumed to be the "primary" word type.  (The "primary" word type is used */
-/*  to determine alignment of items.)  If `alignment' isn't zero, all items  */
-/*  will be `alignment'-byte aligned in memory.  `alignment' must be either  */
-/*  a multiple or a factor of the primary word size; powers of two are safe. */
-/*  `alignment' is normally used to create a few unused bits at the bottom   */
-/*  of each item's pointer, in which information may be stored.              */
-/*                                                                           */
-/*  Don't change this routine unless you understand it.                      */
-/*                                                                           */
-/*****************************************************************************/
-
-void poolinit(pool, bytecount, itemcount, wtype, alignment)
-struct memorypool *pool;
-int bytecount;
-int itemcount;
-enum wordtype wtype;
-int alignment;
-{
-  int wordsize;
-
-  /* Initialize values in the pool. */
-  pool->itemwordtype = wtype;
-  wordsize = (pool->itemwordtype == POINTER) ? sizeof(VOID *) : sizeof(REAL);
-  /* Find the proper alignment, which must be at least as large as:   */
-  /*   - The parameter `alignment'.                                   */
-  /*   - The primary word type, to avoid unaligned accesses.          */
-  /*   - sizeof(VOID *), so the stack of dead items can be maintained */
-  /*       without unaligned accesses.                                */
-  if (alignment > wordsize) {
-    pool->alignbytes = alignment;
-  } else {
-    pool->alignbytes = wordsize;
-  }
-  if (sizeof(VOID *) > pool->alignbytes) {
-    pool->alignbytes = sizeof(VOID *);
-  }
-  pool->itemwords = ((bytecount + pool->alignbytes - 1) / pool->alignbytes)
-                  * (pool->alignbytes / wordsize);
-  pool->itembytes = pool->itemwords * wordsize;
-  pool->itemsperblock = itemcount;
-
-  /* Allocate a block of items.  Space for `itemsperblock' items and one    */
-  /*   pointer (to point to the next block) are allocated, as well as space */
-  /*   to ensure alignment of the items.                                    */
-  pool->firstblock = (VOID **) malloc(pool->itemsperblock * pool->itembytes
-                                      + sizeof(VOID *) + pool->alignbytes);
-  if (pool->firstblock == (VOID **) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  /* Set the next block pointer to NULL. */
-  *(pool->firstblock) = (VOID *) NULL;
-  poolrestart(pool);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  poolrestart()   Deallocate all items in a pool.                          */
-/*                                                                           */
-/*  The pool is returned to its starting state, except that no memory is     */
-/*  freed to the operating system.  Rather, the previously allocated blocks  */
-/*  are ready to be reused.                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void poolrestart(pool)
-struct memorypool *pool;
-{
-  unsigned long alignptr;
-
-  pool->items = 0;
-  pool->maxitems = 0;
-
-  /* Set the currently active block. */
-  pool->nowblock = pool->firstblock;
-  /* Find the first item in the pool.  Increment by the size of (VOID *). */
-  alignptr = (unsigned long) (pool->nowblock + 1);
-  /* Align the item on an `alignbytes'-byte boundary. */
-  pool->nextitem = (VOID *)
-    (alignptr + (unsigned long) pool->alignbytes
-     - (alignptr % (unsigned long) pool->alignbytes));
-  /* There are lots of unallocated items left in this block. */
-  pool->unallocateditems = pool->itemsperblock;
-  /* The stack of deallocated items is empty. */
-  pool->deaditemstack = (VOID *) NULL;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pooldeinit()   Free to the operating system all memory taken by a pool.  */
-/*                                                                           */
-/*****************************************************************************/
-
-void pooldeinit(pool)
-struct memorypool *pool;
-{
-  while (pool->firstblock != (VOID **) NULL) {
-    pool->nowblock = (VOID **) *(pool->firstblock);
-    free(pool->firstblock);
-    pool->firstblock = pool->nowblock;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  poolalloc()   Allocate space for an item.                                */
-/*                                                                           */
-/*****************************************************************************/
-
-VOID *poolalloc(pool)
-struct memorypool *pool;
-{
-  VOID *newitem;
-  VOID **newblock;
-  unsigned long alignptr;
-
-  /* First check the linked list of dead items.  If the list is not   */
-  /*   empty, allocate an item from the list rather than a fresh one. */
-  if (pool->deaditemstack != (VOID *) NULL) {
-    newitem = pool->deaditemstack;               /* Take first item in list. */
-    pool->deaditemstack = * (VOID **) pool->deaditemstack;
-  } else {
-    /* Check if there are any free items left in the current block. */
-    if (pool->unallocateditems == 0) {
-      /* Check if another block must be allocated. */
-      if (*(pool->nowblock) == (VOID *) NULL) {
-        /* Allocate a new block of items, pointed to by the previous block. */
-        newblock = (VOID **) malloc(pool->itemsperblock * pool->itembytes
-                                    + sizeof(VOID *) + pool->alignbytes);
-        if (newblock == (VOID **) NULL) {
-          printf("Error:  Out of memory.\n");
-          exit(1);
-        }
-        *(pool->nowblock) = (VOID *) newblock;
-        /* The next block pointer is NULL. */
-        *newblock = (VOID *) NULL;
-      }
-      /* Move to the new block. */
-      pool->nowblock = (VOID **) *(pool->nowblock);
-      /* Find the first item in the block.    */
-      /*   Increment by the size of (VOID *). */
-      alignptr = (unsigned long) (pool->nowblock + 1);
-      /* Align the item on an `alignbytes'-byte boundary. */
-      pool->nextitem = (VOID *)
-        (alignptr + (unsigned long) pool->alignbytes
-         - (alignptr % (unsigned long) pool->alignbytes));
-      /* There are lots of unallocated items left in this block. */
-      pool->unallocateditems = pool->itemsperblock;
-    }
-    /* Allocate a new item. */
-    newitem = pool->nextitem;
-    /* Advance `nextitem' pointer to next free item in block. */
-    if (pool->itemwordtype == POINTER) {
-      pool->nextitem = (VOID *) ((VOID **) pool->nextitem + pool->itemwords);
-    } else {
-      pool->nextitem = (VOID *) ((REAL *) pool->nextitem + pool->itemwords);
-    }
-    pool->unallocateditems--;
-    pool->maxitems++;
-  }
-  pool->items++;
-  return newitem;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pooldealloc()   Deallocate space for an item.                            */
-/*                                                                           */
-/*  The deallocated space is stored in a queue for later reuse.              */
-/*                                                                           */
-/*****************************************************************************/
-
-void pooldealloc(pool, dyingitem)
-struct memorypool *pool;
-VOID *dyingitem;
-{
-  /* Push freshly killed item onto stack. */
-  *((VOID **) dyingitem) = pool->deaditemstack;
-  pool->deaditemstack = dyingitem;
-  pool->items--;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  traversalinit()   Prepare to traverse the entire list of items.          */
-/*                                                                           */
-/*  This routine is used in conjunction with traverse().                     */
-/*                                                                           */
-/*****************************************************************************/
-
-void traversalinit(pool)
-struct memorypool *pool;
-{
-  unsigned long alignptr;
-
-  /* Begin the traversal in the first block. */
-  pool->pathblock = pool->firstblock;
-  /* Find the first item in the block.  Increment by the size of (VOID *). */
-  alignptr = (unsigned long) (pool->pathblock + 1);
-  /* Align with item on an `alignbytes'-byte boundary. */
-  pool->pathitem = (VOID *)
-    (alignptr + (unsigned long) pool->alignbytes
-     - (alignptr % (unsigned long) pool->alignbytes));
-  /* Set the number of items left in the current block. */
-  pool->pathitemsleft = pool->itemsperblock;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  traverse()   Find the next item in the list.                             */
-/*                                                                           */
-/*  This routine is used in conjunction with traversalinit().  Be forewarned */
-/*  that this routine successively returns all items in the list, including  */
-/*  deallocated ones on the deaditemqueue.  It's up to you to figure out     */
-/*  which ones are actually dead.  Why?  I don't want to allocate extra      */
-/*  space just to demarcate dead items.  It can usually be done more         */
-/*  space-efficiently by a routine that knows something about the structure  */
-/*  of the item.                                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-VOID *traverse(pool)
-struct memorypool *pool;
-{
-  VOID *newitem;
-  unsigned long alignptr;
-
-  /* Stop upon exhausting the list of items. */
-  if (pool->pathitem == pool->nextitem) {
-    return (VOID *) NULL;
-  }
-  /* Check whether any untraversed items remain in the current block. */
-  if (pool->pathitemsleft == 0) {
-    /* Find the next block. */
-    pool->pathblock = (VOID **) *(pool->pathblock);
-    /* Find the first item in the block.  Increment by the size of (VOID *). */
-    alignptr = (unsigned long) (pool->pathblock + 1);
-    /* Align with item on an `alignbytes'-byte boundary. */
-    pool->pathitem = (VOID *)
-      (alignptr + (unsigned long) pool->alignbytes
-       - (alignptr % (unsigned long) pool->alignbytes));
-    /* Set the number of items left in the current block. */
-    pool->pathitemsleft = pool->itemsperblock;
-  }
-  newitem = pool->pathitem;
-  /* Find the next item in the block. */
-  if (pool->itemwordtype == POINTER) {
-    pool->pathitem = (VOID *) ((VOID **) pool->pathitem + pool->itemwords);
-  } else {
-    pool->pathitem = (VOID *) ((REAL *) pool->pathitem + pool->itemwords);
-  }
-  pool->pathitemsleft--;
-  return newitem;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  dummyinit()   Initialize the triangle that fills "outer space" and the   */
-/*                omnipresent shell edge.                                    */
-/*                                                                           */
-/*  The triangle that fills "outer space", called `dummytri', is pointed to  */
-/*  by every triangle and shell edge on a boundary (be it outer or inner) of */
-/*  the triangulation.  Also, `dummytri' points to one of the triangles on   */
-/*  the convex hull (until the holes and concavities are carved), making it  */
-/*  possible to find a starting triangle for point location.                 */
-/*                                                                           */
-/*  The omnipresent shell edge, `dummysh', is pointed to by every triangle   */
-/*  or shell edge that doesn't have a full complement of real shell edges    */
-/*  to point to.                                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-void dummyinit(trianglewords, shellewords)
-int trianglewords;
-int shellewords;
-{
-  unsigned long alignptr;
-
-  /* `triwords' and `shwords' are used by the mesh manipulation primitives */
-  /*   to extract orientations of triangles and shell edges from pointers. */
-  triwords = trianglewords;       /* Initialize `triwords' once and for all. */
-  shwords = shellewords;           /* Initialize `shwords' once and for all. */
-
-  /* Set up `dummytri', the `triangle' that occupies "outer space". */
-  dummytribase = (triangle *) malloc(triwords * sizeof(triangle)
-                                     + triangles.alignbytes);
-  if (dummytribase == (triangle *) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
-  alignptr = (unsigned long) dummytribase;
-  dummytri = (triangle *)
-    (alignptr + (unsigned long) triangles.alignbytes
-     - (alignptr % (unsigned long) triangles.alignbytes));
-  /* Initialize the three adjoining triangles to be "outer space".  These  */
-  /*   will eventually be changed by various bonding operations, but their */
-  /*   values don't really matter, as long as they can legally be          */
-  /*   dereferenced.                                                       */
-  dummytri[0] = (triangle) dummytri;
-  dummytri[1] = (triangle) dummytri;
-  dummytri[2] = (triangle) dummytri;
-  /* Three NULL vertex points. */
-  dummytri[3] = (triangle) NULL;
-  dummytri[4] = (triangle) NULL;
-  dummytri[5] = (triangle) NULL;
-
-  if (useshelles) {
-    /* Set up `dummysh', the omnipresent "shell edge" pointed to by any      */
-    /*   triangle side or shell edge end that isn't attached to a real shell */
-    /*   edge.                                                               */
-    dummyshbase = (shelle *) malloc(shwords * sizeof(shelle)
-                                    + shelles.alignbytes);
-    if (dummyshbase == (shelle *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-    /* Align `dummysh' on a `shelles.alignbytes'-byte boundary. */
-    alignptr = (unsigned long) dummyshbase;
-    dummysh = (shelle *)
-      (alignptr + (unsigned long) shelles.alignbytes
-       - (alignptr % (unsigned long) shelles.alignbytes));
-    /* Initialize the two adjoining shell edges to be the omnipresent shell */
-    /*   edge.  These will eventually be changed by various bonding         */
-    /*   operations, but their values don't really matter, as long as they  */
-    /*   can legally be dereferenced.                                       */
-    dummysh[0] = (shelle) dummysh;
-    dummysh[1] = (shelle) dummysh;
-    /* Two NULL vertex points. */
-    dummysh[2] = (shelle) NULL;
-    dummysh[3] = (shelle) NULL;
-    /* Initialize the two adjoining triangles to be "outer space". */
-    dummysh[4] = (shelle) dummytri;
-    dummysh[5] = (shelle) dummytri;
-    /* Set the boundary marker to zero. */
-    * (int *) (dummysh + 6) = 0;
-
-    /* Initialize the three adjoining shell edges of `dummytri' to be */
-    /*   the omnipresent shell edge.                                  */
-    dummytri[6] = (triangle) dummysh;
-    dummytri[7] = (triangle) dummysh;
-    dummytri[8] = (triangle) dummysh;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  initializepointpool()   Calculate the size of the point data structure   */
-/*                          and initialize its memory pool.                  */
-/*                                                                           */
-/*  This routine also computes the `pointmarkindex' and `point2triindex'     */
-/*  indices used to find values within each point.                           */
-/*                                                                           */
-/*****************************************************************************/
-
-void initializepointpool()
-{
-  int pointsize;
-
-  /* The index within each point at which the boundary marker is found.  */
-  /*   Ensure the point marker is aligned to a sizeof(int)-byte address. */
-  pointmarkindex = ((mesh_dim + nextras) * sizeof(REAL) + sizeof(int) - 1)
-                 / sizeof(int);
-  pointsize = (pointmarkindex + 1) * sizeof(int);
-  if (poly) {
-    /* The index within each point at which a triangle pointer is found.   */
-    /*   Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
-    point2triindex = (pointsize + sizeof(triangle) - 1) / sizeof(triangle);
-    pointsize = (point2triindex + 1) * sizeof(triangle);
-  }
-  /* Initialize the pool of points. */
-  poolinit(&points, pointsize, POINTPERBLOCK,
-           (sizeof(REAL) >= sizeof(triangle)) ? FLOATINGPOINT : POINTER, 0);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  initializetrisegpools()   Calculate the sizes of the triangle and shell  */
-/*                            edge data structures and initialize their      */
-/*                            memory pools.                                  */
-/*                                                                           */
-/*  This routine also computes the `highorderindex', `elemattribindex', and  */
-/*  `areaboundindex' indices used to find values within each triangle.       */
-/*                                                                           */
-/*****************************************************************************/
-
-void initializetrisegpools()
-{
-  int trisize;
-
-  /* The index within each triangle at which the extra nodes (above three)  */
-  /*   associated with high order elements are found.  There are three      */
-  /*   pointers to other triangles, three pointers to corners, and possibly */
-  /*   three pointers to shell edges before the extra nodes.                */
-  highorderindex = 6 + (useshelles * 3);
-  /* The number of bytes occupied by a triangle. */
-  trisize = ((order + 1) * (order + 2) / 2 + (highorderindex - 3)) *
-            sizeof(triangle);
-  /* The index within each triangle at which its attributes are found, */
-  /*   where the index is measured in REALs.                           */
-  elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
-  /* The index within each triangle at which the maximum area constraint  */
-  /*   is found, where the index is measured in REALs.  Note that if the  */
-  /*   `regionattrib' flag is set, an additional attribute will be added. */
-  areaboundindex = elemattribindex + eextras + regionattrib;
-  /* If triangle attributes or an area bound are needed, increase the number */
-  /*   of bytes occupied by a triangle.                                      */
-  if (vararea) {
-    trisize = (areaboundindex + 1) * sizeof(REAL);
-  } else if (eextras + regionattrib > 0) {
-    trisize = areaboundindex * sizeof(REAL);
-  }
-  /* If a Voronoi diagram or triangle neighbor graph is requested, make    */
-  /*   sure there's room to store an integer index in each triangle.  This */
-  /*   integer index can occupy the same space as the shell edges or       */
-  /*   attributes or area constraint or extra nodes.                       */
-  if ((voronoi || neighbors) &&
-      (trisize < 6 * sizeof(triangle) + sizeof(int))) {
-    trisize = 6 * sizeof(triangle) + sizeof(int);
-  }
-  /* Having determined the memory size of a triangle, initialize the pool. */
-  poolinit(&triangles, trisize, TRIPERBLOCK, POINTER, 4);
-
-  if (useshelles) {
-    /* Initialize the pool of shell edges. */
-    poolinit(&shelles, 6 * sizeof(triangle) + sizeof(int), SHELLEPERBLOCK,
-             POINTER, 4);
-
-    /* Initialize the "outer space" triangle and omnipresent shell edge. */
-    dummyinit(triangles.itemwords, shelles.itemwords);
-  } else {
-    /* Initialize the "outer space" triangle. */
-    dummyinit(triangles.itemwords, 0);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangledealloc()   Deallocate space for a triangle, marking it dead.    */
-/*                                                                           */
-/*****************************************************************************/
-
-void triangledealloc(dyingtriangle)
-triangle *dyingtriangle;
-{
-  /* Set triangle's vertices to NULL.  This makes it possible to        */
-  /*   detect dead triangles when traversing the list of all triangles. */
-  dyingtriangle[3] = (triangle) NULL;
-  dyingtriangle[4] = (triangle) NULL;
-  dyingtriangle[5] = (triangle) NULL;
-  pooldealloc(&triangles, (VOID *) dyingtriangle);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangletraverse()   Traverse the triangles, skipping dead ones.         */
-/*                                                                           */
-/*****************************************************************************/
-
-triangle *triangletraverse()
-{
-  triangle *newtriangle;
-
-  do {
-    newtriangle = (triangle *) traverse(&triangles);
-    if (newtriangle == (triangle *) NULL) {
-      return (triangle *) NULL;
-    }
-  } while (newtriangle[3] == (triangle) NULL);            /* Skip dead ones. */
-  return newtriangle;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  shelledealloc()   Deallocate space for a shell edge, marking it dead.    */
-/*                                                                           */
-/*****************************************************************************/
-
-void shelledealloc(dyingshelle)
-shelle *dyingshelle;
-{
-  /* Set shell edge's vertices to NULL.  This makes it possible to */
-  /*   detect dead shells when traversing the list of all shells.  */
-  dyingshelle[2] = (shelle) NULL;
-  dyingshelle[3] = (shelle) NULL;
-  pooldealloc(&shelles, (VOID *) dyingshelle);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  shelletraverse()   Traverse the shell edges, skipping dead ones.         */
-/*                                                                           */
-/*****************************************************************************/
-
-shelle *shelletraverse()
-{
-  shelle *newshelle;
-
-  do {
-    newshelle = (shelle *) traverse(&shelles);
-    if (newshelle == (shelle *) NULL) {
-      return (shelle *) NULL;
-    }
-  } while (newshelle[2] == (shelle) NULL);                /* Skip dead ones. */
-  return newshelle;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointdealloc()   Deallocate space for a point, marking it dead.          */
-/*                                                                           */
-/*****************************************************************************/
-
-void pointdealloc(dyingpoint)
-point dyingpoint;
-{
-  /* Mark the point as dead.  This makes it possible to detect dead points */
-  /*   when traversing the list of all points.                             */
-  setpointmark(dyingpoint, DEADPOINT);
-  pooldealloc(&points, (VOID *) dyingpoint);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointtraverse()   Traverse the points, skipping dead ones.               */
-/*                                                                           */
-/*****************************************************************************/
-
-point pointtraverse()
-{
-  point newpoint;
-
-  do {
-    newpoint = (point) traverse(&points);
-    if (newpoint == (point) NULL) {
-      return (point) NULL;
-    }
-  } while (pointmark(newpoint) == DEADPOINT);             /* Skip dead ones. */
-  return newpoint;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  badsegmentdealloc()   Deallocate space for a bad segment, marking it     */
-/*                        dead.                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void badsegmentdealloc(dyingseg)
-struct edge *dyingseg;
-{
-  /* Set segment's orientation to -1.  This makes it possible to      */
-  /*   detect dead segments when traversing the list of all segments. */
-  dyingseg->shorient = -1;
-  pooldealloc(&badsegments, (VOID *) dyingseg);
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  badsegmenttraverse()   Traverse the bad segments, skipping dead ones.    */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-struct edge *badsegmenttraverse()
-{
-  struct edge *newseg;
-
-  do {
-    newseg = (struct edge *) traverse(&badsegments);
-    if (newseg == (struct edge *) NULL) {
-      return (struct edge *) NULL;
-    }
-  } while (newseg->shorient == -1);                       /* Skip dead ones. */
-  return newseg;
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  getpoint()   Get a specific point, by number, from the list.             */
-/*                                                                           */
-/*  The first point is number 'firstnumber'.                                 */
-/*                                                                           */
-/*  Note that this takes O(n) time (with a small constant, if POINTPERBLOCK  */
-/*  is large).  I don't care to take the trouble to make it work in constant */
-/*  time.                                                                    */
-/*                                                                           */
-/*****************************************************************************/
-
-point getpoint(number)
-int number;
-{
-  VOID **getblock;
-  point foundpoint;
-  unsigned long alignptr;
-  int current;
-
-  getblock = points.firstblock;
-  current = firstnumber;
-  /* Find the right block. */
-  while (current + points.itemsperblock <= number) {
-    getblock = (VOID **) *getblock;
-    current += points.itemsperblock;
-  }
-  /* Now find the right point. */
-  alignptr = (unsigned long) (getblock + 1);
-  foundpoint = (point) (alignptr + (unsigned long) points.alignbytes
-                        - (alignptr % (unsigned long) points.alignbytes));
-  while (current < number) {
-    foundpoint += points.itemwords;
-    current++;
-  }
-  return foundpoint;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangledeinit()   Free all remaining allocated memory.                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void triangledeinit()
-{
-  pooldeinit(&triangles);
-  free(dummytribase);
-  if (useshelles) {
-    pooldeinit(&shelles);
-    free(dummyshbase);
-  }
-  pooldeinit(&points);
-#ifndef CDT_ONLY
-  if (quality) {
-    pooldeinit(&badsegments);
-    if ((minangle > 0.0) || vararea || fixedarea) {
-      pooldeinit(&badtriangles);
-    }
-  }
-#endif /* not CDT_ONLY */
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Memory management routines end here                       *********/
-
-/********* Constructors begin here                                   *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  maketriangle()   Create a new triangle with orientation zero.            */
-/*                                                                           */
-/*****************************************************************************/
-
-void maketriangle(newtriedge)
-struct triedge *newtriedge;
-{
-  int i;
-
-  newtriedge->tri = (triangle *) poolalloc(&triangles);
-  /* Initialize the three adjoining triangles to be "outer space". */
-  newtriedge->tri[0] = (triangle) dummytri;
-  newtriedge->tri[1] = (triangle) dummytri;
-  newtriedge->tri[2] = (triangle) dummytri;
-  /* Three NULL vertex points. */
-  newtriedge->tri[3] = (triangle) NULL;
-  newtriedge->tri[4] = (triangle) NULL;
-  newtriedge->tri[5] = (triangle) NULL;
-  /* Initialize the three adjoining shell edges to be the omnipresent */
-  /*   shell edge.                                                    */
-  if (useshelles) {
-    newtriedge->tri[6] = (triangle) dummysh;
-    newtriedge->tri[7] = (triangle) dummysh;
-    newtriedge->tri[8] = (triangle) dummysh;
-  }
-  for (i = 0; i < eextras; i++) {
-    setelemattribute(*newtriedge, i, 0.0);
-  }
-  if (vararea) {
-    setareabound(*newtriedge, -1.0);
-  }
-
-  newtriedge->orient = 0;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  makeshelle()   Create a new shell edge with orientation zero.            */
-/*                                                                           */
-/*****************************************************************************/
-
-void makeshelle(newedge)
-struct edge *newedge;
-{
-  newedge->sh = (shelle *) poolalloc(&shelles);
-  /* Initialize the two adjoining shell edges to be the omnipresent */
-  /*   shell edge.                                                  */
-  newedge->sh[0] = (shelle) dummysh;
-  newedge->sh[1] = (shelle) dummysh;
-  /* Two NULL vertex points. */
-  newedge->sh[2] = (shelle) NULL;
-  newedge->sh[3] = (shelle) NULL;
-  /* Initialize the two adjoining triangles to be "outer space". */
-  newedge->sh[4] = (shelle) dummytri;
-  newedge->sh[5] = (shelle) dummytri;
-  /* Set the boundary marker to zero. */
-  setmark(*newedge, 0);
-
-  newedge->shorient = 0;
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Constructors end here                                     *********/
-
-/********* Determinant evaluation routines begin here                *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/* The adaptive exact arithmetic geometric predicates implemented herein are */
-/*   described in detail in my Technical Report CMU-CS-96-140.  The complete */
-/*   reference is given in the header.                                       */
-
-/* Which of the following two methods of finding the absolute values is      */
-/*   fastest is compiler-dependent.  A few compilers can inline and optimize */
-/*   the fabs() call; but most will incur the overhead of a function call,   */
-/*   which is disastrously slow.  A faster way on IEEE machines might be to  */
-/*   mask the appropriate bit, but that's difficult to do in C.              */
-
-#define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
-/* #define Absolute(a)  fabs(a) */
-
-/* Many of the operations are broken up into two pieces, a main part that    */
-/*   performs an approximate operation, and a "tail" that computes the       */
-/*   roundoff error of that operation.                                       */
-/*                                                                           */
-/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(),    */
-/*   Split(), and Two_Product() are all implemented as described in the      */
-/*   reference.  Each of these macros requires certain variables to be       */
-/*   defined in the calling routine.  The variables `bvirt', `c', `abig',    */
-/*   `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because   */
-/*   they store the result of an operation that may incur roundoff error.    */
-/*   The input parameter `x' (or the highest numbered `x_' parameter) must   */
-/*   also be declared `INEXACT'.                                             */
-
-#define Fast_Two_Sum_Tail(a, b, x, y) \
-  bvirt = x - a; \
-  y = b - bvirt
-
-#define Fast_Two_Sum(a, b, x, y) \
-  x = (REAL) (a + b); \
-  Fast_Two_Sum_Tail(a, b, x, y)
-
-#define Two_Sum_Tail(a, b, x, y) \
-  bvirt = (REAL) (x - a); \
-  avirt = x - bvirt; \
-  bround = b - bvirt; \
-  around = a - avirt; \
-  y = around + bround
-
-#define Two_Sum(a, b, x, y) \
-  x = (REAL) (a + b); \
-  Two_Sum_Tail(a, b, x, y)
-
-#define Two_Diff_Tail(a, b, x, y) \
-  bvirt = (REAL) (a - x); \
-  avirt = x + bvirt; \
-  bround = bvirt - b; \
-  around = a - avirt; \
-  y = around + bround
-
-#define Two_Diff(a, b, x, y) \
-  x = (REAL) (a - b); \
-  Two_Diff_Tail(a, b, x, y)
-
-#define Split(a, ahi, alo) \
-  c = (REAL) (splitter * a); \
-  abig = (REAL) (c - a); \
-  ahi = (REAL)(c - abig); \
-  alo = (REAL)(a - ahi)
-
-#define Two_Product_Tail(a, b, x, y) \
-  Split(a, ahi, alo); \
-  Split(b, bhi, blo); \
-  err1 = x - (ahi * bhi); \
-  err2 = err1 - (alo * bhi); \
-  err3 = err2 - (ahi * blo); \
-  y = (alo * blo) - err3
-
-#define Two_Product(a, b, x, y) \
-  x = (REAL) (a * b); \
-  Two_Product_Tail(a, b, x, y)
-
-/* Two_Product_Presplit() is Two_Product() where one of the inputs has       */
-/*   already been split.  Avoids redundant splitting.                        */
-
-#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
-  x = (REAL) (a * b); \
-  Split(a, ahi, alo); \
-  err1 = x - (ahi * bhi); \
-  err2 = err1 - (alo * bhi); \
-  err3 = err2 - (ahi * blo); \
-  y = (alo * blo) - err3
-
-/* Square() can be done more quickly than Two_Product().                     */
-
-#define Square_Tail(a, x, y) \
-  Split(a, ahi, alo); \
-  err1 = x - (ahi * ahi); \
-  err3 = err1 - ((ahi + ahi) * alo); \
-  y = (alo * alo) - err3
-
-#define Square(a, x, y) \
-  x = (REAL) (a * a); \
-  Square_Tail(a, x, y)
-
-/* Macros for summing expansions of various fixed lengths.  These are all    */
-/*   unrolled versions of Expansion_Sum().                                   */
-
-#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
-  Two_Sum(a0, b , _i, x0); \
-  Two_Sum(a1, _i, x2, x1)
-
-#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
-  Two_Diff(a0, b , _i, x0); \
-  Two_Sum( a1, _i, x2, x1)
-
-#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
-  Two_One_Sum(a1, a0, b0, _j, _0, x0); \
-  Two_One_Sum(_j, _0, b1, x3, x2, x1)
-
-#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
-  Two_One_Diff(a1, a0, b0, _j, _0, x0); \
-  Two_One_Diff(_j, _0, b1, x3, x2, x1)
-
-/*****************************************************************************/
-/*                                                                           */
-/*  exactinit()   Initialize the variables used for exact arithmetic.        */
-/*                                                                           */
-/*  `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in   */
-/*  floating-point arithmetic.  `epsilon' bounds the relative roundoff       */
-/*  error.  It is used for floating-point error analysis.                    */
-/*                                                                           */
-/*  `splitter' is used to split floating-point numbers into two half-        */
-/*  length significands for exact multiplication.                            */
-/*                                                                           */
-/*  I imagine that a highly optimizing compiler might be too smart for its   */
-/*  own good, and somehow cause this routine to fail, if it pretends that    */
-/*  floating-point arithmetic is too much like real arithmetic.              */
-/*                                                                           */
-/*  Don't change this routine unless you fully understand it.                */
-/*                                                                           */
-/*****************************************************************************/
-
-void exactinit()
-{
-  REAL half;
-  REAL check, lastcheck;
-  int every_other;
-
-  every_other = 1;
-  half = 0.5;
-  epsilon = 1.0;
-  splitter = 1.0;
-  check = 1.0;
-  /* Repeatedly divide `epsilon' by two until it is too small to add to      */
-  /*   one without causing roundoff.  (Also check if the sum is equal to     */
-  /*   the previous sum, for machines that round up instead of using exact   */
-  /*   rounding.  Not that these routines will work on such machines anyway. */
-  do {
-    lastcheck = check;
-    epsilon *= half;
-    if (every_other) {
-      splitter *= 2.0;
-    }
-    every_other = !every_other;
-    check = (REAL)(1.0 + epsilon);
-  } while ((check != 1.0) && (check != lastcheck));
-  splitter += 1.0;
-  if (verbose > 1) {
-    printf("Floating point roundoff is of magnitude %.17g\n", epsilon);
-    printf("Floating point splitter is %.17g\n", splitter);
-  }
-  /* Error bounds for orientation and incircle tests. */
-  resulterrbound = (REAL)((3.0 + 8.0 * epsilon) * epsilon);
-  ccwerrboundA = (REAL)((3.0 + 16.0 * epsilon) * epsilon);
-  ccwerrboundB = (REAL)((2.0 + 12.0 * epsilon) * epsilon);
-  ccwerrboundC = (REAL)((9.0 + 64.0 * epsilon) * epsilon * epsilon);
-  iccerrboundA = (REAL)((10.0 + 96.0 * epsilon) * epsilon);
-  iccerrboundB = (REAL)((4.0 + 48.0 * epsilon) * epsilon);
-  iccerrboundC = (REAL)((44.0 + 576.0 * epsilon) * epsilon * epsilon);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  fast_expansion_sum_zeroelim()   Sum two expansions, eliminating zero     */
-/*                                  components from the output expansion.    */
-/*                                                                           */
-/*  Sets h = e + f.  See my Robust Predicates paper for details.             */
-/*                                                                           */
-/*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
-/*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
-/*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
-/*  properties.                                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-int fast_expansion_sum_zeroelim(elen, e, flen, f, h)  /* h cannot be e or f. */
-int elen;
-REAL *e;
-int flen;
-REAL *f;
-REAL *h;
-{
-  REAL Q;
-  INEXACT REAL Qnew;
-  INEXACT REAL hh;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  int eindex, findex, hindex;
-  REAL enow, fnow;
-
-  enow = e[0];
-  fnow = f[0];
-  eindex = findex = 0;
-  if ((fnow > enow) == (fnow > -enow)) {
-    Q = enow;
-    enow = e[++eindex];
-  } else {
-    Q = fnow;
-    fnow = f[++findex];
-  }
-  hindex = 0;
-  if ((eindex < elen) && (findex < flen)) {
-    if ((fnow > enow) == (fnow > -enow)) {
-      Fast_Two_Sum(enow, Q, Qnew, hh);
-      enow = e[++eindex];
-    } else {
-      Fast_Two_Sum(fnow, Q, Qnew, hh);
-      fnow = f[++findex];
-    }
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-    while ((eindex < elen) && (findex < flen)) {
-      if ((fnow > enow) == (fnow > -enow)) {
-        Two_Sum(Q, enow, Qnew, hh);
-        enow = e[++eindex];
-      } else {
-        Two_Sum(Q, fnow, Qnew, hh);
-        fnow = f[++findex];
-      }
-      Q = Qnew;
-      if (hh != 0.0) {
-        h[hindex++] = hh;
-      }
-    }
-  }
-  while (eindex < elen) {
-    Two_Sum(Q, enow, Qnew, hh);
-    enow = e[++eindex];
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-  }
-  while (findex < flen) {
-    Two_Sum(Q, fnow, Qnew, hh);
-    fnow = f[++findex];
-    Q = Qnew;
-    if (hh != 0.0) {
-      h[hindex++] = hh;
-    }
-  }
-  if ((Q != 0.0) || (hindex == 0)) {
-    h[hindex++] = Q;
-  }
-  return hindex;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  scale_expansion_zeroelim()   Multiply an expansion by a scalar,          */
-/*                               eliminating zero components from the        */
-/*                               output expansion.                           */
-/*                                                                           */
-/*  Sets h = be.  See my Robust Predicates paper for details.                */
-/*                                                                           */
-/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
-/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
-/*  properties as well.  (That is, if e has one of these properties, so      */
-/*  will h.)                                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-int scale_expansion_zeroelim(elen, e, b, h)   /* e and h cannot be the same. */
-int elen;
-REAL *e;
-REAL b;
-REAL *h;
-{
-  INEXACT REAL Q, sum;
-  REAL hh;
-  INEXACT REAL product1;
-  REAL product0;
-  int eindex, hindex;
-  REAL enow;
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-
-  Split(b, bhi, blo);
-  Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
-  hindex = 0;
-  if (hh != 0) {
-    h[hindex++] = hh;
-  }
-  for (eindex = 1; eindex < elen; eindex++) {
-    enow = e[eindex];
-    Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
-    Two_Sum(Q, product0, sum, hh);
-    if (hh != 0) {
-      h[hindex++] = hh;
-    }
-    Fast_Two_Sum(product1, sum, Q, hh);
-    if (hh != 0) {
-      h[hindex++] = hh;
-    }
-  }
-  if ((Q != 0.0) || (hindex == 0)) {
-    h[hindex++] = Q;
-  }
-  return hindex;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  estimate()   Produce a one-word estimate of an expansion's value.        */
-/*                                                                           */
-/*  See my Robust Predicates paper for details.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-REAL estimate(elen, e)
-int elen;
-REAL *e;
-{
-  REAL Q;
-  int eindex;
-
-  Q = e[0];
-  for (eindex = 1; eindex < elen; eindex++) {
-    Q += e[eindex];
-  }
-  return Q;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  counterclockwise()   Return a positive value if the points pa, pb, and   */
-/*                       pc occur in counterclockwise order; a negative      */
-/*                       value if they occur in clockwise order; and zero    */
-/*                       if they are collinear.  The result is also a rough  */
-/*                       approximation of twice the signed area of the       */
-/*                       triangle defined by the three points.               */
-/*                                                                           */
-/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
-/*  result returned is the determinant of a matrix.  This determinant is     */
-/*  computed adaptively, in the sense that exact arithmetic is used only to  */
-/*  the degree it is needed to ensure that the returned value has the        */
-/*  correct sign.  Hence, this function is usually quite fast, but will run  */
-/*  more slowly when the input points are collinear or nearly so.            */
-/*                                                                           */
-/*  See my Robust Predicates paper for details.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-REAL counterclockwiseadapt(pa, pb, pc, detsum)
-point pa;
-point pb;
-point pc;
-REAL detsum;
-{
-  INEXACT REAL acx, acy, bcx, bcy;
-  REAL acxtail, acytail, bcxtail, bcytail;
-  INEXACT REAL detleft, detright;
-  REAL detlefttail, detrighttail;
-  REAL det, errbound;
-  REAL B[4], C1[8], C2[12], D[16];
-  INEXACT REAL B3;
-  int C1length, C2length, Dlength;
-  REAL u[4];
-  INEXACT REAL u3;
-  INEXACT REAL s1, t1;
-  REAL s0, t0;
-
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-  INEXACT REAL _i, _j;
-  REAL _0;
-
-  acx = (REAL) (pa[0] - pc[0]);
-  bcx = (REAL) (pb[0] - pc[0]);
-  acy = (REAL) (pa[1] - pc[1]);
-  bcy = (REAL) (pb[1] - pc[1]);
-
-  Two_Product(acx, bcy, detleft, detlefttail);
-  Two_Product(acy, bcx, detright, detrighttail);
-
-  Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
-               B3, B[2], B[1], B[0]);
-  B[3] = B3;
-
-  det = estimate(4, B);
-  errbound = (REAL)(ccwerrboundB * detsum);
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
-  Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
-  Two_Diff_Tail(pa[1], pc[1], acy, acytail);
-  Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
-
-  if ((acxtail == 0.0) && (acytail == 0.0)
-      && (bcxtail == 0.0) && (bcytail == 0.0)) {
-    return det;
-  }
-
-  errbound = (REAL)(ccwerrboundC * detsum + resulterrbound * Absolute(det));
-  det += (acx * bcytail + bcy * acxtail)
-       - (acy * bcxtail + bcx * acytail);
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Product(acxtail, bcy, s1, s0);
-  Two_Product(acytail, bcx, t1, t0);
-  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
-  u[3] = u3;
-  C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
-
-  Two_Product(acx, bcytail, s1, s0);
-  Two_Product(acy, bcxtail, t1, t0);
-  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
-  u[3] = u3;
-  C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
-
-  Two_Product(acxtail, bcytail, s1, s0);
-  Two_Product(acytail, bcxtail, t1, t0);
-  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
-  u[3] = u3;
-  Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
-
-  return(D[Dlength - 1]);
-}
-
-REAL counterclockwise(pa, pb, pc)
-point pa;
-point pb;
-point pc;
-{
-  REAL detleft, detright, det;
-  REAL detsum, errbound;
-
-  counterclockcount++;
-
-  detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
-  detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
-  det = detleft - detright;
-
-  if (noexact) {
-    return det;
-  }
-
-  if (detleft > 0.0) {
-    if (detright <= 0.0) {
-      return det;
-    } else {
-      detsum = detleft + detright;
-    }
-  } else if (detleft < 0.0) {
-    if (detright >= 0.0) {
-      return det;
-    } else {
-      detsum = -detleft - detright;
-    }
-  } else {
-    return det;
-  }
-
-  errbound = ccwerrboundA * detsum;
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  return counterclockwiseadapt(pa, pb, pc, detsum);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  incircle()   Return a positive value if the point pd lies inside the     */
-/*               circle passing through pa, pb, and pc; a negative value if  */
-/*               it lies outside; and zero if the four points are cocircular.*/
-/*               The points pa, pb, and pc must be in counterclockwise       */
-/*               order, or the sign of the result will be reversed.          */
-/*                                                                           */
-/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
-/*  result returned is the determinant of a matrix.  This determinant is     */
-/*  computed adaptively, in the sense that exact arithmetic is used only to  */
-/*  the degree it is needed to ensure that the returned value has the        */
-/*  correct sign.  Hence, this function is usually quite fast, but will run  */
-/*  more slowly when the input points are cocircular or nearly so.           */
-/*                                                                           */
-/*  See my Robust Predicates paper for details.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-REAL incircleadapt(pa, pb, pc, pd, permanent)
-point pa;
-point pb;
-point pc;
-point pd;
-REAL permanent;
-{
-  INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
-  REAL det, errbound;
-
-  INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
-  REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
-  REAL bc[4], ca[4], ab[4];
-  INEXACT REAL bc3, ca3, ab3;
-  REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
-  int axbclen, axxbclen, aybclen, ayybclen, alen;
-  REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
-  int bxcalen, bxxcalen, bycalen, byycalen, blen;
-  REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
-  int cxablen, cxxablen, cyablen, cyyablen, clen;
-  REAL abdet[64];
-  int ablen;
-  REAL fin1[1152], fin2[1152];
-  REAL *finnow, *finother, *finswap;
-  int finlength;
-
-  REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
-  INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
-  REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
-  REAL aa[4], bb[4], cc[4];
-  INEXACT REAL aa3, bb3, cc3;
-  INEXACT REAL ti1, tj1;
-  REAL ti0, tj0;
-  REAL u[4], v[4];
-  INEXACT REAL u3, v3;
-  REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
-  REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
-  int temp8len, temp16alen, temp16blen, temp16clen;
-  int temp32alen, temp32blen, temp48len, temp64len;
-  REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
-  int axtbblen, axtcclen, aytbblen, aytcclen;
-  REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
-  int bxtaalen, bxtcclen, bytaalen, bytcclen;
-  REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
-  int cxtaalen, cxtbblen, cytaalen, cytbblen;
-  REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
-  int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
-  REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
-  int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
-  REAL axtbctt[8], aytbctt[8], bxtcatt[8];
-  REAL bytcatt[8], cxtabtt[8], cytabtt[8];
-  int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
-  REAL abt[8], bct[8], cat[8];
-  int abtlen, bctlen, catlen;
-  REAL abtt[4], bctt[4], catt[4];
-  int abttlen, bcttlen, cattlen;
-  INEXACT REAL abtt3, bctt3, catt3;
-  REAL negate;
-
-  INEXACT REAL bvirt;
-  REAL avirt, bround, around;
-  INEXACT REAL c;
-  INEXACT REAL abig;
-  REAL ahi, alo, bhi, blo;
-  REAL err1, err2, err3;
-  INEXACT REAL _i, _j;
-  REAL _0;
-
-  adx = (REAL) (pa[0] - pd[0]);
-  bdx = (REAL) (pb[0] - pd[0]);
-  cdx = (REAL) (pc[0] - pd[0]);
-  ady = (REAL) (pa[1] - pd[1]);
-  bdy = (REAL) (pb[1] - pd[1]);
-  cdy = (REAL) (pc[1] - pd[1]);
-
-  Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
-  Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
-  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
-  bc[3] = bc3;
-  axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
-  axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
-  aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
-  ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
-  alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
-
-  Two_Product(cdx, ady, cdxady1, cdxady0);
-  Two_Product(adx, cdy, adxcdy1, adxcdy0);
-  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
-  ca[3] = ca3;
-  bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
-  bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
-  bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
-  byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
-  blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
-
-  Two_Product(adx, bdy, adxbdy1, adxbdy0);
-  Two_Product(bdx, ady, bdxady1, bdxady0);
-  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
-  ab[3] = ab3;
-  cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
-  cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
-  cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
-  cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
-  clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
-
-  ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
-  finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
-
-  det = estimate(finlength, fin1);
-  errbound = (REAL)(iccerrboundB * permanent);
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
-  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
-  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
-  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
-  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
-  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
-  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
-      && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
-    return det;
-  }
-
-  errbound = (REAL)(iccerrboundC * permanent + resulterrbound * Absolute(det));
-  det += (REAL)(((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
-                                     - (bdy * cdxtail + cdx * bdytail))
-          + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
-       + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
-                                     - (cdy * adxtail + adx * cdytail))
-          + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
-       + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
-                                     - (ady * bdxtail + bdx * adytail))
-          + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx)));
-  if ((det >= errbound) || (-det >= errbound)) {
-    return det;
-  }
-
-  finnow = fin1;
-  finother = fin2;
-
-  if ((bdxtail != 0.0) || (bdytail != 0.0)
-      || (cdxtail != 0.0) || (cdytail != 0.0)) {
-    Square(adx, adxadx1, adxadx0);
-    Square(ady, adyady1, adyady0);
-    Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
-    aa[3] = aa3;
-  }
-  if ((cdxtail != 0.0) || (cdytail != 0.0)
-      || (adxtail != 0.0) || (adytail != 0.0)) {
-    Square(bdx, bdxbdx1, bdxbdx0);
-    Square(bdy, bdybdy1, bdybdy0);
-    Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
-    bb[3] = bb3;
-  }
-  if ((adxtail != 0.0) || (adytail != 0.0)
-      || (bdxtail != 0.0) || (bdytail != 0.0)) {
-    Square(cdx, cdxcdx1, cdxcdx0);
-    Square(cdy, cdycdy1, cdycdy0);
-    Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
-    cc[3] = cc3;
-  }
-
-  if (adxtail != 0.0) {
-    axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
-    temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
-                                          temp16a);
-
-    axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
-    temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
-
-    axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
-    temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (adytail != 0.0) {
-    aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
-    temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
-                                          temp16a);
-
-    aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
-    temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
-
-    aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
-    temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (bdxtail != 0.0) {
-    bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
-    temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
-                                          temp16a);
-
-    bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
-    temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
-
-    bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
-    temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (bdytail != 0.0) {
-    bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
-    temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
-                                          temp16a);
-
-    bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
-    temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
-
-    bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
-    temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (cdxtail != 0.0) {
-    cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
-    temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
-                                          temp16a);
-
-    cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
-    temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
-
-    cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
-    temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-  if (cdytail != 0.0) {
-    cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
-    temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
-                                          temp16a);
-
-    cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
-    temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
-
-    cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
-    temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
-
-    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                            temp16blen, temp16b, temp32a);
-    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
-                                            temp32alen, temp32a, temp48);
-    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                            temp48, finother);
-    finswap = finnow; finnow = finother; finother = finswap;
-  }
-
-  if ((adxtail != 0.0) || (adytail != 0.0)) {
-    if ((bdxtail != 0.0) || (bdytail != 0.0)
-        || (cdxtail != 0.0) || (cdytail != 0.0)) {
-      Two_Product(bdxtail, cdy, ti1, ti0);
-      Two_Product(bdx, cdytail, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      negate = -bdy;
-      Two_Product(cdxtail, negate, ti1, ti0);
-      negate = -bdytail;
-      Two_Product(cdx, negate, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
-      v[3] = v3;
-      bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
-
-      Two_Product(bdxtail, cdytail, ti1, ti0);
-      Two_Product(cdxtail, bdytail, tj1, tj0);
-      Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
-      bctt[3] = bctt3;
-      bcttlen = 4;
-    } else {
-      bct[0] = 0.0;
-      bctlen = 1;
-      bctt[0] = 0.0;
-      bcttlen = 1;
-    }
-
-    if (adxtail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
-      axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
-      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (bdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-      if (cdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-
-      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
-                                            temp32a);
-      axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
-      temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-    if (adytail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
-      aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
-      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-
-
-      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
-                                            temp32a);
-      aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
-      temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-  }
-  if ((bdxtail != 0.0) || (bdytail != 0.0)) {
-    if ((cdxtail != 0.0) || (cdytail != 0.0)
-        || (adxtail != 0.0) || (adytail != 0.0)) {
-      Two_Product(cdxtail, ady, ti1, ti0);
-      Two_Product(cdx, adytail, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      negate = -cdy;
-      Two_Product(adxtail, negate, ti1, ti0);
-      negate = -cdytail;
-      Two_Product(adx, negate, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
-      v[3] = v3;
-      catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
-
-      Two_Product(cdxtail, adytail, ti1, ti0);
-      Two_Product(adxtail, cdytail, tj1, tj0);
-      Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
-      catt[3] = catt3;
-      cattlen = 4;
-    } else {
-      cat[0] = 0.0;
-      catlen = 1;
-      catt[0] = 0.0;
-      cattlen = 1;
-    }
-
-    if (bdxtail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
-      bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
-      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (cdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-      if (adytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-
-      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
-                                            temp32a);
-      bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
-      temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-    if (bdytail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
-      bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
-      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-
-
-      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
-                                            temp32a);
-      bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
-      temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-  }
-  if ((cdxtail != 0.0) || (cdytail != 0.0)) {
-    if ((adxtail != 0.0) || (adytail != 0.0)
-        || (bdxtail != 0.0) || (bdytail != 0.0)) {
-      Two_Product(adxtail, bdy, ti1, ti0);
-      Two_Product(adx, bdytail, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
-      u[3] = u3;
-      negate = -ady;
-      Two_Product(bdxtail, negate, ti1, ti0);
-      negate = -adytail;
-      Two_Product(bdx, negate, tj1, tj0);
-      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
-      v[3] = v3;
-      abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
-
-      Two_Product(adxtail, bdytail, ti1, ti0);
-      Two_Product(bdxtail, adytail, tj1, tj0);
-      Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
-      abtt[3] = abtt3;
-      abttlen = 4;
-    } else {
-      abt[0] = 0.0;
-      abtlen = 1;
-      abtt[0] = 0.0;
-      abttlen = 1;
-    }
-
-    if (cdxtail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
-      cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
-      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-      if (adytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-      if (bdytail != 0.0) {
-        temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
-        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
-                                              temp16a);
-        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
-                                                temp16a, finother);
-        finswap = finnow; finnow = finother; finother = finswap;
-      }
-
-      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
-                                            temp32a);
-      cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
-      temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-    if (cdytail != 0.0) {
-      temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
-      cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
-      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
-                                            temp32a);
-      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp32alen, temp32a, temp48);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
-                                              temp48, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-
-
-      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
-                                            temp32a);
-      cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
-      temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
-                                            temp16a);
-      temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
-                                            temp16b);
-      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
-                                              temp16blen, temp16b, temp32b);
-      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
-                                              temp32blen, temp32b, temp64);
-      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
-                                              temp64, finother);
-      finswap = finnow; finnow = finother; finother = finswap;
-    }
-  }
-
-  return finnow[finlength - 1];
-}
-
-REAL incircle(pa, pb, pc, pd)
-point pa;
-point pb;
-point pc;
-point pd;
-{
-  REAL adx, bdx, cdx, ady, bdy, cdy;
-  REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
-  REAL alift, blift, clift;
-  REAL det;
-  REAL permanent, errbound;
-
-  incirclecount++;
-
-  adx = pa[0] - pd[0];
-  bdx = pb[0] - pd[0];
-  cdx = pc[0] - pd[0];
-  ady = pa[1] - pd[1];
-  bdy = pb[1] - pd[1];
-  cdy = pc[1] - pd[1];
-
-  bdxcdy = bdx * cdy;
-  cdxbdy = cdx * bdy;
-  alift = adx * adx + ady * ady;
-
-  cdxady = cdx * ady;
-  adxcdy = adx * cdy;
-  blift = bdx * bdx + bdy * bdy;
-
-  adxbdy = adx * bdy;
-  bdxady = bdx * ady;
-  clift = cdx * cdx + cdy * cdy;
-
-  det = alift * (bdxcdy - cdxbdy)
-      + blift * (cdxady - adxcdy)
-      + clift * (adxbdy - bdxady);
-
-  if (noexact) {
-    return det;
-  }
-
-  permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
-            + (Absolute(cdxady) + Absolute(adxcdy)) * blift
-            + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
-  errbound = iccerrboundA * permanent;
-  if ((det > errbound) || (-det > errbound)) {
-    return det;
-  }
-
-  return incircleadapt(pa, pb, pc, pd, permanent);
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Determinant evaluation routines end here                  *********/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangleinit()   Initialize some variables.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-void triangleinit()
-{
-  points.maxitems = triangles.maxitems = shelles.maxitems = viri.maxitems =
-    badsegments.maxitems = badtriangles.maxitems = splaynodes.maxitems = 0l;
-  points.itembytes = triangles.itembytes = shelles.itembytes = viri.itembytes =
-    badsegments.itembytes = badtriangles.itembytes = splaynodes.itembytes = 0;
-  recenttri.tri = (triangle *) NULL;    /* No triangle has been visited yet. */
-  samples = 1;            /* Point location should take at least one sample. */
-  checksegments = 0;      /* There are no segments in the triangulation yet. */
-  incirclecount = counterclockcount = hyperbolacount = 0;
-  circumcentercount = circletopcount = 0;
-  randomseed = 1;
-
-  exactinit();                     /* Initialize exact arithmetic constants. */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  randomnation()   Generate a random number between 0 and `choices' - 1.   */
-/*                                                                           */
-/*  This is a simple linear congruential random number generator.  Hence, it */
-/*  is a bad random number generator, but good enough for most randomized    */
-/*  geometric algorithms.                                                    */
-/*                                                                           */
-/*****************************************************************************/
-
-unsigned long randomnation(choices)
-unsigned int choices;
-{
-  randomseed = (randomseed * 1366l + 150889l) % 714025l;
-  return randomseed / (714025l / choices + 1);
-}
-
-/********* Mesh quality testing routines begin here                  *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  checkmesh()   Test the mesh for topological consistency.                 */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef REDUCED
-
-void checkmesh()
-{
-  struct triedge triangleloop;
-  struct triedge oppotri, oppooppotri;
-  point triorg, tridest, triapex;
-  point oppoorg, oppodest;
-  int horrors;
-  int saveexact;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  /* Temporarily turn on exact arithmetic if it's off. */
-  saveexact = noexact;
-  noexact = 0;
-  if (!quiet) {
-    printf("  Checking consistency of mesh...\n");
-  }
-  horrors = 0;
-  /* Run through the list of triangles, checking each one. */
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  while (triangleloop.tri != (triangle *) NULL) {
-    /* Check all three edges of the triangle. */
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      org(triangleloop, triorg);
-      dest(triangleloop, tridest);
-      if (triangleloop.orient == 0) {       /* Only test for inversion once. */
-        /* Test if the triangle is flat or inverted. */
-        apex(triangleloop, triapex);
-        if (counterclockwise(triorg, tridest, triapex) <= 0.0) {
-          printf("  !! !! Inverted ");
-          printtriangle(&triangleloop);
-          horrors++;
-        }
-      }
-      /* Find the neighboring triangle on this edge. */
-      sym(triangleloop, oppotri);
-      if (oppotri.tri != dummytri) {
-        /* Check that the triangle's neighbor knows it's a neighbor. */
-        sym(oppotri, oppooppotri);
-        if ((triangleloop.tri != oppooppotri.tri)
-            || (triangleloop.orient != oppooppotri.orient)) {
-          printf("  !! !! Asymmetric triangle-triangle bond:\n");
-          if (triangleloop.tri == oppooppotri.tri) {
-            printf("   (Right triangle, wrong orientation)\n");
-          }
-          printf("    First ");
-          printtriangle(&triangleloop);
-          printf("    Second (nonreciprocating) ");
-          printtriangle(&oppotri);
-          horrors++;
-        }
-        /* Check that both triangles agree on the identities */
-        /*   of their shared vertices.                       */
-        org(oppotri, oppoorg);
-        dest(oppotri, oppodest);
-        if ((triorg != oppodest) || (tridest != oppoorg)) {
-          printf("  !! !! Mismatched edge coordinates between two triangles:\n"
-                 );
-          printf("    First mismatched ");
-          printtriangle(&triangleloop);
-          printf("    Second mismatched ");
-          printtriangle(&oppotri);
-          horrors++;
-        }
-      }
-    }
-    triangleloop.tri = triangletraverse();
-  }
-  if (horrors == 0) {
-    if (!quiet) {
-      printf("  In my studied opinion, the mesh appears to be consistent.\n");
-    }
-  } else if (horrors == 1) {
-    printf("  !! !! !! !! Precisely one festering wound discovered.\n");
-  } else {
-    printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
-  }
-  /* Restore the status of exact arithmetic. */
-  noexact = saveexact;
-}
-
-#endif /* not REDUCED */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  checkdelaunay()   Ensure that the mesh is (constrained) Delaunay.        */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef REDUCED
-
-void checkdelaunay()
-{
-  struct triedge triangleloop;
-  struct triedge oppotri;
-  struct edge opposhelle;
-  point triorg, tridest, triapex;
-  point oppoapex;
-  int shouldbedelaunay;
-  int horrors;
-  int saveexact;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  /* Temporarily turn on exact arithmetic if it's off. */
-  saveexact = noexact;
-  noexact = 0;
-  if (!quiet) {
-    printf("  Checking Delaunay property of mesh...\n");
-  }
-  horrors = 0;
-  /* Run through the list of triangles, checking each one. */
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  while (triangleloop.tri != (triangle *) NULL) {
-    /* Check all three edges of the triangle. */
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      org(triangleloop, triorg);
-      dest(triangleloop, tridest);
-      apex(triangleloop, triapex);
-      sym(triangleloop, oppotri);
-      apex(oppotri, oppoapex);
-      /* Only test that the edge is locally Delaunay if there is an   */
-      /*   adjoining triangle whose pointer is larger (to ensure that */
-      /*   each pair isn't tested twice).                             */
-      shouldbedelaunay = (oppotri.tri != dummytri)
-            && (triapex != (point) NULL) && (oppoapex != (point) NULL)
-            && (triangleloop.tri < oppotri.tri);
-      if (checksegments && shouldbedelaunay) {
-        /* If a shell edge separates the triangles, then the edge is */
-        /*   constrained, so no local Delaunay test should be done.  */
-        tspivot(triangleloop, opposhelle);
-        if (opposhelle.sh != dummysh){
-          shouldbedelaunay = 0;
-        }
-      }
-      if (shouldbedelaunay) {
-        if (incircle(triorg, tridest, triapex, oppoapex) > 0.0) {
-          printf("  !! !! Non-Delaunay pair of triangles:\n");
-          printf("    First non-Delaunay ");
-          printtriangle(&triangleloop);
-          printf("    Second non-Delaunay ");
-          printtriangle(&oppotri);
-          horrors++;
-        }
-      }
-    }
-    triangleloop.tri = triangletraverse();
-  }
-  if (horrors == 0) {
-    if (!quiet) {
-      printf(
-  "  By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
-    }
-  } else if (horrors == 1) {
-    printf(
-         "  !! !! !! !! Precisely one terrifying transgression identified.\n");
-  } else {
-    printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
-  }
-  /* Restore the status of exact arithmetic. */
-  noexact = saveexact;
-}
-
-#endif /* not REDUCED */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  enqueuebadtri()   Add a bad triangle to the end of a queue.              */
-/*                                                                           */
-/*  The queue is actually a set of 64 queues.  I use multiple queues to give */
-/*  priority to smaller angles.  I originally implemented a heap, but the    */
-/*  queues are (to my surprise) much faster.                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void enqueuebadtri(instri, angle, insapex, insorg, insdest)
-struct triedge *instri;
-REAL angle;
-point insapex;
-point insorg;
-point insdest;
-{
-  struct badface *newface;
-  int queuenumber;
-
-  if (verbose > 2) {
-    printf("  Queueing bad triangle:\n");
-    printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", insorg[0],
-           insorg[1], insdest[0], insdest[1], insapex[0], insapex[1]);
-  }
-  /* Allocate space for the bad triangle. */
-  newface = (struct badface *) poolalloc(&badtriangles);
-  triedgecopy(*instri, newface->badfacetri);
-  newface->key = angle;
-  newface->faceapex = insapex;
-  newface->faceorg = insorg;
-  newface->facedest = insdest;
-  newface->nextface = (struct badface *) NULL;
-  /* Determine the appropriate queue to put the bad triangle into. */
-  if (angle > 0.6) {
-    queuenumber = (int) (160.0 * (angle - 0.6));
-    if (queuenumber > 63) {
-      queuenumber = 63;
-    }
-  } else {
-    /* It's not a bad angle; put the triangle in the lowest-priority queue. */
-    queuenumber = 0;
-  }
-  /* Add the triangle to the end of a queue. */
-  *queuetail[queuenumber] = newface;
-  /* Maintain a pointer to the NULL pointer at the end of the queue. */
-  queuetail[queuenumber] = &newface->nextface;
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  dequeuebadtri()   Remove a triangle from the front of the queue.         */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-struct badface *dequeuebadtri()
-{
-  struct badface *result;
-  int queuenumber;
-
-  /* Look for a nonempty queue. */
-  for (queuenumber = 63; queuenumber >= 0; queuenumber--) {
-    result = queuefront[queuenumber];
-    if (result != (struct badface *) NULL) {
-      /* Remove the triangle from the queue. */
-      queuefront[queuenumber] = result->nextface;
-      /* Maintain a pointer to the NULL pointer at the end of the queue. */
-      if (queuefront[queuenumber] == (struct badface *) NULL) {
-        queuetail[queuenumber] = &queuefront[queuenumber];
-      }
-      return result;
-    }
-  }
-  return (struct badface *) NULL;
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  checkedge4encroach()   Check a segment to see if it is encroached; add   */
-/*                         it to the list if it is.                          */
-/*                                                                           */
-/*  An encroached segment is an unflippable edge that has a point in its     */
-/*  diametral circle (that is, it faces an angle greater than 90 degrees).   */
-/*  This definition is due to Ruppert.                                       */
-/*                                                                           */
-/*  Returns a nonzero value if the edge is encroached.                       */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-int checkedge4encroach(testedge)
-struct edge *testedge;
-{
-  struct triedge neighbortri;
-  struct edge testsym;
-  struct edge *badedge;
-  int addtolist;
-  int sides;
-  point eorg, edest, eapex;
-  triangle ptr;                     /* Temporary variable used by stpivot(). */
-
-  addtolist = 0;
-  sides = 0;
-
-  sorg(*testedge, eorg);
-  sdest(*testedge, edest);
-  /* Check one neighbor of the shell edge. */
-  stpivot(*testedge, neighbortri);
-  /* Does the neighbor exist, or is this a boundary edge? */
-  if (neighbortri.tri != dummytri) {
-    sides++;
-    /* Find a vertex opposite this edge. */
-    apex(neighbortri, eapex);
-    /* Check whether the vertex is inside the diametral circle of the  */
-    /*   shell edge.  Pythagoras' Theorem is used to check whether the */
-    /*   angle at the vertex is greater than 90 degrees.               */
-    if (eapex[0] * (eorg[0] + edest[0]) + eapex[1] * (eorg[1] + edest[1]) >
-        eapex[0] * eapex[0] + eorg[0] * edest[0] +
-        eapex[1] * eapex[1] + eorg[1] * edest[1]) {
-      addtolist = 1;
-    }
-  }
-  /* Check the other neighbor of the shell edge. */
-  ssym(*testedge, testsym);
-  stpivot(testsym, neighbortri);
-  /* Does the neighbor exist, or is this a boundary edge? */
-  if (neighbortri.tri != dummytri) {
-    sides++;
-    /* Find the other vertex opposite this edge. */
-    apex(neighbortri, eapex);
-    /* Check whether the vertex is inside the diametral circle of the  */
-    /*   shell edge.  Pythagoras' Theorem is used to check whether the */
-    /*   angle at the vertex is greater than 90 degrees.               */
-    if (eapex[0] * (eorg[0] + edest[0]) +
-        eapex[1] * (eorg[1] + edest[1]) >
-        eapex[0] * eapex[0] + eorg[0] * edest[0] +
-        eapex[1] * eapex[1] + eorg[1] * edest[1]) {
-      addtolist += 2;
-    }
-  }
-
-  if (addtolist && (!nobisect || ((nobisect == 1) && (sides == 2)))) {
-    if (verbose > 2) {
-      printf("  Queueing encroached segment (%.12g, %.12g) (%.12g, %.12g).\n",
-             eorg[0], eorg[1], edest[0], edest[1]);
-    }
-    /* Add the shell edge to the list of encroached segments. */
-    /*   Be sure to get the orientation right.                */
-    badedge = (struct edge *) poolalloc(&badsegments);
-    if (addtolist == 1) {
-      shellecopy(*testedge, *badedge);
-    } else {
-      shellecopy(testsym, *badedge);
-    }
-  }
-  return addtolist;
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  testtriangle()   Test a face for quality measures.                       */
-/*                                                                           */
-/*  Tests a triangle to see if it satisfies the minimum angle condition and  */
-/*  the maximum area condition.  Triangles that aren't up to spec are added  */
-/*  to the bad triangle queue.                                               */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void testtriangle(testtri)
-struct triedge *testtri;
-{
-  struct triedge sametesttri;
-  struct edge edge1, edge2;
-  point torg, tdest, tapex;
-  point anglevertex;
-  REAL dxod, dyod, dxda, dyda, dxao, dyao;
-  REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
-  REAL apexlen, orglen, destlen;
-  REAL angle;
-  REAL area;
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  org(*testtri, torg);
-  dest(*testtri, tdest);
-  apex(*testtri, tapex);
-  dxod = torg[0] - tdest[0];
-  dyod = torg[1] - tdest[1];
-  dxda = tdest[0] - tapex[0];
-  dyda = tdest[1] - tapex[1];
-  dxao = tapex[0] - torg[0];
-  dyao = tapex[1] - torg[1];
-  dxod2 = dxod * dxod;
-  dyod2 = dyod * dyod;
-  dxda2 = dxda * dxda;
-  dyda2 = dyda * dyda;
-  dxao2 = dxao * dxao;
-  dyao2 = dyao * dyao;
-  /* Find the lengths of the triangle's three edges. */
-  apexlen = dxod2 + dyod2;
-  orglen = dxda2 + dyda2;
-  destlen = dxao2 + dyao2;
-  if ((apexlen < orglen) && (apexlen < destlen)) {
-    /* The edge opposite the apex is shortest. */
-    /* Find the square of the cosine of the angle at the apex. */
-    angle = dxda * dxao + dyda * dyao;
-    angle = angle * angle / (orglen * destlen);
-    anglevertex = tapex;
-    lnext(*testtri, sametesttri);
-    tspivot(sametesttri, edge1);
-    lnextself(sametesttri);
-    tspivot(sametesttri, edge2);
-  } else if (orglen < destlen) {
-    /* The edge opposite the origin is shortest. */
-    /* Find the square of the cosine of the angle at the origin. */
-    angle = dxod * dxao + dyod * dyao;
-    angle = angle * angle / (apexlen * destlen);
-    anglevertex = torg;
-    tspivot(*testtri, edge1);
-    lprev(*testtri, sametesttri);
-    tspivot(sametesttri, edge2);
-  } else {
-    /* The edge opposite the destination is shortest. */
-    /* Find the square of the cosine of the angle at the destination. */
-    angle = dxod * dxda + dyod * dyda;
-    angle = angle * angle / (apexlen * orglen);
-    anglevertex = tdest;
-    tspivot(*testtri, edge1);
-    lnext(*testtri, sametesttri);
-    tspivot(sametesttri, edge2);
-  }
-  /* Check if both edges that form the angle are segments. */
-  if ((edge1.sh != dummysh) && (edge2.sh != dummysh)) {
-    /* The angle is a segment intersection. */
-    if ((angle > 0.9924) && !quiet) {                  /* Roughly 5 degrees. */
-      if (angle > 1.0) {
-        /* Beware of a floating exception in acos(). */
-        angle = 1.0;
-      }
-      /* Find the actual angle in degrees, for printing. */
-      angle = acos(sqrt(angle)) * (180.0 / PI);
-      printf(
-      "Warning:  Small angle (%.4g degrees) between segments at point\n",
-             angle);
-      printf("  (%.12g, %.12g)\n", anglevertex[0], anglevertex[1]);
-    }
-    /* Don't add this bad triangle to the list; there's nothing that */
-    /*   can be done about a small angle between two segments.       */
-    angle = 0.0;
-  }
-  /* Check whether the angle is smaller than permitted. */
-  if (angle > goodangle) {
-    /* Add this triangle to the list of bad triangles. */
-    enqueuebadtri(testtri, angle, tapex, torg, tdest);
-    return;
-  }
-  if (vararea || fixedarea) {
-    /* Check whether the area is larger than permitted. */
-    area = 0.5 * (dxod * dyda - dyod * dxda);
-    if (fixedarea && (area > maxarea)) {
-      /* Add this triangle to the list of bad triangles. */
-      enqueuebadtri(testtri, angle, tapex, torg, tdest);
-    } else if (vararea) {
-      /* Nonpositive area constraints are treated as unconstrained. */
-      if ((area > areabound(*testtri)) && (areabound(*testtri) > 0.0)) {
-        /* Add this triangle to the list of bad triangles. */
-        enqueuebadtri(testtri, angle, tapex, torg, tdest);
-      }
-    }
-  }
-}
-
-#endif /* not CDT_ONLY */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Mesh quality testing routines end here                    *********/
-
-/********* Point location routines begin here                        *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  makepointmap()   Construct a mapping from points to triangles to improve  */
-/*                  the speed of point location for segment insertion.       */
-/*                                                                           */
-/*  Traverses all the triangles, and provides each corner of each triangle   */
-/*  with a pointer to that triangle.  Of course, pointers will be            */
-/*  overwritten by other pointers because (almost) each point is a corner    */
-/*  of several triangles, but in the end every point will point to some      */
-/*  triangle that contains it.                                               */
-/*                                                                           */
-/*****************************************************************************/
-
-void makepointmap()
-{
-  struct triedge triangleloop;
-  point triorg;
-
-  if (verbose) {
-    printf("    Constructing mapping from points to triangles.\n");
-  }
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  while (triangleloop.tri != (triangle *) NULL) {
-    /* Check all three points of the triangle. */
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      org(triangleloop, triorg);
-      setpoint2tri(triorg, encode(triangleloop));
-    }
-    triangleloop.tri = triangletraverse();
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  preciselocate()   Find a triangle or edge containing a given point.      */
-/*                                                                           */
-/*  Begins its search from `searchtri'.  It is important that `searchtri'    */
-/*  be a handle with the property that `searchpoint' is strictly to the left */
-/*  of the edge denoted by `searchtri', or is collinear with that edge and   */
-/*  does not intersect that edge.  (In particular, `searchpoint' should not  */
-/*  be the origin or destination of that edge.)                              */
-/*                                                                           */
-/*  These conditions are imposed because preciselocate() is normally used in */
-/*  one of two situations:                                                   */
-/*                                                                           */
-/*  (1)  To try to find the location to insert a new point.  Normally, we    */
-/*       know an edge that the point is strictly to the left of.  In the     */
-/*       incremental Delaunay algorithm, that edge is a bounding box edge.   */
-/*       In Ruppert's Delaunay refinement algorithm for quality meshing,     */
-/*       that edge is the shortest edge of the triangle whose circumcenter   */
-/*       is being inserted.                                                  */
-/*                                                                           */
-/*  (2)  To try to find an existing point.  In this case, any edge on the    */
-/*       convex hull is a good starting edge.  The possibility that the      */
-/*       vertex one seeks is an endpoint of the starting edge must be        */
-/*       screened out before preciselocate() is called.                      */
-/*                                                                           */
-/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
-/*                                                                           */
-/*  This implementation differs from that given by Guibas and Stolfi.  It    */
-/*  walks from triangle to triangle, crossing an edge only if `searchpoint'  */
-/*  is on the other side of the line containing that edge.  After entering   */
-/*  a triangle, there are two edges by which one can leave that triangle.    */
-/*  If both edges are valid (`searchpoint' is on the other side of both      */
-/*  edges), one of the two is chosen by drawing a line perpendicular to      */
-/*  the entry edge (whose endpoints are `forg' and `fdest') passing through  */
-/*  `fapex'.  Depending on which side of this perpendicular `searchpoint'    */
-/*  falls on, an exit edge is chosen.                                        */
-/*                                                                           */
-/*  This implementation is empirically faster than the Guibas and Stolfi     */
-/*  point location routine (which I originally used), which tends to spiral  */
-/*  in toward its target.                                                    */
-/*                                                                           */
-/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
-/*  is a handle whose origin is the existing vertex.                         */
-/*                                                                           */
-/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
-/*  handle whose primary edge is the edge on which the point lies.           */
-/*                                                                           */
-/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
-/*  `searchtri' is a handle on the triangle that contains the point.         */
-/*                                                                           */
-/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
-/*  handle whose primary edge the point is to the right of.  This might      */
-/*  occur when the circumcenter of a triangle falls just slightly outside    */
-/*  the mesh due to floating-point roundoff error.  It also occurs when      */
-/*  seeking a hole or region point that a foolish user has placed outside    */
-/*  the mesh.                                                                */
-/*                                                                           */
-/*  WARNING:  This routine is designed for convex triangulations, and will   */
-/*  not generally work after the holes and concavities have been carved.     */
-/*  However, it can still be used to find the circumcenter of a triangle, as */
-/*  long as the search is begun from the triangle in question.               */
-/*                                                                           */
-/*****************************************************************************/
-
-enum locateresult preciselocate(searchpoint, searchtri)
-point searchpoint;
-struct triedge *searchtri;
-{
-  struct triedge backtracktri;
-  point forg, fdest, fapex;
-  point swappoint;
-  REAL orgorient, destorient;
-  int moveleft;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose > 2) {
-    printf("  Searching for point (%.12g, %.12g).\n",
-           searchpoint[0], searchpoint[1]);
-  }
-  /* Where are we? */
-  org(*searchtri, forg);
-  dest(*searchtri, fdest);
-  apex(*searchtri, fapex);
-  while (1) {
-    if (verbose > 2) {
-      printf("    At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-             forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
-    }
-    /* Check whether the apex is the point we seek. */
-    if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
-      lprevself(*searchtri);
-      return ONVERTEX;
-    }
-    /* Does the point lie on the other side of the line defined by the */
-    /*   triangle edge opposite the triangle's destination?            */
-    destorient = counterclockwise(forg, fapex, searchpoint);
-    /* Does the point lie on the other side of the line defined by the */
-    /*   triangle edge opposite the triangle's origin?                 */
-    orgorient = counterclockwise(fapex, fdest, searchpoint);
-    if (destorient > 0.0) {
-      if (orgorient > 0.0) {
-        /* Move left if the inner product of (fapex - searchpoint) and  */
-        /*   (fdest - forg) is positive.  This is equivalent to drawing */
-        /*   a line perpendicular to the line (forg, fdest) passing     */
-        /*   through `fapex', and determining which side of this line   */
-        /*   `searchpoint' falls on.                                    */
-        moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
-                   (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
-      } else {
-        moveleft = 1;
-      }
-    } else {
-      if (orgorient > 0.0) {
-        moveleft = 0;
-      } else {
-        /* The point we seek must be on the boundary of or inside this */
-        /*   triangle.                                                 */
-        if (destorient == 0.0) {
-          lprevself(*searchtri);
-          return ONEDGE;
-        }
-        if (orgorient == 0.0) {
-          lnextself(*searchtri);
-          return ONEDGE;
-        }
-        return INTRIANGLE;
-      }
-    }
-
-    /* Move to another triangle.  Leave a trace `backtracktri' in case */
-    /*   floating-point roundoff or some such bogey causes us to walk  */
-    /*   off a boundary of the triangulation.  We can just bounce off  */
-    /*   the boundary as if it were an elastic band.                   */
-    if (moveleft) {
-      lprev(*searchtri, backtracktri);
-      fdest = fapex;
-    } else {
-      lnext(*searchtri, backtracktri);
-      forg = fapex;
-    }
-    sym(backtracktri, *searchtri);
-
-    /* Check for walking off the edge. */
-    if (searchtri->tri == dummytri) {
-      /* Turn around. */
-      triedgecopy(backtracktri, *searchtri);
-      swappoint = forg;
-      forg = fdest;
-      fdest = swappoint;
-      apex(*searchtri, fapex);
-      /* Check if the point really is beyond the triangulation boundary. */
-      destorient = counterclockwise(forg, fapex, searchpoint);
-      orgorient = counterclockwise(fapex, fdest, searchpoint);
-      if ((orgorient < 0.0) && (destorient < 0.0)) {
-        return OUTSIDE;
-      }
-    } else {
-      apex(*searchtri, fapex);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  locate()   Find a triangle or edge containing a given point.             */
-/*                                                                           */
-/*  Searching begins from one of:  the input `searchtri', a recently         */
-/*  encountered triangle `recenttri', or from a triangle chosen from a       */
-/*  random sample.  The choice is made by determining which triangle's       */
-/*  origin is closest to the point we are searcing for.  Normally,           */
-/*  `searchtri' should be a handle on the convex hull of the triangulation.  */
-/*                                                                           */
-/*  Details on the random sampling method can be found in the Mucke, Saias,  */
-/*  and Zhu paper cited in the header of this code.                          */
-/*                                                                           */
-/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
-/*                                                                           */
-/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
-/*  is a handle whose origin is the existing vertex.                         */
-/*                                                                           */
-/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
-/*  handle whose primary edge is the edge on which the point lies.           */
-/*                                                                           */
-/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
-/*  `searchtri' is a handle on the triangle that contains the point.         */
-/*                                                                           */
-/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
-/*  handle whose primary edge the point is to the right of.  This might      */
-/*  occur when the circumcenter of a triangle falls just slightly outside    */
-/*  the mesh due to floating-point roundoff error.  It also occurs when      */
-/*  seeking a hole or region point that a foolish user has placed outside    */
-/*  the mesh.                                                                */
-/*                                                                           */
-/*  WARNING:  This routine is designed for convex triangulations, and will   */
-/*  not generally work after the holes and concavities have been carved.     */
-/*                                                                           */
-/*****************************************************************************/
-
-enum locateresult locate(searchpoint, searchtri)
-point searchpoint;
-struct triedge *searchtri;
-{
-  VOID **sampleblock;
-  triangle *firsttri;
-  struct triedge sampletri;
-  point torg, tdest;
-  unsigned long alignptr;
-  REAL searchdist, dist;
-  REAL ahead;
-  long sampleblocks, samplesperblock, samplenum;
-  long triblocks;
-  long i, j;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose > 2) {
-    printf("  Randomly sampling for a triangle near point (%.12g, %.12g).\n",
-           searchpoint[0], searchpoint[1]);
-  }
-  /* Record the distance from the suggested starting triangle to the */
-  /*   point we seek.                                                */
-  org(*searchtri, torg);
-  searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
-             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
-  if (verbose > 2) {
-    printf("    Boundary triangle has origin (%.12g, %.12g).\n",
-           torg[0], torg[1]);
-  }
-
-  /* If a recently encountered triangle has been recorded and has not been */
-  /*   deallocated, test it as a good starting point.                      */
-  if (recenttri.tri != (triangle *) NULL) {
-    if (recenttri.tri[3] != (triangle) NULL) {
-      org(recenttri, torg);
-      if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
-        triedgecopy(recenttri, *searchtri);
-        return ONVERTEX;
-      }
-      dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
-           + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
-      if (dist < searchdist) {
-        triedgecopy(recenttri, *searchtri);
-        searchdist = dist;
-        if (verbose > 2) {
-          printf("    Choosing recent triangle with origin (%.12g, %.12g).\n",
-                 torg[0], torg[1]);
-        }
-      }
-    }
-  }
-
-  /* The number of random samples taken is proportional to the cube root of */
-  /*   the number of triangles in the mesh.  The next bit of code assumes   */
-  /*   that the number of triangles increases monotonically.                */
-  while (SAMPLEFACTOR * samples * samples * samples < triangles.items) {
-    samples++;
-  }
-  triblocks = (triangles.maxitems + TRIPERBLOCK - 1) / TRIPERBLOCK;
-  samplesperblock = 1 + (samples / triblocks);
-  sampleblocks = samples / samplesperblock;
-  sampleblock = triangles.firstblock;
-  sampletri.orient = 0;
-  for (i = 0; i < sampleblocks; i++) {
-    alignptr = (unsigned long) (sampleblock + 1);
-    firsttri = (triangle *) (alignptr + (unsigned long) triangles.alignbytes
-                          - (alignptr % (unsigned long) triangles.alignbytes));
-    for (j = 0; j < samplesperblock; j++) {
-      if (i == triblocks - 1) {
-        samplenum = randomnation((int)
-                                 (triangles.maxitems - (i * TRIPERBLOCK)));
-      } else {
-        samplenum = randomnation(TRIPERBLOCK);
-      }
-      sampletri.tri = (triangle *)
-                      (firsttri + (samplenum * triangles.itemwords));
-      if (sampletri.tri[3] != (triangle) NULL) {
-        org(sampletri, torg);
-        dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
-             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
-        if (dist < searchdist) {
-          triedgecopy(sampletri, *searchtri);
-          searchdist = dist;
-          if (verbose > 2) {
-            printf("    Choosing triangle with origin (%.12g, %.12g).\n",
-                   torg[0], torg[1]);
-          }
-        }
-      }
-    }
-    sampleblock = (VOID **) *sampleblock;
-  }
-  /* Where are we? */
-  org(*searchtri, torg);
-  dest(*searchtri, tdest);
-  /* Check the starting triangle's vertices. */
-  if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
-    return ONVERTEX;
-  }
-  if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
-    lnextself(*searchtri);
-    return ONVERTEX;
-  }
-  /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
-  ahead = counterclockwise(torg, tdest, searchpoint);
-  if (ahead < 0.0) {
-    /* Turn around so that `searchpoint' is to the left of the */
-    /*   edge specified by `searchtri'.                        */
-    symself(*searchtri);
-  } else if (ahead == 0.0) {
-    /* Check if `searchpoint' is between `torg' and `tdest'. */
-    if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0]))
-        && ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
-      return ONEDGE;
-    }
-  }
-  return preciselocate(searchpoint, searchtri);
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Point location routines end here                          *********/
-
-/********* Mesh transformation routines begin here                   *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  insertshelle()   Create a new shell edge and insert it between two       */
-/*                   triangles.                                              */
-/*                                                                           */
-/*  The new shell edge is inserted at the edge described by the handle       */
-/*  `tri'.  Its vertices are properly initialized.  The marker `shellemark'  */
-/*  is applied to the shell edge and, if appropriate, its vertices.          */
-/*                                                                           */
-/*****************************************************************************/
-
-void insertshelle(tri, shellemark)
-struct triedge *tri;          /* Edge at which to insert the new shell edge. */
-int shellemark;                            /* Marker for the new shell edge. */
-{
-  struct triedge oppotri;
-  struct edge newshelle;
-  point triorg, tridest;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  /* Mark points if possible. */
-  org(*tri, triorg);
-  dest(*tri, tridest);
-  if (pointmark(triorg) == 0) {
-    setpointmark(triorg, shellemark);
-  }
-  if (pointmark(tridest) == 0) {
-    setpointmark(tridest, shellemark);
-  }
-  /* Check if there's already a shell edge here. */
-  tspivot(*tri, newshelle);
-  if (newshelle.sh == dummysh) {
-    /* Make new shell edge and initialize its vertices. */
-    makeshelle(&newshelle);
-    setsorg(newshelle, tridest);
-    setsdest(newshelle, triorg);
-    /* Bond new shell edge to the two triangles it is sandwiched between. */
-    /*   Note that the facing triangle `oppotri' might be equal to        */
-    /*   `dummytri' (outer space), but the new shell edge is bonded to it */
-    /*   all the same.                                                    */
-    tsbond(*tri, newshelle);
-    sym(*tri, oppotri);
-    ssymself(newshelle);
-    tsbond(oppotri, newshelle);
-    setmark(newshelle, shellemark);
-    if (verbose > 2) {
-      printf("  Inserting new ");
-      printshelle(&newshelle);
-    }
-  } else {
-    if (mark(newshelle) == 0) {
-      setmark(newshelle, shellemark);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  Terminology                                                              */
-/*                                                                           */
-/*  A "local transformation" replaces a small set of triangles with another  */
-/*  set of triangles.  This may or may not involve inserting or deleting a   */
-/*  point.                                                                   */
-/*                                                                           */
-/*  The term "casing" is used to describe the set of triangles that are      */
-/*  attached to the triangles being transformed, but are not transformed     */
-/*  themselves.  Think of the casing as a fixed hollow structure inside      */
-/*  which all the action happens.  A "casing" is only defined relative to    */
-/*  a single transformation; each occurrence of a transformation will        */
-/*  involve a different casing.                                              */
-/*                                                                           */
-/*  A "shell" is similar to a "casing".  The term "shell" describes the set  */
-/*  of shell edges (if any) that are attached to the triangles being         */
-/*  transformed.  However, I sometimes use "shell" to refer to a single      */
-/*  shell edge, so don't get confused.                                       */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  flip()   Transform two triangles to two different triangles by flipping  */
-/*           an edge within a quadrilateral.                                 */
-/*                                                                           */
-/*  Imagine the original triangles, abc and bad, oriented so that the        */
-/*  shared edge ab lies in a horizontal plane, with the point b on the left  */
-/*  and the point a on the right.  The point c lies below the edge, and the  */
-/*  point d lies above the edge.  The `flipedge' handle holds the edge ab    */
-/*  of triangle abc, and is directed left, from vertex a to vertex b.        */
-/*                                                                           */
-/*  The triangles abc and bad are deleted and replaced by the triangles cdb  */
-/*  and dca.  The triangles that represent abc and bad are NOT deallocated;  */
-/*  they are reused for dca and cdb, respectively.  Hence, any handles that  */
-/*  may have held the original triangles are still valid, although not       */
-/*  directed as they were before.                                            */
-/*                                                                           */
-/*  Upon completion of this routine, the `flipedge' handle holds the edge    */
-/*  dc of triangle dca, and is directed down, from vertex d to vertex c.     */
-/*  (Hence, the two triangles have rotated counterclockwise.)                */
-/*                                                                           */
-/*  WARNING:  This transformation is geometrically valid only if the         */
-/*  quadrilateral adbc is convex.  Furthermore, this transformation is       */
-/*  valid only if there is not a shell edge between the triangles abc and    */
-/*  bad.  This routine does not check either of these preconditions, and     */
-/*  it is the responsibility of the calling routine to ensure that they are  */
-/*  met.  If they are not, the streets shall be filled with wailing and      */
-/*  gnashing of teeth.                                                       */
-/*                                                                           */
-/*****************************************************************************/
-
-void flip(flipedge)
-struct triedge *flipedge;                    /* Handle for the triangle abc. */
-{
-  struct triedge botleft, botright;
-  struct triedge topleft, topright;
-  struct triedge top;
-  struct triedge botlcasing, botrcasing;
-  struct triedge toplcasing, toprcasing;
-  struct edge botlshelle, botrshelle;
-  struct edge toplshelle, toprshelle;
-  point leftpoint, rightpoint, botpoint;
-  point farpoint;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  /* Identify the vertices of the quadrilateral. */
-  org(*flipedge, rightpoint);
-  dest(*flipedge, leftpoint);
-  apex(*flipedge, botpoint);
-  sym(*flipedge, top);
-#ifdef SELF_CHECK
-  if (top.tri == dummytri) {
-    printf("Internal error in flip():  Attempt to flip on boundary.\n");
-    lnextself(*flipedge);
-    return;
-  }
-  if (checksegments) {
-    tspivot(*flipedge, toplshelle);
-    if (toplshelle.sh != dummysh) {
-      printf("Internal error in flip():  Attempt to flip a segment.\n");
-      lnextself(*flipedge);
-      return;
-    }
-  }
-#endif /* SELF_CHECK */
-  apex(top, farpoint);
-
-  /* Identify the casing of the quadrilateral. */
-  lprev(top, topleft);
-  sym(topleft, toplcasing);
-  lnext(top, topright);
-  sym(topright, toprcasing);
-  lnext(*flipedge, botleft);
-  sym(botleft, botlcasing);
-  lprev(*flipedge, botright);
-  sym(botright, botrcasing);
-  /* Rotate the quadrilateral one-quarter turn counterclockwise. */
-  bond(topleft, botlcasing);
-  bond(botleft, botrcasing);
-  bond(botright, toprcasing);
-  bond(topright, toplcasing);
-
-  if (checksegments) {
-    /* Check for shell edges and rebond them to the quadrilateral. */
-    tspivot(topleft, toplshelle);
-    tspivot(botleft, botlshelle);
-    tspivot(botright, botrshelle);
-    tspivot(topright, toprshelle);
-    if (toplshelle.sh == dummysh) {
-      tsdissolve(topright);
-    } else {
-      tsbond(topright, toplshelle);
-    }
-    if (botlshelle.sh == dummysh) {
-      tsdissolve(topleft);
-    } else {
-      tsbond(topleft, botlshelle);
-    }
-    if (botrshelle.sh == dummysh) {
-      tsdissolve(botleft);
-    } else {
-      tsbond(botleft, botrshelle);
-    }
-    if (toprshelle.sh == dummysh) {
-      tsdissolve(botright);
-    } else {
-      tsbond(botright, toprshelle);
-    }
-  }
-
-  /* New point assignments for the rotated quadrilateral. */
-  setorg(*flipedge, farpoint);
-  setdest(*flipedge, botpoint);
-  setapex(*flipedge, rightpoint);
-  setorg(top, botpoint);
-  setdest(top, farpoint);
-  setapex(top, leftpoint);
-  if (verbose > 2) {
-    printf("  Edge flip results in left ");
-    lnextself(topleft);
-    printtriangle(&topleft);
-    printf("  and right ");
-    printtriangle(flipedge);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  insertsite()   Insert a vertex into a Delaunay triangulation,            */
-/*                 performing flips as necessary to maintain the Delaunay    */
-/*                 property.                                                 */
-/*                                                                           */
-/*  The point `insertpoint' is located.  If `searchtri.tri' is not NULL,     */
-/*  the search for the containing triangle begins from `searchtri'.  If      */
-/*  `searchtri.tri' is NULL, a full point location procedure is called.      */
-/*  If `insertpoint' is found inside a triangle, the triangle is split into  */
-/*  three; if `insertpoint' lies on an edge, the edge is split in two,       */
-/*  thereby splitting the two adjacent triangles into four.  Edge flips are  */
-/*  used to restore the Delaunay property.  If `insertpoint' lies on an      */
-/*  existing vertex, no action is taken, and the value DUPLICATEPOINT is     */
-/*  returned.  On return, `searchtri' is set to a handle whose origin is the */
-/*  existing vertex.                                                         */
-/*                                                                           */
-/*  Normally, the parameter `splitedge' is set to NULL, implying that no     */
-/*  segment should be split.  In this case, if `insertpoint' is found to     */
-/*  lie on a segment, no action is taken, and the value VIOLATINGPOINT is    */
-/*  returned.  On return, `searchtri' is set to a handle whose primary edge  */
-/*  is the violated segment.                                                 */
-/*                                                                           */
-/*  If the calling routine wishes to split a segment by inserting a point in */
-/*  it, the parameter `splitedge' should be that segment.  In this case,     */
-/*  `searchtri' MUST be the triangle handle reached by pivoting from that    */
-/*  segment; no point location is done.                                      */
-/*                                                                           */
-/*  `segmentflaws' and `triflaws' are flags that indicate whether or not     */
-/*  there should be checks for the creation of encroached segments or bad    */
-/*  quality faces.  If a newly inserted point encroaches upon segments,      */
-/*  these segments are added to the list of segments to be split if          */
-/*  `segmentflaws' is set.  If bad triangles are created, these are added    */
-/*  to the queue if `triflaws' is set.                                       */
-/*                                                                           */
-/*  If a duplicate point or violated segment does not prevent the point      */
-/*  from being inserted, the return value will be ENCROACHINGPOINT if the    */
-/*  point encroaches upon a segment (and checking is enabled), or            */
-/*  SUCCESSFULPOINT otherwise.  In either case, `searchtri' is set to a      */
-/*  handle whose origin is the newly inserted vertex.                        */
-/*                                                                           */
-/*  insertsite() does not use flip() for reasons of speed; some              */
-/*  information can be reused from edge flip to edge flip, like the          */
-/*  locations of shell edges.                                                */
-/*                                                                           */
-/*****************************************************************************/
-
-enum insertsiteresult insertsite(insertpoint, searchtri, splitedge,
-                                 segmentflaws, triflaws)
-point insertpoint;
-struct triedge *searchtri;
-struct edge *splitedge;
-int segmentflaws;
-int triflaws;
-{
-  struct triedge horiz;
-  struct triedge top;
-  struct triedge botleft, botright;
-  struct triedge topleft, topright;
-  struct triedge newbotleft, newbotright;
-  struct triedge newtopright;
-  struct triedge botlcasing, botrcasing;
-  struct triedge toplcasing, toprcasing;
-  struct triedge testtri;
-  struct edge botlshelle, botrshelle;
-  struct edge toplshelle, toprshelle;
-  struct edge brokenshelle;
-  struct edge checkshelle;
-  struct edge rightedge;
-  struct edge newedge;
-  struct edge *encroached;
-  point first;
-  point leftpoint, rightpoint, botpoint, toppoint, farpoint;
-  REAL attrib;
-  REAL area;
-  enum insertsiteresult success;
-  enum locateresult intersect;
-  int doflip;
-  int mirrorflag;
-  int i;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;         /* Temporary variable used by spivot() and tspivot(). */
-
-  if (verbose > 1) {
-    printf("  Inserting (%.12g, %.12g).\n", insertpoint[0], insertpoint[1]);
-  }
-  if (splitedge == (struct edge *) NULL) {
-    /* Find the location of the point to be inserted.  Check if a good */
-    /*   starting triangle has already been provided by the caller.    */
-    if (searchtri->tri == (triangle *) NULL) {
-      /* Find a boundary triangle. */
-      horiz.tri = dummytri;
-      horiz.orient = 0;
-      symself(horiz);
-      /* Search for a triangle containing `insertpoint'. */
-      intersect = locate(insertpoint, &horiz);
-    } else {
-      /* Start searching from the triangle provided by the caller. */
-      triedgecopy(*searchtri, horiz);
-      intersect = preciselocate(insertpoint, &horiz);
-    }
-  } else {
-    /* The calling routine provides the edge in which the point is inserted. */
-    triedgecopy(*searchtri, horiz);
-    intersect = ONEDGE;
-  }
-  if (intersect == ONVERTEX) {
-    /* There's already a vertex there.  Return in `searchtri' a triangle */
-    /*   whose origin is the existing vertex.                            */
-    triedgecopy(horiz, *searchtri);
-    triedgecopy(horiz, recenttri);
-    return DUPLICATEPOINT;
-  }
-  if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
-    /* The vertex falls on an edge or boundary. */
-    if (checksegments && (splitedge == (struct edge *) NULL)) {
-      /* Check whether the vertex falls on a shell edge. */
-      tspivot(horiz, brokenshelle);
-      if (brokenshelle.sh != dummysh) {
-        /* The vertex falls on a shell edge. */
-        if (segmentflaws) {
-          if (nobisect == 0) {
-            /* Add the shell edge to the list of encroached segments. */
-            encroached = (struct edge *) poolalloc(&badsegments);
-            shellecopy(brokenshelle, *encroached);
-          } else if ((nobisect == 1) && (intersect == ONEDGE)) {
-            /* This segment may be split only if it is an internal boundary. */
-            sym(horiz, testtri);
-            if (testtri.tri != dummytri) {
-              /* Add the shell edge to the list of encroached segments. */
-              encroached = (struct edge *) poolalloc(&badsegments);
-              shellecopy(brokenshelle, *encroached);
-            }
-          }
-        }
-        /* Return a handle whose primary edge contains the point, */
-        /*   which has not been inserted.                         */
-        triedgecopy(horiz, *searchtri);
-        triedgecopy(horiz, recenttri);
-        return VIOLATINGPOINT;
-      }
-    }
-    /* Insert the point on an edge, dividing one triangle into two (if */
-    /*   the edge lies on a boundary) or two triangles into four.      */
-    lprev(horiz, botright);
-    sym(botright, botrcasing);
-    sym(horiz, topright);
-    /* Is there a second triangle?  (Or does this edge lie on a boundary?) */
-    mirrorflag = topright.tri != dummytri;
-    if (mirrorflag) {
-      lnextself(topright);
-      sym(topright, toprcasing);
-      maketriangle(&newtopright);
-    } else {
-      /* Splitting the boundary edge increases the number of boundary edges. */
-      hullsize++;
-    }
-    maketriangle(&newbotright);
-
-    /* Set the vertices of changed and new triangles. */
-    org(horiz, rightpoint);
-    dest(horiz, leftpoint);
-    apex(horiz, botpoint);
-    setorg(newbotright, botpoint);
-    setdest(newbotright, rightpoint);
-    setapex(newbotright, insertpoint);
-    setorg(horiz, insertpoint);
-    for (i = 0; i < eextras; i++) {
-      /* Set the element attributes of a new triangle. */
-      setelemattribute(newbotright, i, elemattribute(botright, i));
-    }
-    if (vararea) {
-      /* Set the area constraint of a new triangle. */
-      setareabound(newbotright, areabound(botright));
-    }
-    if (mirrorflag) {
-      dest(topright, toppoint);
-      setorg(newtopright, rightpoint);
-      setdest(newtopright, toppoint);
-      setapex(newtopright, insertpoint);
-      setorg(topright, insertpoint);
-      for (i = 0; i < eextras; i++) {
-        /* Set the element attributes of another new triangle. */
-        setelemattribute(newtopright, i, elemattribute(topright, i));
-      }
-      if (vararea) {
-        /* Set the area constraint of another new triangle. */
-        setareabound(newtopright, areabound(topright));
-      }
-    }
-
-    /* There may be shell edges that need to be bonded */
-    /*   to the new triangle(s).                       */
-    if (checksegments) {
-      tspivot(botright, botrshelle);
-      if (botrshelle.sh != dummysh) {
-        tsdissolve(botright);
-        tsbond(newbotright, botrshelle);
-      }
-      if (mirrorflag) {
-        tspivot(topright, toprshelle);
-        if (toprshelle.sh != dummysh) {
-          tsdissolve(topright);
-          tsbond(newtopright, toprshelle);
-        }
-      }
-    }
-
-    /* Bond the new triangle(s) to the surrounding triangles. */
-    bond(newbotright, botrcasing);
-    lprevself(newbotright);
-    bond(newbotright, botright);
-    lprevself(newbotright);
-    if (mirrorflag) {
-      bond(newtopright, toprcasing);
-      lnextself(newtopright);
-      bond(newtopright, topright);
-      lnextself(newtopright);
-      bond(newtopright, newbotright);
-    }
-
-    if (splitedge != (struct edge *) NULL) {
-      /* Split the shell edge into two. */
-      setsdest(*splitedge, insertpoint);
-      ssymself(*splitedge);
-      spivot(*splitedge, rightedge);
-      insertshelle(&newbotright, mark(*splitedge));
-      tspivot(newbotright, newedge);
-      sbond(*splitedge, newedge);
-      ssymself(newedge);
-      sbond(newedge, rightedge);
-      ssymself(*splitedge);
-    }
-
-#ifdef SELF_CHECK
-    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle prior to edge point insertion (bottom).\n");
-    }
-    if (mirrorflag) {
-      if (counterclockwise(leftpoint, rightpoint, toppoint) < 0.0) {
-        printf("Internal error in insertsite():\n");
-        printf("  Clockwise triangle prior to edge point insertion (top).\n");
-      }
-      if (counterclockwise(rightpoint, toppoint, insertpoint) < 0.0) {
-        printf("Internal error in insertsite():\n");
-        printf("  Clockwise triangle after edge point insertion (top right).\n"
-               );
-      }
-      if (counterclockwise(toppoint, leftpoint, insertpoint) < 0.0) {
-        printf("Internal error in insertsite():\n");
-        printf("  Clockwise triangle after edge point insertion (top left).\n"
-               );
-      }
-    }
-    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after edge point insertion (bottom left).\n"
-             );
-    }
-    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf(
-        "  Clockwise triangle after edge point insertion (bottom right).\n");
-    }
-#endif /* SELF_CHECK */
-    if (verbose > 2) {
-      printf("  Updating bottom left ");
-      printtriangle(&botright);
-      if (mirrorflag) {
-        printf("  Updating top left ");
-        printtriangle(&topright);
-        printf("  Creating top right ");
-        printtriangle(&newtopright);
-      }
-      printf("  Creating bottom right ");
-      printtriangle(&newbotright);
-    }
-
-    /* Position `horiz' on the first edge to check for */
-    /*   the Delaunay property.                        */
-    lnextself(horiz);
-  } else {
-    /* Insert the point in a triangle, splitting it into three. */
-    lnext(horiz, botleft);
-    lprev(horiz, botright);
-    sym(botleft, botlcasing);
-    sym(botright, botrcasing);
-    maketriangle(&newbotleft);
-    maketriangle(&newbotright);
-
-    /* Set the vertices of changed and new triangles. */
-    org(horiz, rightpoint);
-    dest(horiz, leftpoint);
-    apex(horiz, botpoint);
-    setorg(newbotleft, leftpoint);
-    setdest(newbotleft, botpoint);
-    setapex(newbotleft, insertpoint);
-    setorg(newbotright, botpoint);
-    setdest(newbotright, rightpoint);
-    setapex(newbotright, insertpoint);
-    setapex(horiz, insertpoint);
-    for (i = 0; i < eextras; i++) {
-      /* Set the element attributes of the new triangles. */
-      attrib = elemattribute(horiz, i);
-      setelemattribute(newbotleft, i, attrib);
-      setelemattribute(newbotright, i, attrib);
-    }
-    if (vararea) {
-      /* Set the area constraint of the new triangles. */
-      area = areabound(horiz);
-      setareabound(newbotleft, area);
-      setareabound(newbotright, area);
-    }
-
-    /* There may be shell edges that need to be bonded */
-    /*   to the new triangles.                         */
-    if (checksegments) {
-      tspivot(botleft, botlshelle);
-      if (botlshelle.sh != dummysh) {
-        tsdissolve(botleft);
-        tsbond(newbotleft, botlshelle);
-      }
-      tspivot(botright, botrshelle);
-      if (botrshelle.sh != dummysh) {
-        tsdissolve(botright);
-        tsbond(newbotright, botrshelle);
-      }
-    }
-
-    /* Bond the new triangles to the surrounding triangles. */
-    bond(newbotleft, botlcasing);
-    bond(newbotright, botrcasing);
-    lnextself(newbotleft);
-    lprevself(newbotright);
-    bond(newbotleft, newbotright);
-    lnextself(newbotleft);
-    bond(botleft, newbotleft);
-    lprevself(newbotright);
-    bond(botright, newbotright);
-
-#ifdef SELF_CHECK
-    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle prior to point insertion.\n");
-    }
-    if (counterclockwise(rightpoint, leftpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after point insertion (top).\n");
-    }
-    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after point insertion (left).\n");
-    }
-    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
-      printf("Internal error in insertsite():\n");
-      printf("  Clockwise triangle after point insertion (right).\n");
-    }
-#endif /* SELF_CHECK */
-    if (verbose > 2) {
-      printf("  Updating top ");
-      printtriangle(&horiz);
-      printf("  Creating left ");
-      printtriangle(&newbotleft);
-      printf("  Creating right ");
-      printtriangle(&newbotright);
-    }
-  }
-
-  /* The insertion is successful by default, unless an encroached */
-  /*   edge is found.                                             */
-  success = SUCCESSFULPOINT;
-  /* Circle around the newly inserted vertex, checking each edge opposite */
-  /*   it for the Delaunay property.  Non-Delaunay edges are flipped.     */
-  /*   `horiz' is always the edge being checked.  `first' marks where to  */
-  /*   stop circling.                                                     */
-  org(horiz, first);
-  rightpoint = first;
-  dest(horiz, leftpoint);
-  /* Circle until finished. */
-  while (1) {
-    /* By default, the edge will be flipped. */
-    doflip = 1;
-    if (checksegments) {
-      /* Check for a segment, which cannot be flipped. */
-      tspivot(horiz, checkshelle);
-      if (checkshelle.sh != dummysh) {
-        /* The edge is a segment and cannot be flipped. */
-        doflip = 0;
-#ifndef CDT_ONLY
-        if (segmentflaws) {
-          /* Does the new point encroach upon this segment? */
-          if (checkedge4encroach(&checkshelle)) {
-            success = ENCROACHINGPOINT;
-          }
-        }
-#endif /* not CDT_ONLY */
-      }
-    }
-    if (doflip) {
-      /* Check if the edge is a boundary edge. */
-      sym(horiz, top);
-      if (top.tri == dummytri) {
-        /* The edge is a boundary edge and cannot be flipped. */
-        doflip = 0;
-      } else {
-        /* Find the point on the other side of the edge. */
-        apex(top, farpoint);
-        /* In the incremental Delaunay triangulation algorithm, any of    */
-        /*   `leftpoint', `rightpoint', and `farpoint' could be vertices  */
-        /*   of the triangular bounding box.  These vertices must be      */
-        /*   treated as if they are infinitely distant, even though their */
-        /*   "coordinates" are not.                                       */
-        if ((leftpoint == infpoint1) || (leftpoint == infpoint2)
-                   || (leftpoint == infpoint3)) {
-          /* `leftpoint' is infinitely distant.  Check the convexity of */
-          /*   the boundary of the triangulation.  'farpoint' might be  */
-          /*   infinite as well, but trust me, this same condition      */
-          /*   should be applied.                                       */
-          doflip = counterclockwise(insertpoint, rightpoint, farpoint) > 0.0;
-        } else if ((rightpoint == infpoint1) || (rightpoint == infpoint2)
-                   || (rightpoint == infpoint3)) {
-          /* `rightpoint' is infinitely distant.  Check the convexity of */
-          /*   the boundary of the triangulation.  'farpoint' might be  */
-          /*   infinite as well, but trust me, this same condition      */
-          /*   should be applied.                                       */
-          doflip = counterclockwise(farpoint, leftpoint, insertpoint) > 0.0;
-        } else if ((farpoint == infpoint1) || (farpoint == infpoint2)
-            || (farpoint == infpoint3)) {
-          /* `farpoint' is infinitely distant and cannot be inside */
-          /*   the circumcircle of the triangle `horiz'.           */
-          doflip = 0;
-        } else {
-          /* Test whether the edge is locally Delaunay. */
-          doflip = incircle(leftpoint, insertpoint, rightpoint, farpoint)
-                   > 0.0;
-        }
-        if (doflip) {
-          /* We made it!  Flip the edge `horiz' by rotating its containing */
-          /*   quadrilateral (the two triangles adjacent to `horiz').      */
-          /* Identify the casing of the quadrilateral. */
-          lprev(top, topleft);
-          sym(topleft, toplcasing);
-          lnext(top, topright);
-          sym(topright, toprcasing);
-          lnext(horiz, botleft);
-          sym(botleft, botlcasing);
-          lprev(horiz, botright);
-          sym(botright, botrcasing);
-          /* Rotate the quadrilateral one-quarter turn counterclockwise. */
-          bond(topleft, botlcasing);
-          bond(botleft, botrcasing);
-          bond(botright, toprcasing);
-          bond(topright, toplcasing);
-          if (checksegments) {
-            /* Check for shell edges and rebond them to the quadrilateral. */
-            tspivot(topleft, toplshelle);
-            tspivot(botleft, botlshelle);
-            tspivot(botright, botrshelle);
-            tspivot(topright, toprshelle);
-            if (toplshelle.sh == dummysh) {
-              tsdissolve(topright);
-            } else {
-              tsbond(topright, toplshelle);
-            }
-            if (botlshelle.sh == dummysh) {
-              tsdissolve(topleft);
-            } else {
-              tsbond(topleft, botlshelle);
-            }
-            if (botrshelle.sh == dummysh) {
-              tsdissolve(botleft);
-            } else {
-              tsbond(botleft, botrshelle);
-            }
-            if (toprshelle.sh == dummysh) {
-              tsdissolve(botright);
-            } else {
-              tsbond(botright, toprshelle);
-            }
-          }
-          /* New point assignments for the rotated quadrilateral. */
-          setorg(horiz, farpoint);
-          setdest(horiz, insertpoint);
-          setapex(horiz, rightpoint);
-          setorg(top, insertpoint);
-          setdest(top, farpoint);
-          setapex(top, leftpoint);
-          for (i = 0; i < eextras; i++) {
-            /* Take the average of the two triangles' attributes. */
-            attrib = (REAL)(0.5 * (elemattribute(top, i) + elemattribute(horiz, i)));
-            setelemattribute(top, i, attrib);
-            setelemattribute(horiz, i, attrib);
-          }
-          if (vararea) {
-            if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
-              area = -1.0;
-            } else {
-              /* Take the average of the two triangles' area constraints.    */
-              /*   This prevents small area constraints from migrating a     */
-              /*   long, long way from their original location due to flips. */
-              area = (REAL)(0.5 * (areabound(top) + areabound(horiz)));
-            }
-            setareabound(top, area);
-            setareabound(horiz, area);
-          }
-#ifdef SELF_CHECK
-          if (insertpoint != (point) NULL) {
-            if (counterclockwise(leftpoint, insertpoint, rightpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle prior to edge flip (bottom).\n");
-            }
-            /* The following test has been removed because constrainededge() */
-            /*   sometimes generates inverted triangles that insertsite()    */
-            /*   removes.                                                    */
-/*
-            if (counterclockwise(rightpoint, farpoint, leftpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle prior to edge flip (top).\n");
-            }
-*/
-            if (counterclockwise(farpoint, leftpoint, insertpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle after edge flip (left).\n");
-            }
-            if (counterclockwise(insertpoint, rightpoint, farpoint) < 0.0) {
-              printf("Internal error in insertsite():\n");
-              printf("  Clockwise triangle after edge flip (right).\n");
-            }
-          }
-#endif /* SELF_CHECK */
-          if (verbose > 2) {
-            printf("  Edge flip results in left ");
-            lnextself(topleft);
-            printtriangle(&topleft);
-            printf("  and right ");
-            printtriangle(&horiz);
-          }
-          /* On the next iterations, consider the two edges that were  */
-          /*   exposed (this is, are now visible to the newly inserted */
-          /*   point) by the edge flip.                                */
-          lprevself(horiz);
-          leftpoint = farpoint;
-        }
-      }
-    }
-    if (!doflip) {
-      /* The handle `horiz' is accepted as locally Delaunay. */
-#ifndef CDT_ONLY
-      if (triflaws) {
-        /* Check the triangle `horiz' for quality. */
-        testtriangle(&horiz);
-      }
-#endif /* not CDT_ONLY */
-      /* Look for the next edge around the newly inserted point. */
-      lnextself(horiz);
-      sym(horiz, testtri);
-      /* Check for finishing a complete revolution about the new point, or */
-      /*   falling off the edge of the triangulation.  The latter will     */
-      /*   happen when a point is inserted at a boundary.                  */
-      if ((leftpoint == first) || (testtri.tri == dummytri)) {
-        /* We're done.  Return a triangle whose origin is the new point. */
-        lnext(horiz, *searchtri);
-        lnext(horiz, recenttri);
-        return success;
-      }
-      /* Finish finding the next edge around the newly inserted point. */
-      lnext(testtri, horiz);
-      rightpoint = leftpoint;
-      dest(horiz, leftpoint);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  triangulatepolygon()   Find the Delaunay triangulation of a polygon that */
-/*                         has a certain "nice" shape.  This includes the    */
-/*                         polygons that result from deletion of a point or  */
-/*                         insertion of a segment.                           */
-/*                                                                           */
-/*  This is a conceptually difficult routine.  The starting assumption is    */
-/*  that we have a polygon with n sides.  n - 1 of these sides are currently */
-/*  represented as edges in the mesh.  One side, called the "base", need not */
-/*  be.                                                                      */
-/*                                                                           */
-/*  Inside the polygon is a structure I call a "fan", consisting of n - 1    */
-/*  triangles that share a common origin.  For each of these triangles, the  */
-/*  edge opposite the origin is one of the sides of the polygon.  The        */
-/*  primary edge of each triangle is the edge directed from the origin to    */
-/*  the destination; note that this is not the same edge that is a side of   */
-/*  the polygon.  `firstedge' is the primary edge of the first triangle.     */
-/*  From there, the triangles follow in counterclockwise order about the     */
-/*  polygon, until `lastedge', the primary edge of the last triangle.        */
-/*  `firstedge' and `lastedge' are probably connected to other triangles     */
-/*  beyond the extremes of the fan, but their identity is not important, as  */
-/*  long as the fan remains connected to them.                               */
-/*                                                                           */
-/*  Imagine the polygon oriented so that its base is at the bottom.  This    */
-/*  puts `firstedge' on the far right, and `lastedge' on the far left.       */
-/*  The right vertex of the base is the destination of `firstedge', and the  */
-/*  left vertex of the base is the apex of `lastedge'.                       */
-/*                                                                           */
-/*  The challenge now is to find the right sequence of edge flips to         */
-/*  transform the fan into a Delaunay triangulation of the polygon.  Each    */
-/*  edge flip effectively removes one triangle from the fan, committing it   */
-/*  to the polygon.  The resulting polygon has one fewer edge.  If `doflip'  */
-/*  is set, the final flip will be performed, resulting in a fan of one      */
-/*  (useless?) triangle.  If `doflip' is not set, the final flip is not      */
-/*  performed, resulting in a fan of two triangles, and an unfinished        */
-/*  triangular polygon that is not yet filled out with a single triangle.    */
-/*  On completion of the routine, `lastedge' is the last remaining triangle, */
-/*  or the leftmost of the last two.                                         */
-/*                                                                           */
-/*  Although the flips are performed in the order described above, the       */
-/*  decisions about what flips to perform are made in precisely the reverse  */
-/*  order.  The recursive triangulatepolygon() procedure makes a decision,   */
-/*  uses up to two recursive calls to triangulate the "subproblems"          */
-/*  (polygons with fewer edges), and then performs an edge flip.             */
-/*                                                                           */
-/*  The "decision" it makes is which vertex of the polygon should be         */
-/*  connected to the base.  This decision is made by testing every possible  */
-/*  vertex.  Once the best vertex is found, the two edges that connect this  */
-/*  vertex to the base become the bases for two smaller polygons.  These     */
-/*  are triangulated recursively.  Unfortunately, this approach can take     */
-/*  O(n^2) time not only in the worst case, but in many common cases.  It's  */
-/*  rarely a big deal for point deletion, where n is rarely larger than ten, */
-/*  but it could be a big deal for segment insertion, especially if there's  */
-/*  a lot of long segments that each cut many triangles.  I ought to code    */
-/*  a faster algorithm some time.                                            */
-/*                                                                           */
-/*  The `edgecount' parameter is the number of sides of the polygon,         */
-/*  including its base.  `triflaws' is a flag that determines whether the    */
-/*  new triangles should be tested for quality, and enqueued if they are     */
-/*  bad.                                                                     */
-/*                                                                           */
-/*****************************************************************************/
-
-void triangulatepolygon(firstedge, lastedge, edgecount, doflip, triflaws)
-struct triedge *firstedge;
-struct triedge *lastedge;
-int edgecount;
-int doflip;
-int triflaws;
-{
-  struct triedge testtri;
-  struct triedge besttri;
-  struct triedge tempedge;
-  point leftbasepoint, rightbasepoint;
-  point testpoint;
-  point bestpoint;
-  int bestnumber;
-  int i;
-  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
-
-  /* Identify the base vertices. */
-  apex(*lastedge, leftbasepoint);
-  dest(*firstedge, rightbasepoint);
-  if (verbose > 2) {
-    printf("  Triangulating interior polygon at edge\n");
-    printf("    (%.12g, %.12g) (%.12g, %.12g)\n", leftbasepoint[0],
-           leftbasepoint[1], rightbasepoint[0], rightbasepoint[1]);
-  }
-  /* Find the best vertex to connect the base to. */
-  onext(*firstedge, besttri);
-  dest(besttri, bestpoint);
-  triedgecopy(besttri, testtri);
-  bestnumber = 1;
-  for (i = 2; i <= edgecount - 2; i++) {
-    onextself(testtri);
-    dest(testtri, testpoint);
-    /* Is this a better vertex? */
-    if (incircle(leftbasepoint, rightbasepoint, bestpoint, testpoint) > 0.0) {
-      triedgecopy(testtri, besttri);
-      bestpoint = testpoint;
-      bestnumber = i;
-    }
-  }
-  if (verbose > 2) {
-    printf("    Connecting edge to (%.12g, %.12g)\n", bestpoint[0],
-           bestpoint[1]);
-  }
-  if (bestnumber > 1) {
-    /* Recursively triangulate the smaller polygon on the right. */
-    oprev(besttri, tempedge);
-    triangulatepolygon(firstedge, &tempedge, bestnumber + 1, 1, triflaws);
-  }
-  if (bestnumber < edgecount - 2) {
-    /* Recursively triangulate the smaller polygon on the left. */
-    sym(besttri, tempedge);
-    triangulatepolygon(&besttri, lastedge, edgecount - bestnumber, 1,
-                       triflaws);
-    /* Find `besttri' again; it may have been lost to edge flips. */
-    sym(tempedge, besttri);
-  }
-  if (doflip) {
-    /* Do one final edge flip. */
-    flip(&besttri);
-#ifndef CDT_ONLY
-    if (triflaws) {
-      /* Check the quality of the newly committed triangle. */
-      sym(besttri, testtri);
-      testtriangle(&testtri);
-    }
-#endif /* not CDT_ONLY */
-  }
-  /* Return the base triangle. */
-  triedgecopy(besttri, *lastedge);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  deletesite()   Delete a vertex from a Delaunay triangulation, ensuring   */
-/*                 that the triangulation remains Delaunay.                  */
-/*                                                                           */
-/*  The origin of `deltri' is deleted.  The union of the triangles adjacent  */
-/*  to this point is a polygon, for which the Delaunay triangulation is      */
-/*  found.  Two triangles are removed from the mesh.                         */
-/*                                                                           */
-/*  Only interior points that do not lie on segments (shell edges) or        */
-/*  boundaries may be deleted.                                               */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void deletesite(deltri)
-struct triedge *deltri;
-{
-  struct triedge countingtri;
-  struct triedge firstedge, lastedge;
-  struct triedge deltriright;
-  struct triedge lefttri, righttri;
-  struct triedge leftcasing, rightcasing;
-  struct edge leftshelle, rightshelle;
-  point delpoint;
-  point neworg;
-  int edgecount;
-  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  org(*deltri, delpoint);
-  if (verbose > 1) {
-    printf("  Deleting (%.12g, %.12g).\n", delpoint[0], delpoint[1]);
-  }
-  pointdealloc(delpoint);
-
-  /* Count the degree of the point being deleted. */
-  onext(*deltri, countingtri);
-  edgecount = 1;
-  while (!triedgeequal(*deltri, countingtri)) {
-#ifdef SELF_CHECK
-    if (countingtri.tri == dummytri) {
-      printf("Internal error in deletesite():\n");
-      printf("  Attempt to delete boundary point.\n");
-      internalerror();
-    }
-#endif /* SELF_CHECK */
-    edgecount++;
-    onextself(countingtri);
-  }
-
-#ifdef SELF_CHECK
-  if (edgecount < 3) {
-    printf("Internal error in deletesite():\n  Point has degree %d.\n",
-           edgecount);
-    internalerror();
-  }
-#endif /* SELF_CHECK */
-  if (edgecount > 3) {
-    /* Triangulate the polygon defined by the union of all triangles */
-    /*   adjacent to the point being deleted.  Check the quality of  */
-    /*   the resulting triangles.                                    */
-    onext(*deltri, firstedge);
-    oprev(*deltri, lastedge);
-    triangulatepolygon(&firstedge, &lastedge, edgecount, 0, !nobisect);
-  }
-  /* Splice out two triangles. */
-  lprev(*deltri, deltriright);
-  dnext(*deltri, lefttri);
-  sym(lefttri, leftcasing);
-  oprev(deltriright, righttri);
-  sym(righttri, rightcasing);
-  bond(*deltri, leftcasing);
-  bond(deltriright, rightcasing);
-  tspivot(lefttri, leftshelle);
-  if (leftshelle.sh != dummysh) {
-    tsbond(*deltri, leftshelle);
-  }
-  tspivot(righttri, rightshelle);
-  if (rightshelle.sh != dummysh) {
-    tsbond(deltriright, rightshelle);
-  }
-
-  /* Set the new origin of `deltri' and check its quality. */
-  org(lefttri, neworg);
-  setorg(*deltri, neworg);
-  if (!nobisect) {
-    testtriangle(deltri);
-  }
-
-  /* Delete the two spliced-out triangles. */
-  triangledealloc(lefttri.tri);
-  triangledealloc(righttri.tri);
-}
-
-#endif /* not CDT_ONLY */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Mesh transformation routines end here                     *********/
-
-/********* Divide-and-conquer Delaunay triangulation begins here     *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  The divide-and-conquer bounding box                                      */
-/*                                                                           */
-/*  I originally implemented the divide-and-conquer and incremental Delaunay */
-/*  triangulations using the edge-based data structure presented by Guibas   */
-/*  and Stolfi.  Switching to a triangle-based data structure doubled the    */
-/*  speed.  However, I had to think of a few extra tricks to maintain the    */
-/*  elegance of the original algorithms.                                     */
-/*                                                                           */
-/*  The "bounding box" used by my variant of the divide-and-conquer          */
-/*  algorithm uses one triangle for each edge of the convex hull of the      */
-/*  triangulation.  These bounding triangles all share a common apical       */
-/*  vertex, which is represented by NULL and which represents nothing.       */
-/*  The bounding triangles are linked in a circular fan about this NULL      */
-/*  vertex, and the edges on the convex hull of the triangulation appear     */
-/*  opposite the NULL vertex.  You might find it easiest to imagine that     */
-/*  the NULL vertex is a point in 3D space behind the center of the          */
-/*  triangulation, and that the bounding triangles form a sort of cone.      */
-/*                                                                           */
-/*  This bounding box makes it easy to represent degenerate cases.  For      */
-/*  instance, the triangulation of two vertices is a single edge.  This edge */
-/*  is represented by two bounding box triangles, one on each "side" of the  */
-/*  edge.  These triangles are also linked together in a fan about the NULL  */
-/*  vertex.                                                                  */
-/*                                                                           */
-/*  The bounding box also makes it easy to traverse the convex hull, as the  */
-/*  divide-and-conquer algorithm needs to do.                                */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointsort()   Sort an array of points by x-coordinate, using the         */
-/*                y-coordinate as a secondary key.                           */
-/*                                                                           */
-/*  Uses quicksort.  Randomized O(n log n) time.  No, I did not make any of  */
-/*  the usual quicksort mistakes.                                            */
-/*                                                                           */
-/*****************************************************************************/
-
-void pointsort(sortarray, arraysize)
-point *sortarray;
-int arraysize;
-{
-  int left, right;
-  int pivot;
-  REAL pivotx, pivoty;
-  point temp;
-
-  if (arraysize == 2) {
-    /* Recursive base case. */
-    if ((sortarray[0][0] > sortarray[1][0]) ||
-        ((sortarray[0][0] == sortarray[1][0]) &&
-         (sortarray[0][1] > sortarray[1][1]))) {
-      temp = sortarray[1];
-      sortarray[1] = sortarray[0];
-      sortarray[0] = temp;
-    }
-    return;
-  }
-  /* Choose a random pivot to split the array. */
-  pivot = (int) randomnation(arraysize);
-  pivotx = sortarray[pivot][0];
-  pivoty = sortarray[pivot][1];
-  /* Split the array. */
-  left = -1;
-  right = arraysize;
-  while (left < right) {
-    /* Search for a point whose x-coordinate is too large for the left. */
-    do {
-      left++;
-    } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
-                                 ((sortarray[left][0] == pivotx) &&
-                                  (sortarray[left][1] < pivoty))));
-    /* Search for a point whose x-coordinate is too small for the right. */
-    do {
-      right--;
-    } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
-                                 ((sortarray[right][0] == pivotx) &&
-                                  (sortarray[right][1] > pivoty))));
-    if (left < right) {
-      /* Swap the left and right points. */
-      temp = sortarray[left];
-      sortarray[left] = sortarray[right];
-      sortarray[right] = temp;
-    }
-  }
-  if (left > 1) {
-    /* Recursively sort the left subset. */
-    pointsort(sortarray, left);
-  }
-  if (right < arraysize - 2) {
-    /* Recursively sort the right subset. */
-    pointsort(&sortarray[right + 1], arraysize - right - 1);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  pointmedian()   An order statistic algorithm, almost.  Shuffles an array */
-/*                  of points so that the first `median' points occur        */
-/*                  lexicographically before the remaining points.           */
-/*                                                                           */
-/*  Uses the x-coordinate as the primary key if axis == 0; the y-coordinate  */
-/*  if axis == 1.  Very similar to the pointsort() procedure, but runs in    */
-/*  randomized linear time.                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void pointmedian(sortarray, arraysize, median, axis)
-point *sortarray;
-int arraysize;
-int median;
-int axis;
-{
-  int left, right;
-  int pivot;
-  REAL pivot1, pivot2;
-  point temp;
-
-  if (arraysize == 2) {
-    /* Recursive base case. */
-    if ((sortarray[0][axis] > sortarray[1][axis]) ||
-        ((sortarray[0][axis] == sortarray[1][axis]) &&
-         (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
-      temp = sortarray[1];
-      sortarray[1] = sortarray[0];
-      sortarray[0] = temp;
-    }
-    return;
-  }
-  /* Choose a random pivot to split the array. */
-  pivot = (int) randomnation(arraysize);
-  pivot1 = sortarray[pivot][axis];
-  pivot2 = sortarray[pivot][1 - axis];
-  /* Split the array. */
-  left = -1;
-  right = arraysize;
-  while (left < right) {
-    /* Search for a point whose x-coordinate is too large for the left. */
-    do {
-      left++;
-    } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
-                                 ((sortarray[left][axis] == pivot1) &&
-                                  (sortarray[left][1 - axis] < pivot2))));
-    /* Search for a point whose x-coordinate is too small for the right. */
-    do {
-      right--;
-    } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
-                                 ((sortarray[right][axis] == pivot1) &&
-                                  (sortarray[right][1 - axis] > pivot2))));
-    if (left < right) {
-      /* Swap the left and right points. */
-      temp = sortarray[left];
-      sortarray[left] = sortarray[right];
-      sortarray[right] = temp;
-    }
-  }
-  /* Unlike in pointsort(), at most one of the following */
-  /*   conditionals is true.                             */
-  if (left > median) {
-    /* Recursively shuffle the left subset. */
-    pointmedian(sortarray, left, median, axis);
-  }
-  if (right < median - 1) {
-    /* Recursively shuffle the right subset. */
-    pointmedian(&sortarray[right + 1], arraysize - right - 1,
-                median - right - 1, axis);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  alternateaxes()   Sorts the points as appropriate for the divide-and-    */
-/*                    conquer algorithm with alternating cuts.               */
-/*                                                                           */
-/*  Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1.   */
-/*  For the base case, subsets containing only two or three points are       */
-/*  always sorted by x-coordinate.                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-void alternateaxes(sortarray, arraysize, axis)
-point *sortarray;
-int arraysize;
-int axis;
-{
-  int divider;
-
-  divider = arraysize >> 1;
-  if (arraysize <= 3) {
-    /* Recursive base case:  subsets of two or three points will be      */
-    /*   handled specially, and should always be sorted by x-coordinate. */
-    axis = 0;
-  }
-  /* Partition with a horizontal or vertical cut. */
-  pointmedian(sortarray, arraysize, divider, axis);
-  /* Recursively partition the subsets with a cross cut. */
-  if (arraysize - divider >= 2) {
-    if (divider >= 2) {
-      alternateaxes(sortarray, divider, 1 - axis);
-    }
-    alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  mergehulls()   Merge two adjacent Delaunay triangulations into a         */
-/*                 single Delaunay triangulation.                            */
-/*                                                                           */
-/*  This is similar to the algorithm given by Guibas and Stolfi, but uses    */
-/*  a triangle-based, rather than edge-based, data structure.                */
-/*                                                                           */
-/*  The algorithm walks up the gap between the two triangulations, knitting  */
-/*  them together.  As they are merged, some of their bounding triangles     */
-/*  are converted into real triangles of the triangulation.  The procedure   */
-/*  pulls each hull's bounding triangles apart, then knits them together     */
-/*  like the teeth of two gears.  The Delaunay property determines, at each  */
-/*  step, whether the next "tooth" is a bounding triangle of the left hull   */
-/*  or the right.  When a bounding triangle becomes real, its apex is        */
-/*  changed from NULL to a real point.                                       */
-/*                                                                           */
-/*  Only two new triangles need to be allocated.  These become new bounding  */
-/*  triangles at the top and bottom of the seam.  They are used to connect   */
-/*  the remaining bounding triangles (those that have not been converted     */
-/*  into real triangles) into a single fan.                                  */
-/*                                                                           */
-/*  On entry, `farleft' and `innerleft' are bounding triangles of the left   */
-/*  triangulation.  The origin of `farleft' is the leftmost vertex, and      */
-/*  the destination of `innerleft' is the rightmost vertex of the            */
-/*  triangulation.  Similarly, `innerright' and `farright' are bounding      */
-/*  triangles of the right triangulation.  The origin of `innerright' and    */
-/*  destination of `farright' are the leftmost and rightmost vertices.       */
-/*                                                                           */
-/*  On completion, the origin of `farleft' is the leftmost vertex of the     */
-/*  merged triangulation, and the destination of `farright' is the rightmost */
-/*  vertex.                                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void mergehulls(farleft, innerleft, innerright, farright, axis)
-struct triedge *farleft;
-struct triedge *innerleft;
-struct triedge *innerright;
-struct triedge *farright;
-int axis;
-{
-  struct triedge leftcand, rightcand;
-  struct triedge baseedge;
-  struct triedge nextedge;
-  struct triedge sidecasing, topcasing, outercasing;
-  struct triedge checkedge;
-  point innerleftdest;
-  point innerrightorg;
-  point innerleftapex, innerrightapex;
-  point farleftpt, farrightpt;
-  point farleftapex, farrightapex;
-  point lowerleft, lowerright;
-  point upperleft, upperright;
-  point nextapex;
-  point checkvertex;
-  int changemade;
-  int badedge;
-  int leftfinished, rightfinished;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  dest(*innerleft, innerleftdest);
-  apex(*innerleft, innerleftapex);
-  org(*innerright, innerrightorg);
-  apex(*innerright, innerrightapex);
-  /* Special treatment for horizontal cuts. */
-  if (dwyer && (axis == 1)) {
-    org(*farleft, farleftpt);
-    apex(*farleft, farleftapex);
-    dest(*farright, farrightpt);
-    apex(*farright, farrightapex);
-    /* The pointers to the extremal points are shifted to point to the */
-    /*   topmost and bottommost point of each hull, rather than the    */
-    /*   leftmost and rightmost points.                                */
-    while (farleftapex[1] < farleftpt[1]) {
-      lnextself(*farleft);
-      symself(*farleft);
-      farleftpt = farleftapex;
-      apex(*farleft, farleftapex);
-    }
-    sym(*innerleft, checkedge);
-    apex(checkedge, checkvertex);
-    while (checkvertex[1] > innerleftdest[1]) {
-      lnext(checkedge, *innerleft);
-      innerleftapex = innerleftdest;
-      innerleftdest = checkvertex;
-      sym(*innerleft, checkedge);
-      apex(checkedge, checkvertex);
-    }
-    while (innerrightapex[1] < innerrightorg[1]) {
-      lnextself(*innerright);
-      symself(*innerright);
-      innerrightorg = innerrightapex;
-      apex(*innerright, innerrightapex);
-    }
-    sym(*farright, checkedge);
-    apex(checkedge, checkvertex);
-    while (checkvertex[1] > farrightpt[1]) {
-      lnext(checkedge, *farright);
-      farrightapex = farrightpt;
-      farrightpt = checkvertex;
-      sym(*farright, checkedge);
-      apex(checkedge, checkvertex);
-    }
-  }
-  /* Find a line tangent to and below both hulls. */
-  do {
-    changemade = 0;
-    /* Make innerleftdest the "bottommost" point of the left hull. */
-    if (counterclockwise(innerleftdest, innerleftapex, innerrightorg) > 0.0) {
-      lprevself(*innerleft);
-      symself(*innerleft);
-      innerleftdest = innerleftapex;
-      apex(*innerleft, innerleftapex);
-      changemade = 1;
-    }
-    /* Make innerrightorg the "bottommost" point of the right hull. */
-    if (counterclockwise(innerrightapex, innerrightorg, innerleftdest) > 0.0) {
-      lnextself(*innerright);
-      symself(*innerright);
-      innerrightorg = innerrightapex;
-      apex(*innerright, innerrightapex);
-      changemade = 1;
-    }
-  } while (changemade);
-  /* Find the two candidates to be the next "gear tooth". */
-  sym(*innerleft, leftcand);
-  sym(*innerright, rightcand);
-  /* Create the bottom new bounding triangle. */
-  maketriangle(&baseedge);
-  /* Connect it to the bounding boxes of the left and right triangulations. */
-  bond(baseedge, *innerleft);
-  lnextself(baseedge);
-  bond(baseedge, *innerright);
-  lnextself(baseedge);
-  setorg(baseedge, innerrightorg);
-  setdest(baseedge, innerleftdest);
-  /* Apex is intentionally left NULL. */
-  if (verbose > 2) {
-    printf("  Creating base bounding ");
-    printtriangle(&baseedge);
-  }
-  /* Fix the extreme triangles if necessary. */
-  org(*farleft, farleftpt);
-  if (innerleftdest == farleftpt) {
-    lnext(baseedge, *farleft);
-  }
-  dest(*farright, farrightpt);
-  if (innerrightorg == farrightpt) {
-    lprev(baseedge, *farright);
-  }
-  /* The vertices of the current knitting edge. */
-  lowerleft = innerleftdest;
-  lowerright = innerrightorg;
-  /* The candidate vertices for knitting. */
-  apex(leftcand, upperleft);
-  apex(rightcand, upperright);
-  /* Walk up the gap between the two triangulations, knitting them together. */
-  while (1) {
-    /* Have we reached the top?  (This isn't quite the right question,       */
-    /*   because even though the left triangulation might seem finished now, */
-    /*   moving up on the right triangulation might reveal a new point of    */
-    /*   the left triangulation.  And vice-versa.)                           */
-    leftfinished = counterclockwise(upperleft, lowerleft, lowerright) <= 0.0;
-    rightfinished = counterclockwise(upperright, lowerleft, lowerright) <= 0.0;
-    if (leftfinished && rightfinished) {
-      /* Create the top new bounding triangle. */
-      maketriangle(&nextedge);
-      setorg(nextedge, lowerleft);
-      setdest(nextedge, lowerright);
-      /* Apex is intentionally left NULL. */
-      /* Connect it to the bounding boxes of the two triangulations. */
-      bond(nextedge, baseedge);
-      lnextself(nextedge);
-      bond(nextedge, rightcand);
-      lnextself(nextedge);
-      bond(nextedge, leftcand);
-      if (verbose > 2) {
-        printf("  Creating top bounding ");
-        printtriangle(&baseedge);
-      }
-      /* Special treatment for horizontal cuts. */
-      if (dwyer && (axis == 1)) {
-        org(*farleft, farleftpt);
-        apex(*farleft, farleftapex);
-        dest(*farright, farrightpt);
-        apex(*farright, farrightapex);
-        sym(*farleft, checkedge);
-        apex(checkedge, checkvertex);
-        /* The pointers to the extremal points are restored to the leftmost */
-        /*   and rightmost points (rather than topmost and bottommost).     */
-        while (checkvertex[0] < farleftpt[0]) {
-          lprev(checkedge, *farleft);
-          farleftapex = farleftpt;
-          farleftpt = checkvertex;
-          sym(*farleft, checkedge);
-          apex(checkedge, checkvertex);
-        }
-        while (farrightapex[0] > farrightpt[0]) {
-          lprevself(*farright);
-          symself(*farright);
-          farrightpt = farrightapex;
-          apex(*farright, farrightapex);
-        }
-      }
-      return;
-    }
-    /* Consider eliminating edges from the left triangulation. */
-    if (!leftfinished) {
-      /* What vertex would be exposed if an edge were deleted? */
-      lprev(leftcand, nextedge);
-      symself(nextedge);
-      apex(nextedge, nextapex);
-      /* If nextapex is NULL, then no vertex would be exposed; the */
-      /*   triangulation would have been eaten right through.      */
-      if (nextapex != (point) NULL) {
-        /* Check whether the edge is Delaunay. */
-        badedge = incircle(lowerleft, lowerright, upperleft, nextapex) > 0.0;
-        while (badedge) {
-          /* Eliminate the edge with an edge flip.  As a result, the    */
-          /*   left triangulation will have one more boundary triangle. */
-          lnextself(nextedge);
-          sym(nextedge, topcasing);
-          lnextself(nextedge);
-          sym(nextedge, sidecasing);
-          bond(nextedge, topcasing);
-          bond(leftcand, sidecasing);
-          lnextself(leftcand);
-          sym(leftcand, outercasing);
-          lprevself(nextedge);
-          bond(nextedge, outercasing);
-          /* Correct the vertices to reflect the edge flip. */
-          setorg(leftcand, lowerleft);
-          setdest(leftcand, NULL);
-          setapex(leftcand, nextapex);
-          setorg(nextedge, NULL);
-          setdest(nextedge, upperleft);
-          setapex(nextedge, nextapex);
-          /* Consider the newly exposed vertex. */
-          upperleft = nextapex;
-          /* What vertex would be exposed if another edge were deleted? */
-          triedgecopy(sidecasing, nextedge);
-          apex(nextedge, nextapex);
-          if (nextapex != (point) NULL) {
-            /* Check whether the edge is Delaunay. */
-            badedge = incircle(lowerleft, lowerright, upperleft, nextapex)
-                      > 0.0;
-          } else {
-            /* Avoid eating right through the triangulation. */
-            badedge = 0;
-          }
-        }
-      }
-    }
-    /* Consider eliminating edges from the right triangulation. */
-    if (!rightfinished) {
-      /* What vertex would be exposed if an edge were deleted? */
-      lnext(rightcand, nextedge);
-      symself(nextedge);
-      apex(nextedge, nextapex);
-      /* If nextapex is NULL, then no vertex would be exposed; the */
-      /*   triangulation would have been eaten right through.      */
-      if (nextapex != (point) NULL) {
-        /* Check whether the edge is Delaunay. */
-        badedge = incircle(lowerleft, lowerright, upperright, nextapex) > 0.0;
-        while (badedge) {
-          /* Eliminate the edge with an edge flip.  As a result, the     */
-          /*   right triangulation will have one more boundary triangle. */
-          lprevself(nextedge);
-          sym(nextedge, topcasing);
-          lprevself(nextedge);
-          sym(nextedge, sidecasing);
-          bond(nextedge, topcasing);
-          bond(rightcand, sidecasing);
-          lprevself(rightcand);
-          sym(rightcand, outercasing);
-          lnextself(nextedge);
-          bond(nextedge, outercasing);
-          /* Correct the vertices to reflect the edge flip. */
-          setorg(rightcand, NULL);
-          setdest(rightcand, lowerright);
-          setapex(rightcand, nextapex);
-          setorg(nextedge, upperright);
-          setdest(nextedge, NULL);
-          setapex(nextedge, nextapex);
-          /* Consider the newly exposed vertex. */
-          upperright = nextapex;
-          /* What vertex would be exposed if another edge were deleted? */
-          triedgecopy(sidecasing, nextedge);
-          apex(nextedge, nextapex);
-          if (nextapex != (point) NULL) {
-            /* Check whether the edge is Delaunay. */
-            badedge = incircle(lowerleft, lowerright, upperright, nextapex)
-                      > 0.0;
-          } else {
-            /* Avoid eating right through the triangulation. */
-            badedge = 0;
-          }
-        }
-      }
-    }
-    if (leftfinished || (!rightfinished &&
-           (incircle(upperleft, lowerleft, lowerright, upperright) > 0.0))) {
-      /* Knit the triangulations, adding an edge from `lowerleft' */
-      /*   to `upperright'.                                       */
-      bond(baseedge, rightcand);
-      lprev(rightcand, baseedge);
-      setdest(baseedge, lowerleft);
-      lowerright = upperright;
-      sym(baseedge, rightcand);
-      apex(rightcand, upperright);
-    } else {
-      /* Knit the triangulations, adding an edge from `upperleft' */
-      /*   to `lowerright'.                                       */
-      bond(baseedge, leftcand);
-      lnext(leftcand, baseedge);
-      setorg(baseedge, lowerright);
-      lowerleft = upperleft;
-      sym(baseedge, leftcand);
-      apex(leftcand, upperleft);
-    }
-    if (verbose > 2) {
-      printf("  Connecting ");
-      printtriangle(&baseedge);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  divconqrecurse()   Recursively form a Delaunay triangulation by the      */
-/*                     divide-and-conquer method.                            */
-/*                                                                           */
-/*  Recursively breaks down the problem into smaller pieces, which are       */
-/*  knitted together by mergehulls().  The base cases (problems of two or    */
-/*  three points) are handled specially here.                                */
-/*                                                                           */
-/*  On completion, `farleft' and `farright' are bounding triangles such that */
-/*  the origin of `farleft' is the leftmost vertex (breaking ties by         */
-/*  choosing the highest leftmost vertex), and the destination of            */
-/*  `farright' is the rightmost vertex (breaking ties by choosing the        */
-/*  lowest rightmost vertex).                                                */
-/*                                                                           */
-/*****************************************************************************/
-
-void divconqrecurse(sortarray, vertices, axis, farleft, farright)
-point *sortarray;
-int vertices;
-int axis;
-struct triedge *farleft;
-struct triedge *farright;
-{
-  struct triedge midtri, tri1, tri2, tri3;
-  struct triedge innerleft, innerright;
-  REAL area;
-  int divider;
-
-  if (verbose > 2) {
-    printf("  Triangulating %d points.\n", vertices);
-  }
-  if (vertices == 2) {
-    /* The triangulation of two vertices is an edge.  An edge is */
-    /*   represented by two bounding triangles.                  */
-    maketriangle(farleft);
-    setorg(*farleft, sortarray[0]);
-    setdest(*farleft, sortarray[1]);
-    /* The apex is intentionally left NULL. */
-    maketriangle(farright);
-    setorg(*farright, sortarray[1]);
-    setdest(*farright, sortarray[0]);
-    /* The apex is intentionally left NULL. */
-    bond(*farleft, *farright);
-    lprevself(*farleft);
-    lnextself(*farright);
-    bond(*farleft, *farright);
-    lprevself(*farleft);
-    lnextself(*farright);
-    bond(*farleft, *farright);
-    if (verbose > 2) {
-      printf("  Creating ");
-      printtriangle(farleft);
-      printf("  Creating ");
-      printtriangle(farright);
-    }
-    /* Ensure that the origin of `farleft' is sortarray[0]. */
-    lprev(*farright, *farleft);
-    return;
-  } else if (vertices == 3) {
-    /* The triangulation of three vertices is either a triangle (with */
-    /*   three bounding triangles) or two edges (with four bounding   */
-    /*   triangles).  In either case, four triangles are created.     */
-    maketriangle(&midtri);
-    maketriangle(&tri1);
-    maketriangle(&tri2);
-    maketriangle(&tri3);
-    area = counterclockwise(sortarray[0], sortarray[1], sortarray[2]);
-    if (area == 0.0) {
-      /* Three collinear points; the triangulation is two edges. */
-      setorg(midtri, sortarray[0]);
-      setdest(midtri, sortarray[1]);
-      setorg(tri1, sortarray[1]);
-      setdest(tri1, sortarray[0]);
-      setorg(tri2, sortarray[2]);
-      setdest(tri2, sortarray[1]);
-      setorg(tri3, sortarray[1]);
-      setdest(tri3, sortarray[2]);
-      /* All apices are intentionally left NULL. */
-      bond(midtri, tri1);
-      bond(tri2, tri3);
-      lnextself(midtri);
-      lprevself(tri1);
-      lnextself(tri2);
-      lprevself(tri3);
-      bond(midtri, tri3);
-      bond(tri1, tri2);
-      lnextself(midtri);
-      lprevself(tri1);
-      lnextself(tri2);
-      lprevself(tri3);
-      bond(midtri, tri1);
-      bond(tri2, tri3);
-      /* Ensure that the origin of `farleft' is sortarray[0]. */
-      triedgecopy(tri1, *farleft);
-      /* Ensure that the destination of `farright' is sortarray[2]. */
-      triedgecopy(tri2, *farright);
-    } else {
-      /* The three points are not collinear; the triangulation is one */
-      /*   triangle, namely `midtri'.                                 */
-      setorg(midtri, sortarray[0]);
-      setdest(tri1, sortarray[0]);
-      setorg(tri3, sortarray[0]);
-      /* Apices of tri1, tri2, and tri3 are left NULL. */
-      if (area > 0.0) {
-        /* The vertices are in counterclockwise order. */
-        setdest(midtri, sortarray[1]);
-        setorg(tri1, sortarray[1]);
-        setdest(tri2, sortarray[1]);
-        setapex(midtri, sortarray[2]);
-        setorg(tri2, sortarray[2]);
-        setdest(tri3, sortarray[2]);
-      } else {
-        /* The vertices are in clockwise order. */
-        setdest(midtri, sortarray[2]);
-        setorg(tri1, sortarray[2]);
-        setdest(tri2, sortarray[2]);
-        setapex(midtri, sortarray[1]);
-        setorg(tri2, sortarray[1]);
-        setdest(tri3, sortarray[1]);
-      }
-      /* The topology does not depend on how the vertices are ordered. */
-      bond(midtri, tri1);
-      lnextself(midtri);
-      bond(midtri, tri2);
-      lnextself(midtri);
-      bond(midtri, tri3);
-      lprevself(tri1);
-      lnextself(tri2);
-      bond(tri1, tri2);
-      lprevself(tri1);
-      lprevself(tri3);
-      bond(tri1, tri3);
-      lnextself(tri2);
-      lprevself(tri3);
-      bond(tri2, tri3);
-      /* Ensure that the origin of `farleft' is sortarray[0]. */
-      triedgecopy(tri1, *farleft);
-      /* Ensure that the destination of `farright' is sortarray[2]. */
-      if (area > 0.0) {
-        triedgecopy(tri2, *farright);
-      } else {
-        lnext(*farleft, *farright);
-      }
-    }
-    if (verbose > 2) {
-      printf("  Creating ");
-      printtriangle(&midtri);
-      printf("  Creating ");
-      printtriangle(&tri1);
-      printf("  Creating ");
-      printtriangle(&tri2);
-      printf("  Creating ");
-      printtriangle(&tri3);
-    }
-    return;
-  } else {
-    /* Split the vertices in half. */
-    divider = vertices >> 1;
-    /* Recursively triangulate each half. */
-    divconqrecurse(sortarray, divider, 1 - axis, farleft, &innerleft);
-    divconqrecurse(&sortarray[divider], vertices - divider, 1 - axis,
-                   &innerright, farright);
-    if (verbose > 1) {
-      printf("  Joining triangulations with %d and %d vertices.\n", divider,
-             vertices - divider);
-    }
-    /* Merge the two triangulations into one. */
-    mergehulls(farleft, &innerleft, &innerright, farright, axis);
-  }
-}
-
-long removeghosts(startghost)
-struct triedge *startghost;
-{
-  struct triedge searchedge;
-  struct triedge dissolveedge;
-  struct triedge deadtri;
-  point markorg;
-  long hullsize;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose) {
-    printf("  Removing ghost triangles.\n");
-  }
-  /* Find an edge on the convex hull to start point location from. */
-  lprev(*startghost, searchedge);
-  symself(searchedge);
-  dummytri[0] = encode(searchedge);
-  /* Remove the bounding box and count the convex hull edges. */
-  triedgecopy(*startghost, dissolveedge);
-  hullsize = 0;
-  do {
-    hullsize++;
-    lnext(dissolveedge, deadtri);
-    lprevself(dissolveedge);
-    symself(dissolveedge);
-    /* If no PSLG is involved, set the boundary markers of all the points */
-    /*   on the convex hull.  If a PSLG is used, this step is done later. */
-    if (!poly) {
-      /* Watch out for the case where all the input points are collinear. */
-      if (dissolveedge.tri != dummytri) {
-        org(dissolveedge, markorg);
-        if (pointmark(markorg) == 0) {
-          setpointmark(markorg, 1);
-        }
-      }
-    }
-    /* Remove a bounding triangle from a convex hull triangle. */
-    dissolve(dissolveedge);
-    /* Find the next bounding triangle. */
-    sym(deadtri, dissolveedge);
-    /* Delete the bounding triangle. */
-    triangledealloc(deadtri.tri);
-  } while (!triedgeequal(dissolveedge, *startghost));
-  return hullsize;
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  divconqdelaunay()   Form a Delaunay triangulation by the divide-and-     */
-/*                      conquer method.                                      */
-/*                                                                           */
-/*  Sorts the points, calls a recursive procedure to triangulate them, and   */
-/*  removes the bounding box, setting boundary markers as appropriate.       */
-/*                                                                           */
-/*****************************************************************************/
-
-long divconqdelaunay()
-{
-  point *sortarray;
-  struct triedge hullleft, hullright;
-  int divider;
-  int i, j;
-
-  /* Allocate an array of pointers to points for sorting. */
-  sortarray = (point *) malloc(inpoints * sizeof(point));
-  if (sortarray == (point *) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  traversalinit(&points);
-  for (i = 0; i < inpoints; i++) {
-    sortarray[i] = pointtraverse();
-  }
-  if (verbose) {
-    printf("  Sorting points.\n");
-  }
-  /* Sort the points. */
-  pointsort(sortarray, inpoints);
-  /* Discard duplicate points, which can really mess up the algorithm. */
-  i = 0;
-  for (j = 1; j < inpoints; j++) {
-    if ((sortarray[i][0] == sortarray[j][0])
-        && (sortarray[i][1] == sortarray[j][1])) {
-      if (!quiet) {
-        printf(
-"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
-               sortarray[j][0], sortarray[j][1]);
-      }
-/*  Commented out - would eliminate point from output .node file, but causes
-    a failure if some segment has this point as an endpoint.
-      setpointmark(sortarray[j], DEADPOINT);
-*/
-    } else {
-      i++;
-      sortarray[i] = sortarray[j];
-    }
-  }
-  i++;
-  if (dwyer) {
-    /* Re-sort the array of points to accommodate alternating cuts. */
-    divider = i >> 1;
-    if (i - divider >= 2) {
-      if (divider >= 2) {
-        alternateaxes(sortarray, divider, 1);
-      }
-      alternateaxes(&sortarray[divider], i - divider, 1);
-    }
-  }
-  if (verbose) {
-    printf("  Forming triangulation.\n");
-  }
-  /* Form the Delaunay triangulation. */
-  divconqrecurse(sortarray, i, 0, &hullleft, &hullright);
-  free(sortarray);
-
-  return removeghosts(&hullleft);
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Divide-and-conquer Delaunay triangulation ends here       *********/
-
-/********* Incremental Delaunay triangulation begins here            *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  boundingbox()   Form an "infinite" bounding triangle to insert points    */
-/*                  into.                                                    */
-/*                                                                           */
-/*  The points at "infinity" are assigned finite coordinates, which are used */
-/*  by the point location routines, but (mostly) ignored by the Delaunay     */
-/*  edge flip routines.                                                      */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef REDUCED
-
-void boundingbox()
-{
-  struct triedge inftri;          /* Handle for the triangular bounding box. */
-  REAL width;
-
-  if (verbose) {
-    printf("  Creating triangular bounding box.\n");
-  }
-  /* Find the width (or height, whichever is larger) of the triangulation. */
-  width = xmax - xmin;
-  if (ymax - ymin > width) {
-    width = ymax - ymin;
-  }
-  if (width == 0.0) {
-    width = 1.0;
-  }
-  /* Create the vertices of the bounding box. */
-  infpoint1 = (point) malloc(points.itembytes);
-  infpoint2 = (point) malloc(points.itembytes);
-  infpoint3 = (point) malloc(points.itembytes);
-  if ((infpoint1 == (point) NULL) || (infpoint2 == (point) NULL)
-      || (infpoint3 == (point) NULL)) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  infpoint1[0] = xmin - 50.0 * width;
-  infpoint1[1] = ymin - 40.0 * width;
-  infpoint2[0] = xmax + 50.0 * width;
-  infpoint2[1] = ymin - 40.0 * width;
-  infpoint3[0] = 0.5 * (xmin + xmax);
-  infpoint3[1] = ymax + 60.0 * width;
-
-  /* Create the bounding box. */
-  maketriangle(&inftri);
-  setorg(inftri, infpoint1);
-  setdest(inftri, infpoint2);
-  setapex(inftri, infpoint3);
-  /* Link dummytri to the bounding box so we can always find an */
-  /*   edge to begin searching (point location) from.           */
-  dummytri[0] = (triangle) inftri.tri;
-  if (verbose > 2) {
-    printf("  Creating ");
-    printtriangle(&inftri);
-  }
-}
-
-#endif /* not REDUCED */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  removebox()   Remove the "infinite" bounding triangle, setting boundary  */
-/*                markers as appropriate.                                    */
-/*                                                                           */
-/*  The triangular bounding box has three boundary triangles (one for each   */
-/*  side of the bounding box), and a bunch of triangles fanning out from     */
-/*  the three bounding box vertices (one triangle for each edge of the       */
-/*  convex hull of the inner mesh).  This routine removes these triangles.   */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef REDUCED
-
-long removebox()
-{
-  struct triedge deadtri;
-  struct triedge searchedge;
-  struct triedge checkedge;
-  struct triedge nextedge, finaledge, dissolveedge;
-  point markorg;
-  long hullsize;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose) {
-    printf("  Removing triangular bounding box.\n");
-  }
-  /* Find a boundary triangle. */
-  nextedge.tri = dummytri;
-  nextedge.orient = 0;
-  symself(nextedge);
-  /* Mark a place to stop. */
-  lprev(nextedge, finaledge);
-  lnextself(nextedge);
-  symself(nextedge);
-  /* Find a triangle (on the boundary of the point set) that isn't */
-  /*   a bounding box triangle.                                    */
-  lprev(nextedge, searchedge);
-  symself(searchedge);
-  /* Check whether nextedge is another boundary triangle */
-  /*   adjacent to the first one.                        */
-  lnext(nextedge, checkedge);
-  symself(checkedge);
-  if (checkedge.tri == dummytri) {
-    /* Go on to the next triangle.  There are only three boundary   */
-    /*   triangles, and this next triangle cannot be the third one, */
-    /*   so it's safe to stop here.                                 */
-    lprevself(searchedge);
-    symself(searchedge);
-  }
-  /* Find a new boundary edge to search from, as the current search */
-  /*   edge lies on a bounding box triangle and will be deleted.    */
-  dummytri[0] = encode(searchedge);
-  hullsize = -2l;
-  while (!triedgeequal(nextedge, finaledge)) {
-    hullsize++;
-    lprev(nextedge, dissolveedge);
-    symself(dissolveedge);
-    /* If not using a PSLG, the vertices should be marked now. */
-    /*   (If using a PSLG, markhull() will do the job.)        */
-    if (!poly) {
-      /* Be careful!  One must check for the case where all the input   */
-      /*   points are collinear, and thus all the triangles are part of */
-      /*   the bounding box.  Otherwise, the setpointmark() call below  */
-      /*   will cause a bad pointer reference.                          */
-      if (dissolveedge.tri != dummytri) {
-        org(dissolveedge, markorg);
-        if (pointmark(markorg) == 0) {
-          setpointmark(markorg, 1);
-        }
-      }
-    }
-    /* Disconnect the bounding box triangle from the mesh triangle. */
-    dissolve(dissolveedge);
-    lnext(nextedge, deadtri);
-    sym(deadtri, nextedge);
-    /* Get rid of the bounding box triangle. */
-    triangledealloc(deadtri.tri);
-    /* Do we need to turn the corner? */
-    if (nextedge.tri == dummytri) {
-      /* Turn the corner. */
-      triedgecopy(dissolveedge, nextedge);
-    }
-  }
-  triangledealloc(finaledge.tri);
-
-  free(infpoint1);                  /* Deallocate the bounding box vertices. */
-  free(infpoint2);
-  free(infpoint3);
-
-  return hullsize;
-}
-
-#endif /* not REDUCED */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  incrementaldelaunay()   Form a Delaunay triangulation by incrementally   */
-/*                          adding vertices.                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef REDUCED
-
-long incrementaldelaunay()
-{
-  struct triedge starttri;
-  point pointloop;
-  int i;
-
-  /* Create a triangular bounding box. */
-  boundingbox();
-  if (verbose) {
-    printf("  Incrementally inserting points.\n");
-  }
-  traversalinit(&points);
-  pointloop = pointtraverse();
-  i = 1;
-  while (pointloop != (point) NULL) {
-    /* Find a boundary triangle to search from. */
-    starttri.tri = (triangle *) NULL;
-    if (insertsite(pointloop, &starttri, (struct edge *) NULL, 0, 0) ==
-        DUPLICATEPOINT) {
-      if (!quiet) {
-        printf(
-"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
-               pointloop[0], pointloop[1]);
-      }
-/*  Commented out - would eliminate point from output .node file.
-      setpointmark(pointloop, DEADPOINT);
-*/
-    }
-    pointloop = pointtraverse();
-    i++;
-  }
-  /* Remove the bounding box. */
-  return removebox();
-}
-
-#endif /* not REDUCED */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Incremental Delaunay triangulation ends here              *********/
-
-/********* Sweepline Delaunay triangulation begins here              *********/
-/**                                                                         **/
-/**                                                                         **/
-
-#ifndef REDUCED
-
-void eventheapinsert(heap, heapsize, newevent)
-struct event **heap;
-int heapsize;
-struct event *newevent;
-{
-  REAL eventx, eventy;
-  int eventnum;
-  int parent;
-  int notdone;
-
-  eventx = newevent->xkey;
-  eventy = newevent->ykey;
-  eventnum = heapsize;
-  notdone = eventnum > 0;
-  while (notdone) {
-    parent = (eventnum - 1) >> 1;
-    if ((heap[parent]->ykey < eventy) ||
-        ((heap[parent]->ykey == eventy)
-         && (heap[parent]->xkey <= eventx))) {
-      notdone = 0;
-    } else {
-      heap[eventnum] = heap[parent];
-      heap[eventnum]->heapposition = eventnum;
-
-      eventnum = parent;
-      notdone = eventnum > 0;
-    }
-  }
-  heap[eventnum] = newevent;
-  newevent->heapposition = eventnum;
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-void eventheapify(heap, heapsize, eventnum)
-struct event **heap;
-int heapsize;
-int eventnum;
-{
-  struct event *thisevent;
-  REAL eventx, eventy;
-  int leftchild, rightchild;
-  int smallest;
-  int notdone;
-
-  thisevent = heap[eventnum];
-  eventx = thisevent->xkey;
-  eventy = thisevent->ykey;
-  leftchild = 2 * eventnum + 1;
-  notdone = leftchild < heapsize;
-  while (notdone) {
-    if ((heap[leftchild]->ykey < eventy) ||
-        ((heap[leftchild]->ykey == eventy)
-         && (heap[leftchild]->xkey < eventx))) {
-      smallest = leftchild;
-    } else {
-      smallest = eventnum;
-    }
-    rightchild = leftchild + 1;
-    if (rightchild < heapsize) {
-      if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
-          ((heap[rightchild]->ykey == heap[smallest]->ykey)
-           && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
-        smallest = rightchild;
-      }
-    }
-    if (smallest == eventnum) {
-      notdone = 0;
-    } else {
-      heap[eventnum] = heap[smallest];
-      heap[eventnum]->heapposition = eventnum;
-      heap[smallest] = thisevent;
-      thisevent->heapposition = smallest;
-
-      eventnum = smallest;
-      leftchild = 2 * eventnum + 1;
-      notdone = leftchild < heapsize;
-    }
-  }
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-void eventheapdelete(heap, heapsize, eventnum)
-struct event **heap;
-int heapsize;
-int eventnum;
-{
-  struct event *moveevent;
-  REAL eventx, eventy;
-  int parent;
-  int notdone;
-
-  moveevent = heap[heapsize - 1];
-  if (eventnum > 0) {
-    eventx = moveevent->xkey;
-    eventy = moveevent->ykey;
-    do {
-      parent = (eventnum - 1) >> 1;
-      if ((heap[parent]->ykey < eventy) ||
-          ((heap[parent]->ykey == eventy)
-           && (heap[parent]->xkey <= eventx))) {
-        notdone = 0;
-      } else {
-        heap[eventnum] = heap[parent];
-        heap[eventnum]->heapposition = eventnum;
-
-        eventnum = parent;
-        notdone = eventnum > 0;
-      }
-    } while (notdone);
-  }
-  heap[eventnum] = moveevent;
-  moveevent->heapposition = eventnum;
-  eventheapify(heap, heapsize - 1, eventnum);
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-void createeventheap(eventheap, events, freeevents)
-struct event ***eventheap;
-struct event **events;
-struct event **freeevents;
-{
-  point thispoint;
-  int maxevents;
-  int i;
-
-  maxevents = (3 * inpoints) / 2;
-  *eventheap = (struct event **) malloc(maxevents * sizeof(struct event *));
-  if (*eventheap == (struct event **) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  *events = (struct event *) malloc(maxevents * sizeof(struct event));
-  if (*events == (struct event *) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  traversalinit(&points);
-  for (i = 0; i < inpoints; i++) {
-    thispoint = pointtraverse();
-    (*events)[i].eventptr = (VOID *) thispoint;
-    (*events)[i].xkey = thispoint[0];
-    (*events)[i].ykey = thispoint[1];
-    eventheapinsert(*eventheap, i, *events + i);
-  }
-  *freeevents = (struct event *) NULL;
-  for (i = maxevents - 1; i >= inpoints; i--) {
-    (*events)[i].eventptr = (VOID *) *freeevents;
-    *freeevents = *events + i;
-  }
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-int rightofhyperbola(fronttri, newsite)
-struct triedge *fronttri;
-point newsite;
-{
-  point leftpoint, rightpoint;
-  REAL dxa, dya, dxb, dyb;
-
-  hyperbolacount++;
-
-  dest(*fronttri, leftpoint);
-  apex(*fronttri, rightpoint);
-  if ((leftpoint[1] < rightpoint[1])
-      || ((leftpoint[1] == rightpoint[1]) && (leftpoint[0] < rightpoint[0]))) {
-    if (newsite[0] >= rightpoint[0]) {
-      return 1;
-    }
-  } else {
-    if (newsite[0] <= leftpoint[0]) {
-      return 0;
-    }
-  }
-  dxa = leftpoint[0] - newsite[0];
-  dya = leftpoint[1] - newsite[1];
-  dxb = rightpoint[0] - newsite[0];
-  dyb = rightpoint[1] - newsite[1];
-  return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-REAL circletop(pa, pb, pc, ccwabc)
-point pa;
-point pb;
-point pc;
-REAL ccwabc;
-{
-  REAL xac, yac, xbc, ybc, xab, yab;
-  REAL aclen2, bclen2, ablen2;
-
-  circletopcount++;
-
-  xac = pa[0] - pc[0];
-  yac = pa[1] - pc[1];
-  xbc = pb[0] - pc[0];
-  ybc = pb[1] - pc[1];
-  xab = pa[0] - pb[0];
-  yab = pa[1] - pb[1];
-  aclen2 = xac * xac + yac * yac;
-  bclen2 = xbc * xbc + ybc * ybc;
-  ablen2 = xab * xab + yab * yab;
-  return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
-               / (2.0 * ccwabc);
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-void check4deadevent(checktri, freeevents, eventheap, heapsize)
-struct triedge *checktri;
-struct event **freeevents;
-struct event **eventheap;
-int *heapsize;
-{
-  struct event *deadevent;
-  point eventpoint;
-  int eventnum;
-
-  org(*checktri, eventpoint);
-  if (eventpoint != (point) NULL) {
-    deadevent = (struct event *) eventpoint;
-    eventnum = deadevent->heapposition;
-    deadevent->eventptr = (VOID *) *freeevents;
-    *freeevents = deadevent;
-    eventheapdelete(eventheap, *heapsize, eventnum);
-    (*heapsize)--;
-    setorg(*checktri, NULL);
-  }
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-struct splaynode *splay(splaytree, searchpoint, searchtri)
-struct splaynode *splaytree;
-point searchpoint;
-struct triedge *searchtri;
-{
-  struct splaynode *child, *grandchild;
-  struct splaynode *lefttree, *righttree;
-  struct splaynode *leftright;
-  point checkpoint;
-  int rightofroot, rightofchild;
-
-  if (splaytree == (struct splaynode *) NULL) {
-    return (struct splaynode *) NULL;
-  }
-  dest(splaytree->keyedge, checkpoint);
-  if (checkpoint == splaytree->keydest) {
-    rightofroot = rightofhyperbola(&splaytree->keyedge, searchpoint);
-    if (rightofroot) {
-      triedgecopy(splaytree->keyedge, *searchtri);
-      child = splaytree->rchild;
-    } else {
-      child = splaytree->lchild;
-    }
-    if (child == (struct splaynode *) NULL) {
-      return splaytree;
-    }
-    dest(child->keyedge, checkpoint);
-    if (checkpoint != child->keydest) {
-      child = splay(child, searchpoint, searchtri);
-      if (child == (struct splaynode *) NULL) {
-        if (rightofroot) {
-          splaytree->rchild = (struct splaynode *) NULL;
-        } else {
-          splaytree->lchild = (struct splaynode *) NULL;
-        }
-        return splaytree;
-      }
-    }
-    rightofchild = rightofhyperbola(&child->keyedge, searchpoint);
-    if (rightofchild) {
-      triedgecopy(child->keyedge, *searchtri);
-      grandchild = splay(child->rchild, searchpoint, searchtri);
-      child->rchild = grandchild;
-    } else {
-      grandchild = splay(child->lchild, searchpoint, searchtri);
-      child->lchild = grandchild;
-    }
-    if (grandchild == (struct splaynode *) NULL) {
-      if (rightofroot) {
-        splaytree->rchild = child->lchild;
-        child->lchild = splaytree;
-      } else {
-        splaytree->lchild = child->rchild;
-        child->rchild = splaytree;
-      }
-      return child;
-    }
-    if (rightofchild) {
-      if (rightofroot) {
-        splaytree->rchild = child->lchild;
-        child->lchild = splaytree;
-      } else {
-        splaytree->lchild = grandchild->rchild;
-        grandchild->rchild = splaytree;
-      }
-      child->rchild = grandchild->lchild;
-      grandchild->lchild = child;
-    } else {
-      if (rightofroot) {
-        splaytree->rchild = grandchild->lchild;
-        grandchild->lchild = splaytree;
-      } else {
-        splaytree->lchild = child->rchild;
-        child->rchild = splaytree;
-      }
-      child->lchild = grandchild->rchild;
-      grandchild->rchild = child;
-    }
-    return grandchild;
-  } else {
-    lefttree = splay(splaytree->lchild, searchpoint, searchtri);
-    righttree = splay(splaytree->rchild, searchpoint, searchtri);
-
-    pooldealloc(&splaynodes, (VOID *) splaytree);
-    if (lefttree == (struct splaynode *) NULL) {
-      return righttree;
-    } else if (righttree == (struct splaynode *) NULL) {
-      return lefttree;
-    } else if (lefttree->rchild == (struct splaynode *) NULL) {
-      lefttree->rchild = righttree->lchild;
-      righttree->lchild = lefttree;
-      return righttree;
-    } else if (righttree->lchild == (struct splaynode *) NULL) {
-      righttree->lchild = lefttree->rchild;
-      lefttree->rchild = righttree;
-      return lefttree;
-    } else {
-/*      printf("Holy Toledo!!!\n"); */
-      leftright = lefttree->rchild;
-      while (leftright->rchild != (struct splaynode *) NULL) {
-        leftright = leftright->rchild;
-      }
-      leftright->rchild = righttree;
-      return lefttree;
-    }
-  }
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-struct splaynode *splayinsert(splayroot, newkey, searchpoint)
-struct splaynode *splayroot;
-struct triedge *newkey;
-point searchpoint;
-{
-  struct splaynode *newsplaynode;
-
-  newsplaynode = (struct splaynode *) poolalloc(&splaynodes);
-  triedgecopy(*newkey, newsplaynode->keyedge);
-  dest(*newkey, newsplaynode->keydest);
-  if (splayroot == (struct splaynode *) NULL) {
-    newsplaynode->lchild = (struct splaynode *) NULL;
-    newsplaynode->rchild = (struct splaynode *) NULL;
-  } else if (rightofhyperbola(&splayroot->keyedge, searchpoint)) {
-    newsplaynode->lchild = splayroot;
-    newsplaynode->rchild = splayroot->rchild;
-    splayroot->rchild = (struct splaynode *) NULL;
-  } else {
-    newsplaynode->lchild = splayroot->lchild;
-    newsplaynode->rchild = splayroot;
-    splayroot->lchild = (struct splaynode *) NULL;
-  }
-  return newsplaynode;
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-struct splaynode *circletopinsert(splayroot, newkey, pa, pb, pc, topy)
-struct splaynode *splayroot;
-struct triedge *newkey;
-point pa;
-point pb;
-point pc;
-REAL topy;
-{
-  REAL ccwabc;
-  REAL xac, yac, xbc, ybc;
-  REAL aclen2, bclen2;
-  REAL searchpoint[2];
-  struct triedge dummytri;
-
-  ccwabc = counterclockwise(pa, pb, pc);
-  xac = pa[0] - pc[0];
-  yac = pa[1] - pc[1];
-  xbc = pb[0] - pc[0];
-  ybc = pb[1] - pc[1];
-  aclen2 = xac * xac + yac * yac;
-  bclen2 = xbc * xbc + ybc * ybc;
-  searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
-  searchpoint[1] = topy;
-  return splayinsert(splay(splayroot, (point) searchpoint, &dummytri), newkey,
-                     (point) searchpoint);
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-struct splaynode *frontlocate(splayroot, bottommost, searchpoint, searchtri,
-                              farright)
-struct splaynode *splayroot;
-struct triedge *bottommost;
-point searchpoint;
-struct triedge *searchtri;
-int *farright;
-{
-  int farrightflag;
-  triangle ptr;                       /* Temporary variable used by onext(). */
-
-  triedgecopy(*bottommost, *searchtri);
-  splayroot = splay(splayroot, searchpoint, searchtri);
-
-  farrightflag = 0;
-  while (!farrightflag && rightofhyperbola(searchtri, searchpoint)) {
-    onextself(*searchtri);
-    farrightflag = triedgeequal(*searchtri, *bottommost);
-  }
-  *farright = farrightflag;
-  return splayroot;
-}
-
-#endif /* not REDUCED */
-
-#ifndef REDUCED
-
-long sweeplinedelaunay()
-{
-  struct event **eventheap;
-  struct event *events;
-  struct event *freeevents;
-  struct event *nextevent;
-  struct event *newevent;
-  struct splaynode *splayroot;
-  struct triedge bottommost;
-  struct triedge searchtri;
-  struct triedge fliptri;
-  struct triedge lefttri, righttri, farlefttri, farrighttri;
-  struct triedge inserttri;
-  point firstpoint, secondpoint;
-  point nextpoint, lastpoint;
-  point connectpoint;
-  point leftpoint, midpoint, rightpoint;
-  REAL lefttest, righttest;
-  int heapsize;
-  int check4events, farrightflag;
-  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
-
-  poolinit(&splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK, POINTER,
-           0);
-  splayroot = (struct splaynode *) NULL;
-
-  if (verbose) {
-    printf("  Placing points in event heap.\n");
-  }
-  createeventheap(&eventheap, &events, &freeevents);
-  heapsize = inpoints;
-
-  if (verbose) {
-    printf("  Forming triangulation.\n");
-  }
-  maketriangle(&lefttri);
-  maketriangle(&righttri);
-  bond(lefttri, righttri);
-  lnextself(lefttri);
-  lprevself(righttri);
-  bond(lefttri, righttri);
-  lnextself(lefttri);
-  lprevself(righttri);
-  bond(lefttri, righttri);
-  firstpoint = (point) eventheap[0]->eventptr;
-  eventheap[0]->eventptr = (VOID *) freeevents;
-  freeevents = eventheap[0];
-  eventheapdelete(eventheap, heapsize, 0);
-  heapsize--;
-  do {
-    if (heapsize == 0) {
-      printf("Error:  Input points are all identical.\n");
-      exit(1);
-    }
-    secondpoint = (point) eventheap[0]->eventptr;
-    eventheap[0]->eventptr = (VOID *) freeevents;
-    freeevents = eventheap[0];
-    eventheapdelete(eventheap, heapsize, 0);
-    heapsize--;
-    if ((firstpoint[0] == secondpoint[0])
-        && (firstpoint[1] == secondpoint[1])) {
-      printf(
-"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
-             secondpoint[0], secondpoint[1]);
-/*  Commented out - would eliminate point from output .node file.
-      setpointmark(secondpoint, DEADPOINT);
-*/
-    }
-  } while ((firstpoint[0] == secondpoint[0])
-           && (firstpoint[1] == secondpoint[1]));
-  setorg(lefttri, firstpoint);
-  setdest(lefttri, secondpoint);
-  setorg(righttri, secondpoint);
-  setdest(righttri, firstpoint);
-  lprev(lefttri, bottommost);
-  lastpoint = secondpoint;
-  while (heapsize > 0) {
-    nextevent = eventheap[0];
-    eventheapdelete(eventheap, heapsize, 0);
-    heapsize--;
-    check4events = 1;
-    if (nextevent->xkey < xmin) {
-      decode(nextevent->eventptr, fliptri);
-      oprev(fliptri, farlefttri);
-      check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
-      onext(fliptri, farrighttri);
-      check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
-
-      if (triedgeequal(farlefttri, bottommost)) {
-        lprev(fliptri, bottommost);
-      }
-      flip(&fliptri);
-      setapex(fliptri, NULL);
-      lprev(fliptri, lefttri);
-      lnext(fliptri, righttri);
-      sym(lefttri, farlefttri);
-
-      if (randomnation(SAMPLERATE) == 0) {
-        symself(fliptri);
-        dest(fliptri, leftpoint);
-        apex(fliptri, midpoint);
-        org(fliptri, rightpoint);
-        splayroot = circletopinsert(splayroot, &lefttri, leftpoint, midpoint,
-                                    rightpoint, nextevent->ykey);
-      }
-    } else {
-      nextpoint = (point) nextevent->eventptr;
-      if ((nextpoint[0] == lastpoint[0]) && (nextpoint[1] == lastpoint[1])) {
-        printf(
-"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
-               nextpoint[0], nextpoint[1]);
-/*  Commented out - would eliminate point from output .node file.
-        setpointmark(nextpoint, DEADPOINT);
-*/
-        check4events = 0;
-      } else {
-        lastpoint = nextpoint;
-
-        splayroot = frontlocate(splayroot, &bottommost, nextpoint, &searchtri,
-                                &farrightflag);
-/*
-        triedgecopy(bottommost, searchtri);
-        farrightflag = 0;
-        while (!farrightflag && rightofhyperbola(&searchtri, nextpoint)) {
-          onextself(searchtri);
-          farrightflag = triedgeequal(searchtri, bottommost);
-        }
-*/
-
-        check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
-
-        triedgecopy(searchtri, farrighttri);
-        sym(searchtri, farlefttri);
-        maketriangle(&lefttri);
-        maketriangle(&righttri);
-        dest(farrighttri, connectpoint);
-        setorg(lefttri, connectpoint);
-        setdest(lefttri, nextpoint);
-        setorg(righttri, nextpoint);
-        setdest(righttri, connectpoint);
-        bond(lefttri, righttri);
-        lnextself(lefttri);
-        lprevself(righttri);
-        bond(lefttri, righttri);
-        lnextself(lefttri);
-        lprevself(righttri);
-        bond(lefttri, farlefttri);
-        bond(righttri, farrighttri);
-        if (!farrightflag && triedgeequal(farrighttri, bottommost)) {
-          triedgecopy(lefttri, bottommost);
-        }
-
-        if (randomnation(SAMPLERATE) == 0) {
-          splayroot = splayinsert(splayroot, &lefttri, nextpoint);
-        } else if (randomnation(SAMPLERATE) == 0) {
-          lnext(righttri, inserttri);
-          splayroot = splayinsert(splayroot, &inserttri, nextpoint);
-        }
-      }
-    }
-    nextevent->eventptr = (VOID *) freeevents;
-    freeevents = nextevent;
-
-    if (check4events) {
-      apex(farlefttri, leftpoint);
-      dest(lefttri, midpoint);
-      apex(lefttri, rightpoint);
-      lefttest = counterclockwise(leftpoint, midpoint, rightpoint);
-      if (lefttest > 0.0) {
-        newevent = freeevents;
-        freeevents = (struct event *) freeevents->eventptr;
-        newevent->xkey = xminextreme;
-        newevent->ykey = circletop(leftpoint, midpoint, rightpoint,
-                                   lefttest);
-        newevent->eventptr = (VOID *) encode(lefttri);
-        eventheapinsert(eventheap, heapsize, newevent);
-        heapsize++;
-        setorg(lefttri, newevent);
-      }
-      apex(righttri, leftpoint);
-      org(righttri, midpoint);
-      apex(farrighttri, rightpoint);
-      righttest = counterclockwise(leftpoint, midpoint, rightpoint);
-      if (righttest > 0.0) {
-        newevent = freeevents;
-        freeevents = (struct event *) freeevents->eventptr;
-        newevent->xkey = xminextreme;
-        newevent->ykey = circletop(leftpoint, midpoint, rightpoint,
-                                   righttest);
-        newevent->eventptr = (VOID *) encode(farrighttri);
-        eventheapinsert(eventheap, heapsize, newevent);
-        heapsize++;
-        setorg(farrighttri, newevent);
-      }
-    }
-  }
-
-  pooldeinit(&splaynodes);
-  lprevself(bottommost);
-  return removeghosts(&bottommost);
-}
-
-#endif /* not REDUCED */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Sweepline Delaunay triangulation ends here                *********/
-
-/********* General mesh construction routines begin here             *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  delaunay()   Form a Delaunay triangulation.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-long delaunay()
-{
-  eextras = 0;
-  initializetrisegpools();
-
-#ifdef REDUCED
-  if (!quiet) {
-    printf(
-      "Constructing Delaunay triangulation by divide-and-conquer method.\n");
-  }
-  return divconqdelaunay();
-#else /* not REDUCED */
-  if (!quiet) {
-    printf("Constructing Delaunay triangulation ");
-    if (incremental) {
-      printf("by incremental method.\n");
-    } else if (sweepline) {
-      printf("by sweepline method.\n");
-    } else {
-      printf("by divide-and-conquer method.\n");
-    }
-  }
-  if (incremental) {
-    return incrementaldelaunay();
-  } else if (sweepline) {
-    return sweeplinedelaunay();
-  } else {
-    return divconqdelaunay();
-  }
-#endif /* not REDUCED */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  reconstruct()   Reconstruct a triangulation from its .ele (and possibly  */
-/*                  .poly) file.  Used when the -r switch is used.           */
-/*                                                                           */
-/*  Reads an .ele file and reconstructs the original mesh.  If the -p switch */
-/*  is used, this procedure will also read a .poly file and reconstruct the  */
-/*  shell edges of the original mesh.  If the -a switch is used, this        */
-/*  procedure will also read an .area file and set a maximum area constraint */
-/*  on each triangle.                                                        */
-/*                                                                           */
-/*  Points that are not corners of triangles, such as nodes on edges of      */
-/*  subparametric elements, are discarded.                                   */
-/*                                                                           */
-/*  This routine finds the adjacencies between triangles (and shell edges)   */
-/*  by forming one stack of triangles for each vertex.  Each triangle is on  */
-/*  three different stacks simultaneously.  Each triangle's shell edge       */
-/*  pointers are used to link the items in each stack.  This memory-saving   */
-/*  feature makes the code harder to read.  The most important thing to keep */
-/*  in mind is that each triangle is removed from a stack precisely when     */
-/*  the corresponding pointer is adjusted to refer to a shell edge rather    */
-/*  than the next triangle of the stack.                                     */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-#ifdef TRILIBRARY
-
-int reconstruct(trianglelist, triangleattriblist, trianglearealist, elements,
-                corners, attribs, segmentlist, segmentmarkerlist,
-                numberofsegments)
-int *trianglelist;
-REAL *triangleattriblist;
-REAL *trianglearealist;
-int elements;
-int corners;
-int attribs;
-int *segmentlist;
-int *segmentmarkerlist;
-int numberofsegments;
-
-#else /* not TRILIBRARY */
-
-long reconstruct(elefilename, areafilename, polyfilename, polyfile)
-char *elefilename;
-char *areafilename;
-char *polyfilename;
-FILE *polyfile;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  int pointindex;
-  int attribindex;
-#else /* not TRILIBRARY */
-  FILE *elefile;
-  FILE *areafile;
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  int areaelements;
-#endif /* not TRILIBRARY */
-  struct triedge triangleloop;
-  struct triedge triangleleft;
-  struct triedge checktri;
-  struct triedge checkleft;
-  struct triedge checkneighbor;
-  struct edge shelleloop;
-  triangle *vertexarray;
-  triangle *prevlink;
-  triangle nexttri;
-  point tdest, tapex;
-  point checkdest, checkapex;
-  point shorg;
-  point killpoint;
-  REAL area;
-  int corner[3];
-  int end[2];
-  int killpointindex;
-  int incorners;
-  int segmentmarkers;
-  int boundmarker;
-  int aroundpoint;
-  long hullsize;
-  int notfound;
-  int elementnumber, segmentnumber;
-  int i, j;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-#ifdef TRILIBRARY
-  inelements = elements;
-  incorners = corners;
-  if (incorners < 3) {
-    printf("Error:  Triangles must have at least 3 points.\n");
-    exit(1);
-  }
-  eextras = attribs;
-#else /* not TRILIBRARY */
-  /* Read the triangles from an .ele file. */
-  if (!quiet) {
-    printf("Opening %s.\n", elefilename);
-  }
-  elefile = fopen(elefilename, "r");
-  if (elefile == (FILE *) NULL) {
-    printf("  Error:  Cannot access file %s.\n", elefilename);
-    exit(1);
-  }
-  /* Read number of triangles, number of points per triangle, and */
-  /*   number of triangle attributes from .ele file.              */
-  stringptr = readline(inputline, elefile, elefilename);
-  inelements = (int) strtol (stringptr, &stringptr, 0);
-  stringptr = findfield(stringptr);
-  if (*stringptr == '\0') {
-    incorners = 3;
-  } else {
-    incorners = (int) strtol (stringptr, &stringptr, 0);
-    if (incorners < 3) {
-      printf("Error:  Triangles in %s must have at least 3 points.\n",
-             elefilename);
-      exit(1);
-    }
-  }
-  stringptr = findfield(stringptr);
-  if (*stringptr == '\0') {
-    eextras = 0;
-  } else {
-    eextras = (int) strtol (stringptr, &stringptr, 0);
-  }
-#endif /* not TRILIBRARY */
-
-  initializetrisegpools();
-
-  /* Create the triangles. */
-  for (elementnumber = 1; elementnumber <= inelements; elementnumber++) {
-    maketriangle(&triangleloop);
-    /* Mark the triangle as living. */
-    triangleloop.tri[3] = (triangle) triangleloop.tri;
-  }
-
-  if (poly) {
-#ifdef TRILIBRARY
-    insegments = numberofsegments;
-    segmentmarkers = segmentmarkerlist != (int *) NULL;
-#else /* not TRILIBRARY */
-    /* Read number of segments and number of segment */
-    /*   boundary markers from .poly file.           */
-    stringptr = readline(inputline, polyfile, inpolyfilename);
-    insegments = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      segmentmarkers = 0;
-    } else {
-      segmentmarkers = (int) strtol (stringptr, &stringptr, 0);
-    }
-#endif /* not TRILIBRARY */
-
-    /* Create the shell edges. */
-    for (segmentnumber = 1; segmentnumber <= insegments; segmentnumber++) {
-      makeshelle(&shelleloop);
-      /* Mark the shell edge as living. */
-      shelleloop.sh[2] = (shelle) shelleloop.sh;
-    }
-  }
-
-#ifdef TRILIBRARY
-  pointindex = 0;
-  attribindex = 0;
-#else /* not TRILIBRARY */
-  if (vararea) {
-    /* Open an .area file, check for consistency with the .ele file. */
-    if (!quiet) {
-      printf("Opening %s.\n", areafilename);
-    }
-    areafile = fopen(areafilename, "r");
-    if (areafile == (FILE *) NULL) {
-      printf("  Error:  Cannot access file %s.\n", areafilename);
-      exit(1);
-    }
-    stringptr = readline(inputline, areafile, areafilename);
-    areaelements = (int) strtol (stringptr, &stringptr, 0);
-    if (areaelements != inelements) {
-      printf("Error:  %s and %s disagree on number of triangles.\n",
-             elefilename, areafilename);
-      exit(1);
-    }
-  }
-#endif /* not TRILIBRARY */
-
-  if (!quiet) {
-    printf("Reconstructing mesh.\n");
-  }
-  /* Allocate a temporary array that maps each point to some adjacent  */
-  /*   triangle.  I took care to allocate all the permanent memory for */
-  /*   triangles and shell edges first.                                */
-  vertexarray = (triangle *) malloc(points.items * sizeof(triangle));
-  if (vertexarray == (triangle *) NULL) {
-    printf("Error:  Out of memory.\n");
-    exit(1);
-  }
-  /* Each point is initially unrepresented. */
-  for (i = 0; i < points.items; i++) {
-    vertexarray[i] = (triangle) dummytri;
-  }
-
-  if (verbose) {
-    printf("  Assembling triangles.\n");
-  }
-  /* Read the triangles from the .ele file, and link */
-  /*   together those that share an edge.            */
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  elementnumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-#ifdef TRILIBRARY
-    /* Copy the triangle's three corners. */
-    for (j = 0; j < 3; j++) {
-      corner[j] = trianglelist[pointindex++];
-      if ((corner[j] < firstnumber) || (corner[j] >= firstnumber + inpoints)) {
-        printf("Error:  Triangle %d has an invalid vertex index.\n",
-               elementnumber);
-        exit(1);
-      }
-    }
-#else /* not TRILIBRARY */
-    /* Read triangle number and the triangle's three corners. */
-    stringptr = readline(inputline, elefile, elefilename);
-    for (j = 0; j < 3; j++) {
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Triangle %d is missing point %d in %s.\n",
-               elementnumber, j + 1, elefilename);
-        exit(1);
-      } else {
-        corner[j] = (int) strtol (stringptr, &stringptr, 0);
-        if ((corner[j] < firstnumber) ||
-            (corner[j] >= firstnumber + inpoints)) {
-          printf("Error:  Triangle %d has an invalid vertex index.\n",
-                 elementnumber);
-          exit(1);
-        }
-      }
-    }
-#endif /* not TRILIBRARY */
-
-    /* Find out about (and throw away) extra nodes. */
-    for (j = 3; j < incorners; j++) {
-#ifdef TRILIBRARY
-      killpointindex = trianglelist[pointindex++];
-#else /* not TRILIBRARY */
-      stringptr = findfield(stringptr);
-      if (*stringptr != '\0') {
-        killpointindex = (int) strtol (stringptr, &stringptr, 0);
-#endif /* not TRILIBRARY */
-        if ((killpointindex >= firstnumber) &&
-            (killpointindex < firstnumber + inpoints)) {
-          /* Delete the non-corner point if it's not already deleted. */
-          killpoint = getpoint(killpointindex);
-          if (pointmark(killpoint) != DEADPOINT) {
-            pointdealloc(killpoint);
-          }
-        }
-#ifndef TRILIBRARY
-      }
-#endif /* not TRILIBRARY */
-    }
-
-    /* Read the triangle's attributes. */
-    for (j = 0; j < eextras; j++) {
-#ifdef TRILIBRARY
-      setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
-#else /* not TRILIBRARY */
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        setelemattribute(triangleloop, j, 0);
-      } else {
-        setelemattribute(triangleloop, j,
-                         (REAL) strtod (stringptr, &stringptr));
-      }
-#endif /* not TRILIBRARY */
-    }
-
-    if (vararea) {
-#ifdef TRILIBRARY
-      area = trianglearealist[elementnumber - firstnumber];
-#else /* not TRILIBRARY */
-      /* Read an area constraint from the .area file. */
-      stringptr = readline(inputline, areafile, areafilename);
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        area = -1.0;                      /* No constraint on this triangle. */
-      } else {
-        area = (REAL) strtod(stringptr, &stringptr);
-      }
-#endif /* not TRILIBRARY */
-      setareabound(triangleloop, area);
-    }
-
-    /* Set the triangle's vertices. */
-    triangleloop.orient = 0;
-    setorg(triangleloop, getpoint(corner[0]));
-    setdest(triangleloop, getpoint(corner[1]));
-    setapex(triangleloop, getpoint(corner[2]));
-    /* Try linking the triangle to others that share these vertices. */
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      /* Take the number for the origin of triangleloop. */
-      aroundpoint = corner[triangleloop.orient];
-      /* Look for other triangles having this vertex. */
-      nexttri = vertexarray[aroundpoint - firstnumber];
-      /* Link the current triangle to the next one in the stack. */
-      triangleloop.tri[6 + triangleloop.orient] = nexttri;
-      /* Push the current triangle onto the stack. */
-      vertexarray[aroundpoint - firstnumber] = encode(triangleloop);
-      decode(nexttri, checktri);
-      if (checktri.tri != dummytri) {
-        dest(triangleloop, tdest);
-        apex(triangleloop, tapex);
-        /* Look for other triangles that share an edge. */
-        do {
-          dest(checktri, checkdest);
-          apex(checktri, checkapex);
-          if (tapex == checkdest) {
-            /* The two triangles share an edge; bond them together. */
-            lprev(triangleloop, triangleleft);
-            bond(triangleleft, checktri);
-          }
-          if (tdest == checkapex) {
-            /* The two triangles share an edge; bond them together. */
-            lprev(checktri, checkleft);
-            bond(triangleloop, checkleft);
-          }
-          /* Find the next triangle in the stack. */
-          nexttri = checktri.tri[6 + checktri.orient];
-          decode(nexttri, checktri);
-        } while (checktri.tri != dummytri);
-      }
-    }
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-
-#ifdef TRILIBRARY
-  pointindex = 0;
-#else /* not TRILIBRARY */
-  fclose(elefile);
-  if (vararea) {
-    fclose(areafile);
-  }
-#endif /* not TRILIBRARY */
-
-  hullsize = 0;                      /* Prepare to count the boundary edges. */
-  if (poly) {
-    if (verbose) {
-      printf("  Marking segments in triangulation.\n");
-    }
-    /* Read the segments from the .poly file, and link them */
-    /*   to their neighboring triangles.                    */
-    boundmarker = 0;
-    traversalinit(&shelles);
-    shelleloop.sh = shelletraverse();
-    segmentnumber = firstnumber;
-    while (shelleloop.sh != (shelle *) NULL) {
-#ifdef TRILIBRARY
-      end[0] = segmentlist[pointindex++];
-      end[1] = segmentlist[pointindex++];
-      if (segmentmarkers) {
-        boundmarker = segmentmarkerlist[segmentnumber - firstnumber];
-      }
-#else /* not TRILIBRARY */
-      /* Read the endpoints of each segment, and possibly a boundary marker. */
-      stringptr = readline(inputline, polyfile, inpolyfilename);
-      /* Skip the first (segment number) field. */
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Segment %d has no endpoints in %s.\n", segmentnumber,
-               polyfilename);
-        exit(1);
-      } else {
-        end[0] = (int) strtol (stringptr, &stringptr, 0);
-      }
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Segment %d is missing its second endpoint in %s.\n",
-               segmentnumber, polyfilename);
-        exit(1);
-      } else {
-        end[1] = (int) strtol (stringptr, &stringptr, 0);
-      }
-      if (segmentmarkers) {
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          boundmarker = 0;
-        } else {
-          boundmarker = (int) strtol (stringptr, &stringptr, 0);
-        }
-      }
-#endif /* not TRILIBRARY */
-      for (j = 0; j < 2; j++) {
-        if ((end[j] < firstnumber) || (end[j] >= firstnumber + inpoints)) {
-          printf("Error:  Segment %d has an invalid vertex index.\n", 
-                 segmentnumber);
-          exit(1);
-        }
-      }
-
-      /* set the shell edge's vertices. */
-      shelleloop.shorient = 0;
-      setsorg(shelleloop, getpoint(end[0]));
-      setsdest(shelleloop, getpoint(end[1]));
-      setmark(shelleloop, boundmarker);
-      /* Try linking the shell edge to triangles that share these vertices. */
-      for (shelleloop.shorient = 0; shelleloop.shorient < 2;
-           shelleloop.shorient++) {
-        /* Take the number for the destination of shelleloop. */
-        aroundpoint = end[1 - shelleloop.shorient];
-        /* Look for triangles having this vertex. */
-        prevlink = &vertexarray[aroundpoint - firstnumber];
-        nexttri = vertexarray[aroundpoint - firstnumber];
-        decode(nexttri, checktri);
-        sorg(shelleloop, shorg);
-        notfound = 1;
-        /* Look for triangles having this edge.  Note that I'm only       */
-        /*   comparing each triangle's destination with the shell edge;   */
-        /*   each triangle's apex is handled through a different vertex.  */
-        /*   Because each triangle appears on three vertices' lists, each */
-        /*   occurrence of a triangle on a list can (and does) represent  */
-        /*   an edge.  In this way, most edges are represented twice, and */
-        /*   every triangle-segment bond is represented once.             */
-        while (notfound && (checktri.tri != dummytri)) {
-          dest(checktri, checkdest);
-          if (shorg == checkdest) {
-            /* We have a match.  Remove this triangle from the list. */
-            *prevlink = checktri.tri[6 + checktri.orient];
-            /* Bond the shell edge to the triangle. */
-            tsbond(checktri, shelleloop);
-            /* Check if this is a boundary edge. */
-            sym(checktri, checkneighbor);
-            if (checkneighbor.tri == dummytri) {
-              /* The next line doesn't insert a shell edge (because there's */
-              /*   already one there), but it sets the boundary markers of  */
-              /*   the existing shell edge and its vertices.                */
-              insertshelle(&checktri, 1);
-              hullsize++;
-            }
-            notfound = 0;
-          }
-          /* Find the next triangle in the stack. */
-          prevlink = &checktri.tri[6 + checktri.orient];
-          nexttri = checktri.tri[6 + checktri.orient];
-          decode(nexttri, checktri);
-        }
-      }
-      shelleloop.sh = shelletraverse();
-      segmentnumber++;
-    }
-  }
-
-  /* Mark the remaining edges as not being attached to any shell edge. */
-  /* Also, count the (yet uncounted) boundary edges.                   */
-  for (i = 0; i < points.items; i++) {
-    /* Search the stack of triangles adjacent to a point. */
-    nexttri = vertexarray[i];
-    decode(nexttri, checktri);
-    while (checktri.tri != dummytri) {
-      /* Find the next triangle in the stack before this */
-      /*   information gets overwritten.                 */
-      nexttri = checktri.tri[6 + checktri.orient];
-      /* No adjacent shell edge.  (This overwrites the stack info.) */
-      tsdissolve(checktri);
-      sym(checktri, checkneighbor);
-      if (checkneighbor.tri == dummytri) {
-        insertshelle(&checktri, 1);
-        hullsize++;
-      }
-      decode(nexttri, checktri);
-    }
-  }
-
-  free(vertexarray);
-  return hullsize;
-}
-
-#endif /* not CDT_ONLY */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* General mesh construction routines end here               *********/
-
-/********* Segment (shell edge) insertion begins here                *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  finddirection()   Find the first triangle on the path from one point     */
-/*                    to another.                                            */
-/*                                                                           */
-/*  Finds the triangle that intersects a line segment drawn from the         */
-/*  origin of `searchtri' to the point `endpoint', and returns the result    */
-/*  in `searchtri'.  The origin of `searchtri' does not change, even though  */
-/*  the triangle returned may differ from the one passed in.  This routine   */
-/*  is used to find the direction to move in to get from one point to        */
-/*  another.                                                                 */
-/*                                                                           */
-/*  The return value notes whether the destination or apex of the found      */
-/*  triangle is collinear with the two points in question.                   */
-/*                                                                           */
-/*****************************************************************************/
-
-enum finddirectionresult finddirection(searchtri, endpoint)
-struct triedge *searchtri;
-point endpoint;
-{
-  struct triedge checktri;
-  point startpoint;
-  point leftpoint, rightpoint;
-  REAL leftccw, rightccw;
-  int leftflag, rightflag;
-  triangle ptr;           /* Temporary variable used by onext() and oprev(). */
-
-  org(*searchtri, startpoint);
-  dest(*searchtri, rightpoint);
-  apex(*searchtri, leftpoint);
-  /* Is `endpoint' to the left? */
-  leftccw = counterclockwise(endpoint, startpoint, leftpoint);
-  leftflag = leftccw > 0.0;
-  /* Is `endpoint' to the right? */
-  rightccw = counterclockwise(startpoint, endpoint, rightpoint);
-  rightflag = rightccw > 0.0;
-  if (leftflag && rightflag) {
-    /* `searchtri' faces directly away from `endpoint'.  We could go */
-    /*   left or right.  Ask whether it's a triangle or a boundary   */
-    /*   on the left.                                                */
-    onext(*searchtri, checktri);
-    if (checktri.tri == dummytri) {
-      leftflag = 0;
-    } else {
-      rightflag = 0;
-    }
-  }
-  while (leftflag) {
-    /* Turn left until satisfied. */
-    onextself(*searchtri);
-    if (searchtri->tri == dummytri) {
-      printf("Internal error in finddirection():  Unable to find a\n");
-      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
-             startpoint[1]);
-      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
-      internalerror();
-    }
-    apex(*searchtri, leftpoint);
-    rightccw = leftccw;
-    leftccw = counterclockwise(endpoint, startpoint, leftpoint);
-    leftflag = leftccw > 0.0;
-  }
-  while (rightflag) {
-    /* Turn right until satisfied. */
-    oprevself(*searchtri);
-    if (searchtri->tri == dummytri) {
-      printf("Internal error in finddirection():  Unable to find a\n");
-      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
-             startpoint[1]);
-      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
-      internalerror();
-    }
-    dest(*searchtri, rightpoint);
-    leftccw = rightccw;
-    rightccw = counterclockwise(startpoint, endpoint, rightpoint);
-    rightflag = rightccw > 0.0;
-  }
-  if (leftccw == 0.0) {
-    return LEFTCOLLINEAR;
-  } else if (rightccw == 0.0) {
-    return RIGHTCOLLINEAR;
-  } else {
-    return WITHIN;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  segmentintersection()   Find the intersection of an existing segment     */
-/*                          and a segment that is being inserted.  Insert    */
-/*                          a point at the intersection, splitting an        */
-/*                          existing shell edge.                             */
-/*                                                                           */
-/*  The segment being inserted connects the apex of splittri to endpoint2.   */
-/*  splitshelle is the shell edge being split, and MUST be opposite          */
-/*  splittri.  Hence, the edge being split connects the origin and           */
-/*  destination of splittri.                                                 */
-/*                                                                           */
-/*  On completion, splittri is a handle having the newly inserted            */
-/*  intersection point as its origin, and endpoint1 as its destination.      */
-/*                                                                           */
-/*****************************************************************************/
-
-void segmentintersection(splittri, splitshelle, endpoint2)
-struct triedge *splittri;
-struct edge *splitshelle;
-point endpoint2;
-{
-  point endpoint1;
-  point torg, tdest;
-  point leftpoint, rightpoint;
-  point newpoint;
-  enum insertsiteresult success;
-  enum finddirectionresult collinear;
-  REAL ex, ey;
-  REAL tx, ty;
-  REAL etx, ety;
-  REAL split, denom;
-  int i;
-  triangle ptr;                       /* Temporary variable used by onext(). */
-
-  /* Find the other three segment endpoints. */
-  apex(*splittri, endpoint1);
-  org(*splittri, torg);
-  dest(*splittri, tdest);
-  /* Segment intersection formulae; see the Antonio reference. */
-  tx = tdest[0] - torg[0];
-  ty = tdest[1] - torg[1];
-  ex = endpoint2[0] - endpoint1[0];
-  ey = endpoint2[1] - endpoint1[1];
-  etx = torg[0] - endpoint2[0];
-  ety = torg[1] - endpoint2[1];
-  denom = ty * ex - tx * ey;
-  if (denom == 0.0) {
-    printf("Internal error in segmentintersection():");
-    printf("  Attempt to find intersection of parallel segments.\n");
-    internalerror();
-  }
-  split = (ey * etx - ex * ety) / denom;
-  /* Create the new point. */
-  newpoint = (point) poolalloc(&points);
-  /* Interpolate its coordinate and attributes. */
-  for (i = 0; i < 2 + nextras; i++) {
-    newpoint[i] = torg[i] + split * (tdest[i] - torg[i]);
-  }
-  setpointmark(newpoint, mark(*splitshelle));
-  if (verbose > 1) {
-    printf(
-    "  Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
-           torg[0], torg[1], tdest[0], tdest[1], newpoint[0], newpoint[1]);
-  }
-  /* Insert the intersection point.  This should always succeed. */
-  success = insertsite(newpoint, splittri, splitshelle, 0, 0);
-  if (success != SUCCESSFULPOINT) {
-    printf("Internal error in segmentintersection():\n");
-    printf("  Failure to split a segment.\n");
-    internalerror();
-  }
-  if (steinerleft > 0) {
-    steinerleft--;
-  }
-  /* Inserting the point may have caused edge flips.  We wish to rediscover */
-  /*   the edge connecting endpoint1 to the new intersection point.         */
-  collinear = finddirection(splittri, endpoint1);
-  dest(*splittri, rightpoint);
-  apex(*splittri, leftpoint);
-  if ((leftpoint[0] == endpoint1[0]) && (leftpoint[1] == endpoint1[1])) {
-    onextself(*splittri);
-  } else if ((rightpoint[0] != endpoint1[0]) ||
-             (rightpoint[1] != endpoint1[1])) {
-    printf("Internal error in segmentintersection():\n");
-    printf("  Topological inconsistency after splitting a segment.\n");
-    internalerror();
-  }
-  /* `splittri' should have destination endpoint1. */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  scoutsegment()   Scout the first triangle on the path from one endpoint  */
-/*                   to another, and check for completion (reaching the      */
-/*                   second endpoint), a collinear point, and the            */
-/*                   intersection of two segments.                           */
-/*                                                                           */
-/*  Returns one if the entire segment is successfully inserted, and zero if  */
-/*  the job must be finished by conformingedge() or constrainededge().       */
-/*                                                                           */
-/*  If the first triangle on the path has the second endpoint as its         */
-/*  destination or apex, a shell edge is inserted and the job is done.       */
-/*                                                                           */
-/*  If the first triangle on the path has a destination or apex that lies on */
-/*  the segment, a shell edge is inserted connecting the first endpoint to   */
-/*  the collinear point, and the search is continued from the collinear      */
-/*  point.                                                                   */
-/*                                                                           */
-/*  If the first triangle on the path has a shell edge opposite its origin,  */
-/*  then there is a segment that intersects the segment being inserted.      */
-/*  Their intersection point is inserted, splitting the shell edge.          */
-/*                                                                           */
-/*  Otherwise, return zero.                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-int scoutsegment(searchtri, endpoint2, newmark)
-struct triedge *searchtri;
-point endpoint2;
-int newmark;
-{
-  struct triedge crosstri;
-  struct edge crossedge;
-  point leftpoint, rightpoint;
-  point endpoint1;
-  enum finddirectionresult collinear;
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  collinear = finddirection(searchtri, endpoint2);
-  dest(*searchtri, rightpoint);
-  apex(*searchtri, leftpoint);
-  if (((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) ||
-      ((rightpoint[0] == endpoint2[0]) && (rightpoint[1] == endpoint2[1]))) {
-    /* The segment is already an edge in the mesh. */
-    if ((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) {
-      lprevself(*searchtri);
-    }
-    /* Insert a shell edge, if there isn't already one there. */
-    insertshelle(searchtri, newmark);
-    return 1;
-  } else if (collinear == LEFTCOLLINEAR) {
-    /* We've collided with a point between the segment's endpoints. */
-    /* Make the collinear point be the triangle's origin. */
-    lprevself(*searchtri);
-    insertshelle(searchtri, newmark);
-    /* Insert the remainder of the segment. */
-    return scoutsegment(searchtri, endpoint2, newmark);
-  } else if (collinear == RIGHTCOLLINEAR) {
-    /* We've collided with a point between the segment's endpoints. */
-    insertshelle(searchtri, newmark);
-    /* Make the collinear point be the triangle's origin. */
-    lnextself(*searchtri);
-    /* Insert the remainder of the segment. */
-    return scoutsegment(searchtri, endpoint2, newmark);
-  } else {
-    lnext(*searchtri, crosstri);
-    tspivot(crosstri, crossedge);
-    /* Check for a crossing segment. */
-    if (crossedge.sh == dummysh) {
-      return 0;
-    } else {
-      org(*searchtri, endpoint1);
-      /* Insert a point at the intersection. */
-      segmentintersection(&crosstri, &crossedge, endpoint2);
-      triedgecopy(crosstri, *searchtri);
-      insertshelle(searchtri, newmark);
-      /* Insert the remainder of the segment. */
-      return scoutsegment(searchtri, endpoint2, newmark);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  conformingedge()   Force a segment into a conforming Delaunay            */
-/*                     triangulation by inserting a point at its midpoint,   */
-/*                     and recursively forcing in the two half-segments if   */
-/*                     necessary.                                            */
-/*                                                                           */
-/*  Generates a sequence of edges connecting `endpoint1' to `endpoint2'.     */
-/*  `newmark' is the boundary marker of the segment, assigned to each new    */
-/*  splitting point and shell edge.                                          */
-/*                                                                           */
-/*  Note that conformingedge() does not always maintain the conforming       */
-/*  Delaunay property.  Once inserted, segments are locked into place;       */
-/*  points inserted later (to force other segments in) may render these      */
-/*  fixed segments non-Delaunay.  The conforming Delaunay property will be   */
-/*  restored by enforcequality() by splitting encroached segments.           */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef REDUCED
-#ifndef CDT_ONLY
-
-void conformingedge(endpoint1, endpoint2, newmark)
-point endpoint1;
-point endpoint2;
-int newmark;
-{
-  struct triedge searchtri1, searchtri2;
-  struct edge brokenshelle;
-  point newpoint;
-  point midpoint1, midpoint2;
-  enum insertsiteresult success;
-  int result1, result2;
-  int i;
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose > 2) {
-    printf("Forcing segment into triangulation by recursive splitting:\n");
-    printf("  (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
-           endpoint2[0], endpoint2[1]);
-  }
-  /* Create a new point to insert in the middle of the segment. */
-  newpoint = (point) poolalloc(&points);
-  /* Interpolate coordinates and attributes. */
-  for (i = 0; i < 2 + nextras; i++) {
-    newpoint[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
-  }
-  setpointmark(newpoint, newmark);
-  /* Find a boundary triangle to search from. */
-  searchtri1.tri = (triangle *) NULL;
-  /* Attempt to insert the new point. */
-  success = insertsite(newpoint, &searchtri1, (struct edge *) NULL, 0, 0);
-  if (success == DUPLICATEPOINT) {
-    if (verbose > 2) {
-      printf("  Segment intersects existing point (%.12g, %.12g).\n",
-             newpoint[0], newpoint[1]);
-    }
-    /* Use the point that's already there. */
-    pointdealloc(newpoint);
-    org(searchtri1, newpoint);
-  } else {
-    if (success == VIOLATINGPOINT) {
-      if (verbose > 2) {
-        printf("  Two segments intersect at (%.12g, %.12g).\n",
-               newpoint[0], newpoint[1]);
-      }
-      /* By fluke, we've landed right on another segment.  Split it. */
-      tspivot(searchtri1, brokenshelle);
-      success = insertsite(newpoint, &searchtri1, &brokenshelle, 0, 0);
-      if (success != SUCCESSFULPOINT) {
-        printf("Internal error in conformingedge():\n");
-        printf("  Failure to split a segment.\n");
-        internalerror();
-      }
-    }
-    /* The point has been inserted successfully. */
-    if (steinerleft > 0) {
-      steinerleft--;
-    }
-  }
-  triedgecopy(searchtri1, searchtri2);
-  result1 = scoutsegment(&searchtri1, endpoint1, newmark);
-  result2 = scoutsegment(&searchtri2, endpoint2, newmark);
-  if (!result1) {
-    /* The origin of searchtri1 may have changed if a collision with an */
-    /*   intervening vertex on the segment occurred.                    */
-    org(searchtri1, midpoint1);
-    conformingedge(midpoint1, endpoint1, newmark);
-  }
-  if (!result2) {
-    /* The origin of searchtri2 may have changed if a collision with an */
-    /*   intervening vertex on the segment occurred.                    */
-    org(searchtri2, midpoint2);
-    conformingedge(midpoint2, endpoint2, newmark);
-  }
-}
-
-#endif /* not CDT_ONLY */
-#endif /* not REDUCED */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  delaunayfixup()   Enforce the Delaunay condition at an edge, fanning out */
-/*                    recursively from an existing point.  Pay special       */
-/*                    attention to stacking inverted triangles.              */
-/*                                                                           */
-/*  This is a support routine for inserting segments into a constrained      */
-/*  Delaunay triangulation.                                                  */
-/*                                                                           */
-/*  The origin of fixuptri is treated as if it has just been inserted, and   */
-/*  the local Delaunay condition needs to be enforced.  It is only enforced  */
-/*  in one sector, however, that being the angular range defined by          */
-/*  fixuptri.                                                                */
-/*                                                                           */
-/*  This routine also needs to make decisions regarding the "stacking" of    */
-/*  triangles.  (Read the description of constrainededge() below before      */
-/*  reading on here, so you understand the algorithm.)  If the position of   */
-/*  the new point (the origin of fixuptri) indicates that the vertex before  */
-/*  it on the polygon is a reflex vertex, then "stack" the triangle by       */
-/*  doing nothing.  (fixuptri is an inverted triangle, which is how stacked  */
-/*  triangles are identified.)                                               */
-/*                                                                           */
-/*  Otherwise, check whether the vertex before that was a reflex vertex.     */
-/*  If so, perform an edge flip, thereby eliminating an inverted triangle    */
-/*  (popping it off the stack).  The edge flip may result in the creation    */
-/*  of a new inverted triangle, depending on whether or not the new vertex   */
-/*  is visible to the vertex three edges behind on the polygon.              */
-/*                                                                           */
-/*  If neither of the two vertices behind the new vertex are reflex          */
-/*  vertices, fixuptri and fartri, the triangle opposite it, are not         */
-/*  inverted; hence, ensure that the edge between them is locally Delaunay.  */
-/*                                                                           */
-/*  `leftside' indicates whether or not fixuptri is to the left of the       */
-/*  segment being inserted.  (Imagine that the segment is pointing up from   */
-/*  endpoint1 to endpoint2.)                                                 */
-/*                                                                           */
-/*****************************************************************************/
-
-void delaunayfixup(fixuptri, leftside)
-struct triedge *fixuptri;
-int leftside;
-{
-  struct triedge neartri;
-  struct triedge fartri;
-  struct edge faredge;
-  point nearpoint, leftpoint, rightpoint, farpoint;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  lnext(*fixuptri, neartri);
-  sym(neartri, fartri);
-  /* Check if the edge opposite the origin of fixuptri can be flipped. */
-  if (fartri.tri == dummytri) {
-    return;
-  }
-  tspivot(neartri, faredge);
-  if (faredge.sh != dummysh) {
-    return;
-  }
-  /* Find all the relevant vertices. */
-  apex(neartri, nearpoint);
-  org(neartri, leftpoint);
-  dest(neartri, rightpoint);
-  apex(fartri, farpoint);
-  /* Check whether the previous polygon vertex is a reflex vertex. */
-  if (leftside) {
-    if (counterclockwise(nearpoint, leftpoint, farpoint) <= 0.0) {
-      /* leftpoint is a reflex vertex too.  Nothing can */
-      /*   be done until a convex section is found.     */
-      return;
-    }
-  } else {
-    if (counterclockwise(farpoint, rightpoint, nearpoint) <= 0.0) {
-      /* rightpoint is a reflex vertex too.  Nothing can */
-      /*   be done until a convex section is found.      */
-      return;
-    }
-  }
-  if (counterclockwise(rightpoint, leftpoint, farpoint) > 0.0) {
-    /* fartri is not an inverted triangle, and farpoint is not a reflex */
-    /*   vertex.  As there are no reflex vertices, fixuptri isn't an    */
-    /*   inverted triangle, either.  Hence, test the edge between the   */
-    /*   triangles to ensure it is locally Delaunay.                    */
-    if (incircle(leftpoint, farpoint, rightpoint, nearpoint) <= 0.0) {
-      return;
-    }
-    /* Not locally Delaunay; go on to an edge flip. */
-  }        /* else fartri is inverted; remove it from the stack by flipping. */
-  flip(&neartri);
-  lprevself(*fixuptri);    /* Restore the origin of fixuptri after the flip. */
-  /* Recursively process the two triangles that result from the flip. */
-  delaunayfixup(fixuptri, leftside);
-  delaunayfixup(&fartri, leftside);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  constrainededge()   Force a segment into a constrained Delaunay          */
-/*                      triangulation by deleting the triangles it           */
-/*                      intersects, and triangulating the polygons that      */
-/*                      form on each side of it.                             */
-/*                                                                           */
-/*  Generates a single edge connecting `endpoint1' to `endpoint2'.  The      */
-/*  triangle `starttri' has `endpoint1' as its origin.  `newmark' is the     */
-/*  boundary marker of the segment.                                          */
-/*                                                                           */
-/*  To insert a segment, every triangle whose interior intersects the        */
-/*  segment is deleted.  The union of these deleted triangles is a polygon   */
-/*  (which is not necessarily monotone, but is close enough), which is       */
-/*  divided into two polygons by the new segment.  This routine's task is    */
-/*  to generate the Delaunay triangulation of these two polygons.            */
-/*                                                                           */
-/*  You might think of this routine's behavior as a two-step process.  The   */
-/*  first step is to walk from endpoint1 to endpoint2, flipping each edge    */
-/*  encountered.  This step creates a fan of edges connected to endpoint1,   */
-/*  including the desired edge to endpoint2.  The second step enforces the   */
-/*  Delaunay condition on each side of the segment in an incremental manner: */
-/*  proceeding along the polygon from endpoint1 to endpoint2 (this is done   */
-/*  independently on each side of the segment), each vertex is "enforced"    */
-/*  as if it had just been inserted, but affecting only the previous         */
-/*  vertices.  The result is the same as if the vertices had been inserted   */
-/*  in the order they appear on the polygon, so the result is Delaunay.      */
-/*                                                                           */
-/*  In truth, constrainededge() interleaves these two steps.  The procedure  */
-/*  walks from endpoint1 to endpoint2, and each time an edge is encountered  */
-/*  and flipped, the newly exposed vertex (at the far end of the flipped     */
-/*  edge) is "enforced" upon the previously flipped edges, usually affecting */
-/*  only one side of the polygon (depending upon which side of the segment   */
-/*  the vertex falls on).                                                    */
-/*                                                                           */
-/*  The algorithm is complicated by the need to handle polygons that are not */
-/*  convex.  Although the polygon is not necessarily monotone, it can be     */
-/*  triangulated in a manner similar to the stack-based algorithms for       */
-/*  monotone polygons.  For each reflex vertex (local concavity) of the      */
-/*  polygon, there will be an inverted triangle formed by one of the edge    */
-/*  flips.  (An inverted triangle is one with negative area - that is, its   */
-/*  vertices are arranged in clockwise order - and is best thought of as a   */
-/*  wrinkle in the fabric of the mesh.)  Each inverted triangle can be       */
-/*  thought of as a reflex vertex pushed on the stack, waiting to be fixed   */
-/*  later.                                                                   */
-/*                                                                           */
-/*  A reflex vertex is popped from the stack when a vertex is inserted that  */
-/*  is visible to the reflex vertex.  (However, if the vertex behind the     */
-/*  reflex vertex is not visible to the reflex vertex, a new inverted        */
-/*  triangle will take its place on the stack.)  These details are handled   */
-/*  by the delaunayfixup() routine above.                                    */
-/*                                                                           */
-/*****************************************************************************/
-
-void constrainededge(starttri, endpoint2, newmark)
-struct triedge *starttri;
-point endpoint2;
-int newmark;
-{
-  struct triedge fixuptri, fixuptri2;
-  struct edge fixupedge;
-  point endpoint1;
-  point farpoint;
-  REAL area;
-  int collision;
-  int done;
-  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  org(*starttri, endpoint1);
-  lnext(*starttri, fixuptri);
-  flip(&fixuptri);
-  /* `collision' indicates whether we have found a point directly */
-  /*   between endpoint1 and endpoint2.                           */
-  collision = 0;
-  done = 0;
-  do {
-    org(fixuptri, farpoint);
-    /* `farpoint' is the extreme point of the polygon we are "digging" */
-    /*   to get from endpoint1 to endpoint2.                           */
-    if ((farpoint[0] == endpoint2[0]) && (farpoint[1] == endpoint2[1])) {
-      oprev(fixuptri, fixuptri2);
-      /* Enforce the Delaunay condition around endpoint2. */
-      delaunayfixup(&fixuptri, 0);
-      delaunayfixup(&fixuptri2, 1);
-      done = 1;
-    } else {
-      /* Check whether farpoint is to the left or right of the segment */
-      /*   being inserted, to decide which edge of fixuptri to dig     */
-      /*   through next.                                               */
-      area = counterclockwise(endpoint1, endpoint2, farpoint);
-      if (area == 0.0) {
-        /* We've collided with a point between endpoint1 and endpoint2. */
-        collision = 1;
-        oprev(fixuptri, fixuptri2);
-        /* Enforce the Delaunay condition around farpoint. */
-        delaunayfixup(&fixuptri, 0);
-        delaunayfixup(&fixuptri2, 1);
-        done = 1;
-      } else {
-        if (area > 0.0) {         /* farpoint is to the left of the segment. */
-          oprev(fixuptri, fixuptri2);
-          /* Enforce the Delaunay condition around farpoint, on the */
-          /*   left side of the segment only.                       */
-          delaunayfixup(&fixuptri2, 1);
-          /* Flip the edge that crosses the segment.  After the edge is */
-          /*   flipped, one of its endpoints is the fan vertex, and the */
-          /*   destination of fixuptri is the fan vertex.               */
-          lprevself(fixuptri);
-        } else {                 /* farpoint is to the right of the segment. */
-          delaunayfixup(&fixuptri, 0);
-          /* Flip the edge that crosses the segment.  After the edge is */
-          /*   flipped, one of its endpoints is the fan vertex, and the */
-          /*   destination of fixuptri is the fan vertex.               */
-          oprevself(fixuptri);
-        }
-        /* Check for two intersecting segments. */
-        tspivot(fixuptri, fixupedge);
-        if (fixupedge.sh == dummysh) {
-          flip(&fixuptri);   /* May create an inverted triangle on the left. */
-        } else {
-          /* We've collided with a segment between endpoint1 and endpoint2. */
-          collision = 1;
-          /* Insert a point at the intersection. */
-          segmentintersection(&fixuptri, &fixupedge, endpoint2);
-          done = 1;
-        }
-      }
-    }
-  } while (!done);
-  /* Insert a shell edge to make the segment permanent. */
-  insertshelle(&fixuptri, newmark);
-  /* If there was a collision with an interceding vertex, install another */
-  /*   segment connecting that vertex with endpoint2.                     */
-  if (collision) {
-    /* Insert the remainder of the segment. */
-    if (!scoutsegment(&fixuptri, endpoint2, newmark)) {
-      constrainededge(&fixuptri, endpoint2, newmark);
-    }
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  insertsegment()   Insert a PSLG segment into a triangulation.            */
-/*                                                                           */
-/*****************************************************************************/
-
-void insertsegment(endpoint1, endpoint2, newmark)
-point endpoint1;
-point endpoint2;
-int newmark;
-{
-  struct triedge searchtri1, searchtri2;
-  triangle encodedtri;
-  point checkpoint;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (verbose > 1) {
-    printf("  Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
-           endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
-  }
-
-  /* Find a triangle whose origin is the segment's first endpoint. */
-  checkpoint = (point) NULL;
-  encodedtri = point2tri(endpoint1);
-  if (encodedtri != (triangle) NULL) {
-    decode(encodedtri, searchtri1);
-    org(searchtri1, checkpoint);
-  }
-  if (checkpoint != endpoint1) {
-    /* Find a boundary triangle to search from. */
-    searchtri1.tri = dummytri;
-    searchtri1.orient = 0;
-    symself(searchtri1);
-    /* Search for the segment's first endpoint by point location. */
-    if (locate(endpoint1, &searchtri1) != ONVERTEX) {
-      printf(
-        "Internal error in insertsegment():  Unable to locate PSLG point\n");
-      printf("  (%.12g, %.12g) in triangulation.\n",
-             endpoint1[0], endpoint1[1]);
-      internalerror();
-    }
-  }
-  /* Remember this triangle to improve subsequent point location. */
-  triedgecopy(searchtri1, recenttri);
-  /* Scout the beginnings of a path from the first endpoint */
-  /*   toward the second.                                   */
-  if (scoutsegment(&searchtri1, endpoint2, newmark)) {
-    /* The segment was easily inserted. */
-    return;
-  }
-  /* The first endpoint may have changed if a collision with an intervening */
-  /*   vertex on the segment occurred.                                      */
-  org(searchtri1, endpoint1);
-
-  /* Find a triangle whose origin is the segment's second endpoint. */
-  checkpoint = (point) NULL;
-  encodedtri = point2tri(endpoint2);
-  if (encodedtri != (triangle) NULL) {
-    decode(encodedtri, searchtri2);
-    org(searchtri2, checkpoint);
-  }
-  if (checkpoint != endpoint2) {
-    /* Find a boundary triangle to search from. */
-    searchtri2.tri = dummytri;
-    searchtri2.orient = 0;
-    symself(searchtri2);
-    /* Search for the segment's second endpoint by point location. */
-    if (locate(endpoint2, &searchtri2) != ONVERTEX) {
-      printf(
-        "Internal error in insertsegment():  Unable to locate PSLG point\n");
-      printf("  (%.12g, %.12g) in triangulation.\n",
-             endpoint2[0], endpoint2[1]);
-      internalerror();
-    }
-  }
-  /* Remember this triangle to improve subsequent point location. */
-  triedgecopy(searchtri2, recenttri);
-  /* Scout the beginnings of a path from the second endpoint */
-  /*   toward the first.                                     */
-  if (scoutsegment(&searchtri2, endpoint1, newmark)) {
-    /* The segment was easily inserted. */
-    return;
-  }
-  /* The second endpoint may have changed if a collision with an intervening */
-  /*   vertex on the segment occurred.                                       */
-  org(searchtri2, endpoint2);
-
-#ifndef REDUCED
-#ifndef CDT_ONLY
-  if (splitseg) {
-    /* Insert vertices to force the segment into the triangulation. */
-    conformingedge(endpoint1, endpoint2, newmark);
-  } else {
-#endif /* not CDT_ONLY */
-#endif /* not REDUCED */
-    /* Insert the segment directly into the triangulation. */
-    constrainededge(&searchtri1, endpoint2, newmark);
-#ifndef REDUCED
-#ifndef CDT_ONLY
-  }
-#endif /* not CDT_ONLY */
-#endif /* not REDUCED */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  markhull()   Cover the convex hull of a triangulation with shell edges.  */
-/*                                                                           */
-/*****************************************************************************/
-
-void markhull()
-{
-  struct triedge hulltri;
-  struct triedge nexttri;
-  struct triedge starttri;
-  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
-
-  /* Find a triangle handle on the hull. */
-  hulltri.tri = dummytri;
-  hulltri.orient = 0;
-  symself(hulltri);
-  /* Remember where we started so we know when to stop. */
-  triedgecopy(hulltri, starttri);
-  /* Go once counterclockwise around the convex hull. */
-  do {
-    /* Create a shell edge if there isn't already one here. */
-    insertshelle(&hulltri, 1);
-    /* To find the next hull edge, go clockwise around the next vertex. */
-    lnextself(hulltri);
-    oprev(hulltri, nexttri);
-    while (nexttri.tri != dummytri) {
-      triedgecopy(nexttri, hulltri);
-      oprev(hulltri, nexttri);
-    }
-  } while (!triedgeequal(hulltri, starttri));
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  formskeleton()   Create the shell edges of a triangulation, including    */
-/*                   PSLG edges and edges on the convex hull.                */
-/*                                                                           */
-/*  The PSLG edges are read from a .poly file.  The return value is the      */
-/*  number of segments in the file.                                          */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-int formskeleton(segmentlist, segmentmarkerlist, numberofsegments)
-int *segmentlist;
-int *segmentmarkerlist;
-int numberofsegments;
-
-#else /* not TRILIBRARY */
-
-int formskeleton(polyfile, polyfilename)
-FILE *polyfile;
-char *polyfilename;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  char polyfilename[6];
-  int index;
-#else /* not TRILIBRARY */
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-#endif /* not TRILIBRARY */
-  point endpoint1, endpoint2;
-  int segments;
-  int segmentmarkers;
-  int end1, end2;
-  int boundmarker;
-  int i;
-
-  if (poly) {
-    if (!quiet) {
-      printf("Inserting segments into Delaunay triangulation.\n");
-    }
-#ifdef TRILIBRARY
-    strcpy(polyfilename, "input");
-    segments = numberofsegments;
-    segmentmarkers = segmentmarkerlist != (int *) NULL;
-    index = 0;
-#else /* not TRILIBRARY */
-    /* Read the segments from a .poly file. */
-    /* Read number of segments and number of boundary markers. */
-    stringptr = readline(inputline, polyfile, polyfilename);
-    segments = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      segmentmarkers = 0;
-    } else {
-      segmentmarkers = (int) strtol (stringptr, &stringptr, 0);
-    }
-#endif /* not TRILIBRARY */
-    /* If segments are to be inserted, compute a mapping */
-    /*   from points to triangles.                       */
-    if (segments > 0) {
-      if (verbose) {
-        printf("  Inserting PSLG segments.\n");
-      }
-      makepointmap();
-    }
-
-    boundmarker = 0;
-    /* Read and insert the segments. */
-    for (i = 1; i <= segments; i++) {
-#ifdef TRILIBRARY
-      end1 = segmentlist[index++];
-      end2 = segmentlist[index++];
-      if (segmentmarkers) {
-        boundmarker = segmentmarkerlist[i - 1];
-      }
-#else /* not TRILIBRARY */
-      stringptr = readline(inputline, polyfile, inpolyfilename);
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Segment %d has no endpoints in %s.\n", i,
-               polyfilename);
-        exit(1);
-      } else {
-        end1 = (int) strtol (stringptr, &stringptr, 0);
-      }
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Segment %d is missing its second endpoint in %s.\n", i,
-               polyfilename);
-        exit(1);
-      } else {
-        end2 = (int) strtol (stringptr, &stringptr, 0);
-      }
-      if (segmentmarkers) {
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          boundmarker = 0;
-        } else {
-          boundmarker = (int) strtol (stringptr, &stringptr, 0);
-        }
-      }
-#endif /* not TRILIBRARY */
-      if ((end1 < firstnumber) || (end1 >= firstnumber + inpoints)) {
-        if (!quiet) {
-          printf("Warning:  Invalid first endpoint of segment %d in %s.\n", i,
-                 polyfilename);
-        }
-      } else if ((end2 < firstnumber) || (end2 >= firstnumber + inpoints)) {
-        if (!quiet) {
-          printf("Warning:  Invalid second endpoint of segment %d in %s.\n", i,
-                 polyfilename);
-        }
-      } else {
-        endpoint1 = getpoint(end1);
-        endpoint2 = getpoint(end2);
-        if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
-          if (!quiet) {
-            printf("Warning:  Endpoints of segment %d are coincident in %s.\n",
-                   i, polyfilename);
-          }
-        } else {
-          insertsegment(endpoint1, endpoint2, boundmarker);
-        }
-      }
-    }
-  } else {
-    segments = 0;
-  }
-  if (convex || !poly) {
-    /* Enclose the convex hull with shell edges. */
-    if (verbose) {
-      printf("  Enclosing convex hull with segments.\n");
-    }
-    markhull();
-  }
-  return segments;
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Segment (shell edge) insertion ends here                  *********/
-
-/********* Carving out holes and concavities begins here             *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  infecthull()   Virally infect all of the triangles of the convex hull    */
-/*                 that are not protected by shell edges.  Where there are   */
-/*                 shell edges, set boundary markers as appropriate.         */
-/*                                                                           */
-/*****************************************************************************/
-
-void infecthull()
-{
-  struct triedge hulltri;
-  struct triedge nexttri;
-  struct triedge starttri;
-  struct edge hulledge;
-  triangle **deadtri;
-  point horg, hdest;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose) {
-    printf("  Marking concavities (external triangles) for elimination.\n");
-  }
-  /* Find a triangle handle on the hull. */
-  hulltri.tri = dummytri;
-  hulltri.orient = 0;
-  symself(hulltri);
-  /* Remember where we started so we know when to stop. */
-  triedgecopy(hulltri, starttri);
-  /* Go once counterclockwise around the convex hull. */
-  do {
-    /* Ignore triangles that are already infected. */
-    if (!infected(hulltri)) {
-      /* Is the triangle protected by a shell edge? */
-      tspivot(hulltri, hulledge);
-      if (hulledge.sh == dummysh) {
-        /* The triangle is not protected; infect it. */
-        infect(hulltri);
-        deadtri = (triangle **) poolalloc(&viri);
-        *deadtri = hulltri.tri;
-      } else {
-        /* The triangle is protected; set boundary markers if appropriate. */
-        if (mark(hulledge) == 0) {
-          setmark(hulledge, 1);
-          org(hulltri, horg);
-          dest(hulltri, hdest);
-          if (pointmark(horg) == 0) {
-            setpointmark(horg, 1);
-          }
-          if (pointmark(hdest) == 0) {
-            setpointmark(hdest, 1);
-          }
-        }
-      }
-    }
-    /* To find the next hull edge, go clockwise around the next vertex. */
-    lnextself(hulltri);
-    oprev(hulltri, nexttri);
-    while (nexttri.tri != dummytri) {
-      triedgecopy(nexttri, hulltri);
-      oprev(hulltri, nexttri);
-    }
-  } while (!triedgeequal(hulltri, starttri));
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  plague()   Spread the virus from all infected triangles to any neighbors */
-/*             not protected by shell edges.  Delete all infected triangles. */
-/*                                                                           */
-/*  This is the procedure that actually creates holes and concavities.       */
-/*                                                                           */
-/*  This procedure operates in two phases.  The first phase identifies all   */
-/*  the triangles that will die, and marks them as infected.  They are       */
-/*  marked to ensure that each triangle is added to the virus pool only      */
-/*  once, so the procedure will terminate.                                   */
-/*                                                                           */
-/*  The second phase actually eliminates the infected triangles.  It also    */
-/*  eliminates orphaned points.                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-void plague()
-{
-  struct triedge testtri;
-  struct triedge neighbor;
-  triangle **virusloop;
-  triangle **deadtri;
-  struct edge neighborshelle;
-  point testpoint;
-  point norg, ndest;
-  point deadorg, deaddest, deadapex;
-  int killorg;
-  triangle ptr;             /* Temporary variable used by sym() and onext(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose) {
-    printf("  Marking neighbors of marked triangles.\n");
-  }
-  /* Loop through all the infected triangles, spreading the virus to */
-  /*   their neighbors, then to their neighbors' neighbors.          */
-  traversalinit(&viri);
-  virusloop = (triangle **) traverse(&viri);
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-    /* A triangle is marked as infected by messing with one of its shell */
-    /*   edges, setting it to an illegal value.  Hence, we have to       */
-    /*   temporarily uninfect this triangle so that we can examine its   */
-    /*   adjacent shell edges.                                           */
-    uninfect(testtri);
-    if (verbose > 2) {
-      /* Assign the triangle an orientation for convenience in */
-      /*   checking its points.                                */
-      testtri.orient = 0;
-      org(testtri, deadorg);
-      dest(testtri, deaddest);
-      apex(testtri, deadapex);
-      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-             deadorg[0], deadorg[1], deaddest[0], deaddest[1],
-             deadapex[0], deadapex[1]);
-    }
-    /* Check each of the triangle's three neighbors. */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      /* Find the neighbor. */
-      sym(testtri, neighbor);
-      /* Check for a shell between the triangle and its neighbor. */
-      tspivot(testtri, neighborshelle);
-      /* Check if the neighbor is nonexistent or already infected. */
-      if ((neighbor.tri == dummytri) || infected(neighbor)) {
-        if (neighborshelle.sh != dummysh) {
-          /* There is a shell edge separating the triangle from its */
-          /*   neighbor, but both triangles are dying, so the shell */
-          /*   edge dies too.                                       */
-          shelledealloc(neighborshelle.sh);
-          if (neighbor.tri != dummytri) {
-            /* Make sure the shell edge doesn't get deallocated again */
-            /*   later when the infected neighbor is visited.         */
-            uninfect(neighbor);
-            tsdissolve(neighbor);
-            infect(neighbor);
-          }
-        }
-      } else {                   /* The neighbor exists and is not infected. */
-        if (neighborshelle.sh == dummysh) {
-          /* There is no shell edge protecting the neighbor, so */
-          /*   the neighbor becomes infected.                   */
-          if (verbose > 2) {
-            org(neighbor, deadorg);
-            dest(neighbor, deaddest);
-            apex(neighbor, deadapex);
-            printf(
-              "    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-                   deadorg[0], deadorg[1], deaddest[0], deaddest[1],
-                   deadapex[0], deadapex[1]);
-          }
-          infect(neighbor);
-          /* Ensure that the neighbor's neighbors will be infected. */
-          deadtri = (triangle **) poolalloc(&viri);
-          *deadtri = neighbor.tri;
-        } else {               /* The neighbor is protected by a shell edge. */
-          /* Remove this triangle from the shell edge. */
-          stdissolve(neighborshelle);
-          /* The shell edge becomes a boundary.  Set markers accordingly. */
-          if (mark(neighborshelle) == 0) {
-            setmark(neighborshelle, 1);
-          }
-          org(neighbor, norg);
-          dest(neighbor, ndest);
-          if (pointmark(norg) == 0) {
-            setpointmark(norg, 1);
-          }
-          if (pointmark(ndest) == 0) {
-            setpointmark(ndest, 1);
-          }
-        }
-      }
-    }
-    /* Remark the triangle as infected, so it doesn't get added to the */
-    /*   virus pool again.                                             */
-    infect(testtri);
-    virusloop = (triangle **) traverse(&viri);
-  }
-
-  if (verbose) {
-    printf("  Deleting marked triangles.\n");
-  }
-  traversalinit(&viri);
-  virusloop = (triangle **) traverse(&viri);
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-
-    /* Check each of the three corners of the triangle for elimination. */
-    /*   This is done by walking around each point, checking if it is   */
-    /*   still connected to at least one live triangle.                 */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      org(testtri, testpoint);
-      /* Check if the point has already been tested. */
-      if (testpoint != (point) NULL) {
-        killorg = 1;
-        /* Mark the corner of the triangle as having been tested. */
-        setorg(testtri, NULL);
-        /* Walk counterclockwise about the point. */
-        onext(testtri, neighbor);
-        /* Stop upon reaching a boundary or the starting triangle. */
-        while ((neighbor.tri != dummytri)
-               && (!triedgeequal(neighbor, testtri))) {
-          if (infected(neighbor)) {
-            /* Mark the corner of this triangle as having been tested. */
-            setorg(neighbor, NULL);
-          } else {
-            /* A live triangle.  The point survives. */
-            killorg = 0;
-          }
-          /* Walk counterclockwise about the point. */
-          onextself(neighbor);
-        }
-        /* If we reached a boundary, we must walk clockwise as well. */
-        if (neighbor.tri == dummytri) {
-          /* Walk clockwise about the point. */
-          oprev(testtri, neighbor);
-          /* Stop upon reaching a boundary. */
-          while (neighbor.tri != dummytri) {
-            if (infected(neighbor)) {
-            /* Mark the corner of this triangle as having been tested. */
-              setorg(neighbor, NULL);
-            } else {
-              /* A live triangle.  The point survives. */
-              killorg = 0;
-            }
-            /* Walk clockwise about the point. */
-            oprevself(neighbor);
-          }
-        }
-        if (killorg) {
-          if (verbose > 1) {
-            printf("    Deleting point (%.12g, %.12g)\n",
-                   testpoint[0], testpoint[1]);
-          }
-          pointdealloc(testpoint);
-        }
-      }
-    }
-
-    /* Record changes in the number of boundary edges, and disconnect */
-    /*   dead triangles from their neighbors.                         */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      sym(testtri, neighbor);
-      if (neighbor.tri == dummytri) {
-        /* There is no neighboring triangle on this edge, so this edge    */
-        /*   is a boundary edge.  This triangle is being deleted, so this */
-        /*   boundary edge is deleted.                                    */
-        hullsize--;
-      } else {
-        /* Disconnect the triangle from its neighbor. */
-        dissolve(neighbor);
-        /* There is a neighboring triangle on this edge, so this edge */
-        /*   becomes a boundary edge when this triangle is deleted.   */
-        hullsize++;
-      }
-    }
-    /* Return the dead triangle to the pool of triangles. */
-    triangledealloc(testtri.tri);
-    virusloop = (triangle **) traverse(&viri);
-  }
-  /* Empty the virus pool. */
-  poolrestart(&viri);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  regionplague()   Spread regional attributes and/or area constraints      */
-/*                   (from a .poly file) throughout the mesh.                */
-/*                                                                           */
-/*  This procedure operates in two phases.  The first phase spreads an       */
-/*  attribute and/or an area constraint through a (segment-bounded) region.  */
-/*  The triangles are marked to ensure that each triangle is added to the    */
-/*  virus pool only once, so the procedure will terminate.                   */
-/*                                                                           */
-/*  The second phase uninfects all infected triangles, returning them to     */
-/*  normal.                                                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-void regionplague(attribute, area)
-REAL attribute;
-REAL area;
-{
-  struct triedge testtri;
-  struct triedge neighbor;
-  triangle **virusloop;
-  triangle **regiontri;
-  struct edge neighborshelle;
-  point regionorg, regiondest, regionapex;
-  triangle ptr;             /* Temporary variable used by sym() and onext(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (verbose > 1) {
-    printf("  Marking neighbors of marked triangles.\n");
-  }
-  /* Loop through all the infected triangles, spreading the attribute      */
-  /*   and/or area constraint to their neighbors, then to their neighbors' */
-  /*   neighbors.                                                          */
-  traversalinit(&viri);
-  virusloop = (triangle **) traverse(&viri);
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-    /* A triangle is marked as infected by messing with one of its shell */
-    /*   edges, setting it to an illegal value.  Hence, we have to       */
-    /*   temporarily uninfect this triangle so that we can examine its   */
-    /*   adjacent shell edges.                                           */
-    uninfect(testtri);
-    if (regionattrib) {
-      /* Set an attribute. */
-      setelemattribute(testtri, eextras, attribute);
-    }
-    if (vararea) {
-      /* Set an area constraint. */
-      setareabound(testtri, area);
-    }
-    if (verbose > 2) {
-      /* Assign the triangle an orientation for convenience in */
-      /*   checking its points.                                */
-      testtri.orient = 0;
-      org(testtri, regionorg);
-      dest(testtri, regiondest);
-      apex(testtri, regionapex);
-      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-             regionorg[0], regionorg[1], regiondest[0], regiondest[1],
-             regionapex[0], regionapex[1]);
-    }
-    /* Check each of the triangle's three neighbors. */
-    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
-      /* Find the neighbor. */
-      sym(testtri, neighbor);
-      /* Check for a shell between the triangle and its neighbor. */
-      tspivot(testtri, neighborshelle);
-      /* Make sure the neighbor exists, is not already infected, and */
-      /*   isn't protected by a shell edge.                          */
-      if ((neighbor.tri != dummytri) && !infected(neighbor)
-          && (neighborshelle.sh == dummysh)) {
-        if (verbose > 2) {
-          org(neighbor, regionorg);
-          dest(neighbor, regiondest);
-          apex(neighbor, regionapex);
-          printf("    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-                 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
-                 regionapex[0], regionapex[1]);
-        }
-        /* Infect the neighbor. */
-        infect(neighbor);
-        /* Ensure that the neighbor's neighbors will be infected. */
-        regiontri = (triangle **) poolalloc(&viri);
-        *regiontri = neighbor.tri;
-      }
-    }
-    /* Remark the triangle as infected, so it doesn't get added to the */
-    /*   virus pool again.                                             */
-    infect(testtri);
-    virusloop = (triangle **) traverse(&viri);
-  }
-
-  /* Uninfect all triangles. */
-  if (verbose > 1) {
-    printf("  Unmarking marked triangles.\n");
-  }
-  traversalinit(&viri);
-  virusloop = (triangle **) traverse(&viri);
-  while (virusloop != (triangle **) NULL) {
-    testtri.tri = *virusloop;
-    uninfect(testtri);
-    virusloop = (triangle **) traverse(&viri);
-  }
-  /* Empty the virus pool. */
-  poolrestart(&viri);
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  carveholes()   Find the holes and infect them.  Find the area            */
-/*                 constraints and infect them.  Infect the convex hull.     */
-/*                 Spread the infection and kill triangles.  Spread the      */
-/*                 area constraints.                                         */
-/*                                                                           */
-/*  This routine mainly calls other routines to carry out all these          */
-/*  functions.                                                               */
-/*                                                                           */
-/*****************************************************************************/
-
-void carveholes(holelist, holes, regionlist, regions)
-REAL *holelist;
-int holes;
-REAL *regionlist;
-int regions;
-{
-  struct triedge searchtri;
-  struct triedge triangleloop;
-  struct triedge *regiontris;
-  triangle **holetri;
-  triangle **regiontri;
-  point searchorg, searchdest;
-  enum locateresult intersect;
-  int i;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-  if (!(quiet || (noholes && convex))) {
-    printf("Removing unwanted triangles.\n");
-    if (verbose && (holes > 0)) {
-      printf("  Marking holes for elimination.\n");
-    }
-  }
-
-  if (regions > 0) {
-    /* Allocate storage for the triangles in which region points fall. */
-    regiontris = (struct triedge *) malloc(regions * sizeof(struct triedge));
-    if (regiontris == (struct triedge *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-
-  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
-    /* Initialize a pool of viri to be used for holes, concavities, */
-    /*   regional attributes, and/or regional area constraints.     */
-    poolinit(&viri, sizeof(triangle *), VIRUSPERBLOCK, POINTER, 0);
-  }
-
-  if (!convex) {
-    /* Mark as infected any unprotected triangles on the boundary. */
-    /*   This is one way by which concavities are created.         */
-    infecthull();
-  }
-
-  if ((holes > 0) && !noholes) {
-    /* Infect each triangle in which a hole lies. */
-    for (i = 0; i < 2 * holes; i += 2) {
-      /* Ignore holes that aren't within the bounds of the mesh. */
-      if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
-          && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)) {
-        /* Start searching from some triangle on the outer boundary. */
-        searchtri.tri = dummytri;
-        searchtri.orient = 0;
-        symself(searchtri);
-        /* Ensure that the hole is to the left of this boundary edge; */
-        /*   otherwise, locate() will falsely report that the hole    */
-        /*   falls within the starting triangle.                      */
-        org(searchtri, searchorg);
-        dest(searchtri, searchdest);
-        if (counterclockwise(searchorg, searchdest, &holelist[i]) > 0.0) {
-          /* Find a triangle that contains the hole. */
-          intersect = locate(&holelist[i], &searchtri);
-          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
-            /* Infect the triangle.  This is done by marking the triangle */
-            /*   as infect and including the triangle in the virus pool.  */
-            infect(searchtri);
-            holetri = (triangle **) poolalloc(&viri);
-            *holetri = searchtri.tri;
-          }
-        }
-      }
-    }
-  }
-
-  /* Now, we have to find all the regions BEFORE we carve the holes, because */
-  /*   locate() won't work when the triangulation is no longer convex.       */
-  /*   (Incidentally, this is the reason why regional attributes and area    */
-  /*   constraints can't be used when refining a preexisting mesh, which     */
-  /*   might not be convex; they can only be used with a freshly             */
-  /*   triangulated PSLG.)                                                   */
-  if (regions > 0) {
-    /* Find the starting triangle for each region. */
-    for (i = 0; i < regions; i++) {
-      regiontris[i].tri = dummytri;
-      /* Ignore region points that aren't within the bounds of the mesh. */
-      if ((regionlist[4 * i] >= xmin) && (regionlist[4 * i] <= xmax) &&
-          (regionlist[4 * i + 1] >= ymin) && (regionlist[4 * i + 1] <= ymax)) {
-        /* Start searching from some triangle on the outer boundary. */
-        searchtri.tri = dummytri;
-        searchtri.orient = 0;
-        symself(searchtri);
-        /* Ensure that the region point is to the left of this boundary */
-        /*   edge; otherwise, locate() will falsely report that the     */
-        /*   region point falls within the starting triangle.           */
-        org(searchtri, searchorg);
-        dest(searchtri, searchdest);
-        if (counterclockwise(searchorg, searchdest, &regionlist[4 * i]) >
-            0.0) {
-          /* Find a triangle that contains the region point. */
-          intersect = locate(&regionlist[4 * i], &searchtri);
-          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
-            /* Record the triangle for processing after the */
-            /*   holes have been carved.                    */
-            triedgecopy(searchtri, regiontris[i]);
-          }
-        }
-      }
-    }
-  }
-
-  if (viri.items > 0) {
-    /* Carve the holes and concavities. */
-    plague();
-  }
-  /* The virus pool should be empty now. */
-
-  if (regions > 0) {
-    if (!quiet) {
-      if (regionattrib) {
-        if (vararea) {
-          printf("Spreading regional attributes and area constraints.\n");
-        } else {
-          printf("Spreading regional attributes.\n");
-        }
-      } else { 
-        printf("Spreading regional area constraints.\n");
-      }
-    }
-    if (regionattrib && !refine) {
-      /* Assign every triangle a regional attribute of zero. */
-      traversalinit(&triangles);
-      triangleloop.orient = 0;
-      triangleloop.tri = triangletraverse();
-      while (triangleloop.tri != (triangle *) NULL) {
-        setelemattribute(triangleloop, eextras, 0.0);
-        triangleloop.tri = triangletraverse();
-      }
-    }
-    for (i = 0; i < regions; i++) {
-      if (regiontris[i].tri != dummytri) {
-        /* Make sure the triangle under consideration still exists. */
-        /*   It may have been eaten by the virus.                   */
-        if (regiontris[i].tri[3] != (triangle) NULL) {
-          /* Put one triangle in the virus pool. */
-          infect(regiontris[i]);
-          regiontri = (triangle **) poolalloc(&viri);
-          *regiontri = regiontris[i].tri;
-          /* Apply one region's attribute and/or area constraint. */
-          regionplague(regionlist[4 * i + 2], regionlist[4 * i + 3]);
-          /* The virus pool should be empty now. */
-        }
-      }
-    }
-    if (regionattrib && !refine) {
-      /* Note the fact that each triangle has an additional attribute. */
-      eextras++;
-    }
-  }
-
-  /* Free up memory. */
-  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
-    pooldeinit(&viri);
-  }
-  if (regions > 0) {
-    free(regiontris);
-  }
-}
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Carving out holes and concavities ends here               *********/
-
-/********* Mesh quality maintenance begins here                      *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  tallyencs()   Traverse the entire list of shell edges, check each edge   */
-/*                to see if it is encroached.  If so, add it to the list.    */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void tallyencs()
-{
-  struct edge edgeloop;
-  int dummy;
-
-  traversalinit(&shelles);
-  edgeloop.shorient = 0;
-  edgeloop.sh = shelletraverse();
-  while (edgeloop.sh != (shelle *) NULL) {
-    /* If the segment is encroached, add it to the list. */
-    dummy = checkedge4encroach(&edgeloop);
-    edgeloop.sh = shelletraverse();
-  }
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  precisionerror()  Print an error message for precision problems.         */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void precisionerror()
-{
-  printf("Try increasing the area criterion and/or reducing the minimum\n");
-  printf("  allowable angle so that tiny triangles are not created.\n");
-#ifdef SINGLE
-  printf("Alternatively, try recompiling me with double precision\n");
-  printf("  arithmetic (by removing \"#define SINGLE\" from the\n");
-  printf("  source file or \"-DSINGLE\" from the makefile).\n");
-#endif /* SINGLE */
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  repairencs()   Find and repair all the encroached segments.              */
-/*                                                                           */
-/*  Encroached segments are repaired by splitting them by inserting a point  */
-/*  at or near their centers.                                                */
-/*                                                                           */
-/*  `flaws' is a flag that specifies whether one should take note of new     */
-/*  encroached segments and bad triangles that result from inserting points  */
-/*  to repair existing encroached segments.                                  */
-/*                                                                           */
-/*  When a segment is split, the two resulting subsegments are always        */
-/*  tested to see if they are encroached upon, regardless of the value       */
-/*  of `flaws'.                                                              */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void repairencs(flaws)
-int flaws;
-{
-  struct triedge enctri;
-  struct triedge testtri;
-  struct edge *encloop;
-  struct edge testsh;
-  point eorg, edest;
-  point newpoint;
-  enum insertsiteresult success;
-  REAL segmentlength, nearestpoweroftwo;
-  REAL split;
-  int acuteorg, acutedest;
-  int dummy;
-  int i;
-  triangle ptr;                     /* Temporary variable used by stpivot(). */
-  shelle sptr;                        /* Temporary variable used by snext(). */
-
-  while ((badsegments.items > 0) && (steinerleft != 0)) {
-    traversalinit(&badsegments);
-    encloop = badsegmenttraverse();
-    while ((encloop != (struct edge *) NULL) && (steinerleft != 0)) {
-      /* To decide where to split a segment, we need to know if the  */
-      /*   segment shares an endpoint with an adjacent segment.      */
-      /*   The concern is that, if we simply split every encroached  */
-      /*   segment in its center, two adjacent segments with a small */
-      /*   angle between them might lead to an infinite loop; each   */
-      /*   point added to split one segment will encroach upon the   */
-      /*   other segment, which must then be split with a point that */
-      /*   will encroach upon the first segment, and so on forever.  */
-      /* To avoid this, imagine a set of concentric circles, whose   */
-      /*   radii are powers of two, about each segment endpoint.     */
-      /*   These concentric circles determine where the segment is   */
-      /*   split.  (If both endpoints are shared with adjacent       */
-      /*   segments, split the segment in the middle, and apply the  */
-      /*   concentric shells for later splittings.)                  */
-
-      /* Is the origin shared with another segment? */
-      stpivot(*encloop, enctri);
-      lnext(enctri, testtri);
-      tspivot(testtri, testsh);
-      acuteorg = testsh.sh != dummysh;
-      /* Is the destination shared with another segment? */
-      lnextself(testtri);
-      tspivot(testtri, testsh);
-      acutedest = testsh.sh != dummysh;
-      /* Now, check the other side of the segment, if there's a triangle */
-      /*   there.                                                        */
-      sym(enctri, testtri);
-      if (testtri.tri != dummytri) {
-        /* Is the destination shared with another segment? */
-        lnextself(testtri);
-        tspivot(testtri, testsh);
-        acutedest = acutedest || (testsh.sh != dummysh);
-        /* Is the origin shared with another segment? */
-        lnextself(testtri);
-        tspivot(testtri, testsh);
-        acuteorg = acuteorg || (testsh.sh != dummysh);
-      }
-
-      sorg(*encloop, eorg);
-      sdest(*encloop, edest);
-      /* Use the concentric circles if exactly one endpoint is shared */
-      /*   with another adjacent segment.                             */
-      if (acuteorg ^ acutedest) {
-        segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0])
-                             + (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
-        /* Find the power of two nearest the segment's length. */
-        nearestpoweroftwo = 1.0;
-        while (segmentlength > SQUAREROOTTWO * nearestpoweroftwo) {
-          nearestpoweroftwo *= 2.0;
-        }
-        while (segmentlength < (0.5 * SQUAREROOTTWO) * nearestpoweroftwo) {
-          nearestpoweroftwo *= 0.5;
-        }
-        /* Where do we split the segment? */
-        split = 0.5 * nearestpoweroftwo / segmentlength;
-        if (acutedest) {
-          split = 1.0 - split;
-        }
-      } else {
-        /* If we're not worried about adjacent segments, split */
-        /*   this segment in the middle.                       */
-        split = 0.5;
-      }
-
-      /* Create the new point. */
-      newpoint = (point) poolalloc(&points);
-      /* Interpolate its coordinate and attributes. */
-      for (i = 0; i < 2 + nextras; i++) {
-        newpoint[i] = (1.0 - split) * eorg[i] + split * edest[i];
-      }
-      setpointmark(newpoint, mark(*encloop));
-      if (verbose > 1) {
-        printf(
-        "  Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
-               eorg[0], eorg[1], edest[0], edest[1], newpoint[0], newpoint[1]);
-      }
-      /* Check whether the new point lies on an endpoint. */
-      if (((newpoint[0] == eorg[0]) && (newpoint[1] == eorg[1]))
-        || ((newpoint[0] == edest[0]) && (newpoint[1] == edest[1]))) {
-        printf("Error:  Ran out of precision at (%.12g, %.12g).\n",
-               newpoint[0], newpoint[1]);
-        printf("I attempted to split a segment to a smaller size than can\n");
-        printf("  be accommodated by the finite precision of floating point\n"
-               );
-        printf("  arithmetic.\n");
-        precisionerror();
-        exit(1);
-      }
-      /* Insert the splitting point.  This should always succeed. */
-      success = insertsite(newpoint, &enctri, encloop, flaws, flaws);
-      if ((success != SUCCESSFULPOINT) && (success != ENCROACHINGPOINT)) {
-        printf("Internal error in repairencs():\n");
-        printf("  Failure to split a segment.\n");
-        internalerror();
-      }
-      if (steinerleft > 0) {
-        steinerleft--;
-      }
-      /* Check the two new subsegments to see if they're encroached. */
-      dummy = checkedge4encroach(encloop);
-      snextself(*encloop);
-      dummy = checkedge4encroach(encloop);
-
-      badsegmentdealloc(encloop);
-      encloop = badsegmenttraverse();
-    }
-  }
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  tallyfaces()   Test every triangle in the mesh for quality measures.     */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void tallyfaces()
-{
-  struct triedge triangleloop;
-
-  if (verbose) {
-    printf("  Making a list of bad triangles.\n");
-  }
-  traversalinit(&triangles);
-  triangleloop.orient = 0;
-  triangleloop.tri = triangletraverse();
-  while (triangleloop.tri != (triangle *) NULL) {
-    /* If the triangle is bad, enqueue it. */
-    testtriangle(&triangleloop);
-    triangleloop.tri = triangletraverse();
-  }
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  findcircumcenter()   Find the circumcenter of a triangle.                */
-/*                                                                           */
-/*  The result is returned both in terms of x-y coordinates and xi-eta       */
-/*  coordinates.  The xi-eta coordinate system is defined in terms of the    */
-/*  triangle:  the origin of the triangle is the origin of the coordinate    */
-/*  system; the destination of the triangle is one unit along the xi axis;   */
-/*  and the apex of the triangle is one unit along the eta axis.             */
-/*                                                                           */
-/*  The return value indicates which edge of the triangle is shortest.       */
-/*                                                                           */
-/*****************************************************************************/
-
-enum circumcenterresult findcircumcenter(torg, tdest, tapex, circumcenter,
-                                         xi, eta)
-point torg;
-point tdest;
-point tapex;
-point circumcenter;
-REAL *xi;
-REAL *eta;
-{
-  REAL xdo, ydo, xao, yao, xad, yad;
-  REAL dodist, aodist, addist;
-  REAL denominator;
-  REAL dx, dy;
-
-  circumcentercount++;
-
-  /* Compute the circumcenter of the triangle. */
-  xdo = tdest[0] - torg[0];
-  ydo = tdest[1] - torg[1];
-  xao = tapex[0] - torg[0];
-  yao = tapex[1] - torg[1];
-  dodist = xdo * xdo + ydo * ydo;
-  aodist = xao * xao + yao * yao;
-  if (noexact) {
-    denominator = (REAL)(0.5 / (xdo * yao - xao * ydo));
-  } else {
-    /* Use the counterclockwise() routine to ensure a positive (and */
-    /*   reasonably accurate) result, avoiding any possibility of   */
-    /*   division by zero.                                          */
-    denominator = (REAL)(0.5 / counterclockwise(tdest, tapex, torg));
-    /* Don't count the above as an orientation test. */
-    counterclockcount--;
-  }
-  circumcenter[0] = torg[0] - (ydo * aodist - yao * dodist) * denominator;  
-  circumcenter[1] = torg[1] + (xdo * aodist - xao * dodist) * denominator;  
-
-  /* To interpolate point attributes for the new point inserted at  */
-  /*   the circumcenter, define a coordinate system with a xi-axis, */
-  /*   directed from the triangle's origin to its destination, and  */
-  /*   an eta-axis, directed from its origin to its apex.           */
-  /*   Calculate the xi and eta coordinates of the circumcenter.    */
-  dx = circumcenter[0] - torg[0];
-  dy = circumcenter[1] - torg[1];
-  *xi = (REAL)((dx * yao - xao * dy) * (2.0 * denominator));
-  *eta = (REAL)((xdo * dy - dx * ydo) * (2.0 * denominator));
-
-  xad = tapex[0] - tdest[0];
-  yad = tapex[1] - tdest[1];
-  addist = xad * xad + yad * yad;
-  if ((addist < dodist) && (addist < aodist)) {
-    return OPPOSITEORG;
-  } else if (dodist < aodist) {
-    return OPPOSITEAPEX;
-  } else {
-    return OPPOSITEDEST;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  splittriangle()   Inserts a point at the circumcenter of a triangle.     */
-/*                    Deletes the newly inserted point if it encroaches upon */
-/*                    a segment.                                             */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void splittriangle(badtri)
-struct badface *badtri;
-{
-  point borg, bdest, bapex;
-  point newpoint;
-  REAL xi, eta;
-  enum insertsiteresult success;
-  enum circumcenterresult shortedge;
-  int errorflag;
-  int i;
-
-  org(badtri->badfacetri, borg);
-  dest(badtri->badfacetri, bdest);
-  apex(badtri->badfacetri, bapex);
-  /* Make sure that this triangle is still the same triangle it was      */
-  /*   when it was tested and determined to be of bad quality.           */
-  /*   Subsequent transformations may have made it a different triangle. */
-  if ((borg == badtri->faceorg) && (bdest == badtri->facedest) &&
-      (bapex == badtri->faceapex)) {
-    if (verbose > 1) {
-      printf("  Splitting this triangle at its circumcenter:\n");
-      printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
-             borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
-    }
-    errorflag = 0;
-    /* Create a new point at the triangle's circumcenter. */
-    newpoint = (point) poolalloc(&points);
-    shortedge = findcircumcenter(borg, bdest, bapex, newpoint, &xi, &eta);
-    /* Check whether the new point lies on a triangle vertex. */
-    if (((newpoint[0] == borg[0]) && (newpoint[1] == borg[1]))
-        || ((newpoint[0] == bdest[0]) && (newpoint[1] == bdest[1]))
-        || ((newpoint[0] == bapex[0]) && (newpoint[1] == bapex[1]))) {
-      if (!quiet) {
-        printf("Warning:  New point (%.12g, %.12g) falls on existing vertex.\n"
-               , newpoint[0], newpoint[1]);
-        errorflag = 1;
-      }
-      pointdealloc(newpoint);
-    } else {
-      for (i = 2; i < 2 + nextras; i++) {
-        /* Interpolate the point attributes at the circumcenter. */
-        newpoint[i] = borg[i] + xi * (bdest[i] - borg[i])
-                             + eta * (bapex[i] - borg[i]);
-      }
-      /* The new point must be in the interior, and have a marker of zero. */
-      setpointmark(newpoint, 0);
-      /* Ensure that the handle `badtri->badfacetri' represents the shortest */
-      /*   edge of the triangle.  This ensures that the circumcenter must    */
-      /*   fall to the left of this edge, so point location will work.       */
-      if (shortedge == OPPOSITEORG) {
-        lnextself(badtri->badfacetri);
-      } else if (shortedge == OPPOSITEDEST) {
-        lprevself(badtri->badfacetri);
-      }
-      /* Insert the circumcenter, searching from the edge of the triangle, */
-      /*   and maintain the Delaunay property of the triangulation.        */
-      success = insertsite(newpoint, &(badtri->badfacetri),
-                           (struct edge *) NULL, 1, 1);
-      if (success == SUCCESSFULPOINT) {
-        if (steinerleft > 0) {
-          steinerleft--;
-        }
-      } else if (success == ENCROACHINGPOINT) {
-        /* If the newly inserted point encroaches upon a segment, delete it. */
-        deletesite(&(badtri->badfacetri));
-      } else if (success == VIOLATINGPOINT) {
-        /* Failed to insert the new point, but some segment was */
-        /*   marked as being encroached.                        */
-        pointdealloc(newpoint);
-      } else {                                  /* success == DUPLICATEPOINT */
-        /* Failed to insert the new point because a vertex is already there. */
-        if (!quiet) {
-          printf(
-            "Warning:  New point (%.12g, %.12g) falls on existing vertex.\n"
-                 , newpoint[0], newpoint[1]);
-          errorflag = 1;
-        }
-        pointdealloc(newpoint);
-      }
-    }
-    if (errorflag) {
-      if (verbose) {
-        printf("  The new point is at the circumcenter of triangle\n");
-        printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
-               borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
-      }
-      printf("This probably means that I am trying to refine triangles\n");
-      printf("  to a smaller size than can be accommodated by the finite\n");
-      printf("  precision of floating point arithmetic.  (You can be\n");
-      printf("  sure of this if I fail to terminate.)\n");
-      precisionerror();
-    }
-  }
-  /* Return the bad triangle to the pool. */
-  pooldealloc(&badtriangles, (VOID *) badtri);
-}
-
-#endif /* not CDT_ONLY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  enforcequality()   Remove all the encroached edges and bad triangles     */
-/*                     from the triangulation.                               */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef CDT_ONLY
-
-void enforcequality()
-{
-  int i;
-
-  if (!quiet) {
-    printf("Adding Steiner points to enforce quality.\n");
-  }
-  /* Initialize the pool of encroached segments. */
-  poolinit(&badsegments, sizeof(struct edge), BADSEGMENTPERBLOCK, POINTER, 0);
-  if (verbose) {
-    printf("  Looking for encroached segments.\n");
-  }
-  /* Test all segments to see if they're encroached. */
-  tallyencs();
-  if (verbose && (badsegments.items > 0)) {
-    printf("  Splitting encroached segments.\n");
-  }
-  /* Note that steinerleft == -1 if an unlimited number */
-  /*   of Steiner points is allowed.                    */
-  while ((badsegments.items > 0) && (steinerleft != 0)) {
-    /* Fix the segments without noting newly encroached segments or   */
-    /*   bad triangles.  The reason we don't want to note newly       */
-    /*   encroached segments is because some encroached segments are  */
-    /*   likely to be noted multiple times, and would then be blindly */
-    /*   split multiple times.  I should fix that some time.          */
-    repairencs(0);
-    /* Now, find all the segments that became encroached while adding */
-    /*   points to split encroached segments.                         */
-    tallyencs();
-  }
-  /* At this point, if we haven't run out of Steiner points, the */
-  /*   triangulation should be (conforming) Delaunay.            */
-
-  /* Next, we worry about enforcing triangle quality. */
-  if ((minangle > 0.0) || vararea || fixedarea) {
-    /* Initialize the pool of bad triangles. */
-    poolinit(&badtriangles, sizeof(struct badface), BADTRIPERBLOCK, POINTER,
-             0);
-    /* Initialize the queues of bad triangles. */
-    for (i = 0; i < 64; i++) {
-      queuefront[i] = (struct badface *) NULL;
-      queuetail[i] = &queuefront[i];
-    }
-    /* Test all triangles to see if they're bad. */
-    tallyfaces();
-    if (verbose) {
-      printf("  Splitting bad triangles.\n");
-    }
-    while ((badtriangles.items > 0) && (steinerleft != 0)) {
-      /* Fix one bad triangle by inserting a point at its circumcenter. */
-      splittriangle(dequeuebadtri());
-      /* Fix any encroached segments that may have resulted.  Record */
-      /*   any new bad triangles or encroached segments that result. */
-      if (badsegments.items > 0) {
-        repairencs(1);
-      }
-    }
-  }
-  /* At this point, if we haven't run out of Steiner points, the */
-  /*   triangulation should be (conforming) Delaunay and have no */
-  /*   low-quality triangles.                                    */
-
-  /* Might we have run out of Steiner points too soon? */
-  if (!quiet && (badsegments.items > 0) && (steinerleft == 0)) {
-    printf("\nWarning:  I ran out of Steiner points, but the mesh has\n");
-    if (badsegments.items == 1) {
-      printf("  an encroached segment, and therefore might not be truly\n");
-    } else {
-      printf("  %ld encroached segments, and therefore might not be truly\n",
-             badsegments.items);
-    }
-    printf("  Delaunay.  If the Delaunay property is important to you,\n");
-    printf("  try increasing the number of Steiner points (controlled by\n");
-    printf("  the -S switch) slightly and try again.\n\n");
-  }
-}
-
-#endif /* not CDT_ONLY */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* Mesh quality maintenance ends here                        *********/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  highorder()   Create extra nodes for quadratic subparametric elements.   */
-/*                                                                           */
-/*****************************************************************************/
-
-void highorder()
-{
-  struct triedge triangleloop, trisym;
-  struct edge checkmark;
-  point newpoint;
-  point torg, tdest;
-  int i;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-  if (!quiet) {
-    printf("Adding vertices for second-order triangles.\n");
-  }
-  /* The following line ensures that dead items in the pool of nodes    */
-  /*   cannot be allocated for the extra nodes associated with high     */
-  /*   order elements.  This ensures that the primary nodes (at the     */
-  /*   corners of elements) will occur earlier in the output files, and */
-  /*   have lower indices, than the extra nodes.                        */
-  points.deaditemstack = (VOID *) NULL;
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  /* To loop over the set of edges, loop over all triangles, and look at   */
-  /*   the three edges of each triangle.  If there isn't another triangle  */
-  /*   adjacent to the edge, operate on the edge.  If there is another     */
-  /*   adjacent triangle, operate on the edge only if the current triangle */
-  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
-  /*   considered only once.                                               */
-  while (triangleloop.tri != (triangle *) NULL) {
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      sym(triangleloop, trisym);
-      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
-        org(triangleloop, torg);
-        dest(triangleloop, tdest);
-        /* Create a new node in the middle of the edge.  Interpolate */
-        /*   its attributes.                                         */
-        newpoint = (point) poolalloc(&points);
-        for (i = 0; i < 2 + nextras; i++) {
-          newpoint[i] = (REAL)(0.5 * (torg[i] + tdest[i]));
-        }
-        /* Set the new node's marker to zero or one, depending on */
-        /*   whether it lies on a boundary.                       */
-        setpointmark(newpoint, trisym.tri == dummytri);
-        if (useshelles) {
-          tspivot(triangleloop, checkmark);
-          /* If this edge is a segment, transfer the marker to the new node. */
-          if (checkmark.sh != dummysh) {
-            setpointmark(newpoint, mark(checkmark));
-          }
-        }
-        if (verbose > 1) {
-          printf("  Creating (%.12g, %.12g).\n", newpoint[0], newpoint[1]);
-        }
-        /* Record the new node in the (one or two) adjacent elements. */
-        triangleloop.tri[highorderindex + triangleloop.orient] =
-                (triangle) newpoint;
-        if (trisym.tri != dummytri) {
-          trisym.tri[highorderindex + trisym.orient] = (triangle) newpoint;
-        }
-      }
-    }
-    triangleloop.tri = triangletraverse();
-  }
-}
-
-/********* File I/O routines begin here                              *********/
-/**                                                                         **/
-/**                                                                         **/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  readline()   Read a nonempty line from a file.                           */
-/*                                                                           */
-/*  A line is considered "nonempty" if it contains something that looks like */
-/*  a number.                                                                */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-char *readline(string, infile, infilename)
-char *string;
-FILE *infile;
-char *infilename;
-{
-  char *result;
-
-  /* Search for something that looks like a number. */
-  do {
-    result = fgets(string, INPUTLINESIZE, infile);
-    if (result == (char *) NULL) {
-      printf("  Error:  Unexpected end of file in %s.\n", infilename);
-      exit(1);
-    }
-    /* Skip anything that doesn't look like a number, a comment, */
-    /*   or the end of a line.                                   */
-    while ((*result != '\0') && (*result != '#')
-           && (*result != '.') && (*result != '+') && (*result != '-')
-           && ((*result < '0') || (*result > '9'))) {
-      result++;
-    }
-  /* If it's a comment or end of line, read another line and try again. */
-  } while ((*result == '#') || (*result == '\0'));
-  return result;
-}
-
-#endif /* not TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  findfield()   Find the next field of a string.                           */
-/*                                                                           */
-/*  Jumps past the current field by searching for whitespace, then jumps     */
-/*  past the whitespace to find the next field.                              */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-char *findfield(string)
-char *string;
-{
-  char *result;
-
-  result = string;
-  /* Skip the current field.  Stop upon reaching whitespace. */
-  while ((*result != '\0') && (*result != '#')
-         && (*result != ' ') && (*result != '\t')) {
-    result++;
-  }
-  /* Now skip the whitespace and anything else that doesn't look like a */
-  /*   number, a comment, or the end of a line.                         */
-  while ((*result != '\0') && (*result != '#')
-         && (*result != '.') && (*result != '+') && (*result != '-')
-         && ((*result < '0') || (*result > '9'))) {
-    result++;
-  }
-  /* Check for a comment (prefixed with `#'). */
-  if (*result == '#') {
-    *result = '\0';
-  }
-  return result;
-}
-
-#endif /* not TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  readnodes()   Read the points from a file, which may be a .node or .poly */
-/*                file.                                                      */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-void readnodes(nodefilename, polyfilename, polyfile)
-char *nodefilename;
-char *polyfilename;
-FILE **polyfile;
-{
-  FILE *infile;
-  point pointloop;
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  char *infilename;
-  REAL x, y;
-  int firstnode;
-  int nodemarkers;
-  int currentmarker;
-  int i, j;
-
-  if (poly) {
-    /* Read the points from a .poly file. */
-    if (!quiet) {
-      printf("Opening %s.\n", polyfilename);
-    }
-    *polyfile = fopen(polyfilename, "r");
-    if (*polyfile == (FILE *) NULL) {
-      printf("  Error:  Cannot access file %s.\n", polyfilename);
-      exit(1);
-    }
-    /* Read number of points, number of dimensions, number of point */
-    /*   attributes, and number of boundary markers.                */
-    stringptr = readline(inputline, *polyfile, polyfilename);
-    inpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      mesh_dim = 2;
-    } else {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nextras = 0;
-    } else {
-      nextras = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nodemarkers = 0;
-    } else {
-      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
-    }
-    if (inpoints > 0) {
-      infile = *polyfile;
-      infilename = polyfilename;
-      readnodefile = 0;
-    } else {
-      /* If the .poly file claims there are zero points, that means that */
-      /*   the points should be read from a separate .node file.         */
-      readnodefile = 1;
-      infilename = innodefilename;
-    }
-  } else {
-    readnodefile = 1;
-    infilename = innodefilename;
-    *polyfile = (FILE *) NULL;
-  }
-
-  if (readnodefile) {
-    /* Read the points from a .node file. */
-    if (!quiet) {
-      printf("Opening %s.\n", innodefilename);
-    }
-    infile = fopen(innodefilename, "r");
-    if (infile == (FILE *) NULL) {
-      printf("  Error:  Cannot access file %s.\n", innodefilename);
-      exit(1);
-    }
-    /* Read number of points, number of dimensions, number of point */
-    /*   attributes, and number of boundary markers.                */
-    stringptr = readline(inputline, infile, innodefilename);
-    inpoints = (int) strtol (stringptr, &stringptr, 0);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      mesh_dim = 2;
-    } else {
-      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nextras = 0;
-    } else {
-      nextras = (int) strtol (stringptr, &stringptr, 0);
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      nodemarkers = 0;
-    } else {
-      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
-    }
-  }
-
-  if (inpoints < 3) {
-    printf("Error:  Input must have at least three input points.\n");
-    exit(1);
-  }
-  if (mesh_dim != 2) {
-    printf("Error:  Triangle only works with two-dimensional meshes.\n");
-    exit(1);
-  }
-
-  initializepointpool();
-
-  /* Read the points. */
-  for (i = 0; i < inpoints; i++) {
-    pointloop = (point) poolalloc(&points);
-    stringptr = readline(inputline, infile, infilename);
-    if (i == 0) {
-      firstnode = (int) strtol (stringptr, &stringptr, 0);
-      if ((firstnode == 0) || (firstnode == 1)) {
-        firstnumber = firstnode;
-      }
-    }
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
-      exit(1);
-    }
-    x = (REAL) strtod(stringptr, &stringptr);
-    stringptr = findfield(stringptr);
-    if (*stringptr == '\0') {
-      printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
-      exit(1);
-    }
-    y = (REAL) strtod(stringptr, &stringptr);
-    pointloop[0] = x;
-    pointloop[1] = y;
-    /* Read the point attributes. */
-    for (j = 2; j < 2 + nextras; j++) {
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        pointloop[j] = 0.0;
-      } else {
-        pointloop[j] = (REAL) strtod(stringptr, &stringptr);
-      }
-    }
-    if (nodemarkers) {
-      /* Read a point marker. */
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        setpointmark(pointloop, 0);
-      } else {
-        currentmarker = (int) strtol (stringptr, &stringptr, 0);
-        setpointmark(pointloop, currentmarker);
-      }
-    } else {
-      /* If no markers are specified in the file, they default to zero. */
-      setpointmark(pointloop, 0);
-    }
-    /* Determine the smallest and largest x and y coordinates. */
-    if (i == 0) {
-      xmin = xmax = x;
-      ymin = ymax = y;
-    } else {
-      xmin = (x < xmin) ? x : xmin;
-      xmax = (x > xmax) ? x : xmax;
-      ymin = (y < ymin) ? y : ymin;
-      ymax = (y > ymax) ? y : ymax;
-    }
-  }
-  if (readnodefile) {
-    fclose(infile);
-  }
-
-  /* Nonexistent x value used as a flag to mark circle events in sweepline */
-  /*   Delaunay algorithm.                                                 */
-  xminextreme = 10 * xmin - 9 * xmax;
-}
-
-#endif /* not TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  transfernodes()   Read the points from memory.                           */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-void transfernodes(pointlist, pointattriblist, pointmarkerlist, numberofpoints,
-                   numberofpointattribs)
-REAL *pointlist;
-REAL *pointattriblist;
-int *pointmarkerlist;
-int numberofpoints;
-int numberofpointattribs;
-{
-  point pointloop;
-  REAL x, y;
-  int i, j;
-  int coordindex;
-  int attribindex;
-
-  inpoints = numberofpoints;
-  mesh_dim = 2;
-  nextras = numberofpointattribs;
-  readnodefile = 0;
-  if (inpoints < 3) {
-    printf("Error:  Input must have at least three input points.\n");
-    exit(1);
-  }
-
-  initializepointpool();
-
-  /* Read the points. */
-  coordindex = 0;
-  attribindex = 0;
-  for (i = 0; i < inpoints; i++) {
-    pointloop = (point) poolalloc(&points);
-    /* Read the point coordinates. */
-    x = pointloop[0] = pointlist[coordindex++];
-    y = pointloop[1] = pointlist[coordindex++];
-    /* Read the point attributes. */
-    for (j = 0; j < numberofpointattribs; j++) {
-      pointloop[2 + j] = pointattriblist[attribindex++];
-    }
-    if (pointmarkerlist != (int *) NULL) {
-      /* Read a point marker. */
-      setpointmark(pointloop, pointmarkerlist[i]);
-    } else {
-      /* If no markers are specified, they default to zero. */
-      setpointmark(pointloop, 0);
-    }
-    x = pointloop[0];
-    y = pointloop[1];
-    /* Determine the smallest and largest x and y coordinates. */
-    if (i == 0) {
-      xmin = xmax = x;
-      ymin = ymax = y;
-    } else {
-      xmin = (x < xmin) ? x : xmin;
-      xmax = (x > xmax) ? x : xmax;
-      ymin = (y < ymin) ? y : ymin;
-      ymax = (y > ymax) ? y : ymax;
-    }
-  }
-
-  /* Nonexistent x value used as a flag to mark circle events in sweepline */
-  /*   Delaunay algorithm.                                                 */
-  xminextreme = 10 * xmin - 9 * xmax;
-}
-
-#endif /* TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  readholes()   Read the holes, and possibly regional attributes and area  */
-/*                constraints, from a .poly file.                            */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-void readholes(polyfile, polyfilename, hlist, holes, rlist, regions)
-FILE *polyfile;
-char *polyfilename;
-REAL **hlist;
-int *holes;
-REAL **rlist;
-int *regions;
-{
-  REAL *holelist;
-  REAL *regionlist;
-  char inputline[INPUTLINESIZE];
-  char *stringptr;
-  int index;
-  int i;
-
-  /* Read the holes. */
-  stringptr = readline(inputline, polyfile, polyfilename);
-  *holes = (int) strtol (stringptr, &stringptr, 0);
-  if (*holes > 0) {
-    holelist = (REAL *) malloc(2 * *holes * sizeof(REAL));
-    *hlist = holelist;
-    if (holelist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-    for (i = 0; i < 2 * *holes; i += 2) {
-      stringptr = readline(inputline, polyfile, polyfilename);
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Hole %d has no x coordinate.\n",
-               firstnumber + (i >> 1));
-        exit(1);
-      } else {
-        holelist[i] = (REAL) strtod(stringptr, &stringptr);
-      }
-      stringptr = findfield(stringptr);
-      if (*stringptr == '\0') {
-        printf("Error:  Hole %d has no y coordinate.\n",
-               firstnumber + (i >> 1));
-        exit(1);
-      } else {
-        holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
-      }
-    }
-  } else {
-    *hlist = (REAL *) NULL;
-  }
-
-#ifndef CDT_ONLY
-  if ((regionattrib || vararea) && !refine) {
-    /* Read the area constraints. */
-    stringptr = readline(inputline, polyfile, polyfilename);
-    *regions = (int) strtol (stringptr, &stringptr, 0);
-    if (*regions > 0) {
-      regionlist = (REAL *) malloc(4 * *regions * sizeof(REAL));
-      *rlist = regionlist;
-      if (regionlist == (REAL *) NULL) {
-        printf("Error:  Out of memory.\n");
-        exit(1);
-      }
-      index = 0;
-      for (i = 0; i < *regions; i++) {
-        stringptr = readline(inputline, polyfile, polyfilename);
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Region %d has no x coordinate.\n",
-                 firstnumber + i);
-          exit(1);
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          printf("Error:  Region %d has no y coordinate.\n",
-                 firstnumber + i);
-          exit(1);
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          printf(
-            "Error:  Region %d has no region attribute or area constraint.\n",
-                 firstnumber + i);
-          exit(1);
-        } else {
-          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
-        }
-        stringptr = findfield(stringptr);
-        if (*stringptr == '\0') {
-          regionlist[index] = regionlist[index - 1];
-        } else {
-          regionlist[index] = (REAL) strtod(stringptr, &stringptr);
-        }
-        index++;
-      }
-    }
-  } else {
-    /* Set `*regions' to zero to avoid an accidental free() later. */
-    *regions = 0;
-    *rlist = (REAL *) NULL;
-  }
-#endif /* not CDT_ONLY */
-
-  fclose(polyfile);
-}
-
-#endif /* not TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  finishfile()   Write the command line to the output file so the user     */
-/*                 can remember how the file was generated.  Close the file. */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-void finishfile(outfile, argc, argv)
-FILE *outfile;
-int argc;
-char **argv;
-{
-  int i;
-
-  fprintf(outfile, "# Generated by");
-  for (i = 0; i < argc; i++) {
-    fprintf(outfile, " ");
-    fputs(argv[i], outfile);
-  }
-  fprintf(outfile, "\n");
-  fclose(outfile);
-}
-
-#endif /* not TRILIBRARY */
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writenodes()   Number the points and write them to a .node file.         */
-/*                                                                           */
-/*  To save memory, the point numbers are written over the shell markers     */
-/*  after the points are written to a file.                                  */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-void writenodes(pointlist, pointattriblist, pointmarkerlist)
-REAL **pointlist;
-REAL **pointattriblist;
-int **pointmarkerlist;
-
-#else /* not TRILIBRARY */
-
-void writenodes(nodefilename, argc, argv)
-char *nodefilename;
-int argc;
-char **argv;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  REAL *plist;
-  REAL *palist;
-  int *pmlist;
-  int coordindex;
-  int attribindex;
-#else /* not TRILIBRARY */
-  FILE *outfile;
-#endif /* not TRILIBRARY */
-  point pointloop;
-  int pointnumber;
-  int i;
-
-#ifdef TRILIBRARY
-  if (!quiet) {
-    printf("Writing points.\n");
-  }
-  /* Allocate memory for output points if necessary. */
-  if (*pointlist == (REAL *) NULL) {
-    *pointlist = (REAL *) malloc(points.items * 2 * sizeof(REAL));
-    if (*pointlist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output point attributes if necessary. */
-  if ((nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
-    *pointattriblist = (REAL *) malloc(points.items * nextras * sizeof(REAL));
-    if (*pointattriblist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output point markers if necessary. */
-  if (!nobound && (*pointmarkerlist == (int *) NULL)) {
-    *pointmarkerlist = (int *) malloc(points.items * sizeof(int));
-    if (*pointmarkerlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  plist = *pointlist;
-  palist = *pointattriblist;
-  pmlist = *pointmarkerlist;
-  coordindex = 0;
-  attribindex = 0;
-#else /* not TRILIBRARY */
-  if (!quiet) {
-    printf("Writing %s.\n", nodefilename);
-  }
-  outfile = fopen(nodefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", nodefilename);
-    exit(1);
-  }
-  /* Number of points, number of dimensions, number of point attributes, */
-  /*   and number of boundary markers (zero or one).                     */
-  fprintf(outfile, "%ld  %d  %d  %d\n", points.items, mesh_dim, nextras,
-          1 - nobound);
-#endif /* not TRILIBRARY */
-
-  traversalinit(&points);
-  pointloop = pointtraverse();
-  pointnumber = firstnumber;
-  while (pointloop != (point) NULL) {
-#ifdef TRILIBRARY
-    /* X and y coordinates. */
-    plist[coordindex++] = pointloop[0];
-    plist[coordindex++] = pointloop[1];
-    /* Point attributes. */
-    for (i = 0; i < nextras; i++) {
-      palist[attribindex++] = pointloop[2 + i];
-    }
-    if (!nobound) {
-      /* Copy the boundary marker. */
-      pmlist[pointnumber - firstnumber] = pointmark(pointloop);
-    }
-#else /* not TRILIBRARY */
-    /* Point number, x and y coordinates. */
-    fprintf(outfile, "%4d    %.17g  %.17g", pointnumber, pointloop[0],
-            pointloop[1]);
-    for (i = 0; i < nextras; i++) {
-      /* Write an attribute. */
-      fprintf(outfile, "  %.17g", pointloop[i + 2]);
-    }
-    if (nobound) {
-      fprintf(outfile, "\n");
-    } else {
-      /* Write the boundary marker. */
-      fprintf(outfile, "    %d\n", pointmark(pointloop));
-    }
-#endif /* not TRILIBRARY */
-
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-
-#ifndef TRILIBRARY
-  finishfile(outfile, argc, argv);
-#endif /* not TRILIBRARY */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  numbernodes()   Number the points.                                       */
-/*                                                                           */
-/*  Each point is assigned a marker equal to its number.                     */
-/*                                                                           */
-/*  Used when writenodes() is not called because no .node file is written.   */
-/*                                                                           */
-/*****************************************************************************/
-
-void numbernodes()
-{
-  point pointloop;
-  int pointnumber;
-
-  traversalinit(&points);
-  pointloop = pointtraverse();
-  pointnumber = firstnumber;
-  while (pointloop != (point) NULL) {
-    setpointmark(pointloop, pointnumber);
-    pointloop = pointtraverse();
-    pointnumber++;
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writeelements()   Write the triangles to an .ele file.                   */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-void writeelements(trianglelist, triangleattriblist)
-int **trianglelist;
-REAL **triangleattriblist;
-
-#else /* not TRILIBRARY */
-
-void writeelements(elefilename, argc, argv)
-char *elefilename;
-int argc;
-char **argv;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  int *tlist;
-  REAL *talist;
-  int pointindex;
-  int attribindex;
-#else /* not TRILIBRARY */
-  FILE *outfile;
-#endif /* not TRILIBRARY */
-  struct triedge triangleloop;
-  point p1, p2, p3;
-  point mid1, mid2, mid3;
-  int elementnumber;
-  int i;
-
-#ifdef TRILIBRARY
-  if (!quiet) {
-    printf("Writing triangles.\n");
-  }
-  /* Allocate memory for output triangles if necessary. */
-  if (*trianglelist == (int *) NULL) {
-    *trianglelist = (int *) malloc(triangles.items *
-                               ((order + 1) * (order + 2) / 2) * sizeof(int));
-    if (*trianglelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output triangle attributes if necessary. */
-  if ((eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
-    *triangleattriblist = (REAL *) malloc(triangles.items * eextras *
-                                          sizeof(REAL));
-    if (*triangleattriblist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  tlist = *trianglelist;
-  talist = *triangleattriblist;
-  pointindex = 0;
-  attribindex = 0;
-#else /* not TRILIBRARY */
-  if (!quiet) {
-    printf("Writing %s.\n", elefilename);
-  }
-  outfile = fopen(elefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", elefilename);
-    exit(1);
-  }
-  /* Number of triangles, points per triangle, attributes per triangle. */
-  fprintf(outfile, "%ld  %d  %d\n", triangles.items,
-          (order + 1) * (order + 2) / 2, eextras);
-#endif /* not TRILIBRARY */
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  elementnumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-    org(triangleloop, p1);
-    dest(triangleloop, p2);
-    apex(triangleloop, p3);
-    if (order == 1) {
-#ifdef TRILIBRARY
-      tlist[pointindex++] = pointmark(p1);
-      tlist[pointindex++] = pointmark(p2);
-      tlist[pointindex++] = pointmark(p3);
-#else /* not TRILIBRARY */
-      /* Triangle number, indices for three points. */
-      fprintf(outfile, "%4d    %4d  %4d  %4d", elementnumber,
-              pointmark(p1), pointmark(p2), pointmark(p3));
-#endif /* not TRILIBRARY */
-    } else {
-      mid1 = (point) triangleloop.tri[highorderindex + 1];
-      mid2 = (point) triangleloop.tri[highorderindex + 2];
-      mid3 = (point) triangleloop.tri[highorderindex];
-#ifdef TRILIBRARY
-      tlist[pointindex++] = pointmark(p1);
-      tlist[pointindex++] = pointmark(p2);
-      tlist[pointindex++] = pointmark(p3);
-      tlist[pointindex++] = pointmark(mid1);
-      tlist[pointindex++] = pointmark(mid2);
-      tlist[pointindex++] = pointmark(mid3);
-#else /* not TRILIBRARY */
-      /* Triangle number, indices for six points. */
-      fprintf(outfile, "%4d    %4d  %4d  %4d  %4d  %4d  %4d", elementnumber,
-              pointmark(p1), pointmark(p2), pointmark(p3), pointmark(mid1),
-              pointmark(mid2), pointmark(mid3));
-#endif /* not TRILIBRARY */
-    }
-
-#ifdef TRILIBRARY
-    for (i = 0; i < eextras; i++) {
-      talist[attribindex++] = elemattribute(triangleloop, i);
-    }
-#else /* not TRILIBRARY */
-    for (i = 0; i < eextras; i++) {
-      fprintf(outfile, "  %.17g", elemattribute(triangleloop, i));
-    }
-    fprintf(outfile, "\n");
-#endif /* not TRILIBRARY */
-
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-
-#ifndef TRILIBRARY
-  finishfile(outfile, argc, argv);
-#endif /* not TRILIBRARY */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writepoly()   Write the segments and holes to a .poly file.              */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-void writepoly(segmentlist, segmentmarkerlist)
-int **segmentlist;
-int **segmentmarkerlist;
-
-#else /* not TRILIBRARY */
-
-void writepoly(polyfilename, holelist, holes, regionlist, regions, argc, argv)
-char *polyfilename;
-REAL *holelist;
-int holes;
-REAL *regionlist;
-int regions;
-int argc;
-char **argv;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  int *slist;
-  int *smlist;
-  int index;
-#else /* not TRILIBRARY */
-  FILE *outfile;
-  int i;
-#endif /* not TRILIBRARY */
-  struct edge shelleloop;
-  point endpoint1, endpoint2;
-  int shellenumber;
-
-#ifdef TRILIBRARY
-  if (!quiet) {
-    printf("Writing segments.\n");
-  }
-  /* Allocate memory for output segments if necessary. */
-  if (*segmentlist == (int *) NULL) {
-    *segmentlist = (int *) malloc(shelles.items * 2 * sizeof(int));
-    if (*segmentlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for output segment markers if necessary. */
-  if (!nobound && (*segmentmarkerlist == (int *) NULL)) {
-    *segmentmarkerlist = (int *) malloc(shelles.items * sizeof(int));
-    if (*segmentmarkerlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  slist = *segmentlist;
-  smlist = *segmentmarkerlist;
-  index = 0;
-#else /* not TRILIBRARY */
-  if (!quiet) {
-    printf("Writing %s.\n", polyfilename);
-  }
-  outfile = fopen(polyfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", polyfilename);
-    exit(1);
-  }
-  /* The zero indicates that the points are in a separate .node file. */
-  /*   Followed by number of dimensions, number of point attributes,  */
-  /*   and number of boundary markers (zero or one).                  */
-  fprintf(outfile, "%d  %d  %d  %d\n", 0, mesh_dim, nextras, 1 - nobound);
-  /* Number of segments, number of boundary markers (zero or one). */
-  fprintf(outfile, "%ld  %d\n", shelles.items, 1 - nobound);
-#endif /* not TRILIBRARY */
-
-  traversalinit(&shelles);
-  shelleloop.sh = shelletraverse();
-  shelleloop.shorient = 0;
-  shellenumber = firstnumber;
-  while (shelleloop.sh != (shelle *) NULL) {
-    sorg(shelleloop, endpoint1);
-    sdest(shelleloop, endpoint2);
-#ifdef TRILIBRARY
-    /* Copy indices of the segment's two endpoints. */
-    slist[index++] = pointmark(endpoint1);
-    slist[index++] = pointmark(endpoint2);
-    if (!nobound) {
-      /* Copy the boundary marker. */
-      smlist[shellenumber - firstnumber] = mark(shelleloop);
-    }
-#else /* not TRILIBRARY */
-    /* Segment number, indices of its two endpoints, and possibly a marker. */
-    if (nobound) {
-      fprintf(outfile, "%4d    %4d  %4d\n", shellenumber,
-              pointmark(endpoint1), pointmark(endpoint2));
-    } else {
-      fprintf(outfile, "%4d    %4d  %4d    %4d\n", shellenumber,
-              pointmark(endpoint1), pointmark(endpoint2), mark(shelleloop));
-    }
-#endif /* not TRILIBRARY */
-
-    shelleloop.sh = shelletraverse();
-    shellenumber++;
-  }
-
-#ifndef TRILIBRARY
-#ifndef CDT_ONLY
-  fprintf(outfile, "%d\n", holes);
-  if (holes > 0) {
-    for (i = 0; i < holes; i++) {
-      /* Hole number, x and y coordinates. */
-      fprintf(outfile, "%4d   %.17g  %.17g\n", firstnumber + i,
-              holelist[2 * i], holelist[2 * i + 1]);
-    }
-  }
-  if (regions > 0) {
-    fprintf(outfile, "%d\n", regions);
-    for (i = 0; i < regions; i++) {
-      /* Region number, x and y coordinates, attribute, maximum area. */
-      fprintf(outfile, "%4d   %.17g  %.17g  %.17g  %.17g\n", firstnumber + i,
-              regionlist[4 * i], regionlist[4 * i + 1],
-              regionlist[4 * i + 2], regionlist[4 * i + 3]);
-    }
-  }
-#endif /* not CDT_ONLY */
-
-  finishfile(outfile, argc, argv);
-#endif /* not TRILIBRARY */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writeedges()   Write the edges to a .edge file.                          */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-void writeedges(edgelist, edgemarkerlist)
-int **edgelist;
-int **edgemarkerlist;
-
-#else /* not TRILIBRARY */
-
-void writeedges(edgefilename, argc, argv)
-char *edgefilename;
-int argc;
-char **argv;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  int *elist;
-  int *emlist;
-  int index;
-#else /* not TRILIBRARY */
-  FILE *outfile;
-#endif /* not TRILIBRARY */
-  struct triedge triangleloop, trisym;
-  struct edge checkmark;
-  point p1, p2;
-  int edgenumber;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-  shelle sptr;                      /* Temporary variable used by tspivot(). */
-
-#ifdef TRILIBRARY
-  if (!quiet) {
-    printf("Writing edges.\n");
-  }
-  /* Allocate memory for edges if necessary. */
-  if (*edgelist == (int *) NULL) {
-    *edgelist = (int *) malloc(edges * 2 * sizeof(int));
-    if (*edgelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for edge markers if necessary. */
-  if (!nobound && (*edgemarkerlist == (int *) NULL)) {
-    *edgemarkerlist = (int *) malloc(edges * sizeof(int));
-    if (*edgemarkerlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  elist = *edgelist;
-  emlist = *edgemarkerlist;
-  index = 0;
-#else /* not TRILIBRARY */
-  if (!quiet) {
-    printf("Writing %s.\n", edgefilename);
-  }
-  outfile = fopen(edgefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", edgefilename);
-    exit(1);
-  }
-  /* Number of edges, number of boundary markers (zero or one). */
-  fprintf(outfile, "%ld  %d\n", edges, 1 - nobound);
-#endif /* not TRILIBRARY */
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  edgenumber = firstnumber;
-  /* To loop over the set of edges, loop over all triangles, and look at   */
-  /*   the three edges of each triangle.  If there isn't another triangle  */
-  /*   adjacent to the edge, operate on the edge.  If there is another     */
-  /*   adjacent triangle, operate on the edge only if the current triangle */
-  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
-  /*   considered only once.                                               */
-  while (triangleloop.tri != (triangle *) NULL) {
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      sym(triangleloop, trisym);
-      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
-        org(triangleloop, p1);
-        dest(triangleloop, p2);
-#ifdef TRILIBRARY
-        elist[index++] = pointmark(p1);
-        elist[index++] = pointmark(p2);
-#endif /* TRILIBRARY */
-        if (nobound) {
-#ifndef TRILIBRARY
-          /* Edge number, indices of two endpoints. */
-          fprintf(outfile, "%4d   %d  %d\n", edgenumber,
-                  pointmark(p1), pointmark(p2));
-#endif /* not TRILIBRARY */
-        } else {
-          /* Edge number, indices of two endpoints, and a boundary marker. */
-          /*   If there's no shell edge, the boundary marker is zero.      */
-          if (useshelles) {
-            tspivot(triangleloop, checkmark);
-            if (checkmark.sh == dummysh) {
-#ifdef TRILIBRARY
-              emlist[edgenumber - firstnumber] = 0;
-#else /* not TRILIBRARY */
-              fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
-                      pointmark(p1), pointmark(p2), 0);
-#endif /* not TRILIBRARY */
-            } else {
-#ifdef TRILIBRARY
-              emlist[edgenumber - firstnumber] = mark(checkmark);
-#else /* not TRILIBRARY */
-              fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
-                      pointmark(p1), pointmark(p2), mark(checkmark));
-#endif /* not TRILIBRARY */
-            }
-          } else {
-#ifdef TRILIBRARY
-            emlist[edgenumber - firstnumber] = trisym.tri == dummytri;
-#else /* not TRILIBRARY */
-            fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
-                    pointmark(p1), pointmark(p2), trisym.tri == dummytri);
-#endif /* not TRILIBRARY */
-          }
-        }
-        edgenumber++;
-      }
-    }
-    triangleloop.tri = triangletraverse();
-  }
-
-#ifndef TRILIBRARY
-  finishfile(outfile, argc, argv);
-#endif /* not TRILIBRARY */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writevoronoi()   Write the Voronoi diagram to a .v.node and .v.edge      */
-/*                   file.                                                   */
-/*                                                                           */
-/*  The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
-/*  Hence, the Voronoi vertices are listed by traversing the Delaunay        */
-/*  triangles, and the Voronoi edges are listed by traversing the Delaunay   */
-/*  edges.                                                                   */
-/*                                                                           */
-/*  WARNING:  In order to assign numbers to the Voronoi vertices, this       */
-/*  procedure messes up the shell edges or the extra nodes of every          */
-/*  element.  Hence, you should call this procedure last.                    */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-void writevoronoi(vpointlist, vpointattriblist, vpointmarkerlist, vedgelist,
-                  vedgemarkerlist, vnormlist)
-REAL **vpointlist;
-REAL **vpointattriblist;
-int **vpointmarkerlist;
-int **vedgelist;
-int **vedgemarkerlist;
-REAL **vnormlist;
-
-#else /* not TRILIBRARY */
-
-void writevoronoi(vnodefilename, vedgefilename, argc, argv)
-char *vnodefilename;
-char *vedgefilename;
-int argc;
-char **argv;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  REAL *plist;
-  REAL *palist;
-  int *elist;
-  REAL *normlist;
-  int coordindex;
-  int attribindex;
-#else /* not TRILIBRARY */
-  FILE *outfile;
-#endif /* not TRILIBRARY */
-  struct triedge triangleloop, trisym;
-  point torg, tdest, tapex;
-  REAL circumcenter[2];
-  REAL xi, eta;
-  int vnodenumber, vedgenumber;
-  int p1, p2;
-  int i;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-#ifdef TRILIBRARY
-  if (!quiet) {
-    printf("Writing Voronoi vertices.\n");
-  }
-  /* Allocate memory for Voronoi vertices if necessary. */
-  if (*vpointlist == (REAL *) NULL) {
-    *vpointlist = (REAL *) malloc(triangles.items * 2 * sizeof(REAL));
-    if (*vpointlist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  /* Allocate memory for Voronoi vertex attributes if necessary. */
-  if (*vpointattriblist == (REAL *) NULL) {
-    *vpointattriblist = (REAL *) malloc(triangles.items * nextras *
-                                        sizeof(REAL));
-    if (*vpointattriblist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  *vpointmarkerlist = (int *) NULL;
-  plist = *vpointlist;
-  palist = *vpointattriblist;
-  coordindex = 0;
-  attribindex = 0;
-#else /* not TRILIBRARY */
-  if (!quiet) {
-    printf("Writing %s.\n", vnodefilename);
-  }
-  outfile = fopen(vnodefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", vnodefilename);
-    exit(1);
-  }
-  /* Number of triangles, two dimensions, number of point attributes, */
-  /*   zero markers.                                                  */
-  fprintf(outfile, "%ld  %d  %d  %d\n", triangles.items, 2, nextras, 0);
-#endif /* not TRILIBRARY */
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  vnodenumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-    org(triangleloop, torg);
-    dest(triangleloop, tdest);
-    apex(triangleloop, tapex);
-    findcircumcenter(torg, tdest, tapex, circumcenter, &xi, &eta);
-#ifdef TRILIBRARY
-    /* X and y coordinates. */
-    plist[coordindex++] = circumcenter[0];
-    plist[coordindex++] = circumcenter[1];
-    for (i = 2; i < 2 + nextras; i++) {
-      /* Interpolate the point attributes at the circumcenter. */
-      palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
-                                     + eta * (tapex[i] - torg[i]);
-    }
-#else /* not TRILIBRARY */
-    /* Voronoi vertex number, x and y coordinates. */
-    fprintf(outfile, "%4d    %.17g  %.17g", vnodenumber, circumcenter[0],
-            circumcenter[1]);
-    for (i = 2; i < 2 + nextras; i++) {
-      /* Interpolate the point attributes at the circumcenter. */
-      fprintf(outfile, "  %.17g", torg[i] + xi * (tdest[i] - torg[i])
-                                         + eta * (tapex[i] - torg[i]));
-    }
-    fprintf(outfile, "\n");
-#endif /* not TRILIBRARY */
-
-    * (int *) (triangleloop.tri + 6) = vnodenumber;
-    triangleloop.tri = triangletraverse();
-    vnodenumber++;
-  }
-
-#ifndef TRILIBRARY
-  finishfile(outfile, argc, argv);
-#endif /* not TRILIBRARY */
-
-#ifdef TRILIBRARY
-  if (!quiet) {
-    printf("Writing Voronoi edges.\n");
-  }
-  /* Allocate memory for output Voronoi edges if necessary. */
-  if (*vedgelist == (int *) NULL) {
-    *vedgelist = (int *) malloc(edges * 2 * sizeof(int));
-    if (*vedgelist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  *vedgemarkerlist = (int *) NULL;
-  /* Allocate memory for output Voronoi norms if necessary. */
-  if (*vnormlist == (REAL *) NULL) {
-    *vnormlist = (REAL *) malloc(edges * 2 * sizeof(REAL));
-    if (*vnormlist == (REAL *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  elist = *vedgelist;
-  normlist = *vnormlist;
-  coordindex = 0;
-#else /* not TRILIBRARY */
-  if (!quiet) {
-    printf("Writing %s.\n", vedgefilename);
-  }
-  outfile = fopen(vedgefilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", vedgefilename);
-    exit(1);
-  }
-  /* Number of edges, zero boundary markers. */
-  fprintf(outfile, "%ld  %d\n", edges, 0);
-#endif /* not TRILIBRARY */
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  vedgenumber = firstnumber;
-  /* To loop over the set of edges, loop over all triangles, and look at   */
-  /*   the three edges of each triangle.  If there isn't another triangle  */
-  /*   adjacent to the edge, operate on the edge.  If there is another     */
-  /*   adjacent triangle, operate on the edge only if the current triangle */
-  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
-  /*   considered only once.                                               */
-  while (triangleloop.tri != (triangle *) NULL) {
-    for (triangleloop.orient = 0; triangleloop.orient < 3;
-         triangleloop.orient++) {
-      sym(triangleloop, trisym);
-      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
-        /* Find the number of this triangle (and Voronoi vertex). */
-        p1 = * (int *) (triangleloop.tri + 6);
-        if (trisym.tri == dummytri) {
-          org(triangleloop, torg);
-          dest(triangleloop, tdest);
-#ifdef TRILIBRARY
-          /* Copy an infinite ray.  Index of one endpoint, and -1. */
-          elist[coordindex] = p1;
-          normlist[coordindex++] = tdest[1] - torg[1];
-          elist[coordindex] = -1;
-          normlist[coordindex++] = torg[0] - tdest[0];
-#else /* not TRILIBRARY */
-          /* Write an infinite ray.  Edge number, index of one endpoint, -1, */
-          /*   and x and y coordinates of a vector representing the          */
-          /*   direction of the ray.                                         */
-          fprintf(outfile, "%4d   %d  %d   %.17g  %.17g\n", vedgenumber,
-                  p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
-#endif /* not TRILIBRARY */
-        } else {
-          /* Find the number of the adjacent triangle (and Voronoi vertex). */
-          p2 = * (int *) (trisym.tri + 6);
-          /* Finite edge.  Write indices of two endpoints. */
-#ifdef TRILIBRARY
-          elist[coordindex] = p1;
-          normlist[coordindex++] = 0.0;
-          elist[coordindex] = p2;
-          normlist[coordindex++] = 0.0;
-#else /* not TRILIBRARY */
-          fprintf(outfile, "%4d   %d  %d\n", vedgenumber, p1, p2);
-#endif /* not TRILIBRARY */
-        }
-        vedgenumber++;
-      }
-    }
-    triangleloop.tri = triangletraverse();
-  }
-
-#ifndef TRILIBRARY
-  finishfile(outfile, argc, argv);
-#endif /* not TRILIBRARY */
-}
-
-#ifdef TRILIBRARY
-
-void writeneighbors(neighborlist)
-int **neighborlist;
-
-#else /* not TRILIBRARY */
-
-void writeneighbors(neighborfilename, argc, argv)
-char *neighborfilename;
-int argc;
-char **argv;
-
-#endif /* not TRILIBRARY */
-
-{
-#ifdef TRILIBRARY
-  int *nlist;
-  int index;
-#else /* not TRILIBRARY */
-  FILE *outfile;
-#endif /* not TRILIBRARY */
-  struct triedge triangleloop, trisym;
-  int elementnumber;
-  int neighbor1, neighbor2, neighbor3;
-  triangle ptr;                         /* Temporary variable used by sym(). */
-
-#ifdef TRILIBRARY
-  if (!quiet) {
-    printf("Writing neighbors.\n");
-  }
-  /* Allocate memory for neighbors if necessary. */
-  if (*neighborlist == (int *) NULL) {
-    *neighborlist = (int *) malloc(triangles.items * 3 * sizeof(int));
-    if (*neighborlist == (int *) NULL) {
-      printf("Error:  Out of memory.\n");
-      exit(1);
-    }
-  }
-  nlist = *neighborlist;
-  index = 0;
-#else /* not TRILIBRARY */
-  if (!quiet) {
-    printf("Writing %s.\n", neighborfilename);
-  }
-  outfile = fopen(neighborfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", neighborfilename);
-    exit(1);
-  }
-  /* Number of triangles, three edges per triangle. */
-  fprintf(outfile, "%ld  %d\n", triangles.items, 3);
-#endif /* not TRILIBRARY */
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  elementnumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-    * (int *) (triangleloop.tri + 6) = elementnumber;
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-  * (int *) (dummytri + 6) = -1;
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  elementnumber = firstnumber;
-  while (triangleloop.tri != (triangle *) NULL) {
-    triangleloop.orient = 1;
-    sym(triangleloop, trisym);
-    neighbor1 = * (int *) (trisym.tri + 6);
-    triangleloop.orient = 2;
-    sym(triangleloop, trisym);
-    neighbor2 = * (int *) (trisym.tri + 6);
-    triangleloop.orient = 0;
-    sym(triangleloop, trisym);
-    neighbor3 = * (int *) (trisym.tri + 6);
-#ifdef TRILIBRARY
-    nlist[index++] = neighbor1;
-    nlist[index++] = neighbor2;
-    nlist[index++] = neighbor3;
-#else /* not TRILIBRARY */
-    /* Triangle number, neighboring triangle numbers. */
-    fprintf(outfile, "%4d    %d  %d  %d\n", elementnumber,
-            neighbor1, neighbor2, neighbor3);
-#endif /* not TRILIBRARY */
-
-    triangleloop.tri = triangletraverse();
-    elementnumber++;
-  }
-
-#ifndef TRILIBRARY
-  finishfile(outfile, argc, argv);
-#endif /* TRILIBRARY */
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  writeoff()   Write the triangulation to an .off file.                    */
-/*                                                                           */
-/*  OFF stands for the Object File Format, a format used by the Geometry     */
-/*  Center's Geomview package.                                               */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifndef TRILIBRARY
-
-void writeoff(offfilename, argc, argv)
-char *offfilename;
-int argc;
-char **argv;
-{
-  FILE *outfile;
-  struct triedge triangleloop;
-  point pointloop;
-  point p1, p2, p3;
-
-  if (!quiet) {
-    printf("Writing %s.\n", offfilename);
-  }
-  outfile = fopen(offfilename, "w");
-  if (outfile == (FILE *) NULL) {
-    printf("  Error:  Cannot create file %s.\n", offfilename);
-    exit(1);
-  }
-  /* Number of points, triangles, and edges. */
-  fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points.items, triangles.items,
-          edges);
-
-  /* Write the points. */
-  traversalinit(&points);
-  pointloop = pointtraverse();
-  while (pointloop != (point) NULL) {
-    /* The "0.0" is here because the OFF format uses 3D coordinates. */
-    fprintf(outfile, " %.17g  %.17g  %.17g\n", pointloop[0],
-            pointloop[1], 0.0);
-    pointloop = pointtraverse();
-  }
-
-  /* Write the triangles. */
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  while (triangleloop.tri != (triangle *) NULL) {
-    org(triangleloop, p1);
-    dest(triangleloop, p2);
-    apex(triangleloop, p3);
-    /* The "3" means a three-vertex polygon. */
-    fprintf(outfile, " 3   %4d  %4d  %4d\n", pointmark(p1) - 1,
-            pointmark(p2) - 1, pointmark(p3) - 1);
-    triangleloop.tri = triangletraverse();
-  }
-  finishfile(outfile, argc, argv);
-}
-
-#endif /* not TRILIBRARY */
-
-/**                                                                         **/
-/**                                                                         **/
-/********* File I/O routines end here                                *********/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  quality_statistics()   Print statistics about the quality of the mesh.   */
-/*                                                                           */
-/*****************************************************************************/
-
-void quality_statistics()
-{
-  struct triedge triangleloop;
-  point p[3];
-  REAL cossquaretable[8];
-  REAL ratiotable[16];
-  REAL dx[3], dy[3];
-  REAL edgelength[3];
-  REAL dotproduct;
-  REAL cossquare;
-  REAL triarea;
-  REAL shortest, longest;
-  REAL trilongest2;
-  REAL smallestarea, biggestarea;
-  REAL triminaltitude2;
-  REAL minaltitude;
-  REAL triaspect2;
-  REAL worstaspect;
-  REAL smallestangle, biggestangle;
-  REAL radconst, degconst;
-  int angletable[18];
-  int aspecttable[16];
-  int aspectindex;
-  int tendegree;
-  int acutebiggest;
-  int i, ii, j, k;
-
-  printf("Mesh quality statistics:\n\n");
-  radconst = (REAL)(PI / 18.0);
-  degconst = (REAL)(180.0 / PI);
-  for (i = 0; i < 8; i++) {
-    cossquaretable[i] = (REAL)(cos(radconst * (REAL) (i + 1)));
-    cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
-  }
-  for (i = 0; i < 18; i++) {
-    angletable[i] = 0;
-  }
-
-  ratiotable[0]  =      1.5;      ratiotable[1]  =     2.0;
-  ratiotable[2]  =      2.5;      ratiotable[3]  =     3.0;
-  ratiotable[4]  =      4.0;      ratiotable[5]  =     6.0;
-  ratiotable[6]  =     10.0;      ratiotable[7]  =    15.0;
-  ratiotable[8]  =     25.0;      ratiotable[9]  =    50.0;
-  ratiotable[10] =    100.0;      ratiotable[11] =   300.0;
-  ratiotable[12] =   1000.0;      ratiotable[13] = 10000.0;
-  ratiotable[14] = 100000.0;      ratiotable[15] =     0.0;
-  for (i = 0; i < 16; i++) {
-    aspecttable[i] = 0;
-  }
-
-  worstaspect = 0.0;
-  minaltitude = xmax - xmin + ymax - ymin;
-  minaltitude = minaltitude * minaltitude;
-  shortest = minaltitude;
-  longest = 0.0;
-  smallestarea = minaltitude;
-  biggestarea = 0.0;
-  worstaspect = 0.0;
-  smallestangle = 0.0;
-  biggestangle = 2.0;
-  acutebiggest = 1;
-
-  traversalinit(&triangles);
-  triangleloop.tri = triangletraverse();
-  triangleloop.orient = 0;
-  while (triangleloop.tri != (triangle *) NULL) {
-    org(triangleloop, p[0]);
-    dest(triangleloop, p[1]);
-    apex(triangleloop, p[2]);
-    trilongest2 = 0.0;
-
-    for (i = 0; i < 3; i++) {
-      j = plus1mod3[i];
-      k = minus1mod3[i];
-      dx[i] = p[j][0] - p[k][0];
-      dy[i] = p[j][1] - p[k][1];
-      edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
-      if (edgelength[i] > trilongest2) {
-        trilongest2 = edgelength[i];
-      }
-      if (edgelength[i] > longest) {
-        longest = edgelength[i];
-      }
-      if (edgelength[i] < shortest) {
-        shortest = edgelength[i];
-      }
-    }
-
-    triarea = counterclockwise(p[0], p[1], p[2]);
-    if (triarea < smallestarea) {
-      smallestarea = triarea;
-    }
-    if (triarea > biggestarea) {
-      biggestarea = triarea;
-    }
-    triminaltitude2 = triarea * triarea / trilongest2;
-    if (triminaltitude2 < minaltitude) {
-      minaltitude = triminaltitude2;
-    }
-    triaspect2 = trilongest2 / triminaltitude2;
-    if (triaspect2 > worstaspect) {
-      worstaspect = triaspect2;
-    }
-    aspectindex = 0;
-    while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
-           && (aspectindex < 15)) {
-      aspectindex++;
-    }
-    aspecttable[aspectindex]++;
-
-    for (i = 0; i < 3; i++) {
-      j = plus1mod3[i];
-      k = minus1mod3[i];
-      dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
-      cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
-      tendegree = 8;
-      for (ii = 7; ii >= 0; ii--) {
-        if (cossquare > cossquaretable[ii]) {
-          tendegree = ii;
-        }
-      }
-      if (dotproduct <= 0.0) {
-        angletable[tendegree]++;
-        if (cossquare > smallestangle) {
-          smallestangle = cossquare;
-        }
-        if (acutebiggest && (cossquare < biggestangle)) {
-          biggestangle = cossquare;
-        }
-      } else {
-        angletable[17 - tendegree]++;
-        if (acutebiggest || (cossquare > biggestangle)) {
-          biggestangle = cossquare;
-          acutebiggest = 0;
-        }
-      }
-    }
-    triangleloop.tri = triangletraverse();
-  }
-
-  shortest = (REAL)sqrt(shortest);
-  longest = (REAL)sqrt(longest);
-  minaltitude = (REAL)sqrt(minaltitude);
-  worstaspect = (REAL)sqrt(worstaspect);
-  smallestarea *= 2.0;
-  biggestarea *= 2.0;
-  if (smallestangle >= 1.0) {
-    smallestangle = 0.0;
-  } else {
-    smallestangle = (REAL)(degconst * acos(sqrt(smallestangle)));
-  }
-  if (biggestangle >= 1.0) {
-    biggestangle = 180.0;
-  } else {
-    if (acutebiggest) {
-      biggestangle = (REAL)(degconst * acos(sqrt(biggestangle)));
-    } else {
-      biggestangle = (REAL)(180.0 - degconst * acos(sqrt(biggestangle)));
-    }
-  }
-
-  printf("  Smallest area: %16.5g   |  Largest area: %16.5g\n",
-         smallestarea, biggestarea);
-  printf("  Shortest edge: %16.5g   |  Longest edge: %16.5g\n",
-         shortest, longest);
-  printf("  Shortest altitude: %12.5g   |  Largest aspect ratio: %8.5g\n\n",
-         minaltitude, worstaspect);
-  printf("  Aspect ratio histogram:\n");
-  printf("  1.1547 - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
-         ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
-         aspecttable[8]);
-  for (i = 1; i < 7; i++) {
-    printf("  %6.6g - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
-           ratiotable[i - 1], ratiotable[i], aspecttable[i],
-           ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
-  }
-  printf("  %6.6g - %-6.6g    :  %8d    | %6.6g -            :  %8d\n",
-         ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
-         aspecttable[15]);
-  printf(
-"  (Triangle aspect ratio is longest edge divided by shortest altitude)\n\n");
-  printf("  Smallest angle: %15.5g   |  Largest angle: %15.5g\n\n",
-         smallestangle, biggestangle);
-  printf("  Angle histogram:\n");
-  for (i = 0; i < 9; i++) {
-    printf("    %3d - %3d degrees:  %8d    |    %3d - %3d degrees:  %8d\n",
-           i * 10, i * 10 + 10, angletable[i],
-           i * 10 + 90, i * 10 + 100, angletable[i + 9]);
-  }
-  printf("\n");
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  statistics()   Print all sorts of cool facts.                            */
-/*                                                                           */
-/*****************************************************************************/
-
-void statistics()
-{
-  printf("\nStatistics:\n\n");
-  printf("  Input points: %d\n", inpoints);
-  if (refine) {
-    printf("  Input triangles: %d\n", inelements);
-  }
-  if (poly) {
-    printf("  Input segments: %d\n", insegments);
-    if (!refine) {
-      printf("  Input holes: %d\n", holes);
-    }
-  }
-
-  printf("\n  Mesh points: %ld\n", points.items);
-  printf("  Mesh triangles: %ld\n", triangles.items);
-  printf("  Mesh edges: %ld\n", edges);
-  if (poly || refine) {
-    printf("  Mesh boundary edges: %ld\n", hullsize);
-    printf("  Mesh segments: %ld\n\n", shelles.items);
-  } else {
-    printf("  Mesh convex hull edges: %ld\n\n", hullsize);
-  }
-  if (verbose) {
-    quality_statistics();
-    printf("Memory allocation statistics:\n\n");
-    printf("  Maximum number of points: %ld\n", points.maxitems);
-    printf("  Maximum number of triangles: %ld\n", triangles.maxitems);
-    if (shelles.maxitems > 0) {
-      printf("  Maximum number of segments: %ld\n", shelles.maxitems);
-    }
-    if (viri.maxitems > 0) {
-      printf("  Maximum number of viri: %ld\n", viri.maxitems);
-    }
-    if (badsegments.maxitems > 0) {
-      printf("  Maximum number of encroached segments: %ld\n",
-             badsegments.maxitems);
-    }
-    if (badtriangles.maxitems > 0) {
-      printf("  Maximum number of bad triangles: %ld\n",
-             badtriangles.maxitems);
-    }
-    if (splaynodes.maxitems > 0) {
-      printf("  Maximum number of splay tree nodes: %ld\n",
-             splaynodes.maxitems);
-    }
-    printf("  Approximate heap memory use (bytes): %ld\n\n",
-           points.maxitems * points.itembytes
-           + triangles.maxitems * triangles.itembytes
-           + shelles.maxitems * shelles.itembytes
-           + viri.maxitems * viri.itembytes
-           + badsegments.maxitems * badsegments.itembytes
-           + badtriangles.maxitems * badtriangles.itembytes
-           + splaynodes.maxitems * splaynodes.itembytes);
-
-    printf("Algorithmic statistics:\n\n");
-    printf("  Number of incircle tests: %ld\n", incirclecount);
-    printf("  Number of orientation tests: %ld\n", counterclockcount);
-    if (hyperbolacount > 0) {
-      printf("  Number of right-of-hyperbola tests: %ld\n",
-             hyperbolacount);
-    }
-    if (circumcentercount > 0) {
-      printf("  Number of circumcenter computations: %ld\n",
-             circumcentercount);
-    }
-    if (circletopcount > 0) {
-      printf("  Number of circle top computations: %ld\n",
-             circletopcount);
-    }
-    printf("\n");
-  }
-}
-
-/*****************************************************************************/
-/*                                                                           */
-/*  main() or triangulate()   Gosh, do everything.                           */
-/*                                                                           */
-/*  The sequence is roughly as follows.  Many of these steps can be skipped, */
-/*  depending on the command line switches.                                  */
-/*                                                                           */
-/*  - Initialize constants and parse the command line.                       */
-/*  - Read the points from a file and either                                 */
-/*    - triangulate them (no -r), or                                         */
-/*    - read an old mesh from files and reconstruct it (-r).                 */
-/*  - Insert the PSLG segments (-p), and possibly segments on the convex     */
-/*      hull (-c).                                                           */
-/*  - Read the holes (-p), regional attributes (-pA), and regional area      */
-/*      constraints (-pa).  Carve the holes and concavities, and spread the  */
-/*      regional attributes and area constraints.                            */
-/*  - Enforce the constraints on minimum angle (-q) and maximum area (-a).   */
-/*      Also enforce the conforming Delaunay property (-q and -a).           */
-/*  - Compute the number of edges in the resulting mesh.                     */
-/*  - Promote the mesh's linear triangles to higher order elements (-o).     */
-/*  - Write the output files and print the statistics.                       */
-/*  - Check the consistency and Delaunay property of the mesh (-C).          */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef TRILIBRARY
-
-void triangulate(triswitches, in, out, vorout)
-char *triswitches;
-struct triangulateio *in;
-struct triangulateio *out;
-struct triangulateio *vorout;
-
-#else /* not TRILIBRARY */
-
-int main(argc, argv)
-int argc;
-char **argv;
-
-#endif /* not TRILIBRARY */
-
-{
-  REAL *holearray;                                        /* Array of holes. */
-  REAL *regionarray;   /* Array of regional attributes and area constraints. */
-#ifndef TRILIBRARY
-  FILE *polyfile;
-#endif /* not TRILIBRARY */
-#ifndef NO_TIMER
-  /* Variables for timing the performance of Triangle.  The types are */
-  /*   defined in sys/time.h.                                         */
-  struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
-  struct timezone tz;
-#endif /* NO_TIMER */
-
-#ifndef NO_TIMER
-  gettimeofday(&tv0, &tz);
-#endif /* NO_TIMER */
-
-  triangleinit();
-#ifdef TRILIBRARY
-  parsecommandline(1, &triswitches);
-#else /* not TRILIBRARY */
-  parsecommandline(argc, argv);
-#endif /* not TRILIBRARY */
-
-#ifdef TRILIBRARY
-  transfernodes(in->pointlist, in->pointattributelist, in->pointmarkerlist,
-                in->numberofpoints, in->numberofpointattributes);
-#else /* not TRILIBRARY */
-  readnodes(innodefilename, inpolyfilename, &polyfile);
-#endif /* not TRILIBRARY */
-
-#ifndef NO_TIMER
-  if (!quiet) {
-    gettimeofday(&tv1, &tz);
-  }
-#endif /* NO_TIMER */
-
-#ifdef CDT_ONLY
-  hullsize = delaunay();                          /* Triangulate the points. */
-#else /* not CDT_ONLY */
-  if (refine) {
-    /* Read and reconstruct a mesh. */
-#ifdef TRILIBRARY
-    hullsize = reconstruct(in->trianglelist, in->triangleattributelist,
-                           in->trianglearealist, in->numberoftriangles,
-                           in->numberofcorners, in->numberoftriangleattributes,
-                           in->segmentlist, in->segmentmarkerlist,
-                           in->numberofsegments);
-#else /* not TRILIBRARY */
-    hullsize = reconstruct(inelefilename, areafilename, inpolyfilename,
-                           polyfile);
-#endif /* not TRILIBRARY */
-  } else {
-    hullsize = delaunay();                        /* Triangulate the points. */
-  }
-#endif /* not CDT_ONLY */
-
-#ifndef NO_TIMER
-  if (!quiet) {
-    gettimeofday(&tv2, &tz);
-    if (refine) {
-      printf("Mesh reconstruction");
-    } else {
-      printf("Delaunay");
-    }
-    printf(" milliseconds:  %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec)
-           + (tv2.tv_usec - tv1.tv_usec) / 1000l);
-  }
-#endif /* NO_TIMER */
-
-  /* Ensure that no point can be mistaken for a triangular bounding */
-  /*   box point in insertsite().                                   */
-  infpoint1 = (point) NULL;
-  infpoint2 = (point) NULL;
-  infpoint3 = (point) NULL;
-
-  if (useshelles) {
-    checksegments = 1;                  /* Segments will be introduced next. */
-    if (!refine) {
-      /* Insert PSLG segments and/or convex hull segments. */
-#ifdef TRILIBRARY
-      insegments = formskeleton(in->segmentlist, in->segmentmarkerlist,
-                                in->numberofsegments);
-#else /* not TRILIBRARY */
-      insegments = formskeleton(polyfile, inpolyfilename);
-#endif /* not TRILIBRARY */
-    }
-  }
-
-#ifndef NO_TIMER
-  if (!quiet) {
-    gettimeofday(&tv3, &tz);
-    if (useshelles && !refine) {
-      printf("Segment milliseconds:  %ld\n",
-             1000l * (tv3.tv_sec - tv2.tv_sec)
-             + (tv3.tv_usec - tv2.tv_usec) / 1000l);
-    }
-  }
-#endif /* NO_TIMER */
-
-  if (poly) {
-#ifdef TRILIBRARY
-    holearray = in->holelist;
-    holes = in->numberofholes;
-    regionarray = in->regionlist;
-    regions = in->numberofregions;
-#else /* not TRILIBRARY */
-    readholes(polyfile, inpolyfilename, &holearray, &holes,
-              &regionarray, &regions);
-#endif /* not TRILIBRARY */
-    if (!refine) {
-      /* Carve out holes and concavities. */
-      carveholes(holearray, holes, regionarray, regions);
-    }
-  } else {
-    /* Without a PSLG, there can be no holes or regional attributes   */
-    /*   or area constraints.  The following are set to zero to avoid */
-    /*   an accidental free() later.                                  */
-    holes = 0;
-    regions = 0;
-  }
-
-#ifndef NO_TIMER
-  if (!quiet) {
-    gettimeofday(&tv4, &tz);
-    if (poly && !refine) {
-      printf("Hole milliseconds:  %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec)
-             + (tv4.tv_usec - tv3.tv_usec) / 1000l);
-    }
-  }
-#endif /* NO_TIMER */
-
-#ifndef CDT_ONLY
-  if (quality) {
-    enforcequality();                 /* Enforce angle and area constraints. */
-  }
-#endif /* not CDT_ONLY */
-
-#ifndef NO_TIMER
-  if (!quiet) {
-    gettimeofday(&tv5, &tz);
-#ifndef CDT_ONLY
-    if (quality) {
-      printf("Quality milliseconds:  %ld\n",
-             1000l * (tv5.tv_sec - tv4.tv_sec)
-             + (tv5.tv_usec - tv4.tv_usec) / 1000l);
-    }
-#endif /* not CDT_ONLY */
-  }
-#endif /* NO_TIMER */
-
-  /* Compute the number of edges. */
-  edges = (3l * triangles.items + hullsize) / 2l;
-
-  if (order > 1) {
-    highorder();             /* Promote elements to higher polynomial order. */
-  }
-  if (!quiet) {
-    printf("\n");
-  }
-
-#ifdef TRILIBRARY
-  out->numberofpoints = points.items;
-  out->numberofpointattributes = nextras;
-  out->numberoftriangles = triangles.items;
-  out->numberofcorners = (order + 1) * (order + 2) / 2;
-  out->numberoftriangleattributes = eextras;
-  out->numberofedges = edges;
-  if (useshelles) {
-    out->numberofsegments = shelles.items;
-  } else {
-    out->numberofsegments = hullsize;
-  }
-  if (vorout != (struct triangulateio *) NULL) {
-    vorout->numberofpoints = triangles.items;
-    vorout->numberofpointattributes = nextras;
-    vorout->numberofedges = edges;
-  }
-#endif /* TRILIBRARY */
-  /* If not using iteration numbers, don't write a .node file if one was */
-  /*   read, because the original one would be overwritten!              */
-  if (nonodewritten || (noiterationnum && readnodefile)) {
-    if (!quiet) {
-#ifdef TRILIBRARY
-      printf("NOT writing points.\n");
-#else /* not TRILIBRARY */
-      printf("NOT writing a .node file.\n");
-#endif /* not TRILIBRARY */
-    }
-    numbernodes();                 /* We must remember to number the points. */
-  } else {
-#ifdef TRILIBRARY
-    writenodes(&out->pointlist, &out->pointattributelist,
-               &out->pointmarkerlist);
-#else /* not TRILIBRARY */
-    writenodes(outnodefilename, argc, argv);      /* Numbers the points too. */
-#endif /* TRILIBRARY */
-  }
-  if (noelewritten) {
-    if (!quiet) {
-#ifdef TRILIBRARY
-      printf("NOT writing triangles.\n");
-#else /* not TRILIBRARY */
-      printf("NOT writing an .ele file.\n");
-#endif /* not TRILIBRARY */
-    }
-  } else {
-#ifdef TRILIBRARY
-    writeelements(&out->trianglelist, &out->triangleattributelist);
-#else /* not TRILIBRARY */
-    writeelements(outelefilename, argc, argv);
-#endif /* not TRILIBRARY */
-  }
-  /* The -c switch (convex switch) causes a PSLG to be written */
-  /*   even if none was read.                                  */
-  if (poly || convex) {
-    /* If not using iteration numbers, don't overwrite the .poly file. */
-    if (nopolywritten || noiterationnum) {
-      if (!quiet) {
-#ifdef TRILIBRARY
-        printf("NOT writing segments.\n");
-#else /* not TRILIBRARY */
-        printf("NOT writing a .poly file.\n");
-#endif /* not TRILIBRARY */
-      }
-    } else {
-#ifdef TRILIBRARY
-      writepoly(&out->segmentlist, &out->segmentmarkerlist);
-      out->numberofholes = holes;
-      out->numberofregions = regions;
-      if (poly) {
-        out->holelist = in->holelist;
-        out->regionlist = in->regionlist;
-      } else {
-        out->holelist = (REAL *) NULL;
-        out->regionlist = (REAL *) NULL;
-      }
-#else /* not TRILIBRARY */
-      writepoly(outpolyfilename, holearray, holes, regionarray, regions,
-                argc, argv);
-#endif /* not TRILIBRARY */
-    }
-  }
-#ifndef TRILIBRARY
-#ifndef CDT_ONLY
-  if (regions > 0) {
-    free(regionarray);
-  }
-#endif /* not CDT_ONLY */
-  if (holes > 0) {
-    free(holearray);
-  }
-  if (geomview) {
-    writeoff(offfilename, argc, argv);
-  }
-#endif /* not TRILIBRARY */
-  if (edgesout) {
-#ifdef TRILIBRARY
-    writeedges(&out->edgelist, &out->edgemarkerlist);
-#else /* not TRILIBRARY */
-    writeedges(edgefilename, argc, argv);
-#endif /* not TRILIBRARY */
-  }
-  if (voronoi) {
-#ifdef TRILIBRARY
-    writevoronoi(&vorout->pointlist, &vorout->pointattributelist,
-                 &vorout->pointmarkerlist, &vorout->edgelist,
-                 &vorout->edgemarkerlist, &vorout->normlist);
-#else /* not TRILIBRARY */
-    writevoronoi(vnodefilename, vedgefilename, argc, argv);
-#endif /* not TRILIBRARY */
-  }
-  if (neighbors) {
-#ifdef TRILIBRARY
-    writeneighbors(&out->neighborlist);
-#else /* not TRILIBRARY */
-    writeneighbors(neighborfilename, argc, argv);
-#endif /* not TRILIBRARY */
-  }
-
-  if (!quiet) {
-#ifndef NO_TIMER
-    gettimeofday(&tv6, &tz);
-    printf("\nOutput milliseconds:  %ld\n",
-           1000l * (tv6.tv_sec - tv5.tv_sec)
-           + (tv6.tv_usec - tv5.tv_usec) / 1000l);
-    printf("Total running milliseconds:  %ld\n",
-           1000l * (tv6.tv_sec - tv0.tv_sec)
-           + (tv6.tv_usec - tv0.tv_usec) / 1000l);
-#endif /* NO_TIMER */
-
-    statistics();
-  }
-
-#ifndef REDUCED
-  if (docheck) {
-    checkmesh();
-    checkdelaunay();
-  }
-#endif /* not REDUCED */
-
-  triangledeinit();
-#ifndef TRILIBRARY
-  return 0;
-#endif /* not TRILIBRARY */
-}
+#define ANSI_DECLARATORS
+/*****************************************************************************/
+/*                                                                           */
+/*      888888888        ,o,                          / 888                  */
+/*         888    88o88o  "    o8888o  88o8888o o88888o 888  o88888o         */
+/*         888    888    888       88b 888  888 888 888 888 d888  88b        */
+/*         888    888    888  o88^o888 888  888 "88888" 888 8888oo888        */
+/*         888    888    888 C888  888 888  888  /      888 q888             */
+/*         888    888    888  "88o^888 888  888 Cb      888  "88oooo"        */
+/*                                              "8oo8D                       */
+/*                                                                           */
+/*  A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.      */
+/*  (triangle.c)                                                             */
+/*                                                                           */
+/*  Version 1.3                                                              */
+/*  July 19, 1996                                                            */
+/*                                                                           */
+/*  Copyright 1996                                                           */
+/*  Jonathan Richard Shewchuk                                                */
+/*  School of Computer Science                                               */
+/*  Carnegie Mellon University                                               */
+/*  5000 Forbes Avenue                                                       */
+/*  Pittsburgh, Pennsylvania  15213-3891                                     */
+/*  jrs@cs.cmu.edu                                                           */
+/*                                                                           */
+/*  This program may be freely redistributed under the condition that the    */
+/*    copyright notices (including this entire header and the copyright      */
+/*    notice printed when the `-h' switch is selected) are not removed, and  */
+/*    no compensation is received.  Private, research, and institutional     */
+/*    use is free.  You may distribute modified versions of this code UNDER  */
+/*    THE CONDITION THAT THIS CODE AND ANY MODIFICATIONS MADE TO IT IN THE   */
+/*    SAME FILE REMAIN UNDER COPYRIGHT OF THE ORIGINAL AUTHOR, BOTH SOURCE   */
+/*    AND OBJECT CODE ARE MADE FREELY AVAILABLE WITHOUT CHARGE, AND CLEAR    */
+/*    NOTICE IS GIVEN OF THE MODIFICATIONS.  Distribution of this code as    */
+/*    part of a commercial system is permissible ONLY BY DIRECT ARRANGEMENT  */
+/*    WITH THE AUTHOR.  (If you are not directly supplying this code to a    */
+/*    customer, and you are instead telling them how they can obtain it for  */
+/*    free, then you are not required to make any arrangement with me.)      */
+/*                                                                           */
+/*  Hypertext instructions for Triangle are available on the Web at          */
+/*                                                                           */
+/*      http://www.cs.cmu.edu/~quake/triangle.html                           */
+/*                                                                           */
+/*  Some of the references listed below are marked [*].  These are available */
+/*    for downloading from the Web page                                      */
+/*                                                                           */
+/*      http://www.cs.cmu.edu/~quake/triangle.research.html                  */
+/*                                                                           */
+/*  A paper discussing some aspects of Triangle is available.  See Jonathan  */
+/*    Richard Shewchuk, "Triangle:  Engineering a 2D Quality Mesh Generator  */
+/*    and Delaunay Triangulator," First Workshop on Applied Computational    */
+/*    Geometry, ACM, May 1996.  [*]                                          */
+/*                                                                           */
+/*  Triangle was created as part of the Archimedes project in the School of  */
+/*    Computer Science at Carnegie Mellon University.  Archimedes is a       */
+/*    system for compiling parallel finite element solvers.  For further     */
+/*    information, see Anja Feldmann, Omar Ghattas, John R. Gilbert, Gary L. */
+/*    Miller, David R. O'Hallaron, Eric J. Schwabe, Jonathan R. Shewchuk,    */
+/*    and Shang-Hua Teng, "Automated Parallel Solution of Unstructured PDE   */
+/*    Problems."  To appear in Communications of the ACM, we hope.           */
+/*                                                                           */
+/*  The quality mesh generation algorithm is due to Jim Ruppert, "A          */
+/*    Delaunay Refinement Algorithm for Quality 2-Dimensional Mesh           */
+/*    Generation," Journal of Algorithms 18(3):548-585, May 1995.  [*]       */
+/*                                                                           */
+/*  My implementation of the divide-and-conquer and incremental Delaunay     */
+/*    triangulation algorithms follows closely the presentation of Guibas    */
+/*    and Stolfi, even though I use a triangle-based data structure instead  */
+/*    of their quad-edge data structure.  (In fact, I originally implemented */
+/*    Triangle using the quad-edge data structure, but switching to a        */
+/*    triangle-based data structure sped Triangle by a factor of two.)  The  */
+/*    mesh manipulation primitives and the two aforementioned Delaunay       */
+/*    triangulation algorithms are described by Leonidas J. Guibas and Jorge */
+/*    Stolfi, "Primitives for the Manipulation of General Subdivisions and   */
+/*    the Computation of Voronoi Diagrams," ACM Transactions on Graphics     */
+/*    4(2):74-123, April 1985.                                               */
+/*                                                                           */
+/*  Their O(n log n) divide-and-conquer algorithm is adapted from Der-Tsai   */
+/*    Lee and Bruce J. Schachter, "Two Algorithms for Constructing the       */
+/*    Delaunay Triangulation," International Journal of Computer and         */
+/*    Information Science 9(3):219-242, 1980.  The idea to improve the       */
+/*    divide-and-conquer algorithm by alternating between vertical and       */
+/*    horizontal cuts was introduced by Rex A. Dwyer, "A Faster Divide-and-  */
+/*    Conquer Algorithm for Constructing Delaunay Triangulations,"           */
+/*    Algorithmica 2(2):137-151, 1987.                                       */
+/*                                                                           */
+/*  The incremental insertion algorithm was first proposed by C. L. Lawson,  */
+/*    "Software for C1 Surface Interpolation," in Mathematical Software III, */
+/*    John R. Rice, editor, Academic Press, New York, pp. 161-194, 1977.     */
+/*    For point location, I use the algorithm of Ernst P. Mucke, Isaac       */
+/*    Saias, and Binhai Zhu, "Fast Randomized Point Location Without         */
+/*    Preprocessing in Two- and Three-dimensional Delaunay Triangulations,"  */
+/*    Proceedings of the Twelfth Annual Symposium on Computational Geometry, */
+/*    ACM, May 1996.  [*]  If I were to randomize the order of point         */
+/*    insertion (I currently don't bother), their result combined with the   */
+/*    result of Leonidas J. Guibas, Donald E. Knuth, and Micha Sharir,       */
+/*    "Randomized Incremental Construction of Delaunay and Voronoi           */
+/*    Diagrams," Algorithmica 7(4):381-413, 1992, would yield an expected    */
+/*    O(n^{4/3}) bound on running time.                                      */
+/*                                                                           */
+/*  The O(n log n) sweepline Delaunay triangulation algorithm is taken from  */
+/*    Steven Fortune, "A Sweepline Algorithm for Voronoi Diagrams",          */
+/*    Algorithmica 2(2):153-174, 1987.  A random sample of edges on the      */
+/*    boundary of the triangulation are maintained in a splay tree for the   */
+/*    purpose of point location.  Splay trees are described by Daniel        */
+/*    Dominic Sleator and Robert Endre Tarjan, "Self-Adjusting Binary Search */
+/*    Trees," Journal of the ACM 32(3):652-686, July 1985.                   */
+/*                                                                           */
+/*  The algorithms for exact computation of the signs of determinants are    */
+/*    described in Jonathan Richard Shewchuk, "Adaptive Precision Floating-  */
+/*    Point Arithmetic and Fast Robust Geometric Predicates," Technical      */
+/*    Report CMU-CS-96-140, School of Computer Science, Carnegie Mellon      */
+/*    University, Pittsburgh, Pennsylvania, May 1996.  [*]  (Submitted to    */
+/*    Discrete & Computational Geometry.)  An abbreviated version appears as */
+/*    Jonathan Richard Shewchuk, "Robust Adaptive Floating-Point Geometric   */
+/*    Predicates," Proceedings of the Twelfth Annual Symposium on Computa-   */
+/*    tional Geometry, ACM, May 1996.  [*]  Many of the ideas for my exact   */
+/*    arithmetic routines originate with Douglas M. Priest, "Algorithms for  */
+/*    Arbitrary Precision Floating Point Arithmetic," Tenth Symposium on     */
+/*    Computer Arithmetic, 132-143, IEEE Computer Society Press, 1991.  [*]  */
+/*    Many of the ideas for the correct evaluation of the signs of           */
+/*    determinants are taken from Steven Fortune and Christopher J. Van Wyk, */
+/*    "Efficient Exact Arithmetic for Computational Geometry," Proceedings   */
+/*    of the Ninth Annual Symposium on Computational Geometry, ACM,          */
+/*    pp. 163-172, May 1993, and from Steven Fortune, "Numerical Stability   */
+/*    of Algorithms for 2D Delaunay Triangulations," International Journal   */
+/*    of Computational Geometry & Applications 5(1-2):193-213, March-June    */
+/*    1995.                                                                  */
+/*                                                                           */
+/*  For definitions of and results involving Delaunay triangulations,        */
+/*    constrained and conforming versions thereof, and other aspects of      */
+/*    triangular mesh generation, see the excellent survey by Marshall Bern  */
+/*    and David Eppstein, "Mesh Generation and Optimal Triangulation," in    */
+/*    Computing and Euclidean Geometry, Ding-Zhu Du and Frank Hwang,         */
+/*    editors, World Scientific, Singapore, pp. 23-90, 1992.                 */
+/*                                                                           */
+/*  The time for incrementally adding PSLG (planar straight line graph)      */
+/*    segments to create a constrained Delaunay triangulation is probably    */
+/*    O(n^2) per segment in the worst case and O(n) per edge in the common   */
+/*    case, where n is the number of triangles that intersect the segment    */
+/*    before it is inserted.  This doesn't count point location, which can   */
+/*    be much more expensive.  (This note does not apply to conforming       */
+/*    Delaunay triangulations, for which a different method is used to       */
+/*    insert segments.)                                                      */
+/*                                                                           */
+/*  The time for adding segments to a conforming Delaunay triangulation is   */
+/*    not clear, but does not depend upon n alone.  In some cases, very      */
+/*    small features (like a point lying next to a segment) can cause a      */
+/*    single segment to be split an arbitrary number of times.  Of course,   */
+/*    floating-point precision is a practical barrier to how much this can   */
+/*    happen.                                                                */
+/*                                                                           */
+/*  The time for deleting a point from a Delaunay triangulation is O(n^2) in */
+/*    the worst case and O(n) in the common case, where n is the degree of   */
+/*    the point being deleted.  I could improve this to expected O(n) time   */
+/*    by "inserting" the neighboring vertices in random order, but n is      */
+/*    usually quite small, so it's not worth the bother.  (The O(n) time     */
+/*    for random insertion follows from L. Paul Chew, "Building Voronoi      */
+/*    Diagrams for Convex Polygons in Linear Expected Time," Technical       */
+/*    Report PCS-TR90-147, Department of Mathematics and Computer Science,   */
+/*    Dartmouth College, 1990.                                               */
+/*                                                                           */
+/*  Ruppert's Delaunay refinement algorithm typically generates triangles    */
+/*    at a linear rate (constant time per triangle) after the initial        */
+/*    triangulation is formed.  There may be pathological cases where more   */
+/*    time is required, but these never arise in practice.                   */
+/*                                                                           */
+/*  The segment intersection formulae are straightforward.  If you want to   */
+/*    see them derived, see Franklin Antonio.  "Faster Line Segment          */
+/*    Intersection."  In Graphics Gems III (David Kirk, editor), pp. 199-    */
+/*    202.  Academic Press, Boston, 1992.                                    */
+/*                                                                           */
+/*  If you make any improvements to this code, please please please let me   */
+/*    know, so that I may obtain the improvements.  Even if you don't change */
+/*    the code, I'd still love to hear what it's being used for.             */
+/*                                                                           */
+/*  Disclaimer:  Neither I nor Carnegie Mellon warrant this code in any way  */
+/*    whatsoever.  This code is provided "as-is".  Use at your own risk.     */
+/*                                                                           */
+/*****************************************************************************/
+
+/* For single precision (which will save some memory and reduce paging),     */
+/*   define the symbol SINGLE by using the -DSINGLE compiler switch or by    */
+/*   writing "#define SINGLE" below.                                         */
+/*                                                                           */
+/* For double precision (which will allow you to refine meshes to a smaller  */
+/*   edge length), leave SINGLE undefined.                                   */
+/*                                                                           */
+/* Double precision uses more memory, but improves the resolution of the     */
+/*   meshes you can generate with Triangle.  It also reduces the likelihood  */
+/*   of a floating exception due to overflow.  Finally, it is much faster    */
+/*   than single precision on 64-bit architectures like the DEC Alpha.  I    */
+/*   recommend double precision unless you want to generate a mesh for which */
+/*   you do not have enough memory.                                          */
+
+#define SINGLE
+
+#ifdef SINGLE
+#define REAL float
+#else /* not SINGLE */
+#define REAL double
+#endif /* not SINGLE */
+
+/* If yours is not a Unix system, define the NO_TIMER compiler switch to     */
+/*   remove the Unix-specific timing code.                                   */
+
+#define NO_TIMER
+
+/* To insert lots of self-checks for internal errors, define the SELF_CHECK  */
+/*   symbol.  This will slow down the program significantly.  It is best to  */
+/*   define the symbol using the -DSELF_CHECK compiler switch, but you could */
+/*   write "#define SELF_CHECK" below.  If you are modifying this code, I    */
+/*   recommend you turn self-checks on.                                      */
+
+/* #define SELF_CHECK */
+
+/* To compile Triangle as a callable object library (triangle.o), define the */
+/*   TRILIBRARY symbol.  Read the file triangle.h for details on how to call */
+/*   the procedure triangulate() that results.                               */
+
+#define TRILIBRARY
+
+/* It is possible to generate a smaller version of Triangle using one or     */
+/*   both of the following symbols.  Define the REDUCED symbol to eliminate  */
+/*   all features that are primarily of research interest; specifically, the */
+/*   -i, -F, -s, and -C switches.  Define the CDT_ONLY symbol to eliminate   */
+/*   all meshing algorithms above and beyond constrained Delaunay            */
+/*   triangulation; specifically, the -r, -q, -a, -S, and -s switches.       */
+/*   These reductions are most likely to be useful when generating an object */
+/*   library (triangle.o) by defining the TRILIBRARY symbol.                 */
+
+#define REDUCED
+#define CDT_ONLY
+
+/* On some machines, the exact arithmetic routines might be defeated by the  */
+/*   use of internal extended precision floating-point registers.  Sometimes */
+/*   this problem can be fixed by defining certain values to be volatile,    */
+/*   thus forcing them to be stored to memory and rounded off.  This isn't   */
+/*   a great solution, though, as it slows Triangle down.                    */
+/*                                                                           */
+/* To try this out, write "#define INEXACT volatile" below.  Normally,       */
+/*   however, INEXACT should be defined to be nothing.  ("#define INEXACT".) */
+
+#define INEXACT /* Nothing */
+/* #define INEXACT volatile */
+
+/* Maximum number of characters in a file name (including the null).         */
+
+#define FILENAMESIZE 512
+
+/* Maximum number of characters in a line read from a file (including the    */
+/*   null).                                                                  */
+
+#define INPUTLINESIZE 512
+
+/* For efficiency, a variety of data structures are allocated in bulk.  The  */
+/*   following constants determine how many of each structure is allocated   */
+/*   at once.                                                                */
+
+#define TRIPERBLOCK 4092           /* Number of triangles allocated at once. */
+#define SHELLEPERBLOCK 508       /* Number of shell edges allocated at once. */
+#define POINTPERBLOCK 4092            /* Number of points allocated at once. */
+#define VIRUSPERBLOCK 1020   /* Number of virus triangles allocated at once. */
+/* Number of encroached segments allocated at once. */
+#define BADSEGMENTPERBLOCK 252
+/* Number of skinny triangles allocated at once. */
+#define BADTRIPERBLOCK 4092
+/* Number of splay tree nodes allocated at once. */
+#define SPLAYNODEPERBLOCK 508
+
+/* The point marker DEADPOINT is an arbitrary number chosen large enough to  */
+/*   (hopefully) not conflict with user boundary markers.  Make sure that it */
+/*   is small enough to fit into your machine's integer size.                */
+
+#define DEADPOINT -1073741824
+
+/* The next line is used to outsmart some very stupid compilers.  If your    */
+/*   compiler is smarter, feel free to replace the "int" with "void".        */
+/*   Not that it matters.                                                    */
+
+#define VOID int
+
+/* Two constants for algorithms based on random sampling.  Both constants    */
+/*   have been chosen empirically to optimize their respective algorithms.   */
+
+/* Used for the point location scheme of Mucke, Saias, and Zhu, to decide    */
+/*   how large a random sample of triangles to inspect.                      */
+#define SAMPLEFACTOR 11
+/* Used in Fortune's sweepline Delaunay algorithm to determine what fraction */
+/*   of boundary edges should be maintained in the splay tree for point      */
+/*   location on the front.                                                  */
+#define SAMPLERATE 10
+
+/* A number that speaks for itself, every kissable digit.                    */
+
+#define PI 3.141592653589793238462643383279502884197169399375105820974944592308
+
+/* Another fave.                                                             */
+
+#define SQUAREROOTTWO 1.4142135623730950488016887242096980785696718753769480732
+
+/* And here's one for those of you who are intimidated by math.              */
+
+#define ONETHIRD 0.333333333333333333333333333333333333333333333333333333333333
+
+#include <stdio.h>
+#include <string.h>
+#include <math.h>
+#ifndef NO_TIMER
+#include <sys/time.h>
+#endif /* NO_TIMER */
+#ifdef TRILIBRARY
+#include "triangle.h"
+#endif /* TRILIBRARY */
+
+/* The following obscenity seems to be necessary to ensure that this program */
+/* will port to Dec Alphas running OSF/1, because their stdio.h file commits */
+/* the unpardonable sin of including stdlib.h.  Hence, malloc(), free(), and */
+/* exit() may or may not already be defined at this point.  I declare these  */
+/* functions explicitly because some non-ANSI C compilers lack stdlib.h.     */
+
+#ifndef _STDLIB_H_
+extern void *malloc();
+extern void free();
+extern void exit();
+extern double strtod();
+extern long strtol();
+#endif /* _STDLIB_H_ */
+
+/* A few forward declarations.                                               */
+
+void poolrestart();
+#ifndef TRILIBRARY
+char *readline();
+char *findfield();
+#endif /* not TRILIBRARY */
+
+/* Labels that signify whether a record consists primarily of pointers or of */
+/*   floating-point words.  Used to make decisions about data alignment.     */
+
+enum wordtype {POINTER, FLOATINGPOINT};
+
+/* Labels that signify the result of point location.  The result of a        */
+/*   search indicates that the point falls in the interior of a triangle, on */
+/*   an edge, on a vertex, or outside the mesh.                              */
+
+enum locateresult {INTRIANGLE, ONEDGE, ONVERTEX, OUTSIDE};
+
+/* Labels that signify the result of site insertion.  The result indicates   */
+/*   that the point was inserted with complete success, was inserted but     */
+/*   encroaches on a segment, was not inserted because it lies on a segment, */
+/*   or was not inserted because another point occupies the same location.   */
+
+enum insertsiteresult {SUCCESSFULPOINT, ENCROACHINGPOINT, VIOLATINGPOINT,
+                       DUPLICATEPOINT};
+
+/* Labels that signify the result of direction finding.  The result          */
+/*   indicates that a segment connecting the two query points falls within   */
+/*   the direction triangle, along the left edge of the direction triangle,  */
+/*   or along the right edge of the direction triangle.                      */
+
+enum finddirectionresult {WITHIN, LEFTCOLLINEAR, RIGHTCOLLINEAR};
+
+/* Labels that signify the result of the circumcenter computation routine.   */
+/*   The return value indicates which edge of the triangle is shortest.      */
+
+enum circumcenterresult {OPPOSITEORG, OPPOSITEDEST, OPPOSITEAPEX};
+
+/*****************************************************************************/
+/*                                                                           */
+/*  The basic mesh data structures                                           */
+/*                                                                           */
+/*  There are three:  points, triangles, and shell edges (abbreviated        */
+/*  `shelle').  These three data structures, linked by pointers, comprise    */
+/*  the mesh.  A point simply represents a point in space and its properties.*/
+/*  A triangle is a triangle.  A shell edge is a special data structure used */
+/*  to represent impenetrable segments in the mesh (including the outer      */
+/*  boundary, boundaries of holes, and internal boundaries separating two    */
+/*  triangulated regions).  Shell edges represent boundaries defined by the  */
+/*  user that triangles may not lie across.                                  */
+/*                                                                           */
+/*  A triangle consists of a list of three vertices, a list of three         */
+/*  adjoining triangles, a list of three adjoining shell edges (when shell   */
+/*  edges are used), an arbitrary number of optional user-defined floating-  */
+/*  point attributes, and an optional area constraint.  The latter is an     */
+/*  upper bound on the permissible area of each triangle in a region, used   */
+/*  for mesh refinement.                                                     */
+/*                                                                           */
+/*  For a triangle on a boundary of the mesh, some or all of the neighboring */
+/*  triangles may not be present.  For a triangle in the interior of the     */
+/*  mesh, often no neighboring shell edges are present.  Such absent         */
+/*  triangles and shell edges are never represented by NULL pointers; they   */
+/*  are represented by two special records:  `dummytri', the triangle that   */
+/*  fills "outer space", and `dummysh', the omnipresent shell edge.          */
+/*  `dummytri' and `dummysh' are used for several reasons; for instance,     */
+/*  they can be dereferenced and their contents examined without causing the */
+/*  memory protection exception that would occur if NULL were dereferenced.  */
+/*                                                                           */
+/*  However, it is important to understand that a triangle includes other    */
+/*  information as well.  The pointers to adjoining vertices, triangles, and */
+/*  shell edges are ordered in a way that indicates their geometric relation */
+/*  to each other.  Furthermore, each of these pointers contains orientation */
+/*  information.  Each pointer to an adjoining triangle indicates which face */
+/*  of that triangle is contacted.  Similarly, each pointer to an adjoining  */
+/*  shell edge indicates which side of that shell edge is contacted, and how */
+/*  the shell edge is oriented relative to the triangle.                     */
+/*                                                                           */
+/*  Shell edges are found abutting edges of triangles; either sandwiched     */
+/*  between two triangles, or resting against one triangle on an exterior    */
+/*  boundary or hole boundary.                                               */
+/*                                                                           */
+/*  A shell edge consists of a list of two vertices, a list of two           */
+/*  adjoining shell edges, and a list of two adjoining triangles.  One of    */
+/*  the two adjoining triangles may not be present (though there should      */
+/*  always be one), and neighboring shell edges might not be present.        */
+/*  Shell edges also store a user-defined integer "boundary marker".         */
+/*  Typically, this integer is used to indicate what sort of boundary        */
+/*  conditions are to be applied at that location in a finite element        */
+/*  simulation.                                                              */
+/*                                                                           */
+/*  Like triangles, shell edges maintain information about the relative      */
+/*  orientation of neighboring objects.                                      */
+/*                                                                           */
+/*  Points are relatively simple.  A point is a list of floating point       */
+/*  numbers, starting with the x, and y coordinates, followed by an          */
+/*  arbitrary number of optional user-defined floating-point attributes,     */
+/*  followed by an integer boundary marker.  During the segment insertion    */
+/*  phase, there is also a pointer from each point to a triangle that may    */
+/*  contain it.  Each pointer is not always correct, but when one is, it     */
+/*  speeds up segment insertion.  These pointers are assigned values once    */
+/*  at the beginning of the segment insertion phase, and are not used or     */
+/*  updated at any other time.  Edge swapping during segment insertion will  */
+/*  render some of them incorrect.  Hence, don't rely upon them for          */
+/*  anything.  For the most part, points do not have any information about   */
+/*  what triangles or shell edges they are linked to.                        */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  Handles                                                                  */
+/*                                                                           */
+/*  The oriented triangle (`triedge') and oriented shell edge (`edge') data  */
+/*  structures defined below do not themselves store any part of the mesh.   */
+/*  The mesh itself is made of `triangle's, `shelle's, and `point's.         */
+/*                                                                           */
+/*  Oriented triangles and oriented shell edges will usually be referred to  */
+/*  as "handles".  A handle is essentially a pointer into the mesh; it       */
+/*  allows you to "hold" one particular part of the mesh.  Handles are used  */
+/*  to specify the regions in which one is traversing and modifying the mesh.*/
+/*  A single `triangle' may be held by many handles, or none at all.  (The   */
+/*  latter case is not a memory leak, because the triangle is still          */
+/*  connected to other triangles in the mesh.)                               */
+/*                                                                           */
+/*  A `triedge' is a handle that holds a triangle.  It holds a specific side */
+/*  of the triangle.  An `edge' is a handle that holds a shell edge.  It     */
+/*  holds either the left or right side of the edge.                         */
+/*                                                                           */
+/*  Navigation about the mesh is accomplished through a set of mesh          */
+/*  manipulation primitives, further below.  Many of these primitives take   */
+/*  a handle and produce a new handle that holds the mesh near the first     */
+/*  handle.  Other primitives take two handles and glue the corresponding    */
+/*  parts of the mesh together.  The exact position of the handles is        */
+/*  important.  For instance, when two triangles are glued together by the   */
+/*  bond() primitive, they are glued by the sides on which the handles lie.  */
+/*                                                                           */
+/*  Because points have no information about which triangles they are        */
+/*  attached to, I commonly represent a point by use of a handle whose       */
+/*  origin is the point.  A single handle can simultaneously represent a     */
+/*  triangle, an edge, and a point.                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+/* The triangle data structure.  Each triangle contains three pointers to    */
+/*   adjoining triangles, plus three pointers to vertex points, plus three   */
+/*   pointers to shell edges (defined below; these pointers are usually      */
+/*   `dummysh').  It may or may not also contain user-defined attributes     */
+/*   and/or a floating-point "area constraint".  It may also contain extra   */
+/*   pointers for nodes, when the user asks for high-order elements.         */
+/*   Because the size and structure of a `triangle' is not decided until     */
+/*   runtime, I haven't simply defined the type `triangle' to be a struct.   */
+
+typedef REAL **triangle;            /* Really:  typedef triangle *triangle   */
+
+/* An oriented triangle:  includes a pointer to a triangle and orientation.  */
+/*   The orientation denotes an edge of the triangle.  Hence, there are      */
+/*   three possible orientations.  By convention, each edge is always        */
+/*   directed to point counterclockwise about the corresponding triangle.    */
+
+struct triedge {
+  triangle *tri;
+  int orient;                                         /* Ranges from 0 to 2. */
+};
+
+/* The shell data structure.  Each shell edge contains two pointers to       */
+/*   adjoining shell edges, plus two pointers to vertex points, plus two     */
+/*   pointers to adjoining triangles, plus one shell marker.                 */
+
+typedef REAL **shelle;                  /* Really:  typedef shelle *shelle   */
+
+/* An oriented shell edge:  includes a pointer to a shell edge and an        */
+/*   orientation.  The orientation denotes a side of the edge.  Hence, there */
+/*   are two possible orientations.  By convention, the edge is always       */
+/*   directed so that the "side" denoted is the right side of the edge.      */
+
+struct edge {
+  shelle *sh;
+  int shorient;                                       /* Ranges from 0 to 1. */
+};
+
+/* The point data structure.  Each point is actually an array of REALs.      */
+/*   The number of REALs is unknown until runtime.  An integer boundary      */
+/*   marker, and sometimes a pointer to a triangle, is appended after the    */
+/*   REALs.                                                                  */
+
+typedef REAL *point;
+
+/* A queue used to store encroached segments.  Each segment's vertices are   */
+/*   stored so that one can check whether a segment is still the same.       */
+
+struct badsegment {
+  struct edge encsegment;                          /* An encroached segment. */
+  point segorg, segdest;                                /* The two vertices. */
+  struct badsegment *nextsegment;     /* Pointer to next encroached segment. */
+};
+
+/* A queue used to store bad triangles.  The key is the square of the cosine */
+/*   of the smallest angle of the triangle.  Each triangle's vertices are    */
+/*   stored so that one can check whether a triangle is still the same.      */
+
+struct badface {
+  struct triedge badfacetri;                              /* A bad triangle. */
+  REAL key;                             /* cos^2 of smallest (apical) angle. */
+  point faceorg, facedest, faceapex;                  /* The three vertices. */
+  struct badface *nextface;                 /* Pointer to next bad triangle. */
+};
+
+/* A node in a heap used to store events for the sweepline Delaunay          */
+/*   algorithm.  Nodes do not point directly to their parents or children in */
+/*   the heap.  Instead, each node knows its position in the heap, and can   */
+/*   look up its parent and children in a separate array.  The `eventptr'    */
+/*   points either to a `point' or to a triangle (in encoded format, so that */
+/*   an orientation is included).  In the latter case, the origin of the     */
+/*   oriented triangle is the apex of a "circle event" of the sweepline      */
+/*   algorithm.  To distinguish site events from circle events, all circle   */
+/*   events are given an invalid (smaller than `xmin') x-coordinate `xkey'.  */
+
+struct event {
+  REAL xkey, ykey;                              /* Coordinates of the event. */
+  VOID *eventptr;       /* Can be a point or the location of a circle event. */
+  int heapposition;              /* Marks this event's position in the heap. */
+};
+
+/* A node in the splay tree.  Each node holds an oriented ghost triangle     */
+/*   that represents a boundary edge of the growing triangulation.  When a   */
+/*   circle event covers two boundary edges with a triangle, so that they    */
+/*   are no longer boundary edges, those edges are not immediately deleted   */
+/*   from the tree; rather, they are lazily deleted when they are next       */
+/*   encountered.  (Since only a random sample of boundary edges are kept    */
+/*   in the tree, lazy deletion is faster.)  `keydest' is used to verify     */
+/*   that a triangle is still the same as when it entered the splay tree; if */
+/*   it has been rotated (due to a circle event), it no longer represents a  */
+/*   boundary edge and should be deleted.                                    */
+
+struct splaynode {
+  struct triedge keyedge;                  /* Lprev of an edge on the front. */
+  point keydest;            /* Used to verify that splay node is still live. */
+  struct splaynode *lchild, *rchild;              /* Children in splay tree. */
+};
+
+/* A type used to allocate memory.  firstblock is the first block of items.  */
+/*   nowblock is the block from which items are currently being allocated.   */
+/*   nextitem points to the next slab of free memory for an item.            */
+/*   deaditemstack is the head of a linked list (stack) of deallocated items */
+/*   that can be recycled.  unallocateditems is the number of items that     */
+/*   remain to be allocated from nowblock.                                   */
+/*                                                                           */
+/* Traversal is the process of walking through the entire list of items, and */
+/*   is separate from allocation.  Note that a traversal will visit items on */
+/*   the "deaditemstack" stack as well as live items.  pathblock points to   */
+/*   the block currently being traversed.  pathitem points to the next item  */
+/*   to be traversed.  pathitemsleft is the number of items that remain to   */
+/*   be traversed in pathblock.                                              */
+/*                                                                           */
+/* itemwordtype is set to POINTER or FLOATINGPOINT, and is used to suggest   */
+/*   what sort of word the record is primarily made up of.  alignbytes       */
+/*   determines how new records should be aligned in memory.  itembytes and  */
+/*   itemwords are the length of a record in bytes (after rounding up) and   */
+/*   words.  itemsperblock is the number of items allocated at once in a     */
+/*   single block.  items is the number of currently allocated items.        */
+/*   maxitems is the maximum number of items that have been allocated at     */
+/*   once; it is the current number of items plus the number of records kept */
+/*   on deaditemstack.                                                       */
+
+struct memorypool {
+  VOID **firstblock, **nowblock;
+  VOID *nextitem;
+  VOID *deaditemstack;
+  VOID **pathblock;
+  VOID *pathitem;
+  enum wordtype itemwordtype;
+  int alignbytes;
+  int itembytes, itemwords;
+  int itemsperblock;
+  long items, maxitems;
+  int unallocateditems;
+  int pathitemsleft;
+};
+
+/* Variables used to allocate memory for triangles, shell edges, points,     */
+/*   viri (triangles being eaten), bad (encroached) segments, bad (skinny    */
+/*   or too large) triangles, and splay tree nodes.                          */
+
+static struct memorypool triangles;
+static struct memorypool shelles;
+static struct memorypool points;
+static struct memorypool viri;
+static struct memorypool badsegments;
+static struct memorypool badtriangles;
+static struct memorypool splaynodes;
+
+/* Variables that maintain the bad triangle queues.  The tails are pointers  */
+/*   to the pointers that have to be filled in to enqueue an item.           */
+
+static struct badface *queuefront[64];
+static struct badface **queuetail[64];
+
+static REAL xmin, xmax, ymin, ymax;                              /* x and y bounds. */
+static REAL xminextreme;        /* Nonexistent x value used as a flag in sweepline. */
+static int inpoints;                                     /* Number of input points. */
+static int inelements;                                /* Number of input triangles. */
+static int insegments;                                 /* Number of input segments. */
+static int holes;                                         /* Number of input holes. */
+static int regions;                                     /* Number of input regions. */
+static long edges;                                       /* Number of output edges. */
+static int mesh_dim;                                  /* Dimension (ought to be 2). */
+static int nextras;                              /* Number of attributes per point. */
+static int eextras;                           /* Number of attributes per triangle. */
+static long hullsize;                            /* Number of edges of convex hull. */
+static int triwords;                                   /* Total words per triangle. */
+static int shwords;                                  /* Total words per shell edge. */
+static int pointmarkindex;             /* Index to find boundary marker of a point. */
+static int point2triindex;         /* Index to find a triangle adjacent to a point. */
+static int highorderindex;    /* Index to find extra nodes for high-order elements. */
+static int elemattribindex;              /* Index to find attributes of a triangle. */
+static int areaboundindex;               /* Index to find area bound of a triangle. */
+static int checksegments;           /* Are there segments in the triangulation yet? */
+static int readnodefile;                             /* Has a .node file been read? */
+static long samples;                /* Number of random samples for point location. */
+static unsigned long randomseed;                     /* Current random number seed. */
+
+static REAL splitter;       /* Used to split REAL factors for exact multiplication. */
+static REAL epsilon;                             /* Floating-point machine epsilon. */
+static REAL resulterrbound;
+static REAL ccwerrboundA, ccwerrboundB, ccwerrboundC;
+static REAL iccerrboundA, iccerrboundB, iccerrboundC;
+
+static long incirclecount;                   /* Number of incircle tests performed. */
+static long counterclockcount;       /* Number of counterclockwise tests performed. */
+static long hyperbolacount;        /* Number of right-of-hyperbola tests performed. */
+static long circumcentercount;    /* Number of circumcenter calculations performed. */
+static long circletopcount;         /* Number of circle top calculations performed. */
+
+/* Switches for the triangulator.                                            */
+/*   poly: -p switch.  refine: -r switch.                                    */
+/*   quality: -q switch.                                                     */
+/*     minangle: minimum angle bound, specified after -q switch.             */
+/*     goodangle: cosine squared of minangle.                                */
+/*   vararea: -a switch without number.                                      */
+/*   fixedarea: -a switch with number.                                       */
+/*     maxarea: maximum area bound, specified after -a switch.               */
+/*   regionattrib: -A switch.  convex: -c switch.                            */
+/*   firstnumber: inverse of -z switch.  All items are numbered starting     */
+/*     from firstnumber.                                                     */
+/*   edgesout: -e switch.  voronoi: -v switch.                               */
+/*   neighbors: -n switch.  geomview: -g switch.                             */
+/*   nobound: -B switch.  nopolywritten: -P switch.                          */
+/*   nonodewritten: -N switch.  noelewritten: -E switch.                     */
+/*   noiterationnum: -I switch.  noholes: -O switch.                         */
+/*   noexact: -X switch.                                                     */
+/*   order: element order, specified after -o switch.                        */
+/*   nobisect: count of how often -Y switch is selected.                     */
+/*   steiner: maximum number of Steiner points, specified after -S switch.   */
+/*     steinerleft: number of Steiner points not yet used.                   */
+/*   incremental: -i switch.  sweepline: -F switch.                          */
+/*   dwyer: inverse of -l switch.                                            */
+/*   splitseg: -s switch.                                                    */
+/*   docheck: -C switch.                                                     */
+/*   quiet: -Q switch.  verbose: count of how often -V switch is selected.   */
+/*   useshelles: -p, -r, -q, or -c switch; determines whether shell edges    */
+/*     are used at all.                                                      */
+/*                                                                           */
+/* Read the instructions to find out the meaning of these switches.          */
+
+static int poly, refine, quality, vararea, fixedarea, regionattrib, convex;
+static int firstnumber;
+static int edgesout, voronoi, neighbors, geomview;
+static int nobound, nopolywritten, nonodewritten, noelewritten, noiterationnum;
+static int noholes, noexact;
+static int incremental, sweepline, dwyer;
+static int splitseg;
+static int docheck;
+static int quiet, verbose;
+static int useshelles;
+static int order;
+static int nobisect;
+static int steiner, steinerleft;
+static REAL minangle, goodangle;
+static REAL maxarea;
+
+/* Variables for file names.                                                 */
+
+#ifndef TRILIBRARY
+char innodefilename[FILENAMESIZE];
+char inelefilename[FILENAMESIZE];
+char inpolyfilename[FILENAMESIZE];
+char areafilename[FILENAMESIZE];
+char outnodefilename[FILENAMESIZE];
+char outelefilename[FILENAMESIZE];
+char outpolyfilename[FILENAMESIZE];
+char edgefilename[FILENAMESIZE];
+char vnodefilename[FILENAMESIZE];
+char vedgefilename[FILENAMESIZE];
+char neighborfilename[FILENAMESIZE];
+char offfilename[FILENAMESIZE];
+#endif /* not TRILIBRARY */
+
+/* Triangular bounding box points.                                           */
+
+static point infpoint1, infpoint2, infpoint3;
+
+/* Pointer to the `triangle' that occupies all of "outer space".             */
+
+static triangle *dummytri;
+static triangle *dummytribase;      /* Keep base address so we can free() it later. */
+
+/* Pointer to the omnipresent shell edge.  Referenced by any triangle or     */
+/*   shell edge that isn't really connected to a shell edge at that          */
+/*   location.                                                               */
+
+static shelle *dummysh;
+static shelle *dummyshbase;         /* Keep base address so we can free() it later. */
+
+/* Pointer to a recently visited triangle.  Improves point location if       */
+/*   proximate points are inserted sequentially.                             */
+
+static struct triedge recenttri;
+
+/*****************************************************************************/
+/*                                                                           */
+/*  Mesh manipulation primitives.  Each triangle contains three pointers to  */
+/*  other triangles, with orientations.  Each pointer points not to the      */
+/*  first byte of a triangle, but to one of the first three bytes of a       */
+/*  triangle.  It is necessary to extract both the triangle itself and the   */
+/*  orientation.  To save memory, I keep both pieces of information in one   */
+/*  pointer.  To make this possible, I assume that all triangles are aligned */
+/*  to four-byte boundaries.  The `decode' routine below decodes a pointer,  */
+/*  extracting an orientation (in the range 0 to 2) and a pointer to the     */
+/*  beginning of a triangle.  The `encode' routine compresses a pointer to a */
+/*  triangle and an orientation into a single pointer.  My assumptions that  */
+/*  triangles are four-byte-aligned and that the `unsigned long' type is     */
+/*  long enough to hold a pointer are two of the few kludges in this program.*/
+/*                                                                           */
+/*  Shell edges are manipulated similarly.  A pointer to a shell edge        */
+/*  carries both an address and an orientation in the range 0 to 1.          */
+/*                                                                           */
+/*  The other primitives take an oriented triangle or oriented shell edge,   */
+/*  and return an oriented triangle or oriented shell edge or point; or they */
+/*  change the connections in the data structure.                            */
+/*                                                                           */
+/*****************************************************************************/
+
+/********* Mesh manipulation primitives begin here                   *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/* Fast lookup arrays to speed some of the mesh manipulation primitives.     */
+
+int plus1mod3[3] = {1, 2, 0};
+int minus1mod3[3] = {2, 0, 1};
+
+/********* Primitives for triangles                                  *********/
+/*                                                                           */
+/*                                                                           */
+
+/* decode() converts a pointer to an oriented triangle.  The orientation is  */
+/*   extracted from the two least significant bits of the pointer.           */
+
+#define decode(ptr, triedge)                                                  \
+  (triedge).orient = (int) ((unsigned long) (ptr) & (unsigned long) 3l);      \
+  (triedge).tri = (triangle *)                                                \
+                  ((unsigned long) (ptr) ^ (unsigned long) (triedge).orient)
+
+/* encode() compresses an oriented triangle into a single pointer.  It       */
+/*   relies on the assumption that all triangles are aligned to four-byte    */
+/*   boundaries, so the two least significant bits of (triedge).tri are zero.*/
+
+#define encode(triedge)                                                       \
+  (triangle) ((unsigned long) (triedge).tri | (unsigned long) (triedge).orient)
+
+/* The following edge manipulation primitives are all described by Guibas    */
+/*   and Stolfi.  However, they use an edge-based data structure, whereas I  */
+/*   am using a triangle-based data structure.                               */
+
+/* sym() finds the abutting triangle, on the same edge.  Note that the       */
+/*   edge direction is necessarily reversed, because triangle/edge handles   */
+/*   are always directed counterclockwise around the triangle.               */
+
+#define sym(triedge1, triedge2)                                               \
+  ptr = (triedge1).tri[(triedge1).orient];                                    \
+  decode(ptr, triedge2);
+
+#define symself(triedge)                                                      \
+  ptr = (triedge).tri[(triedge).orient];                                      \
+  decode(ptr, triedge);
+
+/* lnext() finds the next edge (counterclockwise) of a triangle.             */
+
+#define lnext(triedge1, triedge2)                                             \
+  (triedge2).tri = (triedge1).tri;                                            \
+  (triedge2).orient = plus1mod3[(triedge1).orient]
+
+#define lnextself(triedge)                                                    \
+  (triedge).orient = plus1mod3[(triedge).orient]
+
+/* lprev() finds the previous edge (clockwise) of a triangle.                */
+
+#define lprev(triedge1, triedge2)                                             \
+  (triedge2).tri = (triedge1).tri;                                            \
+  (triedge2).orient = minus1mod3[(triedge1).orient]
+
+#define lprevself(triedge)                                                    \
+  (triedge).orient = minus1mod3[(triedge).orient]
+
+/* onext() spins counterclockwise around a point; that is, it finds the next */
+/*   edge with the same origin in the counterclockwise direction.  This edge */
+/*   will be part of a different triangle.                                   */
+
+#define onext(triedge1, triedge2)                                             \
+  lprev(triedge1, triedge2);                                                  \
+  symself(triedge2);
+
+#define onextself(triedge)                                                    \
+  lprevself(triedge);                                                         \
+  symself(triedge);
+
+/* oprev() spins clockwise around a point; that is, it finds the next edge   */
+/*   with the same origin in the clockwise direction.  This edge will be     */
+/*   part of a different triangle.                                           */
+
+#define oprev(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lnextself(triedge2);
+
+#define oprevself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lnextself(triedge);
+
+/* dnext() spins counterclockwise around a point; that is, it finds the next */
+/*   edge with the same destination in the counterclockwise direction.  This */
+/*   edge will be part of a different triangle.                              */
+
+#define dnext(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lprevself(triedge2);
+
+#define dnextself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lprevself(triedge);
+
+/* dprev() spins clockwise around a point; that is, it finds the next edge   */
+/*   with the same destination in the clockwise direction.  This edge will   */
+/*   be part of a different triangle.                                        */
+
+#define dprev(triedge1, triedge2)                                             \
+  lnext(triedge1, triedge2);                                                  \
+  symself(triedge2);
+
+#define dprevself(triedge)                                                    \
+  lnextself(triedge);                                                         \
+  symself(triedge);
+
+/* rnext() moves one edge counterclockwise about the adjacent triangle.      */
+/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
+/*   changing triangles twice.)                                              */
+
+#define rnext(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lnextself(triedge2);                                                        \
+  symself(triedge2);
+
+#define rnextself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lnextself(triedge);                                                         \
+  symself(triedge);
+
+/* rnext() moves one edge clockwise about the adjacent triangle.             */
+/*   (It's best understood by reading Guibas and Stolfi.  It involves        */
+/*   changing triangles twice.)                                              */
+
+#define rprev(triedge1, triedge2)                                             \
+  sym(triedge1, triedge2);                                                    \
+  lprevself(triedge2);                                                        \
+  symself(triedge2);
+
+#define rprevself(triedge)                                                    \
+  symself(triedge);                                                           \
+  lprevself(triedge);                                                         \
+  symself(triedge);
+
+/* These primitives determine or set the origin, destination, or apex of a   */
+/* triangle.                                                                 */
+
+#define org(triedge, pointptr)                                                \
+  pointptr = (point) (triedge).tri[plus1mod3[(triedge).orient] + 3]
+
+#define dest(triedge, pointptr)                                               \
+  pointptr = (point) (triedge).tri[minus1mod3[(triedge).orient] + 3]
+
+#define apex(triedge, pointptr)                                               \
+  pointptr = (point) (triedge).tri[(triedge).orient + 3]
+
+#define setorg(triedge, pointptr)                                             \
+  (triedge).tri[plus1mod3[(triedge).orient] + 3] = (triangle) pointptr
+
+#define setdest(triedge, pointptr)                                            \
+  (triedge).tri[minus1mod3[(triedge).orient] + 3] = (triangle) pointptr
+
+#define setapex(triedge, pointptr)                                            \
+  (triedge).tri[(triedge).orient + 3] = (triangle) pointptr
+
+#define setvertices2null(triedge)                                             \
+  (triedge).tri[3] = (triangle) NULL;                                         \
+  (triedge).tri[4] = (triangle) NULL;                                         \
+  (triedge).tri[5] = (triangle) NULL;
+
+/* Bond two triangles together.                                              */
+
+#define bond(triedge1, triedge2)                                              \
+  (triedge1).tri[(triedge1).orient] = encode(triedge2);                       \
+  (triedge2).tri[(triedge2).orient] = encode(triedge1)
+
+/* Dissolve a bond (from one side).  Note that the other triangle will still */
+/*   think it's connected to this triangle.  Usually, however, the other     */
+/*   triangle is being deleted entirely, or bonded to another triangle, so   */
+/*   it doesn't matter.                                                      */
+
+#define dissolve(triedge)                                                     \
+  (triedge).tri[(triedge).orient] = (triangle) dummytri
+
+/* Copy a triangle/edge handle.                                              */
+
+#define triedgecopy(triedge1, triedge2)                                       \
+  (triedge2).tri = (triedge1).tri;                                            \
+  (triedge2).orient = (triedge1).orient
+
+/* Test for equality of triangle/edge handles.                               */
+
+#define triedgeequal(triedge1, triedge2)                                      \
+  (((triedge1).tri == (triedge2).tri) &&                                      \
+   ((triedge1).orient == (triedge2).orient))
+
+/* Primitives to infect or cure a triangle with the virus.  These rely on    */
+/*   the assumption that all shell edges are aligned to four-byte boundaries.*/
+
+#define infect(triedge)                                                       \
+  (triedge).tri[6] = (triangle)                                               \
+                     ((unsigned long) (triedge).tri[6] | (unsigned long) 2l)
+
+#define uninfect(triedge)                                                     \
+  (triedge).tri[6] = (triangle)                                               \
+                     ((unsigned long) (triedge).tri[6] & ~ (unsigned long) 2l)
+
+/* Test a triangle for viral infection.                                      */
+
+#define infected(triedge)                                                     \
+  (((unsigned long) (triedge).tri[6] & (unsigned long) 2l) != 0)
+
+/* Check or set a triangle's attributes.                                     */
+
+#define elemattribute(triedge, attnum)                                        \
+  ((REAL *) (triedge).tri)[elemattribindex + (attnum)]
+
+#define setelemattribute(triedge, attnum, value)                              \
+  ((REAL *) (triedge).tri)[elemattribindex + (attnum)] = (REAL)value
+
+/* Check or set a triangle's maximum area bound.                             */
+
+#define areabound(triedge)  ((REAL *) (triedge).tri)[areaboundindex]
+
+#define setareabound(triedge, value)                                          \
+  ((REAL *) (triedge).tri)[areaboundindex] = (REAL)value
+
+/********* Primitives for shell edges                                *********/
+/*                                                                           */
+/*                                                                           */
+
+/* sdecode() converts a pointer to an oriented shell edge.  The orientation  */
+/*   is extracted from the least significant bit of the pointer.  The two    */
+/*   least significant bits (one for orientation, one for viral infection)   */
+/*   are masked out to produce the real pointer.                             */
+
+#define sdecode(sptr, edge)                                                   \
+  (edge).shorient = (int) ((unsigned long) (sptr) & (unsigned long) 1l);      \
+  (edge).sh = (shelle *)                                                      \
+              ((unsigned long) (sptr) & ~ (unsigned long) 3l)
+
+/* sencode() compresses an oriented shell edge into a single pointer.  It    */
+/*   relies on the assumption that all shell edges are aligned to two-byte   */
+/*   boundaries, so the least significant bit of (edge).sh is zero.          */
+
+#define sencode(edge)                                                         \
+  (shelle) ((unsigned long) (edge).sh | (unsigned long) (edge).shorient)
+
+/* ssym() toggles the orientation of a shell edge.                           */
+
+#define ssym(edge1, edge2)                                                    \
+  (edge2).sh = (edge1).sh;                                                    \
+  (edge2).shorient = 1 - (edge1).shorient
+
+#define ssymself(edge)                                                        \
+  (edge).shorient = 1 - (edge).shorient
+
+/* spivot() finds the other shell edge (from the same segment) that shares   */
+/*   the same origin.                                                        */
+
+#define spivot(edge1, edge2)                                                  \
+  sptr = (edge1).sh[(edge1).shorient];                                        \
+  sdecode(sptr, edge2)
+
+#define spivotself(edge)                                                      \
+  sptr = (edge).sh[(edge).shorient];                                          \
+  sdecode(sptr, edge)
+
+/* snext() finds the next shell edge (from the same segment) in sequence;    */
+/*   one whose origin is the input shell edge's destination.                 */
+
+#define snext(edge1, edge2)                                                   \
+  sptr = (edge1).sh[1 - (edge1).shorient];                                    \
+  sdecode(sptr, edge2)
+
+#define snextself(edge)                                                       \
+  sptr = (edge).sh[1 - (edge).shorient];                                      \
+  sdecode(sptr, edge)
+
+/* These primitives determine or set the origin or destination of a shell    */
+/*   edge.                                                                   */
+
+#define sorg(edge, pointptr)                                                  \
+  pointptr = (point) (edge).sh[2 + (edge).shorient]
+
+#define sdest(edge, pointptr)                                                 \
+  pointptr = (point) (edge).sh[3 - (edge).shorient]
+
+#define setsorg(edge, pointptr)                                               \
+  (edge).sh[2 + (edge).shorient] = (shelle) pointptr
+
+#define setsdest(edge, pointptr)                                              \
+  (edge).sh[3 - (edge).shorient] = (shelle) pointptr
+
+/* These primitives read or set a shell marker.  Shell markers are used to   */
+/*   hold user boundary information.                                         */
+
+#define mark(edge)  (* (int *) ((edge).sh + 6))
+
+#define setmark(edge, value)                                                  \
+  * (int *) ((edge).sh + 6) = value
+
+/* Bond two shell edges together.                                            */
+
+#define sbond(edge1, edge2)                                                   \
+  (edge1).sh[(edge1).shorient] = sencode(edge2);                              \
+  (edge2).sh[(edge2).shorient] = sencode(edge1)
+
+/* Dissolve a shell edge bond (from one side).  Note that the other shell    */
+/*   edge will still think it's connected to this shell edge.                */
+
+#define sdissolve(edge)                                                       \
+  (edge).sh[(edge).shorient] = (shelle) dummysh
+
+/* Copy a shell edge.                                                        */
+
+#define shellecopy(edge1, edge2)                                              \
+  (edge2).sh = (edge1).sh;                                                    \
+  (edge2).shorient = (edge1).shorient
+
+/* Test for equality of shell edges.                                         */
+
+#define shelleequal(edge1, edge2)                                             \
+  (((edge1).sh == (edge2).sh) &&                                              \
+   ((edge1).shorient == (edge2).shorient))
+
+/********* Primitives for interacting triangles and shell edges      *********/
+/*                                                                           */
+/*                                                                           */
+
+/* tspivot() finds a shell edge abutting a triangle.                         */
+
+#define tspivot(triedge, edge)                                                \
+  sptr = (shelle) (triedge).tri[6 + (triedge).orient];                        \
+  sdecode(sptr, edge)
+
+/* stpivot() finds a triangle abutting a shell edge.  It requires that the   */
+/*   variable `ptr' of type `triangle' be defined.                           */
+
+#define stpivot(edge, triedge)                                                \
+  ptr = (triangle) (edge).sh[4 + (edge).shorient];                            \
+  decode(ptr, triedge)
+
+/* Bond a triangle to a shell edge.                                          */
+
+#define tsbond(triedge, edge)                                                 \
+  (triedge).tri[6 + (triedge).orient] = (triangle) sencode(edge);             \
+  (edge).sh[4 + (edge).shorient] = (shelle) encode(triedge)
+
+/* Dissolve a bond (from the triangle side).                                 */
+
+#define tsdissolve(triedge)                                                   \
+  (triedge).tri[6 + (triedge).orient] = (triangle) dummysh
+
+/* Dissolve a bond (from the shell edge side).                               */
+
+#define stdissolve(edge)                                                      \
+  (edge).sh[4 + (edge).shorient] = (shelle) dummytri
+
+/********* Primitives for points                                     *********/
+/*                                                                           */
+/*                                                                           */
+
+#define pointmark(pt)  ((int *) (pt))[pointmarkindex]
+
+#define setpointmark(pt, value)                                               \
+  ((int *) (pt))[pointmarkindex] = value
+
+#define point2tri(pt)  ((triangle *) (pt))[point2triindex]
+
+#define setpoint2tri(pt, value)                                               \
+  ((triangle *) (pt))[point2triindex] = value
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh manipulation primitives end here                     *********/
+
+/********* User interaction routines begin here                      *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  syntax()   Print list of command line switches.                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void syntax()
+{
+#ifdef CDT_ONLY
+#ifdef REDUCED
+  printf("triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n");
+#else /* not REDUCED */
+  printf("triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n");
+#endif /* not REDUCED */
+#else /* not CDT_ONLY */
+#ifdef REDUCED
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n");
+#else /* not REDUCED */
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n");
+#endif /* not REDUCED */
+#endif /* not CDT_ONLY */
+
+  printf("    -p  Triangulates a Planar Straight Line Graph (.poly file).\n");
+#ifndef CDT_ONLY
+  printf("    -r  Refines a previously generated mesh.\n");
+  printf(
+    "    -q  Quality mesh generation.  A minimum angle may be specified.\n");
+  printf("    -a  Applies a maximum triangle area constraint.\n");
+#endif /* not CDT_ONLY */
+  printf(
+    "    -A  Applies attributes to identify elements in certain regions.\n");
+  printf("    -c  Encloses the convex hull with segments.\n");
+  printf("    -e  Generates an edge list.\n");
+  printf("    -v  Generates a Voronoi diagram.\n");
+  printf("    -n  Generates a list of triangle neighbors.\n");
+  printf("    -g  Generates an .off file for Geomview.\n");
+  printf("    -B  Suppresses output of boundary information.\n");
+  printf("    -P  Suppresses output of .poly file.\n");
+  printf("    -N  Suppresses output of .node file.\n");
+  printf("    -E  Suppresses output of .ele file.\n");
+  printf("    -I  Suppresses mesh iteration numbers.\n");
+  printf("    -O  Ignores holes in .poly file.\n");
+  printf("    -X  Suppresses use of exact arithmetic.\n");
+  printf("    -z  Numbers all items starting from zero (rather than one).\n");
+  printf("    -o2 Generates second-order subparametric elements.\n");
+#ifndef CDT_ONLY
+  printf("    -Y  Suppresses boundary segment splitting.\n");
+  printf("    -S  Specifies maximum number of added Steiner points.\n");
+#endif /* not CDT_ONLY */
+#ifndef REDUCED
+  printf("    -i  Uses incremental method, rather than divide-and-conquer.\n");
+  printf("    -F  Uses Fortune's sweepline algorithm, rather than d-and-c.\n");
+#endif /* not REDUCED */
+  printf("    -l  Uses vertical cuts only, rather than alternating cuts.\n");
+#ifndef REDUCED
+#ifndef CDT_ONLY
+  printf(
+    "    -s  Force segments into mesh by splitting (instead of using CDT).\n");
+#endif /* not CDT_ONLY */
+  printf("    -C  Check consistency of final mesh.\n");
+#endif /* not REDUCED */
+  printf("    -Q  Quiet:  No terminal output except errors.\n");
+  printf("    -V  Verbose:  Detailed information on what I'm doing.\n");
+  printf("    -h  Help:  Detailed instructions for Triangle.\n");
+  exit(0);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  info()   Print out complete instructions.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void info()
+{
+  printf("Triangle\n");
+  printf(
+"A Two-Dimensional Quality Mesh Generator and Delaunay Triangulator.\n");
+  printf("Version 1.3\n\n");
+  printf(
+"Copyright 1996 Jonathan Richard Shewchuk  (bugs/comments to jrs@cs.cmu.edu)\n"
+);
+  printf("School of Computer Science / Carnegie Mellon University\n");
+  printf("5000 Forbes Avenue / Pittsburgh, Pennsylvania  15213-3891\n");
+  printf(
+"Created as part of the Archimedes project (tools for parallel FEM).\n");
+  printf(
+"Supported in part by NSF Grant CMS-9318163 and an NSERC 1967 Scholarship.\n");
+  printf("There is no warranty whatsoever.  Use at your own risk.\n");
+#ifdef SINGLE
+  printf("This executable is compiled for single precision arithmetic.\n\n\n");
+#else /* not SINGLE */
+  printf("This executable is compiled for double precision arithmetic.\n\n\n");
+#endif /* not SINGLE */
+  printf(
+"Triangle generates exact Delaunay triangulations, constrained Delaunay\n");
+  printf(
+"triangulations, and quality conforming Delaunay triangulations.  The latter\n"
+);
+  printf(
+"can be generated with no small angles, and are thus suitable for finite\n");
+  printf(
+"element analysis.  If no command line switches are specified, your .node\n");
+  printf(
+"input file will be read, and the Delaunay triangulation will be returned in\n"
+);
+  printf(".node and .ele output files.  The command syntax is:\n\n");
+#ifdef CDT_ONLY
+#ifdef REDUCED
+  printf("triangle [-pAcevngBPNEIOXzo_lQVh] input_file\n\n");
+#else /* not REDUCED */
+  printf("triangle [-pAcevngBPNEIOXzo_iFlCQVh] input_file\n\n");
+#endif /* not REDUCED */
+#else /* not CDT_ONLY */
+#ifdef REDUCED
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__lQVh] input_file\n\n");
+#else /* not REDUCED */
+  printf("triangle [-prq__a__AcevngBPNEIOXzo_YS__iFlsCQVh] input_file\n\n");
+#endif /* not REDUCED */
+#endif /* not CDT_ONLY */
+  printf(
+"Underscores indicate that numbers may optionally follow certain switches;\n");
+  printf(
+"do not leave any space between a switch and its numeric parameter.\n");
+  printf(
+"input_file must be a file with extension .node, or extension .poly if the\n");
+  printf(
+"-p switch is used.  If -r is used, you must supply .node and .ele files,\n");
+  printf(
+"and possibly a .poly file and .area file as well.  The formats of these\n");
+  printf("files are described below.\n\n");
+  printf("Command Line Switches:\n\n");
+  printf(
+"    -p  Reads a Planar Straight Line Graph (.poly file), which can specify\n"
+);
+  printf(
+"        points, segments, holes, and regional attributes and area\n");
+  printf(
+"        constraints.  Will generate a constrained Delaunay triangulation\n");
+  printf(
+"        fitting the input; or, if -s, -q, or -a is used, a conforming\n");
+  printf(
+"        Delaunay triangulation.  If -p is not used, Triangle reads a .node\n"
+);
+  printf("        file by default.\n");
+  printf(
+"    -r  Refines a previously generated mesh.  The mesh is read from a .node\n"
+);
+  printf(
+"        file and an .ele file.  If -p is also used, a .poly file is read\n");
+  printf(
+"        and used to constrain edges in the mesh.  Further details on\n");
+  printf("        refinement are given below.\n");
+  printf(
+"    -q  Quality mesh generation by Jim Ruppert's Delaunay refinement\n");
+  printf(
+"        algorithm.  Adds points to the mesh to ensure that no angles\n");
+  printf(
+"        smaller than 20 degrees occur.  An alternative minimum angle may be\n"
+);
+  printf(
+"        specified after the `q'.  If the minimum angle is 20.7 degrees or\n");
+  printf(
+"        smaller, the triangulation algorithm is theoretically guaranteed to\n"
+);
+  printf(
+"        terminate (assuming infinite precision arithmetic - Triangle may\n");
+  printf(
+"        fail to terminate if you run out of precision).  In practice, the\n");
+  printf(
+"        algorithm often succeeds for minimum angles up to 33.8 degrees.\n");
+  printf(
+"        For highly refined meshes, however, it may be necessary to reduce\n");
+  printf(
+"        the minimum angle to well below 20 to avoid problems associated\n");
+  printf(
+"        with insufficient floating-point precision.  The specified angle\n");
+  printf("        may include a decimal point.\n");
+  printf(
+"    -a  Imposes a maximum triangle area.  If a number follows the `a', no\n");
+  printf(
+"        triangle will be generated whose area is larger than that number.\n");
+  printf(
+"        If no number is specified, an .area file (if -r is used) or .poly\n");
+  printf(
+"        file (if -r is not used) specifies a number of maximum area\n");
+  printf(
+"        constraints.  An .area file contains a separate area constraint for\n"
+);
+  printf(
+"        each triangle, and is useful for refining a finite element mesh\n");
+  printf(
+"        based on a posteriori error estimates.  A .poly file can optionally\n"
+);
+  printf(
+"        contain an area constraint for each segment-bounded region, thereby\n"
+);
+  printf(
+"        enforcing triangle densities in a first triangulation.  You can\n");
+  printf(
+"        impose both a fixed area constraint and a varying area constraint\n");
+  printf(
+"        by invoking the -a switch twice, once with and once without a\n");
+  printf(
+"        number following.  Each area specified may include a decimal point.\n"
+);
+  printf(
+"    -A  Assigns an additional attribute to each triangle that identifies\n");
+  printf(
+"        what segment-bounded region each triangle belongs to.  Attributes\n");
+  printf(
+"        are assigned to regions by the .poly file.  If a region is not\n");
+  printf(
+"        explicitly marked by the .poly file, triangles in that region are\n");
+  printf(
+"        assigned an attribute of zero.  The -A switch has an effect only\n");
+  printf("        when the -p switch is used and the -r switch is not.\n");
+  printf(
+"    -c  Creates segments on the convex hull of the triangulation.  If you\n");
+  printf(
+"        are triangulating a point set, this switch causes a .poly file to\n");
+  printf(
+"        be written, containing all edges in the convex hull.  (By default,\n"
+);
+  printf(
+"        a .poly file is written only if a .poly file is read.)  If you are\n"
+);
+  printf(
+"        triangulating a PSLG, this switch specifies that the interior of\n");
+  printf(
+"        the convex hull of the PSLG should be triangulated.  If you do not\n"
+);
+  printf(
+"        use this switch when triangulating a PSLG, it is assumed that you\n");
+  printf(
+"        have identified the region to be triangulated by surrounding it\n");
+  printf(
+"        with segments of the input PSLG.  Beware:  if you are not careful,\n"
+);
+  printf(
+"        this switch can cause the introduction of an extremely thin angle\n");
+  printf(
+"        between a PSLG segment and a convex hull segment, which can cause\n");
+  printf(
+"        overrefinement or failure if Triangle runs out of precision.  If\n");
+  printf(
+"        you are refining a mesh, the -c switch works differently; it\n");
+  printf(
+"        generates the set of boundary edges of the mesh, rather than the\n");
+  printf("        convex hull.\n");
+  printf(
+"    -e  Outputs (to an .edge file) a list of edges of the triangulation.\n");
+  printf(
+"    -v  Outputs the Voronoi diagram associated with the triangulation.\n");
+  printf("        Does not attempt to detect degeneracies.\n");
+  printf(
+"    -n  Outputs (to a .neigh file) a list of triangles neighboring each\n");
+  printf("        triangle.\n");
+  printf(
+"    -g  Outputs the mesh to an Object File Format (.off) file, suitable for\n"
+);
+  printf("        viewing with the Geometry Center's Geomview package.\n");
+  printf(
+"    -B  No boundary markers in the output .node, .poly, and .edge output\n");
+  printf(
+"        files.  See the detailed discussion of boundary markers below.\n");
+  printf(
+"    -P  No output .poly file.  Saves disk space, but you lose the ability\n");
+  printf(
+"        to impose segment constraints on later refinements of the mesh.\n");
+  printf("    -N  No output .node file.\n");
+  printf("    -E  No output .ele file.\n");
+  printf(
+"    -I  No iteration numbers.  Suppresses the output of .node and .poly\n");
+  printf(
+"        files, so your input files won't be overwritten.  (If your input is\n"
+);
+  printf(
+"        a .poly file only, a .node file will be written.)  Cannot be used\n");
+  printf(
+"        with the -r switch, because that would overwrite your input .ele\n");
+  printf(
+"        file.  Shouldn't be used with the -s, -q, or -a switch if you are\n");
+  printf(
+"        using a .node file for input, because no .node file will be\n");
+  printf("        written, so there will be no record of any added points.\n");
+  printf("    -O  No holes.  Ignores the holes in the .poly file.\n");
+  printf(
+"    -X  No exact arithmetic.  Normally, Triangle uses exact floating-point\n"
+);
+  printf(
+"        arithmetic for certain tests if it thinks the inexact tests are not\n"
+);
+  printf(
+"        accurate enough.  Exact arithmetic ensures the robustness of the\n");
+  printf(
+"        triangulation algorithms, despite floating-point roundoff error.\n");
+  printf(
+"        Disabling exact arithmetic with the -X switch will cause a small\n");
+  printf(
+"        improvement in speed and create the possibility (albeit small) that\n"
+);
+  printf(
+"        Triangle will fail to produce a valid mesh.  Not recommended.\n");
+  printf(
+"    -z  Numbers all items starting from zero (rather than one).  Note that\n"
+);
+  printf(
+"        this switch is normally overrided by the value used to number the\n");
+  printf(
+"        first point of the input .node or .poly file.  However, this switch\n"
+);
+  printf("        is useful when calling Triangle from another program.\n");
+  printf(
+"    -o2 Generates second-order subparametric elements with six nodes each.\n"
+);
+  printf(
+"    -Y  No new points on the boundary.  This switch is useful when the mesh\n"
+);
+  printf(
+"        boundary must be preserved so that it conforms to some adjacent\n");
+  printf(
+"        mesh.  Be forewarned that you will probably sacrifice some of the\n");
+  printf(
+"        quality of the mesh; Triangle will try, but the resulting mesh may\n"
+);
+  printf(
+"        contain triangles of poor aspect ratio.  Works well if all the\n");
+  printf(
+"        boundary points are closely spaced.  Specify this switch twice\n");
+  printf(
+"        (`-YY') to prevent all segment splitting, including internal\n");
+  printf("        boundaries.\n");
+  printf(
+"    -S  Specifies the maximum number of Steiner points (points that are not\n"
+);
+  printf(
+"        in the input, but are added to meet the constraints of minimum\n");
+  printf(
+"        angle and maximum area).  The default is to allow an unlimited\n");
+  printf(
+"        number.  If you specify this switch with no number after it,\n");
+  printf(
+"        the limit is set to zero.  Triangle always adds points at segment\n");
+  printf(
+"        intersections, even if it needs to use more points than the limit\n");
+  printf(
+"        you set.  When Triangle inserts segments by splitting (-s), it\n");
+  printf(
+"        always adds enough points to ensure that all the segments appear in\n"
+);
+  printf(
+"        the triangulation, again ignoring the limit.  Be forewarned that\n");
+  printf(
+"        the -S switch may result in a conforming triangulation that is not\n"
+);
+  printf(
+"        truly Delaunay, because Triangle may be forced to stop adding\n");
+  printf(
+"        points when the mesh is in a state where a segment is non-Delaunay\n"
+);
+  printf(
+"        and needs to be split.  If so, Triangle will print a warning.\n");
+  printf(
+"    -i  Uses an incremental rather than divide-and-conquer algorithm to\n");
+  printf(
+"        form a Delaunay triangulation.  Try it if the divide-and-conquer\n");
+  printf("        algorithm fails.\n");
+  printf(
+"    -F  Uses Steven Fortune's sweepline algorithm to form a Delaunay\n");
+  printf(
+"        triangulation.  Warning:  does not use exact arithmetic for all\n");
+  printf("        calculations.  An exact result is not guaranteed.\n");
+  printf(
+"    -l  Uses only vertical cuts in the divide-and-conquer algorithm.  By\n");
+  printf(
+"        default, Triangle uses alternating vertical and horizontal cuts,\n");
+  printf(
+"        which usually improve the speed except with point sets that are\n");
+  printf(
+"        small or short and wide.  This switch is primarily of theoretical\n");
+  printf("        interest.\n");
+  printf(
+"    -s  Specifies that segments should be forced into the triangulation by\n"
+);
+  printf(
+"        recursively splitting them at their midpoints, rather than by\n");
+  printf(
+"        generating a constrained Delaunay triangulation.  Segment splitting\n"
+);
+  printf(
+"        is true to Ruppert's original algorithm, but can create needlessly\n"
+);
+  printf("        small triangles near external small features.\n");
+  printf(
+"    -C  Check the consistency of the final mesh.  Uses exact arithmetic for\n"
+);
+  printf(
+"        checking, even if the -X switch is used.  Useful if you suspect\n");
+  printf("        Triangle is buggy.\n");
+  printf(
+"    -Q  Quiet: Suppresses all explanation of what Triangle is doing, unless\n"
+);
+  printf("        an error occurs.\n");
+  printf(
+"    -V  Verbose: Gives detailed information about what Triangle is doing.\n");
+  printf(
+"        Add more `V's for increasing amount of detail.  `-V' gives\n");
+  printf(
+"        information on algorithmic progress and more detailed statistics.\n");
+  printf(
+"        `-VV' gives point-by-point details, and will print so much that\n");
+  printf(
+"        Triangle will run much more slowly.  `-VVV' gives information only\n"
+);
+  printf("        a debugger could love.\n");
+  printf("    -h  Help:  Displays these instructions.\n");
+  printf("\n");
+  printf("Definitions:\n");
+  printf("\n");
+  printf(
+"  A Delaunay triangulation of a point set is a triangulation whose vertices\n"
+);
+  printf(
+"  are the point set, having the property that no point in the point set\n");
+  printf(
+"  falls in the interior of the circumcircle (circle that passes through all\n"
+);
+  printf("  three vertices) of any triangle in the triangulation.\n\n");
+  printf(
+"  A Voronoi diagram of a point set is a subdivision of the plane into\n");
+  printf(
+"  polygonal regions (some of which may be infinite), where each region is\n");
+  printf(
+"  the set of points in the plane that are closer to some input point than\n");
+  printf(
+"  to any other input point.  (The Voronoi diagram is the geometric dual of\n"
+);
+  printf("  the Delaunay triangulation.)\n\n");
+  printf(
+"  A Planar Straight Line Graph (PSLG) is a collection of points and\n");
+  printf(
+"  segments.  Segments are simply edges, whose endpoints are points in the\n");
+  printf(
+"  PSLG.  The file format for PSLGs (.poly files) is described below.\n");
+  printf("\n");
+  printf(
+"  A constrained Delaunay triangulation of a PSLG is similar to a Delaunay\n");
+  printf(
+"  triangulation, but each PSLG segment is present as a single edge in the\n");
+  printf(
+"  triangulation.  (A constrained Delaunay triangulation is not truly a\n");
+  printf("  Delaunay triangulation.)\n\n");
+  printf(
+"  A conforming Delaunay triangulation of a PSLG is a true Delaunay\n");
+  printf(
+"  triangulation in which each PSLG segment may have been subdivided into\n");
+  printf(
+"  several edges by the insertion of additional points.  These inserted\n");
+  printf(
+"  points are necessary to allow the segments to exist in the mesh while\n");
+  printf("  maintaining the Delaunay property.\n\n");
+  printf("File Formats:\n\n");
+  printf(
+"  All files may contain comments prefixed by the character '#'.  Points,\n");
+  printf(
+"  triangles, edges, holes, and maximum area constraints must be numbered\n");
+  printf(
+"  consecutively, starting from either 1 or 0.  Whichever you choose, all\n");
+  printf(
+"  input files must be consistent; if the nodes are numbered from 1, so must\n"
+);
+  printf(
+"  be all other objects.  Triangle automatically detects your choice while\n");
+  printf(
+"  reading the .node (or .poly) file.  (When calling Triangle from another\n");
+  printf(
+"  program, use the -z switch if you wish to number objects from zero.)\n");
+  printf("  Examples of these file formats are given below.\n\n");
+  printf("  .node files:\n");
+  printf(
+"    First line:  <# of points> <dimension (must be 2)> <# of attributes>\n");
+  printf(
+"                                           <# of boundary markers (0 or 1)>\n"
+);
+  printf(
+"    Remaining lines:  <point #> <x> <y> [attributes] [boundary marker]\n");
+  printf("\n");
+  printf(
+"    The attributes, which are typically floating-point values of physical\n");
+  printf(
+"    quantities (such as mass or conductivity) associated with the nodes of\n"
+);
+  printf(
+"    a finite element mesh, are copied unchanged to the output mesh.  If -s,\n"
+);
+  printf(
+"    -q, or -a is selected, each new Steiner point added to the mesh will\n");
+  printf("    have attributes assigned to it by linear interpolation.\n\n");
+  printf(
+"    If the fourth entry of the first line is `1', the last column of the\n");
+  printf(
+"    remainder of the file is assumed to contain boundary markers.  Boundary\n"
+);
+  printf(
+"    markers are used to identify boundary points and points resting on PSLG\n"
+);
+  printf(
+"    segments; a complete description appears in a section below.  The .node\n"
+);
+  printf(
+"    file produced by Triangle will contain boundary markers in the last\n");
+  printf("    column unless they are suppressed by the -B switch.\n\n");
+  printf("  .ele files:\n");
+  printf(
+"    First line:  <# of triangles> <points per triangle> <# of attributes>\n");
+  printf(
+"    Remaining lines:  <triangle #> <point> <point> <point> ... [attributes]\n"
+);
+  printf("\n");
+  printf(
+"    Points are indices into the corresponding .node file.  The first three\n"
+);
+  printf(
+"    points are the corners, and are listed in counterclockwise order around\n"
+);
+  printf(
+"    each triangle.  (The remaining points, if any, depend on the type of\n");
+  printf(
+"    finite element used.)  The attributes are just like those of .node\n");
+  printf(
+"    files.  Because there is no simple mapping from input to output\n");
+  printf(
+"    triangles, an attempt is made to interpolate attributes, which may\n");
+  printf(
+"    result in a good deal of diffusion of attributes among nearby triangles\n"
+);
+  printf(
+"    as the triangulation is refined.  Diffusion does not occur across\n");
+  printf(
+"    segments, so attributes used to identify segment-bounded regions remain\n"
+);
+  printf(
+"    intact.  In output .ele files, all triangles have three points each\n");
+  printf(
+"    unless the -o2 switch is used, in which case they have six, and the\n");
+  printf(
+"    fourth, fifth, and sixth points lie on the midpoints of the edges\n");
+  printf("    opposite the first, second, and third corners.\n\n");
+  printf("  .poly files:\n");
+  printf(
+"    First line:  <# of points> <dimension (must be 2)> <# of attributes>\n");
+  printf(
+"                                           <# of boundary markers (0 or 1)>\n"
+);
+  printf(
+"    Following lines:  <point #> <x> <y> [attributes] [boundary marker]\n");
+  printf("    One line:  <# of segments> <# of boundary markers (0 or 1)>\n");
+  printf(
+"    Following lines:  <segment #> <endpoint> <endpoint> [boundary marker]\n");
+  printf("    One line:  <# of holes>\n");
+  printf("    Following lines:  <hole #> <x> <y>\n");
+  printf(
+"    Optional line:  <# of regional attributes and/or area constraints>\n");
+  printf(
+"    Optional following lines:  <constraint #> <x> <y> <attrib> <max area>\n");
+  printf("\n");
+  printf(
+"    A .poly file represents a PSLG, as well as some additional information.\n"
+);
+  printf(
+"    The first section lists all the points, and is identical to the format\n"
+);
+  printf(
+"    of .node files.  <# of points> may be set to zero to indicate that the\n"
+);
+  printf(
+"    points are listed in a separate .node file; .poly files produced by\n");
+  printf(
+"    Triangle always have this format.  This has the advantage that a point\n"
+);
+  printf(
+"    set may easily be triangulated with or without segments.  (The same\n");
+  printf(
+"    effect can be achieved, albeit using more disk space, by making a copy\n"
+);
+  printf(
+"    of the .poly file with the extension .node; all sections of the file\n");
+  printf("    but the first are ignored.)\n\n");
+  printf(
+"    The second section lists the segments.  Segments are edges whose\n");
+  printf(
+"    presence in the triangulation is enforced.  Each segment is specified\n");
+  printf(
+"    by listing the indices of its two endpoints.  This means that you must\n"
+);
+  printf(
+"    include its endpoints in the point list.  If -s, -q, and -a are not\n");
+  printf(
+"    selected, Triangle will produce a constrained Delaunay triangulation,\n");
+  printf(
+"    in which each segment appears as a single edge in the triangulation.\n");
+  printf(
+"    If -q or -a is selected, Triangle will produce a conforming Delaunay\n");
+  printf(
+"    triangulation, in which segments may be subdivided into smaller edges.\n"
+);
+  printf("    Each segment, like each point, may have a boundary marker.\n\n");
+  printf(
+"    The third section lists holes (and concavities, if -c is selected) in\n");
+  printf(
+"    the triangulation.  Holes are specified by identifying a point inside\n");
+  printf(
+"    each hole.  After the triangulation is formed, Triangle creates holes\n");
+  printf(
+"    by eating triangles, spreading out from each hole point until its\n");
+  printf(
+"    progress is blocked by PSLG segments; you must be careful to enclose\n");
+  printf(
+"    each hole in segments, or your whole triangulation may be eaten away.\n");
+  printf(
+"    If the two triangles abutting a segment are eaten, the segment itself\n");
+  printf(
+"    is also eaten.  Do not place a hole directly on a segment; if you do,\n");
+  printf("    Triangle will choose one side of the segment arbitrarily.\n\n");
+  printf(
+"    The optional fourth section lists regional attributes (to be assigned\n");
+  printf(
+"    to all triangles in a region) and regional constraints on the maximum\n");
+  printf(
+"    triangle area.  Triangle will read this section only if the -A switch\n");
+  printf(
+"    is used or the -a switch is used without a number following it, and the\n"
+);
+  printf(
+"    -r switch is not used.  Regional attributes and area constraints are\n");
+  printf(
+"    propagated in the same manner as holes; you specify a point for each\n");
+  printf(
+"    attribute and/or constraint, and the attribute and/or constraint will\n");
+  printf(
+"    affect the whole region (bounded by segments) containing the point.  If\n"
+);
+  printf(
+"    two values are written on a line after the x and y coordinate, the\n");
+  printf(
+"    former is assumed to be a regional attribute (but will only be applied\n"
+);
+  printf(
+"    if the -A switch is selected), and the latter is assumed to be a\n");
+  printf(
+"    regional area constraint (but will only be applied if the -a switch is\n"
+);
+  printf(
+"    selected).  You may also specify just one value after the coordinates,\n"
+);
+  printf(
+"    which can serve as both an attribute and an area constraint, depending\n"
+);
+  printf(
+"    on the choice of switches.  If you are using the -A and -a switches\n");
+  printf(
+"    simultaneously and wish to assign an attribute to some region without\n");
+  printf("    imposing an area constraint, use a negative maximum area.\n\n");
+  printf(
+"    When a triangulation is created from a .poly file, you must either\n");
+  printf(
+"    enclose the entire region to be triangulated in PSLG segments, or\n");
+  printf(
+"    use the -c switch, which encloses the convex hull of the input point\n");
+  printf(
+"    set.  If you do not use the -c switch, Triangle will eat all triangles\n"
+);
+  printf(
+"    on the outer boundary that are not protected by segments; if you are\n");
+  printf(
+"    not careful, your whole triangulation may be eaten away.  If you do\n");
+  printf(
+"    use the -c switch, you can still produce concavities by appropriate\n");
+  printf("    placement of holes just inside the convex hull.\n\n");
+  printf(
+"    An ideal PSLG has no intersecting segments, nor any points that lie\n");
+  printf(
+"    upon segments (except, of course, the endpoints of each segment.)  You\n"
+);
+  printf(
+"    aren't required to make your .poly files ideal, but you should be aware\n"
+);
+  printf(
+"    of what can go wrong.  Segment intersections are relatively safe -\n");
+  printf(
+"    Triangle will calculate the intersection points for you and add them to\n"
+);
+  printf(
+"    the triangulation - as long as your machine's floating-point precision\n"
+);
+  printf(
+"    doesn't become a problem.  You are tempting the fates if you have three\n"
+);
+  printf(
+"    segments that cross at the same location, and expect Triangle to figure\n"
+);
+  printf(
+"    out where the intersection point is.  Thanks to floating-point roundoff\n"
+);
+  printf(
+"    error, Triangle will probably decide that the three segments intersect\n"
+);
+  printf(
+"    at three different points, and you will find a minuscule triangle in\n");
+  printf(
+"    your output - unless Triangle tries to refine the tiny triangle, uses\n");
+  printf(
+"    up the last bit of machine precision, and fails to terminate at all.\n");
+  printf(
+"    You're better off putting the intersection point in the input files,\n");
+  printf(
+"    and manually breaking up each segment into two.  Similarly, if you\n");
+  printf(
+"    place a point at the middle of a segment, and hope that Triangle will\n");
+  printf(
+"    break up the segment at that point, you might get lucky.  On the other\n"
+);
+  printf(
+"    hand, Triangle might decide that the point doesn't lie precisely on the\n"
+);
+  printf(
+"    line, and you'll have a needle-sharp triangle in your output - or a lot\n"
+);
+  printf("    of tiny triangles if you're generating a quality mesh.\n\n");
+  printf(
+"    When Triangle reads a .poly file, it also writes a .poly file, which\n");
+  printf(
+"    includes all edges that are part of input segments.  If the -c switch\n");
+  printf(
+"    is used, the output .poly file will also include all of the edges on\n");
+  printf(
+"    the convex hull.  Hence, the output .poly file is useful for finding\n");
+  printf(
+"    edges associated with input segments and setting boundary conditions in\n"
+);
+  printf(
+"    finite element simulations.  More importantly, you will need it if you\n"
+);
+  printf(
+"    plan to refine the output mesh, and don't want segments to be missing\n");
+  printf("    in later triangulations.\n\n");
+  printf("  .area files:\n");
+  printf("    First line:  <# of triangles>\n");
+  printf("    Following lines:  <triangle #> <maximum area>\n\n");
+  printf(
+"    An .area file associates with each triangle a maximum area that is used\n"
+);
+  printf(
+"    for mesh refinement.  As with other file formats, every triangle must\n");
+  printf(
+"    be represented, and they must be numbered consecutively.  A triangle\n");
+  printf(
+"    may be left unconstrained by assigning it a negative maximum area.\n");
+  printf("\n");
+  printf("  .edge files:\n");
+  printf("    First line:  <# of edges> <# of boundary markers (0 or 1)>\n");
+  printf(
+"    Following lines:  <edge #> <endpoint> <endpoint> [boundary marker]\n");
+  printf("\n");
+  printf(
+"    Endpoints are indices into the corresponding .node file.  Triangle can\n"
+);
+  printf(
+"    produce .edge files (use the -e switch), but cannot read them.  The\n");
+  printf(
+"    optional column of boundary markers is suppressed by the -B switch.\n");
+  printf("\n");
+  printf(
+"    In Voronoi diagrams, one also finds a special kind of edge that is an\n");
+  printf(
+"    infinite ray with only one endpoint.  For these edges, a different\n");
+  printf("    format is used:\n\n");
+  printf("        <edge #> <endpoint> -1 <direction x> <direction y>\n\n");
+  printf(
+"    The `direction' is a floating-point vector that indicates the direction\n"
+);
+  printf("    of the infinite ray.\n\n");
+  printf("  .neigh files:\n");
+  printf(
+"    First line:  <# of triangles> <# of neighbors per triangle (always 3)>\n"
+);
+  printf(
+"    Following lines:  <triangle #> <neighbor> <neighbor> <neighbor>\n");
+  printf("\n");
+  printf(
+"    Neighbors are indices into the corresponding .ele file.  An index of -1\n"
+);
+  printf(
+"    indicates a mesh boundary, and therefore no neighbor.  Triangle can\n");
+  printf(
+"    produce .neigh files (use the -n switch), but cannot read them.\n");
+  printf("\n");
+  printf(
+"    The first neighbor of triangle i is opposite the first corner of\n");
+  printf("    triangle i, and so on.\n\n");
+  printf("Boundary Markers:\n\n");
+  printf(
+"  Boundary markers are tags used mainly to identify which output points and\n"
+);
+  printf(
+"  edges are associated with which PSLG segment, and to identify which\n");
+  printf(
+"  points and edges occur on a boundary of the triangulation.  A common use\n"
+);
+  printf(
+"  is to determine where boundary conditions should be applied to a finite\n");
+  printf(
+"  element mesh.  You can prevent boundary markers from being written into\n");
+  printf("  files produced by Triangle by using the -B switch.\n\n");
+  printf(
+"  The boundary marker associated with each segment in an output .poly file\n"
+);
+  printf("  or edge in an output .edge file is chosen as follows:\n");
+  printf(
+"    - If an output edge is part or all of a PSLG segment with a nonzero\n");
+  printf(
+"      boundary marker, then the edge is assigned the same marker.\n");
+  printf(
+"    - Otherwise, if the edge occurs on a boundary of the triangulation\n");
+  printf(
+"      (including boundaries of holes), then the edge is assigned the marker\n"
+);
+  printf("      one (1).\n");
+  printf("    - Otherwise, the edge is assigned the marker zero (0).\n");
+  printf(
+"  The boundary marker associated with each point in an output .node file is\n"
+);
+  printf("  chosen as follows:\n");
+  printf(
+"    - If a point is assigned a nonzero boundary marker in the input file,\n");
+  printf(
+"      then it is assigned the same marker in the output .node file.\n");
+  printf(
+"    - Otherwise, if the point lies on a PSLG segment (including the\n");
+  printf(
+"      segment's endpoints) with a nonzero boundary marker, then the point\n");
+  printf(
+"      is assigned the same marker.  If the point lies on several such\n");
+  printf("      segments, one of the markers is chosen arbitrarily.\n");
+  printf(
+"    - Otherwise, if the point occurs on a boundary of the triangulation,\n");
+  printf("      then the point is assigned the marker one (1).\n");
+  printf("    - Otherwise, the point is assigned the marker zero (0).\n");
+  printf("\n");
+  printf(
+"  If you want Triangle to determine for you which points and edges are on\n");
+  printf(
+"  the boundary, assign them the boundary marker zero (or use no markers at\n"
+);
+  printf(
+"  all) in your input files.  Alternatively, you can mark some of them and\n");
+  printf("  leave others marked zero, allowing Triangle to label them.\n\n");
+  printf("Triangulation Iteration Numbers:\n\n");
+  printf(
+"  Because Triangle can read and refine its own triangulations, input\n");
+  printf(
+"  and output files have iteration numbers.  For instance, Triangle might\n");
+  printf(
+"  read the files mesh.3.node, mesh.3.ele, and mesh.3.poly, refine the\n");
+  printf(
+"  triangulation, and output the files mesh.4.node, mesh.4.ele, and\n");
+  printf("  mesh.4.poly.  Files with no iteration number are treated as if\n");
+  printf(
+"  their iteration number is zero; hence, Triangle might read the file\n");
+  printf(
+"  points.node, triangulate it, and produce the files points.1.node and\n");
+  printf("  points.1.ele.\n\n");
+  printf(
+"  Iteration numbers allow you to create a sequence of successively finer\n");
+  printf(
+"  meshes suitable for multigrid methods.  They also allow you to produce a\n"
+);
+  printf(
+"  sequence of meshes using error estimate-driven mesh refinement.\n");
+  printf("\n");
+  printf(
+"  If you're not using refinement or quality meshing, and you don't like\n");
+  printf(
+"  iteration numbers, use the -I switch to disable them.  This switch will\n");
+  printf(
+"  also disable output of .node and .poly files to prevent your input files\n"
+);
+  printf(
+"  from being overwritten.  (If the input is a .poly file that contains its\n"
+);
+  printf("  own points, a .node file will be written.)\n\n");
+  printf("Examples of How to Use Triangle:\n\n");
+  printf(
+"  `triangle dots' will read points from dots.node, and write their Delaunay\n"
+);
+  printf(
+"  triangulation to dots.1.node and dots.1.ele.  (dots.1.node will be\n");
+  printf(
+"  identical to dots.node.)  `triangle -I dots' writes the triangulation to\n"
+);
+  printf(
+"  dots.ele instead.  (No additional .node file is needed, so none is\n");
+  printf("  written.)\n\n");
+  printf(
+"  `triangle -pe object.1' will read a PSLG from object.1.poly (and possibly\n"
+);
+  printf(
+"  object.1.node, if the points are omitted from object.1.poly) and write\n");
+  printf("  their constrained Delaunay triangulation to object.2.node and\n");
+  printf(
+"  object.2.ele.  The segments will be copied to object.2.poly, and all\n");
+  printf("  edges will be written to object.2.edge.\n\n");
+  printf(
+"  `triangle -pq31.5a.1 object' will read a PSLG from object.poly (and\n");
+  printf(
+"  possibly object.node), generate a mesh whose angles are all greater than\n"
+);
+  printf(
+"  31.5 degrees and whose triangles all have area smaller than 0.1, and\n");
+  printf(
+"  write the mesh to object.1.node and object.1.ele.  Each segment may have\n"
+);
+  printf(
+"  been broken up into multiple edges; the resulting constrained edges are\n");
+  printf("  written to object.1.poly.\n\n");
+  printf(
+"  Here is a sample file `box.poly' describing a square with a square hole:\n"
+);
+  printf("\n");
+  printf(
+"    # A box with eight points in 2D, no attributes, one boundary marker.\n");
+  printf("    8 2 0 1\n");
+  printf("    # Outer box has these vertices:\n");
+  printf("     1   0 0   0\n");
+  printf("     2   0 3   0\n");
+  printf("     3   3 0   0\n");
+  printf("     4   3 3   33     # A special marker for this point.\n");
+  printf("    # Inner square has these vertices:\n");
+  printf("     5   1 1   0\n");
+  printf("     6   1 2   0\n");
+  printf("     7   2 1   0\n");
+  printf("     8   2 2   0\n");
+  printf("    # Five segments with boundary markers.\n");
+  printf("    5 1\n");
+  printf("     1   1 2   5      # Left side of outer box.\n");
+  printf("     2   5 7   0      # Segments 2 through 5 enclose the hole.\n");
+  printf("     3   7 8   0\n");
+  printf("     4   8 6   10\n");
+  printf("     5   6 5   0\n");
+  printf("    # One hole in the middle of the inner square.\n");
+  printf("    1\n");
+  printf("     1   1.5 1.5\n\n");
+  printf(
+"  Note that some segments are missing from the outer square, so one must\n");
+  printf(
+"  use the `-c' switch.  After `triangle -pqc box.poly', here is the output\n"
+);
+  printf(
+"  file `box.1.node', with twelve points.  The last four points were added\n");
+  printf(
+"  to meet the angle constraint.  Points 1, 2, and 9 have markers from\n");
+  printf(
+"  segment 1.  Points 6 and 8 have markers from segment 4.  All the other\n");
+  printf(
+"  points but 4 have been marked to indicate that they lie on a boundary.\n");
+  printf("\n");
+  printf("    12  2  0  1\n");
+  printf("       1    0   0      5\n");
+  printf("       2    0   3      5\n");
+  printf("       3    3   0      1\n");
+  printf("       4    3   3     33\n");
+  printf("       5    1   1      1\n");
+  printf("       6    1   2     10\n");
+  printf("       7    2   1      1\n");
+  printf("       8    2   2     10\n");
+  printf("       9    0   1.5    5\n");
+  printf("      10    1.5   0    1\n");
+  printf("      11    3   1.5    1\n");
+  printf("      12    1.5   3    1\n");
+  printf("    # Generated by triangle -pqc box.poly\n\n");
+  printf("  Here is the output file `box.1.ele', with twelve triangles.\n\n");
+  printf("    12  3  0\n");
+  printf("       1     5   6   9\n");
+  printf("       2    10   3   7\n");
+  printf("       3     6   8  12\n");
+  printf("       4     9   1   5\n");
+  printf("       5     6   2   9\n");
+  printf("       6     7   3  11\n");
+  printf("       7    11   4   8\n");
+  printf("       8     7   5  10\n");
+  printf("       9    12   2   6\n");
+  printf("      10     8   7  11\n");
+  printf("      11     5   1  10\n");
+  printf("      12     8   4  12\n");
+  printf("    # Generated by triangle -pqc box.poly\n\n");
+  printf(
+"  Here is the output file `box.1.poly'.  Note that segments have been added\n"
+);
+  printf(
+"  to represent the convex hull, and some segments have been split by newly\n"
+);
+  printf(
+"  added points.  Note also that <# of points> is set to zero to indicate\n");
+  printf("  that the points should be read from the .node file.\n\n");
+  printf("    0  2  0  1\n");
+  printf("    12  1\n");
+  printf("       1     1   9     5\n");
+  printf("       2     5   7     1\n");
+  printf("       3     8   7     1\n");
+  printf("       4     6   8    10\n");
+  printf("       5     5   6     1\n");
+  printf("       6     3  10     1\n");
+  printf("       7     4  11     1\n");
+  printf("       8     2  12     1\n");
+  printf("       9     9   2     5\n");
+  printf("      10    10   1     1\n");
+  printf("      11    11   3     1\n");
+  printf("      12    12   4     1\n");
+  printf("    1\n");
+  printf("       1   1.5 1.5\n");
+  printf("    # Generated by triangle -pqc box.poly\n\n");
+  printf("Refinement and Area Constraints:\n\n");
+  printf(
+"  The -r switch causes a mesh (.node and .ele files) to be read and\n");
+  printf(
+"  refined.  If the -p switch is also used, a .poly file is read and used to\n"
+);
+  printf(
+"  specify edges that are constrained and cannot be eliminated (although\n");
+  printf(
+"  they can be divided into smaller edges) by the refinement process.\n");
+  printf("\n");
+  printf(
+"  When you refine a mesh, you generally want to impose tighter quality\n");
+  printf(
+"  constraints.  One way to accomplish this is to use -q with a larger\n");
+  printf(
+"  angle, or -a followed by a smaller area than you used to generate the\n");
+  printf(
+"  mesh you are refining.  Another way to do this is to create an .area\n");
+  printf(
+"  file, which specifies a maximum area for each triangle, and use the -a\n");
+  printf(
+"  switch (without a number following).  Each triangle's area constraint is\n"
+);
+  printf(
+"  applied to that triangle.  Area constraints tend to diffuse as the mesh\n");
+  printf(
+"  is refined, so if there are large variations in area constraint between\n");
+  printf("  adjacent triangles, you may not get the results you want.\n\n");
+  printf(
+"  If you are refining a mesh composed of linear (three-node) elements, the\n"
+);
+  printf(
+"  output mesh will contain all the nodes present in the input mesh, in the\n"
+);
+  printf(
+"  same order, with new nodes added at the end of the .node file.  However,\n"
+);
+  printf(
+"  there is no guarantee that each output element is contained in a single\n");
+  printf(
+"  input element.  Often, output elements will overlap two input elements,\n");
+  printf(
+"  and input edges are not present in the output mesh.  Hence, a sequence of\n"
+);
+  printf(
+"  refined meshes will form a hierarchy of nodes, but not a hierarchy of\n");
+  printf(
+"  elements.  If you a refining a mesh of higher-order elements, the\n");
+  printf(
+"  hierarchical property applies only to the nodes at the corners of an\n");
+  printf("  element; other nodes may not be present in the refined mesh.\n\n");
+  printf(
+"  It is important to understand that maximum area constraints in .poly\n");
+  printf(
+"  files are handled differently from those in .area files.  A maximum area\n"
+);
+  printf(
+"  in a .poly file applies to the whole (segment-bounded) region in which a\n"
+);
+  printf(
+"  point falls, whereas a maximum area in an .area file applies to only one\n"
+);
+  printf(
+"  triangle.  Area constraints in .poly files are used only when a mesh is\n");
+  printf(
+"  first generated, whereas area constraints in .area files are used only to\n"
+);
+  printf(
+"  refine an existing mesh, and are typically based on a posteriori error\n");
+  printf(
+"  estimates resulting from a finite element simulation on that mesh.\n");
+  printf("\n");
+  printf(
+"  `triangle -rq25 object.1' will read object.1.node and object.1.ele, then\n"
+);
+  printf(
+"  refine the triangulation to enforce a 25 degree minimum angle, and then\n");
+  printf(
+"  write the refined triangulation to object.2.node and object.2.ele.\n");
+  printf("\n");
+  printf(
+"  `triangle -rpaa6.2 z.3' will read z.3.node, z.3.ele, z.3.poly, and\n");
+  printf(
+"  z.3.area.  After reconstructing the mesh and its segments, Triangle will\n"
+);
+  printf(
+"  refine the mesh so that no triangle has area greater than 6.2, and\n");
+  printf(
+"  furthermore the triangles satisfy the maximum area constraints in\n");
+  printf(
+"  z.3.area.  The output is written to z.4.node, z.4.ele, and z.4.poly.\n");
+  printf("\n");
+  printf(
+"  The sequence `triangle -qa1 x', `triangle -rqa.3 x.1', `triangle -rqa.1\n");
+  printf(
+"  x.2' creates a sequence of successively finer meshes x.1, x.2, and x.3,\n");
+  printf("  suitable for multigrid.\n\n");
+  printf("Convex Hulls and Mesh Boundaries:\n\n");
+  printf(
+"  If the input is a point set (rather than a PSLG), Triangle produces its\n");
+  printf(
+"  convex hull as a by-product in the output .poly file if you use the -c\n");
+  printf(
+"  switch.  There are faster algorithms for finding a two-dimensional convex\n"
+);
+  printf(
+"  hull than triangulation, of course, but this one comes for free.  If the\n"
+);
+  printf(
+"  input is an unconstrained mesh (you are using the -r switch but not the\n");
+  printf(
+"  -p switch), Triangle produces a list of its boundary edges (including\n");
+  printf("  hole boundaries) as a by-product if you use the -c switch.\n\n");
+  printf("Voronoi Diagrams:\n\n");
+  printf(
+"  The -v switch produces a Voronoi diagram, in files suffixed .v.node and\n");
+  printf(
+"  .v.edge.  For example, `triangle -v points' will read points.node,\n");
+  printf(
+"  produce its Delaunay triangulation in points.1.node and points.1.ele,\n");
+  printf(
+"  and produce its Voronoi diagram in points.1.v.node and points.1.v.edge.\n");
+  printf(
+"  The .v.node file contains a list of all Voronoi vertices, and the .v.edge\n"
+);
+  printf(
+"  file contains a list of all Voronoi edges, some of which may be infinite\n"
+);
+  printf(
+"  rays.  (The choice of filenames makes it easy to run the set of Voronoi\n");
+  printf("  vertices through Triangle, if so desired.)\n\n");
+  printf(
+"  This implementation does not use exact arithmetic to compute the Voronoi\n"
+);
+  printf(
+"  vertices, and does not check whether neighboring vertices are identical.\n"
+);
+  printf(
+"  Be forewarned that if the Delaunay triangulation is degenerate or\n");
+  printf(
+"  near-degenerate, the Voronoi diagram may have duplicate points, crossing\n"
+);
+  printf(
+"  edges, or infinite rays whose direction vector is zero.  Also, if you\n");
+  printf(
+"  generate a constrained (as opposed to conforming) Delaunay triangulation,\n"
+);
+  printf(
+"  or if the triangulation has holes, the corresponding Voronoi diagram is\n");
+  printf("  likely to have crossing edges and unlikely to make sense.\n\n");
+  printf("Mesh Topology:\n\n");
+  printf(
+"  You may wish to know which triangles are adjacent to a certain Delaunay\n");
+  printf(
+"  edge in an .edge file, which Voronoi regions are adjacent to a certain\n");
+  printf(
+"  Voronoi edge in a .v.edge file, or which Voronoi regions are adjacent to\n"
+);
+  printf(
+"  each other.  All of this information can be found by cross-referencing\n");
+  printf(
+"  output files with the recollection that the Delaunay triangulation and\n");
+  printf("  the Voronoi diagrams are planar duals.\n\n");
+  printf(
+"  Specifically, edge i of an .edge file is the dual of Voronoi edge i of\n");
+  printf(
+"  the corresponding .v.edge file, and is rotated 90 degrees counterclock-\n");
+  printf(
+"  wise from the Voronoi edge.  Triangle j of an .ele file is the dual of\n");
+  printf(
+"  vertex j of the corresponding .v.node file; and Voronoi region k is the\n");
+  printf("  dual of point k of the corresponding .node file.\n\n");
+  printf(
+"  Hence, to find the triangles adjacent to a Delaunay edge, look at the\n");
+  printf(
+"  vertices of the corresponding Voronoi edge; their dual triangles are on\n");
+  printf(
+"  the left and right of the Delaunay edge, respectively.  To find the\n");
+  printf(
+"  Voronoi regions adjacent to a Voronoi edge, look at the endpoints of the\n"
+);
+  printf(
+"  corresponding Delaunay edge; their dual regions are on the right and left\n"
+);
+  printf(
+"  of the Voronoi edge, respectively.  To find which Voronoi regions are\n");
+  printf("  adjacent to each other, just read the list of Delaunay edges.\n");
+  printf("\n");
+  printf("Statistics:\n");
+  printf("\n");
+  printf(
+"  After generating a mesh, Triangle prints a count of the number of points,\n"
+);
+  printf(
+"  triangles, edges, boundary edges, and segments in the output mesh.  If\n");
+  printf(
+"  you've forgotten the statistics for an existing mesh, the -rNEP switches\n"
+);
+  printf(
+"  (or -rpNEP if you've got a .poly file for the existing mesh) will\n");
+  printf("  regenerate these statistics without writing any output.\n\n");
+  printf(
+"  The -V switch produces extended statistics, including a rough estimate\n");
+  printf(
+"  of memory use and a histogram of triangle aspect ratios and angles in the\n"
+);
+  printf("  mesh.\n\n");
+  printf("Exact Arithmetic:\n\n");
+  printf(
+"  Triangle uses adaptive exact arithmetic to perform what computational\n");
+  printf(
+"  geometers call the `orientation' and `incircle' tests.  If the floating-\n"
+);
+  printf(
+"  point arithmetic of your machine conforms to the IEEE 754 standard (as\n");
+  printf(
+"  most workstations do), and does not use extended precision internal\n");
+  printf(
+"  registers, then your output is guaranteed to be an absolutely true\n");
+  printf("  Delaunay or conforming Delaunay triangulation, roundoff error\n");
+  printf(
+"  notwithstanding.  The word `adaptive' implies that these arithmetic\n");
+  printf(
+"  routines compute the result only to the precision necessary to guarantee\n"
+);
+  printf(
+"  correctness, so they are usually nearly as fast as their approximate\n");
+  printf(
+"  counterparts.  The exact tests can be disabled with the -X switch.  On\n");
+  printf(
+"  most inputs, this switch will reduce the computation time by about eight\n"
+);
+  printf(
+"  percent - it's not worth the risk.  There are rare difficult inputs\n");
+  printf(
+"  (having many collinear and cocircular points), however, for which the\n");
+  printf(
+"  difference could be a factor of two.  These are precisely the inputs most\n"
+);
+  printf("  likely to cause errors if you use the -X switch.\n\n");
+  printf(
+"  Unfortunately, these routines don't solve every numerical problem.  Exact\n"
+);
+  printf(
+"  arithmetic is not used to compute the positions of points, because the\n");
+  printf(
+"  bit complexity of point coordinates would grow without bound.  Hence,\n");
+  printf(
+"  segment intersections aren't computed exactly; in very unusual cases,\n");
+  printf(
+"  roundoff error in computing an intersection point might actually lead to\n"
+);
+  printf(
+"  an inverted triangle and an invalid triangulation.  (This is one reason\n");
+  printf(
+"  to compute your own intersection points in your .poly files.)  Similarly,\n"
+);
+  printf(
+"  exact arithmetic is not used to compute the vertices of the Voronoi\n");
+  printf("  diagram.\n\n");
+  printf(
+"  Underflow and overflow can also cause difficulties; the exact arithmetic\n"
+);
+  printf(
+"  routines do not ameliorate out-of-bounds exponents, which can arise\n");
+  printf(
+"  during the orientation and incircle tests.  As a rule of thumb, you\n");
+  printf(
+"  should ensure that your input values are within a range such that their\n");
+  printf(
+"  third powers can be taken without underflow or overflow.  Underflow can\n");
+  printf(
+"  silently prevent the tests from being performed exactly, while overflow\n");
+  printf("  will typically cause a floating exception.\n\n");
+  printf("Calling Triangle from Another Program:\n\n");
+  printf("  Read the file triangle.h for details.\n\n");
+  printf("Troubleshooting:\n\n");
+  printf("  Please read this section before mailing me bugs.\n\n");
+  printf("  `My output mesh has no triangles!'\n\n");
+  printf(
+"    If you're using a PSLG, you've probably failed to specify a proper set\n"
+);
+  printf(
+"    of bounding segments, or forgotten to use the -c switch.  Or you may\n");
+  printf(
+"    have placed a hole badly.  To test these possibilities, try again with\n"
+);
+  printf(
+"    the -c and -O switches.  Alternatively, all your input points may be\n");
+  printf(
+"    collinear, in which case you can hardly expect to triangulate them.\n");
+  printf("\n");
+  printf("  `Triangle doesn't terminate, or just crashes.'\n");
+  printf("\n");
+  printf(
+"    Bad things can happen when triangles get so small that the distance\n");
+  printf(
+"    between their vertices isn't much larger than the precision of your\n");
+  printf(
+"    machine's arithmetic.  If you've compiled Triangle for single-precision\n"
+);
+  printf(
+"    arithmetic, you might do better by recompiling it for double-precision.\n"
+);
+  printf(
+"    Then again, you might just have to settle for more lenient constraints\n"
+);
+  printf(
+"    on the minimum angle and the maximum area than you had planned.\n");
+  printf("\n");
+  printf(
+"    You can minimize precision problems by ensuring that the origin lies\n");
+  printf(
+"    inside your point set, or even inside the densest part of your\n");
+  printf(
+"    mesh.  On the other hand, if you're triangulating an object whose x\n");
+  printf(
+"    coordinates all fall between 6247133 and 6247134, you're not leaving\n");
+  printf("    much floating-point precision for Triangle to work with.\n\n");
+  printf(
+"    Precision problems can occur covertly if the input PSLG contains two\n");
+  printf(
+"    segments that meet (or intersect) at a very small angle, or if such an\n"
+);
+  printf(
+"    angle is introduced by the -c switch, which may occur if a point lies\n");
+  printf(
+"    ever-so-slightly inside the convex hull, and is connected by a PSLG\n");
+  printf(
+"    segment to a point on the convex hull.  If you don't realize that a\n");
+  printf(
+"    small angle is being formed, you might never discover why Triangle is\n");
+  printf(
+"    crashing.  To check for this possibility, use the -S switch (with an\n");
+  printf(
+"    appropriate limit on the number of Steiner points, found by trial-and-\n"
+);
+  printf(
+"    error) to stop Triangle early, and view the output .poly file with\n");
+  printf(
+"    Show Me (described below).  Look carefully for small angles between\n");
+  printf(
+"    segments; zoom in closely, as such segments might look like a single\n");
+  printf("    segment from a distance.\n\n");
+  printf(
+"    If some of the input values are too large, Triangle may suffer a\n");
+  printf(
+"    floating exception due to overflow when attempting to perform an\n");
+  printf(
+"    orientation or incircle test.  (Read the section on exact arithmetic\n");
+  printf(
+"    above.)  Again, I recommend compiling Triangle for double (rather\n");
+  printf("    than single) precision arithmetic.\n\n");
+  printf(
+"  `The numbering of the output points doesn't match the input points.'\n");
+  printf("\n");
+  printf(
+"    You may have eaten some of your input points with a hole, or by placing\n"
+);
+  printf("    them outside the area enclosed by segments.\n\n");
+  printf(
+"  `Triangle executes without incident, but when I look at the resulting\n");
+  printf(
+"  mesh, it has overlapping triangles or other geometric inconsistencies.'\n");
+  printf("\n");
+  printf(
+"    If you select the -X switch, Triangle's divide-and-conquer Delaunay\n");
+  printf(
+"    triangulation algorithm occasionally makes mistakes due to floating-\n");
+  printf(
+"    point roundoff error.  Although these errors are rare, don't use the -X\n"
+);
+  printf("    switch.  If you still have problems, please report the bug.\n");
+  printf("\n");
+  printf(
+"  Strange things can happen if you've taken liberties with your PSLG.  Do\n");
+  printf(
+"  you have a point lying in the middle of a segment?  Triangle sometimes\n");
+  printf(
+"  copes poorly with that sort of thing.  Do you want to lay out a collinear\n"
+);
+  printf(
+"  row of evenly spaced, segment-connected points?  Have you simply defined\n"
+);
+  printf(
+"  one long segment connecting the leftmost point to the rightmost point,\n");
+  printf(
+"  and a bunch of points lying along it?  This method occasionally works,\n");
+  printf(
+"  especially with horizontal and vertical lines, but often it doesn't, and\n"
+);
+  printf(
+"  you'll have to connect each adjacent pair of points with a separate\n");
+  printf("  segment.  If you don't like it, tough.\n\n");
+  printf(
+"  Furthermore, if you have segments that intersect other than at their\n");
+  printf(
+"  endpoints, try not to let the intersections fall extremely close to PSLG\n"
+);
+  printf("  points or each other.\n\n");
+  printf(
+"  If you have problems refining a triangulation not produced by Triangle:\n");
+  printf(
+"  Are you sure the triangulation is geometrically valid?  Is it formatted\n");
+  printf(
+"  correctly for Triangle?  Are the triangles all listed so the first three\n"
+);
+  printf("  points are their corners in counterclockwise order?\n\n");
+  printf("Show Me:\n\n");
+  printf(
+"  Triangle comes with a separate program named `Show Me', whose primary\n");
+  printf(
+"  purpose is to draw meshes on your screen or in PostScript.  Its secondary\n"
+);
+  printf(
+"  purpose is to check the validity of your input files, and do so more\n");
+  printf(
+"  thoroughly than Triangle does.  Show Me requires that you have the X\n");
+  printf(
+"  Windows system.  If you didn't receive Show Me with Triangle, complain to\n"
+);
+  printf("  whomever you obtained Triangle from, then send me mail.\n\n");
+  printf("Triangle on the Web:\n\n");
+  printf(
+"  To see an illustrated, updated version of these instructions, check out\n");
+  printf("\n");
+  printf("    http://www.cs.cmu.edu/~quake/triangle.html\n");
+  printf("\n");
+  printf("A Brief Plea:\n");
+  printf("\n");
+  printf(
+"  If you use Triangle, and especially if you use it to accomplish real\n");
+  printf(
+"  work, I would like very much to hear from you.  A short letter or email\n");
+  printf(
+"  (to jrs@cs.cmu.edu) describing how you use Triangle will mean a lot to\n");
+  printf(
+"  me.  The more people I know are using this program, the more easily I can\n"
+);
+  printf(
+"  justify spending time on improvements and on the three-dimensional\n");
+  printf(
+"  successor to Triangle, which in turn will benefit you.  Also, I can put\n");
+  printf(
+"  you on a list to receive email whenever a new version of Triangle is\n");
+  printf("  available.\n\n");
+  printf(
+"  If you use a mesh generated by Triangle in a publication, please include\n"
+);
+  printf("  an acknowledgment as well.\n\n");
+  printf("Research credit:\n\n");
+  printf(
+"  Of course, I can take credit for only a fraction of the ideas that made\n");
+  printf(
+"  this mesh generator possible.  Triangle owes its existence to the efforts\n"
+);
+  printf(
+"  of many fine computational geometers and other researchers, including\n");
+  printf(
+"  Marshall Bern, L. Paul Chew, Boris Delaunay, Rex A. Dwyer, David\n");
+  printf(
+"  Eppstein, Steven Fortune, Leonidas J. Guibas, Donald E. Knuth, C. L.\n");
+  printf(
+"  Lawson, Der-Tsai Lee, Ernst P. Mucke, Douglas M. Priest, Jim Ruppert,\n");
+  printf(
+"  Isaac Saias, Bruce J. Schachter, Micha Sharir, Jorge Stolfi, Christopher\n"
+);
+  printf(
+"  J. Van Wyk, David F. Watson, and Binhai Zhu.  See the comments at the\n");
+  printf("  beginning of the source code for references.\n\n");
+  exit(0);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  internalerror()   Ask the user to send me the defective product.  Exit.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void internalerror()
+{
+  printf("  Please report this bug to jrs@cs.cmu.edu\n");
+  printf("  Include the message above, your input data set, and the exact\n");
+  printf("    command line you used to run Triangle.\n");
+  exit(1);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  parsecommandline()   Read the command line, identify switches, and set   */
+/*                       up options and file names.                          */
+/*                                                                           */
+/*  The effects of this routine are felt entirely through global variables.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void parsecommandline(argc, argv)
+int argc;
+char **argv;
+{
+#ifdef TRILIBRARY
+#define STARTINDEX 0
+#else /* not TRILIBRARY */
+#define STARTINDEX 1
+  int increment;
+  int meshnumber;
+#endif /* not TRILIBRARY */
+  int i, j;
+#ifndef CDT_ONLY
+  int k;
+  char workstring[FILENAMESIZE];
+#endif
+
+  poly = refine = quality = vararea = fixedarea = regionattrib = convex = 0;
+  firstnumber = 1;
+  edgesout = voronoi = neighbors = geomview = 0;
+  nobound = nopolywritten = nonodewritten = noelewritten = noiterationnum = 0;
+  noholes = noexact = 0;
+  incremental = sweepline = 0;
+  dwyer = 1;
+  splitseg = 0;
+  docheck = 0;
+  nobisect = 0;
+  steiner = -1;
+  order = 1;
+  minangle = 0.0;
+  maxarea = -1.0;
+  quiet = verbose = 0;
+#ifndef TRILIBRARY
+  innodefilename[0] = '\0';
+#endif /* not TRILIBRARY */
+
+  for (i = STARTINDEX; i < argc; i++) {
+#ifndef TRILIBRARY
+    if (argv[i][0] == '-') {
+#endif /* not TRILIBRARY */
+      for (j = STARTINDEX; argv[i][j] != '\0'; j++) {
+        if (argv[i][j] == 'p') {
+          poly = 1;
+	}
+#ifndef CDT_ONLY
+        if (argv[i][j] == 'r') {
+          refine = 1;
+	}
+        if (argv[i][j] == 'q') {
+          quality = 1;
+          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+              (argv[i][j + 1] == '.')) {
+            k = 0;
+            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+                   (argv[i][j + 1] == '.')) {
+              j++;
+              workstring[k] = argv[i][j];
+              k++;
+            }
+            workstring[k] = '\0';
+            minangle = (REAL) strtod(workstring, (char **) NULL);
+	  } else {
+            minangle = 20.0;
+	  }
+	}
+        if (argv[i][j] == 'a') {
+          quality = 1;
+          if (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+              (argv[i][j + 1] == '.')) {
+            fixedarea = 1;
+            k = 0;
+            while (((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) ||
+                   (argv[i][j + 1] == '.')) {
+              j++;
+              workstring[k] = argv[i][j];
+              k++;
+            }
+            workstring[k] = '\0';
+            maxarea = (REAL) strtod(workstring, (char **) NULL);
+            if (maxarea <= 0.0) {
+              printf("Error:  Maximum area must be greater than zero.\n");
+              exit(1);
+	    }
+	  } else {
+            vararea = 1;
+	  }
+	}
+#endif /* not CDT_ONLY */
+        if (argv[i][j] == 'A') {
+          regionattrib = 1;
+        }
+        if (argv[i][j] == 'c') {
+          convex = 1;
+        }
+        if (argv[i][j] == 'z') {
+          firstnumber = 0;
+        }
+        if (argv[i][j] == 'e') {
+          edgesout = 1;
+	}
+        if (argv[i][j] == 'v') {
+          voronoi = 1;
+	}
+        if (argv[i][j] == 'n') {
+          neighbors = 1;
+	}
+        if (argv[i][j] == 'g') {
+          geomview = 1;
+	}
+        if (argv[i][j] == 'B') {
+          nobound = 1;
+	}
+        if (argv[i][j] == 'P') {
+          nopolywritten = 1;
+	}
+        if (argv[i][j] == 'N') {
+          nonodewritten = 1;
+	}
+        if (argv[i][j] == 'E') {
+          noelewritten = 1;
+	}
+#ifndef TRILIBRARY
+        if (argv[i][j] == 'I') {
+          noiterationnum = 1;
+	}
+#endif /* not TRILIBRARY */
+        if (argv[i][j] == 'O') {
+          noholes = 1;
+	}
+        if (argv[i][j] == 'X') {
+          noexact = 1;
+	}
+        if (argv[i][j] == 'o') {
+          if (argv[i][j + 1] == '2') {
+            j++;
+            order = 2;
+          }
+	}
+#ifndef CDT_ONLY
+        if (argv[i][j] == 'Y') {
+          nobisect++;
+	}
+        if (argv[i][j] == 'S') {
+          steiner = 0;
+          while ((argv[i][j + 1] >= '0') && (argv[i][j + 1] <= '9')) {
+            j++;
+            steiner = steiner * 10 + (int) (argv[i][j] - '0');
+          }
+        }
+#endif /* not CDT_ONLY */
+#ifndef REDUCED
+        if (argv[i][j] == 'i') {
+          incremental = 1;
+        }
+        if (argv[i][j] == 'F') {
+          sweepline = 1;
+        }
+#endif /* not REDUCED */
+        if (argv[i][j] == 'l') {
+          dwyer = 0;
+        }
+#ifndef REDUCED
+#ifndef CDT_ONLY
+        if (argv[i][j] == 's') {
+          splitseg = 1;
+        }
+#endif /* not CDT_ONLY */
+        if (argv[i][j] == 'C') {
+          docheck = 1;
+        }
+#endif /* not REDUCED */
+        if (argv[i][j] == 'Q') {
+          quiet = 1;
+        }
+        if (argv[i][j] == 'V') {
+          verbose++;
+        }
+#ifndef TRILIBRARY
+        if ((argv[i][j] == 'h') || (argv[i][j] == 'H') ||
+            (argv[i][j] == '?')) {
+          info();
+	}
+#endif /* not TRILIBRARY */
+      }
+#ifndef TRILIBRARY
+    } else {
+      strncpy(innodefilename, argv[i], FILENAMESIZE - 1);
+      innodefilename[FILENAMESIZE - 1] = '\0';
+    }
+#endif /* not TRILIBRARY */
+  }
+#ifndef TRILIBRARY
+  if (innodefilename[0] == '\0') {
+    syntax();
+  }
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".node")) {
+    innodefilename[strlen(innodefilename) - 5] = '\0';
+  }
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".poly")) {
+    innodefilename[strlen(innodefilename) - 5] = '\0';
+    poly = 1;
+  }
+#ifndef CDT_ONLY
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 4], ".ele")) {
+    innodefilename[strlen(innodefilename) - 4] = '\0';
+    refine = 1;
+  }
+  if (!strcmp(&innodefilename[strlen(innodefilename) - 5], ".area")) {
+    innodefilename[strlen(innodefilename) - 5] = '\0';
+    refine = 1;
+    quality = 1;
+    vararea = 1;
+  }
+#endif /* not CDT_ONLY */
+#endif /* not TRILIBRARY */
+  steinerleft = steiner;
+  useshelles = poly || refine || quality || convex;
+  goodangle = (REAL)cos(minangle * PI / 180.0);
+  goodangle *= goodangle;
+  if (refine && noiterationnum) {
+    printf(
+      "Error:  You cannot use the -I switch when refining a triangulation.\n");
+    exit(1);
+  }
+  /* Be careful not to allocate space for element area constraints that */
+  /*   will never be assigned any value (other than the default -1.0).  */
+  if (!refine && !poly) {
+    vararea = 0;
+  }
+  /* Be careful not to add an extra attribute to each element unless the */
+  /*   input supports it (PSLG in, but not refining a preexisting mesh). */
+  if (refine || !poly) {
+    regionattrib = 0;
+  }
+
+#ifndef TRILIBRARY
+  strcpy(inpolyfilename, innodefilename);
+  strcpy(inelefilename, innodefilename);
+  strcpy(areafilename, innodefilename);
+  increment = 0;
+  strcpy(workstring, innodefilename);
+  j = 1;
+  while (workstring[j] != '\0') {
+    if ((workstring[j] == '.') && (workstring[j + 1] != '\0')) {
+      increment = j + 1;
+    }
+    j++;
+  }
+  meshnumber = 0;
+  if (increment > 0) {
+    j = increment;
+    do {
+      if ((workstring[j] >= '0') && (workstring[j] <= '9')) {
+        meshnumber = meshnumber * 10 + (int) (workstring[j] - '0');
+      } else {
+        increment = 0;
+      }
+      j++;
+    } while (workstring[j] != '\0');
+  }
+  if (noiterationnum) {
+    strcpy(outnodefilename, innodefilename);
+    strcpy(outelefilename, innodefilename);
+    strcpy(edgefilename, innodefilename);
+    strcpy(vnodefilename, innodefilename);
+    strcpy(vedgefilename, innodefilename);
+    strcpy(neighborfilename, innodefilename);
+    strcpy(offfilename, innodefilename);
+    strcat(outnodefilename, ".node");
+    strcat(outelefilename, ".ele");
+    strcat(edgefilename, ".edge");
+    strcat(vnodefilename, ".v.node");
+    strcat(vedgefilename, ".v.edge");
+    strcat(neighborfilename, ".neigh");
+    strcat(offfilename, ".off");
+  } else if (increment == 0) {
+    strcpy(outnodefilename, innodefilename);
+    strcpy(outpolyfilename, innodefilename);
+    strcpy(outelefilename, innodefilename);
+    strcpy(edgefilename, innodefilename);
+    strcpy(vnodefilename, innodefilename);
+    strcpy(vedgefilename, innodefilename);
+    strcpy(neighborfilename, innodefilename);
+    strcpy(offfilename, innodefilename);
+    strcat(outnodefilename, ".1.node");
+    strcat(outpolyfilename, ".1.poly");
+    strcat(outelefilename, ".1.ele");
+    strcat(edgefilename, ".1.edge");
+    strcat(vnodefilename, ".1.v.node");
+    strcat(vedgefilename, ".1.v.edge");
+    strcat(neighborfilename, ".1.neigh");
+    strcat(offfilename, ".1.off");
+  } else {
+    workstring[increment] = '%';
+    workstring[increment + 1] = 'd';
+    workstring[increment + 2] = '\0';
+    sprintf(outnodefilename, workstring, meshnumber + 1);
+    strcpy(outpolyfilename, outnodefilename);
+    strcpy(outelefilename, outnodefilename);
+    strcpy(edgefilename, outnodefilename);
+    strcpy(vnodefilename, outnodefilename);
+    strcpy(vedgefilename, outnodefilename);
+    strcpy(neighborfilename, outnodefilename);
+    strcpy(offfilename, outnodefilename);
+    strcat(outnodefilename, ".node");
+    strcat(outpolyfilename, ".poly");
+    strcat(outelefilename, ".ele");
+    strcat(edgefilename, ".edge");
+    strcat(vnodefilename, ".v.node");
+    strcat(vedgefilename, ".v.edge");
+    strcat(neighborfilename, ".neigh");
+    strcat(offfilename, ".off");
+  }
+  strcat(innodefilename, ".node");
+  strcat(inpolyfilename, ".poly");
+  strcat(inelefilename, ".ele");
+  strcat(areafilename, ".area");
+#endif /* not TRILIBRARY */
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* User interaction routines begin here                      *********/
+
+/********* Debugging routines begin here                             *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  printtriangle()   Print out the details of a triangle/edge handle.       */
+/*                                                                           */
+/*  I originally wrote this procedure to simplify debugging; it can be       */
+/*  called directly from the debugger, and presents information about a      */
+/*  triangle/edge handle in digestible form.  It's also used when the        */
+/*  highest level of verbosity (`-VVV') is specified.                        */
+/*                                                                           */
+/*****************************************************************************/
+
+void printtriangle(t)
+struct triedge *t;
+{
+  struct triedge printtri;
+  struct edge printsh;
+  point printpoint;
+
+  printf("triangle x%lx with orientation %d:\n", (unsigned long) t->tri,
+         t->orient);
+  decode(t->tri[0], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [0] = Outer space\n");
+  } else {
+    printf("    [0] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  decode(t->tri[1], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [1] = Outer space\n");
+  } else {
+    printf("    [1] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  decode(t->tri[2], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [2] = Outer space\n");
+  } else {
+    printf("    [2] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  org(*t, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Origin[%d] = NULL\n", (t->orient + 1) % 3 + 3);
+  else
+    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
+           (t->orient + 1) % 3 + 3, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  dest(*t, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Dest  [%d] = NULL\n", (t->orient + 2) % 3 + 3);
+  else
+    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
+           (t->orient + 2) % 3 + 3, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  apex(*t, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Apex  [%d] = NULL\n", t->orient + 3);
+  else
+    printf("    Apex  [%d] = x%lx  (%.12g, %.12g)\n",
+           t->orient + 3, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  if (useshelles) {
+    sdecode(t->tri[6], printsh);
+    if (printsh.sh != dummysh) {
+      printf("    [6] = x%lx  %d\n", (unsigned long) printsh.sh,
+             printsh.shorient);
+    }
+    sdecode(t->tri[7], printsh);
+    if (printsh.sh != dummysh) {
+      printf("    [7] = x%lx  %d\n", (unsigned long) printsh.sh,
+             printsh.shorient);
+    }
+    sdecode(t->tri[8], printsh);
+    if (printsh.sh != dummysh) {
+      printf("    [8] = x%lx  %d\n", (unsigned long) printsh.sh,
+             printsh.shorient);
+    }
+  }
+  if (vararea) {
+    printf("    Area constraint:  %.4g\n", areabound(*t));
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  printshelle()   Print out the details of a shell edge handle.            */
+/*                                                                           */
+/*  I originally wrote this procedure to simplify debugging; it can be       */
+/*  called directly from the debugger, and presents information about a      */
+/*  shell edge handle in digestible form.  It's also used when the highest   */
+/*  level of verbosity (`-VVV') is specified.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+void printshelle(s)
+struct edge *s;
+{
+  struct edge printsh;
+  struct triedge printtri;
+  point printpoint;
+
+  printf("shell edge x%lx with orientation %d and mark %d:\n",
+         (unsigned long) s->sh, s->shorient, mark(*s));
+  sdecode(s->sh[0], printsh);
+  if (printsh.sh == dummysh) {
+    printf("    [0] = No shell\n");
+  } else {
+    printf("    [0] = x%lx  %d\n", (unsigned long) printsh.sh,
+           printsh.shorient);
+  }
+  sdecode(s->sh[1], printsh);
+  if (printsh.sh == dummysh) {
+    printf("    [1] = No shell\n");
+  } else {
+    printf("    [1] = x%lx  %d\n", (unsigned long) printsh.sh,
+           printsh.shorient);
+  }
+  sorg(*s, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Origin[%d] = NULL\n", 2 + s->shorient);
+  else
+    printf("    Origin[%d] = x%lx  (%.12g, %.12g)\n",
+           2 + s->shorient, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  sdest(*s, printpoint);
+  if (printpoint == (point) NULL)
+    printf("    Dest  [%d] = NULL\n", 3 - s->shorient);
+  else
+    printf("    Dest  [%d] = x%lx  (%.12g, %.12g)\n",
+           3 - s->shorient, (unsigned long) printpoint,
+           printpoint[0], printpoint[1]);
+  decode(s->sh[4], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [4] = Outer space\n");
+  } else {
+    printf("    [4] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+  decode(s->sh[5], printtri);
+  if (printtri.tri == dummytri) {
+    printf("    [5] = Outer space\n");
+  } else {
+    printf("    [5] = x%lx  %d\n", (unsigned long) printtri.tri,
+           printtri.orient);
+  }
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Debugging routines end here                               *********/
+
+/********* Memory management routines begin here                     *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  poolinit()   Initialize a pool of memory for allocation of items.        */
+/*                                                                           */
+/*  This routine initializes the machinery for allocating items.  A `pool'   */
+/*  is created whose records have size at least `bytecount'.  Items will be  */
+/*  allocated in `itemcount'-item blocks.  Each item is assumed to be a      */
+/*  collection of words, and either pointers or floating-point values are    */
+/*  assumed to be the "primary" word type.  (The "primary" word type is used */
+/*  to determine alignment of items.)  If `alignment' isn't zero, all items  */
+/*  will be `alignment'-byte aligned in memory.  `alignment' must be either  */
+/*  a multiple or a factor of the primary word size; powers of two are safe. */
+/*  `alignment' is normally used to create a few unused bits at the bottom   */
+/*  of each item's pointer, in which information may be stored.              */
+/*                                                                           */
+/*  Don't change this routine unless you understand it.                      */
+/*                                                                           */
+/*****************************************************************************/
+
+void poolinit(pool, bytecount, itemcount, wtype, alignment)
+struct memorypool *pool;
+int bytecount;
+int itemcount;
+enum wordtype wtype;
+int alignment;
+{
+  int wordsize;
+
+  /* Initialize values in the pool. */
+  pool->itemwordtype = wtype;
+  wordsize = (pool->itemwordtype == POINTER) ? sizeof(VOID *) : sizeof(REAL);
+  /* Find the proper alignment, which must be at least as large as:   */
+  /*   - The parameter `alignment'.                                   */
+  /*   - The primary word type, to avoid unaligned accesses.          */
+  /*   - sizeof(VOID *), so the stack of dead items can be maintained */
+  /*       without unaligned accesses.                                */
+  if (alignment > wordsize) {
+    pool->alignbytes = alignment;
+  } else {
+    pool->alignbytes = wordsize;
+  }
+  if (sizeof(VOID *) > pool->alignbytes) {
+    pool->alignbytes = sizeof(VOID *);
+  }
+  pool->itemwords = ((bytecount + pool->alignbytes - 1) / pool->alignbytes)
+                  * (pool->alignbytes / wordsize);
+  pool->itembytes = pool->itemwords * wordsize;
+  pool->itemsperblock = itemcount;
+
+  /* Allocate a block of items.  Space for `itemsperblock' items and one    */
+  /*   pointer (to point to the next block) are allocated, as well as space */
+  /*   to ensure alignment of the items.                                    */
+  pool->firstblock = (VOID **) malloc(pool->itemsperblock * pool->itembytes
+                                      + sizeof(VOID *) + pool->alignbytes);
+  if (pool->firstblock == (VOID **) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  /* Set the next block pointer to NULL. */
+  *(pool->firstblock) = (VOID *) NULL;
+  poolrestart(pool);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  poolrestart()   Deallocate all items in a pool.                          */
+/*                                                                           */
+/*  The pool is returned to its starting state, except that no memory is     */
+/*  freed to the operating system.  Rather, the previously allocated blocks  */
+/*  are ready to be reused.                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void poolrestart(pool)
+struct memorypool *pool;
+{
+  unsigned long alignptr;
+
+  pool->items = 0;
+  pool->maxitems = 0;
+
+  /* Set the currently active block. */
+  pool->nowblock = pool->firstblock;
+  /* Find the first item in the pool.  Increment by the size of (VOID *). */
+  alignptr = (unsigned long) (pool->nowblock + 1);
+  /* Align the item on an `alignbytes'-byte boundary. */
+  pool->nextitem = (VOID *)
+    (alignptr + (unsigned long) pool->alignbytes
+     - (alignptr % (unsigned long) pool->alignbytes));
+  /* There are lots of unallocated items left in this block. */
+  pool->unallocateditems = pool->itemsperblock;
+  /* The stack of deallocated items is empty. */
+  pool->deaditemstack = (VOID *) NULL;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pooldeinit()   Free to the operating system all memory taken by a pool.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void pooldeinit(pool)
+struct memorypool *pool;
+{
+  while (pool->firstblock != (VOID **) NULL) {
+    pool->nowblock = (VOID **) *(pool->firstblock);
+    free(pool->firstblock);
+    pool->firstblock = pool->nowblock;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  poolalloc()   Allocate space for an item.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+VOID *poolalloc(pool)
+struct memorypool *pool;
+{
+  VOID *newitem;
+  VOID **newblock;
+  unsigned long alignptr;
+
+  /* First check the linked list of dead items.  If the list is not   */
+  /*   empty, allocate an item from the list rather than a fresh one. */
+  if (pool->deaditemstack != (VOID *) NULL) {
+    newitem = pool->deaditemstack;               /* Take first item in list. */
+    pool->deaditemstack = * (VOID **) pool->deaditemstack;
+  } else {
+    /* Check if there are any free items left in the current block. */
+    if (pool->unallocateditems == 0) {
+      /* Check if another block must be allocated. */
+      if (*(pool->nowblock) == (VOID *) NULL) {
+        /* Allocate a new block of items, pointed to by the previous block. */
+        newblock = (VOID **) malloc(pool->itemsperblock * pool->itembytes
+                                    + sizeof(VOID *) + pool->alignbytes);
+        if (newblock == (VOID **) NULL) {
+          printf("Error:  Out of memory.\n");
+          exit(1);
+        }
+        *(pool->nowblock) = (VOID *) newblock;
+        /* The next block pointer is NULL. */
+        *newblock = (VOID *) NULL;
+      }
+      /* Move to the new block. */
+      pool->nowblock = (VOID **) *(pool->nowblock);
+      /* Find the first item in the block.    */
+      /*   Increment by the size of (VOID *). */
+      alignptr = (unsigned long) (pool->nowblock + 1);
+      /* Align the item on an `alignbytes'-byte boundary. */
+      pool->nextitem = (VOID *)
+        (alignptr + (unsigned long) pool->alignbytes
+         - (alignptr % (unsigned long) pool->alignbytes));
+      /* There are lots of unallocated items left in this block. */
+      pool->unallocateditems = pool->itemsperblock;
+    }
+    /* Allocate a new item. */
+    newitem = pool->nextitem;
+    /* Advance `nextitem' pointer to next free item in block. */
+    if (pool->itemwordtype == POINTER) {
+      pool->nextitem = (VOID *) ((VOID **) pool->nextitem + pool->itemwords);
+    } else {
+      pool->nextitem = (VOID *) ((REAL *) pool->nextitem + pool->itemwords);
+    }
+    pool->unallocateditems--;
+    pool->maxitems++;
+  }
+  pool->items++;
+  return newitem;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pooldealloc()   Deallocate space for an item.                            */
+/*                                                                           */
+/*  The deallocated space is stored in a queue for later reuse.              */
+/*                                                                           */
+/*****************************************************************************/
+
+void pooldealloc(pool, dyingitem)
+struct memorypool *pool;
+VOID *dyingitem;
+{
+  /* Push freshly killed item onto stack. */
+  *((VOID **) dyingitem) = pool->deaditemstack;
+  pool->deaditemstack = dyingitem;
+  pool->items--;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  traversalinit()   Prepare to traverse the entire list of items.          */
+/*                                                                           */
+/*  This routine is used in conjunction with traverse().                     */
+/*                                                                           */
+/*****************************************************************************/
+
+void traversalinit(pool)
+struct memorypool *pool;
+{
+  unsigned long alignptr;
+
+  /* Begin the traversal in the first block. */
+  pool->pathblock = pool->firstblock;
+  /* Find the first item in the block.  Increment by the size of (VOID *). */
+  alignptr = (unsigned long) (pool->pathblock + 1);
+  /* Align with item on an `alignbytes'-byte boundary. */
+  pool->pathitem = (VOID *)
+    (alignptr + (unsigned long) pool->alignbytes
+     - (alignptr % (unsigned long) pool->alignbytes));
+  /* Set the number of items left in the current block. */
+  pool->pathitemsleft = pool->itemsperblock;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  traverse()   Find the next item in the list.                             */
+/*                                                                           */
+/*  This routine is used in conjunction with traversalinit().  Be forewarned */
+/*  that this routine successively returns all items in the list, including  */
+/*  deallocated ones on the deaditemqueue.  It's up to you to figure out     */
+/*  which ones are actually dead.  Why?  I don't want to allocate extra      */
+/*  space just to demarcate dead items.  It can usually be done more         */
+/*  space-efficiently by a routine that knows something about the structure  */
+/*  of the item.                                                             */
+/*                                                                           */
+/*****************************************************************************/
+
+VOID *traverse(pool)
+struct memorypool *pool;
+{
+  VOID *newitem;
+  unsigned long alignptr;
+
+  /* Stop upon exhausting the list of items. */
+  if (pool->pathitem == pool->nextitem) {
+    return (VOID *) NULL;
+  }
+  /* Check whether any untraversed items remain in the current block. */
+  if (pool->pathitemsleft == 0) {
+    /* Find the next block. */
+    pool->pathblock = (VOID **) *(pool->pathblock);
+    /* Find the first item in the block.  Increment by the size of (VOID *). */
+    alignptr = (unsigned long) (pool->pathblock + 1);
+    /* Align with item on an `alignbytes'-byte boundary. */
+    pool->pathitem = (VOID *)
+      (alignptr + (unsigned long) pool->alignbytes
+       - (alignptr % (unsigned long) pool->alignbytes));
+    /* Set the number of items left in the current block. */
+    pool->pathitemsleft = pool->itemsperblock;
+  }
+  newitem = pool->pathitem;
+  /* Find the next item in the block. */
+  if (pool->itemwordtype == POINTER) {
+    pool->pathitem = (VOID *) ((VOID **) pool->pathitem + pool->itemwords);
+  } else {
+    pool->pathitem = (VOID *) ((REAL *) pool->pathitem + pool->itemwords);
+  }
+  pool->pathitemsleft--;
+  return newitem;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  dummyinit()   Initialize the triangle that fills "outer space" and the   */
+/*                omnipresent shell edge.                                    */
+/*                                                                           */
+/*  The triangle that fills "outer space", called `dummytri', is pointed to  */
+/*  by every triangle and shell edge on a boundary (be it outer or inner) of */
+/*  the triangulation.  Also, `dummytri' points to one of the triangles on   */
+/*  the convex hull (until the holes and concavities are carved), making it  */
+/*  possible to find a starting triangle for point location.                 */
+/*                                                                           */
+/*  The omnipresent shell edge, `dummysh', is pointed to by every triangle   */
+/*  or shell edge that doesn't have a full complement of real shell edges    */
+/*  to point to.                                                             */
+/*                                                                           */
+/*****************************************************************************/
+
+void dummyinit(trianglewords, shellewords)
+int trianglewords;
+int shellewords;
+{
+  unsigned long alignptr;
+
+  /* `triwords' and `shwords' are used by the mesh manipulation primitives */
+  /*   to extract orientations of triangles and shell edges from pointers. */
+  triwords = trianglewords;       /* Initialize `triwords' once and for all. */
+  shwords = shellewords;           /* Initialize `shwords' once and for all. */
+
+  /* Set up `dummytri', the `triangle' that occupies "outer space". */
+  dummytribase = (triangle *) malloc(triwords * sizeof(triangle)
+                                     + triangles.alignbytes);
+  if (dummytribase == (triangle *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  /* Align `dummytri' on a `triangles.alignbytes'-byte boundary. */
+  alignptr = (unsigned long) dummytribase;
+  dummytri = (triangle *)
+    (alignptr + (unsigned long) triangles.alignbytes
+     - (alignptr % (unsigned long) triangles.alignbytes));
+  /* Initialize the three adjoining triangles to be "outer space".  These  */
+  /*   will eventually be changed by various bonding operations, but their */
+  /*   values don't really matter, as long as they can legally be          */
+  /*   dereferenced.                                                       */
+  dummytri[0] = (triangle) dummytri;
+  dummytri[1] = (triangle) dummytri;
+  dummytri[2] = (triangle) dummytri;
+  /* Three NULL vertex points. */
+  dummytri[3] = (triangle) NULL;
+  dummytri[4] = (triangle) NULL;
+  dummytri[5] = (triangle) NULL;
+
+  if (useshelles) {
+    /* Set up `dummysh', the omnipresent "shell edge" pointed to by any      */
+    /*   triangle side or shell edge end that isn't attached to a real shell */
+    /*   edge.                                                               */
+    dummyshbase = (shelle *) malloc(shwords * sizeof(shelle)
+                                    + shelles.alignbytes);
+    if (dummyshbase == (shelle *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+    /* Align `dummysh' on a `shelles.alignbytes'-byte boundary. */
+    alignptr = (unsigned long) dummyshbase;
+    dummysh = (shelle *)
+      (alignptr + (unsigned long) shelles.alignbytes
+       - (alignptr % (unsigned long) shelles.alignbytes));
+    /* Initialize the two adjoining shell edges to be the omnipresent shell */
+    /*   edge.  These will eventually be changed by various bonding         */
+    /*   operations, but their values don't really matter, as long as they  */
+    /*   can legally be dereferenced.                                       */
+    dummysh[0] = (shelle) dummysh;
+    dummysh[1] = (shelle) dummysh;
+    /* Two NULL vertex points. */
+    dummysh[2] = (shelle) NULL;
+    dummysh[3] = (shelle) NULL;
+    /* Initialize the two adjoining triangles to be "outer space". */
+    dummysh[4] = (shelle) dummytri;
+    dummysh[5] = (shelle) dummytri;
+    /* Set the boundary marker to zero. */
+    * (int *) (dummysh + 6) = 0;
+
+    /* Initialize the three adjoining shell edges of `dummytri' to be */
+    /*   the omnipresent shell edge.                                  */
+    dummytri[6] = (triangle) dummysh;
+    dummytri[7] = (triangle) dummysh;
+    dummytri[8] = (triangle) dummysh;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  initializepointpool()   Calculate the size of the point data structure   */
+/*                          and initialize its memory pool.                  */
+/*                                                                           */
+/*  This routine also computes the `pointmarkindex' and `point2triindex'     */
+/*  indices used to find values within each point.                           */
+/*                                                                           */
+/*****************************************************************************/
+
+void initializepointpool()
+{
+  int pointsize;
+
+  /* The index within each point at which the boundary marker is found.  */
+  /*   Ensure the point marker is aligned to a sizeof(int)-byte address. */
+  pointmarkindex = ((mesh_dim + nextras) * sizeof(REAL) + sizeof(int) - 1)
+                 / sizeof(int);
+  pointsize = (pointmarkindex + 1) * sizeof(int);
+  if (poly) {
+    /* The index within each point at which a triangle pointer is found.   */
+    /*   Ensure the pointer is aligned to a sizeof(triangle)-byte address. */
+    point2triindex = (pointsize + sizeof(triangle) - 1) / sizeof(triangle);
+    pointsize = (point2triindex + 1) * sizeof(triangle);
+  }
+  /* Initialize the pool of points. */
+  poolinit(&points, pointsize, POINTPERBLOCK,
+           (sizeof(REAL) >= sizeof(triangle)) ? FLOATINGPOINT : POINTER, 0);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  initializetrisegpools()   Calculate the sizes of the triangle and shell  */
+/*                            edge data structures and initialize their      */
+/*                            memory pools.                                  */
+/*                                                                           */
+/*  This routine also computes the `highorderindex', `elemattribindex', and  */
+/*  `areaboundindex' indices used to find values within each triangle.       */
+/*                                                                           */
+/*****************************************************************************/
+
+void initializetrisegpools()
+{
+  int trisize;
+
+  /* The index within each triangle at which the extra nodes (above three)  */
+  /*   associated with high order elements are found.  There are three      */
+  /*   pointers to other triangles, three pointers to corners, and possibly */
+  /*   three pointers to shell edges before the extra nodes.                */
+  highorderindex = 6 + (useshelles * 3);
+  /* The number of bytes occupied by a triangle. */
+  trisize = ((order + 1) * (order + 2) / 2 + (highorderindex - 3)) *
+            sizeof(triangle);
+  /* The index within each triangle at which its attributes are found, */
+  /*   where the index is measured in REALs.                           */
+  elemattribindex = (trisize + sizeof(REAL) - 1) / sizeof(REAL);
+  /* The index within each triangle at which the maximum area constraint  */
+  /*   is found, where the index is measured in REALs.  Note that if the  */
+  /*   `regionattrib' flag is set, an additional attribute will be added. */
+  areaboundindex = elemattribindex + eextras + regionattrib;
+  /* If triangle attributes or an area bound are needed, increase the number */
+  /*   of bytes occupied by a triangle.                                      */
+  if (vararea) {
+    trisize = (areaboundindex + 1) * sizeof(REAL);
+  } else if (eextras + regionattrib > 0) {
+    trisize = areaboundindex * sizeof(REAL);
+  }
+  /* If a Voronoi diagram or triangle neighbor graph is requested, make    */
+  /*   sure there's room to store an integer index in each triangle.  This */
+  /*   integer index can occupy the same space as the shell edges or       */
+  /*   attributes or area constraint or extra nodes.                       */
+  if ((voronoi || neighbors) &&
+      (trisize < 6 * sizeof(triangle) + sizeof(int))) {
+    trisize = 6 * sizeof(triangle) + sizeof(int);
+  }
+  /* Having determined the memory size of a triangle, initialize the pool. */
+  poolinit(&triangles, trisize, TRIPERBLOCK, POINTER, 4);
+
+  if (useshelles) {
+    /* Initialize the pool of shell edges. */
+    poolinit(&shelles, 6 * sizeof(triangle) + sizeof(int), SHELLEPERBLOCK,
+             POINTER, 4);
+
+    /* Initialize the "outer space" triangle and omnipresent shell edge. */
+    dummyinit(triangles.itemwords, shelles.itemwords);
+  } else {
+    /* Initialize the "outer space" triangle. */
+    dummyinit(triangles.itemwords, 0);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangledealloc()   Deallocate space for a triangle, marking it dead.    */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangledealloc(dyingtriangle)
+triangle *dyingtriangle;
+{
+  /* Set triangle's vertices to NULL.  This makes it possible to        */
+  /*   detect dead triangles when traversing the list of all triangles. */
+  dyingtriangle[3] = (triangle) NULL;
+  dyingtriangle[4] = (triangle) NULL;
+  dyingtriangle[5] = (triangle) NULL;
+  pooldealloc(&triangles, (VOID *) dyingtriangle);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangletraverse()   Traverse the triangles, skipping dead ones.         */
+/*                                                                           */
+/*****************************************************************************/
+
+triangle *triangletraverse()
+{
+  triangle *newtriangle;
+
+  do {
+    newtriangle = (triangle *) traverse(&triangles);
+    if (newtriangle == (triangle *) NULL) {
+      return (triangle *) NULL;
+    }
+  } while (newtriangle[3] == (triangle) NULL);            /* Skip dead ones. */
+  return newtriangle;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  shelledealloc()   Deallocate space for a shell edge, marking it dead.    */
+/*                                                                           */
+/*****************************************************************************/
+
+void shelledealloc(dyingshelle)
+shelle *dyingshelle;
+{
+  /* Set shell edge's vertices to NULL.  This makes it possible to */
+  /*   detect dead shells when traversing the list of all shells.  */
+  dyingshelle[2] = (shelle) NULL;
+  dyingshelle[3] = (shelle) NULL;
+  pooldealloc(&shelles, (VOID *) dyingshelle);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  shelletraverse()   Traverse the shell edges, skipping dead ones.         */
+/*                                                                           */
+/*****************************************************************************/
+
+shelle *shelletraverse()
+{
+  shelle *newshelle;
+
+  do {
+    newshelle = (shelle *) traverse(&shelles);
+    if (newshelle == (shelle *) NULL) {
+      return (shelle *) NULL;
+    }
+  } while (newshelle[2] == (shelle) NULL);                /* Skip dead ones. */
+  return newshelle;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointdealloc()   Deallocate space for a point, marking it dead.          */
+/*                                                                           */
+/*****************************************************************************/
+
+void pointdealloc(dyingpoint)
+point dyingpoint;
+{
+  /* Mark the point as dead.  This makes it possible to detect dead points */
+  /*   when traversing the list of all points.                             */
+  setpointmark(dyingpoint, DEADPOINT);
+  pooldealloc(&points, (VOID *) dyingpoint);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointtraverse()   Traverse the points, skipping dead ones.               */
+/*                                                                           */
+/*****************************************************************************/
+
+point pointtraverse()
+{
+  point newpoint;
+
+  do {
+    newpoint = (point) traverse(&points);
+    if (newpoint == (point) NULL) {
+      return (point) NULL;
+    }
+  } while (pointmark(newpoint) == DEADPOINT);             /* Skip dead ones. */
+  return newpoint;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  badsegmentdealloc()   Deallocate space for a bad segment, marking it     */
+/*                        dead.                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void badsegmentdealloc(dyingseg)
+struct edge *dyingseg;
+{
+  /* Set segment's orientation to -1.  This makes it possible to      */
+  /*   detect dead segments when traversing the list of all segments. */
+  dyingseg->shorient = -1;
+  pooldealloc(&badsegments, (VOID *) dyingseg);
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  badsegmenttraverse()   Traverse the bad segments, skipping dead ones.    */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+struct edge *badsegmenttraverse()
+{
+  struct edge *newseg;
+
+  do {
+    newseg = (struct edge *) traverse(&badsegments);
+    if (newseg == (struct edge *) NULL) {
+      return (struct edge *) NULL;
+    }
+  } while (newseg->shorient == -1);                       /* Skip dead ones. */
+  return newseg;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  getpoint()   Get a specific point, by number, from the list.             */
+/*                                                                           */
+/*  The first point is number 'firstnumber'.                                 */
+/*                                                                           */
+/*  Note that this takes O(n) time (with a small constant, if POINTPERBLOCK  */
+/*  is large).  I don't care to take the trouble to make it work in constant */
+/*  time.                                                                    */
+/*                                                                           */
+/*****************************************************************************/
+
+point getpoint(number)
+int number;
+{
+  VOID **getblock;
+  point foundpoint;
+  unsigned long alignptr;
+  int current;
+
+  getblock = points.firstblock;
+  current = firstnumber;
+  /* Find the right block. */
+  while (current + points.itemsperblock <= number) {
+    getblock = (VOID **) *getblock;
+    current += points.itemsperblock;
+  }
+  /* Now find the right point. */
+  alignptr = (unsigned long) (getblock + 1);
+  foundpoint = (point) (alignptr + (unsigned long) points.alignbytes
+                        - (alignptr % (unsigned long) points.alignbytes));
+  while (current < number) {
+    foundpoint += points.itemwords;
+    current++;
+  }
+  return foundpoint;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangledeinit()   Free all remaining allocated memory.                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangledeinit()
+{
+  pooldeinit(&triangles);
+  free(dummytribase);
+  if (useshelles) {
+    pooldeinit(&shelles);
+    free(dummyshbase);
+  }
+  pooldeinit(&points);
+#ifndef CDT_ONLY
+  if (quality) {
+    pooldeinit(&badsegments);
+    if ((minangle > 0.0) || vararea || fixedarea) {
+      pooldeinit(&badtriangles);
+    }
+  }
+#endif /* not CDT_ONLY */
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Memory management routines end here                       *********/
+
+/********* Constructors begin here                                   *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  maketriangle()   Create a new triangle with orientation zero.            */
+/*                                                                           */
+/*****************************************************************************/
+
+void maketriangle(newtriedge)
+struct triedge *newtriedge;
+{
+  int i;
+
+  newtriedge->tri = (triangle *) poolalloc(&triangles);
+  /* Initialize the three adjoining triangles to be "outer space". */
+  newtriedge->tri[0] = (triangle) dummytri;
+  newtriedge->tri[1] = (triangle) dummytri;
+  newtriedge->tri[2] = (triangle) dummytri;
+  /* Three NULL vertex points. */
+  newtriedge->tri[3] = (triangle) NULL;
+  newtriedge->tri[4] = (triangle) NULL;
+  newtriedge->tri[5] = (triangle) NULL;
+  /* Initialize the three adjoining shell edges to be the omnipresent */
+  /*   shell edge.                                                    */
+  if (useshelles) {
+    newtriedge->tri[6] = (triangle) dummysh;
+    newtriedge->tri[7] = (triangle) dummysh;
+    newtriedge->tri[8] = (triangle) dummysh;
+  }
+  for (i = 0; i < eextras; i++) {
+    setelemattribute(*newtriedge, i, 0.0);
+  }
+  if (vararea) {
+    setareabound(*newtriedge, -1.0);
+  }
+
+  newtriedge->orient = 0;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  makeshelle()   Create a new shell edge with orientation zero.            */
+/*                                                                           */
+/*****************************************************************************/
+
+void makeshelle(newedge)
+struct edge *newedge;
+{
+  newedge->sh = (shelle *) poolalloc(&shelles);
+  /* Initialize the two adjoining shell edges to be the omnipresent */
+  /*   shell edge.                                                  */
+  newedge->sh[0] = (shelle) dummysh;
+  newedge->sh[1] = (shelle) dummysh;
+  /* Two NULL vertex points. */
+  newedge->sh[2] = (shelle) NULL;
+  newedge->sh[3] = (shelle) NULL;
+  /* Initialize the two adjoining triangles to be "outer space". */
+  newedge->sh[4] = (shelle) dummytri;
+  newedge->sh[5] = (shelle) dummytri;
+  /* Set the boundary marker to zero. */
+  setmark(*newedge, 0);
+
+  newedge->shorient = 0;
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Constructors end here                                     *********/
+
+/********* Determinant evaluation routines begin here                *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/* The adaptive exact arithmetic geometric predicates implemented herein are */
+/*   described in detail in my Technical Report CMU-CS-96-140.  The complete */
+/*   reference is given in the header.                                       */
+
+/* Which of the following two methods of finding the absolute values is      */
+/*   fastest is compiler-dependent.  A few compilers can inline and optimize */
+/*   the fabs() call; but most will incur the overhead of a function call,   */
+/*   which is disastrously slow.  A faster way on IEEE machines might be to  */
+/*   mask the appropriate bit, but that's difficult to do in C.              */
+
+#define Absolute(a)  ((a) >= 0.0 ? (a) : -(a))
+/* #define Absolute(a)  fabs(a) */
+
+/* Many of the operations are broken up into two pieces, a main part that    */
+/*   performs an approximate operation, and a "tail" that computes the       */
+/*   roundoff error of that operation.                                       */
+/*                                                                           */
+/* The operations Fast_Two_Sum(), Fast_Two_Diff(), Two_Sum(), Two_Diff(),    */
+/*   Split(), and Two_Product() are all implemented as described in the      */
+/*   reference.  Each of these macros requires certain variables to be       */
+/*   defined in the calling routine.  The variables `bvirt', `c', `abig',    */
+/*   `_i', `_j', `_k', `_l', `_m', and `_n' are declared `INEXACT' because   */
+/*   they store the result of an operation that may incur roundoff error.    */
+/*   The input parameter `x' (or the highest numbered `x_' parameter) must   */
+/*   also be declared `INEXACT'.                                             */
+
+#define Fast_Two_Sum_Tail(a, b, x, y) \
+  bvirt = x - a; \
+  y = b - bvirt
+
+#define Fast_Two_Sum(a, b, x, y) \
+  x = (REAL) (a + b); \
+  Fast_Two_Sum_Tail(a, b, x, y)
+
+#define Two_Sum_Tail(a, b, x, y) \
+  bvirt = (REAL) (x - a); \
+  avirt = x - bvirt; \
+  bround = b - bvirt; \
+  around = a - avirt; \
+  y = around + bround
+
+#define Two_Sum(a, b, x, y) \
+  x = (REAL) (a + b); \
+  Two_Sum_Tail(a, b, x, y)
+
+#define Two_Diff_Tail(a, b, x, y) \
+  bvirt = (REAL) (a - x); \
+  avirt = x + bvirt; \
+  bround = bvirt - b; \
+  around = a - avirt; \
+  y = around + bround
+
+#define Two_Diff(a, b, x, y) \
+  x = (REAL) (a - b); \
+  Two_Diff_Tail(a, b, x, y)
+
+#define Split(a, ahi, alo) \
+  c = (REAL) (splitter * a); \
+  abig = (REAL) (c - a); \
+  ahi = (REAL)(c - abig); \
+  alo = (REAL)(a - ahi)
+
+#define Two_Product_Tail(a, b, x, y) \
+  Split(a, ahi, alo); \
+  Split(b, bhi, blo); \
+  err1 = x - (ahi * bhi); \
+  err2 = err1 - (alo * bhi); \
+  err3 = err2 - (ahi * blo); \
+  y = (alo * blo) - err3
+
+#define Two_Product(a, b, x, y) \
+  x = (REAL) (a * b); \
+  Two_Product_Tail(a, b, x, y)
+
+/* Two_Product_Presplit() is Two_Product() where one of the inputs has       */
+/*   already been split.  Avoids redundant splitting.                        */
+
+#define Two_Product_Presplit(a, b, bhi, blo, x, y) \
+  x = (REAL) (a * b); \
+  Split(a, ahi, alo); \
+  err1 = x - (ahi * bhi); \
+  err2 = err1 - (alo * bhi); \
+  err3 = err2 - (ahi * blo); \
+  y = (alo * blo) - err3
+
+/* Square() can be done more quickly than Two_Product().                     */
+
+#define Square_Tail(a, x, y) \
+  Split(a, ahi, alo); \
+  err1 = x - (ahi * ahi); \
+  err3 = err1 - ((ahi + ahi) * alo); \
+  y = (alo * alo) - err3
+
+#define Square(a, x, y) \
+  x = (REAL) (a * a); \
+  Square_Tail(a, x, y)
+
+/* Macros for summing expansions of various fixed lengths.  These are all    */
+/*   unrolled versions of Expansion_Sum().                                   */
+
+#define Two_One_Sum(a1, a0, b, x2, x1, x0) \
+  Two_Sum(a0, b , _i, x0); \
+  Two_Sum(a1, _i, x2, x1)
+
+#define Two_One_Diff(a1, a0, b, x2, x1, x0) \
+  Two_Diff(a0, b , _i, x0); \
+  Two_Sum( a1, _i, x2, x1)
+
+#define Two_Two_Sum(a1, a0, b1, b0, x3, x2, x1, x0) \
+  Two_One_Sum(a1, a0, b0, _j, _0, x0); \
+  Two_One_Sum(_j, _0, b1, x3, x2, x1)
+
+#define Two_Two_Diff(a1, a0, b1, b0, x3, x2, x1, x0) \
+  Two_One_Diff(a1, a0, b0, _j, _0, x0); \
+  Two_One_Diff(_j, _0, b1, x3, x2, x1)
+
+/*****************************************************************************/
+/*                                                                           */
+/*  exactinit()   Initialize the variables used for exact arithmetic.        */
+/*                                                                           */
+/*  `epsilon' is the largest power of two such that 1.0 + epsilon = 1.0 in   */
+/*  floating-point arithmetic.  `epsilon' bounds the relative roundoff       */
+/*  error.  It is used for floating-point error analysis.                    */
+/*                                                                           */
+/*  `splitter' is used to split floating-point numbers into two half-        */
+/*  length significands for exact multiplication.                            */
+/*                                                                           */
+/*  I imagine that a highly optimizing compiler might be too smart for its   */
+/*  own good, and somehow cause this routine to fail, if it pretends that    */
+/*  floating-point arithmetic is too much like real arithmetic.              */
+/*                                                                           */
+/*  Don't change this routine unless you fully understand it.                */
+/*                                                                           */
+/*****************************************************************************/
+
+void exactinit()
+{
+  REAL half;
+  REAL check, lastcheck;
+  int every_other;
+
+  every_other = 1;
+  half = 0.5;
+  epsilon = 1.0;
+  splitter = 1.0;
+  check = 1.0;
+  /* Repeatedly divide `epsilon' by two until it is too small to add to      */
+  /*   one without causing roundoff.  (Also check if the sum is equal to     */
+  /*   the previous sum, for machines that round up instead of using exact   */
+  /*   rounding.  Not that these routines will work on such machines anyway. */
+  do {
+    lastcheck = check;
+    epsilon *= half;
+    if (every_other) {
+      splitter *= 2.0;
+    }
+    every_other = !every_other;
+    check = (REAL)(1.0 + epsilon);
+  } while ((check != 1.0) && (check != lastcheck));
+  splitter += 1.0;
+  if (verbose > 1) {
+    printf("Floating point roundoff is of magnitude %.17g\n", epsilon);
+    printf("Floating point splitter is %.17g\n", splitter);
+  }
+  /* Error bounds for orientation and incircle tests. */
+  resulterrbound = (REAL)((3.0 + 8.0 * epsilon) * epsilon);
+  ccwerrboundA = (REAL)((3.0 + 16.0 * epsilon) * epsilon);
+  ccwerrboundB = (REAL)((2.0 + 12.0 * epsilon) * epsilon);
+  ccwerrboundC = (REAL)((9.0 + 64.0 * epsilon) * epsilon * epsilon);
+  iccerrboundA = (REAL)((10.0 + 96.0 * epsilon) * epsilon);
+  iccerrboundB = (REAL)((4.0 + 48.0 * epsilon) * epsilon);
+  iccerrboundC = (REAL)((44.0 + 576.0 * epsilon) * epsilon * epsilon);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  fast_expansion_sum_zeroelim()   Sum two expansions, eliminating zero     */
+/*                                  components from the output expansion.    */
+/*                                                                           */
+/*  Sets h = e + f.  See my Robust Predicates paper for details.             */
+/*                                                                           */
+/*  If round-to-even is used (as with IEEE 754), maintains the strongly      */
+/*  nonoverlapping property.  (That is, if e is strongly nonoverlapping, h   */
+/*  will be also.)  Does NOT maintain the nonoverlapping or nonadjacent      */
+/*  properties.                                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+int fast_expansion_sum_zeroelim(elen, e, flen, f, h)  /* h cannot be e or f. */
+int elen;
+REAL *e;
+int flen;
+REAL *f;
+REAL *h;
+{
+  REAL Q;
+  INEXACT REAL Qnew;
+  INEXACT REAL hh;
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  int eindex, findex, hindex;
+  REAL enow, fnow;
+
+  enow = e[0];
+  fnow = f[0];
+  eindex = findex = 0;
+  if ((fnow > enow) == (fnow > -enow)) {
+    Q = enow;
+    enow = e[++eindex];
+  } else {
+    Q = fnow;
+    fnow = f[++findex];
+  }
+  hindex = 0;
+  if ((eindex < elen) && (findex < flen)) {
+    if ((fnow > enow) == (fnow > -enow)) {
+      Fast_Two_Sum(enow, Q, Qnew, hh);
+      enow = e[++eindex];
+    } else {
+      Fast_Two_Sum(fnow, Q, Qnew, hh);
+      fnow = f[++findex];
+    }
+    Q = Qnew;
+    if (hh != 0.0) {
+      h[hindex++] = hh;
+    }
+    while ((eindex < elen) && (findex < flen)) {
+      if ((fnow > enow) == (fnow > -enow)) {
+        Two_Sum(Q, enow, Qnew, hh);
+        enow = e[++eindex];
+      } else {
+        Two_Sum(Q, fnow, Qnew, hh);
+        fnow = f[++findex];
+      }
+      Q = Qnew;
+      if (hh != 0.0) {
+        h[hindex++] = hh;
+      }
+    }
+  }
+  while (eindex < elen) {
+    Two_Sum(Q, enow, Qnew, hh);
+    enow = e[++eindex];
+    Q = Qnew;
+    if (hh != 0.0) {
+      h[hindex++] = hh;
+    }
+  }
+  while (findex < flen) {
+    Two_Sum(Q, fnow, Qnew, hh);
+    fnow = f[++findex];
+    Q = Qnew;
+    if (hh != 0.0) {
+      h[hindex++] = hh;
+    }
+  }
+  if ((Q != 0.0) || (hindex == 0)) {
+    h[hindex++] = Q;
+  }
+  return hindex;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  scale_expansion_zeroelim()   Multiply an expansion by a scalar,          */
+/*                               eliminating zero components from the        */
+/*                               output expansion.                           */
+/*                                                                           */
+/*  Sets h = be.  See my Robust Predicates paper for details.                */
+/*                                                                           */
+/*  Maintains the nonoverlapping property.  If round-to-even is used (as     */
+/*  with IEEE 754), maintains the strongly nonoverlapping and nonadjacent    */
+/*  properties as well.  (That is, if e has one of these properties, so      */
+/*  will h.)                                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+int scale_expansion_zeroelim(elen, e, b, h)   /* e and h cannot be the same. */
+int elen;
+REAL *e;
+REAL b;
+REAL *h;
+{
+  INEXACT REAL Q, sum;
+  REAL hh;
+  INEXACT REAL product1;
+  REAL product0;
+  int eindex, hindex;
+  REAL enow;
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  INEXACT REAL c;
+  INEXACT REAL abig;
+  REAL ahi, alo, bhi, blo;
+  REAL err1, err2, err3;
+
+  Split(b, bhi, blo);
+  Two_Product_Presplit(e[0], b, bhi, blo, Q, hh);
+  hindex = 0;
+  if (hh != 0) {
+    h[hindex++] = hh;
+  }
+  for (eindex = 1; eindex < elen; eindex++) {
+    enow = e[eindex];
+    Two_Product_Presplit(enow, b, bhi, blo, product1, product0);
+    Two_Sum(Q, product0, sum, hh);
+    if (hh != 0) {
+      h[hindex++] = hh;
+    }
+    Fast_Two_Sum(product1, sum, Q, hh);
+    if (hh != 0) {
+      h[hindex++] = hh;
+    }
+  }
+  if ((Q != 0.0) || (hindex == 0)) {
+    h[hindex++] = Q;
+  }
+  return hindex;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  estimate()   Produce a one-word estimate of an expansion's value.        */
+/*                                                                           */
+/*  See my Robust Predicates paper for details.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+REAL estimate(elen, e)
+int elen;
+REAL *e;
+{
+  REAL Q;
+  int eindex;
+
+  Q = e[0];
+  for (eindex = 1; eindex < elen; eindex++) {
+    Q += e[eindex];
+  }
+  return Q;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  counterclockwise()   Return a positive value if the points pa, pb, and   */
+/*                       pc occur in counterclockwise order; a negative      */
+/*                       value if they occur in clockwise order; and zero    */
+/*                       if they are collinear.  The result is also a rough  */
+/*                       approximation of twice the signed area of the       */
+/*                       triangle defined by the three points.               */
+/*                                                                           */
+/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
+/*  result returned is the determinant of a matrix.  This determinant is     */
+/*  computed adaptively, in the sense that exact arithmetic is used only to  */
+/*  the degree it is needed to ensure that the returned value has the        */
+/*  correct sign.  Hence, this function is usually quite fast, but will run  */
+/*  more slowly when the input points are collinear or nearly so.            */
+/*                                                                           */
+/*  See my Robust Predicates paper for details.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+REAL counterclockwiseadapt(pa, pb, pc, detsum)
+point pa;
+point pb;
+point pc;
+REAL detsum;
+{
+  INEXACT REAL acx, acy, bcx, bcy;
+  REAL acxtail, acytail, bcxtail, bcytail;
+  INEXACT REAL detleft, detright;
+  REAL detlefttail, detrighttail;
+  REAL det, errbound;
+  REAL B[4], C1[8], C2[12], D[16];
+  INEXACT REAL B3;
+  int C1length, C2length, Dlength;
+  REAL u[4];
+  INEXACT REAL u3;
+  INEXACT REAL s1, t1;
+  REAL s0, t0;
+
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  INEXACT REAL c;
+  INEXACT REAL abig;
+  REAL ahi, alo, bhi, blo;
+  REAL err1, err2, err3;
+  INEXACT REAL _i, _j;
+  REAL _0;
+
+  acx = (REAL) (pa[0] - pc[0]);
+  bcx = (REAL) (pb[0] - pc[0]);
+  acy = (REAL) (pa[1] - pc[1]);
+  bcy = (REAL) (pb[1] - pc[1]);
+
+  Two_Product(acx, bcy, detleft, detlefttail);
+  Two_Product(acy, bcx, detright, detrighttail);
+
+  Two_Two_Diff(detleft, detlefttail, detright, detrighttail,
+               B3, B[2], B[1], B[0]);
+  B[3] = B3;
+
+  det = estimate(4, B);
+  errbound = (REAL)(ccwerrboundB * detsum);
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  Two_Diff_Tail(pa[0], pc[0], acx, acxtail);
+  Two_Diff_Tail(pb[0], pc[0], bcx, bcxtail);
+  Two_Diff_Tail(pa[1], pc[1], acy, acytail);
+  Two_Diff_Tail(pb[1], pc[1], bcy, bcytail);
+
+  if ((acxtail == 0.0) && (acytail == 0.0)
+      && (bcxtail == 0.0) && (bcytail == 0.0)) {
+    return det;
+  }
+
+  errbound = (REAL)(ccwerrboundC * detsum + resulterrbound * Absolute(det));
+  det += (acx * bcytail + bcy * acxtail)
+       - (acy * bcxtail + bcx * acytail);
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  Two_Product(acxtail, bcy, s1, s0);
+  Two_Product(acytail, bcx, t1, t0);
+  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
+  u[3] = u3;
+  C1length = fast_expansion_sum_zeroelim(4, B, 4, u, C1);
+
+  Two_Product(acx, bcytail, s1, s0);
+  Two_Product(acy, bcxtail, t1, t0);
+  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
+  u[3] = u3;
+  C2length = fast_expansion_sum_zeroelim(C1length, C1, 4, u, C2);
+
+  Two_Product(acxtail, bcytail, s1, s0);
+  Two_Product(acytail, bcxtail, t1, t0);
+  Two_Two_Diff(s1, s0, t1, t0, u3, u[2], u[1], u[0]);
+  u[3] = u3;
+  Dlength = fast_expansion_sum_zeroelim(C2length, C2, 4, u, D);
+
+  return(D[Dlength - 1]);
+}
+
+REAL counterclockwise(pa, pb, pc)
+point pa;
+point pb;
+point pc;
+{
+  REAL detleft, detright, det;
+  REAL detsum, errbound;
+
+  counterclockcount++;
+
+  detleft = (pa[0] - pc[0]) * (pb[1] - pc[1]);
+  detright = (pa[1] - pc[1]) * (pb[0] - pc[0]);
+  det = detleft - detright;
+
+  if (noexact) {
+    return det;
+  }
+
+  if (detleft > 0.0) {
+    if (detright <= 0.0) {
+      return det;
+    } else {
+      detsum = detleft + detright;
+    }
+  } else if (detleft < 0.0) {
+    if (detright >= 0.0) {
+      return det;
+    } else {
+      detsum = -detleft - detright;
+    }
+  } else {
+    return det;
+  }
+
+  errbound = ccwerrboundA * detsum;
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  return counterclockwiseadapt(pa, pb, pc, detsum);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  incircle()   Return a positive value if the point pd lies inside the     */
+/*               circle passing through pa, pb, and pc; a negative value if  */
+/*               it lies outside; and zero if the four points are cocircular.*/
+/*               The points pa, pb, and pc must be in counterclockwise       */
+/*               order, or the sign of the result will be reversed.          */
+/*                                                                           */
+/*  Uses exact arithmetic if necessary to ensure a correct answer.  The      */
+/*  result returned is the determinant of a matrix.  This determinant is     */
+/*  computed adaptively, in the sense that exact arithmetic is used only to  */
+/*  the degree it is needed to ensure that the returned value has the        */
+/*  correct sign.  Hence, this function is usually quite fast, but will run  */
+/*  more slowly when the input points are cocircular or nearly so.           */
+/*                                                                           */
+/*  See my Robust Predicates paper for details.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+REAL incircleadapt(pa, pb, pc, pd, permanent)
+point pa;
+point pb;
+point pc;
+point pd;
+REAL permanent;
+{
+  INEXACT REAL adx, bdx, cdx, ady, bdy, cdy;
+  REAL det, errbound;
+
+  INEXACT REAL bdxcdy1, cdxbdy1, cdxady1, adxcdy1, adxbdy1, bdxady1;
+  REAL bdxcdy0, cdxbdy0, cdxady0, adxcdy0, adxbdy0, bdxady0;
+  REAL bc[4], ca[4], ab[4];
+  INEXACT REAL bc3, ca3, ab3;
+  REAL axbc[8], axxbc[16], aybc[8], ayybc[16], adet[32];
+  int axbclen, axxbclen, aybclen, ayybclen, alen;
+  REAL bxca[8], bxxca[16], byca[8], byyca[16], bdet[32];
+  int bxcalen, bxxcalen, bycalen, byycalen, blen;
+  REAL cxab[8], cxxab[16], cyab[8], cyyab[16], cdet[32];
+  int cxablen, cxxablen, cyablen, cyyablen, clen;
+  REAL abdet[64];
+  int ablen;
+  REAL fin1[1152], fin2[1152];
+  REAL *finnow, *finother, *finswap;
+  int finlength;
+
+  REAL adxtail, bdxtail, cdxtail, adytail, bdytail, cdytail;
+  INEXACT REAL adxadx1, adyady1, bdxbdx1, bdybdy1, cdxcdx1, cdycdy1;
+  REAL adxadx0, adyady0, bdxbdx0, bdybdy0, cdxcdx0, cdycdy0;
+  REAL aa[4], bb[4], cc[4];
+  INEXACT REAL aa3, bb3, cc3;
+  INEXACT REAL ti1, tj1;
+  REAL ti0, tj0;
+  REAL u[4], v[4];
+  INEXACT REAL u3, v3;
+  REAL temp8[8], temp16a[16], temp16b[16], temp16c[16];
+  REAL temp32a[32], temp32b[32], temp48[48], temp64[64];
+  int temp8len, temp16alen, temp16blen, temp16clen;
+  int temp32alen, temp32blen, temp48len, temp64len;
+  REAL axtbb[8], axtcc[8], aytbb[8], aytcc[8];
+  int axtbblen, axtcclen, aytbblen, aytcclen;
+  REAL bxtaa[8], bxtcc[8], bytaa[8], bytcc[8];
+  int bxtaalen, bxtcclen, bytaalen, bytcclen;
+  REAL cxtaa[8], cxtbb[8], cytaa[8], cytbb[8];
+  int cxtaalen, cxtbblen, cytaalen, cytbblen;
+  REAL axtbc[8], aytbc[8], bxtca[8], bytca[8], cxtab[8], cytab[8];
+  int axtbclen, aytbclen, bxtcalen, bytcalen, cxtablen, cytablen;
+  REAL axtbct[16], aytbct[16], bxtcat[16], bytcat[16], cxtabt[16], cytabt[16];
+  int axtbctlen, aytbctlen, bxtcatlen, bytcatlen, cxtabtlen, cytabtlen;
+  REAL axtbctt[8], aytbctt[8], bxtcatt[8];
+  REAL bytcatt[8], cxtabtt[8], cytabtt[8];
+  int axtbcttlen, aytbcttlen, bxtcattlen, bytcattlen, cxtabttlen, cytabttlen;
+  REAL abt[8], bct[8], cat[8];
+  int abtlen, bctlen, catlen;
+  REAL abtt[4], bctt[4], catt[4];
+  int abttlen, bcttlen, cattlen;
+  INEXACT REAL abtt3, bctt3, catt3;
+  REAL negate;
+
+  INEXACT REAL bvirt;
+  REAL avirt, bround, around;
+  INEXACT REAL c;
+  INEXACT REAL abig;
+  REAL ahi, alo, bhi, blo;
+  REAL err1, err2, err3;
+  INEXACT REAL _i, _j;
+  REAL _0;
+
+  adx = (REAL) (pa[0] - pd[0]);
+  bdx = (REAL) (pb[0] - pd[0]);
+  cdx = (REAL) (pc[0] - pd[0]);
+  ady = (REAL) (pa[1] - pd[1]);
+  bdy = (REAL) (pb[1] - pd[1]);
+  cdy = (REAL) (pc[1] - pd[1]);
+
+  Two_Product(bdx, cdy, bdxcdy1, bdxcdy0);
+  Two_Product(cdx, bdy, cdxbdy1, cdxbdy0);
+  Two_Two_Diff(bdxcdy1, bdxcdy0, cdxbdy1, cdxbdy0, bc3, bc[2], bc[1], bc[0]);
+  bc[3] = bc3;
+  axbclen = scale_expansion_zeroelim(4, bc, adx, axbc);
+  axxbclen = scale_expansion_zeroelim(axbclen, axbc, adx, axxbc);
+  aybclen = scale_expansion_zeroelim(4, bc, ady, aybc);
+  ayybclen = scale_expansion_zeroelim(aybclen, aybc, ady, ayybc);
+  alen = fast_expansion_sum_zeroelim(axxbclen, axxbc, ayybclen, ayybc, adet);
+
+  Two_Product(cdx, ady, cdxady1, cdxady0);
+  Two_Product(adx, cdy, adxcdy1, adxcdy0);
+  Two_Two_Diff(cdxady1, cdxady0, adxcdy1, adxcdy0, ca3, ca[2], ca[1], ca[0]);
+  ca[3] = ca3;
+  bxcalen = scale_expansion_zeroelim(4, ca, bdx, bxca);
+  bxxcalen = scale_expansion_zeroelim(bxcalen, bxca, bdx, bxxca);
+  bycalen = scale_expansion_zeroelim(4, ca, bdy, byca);
+  byycalen = scale_expansion_zeroelim(bycalen, byca, bdy, byyca);
+  blen = fast_expansion_sum_zeroelim(bxxcalen, bxxca, byycalen, byyca, bdet);
+
+  Two_Product(adx, bdy, adxbdy1, adxbdy0);
+  Two_Product(bdx, ady, bdxady1, bdxady0);
+  Two_Two_Diff(adxbdy1, adxbdy0, bdxady1, bdxady0, ab3, ab[2], ab[1], ab[0]);
+  ab[3] = ab3;
+  cxablen = scale_expansion_zeroelim(4, ab, cdx, cxab);
+  cxxablen = scale_expansion_zeroelim(cxablen, cxab, cdx, cxxab);
+  cyablen = scale_expansion_zeroelim(4, ab, cdy, cyab);
+  cyyablen = scale_expansion_zeroelim(cyablen, cyab, cdy, cyyab);
+  clen = fast_expansion_sum_zeroelim(cxxablen, cxxab, cyyablen, cyyab, cdet);
+
+  ablen = fast_expansion_sum_zeroelim(alen, adet, blen, bdet, abdet);
+  finlength = fast_expansion_sum_zeroelim(ablen, abdet, clen, cdet, fin1);
+
+  det = estimate(finlength, fin1);
+  errbound = (REAL)(iccerrboundB * permanent);
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  Two_Diff_Tail(pa[0], pd[0], adx, adxtail);
+  Two_Diff_Tail(pa[1], pd[1], ady, adytail);
+  Two_Diff_Tail(pb[0], pd[0], bdx, bdxtail);
+  Two_Diff_Tail(pb[1], pd[1], bdy, bdytail);
+  Two_Diff_Tail(pc[0], pd[0], cdx, cdxtail);
+  Two_Diff_Tail(pc[1], pd[1], cdy, cdytail);
+  if ((adxtail == 0.0) && (bdxtail == 0.0) && (cdxtail == 0.0)
+      && (adytail == 0.0) && (bdytail == 0.0) && (cdytail == 0.0)) {
+    return det;
+  }
+
+  errbound = (REAL)(iccerrboundC * permanent + resulterrbound * Absolute(det));
+  det += (REAL)(((adx * adx + ady * ady) * ((bdx * cdytail + cdy * bdxtail)
+                                     - (bdy * cdxtail + cdx * bdytail))
+          + 2.0 * (adx * adxtail + ady * adytail) * (bdx * cdy - bdy * cdx))
+       + ((bdx * bdx + bdy * bdy) * ((cdx * adytail + ady * cdxtail)
+                                     - (cdy * adxtail + adx * cdytail))
+          + 2.0 * (bdx * bdxtail + bdy * bdytail) * (cdx * ady - cdy * adx))
+       + ((cdx * cdx + cdy * cdy) * ((adx * bdytail + bdy * adxtail)
+                                     - (ady * bdxtail + bdx * adytail))
+          + 2.0 * (cdx * cdxtail + cdy * cdytail) * (adx * bdy - ady * bdx)));
+  if ((det >= errbound) || (-det >= errbound)) {
+    return det;
+  }
+
+  finnow = fin1;
+  finother = fin2;
+
+  if ((bdxtail != 0.0) || (bdytail != 0.0)
+      || (cdxtail != 0.0) || (cdytail != 0.0)) {
+    Square(adx, adxadx1, adxadx0);
+    Square(ady, adyady1, adyady0);
+    Two_Two_Sum(adxadx1, adxadx0, adyady1, adyady0, aa3, aa[2], aa[1], aa[0]);
+    aa[3] = aa3;
+  }
+  if ((cdxtail != 0.0) || (cdytail != 0.0)
+      || (adxtail != 0.0) || (adytail != 0.0)) {
+    Square(bdx, bdxbdx1, bdxbdx0);
+    Square(bdy, bdybdy1, bdybdy0);
+    Two_Two_Sum(bdxbdx1, bdxbdx0, bdybdy1, bdybdy0, bb3, bb[2], bb[1], bb[0]);
+    bb[3] = bb3;
+  }
+  if ((adxtail != 0.0) || (adytail != 0.0)
+      || (bdxtail != 0.0) || (bdytail != 0.0)) {
+    Square(cdx, cdxcdx1, cdxcdx0);
+    Square(cdy, cdycdy1, cdycdy0);
+    Two_Two_Sum(cdxcdx1, cdxcdx0, cdycdy1, cdycdy0, cc3, cc[2], cc[1], cc[0]);
+    cc[3] = cc3;
+  }
+
+  if (adxtail != 0.0) {
+    axtbclen = scale_expansion_zeroelim(4, bc, adxtail, axtbc);
+    temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, 2.0 * adx,
+                                          temp16a);
+
+    axtcclen = scale_expansion_zeroelim(4, cc, adxtail, axtcc);
+    temp16blen = scale_expansion_zeroelim(axtcclen, axtcc, bdy, temp16b);
+
+    axtbblen = scale_expansion_zeroelim(4, bb, adxtail, axtbb);
+    temp16clen = scale_expansion_zeroelim(axtbblen, axtbb, -cdy, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (adytail != 0.0) {
+    aytbclen = scale_expansion_zeroelim(4, bc, adytail, aytbc);
+    temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, 2.0 * ady,
+                                          temp16a);
+
+    aytbblen = scale_expansion_zeroelim(4, bb, adytail, aytbb);
+    temp16blen = scale_expansion_zeroelim(aytbblen, aytbb, cdx, temp16b);
+
+    aytcclen = scale_expansion_zeroelim(4, cc, adytail, aytcc);
+    temp16clen = scale_expansion_zeroelim(aytcclen, aytcc, -bdx, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (bdxtail != 0.0) {
+    bxtcalen = scale_expansion_zeroelim(4, ca, bdxtail, bxtca);
+    temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, 2.0 * bdx,
+                                          temp16a);
+
+    bxtaalen = scale_expansion_zeroelim(4, aa, bdxtail, bxtaa);
+    temp16blen = scale_expansion_zeroelim(bxtaalen, bxtaa, cdy, temp16b);
+
+    bxtcclen = scale_expansion_zeroelim(4, cc, bdxtail, bxtcc);
+    temp16clen = scale_expansion_zeroelim(bxtcclen, bxtcc, -ady, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (bdytail != 0.0) {
+    bytcalen = scale_expansion_zeroelim(4, ca, bdytail, bytca);
+    temp16alen = scale_expansion_zeroelim(bytcalen, bytca, 2.0 * bdy,
+                                          temp16a);
+
+    bytcclen = scale_expansion_zeroelim(4, cc, bdytail, bytcc);
+    temp16blen = scale_expansion_zeroelim(bytcclen, bytcc, adx, temp16b);
+
+    bytaalen = scale_expansion_zeroelim(4, aa, bdytail, bytaa);
+    temp16clen = scale_expansion_zeroelim(bytaalen, bytaa, -cdx, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (cdxtail != 0.0) {
+    cxtablen = scale_expansion_zeroelim(4, ab, cdxtail, cxtab);
+    temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, 2.0 * cdx,
+                                          temp16a);
+
+    cxtbblen = scale_expansion_zeroelim(4, bb, cdxtail, cxtbb);
+    temp16blen = scale_expansion_zeroelim(cxtbblen, cxtbb, ady, temp16b);
+
+    cxtaalen = scale_expansion_zeroelim(4, aa, cdxtail, cxtaa);
+    temp16clen = scale_expansion_zeroelim(cxtaalen, cxtaa, -bdy, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+  if (cdytail != 0.0) {
+    cytablen = scale_expansion_zeroelim(4, ab, cdytail, cytab);
+    temp16alen = scale_expansion_zeroelim(cytablen, cytab, 2.0 * cdy,
+                                          temp16a);
+
+    cytaalen = scale_expansion_zeroelim(4, aa, cdytail, cytaa);
+    temp16blen = scale_expansion_zeroelim(cytaalen, cytaa, bdx, temp16b);
+
+    cytbblen = scale_expansion_zeroelim(4, bb, cdytail, cytbb);
+    temp16clen = scale_expansion_zeroelim(cytbblen, cytbb, -adx, temp16c);
+
+    temp32alen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                            temp16blen, temp16b, temp32a);
+    temp48len = fast_expansion_sum_zeroelim(temp16clen, temp16c,
+                                            temp32alen, temp32a, temp48);
+    finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                            temp48, finother);
+    finswap = finnow; finnow = finother; finother = finswap;
+  }
+
+  if ((adxtail != 0.0) || (adytail != 0.0)) {
+    if ((bdxtail != 0.0) || (bdytail != 0.0)
+        || (cdxtail != 0.0) || (cdytail != 0.0)) {
+      Two_Product(bdxtail, cdy, ti1, ti0);
+      Two_Product(bdx, cdytail, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
+      u[3] = u3;
+      negate = -bdy;
+      Two_Product(cdxtail, negate, ti1, ti0);
+      negate = -bdytail;
+      Two_Product(cdx, negate, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
+      v[3] = v3;
+      bctlen = fast_expansion_sum_zeroelim(4, u, 4, v, bct);
+
+      Two_Product(bdxtail, cdytail, ti1, ti0);
+      Two_Product(cdxtail, bdytail, tj1, tj0);
+      Two_Two_Diff(ti1, ti0, tj1, tj0, bctt3, bctt[2], bctt[1], bctt[0]);
+      bctt[3] = bctt3;
+      bcttlen = 4;
+    } else {
+      bct[0] = 0.0;
+      bctlen = 1;
+      bctt[0] = 0.0;
+      bcttlen = 1;
+    }
+
+    if (adxtail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(axtbclen, axtbc, adxtail, temp16a);
+      axtbctlen = scale_expansion_zeroelim(bctlen, bct, adxtail, axtbct);
+      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, 2.0 * adx,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+      if (bdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, cc, adxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+      if (cdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, bb, -adxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+
+      temp32alen = scale_expansion_zeroelim(axtbctlen, axtbct, adxtail,
+                                            temp32a);
+      axtbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adxtail, axtbctt);
+      temp16alen = scale_expansion_zeroelim(axtbcttlen, axtbctt, 2.0 * adx,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(axtbcttlen, axtbctt, adxtail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+    if (adytail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(aytbclen, aytbc, adytail, temp16a);
+      aytbctlen = scale_expansion_zeroelim(bctlen, bct, adytail, aytbct);
+      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, 2.0 * ady,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+
+
+      temp32alen = scale_expansion_zeroelim(aytbctlen, aytbct, adytail,
+                                            temp32a);
+      aytbcttlen = scale_expansion_zeroelim(bcttlen, bctt, adytail, aytbctt);
+      temp16alen = scale_expansion_zeroelim(aytbcttlen, aytbctt, 2.0 * ady,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(aytbcttlen, aytbctt, adytail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+  }
+  if ((bdxtail != 0.0) || (bdytail != 0.0)) {
+    if ((cdxtail != 0.0) || (cdytail != 0.0)
+        || (adxtail != 0.0) || (adytail != 0.0)) {
+      Two_Product(cdxtail, ady, ti1, ti0);
+      Two_Product(cdx, adytail, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
+      u[3] = u3;
+      negate = -cdy;
+      Two_Product(adxtail, negate, ti1, ti0);
+      negate = -cdytail;
+      Two_Product(adx, negate, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
+      v[3] = v3;
+      catlen = fast_expansion_sum_zeroelim(4, u, 4, v, cat);
+
+      Two_Product(cdxtail, adytail, ti1, ti0);
+      Two_Product(adxtail, cdytail, tj1, tj0);
+      Two_Two_Diff(ti1, ti0, tj1, tj0, catt3, catt[2], catt[1], catt[0]);
+      catt[3] = catt3;
+      cattlen = 4;
+    } else {
+      cat[0] = 0.0;
+      catlen = 1;
+      catt[0] = 0.0;
+      cattlen = 1;
+    }
+
+    if (bdxtail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(bxtcalen, bxtca, bdxtail, temp16a);
+      bxtcatlen = scale_expansion_zeroelim(catlen, cat, bdxtail, bxtcat);
+      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, 2.0 * bdx,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+      if (cdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, aa, bdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, cdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+      if (adytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, cc, -bdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+
+      temp32alen = scale_expansion_zeroelim(bxtcatlen, bxtcat, bdxtail,
+                                            temp32a);
+      bxtcattlen = scale_expansion_zeroelim(cattlen, catt, bdxtail, bxtcatt);
+      temp16alen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, 2.0 * bdx,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(bxtcattlen, bxtcatt, bdxtail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+    if (bdytail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(bytcalen, bytca, bdytail, temp16a);
+      bytcatlen = scale_expansion_zeroelim(catlen, cat, bdytail, bytcat);
+      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, 2.0 * bdy,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+
+
+      temp32alen = scale_expansion_zeroelim(bytcatlen, bytcat, bdytail,
+                                            temp32a);
+      bytcattlen = scale_expansion_zeroelim(cattlen, catt, bdytail, bytcatt);
+      temp16alen = scale_expansion_zeroelim(bytcattlen, bytcatt, 2.0 * bdy,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(bytcattlen, bytcatt, bdytail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+  }
+  if ((cdxtail != 0.0) || (cdytail != 0.0)) {
+    if ((adxtail != 0.0) || (adytail != 0.0)
+        || (bdxtail != 0.0) || (bdytail != 0.0)) {
+      Two_Product(adxtail, bdy, ti1, ti0);
+      Two_Product(adx, bdytail, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, u3, u[2], u[1], u[0]);
+      u[3] = u3;
+      negate = -ady;
+      Two_Product(bdxtail, negate, ti1, ti0);
+      negate = -adytail;
+      Two_Product(bdx, negate, tj1, tj0);
+      Two_Two_Sum(ti1, ti0, tj1, tj0, v3, v[2], v[1], v[0]);
+      v[3] = v3;
+      abtlen = fast_expansion_sum_zeroelim(4, u, 4, v, abt);
+
+      Two_Product(adxtail, bdytail, ti1, ti0);
+      Two_Product(bdxtail, adytail, tj1, tj0);
+      Two_Two_Diff(ti1, ti0, tj1, tj0, abtt3, abtt[2], abtt[1], abtt[0]);
+      abtt[3] = abtt3;
+      abttlen = 4;
+    } else {
+      abt[0] = 0.0;
+      abtlen = 1;
+      abtt[0] = 0.0;
+      abttlen = 1;
+    }
+
+    if (cdxtail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(cxtablen, cxtab, cdxtail, temp16a);
+      cxtabtlen = scale_expansion_zeroelim(abtlen, abt, cdxtail, cxtabt);
+      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, 2.0 * cdx,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+      if (adytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, bb, cdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, adytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+      if (bdytail != 0.0) {
+        temp8len = scale_expansion_zeroelim(4, aa, -cdxtail, temp8);
+        temp16alen = scale_expansion_zeroelim(temp8len, temp8, bdytail,
+                                              temp16a);
+        finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp16alen,
+                                                temp16a, finother);
+        finswap = finnow; finnow = finother; finother = finswap;
+      }
+
+      temp32alen = scale_expansion_zeroelim(cxtabtlen, cxtabt, cdxtail,
+                                            temp32a);
+      cxtabttlen = scale_expansion_zeroelim(abttlen, abtt, cdxtail, cxtabtt);
+      temp16alen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, 2.0 * cdx,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(cxtabttlen, cxtabtt, cdxtail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+    if (cdytail != 0.0) {
+      temp16alen = scale_expansion_zeroelim(cytablen, cytab, cdytail, temp16a);
+      cytabtlen = scale_expansion_zeroelim(abtlen, abt, cdytail, cytabt);
+      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, 2.0 * cdy,
+                                            temp32a);
+      temp48len = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp32alen, temp32a, temp48);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp48len,
+                                              temp48, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+
+
+      temp32alen = scale_expansion_zeroelim(cytabtlen, cytabt, cdytail,
+                                            temp32a);
+      cytabttlen = scale_expansion_zeroelim(abttlen, abtt, cdytail, cytabtt);
+      temp16alen = scale_expansion_zeroelim(cytabttlen, cytabtt, 2.0 * cdy,
+                                            temp16a);
+      temp16blen = scale_expansion_zeroelim(cytabttlen, cytabtt, cdytail,
+                                            temp16b);
+      temp32blen = fast_expansion_sum_zeroelim(temp16alen, temp16a,
+                                              temp16blen, temp16b, temp32b);
+      temp64len = fast_expansion_sum_zeroelim(temp32alen, temp32a,
+                                              temp32blen, temp32b, temp64);
+      finlength = fast_expansion_sum_zeroelim(finlength, finnow, temp64len,
+                                              temp64, finother);
+      finswap = finnow; finnow = finother; finother = finswap;
+    }
+  }
+
+  return finnow[finlength - 1];
+}
+
+REAL incircle(pa, pb, pc, pd)
+point pa;
+point pb;
+point pc;
+point pd;
+{
+  REAL adx, bdx, cdx, ady, bdy, cdy;
+  REAL bdxcdy, cdxbdy, cdxady, adxcdy, adxbdy, bdxady;
+  REAL alift, blift, clift;
+  REAL det;
+  REAL permanent, errbound;
+
+  incirclecount++;
+
+  adx = pa[0] - pd[0];
+  bdx = pb[0] - pd[0];
+  cdx = pc[0] - pd[0];
+  ady = pa[1] - pd[1];
+  bdy = pb[1] - pd[1];
+  cdy = pc[1] - pd[1];
+
+  bdxcdy = bdx * cdy;
+  cdxbdy = cdx * bdy;
+  alift = adx * adx + ady * ady;
+
+  cdxady = cdx * ady;
+  adxcdy = adx * cdy;
+  blift = bdx * bdx + bdy * bdy;
+
+  adxbdy = adx * bdy;
+  bdxady = bdx * ady;
+  clift = cdx * cdx + cdy * cdy;
+
+  det = alift * (bdxcdy - cdxbdy)
+      + blift * (cdxady - adxcdy)
+      + clift * (adxbdy - bdxady);
+
+  if (noexact) {
+    return det;
+  }
+
+  permanent = (Absolute(bdxcdy) + Absolute(cdxbdy)) * alift
+            + (Absolute(cdxady) + Absolute(adxcdy)) * blift
+            + (Absolute(adxbdy) + Absolute(bdxady)) * clift;
+  errbound = iccerrboundA * permanent;
+  if ((det > errbound) || (-det > errbound)) {
+    return det;
+  }
+
+  return incircleadapt(pa, pb, pc, pd, permanent);
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Determinant evaluation routines end here                  *********/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangleinit()   Initialize some variables.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangleinit()
+{
+  points.maxitems = triangles.maxitems = shelles.maxitems = viri.maxitems =
+    badsegments.maxitems = badtriangles.maxitems = splaynodes.maxitems = 0l;
+  points.itembytes = triangles.itembytes = shelles.itembytes = viri.itembytes =
+    badsegments.itembytes = badtriangles.itembytes = splaynodes.itembytes = 0;
+  recenttri.tri = (triangle *) NULL;    /* No triangle has been visited yet. */
+  samples = 1;            /* Point location should take at least one sample. */
+  checksegments = 0;      /* There are no segments in the triangulation yet. */
+  incirclecount = counterclockcount = hyperbolacount = 0;
+  circumcentercount = circletopcount = 0;
+  randomseed = 1;
+
+  exactinit();                     /* Initialize exact arithmetic constants. */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  randomnation()   Generate a random number between 0 and `choices' - 1.   */
+/*                                                                           */
+/*  This is a simple linear congruential random number generator.  Hence, it */
+/*  is a bad random number generator, but good enough for most randomized    */
+/*  geometric algorithms.                                                    */
+/*                                                                           */
+/*****************************************************************************/
+
+unsigned long randomnation(choices)
+unsigned int choices;
+{
+  randomseed = (randomseed * 1366l + 150889l) % 714025l;
+  return randomseed / (714025l / choices + 1);
+}
+
+/********* Mesh quality testing routines begin here                  *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  checkmesh()   Test the mesh for topological consistency.                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+void checkmesh()
+{
+  struct triedge triangleloop;
+  struct triedge oppotri, oppooppotri;
+  point triorg, tridest, triapex;
+  point oppoorg, oppodest;
+  int horrors;
+  int saveexact;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  /* Temporarily turn on exact arithmetic if it's off. */
+  saveexact = noexact;
+  noexact = 0;
+  if (!quiet) {
+    printf("  Checking consistency of mesh...\n");
+  }
+  horrors = 0;
+  /* Run through the list of triangles, checking each one. */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* Check all three edges of the triangle. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      org(triangleloop, triorg);
+      dest(triangleloop, tridest);
+      if (triangleloop.orient == 0) {       /* Only test for inversion once. */
+        /* Test if the triangle is flat or inverted. */
+        apex(triangleloop, triapex);
+        if (counterclockwise(triorg, tridest, triapex) <= 0.0) {
+          printf("  !! !! Inverted ");
+          printtriangle(&triangleloop);
+          horrors++;
+        }
+      }
+      /* Find the neighboring triangle on this edge. */
+      sym(triangleloop, oppotri);
+      if (oppotri.tri != dummytri) {
+        /* Check that the triangle's neighbor knows it's a neighbor. */
+        sym(oppotri, oppooppotri);
+        if ((triangleloop.tri != oppooppotri.tri)
+            || (triangleloop.orient != oppooppotri.orient)) {
+          printf("  !! !! Asymmetric triangle-triangle bond:\n");
+          if (triangleloop.tri == oppooppotri.tri) {
+            printf("   (Right triangle, wrong orientation)\n");
+          }
+          printf("    First ");
+          printtriangle(&triangleloop);
+          printf("    Second (nonreciprocating) ");
+          printtriangle(&oppotri);
+          horrors++;
+        }
+        /* Check that both triangles agree on the identities */
+        /*   of their shared vertices.                       */
+        org(oppotri, oppoorg);
+        dest(oppotri, oppodest);
+        if ((triorg != oppodest) || (tridest != oppoorg)) {
+          printf("  !! !! Mismatched edge coordinates between two triangles:\n"
+                 );
+          printf("    First mismatched ");
+          printtriangle(&triangleloop);
+          printf("    Second mismatched ");
+          printtriangle(&oppotri);
+          horrors++;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+  if (horrors == 0) {
+    if (!quiet) {
+      printf("  In my studied opinion, the mesh appears to be consistent.\n");
+    }
+  } else if (horrors == 1) {
+    printf("  !! !! !! !! Precisely one festering wound discovered.\n");
+  } else {
+    printf("  !! !! !! !! %d abominations witnessed.\n", horrors);
+  }
+  /* Restore the status of exact arithmetic. */
+  noexact = saveexact;
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  checkdelaunay()   Ensure that the mesh is (constrained) Delaunay.        */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+void checkdelaunay()
+{
+  struct triedge triangleloop;
+  struct triedge oppotri;
+  struct edge opposhelle;
+  point triorg, tridest, triapex;
+  point oppoapex;
+  int shouldbedelaunay;
+  int horrors;
+  int saveexact;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  /* Temporarily turn on exact arithmetic if it's off. */
+  saveexact = noexact;
+  noexact = 0;
+  if (!quiet) {
+    printf("  Checking Delaunay property of mesh...\n");
+  }
+  horrors = 0;
+  /* Run through the list of triangles, checking each one. */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* Check all three edges of the triangle. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      org(triangleloop, triorg);
+      dest(triangleloop, tridest);
+      apex(triangleloop, triapex);
+      sym(triangleloop, oppotri);
+      apex(oppotri, oppoapex);
+      /* Only test that the edge is locally Delaunay if there is an   */
+      /*   adjoining triangle whose pointer is larger (to ensure that */
+      /*   each pair isn't tested twice).                             */
+      shouldbedelaunay = (oppotri.tri != dummytri)
+            && (triapex != (point) NULL) && (oppoapex != (point) NULL)
+            && (triangleloop.tri < oppotri.tri);
+      if (checksegments && shouldbedelaunay) {
+        /* If a shell edge separates the triangles, then the edge is */
+        /*   constrained, so no local Delaunay test should be done.  */
+        tspivot(triangleloop, opposhelle);
+        if (opposhelle.sh != dummysh){
+          shouldbedelaunay = 0;
+        }
+      }
+      if (shouldbedelaunay) {
+        if (incircle(triorg, tridest, triapex, oppoapex) > 0.0) {
+          printf("  !! !! Non-Delaunay pair of triangles:\n");
+          printf("    First non-Delaunay ");
+          printtriangle(&triangleloop);
+          printf("    Second non-Delaunay ");
+          printtriangle(&oppotri);
+          horrors++;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+  if (horrors == 0) {
+    if (!quiet) {
+      printf(
+  "  By virtue of my perceptive intelligence, I declare the mesh Delaunay.\n");
+    }
+  } else if (horrors == 1) {
+    printf(
+         "  !! !! !! !! Precisely one terrifying transgression identified.\n");
+  } else {
+    printf("  !! !! !! !! %d obscenities viewed with horror.\n", horrors);
+  }
+  /* Restore the status of exact arithmetic. */
+  noexact = saveexact;
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  enqueuebadtri()   Add a bad triangle to the end of a queue.              */
+/*                                                                           */
+/*  The queue is actually a set of 64 queues.  I use multiple queues to give */
+/*  priority to smaller angles.  I originally implemented a heap, but the    */
+/*  queues are (to my surprise) much faster.                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void enqueuebadtri(instri, angle, insapex, insorg, insdest)
+struct triedge *instri;
+REAL angle;
+point insapex;
+point insorg;
+point insdest;
+{
+  struct badface *newface;
+  int queuenumber;
+
+  if (verbose > 2) {
+    printf("  Queueing bad triangle:\n");
+    printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", insorg[0],
+           insorg[1], insdest[0], insdest[1], insapex[0], insapex[1]);
+  }
+  /* Allocate space for the bad triangle. */
+  newface = (struct badface *) poolalloc(&badtriangles);
+  triedgecopy(*instri, newface->badfacetri);
+  newface->key = angle;
+  newface->faceapex = insapex;
+  newface->faceorg = insorg;
+  newface->facedest = insdest;
+  newface->nextface = (struct badface *) NULL;
+  /* Determine the appropriate queue to put the bad triangle into. */
+  if (angle > 0.6) {
+    queuenumber = (int) (160.0 * (angle - 0.6));
+    if (queuenumber > 63) {
+      queuenumber = 63;
+    }
+  } else {
+    /* It's not a bad angle; put the triangle in the lowest-priority queue. */
+    queuenumber = 0;
+  }
+  /* Add the triangle to the end of a queue. */
+  *queuetail[queuenumber] = newface;
+  /* Maintain a pointer to the NULL pointer at the end of the queue. */
+  queuetail[queuenumber] = &newface->nextface;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  dequeuebadtri()   Remove a triangle from the front of the queue.         */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+struct badface *dequeuebadtri()
+{
+  struct badface *result;
+  int queuenumber;
+
+  /* Look for a nonempty queue. */
+  for (queuenumber = 63; queuenumber >= 0; queuenumber--) {
+    result = queuefront[queuenumber];
+    if (result != (struct badface *) NULL) {
+      /* Remove the triangle from the queue. */
+      queuefront[queuenumber] = result->nextface;
+      /* Maintain a pointer to the NULL pointer at the end of the queue. */
+      if (queuefront[queuenumber] == (struct badface *) NULL) {
+        queuetail[queuenumber] = &queuefront[queuenumber];
+      }
+      return result;
+    }
+  }
+  return (struct badface *) NULL;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  checkedge4encroach()   Check a segment to see if it is encroached; add   */
+/*                         it to the list if it is.                          */
+/*                                                                           */
+/*  An encroached segment is an unflippable edge that has a point in its     */
+/*  diametral circle (that is, it faces an angle greater than 90 degrees).   */
+/*  This definition is due to Ruppert.                                       */
+/*                                                                           */
+/*  Returns a nonzero value if the edge is encroached.                       */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+int checkedge4encroach(testedge)
+struct edge *testedge;
+{
+  struct triedge neighbortri;
+  struct edge testsym;
+  struct edge *badedge;
+  int addtolist;
+  int sides;
+  point eorg, edest, eapex;
+  triangle ptr;                     /* Temporary variable used by stpivot(). */
+
+  addtolist = 0;
+  sides = 0;
+
+  sorg(*testedge, eorg);
+  sdest(*testedge, edest);
+  /* Check one neighbor of the shell edge. */
+  stpivot(*testedge, neighbortri);
+  /* Does the neighbor exist, or is this a boundary edge? */
+  if (neighbortri.tri != dummytri) {
+    sides++;
+    /* Find a vertex opposite this edge. */
+    apex(neighbortri, eapex);
+    /* Check whether the vertex is inside the diametral circle of the  */
+    /*   shell edge.  Pythagoras' Theorem is used to check whether the */
+    /*   angle at the vertex is greater than 90 degrees.               */
+    if (eapex[0] * (eorg[0] + edest[0]) + eapex[1] * (eorg[1] + edest[1]) >
+        eapex[0] * eapex[0] + eorg[0] * edest[0] +
+        eapex[1] * eapex[1] + eorg[1] * edest[1]) {
+      addtolist = 1;
+    }
+  }
+  /* Check the other neighbor of the shell edge. */
+  ssym(*testedge, testsym);
+  stpivot(testsym, neighbortri);
+  /* Does the neighbor exist, or is this a boundary edge? */
+  if (neighbortri.tri != dummytri) {
+    sides++;
+    /* Find the other vertex opposite this edge. */
+    apex(neighbortri, eapex);
+    /* Check whether the vertex is inside the diametral circle of the  */
+    /*   shell edge.  Pythagoras' Theorem is used to check whether the */
+    /*   angle at the vertex is greater than 90 degrees.               */
+    if (eapex[0] * (eorg[0] + edest[0]) +
+        eapex[1] * (eorg[1] + edest[1]) >
+        eapex[0] * eapex[0] + eorg[0] * edest[0] +
+        eapex[1] * eapex[1] + eorg[1] * edest[1]) {
+      addtolist += 2;
+    }
+  }
+
+  if (addtolist && (!nobisect || ((nobisect == 1) && (sides == 2)))) {
+    if (verbose > 2) {
+      printf("  Queueing encroached segment (%.12g, %.12g) (%.12g, %.12g).\n",
+             eorg[0], eorg[1], edest[0], edest[1]);
+    }
+    /* Add the shell edge to the list of encroached segments. */
+    /*   Be sure to get the orientation right.                */
+    badedge = (struct edge *) poolalloc(&badsegments);
+    if (addtolist == 1) {
+      shellecopy(*testedge, *badedge);
+    } else {
+      shellecopy(testsym, *badedge);
+    }
+  }
+  return addtolist;
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  testtriangle()   Test a face for quality measures.                       */
+/*                                                                           */
+/*  Tests a triangle to see if it satisfies the minimum angle condition and  */
+/*  the maximum area condition.  Triangles that aren't up to spec are added  */
+/*  to the bad triangle queue.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void testtriangle(testtri)
+struct triedge *testtri;
+{
+  struct triedge sametesttri;
+  struct edge edge1, edge2;
+  point torg, tdest, tapex;
+  point anglevertex;
+  REAL dxod, dyod, dxda, dyda, dxao, dyao;
+  REAL dxod2, dyod2, dxda2, dyda2, dxao2, dyao2;
+  REAL apexlen, orglen, destlen;
+  REAL angle;
+  REAL area;
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  org(*testtri, torg);
+  dest(*testtri, tdest);
+  apex(*testtri, tapex);
+  dxod = torg[0] - tdest[0];
+  dyod = torg[1] - tdest[1];
+  dxda = tdest[0] - tapex[0];
+  dyda = tdest[1] - tapex[1];
+  dxao = tapex[0] - torg[0];
+  dyao = tapex[1] - torg[1];
+  dxod2 = dxod * dxod;
+  dyod2 = dyod * dyod;
+  dxda2 = dxda * dxda;
+  dyda2 = dyda * dyda;
+  dxao2 = dxao * dxao;
+  dyao2 = dyao * dyao;
+  /* Find the lengths of the triangle's three edges. */
+  apexlen = dxod2 + dyod2;
+  orglen = dxda2 + dyda2;
+  destlen = dxao2 + dyao2;
+  if ((apexlen < orglen) && (apexlen < destlen)) {
+    /* The edge opposite the apex is shortest. */
+    /* Find the square of the cosine of the angle at the apex. */
+    angle = dxda * dxao + dyda * dyao;
+    angle = angle * angle / (orglen * destlen);
+    anglevertex = tapex;
+    lnext(*testtri, sametesttri);
+    tspivot(sametesttri, edge1);
+    lnextself(sametesttri);
+    tspivot(sametesttri, edge2);
+  } else if (orglen < destlen) {
+    /* The edge opposite the origin is shortest. */
+    /* Find the square of the cosine of the angle at the origin. */
+    angle = dxod * dxao + dyod * dyao;
+    angle = angle * angle / (apexlen * destlen);
+    anglevertex = torg;
+    tspivot(*testtri, edge1);
+    lprev(*testtri, sametesttri);
+    tspivot(sametesttri, edge2);
+  } else {
+    /* The edge opposite the destination is shortest. */
+    /* Find the square of the cosine of the angle at the destination. */
+    angle = dxod * dxda + dyod * dyda;
+    angle = angle * angle / (apexlen * orglen);
+    anglevertex = tdest;
+    tspivot(*testtri, edge1);
+    lnext(*testtri, sametesttri);
+    tspivot(sametesttri, edge2);
+  }
+  /* Check if both edges that form the angle are segments. */
+  if ((edge1.sh != dummysh) && (edge2.sh != dummysh)) {
+    /* The angle is a segment intersection. */
+    if ((angle > 0.9924) && !quiet) {                  /* Roughly 5 degrees. */
+      if (angle > 1.0) {
+        /* Beware of a floating exception in acos(). */
+        angle = 1.0;
+      }
+      /* Find the actual angle in degrees, for printing. */
+      angle = acos(sqrt(angle)) * (180.0 / PI);
+      printf(
+      "Warning:  Small angle (%.4g degrees) between segments at point\n",
+             angle);
+      printf("  (%.12g, %.12g)\n", anglevertex[0], anglevertex[1]);
+    }
+    /* Don't add this bad triangle to the list; there's nothing that */
+    /*   can be done about a small angle between two segments.       */
+    angle = 0.0;
+  }
+  /* Check whether the angle is smaller than permitted. */
+  if (angle > goodangle) {
+    /* Add this triangle to the list of bad triangles. */
+    enqueuebadtri(testtri, angle, tapex, torg, tdest);
+    return;
+  }
+  if (vararea || fixedarea) {
+    /* Check whether the area is larger than permitted. */
+    area = 0.5 * (dxod * dyda - dyod * dxda);
+    if (fixedarea && (area > maxarea)) {
+      /* Add this triangle to the list of bad triangles. */
+      enqueuebadtri(testtri, angle, tapex, torg, tdest);
+    } else if (vararea) {
+      /* Nonpositive area constraints are treated as unconstrained. */
+      if ((area > areabound(*testtri)) && (areabound(*testtri) > 0.0)) {
+        /* Add this triangle to the list of bad triangles. */
+        enqueuebadtri(testtri, angle, tapex, torg, tdest);
+      }
+    }
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh quality testing routines end here                    *********/
+
+/********* Point location routines begin here                        *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  makepointmap()   Construct a mapping from points to triangles to improve  */
+/*                  the speed of point location for segment insertion.       */
+/*                                                                           */
+/*  Traverses all the triangles, and provides each corner of each triangle   */
+/*  with a pointer to that triangle.  Of course, pointers will be            */
+/*  overwritten by other pointers because (almost) each point is a corner    */
+/*  of several triangles, but in the end every point will point to some      */
+/*  triangle that contains it.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+void makepointmap()
+{
+  struct triedge triangleloop;
+  point triorg;
+
+  if (verbose) {
+    printf("    Constructing mapping from points to triangles.\n");
+  }
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* Check all three points of the triangle. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      org(triangleloop, triorg);
+      setpoint2tri(triorg, encode(triangleloop));
+    }
+    triangleloop.tri = triangletraverse();
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  preciselocate()   Find a triangle or edge containing a given point.      */
+/*                                                                           */
+/*  Begins its search from `searchtri'.  It is important that `searchtri'    */
+/*  be a handle with the property that `searchpoint' is strictly to the left */
+/*  of the edge denoted by `searchtri', or is collinear with that edge and   */
+/*  does not intersect that edge.  (In particular, `searchpoint' should not  */
+/*  be the origin or destination of that edge.)                              */
+/*                                                                           */
+/*  These conditions are imposed because preciselocate() is normally used in */
+/*  one of two situations:                                                   */
+/*                                                                           */
+/*  (1)  To try to find the location to insert a new point.  Normally, we    */
+/*       know an edge that the point is strictly to the left of.  In the     */
+/*       incremental Delaunay algorithm, that edge is a bounding box edge.   */
+/*       In Ruppert's Delaunay refinement algorithm for quality meshing,     */
+/*       that edge is the shortest edge of the triangle whose circumcenter   */
+/*       is being inserted.                                                  */
+/*                                                                           */
+/*  (2)  To try to find an existing point.  In this case, any edge on the    */
+/*       convex hull is a good starting edge.  The possibility that the      */
+/*       vertex one seeks is an endpoint of the starting edge must be        */
+/*       screened out before preciselocate() is called.                      */
+/*                                                                           */
+/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
+/*                                                                           */
+/*  This implementation differs from that given by Guibas and Stolfi.  It    */
+/*  walks from triangle to triangle, crossing an edge only if `searchpoint'  */
+/*  is on the other side of the line containing that edge.  After entering   */
+/*  a triangle, there are two edges by which one can leave that triangle.    */
+/*  If both edges are valid (`searchpoint' is on the other side of both      */
+/*  edges), one of the two is chosen by drawing a line perpendicular to      */
+/*  the entry edge (whose endpoints are `forg' and `fdest') passing through  */
+/*  `fapex'.  Depending on which side of this perpendicular `searchpoint'    */
+/*  falls on, an exit edge is chosen.                                        */
+/*                                                                           */
+/*  This implementation is empirically faster than the Guibas and Stolfi     */
+/*  point location routine (which I originally used), which tends to spiral  */
+/*  in toward its target.                                                    */
+/*                                                                           */
+/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
+/*  is a handle whose origin is the existing vertex.                         */
+/*                                                                           */
+/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
+/*  handle whose primary edge is the edge on which the point lies.           */
+/*                                                                           */
+/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
+/*  `searchtri' is a handle on the triangle that contains the point.         */
+/*                                                                           */
+/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
+/*  handle whose primary edge the point is to the right of.  This might      */
+/*  occur when the circumcenter of a triangle falls just slightly outside    */
+/*  the mesh due to floating-point roundoff error.  It also occurs when      */
+/*  seeking a hole or region point that a foolish user has placed outside    */
+/*  the mesh.                                                                */
+/*                                                                           */
+/*  WARNING:  This routine is designed for convex triangulations, and will   */
+/*  not generally work after the holes and concavities have been carved.     */
+/*  However, it can still be used to find the circumcenter of a triangle, as */
+/*  long as the search is begun from the triangle in question.               */
+/*                                                                           */
+/*****************************************************************************/
+
+enum locateresult preciselocate(searchpoint, searchtri)
+point searchpoint;
+struct triedge *searchtri;
+{
+  struct triedge backtracktri;
+  point forg, fdest, fapex;
+  point swappoint;
+  REAL orgorient, destorient;
+  int moveleft;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose > 2) {
+    printf("  Searching for point (%.12g, %.12g).\n",
+           searchpoint[0], searchpoint[1]);
+  }
+  /* Where are we? */
+  org(*searchtri, forg);
+  dest(*searchtri, fdest);
+  apex(*searchtri, fapex);
+  while (1) {
+    if (verbose > 2) {
+      printf("    At (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+             forg[0], forg[1], fdest[0], fdest[1], fapex[0], fapex[1]);
+    }
+    /* Check whether the apex is the point we seek. */
+    if ((fapex[0] == searchpoint[0]) && (fapex[1] == searchpoint[1])) {
+      lprevself(*searchtri);
+      return ONVERTEX;
+    }
+    /* Does the point lie on the other side of the line defined by the */
+    /*   triangle edge opposite the triangle's destination?            */
+    destorient = counterclockwise(forg, fapex, searchpoint);
+    /* Does the point lie on the other side of the line defined by the */
+    /*   triangle edge opposite the triangle's origin?                 */
+    orgorient = counterclockwise(fapex, fdest, searchpoint);
+    if (destorient > 0.0) {
+      if (orgorient > 0.0) {
+        /* Move left if the inner product of (fapex - searchpoint) and  */
+        /*   (fdest - forg) is positive.  This is equivalent to drawing */
+        /*   a line perpendicular to the line (forg, fdest) passing     */
+        /*   through `fapex', and determining which side of this line   */
+        /*   `searchpoint' falls on.                                    */
+        moveleft = (fapex[0] - searchpoint[0]) * (fdest[0] - forg[0]) +
+                   (fapex[1] - searchpoint[1]) * (fdest[1] - forg[1]) > 0.0;
+      } else {
+        moveleft = 1;
+      }
+    } else {
+      if (orgorient > 0.0) {
+        moveleft = 0;
+      } else {
+        /* The point we seek must be on the boundary of or inside this */
+        /*   triangle.                                                 */
+        if (destorient == 0.0) {
+          lprevself(*searchtri);
+          return ONEDGE;
+        }
+        if (orgorient == 0.0) {
+          lnextself(*searchtri);
+          return ONEDGE;
+        }
+        return INTRIANGLE;
+      }
+    }
+
+    /* Move to another triangle.  Leave a trace `backtracktri' in case */
+    /*   floating-point roundoff or some such bogey causes us to walk  */
+    /*   off a boundary of the triangulation.  We can just bounce off  */
+    /*   the boundary as if it were an elastic band.                   */
+    if (moveleft) {
+      lprev(*searchtri, backtracktri);
+      fdest = fapex;
+    } else {
+      lnext(*searchtri, backtracktri);
+      forg = fapex;
+    }
+    sym(backtracktri, *searchtri);
+
+    /* Check for walking off the edge. */
+    if (searchtri->tri == dummytri) {
+      /* Turn around. */
+      triedgecopy(backtracktri, *searchtri);
+      swappoint = forg;
+      forg = fdest;
+      fdest = swappoint;
+      apex(*searchtri, fapex);
+      /* Check if the point really is beyond the triangulation boundary. */
+      destorient = counterclockwise(forg, fapex, searchpoint);
+      orgorient = counterclockwise(fapex, fdest, searchpoint);
+      if ((orgorient < 0.0) && (destorient < 0.0)) {
+        return OUTSIDE;
+      }
+    } else {
+      apex(*searchtri, fapex);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  locate()   Find a triangle or edge containing a given point.             */
+/*                                                                           */
+/*  Searching begins from one of:  the input `searchtri', a recently         */
+/*  encountered triangle `recenttri', or from a triangle chosen from a       */
+/*  random sample.  The choice is made by determining which triangle's       */
+/*  origin is closest to the point we are searcing for.  Normally,           */
+/*  `searchtri' should be a handle on the convex hull of the triangulation.  */
+/*                                                                           */
+/*  Details on the random sampling method can be found in the Mucke, Saias,  */
+/*  and Zhu paper cited in the header of this code.                          */
+/*                                                                           */
+/*  On completion, `searchtri' is a triangle that contains `searchpoint'.    */
+/*                                                                           */
+/*  Returns ONVERTEX if the point lies on an existing vertex.  `searchtri'   */
+/*  is a handle whose origin is the existing vertex.                         */
+/*                                                                           */
+/*  Returns ONEDGE if the point lies on a mesh edge.  `searchtri' is a       */
+/*  handle whose primary edge is the edge on which the point lies.           */
+/*                                                                           */
+/*  Returns INTRIANGLE if the point lies strictly within a triangle.         */
+/*  `searchtri' is a handle on the triangle that contains the point.         */
+/*                                                                           */
+/*  Returns OUTSIDE if the point lies outside the mesh.  `searchtri' is a    */
+/*  handle whose primary edge the point is to the right of.  This might      */
+/*  occur when the circumcenter of a triangle falls just slightly outside    */
+/*  the mesh due to floating-point roundoff error.  It also occurs when      */
+/*  seeking a hole or region point that a foolish user has placed outside    */
+/*  the mesh.                                                                */
+/*                                                                           */
+/*  WARNING:  This routine is designed for convex triangulations, and will   */
+/*  not generally work after the holes and concavities have been carved.     */
+/*                                                                           */
+/*****************************************************************************/
+
+enum locateresult locate(searchpoint, searchtri)
+point searchpoint;
+struct triedge *searchtri;
+{
+  VOID **sampleblock;
+  triangle *firsttri;
+  struct triedge sampletri;
+  point torg, tdest;
+  unsigned long alignptr;
+  REAL searchdist, dist;
+  REAL ahead;
+  long sampleblocks, samplesperblock, samplenum;
+  long triblocks;
+  long i, j;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose > 2) {
+    printf("  Randomly sampling for a triangle near point (%.12g, %.12g).\n",
+           searchpoint[0], searchpoint[1]);
+  }
+  /* Record the distance from the suggested starting triangle to the */
+  /*   point we seek.                                                */
+  org(*searchtri, torg);
+  searchdist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
+             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
+  if (verbose > 2) {
+    printf("    Boundary triangle has origin (%.12g, %.12g).\n",
+           torg[0], torg[1]);
+  }
+
+  /* If a recently encountered triangle has been recorded and has not been */
+  /*   deallocated, test it as a good starting point.                      */
+  if (recenttri.tri != (triangle *) NULL) {
+    if (recenttri.tri[3] != (triangle) NULL) {
+      org(recenttri, torg);
+      if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
+        triedgecopy(recenttri, *searchtri);
+        return ONVERTEX;
+      }
+      dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
+           + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
+      if (dist < searchdist) {
+        triedgecopy(recenttri, *searchtri);
+        searchdist = dist;
+        if (verbose > 2) {
+          printf("    Choosing recent triangle with origin (%.12g, %.12g).\n",
+                 torg[0], torg[1]);
+        }
+      }
+    }
+  }
+
+  /* The number of random samples taken is proportional to the cube root of */
+  /*   the number of triangles in the mesh.  The next bit of code assumes   */
+  /*   that the number of triangles increases monotonically.                */
+  while (SAMPLEFACTOR * samples * samples * samples < triangles.items) {
+    samples++;
+  }
+  triblocks = (triangles.maxitems + TRIPERBLOCK - 1) / TRIPERBLOCK;
+  samplesperblock = 1 + (samples / triblocks);
+  sampleblocks = samples / samplesperblock;
+  sampleblock = triangles.firstblock;
+  sampletri.orient = 0;
+  for (i = 0; i < sampleblocks; i++) {
+    alignptr = (unsigned long) (sampleblock + 1);
+    firsttri = (triangle *) (alignptr + (unsigned long) triangles.alignbytes
+                          - (alignptr % (unsigned long) triangles.alignbytes));
+    for (j = 0; j < samplesperblock; j++) {
+      if (i == triblocks - 1) {
+        samplenum = randomnation((int)
+                                 (triangles.maxitems - (i * TRIPERBLOCK)));
+      } else {
+        samplenum = randomnation(TRIPERBLOCK);
+      }
+      sampletri.tri = (triangle *)
+                      (firsttri + (samplenum * triangles.itemwords));
+      if (sampletri.tri[3] != (triangle) NULL) {
+        org(sampletri, torg);
+        dist = (searchpoint[0] - torg[0]) * (searchpoint[0] - torg[0])
+             + (searchpoint[1] - torg[1]) * (searchpoint[1] - torg[1]);
+        if (dist < searchdist) {
+          triedgecopy(sampletri, *searchtri);
+          searchdist = dist;
+          if (verbose > 2) {
+            printf("    Choosing triangle with origin (%.12g, %.12g).\n",
+                   torg[0], torg[1]);
+          }
+        }
+      }
+    }
+    sampleblock = (VOID **) *sampleblock;
+  }
+  /* Where are we? */
+  org(*searchtri, torg);
+  dest(*searchtri, tdest);
+  /* Check the starting triangle's vertices. */
+  if ((torg[0] == searchpoint[0]) && (torg[1] == searchpoint[1])) {
+    return ONVERTEX;
+  }
+  if ((tdest[0] == searchpoint[0]) && (tdest[1] == searchpoint[1])) {
+    lnextself(*searchtri);
+    return ONVERTEX;
+  }
+  /* Orient `searchtri' to fit the preconditions of calling preciselocate(). */
+  ahead = counterclockwise(torg, tdest, searchpoint);
+  if (ahead < 0.0) {
+    /* Turn around so that `searchpoint' is to the left of the */
+    /*   edge specified by `searchtri'.                        */
+    symself(*searchtri);
+  } else if (ahead == 0.0) {
+    /* Check if `searchpoint' is between `torg' and `tdest'. */
+    if (((torg[0] < searchpoint[0]) == (searchpoint[0] < tdest[0]))
+        && ((torg[1] < searchpoint[1]) == (searchpoint[1] < tdest[1]))) {
+      return ONEDGE;
+    }
+  }
+  return preciselocate(searchpoint, searchtri);
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Point location routines end here                          *********/
+
+/********* Mesh transformation routines begin here                   *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  insertshelle()   Create a new shell edge and insert it between two       */
+/*                   triangles.                                              */
+/*                                                                           */
+/*  The new shell edge is inserted at the edge described by the handle       */
+/*  `tri'.  Its vertices are properly initialized.  The marker `shellemark'  */
+/*  is applied to the shell edge and, if appropriate, its vertices.          */
+/*                                                                           */
+/*****************************************************************************/
+
+void insertshelle(tri, shellemark)
+struct triedge *tri;          /* Edge at which to insert the new shell edge. */
+int shellemark;                            /* Marker for the new shell edge. */
+{
+  struct triedge oppotri;
+  struct edge newshelle;
+  point triorg, tridest;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  /* Mark points if possible. */
+  org(*tri, triorg);
+  dest(*tri, tridest);
+  if (pointmark(triorg) == 0) {
+    setpointmark(triorg, shellemark);
+  }
+  if (pointmark(tridest) == 0) {
+    setpointmark(tridest, shellemark);
+  }
+  /* Check if there's already a shell edge here. */
+  tspivot(*tri, newshelle);
+  if (newshelle.sh == dummysh) {
+    /* Make new shell edge and initialize its vertices. */
+    makeshelle(&newshelle);
+    setsorg(newshelle, tridest);
+    setsdest(newshelle, triorg);
+    /* Bond new shell edge to the two triangles it is sandwiched between. */
+    /*   Note that the facing triangle `oppotri' might be equal to        */
+    /*   `dummytri' (outer space), but the new shell edge is bonded to it */
+    /*   all the same.                                                    */
+    tsbond(*tri, newshelle);
+    sym(*tri, oppotri);
+    ssymself(newshelle);
+    tsbond(oppotri, newshelle);
+    setmark(newshelle, shellemark);
+    if (verbose > 2) {
+      printf("  Inserting new ");
+      printshelle(&newshelle);
+    }
+  } else {
+    if (mark(newshelle) == 0) {
+      setmark(newshelle, shellemark);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  Terminology                                                              */
+/*                                                                           */
+/*  A "local transformation" replaces a small set of triangles with another  */
+/*  set of triangles.  This may or may not involve inserting or deleting a   */
+/*  point.                                                                   */
+/*                                                                           */
+/*  The term "casing" is used to describe the set of triangles that are      */
+/*  attached to the triangles being transformed, but are not transformed     */
+/*  themselves.  Think of the casing as a fixed hollow structure inside      */
+/*  which all the action happens.  A "casing" is only defined relative to    */
+/*  a single transformation; each occurrence of a transformation will        */
+/*  involve a different casing.                                              */
+/*                                                                           */
+/*  A "shell" is similar to a "casing".  The term "shell" describes the set  */
+/*  of shell edges (if any) that are attached to the triangles being         */
+/*  transformed.  However, I sometimes use "shell" to refer to a single      */
+/*  shell edge, so don't get confused.                                       */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  flip()   Transform two triangles to two different triangles by flipping  */
+/*           an edge within a quadrilateral.                                 */
+/*                                                                           */
+/*  Imagine the original triangles, abc and bad, oriented so that the        */
+/*  shared edge ab lies in a horizontal plane, with the point b on the left  */
+/*  and the point a on the right.  The point c lies below the edge, and the  */
+/*  point d lies above the edge.  The `flipedge' handle holds the edge ab    */
+/*  of triangle abc, and is directed left, from vertex a to vertex b.        */
+/*                                                                           */
+/*  The triangles abc and bad are deleted and replaced by the triangles cdb  */
+/*  and dca.  The triangles that represent abc and bad are NOT deallocated;  */
+/*  they are reused for dca and cdb, respectively.  Hence, any handles that  */
+/*  may have held the original triangles are still valid, although not       */
+/*  directed as they were before.                                            */
+/*                                                                           */
+/*  Upon completion of this routine, the `flipedge' handle holds the edge    */
+/*  dc of triangle dca, and is directed down, from vertex d to vertex c.     */
+/*  (Hence, the two triangles have rotated counterclockwise.)                */
+/*                                                                           */
+/*  WARNING:  This transformation is geometrically valid only if the         */
+/*  quadrilateral adbc is convex.  Furthermore, this transformation is       */
+/*  valid only if there is not a shell edge between the triangles abc and    */
+/*  bad.  This routine does not check either of these preconditions, and     */
+/*  it is the responsibility of the calling routine to ensure that they are  */
+/*  met.  If they are not, the streets shall be filled with wailing and      */
+/*  gnashing of teeth.                                                       */
+/*                                                                           */
+/*****************************************************************************/
+
+void flip(flipedge)
+struct triedge *flipedge;                    /* Handle for the triangle abc. */
+{
+  struct triedge botleft, botright;
+  struct triedge topleft, topright;
+  struct triedge top;
+  struct triedge botlcasing, botrcasing;
+  struct triedge toplcasing, toprcasing;
+  struct edge botlshelle, botrshelle;
+  struct edge toplshelle, toprshelle;
+  point leftpoint, rightpoint, botpoint;
+  point farpoint;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  /* Identify the vertices of the quadrilateral. */
+  org(*flipedge, rightpoint);
+  dest(*flipedge, leftpoint);
+  apex(*flipedge, botpoint);
+  sym(*flipedge, top);
+#ifdef SELF_CHECK
+  if (top.tri == dummytri) {
+    printf("Internal error in flip():  Attempt to flip on boundary.\n");
+    lnextself(*flipedge);
+    return;
+  }
+  if (checksegments) {
+    tspivot(*flipedge, toplshelle);
+    if (toplshelle.sh != dummysh) {
+      printf("Internal error in flip():  Attempt to flip a segment.\n");
+      lnextself(*flipedge);
+      return;
+    }
+  }
+#endif /* SELF_CHECK */
+  apex(top, farpoint);
+
+  /* Identify the casing of the quadrilateral. */
+  lprev(top, topleft);
+  sym(topleft, toplcasing);
+  lnext(top, topright);
+  sym(topright, toprcasing);
+  lnext(*flipedge, botleft);
+  sym(botleft, botlcasing);
+  lprev(*flipedge, botright);
+  sym(botright, botrcasing);
+  /* Rotate the quadrilateral one-quarter turn counterclockwise. */
+  bond(topleft, botlcasing);
+  bond(botleft, botrcasing);
+  bond(botright, toprcasing);
+  bond(topright, toplcasing);
+
+  if (checksegments) {
+    /* Check for shell edges and rebond them to the quadrilateral. */
+    tspivot(topleft, toplshelle);
+    tspivot(botleft, botlshelle);
+    tspivot(botright, botrshelle);
+    tspivot(topright, toprshelle);
+    if (toplshelle.sh == dummysh) {
+      tsdissolve(topright);
+    } else {
+      tsbond(topright, toplshelle);
+    }
+    if (botlshelle.sh == dummysh) {
+      tsdissolve(topleft);
+    } else {
+      tsbond(topleft, botlshelle);
+    }
+    if (botrshelle.sh == dummysh) {
+      tsdissolve(botleft);
+    } else {
+      tsbond(botleft, botrshelle);
+    }
+    if (toprshelle.sh == dummysh) {
+      tsdissolve(botright);
+    } else {
+      tsbond(botright, toprshelle);
+    }
+  }
+
+  /* New point assignments for the rotated quadrilateral. */
+  setorg(*flipedge, farpoint);
+  setdest(*flipedge, botpoint);
+  setapex(*flipedge, rightpoint);
+  setorg(top, botpoint);
+  setdest(top, farpoint);
+  setapex(top, leftpoint);
+  if (verbose > 2) {
+    printf("  Edge flip results in left ");
+    lnextself(topleft);
+    printtriangle(&topleft);
+    printf("  and right ");
+    printtriangle(flipedge);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  insertsite()   Insert a vertex into a Delaunay triangulation,            */
+/*                 performing flips as necessary to maintain the Delaunay    */
+/*                 property.                                                 */
+/*                                                                           */
+/*  The point `insertpoint' is located.  If `searchtri.tri' is not NULL,     */
+/*  the search for the containing triangle begins from `searchtri'.  If      */
+/*  `searchtri.tri' is NULL, a full point location procedure is called.      */
+/*  If `insertpoint' is found inside a triangle, the triangle is split into  */
+/*  three; if `insertpoint' lies on an edge, the edge is split in two,       */
+/*  thereby splitting the two adjacent triangles into four.  Edge flips are  */
+/*  used to restore the Delaunay property.  If `insertpoint' lies on an      */
+/*  existing vertex, no action is taken, and the value DUPLICATEPOINT is     */
+/*  returned.  On return, `searchtri' is set to a handle whose origin is the */
+/*  existing vertex.                                                         */
+/*                                                                           */
+/*  Normally, the parameter `splitedge' is set to NULL, implying that no     */
+/*  segment should be split.  In this case, if `insertpoint' is found to     */
+/*  lie on a segment, no action is taken, and the value VIOLATINGPOINT is    */
+/*  returned.  On return, `searchtri' is set to a handle whose primary edge  */
+/*  is the violated segment.                                                 */
+/*                                                                           */
+/*  If the calling routine wishes to split a segment by inserting a point in */
+/*  it, the parameter `splitedge' should be that segment.  In this case,     */
+/*  `searchtri' MUST be the triangle handle reached by pivoting from that    */
+/*  segment; no point location is done.                                      */
+/*                                                                           */
+/*  `segmentflaws' and `triflaws' are flags that indicate whether or not     */
+/*  there should be checks for the creation of encroached segments or bad    */
+/*  quality faces.  If a newly inserted point encroaches upon segments,      */
+/*  these segments are added to the list of segments to be split if          */
+/*  `segmentflaws' is set.  If bad triangles are created, these are added    */
+/*  to the queue if `triflaws' is set.                                       */
+/*                                                                           */
+/*  If a duplicate point or violated segment does not prevent the point      */
+/*  from being inserted, the return value will be ENCROACHINGPOINT if the    */
+/*  point encroaches upon a segment (and checking is enabled), or            */
+/*  SUCCESSFULPOINT otherwise.  In either case, `searchtri' is set to a      */
+/*  handle whose origin is the newly inserted vertex.                        */
+/*                                                                           */
+/*  insertsite() does not use flip() for reasons of speed; some              */
+/*  information can be reused from edge flip to edge flip, like the          */
+/*  locations of shell edges.                                                */
+/*                                                                           */
+/*****************************************************************************/
+
+enum insertsiteresult insertsite(insertpoint, searchtri, splitedge,
+                                 segmentflaws, triflaws)
+point insertpoint;
+struct triedge *searchtri;
+struct edge *splitedge;
+int segmentflaws;
+int triflaws;
+{
+  struct triedge horiz;
+  struct triedge top;
+  struct triedge botleft, botright;
+  struct triedge topleft, topright;
+  struct triedge newbotleft, newbotright;
+  struct triedge newtopright;
+  struct triedge botlcasing, botrcasing;
+  struct triedge toplcasing, toprcasing;
+  struct triedge testtri;
+  struct edge botlshelle, botrshelle;
+  struct edge toplshelle, toprshelle;
+  struct edge brokenshelle;
+  struct edge checkshelle;
+  struct edge rightedge;
+  struct edge newedge;
+  struct edge *encroached;
+  point first;
+  point leftpoint, rightpoint, botpoint, toppoint, farpoint;
+  REAL attrib;
+  REAL area;
+  enum insertsiteresult success;
+  enum locateresult intersect;
+  int doflip;
+  int mirrorflag;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;         /* Temporary variable used by spivot() and tspivot(). */
+
+  if (verbose > 1) {
+    printf("  Inserting (%.12g, %.12g).\n", insertpoint[0], insertpoint[1]);
+  }
+  if (splitedge == (struct edge *) NULL) {
+    /* Find the location of the point to be inserted.  Check if a good */
+    /*   starting triangle has already been provided by the caller.    */
+    if (searchtri->tri == (triangle *) NULL) {
+      /* Find a boundary triangle. */
+      horiz.tri = dummytri;
+      horiz.orient = 0;
+      symself(horiz);
+      /* Search for a triangle containing `insertpoint'. */
+      intersect = locate(insertpoint, &horiz);
+    } else {
+      /* Start searching from the triangle provided by the caller. */
+      triedgecopy(*searchtri, horiz);
+      intersect = preciselocate(insertpoint, &horiz);
+    }
+  } else {
+    /* The calling routine provides the edge in which the point is inserted. */
+    triedgecopy(*searchtri, horiz);
+    intersect = ONEDGE;
+  }
+  if (intersect == ONVERTEX) {
+    /* There's already a vertex there.  Return in `searchtri' a triangle */
+    /*   whose origin is the existing vertex.                            */
+    triedgecopy(horiz, *searchtri);
+    triedgecopy(horiz, recenttri);
+    return DUPLICATEPOINT;
+  }
+  if ((intersect == ONEDGE) || (intersect == OUTSIDE)) {
+    /* The vertex falls on an edge or boundary. */
+    if (checksegments && (splitedge == (struct edge *) NULL)) {
+      /* Check whether the vertex falls on a shell edge. */
+      tspivot(horiz, brokenshelle);
+      if (brokenshelle.sh != dummysh) {
+        /* The vertex falls on a shell edge. */
+        if (segmentflaws) {
+          if (nobisect == 0) {
+            /* Add the shell edge to the list of encroached segments. */
+            encroached = (struct edge *) poolalloc(&badsegments);
+            shellecopy(brokenshelle, *encroached);
+          } else if ((nobisect == 1) && (intersect == ONEDGE)) {
+            /* This segment may be split only if it is an internal boundary. */
+            sym(horiz, testtri);
+            if (testtri.tri != dummytri) {
+              /* Add the shell edge to the list of encroached segments. */
+              encroached = (struct edge *) poolalloc(&badsegments);
+              shellecopy(brokenshelle, *encroached);
+            }
+          }
+        }
+        /* Return a handle whose primary edge contains the point, */
+        /*   which has not been inserted.                         */
+        triedgecopy(horiz, *searchtri);
+        triedgecopy(horiz, recenttri);
+        return VIOLATINGPOINT;
+      }
+    }
+    /* Insert the point on an edge, dividing one triangle into two (if */
+    /*   the edge lies on a boundary) or two triangles into four.      */
+    lprev(horiz, botright);
+    sym(botright, botrcasing);
+    sym(horiz, topright);
+    /* Is there a second triangle?  (Or does this edge lie on a boundary?) */
+    mirrorflag = topright.tri != dummytri;
+    if (mirrorflag) {
+      lnextself(topright);
+      sym(topright, toprcasing);
+      maketriangle(&newtopright);
+    } else {
+      /* Splitting the boundary edge increases the number of boundary edges. */
+      hullsize++;
+    }
+    maketriangle(&newbotright);
+
+    /* Set the vertices of changed and new triangles. */
+    org(horiz, rightpoint);
+    dest(horiz, leftpoint);
+    apex(horiz, botpoint);
+    setorg(newbotright, botpoint);
+    setdest(newbotright, rightpoint);
+    setapex(newbotright, insertpoint);
+    setorg(horiz, insertpoint);
+    for (i = 0; i < eextras; i++) {
+      /* Set the element attributes of a new triangle. */
+      setelemattribute(newbotright, i, elemattribute(botright, i));
+    }
+    if (vararea) {
+      /* Set the area constraint of a new triangle. */
+      setareabound(newbotright, areabound(botright));
+    }
+    if (mirrorflag) {
+      dest(topright, toppoint);
+      setorg(newtopright, rightpoint);
+      setdest(newtopright, toppoint);
+      setapex(newtopright, insertpoint);
+      setorg(topright, insertpoint);
+      for (i = 0; i < eextras; i++) {
+        /* Set the element attributes of another new triangle. */
+        setelemattribute(newtopright, i, elemattribute(topright, i));
+      }
+      if (vararea) {
+        /* Set the area constraint of another new triangle. */
+        setareabound(newtopright, areabound(topright));
+      }
+    }
+
+    /* There may be shell edges that need to be bonded */
+    /*   to the new triangle(s).                       */
+    if (checksegments) {
+      tspivot(botright, botrshelle);
+      if (botrshelle.sh != dummysh) {
+        tsdissolve(botright);
+        tsbond(newbotright, botrshelle);
+      }
+      if (mirrorflag) {
+        tspivot(topright, toprshelle);
+        if (toprshelle.sh != dummysh) {
+          tsdissolve(topright);
+          tsbond(newtopright, toprshelle);
+        }
+      }
+    }
+
+    /* Bond the new triangle(s) to the surrounding triangles. */
+    bond(newbotright, botrcasing);
+    lprevself(newbotright);
+    bond(newbotright, botright);
+    lprevself(newbotright);
+    if (mirrorflag) {
+      bond(newtopright, toprcasing);
+      lnextself(newtopright);
+      bond(newtopright, topright);
+      lnextself(newtopright);
+      bond(newtopright, newbotright);
+    }
+
+    if (splitedge != (struct edge *) NULL) {
+      /* Split the shell edge into two. */
+      setsdest(*splitedge, insertpoint);
+      ssymself(*splitedge);
+      spivot(*splitedge, rightedge);
+      insertshelle(&newbotright, mark(*splitedge));
+      tspivot(newbotright, newedge);
+      sbond(*splitedge, newedge);
+      ssymself(newedge);
+      sbond(newedge, rightedge);
+      ssymself(*splitedge);
+    }
+
+#ifdef SELF_CHECK
+    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle prior to edge point insertion (bottom).\n");
+    }
+    if (mirrorflag) {
+      if (counterclockwise(leftpoint, rightpoint, toppoint) < 0.0) {
+        printf("Internal error in insertsite():\n");
+        printf("  Clockwise triangle prior to edge point insertion (top).\n");
+      }
+      if (counterclockwise(rightpoint, toppoint, insertpoint) < 0.0) {
+        printf("Internal error in insertsite():\n");
+        printf("  Clockwise triangle after edge point insertion (top right).\n"
+               );
+      }
+      if (counterclockwise(toppoint, leftpoint, insertpoint) < 0.0) {
+        printf("Internal error in insertsite():\n");
+        printf("  Clockwise triangle after edge point insertion (top left).\n"
+               );
+      }
+    }
+    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after edge point insertion (bottom left).\n"
+             );
+    }
+    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf(
+        "  Clockwise triangle after edge point insertion (bottom right).\n");
+    }
+#endif /* SELF_CHECK */
+    if (verbose > 2) {
+      printf("  Updating bottom left ");
+      printtriangle(&botright);
+      if (mirrorflag) {
+        printf("  Updating top left ");
+        printtriangle(&topright);
+        printf("  Creating top right ");
+        printtriangle(&newtopright);
+      }
+      printf("  Creating bottom right ");
+      printtriangle(&newbotright);
+    }
+
+    /* Position `horiz' on the first edge to check for */
+    /*   the Delaunay property.                        */
+    lnextself(horiz);
+  } else {
+    /* Insert the point in a triangle, splitting it into three. */
+    lnext(horiz, botleft);
+    lprev(horiz, botright);
+    sym(botleft, botlcasing);
+    sym(botright, botrcasing);
+    maketriangle(&newbotleft);
+    maketriangle(&newbotright);
+
+    /* Set the vertices of changed and new triangles. */
+    org(horiz, rightpoint);
+    dest(horiz, leftpoint);
+    apex(horiz, botpoint);
+    setorg(newbotleft, leftpoint);
+    setdest(newbotleft, botpoint);
+    setapex(newbotleft, insertpoint);
+    setorg(newbotright, botpoint);
+    setdest(newbotright, rightpoint);
+    setapex(newbotright, insertpoint);
+    setapex(horiz, insertpoint);
+    for (i = 0; i < eextras; i++) {
+      /* Set the element attributes of the new triangles. */
+      attrib = elemattribute(horiz, i);
+      setelemattribute(newbotleft, i, attrib);
+      setelemattribute(newbotright, i, attrib);
+    }
+    if (vararea) {
+      /* Set the area constraint of the new triangles. */
+      area = areabound(horiz);
+      setareabound(newbotleft, area);
+      setareabound(newbotright, area);
+    }
+
+    /* There may be shell edges that need to be bonded */
+    /*   to the new triangles.                         */
+    if (checksegments) {
+      tspivot(botleft, botlshelle);
+      if (botlshelle.sh != dummysh) {
+        tsdissolve(botleft);
+        tsbond(newbotleft, botlshelle);
+      }
+      tspivot(botright, botrshelle);
+      if (botrshelle.sh != dummysh) {
+        tsdissolve(botright);
+        tsbond(newbotright, botrshelle);
+      }
+    }
+
+    /* Bond the new triangles to the surrounding triangles. */
+    bond(newbotleft, botlcasing);
+    bond(newbotright, botrcasing);
+    lnextself(newbotleft);
+    lprevself(newbotright);
+    bond(newbotleft, newbotright);
+    lnextself(newbotleft);
+    bond(botleft, newbotleft);
+    lprevself(newbotright);
+    bond(botright, newbotright);
+
+#ifdef SELF_CHECK
+    if (counterclockwise(rightpoint, leftpoint, botpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle prior to point insertion.\n");
+    }
+    if (counterclockwise(rightpoint, leftpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after point insertion (top).\n");
+    }
+    if (counterclockwise(leftpoint, botpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after point insertion (left).\n");
+    }
+    if (counterclockwise(botpoint, rightpoint, insertpoint) < 0.0) {
+      printf("Internal error in insertsite():\n");
+      printf("  Clockwise triangle after point insertion (right).\n");
+    }
+#endif /* SELF_CHECK */
+    if (verbose > 2) {
+      printf("  Updating top ");
+      printtriangle(&horiz);
+      printf("  Creating left ");
+      printtriangle(&newbotleft);
+      printf("  Creating right ");
+      printtriangle(&newbotright);
+    }
+  }
+
+  /* The insertion is successful by default, unless an encroached */
+  /*   edge is found.                                             */
+  success = SUCCESSFULPOINT;
+  /* Circle around the newly inserted vertex, checking each edge opposite */
+  /*   it for the Delaunay property.  Non-Delaunay edges are flipped.     */
+  /*   `horiz' is always the edge being checked.  `first' marks where to  */
+  /*   stop circling.                                                     */
+  org(horiz, first);
+  rightpoint = first;
+  dest(horiz, leftpoint);
+  /* Circle until finished. */
+  while (1) {
+    /* By default, the edge will be flipped. */
+    doflip = 1;
+    if (checksegments) {
+      /* Check for a segment, which cannot be flipped. */
+      tspivot(horiz, checkshelle);
+      if (checkshelle.sh != dummysh) {
+        /* The edge is a segment and cannot be flipped. */
+        doflip = 0;
+#ifndef CDT_ONLY
+        if (segmentflaws) {
+          /* Does the new point encroach upon this segment? */
+          if (checkedge4encroach(&checkshelle)) {
+            success = ENCROACHINGPOINT;
+          }
+        }
+#endif /* not CDT_ONLY */
+      }
+    }
+    if (doflip) {
+      /* Check if the edge is a boundary edge. */
+      sym(horiz, top);
+      if (top.tri == dummytri) {
+        /* The edge is a boundary edge and cannot be flipped. */
+        doflip = 0;
+      } else {
+        /* Find the point on the other side of the edge. */
+        apex(top, farpoint);
+        /* In the incremental Delaunay triangulation algorithm, any of    */
+        /*   `leftpoint', `rightpoint', and `farpoint' could be vertices  */
+        /*   of the triangular bounding box.  These vertices must be      */
+        /*   treated as if they are infinitely distant, even though their */
+        /*   "coordinates" are not.                                       */
+        if ((leftpoint == infpoint1) || (leftpoint == infpoint2)
+                   || (leftpoint == infpoint3)) {
+          /* `leftpoint' is infinitely distant.  Check the convexity of */
+          /*   the boundary of the triangulation.  'farpoint' might be  */
+          /*   infinite as well, but trust me, this same condition      */
+          /*   should be applied.                                       */
+          doflip = counterclockwise(insertpoint, rightpoint, farpoint) > 0.0;
+        } else if ((rightpoint == infpoint1) || (rightpoint == infpoint2)
+                   || (rightpoint == infpoint3)) {
+          /* `rightpoint' is infinitely distant.  Check the convexity of */
+          /*   the boundary of the triangulation.  'farpoint' might be  */
+          /*   infinite as well, but trust me, this same condition      */
+          /*   should be applied.                                       */
+          doflip = counterclockwise(farpoint, leftpoint, insertpoint) > 0.0;
+        } else if ((farpoint == infpoint1) || (farpoint == infpoint2)
+            || (farpoint == infpoint3)) {
+          /* `farpoint' is infinitely distant and cannot be inside */
+          /*   the circumcircle of the triangle `horiz'.           */
+          doflip = 0;
+        } else {
+          /* Test whether the edge is locally Delaunay. */
+          doflip = incircle(leftpoint, insertpoint, rightpoint, farpoint)
+                   > 0.0;
+        }
+        if (doflip) {
+          /* We made it!  Flip the edge `horiz' by rotating its containing */
+          /*   quadrilateral (the two triangles adjacent to `horiz').      */
+          /* Identify the casing of the quadrilateral. */
+          lprev(top, topleft);
+          sym(topleft, toplcasing);
+          lnext(top, topright);
+          sym(topright, toprcasing);
+          lnext(horiz, botleft);
+          sym(botleft, botlcasing);
+          lprev(horiz, botright);
+          sym(botright, botrcasing);
+          /* Rotate the quadrilateral one-quarter turn counterclockwise. */
+          bond(topleft, botlcasing);
+          bond(botleft, botrcasing);
+          bond(botright, toprcasing);
+          bond(topright, toplcasing);
+          if (checksegments) {
+            /* Check for shell edges and rebond them to the quadrilateral. */
+            tspivot(topleft, toplshelle);
+            tspivot(botleft, botlshelle);
+            tspivot(botright, botrshelle);
+            tspivot(topright, toprshelle);
+            if (toplshelle.sh == dummysh) {
+              tsdissolve(topright);
+            } else {
+              tsbond(topright, toplshelle);
+            }
+            if (botlshelle.sh == dummysh) {
+              tsdissolve(topleft);
+            } else {
+              tsbond(topleft, botlshelle);
+            }
+            if (botrshelle.sh == dummysh) {
+              tsdissolve(botleft);
+            } else {
+              tsbond(botleft, botrshelle);
+            }
+            if (toprshelle.sh == dummysh) {
+              tsdissolve(botright);
+            } else {
+              tsbond(botright, toprshelle);
+            }
+          }
+          /* New point assignments for the rotated quadrilateral. */
+          setorg(horiz, farpoint);
+          setdest(horiz, insertpoint);
+          setapex(horiz, rightpoint);
+          setorg(top, insertpoint);
+          setdest(top, farpoint);
+          setapex(top, leftpoint);
+          for (i = 0; i < eextras; i++) {
+            /* Take the average of the two triangles' attributes. */
+            attrib = (REAL)(0.5 * (elemattribute(top, i) + elemattribute(horiz, i)));
+            setelemattribute(top, i, attrib);
+            setelemattribute(horiz, i, attrib);
+          }
+          if (vararea) {
+            if ((areabound(top) <= 0.0) || (areabound(horiz) <= 0.0)) {
+              area = -1.0;
+            } else {
+              /* Take the average of the two triangles' area constraints.    */
+              /*   This prevents small area constraints from migrating a     */
+              /*   long, long way from their original location due to flips. */
+              area = (REAL)(0.5 * (areabound(top) + areabound(horiz)));
+            }
+            setareabound(top, area);
+            setareabound(horiz, area);
+          }
+#ifdef SELF_CHECK
+          if (insertpoint != (point) NULL) {
+            if (counterclockwise(leftpoint, insertpoint, rightpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle prior to edge flip (bottom).\n");
+            }
+            /* The following test has been removed because constrainededge() */
+            /*   sometimes generates inverted triangles that insertsite()    */
+            /*   removes.                                                    */
+/*
+            if (counterclockwise(rightpoint, farpoint, leftpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle prior to edge flip (top).\n");
+            }
+*/
+            if (counterclockwise(farpoint, leftpoint, insertpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle after edge flip (left).\n");
+            }
+            if (counterclockwise(insertpoint, rightpoint, farpoint) < 0.0) {
+              printf("Internal error in insertsite():\n");
+              printf("  Clockwise triangle after edge flip (right).\n");
+            }
+          }
+#endif /* SELF_CHECK */
+          if (verbose > 2) {
+            printf("  Edge flip results in left ");
+            lnextself(topleft);
+            printtriangle(&topleft);
+            printf("  and right ");
+            printtriangle(&horiz);
+          }
+          /* On the next iterations, consider the two edges that were  */
+          /*   exposed (this is, are now visible to the newly inserted */
+          /*   point) by the edge flip.                                */
+          lprevself(horiz);
+          leftpoint = farpoint;
+        }
+      }
+    }
+    if (!doflip) {
+      /* The handle `horiz' is accepted as locally Delaunay. */
+#ifndef CDT_ONLY
+      if (triflaws) {
+        /* Check the triangle `horiz' for quality. */
+        testtriangle(&horiz);
+      }
+#endif /* not CDT_ONLY */
+      /* Look for the next edge around the newly inserted point. */
+      lnextself(horiz);
+      sym(horiz, testtri);
+      /* Check for finishing a complete revolution about the new point, or */
+      /*   falling off the edge of the triangulation.  The latter will     */
+      /*   happen when a point is inserted at a boundary.                  */
+      if ((leftpoint == first) || (testtri.tri == dummytri)) {
+        /* We're done.  Return a triangle whose origin is the new point. */
+        lnext(horiz, *searchtri);
+        lnext(horiz, recenttri);
+        return success;
+      }
+      /* Finish finding the next edge around the newly inserted point. */
+      lnext(testtri, horiz);
+      rightpoint = leftpoint;
+      dest(horiz, leftpoint);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  triangulatepolygon()   Find the Delaunay triangulation of a polygon that */
+/*                         has a certain "nice" shape.  This includes the    */
+/*                         polygons that result from deletion of a point or  */
+/*                         insertion of a segment.                           */
+/*                                                                           */
+/*  This is a conceptually difficult routine.  The starting assumption is    */
+/*  that we have a polygon with n sides.  n - 1 of these sides are currently */
+/*  represented as edges in the mesh.  One side, called the "base", need not */
+/*  be.                                                                      */
+/*                                                                           */
+/*  Inside the polygon is a structure I call a "fan", consisting of n - 1    */
+/*  triangles that share a common origin.  For each of these triangles, the  */
+/*  edge opposite the origin is one of the sides of the polygon.  The        */
+/*  primary edge of each triangle is the edge directed from the origin to    */
+/*  the destination; note that this is not the same edge that is a side of   */
+/*  the polygon.  `firstedge' is the primary edge of the first triangle.     */
+/*  From there, the triangles follow in counterclockwise order about the     */
+/*  polygon, until `lastedge', the primary edge of the last triangle.        */
+/*  `firstedge' and `lastedge' are probably connected to other triangles     */
+/*  beyond the extremes of the fan, but their identity is not important, as  */
+/*  long as the fan remains connected to them.                               */
+/*                                                                           */
+/*  Imagine the polygon oriented so that its base is at the bottom.  This    */
+/*  puts `firstedge' on the far right, and `lastedge' on the far left.       */
+/*  The right vertex of the base is the destination of `firstedge', and the  */
+/*  left vertex of the base is the apex of `lastedge'.                       */
+/*                                                                           */
+/*  The challenge now is to find the right sequence of edge flips to         */
+/*  transform the fan into a Delaunay triangulation of the polygon.  Each    */
+/*  edge flip effectively removes one triangle from the fan, committing it   */
+/*  to the polygon.  The resulting polygon has one fewer edge.  If `doflip'  */
+/*  is set, the final flip will be performed, resulting in a fan of one      */
+/*  (useless?) triangle.  If `doflip' is not set, the final flip is not      */
+/*  performed, resulting in a fan of two triangles, and an unfinished        */
+/*  triangular polygon that is not yet filled out with a single triangle.    */
+/*  On completion of the routine, `lastedge' is the last remaining triangle, */
+/*  or the leftmost of the last two.                                         */
+/*                                                                           */
+/*  Although the flips are performed in the order described above, the       */
+/*  decisions about what flips to perform are made in precisely the reverse  */
+/*  order.  The recursive triangulatepolygon() procedure makes a decision,   */
+/*  uses up to two recursive calls to triangulate the "subproblems"          */
+/*  (polygons with fewer edges), and then performs an edge flip.             */
+/*                                                                           */
+/*  The "decision" it makes is which vertex of the polygon should be         */
+/*  connected to the base.  This decision is made by testing every possible  */
+/*  vertex.  Once the best vertex is found, the two edges that connect this  */
+/*  vertex to the base become the bases for two smaller polygons.  These     */
+/*  are triangulated recursively.  Unfortunately, this approach can take     */
+/*  O(n^2) time not only in the worst case, but in many common cases.  It's  */
+/*  rarely a big deal for point deletion, where n is rarely larger than ten, */
+/*  but it could be a big deal for segment insertion, especially if there's  */
+/*  a lot of long segments that each cut many triangles.  I ought to code    */
+/*  a faster algorithm some time.                                            */
+/*                                                                           */
+/*  The `edgecount' parameter is the number of sides of the polygon,         */
+/*  including its base.  `triflaws' is a flag that determines whether the    */
+/*  new triangles should be tested for quality, and enqueued if they are     */
+/*  bad.                                                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+void triangulatepolygon(firstedge, lastedge, edgecount, doflip, triflaws)
+struct triedge *firstedge;
+struct triedge *lastedge;
+int edgecount;
+int doflip;
+int triflaws;
+{
+  struct triedge testtri;
+  struct triedge besttri;
+  struct triedge tempedge;
+  point leftbasepoint, rightbasepoint;
+  point testpoint;
+  point bestpoint;
+  int bestnumber;
+  int i;
+  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
+
+  /* Identify the base vertices. */
+  apex(*lastedge, leftbasepoint);
+  dest(*firstedge, rightbasepoint);
+  if (verbose > 2) {
+    printf("  Triangulating interior polygon at edge\n");
+    printf("    (%.12g, %.12g) (%.12g, %.12g)\n", leftbasepoint[0],
+           leftbasepoint[1], rightbasepoint[0], rightbasepoint[1]);
+  }
+  /* Find the best vertex to connect the base to. */
+  onext(*firstedge, besttri);
+  dest(besttri, bestpoint);
+  triedgecopy(besttri, testtri);
+  bestnumber = 1;
+  for (i = 2; i <= edgecount - 2; i++) {
+    onextself(testtri);
+    dest(testtri, testpoint);
+    /* Is this a better vertex? */
+    if (incircle(leftbasepoint, rightbasepoint, bestpoint, testpoint) > 0.0) {
+      triedgecopy(testtri, besttri);
+      bestpoint = testpoint;
+      bestnumber = i;
+    }
+  }
+  if (verbose > 2) {
+    printf("    Connecting edge to (%.12g, %.12g)\n", bestpoint[0],
+           bestpoint[1]);
+  }
+  if (bestnumber > 1) {
+    /* Recursively triangulate the smaller polygon on the right. */
+    oprev(besttri, tempedge);
+    triangulatepolygon(firstedge, &tempedge, bestnumber + 1, 1, triflaws);
+  }
+  if (bestnumber < edgecount - 2) {
+    /* Recursively triangulate the smaller polygon on the left. */
+    sym(besttri, tempedge);
+    triangulatepolygon(&besttri, lastedge, edgecount - bestnumber, 1,
+                       triflaws);
+    /* Find `besttri' again; it may have been lost to edge flips. */
+    sym(tempedge, besttri);
+  }
+  if (doflip) {
+    /* Do one final edge flip. */
+    flip(&besttri);
+#ifndef CDT_ONLY
+    if (triflaws) {
+      /* Check the quality of the newly committed triangle. */
+      sym(besttri, testtri);
+      testtriangle(&testtri);
+    }
+#endif /* not CDT_ONLY */
+  }
+  /* Return the base triangle. */
+  triedgecopy(besttri, *lastedge);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  deletesite()   Delete a vertex from a Delaunay triangulation, ensuring   */
+/*                 that the triangulation remains Delaunay.                  */
+/*                                                                           */
+/*  The origin of `deltri' is deleted.  The union of the triangles adjacent  */
+/*  to this point is a polygon, for which the Delaunay triangulation is      */
+/*  found.  Two triangles are removed from the mesh.                         */
+/*                                                                           */
+/*  Only interior points that do not lie on segments (shell edges) or        */
+/*  boundaries may be deleted.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void deletesite(deltri)
+struct triedge *deltri;
+{
+  struct triedge countingtri;
+  struct triedge firstedge, lastedge;
+  struct triedge deltriright;
+  struct triedge lefttri, righttri;
+  struct triedge leftcasing, rightcasing;
+  struct edge leftshelle, rightshelle;
+  point delpoint;
+  point neworg;
+  int edgecount;
+  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  org(*deltri, delpoint);
+  if (verbose > 1) {
+    printf("  Deleting (%.12g, %.12g).\n", delpoint[0], delpoint[1]);
+  }
+  pointdealloc(delpoint);
+
+  /* Count the degree of the point being deleted. */
+  onext(*deltri, countingtri);
+  edgecount = 1;
+  while (!triedgeequal(*deltri, countingtri)) {
+#ifdef SELF_CHECK
+    if (countingtri.tri == dummytri) {
+      printf("Internal error in deletesite():\n");
+      printf("  Attempt to delete boundary point.\n");
+      internalerror();
+    }
+#endif /* SELF_CHECK */
+    edgecount++;
+    onextself(countingtri);
+  }
+
+#ifdef SELF_CHECK
+  if (edgecount < 3) {
+    printf("Internal error in deletesite():\n  Point has degree %d.\n",
+           edgecount);
+    internalerror();
+  }
+#endif /* SELF_CHECK */
+  if (edgecount > 3) {
+    /* Triangulate the polygon defined by the union of all triangles */
+    /*   adjacent to the point being deleted.  Check the quality of  */
+    /*   the resulting triangles.                                    */
+    onext(*deltri, firstedge);
+    oprev(*deltri, lastedge);
+    triangulatepolygon(&firstedge, &lastedge, edgecount, 0, !nobisect);
+  }
+  /* Splice out two triangles. */
+  lprev(*deltri, deltriright);
+  dnext(*deltri, lefttri);
+  sym(lefttri, leftcasing);
+  oprev(deltriright, righttri);
+  sym(righttri, rightcasing);
+  bond(*deltri, leftcasing);
+  bond(deltriright, rightcasing);
+  tspivot(lefttri, leftshelle);
+  if (leftshelle.sh != dummysh) {
+    tsbond(*deltri, leftshelle);
+  }
+  tspivot(righttri, rightshelle);
+  if (rightshelle.sh != dummysh) {
+    tsbond(deltriright, rightshelle);
+  }
+
+  /* Set the new origin of `deltri' and check its quality. */
+  org(lefttri, neworg);
+  setorg(*deltri, neworg);
+  if (!nobisect) {
+    testtriangle(deltri);
+  }
+
+  /* Delete the two spliced-out triangles. */
+  triangledealloc(lefttri.tri);
+  triangledealloc(righttri.tri);
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh transformation routines end here                     *********/
+
+/********* Divide-and-conquer Delaunay triangulation begins here     *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  The divide-and-conquer bounding box                                      */
+/*                                                                           */
+/*  I originally implemented the divide-and-conquer and incremental Delaunay */
+/*  triangulations using the edge-based data structure presented by Guibas   */
+/*  and Stolfi.  Switching to a triangle-based data structure doubled the    */
+/*  speed.  However, I had to think of a few extra tricks to maintain the    */
+/*  elegance of the original algorithms.                                     */
+/*                                                                           */
+/*  The "bounding box" used by my variant of the divide-and-conquer          */
+/*  algorithm uses one triangle for each edge of the convex hull of the      */
+/*  triangulation.  These bounding triangles all share a common apical       */
+/*  vertex, which is represented by NULL and which represents nothing.       */
+/*  The bounding triangles are linked in a circular fan about this NULL      */
+/*  vertex, and the edges on the convex hull of the triangulation appear     */
+/*  opposite the NULL vertex.  You might find it easiest to imagine that     */
+/*  the NULL vertex is a point in 3D space behind the center of the          */
+/*  triangulation, and that the bounding triangles form a sort of cone.      */
+/*                                                                           */
+/*  This bounding box makes it easy to represent degenerate cases.  For      */
+/*  instance, the triangulation of two vertices is a single edge.  This edge */
+/*  is represented by two bounding box triangles, one on each "side" of the  */
+/*  edge.  These triangles are also linked together in a fan about the NULL  */
+/*  vertex.                                                                  */
+/*                                                                           */
+/*  The bounding box also makes it easy to traverse the convex hull, as the  */
+/*  divide-and-conquer algorithm needs to do.                                */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointsort()   Sort an array of points by x-coordinate, using the         */
+/*                y-coordinate as a secondary key.                           */
+/*                                                                           */
+/*  Uses quicksort.  Randomized O(n log n) time.  No, I did not make any of  */
+/*  the usual quicksort mistakes.                                            */
+/*                                                                           */
+/*****************************************************************************/
+
+void pointsort(sortarray, arraysize)
+point *sortarray;
+int arraysize;
+{
+  int left, right;
+  int pivot;
+  REAL pivotx, pivoty;
+  point temp;
+
+  if (arraysize == 2) {
+    /* Recursive base case. */
+    if ((sortarray[0][0] > sortarray[1][0]) ||
+        ((sortarray[0][0] == sortarray[1][0]) &&
+         (sortarray[0][1] > sortarray[1][1]))) {
+      temp = sortarray[1];
+      sortarray[1] = sortarray[0];
+      sortarray[0] = temp;
+    }
+    return;
+  }
+  /* Choose a random pivot to split the array. */
+  pivot = (int) randomnation(arraysize);
+  pivotx = sortarray[pivot][0];
+  pivoty = sortarray[pivot][1];
+  /* Split the array. */
+  left = -1;
+  right = arraysize;
+  while (left < right) {
+    /* Search for a point whose x-coordinate is too large for the left. */
+    do {
+      left++;
+    } while ((left <= right) && ((sortarray[left][0] < pivotx) ||
+                                 ((sortarray[left][0] == pivotx) &&
+                                  (sortarray[left][1] < pivoty))));
+    /* Search for a point whose x-coordinate is too small for the right. */
+    do {
+      right--;
+    } while ((left <= right) && ((sortarray[right][0] > pivotx) ||
+                                 ((sortarray[right][0] == pivotx) &&
+                                  (sortarray[right][1] > pivoty))));
+    if (left < right) {
+      /* Swap the left and right points. */
+      temp = sortarray[left];
+      sortarray[left] = sortarray[right];
+      sortarray[right] = temp;
+    }
+  }
+  if (left > 1) {
+    /* Recursively sort the left subset. */
+    pointsort(sortarray, left);
+  }
+  if (right < arraysize - 2) {
+    /* Recursively sort the right subset. */
+    pointsort(&sortarray[right + 1], arraysize - right - 1);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  pointmedian()   An order statistic algorithm, almost.  Shuffles an array */
+/*                  of points so that the first `median' points occur        */
+/*                  lexicographically before the remaining points.           */
+/*                                                                           */
+/*  Uses the x-coordinate as the primary key if axis == 0; the y-coordinate  */
+/*  if axis == 1.  Very similar to the pointsort() procedure, but runs in    */
+/*  randomized linear time.                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void pointmedian(sortarray, arraysize, median, axis)
+point *sortarray;
+int arraysize;
+int median;
+int axis;
+{
+  int left, right;
+  int pivot;
+  REAL pivot1, pivot2;
+  point temp;
+
+  if (arraysize == 2) {
+    /* Recursive base case. */
+    if ((sortarray[0][axis] > sortarray[1][axis]) ||
+        ((sortarray[0][axis] == sortarray[1][axis]) &&
+         (sortarray[0][1 - axis] > sortarray[1][1 - axis]))) {
+      temp = sortarray[1];
+      sortarray[1] = sortarray[0];
+      sortarray[0] = temp;
+    }
+    return;
+  }
+  /* Choose a random pivot to split the array. */
+  pivot = (int) randomnation(arraysize);
+  pivot1 = sortarray[pivot][axis];
+  pivot2 = sortarray[pivot][1 - axis];
+  /* Split the array. */
+  left = -1;
+  right = arraysize;
+  while (left < right) {
+    /* Search for a point whose x-coordinate is too large for the left. */
+    do {
+      left++;
+    } while ((left <= right) && ((sortarray[left][axis] < pivot1) ||
+                                 ((sortarray[left][axis] == pivot1) &&
+                                  (sortarray[left][1 - axis] < pivot2))));
+    /* Search for a point whose x-coordinate is too small for the right. */
+    do {
+      right--;
+    } while ((left <= right) && ((sortarray[right][axis] > pivot1) ||
+                                 ((sortarray[right][axis] == pivot1) &&
+                                  (sortarray[right][1 - axis] > pivot2))));
+    if (left < right) {
+      /* Swap the left and right points. */
+      temp = sortarray[left];
+      sortarray[left] = sortarray[right];
+      sortarray[right] = temp;
+    }
+  }
+  /* Unlike in pointsort(), at most one of the following */
+  /*   conditionals is true.                             */
+  if (left > median) {
+    /* Recursively shuffle the left subset. */
+    pointmedian(sortarray, left, median, axis);
+  }
+  if (right < median - 1) {
+    /* Recursively shuffle the right subset. */
+    pointmedian(&sortarray[right + 1], arraysize - right - 1,
+                median - right - 1, axis);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  alternateaxes()   Sorts the points as appropriate for the divide-and-    */
+/*                    conquer algorithm with alternating cuts.               */
+/*                                                                           */
+/*  Partitions by x-coordinate if axis == 0; by y-coordinate if axis == 1.   */
+/*  For the base case, subsets containing only two or three points are       */
+/*  always sorted by x-coordinate.                                           */
+/*                                                                           */
+/*****************************************************************************/
+
+void alternateaxes(sortarray, arraysize, axis)
+point *sortarray;
+int arraysize;
+int axis;
+{
+  int divider;
+
+  divider = arraysize >> 1;
+  if (arraysize <= 3) {
+    /* Recursive base case:  subsets of two or three points will be      */
+    /*   handled specially, and should always be sorted by x-coordinate. */
+    axis = 0;
+  }
+  /* Partition with a horizontal or vertical cut. */
+  pointmedian(sortarray, arraysize, divider, axis);
+  /* Recursively partition the subsets with a cross cut. */
+  if (arraysize - divider >= 2) {
+    if (divider >= 2) {
+      alternateaxes(sortarray, divider, 1 - axis);
+    }
+    alternateaxes(&sortarray[divider], arraysize - divider, 1 - axis);
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  mergehulls()   Merge two adjacent Delaunay triangulations into a         */
+/*                 single Delaunay triangulation.                            */
+/*                                                                           */
+/*  This is similar to the algorithm given by Guibas and Stolfi, but uses    */
+/*  a triangle-based, rather than edge-based, data structure.                */
+/*                                                                           */
+/*  The algorithm walks up the gap between the two triangulations, knitting  */
+/*  them together.  As they are merged, some of their bounding triangles     */
+/*  are converted into real triangles of the triangulation.  The procedure   */
+/*  pulls each hull's bounding triangles apart, then knits them together     */
+/*  like the teeth of two gears.  The Delaunay property determines, at each  */
+/*  step, whether the next "tooth" is a bounding triangle of the left hull   */
+/*  or the right.  When a bounding triangle becomes real, its apex is        */
+/*  changed from NULL to a real point.                                       */
+/*                                                                           */
+/*  Only two new triangles need to be allocated.  These become new bounding  */
+/*  triangles at the top and bottom of the seam.  They are used to connect   */
+/*  the remaining bounding triangles (those that have not been converted     */
+/*  into real triangles) into a single fan.                                  */
+/*                                                                           */
+/*  On entry, `farleft' and `innerleft' are bounding triangles of the left   */
+/*  triangulation.  The origin of `farleft' is the leftmost vertex, and      */
+/*  the destination of `innerleft' is the rightmost vertex of the            */
+/*  triangulation.  Similarly, `innerright' and `farright' are bounding      */
+/*  triangles of the right triangulation.  The origin of `innerright' and    */
+/*  destination of `farright' are the leftmost and rightmost vertices.       */
+/*                                                                           */
+/*  On completion, the origin of `farleft' is the leftmost vertex of the     */
+/*  merged triangulation, and the destination of `farright' is the rightmost */
+/*  vertex.                                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void mergehulls(farleft, innerleft, innerright, farright, axis)
+struct triedge *farleft;
+struct triedge *innerleft;
+struct triedge *innerright;
+struct triedge *farright;
+int axis;
+{
+  struct triedge leftcand, rightcand;
+  struct triedge baseedge;
+  struct triedge nextedge;
+  struct triedge sidecasing, topcasing, outercasing;
+  struct triedge checkedge;
+  point innerleftdest;
+  point innerrightorg;
+  point innerleftapex, innerrightapex;
+  point farleftpt, farrightpt;
+  point farleftapex, farrightapex;
+  point lowerleft, lowerright;
+  point upperleft, upperright;
+  point nextapex;
+  point checkvertex;
+  int changemade;
+  int badedge;
+  int leftfinished, rightfinished;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  dest(*innerleft, innerleftdest);
+  apex(*innerleft, innerleftapex);
+  org(*innerright, innerrightorg);
+  apex(*innerright, innerrightapex);
+  /* Special treatment for horizontal cuts. */
+  if (dwyer && (axis == 1)) {
+    org(*farleft, farleftpt);
+    apex(*farleft, farleftapex);
+    dest(*farright, farrightpt);
+    apex(*farright, farrightapex);
+    /* The pointers to the extremal points are shifted to point to the */
+    /*   topmost and bottommost point of each hull, rather than the    */
+    /*   leftmost and rightmost points.                                */
+    while (farleftapex[1] < farleftpt[1]) {
+      lnextself(*farleft);
+      symself(*farleft);
+      farleftpt = farleftapex;
+      apex(*farleft, farleftapex);
+    }
+    sym(*innerleft, checkedge);
+    apex(checkedge, checkvertex);
+    while (checkvertex[1] > innerleftdest[1]) {
+      lnext(checkedge, *innerleft);
+      innerleftapex = innerleftdest;
+      innerleftdest = checkvertex;
+      sym(*innerleft, checkedge);
+      apex(checkedge, checkvertex);
+    }
+    while (innerrightapex[1] < innerrightorg[1]) {
+      lnextself(*innerright);
+      symself(*innerright);
+      innerrightorg = innerrightapex;
+      apex(*innerright, innerrightapex);
+    }
+    sym(*farright, checkedge);
+    apex(checkedge, checkvertex);
+    while (checkvertex[1] > farrightpt[1]) {
+      lnext(checkedge, *farright);
+      farrightapex = farrightpt;
+      farrightpt = checkvertex;
+      sym(*farright, checkedge);
+      apex(checkedge, checkvertex);
+    }
+  }
+  /* Find a line tangent to and below both hulls. */
+  do {
+    changemade = 0;
+    /* Make innerleftdest the "bottommost" point of the left hull. */
+    if (counterclockwise(innerleftdest, innerleftapex, innerrightorg) > 0.0) {
+      lprevself(*innerleft);
+      symself(*innerleft);
+      innerleftdest = innerleftapex;
+      apex(*innerleft, innerleftapex);
+      changemade = 1;
+    }
+    /* Make innerrightorg the "bottommost" point of the right hull. */
+    if (counterclockwise(innerrightapex, innerrightorg, innerleftdest) > 0.0) {
+      lnextself(*innerright);
+      symself(*innerright);
+      innerrightorg = innerrightapex;
+      apex(*innerright, innerrightapex);
+      changemade = 1;
+    }
+  } while (changemade);
+  /* Find the two candidates to be the next "gear tooth". */
+  sym(*innerleft, leftcand);
+  sym(*innerright, rightcand);
+  /* Create the bottom new bounding triangle. */
+  maketriangle(&baseedge);
+  /* Connect it to the bounding boxes of the left and right triangulations. */
+  bond(baseedge, *innerleft);
+  lnextself(baseedge);
+  bond(baseedge, *innerright);
+  lnextself(baseedge);
+  setorg(baseedge, innerrightorg);
+  setdest(baseedge, innerleftdest);
+  /* Apex is intentionally left NULL. */
+  if (verbose > 2) {
+    printf("  Creating base bounding ");
+    printtriangle(&baseedge);
+  }
+  /* Fix the extreme triangles if necessary. */
+  org(*farleft, farleftpt);
+  if (innerleftdest == farleftpt) {
+    lnext(baseedge, *farleft);
+  }
+  dest(*farright, farrightpt);
+  if (innerrightorg == farrightpt) {
+    lprev(baseedge, *farright);
+  }
+  /* The vertices of the current knitting edge. */
+  lowerleft = innerleftdest;
+  lowerright = innerrightorg;
+  /* The candidate vertices for knitting. */
+  apex(leftcand, upperleft);
+  apex(rightcand, upperright);
+  /* Walk up the gap between the two triangulations, knitting them together. */
+  while (1) {
+    /* Have we reached the top?  (This isn't quite the right question,       */
+    /*   because even though the left triangulation might seem finished now, */
+    /*   moving up on the right triangulation might reveal a new point of    */
+    /*   the left triangulation.  And vice-versa.)                           */
+    leftfinished = counterclockwise(upperleft, lowerleft, lowerright) <= 0.0;
+    rightfinished = counterclockwise(upperright, lowerleft, lowerright) <= 0.0;
+    if (leftfinished && rightfinished) {
+      /* Create the top new bounding triangle. */
+      maketriangle(&nextedge);
+      setorg(nextedge, lowerleft);
+      setdest(nextedge, lowerright);
+      /* Apex is intentionally left NULL. */
+      /* Connect it to the bounding boxes of the two triangulations. */
+      bond(nextedge, baseedge);
+      lnextself(nextedge);
+      bond(nextedge, rightcand);
+      lnextself(nextedge);
+      bond(nextedge, leftcand);
+      if (verbose > 2) {
+        printf("  Creating top bounding ");
+        printtriangle(&baseedge);
+      }
+      /* Special treatment for horizontal cuts. */
+      if (dwyer && (axis == 1)) {
+        org(*farleft, farleftpt);
+        apex(*farleft, farleftapex);
+        dest(*farright, farrightpt);
+        apex(*farright, farrightapex);
+        sym(*farleft, checkedge);
+        apex(checkedge, checkvertex);
+        /* The pointers to the extremal points are restored to the leftmost */
+        /*   and rightmost points (rather than topmost and bottommost).     */
+        while (checkvertex[0] < farleftpt[0]) {
+          lprev(checkedge, *farleft);
+          farleftapex = farleftpt;
+          farleftpt = checkvertex;
+          sym(*farleft, checkedge);
+          apex(checkedge, checkvertex);
+        }
+        while (farrightapex[0] > farrightpt[0]) {
+          lprevself(*farright);
+          symself(*farright);
+          farrightpt = farrightapex;
+          apex(*farright, farrightapex);
+        }
+      }
+      return;
+    }
+    /* Consider eliminating edges from the left triangulation. */
+    if (!leftfinished) {
+      /* What vertex would be exposed if an edge were deleted? */
+      lprev(leftcand, nextedge);
+      symself(nextedge);
+      apex(nextedge, nextapex);
+      /* If nextapex is NULL, then no vertex would be exposed; the */
+      /*   triangulation would have been eaten right through.      */
+      if (nextapex != (point) NULL) {
+        /* Check whether the edge is Delaunay. */
+        badedge = incircle(lowerleft, lowerright, upperleft, nextapex) > 0.0;
+        while (badedge) {
+          /* Eliminate the edge with an edge flip.  As a result, the    */
+          /*   left triangulation will have one more boundary triangle. */
+          lnextself(nextedge);
+          sym(nextedge, topcasing);
+          lnextself(nextedge);
+          sym(nextedge, sidecasing);
+          bond(nextedge, topcasing);
+          bond(leftcand, sidecasing);
+          lnextself(leftcand);
+          sym(leftcand, outercasing);
+          lprevself(nextedge);
+          bond(nextedge, outercasing);
+          /* Correct the vertices to reflect the edge flip. */
+          setorg(leftcand, lowerleft);
+          setdest(leftcand, NULL);
+          setapex(leftcand, nextapex);
+          setorg(nextedge, NULL);
+          setdest(nextedge, upperleft);
+          setapex(nextedge, nextapex);
+          /* Consider the newly exposed vertex. */
+          upperleft = nextapex;
+          /* What vertex would be exposed if another edge were deleted? */
+          triedgecopy(sidecasing, nextedge);
+          apex(nextedge, nextapex);
+          if (nextapex != (point) NULL) {
+            /* Check whether the edge is Delaunay. */
+            badedge = incircle(lowerleft, lowerright, upperleft, nextapex)
+                      > 0.0;
+          } else {
+            /* Avoid eating right through the triangulation. */
+            badedge = 0;
+          }
+        }
+      }
+    }
+    /* Consider eliminating edges from the right triangulation. */
+    if (!rightfinished) {
+      /* What vertex would be exposed if an edge were deleted? */
+      lnext(rightcand, nextedge);
+      symself(nextedge);
+      apex(nextedge, nextapex);
+      /* If nextapex is NULL, then no vertex would be exposed; the */
+      /*   triangulation would have been eaten right through.      */
+      if (nextapex != (point) NULL) {
+        /* Check whether the edge is Delaunay. */
+        badedge = incircle(lowerleft, lowerright, upperright, nextapex) > 0.0;
+        while (badedge) {
+          /* Eliminate the edge with an edge flip.  As a result, the     */
+          /*   right triangulation will have one more boundary triangle. */
+          lprevself(nextedge);
+          sym(nextedge, topcasing);
+          lprevself(nextedge);
+          sym(nextedge, sidecasing);
+          bond(nextedge, topcasing);
+          bond(rightcand, sidecasing);
+          lprevself(rightcand);
+          sym(rightcand, outercasing);
+          lnextself(nextedge);
+          bond(nextedge, outercasing);
+          /* Correct the vertices to reflect the edge flip. */
+          setorg(rightcand, NULL);
+          setdest(rightcand, lowerright);
+          setapex(rightcand, nextapex);
+          setorg(nextedge, upperright);
+          setdest(nextedge, NULL);
+          setapex(nextedge, nextapex);
+          /* Consider the newly exposed vertex. */
+          upperright = nextapex;
+          /* What vertex would be exposed if another edge were deleted? */
+          triedgecopy(sidecasing, nextedge);
+          apex(nextedge, nextapex);
+          if (nextapex != (point) NULL) {
+            /* Check whether the edge is Delaunay. */
+            badedge = incircle(lowerleft, lowerright, upperright, nextapex)
+                      > 0.0;
+          } else {
+            /* Avoid eating right through the triangulation. */
+            badedge = 0;
+          }
+        }
+      }
+    }
+    if (leftfinished || (!rightfinished &&
+           (incircle(upperleft, lowerleft, lowerright, upperright) > 0.0))) {
+      /* Knit the triangulations, adding an edge from `lowerleft' */
+      /*   to `upperright'.                                       */
+      bond(baseedge, rightcand);
+      lprev(rightcand, baseedge);
+      setdest(baseedge, lowerleft);
+      lowerright = upperright;
+      sym(baseedge, rightcand);
+      apex(rightcand, upperright);
+    } else {
+      /* Knit the triangulations, adding an edge from `upperleft' */
+      /*   to `lowerright'.                                       */
+      bond(baseedge, leftcand);
+      lnext(leftcand, baseedge);
+      setorg(baseedge, lowerright);
+      lowerleft = upperleft;
+      sym(baseedge, leftcand);
+      apex(leftcand, upperleft);
+    }
+    if (verbose > 2) {
+      printf("  Connecting ");
+      printtriangle(&baseedge);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  divconqrecurse()   Recursively form a Delaunay triangulation by the      */
+/*                     divide-and-conquer method.                            */
+/*                                                                           */
+/*  Recursively breaks down the problem into smaller pieces, which are       */
+/*  knitted together by mergehulls().  The base cases (problems of two or    */
+/*  three points) are handled specially here.                                */
+/*                                                                           */
+/*  On completion, `farleft' and `farright' are bounding triangles such that */
+/*  the origin of `farleft' is the leftmost vertex (breaking ties by         */
+/*  choosing the highest leftmost vertex), and the destination of            */
+/*  `farright' is the rightmost vertex (breaking ties by choosing the        */
+/*  lowest rightmost vertex).                                                */
+/*                                                                           */
+/*****************************************************************************/
+
+void divconqrecurse(sortarray, vertices, axis, farleft, farright)
+point *sortarray;
+int vertices;
+int axis;
+struct triedge *farleft;
+struct triedge *farright;
+{
+  struct triedge midtri, tri1, tri2, tri3;
+  struct triedge innerleft, innerright;
+  REAL area;
+  int divider;
+
+  if (verbose > 2) {
+    printf("  Triangulating %d points.\n", vertices);
+  }
+  if (vertices == 2) {
+    /* The triangulation of two vertices is an edge.  An edge is */
+    /*   represented by two bounding triangles.                  */
+    maketriangle(farleft);
+    setorg(*farleft, sortarray[0]);
+    setdest(*farleft, sortarray[1]);
+    /* The apex is intentionally left NULL. */
+    maketriangle(farright);
+    setorg(*farright, sortarray[1]);
+    setdest(*farright, sortarray[0]);
+    /* The apex is intentionally left NULL. */
+    bond(*farleft, *farright);
+    lprevself(*farleft);
+    lnextself(*farright);
+    bond(*farleft, *farright);
+    lprevself(*farleft);
+    lnextself(*farright);
+    bond(*farleft, *farright);
+    if (verbose > 2) {
+      printf("  Creating ");
+      printtriangle(farleft);
+      printf("  Creating ");
+      printtriangle(farright);
+    }
+    /* Ensure that the origin of `farleft' is sortarray[0]. */
+    lprev(*farright, *farleft);
+    return;
+  } else if (vertices == 3) {
+    /* The triangulation of three vertices is either a triangle (with */
+    /*   three bounding triangles) or two edges (with four bounding   */
+    /*   triangles).  In either case, four triangles are created.     */
+    maketriangle(&midtri);
+    maketriangle(&tri1);
+    maketriangle(&tri2);
+    maketriangle(&tri3);
+    area = counterclockwise(sortarray[0], sortarray[1], sortarray[2]);
+    if (area == 0.0) {
+      /* Three collinear points; the triangulation is two edges. */
+      setorg(midtri, sortarray[0]);
+      setdest(midtri, sortarray[1]);
+      setorg(tri1, sortarray[1]);
+      setdest(tri1, sortarray[0]);
+      setorg(tri2, sortarray[2]);
+      setdest(tri2, sortarray[1]);
+      setorg(tri3, sortarray[1]);
+      setdest(tri3, sortarray[2]);
+      /* All apices are intentionally left NULL. */
+      bond(midtri, tri1);
+      bond(tri2, tri3);
+      lnextself(midtri);
+      lprevself(tri1);
+      lnextself(tri2);
+      lprevself(tri3);
+      bond(midtri, tri3);
+      bond(tri1, tri2);
+      lnextself(midtri);
+      lprevself(tri1);
+      lnextself(tri2);
+      lprevself(tri3);
+      bond(midtri, tri1);
+      bond(tri2, tri3);
+      /* Ensure that the origin of `farleft' is sortarray[0]. */
+      triedgecopy(tri1, *farleft);
+      /* Ensure that the destination of `farright' is sortarray[2]. */
+      triedgecopy(tri2, *farright);
+    } else {
+      /* The three points are not collinear; the triangulation is one */
+      /*   triangle, namely `midtri'.                                 */
+      setorg(midtri, sortarray[0]);
+      setdest(tri1, sortarray[0]);
+      setorg(tri3, sortarray[0]);
+      /* Apices of tri1, tri2, and tri3 are left NULL. */
+      if (area > 0.0) {
+        /* The vertices are in counterclockwise order. */
+        setdest(midtri, sortarray[1]);
+        setorg(tri1, sortarray[1]);
+        setdest(tri2, sortarray[1]);
+        setapex(midtri, sortarray[2]);
+        setorg(tri2, sortarray[2]);
+        setdest(tri3, sortarray[2]);
+      } else {
+        /* The vertices are in clockwise order. */
+        setdest(midtri, sortarray[2]);
+        setorg(tri1, sortarray[2]);
+        setdest(tri2, sortarray[2]);
+        setapex(midtri, sortarray[1]);
+        setorg(tri2, sortarray[1]);
+        setdest(tri3, sortarray[1]);
+      }
+      /* The topology does not depend on how the vertices are ordered. */
+      bond(midtri, tri1);
+      lnextself(midtri);
+      bond(midtri, tri2);
+      lnextself(midtri);
+      bond(midtri, tri3);
+      lprevself(tri1);
+      lnextself(tri2);
+      bond(tri1, tri2);
+      lprevself(tri1);
+      lprevself(tri3);
+      bond(tri1, tri3);
+      lnextself(tri2);
+      lprevself(tri3);
+      bond(tri2, tri3);
+      /* Ensure that the origin of `farleft' is sortarray[0]. */
+      triedgecopy(tri1, *farleft);
+      /* Ensure that the destination of `farright' is sortarray[2]. */
+      if (area > 0.0) {
+        triedgecopy(tri2, *farright);
+      } else {
+        lnext(*farleft, *farright);
+      }
+    }
+    if (verbose > 2) {
+      printf("  Creating ");
+      printtriangle(&midtri);
+      printf("  Creating ");
+      printtriangle(&tri1);
+      printf("  Creating ");
+      printtriangle(&tri2);
+      printf("  Creating ");
+      printtriangle(&tri3);
+    }
+    return;
+  } else {
+    /* Split the vertices in half. */
+    divider = vertices >> 1;
+    /* Recursively triangulate each half. */
+    divconqrecurse(sortarray, divider, 1 - axis, farleft, &innerleft);
+    divconqrecurse(&sortarray[divider], vertices - divider, 1 - axis,
+                   &innerright, farright);
+    if (verbose > 1) {
+      printf("  Joining triangulations with %d and %d vertices.\n", divider,
+             vertices - divider);
+    }
+    /* Merge the two triangulations into one. */
+    mergehulls(farleft, &innerleft, &innerright, farright, axis);
+  }
+}
+
+long removeghosts(startghost)
+struct triedge *startghost;
+{
+  struct triedge searchedge;
+  struct triedge dissolveedge;
+  struct triedge deadtri;
+  point markorg;
+  long hullsize;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose) {
+    printf("  Removing ghost triangles.\n");
+  }
+  /* Find an edge on the convex hull to start point location from. */
+  lprev(*startghost, searchedge);
+  symself(searchedge);
+  dummytri[0] = encode(searchedge);
+  /* Remove the bounding box and count the convex hull edges. */
+  triedgecopy(*startghost, dissolveedge);
+  hullsize = 0;
+  do {
+    hullsize++;
+    lnext(dissolveedge, deadtri);
+    lprevself(dissolveedge);
+    symself(dissolveedge);
+    /* If no PSLG is involved, set the boundary markers of all the points */
+    /*   on the convex hull.  If a PSLG is used, this step is done later. */
+    if (!poly) {
+      /* Watch out for the case where all the input points are collinear. */
+      if (dissolveedge.tri != dummytri) {
+        org(dissolveedge, markorg);
+        if (pointmark(markorg) == 0) {
+          setpointmark(markorg, 1);
+        }
+      }
+    }
+    /* Remove a bounding triangle from a convex hull triangle. */
+    dissolve(dissolveedge);
+    /* Find the next bounding triangle. */
+    sym(deadtri, dissolveedge);
+    /* Delete the bounding triangle. */
+    triangledealloc(deadtri.tri);
+  } while (!triedgeequal(dissolveedge, *startghost));
+  return hullsize;
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  divconqdelaunay()   Form a Delaunay triangulation by the divide-and-     */
+/*                      conquer method.                                      */
+/*                                                                           */
+/*  Sorts the points, calls a recursive procedure to triangulate them, and   */
+/*  removes the bounding box, setting boundary markers as appropriate.       */
+/*                                                                           */
+/*****************************************************************************/
+
+long divconqdelaunay()
+{
+  point *sortarray;
+  struct triedge hullleft, hullright;
+  int divider;
+  int i, j;
+
+  /* Allocate an array of pointers to points for sorting. */
+  sortarray = (point *) malloc(inpoints * sizeof(point));
+  if (sortarray == (point *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  traversalinit(&points);
+  for (i = 0; i < inpoints; i++) {
+    sortarray[i] = pointtraverse();
+  }
+  if (verbose) {
+    printf("  Sorting points.\n");
+  }
+  /* Sort the points. */
+  pointsort(sortarray, inpoints);
+  /* Discard duplicate points, which can really mess up the algorithm. */
+  i = 0;
+  for (j = 1; j < inpoints; j++) {
+    if ((sortarray[i][0] == sortarray[j][0])
+        && (sortarray[i][1] == sortarray[j][1])) {
+      if (!quiet) {
+        printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+               sortarray[j][0], sortarray[j][1]);
+      }
+/*  Commented out - would eliminate point from output .node file, but causes
+    a failure if some segment has this point as an endpoint.
+      setpointmark(sortarray[j], DEADPOINT);
+*/
+    } else {
+      i++;
+      sortarray[i] = sortarray[j];
+    }
+  }
+  i++;
+  if (dwyer) {
+    /* Re-sort the array of points to accommodate alternating cuts. */
+    divider = i >> 1;
+    if (i - divider >= 2) {
+      if (divider >= 2) {
+        alternateaxes(sortarray, divider, 1);
+      }
+      alternateaxes(&sortarray[divider], i - divider, 1);
+    }
+  }
+  if (verbose) {
+    printf("  Forming triangulation.\n");
+  }
+  /* Form the Delaunay triangulation. */
+  divconqrecurse(sortarray, i, 0, &hullleft, &hullright);
+  free(sortarray);
+
+  return removeghosts(&hullleft);
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Divide-and-conquer Delaunay triangulation ends here       *********/
+
+/********* Incremental Delaunay triangulation begins here            *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  boundingbox()   Form an "infinite" bounding triangle to insert points    */
+/*                  into.                                                    */
+/*                                                                           */
+/*  The points at "infinity" are assigned finite coordinates, which are used */
+/*  by the point location routines, but (mostly) ignored by the Delaunay     */
+/*  edge flip routines.                                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+void boundingbox()
+{
+  struct triedge inftri;          /* Handle for the triangular bounding box. */
+  REAL width;
+
+  if (verbose) {
+    printf("  Creating triangular bounding box.\n");
+  }
+  /* Find the width (or height, whichever is larger) of the triangulation. */
+  width = xmax - xmin;
+  if (ymax - ymin > width) {
+    width = ymax - ymin;
+  }
+  if (width == 0.0) {
+    width = 1.0;
+  }
+  /* Create the vertices of the bounding box. */
+  infpoint1 = (point) malloc(points.itembytes);
+  infpoint2 = (point) malloc(points.itembytes);
+  infpoint3 = (point) malloc(points.itembytes);
+  if ((infpoint1 == (point) NULL) || (infpoint2 == (point) NULL)
+      || (infpoint3 == (point) NULL)) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  infpoint1[0] = xmin - 50.0 * width;
+  infpoint1[1] = ymin - 40.0 * width;
+  infpoint2[0] = xmax + 50.0 * width;
+  infpoint2[1] = ymin - 40.0 * width;
+  infpoint3[0] = 0.5 * (xmin + xmax);
+  infpoint3[1] = ymax + 60.0 * width;
+
+  /* Create the bounding box. */
+  maketriangle(&inftri);
+  setorg(inftri, infpoint1);
+  setdest(inftri, infpoint2);
+  setapex(inftri, infpoint3);
+  /* Link dummytri to the bounding box so we can always find an */
+  /*   edge to begin searching (point location) from.           */
+  dummytri[0] = (triangle) inftri.tri;
+  if (verbose > 2) {
+    printf("  Creating ");
+    printtriangle(&inftri);
+  }
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  removebox()   Remove the "infinite" bounding triangle, setting boundary  */
+/*                markers as appropriate.                                    */
+/*                                                                           */
+/*  The triangular bounding box has three boundary triangles (one for each   */
+/*  side of the bounding box), and a bunch of triangles fanning out from     */
+/*  the three bounding box vertices (one triangle for each edge of the       */
+/*  convex hull of the inner mesh).  This routine removes these triangles.   */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+long removebox()
+{
+  struct triedge deadtri;
+  struct triedge searchedge;
+  struct triedge checkedge;
+  struct triedge nextedge, finaledge, dissolveedge;
+  point markorg;
+  long hullsize;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose) {
+    printf("  Removing triangular bounding box.\n");
+  }
+  /* Find a boundary triangle. */
+  nextedge.tri = dummytri;
+  nextedge.orient = 0;
+  symself(nextedge);
+  /* Mark a place to stop. */
+  lprev(nextedge, finaledge);
+  lnextself(nextedge);
+  symself(nextedge);
+  /* Find a triangle (on the boundary of the point set) that isn't */
+  /*   a bounding box triangle.                                    */
+  lprev(nextedge, searchedge);
+  symself(searchedge);
+  /* Check whether nextedge is another boundary triangle */
+  /*   adjacent to the first one.                        */
+  lnext(nextedge, checkedge);
+  symself(checkedge);
+  if (checkedge.tri == dummytri) {
+    /* Go on to the next triangle.  There are only three boundary   */
+    /*   triangles, and this next triangle cannot be the third one, */
+    /*   so it's safe to stop here.                                 */
+    lprevself(searchedge);
+    symself(searchedge);
+  }
+  /* Find a new boundary edge to search from, as the current search */
+  /*   edge lies on a bounding box triangle and will be deleted.    */
+  dummytri[0] = encode(searchedge);
+  hullsize = -2l;
+  while (!triedgeequal(nextedge, finaledge)) {
+    hullsize++;
+    lprev(nextedge, dissolveedge);
+    symself(dissolveedge);
+    /* If not using a PSLG, the vertices should be marked now. */
+    /*   (If using a PSLG, markhull() will do the job.)        */
+    if (!poly) {
+      /* Be careful!  One must check for the case where all the input   */
+      /*   points are collinear, and thus all the triangles are part of */
+      /*   the bounding box.  Otherwise, the setpointmark() call below  */
+      /*   will cause a bad pointer reference.                          */
+      if (dissolveedge.tri != dummytri) {
+        org(dissolveedge, markorg);
+        if (pointmark(markorg) == 0) {
+          setpointmark(markorg, 1);
+        }
+      }
+    }
+    /* Disconnect the bounding box triangle from the mesh triangle. */
+    dissolve(dissolveedge);
+    lnext(nextedge, deadtri);
+    sym(deadtri, nextedge);
+    /* Get rid of the bounding box triangle. */
+    triangledealloc(deadtri.tri);
+    /* Do we need to turn the corner? */
+    if (nextedge.tri == dummytri) {
+      /* Turn the corner. */
+      triedgecopy(dissolveedge, nextedge);
+    }
+  }
+  triangledealloc(finaledge.tri);
+
+  free(infpoint1);                  /* Deallocate the bounding box vertices. */
+  free(infpoint2);
+  free(infpoint3);
+
+  return hullsize;
+}
+
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  incrementaldelaunay()   Form a Delaunay triangulation by incrementally   */
+/*                          adding vertices.                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+
+long incrementaldelaunay()
+{
+  struct triedge starttri;
+  point pointloop;
+  int i;
+
+  /* Create a triangular bounding box. */
+  boundingbox();
+  if (verbose) {
+    printf("  Incrementally inserting points.\n");
+  }
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  i = 1;
+  while (pointloop != (point) NULL) {
+    /* Find a boundary triangle to search from. */
+    starttri.tri = (triangle *) NULL;
+    if (insertsite(pointloop, &starttri, (struct edge *) NULL, 0, 0) ==
+        DUPLICATEPOINT) {
+      if (!quiet) {
+        printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+               pointloop[0], pointloop[1]);
+      }
+/*  Commented out - would eliminate point from output .node file.
+      setpointmark(pointloop, DEADPOINT);
+*/
+    }
+    pointloop = pointtraverse();
+    i++;
+  }
+  /* Remove the bounding box. */
+  return removebox();
+}
+
+#endif /* not REDUCED */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Incremental Delaunay triangulation ends here              *********/
+
+/********* Sweepline Delaunay triangulation begins here              *********/
+/**                                                                         **/
+/**                                                                         **/
+
+#ifndef REDUCED
+
+void eventheapinsert(heap, heapsize, newevent)
+struct event **heap;
+int heapsize;
+struct event *newevent;
+{
+  REAL eventx, eventy;
+  int eventnum;
+  int parent;
+  int notdone;
+
+  eventx = newevent->xkey;
+  eventy = newevent->ykey;
+  eventnum = heapsize;
+  notdone = eventnum > 0;
+  while (notdone) {
+    parent = (eventnum - 1) >> 1;
+    if ((heap[parent]->ykey < eventy) ||
+        ((heap[parent]->ykey == eventy)
+         && (heap[parent]->xkey <= eventx))) {
+      notdone = 0;
+    } else {
+      heap[eventnum] = heap[parent];
+      heap[eventnum]->heapposition = eventnum;
+
+      eventnum = parent;
+      notdone = eventnum > 0;
+    }
+  }
+  heap[eventnum] = newevent;
+  newevent->heapposition = eventnum;
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void eventheapify(heap, heapsize, eventnum)
+struct event **heap;
+int heapsize;
+int eventnum;
+{
+  struct event *thisevent;
+  REAL eventx, eventy;
+  int leftchild, rightchild;
+  int smallest;
+  int notdone;
+
+  thisevent = heap[eventnum];
+  eventx = thisevent->xkey;
+  eventy = thisevent->ykey;
+  leftchild = 2 * eventnum + 1;
+  notdone = leftchild < heapsize;
+  while (notdone) {
+    if ((heap[leftchild]->ykey < eventy) ||
+        ((heap[leftchild]->ykey == eventy)
+         && (heap[leftchild]->xkey < eventx))) {
+      smallest = leftchild;
+    } else {
+      smallest = eventnum;
+    }
+    rightchild = leftchild + 1;
+    if (rightchild < heapsize) {
+      if ((heap[rightchild]->ykey < heap[smallest]->ykey) ||
+          ((heap[rightchild]->ykey == heap[smallest]->ykey)
+           && (heap[rightchild]->xkey < heap[smallest]->xkey))) {
+        smallest = rightchild;
+      }
+    }
+    if (smallest == eventnum) {
+      notdone = 0;
+    } else {
+      heap[eventnum] = heap[smallest];
+      heap[eventnum]->heapposition = eventnum;
+      heap[smallest] = thisevent;
+      thisevent->heapposition = smallest;
+
+      eventnum = smallest;
+      leftchild = 2 * eventnum + 1;
+      notdone = leftchild < heapsize;
+    }
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void eventheapdelete(heap, heapsize, eventnum)
+struct event **heap;
+int heapsize;
+int eventnum;
+{
+  struct event *moveevent;
+  REAL eventx, eventy;
+  int parent;
+  int notdone;
+
+  moveevent = heap[heapsize - 1];
+  if (eventnum > 0) {
+    eventx = moveevent->xkey;
+    eventy = moveevent->ykey;
+    do {
+      parent = (eventnum - 1) >> 1;
+      if ((heap[parent]->ykey < eventy) ||
+          ((heap[parent]->ykey == eventy)
+           && (heap[parent]->xkey <= eventx))) {
+        notdone = 0;
+      } else {
+        heap[eventnum] = heap[parent];
+        heap[eventnum]->heapposition = eventnum;
+
+        eventnum = parent;
+        notdone = eventnum > 0;
+      }
+    } while (notdone);
+  }
+  heap[eventnum] = moveevent;
+  moveevent->heapposition = eventnum;
+  eventheapify(heap, heapsize - 1, eventnum);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void createeventheap(eventheap, events, freeevents)
+struct event ***eventheap;
+struct event **events;
+struct event **freeevents;
+{
+  point thispoint;
+  int maxevents;
+  int i;
+
+  maxevents = (3 * inpoints) / 2;
+  *eventheap = (struct event **) malloc(maxevents * sizeof(struct event *));
+  if (*eventheap == (struct event **) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  *events = (struct event *) malloc(maxevents * sizeof(struct event));
+  if (*events == (struct event *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  traversalinit(&points);
+  for (i = 0; i < inpoints; i++) {
+    thispoint = pointtraverse();
+    (*events)[i].eventptr = (VOID *) thispoint;
+    (*events)[i].xkey = thispoint[0];
+    (*events)[i].ykey = thispoint[1];
+    eventheapinsert(*eventheap, i, *events + i);
+  }
+  *freeevents = (struct event *) NULL;
+  for (i = maxevents - 1; i >= inpoints; i--) {
+    (*events)[i].eventptr = (VOID *) *freeevents;
+    *freeevents = *events + i;
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+int rightofhyperbola(fronttri, newsite)
+struct triedge *fronttri;
+point newsite;
+{
+  point leftpoint, rightpoint;
+  REAL dxa, dya, dxb, dyb;
+
+  hyperbolacount++;
+
+  dest(*fronttri, leftpoint);
+  apex(*fronttri, rightpoint);
+  if ((leftpoint[1] < rightpoint[1])
+      || ((leftpoint[1] == rightpoint[1]) && (leftpoint[0] < rightpoint[0]))) {
+    if (newsite[0] >= rightpoint[0]) {
+      return 1;
+    }
+  } else {
+    if (newsite[0] <= leftpoint[0]) {
+      return 0;
+    }
+  }
+  dxa = leftpoint[0] - newsite[0];
+  dya = leftpoint[1] - newsite[1];
+  dxb = rightpoint[0] - newsite[0];
+  dyb = rightpoint[1] - newsite[1];
+  return dya * (dxb * dxb + dyb * dyb) > dyb * (dxa * dxa + dya * dya);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+REAL circletop(pa, pb, pc, ccwabc)
+point pa;
+point pb;
+point pc;
+REAL ccwabc;
+{
+  REAL xac, yac, xbc, ybc, xab, yab;
+  REAL aclen2, bclen2, ablen2;
+
+  circletopcount++;
+
+  xac = pa[0] - pc[0];
+  yac = pa[1] - pc[1];
+  xbc = pb[0] - pc[0];
+  ybc = pb[1] - pc[1];
+  xab = pa[0] - pb[0];
+  yab = pa[1] - pb[1];
+  aclen2 = xac * xac + yac * yac;
+  bclen2 = xbc * xbc + ybc * ybc;
+  ablen2 = xab * xab + yab * yab;
+  return pc[1] + (xac * bclen2 - xbc * aclen2 + sqrt(aclen2 * bclen2 * ablen2))
+               / (2.0 * ccwabc);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+void check4deadevent(checktri, freeevents, eventheap, heapsize)
+struct triedge *checktri;
+struct event **freeevents;
+struct event **eventheap;
+int *heapsize;
+{
+  struct event *deadevent;
+  point eventpoint;
+  int eventnum;
+
+  org(*checktri, eventpoint);
+  if (eventpoint != (point) NULL) {
+    deadevent = (struct event *) eventpoint;
+    eventnum = deadevent->heapposition;
+    deadevent->eventptr = (VOID *) *freeevents;
+    *freeevents = deadevent;
+    eventheapdelete(eventheap, *heapsize, eventnum);
+    (*heapsize)--;
+    setorg(*checktri, NULL);
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *splay(splaytree, searchpoint, searchtri)
+struct splaynode *splaytree;
+point searchpoint;
+struct triedge *searchtri;
+{
+  struct splaynode *child, *grandchild;
+  struct splaynode *lefttree, *righttree;
+  struct splaynode *leftright;
+  point checkpoint;
+  int rightofroot, rightofchild;
+
+  if (splaytree == (struct splaynode *) NULL) {
+    return (struct splaynode *) NULL;
+  }
+  dest(splaytree->keyedge, checkpoint);
+  if (checkpoint == splaytree->keydest) {
+    rightofroot = rightofhyperbola(&splaytree->keyedge, searchpoint);
+    if (rightofroot) {
+      triedgecopy(splaytree->keyedge, *searchtri);
+      child = splaytree->rchild;
+    } else {
+      child = splaytree->lchild;
+    }
+    if (child == (struct splaynode *) NULL) {
+      return splaytree;
+    }
+    dest(child->keyedge, checkpoint);
+    if (checkpoint != child->keydest) {
+      child = splay(child, searchpoint, searchtri);
+      if (child == (struct splaynode *) NULL) {
+        if (rightofroot) {
+          splaytree->rchild = (struct splaynode *) NULL;
+        } else {
+          splaytree->lchild = (struct splaynode *) NULL;
+        }
+        return splaytree;
+      }
+    }
+    rightofchild = rightofhyperbola(&child->keyedge, searchpoint);
+    if (rightofchild) {
+      triedgecopy(child->keyedge, *searchtri);
+      grandchild = splay(child->rchild, searchpoint, searchtri);
+      child->rchild = grandchild;
+    } else {
+      grandchild = splay(child->lchild, searchpoint, searchtri);
+      child->lchild = grandchild;
+    }
+    if (grandchild == (struct splaynode *) NULL) {
+      if (rightofroot) {
+        splaytree->rchild = child->lchild;
+        child->lchild = splaytree;
+      } else {
+        splaytree->lchild = child->rchild;
+        child->rchild = splaytree;
+      }
+      return child;
+    }
+    if (rightofchild) {
+      if (rightofroot) {
+        splaytree->rchild = child->lchild;
+        child->lchild = splaytree;
+      } else {
+        splaytree->lchild = grandchild->rchild;
+        grandchild->rchild = splaytree;
+      }
+      child->rchild = grandchild->lchild;
+      grandchild->lchild = child;
+    } else {
+      if (rightofroot) {
+        splaytree->rchild = grandchild->lchild;
+        grandchild->lchild = splaytree;
+      } else {
+        splaytree->lchild = child->rchild;
+        child->rchild = splaytree;
+      }
+      child->lchild = grandchild->rchild;
+      grandchild->rchild = child;
+    }
+    return grandchild;
+  } else {
+    lefttree = splay(splaytree->lchild, searchpoint, searchtri);
+    righttree = splay(splaytree->rchild, searchpoint, searchtri);
+
+    pooldealloc(&splaynodes, (VOID *) splaytree);
+    if (lefttree == (struct splaynode *) NULL) {
+      return righttree;
+    } else if (righttree == (struct splaynode *) NULL) {
+      return lefttree;
+    } else if (lefttree->rchild == (struct splaynode *) NULL) {
+      lefttree->rchild = righttree->lchild;
+      righttree->lchild = lefttree;
+      return righttree;
+    } else if (righttree->lchild == (struct splaynode *) NULL) {
+      righttree->lchild = lefttree->rchild;
+      lefttree->rchild = righttree;
+      return lefttree;
+    } else {
+/*      printf("Holy Toledo!!!\n"); */
+      leftright = lefttree->rchild;
+      while (leftright->rchild != (struct splaynode *) NULL) {
+        leftright = leftright->rchild;
+      }
+      leftright->rchild = righttree;
+      return lefttree;
+    }
+  }
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *splayinsert(splayroot, newkey, searchpoint)
+struct splaynode *splayroot;
+struct triedge *newkey;
+point searchpoint;
+{
+  struct splaynode *newsplaynode;
+
+  newsplaynode = (struct splaynode *) poolalloc(&splaynodes);
+  triedgecopy(*newkey, newsplaynode->keyedge);
+  dest(*newkey, newsplaynode->keydest);
+  if (splayroot == (struct splaynode *) NULL) {
+    newsplaynode->lchild = (struct splaynode *) NULL;
+    newsplaynode->rchild = (struct splaynode *) NULL;
+  } else if (rightofhyperbola(&splayroot->keyedge, searchpoint)) {
+    newsplaynode->lchild = splayroot;
+    newsplaynode->rchild = splayroot->rchild;
+    splayroot->rchild = (struct splaynode *) NULL;
+  } else {
+    newsplaynode->lchild = splayroot->lchild;
+    newsplaynode->rchild = splayroot;
+    splayroot->lchild = (struct splaynode *) NULL;
+  }
+  return newsplaynode;
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *circletopinsert(splayroot, newkey, pa, pb, pc, topy)
+struct splaynode *splayroot;
+struct triedge *newkey;
+point pa;
+point pb;
+point pc;
+REAL topy;
+{
+  REAL ccwabc;
+  REAL xac, yac, xbc, ybc;
+  REAL aclen2, bclen2;
+  REAL searchpoint[2];
+  struct triedge dummytri;
+
+  ccwabc = counterclockwise(pa, pb, pc);
+  xac = pa[0] - pc[0];
+  yac = pa[1] - pc[1];
+  xbc = pb[0] - pc[0];
+  ybc = pb[1] - pc[1];
+  aclen2 = xac * xac + yac * yac;
+  bclen2 = xbc * xbc + ybc * ybc;
+  searchpoint[0] = pc[0] - (yac * bclen2 - ybc * aclen2) / (2.0 * ccwabc);
+  searchpoint[1] = topy;
+  return splayinsert(splay(splayroot, (point) searchpoint, &dummytri), newkey,
+                     (point) searchpoint);
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+struct splaynode *frontlocate(splayroot, bottommost, searchpoint, searchtri,
+                              farright)
+struct splaynode *splayroot;
+struct triedge *bottommost;
+point searchpoint;
+struct triedge *searchtri;
+int *farright;
+{
+  int farrightflag;
+  triangle ptr;                       /* Temporary variable used by onext(). */
+
+  triedgecopy(*bottommost, *searchtri);
+  splayroot = splay(splayroot, searchpoint, searchtri);
+
+  farrightflag = 0;
+  while (!farrightflag && rightofhyperbola(searchtri, searchpoint)) {
+    onextself(*searchtri);
+    farrightflag = triedgeequal(*searchtri, *bottommost);
+  }
+  *farright = farrightflag;
+  return splayroot;
+}
+
+#endif /* not REDUCED */
+
+#ifndef REDUCED
+
+long sweeplinedelaunay()
+{
+  struct event **eventheap;
+  struct event *events;
+  struct event *freeevents;
+  struct event *nextevent;
+  struct event *newevent;
+  struct splaynode *splayroot;
+  struct triedge bottommost;
+  struct triedge searchtri;
+  struct triedge fliptri;
+  struct triedge lefttri, righttri, farlefttri, farrighttri;
+  struct triedge inserttri;
+  point firstpoint, secondpoint;
+  point nextpoint, lastpoint;
+  point connectpoint;
+  point leftpoint, midpoint, rightpoint;
+  REAL lefttest, righttest;
+  int heapsize;
+  int check4events, farrightflag;
+  triangle ptr;   /* Temporary variable used by sym(), onext(), and oprev(). */
+
+  poolinit(&splaynodes, sizeof(struct splaynode), SPLAYNODEPERBLOCK, POINTER,
+           0);
+  splayroot = (struct splaynode *) NULL;
+
+  if (verbose) {
+    printf("  Placing points in event heap.\n");
+  }
+  createeventheap(&eventheap, &events, &freeevents);
+  heapsize = inpoints;
+
+  if (verbose) {
+    printf("  Forming triangulation.\n");
+  }
+  maketriangle(&lefttri);
+  maketriangle(&righttri);
+  bond(lefttri, righttri);
+  lnextself(lefttri);
+  lprevself(righttri);
+  bond(lefttri, righttri);
+  lnextself(lefttri);
+  lprevself(righttri);
+  bond(lefttri, righttri);
+  firstpoint = (point) eventheap[0]->eventptr;
+  eventheap[0]->eventptr = (VOID *) freeevents;
+  freeevents = eventheap[0];
+  eventheapdelete(eventheap, heapsize, 0);
+  heapsize--;
+  do {
+    if (heapsize == 0) {
+      printf("Error:  Input points are all identical.\n");
+      exit(1);
+    }
+    secondpoint = (point) eventheap[0]->eventptr;
+    eventheap[0]->eventptr = (VOID *) freeevents;
+    freeevents = eventheap[0];
+    eventheapdelete(eventheap, heapsize, 0);
+    heapsize--;
+    if ((firstpoint[0] == secondpoint[0])
+        && (firstpoint[1] == secondpoint[1])) {
+      printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+             secondpoint[0], secondpoint[1]);
+/*  Commented out - would eliminate point from output .node file.
+      setpointmark(secondpoint, DEADPOINT);
+*/
+    }
+  } while ((firstpoint[0] == secondpoint[0])
+           && (firstpoint[1] == secondpoint[1]));
+  setorg(lefttri, firstpoint);
+  setdest(lefttri, secondpoint);
+  setorg(righttri, secondpoint);
+  setdest(righttri, firstpoint);
+  lprev(lefttri, bottommost);
+  lastpoint = secondpoint;
+  while (heapsize > 0) {
+    nextevent = eventheap[0];
+    eventheapdelete(eventheap, heapsize, 0);
+    heapsize--;
+    check4events = 1;
+    if (nextevent->xkey < xmin) {
+      decode(nextevent->eventptr, fliptri);
+      oprev(fliptri, farlefttri);
+      check4deadevent(&farlefttri, &freeevents, eventheap, &heapsize);
+      onext(fliptri, farrighttri);
+      check4deadevent(&farrighttri, &freeevents, eventheap, &heapsize);
+
+      if (triedgeequal(farlefttri, bottommost)) {
+        lprev(fliptri, bottommost);
+      }
+      flip(&fliptri);
+      setapex(fliptri, NULL);
+      lprev(fliptri, lefttri);
+      lnext(fliptri, righttri);
+      sym(lefttri, farlefttri);
+
+      if (randomnation(SAMPLERATE) == 0) {
+        symself(fliptri);
+        dest(fliptri, leftpoint);
+        apex(fliptri, midpoint);
+        org(fliptri, rightpoint);
+        splayroot = circletopinsert(splayroot, &lefttri, leftpoint, midpoint,
+                                    rightpoint, nextevent->ykey);
+      }
+    } else {
+      nextpoint = (point) nextevent->eventptr;
+      if ((nextpoint[0] == lastpoint[0]) && (nextpoint[1] == lastpoint[1])) {
+        printf(
+"Warning:  A duplicate point at (%.12g, %.12g) appeared and was ignored.\n",
+               nextpoint[0], nextpoint[1]);
+/*  Commented out - would eliminate point from output .node file.
+        setpointmark(nextpoint, DEADPOINT);
+*/
+        check4events = 0;
+      } else {
+        lastpoint = nextpoint;
+
+        splayroot = frontlocate(splayroot, &bottommost, nextpoint, &searchtri,
+                                &farrightflag);
+/*
+        triedgecopy(bottommost, searchtri);
+        farrightflag = 0;
+        while (!farrightflag && rightofhyperbola(&searchtri, nextpoint)) {
+          onextself(searchtri);
+          farrightflag = triedgeequal(searchtri, bottommost);
+        }
+*/
+
+        check4deadevent(&searchtri, &freeevents, eventheap, &heapsize);
+
+        triedgecopy(searchtri, farrighttri);
+        sym(searchtri, farlefttri);
+        maketriangle(&lefttri);
+        maketriangle(&righttri);
+        dest(farrighttri, connectpoint);
+        setorg(lefttri, connectpoint);
+        setdest(lefttri, nextpoint);
+        setorg(righttri, nextpoint);
+        setdest(righttri, connectpoint);
+        bond(lefttri, righttri);
+        lnextself(lefttri);
+        lprevself(righttri);
+        bond(lefttri, righttri);
+        lnextself(lefttri);
+        lprevself(righttri);
+        bond(lefttri, farlefttri);
+        bond(righttri, farrighttri);
+        if (!farrightflag && triedgeequal(farrighttri, bottommost)) {
+          triedgecopy(lefttri, bottommost);
+        }
+
+        if (randomnation(SAMPLERATE) == 0) {
+          splayroot = splayinsert(splayroot, &lefttri, nextpoint);
+        } else if (randomnation(SAMPLERATE) == 0) {
+          lnext(righttri, inserttri);
+          splayroot = splayinsert(splayroot, &inserttri, nextpoint);
+        }
+      }
+    }
+    nextevent->eventptr = (VOID *) freeevents;
+    freeevents = nextevent;
+
+    if (check4events) {
+      apex(farlefttri, leftpoint);
+      dest(lefttri, midpoint);
+      apex(lefttri, rightpoint);
+      lefttest = counterclockwise(leftpoint, midpoint, rightpoint);
+      if (lefttest > 0.0) {
+        newevent = freeevents;
+        freeevents = (struct event *) freeevents->eventptr;
+        newevent->xkey = xminextreme;
+        newevent->ykey = circletop(leftpoint, midpoint, rightpoint,
+                                   lefttest);
+        newevent->eventptr = (VOID *) encode(lefttri);
+        eventheapinsert(eventheap, heapsize, newevent);
+        heapsize++;
+        setorg(lefttri, newevent);
+      }
+      apex(righttri, leftpoint);
+      org(righttri, midpoint);
+      apex(farrighttri, rightpoint);
+      righttest = counterclockwise(leftpoint, midpoint, rightpoint);
+      if (righttest > 0.0) {
+        newevent = freeevents;
+        freeevents = (struct event *) freeevents->eventptr;
+        newevent->xkey = xminextreme;
+        newevent->ykey = circletop(leftpoint, midpoint, rightpoint,
+                                   righttest);
+        newevent->eventptr = (VOID *) encode(farrighttri);
+        eventheapinsert(eventheap, heapsize, newevent);
+        heapsize++;
+        setorg(farrighttri, newevent);
+      }
+    }
+  }
+
+  pooldeinit(&splaynodes);
+  lprevself(bottommost);
+  return removeghosts(&bottommost);
+}
+
+#endif /* not REDUCED */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Sweepline Delaunay triangulation ends here                *********/
+
+/********* General mesh construction routines begin here             *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  delaunay()   Form a Delaunay triangulation.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+long delaunay()
+{
+  eextras = 0;
+  initializetrisegpools();
+
+#ifdef REDUCED
+  if (!quiet) {
+    printf(
+      "Constructing Delaunay triangulation by divide-and-conquer method.\n");
+  }
+  return divconqdelaunay();
+#else /* not REDUCED */
+  if (!quiet) {
+    printf("Constructing Delaunay triangulation ");
+    if (incremental) {
+      printf("by incremental method.\n");
+    } else if (sweepline) {
+      printf("by sweepline method.\n");
+    } else {
+      printf("by divide-and-conquer method.\n");
+    }
+  }
+  if (incremental) {
+    return incrementaldelaunay();
+  } else if (sweepline) {
+    return sweeplinedelaunay();
+  } else {
+    return divconqdelaunay();
+  }
+#endif /* not REDUCED */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  reconstruct()   Reconstruct a triangulation from its .ele (and possibly  */
+/*                  .poly) file.  Used when the -r switch is used.           */
+/*                                                                           */
+/*  Reads an .ele file and reconstructs the original mesh.  If the -p switch */
+/*  is used, this procedure will also read a .poly file and reconstruct the  */
+/*  shell edges of the original mesh.  If the -a switch is used, this        */
+/*  procedure will also read an .area file and set a maximum area constraint */
+/*  on each triangle.                                                        */
+/*                                                                           */
+/*  Points that are not corners of triangles, such as nodes on edges of      */
+/*  subparametric elements, are discarded.                                   */
+/*                                                                           */
+/*  This routine finds the adjacencies between triangles (and shell edges)   */
+/*  by forming one stack of triangles for each vertex.  Each triangle is on  */
+/*  three different stacks simultaneously.  Each triangle's shell edge       */
+/*  pointers are used to link the items in each stack.  This memory-saving   */
+/*  feature makes the code harder to read.  The most important thing to keep */
+/*  in mind is that each triangle is removed from a stack precisely when     */
+/*  the corresponding pointer is adjusted to refer to a shell edge rather    */
+/*  than the next triangle of the stack.                                     */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+#ifdef TRILIBRARY
+
+int reconstruct(trianglelist, triangleattriblist, trianglearealist, elements,
+                corners, attribs, segmentlist, segmentmarkerlist,
+                numberofsegments)
+int *trianglelist;
+REAL *triangleattriblist;
+REAL *trianglearealist;
+int elements;
+int corners;
+int attribs;
+int *segmentlist;
+int *segmentmarkerlist;
+int numberofsegments;
+
+#else /* not TRILIBRARY */
+
+long reconstruct(elefilename, areafilename, polyfilename, polyfile)
+char *elefilename;
+char *areafilename;
+char *polyfilename;
+FILE *polyfile;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int pointindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *elefile;
+  FILE *areafile;
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  int areaelements;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop;
+  struct triedge triangleleft;
+  struct triedge checktri;
+  struct triedge checkleft;
+  struct triedge checkneighbor;
+  struct edge shelleloop;
+  triangle *vertexarray;
+  triangle *prevlink;
+  triangle nexttri;
+  point tdest, tapex;
+  point checkdest, checkapex;
+  point shorg;
+  point killpoint;
+  REAL area;
+  int corner[3];
+  int end[2];
+  int killpointindex;
+  int incorners;
+  int segmentmarkers;
+  int boundmarker;
+  int aroundpoint;
+  long hullsize;
+  int notfound;
+  int elementnumber, segmentnumber;
+  int i, j;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+#ifdef TRILIBRARY
+  inelements = elements;
+  incorners = corners;
+  if (incorners < 3) {
+    printf("Error:  Triangles must have at least 3 points.\n");
+    exit(1);
+  }
+  eextras = attribs;
+#else /* not TRILIBRARY */
+  /* Read the triangles from an .ele file. */
+  if (!quiet) {
+    printf("Opening %s.\n", elefilename);
+  }
+  elefile = fopen(elefilename, "r");
+  if (elefile == (FILE *) NULL) {
+    printf("  Error:  Cannot access file %s.\n", elefilename);
+    exit(1);
+  }
+  /* Read number of triangles, number of points per triangle, and */
+  /*   number of triangle attributes from .ele file.              */
+  stringptr = readline(inputline, elefile, elefilename);
+  inelements = (int) strtol (stringptr, &stringptr, 0);
+  stringptr = findfield(stringptr);
+  if (*stringptr == '\0') {
+    incorners = 3;
+  } else {
+    incorners = (int) strtol (stringptr, &stringptr, 0);
+    if (incorners < 3) {
+      printf("Error:  Triangles in %s must have at least 3 points.\n",
+             elefilename);
+      exit(1);
+    }
+  }
+  stringptr = findfield(stringptr);
+  if (*stringptr == '\0') {
+    eextras = 0;
+  } else {
+    eextras = (int) strtol (stringptr, &stringptr, 0);
+  }
+#endif /* not TRILIBRARY */
+
+  initializetrisegpools();
+
+  /* Create the triangles. */
+  for (elementnumber = 1; elementnumber <= inelements; elementnumber++) {
+    maketriangle(&triangleloop);
+    /* Mark the triangle as living. */
+    triangleloop.tri[3] = (triangle) triangleloop.tri;
+  }
+
+  if (poly) {
+#ifdef TRILIBRARY
+    insegments = numberofsegments;
+    segmentmarkers = segmentmarkerlist != (int *) NULL;
+#else /* not TRILIBRARY */
+    /* Read number of segments and number of segment */
+    /*   boundary markers from .poly file.           */
+    stringptr = readline(inputline, polyfile, inpolyfilename);
+    insegments = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      segmentmarkers = 0;
+    } else {
+      segmentmarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+#endif /* not TRILIBRARY */
+
+    /* Create the shell edges. */
+    for (segmentnumber = 1; segmentnumber <= insegments; segmentnumber++) {
+      makeshelle(&shelleloop);
+      /* Mark the shell edge as living. */
+      shelleloop.sh[2] = (shelle) shelleloop.sh;
+    }
+  }
+
+#ifdef TRILIBRARY
+  pointindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (vararea) {
+    /* Open an .area file, check for consistency with the .ele file. */
+    if (!quiet) {
+      printf("Opening %s.\n", areafilename);
+    }
+    areafile = fopen(areafilename, "r");
+    if (areafile == (FILE *) NULL) {
+      printf("  Error:  Cannot access file %s.\n", areafilename);
+      exit(1);
+    }
+    stringptr = readline(inputline, areafile, areafilename);
+    areaelements = (int) strtol (stringptr, &stringptr, 0);
+    if (areaelements != inelements) {
+      printf("Error:  %s and %s disagree on number of triangles.\n",
+             elefilename, areafilename);
+      exit(1);
+    }
+  }
+#endif /* not TRILIBRARY */
+
+  if (!quiet) {
+    printf("Reconstructing mesh.\n");
+  }
+  /* Allocate a temporary array that maps each point to some adjacent  */
+  /*   triangle.  I took care to allocate all the permanent memory for */
+  /*   triangles and shell edges first.                                */
+  vertexarray = (triangle *) malloc(points.items * sizeof(triangle));
+  if (vertexarray == (triangle *) NULL) {
+    printf("Error:  Out of memory.\n");
+    exit(1);
+  }
+  /* Each point is initially unrepresented. */
+  for (i = 0; i < points.items; i++) {
+    vertexarray[i] = (triangle) dummytri;
+  }
+
+  if (verbose) {
+    printf("  Assembling triangles.\n");
+  }
+  /* Read the triangles from the .ele file, and link */
+  /*   together those that share an edge.            */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+#ifdef TRILIBRARY
+    /* Copy the triangle's three corners. */
+    for (j = 0; j < 3; j++) {
+      corner[j] = trianglelist[pointindex++];
+      if ((corner[j] < firstnumber) || (corner[j] >= firstnumber + inpoints)) {
+        printf("Error:  Triangle %d has an invalid vertex index.\n",
+               elementnumber);
+        exit(1);
+      }
+    }
+#else /* not TRILIBRARY */
+    /* Read triangle number and the triangle's three corners. */
+    stringptr = readline(inputline, elefile, elefilename);
+    for (j = 0; j < 3; j++) {
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Triangle %d is missing point %d in %s.\n",
+               elementnumber, j + 1, elefilename);
+        exit(1);
+      } else {
+        corner[j] = (int) strtol (stringptr, &stringptr, 0);
+        if ((corner[j] < firstnumber) ||
+            (corner[j] >= firstnumber + inpoints)) {
+          printf("Error:  Triangle %d has an invalid vertex index.\n",
+                 elementnumber);
+          exit(1);
+        }
+      }
+    }
+#endif /* not TRILIBRARY */
+
+    /* Find out about (and throw away) extra nodes. */
+    for (j = 3; j < incorners; j++) {
+#ifdef TRILIBRARY
+      killpointindex = trianglelist[pointindex++];
+#else /* not TRILIBRARY */
+      stringptr = findfield(stringptr);
+      if (*stringptr != '\0') {
+        killpointindex = (int) strtol (stringptr, &stringptr, 0);
+#endif /* not TRILIBRARY */
+        if ((killpointindex >= firstnumber) &&
+            (killpointindex < firstnumber + inpoints)) {
+          /* Delete the non-corner point if it's not already deleted. */
+          killpoint = getpoint(killpointindex);
+          if (pointmark(killpoint) != DEADPOINT) {
+            pointdealloc(killpoint);
+          }
+        }
+#ifndef TRILIBRARY
+      }
+#endif /* not TRILIBRARY */
+    }
+
+    /* Read the triangle's attributes. */
+    for (j = 0; j < eextras; j++) {
+#ifdef TRILIBRARY
+      setelemattribute(triangleloop, j, triangleattriblist[attribindex++]);
+#else /* not TRILIBRARY */
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        setelemattribute(triangleloop, j, 0);
+      } else {
+        setelemattribute(triangleloop, j,
+                         (REAL) strtod (stringptr, &stringptr));
+      }
+#endif /* not TRILIBRARY */
+    }
+
+    if (vararea) {
+#ifdef TRILIBRARY
+      area = trianglearealist[elementnumber - firstnumber];
+#else /* not TRILIBRARY */
+      /* Read an area constraint from the .area file. */
+      stringptr = readline(inputline, areafile, areafilename);
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        area = -1.0;                      /* No constraint on this triangle. */
+      } else {
+        area = (REAL) strtod(stringptr, &stringptr);
+      }
+#endif /* not TRILIBRARY */
+      setareabound(triangleloop, area);
+    }
+
+    /* Set the triangle's vertices. */
+    triangleloop.orient = 0;
+    setorg(triangleloop, getpoint(corner[0]));
+    setdest(triangleloop, getpoint(corner[1]));
+    setapex(triangleloop, getpoint(corner[2]));
+    /* Try linking the triangle to others that share these vertices. */
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      /* Take the number for the origin of triangleloop. */
+      aroundpoint = corner[triangleloop.orient];
+      /* Look for other triangles having this vertex. */
+      nexttri = vertexarray[aroundpoint - firstnumber];
+      /* Link the current triangle to the next one in the stack. */
+      triangleloop.tri[6 + triangleloop.orient] = nexttri;
+      /* Push the current triangle onto the stack. */
+      vertexarray[aroundpoint - firstnumber] = encode(triangleloop);
+      decode(nexttri, checktri);
+      if (checktri.tri != dummytri) {
+        dest(triangleloop, tdest);
+        apex(triangleloop, tapex);
+        /* Look for other triangles that share an edge. */
+        do {
+          dest(checktri, checkdest);
+          apex(checktri, checkapex);
+          if (tapex == checkdest) {
+            /* The two triangles share an edge; bond them together. */
+            lprev(triangleloop, triangleleft);
+            bond(triangleleft, checktri);
+          }
+          if (tdest == checkapex) {
+            /* The two triangles share an edge; bond them together. */
+            lprev(checktri, checkleft);
+            bond(triangleloop, checkleft);
+          }
+          /* Find the next triangle in the stack. */
+          nexttri = checktri.tri[6 + checktri.orient];
+          decode(nexttri, checktri);
+        } while (checktri.tri != dummytri);
+      }
+    }
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+
+#ifdef TRILIBRARY
+  pointindex = 0;
+#else /* not TRILIBRARY */
+  fclose(elefile);
+  if (vararea) {
+    fclose(areafile);
+  }
+#endif /* not TRILIBRARY */
+
+  hullsize = 0;                      /* Prepare to count the boundary edges. */
+  if (poly) {
+    if (verbose) {
+      printf("  Marking segments in triangulation.\n");
+    }
+    /* Read the segments from the .poly file, and link them */
+    /*   to their neighboring triangles.                    */
+    boundmarker = 0;
+    traversalinit(&shelles);
+    shelleloop.sh = shelletraverse();
+    segmentnumber = firstnumber;
+    while (shelleloop.sh != (shelle *) NULL) {
+#ifdef TRILIBRARY
+      end[0] = segmentlist[pointindex++];
+      end[1] = segmentlist[pointindex++];
+      if (segmentmarkers) {
+        boundmarker = segmentmarkerlist[segmentnumber - firstnumber];
+      }
+#else /* not TRILIBRARY */
+      /* Read the endpoints of each segment, and possibly a boundary marker. */
+      stringptr = readline(inputline, polyfile, inpolyfilename);
+      /* Skip the first (segment number) field. */
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d has no endpoints in %s.\n", segmentnumber,
+               polyfilename);
+        exit(1);
+      } else {
+        end[0] = (int) strtol (stringptr, &stringptr, 0);
+      }
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d is missing its second endpoint in %s.\n",
+               segmentnumber, polyfilename);
+        exit(1);
+      } else {
+        end[1] = (int) strtol (stringptr, &stringptr, 0);
+      }
+      if (segmentmarkers) {
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          boundmarker = 0;
+        } else {
+          boundmarker = (int) strtol (stringptr, &stringptr, 0);
+        }
+      }
+#endif /* not TRILIBRARY */
+      for (j = 0; j < 2; j++) {
+        if ((end[j] < firstnumber) || (end[j] >= firstnumber + inpoints)) {
+          printf("Error:  Segment %d has an invalid vertex index.\n", 
+                 segmentnumber);
+          exit(1);
+        }
+      }
+
+      /* set the shell edge's vertices. */
+      shelleloop.shorient = 0;
+      setsorg(shelleloop, getpoint(end[0]));
+      setsdest(shelleloop, getpoint(end[1]));
+      setmark(shelleloop, boundmarker);
+      /* Try linking the shell edge to triangles that share these vertices. */
+      for (shelleloop.shorient = 0; shelleloop.shorient < 2;
+           shelleloop.shorient++) {
+        /* Take the number for the destination of shelleloop. */
+        aroundpoint = end[1 - shelleloop.shorient];
+        /* Look for triangles having this vertex. */
+        prevlink = &vertexarray[aroundpoint - firstnumber];
+        nexttri = vertexarray[aroundpoint - firstnumber];
+        decode(nexttri, checktri);
+        sorg(shelleloop, shorg);
+        notfound = 1;
+        /* Look for triangles having this edge.  Note that I'm only       */
+        /*   comparing each triangle's destination with the shell edge;   */
+        /*   each triangle's apex is handled through a different vertex.  */
+        /*   Because each triangle appears on three vertices' lists, each */
+        /*   occurrence of a triangle on a list can (and does) represent  */
+        /*   an edge.  In this way, most edges are represented twice, and */
+        /*   every triangle-segment bond is represented once.             */
+        while (notfound && (checktri.tri != dummytri)) {
+          dest(checktri, checkdest);
+          if (shorg == checkdest) {
+            /* We have a match.  Remove this triangle from the list. */
+            *prevlink = checktri.tri[6 + checktri.orient];
+            /* Bond the shell edge to the triangle. */
+            tsbond(checktri, shelleloop);
+            /* Check if this is a boundary edge. */
+            sym(checktri, checkneighbor);
+            if (checkneighbor.tri == dummytri) {
+              /* The next line doesn't insert a shell edge (because there's */
+              /*   already one there), but it sets the boundary markers of  */
+              /*   the existing shell edge and its vertices.                */
+              insertshelle(&checktri, 1);
+              hullsize++;
+            }
+            notfound = 0;
+          }
+          /* Find the next triangle in the stack. */
+          prevlink = &checktri.tri[6 + checktri.orient];
+          nexttri = checktri.tri[6 + checktri.orient];
+          decode(nexttri, checktri);
+        }
+      }
+      shelleloop.sh = shelletraverse();
+      segmentnumber++;
+    }
+  }
+
+  /* Mark the remaining edges as not being attached to any shell edge. */
+  /* Also, count the (yet uncounted) boundary edges.                   */
+  for (i = 0; i < points.items; i++) {
+    /* Search the stack of triangles adjacent to a point. */
+    nexttri = vertexarray[i];
+    decode(nexttri, checktri);
+    while (checktri.tri != dummytri) {
+      /* Find the next triangle in the stack before this */
+      /*   information gets overwritten.                 */
+      nexttri = checktri.tri[6 + checktri.orient];
+      /* No adjacent shell edge.  (This overwrites the stack info.) */
+      tsdissolve(checktri);
+      sym(checktri, checkneighbor);
+      if (checkneighbor.tri == dummytri) {
+        insertshelle(&checktri, 1);
+        hullsize++;
+      }
+      decode(nexttri, checktri);
+    }
+  }
+
+  free(vertexarray);
+  return hullsize;
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* General mesh construction routines end here               *********/
+
+/********* Segment (shell edge) insertion begins here                *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  finddirection()   Find the first triangle on the path from one point     */
+/*                    to another.                                            */
+/*                                                                           */
+/*  Finds the triangle that intersects a line segment drawn from the         */
+/*  origin of `searchtri' to the point `endpoint', and returns the result    */
+/*  in `searchtri'.  The origin of `searchtri' does not change, even though  */
+/*  the triangle returned may differ from the one passed in.  This routine   */
+/*  is used to find the direction to move in to get from one point to        */
+/*  another.                                                                 */
+/*                                                                           */
+/*  The return value notes whether the destination or apex of the found      */
+/*  triangle is collinear with the two points in question.                   */
+/*                                                                           */
+/*****************************************************************************/
+
+enum finddirectionresult finddirection(searchtri, endpoint)
+struct triedge *searchtri;
+point endpoint;
+{
+  struct triedge checktri;
+  point startpoint;
+  point leftpoint, rightpoint;
+  REAL leftccw, rightccw;
+  int leftflag, rightflag;
+  triangle ptr;           /* Temporary variable used by onext() and oprev(). */
+
+  org(*searchtri, startpoint);
+  dest(*searchtri, rightpoint);
+  apex(*searchtri, leftpoint);
+  /* Is `endpoint' to the left? */
+  leftccw = counterclockwise(endpoint, startpoint, leftpoint);
+  leftflag = leftccw > 0.0;
+  /* Is `endpoint' to the right? */
+  rightccw = counterclockwise(startpoint, endpoint, rightpoint);
+  rightflag = rightccw > 0.0;
+  if (leftflag && rightflag) {
+    /* `searchtri' faces directly away from `endpoint'.  We could go */
+    /*   left or right.  Ask whether it's a triangle or a boundary   */
+    /*   on the left.                                                */
+    onext(*searchtri, checktri);
+    if (checktri.tri == dummytri) {
+      leftflag = 0;
+    } else {
+      rightflag = 0;
+    }
+  }
+  while (leftflag) {
+    /* Turn left until satisfied. */
+    onextself(*searchtri);
+    if (searchtri->tri == dummytri) {
+      printf("Internal error in finddirection():  Unable to find a\n");
+      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
+             startpoint[1]);
+      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
+      internalerror();
+    }
+    apex(*searchtri, leftpoint);
+    rightccw = leftccw;
+    leftccw = counterclockwise(endpoint, startpoint, leftpoint);
+    leftflag = leftccw > 0.0;
+  }
+  while (rightflag) {
+    /* Turn right until satisfied. */
+    oprevself(*searchtri);
+    if (searchtri->tri == dummytri) {
+      printf("Internal error in finddirection():  Unable to find a\n");
+      printf("  triangle leading from (%.12g, %.12g) to", startpoint[0],
+             startpoint[1]);
+      printf("  (%.12g, %.12g).\n", endpoint[0], endpoint[1]);
+      internalerror();
+    }
+    dest(*searchtri, rightpoint);
+    leftccw = rightccw;
+    rightccw = counterclockwise(startpoint, endpoint, rightpoint);
+    rightflag = rightccw > 0.0;
+  }
+  if (leftccw == 0.0) {
+    return LEFTCOLLINEAR;
+  } else if (rightccw == 0.0) {
+    return RIGHTCOLLINEAR;
+  } else {
+    return WITHIN;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  segmentintersection()   Find the intersection of an existing segment     */
+/*                          and a segment that is being inserted.  Insert    */
+/*                          a point at the intersection, splitting an        */
+/*                          existing shell edge.                             */
+/*                                                                           */
+/*  The segment being inserted connects the apex of splittri to endpoint2.   */
+/*  splitshelle is the shell edge being split, and MUST be opposite          */
+/*  splittri.  Hence, the edge being split connects the origin and           */
+/*  destination of splittri.                                                 */
+/*                                                                           */
+/*  On completion, splittri is a handle having the newly inserted            */
+/*  intersection point as its origin, and endpoint1 as its destination.      */
+/*                                                                           */
+/*****************************************************************************/
+
+void segmentintersection(splittri, splitshelle, endpoint2)
+struct triedge *splittri;
+struct edge *splitshelle;
+point endpoint2;
+{
+  point endpoint1;
+  point torg, tdest;
+  point leftpoint, rightpoint;
+  point newpoint;
+  enum insertsiteresult success;
+  enum finddirectionresult collinear;
+  REAL ex, ey;
+  REAL tx, ty;
+  REAL etx, ety;
+  REAL split, denom;
+  int i;
+  triangle ptr;                       /* Temporary variable used by onext(). */
+
+  /* Find the other three segment endpoints. */
+  apex(*splittri, endpoint1);
+  org(*splittri, torg);
+  dest(*splittri, tdest);
+  /* Segment intersection formulae; see the Antonio reference. */
+  tx = tdest[0] - torg[0];
+  ty = tdest[1] - torg[1];
+  ex = endpoint2[0] - endpoint1[0];
+  ey = endpoint2[1] - endpoint1[1];
+  etx = torg[0] - endpoint2[0];
+  ety = torg[1] - endpoint2[1];
+  denom = ty * ex - tx * ey;
+  if (denom == 0.0) {
+    printf("Internal error in segmentintersection():");
+    printf("  Attempt to find intersection of parallel segments.\n");
+    internalerror();
+  }
+  split = (ey * etx - ex * ety) / denom;
+  /* Create the new point. */
+  newpoint = (point) poolalloc(&points);
+  /* Interpolate its coordinate and attributes. */
+  for (i = 0; i < 2 + nextras; i++) {
+    newpoint[i] = torg[i] + split * (tdest[i] - torg[i]);
+  }
+  setpointmark(newpoint, mark(*splitshelle));
+  if (verbose > 1) {
+    printf(
+    "  Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
+           torg[0], torg[1], tdest[0], tdest[1], newpoint[0], newpoint[1]);
+  }
+  /* Insert the intersection point.  This should always succeed. */
+  success = insertsite(newpoint, splittri, splitshelle, 0, 0);
+  if (success != SUCCESSFULPOINT) {
+    printf("Internal error in segmentintersection():\n");
+    printf("  Failure to split a segment.\n");
+    internalerror();
+  }
+  if (steinerleft > 0) {
+    steinerleft--;
+  }
+  /* Inserting the point may have caused edge flips.  We wish to rediscover */
+  /*   the edge connecting endpoint1 to the new intersection point.         */
+  collinear = finddirection(splittri, endpoint1);
+  dest(*splittri, rightpoint);
+  apex(*splittri, leftpoint);
+  if ((leftpoint[0] == endpoint1[0]) && (leftpoint[1] == endpoint1[1])) {
+    onextself(*splittri);
+  } else if ((rightpoint[0] != endpoint1[0]) ||
+             (rightpoint[1] != endpoint1[1])) {
+    printf("Internal error in segmentintersection():\n");
+    printf("  Topological inconsistency after splitting a segment.\n");
+    internalerror();
+  }
+  /* `splittri' should have destination endpoint1. */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  scoutsegment()   Scout the first triangle on the path from one endpoint  */
+/*                   to another, and check for completion (reaching the      */
+/*                   second endpoint), a collinear point, and the            */
+/*                   intersection of two segments.                           */
+/*                                                                           */
+/*  Returns one if the entire segment is successfully inserted, and zero if  */
+/*  the job must be finished by conformingedge() or constrainededge().       */
+/*                                                                           */
+/*  If the first triangle on the path has the second endpoint as its         */
+/*  destination or apex, a shell edge is inserted and the job is done.       */
+/*                                                                           */
+/*  If the first triangle on the path has a destination or apex that lies on */
+/*  the segment, a shell edge is inserted connecting the first endpoint to   */
+/*  the collinear point, and the search is continued from the collinear      */
+/*  point.                                                                   */
+/*                                                                           */
+/*  If the first triangle on the path has a shell edge opposite its origin,  */
+/*  then there is a segment that intersects the segment being inserted.      */
+/*  Their intersection point is inserted, splitting the shell edge.          */
+/*                                                                           */
+/*  Otherwise, return zero.                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+int scoutsegment(searchtri, endpoint2, newmark)
+struct triedge *searchtri;
+point endpoint2;
+int newmark;
+{
+  struct triedge crosstri;
+  struct edge crossedge;
+  point leftpoint, rightpoint;
+  point endpoint1;
+  enum finddirectionresult collinear;
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  collinear = finddirection(searchtri, endpoint2);
+  dest(*searchtri, rightpoint);
+  apex(*searchtri, leftpoint);
+  if (((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) ||
+      ((rightpoint[0] == endpoint2[0]) && (rightpoint[1] == endpoint2[1]))) {
+    /* The segment is already an edge in the mesh. */
+    if ((leftpoint[0] == endpoint2[0]) && (leftpoint[1] == endpoint2[1])) {
+      lprevself(*searchtri);
+    }
+    /* Insert a shell edge, if there isn't already one there. */
+    insertshelle(searchtri, newmark);
+    return 1;
+  } else if (collinear == LEFTCOLLINEAR) {
+    /* We've collided with a point between the segment's endpoints. */
+    /* Make the collinear point be the triangle's origin. */
+    lprevself(*searchtri);
+    insertshelle(searchtri, newmark);
+    /* Insert the remainder of the segment. */
+    return scoutsegment(searchtri, endpoint2, newmark);
+  } else if (collinear == RIGHTCOLLINEAR) {
+    /* We've collided with a point between the segment's endpoints. */
+    insertshelle(searchtri, newmark);
+    /* Make the collinear point be the triangle's origin. */
+    lnextself(*searchtri);
+    /* Insert the remainder of the segment. */
+    return scoutsegment(searchtri, endpoint2, newmark);
+  } else {
+    lnext(*searchtri, crosstri);
+    tspivot(crosstri, crossedge);
+    /* Check for a crossing segment. */
+    if (crossedge.sh == dummysh) {
+      return 0;
+    } else {
+      org(*searchtri, endpoint1);
+      /* Insert a point at the intersection. */
+      segmentintersection(&crosstri, &crossedge, endpoint2);
+      triedgecopy(crosstri, *searchtri);
+      insertshelle(searchtri, newmark);
+      /* Insert the remainder of the segment. */
+      return scoutsegment(searchtri, endpoint2, newmark);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  conformingedge()   Force a segment into a conforming Delaunay            */
+/*                     triangulation by inserting a point at its midpoint,   */
+/*                     and recursively forcing in the two half-segments if   */
+/*                     necessary.                                            */
+/*                                                                           */
+/*  Generates a sequence of edges connecting `endpoint1' to `endpoint2'.     */
+/*  `newmark' is the boundary marker of the segment, assigned to each new    */
+/*  splitting point and shell edge.                                          */
+/*                                                                           */
+/*  Note that conformingedge() does not always maintain the conforming       */
+/*  Delaunay property.  Once inserted, segments are locked into place;       */
+/*  points inserted later (to force other segments in) may render these      */
+/*  fixed segments non-Delaunay.  The conforming Delaunay property will be   */
+/*  restored by enforcequality() by splitting encroached segments.           */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef REDUCED
+#ifndef CDT_ONLY
+
+void conformingedge(endpoint1, endpoint2, newmark)
+point endpoint1;
+point endpoint2;
+int newmark;
+{
+  struct triedge searchtri1, searchtri2;
+  struct edge brokenshelle;
+  point newpoint;
+  point midpoint1, midpoint2;
+  enum insertsiteresult success;
+  int result1, result2;
+  int i;
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose > 2) {
+    printf("Forcing segment into triangulation by recursive splitting:\n");
+    printf("  (%.12g, %.12g) (%.12g, %.12g)\n", endpoint1[0], endpoint1[1],
+           endpoint2[0], endpoint2[1]);
+  }
+  /* Create a new point to insert in the middle of the segment. */
+  newpoint = (point) poolalloc(&points);
+  /* Interpolate coordinates and attributes. */
+  for (i = 0; i < 2 + nextras; i++) {
+    newpoint[i] = 0.5 * (endpoint1[i] + endpoint2[i]);
+  }
+  setpointmark(newpoint, newmark);
+  /* Find a boundary triangle to search from. */
+  searchtri1.tri = (triangle *) NULL;
+  /* Attempt to insert the new point. */
+  success = insertsite(newpoint, &searchtri1, (struct edge *) NULL, 0, 0);
+  if (success == DUPLICATEPOINT) {
+    if (verbose > 2) {
+      printf("  Segment intersects existing point (%.12g, %.12g).\n",
+             newpoint[0], newpoint[1]);
+    }
+    /* Use the point that's already there. */
+    pointdealloc(newpoint);
+    org(searchtri1, newpoint);
+  } else {
+    if (success == VIOLATINGPOINT) {
+      if (verbose > 2) {
+        printf("  Two segments intersect at (%.12g, %.12g).\n",
+               newpoint[0], newpoint[1]);
+      }
+      /* By fluke, we've landed right on another segment.  Split it. */
+      tspivot(searchtri1, brokenshelle);
+      success = insertsite(newpoint, &searchtri1, &brokenshelle, 0, 0);
+      if (success != SUCCESSFULPOINT) {
+        printf("Internal error in conformingedge():\n");
+        printf("  Failure to split a segment.\n");
+        internalerror();
+      }
+    }
+    /* The point has been inserted successfully. */
+    if (steinerleft > 0) {
+      steinerleft--;
+    }
+  }
+  triedgecopy(searchtri1, searchtri2);
+  result1 = scoutsegment(&searchtri1, endpoint1, newmark);
+  result2 = scoutsegment(&searchtri2, endpoint2, newmark);
+  if (!result1) {
+    /* The origin of searchtri1 may have changed if a collision with an */
+    /*   intervening vertex on the segment occurred.                    */
+    org(searchtri1, midpoint1);
+    conformingedge(midpoint1, endpoint1, newmark);
+  }
+  if (!result2) {
+    /* The origin of searchtri2 may have changed if a collision with an */
+    /*   intervening vertex on the segment occurred.                    */
+    org(searchtri2, midpoint2);
+    conformingedge(midpoint2, endpoint2, newmark);
+  }
+}
+
+#endif /* not CDT_ONLY */
+#endif /* not REDUCED */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  delaunayfixup()   Enforce the Delaunay condition at an edge, fanning out */
+/*                    recursively from an existing point.  Pay special       */
+/*                    attention to stacking inverted triangles.              */
+/*                                                                           */
+/*  This is a support routine for inserting segments into a constrained      */
+/*  Delaunay triangulation.                                                  */
+/*                                                                           */
+/*  The origin of fixuptri is treated as if it has just been inserted, and   */
+/*  the local Delaunay condition needs to be enforced.  It is only enforced  */
+/*  in one sector, however, that being the angular range defined by          */
+/*  fixuptri.                                                                */
+/*                                                                           */
+/*  This routine also needs to make decisions regarding the "stacking" of    */
+/*  triangles.  (Read the description of constrainededge() below before      */
+/*  reading on here, so you understand the algorithm.)  If the position of   */
+/*  the new point (the origin of fixuptri) indicates that the vertex before  */
+/*  it on the polygon is a reflex vertex, then "stack" the triangle by       */
+/*  doing nothing.  (fixuptri is an inverted triangle, which is how stacked  */
+/*  triangles are identified.)                                               */
+/*                                                                           */
+/*  Otherwise, check whether the vertex before that was a reflex vertex.     */
+/*  If so, perform an edge flip, thereby eliminating an inverted triangle    */
+/*  (popping it off the stack).  The edge flip may result in the creation    */
+/*  of a new inverted triangle, depending on whether or not the new vertex   */
+/*  is visible to the vertex three edges behind on the polygon.              */
+/*                                                                           */
+/*  If neither of the two vertices behind the new vertex are reflex          */
+/*  vertices, fixuptri and fartri, the triangle opposite it, are not         */
+/*  inverted; hence, ensure that the edge between them is locally Delaunay.  */
+/*                                                                           */
+/*  `leftside' indicates whether or not fixuptri is to the left of the       */
+/*  segment being inserted.  (Imagine that the segment is pointing up from   */
+/*  endpoint1 to endpoint2.)                                                 */
+/*                                                                           */
+/*****************************************************************************/
+
+void delaunayfixup(fixuptri, leftside)
+struct triedge *fixuptri;
+int leftside;
+{
+  struct triedge neartri;
+  struct triedge fartri;
+  struct edge faredge;
+  point nearpoint, leftpoint, rightpoint, farpoint;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  lnext(*fixuptri, neartri);
+  sym(neartri, fartri);
+  /* Check if the edge opposite the origin of fixuptri can be flipped. */
+  if (fartri.tri == dummytri) {
+    return;
+  }
+  tspivot(neartri, faredge);
+  if (faredge.sh != dummysh) {
+    return;
+  }
+  /* Find all the relevant vertices. */
+  apex(neartri, nearpoint);
+  org(neartri, leftpoint);
+  dest(neartri, rightpoint);
+  apex(fartri, farpoint);
+  /* Check whether the previous polygon vertex is a reflex vertex. */
+  if (leftside) {
+    if (counterclockwise(nearpoint, leftpoint, farpoint) <= 0.0) {
+      /* leftpoint is a reflex vertex too.  Nothing can */
+      /*   be done until a convex section is found.     */
+      return;
+    }
+  } else {
+    if (counterclockwise(farpoint, rightpoint, nearpoint) <= 0.0) {
+      /* rightpoint is a reflex vertex too.  Nothing can */
+      /*   be done until a convex section is found.      */
+      return;
+    }
+  }
+  if (counterclockwise(rightpoint, leftpoint, farpoint) > 0.0) {
+    /* fartri is not an inverted triangle, and farpoint is not a reflex */
+    /*   vertex.  As there are no reflex vertices, fixuptri isn't an    */
+    /*   inverted triangle, either.  Hence, test the edge between the   */
+    /*   triangles to ensure it is locally Delaunay.                    */
+    if (incircle(leftpoint, farpoint, rightpoint, nearpoint) <= 0.0) {
+      return;
+    }
+    /* Not locally Delaunay; go on to an edge flip. */
+  }        /* else fartri is inverted; remove it from the stack by flipping. */
+  flip(&neartri);
+  lprevself(*fixuptri);    /* Restore the origin of fixuptri after the flip. */
+  /* Recursively process the two triangles that result from the flip. */
+  delaunayfixup(fixuptri, leftside);
+  delaunayfixup(&fartri, leftside);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  constrainededge()   Force a segment into a constrained Delaunay          */
+/*                      triangulation by deleting the triangles it           */
+/*                      intersects, and triangulating the polygons that      */
+/*                      form on each side of it.                             */
+/*                                                                           */
+/*  Generates a single edge connecting `endpoint1' to `endpoint2'.  The      */
+/*  triangle `starttri' has `endpoint1' as its origin.  `newmark' is the     */
+/*  boundary marker of the segment.                                          */
+/*                                                                           */
+/*  To insert a segment, every triangle whose interior intersects the        */
+/*  segment is deleted.  The union of these deleted triangles is a polygon   */
+/*  (which is not necessarily monotone, but is close enough), which is       */
+/*  divided into two polygons by the new segment.  This routine's task is    */
+/*  to generate the Delaunay triangulation of these two polygons.            */
+/*                                                                           */
+/*  You might think of this routine's behavior as a two-step process.  The   */
+/*  first step is to walk from endpoint1 to endpoint2, flipping each edge    */
+/*  encountered.  This step creates a fan of edges connected to endpoint1,   */
+/*  including the desired edge to endpoint2.  The second step enforces the   */
+/*  Delaunay condition on each side of the segment in an incremental manner: */
+/*  proceeding along the polygon from endpoint1 to endpoint2 (this is done   */
+/*  independently on each side of the segment), each vertex is "enforced"    */
+/*  as if it had just been inserted, but affecting only the previous         */
+/*  vertices.  The result is the same as if the vertices had been inserted   */
+/*  in the order they appear on the polygon, so the result is Delaunay.      */
+/*                                                                           */
+/*  In truth, constrainededge() interleaves these two steps.  The procedure  */
+/*  walks from endpoint1 to endpoint2, and each time an edge is encountered  */
+/*  and flipped, the newly exposed vertex (at the far end of the flipped     */
+/*  edge) is "enforced" upon the previously flipped edges, usually affecting */
+/*  only one side of the polygon (depending upon which side of the segment   */
+/*  the vertex falls on).                                                    */
+/*                                                                           */
+/*  The algorithm is complicated by the need to handle polygons that are not */
+/*  convex.  Although the polygon is not necessarily monotone, it can be     */
+/*  triangulated in a manner similar to the stack-based algorithms for       */
+/*  monotone polygons.  For each reflex vertex (local concavity) of the      */
+/*  polygon, there will be an inverted triangle formed by one of the edge    */
+/*  flips.  (An inverted triangle is one with negative area - that is, its   */
+/*  vertices are arranged in clockwise order - and is best thought of as a   */
+/*  wrinkle in the fabric of the mesh.)  Each inverted triangle can be       */
+/*  thought of as a reflex vertex pushed on the stack, waiting to be fixed   */
+/*  later.                                                                   */
+/*                                                                           */
+/*  A reflex vertex is popped from the stack when a vertex is inserted that  */
+/*  is visible to the reflex vertex.  (However, if the vertex behind the     */
+/*  reflex vertex is not visible to the reflex vertex, a new inverted        */
+/*  triangle will take its place on the stack.)  These details are handled   */
+/*  by the delaunayfixup() routine above.                                    */
+/*                                                                           */
+/*****************************************************************************/
+
+void constrainededge(starttri, endpoint2, newmark)
+struct triedge *starttri;
+point endpoint2;
+int newmark;
+{
+  struct triedge fixuptri, fixuptri2;
+  struct edge fixupedge;
+  point endpoint1;
+  point farpoint;
+  REAL area;
+  int collision;
+  int done;
+  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  org(*starttri, endpoint1);
+  lnext(*starttri, fixuptri);
+  flip(&fixuptri);
+  /* `collision' indicates whether we have found a point directly */
+  /*   between endpoint1 and endpoint2.                           */
+  collision = 0;
+  done = 0;
+  do {
+    org(fixuptri, farpoint);
+    /* `farpoint' is the extreme point of the polygon we are "digging" */
+    /*   to get from endpoint1 to endpoint2.                           */
+    if ((farpoint[0] == endpoint2[0]) && (farpoint[1] == endpoint2[1])) {
+      oprev(fixuptri, fixuptri2);
+      /* Enforce the Delaunay condition around endpoint2. */
+      delaunayfixup(&fixuptri, 0);
+      delaunayfixup(&fixuptri2, 1);
+      done = 1;
+    } else {
+      /* Check whether farpoint is to the left or right of the segment */
+      /*   being inserted, to decide which edge of fixuptri to dig     */
+      /*   through next.                                               */
+      area = counterclockwise(endpoint1, endpoint2, farpoint);
+      if (area == 0.0) {
+        /* We've collided with a point between endpoint1 and endpoint2. */
+        collision = 1;
+        oprev(fixuptri, fixuptri2);
+        /* Enforce the Delaunay condition around farpoint. */
+        delaunayfixup(&fixuptri, 0);
+        delaunayfixup(&fixuptri2, 1);
+        done = 1;
+      } else {
+        if (area > 0.0) {         /* farpoint is to the left of the segment. */
+          oprev(fixuptri, fixuptri2);
+          /* Enforce the Delaunay condition around farpoint, on the */
+          /*   left side of the segment only.                       */
+          delaunayfixup(&fixuptri2, 1);
+          /* Flip the edge that crosses the segment.  After the edge is */
+          /*   flipped, one of its endpoints is the fan vertex, and the */
+          /*   destination of fixuptri is the fan vertex.               */
+          lprevself(fixuptri);
+        } else {                 /* farpoint is to the right of the segment. */
+          delaunayfixup(&fixuptri, 0);
+          /* Flip the edge that crosses the segment.  After the edge is */
+          /*   flipped, one of its endpoints is the fan vertex, and the */
+          /*   destination of fixuptri is the fan vertex.               */
+          oprevself(fixuptri);
+        }
+        /* Check for two intersecting segments. */
+        tspivot(fixuptri, fixupedge);
+        if (fixupedge.sh == dummysh) {
+          flip(&fixuptri);   /* May create an inverted triangle on the left. */
+        } else {
+          /* We've collided with a segment between endpoint1 and endpoint2. */
+          collision = 1;
+          /* Insert a point at the intersection. */
+          segmentintersection(&fixuptri, &fixupedge, endpoint2);
+          done = 1;
+        }
+      }
+    }
+  } while (!done);
+  /* Insert a shell edge to make the segment permanent. */
+  insertshelle(&fixuptri, newmark);
+  /* If there was a collision with an interceding vertex, install another */
+  /*   segment connecting that vertex with endpoint2.                     */
+  if (collision) {
+    /* Insert the remainder of the segment. */
+    if (!scoutsegment(&fixuptri, endpoint2, newmark)) {
+      constrainededge(&fixuptri, endpoint2, newmark);
+    }
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  insertsegment()   Insert a PSLG segment into a triangulation.            */
+/*                                                                           */
+/*****************************************************************************/
+
+void insertsegment(endpoint1, endpoint2, newmark)
+point endpoint1;
+point endpoint2;
+int newmark;
+{
+  struct triedge searchtri1, searchtri2;
+  triangle encodedtri;
+  point checkpoint;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (verbose > 1) {
+    printf("  Connecting (%.12g, %.12g) to (%.12g, %.12g).\n",
+           endpoint1[0], endpoint1[1], endpoint2[0], endpoint2[1]);
+  }
+
+  /* Find a triangle whose origin is the segment's first endpoint. */
+  checkpoint = (point) NULL;
+  encodedtri = point2tri(endpoint1);
+  if (encodedtri != (triangle) NULL) {
+    decode(encodedtri, searchtri1);
+    org(searchtri1, checkpoint);
+  }
+  if (checkpoint != endpoint1) {
+    /* Find a boundary triangle to search from. */
+    searchtri1.tri = dummytri;
+    searchtri1.orient = 0;
+    symself(searchtri1);
+    /* Search for the segment's first endpoint by point location. */
+    if (locate(endpoint1, &searchtri1) != ONVERTEX) {
+      printf(
+        "Internal error in insertsegment():  Unable to locate PSLG point\n");
+      printf("  (%.12g, %.12g) in triangulation.\n",
+             endpoint1[0], endpoint1[1]);
+      internalerror();
+    }
+  }
+  /* Remember this triangle to improve subsequent point location. */
+  triedgecopy(searchtri1, recenttri);
+  /* Scout the beginnings of a path from the first endpoint */
+  /*   toward the second.                                   */
+  if (scoutsegment(&searchtri1, endpoint2, newmark)) {
+    /* The segment was easily inserted. */
+    return;
+  }
+  /* The first endpoint may have changed if a collision with an intervening */
+  /*   vertex on the segment occurred.                                      */
+  org(searchtri1, endpoint1);
+
+  /* Find a triangle whose origin is the segment's second endpoint. */
+  checkpoint = (point) NULL;
+  encodedtri = point2tri(endpoint2);
+  if (encodedtri != (triangle) NULL) {
+    decode(encodedtri, searchtri2);
+    org(searchtri2, checkpoint);
+  }
+  if (checkpoint != endpoint2) {
+    /* Find a boundary triangle to search from. */
+    searchtri2.tri = dummytri;
+    searchtri2.orient = 0;
+    symself(searchtri2);
+    /* Search for the segment's second endpoint by point location. */
+    if (locate(endpoint2, &searchtri2) != ONVERTEX) {
+      printf(
+        "Internal error in insertsegment():  Unable to locate PSLG point\n");
+      printf("  (%.12g, %.12g) in triangulation.\n",
+             endpoint2[0], endpoint2[1]);
+      internalerror();
+    }
+  }
+  /* Remember this triangle to improve subsequent point location. */
+  triedgecopy(searchtri2, recenttri);
+  /* Scout the beginnings of a path from the second endpoint */
+  /*   toward the first.                                     */
+  if (scoutsegment(&searchtri2, endpoint1, newmark)) {
+    /* The segment was easily inserted. */
+    return;
+  }
+  /* The second endpoint may have changed if a collision with an intervening */
+  /*   vertex on the segment occurred.                                       */
+  org(searchtri2, endpoint2);
+
+#ifndef REDUCED
+#ifndef CDT_ONLY
+  if (splitseg) {
+    /* Insert vertices to force the segment into the triangulation. */
+    conformingedge(endpoint1, endpoint2, newmark);
+  } else {
+#endif /* not CDT_ONLY */
+#endif /* not REDUCED */
+    /* Insert the segment directly into the triangulation. */
+    constrainededge(&searchtri1, endpoint2, newmark);
+#ifndef REDUCED
+#ifndef CDT_ONLY
+  }
+#endif /* not CDT_ONLY */
+#endif /* not REDUCED */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  markhull()   Cover the convex hull of a triangulation with shell edges.  */
+/*                                                                           */
+/*****************************************************************************/
+
+void markhull()
+{
+  struct triedge hulltri;
+  struct triedge nexttri;
+  struct triedge starttri;
+  triangle ptr;             /* Temporary variable used by sym() and oprev(). */
+
+  /* Find a triangle handle on the hull. */
+  hulltri.tri = dummytri;
+  hulltri.orient = 0;
+  symself(hulltri);
+  /* Remember where we started so we know when to stop. */
+  triedgecopy(hulltri, starttri);
+  /* Go once counterclockwise around the convex hull. */
+  do {
+    /* Create a shell edge if there isn't already one here. */
+    insertshelle(&hulltri, 1);
+    /* To find the next hull edge, go clockwise around the next vertex. */
+    lnextself(hulltri);
+    oprev(hulltri, nexttri);
+    while (nexttri.tri != dummytri) {
+      triedgecopy(nexttri, hulltri);
+      oprev(hulltri, nexttri);
+    }
+  } while (!triedgeequal(hulltri, starttri));
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  formskeleton()   Create the shell edges of a triangulation, including    */
+/*                   PSLG edges and edges on the convex hull.                */
+/*                                                                           */
+/*  The PSLG edges are read from a .poly file.  The return value is the      */
+/*  number of segments in the file.                                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+int formskeleton(segmentlist, segmentmarkerlist, numberofsegments)
+int *segmentlist;
+int *segmentmarkerlist;
+int numberofsegments;
+
+#else /* not TRILIBRARY */
+
+int formskeleton(polyfile, polyfilename)
+FILE *polyfile;
+char *polyfilename;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  char polyfilename[6];
+  int index;
+#else /* not TRILIBRARY */
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+#endif /* not TRILIBRARY */
+  point endpoint1, endpoint2;
+  int segments;
+  int segmentmarkers;
+  int end1, end2;
+  int boundmarker;
+  int i;
+
+  if (poly) {
+    if (!quiet) {
+      printf("Inserting segments into Delaunay triangulation.\n");
+    }
+#ifdef TRILIBRARY
+    strcpy(polyfilename, "input");
+    segments = numberofsegments;
+    segmentmarkers = segmentmarkerlist != (int *) NULL;
+    index = 0;
+#else /* not TRILIBRARY */
+    /* Read the segments from a .poly file. */
+    /* Read number of segments and number of boundary markers. */
+    stringptr = readline(inputline, polyfile, polyfilename);
+    segments = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      segmentmarkers = 0;
+    } else {
+      segmentmarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+#endif /* not TRILIBRARY */
+    /* If segments are to be inserted, compute a mapping */
+    /*   from points to triangles.                       */
+    if (segments > 0) {
+      if (verbose) {
+        printf("  Inserting PSLG segments.\n");
+      }
+      makepointmap();
+    }
+
+    boundmarker = 0;
+    /* Read and insert the segments. */
+    for (i = 1; i <= segments; i++) {
+#ifdef TRILIBRARY
+      end1 = segmentlist[index++];
+      end2 = segmentlist[index++];
+      if (segmentmarkers) {
+        boundmarker = segmentmarkerlist[i - 1];
+      }
+#else /* not TRILIBRARY */
+      stringptr = readline(inputline, polyfile, inpolyfilename);
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d has no endpoints in %s.\n", i,
+               polyfilename);
+        exit(1);
+      } else {
+        end1 = (int) strtol (stringptr, &stringptr, 0);
+      }
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Segment %d is missing its second endpoint in %s.\n", i,
+               polyfilename);
+        exit(1);
+      } else {
+        end2 = (int) strtol (stringptr, &stringptr, 0);
+      }
+      if (segmentmarkers) {
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          boundmarker = 0;
+        } else {
+          boundmarker = (int) strtol (stringptr, &stringptr, 0);
+        }
+      }
+#endif /* not TRILIBRARY */
+      if ((end1 < firstnumber) || (end1 >= firstnumber + inpoints)) {
+        if (!quiet) {
+          printf("Warning:  Invalid first endpoint of segment %d in %s.\n", i,
+                 polyfilename);
+        }
+      } else if ((end2 < firstnumber) || (end2 >= firstnumber + inpoints)) {
+        if (!quiet) {
+          printf("Warning:  Invalid second endpoint of segment %d in %s.\n", i,
+                 polyfilename);
+        }
+      } else {
+        endpoint1 = getpoint(end1);
+        endpoint2 = getpoint(end2);
+        if ((endpoint1[0] == endpoint2[0]) && (endpoint1[1] == endpoint2[1])) {
+          if (!quiet) {
+            printf("Warning:  Endpoints of segment %d are coincident in %s.\n",
+                   i, polyfilename);
+          }
+        } else {
+          insertsegment(endpoint1, endpoint2, boundmarker);
+        }
+      }
+    }
+  } else {
+    segments = 0;
+  }
+  if (convex || !poly) {
+    /* Enclose the convex hull with shell edges. */
+    if (verbose) {
+      printf("  Enclosing convex hull with segments.\n");
+    }
+    markhull();
+  }
+  return segments;
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Segment (shell edge) insertion ends here                  *********/
+
+/********* Carving out holes and concavities begins here             *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  infecthull()   Virally infect all of the triangles of the convex hull    */
+/*                 that are not protected by shell edges.  Where there are   */
+/*                 shell edges, set boundary markers as appropriate.         */
+/*                                                                           */
+/*****************************************************************************/
+
+void infecthull()
+{
+  struct triedge hulltri;
+  struct triedge nexttri;
+  struct triedge starttri;
+  struct edge hulledge;
+  triangle **deadtri;
+  point horg, hdest;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose) {
+    printf("  Marking concavities (external triangles) for elimination.\n");
+  }
+  /* Find a triangle handle on the hull. */
+  hulltri.tri = dummytri;
+  hulltri.orient = 0;
+  symself(hulltri);
+  /* Remember where we started so we know when to stop. */
+  triedgecopy(hulltri, starttri);
+  /* Go once counterclockwise around the convex hull. */
+  do {
+    /* Ignore triangles that are already infected. */
+    if (!infected(hulltri)) {
+      /* Is the triangle protected by a shell edge? */
+      tspivot(hulltri, hulledge);
+      if (hulledge.sh == dummysh) {
+        /* The triangle is not protected; infect it. */
+        infect(hulltri);
+        deadtri = (triangle **) poolalloc(&viri);
+        *deadtri = hulltri.tri;
+      } else {
+        /* The triangle is protected; set boundary markers if appropriate. */
+        if (mark(hulledge) == 0) {
+          setmark(hulledge, 1);
+          org(hulltri, horg);
+          dest(hulltri, hdest);
+          if (pointmark(horg) == 0) {
+            setpointmark(horg, 1);
+          }
+          if (pointmark(hdest) == 0) {
+            setpointmark(hdest, 1);
+          }
+        }
+      }
+    }
+    /* To find the next hull edge, go clockwise around the next vertex. */
+    lnextself(hulltri);
+    oprev(hulltri, nexttri);
+    while (nexttri.tri != dummytri) {
+      triedgecopy(nexttri, hulltri);
+      oprev(hulltri, nexttri);
+    }
+  } while (!triedgeequal(hulltri, starttri));
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  plague()   Spread the virus from all infected triangles to any neighbors */
+/*             not protected by shell edges.  Delete all infected triangles. */
+/*                                                                           */
+/*  This is the procedure that actually creates holes and concavities.       */
+/*                                                                           */
+/*  This procedure operates in two phases.  The first phase identifies all   */
+/*  the triangles that will die, and marks them as infected.  They are       */
+/*  marked to ensure that each triangle is added to the virus pool only      */
+/*  once, so the procedure will terminate.                                   */
+/*                                                                           */
+/*  The second phase actually eliminates the infected triangles.  It also    */
+/*  eliminates orphaned points.                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+void plague()
+{
+  struct triedge testtri;
+  struct triedge neighbor;
+  triangle **virusloop;
+  triangle **deadtri;
+  struct edge neighborshelle;
+  point testpoint;
+  point norg, ndest;
+  point deadorg, deaddest, deadapex;
+  int killorg;
+  triangle ptr;             /* Temporary variable used by sym() and onext(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose) {
+    printf("  Marking neighbors of marked triangles.\n");
+  }
+  /* Loop through all the infected triangles, spreading the virus to */
+  /*   their neighbors, then to their neighbors' neighbors.          */
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+    /* A triangle is marked as infected by messing with one of its shell */
+    /*   edges, setting it to an illegal value.  Hence, we have to       */
+    /*   temporarily uninfect this triangle so that we can examine its   */
+    /*   adjacent shell edges.                                           */
+    uninfect(testtri);
+    if (verbose > 2) {
+      /* Assign the triangle an orientation for convenience in */
+      /*   checking its points.                                */
+      testtri.orient = 0;
+      org(testtri, deadorg);
+      dest(testtri, deaddest);
+      apex(testtri, deadapex);
+      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+             deadorg[0], deadorg[1], deaddest[0], deaddest[1],
+             deadapex[0], deadapex[1]);
+    }
+    /* Check each of the triangle's three neighbors. */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      /* Find the neighbor. */
+      sym(testtri, neighbor);
+      /* Check for a shell between the triangle and its neighbor. */
+      tspivot(testtri, neighborshelle);
+      /* Check if the neighbor is nonexistent or already infected. */
+      if ((neighbor.tri == dummytri) || infected(neighbor)) {
+        if (neighborshelle.sh != dummysh) {
+          /* There is a shell edge separating the triangle from its */
+          /*   neighbor, but both triangles are dying, so the shell */
+          /*   edge dies too.                                       */
+          shelledealloc(neighborshelle.sh);
+          if (neighbor.tri != dummytri) {
+            /* Make sure the shell edge doesn't get deallocated again */
+            /*   later when the infected neighbor is visited.         */
+            uninfect(neighbor);
+            tsdissolve(neighbor);
+            infect(neighbor);
+          }
+        }
+      } else {                   /* The neighbor exists and is not infected. */
+        if (neighborshelle.sh == dummysh) {
+          /* There is no shell edge protecting the neighbor, so */
+          /*   the neighbor becomes infected.                   */
+          if (verbose > 2) {
+            org(neighbor, deadorg);
+            dest(neighbor, deaddest);
+            apex(neighbor, deadapex);
+            printf(
+              "    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+                   deadorg[0], deadorg[1], deaddest[0], deaddest[1],
+                   deadapex[0], deadapex[1]);
+          }
+          infect(neighbor);
+          /* Ensure that the neighbor's neighbors will be infected. */
+          deadtri = (triangle **) poolalloc(&viri);
+          *deadtri = neighbor.tri;
+        } else {               /* The neighbor is protected by a shell edge. */
+          /* Remove this triangle from the shell edge. */
+          stdissolve(neighborshelle);
+          /* The shell edge becomes a boundary.  Set markers accordingly. */
+          if (mark(neighborshelle) == 0) {
+            setmark(neighborshelle, 1);
+          }
+          org(neighbor, norg);
+          dest(neighbor, ndest);
+          if (pointmark(norg) == 0) {
+            setpointmark(norg, 1);
+          }
+          if (pointmark(ndest) == 0) {
+            setpointmark(ndest, 1);
+          }
+        }
+      }
+    }
+    /* Remark the triangle as infected, so it doesn't get added to the */
+    /*   virus pool again.                                             */
+    infect(testtri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+
+  if (verbose) {
+    printf("  Deleting marked triangles.\n");
+  }
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+
+    /* Check each of the three corners of the triangle for elimination. */
+    /*   This is done by walking around each point, checking if it is   */
+    /*   still connected to at least one live triangle.                 */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      org(testtri, testpoint);
+      /* Check if the point has already been tested. */
+      if (testpoint != (point) NULL) {
+        killorg = 1;
+        /* Mark the corner of the triangle as having been tested. */
+        setorg(testtri, NULL);
+        /* Walk counterclockwise about the point. */
+        onext(testtri, neighbor);
+        /* Stop upon reaching a boundary or the starting triangle. */
+        while ((neighbor.tri != dummytri)
+               && (!triedgeequal(neighbor, testtri))) {
+          if (infected(neighbor)) {
+            /* Mark the corner of this triangle as having been tested. */
+            setorg(neighbor, NULL);
+          } else {
+            /* A live triangle.  The point survives. */
+            killorg = 0;
+          }
+          /* Walk counterclockwise about the point. */
+          onextself(neighbor);
+        }
+        /* If we reached a boundary, we must walk clockwise as well. */
+        if (neighbor.tri == dummytri) {
+          /* Walk clockwise about the point. */
+          oprev(testtri, neighbor);
+          /* Stop upon reaching a boundary. */
+          while (neighbor.tri != dummytri) {
+            if (infected(neighbor)) {
+            /* Mark the corner of this triangle as having been tested. */
+              setorg(neighbor, NULL);
+            } else {
+              /* A live triangle.  The point survives. */
+              killorg = 0;
+            }
+            /* Walk clockwise about the point. */
+            oprevself(neighbor);
+          }
+        }
+        if (killorg) {
+          if (verbose > 1) {
+            printf("    Deleting point (%.12g, %.12g)\n",
+                   testpoint[0], testpoint[1]);
+          }
+          pointdealloc(testpoint);
+        }
+      }
+    }
+
+    /* Record changes in the number of boundary edges, and disconnect */
+    /*   dead triangles from their neighbors.                         */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      sym(testtri, neighbor);
+      if (neighbor.tri == dummytri) {
+        /* There is no neighboring triangle on this edge, so this edge    */
+        /*   is a boundary edge.  This triangle is being deleted, so this */
+        /*   boundary edge is deleted.                                    */
+        hullsize--;
+      } else {
+        /* Disconnect the triangle from its neighbor. */
+        dissolve(neighbor);
+        /* There is a neighboring triangle on this edge, so this edge */
+        /*   becomes a boundary edge when this triangle is deleted.   */
+        hullsize++;
+      }
+    }
+    /* Return the dead triangle to the pool of triangles. */
+    triangledealloc(testtri.tri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+  /* Empty the virus pool. */
+  poolrestart(&viri);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  regionplague()   Spread regional attributes and/or area constraints      */
+/*                   (from a .poly file) throughout the mesh.                */
+/*                                                                           */
+/*  This procedure operates in two phases.  The first phase spreads an       */
+/*  attribute and/or an area constraint through a (segment-bounded) region.  */
+/*  The triangles are marked to ensure that each triangle is added to the    */
+/*  virus pool only once, so the procedure will terminate.                   */
+/*                                                                           */
+/*  The second phase uninfects all infected triangles, returning them to     */
+/*  normal.                                                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+void regionplague(attribute, area)
+REAL attribute;
+REAL area;
+{
+  struct triedge testtri;
+  struct triedge neighbor;
+  triangle **virusloop;
+  triangle **regiontri;
+  struct edge neighborshelle;
+  point regionorg, regiondest, regionapex;
+  triangle ptr;             /* Temporary variable used by sym() and onext(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (verbose > 1) {
+    printf("  Marking neighbors of marked triangles.\n");
+  }
+  /* Loop through all the infected triangles, spreading the attribute      */
+  /*   and/or area constraint to their neighbors, then to their neighbors' */
+  /*   neighbors.                                                          */
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+    /* A triangle is marked as infected by messing with one of its shell */
+    /*   edges, setting it to an illegal value.  Hence, we have to       */
+    /*   temporarily uninfect this triangle so that we can examine its   */
+    /*   adjacent shell edges.                                           */
+    uninfect(testtri);
+    if (regionattrib) {
+      /* Set an attribute. */
+      setelemattribute(testtri, eextras, attribute);
+    }
+    if (vararea) {
+      /* Set an area constraint. */
+      setareabound(testtri, area);
+    }
+    if (verbose > 2) {
+      /* Assign the triangle an orientation for convenience in */
+      /*   checking its points.                                */
+      testtri.orient = 0;
+      org(testtri, regionorg);
+      dest(testtri, regiondest);
+      apex(testtri, regionapex);
+      printf("    Checking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+             regionorg[0], regionorg[1], regiondest[0], regiondest[1],
+             regionapex[0], regionapex[1]);
+    }
+    /* Check each of the triangle's three neighbors. */
+    for (testtri.orient = 0; testtri.orient < 3; testtri.orient++) {
+      /* Find the neighbor. */
+      sym(testtri, neighbor);
+      /* Check for a shell between the triangle and its neighbor. */
+      tspivot(testtri, neighborshelle);
+      /* Make sure the neighbor exists, is not already infected, and */
+      /*   isn't protected by a shell edge.                          */
+      if ((neighbor.tri != dummytri) && !infected(neighbor)
+          && (neighborshelle.sh == dummysh)) {
+        if (verbose > 2) {
+          org(neighbor, regionorg);
+          dest(neighbor, regiondest);
+          apex(neighbor, regionapex);
+          printf("    Marking (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+                 regionorg[0], regionorg[1], regiondest[0], regiondest[1],
+                 regionapex[0], regionapex[1]);
+        }
+        /* Infect the neighbor. */
+        infect(neighbor);
+        /* Ensure that the neighbor's neighbors will be infected. */
+        regiontri = (triangle **) poolalloc(&viri);
+        *regiontri = neighbor.tri;
+      }
+    }
+    /* Remark the triangle as infected, so it doesn't get added to the */
+    /*   virus pool again.                                             */
+    infect(testtri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+
+  /* Uninfect all triangles. */
+  if (verbose > 1) {
+    printf("  Unmarking marked triangles.\n");
+  }
+  traversalinit(&viri);
+  virusloop = (triangle **) traverse(&viri);
+  while (virusloop != (triangle **) NULL) {
+    testtri.tri = *virusloop;
+    uninfect(testtri);
+    virusloop = (triangle **) traverse(&viri);
+  }
+  /* Empty the virus pool. */
+  poolrestart(&viri);
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  carveholes()   Find the holes and infect them.  Find the area            */
+/*                 constraints and infect them.  Infect the convex hull.     */
+/*                 Spread the infection and kill triangles.  Spread the      */
+/*                 area constraints.                                         */
+/*                                                                           */
+/*  This routine mainly calls other routines to carry out all these          */
+/*  functions.                                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+void carveholes(holelist, holes, regionlist, regions)
+REAL *holelist;
+int holes;
+REAL *regionlist;
+int regions;
+{
+  struct triedge searchtri;
+  struct triedge triangleloop;
+  struct triedge *regiontris;
+  triangle **holetri;
+  triangle **regiontri;
+  point searchorg, searchdest;
+  enum locateresult intersect;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+  if (!(quiet || (noholes && convex))) {
+    printf("Removing unwanted triangles.\n");
+    if (verbose && (holes > 0)) {
+      printf("  Marking holes for elimination.\n");
+    }
+  }
+
+  if (regions > 0) {
+    /* Allocate storage for the triangles in which region points fall. */
+    regiontris = (struct triedge *) malloc(regions * sizeof(struct triedge));
+    if (regiontris == (struct triedge *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+
+  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
+    /* Initialize a pool of viri to be used for holes, concavities, */
+    /*   regional attributes, and/or regional area constraints.     */
+    poolinit(&viri, sizeof(triangle *), VIRUSPERBLOCK, POINTER, 0);
+  }
+
+  if (!convex) {
+    /* Mark as infected any unprotected triangles on the boundary. */
+    /*   This is one way by which concavities are created.         */
+    infecthull();
+  }
+
+  if ((holes > 0) && !noholes) {
+    /* Infect each triangle in which a hole lies. */
+    for (i = 0; i < 2 * holes; i += 2) {
+      /* Ignore holes that aren't within the bounds of the mesh. */
+      if ((holelist[i] >= xmin) && (holelist[i] <= xmax)
+          && (holelist[i + 1] >= ymin) && (holelist[i + 1] <= ymax)) {
+        /* Start searching from some triangle on the outer boundary. */
+        searchtri.tri = dummytri;
+        searchtri.orient = 0;
+        symself(searchtri);
+        /* Ensure that the hole is to the left of this boundary edge; */
+        /*   otherwise, locate() will falsely report that the hole    */
+        /*   falls within the starting triangle.                      */
+        org(searchtri, searchorg);
+        dest(searchtri, searchdest);
+        if (counterclockwise(searchorg, searchdest, &holelist[i]) > 0.0) {
+          /* Find a triangle that contains the hole. */
+          intersect = locate(&holelist[i], &searchtri);
+          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
+            /* Infect the triangle.  This is done by marking the triangle */
+            /*   as infect and including the triangle in the virus pool.  */
+            infect(searchtri);
+            holetri = (triangle **) poolalloc(&viri);
+            *holetri = searchtri.tri;
+          }
+        }
+      }
+    }
+  }
+
+  /* Now, we have to find all the regions BEFORE we carve the holes, because */
+  /*   locate() won't work when the triangulation is no longer convex.       */
+  /*   (Incidentally, this is the reason why regional attributes and area    */
+  /*   constraints can't be used when refining a preexisting mesh, which     */
+  /*   might not be convex; they can only be used with a freshly             */
+  /*   triangulated PSLG.)                                                   */
+  if (regions > 0) {
+    /* Find the starting triangle for each region. */
+    for (i = 0; i < regions; i++) {
+      regiontris[i].tri = dummytri;
+      /* Ignore region points that aren't within the bounds of the mesh. */
+      if ((regionlist[4 * i] >= xmin) && (regionlist[4 * i] <= xmax) &&
+          (regionlist[4 * i + 1] >= ymin) && (regionlist[4 * i + 1] <= ymax)) {
+        /* Start searching from some triangle on the outer boundary. */
+        searchtri.tri = dummytri;
+        searchtri.orient = 0;
+        symself(searchtri);
+        /* Ensure that the region point is to the left of this boundary */
+        /*   edge; otherwise, locate() will falsely report that the     */
+        /*   region point falls within the starting triangle.           */
+        org(searchtri, searchorg);
+        dest(searchtri, searchdest);
+        if (counterclockwise(searchorg, searchdest, &regionlist[4 * i]) >
+            0.0) {
+          /* Find a triangle that contains the region point. */
+          intersect = locate(&regionlist[4 * i], &searchtri);
+          if ((intersect != OUTSIDE) && (!infected(searchtri))) {
+            /* Record the triangle for processing after the */
+            /*   holes have been carved.                    */
+            triedgecopy(searchtri, regiontris[i]);
+          }
+        }
+      }
+    }
+  }
+
+  if (viri.items > 0) {
+    /* Carve the holes and concavities. */
+    plague();
+  }
+  /* The virus pool should be empty now. */
+
+  if (regions > 0) {
+    if (!quiet) {
+      if (regionattrib) {
+        if (vararea) {
+          printf("Spreading regional attributes and area constraints.\n");
+        } else {
+          printf("Spreading regional attributes.\n");
+        }
+      } else { 
+        printf("Spreading regional area constraints.\n");
+      }
+    }
+    if (regionattrib && !refine) {
+      /* Assign every triangle a regional attribute of zero. */
+      traversalinit(&triangles);
+      triangleloop.orient = 0;
+      triangleloop.tri = triangletraverse();
+      while (triangleloop.tri != (triangle *) NULL) {
+        setelemattribute(triangleloop, eextras, 0.0);
+        triangleloop.tri = triangletraverse();
+      }
+    }
+    for (i = 0; i < regions; i++) {
+      if (regiontris[i].tri != dummytri) {
+        /* Make sure the triangle under consideration still exists. */
+        /*   It may have been eaten by the virus.                   */
+        if (regiontris[i].tri[3] != (triangle) NULL) {
+          /* Put one triangle in the virus pool. */
+          infect(regiontris[i]);
+          regiontri = (triangle **) poolalloc(&viri);
+          *regiontri = regiontris[i].tri;
+          /* Apply one region's attribute and/or area constraint. */
+          regionplague(regionlist[4 * i + 2], regionlist[4 * i + 3]);
+          /* The virus pool should be empty now. */
+        }
+      }
+    }
+    if (regionattrib && !refine) {
+      /* Note the fact that each triangle has an additional attribute. */
+      eextras++;
+    }
+  }
+
+  /* Free up memory. */
+  if (((holes > 0) && !noholes) || !convex || (regions > 0)) {
+    pooldeinit(&viri);
+  }
+  if (regions > 0) {
+    free(regiontris);
+  }
+}
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Carving out holes and concavities ends here               *********/
+
+/********* Mesh quality maintenance begins here                      *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  tallyencs()   Traverse the entire list of shell edges, check each edge   */
+/*                to see if it is encroached.  If so, add it to the list.    */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void tallyencs()
+{
+  struct edge edgeloop;
+  int dummy;
+
+  traversalinit(&shelles);
+  edgeloop.shorient = 0;
+  edgeloop.sh = shelletraverse();
+  while (edgeloop.sh != (shelle *) NULL) {
+    /* If the segment is encroached, add it to the list. */
+    dummy = checkedge4encroach(&edgeloop);
+    edgeloop.sh = shelletraverse();
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  precisionerror()  Print an error message for precision problems.         */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void precisionerror()
+{
+  printf("Try increasing the area criterion and/or reducing the minimum\n");
+  printf("  allowable angle so that tiny triangles are not created.\n");
+#ifdef SINGLE
+  printf("Alternatively, try recompiling me with double precision\n");
+  printf("  arithmetic (by removing \"#define SINGLE\" from the\n");
+  printf("  source file or \"-DSINGLE\" from the makefile).\n");
+#endif /* SINGLE */
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  repairencs()   Find and repair all the encroached segments.              */
+/*                                                                           */
+/*  Encroached segments are repaired by splitting them by inserting a point  */
+/*  at or near their centers.                                                */
+/*                                                                           */
+/*  `flaws' is a flag that specifies whether one should take note of new     */
+/*  encroached segments and bad triangles that result from inserting points  */
+/*  to repair existing encroached segments.                                  */
+/*                                                                           */
+/*  When a segment is split, the two resulting subsegments are always        */
+/*  tested to see if they are encroached upon, regardless of the value       */
+/*  of `flaws'.                                                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void repairencs(flaws)
+int flaws;
+{
+  struct triedge enctri;
+  struct triedge testtri;
+  struct edge *encloop;
+  struct edge testsh;
+  point eorg, edest;
+  point newpoint;
+  enum insertsiteresult success;
+  REAL segmentlength, nearestpoweroftwo;
+  REAL split;
+  int acuteorg, acutedest;
+  int dummy;
+  int i;
+  triangle ptr;                     /* Temporary variable used by stpivot(). */
+  shelle sptr;                        /* Temporary variable used by snext(). */
+
+  while ((badsegments.items > 0) && (steinerleft != 0)) {
+    traversalinit(&badsegments);
+    encloop = badsegmenttraverse();
+    while ((encloop != (struct edge *) NULL) && (steinerleft != 0)) {
+      /* To decide where to split a segment, we need to know if the  */
+      /*   segment shares an endpoint with an adjacent segment.      */
+      /*   The concern is that, if we simply split every encroached  */
+      /*   segment in its center, two adjacent segments with a small */
+      /*   angle between them might lead to an infinite loop; each   */
+      /*   point added to split one segment will encroach upon the   */
+      /*   other segment, which must then be split with a point that */
+      /*   will encroach upon the first segment, and so on forever.  */
+      /* To avoid this, imagine a set of concentric circles, whose   */
+      /*   radii are powers of two, about each segment endpoint.     */
+      /*   These concentric circles determine where the segment is   */
+      /*   split.  (If both endpoints are shared with adjacent       */
+      /*   segments, split the segment in the middle, and apply the  */
+      /*   concentric shells for later splittings.)                  */
+
+      /* Is the origin shared with another segment? */
+      stpivot(*encloop, enctri);
+      lnext(enctri, testtri);
+      tspivot(testtri, testsh);
+      acuteorg = testsh.sh != dummysh;
+      /* Is the destination shared with another segment? */
+      lnextself(testtri);
+      tspivot(testtri, testsh);
+      acutedest = testsh.sh != dummysh;
+      /* Now, check the other side of the segment, if there's a triangle */
+      /*   there.                                                        */
+      sym(enctri, testtri);
+      if (testtri.tri != dummytri) {
+        /* Is the destination shared with another segment? */
+        lnextself(testtri);
+        tspivot(testtri, testsh);
+        acutedest = acutedest || (testsh.sh != dummysh);
+        /* Is the origin shared with another segment? */
+        lnextself(testtri);
+        tspivot(testtri, testsh);
+        acuteorg = acuteorg || (testsh.sh != dummysh);
+      }
+
+      sorg(*encloop, eorg);
+      sdest(*encloop, edest);
+      /* Use the concentric circles if exactly one endpoint is shared */
+      /*   with another adjacent segment.                             */
+      if (acuteorg ^ acutedest) {
+        segmentlength = sqrt((edest[0] - eorg[0]) * (edest[0] - eorg[0])
+                             + (edest[1] - eorg[1]) * (edest[1] - eorg[1]));
+        /* Find the power of two nearest the segment's length. */
+        nearestpoweroftwo = 1.0;
+        while (segmentlength > SQUAREROOTTWO * nearestpoweroftwo) {
+          nearestpoweroftwo *= 2.0;
+        }
+        while (segmentlength < (0.5 * SQUAREROOTTWO) * nearestpoweroftwo) {
+          nearestpoweroftwo *= 0.5;
+        }
+        /* Where do we split the segment? */
+        split = 0.5 * nearestpoweroftwo / segmentlength;
+        if (acutedest) {
+          split = 1.0 - split;
+        }
+      } else {
+        /* If we're not worried about adjacent segments, split */
+        /*   this segment in the middle.                       */
+        split = 0.5;
+      }
+
+      /* Create the new point. */
+      newpoint = (point) poolalloc(&points);
+      /* Interpolate its coordinate and attributes. */
+      for (i = 0; i < 2 + nextras; i++) {
+        newpoint[i] = (1.0 - split) * eorg[i] + split * edest[i];
+      }
+      setpointmark(newpoint, mark(*encloop));
+      if (verbose > 1) {
+        printf(
+        "  Splitting edge (%.12g, %.12g) (%.12g, %.12g) at (%.12g, %.12g).\n",
+               eorg[0], eorg[1], edest[0], edest[1], newpoint[0], newpoint[1]);
+      }
+      /* Check whether the new point lies on an endpoint. */
+      if (((newpoint[0] == eorg[0]) && (newpoint[1] == eorg[1]))
+        || ((newpoint[0] == edest[0]) && (newpoint[1] == edest[1]))) {
+        printf("Error:  Ran out of precision at (%.12g, %.12g).\n",
+               newpoint[0], newpoint[1]);
+        printf("I attempted to split a segment to a smaller size than can\n");
+        printf("  be accommodated by the finite precision of floating point\n"
+               );
+        printf("  arithmetic.\n");
+        precisionerror();
+        exit(1);
+      }
+      /* Insert the splitting point.  This should always succeed. */
+      success = insertsite(newpoint, &enctri, encloop, flaws, flaws);
+      if ((success != SUCCESSFULPOINT) && (success != ENCROACHINGPOINT)) {
+        printf("Internal error in repairencs():\n");
+        printf("  Failure to split a segment.\n");
+        internalerror();
+      }
+      if (steinerleft > 0) {
+        steinerleft--;
+      }
+      /* Check the two new subsegments to see if they're encroached. */
+      dummy = checkedge4encroach(encloop);
+      snextself(*encloop);
+      dummy = checkedge4encroach(encloop);
+
+      badsegmentdealloc(encloop);
+      encloop = badsegmenttraverse();
+    }
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  tallyfaces()   Test every triangle in the mesh for quality measures.     */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void tallyfaces()
+{
+  struct triedge triangleloop;
+
+  if (verbose) {
+    printf("  Making a list of bad triangles.\n");
+  }
+  traversalinit(&triangles);
+  triangleloop.orient = 0;
+  triangleloop.tri = triangletraverse();
+  while (triangleloop.tri != (triangle *) NULL) {
+    /* If the triangle is bad, enqueue it. */
+    testtriangle(&triangleloop);
+    triangleloop.tri = triangletraverse();
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  findcircumcenter()   Find the circumcenter of a triangle.                */
+/*                                                                           */
+/*  The result is returned both in terms of x-y coordinates and xi-eta       */
+/*  coordinates.  The xi-eta coordinate system is defined in terms of the    */
+/*  triangle:  the origin of the triangle is the origin of the coordinate    */
+/*  system; the destination of the triangle is one unit along the xi axis;   */
+/*  and the apex of the triangle is one unit along the eta axis.             */
+/*                                                                           */
+/*  The return value indicates which edge of the triangle is shortest.       */
+/*                                                                           */
+/*****************************************************************************/
+
+enum circumcenterresult findcircumcenter(torg, tdest, tapex, circumcenter,
+                                         xi, eta)
+point torg;
+point tdest;
+point tapex;
+point circumcenter;
+REAL *xi;
+REAL *eta;
+{
+  REAL xdo, ydo, xao, yao, xad, yad;
+  REAL dodist, aodist, addist;
+  REAL denominator;
+  REAL dx, dy;
+
+  circumcentercount++;
+
+  /* Compute the circumcenter of the triangle. */
+  xdo = tdest[0] - torg[0];
+  ydo = tdest[1] - torg[1];
+  xao = tapex[0] - torg[0];
+  yao = tapex[1] - torg[1];
+  dodist = xdo * xdo + ydo * ydo;
+  aodist = xao * xao + yao * yao;
+  if (noexact) {
+    denominator = (REAL)(0.5 / (xdo * yao - xao * ydo));
+  } else {
+    /* Use the counterclockwise() routine to ensure a positive (and */
+    /*   reasonably accurate) result, avoiding any possibility of   */
+    /*   division by zero.                                          */
+    denominator = (REAL)(0.5 / counterclockwise(tdest, tapex, torg));
+    /* Don't count the above as an orientation test. */
+    counterclockcount--;
+  }
+  circumcenter[0] = torg[0] - (ydo * aodist - yao * dodist) * denominator;  
+  circumcenter[1] = torg[1] + (xdo * aodist - xao * dodist) * denominator;  
+
+  /* To interpolate point attributes for the new point inserted at  */
+  /*   the circumcenter, define a coordinate system with a xi-axis, */
+  /*   directed from the triangle's origin to its destination, and  */
+  /*   an eta-axis, directed from its origin to its apex.           */
+  /*   Calculate the xi and eta coordinates of the circumcenter.    */
+  dx = circumcenter[0] - torg[0];
+  dy = circumcenter[1] - torg[1];
+  *xi = (REAL)((dx * yao - xao * dy) * (2.0 * denominator));
+  *eta = (REAL)((xdo * dy - dx * ydo) * (2.0 * denominator));
+
+  xad = tapex[0] - tdest[0];
+  yad = tapex[1] - tdest[1];
+  addist = xad * xad + yad * yad;
+  if ((addist < dodist) && (addist < aodist)) {
+    return OPPOSITEORG;
+  } else if (dodist < aodist) {
+    return OPPOSITEAPEX;
+  } else {
+    return OPPOSITEDEST;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  splittriangle()   Inserts a point at the circumcenter of a triangle.     */
+/*                    Deletes the newly inserted point if it encroaches upon */
+/*                    a segment.                                             */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void splittriangle(badtri)
+struct badface *badtri;
+{
+  point borg, bdest, bapex;
+  point newpoint;
+  REAL xi, eta;
+  enum insertsiteresult success;
+  enum circumcenterresult shortedge;
+  int errorflag;
+  int i;
+
+  org(badtri->badfacetri, borg);
+  dest(badtri->badfacetri, bdest);
+  apex(badtri->badfacetri, bapex);
+  /* Make sure that this triangle is still the same triangle it was      */
+  /*   when it was tested and determined to be of bad quality.           */
+  /*   Subsequent transformations may have made it a different triangle. */
+  if ((borg == badtri->faceorg) && (bdest == badtri->facedest) &&
+      (bapex == badtri->faceapex)) {
+    if (verbose > 1) {
+      printf("  Splitting this triangle at its circumcenter:\n");
+      printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n", borg[0],
+             borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
+    }
+    errorflag = 0;
+    /* Create a new point at the triangle's circumcenter. */
+    newpoint = (point) poolalloc(&points);
+    shortedge = findcircumcenter(borg, bdest, bapex, newpoint, &xi, &eta);
+    /* Check whether the new point lies on a triangle vertex. */
+    if (((newpoint[0] == borg[0]) && (newpoint[1] == borg[1]))
+        || ((newpoint[0] == bdest[0]) && (newpoint[1] == bdest[1]))
+        || ((newpoint[0] == bapex[0]) && (newpoint[1] == bapex[1]))) {
+      if (!quiet) {
+        printf("Warning:  New point (%.12g, %.12g) falls on existing vertex.\n"
+               , newpoint[0], newpoint[1]);
+        errorflag = 1;
+      }
+      pointdealloc(newpoint);
+    } else {
+      for (i = 2; i < 2 + nextras; i++) {
+        /* Interpolate the point attributes at the circumcenter. */
+        newpoint[i] = borg[i] + xi * (bdest[i] - borg[i])
+                             + eta * (bapex[i] - borg[i]);
+      }
+      /* The new point must be in the interior, and have a marker of zero. */
+      setpointmark(newpoint, 0);
+      /* Ensure that the handle `badtri->badfacetri' represents the shortest */
+      /*   edge of the triangle.  This ensures that the circumcenter must    */
+      /*   fall to the left of this edge, so point location will work.       */
+      if (shortedge == OPPOSITEORG) {
+        lnextself(badtri->badfacetri);
+      } else if (shortedge == OPPOSITEDEST) {
+        lprevself(badtri->badfacetri);
+      }
+      /* Insert the circumcenter, searching from the edge of the triangle, */
+      /*   and maintain the Delaunay property of the triangulation.        */
+      success = insertsite(newpoint, &(badtri->badfacetri),
+                           (struct edge *) NULL, 1, 1);
+      if (success == SUCCESSFULPOINT) {
+        if (steinerleft > 0) {
+          steinerleft--;
+        }
+      } else if (success == ENCROACHINGPOINT) {
+        /* If the newly inserted point encroaches upon a segment, delete it. */
+        deletesite(&(badtri->badfacetri));
+      } else if (success == VIOLATINGPOINT) {
+        /* Failed to insert the new point, but some segment was */
+        /*   marked as being encroached.                        */
+        pointdealloc(newpoint);
+      } else {                                  /* success == DUPLICATEPOINT */
+        /* Failed to insert the new point because a vertex is already there. */
+        if (!quiet) {
+          printf(
+            "Warning:  New point (%.12g, %.12g) falls on existing vertex.\n"
+                 , newpoint[0], newpoint[1]);
+          errorflag = 1;
+        }
+        pointdealloc(newpoint);
+      }
+    }
+    if (errorflag) {
+      if (verbose) {
+        printf("  The new point is at the circumcenter of triangle\n");
+        printf("    (%.12g, %.12g) (%.12g, %.12g) (%.12g, %.12g)\n",
+               borg[0], borg[1], bdest[0], bdest[1], bapex[0], bapex[1]);
+      }
+      printf("This probably means that I am trying to refine triangles\n");
+      printf("  to a smaller size than can be accommodated by the finite\n");
+      printf("  precision of floating point arithmetic.  (You can be\n");
+      printf("  sure of this if I fail to terminate.)\n");
+      precisionerror();
+    }
+  }
+  /* Return the bad triangle to the pool. */
+  pooldealloc(&badtriangles, (VOID *) badtri);
+}
+
+#endif /* not CDT_ONLY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  enforcequality()   Remove all the encroached edges and bad triangles     */
+/*                     from the triangulation.                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef CDT_ONLY
+
+void enforcequality()
+{
+  int i;
+
+  if (!quiet) {
+    printf("Adding Steiner points to enforce quality.\n");
+  }
+  /* Initialize the pool of encroached segments. */
+  poolinit(&badsegments, sizeof(struct edge), BADSEGMENTPERBLOCK, POINTER, 0);
+  if (verbose) {
+    printf("  Looking for encroached segments.\n");
+  }
+  /* Test all segments to see if they're encroached. */
+  tallyencs();
+  if (verbose && (badsegments.items > 0)) {
+    printf("  Splitting encroached segments.\n");
+  }
+  /* Note that steinerleft == -1 if an unlimited number */
+  /*   of Steiner points is allowed.                    */
+  while ((badsegments.items > 0) && (steinerleft != 0)) {
+    /* Fix the segments without noting newly encroached segments or   */
+    /*   bad triangles.  The reason we don't want to note newly       */
+    /*   encroached segments is because some encroached segments are  */
+    /*   likely to be noted multiple times, and would then be blindly */
+    /*   split multiple times.  I should fix that some time.          */
+    repairencs(0);
+    /* Now, find all the segments that became encroached while adding */
+    /*   points to split encroached segments.                         */
+    tallyencs();
+  }
+  /* At this point, if we haven't run out of Steiner points, the */
+  /*   triangulation should be (conforming) Delaunay.            */
+
+  /* Next, we worry about enforcing triangle quality. */
+  if ((minangle > 0.0) || vararea || fixedarea) {
+    /* Initialize the pool of bad triangles. */
+    poolinit(&badtriangles, sizeof(struct badface), BADTRIPERBLOCK, POINTER,
+             0);
+    /* Initialize the queues of bad triangles. */
+    for (i = 0; i < 64; i++) {
+      queuefront[i] = (struct badface *) NULL;
+      queuetail[i] = &queuefront[i];
+    }
+    /* Test all triangles to see if they're bad. */
+    tallyfaces();
+    if (verbose) {
+      printf("  Splitting bad triangles.\n");
+    }
+    while ((badtriangles.items > 0) && (steinerleft != 0)) {
+      /* Fix one bad triangle by inserting a point at its circumcenter. */
+      splittriangle(dequeuebadtri());
+      /* Fix any encroached segments that may have resulted.  Record */
+      /*   any new bad triangles or encroached segments that result. */
+      if (badsegments.items > 0) {
+        repairencs(1);
+      }
+    }
+  }
+  /* At this point, if we haven't run out of Steiner points, the */
+  /*   triangulation should be (conforming) Delaunay and have no */
+  /*   low-quality triangles.                                    */
+
+  /* Might we have run out of Steiner points too soon? */
+  if (!quiet && (badsegments.items > 0) && (steinerleft == 0)) {
+    printf("\nWarning:  I ran out of Steiner points, but the mesh has\n");
+    if (badsegments.items == 1) {
+      printf("  an encroached segment, and therefore might not be truly\n");
+    } else {
+      printf("  %ld encroached segments, and therefore might not be truly\n",
+             badsegments.items);
+    }
+    printf("  Delaunay.  If the Delaunay property is important to you,\n");
+    printf("  try increasing the number of Steiner points (controlled by\n");
+    printf("  the -S switch) slightly and try again.\n\n");
+  }
+}
+
+#endif /* not CDT_ONLY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* Mesh quality maintenance ends here                        *********/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  highorder()   Create extra nodes for quadratic subparametric elements.   */
+/*                                                                           */
+/*****************************************************************************/
+
+void highorder()
+{
+  struct triedge triangleloop, trisym;
+  struct edge checkmark;
+  point newpoint;
+  point torg, tdest;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+  if (!quiet) {
+    printf("Adding vertices for second-order triangles.\n");
+  }
+  /* The following line ensures that dead items in the pool of nodes    */
+  /*   cannot be allocated for the extra nodes associated with high     */
+  /*   order elements.  This ensures that the primary nodes (at the     */
+  /*   corners of elements) will occur earlier in the output files, and */
+  /*   have lower indices, than the extra nodes.                        */
+  points.deaditemstack = (VOID *) NULL;
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  /* To loop over the set of edges, loop over all triangles, and look at   */
+  /*   the three edges of each triangle.  If there isn't another triangle  */
+  /*   adjacent to the edge, operate on the edge.  If there is another     */
+  /*   adjacent triangle, operate on the edge only if the current triangle */
+  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
+  /*   considered only once.                                               */
+  while (triangleloop.tri != (triangle *) NULL) {
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      sym(triangleloop, trisym);
+      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
+        org(triangleloop, torg);
+        dest(triangleloop, tdest);
+        /* Create a new node in the middle of the edge.  Interpolate */
+        /*   its attributes.                                         */
+        newpoint = (point) poolalloc(&points);
+        for (i = 0; i < 2 + nextras; i++) {
+          newpoint[i] = (REAL)(0.5 * (torg[i] + tdest[i]));
+        }
+        /* Set the new node's marker to zero or one, depending on */
+        /*   whether it lies on a boundary.                       */
+        setpointmark(newpoint, trisym.tri == dummytri);
+        if (useshelles) {
+          tspivot(triangleloop, checkmark);
+          /* If this edge is a segment, transfer the marker to the new node. */
+          if (checkmark.sh != dummysh) {
+            setpointmark(newpoint, mark(checkmark));
+          }
+        }
+        if (verbose > 1) {
+          printf("  Creating (%.12g, %.12g).\n", newpoint[0], newpoint[1]);
+        }
+        /* Record the new node in the (one or two) adjacent elements. */
+        triangleloop.tri[highorderindex + triangleloop.orient] =
+                (triangle) newpoint;
+        if (trisym.tri != dummytri) {
+          trisym.tri[highorderindex + trisym.orient] = (triangle) newpoint;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+}
+
+/********* File I/O routines begin here                              *********/
+/**                                                                         **/
+/**                                                                         **/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  readline()   Read a nonempty line from a file.                           */
+/*                                                                           */
+/*  A line is considered "nonempty" if it contains something that looks like */
+/*  a number.                                                                */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+char *readline(string, infile, infilename)
+char *string;
+FILE *infile;
+char *infilename;
+{
+  char *result;
+
+  /* Search for something that looks like a number. */
+  do {
+    result = fgets(string, INPUTLINESIZE, infile);
+    if (result == (char *) NULL) {
+      printf("  Error:  Unexpected end of file in %s.\n", infilename);
+      exit(1);
+    }
+    /* Skip anything that doesn't look like a number, a comment, */
+    /*   or the end of a line.                                   */
+    while ((*result != '\0') && (*result != '#')
+           && (*result != '.') && (*result != '+') && (*result != '-')
+           && ((*result < '0') || (*result > '9'))) {
+      result++;
+    }
+  /* If it's a comment or end of line, read another line and try again. */
+  } while ((*result == '#') || (*result == '\0'));
+  return result;
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  findfield()   Find the next field of a string.                           */
+/*                                                                           */
+/*  Jumps past the current field by searching for whitespace, then jumps     */
+/*  past the whitespace to find the next field.                              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+char *findfield(string)
+char *string;
+{
+  char *result;
+
+  result = string;
+  /* Skip the current field.  Stop upon reaching whitespace. */
+  while ((*result != '\0') && (*result != '#')
+         && (*result != ' ') && (*result != '\t')) {
+    result++;
+  }
+  /* Now skip the whitespace and anything else that doesn't look like a */
+  /*   number, a comment, or the end of a line.                         */
+  while ((*result != '\0') && (*result != '#')
+         && (*result != '.') && (*result != '+') && (*result != '-')
+         && ((*result < '0') || (*result > '9'))) {
+    result++;
+  }
+  /* Check for a comment (prefixed with `#'). */
+  if (*result == '#') {
+    *result = '\0';
+  }
+  return result;
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  readnodes()   Read the points from a file, which may be a .node or .poly */
+/*                file.                                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void readnodes(nodefilename, polyfilename, polyfile)
+char *nodefilename;
+char *polyfilename;
+FILE **polyfile;
+{
+  FILE *infile;
+  point pointloop;
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  char *infilename;
+  REAL x, y;
+  int firstnode;
+  int nodemarkers;
+  int currentmarker;
+  int i, j;
+
+  if (poly) {
+    /* Read the points from a .poly file. */
+    if (!quiet) {
+      printf("Opening %s.\n", polyfilename);
+    }
+    *polyfile = fopen(polyfilename, "r");
+    if (*polyfile == (FILE *) NULL) {
+      printf("  Error:  Cannot access file %s.\n", polyfilename);
+      exit(1);
+    }
+    /* Read number of points, number of dimensions, number of point */
+    /*   attributes, and number of boundary markers.                */
+    stringptr = readline(inputline, *polyfile, polyfilename);
+    inpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      mesh_dim = 2;
+    } else {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nextras = 0;
+    } else {
+      nextras = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nodemarkers = 0;
+    } else {
+      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+    if (inpoints > 0) {
+      infile = *polyfile;
+      infilename = polyfilename;
+      readnodefile = 0;
+    } else {
+      /* If the .poly file claims there are zero points, that means that */
+      /*   the points should be read from a separate .node file.         */
+      readnodefile = 1;
+      infilename = innodefilename;
+    }
+  } else {
+    readnodefile = 1;
+    infilename = innodefilename;
+    *polyfile = (FILE *) NULL;
+  }
+
+  if (readnodefile) {
+    /* Read the points from a .node file. */
+    if (!quiet) {
+      printf("Opening %s.\n", innodefilename);
+    }
+    infile = fopen(innodefilename, "r");
+    if (infile == (FILE *) NULL) {
+      printf("  Error:  Cannot access file %s.\n", innodefilename);
+      exit(1);
+    }
+    /* Read number of points, number of dimensions, number of point */
+    /*   attributes, and number of boundary markers.                */
+    stringptr = readline(inputline, infile, innodefilename);
+    inpoints = (int) strtol (stringptr, &stringptr, 0);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      mesh_dim = 2;
+    } else {
+      mesh_dim = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nextras = 0;
+    } else {
+      nextras = (int) strtol (stringptr, &stringptr, 0);
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      nodemarkers = 0;
+    } else {
+      nodemarkers = (int) strtol (stringptr, &stringptr, 0);
+    }
+  }
+
+  if (inpoints < 3) {
+    printf("Error:  Input must have at least three input points.\n");
+    exit(1);
+  }
+  if (mesh_dim != 2) {
+    printf("Error:  Triangle only works with two-dimensional meshes.\n");
+    exit(1);
+  }
+
+  initializepointpool();
+
+  /* Read the points. */
+  for (i = 0; i < inpoints; i++) {
+    pointloop = (point) poolalloc(&points);
+    stringptr = readline(inputline, infile, infilename);
+    if (i == 0) {
+      firstnode = (int) strtol (stringptr, &stringptr, 0);
+      if ((firstnode == 0) || (firstnode == 1)) {
+        firstnumber = firstnode;
+      }
+    }
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no x coordinate.\n", firstnumber + i);
+      exit(1);
+    }
+    x = (REAL) strtod(stringptr, &stringptr);
+    stringptr = findfield(stringptr);
+    if (*stringptr == '\0') {
+      printf("Error:  Point %d has no y coordinate.\n", firstnumber + i);
+      exit(1);
+    }
+    y = (REAL) strtod(stringptr, &stringptr);
+    pointloop[0] = x;
+    pointloop[1] = y;
+    /* Read the point attributes. */
+    for (j = 2; j < 2 + nextras; j++) {
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        pointloop[j] = 0.0;
+      } else {
+        pointloop[j] = (REAL) strtod(stringptr, &stringptr);
+      }
+    }
+    if (nodemarkers) {
+      /* Read a point marker. */
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        setpointmark(pointloop, 0);
+      } else {
+        currentmarker = (int) strtol (stringptr, &stringptr, 0);
+        setpointmark(pointloop, currentmarker);
+      }
+    } else {
+      /* If no markers are specified in the file, they default to zero. */
+      setpointmark(pointloop, 0);
+    }
+    /* Determine the smallest and largest x and y coordinates. */
+    if (i == 0) {
+      xmin = xmax = x;
+      ymin = ymax = y;
+    } else {
+      xmin = (x < xmin) ? x : xmin;
+      xmax = (x > xmax) ? x : xmax;
+      ymin = (y < ymin) ? y : ymin;
+      ymax = (y > ymax) ? y : ymax;
+    }
+  }
+  if (readnodefile) {
+    fclose(infile);
+  }
+
+  /* Nonexistent x value used as a flag to mark circle events in sweepline */
+  /*   Delaunay algorithm.                                                 */
+  xminextreme = 10 * xmin - 9 * xmax;
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  transfernodes()   Read the points from memory.                           */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void transfernodes(pointlist, pointattriblist, pointmarkerlist, numberofpoints,
+                   numberofpointattribs)
+REAL *pointlist;
+REAL *pointattriblist;
+int *pointmarkerlist;
+int numberofpoints;
+int numberofpointattribs;
+{
+  point pointloop;
+  REAL x, y;
+  int i, j;
+  int coordindex;
+  int attribindex;
+
+  inpoints = numberofpoints;
+  mesh_dim = 2;
+  nextras = numberofpointattribs;
+  readnodefile = 0;
+  if (inpoints < 3) {
+    printf("Error:  Input must have at least three input points.\n");
+    exit(1);
+  }
+
+  initializepointpool();
+
+  /* Read the points. */
+  coordindex = 0;
+  attribindex = 0;
+  for (i = 0; i < inpoints; i++) {
+    pointloop = (point) poolalloc(&points);
+    /* Read the point coordinates. */
+    x = pointloop[0] = pointlist[coordindex++];
+    y = pointloop[1] = pointlist[coordindex++];
+    /* Read the point attributes. */
+    for (j = 0; j < numberofpointattribs; j++) {
+      pointloop[2 + j] = pointattriblist[attribindex++];
+    }
+    if (pointmarkerlist != (int *) NULL) {
+      /* Read a point marker. */
+      setpointmark(pointloop, pointmarkerlist[i]);
+    } else {
+      /* If no markers are specified, they default to zero. */
+      setpointmark(pointloop, 0);
+    }
+    x = pointloop[0];
+    y = pointloop[1];
+    /* Determine the smallest and largest x and y coordinates. */
+    if (i == 0) {
+      xmin = xmax = x;
+      ymin = ymax = y;
+    } else {
+      xmin = (x < xmin) ? x : xmin;
+      xmax = (x > xmax) ? x : xmax;
+      ymin = (y < ymin) ? y : ymin;
+      ymax = (y > ymax) ? y : ymax;
+    }
+  }
+
+  /* Nonexistent x value used as a flag to mark circle events in sweepline */
+  /*   Delaunay algorithm.                                                 */
+  xminextreme = 10 * xmin - 9 * xmax;
+}
+
+#endif /* TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  readholes()   Read the holes, and possibly regional attributes and area  */
+/*                constraints, from a .poly file.                            */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void readholes(polyfile, polyfilename, hlist, holes, rlist, regions)
+FILE *polyfile;
+char *polyfilename;
+REAL **hlist;
+int *holes;
+REAL **rlist;
+int *regions;
+{
+  REAL *holelist;
+  REAL *regionlist;
+  char inputline[INPUTLINESIZE];
+  char *stringptr;
+  int index;
+  int i;
+
+  /* Read the holes. */
+  stringptr = readline(inputline, polyfile, polyfilename);
+  *holes = (int) strtol (stringptr, &stringptr, 0);
+  if (*holes > 0) {
+    holelist = (REAL *) malloc(2 * *holes * sizeof(REAL));
+    *hlist = holelist;
+    if (holelist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+    for (i = 0; i < 2 * *holes; i += 2) {
+      stringptr = readline(inputline, polyfile, polyfilename);
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Hole %d has no x coordinate.\n",
+               firstnumber + (i >> 1));
+        exit(1);
+      } else {
+        holelist[i] = (REAL) strtod(stringptr, &stringptr);
+      }
+      stringptr = findfield(stringptr);
+      if (*stringptr == '\0') {
+        printf("Error:  Hole %d has no y coordinate.\n",
+               firstnumber + (i >> 1));
+        exit(1);
+      } else {
+        holelist[i + 1] = (REAL) strtod(stringptr, &stringptr);
+      }
+    }
+  } else {
+    *hlist = (REAL *) NULL;
+  }
+
+#ifndef CDT_ONLY
+  if ((regionattrib || vararea) && !refine) {
+    /* Read the area constraints. */
+    stringptr = readline(inputline, polyfile, polyfilename);
+    *regions = (int) strtol (stringptr, &stringptr, 0);
+    if (*regions > 0) {
+      regionlist = (REAL *) malloc(4 * *regions * sizeof(REAL));
+      *rlist = regionlist;
+      if (regionlist == (REAL *) NULL) {
+        printf("Error:  Out of memory.\n");
+        exit(1);
+      }
+      index = 0;
+      for (i = 0; i < *regions; i++) {
+        stringptr = readline(inputline, polyfile, polyfilename);
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no x coordinate.\n",
+                 firstnumber + i);
+          exit(1);
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          printf("Error:  Region %d has no y coordinate.\n",
+                 firstnumber + i);
+          exit(1);
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          printf(
+            "Error:  Region %d has no region attribute or area constraint.\n",
+                 firstnumber + i);
+          exit(1);
+        } else {
+          regionlist[index++] = (REAL) strtod(stringptr, &stringptr);
+        }
+        stringptr = findfield(stringptr);
+        if (*stringptr == '\0') {
+          regionlist[index] = regionlist[index - 1];
+        } else {
+          regionlist[index] = (REAL) strtod(stringptr, &stringptr);
+        }
+        index++;
+      }
+    }
+  } else {
+    /* Set `*regions' to zero to avoid an accidental free() later. */
+    *regions = 0;
+    *rlist = (REAL *) NULL;
+  }
+#endif /* not CDT_ONLY */
+
+  fclose(polyfile);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  finishfile()   Write the command line to the output file so the user     */
+/*                 can remember how the file was generated.  Close the file. */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void finishfile(outfile, argc, argv)
+FILE *outfile;
+int argc;
+char **argv;
+{
+  int i;
+
+  fprintf(outfile, "# Generated by");
+  for (i = 0; i < argc; i++) {
+    fprintf(outfile, " ");
+    fputs(argv[i], outfile);
+  }
+  fprintf(outfile, "\n");
+  fclose(outfile);
+}
+
+#endif /* not TRILIBRARY */
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writenodes()   Number the points and write them to a .node file.         */
+/*                                                                           */
+/*  To save memory, the point numbers are written over the shell markers     */
+/*  after the points are written to a file.                                  */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writenodes(pointlist, pointattriblist, pointmarkerlist)
+REAL **pointlist;
+REAL **pointattriblist;
+int **pointmarkerlist;
+
+#else /* not TRILIBRARY */
+
+void writenodes(nodefilename, argc, argv)
+char *nodefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  REAL *plist;
+  REAL *palist;
+  int *pmlist;
+  int coordindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  point pointloop;
+  int pointnumber;
+  int i;
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing points.\n");
+  }
+  /* Allocate memory for output points if necessary. */
+  if (*pointlist == (REAL *) NULL) {
+    *pointlist = (REAL *) malloc(points.items * 2 * sizeof(REAL));
+    if (*pointlist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output point attributes if necessary. */
+  if ((nextras > 0) && (*pointattriblist == (REAL *) NULL)) {
+    *pointattriblist = (REAL *) malloc(points.items * nextras * sizeof(REAL));
+    if (*pointattriblist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output point markers if necessary. */
+  if (!nobound && (*pointmarkerlist == (int *) NULL)) {
+    *pointmarkerlist = (int *) malloc(points.items * sizeof(int));
+    if (*pointmarkerlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  plist = *pointlist;
+  palist = *pointattriblist;
+  pmlist = *pointmarkerlist;
+  coordindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", nodefilename);
+  }
+  outfile = fopen(nodefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", nodefilename);
+    exit(1);
+  }
+  /* Number of points, number of dimensions, number of point attributes, */
+  /*   and number of boundary markers (zero or one).                     */
+  fprintf(outfile, "%ld  %d  %d  %d\n", points.items, mesh_dim, nextras,
+          1 - nobound);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  pointnumber = firstnumber;
+  while (pointloop != (point) NULL) {
+#ifdef TRILIBRARY
+    /* X and y coordinates. */
+    plist[coordindex++] = pointloop[0];
+    plist[coordindex++] = pointloop[1];
+    /* Point attributes. */
+    for (i = 0; i < nextras; i++) {
+      palist[attribindex++] = pointloop[2 + i];
+    }
+    if (!nobound) {
+      /* Copy the boundary marker. */
+      pmlist[pointnumber - firstnumber] = pointmark(pointloop);
+    }
+#else /* not TRILIBRARY */
+    /* Point number, x and y coordinates. */
+    fprintf(outfile, "%4d    %.17g  %.17g", pointnumber, pointloop[0],
+            pointloop[1]);
+    for (i = 0; i < nextras; i++) {
+      /* Write an attribute. */
+      fprintf(outfile, "  %.17g", pointloop[i + 2]);
+    }
+    if (nobound) {
+      fprintf(outfile, "\n");
+    } else {
+      /* Write the boundary marker. */
+      fprintf(outfile, "    %d\n", pointmark(pointloop));
+    }
+#endif /* not TRILIBRARY */
+
+    setpointmark(pointloop, pointnumber);
+    pointloop = pointtraverse();
+    pointnumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  numbernodes()   Number the points.                                       */
+/*                                                                           */
+/*  Each point is assigned a marker equal to its number.                     */
+/*                                                                           */
+/*  Used when writenodes() is not called because no .node file is written.   */
+/*                                                                           */
+/*****************************************************************************/
+
+void numbernodes()
+{
+  point pointloop;
+  int pointnumber;
+
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  pointnumber = firstnumber;
+  while (pointloop != (point) NULL) {
+    setpointmark(pointloop, pointnumber);
+    pointloop = pointtraverse();
+    pointnumber++;
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writeelements()   Write the triangles to an .ele file.                   */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writeelements(trianglelist, triangleattriblist)
+int **trianglelist;
+REAL **triangleattriblist;
+
+#else /* not TRILIBRARY */
+
+void writeelements(elefilename, argc, argv)
+char *elefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *tlist;
+  REAL *talist;
+  int pointindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop;
+  point p1, p2, p3;
+  point mid1, mid2, mid3;
+  int elementnumber;
+  int i;
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing triangles.\n");
+  }
+  /* Allocate memory for output triangles if necessary. */
+  if (*trianglelist == (int *) NULL) {
+    *trianglelist = (int *) malloc(triangles.items *
+                               ((order + 1) * (order + 2) / 2) * sizeof(int));
+    if (*trianglelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output triangle attributes if necessary. */
+  if ((eextras > 0) && (*triangleattriblist == (REAL *) NULL)) {
+    *triangleattriblist = (REAL *) malloc(triangles.items * eextras *
+                                          sizeof(REAL));
+    if (*triangleattriblist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  tlist = *trianglelist;
+  talist = *triangleattriblist;
+  pointindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", elefilename);
+  }
+  outfile = fopen(elefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", elefilename);
+    exit(1);
+  }
+  /* Number of triangles, points per triangle, attributes per triangle. */
+  fprintf(outfile, "%ld  %d  %d\n", triangles.items,
+          (order + 1) * (order + 2) / 2, eextras);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, p1);
+    dest(triangleloop, p2);
+    apex(triangleloop, p3);
+    if (order == 1) {
+#ifdef TRILIBRARY
+      tlist[pointindex++] = pointmark(p1);
+      tlist[pointindex++] = pointmark(p2);
+      tlist[pointindex++] = pointmark(p3);
+#else /* not TRILIBRARY */
+      /* Triangle number, indices for three points. */
+      fprintf(outfile, "%4d    %4d  %4d  %4d", elementnumber,
+              pointmark(p1), pointmark(p2), pointmark(p3));
+#endif /* not TRILIBRARY */
+    } else {
+      mid1 = (point) triangleloop.tri[highorderindex + 1];
+      mid2 = (point) triangleloop.tri[highorderindex + 2];
+      mid3 = (point) triangleloop.tri[highorderindex];
+#ifdef TRILIBRARY
+      tlist[pointindex++] = pointmark(p1);
+      tlist[pointindex++] = pointmark(p2);
+      tlist[pointindex++] = pointmark(p3);
+      tlist[pointindex++] = pointmark(mid1);
+      tlist[pointindex++] = pointmark(mid2);
+      tlist[pointindex++] = pointmark(mid3);
+#else /* not TRILIBRARY */
+      /* Triangle number, indices for six points. */
+      fprintf(outfile, "%4d    %4d  %4d  %4d  %4d  %4d  %4d", elementnumber,
+              pointmark(p1), pointmark(p2), pointmark(p3), pointmark(mid1),
+              pointmark(mid2), pointmark(mid3));
+#endif /* not TRILIBRARY */
+    }
+
+#ifdef TRILIBRARY
+    for (i = 0; i < eextras; i++) {
+      talist[attribindex++] = elemattribute(triangleloop, i);
+    }
+#else /* not TRILIBRARY */
+    for (i = 0; i < eextras; i++) {
+      fprintf(outfile, "  %.17g", elemattribute(triangleloop, i));
+    }
+    fprintf(outfile, "\n");
+#endif /* not TRILIBRARY */
+
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writepoly()   Write the segments and holes to a .poly file.              */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writepoly(segmentlist, segmentmarkerlist)
+int **segmentlist;
+int **segmentmarkerlist;
+
+#else /* not TRILIBRARY */
+
+void writepoly(polyfilename, holelist, holes, regionlist, regions, argc, argv)
+char *polyfilename;
+REAL *holelist;
+int holes;
+REAL *regionlist;
+int regions;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *slist;
+  int *smlist;
+  int index;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+  int i;
+#endif /* not TRILIBRARY */
+  struct edge shelleloop;
+  point endpoint1, endpoint2;
+  int shellenumber;
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing segments.\n");
+  }
+  /* Allocate memory for output segments if necessary. */
+  if (*segmentlist == (int *) NULL) {
+    *segmentlist = (int *) malloc(shelles.items * 2 * sizeof(int));
+    if (*segmentlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for output segment markers if necessary. */
+  if (!nobound && (*segmentmarkerlist == (int *) NULL)) {
+    *segmentmarkerlist = (int *) malloc(shelles.items * sizeof(int));
+    if (*segmentmarkerlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  slist = *segmentlist;
+  smlist = *segmentmarkerlist;
+  index = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", polyfilename);
+  }
+  outfile = fopen(polyfilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", polyfilename);
+    exit(1);
+  }
+  /* The zero indicates that the points are in a separate .node file. */
+  /*   Followed by number of dimensions, number of point attributes,  */
+  /*   and number of boundary markers (zero or one).                  */
+  fprintf(outfile, "%d  %d  %d  %d\n", 0, mesh_dim, nextras, 1 - nobound);
+  /* Number of segments, number of boundary markers (zero or one). */
+  fprintf(outfile, "%ld  %d\n", shelles.items, 1 - nobound);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&shelles);
+  shelleloop.sh = shelletraverse();
+  shelleloop.shorient = 0;
+  shellenumber = firstnumber;
+  while (shelleloop.sh != (shelle *) NULL) {
+    sorg(shelleloop, endpoint1);
+    sdest(shelleloop, endpoint2);
+#ifdef TRILIBRARY
+    /* Copy indices of the segment's two endpoints. */
+    slist[index++] = pointmark(endpoint1);
+    slist[index++] = pointmark(endpoint2);
+    if (!nobound) {
+      /* Copy the boundary marker. */
+      smlist[shellenumber - firstnumber] = mark(shelleloop);
+    }
+#else /* not TRILIBRARY */
+    /* Segment number, indices of its two endpoints, and possibly a marker. */
+    if (nobound) {
+      fprintf(outfile, "%4d    %4d  %4d\n", shellenumber,
+              pointmark(endpoint1), pointmark(endpoint2));
+    } else {
+      fprintf(outfile, "%4d    %4d  %4d    %4d\n", shellenumber,
+              pointmark(endpoint1), pointmark(endpoint2), mark(shelleloop));
+    }
+#endif /* not TRILIBRARY */
+
+    shelleloop.sh = shelletraverse();
+    shellenumber++;
+  }
+
+#ifndef TRILIBRARY
+#ifndef CDT_ONLY
+  fprintf(outfile, "%d\n", holes);
+  if (holes > 0) {
+    for (i = 0; i < holes; i++) {
+      /* Hole number, x and y coordinates. */
+      fprintf(outfile, "%4d   %.17g  %.17g\n", firstnumber + i,
+              holelist[2 * i], holelist[2 * i + 1]);
+    }
+  }
+  if (regions > 0) {
+    fprintf(outfile, "%d\n", regions);
+    for (i = 0; i < regions; i++) {
+      /* Region number, x and y coordinates, attribute, maximum area. */
+      fprintf(outfile, "%4d   %.17g  %.17g  %.17g  %.17g\n", firstnumber + i,
+              regionlist[4 * i], regionlist[4 * i + 1],
+              regionlist[4 * i + 2], regionlist[4 * i + 3]);
+    }
+  }
+#endif /* not CDT_ONLY */
+
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writeedges()   Write the edges to a .edge file.                          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writeedges(edgelist, edgemarkerlist)
+int **edgelist;
+int **edgemarkerlist;
+
+#else /* not TRILIBRARY */
+
+void writeedges(edgefilename, argc, argv)
+char *edgefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *elist;
+  int *emlist;
+  int index;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop, trisym;
+  struct edge checkmark;
+  point p1, p2;
+  int edgenumber;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+  shelle sptr;                      /* Temporary variable used by tspivot(). */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing edges.\n");
+  }
+  /* Allocate memory for edges if necessary. */
+  if (*edgelist == (int *) NULL) {
+    *edgelist = (int *) malloc(edges * 2 * sizeof(int));
+    if (*edgelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for edge markers if necessary. */
+  if (!nobound && (*edgemarkerlist == (int *) NULL)) {
+    *edgemarkerlist = (int *) malloc(edges * sizeof(int));
+    if (*edgemarkerlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  elist = *edgelist;
+  emlist = *edgemarkerlist;
+  index = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", edgefilename);
+  }
+  outfile = fopen(edgefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", edgefilename);
+    exit(1);
+  }
+  /* Number of edges, number of boundary markers (zero or one). */
+  fprintf(outfile, "%ld  %d\n", edges, 1 - nobound);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  edgenumber = firstnumber;
+  /* To loop over the set of edges, loop over all triangles, and look at   */
+  /*   the three edges of each triangle.  If there isn't another triangle  */
+  /*   adjacent to the edge, operate on the edge.  If there is another     */
+  /*   adjacent triangle, operate on the edge only if the current triangle */
+  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
+  /*   considered only once.                                               */
+  while (triangleloop.tri != (triangle *) NULL) {
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      sym(triangleloop, trisym);
+      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
+        org(triangleloop, p1);
+        dest(triangleloop, p2);
+#ifdef TRILIBRARY
+        elist[index++] = pointmark(p1);
+        elist[index++] = pointmark(p2);
+#endif /* TRILIBRARY */
+        if (nobound) {
+#ifndef TRILIBRARY
+          /* Edge number, indices of two endpoints. */
+          fprintf(outfile, "%4d   %d  %d\n", edgenumber,
+                  pointmark(p1), pointmark(p2));
+#endif /* not TRILIBRARY */
+        } else {
+          /* Edge number, indices of two endpoints, and a boundary marker. */
+          /*   If there's no shell edge, the boundary marker is zero.      */
+          if (useshelles) {
+            tspivot(triangleloop, checkmark);
+            if (checkmark.sh == dummysh) {
+#ifdef TRILIBRARY
+              emlist[edgenumber - firstnumber] = 0;
+#else /* not TRILIBRARY */
+              fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
+                      pointmark(p1), pointmark(p2), 0);
+#endif /* not TRILIBRARY */
+            } else {
+#ifdef TRILIBRARY
+              emlist[edgenumber - firstnumber] = mark(checkmark);
+#else /* not TRILIBRARY */
+              fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
+                      pointmark(p1), pointmark(p2), mark(checkmark));
+#endif /* not TRILIBRARY */
+            }
+          } else {
+#ifdef TRILIBRARY
+            emlist[edgenumber - firstnumber] = trisym.tri == dummytri;
+#else /* not TRILIBRARY */
+            fprintf(outfile, "%4d   %d  %d  %d\n", edgenumber,
+                    pointmark(p1), pointmark(p2), trisym.tri == dummytri);
+#endif /* not TRILIBRARY */
+          }
+        }
+        edgenumber++;
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writevoronoi()   Write the Voronoi diagram to a .v.node and .v.edge      */
+/*                   file.                                                   */
+/*                                                                           */
+/*  The Voronoi diagram is the geometric dual of the Delaunay triangulation. */
+/*  Hence, the Voronoi vertices are listed by traversing the Delaunay        */
+/*  triangles, and the Voronoi edges are listed by traversing the Delaunay   */
+/*  edges.                                                                   */
+/*                                                                           */
+/*  WARNING:  In order to assign numbers to the Voronoi vertices, this       */
+/*  procedure messes up the shell edges or the extra nodes of every          */
+/*  element.  Hence, you should call this procedure last.                    */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void writevoronoi(vpointlist, vpointattriblist, vpointmarkerlist, vedgelist,
+                  vedgemarkerlist, vnormlist)
+REAL **vpointlist;
+REAL **vpointattriblist;
+int **vpointmarkerlist;
+int **vedgelist;
+int **vedgemarkerlist;
+REAL **vnormlist;
+
+#else /* not TRILIBRARY */
+
+void writevoronoi(vnodefilename, vedgefilename, argc, argv)
+char *vnodefilename;
+char *vedgefilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  REAL *plist;
+  REAL *palist;
+  int *elist;
+  REAL *normlist;
+  int coordindex;
+  int attribindex;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop, trisym;
+  point torg, tdest, tapex;
+  REAL circumcenter[2];
+  REAL xi, eta;
+  int vnodenumber, vedgenumber;
+  int p1, p2;
+  int i;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing Voronoi vertices.\n");
+  }
+  /* Allocate memory for Voronoi vertices if necessary. */
+  if (*vpointlist == (REAL *) NULL) {
+    *vpointlist = (REAL *) malloc(triangles.items * 2 * sizeof(REAL));
+    if (*vpointlist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  /* Allocate memory for Voronoi vertex attributes if necessary. */
+  if (*vpointattriblist == (REAL *) NULL) {
+    *vpointattriblist = (REAL *) malloc(triangles.items * nextras *
+                                        sizeof(REAL));
+    if (*vpointattriblist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  *vpointmarkerlist = (int *) NULL;
+  plist = *vpointlist;
+  palist = *vpointattriblist;
+  coordindex = 0;
+  attribindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", vnodefilename);
+  }
+  outfile = fopen(vnodefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", vnodefilename);
+    exit(1);
+  }
+  /* Number of triangles, two dimensions, number of point attributes, */
+  /*   zero markers.                                                  */
+  fprintf(outfile, "%ld  %d  %d  %d\n", triangles.items, 2, nextras, 0);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  vnodenumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, torg);
+    dest(triangleloop, tdest);
+    apex(triangleloop, tapex);
+    findcircumcenter(torg, tdest, tapex, circumcenter, &xi, &eta);
+#ifdef TRILIBRARY
+    /* X and y coordinates. */
+    plist[coordindex++] = circumcenter[0];
+    plist[coordindex++] = circumcenter[1];
+    for (i = 2; i < 2 + nextras; i++) {
+      /* Interpolate the point attributes at the circumcenter. */
+      palist[attribindex++] = torg[i] + xi * (tdest[i] - torg[i])
+                                     + eta * (tapex[i] - torg[i]);
+    }
+#else /* not TRILIBRARY */
+    /* Voronoi vertex number, x and y coordinates. */
+    fprintf(outfile, "%4d    %.17g  %.17g", vnodenumber, circumcenter[0],
+            circumcenter[1]);
+    for (i = 2; i < 2 + nextras; i++) {
+      /* Interpolate the point attributes at the circumcenter. */
+      fprintf(outfile, "  %.17g", torg[i] + xi * (tdest[i] - torg[i])
+                                         + eta * (tapex[i] - torg[i]));
+    }
+    fprintf(outfile, "\n");
+#endif /* not TRILIBRARY */
+
+    * (int *) (triangleloop.tri + 6) = vnodenumber;
+    triangleloop.tri = triangletraverse();
+    vnodenumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing Voronoi edges.\n");
+  }
+  /* Allocate memory for output Voronoi edges if necessary. */
+  if (*vedgelist == (int *) NULL) {
+    *vedgelist = (int *) malloc(edges * 2 * sizeof(int));
+    if (*vedgelist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  *vedgemarkerlist = (int *) NULL;
+  /* Allocate memory for output Voronoi norms if necessary. */
+  if (*vnormlist == (REAL *) NULL) {
+    *vnormlist = (REAL *) malloc(edges * 2 * sizeof(REAL));
+    if (*vnormlist == (REAL *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  elist = *vedgelist;
+  normlist = *vnormlist;
+  coordindex = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", vedgefilename);
+  }
+  outfile = fopen(vedgefilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", vedgefilename);
+    exit(1);
+  }
+  /* Number of edges, zero boundary markers. */
+  fprintf(outfile, "%ld  %d\n", edges, 0);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  vedgenumber = firstnumber;
+  /* To loop over the set of edges, loop over all triangles, and look at   */
+  /*   the three edges of each triangle.  If there isn't another triangle  */
+  /*   adjacent to the edge, operate on the edge.  If there is another     */
+  /*   adjacent triangle, operate on the edge only if the current triangle */
+  /*   has a smaller pointer than its neighbor.  This way, each edge is    */
+  /*   considered only once.                                               */
+  while (triangleloop.tri != (triangle *) NULL) {
+    for (triangleloop.orient = 0; triangleloop.orient < 3;
+         triangleloop.orient++) {
+      sym(triangleloop, trisym);
+      if ((triangleloop.tri < trisym.tri) || (trisym.tri == dummytri)) {
+        /* Find the number of this triangle (and Voronoi vertex). */
+        p1 = * (int *) (triangleloop.tri + 6);
+        if (trisym.tri == dummytri) {
+          org(triangleloop, torg);
+          dest(triangleloop, tdest);
+#ifdef TRILIBRARY
+          /* Copy an infinite ray.  Index of one endpoint, and -1. */
+          elist[coordindex] = p1;
+          normlist[coordindex++] = tdest[1] - torg[1];
+          elist[coordindex] = -1;
+          normlist[coordindex++] = torg[0] - tdest[0];
+#else /* not TRILIBRARY */
+          /* Write an infinite ray.  Edge number, index of one endpoint, -1, */
+          /*   and x and y coordinates of a vector representing the          */
+          /*   direction of the ray.                                         */
+          fprintf(outfile, "%4d   %d  %d   %.17g  %.17g\n", vedgenumber,
+                  p1, -1, tdest[1] - torg[1], torg[0] - tdest[0]);
+#endif /* not TRILIBRARY */
+        } else {
+          /* Find the number of the adjacent triangle (and Voronoi vertex). */
+          p2 = * (int *) (trisym.tri + 6);
+          /* Finite edge.  Write indices of two endpoints. */
+#ifdef TRILIBRARY
+          elist[coordindex] = p1;
+          normlist[coordindex++] = 0.0;
+          elist[coordindex] = p2;
+          normlist[coordindex++] = 0.0;
+#else /* not TRILIBRARY */
+          fprintf(outfile, "%4d   %d  %d\n", vedgenumber, p1, p2);
+#endif /* not TRILIBRARY */
+        }
+        vedgenumber++;
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* not TRILIBRARY */
+}
+
+#ifdef TRILIBRARY
+
+void writeneighbors(neighborlist)
+int **neighborlist;
+
+#else /* not TRILIBRARY */
+
+void writeneighbors(neighborfilename, argc, argv)
+char *neighborfilename;
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+#ifdef TRILIBRARY
+  int *nlist;
+  int index;
+#else /* not TRILIBRARY */
+  FILE *outfile;
+#endif /* not TRILIBRARY */
+  struct triedge triangleloop, trisym;
+  int elementnumber;
+  int neighbor1, neighbor2, neighbor3;
+  triangle ptr;                         /* Temporary variable used by sym(). */
+
+#ifdef TRILIBRARY
+  if (!quiet) {
+    printf("Writing neighbors.\n");
+  }
+  /* Allocate memory for neighbors if necessary. */
+  if (*neighborlist == (int *) NULL) {
+    *neighborlist = (int *) malloc(triangles.items * 3 * sizeof(int));
+    if (*neighborlist == (int *) NULL) {
+      printf("Error:  Out of memory.\n");
+      exit(1);
+    }
+  }
+  nlist = *neighborlist;
+  index = 0;
+#else /* not TRILIBRARY */
+  if (!quiet) {
+    printf("Writing %s.\n", neighborfilename);
+  }
+  outfile = fopen(neighborfilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", neighborfilename);
+    exit(1);
+  }
+  /* Number of triangles, three edges per triangle. */
+  fprintf(outfile, "%ld  %d\n", triangles.items, 3);
+#endif /* not TRILIBRARY */
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    * (int *) (triangleloop.tri + 6) = elementnumber;
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+  * (int *) (dummytri + 6) = -1;
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  elementnumber = firstnumber;
+  while (triangleloop.tri != (triangle *) NULL) {
+    triangleloop.orient = 1;
+    sym(triangleloop, trisym);
+    neighbor1 = * (int *) (trisym.tri + 6);
+    triangleloop.orient = 2;
+    sym(triangleloop, trisym);
+    neighbor2 = * (int *) (trisym.tri + 6);
+    triangleloop.orient = 0;
+    sym(triangleloop, trisym);
+    neighbor3 = * (int *) (trisym.tri + 6);
+#ifdef TRILIBRARY
+    nlist[index++] = neighbor1;
+    nlist[index++] = neighbor2;
+    nlist[index++] = neighbor3;
+#else /* not TRILIBRARY */
+    /* Triangle number, neighboring triangle numbers. */
+    fprintf(outfile, "%4d    %d  %d  %d\n", elementnumber,
+            neighbor1, neighbor2, neighbor3);
+#endif /* not TRILIBRARY */
+
+    triangleloop.tri = triangletraverse();
+    elementnumber++;
+  }
+
+#ifndef TRILIBRARY
+  finishfile(outfile, argc, argv);
+#endif /* TRILIBRARY */
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  writeoff()   Write the triangulation to an .off file.                    */
+/*                                                                           */
+/*  OFF stands for the Object File Format, a format used by the Geometry     */
+/*  Center's Geomview package.                                               */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifndef TRILIBRARY
+
+void writeoff(offfilename, argc, argv)
+char *offfilename;
+int argc;
+char **argv;
+{
+  FILE *outfile;
+  struct triedge triangleloop;
+  point pointloop;
+  point p1, p2, p3;
+
+  if (!quiet) {
+    printf("Writing %s.\n", offfilename);
+  }
+  outfile = fopen(offfilename, "w");
+  if (outfile == (FILE *) NULL) {
+    printf("  Error:  Cannot create file %s.\n", offfilename);
+    exit(1);
+  }
+  /* Number of points, triangles, and edges. */
+  fprintf(outfile, "OFF\n%ld  %ld  %ld\n", points.items, triangles.items,
+          edges);
+
+  /* Write the points. */
+  traversalinit(&points);
+  pointloop = pointtraverse();
+  while (pointloop != (point) NULL) {
+    /* The "0.0" is here because the OFF format uses 3D coordinates. */
+    fprintf(outfile, " %.17g  %.17g  %.17g\n", pointloop[0],
+            pointloop[1], 0.0);
+    pointloop = pointtraverse();
+  }
+
+  /* Write the triangles. */
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, p1);
+    dest(triangleloop, p2);
+    apex(triangleloop, p3);
+    /* The "3" means a three-vertex polygon. */
+    fprintf(outfile, " 3   %4d  %4d  %4d\n", pointmark(p1) - 1,
+            pointmark(p2) - 1, pointmark(p3) - 1);
+    triangleloop.tri = triangletraverse();
+  }
+  finishfile(outfile, argc, argv);
+}
+
+#endif /* not TRILIBRARY */
+
+/**                                                                         **/
+/**                                                                         **/
+/********* File I/O routines end here                                *********/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  quality_statistics()   Print statistics about the quality of the mesh.   */
+/*                                                                           */
+/*****************************************************************************/
+
+void quality_statistics()
+{
+  struct triedge triangleloop;
+  point p[3];
+  REAL cossquaretable[8];
+  REAL ratiotable[16];
+  REAL dx[3], dy[3];
+  REAL edgelength[3];
+  REAL dotproduct;
+  REAL cossquare;
+  REAL triarea;
+  REAL shortest, longest;
+  REAL trilongest2;
+  REAL smallestarea, biggestarea;
+  REAL triminaltitude2;
+  REAL minaltitude;
+  REAL triaspect2;
+  REAL worstaspect;
+  REAL smallestangle, biggestangle;
+  REAL radconst, degconst;
+  int angletable[18];
+  int aspecttable[16];
+  int aspectindex;
+  int tendegree;
+  int acutebiggest;
+  int i, ii, j, k;
+
+  printf("Mesh quality statistics:\n\n");
+  radconst = (REAL)(PI / 18.0);
+  degconst = (REAL)(180.0 / PI);
+  for (i = 0; i < 8; i++) {
+    cossquaretable[i] = (REAL)(cos(radconst * (REAL) (i + 1)));
+    cossquaretable[i] = cossquaretable[i] * cossquaretable[i];
+  }
+  for (i = 0; i < 18; i++) {
+    angletable[i] = 0;
+  }
+
+  ratiotable[0]  =      1.5;      ratiotable[1]  =     2.0;
+  ratiotable[2]  =      2.5;      ratiotable[3]  =     3.0;
+  ratiotable[4]  =      4.0;      ratiotable[5]  =     6.0;
+  ratiotable[6]  =     10.0;      ratiotable[7]  =    15.0;
+  ratiotable[8]  =     25.0;      ratiotable[9]  =    50.0;
+  ratiotable[10] =    100.0;      ratiotable[11] =   300.0;
+  ratiotable[12] =   1000.0;      ratiotable[13] = 10000.0;
+  ratiotable[14] = 100000.0;      ratiotable[15] =     0.0;
+  for (i = 0; i < 16; i++) {
+    aspecttable[i] = 0;
+  }
+
+  worstaspect = 0.0;
+  minaltitude = xmax - xmin + ymax - ymin;
+  minaltitude = minaltitude * minaltitude;
+  shortest = minaltitude;
+  longest = 0.0;
+  smallestarea = minaltitude;
+  biggestarea = 0.0;
+  worstaspect = 0.0;
+  smallestangle = 0.0;
+  biggestangle = 2.0;
+  acutebiggest = 1;
+
+  traversalinit(&triangles);
+  triangleloop.tri = triangletraverse();
+  triangleloop.orient = 0;
+  while (triangleloop.tri != (triangle *) NULL) {
+    org(triangleloop, p[0]);
+    dest(triangleloop, p[1]);
+    apex(triangleloop, p[2]);
+    trilongest2 = 0.0;
+
+    for (i = 0; i < 3; i++) {
+      j = plus1mod3[i];
+      k = minus1mod3[i];
+      dx[i] = p[j][0] - p[k][0];
+      dy[i] = p[j][1] - p[k][1];
+      edgelength[i] = dx[i] * dx[i] + dy[i] * dy[i];
+      if (edgelength[i] > trilongest2) {
+        trilongest2 = edgelength[i];
+      }
+      if (edgelength[i] > longest) {
+        longest = edgelength[i];
+      }
+      if (edgelength[i] < shortest) {
+        shortest = edgelength[i];
+      }
+    }
+
+    triarea = counterclockwise(p[0], p[1], p[2]);
+    if (triarea < smallestarea) {
+      smallestarea = triarea;
+    }
+    if (triarea > biggestarea) {
+      biggestarea = triarea;
+    }
+    triminaltitude2 = triarea * triarea / trilongest2;
+    if (triminaltitude2 < minaltitude) {
+      minaltitude = triminaltitude2;
+    }
+    triaspect2 = trilongest2 / triminaltitude2;
+    if (triaspect2 > worstaspect) {
+      worstaspect = triaspect2;
+    }
+    aspectindex = 0;
+    while ((triaspect2 > ratiotable[aspectindex] * ratiotable[aspectindex])
+           && (aspectindex < 15)) {
+      aspectindex++;
+    }
+    aspecttable[aspectindex]++;
+
+    for (i = 0; i < 3; i++) {
+      j = plus1mod3[i];
+      k = minus1mod3[i];
+      dotproduct = dx[j] * dx[k] + dy[j] * dy[k];
+      cossquare = dotproduct * dotproduct / (edgelength[j] * edgelength[k]);
+      tendegree = 8;
+      for (ii = 7; ii >= 0; ii--) {
+        if (cossquare > cossquaretable[ii]) {
+          tendegree = ii;
+        }
+      }
+      if (dotproduct <= 0.0) {
+        angletable[tendegree]++;
+        if (cossquare > smallestangle) {
+          smallestangle = cossquare;
+        }
+        if (acutebiggest && (cossquare < biggestangle)) {
+          biggestangle = cossquare;
+        }
+      } else {
+        angletable[17 - tendegree]++;
+        if (acutebiggest || (cossquare > biggestangle)) {
+          biggestangle = cossquare;
+          acutebiggest = 0;
+        }
+      }
+    }
+    triangleloop.tri = triangletraverse();
+  }
+
+  shortest = (REAL)sqrt(shortest);
+  longest = (REAL)sqrt(longest);
+  minaltitude = (REAL)sqrt(minaltitude);
+  worstaspect = (REAL)sqrt(worstaspect);
+  smallestarea *= 2.0;
+  biggestarea *= 2.0;
+  if (smallestangle >= 1.0) {
+    smallestangle = 0.0;
+  } else {
+    smallestangle = (REAL)(degconst * acos(sqrt(smallestangle)));
+  }
+  if (biggestangle >= 1.0) {
+    biggestangle = 180.0;
+  } else {
+    if (acutebiggest) {
+      biggestangle = (REAL)(degconst * acos(sqrt(biggestangle)));
+    } else {
+      biggestangle = (REAL)(180.0 - degconst * acos(sqrt(biggestangle)));
+    }
+  }
+
+  printf("  Smallest area: %16.5g   |  Largest area: %16.5g\n",
+         smallestarea, biggestarea);
+  printf("  Shortest edge: %16.5g   |  Longest edge: %16.5g\n",
+         shortest, longest);
+  printf("  Shortest altitude: %12.5g   |  Largest aspect ratio: %8.5g\n\n",
+         minaltitude, worstaspect);
+  printf("  Aspect ratio histogram:\n");
+  printf("  1.1547 - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
+         ratiotable[0], aspecttable[0], ratiotable[7], ratiotable[8],
+         aspecttable[8]);
+  for (i = 1; i < 7; i++) {
+    printf("  %6.6g - %-6.6g    :  %8d    | %6.6g - %-6.6g     :  %8d\n",
+           ratiotable[i - 1], ratiotable[i], aspecttable[i],
+           ratiotable[i + 7], ratiotable[i + 8], aspecttable[i + 8]);
+  }
+  printf("  %6.6g - %-6.6g    :  %8d    | %6.6g -            :  %8d\n",
+         ratiotable[6], ratiotable[7], aspecttable[7], ratiotable[14],
+         aspecttable[15]);
+  printf(
+"  (Triangle aspect ratio is longest edge divided by shortest altitude)\n\n");
+  printf("  Smallest angle: %15.5g   |  Largest angle: %15.5g\n\n",
+         smallestangle, biggestangle);
+  printf("  Angle histogram:\n");
+  for (i = 0; i < 9; i++) {
+    printf("    %3d - %3d degrees:  %8d    |    %3d - %3d degrees:  %8d\n",
+           i * 10, i * 10 + 10, angletable[i],
+           i * 10 + 90, i * 10 + 100, angletable[i + 9]);
+  }
+  printf("\n");
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  statistics()   Print all sorts of cool facts.                            */
+/*                                                                           */
+/*****************************************************************************/
+
+void statistics()
+{
+  printf("\nStatistics:\n\n");
+  printf("  Input points: %d\n", inpoints);
+  if (refine) {
+    printf("  Input triangles: %d\n", inelements);
+  }
+  if (poly) {
+    printf("  Input segments: %d\n", insegments);
+    if (!refine) {
+      printf("  Input holes: %d\n", holes);
+    }
+  }
+
+  printf("\n  Mesh points: %ld\n", points.items);
+  printf("  Mesh triangles: %ld\n", triangles.items);
+  printf("  Mesh edges: %ld\n", edges);
+  if (poly || refine) {
+    printf("  Mesh boundary edges: %ld\n", hullsize);
+    printf("  Mesh segments: %ld\n\n", shelles.items);
+  } else {
+    printf("  Mesh convex hull edges: %ld\n\n", hullsize);
+  }
+  if (verbose) {
+    quality_statistics();
+    printf("Memory allocation statistics:\n\n");
+    printf("  Maximum number of points: %ld\n", points.maxitems);
+    printf("  Maximum number of triangles: %ld\n", triangles.maxitems);
+    if (shelles.maxitems > 0) {
+      printf("  Maximum number of segments: %ld\n", shelles.maxitems);
+    }
+    if (viri.maxitems > 0) {
+      printf("  Maximum number of viri: %ld\n", viri.maxitems);
+    }
+    if (badsegments.maxitems > 0) {
+      printf("  Maximum number of encroached segments: %ld\n",
+             badsegments.maxitems);
+    }
+    if (badtriangles.maxitems > 0) {
+      printf("  Maximum number of bad triangles: %ld\n",
+             badtriangles.maxitems);
+    }
+    if (splaynodes.maxitems > 0) {
+      printf("  Maximum number of splay tree nodes: %ld\n",
+             splaynodes.maxitems);
+    }
+    printf("  Approximate heap memory use (bytes): %ld\n\n",
+           points.maxitems * points.itembytes
+           + triangles.maxitems * triangles.itembytes
+           + shelles.maxitems * shelles.itembytes
+           + viri.maxitems * viri.itembytes
+           + badsegments.maxitems * badsegments.itembytes
+           + badtriangles.maxitems * badtriangles.itembytes
+           + splaynodes.maxitems * splaynodes.itembytes);
+
+    printf("Algorithmic statistics:\n\n");
+    printf("  Number of incircle tests: %ld\n", incirclecount);
+    printf("  Number of orientation tests: %ld\n", counterclockcount);
+    if (hyperbolacount > 0) {
+      printf("  Number of right-of-hyperbola tests: %ld\n",
+             hyperbolacount);
+    }
+    if (circumcentercount > 0) {
+      printf("  Number of circumcenter computations: %ld\n",
+             circumcentercount);
+    }
+    if (circletopcount > 0) {
+      printf("  Number of circle top computations: %ld\n",
+             circletopcount);
+    }
+    printf("\n");
+  }
+}
+
+/*****************************************************************************/
+/*                                                                           */
+/*  main() or triangulate()   Gosh, do everything.                           */
+/*                                                                           */
+/*  The sequence is roughly as follows.  Many of these steps can be skipped, */
+/*  depending on the command line switches.                                  */
+/*                                                                           */
+/*  - Initialize constants and parse the command line.                       */
+/*  - Read the points from a file and either                                 */
+/*    - triangulate them (no -r), or                                         */
+/*    - read an old mesh from files and reconstruct it (-r).                 */
+/*  - Insert the PSLG segments (-p), and possibly segments on the convex     */
+/*      hull (-c).                                                           */
+/*  - Read the holes (-p), regional attributes (-pA), and regional area      */
+/*      constraints (-pa).  Carve the holes and concavities, and spread the  */
+/*      regional attributes and area constraints.                            */
+/*  - Enforce the constraints on minimum angle (-q) and maximum area (-a).   */
+/*      Also enforce the conforming Delaunay property (-q and -a).           */
+/*  - Compute the number of edges in the resulting mesh.                     */
+/*  - Promote the mesh's linear triangles to higher order elements (-o).     */
+/*  - Write the output files and print the statistics.                       */
+/*  - Check the consistency and Delaunay property of the mesh (-C).          */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef TRILIBRARY
+
+void triangulate(triswitches, in, out, vorout)
+char *triswitches;
+struct triangulateio *in;
+struct triangulateio *out;
+struct triangulateio *vorout;
+
+#else /* not TRILIBRARY */
+
+int main(argc, argv)
+int argc;
+char **argv;
+
+#endif /* not TRILIBRARY */
+
+{
+  REAL *holearray;                                        /* Array of holes. */
+  REAL *regionarray;   /* Array of regional attributes and area constraints. */
+#ifndef TRILIBRARY
+  FILE *polyfile;
+#endif /* not TRILIBRARY */
+#ifndef NO_TIMER
+  /* Variables for timing the performance of Triangle.  The types are */
+  /*   defined in sys/time.h.                                         */
+  struct timeval tv0, tv1, tv2, tv3, tv4, tv5, tv6;
+  struct timezone tz;
+#endif /* NO_TIMER */
+
+#ifndef NO_TIMER
+  gettimeofday(&tv0, &tz);
+#endif /* NO_TIMER */
+
+  triangleinit();
+#ifdef TRILIBRARY
+  parsecommandline(1, &triswitches);
+#else /* not TRILIBRARY */
+  parsecommandline(argc, argv);
+#endif /* not TRILIBRARY */
+
+#ifdef TRILIBRARY
+  transfernodes(in->pointlist, in->pointattributelist, in->pointmarkerlist,
+                in->numberofpoints, in->numberofpointattributes);
+#else /* not TRILIBRARY */
+  readnodes(innodefilename, inpolyfilename, &polyfile);
+#endif /* not TRILIBRARY */
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv1, &tz);
+  }
+#endif /* NO_TIMER */
+
+#ifdef CDT_ONLY
+  hullsize = delaunay();                          /* Triangulate the points. */
+#else /* not CDT_ONLY */
+  if (refine) {
+    /* Read and reconstruct a mesh. */
+#ifdef TRILIBRARY
+    hullsize = reconstruct(in->trianglelist, in->triangleattributelist,
+                           in->trianglearealist, in->numberoftriangles,
+                           in->numberofcorners, in->numberoftriangleattributes,
+                           in->segmentlist, in->segmentmarkerlist,
+                           in->numberofsegments);
+#else /* not TRILIBRARY */
+    hullsize = reconstruct(inelefilename, areafilename, inpolyfilename,
+                           polyfile);
+#endif /* not TRILIBRARY */
+  } else {
+    hullsize = delaunay();                        /* Triangulate the points. */
+  }
+#endif /* not CDT_ONLY */
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv2, &tz);
+    if (refine) {
+      printf("Mesh reconstruction");
+    } else {
+      printf("Delaunay");
+    }
+    printf(" milliseconds:  %ld\n", 1000l * (tv2.tv_sec - tv1.tv_sec)
+           + (tv2.tv_usec - tv1.tv_usec) / 1000l);
+  }
+#endif /* NO_TIMER */
+
+  /* Ensure that no point can be mistaken for a triangular bounding */
+  /*   box point in insertsite().                                   */
+  infpoint1 = (point) NULL;
+  infpoint2 = (point) NULL;
+  infpoint3 = (point) NULL;
+
+  if (useshelles) {
+    checksegments = 1;                  /* Segments will be introduced next. */
+    if (!refine) {
+      /* Insert PSLG segments and/or convex hull segments. */
+#ifdef TRILIBRARY
+      insegments = formskeleton(in->segmentlist, in->segmentmarkerlist,
+                                in->numberofsegments);
+#else /* not TRILIBRARY */
+      insegments = formskeleton(polyfile, inpolyfilename);
+#endif /* not TRILIBRARY */
+    }
+  }
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv3, &tz);
+    if (useshelles && !refine) {
+      printf("Segment milliseconds:  %ld\n",
+             1000l * (tv3.tv_sec - tv2.tv_sec)
+             + (tv3.tv_usec - tv2.tv_usec) / 1000l);
+    }
+  }
+#endif /* NO_TIMER */
+
+  if (poly) {
+#ifdef TRILIBRARY
+    holearray = in->holelist;
+    holes = in->numberofholes;
+    regionarray = in->regionlist;
+    regions = in->numberofregions;
+#else /* not TRILIBRARY */
+    readholes(polyfile, inpolyfilename, &holearray, &holes,
+              &regionarray, &regions);
+#endif /* not TRILIBRARY */
+    if (!refine) {
+      /* Carve out holes and concavities. */
+      carveholes(holearray, holes, regionarray, regions);
+    }
+  } else {
+    /* Without a PSLG, there can be no holes or regional attributes   */
+    /*   or area constraints.  The following are set to zero to avoid */
+    /*   an accidental free() later.                                  */
+    holes = 0;
+    regions = 0;
+  }
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv4, &tz);
+    if (poly && !refine) {
+      printf("Hole milliseconds:  %ld\n", 1000l * (tv4.tv_sec - tv3.tv_sec)
+             + (tv4.tv_usec - tv3.tv_usec) / 1000l);
+    }
+  }
+#endif /* NO_TIMER */
+
+#ifndef CDT_ONLY
+  if (quality) {
+    enforcequality();                 /* Enforce angle and area constraints. */
+  }
+#endif /* not CDT_ONLY */
+
+#ifndef NO_TIMER
+  if (!quiet) {
+    gettimeofday(&tv5, &tz);
+#ifndef CDT_ONLY
+    if (quality) {
+      printf("Quality milliseconds:  %ld\n",
+             1000l * (tv5.tv_sec - tv4.tv_sec)
+             + (tv5.tv_usec - tv4.tv_usec) / 1000l);
+    }
+#endif /* not CDT_ONLY */
+  }
+#endif /* NO_TIMER */
+
+  /* Compute the number of edges. */
+  edges = (3l * triangles.items + hullsize) / 2l;
+
+  if (order > 1) {
+    highorder();             /* Promote elements to higher polynomial order. */
+  }
+  if (!quiet) {
+    printf("\n");
+  }
+
+#ifdef TRILIBRARY
+  out->numberofpoints = points.items;
+  out->numberofpointattributes = nextras;
+  out->numberoftriangles = triangles.items;
+  out->numberofcorners = (order + 1) * (order + 2) / 2;
+  out->numberoftriangleattributes = eextras;
+  out->numberofedges = edges;
+  if (useshelles) {
+    out->numberofsegments = shelles.items;
+  } else {
+    out->numberofsegments = hullsize;
+  }
+  if (vorout != (struct triangulateio *) NULL) {
+    vorout->numberofpoints = triangles.items;
+    vorout->numberofpointattributes = nextras;
+    vorout->numberofedges = edges;
+  }
+#endif /* TRILIBRARY */
+  /* If not using iteration numbers, don't write a .node file if one was */
+  /*   read, because the original one would be overwritten!              */
+  if (nonodewritten || (noiterationnum && readnodefile)) {
+    if (!quiet) {
+#ifdef TRILIBRARY
+      printf("NOT writing points.\n");
+#else /* not TRILIBRARY */
+      printf("NOT writing a .node file.\n");
+#endif /* not TRILIBRARY */
+    }
+    numbernodes();                 /* We must remember to number the points. */
+  } else {
+#ifdef TRILIBRARY
+    writenodes(&out->pointlist, &out->pointattributelist,
+               &out->pointmarkerlist);
+#else /* not TRILIBRARY */
+    writenodes(outnodefilename, argc, argv);      /* Numbers the points too. */
+#endif /* TRILIBRARY */
+  }
+  if (noelewritten) {
+    if (!quiet) {
+#ifdef TRILIBRARY
+      printf("NOT writing triangles.\n");
+#else /* not TRILIBRARY */
+      printf("NOT writing an .ele file.\n");
+#endif /* not TRILIBRARY */
+    }
+  } else {
+#ifdef TRILIBRARY
+    writeelements(&out->trianglelist, &out->triangleattributelist);
+#else /* not TRILIBRARY */
+    writeelements(outelefilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+  /* The -c switch (convex switch) causes a PSLG to be written */
+  /*   even if none was read.                                  */
+  if (poly || convex) {
+    /* If not using iteration numbers, don't overwrite the .poly file. */
+    if (nopolywritten || noiterationnum) {
+      if (!quiet) {
+#ifdef TRILIBRARY
+        printf("NOT writing segments.\n");
+#else /* not TRILIBRARY */
+        printf("NOT writing a .poly file.\n");
+#endif /* not TRILIBRARY */
+      }
+    } else {
+#ifdef TRILIBRARY
+      writepoly(&out->segmentlist, &out->segmentmarkerlist);
+      out->numberofholes = holes;
+      out->numberofregions = regions;
+      if (poly) {
+        out->holelist = in->holelist;
+        out->regionlist = in->regionlist;
+      } else {
+        out->holelist = (REAL *) NULL;
+        out->regionlist = (REAL *) NULL;
+      }
+#else /* not TRILIBRARY */
+      writepoly(outpolyfilename, holearray, holes, regionarray, regions,
+                argc, argv);
+#endif /* not TRILIBRARY */
+    }
+  }
+#ifndef TRILIBRARY
+#ifndef CDT_ONLY
+  if (regions > 0) {
+    free(regionarray);
+  }
+#endif /* not CDT_ONLY */
+  if (holes > 0) {
+    free(holearray);
+  }
+  if (geomview) {
+    writeoff(offfilename, argc, argv);
+  }
+#endif /* not TRILIBRARY */
+  if (edgesout) {
+#ifdef TRILIBRARY
+    writeedges(&out->edgelist, &out->edgemarkerlist);
+#else /* not TRILIBRARY */
+    writeedges(edgefilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+  if (voronoi) {
+#ifdef TRILIBRARY
+    writevoronoi(&vorout->pointlist, &vorout->pointattributelist,
+                 &vorout->pointmarkerlist, &vorout->edgelist,
+                 &vorout->edgemarkerlist, &vorout->normlist);
+#else /* not TRILIBRARY */
+    writevoronoi(vnodefilename, vedgefilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+  if (neighbors) {
+#ifdef TRILIBRARY
+    writeneighbors(&out->neighborlist);
+#else /* not TRILIBRARY */
+    writeneighbors(neighborfilename, argc, argv);
+#endif /* not TRILIBRARY */
+  }
+
+  if (!quiet) {
+#ifndef NO_TIMER
+    gettimeofday(&tv6, &tz);
+    printf("\nOutput milliseconds:  %ld\n",
+           1000l * (tv6.tv_sec - tv5.tv_sec)
+           + (tv6.tv_usec - tv5.tv_usec) / 1000l);
+    printf("Total running milliseconds:  %ld\n",
+           1000l * (tv6.tv_sec - tv0.tv_sec)
+           + (tv6.tv_usec - tv0.tv_usec) / 1000l);
+#endif /* NO_TIMER */
+
+    statistics();
+  }
+
+#ifndef REDUCED
+  if (docheck) {
+    checkmesh();
+    checkdelaunay();
+  }
+#endif /* not REDUCED */
+
+  triangledeinit();
+#ifndef TRILIBRARY
+  return 0;
+#endif /* not TRILIBRARY */
+}
diff --git a/contrib/gtkgensurf/triangle.h b/contrib/gtkgensurf/triangle.h
index 70cd6596..e7d87d01 100644
--- a/contrib/gtkgensurf/triangle.h
+++ b/contrib/gtkgensurf/triangle.h
@@ -1,288 +1,288 @@
-/*****************************************************************************/
-/*                                                                           */
-/*  (triangle.h)                                                             */
-/*                                                                           */
-/*  Include file for programs that call Triangle.                            */
-/*                                                                           */
-/*  Accompanies Triangle Version 1.3                                         */
-/*  July 19, 1996                                                            */
-/*                                                                           */
-/*  Copyright 1996                                                           */
-/*  Jonathan Richard Shewchuk                                                */
-/*  School of Computer Science                                               */
-/*  Carnegie Mellon University                                               */
-/*  5000 Forbes Avenue                                                       */
-/*  Pittsburgh, Pennsylvania  15213-3891                                     */
-/*  jrs@cs.cmu.edu                                                           */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  How to call Triangle from another program                                */
-/*                                                                           */
-/*                                                                           */
-/*  If you haven't read Triangle's instructions (run "triangle -h" to read   */
-/*  them), you won't understand what follows.                                */
-/*                                                                           */
-/*  Triangle must be compiled into an object file (triangle.o) with the      */
-/*  TRILIBRARY symbol defined (preferably by using the -DTRILIBRARY compiler */
-/*  switch).  The makefile included with Triangle will do this for you if    */
-/*  you run "make trilibrary".  The resulting object file can be called via  */
-/*  the procedure triangulate().                                             */
-/*                                                                           */
-/*  If the size of the object file is important to you, you may wish to      */
-/*  generate a reduced version of triangle.o.  The REDUCED symbol gets rid   */
-/*  of all features that are primarily of research interest.  Specifically,  */
-/*  the -DREDUCED switch eliminates Triangle's -i, -F, -s, and -C switches.  */
-/*  The CDT_ONLY symbol gets rid of all meshing algorithms above and beyond  */
-/*  constrained Delaunay triangulation.  Specifically, the -DCDT_ONLY switch */
-/*  eliminates Triangle's -r, -q, -a, -S, and -s switches.                   */
-/*                                                                           */
-/*  IMPORTANT:  These definitions (TRILIBRARY, REDUCED, CDT_ONLY) must be    */
-/*  made in the makefile or in triangle.c itself.  Putting these definitions */
-/*  in this file will not create the desired effect.                         */
-/*                                                                           */
-/*                                                                           */
-/*  The calling convention for triangulate() follows.                        */
-/*                                                                           */
-/*      void triangulate(triswitches, in, out, vorout)                       */
-/*      char *triswitches;                                                   */
-/*      struct triangulateio *in;                                            */
-/*      struct triangulateio *out;                                           */
-/*      struct triangulateio *vorout;                                        */
-/*                                                                           */
-/*  `triswitches' is a string containing the command line switches you wish  */
-/*  to invoke.  No initial dash is required.  Some suggestions:              */
-/*                                                                           */
-/*  - You'll probably find it convenient to use the `z' switch so that       */
-/*    points (and other items) are numbered from zero.  This simplifies      */
-/*    indexing, because the first item of any type always starts at index    */
-/*    [0] of the corresponding array, whether that item's number is zero or  */
-/*    one.                                                                   */
-/*  - You'll probably want to use the `Q' (quiet) switch in your final code, */
-/*    but you can take advantage of Triangle's printed output (including the */
-/*    `V' switch) while debugging.                                           */
-/*  - If you are not using the `q' or `a' switches, then the output points   */
-/*    will be identical to the input points, except possibly for the         */
-/*    boundary markers.  If you don't need the boundary markers, you should  */
-/*    use the `N' (no nodes output) switch to save memory.  (If you do need  */
-/*    boundary markers, but need to save memory, a good nasty trick is to    */
-/*    set out->pointlist equal to in->pointlist before calling triangulate(),*/
-/*    so that Triangle overwrites the input points with identical copies.)   */
-/*  - The `I' (no iteration numbers) and `g' (.off file output) switches     */
-/*    have no effect when Triangle is compiled with TRILIBRARY defined.      */
-/*                                                                           */
-/*  `in', `out', and `vorout' are descriptions of the input, the output,     */
-/*  and the Voronoi output.  If the `v' (Voronoi output) switch is not used, */
-/*  `vorout' may be NULL.  `in' and `out' may never be NULL.                 */
-/*                                                                           */
-/*  Certain fields of the input and output structures must be initialized,   */
-/*  as described below.                                                      */
-/*                                                                           */
-/*****************************************************************************/
-
-/*****************************************************************************/
-/*                                                                           */
-/*  The `triangulateio' structure.                                           */
-/*                                                                           */
-/*  Used to pass data into and out of the triangulate() procedure.           */
-/*                                                                           */
-/*                                                                           */
-/*  Arrays are used to store points, triangles, markers, and so forth.  In   */
-/*  all cases, the first item in any array is stored starting at index [0].  */
-/*  However, that item is item number `1' unless the `z' switch is used, in  */
-/*  which case it is item number `0'.  Hence, you may find it easier to      */
-/*  index points (and triangles in the neighbor list) if you use the `z'     */
-/*  switch.  Unless, of course, you're calling Triangle from a Fortran       */
-/*  program.                                                                 */
-/*                                                                           */
-/*  Description of fields (except the `numberof' fields, which are obvious): */
-/*                                                                           */
-/*  `pointlist':  An array of point coordinates.  The first point's x        */
-/*    coordinate is at index [0] and its y coordinate at index [1], followed */
-/*    by the coordinates of the remaining points.  Each point occupies two   */
-/*    REALs.                                                                 */
-/*  `pointattributelist':  An array of point attributes.  Each point's       */
-/*    attributes occupy `numberofpointattributes' REALs.                     */
-/*  `pointmarkerlist':  An array of point markers; one int per point.        */
-/*                                                                           */
-/*  `trianglelist':  An array of triangle corners.  The first triangle's     */
-/*    first corner is at index [0], followed by its other two corners in     */
-/*    counterclockwise order, followed by any other nodes if the triangle    */
-/*    represents a nonlinear element.  Each triangle occupies                */
-/*    `numberofcorners' ints.                                                */
-/*  `triangleattributelist':  An array of triangle attributes.  Each         */
-/*    triangle's attributes occupy `numberoftriangleattributes' REALs.       */
-/*  `trianglearealist':  An array of triangle area constraints; one REAL per */
-/*    triangle.  Input only.                                                 */
-/*  `neighborlist':  An array of triangle neighbors; three ints per          */
-/*    triangle.  Output only.                                                */
-/*                                                                           */
-/*  `segmentlist':  An array of segment endpoints.  The first segment's      */
-/*    endpoints are at indices [0] and [1], followed by the remaining        */
-/*    segments.  Two ints per segment.                                       */
-/*  `segmentmarkerlist':  An array of segment markers; one int per segment.  */
-/*                                                                           */
-/*  `holelist':  An array of holes.  The first hole's x and y coordinates    */
-/*    are at indices [0] and [1], followed by the remaining holes.  Two      */
-/*    REALs per hole.  Input only, although the pointer is copied to the     */
-/*    output structure for your convenience.                                 */
-/*                                                                           */
-/*  `regionlist':  An array of regional attributes and area constraints.     */
-/*    The first constraint's x and y coordinates are at indices [0] and [1], */
-/*    followed by the regional attribute and index [2], followed by the      */
-/*    maximum area at index [3], followed by the remaining area constraints. */
-/*    Four REALs per area constraint.  Note that each regional attribute is  */
-/*    used only if you select the `A' switch, and each area constraint is    */
-/*    used only if you select the `a' switch (with no number following), but */
-/*    omitting one of these switches does not change the memory layout.      */
-/*    Input only, although the pointer is copied to the output structure for */
-/*    your convenience.                                                      */
-/*                                                                           */
-/*  `edgelist':  An array of edge endpoints.  The first edge's endpoints are */
-/*    at indices [0] and [1], followed by the remaining edges.  Two ints per */
-/*    edge.  Output only.                                                    */
-/*  `edgemarkerlist':  An array of edge markers; one int per edge.  Output   */
-/*    only.                                                                  */
-/*  `normlist':  An array of normal vectors, used for infinite rays in       */
-/*    Voronoi diagrams.  The first normal vector's x and y magnitudes are    */
-/*    at indices [0] and [1], followed by the remaining vectors.  For each   */
-/*    finite edge in a Voronoi diagram, the normal vector written is the     */
-/*    zero vector.  Two REALs per edge.  Output only.                        */
-/*                                                                           */
-/*                                                                           */
-/*  Any input fields that Triangle will examine must be initialized.         */
-/*  Furthermore, for each output array that Triangle will write to, you      */
-/*  must either provide space by setting the appropriate pointer to point    */
-/*  to the space you want the data written to, or you must initialize the    */
-/*  pointer to NULL, which tells Triangle to allocate space for the results. */
-/*  The latter option is preferable, because Triangle always knows exactly   */
-/*  how much space to allocate.  The former option is provided mainly for    */
-/*  people who need to call Triangle from Fortran code, though it also makes */
-/*  possible some nasty space-saving tricks, like writing the output to the  */
-/*  same arrays as the input.                                                */
-/*                                                                           */
-/*  Triangle will not free() any input or output arrays, including those it  */
-/*  allocates itself; that's up to you.                                      */
-/*                                                                           */
-/*  Here's a guide to help you decide which fields you must initialize       */
-/*  before you call triangulate().                                           */
-/*                                                                           */
-/*  `in':                                                                    */
-/*                                                                           */
-/*    - `pointlist' must always point to a list of points; `numberofpoints'  */
-/*      and `numberofpointattributes' must be properly set.                  */
-/*      `pointmarkerlist' must either be set to NULL (in which case all      */
-/*      markers default to zero), or must point to a list of markers.  If    */
-/*      `numberofpointattributes' is not zero, `pointattributelist' must     */
-/*      point to a list of point attributes.                                 */
-/*    - If the `r' switch is used, `trianglelist' must point to a list of    */
-/*      triangles, and `numberoftriangles', `numberofcorners', and           */
-/*      `numberoftriangleattributes' must be properly set.  If               */
-/*      `numberoftriangleattributes' is not zero, `triangleattributelist'    */
-/*      must point to a list of triangle attributes.  If the `a' switch is   */
-/*      used (with no number following), `trianglearealist' must point to a  */
-/*      list of triangle area constraints.  `neighborlist' may be ignored.   */
-/*    - If the `p' switch is used, `segmentlist' must point to a list of     */
-/*      segments, `numberofsegments' must be properly set, and               */
-/*      `segmentmarkerlist' must either be set to NULL (in which case all    */
-/*      markers default to zero), or must point to a list of markers.        */
-/*    - If the `p' switch is used without the `r' switch, then               */
-/*      `numberofholes' and `numberofregions' must be properly set.  If      */
-/*      `numberofholes' is not zero, `holelist' must point to a list of      */
-/*      holes.  If `numberofregions' is not zero, `regionlist' must point to */
-/*      a list of region constraints.                                        */
-/*    - If the `p' switch is used, `holelist', `numberofholes',              */
-/*      `regionlist', and `numberofregions' is copied to `out'.  (You can    */
-/*      nonetheless get away with not initializing them if the `r' switch is */
-/*      used.)                                                               */
-/*    - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */
-/*      ignored.                                                             */
-/*                                                                           */
-/*  `out':                                                                   */
-/*                                                                           */
-/*    - `pointlist' must be initialized (NULL or pointing to memory) unless  */
-/*      the `N' switch is used.  `pointmarkerlist' must be initialized       */
-/*      unless the `N' or `B' switch is used.  If `N' is not used and        */
-/*      `in->numberofpointattributes' is not zero, `pointattributelist' must */
-/*      be initialized.                                                      */
-/*    - `trianglelist' must be initialized unless the `E' switch is used.    */
-/*      `neighborlist' must be initialized if the `n' switch is used.  If    */
-/*      the `E' switch is not used and (`in->numberofelementattributes' is   */
-/*      not zero or the `A' switch is used), `elementattributelist' must be  */
-/*      initialized.  `trianglearealist' may be ignored.                     */
-/*    - `segmentlist' must be initialized if the `p' or `c' switch is used,  */
-/*      and the `P' switch is not used.  `segmentmarkerlist' must also be    */
-/*      initialized under these circumstances unless the `B' switch is used. */
-/*    - `edgelist' must be initialized if the `e' switch is used.            */
-/*      `edgemarkerlist' must be initialized if the `e' switch is used and   */
-/*      the `B' switch is not.                                               */
-/*    - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/
-/*                                                                           */
-/*  `vorout' (only needed if `v' switch is used):                            */
-/*                                                                           */
-/*    - `pointlist' must be initialized.  If `in->numberofpointattributes'   */
-/*      is not zero, `pointattributelist' must be initialized.               */
-/*      `pointmarkerlist' may be ignored.                                    */
-/*    - `edgelist' and `normlist' must both be initialized.                  */
-/*      `edgemarkerlist' may be ignored.                                     */
-/*    - Everything else may be ignored.                                      */
-/*                                                                           */
-/*  After a call to triangulate(), the valid fields of `out' and `vorout'    */
-/*  will depend, in an obvious way, on the choice of switches used.  Note    */
-/*  that when the `p' switch is used, the pointers `holelist' and            */
-/*  `regionlist' are copied from `in' to `out', but no new space is          */
-/*  allocated; be careful that you don't free() the same array twice.  On    */
-/*  the other hand, Triangle will never copy the `pointlist' pointer (or any */
-/*  others); new space is allocated for `out->pointlist', or if the `N'      */
-/*  switch is used, `out->pointlist' remains uninitialized.                  */
-/*                                                                           */
-/*  All of the meaningful `numberof' fields will be properly set; for        */
-/*  instance, `numberofedges' will represent the number of edges in the      */
-/*  triangulation whether or not the edges were written.  If segments are    */
-/*  not used, `numberofsegments' will indicate the number of boundary edges. */
-/*                                                                           */
-/*****************************************************************************/
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-struct triangulateio {
-  REAL *pointlist;                                               /* In / out */
-  REAL *pointattributelist;                                      /* In / out */
-  int *pointmarkerlist;                                          /* In / out */
-  int numberofpoints;                                            /* In / out */
-  int numberofpointattributes;                                   /* In / out */
-
-  int *trianglelist;                                             /* In / out */
-  REAL *triangleattributelist;                                   /* In / out */
-  REAL *trianglearealist;                                         /* In only */
-  int *neighborlist;                                             /* Out only */
-  int numberoftriangles;                                         /* In / out */
-  int numberofcorners;                                           /* In / out */
-  int numberoftriangleattributes;                                /* In / out */
-
-  int *segmentlist;                                              /* In / out */
-  int *segmentmarkerlist;                                        /* In / out */
-  int numberofsegments;                                          /* In / out */
-
-  REAL *holelist;                        /* In / pointer to array copied out */
-  int numberofholes;                                      /* In / copied out */
-
-  REAL *regionlist;                      /* In / pointer to array copied out */
-  int numberofregions;                                    /* In / copied out */
-
-  int *edgelist;                                                 /* Out only */
-  int *edgemarkerlist;            /* Not used with Voronoi diagram; out only */
-  REAL *normlist;                /* Used only with Voronoi diagram; out only */
-  int numberofedges;                                             /* Out only */
-};
-
-void triangulate(char *, struct triangulateio *, struct triangulateio *,
-                 struct triangulateio *);
-
-#ifdef __cplusplus
-}
-#endif
+/*****************************************************************************/
+/*                                                                           */
+/*  (triangle.h)                                                             */
+/*                                                                           */
+/*  Include file for programs that call Triangle.                            */
+/*                                                                           */
+/*  Accompanies Triangle Version 1.3                                         */
+/*  July 19, 1996                                                            */
+/*                                                                           */
+/*  Copyright 1996                                                           */
+/*  Jonathan Richard Shewchuk                                                */
+/*  School of Computer Science                                               */
+/*  Carnegie Mellon University                                               */
+/*  5000 Forbes Avenue                                                       */
+/*  Pittsburgh, Pennsylvania  15213-3891                                     */
+/*  jrs@cs.cmu.edu                                                           */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  How to call Triangle from another program                                */
+/*                                                                           */
+/*                                                                           */
+/*  If you haven't read Triangle's instructions (run "triangle -h" to read   */
+/*  them), you won't understand what follows.                                */
+/*                                                                           */
+/*  Triangle must be compiled into an object file (triangle.o) with the      */
+/*  TRILIBRARY symbol defined (preferably by using the -DTRILIBRARY compiler */
+/*  switch).  The makefile included with Triangle will do this for you if    */
+/*  you run "make trilibrary".  The resulting object file can be called via  */
+/*  the procedure triangulate().                                             */
+/*                                                                           */
+/*  If the size of the object file is important to you, you may wish to      */
+/*  generate a reduced version of triangle.o.  The REDUCED symbol gets rid   */
+/*  of all features that are primarily of research interest.  Specifically,  */
+/*  the -DREDUCED switch eliminates Triangle's -i, -F, -s, and -C switches.  */
+/*  The CDT_ONLY symbol gets rid of all meshing algorithms above and beyond  */
+/*  constrained Delaunay triangulation.  Specifically, the -DCDT_ONLY switch */
+/*  eliminates Triangle's -r, -q, -a, -S, and -s switches.                   */
+/*                                                                           */
+/*  IMPORTANT:  These definitions (TRILIBRARY, REDUCED, CDT_ONLY) must be    */
+/*  made in the makefile or in triangle.c itself.  Putting these definitions */
+/*  in this file will not create the desired effect.                         */
+/*                                                                           */
+/*                                                                           */
+/*  The calling convention for triangulate() follows.                        */
+/*                                                                           */
+/*      void triangulate(triswitches, in, out, vorout)                       */
+/*      char *triswitches;                                                   */
+/*      struct triangulateio *in;                                            */
+/*      struct triangulateio *out;                                           */
+/*      struct triangulateio *vorout;                                        */
+/*                                                                           */
+/*  `triswitches' is a string containing the command line switches you wish  */
+/*  to invoke.  No initial dash is required.  Some suggestions:              */
+/*                                                                           */
+/*  - You'll probably find it convenient to use the `z' switch so that       */
+/*    points (and other items) are numbered from zero.  This simplifies      */
+/*    indexing, because the first item of any type always starts at index    */
+/*    [0] of the corresponding array, whether that item's number is zero or  */
+/*    one.                                                                   */
+/*  - You'll probably want to use the `Q' (quiet) switch in your final code, */
+/*    but you can take advantage of Triangle's printed output (including the */
+/*    `V' switch) while debugging.                                           */
+/*  - If you are not using the `q' or `a' switches, then the output points   */
+/*    will be identical to the input points, except possibly for the         */
+/*    boundary markers.  If you don't need the boundary markers, you should  */
+/*    use the `N' (no nodes output) switch to save memory.  (If you do need  */
+/*    boundary markers, but need to save memory, a good nasty trick is to    */
+/*    set out->pointlist equal to in->pointlist before calling triangulate(),*/
+/*    so that Triangle overwrites the input points with identical copies.)   */
+/*  - The `I' (no iteration numbers) and `g' (.off file output) switches     */
+/*    have no effect when Triangle is compiled with TRILIBRARY defined.      */
+/*                                                                           */
+/*  `in', `out', and `vorout' are descriptions of the input, the output,     */
+/*  and the Voronoi output.  If the `v' (Voronoi output) switch is not used, */
+/*  `vorout' may be NULL.  `in' and `out' may never be NULL.                 */
+/*                                                                           */
+/*  Certain fields of the input and output structures must be initialized,   */
+/*  as described below.                                                      */
+/*                                                                           */
+/*****************************************************************************/
+
+/*****************************************************************************/
+/*                                                                           */
+/*  The `triangulateio' structure.                                           */
+/*                                                                           */
+/*  Used to pass data into and out of the triangulate() procedure.           */
+/*                                                                           */
+/*                                                                           */
+/*  Arrays are used to store points, triangles, markers, and so forth.  In   */
+/*  all cases, the first item in any array is stored starting at index [0].  */
+/*  However, that item is item number `1' unless the `z' switch is used, in  */
+/*  which case it is item number `0'.  Hence, you may find it easier to      */
+/*  index points (and triangles in the neighbor list) if you use the `z'     */
+/*  switch.  Unless, of course, you're calling Triangle from a Fortran       */
+/*  program.                                                                 */
+/*                                                                           */
+/*  Description of fields (except the `numberof' fields, which are obvious): */
+/*                                                                           */
+/*  `pointlist':  An array of point coordinates.  The first point's x        */
+/*    coordinate is at index [0] and its y coordinate at index [1], followed */
+/*    by the coordinates of the remaining points.  Each point occupies two   */
+/*    REALs.                                                                 */
+/*  `pointattributelist':  An array of point attributes.  Each point's       */
+/*    attributes occupy `numberofpointattributes' REALs.                     */
+/*  `pointmarkerlist':  An array of point markers; one int per point.        */
+/*                                                                           */
+/*  `trianglelist':  An array of triangle corners.  The first triangle's     */
+/*    first corner is at index [0], followed by its other two corners in     */
+/*    counterclockwise order, followed by any other nodes if the triangle    */
+/*    represents a nonlinear element.  Each triangle occupies                */
+/*    `numberofcorners' ints.                                                */
+/*  `triangleattributelist':  An array of triangle attributes.  Each         */
+/*    triangle's attributes occupy `numberoftriangleattributes' REALs.       */
+/*  `trianglearealist':  An array of triangle area constraints; one REAL per */
+/*    triangle.  Input only.                                                 */
+/*  `neighborlist':  An array of triangle neighbors; three ints per          */
+/*    triangle.  Output only.                                                */
+/*                                                                           */
+/*  `segmentlist':  An array of segment endpoints.  The first segment's      */
+/*    endpoints are at indices [0] and [1], followed by the remaining        */
+/*    segments.  Two ints per segment.                                       */
+/*  `segmentmarkerlist':  An array of segment markers; one int per segment.  */
+/*                                                                           */
+/*  `holelist':  An array of holes.  The first hole's x and y coordinates    */
+/*    are at indices [0] and [1], followed by the remaining holes.  Two      */
+/*    REALs per hole.  Input only, although the pointer is copied to the     */
+/*    output structure for your convenience.                                 */
+/*                                                                           */
+/*  `regionlist':  An array of regional attributes and area constraints.     */
+/*    The first constraint's x and y coordinates are at indices [0] and [1], */
+/*    followed by the regional attribute and index [2], followed by the      */
+/*    maximum area at index [3], followed by the remaining area constraints. */
+/*    Four REALs per area constraint.  Note that each regional attribute is  */
+/*    used only if you select the `A' switch, and each area constraint is    */
+/*    used only if you select the `a' switch (with no number following), but */
+/*    omitting one of these switches does not change the memory layout.      */
+/*    Input only, although the pointer is copied to the output structure for */
+/*    your convenience.                                                      */
+/*                                                                           */
+/*  `edgelist':  An array of edge endpoints.  The first edge's endpoints are */
+/*    at indices [0] and [1], followed by the remaining edges.  Two ints per */
+/*    edge.  Output only.                                                    */
+/*  `edgemarkerlist':  An array of edge markers; one int per edge.  Output   */
+/*    only.                                                                  */
+/*  `normlist':  An array of normal vectors, used for infinite rays in       */
+/*    Voronoi diagrams.  The first normal vector's x and y magnitudes are    */
+/*    at indices [0] and [1], followed by the remaining vectors.  For each   */
+/*    finite edge in a Voronoi diagram, the normal vector written is the     */
+/*    zero vector.  Two REALs per edge.  Output only.                        */
+/*                                                                           */
+/*                                                                           */
+/*  Any input fields that Triangle will examine must be initialized.         */
+/*  Furthermore, for each output array that Triangle will write to, you      */
+/*  must either provide space by setting the appropriate pointer to point    */
+/*  to the space you want the data written to, or you must initialize the    */
+/*  pointer to NULL, which tells Triangle to allocate space for the results. */
+/*  The latter option is preferable, because Triangle always knows exactly   */
+/*  how much space to allocate.  The former option is provided mainly for    */
+/*  people who need to call Triangle from Fortran code, though it also makes */
+/*  possible some nasty space-saving tricks, like writing the output to the  */
+/*  same arrays as the input.                                                */
+/*                                                                           */
+/*  Triangle will not free() any input or output arrays, including those it  */
+/*  allocates itself; that's up to you.                                      */
+/*                                                                           */
+/*  Here's a guide to help you decide which fields you must initialize       */
+/*  before you call triangulate().                                           */
+/*                                                                           */
+/*  `in':                                                                    */
+/*                                                                           */
+/*    - `pointlist' must always point to a list of points; `numberofpoints'  */
+/*      and `numberofpointattributes' must be properly set.                  */
+/*      `pointmarkerlist' must either be set to NULL (in which case all      */
+/*      markers default to zero), or must point to a list of markers.  If    */
+/*      `numberofpointattributes' is not zero, `pointattributelist' must     */
+/*      point to a list of point attributes.                                 */
+/*    - If the `r' switch is used, `trianglelist' must point to a list of    */
+/*      triangles, and `numberoftriangles', `numberofcorners', and           */
+/*      `numberoftriangleattributes' must be properly set.  If               */
+/*      `numberoftriangleattributes' is not zero, `triangleattributelist'    */
+/*      must point to a list of triangle attributes.  If the `a' switch is   */
+/*      used (with no number following), `trianglearealist' must point to a  */
+/*      list of triangle area constraints.  `neighborlist' may be ignored.   */
+/*    - If the `p' switch is used, `segmentlist' must point to a list of     */
+/*      segments, `numberofsegments' must be properly set, and               */
+/*      `segmentmarkerlist' must either be set to NULL (in which case all    */
+/*      markers default to zero), or must point to a list of markers.        */
+/*    - If the `p' switch is used without the `r' switch, then               */
+/*      `numberofholes' and `numberofregions' must be properly set.  If      */
+/*      `numberofholes' is not zero, `holelist' must point to a list of      */
+/*      holes.  If `numberofregions' is not zero, `regionlist' must point to */
+/*      a list of region constraints.                                        */
+/*    - If the `p' switch is used, `holelist', `numberofholes',              */
+/*      `regionlist', and `numberofregions' is copied to `out'.  (You can    */
+/*      nonetheless get away with not initializing them if the `r' switch is */
+/*      used.)                                                               */
+/*    - `edgelist', `edgemarkerlist', `normlist', and `numberofedges' may be */
+/*      ignored.                                                             */
+/*                                                                           */
+/*  `out':                                                                   */
+/*                                                                           */
+/*    - `pointlist' must be initialized (NULL or pointing to memory) unless  */
+/*      the `N' switch is used.  `pointmarkerlist' must be initialized       */
+/*      unless the `N' or `B' switch is used.  If `N' is not used and        */
+/*      `in->numberofpointattributes' is not zero, `pointattributelist' must */
+/*      be initialized.                                                      */
+/*    - `trianglelist' must be initialized unless the `E' switch is used.    */
+/*      `neighborlist' must be initialized if the `n' switch is used.  If    */
+/*      the `E' switch is not used and (`in->numberofelementattributes' is   */
+/*      not zero or the `A' switch is used), `elementattributelist' must be  */
+/*      initialized.  `trianglearealist' may be ignored.                     */
+/*    - `segmentlist' must be initialized if the `p' or `c' switch is used,  */
+/*      and the `P' switch is not used.  `segmentmarkerlist' must also be    */
+/*      initialized under these circumstances unless the `B' switch is used. */
+/*    - `edgelist' must be initialized if the `e' switch is used.            */
+/*      `edgemarkerlist' must be initialized if the `e' switch is used and   */
+/*      the `B' switch is not.                                               */
+/*    - `holelist', `regionlist', `normlist', and all scalars may be ignored.*/
+/*                                                                           */
+/*  `vorout' (only needed if `v' switch is used):                            */
+/*                                                                           */
+/*    - `pointlist' must be initialized.  If `in->numberofpointattributes'   */
+/*      is not zero, `pointattributelist' must be initialized.               */
+/*      `pointmarkerlist' may be ignored.                                    */
+/*    - `edgelist' and `normlist' must both be initialized.                  */
+/*      `edgemarkerlist' may be ignored.                                     */
+/*    - Everything else may be ignored.                                      */
+/*                                                                           */
+/*  After a call to triangulate(), the valid fields of `out' and `vorout'    */
+/*  will depend, in an obvious way, on the choice of switches used.  Note    */
+/*  that when the `p' switch is used, the pointers `holelist' and            */
+/*  `regionlist' are copied from `in' to `out', but no new space is          */
+/*  allocated; be careful that you don't free() the same array twice.  On    */
+/*  the other hand, Triangle will never copy the `pointlist' pointer (or any */
+/*  others); new space is allocated for `out->pointlist', or if the `N'      */
+/*  switch is used, `out->pointlist' remains uninitialized.                  */
+/*                                                                           */
+/*  All of the meaningful `numberof' fields will be properly set; for        */
+/*  instance, `numberofedges' will represent the number of edges in the      */
+/*  triangulation whether or not the edges were written.  If segments are    */
+/*  not used, `numberofsegments' will indicate the number of boundary edges. */
+/*                                                                           */
+/*****************************************************************************/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct triangulateio {
+  REAL *pointlist;                                               /* In / out */
+  REAL *pointattributelist;                                      /* In / out */
+  int *pointmarkerlist;                                          /* In / out */
+  int numberofpoints;                                            /* In / out */
+  int numberofpointattributes;                                   /* In / out */
+
+  int *trianglelist;                                             /* In / out */
+  REAL *triangleattributelist;                                   /* In / out */
+  REAL *trianglearealist;                                         /* In only */
+  int *neighborlist;                                             /* Out only */
+  int numberoftriangles;                                         /* In / out */
+  int numberofcorners;                                           /* In / out */
+  int numberoftriangleattributes;                                /* In / out */
+
+  int *segmentlist;                                              /* In / out */
+  int *segmentmarkerlist;                                        /* In / out */
+  int numberofsegments;                                          /* In / out */
+
+  REAL *holelist;                        /* In / pointer to array copied out */
+  int numberofholes;                                      /* In / copied out */
+
+  REAL *regionlist;                      /* In / pointer to array copied out */
+  int numberofregions;                                    /* In / copied out */
+
+  int *edgelist;                                                 /* Out only */
+  int *edgemarkerlist;            /* Not used with Voronoi diagram; out only */
+  REAL *normlist;                /* Used only with Voronoi diagram; out only */
+  int numberofedges;                                             /* Out only */
+};
+
+void triangulate(char *, struct triangulateio *, struct triangulateio *,
+                 struct triangulateio *);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/contrib/hydratoolz/plugin.h b/contrib/hydratoolz/plugin.h
index 493fa839..42b3c20c 100644
--- a/contrib/hydratoolz/plugin.h
+++ b/contrib/hydratoolz/plugin.h
@@ -1,51 +1,51 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-//#include <gdk/gdkkeysyms.h>
-//#include <gtk/gtk.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#include "synapse.h"
-#include "iplugin.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#include "ishaders.h"
-#define USE_VFSTABLE_DEFINE
-#include "ifilesystem.h"
-#define USE_ENTITYTABLE_DEFINE
-#include "ientity.h"
-
-class CSynapseClientHydraToolz : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-
-  CSynapseClientHydraToolz() { }
-  virtual ~CSynapseClientHydraToolz() { }
-};
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+//#include <gdk/gdkkeysyms.h>
+//#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include "synapse.h"
+#include "iplugin.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#include "ishaders.h"
+#define USE_VFSTABLE_DEFINE
+#include "ifilesystem.h"
+#define USE_ENTITYTABLE_DEFINE
+#include "ientity.h"
+
+class CSynapseClientHydraToolz : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+
+  CSynapseClientHydraToolz() { }
+  virtual ~CSynapseClientHydraToolz() { }
+};
+
+#endif // _PLUGIN_H_
diff --git a/contrib/prtview/AboutDialog.h b/contrib/prtview/AboutDialog.h
index 73dbad78..66d8c0d0 100644
--- a/contrib/prtview/AboutDialog.h
+++ b/contrib/prtview/AboutDialog.h
@@ -1,72 +1,72 @@
-/*
-PrtView plugin for GtkRadiant
-Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_ABOUTDIALOG_H__FA3BE6A2_1F1F_11D4_BFF1_204C4F4F5020__INCLUDED_)
-#define AFX_ABOUTDIALOG_H__FA3BE6A2_1F1F_11D4_BFF1_204C4F4F5020__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// AboutDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CAboutDialog dialog
-
-#ifdef GTK_PLUGIN
-void DoAboutDlg ();
-
-#else // GTK_PLUGIN
-
-class CAboutDialog : public CDialog
-{
-// Construction
-public:
-	CAboutDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CAboutDialog)
-	enum { IDD = IDD_ABOUT };
-		// NOTE: the ClassWizard will add data members here
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CAboutDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CAboutDialog)
-		// NOTE: the ClassWizard will add member functions here
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-#endif // GTK_PLUGIN
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_ABOUTDIALOG_H__FA3BE6A2_1F1F_11D4_BFF1_204C4F4F5020__INCLUDED_)
+/*
+PrtView plugin for GtkRadiant
+Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_ABOUTDIALOG_H__FA3BE6A2_1F1F_11D4_BFF1_204C4F4F5020__INCLUDED_)
+#define AFX_ABOUTDIALOG_H__FA3BE6A2_1F1F_11D4_BFF1_204C4F4F5020__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// AboutDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CAboutDialog dialog
+
+#ifdef GTK_PLUGIN
+void DoAboutDlg ();
+
+#else // GTK_PLUGIN
+
+class CAboutDialog : public CDialog
+{
+// Construction
+public:
+	CAboutDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CAboutDialog)
+	enum { IDD = IDD_ABOUT };
+		// NOTE: the ClassWizard will add data members here
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CAboutDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CAboutDialog)
+		// NOTE: the ClassWizard will add member functions here
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+#endif // GTK_PLUGIN
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_ABOUTDIALOG_H__FA3BE6A2_1F1F_11D4_BFF1_204C4F4F5020__INCLUDED_)
diff --git a/contrib/prtview/ConfigDialog.h b/contrib/prtview/ConfigDialog.h
index 7ca84920..11690fdc 100644
--- a/contrib/prtview/ConfigDialog.h
+++ b/contrib/prtview/ConfigDialog.h
@@ -1,107 +1,107 @@
-/*
-PrtView plugin for GtkRadiant
-Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_CONFIGDIALOG_H__E484E672_2088_11D4_BFFA_204C4F4F5020__INCLUDED_)
-#define AFX_CONFIGDIALOG_H__E484E672_2088_11D4_BFFA_204C4F4F5020__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// ConfigDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CConfigDialog dialog
-
-#ifdef GTK_PLUGIN
-
-void DoConfigDialog ();
-
-#else
-
-class CConfigDialog : public CDialog
-{
-// Construction
-public:
-	CConfigDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CConfigDialog)
-	enum { IDD = IDD_CONFIG };
-	CButton	m_clip_ctrl;
-	CStatic	m_cubic_ctrl;
-	CScrollBar	m_scroll_cubic_ctrl;
-	CButton	m_line_ctrl;
-	CScrollBar	m_scroll_3d_trans_ctrl;
-	CStatic	m_3d_trans_ctrl;
-	CButton	m_poly_ctrl;
-	CButton	m_fog_ctrl;
-	CComboBox	m_z_ctrl;
-	CScrollBar	m_scroll_3d_width_ctrl;
-	CButton	m_aa_3d_ctrl;
-	CStatic	m_3d_width_ctrl;
-	CButton	m_aa_2d_ctrl;
-	CScrollBar	m_scroll_2d_width_ctrl;
-	CStatic	m_2d_width_ctrl;
-	CButton	m_3d_ctrl;
-	CButton	m_2d_ctrl;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CConfigDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	void Set2DText();
-	void Set3DText();
-	void Set3DTransText();
-	void SetClipText();
-
-	// Generated message map functions
-	//{{AFX_MSG(CConfigDialog)
-	virtual qboolean OnInitDialog();
-	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
-	afx_msg void OnAntiAlias2d();
-	afx_msg void OnConfig2d();
-	afx_msg void OnConfig3d();
-	afx_msg void OnColor2d();
-	afx_msg void OnAntiAlias3d();
-	afx_msg void OnColor3d();
-	afx_msg void OnColorFog();
-	afx_msg void OnFog();
-	afx_msg void OnSelchangeZbuffer();
-	afx_msg void OnPoly();
-	afx_msg void OnLines();
-	afx_msg void OnClip();
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-#endif // GTK_PLUGIN
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_CONFIGDIALOG_H__E484E672_2088_11D4_BFFA_204C4F4F5020__INCLUDED_)
+/*
+PrtView plugin for GtkRadiant
+Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_CONFIGDIALOG_H__E484E672_2088_11D4_BFFA_204C4F4F5020__INCLUDED_)
+#define AFX_CONFIGDIALOG_H__E484E672_2088_11D4_BFFA_204C4F4F5020__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// ConfigDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CConfigDialog dialog
+
+#ifdef GTK_PLUGIN
+
+void DoConfigDialog ();
+
+#else
+
+class CConfigDialog : public CDialog
+{
+// Construction
+public:
+	CConfigDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CConfigDialog)
+	enum { IDD = IDD_CONFIG };
+	CButton	m_clip_ctrl;
+	CStatic	m_cubic_ctrl;
+	CScrollBar	m_scroll_cubic_ctrl;
+	CButton	m_line_ctrl;
+	CScrollBar	m_scroll_3d_trans_ctrl;
+	CStatic	m_3d_trans_ctrl;
+	CButton	m_poly_ctrl;
+	CButton	m_fog_ctrl;
+	CComboBox	m_z_ctrl;
+	CScrollBar	m_scroll_3d_width_ctrl;
+	CButton	m_aa_3d_ctrl;
+	CStatic	m_3d_width_ctrl;
+	CButton	m_aa_2d_ctrl;
+	CScrollBar	m_scroll_2d_width_ctrl;
+	CStatic	m_2d_width_ctrl;
+	CButton	m_3d_ctrl;
+	CButton	m_2d_ctrl;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CConfigDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	void Set2DText();
+	void Set3DText();
+	void Set3DTransText();
+	void SetClipText();
+
+	// Generated message map functions
+	//{{AFX_MSG(CConfigDialog)
+	virtual qboolean OnInitDialog();
+	afx_msg void OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar);
+	afx_msg void OnAntiAlias2d();
+	afx_msg void OnConfig2d();
+	afx_msg void OnConfig3d();
+	afx_msg void OnColor2d();
+	afx_msg void OnAntiAlias3d();
+	afx_msg void OnColor3d();
+	afx_msg void OnColorFog();
+	afx_msg void OnFog();
+	afx_msg void OnSelchangeZbuffer();
+	afx_msg void OnPoly();
+	afx_msg void OnLines();
+	afx_msg void OnClip();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+#endif // GTK_PLUGIN
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_CONFIGDIALOG_H__E484E672_2088_11D4_BFFA_204C4F4F5020__INCLUDED_)
diff --git a/contrib/prtview/LoadPortalFileDialog.h b/contrib/prtview/LoadPortalFileDialog.h
index c11c01ea..4540c104 100644
--- a/contrib/prtview/LoadPortalFileDialog.h
+++ b/contrib/prtview/LoadPortalFileDialog.h
@@ -1,77 +1,77 @@
-/*
-PrtView plugin for GtkRadiant
-Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#if !defined(AFX_LOADPORTALFILEDIALOG_H__6BEDE392_1FDC_11D4_BFF7_204C4F4F5020__INCLUDED_)
-#define AFX_LOADPORTALFILEDIALOG_H__6BEDE392_1FDC_11D4_BFF7_204C4F4F5020__INCLUDED_
-
-#if _MSC_VER >= 1000
-#pragma once
-#endif // _MSC_VER >= 1000
-// LoadPortalFileDialog.h : header file
-//
-
-/////////////////////////////////////////////////////////////////////////////
-// CLoadPortalFileDialog dialog
-
-#ifdef GTK_PLUGIN
-
-int DoLoadPortalFileDialog ();
-
-#else
-
-class CLoadPortalFileDialog : public CDialog
-{
-// Construction
-public:
-	CLoadPortalFileDialog(CWnd* pParent = NULL);   // standard constructor
-
-// Dialog Data
-	//{{AFX_DATA(CLoadPortalFileDialog)
-	enum { IDD = IDD_LOAD };
-	CButton	m_3d_ctrl;
-	CButton	m_2d_ctrl;
-	CStatic	m_fn_ctrl;
-	//}}AFX_DATA
-
-
-// Overrides
-	// ClassWizard generated virtual function overrides
-	//{{AFX_VIRTUAL(CLoadPortalFileDialog)
-	protected:
-	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
-	//}}AFX_VIRTUAL
-
-// Implementation
-protected:
-
-	// Generated message map functions
-	//{{AFX_MSG(CLoadPortalFileDialog)
-	virtual qboolean OnInitDialog();
-	virtual void OnOK();
-	afx_msg void OnLoadOther();
-	//}}AFX_MSG
-	DECLARE_MESSAGE_MAP()
-};
-
-#endif // GTK_PLUGIN
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_LOADPORTALFILEDIALOG_H__6BEDE392_1FDC_11D4_BFF7_204C4F4F5020__INCLUDED_)
+/*
+PrtView plugin for GtkRadiant
+Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#if !defined(AFX_LOADPORTALFILEDIALOG_H__6BEDE392_1FDC_11D4_BFF7_204C4F4F5020__INCLUDED_)
+#define AFX_LOADPORTALFILEDIALOG_H__6BEDE392_1FDC_11D4_BFF7_204C4F4F5020__INCLUDED_
+
+#if _MSC_VER >= 1000
+#pragma once
+#endif // _MSC_VER >= 1000
+// LoadPortalFileDialog.h : header file
+//
+
+/////////////////////////////////////////////////////////////////////////////
+// CLoadPortalFileDialog dialog
+
+#ifdef GTK_PLUGIN
+
+int DoLoadPortalFileDialog ();
+
+#else
+
+class CLoadPortalFileDialog : public CDialog
+{
+// Construction
+public:
+	CLoadPortalFileDialog(CWnd* pParent = NULL);   // standard constructor
+
+// Dialog Data
+	//{{AFX_DATA(CLoadPortalFileDialog)
+	enum { IDD = IDD_LOAD };
+	CButton	m_3d_ctrl;
+	CButton	m_2d_ctrl;
+	CStatic	m_fn_ctrl;
+	//}}AFX_DATA
+
+
+// Overrides
+	// ClassWizard generated virtual function overrides
+	//{{AFX_VIRTUAL(CLoadPortalFileDialog)
+	protected:
+	virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV support
+	//}}AFX_VIRTUAL
+
+// Implementation
+protected:
+
+	// Generated message map functions
+	//{{AFX_MSG(CLoadPortalFileDialog)
+	virtual qboolean OnInitDialog();
+	virtual void OnOK();
+	afx_msg void OnLoadOther();
+	//}}AFX_MSG
+	DECLARE_MESSAGE_MAP()
+};
+
+#endif // GTK_PLUGIN
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Developer Studio will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_LOADPORTALFILEDIALOG_H__6BEDE392_1FDC_11D4_BFF7_204C4F4F5020__INCLUDED_)
diff --git a/contrib/prtview/gtkdlgs.h b/contrib/prtview/gtkdlgs.h
index afa3ea74..37ca5031 100644
--- a/contrib/prtview/gtkdlgs.h
+++ b/contrib/prtview/gtkdlgs.h
@@ -1,27 +1,27 @@
-/*
-PrtView plugin for GtkRadiant
-Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef _GTKDLGS_H_
-#define _GTKDLGS_H_
-
-int DoLoadPortalFileDialog ();
-void DoAboutDlg ();
-void DoConfigDialog ();
-
-#endif // _GTKDLGS_H_
+/*
+PrtView plugin for GtkRadiant
+Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _GTKDLGS_H_
+#define _GTKDLGS_H_
+
+int DoLoadPortalFileDialog ();
+void DoAboutDlg ();
+void DoConfigDialog ();
+
+#endif // _GTKDLGS_H_
diff --git a/contrib/prtview/portals.h b/contrib/prtview/portals.h
index 33bac1ec..13c7b89f 100644
--- a/contrib/prtview/portals.h
+++ b/contrib/prtview/portals.h
@@ -1,125 +1,125 @@
-/*
-PrtView plugin for GtkRadiant
-Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef _PORTALS_H_
-#define _PORTALS_H_
-
-class CBspPoint {
-public:
-	float p[3];
-};
-
-class CBspPortal {
-public:
-	CBspPortal();
-	~CBspPortal();
-
-protected:
-
-public:
-	CBspPoint center;
-	unsigned point_count;
-	CBspPoint *point;
-	CBspPoint *inner_point;
-	float fp_color_random[4];
-	float min[3];
-	float max[3];
-	float dist;
-	qboolean hint;
-
-	qboolean Build(char *def);
-};
-
-class CPortals {
-public:
-
-  CPortals();
-  ~CPortals();
-
-protected:
-
-
-public:
-
-	void Load(); // use filename in fn
-	void Purge();
-
-	void FixColors();
-
-	char fn[_MAX_PATH];
-
-	int zbuffer;
-	int polygons;
-	int lines;
-	qboolean show_3d;
-	qboolean aa_3d;
-	qboolean fog;
-	COLORREF color_3d;
-	float width_3d;  // in 8'ths
-	float fp_color_3d[4];
-	COLORREF color_fog;
-	float fp_color_fog[4];
-	float trans_3d;
-	float clip_range;
-	qboolean clip;
-
-	qboolean show_2d;
-	qboolean aa_2d;
-	COLORREF color_2d;
-	float width_2d;  // in 8'ths
-	float fp_color_2d[4];
-
-	CBspPortal *portal;
-	int *portal_sort;
-	qboolean hint_flags;
-//	CBspNode *node;
-
-	unsigned int node_count;
-	unsigned int portal_count;
-};
-
-class CPortalsRender : public IGL2DWindow, public IGL3DWindow {
-public:
-
-  CPortalsRender();
-  virtual ~CPortalsRender();
-
-protected:
-
-	int refCount;
-#ifdef _WIN32
-	CRITICAL_SECTION protect;
-#endif
-
-public:
-
-  // IGL2DWindow IGL3DWindow interface
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-	void Draw2D( VIEWTYPE vt );
-	void Draw3D();
-	void Register();
-};
-
-// void Sys_Printf (char *text, ...);
-
-extern CPortals portals;
-extern CPortalsRender render;
-
-#endif // _PORTALS_H_
+/*
+PrtView plugin for GtkRadiant
+Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef _PORTALS_H_
+#define _PORTALS_H_
+
+class CBspPoint {
+public:
+	float p[3];
+};
+
+class CBspPortal {
+public:
+	CBspPortal();
+	~CBspPortal();
+
+protected:
+
+public:
+	CBspPoint center;
+	unsigned point_count;
+	CBspPoint *point;
+	CBspPoint *inner_point;
+	float fp_color_random[4];
+	float min[3];
+	float max[3];
+	float dist;
+	qboolean hint;
+
+	qboolean Build(char *def);
+};
+
+class CPortals {
+public:
+
+  CPortals();
+  ~CPortals();
+
+protected:
+
+
+public:
+
+	void Load(); // use filename in fn
+	void Purge();
+
+	void FixColors();
+
+	char fn[_MAX_PATH];
+
+	int zbuffer;
+	int polygons;
+	int lines;
+	qboolean show_3d;
+	qboolean aa_3d;
+	qboolean fog;
+	COLORREF color_3d;
+	float width_3d;  // in 8'ths
+	float fp_color_3d[4];
+	COLORREF color_fog;
+	float fp_color_fog[4];
+	float trans_3d;
+	float clip_range;
+	qboolean clip;
+
+	qboolean show_2d;
+	qboolean aa_2d;
+	COLORREF color_2d;
+	float width_2d;  // in 8'ths
+	float fp_color_2d[4];
+
+	CBspPortal *portal;
+	int *portal_sort;
+	qboolean hint_flags;
+//	CBspNode *node;
+
+	unsigned int node_count;
+	unsigned int portal_count;
+};
+
+class CPortalsRender : public IGL2DWindow, public IGL3DWindow {
+public:
+
+  CPortalsRender();
+  virtual ~CPortalsRender();
+
+protected:
+
+	int refCount;
+#ifdef _WIN32
+	CRITICAL_SECTION protect;
+#endif
+
+public:
+
+  // IGL2DWindow IGL3DWindow interface
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+	void Draw2D( VIEWTYPE vt );
+	void Draw3D();
+	void Register();
+};
+
+// void Sys_Printf (char *text, ...);
+
+extern CPortals portals;
+extern CPortalsRender render;
+
+#endif // _PORTALS_H_
diff --git a/contrib/prtview/prtview.h b/contrib/prtview/prtview.h
index e478f7d9..468df3fc 100644
--- a/contrib/prtview/prtview.h
+++ b/contrib/prtview/prtview.h
@@ -1,29 +1,29 @@
-/*
-PrtView plugin for GtkRadiant
-Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-// PrtView.h : main header file for the PRTVIEW DLL
-//
-
-#if !defined(AFX_PRTVIEW_H__234356A6_1D66_11D4_BFEB_204C4F4F5020__INCLUDED_)
-#define AFX_PRTVIEW_H__234356A6_1D66_11D4_BFEB_204C4F4F5020__INCLUDED_
-
-void InitInstance ();
-void SaveConfig ();
-
-#endif // !defined(AFX_PRTVIEW_H__234356A6_1D66_11D4_BFEB_204C4F4F5020__INCLUDED_)
+/*
+PrtView plugin for GtkRadiant
+Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+// PrtView.h : main header file for the PRTVIEW DLL
+//
+
+#if !defined(AFX_PRTVIEW_H__234356A6_1D66_11D4_BFEB_204C4F4F5020__INCLUDED_)
+#define AFX_PRTVIEW_H__234356A6_1D66_11D4_BFEB_204C4F4F5020__INCLUDED_
+
+void InitInstance ();
+void SaveConfig ();
+
+#endif // !defined(AFX_PRTVIEW_H__234356A6_1D66_11D4_BFEB_204C4F4F5020__INCLUDED_)
diff --git a/contrib/prtview/resource.h b/contrib/prtview/resource.h
index afa9db6e..5fdce405 100644
--- a/contrib/prtview/resource.h
+++ b/contrib/prtview/resource.h
@@ -1,42 +1,42 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by PrtView.rc
-//
-#define IDD_ABOUT                       129
-#define IDD_LOAD                        130
-#define IDD_CONFIG                      131
-#define IDC_LOAD_2D                     1000
-#define IDC_LOAD_3D                     1001
-#define IDC_LOAD_FILE_NAME              1002
-#define IDC_LOAD_OTHER                  1003
-#define IDC_CONFIG_3D                   1004
-#define IDC_CONFIG_2D                   1005
-#define IDC_SCROLL_2D_WIDTH             1006
-#define IDC_2D_WIDTH                    1007
-#define IDC_ANTI_ALIAS_2D               1008
-#define IDC_COLOR_2D                    1009
-#define IDC_ZBUFFER                     1010
-#define IDC_SCROLL_3D_WIDTH             1011
-#define IDC_3D_WIDTH                    1012
-#define IDC_ANTI_ALIAS_3D               1013
-#define IDC_COLOR_3D                    1014
-#define IDC_COLOR_FOG                   1015
-#define IDC_FOG                         1016
-#define IDC_SCROLL_3D_TRANS             1017
-#define IDC_POLY                        1018
-#define IDC_3D_TRANS                    1019
-#define IDC_LINES                       1020
-#define IDC_SCROLL_CUBIC                1021
-#define IDC_CUBIC                       1022
-#define IDC_CLIP                        1023
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        133
-#define _APS_NEXT_COMMAND_VALUE         32771
-#define _APS_NEXT_CONTROL_VALUE         1011
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by PrtView.rc
+//
+#define IDD_ABOUT                       129
+#define IDD_LOAD                        130
+#define IDD_CONFIG                      131
+#define IDC_LOAD_2D                     1000
+#define IDC_LOAD_3D                     1001
+#define IDC_LOAD_FILE_NAME              1002
+#define IDC_LOAD_OTHER                  1003
+#define IDC_CONFIG_3D                   1004
+#define IDC_CONFIG_2D                   1005
+#define IDC_SCROLL_2D_WIDTH             1006
+#define IDC_2D_WIDTH                    1007
+#define IDC_ANTI_ALIAS_2D               1008
+#define IDC_COLOR_2D                    1009
+#define IDC_ZBUFFER                     1010
+#define IDC_SCROLL_3D_WIDTH             1011
+#define IDC_3D_WIDTH                    1012
+#define IDC_ANTI_ALIAS_3D               1013
+#define IDC_COLOR_3D                    1014
+#define IDC_COLOR_FOG                   1015
+#define IDC_FOG                         1016
+#define IDC_SCROLL_3D_TRANS             1017
+#define IDC_POLY                        1018
+#define IDC_3D_TRANS                    1019
+#define IDC_LINES                       1020
+#define IDC_SCROLL_CUBIC                1021
+#define IDC_CUBIC                       1022
+#define IDC_CLIP                        1023
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        133
+#define _APS_NEXT_COMMAND_VALUE         32771
+#define _APS_NEXT_CONTROL_VALUE         1011
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/contrib/prtview/stdafx.h b/contrib/prtview/stdafx.h
index b4afbc8e..e251fa79 100644
--- a/contrib/prtview/stdafx.h
+++ b/contrib/prtview/stdafx.h
@@ -1,79 +1,79 @@
-/*
-PrtView plugin for GtkRadiant
-Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
-
-This library is free software; you can redistribute it and/or
-modify it under the terms of the GNU Lesser General Public
-License as published by the Free Software Foundation; either
-version 2.1 of the License, or (at your option) any later version.
-
-This library 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
-Lesser General Public License for more details.
-
-You should have received a copy of the GNU Lesser General Public
-License along with this library; if not, write to the Free Software
-Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
-*/
-
-#ifndef __PRTVIEW_AFX_H__
-#define __PRTVIEW_AFX_H__
-
-#include <gtk/gtk.h>
-
-#if defined(__linux__) || defined(__APPLE__)
-#include <GL/glx.h>
-
-// Necessary for proper boolean type declaration
-#include "qertypes.h"
-
-typedef guint32 COLORREF;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-typedef void* HMODULE;
-typedef int 	BOOL;
-
-#define RGB(r, g, b) ((guint32)(((guint8) (r) | ((guint16) (g) << 8))|(((guint32) (guint8) (b)) << 16)))
-#define GetRValue(rgb)      ((guint8)(rgb))
-#define GetGValue(rgb)      ((guint8)(((guint16)(rgb)) >> 8))
-#define GetBValue(rgb)      ((guint8)((rgb)>>16))
-
-#define _MAX_PATH PATH_MAX
-
-#define IDOK                1
-#define IDCANCEL            2
-
-#endif // __linux__
-
-#include "synapse.h"
-
-// plugin
-#include "iplugin.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#include "ibspfrontend.h"
-#include "igl.h"
-#include "version.h"
-
-// PrtView
-#include "gtkdlgs.h"
-#include "prtview.h"
-#include "portals.h"
-
-#define MSG_PREFIX "Portal Viewer plugin: "
-#define PRTVIEW_MINOR "prtview"
-
-#define UPDATE_2D (W_XY | W_XZ | W_YZ)
-#define UPDATE_3D (W_CAMERA)
-#define UPDATE_ALL (UPDATE_2D | UPDATE_3D)
-
-int INIGetInt(char *key, int def);
-void INISetInt(char *key, int val, char *comment = NULL);
-
-extern bool interfaces_started;
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERQglTable g_QglTable;
-
-#endif
+/*
+PrtView plugin for GtkRadiant
+Copyright (C) 2001 Geoffrey Dewan, Loki software and qeradiant.com
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library 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
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+*/
+
+#ifndef __PRTVIEW_AFX_H__
+#define __PRTVIEW_AFX_H__
+
+#include <gtk/gtk.h>
+
+#if defined(__linux__) || defined(__APPLE__)
+#include <GL/glx.h>
+
+// Necessary for proper boolean type declaration
+#include "qertypes.h"
+
+typedef guint32 COLORREF;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+typedef void* HMODULE;
+typedef int 	BOOL;
+
+#define RGB(r, g, b) ((guint32)(((guint8) (r) | ((guint16) (g) << 8))|(((guint32) (guint8) (b)) << 16)))
+#define GetRValue(rgb)      ((guint8)(rgb))
+#define GetGValue(rgb)      ((guint8)(((guint16)(rgb)) >> 8))
+#define GetBValue(rgb)      ((guint8)((rgb)>>16))
+
+#define _MAX_PATH PATH_MAX
+
+#define IDOK                1
+#define IDCANCEL            2
+
+#endif // __linux__
+
+#include "synapse.h"
+
+// plugin
+#include "iplugin.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#include "ibspfrontend.h"
+#include "igl.h"
+#include "version.h"
+
+// PrtView
+#include "gtkdlgs.h"
+#include "prtview.h"
+#include "portals.h"
+
+#define MSG_PREFIX "Portal Viewer plugin: "
+#define PRTVIEW_MINOR "prtview"
+
+#define UPDATE_2D (W_XY | W_XZ | W_YZ)
+#define UPDATE_3D (W_CAMERA)
+#define UPDATE_ALL (UPDATE_2D | UPDATE_3D)
+
+int INIGetInt(char *key, int def);
+void INISetInt(char *key, int val, char *comment = NULL);
+
+extern bool interfaces_started;
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERQglTable g_QglTable;
+
+#endif
diff --git a/docs/developer/XMLPush/StdAfx.h b/docs/developer/XMLPush/StdAfx.h
index fbb8d5e2..628f0aba 100644
--- a/docs/developer/XMLPush/StdAfx.h
+++ b/docs/developer/XMLPush/StdAfx.h
@@ -1,22 +1,22 @@
-// stdafx.h : include file for standard system include files,
-//  or project specific include files that are used frequently, but
-//      are changed infrequently
-//
-
-#if !defined(AFX_STDAFX_H__323F1140_CFC1_11D4_A457_0004AC96D4C3__INCLUDED_)
-#define AFX_STDAFX_H__323F1140_CFC1_11D4_A457_0004AC96D4C3__INCLUDED_
-
-#if _MSC_VER > 1000
-#pragma once
-#endif // _MSC_VER > 1000
-
-
-// TODO: reference additional headers your program requires here
-
-//{{AFX_INSERT_LOCATION}}
-// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
-
-#endif // !defined(AFX_STDAFX_H__323F1140_CFC1_11D4_A457_0004AC96D4C3__INCLUDED_)
-
-#include "libxml/parser.h"
-#include "libxml/tree.h"
+// stdafx.h : include file for standard system include files,
+//  or project specific include files that are used frequently, but
+//      are changed infrequently
+//
+
+#if !defined(AFX_STDAFX_H__323F1140_CFC1_11D4_A457_0004AC96D4C3__INCLUDED_)
+#define AFX_STDAFX_H__323F1140_CFC1_11D4_A457_0004AC96D4C3__INCLUDED_
+
+#if _MSC_VER > 1000
+#pragma once
+#endif // _MSC_VER > 1000
+
+
+// TODO: reference additional headers your program requires here
+
+//{{AFX_INSERT_LOCATION}}
+// Microsoft Visual C++ will insert additional declarations immediately before the previous line.
+
+#endif // !defined(AFX_STDAFX_H__323F1140_CFC1_11D4_A457_0004AC96D4C3__INCLUDED_)
+
+#include "libxml/parser.h"
+#include "libxml/tree.h"
diff --git a/docs/manual/quake3/Compile_Manual/cfgq3.c b/docs/manual/quake3/Compile_Manual/cfgq3.c
index b3694bef..47e43c80 100644
--- a/docs/manual/quake3/Compile_Manual/cfgq3.c
+++ b/docs/manual/quake3/Compile_Manual/cfgq3.c
@@ -1,78 +1,78 @@
-//===========================================================================
-// BSPC configuration file
-// Quake3
-//===========================================================================
-
-#define PRESENCE_NONE				1
-#define PRESENCE_NORMAL				2
-#define PRESENCE_CROUCH				4
-
-// more bounding boxes can be added if required
-// always minimize the number of bounding boxes listed here to reduce AAS file size
-// for instance if players cannot crouch then it's good to remove the bbox definition for it
-
-//bounding box when running/walking
-bbox	//30x30x56
-{
-	presencetype	PRESENCE_NORMAL
-	flags			0x0000
-	mins			{-15, -15, -24}
-	maxs			{15, 15, 32}
-}
-
-// bounding box when crouched
-bbox	//30x30x40
-{
-	presencetype	PRESENCE_CROUCH
-	flags			0x0001
-	mins			{-15, -15, -24}
-	maxs			{15, 15, 16}
-}
-
-// do not forget settings as they might not be defaulted correctly when this cfg is used
-settings
-{
-	// physics settings
-	phys_gravitydirection		{0, 0, -1}		// direction of gravity
-	phys_friction				6				// friction
-	phys_stopspeed				100				// stop speed
-	phys_gravity				800				// gravity
-	phys_waterfriction			1				// friction in water
-	phys_watergravity			400				// gravity in water
-	phys_maxvelocity			320				// maximum run speed
-	phys_maxwalkvelocity		320				// maximum walk speed (set for running)
-	phys_maxcrouchvelocity		100				// maximum crouch speed
-	phys_maxswimvelocity		150				// maximum swim speed
-	phys_walkaccelerate			100				// acceleration for walking
-	phys_airaccelerate			0				// acceleration flying through the air
-	phys_swimaccelerate			0				// acceleration for swimming
-	phys_maxstep				18				// maximum step height
-	phys_maxsteepness			0.7				// maximum floor steepness a player can walk on
-	phys_maxwaterjump			19				// maximum height for an out of water jump
-	phys_maxbarrier				33				// maximum barrier a player can jump onto
-	phys_jumpvel				270				// jump velocity
-	phys_falldelta5				40				// falling delta for 5 damage ( see PM_CrashLand in game/bg_pmove.c )
-	phys_falldelta10			60				// falling delta for 5 damage ( see PM_CrashLand in game/bg_pmove.c )
-	// reachability settings
-	// the following are all additional travel times added
-	// for certain reachabilities in 1/100th of a second
-	rs_waterjump				400
-	rs_teleport					50
-	rs_barrierjump				100
-	rs_startcrouch				300
-	rs_startgrapple				500
-	rs_startwalkoffledge		70
-	rs_startjump				300
-	rs_rocketjump				500
-	rs_bfgjump					500
-	rs_jumppad					250
-	rs_aircontrolledjumppad		300
-	rs_funcbob					300
-	rs_startelevator			50
-	rs_falldamage5				300				// avoid getting 5 damage
-	rs_falldamage10				500				// avoid getting 10 damage
-	// if != 0 then this is the maximum fall height a reachability can be created for
-	rs_maxfallheight			0
-	// maximum height a bot may fall down when jumping to some location
-	rs_maxjumpfallheight		450
-}
+//===========================================================================
+// BSPC configuration file
+// Quake3
+//===========================================================================
+
+#define PRESENCE_NONE				1
+#define PRESENCE_NORMAL				2
+#define PRESENCE_CROUCH				4
+
+// more bounding boxes can be added if required
+// always minimize the number of bounding boxes listed here to reduce AAS file size
+// for instance if players cannot crouch then it's good to remove the bbox definition for it
+
+//bounding box when running/walking
+bbox	//30x30x56
+{
+	presencetype	PRESENCE_NORMAL
+	flags			0x0000
+	mins			{-15, -15, -24}
+	maxs			{15, 15, 32}
+}
+
+// bounding box when crouched
+bbox	//30x30x40
+{
+	presencetype	PRESENCE_CROUCH
+	flags			0x0001
+	mins			{-15, -15, -24}
+	maxs			{15, 15, 16}
+}
+
+// do not forget settings as they might not be defaulted correctly when this cfg is used
+settings
+{
+	// physics settings
+	phys_gravitydirection		{0, 0, -1}		// direction of gravity
+	phys_friction				6				// friction
+	phys_stopspeed				100				// stop speed
+	phys_gravity				800				// gravity
+	phys_waterfriction			1				// friction in water
+	phys_watergravity			400				// gravity in water
+	phys_maxvelocity			320				// maximum run speed
+	phys_maxwalkvelocity		320				// maximum walk speed (set for running)
+	phys_maxcrouchvelocity		100				// maximum crouch speed
+	phys_maxswimvelocity		150				// maximum swim speed
+	phys_walkaccelerate			100				// acceleration for walking
+	phys_airaccelerate			0				// acceleration flying through the air
+	phys_swimaccelerate			0				// acceleration for swimming
+	phys_maxstep				18				// maximum step height
+	phys_maxsteepness			0.7				// maximum floor steepness a player can walk on
+	phys_maxwaterjump			19				// maximum height for an out of water jump
+	phys_maxbarrier				33				// maximum barrier a player can jump onto
+	phys_jumpvel				270				// jump velocity
+	phys_falldelta5				40				// falling delta for 5 damage ( see PM_CrashLand in game/bg_pmove.c )
+	phys_falldelta10			60				// falling delta for 5 damage ( see PM_CrashLand in game/bg_pmove.c )
+	// reachability settings
+	// the following are all additional travel times added
+	// for certain reachabilities in 1/100th of a second
+	rs_waterjump				400
+	rs_teleport					50
+	rs_barrierjump				100
+	rs_startcrouch				300
+	rs_startgrapple				500
+	rs_startwalkoffledge		70
+	rs_startjump				300
+	rs_rocketjump				500
+	rs_bfgjump					500
+	rs_jumppad					250
+	rs_aircontrolledjumppad		300
+	rs_funcbob					300
+	rs_startelevator			50
+	rs_falldamage5				300				// avoid getting 5 damage
+	rs_falldamage10				500				// avoid getting 10 damage
+	// if != 0 then this is the maximum fall height a reachability can be created for
+	rs_maxfallheight			0
+	// maximum height a bot may fall down when jumping to some location
+	rs_maxjumpfallheight		450
+}
diff --git a/include/aboutmsg.h b/include/aboutmsg.h
index 213fe347..33748496 100644
--- a/include/aboutmsg.h
+++ b/include/aboutmsg.h
@@ -1,2 +1,2 @@
-// generated header, see makeversion.py
-#define RADIANT_ABOUTMSG "ZeroRadiant build"
+// generated header, see makeversion.py
+#define RADIANT_ABOUTMSG "ZeroRadiant build"
diff --git a/include/gtkr_list.h b/include/gtkr_list.h
index 64ac1710..760f09f7 100644
--- a/include/gtkr_list.h
+++ b/include/gtkr_list.h
@@ -1,23 +1,23 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <list>
-#include "stl_check.h"
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <list>
+#include "stl_check.h"
diff --git a/include/gtkr_vector.h b/include/gtkr_vector.h
index 3964be67..a070cf46 100644
--- a/include/gtkr_vector.h
+++ b/include/gtkr_vector.h
@@ -1,23 +1,23 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <vector>
-#include "stl_check.h"
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <vector>
+#include "stl_check.h"
diff --git a/include/ibrush.h b/include/ibrush.h
index 47eb7a81..e191ac26 100644
--- a/include/ibrush.h
+++ b/include/ibrush.h
@@ -1,73 +1,73 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IBRUSH_H_
-#define _IBRUSH_H_
-
-//
-// API for brush stuff
-//
-
-#define BRUSH_MAJOR "brush"
-// {c1c3f567-2541-4aa3-9d5b-031fbe2a013b}
-static const GUID QERBrushTable_GUID = 
-{ 0xc1c3f567, 0x2541, 0x4aa3, { 0x9d, 0x5b, 0x03, 0x1f, 0xbe, 0x2a, 0x01, 0x3b } };
-
-typedef void	    (* PFN_BRUSHADDTOLIST)  (brush_t *b, brush_t *lst);
-typedef void      (* PFN_BRUSHBUILD)      (brush_t *b, bool bSnap, bool bMarkMap, bool bConvert, bool bFilterTest);
-typedef brush_t*  (* PFN_BRUSHCREATE)     (vec3_t mins, vec3_t maxs, texdef_t *texdef);
-typedef void      (* PFN_BRUSHFREE)       (brush_t *b, bool bRemoveNode);
-typedef void      (* PFN_BRUSHROTATE)     (brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild);
-typedef brush_t*  (* PFN_BRUSHALLOC)      ();
-typedef int       (* PFN_BPMESSAGEBOX)    (int);
-typedef face_t*   (* PFN_FACEALLOC)       (void);
-typedef eclass_t* (* PFN_HASMODEL)        (brush_t *b);
-
-struct _QERBrushTable
-{
-  int m_nSize;
-  PFN_BRUSHADDTOLIST m_pfnBrush_AddToList;
-  PFN_BRUSHBUILD m_pfnBrush_Build;
-  PFN_BRUSHCREATE m_pfnBrush_Create;
-  PFN_BRUSHFREE m_pfnBrush_Free;
-  PFN_BRUSHROTATE m_pfnBrush_Rotate;
-  PFN_BRUSHALLOC m_pfnBrushAlloc;
-  PFN_BPMESSAGEBOX m_pfnBP_MessageBox;
-  PFN_FACEALLOC m_pfnFace_Alloc;
-  PFN_HASMODEL m_pfnHasModel;
-};
-
-#ifdef USE_BRUSHTABLE_DEFINE
-#ifndef __BRUSHTABLENAME
-#define __BRUSHTABLENAME g_BrushTable
-#endif
-#define Brush_AddToList __BRUSHTABLENAME.m_pfnBrush_AddToList
-#define Brush_Build __BRUSHTABLENAME.m_pfnBrush_Build
-#define Brush_Create __BRUSHTABLENAME.m_pfnBrush_Create
-#define Brush_Free __BRUSHTABLENAME.m_pfnBrush_Free
-#define Brush_Rotate __BRUSHTABLENAME.m_pfnBrush_Rotate
-#define Brush_Alloc __BRUSHTABLENAME.m_pfnBrushAlloc
-#define BP_MessageBox __BRUSHTABLENAME.m_pfnBP_MessageBox
-#define Face_Alloc __BRUSHTABLENAME.m_pfnFace_Alloc
-#define HasModel __BRUSHTABLENAME.m_pfnHasModel
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IBRUSH_H_
+#define _IBRUSH_H_
+
+//
+// API for brush stuff
+//
+
+#define BRUSH_MAJOR "brush"
+// {c1c3f567-2541-4aa3-9d5b-031fbe2a013b}
+static const GUID QERBrushTable_GUID = 
+{ 0xc1c3f567, 0x2541, 0x4aa3, { 0x9d, 0x5b, 0x03, 0x1f, 0xbe, 0x2a, 0x01, 0x3b } };
+
+typedef void	    (* PFN_BRUSHADDTOLIST)  (brush_t *b, brush_t *lst);
+typedef void      (* PFN_BRUSHBUILD)      (brush_t *b, bool bSnap, bool bMarkMap, bool bConvert, bool bFilterTest);
+typedef brush_t*  (* PFN_BRUSHCREATE)     (vec3_t mins, vec3_t maxs, texdef_t *texdef);
+typedef void      (* PFN_BRUSHFREE)       (brush_t *b, bool bRemoveNode);
+typedef void      (* PFN_BRUSHROTATE)     (brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild);
+typedef brush_t*  (* PFN_BRUSHALLOC)      ();
+typedef int       (* PFN_BPMESSAGEBOX)    (int);
+typedef face_t*   (* PFN_FACEALLOC)       (void);
+typedef eclass_t* (* PFN_HASMODEL)        (brush_t *b);
+
+struct _QERBrushTable
+{
+  int m_nSize;
+  PFN_BRUSHADDTOLIST m_pfnBrush_AddToList;
+  PFN_BRUSHBUILD m_pfnBrush_Build;
+  PFN_BRUSHCREATE m_pfnBrush_Create;
+  PFN_BRUSHFREE m_pfnBrush_Free;
+  PFN_BRUSHROTATE m_pfnBrush_Rotate;
+  PFN_BRUSHALLOC m_pfnBrushAlloc;
+  PFN_BPMESSAGEBOX m_pfnBP_MessageBox;
+  PFN_FACEALLOC m_pfnFace_Alloc;
+  PFN_HASMODEL m_pfnHasModel;
+};
+
+#ifdef USE_BRUSHTABLE_DEFINE
+#ifndef __BRUSHTABLENAME
+#define __BRUSHTABLENAME g_BrushTable
+#endif
+#define Brush_AddToList __BRUSHTABLENAME.m_pfnBrush_AddToList
+#define Brush_Build __BRUSHTABLENAME.m_pfnBrush_Build
+#define Brush_Create __BRUSHTABLENAME.m_pfnBrush_Create
+#define Brush_Free __BRUSHTABLENAME.m_pfnBrush_Free
+#define Brush_Rotate __BRUSHTABLENAME.m_pfnBrush_Rotate
+#define Brush_Alloc __BRUSHTABLENAME.m_pfnBrushAlloc
+#define BP_MessageBox __BRUSHTABLENAME.m_pfnBP_MessageBox
+#define Face_Alloc __BRUSHTABLENAME.m_pfnFace_Alloc
+#define HasModel __BRUSHTABLENAME.m_pfnHasModel
+#endif
+
+#endif
diff --git a/include/ibspfrontend.h b/include/ibspfrontend.h
index c00217fb..973f0633 100644
--- a/include/ibspfrontend.h
+++ b/include/ibspfrontend.h
@@ -1,77 +1,77 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// interface for BSP frontends plugins
-//
-
-// DONE:	- change BSP menu to Q3Build menu ?
-// DONE:    - detect when Q3Build dies ?
-// DELAYED: - hotkeys !
-// SUCCESS: - try again getting feedback from Q3Build
-
-#ifndef __IBSPFRONTEND_H_
-#define __IBSPFRONTEND_H_
-
-// define a GUID for this interface so plugins can access and reference it
-// {8ED6A480-BA5E-11d3-A3E3-0004AC96D4C3}
-static const GUID QERPlugBSPFrontendTable_GUID = 
-{ 0x8ed6a480, 0xba5e, 0x11d3, { 0xa3, 0xe3, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
-
-// ask the plugin about the items to show up in the BSP menu
-typedef char * (WINAPI* PFN_GETBSPMENU)	();
-// dispatch a BSP menu command
-typedef void (WINAPI* PFN_DISPATCHBSPCOMMAND) (char *);
-// this one gets called after a monitoring loop ends
-// 0: all good
-// 1: timed out / Radiant didn't get the connection
-// 2: got a connection, compilation ended with an error
-typedef void (WINAPI* PFN_ENDLISTEN) (int status);
-
-struct _QERPlugBSPFrontendTable
-{
-	int m_nSize;
-	PFN_GETBSPMENU			m_pfnGetBSPMenu;
-	PFN_DISPATCHBSPCOMMAND	m_pfnDispatchBSPCommand;
-  PFN_ENDLISTEN       m_pfnEndListen;
-};
-
-// interface provided by Radiant to the plugin
-// {A2CCF366-BA60-11d3-A3E3-0004AC96D4C3}
-static const GUID QERAppBSPFrontendTable_GUID = 
-{ 0xa2ccf366, 0xba60, 0x11d3, { 0xa3, 0xe3, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
-
-typedef char * (WINAPI* PFN_GETMAPNAME) ();
-typedef void (WINAPI* PFN_LISTEN) ();
-typedef void (WINAPI* PFN_SLEEP) ();
-
-struct _QERAppBSPFrontendTable
-{
-	int m_nSize;
-	PFN_GETMAPNAME		m_pfnGetMapName;
-  PFN_LISTEN        m_pfnListen;
-  PFN_SLEEP         m_pfnSleep;
-  //++timo TODO: needs a hook to reset the debug window (in regular mode it's done at startup of the BSP operation)
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// interface for BSP frontends plugins
+//
+
+// DONE:	- change BSP menu to Q3Build menu ?
+// DONE:    - detect when Q3Build dies ?
+// DELAYED: - hotkeys !
+// SUCCESS: - try again getting feedback from Q3Build
+
+#ifndef __IBSPFRONTEND_H_
+#define __IBSPFRONTEND_H_
+
+// define a GUID for this interface so plugins can access and reference it
+// {8ED6A480-BA5E-11d3-A3E3-0004AC96D4C3}
+static const GUID QERPlugBSPFrontendTable_GUID = 
+{ 0x8ed6a480, 0xba5e, 0x11d3, { 0xa3, 0xe3, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+// ask the plugin about the items to show up in the BSP menu
+typedef char * (WINAPI* PFN_GETBSPMENU)	();
+// dispatch a BSP menu command
+typedef void (WINAPI* PFN_DISPATCHBSPCOMMAND) (char *);
+// this one gets called after a monitoring loop ends
+// 0: all good
+// 1: timed out / Radiant didn't get the connection
+// 2: got a connection, compilation ended with an error
+typedef void (WINAPI* PFN_ENDLISTEN) (int status);
+
+struct _QERPlugBSPFrontendTable
+{
+	int m_nSize;
+	PFN_GETBSPMENU			m_pfnGetBSPMenu;
+	PFN_DISPATCHBSPCOMMAND	m_pfnDispatchBSPCommand;
+  PFN_ENDLISTEN       m_pfnEndListen;
+};
+
+// interface provided by Radiant to the plugin
+// {A2CCF366-BA60-11d3-A3E3-0004AC96D4C3}
+static const GUID QERAppBSPFrontendTable_GUID = 
+{ 0xa2ccf366, 0xba60, 0x11d3, { 0xa3, 0xe3, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+typedef char * (WINAPI* PFN_GETMAPNAME) ();
+typedef void (WINAPI* PFN_LISTEN) ();
+typedef void (WINAPI* PFN_SLEEP) ();
+
+struct _QERAppBSPFrontendTable
+{
+	int m_nSize;
+	PFN_GETMAPNAME		m_pfnGetMapName;
+  PFN_LISTEN        m_pfnListen;
+  PFN_SLEEP         m_pfnSleep;
+  //++timo TODO: needs a hook to reset the debug window (in regular mode it's done at startup of the BSP operation)
+};
+
+#endif
diff --git a/include/icamera.h b/include/icamera.h
index 22faf0fe..07425ec4 100644
--- a/include/icamera.h
+++ b/include/icamera.h
@@ -1,45 +1,45 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// camera interface
-//
-
-#ifndef __ICAMERA_H_
-#define __ICAMERA_H_
-
-#define CAMERA_MAJOR "camera"
-
-typedef void		(* PFN_GETCAMERA)		( vec3_t origin, vec3_t angles );
-typedef void		(* PFN_SETCAMERA)		( vec3_t origin, vec3_t angles );
-typedef void		(* PFN_GETCAMWINDOWEXTENTS)	( int *x, int *y, int *width, int *height );
-
-struct _QERCameraTable
-{
-	int m_nSize;
-	PFN_GETCAMERA		m_pfnGetCamera;
-	PFN_SETCAMERA		m_pfnSetCamera;
-	PFN_GETCAMWINDOWEXTENTS	m_pfnGetCamWindowExtents;
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// camera interface
+//
+
+#ifndef __ICAMERA_H_
+#define __ICAMERA_H_
+
+#define CAMERA_MAJOR "camera"
+
+typedef void		(* PFN_GETCAMERA)		( vec3_t origin, vec3_t angles );
+typedef void		(* PFN_SETCAMERA)		( vec3_t origin, vec3_t angles );
+typedef void		(* PFN_GETCAMWINDOWEXTENTS)	( int *x, int *y, int *width, int *height );
+
+struct _QERCameraTable
+{
+	int m_nSize;
+	PFN_GETCAMERA		m_pfnGetCamera;
+	PFN_SETCAMERA		m_pfnSetCamera;
+	PFN_GETCAMWINDOWEXTENTS	m_pfnGetCamWindowExtents;
+};
+
+#endif
diff --git a/include/idata.h b/include/idata.h
index eb39cfa9..fe453366 100644
--- a/include/idata.h
+++ b/include/idata.h
@@ -1,57 +1,57 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// interface table to access low-level data inside Radiant (brushes, patches and generic editing primitives)
-
-#ifndef __IDATA_H_
-#define __IDATA_H_
-
-// FIXME TTimo this should probably go away and be replaced by a more flat structure
-//   having to write access functions for every single var is a big annoyance
-//   see IMapData_t, generalize it?
-
-#define DATA_MAJOR "data"
-// FIXME: remove
-// define a GUID for this interface so plugins can access and reference it
-// {608A9870-BCE7-11d4-A454-0004AC96D4C3}
-static const GUID QERAppDataTable_GUID = 
-{ 0x608a9870, 0xbce7, 0x11d4, { 0xa4, 0x54, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
-
-
-// pointers to active_brushes, selected_brushes and filtered_brushes
-typedef brush_t* (WINAPI* PFN_ACTIVEBRUSHES) ();
-typedef brush_t* (WINAPI* PFN_SELECTEDBRUSHES) ();
-typedef brush_t* (WINAPI* PFN_FILTEREDBRUSHES) ();
-typedef CPtrArray* (WINAPI* PFN_LSTSKINCACHE) ();
-
-struct _QERAppDataTable
-{
-  int m_nSize;
-  PFN_ACTIVEBRUSHES m_pfnActiveBrushes;
-  PFN_SELECTEDBRUSHES m_pfnSelectedBrushes;
-  PFN_FILTEREDBRUSHES m_pfnFilteredBrushes;
-  PFN_LSTSKINCACHE m_pfnLstSkinCache;
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// interface table to access low-level data inside Radiant (brushes, patches and generic editing primitives)
+
+#ifndef __IDATA_H_
+#define __IDATA_H_
+
+// FIXME TTimo this should probably go away and be replaced by a more flat structure
+//   having to write access functions for every single var is a big annoyance
+//   see IMapData_t, generalize it?
+
+#define DATA_MAJOR "data"
+// FIXME: remove
+// define a GUID for this interface so plugins can access and reference it
+// {608A9870-BCE7-11d4-A454-0004AC96D4C3}
+static const GUID QERAppDataTable_GUID = 
+{ 0x608a9870, 0xbce7, 0x11d4, { 0xa4, 0x54, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+
+// pointers to active_brushes, selected_brushes and filtered_brushes
+typedef brush_t* (WINAPI* PFN_ACTIVEBRUSHES) ();
+typedef brush_t* (WINAPI* PFN_SELECTEDBRUSHES) ();
+typedef brush_t* (WINAPI* PFN_FILTEREDBRUSHES) ();
+typedef CPtrArray* (WINAPI* PFN_LSTSKINCACHE) ();
+
+struct _QERAppDataTable
+{
+  int m_nSize;
+  PFN_ACTIVEBRUSHES m_pfnActiveBrushes;
+  PFN_SELECTEDBRUSHES m_pfnSelectedBrushes;
+  PFN_FILTEREDBRUSHES m_pfnFilteredBrushes;
+  PFN_LSTSKINCACHE m_pfnLstSkinCache;
+};
+
+#endif
diff --git a/include/idatastream.h b/include/idatastream.h
index 8f6b0b8c..19534aa4 100644
--- a/include/idatastream.h
+++ b/include/idatastream.h
@@ -1,71 +1,71 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-modifications (c) 2001, Id software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _ISTREAM_H_
-#define _ISTREAM_H_
-
-/*!
-API for data streams
-
-Based on an initial implementation by Loki software
-modified to be abstracted and shared across modules
-
-NOTE: why IDataStream and not IStream? because IStream is defined in windows IDL headers
-*/
-
-class IDataStream
-{
-public:  
-  IDataStream();
-  virtual ~IDataStream();
-
-	virtual void IncRef () = 0;	///< Increment the number of references to this object
-	virtual void DecRef () = 0; ///< Decrement the reference count
-
-	virtual unsigned long GetPosition() const = 0;
-	virtual unsigned long Seek(long lOff, int nFrom) = 0;
-	virtual void SetLength(unsigned long nNewLen) = 0;
-	virtual unsigned long GetLength() const = 0;
-
-	virtual char* ReadString(char* pBuf, unsigned long nMax)=0;
-	virtual unsigned long Read(void* pBuf, unsigned long nCount)=0;
-	virtual unsigned long Write(const void* pBuf, unsigned long nCount)=0;
-	virtual int GetChar()=0;
-	virtual int PutChar(int c)=0;
-
-  virtual void printf(const char*, ...) = 0; ///< completely matches the usual printf behaviour
-
-	virtual void Abort()=0;
-	virtual void Flush()=0;
-	virtual void Close()=0;
-};
-
-#endif // _ISTREAM_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+modifications (c) 2001, Id software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _ISTREAM_H_
+#define _ISTREAM_H_
+
+/*!
+API for data streams
+
+Based on an initial implementation by Loki software
+modified to be abstracted and shared across modules
+
+NOTE: why IDataStream and not IStream? because IStream is defined in windows IDL headers
+*/
+
+class IDataStream
+{
+public:  
+  IDataStream();
+  virtual ~IDataStream();
+
+	virtual void IncRef () = 0;	///< Increment the number of references to this object
+	virtual void DecRef () = 0; ///< Decrement the reference count
+
+	virtual unsigned long GetPosition() const = 0;
+	virtual unsigned long Seek(long lOff, int nFrom) = 0;
+	virtual void SetLength(unsigned long nNewLen) = 0;
+	virtual unsigned long GetLength() const = 0;
+
+	virtual char* ReadString(char* pBuf, unsigned long nMax)=0;
+	virtual unsigned long Read(void* pBuf, unsigned long nCount)=0;
+	virtual unsigned long Write(const void* pBuf, unsigned long nCount)=0;
+	virtual int GetChar()=0;
+	virtual int PutChar(int c)=0;
+
+  virtual void printf(const char*, ...) = 0; ///< completely matches the usual printf behaviour
+
+	virtual void Abort()=0;
+	virtual void Flush()=0;
+	virtual void Close()=0;
+};
+
+#endif // _ISTREAM_H_
diff --git a/include/ieclass.h b/include/ieclass.h
index bfca1d60..cb32647c 100644
--- a/include/ieclass.h
+++ b/include/ieclass.h
@@ -1,84 +1,84 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*! \file ieclass.h
-    \brief entity files loader API
-    this describes the APIs involved when loading entity description files
-    (initially, .def and .fgd)
-*/
-
-#ifndef _IECLASS_H_
-#define _IECLASS_H_
-
-#define ECLASS_MAJOR "eclass"
-
-typedef void (* PFN_ECLASS_SCANFILE) (char *filename);
-typedef const char*       (* PFN_ECLASS_GETEXTENSION)     ();
-
-struct _EClassTable
-{
-  int m_nSize;
-  PFN_ECLASS_SCANFILE m_pfnScanFile;
-  PFN_ECLASS_GETEXTENSION       m_pfnGetExtension;
-};
-
-#ifdef USE_ECLASSTABLE_DEFINE
-#ifndef __ECLASSTABLENAME
-#define __ECLASSTABLENAME g_EClassTable
-#endif
-#define EClass_ScanFile __ECLASSTABLENAME.m_pfnEClass_ScanFile
-#define EClass_GetExtension __ECLASSTABLENAME.m_pfnEClass_GetExtension
-#endif
-
-#define ECLASSMANAGER_MAJOR "eclassmanager"
-
-typedef void (* PFN_ECLASS_INSERTALPHABETIZED) (eclass_t *e);
-typedef eclass_t** (* PFN_GET_ECLASS_E) ();
-typedef void (* PFN_SET_ECLASS_FOUND) (qboolean);
-typedef qboolean (* PFN_GET_PARSING_SINGLE) ();
-typedef eclass_t* (* PFN_ECLASS_CREATE) (const char *name, float col1, float col2, float col3, const vec3_t *mins, const vec3_t *maxs, const char *comments);
-typedef eclass_t* (* PFN_ECLASS_FORNAME) (const char* name, qboolean has_brushes);
-
-struct _EClassManagerTable
-{
-  int m_nSize;
-  PFN_ECLASS_INSERTALPHABETIZED m_pfnEclass_InsertAlphabetized;
-  PFN_GET_ECLASS_E m_pfnGet_Eclass_E;
-  PFN_SET_ECLASS_FOUND m_pfnSet_Eclass_Found;
-  PFN_GET_PARSING_SINGLE m_pfnGet_Parsing_Single;
-  PFN_ECLASS_CREATE m_pfnEClass_Create;
-  PFN_ECLASS_FORNAME m_pfnEclass_ForName;
-};
-
-#ifdef USE_ECLASSMANAGER_DEFINE
-#ifndef __ECLASSMANAGERTABLENAME
-#define __ECLASSMANAGERTABLENAME g_EClassManagerTable
-#endif
-#define Eclass_InsertAlphabetized __ECLASSMANAGERTABLENAME.m_pfnEclass_InsertAlphabetized
-#define Get_Eclass_E __ECLASSMANAGERTABLENAME.m_pfnGet_Eclass_E
-#define Set_Eclass_Found __ECLASSMANAGERTABLENAME.m_pfnSet_Eclass_Found
-#define Get_Parsing_Single __ECLASSMANAGERTABLENAME.m_pfnGet_Parsing_Single
-#define EClass_Create __ECLASSMANAGERTABLENAME.m_pfnEClass_Create
-#define Eclass_ForName __ECLASSMANAGERTABLENAME.m_pfnEclass_ForName
-#endif
-
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*! \file ieclass.h
+    \brief entity files loader API
+    this describes the APIs involved when loading entity description files
+    (initially, .def and .fgd)
+*/
+
+#ifndef _IECLASS_H_
+#define _IECLASS_H_
+
+#define ECLASS_MAJOR "eclass"
+
+typedef void (* PFN_ECLASS_SCANFILE) (char *filename);
+typedef const char*       (* PFN_ECLASS_GETEXTENSION)     ();
+
+struct _EClassTable
+{
+  int m_nSize;
+  PFN_ECLASS_SCANFILE m_pfnScanFile;
+  PFN_ECLASS_GETEXTENSION       m_pfnGetExtension;
+};
+
+#ifdef USE_ECLASSTABLE_DEFINE
+#ifndef __ECLASSTABLENAME
+#define __ECLASSTABLENAME g_EClassTable
+#endif
+#define EClass_ScanFile __ECLASSTABLENAME.m_pfnEClass_ScanFile
+#define EClass_GetExtension __ECLASSTABLENAME.m_pfnEClass_GetExtension
+#endif
+
+#define ECLASSMANAGER_MAJOR "eclassmanager"
+
+typedef void (* PFN_ECLASS_INSERTALPHABETIZED) (eclass_t *e);
+typedef eclass_t** (* PFN_GET_ECLASS_E) ();
+typedef void (* PFN_SET_ECLASS_FOUND) (qboolean);
+typedef qboolean (* PFN_GET_PARSING_SINGLE) ();
+typedef eclass_t* (* PFN_ECLASS_CREATE) (const char *name, float col1, float col2, float col3, const vec3_t *mins, const vec3_t *maxs, const char *comments);
+typedef eclass_t* (* PFN_ECLASS_FORNAME) (const char* name, qboolean has_brushes);
+
+struct _EClassManagerTable
+{
+  int m_nSize;
+  PFN_ECLASS_INSERTALPHABETIZED m_pfnEclass_InsertAlphabetized;
+  PFN_GET_ECLASS_E m_pfnGet_Eclass_E;
+  PFN_SET_ECLASS_FOUND m_pfnSet_Eclass_Found;
+  PFN_GET_PARSING_SINGLE m_pfnGet_Parsing_Single;
+  PFN_ECLASS_CREATE m_pfnEClass_Create;
+  PFN_ECLASS_FORNAME m_pfnEclass_ForName;
+};
+
+#ifdef USE_ECLASSMANAGER_DEFINE
+#ifndef __ECLASSMANAGERTABLENAME
+#define __ECLASSMANAGERTABLENAME g_EClassManagerTable
+#endif
+#define Eclass_InsertAlphabetized __ECLASSMANAGERTABLENAME.m_pfnEclass_InsertAlphabetized
+#define Get_Eclass_E __ECLASSMANAGERTABLENAME.m_pfnGet_Eclass_E
+#define Set_Eclass_Found __ECLASSMANAGERTABLENAME.m_pfnSet_Eclass_Found
+#define Get_Parsing_Single __ECLASSMANAGERTABLENAME.m_pfnGet_Parsing_Single
+#define EClass_Create __ECLASSMANAGERTABLENAME.m_pfnEClass_Create
+#define Eclass_ForName __ECLASSMANAGERTABLENAME.m_pfnEclass_ForName
+#endif
+
+#endif
+
diff --git a/include/ientity.h b/include/ientity.h
index 51ca389f..015cf1ec 100644
--- a/include/ientity.h
+++ b/include/ientity.h
@@ -1,116 +1,116 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IENTITY_H_
-#define _IENTITY_H_
-
-//
-// API for entity manip stuff
-//
-
-// FIXME TTimo this prolly needs to merge with iepairs.h?
-
-/*!
-SPoG
-generic "entity" module... 
-at first, there will only be one implementation for all entities, 
-perhaps later there will be one for each entity type? 
-it would probably make more sense to have a single implementation, 
-a generic one that is very flexible and can adapt the visualisation of 
-itself depending on an xml config specified in the entity definitions file
-*/
-#define ENTITY_MAJOR "entity"
-// {A1C9F9FD-75D5-4e4d-9D65-235D6D3F254C}
-static const GUID QEREntityTable_GUID = 
-{ 0xa1c9f9fd, 0x75d5, 0x4e4d, { 0x9d, 0x65, 0x23, 0x5d, 0x6d, 0x3f, 0x25, 0x4c } };
-
-typedef entity_t* (* PFN_ENTITYALLOC) ();
-typedef void (* PFN_ENTITYFREE) (entity_t *e);
-typedef entity_t* (* PFN_ENTITYCREATE) (eclass_t *c);
-typedef entity_t* (* PFN_ENTITYCLONE) (entity_t *e);
-typedef void  (* PFN_ENTITYSETKEYVALUE) (entity_t *ent, const char *key, const char *value);
-typedef void  (* PFN_ENTITYDELETEKEY) (entity_t *ent, const char *key);
-typedef const char* (* PFN_ENTITYVALUEFORKEY) (entity_t *ent, const char *key);
-typedef float (* PFN_ENTITYFLOATFORKEY) (entity_t *ent, const char *key);
-typedef int   (* PFN_ENTITYINTFORKEY) (entity_t *ent, const char *key);
-typedef void  (* PFN_ENTITYVECTORFORKEY) (entity_t *ent, const char *key, vec3_t vec);
-typedef void (* PFN_ENTITYADDTOLIST) (entity_t *e, entity_t *lst);
-typedef void (* PFN_ENTITYREMOVEFROMLIST) (entity_t *e);
-typedef void (* PFN_ENTITYLINKBRUSH) (entity_t *e, brush_t *b);
-typedef void (* PFN_ENTITYUNLINKBRUSH) (brush_t *b);
-typedef void (* PFN_ENTITYDRAWLIGHT) (entity_t* e, int nGLState, int pref, int nViewType);
-typedef int (* PFN_ENTITYMEMORYSIZE) (entity_t *e);
-typedef void (* PFN_ENTITYUPDATEMODEL) (entity_t *e);
-typedef epair_t* (* PFN_ALLOCATEEPAIR) (const char *key, const char *value);
-typedef epair_t** (* PFN_GETENTITYKEYVALLIST) (entity_t *e);
-typedef void (* PFN_SETENTITYKEYVALLIST) (entity_t *e, epair_t* ep);
-
-
-struct _QEREntityTable
-{
-  int m_nSize;
-  PFN_ENTITYALLOC m_pfnEntity_Alloc;
-  PFN_ENTITYFREE m_pfnEntity_Free;
-  PFN_ENTITYCREATE m_pfnEntity_Create;
-  PFN_ENTITYCLONE m_pfnEntity_Clone;
-  PFN_ENTITYSETKEYVALUE m_pfnSetKeyValue;
-  PFN_ENTITYDELETEKEY m_pfnDeleteKey;
-  PFN_ENTITYVALUEFORKEY m_pfnValueForKey;
-  PFN_ENTITYFLOATFORKEY m_pfnFloatForKey;
-  PFN_ENTITYINTFORKEY m_pfnIntForKey;
-  PFN_ENTITYVECTORFORKEY m_pfnGetVectorForKey;
-  PFN_ENTITYADDTOLIST m_pfnEntity_AddToList;
-  PFN_ENTITYREMOVEFROMLIST m_pfnEntity_RemoveFromList;
-  PFN_ENTITYLINKBRUSH m_pfnEntity_LinkBrush;
-  PFN_ENTITYUNLINKBRUSH m_pfnEntity_UnlinkBrush;
-  PFN_ENTITYDRAWLIGHT m_pfnDrawLight;
-  PFN_ENTITYMEMORYSIZE m_pfnEntity_MemorySize;
-  PFN_ALLOCATEEPAIR m_pfnAllocateEpair;
-  PFN_GETENTITYKEYVALLIST m_pfnGetEntityKeyValList;
-  PFN_SETENTITYKEYVALLIST m_pfnSetEntityKeyValList;
-};
-
-#ifdef USE_ENTITYTABLE_DEFINE
-#ifndef __ENTITYTABLENAME
-#define __ENTITYTABLENAME g_EntityTable
-#endif
-#define Entity_Alloc __ENTITYTABLENAME.m_pfnEntity_Alloc
-#define Entity_Free __ENTITYTABLENAME.m_pfnEntity_Free
-#define Entity_Clone __ENTITYTABLENAME.m_pfnEntity_Clone
-#define SetKeyValue __ENTITYTABLENAME.m_pfnSetKeyValue
-#define DeleteKey __ENTITYTABLENAME.m_pfnDeleteKey
-#define ValueForKey __ENTITYTABLENAME.m_pfnValueForKey
-#define FloatForKey __ENTITYTABLENAME.m_pfnFloatForKey
-#define IntForKey __ENTITYTABLENAME.m_pfnIntForKey
-#define GetVectorForKey __ENTITYTABLENAME.m_pfnGetVectorForKey
-#define Entity_AddToList __ENTITYTABLENAME.m_pfnEntity_AddToList
-#define Entity_RemoveFromList __ENTITYTABLENAME.m_pfnEntity_RemoveFromList
-#define Entity_LinkBrush __ENTITYTABLENAME.m_pfnEntity_LinkBrush
-#define Entity_UnlinkBrush __ENTITYTABLENAME.m_pfnEntity_UnlinkBrush
-#define DrawLight __ENTITYTABLENAME.m_pfnDrawLight
-#define Entity_MemorySize __ENTITYTABLENAME.m_pfnEntity_MemorySize
-#define Entity_AllocateEpair __ENTITYTABLENAME.m_pfnAllocateEpair
-#define Entity_GetKeyValList __ENTITYTABLENAME.m_pfnGetEntityKeyValList
-#define Entity_SetKeyValList __ENTITYTABLENAME.m_pfnSetEntityKeyValList
-#endif
-
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IENTITY_H_
+#define _IENTITY_H_
+
+//
+// API for entity manip stuff
+//
+
+// FIXME TTimo this prolly needs to merge with iepairs.h?
+
+/*!
+SPoG
+generic "entity" module... 
+at first, there will only be one implementation for all entities, 
+perhaps later there will be one for each entity type? 
+it would probably make more sense to have a single implementation, 
+a generic one that is very flexible and can adapt the visualisation of 
+itself depending on an xml config specified in the entity definitions file
+*/
+#define ENTITY_MAJOR "entity"
+// {A1C9F9FD-75D5-4e4d-9D65-235D6D3F254C}
+static const GUID QEREntityTable_GUID = 
+{ 0xa1c9f9fd, 0x75d5, 0x4e4d, { 0x9d, 0x65, 0x23, 0x5d, 0x6d, 0x3f, 0x25, 0x4c } };
+
+typedef entity_t* (* PFN_ENTITYALLOC) ();
+typedef void (* PFN_ENTITYFREE) (entity_t *e);
+typedef entity_t* (* PFN_ENTITYCREATE) (eclass_t *c);
+typedef entity_t* (* PFN_ENTITYCLONE) (entity_t *e);
+typedef void  (* PFN_ENTITYSETKEYVALUE) (entity_t *ent, const char *key, const char *value);
+typedef void  (* PFN_ENTITYDELETEKEY) (entity_t *ent, const char *key);
+typedef const char* (* PFN_ENTITYVALUEFORKEY) (entity_t *ent, const char *key);
+typedef float (* PFN_ENTITYFLOATFORKEY) (entity_t *ent, const char *key);
+typedef int   (* PFN_ENTITYINTFORKEY) (entity_t *ent, const char *key);
+typedef void  (* PFN_ENTITYVECTORFORKEY) (entity_t *ent, const char *key, vec3_t vec);
+typedef void (* PFN_ENTITYADDTOLIST) (entity_t *e, entity_t *lst);
+typedef void (* PFN_ENTITYREMOVEFROMLIST) (entity_t *e);
+typedef void (* PFN_ENTITYLINKBRUSH) (entity_t *e, brush_t *b);
+typedef void (* PFN_ENTITYUNLINKBRUSH) (brush_t *b);
+typedef void (* PFN_ENTITYDRAWLIGHT) (entity_t* e, int nGLState, int pref, int nViewType);
+typedef int (* PFN_ENTITYMEMORYSIZE) (entity_t *e);
+typedef void (* PFN_ENTITYUPDATEMODEL) (entity_t *e);
+typedef epair_t* (* PFN_ALLOCATEEPAIR) (const char *key, const char *value);
+typedef epair_t** (* PFN_GETENTITYKEYVALLIST) (entity_t *e);
+typedef void (* PFN_SETENTITYKEYVALLIST) (entity_t *e, epair_t* ep);
+
+
+struct _QEREntityTable
+{
+  int m_nSize;
+  PFN_ENTITYALLOC m_pfnEntity_Alloc;
+  PFN_ENTITYFREE m_pfnEntity_Free;
+  PFN_ENTITYCREATE m_pfnEntity_Create;
+  PFN_ENTITYCLONE m_pfnEntity_Clone;
+  PFN_ENTITYSETKEYVALUE m_pfnSetKeyValue;
+  PFN_ENTITYDELETEKEY m_pfnDeleteKey;
+  PFN_ENTITYVALUEFORKEY m_pfnValueForKey;
+  PFN_ENTITYFLOATFORKEY m_pfnFloatForKey;
+  PFN_ENTITYINTFORKEY m_pfnIntForKey;
+  PFN_ENTITYVECTORFORKEY m_pfnGetVectorForKey;
+  PFN_ENTITYADDTOLIST m_pfnEntity_AddToList;
+  PFN_ENTITYREMOVEFROMLIST m_pfnEntity_RemoveFromList;
+  PFN_ENTITYLINKBRUSH m_pfnEntity_LinkBrush;
+  PFN_ENTITYUNLINKBRUSH m_pfnEntity_UnlinkBrush;
+  PFN_ENTITYDRAWLIGHT m_pfnDrawLight;
+  PFN_ENTITYMEMORYSIZE m_pfnEntity_MemorySize;
+  PFN_ALLOCATEEPAIR m_pfnAllocateEpair;
+  PFN_GETENTITYKEYVALLIST m_pfnGetEntityKeyValList;
+  PFN_SETENTITYKEYVALLIST m_pfnSetEntityKeyValList;
+};
+
+#ifdef USE_ENTITYTABLE_DEFINE
+#ifndef __ENTITYTABLENAME
+#define __ENTITYTABLENAME g_EntityTable
+#endif
+#define Entity_Alloc __ENTITYTABLENAME.m_pfnEntity_Alloc
+#define Entity_Free __ENTITYTABLENAME.m_pfnEntity_Free
+#define Entity_Clone __ENTITYTABLENAME.m_pfnEntity_Clone
+#define SetKeyValue __ENTITYTABLENAME.m_pfnSetKeyValue
+#define DeleteKey __ENTITYTABLENAME.m_pfnDeleteKey
+#define ValueForKey __ENTITYTABLENAME.m_pfnValueForKey
+#define FloatForKey __ENTITYTABLENAME.m_pfnFloatForKey
+#define IntForKey __ENTITYTABLENAME.m_pfnIntForKey
+#define GetVectorForKey __ENTITYTABLENAME.m_pfnGetVectorForKey
+#define Entity_AddToList __ENTITYTABLENAME.m_pfnEntity_AddToList
+#define Entity_RemoveFromList __ENTITYTABLENAME.m_pfnEntity_RemoveFromList
+#define Entity_LinkBrush __ENTITYTABLENAME.m_pfnEntity_LinkBrush
+#define Entity_UnlinkBrush __ENTITYTABLENAME.m_pfnEntity_UnlinkBrush
+#define DrawLight __ENTITYTABLENAME.m_pfnDrawLight
+#define Entity_MemorySize __ENTITYTABLENAME.m_pfnEntity_MemorySize
+#define Entity_AllocateEpair __ENTITYTABLENAME.m_pfnAllocateEpair
+#define Entity_GetKeyValList __ENTITYTABLENAME.m_pfnGetEntityKeyValList
+#define Entity_SetKeyValList __ENTITYTABLENAME.m_pfnSetEntityKeyValList
+#endif
+
+#endif
+
diff --git a/include/ifilesystem.h b/include/ifilesystem.h
index 8a9a2006..e9c3e725 100644
--- a/include/ifilesystem.h
+++ b/include/ifilesystem.h
@@ -1,140 +1,140 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IFILESYSTEM_H_
-#define _IFILESYSTEM_H_
-
-//
-// Plugin interface for the virtual filesystem used by Radiant
-//
-
-// NOTE: If you want to write a VFS plugin then you must export
-// "QERPlug_ListInterfaces" and "QERPlug_RequestInterface"
-// (see qerplugin.h for more information)
-
-#ifdef _WIN32
-#define VFS_NATIVESEPARATOR '\\'
-#else
-#define VFS_NATIVESEPARATOR '/'
-#endif
-
-#define VFS_MAJOR "VFS"
-
-// return the file system supported by the plugin, for example: "quake1" or "quake3"
-//typedef const char* (WINAPI* PFN_VFSGETFORMAT) ();
-// add all files from a directory to the vfs
-typedef void (* PFN_VFSINITDIRECTORY) (const char *path);
-// free all resources used by the plugin
-typedef void (* PFN_VFSSHUTDOWN) ();
-// free memory allocated by VFS for this pointer
-typedef void (* PFN_VFSFREEFILE) (void *p);
-// return a GSList with all the directories under basedir 
-typedef GSList* (* PFN_VFSGETDIRLIST) (const char *basedir);
-// return a GSList with all the files under basedir (extension can be NULL)
-typedef GSList* (* PFN_VFSGETFILELIST) (const char *basedir, const char *extension);
-// free a dirlist or filelist returned from one of the above functions
-typedef void (* PFN_VFSCLEARFILEDIRLIST) (GSList **lst);
-#define VFS_SEARCH_PAK 0x1
-#define VFS_SEARCH_DIR 0x2
-/*!
-\brief return the number of files with the exact name described in filename
-there can be several hits for a given file, or this can be used to check for existence
-\param flags is optional and can be used with VFS_SEARCH_* bits, if flag is 0, everything is searched, else only the specified bits
-paks are searched first, then search directories
-*/
-typedef int (* PFN_VFSGETFILECOUNT) (const char *filename, int flags);
-/*!
-\brief load file, allocate buffer
-\return -1 if fails or the size of the buffer allocated
-\param index is used to load the i-th file in the search directories (see vfsGetFileCount)
-this will scan in the search directories first, then it will search in the pak files
-WARNING: the allocated buffer must be freed with a g_free call
-NOTE TTimo: the g_free release is utter horror
- see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
-*/
-typedef int (* PFN_VFSLOADFILE) (const char *filename, void **buffer, int index);
-// load a file from it's full path into the buffer, returns the file size or -1
-// the allocated buffer must be freed with a g_free call
-typedef int (* PFN_VFSLOADFULLPATHFILE) (const char *filename, void **buffer);
-// takes an absolute file path, returns a shortened relative file path if the absolute path matches a valid basedir or NULL if an error occured
-typedef char* (* PFN_VFSEXTRACTRELATIVEPATH) (const char *in);
-/*!
-\return the full path (in a static buff) to a file given it's relative path (NULL if not found)
-\param index if several files are matching (as returned in a call to vfsGetFileCount), get the index-th file
-\param flag 0 or a combination of VFS_SEARCH_PAK or VFS_SEARCH_DIR
-HYDRA:
-  this now searches VFS/PAK files in addition to the filesystem
-  if FLAG is 0 then ONLY dirs are searched.
-  PAK's are searched before DIRs to mimic engine behaviour
-  index is ignored when searching PAK files.
-  when searching VFS, files are searched case insensitive.
-
-WARNING: if you use index from vfsGetFileCount, it works only with a vfsGetFileCount for the search directories only (not the pak files)
-FIXME TTimo our VFS names are case insensitive.
-   this function is not able to build the full path from case-insensitive name
-   ( this is http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=130 )
-*/
-typedef char* (* PFN_VFSGETFULLPATH) (const char *in, int index, int flag);
-/*!
-these return a static char*, doesn't need to be freed or anything
-get the base path to use when raising file dialogs
-we manually add "maps/" or "sounds/" or "mapobjects/models/" etc.
-FIXME: I'm not sure this is used / relevant anymore
-*/
-typedef const char* (* PFN_VFSBASEPROMPTPATH) ();
-
-// VFS API
-struct _QERFileSystemTable
-{
-  int m_nSize;
-  PFN_VFSINITDIRECTORY        m_pfnInitDirectory;
-  PFN_VFSSHUTDOWN             m_pfnShutdown;
-  PFN_VFSFREEFILE             m_pfnFreeFile;
-  PFN_VFSGETDIRLIST           m_pfnGetDirList;
-  PFN_VFSGETFILELIST          m_pfnGetFileList;
-  PFN_VFSCLEARFILEDIRLIST     m_pfnClearFileDirList;
-  PFN_VFSGETFILECOUNT         m_pfnGetFileCount;
-  PFN_VFSLOADFILE             m_pfnLoadFile;
-  PFN_VFSLOADFULLPATHFILE     m_pfnLoadFullPathFile;
-  PFN_VFSEXTRACTRELATIVEPATH  m_pfnExtractRelativePath;
-  PFN_VFSGETFULLPATH          m_pfnGetFullPath;
-  PFN_VFSBASEPROMPTPATH       m_pfnBasePromptPath;
-};
-
-#ifdef USE_VFSTABLE_DEFINE
-#ifndef __VFSTABLENAME
-#define __VFSTABLENAME g_FileSystemTable
-#endif
-#define vfsInitDirectory __VFSTABLENAME.m_pfnInitDirectory
-#define vfsShutdown __VFSTABLENAME.m_pfnShutdown
-#define vfsFreeFile __VFSTABLENAME.m_pfnFreeFile
-#define vfsGetDirList __VFSTABLENAME.m_pfnGetDirList
-#define vfsGetFileList __VFSTABLENAME.m_pfnGetFileList
-#define vfsClearFileDirList __VFSTABLENAME.m_pfnClearFileDirList
-#define vfsGetFileCount __VFSTABLENAME.m_pfnGetFileCount
-#define vfsLoadFile __VFSTABLENAME.m_pfnLoadFile
-#define vfsLoadFullPathFile __VFSTABLENAME.m_pfnLoadFullPathFile
-#define vfsExtractRelativePath __VFSTABLENAME.m_pfnExtractRelativePath
-#define vfsGetFullPath __VFSTABLENAME.m_pfnGetFullPath
-#define vfsBasePromptPath __VFSTABLENAME.m_pfnBasePromptPath
-#endif
-
-#endif // _IFILESYSTEM_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IFILESYSTEM_H_
+#define _IFILESYSTEM_H_
+
+//
+// Plugin interface for the virtual filesystem used by Radiant
+//
+
+// NOTE: If you want to write a VFS plugin then you must export
+// "QERPlug_ListInterfaces" and "QERPlug_RequestInterface"
+// (see qerplugin.h for more information)
+
+#ifdef _WIN32
+#define VFS_NATIVESEPARATOR '\\'
+#else
+#define VFS_NATIVESEPARATOR '/'
+#endif
+
+#define VFS_MAJOR "VFS"
+
+// return the file system supported by the plugin, for example: "quake1" or "quake3"
+//typedef const char* (WINAPI* PFN_VFSGETFORMAT) ();
+// add all files from a directory to the vfs
+typedef void (* PFN_VFSINITDIRECTORY) (const char *path);
+// free all resources used by the plugin
+typedef void (* PFN_VFSSHUTDOWN) ();
+// free memory allocated by VFS for this pointer
+typedef void (* PFN_VFSFREEFILE) (void *p);
+// return a GSList with all the directories under basedir 
+typedef GSList* (* PFN_VFSGETDIRLIST) (const char *basedir);
+// return a GSList with all the files under basedir (extension can be NULL)
+typedef GSList* (* PFN_VFSGETFILELIST) (const char *basedir, const char *extension);
+// free a dirlist or filelist returned from one of the above functions
+typedef void (* PFN_VFSCLEARFILEDIRLIST) (GSList **lst);
+#define VFS_SEARCH_PAK 0x1
+#define VFS_SEARCH_DIR 0x2
+/*!
+\brief return the number of files with the exact name described in filename
+there can be several hits for a given file, or this can be used to check for existence
+\param flags is optional and can be used with VFS_SEARCH_* bits, if flag is 0, everything is searched, else only the specified bits
+paks are searched first, then search directories
+*/
+typedef int (* PFN_VFSGETFILECOUNT) (const char *filename, int flags);
+/*!
+\brief load file, allocate buffer
+\return -1 if fails or the size of the buffer allocated
+\param index is used to load the i-th file in the search directories (see vfsGetFileCount)
+this will scan in the search directories first, then it will search in the pak files
+WARNING: the allocated buffer must be freed with a g_free call
+NOTE TTimo: the g_free release is utter horror
+ see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=491
+*/
+typedef int (* PFN_VFSLOADFILE) (const char *filename, void **buffer, int index);
+// load a file from it's full path into the buffer, returns the file size or -1
+// the allocated buffer must be freed with a g_free call
+typedef int (* PFN_VFSLOADFULLPATHFILE) (const char *filename, void **buffer);
+// takes an absolute file path, returns a shortened relative file path if the absolute path matches a valid basedir or NULL if an error occured
+typedef char* (* PFN_VFSEXTRACTRELATIVEPATH) (const char *in);
+/*!
+\return the full path (in a static buff) to a file given it's relative path (NULL if not found)
+\param index if several files are matching (as returned in a call to vfsGetFileCount), get the index-th file
+\param flag 0 or a combination of VFS_SEARCH_PAK or VFS_SEARCH_DIR
+HYDRA:
+  this now searches VFS/PAK files in addition to the filesystem
+  if FLAG is 0 then ONLY dirs are searched.
+  PAK's are searched before DIRs to mimic engine behaviour
+  index is ignored when searching PAK files.
+  when searching VFS, files are searched case insensitive.
+
+WARNING: if you use index from vfsGetFileCount, it works only with a vfsGetFileCount for the search directories only (not the pak files)
+FIXME TTimo our VFS names are case insensitive.
+   this function is not able to build the full path from case-insensitive name
+   ( this is http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=130 )
+*/
+typedef char* (* PFN_VFSGETFULLPATH) (const char *in, int index, int flag);
+/*!
+these return a static char*, doesn't need to be freed or anything
+get the base path to use when raising file dialogs
+we manually add "maps/" or "sounds/" or "mapobjects/models/" etc.
+FIXME: I'm not sure this is used / relevant anymore
+*/
+typedef const char* (* PFN_VFSBASEPROMPTPATH) ();
+
+// VFS API
+struct _QERFileSystemTable
+{
+  int m_nSize;
+  PFN_VFSINITDIRECTORY        m_pfnInitDirectory;
+  PFN_VFSSHUTDOWN             m_pfnShutdown;
+  PFN_VFSFREEFILE             m_pfnFreeFile;
+  PFN_VFSGETDIRLIST           m_pfnGetDirList;
+  PFN_VFSGETFILELIST          m_pfnGetFileList;
+  PFN_VFSCLEARFILEDIRLIST     m_pfnClearFileDirList;
+  PFN_VFSGETFILECOUNT         m_pfnGetFileCount;
+  PFN_VFSLOADFILE             m_pfnLoadFile;
+  PFN_VFSLOADFULLPATHFILE     m_pfnLoadFullPathFile;
+  PFN_VFSEXTRACTRELATIVEPATH  m_pfnExtractRelativePath;
+  PFN_VFSGETFULLPATH          m_pfnGetFullPath;
+  PFN_VFSBASEPROMPTPATH       m_pfnBasePromptPath;
+};
+
+#ifdef USE_VFSTABLE_DEFINE
+#ifndef __VFSTABLENAME
+#define __VFSTABLENAME g_FileSystemTable
+#endif
+#define vfsInitDirectory __VFSTABLENAME.m_pfnInitDirectory
+#define vfsShutdown __VFSTABLENAME.m_pfnShutdown
+#define vfsFreeFile __VFSTABLENAME.m_pfnFreeFile
+#define vfsGetDirList __VFSTABLENAME.m_pfnGetDirList
+#define vfsGetFileList __VFSTABLENAME.m_pfnGetFileList
+#define vfsClearFileDirList __VFSTABLENAME.m_pfnClearFileDirList
+#define vfsGetFileCount __VFSTABLENAME.m_pfnGetFileCount
+#define vfsLoadFile __VFSTABLENAME.m_pfnLoadFile
+#define vfsLoadFullPathFile __VFSTABLENAME.m_pfnLoadFullPathFile
+#define vfsExtractRelativePath __VFSTABLENAME.m_pfnExtractRelativePath
+#define vfsGetFullPath __VFSTABLENAME.m_pfnGetFullPath
+#define vfsBasePromptPath __VFSTABLENAME.m_pfnBasePromptPath
+#endif
+
+#endif // _IFILESYSTEM_H_
diff --git a/include/igl.h b/include/igl.h
index 99e4141f..630d3d34 100644
--- a/include/igl.h
+++ b/include/igl.h
@@ -1,266 +1,266 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-//
-// DESCRIPTION:
-// all purpose OpenGL interface for Q3Radiant plugins
-//
-
-#ifndef __IGL_H__
-#define __IGL_H__
-
-#if defined (__linux__) || defined (__APPLE__)
-#include <GL/glx.h>
-#endif
-
-// we use these classes to let plugins draw inside the Radiant windows
-// 2D window like YZ XZ XY
-class IGL2DWindow
-{
-public:
-	// Increment the number of references to this object
-	virtual void IncRef () = 0;
-	// Decrement the reference count
-	virtual void DecRef () = 0;
-	virtual void Draw2D( VIEWTYPE vt ) = 0;
-};
-
-// 3D window
-class IGL3DWindow
-{
-public:
-  // Increment the number of references to this object
-  virtual void IncRef () = 0;
-  // Decrement the reference count
-  virtual void DecRef () = 0;
-  virtual void Draw3D() = 0;
-};
-
-#define QGL_MAJOR "qgl"
-
-#include <GL/gl.h>
-
-typedef void (APIENTRY* PFN_QGLALPHAFUNC) (GLenum func, GLclampf ref);
-typedef void (APIENTRY* PFN_QGLBEGIN) (GLenum);
-typedef void (APIENTRY* PFN_QGLBINDTEXTURE) (GLenum target, GLuint texture);
-typedef void (APIENTRY* PFN_QGLBLENDFUNC) (GLenum sfactor, GLenum dfactor);
-typedef void (APIENTRY* PFN_QGLCALLLIST) (GLuint list);
-typedef void (APIENTRY* PFN_QGLCALLLISTS) (GLsizei n, GLenum type, const GLvoid *lists);
-typedef void (APIENTRY* PFN_QGLCLEAR) (GLbitfield mask);
-typedef void (APIENTRY* PFN_QGLCLEARCOLOR) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-typedef void (APIENTRY* PFN_QGLCLEARDEPTH) (GLclampd depth);
-typedef void (APIENTRY* PFN_QGLCOLOR3F)	(GLfloat red, GLfloat green, GLfloat blue);
-typedef void (APIENTRY* PFN_QGLCOLOR3FV) (const GLfloat *v);
-typedef void (APIENTRY* PFN_QGLCOLOR4F) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-typedef void (APIENTRY* PFN_QGLCOLOR4FV) (const GLfloat *v);
-typedef void (APIENTRY* PFN_QGLCOLOR4UBV) (const GLubyte *v);
-typedef void (APIENTRY* PFN_QGLCOLORPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-typedef void (APIENTRY* PFN_QGLCULLFACE) (GLenum mode);
-typedef void (APIENTRY* PFN_QGLDELETELISTS) (GLuint list, GLsizei range);
-typedef void (APIENTRY* PFN_QGLDELETETEXTURES)  (GLsizei n, const GLuint *textures);
-typedef void (APIENTRY* PFN_QGLDEPTHFUNC) (GLenum func);
-typedef void (APIENTRY* PFN_QGLDEPTHMASK) (GLboolean flag);
-typedef void (APIENTRY* PFN_QGLDISABLE) (GLenum cap);
-typedef void (APIENTRY* PFN_QGLDISABLECLIENTSTATE) (GLenum array);
-typedef void (APIENTRY* PFN_QGLDRAWELEMENTS) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-typedef void (APIENTRY* PFN_QGLENABLE) (GLenum cap);
-typedef void (APIENTRY* PFN_QGLENABLECLIENTSTATE) (GLenum array);
-typedef void (APIENTRY* PFN_QGLEND) ();
-typedef void (APIENTRY* PFN_QGLENDLIST) ();
-typedef void (APIENTRY* PFN_QGLFOGF) (GLenum pname, GLfloat param);
-typedef void (APIENTRY* PFN_QGLFOGFV) (GLenum pname, const GLfloat *params);
-typedef void (APIENTRY* PFN_QGLFOGFI) (GLenum pname, GLint param);
-typedef GLuint (APIENTRY* PFN_QGLGENLISTS) (GLsizei range);
-typedef void (APIENTRY *PFN_QGLGENTEXTURES) (GLsizei n, GLuint *textures);
-typedef void (APIENTRY* PFN_QGLGETDOUBLEV) (GLenum pname, GLdouble *params);
-typedef void (APIENTRY* PFN_QGLHINT) (GLenum target, GLenum mode);
-typedef void (APIENTRY* PFN_QGLGETINTEGERV) (GLenum pname, GLint *params);
-typedef void (APIENTRY* PFN_QGLLIGHTFV) (GLenum light, GLenum pname, const GLfloat *params);
-typedef void (APIENTRY* PFN_QGLLINEWIDTH) (GLfloat size);
-typedef void (APIENTRY* PFN_QGLLINESTIPPLE) (GLint factor, GLushort pattern);
-typedef void (APIENTRY* PFN_QGLLINEWIDTH)       (GLfloat size);
-typedef void (APIENTRY* PFN_QGLLISTBASE) (GLuint base);
-typedef void (APIENTRY* PFN_QGLLOADIDENTITY) ();
-typedef void (APIENTRY* PFN_QGLMATERIALF) (GLenum face, GLenum pname, GLfloat param);
-typedef void (APIENTRY* PFN_QGLMATERIALFV) (GLenum face, GLenum pname, const GLfloat *params);
-typedef void (APIENTRY* PFN_QGLMATRIXMODE) (GLenum mode);
-typedef void (APIENTRY* PFN_QGLMULTMATRIXF)    (const GLfloat *m);
-typedef void (APIENTRY* PFN_QGLNEWLIST) (GLuint list, GLenum mode);
-typedef void (APIENTRY* PFN_QGLNORMAL3F) (GLfloat nx, GLfloat ny, GLfloat nz);
-typedef void (APIENTRY* PFN_QGLNORMAL3FV) (const GLfloat *n);
-typedef void (APIENTRY* PFN_QGLNORMALPOINTER) (GLenum type, GLsizei stride, const GLvoid *pointer);
-typedef void (APIENTRY* PFN_QGLORTHO) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-typedef void (APIENTRY*	PFN_QGLPOINTSIZE) (GLfloat size);
-typedef void (APIENTRY* PFN_QGLPOLYGONMODE) (GLenum face, GLenum mode);
-typedef void (APIENTRY* PFN_QGLPOPATTRIB) ();
-typedef void (APIENTRY* PFN_QGLPOPMATRIX) ();
-typedef void (APIENTRY* PFN_QGLPUSHATTRIB) (GLbitfield mask);
-typedef void (APIENTRY* PFN_QGLPUSHMATRIX) ();
-typedef void (APIENTRY* PFN_QGLRASTERPOS3FV) (const GLfloat *v);
-typedef void (APIENTRY* PFN_QGLROTATED) (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
-typedef void (APIENTRY* PFN_QGLROTATEF)	(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-typedef void (APIENTRY* PFN_QGLSCALEF)			(GLfloat x, GLfloat y, GLfloat z);
-typedef void (APIENTRY* PFN_QGLSCISSOR) (GLint x, GLint y, GLsizei width, GLsizei height);
-typedef void (APIENTRY* PFN_QGLSCALEF) (GLfloat x, GLfloat y, GLfloat z);
-typedef void (APIENTRY* PFN_QGLSHADEMODEL) (GLenum mode);
-typedef void (APIENTRY* PFN_QGLTEXCOORD2F) (GLfloat s, GLfloat t);
-typedef void (APIENTRY* PFN_QGLTEXCOORD2FV) (const GLfloat *v);
-typedef void (APIENTRY* PFN_QGLTEXCOORDPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-typedef void (APIENTRY* PFN_QGLTEXENVF) (GLenum target, GLenum pname, GLfloat param);
-typedef void (APIENTRY* PFN_QGLTEXGENF) (GLenum coord, GLenum pname, GLfloat param);
-typedef void (APIENTRY* PFN_QGLTEXIMAGE1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-typedef void (APIENTRY* PFN_QGLTEXIMAGE2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-typedef void (APIENTRY* PFN_QGLTEXPARAMETERF) (GLenum target, GLenum pname, GLfloat param);
-typedef void (APIENTRY* PFN_QGLTEXPARAMETERFV) (GLenum target, GLenum pname, const GLfloat *params);
-typedef void (APIENTRY* PFN_QGLTEXPARAMETERI) (GLenum target, GLenum pname, GLint param);
-typedef void (APIENTRY* PFN_QGLTEXPARAMETERIV) (GLenum target, GLenum pname, const GLint *params);
-typedef void (APIENTRY* PFN_QGLTEXSUBIMAGE1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
-typedef void (APIENTRY* PFN_QGLTEXSUBIMAGE2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-typedef void (APIENTRY* PFN_QGLTRANSLATED) (GLdouble x, GLdouble y, GLdouble z);
-typedef void (APIENTRY* PFN_QGLTRANSLATEF) (GLfloat x, GLfloat y, GLfloat z);
-typedef void (APIENTRY* PFN_QGLVERTEX2F) (GLfloat x, GLfloat y);
-typedef void (APIENTRY* PFN_QGLVERTEX3F) (GLfloat x, GLfloat y, GLfloat z);
-typedef void (APIENTRY* PFN_QGLVERTEX3FV) (const GLfloat *v);
-typedef void (APIENTRY* PFN_QGLVERTEXPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-typedef void (APIENTRY* PFN_QGLVIEWPORT) (GLint x, GLint y, GLsizei width, GLsizei height);
-
-typedef void (WINAPI* PFN_QE_CHECKOPENGLFORERRORS)	();
-
-// glu stuff
-// TTimo: NOTE: relying on glu might not be such a good idea. On many systems, the GLU lib is outdated, misversioned etc.
-typedef void (APIENTRY * PFN_QGLUPERSPECTIVE) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
-typedef void (APIENTRY * PFN_QGLULOOKAT) (GLdouble eyex, GLdouble eyey, GLdouble eyez,
-                                          GLdouble centerx, GLdouble centery, GLdouble centerz,
-                                          GLdouble upx, GLdouble upy, GLdouble upz);
-//++timo gluErrorString is defined but not exposed in the IGL interface
-
-
-// plugins drawing inside the GL windows
-//++timo TODO: add hooking into other windows (Z and .. texture??)
-//+timo NOTE: this could be moved to the messaging system instead of having a dedicated interface <- yet I don't know how
-typedef void (WINAPI* PFN_QERAPP_HOOKGL2DWINDOW) (IGL2DWindow *);
-typedef void (WINAPI* PFN_QERAPP_UNHOOKGL2DWINDOW) (IGL2DWindow *);
-typedef void (WINAPI* PFN_QERAPP_HOOKGL3DWINDOW) (IGL3DWindow *);
-typedef void (WINAPI* PFN_QERAPP_UNHOOKGL3DWINDOW) (IGL3DWindow *);
-
-struct _QERQglTable
-{
-  //++timo do we really wanna play with versions ?
-  //	float m_fVersion;
-  int m_nSize;
-  PFN_QGLALPHAFUNC		m_pfn_qglAlphaFunc;
-  PFN_QGLBEGIN			m_pfn_qglBegin;
-  PFN_QGLBINDTEXTURE		m_pfn_qglBindTexture;
-  PFN_QGLBLENDFUNC		m_pfn_qglBlendFunc;
-  PFN_QGLCALLLIST			m_pfn_qglCallList;
-  PFN_QGLCLEAR			m_pfn_qglClear;
-  PFN_QGLCLEARCOLOR		m_pfn_qglClearColor;
-  PFN_QGLCALLLISTS		m_pfn_qglCallLists;
-  PFN_QGLCLEARDEPTH		m_pfn_qglClearDepth;
-  PFN_QGLCOLOR3F			m_pfn_qglColor3f;
-  PFN_QGLCOLOR3FV         m_pfn_qglColor3fv;
-  PFN_QGLCOLOR4F			m_pfn_qglColor4f;
-  PFN_QGLCOLOR4FV         m_pfn_qglColor4fv;
-  PFN_QGLCOLOR4UBV        m_pfn_qglColor4ubv;	// ydnar
-  PFN_QGLCOLORPOINTER     m_pfn_qglColorPointer;
-  PFN_QGLCULLFACE			m_pfn_qglCullFace;
-  PFN_QGLDELETELISTS		m_pfn_qglDeleteLists;
-  PFN_QGLDELETETEXTURES  m_pfn_qglDeleteTextures;
-  PFN_QGLDEPTHFUNC        m_pfn_qglDepthFunc;
-  PFN_QGLDEPTHMASK        m_pfn_qglDepthMask;
-  PFN_QGLDISABLE			m_pfn_qglDisable;
-  PFN_QGLDISABLECLIENTSTATE m_pfn_qglDisableClientState;
-  PFN_QGLDRAWELEMENTS			m_pfn_qglDrawElements;
-  PFN_QGLENABLE			m_pfn_qglEnable;
-  PFN_QGLENABLECLIENTSTATE  m_pfn_qglEnableClientState;
-  PFN_QGLEND				m_pfn_qglEnd;
-  PFN_QGLENDLIST			m_pfn_qglEndList;
-  PFN_QGLFOGF              m_pfn_qglFogf;
-  PFN_QGLFOGFV             m_pfn_qglFogfv;
-  PFN_QGLFOGFI             m_pfn_qglFogi;
-  PFN_QGLGENLISTS			m_pfn_qglGenLists;
-  PFN_QGLGENTEXTURES  m_pfn_qglGenTextures;
-  PFN_QGLGETDOUBLEV			m_pfn_qglGetDoublev;
-  PFN_QGLGETINTEGERV      m_pfn_qglGetIntegerv;
-  PFN_QGLHINT             m_pfn_qglHint;
-  PFN_QGLLIGHTFV          m_pfn_qglLightfv;
-  PFN_QGLLINESTIPPLE      m_pfn_qglLineStipple;
-  PFN_QGLLINEWIDTH        m_pfn_qglLineWidth;
-  PFN_QGLLISTBASE			m_pfn_qglListBase;
-  PFN_QGLLOADIDENTITY		m_pfn_qglLoadIdentity;
-  PFN_QGLMATERIALF		m_pfn_qglMaterialf;
-  PFN_QGLMATERIALFV       m_pfn_qglMaterialfv;
-  PFN_QGLMATRIXMODE		m_pfn_qglMatrixMode;
-  PFN_QGLMULTMATRIXF  m_pfn_qglMultMatrixf;
-  PFN_QGLNEWLIST			m_pfn_qglNewList;
-  PFN_QGLNORMAL3F			m_pfn_qglNormal3f;
-  PFN_QGLNORMAL3FV			m_pfn_qglNormal3fv;
-	PFN_QGLNORMALPOINTER		m_pfn_qglNormalPointer;
-  PFN_QGLORTHO			m_pfn_qglOrtho;
-  PFN_QGLPOINTSIZE		m_pfn_qglPointSize;
-  PFN_QGLPOLYGONMODE		m_pfn_qglPolygonMode;
-  PFN_QGLPOPATTRIB		m_pfn_qglPopAttrib;
-  PFN_QGLPOPMATRIX		m_pfn_qglPopMatrix;
-  PFN_QGLPUSHATTRIB		m_pfn_qglPushAttrib;
-  PFN_QGLPUSHMATRIX		m_pfn_qglPushMatrix;
-	PFN_QGLRASTERPOS3FV	m_pfn_qglRasterPos3fv;
-  PFN_QGLROTATED			m_pfn_qglRotated;
-  PFN_QGLROTATEF			m_pfn_qglRotatef;
-  PFN_QGLSCALEF			m_pfn_qglScalef;
-  PFN_QGLSCISSOR        m_pfn_qglScissor;
-  PFN_QGLSHADEMODEL		m_pfn_qglShadeModel;
-  PFN_QGLTEXCOORD2F		m_pfn_qglTexCoord2f;
-  PFN_QGLTEXCOORD2FV      m_pfn_qglTexCoord2fv;
-	PFN_QGLTEXCOORDPOINTER		m_pfn_qglTexCoordPointer;
-  PFN_QGLTEXENVF			m_pfn_qglTexEnvf;
-  PFN_QGLTEXGENF			m_pfn_qglTexGenf;
-  PFN_QGLTEXIMAGE1D     m_pfn_qglTexImage1D;
-  PFN_QGLTEXIMAGE2D     m_pfn_qglTexImage2D;
-  PFN_QGLTEXPARAMETERF  m_pfn_qglTexParameterf;
-  PFN_QGLTEXPARAMETERFV m_pfn_qglTexParameterfv;
-  PFN_QGLTEXPARAMETERI  m_pfn_qglTexParameteri;
-  PFN_QGLTEXPARAMETERIV m_pfn_qglTexParameteriv;
-  PFN_QGLTEXSUBIMAGE1D  m_pfn_qglTexSubImage1D;
-  PFN_QGLTEXSUBIMAGE2D  m_pfn_qglTexSubImage2D;
-  PFN_QGLTRANSLATED		m_pfn_qglTranslated;
-  PFN_QGLTRANSLATEF		m_pfn_qglTranslatef;
-  PFN_QGLVERTEX2F			m_pfn_qglVertex2f;
-  PFN_QGLVERTEX3F			m_pfn_qglVertex3f;
-  PFN_QGLVERTEX3FV        m_pfn_qglVertex3fv;
-	PFN_QGLVERTEXPOINTER		m_pfn_qglVertexPointer;
-  PFN_QGLVIEWPORT			m_pfn_qglViewport;
-
-  PFN_QE_CHECKOPENGLFORERRORS	m_pfn_QE_CheckOpenGLForErrors;
-
-  // glu stuff
-  PFN_QGLUPERSPECTIVE			m_pfn_qgluPerspective;
-  PFN_QGLULOOKAT				m_pfn_qgluLookAt;
-
-  // plugin entities drawing inside Radiant windows
-  PFN_QERAPP_HOOKGL2DWINDOW	m_pfnHookGL2DWindow;
-  PFN_QERAPP_UNHOOKGL2DWINDOW	m_pfnUnHookGL2DWindow;
-  PFN_QERAPP_HOOKGL3DWINDOW m_pfnHookGL3DWindow;
-  PFN_QERAPP_UNHOOKGL3DWINDOW m_pfnUnHookGL3DWindow;
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+//
+// DESCRIPTION:
+// all purpose OpenGL interface for Q3Radiant plugins
+//
+
+#ifndef __IGL_H__
+#define __IGL_H__
+
+#if defined (__linux__) || defined (__APPLE__)
+#include <GL/glx.h>
+#endif
+
+// we use these classes to let plugins draw inside the Radiant windows
+// 2D window like YZ XZ XY
+class IGL2DWindow
+{
+public:
+	// Increment the number of references to this object
+	virtual void IncRef () = 0;
+	// Decrement the reference count
+	virtual void DecRef () = 0;
+	virtual void Draw2D( VIEWTYPE vt ) = 0;
+};
+
+// 3D window
+class IGL3DWindow
+{
+public:
+  // Increment the number of references to this object
+  virtual void IncRef () = 0;
+  // Decrement the reference count
+  virtual void DecRef () = 0;
+  virtual void Draw3D() = 0;
+};
+
+#define QGL_MAJOR "qgl"
+
+#include <GL/gl.h>
+
+typedef void (APIENTRY* PFN_QGLALPHAFUNC) (GLenum func, GLclampf ref);
+typedef void (APIENTRY* PFN_QGLBEGIN) (GLenum);
+typedef void (APIENTRY* PFN_QGLBINDTEXTURE) (GLenum target, GLuint texture);
+typedef void (APIENTRY* PFN_QGLBLENDFUNC) (GLenum sfactor, GLenum dfactor);
+typedef void (APIENTRY* PFN_QGLCALLLIST) (GLuint list);
+typedef void (APIENTRY* PFN_QGLCALLLISTS) (GLsizei n, GLenum type, const GLvoid *lists);
+typedef void (APIENTRY* PFN_QGLCLEAR) (GLbitfield mask);
+typedef void (APIENTRY* PFN_QGLCLEARCOLOR) (GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+typedef void (APIENTRY* PFN_QGLCLEARDEPTH) (GLclampd depth);
+typedef void (APIENTRY* PFN_QGLCOLOR3F)	(GLfloat red, GLfloat green, GLfloat blue);
+typedef void (APIENTRY* PFN_QGLCOLOR3FV) (const GLfloat *v);
+typedef void (APIENTRY* PFN_QGLCOLOR4F) (GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+typedef void (APIENTRY* PFN_QGLCOLOR4FV) (const GLfloat *v);
+typedef void (APIENTRY* PFN_QGLCOLOR4UBV) (const GLubyte *v);
+typedef void (APIENTRY* PFN_QGLCOLORPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRY* PFN_QGLCULLFACE) (GLenum mode);
+typedef void (APIENTRY* PFN_QGLDELETELISTS) (GLuint list, GLsizei range);
+typedef void (APIENTRY* PFN_QGLDELETETEXTURES)  (GLsizei n, const GLuint *textures);
+typedef void (APIENTRY* PFN_QGLDEPTHFUNC) (GLenum func);
+typedef void (APIENTRY* PFN_QGLDEPTHMASK) (GLboolean flag);
+typedef void (APIENTRY* PFN_QGLDISABLE) (GLenum cap);
+typedef void (APIENTRY* PFN_QGLDISABLECLIENTSTATE) (GLenum array);
+typedef void (APIENTRY* PFN_QGLDRAWELEMENTS) (GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+typedef void (APIENTRY* PFN_QGLENABLE) (GLenum cap);
+typedef void (APIENTRY* PFN_QGLENABLECLIENTSTATE) (GLenum array);
+typedef void (APIENTRY* PFN_QGLEND) ();
+typedef void (APIENTRY* PFN_QGLENDLIST) ();
+typedef void (APIENTRY* PFN_QGLFOGF) (GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLFOGFV) (GLenum pname, const GLfloat *params);
+typedef void (APIENTRY* PFN_QGLFOGFI) (GLenum pname, GLint param);
+typedef GLuint (APIENTRY* PFN_QGLGENLISTS) (GLsizei range);
+typedef void (APIENTRY *PFN_QGLGENTEXTURES) (GLsizei n, GLuint *textures);
+typedef void (APIENTRY* PFN_QGLGETDOUBLEV) (GLenum pname, GLdouble *params);
+typedef void (APIENTRY* PFN_QGLHINT) (GLenum target, GLenum mode);
+typedef void (APIENTRY* PFN_QGLGETINTEGERV) (GLenum pname, GLint *params);
+typedef void (APIENTRY* PFN_QGLLIGHTFV) (GLenum light, GLenum pname, const GLfloat *params);
+typedef void (APIENTRY* PFN_QGLLINEWIDTH) (GLfloat size);
+typedef void (APIENTRY* PFN_QGLLINESTIPPLE) (GLint factor, GLushort pattern);
+typedef void (APIENTRY* PFN_QGLLINEWIDTH)       (GLfloat size);
+typedef void (APIENTRY* PFN_QGLLISTBASE) (GLuint base);
+typedef void (APIENTRY* PFN_QGLLOADIDENTITY) ();
+typedef void (APIENTRY* PFN_QGLMATERIALF) (GLenum face, GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLMATERIALFV) (GLenum face, GLenum pname, const GLfloat *params);
+typedef void (APIENTRY* PFN_QGLMATRIXMODE) (GLenum mode);
+typedef void (APIENTRY* PFN_QGLMULTMATRIXF)    (const GLfloat *m);
+typedef void (APIENTRY* PFN_QGLNEWLIST) (GLuint list, GLenum mode);
+typedef void (APIENTRY* PFN_QGLNORMAL3F) (GLfloat nx, GLfloat ny, GLfloat nz);
+typedef void (APIENTRY* PFN_QGLNORMAL3FV) (const GLfloat *n);
+typedef void (APIENTRY* PFN_QGLNORMALPOINTER) (GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRY* PFN_QGLORTHO) (GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRY*	PFN_QGLPOINTSIZE) (GLfloat size);
+typedef void (APIENTRY* PFN_QGLPOLYGONMODE) (GLenum face, GLenum mode);
+typedef void (APIENTRY* PFN_QGLPOPATTRIB) ();
+typedef void (APIENTRY* PFN_QGLPOPMATRIX) ();
+typedef void (APIENTRY* PFN_QGLPUSHATTRIB) (GLbitfield mask);
+typedef void (APIENTRY* PFN_QGLPUSHMATRIX) ();
+typedef void (APIENTRY* PFN_QGLRASTERPOS3FV) (const GLfloat *v);
+typedef void (APIENTRY* PFN_QGLROTATED) (GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY* PFN_QGLROTATEF)	(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLSCALEF)			(GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLSCISSOR) (GLint x, GLint y, GLsizei width, GLsizei height);
+typedef void (APIENTRY* PFN_QGLSCALEF) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLSHADEMODEL) (GLenum mode);
+typedef void (APIENTRY* PFN_QGLTEXCOORD2F) (GLfloat s, GLfloat t);
+typedef void (APIENTRY* PFN_QGLTEXCOORD2FV) (const GLfloat *v);
+typedef void (APIENTRY* PFN_QGLTEXCOORDPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRY* PFN_QGLTEXENVF) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLTEXGENF) (GLenum coord, GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLTEXIMAGE1D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRY* PFN_QGLTEXIMAGE2D) (GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRY* PFN_QGLTEXPARAMETERF) (GLenum target, GLenum pname, GLfloat param);
+typedef void (APIENTRY* PFN_QGLTEXPARAMETERFV) (GLenum target, GLenum pname, const GLfloat *params);
+typedef void (APIENTRY* PFN_QGLTEXPARAMETERI) (GLenum target, GLenum pname, GLint param);
+typedef void (APIENTRY* PFN_QGLTEXPARAMETERIV) (GLenum target, GLenum pname, const GLint *params);
+typedef void (APIENTRY* PFN_QGLTEXSUBIMAGE1D) (GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRY* PFN_QGLTEXSUBIMAGE2D) (GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+typedef void (APIENTRY* PFN_QGLTRANSLATED) (GLdouble x, GLdouble y, GLdouble z);
+typedef void (APIENTRY* PFN_QGLTRANSLATEF) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLVERTEX2F) (GLfloat x, GLfloat y);
+typedef void (APIENTRY* PFN_QGLVERTEX3F) (GLfloat x, GLfloat y, GLfloat z);
+typedef void (APIENTRY* PFN_QGLVERTEX3FV) (const GLfloat *v);
+typedef void (APIENTRY* PFN_QGLVERTEXPOINTER) (GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+typedef void (APIENTRY* PFN_QGLVIEWPORT) (GLint x, GLint y, GLsizei width, GLsizei height);
+
+typedef void (WINAPI* PFN_QE_CHECKOPENGLFORERRORS)	();
+
+// glu stuff
+// TTimo: NOTE: relying on glu might not be such a good idea. On many systems, the GLU lib is outdated, misversioned etc.
+typedef void (APIENTRY * PFN_QGLUPERSPECTIVE) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+typedef void (APIENTRY * PFN_QGLULOOKAT) (GLdouble eyex, GLdouble eyey, GLdouble eyez,
+                                          GLdouble centerx, GLdouble centery, GLdouble centerz,
+                                          GLdouble upx, GLdouble upy, GLdouble upz);
+//++timo gluErrorString is defined but not exposed in the IGL interface
+
+
+// plugins drawing inside the GL windows
+//++timo TODO: add hooking into other windows (Z and .. texture??)
+//+timo NOTE: this could be moved to the messaging system instead of having a dedicated interface <- yet I don't know how
+typedef void (WINAPI* PFN_QERAPP_HOOKGL2DWINDOW) (IGL2DWindow *);
+typedef void (WINAPI* PFN_QERAPP_UNHOOKGL2DWINDOW) (IGL2DWindow *);
+typedef void (WINAPI* PFN_QERAPP_HOOKGL3DWINDOW) (IGL3DWindow *);
+typedef void (WINAPI* PFN_QERAPP_UNHOOKGL3DWINDOW) (IGL3DWindow *);
+
+struct _QERQglTable
+{
+  //++timo do we really wanna play with versions ?
+  //	float m_fVersion;
+  int m_nSize;
+  PFN_QGLALPHAFUNC		m_pfn_qglAlphaFunc;
+  PFN_QGLBEGIN			m_pfn_qglBegin;
+  PFN_QGLBINDTEXTURE		m_pfn_qglBindTexture;
+  PFN_QGLBLENDFUNC		m_pfn_qglBlendFunc;
+  PFN_QGLCALLLIST			m_pfn_qglCallList;
+  PFN_QGLCLEAR			m_pfn_qglClear;
+  PFN_QGLCLEARCOLOR		m_pfn_qglClearColor;
+  PFN_QGLCALLLISTS		m_pfn_qglCallLists;
+  PFN_QGLCLEARDEPTH		m_pfn_qglClearDepth;
+  PFN_QGLCOLOR3F			m_pfn_qglColor3f;
+  PFN_QGLCOLOR3FV         m_pfn_qglColor3fv;
+  PFN_QGLCOLOR4F			m_pfn_qglColor4f;
+  PFN_QGLCOLOR4FV         m_pfn_qglColor4fv;
+  PFN_QGLCOLOR4UBV        m_pfn_qglColor4ubv;	// ydnar
+  PFN_QGLCOLORPOINTER     m_pfn_qglColorPointer;
+  PFN_QGLCULLFACE			m_pfn_qglCullFace;
+  PFN_QGLDELETELISTS		m_pfn_qglDeleteLists;
+  PFN_QGLDELETETEXTURES  m_pfn_qglDeleteTextures;
+  PFN_QGLDEPTHFUNC        m_pfn_qglDepthFunc;
+  PFN_QGLDEPTHMASK        m_pfn_qglDepthMask;
+  PFN_QGLDISABLE			m_pfn_qglDisable;
+  PFN_QGLDISABLECLIENTSTATE m_pfn_qglDisableClientState;
+  PFN_QGLDRAWELEMENTS			m_pfn_qglDrawElements;
+  PFN_QGLENABLE			m_pfn_qglEnable;
+  PFN_QGLENABLECLIENTSTATE  m_pfn_qglEnableClientState;
+  PFN_QGLEND				m_pfn_qglEnd;
+  PFN_QGLENDLIST			m_pfn_qglEndList;
+  PFN_QGLFOGF              m_pfn_qglFogf;
+  PFN_QGLFOGFV             m_pfn_qglFogfv;
+  PFN_QGLFOGFI             m_pfn_qglFogi;
+  PFN_QGLGENLISTS			m_pfn_qglGenLists;
+  PFN_QGLGENTEXTURES  m_pfn_qglGenTextures;
+  PFN_QGLGETDOUBLEV			m_pfn_qglGetDoublev;
+  PFN_QGLGETINTEGERV      m_pfn_qglGetIntegerv;
+  PFN_QGLHINT             m_pfn_qglHint;
+  PFN_QGLLIGHTFV          m_pfn_qglLightfv;
+  PFN_QGLLINESTIPPLE      m_pfn_qglLineStipple;
+  PFN_QGLLINEWIDTH        m_pfn_qglLineWidth;
+  PFN_QGLLISTBASE			m_pfn_qglListBase;
+  PFN_QGLLOADIDENTITY		m_pfn_qglLoadIdentity;
+  PFN_QGLMATERIALF		m_pfn_qglMaterialf;
+  PFN_QGLMATERIALFV       m_pfn_qglMaterialfv;
+  PFN_QGLMATRIXMODE		m_pfn_qglMatrixMode;
+  PFN_QGLMULTMATRIXF  m_pfn_qglMultMatrixf;
+  PFN_QGLNEWLIST			m_pfn_qglNewList;
+  PFN_QGLNORMAL3F			m_pfn_qglNormal3f;
+  PFN_QGLNORMAL3FV			m_pfn_qglNormal3fv;
+	PFN_QGLNORMALPOINTER		m_pfn_qglNormalPointer;
+  PFN_QGLORTHO			m_pfn_qglOrtho;
+  PFN_QGLPOINTSIZE		m_pfn_qglPointSize;
+  PFN_QGLPOLYGONMODE		m_pfn_qglPolygonMode;
+  PFN_QGLPOPATTRIB		m_pfn_qglPopAttrib;
+  PFN_QGLPOPMATRIX		m_pfn_qglPopMatrix;
+  PFN_QGLPUSHATTRIB		m_pfn_qglPushAttrib;
+  PFN_QGLPUSHMATRIX		m_pfn_qglPushMatrix;
+	PFN_QGLRASTERPOS3FV	m_pfn_qglRasterPos3fv;
+  PFN_QGLROTATED			m_pfn_qglRotated;
+  PFN_QGLROTATEF			m_pfn_qglRotatef;
+  PFN_QGLSCALEF			m_pfn_qglScalef;
+  PFN_QGLSCISSOR        m_pfn_qglScissor;
+  PFN_QGLSHADEMODEL		m_pfn_qglShadeModel;
+  PFN_QGLTEXCOORD2F		m_pfn_qglTexCoord2f;
+  PFN_QGLTEXCOORD2FV      m_pfn_qglTexCoord2fv;
+	PFN_QGLTEXCOORDPOINTER		m_pfn_qglTexCoordPointer;
+  PFN_QGLTEXENVF			m_pfn_qglTexEnvf;
+  PFN_QGLTEXGENF			m_pfn_qglTexGenf;
+  PFN_QGLTEXIMAGE1D     m_pfn_qglTexImage1D;
+  PFN_QGLTEXIMAGE2D     m_pfn_qglTexImage2D;
+  PFN_QGLTEXPARAMETERF  m_pfn_qglTexParameterf;
+  PFN_QGLTEXPARAMETERFV m_pfn_qglTexParameterfv;
+  PFN_QGLTEXPARAMETERI  m_pfn_qglTexParameteri;
+  PFN_QGLTEXPARAMETERIV m_pfn_qglTexParameteriv;
+  PFN_QGLTEXSUBIMAGE1D  m_pfn_qglTexSubImage1D;
+  PFN_QGLTEXSUBIMAGE2D  m_pfn_qglTexSubImage2D;
+  PFN_QGLTRANSLATED		m_pfn_qglTranslated;
+  PFN_QGLTRANSLATEF		m_pfn_qglTranslatef;
+  PFN_QGLVERTEX2F			m_pfn_qglVertex2f;
+  PFN_QGLVERTEX3F			m_pfn_qglVertex3f;
+  PFN_QGLVERTEX3FV        m_pfn_qglVertex3fv;
+	PFN_QGLVERTEXPOINTER		m_pfn_qglVertexPointer;
+  PFN_QGLVIEWPORT			m_pfn_qglViewport;
+
+  PFN_QE_CHECKOPENGLFORERRORS	m_pfn_QE_CheckOpenGLForErrors;
+
+  // glu stuff
+  PFN_QGLUPERSPECTIVE			m_pfn_qgluPerspective;
+  PFN_QGLULOOKAT				m_pfn_qgluLookAt;
+
+  // plugin entities drawing inside Radiant windows
+  PFN_QERAPP_HOOKGL2DWINDOW	m_pfnHookGL2DWindow;
+  PFN_QERAPP_UNHOOKGL2DWINDOW	m_pfnUnHookGL2DWindow;
+  PFN_QERAPP_HOOKGL3DWINDOW m_pfnHookGL3DWindow;
+  PFN_QERAPP_UNHOOKGL3DWINDOW m_pfnUnHookGL3DWindow;
+};
+
+#endif
diff --git a/include/iimage.h b/include/iimage.h
index e473c4fe..6335082b 100644
--- a/include/iimage.h
+++ b/include/iimage.h
@@ -1,40 +1,40 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// Plugin interface for loading image files
-//
-
-#ifndef _IIMAGE_H_
-#define _IIMAGE_H_
-
-#define IMAGE_MAJOR "image"
-
-// Load an image file
-typedef void (* PFN_QERPLUG_LOADIMAGE) (const char *name, unsigned char **pic, int *width, int *height);
-
-struct _QERPlugImageTable
-{
-  int m_nSize;
-  PFN_QERPLUG_LOADIMAGE m_pfnLoadImage;
-};
-
-#endif // _IIMAGE_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// Plugin interface for loading image files
+//
+
+#ifndef _IIMAGE_H_
+#define _IIMAGE_H_
+
+#define IMAGE_MAJOR "image"
+
+// Load an image file
+typedef void (* PFN_QERPLUG_LOADIMAGE) (const char *name, unsigned char **pic, int *width, int *height);
+
+struct _QERPlugImageTable
+{
+  int m_nSize;
+  PFN_QERPLUG_LOADIMAGE m_pfnLoadImage;
+};
+
+#endif // _IIMAGE_H_
diff --git a/include/imap.h b/include/imap.h
index 230d5dd1..cddbadf7 100644
--- a/include/imap.h
+++ b/include/imap.h
@@ -1,82 +1,82 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// map format interface (.map and .xmap, Q3 and other games)
-//
-
-#ifndef __IMAP_H__
-#define __IMAP_H__
-
-/*! IMap depends on IDataStream, including the header there for now */
-#include "idatastream.h"
-
-/*! header for CPtrArray */
-#include "missing.h"
-
-#define MAP_MAJOR "map"
-/*!
-define a GUID for this interface so everyone can acces and reference it
-{75076973-3414-49c9-be5b-2378ec5601af}
-*/
-static const GUID QERPlugMapTable_GUID =
-{ 0x75076973, 0x3414, 0x49c9, { 0xbe, 0x5b, 0x23, 0x78, 0xec, 0x56, 0x01, 0xaf } };
-
-/*!
-read from a stream into a list of entities
-\param in the input stream. For regular map file parsing it's possible to copy the content in a text buffer
-and use the old school parser
-\param ents the list of entities read from the stream. They are not linked to the world, and their brushes
-are not either.
-*/
-typedef void (* PFN_MAP_READ) (IDataStream *in, CPtrArray *ents); ///< read from a stream into a list of entities
-typedef void (* PFN_MAP_WRITE) (CPtrArray *ents, IDataStream *out); ///< save a list of entities into a stream
-
-struct _QERPlugMapTable
-{
-  int m_nSize;
-  PFN_MAP_READ m_pfnMap_Read;
-  PFN_MAP_WRITE m_pfnMap_Write;
-};
-
-/*!
-this set of macros will define the functions to map on a given table
-  it should be used in the headers (see modules source, plugin.h)
-we don't want those defines in the part where WE implement the Map_LoadFile
-  so we're using a define to disable .. should find a standard define name
-  (for instance QCOM_CLIENT / QCOM_SERVER ?)
-  or the name should be specific to any interface .. it's not a client/server thing here anyway
-*/
-#ifdef USE_MAPTABLE_DEFINE
-#ifndef __MAPTABLENAME
-/*! 
-TTimo NOTE: this is the default table name we map to
-  if you are using a different table name, just define __MAPTABLENAME before you include the imap.h header
-*/
-#define __MAPTABLENAME g_MapTable
-#endif
-#define Map_Read __MAPTABLENAME.m_pfnMap_Read
-#define Map_Write __MAPTABLENAME.m_pfnMap_Write
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// map format interface (.map and .xmap, Q3 and other games)
+//
+
+#ifndef __IMAP_H__
+#define __IMAP_H__
+
+/*! IMap depends on IDataStream, including the header there for now */
+#include "idatastream.h"
+
+/*! header for CPtrArray */
+#include "missing.h"
+
+#define MAP_MAJOR "map"
+/*!
+define a GUID for this interface so everyone can acces and reference it
+{75076973-3414-49c9-be5b-2378ec5601af}
+*/
+static const GUID QERPlugMapTable_GUID =
+{ 0x75076973, 0x3414, 0x49c9, { 0xbe, 0x5b, 0x23, 0x78, 0xec, 0x56, 0x01, 0xaf } };
+
+/*!
+read from a stream into a list of entities
+\param in the input stream. For regular map file parsing it's possible to copy the content in a text buffer
+and use the old school parser
+\param ents the list of entities read from the stream. They are not linked to the world, and their brushes
+are not either.
+*/
+typedef void (* PFN_MAP_READ) (IDataStream *in, CPtrArray *ents); ///< read from a stream into a list of entities
+typedef void (* PFN_MAP_WRITE) (CPtrArray *ents, IDataStream *out); ///< save a list of entities into a stream
+
+struct _QERPlugMapTable
+{
+  int m_nSize;
+  PFN_MAP_READ m_pfnMap_Read;
+  PFN_MAP_WRITE m_pfnMap_Write;
+};
+
+/*!
+this set of macros will define the functions to map on a given table
+  it should be used in the headers (see modules source, plugin.h)
+we don't want those defines in the part where WE implement the Map_LoadFile
+  so we're using a define to disable .. should find a standard define name
+  (for instance QCOM_CLIENT / QCOM_SERVER ?)
+  or the name should be specific to any interface .. it's not a client/server thing here anyway
+*/
+#ifdef USE_MAPTABLE_DEFINE
+#ifndef __MAPTABLENAME
+/*! 
+TTimo NOTE: this is the default table name we map to
+  if you are using a different table name, just define __MAPTABLENAME before you include the imap.h header
+*/
+#define __MAPTABLENAME g_MapTable
+#endif
+#define Map_Read __MAPTABLENAME.m_pfnMap_Read
+#define Map_Write __MAPTABLENAME.m_pfnMap_Write
+#endif
+
+#endif
diff --git a/include/imodel.h b/include/imodel.h
index de5964a8..3dead05e 100644
--- a/include/imodel.h
+++ b/include/imodel.h
@@ -1,106 +1,106 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IMODEL_H_
-#define _IMODEL_H_
-
-#define MODEL_MAJOR "model"
-
-/*!
-loads model from model file name specified,
-fills model struct with pointers to model interfaces
-
-name is a relative path, we'll use VFS to extract a basepath to add to get the absolute path.
-*/
-typedef void (* PFN_LOADMODEL) (entity_interfaces_t *model, const char *name);
-
-struct _QERPlugModelTable
-{
-  int		m_nSize;
-  PFN_LOADMODEL       m_pfnLoadModel;
-};
-
-
-//forward declare entity_t
-struct entity_s;
-typedef struct entity_s entity_t;
-
-// any module relying on imodel will need to link against the mathlib
-#include "mathlib.h"
-
-// state flags
-#define DRAW_GL_FILL          0x0001
-#define DRAW_GL_LIGHTING      0x0010
-#define DRAW_GL_TEXTURE_2D    0x0100
-#define DRAW_GL_BLEND         0x1000
-
-// predefined state combinations
-#define DRAW_GL_WIRE					0x0000
-#define DRAW_GL_FLAT					0x0001
-#define DRAW_GL_SOLID					0x0011
-#define DRAW_GL_TEXTURED			0x0111
-
-// mode
-#define DRAW_WIRE							0
-#define DRAW_SOLID						1
-#define DRAW_TEXTURED					2
-
-// render flags
-#define DRAW_RF_NONE          0x0000
-#define DRAW_RF_SEL_OUTLINE   0x0001
-#define DRAW_RF_SEL_FILL      0x0010
-#define DRAW_RF_XY            0x0011
-#define DRAW_RF_CAM           0x0100
-
-class IRender
-{
-public:
-  virtual ~IRender() { }
-  virtual void IncRef() = 0; // increments the reference counter for this object
-  virtual void DecRef() = 0; // decrements the reference counter for this object, deletes the object if reference count is zero
-  virtual void Draw(int state, int rflags) const = 0; // render the object - state = the opengl state
-  virtual const aabb_t *GetAABB() const = 0;
-};
-
-class ISelect
-{
-public:
-  virtual ~ISelect() { }
-	virtual void IncRef() = 0; // increments the reference counter for this object
-	virtual void DecRef() = 0; // decrements the reference counter for this object, deletes the object if reference count is zero
-  virtual bool TestRay(const ray_t *ray, vec_t *dist) const = 0; // test ray intersection, return bool true if intersects, and store distance to closest point of intersection
-  //virtual bool TestBox(const aabb_t *aabb) const = 0; // test aabb intersection, return bool true if touching or intersecting
-};
-
-class IEdit
-{
-public:
-  virtual ~IEdit() { }
-	virtual void IncRef() = 0; // increments the reference counter for this object
-	virtual void DecRef() = 0; // decrements the reference counter for this object, deletes the object if reference count is zero
-  virtual void Translate(const vec3_t translation) = 0;
-  virtual void Rotate(const vec3_t pivot, const vec3_t rotation) = 0;
-  virtual const vec_t *GetTranslation() const = 0;
-  virtual const vec_t *GetRotation() const = 0;
-  virtual void OnKeyValueChanged(entity_t *e, const char *key, const char* value) = 0;
-};
-
-#endif /* _IMODEL_H_ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IMODEL_H_
+#define _IMODEL_H_
+
+#define MODEL_MAJOR "model"
+
+/*!
+loads model from model file name specified,
+fills model struct with pointers to model interfaces
+
+name is a relative path, we'll use VFS to extract a basepath to add to get the absolute path.
+*/
+typedef void (* PFN_LOADMODEL) (entity_interfaces_t *model, const char *name);
+
+struct _QERPlugModelTable
+{
+  int		m_nSize;
+  PFN_LOADMODEL       m_pfnLoadModel;
+};
+
+
+//forward declare entity_t
+struct entity_s;
+typedef struct entity_s entity_t;
+
+// any module relying on imodel will need to link against the mathlib
+#include "mathlib.h"
+
+// state flags
+#define DRAW_GL_FILL          0x0001
+#define DRAW_GL_LIGHTING      0x0010
+#define DRAW_GL_TEXTURE_2D    0x0100
+#define DRAW_GL_BLEND         0x1000
+
+// predefined state combinations
+#define DRAW_GL_WIRE					0x0000
+#define DRAW_GL_FLAT					0x0001
+#define DRAW_GL_SOLID					0x0011
+#define DRAW_GL_TEXTURED			0x0111
+
+// mode
+#define DRAW_WIRE							0
+#define DRAW_SOLID						1
+#define DRAW_TEXTURED					2
+
+// render flags
+#define DRAW_RF_NONE          0x0000
+#define DRAW_RF_SEL_OUTLINE   0x0001
+#define DRAW_RF_SEL_FILL      0x0010
+#define DRAW_RF_XY            0x0011
+#define DRAW_RF_CAM           0x0100
+
+class IRender
+{
+public:
+  virtual ~IRender() { }
+  virtual void IncRef() = 0; // increments the reference counter for this object
+  virtual void DecRef() = 0; // decrements the reference counter for this object, deletes the object if reference count is zero
+  virtual void Draw(int state, int rflags) const = 0; // render the object - state = the opengl state
+  virtual const aabb_t *GetAABB() const = 0;
+};
+
+class ISelect
+{
+public:
+  virtual ~ISelect() { }
+	virtual void IncRef() = 0; // increments the reference counter for this object
+	virtual void DecRef() = 0; // decrements the reference counter for this object, deletes the object if reference count is zero
+  virtual bool TestRay(const ray_t *ray, vec_t *dist) const = 0; // test ray intersection, return bool true if intersects, and store distance to closest point of intersection
+  //virtual bool TestBox(const aabb_t *aabb) const = 0; // test aabb intersection, return bool true if touching or intersecting
+};
+
+class IEdit
+{
+public:
+  virtual ~IEdit() { }
+	virtual void IncRef() = 0; // increments the reference counter for this object
+	virtual void DecRef() = 0; // decrements the reference counter for this object, deletes the object if reference count is zero
+  virtual void Translate(const vec3_t translation) = 0;
+  virtual void Rotate(const vec3_t pivot, const vec3_t rotation) = 0;
+  virtual const vec_t *GetTranslation() const = 0;
+  virtual const vec_t *GetRotation() const = 0;
+  virtual void OnKeyValueChanged(entity_t *e, const char *key, const char* value) = 0;
+};
+
+#endif /* _IMODEL_H_ */
diff --git a/include/ipatch.h b/include/ipatch.h
index ccfd39ed..300a0a75 100644
--- a/include/ipatch.h
+++ b/include/ipatch.h
@@ -1,53 +1,53 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IPATCH_H_
-#define _IPATCH_H_
-
-//
-// API for patch stuff
-//
-
-#define PATCH_MAJOR "patch"
-// {4715565b-ab3a-49fa-841f-ee965b6d88a5}
-static const GUID QERPatchTable_GUID = 
-{ 0x4715565b, 0xab3a, 0x49fa, { 0x84, 0x1f, 0xee, 0x96, 0x5b, 0x6d, 0x88, 0xa5 } };
-
-typedef patchMesh_t* (* PFN_PATCHALLOC)   ();
-typedef patchMesh_t* (* PFN_MAKENEWPATCH) ();
-typedef brush_t* (* PFN_ADDBRUSHFORPATCH) (patchMesh_t *pm, bool bLinkToWorld );
-
-struct _QERPatchTable
-{
-  int m_nSize;
-  PFN_PATCHALLOC m_pfnPatch_Alloc;
-  PFN_MAKENEWPATCH m_pfnMakeNewPatch;
-  PFN_ADDBRUSHFORPATCH m_pfnAddBrushForPatch;
-};
-
-#ifdef USE_PATCHTABLE_DEFINE
-#define __PATCHTABLENAME g_PatchTable
-#define Patch_Alloc __PATCHTABLENAME.m_pfnPatch_Alloc
-#define MakeNewPatch __PATCHTABLENAME.m_pfnMakeNewPatch
-#define AddBrushForPatch __PATCHTABLENAME.m_pfnAddBrushForPatch
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IPATCH_H_
+#define _IPATCH_H_
+
+//
+// API for patch stuff
+//
+
+#define PATCH_MAJOR "patch"
+// {4715565b-ab3a-49fa-841f-ee965b6d88a5}
+static const GUID QERPatchTable_GUID = 
+{ 0x4715565b, 0xab3a, 0x49fa, { 0x84, 0x1f, 0xee, 0x96, 0x5b, 0x6d, 0x88, 0xa5 } };
+
+typedef patchMesh_t* (* PFN_PATCHALLOC)   ();
+typedef patchMesh_t* (* PFN_MAKENEWPATCH) ();
+typedef brush_t* (* PFN_ADDBRUSHFORPATCH) (patchMesh_t *pm, bool bLinkToWorld );
+
+struct _QERPatchTable
+{
+  int m_nSize;
+  PFN_PATCHALLOC m_pfnPatch_Alloc;
+  PFN_MAKENEWPATCH m_pfnMakeNewPatch;
+  PFN_ADDBRUSHFORPATCH m_pfnAddBrushForPatch;
+};
+
+#ifdef USE_PATCHTABLE_DEFINE
+#define __PATCHTABLENAME g_PatchTable
+#define Patch_Alloc __PATCHTABLENAME.m_pfnPatch_Alloc
+#define MakeNewPatch __PATCHTABLENAME.m_pfnMakeNewPatch
+#define AddBrushForPatch __PATCHTABLENAME.m_pfnAddBrushForPatch
+#endif
+
+#endif
diff --git a/include/iplugin.h b/include/iplugin.h
index e2974b9b..3f21bfef 100644
--- a/include/iplugin.h
+++ b/include/iplugin.h
@@ -1,41 +1,41 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IPLUGIN_H_
-#define _IPLUGIN_H_
-
-#define PLUGIN_MAJOR "plugin"
-
-typedef const char* (* PFN_QERPLUG_INIT) (void* hApp, void* pMainWidget);
-typedef const char* (* PFN_QERPLUG_GETNAME) ();
-typedef const char* (* PFN_QERPLUG_GETCOMMANDLIST) ();
-typedef void        (* PFN_QERPLUG_DISPATCH) (const char* p, float* vMin, float* vMax, bool bSingleBrush);
-
-struct _QERPluginTable
-{
-  int m_nSize;
-  PFN_QERPLUG_INIT m_pfnQERPlug_Init;
-  PFN_QERPLUG_GETNAME m_pfnQERPlug_GetName;
-  PFN_QERPLUG_GETCOMMANDLIST m_pfnQERPlug_GetCommandList;
-  PFN_QERPLUG_DISPATCH m_pfnQERPlug_Dispatch;
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IPLUGIN_H_
+#define _IPLUGIN_H_
+
+#define PLUGIN_MAJOR "plugin"
+
+typedef const char* (* PFN_QERPLUG_INIT) (void* hApp, void* pMainWidget);
+typedef const char* (* PFN_QERPLUG_GETNAME) ();
+typedef const char* (* PFN_QERPLUG_GETCOMMANDLIST) ();
+typedef void        (* PFN_QERPLUG_DISPATCH) (const char* p, float* vMin, float* vMax, bool bSingleBrush);
+
+struct _QERPluginTable
+{
+  int m_nSize;
+  PFN_QERPLUG_INIT m_pfnQERPlug_Init;
+  PFN_QERPLUG_GETNAME m_pfnQERPlug_GetName;
+  PFN_QERPLUG_GETCOMMANDLIST m_pfnQERPlug_GetCommandList;
+  PFN_QERPLUG_DISPATCH m_pfnQERPlug_Dispatch;
+};
+
+#endif
diff --git a/include/irefcount.h b/include/irefcount.h
index 2fc495ad..e49e80d7 100644
--- a/include/irefcount.h
+++ b/include/irefcount.h
@@ -1,62 +1,62 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __IREFCOUNT_H__
-#define __IREFCOUNT_H__
-
-/*!
-\class IRefCounted
-\brief reference counted objects
-
-general hints: how to use ref count properly
-  we consider ref counting as an extension of new and delete operators
-  the main issue is 'when to incref' 'when to decref'
-  in most cases connected to function calls
-  the general thinking about that:
-    - if you get a pointer to a refcounted object through a call to a function, assume that this object has been 'reserved' for you
-    already (i.e. allocated if you think this the new/delete way). so if you keep the object, you don't need to incref it, and if
-    you don't keep it you need to decref it.
-    - if you are called in a function and a refcounted object passed as parameter, then you should assume that this is an optional
-    object given to you FYI, which you don't need to decref if you don't keep / need to incref if you keep
-    
-  refcount is initialized to 1 in constructor. that serves for static objects and memory allocator
-  when you allocate in memory a ref counted object, it's default ref count will be 1, you should never delete it but just call DecRef on it
-  
-define an interface and an implementation macro to make things easier
-NOTE: we may have to provide a static library to go with that
-  in case we would move irecount.h out of here into libs/
-  
-\todo functionality needed:
-mostly enable/disable some features with compile time flags (independently from each other as much as possible)
-- log the destructor calls with != 0 ref count
-- log all incref/decref (with module info, and maybe even file/line number etc.?)
-*/
-class IRefCounted
-{
-  int refCount;
-public:
-  IRefCounted() { refCount = 1; }
-  virtual ~IRefCounted() { }
-  void IncRef() { refCount++; }
-  void DecRef() { refCount--; if (refCount <= 0) delete this; }
-};
-  
-#endif // __ISYNAPSE_H__
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __IREFCOUNT_H__
+#define __IREFCOUNT_H__
+
+/*!
+\class IRefCounted
+\brief reference counted objects
+
+general hints: how to use ref count properly
+  we consider ref counting as an extension of new and delete operators
+  the main issue is 'when to incref' 'when to decref'
+  in most cases connected to function calls
+  the general thinking about that:
+    - if you get a pointer to a refcounted object through a call to a function, assume that this object has been 'reserved' for you
+    already (i.e. allocated if you think this the new/delete way). so if you keep the object, you don't need to incref it, and if
+    you don't keep it you need to decref it.
+    - if you are called in a function and a refcounted object passed as parameter, then you should assume that this is an optional
+    object given to you FYI, which you don't need to decref if you don't keep / need to incref if you keep
+    
+  refcount is initialized to 1 in constructor. that serves for static objects and memory allocator
+  when you allocate in memory a ref counted object, it's default ref count will be 1, you should never delete it but just call DecRef on it
+  
+define an interface and an implementation macro to make things easier
+NOTE: we may have to provide a static library to go with that
+  in case we would move irecount.h out of here into libs/
+  
+\todo functionality needed:
+mostly enable/disable some features with compile time flags (independently from each other as much as possible)
+- log the destructor calls with != 0 ref count
+- log all incref/decref (with module info, and maybe even file/line number etc.?)
+*/
+class IRefCounted
+{
+  int refCount;
+public:
+  IRefCounted() { refCount = 1; }
+  virtual ~IRefCounted() { }
+  void IncRef() { refCount++; }
+  void DecRef() { refCount--; if (refCount <= 0) delete this; }
+};
+  
+#endif // __ISYNAPSE_H__
diff --git a/include/iscriplib.h b/include/iscriplib.h
index 00ba6617..30b9bd8a 100644
--- a/include/iscriplib.h
+++ b/include/iscriplib.h
@@ -1,86 +1,86 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// all purpose scriplib interface for Q3Radiant plugins (cf. parse.h)
-//
-
-#ifndef __ISCRIPLIB_H_
-#define __ISCRIPLIB_H_
-
-/*! \file iscriplib.h
- \brief function tables for Radiant core's text parsing functions
- two token based parsers cohexist in Radiant
- the primary one (GetToken UnGetToken etc.) is used on the .map parsing etc.
- COM_Parse is another parser, used on .def parse for instance
- 
- NOTE: I hope we can totally get rid of this part when we have XML support
-*/
-
-#define SCRIPLIB_MAJOR "scriptlib"
-
-typedef qboolean	(* PFN_GETTOKEN)		(qboolean crossline);
-typedef void      (* PFN_UNGETTOKEN)	();
-// only used to retrieve &token
-typedef char*     (* PFN_TOKEN) ();
-typedef void      (* PFN_STARTTOKENPARSING) (char *);
-// script line
-typedef int       (* PFN_SCRIPTLINE) ();
-typedef qboolean  (* PFN_TOKENAVAILABLE) ();
-// COM_Parse
-typedef char*     (* PFN_COM_PARSE) (char *data);
-typedef char*     (* PFN_GET_COM_TOKEN) ();
-// Hydra: added support for GetTokenExtra()
-typedef qboolean	(* PFN_GETTOKENEXTRA)		(qboolean crossline,char *delimiters,qboolean keepdelimiter);
-
-struct _QERScripLibTable
-{
-	float m_fVersion;
-	int m_nSize;
-	PFN_GETTOKEN	m_pfnGetToken;
-	PFN_GETTOKENEXTRA	m_pfnGetTokenExtra; // Hydra: added support for GetTokenExtra()
-	PFN_UNGETTOKEN	m_pfnUnGetToken;
-	PFN_TOKEN		m_pfnToken;
-	PFN_STARTTOKENPARSING  m_pfnStartTokenParsing;
-  PFN_SCRIPTLINE m_pfnScriptLine;
-  PFN_TOKENAVAILABLE m_pfnTokenAvailable;
-  PFN_COM_PARSE m_pfnCOM_Parse;
-  PFN_GET_COM_TOKEN m_pfnGet_COM_Token;
-};
-
-#ifdef USE_SCRIPLIBTABLE_DEFINE
-#ifndef __SCRIPLIBTABLENAME
-#define __SCRIPLIBTABLENAME g_ScripLibTable
-#endif
-#define GetToken __SCRIPLIBTABLENAME.m_pfnGetToken
-#define Token __SCRIPLIBTABLENAME.m_pfnToken
-#define UnGetToken __SCRIPLIBTABLENAME.m_pfnUnGetToken
-#define StartTokenParsing __SCRIPLIBTABLENAME.m_pfnStartTokenParsing
-#define ScriptLine __SCRIPLIBTABLENAME.m_pfnScriptLine
-#define TokenAvailable __SCRIPLIBTABLENAME.m_pfnTokenAvailable
-#define COM_Parse __SCRIPLIBTABLENAME.m_pfnCOM_Parse
-#define Get_COM_Token __SCRIPLIBTABLENAME.m_pfnGet_COM_Token
-#define GetTokenExtra __SCRIPLIBTABLENAME.m_pfnGetTokenExtra // Hydra: added support for GetTokenExtra()
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// all purpose scriplib interface for Q3Radiant plugins (cf. parse.h)
+//
+
+#ifndef __ISCRIPLIB_H_
+#define __ISCRIPLIB_H_
+
+/*! \file iscriplib.h
+ \brief function tables for Radiant core's text parsing functions
+ two token based parsers cohexist in Radiant
+ the primary one (GetToken UnGetToken etc.) is used on the .map parsing etc.
+ COM_Parse is another parser, used on .def parse for instance
+ 
+ NOTE: I hope we can totally get rid of this part when we have XML support
+*/
+
+#define SCRIPLIB_MAJOR "scriptlib"
+
+typedef qboolean	(* PFN_GETTOKEN)		(qboolean crossline);
+typedef void      (* PFN_UNGETTOKEN)	();
+// only used to retrieve &token
+typedef char*     (* PFN_TOKEN) ();
+typedef void      (* PFN_STARTTOKENPARSING) (char *);
+// script line
+typedef int       (* PFN_SCRIPTLINE) ();
+typedef qboolean  (* PFN_TOKENAVAILABLE) ();
+// COM_Parse
+typedef char*     (* PFN_COM_PARSE) (char *data);
+typedef char*     (* PFN_GET_COM_TOKEN) ();
+// Hydra: added support for GetTokenExtra()
+typedef qboolean	(* PFN_GETTOKENEXTRA)		(qboolean crossline,char *delimiters,qboolean keepdelimiter);
+
+struct _QERScripLibTable
+{
+	float m_fVersion;
+	int m_nSize;
+	PFN_GETTOKEN	m_pfnGetToken;
+	PFN_GETTOKENEXTRA	m_pfnGetTokenExtra; // Hydra: added support for GetTokenExtra()
+	PFN_UNGETTOKEN	m_pfnUnGetToken;
+	PFN_TOKEN		m_pfnToken;
+	PFN_STARTTOKENPARSING  m_pfnStartTokenParsing;
+  PFN_SCRIPTLINE m_pfnScriptLine;
+  PFN_TOKENAVAILABLE m_pfnTokenAvailable;
+  PFN_COM_PARSE m_pfnCOM_Parse;
+  PFN_GET_COM_TOKEN m_pfnGet_COM_Token;
+};
+
+#ifdef USE_SCRIPLIBTABLE_DEFINE
+#ifndef __SCRIPLIBTABLENAME
+#define __SCRIPLIBTABLENAME g_ScripLibTable
+#endif
+#define GetToken __SCRIPLIBTABLENAME.m_pfnGetToken
+#define Token __SCRIPLIBTABLENAME.m_pfnToken
+#define UnGetToken __SCRIPLIBTABLENAME.m_pfnUnGetToken
+#define StartTokenParsing __SCRIPLIBTABLENAME.m_pfnStartTokenParsing
+#define ScriptLine __SCRIPLIBTABLENAME.m_pfnScriptLine
+#define TokenAvailable __SCRIPLIBTABLENAME.m_pfnTokenAvailable
+#define COM_Parse __SCRIPLIBTABLENAME.m_pfnCOM_Parse
+#define Get_COM_Token __SCRIPLIBTABLENAME.m_pfnGet_COM_Token
+#define GetTokenExtra __SCRIPLIBTABLENAME.m_pfnGetTokenExtra // Hydra: added support for GetTokenExtra()
+#endif
+
+#endif
diff --git a/include/iselectedface.h b/include/iselectedface.h
index a01c5283..61bc70d4 100644
--- a/include/iselectedface.h
+++ b/include/iselectedface.h
@@ -1,88 +1,88 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// Quick interface hack for selected face interface
-// this one really needs more work, but I'm in a hurry with TexTool
-
-#ifndef __ISELECTEDFACE_H_
-#define __ISELECTEDFACE_H_
-
-#define SELECTEDFACE_MAJOR "selectedface"
-// v2.0
-// support for multiple faces selection (first use in textool v2)
-// using the g_ptrSelectedFaces indexes, get the face_t* with GETFACE
-// still relies on the _QERFaceData*, unless you cast the face_t* to do your own stuff
-// removed PFN_TEXTUREFORNAME, it's in the IShaders API now
-
-//++timo TODO: this interface needs some cleanup with the new texture / shaders interface
-
-// number of selected textures
-typedef int   (WINAPI* PFN_GETSELECTEDFACECOUNT) ();
-// retrieve the corresponding brush_t* (we need it when we need to explicitely rebuild stuff)
-typedef brush_t*    (WINAPI* PFN_GETFACEBRUSH) (int iface);
-// retrieve a given face_t*
-typedef face_t*     (WINAPI* PFN_GETFACE) (int iface);
-// winding_t is assumed to have MAX_POINTS_ON_WINDING allocated and waiting
-typedef int		(WINAPI* PFN_GETFACEINFO)		(int iface, _QERFaceData*, winding_t* );
-// tell editor to update the selected face data
-typedef int		(WINAPI* PFN_SETFACEINFO)		(int iface, _QERFaceData*);
-// retrieve the texture number to bind to
-typedef int		(WINAPI* PFN_GETTEXTURENUMBER)	(int iface);
-// retrieving some texture information
-typedef void	(WINAPI* PFN_GETTEXTURESIZE)	(int iface, int Size[2] );
-// straight func pointer to Select_SetTexture
-// last parameter must be casted to an IPluginTexdef
-typedef void	(WINAPI* PFN_SELECT_SETTEXTURE)		(texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, void* pPlugTexdef);
-
-// NOTE: some things in there are not really related to the selected face
-// having some stuff moved into a textures-dedicated part ?
-struct _QERSelectedFaceTable
-{
-	int m_nSize;
-  PFN_GETSELECTEDFACECOUNT  m_pfnGetSelectedFaceCount;
-  PFN_GETFACEBRUSH          m_pfnGetFaceBrush;
-  PFN_GETFACE               m_pfnGetFace;
-  PFN_GETFACEINFO			      m_pfnGetFaceInfo;
-  PFN_SETFACEINFO			      m_pfnSetFaceInfo;
-  PFN_GETTEXTURENUMBER	    m_pfnGetTextureNumber;
-  PFN_GETTEXTURESIZE		    m_pfnGetTextureSize;
-  PFN_SELECT_SETTEXTURE	    m_pfnSelect_SetTexture;	
-};
-
-#ifdef USE_SELECTEDFACETABLE_DEFINE
-  #ifndef __SELECTEDFACETABLENAME
-    #define __SELECTEDFACETABLENAME g_SelectedFaceTable
-  #endif
-
-  #define GetSelectedFaceCount __SELECTEDFACETABLENAME.m_pfnGetSelectedFaceCount
-  #define GetFaceBrush __SELECTEDFACETABLENAME.m_pfnGetFaceBrush
-  #define GetFace __SELECTEDFACETABLENAME.m_pfnGetFace
-  #define GetFaceInfo __SELECTEDFACETABLENAME.m_pfnGetFaceInfo
-  #define SetFaceInfo __SELECTEDFACETABLENAME.m_pfnSetFaceInfo
-  #define GetTextureNumber __SELECTEDFACETABLENAME.m_pfnGetTextureNumber
-  #define GetTextureSize __SELECTEDFACETABLENAME.m_pfnGetTextureSize
-  #define Select_SetTexture __SELECTEDFACETABLENAME.m_pfnSelect_SetTexture
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// Quick interface hack for selected face interface
+// this one really needs more work, but I'm in a hurry with TexTool
+
+#ifndef __ISELECTEDFACE_H_
+#define __ISELECTEDFACE_H_
+
+#define SELECTEDFACE_MAJOR "selectedface"
+// v2.0
+// support for multiple faces selection (first use in textool v2)
+// using the g_ptrSelectedFaces indexes, get the face_t* with GETFACE
+// still relies on the _QERFaceData*, unless you cast the face_t* to do your own stuff
+// removed PFN_TEXTUREFORNAME, it's in the IShaders API now
+
+//++timo TODO: this interface needs some cleanup with the new texture / shaders interface
+
+// number of selected textures
+typedef int   (WINAPI* PFN_GETSELECTEDFACECOUNT) ();
+// retrieve the corresponding brush_t* (we need it when we need to explicitely rebuild stuff)
+typedef brush_t*    (WINAPI* PFN_GETFACEBRUSH) (int iface);
+// retrieve a given face_t*
+typedef face_t*     (WINAPI* PFN_GETFACE) (int iface);
+// winding_t is assumed to have MAX_POINTS_ON_WINDING allocated and waiting
+typedef int		(WINAPI* PFN_GETFACEINFO)		(int iface, _QERFaceData*, winding_t* );
+// tell editor to update the selected face data
+typedef int		(WINAPI* PFN_SETFACEINFO)		(int iface, _QERFaceData*);
+// retrieve the texture number to bind to
+typedef int		(WINAPI* PFN_GETTEXTURENUMBER)	(int iface);
+// retrieving some texture information
+typedef void	(WINAPI* PFN_GETTEXTURESIZE)	(int iface, int Size[2] );
+// straight func pointer to Select_SetTexture
+// last parameter must be casted to an IPluginTexdef
+typedef void	(WINAPI* PFN_SELECT_SETTEXTURE)		(texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale, void* pPlugTexdef);
+
+// NOTE: some things in there are not really related to the selected face
+// having some stuff moved into a textures-dedicated part ?
+struct _QERSelectedFaceTable
+{
+	int m_nSize;
+  PFN_GETSELECTEDFACECOUNT  m_pfnGetSelectedFaceCount;
+  PFN_GETFACEBRUSH          m_pfnGetFaceBrush;
+  PFN_GETFACE               m_pfnGetFace;
+  PFN_GETFACEINFO			      m_pfnGetFaceInfo;
+  PFN_SETFACEINFO			      m_pfnSetFaceInfo;
+  PFN_GETTEXTURENUMBER	    m_pfnGetTextureNumber;
+  PFN_GETTEXTURESIZE		    m_pfnGetTextureSize;
+  PFN_SELECT_SETTEXTURE	    m_pfnSelect_SetTexture;	
+};
+
+#ifdef USE_SELECTEDFACETABLE_DEFINE
+  #ifndef __SELECTEDFACETABLENAME
+    #define __SELECTEDFACETABLENAME g_SelectedFaceTable
+  #endif
+
+  #define GetSelectedFaceCount __SELECTEDFACETABLENAME.m_pfnGetSelectedFaceCount
+  #define GetFaceBrush __SELECTEDFACETABLENAME.m_pfnGetFaceBrush
+  #define GetFace __SELECTEDFACETABLENAME.m_pfnGetFace
+  #define GetFaceInfo __SELECTEDFACETABLENAME.m_pfnGetFaceInfo
+  #define SetFaceInfo __SELECTEDFACETABLENAME.m_pfnSetFaceInfo
+  #define GetTextureNumber __SELECTEDFACETABLENAME.m_pfnGetTextureNumber
+  #define GetTextureSize __SELECTEDFACETABLENAME.m_pfnGetTextureSize
+  #define Select_SetTexture __SELECTEDFACETABLENAME.m_pfnSelect_SetTexture
+#endif
+
+#endif
diff --git a/include/ishaders.h b/include/ishaders.h
index 17cafc36..e50233ed 100644
--- a/include/ishaders.h
+++ b/include/ishaders.h
@@ -1,284 +1,284 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-//
-// DESCRIPTION:
-// a set of functions to manipulate textures in Radiant
-// 
-
-#ifndef __ISHADERS_H_
-#define __ISHADERS_H_
-
-#define SHADERS_MAJOR "shaders"
-// define a GUID for this interface so plugins can access and reference it
-// {D42F798A-DF57-11d3-A3EE-0004AC96D4C3}
-static const GUID QERShadersTable_GUID = 
-{ 0xd42f798a, 0xdf57, 0x11d3, { 0xa3, 0xee, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
-
-// NOTES ABOUT SYNTAX:
-// if a function starts by 'Try' it means that if the requested thing could not be found / loaded it will return nothing / NULL
-// otherwise a default object will be created
-// the _QERShadersTable is also used by shader code inside Radiant. but for speed and "keep it simple" consideration you
-// can get the static equivalent of the func pointers by adding 'QERApp_' (access to _QERShadersTable is better thought ..
-// see the note to move all the shader language out of Radiant below)
-
-/*!
-\todo FIXME TTimo
-fix the reference count strategy
-- define the policy. It seems the initial policy of doing an inc ref when you create the shader is not good
-(it doesn't work, and it's not being used right)
-so, when you request an IShader and store it, incref it yourself
-as a debugging safe check: push the created increfed objects into a list, and scan them at next idle loop
-to make sure they have been decref'ed ? (sounds easy, may not be that much).
-*/
-
-class IShader
-{
-public:
-  // Increment the number of references to this object
-  virtual void IncRef () = 0;
-  // Decrement the reference count
-  virtual void DecRef () = 0;
-  // get/set the qtexture_t* Radiant uses to represent this shader object
-  virtual qtexture_t* getTexture() const = 0;
-  virtual void setTexture(qtexture_t *pTex) = 0;
-  // get shader name
-  virtual const char* getName() const = 0;
-  // is this shader in use?
-  // NOTE: this flag can mean this shader has been in use at least once since the last rescan of in-use stuff
-  // (rescan of in-use happens in several cases, user command or during a texture directory load)
-  // NOTE: this is used to draw the green outline in the texture window
-  // NOTE: when does Radiant set the InUse flag? Whenever Select_SetTexture is called (well that doesn't necessarily means the texture actually gets in use, but that's close enough)
-  virtual bool IsInUse() const = 0;
-  virtual void SetInUse(bool) = 0;
-  // is this shader displayed in the texture browser?
-  // NOTE: if IsInUse() == true, the shader will always be displayed in the texture window and this flag ingored
-  virtual bool IsDisplayed() const = 0;
-  virtual void SetDisplayed(bool) = 0;
-  // get the editor flags (QER_NOCARVE QER_TRANS)
-  virtual int getFlags() = 0;
-  // get the transparency value
-  virtual float getTrans() = 0;
-  // test if it's a true shader, or a default shader created to wrap around a texture
-  virtual bool IsDefault() = 0;
-  // test if it's a plain color shader, i.e. a shader we use on plain color stuff (like info_playerstart)
-  virtual bool IsColor() = 0;
-  // get the related color then!
-  virtual void getColor(vec3_t v) = 0;
-  // get the alphaFunc
-  virtual void getAlphaFunc(int *func, float *ref) = 0;
-  // get the cull type
-  virtual int getCull() = 0;
-  // get shader file name (ie the file where this one is defined)
-  virtual const char* getShaderFileName() const = 0;
-};
-
-// NOTE: how to move all the shader language out of Radiant in a plugin?
-// -> change this _QERShadersTable into an IShadersManager
-// -> let the plugin create an instance of IShadersManager
-// -> make sure Radiant uses this IShadersManager to load / query the shaders
-
-// NOTE: shader and texture names used must be full path, ie. most often with "textures/" prefix
-// (since shaders are defined in .shader files with textures/)
-
-// free all shaders
-// free the shaders, will not free the qtexture_t*
-typedef void		(WINAPI* PFN_FREESHADERS)		();
-// reload all the shaders
-// this will free everything (shaders and their textures), then reload all in use stuff
-typedef void		(WINAPI* PFN_RELOADSHADERS)		();
-// load all shaders in a given directory
-// this will scan the list of in-memory shaders, and load the related qtexture_t if needed
-typedef int		(WINAPI* PFN_LOADSHADERSFROMDIR)(const char* path);
-// load a shader file (ie a set of shaders)
-// after LoadShaderFile shaders will be in memory, next step is to load the qtexture_t Radiant uses to represent them
-// if a shader with the same name exists, new one will not be loaded - don't use this to refresh the shaders!
-typedef void		(WINAPI* PFN_LOADSHADERFILE)	(const char* filename);
-// tell if a given shader exists in our shader table
-// NOTE: this doesn't tell wether it's corresponding qtexture is loaded 
-typedef int			(WINAPI* PFN_HASSHADER)			(const char* name);
-// return the shader for a given name
-// if the qtexture is not already in memory, will try loading it
-// if the qtexture could not be found, will use default
-// will return NULL on shader not found
-typedef IShader*	(WINAPI* PFN_TRYSHADERFORNAME)	(const char* name);
-// return the shader for a given name
-// if the qtexture is not already in memory, will try loading it
-// will create a default shader if not found (will use a default texture)
-typedef IShader*	(WINAPI* PFN_SHADERFORNAME)		(const char* name);
-// query / load a texture
-// will not try loading a shader, will look for the actual image file ..
-// returns NULL on file not found
-// NOTE: strategy for file lookup:
-//   paths must be relative, ie. textures/me/myfile
-//   if a 3-letters filename extension (such as .jpg or .tga) is provided, it will get loaded first
-//   if not found or no extension, will try loading after adding .tga and .jpg (in this order)
-typedef qtexture_t* (WINAPI* PFN_TRYTEXTUREFORNAME) (const char* filename);
-// query / load a texture
-// will not try loading a shader, will look for the actual image file ..
-// on file not found will use the "texture not found"
-typedef qtexture_t* (WINAPI* PFN_TEXTUREFORNAME)	(const char* filename);
-// get the number of active shaders
-// these are the shaders currently loaded, that have an associated qtexture_t*
-typedef int			(WINAPI* PFN_GETACTIVESHADERCOUNT)	();
-// for stuff that needs to be represented by a plain texture
-// the shader will get a "color" name, use GetColor to get the actual color
-typedef IShader*	(WINAPI* PFN_COLORSHADERFORNAME)	(const char* name);
-// reload a shaderfile - update shaders and their display properties/qtexture_t if needed
-// will not reload the texture files
-// will switch to "show in use" atfer use
-// filename must be reletive path of the shader, ex. scripts/gothic_wall.shader
-typedef void		(WINAPI* PFN_RELOADSHADERFILE)(const char* filename);
-// retrieve a shader if exists, without loading the textures for it etc.
-// use this function if you want special info on a shader
-typedef IShader* (WINAPI* PFN_SHADERFORNAMENOLOAD) (const char* name);
-// force the "in use" flag on all active shaders
-typedef void (WINAPI* PFN_ACTIVESHADERSSETINUSE) (bool b);
-// sort the shaders in alphabetical order, we use the order in the texture inspector
-typedef void (WINAPI* PFN_SORTACTIVESHADERS) ();
-// check if there exists an active shader with the given texture name (loaded or not, doesn't matter)
-// (used to detect the textures we need to create a default shader for .. while scanning a directory)
-typedef IShader* (WINAPI* PFN_ACTIVESHADERFORTEXTURENAME) (char *);
-// create a shader to wrap around a texture name, we use this when loading a texture directory and some textures
-// are not present as shaders
-typedef IShader* (WINAPI* PFN_CREATESHADERFORTEXTURENAME) (const char* name);
-// switch the IsDisplayed flag on all the active shaders
-typedef void (WINAPI* PFN_ACTIVESHADERSSETDISPLAYED) (bool b);
-// retrieve an active shader based on index
-typedef IShader* (WINAPI* PFN_ACTIVESHADERFORINDEX) (int i);
-// will cleanup a texture name and force it to the right format
-// the debug version is painfully slow, but will detect more problems
-// the idea being to avoid loading the same file several time because of uppercase/lowercase etc.
-typedef const char* (WINAPI* PFN_CLEANTEXTURENAME) (const char* name, bool bAddTexture);
-
-struct _QERShadersTable
-{
-  int		m_nSize;
-  PFN_FREESHADERS			              m_pfnFreeShaders;
-  PFN_RELOADSHADERS		              m_pfnReloadShaders;
-  PFN_LOADSHADERSFROMDIR            m_pfnLoadShadersFromDir;
-  PFN_LOADSHADERFILE		            m_pfnLoadShaderFile;
-  PFN_RELOADSHADERFILE              m_pfnReloadShaderFile;
-  PFN_HASSHADER			                m_pfnHasShader;
-  PFN_TRYSHADERFORNAME	            m_pfnTry_Shader_ForName;
-  PFN_SHADERFORNAME		              m_pfnShader_ForName;
-  PFN_TRYTEXTUREFORNAME	            m_pfnTry_Texture_ForName;
-  PFN_TEXTUREFORNAME		            m_pfnTexture_ForName;
-  PFN_GETACTIVESHADERCOUNT			    m_pfnGetActiveShaderCount;
-  PFN_COLORSHADERFORNAME						m_pfnColorShader_ForName;
-  PFN_SHADERFORNAMENOLOAD						m_pfnShader_ForName_NoLoad;
-  PFN_ACTIVESHADERSSETINUSE         m_pfnActiveShaders_SetInUse;
-  PFN_SORTACTIVESHADERS             m_pfnSortActiveShaders;
-  PFN_ACTIVESHADERFORTEXTURENAME    m_pfnActiveShader_ForTextureName;
-  PFN_CREATESHADERFORTEXTURENAME    m_pfnCreateShader_ForTextureName;
-  PFN_ACTIVESHADERSSETDISPLAYED     m_pfnActiveShaders_SetDisplayed;
-  PFN_ACTIVESHADERFORINDEX          m_pfnActiveShader_ForIndex;
-  PFN_CLEANTEXTURENAME              m_pfnCleanTextureName;
-};
-
-/*!
-\todo FIXME fix the QERApp_ prototyping on shaders module
-make it homogeneous with other modules, should be straight calls
-*/
-
-#ifdef USE_SHADERSTABLE_DEFINE
-  #ifndef __SHADERSTABLENAME
-    #define __SHADERSTABLENAME g_ShadersTable
-  #endif
-#define QERApp_Shader_ForName __SHADERSTABLENAME.m_pfnShader_ForName
-#define QERApp_Texture_ForName2 __SHADERSTABLENAME.m_pfnTexture_ForName
-#define QERApp_FreeShaders __SHADERSTABLENAME.m_pfnFreeShaders
-#define QERApp_ReloadShaders __SHADERSTABLENAME.m_pfnReloadShaders
-#define QERApp_SortActiveShaders __SHADERSTABLENAME.m_pfnSortActiveShaders
-#define QERApp_ReloadShaderFile __SHADERSTABLENAME.m_pfnReloadShaderFile
-#define QERApp_LoadShaderFile __SHADERSTABLENAME.m_pfnLoadShaderFile
-#define QERApp_HasShader __SHADERSTABLENAME.m_pfnHasShader
-#define QERApp_Try_Shader_ForName __SHADERSTABLENAME.m_pfnTry_Shader_ForName
-#define QERApp_Try_Texture_ForName __SHADERSTABLENAME.m_pfnTry_Texture_ForName
-#define QERApp_ColorShader_ForName __SHADERSTABLENAME.m_pfnColorShader_ForName
-#define QERApp_Shader_ForName_NoLoad __SHADERSTABLENAME.m_pfnShader_ForName_NoLoad
-#define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir
-#define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir
-#define QERApp_CreateShader_ForTextureName __SHADERSTABLENAME.m_pfnCreateShader_ForTextureName
-#define QERApp_GetActiveShaderCount __SHADERSTABLENAME.m_pfnGetActiveShaderCount
-#define QERApp_ActiveShaders_SetDisplayed __SHADERSTABLENAME.m_pfnActiveShaders_SetDisplayed
-#define QERApp_ActiveShader_ForIndex __SHADERSTABLENAME.m_pfnActiveShader_ForIndex
-#define QERApp_ActiveShaders_SetInUse __SHADERSTABLENAME.m_pfnActiveShaders_SetInUse
-#define QERApp_ActiveShader_ForTextureName __SHADERSTABLENAME.m_pfnActiveShader_ForTextureName
-#define QERApp_ActiveShader_ForIndex __SHADERSTABLENAME.m_pfnActiveShader_ForIndex
-#define QERApp_CleanTextureName __SHADERSTABLENAME.m_pfnCleanTextureName
-#endif
-
-#define APPSHADERS_MAJOR "appshaders"
-// FIXME: remove
-static const GUID QERAppShadersTable_GUID = 
-{ 0xec3008a8, 0xbd0b, 0x11d4, { 0x82, 0x51, 0x20, 0x4c, 0x4f, 0x4f, 0x50, 0x20 } };
-
-// g_qeglobals.d_qtextures is used internally by the editor for actual camera drawing
-typedef qtexture_t** (WINAPI* PFN_QTEXTURES)();
-// g_qeglobals.d_qtexmap is a map for fast access
-typedef GHashTable* (WINAPI* PFN_QTEXMAP)();
-// d_texturewin
-//++timo NOTE: this same function is also in isurface.h table, we would eventually have to merge some stuff
-typedef texturewin_t* (* PFN_QEGLOBALSTEXTUREWIN)();
-// Texture_SetTexture
-//++timo NOTE: this one may have to be reorganized too .. putting it here is a bit clumsy
-// NOTE: the C++ function used internally has a lot of default values
-typedef void (WINAPI* PFN_TEXTURESETTEXTURE)(texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef);
-// Texture_ShowInuse
-typedef void (WINAPI* PFN_TEXTURESHOWINUSE)();
-// BuildShaderList
-typedef void (* PFN_BUILDSHADERLIST)();
-// PreloadShaders
-typedef void (* PFN_PRELOADSHADERS)();
-
-// a table that Radiant makes available to the shader module in return
-struct _QERAppShadersTable
-{
-  int m_nSize;
-  PFN_QTEXTURES           m_pfnQTextures;
-  PFN_QTEXMAP             m_pfnQTexmap;
-	PFN_QEGLOBALSTEXTUREWIN	m_pfnQeglobalsTexturewin;
-	PFN_TEXTURESETTEXTURE   m_pfnTexture_SetTexture;
-	PFN_TEXTURESHOWINUSE    m_pfnTexture_ShowInuse;
-  PFN_BUILDSHADERLIST     m_pfnBuildShaderList;
-  PFN_PRELOADSHADERS      m_pfnPreloadShaders;
-};
-
-#ifdef USE_APPSHADERSTABLE_DEFINE
-  #ifndef __APPSHADERTABLENAME
-    #define __APPSHADERTABLENAME g_AppShadersTable
-  #endif
-#define Texture_ShowInuse __APPSHADERTABLENAME.m_pfnTexture_ShowInuse
-#endif
-
-/*!
-NOTE TTimo: there is an important distinction between SHADER_NOT_FOUND and SHADER_NOTEX:
-SHADER_NOT_FOUND means we didn't find the raw texture or the shader for this
-SHADER_NOTEX means we recognize this as a shader script, but we are missing the texture to represent it
-this was in the initial design of the shader code since early GtkRadiant alpha, and got sort of foxed in 1.2 and put back in
-*/
-#define SHADER_NOT_FOUND "textures/radiant/notex"
-#define SHADER_NOTEX "textures/radiant/shadernotex" ///< Q3 tech specific
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+//
+// DESCRIPTION:
+// a set of functions to manipulate textures in Radiant
+// 
+
+#ifndef __ISHADERS_H_
+#define __ISHADERS_H_
+
+#define SHADERS_MAJOR "shaders"
+// define a GUID for this interface so plugins can access and reference it
+// {D42F798A-DF57-11d3-A3EE-0004AC96D4C3}
+static const GUID QERShadersTable_GUID = 
+{ 0xd42f798a, 0xdf57, 0x11d3, { 0xa3, 0xee, 0x0, 0x4, 0xac, 0x96, 0xd4, 0xc3 } };
+
+// NOTES ABOUT SYNTAX:
+// if a function starts by 'Try' it means that if the requested thing could not be found / loaded it will return nothing / NULL
+// otherwise a default object will be created
+// the _QERShadersTable is also used by shader code inside Radiant. but for speed and "keep it simple" consideration you
+// can get the static equivalent of the func pointers by adding 'QERApp_' (access to _QERShadersTable is better thought ..
+// see the note to move all the shader language out of Radiant below)
+
+/*!
+\todo FIXME TTimo
+fix the reference count strategy
+- define the policy. It seems the initial policy of doing an inc ref when you create the shader is not good
+(it doesn't work, and it's not being used right)
+so, when you request an IShader and store it, incref it yourself
+as a debugging safe check: push the created increfed objects into a list, and scan them at next idle loop
+to make sure they have been decref'ed ? (sounds easy, may not be that much).
+*/
+
+class IShader
+{
+public:
+  // Increment the number of references to this object
+  virtual void IncRef () = 0;
+  // Decrement the reference count
+  virtual void DecRef () = 0;
+  // get/set the qtexture_t* Radiant uses to represent this shader object
+  virtual qtexture_t* getTexture() const = 0;
+  virtual void setTexture(qtexture_t *pTex) = 0;
+  // get shader name
+  virtual const char* getName() const = 0;
+  // is this shader in use?
+  // NOTE: this flag can mean this shader has been in use at least once since the last rescan of in-use stuff
+  // (rescan of in-use happens in several cases, user command or during a texture directory load)
+  // NOTE: this is used to draw the green outline in the texture window
+  // NOTE: when does Radiant set the InUse flag? Whenever Select_SetTexture is called (well that doesn't necessarily means the texture actually gets in use, but that's close enough)
+  virtual bool IsInUse() const = 0;
+  virtual void SetInUse(bool) = 0;
+  // is this shader displayed in the texture browser?
+  // NOTE: if IsInUse() == true, the shader will always be displayed in the texture window and this flag ingored
+  virtual bool IsDisplayed() const = 0;
+  virtual void SetDisplayed(bool) = 0;
+  // get the editor flags (QER_NOCARVE QER_TRANS)
+  virtual int getFlags() = 0;
+  // get the transparency value
+  virtual float getTrans() = 0;
+  // test if it's a true shader, or a default shader created to wrap around a texture
+  virtual bool IsDefault() = 0;
+  // test if it's a plain color shader, i.e. a shader we use on plain color stuff (like info_playerstart)
+  virtual bool IsColor() = 0;
+  // get the related color then!
+  virtual void getColor(vec3_t v) = 0;
+  // get the alphaFunc
+  virtual void getAlphaFunc(int *func, float *ref) = 0;
+  // get the cull type
+  virtual int getCull() = 0;
+  // get shader file name (ie the file where this one is defined)
+  virtual const char* getShaderFileName() const = 0;
+};
+
+// NOTE: how to move all the shader language out of Radiant in a plugin?
+// -> change this _QERShadersTable into an IShadersManager
+// -> let the plugin create an instance of IShadersManager
+// -> make sure Radiant uses this IShadersManager to load / query the shaders
+
+// NOTE: shader and texture names used must be full path, ie. most often with "textures/" prefix
+// (since shaders are defined in .shader files with textures/)
+
+// free all shaders
+// free the shaders, will not free the qtexture_t*
+typedef void		(WINAPI* PFN_FREESHADERS)		();
+// reload all the shaders
+// this will free everything (shaders and their textures), then reload all in use stuff
+typedef void		(WINAPI* PFN_RELOADSHADERS)		();
+// load all shaders in a given directory
+// this will scan the list of in-memory shaders, and load the related qtexture_t if needed
+typedef int		(WINAPI* PFN_LOADSHADERSFROMDIR)(const char* path);
+// load a shader file (ie a set of shaders)
+// after LoadShaderFile shaders will be in memory, next step is to load the qtexture_t Radiant uses to represent them
+// if a shader with the same name exists, new one will not be loaded - don't use this to refresh the shaders!
+typedef void		(WINAPI* PFN_LOADSHADERFILE)	(const char* filename);
+// tell if a given shader exists in our shader table
+// NOTE: this doesn't tell wether it's corresponding qtexture is loaded 
+typedef int			(WINAPI* PFN_HASSHADER)			(const char* name);
+// return the shader for a given name
+// if the qtexture is not already in memory, will try loading it
+// if the qtexture could not be found, will use default
+// will return NULL on shader not found
+typedef IShader*	(WINAPI* PFN_TRYSHADERFORNAME)	(const char* name);
+// return the shader for a given name
+// if the qtexture is not already in memory, will try loading it
+// will create a default shader if not found (will use a default texture)
+typedef IShader*	(WINAPI* PFN_SHADERFORNAME)		(const char* name);
+// query / load a texture
+// will not try loading a shader, will look for the actual image file ..
+// returns NULL on file not found
+// NOTE: strategy for file lookup:
+//   paths must be relative, ie. textures/me/myfile
+//   if a 3-letters filename extension (such as .jpg or .tga) is provided, it will get loaded first
+//   if not found or no extension, will try loading after adding .tga and .jpg (in this order)
+typedef qtexture_t* (WINAPI* PFN_TRYTEXTUREFORNAME) (const char* filename);
+// query / load a texture
+// will not try loading a shader, will look for the actual image file ..
+// on file not found will use the "texture not found"
+typedef qtexture_t* (WINAPI* PFN_TEXTUREFORNAME)	(const char* filename);
+// get the number of active shaders
+// these are the shaders currently loaded, that have an associated qtexture_t*
+typedef int			(WINAPI* PFN_GETACTIVESHADERCOUNT)	();
+// for stuff that needs to be represented by a plain texture
+// the shader will get a "color" name, use GetColor to get the actual color
+typedef IShader*	(WINAPI* PFN_COLORSHADERFORNAME)	(const char* name);
+// reload a shaderfile - update shaders and their display properties/qtexture_t if needed
+// will not reload the texture files
+// will switch to "show in use" atfer use
+// filename must be reletive path of the shader, ex. scripts/gothic_wall.shader
+typedef void		(WINAPI* PFN_RELOADSHADERFILE)(const char* filename);
+// retrieve a shader if exists, without loading the textures for it etc.
+// use this function if you want special info on a shader
+typedef IShader* (WINAPI* PFN_SHADERFORNAMENOLOAD) (const char* name);
+// force the "in use" flag on all active shaders
+typedef void (WINAPI* PFN_ACTIVESHADERSSETINUSE) (bool b);
+// sort the shaders in alphabetical order, we use the order in the texture inspector
+typedef void (WINAPI* PFN_SORTACTIVESHADERS) ();
+// check if there exists an active shader with the given texture name (loaded or not, doesn't matter)
+// (used to detect the textures we need to create a default shader for .. while scanning a directory)
+typedef IShader* (WINAPI* PFN_ACTIVESHADERFORTEXTURENAME) (char *);
+// create a shader to wrap around a texture name, we use this when loading a texture directory and some textures
+// are not present as shaders
+typedef IShader* (WINAPI* PFN_CREATESHADERFORTEXTURENAME) (const char* name);
+// switch the IsDisplayed flag on all the active shaders
+typedef void (WINAPI* PFN_ACTIVESHADERSSETDISPLAYED) (bool b);
+// retrieve an active shader based on index
+typedef IShader* (WINAPI* PFN_ACTIVESHADERFORINDEX) (int i);
+// will cleanup a texture name and force it to the right format
+// the debug version is painfully slow, but will detect more problems
+// the idea being to avoid loading the same file several time because of uppercase/lowercase etc.
+typedef const char* (WINAPI* PFN_CLEANTEXTURENAME) (const char* name, bool bAddTexture);
+
+struct _QERShadersTable
+{
+  int		m_nSize;
+  PFN_FREESHADERS			              m_pfnFreeShaders;
+  PFN_RELOADSHADERS		              m_pfnReloadShaders;
+  PFN_LOADSHADERSFROMDIR            m_pfnLoadShadersFromDir;
+  PFN_LOADSHADERFILE		            m_pfnLoadShaderFile;
+  PFN_RELOADSHADERFILE              m_pfnReloadShaderFile;
+  PFN_HASSHADER			                m_pfnHasShader;
+  PFN_TRYSHADERFORNAME	            m_pfnTry_Shader_ForName;
+  PFN_SHADERFORNAME		              m_pfnShader_ForName;
+  PFN_TRYTEXTUREFORNAME	            m_pfnTry_Texture_ForName;
+  PFN_TEXTUREFORNAME		            m_pfnTexture_ForName;
+  PFN_GETACTIVESHADERCOUNT			    m_pfnGetActiveShaderCount;
+  PFN_COLORSHADERFORNAME						m_pfnColorShader_ForName;
+  PFN_SHADERFORNAMENOLOAD						m_pfnShader_ForName_NoLoad;
+  PFN_ACTIVESHADERSSETINUSE         m_pfnActiveShaders_SetInUse;
+  PFN_SORTACTIVESHADERS             m_pfnSortActiveShaders;
+  PFN_ACTIVESHADERFORTEXTURENAME    m_pfnActiveShader_ForTextureName;
+  PFN_CREATESHADERFORTEXTURENAME    m_pfnCreateShader_ForTextureName;
+  PFN_ACTIVESHADERSSETDISPLAYED     m_pfnActiveShaders_SetDisplayed;
+  PFN_ACTIVESHADERFORINDEX          m_pfnActiveShader_ForIndex;
+  PFN_CLEANTEXTURENAME              m_pfnCleanTextureName;
+};
+
+/*!
+\todo FIXME fix the QERApp_ prototyping on shaders module
+make it homogeneous with other modules, should be straight calls
+*/
+
+#ifdef USE_SHADERSTABLE_DEFINE
+  #ifndef __SHADERSTABLENAME
+    #define __SHADERSTABLENAME g_ShadersTable
+  #endif
+#define QERApp_Shader_ForName __SHADERSTABLENAME.m_pfnShader_ForName
+#define QERApp_Texture_ForName2 __SHADERSTABLENAME.m_pfnTexture_ForName
+#define QERApp_FreeShaders __SHADERSTABLENAME.m_pfnFreeShaders
+#define QERApp_ReloadShaders __SHADERSTABLENAME.m_pfnReloadShaders
+#define QERApp_SortActiveShaders __SHADERSTABLENAME.m_pfnSortActiveShaders
+#define QERApp_ReloadShaderFile __SHADERSTABLENAME.m_pfnReloadShaderFile
+#define QERApp_LoadShaderFile __SHADERSTABLENAME.m_pfnLoadShaderFile
+#define QERApp_HasShader __SHADERSTABLENAME.m_pfnHasShader
+#define QERApp_Try_Shader_ForName __SHADERSTABLENAME.m_pfnTry_Shader_ForName
+#define QERApp_Try_Texture_ForName __SHADERSTABLENAME.m_pfnTry_Texture_ForName
+#define QERApp_ColorShader_ForName __SHADERSTABLENAME.m_pfnColorShader_ForName
+#define QERApp_Shader_ForName_NoLoad __SHADERSTABLENAME.m_pfnShader_ForName_NoLoad
+#define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir
+#define QERApp_LoadShadersFromDir __SHADERSTABLENAME.m_pfnLoadShadersFromDir
+#define QERApp_CreateShader_ForTextureName __SHADERSTABLENAME.m_pfnCreateShader_ForTextureName
+#define QERApp_GetActiveShaderCount __SHADERSTABLENAME.m_pfnGetActiveShaderCount
+#define QERApp_ActiveShaders_SetDisplayed __SHADERSTABLENAME.m_pfnActiveShaders_SetDisplayed
+#define QERApp_ActiveShader_ForIndex __SHADERSTABLENAME.m_pfnActiveShader_ForIndex
+#define QERApp_ActiveShaders_SetInUse __SHADERSTABLENAME.m_pfnActiveShaders_SetInUse
+#define QERApp_ActiveShader_ForTextureName __SHADERSTABLENAME.m_pfnActiveShader_ForTextureName
+#define QERApp_ActiveShader_ForIndex __SHADERSTABLENAME.m_pfnActiveShader_ForIndex
+#define QERApp_CleanTextureName __SHADERSTABLENAME.m_pfnCleanTextureName
+#endif
+
+#define APPSHADERS_MAJOR "appshaders"
+// FIXME: remove
+static const GUID QERAppShadersTable_GUID = 
+{ 0xec3008a8, 0xbd0b, 0x11d4, { 0x82, 0x51, 0x20, 0x4c, 0x4f, 0x4f, 0x50, 0x20 } };
+
+// g_qeglobals.d_qtextures is used internally by the editor for actual camera drawing
+typedef qtexture_t** (WINAPI* PFN_QTEXTURES)();
+// g_qeglobals.d_qtexmap is a map for fast access
+typedef GHashTable* (WINAPI* PFN_QTEXMAP)();
+// d_texturewin
+//++timo NOTE: this same function is also in isurface.h table, we would eventually have to merge some stuff
+typedef texturewin_t* (* PFN_QEGLOBALSTEXTUREWIN)();
+// Texture_SetTexture
+//++timo NOTE: this one may have to be reorganized too .. putting it here is a bit clumsy
+// NOTE: the C++ function used internally has a lot of default values
+typedef void (WINAPI* PFN_TEXTURESETTEXTURE)(texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef);
+// Texture_ShowInuse
+typedef void (WINAPI* PFN_TEXTURESHOWINUSE)();
+// BuildShaderList
+typedef void (* PFN_BUILDSHADERLIST)();
+// PreloadShaders
+typedef void (* PFN_PRELOADSHADERS)();
+
+// a table that Radiant makes available to the shader module in return
+struct _QERAppShadersTable
+{
+  int m_nSize;
+  PFN_QTEXTURES           m_pfnQTextures;
+  PFN_QTEXMAP             m_pfnQTexmap;
+	PFN_QEGLOBALSTEXTUREWIN	m_pfnQeglobalsTexturewin;
+	PFN_TEXTURESETTEXTURE   m_pfnTexture_SetTexture;
+	PFN_TEXTURESHOWINUSE    m_pfnTexture_ShowInuse;
+  PFN_BUILDSHADERLIST     m_pfnBuildShaderList;
+  PFN_PRELOADSHADERS      m_pfnPreloadShaders;
+};
+
+#ifdef USE_APPSHADERSTABLE_DEFINE
+  #ifndef __APPSHADERTABLENAME
+    #define __APPSHADERTABLENAME g_AppShadersTable
+  #endif
+#define Texture_ShowInuse __APPSHADERTABLENAME.m_pfnTexture_ShowInuse
+#endif
+
+/*!
+NOTE TTimo: there is an important distinction between SHADER_NOT_FOUND and SHADER_NOTEX:
+SHADER_NOT_FOUND means we didn't find the raw texture or the shader for this
+SHADER_NOTEX means we recognize this as a shader script, but we are missing the texture to represent it
+this was in the initial design of the shader code since early GtkRadiant alpha, and got sort of foxed in 1.2 and put back in
+*/
+#define SHADER_NOT_FOUND "textures/radiant/notex"
+#define SHADER_NOTEX "textures/radiant/shadernotex" ///< Q3 tech specific
+
+#endif
diff --git a/include/ishadersmanager.h b/include/ishadersmanager.h
index a9bf0f03..06ac9d32 100644
--- a/include/ishadersmanager.h
+++ b/include/ishadersmanager.h
@@ -1,102 +1,102 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _ISHADERSMANAGER_H_
-#define _ISHADERSMANAGER_H_
-
-class IShadersManager
-{
- public:
-  IShadersManager ();
-  virtual ~IShadersManager ();
-
-  // Increment the number of references to this object
-  virtual void IncRef () = 0;
-  // Decrement the reference count
-  virtual void DecRef () = 0;
-
-  // free all shaders
-  // free the shaders, will not free the qtexture_t*
-  virtual void FreeShaders () = 0;
-
-  // reload all the shaders
-  // this will free everything (shaders and their textures), then reload all in use stuff
-  virtual void ReloadShaders () = 0;
-
-  // load all shaders in a given directory
-  // this will scan the list of in-memory shaders, and load the related qtexture_t if needed
-  virtual void LoadShadersFromDir (const char* path) = 0;
-
-  // load a shader file (ie a set of shaders)
-  // after LoadShaderFile shaders will be in memory, next step is to load the qtexture_t Radiant uses
-  // to represent them if a shader with the same name exists, new one will not be loaded
-  // don't use this to refresh the shaders!
-  virtual void LoadShaderFile (const char* filename) = 0;
-
-  // tell if a given shader exists in our shader table
-  // NOTE: this doesn't tell wether it's corresponding qtexture is loaded 
-  virtual int HasShader (const char* name) = 0;
-
-  // return the shader for a given name
-  // if the qtexture is not already in memory, will try loading it
-  // if the qtexture could not be found, will use default
-  // will return NULL on shader not found
-  virtual IShader* Try_Shader_ForName (const char* name) = 0;
-
-  // return the shader for a given name
-  // if the qtexture is not already in memory, will try loading it
-  // will create a default shader if not found (will use a default texture)
-  virtual IShader* Shader_ForName (const char* name) = 0;
-
-  // query / load a texture
-  // will not try loading a shader, will look for the actual image file ..
-  // returns NULL on file not found
-  // NOTE: strategy for file lookup:
-  //   paths must be relative, ie. textures/me/myfile
-  //   if a 3-letters filename extension (such as .jpg or .tga) is provided, it will get loaded first
-  //   if not found or no extension, will try loading after adding .tga and .jpg (in this order)
-  virtual qtexture_t* Try_Texture_ForName (const char* filename) = 0;
-
-  // query / load a texture
-  // will not try loading a shader, will look for the actual image file ..
-  // on file not found will use the "texture not found"
-  virtual qtexture_t* Texture_ForName (const char* filename) = 0;
-
-  // get the number of active shaders
-  // these are the shaders currently loaded, that have an associated qtexture_t*
-  virtual int GetActiveShaderCount () = 0;
-
-  // for stuff that needs to be represented by a plain texture
-  // the shader will get a "color" name, use GetColor to get the actual color
-  virtual IShader* ColorShader_ForName (const char* name) = 0;
-
-  // reload a shaderfile - update shaders and their display properties/qtexture_t if needed
-  // will not reload the texture files
-  // will switch to "show in use" atfer use
-  // filename must be reletive path of the shader, ex. scripts/gothic_wall.shader
-  virtual void ReloadShaderFile (const char* filename) = 0;
-
-  // retrieve a shader if exists, without loading the textures for it etc.
-  // use this function if you want special info on a shader
-  virtual IShader* Shader_ForName_NoLoad (const char* name) = 0;
-};
-
-#endif // _ISHADERSMANAGER_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _ISHADERSMANAGER_H_
+#define _ISHADERSMANAGER_H_
+
+class IShadersManager
+{
+ public:
+  IShadersManager ();
+  virtual ~IShadersManager ();
+
+  // Increment the number of references to this object
+  virtual void IncRef () = 0;
+  // Decrement the reference count
+  virtual void DecRef () = 0;
+
+  // free all shaders
+  // free the shaders, will not free the qtexture_t*
+  virtual void FreeShaders () = 0;
+
+  // reload all the shaders
+  // this will free everything (shaders and their textures), then reload all in use stuff
+  virtual void ReloadShaders () = 0;
+
+  // load all shaders in a given directory
+  // this will scan the list of in-memory shaders, and load the related qtexture_t if needed
+  virtual void LoadShadersFromDir (const char* path) = 0;
+
+  // load a shader file (ie a set of shaders)
+  // after LoadShaderFile shaders will be in memory, next step is to load the qtexture_t Radiant uses
+  // to represent them if a shader with the same name exists, new one will not be loaded
+  // don't use this to refresh the shaders!
+  virtual void LoadShaderFile (const char* filename) = 0;
+
+  // tell if a given shader exists in our shader table
+  // NOTE: this doesn't tell wether it's corresponding qtexture is loaded 
+  virtual int HasShader (const char* name) = 0;
+
+  // return the shader for a given name
+  // if the qtexture is not already in memory, will try loading it
+  // if the qtexture could not be found, will use default
+  // will return NULL on shader not found
+  virtual IShader* Try_Shader_ForName (const char* name) = 0;
+
+  // return the shader for a given name
+  // if the qtexture is not already in memory, will try loading it
+  // will create a default shader if not found (will use a default texture)
+  virtual IShader* Shader_ForName (const char* name) = 0;
+
+  // query / load a texture
+  // will not try loading a shader, will look for the actual image file ..
+  // returns NULL on file not found
+  // NOTE: strategy for file lookup:
+  //   paths must be relative, ie. textures/me/myfile
+  //   if a 3-letters filename extension (such as .jpg or .tga) is provided, it will get loaded first
+  //   if not found or no extension, will try loading after adding .tga and .jpg (in this order)
+  virtual qtexture_t* Try_Texture_ForName (const char* filename) = 0;
+
+  // query / load a texture
+  // will not try loading a shader, will look for the actual image file ..
+  // on file not found will use the "texture not found"
+  virtual qtexture_t* Texture_ForName (const char* filename) = 0;
+
+  // get the number of active shaders
+  // these are the shaders currently loaded, that have an associated qtexture_t*
+  virtual int GetActiveShaderCount () = 0;
+
+  // for stuff that needs to be represented by a plain texture
+  // the shader will get a "color" name, use GetColor to get the actual color
+  virtual IShader* ColorShader_ForName (const char* name) = 0;
+
+  // reload a shaderfile - update shaders and their display properties/qtexture_t if needed
+  // will not reload the texture files
+  // will switch to "show in use" atfer use
+  // filename must be reletive path of the shader, ex. scripts/gothic_wall.shader
+  virtual void ReloadShaderFile (const char* filename) = 0;
+
+  // retrieve a shader if exists, without loading the textures for it etc.
+  // use this function if you want special info on a shader
+  virtual IShader* Shader_ForName_NoLoad (const char* name) = 0;
+};
+
+#endif // _ISHADERSMANAGER_H_
diff --git a/include/isurfaceplugin.h b/include/isurfaceplugin.h
index 6783bb2c..d7be03fd 100644
--- a/include/isurfaceplugin.h
+++ b/include/isurfaceplugin.h
@@ -1,158 +1,158 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// 
-//
-
-#ifndef __ISURFACEPLUGIN_H_
-#define __ISURFACEPLUGIN_H_
-
-typedef struct _GtkWidget GtkWidget;
-typedef struct _GtkWindow GtkWindow;
-
-#define SURFACEDIALOG_MAJOR "surfdialog"
-
-// there's a void* in each qtexture_t, must be casted to a IPluginTexdef*
-// there's a void* in each face_t, must be casted to a IPluginTexdef*
-// NOTE: IPluginTexdef stores a pointer to the qtexture_t or face_t it's stored in
-// members of IPluginTexdef often access the qtexture_t or face_t they are connected to
-
-// Write texdef needs a function pointer, because Radiant either writes into a FILE or a CMemFile
-typedef void (* PFN_QERAPP_MAPPRINTF) ( char *text, ... );
-
-class IPluginTexdef
-{
-public:
-	// Increment the number of references to this object
-	virtual void IncRef () = 0;
-	// Decrement the reference count
-	virtual void DecRef () = 0;
-};
-
-
-
-// Nurail: For SI module
-class texdef_to_face_t
-{
-public:
-  texdef_to_face_t* next;
-  brush_t *brush;   // Brush faces belong to (for Undo)
-  face_t *face;     // Face of Texdef
-  texdef_t texdef;  // Working texdef
-  texdef_t orig_texdef;  // Original, for baselining changes
-};
-
-
-typedef void (* PFN_QERPLUG_DOSURFACE)			();
-typedef void (* PFN_QERPLUG_TOGGLESURFACE)	();
-typedef void (* PFN_QERPLUG_UPDATESURFACEDIALOG)	();
-typedef void (* PFN_QERPLUG_SURFACEDLGFITALL)	();
-typedef GtkWidget* (* PFN_GET_SI_MODULE_WIDGET) ();
-
-struct _QERPlugSurfaceTable
-{
-	int m_nSize;
-	PFN_QERPLUG_TOGGLESURFACE		m_pfnToggleSurface;
-	PFN_QERPLUG_DOSURFACE				m_pfnDoSurface;
-	PFN_QERPLUG_UPDATESURFACEDIALOG		m_pfnUpdateSurfaceDialog;
-	PFN_QERPLUG_SURFACEDLGFITALL		m_pfnSurfaceDlgFitAll;
-	PFN_GET_SI_MODULE_WIDGET		m_pfnGet_SI_Module_Widget;
-};
-
-// this one is used by the plugin to access some Radiant stuff
-
-#define APPSURFACEDIALOG_MAJOR "appsurfdialog"
-
-// {42BAE4C0-9787-11d3-8EF3-0000E8E8657B}
-static const GUID QERAppSurfaceTable_GUID = 
-{ 0x42bae4c0, 0x9787, 0x11d3, { 0x8e, 0xf3, 0x0, 0x0, 0xe8, 0xe8, 0x65, 0x7b } };
-
-typedef bool (* PFN_PATCHESSELECTED)	();
-// retrieve g_qeglobals.texturewin_t
-//++timo FIXME: this should move in a dedicated table for all g_qeglobals stuff
-typedef texturewin_t* (* PFN_QEGLOBALSTEXTUREWIN) ();
-// look for the first selected patch mesh
-//++timo FIXME: this is a convenient func since there's no way to scan patches ( yet )
-typedef patchMesh_t* (* PFN_GETSELECTEDPATCH) ();
-//++timo FIXME: this one in particular is a hack
-typedef void (* PFN_GETTWOSELECTEDPATCH) (patchMesh_t **p1, patchMesh_t **p2);
-
-
-// leo FIXME: hacks uglier than the ones above
-typedef void (* PFN_TEXMATTOFAKETEXCOORDS) (vec_t texMat[2][3], float shift[2], float *rot, float scale[2]);
-typedef void (* PFN_CONVERTTEXMATWITHQTEXTURE) (brushprimit_texdef_t *texMat1, qtexture_t *qtex1, brushprimit_texdef_t *texMat2, qtexture_t *qtex2);
-typedef void (* PFN_FAKETEXCOORDSTOTEXMAT) (float shift[2], float rot, float scale[2], vec_t texMat[2][3]);
-typedef void (* PFN_PATCH_RESETTEXTURING) (float fx, float fy);
-typedef void (* PFN_PATCH_FITTEXTURING) ();
-typedef void (* PFN_PATCH_NATURALIZESELECTED) (bool bCap);
-typedef const char* (* PFN_PATCH_GETTEXTURENAME) (); 
-typedef qboolean (* PFN_QE_SINGLEBRUSH) (bool bQuiet);
-typedef qboolean (* PFN_ISBRUSHPRIMITMODE) ();
-typedef void (* PFN_SELECT_FITTEXTURE)(int nHeight, int nWidth);
-typedef void (*PFN_COMPUTEAXISBASE)(vec3_t normal,vec3_t texS,vec3_t texT );
-typedef void (*PFN_BPMATMUL)(vec_t A[2][3], vec_t B[2][3], vec_t C[2][3]);
-typedef void (*PFN_EMITBRUSHPRIMITTEXCOORDS)(face_t * f, winding_t * w);
-typedef texdef_t* (*PFN_QEGLOBALSSAVEDINFO_SIINC) ();
-typedef float (* PFN_QEGLOBALSGETGRIDSIZE) ();
-typedef void (* PFN_FACELIST_FITTEXTURE) (texdef_to_face_t* texdef_face_list, int nHeight, int nWidth);
-typedef GtkWindow* (* PFN_GETMAINWINDOW)();
-typedef void (* PFN_SETWINPOS_FROM_PREFS) (GtkWidget *win);
-typedef int (* PFN_GETSELECTEDFACECOUNT_BRUSH) ();
-typedef void (* PFN_GETSELFACESTEXDEF) (texdef_to_face_t *);
-typedef void (* PFN_SETTEXDEF_FACELIST) (texdef_to_face_t* texdef_face_list, bool b_SetUndoPoint, bool bFit_to_Scale);
-typedef void (* PFN_SETACTIVEINRADIANT) ();
-
-
-struct _QERAppSurfaceTable
-{
-  int m_nSize;
-  PFN_PATCHESSELECTED		m_pfnOnlyPatchesSelected;
-  PFN_PATCHESSELECTED		m_pfnAnyPatchesSelected;
-  PFN_GETSELECTEDPATCH		m_pfnGetSelectedPatch;
-  PFN_GETTWOSELECTEDPATCH		m_pfnGetTwoSelectedPatch;
-  PFN_TEXMATTOFAKETEXCOORDS	m_pfnTexMatToFakeTexCoords;
-  PFN_CONVERTTEXMATWITHQTEXTURE	m_pfnConvertTexMatWithQTexture;
-  PFN_FAKETEXCOORDSTOTEXMAT	m_pfnFakeTexCoordsToTexMat;
-  PFN_PATCH_RESETTEXTURING	m_pfnPatch_ResetTexturing;
-  PFN_PATCH_FITTEXTURING		m_pfnPatch_FitTexturing;
-  PFN_PATCH_NATURALIZESELECTED	m_pfnPatch_NaturalizeSelected;
-  PFN_PATCH_GETTEXTURENAME	m_pfnPatch_GetTextureName;
-  PFN_QE_SINGLEBRUSH		m_pfnQE_SingleBrush;
-  PFN_ISBRUSHPRIMITMODE		m_pfnIsBrushPrimitMode;
-  PFN_COMPUTEAXISBASE		m_pfnComputeAxisBase;
-  PFN_BPMATMUL			m_pfnBPMatMul;
-  PFN_EMITBRUSHPRIMITTEXCOORDS	m_pfnEmitBrushPrimitTextureCoordinates;
-  PFN_QEGLOBALSTEXTUREWIN		m_pfnQeglobalsTexturewin;
-  PFN_SELECT_FITTEXTURE		m_pfnSelect_FitTexture;
-  PFN_QEGLOBALSSAVEDINFO_SIINC		m_pfnQERApp_QeglobalsSavedinfo_SIInc;
-  PFN_QEGLOBALSGETGRIDSIZE	m_pfnQeglobalsGetGridSize;
-  PFN_FACELIST_FITTEXTURE		m_pfnFaceList_FitTexture;
-  PFN_GETMAINWINDOW		m_pfnGetMainWindow;
-  PFN_SETWINPOS_FROM_PREFS	m_pfnSetWinPos_From_Prefs;
-  PFN_GETSELECTEDFACECOUNT_BRUSH  m_pfnGetSelectedFaceCountfromBrushes;
-  PFN_GETSELFACESTEXDEF		m_pfnGetSelFacesTexdef;
-  PFN_SETTEXDEF_FACELIST		m_pfnSetTexdef_FaceList;
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// 
+//
+
+#ifndef __ISURFACEPLUGIN_H_
+#define __ISURFACEPLUGIN_H_
+
+typedef struct _GtkWidget GtkWidget;
+typedef struct _GtkWindow GtkWindow;
+
+#define SURFACEDIALOG_MAJOR "surfdialog"
+
+// there's a void* in each qtexture_t, must be casted to a IPluginTexdef*
+// there's a void* in each face_t, must be casted to a IPluginTexdef*
+// NOTE: IPluginTexdef stores a pointer to the qtexture_t or face_t it's stored in
+// members of IPluginTexdef often access the qtexture_t or face_t they are connected to
+
+// Write texdef needs a function pointer, because Radiant either writes into a FILE or a CMemFile
+typedef void (* PFN_QERAPP_MAPPRINTF) ( char *text, ... );
+
+class IPluginTexdef
+{
+public:
+	// Increment the number of references to this object
+	virtual void IncRef () = 0;
+	// Decrement the reference count
+	virtual void DecRef () = 0;
+};
+
+
+
+// Nurail: For SI module
+class texdef_to_face_t
+{
+public:
+  texdef_to_face_t* next;
+  brush_t *brush;   // Brush faces belong to (for Undo)
+  face_t *face;     // Face of Texdef
+  texdef_t texdef;  // Working texdef
+  texdef_t orig_texdef;  // Original, for baselining changes
+};
+
+
+typedef void (* PFN_QERPLUG_DOSURFACE)			();
+typedef void (* PFN_QERPLUG_TOGGLESURFACE)	();
+typedef void (* PFN_QERPLUG_UPDATESURFACEDIALOG)	();
+typedef void (* PFN_QERPLUG_SURFACEDLGFITALL)	();
+typedef GtkWidget* (* PFN_GET_SI_MODULE_WIDGET) ();
+
+struct _QERPlugSurfaceTable
+{
+	int m_nSize;
+	PFN_QERPLUG_TOGGLESURFACE		m_pfnToggleSurface;
+	PFN_QERPLUG_DOSURFACE				m_pfnDoSurface;
+	PFN_QERPLUG_UPDATESURFACEDIALOG		m_pfnUpdateSurfaceDialog;
+	PFN_QERPLUG_SURFACEDLGFITALL		m_pfnSurfaceDlgFitAll;
+	PFN_GET_SI_MODULE_WIDGET		m_pfnGet_SI_Module_Widget;
+};
+
+// this one is used by the plugin to access some Radiant stuff
+
+#define APPSURFACEDIALOG_MAJOR "appsurfdialog"
+
+// {42BAE4C0-9787-11d3-8EF3-0000E8E8657B}
+static const GUID QERAppSurfaceTable_GUID = 
+{ 0x42bae4c0, 0x9787, 0x11d3, { 0x8e, 0xf3, 0x0, 0x0, 0xe8, 0xe8, 0x65, 0x7b } };
+
+typedef bool (* PFN_PATCHESSELECTED)	();
+// retrieve g_qeglobals.texturewin_t
+//++timo FIXME: this should move in a dedicated table for all g_qeglobals stuff
+typedef texturewin_t* (* PFN_QEGLOBALSTEXTUREWIN) ();
+// look for the first selected patch mesh
+//++timo FIXME: this is a convenient func since there's no way to scan patches ( yet )
+typedef patchMesh_t* (* PFN_GETSELECTEDPATCH) ();
+//++timo FIXME: this one in particular is a hack
+typedef void (* PFN_GETTWOSELECTEDPATCH) (patchMesh_t **p1, patchMesh_t **p2);
+
+
+// leo FIXME: hacks uglier than the ones above
+typedef void (* PFN_TEXMATTOFAKETEXCOORDS) (vec_t texMat[2][3], float shift[2], float *rot, float scale[2]);
+typedef void (* PFN_CONVERTTEXMATWITHQTEXTURE) (brushprimit_texdef_t *texMat1, qtexture_t *qtex1, brushprimit_texdef_t *texMat2, qtexture_t *qtex2);
+typedef void (* PFN_FAKETEXCOORDSTOTEXMAT) (float shift[2], float rot, float scale[2], vec_t texMat[2][3]);
+typedef void (* PFN_PATCH_RESETTEXTURING) (float fx, float fy);
+typedef void (* PFN_PATCH_FITTEXTURING) ();
+typedef void (* PFN_PATCH_NATURALIZESELECTED) (bool bCap);
+typedef const char* (* PFN_PATCH_GETTEXTURENAME) (); 
+typedef qboolean (* PFN_QE_SINGLEBRUSH) (bool bQuiet);
+typedef qboolean (* PFN_ISBRUSHPRIMITMODE) ();
+typedef void (* PFN_SELECT_FITTEXTURE)(int nHeight, int nWidth);
+typedef void (*PFN_COMPUTEAXISBASE)(vec3_t normal,vec3_t texS,vec3_t texT );
+typedef void (*PFN_BPMATMUL)(vec_t A[2][3], vec_t B[2][3], vec_t C[2][3]);
+typedef void (*PFN_EMITBRUSHPRIMITTEXCOORDS)(face_t * f, winding_t * w);
+typedef texdef_t* (*PFN_QEGLOBALSSAVEDINFO_SIINC) ();
+typedef float (* PFN_QEGLOBALSGETGRIDSIZE) ();
+typedef void (* PFN_FACELIST_FITTEXTURE) (texdef_to_face_t* texdef_face_list, int nHeight, int nWidth);
+typedef GtkWindow* (* PFN_GETMAINWINDOW)();
+typedef void (* PFN_SETWINPOS_FROM_PREFS) (GtkWidget *win);
+typedef int (* PFN_GETSELECTEDFACECOUNT_BRUSH) ();
+typedef void (* PFN_GETSELFACESTEXDEF) (texdef_to_face_t *);
+typedef void (* PFN_SETTEXDEF_FACELIST) (texdef_to_face_t* texdef_face_list, bool b_SetUndoPoint, bool bFit_to_Scale);
+typedef void (* PFN_SETACTIVEINRADIANT) ();
+
+
+struct _QERAppSurfaceTable
+{
+  int m_nSize;
+  PFN_PATCHESSELECTED		m_pfnOnlyPatchesSelected;
+  PFN_PATCHESSELECTED		m_pfnAnyPatchesSelected;
+  PFN_GETSELECTEDPATCH		m_pfnGetSelectedPatch;
+  PFN_GETTWOSELECTEDPATCH		m_pfnGetTwoSelectedPatch;
+  PFN_TEXMATTOFAKETEXCOORDS	m_pfnTexMatToFakeTexCoords;
+  PFN_CONVERTTEXMATWITHQTEXTURE	m_pfnConvertTexMatWithQTexture;
+  PFN_FAKETEXCOORDSTOTEXMAT	m_pfnFakeTexCoordsToTexMat;
+  PFN_PATCH_RESETTEXTURING	m_pfnPatch_ResetTexturing;
+  PFN_PATCH_FITTEXTURING		m_pfnPatch_FitTexturing;
+  PFN_PATCH_NATURALIZESELECTED	m_pfnPatch_NaturalizeSelected;
+  PFN_PATCH_GETTEXTURENAME	m_pfnPatch_GetTextureName;
+  PFN_QE_SINGLEBRUSH		m_pfnQE_SingleBrush;
+  PFN_ISBRUSHPRIMITMODE		m_pfnIsBrushPrimitMode;
+  PFN_COMPUTEAXISBASE		m_pfnComputeAxisBase;
+  PFN_BPMATMUL			m_pfnBPMatMul;
+  PFN_EMITBRUSHPRIMITTEXCOORDS	m_pfnEmitBrushPrimitTextureCoordinates;
+  PFN_QEGLOBALSTEXTUREWIN		m_pfnQeglobalsTexturewin;
+  PFN_SELECT_FITTEXTURE		m_pfnSelect_FitTexture;
+  PFN_QEGLOBALSSAVEDINFO_SIINC		m_pfnQERApp_QeglobalsSavedinfo_SIInc;
+  PFN_QEGLOBALSGETGRIDSIZE	m_pfnQeglobalsGetGridSize;
+  PFN_FACELIST_FITTEXTURE		m_pfnFaceList_FitTexture;
+  PFN_GETMAINWINDOW		m_pfnGetMainWindow;
+  PFN_SETWINPOS_FROM_PREFS	m_pfnSetWinPos_From_Prefs;
+  PFN_GETSELECTEDFACECOUNT_BRUSH  m_pfnGetSelectedFaceCountfromBrushes;
+  PFN_GETSELFACESTEXDEF		m_pfnGetSelFacesTexdef;
+  PFN_SETTEXDEF_FACELIST		m_pfnSetTexdef_FaceList;
+};
+
+#endif
diff --git a/include/itoolbar.h b/include/itoolbar.h
index 05a05559..221938f6 100644
--- a/include/itoolbar.h
+++ b/include/itoolbar.h
@@ -1,61 +1,61 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __IPLUGTOOLBAR_H_
-#define __IPLUGTOOLBAR_H_
-
-/*
-NOTE: this API requires Gtk
-it's a good practice to avoid putting #include <gtk/gtk.h> here
-in some cases, the compiler will get confused because of 'list' identifiers between Gtk and STL headers
-*/
-
-#define TOOLBAR_MAJOR "toolbar"
-
-class IToolbarButton
-{
-public:
-  enum EType
-  {
-    eSpace,
-    eButton,
-    eToggleButton,
-    eRadioButton,
-  };
-
-  virtual const char* getImage() const = 0;
-  virtual const char* getText() const = 0;
-  virtual const char* getTooltip() const = 0;
-  virtual EType getType() const = 0;
-  virtual void activate() const = 0;
-};
-
-typedef unsigned int  (* PFN_TOOLBARBUTTONCOUNT)();
-typedef const IToolbarButton* (* PFN_GETTOOLBARBUTTON)(unsigned int index);
-
-struct _QERPlugToolbarTable
-{
-  int m_nSize;
-  PFN_TOOLBARBUTTONCOUNT m_pfnToolbarButtonCount;
-  PFN_GETTOOLBARBUTTON   m_pfnGetToolbarButton;
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __IPLUGTOOLBAR_H_
+#define __IPLUGTOOLBAR_H_
+
+/*
+NOTE: this API requires Gtk
+it's a good practice to avoid putting #include <gtk/gtk.h> here
+in some cases, the compiler will get confused because of 'list' identifiers between Gtk and STL headers
+*/
+
+#define TOOLBAR_MAJOR "toolbar"
+
+class IToolbarButton
+{
+public:
+  enum EType
+  {
+    eSpace,
+    eButton,
+    eToggleButton,
+    eRadioButton,
+  };
+
+  virtual const char* getImage() const = 0;
+  virtual const char* getText() const = 0;
+  virtual const char* getTooltip() const = 0;
+  virtual EType getType() const = 0;
+  virtual void activate() const = 0;
+};
+
+typedef unsigned int  (* PFN_TOOLBARBUTTONCOUNT)();
+typedef const IToolbarButton* (* PFN_GETTOOLBARBUTTON)(unsigned int index);
+
+struct _QERPlugToolbarTable
+{
+  int m_nSize;
+  PFN_TOOLBARBUTTONCOUNT m_pfnToolbarButtonCount;
+  PFN_GETTOOLBARBUTTON   m_pfnGetToolbarButton;
+};
+
+#endif
diff --git a/include/iui.h b/include/iui.h
index 16b7c8cd..d3af6777 100644
--- a/include/iui.h
+++ b/include/iui.h
@@ -1,158 +1,158 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// interface for all-purpose messaging and UI
-// window class for MFC, Gtk or Q3 UI
-// each version of Radiant implements the API, using the native code that it needs
-
-#ifndef __IUI_H_
-#define __IUI_H_
-
-// this one can be hooked in the GL window procs for customizing GUI through plugins
-// the class is implemented by the plugin module, and given to Radiant who calls into it
-class IWindowListener
-{
-public:
-  // Increment the number of references to this object
-  virtual void IncRef () = 0;
-  // Decrement the reference count
-  virtual void DecRef () = 0;
-  // since Radiant is MFC we don't use a WNDPROC, we wrap the MFC handlers
-  // the handler is called first, if returns false Radiant continues processing
-  //++timo maybe add more later ? OnKeyUp and OnKeyDown for instance
-  //++timo TODO: add handlers everywhere
-  // Gef: Changed 2nd & 3rd params to gdouble's for sub-integer grid sizes
-  virtual bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y) = 0;
-  virtual bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y) = 0;
-  virtual bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y) = 0;
-  virtual bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y) = 0;
-  virtual bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y) = 0;
-  virtual bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y) = 0;
-  virtual bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y) = 0;
-  virtual bool OnKeyPressed(char *s) = 0;
-
-  // paint message, the caller makes the GL context current, calls Paint, then swaps GL buffers
-  // return value might be false if something failed and closure is requested .. then the buffer swap will be cancelled
-  virtual bool Paint() = 0;
-  // window is closing (nothing you can do, just telling)
-  virtual void Close() = 0;
-};
-
-// IWindowListener with additional properties
-// NOTE: for now it is both a window and the GL widget
-//   in the case of Gtk, there are two widgets, the window widget (a container) and the GL widget
-class IWindow
-{
-public:
-  // Increment the number of references to this object
-  virtual void IncRef () = 0;
-  // Decrement the reference count
-  virtual void DecRef () = 0;
-  // misc data ------------------------------------------------
-  // get pixel size
-  virtual int getHeight() = 0;
-  virtual int getWidth() = 0;
-  // initialisation stuff -------------------------------------
-  // set pixel size and other parameters before showing it
-  virtual void setSizeParm(int width, int height) = 0;
-  // set the IWindowListener (implemented by the plugin using this window)
-  virtual void setListener(IWindowListener *) = 0;
-  // set the window name
-  virtual void setName(char *) = 0;
-  // will actually create the GL and the window based on the parameters
-  virtual bool Show() = 0;
-  // commands -------------------------------------------------
-  // call this to ask for a Redraw
-  virtual void Redraw() = 0;
-};
-
-// various Radiant messages --------
-// this one holds the total number of supported messages (this is used to allocate structs)
-#define RADIANT_MSGCOUNT 5
-// they start with a 0, can be indexed in an array
-// something was selected / deselected
-#define RADIANT_SELECTION 0
-// a brush face was selected / deselected
-#define RADIANT_SFACE     1
-// current texture / shader changed
-#define RADIANT_TEXTURE   2
-// Radiant is going to enter "sleep mode" (all GL contexts will be destroyed)
-#define RADIANT_SLEEP     3
-// Radiant has left "sleep mode" (GL contexts are recreated)
-#define RADIANT_WAKEUP    4
-
-
-// this one can be used to listen for Radiant-specific events, not related to a window
-class IListener
-{
-public:
-  // Increment the number of references to this object
-  virtual void IncRef () = 0;
-  // Decrement the reference count
-  virtual void DecRef () = 0;
-  // message is one of the RADIANT_* consts
-  virtual void DispatchRadiantMsg( int Msg ) = 0;
-};
-
-// this one is provided by Radiant, it's a wrapper for some usefull functions
-class IXYWndWrapper
-{
-public:
-  virtual void SnapToGrid( int x1, int y1, vec3_t pt ) = 0;
-  virtual VIEWTYPE GetViewType( void ) = 0;
-};
-
-#define UI_MAJOR "ui"
-
-// create an IWindow with GL context
-typedef IWindow* (WINAPI* PFN_QERAPP_CREATEGLWINDOW) ();
-
-// will hook the given IWindowListener to the XY window and increment the ref count
-//++timo TODO: add hooking in the CAM view and Z view
-typedef void (WINAPI* PFN_QERAPP_HOOKWINDOW)	(IWindowListener *);
-// will unhook the given IWindowListener
-typedef void (WINAPI* PFN_QERAPP_UNHOOKWINDOW)	(IWindowListener *);
-// to retrieve the IXYWndWrapper
-typedef IXYWndWrapper* (WINAPI* PFN_QERAPP_GETXYWNDWRAPPER)	();
-
-// will hook a given listener into Radiant listening for the given message and increment ref count
-// call several times to listen for several messages
-typedef void (WINAPI* PFN_QERAPP_HOOKLISTENER)	(IListener *, int Msg);
-// will unhook the listener and return the number of messages the given listener was removed from
-typedef int  (WINAPI* PFN_QERAPP_UNHOOKLISTENER)(IListener *);
-
-// TODO: create GL widget, destroy it
-
-struct _QERUITable
-{
-  int m_nSize;
-  PFN_QERAPP_CREATEGLWINDOW m_pfnCreateGLWindow;
-  PFN_QERAPP_HOOKWINDOW		m_pfnHookWindow;
-  PFN_QERAPP_UNHOOKWINDOW	m_pfnUnHookWindow;
-  PFN_QERAPP_GETXYWNDWRAPPER	m_pfnGetXYWndWrapper;
-  PFN_QERAPP_HOOKLISTENER	m_pfnHookListener;
-  PFN_QERAPP_UNHOOKLISTENER	m_pfnUnHookListener;
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// interface for all-purpose messaging and UI
+// window class for MFC, Gtk or Q3 UI
+// each version of Radiant implements the API, using the native code that it needs
+
+#ifndef __IUI_H_
+#define __IUI_H_
+
+// this one can be hooked in the GL window procs for customizing GUI through plugins
+// the class is implemented by the plugin module, and given to Radiant who calls into it
+class IWindowListener
+{
+public:
+  // Increment the number of references to this object
+  virtual void IncRef () = 0;
+  // Decrement the reference count
+  virtual void DecRef () = 0;
+  // since Radiant is MFC we don't use a WNDPROC, we wrap the MFC handlers
+  // the handler is called first, if returns false Radiant continues processing
+  //++timo maybe add more later ? OnKeyUp and OnKeyDown for instance
+  //++timo TODO: add handlers everywhere
+  // Gef: Changed 2nd & 3rd params to gdouble's for sub-integer grid sizes
+  virtual bool OnLButtonDown(guint32 nFlags, gdouble x, gdouble y) = 0;
+  virtual bool OnMButtonDown(guint32 nFlags, gdouble x, gdouble y) = 0;
+  virtual bool OnRButtonDown(guint32 nFlags, gdouble x, gdouble y) = 0;
+  virtual bool OnLButtonUp(guint32 nFlags, gdouble x, gdouble y) = 0;
+  virtual bool OnMButtonUp(guint32 nFlags, gdouble x, gdouble y) = 0;
+  virtual bool OnRButtonUp(guint32 nFlags, gdouble x, gdouble y) = 0;
+  virtual bool OnMouseMove(guint32 nFlags, gdouble x, gdouble y) = 0;
+  virtual bool OnKeyPressed(char *s) = 0;
+
+  // paint message, the caller makes the GL context current, calls Paint, then swaps GL buffers
+  // return value might be false if something failed and closure is requested .. then the buffer swap will be cancelled
+  virtual bool Paint() = 0;
+  // window is closing (nothing you can do, just telling)
+  virtual void Close() = 0;
+};
+
+// IWindowListener with additional properties
+// NOTE: for now it is both a window and the GL widget
+//   in the case of Gtk, there are two widgets, the window widget (a container) and the GL widget
+class IWindow
+{
+public:
+  // Increment the number of references to this object
+  virtual void IncRef () = 0;
+  // Decrement the reference count
+  virtual void DecRef () = 0;
+  // misc data ------------------------------------------------
+  // get pixel size
+  virtual int getHeight() = 0;
+  virtual int getWidth() = 0;
+  // initialisation stuff -------------------------------------
+  // set pixel size and other parameters before showing it
+  virtual void setSizeParm(int width, int height) = 0;
+  // set the IWindowListener (implemented by the plugin using this window)
+  virtual void setListener(IWindowListener *) = 0;
+  // set the window name
+  virtual void setName(char *) = 0;
+  // will actually create the GL and the window based on the parameters
+  virtual bool Show() = 0;
+  // commands -------------------------------------------------
+  // call this to ask for a Redraw
+  virtual void Redraw() = 0;
+};
+
+// various Radiant messages --------
+// this one holds the total number of supported messages (this is used to allocate structs)
+#define RADIANT_MSGCOUNT 5
+// they start with a 0, can be indexed in an array
+// something was selected / deselected
+#define RADIANT_SELECTION 0
+// a brush face was selected / deselected
+#define RADIANT_SFACE     1
+// current texture / shader changed
+#define RADIANT_TEXTURE   2
+// Radiant is going to enter "sleep mode" (all GL contexts will be destroyed)
+#define RADIANT_SLEEP     3
+// Radiant has left "sleep mode" (GL contexts are recreated)
+#define RADIANT_WAKEUP    4
+
+
+// this one can be used to listen for Radiant-specific events, not related to a window
+class IListener
+{
+public:
+  // Increment the number of references to this object
+  virtual void IncRef () = 0;
+  // Decrement the reference count
+  virtual void DecRef () = 0;
+  // message is one of the RADIANT_* consts
+  virtual void DispatchRadiantMsg( int Msg ) = 0;
+};
+
+// this one is provided by Radiant, it's a wrapper for some usefull functions
+class IXYWndWrapper
+{
+public:
+  virtual void SnapToGrid( int x1, int y1, vec3_t pt ) = 0;
+  virtual VIEWTYPE GetViewType( void ) = 0;
+};
+
+#define UI_MAJOR "ui"
+
+// create an IWindow with GL context
+typedef IWindow* (WINAPI* PFN_QERAPP_CREATEGLWINDOW) ();
+
+// will hook the given IWindowListener to the XY window and increment the ref count
+//++timo TODO: add hooking in the CAM view and Z view
+typedef void (WINAPI* PFN_QERAPP_HOOKWINDOW)	(IWindowListener *);
+// will unhook the given IWindowListener
+typedef void (WINAPI* PFN_QERAPP_UNHOOKWINDOW)	(IWindowListener *);
+// to retrieve the IXYWndWrapper
+typedef IXYWndWrapper* (WINAPI* PFN_QERAPP_GETXYWNDWRAPPER)	();
+
+// will hook a given listener into Radiant listening for the given message and increment ref count
+// call several times to listen for several messages
+typedef void (WINAPI* PFN_QERAPP_HOOKLISTENER)	(IListener *, int Msg);
+// will unhook the listener and return the number of messages the given listener was removed from
+typedef int  (WINAPI* PFN_QERAPP_UNHOOKLISTENER)(IListener *);
+
+// TODO: create GL widget, destroy it
+
+struct _QERUITable
+{
+  int m_nSize;
+  PFN_QERAPP_CREATEGLWINDOW m_pfnCreateGLWindow;
+  PFN_QERAPP_HOOKWINDOW		m_pfnHookWindow;
+  PFN_QERAPP_UNHOOKWINDOW	m_pfnUnHookWindow;
+  PFN_QERAPP_GETXYWNDWRAPPER	m_pfnGetXYWndWrapper;
+  PFN_QERAPP_HOOKLISTENER	m_pfnHookListener;
+  PFN_QERAPP_UNHOOKLISTENER	m_pfnUnHookListener;
+};
+
+#endif
diff --git a/include/iui_gtk.h b/include/iui_gtk.h
index 5cd820c4..93973672 100644
--- a/include/iui_gtk.h
+++ b/include/iui_gtk.h
@@ -1,59 +1,59 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION
-// This contains functions specific to the UI toolkit
-//   it is best to avoid using them, but they are provided for backward compatibility with the older interfaces
-//   the abstracted UI layer in iUI.h is not sufficient for some tasks .. no other choice than to rely on UI specific code
-
-#ifndef __IGL_GTK_H__
-#define __IGL_GTK_H__
-
-#define UIGTK_MAJOR "uigtk"
-
-// All OpenGL stuff is handled by GLWidget to ensure portability
-typedef GtkWidget* (WINAPI* PFN_QERAPP_GETQEGLOBALSGLWIDGET) (); 
-typedef GtkWidget* (WINAPI* PFN_GLWIDGET_NEW) (gboolean zbufffer, GtkWidget* share);
-typedef void       (WINAPI* PFN_GLWIDGET_SWAPBUFFERS) (GtkWidget* widget);
-typedef gboolean   (WINAPI* PFN_GLWIDGET_MAKECURRENT) (GtkWidget* widget);
-typedef void       (WINAPI* PFN_GLWIDGET_DESTROYCONTEXT) (GtkWidget* widget);
-typedef void       (WINAPI* PFN_GLWIDGET_CREATECONTEXT) (GtkWidget* widget);
-#if 0
-typedef gpointer   (WINAPI* PFN_GLWIDGET_GETCONTEXT) (GtkWidget* widget);
-#endif
-
-struct _QERUIGtkTable
-{
-  int m_nSize;
-  PFN_QERAPP_GETQEGLOBALSGLWIDGET       m_pfn_GetQeglobalsGLWidget;
-  PFN_GLWIDGET_NEW                      m_pfn_glwidget_new;
-  PFN_GLWIDGET_SWAPBUFFERS              m_pfn_glwidget_swap_buffers;
-  PFN_GLWIDGET_MAKECURRENT              m_pfn_glwidget_make_current;
-  PFN_GLWIDGET_DESTROYCONTEXT           m_pfn_glwidget_destroy_context;
-  PFN_GLWIDGET_CREATECONTEXT            m_pfn_glwidget_create_context;
-#if 0
-  PFN_GLWIDGET_GETCONTEXT               m_pfn_glwidget_get_context;
-#endif
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION
+// This contains functions specific to the UI toolkit
+//   it is best to avoid using them, but they are provided for backward compatibility with the older interfaces
+//   the abstracted UI layer in iUI.h is not sufficient for some tasks .. no other choice than to rely on UI specific code
+
+#ifndef __IGL_GTK_H__
+#define __IGL_GTK_H__
+
+#define UIGTK_MAJOR "uigtk"
+
+// All OpenGL stuff is handled by GLWidget to ensure portability
+typedef GtkWidget* (WINAPI* PFN_QERAPP_GETQEGLOBALSGLWIDGET) (); 
+typedef GtkWidget* (WINAPI* PFN_GLWIDGET_NEW) (gboolean zbufffer, GtkWidget* share);
+typedef void       (WINAPI* PFN_GLWIDGET_SWAPBUFFERS) (GtkWidget* widget);
+typedef gboolean   (WINAPI* PFN_GLWIDGET_MAKECURRENT) (GtkWidget* widget);
+typedef void       (WINAPI* PFN_GLWIDGET_DESTROYCONTEXT) (GtkWidget* widget);
+typedef void       (WINAPI* PFN_GLWIDGET_CREATECONTEXT) (GtkWidget* widget);
+#if 0
+typedef gpointer   (WINAPI* PFN_GLWIDGET_GETCONTEXT) (GtkWidget* widget);
+#endif
+
+struct _QERUIGtkTable
+{
+  int m_nSize;
+  PFN_QERAPP_GETQEGLOBALSGLWIDGET       m_pfn_GetQeglobalsGLWidget;
+  PFN_GLWIDGET_NEW                      m_pfn_glwidget_new;
+  PFN_GLWIDGET_SWAPBUFFERS              m_pfn_glwidget_swap_buffers;
+  PFN_GLWIDGET_MAKECURRENT              m_pfn_glwidget_make_current;
+  PFN_GLWIDGET_DESTROYCONTEXT           m_pfn_glwidget_destroy_context;
+  PFN_GLWIDGET_CREATECONTEXT            m_pfn_glwidget_create_context;
+#if 0
+  PFN_GLWIDGET_GETCONTEXT               m_pfn_glwidget_get_context;
+#endif
+};
+
+#endif
diff --git a/include/iundo.h b/include/iundo.h
index d5194b52..b4fffeec 100644
--- a/include/iundo.h
+++ b/include/iundo.h
@@ -1,87 +1,87 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IUNDO_H_
-#define _IUNDO_H_
-
-#define UNDO_MAJOR "undo"
-
-//start operation
-typedef void (*PFN_UNDOSTART) (char *operation);
-//end operation
-typedef void (*PFN_UNDOEND) (void);
-//add brush to the undo
-typedef void (*PFN_UNDOADDBRUSH) (brush_t *pBrush);
-//end a brush after the operation is performed
-typedef void (*PFN_UNDOENDBRUSH) (brush_t *pBrush);
-//add a list with brushes to the undo
-typedef void (*PFN_UNDOADDBRUSHLIST) (brush_t *brushlist);
-//end a list with brushes after the operation is performed
-typedef void (*PFN_UNDOENDBRUSHLIST) (brush_t *brushlist);
-//add entity to undo
-typedef void (*PFN_UNDOADDENTITY) (entity_t *entity);
-//end an entity after the operation is performed
-typedef void (*PFN_UNDOENDENTITY) (entity_t *entity);
-//undo last operation (bSilent == true -> will not print the "undone blah blah message")
-typedef void (*PFN_UNDO) (unsigned char bSilent);
-//redo last undone operation
-typedef void (*PFN_REDO) (void);
-//get the undo Id of the next undo (0 if none available)
-typedef int (*PFN_GETUNDOID) (void);
-//returns true if there is something to be undone available
-typedef int  (*PFN_UNDOAVAILABLE) (void);
-//returns true if there is something to redo available
-typedef int  (*PFN_REDOAVAILABLE) (void);
-
-struct _QERUndoTable
-{
-  int m_nSize;
-  PFN_UNDOSTART m_pfnUndo_Start;
-  PFN_UNDOEND m_pfnUndo_End;
-  PFN_UNDOADDBRUSH m_pfnUndo_AddBrush;
-  PFN_UNDOENDBRUSH m_pfnUndo_EndBrush;
-  PFN_UNDOADDBRUSHLIST m_pfnUndo_AddBrushList;
-  PFN_UNDOENDBRUSHLIST m_pfnUndo_EndBrushList;
-  PFN_UNDOADDENTITY m_pfnUndo_AddEntity;
-  PFN_UNDOENDENTITY m_pfnUndo_EndEntity;
-  PFN_UNDO m_pfnUndo_Undo;
-  PFN_REDO m_pfnUndo_Redo;
-  PFN_GETUNDOID m_pfnUndo_GetUndoId;
-  PFN_UNDOAVAILABLE m_pfnUndo_UndoAvailable;
-  PFN_REDOAVAILABLE m_pfnUndo_RedoAvailable;
-};
-
-#ifdef USE_UNDOTABLE_DEFINE
-#ifndef __UNDOTABLENAME
-#define __UNDOTABLENAME g_UndoTable
-#endif
-#define Undo_Start __UNDOTABLENAME.m_pfnUndo_Start
-#define Undo_End __UNDOTABLENAME.m_pfnUndo_End
-#define Undo_AddBrush __UNDOTABLENAME.m_pfnUndo_AddBrush
-#define Undo_EndBrush __UNDOTABLENAME.m_pfnUndo_EndBrush
-#define Undo_AddBrushList __UNDOTABLENAME.m_pfnUndo_AddBrushList
-#define Undo_EndBrushList __UNDOTABLENAME.m_pfnUndo_EndBrushList
-#define Undo_AddEntity __UNDOTABLENAME.m_pfnUndo_AddEntity
-#define Undo_EndEntity __UNDOTABLENAME.m_pfnUndo_EndEntity
-#endif
-
-#endif // _IUNDO_H_
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IUNDO_H_
+#define _IUNDO_H_
+
+#define UNDO_MAJOR "undo"
+
+//start operation
+typedef void (*PFN_UNDOSTART) (char *operation);
+//end operation
+typedef void (*PFN_UNDOEND) (void);
+//add brush to the undo
+typedef void (*PFN_UNDOADDBRUSH) (brush_t *pBrush);
+//end a brush after the operation is performed
+typedef void (*PFN_UNDOENDBRUSH) (brush_t *pBrush);
+//add a list with brushes to the undo
+typedef void (*PFN_UNDOADDBRUSHLIST) (brush_t *brushlist);
+//end a list with brushes after the operation is performed
+typedef void (*PFN_UNDOENDBRUSHLIST) (brush_t *brushlist);
+//add entity to undo
+typedef void (*PFN_UNDOADDENTITY) (entity_t *entity);
+//end an entity after the operation is performed
+typedef void (*PFN_UNDOENDENTITY) (entity_t *entity);
+//undo last operation (bSilent == true -> will not print the "undone blah blah message")
+typedef void (*PFN_UNDO) (unsigned char bSilent);
+//redo last undone operation
+typedef void (*PFN_REDO) (void);
+//get the undo Id of the next undo (0 if none available)
+typedef int (*PFN_GETUNDOID) (void);
+//returns true if there is something to be undone available
+typedef int  (*PFN_UNDOAVAILABLE) (void);
+//returns true if there is something to redo available
+typedef int  (*PFN_REDOAVAILABLE) (void);
+
+struct _QERUndoTable
+{
+  int m_nSize;
+  PFN_UNDOSTART m_pfnUndo_Start;
+  PFN_UNDOEND m_pfnUndo_End;
+  PFN_UNDOADDBRUSH m_pfnUndo_AddBrush;
+  PFN_UNDOENDBRUSH m_pfnUndo_EndBrush;
+  PFN_UNDOADDBRUSHLIST m_pfnUndo_AddBrushList;
+  PFN_UNDOENDBRUSHLIST m_pfnUndo_EndBrushList;
+  PFN_UNDOADDENTITY m_pfnUndo_AddEntity;
+  PFN_UNDOENDENTITY m_pfnUndo_EndEntity;
+  PFN_UNDO m_pfnUndo_Undo;
+  PFN_REDO m_pfnUndo_Redo;
+  PFN_GETUNDOID m_pfnUndo_GetUndoId;
+  PFN_UNDOAVAILABLE m_pfnUndo_UndoAvailable;
+  PFN_REDOAVAILABLE m_pfnUndo_RedoAvailable;
+};
+
+#ifdef USE_UNDOTABLE_DEFINE
+#ifndef __UNDOTABLENAME
+#define __UNDOTABLENAME g_UndoTable
+#endif
+#define Undo_Start __UNDOTABLENAME.m_pfnUndo_Start
+#define Undo_End __UNDOTABLENAME.m_pfnUndo_End
+#define Undo_AddBrush __UNDOTABLENAME.m_pfnUndo_AddBrush
+#define Undo_EndBrush __UNDOTABLENAME.m_pfnUndo_EndBrush
+#define Undo_AddBrushList __UNDOTABLENAME.m_pfnUndo_AddBrushList
+#define Undo_EndBrushList __UNDOTABLENAME.m_pfnUndo_EndBrushList
+#define Undo_AddEntity __UNDOTABLENAME.m_pfnUndo_AddEntity
+#define Undo_EndEntity __UNDOTABLENAME.m_pfnUndo_EndEntity
+#endif
+
+#endif // _IUNDO_H_
+
diff --git a/include/misc_def.h b/include/misc_def.h
index ea5a600b..c6ab2ebb 100644
--- a/include/misc_def.h
+++ b/include/misc_def.h
@@ -1,64 +1,64 @@
-#ifndef _WIN32
-
-#define WINAPI
-#define APIENTRY
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-typedef char* LPSTR;
-
-#define IsEqualGUID(a,b) (memcmp(&a,&b,sizeof(a)) == 0)
-
-#ifndef GUID_DEFINED
-#define GUID_DEFINED
-typedef struct _GUID
-{
-  unsigned long  Data1;
-  unsigned short Data2;
-  unsigned short Data3;
-  unsigned char  Data4[8];
-} GUID;
-#endif
- 
-#if defined(__cplusplus)
-#ifndef _REFGUID_DEFINED
-#define _REFGUID_DEFINED
-#define REFGUID const GUID &
-#endif // !_REFGUID_DEFINED
-#endif
-
-// Message box constants
-#define MB_OK                       0x00000000L
-#define MB_OKCANCEL                 0x00000001L
-#define MB_ABORTRETRYIGNORE         0x00000002L
-#define MB_YESNOCANCEL              0x00000003L
-#define MB_YESNO                    0x00000004L
-#define MB_RETRYCANCEL              0x00000005L
-
-#define MB_ICONHAND                 0x00000010L
-#define MB_ICONQUESTION             0x00000020L
-#define MB_ICONEXCLAMATION          0x00000030L
-#define MB_ICONASTERISK             0x00000040L
-
-#define MB_USERICON                 0x00000080L
-#define MB_ICONWARNING              MB_ICONEXCLAMATION
-#define MB_ICONERROR                MB_ICONHAND
-#define MB_ICONINFORMATION          MB_ICONASTERISK
-#define MB_ICONSTOP                 MB_ICONHAND
-
-#define MB_TYPEMASK                 0x0000000FL
-#define MB_ICONMASK                 0x000000F0L
-#define MB_DEFMASK                  0x00000F00L
-#define MB_MODEMASK                 0x00003000L
-#define MB_MISCMASK                 0x0000C000L
-
-#define IDOK                1
-#define IDCANCEL            2
-#define IDABORT             3
-#define IDRETRY             4
-#define IDIGNORE            5
-#define IDYES               6
-#define IDNO                7 
-
-#endif
+#ifndef _WIN32
+
+#define WINAPI
+#define APIENTRY
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+typedef char* LPSTR;
+
+#define IsEqualGUID(a,b) (memcmp(&a,&b,sizeof(a)) == 0)
+
+#ifndef GUID_DEFINED
+#define GUID_DEFINED
+typedef struct _GUID
+{
+  unsigned long  Data1;
+  unsigned short Data2;
+  unsigned short Data3;
+  unsigned char  Data4[8];
+} GUID;
+#endif
+ 
+#if defined(__cplusplus)
+#ifndef _REFGUID_DEFINED
+#define _REFGUID_DEFINED
+#define REFGUID const GUID &
+#endif // !_REFGUID_DEFINED
+#endif
+
+// Message box constants
+#define MB_OK                       0x00000000L
+#define MB_OKCANCEL                 0x00000001L
+#define MB_ABORTRETRYIGNORE         0x00000002L
+#define MB_YESNOCANCEL              0x00000003L
+#define MB_YESNO                    0x00000004L
+#define MB_RETRYCANCEL              0x00000005L
+
+#define MB_ICONHAND                 0x00000010L
+#define MB_ICONQUESTION             0x00000020L
+#define MB_ICONEXCLAMATION          0x00000030L
+#define MB_ICONASTERISK             0x00000040L
+
+#define MB_USERICON                 0x00000080L
+#define MB_ICONWARNING              MB_ICONEXCLAMATION
+#define MB_ICONERROR                MB_ICONHAND
+#define MB_ICONINFORMATION          MB_ICONASTERISK
+#define MB_ICONSTOP                 MB_ICONHAND
+
+#define MB_TYPEMASK                 0x0000000FL
+#define MB_ICONMASK                 0x000000F0L
+#define MB_DEFMASK                  0x00000F00L
+#define MB_MODEMASK                 0x00003000L
+#define MB_MISCMASK                 0x0000C000L
+
+#define IDOK                1
+#define IDCANCEL            2
+#define IDABORT             3
+#define IDRETRY             4
+#define IDIGNORE            5
+#define IDYES               6
+#define IDNO                7 
+
+#endif
diff --git a/include/qerplugin.h b/include/qerplugin.h
index 907a4bee..e6f1a96e 100644
--- a/include/qerplugin.h
+++ b/include/qerplugin.h
@@ -1,787 +1,787 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// QERadiant PlugIns
-//
-//
-
-#ifndef __QERPLUGIN_H__
-#define __QERPLUGIN_H__
-
-/*!
-\todo this header is intended to be turned into a header for the core editor functionality
-some portability related code should be moved to synapse (such as the GUID stuff)
-*/
-
-#include <stdio.h>
-#include <string.h>
-// TTimo
-// ideally the plugin API would be UI toolkit independent, but removing the dependency with GLib seems tricky right now..
-#include <glib.h>
-#include "qertypes.h"
-
-// FIXME TTimo:
-// GUID declaration here should be trashed, it is in synapse.h
-#ifdef _WIN32
-#include <wtypes.h>
-#endif
-
-#define QER_MAX_NAMELEN 1024
-
-#ifndef _WIN32
-#include "misc_def.h"
-#endif
-
-// the editor will look for plugins in two places, the plugins path 
-// under the application path, and the path under the basepath as defined
-// in the project (.qe4) file.
-//
-// you can drop any number of new texture, model format DLL's in the standard plugin path
-// but only one plugin that overrides map loading/saving, surface dialog, surface flags, etc.. 
-// should be used at one time.. if multiples are loaded then the last one loaded will be the 
-// active one
-//
-// type of services the plugin supplies, pass any combo of these flags
-// it is assumed the plugin will have a matching function as defined below
-// to correlate to the implied functionality
-// 
-
-#define RADIANT_MAJOR "radiant"
-
-// basics
-#define QERPLUG_INIT "QERPlug_Init"
-#define QERPLUG_GETNAME "QERPlug_GetName"
-#define QERPLUG_GETCOMMANDLIST "QERPlug_GetCommandList"
-#define QERPLUG_DISPATCH "QERPlug_Dispatch"
-#define QERPLUG_GETFUNCTABLE "QERPlug_GetFuncTable"
-
-// game stuff
-#define QERPLUG_GETTEXTUREINFO "QERPlug_GetTextureInfo"   // gets a texture info structure
-#define QERPLUG_LOADTEXTURE    "QERPlug_LoadTexture"      // loads a texture, will return an RGBA structure
-                                                          // and any surface flags/contents for it
-#define QERPLUG_GETSURFACEFLAGS "QERPlug_GetSurfaceFlags" // gets a list of surface/content flag names from a plugin
-
-struct _QERTextureInfo
-{
-  char m_TextureExtension[QER_MAX_NAMELEN];   // the extension these textures have
-  qboolean m_bHiColor;    // if textures are NOT high color, the default 
-                      // palette (as described inthe qe4 file will be used for gamma correction)
-                      // if they are high color, gamma and shading are computed on the fly 
-                      // based on the rgba data
-  //--bool m_bIsShader;   // will probably do q3 shaders this way when i merge
-  qboolean m_bWadStyle;   // if this is true, the plugin will be presented with the texture path
-                      // defined in the .qe4 file and is expected to preload all the textures
-  qboolean m_bHalfLife;   // causes brushes to be saved/parsed without the surface contents/flags/value
-};
-
-struct _QERTextureLoad    // returned by a plugin
-{
-  _QERTextureLoad()
-  { 
-    memset(reinterpret_cast<void*>(this), 0, sizeof(_QERTextureLoad));
-  };
-
-  ~_QERTextureLoad()
-  {
-    delete []m_pRGBA;
-    delete []m_pName;
-  };
-
-  void makeSpace(int nSize)
-  {
-    m_pRGBA = new unsigned char[nSize+1];
-  };
-
-  void setName(const char* p)
-  {
-    m_pName = new char[strlen(p)+1];
-    strcpy(m_pName, p);
-  };
-
-
-  unsigned char *m_pRGBA; // rgba data (alpha channel is supported and drawn appropriately)
-  int m_nWidth;           // width
-  int m_nHeight;          // height
-  int m_nContents;        // default contents
-  int m_nFlags;           // "" flags
-  int m_nValue;           // "" value
-  char *m_pName;          // name to be referenced in map, build tools, etc.
-};
-
-struct _QERModelInfo
-{
-  char m_ModelExtension[QER_MAX_NAMELEN];
-  bool m_bSkinned;
-  bool m_bMultipart;
-};
-
-struct _QERModelLoad
-{
-  // vertex and skin data
-};
-
-
-//=========================================
-// plugin functions
-#if 0
-// NOTE TTimo: hack to make old plugin tech and new plugin tech live together
-#ifndef _IPLUGIN_H_
-// toolkit-independant interface, cast hwndMain to GtkWidget*
-typedef const char* (WINAPI *PFN_QERPLUG_INIT)(void* hApp, void* hwndMain);
-typedef const char* (WINAPI *PFN_QERPLUG_GETNAME)();
-typedef const char* (WINAPI *PFN_QERPLUG_GETCOMMANDLIST)();
-typedef void  (WINAPI *PFN_QERPLUG_DISPATCH)(const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush);
-#endif
-#endif
-
-typedef char* (WINAPI *PFN_QERPLUG_GETFUNCTABLE)();
-
-// v1.5
-//
-// Texture loading
-// returns a ptr to _QERTextureInfo
-typedef void* (WINAPI *PFN_QERPLUG_GETTEXTUREINFO)();
-//
-// loads a texture by calling the texture load func in the editor (defined below)
-// transparency (for water, fog, lava, etc.. ) can be emulated in the editor
-// by passing in appropriate alpha data or by setting the appropriate surface flags
-// expected by q2 (which the editor will use.. )
-typedef void (WINAPI *PFN_QERPLUG_LOADTEXTURE)(const char* pFilename); 
-
-// v1.6
-typedef void* (WINAPI *PFN_QERPLUG_GETSURFACEFLAGS)();
-
-// v1.7
-// if exists in plugin, gets called between INIT and GETCOMMANDLIST
-// the plugin can register the EClasses he wants to handle
-//++timo TODO: this has got to move into the table, and be requested by QERPlug_RequestInterface
-//++timo FIXME: the LPVOID parameter must be casted to an IEpair interface
-#define QERPLUG_REGISTERPLUGINENTITIES "QERPlug_RegisterPluginEntities"
-typedef void (WINAPI * PFN_QERPLUG_REGISTERPLUGINENTITIES)( void* );
-
-// if exists in plugin, gets called between INIT and GETCOMMANDLIST
-// the plugin can Init all it needs for surface properties
-#define QERPLUG_INITSURFACEPROPERTIES "QERPlug_InitSurfaceProperties"
-typedef void (WINAPI * PFN_QERPLUG_INITSURFACEPROPERTIES)();
-
-// if Radiant needs to use a particular set of commands, it can request the plugin to fill a func table
-// this is similar to PFN_QERAPP_REQUESTINTERFACE
-#define QERPLUG_REQUESTINTERFACE "QERPlug_RequestInterface"
-typedef int (WINAPI * PFN_QERPLUG_REQUESTINTERFACE) (REFGUID refGUID, void* pInterface, const char *version_name);
-
-// Load an image file
-typedef void (* PFN_QERAPP_LOADIMAGE) (const char *name, unsigned char **pic, int *width, int *height);
-
-// TTimo FIXME: the logic for this is in synapse now
-
-// MODULES specific:
-// if it exports this entry point, will be considered as a module
-// a module is a plugin that provides some REQUIRED interfaces to Radiant, such as the shader module
-// Radiant will call QERPLUG_LISTINTERFACES to get a list of the interfaces a given plugin implements
-// then it will call PFN_QERPLUG_REQUESTINTERFACE to actually get them
-
-// following leo's code .. looks ok to use a string to identify the various versions of a same interface
-// obviously it would be handy to have the same string naming for the interfaces.
-// best way would be to have the names come in when you list the interfaces
-// NOTE: we might have a problem with the order in which the interfaces are filled in
-//   there's some kind of dependency graph, the shader module expects to find the VFS ready etc.
-typedef struct moduleentry_s {
-  const GUID *interface_GUID;
-  const char* interface_name;
-  const char* version_name; 
-} moduleentry_t;
-
-#define QERPLUG_LISTINTERFACES "QERPlug_ListInterfaces"
-#define MAX_QERPLUG_INTERFACES 10
-typedef int (WINAPI* PFN_QERPLUG_LISTINTERFACES) (moduleentry_t table[MAX_QERPLUG_INTERFACES]);
-
-// ========================================
-// GTK+ helper functions
-
-// NOTE: parent can be NULL in all functions but it's best to set them
-
-// simple Message Box, see above for the 'type' flags
-// toolkit-independent, cast parent ot a GtkWidget*
-typedef gint (WINAPI* PFN_QERAPP_MESSAGEBOX) (void *parent, const char* text,
-                                              const char* caption, guint32 type, const char *URL);
-
-// file and directory selection functions return NULL if the user hits cancel
-// or a gchar* string that must be g_free'd by the user
-// - 'title' is the dialog title (can be NULL)
-// - 'path' is used to set the initial directory (can be NULL)
-// - 'pattern': the first pattern is for the win32 mode, then comes the Gtk pattern list, see Radiant source for samples
-// TTimo 04/01/2001 toolkit-independant, cast parent to a GtkWidget*
-typedef const gchar* (* PFN_QERAPP_FILEDIALOG) (void *parent, gboolean open, const char* title,
-                                                const char* path, const char* pattern);
-typedef gchar* (WINAPI* PFN_QERAPP_DIRDIALOG) (void *parent, const char* title,
-                                               const char* path);
-
-// return true if the user closed the dialog with 'Ok'
-// 'color' is used to set the initial value and store the selected value
-typedef bool (WINAPI* PFN_QERAPP_COLORDIALOG) (void *parent, float *color,
-                                               const char* title);
-
-// load a .bmp file and store the results in 'gdkpixmap' and 'mask'
-// returns TRUE on success but even if it fails, it creates an empty pixmap
-// NOTE: 'filename' is relative to <radiant_path>/plugins/bitmaps/
-// TTimo 04/01/2001 toolkit-independant, cast gkpixmap to GdkPixmap and mask to GdkBitmap
-typedef bool (WINAPI* PFN_QERAPP_LOADBITMAP) (const char* filename, void **gdkpixmap, void **mask);
-
-// ========================================
-// read/write preferences file
-
-// use this function to get the directory where the preferences file are stored
-typedef const char* (WINAPI* PFN_QERAPP_PROFILE_GETDIR) ();
-
-// 'filename' is the absolute path
-typedef bool (WINAPI* PFN_QERAPP_PROFILE_SAVEINT) (const char *filename, const char *section,
-                                                   const char *key, int value);
-typedef bool (WINAPI* PFN_QERAPP_PROFILE_SAVESTR) (const char *filename, const char *section,
-                                                   const char *key, const char *value);
-typedef int (WINAPI* PFN_QERAPP_PROFILE_LOADINT) (const char *filename, const char *section,
-                                                  const char *key, int default_value);
-typedef char* (WINAPI* PFN_QERAPP_PROFILE_LOADSTR) (const char *filename, const char *section,
-                                                    const char *key, const char *default_value);
-
-//=========================================
-// editor functions
-
-// There are 3 potential brush handle lists
-// 1. the list that contains brushes a plugin creates using CreateBrushHandle
-// 2. the selected brush list (brushes the user has selected)
-// 3. the active brush list (brushes in the map that are not selected)
-// 
-// In general, the same things can be done to brush handles (face manip, delete brushhandle, etc.. ) in each
-// list. There are a few exceptions. 
-// 1. You cannot commit a selected or active brush handle to the map. This is because it is already in the map. 
-// 2. You cannot bind brush handles from the selected or active brush list to an entity. As of v1.0 of the plugins
-// the only way for a plugin to create entities is to create a brush handles (or a list of handles) and then bind
-// them to an entity. This will commit the brush(s) and/or the entities to the map as well.
-// 
-// To use the active or selected brush lists, you must first allocate them (which returns a count) and then
-// release them when you are finish manipulating brushes in one of those lists. 
-
-//++timo NOTE : the #defines here are never used, but can help finding where things are done in the editor
-#if 0
-// brush manipulation routines
-#define QERAPP_CREATEBRUSH "QERApp_CreateBrush"
-#define QERAPP_CREATEBRUSHHANDLE "QERApp_CreateBrushHandle"
-#define QERAPP_DELETEBRUSHHANDLE "QERApp_DeleteBrushHandle"
-#define QERAPP_COMMITBRUSHHANDLETOMAP "QERApp_CommitBrushHandleToMap"
-//++timo not implemented .. remove
-// #define QERAPP_BINDHANDLESTOENTITY "QERApp_BindHandlesToEntity"
-#define QERAPP_ADDFACE "QERApp_AddFace"
-#define QERAPP_ADDFACEDATA "QERApp_AddFaceData"
-#define QERAPP_GETFACECOUNT "QERApp_GetFaceCount"
-#define QERAPP_GETFACEDATA "QERApp_GetFaceData"
-#define QERAPP_SETFACEDATA "QERApp_SetFaceData"
-#define QERAPP_DELETEFACE "QERApp_DeleteFace"
-#define QERAPP_TEXTUREBRUSH "QERApp_TextureBrush"
-#define QERAPP_BUILDBRUSH "QERApp_BuildBrush"					// PGM
-#define QERAPP_SELECTEDBRUSHCOUNT "QERApp_SelectedBrushCount"
-#define QERAPP_ALLOCATESELECTEDBRUSHHANDLES "QERApp_AllocateSelectedBrushHandles"
-#define QERAPP_RELEASESELECTEDBRUSHHANDLES "QERApp_ReleaseSelectedBrushHandles"
-#define QERAPP_GETSELECTEDBRUSHHANDLE "QERApp_GetSelectedBrushHandle"
-#define QERAPP_ACTIVEBRUSHCOUNT "QERApp_ActiveBrushCount"
-#define QERAPP_ALLOCATEACTIVEBRUSHHANDLES "QERApp_AllocateActiveBrushHandles"
-#define QERAPP_RELEASEACTIVEBRUSHHANDLES "QERApp_ReleaseActiveBrushHandles"
-#define QERAPP_GETACTIVEBRUSHHANDLE "QERApp_GetActiveBrushHandle"
-
-// texture stuff
-#define QERAPP_TEXTURECOUNT "QERApp_TextureCount"
-#define QERAPP_GETTEXTURE "QERApp_GetTexture"
-#define QERAPP_GETCURRENTTEXTURE "QERApp_GetCurrentTexture"
-#define QERAPP_SETCURRENTTEXTURE "QERApp_SetCurrentTexture"
-
-// selection 
-#define QERAPP_DELETESELECTION "QERApp_DeleteSelection"
-#define QERAPP_SELECTBRUSH "QERApp_SelectBrush"					// PGM
-#define QERAPP_DESELECTBRUSH "QERApp_DeselectBrush"				// PGM
-#define QERAPP_DESELECTALLBRUSHES "QERApp_DeselectAllBrushes"	// PGM
-
-// data gathering
-#define QERAPP_GETPOINTS "QERApp_GetPoints"
-#define QERAPP_SELECTBRUSHES "QERApp_GetBrushes"
-
-// entity class stuff
-// the entity handling is very basic for 1.0
-#define QERAPP_GETECLASSCOUNT "QERApp_GetEClassCount"
-#define QERAPP_GETECLASS "QERApp_GetEClass"
-
-// misc
-#define QERAPP_SYSMSG "QERApp_SysMsg"
-#define QERAPP_INFOMSG "QERApp_InfoMsg"
-#define QERAPP_HIDEINFOMSG "QERApp_HideInfoMsg"
-#define QERAPP_RESET_PLUGINS "QERApp_ResetPlugins"
-
-// texture loading
-#define QERAPP_LOADTEXTURERGBA "QERApp_LoadTextureRGBA"
-
-// FIXME: the following are not implemented yet
-// hook registrations
-#define QERAPP_REGISTER_MAPLOADFUNC "QERApp_Register_MapLoadFunc"
-#define QERAPP_REGISTER_MAPSAVEFUNC "QERApp_Register_MapSaveFunc"
-
-// FIXME: the following are not implemented yet
-#define QERAPP_REGISTER_PROJECTLOADFUNC "QERApp_Register_ProjectLoadFunc"
-#define QERAPP_REGISTER_MOUSEHANDLER "QERApp_Register_MouseHandler"
-#define QERAPP_REGISTER_KEYHANDLER "QERApp_Register_KeyHandler"
-
-// FIXME: new primtives do not work in v1.00
-// primitives are new types of things in the map
-// for instance, the Q3 curves could have been done as 
-// primitives instead of being built in 
-// it will be a plugins responsibility to hook the map load and save funcs to load
-// and/or save any additional data (like new primitives of some type)
-// the editor will call each registered renderer during the rendering process to repaint
-// any primitives the plugin owns
-// each primitive object has a temporary sibling brush that lives in the map
-// FIXME: go backwards on this a bit.. orient it more towards the temp brush mode as it will be cleaner
-// basically a plugin will hook the map load and save and will add the primitives to the map.. this will
-// produce a temporary 'primitive' brush and the appropriate renderer will be called as well as the 
-// edit handler (for edge drags, sizes, rotates, etc.. ) and the vertex maker will be called when vertex
-// mode is attemped on the brush.. there will need to be a GetPrimitiveBounds callback in the edit handler
-// so the brush can resize appropriately as needed.. this might be the plugins responsibility to set the 
-// sibling brushes size.. it will then be the plugins responsibility to hook map save to save the primitives
-// as the editor will discard any temp primitive brushes.. (there probably needs to be some kind of sanity check
-// here as far as keeping the brushes and the plugin in sync.. i suppose the edit handler can deal with all of that
-// crap but it looks like a nice place for a mess)
-#define QERAPP_REGISTER_PRIMITIVE "QERApp_Register_Primitive"
-#define QERAPP_REGISTER_RENDERER "QERApp_Register_Renderer"
-#define QERAPP_REGISTER_EDITHANDLER "QERApp_Register_EditHandler"
-#define QERAPP_REGISTER_VERTEXMAKER "QERApp_Register_VertexMaker"
-#define QERAPP_ADDPRIMITIVE "QERApp_AddPrimitive"
-
-// v1.70
-#define QERAPP_GETENTITYCOUNT "QERApp_GetEntityCount"
-#define QERAPP_GETENTITYHANDLE "QERApp_GetEntityHandle"
-//++timo not implemented for the moment
-// #define QERAPP_GETENTITYINFO "QERApp_GetEntityInfo"
-//++timo does the keyval need some more funcs to add/remove ?
-// get the pointer and do the changes yourself
-#define QERAPP_ALLOCATEEPAIR "QERApp_AllocateEpair"
-#define QERAPP_ALLOCATEENTITYBRUSHHANDLES "QERApp_AllocateEntityBrushHandles"
-#define QERAPP_RELEASEENTITYBRUSHHANDLES "QERApp_ReleaseEntityBrushHandles"
-#define QERAPP_GETENTITYBRUSHHANDLE "QERApp_GetEntityBrushHandle"
-#define QERAPP_CREATEENTITYHANDLE "QERApp_CreateEntityHandle"
-#define QERAPP_COMMITBRUSHHANDLETOENTITY "QERApp_CommitBrushHandleToEntity"
-#define QERAPP_COMMITENTITYHANDLETOMAP "QERApp_CommitEntityHandleToMap"
-#define QERAPP_SETSCREENUPDATE "QERApp_SetScreenUpdate"
-#define QERAPP_BUILDBRUSH2 "QERApp_BuildBrush2"
-#endif
-
-// v1.80
-#define QERAPP_GETDISPATCHPARAMS "QERApp_GetDispatchParams"
-
-struct _QERPointData
-{
-  int     m_nCount;
-  vec3_t *m_pVectors;
-};
-
-struct _QERFaceData
-{
-  char  m_TextureName[QER_MAX_NAMELEN];
-  int   m_nContents;
-  int   m_nFlags;
-  int   m_nValue;
-  float m_fShift[2];
-  float m_fRotate;
-  float m_fScale[2];
-  vec3_t m_v1, m_v2, m_v3;
-  // brush primitive additions
-  qboolean m_bBPrimit;
-  brushprimit_texdef_t brushprimit_texdef;
-};
-
-typedef void (WINAPI * PFN_QERAPP_CREATEBRUSH)(vec3_t vMin, vec3_t vMax);
-
-typedef void* (WINAPI * PFN_QERAPP_CREATEBRUSHHANDLE)();
-typedef void (WINAPI * PFN_QERAPP_DELETEBRUSHHANDLE)(void* pv);
-typedef void (WINAPI * PFN_QERAPP_COMMITBRUSHHANDLETOMAP)(void* pv);
-typedef void (WINAPI * PFN_QERAPP_ADDFACE)(void* pv, vec3_t v1, vec3_t v2, vec3_t v3);
-
-typedef void (WINAPI * PFN_QERAPP_ADDFACEDATA)(void* pv, _QERFaceData *pData);
-typedef int  (WINAPI * PFN_QERAPP_GETFACECOUNT)(void* pv);
-typedef _QERFaceData* (WINAPI * PFN_QERAPP_GETFACEDATA)(void* pv, int nFaceIndex);
-typedef void (WINAPI * PFN_QERAPP_SETFACEDATA)(void* pv, int nFaceIndex, _QERFaceData *pData);
-typedef void (WINAPI * PFN_QERAPP_DELETEFACE)(void* pv, int nFaceIndex);
-typedef void (WINAPI * PFN_QERAPP_TEXTUREBRUSH)(void* pv, char* pName);
-typedef void (WINAPI * PFN_QERAPP_BUILDBRUSH)(void* pv);		// PGM
-typedef void (WINAPI * PFN_QERAPP_SELECTBRUSH)(void* pv);		// PGM
-typedef void (WINAPI * PFN_QERAPP_DESELECTBRUSH)(void* pv);		// PGM
-typedef void (WINAPI * PFN_QERAPP_DESELECTALLBRUSHES)();			// PGM
-
-typedef void (WINAPI * PFN_QERAPP_DELETESELECTION)();
-typedef void (WINAPI * PFN_QERAPP_GETPOINTS)(int nMax, _QERPointData *pData, char* pMsg);
-
-typedef int  (WINAPI * PFN_QERAPP_SELECTEDBRUSHCOUNT)();
-typedef int (WINAPI * PFN_QERAPP_ALLOCATESELECTEDBRUSHHANDLES)();
-typedef void (WINAPI * PFN_QERAPP_RELEASESELECTEDBRUSHHANDLES)();
-typedef void* (WINAPI * PFN_QERAPP_GETSELECTEDBRUSHHANDLE)(int nIndex);
-
-typedef int  (WINAPI * PFN_QERAPP_ACTIVEBRUSHCOUNT)();
-typedef int (WINAPI * PFN_QERAPP_ALLOCATEACTIVEBRUSHHANDLES)();
-typedef void (WINAPI * PFN_QERAPP_RELEASEACTIVEBRUSHHANDLES)();
-typedef void* (WINAPI * PFN_QERAPP_GETACTIVEBRUSHHANDLE)(int nIndex);
-
-typedef int  (WINAPI * PFN_QERAPP_TEXTURECOUNT)();
-typedef char* (WINAPI * PFN_QERAPP_GETTEXTURE)(int nIndex);
-typedef char* (WINAPI * PFN_QERAPP_GETCURRENTTEXTURE)();
-typedef void (WINAPI * PFN_QERAPP_SETCURRENTTEXTURE)(char* pName);
-
-typedef void (WINAPI * PFN_QERAPP_REGISTERMAPLOAD)(void* vp);
-typedef void (WINAPI * PFN_QERAPP_REGISTERMAPSAVE)(void* vp);
-
-typedef int (WINAPI * PFN_QERAPP_GETECLASSCOUNT)();
-typedef char* (WINAPI * PFN_QERAPP_GETECLASS)(int nIndex);
-
-typedef void (WINAPI * PFN_QERAPP_RESETPLUGINS)();
-//--typedef int (WINAPI* PFN_QERAPP_GETENTITYCOUNT)();
-
-/*!
-\fn LoadTextureRGBA
-\param pPixels is the raw RGBA pixel data (24bits, 8 bit depth)
-\param nWidth image width
-\param nHeight image height
-this will work from the RGBA data and create a GL texture (accessed through a GL bind number)
-it takes care of creating the mipmapping levels too
-see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=575 for some related issues
-*/
-typedef qtexture_t* (* PFN_QERAPP_LOADTEXTURERGBA)(unsigned char* pPixels, int nWidth, int nHeight);
-
-//--typedef LPCSTR (WINAPI* PFN_QERAPP_GETENTITY)(int nIndex);
-
-// v1.70
-typedef int (WINAPI * PFN_QERAPP_GETENTITYCOUNT)();
-typedef void* (WINAPI * PFN_QERAPP_GETENTITYHANDLE)(int nIndex);
-// FIXME: those two are fairly outdated, you get the epairs
-//   but you don't have a clean epair read/write query
-//   and you rely on the C structs directly, which might go away soon
-//   ok now, stop using, it's bad for your karma (see iepairs.h instead)
-typedef epair_t* (WINAPI * PFN_QERAPP_ALLOCATEEPAIR)( char*, char* );
-typedef int (WINAPI * PFN_QERAPP_ALLOCATEENTITYBRUSHHANDLES)(void* vp);
-typedef void (WINAPI * PFN_QERAPP_RELEASEENTITYBRUSHHANDLES)();
-typedef void* (WINAPI * PFN_QERAPP_GETENTITYBRUSHHANDLE)(int nIndex);
-typedef void* (WINAPI * PFN_QERAPP_CREATEENTITYHANDLE)();
-typedef void (WINAPI * PFN_QERAPP_COMMITBRUSHHANDLETOENTITY)( void* vpBrush, void* vpEntity);
-typedef void (WINAPI * PFN_QERAPP_COMMITENTITYHANDLETOMAP)(void* vp);
-typedef void (WINAPI * PFN_QERAPP_SETSCREENUPDATE)(int bScreenUpdate);
-// this one uses window flags defined in qertypes.h
-typedef void (WINAPI * PFN_QERAPP_SYSUPDATEWINDOWS)(int bits);
-//++timo remove this one
-typedef void (WINAPI * PFN_QERAPP_BUILDBRUSH2)(void* vp, int bConvert);
-
-// v1.80
-typedef void (WINAPI * PFN_QERAPP_GETDISPATCHPARAMS)(vec3_t vMin, vec3_t vMax, bool *bSingleBrush);
-
-typedef int (WINAPI * PFN_QERAPP_REQUESTINTERFACE)( REFGUID, void* );
-// use this one for errors, Radiant will stop after the "edit preferences" dialog
-typedef void (WINAPI * PFN_QERAPP_ERROR)(char* pMsg, ...);
-// use to gain read access to the project epairs
-// FIXME: removed, accessed through QERPlug_RegisterPluginEntities with the IEpair interface
-// typedef void (WINAPI* PFN_QERAPP_GETPROJECTEPAIR)(epair_t **);
-// used to allocate and read a buffer
-//++timo NOTE: perhaps this would need moving to some kind of dedicated interface
-typedef int (WINAPI * PFN_QERAPP_LOADFILE)(const char *pLocation, void ** buffer);
-typedef char* (WINAPI * PFN_QERAPP_EXPANDRELETIVEPATH)(char *);
-typedef void (WINAPI * PFN_QERAPP_QECONVERTDOSTOUNIXNAME)( char *dst, const char *src );
-typedef int (WINAPI * PFN_QERAPP_HASSHADER)(const char *);
-typedef int (WINAPI * PFN_QERAPP_TEXTURELOADSKIN)(char *pName, int *pnWidth, int *pnHeight);
-// retrieves the path to the engine from the preferences dialog box
-typedef const char* (WINAPI * PFN_QERAPP_GETGAMEPATH)();
-// retrieves full Radiant path
-typedef const char* (WINAPI * PFN_QERAPP_GETQERPATH)();
-// retieves .game name of current active game
-typedef const char* (WINAPI * PFN_QERAPP_GETGAMEFILE)();
-
-// patches in/out
-// NOTE: this is a bit different from the brushes in/out, no LPVOID handles this time
-// use int indexes instead
-// if you call AllocateActivePatchHandles, you'll be playing with active patches
-// AllocateSelectedPatcheHandles for selected stuff
-// a call to CreatePatchHandle will move you to a seperate index table
-typedef int				(WINAPI * PFN_QERAPP_ALLOCATEACTIVEPATCHHANDLES)		();
-typedef int				(WINAPI * PFN_QERAPP_ALLOCATESELECTEDPATCHHANDLES)	();
-typedef void			(WINAPI * PFN_QERAPP_RELEASEPATCHHANDLES)			();
-typedef patchMesh_t*	(WINAPI * PFN_QERAPP_GETPATCHDATA)					(int);
-typedef patchMesh_t*	(WINAPI * PFN_QERAPP_GETPATCHHANDLE)				(int);
-typedef void			(WINAPI * PFN_QERAPP_DELETEPATCH)				(int);
-typedef int				(WINAPI * PFN_QERAPP_CREATEPATCHHANDLE)				();
-// when commiting, only a few patchMesh_t members are relevant:
-//  int	width, height;		// in control points, not patches
-//  int   contents, flags, value, type;
-//  drawVert_t ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
-// once you have commited the index is still available, if the patch handle was allocated by you
-//   then you can re-use the index to commit other patches .. otherwise you can change existing patches
-// NOTE: the handle thing for plugin-allocated patches is a bit silly (nobody's perfect)
-// TODO: change current behaviour to an index = 0 to tell Radiant to allocate, other indexes to existing patches
-// patch is selected after a commit
-// you can add an optional texture / shader name .. if NULL will use the current texture
-typedef void			(WINAPI * PFN_QERAPP_COMMITPATCHHANDLETOMAP)			(int, patchMesh_t* pMesh, char *texName);
-typedef void			(WINAPI * PFN_QERAPP_COMMITPATCHHANDLETOENTITY)			(int, patchMesh_t* pMesh, char *texName, void* vpEntity);
-
-// console output
-#define SYS_VRB 0 ///< verbose support (on/off)
-#define SYS_STD 1 ///< standard print level - this is the default
-#define SYS_WRN 2 ///< warnings
-#define SYS_ERR 3 ///< error
-#define SYS_NOCON 4 ///< no console, only print to the file (useful whenever Sys_Printf and output IS the problem)
-typedef void (WINAPI* PFN_QERAPP_SYSPRINTF) (const char *text, ...);
-typedef void (WINAPI* PFN_QERAPP_SYSFPRINTF) (int flag, const char *text, ...);
-
-typedef void (WINAPI* PFN_QERAPP_SYSBEGINWAIT) ();
-typedef void (WINAPI* PFN_QERAPP_SYSENDWAIT) ();
-
-typedef void (* PFN_QERAPP_SYSBEEP) ();
-
-typedef void (* PFN_QERAPP_SYSSTATUS) (const char *psz, int part );
-
-// core map functionality
-typedef void      (* PFN_QERAPP_MAPNEW)                     ();
-typedef void      (* PFN_QERAPP_MAPFREE)                    ();
-typedef void      (* PFN_QERAPP_MAPBUILDBRUSHDATA)          ();
-typedef qboolean  (* PFN_QERAPP_MAPISBRUSHFILTERED)         (brush_t *);
-typedef void      (* PFN_QERAPP_MAPSTARTPOSITION)           ();
-typedef void      (* PFN_QERAPP_MAPREGIONOFF)               ();
-//typedef void      (* PFN_QERAPP_SAVEASDIALOG)               (bool bRegion);
-typedef void      (* PFN_QERAPP_SETBUILDWINDINGSNOTEXBUILD) (bool);
-typedef void      (* PFN_QERAPP_POINTFILECLEAR)             ();
-
-typedef void (* PFN_QERAPP_SYSSETTITLE) (const char *text);
-
-typedef void (* PFN_QERAPP_CSGMAKEHOLLOW) ();
-
-typedef void (* PFN_QERAPP_REGIONSPAWNPOINT) (FILE *f);
-
-/*!
-access to a portable GetTickCount
-*/
-typedef unsigned long (* PFN_QERAPP_GETTICKCOUNT) ();
-
-class IModelCache
-{
-public:
-  virtual entity_interfaces_t *GetByID(const char *id, const char* version) = 0;
-  virtual void DeleteByID(const char *id, const char* version) = 0;
-  virtual void RefreshAll() = 0;
-};
-
-typedef IModelCache* (* PFN_GETMODELCACHE)();
-
-class IFileTypeList
-{
-public:
-  virtual void addType(filetype_t type) = 0;
-};
-
-class IFileTypeRegistry
-{
-public:
-  virtual void addType(const char* key, filetype_t type) = 0;
-  virtual void getTypeList(const char* key, IFileTypeList* typelist) = 0;
-private:
-};
-
-typedef IFileTypeRegistry* (* PFN_GETFILETYPEREGISTRY)();
-
-typedef const char* (* PFN_QERAPP_READPROJECTKEY)(const char* key);
-
-typedef char* (* PFN_GETMAPFILENAME)();
-
-  // FIXME:
-// add map format extensions
-// add texture format handlers
-// add surface dialog handler
-// add model handler/displayer
-
-// v1 func table
-// Plugins need to declare one of these and implement the getfunctable as described above
-struct _QERFuncTable_1
-{
-  int   m_nSize;
-  PFN_QERAPP_CREATEBRUSH            m_pfnCreateBrush;
-  PFN_QERAPP_CREATEBRUSHHANDLE      m_pfnCreateBrushHandle;
-  PFN_QERAPP_DELETEBRUSHHANDLE      m_pfnDeleteBrushHandle;
-  PFN_QERAPP_COMMITBRUSHHANDLETOMAP m_pfnCommitBrushHandle;
-  PFN_QERAPP_ADDFACE                m_pfnAddFace;
-  PFN_QERAPP_ADDFACEDATA            m_pfnAddFaceData;
-  PFN_QERAPP_GETFACEDATA            m_pfnGetFaceData;
-  PFN_QERAPP_GETFACECOUNT           m_pfnGetFaceCount;
-  PFN_QERAPP_SETFACEDATA            m_pfnSetFaceData;
-  PFN_QERAPP_DELETEFACE             m_pfnDeleteFace;
-  PFN_QERAPP_TEXTUREBRUSH           m_pfnTextureBrush;
-  PFN_QERAPP_BUILDBRUSH				m_pfnBuildBrush;				// PGM
-  PFN_QERAPP_SELECTBRUSH			m_pfnSelectBrush;				// PGM
-  PFN_QERAPP_DESELECTBRUSH			m_pfnDeselectBrush;				// PGM
-  PFN_QERAPP_DESELECTALLBRUSHES		m_pfnDeselectAllBrushes;		// PGM
-
-  PFN_QERAPP_DELETESELECTION        m_pfnDeleteSelection;
-  PFN_QERAPP_GETPOINTS              m_pfnGetPoints;
-
-  PFN_QERAPP_SELECTEDBRUSHCOUNT           m_pfnSelectedBrushCount;
-  PFN_QERAPP_ALLOCATESELECTEDBRUSHHANDLES m_pfnAllocateSelectedBrushHandles;
-  PFN_QERAPP_RELEASESELECTEDBRUSHHANDLES  m_pfnReleaseSelectedBrushHandles;
-  PFN_QERAPP_GETSELECTEDBRUSHHANDLE       m_pfnGetSelectedBrushHandle;
-
-  PFN_QERAPP_ACTIVEBRUSHCOUNT             m_pfnActiveBrushCount;
-  PFN_QERAPP_ALLOCATEACTIVEBRUSHHANDLES   m_pfnAllocateActiveBrushHandles;
-  PFN_QERAPP_RELEASEACTIVEBRUSHHANDLES    m_pfnReleaseActiveBrushHandles;
-  PFN_QERAPP_GETACTIVEBRUSHHANDLE         m_pfnGetActiveBrushHandle;
-
-  //++timo this would need to be removed and replaced by the IShaders interface
-  PFN_QERAPP_TEXTURECOUNT                 m_pfnTextureCount;
-  PFN_QERAPP_GETTEXTURE                   m_pfnGetTexture;
-  PFN_QERAPP_GETCURRENTTEXTURE            m_pfnGetCurrentTexture;
-  PFN_QERAPP_SETCURRENTTEXTURE            m_pfnSetCurrentTexture;
-
-  PFN_QERAPP_GETECLASSCOUNT         m_pfnGetEClassCount;
-  PFN_QERAPP_GETECLASS              m_pfnGetEClass;
-  PFN_QERAPP_RESETPLUGINS           m_pfnResetPlugins;
-  // v1.00 ends here
-  // v1.50 starts here
-  PFN_QERAPP_LOADTEXTURERGBA        m_pfnLoadTextureRGBA;
-  // v1.50 ends here
-  // v1.70 starts here
-  PFN_QERAPP_GETENTITYCOUNT			m_pfnGetEntityCount;
-  PFN_QERAPP_GETENTITYHANDLE		m_pfnGetEntityHandle;
-  PFN_QERAPP_ALLOCATEENTITYBRUSHHANDLES	m_pfnAllocateEntityBrushHandles;
-  PFN_QERAPP_RELEASEENTITYBRUSHHANDLES	m_pfnReleaseEntityBrushHandles;
-  PFN_QERAPP_GETENTITYBRUSHHANDLE	m_pfnGetEntityBrushHandle;
-  PFN_QERAPP_CREATEENTITYHANDLE		m_pfnCreateEntityHandle;
-  PFN_QERAPP_COMMITBRUSHHANDLETOENTITY	m_pfnCommitBrushHandleToEntity;
-  PFN_QERAPP_COMMITENTITYHANDLETOMAP	m_pfnCommitEntityHandleToMap;
-  PFN_QERAPP_ALLOCATEEPAIR			m_pfnAllocateEpair;
-  PFN_QERAPP_SETSCREENUPDATE		m_pfnSetScreenUpdate;
-  PFN_QERAPP_BUILDBRUSH2			m_pfnBuildBrush2;
-  // v1.70 ends here
-  // v1.80 starts here
-  PFN_QERAPP_GETDISPATCHPARAMS     m_pfnGetDispatchParams;
-
-  // plugins can request additional interfaces
-  PFN_QERAPP_REQUESTINTERFACE		m_pfnRequestInterface;
-  PFN_QERAPP_ERROR					m_pfnError;
-  // loading a file into a buffer
-  PFN_QERAPP_LOADFILE				m_pfnLoadFile;
-  PFN_QERAPP_EXPANDRELETIVEPATH		m_pfnExpandReletivePath;
-  PFN_QERAPP_QECONVERTDOSTOUNIXNAME	m_pfnQE_ConvertDOSToUnixName;
-  PFN_QERAPP_HASSHADER				m_pfnHasShader;
-  PFN_QERAPP_TEXTURELOADSKIN		m_pfnTexture_LoadSkin;
-  PFN_QERAPP_GETGAMEPATH			m_pfnGetGamePath;
-  PFN_QERAPP_GETQERPATH				m_pfnGetQERPath;
-  PFN_QERAPP_GETGAMEFILE			m_pfnGetGameFile;
-  // patches in / out
-  PFN_QERAPP_ALLOCATEACTIVEPATCHHANDLES		m_pfnAllocateActivePatchHandles;
-  PFN_QERAPP_ALLOCATESELECTEDPATCHHANDLES	m_pfnAllocateSelectedPatchHandles;
-  PFN_QERAPP_RELEASEPATCHHANDLES			m_pfnReleasePatchHandles;
-  PFN_QERAPP_GETPATCHDATA					m_pfnGetPatchData;
-  PFN_QERAPP_GETPATCHHANDLE				m_pfnGetPatchHandle;
-  PFN_QERAPP_DELETEPATCH					m_pfnDeletePatch;
-  PFN_QERAPP_CREATEPATCHHANDLE				m_pfnCreatePatchHandle;
-  PFN_QERAPP_COMMITPATCHHANDLETOMAP			m_pfnCommitPatchHandleToMap;
-  PFN_QERAPP_COMMITPATCHHANDLETOENTITY	m_pfnCommitPatchHandleToEntity;
-
-  PFN_QERAPP_LOADIMAGE  m_pfnLoadImage;
-
-  // GTK+ functions
-  PFN_QERAPP_MESSAGEBOX  m_pfnMessageBox;
-  PFN_QERAPP_FILEDIALOG  m_pfnFileDialog;
-  PFN_QERAPP_DIRDIALOG   m_pfnDirDialog;
-  PFN_QERAPP_COLORDIALOG m_pfnColorDialog;
-  PFN_QERAPP_LOADBITMAP  m_pfnLoadBitmap;
-
-  // Profile functions
-  PFN_QERAPP_PROFILE_GETDIR  m_pfnProfileGetDirectory;
-  PFN_QERAPP_PROFILE_SAVEINT m_pfnProfileSaveInt;
-  PFN_QERAPP_PROFILE_SAVESTR m_pfnProfileSaveString;
-  PFN_QERAPP_PROFILE_LOADINT m_pfnProfileLoadInt;
-  PFN_QERAPP_PROFILE_LOADSTR m_pfnProfileLoadString;
-
-  // Sys_ functions
-  PFN_QERAPP_SYSUPDATEWINDOWS		m_pfnSysUpdateWindows;
-  PFN_QERAPP_SYSBEEP m_pfnSysBeep;
-  PFN_QERAPP_SYSPRINTF  m_pfnSysPrintf;
-  PFN_QERAPP_SYSFPRINTF m_pfnSysFPrintf;
-  PFN_QERAPP_SYSBEGINWAIT m_pfnSysBeginWait;
-  PFN_QERAPP_SYSENDWAIT m_pfnSysEndWait;
-  PFN_QERAPP_SYSSETTITLE m_pfnSys_SetTitle;
-  PFN_QERAPP_SYSSTATUS m_pfnSys_Status;
-
-  // some core functionality on the map
-  PFN_QERAPP_MAPNEW m_pfnMapNew;
-  PFN_QERAPP_MAPFREE m_pfnMapFree;
-  PFN_QERAPP_MAPBUILDBRUSHDATA m_pfnMapBuildBrushData;
-  PFN_QERAPP_MAPISBRUSHFILTERED m_pfnMap_IsBrushFiltered;
-  PFN_QERAPP_MAPSTARTPOSITION m_pfnMapStartPosition;
-  PFN_QERAPP_MAPREGIONOFF m_pfnMapRegionOff;
-  PFN_QERAPP_SETBUILDWINDINGSNOTEXBUILD m_pfnSetBuildWindingsNoTexBuild;
-//  PFN_QERAPP_SAVEASDIALOG m_pfnSaveAsDialog;
-  PFN_QERAPP_POINTFILECLEAR m_pfnPointFileClear;
-
-  // FIXME TTimo prolly want to move that somewhere else
-  PFN_QERAPP_CSGMAKEHOLLOW m_pfnCSG_MakeHollow;
-
-  PFN_QERAPP_REGIONSPAWNPOINT m_pfnRegionSpawnPoint;
-  PFN_QERAPP_GETTICKCOUNT m_pfnQGetTickCount;
-  PFN_GETMODELCACHE m_pfnGetModelCache;
-  PFN_GETFILETYPEREGISTRY m_pfnGetFileTypeRegistry;
-
-  PFN_QERAPP_READPROJECTKEY m_pfnReadProjectKey;
-
-  // digibob from the old _QERAppBSPFrontendTable table
-	PFN_GETMAPFILENAME  m_pfnGetMapName;
-};
-
-// macros to access those faster in plugins
-#ifdef USE_QERTABLE_DEFINE
-#ifndef __QERTABLENAME
-#define __QERTABLENAME g_FuncTable
-#endif
-#define CSG_MakeHollow __QERTABLENAME.m_pfnCSG_MakeHollow
-#define Sys_Beep __QERTABLENAME.m_pfnSysBeep
-#define Sys_Printf __QERTABLENAME.m_pfnSysPrintf
-#define Sys_FPrintf __QERTABLENAME.m_pfnSysFPrintf
-#define Sys_BeginWait __QERTABLENAME.m_pfnSysBeginWait
-#define Sys_EndWait __QERTABLENAME.m_pfnSysEndWait
-#define Sys_UpdateWindows __QERTABLENAME.m_pfnSysUpdateWindows
-#define Sys_SetTitle __QERTABLENAME.m_pfnSys_SetTitle
-#define Sys_Status __QERTABLENAME.m_pfnSys_Status
-#define Select_Deselect __QERTABLENAME.m_pfnDeselectAllBrushes
-#define Map_New __QERTABLENAME.m_pfnMapNew
-#define Map_Free __QERTABLENAME.m_pfnMapFree
-#define Map_IsBrushFiltered __QERTABLENAME.m_pfnMap_IsBrushFiltered
-#define Map_BuildBrushData __QERTABLENAME.m_pfnMapBuildBrushData
-#define Map_StartPosition __QERTABLENAME.m_pfnMapStartPosition
-#define Map_RegionOff __QERTABLENAME.m_pfnMapRegionOff
-#define QE_ConvertDOSToUnixName __QERTABLENAME.m_pfnQE_ConvertDOSToUnixName
-#define SetBuildWindingsNoTexBuild __QERTABLENAME.m_pfnSetBuildWindingsNoTexBuild
-//#define SaveAsDialog __QERTABLENAME.m_pfnSaveAsDialog
-#define Pointfile_Clear __QERTABLENAME.m_pfnPointFileClear
-#define SetScreenUpdate __QERTABLENAME.m_pfnSetScreenUpdate
-#define Region_SpawnPoint __QERTABLENAME.m_pfnRegionSpawnPoint
-#define QGetTickCount __QERTABLENAME.m_pfnGetTickCount
-#define GetModelCache __QERTABLENAME.m_pfnGetModelCache
-#define GetFileTypeRegistry __QERTABLENAME.m_pfnGetFileTypeRegistry
-#else
-IFileTypeRegistry* GetFileTypeRegistry();
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// QERadiant PlugIns
+//
+//
+
+#ifndef __QERPLUGIN_H__
+#define __QERPLUGIN_H__
+
+/*!
+\todo this header is intended to be turned into a header for the core editor functionality
+some portability related code should be moved to synapse (such as the GUID stuff)
+*/
+
+#include <stdio.h>
+#include <string.h>
+// TTimo
+// ideally the plugin API would be UI toolkit independent, but removing the dependency with GLib seems tricky right now..
+#include <glib.h>
+#include "qertypes.h"
+
+// FIXME TTimo:
+// GUID declaration here should be trashed, it is in synapse.h
+#ifdef _WIN32
+#include <wtypes.h>
+#endif
+
+#define QER_MAX_NAMELEN 1024
+
+#ifndef _WIN32
+#include "misc_def.h"
+#endif
+
+// the editor will look for plugins in two places, the plugins path 
+// under the application path, and the path under the basepath as defined
+// in the project (.qe4) file.
+//
+// you can drop any number of new texture, model format DLL's in the standard plugin path
+// but only one plugin that overrides map loading/saving, surface dialog, surface flags, etc.. 
+// should be used at one time.. if multiples are loaded then the last one loaded will be the 
+// active one
+//
+// type of services the plugin supplies, pass any combo of these flags
+// it is assumed the plugin will have a matching function as defined below
+// to correlate to the implied functionality
+// 
+
+#define RADIANT_MAJOR "radiant"
+
+// basics
+#define QERPLUG_INIT "QERPlug_Init"
+#define QERPLUG_GETNAME "QERPlug_GetName"
+#define QERPLUG_GETCOMMANDLIST "QERPlug_GetCommandList"
+#define QERPLUG_DISPATCH "QERPlug_Dispatch"
+#define QERPLUG_GETFUNCTABLE "QERPlug_GetFuncTable"
+
+// game stuff
+#define QERPLUG_GETTEXTUREINFO "QERPlug_GetTextureInfo"   // gets a texture info structure
+#define QERPLUG_LOADTEXTURE    "QERPlug_LoadTexture"      // loads a texture, will return an RGBA structure
+                                                          // and any surface flags/contents for it
+#define QERPLUG_GETSURFACEFLAGS "QERPlug_GetSurfaceFlags" // gets a list of surface/content flag names from a plugin
+
+struct _QERTextureInfo
+{
+  char m_TextureExtension[QER_MAX_NAMELEN];   // the extension these textures have
+  qboolean m_bHiColor;    // if textures are NOT high color, the default 
+                      // palette (as described inthe qe4 file will be used for gamma correction)
+                      // if they are high color, gamma and shading are computed on the fly 
+                      // based on the rgba data
+  //--bool m_bIsShader;   // will probably do q3 shaders this way when i merge
+  qboolean m_bWadStyle;   // if this is true, the plugin will be presented with the texture path
+                      // defined in the .qe4 file and is expected to preload all the textures
+  qboolean m_bHalfLife;   // causes brushes to be saved/parsed without the surface contents/flags/value
+};
+
+struct _QERTextureLoad    // returned by a plugin
+{
+  _QERTextureLoad()
+  { 
+    memset(reinterpret_cast<void*>(this), 0, sizeof(_QERTextureLoad));
+  };
+
+  ~_QERTextureLoad()
+  {
+    delete []m_pRGBA;
+    delete []m_pName;
+  };
+
+  void makeSpace(int nSize)
+  {
+    m_pRGBA = new unsigned char[nSize+1];
+  };
+
+  void setName(const char* p)
+  {
+    m_pName = new char[strlen(p)+1];
+    strcpy(m_pName, p);
+  };
+
+
+  unsigned char *m_pRGBA; // rgba data (alpha channel is supported and drawn appropriately)
+  int m_nWidth;           // width
+  int m_nHeight;          // height
+  int m_nContents;        // default contents
+  int m_nFlags;           // "" flags
+  int m_nValue;           // "" value
+  char *m_pName;          // name to be referenced in map, build tools, etc.
+};
+
+struct _QERModelInfo
+{
+  char m_ModelExtension[QER_MAX_NAMELEN];
+  bool m_bSkinned;
+  bool m_bMultipart;
+};
+
+struct _QERModelLoad
+{
+  // vertex and skin data
+};
+
+
+//=========================================
+// plugin functions
+#if 0
+// NOTE TTimo: hack to make old plugin tech and new plugin tech live together
+#ifndef _IPLUGIN_H_
+// toolkit-independant interface, cast hwndMain to GtkWidget*
+typedef const char* (WINAPI *PFN_QERPLUG_INIT)(void* hApp, void* hwndMain);
+typedef const char* (WINAPI *PFN_QERPLUG_GETNAME)();
+typedef const char* (WINAPI *PFN_QERPLUG_GETCOMMANDLIST)();
+typedef void  (WINAPI *PFN_QERPLUG_DISPATCH)(const char* p, vec3_t vMin, vec3_t vMax, bool bSingleBrush);
+#endif
+#endif
+
+typedef char* (WINAPI *PFN_QERPLUG_GETFUNCTABLE)();
+
+// v1.5
+//
+// Texture loading
+// returns a ptr to _QERTextureInfo
+typedef void* (WINAPI *PFN_QERPLUG_GETTEXTUREINFO)();
+//
+// loads a texture by calling the texture load func in the editor (defined below)
+// transparency (for water, fog, lava, etc.. ) can be emulated in the editor
+// by passing in appropriate alpha data or by setting the appropriate surface flags
+// expected by q2 (which the editor will use.. )
+typedef void (WINAPI *PFN_QERPLUG_LOADTEXTURE)(const char* pFilename); 
+
+// v1.6
+typedef void* (WINAPI *PFN_QERPLUG_GETSURFACEFLAGS)();
+
+// v1.7
+// if exists in plugin, gets called between INIT and GETCOMMANDLIST
+// the plugin can register the EClasses he wants to handle
+//++timo TODO: this has got to move into the table, and be requested by QERPlug_RequestInterface
+//++timo FIXME: the LPVOID parameter must be casted to an IEpair interface
+#define QERPLUG_REGISTERPLUGINENTITIES "QERPlug_RegisterPluginEntities"
+typedef void (WINAPI * PFN_QERPLUG_REGISTERPLUGINENTITIES)( void* );
+
+// if exists in plugin, gets called between INIT and GETCOMMANDLIST
+// the plugin can Init all it needs for surface properties
+#define QERPLUG_INITSURFACEPROPERTIES "QERPlug_InitSurfaceProperties"
+typedef void (WINAPI * PFN_QERPLUG_INITSURFACEPROPERTIES)();
+
+// if Radiant needs to use a particular set of commands, it can request the plugin to fill a func table
+// this is similar to PFN_QERAPP_REQUESTINTERFACE
+#define QERPLUG_REQUESTINTERFACE "QERPlug_RequestInterface"
+typedef int (WINAPI * PFN_QERPLUG_REQUESTINTERFACE) (REFGUID refGUID, void* pInterface, const char *version_name);
+
+// Load an image file
+typedef void (* PFN_QERAPP_LOADIMAGE) (const char *name, unsigned char **pic, int *width, int *height);
+
+// TTimo FIXME: the logic for this is in synapse now
+
+// MODULES specific:
+// if it exports this entry point, will be considered as a module
+// a module is a plugin that provides some REQUIRED interfaces to Radiant, such as the shader module
+// Radiant will call QERPLUG_LISTINTERFACES to get a list of the interfaces a given plugin implements
+// then it will call PFN_QERPLUG_REQUESTINTERFACE to actually get them
+
+// following leo's code .. looks ok to use a string to identify the various versions of a same interface
+// obviously it would be handy to have the same string naming for the interfaces.
+// best way would be to have the names come in when you list the interfaces
+// NOTE: we might have a problem with the order in which the interfaces are filled in
+//   there's some kind of dependency graph, the shader module expects to find the VFS ready etc.
+typedef struct moduleentry_s {
+  const GUID *interface_GUID;
+  const char* interface_name;
+  const char* version_name; 
+} moduleentry_t;
+
+#define QERPLUG_LISTINTERFACES "QERPlug_ListInterfaces"
+#define MAX_QERPLUG_INTERFACES 10
+typedef int (WINAPI* PFN_QERPLUG_LISTINTERFACES) (moduleentry_t table[MAX_QERPLUG_INTERFACES]);
+
+// ========================================
+// GTK+ helper functions
+
+// NOTE: parent can be NULL in all functions but it's best to set them
+
+// simple Message Box, see above for the 'type' flags
+// toolkit-independent, cast parent ot a GtkWidget*
+typedef gint (WINAPI* PFN_QERAPP_MESSAGEBOX) (void *parent, const char* text,
+                                              const char* caption, guint32 type, const char *URL);
+
+// file and directory selection functions return NULL if the user hits cancel
+// or a gchar* string that must be g_free'd by the user
+// - 'title' is the dialog title (can be NULL)
+// - 'path' is used to set the initial directory (can be NULL)
+// - 'pattern': the first pattern is for the win32 mode, then comes the Gtk pattern list, see Radiant source for samples
+// TTimo 04/01/2001 toolkit-independant, cast parent to a GtkWidget*
+typedef const gchar* (* PFN_QERAPP_FILEDIALOG) (void *parent, gboolean open, const char* title,
+                                                const char* path, const char* pattern);
+typedef gchar* (WINAPI* PFN_QERAPP_DIRDIALOG) (void *parent, const char* title,
+                                               const char* path);
+
+// return true if the user closed the dialog with 'Ok'
+// 'color' is used to set the initial value and store the selected value
+typedef bool (WINAPI* PFN_QERAPP_COLORDIALOG) (void *parent, float *color,
+                                               const char* title);
+
+// load a .bmp file and store the results in 'gdkpixmap' and 'mask'
+// returns TRUE on success but even if it fails, it creates an empty pixmap
+// NOTE: 'filename' is relative to <radiant_path>/plugins/bitmaps/
+// TTimo 04/01/2001 toolkit-independant, cast gkpixmap to GdkPixmap and mask to GdkBitmap
+typedef bool (WINAPI* PFN_QERAPP_LOADBITMAP) (const char* filename, void **gdkpixmap, void **mask);
+
+// ========================================
+// read/write preferences file
+
+// use this function to get the directory where the preferences file are stored
+typedef const char* (WINAPI* PFN_QERAPP_PROFILE_GETDIR) ();
+
+// 'filename' is the absolute path
+typedef bool (WINAPI* PFN_QERAPP_PROFILE_SAVEINT) (const char *filename, const char *section,
+                                                   const char *key, int value);
+typedef bool (WINAPI* PFN_QERAPP_PROFILE_SAVESTR) (const char *filename, const char *section,
+                                                   const char *key, const char *value);
+typedef int (WINAPI* PFN_QERAPP_PROFILE_LOADINT) (const char *filename, const char *section,
+                                                  const char *key, int default_value);
+typedef char* (WINAPI* PFN_QERAPP_PROFILE_LOADSTR) (const char *filename, const char *section,
+                                                    const char *key, const char *default_value);
+
+//=========================================
+// editor functions
+
+// There are 3 potential brush handle lists
+// 1. the list that contains brushes a plugin creates using CreateBrushHandle
+// 2. the selected brush list (brushes the user has selected)
+// 3. the active brush list (brushes in the map that are not selected)
+// 
+// In general, the same things can be done to brush handles (face manip, delete brushhandle, etc.. ) in each
+// list. There are a few exceptions. 
+// 1. You cannot commit a selected or active brush handle to the map. This is because it is already in the map. 
+// 2. You cannot bind brush handles from the selected or active brush list to an entity. As of v1.0 of the plugins
+// the only way for a plugin to create entities is to create a brush handles (or a list of handles) and then bind
+// them to an entity. This will commit the brush(s) and/or the entities to the map as well.
+// 
+// To use the active or selected brush lists, you must first allocate them (which returns a count) and then
+// release them when you are finish manipulating brushes in one of those lists. 
+
+//++timo NOTE : the #defines here are never used, but can help finding where things are done in the editor
+#if 0
+// brush manipulation routines
+#define QERAPP_CREATEBRUSH "QERApp_CreateBrush"
+#define QERAPP_CREATEBRUSHHANDLE "QERApp_CreateBrushHandle"
+#define QERAPP_DELETEBRUSHHANDLE "QERApp_DeleteBrushHandle"
+#define QERAPP_COMMITBRUSHHANDLETOMAP "QERApp_CommitBrushHandleToMap"
+//++timo not implemented .. remove
+// #define QERAPP_BINDHANDLESTOENTITY "QERApp_BindHandlesToEntity"
+#define QERAPP_ADDFACE "QERApp_AddFace"
+#define QERAPP_ADDFACEDATA "QERApp_AddFaceData"
+#define QERAPP_GETFACECOUNT "QERApp_GetFaceCount"
+#define QERAPP_GETFACEDATA "QERApp_GetFaceData"
+#define QERAPP_SETFACEDATA "QERApp_SetFaceData"
+#define QERAPP_DELETEFACE "QERApp_DeleteFace"
+#define QERAPP_TEXTUREBRUSH "QERApp_TextureBrush"
+#define QERAPP_BUILDBRUSH "QERApp_BuildBrush"					// PGM
+#define QERAPP_SELECTEDBRUSHCOUNT "QERApp_SelectedBrushCount"
+#define QERAPP_ALLOCATESELECTEDBRUSHHANDLES "QERApp_AllocateSelectedBrushHandles"
+#define QERAPP_RELEASESELECTEDBRUSHHANDLES "QERApp_ReleaseSelectedBrushHandles"
+#define QERAPP_GETSELECTEDBRUSHHANDLE "QERApp_GetSelectedBrushHandle"
+#define QERAPP_ACTIVEBRUSHCOUNT "QERApp_ActiveBrushCount"
+#define QERAPP_ALLOCATEACTIVEBRUSHHANDLES "QERApp_AllocateActiveBrushHandles"
+#define QERAPP_RELEASEACTIVEBRUSHHANDLES "QERApp_ReleaseActiveBrushHandles"
+#define QERAPP_GETACTIVEBRUSHHANDLE "QERApp_GetActiveBrushHandle"
+
+// texture stuff
+#define QERAPP_TEXTURECOUNT "QERApp_TextureCount"
+#define QERAPP_GETTEXTURE "QERApp_GetTexture"
+#define QERAPP_GETCURRENTTEXTURE "QERApp_GetCurrentTexture"
+#define QERAPP_SETCURRENTTEXTURE "QERApp_SetCurrentTexture"
+
+// selection 
+#define QERAPP_DELETESELECTION "QERApp_DeleteSelection"
+#define QERAPP_SELECTBRUSH "QERApp_SelectBrush"					// PGM
+#define QERAPP_DESELECTBRUSH "QERApp_DeselectBrush"				// PGM
+#define QERAPP_DESELECTALLBRUSHES "QERApp_DeselectAllBrushes"	// PGM
+
+// data gathering
+#define QERAPP_GETPOINTS "QERApp_GetPoints"
+#define QERAPP_SELECTBRUSHES "QERApp_GetBrushes"
+
+// entity class stuff
+// the entity handling is very basic for 1.0
+#define QERAPP_GETECLASSCOUNT "QERApp_GetEClassCount"
+#define QERAPP_GETECLASS "QERApp_GetEClass"
+
+// misc
+#define QERAPP_SYSMSG "QERApp_SysMsg"
+#define QERAPP_INFOMSG "QERApp_InfoMsg"
+#define QERAPP_HIDEINFOMSG "QERApp_HideInfoMsg"
+#define QERAPP_RESET_PLUGINS "QERApp_ResetPlugins"
+
+// texture loading
+#define QERAPP_LOADTEXTURERGBA "QERApp_LoadTextureRGBA"
+
+// FIXME: the following are not implemented yet
+// hook registrations
+#define QERAPP_REGISTER_MAPLOADFUNC "QERApp_Register_MapLoadFunc"
+#define QERAPP_REGISTER_MAPSAVEFUNC "QERApp_Register_MapSaveFunc"
+
+// FIXME: the following are not implemented yet
+#define QERAPP_REGISTER_PROJECTLOADFUNC "QERApp_Register_ProjectLoadFunc"
+#define QERAPP_REGISTER_MOUSEHANDLER "QERApp_Register_MouseHandler"
+#define QERAPP_REGISTER_KEYHANDLER "QERApp_Register_KeyHandler"
+
+// FIXME: new primtives do not work in v1.00
+// primitives are new types of things in the map
+// for instance, the Q3 curves could have been done as 
+// primitives instead of being built in 
+// it will be a plugins responsibility to hook the map load and save funcs to load
+// and/or save any additional data (like new primitives of some type)
+// the editor will call each registered renderer during the rendering process to repaint
+// any primitives the plugin owns
+// each primitive object has a temporary sibling brush that lives in the map
+// FIXME: go backwards on this a bit.. orient it more towards the temp brush mode as it will be cleaner
+// basically a plugin will hook the map load and save and will add the primitives to the map.. this will
+// produce a temporary 'primitive' brush and the appropriate renderer will be called as well as the 
+// edit handler (for edge drags, sizes, rotates, etc.. ) and the vertex maker will be called when vertex
+// mode is attemped on the brush.. there will need to be a GetPrimitiveBounds callback in the edit handler
+// so the brush can resize appropriately as needed.. this might be the plugins responsibility to set the 
+// sibling brushes size.. it will then be the plugins responsibility to hook map save to save the primitives
+// as the editor will discard any temp primitive brushes.. (there probably needs to be some kind of sanity check
+// here as far as keeping the brushes and the plugin in sync.. i suppose the edit handler can deal with all of that
+// crap but it looks like a nice place for a mess)
+#define QERAPP_REGISTER_PRIMITIVE "QERApp_Register_Primitive"
+#define QERAPP_REGISTER_RENDERER "QERApp_Register_Renderer"
+#define QERAPP_REGISTER_EDITHANDLER "QERApp_Register_EditHandler"
+#define QERAPP_REGISTER_VERTEXMAKER "QERApp_Register_VertexMaker"
+#define QERAPP_ADDPRIMITIVE "QERApp_AddPrimitive"
+
+// v1.70
+#define QERAPP_GETENTITYCOUNT "QERApp_GetEntityCount"
+#define QERAPP_GETENTITYHANDLE "QERApp_GetEntityHandle"
+//++timo not implemented for the moment
+// #define QERAPP_GETENTITYINFO "QERApp_GetEntityInfo"
+//++timo does the keyval need some more funcs to add/remove ?
+// get the pointer and do the changes yourself
+#define QERAPP_ALLOCATEEPAIR "QERApp_AllocateEpair"
+#define QERAPP_ALLOCATEENTITYBRUSHHANDLES "QERApp_AllocateEntityBrushHandles"
+#define QERAPP_RELEASEENTITYBRUSHHANDLES "QERApp_ReleaseEntityBrushHandles"
+#define QERAPP_GETENTITYBRUSHHANDLE "QERApp_GetEntityBrushHandle"
+#define QERAPP_CREATEENTITYHANDLE "QERApp_CreateEntityHandle"
+#define QERAPP_COMMITBRUSHHANDLETOENTITY "QERApp_CommitBrushHandleToEntity"
+#define QERAPP_COMMITENTITYHANDLETOMAP "QERApp_CommitEntityHandleToMap"
+#define QERAPP_SETSCREENUPDATE "QERApp_SetScreenUpdate"
+#define QERAPP_BUILDBRUSH2 "QERApp_BuildBrush2"
+#endif
+
+// v1.80
+#define QERAPP_GETDISPATCHPARAMS "QERApp_GetDispatchParams"
+
+struct _QERPointData
+{
+  int     m_nCount;
+  vec3_t *m_pVectors;
+};
+
+struct _QERFaceData
+{
+  char  m_TextureName[QER_MAX_NAMELEN];
+  int   m_nContents;
+  int   m_nFlags;
+  int   m_nValue;
+  float m_fShift[2];
+  float m_fRotate;
+  float m_fScale[2];
+  vec3_t m_v1, m_v2, m_v3;
+  // brush primitive additions
+  qboolean m_bBPrimit;
+  brushprimit_texdef_t brushprimit_texdef;
+};
+
+typedef void (WINAPI * PFN_QERAPP_CREATEBRUSH)(vec3_t vMin, vec3_t vMax);
+
+typedef void* (WINAPI * PFN_QERAPP_CREATEBRUSHHANDLE)();
+typedef void (WINAPI * PFN_QERAPP_DELETEBRUSHHANDLE)(void* pv);
+typedef void (WINAPI * PFN_QERAPP_COMMITBRUSHHANDLETOMAP)(void* pv);
+typedef void (WINAPI * PFN_QERAPP_ADDFACE)(void* pv, vec3_t v1, vec3_t v2, vec3_t v3);
+
+typedef void (WINAPI * PFN_QERAPP_ADDFACEDATA)(void* pv, _QERFaceData *pData);
+typedef int  (WINAPI * PFN_QERAPP_GETFACECOUNT)(void* pv);
+typedef _QERFaceData* (WINAPI * PFN_QERAPP_GETFACEDATA)(void* pv, int nFaceIndex);
+typedef void (WINAPI * PFN_QERAPP_SETFACEDATA)(void* pv, int nFaceIndex, _QERFaceData *pData);
+typedef void (WINAPI * PFN_QERAPP_DELETEFACE)(void* pv, int nFaceIndex);
+typedef void (WINAPI * PFN_QERAPP_TEXTUREBRUSH)(void* pv, char* pName);
+typedef void (WINAPI * PFN_QERAPP_BUILDBRUSH)(void* pv);		// PGM
+typedef void (WINAPI * PFN_QERAPP_SELECTBRUSH)(void* pv);		// PGM
+typedef void (WINAPI * PFN_QERAPP_DESELECTBRUSH)(void* pv);		// PGM
+typedef void (WINAPI * PFN_QERAPP_DESELECTALLBRUSHES)();			// PGM
+
+typedef void (WINAPI * PFN_QERAPP_DELETESELECTION)();
+typedef void (WINAPI * PFN_QERAPP_GETPOINTS)(int nMax, _QERPointData *pData, char* pMsg);
+
+typedef int  (WINAPI * PFN_QERAPP_SELECTEDBRUSHCOUNT)();
+typedef int (WINAPI * PFN_QERAPP_ALLOCATESELECTEDBRUSHHANDLES)();
+typedef void (WINAPI * PFN_QERAPP_RELEASESELECTEDBRUSHHANDLES)();
+typedef void* (WINAPI * PFN_QERAPP_GETSELECTEDBRUSHHANDLE)(int nIndex);
+
+typedef int  (WINAPI * PFN_QERAPP_ACTIVEBRUSHCOUNT)();
+typedef int (WINAPI * PFN_QERAPP_ALLOCATEACTIVEBRUSHHANDLES)();
+typedef void (WINAPI * PFN_QERAPP_RELEASEACTIVEBRUSHHANDLES)();
+typedef void* (WINAPI * PFN_QERAPP_GETACTIVEBRUSHHANDLE)(int nIndex);
+
+typedef int  (WINAPI * PFN_QERAPP_TEXTURECOUNT)();
+typedef char* (WINAPI * PFN_QERAPP_GETTEXTURE)(int nIndex);
+typedef char* (WINAPI * PFN_QERAPP_GETCURRENTTEXTURE)();
+typedef void (WINAPI * PFN_QERAPP_SETCURRENTTEXTURE)(char* pName);
+
+typedef void (WINAPI * PFN_QERAPP_REGISTERMAPLOAD)(void* vp);
+typedef void (WINAPI * PFN_QERAPP_REGISTERMAPSAVE)(void* vp);
+
+typedef int (WINAPI * PFN_QERAPP_GETECLASSCOUNT)();
+typedef char* (WINAPI * PFN_QERAPP_GETECLASS)(int nIndex);
+
+typedef void (WINAPI * PFN_QERAPP_RESETPLUGINS)();
+//--typedef int (WINAPI* PFN_QERAPP_GETENTITYCOUNT)();
+
+/*!
+\fn LoadTextureRGBA
+\param pPixels is the raw RGBA pixel data (24bits, 8 bit depth)
+\param nWidth image width
+\param nHeight image height
+this will work from the RGBA data and create a GL texture (accessed through a GL bind number)
+it takes care of creating the mipmapping levels too
+see http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=575 for some related issues
+*/
+typedef qtexture_t* (* PFN_QERAPP_LOADTEXTURERGBA)(unsigned char* pPixels, int nWidth, int nHeight);
+
+//--typedef LPCSTR (WINAPI* PFN_QERAPP_GETENTITY)(int nIndex);
+
+// v1.70
+typedef int (WINAPI * PFN_QERAPP_GETENTITYCOUNT)();
+typedef void* (WINAPI * PFN_QERAPP_GETENTITYHANDLE)(int nIndex);
+// FIXME: those two are fairly outdated, you get the epairs
+//   but you don't have a clean epair read/write query
+//   and you rely on the C structs directly, which might go away soon
+//   ok now, stop using, it's bad for your karma (see iepairs.h instead)
+typedef epair_t* (WINAPI * PFN_QERAPP_ALLOCATEEPAIR)( char*, char* );
+typedef int (WINAPI * PFN_QERAPP_ALLOCATEENTITYBRUSHHANDLES)(void* vp);
+typedef void (WINAPI * PFN_QERAPP_RELEASEENTITYBRUSHHANDLES)();
+typedef void* (WINAPI * PFN_QERAPP_GETENTITYBRUSHHANDLE)(int nIndex);
+typedef void* (WINAPI * PFN_QERAPP_CREATEENTITYHANDLE)();
+typedef void (WINAPI * PFN_QERAPP_COMMITBRUSHHANDLETOENTITY)( void* vpBrush, void* vpEntity);
+typedef void (WINAPI * PFN_QERAPP_COMMITENTITYHANDLETOMAP)(void* vp);
+typedef void (WINAPI * PFN_QERAPP_SETSCREENUPDATE)(int bScreenUpdate);
+// this one uses window flags defined in qertypes.h
+typedef void (WINAPI * PFN_QERAPP_SYSUPDATEWINDOWS)(int bits);
+//++timo remove this one
+typedef void (WINAPI * PFN_QERAPP_BUILDBRUSH2)(void* vp, int bConvert);
+
+// v1.80
+typedef void (WINAPI * PFN_QERAPP_GETDISPATCHPARAMS)(vec3_t vMin, vec3_t vMax, bool *bSingleBrush);
+
+typedef int (WINAPI * PFN_QERAPP_REQUESTINTERFACE)( REFGUID, void* );
+// use this one for errors, Radiant will stop after the "edit preferences" dialog
+typedef void (WINAPI * PFN_QERAPP_ERROR)(char* pMsg, ...);
+// use to gain read access to the project epairs
+// FIXME: removed, accessed through QERPlug_RegisterPluginEntities with the IEpair interface
+// typedef void (WINAPI* PFN_QERAPP_GETPROJECTEPAIR)(epair_t **);
+// used to allocate and read a buffer
+//++timo NOTE: perhaps this would need moving to some kind of dedicated interface
+typedef int (WINAPI * PFN_QERAPP_LOADFILE)(const char *pLocation, void ** buffer);
+typedef char* (WINAPI * PFN_QERAPP_EXPANDRELETIVEPATH)(char *);
+typedef void (WINAPI * PFN_QERAPP_QECONVERTDOSTOUNIXNAME)( char *dst, const char *src );
+typedef int (WINAPI * PFN_QERAPP_HASSHADER)(const char *);
+typedef int (WINAPI * PFN_QERAPP_TEXTURELOADSKIN)(char *pName, int *pnWidth, int *pnHeight);
+// retrieves the path to the engine from the preferences dialog box
+typedef const char* (WINAPI * PFN_QERAPP_GETGAMEPATH)();
+// retrieves full Radiant path
+typedef const char* (WINAPI * PFN_QERAPP_GETQERPATH)();
+// retieves .game name of current active game
+typedef const char* (WINAPI * PFN_QERAPP_GETGAMEFILE)();
+
+// patches in/out
+// NOTE: this is a bit different from the brushes in/out, no LPVOID handles this time
+// use int indexes instead
+// if you call AllocateActivePatchHandles, you'll be playing with active patches
+// AllocateSelectedPatcheHandles for selected stuff
+// a call to CreatePatchHandle will move you to a seperate index table
+typedef int				(WINAPI * PFN_QERAPP_ALLOCATEACTIVEPATCHHANDLES)		();
+typedef int				(WINAPI * PFN_QERAPP_ALLOCATESELECTEDPATCHHANDLES)	();
+typedef void			(WINAPI * PFN_QERAPP_RELEASEPATCHHANDLES)			();
+typedef patchMesh_t*	(WINAPI * PFN_QERAPP_GETPATCHDATA)					(int);
+typedef patchMesh_t*	(WINAPI * PFN_QERAPP_GETPATCHHANDLE)				(int);
+typedef void			(WINAPI * PFN_QERAPP_DELETEPATCH)				(int);
+typedef int				(WINAPI * PFN_QERAPP_CREATEPATCHHANDLE)				();
+// when commiting, only a few patchMesh_t members are relevant:
+//  int	width, height;		// in control points, not patches
+//  int   contents, flags, value, type;
+//  drawVert_t ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
+// once you have commited the index is still available, if the patch handle was allocated by you
+//   then you can re-use the index to commit other patches .. otherwise you can change existing patches
+// NOTE: the handle thing for plugin-allocated patches is a bit silly (nobody's perfect)
+// TODO: change current behaviour to an index = 0 to tell Radiant to allocate, other indexes to existing patches
+// patch is selected after a commit
+// you can add an optional texture / shader name .. if NULL will use the current texture
+typedef void			(WINAPI * PFN_QERAPP_COMMITPATCHHANDLETOMAP)			(int, patchMesh_t* pMesh, char *texName);
+typedef void			(WINAPI * PFN_QERAPP_COMMITPATCHHANDLETOENTITY)			(int, patchMesh_t* pMesh, char *texName, void* vpEntity);
+
+// console output
+#define SYS_VRB 0 ///< verbose support (on/off)
+#define SYS_STD 1 ///< standard print level - this is the default
+#define SYS_WRN 2 ///< warnings
+#define SYS_ERR 3 ///< error
+#define SYS_NOCON 4 ///< no console, only print to the file (useful whenever Sys_Printf and output IS the problem)
+typedef void (WINAPI* PFN_QERAPP_SYSPRINTF) (const char *text, ...);
+typedef void (WINAPI* PFN_QERAPP_SYSFPRINTF) (int flag, const char *text, ...);
+
+typedef void (WINAPI* PFN_QERAPP_SYSBEGINWAIT) ();
+typedef void (WINAPI* PFN_QERAPP_SYSENDWAIT) ();
+
+typedef void (* PFN_QERAPP_SYSBEEP) ();
+
+typedef void (* PFN_QERAPP_SYSSTATUS) (const char *psz, int part );
+
+// core map functionality
+typedef void      (* PFN_QERAPP_MAPNEW)                     ();
+typedef void      (* PFN_QERAPP_MAPFREE)                    ();
+typedef void      (* PFN_QERAPP_MAPBUILDBRUSHDATA)          ();
+typedef qboolean  (* PFN_QERAPP_MAPISBRUSHFILTERED)         (brush_t *);
+typedef void      (* PFN_QERAPP_MAPSTARTPOSITION)           ();
+typedef void      (* PFN_QERAPP_MAPREGIONOFF)               ();
+//typedef void      (* PFN_QERAPP_SAVEASDIALOG)               (bool bRegion);
+typedef void      (* PFN_QERAPP_SETBUILDWINDINGSNOTEXBUILD) (bool);
+typedef void      (* PFN_QERAPP_POINTFILECLEAR)             ();
+
+typedef void (* PFN_QERAPP_SYSSETTITLE) (const char *text);
+
+typedef void (* PFN_QERAPP_CSGMAKEHOLLOW) ();
+
+typedef void (* PFN_QERAPP_REGIONSPAWNPOINT) (FILE *f);
+
+/*!
+access to a portable GetTickCount
+*/
+typedef unsigned long (* PFN_QERAPP_GETTICKCOUNT) ();
+
+class IModelCache
+{
+public:
+  virtual entity_interfaces_t *GetByID(const char *id, const char* version) = 0;
+  virtual void DeleteByID(const char *id, const char* version) = 0;
+  virtual void RefreshAll() = 0;
+};
+
+typedef IModelCache* (* PFN_GETMODELCACHE)();
+
+class IFileTypeList
+{
+public:
+  virtual void addType(filetype_t type) = 0;
+};
+
+class IFileTypeRegistry
+{
+public:
+  virtual void addType(const char* key, filetype_t type) = 0;
+  virtual void getTypeList(const char* key, IFileTypeList* typelist) = 0;
+private:
+};
+
+typedef IFileTypeRegistry* (* PFN_GETFILETYPEREGISTRY)();
+
+typedef const char* (* PFN_QERAPP_READPROJECTKEY)(const char* key);
+
+typedef char* (* PFN_GETMAPFILENAME)();
+
+  // FIXME:
+// add map format extensions
+// add texture format handlers
+// add surface dialog handler
+// add model handler/displayer
+
+// v1 func table
+// Plugins need to declare one of these and implement the getfunctable as described above
+struct _QERFuncTable_1
+{
+  int   m_nSize;
+  PFN_QERAPP_CREATEBRUSH            m_pfnCreateBrush;
+  PFN_QERAPP_CREATEBRUSHHANDLE      m_pfnCreateBrushHandle;
+  PFN_QERAPP_DELETEBRUSHHANDLE      m_pfnDeleteBrushHandle;
+  PFN_QERAPP_COMMITBRUSHHANDLETOMAP m_pfnCommitBrushHandle;
+  PFN_QERAPP_ADDFACE                m_pfnAddFace;
+  PFN_QERAPP_ADDFACEDATA            m_pfnAddFaceData;
+  PFN_QERAPP_GETFACEDATA            m_pfnGetFaceData;
+  PFN_QERAPP_GETFACECOUNT           m_pfnGetFaceCount;
+  PFN_QERAPP_SETFACEDATA            m_pfnSetFaceData;
+  PFN_QERAPP_DELETEFACE             m_pfnDeleteFace;
+  PFN_QERAPP_TEXTUREBRUSH           m_pfnTextureBrush;
+  PFN_QERAPP_BUILDBRUSH				m_pfnBuildBrush;				// PGM
+  PFN_QERAPP_SELECTBRUSH			m_pfnSelectBrush;				// PGM
+  PFN_QERAPP_DESELECTBRUSH			m_pfnDeselectBrush;				// PGM
+  PFN_QERAPP_DESELECTALLBRUSHES		m_pfnDeselectAllBrushes;		// PGM
+
+  PFN_QERAPP_DELETESELECTION        m_pfnDeleteSelection;
+  PFN_QERAPP_GETPOINTS              m_pfnGetPoints;
+
+  PFN_QERAPP_SELECTEDBRUSHCOUNT           m_pfnSelectedBrushCount;
+  PFN_QERAPP_ALLOCATESELECTEDBRUSHHANDLES m_pfnAllocateSelectedBrushHandles;
+  PFN_QERAPP_RELEASESELECTEDBRUSHHANDLES  m_pfnReleaseSelectedBrushHandles;
+  PFN_QERAPP_GETSELECTEDBRUSHHANDLE       m_pfnGetSelectedBrushHandle;
+
+  PFN_QERAPP_ACTIVEBRUSHCOUNT             m_pfnActiveBrushCount;
+  PFN_QERAPP_ALLOCATEACTIVEBRUSHHANDLES   m_pfnAllocateActiveBrushHandles;
+  PFN_QERAPP_RELEASEACTIVEBRUSHHANDLES    m_pfnReleaseActiveBrushHandles;
+  PFN_QERAPP_GETACTIVEBRUSHHANDLE         m_pfnGetActiveBrushHandle;
+
+  //++timo this would need to be removed and replaced by the IShaders interface
+  PFN_QERAPP_TEXTURECOUNT                 m_pfnTextureCount;
+  PFN_QERAPP_GETTEXTURE                   m_pfnGetTexture;
+  PFN_QERAPP_GETCURRENTTEXTURE            m_pfnGetCurrentTexture;
+  PFN_QERAPP_SETCURRENTTEXTURE            m_pfnSetCurrentTexture;
+
+  PFN_QERAPP_GETECLASSCOUNT         m_pfnGetEClassCount;
+  PFN_QERAPP_GETECLASS              m_pfnGetEClass;
+  PFN_QERAPP_RESETPLUGINS           m_pfnResetPlugins;
+  // v1.00 ends here
+  // v1.50 starts here
+  PFN_QERAPP_LOADTEXTURERGBA        m_pfnLoadTextureRGBA;
+  // v1.50 ends here
+  // v1.70 starts here
+  PFN_QERAPP_GETENTITYCOUNT			m_pfnGetEntityCount;
+  PFN_QERAPP_GETENTITYHANDLE		m_pfnGetEntityHandle;
+  PFN_QERAPP_ALLOCATEENTITYBRUSHHANDLES	m_pfnAllocateEntityBrushHandles;
+  PFN_QERAPP_RELEASEENTITYBRUSHHANDLES	m_pfnReleaseEntityBrushHandles;
+  PFN_QERAPP_GETENTITYBRUSHHANDLE	m_pfnGetEntityBrushHandle;
+  PFN_QERAPP_CREATEENTITYHANDLE		m_pfnCreateEntityHandle;
+  PFN_QERAPP_COMMITBRUSHHANDLETOENTITY	m_pfnCommitBrushHandleToEntity;
+  PFN_QERAPP_COMMITENTITYHANDLETOMAP	m_pfnCommitEntityHandleToMap;
+  PFN_QERAPP_ALLOCATEEPAIR			m_pfnAllocateEpair;
+  PFN_QERAPP_SETSCREENUPDATE		m_pfnSetScreenUpdate;
+  PFN_QERAPP_BUILDBRUSH2			m_pfnBuildBrush2;
+  // v1.70 ends here
+  // v1.80 starts here
+  PFN_QERAPP_GETDISPATCHPARAMS     m_pfnGetDispatchParams;
+
+  // plugins can request additional interfaces
+  PFN_QERAPP_REQUESTINTERFACE		m_pfnRequestInterface;
+  PFN_QERAPP_ERROR					m_pfnError;
+  // loading a file into a buffer
+  PFN_QERAPP_LOADFILE				m_pfnLoadFile;
+  PFN_QERAPP_EXPANDRELETIVEPATH		m_pfnExpandReletivePath;
+  PFN_QERAPP_QECONVERTDOSTOUNIXNAME	m_pfnQE_ConvertDOSToUnixName;
+  PFN_QERAPP_HASSHADER				m_pfnHasShader;
+  PFN_QERAPP_TEXTURELOADSKIN		m_pfnTexture_LoadSkin;
+  PFN_QERAPP_GETGAMEPATH			m_pfnGetGamePath;
+  PFN_QERAPP_GETQERPATH				m_pfnGetQERPath;
+  PFN_QERAPP_GETGAMEFILE			m_pfnGetGameFile;
+  // patches in / out
+  PFN_QERAPP_ALLOCATEACTIVEPATCHHANDLES		m_pfnAllocateActivePatchHandles;
+  PFN_QERAPP_ALLOCATESELECTEDPATCHHANDLES	m_pfnAllocateSelectedPatchHandles;
+  PFN_QERAPP_RELEASEPATCHHANDLES			m_pfnReleasePatchHandles;
+  PFN_QERAPP_GETPATCHDATA					m_pfnGetPatchData;
+  PFN_QERAPP_GETPATCHHANDLE				m_pfnGetPatchHandle;
+  PFN_QERAPP_DELETEPATCH					m_pfnDeletePatch;
+  PFN_QERAPP_CREATEPATCHHANDLE				m_pfnCreatePatchHandle;
+  PFN_QERAPP_COMMITPATCHHANDLETOMAP			m_pfnCommitPatchHandleToMap;
+  PFN_QERAPP_COMMITPATCHHANDLETOENTITY	m_pfnCommitPatchHandleToEntity;
+
+  PFN_QERAPP_LOADIMAGE  m_pfnLoadImage;
+
+  // GTK+ functions
+  PFN_QERAPP_MESSAGEBOX  m_pfnMessageBox;
+  PFN_QERAPP_FILEDIALOG  m_pfnFileDialog;
+  PFN_QERAPP_DIRDIALOG   m_pfnDirDialog;
+  PFN_QERAPP_COLORDIALOG m_pfnColorDialog;
+  PFN_QERAPP_LOADBITMAP  m_pfnLoadBitmap;
+
+  // Profile functions
+  PFN_QERAPP_PROFILE_GETDIR  m_pfnProfileGetDirectory;
+  PFN_QERAPP_PROFILE_SAVEINT m_pfnProfileSaveInt;
+  PFN_QERAPP_PROFILE_SAVESTR m_pfnProfileSaveString;
+  PFN_QERAPP_PROFILE_LOADINT m_pfnProfileLoadInt;
+  PFN_QERAPP_PROFILE_LOADSTR m_pfnProfileLoadString;
+
+  // Sys_ functions
+  PFN_QERAPP_SYSUPDATEWINDOWS		m_pfnSysUpdateWindows;
+  PFN_QERAPP_SYSBEEP m_pfnSysBeep;
+  PFN_QERAPP_SYSPRINTF  m_pfnSysPrintf;
+  PFN_QERAPP_SYSFPRINTF m_pfnSysFPrintf;
+  PFN_QERAPP_SYSBEGINWAIT m_pfnSysBeginWait;
+  PFN_QERAPP_SYSENDWAIT m_pfnSysEndWait;
+  PFN_QERAPP_SYSSETTITLE m_pfnSys_SetTitle;
+  PFN_QERAPP_SYSSTATUS m_pfnSys_Status;
+
+  // some core functionality on the map
+  PFN_QERAPP_MAPNEW m_pfnMapNew;
+  PFN_QERAPP_MAPFREE m_pfnMapFree;
+  PFN_QERAPP_MAPBUILDBRUSHDATA m_pfnMapBuildBrushData;
+  PFN_QERAPP_MAPISBRUSHFILTERED m_pfnMap_IsBrushFiltered;
+  PFN_QERAPP_MAPSTARTPOSITION m_pfnMapStartPosition;
+  PFN_QERAPP_MAPREGIONOFF m_pfnMapRegionOff;
+  PFN_QERAPP_SETBUILDWINDINGSNOTEXBUILD m_pfnSetBuildWindingsNoTexBuild;
+//  PFN_QERAPP_SAVEASDIALOG m_pfnSaveAsDialog;
+  PFN_QERAPP_POINTFILECLEAR m_pfnPointFileClear;
+
+  // FIXME TTimo prolly want to move that somewhere else
+  PFN_QERAPP_CSGMAKEHOLLOW m_pfnCSG_MakeHollow;
+
+  PFN_QERAPP_REGIONSPAWNPOINT m_pfnRegionSpawnPoint;
+  PFN_QERAPP_GETTICKCOUNT m_pfnQGetTickCount;
+  PFN_GETMODELCACHE m_pfnGetModelCache;
+  PFN_GETFILETYPEREGISTRY m_pfnGetFileTypeRegistry;
+
+  PFN_QERAPP_READPROJECTKEY m_pfnReadProjectKey;
+
+  // digibob from the old _QERAppBSPFrontendTable table
+	PFN_GETMAPFILENAME  m_pfnGetMapName;
+};
+
+// macros to access those faster in plugins
+#ifdef USE_QERTABLE_DEFINE
+#ifndef __QERTABLENAME
+#define __QERTABLENAME g_FuncTable
+#endif
+#define CSG_MakeHollow __QERTABLENAME.m_pfnCSG_MakeHollow
+#define Sys_Beep __QERTABLENAME.m_pfnSysBeep
+#define Sys_Printf __QERTABLENAME.m_pfnSysPrintf
+#define Sys_FPrintf __QERTABLENAME.m_pfnSysFPrintf
+#define Sys_BeginWait __QERTABLENAME.m_pfnSysBeginWait
+#define Sys_EndWait __QERTABLENAME.m_pfnSysEndWait
+#define Sys_UpdateWindows __QERTABLENAME.m_pfnSysUpdateWindows
+#define Sys_SetTitle __QERTABLENAME.m_pfnSys_SetTitle
+#define Sys_Status __QERTABLENAME.m_pfnSys_Status
+#define Select_Deselect __QERTABLENAME.m_pfnDeselectAllBrushes
+#define Map_New __QERTABLENAME.m_pfnMapNew
+#define Map_Free __QERTABLENAME.m_pfnMapFree
+#define Map_IsBrushFiltered __QERTABLENAME.m_pfnMap_IsBrushFiltered
+#define Map_BuildBrushData __QERTABLENAME.m_pfnMapBuildBrushData
+#define Map_StartPosition __QERTABLENAME.m_pfnMapStartPosition
+#define Map_RegionOff __QERTABLENAME.m_pfnMapRegionOff
+#define QE_ConvertDOSToUnixName __QERTABLENAME.m_pfnQE_ConvertDOSToUnixName
+#define SetBuildWindingsNoTexBuild __QERTABLENAME.m_pfnSetBuildWindingsNoTexBuild
+//#define SaveAsDialog __QERTABLENAME.m_pfnSaveAsDialog
+#define Pointfile_Clear __QERTABLENAME.m_pfnPointFileClear
+#define SetScreenUpdate __QERTABLENAME.m_pfnSetScreenUpdate
+#define Region_SpawnPoint __QERTABLENAME.m_pfnRegionSpawnPoint
+#define QGetTickCount __QERTABLENAME.m_pfnGetTickCount
+#define GetModelCache __QERTABLENAME.m_pfnGetModelCache
+#define GetFileTypeRegistry __QERTABLENAME.m_pfnGetFileTypeRegistry
+#else
+IFileTypeRegistry* GetFileTypeRegistry();
+#endif
+
+#endif
diff --git a/include/qertypes.h b/include/qertypes.h
index 0c6ebbdb..ad785cfe 100644
--- a/include/qertypes.h
+++ b/include/qertypes.h
@@ -1,911 +1,911 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// qertypes.h
-//
-// common types
-// merged from brush.h, etc. for plugin support
-//
-#ifndef _QERTYPES_H_
-#define _QERTYPES_H_
-
-#ifdef _WIN32
-#include <wtypes.h>
-#endif
-
-#include <GL/gl.h>
-
-#include "str.h"
-
-#ifdef _WIN32
-#define PATH_MAX 260
-#endif
-
-// HACK glib-2.0
-#define NAME_MAX 255
-
-typedef bool qboolean;
-
-#define	MAXPOINTS	16
-
-// merged from qedefs.h ------
-
-#define	MAX_EDGES	512
-#define	MAX_POINTS	1024
-
-#define	COLOR_TEXTUREBACK	  0
-#define	COLOR_GRIDBACK		  1
-#define	COLOR_GRIDMINOR		  2
-#define	COLOR_GRIDMAJOR		  3
-#define	COLOR_CAMERABACK	  4
-#define COLOR_ENTITY        5
-#define COLOR_GRIDBLOCK     6
-#define COLOR_GRIDTEXT      7
-#define COLOR_BRUSHES       8
-#define COLOR_SELBRUSHES    9
-#define COLOR_CLIPPER       10
-#define COLOR_VIEWNAME      11
-#define COLOR_SELBRUSHES3D  12
-
-#define COLOR_GRIDMINOR_ALT 13
-#define COLOR_GRIDMAJOR_ALT 14
-
-#define COLOR_LAST          15
-
-// ----------------------------
-
-typedef float vec_t;
-typedef vec_t vec3_t[3];
-
-// turn this on/off to use a static texdef or a memory one
-// THIS MUST BE CONSISTENT throughout a whole build of Radiant / modules / plugins
-// DO_TEXDEF_ALLOC is more memory efficient, but I suspect it to be wacky on win32 / C runtime etc.
-#define DO_TEXDEF_ALLOC 1
-#if DO_TEXDEF_ALLOC
-
-class texdef_t
-{
-private:
-  char *name;
-public:
-  texdef_t()
-  {
-    name = new char[1];
-    name[0] = '\0';
-    shift[0] = 0.0f;
-    shift[1] = 0.0f;
-    rotate = 0.0f;
-    scale[0] = 1.0f;
-    scale[1] = 1.0f;
-    contents = 0;
-    flags = 0;
-    value = 0;
-  }
-  texdef_t(const texdef_t& other)
-  {
-    name = NULL;
-    SetName(other.name);
-    shift[0] = other.shift[0];
-    shift[1] = other.shift[1];
-    rotate = other.rotate;
-    scale[0] = other.scale[0];
-    scale[1] = other.scale[1];
-    contents = other.contents;
-    flags = other.flags;
-    value = other.value;
-  }
-  ~texdef_t()
-  {
-    if (name)
-    {
-      delete []name;
-      name = (char*)NULL;
-    }
-  }
-
-  void SetName(const char *p)
-  {
-    if (name)
-    {
-      delete []name;
-      name = NULL;
-    }
-    if (p)
-    {
-      name = strcpy(new char[strlen(p)+1], p);
-    }
-    else
-    {
-      name = new char[1];
-      name[0] = '\0';
-    }
-  }
-
-  const char * GetName() const
-  {
-    return name;
-  }
-
-  // NOTE TTimo when loading prefs as binary, we load a bogus value in texdef..
-  void DropName()
-  {
-    name = NULL;
-    SetName(NULL);
-  }
-
-  texdef_t& operator =(const texdef_t& rhs)
-  {
-    if (&rhs != this)
-    {
-      SetName(rhs.name);
-      shift[0] = rhs.shift[0];
-      shift[1] = rhs.shift[1];
-      rotate = rhs.rotate;
-      scale[0] = rhs.scale[0];
-      scale[1] = rhs.scale[1];
-      contents = rhs.contents;
-      flags = rhs.flags;
-      value = rhs.value;
-    }
-    return *this;
-  }
-	float	shift[2];
-	float	rotate;
-	float	scale[2];
-	int		contents;
-	int		flags;
-	int		value;
-};
-
-#else
-
-// max length of a vfs texture path
-#define QPATH 64
-class texdef_t
-{
-private:
-  char name[QPATH];
-public:
-  texdef_t() { name[0] = '\0'; }
-  ~texdef_t() {  }
-
-  void SetName(const char *p)
-  {
-    strncpy(name, p, QPATH);
-  }
-
-  const char * GetName() const
-  {
-    return name;
-  }
-
-  // NOTE TTimo when loading prefs as binary, we load a bogus value in texdef..
-  void DropName()
-  {
-    name[0] = '\0';
-  }
-
-  texdef_t& operator =(const texdef_t& rhs)
-  {
-    if (&rhs != this)
-    {
-      SetName(rhs.name);
-      shift[0] = rhs.shift[0];
-      shift[1] = rhs.shift[1];
-      rotate = rhs.rotate;
-      scale[0] = rhs.scale[0];
-      scale[1] = rhs.scale[1];
-      contents = rhs.contents;
-      flags = rhs.flags;
-      value = rhs.value;
-    }
-    return *this;
-  }
-	float	shift[2];
-	float	rotate;
-	float	scale[2];
-	int		contents;
-	int		flags;
-	int		value;
-};
-
-#endif
-
-// forward declare
-class IShader;
-
-// Timo
-// new brush primitive texdef
-typedef struct brushprimit_texdef_s
-{
-	vec_t	coords[2][3];
-} brushprimit_texdef_t;
-
-// this structure is used in Radiant to reflect the state of the texture window
-// it gives information on current shader and various flags
-class texturewin_t
-{
-public:
-  texturewin_t()
-  {
-  }
-  ~texturewin_t()
-  {
-  }
-	int			width, height;
-	int			originy;
-	// add brushprimit_texdef_t for brush primitive coordinates storage
-	brushprimit_texdef_t	brushprimit_texdef;
-	int m_nTotalHeight;
-	// surface plugin, must be casted to a IPluginTexdef*
-	void* pTexdef;
-	texdef_t	texdef;
- 	// shader
- 	// NOTE: never NULL, initialized in Texture_Init
- 	// NOTE: the reference name of the shader is texdef.name (see QERApp_ReloadShaders for an example)
- 	IShader *pShader;
-};
-
-#define QER_TRANS     0x00000001
-#define QER_NOCARVE   0x00000002
-#define QER_NODRAW    0x00000004
-#define QER_NONSOLID  0x00000008
-#define QER_WATER     0x00000010
-#define QER_LAVA      0x00000020
-#define QER_FOG       0x00000040
-#define QER_ALPHAFUNC 0x00000080
-#define QER_CULL      0x00000100
-
-
-// describes a GL texture that Radiant uses to represent a shader
-// NOTE: all qtexture_t are stored in a main list at g_qeglobals.d_qtextures
-// shaders have reference couting, but qtexture_t don't (they're way too deep into Radiant)
-typedef struct qtexture_s
-{
-  struct	qtexture_s *next;
-  // name of the texture file (the physical image file we are using)
-  // NOTE: used for lookup, must be unique .. vfs path of the texture, lowercase, NO FILE EXTENSION
-  // ex textures/gothic_wall/iron
-  // NOTE: the "textures/" prefix might seem unnecessary .. but it's better to stick to the vfs name
-  char		  name[64];
-  int		    width,  height;
-  GLuint		texture_number;	// gl bind number (the qtexture_t are usually loaded and binded by the shaders module)
-  vec3_t		color;			    // for flat shade mode
-  qboolean	inuse;				  // true = is present on the level (for the texture browser interface)
-} qtexture_t;
-
-// NOTE: don't trust this definition!
-// you should read float points[..][5]
-// see NewWinding definition
-// WARNING: don't touch anything to this struct unless you looked into winding.cpp and WINDING_SIZE(pt)
-#define MAX_POINTS_ON_WINDING 64
-typedef struct
-{
-  int		numpoints;
-  int		maxpoints;
-  float 	points[8][5];			// variable sized
-} winding_t;
-
-typedef struct
-{
-  vec3_t	normal;
-  double	dist;
-  int		type;
-} plane_t;
-
-// pShader is a shortcut to the shader
-// it's only up-to-date after a Brush_Build call
-// to initialize the pShader, use QERApp_Shader_ForName(texdef.name)
-typedef struct face_s
-{
-	struct face_s			*next;
-	struct face_s			*prev;
-	struct face_s			*original;		//used for vertex movement
-	vec3_t					planepts[3];
-	texdef_t				texdef;
-	plane_t					plane;
-	
-	// Nurail: Face Undo
-	int				undoId;
-	int				redoId;
-
-	winding_t				*face_winding;
-
-	vec3_t					d_color;
-  vec_t           d_shade;
-  // calls through here have indirections (pure virtual)
-  // it would be good if the rendering loop would avoid scanning there (for the GL binding number for example)
-	IShader					*pShader;
-	//++timo FIXME: remove!
-	qtexture_t				*d_texture;
-
-	// Timo new brush primit texdef
-	brushprimit_texdef_t	brushprimit_texdef;
-
-	// cast this one to an IPluginTexdef if you are using it
-	// NOTE: casting can be done with a GETPLUGINTEXDEF defined in isurfaceplugin.h
-	// TODO: if the __ISURFACEPLUGIN_H_ header is used, use a union { void *pData; IPluginTexdef *pPluginTexdef } kind of thing ?
-	void					*pData;
-} face_t;
-
-typedef struct {
-  vec3_t	xyz;
-  float	sideST[2];
-  float	capST[2];
-} curveVertex_t;
-
-typedef struct {
-  curveVertex_t	v[2];
-} sideVertex_t;
-
-
-#define	MIN_PATCH_WIDTH		3
-#define	MIN_PATCH_HEIGHT 	3
-
-#define	MAX_PATCH_WIDTH		16
-#define	MAX_PATCH_HEIGHT	16
-
-// patch type info
-// type in lower 16 bits, flags in upper
-// endcaps directly follow this patch in the list
-
-// types
-#define PATCH_GENERIC     0x00000000    // generic flat patch
-#define PATCH_CYLINDER    0x00000001    // cylinder
-#define PATCH_BEVEL       0x00000002    // bevel
-#define PATCH_ENDCAP      0x00000004    // endcap
-#define PATCH_HEMISPHERE  0x00000008    // hemisphere
-#define PATCH_CONE        0x00000010    // cone
-#define PATCH_TRIANGLE    0x00000020    // simple tri, assumes 3x3 patch
-
-// behaviour styles
-#define PATCH_CAP         0x00001000    // flat patch applied as a cap
-#define PATCH_SEAM        0x00002000    // flat patch applied as a seam
-#define PATCH_THICK       0x00004000    // patch applied as a thick portion
-
-// styles
-#define PATCH_BEZIER      0x00000000    // default bezier
-#define PATCH_BSPLINE     0x10000000    // bspline
-
-#define PATCH_TYPEMASK     0x00000fff    // 
-#define PATCH_BTYPEMASK    0x0000f000    // 
-#define PATCH_STYLEMASK    0xffff0000    // 
-
-typedef struct {
-  vec3_t	xyz;
-  float		st[2];
-  float		lightmap[2];
-  vec3_t	normal;
-} drawVert_t;
-
-// spog - used for patch LOD trees
-
-struct BTNode_t
-{
-	BTNode_t *left, *right;
-	drawVert_t info;
-	drawVert_t vMid;
-};
-
-struct BTreeList_t
-{
-	BTreeList_t *next;
-	BTNode_t *pBT;
-	drawVert_t vLeft, vRight;
-};
-
-struct BTListList_t
-{
-	BTListList_t *next;
-	BTreeList_t *list;
-};
-
-// used in brush primitive AND entities
-typedef struct epair_s
-{
-  struct epair_s	*next;
-  char	*key;
-  char	*value;
-} epair_t;
-
-struct brush_s;
-typedef struct brush_s brush_t;
-
-typedef struct {
-  int	width, height;		// in control points, not patches
-  int   contents, flags, value, type;
-  qtexture_t  *d_texture;
-  IShader     *pShader;
-  drawVert_t ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
-  brush_t *pSymbiot;
-  qboolean bSelected;
-  qboolean bOverlay;
-  qboolean bDirty;
-  int  nListID;
-  epair_t *epairs;
-  // cast this one to an IPluginTexdef if you are using it
-  // NOTE: casting can be done with a GETPLUGINTEXDEF defined in isurfaceplugin.h
-  // TODO: if the __ISURFACEPLUGIN_H_ header is used, use a union { void *pData; IPluginTexdef *pPluginTexdef } kind of thing ?
-  void					*pData;
-  // spog - curve LOD binary trees and lists
-  BTNode_t *rowLOD[((MAX_PATCH_WIDTH-1)/2) * MAX_PATCH_HEIGHT]; // = ((MAX_PATCH_WIDTH-1)/2) * MAX_PATCH_HEIGHT
-  BTNode_t *colLOD[((MAX_PATCH_HEIGHT-1)/2) * MAX_PATCH_WIDTH]; // = ((MAX_PATCH_HEIGHT-1)/2) * MAX_PATCH_WIDTH
-  bool rowDirty[((MAX_PATCH_WIDTH-1)-1)/2];
-  bool colDirty[((MAX_PATCH_HEIGHT-1)-1)/2];
-  bool LODUpdated;
-  void *drawLists; // pointer to std::list
-} patchMesh_t;
-
-typedef struct brush_s
-{
-  struct brush_s	*prev, *next;	// links in active/selected
-  struct brush_s	*oprev, *onext;	// links in entity
-  struct entity_s	*owner;
-  vec3_t	        mins, maxs;
-  face_t                *brush_faces;
-
-  qboolean bModelFailed;
-  //
-  // curve brush extensions
-  // all are derived from brush_faces
-  qboolean	patchBrush;
-  qboolean	hiddenBrush;
-  
-  //int nPatchID;
-
-  patchMesh_t *pPatch;
-  struct entity_s *pUndoOwner;
-
-  int undoId;						//undo ID
-  int redoId;						//redo ID
-  int ownerId;					//entityId of the owner entity for undo
-
-  // TTimo: this is not legal, we are not supposed to put UI toolkit dependant stuff in the interfaces
-  // NOTE: the grouping stuff never worked, there is embryonary code everywhere though
-  int numberId;
-  void* itemOwner; // GtkCTreeNode* ?
-
-  // brush primitive only
-  epair_t *epairs;
-
-  // brush filtered toggle
-  bool bFiltered;
-  bool bCamCulled;
-  bool bBrushDef;
-} brush_t;
-
-#define	MAX_FLAGS	16
-
-typedef struct vertmodel_t
-{
-  float v[3];
-  float st[2];
-  float normal[3];
-} vertmodel;
-
-typedef struct triindex_t
-{
-  int indexes[3];
-} triindex;
-
-// TTimo: NOTE: we don't have dedicated stuff to copy/allocate/delete this structure like we do for entity_t and brush_t
-//   could be necessary, I'm adding GString *strSkin that needs to be copied around
-// TTimo 04/01/2001 removing the GString* for toolkit-independent interfaces .. cast it ..
-typedef struct entitymodel_t
-{
-  struct entitymodel_t *pNext;
-  int nTriCount;
-  //trimodel *pTriList;
-  //md3Triangle_t *pTriList;
-  triindex *pTriList;
-  vertmodel *pVertList;
-  int numVerts;
-  int nTextureBind;
-  void *strSkin; // toolkit-independent .. cast to a GString*
-  int nSkinWidth;
-  int nSkinHeight;
-  int	nModelPosition;
-} entitymodel;
-
-// eclass show flags
-
-#define     ECLASS_LIGHT      0x00000001
-#define     ECLASS_ANGLE      0x00000002
-#define     ECLASS_PATH       0x00000004
-#define     ECLASS_MISCMODEL  0x00000008
-
-#ifdef USEPLUGINENTITIES
-#define		ECLASS_PLUGINENTITY 0x00000010
-#endif // USEPLUGINENTITIES
-
-typedef struct eclass_s
-{
-	struct eclass_s *next;
-	char	*name;
-	qboolean	fixedsize;
-	qboolean	unknown;		// wasn't found in source
-	vec3_t	mins, maxs;
-	vec3_t	color;
-	texdef_t	texdef;
-	char	*comments;
-	char	flagnames[MAX_FLAGS][32];
-
-  entitymodel *model;
-  char	*modelpath;
-  //++timo NOTE: I don't know what this is used for exactly. But don't trust it for the real skin paths on models (screws up with long/short path names)
-  //++hydra NOTE: this, hopefully, will be used to use specific shaders on the bounding boxes of the eclass instead of a color.
-  char	*skinpath;
-  int   nFrame;
-  unsigned int nShowFlags;
-
-  void*	hPlug;
-} eclass_t;
-
-extern	eclass_t	*eclass;
-
-/*
-** window bits
-*/
-#define	W_CAMERA		  0x0001
-#define	W_XY			    0x0002
-#define	W_XY_OVERLAY	0x0004
-#define	W_Z				    0x0008
-#define	W_TEXTURE		  0x0010
-#define	W_Z_OVERLAY		0x0020
-#define W_CONSOLE		  0x0040
-#define W_ENTITY		  0x0080
-#define W_CAMERA_IFON 0x0100
-#define W_XZ          0x0200  //--| only used for patch vertex manip stuff
-#define W_YZ          0x0400  //--|
-#define W_GROUP       0x0800 
-#define W_MEDIA       0x1000 
-#define	W_ALL			0xFFFFFFFF
-
-// used in some Drawing routines
-enum VIEWTYPE {YZ, XZ, XY};
-const char g_AxisName[3] = { 'X', 'Y', 'Z' };
-
-// dynamically allocated string
-class string_t
-{
-public:
-  inline string_t()
-  {
-    copy("");
-  }
-  inline string_t(const string_t& other)
-  {
-    copy(other.m_string);
-  }
-  inline string_t(const char* string)
-  {
-    copy(string);
-  }
-  inline ~string_t()
-  {
-    destroy();
-  }
-  inline const string_t& operator=(const string_t& other)
-  {
-    destroy();
-    copy(other.m_string);
-    return *this;
-  }
-  inline const string_t& operator=(const char* string)
-  {
-    destroy();
-    copy(string);
-    return *this;
-  }
-  inline bool operator<(const string_t& other) const
-  {
-    return compare(other) < 0;
-  }
-  inline bool operator>(const string_t& other) const
-  {
-    return compare(other) > 0;
-  }
-  inline bool operator==(const string_t& other) const
-  {
-    return compare(other) == 0;
-  }
-  inline bool operator!=(const string_t& other) const
-  {
-    return compare(other) != 0;
-  }
-  inline const char* c_str() const
-  {
-    return m_string;
-  }
-private:
-  inline void copy(const char* string)
-  {
-    m_string = new char[strlen(string)+1];
-    strcpy(m_string, string);
-  }
-  inline void destroy()
-  {
-    delete[] m_string;
-  }
-  inline int compare(const string_t& other) const
-  {
-    return strcmp(m_string, other.m_string);
-  }
-
-  char* m_string;
-};
-
-class filetype_t
-{
-public:
-  filetype_t()
-    : name(""), pattern("")
-  {}
-  filetype_t(const char* _name, const char* _pattern)
-    : name(_name), pattern(_pattern)
-  {}
-  const char* name;
-  const char* pattern;
-};
-
-
-/*
-** Outline bits
-*/
-#define OUTLINE_ZBUF  0x01  // zbuffered outline
-#define OUTLINE_BSEL  0x02  // selection overlay
-
-#ifdef USEPLUGINENTITIES
-// forward declare this one
-class IPluginEntity;
-#endif // USEPLUGINENTITIES
-
-// MODEL
-
-class IRender;
-class ISelect;
-class IEdit;
-
-// NOTE TTimo about ~entity_interfaces_t
-// using constructors / destructors on C structs is bad practice
-struct entity_interfaces_t
-{
-  IRender *pRender;
-  ISelect *pSelect;
-  IEdit *pEdit;
-};
-// MODEL END
-   
-typedef struct entity_s
-{
-  struct entity_s	*prev, *next;
-
-  /*!
-  \todo can use a brushes list, or the blind data below
-  for now, blind data should be interpreted as CPtrArray*, only use in the IMAP API
-  */
-  brush_t		brushes;					// head/tail of list
-  void *pData;
-
-  int			undoId, redoId, entityId;	// used for undo/redo
-  vec3_t		origin;
-  eclass_t	*eclass;
-  epair_t		*epairs;
-  entity_interfaces_t model;
-#ifdef USEPLUGINENTITIES
-  IPluginEntity *pPlugEnt;
-#endif // USEPLUGINENTITIES
-
-  // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=252
-  // this is cam code addition?
-  vec3_t color;
-
-	// Arnout: HACK-ish and change for 1.3 (in 1.3 we have a blind data pointer according to TTimo)
-	float fLightEnvelope1[3];
-	float fLightEnvelope2[2];
-} entity_t;
-
-typedef struct
-{
-  int	   p1, p2;
-  face_t   *f1, *f2;
-} pedge_t;
-
-// window system independent camera view code
-// NOTE TTimo taken from xy.h
-typedef struct
-{
-  int	    width, height;
-
-  qboolean  timing;
-
-  vec3_t    origin;  // at center of window
-  float	    scale;
-
-  float	    topclip, bottomclip;
-
-  qboolean  d_dirty;
-} xy_t;
-
-// spog - struct used for nodes in filters list
-struct bfilter_t //c++ style
-{
-	bfilter_t	*next;
-	int		attribute;		// 1=brush->face->pShader->getName()
-							// 2=brush->pPatch->pShader->getFlags()
-							// 3=brush->owner->eclass->name
-							// 4=brush->owner->eclass->nShowFlags
-	int		mask;
-	char	*string;
-	bool	active;
-};
-
-// djbob: no longer any need to add only to end, versioning removed, it is no longer saved as binary
-// IMPORTANT: whenever you update this struct, you need to add the relevant load/save code
-// preferences.cpp LoadPref / SavePref
-typedef struct
-{
-  int	      iTexMenu;		// nearest, linear, etc
-  float	    fGamma;		  // gamma for textures
-  vec3_t    colors[COLOR_LAST];
-  int       exclude;
-  int       include;
-  texdef_t  m_SIIncrement;  // increments for the surface inspector
-  texdef_t  m_PIIncrement;  // increments for the patch inspector
-  vec3_t    AxisColors[3];  // colors used for X, Y Z axis
-                            // these are in the View > Show menu with Show coordinates
-  qboolean  show_names;
-  qboolean  show_coordinates;
-  qboolean  show_angles;
-  qboolean  show_outline;
-  qboolean  show_axis;
-  qboolean  bNoSelectedOutlines;
-  bfilter_t	*filters; // FIXME spog - might be better in another location?
-  int       iSelectedOutlinesStyle;
-} SavedInfo_t;
-
-typedef enum
-{
-  sel_brush,
-  sel_brush_on,
-  sel_brush_off,
-  // sel_sticky_brush,
-  // sel_face,
-  sel_vertex,
-  sel_edge,
-  sel_singlevertex,
-  sel_curvepoint,
-  sel_area,
-  sel_areatall,
-  sel_facets_on,
-  sel_facets_off,
-} select_t;
-
-// most of the QE globals are stored in this structure
-typedef struct
-{
-  qboolean  d_showgrid;
-  float     d_gridsize;
-  qboolean  d_bSmallGrid; // we use this flag to hack our way into editing of <1 grids
-	
-  int      d_num_entities;
-	
-  entity_t *d_project_entity;
-
-  // defines the boundaries of the current work area
-  // is used to guess brushes and drop points third coordinate when creating from 2D view
-  vec3_t    d_work_min,d_work_max;
-  // not stored in registry, default is off
-  qboolean	d_show_work;
-
-  vec3_t       d_points[MAX_POINTS];
-  int          d_numpoints;
-  pedge_t      d_edges[MAX_EDGES];
-  int          d_numedges;
-
-  int          d_num_move_points;
-  float        *d_move_points[4096];
-
-  qtexture_t   *d_qtextures;
-  // used to speedup access, specially in QERApp_Try_Texture_ForName
-  // must always be kept up-to-date with d_qtextures*
-  //++timo FIXME at some point in the future it would even be better to remove d_qtextures and use this instead
-  GHashTable *d_qtexmap;
-
-  texturewin_t d_texturewin;
-
-  int	       d_pointfile_display_list;
-
-  xy_t         d_xyOld;
-
-  SavedInfo_t  d_savedinfo;
-	
-  int          d_workcount;
-	
-  // connect entities uses the last two brushes selected
-  int	         d_select_count;
-  brush_t      *d_select_order[2];
-  vec3_t       d_select_translate;    // for dragging w/o making new display lists
-  select_t     d_select_mode;
-	
-  int          d_parsed_brushes;
-	
-  qboolean     show_blocks;
-  int		       blockSize;
-
-  // NOTE TTimo
-  // a lot of this data should be in a property bag and available to the other modules through an API
-  // this is generated from game configuration and the project settings, and should be still be part of it
-	
-  // tells if we are internally using brush primitive (texture coordinates and map format)
-  // this is a shortcut for IntForKey( g_qeglobals.d_project_entity, "brush_primit" )
-  // NOTE: must keep the two ones in sync
-  bool         m_bBrushPrimitMode;
-
-  /*!
-  win32: engine full path.
-  unix: user home full path + engine dir.
-  */
-  Str         m_strHomeGame;
-  /*!
-  cache for m_strHomeGame + mod subdirectory.
-  */
-  Str         m_strHomeMaps;
-
-  // used while importing brush data from file or memory buffer
-  // tells if conversion between map format and internal preferences ( m_bBrushPrimitMode ) is needed
-  qboolean     bNeedConvert;
-  qboolean     bOldBrushes;
-  qboolean     bPrimitBrushes;
-	
-  vec3_t       d_vAreaTL;
-  vec3_t       d_vAreaBR;
-	
-  // tells if we are using .INI files for prefs instead of registry
-  qboolean	use_ini;
-  // even in .INI mode we use the registry for all void* prefs
-  char		use_ini_registry[64];
-  // disabled all INI / registry read write .. used when shutting down after registry cleanup
-  qboolean disable_ini;
-	
-  // tells we are using a BSP frontend plugin
-  qboolean	bBSPFrontendPlugin;
-
-  // handle to the console log file
-  // we use low level I/O to get rid of buffering and have everything on file if we crash
-  int hLogFile;
-
-  qboolean bTextureCompressionSupported; // is texture compression supported by hardware?
-  GLint texture_components;
-
-  // temporary values that should be initialised only once at run-time
-  // there are too many uneccessary calls to Sys_QGL_ExtensionSupported
-  // NOTE TTimo: those are unused atm (set right, but not used)
-  // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=623
-  bool m_bOpenGLCompressionSupported;
-  bool m_bS3CompressionSupported;
-  
-  // set to true after OpenGL has been initialized and extensions have been tested
-  bool m_bOpenGLReady;
-
-} QEGlobals_t;
-
-#endif // _QERTYPES_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// qertypes.h
+//
+// common types
+// merged from brush.h, etc. for plugin support
+//
+#ifndef _QERTYPES_H_
+#define _QERTYPES_H_
+
+#ifdef _WIN32
+#include <wtypes.h>
+#endif
+
+#include <GL/gl.h>
+
+#include "str.h"
+
+#ifdef _WIN32
+#define PATH_MAX 260
+#endif
+
+// HACK glib-2.0
+#define NAME_MAX 255
+
+typedef bool qboolean;
+
+#define	MAXPOINTS	16
+
+// merged from qedefs.h ------
+
+#define	MAX_EDGES	512
+#define	MAX_POINTS	1024
+
+#define	COLOR_TEXTUREBACK	  0
+#define	COLOR_GRIDBACK		  1
+#define	COLOR_GRIDMINOR		  2
+#define	COLOR_GRIDMAJOR		  3
+#define	COLOR_CAMERABACK	  4
+#define COLOR_ENTITY        5
+#define COLOR_GRIDBLOCK     6
+#define COLOR_GRIDTEXT      7
+#define COLOR_BRUSHES       8
+#define COLOR_SELBRUSHES    9
+#define COLOR_CLIPPER       10
+#define COLOR_VIEWNAME      11
+#define COLOR_SELBRUSHES3D  12
+
+#define COLOR_GRIDMINOR_ALT 13
+#define COLOR_GRIDMAJOR_ALT 14
+
+#define COLOR_LAST          15
+
+// ----------------------------
+
+typedef float vec_t;
+typedef vec_t vec3_t[3];
+
+// turn this on/off to use a static texdef or a memory one
+// THIS MUST BE CONSISTENT throughout a whole build of Radiant / modules / plugins
+// DO_TEXDEF_ALLOC is more memory efficient, but I suspect it to be wacky on win32 / C runtime etc.
+#define DO_TEXDEF_ALLOC 1
+#if DO_TEXDEF_ALLOC
+
+class texdef_t
+{
+private:
+  char *name;
+public:
+  texdef_t()
+  {
+    name = new char[1];
+    name[0] = '\0';
+    shift[0] = 0.0f;
+    shift[1] = 0.0f;
+    rotate = 0.0f;
+    scale[0] = 1.0f;
+    scale[1] = 1.0f;
+    contents = 0;
+    flags = 0;
+    value = 0;
+  }
+  texdef_t(const texdef_t& other)
+  {
+    name = NULL;
+    SetName(other.name);
+    shift[0] = other.shift[0];
+    shift[1] = other.shift[1];
+    rotate = other.rotate;
+    scale[0] = other.scale[0];
+    scale[1] = other.scale[1];
+    contents = other.contents;
+    flags = other.flags;
+    value = other.value;
+  }
+  ~texdef_t()
+  {
+    if (name)
+    {
+      delete []name;
+      name = (char*)NULL;
+    }
+  }
+
+  void SetName(const char *p)
+  {
+    if (name)
+    {
+      delete []name;
+      name = NULL;
+    }
+    if (p)
+    {
+      name = strcpy(new char[strlen(p)+1], p);
+    }
+    else
+    {
+      name = new char[1];
+      name[0] = '\0';
+    }
+  }
+
+  const char * GetName() const
+  {
+    return name;
+  }
+
+  // NOTE TTimo when loading prefs as binary, we load a bogus value in texdef..
+  void DropName()
+  {
+    name = NULL;
+    SetName(NULL);
+  }
+
+  texdef_t& operator =(const texdef_t& rhs)
+  {
+    if (&rhs != this)
+    {
+      SetName(rhs.name);
+      shift[0] = rhs.shift[0];
+      shift[1] = rhs.shift[1];
+      rotate = rhs.rotate;
+      scale[0] = rhs.scale[0];
+      scale[1] = rhs.scale[1];
+      contents = rhs.contents;
+      flags = rhs.flags;
+      value = rhs.value;
+    }
+    return *this;
+  }
+	float	shift[2];
+	float	rotate;
+	float	scale[2];
+	int		contents;
+	int		flags;
+	int		value;
+};
+
+#else
+
+// max length of a vfs texture path
+#define QPATH 64
+class texdef_t
+{
+private:
+  char name[QPATH];
+public:
+  texdef_t() { name[0] = '\0'; }
+  ~texdef_t() {  }
+
+  void SetName(const char *p)
+  {
+    strncpy(name, p, QPATH);
+  }
+
+  const char * GetName() const
+  {
+    return name;
+  }
+
+  // NOTE TTimo when loading prefs as binary, we load a bogus value in texdef..
+  void DropName()
+  {
+    name[0] = '\0';
+  }
+
+  texdef_t& operator =(const texdef_t& rhs)
+  {
+    if (&rhs != this)
+    {
+      SetName(rhs.name);
+      shift[0] = rhs.shift[0];
+      shift[1] = rhs.shift[1];
+      rotate = rhs.rotate;
+      scale[0] = rhs.scale[0];
+      scale[1] = rhs.scale[1];
+      contents = rhs.contents;
+      flags = rhs.flags;
+      value = rhs.value;
+    }
+    return *this;
+  }
+	float	shift[2];
+	float	rotate;
+	float	scale[2];
+	int		contents;
+	int		flags;
+	int		value;
+};
+
+#endif
+
+// forward declare
+class IShader;
+
+// Timo
+// new brush primitive texdef
+typedef struct brushprimit_texdef_s
+{
+	vec_t	coords[2][3];
+} brushprimit_texdef_t;
+
+// this structure is used in Radiant to reflect the state of the texture window
+// it gives information on current shader and various flags
+class texturewin_t
+{
+public:
+  texturewin_t()
+  {
+  }
+  ~texturewin_t()
+  {
+  }
+	int			width, height;
+	int			originy;
+	// add brushprimit_texdef_t for brush primitive coordinates storage
+	brushprimit_texdef_t	brushprimit_texdef;
+	int m_nTotalHeight;
+	// surface plugin, must be casted to a IPluginTexdef*
+	void* pTexdef;
+	texdef_t	texdef;
+ 	// shader
+ 	// NOTE: never NULL, initialized in Texture_Init
+ 	// NOTE: the reference name of the shader is texdef.name (see QERApp_ReloadShaders for an example)
+ 	IShader *pShader;
+};
+
+#define QER_TRANS     0x00000001
+#define QER_NOCARVE   0x00000002
+#define QER_NODRAW    0x00000004
+#define QER_NONSOLID  0x00000008
+#define QER_WATER     0x00000010
+#define QER_LAVA      0x00000020
+#define QER_FOG       0x00000040
+#define QER_ALPHAFUNC 0x00000080
+#define QER_CULL      0x00000100
+
+
+// describes a GL texture that Radiant uses to represent a shader
+// NOTE: all qtexture_t are stored in a main list at g_qeglobals.d_qtextures
+// shaders have reference couting, but qtexture_t don't (they're way too deep into Radiant)
+typedef struct qtexture_s
+{
+  struct	qtexture_s *next;
+  // name of the texture file (the physical image file we are using)
+  // NOTE: used for lookup, must be unique .. vfs path of the texture, lowercase, NO FILE EXTENSION
+  // ex textures/gothic_wall/iron
+  // NOTE: the "textures/" prefix might seem unnecessary .. but it's better to stick to the vfs name
+  char		  name[64];
+  int		    width,  height;
+  GLuint		texture_number;	// gl bind number (the qtexture_t are usually loaded and binded by the shaders module)
+  vec3_t		color;			    // for flat shade mode
+  qboolean	inuse;				  // true = is present on the level (for the texture browser interface)
+} qtexture_t;
+
+// NOTE: don't trust this definition!
+// you should read float points[..][5]
+// see NewWinding definition
+// WARNING: don't touch anything to this struct unless you looked into winding.cpp and WINDING_SIZE(pt)
+#define MAX_POINTS_ON_WINDING 64
+typedef struct
+{
+  int		numpoints;
+  int		maxpoints;
+  float 	points[8][5];			// variable sized
+} winding_t;
+
+typedef struct
+{
+  vec3_t	normal;
+  double	dist;
+  int		type;
+} plane_t;
+
+// pShader is a shortcut to the shader
+// it's only up-to-date after a Brush_Build call
+// to initialize the pShader, use QERApp_Shader_ForName(texdef.name)
+typedef struct face_s
+{
+	struct face_s			*next;
+	struct face_s			*prev;
+	struct face_s			*original;		//used for vertex movement
+	vec3_t					planepts[3];
+	texdef_t				texdef;
+	plane_t					plane;
+	
+	// Nurail: Face Undo
+	int				undoId;
+	int				redoId;
+
+	winding_t				*face_winding;
+
+	vec3_t					d_color;
+  vec_t           d_shade;
+  // calls through here have indirections (pure virtual)
+  // it would be good if the rendering loop would avoid scanning there (for the GL binding number for example)
+	IShader					*pShader;
+	//++timo FIXME: remove!
+	qtexture_t				*d_texture;
+
+	// Timo new brush primit texdef
+	brushprimit_texdef_t	brushprimit_texdef;
+
+	// cast this one to an IPluginTexdef if you are using it
+	// NOTE: casting can be done with a GETPLUGINTEXDEF defined in isurfaceplugin.h
+	// TODO: if the __ISURFACEPLUGIN_H_ header is used, use a union { void *pData; IPluginTexdef *pPluginTexdef } kind of thing ?
+	void					*pData;
+} face_t;
+
+typedef struct {
+  vec3_t	xyz;
+  float	sideST[2];
+  float	capST[2];
+} curveVertex_t;
+
+typedef struct {
+  curveVertex_t	v[2];
+} sideVertex_t;
+
+
+#define	MIN_PATCH_WIDTH		3
+#define	MIN_PATCH_HEIGHT 	3
+
+#define	MAX_PATCH_WIDTH		16
+#define	MAX_PATCH_HEIGHT	16
+
+// patch type info
+// type in lower 16 bits, flags in upper
+// endcaps directly follow this patch in the list
+
+// types
+#define PATCH_GENERIC     0x00000000    // generic flat patch
+#define PATCH_CYLINDER    0x00000001    // cylinder
+#define PATCH_BEVEL       0x00000002    // bevel
+#define PATCH_ENDCAP      0x00000004    // endcap
+#define PATCH_HEMISPHERE  0x00000008    // hemisphere
+#define PATCH_CONE        0x00000010    // cone
+#define PATCH_TRIANGLE    0x00000020    // simple tri, assumes 3x3 patch
+
+// behaviour styles
+#define PATCH_CAP         0x00001000    // flat patch applied as a cap
+#define PATCH_SEAM        0x00002000    // flat patch applied as a seam
+#define PATCH_THICK       0x00004000    // patch applied as a thick portion
+
+// styles
+#define PATCH_BEZIER      0x00000000    // default bezier
+#define PATCH_BSPLINE     0x10000000    // bspline
+
+#define PATCH_TYPEMASK     0x00000fff    // 
+#define PATCH_BTYPEMASK    0x0000f000    // 
+#define PATCH_STYLEMASK    0xffff0000    // 
+
+typedef struct {
+  vec3_t	xyz;
+  float		st[2];
+  float		lightmap[2];
+  vec3_t	normal;
+} drawVert_t;
+
+// spog - used for patch LOD trees
+
+struct BTNode_t
+{
+	BTNode_t *left, *right;
+	drawVert_t info;
+	drawVert_t vMid;
+};
+
+struct BTreeList_t
+{
+	BTreeList_t *next;
+	BTNode_t *pBT;
+	drawVert_t vLeft, vRight;
+};
+
+struct BTListList_t
+{
+	BTListList_t *next;
+	BTreeList_t *list;
+};
+
+// used in brush primitive AND entities
+typedef struct epair_s
+{
+  struct epair_s	*next;
+  char	*key;
+  char	*value;
+} epair_t;
+
+struct brush_s;
+typedef struct brush_s brush_t;
+
+typedef struct {
+  int	width, height;		// in control points, not patches
+  int   contents, flags, value, type;
+  qtexture_t  *d_texture;
+  IShader     *pShader;
+  drawVert_t ctrl[MAX_PATCH_WIDTH][MAX_PATCH_HEIGHT];
+  brush_t *pSymbiot;
+  qboolean bSelected;
+  qboolean bOverlay;
+  qboolean bDirty;
+  int  nListID;
+  epair_t *epairs;
+  // cast this one to an IPluginTexdef if you are using it
+  // NOTE: casting can be done with a GETPLUGINTEXDEF defined in isurfaceplugin.h
+  // TODO: if the __ISURFACEPLUGIN_H_ header is used, use a union { void *pData; IPluginTexdef *pPluginTexdef } kind of thing ?
+  void					*pData;
+  // spog - curve LOD binary trees and lists
+  BTNode_t *rowLOD[((MAX_PATCH_WIDTH-1)/2) * MAX_PATCH_HEIGHT]; // = ((MAX_PATCH_WIDTH-1)/2) * MAX_PATCH_HEIGHT
+  BTNode_t *colLOD[((MAX_PATCH_HEIGHT-1)/2) * MAX_PATCH_WIDTH]; // = ((MAX_PATCH_HEIGHT-1)/2) * MAX_PATCH_WIDTH
+  bool rowDirty[((MAX_PATCH_WIDTH-1)-1)/2];
+  bool colDirty[((MAX_PATCH_HEIGHT-1)-1)/2];
+  bool LODUpdated;
+  void *drawLists; // pointer to std::list
+} patchMesh_t;
+
+typedef struct brush_s
+{
+  struct brush_s	*prev, *next;	// links in active/selected
+  struct brush_s	*oprev, *onext;	// links in entity
+  struct entity_s	*owner;
+  vec3_t	        mins, maxs;
+  face_t                *brush_faces;
+
+  qboolean bModelFailed;
+  //
+  // curve brush extensions
+  // all are derived from brush_faces
+  qboolean	patchBrush;
+  qboolean	hiddenBrush;
+  
+  //int nPatchID;
+
+  patchMesh_t *pPatch;
+  struct entity_s *pUndoOwner;
+
+  int undoId;						//undo ID
+  int redoId;						//redo ID
+  int ownerId;					//entityId of the owner entity for undo
+
+  // TTimo: this is not legal, we are not supposed to put UI toolkit dependant stuff in the interfaces
+  // NOTE: the grouping stuff never worked, there is embryonary code everywhere though
+  int numberId;
+  void* itemOwner; // GtkCTreeNode* ?
+
+  // brush primitive only
+  epair_t *epairs;
+
+  // brush filtered toggle
+  bool bFiltered;
+  bool bCamCulled;
+  bool bBrushDef;
+} brush_t;
+
+#define	MAX_FLAGS	16
+
+typedef struct vertmodel_t
+{
+  float v[3];
+  float st[2];
+  float normal[3];
+} vertmodel;
+
+typedef struct triindex_t
+{
+  int indexes[3];
+} triindex;
+
+// TTimo: NOTE: we don't have dedicated stuff to copy/allocate/delete this structure like we do for entity_t and brush_t
+//   could be necessary, I'm adding GString *strSkin that needs to be copied around
+// TTimo 04/01/2001 removing the GString* for toolkit-independent interfaces .. cast it ..
+typedef struct entitymodel_t
+{
+  struct entitymodel_t *pNext;
+  int nTriCount;
+  //trimodel *pTriList;
+  //md3Triangle_t *pTriList;
+  triindex *pTriList;
+  vertmodel *pVertList;
+  int numVerts;
+  int nTextureBind;
+  void *strSkin; // toolkit-independent .. cast to a GString*
+  int nSkinWidth;
+  int nSkinHeight;
+  int	nModelPosition;
+} entitymodel;
+
+// eclass show flags
+
+#define     ECLASS_LIGHT      0x00000001
+#define     ECLASS_ANGLE      0x00000002
+#define     ECLASS_PATH       0x00000004
+#define     ECLASS_MISCMODEL  0x00000008
+
+#ifdef USEPLUGINENTITIES
+#define		ECLASS_PLUGINENTITY 0x00000010
+#endif // USEPLUGINENTITIES
+
+typedef struct eclass_s
+{
+	struct eclass_s *next;
+	char	*name;
+	qboolean	fixedsize;
+	qboolean	unknown;		// wasn't found in source
+	vec3_t	mins, maxs;
+	vec3_t	color;
+	texdef_t	texdef;
+	char	*comments;
+	char	flagnames[MAX_FLAGS][32];
+
+  entitymodel *model;
+  char	*modelpath;
+  //++timo NOTE: I don't know what this is used for exactly. But don't trust it for the real skin paths on models (screws up with long/short path names)
+  //++hydra NOTE: this, hopefully, will be used to use specific shaders on the bounding boxes of the eclass instead of a color.
+  char	*skinpath;
+  int   nFrame;
+  unsigned int nShowFlags;
+
+  void*	hPlug;
+} eclass_t;
+
+extern	eclass_t	*eclass;
+
+/*
+** window bits
+*/
+#define	W_CAMERA		  0x0001
+#define	W_XY			    0x0002
+#define	W_XY_OVERLAY	0x0004
+#define	W_Z				    0x0008
+#define	W_TEXTURE		  0x0010
+#define	W_Z_OVERLAY		0x0020
+#define W_CONSOLE		  0x0040
+#define W_ENTITY		  0x0080
+#define W_CAMERA_IFON 0x0100
+#define W_XZ          0x0200  //--| only used for patch vertex manip stuff
+#define W_YZ          0x0400  //--|
+#define W_GROUP       0x0800 
+#define W_MEDIA       0x1000 
+#define	W_ALL			0xFFFFFFFF
+
+// used in some Drawing routines
+enum VIEWTYPE {YZ, XZ, XY};
+const char g_AxisName[3] = { 'X', 'Y', 'Z' };
+
+// dynamically allocated string
+class string_t
+{
+public:
+  inline string_t()
+  {
+    copy("");
+  }
+  inline string_t(const string_t& other)
+  {
+    copy(other.m_string);
+  }
+  inline string_t(const char* string)
+  {
+    copy(string);
+  }
+  inline ~string_t()
+  {
+    destroy();
+  }
+  inline const string_t& operator=(const string_t& other)
+  {
+    destroy();
+    copy(other.m_string);
+    return *this;
+  }
+  inline const string_t& operator=(const char* string)
+  {
+    destroy();
+    copy(string);
+    return *this;
+  }
+  inline bool operator<(const string_t& other) const
+  {
+    return compare(other) < 0;
+  }
+  inline bool operator>(const string_t& other) const
+  {
+    return compare(other) > 0;
+  }
+  inline bool operator==(const string_t& other) const
+  {
+    return compare(other) == 0;
+  }
+  inline bool operator!=(const string_t& other) const
+  {
+    return compare(other) != 0;
+  }
+  inline const char* c_str() const
+  {
+    return m_string;
+  }
+private:
+  inline void copy(const char* string)
+  {
+    m_string = new char[strlen(string)+1];
+    strcpy(m_string, string);
+  }
+  inline void destroy()
+  {
+    delete[] m_string;
+  }
+  inline int compare(const string_t& other) const
+  {
+    return strcmp(m_string, other.m_string);
+  }
+
+  char* m_string;
+};
+
+class filetype_t
+{
+public:
+  filetype_t()
+    : name(""), pattern("")
+  {}
+  filetype_t(const char* _name, const char* _pattern)
+    : name(_name), pattern(_pattern)
+  {}
+  const char* name;
+  const char* pattern;
+};
+
+
+/*
+** Outline bits
+*/
+#define OUTLINE_ZBUF  0x01  // zbuffered outline
+#define OUTLINE_BSEL  0x02  // selection overlay
+
+#ifdef USEPLUGINENTITIES
+// forward declare this one
+class IPluginEntity;
+#endif // USEPLUGINENTITIES
+
+// MODEL
+
+class IRender;
+class ISelect;
+class IEdit;
+
+// NOTE TTimo about ~entity_interfaces_t
+// using constructors / destructors on C structs is bad practice
+struct entity_interfaces_t
+{
+  IRender *pRender;
+  ISelect *pSelect;
+  IEdit *pEdit;
+};
+// MODEL END
+   
+typedef struct entity_s
+{
+  struct entity_s	*prev, *next;
+
+  /*!
+  \todo can use a brushes list, or the blind data below
+  for now, blind data should be interpreted as CPtrArray*, only use in the IMAP API
+  */
+  brush_t		brushes;					// head/tail of list
+  void *pData;
+
+  int			undoId, redoId, entityId;	// used for undo/redo
+  vec3_t		origin;
+  eclass_t	*eclass;
+  epair_t		*epairs;
+  entity_interfaces_t model;
+#ifdef USEPLUGINENTITIES
+  IPluginEntity *pPlugEnt;
+#endif // USEPLUGINENTITIES
+
+  // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=252
+  // this is cam code addition?
+  vec3_t color;
+
+	// Arnout: HACK-ish and change for 1.3 (in 1.3 we have a blind data pointer according to TTimo)
+	float fLightEnvelope1[3];
+	float fLightEnvelope2[2];
+} entity_t;
+
+typedef struct
+{
+  int	   p1, p2;
+  face_t   *f1, *f2;
+} pedge_t;
+
+// window system independent camera view code
+// NOTE TTimo taken from xy.h
+typedef struct
+{
+  int	    width, height;
+
+  qboolean  timing;
+
+  vec3_t    origin;  // at center of window
+  float	    scale;
+
+  float	    topclip, bottomclip;
+
+  qboolean  d_dirty;
+} xy_t;
+
+// spog - struct used for nodes in filters list
+struct bfilter_t //c++ style
+{
+	bfilter_t	*next;
+	int		attribute;		// 1=brush->face->pShader->getName()
+							// 2=brush->pPatch->pShader->getFlags()
+							// 3=brush->owner->eclass->name
+							// 4=brush->owner->eclass->nShowFlags
+	int		mask;
+	char	*string;
+	bool	active;
+};
+
+// djbob: no longer any need to add only to end, versioning removed, it is no longer saved as binary
+// IMPORTANT: whenever you update this struct, you need to add the relevant load/save code
+// preferences.cpp LoadPref / SavePref
+typedef struct
+{
+  int	      iTexMenu;		// nearest, linear, etc
+  float	    fGamma;		  // gamma for textures
+  vec3_t    colors[COLOR_LAST];
+  int       exclude;
+  int       include;
+  texdef_t  m_SIIncrement;  // increments for the surface inspector
+  texdef_t  m_PIIncrement;  // increments for the patch inspector
+  vec3_t    AxisColors[3];  // colors used for X, Y Z axis
+                            // these are in the View > Show menu with Show coordinates
+  qboolean  show_names;
+  qboolean  show_coordinates;
+  qboolean  show_angles;
+  qboolean  show_outline;
+  qboolean  show_axis;
+  qboolean  bNoSelectedOutlines;
+  bfilter_t	*filters; // FIXME spog - might be better in another location?
+  int       iSelectedOutlinesStyle;
+} SavedInfo_t;
+
+typedef enum
+{
+  sel_brush,
+  sel_brush_on,
+  sel_brush_off,
+  // sel_sticky_brush,
+  // sel_face,
+  sel_vertex,
+  sel_edge,
+  sel_singlevertex,
+  sel_curvepoint,
+  sel_area,
+  sel_areatall,
+  sel_facets_on,
+  sel_facets_off,
+} select_t;
+
+// most of the QE globals are stored in this structure
+typedef struct
+{
+  qboolean  d_showgrid;
+  float     d_gridsize;
+  qboolean  d_bSmallGrid; // we use this flag to hack our way into editing of <1 grids
+	
+  int      d_num_entities;
+	
+  entity_t *d_project_entity;
+
+  // defines the boundaries of the current work area
+  // is used to guess brushes and drop points third coordinate when creating from 2D view
+  vec3_t    d_work_min,d_work_max;
+  // not stored in registry, default is off
+  qboolean	d_show_work;
+
+  vec3_t       d_points[MAX_POINTS];
+  int          d_numpoints;
+  pedge_t      d_edges[MAX_EDGES];
+  int          d_numedges;
+
+  int          d_num_move_points;
+  float        *d_move_points[4096];
+
+  qtexture_t   *d_qtextures;
+  // used to speedup access, specially in QERApp_Try_Texture_ForName
+  // must always be kept up-to-date with d_qtextures*
+  //++timo FIXME at some point in the future it would even be better to remove d_qtextures and use this instead
+  GHashTable *d_qtexmap;
+
+  texturewin_t d_texturewin;
+
+  int	       d_pointfile_display_list;
+
+  xy_t         d_xyOld;
+
+  SavedInfo_t  d_savedinfo;
+	
+  int          d_workcount;
+	
+  // connect entities uses the last two brushes selected
+  int	         d_select_count;
+  brush_t      *d_select_order[2];
+  vec3_t       d_select_translate;    // for dragging w/o making new display lists
+  select_t     d_select_mode;
+	
+  int          d_parsed_brushes;
+	
+  qboolean     show_blocks;
+  int		       blockSize;
+
+  // NOTE TTimo
+  // a lot of this data should be in a property bag and available to the other modules through an API
+  // this is generated from game configuration and the project settings, and should be still be part of it
+	
+  // tells if we are internally using brush primitive (texture coordinates and map format)
+  // this is a shortcut for IntForKey( g_qeglobals.d_project_entity, "brush_primit" )
+  // NOTE: must keep the two ones in sync
+  bool         m_bBrushPrimitMode;
+
+  /*!
+  win32: engine full path.
+  unix: user home full path + engine dir.
+  */
+  Str         m_strHomeGame;
+  /*!
+  cache for m_strHomeGame + mod subdirectory.
+  */
+  Str         m_strHomeMaps;
+
+  // used while importing brush data from file or memory buffer
+  // tells if conversion between map format and internal preferences ( m_bBrushPrimitMode ) is needed
+  qboolean     bNeedConvert;
+  qboolean     bOldBrushes;
+  qboolean     bPrimitBrushes;
+	
+  vec3_t       d_vAreaTL;
+  vec3_t       d_vAreaBR;
+	
+  // tells if we are using .INI files for prefs instead of registry
+  qboolean	use_ini;
+  // even in .INI mode we use the registry for all void* prefs
+  char		use_ini_registry[64];
+  // disabled all INI / registry read write .. used when shutting down after registry cleanup
+  qboolean disable_ini;
+	
+  // tells we are using a BSP frontend plugin
+  qboolean	bBSPFrontendPlugin;
+
+  // handle to the console log file
+  // we use low level I/O to get rid of buffering and have everything on file if we crash
+  int hLogFile;
+
+  qboolean bTextureCompressionSupported; // is texture compression supported by hardware?
+  GLint texture_components;
+
+  // temporary values that should be initialised only once at run-time
+  // there are too many uneccessary calls to Sys_QGL_ExtensionSupported
+  // NOTE TTimo: those are unused atm (set right, but not used)
+  // http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=623
+  bool m_bOpenGLCompressionSupported;
+  bool m_bS3CompressionSupported;
+  
+  // set to true after OpenGL has been initialized and extensions have been tested
+  bool m_bOpenGLReady;
+
+} QEGlobals_t;
+
+#endif // _QERTYPES_H_
diff --git a/include/qsysprintf.h b/include/qsysprintf.h
index 83622784..a8d2874a 100644
--- a/include/qsysprintf.h
+++ b/include/qsysprintf.h
@@ -1,67 +1,67 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __QSYSPRINTF_H__
-#define __QSYSPRINTF_H__
-
-/*!
-this header is provided in libs/ in an attempt to provide a common API
-for all the diagnostic printing / fatal error situations
-
-this is oriented at synapse server targets ONLY
-synapse clients should not include this, as they are supposed to go
-through the function tables to report print diagnostics
-(or use Syn_Printf for situations where the func table may not be available)
-
-each server target implements that in it's own way. Radiant logs to
-a file and sends to the console, q3map prints to stdout and to the
-XML network stream, etc.
-*/
-
-#if defined(__cplusplus)
-extern "C"
-{
-#endif
-
-// NOTE: might want to switch to bits if needed
-#define SYS_VRB 0 ///< verbose support (on/off)
-#define SYS_STD 1 ///< standard print level - this is the default
-#define SYS_WRN 2 ///< warnings
-#define SYS_ERR 3 ///< error
-#define SYS_NOCON 4 ///< no console, only print to the file (useful whenever Sys_Printf and output IS the problem)
-
-/*!
-those are the real implementation  
-*/
-void Sys_Printf_VA (const char *text, va_list args); ///< matches PFN_SYN_PRINTF_VA prototype
-void Sys_FPrintf_VA (int level, const char *text, va_list args);
-
-/*!
-this is easy to call, wrappers around va_list version
-*/
-void Sys_Printf (const char *text, ...);
-void Sys_FPrintf (int flag, const char *text, ...);
-  
-#if defined(__cplusplus)
-};
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __QSYSPRINTF_H__
+#define __QSYSPRINTF_H__
+
+/*!
+this header is provided in libs/ in an attempt to provide a common API
+for all the diagnostic printing / fatal error situations
+
+this is oriented at synapse server targets ONLY
+synapse clients should not include this, as they are supposed to go
+through the function tables to report print diagnostics
+(or use Syn_Printf for situations where the func table may not be available)
+
+each server target implements that in it's own way. Radiant logs to
+a file and sends to the console, q3map prints to stdout and to the
+XML network stream, etc.
+*/
+
+#if defined(__cplusplus)
+extern "C"
+{
+#endif
+
+// NOTE: might want to switch to bits if needed
+#define SYS_VRB 0 ///< verbose support (on/off)
+#define SYS_STD 1 ///< standard print level - this is the default
+#define SYS_WRN 2 ///< warnings
+#define SYS_ERR 3 ///< error
+#define SYS_NOCON 4 ///< no console, only print to the file (useful whenever Sys_Printf and output IS the problem)
+
+/*!
+those are the real implementation  
+*/
+void Sys_Printf_VA (const char *text, va_list args); ///< matches PFN_SYN_PRINTF_VA prototype
+void Sys_FPrintf_VA (int level, const char *text, va_list args);
+
+/*!
+this is easy to call, wrappers around va_list version
+*/
+void Sys_Printf (const char *text, ...);
+void Sys_FPrintf (int flag, const char *text, ...);
+  
+#if defined(__cplusplus)
+};
+#endif
+
+#endif
diff --git a/include/stl_check.h b/include/stl_check.h
index b30481df..b6def1db 100644
--- a/include/stl_check.h
+++ b/include/stl_check.h
@@ -1,60 +1,60 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*!
-This header is used to make sure the STL we are using is what we expect
-this allows to catch some weird errors early at compile time
-*/
-
-#ifdef Q_NO_STLPORT
-
-// not using STLPort (gcc 3.x build)
-using namespace std;
-
-#else
-
-#ifndef _STLPORT_VERSION
-#error "Can't find _STLPORT_VERSION, check you are compiling against STLPort"
-#endif
-
-#if !defined(_STLP_DONT_USE_EXCEPTIONS)
-#error exc
-#endif
-
-#if !defined(_STLP_NO_NAMESPACES)
-#error namespace
-#endif
-
-#if !defined(_STLP_NO_IOSTREAMS)
-#error io
-#endif
-
-// now check a few more things (paranoid)
-// if you use our custom STLPort distribution it should be alright though
-#if !defined(_STLP_DONT_USE_EXCEPTIONS) || !defined(_STLP_NO_NAMESPACES) || !defined(_STLP_NO_IOSTREAMS)
-#error "There is something broken in your STLPort config"
-#endif
-
-#ifdef _WIN32
-#pragma warning(disable : 4786)
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*!
+This header is used to make sure the STL we are using is what we expect
+this allows to catch some weird errors early at compile time
+*/
+
+#ifdef Q_NO_STLPORT
+
+// not using STLPort (gcc 3.x build)
+using namespace std;
+
+#else
+
+#ifndef _STLPORT_VERSION
+#error "Can't find _STLPORT_VERSION, check you are compiling against STLPort"
+#endif
+
+#if !defined(_STLP_DONT_USE_EXCEPTIONS)
+#error exc
+#endif
+
+#if !defined(_STLP_NO_NAMESPACES)
+#error namespace
+#endif
+
+#if !defined(_STLP_NO_IOSTREAMS)
+#error io
+#endif
+
+// now check a few more things (paranoid)
+// if you use our custom STLPort distribution it should be alright though
+#if !defined(_STLP_DONT_USE_EXCEPTIONS) || !defined(_STLP_NO_NAMESPACES) || !defined(_STLP_NO_IOSTREAMS)
+#error "There is something broken in your STLPort config"
+#endif
+
+#ifdef _WIN32
+#pragma warning(disable : 4786)
+#endif
+
+#endif
diff --git a/include/stream_version.h b/include/stream_version.h
index d9271854..17ce6339 100644
--- a/include/stream_version.h
+++ b/include/stream_version.h
@@ -1,3 +1,3 @@
-// version defines for q3map stream
-#define Q3MAP_STREAM_VERSION "1"
-
+// version defines for q3map stream
+#define Q3MAP_STREAM_VERSION "1"
+
diff --git a/include/version.h b/include/version.h
index f3905933..2ef2606b 100644
--- a/include/version.h
+++ b/include/version.h
@@ -1,4 +1,4 @@
-// generated header, see makeversion.py
-#define RADIANT_VERSION "1.4.0"
-#define RADIANT_MINOR_VERSION "0"
-#define RADIANT_MAJOR_VERSION "4"
+// generated header, see makeversion.py
+#define RADIANT_VERSION "1.4.0"
+#define RADIANT_MINOR_VERSION "0"
+#define RADIANT_MAJOR_VERSION "4"
diff --git a/install/games/default_project.proj b/install/games/default_project.proj
new file mode 100644
index 00000000..9738c418
--- /dev/null
+++ b/install/games/default_project.proj
@@ -0,0 +1,62 @@
+<?xml version="1.0"?>
+<!DOCTYPE project SYSTEM "dtds/project.dtd">
+<!--
+project template
+the $* strings will be expanded following these rules:
+$TEMPLATEapppath: path to the Radiant .. C:\Program Files\Gtkradiant
+$TEMPLATEenginepath: path to the engine .. C:\quake3\ C:\Program Files\Quake III Arena\ /usr/local/games/quake3/
+$TEMPLATEtoolspath: path to the tools directory (enginepath)radiant
+  (NOTE: on win32 tools directory is usually where the editor is .. but it's not true on linux)
+$TEMPLATEuserhomepath: on linux, the directory with write permissions for saving maps etc.
+  on win32, == $TEMPLATEenginepath
+$TEMPLATEbasedir: base game dir
+
+Note : Default project settings are for single player... this can be changed throught the projects select in the File Menu
+
+-->
+<project>
+<key name="version" value="2"/>
+<key name="basepath" value="$TEMPLATEenginepath$TEMPLATEbasedir/"/>
+<key name="rshcmd" value=""/>
+<key name="remotebasepath" value="$TEMPLATEenginepath$TEMPLATEbasedir/"/>
+<key name="entitypath" value="$TEMPLATEtoolspath$TEMPLATEbasedir/scripts/entities.def"/>
+<key name="texturepath" value="$TEMPLATEenginepath$TEMPLATEbasedir/textures/"/>
+<key name="autosave" value="$TEMPLATEuserhomepath$TEMPLATEbasedir/maps/autosave.map"/>
+<key name="mapspath" value="$TEMPLATEuserhomepath$TEMPLATEbasedir/maps/"/>
+
+<key name="bsp_Q3Map2: (single) BSP -meta" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -meta $"/>
+
+<key name="bsp_Q3Map2: (single) -vis" value="! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis $" />
+
+<key name="bsp_Q3Map2: (single test) -vis -fast" value="! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis -fast $" />
+
+<key name="bsp_Q3Map2: (single test) -light -faster" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -faster $" />
+
+<key name="bsp_Q3Map2: (single test) -light -fast" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast $" />
+
+<key name="bsp_Q3Map2: (single) -light -super 2" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -super 2 $" />
+
+<key name="bsp_Q3Map2: (single) -light -fast -super 2" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -super 2 $" />
+
+<key name="bsp_Q3Map2: (single) -light -fast -super 2 -filter" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -super 2 -filter $" />
+
+<key name="bsp_Q3Map2: (single) -light -super 2 -filter -bounce 8" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -super 2 -filter -bounce 8 $" />
+
+<key name="bsp_Q3Map2: (single) -light -super 2 -filter -bounce 1" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -super 2 -filter -bounce 1 $" />
+
+<key name="bsp_Q3Map2: (single) -light -fast -super 2 -filter -bounce 8" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -super 2 -filter -bounce 8 $" />
+
+<key name="bsp_Q3Map2: (test) BSP -meta, -vis, -light -fast -filter" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -meta $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis -saveprt $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -filter $" />
+
+<key name="bsp_Q3Map2: (test) BSP -meta, -vis -fast, -light -fast -super 2 -filter" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -meta $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis -saveprt -fast $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -super 2 -filter $" />
+
+<key name="bsp_Q3Map2: (final) BSP -meta, -vis, -light -fast -filter -super 2" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -meta $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis -saveprt $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -filter -super 2 $" />
+
+<key name="bsp_Q3Map2: (final) BSP -meta, -vis, -light -fast -filter -super 2" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -meta $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis -saveprt $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -filter -super 2 $" />
+
+<key name="bsp_Q3Map2: (final) BSP -meta, -vis, -light -fast -filter -super 2 -bounce 8" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -meta $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis -saveprt $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -fast -super 2 -filter -bounce 8 $" />
+
+<key name="bsp_Q3Map2: (simulate old style -light -extra) BSP -meta, -vis, -light -super 2" value="! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -meta $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -vis -saveprt $ &amp;&amp; ! &quot;$TEMPLATEapppathq3map2&quot; -v # -game quake3 -fs_basepath &quot;$TEMPLATEenginepath&quot; -light -super 2 $" />
+
+<key name="bsp_AAS: compile AAS" value="! &quot;$TEMPLATEapppathbspc&quot; -optimize -threads 2 -forcesidesvisible -bsp2aas $" />
+</project>
diff --git a/install/games/qz.game b/install/games/q3.game
similarity index 57%
rename from install/games/qz.game
rename to install/games/q3.game
index 5e116a9c..fc3e82fa 100644
--- a/install/games/qz.game
+++ b/install/games/q3.game
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="iso-8859-1" standalone="yes"?>
 <game
-  name="QuakeZero"
-  enginepath =".."
+  name="Quake III Arena"
+  enginepath="/usr/local/games/quake3"
   gametools="/home/timo/SVN/ZeroRadiant/install/games"
-  gamename="quakezero"
+  gamename="quake3"
 />
diff --git a/libs/bytebool.h b/libs/bytebool.h
index 9253bd35..e0617893 100644
--- a/libs/bytebool.h
+++ b/libs/bytebool.h
@@ -1,20 +1,20 @@
-#ifndef __BYTEBOOL__
-#define __BYTEBOOL__
-
-// bool is a C++ type
-// if we are compiling for C, use an enum
-
-// this header is not really meant for direct inclusion,
-// it is used by mathlib and cmdlib
-
-#ifdef __cplusplus
-typedef bool qboolean;
-#define qtrue true
-#define qfalse false
-#else
-typedef enum { qfalse, qtrue } qboolean;
-#endif
-
-typedef unsigned char byte;
-
-#endif
+#ifndef __BYTEBOOL__
+#define __BYTEBOOL__
+
+// bool is a C++ type
+// if we are compiling for C, use an enum
+
+// this header is not really meant for direct inclusion,
+// it is used by mathlib and cmdlib
+
+#ifdef __cplusplus
+typedef bool qboolean;
+#define qtrue true
+#define qfalse false
+#else
+typedef enum { qfalse, qtrue } qboolean;
+#endif
+
+typedef unsigned char byte;
+
+#endif
diff --git a/libs/cmdlib.h b/libs/cmdlib.h
index 84833fcd..92d985ae 100644
--- a/libs/cmdlib.h
+++ b/libs/cmdlib.h
@@ -1,111 +1,111 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// start of shared cmdlib stuff
-// 
-
-#ifndef __CMDLIB__
-#define __CMDLIB__
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-#include <limits.h>
-#ifdef _WIN32
-  #define PATH_MAX 260
-#endif
-
-// some easy portability crap
-#ifdef _WIN32
-  #include <direct.h>
-  #define Q_mkdir(a,b) _mkdir(a)
-#else
-  #include <sys/stat.h>
-  #define Q_mkdir(a,b) mkdir(a,b)
-#endif
-
-#ifdef __cplusplus
-  typedef bool qboolean;
-#endif
-
-// NOTE TTimo: is this worth anything?
-#ifndef __BYTEBOOL__
-#define __BYTEBOOL__
-
-#ifndef __cplusplus
-  typedef enum {false, true} boolean;
-#else
-  typedef unsigned char boolean;
-#endif
-
-typedef unsigned char byte;
-
-#endif // __BYTEBOOL__
-
-void 	DefaultExtension( char *path, char *extension );
-void 	DefaultPath( char *path, char *basepath );
-void 	StripFilename( char *path );
-void 	StripExtension( char *path );
-void 	ExtractFilePath( const char *path, char *dest );
-void	ExtractFileName( const char *path, char *dest );
-void 	ExtractFileBase( const char *path, char *dest );
-void	ExtractFileExtension( const char *path, char *dest );
-/*!
-\brief create all directories leading to a file path. if you pass a directory, terminate it with a '/'
-*/  
-void  CreateDirectoryPath (const char *path);
-  
-short	BigShort (short l);
-short	LittleShort (short l);
-int		BigLong (int l);
-int		LittleLong (int l);
-float	BigFloat (float l);
-float	LittleFloat (float l);
-void *qmalloc (size_t size);
-void* qblockmalloc(size_t nSize);
-
-void ConvertDOSToUnixName( char *dst, const char *src );
-#ifdef __cplusplus
-  char* StrDup(char* pStr);
-#endif
-char* StrDup(const char* pStr);
-
-// TTimo started adding portability code:
-// return true if spawning was successful, false otherwise
-// on win32 we have a bCreateConsole flag to create a new console or run inside the current one
-//boolean Q_Exec(const char* pCmd, boolean bCreateConsole);
-// execute a system command:
-//   cmd: the command to run
-//   cmdline: the command line
-// NOTE TTimo following are win32 specific:
-//   execdir: the directory to execute in
-//   bCreateConsole: spawn a new console or not
-// return values;
-//   if the spawn was fine
-//   TODO TTimo add functionality to track the process until it dies
-bool Q_Exec(const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole);
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// start of shared cmdlib stuff
+// 
+
+#ifndef __CMDLIB__
+#define __CMDLIB__
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdarg.h>
+#include <limits.h>
+#ifdef _WIN32
+  #define PATH_MAX 260
+#endif
+
+// some easy portability crap
+#ifdef _WIN32
+  #include <direct.h>
+  #define Q_mkdir(a,b) _mkdir(a)
+#else
+  #include <sys/stat.h>
+  #define Q_mkdir(a,b) mkdir(a,b)
+#endif
+
+#ifdef __cplusplus
+  typedef bool qboolean;
+#endif
+
+// NOTE TTimo: is this worth anything?
+#ifndef __BYTEBOOL__
+#define __BYTEBOOL__
+
+#ifndef __cplusplus
+  typedef enum {false, true} boolean;
+#else
+  typedef unsigned char boolean;
+#endif
+
+typedef unsigned char byte;
+
+#endif // __BYTEBOOL__
+
+void 	DefaultExtension( char *path, char *extension );
+void 	DefaultPath( char *path, char *basepath );
+void 	StripFilename( char *path );
+void 	StripExtension( char *path );
+void 	ExtractFilePath( const char *path, char *dest );
+void	ExtractFileName( const char *path, char *dest );
+void 	ExtractFileBase( const char *path, char *dest );
+void	ExtractFileExtension( const char *path, char *dest );
+/*!
+\brief create all directories leading to a file path. if you pass a directory, terminate it with a '/'
+*/  
+void  CreateDirectoryPath (const char *path);
+  
+short	BigShort (short l);
+short	LittleShort (short l);
+int		BigLong (int l);
+int		LittleLong (int l);
+float	BigFloat (float l);
+float	LittleFloat (float l);
+void *qmalloc (size_t size);
+void* qblockmalloc(size_t nSize);
+
+void ConvertDOSToUnixName( char *dst, const char *src );
+#ifdef __cplusplus
+  char* StrDup(char* pStr);
+#endif
+char* StrDup(const char* pStr);
+
+// TTimo started adding portability code:
+// return true if spawning was successful, false otherwise
+// on win32 we have a bCreateConsole flag to create a new console or run inside the current one
+//boolean Q_Exec(const char* pCmd, boolean bCreateConsole);
+// execute a system command:
+//   cmd: the command to run
+//   cmdline: the command line
+// NOTE TTimo following are win32 specific:
+//   execdir: the directory to execute in
+//   bCreateConsole: spawn a new console or not
+// return values;
+//   if the spawn was fine
+//   TODO TTimo add functionality to track the process until it dies
+bool Q_Exec(const char *cmd, char *cmdline, const char *execdir, bool bCreateConsole);
+
+#endif
diff --git a/libs/ddslib.h b/libs/ddslib.h
index 246e31be..3f5f124c 100644
--- a/libs/ddslib.h
+++ b/libs/ddslib.h
@@ -1,250 +1,250 @@
-/* -----------------------------------------------------------------------------
-
-DDS Library 
-
-Based on code from Nvidia's DDS example:
-http://www.nvidia.com/object/dxtc_decompression_code.html
-
-Copyright (c) 2003 Randy Reddig
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#ifndef DDSLIB_H
-#define DDSLIB_H
-
-
-
-/* dependencies */
-#include <stdio.h>
-#include <memory.h>
-
-
-
-/* c++ marker */
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
-
-/* dds definition */
-typedef enum
-{
-	DDS_PF_ARGB8888,
-	DDS_PF_DXT1,
-	DDS_PF_DXT2,
-	DDS_PF_DXT3,
-	DDS_PF_DXT4,
-	DDS_PF_DXT5,
-	DDS_PF_UNKNOWN
-}
-ddsPF_t;
-
-
-/* 16bpp stuff */
-#define DDS_LOW_5		0x001F;
-#define DDS_MID_6		0x07E0;
-#define DDS_HIGH_5		0xF800;
-#define DDS_MID_555		0x03E0;
-#define DDS_HI_555		0x7C00;
-
-
-/* structures */
-typedef struct ddsColorKey_s
-{
-	unsigned int		colorSpaceLowValue;
-	unsigned int		colorSpaceHighValue;
-} 
-ddsColorKey_t;
-
-
-typedef struct ddsCaps_s
-{
-	unsigned int		caps1;
-	unsigned int		caps2;
-	unsigned int		caps3;
-	unsigned int		caps4;
-} 
-ddsCaps_t;
-
-
-typedef struct ddsMultiSampleCaps_s
-{
-	unsigned short		flipMSTypes;
-	unsigned short		bltMSTypes;
-}
-ddsMultiSampleCaps_t;
-
-
-typedef struct ddsPixelFormat_s
-{
-	unsigned int		size;
-	unsigned int		flags;
-	unsigned int		fourCC;
-	union
-	{
-		unsigned int	rgbBitCount;
-		unsigned int	yuvBitCount;
-		unsigned int	zBufferBitDepth;
-		unsigned int	alphaBitDepth;
-		unsigned int	luminanceBitCount;
-		unsigned int	bumpBitCount;
-		unsigned int	privateFormatBitCount;
-	};
-	union
-	{
-		unsigned int	rBitMask;
-		unsigned int	yBitMask;
-		unsigned int	stencilBitDepth;
-		unsigned int	luminanceBitMask;
-		unsigned int	bumpDuBitMask;
-		unsigned int	operations;
-	};
-	union
-	{
-		unsigned int	gBitMask;
-		unsigned int	uBitMask;
-		unsigned int	zBitMask;
-		unsigned int	bumpDvBitMask;
-		ddsMultiSampleCaps_t	multiSampleCaps;
-	};
-	union
-	{
-		unsigned int	bBitMask;
-		unsigned int	vBitMask;
-		unsigned int	stencilBitMask;
-		unsigned int	bumpLuminanceBitMask;
-	};
-	union
-	{
-		unsigned int	rgbAlphaBitMask;
-		unsigned int	yuvAlphaBitMask;
-		unsigned int	luminanceAlphaBitMask;
-		unsigned int	rgbZBitMask;
-		unsigned int	yuvZBitMask;
-	};
-}
-ddsPixelFormat_t;
-
-
-typedef struct ddsBuffer_s
-{
-	/* magic: 'dds ' */
-	char				magic[ 4 ];
-	
-	/* directdraw surface */
-	unsigned int		size;
-	unsigned int		flags;
-	unsigned int		height;
-	unsigned int		width; 
-	union
-	{
-		int				pitch;
-		unsigned int	linearSize;
-	};
-	unsigned int		backBufferCount;
-	union
-	{
-		unsigned int	mipMapCount;
-		unsigned int	refreshRate;
-		unsigned int	srcVBHandle;
-	};
-	unsigned int		alphaBitDepth;
-	unsigned int		reserved;
-	void				*surface;
-	union
-	{
-		ddsColorKey_t	ckDestOverlay;   
-		unsigned int	emptyFaceColor;
-	};
-	ddsColorKey_t		ckDestBlt;
-	ddsColorKey_t		ckSrcOverlay;    
-	ddsColorKey_t		ckSrcBlt;     
-	union
-	{
-		ddsPixelFormat_t	pixelFormat;
-		unsigned int	fvf;
-	};
-	ddsCaps_t			ddsCaps;
-	unsigned int		textureStage;
-	
-	/* data (Varying size) */
-	unsigned char		data[ 4 ];
-}
-ddsBuffer_t;
-
-
-typedef struct ddsColorBlock_s
-{
-	unsigned short		colors[ 2 ];
-	unsigned char		row[ 4 ];
-}
-ddsColorBlock_t;
-
-
-typedef struct ddsAlphaBlockExplicit_s
-{
-	unsigned short		row[ 4 ];
-}
-ddsAlphaBlockExplicit_t;
-
-
-typedef struct ddsAlphaBlock3BitLinear_s
-{
-	unsigned char		alpha0;
-	unsigned char		alpha1;
-	unsigned char		stuff[ 6 ];
-}
-ddsAlphaBlock3BitLinear_t;
-
-
-typedef struct ddsColor_s
-{
-	unsigned char		r, g, b, a;
-}
-ddsColor_t;
-
-
-
-/* public functions */
-int						DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf );
-int						DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels );
-
-
-
-/* end marker */
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* -----------------------------------------------------------------------------
+
+DDS Library 
+
+Based on code from Nvidia's DDS example:
+http://www.nvidia.com/object/dxtc_decompression_code.html
+
+Copyright (c) 2003 Randy Reddig
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef DDSLIB_H
+#define DDSLIB_H
+
+
+
+/* dependencies */
+#include <stdio.h>
+#include <memory.h>
+
+
+
+/* c++ marker */
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+/* dds definition */
+typedef enum
+{
+	DDS_PF_ARGB8888,
+	DDS_PF_DXT1,
+	DDS_PF_DXT2,
+	DDS_PF_DXT3,
+	DDS_PF_DXT4,
+	DDS_PF_DXT5,
+	DDS_PF_UNKNOWN
+}
+ddsPF_t;
+
+
+/* 16bpp stuff */
+#define DDS_LOW_5		0x001F;
+#define DDS_MID_6		0x07E0;
+#define DDS_HIGH_5		0xF800;
+#define DDS_MID_555		0x03E0;
+#define DDS_HI_555		0x7C00;
+
+
+/* structures */
+typedef struct ddsColorKey_s
+{
+	unsigned int		colorSpaceLowValue;
+	unsigned int		colorSpaceHighValue;
+} 
+ddsColorKey_t;
+
+
+typedef struct ddsCaps_s
+{
+	unsigned int		caps1;
+	unsigned int		caps2;
+	unsigned int		caps3;
+	unsigned int		caps4;
+} 
+ddsCaps_t;
+
+
+typedef struct ddsMultiSampleCaps_s
+{
+	unsigned short		flipMSTypes;
+	unsigned short		bltMSTypes;
+}
+ddsMultiSampleCaps_t;
+
+
+typedef struct ddsPixelFormat_s
+{
+	unsigned int		size;
+	unsigned int		flags;
+	unsigned int		fourCC;
+	union
+	{
+		unsigned int	rgbBitCount;
+		unsigned int	yuvBitCount;
+		unsigned int	zBufferBitDepth;
+		unsigned int	alphaBitDepth;
+		unsigned int	luminanceBitCount;
+		unsigned int	bumpBitCount;
+		unsigned int	privateFormatBitCount;
+	};
+	union
+	{
+		unsigned int	rBitMask;
+		unsigned int	yBitMask;
+		unsigned int	stencilBitDepth;
+		unsigned int	luminanceBitMask;
+		unsigned int	bumpDuBitMask;
+		unsigned int	operations;
+	};
+	union
+	{
+		unsigned int	gBitMask;
+		unsigned int	uBitMask;
+		unsigned int	zBitMask;
+		unsigned int	bumpDvBitMask;
+		ddsMultiSampleCaps_t	multiSampleCaps;
+	};
+	union
+	{
+		unsigned int	bBitMask;
+		unsigned int	vBitMask;
+		unsigned int	stencilBitMask;
+		unsigned int	bumpLuminanceBitMask;
+	};
+	union
+	{
+		unsigned int	rgbAlphaBitMask;
+		unsigned int	yuvAlphaBitMask;
+		unsigned int	luminanceAlphaBitMask;
+		unsigned int	rgbZBitMask;
+		unsigned int	yuvZBitMask;
+	};
+}
+ddsPixelFormat_t;
+
+
+typedef struct ddsBuffer_s
+{
+	/* magic: 'dds ' */
+	char				magic[ 4 ];
+	
+	/* directdraw surface */
+	unsigned int		size;
+	unsigned int		flags;
+	unsigned int		height;
+	unsigned int		width; 
+	union
+	{
+		int				pitch;
+		unsigned int	linearSize;
+	};
+	unsigned int		backBufferCount;
+	union
+	{
+		unsigned int	mipMapCount;
+		unsigned int	refreshRate;
+		unsigned int	srcVBHandle;
+	};
+	unsigned int		alphaBitDepth;
+	unsigned int		reserved;
+	void				*surface;
+	union
+	{
+		ddsColorKey_t	ckDestOverlay;   
+		unsigned int	emptyFaceColor;
+	};
+	ddsColorKey_t		ckDestBlt;
+	ddsColorKey_t		ckSrcOverlay;    
+	ddsColorKey_t		ckSrcBlt;     
+	union
+	{
+		ddsPixelFormat_t	pixelFormat;
+		unsigned int	fvf;
+	};
+	ddsCaps_t			ddsCaps;
+	unsigned int		textureStage;
+	
+	/* data (Varying size) */
+	unsigned char		data[ 4 ];
+}
+ddsBuffer_t;
+
+
+typedef struct ddsColorBlock_s
+{
+	unsigned short		colors[ 2 ];
+	unsigned char		row[ 4 ];
+}
+ddsColorBlock_t;
+
+
+typedef struct ddsAlphaBlockExplicit_s
+{
+	unsigned short		row[ 4 ];
+}
+ddsAlphaBlockExplicit_t;
+
+
+typedef struct ddsAlphaBlock3BitLinear_s
+{
+	unsigned char		alpha0;
+	unsigned char		alpha1;
+	unsigned char		stuff[ 6 ];
+}
+ddsAlphaBlock3BitLinear_t;
+
+
+typedef struct ddsColor_s
+{
+	unsigned char		r, g, b, a;
+}
+ddsColor_t;
+
+
+
+/* public functions */
+int						DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf );
+int						DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels );
+
+
+
+/* end marker */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/ddslib/ddslib.c b/libs/ddslib/ddslib.c
index e7bfeb2b..bf1a9f15 100644
--- a/libs/ddslib/ddslib.c
+++ b/libs/ddslib/ddslib.c
@@ -1,781 +1,781 @@
-/* -----------------------------------------------------------------------------
-
-DDS Library 
-
-Based on code from Nvidia's DDS example:
-http://www.nvidia.com/object/dxtc_decompression_code.html
-
-Copyright (c) 2003 Randy Reddig
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define DDSLIB_C
-
-
-
-/* dependencies */
-#include "ddslib.h"
-
-
-
-/* endian tomfoolery */
-typedef union
-{
-	float	f;
-	char	c[ 4 ];
-}
-floatSwapUnion;
-
-
-#ifndef __BIG_ENDIAN__
-	#ifdef _SGI_SOURCE
-		#define	__BIG_ENDIAN__
-	#endif
-#endif
-
-
-#ifdef __BIG_ENDIAN__
-
-	int   DDSBigLong( int src ) { return src; }
-	short DDSBigShort( short src ) { return src; }
-	float DDSBigFloat( float src ) { return src; }
-
-	int DDSLittleLong( int src )
-	{
-		return ((src & 0xFF000000) >> 24) |
-			   ((src & 0x00FF0000) >> 8) |
-			   ((src & 0x0000FF00) << 8) |
-			   ((src & 0x000000FF) << 24);
-	}
-
-	short DDSLittleShort( short src )
-	{
-		return ((src & 0xFF00) >> 8) |
-			   ((src & 0x00FF) << 8);
-	}
-
-	float DDSLittleFloat( float src )
-	{
-		floatSwapUnion in,out;
-		in.f = src;
-		out.c[ 0 ] = in.c[ 3 ];
-		out.c[ 1 ] = in.c[ 2 ];
-		out.c[ 2 ] = in.c[ 1 ];
-		out.c[ 3 ] = in.c[ 0 ];
-		return out.f;
-	}
-
-#else /*__BIG_ENDIAN__*/
-
-	int   DDSLittleLong( int src ) { return src; }
-	short DDSLittleShort( short src ) { return src; }
-	float DDSLittleFloat( float src ) { return src; }
-		
-	int DDSBigLong( int src )
-	{
-		return ((src & 0xFF000000) >> 24) |
-			   ((src & 0x00FF0000) >> 8) |
-			   ((src & 0x0000FF00) << 8) |
-			   ((src & 0x000000FF) << 24);
-	}
-		
-	short DDSBigShort( short src )
-	{
-		return ((src & 0xFF00) >> 8) |
-			   ((src & 0x00FF) << 8);
-	}
-		
-	float DDSBigFloat( float src )
-	{
-		floatSwapUnion in,out;
-		in.f = src;
-		out.c[ 0 ] = in.c[ 3 ];
-		out.c[ 1 ] = in.c[ 2 ];
-		out.c[ 2 ] = in.c[ 1 ];
-		out.c[ 3 ] = in.c[ 0 ];
-		return out.f;
-	}
-
-#endif /*__BIG_ENDIAN__*/
-
-
-
-/*
-DDSDecodePixelFormat()
-determines which pixel format the dds texture is in
-*/
-
-static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf )
-{
-	unsigned int	fourCC;
-	
-	
-	/* dummy check */
-	if(	dds == NULL || pf == NULL )
-		return;
-	
-	/* extract fourCC */
-	fourCC = dds->pixelFormat.fourCC;
-	
-	/* test it */
-	if( fourCC == 0 )
-		*pf = DDS_PF_ARGB8888;
-	else if( fourCC == *((unsigned int*) "DXT1") )
-		*pf = DDS_PF_DXT1;
-	else if( fourCC == *((unsigned int*) "DXT2") )
-		*pf = DDS_PF_DXT2;
-	else if( fourCC == *((unsigned int*) "DXT3") )
-		*pf = DDS_PF_DXT3;
-	else if( fourCC == *((unsigned int*) "DXT4") )
-		*pf = DDS_PF_DXT4;
-	else if( fourCC == *((unsigned int*) "DXT5") )
-		*pf = DDS_PF_DXT5;
-	else
-		*pf = DDS_PF_UNKNOWN;
-}
-
-
-
-/*
-DDSGetInfo()
-extracts relevant info from a dds texture, returns 0 on success
-*/
-
-int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf )
-{
-	/* dummy test */
-	if( dds == NULL )
-		return -1;
-	
-	/* test dds header */
-	if( *((int*) dds->magic) != *((int*) "DDS ") )
-		return -1;
-	if( DDSLittleLong( dds->size ) != 124 )
-		return -1;
-	
-	/* extract width and height */
-	if( width != NULL )
-		*width = DDSLittleLong( dds->width );
-	if( height != NULL )
-		*height = DDSLittleLong( dds->height );
-	
-	/* get pixel format */
-	DDSDecodePixelFormat( dds, pf );
-	
-	/* return ok */
-	return 0;
-}
-
-
-
-/*
-DDSGetColorBlockColors()
-extracts colors from a dds color block
-*/
-
-static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] )
-{
-	unsigned short		word;
-
-	
-	/* color 0 */
-	word = DDSLittleShort( block->colors[ 0 ] );
-	colors[ 0 ].a = 0xff;
-	
-	/* extract rgb bits */
-	colors[ 0 ].b = (unsigned char) word;
-	colors[ 0 ].b <<= 3;
-	colors[ 0 ].b |= (colors[ 0 ].b >> 5);
-	word >>= 5;
-	colors[ 0 ].g = (unsigned char) word;
-	colors[ 0 ].g <<= 2;
-	colors[ 0 ].g |= (colors[ 0 ].g >> 5);
-	word >>= 6;
-	colors[ 0 ].r = (unsigned char) word;
-	colors[ 0 ].r <<= 3;
-	colors[ 0 ].r |= (colors[ 0 ].r >> 5);
-
-	/* same for color 1 */
-	word = DDSLittleShort( block->colors[ 1 ] );
-	colors[ 1 ].a = 0xff;
-	
-	/* extract rgb bits */
-	colors[ 1 ].b = (unsigned char) word;
-	colors[ 1 ].b <<= 3;
-	colors[ 1 ].b |= (colors[ 1 ].b >> 5);
-	word >>= 5;
-	colors[ 1 ].g = (unsigned char) word;
-	colors[ 1 ].g <<= 2;
-	colors[ 1 ].g |= (colors[ 1 ].g >> 5);
-	word >>= 6;
-	colors[ 1 ].r = (unsigned char) word;
-	colors[ 1 ].r <<= 3;
-	colors[ 1 ].r |= (colors[ 1 ].r >> 5);
-	
-	/* use this for all but the super-freak math method */
-	if( block->colors[ 0 ] > block->colors[ 1 ] )
-	{
-		/* four-color block: derive the other two colors.    
-		   00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
-		   these two bit codes correspond to the 2-bit fields 
-		   stored in the 64-bit block. */
-
-		word = ((unsigned short) colors[ 0 ].r * 2 + (unsigned short) colors[ 1 ].r ) / 3;
-											/* no +1 for rounding */
-											/* as bits have been shifted to 888 */
-		colors[ 2 ].r = (unsigned char) word;
-		word = ((unsigned short) colors[ 0 ].g * 2 + (unsigned short) colors[ 1 ].g) / 3;
-		colors[ 2 ].g = (unsigned char) word;
-		word = ((unsigned short) colors[ 0 ].b * 2 + (unsigned short) colors[ 1 ].b) / 3;
-		colors[ 2 ].b = (unsigned char) word;
-		colors[ 2 ].a = 0xff;
-
-		word = ((unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r * 2) / 3;
-		colors[ 3 ].r = (unsigned char) word;
-		word = ((unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g * 2) / 3;
-		colors[ 3 ].g = (unsigned char) word;
-		word = ((unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b * 2) / 3;
-		colors[ 3 ].b = (unsigned char) word;
-		colors[ 3 ].a = 0xff;
-	}
-	else
-	{
-		/* three-color block: derive the other color.
-		   00 = color 0, 01 = color 1, 10 = color 2,  
-		   11 = transparent.
-		   These two bit codes correspond to the 2-bit fields 
-		   stored in the 64-bit block */
-
-		word = ((unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r) / 2;
-		colors[ 2 ].r = (unsigned char) word;
-		word = ((unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g) / 2;
-		colors[ 2 ].g = (unsigned char) word;
-		word = ((unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b) / 2;
-		colors[ 2 ].b = (unsigned char) word;
-		colors[ 2 ].a = 0xff;
-		
-		/* random color to indicate alpha */
-		colors[ 3 ].r = 0x00;
-		colors[ 3 ].g = 0xff;
-		colors[ 3 ].b = 0xff;
-		colors[ 3 ].a = 0x00;
-	}
-}
-
-
-
-/*
-DDSDecodeColorBlock()
-decodes a dds color block
-fixme: make endian-safe
-*/
-
-static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] )
-{
-	int				r, n;
-	unsigned int	bits;
-	unsigned int	masks[] = { 3, 12, 3 << 4, 3 << 6 };	/* bit masks = 00000011, 00001100, 00110000, 11000000 */
-	int				shift[] = { 0, 2, 4, 6 };
-	
-	
-	/* r steps through lines in y */
-	for( r = 0; r < 4; r++, pixel += (width - 4) )	/* no width * 4 as unsigned int ptr inc will * 4 */
-	{
-		/* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
-
-		/* n steps through pixels */
-		for( n = 0; n < 4; n++ )
-		{
-			bits = block->row[ r ] & masks[ n ];
-			bits >>= shift[ n ];
-
-			switch( bits )
-			{
-				case 0:
-					*pixel = colors[ 0 ];
-					pixel++;
-					break;
-
-				case 1:
-					*pixel = colors[ 1 ];
-					pixel++;
-					break;
-
-				case 2:
-					*pixel = colors[ 2 ];
-					pixel++;
-					break;
-
-				case 3:
-					*pixel = colors[ 3 ];
-					pixel++;
-					break;
-
-				default:
-					/* invalid */
-					pixel++;
-					break;
-			}
-		}
-	}
-}
-
-
-
-/*
-DDSDecodeAlphaExplicit()
-decodes a dds explicit alpha block
-*/
-
-static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero )
-{	
-	int				row, pix;
-	unsigned short	word;
-	ddsColor_t		color;
-	
-	
-	/* clear color */
-	color.r = 0;
-	color.g = 0;
-	color.b = 0;
-	
-	/* walk rows */
-	for( row = 0; row < 4; row++, pixel += (width - 4) )
-	{
-		word = DDSLittleShort( alphaBlock->row[ row ] );
-		
-		/* walk pixels */
-		for( pix = 0; pix < 4; pix++ )
-		{
-			/* zero the alpha bits of image pixel */
-			*pixel &= alphaZero;
-			color.a = word & 0x000F;
-			color.a = color.a | (color.a << 4);
-			*pixel |= *((unsigned int*) &color);
-			word >>= 4;		/* move next bits to lowest 4 */
-			pixel++;		/* move to next pixel in the row */
-
-		}
-	}
-}
-
-
-
-/*
-DDSDecodeAlpha3BitLinear()
-decodes interpolated alpha block
-*/
-
-static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero )
-{
-	
-	int					row, pix;
-	unsigned int		stuff;
-	unsigned char		bits[ 4 ][ 4 ];
-	unsigned short		alphas[ 8 ];
-	ddsColor_t			aColors[ 4 ][ 4 ];
-	
-	
-	/* get initial alphas */
-	alphas[ 0 ] = alphaBlock->alpha0;
-	alphas[ 1 ] = alphaBlock->alpha1;
-	
-	/* 8-alpha block */
-	if( alphas[ 0 ] > alphas[ 1 ] )
-	{
-		/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
-		alphas[ 2 ] = ( 6 * alphas[ 0 ] +     alphas[ 1 ]) / 7;	/* bit code 010 */
-		alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 7;	/* bit code 011 */
-		alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 7;	/* bit code 100 */
-		alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ]) / 7;	/* bit code 101 */
-		alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ]) / 7;	/* bit code 110 */
-		alphas[ 7 ] = (     alphas[ 0 ] + 6 * alphas[ 1 ]) / 7;	/* bit code 111 */
-	}
-	
-	/* 6-alpha block */
-	else
-	{ 
-		/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
-		alphas[ 2 ] = (4 * alphas[ 0 ] +     alphas[ 1 ]) / 5;	/* bit code 010 */
-		alphas[ 3 ] = (3 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 5;	/* bit code 011 */
-		alphas[ 4 ] = (2 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 5;	/* bit code 100 */
-		alphas[ 5 ] = (    alphas[ 0 ] + 4 * alphas[ 1 ]) / 5;	/* bit code 101 */
-		alphas[ 6 ] = 0;										/* bit code 110 */
-		alphas[ 7 ] = 255;										/* bit code 111 */
-	}
-	
-	/* decode 3-bit fields into array of 16 bytes with same value */
-	
-	/* first two rows of 4 pixels each */
-	stuff = *((unsigned int*) &(alphaBlock->stuff[ 0 ]));
-	
-	bits[ 0 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 0 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 0 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 0 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 1 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 1 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 1 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 1 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
-	
-	/* last two rows */
-	stuff = *((unsigned int*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */
-	
-	bits[ 2 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 2 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 2 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 2 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 3 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 3 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 3 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
-	stuff >>= 3;
-	bits[ 3 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
-	
-	/* decode the codes into alpha values */
-	for( row = 0; row < 4; row++ )
-	{
-		for( pix=0; pix < 4; pix++ )
-		{
-			aColors[ row ][ pix ].r = 0;
-			aColors[ row ][ pix ].g = 0;
-			aColors[ row ][ pix ].b = 0;
-			aColors[ row ][ pix ].a = (unsigned char) alphas[ bits[ row ][ pix ] ];
-		}
-	}
-	
-	/* write out alpha values to the image bits */
-	for( row = 0; row < 4; row++, pixel += width-4 )
-	{
-		for( pix = 0; pix < 4; pix++ )
-		{
-			/* zero the alpha bits of image pixel */
-			*pixel &= alphaZero;
-			
-			/* or the bits into the prev. nulled alpha */
-			*pixel |= *((unsigned int*) &(aColors[ row ][ pix ]));	
-			pixel++;
-		}
-	}
-}
-
-
-
-/*
-DDSDecompressDXT1()
-decompresses a dxt1 format texture
-*/
-
-static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
-{
-	int				x, y, xBlocks, yBlocks;
-	unsigned int	*pixel;
-	ddsColorBlock_t	*block;
-	ddsColor_t		colors[ 4 ];
-	
-	
-	/* setup */
-	xBlocks = width / 4;
-	yBlocks = height / 4;
-	
-	/* walk y */
-	for( y = 0; y < yBlocks; y++ )
-	{
-		/* 8 bytes per block */
-		block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 8);
-
-		/* walk x */
-		for( x = 0; x < xBlocks; x++, block++ )
-		{
-			DDSGetColorBlockColors( block, colors );
-			pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
-			DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
-		}
-	}
-	
-	/* return ok */
-	return 0;
-}
-
-
-
-/*
-DDSDecompressDXT3()
-decompresses a dxt3 format texture
-*/
-
-static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
-{
-	int						x, y, xBlocks, yBlocks;
-	unsigned int			*pixel, alphaZero;
-	ddsColorBlock_t			*block;
-	ddsAlphaBlockExplicit_t	*alphaBlock;
-	ddsColor_t				colors[ 4 ];
-
-
-	/* setup */
-	xBlocks = width / 4;
-	yBlocks = height / 4;
-	
-	/* create zero alpha */
-	colors[ 0 ].a = 0;
-	colors[ 0 ].r = 0xFF;
-	colors[ 0 ].g = 0xFF;
-	colors[ 0 ].b = 0xFF;
-	alphaZero = *((unsigned int*) &colors[ 0 ]);
-	
-	/* walk y */
-	for( y = 0; y < yBlocks; y++ )
-	{
-		/* 8 bytes per block, 1 block for alpha, 1 block for color */
-		block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
-
-		/* walk x */
-		for( x = 0; x < xBlocks; x++, block++ )
-		{
-			/* get alpha block */
-			alphaBlock = (ddsAlphaBlockExplicit_t*) block;
-			
-			/* get color block */
-			block++;
-			DDSGetColorBlockColors( block, colors );
-			
-			/* decode color block */
-			pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
-			DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
-			
-			/* overwrite alpha bits with alpha block */
-			DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
-		}
-	}
-	
-	/* return ok */
-	return 0;
-}
-
-
-
-/*
-DDSDecompressDXT5()
-decompresses a dxt5 format texture
-*/
-
-static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
-{
-	int							x, y, xBlocks, yBlocks;
-	unsigned int				*pixel, alphaZero;
-	ddsColorBlock_t				*block;
-	ddsAlphaBlock3BitLinear_t	*alphaBlock;
-	ddsColor_t					colors[ 4 ];
-
-
-	/* setup */
-	xBlocks = width / 4;
-	yBlocks = height / 4;
-	
-	/* create zero alpha */
-	colors[ 0 ].a = 0;
-	colors[ 0 ].r = 0xFF;
-	colors[ 0 ].g = 0xFF;
-	colors[ 0 ].b = 0xFF;
-	alphaZero = *((unsigned int*) &colors[ 0 ]);
-	
-	/* walk y */
-	for( y = 0; y < yBlocks; y++ )
-	{
-		/* 8 bytes per block, 1 block for alpha, 1 block for color */
-		block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
-
-		/* walk x */
-		for( x = 0; x < xBlocks; x++, block++ )
-		{
-			/* get alpha block */
-			alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
-			
-			/* get color block */
-			block++;
-			DDSGetColorBlockColors( block, colors );
-			
-			/* decode color block */
-			pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
-			DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
-			
-			/* overwrite alpha bits with alpha block */
-			DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
-		}
-	}
-	
-	/* return ok */
-	return 0;
-}
-
-
-
-/*
-DDSDecompressDXT2()
-decompresses a dxt2 format texture (fixme: un-premultiply alpha)
-*/
-
-static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
-{
-	int		r;
-	
-	
-	/* decompress dxt3 first */
-	r = DDSDecompressDXT3( dds, width, height, pixels );
-	
-	/* return to sender */
-	return r;
-}
-
-
-
-/*
-DDSDecompressDXT4()
-decompresses a dxt4 format texture (fixme: un-premultiply alpha)
-*/
-
-static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
-{
-	int		r;
-	
-	
-	/* decompress dxt5 first */
-	r = DDSDecompressDXT5( dds, width, height, pixels );
-	
-	/* return to sender */
-	return r;
-}
-
-
-
-/*
-DDSDecompressARGB8888()
-decompresses an argb 8888 format texture
-*/
-
-static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
-{
-	int							x, y;
-	unsigned char				*in, *out;
-	
-	
-	/* setup */
-	in = dds->data;
-	out = pixels;
-	
-	/* walk y */
-	for( y = 0; y < height; y++ )
-	{
-		/* walk x */
-		for( x = 0; x < width; x++ )
-		{
-			*out++ = *in++;
-			*out++ = *in++;
-			*out++ = *in++;
-			*out++ = *in++;
-		}
-	}
-	
-	/* return ok */
-	return 0;
-}
-
-
-
-/*
-DDSDecompress()
-decompresses a dds texture into an rgba image buffer, returns 0 on success
-*/
-
-int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels )
-{
-	int			width, height, r;
-	ddsPF_t		pf;
-	
-	
-	/* get dds info */
-	r = DDSGetInfo( dds, &width, &height, &pf );
-	if( r )
-		return r;
-	
-	/* decompress */
-	switch( pf )
-	{
-		case DDS_PF_ARGB8888:
-			/* fixme: support other [a]rgb formats */
-			r = DDSDecompressARGB8888( dds, width, height, pixels );
-			break;
-		
-		case DDS_PF_DXT1:
-			r = DDSDecompressDXT1( dds, width, height, pixels );
-			break;
-		
-		case DDS_PF_DXT2:
-			r = DDSDecompressDXT2( dds, width, height, pixels );
-			break;
-		
-		case DDS_PF_DXT3:
-			r = DDSDecompressDXT3( dds, width, height, pixels );	
-			break;
-		
-		case DDS_PF_DXT4:
-			r = DDSDecompressDXT4( dds, width, height, pixels );
-			break;
-		
-		case DDS_PF_DXT5:
-			r = DDSDecompressDXT5( dds, width, height, pixels );		
-			break;
-		
-		default:
-		case DDS_PF_UNKNOWN:
-			memset( pixels, 0xFF, width * height * 4 );
-			r = -1;
-			break;
-	}
-	
-	/* return to sender */
-	return r;
-}
-
+/* -----------------------------------------------------------------------------
+
+DDS Library 
+
+Based on code from Nvidia's DDS example:
+http://www.nvidia.com/object/dxtc_decompression_code.html
+
+Copyright (c) 2003 Randy Reddig
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define DDSLIB_C
+
+
+
+/* dependencies */
+#include "ddslib.h"
+
+
+
+/* endian tomfoolery */
+typedef union
+{
+	float	f;
+	char	c[ 4 ];
+}
+floatSwapUnion;
+
+
+#ifndef __BIG_ENDIAN__
+	#ifdef _SGI_SOURCE
+		#define	__BIG_ENDIAN__
+	#endif
+#endif
+
+
+#ifdef __BIG_ENDIAN__
+
+	int   DDSBigLong( int src ) { return src; }
+	short DDSBigShort( short src ) { return src; }
+	float DDSBigFloat( float src ) { return src; }
+
+	int DDSLittleLong( int src )
+	{
+		return ((src & 0xFF000000) >> 24) |
+			   ((src & 0x00FF0000) >> 8) |
+			   ((src & 0x0000FF00) << 8) |
+			   ((src & 0x000000FF) << 24);
+	}
+
+	short DDSLittleShort( short src )
+	{
+		return ((src & 0xFF00) >> 8) |
+			   ((src & 0x00FF) << 8);
+	}
+
+	float DDSLittleFloat( float src )
+	{
+		floatSwapUnion in,out;
+		in.f = src;
+		out.c[ 0 ] = in.c[ 3 ];
+		out.c[ 1 ] = in.c[ 2 ];
+		out.c[ 2 ] = in.c[ 1 ];
+		out.c[ 3 ] = in.c[ 0 ];
+		return out.f;
+	}
+
+#else /*__BIG_ENDIAN__*/
+
+	int   DDSLittleLong( int src ) { return src; }
+	short DDSLittleShort( short src ) { return src; }
+	float DDSLittleFloat( float src ) { return src; }
+		
+	int DDSBigLong( int src )
+	{
+		return ((src & 0xFF000000) >> 24) |
+			   ((src & 0x00FF0000) >> 8) |
+			   ((src & 0x0000FF00) << 8) |
+			   ((src & 0x000000FF) << 24);
+	}
+		
+	short DDSBigShort( short src )
+	{
+		return ((src & 0xFF00) >> 8) |
+			   ((src & 0x00FF) << 8);
+	}
+		
+	float DDSBigFloat( float src )
+	{
+		floatSwapUnion in,out;
+		in.f = src;
+		out.c[ 0 ] = in.c[ 3 ];
+		out.c[ 1 ] = in.c[ 2 ];
+		out.c[ 2 ] = in.c[ 1 ];
+		out.c[ 3 ] = in.c[ 0 ];
+		return out.f;
+	}
+
+#endif /*__BIG_ENDIAN__*/
+
+
+
+/*
+DDSDecodePixelFormat()
+determines which pixel format the dds texture is in
+*/
+
+static void DDSDecodePixelFormat( ddsBuffer_t *dds, ddsPF_t *pf )
+{
+	unsigned int	fourCC;
+	
+	
+	/* dummy check */
+	if(	dds == NULL || pf == NULL )
+		return;
+	
+	/* extract fourCC */
+	fourCC = dds->pixelFormat.fourCC;
+	
+	/* test it */
+	if( fourCC == 0 )
+		*pf = DDS_PF_ARGB8888;
+	else if( fourCC == *((unsigned int*) "DXT1") )
+		*pf = DDS_PF_DXT1;
+	else if( fourCC == *((unsigned int*) "DXT2") )
+		*pf = DDS_PF_DXT2;
+	else if( fourCC == *((unsigned int*) "DXT3") )
+		*pf = DDS_PF_DXT3;
+	else if( fourCC == *((unsigned int*) "DXT4") )
+		*pf = DDS_PF_DXT4;
+	else if( fourCC == *((unsigned int*) "DXT5") )
+		*pf = DDS_PF_DXT5;
+	else
+		*pf = DDS_PF_UNKNOWN;
+}
+
+
+
+/*
+DDSGetInfo()
+extracts relevant info from a dds texture, returns 0 on success
+*/
+
+int DDSGetInfo( ddsBuffer_t *dds, int *width, int *height, ddsPF_t *pf )
+{
+	/* dummy test */
+	if( dds == NULL )
+		return -1;
+	
+	/* test dds header */
+	if( *((int*) dds->magic) != *((int*) "DDS ") )
+		return -1;
+	if( DDSLittleLong( dds->size ) != 124 )
+		return -1;
+	
+	/* extract width and height */
+	if( width != NULL )
+		*width = DDSLittleLong( dds->width );
+	if( height != NULL )
+		*height = DDSLittleLong( dds->height );
+	
+	/* get pixel format */
+	DDSDecodePixelFormat( dds, pf );
+	
+	/* return ok */
+	return 0;
+}
+
+
+
+/*
+DDSGetColorBlockColors()
+extracts colors from a dds color block
+*/
+
+static void DDSGetColorBlockColors( ddsColorBlock_t *block, ddsColor_t colors[ 4 ] )
+{
+	unsigned short		word;
+
+	
+	/* color 0 */
+	word = DDSLittleShort( block->colors[ 0 ] );
+	colors[ 0 ].a = 0xff;
+	
+	/* extract rgb bits */
+	colors[ 0 ].b = (unsigned char) word;
+	colors[ 0 ].b <<= 3;
+	colors[ 0 ].b |= (colors[ 0 ].b >> 5);
+	word >>= 5;
+	colors[ 0 ].g = (unsigned char) word;
+	colors[ 0 ].g <<= 2;
+	colors[ 0 ].g |= (colors[ 0 ].g >> 5);
+	word >>= 6;
+	colors[ 0 ].r = (unsigned char) word;
+	colors[ 0 ].r <<= 3;
+	colors[ 0 ].r |= (colors[ 0 ].r >> 5);
+
+	/* same for color 1 */
+	word = DDSLittleShort( block->colors[ 1 ] );
+	colors[ 1 ].a = 0xff;
+	
+	/* extract rgb bits */
+	colors[ 1 ].b = (unsigned char) word;
+	colors[ 1 ].b <<= 3;
+	colors[ 1 ].b |= (colors[ 1 ].b >> 5);
+	word >>= 5;
+	colors[ 1 ].g = (unsigned char) word;
+	colors[ 1 ].g <<= 2;
+	colors[ 1 ].g |= (colors[ 1 ].g >> 5);
+	word >>= 6;
+	colors[ 1 ].r = (unsigned char) word;
+	colors[ 1 ].r <<= 3;
+	colors[ 1 ].r |= (colors[ 1 ].r >> 5);
+	
+	/* use this for all but the super-freak math method */
+	if( block->colors[ 0 ] > block->colors[ 1 ] )
+	{
+		/* four-color block: derive the other two colors.    
+		   00 = color 0, 01 = color 1, 10 = color 2, 11 = color 3
+		   these two bit codes correspond to the 2-bit fields 
+		   stored in the 64-bit block. */
+
+		word = ((unsigned short) colors[ 0 ].r * 2 + (unsigned short) colors[ 1 ].r ) / 3;
+											/* no +1 for rounding */
+											/* as bits have been shifted to 888 */
+		colors[ 2 ].r = (unsigned char) word;
+		word = ((unsigned short) colors[ 0 ].g * 2 + (unsigned short) colors[ 1 ].g) / 3;
+		colors[ 2 ].g = (unsigned char) word;
+		word = ((unsigned short) colors[ 0 ].b * 2 + (unsigned short) colors[ 1 ].b) / 3;
+		colors[ 2 ].b = (unsigned char) word;
+		colors[ 2 ].a = 0xff;
+
+		word = ((unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r * 2) / 3;
+		colors[ 3 ].r = (unsigned char) word;
+		word = ((unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g * 2) / 3;
+		colors[ 3 ].g = (unsigned char) word;
+		word = ((unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b * 2) / 3;
+		colors[ 3 ].b = (unsigned char) word;
+		colors[ 3 ].a = 0xff;
+	}
+	else
+	{
+		/* three-color block: derive the other color.
+		   00 = color 0, 01 = color 1, 10 = color 2,  
+		   11 = transparent.
+		   These two bit codes correspond to the 2-bit fields 
+		   stored in the 64-bit block */
+
+		word = ((unsigned short) colors[ 0 ].r + (unsigned short) colors[ 1 ].r) / 2;
+		colors[ 2 ].r = (unsigned char) word;
+		word = ((unsigned short) colors[ 0 ].g + (unsigned short) colors[ 1 ].g) / 2;
+		colors[ 2 ].g = (unsigned char) word;
+		word = ((unsigned short) colors[ 0 ].b + (unsigned short) colors[ 1 ].b) / 2;
+		colors[ 2 ].b = (unsigned char) word;
+		colors[ 2 ].a = 0xff;
+		
+		/* random color to indicate alpha */
+		colors[ 3 ].r = 0x00;
+		colors[ 3 ].g = 0xff;
+		colors[ 3 ].b = 0xff;
+		colors[ 3 ].a = 0x00;
+	}
+}
+
+
+
+/*
+DDSDecodeColorBlock()
+decodes a dds color block
+fixme: make endian-safe
+*/
+
+static void DDSDecodeColorBlock( unsigned int *pixel, ddsColorBlock_t *block, int width, unsigned int colors[ 4 ] )
+{
+	int				r, n;
+	unsigned int	bits;
+	unsigned int	masks[] = { 3, 12, 3 << 4, 3 << 6 };	/* bit masks = 00000011, 00001100, 00110000, 11000000 */
+	int				shift[] = { 0, 2, 4, 6 };
+	
+	
+	/* r steps through lines in y */
+	for( r = 0; r < 4; r++, pixel += (width - 4) )	/* no width * 4 as unsigned int ptr inc will * 4 */
+	{
+		/* width * 4 bytes per pixel per line, each j dxtc row is 4 lines of pixels */
+
+		/* n steps through pixels */
+		for( n = 0; n < 4; n++ )
+		{
+			bits = block->row[ r ] & masks[ n ];
+			bits >>= shift[ n ];
+
+			switch( bits )
+			{
+				case 0:
+					*pixel = colors[ 0 ];
+					pixel++;
+					break;
+
+				case 1:
+					*pixel = colors[ 1 ];
+					pixel++;
+					break;
+
+				case 2:
+					*pixel = colors[ 2 ];
+					pixel++;
+					break;
+
+				case 3:
+					*pixel = colors[ 3 ];
+					pixel++;
+					break;
+
+				default:
+					/* invalid */
+					pixel++;
+					break;
+			}
+		}
+	}
+}
+
+
+
+/*
+DDSDecodeAlphaExplicit()
+decodes a dds explicit alpha block
+*/
+
+static void DDSDecodeAlphaExplicit( unsigned int *pixel, ddsAlphaBlockExplicit_t *alphaBlock, int width, unsigned int alphaZero )
+{	
+	int				row, pix;
+	unsigned short	word;
+	ddsColor_t		color;
+	
+	
+	/* clear color */
+	color.r = 0;
+	color.g = 0;
+	color.b = 0;
+	
+	/* walk rows */
+	for( row = 0; row < 4; row++, pixel += (width - 4) )
+	{
+		word = DDSLittleShort( alphaBlock->row[ row ] );
+		
+		/* walk pixels */
+		for( pix = 0; pix < 4; pix++ )
+		{
+			/* zero the alpha bits of image pixel */
+			*pixel &= alphaZero;
+			color.a = word & 0x000F;
+			color.a = color.a | (color.a << 4);
+			*pixel |= *((unsigned int*) &color);
+			word >>= 4;		/* move next bits to lowest 4 */
+			pixel++;		/* move to next pixel in the row */
+
+		}
+	}
+}
+
+
+
+/*
+DDSDecodeAlpha3BitLinear()
+decodes interpolated alpha block
+*/
+
+static void DDSDecodeAlpha3BitLinear( unsigned int *pixel, ddsAlphaBlock3BitLinear_t *alphaBlock, int width, unsigned int alphaZero )
+{
+	
+	int					row, pix;
+	unsigned int		stuff;
+	unsigned char		bits[ 4 ][ 4 ];
+	unsigned short		alphas[ 8 ];
+	ddsColor_t			aColors[ 4 ][ 4 ];
+	
+	
+	/* get initial alphas */
+	alphas[ 0 ] = alphaBlock->alpha0;
+	alphas[ 1 ] = alphaBlock->alpha1;
+	
+	/* 8-alpha block */
+	if( alphas[ 0 ] > alphas[ 1 ] )
+	{
+		/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
+		alphas[ 2 ] = ( 6 * alphas[ 0 ] +     alphas[ 1 ]) / 7;	/* bit code 010 */
+		alphas[ 3 ] = ( 5 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 7;	/* bit code 011 */
+		alphas[ 4 ] = ( 4 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 7;	/* bit code 100 */
+		alphas[ 5 ] = ( 3 * alphas[ 0 ] + 4 * alphas[ 1 ]) / 7;	/* bit code 101 */
+		alphas[ 6 ] = ( 2 * alphas[ 0 ] + 5 * alphas[ 1 ]) / 7;	/* bit code 110 */
+		alphas[ 7 ] = (     alphas[ 0 ] + 6 * alphas[ 1 ]) / 7;	/* bit code 111 */
+	}
+	
+	/* 6-alpha block */
+	else
+	{ 
+		/* 000 = alpha_0, 001 = alpha_1, others are interpolated */
+		alphas[ 2 ] = (4 * alphas[ 0 ] +     alphas[ 1 ]) / 5;	/* bit code 010 */
+		alphas[ 3 ] = (3 * alphas[ 0 ] + 2 * alphas[ 1 ]) / 5;	/* bit code 011 */
+		alphas[ 4 ] = (2 * alphas[ 0 ] + 3 * alphas[ 1 ]) / 5;	/* bit code 100 */
+		alphas[ 5 ] = (    alphas[ 0 ] + 4 * alphas[ 1 ]) / 5;	/* bit code 101 */
+		alphas[ 6 ] = 0;										/* bit code 110 */
+		alphas[ 7 ] = 255;										/* bit code 111 */
+	}
+	
+	/* decode 3-bit fields into array of 16 bytes with same value */
+	
+	/* first two rows of 4 pixels each */
+	stuff = *((unsigned int*) &(alphaBlock->stuff[ 0 ]));
+	
+	bits[ 0 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 0 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 0 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 0 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 1 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 1 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 1 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 1 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
+	
+	/* last two rows */
+	stuff = *((unsigned int*) &(alphaBlock->stuff[ 3 ])); /* last 3 bytes */
+	
+	bits[ 2 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 2 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 2 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 2 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 3 ][ 0 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 3 ][ 1 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 3 ][ 2 ] = (unsigned char) (stuff & 0x00000007);
+	stuff >>= 3;
+	bits[ 3 ][ 3 ] = (unsigned char) (stuff & 0x00000007);
+	
+	/* decode the codes into alpha values */
+	for( row = 0; row < 4; row++ )
+	{
+		for( pix=0; pix < 4; pix++ )
+		{
+			aColors[ row ][ pix ].r = 0;
+			aColors[ row ][ pix ].g = 0;
+			aColors[ row ][ pix ].b = 0;
+			aColors[ row ][ pix ].a = (unsigned char) alphas[ bits[ row ][ pix ] ];
+		}
+	}
+	
+	/* write out alpha values to the image bits */
+	for( row = 0; row < 4; row++, pixel += width-4 )
+	{
+		for( pix = 0; pix < 4; pix++ )
+		{
+			/* zero the alpha bits of image pixel */
+			*pixel &= alphaZero;
+			
+			/* or the bits into the prev. nulled alpha */
+			*pixel |= *((unsigned int*) &(aColors[ row ][ pix ]));	
+			pixel++;
+		}
+	}
+}
+
+
+
+/*
+DDSDecompressDXT1()
+decompresses a dxt1 format texture
+*/
+
+static int DDSDecompressDXT1( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
+{
+	int				x, y, xBlocks, yBlocks;
+	unsigned int	*pixel;
+	ddsColorBlock_t	*block;
+	ddsColor_t		colors[ 4 ];
+	
+	
+	/* setup */
+	xBlocks = width / 4;
+	yBlocks = height / 4;
+	
+	/* walk y */
+	for( y = 0; y < yBlocks; y++ )
+	{
+		/* 8 bytes per block */
+		block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 8);
+
+		/* walk x */
+		for( x = 0; x < xBlocks; x++, block++ )
+		{
+			DDSGetColorBlockColors( block, colors );
+			pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
+			DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
+		}
+	}
+	
+	/* return ok */
+	return 0;
+}
+
+
+
+/*
+DDSDecompressDXT3()
+decompresses a dxt3 format texture
+*/
+
+static int DDSDecompressDXT3( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
+{
+	int						x, y, xBlocks, yBlocks;
+	unsigned int			*pixel, alphaZero;
+	ddsColorBlock_t			*block;
+	ddsAlphaBlockExplicit_t	*alphaBlock;
+	ddsColor_t				colors[ 4 ];
+
+
+	/* setup */
+	xBlocks = width / 4;
+	yBlocks = height / 4;
+	
+	/* create zero alpha */
+	colors[ 0 ].a = 0;
+	colors[ 0 ].r = 0xFF;
+	colors[ 0 ].g = 0xFF;
+	colors[ 0 ].b = 0xFF;
+	alphaZero = *((unsigned int*) &colors[ 0 ]);
+	
+	/* walk y */
+	for( y = 0; y < yBlocks; y++ )
+	{
+		/* 8 bytes per block, 1 block for alpha, 1 block for color */
+		block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
+
+		/* walk x */
+		for( x = 0; x < xBlocks; x++, block++ )
+		{
+			/* get alpha block */
+			alphaBlock = (ddsAlphaBlockExplicit_t*) block;
+			
+			/* get color block */
+			block++;
+			DDSGetColorBlockColors( block, colors );
+			
+			/* decode color block */
+			pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
+			DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
+			
+			/* overwrite alpha bits with alpha block */
+			DDSDecodeAlphaExplicit( pixel, alphaBlock, width, alphaZero );
+		}
+	}
+	
+	/* return ok */
+	return 0;
+}
+
+
+
+/*
+DDSDecompressDXT5()
+decompresses a dxt5 format texture
+*/
+
+static int DDSDecompressDXT5( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
+{
+	int							x, y, xBlocks, yBlocks;
+	unsigned int				*pixel, alphaZero;
+	ddsColorBlock_t				*block;
+	ddsAlphaBlock3BitLinear_t	*alphaBlock;
+	ddsColor_t					colors[ 4 ];
+
+
+	/* setup */
+	xBlocks = width / 4;
+	yBlocks = height / 4;
+	
+	/* create zero alpha */
+	colors[ 0 ].a = 0;
+	colors[ 0 ].r = 0xFF;
+	colors[ 0 ].g = 0xFF;
+	colors[ 0 ].b = 0xFF;
+	alphaZero = *((unsigned int*) &colors[ 0 ]);
+	
+	/* walk y */
+	for( y = 0; y < yBlocks; y++ )
+	{
+		/* 8 bytes per block, 1 block for alpha, 1 block for color */
+		block = (ddsColorBlock_t*) ((unsigned int) dds->data + y * xBlocks * 16);
+
+		/* walk x */
+		for( x = 0; x < xBlocks; x++, block++ )
+		{
+			/* get alpha block */
+			alphaBlock = (ddsAlphaBlock3BitLinear_t*) block;
+			
+			/* get color block */
+			block++;
+			DDSGetColorBlockColors( block, colors );
+			
+			/* decode color block */
+			pixel = (unsigned int*) (pixels + x * 16 + (y * 4) * width * 4);
+			DDSDecodeColorBlock( pixel, block, width, (unsigned int*) colors );
+			
+			/* overwrite alpha bits with alpha block */
+			DDSDecodeAlpha3BitLinear( pixel, alphaBlock, width, alphaZero );
+		}
+	}
+	
+	/* return ok */
+	return 0;
+}
+
+
+
+/*
+DDSDecompressDXT2()
+decompresses a dxt2 format texture (fixme: un-premultiply alpha)
+*/
+
+static int DDSDecompressDXT2( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
+{
+	int		r;
+	
+	
+	/* decompress dxt3 first */
+	r = DDSDecompressDXT3( dds, width, height, pixels );
+	
+	/* return to sender */
+	return r;
+}
+
+
+
+/*
+DDSDecompressDXT4()
+decompresses a dxt4 format texture (fixme: un-premultiply alpha)
+*/
+
+static int DDSDecompressDXT4( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
+{
+	int		r;
+	
+	
+	/* decompress dxt5 first */
+	r = DDSDecompressDXT5( dds, width, height, pixels );
+	
+	/* return to sender */
+	return r;
+}
+
+
+
+/*
+DDSDecompressARGB8888()
+decompresses an argb 8888 format texture
+*/
+
+static int DDSDecompressARGB8888( ddsBuffer_t *dds, int width, int height, unsigned char *pixels )
+{
+	int							x, y;
+	unsigned char				*in, *out;
+	
+	
+	/* setup */
+	in = dds->data;
+	out = pixels;
+	
+	/* walk y */
+	for( y = 0; y < height; y++ )
+	{
+		/* walk x */
+		for( x = 0; x < width; x++ )
+		{
+			*out++ = *in++;
+			*out++ = *in++;
+			*out++ = *in++;
+			*out++ = *in++;
+		}
+	}
+	
+	/* return ok */
+	return 0;
+}
+
+
+
+/*
+DDSDecompress()
+decompresses a dds texture into an rgba image buffer, returns 0 on success
+*/
+
+int DDSDecompress( ddsBuffer_t *dds, unsigned char *pixels )
+{
+	int			width, height, r;
+	ddsPF_t		pf;
+	
+	
+	/* get dds info */
+	r = DDSGetInfo( dds, &width, &height, &pf );
+	if( r )
+		return r;
+	
+	/* decompress */
+	switch( pf )
+	{
+		case DDS_PF_ARGB8888:
+			/* fixme: support other [a]rgb formats */
+			r = DDSDecompressARGB8888( dds, width, height, pixels );
+			break;
+		
+		case DDS_PF_DXT1:
+			r = DDSDecompressDXT1( dds, width, height, pixels );
+			break;
+		
+		case DDS_PF_DXT2:
+			r = DDSDecompressDXT2( dds, width, height, pixels );
+			break;
+		
+		case DDS_PF_DXT3:
+			r = DDSDecompressDXT3( dds, width, height, pixels );	
+			break;
+		
+		case DDS_PF_DXT4:
+			r = DDSDecompressDXT4( dds, width, height, pixels );
+			break;
+		
+		case DDS_PF_DXT5:
+			r = DDSDecompressDXT5( dds, width, height, pixels );		
+			break;
+		
+		default:
+		case DDS_PF_UNKNOWN:
+			memset( pixels, 0xFF, width * height * 4 );
+			r = -1;
+			break;
+	}
+	
+	/* return to sender */
+	return r;
+}
+
diff --git a/libs/igl_to_qgl.h b/libs/igl_to_qgl.h
index a71ecd2e..633cf478 100644
--- a/libs/igl_to_qgl.h
+++ b/libs/igl_to_qgl.h
@@ -1,806 +1,806 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-IGL tp QGL mapping header
-Copyright (C) 2002 Splash Damage Ltd.
-*/
-
-#ifndef _IGL_TO_QGL_H_
-#define _IGL_TO_QGL_H_
-
-#ifdef _WIN32
-#include <wtypes.h>
-#endif
-
-enum VIEWTYPE {YZ, XZ, XY};
-
-#include "igl.h"
-
-#ifndef APIENTRY
- #define APIENTRY
-#endif
-
-void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
-void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
-GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
-void ( APIENTRY * qglArrayElement )(GLint i);
-void ( APIENTRY * qglBegin )(GLenum mode);
-void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
-void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
-void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
-void ( APIENTRY * qglCallList )(GLuint list);
-void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
-void ( APIENTRY * qglClear )(GLbitfield mask);
-void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-void ( APIENTRY * qglClearDepth )(GLclampd depth);
-void ( APIENTRY * qglClearIndex )(GLfloat c);
-void ( APIENTRY * qglClearStencil )(GLint s);
-void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
-void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
-void ( APIENTRY * qglColor3bv )(const GLbyte *v);
-void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
-void ( APIENTRY * qglColor3dv )(const GLdouble *v);
-void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
-void ( APIENTRY * qglColor3fv )(const GLfloat *v);
-void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
-void ( APIENTRY * qglColor3iv )(const GLint *v);
-void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
-void ( APIENTRY * qglColor3sv )(const GLshort *v);
-void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
-void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
-void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
-void ( APIENTRY * qglColor3uiv )(const GLuint *v);
-void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
-void ( APIENTRY * qglColor3usv )(const GLushort *v);
-void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
-void ( APIENTRY * qglColor4bv )(const GLbyte *v);
-void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
-void ( APIENTRY * qglColor4dv )(const GLdouble *v);
-void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void ( APIENTRY * qglColor4fv )(const GLfloat *v);
-void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
-void ( APIENTRY * qglColor4iv )(const GLint *v);
-void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
-void ( APIENTRY * qglColor4sv )(const GLshort *v);
-void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
-void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
-void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
-void ( APIENTRY * qglColor4uiv )(const GLuint *v);
-void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
-void ( APIENTRY * qglColor4usv )(const GLushort *v);
-void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
-void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
-void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
-void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-void ( APIENTRY * qglCullFace )(GLenum mode);
-void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
-void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
-void ( APIENTRY * qglDepthFunc )(GLenum func);
-void ( APIENTRY * qglDepthMask )(GLboolean flag);
-void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
-void ( APIENTRY * qglDisable )(GLenum cap);
-void ( APIENTRY * qglDisableClientState )(GLenum array);
-void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
-void ( APIENTRY * qglDrawBuffer )(GLenum mode);
-void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
-void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
-void ( APIENTRY * qglEnable )(GLenum cap);
-void ( APIENTRY * qglEnableClientState )(GLenum array);
-void ( APIENTRY * qglEnd )(void);
-void ( APIENTRY * qglEndList )(void);
-void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
-void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
-void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
-void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
-void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
-void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
-void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
-void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
-void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
-void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
-void ( APIENTRY * qglEvalPoint1 )(GLint i);
-void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
-void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
-void ( APIENTRY * qglFinish )(void);
-void ( APIENTRY * qglFlush )(void);
-void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
-void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
-void ( APIENTRY * qglFrontFace )(GLenum mode);
-void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-GLuint ( APIENTRY * qglGenLists )(GLsizei range);
-void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
-void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
-void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
-void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
-GLenum ( APIENTRY * qglGetError )(void);
-void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
-void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
-void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
-void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
-void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
-void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
-void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
-void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
-void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
-const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
-void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
-void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
-void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
-void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
-void ( APIENTRY * qglIndexMask )(GLuint mask);
-void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglIndexd )(GLdouble c);
-void ( APIENTRY * qglIndexdv )(const GLdouble *c);
-void ( APIENTRY * qglIndexf )(GLfloat c);
-void ( APIENTRY * qglIndexfv )(const GLfloat *c);
-void ( APIENTRY * qglIndexi )(GLint c);
-void ( APIENTRY * qglIndexiv )(const GLint *c);
-void ( APIENTRY * qglIndexs )(GLshort c);
-void ( APIENTRY * qglIndexsv )(const GLshort *c);
-void ( APIENTRY * qglIndexub )(GLubyte c);
-void ( APIENTRY * qglIndexubv )(const GLubyte *c);
-void ( APIENTRY * qglInitNames )(void);
-void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
-GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
-GLboolean ( APIENTRY * qglIsList )(GLuint list);
-GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
-void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
-void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
-void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
-void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
-void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
-void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
-void ( APIENTRY * qglLineWidth )(GLfloat width);
-void ( APIENTRY * qglListBase )(GLuint base);
-void ( APIENTRY * qglLoadIdentity )(void);
-void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
-void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
-void ( APIENTRY * qglLoadName )(GLuint name);
-void ( APIENTRY * qglLogicOp )(GLenum opcode);
-void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
-void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
-void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
-void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
-void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
-void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
-void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
-void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
-void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
-void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
-void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
-void ( APIENTRY * qglMatrixMode )(GLenum mode);
-void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
-void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
-void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
-void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
-void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
-void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
-void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
-void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
-void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
-void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
-void ( APIENTRY * qglNormal3iv )(const GLint *v);
-void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
-void ( APIENTRY * qglNormal3sv )(const GLshort *v);
-void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-void ( APIENTRY * qglPassThrough )(GLfloat token);
-void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
-void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
-void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
-void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
-void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
-void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
-void ( APIENTRY * qglPointSize )(GLfloat size);
-void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
-void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
-void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
-void ( APIENTRY * qglPopAttrib )(void);
-void ( APIENTRY * qglPopClientAttrib )(void);
-void ( APIENTRY * qglPopMatrix )(void);
-void ( APIENTRY * qglPopName )(void);
-void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
-void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
-void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
-void ( APIENTRY * qglPushMatrix )(void);
-void ( APIENTRY * qglPushName )(GLuint name);
-void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
-void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
-void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
-void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
-void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
-void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
-void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
-void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
-void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
-void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
-void ( APIENTRY * qglReadBuffer )(GLenum mode);
-void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
-void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
-void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
-void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
-void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
-void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
-void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
-void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
-void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
-GLint ( APIENTRY * qglRenderMode )(GLenum mode);
-void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
-void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
-void ( APIENTRY * qglShadeModel )(GLenum mode);
-void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
-void ( APIENTRY * qglStencilMask )(GLuint mask);
-void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
-void ( APIENTRY * qglTexCoord1d )(GLdouble s);
-void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord1f )(GLfloat s);
-void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord1i )(GLint s);
-void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord1s )(GLshort s);
-void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
-void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
-void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
-void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
-void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
-void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
-void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
-void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
-void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
-void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
-void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
-void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
-void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
-void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
-void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
-void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
-void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
-void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
-void ( APIENTRY * qglVertex2iv )(const GLint *v);
-void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
-void ( APIENTRY * qglVertex2sv )(const GLshort *v);
-void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
-void ( APIENTRY * qglVertex3iv )(const GLint *v);
-void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
-void ( APIENTRY * qglVertex3sv )(const GLshort *v);
-void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
-void ( APIENTRY * qglVertex4iv )(const GLint *v);
-void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-void ( APIENTRY * qglVertex4sv )(const GLshort *v);
-void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
-
-void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
-void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
-void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
-
-void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
-void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
-
-void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
-void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
-void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
-
-extern "C" void InitIglToQgl( _QERQglTable *g_QglTable )
-{
-/*
-  // initialze the qgl functions
-  qglAccum = NULL;
-  qglAlphaFunc = g_QglTable->m_pfn_qglAlphaFunc;
-  qglAreTexturesResident = NULL;
-  qglArrayElement = NULL;
-  qglBegin = g_QglTable->m_pfn_qglBegin;
-  qglBindTexture = g_QglTable->m_pfn_qglBindTexture;
-  qglBitmap = NULL;
-  qglBlendFunc = g_QglTable->m_pfn_qglBlendFunc;
-  qglCallList = g_QglTable->m_pfn_qglCallList;
-  qglCallLists = g_QglTable->m_pfn_qglCallLists;
-  qglClear = g_QglTable->m_pfn_qglClear;
-  qglClearAccum = NULL;
-  qglClearColor = g_QglTable->m_pfn_qglClearColor;
-  qglClearDepth = g_QglTable->m_pfn_qglClearDepth;
-  qglClearIndex = NULL;
-  qglClearStencil = NULL;
-  qglClipPlane = NULL;
-  qglColor3b = NULL;
-  qglColor3bv = NULL;
-  qglColor3d = NULL;
-  qglColor3dv = NULL;
-  qglColor3f = g_QglTable->m_pfn_qglColor3f;
-  qglColor3fv = g_QglTable->m_pfn_qglColor3fv;
-  qglColor3i = NULL;
-  qglColor3iv = NULL;
-  qglColor3s = NULL;
-  qglColor3sv = NULL;
-  qglColor3ub = NULL;
-  qglColor3ubv = NULL;
-  qglColor3ui = NULL;
-  qglColor3uiv = NULL;
-  qglColor3us = NULL;
-  qglColor3usv = NULL;
-  qglColor4b = NULL;
-  qglColor4bv = NULL;
-  qglColor4d = NULL;
-  qglColor4dv = NULL;
-  qglColor4f = g_QglTable->m_pfn_qglColor4f;
-  qglColor4fv = g_QglTable->m_pfn_qglColor4fv;
-  qglColor4i = NULL;
-  qglColor4iv = NULL;
-  qglColor4s = NULL;
-  qglColor4sv = NULL;
-  qglColor4ub = NULL;
-  qglColor4ubv = NULL;
-  qglColor4ui = NULL;
-  qglColor4uiv = NULL;
-  qglColor4us = NULL;
-  qglColor4usv = NULL;
-  qglColorMask = NULL;
-  qglColorMaterial = NULL;
-  qglColorPointer = NULL;
-  qglCopyPixels = NULL;
-  qglCopyTexImage1D = NULL;
-  qglCopyTexImage2D = NULL;
-  qglCopyTexSubImage1D = NULL;
-  qglCopyTexSubImage2D = NULL;
-  qglCullFace = g_QglTable->m_pfn_qglCullFace;
-  qglDeleteLists = g_QglTable->m_pfn_qglDeleteLists;
-  qglDeleteTextures = g_QglTable->m_pfn_qglDeleteTextures;
-  qglDepthFunc = g_QglTable->m_pfn_qglDepthFunc;
-  qglDepthMask = g_QglTable->m_pfn_qglDepthMask;
-  qglDepthRange = NULL;
-  qglDisable = g_QglTable->m_pfn_qglDisable;
-  qglDisableClientState = NULL;
-  qglDrawArrays = NULL;
-  qglDrawBuffer = NULL;
-  qglDrawElements = NULL;
-  qglDrawPixels = NULL;
-  qglEdgeFlag = NULL;
-  qglEdgeFlagPointer = NULL;
-  qglEdgeFlagv = NULL;
-  qglEnable = g_QglTable->m_pfn_qglEnable;
-  qglEnableClientState = NULL;
-  qglEnd = g_QglTable->m_pfn_qglEnd;
-  qglEndList = g_QglTable->m_pfn_qglEndList;
-  qglEvalCoord1d = NULL;
-  qglEvalCoord1dv = NULL;
-  qglEvalCoord1f  = NULL;
-  qglEvalCoord1fv = NULL;
-  qglEvalCoord2d = NULL;
-  qglEvalCoord2dv = NULL;
-  qglEvalCoord2f= NULL;
-  qglEvalCoord2fv = NULL;
-  qglEvalMesh1 = NULL;
-  qglEvalMesh2 = NULL;
-  qglEvalPoint1 = NULL;
-  qglEvalPoint2 = NULL;
-  qglFeedbackBuffer = NULL;
-  qglFinish = NULL;
-  qglFlush = NULL;
-  qglFogf = g_QglTable->m_pfn_qglFogf;
-  qglFogfv = g_QglTable->m_pfn_qglFogfv;
-  qglFogi = g_QglTable->m_pfn_qglFogi;
-  qglFogiv = NULL;
-  qglFrontFace = NULL;
-  qglFrustum = NULL;
-  qglGenLists = g_QglTable->m_pfn_qglGenLists;
-  qglGenTextures = g_QglTable->m_pfn_qglGenTextures;
-  qglGetBooleanv = NULL;
-  qglGetClipPlane = NULL;
-  qglGetDoublev = NULL;
-  qglGetError = NULL;
-  qglGetFloatv = NULL;
-  qglGetIntegerv = NULL;
-  qglGetLightfv = NULL;
-  qglGetLightiv = NULL;
-  qglGetMapdv = NULL;
-  qglGetMapfv = NULL;
-  qglGetMapiv = NULL;
-  qglGetMaterialfv = NULL;
-  qglGetMaterialiv = NULL;
-  qglGetPixelMapfv = NULL;
-  qglGetPixelMapuiv = NULL;
-  qglGetPixelMapusv = NULL;
-  qglGetPointerv = NULL;
-  qglGetPolygonStipple = NULL;
-  qglGetString = NULL;
-  qglGetTexEnvfv = NULL;
-  qglGetTexEnviv = NULL;
-  qglGetTexGendv = NULL;
-  qglGetTexGenfv = NULL;
-  qglGetTexGeniv = NULL;
-  qglGetTexImage = NULL;
-  qglGetTexLevelParameterfv = NULL;
-  qglGetTexLevelParameteriv = NULL;
-  qglGetTexParameterfv = NULL;
-  qglGetTexParameteriv = NULL;
-  qglHint = g_QglTable->m_pfn_qglHint;
-  qglIndexMask = NULL;
-  qglIndexPointer = NULL;
-  qglIndexd = NULL;
-  qglIndexdv = NULL;
-  qglIndexf = NULL;
-  qglIndexfv = NULL;
-  qglIndexi = NULL;
-  qglIndexiv = NULL;
-  qglIndexs = NULL;
-  qglIndexsv = NULL;
-  qglIndexub = NULL;
-  qglIndexubv = NULL;
-  qglInitNames = NULL;
-  qglInterleavedArrays = NULL;
-  qglIsEnabled = NULL;
-  qglIsList = NULL;
-  qglIsTexture = NULL;
-  qglLightModelf = NULL;
-  qglLightModelfv = NULL;
-  qglLightModeli = NULL;
-  qglLightModeliv = NULL;
-  qglLightf = NULL;
-  qglLightfv = g_QglTable->m_pfn_qglLightfv;
-  qglLighti = NULL;
-  qglLightiv = NULL;
-  qglLineStipple = g_QglTable->m_pfn_qglLineStipple;
-  qglLineWidth = g_QglTable->m_pfn_qglLineWidth;
-  qglListBase = g_QglTable->m_pfn_qglListBase;
-  qglLoadIdentity = g_QglTable->m_pfn_qglLoadIdentity;
-  qglLoadMatrixd = NULL;
-  qglLoadMatrixf = NULL;
-  qglLoadName = NULL;
-  qglLogicOp = NULL;
-  qglMap1d = NULL;
-  qglMap1f = NULL;
-  qglMap2d = NULL;
-  qglMap2f = NULL;
-  qglMapGrid1d = NULL;
-  qglMapGrid1f = NULL;
-  qglMapGrid2d = NULL;
-  qglMapGrid2f = NULL;
-  qglMaterialf = g_QglTable->m_pfn_qglMaterialf;
-  qglMaterialfv = g_QglTable->m_pfn_qglMaterialfv;
-  qglMateriali = NULL;
-  qglMaterialiv = NULL;
-  qglMatrixMode = g_QglTable->m_pfn_qglMatrixMode;
-  qglMultMatrixd = NULL;
-  qglMultMatrixf = g_QglTable->m_pfn_qglMultMatrixf;
-  qglNewList = g_QglTable->m_pfn_qglNewList;
-  qglNormal3b = NULL;
-  qglNormal3bv = NULL;
-  qglNormal3d = NULL;
-  qglNormal3dv = NULL;
-  qglNormal3f = g_QglTable->m_pfn_qglNormal3f;
-  qglNormal3fv = g_QglTable->m_pfn_qglNormal3fv;
-  qglNormal3i = NULL;
-  qglNormal3iv = NULL;
-  qglNormal3s = NULL;
-  qglNormal3sv = NULL;
-  qglNormalPointer = NULL;
-  qglOrtho = g_QglTable->m_pfn_qglOrtho;
-  qglPassThrough = NULL;
-  qglPixelMapfv = NULL;
-  qglPixelMapuiv = NULL;
-  qglPixelMapusv = NULL;
-  qglPixelStoref = NULL;
-  qglPixelStorei = NULL;
-  qglPixelTransferf = NULL;
-  qglPixelTransferi = NULL;
-  qglPixelZoom = NULL;
-  qglPointSize = g_QglTable->m_pfn_qglPointSize;
-  qglPolygonMode = g_QglTable->m_pfn_qglPolygonMode;
-  qglPolygonOffset = NULL;
-  qglPolygonStipple = NULL;
-  qglPopAttrib = g_QglTable->m_pfn_qglPopAttrib;
-  qglPopClientAttrib = NULL;
-  qglPopMatrix = g_QglTable->m_pfn_qglPopMatrix;
-  qglPopName = NULL;
-  qglPrioritizeTextures = NULL;
-  qglPushAttrib = g_QglTable->m_pfn_qglPushAttrib;
-  qglPushClientAttrib = NULL;
-  qglPushMatrix = g_QglTable->m_pfn_qglPushMatrix;
-  qglPushName = NULL;
-  qglRasterPos2d = NULL;
-  qglRasterPos2dv = NULL;
-  qglRasterPos2f = NULL;
-  qglRasterPos2fv = NULL;
-  qglRasterPos2i = NULL;
-  qglRasterPos2iv = NULL;
-  qglRasterPos2s = NULL;
-  qglRasterPos2sv = NULL;
-  qglRasterPos3d = NULL;
-  qglRasterPos3dv = NULL;
-  qglRasterPos3f = NULL;
-  qglRasterPos3fv = g_QglTable->m_pfn_qglRasterPos3fv;
-  qglRasterPos3i = NULL;
-  qglRasterPos3iv = NULL;
-  qglRasterPos3s = NULL;
-  qglRasterPos3sv = NULL;
-  qglRasterPos4d = NULL;
-  qglRasterPos4dv = NULL;
-  qglRasterPos4f = NULL;
-  qglRasterPos4fv = NULL;
-  qglRasterPos4i = NULL;
-  qglRasterPos4iv = NULL;
-  qglRasterPos4s = NULL;
-  qglRasterPos4sv = NULL;
-  qglReadBuffer = NULL;
-  qglReadPixels = NULL;
-  qglRectd = NULL;
-  qglRectdv = NULL;
-  qglRectf = NULL;
-  qglRectfv = NULL;
-  qglRecti = NULL;
-  qglRectiv = NULL;
-  qglRects = NULL;
-  qglRectsv = NULL;
-  qglRenderMode = NULL;
-  qglRotated = g_QglTable->m_pfn_qglRotated;
-  qglRotatef = g_QglTable->m_pfn_qglRotatef;
-  qglScaled = NULL;
-  qglScalef = g_QglTable->m_pfn_qglScalef;
-  qglScissor = g_QglTable->m_pfn_qglScissor;
-  qglSelectBuffer = NULL;
-  qglShadeModel = g_QglTable->m_pfn_qglShadeModel;
-  qglStencilFunc = NULL;
-  qglStencilMask = NULL;
-  qglStencilOp = NULL;
-  qglTexCoord1d = NULL;
-  qglTexCoord1dv = NULL;
-  qglTexCoord1f = NULL;
-  qglTexCoord1fv = NULL;
-  qglTexCoord1i = NULL;
-  qglTexCoord1iv = NULL;
-  qglTexCoord1s = NULL;
-  qglTexCoord1sv = NULL;
-  qglTexCoord2d = NULL;
-  qglTexCoord2dv = NULL;
-  qglTexCoord2f = g_QglTable->m_pfn_qglTexCoord2f;
-  qglTexCoord2fv = g_QglTable->m_pfn_qglTexCoord2fv;
-  qglTexCoord2i = NULL;
-  qglTexCoord2iv = NULL;
-  qglTexCoord2s = NULL;
-  qglTexCoord2sv = NULL;
-  qglTexCoord3d = NULL;
-  qglTexCoord3dv = NULL;
-  qglTexCoord3f = NULL;
-  qglTexCoord3fv = NULL;
-  qglTexCoord3i = NULL;
-  qglTexCoord3iv = NULL;
-  qglTexCoord3s = NULL;
-  qglTexCoord3sv = NULL;
-  qglTexCoord4d = NULL;
-  qglTexCoord4dv = NULL;
-  qglTexCoord4f = NULL;
-  qglTexCoord4fv = NULL;
-  qglTexCoord4i = NULL;
-  qglTexCoord4iv = NULL;
-  qglTexCoord4s = NULL;
-  qglTexCoord4sv = NULL;
-  qglTexCoordPointer = NULL;
-  qglTexEnvf = g_QglTable->m_pfn_qglTexEnvf;
-  qglTexEnvfv = NULL;
-  qglTexEnvi = NULL;
-  qglTexEnviv = NULL;
-  qglTexGend = NULL;
-  qglTexGendv = NULL;
-  qglTexGenf = g_QglTable->m_pfn_qglTexGenf;
-  qglTexGenfv = NULL;
-  qglTexGeni = NULL;
-  qglTexGeniv = NULL;
-  qglTexImage1D = g_QglTable->m_pfn_qglTexImage1D;
-  qglTexImage2D = g_QglTable->m_pfn_qglTexImage2D;
-  qglTexParameterf = g_QglTable->m_pfn_qglTexParameterf;
-  qglTexParameterfv = g_QglTable->m_pfn_qglTexParameterfv;
-  qglTexParameteri = g_QglTable->m_pfn_qglTexParameteri;
-  qglTexParameteriv = g_QglTable->m_pfn_qglTexParameteriv;
-  qglTexSubImage1D = g_QglTable->m_pfn_qglTexSubImage1D;
-  qglTexSubImage2D = g_QglTable->m_pfn_qglTexSubImage2D;
-  qglTranslated = g_QglTable->m_pfn_qglTranslated;
-  qglTranslatef = g_QglTable->m_pfn_qglTranslatef;
-  qglVertex2d = NULL;
-  qglVertex2dv = NULL;
-  qglVertex2f = g_QglTable->m_pfn_qglVertex2f;
-  qglVertex2fv = NULL;
-  qglVertex2i = NULL;
-  qglVertex2iv = NULL;
-  qglVertex2s = NULL;
-  qglVertex2sv = NULL;
-  qglVertex3d = NULL;
-  qglVertex3dv = NULL;
-  qglVertex3f = g_QglTable->m_pfn_qglVertex3f;
-  qglVertex3fv = g_QglTable->m_pfn_qglVertex3fv;
-  qglVertex3i = NULL;
-  qglVertex3iv = NULL;
-  qglVertex3s = NULL;
-  qglVertex3sv = NULL;
-  qglVertex4d = NULL;
-  qglVertex4dv = NULL;
-  qglVertex4f = NULL;
-  qglVertex4fv = NULL;
-  qglVertex4i = NULL;
-  qglVertex4iv = NULL;
-  qglVertex4s = NULL;
-  qglVertex4sv = NULL;
-  qglVertexPointer = NULL;
-  qglViewport = g_QglTable->m_pfn_qglViewport;
-
-  qglPointParameterfEXT = NULL;
-  qglPointParameterfvEXT = NULL;
-  qglColorTableEXT = NULL;
-
-  qglMTexCoord2fSGIS = NULL;
-  qglSelectTextureSGIS = NULL;
-
-  qglActiveTextureARB = NULL;
-  qglClientActiveTextureARB = NULL;
-  qglMultiTexCoord1dARB = NULL;
-  qglMultiTexCoord1dvARB = NULL;
-  qglMultiTexCoord1fARB = NULL;
-  qglMultiTexCoord1fvARB = NULL;
-  qglMultiTexCoord1iARB = NULL;
-  qglMultiTexCoord1ivARB = NULL;
-  qglMultiTexCoord1sARB = NULL;
-  qglMultiTexCoord1svARB = NULL;
-  qglMultiTexCoord2dARB = NULL;
-  qglMultiTexCoord2dvARB = NULL;
-  qglMultiTexCoord2fARB = NULL;
-  qglMultiTexCoord2fvARB = NULL;
-  qglMultiTexCoord2iARB = NULL;
-  qglMultiTexCoord2ivARB = NULL;
-  qglMultiTexCoord2sARB = NULL;
-  qglMultiTexCoord2svARB = NULL;
-  qglMultiTexCoord3dARB = NULL;
-  qglMultiTexCoord3dvARB = NULL;
-  qglMultiTexCoord3fARB = NULL;
-  qglMultiTexCoord3fvARB = NULL;
-  qglMultiTexCoord3iARB = NULL;
-  qglMultiTexCoord3ivARB = NULL;
-  qglMultiTexCoord3sARB = NULL;
-  qglMultiTexCoord3svARB = NULL;
-  qglMultiTexCoord4dARB = NULL;
-  qglMultiTexCoord4dvARB = NULL;
-  qglMultiTexCoord4fARB = NULL;
-  qglMultiTexCoord4fvARB = NULL;
-  qglMultiTexCoord4iARB = NULL;
-  qglMultiTexCoord4ivARB = NULL;
-  qglMultiTexCoord4sARB = NULL;
-  qglMultiTexCoord4svARB = NULL;
-*/
-}
-
-#endif // _IGL_TO_QGL_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+IGL tp QGL mapping header
+Copyright (C) 2002 Splash Damage Ltd.
+*/
+
+#ifndef _IGL_TO_QGL_H_
+#define _IGL_TO_QGL_H_
+
+#ifdef _WIN32
+#include <wtypes.h>
+#endif
+
+enum VIEWTYPE {YZ, XZ, XY};
+
+#include "igl.h"
+
+#ifndef APIENTRY
+ #define APIENTRY
+#endif
+
+void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
+void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
+GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+void ( APIENTRY * qglArrayElement )(GLint i);
+void ( APIENTRY * qglBegin )(GLenum mode);
+void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
+void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
+void ( APIENTRY * qglCallList )(GLuint list);
+void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+void ( APIENTRY * qglClear )(GLbitfield mask);
+void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+void ( APIENTRY * qglClearDepth )(GLclampd depth);
+void ( APIENTRY * qglClearIndex )(GLfloat c);
+void ( APIENTRY * qglClearStencil )(GLint s);
+void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
+void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+void ( APIENTRY * qglColor3bv )(const GLbyte *v);
+void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+void ( APIENTRY * qglColor3dv )(const GLdouble *v);
+void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+void ( APIENTRY * qglColor3fv )(const GLfloat *v);
+void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
+void ( APIENTRY * qglColor3iv )(const GLint *v);
+void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
+void ( APIENTRY * qglColor3sv )(const GLshort *v);
+void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
+void ( APIENTRY * qglColor3uiv )(const GLuint *v);
+void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
+void ( APIENTRY * qglColor3usv )(const GLushort *v);
+void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+void ( APIENTRY * qglColor4bv )(const GLbyte *v);
+void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+void ( APIENTRY * qglColor4dv )(const GLdouble *v);
+void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglColor4fv )(const GLfloat *v);
+void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+void ( APIENTRY * qglColor4iv )(const GLint *v);
+void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+void ( APIENTRY * qglColor4sv )(const GLshort *v);
+void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+void ( APIENTRY * qglColor4uiv )(const GLuint *v);
+void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+void ( APIENTRY * qglColor4usv )(const GLushort *v);
+void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
+void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglCullFace )(GLenum mode);
+void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
+void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
+void ( APIENTRY * qglDepthFunc )(GLenum func);
+void ( APIENTRY * qglDepthMask )(GLboolean flag);
+void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
+void ( APIENTRY * qglDisable )(GLenum cap);
+void ( APIENTRY * qglDisableClientState )(GLenum array);
+void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
+void ( APIENTRY * qglDrawBuffer )(GLenum mode);
+void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
+void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
+void ( APIENTRY * qglEnable )(GLenum cap);
+void ( APIENTRY * qglEnableClientState )(GLenum array);
+void ( APIENTRY * qglEnd )(void);
+void ( APIENTRY * qglEndList )(void);
+void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
+void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
+void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
+void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
+void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+void ( APIENTRY * qglEvalPoint1 )(GLint i);
+void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
+void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+void ( APIENTRY * qglFinish )(void);
+void ( APIENTRY * qglFlush )(void);
+void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
+void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglFrontFace )(GLenum mode);
+void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLuint ( APIENTRY * qglGenLists )(GLsizei range);
+void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
+void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
+void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
+void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
+GLenum ( APIENTRY * qglGetError )(void);
+void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
+void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
+void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
+void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
+void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
+void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
+void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
+const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
+void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
+void ( APIENTRY * qglIndexMask )(GLuint mask);
+void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglIndexd )(GLdouble c);
+void ( APIENTRY * qglIndexdv )(const GLdouble *c);
+void ( APIENTRY * qglIndexf )(GLfloat c);
+void ( APIENTRY * qglIndexfv )(const GLfloat *c);
+void ( APIENTRY * qglIndexi )(GLint c);
+void ( APIENTRY * qglIndexiv )(const GLint *c);
+void ( APIENTRY * qglIndexs )(GLshort c);
+void ( APIENTRY * qglIndexsv )(const GLshort *c);
+void ( APIENTRY * qglIndexub )(GLubyte c);
+void ( APIENTRY * qglIndexubv )(const GLubyte *c);
+void ( APIENTRY * qglInitNames )(void);
+void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
+GLboolean ( APIENTRY * qglIsList )(GLuint list);
+GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
+void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
+void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
+void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
+void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
+void ( APIENTRY * qglLineWidth )(GLfloat width);
+void ( APIENTRY * qglListBase )(GLuint base);
+void ( APIENTRY * qglLoadIdentity )(void);
+void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglLoadName )(GLuint name);
+void ( APIENTRY * qglLogicOp )(GLenum opcode);
+void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
+void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
+void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+void ( APIENTRY * qglMatrixMode )(GLenum mode);
+void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
+void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
+void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
+void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
+void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
+void ( APIENTRY * qglNormal3iv )(const GLint *v);
+void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+void ( APIENTRY * qglNormal3sv )(const GLshort *v);
+void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+void ( APIENTRY * qglPassThrough )(GLfloat token);
+void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+void ( APIENTRY * qglPointSize )(GLfloat size);
+void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
+void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
+void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
+void ( APIENTRY * qglPopAttrib )(void);
+void ( APIENTRY * qglPopClientAttrib )(void);
+void ( APIENTRY * qglPopMatrix )(void);
+void ( APIENTRY * qglPopName )(void);
+void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushMatrix )(void);
+void ( APIENTRY * qglPushName )(GLuint name);
+void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
+void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
+void ( APIENTRY * qglReadBuffer )(GLenum mode);
+void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
+void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
+void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
+void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
+GLint ( APIENTRY * qglRenderMode )(GLenum mode);
+void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
+void ( APIENTRY * qglShadeModel )(GLenum mode);
+void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
+void ( APIENTRY * qglStencilMask )(GLuint mask);
+void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+void ( APIENTRY * qglTexCoord1d )(GLdouble s);
+void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord1f )(GLfloat s);
+void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord1i )(GLint s);
+void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord1s )(GLshort s);
+void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
+void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
+void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
+void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
+void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
+void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
+void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
+void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
+void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
+void ( APIENTRY * qglVertex2iv )(const GLint *v);
+void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglVertex2sv )(const GLshort *v);
+void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglVertex3iv )(const GLint *v);
+void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglVertex3sv )(const GLshort *v);
+void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglVertex4iv )(const GLint *v);
+void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglVertex4sv )(const GLshort *v);
+void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
+void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
+void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
+
+void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
+void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
+
+void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
+void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
+void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
+
+extern "C" void InitIglToQgl( _QERQglTable *g_QglTable )
+{
+/*
+  // initialze the qgl functions
+  qglAccum = NULL;
+  qglAlphaFunc = g_QglTable->m_pfn_qglAlphaFunc;
+  qglAreTexturesResident = NULL;
+  qglArrayElement = NULL;
+  qglBegin = g_QglTable->m_pfn_qglBegin;
+  qglBindTexture = g_QglTable->m_pfn_qglBindTexture;
+  qglBitmap = NULL;
+  qglBlendFunc = g_QglTable->m_pfn_qglBlendFunc;
+  qglCallList = g_QglTable->m_pfn_qglCallList;
+  qglCallLists = g_QglTable->m_pfn_qglCallLists;
+  qglClear = g_QglTable->m_pfn_qglClear;
+  qglClearAccum = NULL;
+  qglClearColor = g_QglTable->m_pfn_qglClearColor;
+  qglClearDepth = g_QglTable->m_pfn_qglClearDepth;
+  qglClearIndex = NULL;
+  qglClearStencil = NULL;
+  qglClipPlane = NULL;
+  qglColor3b = NULL;
+  qglColor3bv = NULL;
+  qglColor3d = NULL;
+  qglColor3dv = NULL;
+  qglColor3f = g_QglTable->m_pfn_qglColor3f;
+  qglColor3fv = g_QglTable->m_pfn_qglColor3fv;
+  qglColor3i = NULL;
+  qglColor3iv = NULL;
+  qglColor3s = NULL;
+  qglColor3sv = NULL;
+  qglColor3ub = NULL;
+  qglColor3ubv = NULL;
+  qglColor3ui = NULL;
+  qglColor3uiv = NULL;
+  qglColor3us = NULL;
+  qglColor3usv = NULL;
+  qglColor4b = NULL;
+  qglColor4bv = NULL;
+  qglColor4d = NULL;
+  qglColor4dv = NULL;
+  qglColor4f = g_QglTable->m_pfn_qglColor4f;
+  qglColor4fv = g_QglTable->m_pfn_qglColor4fv;
+  qglColor4i = NULL;
+  qglColor4iv = NULL;
+  qglColor4s = NULL;
+  qglColor4sv = NULL;
+  qglColor4ub = NULL;
+  qglColor4ubv = NULL;
+  qglColor4ui = NULL;
+  qglColor4uiv = NULL;
+  qglColor4us = NULL;
+  qglColor4usv = NULL;
+  qglColorMask = NULL;
+  qglColorMaterial = NULL;
+  qglColorPointer = NULL;
+  qglCopyPixels = NULL;
+  qglCopyTexImage1D = NULL;
+  qglCopyTexImage2D = NULL;
+  qglCopyTexSubImage1D = NULL;
+  qglCopyTexSubImage2D = NULL;
+  qglCullFace = g_QglTable->m_pfn_qglCullFace;
+  qglDeleteLists = g_QglTable->m_pfn_qglDeleteLists;
+  qglDeleteTextures = g_QglTable->m_pfn_qglDeleteTextures;
+  qglDepthFunc = g_QglTable->m_pfn_qglDepthFunc;
+  qglDepthMask = g_QglTable->m_pfn_qglDepthMask;
+  qglDepthRange = NULL;
+  qglDisable = g_QglTable->m_pfn_qglDisable;
+  qglDisableClientState = NULL;
+  qglDrawArrays = NULL;
+  qglDrawBuffer = NULL;
+  qglDrawElements = NULL;
+  qglDrawPixels = NULL;
+  qglEdgeFlag = NULL;
+  qglEdgeFlagPointer = NULL;
+  qglEdgeFlagv = NULL;
+  qglEnable = g_QglTable->m_pfn_qglEnable;
+  qglEnableClientState = NULL;
+  qglEnd = g_QglTable->m_pfn_qglEnd;
+  qglEndList = g_QglTable->m_pfn_qglEndList;
+  qglEvalCoord1d = NULL;
+  qglEvalCoord1dv = NULL;
+  qglEvalCoord1f  = NULL;
+  qglEvalCoord1fv = NULL;
+  qglEvalCoord2d = NULL;
+  qglEvalCoord2dv = NULL;
+  qglEvalCoord2f= NULL;
+  qglEvalCoord2fv = NULL;
+  qglEvalMesh1 = NULL;
+  qglEvalMesh2 = NULL;
+  qglEvalPoint1 = NULL;
+  qglEvalPoint2 = NULL;
+  qglFeedbackBuffer = NULL;
+  qglFinish = NULL;
+  qglFlush = NULL;
+  qglFogf = g_QglTable->m_pfn_qglFogf;
+  qglFogfv = g_QglTable->m_pfn_qglFogfv;
+  qglFogi = g_QglTable->m_pfn_qglFogi;
+  qglFogiv = NULL;
+  qglFrontFace = NULL;
+  qglFrustum = NULL;
+  qglGenLists = g_QglTable->m_pfn_qglGenLists;
+  qglGenTextures = g_QglTable->m_pfn_qglGenTextures;
+  qglGetBooleanv = NULL;
+  qglGetClipPlane = NULL;
+  qglGetDoublev = NULL;
+  qglGetError = NULL;
+  qglGetFloatv = NULL;
+  qglGetIntegerv = NULL;
+  qglGetLightfv = NULL;
+  qglGetLightiv = NULL;
+  qglGetMapdv = NULL;
+  qglGetMapfv = NULL;
+  qglGetMapiv = NULL;
+  qglGetMaterialfv = NULL;
+  qglGetMaterialiv = NULL;
+  qglGetPixelMapfv = NULL;
+  qglGetPixelMapuiv = NULL;
+  qglGetPixelMapusv = NULL;
+  qglGetPointerv = NULL;
+  qglGetPolygonStipple = NULL;
+  qglGetString = NULL;
+  qglGetTexEnvfv = NULL;
+  qglGetTexEnviv = NULL;
+  qglGetTexGendv = NULL;
+  qglGetTexGenfv = NULL;
+  qglGetTexGeniv = NULL;
+  qglGetTexImage = NULL;
+  qglGetTexLevelParameterfv = NULL;
+  qglGetTexLevelParameteriv = NULL;
+  qglGetTexParameterfv = NULL;
+  qglGetTexParameteriv = NULL;
+  qglHint = g_QglTable->m_pfn_qglHint;
+  qglIndexMask = NULL;
+  qglIndexPointer = NULL;
+  qglIndexd = NULL;
+  qglIndexdv = NULL;
+  qglIndexf = NULL;
+  qglIndexfv = NULL;
+  qglIndexi = NULL;
+  qglIndexiv = NULL;
+  qglIndexs = NULL;
+  qglIndexsv = NULL;
+  qglIndexub = NULL;
+  qglIndexubv = NULL;
+  qglInitNames = NULL;
+  qglInterleavedArrays = NULL;
+  qglIsEnabled = NULL;
+  qglIsList = NULL;
+  qglIsTexture = NULL;
+  qglLightModelf = NULL;
+  qglLightModelfv = NULL;
+  qglLightModeli = NULL;
+  qglLightModeliv = NULL;
+  qglLightf = NULL;
+  qglLightfv = g_QglTable->m_pfn_qglLightfv;
+  qglLighti = NULL;
+  qglLightiv = NULL;
+  qglLineStipple = g_QglTable->m_pfn_qglLineStipple;
+  qglLineWidth = g_QglTable->m_pfn_qglLineWidth;
+  qglListBase = g_QglTable->m_pfn_qglListBase;
+  qglLoadIdentity = g_QglTable->m_pfn_qglLoadIdentity;
+  qglLoadMatrixd = NULL;
+  qglLoadMatrixf = NULL;
+  qglLoadName = NULL;
+  qglLogicOp = NULL;
+  qglMap1d = NULL;
+  qglMap1f = NULL;
+  qglMap2d = NULL;
+  qglMap2f = NULL;
+  qglMapGrid1d = NULL;
+  qglMapGrid1f = NULL;
+  qglMapGrid2d = NULL;
+  qglMapGrid2f = NULL;
+  qglMaterialf = g_QglTable->m_pfn_qglMaterialf;
+  qglMaterialfv = g_QglTable->m_pfn_qglMaterialfv;
+  qglMateriali = NULL;
+  qglMaterialiv = NULL;
+  qglMatrixMode = g_QglTable->m_pfn_qglMatrixMode;
+  qglMultMatrixd = NULL;
+  qglMultMatrixf = g_QglTable->m_pfn_qglMultMatrixf;
+  qglNewList = g_QglTable->m_pfn_qglNewList;
+  qglNormal3b = NULL;
+  qglNormal3bv = NULL;
+  qglNormal3d = NULL;
+  qglNormal3dv = NULL;
+  qglNormal3f = g_QglTable->m_pfn_qglNormal3f;
+  qglNormal3fv = g_QglTable->m_pfn_qglNormal3fv;
+  qglNormal3i = NULL;
+  qglNormal3iv = NULL;
+  qglNormal3s = NULL;
+  qglNormal3sv = NULL;
+  qglNormalPointer = NULL;
+  qglOrtho = g_QglTable->m_pfn_qglOrtho;
+  qglPassThrough = NULL;
+  qglPixelMapfv = NULL;
+  qglPixelMapuiv = NULL;
+  qglPixelMapusv = NULL;
+  qglPixelStoref = NULL;
+  qglPixelStorei = NULL;
+  qglPixelTransferf = NULL;
+  qglPixelTransferi = NULL;
+  qglPixelZoom = NULL;
+  qglPointSize = g_QglTable->m_pfn_qglPointSize;
+  qglPolygonMode = g_QglTable->m_pfn_qglPolygonMode;
+  qglPolygonOffset = NULL;
+  qglPolygonStipple = NULL;
+  qglPopAttrib = g_QglTable->m_pfn_qglPopAttrib;
+  qglPopClientAttrib = NULL;
+  qglPopMatrix = g_QglTable->m_pfn_qglPopMatrix;
+  qglPopName = NULL;
+  qglPrioritizeTextures = NULL;
+  qglPushAttrib = g_QglTable->m_pfn_qglPushAttrib;
+  qglPushClientAttrib = NULL;
+  qglPushMatrix = g_QglTable->m_pfn_qglPushMatrix;
+  qglPushName = NULL;
+  qglRasterPos2d = NULL;
+  qglRasterPos2dv = NULL;
+  qglRasterPos2f = NULL;
+  qglRasterPos2fv = NULL;
+  qglRasterPos2i = NULL;
+  qglRasterPos2iv = NULL;
+  qglRasterPos2s = NULL;
+  qglRasterPos2sv = NULL;
+  qglRasterPos3d = NULL;
+  qglRasterPos3dv = NULL;
+  qglRasterPos3f = NULL;
+  qglRasterPos3fv = g_QglTable->m_pfn_qglRasterPos3fv;
+  qglRasterPos3i = NULL;
+  qglRasterPos3iv = NULL;
+  qglRasterPos3s = NULL;
+  qglRasterPos3sv = NULL;
+  qglRasterPos4d = NULL;
+  qglRasterPos4dv = NULL;
+  qglRasterPos4f = NULL;
+  qglRasterPos4fv = NULL;
+  qglRasterPos4i = NULL;
+  qglRasterPos4iv = NULL;
+  qglRasterPos4s = NULL;
+  qglRasterPos4sv = NULL;
+  qglReadBuffer = NULL;
+  qglReadPixels = NULL;
+  qglRectd = NULL;
+  qglRectdv = NULL;
+  qglRectf = NULL;
+  qglRectfv = NULL;
+  qglRecti = NULL;
+  qglRectiv = NULL;
+  qglRects = NULL;
+  qglRectsv = NULL;
+  qglRenderMode = NULL;
+  qglRotated = g_QglTable->m_pfn_qglRotated;
+  qglRotatef = g_QglTable->m_pfn_qglRotatef;
+  qglScaled = NULL;
+  qglScalef = g_QglTable->m_pfn_qglScalef;
+  qglScissor = g_QglTable->m_pfn_qglScissor;
+  qglSelectBuffer = NULL;
+  qglShadeModel = g_QglTable->m_pfn_qglShadeModel;
+  qglStencilFunc = NULL;
+  qglStencilMask = NULL;
+  qglStencilOp = NULL;
+  qglTexCoord1d = NULL;
+  qglTexCoord1dv = NULL;
+  qglTexCoord1f = NULL;
+  qglTexCoord1fv = NULL;
+  qglTexCoord1i = NULL;
+  qglTexCoord1iv = NULL;
+  qglTexCoord1s = NULL;
+  qglTexCoord1sv = NULL;
+  qglTexCoord2d = NULL;
+  qglTexCoord2dv = NULL;
+  qglTexCoord2f = g_QglTable->m_pfn_qglTexCoord2f;
+  qglTexCoord2fv = g_QglTable->m_pfn_qglTexCoord2fv;
+  qglTexCoord2i = NULL;
+  qglTexCoord2iv = NULL;
+  qglTexCoord2s = NULL;
+  qglTexCoord2sv = NULL;
+  qglTexCoord3d = NULL;
+  qglTexCoord3dv = NULL;
+  qglTexCoord3f = NULL;
+  qglTexCoord3fv = NULL;
+  qglTexCoord3i = NULL;
+  qglTexCoord3iv = NULL;
+  qglTexCoord3s = NULL;
+  qglTexCoord3sv = NULL;
+  qglTexCoord4d = NULL;
+  qglTexCoord4dv = NULL;
+  qglTexCoord4f = NULL;
+  qglTexCoord4fv = NULL;
+  qglTexCoord4i = NULL;
+  qglTexCoord4iv = NULL;
+  qglTexCoord4s = NULL;
+  qglTexCoord4sv = NULL;
+  qglTexCoordPointer = NULL;
+  qglTexEnvf = g_QglTable->m_pfn_qglTexEnvf;
+  qglTexEnvfv = NULL;
+  qglTexEnvi = NULL;
+  qglTexEnviv = NULL;
+  qglTexGend = NULL;
+  qglTexGendv = NULL;
+  qglTexGenf = g_QglTable->m_pfn_qglTexGenf;
+  qglTexGenfv = NULL;
+  qglTexGeni = NULL;
+  qglTexGeniv = NULL;
+  qglTexImage1D = g_QglTable->m_pfn_qglTexImage1D;
+  qglTexImage2D = g_QglTable->m_pfn_qglTexImage2D;
+  qglTexParameterf = g_QglTable->m_pfn_qglTexParameterf;
+  qglTexParameterfv = g_QglTable->m_pfn_qglTexParameterfv;
+  qglTexParameteri = g_QglTable->m_pfn_qglTexParameteri;
+  qglTexParameteriv = g_QglTable->m_pfn_qglTexParameteriv;
+  qglTexSubImage1D = g_QglTable->m_pfn_qglTexSubImage1D;
+  qglTexSubImage2D = g_QglTable->m_pfn_qglTexSubImage2D;
+  qglTranslated = g_QglTable->m_pfn_qglTranslated;
+  qglTranslatef = g_QglTable->m_pfn_qglTranslatef;
+  qglVertex2d = NULL;
+  qglVertex2dv = NULL;
+  qglVertex2f = g_QglTable->m_pfn_qglVertex2f;
+  qglVertex2fv = NULL;
+  qglVertex2i = NULL;
+  qglVertex2iv = NULL;
+  qglVertex2s = NULL;
+  qglVertex2sv = NULL;
+  qglVertex3d = NULL;
+  qglVertex3dv = NULL;
+  qglVertex3f = g_QglTable->m_pfn_qglVertex3f;
+  qglVertex3fv = g_QglTable->m_pfn_qglVertex3fv;
+  qglVertex3i = NULL;
+  qglVertex3iv = NULL;
+  qglVertex3s = NULL;
+  qglVertex3sv = NULL;
+  qglVertex4d = NULL;
+  qglVertex4dv = NULL;
+  qglVertex4f = NULL;
+  qglVertex4fv = NULL;
+  qglVertex4i = NULL;
+  qglVertex4iv = NULL;
+  qglVertex4s = NULL;
+  qglVertex4sv = NULL;
+  qglVertexPointer = NULL;
+  qglViewport = g_QglTable->m_pfn_qglViewport;
+
+  qglPointParameterfEXT = NULL;
+  qglPointParameterfvEXT = NULL;
+  qglColorTableEXT = NULL;
+
+  qglMTexCoord2fSGIS = NULL;
+  qglSelectTextureSGIS = NULL;
+
+  qglActiveTextureARB = NULL;
+  qglClientActiveTextureARB = NULL;
+  qglMultiTexCoord1dARB = NULL;
+  qglMultiTexCoord1dvARB = NULL;
+  qglMultiTexCoord1fARB = NULL;
+  qglMultiTexCoord1fvARB = NULL;
+  qglMultiTexCoord1iARB = NULL;
+  qglMultiTexCoord1ivARB = NULL;
+  qglMultiTexCoord1sARB = NULL;
+  qglMultiTexCoord1svARB = NULL;
+  qglMultiTexCoord2dARB = NULL;
+  qglMultiTexCoord2dvARB = NULL;
+  qglMultiTexCoord2fARB = NULL;
+  qglMultiTexCoord2fvARB = NULL;
+  qglMultiTexCoord2iARB = NULL;
+  qglMultiTexCoord2ivARB = NULL;
+  qglMultiTexCoord2sARB = NULL;
+  qglMultiTexCoord2svARB = NULL;
+  qglMultiTexCoord3dARB = NULL;
+  qglMultiTexCoord3dvARB = NULL;
+  qglMultiTexCoord3fARB = NULL;
+  qglMultiTexCoord3fvARB = NULL;
+  qglMultiTexCoord3iARB = NULL;
+  qglMultiTexCoord3ivARB = NULL;
+  qglMultiTexCoord3sARB = NULL;
+  qglMultiTexCoord3svARB = NULL;
+  qglMultiTexCoord4dARB = NULL;
+  qglMultiTexCoord4dvARB = NULL;
+  qglMultiTexCoord4fARB = NULL;
+  qglMultiTexCoord4fvARB = NULL;
+  qglMultiTexCoord4iARB = NULL;
+  qglMultiTexCoord4ivARB = NULL;
+  qglMultiTexCoord4sARB = NULL;
+  qglMultiTexCoord4svARB = NULL;
+*/
+}
+
+#endif // _IGL_TO_QGL_H_
diff --git a/libs/l_net/l_net.c b/libs/l_net/l_net.c
index fed856b5..9ead6652 100644
--- a/libs/l_net/l_net.c
+++ b/libs/l_net/l_net.c
@@ -1,627 +1,627 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//====================================================================
-//
-// Name:			l_net.c
-// Function:		-
-// Programmer:		MrElusive
-// Last update:		-
-// Tab size:		3
-// Notes:
-//====================================================================
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-#include "l_net.h"
-#include "l_net_wins.h"
-
-#define GetMemory malloc
-#define FreeMemory free
-
-#define qtrue	1
-#define qfalse	0
-
-#ifdef _DEBUG
-void WinPrint(char *str, ...)
-{
-	va_list argptr;
-  char text[4096];
-
-  va_start (argptr,str);
-	vsprintf (text, str, argptr);
-	va_end (argptr);
-
-  printf(text);
-}
-#else
-void WinPrint(char *str, ...)
-{
-}
-#endif
-
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void Net_SetAddressPort(address_t *address, int port)
-{
-	sockaddr_t addr;
-
-	WINS_StringToAddr(address->ip, &addr);
-	WINS_SetSocketPort(&addr, port);
-	strcpy(address->ip, WINS_AddrToString(&addr));
-} //end of the function Net_SetAddressPort
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int Net_AddressCompare(address_t *addr1, address_t *addr2)
-{
-#ifdef _WIN32
-	return stricmp(addr1->ip, addr2->ip);
-#endif
-#ifdef __linux__
-	return strcasecmp(addr1->ip, addr2->ip);
-#endif
-} //end of the function Net_AddressCompare
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void Net_SocketToAddress(socket_t *sock, address_t *address)
-{
-	strcpy(address->ip, WINS_AddrToString(&sock->addr));
-} //end of the function Net_SocketToAddress
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int Net_Send(socket_t *sock, netmessage_t *msg)
-{
-	int size;
-
-	size = msg->size;
-	msg->size = 0;
-	NMSG_WriteLong(msg, size-4);
-	msg->size = size;
-	//WinPrint("Net_Send: message of size %d\n", sendmsg.size);
-	return WINS_Write(sock->socket, msg->data, msg->size, NULL);
-} //end of the function Net_SendSocketReliable
-//===========================================================================
-// returns the number of bytes recieved
-// -1 on error
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int Net_Receive(socket_t *sock, netmessage_t *msg)
-{
-	int curread;
-
-	if (sock->remaining > 0)
-	{
-		curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
-		if (curread == -1)
-		{
-			WinPrint("Net_Receive: read error\n");
-			return -1;
-		} //end if
-		sock->remaining -= curread;
-		sock->msg.size += curread;
-		if (sock->remaining <= 0)
-		{
-			sock->remaining = 0;
-			memcpy(msg, &sock->msg, sizeof(netmessage_t));
-			sock->msg.size = 0;
-			return msg->size - 4;
-		} //end if
-		return 0;
-	} //end if
-	sock->msg.size = WINS_Read(sock->socket, sock->msg.data, 4, NULL);
-	if (sock->msg.size == 0) return 0;
-	if (sock->msg.size == -1)
-	{
-		WinPrint("Net_Receive: size header read error\n");
-		return -1;
-	} //end if
-	//WinPrint("Net_Receive: message size header %d\n", msg->size);
-	sock->msg.read = 0;
-	sock->remaining = NMSG_ReadLong(&sock->msg);
-	if (sock->remaining == 0) return 0;
-	if (sock->remaining < 0 || sock->remaining > MAX_NETMESSAGE)
-	{
-		WinPrint("Net_Receive: invalid message size %d\n", sock->remaining);
-		return -1;
-	} //end if
-	//try to read the message
-	curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
-	if (curread == -1)
-	{
-		WinPrint("Net_Receive: read error\n");
-		return -1;
-	} //end if
-	sock->remaining -= curread;
-	sock->msg.size += curread;
-	if (sock->remaining <= 0)
-	{
-		sock->remaining = 0;
-		memcpy(msg, &sock->msg, sizeof(netmessage_t));
-		sock->msg.size = 0;
-		return msg->size - 4;
-	} //end if
-	//the message has not been completely read yet
-#ifdef _DEBUG
-  printf("++timo TODO: debug the Net_Receive on big size messages\n");
-#endif
-	return 0;
-} //end of the function Net_Receive
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-socket_t *Net_AllocSocket(void)
-{
-	socket_t *sock;
-
-	sock = (socket_t *) GetMemory(sizeof(socket_t));
-	memset(sock, 0, sizeof(socket_t));
-	return sock;
-} //end of the function Net_AllocSocket
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void Net_FreeSocket(socket_t *sock)
-{
-	FreeMemory(sock);
-} //end of the function Net_FreeSocket
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-socket_t *Net_Connect(address_t *address, int port)
-{
-	int newsock;
-	socket_t *sock;
-	sockaddr_t sendaddr;
-
-	// see if we can resolve the host name
-	WINS_StringToAddr(address->ip, &sendaddr);
-
-  newsock = WINS_OpenReliableSocket(port);
-	if (newsock == -1) return NULL;
-
-	sock = Net_AllocSocket();
-	if (sock == NULL)
-	{
-		WINS_CloseSocket(newsock);
-		return NULL;
-	} //end if
-	sock->socket = newsock;
-
-	//connect to the host
-	if (WINS_Connect(newsock, &sendaddr) == -1)
-	{
-		Net_FreeSocket(sock);
-		WINS_CloseSocket(newsock);
-		WinPrint("Net_Connect: error connecting\n");
-		return NULL;
-	} //end if
-
-	memcpy(&sock->addr, &sendaddr, sizeof(sockaddr_t));
-	//now we can send messages
-	//
-	return sock;
-} //end of the function Net_Connect
-
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-socket_t *Net_ListenSocket(int port)
-{
-	int newsock;
-	socket_t *sock;
-
-	newsock = WINS_OpenReliableSocket(port);
-	if (newsock == -1) return NULL;
-
-	if (WINS_Listen(newsock) == -1)
-	{
-		WINS_CloseSocket(newsock);
-		return NULL;
-	} //end if
-	sock = Net_AllocSocket();
-	if (sock == NULL)
-	{
-		WINS_CloseSocket(newsock);
-		return NULL;
-	} //end if
-	sock->socket = newsock;
-	WINS_GetSocketAddr(newsock, &sock->addr);
-	WinPrint("listen socket opened at %s\n", WINS_AddrToString(&sock->addr));
-	//
-	return sock;
-} //end of the function Net_ListenSocket
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-socket_t *Net_Accept(socket_t *sock)
-{
-	int newsocket;
-	sockaddr_t sendaddr;
-	socket_t *newsock;
-
-	newsocket = WINS_Accept(sock->socket, &sendaddr);
-	if (newsocket == -1) return NULL;
-
-	newsock = Net_AllocSocket();
-	if (newsock == NULL)
-	{
-		WINS_CloseSocket(newsocket);
-		return NULL;
-	} //end if
-	newsock->socket = newsocket;
-	memcpy(&newsock->addr, &sendaddr, sizeof(sockaddr_t));
-	//
-	return newsock;
-} //end of the function Net_Accept
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void Net_Disconnect(socket_t *sock)
-{
-	WINS_CloseSocket(sock->socket);
-	Net_FreeSocket(sock);
-} //end of the function Net_Disconnect
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void Net_StringToAddress(char *string, address_t *address)
-{
-	strcpy(address->ip, string);
-} //end of the function Net_StringToAddress
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void Net_MyAddress(address_t *address)
-{
-	strcpy(address->ip, WINS_MyAddress());
-} //end of the function Net_MyAddress
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int Net_Setup(void)
-{
-	WINS_Init();
-	//
-	WinPrint("my address is %s\n", WINS_MyAddress());
-	//
-	return qtrue;
-} //end of the function Net_Setup
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void Net_Shutdown(void)
-{
-	WINS_Shutdown();
-} //end of the function Net_Shutdown
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_Clear(netmessage_t *msg)
-{
-	msg->size = 4;
-} //end of the function NMSG_Clear
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_WriteChar (netmessage_t *msg, int c)
-{
-	if (c < -128 || c > 127)
-		WinPrint("NMSG_WriteChar: range error\n");
-
-	if (msg->size >= MAX_NETMESSAGE)
-	{
-		WinPrint("NMSG_WriteChar: overflow\n");
-		return;
-	} //end if
-	msg->data[msg->size] = c;
-	msg->size++;
-} //end of the function NMSG_WriteChar
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_WriteByte(netmessage_t *msg, int c)
-{
-	if (c < -128 || c > 127)
-		WinPrint("NMSG_WriteByte: range error\n");
-
-	if (msg->size + 1 >= MAX_NETMESSAGE)
-	{
-		WinPrint("NMSG_WriteByte: overflow\n");
-		return;
-	} //end if
-	msg->data[msg->size] = c;
-	msg->size++;
-} //end of the function NMSG_WriteByte
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_WriteShort(netmessage_t *msg, int c)
-{
-	if (c < ((short)0x8000) || c > (short)0x7fff)
-		WinPrint("NMSG_WriteShort: range error");
-
-	if (msg->size + 2 >= MAX_NETMESSAGE)
-	{
-		WinPrint("NMSG_WriteShort: overflow\n");
-		return;
-	} //end if
-	msg->data[msg->size] = c&0xff;
-	msg->data[msg->size+1] = c>>8;
-	msg->size += 2;
-} //end of the function NMSG_WriteShort
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_WriteLong(netmessage_t *msg, int c)
-{
-	if (msg->size + 4 >= MAX_NETMESSAGE)
-	{
-		WinPrint("NMSG_WriteLong: overflow\n");
-		return;
-	} //end if
-	msg->data[msg->size] = c&0xff;
-	msg->data[msg->size+1] = (c>>8)&0xff;
-	msg->data[msg->size+2] = (c>>16)&0xff;
-	msg->data[msg->size+3] = c>>24;
-	msg->size += 4;
-} //end of the function NMSG_WriteLong
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_WriteFloat(netmessage_t *msg, float c)
-{
-	if (msg->size + 4 >= MAX_NETMESSAGE)
-	{
-		WinPrint("NMSG_WriteLong: overflow\n");
-		return;
-	} //end if
-	msg->data[msg->size] = *((int *)&c)&0xff;
-	msg->data[msg->size+1] = (*((int *)&c)>>8)&0xff;
-	msg->data[msg->size+2] = (*((int *)&c)>>16)&0xff;
-	msg->data[msg->size+3] = *((int *)&c)>>24;
-	msg->size += 4;
-} //end of the function NMSG_WriteFloat
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_WriteString(netmessage_t *msg, char *string)
-{
-	if (msg->size + strlen(string) + 1 >= MAX_NETMESSAGE)
-	{
-		WinPrint("NMSG_WriteString: overflow\n");
-		return;
-	} //end if
-	strcpy(&msg->data[msg->size], string);
-	msg->size += strlen(string) + 1;
-} //end of the function NMSG_WriteString
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void NMSG_ReadStart(netmessage_t *msg)
-{
-	msg->readoverflow = qfalse;
-	msg->read = 4;
-} //end of the function NMSG_ReadStart
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int NMSG_ReadChar(netmessage_t *msg)
-{
-	if (msg->size + 1 > msg->size)
-	{
-		msg->readoverflow = qtrue;
-		WinPrint("NMSG_ReadChar: read overflow\n");
-		return 0;
-	} //end if
-	msg->read++;
-	return msg->data[msg->read-1];
-} //end of the function NMSG_ReadChar
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int NMSG_ReadByte(netmessage_t *msg)
-{
-	if (msg->read + 1 > msg->size)
-	{
-		msg->readoverflow = qtrue;
-		WinPrint("NMSG_ReadByte: read overflow\n");
-		return 0;
-	} //end if
-	msg->read++;
-	return msg->data[msg->read-1];
-} //end of the function NMSG_ReadByte
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int NMSG_ReadShort(netmessage_t *msg)
-{
-	int c;
-
-	if (msg->read + 2 > msg->size)
-	{
-		msg->readoverflow = qtrue;
-		WinPrint("NMSG_ReadShort: read overflow\n");
-		return 0;
-	} //end if
-	c = (short)(msg->data[msg->read] + (msg->data[msg->read+1]<<8));
-	msg->read += 2;
-	return c;
-} //end of the function NMSG_ReadShort
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int NMSG_ReadLong(netmessage_t *msg)
-{
-	int c;
-
-	if (msg->read + 4 > msg->size)
-	{
-		msg->readoverflow = qtrue;
-		WinPrint("NMSG_ReadLong: read overflow\n");
-		return 0;
-	} //end if
-	c = msg->data[msg->read]
-		+ (msg->data[msg->read+1]<<8)
-		+ (msg->data[msg->read+2]<<16)
-		+ (msg->data[msg->read+3]<<24);
-	msg->read += 4;
-	return c;
-} //end of the function NMSG_ReadLong
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-float NMSG_ReadFloat(netmessage_t *msg)
-{
-	int c;
-
-	if (msg->read + 4 > msg->size)
-	{
-		msg->readoverflow = qtrue;
-		WinPrint("NMSG_ReadLong: read overflow\n");
-		return 0;
-	} //end if
-	c = msg->data[msg->read]
-		+ (msg->data[msg->read+1]<<8)
-		+ (msg->data[msg->read+2]<<16)
-		+ (msg->data[msg->read+3]<<24);
-	msg->read += 4;
-	return *(float *)&c;
-} //end of the function NMSG_ReadFloat
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-char *NMSG_ReadString(netmessage_t *msg)
-{
-	static char	string[2048];
-	int l, c;
-	
-	l = 0;
-	do
-	{
-		if (msg->read + 1 > msg->size)
-		{
-			msg->readoverflow = qtrue;
-			WinPrint("NMSG_ReadString: read overflow\n");
-			string[l] = 0;
-			return string;
-		} //end if
-		c = msg->data[msg->read];
-		msg->read++;
-		if (c == 0) break;
-		string[l] = c;
-		l++;
-	} while (l < sizeof(string)-1);
-	string[l] = 0;
-	return string;
-} //end of the function NMSG_ReadString
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//====================================================================
+//
+// Name:			l_net.c
+// Function:		-
+// Programmer:		MrElusive
+// Last update:		-
+// Tab size:		3
+// Notes:
+//====================================================================
+
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include "l_net.h"
+#include "l_net_wins.h"
+
+#define GetMemory malloc
+#define FreeMemory free
+
+#define qtrue	1
+#define qfalse	0
+
+#ifdef _DEBUG
+void WinPrint(char *str, ...)
+{
+	va_list argptr;
+  char text[4096];
+
+  va_start (argptr,str);
+	vsprintf (text, str, argptr);
+	va_end (argptr);
+
+  printf(text);
+}
+#else
+void WinPrint(char *str, ...)
+{
+}
+#endif
+
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void Net_SetAddressPort(address_t *address, int port)
+{
+	sockaddr_t addr;
+
+	WINS_StringToAddr(address->ip, &addr);
+	WINS_SetSocketPort(&addr, port);
+	strcpy(address->ip, WINS_AddrToString(&addr));
+} //end of the function Net_SetAddressPort
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int Net_AddressCompare(address_t *addr1, address_t *addr2)
+{
+#ifdef _WIN32
+	return stricmp(addr1->ip, addr2->ip);
+#endif
+#ifdef __linux__
+	return strcasecmp(addr1->ip, addr2->ip);
+#endif
+} //end of the function Net_AddressCompare
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void Net_SocketToAddress(socket_t *sock, address_t *address)
+{
+	strcpy(address->ip, WINS_AddrToString(&sock->addr));
+} //end of the function Net_SocketToAddress
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int Net_Send(socket_t *sock, netmessage_t *msg)
+{
+	int size;
+
+	size = msg->size;
+	msg->size = 0;
+	NMSG_WriteLong(msg, size-4);
+	msg->size = size;
+	//WinPrint("Net_Send: message of size %d\n", sendmsg.size);
+	return WINS_Write(sock->socket, msg->data, msg->size, NULL);
+} //end of the function Net_SendSocketReliable
+//===========================================================================
+// returns the number of bytes recieved
+// -1 on error
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int Net_Receive(socket_t *sock, netmessage_t *msg)
+{
+	int curread;
+
+	if (sock->remaining > 0)
+	{
+		curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
+		if (curread == -1)
+		{
+			WinPrint("Net_Receive: read error\n");
+			return -1;
+		} //end if
+		sock->remaining -= curread;
+		sock->msg.size += curread;
+		if (sock->remaining <= 0)
+		{
+			sock->remaining = 0;
+			memcpy(msg, &sock->msg, sizeof(netmessage_t));
+			sock->msg.size = 0;
+			return msg->size - 4;
+		} //end if
+		return 0;
+	} //end if
+	sock->msg.size = WINS_Read(sock->socket, sock->msg.data, 4, NULL);
+	if (sock->msg.size == 0) return 0;
+	if (sock->msg.size == -1)
+	{
+		WinPrint("Net_Receive: size header read error\n");
+		return -1;
+	} //end if
+	//WinPrint("Net_Receive: message size header %d\n", msg->size);
+	sock->msg.read = 0;
+	sock->remaining = NMSG_ReadLong(&sock->msg);
+	if (sock->remaining == 0) return 0;
+	if (sock->remaining < 0 || sock->remaining > MAX_NETMESSAGE)
+	{
+		WinPrint("Net_Receive: invalid message size %d\n", sock->remaining);
+		return -1;
+	} //end if
+	//try to read the message
+	curread = WINS_Read(sock->socket, &sock->msg.data[sock->msg.size], sock->remaining, NULL);
+	if (curread == -1)
+	{
+		WinPrint("Net_Receive: read error\n");
+		return -1;
+	} //end if
+	sock->remaining -= curread;
+	sock->msg.size += curread;
+	if (sock->remaining <= 0)
+	{
+		sock->remaining = 0;
+		memcpy(msg, &sock->msg, sizeof(netmessage_t));
+		sock->msg.size = 0;
+		return msg->size - 4;
+	} //end if
+	//the message has not been completely read yet
+#ifdef _DEBUG
+  printf("++timo TODO: debug the Net_Receive on big size messages\n");
+#endif
+	return 0;
+} //end of the function Net_Receive
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+socket_t *Net_AllocSocket(void)
+{
+	socket_t *sock;
+
+	sock = (socket_t *) GetMemory(sizeof(socket_t));
+	memset(sock, 0, sizeof(socket_t));
+	return sock;
+} //end of the function Net_AllocSocket
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void Net_FreeSocket(socket_t *sock)
+{
+	FreeMemory(sock);
+} //end of the function Net_FreeSocket
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+socket_t *Net_Connect(address_t *address, int port)
+{
+	int newsock;
+	socket_t *sock;
+	sockaddr_t sendaddr;
+
+	// see if we can resolve the host name
+	WINS_StringToAddr(address->ip, &sendaddr);
+
+  newsock = WINS_OpenReliableSocket(port);
+	if (newsock == -1) return NULL;
+
+	sock = Net_AllocSocket();
+	if (sock == NULL)
+	{
+		WINS_CloseSocket(newsock);
+		return NULL;
+	} //end if
+	sock->socket = newsock;
+
+	//connect to the host
+	if (WINS_Connect(newsock, &sendaddr) == -1)
+	{
+		Net_FreeSocket(sock);
+		WINS_CloseSocket(newsock);
+		WinPrint("Net_Connect: error connecting\n");
+		return NULL;
+	} //end if
+
+	memcpy(&sock->addr, &sendaddr, sizeof(sockaddr_t));
+	//now we can send messages
+	//
+	return sock;
+} //end of the function Net_Connect
+
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+socket_t *Net_ListenSocket(int port)
+{
+	int newsock;
+	socket_t *sock;
+
+	newsock = WINS_OpenReliableSocket(port);
+	if (newsock == -1) return NULL;
+
+	if (WINS_Listen(newsock) == -1)
+	{
+		WINS_CloseSocket(newsock);
+		return NULL;
+	} //end if
+	sock = Net_AllocSocket();
+	if (sock == NULL)
+	{
+		WINS_CloseSocket(newsock);
+		return NULL;
+	} //end if
+	sock->socket = newsock;
+	WINS_GetSocketAddr(newsock, &sock->addr);
+	WinPrint("listen socket opened at %s\n", WINS_AddrToString(&sock->addr));
+	//
+	return sock;
+} //end of the function Net_ListenSocket
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+socket_t *Net_Accept(socket_t *sock)
+{
+	int newsocket;
+	sockaddr_t sendaddr;
+	socket_t *newsock;
+
+	newsocket = WINS_Accept(sock->socket, &sendaddr);
+	if (newsocket == -1) return NULL;
+
+	newsock = Net_AllocSocket();
+	if (newsock == NULL)
+	{
+		WINS_CloseSocket(newsocket);
+		return NULL;
+	} //end if
+	newsock->socket = newsocket;
+	memcpy(&newsock->addr, &sendaddr, sizeof(sockaddr_t));
+	//
+	return newsock;
+} //end of the function Net_Accept
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void Net_Disconnect(socket_t *sock)
+{
+	WINS_CloseSocket(sock->socket);
+	Net_FreeSocket(sock);
+} //end of the function Net_Disconnect
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void Net_StringToAddress(char *string, address_t *address)
+{
+	strcpy(address->ip, string);
+} //end of the function Net_StringToAddress
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void Net_MyAddress(address_t *address)
+{
+	strcpy(address->ip, WINS_MyAddress());
+} //end of the function Net_MyAddress
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int Net_Setup(void)
+{
+	WINS_Init();
+	//
+	WinPrint("my address is %s\n", WINS_MyAddress());
+	//
+	return qtrue;
+} //end of the function Net_Setup
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void Net_Shutdown(void)
+{
+	WINS_Shutdown();
+} //end of the function Net_Shutdown
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_Clear(netmessage_t *msg)
+{
+	msg->size = 4;
+} //end of the function NMSG_Clear
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_WriteChar (netmessage_t *msg, int c)
+{
+	if (c < -128 || c > 127)
+		WinPrint("NMSG_WriteChar: range error\n");
+
+	if (msg->size >= MAX_NETMESSAGE)
+	{
+		WinPrint("NMSG_WriteChar: overflow\n");
+		return;
+	} //end if
+	msg->data[msg->size] = c;
+	msg->size++;
+} //end of the function NMSG_WriteChar
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_WriteByte(netmessage_t *msg, int c)
+{
+	if (c < -128 || c > 127)
+		WinPrint("NMSG_WriteByte: range error\n");
+
+	if (msg->size + 1 >= MAX_NETMESSAGE)
+	{
+		WinPrint("NMSG_WriteByte: overflow\n");
+		return;
+	} //end if
+	msg->data[msg->size] = c;
+	msg->size++;
+} //end of the function NMSG_WriteByte
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_WriteShort(netmessage_t *msg, int c)
+{
+	if (c < ((short)0x8000) || c > (short)0x7fff)
+		WinPrint("NMSG_WriteShort: range error");
+
+	if (msg->size + 2 >= MAX_NETMESSAGE)
+	{
+		WinPrint("NMSG_WriteShort: overflow\n");
+		return;
+	} //end if
+	msg->data[msg->size] = c&0xff;
+	msg->data[msg->size+1] = c>>8;
+	msg->size += 2;
+} //end of the function NMSG_WriteShort
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_WriteLong(netmessage_t *msg, int c)
+{
+	if (msg->size + 4 >= MAX_NETMESSAGE)
+	{
+		WinPrint("NMSG_WriteLong: overflow\n");
+		return;
+	} //end if
+	msg->data[msg->size] = c&0xff;
+	msg->data[msg->size+1] = (c>>8)&0xff;
+	msg->data[msg->size+2] = (c>>16)&0xff;
+	msg->data[msg->size+3] = c>>24;
+	msg->size += 4;
+} //end of the function NMSG_WriteLong
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_WriteFloat(netmessage_t *msg, float c)
+{
+	if (msg->size + 4 >= MAX_NETMESSAGE)
+	{
+		WinPrint("NMSG_WriteLong: overflow\n");
+		return;
+	} //end if
+	msg->data[msg->size] = *((int *)&c)&0xff;
+	msg->data[msg->size+1] = (*((int *)&c)>>8)&0xff;
+	msg->data[msg->size+2] = (*((int *)&c)>>16)&0xff;
+	msg->data[msg->size+3] = *((int *)&c)>>24;
+	msg->size += 4;
+} //end of the function NMSG_WriteFloat
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_WriteString(netmessage_t *msg, char *string)
+{
+	if (msg->size + strlen(string) + 1 >= MAX_NETMESSAGE)
+	{
+		WinPrint("NMSG_WriteString: overflow\n");
+		return;
+	} //end if
+	strcpy(&msg->data[msg->size], string);
+	msg->size += strlen(string) + 1;
+} //end of the function NMSG_WriteString
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void NMSG_ReadStart(netmessage_t *msg)
+{
+	msg->readoverflow = qfalse;
+	msg->read = 4;
+} //end of the function NMSG_ReadStart
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int NMSG_ReadChar(netmessage_t *msg)
+{
+	if (msg->size + 1 > msg->size)
+	{
+		msg->readoverflow = qtrue;
+		WinPrint("NMSG_ReadChar: read overflow\n");
+		return 0;
+	} //end if
+	msg->read++;
+	return msg->data[msg->read-1];
+} //end of the function NMSG_ReadChar
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int NMSG_ReadByte(netmessage_t *msg)
+{
+	if (msg->read + 1 > msg->size)
+	{
+		msg->readoverflow = qtrue;
+		WinPrint("NMSG_ReadByte: read overflow\n");
+		return 0;
+	} //end if
+	msg->read++;
+	return msg->data[msg->read-1];
+} //end of the function NMSG_ReadByte
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int NMSG_ReadShort(netmessage_t *msg)
+{
+	int c;
+
+	if (msg->read + 2 > msg->size)
+	{
+		msg->readoverflow = qtrue;
+		WinPrint("NMSG_ReadShort: read overflow\n");
+		return 0;
+	} //end if
+	c = (short)(msg->data[msg->read] + (msg->data[msg->read+1]<<8));
+	msg->read += 2;
+	return c;
+} //end of the function NMSG_ReadShort
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int NMSG_ReadLong(netmessage_t *msg)
+{
+	int c;
+
+	if (msg->read + 4 > msg->size)
+	{
+		msg->readoverflow = qtrue;
+		WinPrint("NMSG_ReadLong: read overflow\n");
+		return 0;
+	} //end if
+	c = msg->data[msg->read]
+		+ (msg->data[msg->read+1]<<8)
+		+ (msg->data[msg->read+2]<<16)
+		+ (msg->data[msg->read+3]<<24);
+	msg->read += 4;
+	return c;
+} //end of the function NMSG_ReadLong
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+float NMSG_ReadFloat(netmessage_t *msg)
+{
+	int c;
+
+	if (msg->read + 4 > msg->size)
+	{
+		msg->readoverflow = qtrue;
+		WinPrint("NMSG_ReadLong: read overflow\n");
+		return 0;
+	} //end if
+	c = msg->data[msg->read]
+		+ (msg->data[msg->read+1]<<8)
+		+ (msg->data[msg->read+2]<<16)
+		+ (msg->data[msg->read+3]<<24);
+	msg->read += 4;
+	return *(float *)&c;
+} //end of the function NMSG_ReadFloat
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+char *NMSG_ReadString(netmessage_t *msg)
+{
+	static char	string[2048];
+	int l, c;
+	
+	l = 0;
+	do
+	{
+		if (msg->read + 1 > msg->size)
+		{
+			msg->readoverflow = qtrue;
+			WinPrint("NMSG_ReadString: read overflow\n");
+			string[l] = 0;
+			return string;
+		} //end if
+		c = msg->data[msg->read];
+		msg->read++;
+		if (c == 0) break;
+		string[l] = c;
+		l++;
+	} while (l < sizeof(string)-1);
+	string[l] = 0;
+	return string;
+} //end of the function NMSG_ReadString
diff --git a/libs/l_net/l_net.h b/libs/l_net/l_net.h
index dd27d38b..167a5a36 100644
--- a/libs/l_net/l_net.h
+++ b/libs/l_net/l_net.h
@@ -1,125 +1,125 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//====================================================================
-//
-// Name:			l_net.h
-// Function:		-
-// Programmer:		MrElusive
-// Last update:		TTimo: cross-platform version, l_net library
-// Tab size:		2
-// Notes:
-//====================================================================
-
-//++timo FIXME: the l_net code understands that as the max size for the netmessage_s structure
-//  we have defined unsigned char data[MAX_NETMESSAGE] in netmessage_s but actually it cannot be filled completely
-//  we need to introduce a new #define and adapt to data[MAX_NETBUFFER]
-#define MAX_NETMESSAGE		1024
-#define MAX_NETADDRESS		32
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#ifndef __BYTEBOOL__
-#define __BYTEBOOL__
-typedef enum { qfalse, qtrue } qboolean;
-typedef unsigned char byte;
-#endif
-
-typedef struct address_s
-{
-	char ip[MAX_NETADDRESS];
-} address_t;
-
-typedef struct sockaddr_s
-{
-	short sa_family;
-	unsigned char sa_data[14];
-} sockaddr_t;
-
-typedef struct netmessage_s
-{
-	unsigned char data[MAX_NETMESSAGE];
-	int size;
-	int read;
-	int readoverflow;
-} netmessage_t;
-
-typedef struct socket_s
-{
-	int socket;							//socket number
-	sockaddr_t addr;					//socket address
-	netmessage_t msg;					//current message being read
-	int remaining;						//remaining bytes to read for the current message
-	struct socket_s *prev, *next;	//prev and next socket in a list
-} socket_t;
-
-//compare addresses
-int Net_AddressCompare(address_t *addr1, address_t *addr2);
-//gives the address of a socket
-void Net_SocketToAddress(socket_t *sock, address_t *address);
-//converts a string to an address
-void Net_StringToAddress(char *string, address_t *address);
-//set the address ip port
-void Net_SetAddressPort(address_t *address, int port);
-//send a message to the given socket
-int Net_Send(socket_t *sock, netmessage_t *msg);
-//recieve a message from the given socket
-int Net_Receive(socket_t *sock, netmessage_t *msg);
-//connect to a host
-// NOTE: port is the localhost port, usually 0
-// ex: Net_Connect( "192.168.0.1:39000", 0 )
-socket_t *Net_Connect(address_t *address, int port);
-//disconnect from a host
-void Net_Disconnect(socket_t *sock);
-//returns the local address
-void Net_MyAddress(address_t *address);
-//listen at the given port
-socket_t *Net_ListenSocket(int port);
-//accept new connections at the given socket
-socket_t *Net_Accept(socket_t *sock);
-//setup networking
-int Net_Setup(void);
-//shutdown networking
-void Net_Shutdown(void);
-//message handling
-void  NMSG_Clear(netmessage_t *msg);
-void  NMSG_WriteChar(netmessage_t *msg, int c);
-void  NMSG_WriteByte(netmessage_t *msg, int c);
-void  NMSG_WriteShort(netmessage_t *msg, int c);
-void  NMSG_WriteLong(netmessage_t *msg, int c);
-void  NMSG_WriteFloat(netmessage_t *msg, float c);
-void  NMSG_WriteString(netmessage_t *msg, char *string);
-void  NMSG_ReadStart(netmessage_t *msg);
-int   NMSG_ReadChar(netmessage_t *msg);
-int   NMSG_ReadByte(netmessage_t *msg);
-int   NMSG_ReadShort(netmessage_t *msg);
-int   NMSG_ReadLong(netmessage_t *msg);
-float NMSG_ReadFloat(netmessage_t *msg);
-char *NMSG_ReadString(netmessage_t *msg);
-
-//++timo FIXME: the WINS_ things are not necessary, they can be made portable arther easily
-char *WINS_ErrorMessage(int error);
-
-#ifdef __cplusplus
-}
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//====================================================================
+//
+// Name:			l_net.h
+// Function:		-
+// Programmer:		MrElusive
+// Last update:		TTimo: cross-platform version, l_net library
+// Tab size:		2
+// Notes:
+//====================================================================
+
+//++timo FIXME: the l_net code understands that as the max size for the netmessage_s structure
+//  we have defined unsigned char data[MAX_NETMESSAGE] in netmessage_s but actually it cannot be filled completely
+//  we need to introduce a new #define and adapt to data[MAX_NETBUFFER]
+#define MAX_NETMESSAGE		1024
+#define MAX_NETADDRESS		32
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef __BYTEBOOL__
+#define __BYTEBOOL__
+typedef enum { qfalse, qtrue } qboolean;
+typedef unsigned char byte;
+#endif
+
+typedef struct address_s
+{
+	char ip[MAX_NETADDRESS];
+} address_t;
+
+typedef struct sockaddr_s
+{
+	short sa_family;
+	unsigned char sa_data[14];
+} sockaddr_t;
+
+typedef struct netmessage_s
+{
+	unsigned char data[MAX_NETMESSAGE];
+	int size;
+	int read;
+	int readoverflow;
+} netmessage_t;
+
+typedef struct socket_s
+{
+	int socket;							//socket number
+	sockaddr_t addr;					//socket address
+	netmessage_t msg;					//current message being read
+	int remaining;						//remaining bytes to read for the current message
+	struct socket_s *prev, *next;	//prev and next socket in a list
+} socket_t;
+
+//compare addresses
+int Net_AddressCompare(address_t *addr1, address_t *addr2);
+//gives the address of a socket
+void Net_SocketToAddress(socket_t *sock, address_t *address);
+//converts a string to an address
+void Net_StringToAddress(char *string, address_t *address);
+//set the address ip port
+void Net_SetAddressPort(address_t *address, int port);
+//send a message to the given socket
+int Net_Send(socket_t *sock, netmessage_t *msg);
+//recieve a message from the given socket
+int Net_Receive(socket_t *sock, netmessage_t *msg);
+//connect to a host
+// NOTE: port is the localhost port, usually 0
+// ex: Net_Connect( "192.168.0.1:39000", 0 )
+socket_t *Net_Connect(address_t *address, int port);
+//disconnect from a host
+void Net_Disconnect(socket_t *sock);
+//returns the local address
+void Net_MyAddress(address_t *address);
+//listen at the given port
+socket_t *Net_ListenSocket(int port);
+//accept new connections at the given socket
+socket_t *Net_Accept(socket_t *sock);
+//setup networking
+int Net_Setup(void);
+//shutdown networking
+void Net_Shutdown(void);
+//message handling
+void  NMSG_Clear(netmessage_t *msg);
+void  NMSG_WriteChar(netmessage_t *msg, int c);
+void  NMSG_WriteByte(netmessage_t *msg, int c);
+void  NMSG_WriteShort(netmessage_t *msg, int c);
+void  NMSG_WriteLong(netmessage_t *msg, int c);
+void  NMSG_WriteFloat(netmessage_t *msg, float c);
+void  NMSG_WriteString(netmessage_t *msg, char *string);
+void  NMSG_ReadStart(netmessage_t *msg);
+int   NMSG_ReadChar(netmessage_t *msg);
+int   NMSG_ReadByte(netmessage_t *msg);
+int   NMSG_ReadShort(netmessage_t *msg);
+int   NMSG_ReadLong(netmessage_t *msg);
+float NMSG_ReadFloat(netmessage_t *msg);
+char *NMSG_ReadString(netmessage_t *msg);
+
+//++timo FIXME: the WINS_ things are not necessary, they can be made portable arther easily
+char *WINS_ErrorMessage(int error);
+
+#ifdef __cplusplus
+}
+#endif
diff --git a/libs/l_net/l_net_berkeley.c b/libs/l_net/l_net_berkeley.c
index 60912aee..2d4d33bc 100644
--- a/libs/l_net/l_net_berkeley.c
+++ b/libs/l_net/l_net_berkeley.c
@@ -1,770 +1,770 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//===========================================================================
-//
-// Name:         l_net_wins.c
-// Function:     WinSock
-// Programmer:   MrElusive
-// Last update:  TTimo: cross-platform version, l_net library
-// Tab Size:     2
-// Notes:
-//===========================================================================
-
-//#include <windows.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "l_net.h"
-#include "l_net_wins.h"
-
-#include <arpa/inet.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/ioctl.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-#include <errno.h>
-#include <netdb.h>
-#define SOCKET_ERROR -1
-#define INVALID_SOCKET -1
-
-extern void WinPrint(char *str, ...);
-
-#define WinError WinPrint
-
-#define qtrue	1
-#define qfalse	0
-
-#define ioctlsocket ioctl
-#define closesocket close
-
-int WSAGetLastError()
-{
-	return errno;
-}
-
-/*
-typedef struct tag_error_struct
-{
-    int     errnum;
-    LPSTR   errstr;
-} ERROR_STRUCT;
-*/
-
-typedef struct tag_error_struct
-{
-    int     errnum;
-    const char *errstr;
-} ERROR_STRUCT;
-
-#define	NET_NAMELEN			64
-
-static char my_tcpip_address[NET_NAMELEN];
-
-#define	DEFAULTnet_hostport	26000
-
-#define MAXHOSTNAMELEN		256
-
-static int net_acceptsocket = -1;		// socket for fielding new connections
-static int net_controlsocket;
-static int net_hostport;				// udp port number for acceptsocket
-static int net_broadcastsocket = 0;
-//static qboolean ifbcastinit = qfalse;
-//static struct sockaddr_s broadcastaddr;
-static struct sockaddr_s broadcastaddr;
-
-static unsigned long myAddr;
-
-ERROR_STRUCT errlist[] = {
-  {EACCES,"EACCES - The address is protected, user is not root"},
-  {EAGAIN,"EAGAIN - Operation on non-blocking socket that cannot return immediatly"},
-  {EBADF, "EBADF - sockfd is not a valid descriptor"},
-  {EFAULT, "EFAULT - The parameter is not in a writable part of the user address space"},
-  {EINVAL,"EINVAL - The socket is already bound to an address"},
-  {ENOBUFS,"ENOBUFS - not enough memory"},
-  {ENOMEM, "ENOMEM - not enough memory"},
-  {ENOTCONN, "ENOTCONN - not connected"},
-  {ENOTSOCK,"ENOTSOCK - Argument is file descriptor not a socket"},
-  {EOPNOTSUPP,"ENOTSUPP - The referenced socket is not of type SOCK_STREAM"},
-  {EPERM, "EPERM - Firewall rules forbid connection"},
-  {-1, NULL}
-};
-
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-char *WINS_ErrorMessage(int error)
-{
-    int search = 0;
-
-    if (!error) return "No error occurred";
-
-	 for (search = 0; errlist[search].errstr; search++)
-	 {
-		if (error == errlist[search].errnum)
-				return (char *)errlist[search].errstr;
-	 } //end for
-
-    return "Unknown error";
-} //end of the function WINS_ErrorMessage
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Init(void)
-{
-	int		i;
-	struct hostent *local;
-	char	buff[MAXHOSTNAMELEN];
-	struct sockaddr_s addr;
-	char	*p;
-	int		r;
-/* 
- linux doesn't have anything to initialize for the net
- "Windows .. built for the internet .. the internet .. built with unix" 
- */
-#if 0
-	WORD	wVersionRequested; 
-
-	wVersionRequested = MAKEWORD(2, 2);
-
-	r = WSAStartup (wVersionRequested, &winsockdata);
-
-	if (r)
-	{
-		WinPrint("Winsock initialization failed.\n");
-		return -1;
-	}
-#endif
-	/*
-	i = COM_CheckParm ("-udpport");
-	if (i == 0)*/
-		net_hostport = DEFAULTnet_hostport;
-	/*
-	else if (i < com_argc-1)
-		net_hostport = Q_atoi (com_argv[i+1]);
-	else
-		Sys_Error ("WINS_Init: you must specify a number after -udpport");
-	*/
-
-	// determine my name & address
-	gethostname(buff, MAXHOSTNAMELEN);
-	local = gethostbyname(buff);
-	myAddr = *(int *)local->h_addr_list[0];
-
-	// if the quake hostname isn't set, set it to the machine name
-//	if (Q_strcmp(hostname.string, "UNNAMED") == 0)
-	{
-		// see if it's a text IP address (well, close enough)
-		for (p = buff; *p; p++)
-			if ((*p < '0' || *p > '9') && *p != '.')
-				break;
-
-		// if it is a real name, strip off the domain; we only want the host
-		if (*p)
-		{
-			for (i = 0; i < 15; i++)
-				if (buff[i] == '.')
-					break;
-			buff[i] = 0;
-		}
-//		Cvar_Set ("hostname", buff);
-	}
-
-  //++timo WTF is that net_controlsocket? it's sole purpose is to retrieve the local IP?
-	if ((net_controlsocket = WINS_OpenSocket (0)) == SOCKET_ERROR)
-		WinError("WINS_Init: Unable to open control socket\n");
-
-	((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
-	((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
-	((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((u_short)net_hostport);
-
-	WINS_GetSocketAddr (net_controlsocket, &addr);
-	strcpy(my_tcpip_address,  WINS_AddrToString (&addr));
-	p = strrchr (my_tcpip_address, ':');
-	if (p) *p = 0;
-	WinPrint("Winsock Initialized\n");
-
-	return net_controlsocket;
-} //end of the function WINS_Init
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-char *WINS_MyAddress(void)
-{
-	return my_tcpip_address;
-} //end of the function WINS_MyAddress
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void WINS_Shutdown(void)
-{
-	//WINS_Listen(0);
-	WINS_CloseSocket(net_controlsocket);
-//	WSACleanup();
-	//
-	WinPrint("Winsock Shutdown\n");
-} //end of the function WINS_Shutdown
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-/*
-void WINS_Listen(int state)
-{
-	// enable listening
-	if (state)
-	{
-		if (net_acceptsocket != -1)
-			return;
-		if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1)
-			WinError ("WINS_Listen: Unable to open accept socket\n");
-		return;
-	}
-
-	// disable listening
-	if (net_acceptsocket == -1)
-		return;
-	WINS_CloseSocket (net_acceptsocket);
-	net_acceptsocket = -1;
-} //end of the function WINS_Listen*/
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_OpenSocket(int port)
-{
-	int newsocket;
-	struct sockaddr_in address;
-	u_long _true = 1;
-
-	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-
-	if (ioctlsocket (newsocket, FIONBIO, &_true) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		closesocket(newsocket);
-		return -1;
-	} //end if
-
-	memset((char *) &address, 0, sizeof(address));
-	address.sin_family = AF_INET;
-	address.sin_addr.s_addr = INADDR_ANY;
-	address.sin_port = htons((u_short)port);
-	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
-	{
-		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		closesocket(newsocket);
-		return -1;
-	} //end if
-
-	return newsocket;
-} //end of the function WINS_OpenSocket
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_OpenReliableSocket(int port)
-{
-	int newsocket;
-	struct sockaddr_in address;
-	qboolean _true = 0xFFFFFFFF;
-
-	//IPPROTO_TCP
-	//
-	if ((newsocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
-	{
-		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-
-	memset((char *) &address, 0, sizeof(address));
-	address.sin_family = AF_INET;
-	address.sin_addr.s_addr = htonl(INADDR_ANY);
-	address.sin_port = htons((u_short)port);
-	if (bind(newsocket, (void *)&address, sizeof(address)) == -1)
-	{
-		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		closesocket(newsocket);
-		return -1;
-	} //end if
-
-  //
-	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == -1)
-	{
-		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		WinPrint("setsockopt error\n");
-	} //end if
-
-	return newsocket;
-} //end of the function WINS_OpenReliableSocket
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Listen(int socket)
-{
-	u_long _true = 1;
-
-	if (ioctlsocket(socket, FIONBIO, &_true) == -1)
-	{
-		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	if (listen(socket, SOMAXCONN) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	return 0;
-} //end of the function WINS_Listen
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Accept(int socket, struct sockaddr_s *addr)
-{
-	int addrlen = sizeof (struct sockaddr_s);
-	int newsocket;
-	qboolean _true = 1;
-
-	newsocket = accept(socket, (struct sockaddr *)addr, &addrlen);
-	if (newsocket == INVALID_SOCKET)
-	{
-    if (errno == EAGAIN) return -1;
-		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	//
-	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		WinPrint("setsockopt error\n");
-	} //end if
-	return newsocket;
-} //end of the function WINS_Accept
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_CloseSocket(int socket)
-{
-	/*
-	if (socket == net_broadcastsocket)
-		net_broadcastsocket = 0;
-	*/
-//	shutdown(socket, SD_SEND);
-
-	if (closesocket(socket) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_CloseSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return SOCKET_ERROR;
-	} //end if
-	return 0;
-} //end of the function WINS_CloseSocket
-//===========================================================================
-// this lets you type only as much of the net address as required, using
-// the local network components to fill in the rest
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-static int PartialIPAddress (char *in, struct sockaddr_s *hostaddr)
-{
-	char buff[256];
-	char *b;
-	int addr;
-	int num;
-	int mask;
-	
-	buff[0] = '.';
-	b = buff;
-	strcpy(buff+1, in);
-	if (buff[1] == '.') b++;
-
-	addr = 0;
-	mask=-1;
-	while (*b == '.')
-	{
-		num = 0;
-		if (*++b < '0' || *b > '9') return -1;
-		while (!( *b < '0' || *b > '9'))
-		  num = num*10 + *(b++) - '0';
-		mask<<=8;
-		addr = (addr<<8) + num;
-	}
-	
-	hostaddr->sa_family = AF_INET;
-	((struct sockaddr_in *)hostaddr)->sin_port = htons((u_short)net_hostport);
-	((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
-	
-	return 0;
-} //end of the function PartialIPAddress
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Connect(int socket, struct sockaddr_s *addr)
-{
-	int ret;
-	u_long _true2 = 0xFFFFFFFF;
-
-	ret = connect(socket, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
-	if (ret == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	if (ioctlsocket(socket, FIONBIO, &_true2) == -1)
-	{
-		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	return 0;
-} //end of the function WINS_Connect
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_CheckNewConnections(void)
-{
-	char buf[4];
-
-	if (net_acceptsocket == -1)
-		return -1;
-
-	if (recvfrom(net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
-		return net_acceptsocket;
-	return -1;
-} //end of the function WINS_CheckNewConnections
-//===========================================================================
-// returns the number of bytes read
-// 0 if no bytes available
-// -1 on failure
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Read(int socket, byte *buf, int len, struct sockaddr_s *addr)
-{
-	int addrlen = sizeof (struct sockaddr_s);
-	int ret;
-
-	if (addr)
-	{
-		ret = recvfrom(socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
-		if (ret == -1)
-		{
-//			errno = WSAGetLastError();
-
-			if (errno == EAGAIN || errno == ENOTCONN)
-				return 0;
-		} //end if
-	} //end if
-	else
-	{
-		ret = recv(socket, buf, len, 0);
-    // if there's no data on the socket ret == -1 and errno == EAGAIN
-    // MSDN states that if ret == 0 the socket has been closed
-    // man recv doesn't say anything
-    if (ret == 0)
-      return -1;
-		if (ret == SOCKET_ERROR)
-		{
-//			errno = WSAGetLastError();
-
-			if (errno == EAGAIN || errno == ENOTCONN)
-				return 0;
-		} //end if
-	} //end else
-	if (ret == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Read: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-	} //end if
-	return ret;
-} //end of the function WINS_Read
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_MakeSocketBroadcastCapable (int socket)
-{
-	int	i = 1;
-
-	// make this socket broadcast capable
-	if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
-		return -1;
-	net_broadcastsocket = socket;
-
-	return 0;
-} //end of the function WINS_MakeSocketBroadcastCapable
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Broadcast (int socket, byte *buf, int len)
-{
-	int ret;
-
-	if (socket != net_broadcastsocket)
-	{
-		if (net_broadcastsocket != 0)
-			WinError("Attempted to use multiple broadcasts sockets\n");
-		ret = WINS_MakeSocketBroadcastCapable (socket);
-		if (ret == -1)
-		{
-			WinPrint("Unable to make socket broadcast capable\n");
-			return ret;
-		}
-	}
-
-	return WINS_Write (socket, buf, len, &broadcastaddr);
-} //end of the function WINS_Broadcast
-//===========================================================================
-// returns qtrue on success or qfalse on failure
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Write(int socket, byte *buf, int len, struct sockaddr_s *addr)
-{
-	int ret, written;
-
-	if (addr)
-	{
-		written = 0;
-		while(written < len)
-		{
-			ret = sendto (socket, &buf[written], len-written, 0, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
-			if (ret == SOCKET_ERROR)
-			{
-				if (WSAGetLastError() != EAGAIN)
-					return qfalse;
-					//++timo FIXME: what is this used for?
-//				Sleep(1000);
-			} //end if
-			else
-			{
-				written += ret;
-			}
-		}
-	} //end if
-	else
-	{
-		written = 0;
-		while(written < len)
-		{
-			ret = send(socket, buf, len, 0);
-			if (ret == SOCKET_ERROR)
-			{
-				if (WSAGetLastError() != EAGAIN)
-					return qfalse;
-					//++timo FIXME: what is this used for?
-//				Sleep(1000);
-			} //end if
-			else
-			{
-				written += ret;
-			}
-		}
-	} //end else
-	if (ret == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Write: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-	} //end if
-	return (ret == len);
-} //end of the function WINS_Write
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-char *WINS_AddrToString (struct sockaddr_s *addr)
-{
-	static char buffer[22];
-	int haddr;
-
-	haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
-	sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
-	return buffer;
-} //end of the function WINS_AddrToString
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_StringToAddr(char *string, struct sockaddr_s *addr)
-{
-	int ha1, ha2, ha3, ha4, hp;
-	int ipaddr;
-
-	sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
-	ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
-
-	addr->sa_family = AF_INET;
-	((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
-	((struct sockaddr_in *)addr)->sin_port = htons((u_short)hp);
-	return 0;
-} //end of the function WINS_StringToAddr
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetSocketAddr(int socket, struct sockaddr_s *addr)
-{
-	int addrlen = sizeof(struct sockaddr_s);
-	unsigned int a;
-
-	memset(addr, 0, sizeof(struct sockaddr_s));
-	getsockname(socket, (struct sockaddr *)addr, &addrlen);
-	a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
-	if (a == 0 || a == inet_addr("127.0.0.1"))
-		((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
-
-	return 0;
-} //end of the function WINS_GetSocketAddr
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetNameFromAddr (struct sockaddr_s *addr, char *name)
-{
-	struct hostent *hostentry;
-
-	hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
-	if (hostentry)
-	{
-		strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
-		return 0;
-	}
-
-	strcpy (name, WINS_AddrToString (addr));
-	return 0;
-} //end of the function WINS_GetNameFromAddr
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetAddrFromName(char *name, struct sockaddr_s *addr)
-{
-	struct hostent *hostentry;
-
-	if (name[0] >= '0' && name[0] <= '9')
-		return PartialIPAddress (name, addr);
-	
-	hostentry = gethostbyname (name);
-	if (!hostentry)
-		return -1;
-
-	addr->sa_family = AF_INET;
-	((struct sockaddr_in *)addr)->sin_port = htons((u_short)net_hostport);
-	((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
-
-	return 0;
-} //end of the function WINS_GetAddrFromName
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_AddrCompare (struct sockaddr_s *addr1, struct sockaddr_s *addr2)
-{
-	if (addr1->sa_family != addr2->sa_family)
-		return -1;
-
-	if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
-		return -1;
-
-	if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
-		return 1;
-
-	return 0;
-} //end of the function WINS_AddrCompare
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetSocketPort (struct sockaddr_s *addr)
-{
-	return ntohs(((struct sockaddr_in *)addr)->sin_port);
-} //end of the function WINS_GetSocketPort
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_SetSocketPort (struct sockaddr_s *addr, int port)
-{
-	((struct sockaddr_in *)addr)->sin_port = htons((u_short)port);
-	return 0;
-} //end of the function WINS_SetSocketPort
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//===========================================================================
+//
+// Name:         l_net_wins.c
+// Function:     WinSock
+// Programmer:   MrElusive
+// Last update:  TTimo: cross-platform version, l_net library
+// Tab Size:     2
+// Notes:
+//===========================================================================
+
+//#include <windows.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "l_net.h"
+#include "l_net_wins.h"
+
+#include <arpa/inet.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/ioctl.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <errno.h>
+#include <netdb.h>
+#define SOCKET_ERROR -1
+#define INVALID_SOCKET -1
+
+extern void WinPrint(char *str, ...);
+
+#define WinError WinPrint
+
+#define qtrue	1
+#define qfalse	0
+
+#define ioctlsocket ioctl
+#define closesocket close
+
+int WSAGetLastError()
+{
+	return errno;
+}
+
+/*
+typedef struct tag_error_struct
+{
+    int     errnum;
+    LPSTR   errstr;
+} ERROR_STRUCT;
+*/
+
+typedef struct tag_error_struct
+{
+    int     errnum;
+    const char *errstr;
+} ERROR_STRUCT;
+
+#define	NET_NAMELEN			64
+
+static char my_tcpip_address[NET_NAMELEN];
+
+#define	DEFAULTnet_hostport	26000
+
+#define MAXHOSTNAMELEN		256
+
+static int net_acceptsocket = -1;		// socket for fielding new connections
+static int net_controlsocket;
+static int net_hostport;				// udp port number for acceptsocket
+static int net_broadcastsocket = 0;
+//static qboolean ifbcastinit = qfalse;
+//static struct sockaddr_s broadcastaddr;
+static struct sockaddr_s broadcastaddr;
+
+static unsigned long myAddr;
+
+ERROR_STRUCT errlist[] = {
+  {EACCES,"EACCES - The address is protected, user is not root"},
+  {EAGAIN,"EAGAIN - Operation on non-blocking socket that cannot return immediatly"},
+  {EBADF, "EBADF - sockfd is not a valid descriptor"},
+  {EFAULT, "EFAULT - The parameter is not in a writable part of the user address space"},
+  {EINVAL,"EINVAL - The socket is already bound to an address"},
+  {ENOBUFS,"ENOBUFS - not enough memory"},
+  {ENOMEM, "ENOMEM - not enough memory"},
+  {ENOTCONN, "ENOTCONN - not connected"},
+  {ENOTSOCK,"ENOTSOCK - Argument is file descriptor not a socket"},
+  {EOPNOTSUPP,"ENOTSUPP - The referenced socket is not of type SOCK_STREAM"},
+  {EPERM, "EPERM - Firewall rules forbid connection"},
+  {-1, NULL}
+};
+
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+char *WINS_ErrorMessage(int error)
+{
+    int search = 0;
+
+    if (!error) return "No error occurred";
+
+	 for (search = 0; errlist[search].errstr; search++)
+	 {
+		if (error == errlist[search].errnum)
+				return (char *)errlist[search].errstr;
+	 } //end for
+
+    return "Unknown error";
+} //end of the function WINS_ErrorMessage
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Init(void)
+{
+	int		i;
+	struct hostent *local;
+	char	buff[MAXHOSTNAMELEN];
+	struct sockaddr_s addr;
+	char	*p;
+	int		r;
+/* 
+ linux doesn't have anything to initialize for the net
+ "Windows .. built for the internet .. the internet .. built with unix" 
+ */
+#if 0
+	WORD	wVersionRequested; 
+
+	wVersionRequested = MAKEWORD(2, 2);
+
+	r = WSAStartup (wVersionRequested, &winsockdata);
+
+	if (r)
+	{
+		WinPrint("Winsock initialization failed.\n");
+		return -1;
+	}
+#endif
+	/*
+	i = COM_CheckParm ("-udpport");
+	if (i == 0)*/
+		net_hostport = DEFAULTnet_hostport;
+	/*
+	else if (i < com_argc-1)
+		net_hostport = Q_atoi (com_argv[i+1]);
+	else
+		Sys_Error ("WINS_Init: you must specify a number after -udpport");
+	*/
+
+	// determine my name & address
+	gethostname(buff, MAXHOSTNAMELEN);
+	local = gethostbyname(buff);
+	myAddr = *(int *)local->h_addr_list[0];
+
+	// if the quake hostname isn't set, set it to the machine name
+//	if (Q_strcmp(hostname.string, "UNNAMED") == 0)
+	{
+		// see if it's a text IP address (well, close enough)
+		for (p = buff; *p; p++)
+			if ((*p < '0' || *p > '9') && *p != '.')
+				break;
+
+		// if it is a real name, strip off the domain; we only want the host
+		if (*p)
+		{
+			for (i = 0; i < 15; i++)
+				if (buff[i] == '.')
+					break;
+			buff[i] = 0;
+		}
+//		Cvar_Set ("hostname", buff);
+	}
+
+  //++timo WTF is that net_controlsocket? it's sole purpose is to retrieve the local IP?
+	if ((net_controlsocket = WINS_OpenSocket (0)) == SOCKET_ERROR)
+		WinError("WINS_Init: Unable to open control socket\n");
+
+	((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
+	((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
+	((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((u_short)net_hostport);
+
+	WINS_GetSocketAddr (net_controlsocket, &addr);
+	strcpy(my_tcpip_address,  WINS_AddrToString (&addr));
+	p = strrchr (my_tcpip_address, ':');
+	if (p) *p = 0;
+	WinPrint("Winsock Initialized\n");
+
+	return net_controlsocket;
+} //end of the function WINS_Init
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+char *WINS_MyAddress(void)
+{
+	return my_tcpip_address;
+} //end of the function WINS_MyAddress
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void WINS_Shutdown(void)
+{
+	//WINS_Listen(0);
+	WINS_CloseSocket(net_controlsocket);
+//	WSACleanup();
+	//
+	WinPrint("Winsock Shutdown\n");
+} //end of the function WINS_Shutdown
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+/*
+void WINS_Listen(int state)
+{
+	// enable listening
+	if (state)
+	{
+		if (net_acceptsocket != -1)
+			return;
+		if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1)
+			WinError ("WINS_Listen: Unable to open accept socket\n");
+		return;
+	}
+
+	// disable listening
+	if (net_acceptsocket == -1)
+		return;
+	WINS_CloseSocket (net_acceptsocket);
+	net_acceptsocket = -1;
+} //end of the function WINS_Listen*/
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_OpenSocket(int port)
+{
+	int newsocket;
+	struct sockaddr_in address;
+	u_long _true = 1;
+
+	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+
+	if (ioctlsocket (newsocket, FIONBIO, &_true) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		closesocket(newsocket);
+		return -1;
+	} //end if
+
+	memset((char *) &address, 0, sizeof(address));
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = INADDR_ANY;
+	address.sin_port = htons((u_short)port);
+	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
+	{
+		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		closesocket(newsocket);
+		return -1;
+	} //end if
+
+	return newsocket;
+} //end of the function WINS_OpenSocket
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_OpenReliableSocket(int port)
+{
+	int newsocket;
+	struct sockaddr_in address;
+	qboolean _true = 0xFFFFFFFF;
+
+	//IPPROTO_TCP
+	//
+	if ((newsocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+	{
+		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+
+	memset((char *) &address, 0, sizeof(address));
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = htonl(INADDR_ANY);
+	address.sin_port = htons((u_short)port);
+	if (bind(newsocket, (void *)&address, sizeof(address)) == -1)
+	{
+		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		closesocket(newsocket);
+		return -1;
+	} //end if
+
+  //
+	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == -1)
+	{
+		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		WinPrint("setsockopt error\n");
+	} //end if
+
+	return newsocket;
+} //end of the function WINS_OpenReliableSocket
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Listen(int socket)
+{
+	u_long _true = 1;
+
+	if (ioctlsocket(socket, FIONBIO, &_true) == -1)
+	{
+		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	if (listen(socket, SOMAXCONN) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	return 0;
+} //end of the function WINS_Listen
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Accept(int socket, struct sockaddr_s *addr)
+{
+	int addrlen = sizeof (struct sockaddr_s);
+	int newsocket;
+	qboolean _true = 1;
+
+	newsocket = accept(socket, (struct sockaddr *)addr, &addrlen);
+	if (newsocket == INVALID_SOCKET)
+	{
+    if (errno == EAGAIN) return -1;
+		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	//
+	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		WinPrint("setsockopt error\n");
+	} //end if
+	return newsocket;
+} //end of the function WINS_Accept
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_CloseSocket(int socket)
+{
+	/*
+	if (socket == net_broadcastsocket)
+		net_broadcastsocket = 0;
+	*/
+//	shutdown(socket, SD_SEND);
+
+	if (closesocket(socket) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_CloseSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return SOCKET_ERROR;
+	} //end if
+	return 0;
+} //end of the function WINS_CloseSocket
+//===========================================================================
+// this lets you type only as much of the net address as required, using
+// the local network components to fill in the rest
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+static int PartialIPAddress (char *in, struct sockaddr_s *hostaddr)
+{
+	char buff[256];
+	char *b;
+	int addr;
+	int num;
+	int mask;
+	
+	buff[0] = '.';
+	b = buff;
+	strcpy(buff+1, in);
+	if (buff[1] == '.') b++;
+
+	addr = 0;
+	mask=-1;
+	while (*b == '.')
+	{
+		num = 0;
+		if (*++b < '0' || *b > '9') return -1;
+		while (!( *b < '0' || *b > '9'))
+		  num = num*10 + *(b++) - '0';
+		mask<<=8;
+		addr = (addr<<8) + num;
+	}
+	
+	hostaddr->sa_family = AF_INET;
+	((struct sockaddr_in *)hostaddr)->sin_port = htons((u_short)net_hostport);
+	((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
+	
+	return 0;
+} //end of the function PartialIPAddress
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Connect(int socket, struct sockaddr_s *addr)
+{
+	int ret;
+	u_long _true2 = 0xFFFFFFFF;
+
+	ret = connect(socket, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
+	if (ret == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	if (ioctlsocket(socket, FIONBIO, &_true2) == -1)
+	{
+		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	return 0;
+} //end of the function WINS_Connect
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_CheckNewConnections(void)
+{
+	char buf[4];
+
+	if (net_acceptsocket == -1)
+		return -1;
+
+	if (recvfrom(net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
+		return net_acceptsocket;
+	return -1;
+} //end of the function WINS_CheckNewConnections
+//===========================================================================
+// returns the number of bytes read
+// 0 if no bytes available
+// -1 on failure
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Read(int socket, byte *buf, int len, struct sockaddr_s *addr)
+{
+	int addrlen = sizeof (struct sockaddr_s);
+	int ret;
+
+	if (addr)
+	{
+		ret = recvfrom(socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
+		if (ret == -1)
+		{
+//			errno = WSAGetLastError();
+
+			if (errno == EAGAIN || errno == ENOTCONN)
+				return 0;
+		} //end if
+	} //end if
+	else
+	{
+		ret = recv(socket, buf, len, 0);
+    // if there's no data on the socket ret == -1 and errno == EAGAIN
+    // MSDN states that if ret == 0 the socket has been closed
+    // man recv doesn't say anything
+    if (ret == 0)
+      return -1;
+		if (ret == SOCKET_ERROR)
+		{
+//			errno = WSAGetLastError();
+
+			if (errno == EAGAIN || errno == ENOTCONN)
+				return 0;
+		} //end if
+	} //end else
+	if (ret == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Read: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+	} //end if
+	return ret;
+} //end of the function WINS_Read
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_MakeSocketBroadcastCapable (int socket)
+{
+	int	i = 1;
+
+	// make this socket broadcast capable
+	if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
+		return -1;
+	net_broadcastsocket = socket;
+
+	return 0;
+} //end of the function WINS_MakeSocketBroadcastCapable
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Broadcast (int socket, byte *buf, int len)
+{
+	int ret;
+
+	if (socket != net_broadcastsocket)
+	{
+		if (net_broadcastsocket != 0)
+			WinError("Attempted to use multiple broadcasts sockets\n");
+		ret = WINS_MakeSocketBroadcastCapable (socket);
+		if (ret == -1)
+		{
+			WinPrint("Unable to make socket broadcast capable\n");
+			return ret;
+		}
+	}
+
+	return WINS_Write (socket, buf, len, &broadcastaddr);
+} //end of the function WINS_Broadcast
+//===========================================================================
+// returns qtrue on success or qfalse on failure
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Write(int socket, byte *buf, int len, struct sockaddr_s *addr)
+{
+	int ret, written;
+
+	if (addr)
+	{
+		written = 0;
+		while(written < len)
+		{
+			ret = sendto (socket, &buf[written], len-written, 0, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
+			if (ret == SOCKET_ERROR)
+			{
+				if (WSAGetLastError() != EAGAIN)
+					return qfalse;
+					//++timo FIXME: what is this used for?
+//				Sleep(1000);
+			} //end if
+			else
+			{
+				written += ret;
+			}
+		}
+	} //end if
+	else
+	{
+		written = 0;
+		while(written < len)
+		{
+			ret = send(socket, buf, len, 0);
+			if (ret == SOCKET_ERROR)
+			{
+				if (WSAGetLastError() != EAGAIN)
+					return qfalse;
+					//++timo FIXME: what is this used for?
+//				Sleep(1000);
+			} //end if
+			else
+			{
+				written += ret;
+			}
+		}
+	} //end else
+	if (ret == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Write: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+	} //end if
+	return (ret == len);
+} //end of the function WINS_Write
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+char *WINS_AddrToString (struct sockaddr_s *addr)
+{
+	static char buffer[22];
+	int haddr;
+
+	haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
+	sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
+	return buffer;
+} //end of the function WINS_AddrToString
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_StringToAddr(char *string, struct sockaddr_s *addr)
+{
+	int ha1, ha2, ha3, ha4, hp;
+	int ipaddr;
+
+	sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
+	ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
+
+	addr->sa_family = AF_INET;
+	((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
+	((struct sockaddr_in *)addr)->sin_port = htons((u_short)hp);
+	return 0;
+} //end of the function WINS_StringToAddr
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetSocketAddr(int socket, struct sockaddr_s *addr)
+{
+	int addrlen = sizeof(struct sockaddr_s);
+	unsigned int a;
+
+	memset(addr, 0, sizeof(struct sockaddr_s));
+	getsockname(socket, (struct sockaddr *)addr, &addrlen);
+	a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+	if (a == 0 || a == inet_addr("127.0.0.1"))
+		((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
+
+	return 0;
+} //end of the function WINS_GetSocketAddr
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetNameFromAddr (struct sockaddr_s *addr, char *name)
+{
+	struct hostent *hostentry;
+
+	hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
+	if (hostentry)
+	{
+		strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
+		return 0;
+	}
+
+	strcpy (name, WINS_AddrToString (addr));
+	return 0;
+} //end of the function WINS_GetNameFromAddr
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetAddrFromName(char *name, struct sockaddr_s *addr)
+{
+	struct hostent *hostentry;
+
+	if (name[0] >= '0' && name[0] <= '9')
+		return PartialIPAddress (name, addr);
+	
+	hostentry = gethostbyname (name);
+	if (!hostentry)
+		return -1;
+
+	addr->sa_family = AF_INET;
+	((struct sockaddr_in *)addr)->sin_port = htons((u_short)net_hostport);
+	((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
+
+	return 0;
+} //end of the function WINS_GetAddrFromName
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_AddrCompare (struct sockaddr_s *addr1, struct sockaddr_s *addr2)
+{
+	if (addr1->sa_family != addr2->sa_family)
+		return -1;
+
+	if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
+		return -1;
+
+	if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
+		return 1;
+
+	return 0;
+} //end of the function WINS_AddrCompare
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetSocketPort (struct sockaddr_s *addr)
+{
+	return ntohs(((struct sockaddr_in *)addr)->sin_port);
+} //end of the function WINS_GetSocketPort
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_SetSocketPort (struct sockaddr_s *addr, int port)
+{
+	((struct sockaddr_in *)addr)->sin_port = htons((u_short)port);
+	return 0;
+} //end of the function WINS_SetSocketPort
diff --git a/libs/l_net/l_net_wins.c b/libs/l_net/l_net_wins.c
index 56ee6789..8a73f996 100644
--- a/libs/l_net/l_net_wins.c
+++ b/libs/l_net/l_net_wins.c
@@ -1,789 +1,789 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//===========================================================================
-//
-// Name:         l_net_wins.c
-// Function:     WinSock
-// Programmer:   MrElusive
-// Last update:  -
-// Tab Size:     3
-// Notes:
-//===========================================================================
-
-#include <windows.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include "l_net.h"
-#include "l_net_wins.h"
-//#include <winsock.h>
-//#include "mpdosock.h"
-
-#define WinError WinPrint
-
-#define qtrue	1
-#define qfalse	0
-
-typedef struct tag_error_struct
-{
-    int     errnum;
-    LPSTR   errstr;
-} ERROR_STRUCT;
-
-#define	NET_NAMELEN			64
-
-char my_tcpip_address[NET_NAMELEN];
-
-#define	DEFAULTnet_hostport	26000
-
-#define MAXHOSTNAMELEN		256
-
-static int net_acceptsocket = -1;		// socket for fielding new connections
-static int net_controlsocket;
-static int net_hostport;				// udp port number for acceptsocket
-static int net_broadcastsocket = 0;
-//static qboolean ifbcastinit = qfalse;
-static struct sockaddr_s broadcastaddr;
-
-static unsigned long myAddr;
-
-WSADATA winsockdata;
-
-ERROR_STRUCT errlist[] = {
-    {WSAEINTR,           "WSAEINTR - Interrupted"},
-    {WSAEBADF,           "WSAEBADF - Bad file number"},
-    {WSAEFAULT,          "WSAEFAULT - Bad address"},
-    {WSAEINVAL,          "WSAEINVAL - Invalid argument"},
-    {WSAEMFILE,          "WSAEMFILE - Too many open files"},
-
-/*
-*    Windows Sockets definitions of regular Berkeley error constants
-*/
-
-    {WSAEWOULDBLOCK,     "WSAEWOULDBLOCK - Socket marked as non-blocking"},
-    {WSAEINPROGRESS,     "WSAEINPROGRESS - Blocking call in progress"},
-    {WSAEALREADY,        "WSAEALREADY - Command already completed"},
-    {WSAENOTSOCK,        "WSAENOTSOCK - Descriptor is not a socket"},
-    {WSAEDESTADDRREQ,    "WSAEDESTADDRREQ - Destination address required"},
-    {WSAEMSGSIZE,        "WSAEMSGSIZE - Data size too large"},
-    {WSAEPROTOTYPE,      "WSAEPROTOTYPE - Protocol is of wrong type for this socket"},
-    {WSAENOPROTOOPT,     "WSAENOPROTOOPT - Protocol option not supported for this socket type"},
-    {WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT - Protocol is not supported"},
-    {WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT - Socket type not supported by this address family"},
-    {WSAEOPNOTSUPP,      "WSAEOPNOTSUPP - Option not supported"},
-    {WSAEPFNOSUPPORT,    "WSAEPFNOSUPPORT - "},
-    {WSAEAFNOSUPPORT,    "WSAEAFNOSUPPORT - Address family not supported by this protocol"},
-    {WSAEADDRINUSE,      "WSAEADDRINUSE - Address is in use"},
-    {WSAEADDRNOTAVAIL,   "WSAEADDRNOTAVAIL - Address not available from local machine"},
-    {WSAENETDOWN,        "WSAENETDOWN - Network subsystem is down"},
-    {WSAENETUNREACH,     "WSAENETUNREACH - Network cannot be reached"},
-    {WSAENETRESET,       "WSAENETRESET - Connection has been dropped"},
-    {WSAECONNABORTED,    "WSAECONNABORTED - Connection aborted"},
-    {WSAECONNRESET,      "WSAECONNRESET - Connection reset"},
-    {WSAENOBUFS,         "WSAENOBUFS - No buffer space available"},
-    {WSAEISCONN,         "WSAEISCONN - Socket is already connected"},
-    {WSAENOTCONN,        "WSAENOTCONN - Socket is not connected"},
-    {WSAESHUTDOWN,       "WSAESHUTDOWN - Socket has been shut down"},
-    {WSAETOOMANYREFS,    "WSAETOOMANYREFS - Too many references"},
-    {WSAETIMEDOUT,       "WSAETIMEDOUT - Command timed out"},
-    {WSAECONNREFUSED,    "WSAECONNREFUSED - Connection refused"},
-    {WSAELOOP,           "WSAELOOP - "},
-    {WSAENAMETOOLONG,    "WSAENAMETOOLONG - "},
-    {WSAEHOSTDOWN,       "WSAEHOSTDOWN - Host is down"},
-    {WSAEHOSTUNREACH,    "WSAEHOSTUNREACH - "},
-    {WSAENOTEMPTY,       "WSAENOTEMPTY - "},
-    {WSAEPROCLIM,        "WSAEPROCLIM - "},
-    {WSAEUSERS,          "WSAEUSERS - "},
-    {WSAEDQUOT,          "WSAEDQUOT - "},
-    {WSAESTALE,          "WSAESTALE - "},
-    {WSAEREMOTE,         "WSAEREMOTE - "},
-
-/*
-*    Extended Windows Sockets error constant definitions
-*/
-
-    {WSASYSNOTREADY,     "WSASYSNOTREADY - Network subsystem not ready"},
-    {WSAVERNOTSUPPORTED, "WSAVERNOTSUPPORTED - Version not supported"},
-    {WSANOTINITIALISED,  "WSANOTINITIALISED - WSAStartup() has not been successfully called"},
-
-/*
-*    Other error constants.
-*/
-
-    {WSAHOST_NOT_FOUND,  "WSAHOST_NOT_FOUND - Host not found"},
-    {WSATRY_AGAIN,       "WSATRY_AGAIN - Host not found or SERVERFAIL"},
-    {WSANO_RECOVERY,     "WSANO_RECOVERY - Non-recoverable error"},
-    {WSANO_DATA,         "WSANO_DATA - (or WSANO_ADDRESS) - No data record of requested type"},
-    {-1,                 NULL}
-};
-
-#ifdef _DEBUG
-void WinPrint(char *str, ...);
-#else
-void WinPrint(char *str, ...);
-#endif
-
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-char *WINS_ErrorMessage(int error)
-{
-    int search = 0;
-
-    if (!error) return "No error occurred";
-
-	 for (search = 0; errlist[search].errstr; search++)
-	 {
-		if (error == errlist[search].errnum)
-				return errlist[search].errstr;
-	 } //end for
-
-    return "Unknown error";
-} //end of the function WINS_ErrorMessage
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Init(void)
-{
-	int		i;
-	struct hostent *local;
-	char	buff[MAXHOSTNAMELEN];
-	struct sockaddr_s addr;
-	char	*p;
-	int		r;
-	WORD	wVersionRequested; 
-
-	wVersionRequested = MAKEWORD(1, 1);
-
-	r = WSAStartup (wVersionRequested, &winsockdata);
-
-	if (r)
-	{
-		WinPrint("Winsock initialization failed.\n");
-		return -1;
-	}
-
-	/*
-	i = COM_CheckParm ("-udpport");
-	if (i == 0)*/
-		net_hostport = DEFAULTnet_hostport;
-	/*
-	else if (i < com_argc-1)
-		net_hostport = Q_atoi (com_argv[i+1]);
-	else
-		Sys_Error ("WINS_Init: you must specify a number after -udpport");
-	*/
-
-	// determine my name & address
-	gethostname(buff, MAXHOSTNAMELEN);
-	local = gethostbyname(buff);
-	myAddr = *(int *)local->h_addr_list[0];
-
-	// if the quake hostname isn't set, set it to the machine name
-//	if (Q_strcmp(hostname.string, "UNNAMED") == 0)
-	{
-		// see if it's a text IP address (well, close enough)
-		for (p = buff; *p; p++)
-			if ((*p < '0' || *p > '9') && *p != '.')
-				break;
-
-		// if it is a real name, strip off the domain; we only want the host
-		if (*p)
-		{
-			for (i = 0; i < 15; i++)
-				if (buff[i] == '.')
-					break;
-			buff[i] = 0;
-		}
-//		Cvar_Set ("hostname", buff);
-	}
-
-	if ((net_controlsocket = WINS_OpenSocket (0)) == -1)
-		WinError("WINS_Init: Unable to open control socket\n");
-
-	((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
-	((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
-	((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((u_short)net_hostport);
-
-	WINS_GetSocketAddr (net_controlsocket, &addr);
-	strcpy(my_tcpip_address,  WINS_AddrToString (&addr));
-	p = strrchr (my_tcpip_address, ':');
-	if (p) *p = 0;
-	WinPrint("Winsock Initialized\n");
-
-	return net_controlsocket;
-} //end of the function WINS_Init
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-char *WINS_MyAddress(void)
-{
-	return my_tcpip_address;
-} //end of the function WINS_MyAddress
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-void WINS_Shutdown(void)
-{
-	//WINS_Listen(0);
-	WINS_CloseSocket(net_controlsocket);
-	WSACleanup();
-	//
-	WinPrint("Winsock Shutdown\n");
-} //end of the function WINS_Shutdown
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-/*
-void WINS_Listen(int state)
-{
-	// enable listening
-	if (state)
-	{
-		if (net_acceptsocket != -1)
-			return;
-		if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1)
-			WinError ("WINS_Listen: Unable to open accept socket\n");
-		return;
-	}
-
-	// disable listening
-	if (net_acceptsocket == -1)
-		return;
-	WINS_CloseSocket (net_acceptsocket);
-	net_acceptsocket = -1;
-} //end of the function WINS_Listen*/
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_OpenSocket(int port)
-{
-	int newsocket;
-	struct sockaddr_in address;
-	u_long _true = 1;
-
-	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
-	{
-		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-
-	if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
-	{
-		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		closesocket(newsocket);
-		return -1;
-	} //end if
-
-	memset((char *) &address, 0, sizeof(address));
-	address.sin_family = AF_INET;
-	address.sin_addr.s_addr = INADDR_ANY;
-	address.sin_port = htons((u_short)port);
-	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
-	{
-		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		closesocket(newsocket);
-		return -1;
-	} //end if
-
-	return newsocket;
-} //end of the function WINS_OpenSocket
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_OpenReliableSocket(int port)
-{
-	int newsocket;
-	struct sockaddr_in address;
-	BOOL _true = 0xFFFFFFFF;
-
-	//IPPROTO_TCP
-	//
-	if ((newsocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
-	{
-		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-
-	memset((char *) &address, 0, sizeof(address));
-	address.sin_family = AF_INET;
-	address.sin_addr.s_addr = htonl(INADDR_ANY);
-	address.sin_port = htons((u_short)port);
-	if (bind(newsocket, (void *)&address, sizeof(address)) == -1)
-	{
-		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		closesocket(newsocket);
-		return -1;
-	} //end if
-
-  //
-	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		WinPrint("setsockopt error\n");
-	} //end if
-
-	return newsocket;
-} //end of the function WINS_OpenReliableSocket
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Listen(int socket)
-{
-	u_long _true = 1;
-
-	if (ioctlsocket(socket, FIONBIO, &_true) == -1)
-	{
-		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	if (listen(socket, SOMAXCONN) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	return 0;
-} //end of the function WINS_Listen
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Accept(int socket, struct sockaddr_s *addr)
-{
-	int addrlen = sizeof (struct sockaddr_s);
-	int newsocket;
-	BOOL _true = 1;
-
-	newsocket = accept(socket, (struct sockaddr *)addr, &addrlen);
-	if (newsocket == INVALID_SOCKET)
-	{
-		if (WSAGetLastError() == WSAEWOULDBLOCK) return -1;
-		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	//
-	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		WinPrint("setsockopt error\n");
-	} //end if
-	return newsocket;
-} //end of the function WINS_Accept
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_CloseSocket(int socket)
-{
-	/*
-	if (socket == net_broadcastsocket)
-		net_broadcastsocket = 0;
-	*/
-//	shutdown(socket, SD_SEND);
-
-	if (closesocket(socket) == SOCKET_ERROR)
-	{
-		WinPrint("WINS_CloseSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return SOCKET_ERROR;
-	} //end if
-	return 0;
-} //end of the function WINS_CloseSocket
-//===========================================================================
-// this lets you type only as much of the net address as required, using
-// the local network components to fill in the rest
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-static int PartialIPAddress (char *in, struct sockaddr_s *hostaddr)
-{
-	char buff[256];
-	char *b;
-	int addr;
-	int num;
-	int mask;
-	
-	buff[0] = '.';
-	b = buff;
-	strcpy(buff+1, in);
-	if (buff[1] == '.') b++;
-
-	addr = 0;
-	mask=-1;
-	while (*b == '.')
-	{
-		num = 0;
-		if (*++b < '0' || *b > '9') return -1;
-		while (!( *b < '0' || *b > '9'))
-		  num = num*10 + *(b++) - '0';
-		mask<<=8;
-		addr = (addr<<8) + num;
-	}
-	
-	hostaddr->sa_family = AF_INET;
-	((struct sockaddr_in *)hostaddr)->sin_port = htons((u_short)net_hostport);
-	((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
-	
-	return 0;
-} //end of the function PartialIPAddress
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Connect(int socket, struct sockaddr_s *addr)
-{
-	int ret;
-	u_long _true2 = 0xFFFFFFFF;
-
-	ret = connect(socket, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
-	if (ret == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	if (ioctlsocket(socket, FIONBIO, &_true2) == -1)
-	{
-		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-		return -1;
-	} //end if
-	return 0;
-} //end of the function WINS_Connect
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_CheckNewConnections(void)
-{
-	char buf[4];
-
-	if (net_acceptsocket == -1)
-		return -1;
-
-	if (recvfrom(net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
-		return net_acceptsocket;
-	return -1;
-} //end of the function WINS_CheckNewConnections
-//===========================================================================
-// returns the number of bytes read
-// 0 if no bytes available
-// -1 on failure
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Read(int socket, byte *buf, int len, struct sockaddr_s *addr)
-{
-	int addrlen = sizeof (struct sockaddr_s);
-	int ret, errno;
-
-	if (addr)
-	{
-		ret = recvfrom(socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
-		if (ret == -1)
-		{
-			errno = WSAGetLastError();
-
-			if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
-				return 0;
-		} //end if
-	} //end if
-	else
-	{
-		ret = recv(socket, buf, len, 0);
-		if (ret == SOCKET_ERROR)
-		{
-			errno = WSAGetLastError();
-
-			if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
-				return 0;
-		} //end if
-	} //end else
-	if (ret == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Read: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-	} //end if
-	return ret;
-} //end of the function WINS_Read
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_MakeSocketBroadcastCapable (int socket)
-{
-	int	i = 1;
-
-	// make this socket broadcast capable
-	if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
-		return -1;
-	net_broadcastsocket = socket;
-
-	return 0;
-} //end of the function WINS_MakeSocketBroadcastCapable
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Broadcast (int socket, byte *buf, int len)
-{
-	int ret;
-
-	if (socket != net_broadcastsocket)
-	{
-		if (net_broadcastsocket != 0)
-			WinError("Attempted to use multiple broadcasts sockets\n");
-		ret = WINS_MakeSocketBroadcastCapable (socket);
-		if (ret == -1)
-		{
-			WinPrint("Unable to make socket broadcast capable\n");
-			return ret;
-		}
-	}
-
-	return WINS_Write (socket, buf, len, &broadcastaddr);
-} //end of the function WINS_Broadcast
-//===========================================================================
-// returns qtrue on success or qfalse on failure
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_Write(int socket, byte *buf, int len, struct sockaddr_s *addr)
-{
-	int ret, written;
-
-	if (addr)
-	{
-		written = 0;
-		while(written < len)
-		{
-			ret = sendto (socket, &buf[written], len-written, 0, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
-			if (ret == SOCKET_ERROR)
-			{
-				if (WSAGetLastError() != WSAEWOULDBLOCK)
-					return qfalse;
-				Sleep(1000);
-			} //end if
-			else
-			{
-				written += ret;
-			}
-		}
-	} //end if
-	else
-	{
-		written = 0;
-		while(written < len)
-		{
-			ret = send(socket, buf, len, 0);
-			if (ret == SOCKET_ERROR)
-			{
-				if (WSAGetLastError() != WSAEWOULDBLOCK)
-					return qfalse;
-				Sleep(1000);
-			} //end if
-			else
-			{
-				written += ret;
-			}
-		}
-	} //end else
-	if (ret == SOCKET_ERROR)
-	{
-		WinPrint("WINS_Write: %s\n", WINS_ErrorMessage(WSAGetLastError()));
-	} //end if
-	return (ret == len);
-} //end of the function WINS_Write
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-char *WINS_AddrToString (struct sockaddr_s *addr)
-{
-	static char buffer[22];
-	int haddr;
-
-	haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
-	sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
-	return buffer;
-} //end of the function WINS_AddrToString
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_StringToAddr(char *string, struct sockaddr_s *addr)
-{
-	int ha1, ha2, ha3, ha4, hp;
-	int ipaddr;
-
-	sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
-	ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
-
-	addr->sa_family = AF_INET;
-	((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
-	((struct sockaddr_in *)addr)->sin_port = htons((u_short)hp);
-	return 0;
-} //end of the function WINS_StringToAddr
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetSocketAddr(int socket, struct sockaddr_s *addr)
-{
-	int addrlen = sizeof(struct sockaddr_s);
-	unsigned int a;
-
-	memset(addr, 0, sizeof(struct sockaddr_s));
-	getsockname(socket, (struct sockaddr *)addr, &addrlen);
-	a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
-	if (a == 0 || a == inet_addr("127.0.0.1"))
-		((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
-
-	return 0;
-} //end of the function WINS_GetSocketAddr
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetNameFromAddr (struct sockaddr_s *addr, char *name)
-{
-	struct hostent *hostentry;
-
-	hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
-	if (hostentry)
-	{
-		strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
-		return 0;
-	}
-
-	strcpy (name, WINS_AddrToString (addr));
-	return 0;
-} //end of the function WINS_GetNameFromAddr
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetAddrFromName(char *name, struct sockaddr_s *addr)
-{
-	struct hostent *hostentry;
-
-	if (name[0] >= '0' && name[0] <= '9')
-		return PartialIPAddress (name, addr);
-	
-	hostentry = gethostbyname (name);
-	if (!hostentry)
-		return -1;
-
-	addr->sa_family = AF_INET;
-	((struct sockaddr_in *)addr)->sin_port = htons((u_short)net_hostport);
-	((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
-
-	return 0;
-} //end of the function WINS_GetAddrFromName
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_AddrCompare (struct sockaddr_s *addr1, struct sockaddr_s *addr2)
-{
-	if (addr1->sa_family != addr2->sa_family)
-		return -1;
-
-	if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
-		return -1;
-
-	if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
-		return 1;
-
-	return 0;
-} //end of the function WINS_AddrCompare
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_GetSocketPort (struct sockaddr_s *addr)
-{
-	return ntohs(((struct sockaddr_in *)addr)->sin_port);
-} //end of the function WINS_GetSocketPort
-//===========================================================================
-//
-// Parameter:				-
-// Returns:					-
-// Changes Globals:		-
-//===========================================================================
-int WINS_SetSocketPort (struct sockaddr_s *addr, int port)
-{
-	((struct sockaddr_in *)addr)->sin_port = htons((u_short)port);
-	return 0;
-} //end of the function WINS_SetSocketPort
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//===========================================================================
+//
+// Name:         l_net_wins.c
+// Function:     WinSock
+// Programmer:   MrElusive
+// Last update:  -
+// Tab Size:     3
+// Notes:
+//===========================================================================
+
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "l_net.h"
+#include "l_net_wins.h"
+//#include <winsock.h>
+//#include "mpdosock.h"
+
+#define WinError WinPrint
+
+#define qtrue	1
+#define qfalse	0
+
+typedef struct tag_error_struct
+{
+    int     errnum;
+    LPSTR   errstr;
+} ERROR_STRUCT;
+
+#define	NET_NAMELEN			64
+
+char my_tcpip_address[NET_NAMELEN];
+
+#define	DEFAULTnet_hostport	26000
+
+#define MAXHOSTNAMELEN		256
+
+static int net_acceptsocket = -1;		// socket for fielding new connections
+static int net_controlsocket;
+static int net_hostport;				// udp port number for acceptsocket
+static int net_broadcastsocket = 0;
+//static qboolean ifbcastinit = qfalse;
+static struct sockaddr_s broadcastaddr;
+
+static unsigned long myAddr;
+
+WSADATA winsockdata;
+
+ERROR_STRUCT errlist[] = {
+    {WSAEINTR,           "WSAEINTR - Interrupted"},
+    {WSAEBADF,           "WSAEBADF - Bad file number"},
+    {WSAEFAULT,          "WSAEFAULT - Bad address"},
+    {WSAEINVAL,          "WSAEINVAL - Invalid argument"},
+    {WSAEMFILE,          "WSAEMFILE - Too many open files"},
+
+/*
+*    Windows Sockets definitions of regular Berkeley error constants
+*/
+
+    {WSAEWOULDBLOCK,     "WSAEWOULDBLOCK - Socket marked as non-blocking"},
+    {WSAEINPROGRESS,     "WSAEINPROGRESS - Blocking call in progress"},
+    {WSAEALREADY,        "WSAEALREADY - Command already completed"},
+    {WSAENOTSOCK,        "WSAENOTSOCK - Descriptor is not a socket"},
+    {WSAEDESTADDRREQ,    "WSAEDESTADDRREQ - Destination address required"},
+    {WSAEMSGSIZE,        "WSAEMSGSIZE - Data size too large"},
+    {WSAEPROTOTYPE,      "WSAEPROTOTYPE - Protocol is of wrong type for this socket"},
+    {WSAENOPROTOOPT,     "WSAENOPROTOOPT - Protocol option not supported for this socket type"},
+    {WSAEPROTONOSUPPORT, "WSAEPROTONOSUPPORT - Protocol is not supported"},
+    {WSAESOCKTNOSUPPORT, "WSAESOCKTNOSUPPORT - Socket type not supported by this address family"},
+    {WSAEOPNOTSUPP,      "WSAEOPNOTSUPP - Option not supported"},
+    {WSAEPFNOSUPPORT,    "WSAEPFNOSUPPORT - "},
+    {WSAEAFNOSUPPORT,    "WSAEAFNOSUPPORT - Address family not supported by this protocol"},
+    {WSAEADDRINUSE,      "WSAEADDRINUSE - Address is in use"},
+    {WSAEADDRNOTAVAIL,   "WSAEADDRNOTAVAIL - Address not available from local machine"},
+    {WSAENETDOWN,        "WSAENETDOWN - Network subsystem is down"},
+    {WSAENETUNREACH,     "WSAENETUNREACH - Network cannot be reached"},
+    {WSAENETRESET,       "WSAENETRESET - Connection has been dropped"},
+    {WSAECONNABORTED,    "WSAECONNABORTED - Connection aborted"},
+    {WSAECONNRESET,      "WSAECONNRESET - Connection reset"},
+    {WSAENOBUFS,         "WSAENOBUFS - No buffer space available"},
+    {WSAEISCONN,         "WSAEISCONN - Socket is already connected"},
+    {WSAENOTCONN,        "WSAENOTCONN - Socket is not connected"},
+    {WSAESHUTDOWN,       "WSAESHUTDOWN - Socket has been shut down"},
+    {WSAETOOMANYREFS,    "WSAETOOMANYREFS - Too many references"},
+    {WSAETIMEDOUT,       "WSAETIMEDOUT - Command timed out"},
+    {WSAECONNREFUSED,    "WSAECONNREFUSED - Connection refused"},
+    {WSAELOOP,           "WSAELOOP - "},
+    {WSAENAMETOOLONG,    "WSAENAMETOOLONG - "},
+    {WSAEHOSTDOWN,       "WSAEHOSTDOWN - Host is down"},
+    {WSAEHOSTUNREACH,    "WSAEHOSTUNREACH - "},
+    {WSAENOTEMPTY,       "WSAENOTEMPTY - "},
+    {WSAEPROCLIM,        "WSAEPROCLIM - "},
+    {WSAEUSERS,          "WSAEUSERS - "},
+    {WSAEDQUOT,          "WSAEDQUOT - "},
+    {WSAESTALE,          "WSAESTALE - "},
+    {WSAEREMOTE,         "WSAEREMOTE - "},
+
+/*
+*    Extended Windows Sockets error constant definitions
+*/
+
+    {WSASYSNOTREADY,     "WSASYSNOTREADY - Network subsystem not ready"},
+    {WSAVERNOTSUPPORTED, "WSAVERNOTSUPPORTED - Version not supported"},
+    {WSANOTINITIALISED,  "WSANOTINITIALISED - WSAStartup() has not been successfully called"},
+
+/*
+*    Other error constants.
+*/
+
+    {WSAHOST_NOT_FOUND,  "WSAHOST_NOT_FOUND - Host not found"},
+    {WSATRY_AGAIN,       "WSATRY_AGAIN - Host not found or SERVERFAIL"},
+    {WSANO_RECOVERY,     "WSANO_RECOVERY - Non-recoverable error"},
+    {WSANO_DATA,         "WSANO_DATA - (or WSANO_ADDRESS) - No data record of requested type"},
+    {-1,                 NULL}
+};
+
+#ifdef _DEBUG
+void WinPrint(char *str, ...);
+#else
+void WinPrint(char *str, ...);
+#endif
+
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+char *WINS_ErrorMessage(int error)
+{
+    int search = 0;
+
+    if (!error) return "No error occurred";
+
+	 for (search = 0; errlist[search].errstr; search++)
+	 {
+		if (error == errlist[search].errnum)
+				return errlist[search].errstr;
+	 } //end for
+
+    return "Unknown error";
+} //end of the function WINS_ErrorMessage
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Init(void)
+{
+	int		i;
+	struct hostent *local;
+	char	buff[MAXHOSTNAMELEN];
+	struct sockaddr_s addr;
+	char	*p;
+	int		r;
+	WORD	wVersionRequested; 
+
+	wVersionRequested = MAKEWORD(1, 1);
+
+	r = WSAStartup (wVersionRequested, &winsockdata);
+
+	if (r)
+	{
+		WinPrint("Winsock initialization failed.\n");
+		return -1;
+	}
+
+	/*
+	i = COM_CheckParm ("-udpport");
+	if (i == 0)*/
+		net_hostport = DEFAULTnet_hostport;
+	/*
+	else if (i < com_argc-1)
+		net_hostport = Q_atoi (com_argv[i+1]);
+	else
+		Sys_Error ("WINS_Init: you must specify a number after -udpport");
+	*/
+
+	// determine my name & address
+	gethostname(buff, MAXHOSTNAMELEN);
+	local = gethostbyname(buff);
+	myAddr = *(int *)local->h_addr_list[0];
+
+	// if the quake hostname isn't set, set it to the machine name
+//	if (Q_strcmp(hostname.string, "UNNAMED") == 0)
+	{
+		// see if it's a text IP address (well, close enough)
+		for (p = buff; *p; p++)
+			if ((*p < '0' || *p > '9') && *p != '.')
+				break;
+
+		// if it is a real name, strip off the domain; we only want the host
+		if (*p)
+		{
+			for (i = 0; i < 15; i++)
+				if (buff[i] == '.')
+					break;
+			buff[i] = 0;
+		}
+//		Cvar_Set ("hostname", buff);
+	}
+
+	if ((net_controlsocket = WINS_OpenSocket (0)) == -1)
+		WinError("WINS_Init: Unable to open control socket\n");
+
+	((struct sockaddr_in *)&broadcastaddr)->sin_family = AF_INET;
+	((struct sockaddr_in *)&broadcastaddr)->sin_addr.s_addr = INADDR_BROADCAST;
+	((struct sockaddr_in *)&broadcastaddr)->sin_port = htons((u_short)net_hostport);
+
+	WINS_GetSocketAddr (net_controlsocket, &addr);
+	strcpy(my_tcpip_address,  WINS_AddrToString (&addr));
+	p = strrchr (my_tcpip_address, ':');
+	if (p) *p = 0;
+	WinPrint("Winsock Initialized\n");
+
+	return net_controlsocket;
+} //end of the function WINS_Init
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+char *WINS_MyAddress(void)
+{
+	return my_tcpip_address;
+} //end of the function WINS_MyAddress
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+void WINS_Shutdown(void)
+{
+	//WINS_Listen(0);
+	WINS_CloseSocket(net_controlsocket);
+	WSACleanup();
+	//
+	WinPrint("Winsock Shutdown\n");
+} //end of the function WINS_Shutdown
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+/*
+void WINS_Listen(int state)
+{
+	// enable listening
+	if (state)
+	{
+		if (net_acceptsocket != -1)
+			return;
+		if ((net_acceptsocket = WINS_OpenSocket (net_hostport)) == -1)
+			WinError ("WINS_Listen: Unable to open accept socket\n");
+		return;
+	}
+
+	// disable listening
+	if (net_acceptsocket == -1)
+		return;
+	WINS_CloseSocket (net_acceptsocket);
+	net_acceptsocket = -1;
+} //end of the function WINS_Listen*/
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_OpenSocket(int port)
+{
+	int newsocket;
+	struct sockaddr_in address;
+	u_long _true = 1;
+
+	if ((newsocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
+	{
+		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+
+	if (ioctlsocket (newsocket, FIONBIO, &_true) == -1)
+	{
+		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		closesocket(newsocket);
+		return -1;
+	} //end if
+
+	memset((char *) &address, 0, sizeof(address));
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = INADDR_ANY;
+	address.sin_port = htons((u_short)port);
+	if( bind (newsocket, (void *)&address, sizeof(address)) == -1)
+	{
+		WinPrint("WINS_OpenSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		closesocket(newsocket);
+		return -1;
+	} //end if
+
+	return newsocket;
+} //end of the function WINS_OpenSocket
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_OpenReliableSocket(int port)
+{
+	int newsocket;
+	struct sockaddr_in address;
+	BOOL _true = 0xFFFFFFFF;
+
+	//IPPROTO_TCP
+	//
+	if ((newsocket = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+	{
+		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+
+	memset((char *) &address, 0, sizeof(address));
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = htonl(INADDR_ANY);
+	address.sin_port = htons((u_short)port);
+	if (bind(newsocket, (void *)&address, sizeof(address)) == -1)
+	{
+		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		closesocket(newsocket);
+		return -1;
+	} //end if
+
+  //
+	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_OpenReliableSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		WinPrint("setsockopt error\n");
+	} //end if
+
+	return newsocket;
+} //end of the function WINS_OpenReliableSocket
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Listen(int socket)
+{
+	u_long _true = 1;
+
+	if (ioctlsocket(socket, FIONBIO, &_true) == -1)
+	{
+		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	if (listen(socket, SOMAXCONN) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Listen: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	return 0;
+} //end of the function WINS_Listen
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Accept(int socket, struct sockaddr_s *addr)
+{
+	int addrlen = sizeof (struct sockaddr_s);
+	int newsocket;
+	BOOL _true = 1;
+
+	newsocket = accept(socket, (struct sockaddr *)addr, &addrlen);
+	if (newsocket == INVALID_SOCKET)
+	{
+		if (WSAGetLastError() == WSAEWOULDBLOCK) return -1;
+		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	//
+	if (setsockopt(newsocket, IPPROTO_TCP, TCP_NODELAY, (void *) &_true, sizeof(int)) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Accept: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		WinPrint("setsockopt error\n");
+	} //end if
+	return newsocket;
+} //end of the function WINS_Accept
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_CloseSocket(int socket)
+{
+	/*
+	if (socket == net_broadcastsocket)
+		net_broadcastsocket = 0;
+	*/
+//	shutdown(socket, SD_SEND);
+
+	if (closesocket(socket) == SOCKET_ERROR)
+	{
+		WinPrint("WINS_CloseSocket: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return SOCKET_ERROR;
+	} //end if
+	return 0;
+} //end of the function WINS_CloseSocket
+//===========================================================================
+// this lets you type only as much of the net address as required, using
+// the local network components to fill in the rest
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+static int PartialIPAddress (char *in, struct sockaddr_s *hostaddr)
+{
+	char buff[256];
+	char *b;
+	int addr;
+	int num;
+	int mask;
+	
+	buff[0] = '.';
+	b = buff;
+	strcpy(buff+1, in);
+	if (buff[1] == '.') b++;
+
+	addr = 0;
+	mask=-1;
+	while (*b == '.')
+	{
+		num = 0;
+		if (*++b < '0' || *b > '9') return -1;
+		while (!( *b < '0' || *b > '9'))
+		  num = num*10 + *(b++) - '0';
+		mask<<=8;
+		addr = (addr<<8) + num;
+	}
+	
+	hostaddr->sa_family = AF_INET;
+	((struct sockaddr_in *)hostaddr)->sin_port = htons((u_short)net_hostport);
+	((struct sockaddr_in *)hostaddr)->sin_addr.s_addr = (myAddr & htonl(mask)) | htonl(addr);
+	
+	return 0;
+} //end of the function PartialIPAddress
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Connect(int socket, struct sockaddr_s *addr)
+{
+	int ret;
+	u_long _true2 = 0xFFFFFFFF;
+
+	ret = connect(socket, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
+	if (ret == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	if (ioctlsocket(socket, FIONBIO, &_true2) == -1)
+	{
+		WinPrint("WINS_Connect: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+		return -1;
+	} //end if
+	return 0;
+} //end of the function WINS_Connect
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_CheckNewConnections(void)
+{
+	char buf[4];
+
+	if (net_acceptsocket == -1)
+		return -1;
+
+	if (recvfrom(net_acceptsocket, buf, 4, MSG_PEEK, NULL, NULL) > 0)
+		return net_acceptsocket;
+	return -1;
+} //end of the function WINS_CheckNewConnections
+//===========================================================================
+// returns the number of bytes read
+// 0 if no bytes available
+// -1 on failure
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Read(int socket, byte *buf, int len, struct sockaddr_s *addr)
+{
+	int addrlen = sizeof (struct sockaddr_s);
+	int ret, errno;
+
+	if (addr)
+	{
+		ret = recvfrom(socket, buf, len, 0, (struct sockaddr *)addr, &addrlen);
+		if (ret == -1)
+		{
+			errno = WSAGetLastError();
+
+			if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
+				return 0;
+		} //end if
+	} //end if
+	else
+	{
+		ret = recv(socket, buf, len, 0);
+		if (ret == SOCKET_ERROR)
+		{
+			errno = WSAGetLastError();
+
+			if (errno == WSAEWOULDBLOCK || errno == WSAECONNREFUSED)
+				return 0;
+		} //end if
+	} //end else
+	if (ret == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Read: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+	} //end if
+	return ret;
+} //end of the function WINS_Read
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_MakeSocketBroadcastCapable (int socket)
+{
+	int	i = 1;
+
+	// make this socket broadcast capable
+	if (setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (char *)&i, sizeof(i)) < 0)
+		return -1;
+	net_broadcastsocket = socket;
+
+	return 0;
+} //end of the function WINS_MakeSocketBroadcastCapable
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Broadcast (int socket, byte *buf, int len)
+{
+	int ret;
+
+	if (socket != net_broadcastsocket)
+	{
+		if (net_broadcastsocket != 0)
+			WinError("Attempted to use multiple broadcasts sockets\n");
+		ret = WINS_MakeSocketBroadcastCapable (socket);
+		if (ret == -1)
+		{
+			WinPrint("Unable to make socket broadcast capable\n");
+			return ret;
+		}
+	}
+
+	return WINS_Write (socket, buf, len, &broadcastaddr);
+} //end of the function WINS_Broadcast
+//===========================================================================
+// returns qtrue on success or qfalse on failure
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_Write(int socket, byte *buf, int len, struct sockaddr_s *addr)
+{
+	int ret, written;
+
+	if (addr)
+	{
+		written = 0;
+		while(written < len)
+		{
+			ret = sendto (socket, &buf[written], len-written, 0, (struct sockaddr *)addr, sizeof(struct sockaddr_s));
+			if (ret == SOCKET_ERROR)
+			{
+				if (WSAGetLastError() != WSAEWOULDBLOCK)
+					return qfalse;
+				Sleep(1000);
+			} //end if
+			else
+			{
+				written += ret;
+			}
+		}
+	} //end if
+	else
+	{
+		written = 0;
+		while(written < len)
+		{
+			ret = send(socket, buf, len, 0);
+			if (ret == SOCKET_ERROR)
+			{
+				if (WSAGetLastError() != WSAEWOULDBLOCK)
+					return qfalse;
+				Sleep(1000);
+			} //end if
+			else
+			{
+				written += ret;
+			}
+		}
+	} //end else
+	if (ret == SOCKET_ERROR)
+	{
+		WinPrint("WINS_Write: %s\n", WINS_ErrorMessage(WSAGetLastError()));
+	} //end if
+	return (ret == len);
+} //end of the function WINS_Write
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+char *WINS_AddrToString (struct sockaddr_s *addr)
+{
+	static char buffer[22];
+	int haddr;
+
+	haddr = ntohl(((struct sockaddr_in *)addr)->sin_addr.s_addr);
+	sprintf(buffer, "%d.%d.%d.%d:%d", (haddr >> 24) & 0xff, (haddr >> 16) & 0xff, (haddr >> 8) & 0xff, haddr & 0xff, ntohs(((struct sockaddr_in *)addr)->sin_port));
+	return buffer;
+} //end of the function WINS_AddrToString
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_StringToAddr(char *string, struct sockaddr_s *addr)
+{
+	int ha1, ha2, ha3, ha4, hp;
+	int ipaddr;
+
+	sscanf(string, "%d.%d.%d.%d:%d", &ha1, &ha2, &ha3, &ha4, &hp);
+	ipaddr = (ha1 << 24) | (ha2 << 16) | (ha3 << 8) | ha4;
+
+	addr->sa_family = AF_INET;
+	((struct sockaddr_in *)addr)->sin_addr.s_addr = htonl(ipaddr);
+	((struct sockaddr_in *)addr)->sin_port = htons((u_short)hp);
+	return 0;
+} //end of the function WINS_StringToAddr
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetSocketAddr(int socket, struct sockaddr_s *addr)
+{
+	int addrlen = sizeof(struct sockaddr_s);
+	unsigned int a;
+
+	memset(addr, 0, sizeof(struct sockaddr_s));
+	getsockname(socket, (struct sockaddr *)addr, &addrlen);
+	a = ((struct sockaddr_in *)addr)->sin_addr.s_addr;
+	if (a == 0 || a == inet_addr("127.0.0.1"))
+		((struct sockaddr_in *)addr)->sin_addr.s_addr = myAddr;
+
+	return 0;
+} //end of the function WINS_GetSocketAddr
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetNameFromAddr (struct sockaddr_s *addr, char *name)
+{
+	struct hostent *hostentry;
+
+	hostentry = gethostbyaddr ((char *)&((struct sockaddr_in *)addr)->sin_addr, sizeof(struct in_addr), AF_INET);
+	if (hostentry)
+	{
+		strncpy (name, (char *)hostentry->h_name, NET_NAMELEN - 1);
+		return 0;
+	}
+
+	strcpy (name, WINS_AddrToString (addr));
+	return 0;
+} //end of the function WINS_GetNameFromAddr
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetAddrFromName(char *name, struct sockaddr_s *addr)
+{
+	struct hostent *hostentry;
+
+	if (name[0] >= '0' && name[0] <= '9')
+		return PartialIPAddress (name, addr);
+	
+	hostentry = gethostbyname (name);
+	if (!hostentry)
+		return -1;
+
+	addr->sa_family = AF_INET;
+	((struct sockaddr_in *)addr)->sin_port = htons((u_short)net_hostport);
+	((struct sockaddr_in *)addr)->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0];
+
+	return 0;
+} //end of the function WINS_GetAddrFromName
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_AddrCompare (struct sockaddr_s *addr1, struct sockaddr_s *addr2)
+{
+	if (addr1->sa_family != addr2->sa_family)
+		return -1;
+
+	if (((struct sockaddr_in *)addr1)->sin_addr.s_addr != ((struct sockaddr_in *)addr2)->sin_addr.s_addr)
+		return -1;
+
+	if (((struct sockaddr_in *)addr1)->sin_port != ((struct sockaddr_in *)addr2)->sin_port)
+		return 1;
+
+	return 0;
+} //end of the function WINS_AddrCompare
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_GetSocketPort (struct sockaddr_s *addr)
+{
+	return ntohs(((struct sockaddr_in *)addr)->sin_port);
+} //end of the function WINS_GetSocketPort
+//===========================================================================
+//
+// Parameter:				-
+// Returns:					-
+// Changes Globals:		-
+//===========================================================================
+int WINS_SetSocketPort (struct sockaddr_s *addr, int port)
+{
+	((struct sockaddr_in *)addr)->sin_port = htons((u_short)port);
+	return 0;
+} //end of the function WINS_SetSocketPort
diff --git a/libs/l_net/l_net_wins.h b/libs/l_net/l_net_wins.h
index 0a06ea7a..73598795 100644
--- a/libs/l_net/l_net_wins.h
+++ b/libs/l_net/l_net_wins.h
@@ -1,52 +1,52 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//===========================================================================
-//
-// Name:         l_net_wins.h
-// Function:     WinSock
-// Programmer:   MrElusive
-// Last update:  TTimo: cross-platform version, l_net library
-// Tab Size:     3
-// Notes:
-//===========================================================================
-
-int  WINS_Init(void);
-void WINS_Shutdown(void);
-char *WINS_MyAddress(void);
-int  WINS_Listen(int socket);
-int  WINS_Accept(int socket, struct sockaddr_s *addr);
-int  WINS_OpenSocket(int port);
-int  WINS_OpenReliableSocket(int port);
-int  WINS_CloseSocket(int socket);
-int  WINS_Connect (int socket, struct sockaddr_s *addr);
-int  WINS_CheckNewConnections(void);
-int  WINS_Read(int socket, byte *buf, int len, struct sockaddr_s *addr);
-int  WINS_Write(int socket, byte *buf, int len, struct sockaddr_s *addr);
-int  WINS_Broadcast (int socket, byte *buf, int len);
-char *WINS_AddrToString (struct sockaddr_s *addr);
-int  WINS_StringToAddr (char *string, struct sockaddr_s *addr);
-int  WINS_GetSocketAddr (int socket, struct sockaddr_s *addr);
-int  WINS_GetNameFromAddr (struct sockaddr_s *addr, char *name);
-int  WINS_GetAddrFromName (char *name, struct sockaddr_s *addr);
-int  WINS_AddrCompare (struct sockaddr_s *addr1, struct sockaddr_s *addr2);
-int  WINS_GetSocketPort (struct sockaddr_s *addr);
-int  WINS_SetSocketPort (struct sockaddr_s *addr, int port);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//===========================================================================
+//
+// Name:         l_net_wins.h
+// Function:     WinSock
+// Programmer:   MrElusive
+// Last update:  TTimo: cross-platform version, l_net library
+// Tab Size:     3
+// Notes:
+//===========================================================================
+
+int  WINS_Init(void);
+void WINS_Shutdown(void);
+char *WINS_MyAddress(void);
+int  WINS_Listen(int socket);
+int  WINS_Accept(int socket, struct sockaddr_s *addr);
+int  WINS_OpenSocket(int port);
+int  WINS_OpenReliableSocket(int port);
+int  WINS_CloseSocket(int socket);
+int  WINS_Connect (int socket, struct sockaddr_s *addr);
+int  WINS_CheckNewConnections(void);
+int  WINS_Read(int socket, byte *buf, int len, struct sockaddr_s *addr);
+int  WINS_Write(int socket, byte *buf, int len, struct sockaddr_s *addr);
+int  WINS_Broadcast (int socket, byte *buf, int len);
+char *WINS_AddrToString (struct sockaddr_s *addr);
+int  WINS_StringToAddr (char *string, struct sockaddr_s *addr);
+int  WINS_GetSocketAddr (int socket, struct sockaddr_s *addr);
+int  WINS_GetNameFromAddr (struct sockaddr_s *addr, char *name);
+int  WINS_GetAddrFromName (char *name, struct sockaddr_s *addr);
+int  WINS_AddrCompare (struct sockaddr_s *addr1, struct sockaddr_s *addr2);
+int  WINS_GetSocketPort (struct sockaddr_s *addr);
+int  WINS_SetSocketPort (struct sockaddr_s *addr, int port);
diff --git a/libs/mathlib.h b/libs/mathlib.h
index 97fcf461..44bf01c9 100644
--- a/libs/mathlib.h
+++ b/libs/mathlib.h
@@ -1,305 +1,305 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __MATHLIB__
-#define __MATHLIB__
-
-// mathlib.h
-#include <math.h>
-
-#include "bytebool.h"
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef float vec_t;
-typedef vec_t vec3_t[3];
-typedef vec_t vec5_t[5];
-typedef vec_t vec4_t[4];
-
-#define	SIDE_FRONT		0
-#define	SIDE_ON			2
-#define	SIDE_BACK		1
-#define	SIDE_CROSS		-2
-
-// plane types are used to speed some tests
-// 0-2 are axial planes
-#define	PLANE_X			0
-#define	PLANE_Y			1
-#define	PLANE_Z			2
-#define	PLANE_NON_AXIAL	3
-
-#define	Q_PI	3.14159265358979323846f
-
-extern vec3_t vec3_origin;
-
-#define	EQUAL_EPSILON	0.001
-
-#ifndef VEC_MAX
-#define VEC_MAX 3.402823466e+38F
-#endif
-
-qboolean VectorCompare (vec3_t v1, vec3_t v2);
-
-#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
-#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
-#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
-#define VectorIncrement(a,b) ((b)[0]+=(a)[0],(b)[1]+=(a)[1],(b)[2]+=(a)[2])
-#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
-#define VectorSet(v, a, b, c) ((v)[0]=(a),(v)[1]=(b),(v)[2]=(c))
-#define VectorScale(a,b,c) ((c)[0]=(b)*(a)[0],(c)[1]=(b)*(a)[1],(c)[2]=(b)*(a)[2])
-#define VectorMid(a,b,c) ((c)[0]=((a)[0]+(b)[0])*0.5f,(c)[1]=((a)[1]+(b)[1])*0.5f,(c)[2]=((a)[2]+(b)[2])*0.5f)
-#define VectorNegative(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
-#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
-#define VectorClear(x) ((x)[0]=(x)[1]=(x)[2]=0)
-
-#define Q_rint(in) ((vec_t)floor(in+0.5))
-
-vec_t VectorLength(vec3_t v);
-
-void VectorMA( const vec3_t va, vec_t scale, const vec3_t vb, vec3_t vc );
-
-void _CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
-vec_t VectorNormalize (const vec3_t in, vec3_t out);
-vec_t ColorNormalize( const vec3_t in, vec3_t out );
-void VectorInverse (vec3_t v);
-void VectorPolar(vec3_t v, float radius, float theta, float phi);
-
-// default snapping, to 1
-void VectorSnap(vec3_t v);
-
-// integer snapping
-void VectorISnap(vec3_t point, int snap);
-
-// Gef:   added snap to float for sub-integer grid sizes
-// TTimo: we still use the int version of VectorSnap when possible
-//        to avoid potential rounding issues
-// TTimo: renaming to VectorFSnap for C implementation
-void VectorFSnap(vec3_t point, float snap);
-
-// NOTE: added these from Ritual's Q3Radiant
-void ClearBounds (vec3_t mins, vec3_t maxs);
-void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
-
-void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
-void VectorToAngles( vec3_t vec, vec3_t angles );
-
-#define ZERO_EPSILON 1.0E-6
-#define RAD2DEGMULT 57.29577951308232f
-#define DEG2RADMULT 0.01745329251994329f
-#define RAD2DEG( a ) ( (a) * RAD2DEGMULT )
-#define DEG2RAD( a ) ( (a) * DEG2RADMULT )
-
-void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t out);
-void VectorRotateOrigin (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out);
-
-// some function merged from tools mathlib code
-
-qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c );
-void NormalToLatLong( const vec3_t normal, byte bytes[2] );
-int	PlaneTypeForNormal (vec3_t normal);
-void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
-
-// Spog
-// code imported from geomlib
-
-/*!
-\todo
-FIXME test calls such as intersect tests should be named test_
-*/
-
-typedef vec_t m3x3_t[9];
-/*!NOTE 
-m4x4 looks like this..
-
-                x  y  z
-x axis        ( 0  1  2)
-y axis        ( 4  5  6)
-z axis        ( 8  9 10)
-translation   (12 13 14)
-scale         ( 0  5 10)
-*/
-typedef vec_t m4x4_t[16];
-
-#define M4X4_INDEX(m,row,col) (m[(col<<2)+row])
-
-typedef enum { TRANSLATE, SCALE, ROTATE } transformtype; // legacy, used only in pmesh.cpp
-
-typedef enum { eXYZ, eYZX, eZXY, eXZY, eYXZ, eZYX } eulerOrder_t;
-
-// constructors
-/*! create m4x4 as identity matrix */
-void m4x4_identity(m4x4_t matrix);
-/*! create m4x4 as a translation matrix, for a translation vec3 */
-void m4x4_translation_for_vec3(m4x4_t matrix, const vec3_t translation);
-/*! create m4x4 as a rotation matrix, for an euler angles (degrees) vec3 */
-void m4x4_rotation_for_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order);
-/*! create m4x4 as a scaling matrix, for a scale vec3 */
-void m4x4_scale_for_vec3(m4x4_t matrix, const vec3_t scale);
-/*! create m4x4 as a rotation matrix, for a quaternion vec4 */
-void m4x4_rotation_for_quat(m4x4_t matrix, const vec4_t rotation);
-/*! create m4x4 as a rotation matrix, for an axis vec3 and an angle (radians) */
-void m4x4_rotation_for_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle);
-
-// a valid m4x4 to be modified is always first argument
-/*! translate m4x4 by a translation vec3 */
-void m4x4_translate_by_vec3(m4x4_t matrix, const vec3_t translation);
-/*! rotate m4x4 by a euler (degrees) vec3 */
-void m4x4_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order);
-/*! scale m4x4 by a scaling vec3 */
-void m4x4_scale_by_vec3(m4x4_t matrix, const vec3_t scale);
-/*! rotate m4x4 by a quaternion vec4 */
-void m4x4_rotate_by_quat(m4x4_t matrix, const vec4_t rotation);
-/*! rotate m4x4 by an axis vec3 and an angle (radians) */
-void m4x4_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle);
-/*! transform m4x4 by translation/euler/scaling vec3 (transform = translation.euler.scale) */
-void m4x4_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale);
-/*! rotate m4x4 around a pivot point by euler(degrees) vec3 */
-void m4x4_pivoted_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order, const vec3_t pivotpoint);
-/*! scale m4x4 around a pivot point by scaling vec3 */
-void m4x4_pivoted_scale_by_vec3(m4x4_t matrix, const vec3_t scale, const vec3_t pivotpoint);
-/*! transform m4x4 around a pivot point by translation/euler/scaling vec3 */
-void m4x4_pivoted_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale, const vec3_t pivotpoint);
-/*! rotate m4x4 around a pivot point by quaternion vec4 */
-void m4x4_pivoted_rotate_by_quat(m4x4_t matrix, const vec4_t rotation, const vec3_t pivotpoint);
-/*! rotate m4x4 around a pivot point by axis vec3 and angle (radians) */
-void m4x4_pivoted_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle, const vec3_t pivotpoint);
-/*! post-multiply m4x4 by another m4x4 */
-void m4x4_multiply_by_m4x4(m4x4_t matrix, const m4x4_t other);
-/*! pre-multiply m4x4 by another m4x4 */
-void m4x4_premultiply_by_m4x4(m4x4_t matrix, const m4x4_t other);
-
-/*! multiply a point (x,y,z,1) by matrix */
-void m4x4_transform_point(const m4x4_t matrix, vec3_t point);
-/*! multiply a normal (x,y,z,0) by matrix */
-void m4x4_transform_normal(const m4x4_t matrix, vec3_t normal);
-/*! multiply a vec4 (x,y,z,w) by matrix */
-void m4x4_transform_vec4(const m4x4_t matrix, vec4_t vector);
-
-/*! multiply a point (x,y,z,1) by matrix */
-void m4x4_transform_point(const m4x4_t matrix, vec3_t point);
-/*! multiply a normal (x,y,z,0) by matrix */
-void m4x4_transform_normal(const m4x4_t matrix, vec3_t normal);
-
-/*! transpose a m4x4 */
-void m4x4_transpose(m4x4_t matrix);
-/*! invert an orthogonal 4x3 subset of a 4x4 matrix */
-void m4x4_orthogonal_invert(m4x4_t matrix);
-/*! invert any m4x4 using Kramer's rule.. return 1 if matrix is singular, else return 0 */
-int m4x4_invert(m4x4_t matrix);
-
-/*!
-\todo object/ray intersection functions should maybe return a point rather than a distance?
-*/
-
-/*!
-aabb_t -  "axis-aligned" bounding box... 
-  origin: centre of bounding box... 
-  extents: +/- extents of box from origin... 
-  radius: cached length of extents vector... 
-*/
-typedef struct aabb_s
-{
-  vec3_t origin;
-  vec3_t extents;
-  vec_t radius;
-} aabb_t;
-
-/*!
-bbox_t - oriented bounding box... 
-  aabb: axis-aligned bounding box... 
-  axes: orientation axes... 
-*/
-typedef struct bbox_s
-{
-  aabb_t aabb;
-  vec3_t axes[3];
-} bbox_t;
-
-/*!
-ray_t - origin point and direction unit-vector
-*/
-typedef struct ray_s
-{
-  vec3_t origin;
-  vec3_t direction;
-} ray_t;
-
-
-/*! Generate AABB from min/max. */
-void aabb_construct_for_vec3(aabb_t *aabb, const vec3_t min, const vec3_t max);
-/*! Update bounding-sphere radius. */
-void aabb_update_radius(aabb_t *aabb);
-/*! Initialise AABB to negative size. */
-void aabb_clear(aabb_t *aabb);
-
-/*! Extend AABB to include point. */
-void aabb_extend_by_point(aabb_t *aabb, const vec3_t point);
-/*! Extend AABB to include aabb_src. */
-void aabb_extend_by_aabb(aabb_t *aabb, const aabb_t *aabb_src);
-/*! Extend AABB by +/- extension vector. */
-void aabb_extend_by_vec3(aabb_t *aabb, vec3_t extension);
-
-/*! Return 2 if point is inside, else 1 if point is on surface, else 0. */
-int aabb_intersect_point(const aabb_t *aabb, const vec3_t point);
-/*! Return 2 if aabb_src intersects, else 1 if aabb_src touches exactly, else 0. */
-int aabb_intersect_aabb(const aabb_t *aabb, const aabb_t *aabb_src);
-/*! Return 2 if aabb is behind plane, else 1 if aabb intersects plane, else 0. */
-int aabb_intersect_plane(const aabb_t *aabb, const float *plane);
-/*! Return 1 if aabb intersects ray, else 0... dist = closest intersection. */
-int aabb_intersect_ray(const aabb_t *aabb, const ray_t *ray, vec_t *dist);
-/*! Return 1 if aabb intersects ray, else 0. Faster, but does not provide point of intersection */
-int aabb_test_ray(const aabb_t* aabb, const ray_t* ray);
-
-/*! Generate AABB from oriented bounding box. */
-void aabb_for_bbox(aabb_t *aabb, const bbox_t *bbox);
-/*! Generate AABB from 2-dimensions of min/max, specified by axis. */
-void aabb_for_area(aabb_t *aabb, vec3_t area_tl, vec3_t area_br, int axis);
-/*! Generate AABB to contain src * transform. NOTE: transform must be orthogonal */
-void aabb_for_transformed_aabb(aabb_t* dst, const aabb_t* src, const m4x4_t transform);
-
-
-/*! Generate oriented bounding box from AABB and transformation matrix. */
-/*!\todo Remove need to specify euler/scale. */
-void bbox_for_oriented_aabb(bbox_t *bbox, const aabb_t *aabb,
-                    const m4x4_t matrix, const vec3_t euler, const vec3_t scale);
-/*! Return 2 is bbox is behind plane, else return 1 if bbox intersects plane, else return 0. */
-int bbox_intersect_plane(const bbox_t *bbox, const vec_t* plane);
-
-
-/*! Generate a ray from an origin point and a direction unit-vector */
-void ray_construct_for_vec3(ray_t *ray, const vec3_t origin, const vec3_t direction);
-  
-/*! Transform a ray */
-void ray_transform(ray_t *ray, const m4x4_t matrix);
-
-/*! return true if point intersects cone formed by ray, divergence and epsilon */
-vec_t ray_intersect_point(const ray_t *ray, const vec3_t point, vec_t epsilon, vec_t divergence);
-/*! return true if triangle intersects ray... dist = dist from intersection point to ray-origin */
-vec_t ray_intersect_triangle(const ray_t *ray, qboolean bCullBack, const vec3_t vert0, const vec3_t vert1, const vec3_t vert2);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* __MATHLIB__ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __MATHLIB__
+#define __MATHLIB__
+
+// mathlib.h
+#include <math.h>
+
+#include "bytebool.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef float vec_t;
+typedef vec_t vec3_t[3];
+typedef vec_t vec5_t[5];
+typedef vec_t vec4_t[4];
+
+#define	SIDE_FRONT		0
+#define	SIDE_ON			2
+#define	SIDE_BACK		1
+#define	SIDE_CROSS		-2
+
+// plane types are used to speed some tests
+// 0-2 are axial planes
+#define	PLANE_X			0
+#define	PLANE_Y			1
+#define	PLANE_Z			2
+#define	PLANE_NON_AXIAL	3
+
+#define	Q_PI	3.14159265358979323846f
+
+extern vec3_t vec3_origin;
+
+#define	EQUAL_EPSILON	0.001
+
+#ifndef VEC_MAX
+#define VEC_MAX 3.402823466e+38F
+#endif
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2);
+
+#define DotProduct(x,y) ((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2])
+#define VectorSubtract(a,b,c) ((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+#define VectorAdd(a,b,c) ((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+#define VectorIncrement(a,b) ((b)[0]+=(a)[0],(b)[1]+=(a)[1],(b)[2]+=(a)[2])
+#define VectorCopy(a,b) ((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+#define VectorSet(v, a, b, c) ((v)[0]=(a),(v)[1]=(b),(v)[2]=(c))
+#define VectorScale(a,b,c) ((c)[0]=(b)*(a)[0],(c)[1]=(b)*(a)[1],(c)[2]=(b)*(a)[2])
+#define VectorMid(a,b,c) ((c)[0]=((a)[0]+(b)[0])*0.5f,(c)[1]=((a)[1]+(b)[1])*0.5f,(c)[2]=((a)[2]+(b)[2])*0.5f)
+#define VectorNegative(a,b) ((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
+#define CrossProduct(a,b,c) ((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+#define VectorClear(x) ((x)[0]=(x)[1]=(x)[2]=0)
+
+#define Q_rint(in) ((vec_t)floor(in+0.5))
+
+vec_t VectorLength(vec3_t v);
+
+void VectorMA( const vec3_t va, vec_t scale, const vec3_t vb, vec3_t vc );
+
+void _CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
+vec_t VectorNormalize (const vec3_t in, vec3_t out);
+vec_t ColorNormalize( const vec3_t in, vec3_t out );
+void VectorInverse (vec3_t v);
+void VectorPolar(vec3_t v, float radius, float theta, float phi);
+
+// default snapping, to 1
+void VectorSnap(vec3_t v);
+
+// integer snapping
+void VectorISnap(vec3_t point, int snap);
+
+// Gef:   added snap to float for sub-integer grid sizes
+// TTimo: we still use the int version of VectorSnap when possible
+//        to avoid potential rounding issues
+// TTimo: renaming to VectorFSnap for C implementation
+void VectorFSnap(vec3_t point, float snap);
+
+// NOTE: added these from Ritual's Q3Radiant
+void ClearBounds (vec3_t mins, vec3_t maxs);
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
+
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up);
+void VectorToAngles( vec3_t vec, vec3_t angles );
+
+#define ZERO_EPSILON 1.0E-6
+#define RAD2DEGMULT 57.29577951308232f
+#define DEG2RADMULT 0.01745329251994329f
+#define RAD2DEG( a ) ( (a) * RAD2DEGMULT )
+#define DEG2RAD( a ) ( (a) * DEG2RADMULT )
+
+void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t out);
+void VectorRotateOrigin (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out);
+
+// some function merged from tools mathlib code
+
+qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c );
+void NormalToLatLong( const vec3_t normal, byte bytes[2] );
+int	PlaneTypeForNormal (vec3_t normal);
+void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point, float degrees );
+
+// Spog
+// code imported from geomlib
+
+/*!
+\todo
+FIXME test calls such as intersect tests should be named test_
+*/
+
+typedef vec_t m3x3_t[9];
+/*!NOTE 
+m4x4 looks like this..
+
+                x  y  z
+x axis        ( 0  1  2)
+y axis        ( 4  5  6)
+z axis        ( 8  9 10)
+translation   (12 13 14)
+scale         ( 0  5 10)
+*/
+typedef vec_t m4x4_t[16];
+
+#define M4X4_INDEX(m,row,col) (m[(col<<2)+row])
+
+typedef enum { TRANSLATE, SCALE, ROTATE } transformtype; // legacy, used only in pmesh.cpp
+
+typedef enum { eXYZ, eYZX, eZXY, eXZY, eYXZ, eZYX } eulerOrder_t;
+
+// constructors
+/*! create m4x4 as identity matrix */
+void m4x4_identity(m4x4_t matrix);
+/*! create m4x4 as a translation matrix, for a translation vec3 */
+void m4x4_translation_for_vec3(m4x4_t matrix, const vec3_t translation);
+/*! create m4x4 as a rotation matrix, for an euler angles (degrees) vec3 */
+void m4x4_rotation_for_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order);
+/*! create m4x4 as a scaling matrix, for a scale vec3 */
+void m4x4_scale_for_vec3(m4x4_t matrix, const vec3_t scale);
+/*! create m4x4 as a rotation matrix, for a quaternion vec4 */
+void m4x4_rotation_for_quat(m4x4_t matrix, const vec4_t rotation);
+/*! create m4x4 as a rotation matrix, for an axis vec3 and an angle (radians) */
+void m4x4_rotation_for_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle);
+
+// a valid m4x4 to be modified is always first argument
+/*! translate m4x4 by a translation vec3 */
+void m4x4_translate_by_vec3(m4x4_t matrix, const vec3_t translation);
+/*! rotate m4x4 by a euler (degrees) vec3 */
+void m4x4_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order);
+/*! scale m4x4 by a scaling vec3 */
+void m4x4_scale_by_vec3(m4x4_t matrix, const vec3_t scale);
+/*! rotate m4x4 by a quaternion vec4 */
+void m4x4_rotate_by_quat(m4x4_t matrix, const vec4_t rotation);
+/*! rotate m4x4 by an axis vec3 and an angle (radians) */
+void m4x4_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle);
+/*! transform m4x4 by translation/euler/scaling vec3 (transform = translation.euler.scale) */
+void m4x4_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale);
+/*! rotate m4x4 around a pivot point by euler(degrees) vec3 */
+void m4x4_pivoted_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order, const vec3_t pivotpoint);
+/*! scale m4x4 around a pivot point by scaling vec3 */
+void m4x4_pivoted_scale_by_vec3(m4x4_t matrix, const vec3_t scale, const vec3_t pivotpoint);
+/*! transform m4x4 around a pivot point by translation/euler/scaling vec3 */
+void m4x4_pivoted_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale, const vec3_t pivotpoint);
+/*! rotate m4x4 around a pivot point by quaternion vec4 */
+void m4x4_pivoted_rotate_by_quat(m4x4_t matrix, const vec4_t rotation, const vec3_t pivotpoint);
+/*! rotate m4x4 around a pivot point by axis vec3 and angle (radians) */
+void m4x4_pivoted_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle, const vec3_t pivotpoint);
+/*! post-multiply m4x4 by another m4x4 */
+void m4x4_multiply_by_m4x4(m4x4_t matrix, const m4x4_t other);
+/*! pre-multiply m4x4 by another m4x4 */
+void m4x4_premultiply_by_m4x4(m4x4_t matrix, const m4x4_t other);
+
+/*! multiply a point (x,y,z,1) by matrix */
+void m4x4_transform_point(const m4x4_t matrix, vec3_t point);
+/*! multiply a normal (x,y,z,0) by matrix */
+void m4x4_transform_normal(const m4x4_t matrix, vec3_t normal);
+/*! multiply a vec4 (x,y,z,w) by matrix */
+void m4x4_transform_vec4(const m4x4_t matrix, vec4_t vector);
+
+/*! multiply a point (x,y,z,1) by matrix */
+void m4x4_transform_point(const m4x4_t matrix, vec3_t point);
+/*! multiply a normal (x,y,z,0) by matrix */
+void m4x4_transform_normal(const m4x4_t matrix, vec3_t normal);
+
+/*! transpose a m4x4 */
+void m4x4_transpose(m4x4_t matrix);
+/*! invert an orthogonal 4x3 subset of a 4x4 matrix */
+void m4x4_orthogonal_invert(m4x4_t matrix);
+/*! invert any m4x4 using Kramer's rule.. return 1 if matrix is singular, else return 0 */
+int m4x4_invert(m4x4_t matrix);
+
+/*!
+\todo object/ray intersection functions should maybe return a point rather than a distance?
+*/
+
+/*!
+aabb_t -  "axis-aligned" bounding box... 
+  origin: centre of bounding box... 
+  extents: +/- extents of box from origin... 
+  radius: cached length of extents vector... 
+*/
+typedef struct aabb_s
+{
+  vec3_t origin;
+  vec3_t extents;
+  vec_t radius;
+} aabb_t;
+
+/*!
+bbox_t - oriented bounding box... 
+  aabb: axis-aligned bounding box... 
+  axes: orientation axes... 
+*/
+typedef struct bbox_s
+{
+  aabb_t aabb;
+  vec3_t axes[3];
+} bbox_t;
+
+/*!
+ray_t - origin point and direction unit-vector
+*/
+typedef struct ray_s
+{
+  vec3_t origin;
+  vec3_t direction;
+} ray_t;
+
+
+/*! Generate AABB from min/max. */
+void aabb_construct_for_vec3(aabb_t *aabb, const vec3_t min, const vec3_t max);
+/*! Update bounding-sphere radius. */
+void aabb_update_radius(aabb_t *aabb);
+/*! Initialise AABB to negative size. */
+void aabb_clear(aabb_t *aabb);
+
+/*! Extend AABB to include point. */
+void aabb_extend_by_point(aabb_t *aabb, const vec3_t point);
+/*! Extend AABB to include aabb_src. */
+void aabb_extend_by_aabb(aabb_t *aabb, const aabb_t *aabb_src);
+/*! Extend AABB by +/- extension vector. */
+void aabb_extend_by_vec3(aabb_t *aabb, vec3_t extension);
+
+/*! Return 2 if point is inside, else 1 if point is on surface, else 0. */
+int aabb_intersect_point(const aabb_t *aabb, const vec3_t point);
+/*! Return 2 if aabb_src intersects, else 1 if aabb_src touches exactly, else 0. */
+int aabb_intersect_aabb(const aabb_t *aabb, const aabb_t *aabb_src);
+/*! Return 2 if aabb is behind plane, else 1 if aabb intersects plane, else 0. */
+int aabb_intersect_plane(const aabb_t *aabb, const float *plane);
+/*! Return 1 if aabb intersects ray, else 0... dist = closest intersection. */
+int aabb_intersect_ray(const aabb_t *aabb, const ray_t *ray, vec_t *dist);
+/*! Return 1 if aabb intersects ray, else 0. Faster, but does not provide point of intersection */
+int aabb_test_ray(const aabb_t* aabb, const ray_t* ray);
+
+/*! Generate AABB from oriented bounding box. */
+void aabb_for_bbox(aabb_t *aabb, const bbox_t *bbox);
+/*! Generate AABB from 2-dimensions of min/max, specified by axis. */
+void aabb_for_area(aabb_t *aabb, vec3_t area_tl, vec3_t area_br, int axis);
+/*! Generate AABB to contain src * transform. NOTE: transform must be orthogonal */
+void aabb_for_transformed_aabb(aabb_t* dst, const aabb_t* src, const m4x4_t transform);
+
+
+/*! Generate oriented bounding box from AABB and transformation matrix. */
+/*!\todo Remove need to specify euler/scale. */
+void bbox_for_oriented_aabb(bbox_t *bbox, const aabb_t *aabb,
+                    const m4x4_t matrix, const vec3_t euler, const vec3_t scale);
+/*! Return 2 is bbox is behind plane, else return 1 if bbox intersects plane, else return 0. */
+int bbox_intersect_plane(const bbox_t *bbox, const vec_t* plane);
+
+
+/*! Generate a ray from an origin point and a direction unit-vector */
+void ray_construct_for_vec3(ray_t *ray, const vec3_t origin, const vec3_t direction);
+  
+/*! Transform a ray */
+void ray_transform(ray_t *ray, const m4x4_t matrix);
+
+/*! return true if point intersects cone formed by ray, divergence and epsilon */
+vec_t ray_intersect_point(const ray_t *ray, const vec3_t point, vec_t epsilon, vec_t divergence);
+/*! return true if triangle intersects ray... dist = dist from intersection point to ray-origin */
+vec_t ray_intersect_triangle(const ray_t *ray, qboolean bCullBack, const vec3_t vert0, const vec3_t vert1, const vec3_t vert2);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* __MATHLIB__ */
diff --git a/libs/mathlib/bbox.c b/libs/mathlib/bbox.c
index 510c4e7c..f421f917 100644
--- a/libs/mathlib/bbox.c
+++ b/libs/mathlib/bbox.c
@@ -1,391 +1,391 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <float.h>
-
-#include "mathlib.h"
-
-void aabb_construct_for_vec3(aabb_t *aabb, const vec3_t min, const vec3_t max)
-{
-  VectorMid(min, max, aabb->origin);
-  VectorSubtract(max, aabb->origin, aabb->extents);
-}
-
-void aabb_update_radius(aabb_t *aabb)
-{
-  aabb->radius = VectorLength(aabb->extents);
-}
-
-void aabb_clear(aabb_t *aabb)
-{
-  aabb->origin[0] = aabb->origin[1] = aabb->origin[2] = 0;
-  aabb->extents[0] = aabb->extents[1] = aabb->extents[2] = -FLT_MAX;
-}
-
-void aabb_extend_by_point(aabb_t *aabb, const vec3_t point)
-{
-  int i;
-  vec_t min, max, displacement;
-  for(i=0; i<3; i++)
-  {
-    displacement = point[i] - aabb->origin[i];
-    if(fabs(displacement) > aabb->extents[i])
-    {
-      if(aabb->extents[i] < 0) // degenerate
-      {
-        min = max = point[i];
-      }
-      else if(displacement > 0)
-      {
-        min = aabb->origin[i] - aabb->extents[i];
-        max = aabb->origin[i] + displacement;
-      }
-      else
-      {
-        max = aabb->origin[i] + aabb->extents[i];
-        min = aabb->origin[i] + displacement;
-      }
-      aabb->origin[i] = (min + max) * 0.5f;
-      aabb->extents[i] = max - aabb->origin[i];
-    }
-  }
-}
-
-void aabb_extend_by_aabb(aabb_t *aabb, const aabb_t *aabb_src)
-{
-  int i;
-  vec_t min, max, displacement, difference;
-  for(i=0; i<3; i++)
-  {
-    displacement = aabb_src->origin[i] - aabb->origin[i];
-    difference = aabb_src->extents[i] - aabb->extents[i];
-    if(aabb->extents[i] < 0
-      || difference >= fabs(displacement))
-    {
-      // 2nd contains 1st
-      aabb->extents[i] = aabb_src->extents[i];
-      aabb->origin[i] = aabb_src->origin[i];
-    }
-    else if(aabb_src->extents[i] < 0
-      || -difference >= fabs(displacement))
-    {
-      // 1st contains 2nd
-      continue;
-    }
-    else
-    {
-      // not contained
-      if(displacement > 0)
-      {
-        min = aabb->origin[i] - aabb->extents[i];
-        max = aabb_src->origin[i] + aabb_src->extents[i];
-      }
-      else
-      {
-        min = aabb_src->origin[i] - aabb_src->extents[i];
-        max = aabb->origin[i] + aabb->extents[i];
-      }
-      aabb->origin[i] = (min + max) * 0.5f;
-      aabb->extents[i] = max - aabb->origin[i];
-    }
-  }
-}
-
-void aabb_extend_by_vec3(aabb_t *aabb, vec3_t extension)
-{
-  VectorAdd(aabb->extents, extension, aabb->extents);
-}
-
-int aabb_intersect_point(const aabb_t *aabb, const vec3_t point)
-{
-  int i;
-  for(i=0; i<3; i++)
-    if(fabs(point[i] - aabb->origin[i]) >= aabb->extents[i])
-      return 0;
-  return 1;
-}
-
-int aabb_intersect_aabb(const aabb_t *aabb, const aabb_t *aabb_src)
-{
-  int i;
-  for (i=0; i<3; i++)
-    if ( fabs(aabb_src->origin[i] - aabb->origin[i]) > (fabs(aabb->extents[i]) + fabs(aabb_src->extents[i])) )
-      return 0;
-  return 1;
-}
-
-int aabb_intersect_plane(const aabb_t *aabb, const float *plane)
-{
-  float fDist, fIntersect;
-
-  // calc distance of origin from plane
-  fDist = DotProduct(plane, aabb->origin) + plane[3];
-  
-  // trivial accept/reject using bounding sphere
-	if (fabs(fDist) > aabb->radius)
-	{
-		if (fDist < 0)
-			return 2; // totally inside
-		else
-			return 0; // totally outside
-	}
-
-  // calc extents distance relative to plane normal
-  fIntersect = (vec_t)(fabs(plane[0] * aabb->extents[0]) + fabs(plane[1] * aabb->extents[1]) + fabs(plane[2] * aabb->extents[2]));
-  // accept if origin is less than or equal to this distance
-  if (fabs(fDist) < fIntersect) return 1; // partially inside
-  else if (fDist < 0) return 2; // totally inside
-  return 0; // totally outside
-}
-
-/* 
-Fast Ray-Box Intersection
-by Andrew Woo
-from "Graphics Gems", Academic Press, 1990
-*/
-
-#define NUMDIM	3
-#define RIGHT	0
-#define LEFT	1
-#define MIDDLE	2
-
-int aabb_intersect_ray(const aabb_t *aabb, const ray_t *ray, vec_t *dist)
-{
-	int inside = 1;
-	char quadrant[NUMDIM];
-	register int i;
-	int whichPlane;
-	double maxT[NUMDIM];
-	double candidatePlane[NUMDIM];
-  vec3_t coord, segment;
-  
-  const float *origin = ray->origin;
-  const float *direction = ray->direction;
-
-	/* Find candidate planes; this loop can be avoided if
-   	rays cast all from the eye(assume perpsective view) */
-	for (i=0; i<NUMDIM; i++)
-  {
-		if(origin[i] < (aabb->origin[i] - aabb->extents[i]))
-    {
-			quadrant[i] = LEFT;
-			candidatePlane[i] = (aabb->origin[i] - aabb->extents[i]);
-			inside = 0;
-		}
-    else if (origin[i] > (aabb->origin[i] + aabb->extents[i]))
-    {
-			quadrant[i] = RIGHT;
-			candidatePlane[i] = (aabb->origin[i] + aabb->extents[i]);
-			inside = 0;
-		}
-    else
-    {
-			quadrant[i] = MIDDLE;
-    }
-  }
-
-	/* Ray origin inside bounding box */
-	if(inside == 1)
-  {
-		*dist = 0.0f;
-		return 1;
-	}
-
-
-	/* Calculate T distances to candidate planes */
-	for (i = 0; i < NUMDIM; i++)
-  {
-		if (quadrant[i] != MIDDLE && direction[i] !=0.)
-			maxT[i] = (candidatePlane[i] - origin[i]) / direction[i];
-		else
-			maxT[i] = -1.;
-  }
-
-	/* Get largest of the maxT's for final choice of intersection */
-	whichPlane = 0;
-	for (i = 1; i < NUMDIM; i++)
-		if (maxT[whichPlane] < maxT[i])
-			whichPlane = i;
-
-	/* Check final candidate actually inside box */
-	if (maxT[whichPlane] < 0.)
-    return 0;
-	for (i = 0; i < NUMDIM; i++)
-  {
-		if (whichPlane != i)
-    {
-			coord[i] = (vec_t)(origin[i] + maxT[whichPlane] * direction[i]);
-			if (fabs(coord[i] - aabb->origin[i]) > aabb->extents[i])
-				return 0;
-		}
-    else
-    {
-			coord[i] = (vec_t)candidatePlane[i];
-		}
-  }
-
-  VectorSubtract(coord, origin, segment);
-  *dist = DotProduct(segment, direction);
-
-	return 1;				/* ray hits box */
-}
-
-int aabb_test_ray(const aabb_t* aabb, const ray_t* ray)
-{
- vec3_t displacement, ray_absolute;
- vec_t f;
- 
- displacement[0] = ray->origin[0] - aabb->origin[0];
- if(fabs(displacement[0]) > aabb->extents[0] && displacement[0] * ray->direction[0] >= 0.0f)
-   return 0;
- 
- displacement[1] = ray->origin[1] - aabb->origin[1];
- if(fabs(displacement[1]) > aabb->extents[1] && displacement[1] * ray->direction[1] >= 0.0f)
-   return 0;
- 
- displacement[2] = ray->origin[2] - aabb->origin[2];
- if(fabs(displacement[2]) > aabb->extents[2] && displacement[2] * ray->direction[2] >= 0.0f)
-   return 0;
- 
- ray_absolute[0] = (float)fabs(ray->direction[0]);
- ray_absolute[1] = (float)fabs(ray->direction[1]);
- ray_absolute[2] = (float)fabs(ray->direction[2]);
-
- f = ray->direction[1] * displacement[2] - ray->direction[2] * displacement[1];
- if((float)fabs(f) > aabb->extents[1] * ray_absolute[2] + aabb->extents[2] * ray_absolute[1])
-   return 0;
-
- f = ray->direction[2] * displacement[0] - ray->direction[0] * displacement[2];
- if((float)fabs(f) > aabb->extents[0] * ray_absolute[2] + aabb->extents[2] * ray_absolute[0])
-   return 0;
-
- f = ray->direction[0] * displacement[1] - ray->direction[1] * displacement[0];
- if((float)fabs(f) > aabb->extents[0] * ray_absolute[1] + aabb->extents[1] * ray_absolute[0])
-   return 0;
- 
- return 1;
-}
-
-void aabb_for_bbox(aabb_t *aabb, const bbox_t *bbox)
-{
-	int i;
-	vec3_t temp[3];
-
-  VectorCopy(bbox->aabb.origin, aabb->origin);
-
-	// calculate the AABB extents in local coord space from the OBB extents and axes
-	VectorScale(bbox->axes[0], bbox->aabb.extents[0], temp[0]);
-	VectorScale(bbox->axes[1], bbox->aabb.extents[1], temp[1]);
-	VectorScale(bbox->axes[2], bbox->aabb.extents[2], temp[2]);
-	for(i=0;i<3;i++) aabb->extents[i] = (vec_t)(fabs(temp[0][i]) + fabs(temp[1][i]) + fabs(temp[2][i]));
-}
-
-void aabb_for_area(aabb_t *aabb, vec3_t area_tl, vec3_t area_br, int axis)
-{
-  aabb_clear(aabb);
-  aabb->extents[axis] = FLT_MAX;
-  aabb_extend_by_point(aabb, area_tl);
-  aabb_extend_by_point(aabb, area_br);
-}
-
-void aabb_for_transformed_aabb(aabb_t* dst, const aabb_t* src, const m4x4_t transform)
-{
-  VectorCopy(src->origin, dst->origin);
-  m4x4_transform_point(transform, dst->origin);
-
-  dst->extents[0] = (vec_t)(fabs(transform[0]  * src->extents[0])
-                          + fabs(transform[4]  * src->extents[1])
-                          + fabs(transform[8]  * src->extents[2]));
-  dst->extents[1] = (vec_t)(fabs(transform[1]  * src->extents[0])
-                          + fabs(transform[5]  * src->extents[1])
-                          + fabs(transform[9]  * src->extents[2]));
-  dst->extents[2] = (vec_t)(fabs(transform[2]  * src->extents[0])
-                          + fabs(transform[6]  * src->extents[1])
-                          + fabs(transform[10] * src->extents[2]));
-}
-
-
-void bbox_for_oriented_aabb(bbox_t *bbox, const aabb_t *aabb, const m4x4_t matrix, const vec3_t euler, const vec3_t scale)
-{
-	double rad[3];
-	double pi_180 = Q_PI / 180;
-  double A, B, C, D, E, F, AD, BD;
-  
-	VectorCopy(aabb->origin, bbox->aabb.origin);
-	
-  m4x4_transform_point(matrix, bbox->aabb.origin);
-
-	bbox->aabb.extents[0] = aabb->extents[0] * scale[0];
-	bbox->aabb.extents[1] = aabb->extents[1] * scale[1];
-	bbox->aabb.extents[2] = aabb->extents[2] * scale[2];
-
-  rad[0] = euler[0] * pi_180;
-	rad[1] = euler[1] * pi_180;
-	rad[2] = euler[2] * pi_180;
-
-  A       = cos(rad[0]);
-  B       = sin(rad[0]);
-  C       = cos(rad[1]);
-  D       = sin(rad[1]);
-  E       = cos(rad[2]);
-  F       = sin(rad[2]);
-
-  AD      =   A * -D;
-  BD      =   B * -D;
-
-	bbox->axes[0][0] = (vec_t)(C*E);
-	bbox->axes[0][1] = (vec_t)(-BD*E + A*F);
-	bbox->axes[0][2] = (vec_t)(AD*E + B*F);
-	bbox->axes[1][0] = (vec_t)(-C*F);
-	bbox->axes[1][1] = (vec_t)(BD*F + A*E);
-	bbox->axes[1][2] = (vec_t)(-AD*F + B*E);
-	bbox->axes[2][0] = (vec_t)D;
-	bbox->axes[2][1] = (vec_t)(-B*C);
-	bbox->axes[2][2] = (vec_t)(A*C);
-
-  aabb_update_radius(&bbox->aabb);
-}
-
-int bbox_intersect_plane(const bbox_t *bbox, const vec_t* plane)
-{
-  vec_t fDist, fIntersect;
-
-  // calc distance of origin from plane
-  fDist = DotProduct(plane, bbox->aabb.origin) + plane[3];
-
-	// trivial accept/reject using bounding sphere
-	if (fabs(fDist) > bbox->aabb.radius)
-	{
-		if (fDist < 0)
-			return 2; // totally inside
-		else
-			return 0; // totally outside
-	}
-
-  // calc extents distance relative to plane normal
-  fIntersect = (vec_t)(fabs(bbox->aabb.extents[0] * DotProduct(plane, bbox->axes[0]))
-             + fabs(bbox->aabb.extents[1] * DotProduct(plane, bbox->axes[1]))
-             + fabs(bbox->aabb.extents[2] * DotProduct(plane, bbox->axes[2])));
-  // accept if origin is less than this distance
-  if (fabs(fDist) < fIntersect) return 1; // partially inside
-  else if (fDist < 0) return 2; // totally inside
-  return 0; // totally outside
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <float.h>
+
+#include "mathlib.h"
+
+void aabb_construct_for_vec3(aabb_t *aabb, const vec3_t min, const vec3_t max)
+{
+  VectorMid(min, max, aabb->origin);
+  VectorSubtract(max, aabb->origin, aabb->extents);
+}
+
+void aabb_update_radius(aabb_t *aabb)
+{
+  aabb->radius = VectorLength(aabb->extents);
+}
+
+void aabb_clear(aabb_t *aabb)
+{
+  aabb->origin[0] = aabb->origin[1] = aabb->origin[2] = 0;
+  aabb->extents[0] = aabb->extents[1] = aabb->extents[2] = -FLT_MAX;
+}
+
+void aabb_extend_by_point(aabb_t *aabb, const vec3_t point)
+{
+  int i;
+  vec_t min, max, displacement;
+  for(i=0; i<3; i++)
+  {
+    displacement = point[i] - aabb->origin[i];
+    if(fabs(displacement) > aabb->extents[i])
+    {
+      if(aabb->extents[i] < 0) // degenerate
+      {
+        min = max = point[i];
+      }
+      else if(displacement > 0)
+      {
+        min = aabb->origin[i] - aabb->extents[i];
+        max = aabb->origin[i] + displacement;
+      }
+      else
+      {
+        max = aabb->origin[i] + aabb->extents[i];
+        min = aabb->origin[i] + displacement;
+      }
+      aabb->origin[i] = (min + max) * 0.5f;
+      aabb->extents[i] = max - aabb->origin[i];
+    }
+  }
+}
+
+void aabb_extend_by_aabb(aabb_t *aabb, const aabb_t *aabb_src)
+{
+  int i;
+  vec_t min, max, displacement, difference;
+  for(i=0; i<3; i++)
+  {
+    displacement = aabb_src->origin[i] - aabb->origin[i];
+    difference = aabb_src->extents[i] - aabb->extents[i];
+    if(aabb->extents[i] < 0
+      || difference >= fabs(displacement))
+    {
+      // 2nd contains 1st
+      aabb->extents[i] = aabb_src->extents[i];
+      aabb->origin[i] = aabb_src->origin[i];
+    }
+    else if(aabb_src->extents[i] < 0
+      || -difference >= fabs(displacement))
+    {
+      // 1st contains 2nd
+      continue;
+    }
+    else
+    {
+      // not contained
+      if(displacement > 0)
+      {
+        min = aabb->origin[i] - aabb->extents[i];
+        max = aabb_src->origin[i] + aabb_src->extents[i];
+      }
+      else
+      {
+        min = aabb_src->origin[i] - aabb_src->extents[i];
+        max = aabb->origin[i] + aabb->extents[i];
+      }
+      aabb->origin[i] = (min + max) * 0.5f;
+      aabb->extents[i] = max - aabb->origin[i];
+    }
+  }
+}
+
+void aabb_extend_by_vec3(aabb_t *aabb, vec3_t extension)
+{
+  VectorAdd(aabb->extents, extension, aabb->extents);
+}
+
+int aabb_intersect_point(const aabb_t *aabb, const vec3_t point)
+{
+  int i;
+  for(i=0; i<3; i++)
+    if(fabs(point[i] - aabb->origin[i]) >= aabb->extents[i])
+      return 0;
+  return 1;
+}
+
+int aabb_intersect_aabb(const aabb_t *aabb, const aabb_t *aabb_src)
+{
+  int i;
+  for (i=0; i<3; i++)
+    if ( fabs(aabb_src->origin[i] - aabb->origin[i]) > (fabs(aabb->extents[i]) + fabs(aabb_src->extents[i])) )
+      return 0;
+  return 1;
+}
+
+int aabb_intersect_plane(const aabb_t *aabb, const float *plane)
+{
+  float fDist, fIntersect;
+
+  // calc distance of origin from plane
+  fDist = DotProduct(plane, aabb->origin) + plane[3];
+  
+  // trivial accept/reject using bounding sphere
+	if (fabs(fDist) > aabb->radius)
+	{
+		if (fDist < 0)
+			return 2; // totally inside
+		else
+			return 0; // totally outside
+	}
+
+  // calc extents distance relative to plane normal
+  fIntersect = (vec_t)(fabs(plane[0] * aabb->extents[0]) + fabs(plane[1] * aabb->extents[1]) + fabs(plane[2] * aabb->extents[2]));
+  // accept if origin is less than or equal to this distance
+  if (fabs(fDist) < fIntersect) return 1; // partially inside
+  else if (fDist < 0) return 2; // totally inside
+  return 0; // totally outside
+}
+
+/* 
+Fast Ray-Box Intersection
+by Andrew Woo
+from "Graphics Gems", Academic Press, 1990
+*/
+
+#define NUMDIM	3
+#define RIGHT	0
+#define LEFT	1
+#define MIDDLE	2
+
+int aabb_intersect_ray(const aabb_t *aabb, const ray_t *ray, vec_t *dist)
+{
+	int inside = 1;
+	char quadrant[NUMDIM];
+	register int i;
+	int whichPlane;
+	double maxT[NUMDIM];
+	double candidatePlane[NUMDIM];
+  vec3_t coord, segment;
+  
+  const float *origin = ray->origin;
+  const float *direction = ray->direction;
+
+	/* Find candidate planes; this loop can be avoided if
+   	rays cast all from the eye(assume perpsective view) */
+	for (i=0; i<NUMDIM; i++)
+  {
+		if(origin[i] < (aabb->origin[i] - aabb->extents[i]))
+    {
+			quadrant[i] = LEFT;
+			candidatePlane[i] = (aabb->origin[i] - aabb->extents[i]);
+			inside = 0;
+		}
+    else if (origin[i] > (aabb->origin[i] + aabb->extents[i]))
+    {
+			quadrant[i] = RIGHT;
+			candidatePlane[i] = (aabb->origin[i] + aabb->extents[i]);
+			inside = 0;
+		}
+    else
+    {
+			quadrant[i] = MIDDLE;
+    }
+  }
+
+	/* Ray origin inside bounding box */
+	if(inside == 1)
+  {
+		*dist = 0.0f;
+		return 1;
+	}
+
+
+	/* Calculate T distances to candidate planes */
+	for (i = 0; i < NUMDIM; i++)
+  {
+		if (quadrant[i] != MIDDLE && direction[i] !=0.)
+			maxT[i] = (candidatePlane[i] - origin[i]) / direction[i];
+		else
+			maxT[i] = -1.;
+  }
+
+	/* Get largest of the maxT's for final choice of intersection */
+	whichPlane = 0;
+	for (i = 1; i < NUMDIM; i++)
+		if (maxT[whichPlane] < maxT[i])
+			whichPlane = i;
+
+	/* Check final candidate actually inside box */
+	if (maxT[whichPlane] < 0.)
+    return 0;
+	for (i = 0; i < NUMDIM; i++)
+  {
+		if (whichPlane != i)
+    {
+			coord[i] = (vec_t)(origin[i] + maxT[whichPlane] * direction[i]);
+			if (fabs(coord[i] - aabb->origin[i]) > aabb->extents[i])
+				return 0;
+		}
+    else
+    {
+			coord[i] = (vec_t)candidatePlane[i];
+		}
+  }
+
+  VectorSubtract(coord, origin, segment);
+  *dist = DotProduct(segment, direction);
+
+	return 1;				/* ray hits box */
+}
+
+int aabb_test_ray(const aabb_t* aabb, const ray_t* ray)
+{
+ vec3_t displacement, ray_absolute;
+ vec_t f;
+ 
+ displacement[0] = ray->origin[0] - aabb->origin[0];
+ if(fabs(displacement[0]) > aabb->extents[0] && displacement[0] * ray->direction[0] >= 0.0f)
+   return 0;
+ 
+ displacement[1] = ray->origin[1] - aabb->origin[1];
+ if(fabs(displacement[1]) > aabb->extents[1] && displacement[1] * ray->direction[1] >= 0.0f)
+   return 0;
+ 
+ displacement[2] = ray->origin[2] - aabb->origin[2];
+ if(fabs(displacement[2]) > aabb->extents[2] && displacement[2] * ray->direction[2] >= 0.0f)
+   return 0;
+ 
+ ray_absolute[0] = (float)fabs(ray->direction[0]);
+ ray_absolute[1] = (float)fabs(ray->direction[1]);
+ ray_absolute[2] = (float)fabs(ray->direction[2]);
+
+ f = ray->direction[1] * displacement[2] - ray->direction[2] * displacement[1];
+ if((float)fabs(f) > aabb->extents[1] * ray_absolute[2] + aabb->extents[2] * ray_absolute[1])
+   return 0;
+
+ f = ray->direction[2] * displacement[0] - ray->direction[0] * displacement[2];
+ if((float)fabs(f) > aabb->extents[0] * ray_absolute[2] + aabb->extents[2] * ray_absolute[0])
+   return 0;
+
+ f = ray->direction[0] * displacement[1] - ray->direction[1] * displacement[0];
+ if((float)fabs(f) > aabb->extents[0] * ray_absolute[1] + aabb->extents[1] * ray_absolute[0])
+   return 0;
+ 
+ return 1;
+}
+
+void aabb_for_bbox(aabb_t *aabb, const bbox_t *bbox)
+{
+	int i;
+	vec3_t temp[3];
+
+  VectorCopy(bbox->aabb.origin, aabb->origin);
+
+	// calculate the AABB extents in local coord space from the OBB extents and axes
+	VectorScale(bbox->axes[0], bbox->aabb.extents[0], temp[0]);
+	VectorScale(bbox->axes[1], bbox->aabb.extents[1], temp[1]);
+	VectorScale(bbox->axes[2], bbox->aabb.extents[2], temp[2]);
+	for(i=0;i<3;i++) aabb->extents[i] = (vec_t)(fabs(temp[0][i]) + fabs(temp[1][i]) + fabs(temp[2][i]));
+}
+
+void aabb_for_area(aabb_t *aabb, vec3_t area_tl, vec3_t area_br, int axis)
+{
+  aabb_clear(aabb);
+  aabb->extents[axis] = FLT_MAX;
+  aabb_extend_by_point(aabb, area_tl);
+  aabb_extend_by_point(aabb, area_br);
+}
+
+void aabb_for_transformed_aabb(aabb_t* dst, const aabb_t* src, const m4x4_t transform)
+{
+  VectorCopy(src->origin, dst->origin);
+  m4x4_transform_point(transform, dst->origin);
+
+  dst->extents[0] = (vec_t)(fabs(transform[0]  * src->extents[0])
+                          + fabs(transform[4]  * src->extents[1])
+                          + fabs(transform[8]  * src->extents[2]));
+  dst->extents[1] = (vec_t)(fabs(transform[1]  * src->extents[0])
+                          + fabs(transform[5]  * src->extents[1])
+                          + fabs(transform[9]  * src->extents[2]));
+  dst->extents[2] = (vec_t)(fabs(transform[2]  * src->extents[0])
+                          + fabs(transform[6]  * src->extents[1])
+                          + fabs(transform[10] * src->extents[2]));
+}
+
+
+void bbox_for_oriented_aabb(bbox_t *bbox, const aabb_t *aabb, const m4x4_t matrix, const vec3_t euler, const vec3_t scale)
+{
+	double rad[3];
+	double pi_180 = Q_PI / 180;
+  double A, B, C, D, E, F, AD, BD;
+  
+	VectorCopy(aabb->origin, bbox->aabb.origin);
+	
+  m4x4_transform_point(matrix, bbox->aabb.origin);
+
+	bbox->aabb.extents[0] = aabb->extents[0] * scale[0];
+	bbox->aabb.extents[1] = aabb->extents[1] * scale[1];
+	bbox->aabb.extents[2] = aabb->extents[2] * scale[2];
+
+  rad[0] = euler[0] * pi_180;
+	rad[1] = euler[1] * pi_180;
+	rad[2] = euler[2] * pi_180;
+
+  A       = cos(rad[0]);
+  B       = sin(rad[0]);
+  C       = cos(rad[1]);
+  D       = sin(rad[1]);
+  E       = cos(rad[2]);
+  F       = sin(rad[2]);
+
+  AD      =   A * -D;
+  BD      =   B * -D;
+
+	bbox->axes[0][0] = (vec_t)(C*E);
+	bbox->axes[0][1] = (vec_t)(-BD*E + A*F);
+	bbox->axes[0][2] = (vec_t)(AD*E + B*F);
+	bbox->axes[1][0] = (vec_t)(-C*F);
+	bbox->axes[1][1] = (vec_t)(BD*F + A*E);
+	bbox->axes[1][2] = (vec_t)(-AD*F + B*E);
+	bbox->axes[2][0] = (vec_t)D;
+	bbox->axes[2][1] = (vec_t)(-B*C);
+	bbox->axes[2][2] = (vec_t)(A*C);
+
+  aabb_update_radius(&bbox->aabb);
+}
+
+int bbox_intersect_plane(const bbox_t *bbox, const vec_t* plane)
+{
+  vec_t fDist, fIntersect;
+
+  // calc distance of origin from plane
+  fDist = DotProduct(plane, bbox->aabb.origin) + plane[3];
+
+	// trivial accept/reject using bounding sphere
+	if (fabs(fDist) > bbox->aabb.radius)
+	{
+		if (fDist < 0)
+			return 2; // totally inside
+		else
+			return 0; // totally outside
+	}
+
+  // calc extents distance relative to plane normal
+  fIntersect = (vec_t)(fabs(bbox->aabb.extents[0] * DotProduct(plane, bbox->axes[0]))
+             + fabs(bbox->aabb.extents[1] * DotProduct(plane, bbox->axes[1]))
+             + fabs(bbox->aabb.extents[2] * DotProduct(plane, bbox->axes[2])));
+  // accept if origin is less than this distance
+  if (fabs(fDist) < fIntersect) return 1; // partially inside
+  else if (fDist < 0) return 2; // totally inside
+  return 0; // totally outside
+}
diff --git a/libs/mathlib/linear.c b/libs/mathlib/linear.c
index bdef7145..7414c135 100644
--- a/libs/mathlib/linear.c
+++ b/libs/mathlib/linear.c
@@ -1,100 +1,100 @@
-#ifndef __APPLE__
-#include <malloc.h>
-#else
-#include <stdlib.h>
-#endif
-#include <limits.h>
-#include <float.h>
-
-#include "mathlib.h"
-
-#define TINY FLT_MIN
-
-void lubksb(float **a, int n, int *indx, float b[])
-// Solves the set of n linear equations A.X=B. Here a[n][n] is input, not as the matrix
-// A but rather as its LU decomposition determined by the routine ludcmp. indx[n] is input
-// as the permutation vector returned by ludcmp. b[n] is input as the right-hand side vector
-// B, and returns with the solution vector X. a, n and indx are not modified by this routine
-// and can be left in place for successive calls with different right-hand sides b. This routine takes
-// into account the possibility that b will begin with many zero elements, so it is efficient for use
-// in matrix inversion
-{
-	int i,ii=-1,ip,j;
-	float sum;
-
-	for (i=0;i<n;i++) {
-		ip=indx[i];
-		sum=b[ip];
-		b[ip]=b[i];
-		if (ii>=0)
-			for (j=ii;j<i;j++) sum -= a[i][j]*b[j];
-		else if (sum) ii=i;
-		b[i]=sum;
-	}
-	for (i=n-1;i>=0;i--) {
-		sum=b[i];
-		for (j=i+1;j<n;j++) sum -= a[i][j]*b[j];
-		b[i]=sum/a[i][i];
-	}
-}
-/* (C) Copr. 1986-92 Numerical Recipes Software */
-
-
-int ludcmp(float **a, int n, int *indx, float *d)
-// given a matrix a[n][n] this routine replaces it with the LU decomposition of a rowwise
-// permutation of itself. a and n are input. a is output, arranged as in above equation;
-// indx[n] is an output vector that records the row permutation effected by the partial
-// pivoting; d is output as +/-1 depending on whether the number of row interchanges was even
-// or odd, respectively. This routine is used in combination with lubksb to solve linear
-// equations or invert a matrix.
-{
-	int i,imax,j,k;
-	float big,dum,sum,temp;
-	float *vv;
-
-	vv=(float*)malloc(sizeof(float)*n);
-	*d=1.0;
-	for (i=0;i<n;i++) {
-		big=0.0;
-		for (j=0;j<n;j++)
-			if ((temp=(float)fabs(a[i][j])) > big) big=temp;
-		if (big == 0.0) return 1;
-		vv[i]=1.0f/big;
-	}
-	for (j=0;j<n;j++) {
-		for (i=0;i<j;i++) {
-			sum=a[i][j];
-			for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
-			a[i][j]=sum;
-		}
-		big=0.0;
-		for (i=j;i<n;i++) {
-			sum=a[i][j];
-			for (k=0;k<j;k++)
-				sum -= a[i][k]*a[k][j];
-			a[i][j]=sum;
-			if ( (dum=vv[i]*(float)fabs(sum)) >= big) {
-				big=dum;
-				imax=i;
-			}
-		}
-		if (j != imax) {
-			for (k=0;k<n;k++) {
-				dum=a[imax][k];
-				a[imax][k]=a[j][k];
-				a[j][k]=dum;
-			}
-			*d = -(*d);
-			vv[imax]=vv[j];
-		}
-		indx[j]=imax;
-		if (a[j][j] == 0.0) a[j][j]=TINY;
-		if (j != n) {
-			dum=1.0f/(a[j][j]);
-			for (i=j+1;i<n;i++) a[i][j] *= dum;
-		}
-	}
-	free(vv);
-  return 0;
-}
-/* (C) Copr. 1986-92 Numerical Recipes Software */
+#ifndef __APPLE__
+#include <malloc.h>
+#else
+#include <stdlib.h>
+#endif
+#include <limits.h>
+#include <float.h>
+
+#include "mathlib.h"
+
+#define TINY FLT_MIN
+
+void lubksb(float **a, int n, int *indx, float b[])
+// Solves the set of n linear equations A.X=B. Here a[n][n] is input, not as the matrix
+// A but rather as its LU decomposition determined by the routine ludcmp. indx[n] is input
+// as the permutation vector returned by ludcmp. b[n] is input as the right-hand side vector
+// B, and returns with the solution vector X. a, n and indx are not modified by this routine
+// and can be left in place for successive calls with different right-hand sides b. This routine takes
+// into account the possibility that b will begin with many zero elements, so it is efficient for use
+// in matrix inversion
+{
+	int i,ii=-1,ip,j;
+	float sum;
+
+	for (i=0;i<n;i++) {
+		ip=indx[i];
+		sum=b[ip];
+		b[ip]=b[i];
+		if (ii>=0)
+			for (j=ii;j<i;j++) sum -= a[i][j]*b[j];
+		else if (sum) ii=i;
+		b[i]=sum;
+	}
+	for (i=n-1;i>=0;i--) {
+		sum=b[i];
+		for (j=i+1;j<n;j++) sum -= a[i][j]*b[j];
+		b[i]=sum/a[i][i];
+	}
+}
+/* (C) Copr. 1986-92 Numerical Recipes Software */
+
+
+int ludcmp(float **a, int n, int *indx, float *d)
+// given a matrix a[n][n] this routine replaces it with the LU decomposition of a rowwise
+// permutation of itself. a and n are input. a is output, arranged as in above equation;
+// indx[n] is an output vector that records the row permutation effected by the partial
+// pivoting; d is output as +/-1 depending on whether the number of row interchanges was even
+// or odd, respectively. This routine is used in combination with lubksb to solve linear
+// equations or invert a matrix.
+{
+	int i,imax,j,k;
+	float big,dum,sum,temp;
+	float *vv;
+
+	vv=(float*)malloc(sizeof(float)*n);
+	*d=1.0;
+	for (i=0;i<n;i++) {
+		big=0.0;
+		for (j=0;j<n;j++)
+			if ((temp=(float)fabs(a[i][j])) > big) big=temp;
+		if (big == 0.0) return 1;
+		vv[i]=1.0f/big;
+	}
+	for (j=0;j<n;j++) {
+		for (i=0;i<j;i++) {
+			sum=a[i][j];
+			for (k=0;k<i;k++) sum -= a[i][k]*a[k][j];
+			a[i][j]=sum;
+		}
+		big=0.0;
+		for (i=j;i<n;i++) {
+			sum=a[i][j];
+			for (k=0;k<j;k++)
+				sum -= a[i][k]*a[k][j];
+			a[i][j]=sum;
+			if ( (dum=vv[i]*(float)fabs(sum)) >= big) {
+				big=dum;
+				imax=i;
+			}
+		}
+		if (j != imax) {
+			for (k=0;k<n;k++) {
+				dum=a[imax][k];
+				a[imax][k]=a[j][k];
+				a[j][k]=dum;
+			}
+			*d = -(*d);
+			vv[imax]=vv[j];
+		}
+		indx[j]=imax;
+		if (a[j][j] == 0.0) a[j][j]=TINY;
+		if (j != n) {
+			dum=1.0f/(a[j][j]);
+			for (i=j+1;i<n;i++) a[i][j] *= dum;
+		}
+	}
+	free(vv);
+  return 0;
+}
+/* (C) Copr. 1986-92 Numerical Recipes Software */
diff --git a/libs/mathlib/m4x4.c b/libs/mathlib/m4x4.c
index c1d01ee4..c2c64c53 100644
--- a/libs/mathlib/m4x4.c
+++ b/libs/mathlib/m4x4.c
@@ -1,790 +1,790 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "mathlib.h"
-#include "memory.h"
-
-void m4x4_identity(m4x4_t matrix)
-{
-  matrix[1] = matrix[2] = matrix[3] =
-  matrix[4] = matrix[6] = matrix[7] =
-  matrix[8] = matrix[9] = matrix[11] =
-  matrix[12] = matrix[13] = matrix[14] = 0;
-
-  matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1;
-}
-
-void m4x4_translation_for_vec3(m4x4_t matrix, const vec3_t translation)
-{
-  matrix[1] = matrix[2] = matrix[3] =
-  matrix[4] = matrix[6] = matrix[7] =
-  matrix[8] = matrix[9] = matrix[11] = 0;
-
-  matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1;
-
-  matrix[12] = translation[0];
-  matrix[13] = translation[1];
-  matrix[14] = translation[2];
-}
-
-void m4x4_rotation_for_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order)
-{
-  double cx, sx, cy, sy, cz, sz;
-    
-  cx = cos(DEG2RAD(euler[0]));
-  sx = sin(DEG2RAD(euler[0]));
-  cy = cos(DEG2RAD(euler[1]));
-  sy = sin(DEG2RAD(euler[1]));
-  cz = cos(DEG2RAD(euler[2]));
-  sz = sin(DEG2RAD(euler[2]));
-
-  switch(order)
-  {
-  case eXYZ:
-
-#if 1
-
-    {
-      matrix[0]  = (vec_t)(cy*cz);
-      matrix[1]  = (vec_t)(cy*sz);
-      matrix[2]  = (vec_t)-sy;
-      matrix[4]  = (vec_t)(sx*sy*cz + cx*-sz);
-      matrix[5]  = (vec_t)(sx*sy*sz + cx*cz);
-      matrix[6]  = (vec_t)(sx*cy);
-      matrix[8]  = (vec_t)(cx*sy*cz + sx*sz);
-      matrix[9]  = (vec_t)(cx*sy*sz + -sx*cz);
-      matrix[10] = (vec_t)(cx*cy);
-    }
-
-    matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
-    matrix[15] =  1;
-
-#else
-
-    m4x4_identity(matrix);
-    matrix[5] =(vec_t) cx; matrix[6] =(vec_t) sx;
-    matrix[9] =(vec_t)-sx; matrix[10]=(vec_t) cx;
-
-    {
-      m4x4_t temp;
-      m4x4_identity(temp);
-      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
-      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-      m4x4_identity(temp);
-      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
-      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-    }
-#endif
-
-    break;
-
-  case eYZX:
-    m4x4_identity(matrix);
-    matrix[0] =(vec_t) cy; matrix[2] =(vec_t)-sy;
-    matrix[8] =(vec_t) sy; matrix[10]=(vec_t) cy;
-
-    {
-      m4x4_t temp;
-      m4x4_identity(temp);
-      temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
-      temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-      m4x4_identity(temp);
-      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
-      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-    }
-    break;
-
-  case eZXY:
-    m4x4_identity(matrix);
-    matrix[0] =(vec_t) cz; matrix[1] =(vec_t) sz;
-    matrix[4] =(vec_t)-sz; matrix[5] =(vec_t) cz;
-
-    {
-      m4x4_t temp;
-      m4x4_identity(temp);
-      temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
-      temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-      m4x4_identity(temp);
-      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
-      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-    }
-    break;
-
-  case eXZY:
-    m4x4_identity(matrix);
-    matrix[5] =(vec_t) cx; matrix[6] =(vec_t) sx;
-    matrix[9] =(vec_t)-sx; matrix[10]=(vec_t) cx;
-
-    {
-      m4x4_t temp;
-      m4x4_identity(temp);
-      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
-      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-      m4x4_identity(temp);
-      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
-      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
-      m4x4_premultiply_by_m4x4(matrix, temp);
-    }
-    break;
-
-  case eYXZ:
-
-/* transposed
-|  cy.cz + sx.sy.-sz + -cx.sy.0   0.cz + cx.-sz + sx.0   sy.cz + -sx.cy.-sz + cx.cy.0 |
-|  cy.sz + sx.sy.cz + -cx.sy.0    0.sz + cx.cz + sx.0    sy.sz + -sx.cy.cz + cx.cy.0  |
-|  cy.0 + sx.sy.0 + -cx.sy.1      0.0 + cx.0 + sx.1      sy.0 + -sx.cy.0 + cx.cy.1    |
-*/
-
-#if 1
-
-  {
-    matrix[0]  = (vec_t)(cy*cz + sx*sy*-sz);
-    matrix[1]  = (vec_t)(cy*sz + sx*sy*cz);
-    matrix[2]  = (vec_t)(-cx*sy);
-    matrix[4]  = (vec_t)(cx*-sz);
-    matrix[5]  = (vec_t)(cx*cz);
-    matrix[6]  = (vec_t)(sx);
-    matrix[8]  = (vec_t)(sy*cz + -sx*cy*-sz);
-    matrix[9]  = (vec_t)(sy*sz + -sx*cy*cz);
-    matrix[10] = (vec_t)(cx*cy);
-  }
-
-  matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
-  matrix[15] =  1;
-
-#else
-
-  m4x4_identity(matrix);
-  matrix[0] =(vec_t) cy; matrix[2] =(vec_t)-sy;
-  matrix[8] =(vec_t) sy; matrix[10]=(vec_t) cy;
-
-  {
-    m4x4_t temp;
-    m4x4_identity(temp);
-    temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
-    temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
-    m4x4_premultiply_by_m4x4(matrix, temp);
-    m4x4_identity(temp);
-    temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
-    temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
-    m4x4_premultiply_by_m4x4(matrix, temp);
-  }
-#endif
-  break;
-
-  case eZYX:
-#if 1
-
-  {
-    matrix[0]  = (vec_t)(cy*cz);
-    matrix[4]  = (vec_t)(cy*-sz);
-    matrix[8]  = (vec_t)sy;
-    matrix[1]  = (vec_t)(sx*sy*cz + cx*sz);
-    matrix[5]  = (vec_t)(sx*sy*-sz + cx*cz);
-    matrix[9]  = (vec_t)(-sx*cy);
-    matrix[2]  = (vec_t)(cx*-sy*cz + sx*sz);
-    matrix[6]  = (vec_t)(cx*-sy*-sz + sx*cz);
-    matrix[10] = (vec_t)(cx*cy);
-  }
-
-  matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
-  matrix[15] =  1;
-
-#else
-
-  m4x4_identity(matrix);
-  matrix[0] =(vec_t) cz; matrix[1] =(vec_t) sz;
-  matrix[4] =(vec_t)-sz; matrix[5] =(vec_t) cz;
-  {
-    m4x4_t temp;
-    m4x4_identity(temp);
-    temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
-    temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
-    m4x4_premultiply_by_m4x4(matrix, temp);
-    m4x4_identity(temp);
-    temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
-    temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
-    m4x4_premultiply_by_m4x4(matrix, temp);
-  }
-
-#endif
-  break;
-
-  }
-
-}
-
-void m4x4_scale_for_vec3(m4x4_t matrix, const vec3_t scale)
-{
-  matrix[1] = matrix[2] = matrix[3] =
-  matrix[4] = matrix[6] = matrix[7] =
-  matrix[8] = matrix[9] = matrix[11] =
-  matrix[12] = matrix[13] = matrix[14] = 0;
-
-  matrix[15] = 1;
-
-  matrix[0] = scale[0];
-  matrix[5] = scale[1];
-  matrix[10] = scale[2];
-}
-
-void m4x4_rotation_for_quat(m4x4_t matrix, const vec4_t rotation)
-{
-  float xx,xy,xz,xw,yy,yz,yw,zz,zw;
-
-  xx      = rotation[0] * rotation[0];
-  xy      = rotation[0] * rotation[1];
-  xz      = rotation[0] * rotation[2];
-  xw      = rotation[0] * rotation[3];
-
-  yy      = rotation[1] * rotation[1];
-  yz      = rotation[1] * rotation[2];
-  yw      = rotation[1] * rotation[3];
-
-  zz      = rotation[2] * rotation[2];
-  zw      = rotation[2] * rotation[3];
-
-  matrix[0]  = 1 - 2 * ( yy + zz );
-  matrix[4]  =     2 * ( xy - zw );
-  matrix[8]  =     2 * ( xz + yw );
-
-  matrix[1]  =     2 * ( xy + zw );
-  matrix[5]  = 1 - 2 * ( xx + zz );
-  matrix[9]  =     2 * ( yz - xw );
-
-  matrix[2]  =     2 * ( xz - yw );
-  matrix[6]  =     2 * ( yz + xw );
-  matrix[10] = 1 - 2 * ( xx + yy );
-
-  matrix[3]  = matrix[7] = matrix[11] = matrix[12] = matrix[13] = matrix[14] = 0;
-  matrix[15] = 1;
-}
-
-void m4x4_rotation_for_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle)
-{
-  vec4_t rotation;
-  angle *= 0.5;
-
-  rotation[3] = (float)sin((float)(angle));
-
-  rotation[0]    = axis[0] * rotation[3];
-  rotation[1]    = axis[1] * rotation[3];
-  rotation[2]    = axis[2] * rotation[3];
-  rotation[3]    = (float)cos((float)(angle));
-
-  m4x4_rotation_for_quat(matrix, rotation);
-}
-
-void m4x4_translate_by_vec3(m4x4_t matrix, const vec3_t translation)
-{
-  m4x4_t temp;
-  m4x4_translation_for_vec3(temp, translation);
-  m4x4_multiply_by_m4x4(matrix, temp);
-}
-
-void m4x4_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order)
-{
-  m4x4_t temp;
-  m4x4_rotation_for_vec3(temp, euler, order);
-  m4x4_multiply_by_m4x4(matrix, temp);
-}
-
-void m4x4_scale_by_vec3(m4x4_t matrix, const vec3_t scale)
-{
-  m4x4_t temp;
-  m4x4_scale_for_vec3(temp, scale);
-  m4x4_multiply_by_m4x4(matrix, temp);
-}
-
-void m4x4_rotate_by_quat(m4x4_t matrix, const vec4_t rotation)
-{
-  m4x4_t temp;
-  m4x4_rotation_for_quat(temp, rotation);
-  m4x4_multiply_by_m4x4(matrix, temp);
-}
-
-void m4x4_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle)
-{
-  m4x4_t temp;
-  m4x4_rotation_for_axisangle(temp, axis, angle);
-  m4x4_multiply_by_m4x4(matrix, temp);
-}
-
-void m4x4_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale)
-{
-  m4x4_translate_by_vec3(matrix, translation);
-  m4x4_rotate_by_vec3(matrix, euler, order);
-  m4x4_scale_by_vec3(matrix, scale);
-}
-
-void m4x4_pivoted_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order, const vec3_t pivotpoint)
-{
-  vec3_t vec3_temp;
-  VectorNegative(pivotpoint, vec3_temp);
-
-  m4x4_translate_by_vec3(matrix, pivotpoint);
-  m4x4_rotate_by_vec3(matrix, euler, order);
-  m4x4_translate_by_vec3(matrix, vec3_temp);
-}
-
-void m4x4_pivoted_scale_by_vec3(m4x4_t matrix, const vec3_t scale, const vec3_t pivotpoint)
-{
-  vec3_t vec3_temp;
-  VectorNegative(pivotpoint, vec3_temp);
-
-  m4x4_translate_by_vec3(matrix, pivotpoint);
-  m4x4_scale_by_vec3(matrix, scale);
-  m4x4_translate_by_vec3(matrix, vec3_temp);
-}
-
-void m4x4_pivoted_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale, const vec3_t pivotpoint)
-{
-  vec3_t vec3_temp;
-
-  VectorAdd(pivotpoint, translation, vec3_temp);
-  m4x4_translate_by_vec3(matrix, vec3_temp);
-  m4x4_rotate_by_vec3(matrix, euler, order);
-  m4x4_scale_by_vec3(matrix, scale);
-  VectorNegative(pivotpoint, vec3_temp);
-  m4x4_translate_by_vec3(matrix, vec3_temp);
-}
-
-void m4x4_pivoted_rotate_by_quat(m4x4_t matrix, const vec4_t rotation, const vec3_t pivotpoint)
-{
-  vec3_t vec3_temp;
-  VectorNegative(pivotpoint, vec3_temp);
-
-  m4x4_translate_by_vec3(matrix, pivotpoint);
-  m4x4_rotate_by_quat(matrix, rotation);
-  m4x4_translate_by_vec3(matrix, vec3_temp);
-}
-
-void m4x4_pivoted_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle, const vec3_t pivotpoint)
-{
-  vec3_t vec3_temp;
-  VectorNegative(pivotpoint, vec3_temp);
-
-  m4x4_translate_by_vec3(matrix, pivotpoint);
-  m4x4_rotate_by_axisangle(matrix, axis, angle);
-  m4x4_translate_by_vec3(matrix, vec3_temp);
-}
-
-
-/*
-A = A.B
-
-A0 = B0 * A0 + B1 * A4 + B2 * A8 + B3 * A12
-A4 = B4 * A0 + B5 * A4 + B6 * A8 + B7 * A12
-A8 = B8 * A0 + B9 * A4 + B10* A8 + B11* A12
-A12= B12* A0 + B13* A4 + B14* A8 + B15* A12
-
-A1 = B0 * A1 + B1 * A5 + B2 * A9 + B3 * A13
-A5 = B4 * A1 + B5 * A5 + B6 * A9 + B7 * A13
-A9 = B8 * A1 + B9 * A5 + B10* A9 + B11* A13
-A13= B12* A1 + B13* A5 + B14* A9 + B15* A13
-
-A2 = B0 * A2 + B1 * A6 + B2 * A10+ B3 * A14
-A6 = B4 * A2 + B5 * A6 + B6 * A10+ B7 * A14
-A10= B8 * A2 + B9 * A6 + B10* A10+ B11* A14
-A14= B12* A2 + B13* A6 + B14* A10+ B15* A14
-
-A3 = B0 * A3 + B1 * A7 + B2 * A11+ B3 * A15
-A7 = B4 * A3 + B5 * A7 + B6 * A11+ B7 * A15
-A11= B8 * A3 + B9 * A7 + B10* A11+ B11* A15
-A15= B12* A3 + B13* A7 + B14* A11+ B15* A15
-*/
-
-void m4x4_multiply_by_m4x4(m4x4_t dst, const m4x4_t src)
-{
-	vec_t dst0, dst1, dst2, dst3;
-
-#if 1
-
-  dst0 = src[0] * dst[0] + src[1] * dst[4] + src[2] * dst[8] + src[3] * dst[12];
-  dst1 = src[4] * dst[0] + src[5] * dst[4] + src[6] * dst[8] + src[7] * dst[12];
-  dst2 = src[8] * dst[0] + src[9] * dst[4] + src[10]* dst[8] + src[11]* dst[12];
-  dst3 = src[12]* dst[0] + src[13]* dst[4] + src[14]* dst[8] + src[15]* dst[12];
-  dst[0] = dst0; dst[4] = dst1; dst[8] = dst2; dst[12]= dst3;
-
-  dst0 = src[0] * dst[1] + src[1] * dst[5] + src[2] * dst[9] + src[3] * dst[13];
-  dst1 = src[4] * dst[1] + src[5] * dst[5] + src[6] * dst[9] + src[7] * dst[13];
-  dst2 = src[8] * dst[1] + src[9] * dst[5] + src[10]* dst[9] + src[11]* dst[13];
-  dst3 = src[12]* dst[1] + src[13]* dst[5] + src[14]* dst[9] + src[15]* dst[13];
-  dst[1] = dst0; dst[5] = dst1; dst[9] = dst2; dst[13]= dst3;
-
-  dst0 = src[0] * dst[2] + src[1] * dst[6] + src[2] * dst[10]+ src[3] * dst[14];
-  dst1 = src[4] * dst[2] + src[5] * dst[6] + src[6] * dst[10]+ src[7] * dst[14];
-  dst2 = src[8] * dst[2] + src[9] * dst[6] + src[10]* dst[10]+ src[11]* dst[14];
-  dst3 = src[12]* dst[2] + src[13]* dst[6] + src[14]* dst[10]+ src[15]* dst[14];
-  dst[2] = dst0; dst[6] = dst1; dst[10]= dst2; dst[14]= dst3;
-
-  dst0 = src[0] * dst[3] + src[1] * dst[7] + src[2] * dst[11]+ src[3] * dst[15];
-  dst1 = src[4] * dst[3] + src[5] * dst[7] + src[6] * dst[11]+ src[7] * dst[15];
-  dst2 = src[8] * dst[3] + src[9] * dst[7] + src[10]* dst[11]+ src[11]* dst[15];
-  dst3 = src[12]* dst[3] + src[13]* dst[7] + src[14]* dst[11]+ src[15]* dst[15];
-  dst[3] = dst0; dst[7] = dst1; dst[11]= dst2; dst[15]= dst3;
-
-#else
-
-  vec_t * p = dst;
-	for(int i=0;i<4;i++)
-	{
-		dst1 =  src[0]  * p[0];
-		dst1 += src[1]  * p[4];
-		dst1 += src[2]  * p[8];
-		dst1 += src[3]  * p[12];
-		dst2 =  src[4]  * p[0];
-		dst2 += src[5]  * p[4];
-		dst2 += src[6]  * p[8];
-		dst2 += src[7]  * p[12];
-		dst3 =  src[8]  * p[0];
-		dst3 += src[9]  * p[4];
-		dst3 += src[10] * p[8];
-		dst3 += src[11] * p[12];
-		dst4 =  src[12] * p[0];
-		dst4 += src[13] * p[4];
-		dst4 += src[14] * p[8];
-		dst4 += src[15] * p[12];
-
-		p[0] = dst1;
-		p[4] = dst2;
-		p[8] = dst3;
-		p[12] = dst4;
-    p++;
-	}
-
-#endif
-}
-
-/*
-A = B.A
-
-A0 = A0 * B0 + A1 * B4 + A2 * B8 + A3 * B12
-A1 = A0 * B1 + A1 * B5 + A2 * B9 + A3 * B13
-A2 = A0 * B2 + A1 * B6 + A2 * B10+ A3 * B14
-A3 = A0 * B3 + A1 * B7 + A2 * B11+ A3 * B15
-
-A4 = A4 * B0 + A5 * B4 + A6 * B8 + A7 * B12
-A5 = A4 * B1 + A5 * B5 + A6 * B9 + A7 * B13
-A6 = A4 * B2 + A5 * B6 + A6 * B10+ A7 * B14
-A7 = A4 * B3 + A5 * B7 + A6 * B11+ A7 * B15
-
-A8 = A8 * B0 + A9 * B4 + A10* B8 + A11* B12
-A9 = A8 * B1 + A9 * B5 + A10* B9 + A11* B13
-A10= A8 * B2 + A9 * B6 + A10* B10+ A11* B14
-A11= A8 * B3 + A9 * B7 + A10* B11+ A11* B15
-
-A12= A12* B0 + A13* B4 + A14* B8 + A15* B12
-A13= A12* B1 + A13* B5 + A14* B9 + A15* B13
-A14= A12* B2 + A13* B6 + A14* B10+ A15* B14
-A15= A12* B3 + A13* B7 + A14* B11+ A15* B15
-*/
-
-void m4x4_premultiply_by_m4x4(m4x4_t dst, const m4x4_t src)
-{
-	vec_t dst0, dst1, dst2, dst3;
-
-#if 1
-
-  dst0 = dst[0] * src[0] + dst[1] * src[4] + dst[2] * src[8] + dst[3] * src[12];
-  dst1 = dst[0] * src[1] + dst[1] * src[5] + dst[2] * src[9] + dst[3] * src[13];
-  dst2 = dst[0] * src[2] + dst[1] * src[6] + dst[2] * src[10]+ dst[3] * src[14];
-  dst3 = dst[0] * src[3] + dst[1] * src[7] + dst[2] * src[11]+ dst[3] * src[15];
-  dst[0] = dst0; dst[1] = dst1; dst[2] = dst2; dst[3]= dst3;
-
-  dst0 = dst[4] * src[0] + dst[5] * src[4] + dst[6] * src[8] + dst[7] * src[12];
-  dst1 = dst[4] * src[1] + dst[5] * src[5] + dst[6] * src[9] + dst[7] * src[13];
-  dst2 = dst[4] * src[2] + dst[5] * src[6] + dst[6] * src[10]+ dst[7] * src[14];
-  dst3 = dst[4] * src[3] + dst[5] * src[7] + dst[6] * src[11]+ dst[7] * src[15];
-  dst[4] = dst0; dst[5] = dst1; dst[6] = dst2; dst[7]= dst3;
-
-  dst0 = dst[8] * src[0] + dst[9] * src[4] + dst[10]* src[8] + dst[11]* src[12];
-  dst1 = dst[8] * src[1] + dst[9] * src[5] + dst[10]* src[9] + dst[11]* src[13];
-  dst2 = dst[8] * src[2] + dst[9] * src[6] + dst[10]* src[10]+ dst[11]* src[14];
-  dst3 = dst[8] * src[3] + dst[9] * src[7] + dst[10]* src[11]+ dst[11]* src[15];
-  dst[8] = dst0; dst[9] = dst1; dst[10] = dst2; dst[11]= dst3;
-
-  dst0 = dst[12]* src[0] + dst[13]* src[4] + dst[14]* src[8] + dst[15]* src[12];
-  dst1 = dst[12]* src[1] + dst[13]* src[5] + dst[14]* src[9] + dst[15]* src[13];
-  dst2 = dst[12]* src[2] + dst[13]* src[6] + dst[14]* src[10]+ dst[15]* src[14];
-  dst3 = dst[12]* src[3] + dst[13]* src[7] + dst[14]* src[11]+ dst[15]* src[15];
-  dst[12] = dst0; dst[13] = dst1; dst[14] = dst2; dst[15]= dst3;
-
-#else
-
-  vec_t* p = dst;
-	for(int i=0;i<4;i++)
-	{
-		dst1 =  src[0]  * p[0];
-		dst2 =  src[1]  * p[0];
-		dst3 =  src[2]  * p[0];
-		dst4 =  src[3]  * p[0];
-		dst1 += src[4]  * p[1];
-		dst2 += src[5]  * p[1];
-		dst3 += src[6]  * p[1];
-		dst4 += src[7]  * p[1];
-		dst1 += src[8]  * p[2];
-		dst2 += src[9]  * p[2];
-		dst4 += src[11] * p[2];
-		dst3 += src[10] * p[2];
-		dst1 += src[12] * p[3];
-		dst2 += src[13] * p[3];
-		dst3 += src[14] * p[3];
-		dst4 += src[15] * p[3];
-
-		*p++ = dst1;
-		*p++ = dst2;
-		*p++ = dst3;
-		*p++ = dst4;
-	}
-
-#endif
-}
-
-void m4x4_transform_point(const m4x4_t matrix, vec3_t point)
-{
-  float out1, out2, out3;
-
-	out1 =  matrix[0]  * point[0];
-	out2 =  matrix[1]  * point[0];
-	out3 =  matrix[2]  * point[0];
-	out1 += matrix[4]  * point[1];
-	out2 += matrix[5]  * point[1];
-	out3 += matrix[6]  * point[1];
-	out1 += matrix[8]  * point[2];
-	out2 += matrix[9]  * point[2];
-	out3 += matrix[10] * point[2];
-  out1 += matrix[12];
-  out2 += matrix[13];
-  out3 += matrix[14];
-
-	point[0] = out1;
-	point[1] = out2;
-	point[2] = out3;
-}
-
-void m4x4_transform_normal(const m4x4_t matrix, vec3_t normal)
-{
-  float out1, out2, out3;
-
-	out1 =  matrix[0]  * normal[0];
-	out2 =  matrix[1]  * normal[0];
-	out3 =  matrix[2]  * normal[0];
-	out1 += matrix[4]  * normal[1];
-	out2 += matrix[5]  * normal[1];
-	out3 += matrix[6]  * normal[1];
-	out1 += matrix[8]  * normal[2];
-	out2 += matrix[9]  * normal[2];
-	out3 += matrix[10] * normal[2];
-
-	normal[0] = out1;
-	normal[1] = out2;
-	normal[2] = out3;
-}
-
-void m4x4_transform_vec4(const m4x4_t matrix, vec4_t vector)
-{
-  float out1, out2, out3, out4;
-
-	out1 =  matrix[0]  * vector[0];
-	out2 =  matrix[1]  * vector[0];
-	out3 =  matrix[2]  * vector[0];
-	out4 =  matrix[3]  * vector[0];
-	out1 += matrix[4]  * vector[1];
-	out2 += matrix[5]  * vector[1];
-	out3 += matrix[6]  * vector[1];
-	out4 += matrix[7]  * vector[1];
-	out1 += matrix[8]  * vector[2];
-	out2 += matrix[9]  * vector[2];
-	out3 += matrix[10] * vector[2];
-	out4 += matrix[11] * vector[2];
-  out1 += matrix[12] * vector[3];
-  out2 += matrix[13] * vector[3];
-  out3 += matrix[14] * vector[3];
-  out4 += matrix[15] * vector[3];
-
-	vector[0] = out1;
-	vector[1] = out2;
-	vector[2] = out3;
-  vector[3] = out4;
-}
-
-void m4x4_transpose(m4x4_t matrix)
-{
-	int i, j;
-	float temp, *p1, *p2;
-
-  for (i=1; i<4; i++) {
-    for (j=0; j<i; j++) {
-      p1 = matrix+(j*4+i);
-      p2 = matrix+(i*4+j);
-      temp = *p1;
-      *p1=*p2;
-      *p2=temp;
-    }
-  }
-}
-
-void m4x4_orthogonal_invert(m4x4_t matrix)
-{
-  float temp;
-
-  temp = -matrix[3];
-  matrix[3] = matrix[12];
-  matrix[12] = temp;
-
-  temp = -matrix[7];
-  matrix[7] = matrix[13];
-  matrix[13] = temp;
-
-  temp = -matrix[11];
-  matrix[11] = matrix[14];
-  matrix[14] = temp;
-
-  /*
-  temp = matrix[1];
-  matrix[1] = matrix[4];
-  matrix[4] = temp;
-
-  temp = matrix[2];
-  matrix[2] = matrix[8];
-  matrix[8] = temp;
-
-  temp = matrix[6];
-  matrix[6] = matrix[9];
-  matrix[9] = temp;
-
-  matrix[3] = -matrix[3];
-  matrix[7] = -matrix[7];
-  matrix[11] = -matrix[11];
-  */
-}
-
-float m3_det( m3x3_t mat )
-{
-  float det;
-  
-  det = mat[0] * ( mat[4]*mat[8] - mat[7]*mat[5] )
-    - mat[1] * ( mat[3]*mat[8] - mat[6]*mat[5] )
-    + mat[2] * ( mat[3]*mat[7] - mat[6]*mat[4] );
-  
-  return( det );
-}
-
-/*
-void m3_inverse( m3x3_t mr, m3x3_t ma )
-{
-  float det = m3_det( ma );
-  
-  if ( fabs( det ) < 0.0005 )
-  {
-    m3_identity( ma );
-    return;
-  }
-  
-  mr[0] =    ma[4]*ma[8] - ma[5]*ma[7]   / det;
-  mr[1] = -( ma[1]*ma[8] - ma[7]*ma[2] ) / det;
-  mr[2] =    ma[1]*ma[5] - ma[4]*ma[2]   / det;
-  
-  mr[3] = -( ma[3]*ma[8] - ma[5]*ma[6] ) / det;
-  mr[4] =    ma[0]*ma[8] - ma[6]*ma[2]   / det;
-  mr[5] = -( ma[0]*ma[5] - ma[3]*ma[2] ) / det;
-  
-  mr[6] =    ma[3]*ma[7] - ma[6]*ma[4]   / det;
-  mr[7] = -( ma[0]*ma[7] - ma[6]*ma[1] ) / det;
-  mr[8] =    ma[0]*ma[4] - ma[1]*ma[3]   / det;
-}
-*/
-
-void m4_submat( m4x4_t mr, m3x3_t mb, int i, int j )
-{
-  int ti, tj, idst, jdst;
-  
-  for ( ti = 0; ti < 4; ti++ )
-  {
-    if ( ti < i )
-      idst = ti;
-    else
-      if ( ti > i )
-        idst = ti-1;
-      
-      for ( tj = 0; tj < 4; tj++ )
-      {
-        if ( tj < j )
-          jdst = tj;
-        else
-          if ( tj > j )
-            jdst = tj-1;
-          
-          if ( ti != i && tj != j )
-            mb[idst*3 + jdst] = mr[ti*4 + tj ];
-      }
-  }
-}
-
-float m4_det( m4x4_t mr )
-{
-  float  det, result = 0, i = 1;
-  m3x3_t msub3;
-  int     n;
-  
-  for ( n = 0; n < 4; n++, i *= -1 )
-  {
-    m4_submat( mr, msub3, 0, n );
-    
-    det     = m3_det( msub3 );
-    result += mr[n] * det * i;
-  }
-  
-  return result;
-}
-
-int m4x4_invert(m4x4_t matrix)
-{
-  float  mdet = m4_det( matrix );
-  m3x3_t mtemp;
-  int     i, j, sign;
-  m4x4_t m4x4_temp;
-  
-  if ( fabs( mdet ) < 0.0000000001 )	//% 0.0005
-    return 1;
-
-  memcpy(m4x4_temp, matrix, sizeof(m4x4_t));
-  
-  for ( i = 0; i < 4; i++ )
-    for ( j = 0; j < 4; j++ )
-    {
-      sign = 1 - ( (i +j) % 2 ) * 2;
-      
-      m4_submat( m4x4_temp, mtemp, i, j );
-      
-      matrix[i+j*4] = ( m3_det( mtemp ) * sign ) / mdet;
-    }
-    
-  return 0;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "mathlib.h"
+#include "memory.h"
+
+void m4x4_identity(m4x4_t matrix)
+{
+  matrix[1] = matrix[2] = matrix[3] =
+  matrix[4] = matrix[6] = matrix[7] =
+  matrix[8] = matrix[9] = matrix[11] =
+  matrix[12] = matrix[13] = matrix[14] = 0;
+
+  matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1;
+}
+
+void m4x4_translation_for_vec3(m4x4_t matrix, const vec3_t translation)
+{
+  matrix[1] = matrix[2] = matrix[3] =
+  matrix[4] = matrix[6] = matrix[7] =
+  matrix[8] = matrix[9] = matrix[11] = 0;
+
+  matrix[0] = matrix[5] = matrix[10] = matrix[15] = 1;
+
+  matrix[12] = translation[0];
+  matrix[13] = translation[1];
+  matrix[14] = translation[2];
+}
+
+void m4x4_rotation_for_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order)
+{
+  double cx, sx, cy, sy, cz, sz;
+    
+  cx = cos(DEG2RAD(euler[0]));
+  sx = sin(DEG2RAD(euler[0]));
+  cy = cos(DEG2RAD(euler[1]));
+  sy = sin(DEG2RAD(euler[1]));
+  cz = cos(DEG2RAD(euler[2]));
+  sz = sin(DEG2RAD(euler[2]));
+
+  switch(order)
+  {
+  case eXYZ:
+
+#if 1
+
+    {
+      matrix[0]  = (vec_t)(cy*cz);
+      matrix[1]  = (vec_t)(cy*sz);
+      matrix[2]  = (vec_t)-sy;
+      matrix[4]  = (vec_t)(sx*sy*cz + cx*-sz);
+      matrix[5]  = (vec_t)(sx*sy*sz + cx*cz);
+      matrix[6]  = (vec_t)(sx*cy);
+      matrix[8]  = (vec_t)(cx*sy*cz + sx*sz);
+      matrix[9]  = (vec_t)(cx*sy*sz + -sx*cz);
+      matrix[10] = (vec_t)(cx*cy);
+    }
+
+    matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
+    matrix[15] =  1;
+
+#else
+
+    m4x4_identity(matrix);
+    matrix[5] =(vec_t) cx; matrix[6] =(vec_t) sx;
+    matrix[9] =(vec_t)-sx; matrix[10]=(vec_t) cx;
+
+    {
+      m4x4_t temp;
+      m4x4_identity(temp);
+      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
+      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+      m4x4_identity(temp);
+      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
+      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+    }
+#endif
+
+    break;
+
+  case eYZX:
+    m4x4_identity(matrix);
+    matrix[0] =(vec_t) cy; matrix[2] =(vec_t)-sy;
+    matrix[8] =(vec_t) sy; matrix[10]=(vec_t) cy;
+
+    {
+      m4x4_t temp;
+      m4x4_identity(temp);
+      temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
+      temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+      m4x4_identity(temp);
+      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
+      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+    }
+    break;
+
+  case eZXY:
+    m4x4_identity(matrix);
+    matrix[0] =(vec_t) cz; matrix[1] =(vec_t) sz;
+    matrix[4] =(vec_t)-sz; matrix[5] =(vec_t) cz;
+
+    {
+      m4x4_t temp;
+      m4x4_identity(temp);
+      temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
+      temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+      m4x4_identity(temp);
+      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
+      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+    }
+    break;
+
+  case eXZY:
+    m4x4_identity(matrix);
+    matrix[5] =(vec_t) cx; matrix[6] =(vec_t) sx;
+    matrix[9] =(vec_t)-sx; matrix[10]=(vec_t) cx;
+
+    {
+      m4x4_t temp;
+      m4x4_identity(temp);
+      temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
+      temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+      m4x4_identity(temp);
+      temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
+      temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
+      m4x4_premultiply_by_m4x4(matrix, temp);
+    }
+    break;
+
+  case eYXZ:
+
+/* transposed
+|  cy.cz + sx.sy.-sz + -cx.sy.0   0.cz + cx.-sz + sx.0   sy.cz + -sx.cy.-sz + cx.cy.0 |
+|  cy.sz + sx.sy.cz + -cx.sy.0    0.sz + cx.cz + sx.0    sy.sz + -sx.cy.cz + cx.cy.0  |
+|  cy.0 + sx.sy.0 + -cx.sy.1      0.0 + cx.0 + sx.1      sy.0 + -sx.cy.0 + cx.cy.1    |
+*/
+
+#if 1
+
+  {
+    matrix[0]  = (vec_t)(cy*cz + sx*sy*-sz);
+    matrix[1]  = (vec_t)(cy*sz + sx*sy*cz);
+    matrix[2]  = (vec_t)(-cx*sy);
+    matrix[4]  = (vec_t)(cx*-sz);
+    matrix[5]  = (vec_t)(cx*cz);
+    matrix[6]  = (vec_t)(sx);
+    matrix[8]  = (vec_t)(sy*cz + -sx*cy*-sz);
+    matrix[9]  = (vec_t)(sy*sz + -sx*cy*cz);
+    matrix[10] = (vec_t)(cx*cy);
+  }
+
+  matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
+  matrix[15] =  1;
+
+#else
+
+  m4x4_identity(matrix);
+  matrix[0] =(vec_t) cy; matrix[2] =(vec_t)-sy;
+  matrix[8] =(vec_t) sy; matrix[10]=(vec_t) cy;
+
+  {
+    m4x4_t temp;
+    m4x4_identity(temp);
+    temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
+    temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
+    m4x4_premultiply_by_m4x4(matrix, temp);
+    m4x4_identity(temp);
+    temp[0] =(vec_t) cz; temp[1] =(vec_t) sz;
+    temp[4] =(vec_t)-sz; temp[5] =(vec_t) cz;
+    m4x4_premultiply_by_m4x4(matrix, temp);
+  }
+#endif
+  break;
+
+  case eZYX:
+#if 1
+
+  {
+    matrix[0]  = (vec_t)(cy*cz);
+    matrix[4]  = (vec_t)(cy*-sz);
+    matrix[8]  = (vec_t)sy;
+    matrix[1]  = (vec_t)(sx*sy*cz + cx*sz);
+    matrix[5]  = (vec_t)(sx*sy*-sz + cx*cz);
+    matrix[9]  = (vec_t)(-sx*cy);
+    matrix[2]  = (vec_t)(cx*-sy*cz + sx*sz);
+    matrix[6]  = (vec_t)(cx*-sy*-sz + sx*cz);
+    matrix[10] = (vec_t)(cx*cy);
+  }
+
+  matrix[12]  =  matrix[13] = matrix[14] = matrix[3] = matrix[7] = matrix[11] = 0;
+  matrix[15] =  1;
+
+#else
+
+  m4x4_identity(matrix);
+  matrix[0] =(vec_t) cz; matrix[1] =(vec_t) sz;
+  matrix[4] =(vec_t)-sz; matrix[5] =(vec_t) cz;
+  {
+    m4x4_t temp;
+    m4x4_identity(temp);
+    temp[0] =(vec_t) cy; temp[2] =(vec_t)-sy;
+    temp[8] =(vec_t) sy; temp[10]=(vec_t) cy;
+    m4x4_premultiply_by_m4x4(matrix, temp);
+    m4x4_identity(temp);
+    temp[5] =(vec_t) cx; temp[6] =(vec_t) sx;
+    temp[9] =(vec_t)-sx; temp[10]=(vec_t) cx;
+    m4x4_premultiply_by_m4x4(matrix, temp);
+  }
+
+#endif
+  break;
+
+  }
+
+}
+
+void m4x4_scale_for_vec3(m4x4_t matrix, const vec3_t scale)
+{
+  matrix[1] = matrix[2] = matrix[3] =
+  matrix[4] = matrix[6] = matrix[7] =
+  matrix[8] = matrix[9] = matrix[11] =
+  matrix[12] = matrix[13] = matrix[14] = 0;
+
+  matrix[15] = 1;
+
+  matrix[0] = scale[0];
+  matrix[5] = scale[1];
+  matrix[10] = scale[2];
+}
+
+void m4x4_rotation_for_quat(m4x4_t matrix, const vec4_t rotation)
+{
+  float xx,xy,xz,xw,yy,yz,yw,zz,zw;
+
+  xx      = rotation[0] * rotation[0];
+  xy      = rotation[0] * rotation[1];
+  xz      = rotation[0] * rotation[2];
+  xw      = rotation[0] * rotation[3];
+
+  yy      = rotation[1] * rotation[1];
+  yz      = rotation[1] * rotation[2];
+  yw      = rotation[1] * rotation[3];
+
+  zz      = rotation[2] * rotation[2];
+  zw      = rotation[2] * rotation[3];
+
+  matrix[0]  = 1 - 2 * ( yy + zz );
+  matrix[4]  =     2 * ( xy - zw );
+  matrix[8]  =     2 * ( xz + yw );
+
+  matrix[1]  =     2 * ( xy + zw );
+  matrix[5]  = 1 - 2 * ( xx + zz );
+  matrix[9]  =     2 * ( yz - xw );
+
+  matrix[2]  =     2 * ( xz - yw );
+  matrix[6]  =     2 * ( yz + xw );
+  matrix[10] = 1 - 2 * ( xx + yy );
+
+  matrix[3]  = matrix[7] = matrix[11] = matrix[12] = matrix[13] = matrix[14] = 0;
+  matrix[15] = 1;
+}
+
+void m4x4_rotation_for_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle)
+{
+  vec4_t rotation;
+  angle *= 0.5;
+
+  rotation[3] = (float)sin((float)(angle));
+
+  rotation[0]    = axis[0] * rotation[3];
+  rotation[1]    = axis[1] * rotation[3];
+  rotation[2]    = axis[2] * rotation[3];
+  rotation[3]    = (float)cos((float)(angle));
+
+  m4x4_rotation_for_quat(matrix, rotation);
+}
+
+void m4x4_translate_by_vec3(m4x4_t matrix, const vec3_t translation)
+{
+  m4x4_t temp;
+  m4x4_translation_for_vec3(temp, translation);
+  m4x4_multiply_by_m4x4(matrix, temp);
+}
+
+void m4x4_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order)
+{
+  m4x4_t temp;
+  m4x4_rotation_for_vec3(temp, euler, order);
+  m4x4_multiply_by_m4x4(matrix, temp);
+}
+
+void m4x4_scale_by_vec3(m4x4_t matrix, const vec3_t scale)
+{
+  m4x4_t temp;
+  m4x4_scale_for_vec3(temp, scale);
+  m4x4_multiply_by_m4x4(matrix, temp);
+}
+
+void m4x4_rotate_by_quat(m4x4_t matrix, const vec4_t rotation)
+{
+  m4x4_t temp;
+  m4x4_rotation_for_quat(temp, rotation);
+  m4x4_multiply_by_m4x4(matrix, temp);
+}
+
+void m4x4_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle)
+{
+  m4x4_t temp;
+  m4x4_rotation_for_axisangle(temp, axis, angle);
+  m4x4_multiply_by_m4x4(matrix, temp);
+}
+
+void m4x4_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale)
+{
+  m4x4_translate_by_vec3(matrix, translation);
+  m4x4_rotate_by_vec3(matrix, euler, order);
+  m4x4_scale_by_vec3(matrix, scale);
+}
+
+void m4x4_pivoted_rotate_by_vec3(m4x4_t matrix, const vec3_t euler, eulerOrder_t order, const vec3_t pivotpoint)
+{
+  vec3_t vec3_temp;
+  VectorNegative(pivotpoint, vec3_temp);
+
+  m4x4_translate_by_vec3(matrix, pivotpoint);
+  m4x4_rotate_by_vec3(matrix, euler, order);
+  m4x4_translate_by_vec3(matrix, vec3_temp);
+}
+
+void m4x4_pivoted_scale_by_vec3(m4x4_t matrix, const vec3_t scale, const vec3_t pivotpoint)
+{
+  vec3_t vec3_temp;
+  VectorNegative(pivotpoint, vec3_temp);
+
+  m4x4_translate_by_vec3(matrix, pivotpoint);
+  m4x4_scale_by_vec3(matrix, scale);
+  m4x4_translate_by_vec3(matrix, vec3_temp);
+}
+
+void m4x4_pivoted_transform_by_vec3(m4x4_t matrix, const vec3_t translation, const vec3_t euler, eulerOrder_t order, const vec3_t scale, const vec3_t pivotpoint)
+{
+  vec3_t vec3_temp;
+
+  VectorAdd(pivotpoint, translation, vec3_temp);
+  m4x4_translate_by_vec3(matrix, vec3_temp);
+  m4x4_rotate_by_vec3(matrix, euler, order);
+  m4x4_scale_by_vec3(matrix, scale);
+  VectorNegative(pivotpoint, vec3_temp);
+  m4x4_translate_by_vec3(matrix, vec3_temp);
+}
+
+void m4x4_pivoted_rotate_by_quat(m4x4_t matrix, const vec4_t rotation, const vec3_t pivotpoint)
+{
+  vec3_t vec3_temp;
+  VectorNegative(pivotpoint, vec3_temp);
+
+  m4x4_translate_by_vec3(matrix, pivotpoint);
+  m4x4_rotate_by_quat(matrix, rotation);
+  m4x4_translate_by_vec3(matrix, vec3_temp);
+}
+
+void m4x4_pivoted_rotate_by_axisangle(m4x4_t matrix, const vec3_t axis, vec_t angle, const vec3_t pivotpoint)
+{
+  vec3_t vec3_temp;
+  VectorNegative(pivotpoint, vec3_temp);
+
+  m4x4_translate_by_vec3(matrix, pivotpoint);
+  m4x4_rotate_by_axisangle(matrix, axis, angle);
+  m4x4_translate_by_vec3(matrix, vec3_temp);
+}
+
+
+/*
+A = A.B
+
+A0 = B0 * A0 + B1 * A4 + B2 * A8 + B3 * A12
+A4 = B4 * A0 + B5 * A4 + B6 * A8 + B7 * A12
+A8 = B8 * A0 + B9 * A4 + B10* A8 + B11* A12
+A12= B12* A0 + B13* A4 + B14* A8 + B15* A12
+
+A1 = B0 * A1 + B1 * A5 + B2 * A9 + B3 * A13
+A5 = B4 * A1 + B5 * A5 + B6 * A9 + B7 * A13
+A9 = B8 * A1 + B9 * A5 + B10* A9 + B11* A13
+A13= B12* A1 + B13* A5 + B14* A9 + B15* A13
+
+A2 = B0 * A2 + B1 * A6 + B2 * A10+ B3 * A14
+A6 = B4 * A2 + B5 * A6 + B6 * A10+ B7 * A14
+A10= B8 * A2 + B9 * A6 + B10* A10+ B11* A14
+A14= B12* A2 + B13* A6 + B14* A10+ B15* A14
+
+A3 = B0 * A3 + B1 * A7 + B2 * A11+ B3 * A15
+A7 = B4 * A3 + B5 * A7 + B6 * A11+ B7 * A15
+A11= B8 * A3 + B9 * A7 + B10* A11+ B11* A15
+A15= B12* A3 + B13* A7 + B14* A11+ B15* A15
+*/
+
+void m4x4_multiply_by_m4x4(m4x4_t dst, const m4x4_t src)
+{
+	vec_t dst0, dst1, dst2, dst3;
+
+#if 1
+
+  dst0 = src[0] * dst[0] + src[1] * dst[4] + src[2] * dst[8] + src[3] * dst[12];
+  dst1 = src[4] * dst[0] + src[5] * dst[4] + src[6] * dst[8] + src[7] * dst[12];
+  dst2 = src[8] * dst[0] + src[9] * dst[4] + src[10]* dst[8] + src[11]* dst[12];
+  dst3 = src[12]* dst[0] + src[13]* dst[4] + src[14]* dst[8] + src[15]* dst[12];
+  dst[0] = dst0; dst[4] = dst1; dst[8] = dst2; dst[12]= dst3;
+
+  dst0 = src[0] * dst[1] + src[1] * dst[5] + src[2] * dst[9] + src[3] * dst[13];
+  dst1 = src[4] * dst[1] + src[5] * dst[5] + src[6] * dst[9] + src[7] * dst[13];
+  dst2 = src[8] * dst[1] + src[9] * dst[5] + src[10]* dst[9] + src[11]* dst[13];
+  dst3 = src[12]* dst[1] + src[13]* dst[5] + src[14]* dst[9] + src[15]* dst[13];
+  dst[1] = dst0; dst[5] = dst1; dst[9] = dst2; dst[13]= dst3;
+
+  dst0 = src[0] * dst[2] + src[1] * dst[6] + src[2] * dst[10]+ src[3] * dst[14];
+  dst1 = src[4] * dst[2] + src[5] * dst[6] + src[6] * dst[10]+ src[7] * dst[14];
+  dst2 = src[8] * dst[2] + src[9] * dst[6] + src[10]* dst[10]+ src[11]* dst[14];
+  dst3 = src[12]* dst[2] + src[13]* dst[6] + src[14]* dst[10]+ src[15]* dst[14];
+  dst[2] = dst0; dst[6] = dst1; dst[10]= dst2; dst[14]= dst3;
+
+  dst0 = src[0] * dst[3] + src[1] * dst[7] + src[2] * dst[11]+ src[3] * dst[15];
+  dst1 = src[4] * dst[3] + src[5] * dst[7] + src[6] * dst[11]+ src[7] * dst[15];
+  dst2 = src[8] * dst[3] + src[9] * dst[7] + src[10]* dst[11]+ src[11]* dst[15];
+  dst3 = src[12]* dst[3] + src[13]* dst[7] + src[14]* dst[11]+ src[15]* dst[15];
+  dst[3] = dst0; dst[7] = dst1; dst[11]= dst2; dst[15]= dst3;
+
+#else
+
+  vec_t * p = dst;
+	for(int i=0;i<4;i++)
+	{
+		dst1 =  src[0]  * p[0];
+		dst1 += src[1]  * p[4];
+		dst1 += src[2]  * p[8];
+		dst1 += src[3]  * p[12];
+		dst2 =  src[4]  * p[0];
+		dst2 += src[5]  * p[4];
+		dst2 += src[6]  * p[8];
+		dst2 += src[7]  * p[12];
+		dst3 =  src[8]  * p[0];
+		dst3 += src[9]  * p[4];
+		dst3 += src[10] * p[8];
+		dst3 += src[11] * p[12];
+		dst4 =  src[12] * p[0];
+		dst4 += src[13] * p[4];
+		dst4 += src[14] * p[8];
+		dst4 += src[15] * p[12];
+
+		p[0] = dst1;
+		p[4] = dst2;
+		p[8] = dst3;
+		p[12] = dst4;
+    p++;
+	}
+
+#endif
+}
+
+/*
+A = B.A
+
+A0 = A0 * B0 + A1 * B4 + A2 * B8 + A3 * B12
+A1 = A0 * B1 + A1 * B5 + A2 * B9 + A3 * B13
+A2 = A0 * B2 + A1 * B6 + A2 * B10+ A3 * B14
+A3 = A0 * B3 + A1 * B7 + A2 * B11+ A3 * B15
+
+A4 = A4 * B0 + A5 * B4 + A6 * B8 + A7 * B12
+A5 = A4 * B1 + A5 * B5 + A6 * B9 + A7 * B13
+A6 = A4 * B2 + A5 * B6 + A6 * B10+ A7 * B14
+A7 = A4 * B3 + A5 * B7 + A6 * B11+ A7 * B15
+
+A8 = A8 * B0 + A9 * B4 + A10* B8 + A11* B12
+A9 = A8 * B1 + A9 * B5 + A10* B9 + A11* B13
+A10= A8 * B2 + A9 * B6 + A10* B10+ A11* B14
+A11= A8 * B3 + A9 * B7 + A10* B11+ A11* B15
+
+A12= A12* B0 + A13* B4 + A14* B8 + A15* B12
+A13= A12* B1 + A13* B5 + A14* B9 + A15* B13
+A14= A12* B2 + A13* B6 + A14* B10+ A15* B14
+A15= A12* B3 + A13* B7 + A14* B11+ A15* B15
+*/
+
+void m4x4_premultiply_by_m4x4(m4x4_t dst, const m4x4_t src)
+{
+	vec_t dst0, dst1, dst2, dst3;
+
+#if 1
+
+  dst0 = dst[0] * src[0] + dst[1] * src[4] + dst[2] * src[8] + dst[3] * src[12];
+  dst1 = dst[0] * src[1] + dst[1] * src[5] + dst[2] * src[9] + dst[3] * src[13];
+  dst2 = dst[0] * src[2] + dst[1] * src[6] + dst[2] * src[10]+ dst[3] * src[14];
+  dst3 = dst[0] * src[3] + dst[1] * src[7] + dst[2] * src[11]+ dst[3] * src[15];
+  dst[0] = dst0; dst[1] = dst1; dst[2] = dst2; dst[3]= dst3;
+
+  dst0 = dst[4] * src[0] + dst[5] * src[4] + dst[6] * src[8] + dst[7] * src[12];
+  dst1 = dst[4] * src[1] + dst[5] * src[5] + dst[6] * src[9] + dst[7] * src[13];
+  dst2 = dst[4] * src[2] + dst[5] * src[6] + dst[6] * src[10]+ dst[7] * src[14];
+  dst3 = dst[4] * src[3] + dst[5] * src[7] + dst[6] * src[11]+ dst[7] * src[15];
+  dst[4] = dst0; dst[5] = dst1; dst[6] = dst2; dst[7]= dst3;
+
+  dst0 = dst[8] * src[0] + dst[9] * src[4] + dst[10]* src[8] + dst[11]* src[12];
+  dst1 = dst[8] * src[1] + dst[9] * src[5] + dst[10]* src[9] + dst[11]* src[13];
+  dst2 = dst[8] * src[2] + dst[9] * src[6] + dst[10]* src[10]+ dst[11]* src[14];
+  dst3 = dst[8] * src[3] + dst[9] * src[7] + dst[10]* src[11]+ dst[11]* src[15];
+  dst[8] = dst0; dst[9] = dst1; dst[10] = dst2; dst[11]= dst3;
+
+  dst0 = dst[12]* src[0] + dst[13]* src[4] + dst[14]* src[8] + dst[15]* src[12];
+  dst1 = dst[12]* src[1] + dst[13]* src[5] + dst[14]* src[9] + dst[15]* src[13];
+  dst2 = dst[12]* src[2] + dst[13]* src[6] + dst[14]* src[10]+ dst[15]* src[14];
+  dst3 = dst[12]* src[3] + dst[13]* src[7] + dst[14]* src[11]+ dst[15]* src[15];
+  dst[12] = dst0; dst[13] = dst1; dst[14] = dst2; dst[15]= dst3;
+
+#else
+
+  vec_t* p = dst;
+	for(int i=0;i<4;i++)
+	{
+		dst1 =  src[0]  * p[0];
+		dst2 =  src[1]  * p[0];
+		dst3 =  src[2]  * p[0];
+		dst4 =  src[3]  * p[0];
+		dst1 += src[4]  * p[1];
+		dst2 += src[5]  * p[1];
+		dst3 += src[6]  * p[1];
+		dst4 += src[7]  * p[1];
+		dst1 += src[8]  * p[2];
+		dst2 += src[9]  * p[2];
+		dst4 += src[11] * p[2];
+		dst3 += src[10] * p[2];
+		dst1 += src[12] * p[3];
+		dst2 += src[13] * p[3];
+		dst3 += src[14] * p[3];
+		dst4 += src[15] * p[3];
+
+		*p++ = dst1;
+		*p++ = dst2;
+		*p++ = dst3;
+		*p++ = dst4;
+	}
+
+#endif
+}
+
+void m4x4_transform_point(const m4x4_t matrix, vec3_t point)
+{
+  float out1, out2, out3;
+
+	out1 =  matrix[0]  * point[0];
+	out2 =  matrix[1]  * point[0];
+	out3 =  matrix[2]  * point[0];
+	out1 += matrix[4]  * point[1];
+	out2 += matrix[5]  * point[1];
+	out3 += matrix[6]  * point[1];
+	out1 += matrix[8]  * point[2];
+	out2 += matrix[9]  * point[2];
+	out3 += matrix[10] * point[2];
+  out1 += matrix[12];
+  out2 += matrix[13];
+  out3 += matrix[14];
+
+	point[0] = out1;
+	point[1] = out2;
+	point[2] = out3;
+}
+
+void m4x4_transform_normal(const m4x4_t matrix, vec3_t normal)
+{
+  float out1, out2, out3;
+
+	out1 =  matrix[0]  * normal[0];
+	out2 =  matrix[1]  * normal[0];
+	out3 =  matrix[2]  * normal[0];
+	out1 += matrix[4]  * normal[1];
+	out2 += matrix[5]  * normal[1];
+	out3 += matrix[6]  * normal[1];
+	out1 += matrix[8]  * normal[2];
+	out2 += matrix[9]  * normal[2];
+	out3 += matrix[10] * normal[2];
+
+	normal[0] = out1;
+	normal[1] = out2;
+	normal[2] = out3;
+}
+
+void m4x4_transform_vec4(const m4x4_t matrix, vec4_t vector)
+{
+  float out1, out2, out3, out4;
+
+	out1 =  matrix[0]  * vector[0];
+	out2 =  matrix[1]  * vector[0];
+	out3 =  matrix[2]  * vector[0];
+	out4 =  matrix[3]  * vector[0];
+	out1 += matrix[4]  * vector[1];
+	out2 += matrix[5]  * vector[1];
+	out3 += matrix[6]  * vector[1];
+	out4 += matrix[7]  * vector[1];
+	out1 += matrix[8]  * vector[2];
+	out2 += matrix[9]  * vector[2];
+	out3 += matrix[10] * vector[2];
+	out4 += matrix[11] * vector[2];
+  out1 += matrix[12] * vector[3];
+  out2 += matrix[13] * vector[3];
+  out3 += matrix[14] * vector[3];
+  out4 += matrix[15] * vector[3];
+
+	vector[0] = out1;
+	vector[1] = out2;
+	vector[2] = out3;
+  vector[3] = out4;
+}
+
+void m4x4_transpose(m4x4_t matrix)
+{
+	int i, j;
+	float temp, *p1, *p2;
+
+  for (i=1; i<4; i++) {
+    for (j=0; j<i; j++) {
+      p1 = matrix+(j*4+i);
+      p2 = matrix+(i*4+j);
+      temp = *p1;
+      *p1=*p2;
+      *p2=temp;
+    }
+  }
+}
+
+void m4x4_orthogonal_invert(m4x4_t matrix)
+{
+  float temp;
+
+  temp = -matrix[3];
+  matrix[3] = matrix[12];
+  matrix[12] = temp;
+
+  temp = -matrix[7];
+  matrix[7] = matrix[13];
+  matrix[13] = temp;
+
+  temp = -matrix[11];
+  matrix[11] = matrix[14];
+  matrix[14] = temp;
+
+  /*
+  temp = matrix[1];
+  matrix[1] = matrix[4];
+  matrix[4] = temp;
+
+  temp = matrix[2];
+  matrix[2] = matrix[8];
+  matrix[8] = temp;
+
+  temp = matrix[6];
+  matrix[6] = matrix[9];
+  matrix[9] = temp;
+
+  matrix[3] = -matrix[3];
+  matrix[7] = -matrix[7];
+  matrix[11] = -matrix[11];
+  */
+}
+
+float m3_det( m3x3_t mat )
+{
+  float det;
+  
+  det = mat[0] * ( mat[4]*mat[8] - mat[7]*mat[5] )
+    - mat[1] * ( mat[3]*mat[8] - mat[6]*mat[5] )
+    + mat[2] * ( mat[3]*mat[7] - mat[6]*mat[4] );
+  
+  return( det );
+}
+
+/*
+void m3_inverse( m3x3_t mr, m3x3_t ma )
+{
+  float det = m3_det( ma );
+  
+  if ( fabs( det ) < 0.0005 )
+  {
+    m3_identity( ma );
+    return;
+  }
+  
+  mr[0] =    ma[4]*ma[8] - ma[5]*ma[7]   / det;
+  mr[1] = -( ma[1]*ma[8] - ma[7]*ma[2] ) / det;
+  mr[2] =    ma[1]*ma[5] - ma[4]*ma[2]   / det;
+  
+  mr[3] = -( ma[3]*ma[8] - ma[5]*ma[6] ) / det;
+  mr[4] =    ma[0]*ma[8] - ma[6]*ma[2]   / det;
+  mr[5] = -( ma[0]*ma[5] - ma[3]*ma[2] ) / det;
+  
+  mr[6] =    ma[3]*ma[7] - ma[6]*ma[4]   / det;
+  mr[7] = -( ma[0]*ma[7] - ma[6]*ma[1] ) / det;
+  mr[8] =    ma[0]*ma[4] - ma[1]*ma[3]   / det;
+}
+*/
+
+void m4_submat( m4x4_t mr, m3x3_t mb, int i, int j )
+{
+  int ti, tj, idst, jdst;
+  
+  for ( ti = 0; ti < 4; ti++ )
+  {
+    if ( ti < i )
+      idst = ti;
+    else
+      if ( ti > i )
+        idst = ti-1;
+      
+      for ( tj = 0; tj < 4; tj++ )
+      {
+        if ( tj < j )
+          jdst = tj;
+        else
+          if ( tj > j )
+            jdst = tj-1;
+          
+          if ( ti != i && tj != j )
+            mb[idst*3 + jdst] = mr[ti*4 + tj ];
+      }
+  }
+}
+
+float m4_det( m4x4_t mr )
+{
+  float  det, result = 0, i = 1;
+  m3x3_t msub3;
+  int     n;
+  
+  for ( n = 0; n < 4; n++, i *= -1 )
+  {
+    m4_submat( mr, msub3, 0, n );
+    
+    det     = m3_det( msub3 );
+    result += mr[n] * det * i;
+  }
+  
+  return result;
+}
+
+int m4x4_invert(m4x4_t matrix)
+{
+  float  mdet = m4_det( matrix );
+  m3x3_t mtemp;
+  int     i, j, sign;
+  m4x4_t m4x4_temp;
+  
+  if ( fabs( mdet ) < 0.0000000001 )	//% 0.0005
+    return 1;
+
+  memcpy(m4x4_temp, matrix, sizeof(m4x4_t));
+  
+  for ( i = 0; i < 4; i++ )
+    for ( j = 0; j < 4; j++ )
+    {
+      sign = 1 - ( (i +j) % 2 ) * 2;
+      
+      m4_submat( m4x4_temp, mtemp, i, j );
+      
+      matrix[i+j*4] = ( m3_det( mtemp ) * sign ) / mdet;
+    }
+    
+  return 0;
+}
diff --git a/libs/mathlib/mathlib.c b/libs/mathlib/mathlib.c
index 0c26a963..b9b7b869 100644
--- a/libs/mathlib/mathlib.c
+++ b/libs/mathlib/mathlib.c
@@ -1,593 +1,593 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// mathlib.c -- math primitives
-#include "mathlib.h"
-// we use memcpy and memset
-#include <memory.h>
-
-vec3_t vec3_origin = {0.0f,0.0f,0.0f};
-
-/*
-================
-MakeNormalVectors
-
-Given a normalized forward vector, create two
-other perpendicular vectors
-================
-*/
-void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
-{
-	float		d;
-
-	// this rotate and negate guarantees a vector
-	// not colinear with the original
-	right[1] = -forward[0];
-	right[2] = forward[1];
-	right[0] = forward[2];
-
-	d = DotProduct (right, forward);
-	VectorMA (right, -d, forward, right);
-	VectorNormalize (right, right);
-	CrossProduct (right, forward, up);
-}
-
-vec_t VectorLength(vec3_t v)
-{
-	int		i;
-	float	length;
-	
-	length = 0.0f;
-	for (i=0 ; i< 3 ; i++)
-		length += v[i]*v[i];
-	length = (float)sqrt (length);
-
-	return length;
-}
-
-qboolean VectorCompare (vec3_t v1, vec3_t v2)
-{
-	int		i;
-	
-	for (i=0 ; i<3 ; i++)
-		if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
-			return qfalse;
-			
-	return qtrue;
-}
-
-/*
-// FIXME TTimo this implementation has to be particular to radiant
-//   through another name I'd say
-vec_t Q_rint (vec_t in)
-{
-  if (g_PrefsDlg.m_bNoClamp)
-    return in;
-  else
-    return (float)floor (in + 0.5);
-}
-*/
-
-void VectorMA( const vec3_t va, vec_t scale, const vec3_t vb, vec3_t vc )
-{
-	vc[0] = va[0] + scale*vb[0];
-	vc[1] = va[1] + scale*vb[1];
-	vc[2] = va[2] + scale*vb[2];
-}
-
-void _CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
-{
-	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
-	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
-	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
-}
-
-vec_t _DotProduct (vec3_t v1, vec3_t v2)
-{
-	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
-}
-
-void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
-{
-	out[0] = va[0]-vb[0];
-	out[1] = va[1]-vb[1];
-	out[2] = va[2]-vb[2];
-}
-
-void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
-{
-	out[0] = va[0]+vb[0];
-	out[1] = va[1]+vb[1];
-	out[2] = va[2]+vb[2];
-}
-
-void _VectorCopy (vec3_t in, vec3_t out)
-{
-	out[0] = in[0];
-	out[1] = in[1];
-	out[2] = in[2];
-}
-
-vec_t VectorNormalize( const vec3_t in, vec3_t out ) {
-	vec_t	length, ilength;
-
-	length = (vec_t)sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
-	if (length == 0)
-	{
-		VectorClear (out);
-		return 0;
-	}
-
-	ilength = 1.0f/length;
-	out[0] = in[0]*ilength;
-	out[1] = in[1]*ilength;
-	out[2] = in[2]*ilength;
-
-	return length;
-}
-
-vec_t ColorNormalize( const vec3_t in, vec3_t out ) {
-	float	max, scale;
-
-	max = in[0];
-	if (in[1] > max)
-		max = in[1];
-	if (in[2] > max)
-		max = in[2];
-
-	if (max == 0) {
-		out[0] = out[1] = out[2] = 1.0;
-		return 0;
-	}
-
-	scale = 1.0f / max;
-
-	VectorScale (in, scale, out);
-
-	return max;
-}
-
-void VectorInverse (vec3_t v)
-{
-	v[0] = -v[0];
-	v[1] = -v[1];
-	v[2] = -v[2];
-}
-
-/*
-void VectorScale (vec3_t v, vec_t scale, vec3_t out)
-{
-	out[0] = v[0] * scale;
-	out[1] = v[1] * scale;
-	out[2] = v[2] * scale;
-}
-*/
-
-void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t out)
-{
-  vec3_t vWork, va;
-  int nIndex[3][2];
-  int i;
-
-  VectorCopy(vIn, va);
-  VectorCopy(va, vWork);
-  nIndex[0][0] = 1; nIndex[0][1] = 2;
-  nIndex[1][0] = 2; nIndex[1][1] = 0;
-  nIndex[2][0] = 0; nIndex[2][1] = 1;
-
-  for (i = 0; i < 3; i++)
-  {
-    if (vRotation[i] != 0)
-    {
-      float dAngle = vRotation[i] * Q_PI / 180.0f;
-	    float c = (vec_t)cos(dAngle);
-      float s = (vec_t)sin(dAngle);
-      vWork[nIndex[i][0]] = va[nIndex[i][0]] * c - va[nIndex[i][1]] * s;
-      vWork[nIndex[i][1]] = va[nIndex[i][0]] * s + va[nIndex[i][1]] * c;
-    }
-    VectorCopy(vWork, va);
-  }
-  VectorCopy(vWork, out);
-}
-
-void VectorRotateOrigin (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out)
-{
-  vec3_t vTemp, vTemp2;
-
-  VectorSubtract(vIn, vOrigin, vTemp);
-  VectorRotate(vTemp, vRotation, vTemp2);
-  VectorAdd(vTemp2, vOrigin, out);
-}
-
-void VectorPolar(vec3_t v, float radius, float theta, float phi)
-{
- 	v[0]=(float)(radius * cos(theta) * cos(phi));
-	v[1]=(float)(radius * sin(theta) * cos(phi));
-	v[2]=(float)(radius * sin(phi));
-}
-
-void VectorSnap(vec3_t v)
-{
-  int i;
-  for (i = 0; i < 3; i++)
-  {
-    v[i] = (vec_t)floor (v[i] + 0.5);
-  }
-}
-
-void VectorISnap(vec3_t point, int snap)
-{
-  int i;
-	for (i = 0 ;i < 3 ; i++)
-	{
-		point[i] = (vec_t)floor (point[i] / snap + 0.5) * snap;
-	}
-}
-
-void VectorFSnap(vec3_t point, float snap)
-{
-  int i;
-	for (i = 0 ;i < 3 ; i++)
-	{
-		point[i] = (vec_t)floor (point[i] / snap + 0.5) * snap;
-	}
-}
-
-void _Vector5Add (vec5_t va, vec5_t vb, vec5_t out)
-{
-	out[0] = va[0]+vb[0];
-	out[1] = va[1]+vb[1];
-	out[2] = va[2]+vb[2];
-	out[3] = va[3]+vb[3];
-	out[4] = va[4]+vb[4];
-}
-
-void _Vector5Scale (vec5_t v, vec_t scale, vec5_t out)
-{
-	out[0] = v[0] * scale;
-	out[1] = v[1] * scale;
-	out[2] = v[2] * scale;
-	out[3] = v[3] * scale;
-	out[4] = v[4] * scale;
-}
-
-void _Vector53Copy (vec5_t in, vec3_t out)
-{
-	out[0] = in[0];
-	out[1] = in[1];
-	out[2] = in[2];
-}
-
-// NOTE: added these from Ritual's Q3Radiant
-void ClearBounds (vec3_t mins, vec3_t maxs)
-{
-	mins[0] = mins[1] = mins[2] = 99999;
-	maxs[0] = maxs[1] = maxs[2] = -99999;
-}
-
-void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
-{
-	int		i;
-	vec_t	val;
-	
-	for (i=0 ; i<3 ; i++)
-	{
-		val = v[i];
-		if (val < mins[i])
-			mins[i] = val;
-		if (val > maxs[i])
-			maxs[i] = val;
-	}
-}
-
-#define	PITCH				0		// up / down
-#define	YAW					1		// left / right
-#define	ROLL				2		// fall over
-#ifndef M_PI
-#define M_PI		3.14159265358979323846f	// matches value in gcc v2 math.h
-#endif
-
-void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
-{
-	float		angle;
-	static float		sr, sp, sy, cr, cp, cy;
-	// static to help MS compiler fp bugs
-	
-	angle = angles[YAW] * (M_PI*2.0f / 360.0f);
-	sy = (vec_t)sin(angle);
-	cy = (vec_t)cos(angle);
-	angle = angles[PITCH] * (M_PI*2.0f / 360.0f);
-	sp = (vec_t)sin(angle);
-	cp = (vec_t)cos(angle);
-	angle = angles[ROLL] * (M_PI*2.0f / 360.0f);
-	sr = (vec_t)sin(angle);
-	cr = (vec_t)cos(angle);
-	
-	if (forward)
-	{
-		forward[0] = cp*cy;
-		forward[1] = cp*sy;
-		forward[2] = -sp;
-	}
-	if (right)
-	{
-		right[0] = -sr*sp*cy+cr*sy;
-		right[1] = -sr*sp*sy-cr*cy;
-		right[2] = -sr*cp;
-	}
-	if (up)
-	{
-		up[0] = cr*sp*cy+sr*sy;
-		up[1] = cr*sp*sy-sr*cy;
-		up[2] = cr*cp;
-	}
-}
-
-void VectorToAngles( vec3_t vec, vec3_t angles )
-{
-	float forward;
-	float yaw, pitch;
-	
-	if ( ( vec[ 0 ] == 0 ) && ( vec[ 1 ] == 0 ) )
-	{
-		yaw = 0;
-		if ( vec[ 2 ] > 0 )
-		{
-			pitch = 90;
-		}
-		else
-		{
-			pitch = 270;
-		}
-	}
-	else
-	{
-		yaw = (vec_t)atan2( vec[ 1 ], vec[ 0 ] ) * 180 / M_PI;
-		if ( yaw < 0 )
-		{
-			yaw += 360;
-		}
-		
-		forward = ( float )sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] );
-		pitch = (vec_t)atan2( vec[ 2 ], forward ) * 180 / M_PI;
-		if ( pitch < 0 )
-		{
-			pitch += 360;
-		}
-	}
-	
-	angles[ 0 ] = pitch;
-	angles[ 1 ] = yaw;
-	angles[ 2 ] = 0;
-}
-
-/*
-=====================
-PlaneFromPoints
-
-Returns false if the triangle is degenrate.
-The normal will point out of the clock for clockwise ordered points
-=====================
-*/
-qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
-	vec3_t	d1, d2;
-
-	VectorSubtract( b, a, d1 );
-	VectorSubtract( c, a, d2 );
-	CrossProduct( d2, d1, plane );
-	if ( VectorNormalize( plane, plane ) == 0 ) {
-		return qfalse;
-	}
-
-	plane[3] = DotProduct( a, plane );
-	return qtrue;
-}
-
-/*
-** NormalToLatLong
-**
-** We use two byte encoded normals in some space critical applications.
-** Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format
-** Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
-**
-*/
-void NormalToLatLong( const vec3_t normal, byte bytes[2] ) {
-	// check for singularities
-	if ( normal[0] == 0 && normal[1] == 0 ) {
-		if ( normal[2] > 0 ) {
-			bytes[0] = 0;
-			bytes[1] = 0;		// lat = 0, long = 0
-		} else {
-			bytes[0] = 128;
-			bytes[1] = 0;		// lat = 0, long = 128
-		}
-	} else {
-		int	a, b;
-
-		a = (int)( RAD2DEG( atan2( normal[1], normal[0] ) ) * (255.0f / 360.0f ) );
-		a &= 0xff;
-
-		b = (int)( RAD2DEG( acos( normal[2] ) ) * ( 255.0f / 360.0f ) );
-		b &= 0xff;
-
-		bytes[0] = b;	// longitude
-		bytes[1] = a;	// lattitude
-	}
-}
-
-/*
-=================
-PlaneTypeForNormal
-=================
-*/
-int	PlaneTypeForNormal (vec3_t normal) {
-	if (normal[0] == 1.0 || normal[0] == -1.0)
-		return PLANE_X;
-	if (normal[1] == 1.0 || normal[1] == -1.0)
-		return PLANE_Y;
-	if (normal[2] == 1.0 || normal[2] == -1.0)
-		return PLANE_Z;
-	
-	return PLANE_NON_AXIAL;
-}
-
-/*
-================
-MatrixMultiply
-================
-*/
-void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
-	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
-				in1[0][2] * in2[2][0];
-	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
-				in1[0][2] * in2[2][1];
-	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
-				in1[0][2] * in2[2][2];
-	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
-				in1[1][2] * in2[2][0];
-	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
-				in1[1][2] * in2[2][1];
-	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
-				in1[1][2] * in2[2][2];
-	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
-				in1[2][2] * in2[2][0];
-	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
-				in1[2][2] * in2[2][1];
-	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
-				in1[2][2] * in2[2][2];
-}
-
-void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
-{
-	float d;
-	vec3_t n;
-	float inv_denom;
-
-	inv_denom = 1.0F / DotProduct( normal, normal );
-
-	d = DotProduct( normal, p ) * inv_denom;
-
-	n[0] = normal[0] * inv_denom;
-	n[1] = normal[1] * inv_denom;
-	n[2] = normal[2] * inv_denom;
-
-	dst[0] = p[0] - d * n[0];
-	dst[1] = p[1] - d * n[1];
-	dst[2] = p[2] - d * n[2];
-}
-
-/*
-** assumes "src" is normalized
-*/
-void PerpendicularVector( vec3_t dst, const vec3_t src )
-{
-	int	pos;
-	int i;
-	vec_t minelem = 1.0F;
-	vec3_t tempvec;
-
-	/*
-	** find the smallest magnitude axially aligned vector
-	*/
-	for ( pos = 0, i = 0; i < 3; i++ )
-	{
-		if ( fabs( src[i] ) < minelem )
-		{
-			pos = i;
-			minelem = (vec_t)fabs( src[i] );
-		}
-	}
-	tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
-	tempvec[pos] = 1.0F;
-
-	/*
-	** project the point onto the plane defined by src
-	*/
-	ProjectPointOnPlane( dst, tempvec, src );
-
-	/*
-	** normalize the result
-	*/
-	VectorNormalize( dst, dst );
-}
-
-/*
-===============
-RotatePointAroundVector
-
-This is not implemented very well...
-===============
-*/
-void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
-							 float degrees ) {
-	float	m[3][3];
-	float	im[3][3];
-	float	zrot[3][3];
-	float	tmpmat[3][3];
-	float	rot[3][3];
-	int	i;
-	vec3_t vr, vup, vf;
-	float	rad;
-
-	vf[0] = dir[0];
-	vf[1] = dir[1];
-	vf[2] = dir[2];
-
-	PerpendicularVector( vr, dir );
-	CrossProduct( vr, vf, vup );
-
-	m[0][0] = vr[0];
-	m[1][0] = vr[1];
-	m[2][0] = vr[2];
-
-	m[0][1] = vup[0];
-	m[1][1] = vup[1];
-	m[2][1] = vup[2];
-
-	m[0][2] = vf[0];
-	m[1][2] = vf[1];
-	m[2][2] = vf[2];
-
-	memcpy( im, m, sizeof( im ) );
-
-	im[0][1] = m[1][0];
-	im[0][2] = m[2][0];
-	im[1][0] = m[0][1];
-	im[1][2] = m[2][1];
-	im[2][0] = m[0][2];
-	im[2][1] = m[1][2];
-
-	memset( zrot, 0, sizeof( zrot ) );
-	zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
-
-	rad = DEG2RAD( degrees );
-	zrot[0][0] = (vec_t)cos( rad );
-	zrot[0][1] = (vec_t)sin( rad );
-	zrot[1][0] = (vec_t)-sin( rad );
-	zrot[1][1] = (vec_t)cos( rad );
-
-	MatrixMultiply( m, zrot, tmpmat );
-	MatrixMultiply( tmpmat, im, rot );
-
-	for ( i = 0; i < 3; i++ ) {
-		dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// mathlib.c -- math primitives
+#include "mathlib.h"
+// we use memcpy and memset
+#include <memory.h>
+
+vec3_t vec3_origin = {0.0f,0.0f,0.0f};
+
+/*
+================
+MakeNormalVectors
+
+Given a normalized forward vector, create two
+other perpendicular vectors
+================
+*/
+void MakeNormalVectors (vec3_t forward, vec3_t right, vec3_t up)
+{
+	float		d;
+
+	// this rotate and negate guarantees a vector
+	// not colinear with the original
+	right[1] = -forward[0];
+	right[2] = forward[1];
+	right[0] = forward[2];
+
+	d = DotProduct (right, forward);
+	VectorMA (right, -d, forward, right);
+	VectorNormalize (right, right);
+	CrossProduct (right, forward, up);
+}
+
+vec_t VectorLength(vec3_t v)
+{
+	int		i;
+	float	length;
+	
+	length = 0.0f;
+	for (i=0 ; i< 3 ; i++)
+		length += v[i]*v[i];
+	length = (float)sqrt (length);
+
+	return length;
+}
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2)
+{
+	int		i;
+	
+	for (i=0 ; i<3 ; i++)
+		if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
+			return qfalse;
+			
+	return qtrue;
+}
+
+/*
+// FIXME TTimo this implementation has to be particular to radiant
+//   through another name I'd say
+vec_t Q_rint (vec_t in)
+{
+  if (g_PrefsDlg.m_bNoClamp)
+    return in;
+  else
+    return (float)floor (in + 0.5);
+}
+*/
+
+void VectorMA( const vec3_t va, vec_t scale, const vec3_t vb, vec3_t vc )
+{
+	vc[0] = va[0] + scale*vb[0];
+	vc[1] = va[1] + scale*vb[1];
+	vc[2] = va[2] + scale*vb[2];
+}
+
+void _CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
+{
+	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
+	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
+	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+vec_t _DotProduct (vec3_t v1, vec3_t v2)
+{
+	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+}
+
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
+{
+	out[0] = va[0]-vb[0];
+	out[1] = va[1]-vb[1];
+	out[2] = va[2]-vb[2];
+}
+
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
+{
+	out[0] = va[0]+vb[0];
+	out[1] = va[1]+vb[1];
+	out[2] = va[2]+vb[2];
+}
+
+void _VectorCopy (vec3_t in, vec3_t out)
+{
+	out[0] = in[0];
+	out[1] = in[1];
+	out[2] = in[2];
+}
+
+vec_t VectorNormalize( const vec3_t in, vec3_t out ) {
+	vec_t	length, ilength;
+
+	length = (vec_t)sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
+	if (length == 0)
+	{
+		VectorClear (out);
+		return 0;
+	}
+
+	ilength = 1.0f/length;
+	out[0] = in[0]*ilength;
+	out[1] = in[1]*ilength;
+	out[2] = in[2]*ilength;
+
+	return length;
+}
+
+vec_t ColorNormalize( const vec3_t in, vec3_t out ) {
+	float	max, scale;
+
+	max = in[0];
+	if (in[1] > max)
+		max = in[1];
+	if (in[2] > max)
+		max = in[2];
+
+	if (max == 0) {
+		out[0] = out[1] = out[2] = 1.0;
+		return 0;
+	}
+
+	scale = 1.0f / max;
+
+	VectorScale (in, scale, out);
+
+	return max;
+}
+
+void VectorInverse (vec3_t v)
+{
+	v[0] = -v[0];
+	v[1] = -v[1];
+	v[2] = -v[2];
+}
+
+/*
+void VectorScale (vec3_t v, vec_t scale, vec3_t out)
+{
+	out[0] = v[0] * scale;
+	out[1] = v[1] * scale;
+	out[2] = v[2] * scale;
+}
+*/
+
+void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t out)
+{
+  vec3_t vWork, va;
+  int nIndex[3][2];
+  int i;
+
+  VectorCopy(vIn, va);
+  VectorCopy(va, vWork);
+  nIndex[0][0] = 1; nIndex[0][1] = 2;
+  nIndex[1][0] = 2; nIndex[1][1] = 0;
+  nIndex[2][0] = 0; nIndex[2][1] = 1;
+
+  for (i = 0; i < 3; i++)
+  {
+    if (vRotation[i] != 0)
+    {
+      float dAngle = vRotation[i] * Q_PI / 180.0f;
+	    float c = (vec_t)cos(dAngle);
+      float s = (vec_t)sin(dAngle);
+      vWork[nIndex[i][0]] = va[nIndex[i][0]] * c - va[nIndex[i][1]] * s;
+      vWork[nIndex[i][1]] = va[nIndex[i][0]] * s + va[nIndex[i][1]] * c;
+    }
+    VectorCopy(vWork, va);
+  }
+  VectorCopy(vWork, out);
+}
+
+void VectorRotateOrigin (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out)
+{
+  vec3_t vTemp, vTemp2;
+
+  VectorSubtract(vIn, vOrigin, vTemp);
+  VectorRotate(vTemp, vRotation, vTemp2);
+  VectorAdd(vTemp2, vOrigin, out);
+}
+
+void VectorPolar(vec3_t v, float radius, float theta, float phi)
+{
+ 	v[0]=(float)(radius * cos(theta) * cos(phi));
+	v[1]=(float)(radius * sin(theta) * cos(phi));
+	v[2]=(float)(radius * sin(phi));
+}
+
+void VectorSnap(vec3_t v)
+{
+  int i;
+  for (i = 0; i < 3; i++)
+  {
+    v[i] = (vec_t)floor (v[i] + 0.5);
+  }
+}
+
+void VectorISnap(vec3_t point, int snap)
+{
+  int i;
+	for (i = 0 ;i < 3 ; i++)
+	{
+		point[i] = (vec_t)floor (point[i] / snap + 0.5) * snap;
+	}
+}
+
+void VectorFSnap(vec3_t point, float snap)
+{
+  int i;
+	for (i = 0 ;i < 3 ; i++)
+	{
+		point[i] = (vec_t)floor (point[i] / snap + 0.5) * snap;
+	}
+}
+
+void _Vector5Add (vec5_t va, vec5_t vb, vec5_t out)
+{
+	out[0] = va[0]+vb[0];
+	out[1] = va[1]+vb[1];
+	out[2] = va[2]+vb[2];
+	out[3] = va[3]+vb[3];
+	out[4] = va[4]+vb[4];
+}
+
+void _Vector5Scale (vec5_t v, vec_t scale, vec5_t out)
+{
+	out[0] = v[0] * scale;
+	out[1] = v[1] * scale;
+	out[2] = v[2] * scale;
+	out[3] = v[3] * scale;
+	out[4] = v[4] * scale;
+}
+
+void _Vector53Copy (vec5_t in, vec3_t out)
+{
+	out[0] = in[0];
+	out[1] = in[1];
+	out[2] = in[2];
+}
+
+// NOTE: added these from Ritual's Q3Radiant
+void ClearBounds (vec3_t mins, vec3_t maxs)
+{
+	mins[0] = mins[1] = mins[2] = 99999;
+	maxs[0] = maxs[1] = maxs[2] = -99999;
+}
+
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
+{
+	int		i;
+	vec_t	val;
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		val = v[i];
+		if (val < mins[i])
+			mins[i] = val;
+		if (val > maxs[i])
+			maxs[i] = val;
+	}
+}
+
+#define	PITCH				0		// up / down
+#define	YAW					1		// left / right
+#define	ROLL				2		// fall over
+#ifndef M_PI
+#define M_PI		3.14159265358979323846f	// matches value in gcc v2 math.h
+#endif
+
+void AngleVectors (vec3_t angles, vec3_t forward, vec3_t right, vec3_t up)
+{
+	float		angle;
+	static float		sr, sp, sy, cr, cp, cy;
+	// static to help MS compiler fp bugs
+	
+	angle = angles[YAW] * (M_PI*2.0f / 360.0f);
+	sy = (vec_t)sin(angle);
+	cy = (vec_t)cos(angle);
+	angle = angles[PITCH] * (M_PI*2.0f / 360.0f);
+	sp = (vec_t)sin(angle);
+	cp = (vec_t)cos(angle);
+	angle = angles[ROLL] * (M_PI*2.0f / 360.0f);
+	sr = (vec_t)sin(angle);
+	cr = (vec_t)cos(angle);
+	
+	if (forward)
+	{
+		forward[0] = cp*cy;
+		forward[1] = cp*sy;
+		forward[2] = -sp;
+	}
+	if (right)
+	{
+		right[0] = -sr*sp*cy+cr*sy;
+		right[1] = -sr*sp*sy-cr*cy;
+		right[2] = -sr*cp;
+	}
+	if (up)
+	{
+		up[0] = cr*sp*cy+sr*sy;
+		up[1] = cr*sp*sy-sr*cy;
+		up[2] = cr*cp;
+	}
+}
+
+void VectorToAngles( vec3_t vec, vec3_t angles )
+{
+	float forward;
+	float yaw, pitch;
+	
+	if ( ( vec[ 0 ] == 0 ) && ( vec[ 1 ] == 0 ) )
+	{
+		yaw = 0;
+		if ( vec[ 2 ] > 0 )
+		{
+			pitch = 90;
+		}
+		else
+		{
+			pitch = 270;
+		}
+	}
+	else
+	{
+		yaw = (vec_t)atan2( vec[ 1 ], vec[ 0 ] ) * 180 / M_PI;
+		if ( yaw < 0 )
+		{
+			yaw += 360;
+		}
+		
+		forward = ( float )sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] );
+		pitch = (vec_t)atan2( vec[ 2 ], forward ) * 180 / M_PI;
+		if ( pitch < 0 )
+		{
+			pitch += 360;
+		}
+	}
+	
+	angles[ 0 ] = pitch;
+	angles[ 1 ] = yaw;
+	angles[ 2 ] = 0;
+}
+
+/*
+=====================
+PlaneFromPoints
+
+Returns false if the triangle is degenrate.
+The normal will point out of the clock for clockwise ordered points
+=====================
+*/
+qboolean PlaneFromPoints( vec4_t plane, const vec3_t a, const vec3_t b, const vec3_t c ) {
+	vec3_t	d1, d2;
+
+	VectorSubtract( b, a, d1 );
+	VectorSubtract( c, a, d2 );
+	CrossProduct( d2, d1, plane );
+	if ( VectorNormalize( plane, plane ) == 0 ) {
+		return qfalse;
+	}
+
+	plane[3] = DotProduct( a, plane );
+	return qtrue;
+}
+
+/*
+** NormalToLatLong
+**
+** We use two byte encoded normals in some space critical applications.
+** Lat = 0 at (1,0,0) to 360 (-1,0,0), encoded in 8-bit sine table format
+** Lng = 0 at (0,0,1) to 180 (0,0,-1), encoded in 8-bit sine table format
+**
+*/
+void NormalToLatLong( const vec3_t normal, byte bytes[2] ) {
+	// check for singularities
+	if ( normal[0] == 0 && normal[1] == 0 ) {
+		if ( normal[2] > 0 ) {
+			bytes[0] = 0;
+			bytes[1] = 0;		// lat = 0, long = 0
+		} else {
+			bytes[0] = 128;
+			bytes[1] = 0;		// lat = 0, long = 128
+		}
+	} else {
+		int	a, b;
+
+		a = (int)( RAD2DEG( atan2( normal[1], normal[0] ) ) * (255.0f / 360.0f ) );
+		a &= 0xff;
+
+		b = (int)( RAD2DEG( acos( normal[2] ) ) * ( 255.0f / 360.0f ) );
+		b &= 0xff;
+
+		bytes[0] = b;	// longitude
+		bytes[1] = a;	// lattitude
+	}
+}
+
+/*
+=================
+PlaneTypeForNormal
+=================
+*/
+int	PlaneTypeForNormal (vec3_t normal) {
+	if (normal[0] == 1.0 || normal[0] == -1.0)
+		return PLANE_X;
+	if (normal[1] == 1.0 || normal[1] == -1.0)
+		return PLANE_Y;
+	if (normal[2] == 1.0 || normal[2] == -1.0)
+		return PLANE_Z;
+	
+	return PLANE_NON_AXIAL;
+}
+
+/*
+================
+MatrixMultiply
+================
+*/
+void MatrixMultiply(float in1[3][3], float in2[3][3], float out[3][3]) {
+	out[0][0] = in1[0][0] * in2[0][0] + in1[0][1] * in2[1][0] +
+				in1[0][2] * in2[2][0];
+	out[0][1] = in1[0][0] * in2[0][1] + in1[0][1] * in2[1][1] +
+				in1[0][2] * in2[2][1];
+	out[0][2] = in1[0][0] * in2[0][2] + in1[0][1] * in2[1][2] +
+				in1[0][2] * in2[2][2];
+	out[1][0] = in1[1][0] * in2[0][0] + in1[1][1] * in2[1][0] +
+				in1[1][2] * in2[2][0];
+	out[1][1] = in1[1][0] * in2[0][1] + in1[1][1] * in2[1][1] +
+				in1[1][2] * in2[2][1];
+	out[1][2] = in1[1][0] * in2[0][2] + in1[1][1] * in2[1][2] +
+				in1[1][2] * in2[2][2];
+	out[2][0] = in1[2][0] * in2[0][0] + in1[2][1] * in2[1][0] +
+				in1[2][2] * in2[2][0];
+	out[2][1] = in1[2][0] * in2[0][1] + in1[2][1] * in2[1][1] +
+				in1[2][2] * in2[2][1];
+	out[2][2] = in1[2][0] * in2[0][2] + in1[2][1] * in2[1][2] +
+				in1[2][2] * in2[2][2];
+}
+
+void ProjectPointOnPlane( vec3_t dst, const vec3_t p, const vec3_t normal )
+{
+	float d;
+	vec3_t n;
+	float inv_denom;
+
+	inv_denom = 1.0F / DotProduct( normal, normal );
+
+	d = DotProduct( normal, p ) * inv_denom;
+
+	n[0] = normal[0] * inv_denom;
+	n[1] = normal[1] * inv_denom;
+	n[2] = normal[2] * inv_denom;
+
+	dst[0] = p[0] - d * n[0];
+	dst[1] = p[1] - d * n[1];
+	dst[2] = p[2] - d * n[2];
+}
+
+/*
+** assumes "src" is normalized
+*/
+void PerpendicularVector( vec3_t dst, const vec3_t src )
+{
+	int	pos;
+	int i;
+	vec_t minelem = 1.0F;
+	vec3_t tempvec;
+
+	/*
+	** find the smallest magnitude axially aligned vector
+	*/
+	for ( pos = 0, i = 0; i < 3; i++ )
+	{
+		if ( fabs( src[i] ) < minelem )
+		{
+			pos = i;
+			minelem = (vec_t)fabs( src[i] );
+		}
+	}
+	tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
+	tempvec[pos] = 1.0F;
+
+	/*
+	** project the point onto the plane defined by src
+	*/
+	ProjectPointOnPlane( dst, tempvec, src );
+
+	/*
+	** normalize the result
+	*/
+	VectorNormalize( dst, dst );
+}
+
+/*
+===============
+RotatePointAroundVector
+
+This is not implemented very well...
+===============
+*/
+void RotatePointAroundVector( vec3_t dst, const vec3_t dir, const vec3_t point,
+							 float degrees ) {
+	float	m[3][3];
+	float	im[3][3];
+	float	zrot[3][3];
+	float	tmpmat[3][3];
+	float	rot[3][3];
+	int	i;
+	vec3_t vr, vup, vf;
+	float	rad;
+
+	vf[0] = dir[0];
+	vf[1] = dir[1];
+	vf[2] = dir[2];
+
+	PerpendicularVector( vr, dir );
+	CrossProduct( vr, vf, vup );
+
+	m[0][0] = vr[0];
+	m[1][0] = vr[1];
+	m[2][0] = vr[2];
+
+	m[0][1] = vup[0];
+	m[1][1] = vup[1];
+	m[2][1] = vup[2];
+
+	m[0][2] = vf[0];
+	m[1][2] = vf[1];
+	m[2][2] = vf[2];
+
+	memcpy( im, m, sizeof( im ) );
+
+	im[0][1] = m[1][0];
+	im[0][2] = m[2][0];
+	im[1][0] = m[0][1];
+	im[1][2] = m[2][1];
+	im[2][0] = m[0][2];
+	im[2][1] = m[1][2];
+
+	memset( zrot, 0, sizeof( zrot ) );
+	zrot[0][0] = zrot[1][1] = zrot[2][2] = 1.0F;
+
+	rad = DEG2RAD( degrees );
+	zrot[0][0] = (vec_t)cos( rad );
+	zrot[0][1] = (vec_t)sin( rad );
+	zrot[1][0] = (vec_t)-sin( rad );
+	zrot[1][1] = (vec_t)cos( rad );
+
+	MatrixMultiply( m, zrot, tmpmat );
+	MatrixMultiply( tmpmat, im, rot );
+
+	for ( i = 0; i < 3; i++ ) {
+		dst[i] = rot[i][0] * point[0] + rot[i][1] * point[1] + rot[i][2] * point[2];
+	}
+}
diff --git a/libs/mathlib/ray.c b/libs/mathlib/ray.c
index 08cb9f87..cfe4bfd4 100644
--- a/libs/mathlib/ray.c
+++ b/libs/mathlib/ray.c
@@ -1,135 +1,135 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "mathlib.h"
-/*! for memcpy */
-#include <memory.h>
-
-vec3_t identity = { 0,0,0 };
-
-void ray_construct_for_vec3(ray_t *ray, const vec3_t origin, const vec3_t direction)
-{
-  VectorCopy(origin, ray->origin);
-  VectorCopy(direction, ray->direction);
-}
-  
-void ray_transform(ray_t *ray, const m4x4_t matrix)
-{
-  m4x4_transform_point(matrix, ray->origin);
-  m4x4_transform_normal(matrix, ray->direction);
-}
-
-vec_t ray_intersect_point(const ray_t *ray, const vec3_t point, vec_t epsilon, vec_t divergence)
-{
-  vec3_t displacement;
-  vec_t depth;
-
-  // calc displacement of test point from ray origin
-  VectorSubtract(point, ray->origin, displacement);
-  // calc length of displacement vector along ray direction
-	depth = DotProduct(displacement, ray->direction);
-  if(depth < 0.0f) return (vec_t)VEC_MAX;
-  // calc position of closest point on ray to test point
-  VectorMA (ray->origin, depth, ray->direction, displacement);
-  // calc displacement of test point from closest point
-	VectorSubtract(point, displacement, displacement);
-  // calc length of displacement, subtract depth-dependant epsilon
-  if (VectorLength(displacement) - (epsilon + (depth * divergence)) > 0.0f) return (vec_t)VEC_MAX;
-  return depth;
-}
-
-// Tomas Moller and Ben Trumbore. Fast, minimum storage ray-triangle intersection. Journal of graphics tools, 2(1):21-28, 1997
-
-#define EPSILON 0.000001
-
-vec_t ray_intersect_triangle(const ray_t *ray, qboolean bCullBack, const vec3_t vert0, const vec3_t vert1, const vec3_t vert2)
-{
-  float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
-  float det,inv_det;
-  float u, v;
-  vec_t depth = (vec_t)VEC_MAX;
-  
-  /* find vectors for two edges sharing vert0 */
-  VectorSubtract(vert1, vert0, edge1);
-  VectorSubtract(vert2, vert0, edge2);
-  
-  /* begin calculating determinant - also used to calculate U parameter */
-  CrossProduct(ray->direction, edge2, pvec);
-  
-  /* if determinant is near zero, ray lies in plane of triangle */
-  det = DotProduct(edge1, pvec);
-  
-  if (bCullBack == qtrue)
-  {
-    if (det < EPSILON)
-      return depth;
-    
-    // calculate distance from vert0 to ray origin
-    VectorSubtract(ray->origin, vert0, tvec);
-    
-    // calculate U parameter and test bounds
-    u = DotProduct(tvec, pvec);
-    if (u < 0.0 || u > det)
-      return depth;
-    
-    // prepare to test V parameter
-    CrossProduct(tvec, edge1, qvec);
-    
-    // calculate V parameter and test bounds
-    v = DotProduct(ray->direction, qvec);
-    if (v < 0.0 || u + v > det)
-      return depth;
-    
-    // calculate t, scale parameters, ray intersects triangle
-    depth = DotProduct(edge2, qvec);
-    inv_det = 1.0f / det;
-    depth *= inv_det;
-    //u *= inv_det;
-    //v *= inv_det;
-  }
-  else
-  {
-    /* the non-culling branch */
-    if (det > -EPSILON && det < EPSILON)
-      return depth;
-    inv_det = 1.0f / det;
-    
-    /* calculate distance from vert0 to ray origin */
-    VectorSubtract(ray->origin, vert0, tvec);
-    
-    /* calculate U parameter and test bounds */
-    u = DotProduct(tvec, pvec) * inv_det;
-    if (u < 0.0 || u > 1.0)
-      return depth;
-    
-    /* prepare to test V parameter */
-    CrossProduct(tvec, edge1, qvec);
-    
-    /* calculate V parameter and test bounds */
-    v = DotProduct(ray->direction, qvec) * inv_det;
-    if (v < 0.0 || u + v > 1.0)
-      return depth;
-    
-    /* calculate t, ray intersects triangle */
-    depth = DotProduct(edge2, qvec) * inv_det;
-  }
-  return depth;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "mathlib.h"
+/*! for memcpy */
+#include <memory.h>
+
+vec3_t identity = { 0,0,0 };
+
+void ray_construct_for_vec3(ray_t *ray, const vec3_t origin, const vec3_t direction)
+{
+  VectorCopy(origin, ray->origin);
+  VectorCopy(direction, ray->direction);
+}
+  
+void ray_transform(ray_t *ray, const m4x4_t matrix)
+{
+  m4x4_transform_point(matrix, ray->origin);
+  m4x4_transform_normal(matrix, ray->direction);
+}
+
+vec_t ray_intersect_point(const ray_t *ray, const vec3_t point, vec_t epsilon, vec_t divergence)
+{
+  vec3_t displacement;
+  vec_t depth;
+
+  // calc displacement of test point from ray origin
+  VectorSubtract(point, ray->origin, displacement);
+  // calc length of displacement vector along ray direction
+	depth = DotProduct(displacement, ray->direction);
+  if(depth < 0.0f) return (vec_t)VEC_MAX;
+  // calc position of closest point on ray to test point
+  VectorMA (ray->origin, depth, ray->direction, displacement);
+  // calc displacement of test point from closest point
+	VectorSubtract(point, displacement, displacement);
+  // calc length of displacement, subtract depth-dependant epsilon
+  if (VectorLength(displacement) - (epsilon + (depth * divergence)) > 0.0f) return (vec_t)VEC_MAX;
+  return depth;
+}
+
+// Tomas Moller and Ben Trumbore. Fast, minimum storage ray-triangle intersection. Journal of graphics tools, 2(1):21-28, 1997
+
+#define EPSILON 0.000001
+
+vec_t ray_intersect_triangle(const ray_t *ray, qboolean bCullBack, const vec3_t vert0, const vec3_t vert1, const vec3_t vert2)
+{
+  float edge1[3], edge2[3], tvec[3], pvec[3], qvec[3];
+  float det,inv_det;
+  float u, v;
+  vec_t depth = (vec_t)VEC_MAX;
+  
+  /* find vectors for two edges sharing vert0 */
+  VectorSubtract(vert1, vert0, edge1);
+  VectorSubtract(vert2, vert0, edge2);
+  
+  /* begin calculating determinant - also used to calculate U parameter */
+  CrossProduct(ray->direction, edge2, pvec);
+  
+  /* if determinant is near zero, ray lies in plane of triangle */
+  det = DotProduct(edge1, pvec);
+  
+  if (bCullBack == qtrue)
+  {
+    if (det < EPSILON)
+      return depth;
+    
+    // calculate distance from vert0 to ray origin
+    VectorSubtract(ray->origin, vert0, tvec);
+    
+    // calculate U parameter and test bounds
+    u = DotProduct(tvec, pvec);
+    if (u < 0.0 || u > det)
+      return depth;
+    
+    // prepare to test V parameter
+    CrossProduct(tvec, edge1, qvec);
+    
+    // calculate V parameter and test bounds
+    v = DotProduct(ray->direction, qvec);
+    if (v < 0.0 || u + v > det)
+      return depth;
+    
+    // calculate t, scale parameters, ray intersects triangle
+    depth = DotProduct(edge2, qvec);
+    inv_det = 1.0f / det;
+    depth *= inv_det;
+    //u *= inv_det;
+    //v *= inv_det;
+  }
+  else
+  {
+    /* the non-culling branch */
+    if (det > -EPSILON && det < EPSILON)
+      return depth;
+    inv_det = 1.0f / det;
+    
+    /* calculate distance from vert0 to ray origin */
+    VectorSubtract(ray->origin, vert0, tvec);
+    
+    /* calculate U parameter and test bounds */
+    u = DotProduct(tvec, pvec) * inv_det;
+    if (u < 0.0 || u > 1.0)
+      return depth;
+    
+    /* prepare to test V parameter */
+    CrossProduct(tvec, edge1, qvec);
+    
+    /* calculate V parameter and test bounds */
+    v = DotProduct(ray->direction, qvec) * inv_det;
+    if (v < 0.0 || u + v > 1.0)
+      return depth;
+    
+    /* calculate t, ray intersects triangle */
+    depth = DotProduct(edge2, qvec) * inv_det;
+  }
+  return depth;
+}
diff --git a/libs/md5lib.h b/libs/md5lib.h
index 32963357..d56f0263 100644
--- a/libs/md5lib.h
+++ b/libs/md5lib.h
@@ -1,91 +1,91 @@
-/*
-  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost@aladdin.com
-
- */
-/* $Id: md5lib.h,v 1.1 2003/07/18 04:24:39 ydnar Exp $ */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321, whose
-  text is available at
-	http://www.ietf.org/rfc/rfc1321.txt
-  The code is derived from the text of the RFC, including the test suite
-  (section A.5) but excluding the rest of Appendix A.  It does not include
-  any code or documentation that is identified in the RFC as being
-  copyrighted.
-
-  The original and principal author of md5.h is L. Peter Deutsch
-  <ghost@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-
-  2002-04-13 lpd Removed support for non-ANSI compilers; removed
-	references to Ghostscript; clarified derivation from RFC 1321;
-	now handles byte order either statically or dynamically.
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
-	added conditionalization for C++ compilation from Martin
-	Purschke <purschke@bnl.gov>.
-  1999-05-03 lpd Original version.
- */
-
-#ifndef md5_INCLUDED
-#  define md5_INCLUDED
-
-/*
- * This package supports both compile-time and run-time determination of CPU
- * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
- * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
- * defined as non-zero, the code will be compiled to run only on big-endian
- * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
- * run on either big- or little-endian CPUs, but will run slightly less
- * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
- */
-
-typedef unsigned char md5_byte_t; /* 8-bit byte */
-typedef unsigned int md5_word_t; /* 32-bit word */
-
-/* Define the state of the MD5 Algorithm. */
-typedef struct md5_state_s {
-    md5_word_t count[2];	/* message length in bits, lsw first */
-    md5_word_t abcd[4];		/* digest buffer */
-    md5_byte_t buf[64];		/* accumulate block */
-} md5_state_t;
-
-#ifdef __cplusplus
-extern "C" 
-{
-#endif
-
-/* Initialize the algorithm. */
-void md5_init(md5_state_t *pms);
-
-/* Append a string to the message. */
-void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
-
-/* Finish the message and return the digest. */
-void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
-
-#ifdef __cplusplus
-}  /* end extern "C" */
-#endif
-
-#endif /* md5_INCLUDED */
+/*
+  Copyright (C) 1999, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5lib.h,v 1.1 2003/07/18 04:24:39 ydnar Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.h is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+
+  2002-04-13 lpd Removed support for non-ANSI compilers; removed
+	references to Ghostscript; clarified derivation from RFC 1321;
+	now handles byte order either statically or dynamically.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5);
+	added conditionalization for C++ compilation from Martin
+	Purschke <purschke@bnl.gov>.
+  1999-05-03 lpd Original version.
+ */
+
+#ifndef md5_INCLUDED
+#  define md5_INCLUDED
+
+/*
+ * This package supports both compile-time and run-time determination of CPU
+ * byte order.  If ARCH_IS_BIG_ENDIAN is defined as 0, the code will be
+ * compiled to run only on little-endian CPUs; if ARCH_IS_BIG_ENDIAN is
+ * defined as non-zero, the code will be compiled to run only on big-endian
+ * CPUs; if ARCH_IS_BIG_ENDIAN is not defined, the code will be compiled to
+ * run on either big- or little-endian CPUs, but will run slightly less
+ * efficiently on either one than if ARCH_IS_BIG_ENDIAN is defined.
+ */
+
+typedef unsigned char md5_byte_t; /* 8-bit byte */
+typedef unsigned int md5_word_t; /* 32-bit word */
+
+/* Define the state of the MD5 Algorithm. */
+typedef struct md5_state_s {
+    md5_word_t count[2];	/* message length in bits, lsw first */
+    md5_word_t abcd[4];		/* digest buffer */
+    md5_byte_t buf[64];		/* accumulate block */
+} md5_state_t;
+
+#ifdef __cplusplus
+extern "C" 
+{
+#endif
+
+/* Initialize the algorithm. */
+void md5_init(md5_state_t *pms);
+
+/* Append a string to the message. */
+void md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes);
+
+/* Finish the message and return the digest. */
+void md5_finish(md5_state_t *pms, md5_byte_t digest[16]);
+
+#ifdef __cplusplus
+}  /* end extern "C" */
+#endif
+
+#endif /* md5_INCLUDED */
diff --git a/libs/md5lib/md5lib.c b/libs/md5lib/md5lib.c
index 6fb45f13..60b45148 100644
--- a/libs/md5lib/md5lib.c
+++ b/libs/md5lib/md5lib.c
@@ -1,395 +1,395 @@
-/*
-  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  L. Peter Deutsch
-  ghost@aladdin.com
-
- */
-/* $Id: md5lib.c,v 1.1 2003/07/18 04:24:39 ydnar Exp $ */
-/*
-  Independent implementation of MD5 (RFC 1321).
-
-  This code implements the MD5 Algorithm defined in RFC 1321, whose
-  text is available at
-	http://www.ietf.org/rfc/rfc1321.txt
-  The code is derived from the text of the RFC, including the test suite
-  (section A.5) but excluding the rest of Appendix A.  It does not include
-  any code or documentation that is identified in the RFC as being
-  copyrighted.
-
-  The original and principal author of md5.c is L. Peter Deutsch
-  <ghost@aladdin.com>.  Other authors are noted in the change history
-  that follows (in reverse chronological order):
-  
-  2003-07-17 ydnar added to gtkradiant project from
-     http://sourceforge.net/projects/libmd5-rfc/
-  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
-	either statically or dynamically; added missing #include <string.h>
-	in library.
-  2002-03-11 lpd Corrected argument list for main(), and added int return
-	type, in test program and T value program.
-  2002-02-21 lpd Added missing #include <stdio.h> in test program.
-  2000-07-03 lpd Patched to eliminate warnings about "constant is
-	unsigned in ANSI C, signed in traditional"; made test program
-	self-checking.
-  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
-  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
-  1999-05-03 lpd Original version.
- */
-
-#include "md5lib.h"	/* ydnar */
-#include <string.h>
-
-/* ydnar: gtkradiant endian picking */
-#ifdef _SGI_SOURCE
-#define	__BIG_ENDIAN__
-#endif
-
-#ifdef __BIG_ENDIAN__
-#define ARCH_IS_BIG_ENDIAN  1
-#else
-#define ARCH_IS_BIG_ENDIAN  0
-#endif
-/* ydnar: end */
-
-#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
-#ifdef ARCH_IS_BIG_ENDIAN
-#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
-#else
-#  define BYTE_ORDER 0
-#endif
-
-#define T_MASK ((md5_word_t)~0)
-#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
-#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
-#define T3    0x242070db
-#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
-#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
-#define T6    0x4787c62a
-#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
-#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
-#define T9    0x698098d8
-#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
-#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
-#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
-#define T13    0x6b901122
-#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
-#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
-#define T16    0x49b40821
-#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
-#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
-#define T19    0x265e5a51
-#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
-#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
-#define T22    0x02441453
-#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
-#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
-#define T25    0x21e1cde6
-#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
-#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
-#define T28    0x455a14ed
-#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
-#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
-#define T31    0x676f02d9
-#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
-#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
-#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
-#define T35    0x6d9d6122
-#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
-#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
-#define T38    0x4bdecfa9
-#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
-#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
-#define T41    0x289b7ec6
-#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
-#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
-#define T44    0x04881d05
-#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
-#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
-#define T47    0x1fa27cf8
-#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
-#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
-#define T50    0x432aff97
-#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
-#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
-#define T53    0x655b59c3
-#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
-#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
-#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
-#define T57    0x6fa87e4f
-#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
-#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
-#define T60    0x4e0811a1
-#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
-#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
-#define T63    0x2ad7d2bb
-#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
-
-
-static void
-md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
-{
-    md5_word_t
-	a = pms->abcd[0], b = pms->abcd[1],
-	c = pms->abcd[2], d = pms->abcd[3];
-    md5_word_t t;
-#if BYTE_ORDER > 0
-    /* Define storage only for big-endian CPUs. */
-    md5_word_t X[16];
-#else
-    /* Define storage for little-endian or both types of CPUs. */
-    md5_word_t xbuf[16];
-    const md5_word_t *X;
-#endif
-
-    {
-#if BYTE_ORDER == 0
-	/*
-	 * Determine dynamically whether this is a big-endian or
-	 * little-endian machine, since we can use a more efficient
-	 * algorithm on the latter.
-	 */
-	static const int w = 1;
-
-	if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
-#endif
-#if BYTE_ORDER <= 0		/* little-endian */
-	{
-	    /*
-	     * On little-endian machines, we can process properly aligned
-	     * data without copying it.
-	     */
-	    if (!((data - (const md5_byte_t *)0) & 3)) {
-		/* data are properly aligned */
-		X = (const md5_word_t *)data;
-	    } else {
-		/* not aligned */
-		memcpy(xbuf, data, 64);
-		X = xbuf;
-	    }
-	}
-#endif
-#if BYTE_ORDER == 0
-	else			/* dynamic big-endian */
-#endif
-#if BYTE_ORDER >= 0		/* big-endian */
-	{
-	    /*
-	     * On big-endian machines, we must arrange the bytes in the
-	     * right order.
-	     */
-	    const md5_byte_t *xp = data;
-	    int i;
-
-#  if BYTE_ORDER == 0
-	    X = xbuf;		/* (dynamic only) */
-#  else
-#    define xbuf X		/* (static only) */
-#  endif
-	    for (i = 0; i < 16; ++i, xp += 4)
-		xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
-	}
-#endif
-    }
-
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
-
-    /* Round 1. */
-    /* Let [abcd k s i] denote the operation
-       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
-#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + F(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-    /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  7,  T1);
-    SET(d, a, b, c,  1, 12,  T2);
-    SET(c, d, a, b,  2, 17,  T3);
-    SET(b, c, d, a,  3, 22,  T4);
-    SET(a, b, c, d,  4,  7,  T5);
-    SET(d, a, b, c,  5, 12,  T6);
-    SET(c, d, a, b,  6, 17,  T7);
-    SET(b, c, d, a,  7, 22,  T8);
-    SET(a, b, c, d,  8,  7,  T9);
-    SET(d, a, b, c,  9, 12, T10);
-    SET(c, d, a, b, 10, 17, T11);
-    SET(b, c, d, a, 11, 22, T12);
-    SET(a, b, c, d, 12,  7, T13);
-    SET(d, a, b, c, 13, 12, T14);
-    SET(c, d, a, b, 14, 17, T15);
-    SET(b, c, d, a, 15, 22, T16);
-#undef SET
-
-     /* Round 2. */
-     /* Let [abcd k s i] denote the operation
-          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
-#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + G(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  1,  5, T17);
-    SET(d, a, b, c,  6,  9, T18);
-    SET(c, d, a, b, 11, 14, T19);
-    SET(b, c, d, a,  0, 20, T20);
-    SET(a, b, c, d,  5,  5, T21);
-    SET(d, a, b, c, 10,  9, T22);
-    SET(c, d, a, b, 15, 14, T23);
-    SET(b, c, d, a,  4, 20, T24);
-    SET(a, b, c, d,  9,  5, T25);
-    SET(d, a, b, c, 14,  9, T26);
-    SET(c, d, a, b,  3, 14, T27);
-    SET(b, c, d, a,  8, 20, T28);
-    SET(a, b, c, d, 13,  5, T29);
-    SET(d, a, b, c,  2,  9, T30);
-    SET(c, d, a, b,  7, 14, T31);
-    SET(b, c, d, a, 12, 20, T32);
-#undef SET
-
-     /* Round 3. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + H(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  5,  4, T33);
-    SET(d, a, b, c,  8, 11, T34);
-    SET(c, d, a, b, 11, 16, T35);
-    SET(b, c, d, a, 14, 23, T36);
-    SET(a, b, c, d,  1,  4, T37);
-    SET(d, a, b, c,  4, 11, T38);
-    SET(c, d, a, b,  7, 16, T39);
-    SET(b, c, d, a, 10, 23, T40);
-    SET(a, b, c, d, 13,  4, T41);
-    SET(d, a, b, c,  0, 11, T42);
-    SET(c, d, a, b,  3, 16, T43);
-    SET(b, c, d, a,  6, 23, T44);
-    SET(a, b, c, d,  9,  4, T45);
-    SET(d, a, b, c, 12, 11, T46);
-    SET(c, d, a, b, 15, 16, T47);
-    SET(b, c, d, a,  2, 23, T48);
-#undef SET
-
-     /* Round 4. */
-     /* Let [abcd k s t] denote the operation
-          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
-#define I(x, y, z) ((y) ^ ((x) | ~(z)))
-#define SET(a, b, c, d, k, s, Ti)\
-  t = a + I(b,c,d) + X[k] + Ti;\
-  a = ROTATE_LEFT(t, s) + b
-     /* Do the following 16 operations. */
-    SET(a, b, c, d,  0,  6, T49);
-    SET(d, a, b, c,  7, 10, T50);
-    SET(c, d, a, b, 14, 15, T51);
-    SET(b, c, d, a,  5, 21, T52);
-    SET(a, b, c, d, 12,  6, T53);
-    SET(d, a, b, c,  3, 10, T54);
-    SET(c, d, a, b, 10, 15, T55);
-    SET(b, c, d, a,  1, 21, T56);
-    SET(a, b, c, d,  8,  6, T57);
-    SET(d, a, b, c, 15, 10, T58);
-    SET(c, d, a, b,  6, 15, T59);
-    SET(b, c, d, a, 13, 21, T60);
-    SET(a, b, c, d,  4,  6, T61);
-    SET(d, a, b, c, 11, 10, T62);
-    SET(c, d, a, b,  2, 15, T63);
-    SET(b, c, d, a,  9, 21, T64);
-#undef SET
-
-     /* Then perform the following additions. (That is increment each
-        of the four registers by the value it had before this block
-        was started.) */
-    pms->abcd[0] += a;
-    pms->abcd[1] += b;
-    pms->abcd[2] += c;
-    pms->abcd[3] += d;
-}
-
-void
-md5_init(md5_state_t *pms)
-{
-    pms->count[0] = pms->count[1] = 0;
-    pms->abcd[0] = 0x67452301;
-    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
-    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
-    pms->abcd[3] = 0x10325476;
-}
-
-void
-md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
-{
-    const md5_byte_t *p = data;
-    int left = nbytes;
-    int offset = (pms->count[0] >> 3) & 63;
-    md5_word_t nbits = (md5_word_t)(nbytes << 3);
-
-    if (nbytes <= 0)
-	return;
-
-    /* Update the message length. */
-    pms->count[1] += nbytes >> 29;
-    pms->count[0] += nbits;
-    if (pms->count[0] < nbits)
-	pms->count[1]++;
-
-    /* Process an initial partial block. */
-    if (offset) {
-	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
-
-	memcpy(pms->buf + offset, p, copy);
-	if (offset + copy < 64)
-	    return;
-	p += copy;
-	left -= copy;
-	md5_process(pms, pms->buf);
-    }
-
-    /* Process full blocks. */
-    for (; left >= 64; p += 64, left -= 64)
-	md5_process(pms, p);
-
-    /* Process a final partial block. */
-    if (left)
-	memcpy(pms->buf, p, left);
-}
-
-void
-md5_finish(md5_state_t *pms, md5_byte_t digest[16])
-{
-    static const md5_byte_t pad[64] = {
-	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-    };
-    md5_byte_t data[8];
-    int i;
-
-    /* Save the length before padding. */
-    for (i = 0; i < 8; ++i)
-	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
-    /* Pad to 56 bytes mod 64. */
-    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
-    /* Append the length. */
-    md5_append(pms, data, 8);
-    for (i = 0; i < 16; ++i)
-	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
-}
+/*
+  Copyright (C) 1999, 2000, 2002 Aladdin Enterprises.  All rights reserved.
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  L. Peter Deutsch
+  ghost@aladdin.com
+
+ */
+/* $Id: md5lib.c,v 1.1 2003/07/18 04:24:39 ydnar Exp $ */
+/*
+  Independent implementation of MD5 (RFC 1321).
+
+  This code implements the MD5 Algorithm defined in RFC 1321, whose
+  text is available at
+	http://www.ietf.org/rfc/rfc1321.txt
+  The code is derived from the text of the RFC, including the test suite
+  (section A.5) but excluding the rest of Appendix A.  It does not include
+  any code or documentation that is identified in the RFC as being
+  copyrighted.
+
+  The original and principal author of md5.c is L. Peter Deutsch
+  <ghost@aladdin.com>.  Other authors are noted in the change history
+  that follows (in reverse chronological order):
+  
+  2003-07-17 ydnar added to gtkradiant project from
+     http://sourceforge.net/projects/libmd5-rfc/
+  2002-04-13 lpd Clarified derivation from RFC 1321; now handles byte order
+	either statically or dynamically; added missing #include <string.h>
+	in library.
+  2002-03-11 lpd Corrected argument list for main(), and added int return
+	type, in test program and T value program.
+  2002-02-21 lpd Added missing #include <stdio.h> in test program.
+  2000-07-03 lpd Patched to eliminate warnings about "constant is
+	unsigned in ANSI C, signed in traditional"; made test program
+	self-checking.
+  1999-11-04 lpd Edited comments slightly for automatic TOC extraction.
+  1999-10-18 lpd Fixed typo in header comment (ansi2knr rather than md5).
+  1999-05-03 lpd Original version.
+ */
+
+#include "md5lib.h"	/* ydnar */
+#include <string.h>
+
+/* ydnar: gtkradiant endian picking */
+#ifdef _SGI_SOURCE
+#define	__BIG_ENDIAN__
+#endif
+
+#ifdef __BIG_ENDIAN__
+#define ARCH_IS_BIG_ENDIAN  1
+#else
+#define ARCH_IS_BIG_ENDIAN  0
+#endif
+/* ydnar: end */
+
+#undef BYTE_ORDER	/* 1 = big-endian, -1 = little-endian, 0 = unknown */
+#ifdef ARCH_IS_BIG_ENDIAN
+#  define BYTE_ORDER (ARCH_IS_BIG_ENDIAN ? 1 : -1)
+#else
+#  define BYTE_ORDER 0
+#endif
+
+#define T_MASK ((md5_word_t)~0)
+#define T1 /* 0xd76aa478 */ (T_MASK ^ 0x28955b87)
+#define T2 /* 0xe8c7b756 */ (T_MASK ^ 0x173848a9)
+#define T3    0x242070db
+#define T4 /* 0xc1bdceee */ (T_MASK ^ 0x3e423111)
+#define T5 /* 0xf57c0faf */ (T_MASK ^ 0x0a83f050)
+#define T6    0x4787c62a
+#define T7 /* 0xa8304613 */ (T_MASK ^ 0x57cfb9ec)
+#define T8 /* 0xfd469501 */ (T_MASK ^ 0x02b96afe)
+#define T9    0x698098d8
+#define T10 /* 0x8b44f7af */ (T_MASK ^ 0x74bb0850)
+#define T11 /* 0xffff5bb1 */ (T_MASK ^ 0x0000a44e)
+#define T12 /* 0x895cd7be */ (T_MASK ^ 0x76a32841)
+#define T13    0x6b901122
+#define T14 /* 0xfd987193 */ (T_MASK ^ 0x02678e6c)
+#define T15 /* 0xa679438e */ (T_MASK ^ 0x5986bc71)
+#define T16    0x49b40821
+#define T17 /* 0xf61e2562 */ (T_MASK ^ 0x09e1da9d)
+#define T18 /* 0xc040b340 */ (T_MASK ^ 0x3fbf4cbf)
+#define T19    0x265e5a51
+#define T20 /* 0xe9b6c7aa */ (T_MASK ^ 0x16493855)
+#define T21 /* 0xd62f105d */ (T_MASK ^ 0x29d0efa2)
+#define T22    0x02441453
+#define T23 /* 0xd8a1e681 */ (T_MASK ^ 0x275e197e)
+#define T24 /* 0xe7d3fbc8 */ (T_MASK ^ 0x182c0437)
+#define T25    0x21e1cde6
+#define T26 /* 0xc33707d6 */ (T_MASK ^ 0x3cc8f829)
+#define T27 /* 0xf4d50d87 */ (T_MASK ^ 0x0b2af278)
+#define T28    0x455a14ed
+#define T29 /* 0xa9e3e905 */ (T_MASK ^ 0x561c16fa)
+#define T30 /* 0xfcefa3f8 */ (T_MASK ^ 0x03105c07)
+#define T31    0x676f02d9
+#define T32 /* 0x8d2a4c8a */ (T_MASK ^ 0x72d5b375)
+#define T33 /* 0xfffa3942 */ (T_MASK ^ 0x0005c6bd)
+#define T34 /* 0x8771f681 */ (T_MASK ^ 0x788e097e)
+#define T35    0x6d9d6122
+#define T36 /* 0xfde5380c */ (T_MASK ^ 0x021ac7f3)
+#define T37 /* 0xa4beea44 */ (T_MASK ^ 0x5b4115bb)
+#define T38    0x4bdecfa9
+#define T39 /* 0xf6bb4b60 */ (T_MASK ^ 0x0944b49f)
+#define T40 /* 0xbebfbc70 */ (T_MASK ^ 0x4140438f)
+#define T41    0x289b7ec6
+#define T42 /* 0xeaa127fa */ (T_MASK ^ 0x155ed805)
+#define T43 /* 0xd4ef3085 */ (T_MASK ^ 0x2b10cf7a)
+#define T44    0x04881d05
+#define T45 /* 0xd9d4d039 */ (T_MASK ^ 0x262b2fc6)
+#define T46 /* 0xe6db99e5 */ (T_MASK ^ 0x1924661a)
+#define T47    0x1fa27cf8
+#define T48 /* 0xc4ac5665 */ (T_MASK ^ 0x3b53a99a)
+#define T49 /* 0xf4292244 */ (T_MASK ^ 0x0bd6ddbb)
+#define T50    0x432aff97
+#define T51 /* 0xab9423a7 */ (T_MASK ^ 0x546bdc58)
+#define T52 /* 0xfc93a039 */ (T_MASK ^ 0x036c5fc6)
+#define T53    0x655b59c3
+#define T54 /* 0x8f0ccc92 */ (T_MASK ^ 0x70f3336d)
+#define T55 /* 0xffeff47d */ (T_MASK ^ 0x00100b82)
+#define T56 /* 0x85845dd1 */ (T_MASK ^ 0x7a7ba22e)
+#define T57    0x6fa87e4f
+#define T58 /* 0xfe2ce6e0 */ (T_MASK ^ 0x01d3191f)
+#define T59 /* 0xa3014314 */ (T_MASK ^ 0x5cfebceb)
+#define T60    0x4e0811a1
+#define T61 /* 0xf7537e82 */ (T_MASK ^ 0x08ac817d)
+#define T62 /* 0xbd3af235 */ (T_MASK ^ 0x42c50dca)
+#define T63    0x2ad7d2bb
+#define T64 /* 0xeb86d391 */ (T_MASK ^ 0x14792c6e)
+
+
+static void
+md5_process(md5_state_t *pms, const md5_byte_t *data /*[64]*/)
+{
+    md5_word_t
+	a = pms->abcd[0], b = pms->abcd[1],
+	c = pms->abcd[2], d = pms->abcd[3];
+    md5_word_t t;
+#if BYTE_ORDER > 0
+    /* Define storage only for big-endian CPUs. */
+    md5_word_t X[16];
+#else
+    /* Define storage for little-endian or both types of CPUs. */
+    md5_word_t xbuf[16];
+    const md5_word_t *X;
+#endif
+
+    {
+#if BYTE_ORDER == 0
+	/*
+	 * Determine dynamically whether this is a big-endian or
+	 * little-endian machine, since we can use a more efficient
+	 * algorithm on the latter.
+	 */
+	static const int w = 1;
+
+	if (*((const md5_byte_t *)&w)) /* dynamic little-endian */
+#endif
+#if BYTE_ORDER <= 0		/* little-endian */
+	{
+	    /*
+	     * On little-endian machines, we can process properly aligned
+	     * data without copying it.
+	     */
+	    if (!((data - (const md5_byte_t *)0) & 3)) {
+		/* data are properly aligned */
+		X = (const md5_word_t *)data;
+	    } else {
+		/* not aligned */
+		memcpy(xbuf, data, 64);
+		X = xbuf;
+	    }
+	}
+#endif
+#if BYTE_ORDER == 0
+	else			/* dynamic big-endian */
+#endif
+#if BYTE_ORDER >= 0		/* big-endian */
+	{
+	    /*
+	     * On big-endian machines, we must arrange the bytes in the
+	     * right order.
+	     */
+	    const md5_byte_t *xp = data;
+	    int i;
+
+#  if BYTE_ORDER == 0
+	    X = xbuf;		/* (dynamic only) */
+#  else
+#    define xbuf X		/* (static only) */
+#  endif
+	    for (i = 0; i < 16; ++i, xp += 4)
+		xbuf[i] = xp[0] + (xp[1] << 8) + (xp[2] << 16) + (xp[3] << 24);
+	}
+#endif
+    }
+
+#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32 - (n))))
+
+    /* Round 1. */
+    /* Let [abcd k s i] denote the operation
+       a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
+#define F(x, y, z) (((x) & (y)) | (~(x) & (z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + F(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+    /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  7,  T1);
+    SET(d, a, b, c,  1, 12,  T2);
+    SET(c, d, a, b,  2, 17,  T3);
+    SET(b, c, d, a,  3, 22,  T4);
+    SET(a, b, c, d,  4,  7,  T5);
+    SET(d, a, b, c,  5, 12,  T6);
+    SET(c, d, a, b,  6, 17,  T7);
+    SET(b, c, d, a,  7, 22,  T8);
+    SET(a, b, c, d,  8,  7,  T9);
+    SET(d, a, b, c,  9, 12, T10);
+    SET(c, d, a, b, 10, 17, T11);
+    SET(b, c, d, a, 11, 22, T12);
+    SET(a, b, c, d, 12,  7, T13);
+    SET(d, a, b, c, 13, 12, T14);
+    SET(c, d, a, b, 14, 17, T15);
+    SET(b, c, d, a, 15, 22, T16);
+#undef SET
+
+     /* Round 2. */
+     /* Let [abcd k s i] denote the operation
+          a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
+#define G(x, y, z) (((x) & (z)) | ((y) & ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + G(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  1,  5, T17);
+    SET(d, a, b, c,  6,  9, T18);
+    SET(c, d, a, b, 11, 14, T19);
+    SET(b, c, d, a,  0, 20, T20);
+    SET(a, b, c, d,  5,  5, T21);
+    SET(d, a, b, c, 10,  9, T22);
+    SET(c, d, a, b, 15, 14, T23);
+    SET(b, c, d, a,  4, 20, T24);
+    SET(a, b, c, d,  9,  5, T25);
+    SET(d, a, b, c, 14,  9, T26);
+    SET(c, d, a, b,  3, 14, T27);
+    SET(b, c, d, a,  8, 20, T28);
+    SET(a, b, c, d, 13,  5, T29);
+    SET(d, a, b, c,  2,  9, T30);
+    SET(c, d, a, b,  7, 14, T31);
+    SET(b, c, d, a, 12, 20, T32);
+#undef SET
+
+     /* Round 3. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
+#define H(x, y, z) ((x) ^ (y) ^ (z))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + H(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  5,  4, T33);
+    SET(d, a, b, c,  8, 11, T34);
+    SET(c, d, a, b, 11, 16, T35);
+    SET(b, c, d, a, 14, 23, T36);
+    SET(a, b, c, d,  1,  4, T37);
+    SET(d, a, b, c,  4, 11, T38);
+    SET(c, d, a, b,  7, 16, T39);
+    SET(b, c, d, a, 10, 23, T40);
+    SET(a, b, c, d, 13,  4, T41);
+    SET(d, a, b, c,  0, 11, T42);
+    SET(c, d, a, b,  3, 16, T43);
+    SET(b, c, d, a,  6, 23, T44);
+    SET(a, b, c, d,  9,  4, T45);
+    SET(d, a, b, c, 12, 11, T46);
+    SET(c, d, a, b, 15, 16, T47);
+    SET(b, c, d, a,  2, 23, T48);
+#undef SET
+
+     /* Round 4. */
+     /* Let [abcd k s t] denote the operation
+          a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
+#define I(x, y, z) ((y) ^ ((x) | ~(z)))
+#define SET(a, b, c, d, k, s, Ti)\
+  t = a + I(b,c,d) + X[k] + Ti;\
+  a = ROTATE_LEFT(t, s) + b
+     /* Do the following 16 operations. */
+    SET(a, b, c, d,  0,  6, T49);
+    SET(d, a, b, c,  7, 10, T50);
+    SET(c, d, a, b, 14, 15, T51);
+    SET(b, c, d, a,  5, 21, T52);
+    SET(a, b, c, d, 12,  6, T53);
+    SET(d, a, b, c,  3, 10, T54);
+    SET(c, d, a, b, 10, 15, T55);
+    SET(b, c, d, a,  1, 21, T56);
+    SET(a, b, c, d,  8,  6, T57);
+    SET(d, a, b, c, 15, 10, T58);
+    SET(c, d, a, b,  6, 15, T59);
+    SET(b, c, d, a, 13, 21, T60);
+    SET(a, b, c, d,  4,  6, T61);
+    SET(d, a, b, c, 11, 10, T62);
+    SET(c, d, a, b,  2, 15, T63);
+    SET(b, c, d, a,  9, 21, T64);
+#undef SET
+
+     /* Then perform the following additions. (That is increment each
+        of the four registers by the value it had before this block
+        was started.) */
+    pms->abcd[0] += a;
+    pms->abcd[1] += b;
+    pms->abcd[2] += c;
+    pms->abcd[3] += d;
+}
+
+void
+md5_init(md5_state_t *pms)
+{
+    pms->count[0] = pms->count[1] = 0;
+    pms->abcd[0] = 0x67452301;
+    pms->abcd[1] = /*0xefcdab89*/ T_MASK ^ 0x10325476;
+    pms->abcd[2] = /*0x98badcfe*/ T_MASK ^ 0x67452301;
+    pms->abcd[3] = 0x10325476;
+}
+
+void
+md5_append(md5_state_t *pms, const md5_byte_t *data, int nbytes)
+{
+    const md5_byte_t *p = data;
+    int left = nbytes;
+    int offset = (pms->count[0] >> 3) & 63;
+    md5_word_t nbits = (md5_word_t)(nbytes << 3);
+
+    if (nbytes <= 0)
+	return;
+
+    /* Update the message length. */
+    pms->count[1] += nbytes >> 29;
+    pms->count[0] += nbits;
+    if (pms->count[0] < nbits)
+	pms->count[1]++;
+
+    /* Process an initial partial block. */
+    if (offset) {
+	int copy = (offset + nbytes > 64 ? 64 - offset : nbytes);
+
+	memcpy(pms->buf + offset, p, copy);
+	if (offset + copy < 64)
+	    return;
+	p += copy;
+	left -= copy;
+	md5_process(pms, pms->buf);
+    }
+
+    /* Process full blocks. */
+    for (; left >= 64; p += 64, left -= 64)
+	md5_process(pms, p);
+
+    /* Process a final partial block. */
+    if (left)
+	memcpy(pms->buf, p, left);
+}
+
+void
+md5_finish(md5_state_t *pms, md5_byte_t digest[16])
+{
+    static const md5_byte_t pad[64] = {
+	0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
+    };
+    md5_byte_t data[8];
+    int i;
+
+    /* Save the length before padding. */
+    for (i = 0; i < 8; ++i)
+	data[i] = (md5_byte_t)(pms->count[i >> 2] >> ((i & 3) << 3));
+    /* Pad to 56 bytes mod 64. */
+    md5_append(pms, pad, ((55 - (pms->count[0] >> 3)) & 63) + 1);
+    /* Append the length. */
+    md5_append(pms, data, 8);
+    for (i = 0; i < 16; ++i)
+	digest[i] = (md5_byte_t)(pms->abcd[i >> 2] >> ((i & 3) << 3));
+}
diff --git a/libs/missing.h b/libs/missing.h
index a9288d5c..f374d1ac 100644
--- a/libs/missing.h
+++ b/libs/missing.h
@@ -1,212 +1,212 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _MISSING_H_
-#define _MISSING_H_
-
-// NOTE TTimo
-//   this goes along with str.h and provides various utility classes
-//   and portability defines
-//   the filename is a legecy issue, it would be better to clean that up
-//   in a central 'portability' lib
-
-#include <glib.h>
-#include <string.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <io.h>
-
-#define MyCopyFile(a,b) CopyFile(a,b,FALSE)
-
-#define S_ISDIR(mode) (mode & _S_IFDIR)
-#define R_OK 04
-#define mymkdir(a,b) _mkdir(a)
-
-#else
-
-#define MyCopyFile CopyFile
-#define mymkdir(a,b) mkdir(a,b)
-
-#endif
-
-#ifndef _WIN32
-
-// LZ: very ugly hacks
-inline int GetLastError () { return 0; };
-
-// temp stuff
-inline int GetPrivateProfileInt(char* a, char* b, int i, char* c) { return i; };
-#define VERIFY(a) a;
-int GetFullPathName(const char *lpFileName, int nBufferLength, char *lpBuffer, char **lpFilePart);
-bool CopyFile(const char *lpExistingFileName, const char *lpNewFileName);
-
-#ifndef APIENTRY
-#define APIENTRY
-#endif
-
-int MemorySize(void *ptr);
-#define _msize MemorySize
-
-#define MK_LBUTTON          0x0001
-#define MK_RBUTTON          0x0002
-#define MK_SHIFT            0x0004
-#define MK_CONTROL          0x0008
-#define MK_MBUTTON          0x0010
-
-#endif
-
-#define CString Str
-#include "str.h"
-
-class CPtrArray
-{
-public:
-  CPtrArray ()
-  { m_ptrs = g_ptr_array_new (); };
-  virtual ~CPtrArray ()
-  { g_ptr_array_free (m_ptrs, TRUE); };
-  
-  void* operator[](int i) const
-  { return g_ptr_array_index (m_ptrs,i); };
-  void* GetAt(int i) const
-  { return g_ptr_array_index (m_ptrs,i); };
-  int GetSize () const
-  { return m_ptrs->len; };
-  void Add (void* ptr)
-  { g_ptr_array_add (m_ptrs, ptr); };
-  void RemoveAll ()
-  { g_ptr_array_set_size (m_ptrs, 0); };
-  void RemoveAt(int index, int count = 1)
-  {
-    if ((index < 0) || (count < 0) || (count + index > (int)m_ptrs->len))
-      return;
-    for (; count > 0; count--)
-      g_ptr_array_remove_index (m_ptrs, index);
-  }
-  void InsertAt(int nStartIndex, CPtrArray* pNewArray)
-  {
-    for (int i = 0; i < pNewArray->GetSize(); i++)
-      InsertAt(nStartIndex+i, pNewArray->GetAt(i));
-  }
-  void InsertAt(int nIndex, void* newElement, int nCount = 1)
-  {
-    if ((guint32)nIndex >= m_ptrs->len)
-    {
-      g_ptr_array_set_size (m_ptrs, nIndex + nCount);  // grow so nIndex is valid
-    }
-    else
-    {
-      // inserting in the middle of the array
-      int nOldSize = m_ptrs->len;
-      g_ptr_array_set_size (m_ptrs, m_ptrs->len + nCount);
-      // shift old data up to fill gap
-      memmove(&m_ptrs->pdata[nIndex+nCount], &m_ptrs->pdata[nIndex],
-        (nOldSize-nIndex) * sizeof(gpointer));
-      
-      memset(&m_ptrs->pdata[nIndex], 0, nCount * sizeof(gpointer));
-    }
-    
-    // insert new value in the gap
-    while (nCount--)
-      m_ptrs->pdata[nIndex++] = newElement;
-  }
-  void Copy(const CPtrArray& src)
-  {
-    g_ptr_array_set_size (m_ptrs, src.m_ptrs->len);
-    memcpy (m_ptrs->pdata, src.m_ptrs->pdata, m_ptrs->len*sizeof(gpointer));
-  }
-  
-protected:
-  GPtrArray* m_ptrs;
-};
-
-typedef struct stringmap_s
-{
-  char* key;
-  char* value;
-} stringmap_t;
-
-class CMapStringToString
-{
-public:
-  CMapStringToString ()
-  { m_map = g_ptr_array_new (); };
-  ~CMapStringToString ()
-  {
-    for (guint32 i = 0; i < m_map->len; i++)
-      FreeElement ((stringmap_t*)g_ptr_array_index (m_map,i));
-    g_ptr_array_set_size (m_map, 0);
-    g_ptr_array_free (m_map, TRUE);
-  };
-  void SetAt(char* key, char* newValue)
-  {
-    for (guint32 i = 0; i < m_map->len; i++)
-    {
-      stringmap_t* entry = (stringmap_t*)g_ptr_array_index (m_map,i);
-      if (strcmp (entry->key, key) == 0)
-      {
-        g_free (entry->value);
-        entry->value = g_strdup (newValue);
-        return;
-      }
-    }
-    stringmap_t* entry = (stringmap_t*)g_malloc (sizeof (stringmap_t));
-    entry->key = g_strdup (key);
-    entry->value = g_strdup (newValue);
-    g_ptr_array_add (m_map, entry);
-  }
-  
-  bool Lookup(const char* key, CString& rValue) const
-  {
-    for (guint32 i = 0; i < m_map->len; i++)
-    {
-      stringmap_t* entry = (stringmap_t*)g_ptr_array_index (m_map,i);
-      if (strcmp (entry->key, key) == 0)
-      {
-        rValue = entry->value;
-        return true;
-      }
-    }
-    return false;
-  }
-  
-protected:
-  GPtrArray* m_map;
-  
-  void FreeElement(stringmap_t* elem)
-  { 
-    g_free (elem->key);
-    g_free (elem->value);
-    g_free (elem);
-  };
-};
-
-#endif // _MISSING_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _MISSING_H_
+#define _MISSING_H_
+
+// NOTE TTimo
+//   this goes along with str.h and provides various utility classes
+//   and portability defines
+//   the filename is a legecy issue, it would be better to clean that up
+//   in a central 'portability' lib
+
+#include <glib.h>
+#include <string.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <io.h>
+
+#define MyCopyFile(a,b) CopyFile(a,b,FALSE)
+
+#define S_ISDIR(mode) (mode & _S_IFDIR)
+#define R_OK 04
+#define mymkdir(a,b) _mkdir(a)
+
+#else
+
+#define MyCopyFile CopyFile
+#define mymkdir(a,b) mkdir(a,b)
+
+#endif
+
+#ifndef _WIN32
+
+// LZ: very ugly hacks
+inline int GetLastError () { return 0; };
+
+// temp stuff
+inline int GetPrivateProfileInt(char* a, char* b, int i, char* c) { return i; };
+#define VERIFY(a) a;
+int GetFullPathName(const char *lpFileName, int nBufferLength, char *lpBuffer, char **lpFilePart);
+bool CopyFile(const char *lpExistingFileName, const char *lpNewFileName);
+
+#ifndef APIENTRY
+#define APIENTRY
+#endif
+
+int MemorySize(void *ptr);
+#define _msize MemorySize
+
+#define MK_LBUTTON          0x0001
+#define MK_RBUTTON          0x0002
+#define MK_SHIFT            0x0004
+#define MK_CONTROL          0x0008
+#define MK_MBUTTON          0x0010
+
+#endif
+
+#define CString Str
+#include "str.h"
+
+class CPtrArray
+{
+public:
+  CPtrArray ()
+  { m_ptrs = g_ptr_array_new (); };
+  virtual ~CPtrArray ()
+  { g_ptr_array_free (m_ptrs, TRUE); };
+  
+  void* operator[](int i) const
+  { return g_ptr_array_index (m_ptrs,i); };
+  void* GetAt(int i) const
+  { return g_ptr_array_index (m_ptrs,i); };
+  int GetSize () const
+  { return m_ptrs->len; };
+  void Add (void* ptr)
+  { g_ptr_array_add (m_ptrs, ptr); };
+  void RemoveAll ()
+  { g_ptr_array_set_size (m_ptrs, 0); };
+  void RemoveAt(int index, int count = 1)
+  {
+    if ((index < 0) || (count < 0) || (count + index > (int)m_ptrs->len))
+      return;
+    for (; count > 0; count--)
+      g_ptr_array_remove_index (m_ptrs, index);
+  }
+  void InsertAt(int nStartIndex, CPtrArray* pNewArray)
+  {
+    for (int i = 0; i < pNewArray->GetSize(); i++)
+      InsertAt(nStartIndex+i, pNewArray->GetAt(i));
+  }
+  void InsertAt(int nIndex, void* newElement, int nCount = 1)
+  {
+    if ((guint32)nIndex >= m_ptrs->len)
+    {
+      g_ptr_array_set_size (m_ptrs, nIndex + nCount);  // grow so nIndex is valid
+    }
+    else
+    {
+      // inserting in the middle of the array
+      int nOldSize = m_ptrs->len;
+      g_ptr_array_set_size (m_ptrs, m_ptrs->len + nCount);
+      // shift old data up to fill gap
+      memmove(&m_ptrs->pdata[nIndex+nCount], &m_ptrs->pdata[nIndex],
+        (nOldSize-nIndex) * sizeof(gpointer));
+      
+      memset(&m_ptrs->pdata[nIndex], 0, nCount * sizeof(gpointer));
+    }
+    
+    // insert new value in the gap
+    while (nCount--)
+      m_ptrs->pdata[nIndex++] = newElement;
+  }
+  void Copy(const CPtrArray& src)
+  {
+    g_ptr_array_set_size (m_ptrs, src.m_ptrs->len);
+    memcpy (m_ptrs->pdata, src.m_ptrs->pdata, m_ptrs->len*sizeof(gpointer));
+  }
+  
+protected:
+  GPtrArray* m_ptrs;
+};
+
+typedef struct stringmap_s
+{
+  char* key;
+  char* value;
+} stringmap_t;
+
+class CMapStringToString
+{
+public:
+  CMapStringToString ()
+  { m_map = g_ptr_array_new (); };
+  ~CMapStringToString ()
+  {
+    for (guint32 i = 0; i < m_map->len; i++)
+      FreeElement ((stringmap_t*)g_ptr_array_index (m_map,i));
+    g_ptr_array_set_size (m_map, 0);
+    g_ptr_array_free (m_map, TRUE);
+  };
+  void SetAt(char* key, char* newValue)
+  {
+    for (guint32 i = 0; i < m_map->len; i++)
+    {
+      stringmap_t* entry = (stringmap_t*)g_ptr_array_index (m_map,i);
+      if (strcmp (entry->key, key) == 0)
+      {
+        g_free (entry->value);
+        entry->value = g_strdup (newValue);
+        return;
+      }
+    }
+    stringmap_t* entry = (stringmap_t*)g_malloc (sizeof (stringmap_t));
+    entry->key = g_strdup (key);
+    entry->value = g_strdup (newValue);
+    g_ptr_array_add (m_map, entry);
+  }
+  
+  bool Lookup(const char* key, CString& rValue) const
+  {
+    for (guint32 i = 0; i < m_map->len; i++)
+    {
+      stringmap_t* entry = (stringmap_t*)g_ptr_array_index (m_map,i);
+      if (strcmp (entry->key, key) == 0)
+      {
+        rValue = entry->value;
+        return true;
+      }
+    }
+    return false;
+  }
+  
+protected:
+  GPtrArray* m_map;
+  
+  void FreeElement(stringmap_t* elem)
+  { 
+    g_free (elem->key);
+    g_free (elem->value);
+    g_free (elem);
+  };
+};
+
+#endif // _MISSING_H_
diff --git a/libs/multimon.h b/libs/multimon.h
index 9a4e9ad7..638e353a 100644
--- a/libs/multimon.h
+++ b/libs/multimon.h
@@ -1,381 +1,381 @@
-#ifndef __MULTIMON_H
-#define __MULTIMON_H
-
-#ifdef _WIN32
-
-//=============================================================================
-//
-// MULTIMON
-// stub module that "stubs" multiple monitor APIs on pre-Memphis Win32 OSes
-//
-// By using this header your code will work unchanged on Win95,
-// you will get back correct values from GetSystemMetrics() for new metrics
-// and the new APIs will act like only one display is present.
-//
-// exactly one source must include this with COMPILE_MULTIMON_STUBS defined
-//
-//=============================================================================
-
-#ifdef __cplusplus
-extern "C" {            /* Assume C declarations for C++ */
-#endif  /* __cplusplus */
-
-//
-// if we are building on Win95/NT4 headers we need to declare this stuff ourselves
-//
-#ifndef SM_CMONITORS
-
-#define SM_XVIRTUALSCREEN                   76
-#define SM_YVIRTUALSCREEN                   77
-#define SM_CXVIRTUALSCREEN                  78
-#define SM_CYVIRTUALSCREEN                  79
-#define SM_CMONITORS                        80
-#define SM_SAMEDISPLAYFORMAT                81
-
-DECLARE_HANDLE(HMONITOR);
-
-#define MONITOR_DEFAULTTONULL               0x00000000
-#define MONITOR_DEFAULTTOPRIMARY            0x00000001
-#define MONITOR_DEFAULTTONEAREST            0x00000002
-
-#define MONITORINFOF_PRIMARY                0x00000001
-
-typedef struct tagMONITORINFO
-{
-  DWORD cbSize;
-  RECT  rcMonitor;
-  RECT  rcWork;
-  DWORD dwFlags;
-} MONITORINFO, *LPMONITORINFO;
-
-#define CCHDEVICENAME 32
-
-#ifdef __cplusplus
-typedef struct tagMONITORINFOEX : public tagMONITORINFO
-{
-  TCHAR       szDevice[CCHDEVICENAME];
-} MONITORINFOEX, *LPMONITORINFOEX;
-#else
-typedef struct
-{
-  MONITORINFO;
-  TCHAR       szDevice[CCHDEVICENAME];
-} MONITORINFOEX, *LPMONITORINFOEX;
-#endif
-
-typedef BOOL (CALLBACK* MONITORENUMPROC)(HMONITOR, HDC, LPRECT, LPARAM);
-
-#endif // SM_CMONITORS
-
-#ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
-
-typedef struct {
-  DWORD cb;
-  CHAR  DeviceName[32];
-  CHAR  DeviceString[128];
-  DWORD StateFlags;
-} DISPLAY_DEVICE;
-
-#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP  0x00000001
-#define DISPLAY_DEVICE_MULTI_DRIVER         0x00000002
-#define DISPLAY_DEVICE_PRIMARY_DEVICE       0x00000004
-#define DISPLAY_DEVICE_MIRRORING_DRIVER     0x00000008
-
-#endif
-#define DISPLAY_DEVICE_VGA                  0x00000010
-
-#ifndef ENUM_CURRENT_SETTINGS
-#define ENUM_CURRENT_SETTINGS               ((DWORD)-1)
-#define ENUM_REGISTRY_SETTINGS              ((DWORD)-2)
-#endif
-
-#undef GetMonitorInfo
-#undef GetSystemMetrics
-#undef MonitorFromWindow
-#undef MonitorFromRect
-#undef MonitorFromPoint
-#undef EnumDisplayMonitors
-#undef EnumDisplayDevices
-
-//
-// define this to compile the stubs
-// otherwise you get the declarations
-//
-#ifdef COMPILE_MULTIMON_STUBS
-
-  //---------------------------------------------------------------------------
-  //
-  // Implement the API stubs.
-  //
-  //---------------------------------------------------------------------------
-
-  int       (WINAPI* g_pfnGetSystemMetrics)(int);
-  HMONITOR  (WINAPI* g_pfnMonitorFromWindow)(HWND, BOOL);
-  HMONITOR  (WINAPI* g_pfnMonitorFromRect)(LPCRECT, BOOL);
-  HMONITOR  (WINAPI* g_pfnMonitorFromPoint)(POINT, BOOL);
-  BOOL      (WINAPI* g_pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO);
-  BOOL      (WINAPI* g_pfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
-  BOOL      (WINAPI *g_pfnEnumDisplayDevices)(LPVOID, int, DISPLAY_DEVICE *, DWORD);
-
-  BOOL InitMultipleMonitorStubs(void)
-  {
-    HMODULE hUser32;
-    static BOOL fInitDone;
-
-    if (fInitDone)
-    {
-      return g_pfnGetMonitorInfo != NULL;
-    }
-
-    if ((hUser32 = GetModuleHandle(TEXT("USER32"))) &&
-        (*(FARPROC*)&g_pfnGetSystemMetrics    = GetProcAddress(hUser32,"GetSystemMetrics")) &&
-        (*(FARPROC*)&g_pfnMonitorFromWindow   = GetProcAddress(hUser32,"MonitorFromWindow")) &&
-        (*(FARPROC*)&g_pfnMonitorFromRect     = GetProcAddress(hUser32,"MonitorFromRect")) &&
-        (*(FARPROC*)&g_pfnMonitorFromPoint    = GetProcAddress(hUser32,"MonitorFromPoint")) &&
-        (*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors")) &&
-    #ifdef UNICODE
-        (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoW")) &&
-        (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesW")) &&
-    #else
-        (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoA")) &&
-        (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesA")) &&
-    #endif
-        (GetSystemMetrics(SM_CXVIRTUALSCREEN) >= GetSystemMetrics(SM_CXSCREEN)) &&
-        (GetSystemMetrics(SM_CYVIRTUALSCREEN) >= GetSystemMetrics(SM_CYSCREEN)) )
-    {
-      fInitDone = TRUE;
-      return TRUE;
-    }
-    else
-    {
-      g_pfnGetSystemMetrics    = NULL;
-      g_pfnMonitorFromWindow   = NULL;
-      g_pfnMonitorFromRect     = NULL;
-      g_pfnMonitorFromPoint    = NULL;
-      g_pfnGetMonitorInfo      = NULL;
-      g_pfnEnumDisplayMonitors = NULL;
-      g_pfnEnumDisplayDevices  = NULL;
-
-      fInitDone = TRUE;
-      return FALSE;
-    }
-  }
-
-  //---------------------------------------------------------------------------
-  //
-  // "stubbed" implementations of Monitor APIs that work with the primary 	    //  display
-  //
-  //---------------------------------------------------------------------------
-
-  int WINAPI
-  xGetSystemMetrics(int nIndex)
-  {
-    if (InitMultipleMonitorStubs())
-      return g_pfnGetSystemMetrics(nIndex);
-
-    switch (nIndex)
-    {
-    case SM_CMONITORS:
-    case SM_SAMEDISPLAYFORMAT:
-      return 1;
-
-    case SM_XVIRTUALSCREEN:
-    case SM_YVIRTUALSCREEN:
-      return 0;
-
-    case SM_CXVIRTUALSCREEN:
-      nIndex = SM_CXSCREEN;
-      break;
-
-    case SM_CYVIRTUALSCREEN:
-      nIndex = SM_CYSCREEN;
-      break;
-    }
-
-    return GetSystemMetrics(nIndex);
-  }
-
-  #define xPRIMARY_MONITOR ((HMONITOR)0x42)
-
-  HMONITOR WINAPI
-  xMonitorFromRect(LPCRECT lprcScreenCoords,
-                   UINT uFlags)
-  {
-    if (InitMultipleMonitorStubs())
-      return g_pfnMonitorFromRect(lprcScreenCoords, uFlags);
-
-    if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
-        ((lprcScreenCoords->right > 0) &&
-        (lprcScreenCoords->bottom > 0) &&
-        (lprcScreenCoords->left < GetSystemMetrics(SM_CXSCREEN)) &&
-        (lprcScreenCoords->top < GetSystemMetrics(SM_CYSCREEN))))
-    {
-      return xPRIMARY_MONITOR;
-    }
-
-    return NULL;
-  }
-
-  HMONITOR WINAPI
-  xMonitorFromWindow(HWND hWnd,
-                     UINT uFlags)
-  {
-    RECT rc;
-
-    if (InitMultipleMonitorStubs())
-      return g_pfnMonitorFromWindow(hWnd, uFlags);
-
-    if (uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
-      return xPRIMARY_MONITOR;
-
-    if (GetWindowRect(hWnd, &rc))
-      return xMonitorFromRect(&rc, uFlags);
-
-    return NULL;
-  }
-
-  HMONITOR WINAPI
-  xMonitorFromPoint(POINT ptScreenCoords,
-                    UINT uFlags)
-  {
-    if (InitMultipleMonitorStubs())
-      return g_pfnMonitorFromPoint(ptScreenCoords, uFlags);
-
-    if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
-        ((ptScreenCoords.x >= 0) &&
-        (ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
-        (ptScreenCoords.y >= 0) &&
-        (ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
-    {
-      return xPRIMARY_MONITOR;
-    }
-
-    return NULL;
-  }
-
-  BOOL WINAPI
-  xGetMonitorInfo(HMONITOR hMonitor,
-                  LPMONITORINFO lpMonitorInfo)
-  {
-    RECT rcWork;
-
-    if (InitMultipleMonitorStubs())
-      return g_pfnGetMonitorInfo(hMonitor, lpMonitorInfo);
-
-    if ((hMonitor == xPRIMARY_MONITOR) && lpMonitorInfo &&
-        (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
-        SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0))
-    {
-      lpMonitorInfo->rcMonitor.left = 0;
-      lpMonitorInfo->rcMonitor.top  = 0;
-      lpMonitorInfo->rcMonitor.right  = GetSystemMetrics(SM_CXSCREEN);
-      lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
-      lpMonitorInfo->rcWork = rcWork;
-      lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
-
-      if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX))
-          lstrcpy(((MONITORINFOEX*)lpMonitorInfo)->szDevice,
-          TEXT("DISPLAY"));
-
-      return TRUE;
-    }
-
-    return FALSE;
-  }
-
-  BOOL WINAPI
-  xEnumDisplayMonitors(HDC hdc,
-                       LPCRECT lprcIntersect, 
-                       MONITORENUMPROC lpfnEnumProc,
-                       LPARAM lData)
-  {
-    RECT rcCallback, rcLimit;
-
-    if (InitMultipleMonitorStubs())
-      return g_pfnEnumDisplayMonitors(hdc, lprcIntersect, lpfnEnumProc, lData);
-    
-    if (!lpfnEnumProc)
-      return FALSE;
-
-    rcLimit.left   = 0;
-    rcLimit.top    = 0;
-    rcLimit.right  = GetSystemMetrics(SM_CXSCREEN);
-    rcLimit.bottom = GetSystemMetrics(SM_CYSCREEN);
-
-    if (hdc)
-    {
-      RECT rcClip;
-      HWND hWnd;
-
-      if ((hWnd = WindowFromDC(hdc)) == NULL)
-        return FALSE;
-
-      switch (GetClipBox(hdc, &rcClip))
-      {
-      default:
-        MapWindowPoints(NULL, hWnd, (LPPOINT)&rcLimit, 2);
-        if (IntersectRect(&rcCallback, &rcClip, &rcLimit))
-          break;
-      //fall thru
-      case NULLREGION:
-        return TRUE;
-      case ERROR:
-        return FALSE;
-      }
-
-      rcLimit = rcCallback;
-    }
-
-    if (!lprcIntersect || IntersectRect(&rcCallback, lprcIntersect, &rcLimit))
-    {
-      lpfnEnumProc(xPRIMARY_MONITOR, hdc, &rcCallback, lData);
-    }
-
-    return TRUE;
-  }
-
-  BOOL WINAPI
-  xEnumDisplayDevices(LPVOID lpReserved,
-                      int iDeviceNum, 
-                      DISPLAY_DEVICE * pDisplayDevice,
-                      DWORD dwFlags)
-  {
-    if (InitMultipleMonitorStubs())
-      return g_pfnEnumDisplayDevices(lpReserved, iDeviceNum, pDisplayDevice, dwFlags);
-    
-    return FALSE;
-  }
-
-  #undef xPRIMARY_MONITOR
-  #undef COMPILE_MULTIMON_STUBS
-
-#else    // COMPILE_MULTIMON_STUBS
-
-  extern int      WINAPI xGetSystemMetrics(int);
-  extern HMONITOR WINAPI xMonitorFromWindow(HWND, UINT);
-  extern HMONITOR WINAPI xMonitorFromRect(LPCRECT, UINT);
-  extern HMONITOR WINAPI xMonitorFromPoint(POINT, UINT);
-  extern BOOL     WINAPI xGetMonitorInfo(HMONITOR, LPMONITORINFO);
-  extern BOOL     WINAPI xEnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
-  extern BOOL     WINAPI xEnumDisplayDevices(LPVOID, int, DISPLAY_DEVICE *, DWORD);
-
-#endif    // COMPILE_MULTIMON_STUBS
-
-//
-// build defines that replace the regular APIs with our versions
-//
-#define GetSystemMetrics    xGetSystemMetrics
-#define MonitorFromWindow   xMonitorFromWindow
-#define MonitorFromRect     xMonitorFromRect
-#define MonitorFromPoint    xMonitorFromPoint
-#define GetMonitorInfo      xGetMonitorInfo
-#define EnumDisplayMonitors xEnumDisplayMonitors
-#define EnumDisplayDevices  xEnumDisplayDevices
-
-#ifdef __cplusplus
-}
-#endif // __cplusplus
-
-#endif // WIN32
-
+#ifndef __MULTIMON_H
+#define __MULTIMON_H
+
+#ifdef _WIN32
+
+//=============================================================================
+//
+// MULTIMON
+// stub module that "stubs" multiple monitor APIs on pre-Memphis Win32 OSes
+//
+// By using this header your code will work unchanged on Win95,
+// you will get back correct values from GetSystemMetrics() for new metrics
+// and the new APIs will act like only one display is present.
+//
+// exactly one source must include this with COMPILE_MULTIMON_STUBS defined
+//
+//=============================================================================
+
+#ifdef __cplusplus
+extern "C" {            /* Assume C declarations for C++ */
+#endif  /* __cplusplus */
+
+//
+// if we are building on Win95/NT4 headers we need to declare this stuff ourselves
+//
+#ifndef SM_CMONITORS
+
+#define SM_XVIRTUALSCREEN                   76
+#define SM_YVIRTUALSCREEN                   77
+#define SM_CXVIRTUALSCREEN                  78
+#define SM_CYVIRTUALSCREEN                  79
+#define SM_CMONITORS                        80
+#define SM_SAMEDISPLAYFORMAT                81
+
+DECLARE_HANDLE(HMONITOR);
+
+#define MONITOR_DEFAULTTONULL               0x00000000
+#define MONITOR_DEFAULTTOPRIMARY            0x00000001
+#define MONITOR_DEFAULTTONEAREST            0x00000002
+
+#define MONITORINFOF_PRIMARY                0x00000001
+
+typedef struct tagMONITORINFO
+{
+  DWORD cbSize;
+  RECT  rcMonitor;
+  RECT  rcWork;
+  DWORD dwFlags;
+} MONITORINFO, *LPMONITORINFO;
+
+#define CCHDEVICENAME 32
+
+#ifdef __cplusplus
+typedef struct tagMONITORINFOEX : public tagMONITORINFO
+{
+  TCHAR       szDevice[CCHDEVICENAME];
+} MONITORINFOEX, *LPMONITORINFOEX;
+#else
+typedef struct
+{
+  MONITORINFO;
+  TCHAR       szDevice[CCHDEVICENAME];
+} MONITORINFOEX, *LPMONITORINFOEX;
+#endif
+
+typedef BOOL (CALLBACK* MONITORENUMPROC)(HMONITOR, HDC, LPRECT, LPARAM);
+
+#endif // SM_CMONITORS
+
+#ifndef DISPLAY_DEVICE_ATTACHED_TO_DESKTOP
+
+typedef struct {
+  DWORD cb;
+  CHAR  DeviceName[32];
+  CHAR  DeviceString[128];
+  DWORD StateFlags;
+} DISPLAY_DEVICE;
+
+#define DISPLAY_DEVICE_ATTACHED_TO_DESKTOP  0x00000001
+#define DISPLAY_DEVICE_MULTI_DRIVER         0x00000002
+#define DISPLAY_DEVICE_PRIMARY_DEVICE       0x00000004
+#define DISPLAY_DEVICE_MIRRORING_DRIVER     0x00000008
+
+#endif
+#define DISPLAY_DEVICE_VGA                  0x00000010
+
+#ifndef ENUM_CURRENT_SETTINGS
+#define ENUM_CURRENT_SETTINGS               ((DWORD)-1)
+#define ENUM_REGISTRY_SETTINGS              ((DWORD)-2)
+#endif
+
+#undef GetMonitorInfo
+#undef GetSystemMetrics
+#undef MonitorFromWindow
+#undef MonitorFromRect
+#undef MonitorFromPoint
+#undef EnumDisplayMonitors
+#undef EnumDisplayDevices
+
+//
+// define this to compile the stubs
+// otherwise you get the declarations
+//
+#ifdef COMPILE_MULTIMON_STUBS
+
+  //---------------------------------------------------------------------------
+  //
+  // Implement the API stubs.
+  //
+  //---------------------------------------------------------------------------
+
+  int       (WINAPI* g_pfnGetSystemMetrics)(int);
+  HMONITOR  (WINAPI* g_pfnMonitorFromWindow)(HWND, BOOL);
+  HMONITOR  (WINAPI* g_pfnMonitorFromRect)(LPCRECT, BOOL);
+  HMONITOR  (WINAPI* g_pfnMonitorFromPoint)(POINT, BOOL);
+  BOOL      (WINAPI* g_pfnGetMonitorInfo)(HMONITOR, LPMONITORINFO);
+  BOOL      (WINAPI* g_pfnEnumDisplayMonitors)(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
+  BOOL      (WINAPI *g_pfnEnumDisplayDevices)(LPVOID, int, DISPLAY_DEVICE *, DWORD);
+
+  BOOL InitMultipleMonitorStubs(void)
+  {
+    HMODULE hUser32;
+    static BOOL fInitDone;
+
+    if (fInitDone)
+    {
+      return g_pfnGetMonitorInfo != NULL;
+    }
+
+    if ((hUser32 = GetModuleHandle(TEXT("USER32"))) &&
+        (*(FARPROC*)&g_pfnGetSystemMetrics    = GetProcAddress(hUser32,"GetSystemMetrics")) &&
+        (*(FARPROC*)&g_pfnMonitorFromWindow   = GetProcAddress(hUser32,"MonitorFromWindow")) &&
+        (*(FARPROC*)&g_pfnMonitorFromRect     = GetProcAddress(hUser32,"MonitorFromRect")) &&
+        (*(FARPROC*)&g_pfnMonitorFromPoint    = GetProcAddress(hUser32,"MonitorFromPoint")) &&
+        (*(FARPROC*)&g_pfnEnumDisplayMonitors = GetProcAddress(hUser32,"EnumDisplayMonitors")) &&
+    #ifdef UNICODE
+        (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoW")) &&
+        (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesW")) &&
+    #else
+        (*(FARPROC*)&g_pfnGetMonitorInfo      = GetProcAddress(hUser32,"GetMonitorInfoA")) &&
+        (*(FARPROC*)&g_pfnEnumDisplayDevices  = GetProcAddress(hUser32,"EnumDisplayDevicesA")) &&
+    #endif
+        (GetSystemMetrics(SM_CXVIRTUALSCREEN) >= GetSystemMetrics(SM_CXSCREEN)) &&
+        (GetSystemMetrics(SM_CYVIRTUALSCREEN) >= GetSystemMetrics(SM_CYSCREEN)) )
+    {
+      fInitDone = TRUE;
+      return TRUE;
+    }
+    else
+    {
+      g_pfnGetSystemMetrics    = NULL;
+      g_pfnMonitorFromWindow   = NULL;
+      g_pfnMonitorFromRect     = NULL;
+      g_pfnMonitorFromPoint    = NULL;
+      g_pfnGetMonitorInfo      = NULL;
+      g_pfnEnumDisplayMonitors = NULL;
+      g_pfnEnumDisplayDevices  = NULL;
+
+      fInitDone = TRUE;
+      return FALSE;
+    }
+  }
+
+  //---------------------------------------------------------------------------
+  //
+  // "stubbed" implementations of Monitor APIs that work with the primary 	    //  display
+  //
+  //---------------------------------------------------------------------------
+
+  int WINAPI
+  xGetSystemMetrics(int nIndex)
+  {
+    if (InitMultipleMonitorStubs())
+      return g_pfnGetSystemMetrics(nIndex);
+
+    switch (nIndex)
+    {
+    case SM_CMONITORS:
+    case SM_SAMEDISPLAYFORMAT:
+      return 1;
+
+    case SM_XVIRTUALSCREEN:
+    case SM_YVIRTUALSCREEN:
+      return 0;
+
+    case SM_CXVIRTUALSCREEN:
+      nIndex = SM_CXSCREEN;
+      break;
+
+    case SM_CYVIRTUALSCREEN:
+      nIndex = SM_CYSCREEN;
+      break;
+    }
+
+    return GetSystemMetrics(nIndex);
+  }
+
+  #define xPRIMARY_MONITOR ((HMONITOR)0x42)
+
+  HMONITOR WINAPI
+  xMonitorFromRect(LPCRECT lprcScreenCoords,
+                   UINT uFlags)
+  {
+    if (InitMultipleMonitorStubs())
+      return g_pfnMonitorFromRect(lprcScreenCoords, uFlags);
+
+    if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
+        ((lprcScreenCoords->right > 0) &&
+        (lprcScreenCoords->bottom > 0) &&
+        (lprcScreenCoords->left < GetSystemMetrics(SM_CXSCREEN)) &&
+        (lprcScreenCoords->top < GetSystemMetrics(SM_CYSCREEN))))
+    {
+      return xPRIMARY_MONITOR;
+    }
+
+    return NULL;
+  }
+
+  HMONITOR WINAPI
+  xMonitorFromWindow(HWND hWnd,
+                     UINT uFlags)
+  {
+    RECT rc;
+
+    if (InitMultipleMonitorStubs())
+      return g_pfnMonitorFromWindow(hWnd, uFlags);
+
+    if (uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST))
+      return xPRIMARY_MONITOR;
+
+    if (GetWindowRect(hWnd, &rc))
+      return xMonitorFromRect(&rc, uFlags);
+
+    return NULL;
+  }
+
+  HMONITOR WINAPI
+  xMonitorFromPoint(POINT ptScreenCoords,
+                    UINT uFlags)
+  {
+    if (InitMultipleMonitorStubs())
+      return g_pfnMonitorFromPoint(ptScreenCoords, uFlags);
+
+    if ((uFlags & (MONITOR_DEFAULTTOPRIMARY | MONITOR_DEFAULTTONEAREST)) ||
+        ((ptScreenCoords.x >= 0) &&
+        (ptScreenCoords.x < GetSystemMetrics(SM_CXSCREEN)) &&
+        (ptScreenCoords.y >= 0) &&
+        (ptScreenCoords.y < GetSystemMetrics(SM_CYSCREEN))))
+    {
+      return xPRIMARY_MONITOR;
+    }
+
+    return NULL;
+  }
+
+  BOOL WINAPI
+  xGetMonitorInfo(HMONITOR hMonitor,
+                  LPMONITORINFO lpMonitorInfo)
+  {
+    RECT rcWork;
+
+    if (InitMultipleMonitorStubs())
+      return g_pfnGetMonitorInfo(hMonitor, lpMonitorInfo);
+
+    if ((hMonitor == xPRIMARY_MONITOR) && lpMonitorInfo &&
+        (lpMonitorInfo->cbSize >= sizeof(MONITORINFO)) &&
+        SystemParametersInfo(SPI_GETWORKAREA, 0, &rcWork, 0))
+    {
+      lpMonitorInfo->rcMonitor.left = 0;
+      lpMonitorInfo->rcMonitor.top  = 0;
+      lpMonitorInfo->rcMonitor.right  = GetSystemMetrics(SM_CXSCREEN);
+      lpMonitorInfo->rcMonitor.bottom = GetSystemMetrics(SM_CYSCREEN);
+      lpMonitorInfo->rcWork = rcWork;
+      lpMonitorInfo->dwFlags = MONITORINFOF_PRIMARY;
+
+      if (lpMonitorInfo->cbSize >= sizeof(MONITORINFOEX))
+          lstrcpy(((MONITORINFOEX*)lpMonitorInfo)->szDevice,
+          TEXT("DISPLAY"));
+
+      return TRUE;
+    }
+
+    return FALSE;
+  }
+
+  BOOL WINAPI
+  xEnumDisplayMonitors(HDC hdc,
+                       LPCRECT lprcIntersect, 
+                       MONITORENUMPROC lpfnEnumProc,
+                       LPARAM lData)
+  {
+    RECT rcCallback, rcLimit;
+
+    if (InitMultipleMonitorStubs())
+      return g_pfnEnumDisplayMonitors(hdc, lprcIntersect, lpfnEnumProc, lData);
+    
+    if (!lpfnEnumProc)
+      return FALSE;
+
+    rcLimit.left   = 0;
+    rcLimit.top    = 0;
+    rcLimit.right  = GetSystemMetrics(SM_CXSCREEN);
+    rcLimit.bottom = GetSystemMetrics(SM_CYSCREEN);
+
+    if (hdc)
+    {
+      RECT rcClip;
+      HWND hWnd;
+
+      if ((hWnd = WindowFromDC(hdc)) == NULL)
+        return FALSE;
+
+      switch (GetClipBox(hdc, &rcClip))
+      {
+      default:
+        MapWindowPoints(NULL, hWnd, (LPPOINT)&rcLimit, 2);
+        if (IntersectRect(&rcCallback, &rcClip, &rcLimit))
+          break;
+      //fall thru
+      case NULLREGION:
+        return TRUE;
+      case ERROR:
+        return FALSE;
+      }
+
+      rcLimit = rcCallback;
+    }
+
+    if (!lprcIntersect || IntersectRect(&rcCallback, lprcIntersect, &rcLimit))
+    {
+      lpfnEnumProc(xPRIMARY_MONITOR, hdc, &rcCallback, lData);
+    }
+
+    return TRUE;
+  }
+
+  BOOL WINAPI
+  xEnumDisplayDevices(LPVOID lpReserved,
+                      int iDeviceNum, 
+                      DISPLAY_DEVICE * pDisplayDevice,
+                      DWORD dwFlags)
+  {
+    if (InitMultipleMonitorStubs())
+      return g_pfnEnumDisplayDevices(lpReserved, iDeviceNum, pDisplayDevice, dwFlags);
+    
+    return FALSE;
+  }
+
+  #undef xPRIMARY_MONITOR
+  #undef COMPILE_MULTIMON_STUBS
+
+#else    // COMPILE_MULTIMON_STUBS
+
+  extern int      WINAPI xGetSystemMetrics(int);
+  extern HMONITOR WINAPI xMonitorFromWindow(HWND, UINT);
+  extern HMONITOR WINAPI xMonitorFromRect(LPCRECT, UINT);
+  extern HMONITOR WINAPI xMonitorFromPoint(POINT, UINT);
+  extern BOOL     WINAPI xGetMonitorInfo(HMONITOR, LPMONITORINFO);
+  extern BOOL     WINAPI xEnumDisplayMonitors(HDC, LPCRECT, MONITORENUMPROC, LPARAM);
+  extern BOOL     WINAPI xEnumDisplayDevices(LPVOID, int, DISPLAY_DEVICE *, DWORD);
+
+#endif    // COMPILE_MULTIMON_STUBS
+
+//
+// build defines that replace the regular APIs with our versions
+//
+#define GetSystemMetrics    xGetSystemMetrics
+#define MonitorFromWindow   xMonitorFromWindow
+#define MonitorFromRect     xMonitorFromRect
+#define MonitorFromPoint    xMonitorFromPoint
+#define GetMonitorInfo      xGetMonitorInfo
+#define EnumDisplayMonitors xEnumDisplayMonitors
+#define EnumDisplayDevices  xEnumDisplayDevices
+
+#ifdef __cplusplus
+}
+#endif // __cplusplus
+
+#endif // WIN32
+
 #endif // __MULTIMON_H
\ No newline at end of file
diff --git a/libs/pak/unzip.h b/libs/pak/unzip.h
index d5c165dc..79a487e3 100644
--- a/libs/pak/unzip.h
+++ b/libs/pak/unzip.h
@@ -1,300 +1,300 @@
-
-#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
-/* like the STRICT of WIN32, we define a pointer that cannot be converted
-    from (void*) without cast */
-typedef struct TagunzFile__ { int unused; } unzFile__; 
-typedef unzFile__ *unzFile;
-#else
-typedef void* unzFile;
-#endif
-
-
-/* tm_unz contain date/time info */
-typedef struct tm_unz_s 
-{
-	unsigned int tm_sec;            /* seconds after the minute - [0,59] */
-	unsigned int tm_min;            /* minutes after the hour - [0,59] */
-	unsigned int tm_hour;           /* hours since midnight - [0,23] */
-	unsigned int tm_mday;           /* day of the month - [1,31] */
-	unsigned int tm_mon;            /* months since January - [0,11] */
-	unsigned int tm_year;           /* years - [1980..2044] */
-} tm_unz;
-
-/* unz_global_info structure contain global data about the ZIPfile
-   These data comes from the end of central dir */
-typedef struct unz_global_info_s
-{
-	unsigned long number_entry;         /* total number of entries in the central dir on this disk */
-	unsigned long size_comment;         /* size of the global comment of the zipfile */
-} unz_global_info;
-
-
-/* unz_file_info contain information about a file in the zipfile */
-typedef struct unz_file_info_s
-{
-    unsigned long version;              /* version made by                 2 unsigned chars */
-    unsigned long version_needed;       /* version needed to extract       2 unsigned chars */
-    unsigned long flag;                 /* general purpose bit flag        2 unsigned chars */
-    unsigned long compression_method;   /* compression method              2 unsigned chars */
-    unsigned long dosDate;              /* last mod file date in Dos fmt   4 unsigned chars */
-    unsigned long crc;                  /* crc-32                          4 unsigned chars */
-    unsigned long compressed_size;      /* compressed size                 4 unsigned chars */ 
-    unsigned long uncompressed_size;    /* uncompressed size               4 unsigned chars */ 
-    unsigned long size_filename;        /* filename length                 2 unsigned chars */
-    unsigned long size_file_extra;      /* extra field length              2 unsigned chars */
-    unsigned long size_file_comment;    /* file comment length             2 unsigned chars */
-
-    unsigned long disk_num_start;       /* disk number start               2 unsigned chars */
-    unsigned long internal_fa;          /* internal file attributes        2 unsigned chars */
-    unsigned long external_fa;          /* external file attributes        4 unsigned chars */
-
-    tm_unz tmu_date;
-} unz_file_info;
-
-/* unz_file_info_interntal contain internal info about a file in zipfile*/
-typedef struct unz_file_info_internal_s
-{
-    unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
-} unz_file_info_internal;
-
-typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
-typedef void   (*free_func) (void* opaque, void* address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    unsigned char    *next_in;  /* next input unsigned char */
-    unsigned int     avail_in;  /* number of unsigned chars available at next_in */
-    unsigned long    total_in;  /* total nb of input unsigned chars read so */
-
-    unsigned char    *next_out; /* next output unsigned char should be put there */
-    unsigned int     avail_out; /* remaining free space at next_out */
-    unsigned long    total_out; /* total nb of unsigned chars output so */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    unsigned char*     opaque;  /* private data object passed to zalloc and zfree */
-
-    int     data_type;  /* best guess about the data type: ascii or binary */
-    unsigned long   adler;      /* adler32 value of the uncompressed data */
-    unsigned long   reserved;   /* reserved for future use */
-} z_stream;
-
-typedef z_stream *z_streamp;
-
-
-/* file_in_zip_read_info_s contain internal information about a file in zipfile,
-    when reading and decompress it */
-typedef struct
-{
-	char  *read_buffer;         /* internal buffer for compressed data */
-	z_stream stream;            /* zLib stream structure for inflate */
-
-	unsigned long pos_in_zipfile;       /* position in unsigned char on the zipfile, for fseek*/
-	unsigned long stream_initialised;   /* flag set if stream structure is initialised*/
-
-	unsigned long offset_local_extrafield;/* offset of the static extra field */
-	unsigned int  size_local_extrafield;/* size of the static extra field */
-	unsigned long pos_local_extrafield;   /* position in the static extra field in read*/
-
-	unsigned long crc32;                /* crc32 of all data uncompressed */
-	unsigned long crc32_wait;           /* crc32 we must obtain after decompress all */
-	unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
-	unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
-	FILE* file;                 /* io structore of the zipfile */
-	unsigned long compression_method;   /* compression method (0==store) */
-	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
-} file_in_zip_read_info_s;
-
-
-/* unz_s contain internal information about the zipfile
-*/
-typedef struct
-{
-	FILE* file;                 /* io structore of the zipfile */
-	unz_global_info gi;       /* public global information */
-	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
-	unsigned long num_file;             /* number of the current file in the zipfile*/
-	unsigned long pos_in_central_dir;   /* pos of the current file in the central dir*/
-	unsigned long current_file_ok;      /* flag about the usability of the current file*/
-	unsigned long central_pos;          /* position of the beginning of the central dir*/
-
-	unsigned long size_central_dir;     /* size of the central directory  */
-	unsigned long offset_central_dir;   /* offset of start of central directory with
-								   respect to the starting disk number */
-
-	unz_file_info cur_file_info; /* public info about the current file in zip*/
-	unz_file_info_internal cur_file_info_internal; /* private info about it*/
-    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
-	                                    file if we are decompressing it */
-} unz_s;
-
-#define UNZ_OK                                  (0)
-#define UNZ_END_OF_LIST_OF_FILE (-100)
-#define UNZ_ERRNO               (Z_ERRNO)
-#define UNZ_EOF                 (0)
-#define UNZ_PARAMERROR                  (-102)
-#define UNZ_BADZIPFILE                  (-103)
-#define UNZ_INTERNALERROR               (-104)
-#define UNZ_CRCERROR                    (-105)
-
-#define UNZ_CASESENSITIVE		1
-#define UNZ_NOTCASESENSITIVE	2
-#define UNZ_OSDEFAULTCASE		0
-
-extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
-
-/*
-   Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-								or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
-	(like 1 on Unix, 2 on Windows)
-*/
-
-extern unzFile unzOpen (const char *path);
-extern unzFile unzReOpen (const char* path, unzFile file);
-
-/*
-  Open a Zip file. path contain the full pathname (by example,
-     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
-	 "zlib/zlib111.zip".
-	 If the zipfile cannot be opened (file don't exist or in not valid), the
-	   return value is NULL.
-     Else, the return value is a unzFile Handle, usable with other function
-	   of this unzip package.
-*/
-
-extern int unzClose (unzFile file);
-
-/*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
-  return UNZ_OK if there is no problem. */
-
-extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
-
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem. */
-
-
-extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
-
-/*
-  Get the global comment string of the ZipFile, in the szComment buffer.
-  uSizeBuf is the size of the szComment buffer.
-  return the number of unsigned char copied or an error code <0
-*/
-
-
-/***************************************************************************/
-/* Unzip package allow you browse the directory of the zipfile */
-
-extern int unzGoToFirstFile (unzFile file);
-
-/*
-  Set the current file of the zipfile to the first file.
-  return UNZ_OK if there is no problem
-*/
-
-extern int unzGoToNextFile (unzFile file);
-
-/*
-  Set the current file of the zipfile to the next file.
-  return UNZ_OK if there is no problem
-  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
-*/
-
-extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
-
-/*
-  Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzStringFileNameCompare
-
-  return value :
-  UNZ_OK if the file is found. It becomes the current file.
-  UNZ_END_OF_LIST_OF_FILE if the file is not found
-*/
-
-
-extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
-
-/*
-  Get Info about the current file
-  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
-	    the current file
-  if szFileName!=NULL, the filemane string will be copied in szFileName
-			(fileNameBufferSize is the size of the buffer)
-  if extraField!=NULL, the extra field information will be copied in extraField
-			(extraFieldBufferSize is the size of the buffer).
-			This is the Central-header version of the extra field
-  if szComment!=NULL, the comment string of the file will be copied in szComment
-			(commentBufferSize is the size of the buffer)
-*/
-
-/***************************************************************************/
-/* for reading the content of the current zipfile, you can open it, read data
-   from it, and close it (you can close it before reading all the file)
-   */
-
-extern int unzOpenCurrentFile (unzFile file);
-
-/*
-  Open for reading data the current file in the zipfile.
-  If there is no error, the return value is UNZ_OK.
-*/
-
-extern int unzCloseCurrentFile (unzFile file);
-
-/*
-  Close the file in zip opened with unzOpenCurrentFile
-  Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-
-												
-extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
-
-/*
-  Read unsigned chars from the current file (opened by unzOpenCurrentFile)
-  buf contain buffer where data must be copied
-  len the size of buf.
-
-  return the number of unsigned char copied if somes unsigned chars are copied
-  return 0 if the end of file was reached
-  return <0 with error code if there is an error
-    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-
-extern long unztell(unzFile file);
-
-/*
-  Give the current position in uncompressed data
-*/
-
-extern int unzeof (unzFile file);
-
-/*
-  return 1 if the end of file was reached, 0 elsewhere 
-*/
-
-extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
-
-/*
-  Read extra field from the current file (opened by unzOpenCurrentFile)
-  This is the local-header version of the extra field (sometimes, there is
-    more info in the local-header version than in the central-header)
-
-  if buf==NULL, it return the size of the local extra field
-
-  if buf!=NULL, len is the size of the buffer, the extra header is copied in
-	buf.
-  the return value is the number of unsigned chars copied in buf, or (if <0) 
-	the error code
-*/
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__; 
+typedef unzFile__ *unzFile;
+#else
+typedef void* unzFile;
+#endif
+
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s 
+{
+	unsigned int tm_sec;            /* seconds after the minute - [0,59] */
+	unsigned int tm_min;            /* minutes after the hour - [0,59] */
+	unsigned int tm_hour;           /* hours since midnight - [0,23] */
+	unsigned int tm_mday;           /* day of the month - [1,31] */
+	unsigned int tm_mon;            /* months since January - [0,11] */
+	unsigned int tm_year;           /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+   These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+	unsigned long number_entry;         /* total number of entries in the central dir on this disk */
+	unsigned long size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+    unsigned long version;              /* version made by                 2 unsigned chars */
+    unsigned long version_needed;       /* version needed to extract       2 unsigned chars */
+    unsigned long flag;                 /* general purpose bit flag        2 unsigned chars */
+    unsigned long compression_method;   /* compression method              2 unsigned chars */
+    unsigned long dosDate;              /* last mod file date in Dos fmt   4 unsigned chars */
+    unsigned long crc;                  /* crc-32                          4 unsigned chars */
+    unsigned long compressed_size;      /* compressed size                 4 unsigned chars */ 
+    unsigned long uncompressed_size;    /* uncompressed size               4 unsigned chars */ 
+    unsigned long size_filename;        /* filename length                 2 unsigned chars */
+    unsigned long size_file_extra;      /* extra field length              2 unsigned chars */
+    unsigned long size_file_comment;    /* file comment length             2 unsigned chars */
+
+    unsigned long disk_num_start;       /* disk number start               2 unsigned chars */
+    unsigned long internal_fa;          /* internal file attributes        2 unsigned chars */
+    unsigned long external_fa;          /* external file attributes        4 unsigned chars */
+
+    tm_unz tmu_date;
+} unz_file_info;
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+    unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
+} unz_file_info_internal;
+
+typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
+typedef void   (*free_func) (void* opaque, void* address);
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    unsigned char    *next_in;  /* next input unsigned char */
+    unsigned int     avail_in;  /* number of unsigned chars available at next_in */
+    unsigned long    total_in;  /* total nb of input unsigned chars read so */
+
+    unsigned char    *next_out; /* next output unsigned char should be put there */
+    unsigned int     avail_out; /* remaining free space at next_out */
+    unsigned long    total_out; /* total nb of unsigned chars output so */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    unsigned char*     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    unsigned long   adler;      /* adler32 value of the uncompressed data */
+    unsigned long   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream *z_streamp;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+    when reading and decompress it */
+typedef struct
+{
+	char  *read_buffer;         /* internal buffer for compressed data */
+	z_stream stream;            /* zLib stream structure for inflate */
+
+	unsigned long pos_in_zipfile;       /* position in unsigned char on the zipfile, for fseek*/
+	unsigned long stream_initialised;   /* flag set if stream structure is initialised*/
+
+	unsigned long offset_local_extrafield;/* offset of the static extra field */
+	unsigned int  size_local_extrafield;/* size of the static extra field */
+	unsigned long pos_local_extrafield;   /* position in the static extra field in read*/
+
+	unsigned long crc32;                /* crc32 of all data uncompressed */
+	unsigned long crc32_wait;           /* crc32 we must obtain after decompress all */
+	unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
+	unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
+	FILE* file;                 /* io structore of the zipfile */
+	unsigned long compression_method;   /* compression method (0==store) */
+	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+	FILE* file;                 /* io structore of the zipfile */
+	unz_global_info gi;       /* public global information */
+	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
+	unsigned long num_file;             /* number of the current file in the zipfile*/
+	unsigned long pos_in_central_dir;   /* pos of the current file in the central dir*/
+	unsigned long current_file_ok;      /* flag about the usability of the current file*/
+	unsigned long central_pos;          /* position of the beginning of the central dir*/
+
+	unsigned long size_central_dir;     /* size of the central directory  */
+	unsigned long offset_central_dir;   /* offset of start of central directory with
+								   respect to the starting disk number */
+
+	unz_file_info cur_file_info; /* public info about the current file in zip*/
+	unz_file_info_internal cur_file_info_internal; /* private info about it*/
+    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+	                                    file if we are decompressing it */
+} unz_s;
+
+#define UNZ_OK                                  (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO               (Z_ERRNO)
+#define UNZ_EOF                 (0)
+#define UNZ_PARAMERROR                  (-102)
+#define UNZ_BADZIPFILE                  (-103)
+#define UNZ_INTERNALERROR               (-104)
+#define UNZ_CRCERROR                    (-105)
+
+#define UNZ_CASESENSITIVE		1
+#define UNZ_NOTCASESENSITIVE	2
+#define UNZ_OSDEFAULTCASE		0
+
+extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
+
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+								or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+	(like 1 on Unix, 2 on Windows)
+*/
+
+extern unzFile unzOpen (const char *path);
+extern unzFile unzReOpen (const char* path, unzFile file);
+
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
+	 "zlib/zlib111.zip".
+	 If the zipfile cannot be opened (file don't exist or in not valid), the
+	   return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+	   of this unzip package.
+*/
+
+extern int unzClose (unzFile file);
+
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+
+extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+
+
+extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
+
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of unsigned char copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int unzGoToFirstFile (unzFile file);
+
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+
+extern int unzGoToNextFile (unzFile file);
+
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
+
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
+
+/*
+  Get Info about the current file
+  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+	    the current file
+  if szFileName!=NULL, the filemane string will be copied in szFileName
+			(fileNameBufferSize is the size of the buffer)
+  if extraField!=NULL, the extra field information will be copied in extraField
+			(extraFieldBufferSize is the size of the buffer).
+			This is the Central-header version of the extra field
+  if szComment!=NULL, the comment string of the file will be copied in szComment
+			(commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+   from it, and close it (you can close it before reading all the file)
+   */
+
+extern int unzOpenCurrentFile (unzFile file);
+
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int unzCloseCurrentFile (unzFile file);
+
+/*
+  Close the file in zip opened with unzOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+												
+extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
+
+/*
+  Read unsigned chars from the current file (opened by unzOpenCurrentFile)
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of unsigned char copied if somes unsigned chars are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern long unztell(unzFile file);
+
+/*
+  Give the current position in uncompressed data
+*/
+
+extern int unzeof (unzFile file);
+
+/*
+  return 1 if the end of file was reached, 0 elsewhere 
+*/
+
+extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
+
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+	buf.
+  the return value is the number of unsigned chars copied in buf, or (if <0) 
+	the error code
+*/
diff --git a/libs/pakstuff.h b/libs/pakstuff.h
index 4c709cae..340e8798 100644
--- a/libs/pakstuff.h
+++ b/libs/pakstuff.h
@@ -1,150 +1,150 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PAKSTUFF_H_
-#define _PAKSTUFF_H_
-
-#ifndef _WIN32
-#define WINAPI
-#else
-#include <windows.h>
-#endif
-
-#ifndef __cplusplus
-typedef int bool; // leo
-#endif
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-typedef char           Int8;
-typedef short          Int16;
-typedef long           Int32;
-typedef unsigned char  UInt8;
-typedef unsigned short UInt16;
-typedef unsigned long  UInt32;
-typedef float          Float32;
-typedef double         Float64;
-#define MAX(a, b)              (((a) > (b)) ? (a) : (b))
-#define MIN(a, b)              (((a) < (b)) ? (a) : (b))
-#define RANDOM(x)              (random() % (x))
-#define RANDOMIZE()             srand((int) time(NULL))
-
-#define FTYPE_UNKNOWN 0
-#define FTYPE_IWAD    1    /* .wad  "IWAD" */
-#define FTYPE_PWAD    2    /* .wad  "PWAD" */
-#define FTYPE_PACK    3    /* .pak  "PACK" */
-#define FTYPE_WAD2    4    /* .wad  "WAD2" */
-#define FTYPE_BSP     10   /* .bsp  (0x17 0x00 0x00 0x00) */
-#define FTYPE_MODEL   11   /* .mdl  "IDPO" */
-#define FTYPE_SPRITE  12   /* .spr  "IDSP" */
-#define FTYPE_WAV     20   /* .wav  "RIFF" */
-#define FTYPE_AU      21   /* .au   ".snd" */
-#define FTYPE_VOC     22   /* .voc  ?      */
-#define FTYPE_PBM_ASC 30   /* .pbm  "P1"   */
-#define FTYPE_PGM_ASC 31   /* .pgm  "P2"   */
-#define FTYPE_PPM_ASC 32   /* .ppm  "P3"   */
-#define FTYPE_PBM_RAW 33   /* .pbm  "P4"   */
-#define FTYPE_PGM_RAW 34   /* .pgm  "P5"   */
-#define FTYPE_PPM_RAW 35   /* .ppm  "P6"   */
-#define FTYPE_BMP     36   /* .bmp  "BM"   */
-#define FTYPE_GIF     37   /* .gif  "GIF8" */
-#define FTYPE_PCX     38   /* .pcx  (0x0a 0x05 0x01 0x08) */
-#define FTYPE_ERROR   -1
-
-#ifdef FAT_ENDIAN
-Bool	ReadInt16		(FILE *file, UInt16 huge *x);
-Bool	ReadInt32		(FILE *file, UInt32 huge *x);
-Bool	ReadFloat32		(FILE *file, Float32 huge *x);
-Bool	WriteInt16		(FILE *file, UInt16 huge *x);
-Bool	WriteInt32		(FILE *file, UInt32 huge *x);
-Bool	WriteFloat32	(FILE *file, Float32 huge *x);
-UInt16	SwapInt16		(UInt16 x);
-UInt32	SwapInt32		(UInt32 x);
-Float32	SwapFloat32		(Float32 x);
-#else
-#define ReadInt16(f, p)		ReadBytes((f), (p), 2L)
-#define ReadInt32(f, p)		ReadBytes((f), (p), 4L)
-#define ReadFloat32(f, p)	ReadBytes((f), (p), 4L)
-#define WriteInt16(f, p)	WriteBytes((f), (p), 2L)
-#define WriteInt32(f, p)	WriteBytes((f), (p), 4L)
-#define WriteFloat32(f, p)	WriteBytes((f), (p), 4L)
-#define SwapInt16(x)		(x)
-#define SwapInt32(x)		(x)
-#define SwapFloat32(x)		(x)
-#endif /* FAT_ENDIAN */
-
-#define FROMDISK	-1
-struct PACKDirectory
-{
-   char   name[56];             /* name of file */
-   UInt32 offset;               /* offset to start of data */
-   UInt32 size;                 /* byte size of data */
-};
-typedef struct PACKDirectory *PACKDirPtr;
-
-typedef struct DirListStruct
-{
-	char					dirname[1024];
-	int						from;
-	struct	DirListStruct	*next;
-} DIRLIST;
-
-typedef struct FileListStruct
-{
-	char					filename[1024];
-	UInt32					offset;
-	UInt32					size;
-	struct	FileListStruct	*next;
-} FILELIST;
-
-typedef struct DirStruct
-{
-	char				name[1024];
-	FILELIST			*files;
-	struct DirStruct	*next;
-} DIRECTORY;
-
-
-extern int m_nPAKIndex;
-extern FILE* pakfile[16];
-extern bool pakopen;
-extern DIRECTORY	*paktextures;
-
-void ClearFileList				(FILELIST **);
-void ClearDirList				(DIRLIST **);
-bool GetPackFileList				(FILELIST **, char *);
-bool GetPackTextureDirs			(DIRLIST **);
-bool AddToDirListAlphabetized	(DIRLIST **, char *, int);
-bool AddToFileListAlphabetized	(FILELIST **t, char *, UInt32, UInt32, bool);
-bool PakLoadFile					(const char *, void **);
-void OpenPakFile					(const char *);
-void ClosePakFile				(void);
-int  PakLoadAnyFile(const char *filename, void **bufferptr);
-void WINAPI InitPakFile(const char * pBasePath, const char *pName);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PAKSTUFF_H_
+#define _PAKSTUFF_H_
+
+#ifndef _WIN32
+#define WINAPI
+#else
+#include <windows.h>
+#endif
+
+#ifndef __cplusplus
+typedef int bool; // leo
+#endif
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef char           Int8;
+typedef short          Int16;
+typedef long           Int32;
+typedef unsigned char  UInt8;
+typedef unsigned short UInt16;
+typedef unsigned long  UInt32;
+typedef float          Float32;
+typedef double         Float64;
+#define MAX(a, b)              (((a) > (b)) ? (a) : (b))
+#define MIN(a, b)              (((a) < (b)) ? (a) : (b))
+#define RANDOM(x)              (random() % (x))
+#define RANDOMIZE()             srand((int) time(NULL))
+
+#define FTYPE_UNKNOWN 0
+#define FTYPE_IWAD    1    /* .wad  "IWAD" */
+#define FTYPE_PWAD    2    /* .wad  "PWAD" */
+#define FTYPE_PACK    3    /* .pak  "PACK" */
+#define FTYPE_WAD2    4    /* .wad  "WAD2" */
+#define FTYPE_BSP     10   /* .bsp  (0x17 0x00 0x00 0x00) */
+#define FTYPE_MODEL   11   /* .mdl  "IDPO" */
+#define FTYPE_SPRITE  12   /* .spr  "IDSP" */
+#define FTYPE_WAV     20   /* .wav  "RIFF" */
+#define FTYPE_AU      21   /* .au   ".snd" */
+#define FTYPE_VOC     22   /* .voc  ?      */
+#define FTYPE_PBM_ASC 30   /* .pbm  "P1"   */
+#define FTYPE_PGM_ASC 31   /* .pgm  "P2"   */
+#define FTYPE_PPM_ASC 32   /* .ppm  "P3"   */
+#define FTYPE_PBM_RAW 33   /* .pbm  "P4"   */
+#define FTYPE_PGM_RAW 34   /* .pgm  "P5"   */
+#define FTYPE_PPM_RAW 35   /* .ppm  "P6"   */
+#define FTYPE_BMP     36   /* .bmp  "BM"   */
+#define FTYPE_GIF     37   /* .gif  "GIF8" */
+#define FTYPE_PCX     38   /* .pcx  (0x0a 0x05 0x01 0x08) */
+#define FTYPE_ERROR   -1
+
+#ifdef FAT_ENDIAN
+Bool	ReadInt16		(FILE *file, UInt16 huge *x);
+Bool	ReadInt32		(FILE *file, UInt32 huge *x);
+Bool	ReadFloat32		(FILE *file, Float32 huge *x);
+Bool	WriteInt16		(FILE *file, UInt16 huge *x);
+Bool	WriteInt32		(FILE *file, UInt32 huge *x);
+Bool	WriteFloat32	(FILE *file, Float32 huge *x);
+UInt16	SwapInt16		(UInt16 x);
+UInt32	SwapInt32		(UInt32 x);
+Float32	SwapFloat32		(Float32 x);
+#else
+#define ReadInt16(f, p)		ReadBytes((f), (p), 2L)
+#define ReadInt32(f, p)		ReadBytes((f), (p), 4L)
+#define ReadFloat32(f, p)	ReadBytes((f), (p), 4L)
+#define WriteInt16(f, p)	WriteBytes((f), (p), 2L)
+#define WriteInt32(f, p)	WriteBytes((f), (p), 4L)
+#define WriteFloat32(f, p)	WriteBytes((f), (p), 4L)
+#define SwapInt16(x)		(x)
+#define SwapInt32(x)		(x)
+#define SwapFloat32(x)		(x)
+#endif /* FAT_ENDIAN */
+
+#define FROMDISK	-1
+struct PACKDirectory
+{
+   char   name[56];             /* name of file */
+   UInt32 offset;               /* offset to start of data */
+   UInt32 size;                 /* byte size of data */
+};
+typedef struct PACKDirectory *PACKDirPtr;
+
+typedef struct DirListStruct
+{
+	char					dirname[1024];
+	int						from;
+	struct	DirListStruct	*next;
+} DIRLIST;
+
+typedef struct FileListStruct
+{
+	char					filename[1024];
+	UInt32					offset;
+	UInt32					size;
+	struct	FileListStruct	*next;
+} FILELIST;
+
+typedef struct DirStruct
+{
+	char				name[1024];
+	FILELIST			*files;
+	struct DirStruct	*next;
+} DIRECTORY;
+
+
+extern int m_nPAKIndex;
+extern FILE* pakfile[16];
+extern bool pakopen;
+extern DIRECTORY	*paktextures;
+
+void ClearFileList				(FILELIST **);
+void ClearDirList				(DIRLIST **);
+bool GetPackFileList				(FILELIST **, char *);
+bool GetPackTextureDirs			(DIRLIST **);
+bool AddToDirListAlphabetized	(DIRLIST **, char *, int);
+bool AddToFileListAlphabetized	(FILELIST **t, char *, UInt32, UInt32, bool);
+bool PakLoadFile					(const char *, void **);
+void OpenPakFile					(const char *);
+void ClosePakFile				(void);
+int  PakLoadAnyFile(const char *filename, void **bufferptr);
+void WINAPI InitPakFile(const char * pBasePath, const char *pName);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/picomodel.h b/libs/picomodel.h
index 8642527a..1912b4cb 100644
--- a/libs/picomodel.h
+++ b/libs/picomodel.h
@@ -1,345 +1,345 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library 
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#ifndef PICOMODEL_H
-#define PICOMODEL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
-
-/* version */
-#define PICOMODEL_VERSION		"0.8.20"
-
-
-/* constants */
-#define PICO_GROW_SHADERS		16
-#define PICO_GROW_SURFACES		16
-#define PICO_GROW_VERTEXES		1024
-#define PICO_GROW_INDEXES		1024
-#define PICO_GROW_ARRAYS		8
-#define PICO_GROW_FACES			256
-#define PICO_MAX_SPECIAL		8
-#define PICO_MAX_DEFAULT_EXTS	4		/* max default extensions per module */
-
-
-/* types */
-typedef unsigned char			picoByte_t;
-typedef float					picoVec_t;
-typedef float					picoVec2_t[ 2 ];
-typedef float					picoVec3_t[ 3 ];
-typedef float					picoVec4_t[ 4 ];
-typedef picoByte_t   			picoColor_t[ 4 ];
-typedef int						picoIndex_t;
-
-typedef enum
-{
-	PICO_BAD,
-	PICO_TRIANGLES,
-	PICO_PATCH
-}
-picoSurfaceType_t;
-
-typedef enum
-{
-	PICO_NORMAL,
-	PICO_VERBOSE,
-	PICO_WARNING,
-	PICO_ERROR,
-	PICO_FATAL
-}
-picoPrintLevel_t;
-
-typedef struct picoSurface_s	picoSurface_t;
-typedef struct picoShader_s		picoShader_t;
-typedef struct picoModel_s		picoModel_t;
-typedef struct picoModule_s		picoModule_t;
-
-struct picoSurface_s
-{
-	void						*data;
-	
-	picoModel_t					*model;		/* owner model */
-	
-	picoSurfaceType_t			type;
-	char					 	*name;		/* sea: surface name */
-	picoShader_t				*shader;	/* ydnar: changed to ptr */
-	
-	int							numVertexes, maxVertexes;
-	picoVec3_t					*xyz;
-	picoVec3_t					*normal;
-	
-	int							numSTArrays, maxSTArrays;
-	picoVec2_t					**st;
-	
-	int							numColorArrays, maxColorArrays;
-	picoColor_t					**color;
-	
-	int							numIndexes, maxIndexes;
-	picoIndex_t					*index;
-
-	int							numFaceNormals, maxFaceNormals;
-	picoVec3_t					*faceNormal;
-
-	int							special[ PICO_MAX_SPECIAL ];
-};
-
-
-/* seaw0lf */
-struct picoShader_s
-{
-	picoModel_t					*model;			/* owner model */
-
-	char   						*name;			/* shader name */
-	char						*mapName;		/* shader file name (name of diffuse texturemap) */
-	picoColor_t					ambientColor;	/* ambient color of mesh (rgba) */
-	picoColor_t					diffuseColor;	/* diffuse color of mesh (rgba) */
-	picoColor_t					specularColor;	/* specular color of mesh (rgba) */
-	float						transparency;	/* transparency (0..1; 1 = 100% transparent) */
-	float						shininess;		/* shininess (0..128; 128 = 100% shiny) */
-};
-
-struct picoModel_s
-{
-	void						*data;
-	char						*name;			/* model name */
-	char						*fileName;		/* sea: model file name */
-	int							frameNum;		/* sea: renamed to frameNum */
-	int							numFrames;		/* sea: number of frames */
-	picoVec3_t					mins;
-	picoVec3_t					maxs;
-
-	int							numShaders, maxShaders;
-	picoShader_t				**shader;
-	
-	int							numSurfaces, maxSurfaces;
-	picoSurface_t				**surface;
-	
-	const picoModule_t			*module;		/* sea */
-};
-
-
-/* seaw0lf */
-/* return codes used by the validation callbacks; pmv is short */
-/* for 'pico module validation'. everything >PICO_PMV_OK means */
-/* that there was an error. */
-enum
-{
-	PICO_PMV_OK,			/* file valid */
-	PICO_PMV_ERROR,			/* file not valid */
-	PICO_PMV_ERROR_IDENT,	/* unknown file magic (aka ident) */
-	PICO_PMV_ERROR_VERSION,	/* unsupported file version */
-	PICO_PMV_ERROR_SIZE,	/* file size error */
-	PICO_PMV_ERROR_MEMORY,	/* out of memory error */
-};
-
-/* convenience (makes it easy to add new params to the callbacks) */
-#define PM_PARAMS_CANLOAD \
-	char *fileName, const void *buffer, int bufSize
-
-#define PM_PARAMS_LOAD \
-	char *fileName, int frameNum, const void *buffer, int bufSize
-
-#define PM_PARAMS_CANSAVE \
-	void
-
-#define PM_PARAMS_SAVE \
-	char *fileName, picoModel_t *model
-
-/* pico file format module structure */
-struct picoModule_s
-{
-	char					*version;								/* internal module version (e.g. '1.5-b2') */
-
-	char					*displayName;							/* string used to display in guis, etc. */
-	char					*authorName;							/* author name (eg. 'My Real Name') */
-	char					*copyright;								/* copyright year and holder (eg. '2002 My Company') */
-
-	char					*defaultExts[ PICO_MAX_DEFAULT_EXTS ];	/* default file extensions used by this file type */
-	int						(*canload)( PM_PARAMS_CANLOAD );		/* checks whether module can load given file (returns PMVR_*) */
-	picoModel_t				*(*load)( PM_PARAMS_LOAD );				/* parses model file data */
-	int						(*cansave)( PM_PARAMS_CANSAVE );		/* checks whether module can save (returns 1 or 0 and might spit out a message) */
-	int						(*save)( PM_PARAMS_SAVE );				/* saves a pico model in module's native model format */
-};
-
-
-
-/* general functions */
-int							PicoInit( void );
-void						PicoShutdown( void );
-int							PicoError( void );
-
-void 						PicoSetMallocFunc( void *(*func)( size_t ) );
-void 						PicoSetFreeFunc( void (*func)( void* ) );
-void 						PicoSetLoadFileFunc( void (*func)( char*, unsigned char**, int* ) );
-void 						PicoSetFreeFileFunc( void (*func)( void* ) );
-void 						PicoSetPrintFunc( void (*func)( int, const char* ) );
-
-const picoModule_t			**PicoModuleList( int *numModules );
-
-picoModel_t					*PicoLoadModel( char *name, int frameNum );
-
-
-/* model functions */
-picoModel_t					*PicoNewModel( void );
-void						PicoFreeModel( picoModel_t *model );
-int							PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces );
-
-
-/* shader functions */
-picoShader_t	   			*PicoNewShader( picoModel_t *model );
-void						PicoFreeShader( picoShader_t *shader );
-picoShader_t				*PicoFindShader( picoModel_t *model, char *name, int caseSensitive );
-
-
-/* surface functions */
-picoSurface_t				*PicoNewSurface( picoModel_t *model );
-void						PicoFreeSurface( picoSurface_t *surface );
-picoSurface_t				*PicoFindSurface( picoModel_t *model, char *name, int caseSensitive );
-int							PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals );
-
-
-/* setter functions */
-void						PicoSetModelName( picoModel_t *model, char *name );
-void						PicoSetModelFileName( picoModel_t *model, char *fileName );
-void						PicoSetModelFrameNum( picoModel_t *model, int frameNum );
-void						PicoSetModelNumFrames( picoModel_t *model, int numFrames );
-void						PicoSetModelData( picoModel_t *model, void *data );
-
-void 						PicoSetShaderName( picoShader_t *shader, char *name );
-void 						PicoSetShaderMapName( picoShader_t *shader, char *mapName );
-void 						PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color );
-void 						PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color );
-void 						PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color );
-void 						PicoSetShaderTransparency( picoShader_t *shader, float value );
-void 						PicoSetShaderShininess( picoShader_t *shader, float value );
-
-void						PicoSetSurfaceData( picoSurface_t *surface, void *data );
-void						PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type );
-void						PicoSetSurfaceName( picoSurface_t *surface, char *name );
-void						PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader );
-void						PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz );
-void						PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
-void						PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st );
-void						PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color );
-void						PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index );
-void						PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count );
-void						PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
-void						PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special );
-
-
-/* getter functions */
-char						*PicoGetModelName( picoModel_t *model );
-char						*PicoGetModelFileName( picoModel_t *model );
-int							PicoGetModelFrameNum( picoModel_t *model );
-int							PicoGetModelNumFrames( picoModel_t *model );
-void						*PicoGetModelData( picoModel_t *model );
-int 						PicoGetModelNumShaders( picoModel_t *model );
-picoShader_t				*PicoGetModelShader( picoModel_t *model, int num );	/* sea */
-int							PicoGetModelNumSurfaces( picoModel_t *model );
-picoSurface_t				*PicoGetModelSurface( picoModel_t *model, int num );
-int 						PicoGetModelTotalVertexes( picoModel_t *model );
-int 						PicoGetModelTotalIndexes( picoModel_t *model );
-
-char 						*PicoGetShaderName( picoShader_t *shader );
-char 						*PicoGetShaderMapName( picoShader_t *shader );
-picoByte_t 					*PicoGetShaderAmbientColor( picoShader_t *shader );
-picoByte_t 					*PicoGetShaderDiffuseColor( picoShader_t *shader );
-picoByte_t 					*PicoGetShaderSpecularColor( picoShader_t *shader );
-float						PicoGetShaderTransparency( picoShader_t *shader );
-float						PicoGetShaderShininess( picoShader_t *shader );
-
-void						*PicoGetSurfaceData( picoSurface_t *surface );
-char						*PicoGetSurfaceName( picoSurface_t *surface );		/* sea */
-picoSurfaceType_t			PicoGetSurfaceType( picoSurface_t *surface );
-char						*PicoGetSurfaceName( picoSurface_t *surface );
-picoShader_t				*PicoGetSurfaceShader( picoSurface_t *surface );	/* sea */
-
-int							PicoGetSurfaceNumVertexes( picoSurface_t *surface );
-picoVec_t					*PicoGetSurfaceXYZ( picoSurface_t *surface, int num );
-picoVec_t					*PicoGetSurfaceNormal( picoSurface_t *surface, int num );
-picoVec_t					*PicoGetSurfaceST( picoSurface_t *surface, int array, int num );
-picoByte_t					*PicoGetSurfaceColor( picoSurface_t *surface, int array, int num );
-int							PicoGetSurfaceNumIndexes( picoSurface_t *surface );
-picoIndex_t					PicoGetSurfaceIndex( picoSurface_t *surface, int num );
-picoIndex_t					*PicoGetSurfaceIndexes( picoSurface_t *surface, int num );
-picoVec_t					*PicoGetFaceNormal( picoSurface_t *surface, int num );
-int							PicoGetSurfaceSpecial( picoSurface_t *surface, int num );
-
-
-/* hashtable related functions */
-typedef struct picoVertexCombinationData_s
-{
-	picoVec3_t	xyz, normal;
-	picoVec2_t	st;
-	picoColor_t	color;
-} picoVertexCombinationData_t;
-
-typedef struct picoVertexCombinationHash_s
-{
-	picoVertexCombinationData_t	vcd;
-	picoIndex_t					index;
-
-	void						*data;
-
-	struct picoVertexCombinationHash_s	*next;
-} picoVertexCombinationHash_t;
-
-int							PicoGetHashTableSize( void );
-unsigned int				PicoVertexCoordGenerateHash( picoVec3_t xyz );
-picoVertexCombinationHash_t	**PicoNewVertexCombinationHashTable( void );
-void						PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable );
-picoVertexCombinationHash_t	*PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color );
-picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index );
-
-/* specialized functions */
-int							PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color );
-void						PicoFixSurfaceNormals( picoSurface_t *surface );
-int							PicoRemapModel( picoModel_t *model, char *remapFile );
-
-
-void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors, picoShader_t* shader );
-
-/* end marker */
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* -----------------------------------------------------------------------------
+
+PicoModel Library 
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef PICOMODEL_H
+#define PICOMODEL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+
+/* version */
+#define PICOMODEL_VERSION		"0.8.20"
+
+
+/* constants */
+#define PICO_GROW_SHADERS		16
+#define PICO_GROW_SURFACES		16
+#define PICO_GROW_VERTEXES		1024
+#define PICO_GROW_INDEXES		1024
+#define PICO_GROW_ARRAYS		8
+#define PICO_GROW_FACES			256
+#define PICO_MAX_SPECIAL		8
+#define PICO_MAX_DEFAULT_EXTS	4		/* max default extensions per module */
+
+
+/* types */
+typedef unsigned char			picoByte_t;
+typedef float					picoVec_t;
+typedef float					picoVec2_t[ 2 ];
+typedef float					picoVec3_t[ 3 ];
+typedef float					picoVec4_t[ 4 ];
+typedef picoByte_t   			picoColor_t[ 4 ];
+typedef int						picoIndex_t;
+
+typedef enum
+{
+	PICO_BAD,
+	PICO_TRIANGLES,
+	PICO_PATCH
+}
+picoSurfaceType_t;
+
+typedef enum
+{
+	PICO_NORMAL,
+	PICO_VERBOSE,
+	PICO_WARNING,
+	PICO_ERROR,
+	PICO_FATAL
+}
+picoPrintLevel_t;
+
+typedef struct picoSurface_s	picoSurface_t;
+typedef struct picoShader_s		picoShader_t;
+typedef struct picoModel_s		picoModel_t;
+typedef struct picoModule_s		picoModule_t;
+
+struct picoSurface_s
+{
+	void						*data;
+	
+	picoModel_t					*model;		/* owner model */
+	
+	picoSurfaceType_t			type;
+	char					 	*name;		/* sea: surface name */
+	picoShader_t				*shader;	/* ydnar: changed to ptr */
+	
+	int							numVertexes, maxVertexes;
+	picoVec3_t					*xyz;
+	picoVec3_t					*normal;
+	
+	int							numSTArrays, maxSTArrays;
+	picoVec2_t					**st;
+	
+	int							numColorArrays, maxColorArrays;
+	picoColor_t					**color;
+	
+	int							numIndexes, maxIndexes;
+	picoIndex_t					*index;
+
+	int							numFaceNormals, maxFaceNormals;
+	picoVec3_t					*faceNormal;
+
+	int							special[ PICO_MAX_SPECIAL ];
+};
+
+
+/* seaw0lf */
+struct picoShader_s
+{
+	picoModel_t					*model;			/* owner model */
+
+	char   						*name;			/* shader name */
+	char						*mapName;		/* shader file name (name of diffuse texturemap) */
+	picoColor_t					ambientColor;	/* ambient color of mesh (rgba) */
+	picoColor_t					diffuseColor;	/* diffuse color of mesh (rgba) */
+	picoColor_t					specularColor;	/* specular color of mesh (rgba) */
+	float						transparency;	/* transparency (0..1; 1 = 100% transparent) */
+	float						shininess;		/* shininess (0..128; 128 = 100% shiny) */
+};
+
+struct picoModel_s
+{
+	void						*data;
+	char						*name;			/* model name */
+	char						*fileName;		/* sea: model file name */
+	int							frameNum;		/* sea: renamed to frameNum */
+	int							numFrames;		/* sea: number of frames */
+	picoVec3_t					mins;
+	picoVec3_t					maxs;
+
+	int							numShaders, maxShaders;
+	picoShader_t				**shader;
+	
+	int							numSurfaces, maxSurfaces;
+	picoSurface_t				**surface;
+	
+	const picoModule_t			*module;		/* sea */
+};
+
+
+/* seaw0lf */
+/* return codes used by the validation callbacks; pmv is short */
+/* for 'pico module validation'. everything >PICO_PMV_OK means */
+/* that there was an error. */
+enum
+{
+	PICO_PMV_OK,			/* file valid */
+	PICO_PMV_ERROR,			/* file not valid */
+	PICO_PMV_ERROR_IDENT,	/* unknown file magic (aka ident) */
+	PICO_PMV_ERROR_VERSION,	/* unsupported file version */
+	PICO_PMV_ERROR_SIZE,	/* file size error */
+	PICO_PMV_ERROR_MEMORY,	/* out of memory error */
+};
+
+/* convenience (makes it easy to add new params to the callbacks) */
+#define PM_PARAMS_CANLOAD \
+	char *fileName, const void *buffer, int bufSize
+
+#define PM_PARAMS_LOAD \
+	char *fileName, int frameNum, const void *buffer, int bufSize
+
+#define PM_PARAMS_CANSAVE \
+	void
+
+#define PM_PARAMS_SAVE \
+	char *fileName, picoModel_t *model
+
+/* pico file format module structure */
+struct picoModule_s
+{
+	char					*version;								/* internal module version (e.g. '1.5-b2') */
+
+	char					*displayName;							/* string used to display in guis, etc. */
+	char					*authorName;							/* author name (eg. 'My Real Name') */
+	char					*copyright;								/* copyright year and holder (eg. '2002 My Company') */
+
+	char					*defaultExts[ PICO_MAX_DEFAULT_EXTS ];	/* default file extensions used by this file type */
+	int						(*canload)( PM_PARAMS_CANLOAD );		/* checks whether module can load given file (returns PMVR_*) */
+	picoModel_t				*(*load)( PM_PARAMS_LOAD );				/* parses model file data */
+	int						(*cansave)( PM_PARAMS_CANSAVE );		/* checks whether module can save (returns 1 or 0 and might spit out a message) */
+	int						(*save)( PM_PARAMS_SAVE );				/* saves a pico model in module's native model format */
+};
+
+
+
+/* general functions */
+int							PicoInit( void );
+void						PicoShutdown( void );
+int							PicoError( void );
+
+void 						PicoSetMallocFunc( void *(*func)( size_t ) );
+void 						PicoSetFreeFunc( void (*func)( void* ) );
+void 						PicoSetLoadFileFunc( void (*func)( char*, unsigned char**, int* ) );
+void 						PicoSetFreeFileFunc( void (*func)( void* ) );
+void 						PicoSetPrintFunc( void (*func)( int, const char* ) );
+
+const picoModule_t			**PicoModuleList( int *numModules );
+
+picoModel_t					*PicoLoadModel( char *name, int frameNum );
+
+
+/* model functions */
+picoModel_t					*PicoNewModel( void );
+void						PicoFreeModel( picoModel_t *model );
+int							PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces );
+
+
+/* shader functions */
+picoShader_t	   			*PicoNewShader( picoModel_t *model );
+void						PicoFreeShader( picoShader_t *shader );
+picoShader_t				*PicoFindShader( picoModel_t *model, char *name, int caseSensitive );
+
+
+/* surface functions */
+picoSurface_t				*PicoNewSurface( picoModel_t *model );
+void						PicoFreeSurface( picoSurface_t *surface );
+picoSurface_t				*PicoFindSurface( picoModel_t *model, char *name, int caseSensitive );
+int							PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals );
+
+
+/* setter functions */
+void						PicoSetModelName( picoModel_t *model, char *name );
+void						PicoSetModelFileName( picoModel_t *model, char *fileName );
+void						PicoSetModelFrameNum( picoModel_t *model, int frameNum );
+void						PicoSetModelNumFrames( picoModel_t *model, int numFrames );
+void						PicoSetModelData( picoModel_t *model, void *data );
+
+void 						PicoSetShaderName( picoShader_t *shader, char *name );
+void 						PicoSetShaderMapName( picoShader_t *shader, char *mapName );
+void 						PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color );
+void 						PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color );
+void 						PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color );
+void 						PicoSetShaderTransparency( picoShader_t *shader, float value );
+void 						PicoSetShaderShininess( picoShader_t *shader, float value );
+
+void						PicoSetSurfaceData( picoSurface_t *surface, void *data );
+void						PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type );
+void						PicoSetSurfaceName( picoSurface_t *surface, char *name );
+void						PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader );
+void						PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz );
+void						PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
+void						PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st );
+void						PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color );
+void						PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index );
+void						PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count );
+void						PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal );
+void						PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special );
+
+
+/* getter functions */
+char						*PicoGetModelName( picoModel_t *model );
+char						*PicoGetModelFileName( picoModel_t *model );
+int							PicoGetModelFrameNum( picoModel_t *model );
+int							PicoGetModelNumFrames( picoModel_t *model );
+void						*PicoGetModelData( picoModel_t *model );
+int 						PicoGetModelNumShaders( picoModel_t *model );
+picoShader_t				*PicoGetModelShader( picoModel_t *model, int num );	/* sea */
+int							PicoGetModelNumSurfaces( picoModel_t *model );
+picoSurface_t				*PicoGetModelSurface( picoModel_t *model, int num );
+int 						PicoGetModelTotalVertexes( picoModel_t *model );
+int 						PicoGetModelTotalIndexes( picoModel_t *model );
+
+char 						*PicoGetShaderName( picoShader_t *shader );
+char 						*PicoGetShaderMapName( picoShader_t *shader );
+picoByte_t 					*PicoGetShaderAmbientColor( picoShader_t *shader );
+picoByte_t 					*PicoGetShaderDiffuseColor( picoShader_t *shader );
+picoByte_t 					*PicoGetShaderSpecularColor( picoShader_t *shader );
+float						PicoGetShaderTransparency( picoShader_t *shader );
+float						PicoGetShaderShininess( picoShader_t *shader );
+
+void						*PicoGetSurfaceData( picoSurface_t *surface );
+char						*PicoGetSurfaceName( picoSurface_t *surface );		/* sea */
+picoSurfaceType_t			PicoGetSurfaceType( picoSurface_t *surface );
+char						*PicoGetSurfaceName( picoSurface_t *surface );
+picoShader_t				*PicoGetSurfaceShader( picoSurface_t *surface );	/* sea */
+
+int							PicoGetSurfaceNumVertexes( picoSurface_t *surface );
+picoVec_t					*PicoGetSurfaceXYZ( picoSurface_t *surface, int num );
+picoVec_t					*PicoGetSurfaceNormal( picoSurface_t *surface, int num );
+picoVec_t					*PicoGetSurfaceST( picoSurface_t *surface, int array, int num );
+picoByte_t					*PicoGetSurfaceColor( picoSurface_t *surface, int array, int num );
+int							PicoGetSurfaceNumIndexes( picoSurface_t *surface );
+picoIndex_t					PicoGetSurfaceIndex( picoSurface_t *surface, int num );
+picoIndex_t					*PicoGetSurfaceIndexes( picoSurface_t *surface, int num );
+picoVec_t					*PicoGetFaceNormal( picoSurface_t *surface, int num );
+int							PicoGetSurfaceSpecial( picoSurface_t *surface, int num );
+
+
+/* hashtable related functions */
+typedef struct picoVertexCombinationData_s
+{
+	picoVec3_t	xyz, normal;
+	picoVec2_t	st;
+	picoColor_t	color;
+} picoVertexCombinationData_t;
+
+typedef struct picoVertexCombinationHash_s
+{
+	picoVertexCombinationData_t	vcd;
+	picoIndex_t					index;
+
+	void						*data;
+
+	struct picoVertexCombinationHash_s	*next;
+} picoVertexCombinationHash_t;
+
+int							PicoGetHashTableSize( void );
+unsigned int				PicoVertexCoordGenerateHash( picoVec3_t xyz );
+picoVertexCombinationHash_t	**PicoNewVertexCombinationHashTable( void );
+void						PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable );
+picoVertexCombinationHash_t	*PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color );
+picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index );
+
+/* specialized functions */
+int							PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color );
+void						PicoFixSurfaceNormals( picoSurface_t *surface );
+int							PicoRemapModel( picoModel_t *model, char *remapFile );
+
+
+void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors, picoShader_t* shader );
+
+/* end marker */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/picomodel/lwo/clip.c b/libs/picomodel/lwo/clip.c
index 349222a4..8999f409 100644
--- a/libs/picomodel/lwo/clip.c
+++ b/libs/picomodel/lwo/clip.c
@@ -1,249 +1,249 @@
-/*
-======================================================================
-clip.c
-
-Functions for LWO2 image references.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-
-/*
-======================================================================
-lwFreeClip()
-
-Free memory used by an lwClip.
-====================================================================== */
-
-void lwFreeClip( lwClip *clip )
-{
-   if ( clip ) {
-      lwListFree( (void*) clip->ifilter, lwFreePlugin );
-      lwListFree( (void*) clip->pfilter, lwFreePlugin );
-      _pico_free( clip );
-   }
-}
-
-
-/*
-======================================================================
-lwGetClip()
-
-Read image references from a CLIP chunk in an LWO2 file.
-====================================================================== */
-
-lwClip *lwGetClip( picoMemStream_t *fp, int cksize )
-{
-   lwClip *clip;
-   lwPlugin *filt;
-   unsigned int id;
-   unsigned short sz;
-   int pos, rlen;
-
-
-   /* allocate the Clip structure */
-
-   clip = _pico_calloc( 1, sizeof( lwClip ));
-   if ( !clip ) goto Fail;
-
-   clip->contrast.val = 1.0f;
-   clip->brightness.val = 1.0f;
-   clip->saturation.val = 1.0f;
-   clip->gamma.val = 1.0f;
-
-   /* remember where we started */
-
-   set_flen( 0 );
-   pos = _pico_memstream_tell( fp );
-
-   /* index */
-
-   clip->index = getI4( fp );
-
-   /* first subchunk header */
-
-   clip->type = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   sz += sz & 1;
-   set_flen( 0 );
-
-   switch ( clip->type ) {
-      case ID_STIL:
-         clip->source.still.name = getS0( fp );
-         break;
-
-      case ID_ISEQ:
-         clip->source.seq.digits  = getU1( fp );
-         clip->source.seq.flags   = getU1( fp );
-         clip->source.seq.offset  = getI2( fp );
-         getU2( fp );  /* not sure what this is yet */
-         clip->source.seq.start   = getI2( fp );
-         clip->source.seq.end     = getI2( fp );
-         clip->source.seq.prefix  = getS0( fp );
-         clip->source.seq.suffix  = getS0( fp );
-         break;
-
-      case ID_ANIM:
-         clip->source.anim.name   = getS0( fp );
-         clip->source.anim.server = getS0( fp );
-         rlen = get_flen();
-         clip->source.anim.data   = getbytes( fp, sz - rlen );
-         break;
-
-      case ID_XREF:
-         clip->source.xref.index  = getI4( fp );
-         clip->source.xref.string = getS0( fp );
-         break;
-
-      case ID_STCC:
-         clip->source.cycle.lo   = getI2( fp );
-         clip->source.cycle.hi   = getI2( fp );
-         clip->source.cycle.name = getS0( fp );
-         break;
-
-      default:
-         break;
-   }
-
-   /* error while reading current subchunk? */
-
-   rlen = get_flen();
-   if ( rlen < 0 || rlen > sz ) goto Fail;
-
-   /* skip unread parts of the current subchunk */
-
-   if ( rlen < sz )
-      _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-   /* end of the CLIP chunk? */
-
-   rlen = _pico_memstream_tell( fp ) - pos;
-   if ( cksize < rlen ) goto Fail;
-   if ( cksize == rlen )
-      return clip;
-
-   /* process subchunks as they're encountered */
-
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_TIME:
-            clip->start_time = getF4( fp );
-            clip->duration = getF4( fp );
-            clip->frame_rate = getF4( fp );
-            break;
-
-         case ID_CONT:
-            clip->contrast.val = getF4( fp );
-            clip->contrast.eindex = getVX( fp );
-            break;
-
-         case ID_BRIT:
-            clip->brightness.val = getF4( fp );
-            clip->brightness.eindex = getVX( fp );
-            break;
-
-         case ID_SATR:
-            clip->saturation.val = getF4( fp );
-            clip->saturation.eindex = getVX( fp );
-            break;
-
-         case ID_HUE:
-            clip->hue.val = getF4( fp );
-            clip->hue.eindex = getVX( fp );
-            break;
-
-         case ID_GAMM:
-            clip->gamma.val = getF4( fp );
-            clip->gamma.eindex = getVX( fp );
-            break;
-
-         case ID_NEGA:
-            clip->negative = getU2( fp );
-            break;
-
-         case ID_IFLT:
-         case ID_PFLT:
-            filt = _pico_calloc( 1, sizeof( lwPlugin ));
-            if ( !filt ) goto Fail;
-
-            filt->name = getS0( fp );
-            filt->flags = getU2( fp );
-            rlen = get_flen();
-            filt->data = getbytes( fp, sz - rlen );
-
-            if ( id == ID_IFLT ) {
-               lwListAdd( &clip->ifilter, filt );
-               clip->nifilters++;
-            }
-            else {
-               lwListAdd( &clip->pfilter, filt );
-               clip->npfilters++;
-            }
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) goto Fail;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the CLIP chunk? */
-
-      rlen = _pico_memstream_tell( fp ) - pos;
-      if ( cksize < rlen ) goto Fail;
-      if ( cksize == rlen ) break;
-
-      /* get the next chunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) goto Fail;
-   }
-
-   return clip;
-
-Fail:
-   lwFreeClip( clip );
-   return NULL;
-}
-
-
-/*
-======================================================================
-lwFindClip()
-
-Returns an lwClip pointer, given a clip index.
-====================================================================== */
-
-lwClip *lwFindClip( lwClip *list, int index )
-{
-   lwClip *clip;
-
-   clip = list;
-   while ( clip ) {
-      if ( clip->index == index ) break;
-      clip = clip->next;
-   }
-   return clip;
-}
+/*
+======================================================================
+clip.c
+
+Functions for LWO2 image references.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+
+/*
+======================================================================
+lwFreeClip()
+
+Free memory used by an lwClip.
+====================================================================== */
+
+void lwFreeClip( lwClip *clip )
+{
+   if ( clip ) {
+      lwListFree( (void*) clip->ifilter, lwFreePlugin );
+      lwListFree( (void*) clip->pfilter, lwFreePlugin );
+      _pico_free( clip );
+   }
+}
+
+
+/*
+======================================================================
+lwGetClip()
+
+Read image references from a CLIP chunk in an LWO2 file.
+====================================================================== */
+
+lwClip *lwGetClip( picoMemStream_t *fp, int cksize )
+{
+   lwClip *clip;
+   lwPlugin *filt;
+   unsigned int id;
+   unsigned short sz;
+   int pos, rlen;
+
+
+   /* allocate the Clip structure */
+
+   clip = _pico_calloc( 1, sizeof( lwClip ));
+   if ( !clip ) goto Fail;
+
+   clip->contrast.val = 1.0f;
+   clip->brightness.val = 1.0f;
+   clip->saturation.val = 1.0f;
+   clip->gamma.val = 1.0f;
+
+   /* remember where we started */
+
+   set_flen( 0 );
+   pos = _pico_memstream_tell( fp );
+
+   /* index */
+
+   clip->index = getI4( fp );
+
+   /* first subchunk header */
+
+   clip->type = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   sz += sz & 1;
+   set_flen( 0 );
+
+   switch ( clip->type ) {
+      case ID_STIL:
+         clip->source.still.name = getS0( fp );
+         break;
+
+      case ID_ISEQ:
+         clip->source.seq.digits  = getU1( fp );
+         clip->source.seq.flags   = getU1( fp );
+         clip->source.seq.offset  = getI2( fp );
+         getU2( fp );  /* not sure what this is yet */
+         clip->source.seq.start   = getI2( fp );
+         clip->source.seq.end     = getI2( fp );
+         clip->source.seq.prefix  = getS0( fp );
+         clip->source.seq.suffix  = getS0( fp );
+         break;
+
+      case ID_ANIM:
+         clip->source.anim.name   = getS0( fp );
+         clip->source.anim.server = getS0( fp );
+         rlen = get_flen();
+         clip->source.anim.data   = getbytes( fp, sz - rlen );
+         break;
+
+      case ID_XREF:
+         clip->source.xref.index  = getI4( fp );
+         clip->source.xref.string = getS0( fp );
+         break;
+
+      case ID_STCC:
+         clip->source.cycle.lo   = getI2( fp );
+         clip->source.cycle.hi   = getI2( fp );
+         clip->source.cycle.name = getS0( fp );
+         break;
+
+      default:
+         break;
+   }
+
+   /* error while reading current subchunk? */
+
+   rlen = get_flen();
+   if ( rlen < 0 || rlen > sz ) goto Fail;
+
+   /* skip unread parts of the current subchunk */
+
+   if ( rlen < sz )
+      _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+   /* end of the CLIP chunk? */
+
+   rlen = _pico_memstream_tell( fp ) - pos;
+   if ( cksize < rlen ) goto Fail;
+   if ( cksize == rlen )
+      return clip;
+
+   /* process subchunks as they're encountered */
+
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_TIME:
+            clip->start_time = getF4( fp );
+            clip->duration = getF4( fp );
+            clip->frame_rate = getF4( fp );
+            break;
+
+         case ID_CONT:
+            clip->contrast.val = getF4( fp );
+            clip->contrast.eindex = getVX( fp );
+            break;
+
+         case ID_BRIT:
+            clip->brightness.val = getF4( fp );
+            clip->brightness.eindex = getVX( fp );
+            break;
+
+         case ID_SATR:
+            clip->saturation.val = getF4( fp );
+            clip->saturation.eindex = getVX( fp );
+            break;
+
+         case ID_HUE:
+            clip->hue.val = getF4( fp );
+            clip->hue.eindex = getVX( fp );
+            break;
+
+         case ID_GAMM:
+            clip->gamma.val = getF4( fp );
+            clip->gamma.eindex = getVX( fp );
+            break;
+
+         case ID_NEGA:
+            clip->negative = getU2( fp );
+            break;
+
+         case ID_IFLT:
+         case ID_PFLT:
+            filt = _pico_calloc( 1, sizeof( lwPlugin ));
+            if ( !filt ) goto Fail;
+
+            filt->name = getS0( fp );
+            filt->flags = getU2( fp );
+            rlen = get_flen();
+            filt->data = getbytes( fp, sz - rlen );
+
+            if ( id == ID_IFLT ) {
+               lwListAdd( &clip->ifilter, filt );
+               clip->nifilters++;
+            }
+            else {
+               lwListAdd( &clip->pfilter, filt );
+               clip->npfilters++;
+            }
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) goto Fail;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the CLIP chunk? */
+
+      rlen = _pico_memstream_tell( fp ) - pos;
+      if ( cksize < rlen ) goto Fail;
+      if ( cksize == rlen ) break;
+
+      /* get the next chunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) goto Fail;
+   }
+
+   return clip;
+
+Fail:
+   lwFreeClip( clip );
+   return NULL;
+}
+
+
+/*
+======================================================================
+lwFindClip()
+
+Returns an lwClip pointer, given a clip index.
+====================================================================== */
+
+lwClip *lwFindClip( lwClip *list, int index )
+{
+   lwClip *clip;
+
+   clip = list;
+   while ( clip ) {
+      if ( clip->index == index ) break;
+      clip = clip->next;
+   }
+   return clip;
+}
diff --git a/libs/picomodel/lwo/envelope.c b/libs/picomodel/lwo/envelope.c
index 4ece5951..e3e281ff 100644
--- a/libs/picomodel/lwo/envelope.c
+++ b/libs/picomodel/lwo/envelope.c
@@ -1,600 +1,600 @@
-/*
-======================================================================
-envelope.c
-
-Envelope functions for an LWO2 reader.
-
-Ernie Wright  16 Nov 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-/*
-======================================================================
-lwFreeEnvelope()
-
-Free the memory used by an lwEnvelope.
-====================================================================== */
-
-void lwFreeEnvelope( lwEnvelope *env )
-{
-   if ( env ) {
-      if ( env->name ) _pico_free( env->name );
-      lwListFree( env->key, _pico_free );
-      lwListFree( env->cfilter, lwFreePlugin );
-      _pico_free( env );
-   }
-}
-
-
-static int compare_keys( lwKey *k1, lwKey *k2 )
-{
-   return k1->time > k2->time ? 1 : k1->time < k2->time ? -1 : 0;
-}
-
-
-/*
-======================================================================
-lwGetEnvelope()
-
-Read an ENVL chunk from an LWO2 file.
-====================================================================== */
-
-lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize )
-{
-   lwEnvelope *env;
-   lwKey *key;
-   lwPlugin *plug;
-   unsigned int id;
-   unsigned short sz;
-   float f[ 4 ];
-   int i, nparams, pos, rlen;
-
-
-   /* allocate the Envelope structure */
-
-   env = _pico_calloc( 1, sizeof( lwEnvelope ));
-   if ( !env ) goto Fail;
-
-   /* remember where we started */
-
-   set_flen( 0 );
-   pos = _pico_memstream_tell( fp );
-
-   /* index */
-
-   env->index = getVX( fp );
-
-   /* first subchunk header */
-
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   /* process subchunks as they're encountered */
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_TYPE:
-            env->type = getU2( fp );
-            break;
-
-         case ID_NAME:
-            env->name = getS0( fp );
-            break;
-
-         case ID_PRE:
-            env->behavior[ 0 ] = getU2( fp );
-            break;
-
-         case ID_POST:
-            env->behavior[ 1 ] = getU2( fp );
-            break;
-
-         case ID_KEY:
-            key = _pico_calloc( 1, sizeof( lwKey ));
-            if ( !key ) goto Fail;
-            key->time = getF4( fp );
-            key->value = getF4( fp );
-            lwListInsert( &env->key, key, compare_keys );
-            env->nkeys++;
-            break;
-
-         case ID_SPAN:
-            if ( !key ) goto Fail;
-            key->shape = getU4( fp );
-
-            nparams = ( sz - 4 ) / 4;
-            if ( nparams > 4 ) nparams = 4;
-            for ( i = 0; i < nparams; i++ )
-               f[ i ] = getF4( fp );
-
-            switch ( key->shape ) {
-               case ID_TCB:
-                  key->tension = f[ 0 ];
-                  key->continuity = f[ 1 ];
-                  key->bias = f[ 2 ];
-                  break;
-
-               case ID_BEZI:
-               case ID_HERM:
-               case ID_BEZ2:
-                  for ( i = 0; i < nparams; i++ )
-                     key->param[ i ] = f[ i ];
-                  break;
-            }
-            break;
-
-         case ID_CHAN:
-            plug = _pico_calloc( 1, sizeof( lwPlugin ));
-            if ( !plug ) goto Fail;
-
-            plug->name = getS0( fp );
-            plug->flags = getU2( fp );
-            plug->data = getbytes( fp, sz - get_flen() );
-
-            lwListAdd( &env->cfilter, plug );
-            env->ncfilters++;
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) goto Fail;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the ENVL chunk? */
-
-      rlen = _pico_memstream_tell( fp ) - pos;
-      if ( cksize < rlen ) goto Fail;
-      if ( cksize == rlen ) break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) goto Fail;
-   }
-
-   return env;
-
-Fail:
-   lwFreeEnvelope( env );
-   return NULL;
-}
-
-
-/*
-======================================================================
-lwFindEnvelope()
-
-Returns an lwEnvelope pointer, given an envelope index.
-====================================================================== */
-
-lwEnvelope *lwFindEnvelope( lwEnvelope *list, int index )
-{
-   lwEnvelope *env;
-
-   env = list;
-   while ( env ) {
-      if ( env->index == index ) break;
-      env = env->next;
-   }
-   return env;
-}
-
-
-/*
-======================================================================
-range()
-
-Given the value v of a periodic function, returns the equivalent value
-v2 in the principal interval [lo, hi].  If i isn't NULL, it receives
-the number of wavelengths between v and v2.
-
-   v2 = v - i * (hi - lo)
-
-For example, range( 3 pi, 0, 2 pi, i ) returns pi, with i = 1.
-====================================================================== */
-
-static float range( float v, float lo, float hi, int *i )
-{
-   float v2, r = hi - lo;
-
-   if ( r == 0.0 ) {
-      if ( i ) *i = 0;
-      return lo;
-   }
-
-   v2 = lo + v - r * ( float ) floor(( double ) v / r );
-   if ( i ) *i = -( int )(( v2 - v ) / r + ( v2 > v ? 0.5 : -0.5 ));
-
-   return v2;
-}
-
-
-/*
-======================================================================
-hermite()
-
-Calculate the Hermite coefficients.
-====================================================================== */
-
-static void hermite( float t, float *h1, float *h2, float *h3, float *h4 )
-{
-   float t2, t3;
-
-   t2 = t * t;
-   t3 = t * t2;
-
-   *h2 = 3.0f * t2 - t3 - t3;
-   *h1 = 1.0f - *h2;
-   *h4 = t3 - t2;
-   *h3 = *h4 - t2 + t;
-}
-
-
-/*
-======================================================================
-bezier()
-
-Interpolate the value of a 1D Bezier curve.
-====================================================================== */
-
-static float bezier( float x0, float x1, float x2, float x3, float t )
-{
-   float a, b, c, t2, t3;
-
-   t2 = t * t;
-   t3 = t2 * t;
-
-   c = 3.0f * ( x1 - x0 );
-   b = 3.0f * ( x2 - x1 ) - c;
-   a = x3 - x0 - c - b;
-
-   return a * t3 + b * t2 + c * t + x0;
-}
-
-
-/*
-======================================================================
-bez2_time()
-
-Find the t for which bezier() returns the input time.  The handle
-endpoints of a BEZ2 curve represent the control points, and these have
-(time, value) coordinates, so time is used as both a coordinate and a
-parameter for this curve type.
-====================================================================== */
-
-static float bez2_time( float x0, float x1, float x2, float x3, float time,
-   float *t0, float *t1 )
-{
-   float v, t;
-
-   t = *t0 + ( *t1 - *t0 ) * 0.5f;
-   v = bezier( x0, x1, x2, x3, t );
-   if ( fabs( time - v ) > .0001f ) {
-      if ( v > time )
-         *t1 = t;
-      else
-         *t0 = t;
-      return bez2_time( x0, x1, x2, x3, time, t0, t1 );
-   }
-   else
-      return t;
-}
-
-
-/*
-======================================================================
-bez2()
-
-Interpolate the value of a BEZ2 curve.
-====================================================================== */
-
-static float bez2( lwKey *key0, lwKey *key1, float time )
-{
-   float x, y, t, t0 = 0.0f, t1 = 1.0f;
-
-   if ( key0->shape == ID_BEZ2 )
-      x = key0->time + key0->param[ 2 ];
-   else
-      x = key0->time + ( key1->time - key0->time ) / 3.0f;
-
-   t = bez2_time( key0->time, x, key1->time + key1->param[ 0 ], key1->time,
-      time, &t0, &t1 );
-
-   if ( key0->shape == ID_BEZ2 )
-      y = key0->value + key0->param[ 3 ];
-   else
-      y = key0->value + key0->param[ 1 ] / 3.0f;
-
-   return bezier( key0->value, y, key1->param[ 1 ] + key1->value, key1->value, t );
-}
-
-
-/*
-======================================================================
-outgoing()
-
-Return the outgoing tangent to the curve at key0.  The value returned
-for the BEZ2 case is used when extrapolating a linear pre behavior and
-when interpolating a non-BEZ2 span.
-====================================================================== */
-
-static float outgoing( lwKey *key0, lwKey *key1 )
-{
-   float a, b, d, t, out;
-
-   switch ( key0->shape )
-   {
-      case ID_TCB:
-         a = ( 1.0f - key0->tension )
-           * ( 1.0f + key0->continuity )
-           * ( 1.0f + key0->bias );
-         b = ( 1.0f - key0->tension )
-           * ( 1.0f - key0->continuity )
-           * ( 1.0f - key0->bias );
-         d = key1->value - key0->value;
-
-         if ( key0->prev ) {
-            t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
-            out = t * ( a * ( key0->value - key0->prev->value ) + b * d );
-         }
-         else
-            out = b * d;
-         break;
-
-      case ID_LINE:
-         d = key1->value - key0->value;
-         if ( key0->prev ) {
-            t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
-            out = t * ( key0->value - key0->prev->value + d );
-         }
-         else
-            out = d;
-         break;
-
-      case ID_BEZI:
-      case ID_HERM:
-         out = key0->param[ 1 ];
-         if ( key0->prev )
-            out *= ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
-         break;
-
-      case ID_BEZ2:
-         out = key0->param[ 3 ] * ( key1->time - key0->time );
-         if ( fabs( key0->param[ 2 ] ) > 1e-5f )
-            out /= key0->param[ 2 ];
-         else
-            out *= 1e5f;
-         break;
-
-      case ID_STEP:
-      default:
-         out = 0.0f;
-         break;
-   }
-
-   return out;
-}
-
-
-/*
-======================================================================
-incoming()
-
-Return the incoming tangent to the curve at key1.  The value returned
-for the BEZ2 case is used when extrapolating a linear post behavior.
-====================================================================== */
-
-static float incoming( lwKey *key0, lwKey *key1 )
-{
-   float a, b, d, t, in;
-
-   switch ( key1->shape )
-   {
-      case ID_LINE:
-         d = key1->value - key0->value;
-         if ( key1->next ) {
-            t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
-            in = t * ( key1->next->value - key1->value + d );
-         }
-         else
-            in = d;
-         break;
-
-      case ID_TCB:
-         a = ( 1.0f - key1->tension )
-           * ( 1.0f - key1->continuity )
-           * ( 1.0f + key1->bias );
-         b = ( 1.0f - key1->tension )
-           * ( 1.0f + key1->continuity )
-           * ( 1.0f - key1->bias );
-         d = key1->value - key0->value;
-
-         if ( key1->next ) {
-            t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
-            in = t * ( b * ( key1->next->value - key1->value ) + a * d );
-         }
-         else
-            in = a * d;
-         break;
-
-      case ID_BEZI:
-      case ID_HERM:
-         in = key1->param[ 0 ];
-         if ( key1->next )
-            in *= ( key1->time - key0->time ) / ( key1->next->time - key0->time );
-         break;
-         return in;
-
-      case ID_BEZ2:
-         in = key1->param[ 1 ] * ( key1->time - key0->time );
-         if ( fabs( key1->param[ 0 ] ) > 1e-5f )
-            in /= key1->param[ 0 ];
-         else
-            in *= 1e5f;
-         break;
-
-      case ID_STEP:
-      default:
-         in = 0.0f;
-         break;
-   }
-
-   return in;
-}
-
-
-/*
-======================================================================
-evalEnvelope()
-
-Given a list of keys and a time, returns the interpolated value of the
-envelope at that time.
-====================================================================== */
-
-float evalEnvelope( lwEnvelope *env, float time )
-{
-   lwKey *key0, *key1, *skey, *ekey;
-   float t, h1, h2, h3, h4, in, out, offset = 0.0f;
-   int noff;
-
-
-   /* if there's no key, the value is 0 */
-
-   if ( env->nkeys == 0 ) return 0.0f;
-
-   /* if there's only one key, the value is constant */
-
-   if ( env->nkeys == 1 )
-      return env->key->value;
-
-   /* find the first and last keys */
-
-   skey = ekey = env->key;
-   while ( ekey->next ) ekey = ekey->next;
-
-   /* use pre-behavior if time is before first key time */
-
-   if ( time < skey->time ) {
-      switch ( env->behavior[ 0 ] )
-      {
-         case BEH_RESET:
-            return 0.0f;
-
-         case BEH_CONSTANT:
-            return skey->value;
-
-         case BEH_REPEAT:
-            time = range( time, skey->time, ekey->time, NULL );
-            break;
-
-         case BEH_OSCILLATE:
-            time = range( time, skey->time, ekey->time, &noff );
-            if ( noff % 2 )
-               time = ekey->time - skey->time - time;
-            break;
-
-         case BEH_OFFSET:
-            time = range( time, skey->time, ekey->time, &noff );
-            offset = noff * ( ekey->value - skey->value );
-            break;
-
-         case BEH_LINEAR:
-            out = outgoing( skey, skey->next )
-                / ( skey->next->time - skey->time );
-            return out * ( time - skey->time ) + skey->value;
-      }
-   }
-
-   /* use post-behavior if time is after last key time */
-
-   else if ( time > ekey->time ) {
-      switch ( env->behavior[ 1 ] )
-      {
-         case BEH_RESET:
-            return 0.0f;
-
-         case BEH_CONSTANT:
-            return ekey->value;
-
-         case BEH_REPEAT:
-            time = range( time, skey->time, ekey->time, NULL );
-            break;
-
-         case BEH_OSCILLATE:
-            time = range( time, skey->time, ekey->time, &noff );
-            if ( noff % 2 )
-               time = ekey->time - skey->time - time;
-            break;
-
-         case BEH_OFFSET:
-            time = range( time, skey->time, ekey->time, &noff );
-            offset = noff * ( ekey->value - skey->value );
-            break;
-
-         case BEH_LINEAR:
-            in = incoming( ekey->prev, ekey )
-               / ( ekey->time - ekey->prev->time );
-            return in * ( time - ekey->time ) + ekey->value;
-      }
-   }
-
-   /* get the endpoints of the interval being evaluated */
-
-   key0 = env->key;
-   while ( time > key0->next->time )
-      key0 = key0->next;
-   key1 = key0->next;
-
-   /* check for singularities first */
-
-   if ( time == key0->time )
-      return key0->value + offset;
-   else if ( time == key1->time )
-      return key1->value + offset;
-
-   /* get interval length, time in [0, 1] */
-
-   t = ( time - key0->time ) / ( key1->time - key0->time );
-
-   /* interpolate */
-
-   switch ( key1->shape )
-   {
-      case ID_TCB:
-      case ID_BEZI:
-      case ID_HERM:
-         out = outgoing( key0, key1 );
-         in = incoming( key0, key1 );
-         hermite( t, &h1, &h2, &h3, &h4 );
-         return h1 * key0->value + h2 * key1->value + h3 * out + h4 * in + offset;
-
-      case ID_BEZ2:
-         return bez2( key0, key1, time ) + offset;
-
-      case ID_LINE:
-         return key0->value + t * ( key1->value - key0->value ) + offset;
-
-      case ID_STEP:
-         return key0->value + offset;
-
-      default:
-         return offset;
-   }
-}
+/*
+======================================================================
+envelope.c
+
+Envelope functions for an LWO2 reader.
+
+Ernie Wright  16 Nov 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+/*
+======================================================================
+lwFreeEnvelope()
+
+Free the memory used by an lwEnvelope.
+====================================================================== */
+
+void lwFreeEnvelope( lwEnvelope *env )
+{
+   if ( env ) {
+      if ( env->name ) _pico_free( env->name );
+      lwListFree( env->key, _pico_free );
+      lwListFree( env->cfilter, lwFreePlugin );
+      _pico_free( env );
+   }
+}
+
+
+static int compare_keys( lwKey *k1, lwKey *k2 )
+{
+   return k1->time > k2->time ? 1 : k1->time < k2->time ? -1 : 0;
+}
+
+
+/*
+======================================================================
+lwGetEnvelope()
+
+Read an ENVL chunk from an LWO2 file.
+====================================================================== */
+
+lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize )
+{
+   lwEnvelope *env;
+   lwKey *key;
+   lwPlugin *plug;
+   unsigned int id;
+   unsigned short sz;
+   float f[ 4 ];
+   int i, nparams, pos, rlen;
+
+
+   /* allocate the Envelope structure */
+
+   env = _pico_calloc( 1, sizeof( lwEnvelope ));
+   if ( !env ) goto Fail;
+
+   /* remember where we started */
+
+   set_flen( 0 );
+   pos = _pico_memstream_tell( fp );
+
+   /* index */
+
+   env->index = getVX( fp );
+
+   /* first subchunk header */
+
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   /* process subchunks as they're encountered */
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_TYPE:
+            env->type = getU2( fp );
+            break;
+
+         case ID_NAME:
+            env->name = getS0( fp );
+            break;
+
+         case ID_PRE:
+            env->behavior[ 0 ] = getU2( fp );
+            break;
+
+         case ID_POST:
+            env->behavior[ 1 ] = getU2( fp );
+            break;
+
+         case ID_KEY:
+            key = _pico_calloc( 1, sizeof( lwKey ));
+            if ( !key ) goto Fail;
+            key->time = getF4( fp );
+            key->value = getF4( fp );
+            lwListInsert( &env->key, key, compare_keys );
+            env->nkeys++;
+            break;
+
+         case ID_SPAN:
+            if ( !key ) goto Fail;
+            key->shape = getU4( fp );
+
+            nparams = ( sz - 4 ) / 4;
+            if ( nparams > 4 ) nparams = 4;
+            for ( i = 0; i < nparams; i++ )
+               f[ i ] = getF4( fp );
+
+            switch ( key->shape ) {
+               case ID_TCB:
+                  key->tension = f[ 0 ];
+                  key->continuity = f[ 1 ];
+                  key->bias = f[ 2 ];
+                  break;
+
+               case ID_BEZI:
+               case ID_HERM:
+               case ID_BEZ2:
+                  for ( i = 0; i < nparams; i++ )
+                     key->param[ i ] = f[ i ];
+                  break;
+            }
+            break;
+
+         case ID_CHAN:
+            plug = _pico_calloc( 1, sizeof( lwPlugin ));
+            if ( !plug ) goto Fail;
+
+            plug->name = getS0( fp );
+            plug->flags = getU2( fp );
+            plug->data = getbytes( fp, sz - get_flen() );
+
+            lwListAdd( &env->cfilter, plug );
+            env->ncfilters++;
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) goto Fail;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the ENVL chunk? */
+
+      rlen = _pico_memstream_tell( fp ) - pos;
+      if ( cksize < rlen ) goto Fail;
+      if ( cksize == rlen ) break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) goto Fail;
+   }
+
+   return env;
+
+Fail:
+   lwFreeEnvelope( env );
+   return NULL;
+}
+
+
+/*
+======================================================================
+lwFindEnvelope()
+
+Returns an lwEnvelope pointer, given an envelope index.
+====================================================================== */
+
+lwEnvelope *lwFindEnvelope( lwEnvelope *list, int index )
+{
+   lwEnvelope *env;
+
+   env = list;
+   while ( env ) {
+      if ( env->index == index ) break;
+      env = env->next;
+   }
+   return env;
+}
+
+
+/*
+======================================================================
+range()
+
+Given the value v of a periodic function, returns the equivalent value
+v2 in the principal interval [lo, hi].  If i isn't NULL, it receives
+the number of wavelengths between v and v2.
+
+   v2 = v - i * (hi - lo)
+
+For example, range( 3 pi, 0, 2 pi, i ) returns pi, with i = 1.
+====================================================================== */
+
+static float range( float v, float lo, float hi, int *i )
+{
+   float v2, r = hi - lo;
+
+   if ( r == 0.0 ) {
+      if ( i ) *i = 0;
+      return lo;
+   }
+
+   v2 = lo + v - r * ( float ) floor(( double ) v / r );
+   if ( i ) *i = -( int )(( v2 - v ) / r + ( v2 > v ? 0.5 : -0.5 ));
+
+   return v2;
+}
+
+
+/*
+======================================================================
+hermite()
+
+Calculate the Hermite coefficients.
+====================================================================== */
+
+static void hermite( float t, float *h1, float *h2, float *h3, float *h4 )
+{
+   float t2, t3;
+
+   t2 = t * t;
+   t3 = t * t2;
+
+   *h2 = 3.0f * t2 - t3 - t3;
+   *h1 = 1.0f - *h2;
+   *h4 = t3 - t2;
+   *h3 = *h4 - t2 + t;
+}
+
+
+/*
+======================================================================
+bezier()
+
+Interpolate the value of a 1D Bezier curve.
+====================================================================== */
+
+static float bezier( float x0, float x1, float x2, float x3, float t )
+{
+   float a, b, c, t2, t3;
+
+   t2 = t * t;
+   t3 = t2 * t;
+
+   c = 3.0f * ( x1 - x0 );
+   b = 3.0f * ( x2 - x1 ) - c;
+   a = x3 - x0 - c - b;
+
+   return a * t3 + b * t2 + c * t + x0;
+}
+
+
+/*
+======================================================================
+bez2_time()
+
+Find the t for which bezier() returns the input time.  The handle
+endpoints of a BEZ2 curve represent the control points, and these have
+(time, value) coordinates, so time is used as both a coordinate and a
+parameter for this curve type.
+====================================================================== */
+
+static float bez2_time( float x0, float x1, float x2, float x3, float time,
+   float *t0, float *t1 )
+{
+   float v, t;
+
+   t = *t0 + ( *t1 - *t0 ) * 0.5f;
+   v = bezier( x0, x1, x2, x3, t );
+   if ( fabs( time - v ) > .0001f ) {
+      if ( v > time )
+         *t1 = t;
+      else
+         *t0 = t;
+      return bez2_time( x0, x1, x2, x3, time, t0, t1 );
+   }
+   else
+      return t;
+}
+
+
+/*
+======================================================================
+bez2()
+
+Interpolate the value of a BEZ2 curve.
+====================================================================== */
+
+static float bez2( lwKey *key0, lwKey *key1, float time )
+{
+   float x, y, t, t0 = 0.0f, t1 = 1.0f;
+
+   if ( key0->shape == ID_BEZ2 )
+      x = key0->time + key0->param[ 2 ];
+   else
+      x = key0->time + ( key1->time - key0->time ) / 3.0f;
+
+   t = bez2_time( key0->time, x, key1->time + key1->param[ 0 ], key1->time,
+      time, &t0, &t1 );
+
+   if ( key0->shape == ID_BEZ2 )
+      y = key0->value + key0->param[ 3 ];
+   else
+      y = key0->value + key0->param[ 1 ] / 3.0f;
+
+   return bezier( key0->value, y, key1->param[ 1 ] + key1->value, key1->value, t );
+}
+
+
+/*
+======================================================================
+outgoing()
+
+Return the outgoing tangent to the curve at key0.  The value returned
+for the BEZ2 case is used when extrapolating a linear pre behavior and
+when interpolating a non-BEZ2 span.
+====================================================================== */
+
+static float outgoing( lwKey *key0, lwKey *key1 )
+{
+   float a, b, d, t, out;
+
+   switch ( key0->shape )
+   {
+      case ID_TCB:
+         a = ( 1.0f - key0->tension )
+           * ( 1.0f + key0->continuity )
+           * ( 1.0f + key0->bias );
+         b = ( 1.0f - key0->tension )
+           * ( 1.0f - key0->continuity )
+           * ( 1.0f - key0->bias );
+         d = key1->value - key0->value;
+
+         if ( key0->prev ) {
+            t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
+            out = t * ( a * ( key0->value - key0->prev->value ) + b * d );
+         }
+         else
+            out = b * d;
+         break;
+
+      case ID_LINE:
+         d = key1->value - key0->value;
+         if ( key0->prev ) {
+            t = ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
+            out = t * ( key0->value - key0->prev->value + d );
+         }
+         else
+            out = d;
+         break;
+
+      case ID_BEZI:
+      case ID_HERM:
+         out = key0->param[ 1 ];
+         if ( key0->prev )
+            out *= ( key1->time - key0->time ) / ( key1->time - key0->prev->time );
+         break;
+
+      case ID_BEZ2:
+         out = key0->param[ 3 ] * ( key1->time - key0->time );
+         if ( fabs( key0->param[ 2 ] ) > 1e-5f )
+            out /= key0->param[ 2 ];
+         else
+            out *= 1e5f;
+         break;
+
+      case ID_STEP:
+      default:
+         out = 0.0f;
+         break;
+   }
+
+   return out;
+}
+
+
+/*
+======================================================================
+incoming()
+
+Return the incoming tangent to the curve at key1.  The value returned
+for the BEZ2 case is used when extrapolating a linear post behavior.
+====================================================================== */
+
+static float incoming( lwKey *key0, lwKey *key1 )
+{
+   float a, b, d, t, in;
+
+   switch ( key1->shape )
+   {
+      case ID_LINE:
+         d = key1->value - key0->value;
+         if ( key1->next ) {
+            t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
+            in = t * ( key1->next->value - key1->value + d );
+         }
+         else
+            in = d;
+         break;
+
+      case ID_TCB:
+         a = ( 1.0f - key1->tension )
+           * ( 1.0f - key1->continuity )
+           * ( 1.0f + key1->bias );
+         b = ( 1.0f - key1->tension )
+           * ( 1.0f + key1->continuity )
+           * ( 1.0f - key1->bias );
+         d = key1->value - key0->value;
+
+         if ( key1->next ) {
+            t = ( key1->time - key0->time ) / ( key1->next->time - key0->time );
+            in = t * ( b * ( key1->next->value - key1->value ) + a * d );
+         }
+         else
+            in = a * d;
+         break;
+
+      case ID_BEZI:
+      case ID_HERM:
+         in = key1->param[ 0 ];
+         if ( key1->next )
+            in *= ( key1->time - key0->time ) / ( key1->next->time - key0->time );
+         break;
+         return in;
+
+      case ID_BEZ2:
+         in = key1->param[ 1 ] * ( key1->time - key0->time );
+         if ( fabs( key1->param[ 0 ] ) > 1e-5f )
+            in /= key1->param[ 0 ];
+         else
+            in *= 1e5f;
+         break;
+
+      case ID_STEP:
+      default:
+         in = 0.0f;
+         break;
+   }
+
+   return in;
+}
+
+
+/*
+======================================================================
+evalEnvelope()
+
+Given a list of keys and a time, returns the interpolated value of the
+envelope at that time.
+====================================================================== */
+
+float evalEnvelope( lwEnvelope *env, float time )
+{
+   lwKey *key0, *key1, *skey, *ekey;
+   float t, h1, h2, h3, h4, in, out, offset = 0.0f;
+   int noff;
+
+
+   /* if there's no key, the value is 0 */
+
+   if ( env->nkeys == 0 ) return 0.0f;
+
+   /* if there's only one key, the value is constant */
+
+   if ( env->nkeys == 1 )
+      return env->key->value;
+
+   /* find the first and last keys */
+
+   skey = ekey = env->key;
+   while ( ekey->next ) ekey = ekey->next;
+
+   /* use pre-behavior if time is before first key time */
+
+   if ( time < skey->time ) {
+      switch ( env->behavior[ 0 ] )
+      {
+         case BEH_RESET:
+            return 0.0f;
+
+         case BEH_CONSTANT:
+            return skey->value;
+
+         case BEH_REPEAT:
+            time = range( time, skey->time, ekey->time, NULL );
+            break;
+
+         case BEH_OSCILLATE:
+            time = range( time, skey->time, ekey->time, &noff );
+            if ( noff % 2 )
+               time = ekey->time - skey->time - time;
+            break;
+
+         case BEH_OFFSET:
+            time = range( time, skey->time, ekey->time, &noff );
+            offset = noff * ( ekey->value - skey->value );
+            break;
+
+         case BEH_LINEAR:
+            out = outgoing( skey, skey->next )
+                / ( skey->next->time - skey->time );
+            return out * ( time - skey->time ) + skey->value;
+      }
+   }
+
+   /* use post-behavior if time is after last key time */
+
+   else if ( time > ekey->time ) {
+      switch ( env->behavior[ 1 ] )
+      {
+         case BEH_RESET:
+            return 0.0f;
+
+         case BEH_CONSTANT:
+            return ekey->value;
+
+         case BEH_REPEAT:
+            time = range( time, skey->time, ekey->time, NULL );
+            break;
+
+         case BEH_OSCILLATE:
+            time = range( time, skey->time, ekey->time, &noff );
+            if ( noff % 2 )
+               time = ekey->time - skey->time - time;
+            break;
+
+         case BEH_OFFSET:
+            time = range( time, skey->time, ekey->time, &noff );
+            offset = noff * ( ekey->value - skey->value );
+            break;
+
+         case BEH_LINEAR:
+            in = incoming( ekey->prev, ekey )
+               / ( ekey->time - ekey->prev->time );
+            return in * ( time - ekey->time ) + ekey->value;
+      }
+   }
+
+   /* get the endpoints of the interval being evaluated */
+
+   key0 = env->key;
+   while ( time > key0->next->time )
+      key0 = key0->next;
+   key1 = key0->next;
+
+   /* check for singularities first */
+
+   if ( time == key0->time )
+      return key0->value + offset;
+   else if ( time == key1->time )
+      return key1->value + offset;
+
+   /* get interval length, time in [0, 1] */
+
+   t = ( time - key0->time ) / ( key1->time - key0->time );
+
+   /* interpolate */
+
+   switch ( key1->shape )
+   {
+      case ID_TCB:
+      case ID_BEZI:
+      case ID_HERM:
+         out = outgoing( key0, key1 );
+         in = incoming( key0, key1 );
+         hermite( t, &h1, &h2, &h3, &h4 );
+         return h1 * key0->value + h2 * key1->value + h3 * out + h4 * in + offset;
+
+      case ID_BEZ2:
+         return bez2( key0, key1, time ) + offset;
+
+      case ID_LINE:
+         return key0->value + t * ( key1->value - key0->value ) + offset;
+
+      case ID_STEP:
+         return key0->value + offset;
+
+      default:
+         return offset;
+   }
+}
diff --git a/libs/picomodel/lwo/list.c b/libs/picomodel/lwo/list.c
index d07b0337..d337296c 100644
--- a/libs/picomodel/lwo/list.c
+++ b/libs/picomodel/lwo/list.c
@@ -1,101 +1,101 @@
-/*
-======================================================================
-list.c
-
-Generic linked list operations.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-
-/*
-======================================================================
-lwListFree()
-
-Free the items in a list.
-====================================================================== */
-
-void lwListFree( void *list, void ( *freeNode )( void * ))
-{
-   lwNode *node, *next;
-
-   node = ( lwNode * ) list;
-   while ( node ) {
-      next = node->next;
-      freeNode( node );
-      node = next;
-   }
-}
-
-
-/*
-======================================================================
-lwListAdd()
-
-Append a node to a list.
-====================================================================== */
-
-void lwListAdd( void **list, void *node )
-{
-   lwNode *head, *tail;
-
-   head = *(( lwNode ** ) list );
-   if ( !head ) {
-      *list = node;
-      return;
-   }
-   while ( head ) {
-      tail = head;
-      head = head->next;
-   }
-   tail->next = ( lwNode * ) node;
-   (( lwNode * ) node )->prev = tail;
-}
-
-
-/*
-======================================================================
-lwListInsert()
-
-Insert a node into a list in sorted order.
-====================================================================== */
-
-void lwListInsert( void **vlist, void *vitem, int ( *compare )( void *, void * ))
-{
-   lwNode **list, *item, *node, *prev;
-
-   if ( !*vlist ) {
-      *vlist = vitem;
-      return;
-   }
-
-   list = ( lwNode ** ) vlist;
-   item = ( lwNode * ) vitem;
-   node = *list;
-   prev = NULL;
-
-   while ( node ) {
-      if ( 0 < compare( node, item )) break;
-      prev = node;
-      node = node->next;
-   }
-
-   if ( !prev ) {
-      *list = item;
-      node->prev = item;
-      item->next = node;
-   }
-   else if ( !node ) {
-      prev->next = item;
-      item->prev = prev;
-   }
-   else {
-      item->next = node;
-      item->prev = prev;
-      prev->next = item;
-      node->prev = item;
-   }
-}
+/*
+======================================================================
+list.c
+
+Generic linked list operations.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+
+/*
+======================================================================
+lwListFree()
+
+Free the items in a list.
+====================================================================== */
+
+void lwListFree( void *list, void ( *freeNode )( void * ))
+{
+   lwNode *node, *next;
+
+   node = ( lwNode * ) list;
+   while ( node ) {
+      next = node->next;
+      freeNode( node );
+      node = next;
+   }
+}
+
+
+/*
+======================================================================
+lwListAdd()
+
+Append a node to a list.
+====================================================================== */
+
+void lwListAdd( void **list, void *node )
+{
+   lwNode *head, *tail;
+
+   head = *(( lwNode ** ) list );
+   if ( !head ) {
+      *list = node;
+      return;
+   }
+   while ( head ) {
+      tail = head;
+      head = head->next;
+   }
+   tail->next = ( lwNode * ) node;
+   (( lwNode * ) node )->prev = tail;
+}
+
+
+/*
+======================================================================
+lwListInsert()
+
+Insert a node into a list in sorted order.
+====================================================================== */
+
+void lwListInsert( void **vlist, void *vitem, int ( *compare )( void *, void * ))
+{
+   lwNode **list, *item, *node, *prev;
+
+   if ( !*vlist ) {
+      *vlist = vitem;
+      return;
+   }
+
+   list = ( lwNode ** ) vlist;
+   item = ( lwNode * ) vitem;
+   node = *list;
+   prev = NULL;
+
+   while ( node ) {
+      if ( 0 < compare( node, item )) break;
+      prev = node;
+      node = node->next;
+   }
+
+   if ( !prev ) {
+      *list = item;
+      node->prev = item;
+      item->next = node;
+   }
+   else if ( !node ) {
+      prev->next = item;
+      item->prev = prev;
+   }
+   else {
+      item->next = node;
+      item->prev = prev;
+      prev->next = item;
+      node->prev = item;
+   }
+}
diff --git a/libs/picomodel/lwo/lwio.c b/libs/picomodel/lwo/lwio.c
index eea380bf..ec74932f 100644
--- a/libs/picomodel/lwo/lwio.c
+++ b/libs/picomodel/lwo/lwio.c
@@ -1,442 +1,442 @@
-/*
-======================================================================
-lwio.c
-
-Functions for reading basic LWO2 data types.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-
-/*
-======================================================================
-flen
-
-This accumulates a count of the number of bytes read.  Callers can set
-it at the beginning of a sequence of reads and then retrieve it to get
-the number of bytes actually read.  If one of the I/O functions fails,
-flen is set to an error code, after which the I/O functions ignore
-read requests until flen is reset.
-====================================================================== */
-
-#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
-#define FLEN_ERROR INT_MIN
-
-static int flen;
-
-void set_flen( int i ) { flen = i; }
-
-int get_flen( void ) { return flen; }
-
-
-#ifdef _WIN32
-/*
-=====================================================================
-revbytes()
-
-Reverses byte order in place.
-
-INPUTS
-   bp       bytes to reverse
-   elsize   size of the underlying data type
-   elcount  number of elements to swap
-
-RESULTS
-   Reverses the byte order in each of elcount elements.
-
-This only needs to be defined on little-endian platforms, most
-notably Windows.  lwo2.h replaces this with a #define on big-endian
-platforms.
-===================================================================== */
-
-void revbytes( void *bp, int elsize, int elcount )
-{
-   register unsigned char *p, *q;
-
-   p = ( unsigned char * ) bp;
-
-   if ( elsize == 2 ) {
-      q = p + 1;
-      while ( elcount-- ) {
-         *p ^= *q;
-         *q ^= *p;
-         *p ^= *q;
-         p += 2;
-         q += 2;
-      }
-      return;
-   }
-
-   while ( elcount-- ) {
-      q = p + elsize - 1;
-      while ( p < q ) {
-         *p ^= *q;
-         *q ^= *p;
-         *p ^= *q;
-         ++p;
-         --q;
-      }
-      p += elsize >> 1;
-   }
-}
-#endif
-
-
-void *getbytes( picoMemStream_t *fp, int size )
-{
-   void *data;
-
-   if ( flen == FLEN_ERROR ) return NULL;
-   if ( size < 0 ) {
-      flen = FLEN_ERROR;
-      return NULL;
-   }
-   data = _pico_alloc( size );
-   if ( !data ) {
-      flen = FLEN_ERROR;
-      return NULL;
-   }
-   if ( 1 != _pico_memstream_read( fp, data, size )) {
-      flen = FLEN_ERROR;
-      _pico_free( data );
-      return NULL;
-   }
-
-   flen += size;
-   return data;
-}
-
-
-void skipbytes( picoMemStream_t *fp, int n )
-{
-   if ( flen == FLEN_ERROR ) return;
-   if ( _pico_memstream_seek( fp, n, PICO_SEEK_CUR ))
-      flen = FLEN_ERROR;
-   else
-      flen += n;
-}
-
-
-int getI1( picoMemStream_t *fp )
-{
-   int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   i = _pico_memstream_getc( fp );
-   if ( i < 0 ) {
-      flen = FLEN_ERROR;
-      return 0;
-   }
-   if ( i > 127 ) i -= 256;
-   flen += 1;
-   return i;
-}
-
-
-short getI2( picoMemStream_t *fp )
-{
-   short i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   if ( 1 != _pico_memstream_read( fp, &i, 2 )) {
-      flen = FLEN_ERROR;
-      return 0;
-   }
-   revbytes( &i, 2, 1 );
-   flen += 2;
-   return i;
-}
-
-
-int getI4( picoMemStream_t *fp )
-{
-   int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   if ( 1 != _pico_memstream_read( fp, &i, 4 )) {
-      flen = FLEN_ERROR;
-      return 0;
-   }
-   revbytes( &i, 4, 1 );
-   flen += 4;
-   return i;
-}
-
-
-unsigned char getU1( picoMemStream_t *fp )
-{
-   int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   i = _pico_memstream_getc( fp );
-   if ( i < 0 ) {
-      flen = FLEN_ERROR;
-      return 0;
-   }
-   flen += 1;
-   return i;
-}
-
-
-unsigned short getU2( picoMemStream_t *fp )
-{
-   unsigned short i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   if ( 1 != _pico_memstream_read( fp, &i, 2 )) {
-      flen = FLEN_ERROR;
-      return 0;
-   }
-   revbytes( &i, 2, 1 );
-   flen += 2;
-   return i;
-}
-
-
-unsigned int getU4( picoMemStream_t *fp )
-{
-   unsigned int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   if ( 1 != _pico_memstream_read( fp, &i, 4 )) {
-      flen = FLEN_ERROR;
-      return 0;
-   }
-   revbytes( &i, 4, 1 );
-   flen += 4;
-   return i;
-}
-
-
-int getVX( picoMemStream_t *fp )
-{
-   int i, c;
-
-   if ( flen == FLEN_ERROR ) return 0;
-
-   c = _pico_memstream_getc( fp );
-   if ( c != 0xFF ) {
-      i = c << 8;
-      c = _pico_memstream_getc( fp );
-      i |= c;
-      flen += 2;
-   }
-   else {
-      c = _pico_memstream_getc( fp );
-      i = c << 16;
-      c = _pico_memstream_getc( fp );
-      i |= c << 8;
-      c = _pico_memstream_getc( fp );
-      i |= c;
-      flen += 4;
-   }
-
-   if ( _pico_memstream_error( fp )) {
-      flen = FLEN_ERROR;
-      return 0;
-   }
-   return i;
-}
-
-
-float getF4( picoMemStream_t *fp )
-{
-   float f;
-
-   if ( flen == FLEN_ERROR ) return 0.0f;
-   if ( 1 != _pico_memstream_read( fp, &f, 4 )) {
-      flen = FLEN_ERROR;
-      return 0.0f;
-   }
-   revbytes( &f, 4, 1 );
-   flen += 4;
-   return f;
-}
-
-
-char *getS0( picoMemStream_t *fp )
-{
-   char *s;
-   int i, c, len, pos;
-
-   if ( flen == FLEN_ERROR ) return NULL;
-
-   pos = _pico_memstream_tell( fp );
-   for ( i = 1; ; i++ ) {
-      c = _pico_memstream_getc( fp );
-      if ( c <= 0 ) break;
-   }
-   if ( c < 0 ) {
-      flen = FLEN_ERROR;
-      return NULL;
-   }
-
-   if ( i == 1 ) {
-      if ( _pico_memstream_seek( fp, pos + 2, PICO_SEEK_SET ))
-         flen = FLEN_ERROR;
-      else
-         flen += 2;
-      return NULL;
-   }
-
-   len = i + ( i & 1 );
-   s = _pico_alloc( len );
-   if ( !s ) {
-      flen = FLEN_ERROR;
-      return NULL;
-   }
-
-   if ( _pico_memstream_seek( fp, pos, PICO_SEEK_SET )) {
-      flen = FLEN_ERROR;
-      return NULL;
-   }
-   if ( 1 != _pico_memstream_read( fp, s, len )) {
-      flen = FLEN_ERROR;
-      return NULL;
-   }
-
-   flen += len;
-   return s;
-}
-
-
-int sgetI1( unsigned char **bp )
-{
-   int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   i = **bp;
-   if ( i > 127 ) i -= 256;
-   flen += 1;
-   *bp++;
-   return i;
-}
-
-
-short sgetI2( unsigned char **bp )
-{
-   short i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   memcpy( &i, *bp, 2 );
-   revbytes( &i, 2, 1 );
-   flen += 2;
-   *bp += 2;
-   return i;
-}
-
-
-int sgetI4( unsigned char **bp )
-{
-   int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   memcpy( &i, *bp, 4 );
-   revbytes( &i, 4, 1 );
-   flen += 4;
-   *bp += 4;
-   return i;
-}
-
-
-unsigned char sgetU1( unsigned char **bp )
-{
-   unsigned char c;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   c = **bp;
-   flen += 1;
-   *bp++;
-   return c;
-}
-
-
-unsigned short sgetU2( unsigned char **bp )
-{
-   unsigned char *buf = *bp;
-   unsigned short i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   i = ( buf[ 0 ] << 8 ) | buf[ 1 ];
-   flen += 2;
-   *bp += 2;
-   return i;
-}
-
-
-unsigned int sgetU4( unsigned char **bp )
-{
-   unsigned int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-   memcpy( &i, *bp, 4 );
-   revbytes( &i, 4, 1 );
-   flen += 4;
-   *bp += 4;
-   return i;
-}
-
-
-int sgetVX( unsigned char **bp )
-{
-   unsigned char *buf = *bp;
-   int i;
-
-   if ( flen == FLEN_ERROR ) return 0;
-
-   if ( buf[ 0 ] != 0xFF ) {
-      i = buf[ 0 ] << 8 | buf[ 1 ];
-      flen += 2;
-      *bp += 2;
-   }
-   else {
-      i = ( buf[ 1 ] << 16 ) | ( buf[ 2 ] << 8 ) | buf[ 3 ];
-      flen += 4;
-      *bp += 4;
-   }
-   return i;
-}
-
-
-float sgetF4( unsigned char **bp )
-{
-   float f;
-
-   if ( flen == FLEN_ERROR ) return 0.0f;
-   memcpy( &f, *bp, 4 );
-   revbytes( &f, 4, 1 );
-   flen += 4;
-   *bp += 4;
-   return f;
-}
-
-
-char *sgetS0( unsigned char **bp )
-{
-   char *s;
-   unsigned char *buf = *bp;
-   int len;
-
-   if ( flen == FLEN_ERROR ) return NULL;
-
-   len = strlen( buf ) + 1;
-   if ( len == 1 ) {
-      flen += 2;
-      *bp += 2;
-      return NULL;
-   }
-   len += len & 1;
-   s = _pico_alloc( len );
-   if ( !s ) {
-      flen = FLEN_ERROR;
-      return NULL;
-   }
-
-   memcpy( s, buf, len );
-   flen += len;
-   *bp += len;
-   return s;
-}
+/*
+======================================================================
+lwio.c
+
+Functions for reading basic LWO2 data types.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+
+/*
+======================================================================
+flen
+
+This accumulates a count of the number of bytes read.  Callers can set
+it at the beginning of a sequence of reads and then retrieve it to get
+the number of bytes actually read.  If one of the I/O functions fails,
+flen is set to an error code, after which the I/O functions ignore
+read requests until flen is reset.
+====================================================================== */
+
+#define INT_MIN     (-2147483647 - 1) /* minimum (signed) int value */
+#define FLEN_ERROR INT_MIN
+
+static int flen;
+
+void set_flen( int i ) { flen = i; }
+
+int get_flen( void ) { return flen; }
+
+
+#ifdef _WIN32
+/*
+=====================================================================
+revbytes()
+
+Reverses byte order in place.
+
+INPUTS
+   bp       bytes to reverse
+   elsize   size of the underlying data type
+   elcount  number of elements to swap
+
+RESULTS
+   Reverses the byte order in each of elcount elements.
+
+This only needs to be defined on little-endian platforms, most
+notably Windows.  lwo2.h replaces this with a #define on big-endian
+platforms.
+===================================================================== */
+
+void revbytes( void *bp, int elsize, int elcount )
+{
+   register unsigned char *p, *q;
+
+   p = ( unsigned char * ) bp;
+
+   if ( elsize == 2 ) {
+      q = p + 1;
+      while ( elcount-- ) {
+         *p ^= *q;
+         *q ^= *p;
+         *p ^= *q;
+         p += 2;
+         q += 2;
+      }
+      return;
+   }
+
+   while ( elcount-- ) {
+      q = p + elsize - 1;
+      while ( p < q ) {
+         *p ^= *q;
+         *q ^= *p;
+         *p ^= *q;
+         ++p;
+         --q;
+      }
+      p += elsize >> 1;
+   }
+}
+#endif
+
+
+void *getbytes( picoMemStream_t *fp, int size )
+{
+   void *data;
+
+   if ( flen == FLEN_ERROR ) return NULL;
+   if ( size < 0 ) {
+      flen = FLEN_ERROR;
+      return NULL;
+   }
+   data = _pico_alloc( size );
+   if ( !data ) {
+      flen = FLEN_ERROR;
+      return NULL;
+   }
+   if ( 1 != _pico_memstream_read( fp, data, size )) {
+      flen = FLEN_ERROR;
+      _pico_free( data );
+      return NULL;
+   }
+
+   flen += size;
+   return data;
+}
+
+
+void skipbytes( picoMemStream_t *fp, int n )
+{
+   if ( flen == FLEN_ERROR ) return;
+   if ( _pico_memstream_seek( fp, n, PICO_SEEK_CUR ))
+      flen = FLEN_ERROR;
+   else
+      flen += n;
+}
+
+
+int getI1( picoMemStream_t *fp )
+{
+   int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   i = _pico_memstream_getc( fp );
+   if ( i < 0 ) {
+      flen = FLEN_ERROR;
+      return 0;
+   }
+   if ( i > 127 ) i -= 256;
+   flen += 1;
+   return i;
+}
+
+
+short getI2( picoMemStream_t *fp )
+{
+   short i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   if ( 1 != _pico_memstream_read( fp, &i, 2 )) {
+      flen = FLEN_ERROR;
+      return 0;
+   }
+   revbytes( &i, 2, 1 );
+   flen += 2;
+   return i;
+}
+
+
+int getI4( picoMemStream_t *fp )
+{
+   int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   if ( 1 != _pico_memstream_read( fp, &i, 4 )) {
+      flen = FLEN_ERROR;
+      return 0;
+   }
+   revbytes( &i, 4, 1 );
+   flen += 4;
+   return i;
+}
+
+
+unsigned char getU1( picoMemStream_t *fp )
+{
+   int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   i = _pico_memstream_getc( fp );
+   if ( i < 0 ) {
+      flen = FLEN_ERROR;
+      return 0;
+   }
+   flen += 1;
+   return i;
+}
+
+
+unsigned short getU2( picoMemStream_t *fp )
+{
+   unsigned short i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   if ( 1 != _pico_memstream_read( fp, &i, 2 )) {
+      flen = FLEN_ERROR;
+      return 0;
+   }
+   revbytes( &i, 2, 1 );
+   flen += 2;
+   return i;
+}
+
+
+unsigned int getU4( picoMemStream_t *fp )
+{
+   unsigned int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   if ( 1 != _pico_memstream_read( fp, &i, 4 )) {
+      flen = FLEN_ERROR;
+      return 0;
+   }
+   revbytes( &i, 4, 1 );
+   flen += 4;
+   return i;
+}
+
+
+int getVX( picoMemStream_t *fp )
+{
+   int i, c;
+
+   if ( flen == FLEN_ERROR ) return 0;
+
+   c = _pico_memstream_getc( fp );
+   if ( c != 0xFF ) {
+      i = c << 8;
+      c = _pico_memstream_getc( fp );
+      i |= c;
+      flen += 2;
+   }
+   else {
+      c = _pico_memstream_getc( fp );
+      i = c << 16;
+      c = _pico_memstream_getc( fp );
+      i |= c << 8;
+      c = _pico_memstream_getc( fp );
+      i |= c;
+      flen += 4;
+   }
+
+   if ( _pico_memstream_error( fp )) {
+      flen = FLEN_ERROR;
+      return 0;
+   }
+   return i;
+}
+
+
+float getF4( picoMemStream_t *fp )
+{
+   float f;
+
+   if ( flen == FLEN_ERROR ) return 0.0f;
+   if ( 1 != _pico_memstream_read( fp, &f, 4 )) {
+      flen = FLEN_ERROR;
+      return 0.0f;
+   }
+   revbytes( &f, 4, 1 );
+   flen += 4;
+   return f;
+}
+
+
+char *getS0( picoMemStream_t *fp )
+{
+   char *s;
+   int i, c, len, pos;
+
+   if ( flen == FLEN_ERROR ) return NULL;
+
+   pos = _pico_memstream_tell( fp );
+   for ( i = 1; ; i++ ) {
+      c = _pico_memstream_getc( fp );
+      if ( c <= 0 ) break;
+   }
+   if ( c < 0 ) {
+      flen = FLEN_ERROR;
+      return NULL;
+   }
+
+   if ( i == 1 ) {
+      if ( _pico_memstream_seek( fp, pos + 2, PICO_SEEK_SET ))
+         flen = FLEN_ERROR;
+      else
+         flen += 2;
+      return NULL;
+   }
+
+   len = i + ( i & 1 );
+   s = _pico_alloc( len );
+   if ( !s ) {
+      flen = FLEN_ERROR;
+      return NULL;
+   }
+
+   if ( _pico_memstream_seek( fp, pos, PICO_SEEK_SET )) {
+      flen = FLEN_ERROR;
+      return NULL;
+   }
+   if ( 1 != _pico_memstream_read( fp, s, len )) {
+      flen = FLEN_ERROR;
+      return NULL;
+   }
+
+   flen += len;
+   return s;
+}
+
+
+int sgetI1( unsigned char **bp )
+{
+   int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   i = **bp;
+   if ( i > 127 ) i -= 256;
+   flen += 1;
+   *bp++;
+   return i;
+}
+
+
+short sgetI2( unsigned char **bp )
+{
+   short i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   memcpy( &i, *bp, 2 );
+   revbytes( &i, 2, 1 );
+   flen += 2;
+   *bp += 2;
+   return i;
+}
+
+
+int sgetI4( unsigned char **bp )
+{
+   int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   memcpy( &i, *bp, 4 );
+   revbytes( &i, 4, 1 );
+   flen += 4;
+   *bp += 4;
+   return i;
+}
+
+
+unsigned char sgetU1( unsigned char **bp )
+{
+   unsigned char c;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   c = **bp;
+   flen += 1;
+   *bp++;
+   return c;
+}
+
+
+unsigned short sgetU2( unsigned char **bp )
+{
+   unsigned char *buf = *bp;
+   unsigned short i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   i = ( buf[ 0 ] << 8 ) | buf[ 1 ];
+   flen += 2;
+   *bp += 2;
+   return i;
+}
+
+
+unsigned int sgetU4( unsigned char **bp )
+{
+   unsigned int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+   memcpy( &i, *bp, 4 );
+   revbytes( &i, 4, 1 );
+   flen += 4;
+   *bp += 4;
+   return i;
+}
+
+
+int sgetVX( unsigned char **bp )
+{
+   unsigned char *buf = *bp;
+   int i;
+
+   if ( flen == FLEN_ERROR ) return 0;
+
+   if ( buf[ 0 ] != 0xFF ) {
+      i = buf[ 0 ] << 8 | buf[ 1 ];
+      flen += 2;
+      *bp += 2;
+   }
+   else {
+      i = ( buf[ 1 ] << 16 ) | ( buf[ 2 ] << 8 ) | buf[ 3 ];
+      flen += 4;
+      *bp += 4;
+   }
+   return i;
+}
+
+
+float sgetF4( unsigned char **bp )
+{
+   float f;
+
+   if ( flen == FLEN_ERROR ) return 0.0f;
+   memcpy( &f, *bp, 4 );
+   revbytes( &f, 4, 1 );
+   flen += 4;
+   *bp += 4;
+   return f;
+}
+
+
+char *sgetS0( unsigned char **bp )
+{
+   char *s;
+   unsigned char *buf = *bp;
+   int len;
+
+   if ( flen == FLEN_ERROR ) return NULL;
+
+   len = strlen( buf ) + 1;
+   if ( len == 1 ) {
+      flen += 2;
+      *bp += 2;
+      return NULL;
+   }
+   len += len & 1;
+   s = _pico_alloc( len );
+   if ( !s ) {
+      flen = FLEN_ERROR;
+      return NULL;
+   }
+
+   memcpy( s, buf, len );
+   flen += len;
+   *bp += len;
+   return s;
+}
diff --git a/libs/picomodel/lwo/lwo2.c b/libs/picomodel/lwo/lwo2.c
index 1d72af7d..f4c72443 100644
--- a/libs/picomodel/lwo/lwo2.c
+++ b/libs/picomodel/lwo/lwo2.c
@@ -1,308 +1,308 @@
-/*
-======================================================================
-lwo2.c
-
-The entry point for loading LightWave object files.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-/* disable warnings */
-#ifdef _WIN32
-#pragma warning( disable:4018 )		/* signed/unsigned mismatch */
-#endif
-
-
-/*
-======================================================================
-lwFreeLayer()
-
-Free memory used by an lwLayer.
-====================================================================== */
-
-void lwFreeLayer( lwLayer *layer )
-{
-   if ( layer ) {
-      if ( layer->name ) _pico_free( layer->name );
-      lwFreePoints( &layer->point );
-      lwFreePolygons( &layer->polygon );
-      lwListFree( layer->vmap, lwFreeVMap );
-      _pico_free( layer );
-   }
-}
-
-
-/*
-======================================================================
-lwFreeObject()
-
-Free memory used by an lwObject.
-====================================================================== */
-
-void lwFreeObject( lwObject *object )
-{
-   if ( object ) {
-      lwListFree( object->layer, lwFreeLayer );
-      lwListFree( object->env, lwFreeEnvelope );
-      lwListFree( object->clip, lwFreeClip );
-      lwListFree( object->surf, lwFreeSurface );
-      lwFreeTags( &object->taglist );
-      _pico_free( object );
-   }
-}
-
-
-/*
-======================================================================
-lwGetObject()
-
-Returns the contents of a LightWave object, given its filename, or
-NULL if the file couldn't be loaded.  On failure, failID and failpos
-can be used to diagnose the cause.
-
-1.  If the file isn't an LWO2 or an LWOB, failpos will contain 12 and
-    failID will be unchanged.
-
-2.  If an error occurs while reading, failID will contain the most
-    recently read IFF chunk ID, and failpos will contain the value
-    returned by _pico_memstream_tell() at the time of the failure.
-
-3.  If the file couldn't be opened, or an error occurs while reading
-    the first 12 bytes, both failID and failpos will be unchanged.
-
-If you don't need this information, failID and failpos can be NULL.
-====================================================================== */
-
-lwObject *lwGetObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
-{
-   lwObject *object;
-   lwLayer *layer;
-   lwNode *node;
-   unsigned int id, formsize, type, cksize;
-   int i, rlen;
-
-   /* open the file */
-
-   if ( !fp ) return NULL;
-
-   /* read the first 12 bytes */
-
-   set_flen( 0 );
-   id       = getU4( fp );
-   formsize = getU4( fp );
-   type     = getU4( fp );
-   if ( 12 != get_flen() ) {
-      return NULL;
-   }
-
-   /* is this a LW object? */
-
-   if ( id != ID_FORM ) {
-      if ( failpos ) *failpos = 12;
-      return NULL;
-   }
-
-   if ( type != ID_LWO2 ) {
-      if ( type == ID_LWOB )
-         return lwGetObject5( filename, fp, failID, failpos );
-      else {
-         if ( failpos ) *failpos = 12;
-         return NULL;
-      }
-   }
-
-   /* allocate an object and a default layer */
-
-   object = _pico_calloc( 1, sizeof( lwObject ));
-   if ( !object ) goto Fail;
-
-   layer = _pico_calloc( 1, sizeof( lwLayer ));
-   if ( !layer ) goto Fail;
-   object->layer = layer;
-
-   /* get the first chunk header */
-
-   id = getU4( fp );
-   cksize = getU4( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   /* process chunks as they're encountered */
-
-   while ( 1 ) {
-      cksize += cksize & 1;
-
-      switch ( id )
-      {
-         case ID_LAYR:
-            if ( object->nlayers > 0 ) {
-               layer = _pico_calloc( 1, sizeof( lwLayer ));
-               if ( !layer ) goto Fail;
-               lwListAdd( &object->layer, layer );
-            }
-            object->nlayers++;
-
-            set_flen( 0 );
-            layer->index = getU2( fp );
-            layer->flags = getU2( fp );
-            layer->pivot[ 0 ] = getF4( fp );
-            layer->pivot[ 1 ] = getF4( fp );
-            layer->pivot[ 2 ] = getF4( fp );
-            layer->name = getS0( fp );
-
-            rlen = get_flen();
-            if ( rlen < 0 || rlen > cksize ) goto Fail;
-            if ( rlen <= cksize - 2 )
-               layer->parent = getU2( fp );
-            rlen = get_flen();
-            if ( rlen < cksize )
-               _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
-            break;
-
-         case ID_PNTS:
-            if ( !lwGetPoints( fp, cksize, &layer->point ))
-               goto Fail;
-            break;
-
-         case ID_POLS:
-            if ( !lwGetPolygons( fp, cksize, &layer->polygon,
-               layer->point.offset ))
-               goto Fail;
-            break;
-
-         case ID_VMAP:
-         case ID_VMAD:
-            node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset,
-               layer->polygon.offset, id == ID_VMAD );
-            if ( !node ) goto Fail;
-            lwListAdd( &layer->vmap, node );
-            layer->nvmaps++;
-            break;
-
-         case ID_PTAG:
-            if ( !lwGetPolygonTags( fp, cksize, &object->taglist,
-               &layer->polygon ))
-               goto Fail;
-            break;
-
-         case ID_BBOX:
-            set_flen( 0 );
-            for ( i = 0; i < 6; i++ )
-               layer->bbox[ i ] = getF4( fp );
-            rlen = get_flen();
-            if ( rlen < 0 || rlen > cksize ) goto Fail;
-            if ( rlen < cksize )
-               _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
-            break;
-
-         case ID_TAGS:
-            if ( !lwGetTags( fp, cksize, &object->taglist ))
-               goto Fail;
-            break;
-
-         case ID_ENVL:
-            node = ( lwNode * ) lwGetEnvelope( fp, cksize );
-            if ( !node ) goto Fail;
-            lwListAdd( &object->env, node );
-            object->nenvs++;
-            break;
-
-         case ID_CLIP:
-            node = ( lwNode * ) lwGetClip( fp, cksize );
-            if ( !node ) goto Fail;
-            lwListAdd( &object->clip, node );
-            object->nclips++;
-            break;
-
-         case ID_SURF:
-            node = ( lwNode * ) lwGetSurface( fp, cksize );
-            if ( !node ) goto Fail;
-            lwListAdd( &object->surf, node );
-            object->nsurfs++;
-            break;
-
-         case ID_DESC:
-         case ID_TEXT:
-         case ID_ICON:
-         default:
-            _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR );
-            break;
-      }
-
-      /* end of the file? */
-
-      if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break;
-
-      /* get the next chunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      cksize = getU4( fp );
-      if ( 8 != get_flen() ) goto Fail;
-   }
-
-   if ( object->nlayers == 0 )
-      object->nlayers = 1;
-
-   layer = object->layer;
-   while ( layer ) {
-      lwGetBoundingBox( &layer->point, layer->bbox );
-      lwGetPolyNormals( &layer->point, &layer->polygon );
-      if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail;
-      if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist,
-         &object->surf, &object->nsurfs )) goto Fail;
-      lwGetVertNormals( &layer->point, &layer->polygon );
-      if ( !lwGetPointVMaps( &layer->point, layer->vmap )) goto Fail;
-      if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap )) goto Fail;
-      layer = layer->next;
-   }
-
-   return object;
-
-Fail:
-  if ( failID ) *failID = id;
-   if ( fp ) {
-      if ( failpos ) *failpos = _pico_memstream_tell( fp );
-   }
-   lwFreeObject( object );
-   return NULL;
-}
-
-int lwValidateObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
-{
-   unsigned int id, formsize, type;
-
-   /* open the file */
-
-   if ( !fp ) return PICO_PMV_ERROR_MEMORY;
-
-   /* read the first 12 bytes */
-
-   set_flen( 0 );
-   id       = getU4( fp );
-   formsize = getU4( fp );
-   type     = getU4( fp );
-   if ( 12 != get_flen() ) {
-      return PICO_PMV_ERROR_SIZE;
-   }
-
-   /* is this a LW object? */
-
-   if ( id != ID_FORM ) {
-      if ( failpos ) *failpos = 12;
-      return PICO_PMV_ERROR_SIZE;
-   }
-
-   if ( type != ID_LWO2 ) {
-      if ( type == ID_LWOB )
-         return lwValidateObject5( filename, fp, failID, failpos );
-      else {
-         if ( failpos ) *failpos = 12;
-         return PICO_PMV_ERROR_IDENT;
-      }
-   }
-
-   return PICO_PMV_OK;
-}
+/*
+======================================================================
+lwo2.c
+
+The entry point for loading LightWave object files.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+/* disable warnings */
+#ifdef _WIN32
+#pragma warning( disable:4018 )		/* signed/unsigned mismatch */
+#endif
+
+
+/*
+======================================================================
+lwFreeLayer()
+
+Free memory used by an lwLayer.
+====================================================================== */
+
+void lwFreeLayer( lwLayer *layer )
+{
+   if ( layer ) {
+      if ( layer->name ) _pico_free( layer->name );
+      lwFreePoints( &layer->point );
+      lwFreePolygons( &layer->polygon );
+      lwListFree( layer->vmap, lwFreeVMap );
+      _pico_free( layer );
+   }
+}
+
+
+/*
+======================================================================
+lwFreeObject()
+
+Free memory used by an lwObject.
+====================================================================== */
+
+void lwFreeObject( lwObject *object )
+{
+   if ( object ) {
+      lwListFree( object->layer, lwFreeLayer );
+      lwListFree( object->env, lwFreeEnvelope );
+      lwListFree( object->clip, lwFreeClip );
+      lwListFree( object->surf, lwFreeSurface );
+      lwFreeTags( &object->taglist );
+      _pico_free( object );
+   }
+}
+
+
+/*
+======================================================================
+lwGetObject()
+
+Returns the contents of a LightWave object, given its filename, or
+NULL if the file couldn't be loaded.  On failure, failID and failpos
+can be used to diagnose the cause.
+
+1.  If the file isn't an LWO2 or an LWOB, failpos will contain 12 and
+    failID will be unchanged.
+
+2.  If an error occurs while reading, failID will contain the most
+    recently read IFF chunk ID, and failpos will contain the value
+    returned by _pico_memstream_tell() at the time of the failure.
+
+3.  If the file couldn't be opened, or an error occurs while reading
+    the first 12 bytes, both failID and failpos will be unchanged.
+
+If you don't need this information, failID and failpos can be NULL.
+====================================================================== */
+
+lwObject *lwGetObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
+{
+   lwObject *object;
+   lwLayer *layer;
+   lwNode *node;
+   unsigned int id, formsize, type, cksize;
+   int i, rlen;
+
+   /* open the file */
+
+   if ( !fp ) return NULL;
+
+   /* read the first 12 bytes */
+
+   set_flen( 0 );
+   id       = getU4( fp );
+   formsize = getU4( fp );
+   type     = getU4( fp );
+   if ( 12 != get_flen() ) {
+      return NULL;
+   }
+
+   /* is this a LW object? */
+
+   if ( id != ID_FORM ) {
+      if ( failpos ) *failpos = 12;
+      return NULL;
+   }
+
+   if ( type != ID_LWO2 ) {
+      if ( type == ID_LWOB )
+         return lwGetObject5( filename, fp, failID, failpos );
+      else {
+         if ( failpos ) *failpos = 12;
+         return NULL;
+      }
+   }
+
+   /* allocate an object and a default layer */
+
+   object = _pico_calloc( 1, sizeof( lwObject ));
+   if ( !object ) goto Fail;
+
+   layer = _pico_calloc( 1, sizeof( lwLayer ));
+   if ( !layer ) goto Fail;
+   object->layer = layer;
+
+   /* get the first chunk header */
+
+   id = getU4( fp );
+   cksize = getU4( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   /* process chunks as they're encountered */
+
+   while ( 1 ) {
+      cksize += cksize & 1;
+
+      switch ( id )
+      {
+         case ID_LAYR:
+            if ( object->nlayers > 0 ) {
+               layer = _pico_calloc( 1, sizeof( lwLayer ));
+               if ( !layer ) goto Fail;
+               lwListAdd( &object->layer, layer );
+            }
+            object->nlayers++;
+
+            set_flen( 0 );
+            layer->index = getU2( fp );
+            layer->flags = getU2( fp );
+            layer->pivot[ 0 ] = getF4( fp );
+            layer->pivot[ 1 ] = getF4( fp );
+            layer->pivot[ 2 ] = getF4( fp );
+            layer->name = getS0( fp );
+
+            rlen = get_flen();
+            if ( rlen < 0 || rlen > cksize ) goto Fail;
+            if ( rlen <= cksize - 2 )
+               layer->parent = getU2( fp );
+            rlen = get_flen();
+            if ( rlen < cksize )
+               _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
+            break;
+
+         case ID_PNTS:
+            if ( !lwGetPoints( fp, cksize, &layer->point ))
+               goto Fail;
+            break;
+
+         case ID_POLS:
+            if ( !lwGetPolygons( fp, cksize, &layer->polygon,
+               layer->point.offset ))
+               goto Fail;
+            break;
+
+         case ID_VMAP:
+         case ID_VMAD:
+            node = ( lwNode * ) lwGetVMap( fp, cksize, layer->point.offset,
+               layer->polygon.offset, id == ID_VMAD );
+            if ( !node ) goto Fail;
+            lwListAdd( &layer->vmap, node );
+            layer->nvmaps++;
+            break;
+
+         case ID_PTAG:
+            if ( !lwGetPolygonTags( fp, cksize, &object->taglist,
+               &layer->polygon ))
+               goto Fail;
+            break;
+
+         case ID_BBOX:
+            set_flen( 0 );
+            for ( i = 0; i < 6; i++ )
+               layer->bbox[ i ] = getF4( fp );
+            rlen = get_flen();
+            if ( rlen < 0 || rlen > cksize ) goto Fail;
+            if ( rlen < cksize )
+               _pico_memstream_seek( fp, cksize - rlen, PICO_SEEK_CUR );
+            break;
+
+         case ID_TAGS:
+            if ( !lwGetTags( fp, cksize, &object->taglist ))
+               goto Fail;
+            break;
+
+         case ID_ENVL:
+            node = ( lwNode * ) lwGetEnvelope( fp, cksize );
+            if ( !node ) goto Fail;
+            lwListAdd( &object->env, node );
+            object->nenvs++;
+            break;
+
+         case ID_CLIP:
+            node = ( lwNode * ) lwGetClip( fp, cksize );
+            if ( !node ) goto Fail;
+            lwListAdd( &object->clip, node );
+            object->nclips++;
+            break;
+
+         case ID_SURF:
+            node = ( lwNode * ) lwGetSurface( fp, cksize );
+            if ( !node ) goto Fail;
+            lwListAdd( &object->surf, node );
+            object->nsurfs++;
+            break;
+
+         case ID_DESC:
+         case ID_TEXT:
+         case ID_ICON:
+         default:
+            _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR );
+            break;
+      }
+
+      /* end of the file? */
+
+      if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break;
+
+      /* get the next chunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      cksize = getU4( fp );
+      if ( 8 != get_flen() ) goto Fail;
+   }
+
+   if ( object->nlayers == 0 )
+      object->nlayers = 1;
+
+   layer = object->layer;
+   while ( layer ) {
+      lwGetBoundingBox( &layer->point, layer->bbox );
+      lwGetPolyNormals( &layer->point, &layer->polygon );
+      if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail;
+      if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist,
+         &object->surf, &object->nsurfs )) goto Fail;
+      lwGetVertNormals( &layer->point, &layer->polygon );
+      if ( !lwGetPointVMaps( &layer->point, layer->vmap )) goto Fail;
+      if ( !lwGetPolyVMaps( &layer->polygon, layer->vmap )) goto Fail;
+      layer = layer->next;
+   }
+
+   return object;
+
+Fail:
+  if ( failID ) *failID = id;
+   if ( fp ) {
+      if ( failpos ) *failpos = _pico_memstream_tell( fp );
+   }
+   lwFreeObject( object );
+   return NULL;
+}
+
+int lwValidateObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
+{
+   unsigned int id, formsize, type;
+
+   /* open the file */
+
+   if ( !fp ) return PICO_PMV_ERROR_MEMORY;
+
+   /* read the first 12 bytes */
+
+   set_flen( 0 );
+   id       = getU4( fp );
+   formsize = getU4( fp );
+   type     = getU4( fp );
+   if ( 12 != get_flen() ) {
+      return PICO_PMV_ERROR_SIZE;
+   }
+
+   /* is this a LW object? */
+
+   if ( id != ID_FORM ) {
+      if ( failpos ) *failpos = 12;
+      return PICO_PMV_ERROR_SIZE;
+   }
+
+   if ( type != ID_LWO2 ) {
+      if ( type == ID_LWOB )
+         return lwValidateObject5( filename, fp, failID, failpos );
+      else {
+         if ( failpos ) *failpos = 12;
+         return PICO_PMV_ERROR_IDENT;
+      }
+   }
+
+   return PICO_PMV_OK;
+}
diff --git a/libs/picomodel/lwo/lwo2.h b/libs/picomodel/lwo/lwo2.h
index 1fe1dd97..1d55ba46 100644
--- a/libs/picomodel/lwo/lwo2.h
+++ b/libs/picomodel/lwo/lwo2.h
@@ -1,651 +1,651 @@
-/*
-======================================================================
-lwo2.h
-
-Definitions and typedefs for LWO2 files.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#ifndef LWO2_H
-#define LWO2_H
-
-/* chunk and subchunk IDs */
-
-#define LWID_(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
-
-#define ID_FORM  LWID_('F','O','R','M')
-#define ID_LWO2  LWID_('L','W','O','2')
-#define ID_LWOB  LWID_('L','W','O','B')
-
-/* top-level chunks */
-#define ID_LAYR  LWID_('L','A','Y','R')
-#define ID_TAGS  LWID_('T','A','G','S')
-#define ID_PNTS  LWID_('P','N','T','S')
-#define ID_BBOX  LWID_('B','B','O','X')
-#define ID_VMAP  LWID_('V','M','A','P')
-#define ID_VMAD  LWID_('V','M','A','D')
-#define ID_POLS  LWID_('P','O','L','S')
-#define ID_PTAG  LWID_('P','T','A','G')
-#define ID_ENVL  LWID_('E','N','V','L')
-#define ID_CLIP  LWID_('C','L','I','P')
-#define ID_SURF  LWID_('S','U','R','F')
-#define ID_DESC  LWID_('D','E','S','C')
-#define ID_TEXT  LWID_('T','E','X','T')
-#define ID_ICON  LWID_('I','C','O','N')
-
-/* polygon types */
-#define ID_FACE  LWID_('F','A','C','E')
-#define ID_CURV  LWID_('C','U','R','V')
-#define ID_PTCH  LWID_('P','T','C','H')
-#define ID_MBAL  LWID_('M','B','A','L')
-#define ID_BONE  LWID_('B','O','N','E')
-
-/* polygon tags */
-#define ID_SURF  LWID_('S','U','R','F')
-#define ID_PART  LWID_('P','A','R','T')
-#define ID_SMGP  LWID_('S','M','G','P')
-
-/* envelopes */
-#define ID_PRE   LWID_('P','R','E',' ')
-#define ID_POST  LWID_('P','O','S','T')
-#define ID_KEY   LWID_('K','E','Y',' ')
-#define ID_SPAN  LWID_('S','P','A','N')
-#define ID_TCB   LWID_('T','C','B',' ')
-#define ID_HERM  LWID_('H','E','R','M')
-#define ID_BEZI  LWID_('B','E','Z','I')
-#define ID_BEZ2  LWID_('B','E','Z','2')
-#define ID_LINE  LWID_('L','I','N','E')
-#define ID_STEP  LWID_('S','T','E','P')
-
-/* clips */
-#define ID_STIL  LWID_('S','T','I','L')
-#define ID_ISEQ  LWID_('I','S','E','Q')
-#define ID_ANIM  LWID_('A','N','I','M')
-#define ID_XREF  LWID_('X','R','E','F')
-#define ID_STCC  LWID_('S','T','C','C')
-#define ID_TIME  LWID_('T','I','M','E')
-#define ID_CONT  LWID_('C','O','N','T')
-#define ID_BRIT  LWID_('B','R','I','T')
-#define ID_SATR  LWID_('S','A','T','R')
-#define ID_HUE   LWID_('H','U','E',' ')
-#define ID_GAMM  LWID_('G','A','M','M')
-#define ID_NEGA  LWID_('N','E','G','A')
-#define ID_IFLT  LWID_('I','F','L','T')
-#define ID_PFLT  LWID_('P','F','L','T')
-
-/* surfaces */
-#define ID_COLR  LWID_('C','O','L','R')
-#define ID_LUMI  LWID_('L','U','M','I')
-#define ID_DIFF  LWID_('D','I','F','F')
-#define ID_SPEC  LWID_('S','P','E','C')
-#define ID_GLOS  LWID_('G','L','O','S')
-#define ID_REFL  LWID_('R','E','F','L')
-#define ID_RFOP  LWID_('R','F','O','P')
-#define ID_RIMG  LWID_('R','I','M','G')
-#define ID_RSAN  LWID_('R','S','A','N')
-#define ID_TRAN  LWID_('T','R','A','N')
-#define ID_TROP  LWID_('T','R','O','P')
-#define ID_TIMG  LWID_('T','I','M','G')
-#define ID_RIND  LWID_('R','I','N','D')
-#define ID_TRNL  LWID_('T','R','N','L')
-#define ID_BUMP  LWID_('B','U','M','P')
-#define ID_SMAN  LWID_('S','M','A','N')
-#define ID_SIDE  LWID_('S','I','D','E')
-#define ID_CLRH  LWID_('C','L','R','H')
-#define ID_CLRF  LWID_('C','L','R','F')
-#define ID_ADTR  LWID_('A','D','T','R')
-#define ID_SHRP  LWID_('S','H','R','P')
-#define ID_LINE  LWID_('L','I','N','E')
-#define ID_LSIZ  LWID_('L','S','I','Z')
-#define ID_ALPH  LWID_('A','L','P','H')
-#define ID_AVAL  LWID_('A','V','A','L')
-#define ID_GVAL  LWID_('G','V','A','L')
-#define ID_BLOK  LWID_('B','L','O','K')
-
-/* texture layer */
-#define ID_TYPE  LWID_('T','Y','P','E')
-#define ID_CHAN  LWID_('C','H','A','N')
-#define ID_NAME  LWID_('N','A','M','E')
-#define ID_ENAB  LWID_('E','N','A','B')
-#define ID_OPAC  LWID_('O','P','A','C')
-#define ID_FLAG  LWID_('F','L','A','G')
-#define ID_PROJ  LWID_('P','R','O','J')
-#define ID_STCK  LWID_('S','T','C','K')
-#define ID_TAMP  LWID_('T','A','M','P')
-
-/* texture coordinates */
-#define ID_TMAP  LWID_('T','M','A','P')
-#define ID_AXIS  LWID_('A','X','I','S')
-#define ID_CNTR  LWID_('C','N','T','R')
-#define ID_SIZE  LWID_('S','I','Z','E')
-#define ID_ROTA  LWID_('R','O','T','A')
-#define ID_OREF  LWID_('O','R','E','F')
-#define ID_FALL  LWID_('F','A','L','L')
-#define ID_CSYS  LWID_('C','S','Y','S')
-
-/* image map */
-#define ID_IMAP  LWID_('I','M','A','P')
-#define ID_IMAG  LWID_('I','M','A','G')
-#define ID_WRAP  LWID_('W','R','A','P')
-#define ID_WRPW  LWID_('W','R','P','W')
-#define ID_WRPH  LWID_('W','R','P','H')
-#define ID_VMAP  LWID_('V','M','A','P')
-#define ID_AAST  LWID_('A','A','S','T')
-#define ID_PIXB  LWID_('P','I','X','B')
-
-/* procedural */
-#define ID_PROC  LWID_('P','R','O','C')
-#define ID_COLR  LWID_('C','O','L','R')
-#define ID_VALU  LWID_('V','A','L','U')
-#define ID_FUNC  LWID_('F','U','N','C')
-#define ID_FTPS  LWID_('F','T','P','S')
-#define ID_ITPS  LWID_('I','T','P','S')
-#define ID_ETPS  LWID_('E','T','P','S')
-
-/* gradient */
-#define ID_GRAD  LWID_('G','R','A','D')
-#define ID_GRST  LWID_('G','R','S','T')
-#define ID_GREN  LWID_('G','R','E','N')
-#define ID_PNAM  LWID_('P','N','A','M')
-#define ID_INAM  LWID_('I','N','A','M')
-#define ID_GRPT  LWID_('G','R','P','T')
-#define ID_FKEY  LWID_('F','K','E','Y')
-#define ID_IKEY  LWID_('I','K','E','Y')
-
-/* shader */
-#define ID_SHDR  LWID_('S','H','D','R')
-#define ID_DATA  LWID_('D','A','T','A')
-
-
-/* generic linked list */
-
-typedef struct st_lwNode {
-   struct st_lwNode *next, *prev;
-   void *data;
-} lwNode;
-
-
-/* plug-in reference */
-
-typedef struct st_lwPlugin {
-   struct st_lwPlugin *next, *prev;
-   char          *ord;
-   char          *name;
-   int            flags;
-   void          *data;
-} lwPlugin;
-
-
-/* envelopes */
-
-typedef struct st_lwKey {
-   struct st_lwKey *next, *prev;
-   float          value;
-   float          time;
-   unsigned int   shape;               /* ID_TCB, ID_BEZ2, etc. */
-   float          tension;
-   float          continuity;
-   float          bias;
-   float          param[ 4 ];
-} lwKey;
-
-typedef struct st_lwEnvelope {
-   struct st_lwEnvelope *next, *prev;
-   int            index;
-   int            type;
-   char          *name;
-   lwKey         *key;                 /* linked list of keys */
-   int            nkeys;
-   int            behavior[ 2 ];       /* pre and post (extrapolation) */
-   lwPlugin      *cfilter;             /* linked list of channel filters */
-   int            ncfilters;
-} lwEnvelope;
-
-#define BEH_RESET      0
-#define BEH_CONSTANT   1
-#define BEH_REPEAT     2
-#define BEH_OSCILLATE  3
-#define BEH_OFFSET     4
-#define BEH_LINEAR     5
-
-
-/* values that can be enveloped */
-
-typedef struct st_lwEParam {
-   float          val;
-   int            eindex;
-} lwEParam;
-
-typedef struct st_lwVParam {
-   float          val[ 3 ];
-   int            eindex;
-} lwVParam;
-
-
-/* clips */
-
-typedef struct st_lwClipStill {
-   char          *name;
-} lwClipStill;
-
-typedef struct st_lwClipSeq {
-   char          *prefix;              /* filename before sequence digits */
-   char          *suffix;              /* after digits, e.g. extensions */
-   int            digits;
-   int            flags;
-   int            offset;
-   int            start;
-   int            end;
-} lwClipSeq;
-
-typedef struct st_lwClipAnim {
-   char          *name;
-   char          *server;              /* anim loader plug-in */
-   void          *data;
-} lwClipAnim;
-
-typedef struct st_lwClipXRef {
-   char          *string;
-   int            index;
-   struct st_lwClip *clip;
-} lwClipXRef;
-
-typedef struct st_lwClipCycle {
-   char          *name;
-   int            lo;
-   int            hi;
-} lwClipCycle;
-
-typedef struct st_lwClip {
-   struct st_lwClip *next, *prev;
-   int            index;
-   unsigned int   type;                /* ID_STIL, ID_ISEQ, etc. */
-   union {
-      lwClipStill    still;
-      lwClipSeq      seq;
-      lwClipAnim     anim;
-      lwClipXRef     xref;
-      lwClipCycle    cycle;
-   }              source;
-   float          start_time;
-   float          duration;
-   float          frame_rate;
-   lwEParam       contrast;
-   lwEParam       brightness;
-   lwEParam       saturation;
-   lwEParam       hue;
-   lwEParam       gamma;
-   int            negative;
-   lwPlugin      *ifilter;             /* linked list of image filters */
-   int            nifilters;
-   lwPlugin      *pfilter;             /* linked list of pixel filters */
-   int            npfilters;
-} lwClip;
-
-
-/* textures */
-
-typedef struct st_lwTMap {
-   lwVParam       size;
-   lwVParam       center;
-   lwVParam       rotate;
-   lwVParam       falloff;
-   int            fall_type;
-   char          *ref_object;
-   int            coord_sys;
-} lwTMap;
-
-typedef struct st_lwImageMap {
-   int            cindex;
-   int            projection;
-   char          *vmap_name;
-   int            axis;
-   int            wrapw_type;
-   int            wraph_type;
-   lwEParam       wrapw;
-   lwEParam       wraph;
-   float          aa_strength;
-   int            aas_flags;
-   int            pblend;
-   lwEParam       stck;
-   lwEParam       amplitude;
-} lwImageMap;
-
-#define PROJ_PLANAR       0
-#define PROJ_CYLINDRICAL  1
-#define PROJ_SPHERICAL    2
-#define PROJ_CUBIC        3
-#define PROJ_FRONT        4
-
-#define WRAP_NONE    0
-#define WRAP_EDGE    1
-#define WRAP_REPEAT  2
-#define WRAP_MIRROR  3
-
-typedef struct st_lwProcedural {
-   int            axis;
-   float          value[ 3 ];
-   char          *name;
-   void          *data;
-} lwProcedural;
-
-typedef struct st_lwGradKey {
-   struct st_lwGradKey *next, *prev;
-   float          value;
-   float          rgba[ 4 ];
-} lwGradKey;
-
-typedef struct st_lwGradient {
-   char          *paramname;
-   char          *itemname;
-   float          start;
-   float          end;
-   int            repeat;
-   lwGradKey     *key;                 /* array of gradient keys */
-   short         *ikey;                /* array of interpolation codes */
-} lwGradient;
-
-typedef struct st_lwTexture {
-   struct st_lwTexture *next, *prev;
-   char          *ord;
-   unsigned int   type;
-   unsigned int   chan;
-   lwEParam       opacity;
-   short          opac_type;
-   short          enabled;
-   short          negative;
-   short          axis;
-   union {
-      lwImageMap     imap;
-      lwProcedural   proc;
-      lwGradient     grad;
-   }              param;
-   lwTMap         tmap;
-} lwTexture;
-
-
-/* values that can be textured */
-
-typedef struct st_lwTParam {
-   float          val;
-   int            eindex;
-   lwTexture     *tex;                 /* linked list of texture layers */
-} lwTParam;
-
-typedef struct st_lwCParam {
-   float          rgb[ 3 ];
-   int            eindex;
-   lwTexture     *tex;                 /* linked list of texture layers */
-} lwCParam;
-
-
-/* surfaces */
-
-typedef struct st_lwGlow {
-   short          enabled;
-   short          type;
-   lwEParam       intensity;
-   lwEParam       size;
-} Glow;
-
-typedef struct st_lwRMap {
-   lwTParam       val;
-   int            options;
-   int            cindex;
-   float          seam_angle;
-} lwRMap;
-
-typedef struct st_lwLine {
-   short          enabled;
-   unsigned short flags;
-   lwEParam       size;
-} lwLine;
-
-typedef struct st_lwSurface {
-   struct st_lwSurface *next, *prev;
-   char          *name;
-   char          *srcname;
-   lwCParam       color;
-   lwTParam       luminosity;
-   lwTParam       diffuse;
-   lwTParam       specularity;
-   lwTParam       glossiness;
-   lwRMap         reflection;
-   lwRMap         transparency;
-   lwTParam       eta;
-   lwTParam       translucency;
-   lwTParam       bump;
-   float          smooth;
-   int            sideflags;
-   float          alpha;
-   int            alpha_mode;
-   lwEParam       color_hilite;
-   lwEParam       color_filter;
-   lwEParam       add_trans;
-   lwEParam       dif_sharp;
-   lwEParam       glow;
-   lwLine         line;
-   lwPlugin      *shader;              /* linked list of shaders */
-   int            nshaders;
-} lwSurface;
-
-
-/* vertex maps */
-
-typedef struct st_lwVMap {
-   struct st_lwVMap *next, *prev;
-   char          *name;
-   unsigned int   type;
-   int            dim;
-   int            nverts;
-   int            perpoly;
-   int           *vindex;              /* array of point indexes */
-   int           *pindex;              /* array of polygon indexes */
-   float        **val;
-} lwVMap;
-
-typedef struct st_lwVMapPt {
-   lwVMap        *vmap;
-   int            index;               /* vindex or pindex element */
-} lwVMapPt;
-
-
-/* points and polygons */
-
-typedef struct st_lwPoint {
-   float          pos[ 3 ];
-   int            npols;               /* number of polygons sharing the point */
-   int           *pol;                 /* array of polygon indexes */
-   int            nvmaps;
-   lwVMapPt      *vm;                  /* array of vmap references */
-} lwPoint;
-
-typedef struct st_lwPolVert {
-   int            index;               /* index into the point array */
-   float          norm[ 3 ];
-   int            nvmaps;
-   lwVMapPt      *vm;                  /* array of vmap references */
-} lwPolVert;
-
-typedef struct st_lwPolygon {
-   lwSurface     *surf;
-   int            part;                /* part index */
-   int            smoothgrp;           /* smoothing group */
-   int            flags;
-   unsigned int   type;
-   float          norm[ 3 ];
-   int            nverts;
-   lwPolVert     *v;                   /* array of vertex records */
-} lwPolygon;
-
-typedef struct st_lwPointList {
-   int            count;
-   int            offset;              /* only used during reading */
-   lwPoint       *pt;                  /* array of points */
-} lwPointList;
-
-typedef struct st_lwPolygonList {
-   int            count;
-   int            offset;              /* only used during reading */
-   int            vcount;              /* total number of vertices */
-   int            voffset;             /* only used during reading */
-   lwPolygon     *pol;                 /* array of polygons */
-} lwPolygonList;
-
-
-/* geometry layers */
-
-typedef struct st_lwLayer {
-   struct st_lwLayer *next, *prev;
-   char          *name;
-   int            index;
-   int            parent;
-   int            flags;
-   float          pivot[ 3 ];
-   float          bbox[ 6 ];
-   lwPointList    point;
-   lwPolygonList  polygon;
-   int            nvmaps;
-   lwVMap        *vmap;                /* linked list of vmaps */
-} lwLayer;
-
-
-/* tag strings */
-
-typedef struct st_lwTagList {
-   int            count;
-   int            offset;              /* only used during reading */
-   char         **tag;                 /* array of strings */
-} lwTagList;
-
-
-/* an object */
-
-typedef struct st_lwObject {
-   lwLayer       *layer;               /* linked list of layers */
-   lwEnvelope    *env;                 /* linked list of envelopes */
-   lwClip        *clip;                /* linked list of clips */
-   lwSurface     *surf;                /* linked list of surfaces */
-   lwTagList      taglist;
-   int            nlayers;
-   int            nenvs;
-   int            nclips;
-   int            nsurfs;
-} lwObject;
-
-
-/* lwo2.c */
-
-void lwFreeLayer( lwLayer *layer );
-void lwFreeObject( lwObject *object );
-lwObject *lwGetObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
-int lwValidateObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
-
-/* pntspols.c */
-
-void lwFreePoints( lwPointList *point );
-void lwFreePolygons( lwPolygonList *plist );
-int lwGetPoints( picoMemStream_t *fp, int cksize, lwPointList *point );
-void lwGetBoundingBox( lwPointList *point, float bbox[] );
-int lwAllocPolygons( lwPolygonList *plist, int npols, int nverts );
-int lwGetPolygons( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset );
-void lwGetPolyNormals( lwPointList *point, lwPolygonList *polygon );
-int lwGetPointPolygons( lwPointList *point, lwPolygonList *polygon );
-int lwResolvePolySurfaces( lwPolygonList *polygon, lwTagList *tlist,
-   lwSurface **surf, int *nsurfs );
-void lwGetVertNormals( lwPointList *point, lwPolygonList *polygon );
-void lwFreeTags( lwTagList *tlist );
-int lwGetTags( picoMemStream_t *fp, int cksize, lwTagList *tlist );
-int lwGetPolygonTags( picoMemStream_t *fp, int cksize, lwTagList *tlist,
-   lwPolygonList *plist );
-
-/* vmap.c */
-
-void lwFreeVMap( lwVMap *vmap );
-lwVMap *lwGetVMap( picoMemStream_t *fp, int cksize, int ptoffset, int poloffset,
-   int perpoly );
-int lwGetPointVMaps( lwPointList *point, lwVMap *vmap );
-int lwGetPolyVMaps( lwPolygonList *polygon, lwVMap *vmap );
-
-/* clip.c */
-
-void lwFreeClip( lwClip *clip );
-lwClip *lwGetClip( picoMemStream_t *fp, int cksize );
-lwClip *lwFindClip( lwClip *list, int index );
-
-/* envelope.c */
-
-void lwFreeEnvelope( lwEnvelope *env );
-lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize );
-lwEnvelope *lwFindEnvelope( lwEnvelope *list, int index );
-float lwEvalEnvelope( lwEnvelope *env, float time );
-
-/* surface.c */
-
-void lwFreePlugin( lwPlugin *p );
-void lwFreeTexture( lwTexture *t );
-void lwFreeSurface( lwSurface *surf );
-int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex );
-int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap );
-int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex );
-int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex );
-int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex );
-lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type );
-lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz );
-lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize );
-lwSurface *lwDefaultSurface( void );
-
-/* lwob.c */
-
-lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj );
-int lwGetPolygons5( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset );
-lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
-int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
-
-/* list.c */
-
-void lwListFree( void *list, void ( *freeNode )( void * ));
-void lwListAdd( void **list, void *node );
-void lwListInsert( void **vlist, void *vitem,
-   int ( *compare )( void *, void * ));
-
-/* vecmath.c */
-
-float dot( float a[], float b[] );
-void cross( float a[], float b[], float c[] );
-void normalize( float v[] );
-#define vecangle( a, b ) ( float ) acos( dot( a, b ))
-
-/* lwio.c */
-
-void  set_flen( int i );
-int   get_flen( void );
-void *getbytes( picoMemStream_t *fp, int size );
-void  skipbytes( picoMemStream_t *fp, int n );
-int   getI1( picoMemStream_t *fp );
-short getI2( picoMemStream_t *fp );
-int   getI4( picoMemStream_t *fp );
-unsigned char  getU1( picoMemStream_t *fp );
-unsigned short getU2( picoMemStream_t *fp );
-unsigned int   getU4( picoMemStream_t *fp );
-int   getVX( picoMemStream_t *fp );
-float getF4( picoMemStream_t *fp );
-char *getS0( picoMemStream_t *fp );
-int   sgetI1( unsigned char **bp );
-short sgetI2( unsigned char **bp );
-int   sgetI4( unsigned char **bp );
-unsigned char  sgetU1( unsigned char **bp );
-unsigned short sgetU2( unsigned char **bp );
-unsigned int   sgetU4( unsigned char **bp );
-int   sgetVX( unsigned char **bp );
-float sgetF4( unsigned char **bp );
-char *sgetS0( unsigned char **bp );
-
-#ifdef _WIN32
-  void revbytes( void *bp, int elsize, int elcount );
-#else
-  #define revbytes( b, s, c )
-#endif
-
-#endif
+/*
+======================================================================
+lwo2.h
+
+Definitions and typedefs for LWO2 files.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#ifndef LWO2_H
+#define LWO2_H
+
+/* chunk and subchunk IDs */
+
+#define LWID_(a,b,c,d) (((a)<<24)|((b)<<16)|((c)<<8)|(d))
+
+#define ID_FORM  LWID_('F','O','R','M')
+#define ID_LWO2  LWID_('L','W','O','2')
+#define ID_LWOB  LWID_('L','W','O','B')
+
+/* top-level chunks */
+#define ID_LAYR  LWID_('L','A','Y','R')
+#define ID_TAGS  LWID_('T','A','G','S')
+#define ID_PNTS  LWID_('P','N','T','S')
+#define ID_BBOX  LWID_('B','B','O','X')
+#define ID_VMAP  LWID_('V','M','A','P')
+#define ID_VMAD  LWID_('V','M','A','D')
+#define ID_POLS  LWID_('P','O','L','S')
+#define ID_PTAG  LWID_('P','T','A','G')
+#define ID_ENVL  LWID_('E','N','V','L')
+#define ID_CLIP  LWID_('C','L','I','P')
+#define ID_SURF  LWID_('S','U','R','F')
+#define ID_DESC  LWID_('D','E','S','C')
+#define ID_TEXT  LWID_('T','E','X','T')
+#define ID_ICON  LWID_('I','C','O','N')
+
+/* polygon types */
+#define ID_FACE  LWID_('F','A','C','E')
+#define ID_CURV  LWID_('C','U','R','V')
+#define ID_PTCH  LWID_('P','T','C','H')
+#define ID_MBAL  LWID_('M','B','A','L')
+#define ID_BONE  LWID_('B','O','N','E')
+
+/* polygon tags */
+#define ID_SURF  LWID_('S','U','R','F')
+#define ID_PART  LWID_('P','A','R','T')
+#define ID_SMGP  LWID_('S','M','G','P')
+
+/* envelopes */
+#define ID_PRE   LWID_('P','R','E',' ')
+#define ID_POST  LWID_('P','O','S','T')
+#define ID_KEY   LWID_('K','E','Y',' ')
+#define ID_SPAN  LWID_('S','P','A','N')
+#define ID_TCB   LWID_('T','C','B',' ')
+#define ID_HERM  LWID_('H','E','R','M')
+#define ID_BEZI  LWID_('B','E','Z','I')
+#define ID_BEZ2  LWID_('B','E','Z','2')
+#define ID_LINE  LWID_('L','I','N','E')
+#define ID_STEP  LWID_('S','T','E','P')
+
+/* clips */
+#define ID_STIL  LWID_('S','T','I','L')
+#define ID_ISEQ  LWID_('I','S','E','Q')
+#define ID_ANIM  LWID_('A','N','I','M')
+#define ID_XREF  LWID_('X','R','E','F')
+#define ID_STCC  LWID_('S','T','C','C')
+#define ID_TIME  LWID_('T','I','M','E')
+#define ID_CONT  LWID_('C','O','N','T')
+#define ID_BRIT  LWID_('B','R','I','T')
+#define ID_SATR  LWID_('S','A','T','R')
+#define ID_HUE   LWID_('H','U','E',' ')
+#define ID_GAMM  LWID_('G','A','M','M')
+#define ID_NEGA  LWID_('N','E','G','A')
+#define ID_IFLT  LWID_('I','F','L','T')
+#define ID_PFLT  LWID_('P','F','L','T')
+
+/* surfaces */
+#define ID_COLR  LWID_('C','O','L','R')
+#define ID_LUMI  LWID_('L','U','M','I')
+#define ID_DIFF  LWID_('D','I','F','F')
+#define ID_SPEC  LWID_('S','P','E','C')
+#define ID_GLOS  LWID_('G','L','O','S')
+#define ID_REFL  LWID_('R','E','F','L')
+#define ID_RFOP  LWID_('R','F','O','P')
+#define ID_RIMG  LWID_('R','I','M','G')
+#define ID_RSAN  LWID_('R','S','A','N')
+#define ID_TRAN  LWID_('T','R','A','N')
+#define ID_TROP  LWID_('T','R','O','P')
+#define ID_TIMG  LWID_('T','I','M','G')
+#define ID_RIND  LWID_('R','I','N','D')
+#define ID_TRNL  LWID_('T','R','N','L')
+#define ID_BUMP  LWID_('B','U','M','P')
+#define ID_SMAN  LWID_('S','M','A','N')
+#define ID_SIDE  LWID_('S','I','D','E')
+#define ID_CLRH  LWID_('C','L','R','H')
+#define ID_CLRF  LWID_('C','L','R','F')
+#define ID_ADTR  LWID_('A','D','T','R')
+#define ID_SHRP  LWID_('S','H','R','P')
+#define ID_LINE  LWID_('L','I','N','E')
+#define ID_LSIZ  LWID_('L','S','I','Z')
+#define ID_ALPH  LWID_('A','L','P','H')
+#define ID_AVAL  LWID_('A','V','A','L')
+#define ID_GVAL  LWID_('G','V','A','L')
+#define ID_BLOK  LWID_('B','L','O','K')
+
+/* texture layer */
+#define ID_TYPE  LWID_('T','Y','P','E')
+#define ID_CHAN  LWID_('C','H','A','N')
+#define ID_NAME  LWID_('N','A','M','E')
+#define ID_ENAB  LWID_('E','N','A','B')
+#define ID_OPAC  LWID_('O','P','A','C')
+#define ID_FLAG  LWID_('F','L','A','G')
+#define ID_PROJ  LWID_('P','R','O','J')
+#define ID_STCK  LWID_('S','T','C','K')
+#define ID_TAMP  LWID_('T','A','M','P')
+
+/* texture coordinates */
+#define ID_TMAP  LWID_('T','M','A','P')
+#define ID_AXIS  LWID_('A','X','I','S')
+#define ID_CNTR  LWID_('C','N','T','R')
+#define ID_SIZE  LWID_('S','I','Z','E')
+#define ID_ROTA  LWID_('R','O','T','A')
+#define ID_OREF  LWID_('O','R','E','F')
+#define ID_FALL  LWID_('F','A','L','L')
+#define ID_CSYS  LWID_('C','S','Y','S')
+
+/* image map */
+#define ID_IMAP  LWID_('I','M','A','P')
+#define ID_IMAG  LWID_('I','M','A','G')
+#define ID_WRAP  LWID_('W','R','A','P')
+#define ID_WRPW  LWID_('W','R','P','W')
+#define ID_WRPH  LWID_('W','R','P','H')
+#define ID_VMAP  LWID_('V','M','A','P')
+#define ID_AAST  LWID_('A','A','S','T')
+#define ID_PIXB  LWID_('P','I','X','B')
+
+/* procedural */
+#define ID_PROC  LWID_('P','R','O','C')
+#define ID_COLR  LWID_('C','O','L','R')
+#define ID_VALU  LWID_('V','A','L','U')
+#define ID_FUNC  LWID_('F','U','N','C')
+#define ID_FTPS  LWID_('F','T','P','S')
+#define ID_ITPS  LWID_('I','T','P','S')
+#define ID_ETPS  LWID_('E','T','P','S')
+
+/* gradient */
+#define ID_GRAD  LWID_('G','R','A','D')
+#define ID_GRST  LWID_('G','R','S','T')
+#define ID_GREN  LWID_('G','R','E','N')
+#define ID_PNAM  LWID_('P','N','A','M')
+#define ID_INAM  LWID_('I','N','A','M')
+#define ID_GRPT  LWID_('G','R','P','T')
+#define ID_FKEY  LWID_('F','K','E','Y')
+#define ID_IKEY  LWID_('I','K','E','Y')
+
+/* shader */
+#define ID_SHDR  LWID_('S','H','D','R')
+#define ID_DATA  LWID_('D','A','T','A')
+
+
+/* generic linked list */
+
+typedef struct st_lwNode {
+   struct st_lwNode *next, *prev;
+   void *data;
+} lwNode;
+
+
+/* plug-in reference */
+
+typedef struct st_lwPlugin {
+   struct st_lwPlugin *next, *prev;
+   char          *ord;
+   char          *name;
+   int            flags;
+   void          *data;
+} lwPlugin;
+
+
+/* envelopes */
+
+typedef struct st_lwKey {
+   struct st_lwKey *next, *prev;
+   float          value;
+   float          time;
+   unsigned int   shape;               /* ID_TCB, ID_BEZ2, etc. */
+   float          tension;
+   float          continuity;
+   float          bias;
+   float          param[ 4 ];
+} lwKey;
+
+typedef struct st_lwEnvelope {
+   struct st_lwEnvelope *next, *prev;
+   int            index;
+   int            type;
+   char          *name;
+   lwKey         *key;                 /* linked list of keys */
+   int            nkeys;
+   int            behavior[ 2 ];       /* pre and post (extrapolation) */
+   lwPlugin      *cfilter;             /* linked list of channel filters */
+   int            ncfilters;
+} lwEnvelope;
+
+#define BEH_RESET      0
+#define BEH_CONSTANT   1
+#define BEH_REPEAT     2
+#define BEH_OSCILLATE  3
+#define BEH_OFFSET     4
+#define BEH_LINEAR     5
+
+
+/* values that can be enveloped */
+
+typedef struct st_lwEParam {
+   float          val;
+   int            eindex;
+} lwEParam;
+
+typedef struct st_lwVParam {
+   float          val[ 3 ];
+   int            eindex;
+} lwVParam;
+
+
+/* clips */
+
+typedef struct st_lwClipStill {
+   char          *name;
+} lwClipStill;
+
+typedef struct st_lwClipSeq {
+   char          *prefix;              /* filename before sequence digits */
+   char          *suffix;              /* after digits, e.g. extensions */
+   int            digits;
+   int            flags;
+   int            offset;
+   int            start;
+   int            end;
+} lwClipSeq;
+
+typedef struct st_lwClipAnim {
+   char          *name;
+   char          *server;              /* anim loader plug-in */
+   void          *data;
+} lwClipAnim;
+
+typedef struct st_lwClipXRef {
+   char          *string;
+   int            index;
+   struct st_lwClip *clip;
+} lwClipXRef;
+
+typedef struct st_lwClipCycle {
+   char          *name;
+   int            lo;
+   int            hi;
+} lwClipCycle;
+
+typedef struct st_lwClip {
+   struct st_lwClip *next, *prev;
+   int            index;
+   unsigned int   type;                /* ID_STIL, ID_ISEQ, etc. */
+   union {
+      lwClipStill    still;
+      lwClipSeq      seq;
+      lwClipAnim     anim;
+      lwClipXRef     xref;
+      lwClipCycle    cycle;
+   }              source;
+   float          start_time;
+   float          duration;
+   float          frame_rate;
+   lwEParam       contrast;
+   lwEParam       brightness;
+   lwEParam       saturation;
+   lwEParam       hue;
+   lwEParam       gamma;
+   int            negative;
+   lwPlugin      *ifilter;             /* linked list of image filters */
+   int            nifilters;
+   lwPlugin      *pfilter;             /* linked list of pixel filters */
+   int            npfilters;
+} lwClip;
+
+
+/* textures */
+
+typedef struct st_lwTMap {
+   lwVParam       size;
+   lwVParam       center;
+   lwVParam       rotate;
+   lwVParam       falloff;
+   int            fall_type;
+   char          *ref_object;
+   int            coord_sys;
+} lwTMap;
+
+typedef struct st_lwImageMap {
+   int            cindex;
+   int            projection;
+   char          *vmap_name;
+   int            axis;
+   int            wrapw_type;
+   int            wraph_type;
+   lwEParam       wrapw;
+   lwEParam       wraph;
+   float          aa_strength;
+   int            aas_flags;
+   int            pblend;
+   lwEParam       stck;
+   lwEParam       amplitude;
+} lwImageMap;
+
+#define PROJ_PLANAR       0
+#define PROJ_CYLINDRICAL  1
+#define PROJ_SPHERICAL    2
+#define PROJ_CUBIC        3
+#define PROJ_FRONT        4
+
+#define WRAP_NONE    0
+#define WRAP_EDGE    1
+#define WRAP_REPEAT  2
+#define WRAP_MIRROR  3
+
+typedef struct st_lwProcedural {
+   int            axis;
+   float          value[ 3 ];
+   char          *name;
+   void          *data;
+} lwProcedural;
+
+typedef struct st_lwGradKey {
+   struct st_lwGradKey *next, *prev;
+   float          value;
+   float          rgba[ 4 ];
+} lwGradKey;
+
+typedef struct st_lwGradient {
+   char          *paramname;
+   char          *itemname;
+   float          start;
+   float          end;
+   int            repeat;
+   lwGradKey     *key;                 /* array of gradient keys */
+   short         *ikey;                /* array of interpolation codes */
+} lwGradient;
+
+typedef struct st_lwTexture {
+   struct st_lwTexture *next, *prev;
+   char          *ord;
+   unsigned int   type;
+   unsigned int   chan;
+   lwEParam       opacity;
+   short          opac_type;
+   short          enabled;
+   short          negative;
+   short          axis;
+   union {
+      lwImageMap     imap;
+      lwProcedural   proc;
+      lwGradient     grad;
+   }              param;
+   lwTMap         tmap;
+} lwTexture;
+
+
+/* values that can be textured */
+
+typedef struct st_lwTParam {
+   float          val;
+   int            eindex;
+   lwTexture     *tex;                 /* linked list of texture layers */
+} lwTParam;
+
+typedef struct st_lwCParam {
+   float          rgb[ 3 ];
+   int            eindex;
+   lwTexture     *tex;                 /* linked list of texture layers */
+} lwCParam;
+
+
+/* surfaces */
+
+typedef struct st_lwGlow {
+   short          enabled;
+   short          type;
+   lwEParam       intensity;
+   lwEParam       size;
+} Glow;
+
+typedef struct st_lwRMap {
+   lwTParam       val;
+   int            options;
+   int            cindex;
+   float          seam_angle;
+} lwRMap;
+
+typedef struct st_lwLine {
+   short          enabled;
+   unsigned short flags;
+   lwEParam       size;
+} lwLine;
+
+typedef struct st_lwSurface {
+   struct st_lwSurface *next, *prev;
+   char          *name;
+   char          *srcname;
+   lwCParam       color;
+   lwTParam       luminosity;
+   lwTParam       diffuse;
+   lwTParam       specularity;
+   lwTParam       glossiness;
+   lwRMap         reflection;
+   lwRMap         transparency;
+   lwTParam       eta;
+   lwTParam       translucency;
+   lwTParam       bump;
+   float          smooth;
+   int            sideflags;
+   float          alpha;
+   int            alpha_mode;
+   lwEParam       color_hilite;
+   lwEParam       color_filter;
+   lwEParam       add_trans;
+   lwEParam       dif_sharp;
+   lwEParam       glow;
+   lwLine         line;
+   lwPlugin      *shader;              /* linked list of shaders */
+   int            nshaders;
+} lwSurface;
+
+
+/* vertex maps */
+
+typedef struct st_lwVMap {
+   struct st_lwVMap *next, *prev;
+   char          *name;
+   unsigned int   type;
+   int            dim;
+   int            nverts;
+   int            perpoly;
+   int           *vindex;              /* array of point indexes */
+   int           *pindex;              /* array of polygon indexes */
+   float        **val;
+} lwVMap;
+
+typedef struct st_lwVMapPt {
+   lwVMap        *vmap;
+   int            index;               /* vindex or pindex element */
+} lwVMapPt;
+
+
+/* points and polygons */
+
+typedef struct st_lwPoint {
+   float          pos[ 3 ];
+   int            npols;               /* number of polygons sharing the point */
+   int           *pol;                 /* array of polygon indexes */
+   int            nvmaps;
+   lwVMapPt      *vm;                  /* array of vmap references */
+} lwPoint;
+
+typedef struct st_lwPolVert {
+   int            index;               /* index into the point array */
+   float          norm[ 3 ];
+   int            nvmaps;
+   lwVMapPt      *vm;                  /* array of vmap references */
+} lwPolVert;
+
+typedef struct st_lwPolygon {
+   lwSurface     *surf;
+   int            part;                /* part index */
+   int            smoothgrp;           /* smoothing group */
+   int            flags;
+   unsigned int   type;
+   float          norm[ 3 ];
+   int            nverts;
+   lwPolVert     *v;                   /* array of vertex records */
+} lwPolygon;
+
+typedef struct st_lwPointList {
+   int            count;
+   int            offset;              /* only used during reading */
+   lwPoint       *pt;                  /* array of points */
+} lwPointList;
+
+typedef struct st_lwPolygonList {
+   int            count;
+   int            offset;              /* only used during reading */
+   int            vcount;              /* total number of vertices */
+   int            voffset;             /* only used during reading */
+   lwPolygon     *pol;                 /* array of polygons */
+} lwPolygonList;
+
+
+/* geometry layers */
+
+typedef struct st_lwLayer {
+   struct st_lwLayer *next, *prev;
+   char          *name;
+   int            index;
+   int            parent;
+   int            flags;
+   float          pivot[ 3 ];
+   float          bbox[ 6 ];
+   lwPointList    point;
+   lwPolygonList  polygon;
+   int            nvmaps;
+   lwVMap        *vmap;                /* linked list of vmaps */
+} lwLayer;
+
+
+/* tag strings */
+
+typedef struct st_lwTagList {
+   int            count;
+   int            offset;              /* only used during reading */
+   char         **tag;                 /* array of strings */
+} lwTagList;
+
+
+/* an object */
+
+typedef struct st_lwObject {
+   lwLayer       *layer;               /* linked list of layers */
+   lwEnvelope    *env;                 /* linked list of envelopes */
+   lwClip        *clip;                /* linked list of clips */
+   lwSurface     *surf;                /* linked list of surfaces */
+   lwTagList      taglist;
+   int            nlayers;
+   int            nenvs;
+   int            nclips;
+   int            nsurfs;
+} lwObject;
+
+
+/* lwo2.c */
+
+void lwFreeLayer( lwLayer *layer );
+void lwFreeObject( lwObject *object );
+lwObject *lwGetObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
+int lwValidateObject( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
+
+/* pntspols.c */
+
+void lwFreePoints( lwPointList *point );
+void lwFreePolygons( lwPolygonList *plist );
+int lwGetPoints( picoMemStream_t *fp, int cksize, lwPointList *point );
+void lwGetBoundingBox( lwPointList *point, float bbox[] );
+int lwAllocPolygons( lwPolygonList *plist, int npols, int nverts );
+int lwGetPolygons( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset );
+void lwGetPolyNormals( lwPointList *point, lwPolygonList *polygon );
+int lwGetPointPolygons( lwPointList *point, lwPolygonList *polygon );
+int lwResolvePolySurfaces( lwPolygonList *polygon, lwTagList *tlist,
+   lwSurface **surf, int *nsurfs );
+void lwGetVertNormals( lwPointList *point, lwPolygonList *polygon );
+void lwFreeTags( lwTagList *tlist );
+int lwGetTags( picoMemStream_t *fp, int cksize, lwTagList *tlist );
+int lwGetPolygonTags( picoMemStream_t *fp, int cksize, lwTagList *tlist,
+   lwPolygonList *plist );
+
+/* vmap.c */
+
+void lwFreeVMap( lwVMap *vmap );
+lwVMap *lwGetVMap( picoMemStream_t *fp, int cksize, int ptoffset, int poloffset,
+   int perpoly );
+int lwGetPointVMaps( lwPointList *point, lwVMap *vmap );
+int lwGetPolyVMaps( lwPolygonList *polygon, lwVMap *vmap );
+
+/* clip.c */
+
+void lwFreeClip( lwClip *clip );
+lwClip *lwGetClip( picoMemStream_t *fp, int cksize );
+lwClip *lwFindClip( lwClip *list, int index );
+
+/* envelope.c */
+
+void lwFreeEnvelope( lwEnvelope *env );
+lwEnvelope *lwGetEnvelope( picoMemStream_t *fp, int cksize );
+lwEnvelope *lwFindEnvelope( lwEnvelope *list, int index );
+float lwEvalEnvelope( lwEnvelope *env, float time );
+
+/* surface.c */
+
+void lwFreePlugin( lwPlugin *p );
+void lwFreeTexture( lwTexture *t );
+void lwFreeSurface( lwSurface *surf );
+int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex );
+int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap );
+int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex );
+int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex );
+int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex );
+lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type );
+lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz );
+lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize );
+lwSurface *lwDefaultSurface( void );
+
+/* lwob.c */
+
+lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj );
+int lwGetPolygons5( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset );
+lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
+int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos );
+
+/* list.c */
+
+void lwListFree( void *list, void ( *freeNode )( void * ));
+void lwListAdd( void **list, void *node );
+void lwListInsert( void **vlist, void *vitem,
+   int ( *compare )( void *, void * ));
+
+/* vecmath.c */
+
+float dot( float a[], float b[] );
+void cross( float a[], float b[], float c[] );
+void normalize( float v[] );
+#define vecangle( a, b ) ( float ) acos( dot( a, b ))
+
+/* lwio.c */
+
+void  set_flen( int i );
+int   get_flen( void );
+void *getbytes( picoMemStream_t *fp, int size );
+void  skipbytes( picoMemStream_t *fp, int n );
+int   getI1( picoMemStream_t *fp );
+short getI2( picoMemStream_t *fp );
+int   getI4( picoMemStream_t *fp );
+unsigned char  getU1( picoMemStream_t *fp );
+unsigned short getU2( picoMemStream_t *fp );
+unsigned int   getU4( picoMemStream_t *fp );
+int   getVX( picoMemStream_t *fp );
+float getF4( picoMemStream_t *fp );
+char *getS0( picoMemStream_t *fp );
+int   sgetI1( unsigned char **bp );
+short sgetI2( unsigned char **bp );
+int   sgetI4( unsigned char **bp );
+unsigned char  sgetU1( unsigned char **bp );
+unsigned short sgetU2( unsigned char **bp );
+unsigned int   sgetU4( unsigned char **bp );
+int   sgetVX( unsigned char **bp );
+float sgetF4( unsigned char **bp );
+char *sgetS0( unsigned char **bp );
+
+#ifdef _WIN32
+  void revbytes( void *bp, int elsize, int elcount );
+#else
+  #define revbytes( b, s, c )
+#endif
+
+#endif
diff --git a/libs/picomodel/lwo/lwob.c b/libs/picomodel/lwo/lwob.c
index 0e386a30..edf42cff 100644
--- a/libs/picomodel/lwo/lwob.c
+++ b/libs/picomodel/lwo/lwob.c
@@ -1,723 +1,723 @@
-/*
-======================================================================
-lwob.c
-
-Functions for an LWOB reader.  LWOB is the LightWave object format
-for versions of LW prior to 6.0.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-/* disable warnings */
-#ifdef _WIN32
-#pragma warning( disable:4018 )		/* signed/unsigned mismatch */
-#endif
-
-
-/* IDs specific to LWOB */
-
-#define ID_SRFS  LWID_('S','R','F','S')
-#define ID_FLAG  LWID_('F','L','A','G')
-#define ID_VLUM  LWID_('V','L','U','M')
-#define ID_VDIF  LWID_('V','D','I','F')
-#define ID_VSPC  LWID_('V','S','P','C')
-#define ID_RFLT  LWID_('R','F','L','T')
-#define ID_BTEX  LWID_('B','T','E','X')
-#define ID_CTEX  LWID_('C','T','E','X')
-#define ID_DTEX  LWID_('D','T','E','X')
-#define ID_LTEX  LWID_('L','T','E','X')
-#define ID_RTEX  LWID_('R','T','E','X')
-#define ID_STEX  LWID_('S','T','E','X')
-#define ID_TTEX  LWID_('T','T','E','X')
-#define ID_TFLG  LWID_('T','F','L','G')
-#define ID_TSIZ  LWID_('T','S','I','Z')
-#define ID_TCTR  LWID_('T','C','T','R')
-#define ID_TFAL  LWID_('T','F','A','L')
-#define ID_TVEL  LWID_('T','V','E','L')
-#define ID_TCLR  LWID_('T','C','L','R')
-#define ID_TVAL  LWID_('T','V','A','L')
-#define ID_TAMP  LWID_('T','A','M','P')
-#define ID_TIMG  LWID_('T','I','M','G')
-#define ID_TAAS  LWID_('T','A','A','S')
-#define ID_TREF  LWID_('T','R','E','F')
-#define ID_TOPC  LWID_('T','O','P','C')
-#define ID_SDAT  LWID_('S','D','A','T')
-#define ID_TFP0  LWID_('T','F','P','0')
-#define ID_TFP1  LWID_('T','F','P','1')
-
-
-/*
-======================================================================
-add_clip()
-
-Add a clip to the clip list.  Used to store the contents of an RIMG or
-TIMG surface subchunk.
-====================================================================== */
-
-static int add_clip( char *s, lwClip **clist, int *nclips )
-{
-   lwClip *clip;
-   char *p;
-
-   clip = _pico_calloc( 1, sizeof( lwClip ));
-   if ( !clip ) return 0;
-
-   clip->contrast.val = 1.0f;
-   clip->brightness.val = 1.0f;
-   clip->saturation.val = 1.0f;
-   clip->gamma.val = 1.0f;
-
-   if ( p = strstr( s, "(sequence)" )) {
-      p[ -1 ] = 0;
-      clip->type = ID_ISEQ;
-      clip->source.seq.prefix = s;
-      clip->source.seq.digits = 3;
-   }
-   else {
-      clip->type = ID_STIL;
-      clip->source.still.name = s;
-   }
-
-   *nclips++;
-   clip->index = *nclips;
-
-   lwListAdd( clist, clip );
-
-   return clip->index;
-}
-
-
-/*
-======================================================================
-add_tvel()
-
-Add a triple of envelopes to simulate the old texture velocity
-parameters.
-====================================================================== */
-
-static int add_tvel( float pos[], float vel[], lwEnvelope **elist, int *nenvs )
-{
-   lwEnvelope *env;
-   lwKey *key0, *key1;
-   int i;
-
-   for ( i = 0; i < 3; i++ ) {
-      env = _pico_calloc( 1, sizeof( lwEnvelope ));
-      key0 = _pico_calloc( 1, sizeof( lwKey ));
-      key1 = _pico_calloc( 1, sizeof( lwKey ));
-      if ( !env || !key0 || !key1 ) return 0;
-
-      key0->next = key1;
-      key0->value = pos[ i ];
-      key0->time = 0.0f;
-      key1->prev = key0;
-      key1->value = pos[ i ] + vel[ i ] * 30.0f;
-      key1->time = 1.0f;
-      key0->shape = key1->shape = ID_LINE;
-
-      env->index = *nenvs + i + 1;
-      env->type = 0x0301 + i;
-      env->name = _pico_alloc( 11 );
-      if ( env->name ) {
-         strcpy( env->name, "Position.X" );
-         env->name[ 9 ] += i;
-      }
-      env->key = key0;
-      env->nkeys = 2;
-      env->behavior[ 0 ] = BEH_LINEAR;
-      env->behavior[ 1 ] = BEH_LINEAR;
-
-      lwListAdd( elist, env );
-   }
-
-   *nenvs += 3;
-   return env->index - 2;
-}
-
-
-/*
-======================================================================
-get_texture()
-
-Create a new texture for BTEX, CTEX, etc. subchunks.
-====================================================================== */
-
-static lwTexture *get_texture( char *s )
-{
-   lwTexture *tex;
-
-   tex = _pico_calloc( 1, sizeof( lwTexture ));
-   if ( !tex ) return NULL;
-
-   tex->tmap.size.val[ 0 ] =
-   tex->tmap.size.val[ 1 ] =
-   tex->tmap.size.val[ 2 ] = 1.0f;
-   tex->opacity.val = 1.0f;
-   tex->enabled = 1;
-
-   if ( strstr( s, "Image Map" )) {
-      tex->type = ID_IMAP;
-      if ( strstr( s, "Planar" ))           tex->param.imap.projection = 0;
-      else if ( strstr( s, "Cylindrical" )) tex->param.imap.projection = 1;
-      else if ( strstr( s, "Spherical" ))   tex->param.imap.projection = 2;
-      else if ( strstr( s, "Cubic" ))       tex->param.imap.projection = 3;
-      else if ( strstr( s, "Front" ))       tex->param.imap.projection = 4;
-      tex->param.imap.aa_strength = 1.0f;
-      tex->param.imap.amplitude.val = 1.0f;
-      _pico_free( s );
-   }
-   else {
-      tex->type = ID_PROC;
-      tex->param.proc.name = s;
-   }
-
-   return tex;
-}
-
-
-/*
-======================================================================
-lwGetSurface5()
-
-Read an lwSurface from an LWOB file.
-====================================================================== */
-
-lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj )
-{
-   lwSurface *surf;
-   lwTexture *tex;
-   lwPlugin *shdr;
-   char *s;
-   float v[ 3 ];
-   unsigned int id, flags;
-   unsigned short sz;
-   int pos, rlen, i;
-
-
-   /* allocate the Surface structure */
-
-   surf = _pico_calloc( 1, sizeof( lwSurface ));
-   if ( !surf ) goto Fail;
-
-   /* non-zero defaults */
-
-   surf->color.rgb[ 0 ] = 0.78431f;
-   surf->color.rgb[ 1 ] = 0.78431f;
-   surf->color.rgb[ 2 ] = 0.78431f;
-   surf->diffuse.val    = 1.0f;
-   surf->glossiness.val = 0.4f;
-   surf->bump.val       = 1.0f;
-   surf->eta.val        = 1.0f;
-   surf->sideflags      = 1;
-
-   /* remember where we started */
-
-   set_flen( 0 );
-   pos = _pico_memstream_tell( fp );
-
-   /* name */
-
-   surf->name = getS0( fp );
-
-   /* first subchunk header */
-
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   /* process subchunks as they're encountered */
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_COLR:
-            surf->color.rgb[ 0 ] = getU1( fp ) / 255.0f;
-            surf->color.rgb[ 1 ] = getU1( fp ) / 255.0f;
-            surf->color.rgb[ 2 ] = getU1( fp ) / 255.0f;
-            break;
-
-         case ID_FLAG:
-            flags = getU2( fp );
-            if ( flags &   4 ) surf->smooth = 1.56207f;
-            if ( flags &   8 ) surf->color_hilite.val = 1.0f;
-            if ( flags &  16 ) surf->color_filter.val = 1.0f;
-            if ( flags & 128 ) surf->dif_sharp.val = 0.5f;
-            if ( flags & 256 ) surf->sideflags = 3;
-            if ( flags & 512 ) surf->add_trans.val = 1.0f;
-            break;
-
-         case ID_LUMI:
-            surf->luminosity.val = getI2( fp ) / 256.0f;
-            break;
-
-         case ID_VLUM:
-            surf->luminosity.val = getF4( fp );
-            break;
-
-         case ID_DIFF:
-            surf->diffuse.val = getI2( fp ) / 256.0f;
-            break;
-
-         case ID_VDIF:
-            surf->diffuse.val = getF4( fp );
-            break;
-
-         case ID_SPEC:
-            surf->specularity.val = getI2( fp ) / 256.0f;
-            break;
-
-         case ID_VSPC:
-            surf->specularity.val = getF4( fp );
-            break;
-
-         case ID_GLOS:
-            surf->glossiness.val = ( float ) log( getU2( fp )) / 20.7944f;
-            break;
-
-         case ID_SMAN:
-            surf->smooth = getF4( fp );
-            break;
-
-         case ID_REFL:
-            surf->reflection.val.val = getI2( fp ) / 256.0f;
-            break;
-
-         case ID_RFLT:
-            surf->reflection.options = getU2( fp );
-            break;
-
-         case ID_RIMG:
-            s = getS0( fp );
-            surf->reflection.cindex = add_clip( s, &obj->clip, &obj->nclips );
-            surf->reflection.options = 3;
-            break;
-
-         case ID_RSAN:
-            surf->reflection.seam_angle = getF4( fp );
-            break;
-
-         case ID_TRAN:
-            surf->transparency.val.val = getI2( fp ) / 256.0f;
-            break;
-
-         case ID_RIND:
-            surf->eta.val = getF4( fp );
-            break;
-
-         case ID_BTEX:
-            s = getbytes( fp, sz );
-            tex = get_texture( s );
-            lwListAdd( &surf->bump.tex, tex );
-            break;
-
-         case ID_CTEX:
-            s = getbytes( fp, sz );
-            tex = get_texture( s );
-            lwListAdd( &surf->color.tex, tex );
-            break;
-
-         case ID_DTEX:
-            s = getbytes( fp, sz );
-            tex = get_texture( s );
-            lwListAdd( &surf->diffuse.tex, tex );
-            break;
-
-         case ID_LTEX:
-            s = getbytes( fp, sz );
-            tex = get_texture( s );
-            lwListAdd( &surf->luminosity.tex, tex );
-            break;
-
-         case ID_RTEX:
-            s = getbytes( fp, sz );
-            tex = get_texture( s );
-            lwListAdd( &surf->reflection.val.tex, tex );
-            break;
-
-         case ID_STEX:
-            s = getbytes( fp, sz );
-            tex = get_texture( s );
-            lwListAdd( &surf->specularity.tex, tex );
-            break;
-
-         case ID_TTEX:
-            s = getbytes( fp, sz );
-            tex = get_texture( s );
-            lwListAdd( &surf->transparency.val.tex, tex );
-            break;
-
-         case ID_TFLG:
-            flags = getU2( fp );
-
-            if ( flags & 1 ) i = 0;
-            if ( flags & 2 ) i = 1;
-            if ( flags & 4 ) i = 2;
-            tex->axis = i;
-            if ( tex->type == ID_IMAP )
-               tex->param.imap.axis = i;
-            else
-               tex->param.proc.axis = i;
-
-            if ( flags &  8 ) tex->tmap.coord_sys = 1;
-            if ( flags & 16 ) tex->negative = 1;
-            if ( flags & 32 ) tex->param.imap.pblend = 1;
-            if ( flags & 64 ) {
-               tex->param.imap.aa_strength = 1.0f;
-               tex->param.imap.aas_flags = 1;
-            }
-            break;
-
-         case ID_TSIZ:
-            for ( i = 0; i < 3; i++ )
-               tex->tmap.size.val[ i ] = getF4( fp );
-            break;
-
-         case ID_TCTR:
-            for ( i = 0; i < 3; i++ )
-               tex->tmap.center.val[ i ] = getF4( fp );
-            break;
-
-         case ID_TFAL:
-            for ( i = 0; i < 3; i++ )
-               tex->tmap.falloff.val[ i ] = getF4( fp );
-            break;
-
-         case ID_TVEL:
-            for ( i = 0; i < 3; i++ )
-               v[ i ] = getF4( fp );
-            tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v,
-               &obj->env, &obj->nenvs );
-            break;
-
-         case ID_TCLR:
-            if ( tex->type == ID_PROC )
-               for ( i = 0; i < 3; i++ )
-                  tex->param.proc.value[ i ] = getU1( fp ) / 255.0f;
-            break;
-
-         case ID_TVAL:
-            tex->param.proc.value[ 0 ] = getI2( fp ) / 256.0f;
-            break;
-
-         case ID_TAMP:
-            if ( tex->type == ID_IMAP )
-               tex->param.imap.amplitude.val = getF4( fp );
-            break;
-
-         case ID_TIMG:
-            s = getS0( fp );
-            tex->param.imap.cindex = add_clip( s, &obj->clip, &obj->nclips );
-            break;
-
-         case ID_TAAS:
-            tex->param.imap.aa_strength = getF4( fp );
-            tex->param.imap.aas_flags = 1;
-            break;
-
-         case ID_TREF:
-            tex->tmap.ref_object = getbytes( fp, sz );
-            break;
-
-         case ID_TOPC:
-            tex->opacity.val = getF4( fp );
-            break;
-
-         case ID_TFP0:
-            if ( tex->type == ID_IMAP )
-               tex->param.imap.wrapw.val = getF4( fp );
-            break;
-
-         case ID_TFP1:
-            if ( tex->type == ID_IMAP )
-               tex->param.imap.wraph.val = getF4( fp );
-            break;
-
-         case ID_SHDR:
-            shdr = _pico_calloc( 1, sizeof( lwPlugin ));
-            if ( !shdr ) goto Fail;
-            shdr->name = getbytes( fp, sz );
-            lwListAdd( &surf->shader, shdr );
-            surf->nshaders++;
-            break;
-
-         case ID_SDAT:
-            shdr->data = getbytes( fp, sz );
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) goto Fail;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the SURF chunk? */
-
-      if ( cksize <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) goto Fail;
-   }
-
-   return surf;
-
-Fail:
-   if ( surf ) lwFreeSurface( surf );
-   return NULL;
-}
-
-
-/*
-======================================================================
-lwGetPolygons5()
-
-Read polygon records from a POLS chunk in an LWOB file.  The polygons
-are added to the array in the lwPolygonList.
-====================================================================== */
-
-int lwGetPolygons5( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset )
-{
-   lwPolygon *pp;
-   lwPolVert *pv;
-   unsigned char *buf, *bp;
-   int i, j, nv, nverts, npols;
-
-
-   if ( cksize == 0 ) return 1;
-
-   /* read the whole chunk */
-
-   set_flen( 0 );
-   buf = getbytes( fp, cksize );
-   if ( !buf ) goto Fail;
-
-   /* count the polygons and vertices */
-
-   nverts = 0;
-   npols = 0;
-   bp = buf;
-
-   while ( bp < buf + cksize ) {
-      nv = sgetU2( &bp );
-      nverts += nv;
-      npols++;
-      bp += 2 * nv;
-      i = sgetI2( &bp );
-      if ( i < 0 ) bp += 2;      /* detail polygons */
-   }
-
-   if ( !lwAllocPolygons( plist, npols, nverts ))
-      goto Fail;
-
-   /* fill in the new polygons */
-
-   bp = buf;
-   pp = plist->pol + plist->offset;
-   pv = plist->pol[ 0 ].v + plist->voffset;
-
-   for ( i = 0; i < npols; i++ ) {
-      nv = sgetU2( &bp );
-
-      pp->nverts = nv;
-      pp->type = ID_FACE;
-      if ( !pp->v ) pp->v = pv;
-      for ( j = 0; j < nv; j++ )
-         pv[ j ].index = sgetU2( &bp ) + ptoffset;
-      j = sgetI2( &bp );
-      if ( j < 0 ) {
-         j = -j;
-         bp += 2;
-      }
-      j -= 1;
-      pp->surf = ( lwSurface * ) j;
-
-      pp++;
-      pv += nv;
-   }
-
-   _pico_free( buf );
-   return 1;
-
-Fail:
-   if ( buf ) _pico_free( buf );
-   lwFreePolygons( plist );
-   return 0;
-}
-
-
-/*
-======================================================================
-getLWObject5()
-
-Returns the contents of an LWOB, given its filename, or NULL if the
-file couldn't be loaded.  On failure, failID and failpos can be used
-to diagnose the cause.
-
-1.  If the file isn't an LWOB, failpos will contain 12 and failID will
-    be unchanged.
-
-2.  If an error occurs while reading an LWOB, failID will contain the
-    most recently read IFF chunk ID, and failpos will contain the
-    value returned by _pico_memstream_tell() at the time of the failure.
-
-3.  If the file couldn't be opened, or an error occurs while reading
-    the first 12 bytes, both failID and failpos will be unchanged.
-
-If you don't need this information, failID and failpos can be NULL.
-====================================================================== */
-
-lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
-{
-   lwObject *object;
-   lwLayer *layer;
-   lwNode *node;
-   unsigned int id, formsize, type, cksize;
-
-
-   /* open the file */
-
-   if ( !fp ) return NULL;
-
-   /* read the first 12 bytes */
-
-   set_flen( 0 );
-   id       = getU4( fp );
-   formsize = getU4( fp );
-   type     = getU4( fp );
-   if ( 12 != get_flen() ) {
-      return NULL;
-   }
-
-   /* LWOB? */
-
-   if ( id != ID_FORM || type != ID_LWOB ) {
-      if ( failpos ) *failpos = 12;
-      return NULL;
-   }
-
-   /* allocate an object and a default layer */
-
-   object = _pico_calloc( 1, sizeof( lwObject ));
-   if ( !object ) goto Fail;
-
-   layer = _pico_calloc( 1, sizeof( lwLayer ));
-   if ( !layer ) goto Fail;
-   object->layer = layer;
-   object->nlayers = 1;
-
-   /* get the first chunk header */
-
-   id = getU4( fp );
-   cksize = getU4( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   /* process chunks as they're encountered */
-
-   while ( 1 ) {
-      cksize += cksize & 1;
-
-      switch ( id )
-      {
-         case ID_PNTS:
-            if ( !lwGetPoints( fp, cksize, &layer->point ))
-               goto Fail;
-            break;
-
-         case ID_POLS:
-            if ( !lwGetPolygons5( fp, cksize, &layer->polygon,
-               layer->point.offset ))
-               goto Fail;
-            break;
-
-         case ID_SRFS:
-            if ( !lwGetTags( fp, cksize, &object->taglist ))
-               goto Fail;
-            break;
-
-         case ID_SURF:
-            node = ( lwNode * ) lwGetSurface5( fp, cksize, object );
-            if ( !node ) goto Fail;
-            lwListAdd( &object->surf, node );
-            object->nsurfs++;
-            break;
-
-         default:
-            _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR );
-            break;
-      }
-
-      /* end of the file? */
-
-      if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break;
-
-      /* get the next chunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      cksize = getU4( fp );
-      if ( 8 != get_flen() ) goto Fail;
-   }
-
-   lwGetBoundingBox( &layer->point, layer->bbox );
-   lwGetPolyNormals( &layer->point, &layer->polygon );
-   if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail;
-   if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist,
-      &object->surf, &object->nsurfs )) goto Fail;
-   lwGetVertNormals( &layer->point, &layer->polygon );
-
-   return object;
-
-Fail:
-   if ( failID ) *failID = id;
-   if ( fp ) {
-      if ( failpos ) *failpos = _pico_memstream_tell( fp );
-   }
-   lwFreeObject( object );
-   return NULL;
-}
-
-int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
-{
-   unsigned int id, formsize, type;
-
-
-   /* open the file */
-
-   if ( !fp ) return PICO_PMV_ERROR_MEMORY;
-
-   /* read the first 12 bytes */
-
-   set_flen( 0 );
-   id       = getU4( fp );
-   formsize = getU4( fp );
-   type     = getU4( fp );
-   if ( 12 != get_flen() ) {
-      return PICO_PMV_ERROR_SIZE;
-   }
-
-   /* LWOB? */
-
-   if ( id != ID_FORM || type != ID_LWOB ) {
-      if ( failpos ) *failpos = 12;
-      return PICO_PMV_ERROR_IDENT;
-   }
-
-   return PICO_PMV_OK;
-}
+/*
+======================================================================
+lwob.c
+
+Functions for an LWOB reader.  LWOB is the LightWave object format
+for versions of LW prior to 6.0.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+/* disable warnings */
+#ifdef _WIN32
+#pragma warning( disable:4018 )		/* signed/unsigned mismatch */
+#endif
+
+
+/* IDs specific to LWOB */
+
+#define ID_SRFS  LWID_('S','R','F','S')
+#define ID_FLAG  LWID_('F','L','A','G')
+#define ID_VLUM  LWID_('V','L','U','M')
+#define ID_VDIF  LWID_('V','D','I','F')
+#define ID_VSPC  LWID_('V','S','P','C')
+#define ID_RFLT  LWID_('R','F','L','T')
+#define ID_BTEX  LWID_('B','T','E','X')
+#define ID_CTEX  LWID_('C','T','E','X')
+#define ID_DTEX  LWID_('D','T','E','X')
+#define ID_LTEX  LWID_('L','T','E','X')
+#define ID_RTEX  LWID_('R','T','E','X')
+#define ID_STEX  LWID_('S','T','E','X')
+#define ID_TTEX  LWID_('T','T','E','X')
+#define ID_TFLG  LWID_('T','F','L','G')
+#define ID_TSIZ  LWID_('T','S','I','Z')
+#define ID_TCTR  LWID_('T','C','T','R')
+#define ID_TFAL  LWID_('T','F','A','L')
+#define ID_TVEL  LWID_('T','V','E','L')
+#define ID_TCLR  LWID_('T','C','L','R')
+#define ID_TVAL  LWID_('T','V','A','L')
+#define ID_TAMP  LWID_('T','A','M','P')
+#define ID_TIMG  LWID_('T','I','M','G')
+#define ID_TAAS  LWID_('T','A','A','S')
+#define ID_TREF  LWID_('T','R','E','F')
+#define ID_TOPC  LWID_('T','O','P','C')
+#define ID_SDAT  LWID_('S','D','A','T')
+#define ID_TFP0  LWID_('T','F','P','0')
+#define ID_TFP1  LWID_('T','F','P','1')
+
+
+/*
+======================================================================
+add_clip()
+
+Add a clip to the clip list.  Used to store the contents of an RIMG or
+TIMG surface subchunk.
+====================================================================== */
+
+static int add_clip( char *s, lwClip **clist, int *nclips )
+{
+   lwClip *clip;
+   char *p;
+
+   clip = _pico_calloc( 1, sizeof( lwClip ));
+   if ( !clip ) return 0;
+
+   clip->contrast.val = 1.0f;
+   clip->brightness.val = 1.0f;
+   clip->saturation.val = 1.0f;
+   clip->gamma.val = 1.0f;
+
+   if ( p = strstr( s, "(sequence)" )) {
+      p[ -1 ] = 0;
+      clip->type = ID_ISEQ;
+      clip->source.seq.prefix = s;
+      clip->source.seq.digits = 3;
+   }
+   else {
+      clip->type = ID_STIL;
+      clip->source.still.name = s;
+   }
+
+   *nclips++;
+   clip->index = *nclips;
+
+   lwListAdd( clist, clip );
+
+   return clip->index;
+}
+
+
+/*
+======================================================================
+add_tvel()
+
+Add a triple of envelopes to simulate the old texture velocity
+parameters.
+====================================================================== */
+
+static int add_tvel( float pos[], float vel[], lwEnvelope **elist, int *nenvs )
+{
+   lwEnvelope *env;
+   lwKey *key0, *key1;
+   int i;
+
+   for ( i = 0; i < 3; i++ ) {
+      env = _pico_calloc( 1, sizeof( lwEnvelope ));
+      key0 = _pico_calloc( 1, sizeof( lwKey ));
+      key1 = _pico_calloc( 1, sizeof( lwKey ));
+      if ( !env || !key0 || !key1 ) return 0;
+
+      key0->next = key1;
+      key0->value = pos[ i ];
+      key0->time = 0.0f;
+      key1->prev = key0;
+      key1->value = pos[ i ] + vel[ i ] * 30.0f;
+      key1->time = 1.0f;
+      key0->shape = key1->shape = ID_LINE;
+
+      env->index = *nenvs + i + 1;
+      env->type = 0x0301 + i;
+      env->name = _pico_alloc( 11 );
+      if ( env->name ) {
+         strcpy( env->name, "Position.X" );
+         env->name[ 9 ] += i;
+      }
+      env->key = key0;
+      env->nkeys = 2;
+      env->behavior[ 0 ] = BEH_LINEAR;
+      env->behavior[ 1 ] = BEH_LINEAR;
+
+      lwListAdd( elist, env );
+   }
+
+   *nenvs += 3;
+   return env->index - 2;
+}
+
+
+/*
+======================================================================
+get_texture()
+
+Create a new texture for BTEX, CTEX, etc. subchunks.
+====================================================================== */
+
+static lwTexture *get_texture( char *s )
+{
+   lwTexture *tex;
+
+   tex = _pico_calloc( 1, sizeof( lwTexture ));
+   if ( !tex ) return NULL;
+
+   tex->tmap.size.val[ 0 ] =
+   tex->tmap.size.val[ 1 ] =
+   tex->tmap.size.val[ 2 ] = 1.0f;
+   tex->opacity.val = 1.0f;
+   tex->enabled = 1;
+
+   if ( strstr( s, "Image Map" )) {
+      tex->type = ID_IMAP;
+      if ( strstr( s, "Planar" ))           tex->param.imap.projection = 0;
+      else if ( strstr( s, "Cylindrical" )) tex->param.imap.projection = 1;
+      else if ( strstr( s, "Spherical" ))   tex->param.imap.projection = 2;
+      else if ( strstr( s, "Cubic" ))       tex->param.imap.projection = 3;
+      else if ( strstr( s, "Front" ))       tex->param.imap.projection = 4;
+      tex->param.imap.aa_strength = 1.0f;
+      tex->param.imap.amplitude.val = 1.0f;
+      _pico_free( s );
+   }
+   else {
+      tex->type = ID_PROC;
+      tex->param.proc.name = s;
+   }
+
+   return tex;
+}
+
+
+/*
+======================================================================
+lwGetSurface5()
+
+Read an lwSurface from an LWOB file.
+====================================================================== */
+
+lwSurface *lwGetSurface5( picoMemStream_t *fp, int cksize, lwObject *obj )
+{
+   lwSurface *surf;
+   lwTexture *tex;
+   lwPlugin *shdr;
+   char *s;
+   float v[ 3 ];
+   unsigned int id, flags;
+   unsigned short sz;
+   int pos, rlen, i;
+
+
+   /* allocate the Surface structure */
+
+   surf = _pico_calloc( 1, sizeof( lwSurface ));
+   if ( !surf ) goto Fail;
+
+   /* non-zero defaults */
+
+   surf->color.rgb[ 0 ] = 0.78431f;
+   surf->color.rgb[ 1 ] = 0.78431f;
+   surf->color.rgb[ 2 ] = 0.78431f;
+   surf->diffuse.val    = 1.0f;
+   surf->glossiness.val = 0.4f;
+   surf->bump.val       = 1.0f;
+   surf->eta.val        = 1.0f;
+   surf->sideflags      = 1;
+
+   /* remember where we started */
+
+   set_flen( 0 );
+   pos = _pico_memstream_tell( fp );
+
+   /* name */
+
+   surf->name = getS0( fp );
+
+   /* first subchunk header */
+
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   /* process subchunks as they're encountered */
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_COLR:
+            surf->color.rgb[ 0 ] = getU1( fp ) / 255.0f;
+            surf->color.rgb[ 1 ] = getU1( fp ) / 255.0f;
+            surf->color.rgb[ 2 ] = getU1( fp ) / 255.0f;
+            break;
+
+         case ID_FLAG:
+            flags = getU2( fp );
+            if ( flags &   4 ) surf->smooth = 1.56207f;
+            if ( flags &   8 ) surf->color_hilite.val = 1.0f;
+            if ( flags &  16 ) surf->color_filter.val = 1.0f;
+            if ( flags & 128 ) surf->dif_sharp.val = 0.5f;
+            if ( flags & 256 ) surf->sideflags = 3;
+            if ( flags & 512 ) surf->add_trans.val = 1.0f;
+            break;
+
+         case ID_LUMI:
+            surf->luminosity.val = getI2( fp ) / 256.0f;
+            break;
+
+         case ID_VLUM:
+            surf->luminosity.val = getF4( fp );
+            break;
+
+         case ID_DIFF:
+            surf->diffuse.val = getI2( fp ) / 256.0f;
+            break;
+
+         case ID_VDIF:
+            surf->diffuse.val = getF4( fp );
+            break;
+
+         case ID_SPEC:
+            surf->specularity.val = getI2( fp ) / 256.0f;
+            break;
+
+         case ID_VSPC:
+            surf->specularity.val = getF4( fp );
+            break;
+
+         case ID_GLOS:
+            surf->glossiness.val = ( float ) log( getU2( fp )) / 20.7944f;
+            break;
+
+         case ID_SMAN:
+            surf->smooth = getF4( fp );
+            break;
+
+         case ID_REFL:
+            surf->reflection.val.val = getI2( fp ) / 256.0f;
+            break;
+
+         case ID_RFLT:
+            surf->reflection.options = getU2( fp );
+            break;
+
+         case ID_RIMG:
+            s = getS0( fp );
+            surf->reflection.cindex = add_clip( s, &obj->clip, &obj->nclips );
+            surf->reflection.options = 3;
+            break;
+
+         case ID_RSAN:
+            surf->reflection.seam_angle = getF4( fp );
+            break;
+
+         case ID_TRAN:
+            surf->transparency.val.val = getI2( fp ) / 256.0f;
+            break;
+
+         case ID_RIND:
+            surf->eta.val = getF4( fp );
+            break;
+
+         case ID_BTEX:
+            s = getbytes( fp, sz );
+            tex = get_texture( s );
+            lwListAdd( &surf->bump.tex, tex );
+            break;
+
+         case ID_CTEX:
+            s = getbytes( fp, sz );
+            tex = get_texture( s );
+            lwListAdd( &surf->color.tex, tex );
+            break;
+
+         case ID_DTEX:
+            s = getbytes( fp, sz );
+            tex = get_texture( s );
+            lwListAdd( &surf->diffuse.tex, tex );
+            break;
+
+         case ID_LTEX:
+            s = getbytes( fp, sz );
+            tex = get_texture( s );
+            lwListAdd( &surf->luminosity.tex, tex );
+            break;
+
+         case ID_RTEX:
+            s = getbytes( fp, sz );
+            tex = get_texture( s );
+            lwListAdd( &surf->reflection.val.tex, tex );
+            break;
+
+         case ID_STEX:
+            s = getbytes( fp, sz );
+            tex = get_texture( s );
+            lwListAdd( &surf->specularity.tex, tex );
+            break;
+
+         case ID_TTEX:
+            s = getbytes( fp, sz );
+            tex = get_texture( s );
+            lwListAdd( &surf->transparency.val.tex, tex );
+            break;
+
+         case ID_TFLG:
+            flags = getU2( fp );
+
+            if ( flags & 1 ) i = 0;
+            if ( flags & 2 ) i = 1;
+            if ( flags & 4 ) i = 2;
+            tex->axis = i;
+            if ( tex->type == ID_IMAP )
+               tex->param.imap.axis = i;
+            else
+               tex->param.proc.axis = i;
+
+            if ( flags &  8 ) tex->tmap.coord_sys = 1;
+            if ( flags & 16 ) tex->negative = 1;
+            if ( flags & 32 ) tex->param.imap.pblend = 1;
+            if ( flags & 64 ) {
+               tex->param.imap.aa_strength = 1.0f;
+               tex->param.imap.aas_flags = 1;
+            }
+            break;
+
+         case ID_TSIZ:
+            for ( i = 0; i < 3; i++ )
+               tex->tmap.size.val[ i ] = getF4( fp );
+            break;
+
+         case ID_TCTR:
+            for ( i = 0; i < 3; i++ )
+               tex->tmap.center.val[ i ] = getF4( fp );
+            break;
+
+         case ID_TFAL:
+            for ( i = 0; i < 3; i++ )
+               tex->tmap.falloff.val[ i ] = getF4( fp );
+            break;
+
+         case ID_TVEL:
+            for ( i = 0; i < 3; i++ )
+               v[ i ] = getF4( fp );
+            tex->tmap.center.eindex = add_tvel( tex->tmap.center.val, v,
+               &obj->env, &obj->nenvs );
+            break;
+
+         case ID_TCLR:
+            if ( tex->type == ID_PROC )
+               for ( i = 0; i < 3; i++ )
+                  tex->param.proc.value[ i ] = getU1( fp ) / 255.0f;
+            break;
+
+         case ID_TVAL:
+            tex->param.proc.value[ 0 ] = getI2( fp ) / 256.0f;
+            break;
+
+         case ID_TAMP:
+            if ( tex->type == ID_IMAP )
+               tex->param.imap.amplitude.val = getF4( fp );
+            break;
+
+         case ID_TIMG:
+            s = getS0( fp );
+            tex->param.imap.cindex = add_clip( s, &obj->clip, &obj->nclips );
+            break;
+
+         case ID_TAAS:
+            tex->param.imap.aa_strength = getF4( fp );
+            tex->param.imap.aas_flags = 1;
+            break;
+
+         case ID_TREF:
+            tex->tmap.ref_object = getbytes( fp, sz );
+            break;
+
+         case ID_TOPC:
+            tex->opacity.val = getF4( fp );
+            break;
+
+         case ID_TFP0:
+            if ( tex->type == ID_IMAP )
+               tex->param.imap.wrapw.val = getF4( fp );
+            break;
+
+         case ID_TFP1:
+            if ( tex->type == ID_IMAP )
+               tex->param.imap.wraph.val = getF4( fp );
+            break;
+
+         case ID_SHDR:
+            shdr = _pico_calloc( 1, sizeof( lwPlugin ));
+            if ( !shdr ) goto Fail;
+            shdr->name = getbytes( fp, sz );
+            lwListAdd( &surf->shader, shdr );
+            surf->nshaders++;
+            break;
+
+         case ID_SDAT:
+            shdr->data = getbytes( fp, sz );
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) goto Fail;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the SURF chunk? */
+
+      if ( cksize <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) goto Fail;
+   }
+
+   return surf;
+
+Fail:
+   if ( surf ) lwFreeSurface( surf );
+   return NULL;
+}
+
+
+/*
+======================================================================
+lwGetPolygons5()
+
+Read polygon records from a POLS chunk in an LWOB file.  The polygons
+are added to the array in the lwPolygonList.
+====================================================================== */
+
+int lwGetPolygons5( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset )
+{
+   lwPolygon *pp;
+   lwPolVert *pv;
+   unsigned char *buf, *bp;
+   int i, j, nv, nverts, npols;
+
+
+   if ( cksize == 0 ) return 1;
+
+   /* read the whole chunk */
+
+   set_flen( 0 );
+   buf = getbytes( fp, cksize );
+   if ( !buf ) goto Fail;
+
+   /* count the polygons and vertices */
+
+   nverts = 0;
+   npols = 0;
+   bp = buf;
+
+   while ( bp < buf + cksize ) {
+      nv = sgetU2( &bp );
+      nverts += nv;
+      npols++;
+      bp += 2 * nv;
+      i = sgetI2( &bp );
+      if ( i < 0 ) bp += 2;      /* detail polygons */
+   }
+
+   if ( !lwAllocPolygons( plist, npols, nverts ))
+      goto Fail;
+
+   /* fill in the new polygons */
+
+   bp = buf;
+   pp = plist->pol + plist->offset;
+   pv = plist->pol[ 0 ].v + plist->voffset;
+
+   for ( i = 0; i < npols; i++ ) {
+      nv = sgetU2( &bp );
+
+      pp->nverts = nv;
+      pp->type = ID_FACE;
+      if ( !pp->v ) pp->v = pv;
+      for ( j = 0; j < nv; j++ )
+         pv[ j ].index = sgetU2( &bp ) + ptoffset;
+      j = sgetI2( &bp );
+      if ( j < 0 ) {
+         j = -j;
+         bp += 2;
+      }
+      j -= 1;
+      pp->surf = ( lwSurface * ) j;
+
+      pp++;
+      pv += nv;
+   }
+
+   _pico_free( buf );
+   return 1;
+
+Fail:
+   if ( buf ) _pico_free( buf );
+   lwFreePolygons( plist );
+   return 0;
+}
+
+
+/*
+======================================================================
+getLWObject5()
+
+Returns the contents of an LWOB, given its filename, or NULL if the
+file couldn't be loaded.  On failure, failID and failpos can be used
+to diagnose the cause.
+
+1.  If the file isn't an LWOB, failpos will contain 12 and failID will
+    be unchanged.
+
+2.  If an error occurs while reading an LWOB, failID will contain the
+    most recently read IFF chunk ID, and failpos will contain the
+    value returned by _pico_memstream_tell() at the time of the failure.
+
+3.  If the file couldn't be opened, or an error occurs while reading
+    the first 12 bytes, both failID and failpos will be unchanged.
+
+If you don't need this information, failID and failpos can be NULL.
+====================================================================== */
+
+lwObject *lwGetObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
+{
+   lwObject *object;
+   lwLayer *layer;
+   lwNode *node;
+   unsigned int id, formsize, type, cksize;
+
+
+   /* open the file */
+
+   if ( !fp ) return NULL;
+
+   /* read the first 12 bytes */
+
+   set_flen( 0 );
+   id       = getU4( fp );
+   formsize = getU4( fp );
+   type     = getU4( fp );
+   if ( 12 != get_flen() ) {
+      return NULL;
+   }
+
+   /* LWOB? */
+
+   if ( id != ID_FORM || type != ID_LWOB ) {
+      if ( failpos ) *failpos = 12;
+      return NULL;
+   }
+
+   /* allocate an object and a default layer */
+
+   object = _pico_calloc( 1, sizeof( lwObject ));
+   if ( !object ) goto Fail;
+
+   layer = _pico_calloc( 1, sizeof( lwLayer ));
+   if ( !layer ) goto Fail;
+   object->layer = layer;
+   object->nlayers = 1;
+
+   /* get the first chunk header */
+
+   id = getU4( fp );
+   cksize = getU4( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   /* process chunks as they're encountered */
+
+   while ( 1 ) {
+      cksize += cksize & 1;
+
+      switch ( id )
+      {
+         case ID_PNTS:
+            if ( !lwGetPoints( fp, cksize, &layer->point ))
+               goto Fail;
+            break;
+
+         case ID_POLS:
+            if ( !lwGetPolygons5( fp, cksize, &layer->polygon,
+               layer->point.offset ))
+               goto Fail;
+            break;
+
+         case ID_SRFS:
+            if ( !lwGetTags( fp, cksize, &object->taglist ))
+               goto Fail;
+            break;
+
+         case ID_SURF:
+            node = ( lwNode * ) lwGetSurface5( fp, cksize, object );
+            if ( !node ) goto Fail;
+            lwListAdd( &object->surf, node );
+            object->nsurfs++;
+            break;
+
+         default:
+            _pico_memstream_seek( fp, cksize, PICO_SEEK_CUR );
+            break;
+      }
+
+      /* end of the file? */
+
+      if ( formsize <= _pico_memstream_tell( fp ) - 8 ) break;
+
+      /* get the next chunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      cksize = getU4( fp );
+      if ( 8 != get_flen() ) goto Fail;
+   }
+
+   lwGetBoundingBox( &layer->point, layer->bbox );
+   lwGetPolyNormals( &layer->point, &layer->polygon );
+   if ( !lwGetPointPolygons( &layer->point, &layer->polygon )) goto Fail;
+   if ( !lwResolvePolySurfaces( &layer->polygon, &object->taglist,
+      &object->surf, &object->nsurfs )) goto Fail;
+   lwGetVertNormals( &layer->point, &layer->polygon );
+
+   return object;
+
+Fail:
+   if ( failID ) *failID = id;
+   if ( fp ) {
+      if ( failpos ) *failpos = _pico_memstream_tell( fp );
+   }
+   lwFreeObject( object );
+   return NULL;
+}
+
+int lwValidateObject5( char *filename, picoMemStream_t *fp, unsigned int *failID, int *failpos )
+{
+   unsigned int id, formsize, type;
+
+
+   /* open the file */
+
+   if ( !fp ) return PICO_PMV_ERROR_MEMORY;
+
+   /* read the first 12 bytes */
+
+   set_flen( 0 );
+   id       = getU4( fp );
+   formsize = getU4( fp );
+   type     = getU4( fp );
+   if ( 12 != get_flen() ) {
+      return PICO_PMV_ERROR_SIZE;
+   }
+
+   /* LWOB? */
+
+   if ( id != ID_FORM || type != ID_LWOB ) {
+      if ( failpos ) *failpos = 12;
+      return PICO_PMV_ERROR_IDENT;
+   }
+
+   return PICO_PMV_OK;
+}
diff --git a/libs/picomodel/lwo/pntspols.c b/libs/picomodel/lwo/pntspols.c
index d6c3152d..5cef01e6 100644
--- a/libs/picomodel/lwo/pntspols.c
+++ b/libs/picomodel/lwo/pntspols.c
@@ -1,537 +1,537 @@
-/*
-======================================================================
-pntspols.c
-
-Point and polygon functions for an LWO2 reader.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-
-/*
-======================================================================
-lwFreePoints()
-
-Free the memory used by an lwPointList.
-====================================================================== */
-
-void lwFreePoints( lwPointList *point )
-{
-   int i;
-
-   if ( point ) {
-      if ( point->pt ) {
-         for ( i = 0; i < point->count; i++ ) {
-            if ( point->pt[ i ].pol ) _pico_free( point->pt[ i ].pol );
-            if ( point->pt[ i ].vm ) _pico_free( point->pt[ i ].vm );
-         }
-         _pico_free( point->pt );
-      }
-      memset( point, 0, sizeof( lwPointList ));
-   }
-}
-
-
-/*
-======================================================================
-lwFreePolygons()
-
-Free the memory used by an lwPolygonList.
-====================================================================== */
-
-void lwFreePolygons( lwPolygonList *plist )
-{
-   int i, j;
-
-   if ( plist ) {
-      if ( plist->pol ) {
-         for ( i = 0; i < plist->count; i++ ) {
-            if ( plist->pol[ i ].v ) {
-               for ( j = 0; j < plist->pol[ i ].nverts; j++ )
-                  if ( plist->pol[ i ].v[ j ].vm )
-                     _pico_free( plist->pol[ i ].v[ j ].vm );
-            }
-         }
-         if ( plist->pol[ 0 ].v )
-            _pico_free( plist->pol[ 0 ].v );
-         _pico_free( plist->pol );
-      }
-      memset( plist, 0, sizeof( lwPolygonList ));
-   }
-}
-
-
-/*
-======================================================================
-lwGetPoints()
-
-Read point records from a PNTS chunk in an LWO2 file.  The points are
-added to the array in the lwPointList.
-====================================================================== */
-
-int lwGetPoints( picoMemStream_t *fp, int cksize, lwPointList *point )
-{
-   float *f;
-   int np, i, j;
-
-   if ( cksize == 1 ) return 1;
-
-   /* extend the point array to hold the new points */
-
-   np = cksize / 12;
-   point->offset = point->count;
-   point->count += np;
-   if ( !_pico_realloc( (void *) &point->pt, (point->count - np) * sizeof( lwPoint ), point->count * sizeof( lwPoint )) )
-      return 0;
-   memset( &point->pt[ point->offset ], 0, np * sizeof( lwPoint ));
-
-   /* read the whole chunk */
-
-   f = ( float * ) getbytes( fp, cksize );
-   if ( !f ) return 0;
-   revbytes( f, 4, np * 3 );
-
-   /* assign position values */
-
-   for ( i = 0, j = 0; i < np; i++, j += 3 ) {
-      point->pt[ i ].pos[ 0 ] = f[ j ];
-      point->pt[ i ].pos[ 1 ] = f[ j + 1 ];
-      point->pt[ i ].pos[ 2 ] = f[ j + 2 ];
-   }
-
-   _pico_free( f );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetBoundingBox()
-
-Calculate the bounding box for a point list, but only if the bounding
-box hasn't already been initialized.
-====================================================================== */
-
-void lwGetBoundingBox( lwPointList *point, float bbox[] )
-{
-   int i, j;
-
-   if ( point->count == 0 ) return;
-
-   for ( i = 0; i < 6; i++ )
-      if ( bbox[ i ] != 0.0f ) return;
-
-   bbox[ 0 ] = bbox[ 1 ] = bbox[ 2 ] = 1e20f;
-   bbox[ 3 ] = bbox[ 4 ] = bbox[ 5 ] = -1e20f;
-   for ( i = 0; i < point->count; i++ ) {
-      for ( j = 0; j < 3; j++ ) {
-         if ( bbox[ j ] > point->pt[ i ].pos[ j ] )
-            bbox[ j ] = point->pt[ i ].pos[ j ];
-         if ( bbox[ j + 3 ] < point->pt[ i ].pos[ j ] )
-            bbox[ j + 3 ] = point->pt[ i ].pos[ j ];
-      }
-   }
-}
-
-
-/*
-======================================================================
-lwAllocPolygons()
-
-Allocate or extend the polygon arrays to hold new records.
-====================================================================== */
-
-int lwAllocPolygons( lwPolygonList *plist, int npols, int nverts )
-{
-   int i;
-
-   plist->offset = plist->count;
-   plist->count += npols;
-   if ( !_pico_realloc( (void *) &plist->pol, (plist->count - npols) * sizeof( lwPolygon ), plist->count * sizeof( lwPolygon )) )
-      return 0;
-   memset( plist->pol + plist->offset, 0, npols * sizeof( lwPolygon ));
-
-   plist->voffset = plist->vcount;
-   plist->vcount += nverts;
-   if ( !_pico_realloc( (void *) &plist->pol[ 0 ].v, (plist->vcount - nverts) * sizeof( lwPolVert ), plist->vcount * sizeof( lwPolVert )) )
-      return 0;
-   memset( plist->pol[ 0 ].v + plist->voffset, 0, nverts * sizeof( lwPolVert ));
-
-   /* fix up the old vertex pointers */
-
-   for ( i = 1; i < plist->offset; i++ )
-      plist->pol[ i ].v = plist->pol[ i - 1 ].v + plist->pol[ i - 1 ].nverts;
-
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetPolygons()
-
-Read polygon records from a POLS chunk in an LWO2 file.  The polygons
-are added to the array in the lwPolygonList.
-====================================================================== */
-
-int lwGetPolygons( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset )
-{
-   lwPolygon *pp;
-   lwPolVert *pv;
-   unsigned char *buf, *bp;
-   int i, j, flags, nv, nverts, npols;
-   unsigned int type;
-
-
-   if ( cksize == 0 ) return 1;
-
-   /* read the whole chunk */
-
-   set_flen( 0 );
-   type = getU4( fp );
-   buf = getbytes( fp, cksize - 4 );
-   if ( cksize != get_flen() ) goto Fail;
-
-   /* count the polygons and vertices */
-
-   nverts = 0;
-   npols = 0;
-   bp = buf;
-
-   while ( bp < buf + cksize - 4 ) {
-      nv = sgetU2( &bp );
-      nv &= 0x03FF;
-      nverts += nv;
-      npols++;
-      for ( i = 0; i < nv; i++ )
-         j = sgetVX( &bp );
-   }
-
-   if ( !lwAllocPolygons( plist, npols, nverts ))
-      goto Fail;
-
-   /* fill in the new polygons */
-
-   bp = buf;
-   pp = plist->pol + plist->offset;
-   pv = plist->pol[ 0 ].v + plist->voffset;
-
-   for ( i = 0; i < npols; i++ ) {
-      nv = sgetU2( &bp );
-      flags = nv & 0xFC00;
-      nv &= 0x03FF;
-
-      pp->nverts = nv;
-      pp->flags = flags;
-      pp->type = type;
-      if ( !pp->v ) pp->v = pv;
-      for ( j = 0; j < nv; j++ )
-         pp->v[ j ].index = sgetVX( &bp ) + ptoffset;
-
-      pp++;
-      pv += nv;
-   }
-
-   _pico_free( buf );
-   return 1;
-
-Fail:
-   if ( buf ) _pico_free( buf );
-   lwFreePolygons( plist );
-   return 0;
-}
-
-
-/*
-======================================================================
-lwGetPolyNormals()
-
-Calculate the polygon normals.  By convention, LW's polygon normals
-are found as the cross product of the first and last edges.  It's
-undefined for one- and two-point polygons.
-====================================================================== */
-
-void lwGetPolyNormals( lwPointList *point, lwPolygonList *polygon )
-{
-   int i, j;
-   float p1[ 3 ], p2[ 3 ], pn[ 3 ], v1[ 3 ], v2[ 3 ];
-
-   for ( i = 0; i < polygon->count; i++ ) {
-      if ( polygon->pol[ i ].nverts < 3 ) continue;
-      for ( j = 0; j < 3; j++ ) {
-         p1[ j ] = point->pt[ polygon->pol[ i ].v[ 0 ].index ].pos[ j ];
-         p2[ j ] = point->pt[ polygon->pol[ i ].v[ 1 ].index ].pos[ j ];
-         pn[ j ] = point->pt[ polygon->pol[ i ].v[
-            polygon->pol[ i ].nverts - 1 ].index ].pos[ j ];
-      }
-
-      for ( j = 0; j < 3; j++ ) {
-         v1[ j ] = p2[ j ] - p1[ j ];
-         v2[ j ] = pn[ j ] - p1[ j ];
-      }
-
-      cross( v1, v2, polygon->pol[ i ].norm );
-      normalize( polygon->pol[ i ].norm );
-   }
-}
-
-
-/*
-======================================================================
-lwGetPointPolygons()
-
-For each point, fill in the indexes of the polygons that share the
-point.  Returns 0 if any of the memory allocations fail, otherwise
-returns 1.
-====================================================================== */
-
-int lwGetPointPolygons( lwPointList *point, lwPolygonList *polygon )
-{
-   int i, j, k;
-
-   /* count the number of polygons per point */
-
-   for ( i = 0; i < polygon->count; i++ )
-      for ( j = 0; j < polygon->pol[ i ].nverts; j++ )
-         ++point->pt[ polygon->pol[ i ].v[ j ].index ].npols;
-
-   /* alloc per-point polygon arrays */
-
-   for ( i = 0; i < point->count; i++ ) {
-      if ( point->pt[ i ].npols == 0 ) continue;
-      point->pt[ i ].pol = _pico_calloc( point->pt[ i ].npols, sizeof( int ));
-      if ( !point->pt[ i ].pol ) return 0;
-      point->pt[ i ].npols = 0;
-   }
-
-   /* fill in polygon array for each point */
-
-   for ( i = 0; i < polygon->count; i++ ) {
-      for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) {
-         k = polygon->pol[ i ].v[ j ].index;
-         point->pt[ k ].pol[ point->pt[ k ].npols ] = i;
-         ++point->pt[ k ].npols;
-      }
-   }
-
-   return 1;
-}
-
-
-/*
-======================================================================
-lwResolvePolySurfaces()
-
-Convert tag indexes into actual lwSurface pointers.  If any polygons
-point to tags for which no corresponding surface can be found, a
-default surface is created.
-====================================================================== */
-
-int lwResolvePolySurfaces( lwPolygonList *polygon, lwTagList *tlist,
-   lwSurface **surf, int *nsurfs )
-{
-   lwSurface **s, *st;
-   int i, index;
-
-   if ( tlist->count == 0 ) return 1;
-
-   s = _pico_calloc( tlist->count, sizeof( lwSurface * ));
-   if ( !s ) return 0;
-
-   for ( i = 0; i < tlist->count; i++ ) {
-      st = *surf;
-      while ( st ) {
-         if ( !strcmp( st->name, tlist->tag[ i ] )) {
-            s[ i ] = st;
-            break;
-         }
-         st = st->next;
-      }
-   }
-
-   for ( i = 0; i < polygon->count; i++ ) {
-      index = ( int ) polygon->pol[ i ].surf;
-      if ( index < 0 || index > tlist->count ) return 0;
-      if ( !s[ index ] ) {
-         s[ index ] = lwDefaultSurface();
-         if ( !s[ index ] ) return 0;
-         s[ index ]->name = _pico_alloc( strlen( tlist->tag[ index ] ) + 1 );
-         if ( !s[ index ]->name ) return 0;
-         strcpy( s[ index ]->name, tlist->tag[ index ] );
-         lwListAdd( surf, s[ index ] );
-         *nsurfs = *nsurfs + 1;
-      }
-      polygon->pol[ i ].surf = s[ index ];
-   }
-
-   _pico_free( s );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetVertNormals()
-
-Calculate the vertex normals.  For each polygon vertex, sum the
-normals of the polygons that share the point.  If the normals of the
-current and adjacent polygons form an angle greater than the max
-smoothing angle for the current polygon's surface, the normal of the
-adjacent polygon is excluded from the sum.  It's also excluded if the
-polygons aren't in the same smoothing group.
-
-Assumes that lwGetPointPolygons(), lwGetPolyNormals() and
-lwResolvePolySurfaces() have already been called.
-====================================================================== */
-
-void lwGetVertNormals( lwPointList *point, lwPolygonList *polygon )
-{
-   int j, k, n, g, h, p;
-   float a;
-
-   for ( j = 0; j < polygon->count; j++ ) {
-      for ( n = 0; n < polygon->pol[ j ].nverts; n++ ) {
-         for ( k = 0; k < 3; k++ )
-            polygon->pol[ j ].v[ n ].norm[ k ] = polygon->pol[ j ].norm[ k ];
-
-         if ( polygon->pol[ j ].surf->smooth <= 0 ) continue;
-
-         p = polygon->pol[ j ].v[ n ].index;
-
-         for ( g = 0; g < point->pt[ p ].npols; g++ ) {
-            h = point->pt[ p ].pol[ g ];
-            if ( h == j ) continue;
-
-            if ( polygon->pol[ j ].smoothgrp != polygon->pol[ h ].smoothgrp )
-               continue;
-            a = vecangle( polygon->pol[ j ].norm, polygon->pol[ h ].norm );
-            if ( a > polygon->pol[ j ].surf->smooth ) continue;
-
-            for ( k = 0; k < 3; k++ )
-               polygon->pol[ j ].v[ n ].norm[ k ] += polygon->pol[ h ].norm[ k ];
-         }
-
-         normalize( polygon->pol[ j ].v[ n ].norm );
-      }
-   }
-}
-
-
-/*
-======================================================================
-lwFreeTags()
-
-Free memory used by an lwTagList.
-====================================================================== */
-
-void lwFreeTags( lwTagList *tlist )
-{
-   int i;
-
-   if ( tlist ) {
-      if ( tlist->tag ) {
-         for ( i = 0; i < tlist->count; i++ )
-            if ( tlist->tag[ i ] ) _pico_free( tlist->tag[ i ] );
-         _pico_free( tlist->tag );
-      }
-      memset( tlist, 0, sizeof( lwTagList ));
-   }
-}
-
-
-/*
-======================================================================
-lwGetTags()
-
-Read tag strings from a TAGS chunk in an LWO2 file.  The tags are
-added to the lwTagList array.
-====================================================================== */
-
-int lwGetTags( picoMemStream_t *fp, int cksize, lwTagList *tlist )
-{
-   char *buf, *bp;
-   int i, len, ntags;
-
-   if ( cksize == 0 ) return 1;
-
-   /* read the whole chunk */
-
-   set_flen( 0 );
-   buf = getbytes( fp, cksize );
-   if ( !buf ) return 0;
-
-   /* count the strings */
-
-   ntags = 0;
-   bp = buf;
-   while ( bp < buf + cksize ) {
-      len = strlen( bp ) + 1;
-      len += len & 1;
-      bp += len;
-      ++ntags;
-   }
-
-   /* expand the string array to hold the new tags */
-
-   tlist->offset = tlist->count;
-   tlist->count += ntags;
-   if ( !_pico_realloc( (void *) &tlist->tag, (tlist->count - ntags) * sizeof( char * ), tlist->count * sizeof( char * )) )
-      goto Fail;
-   memset( &tlist->tag[ tlist->offset ], 0, ntags * sizeof( char * ));
-
-   /* copy the new tags to the tag array */
-
-   bp = buf;
-   for ( i = 0; i < ntags; i++ )
-      tlist->tag[ i + tlist->offset ] = sgetS0( &bp );
-
-   _pico_free( buf );
-   return 1;
-
-Fail:
-   if ( buf ) _pico_free( buf );
-   return 0;
-}
-
-
-/*
-======================================================================
-lwGetPolygonTags()
-
-Read polygon tags from a PTAG chunk in an LWO2 file.
-====================================================================== */
-
-int lwGetPolygonTags( picoMemStream_t *fp, int cksize, lwTagList *tlist,
-   lwPolygonList *plist )
-{
-   unsigned int type;
-   int rlen = 0, i, j;
-
-   set_flen( 0 );
-   type = getU4( fp );
-   rlen = get_flen();
-   if ( rlen < 0 ) return 0;
-
-   if ( type != ID_SURF && type != ID_PART && type != ID_SMGP ) {
-      _pico_memstream_seek( fp, cksize - 4, PICO_SEEK_CUR );
-      return 1;
-   }
-
-   while ( rlen < cksize ) {
-      i = getVX( fp ) + plist->offset;
-      j = getVX( fp ) + tlist->offset;
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > cksize ) return 0;
-
-      switch ( type ) {
-         case ID_SURF:  plist->pol[ i ].surf = ( lwSurface * ) j;  break;
-         case ID_PART:  plist->pol[ i ].part = j;  break;
-         case ID_SMGP:  plist->pol[ i ].smoothgrp = j;  break;
-      }
-   }
-
-   return 1;
-}
+/*
+======================================================================
+pntspols.c
+
+Point and polygon functions for an LWO2 reader.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+
+/*
+======================================================================
+lwFreePoints()
+
+Free the memory used by an lwPointList.
+====================================================================== */
+
+void lwFreePoints( lwPointList *point )
+{
+   int i;
+
+   if ( point ) {
+      if ( point->pt ) {
+         for ( i = 0; i < point->count; i++ ) {
+            if ( point->pt[ i ].pol ) _pico_free( point->pt[ i ].pol );
+            if ( point->pt[ i ].vm ) _pico_free( point->pt[ i ].vm );
+         }
+         _pico_free( point->pt );
+      }
+      memset( point, 0, sizeof( lwPointList ));
+   }
+}
+
+
+/*
+======================================================================
+lwFreePolygons()
+
+Free the memory used by an lwPolygonList.
+====================================================================== */
+
+void lwFreePolygons( lwPolygonList *plist )
+{
+   int i, j;
+
+   if ( plist ) {
+      if ( plist->pol ) {
+         for ( i = 0; i < plist->count; i++ ) {
+            if ( plist->pol[ i ].v ) {
+               for ( j = 0; j < plist->pol[ i ].nverts; j++ )
+                  if ( plist->pol[ i ].v[ j ].vm )
+                     _pico_free( plist->pol[ i ].v[ j ].vm );
+            }
+         }
+         if ( plist->pol[ 0 ].v )
+            _pico_free( plist->pol[ 0 ].v );
+         _pico_free( plist->pol );
+      }
+      memset( plist, 0, sizeof( lwPolygonList ));
+   }
+}
+
+
+/*
+======================================================================
+lwGetPoints()
+
+Read point records from a PNTS chunk in an LWO2 file.  The points are
+added to the array in the lwPointList.
+====================================================================== */
+
+int lwGetPoints( picoMemStream_t *fp, int cksize, lwPointList *point )
+{
+   float *f;
+   int np, i, j;
+
+   if ( cksize == 1 ) return 1;
+
+   /* extend the point array to hold the new points */
+
+   np = cksize / 12;
+   point->offset = point->count;
+   point->count += np;
+   if ( !_pico_realloc( (void *) &point->pt, (point->count - np) * sizeof( lwPoint ), point->count * sizeof( lwPoint )) )
+      return 0;
+   memset( &point->pt[ point->offset ], 0, np * sizeof( lwPoint ));
+
+   /* read the whole chunk */
+
+   f = ( float * ) getbytes( fp, cksize );
+   if ( !f ) return 0;
+   revbytes( f, 4, np * 3 );
+
+   /* assign position values */
+
+   for ( i = 0, j = 0; i < np; i++, j += 3 ) {
+      point->pt[ i ].pos[ 0 ] = f[ j ];
+      point->pt[ i ].pos[ 1 ] = f[ j + 1 ];
+      point->pt[ i ].pos[ 2 ] = f[ j + 2 ];
+   }
+
+   _pico_free( f );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetBoundingBox()
+
+Calculate the bounding box for a point list, but only if the bounding
+box hasn't already been initialized.
+====================================================================== */
+
+void lwGetBoundingBox( lwPointList *point, float bbox[] )
+{
+   int i, j;
+
+   if ( point->count == 0 ) return;
+
+   for ( i = 0; i < 6; i++ )
+      if ( bbox[ i ] != 0.0f ) return;
+
+   bbox[ 0 ] = bbox[ 1 ] = bbox[ 2 ] = 1e20f;
+   bbox[ 3 ] = bbox[ 4 ] = bbox[ 5 ] = -1e20f;
+   for ( i = 0; i < point->count; i++ ) {
+      for ( j = 0; j < 3; j++ ) {
+         if ( bbox[ j ] > point->pt[ i ].pos[ j ] )
+            bbox[ j ] = point->pt[ i ].pos[ j ];
+         if ( bbox[ j + 3 ] < point->pt[ i ].pos[ j ] )
+            bbox[ j + 3 ] = point->pt[ i ].pos[ j ];
+      }
+   }
+}
+
+
+/*
+======================================================================
+lwAllocPolygons()
+
+Allocate or extend the polygon arrays to hold new records.
+====================================================================== */
+
+int lwAllocPolygons( lwPolygonList *plist, int npols, int nverts )
+{
+   int i;
+
+   plist->offset = plist->count;
+   plist->count += npols;
+   if ( !_pico_realloc( (void *) &plist->pol, (plist->count - npols) * sizeof( lwPolygon ), plist->count * sizeof( lwPolygon )) )
+      return 0;
+   memset( plist->pol + plist->offset, 0, npols * sizeof( lwPolygon ));
+
+   plist->voffset = plist->vcount;
+   plist->vcount += nverts;
+   if ( !_pico_realloc( (void *) &plist->pol[ 0 ].v, (plist->vcount - nverts) * sizeof( lwPolVert ), plist->vcount * sizeof( lwPolVert )) )
+      return 0;
+   memset( plist->pol[ 0 ].v + plist->voffset, 0, nverts * sizeof( lwPolVert ));
+
+   /* fix up the old vertex pointers */
+
+   for ( i = 1; i < plist->offset; i++ )
+      plist->pol[ i ].v = plist->pol[ i - 1 ].v + plist->pol[ i - 1 ].nverts;
+
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetPolygons()
+
+Read polygon records from a POLS chunk in an LWO2 file.  The polygons
+are added to the array in the lwPolygonList.
+====================================================================== */
+
+int lwGetPolygons( picoMemStream_t *fp, int cksize, lwPolygonList *plist, int ptoffset )
+{
+   lwPolygon *pp;
+   lwPolVert *pv;
+   unsigned char *buf, *bp;
+   int i, j, flags, nv, nverts, npols;
+   unsigned int type;
+
+
+   if ( cksize == 0 ) return 1;
+
+   /* read the whole chunk */
+
+   set_flen( 0 );
+   type = getU4( fp );
+   buf = getbytes( fp, cksize - 4 );
+   if ( cksize != get_flen() ) goto Fail;
+
+   /* count the polygons and vertices */
+
+   nverts = 0;
+   npols = 0;
+   bp = buf;
+
+   while ( bp < buf + cksize - 4 ) {
+      nv = sgetU2( &bp );
+      nv &= 0x03FF;
+      nverts += nv;
+      npols++;
+      for ( i = 0; i < nv; i++ )
+         j = sgetVX( &bp );
+   }
+
+   if ( !lwAllocPolygons( plist, npols, nverts ))
+      goto Fail;
+
+   /* fill in the new polygons */
+
+   bp = buf;
+   pp = plist->pol + plist->offset;
+   pv = plist->pol[ 0 ].v + plist->voffset;
+
+   for ( i = 0; i < npols; i++ ) {
+      nv = sgetU2( &bp );
+      flags = nv & 0xFC00;
+      nv &= 0x03FF;
+
+      pp->nverts = nv;
+      pp->flags = flags;
+      pp->type = type;
+      if ( !pp->v ) pp->v = pv;
+      for ( j = 0; j < nv; j++ )
+         pp->v[ j ].index = sgetVX( &bp ) + ptoffset;
+
+      pp++;
+      pv += nv;
+   }
+
+   _pico_free( buf );
+   return 1;
+
+Fail:
+   if ( buf ) _pico_free( buf );
+   lwFreePolygons( plist );
+   return 0;
+}
+
+
+/*
+======================================================================
+lwGetPolyNormals()
+
+Calculate the polygon normals.  By convention, LW's polygon normals
+are found as the cross product of the first and last edges.  It's
+undefined for one- and two-point polygons.
+====================================================================== */
+
+void lwGetPolyNormals( lwPointList *point, lwPolygonList *polygon )
+{
+   int i, j;
+   float p1[ 3 ], p2[ 3 ], pn[ 3 ], v1[ 3 ], v2[ 3 ];
+
+   for ( i = 0; i < polygon->count; i++ ) {
+      if ( polygon->pol[ i ].nverts < 3 ) continue;
+      for ( j = 0; j < 3; j++ ) {
+         p1[ j ] = point->pt[ polygon->pol[ i ].v[ 0 ].index ].pos[ j ];
+         p2[ j ] = point->pt[ polygon->pol[ i ].v[ 1 ].index ].pos[ j ];
+         pn[ j ] = point->pt[ polygon->pol[ i ].v[
+            polygon->pol[ i ].nverts - 1 ].index ].pos[ j ];
+      }
+
+      for ( j = 0; j < 3; j++ ) {
+         v1[ j ] = p2[ j ] - p1[ j ];
+         v2[ j ] = pn[ j ] - p1[ j ];
+      }
+
+      cross( v1, v2, polygon->pol[ i ].norm );
+      normalize( polygon->pol[ i ].norm );
+   }
+}
+
+
+/*
+======================================================================
+lwGetPointPolygons()
+
+For each point, fill in the indexes of the polygons that share the
+point.  Returns 0 if any of the memory allocations fail, otherwise
+returns 1.
+====================================================================== */
+
+int lwGetPointPolygons( lwPointList *point, lwPolygonList *polygon )
+{
+   int i, j, k;
+
+   /* count the number of polygons per point */
+
+   for ( i = 0; i < polygon->count; i++ )
+      for ( j = 0; j < polygon->pol[ i ].nverts; j++ )
+         ++point->pt[ polygon->pol[ i ].v[ j ].index ].npols;
+
+   /* alloc per-point polygon arrays */
+
+   for ( i = 0; i < point->count; i++ ) {
+      if ( point->pt[ i ].npols == 0 ) continue;
+      point->pt[ i ].pol = _pico_calloc( point->pt[ i ].npols, sizeof( int ));
+      if ( !point->pt[ i ].pol ) return 0;
+      point->pt[ i ].npols = 0;
+   }
+
+   /* fill in polygon array for each point */
+
+   for ( i = 0; i < polygon->count; i++ ) {
+      for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) {
+         k = polygon->pol[ i ].v[ j ].index;
+         point->pt[ k ].pol[ point->pt[ k ].npols ] = i;
+         ++point->pt[ k ].npols;
+      }
+   }
+
+   return 1;
+}
+
+
+/*
+======================================================================
+lwResolvePolySurfaces()
+
+Convert tag indexes into actual lwSurface pointers.  If any polygons
+point to tags for which no corresponding surface can be found, a
+default surface is created.
+====================================================================== */
+
+int lwResolvePolySurfaces( lwPolygonList *polygon, lwTagList *tlist,
+   lwSurface **surf, int *nsurfs )
+{
+   lwSurface **s, *st;
+   int i, index;
+
+   if ( tlist->count == 0 ) return 1;
+
+   s = _pico_calloc( tlist->count, sizeof( lwSurface * ));
+   if ( !s ) return 0;
+
+   for ( i = 0; i < tlist->count; i++ ) {
+      st = *surf;
+      while ( st ) {
+         if ( !strcmp( st->name, tlist->tag[ i ] )) {
+            s[ i ] = st;
+            break;
+         }
+         st = st->next;
+      }
+   }
+
+   for ( i = 0; i < polygon->count; i++ ) {
+      index = ( int ) polygon->pol[ i ].surf;
+      if ( index < 0 || index > tlist->count ) return 0;
+      if ( !s[ index ] ) {
+         s[ index ] = lwDefaultSurface();
+         if ( !s[ index ] ) return 0;
+         s[ index ]->name = _pico_alloc( strlen( tlist->tag[ index ] ) + 1 );
+         if ( !s[ index ]->name ) return 0;
+         strcpy( s[ index ]->name, tlist->tag[ index ] );
+         lwListAdd( surf, s[ index ] );
+         *nsurfs = *nsurfs + 1;
+      }
+      polygon->pol[ i ].surf = s[ index ];
+   }
+
+   _pico_free( s );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetVertNormals()
+
+Calculate the vertex normals.  For each polygon vertex, sum the
+normals of the polygons that share the point.  If the normals of the
+current and adjacent polygons form an angle greater than the max
+smoothing angle for the current polygon's surface, the normal of the
+adjacent polygon is excluded from the sum.  It's also excluded if the
+polygons aren't in the same smoothing group.
+
+Assumes that lwGetPointPolygons(), lwGetPolyNormals() and
+lwResolvePolySurfaces() have already been called.
+====================================================================== */
+
+void lwGetVertNormals( lwPointList *point, lwPolygonList *polygon )
+{
+   int j, k, n, g, h, p;
+   float a;
+
+   for ( j = 0; j < polygon->count; j++ ) {
+      for ( n = 0; n < polygon->pol[ j ].nverts; n++ ) {
+         for ( k = 0; k < 3; k++ )
+            polygon->pol[ j ].v[ n ].norm[ k ] = polygon->pol[ j ].norm[ k ];
+
+         if ( polygon->pol[ j ].surf->smooth <= 0 ) continue;
+
+         p = polygon->pol[ j ].v[ n ].index;
+
+         for ( g = 0; g < point->pt[ p ].npols; g++ ) {
+            h = point->pt[ p ].pol[ g ];
+            if ( h == j ) continue;
+
+            if ( polygon->pol[ j ].smoothgrp != polygon->pol[ h ].smoothgrp )
+               continue;
+            a = vecangle( polygon->pol[ j ].norm, polygon->pol[ h ].norm );
+            if ( a > polygon->pol[ j ].surf->smooth ) continue;
+
+            for ( k = 0; k < 3; k++ )
+               polygon->pol[ j ].v[ n ].norm[ k ] += polygon->pol[ h ].norm[ k ];
+         }
+
+         normalize( polygon->pol[ j ].v[ n ].norm );
+      }
+   }
+}
+
+
+/*
+======================================================================
+lwFreeTags()
+
+Free memory used by an lwTagList.
+====================================================================== */
+
+void lwFreeTags( lwTagList *tlist )
+{
+   int i;
+
+   if ( tlist ) {
+      if ( tlist->tag ) {
+         for ( i = 0; i < tlist->count; i++ )
+            if ( tlist->tag[ i ] ) _pico_free( tlist->tag[ i ] );
+         _pico_free( tlist->tag );
+      }
+      memset( tlist, 0, sizeof( lwTagList ));
+   }
+}
+
+
+/*
+======================================================================
+lwGetTags()
+
+Read tag strings from a TAGS chunk in an LWO2 file.  The tags are
+added to the lwTagList array.
+====================================================================== */
+
+int lwGetTags( picoMemStream_t *fp, int cksize, lwTagList *tlist )
+{
+   char *buf, *bp;
+   int i, len, ntags;
+
+   if ( cksize == 0 ) return 1;
+
+   /* read the whole chunk */
+
+   set_flen( 0 );
+   buf = getbytes( fp, cksize );
+   if ( !buf ) return 0;
+
+   /* count the strings */
+
+   ntags = 0;
+   bp = buf;
+   while ( bp < buf + cksize ) {
+      len = strlen( bp ) + 1;
+      len += len & 1;
+      bp += len;
+      ++ntags;
+   }
+
+   /* expand the string array to hold the new tags */
+
+   tlist->offset = tlist->count;
+   tlist->count += ntags;
+   if ( !_pico_realloc( (void *) &tlist->tag, (tlist->count - ntags) * sizeof( char * ), tlist->count * sizeof( char * )) )
+      goto Fail;
+   memset( &tlist->tag[ tlist->offset ], 0, ntags * sizeof( char * ));
+
+   /* copy the new tags to the tag array */
+
+   bp = buf;
+   for ( i = 0; i < ntags; i++ )
+      tlist->tag[ i + tlist->offset ] = sgetS0( &bp );
+
+   _pico_free( buf );
+   return 1;
+
+Fail:
+   if ( buf ) _pico_free( buf );
+   return 0;
+}
+
+
+/*
+======================================================================
+lwGetPolygonTags()
+
+Read polygon tags from a PTAG chunk in an LWO2 file.
+====================================================================== */
+
+int lwGetPolygonTags( picoMemStream_t *fp, int cksize, lwTagList *tlist,
+   lwPolygonList *plist )
+{
+   unsigned int type;
+   int rlen = 0, i, j;
+
+   set_flen( 0 );
+   type = getU4( fp );
+   rlen = get_flen();
+   if ( rlen < 0 ) return 0;
+
+   if ( type != ID_SURF && type != ID_PART && type != ID_SMGP ) {
+      _pico_memstream_seek( fp, cksize - 4, PICO_SEEK_CUR );
+      return 1;
+   }
+
+   while ( rlen < cksize ) {
+      i = getVX( fp ) + plist->offset;
+      j = getVX( fp ) + tlist->offset;
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > cksize ) return 0;
+
+      switch ( type ) {
+         case ID_SURF:  plist->pol[ i ].surf = ( lwSurface * ) j;  break;
+         case ID_PART:  plist->pol[ i ].part = j;  break;
+         case ID_SMGP:  plist->pol[ i ].smoothgrp = j;  break;
+      }
+   }
+
+   return 1;
+}
diff --git a/libs/picomodel/lwo/surface.c b/libs/picomodel/lwo/surface.c
index 6456a957..6c205df2 100644
--- a/libs/picomodel/lwo/surface.c
+++ b/libs/picomodel/lwo/surface.c
@@ -1,1004 +1,1004 @@
-/*
-======================================================================
-surface.c
-
-Surface functions for an LWO2 reader.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-
-/*
-======================================================================
-lwFreePlugin()
-
-Free the memory used by an lwPlugin.
-====================================================================== */
-
-void lwFreePlugin( lwPlugin *p )
-{
-   if ( p ) {
-      if ( p->ord ) _pico_free( p->ord );
-      if ( p->name ) _pico_free( p->name );
-      if ( p->data ) _pico_free( p->data );
-      _pico_free( p );
-   }
-}
-
-
-/*
-======================================================================
-lwFreeTexture()
-
-Free the memory used by an lwTexture.
-====================================================================== */
-
-void lwFreeTexture( lwTexture *t )
-{
-   if ( t ) {
-      if ( t->ord ) _pico_free( t->ord );
-      switch ( t->type ) {
-         case ID_IMAP:
-            if ( t->param.imap.vmap_name ) _pico_free( t->param.imap.vmap_name );
-            break;
-         case ID_PROC:
-            if ( t->param.proc.name ) _pico_free( t->param.proc.name );
-            if ( t->param.proc.data ) _pico_free( t->param.proc.data );
-            break;
-         case ID_GRAD:
-            if ( t->param.grad.key ) _pico_free( t->param.grad.key );
-            if ( t->param.grad.ikey ) _pico_free( t->param.grad.ikey );
-            break;
-      }
-      _pico_free( t );
-   }
-}
-
-
-/*
-======================================================================
-lwFreeSurface()
-
-Free the memory used by an lwSurface.
-====================================================================== */
-
-void lwFreeSurface( lwSurface *surf )
-{
-   if ( surf ) {
-      if ( surf->name ) _pico_free( surf->name );
-      if ( surf->srcname ) _pico_free( surf->srcname );
-
-      lwListFree( surf->shader, lwFreePlugin );
-
-      lwListFree( surf->color.tex, lwFreeTexture );
-      lwListFree( surf->luminosity.tex, lwFreeTexture );
-      lwListFree( surf->diffuse.tex, lwFreeTexture );
-      lwListFree( surf->specularity.tex, lwFreeTexture );
-      lwListFree( surf->glossiness.tex, lwFreeTexture );
-      lwListFree( surf->reflection.val.tex, lwFreeTexture );
-      lwListFree( surf->transparency.val.tex, lwFreeTexture );
-      lwListFree( surf->eta.tex, lwFreeTexture );
-      lwListFree( surf->translucency.tex, lwFreeTexture );
-      lwListFree( surf->bump.tex, lwFreeTexture );
-
-      _pico_free( surf );
-   }
-}
-
-
-/*
-======================================================================
-lwGetTHeader()
-
-Read a texture map header from a SURF.BLOK in an LWO2 file.  This is
-the first subchunk in a BLOK, and its contents are common to all three
-texture types.
-====================================================================== */
-
-int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex )
-{
-   unsigned int id;
-   unsigned short sz;
-   int pos, rlen;
-
-
-   /* remember where we started */
-
-   set_flen( 0 );
-   pos = _pico_memstream_tell( fp );
-
-   /* ordinal string */
-
-   tex->ord = getS0( fp );
-
-   /* first subchunk header */
-
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) return 0;
-
-   /* process subchunks as they're encountered */
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_CHAN:
-            tex->chan = getU4( fp );
-            break;
-
-         case ID_OPAC:
-            tex->opac_type = getU2( fp );
-            tex->opacity.val = getF4( fp );
-            tex->opacity.eindex = getVX( fp );
-            break;
-
-         case ID_ENAB:
-            tex->enabled = getU2( fp );
-            break;
-
-         case ID_NEGA:
-            tex->negative = getU2( fp );
-            break;
-
-         case ID_AXIS:
-            tex->axis = getU2( fp );
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) return 0;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the texture header subchunk? */
-
-      if ( hsz <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) return 0;
-   }
-
-   set_flen( _pico_memstream_tell( fp ) - pos );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetTMap()
-
-Read a texture map from a SURF.BLOK in an LWO2 file.  The TMAP
-defines the mapping from texture to world or object coordinates.
-====================================================================== */
-
-int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap )
-{
-   unsigned int id;
-   unsigned short sz;
-   int rlen, pos, i;
-
-   pos = _pico_memstream_tell( fp );
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) return 0;
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_SIZE:
-            for ( i = 0; i < 3; i++ )
-               tmap->size.val[ i ] = getF4( fp );
-            tmap->size.eindex = getVX( fp );
-            break;
-
-         case ID_CNTR:
-            for ( i = 0; i < 3; i++ )
-               tmap->center.val[ i ] = getF4( fp );
-            tmap->center.eindex = getVX( fp );
-            break;
-
-         case ID_ROTA:
-            for ( i = 0; i < 3; i++ )
-               tmap->rotate.val[ i ] = getF4( fp );
-            tmap->rotate.eindex = getVX( fp );
-            break;
-
-         case ID_FALL:
-            tmap->fall_type = getU2( fp );
-            for ( i = 0; i < 3; i++ )
-               tmap->falloff.val[ i ] = getF4( fp );
-            tmap->falloff.eindex = getVX( fp );
-            break;
-
-         case ID_OREF:
-            tmap->ref_object = getS0( fp );
-            break;
-
-         case ID_CSYS:
-            tmap->coord_sys = getU2( fp );
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading the current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) return 0;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the TMAP subchunk? */
-
-      if ( tmapsz <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) return 0;
-   }
-
-   set_flen( _pico_memstream_tell( fp ) - pos );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetImageMap()
-
-Read an lwImageMap from a SURF.BLOK in an LWO2 file.
-====================================================================== */
-
-int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex )
-{
-   unsigned int id;
-   unsigned short sz;
-   int rlen, pos;
-
-   pos = _pico_memstream_tell( fp );
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) return 0;
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_TMAP:
-            if ( !lwGetTMap( fp, sz, &tex->tmap )) return 0;
-            break;
-
-         case ID_PROJ:
-            tex->param.imap.projection = getU2( fp );
-            break;
-
-         case ID_VMAP:
-            tex->param.imap.vmap_name = getS0( fp );
-            break;
-
-         case ID_AXIS:
-            tex->param.imap.axis = getU2( fp );
-            break;
-
-         case ID_IMAG:
-            tex->param.imap.cindex = getVX( fp );
-            break;
-
-         case ID_WRAP:
-            tex->param.imap.wrapw_type = getU2( fp );
-            tex->param.imap.wraph_type = getU2( fp );
-            break;
-
-         case ID_WRPW:
-            tex->param.imap.wrapw.val = getF4( fp );
-            tex->param.imap.wrapw.eindex = getVX( fp );
-            break;
-
-         case ID_WRPH:
-            tex->param.imap.wraph.val = getF4( fp );
-            tex->param.imap.wraph.eindex = getVX( fp );
-            break;
-
-         case ID_AAST:
-            tex->param.imap.aas_flags = getU2( fp );
-            tex->param.imap.aa_strength = getF4( fp );
-            break;
-
-         case ID_PIXB:
-            tex->param.imap.pblend = getU2( fp );
-            break;
-
-         case ID_STCK:
-            tex->param.imap.stck.val = getF4( fp );
-            tex->param.imap.stck.eindex = getVX( fp );
-            break;
-
-         case ID_TAMP:
-            tex->param.imap.amplitude.val = getF4( fp );
-            tex->param.imap.amplitude.eindex = getVX( fp );
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading the current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) return 0;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the image map? */
-
-      if ( rsz <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) return 0;
-   }
-
-   set_flen( _pico_memstream_tell( fp ) - pos );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetProcedural()
-
-Read an lwProcedural from a SURF.BLOK in an LWO2 file.
-====================================================================== */
-
-int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex )
-{
-   unsigned int id;
-   unsigned short sz;
-   int rlen, pos;
-
-   pos = _pico_memstream_tell( fp );
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) return 0;
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_TMAP:
-            if ( !lwGetTMap( fp, sz, &tex->tmap )) return 0;
-            break;
-
-         case ID_AXIS:
-            tex->param.proc.axis = getU2( fp );
-            break;
-
-         case ID_VALU:
-            tex->param.proc.value[ 0 ] = getF4( fp );
-            if ( sz >= 8 ) tex->param.proc.value[ 1 ] = getF4( fp );
-            if ( sz >= 12 ) tex->param.proc.value[ 2 ] = getF4( fp );
-            break;
-
-         case ID_FUNC:
-            tex->param.proc.name = getS0( fp );
-            rlen = get_flen();
-            tex->param.proc.data = getbytes( fp, sz - rlen );
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading the current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) return 0;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the procedural block? */
-
-      if ( rsz <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) return 0;
-   }
-
-   set_flen( _pico_memstream_tell( fp ) - pos );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetGradient()
-
-Read an lwGradient from a SURF.BLOK in an LWO2 file.
-====================================================================== */
-
-int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex )
-{
-   unsigned int id;
-   unsigned short sz;
-   int rlen, pos, i, j, nkeys;
-
-   pos = _pico_memstream_tell( fp );
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) return 0;
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_TMAP:
-            if ( !lwGetTMap( fp, sz, &tex->tmap )) return 0;
-            break;
-
-         case ID_PNAM:
-            tex->param.grad.paramname = getS0( fp );
-            break;
-
-         case ID_INAM:
-            tex->param.grad.itemname = getS0( fp );
-            break;
-
-         case ID_GRST:
-            tex->param.grad.start = getF4( fp );
-            break;
-
-         case ID_GREN:
-            tex->param.grad.end = getF4( fp );
-            break;
-
-         case ID_GRPT:
-            tex->param.grad.repeat = getU2( fp );
-            break;
-
-         case ID_FKEY:
-            nkeys = sz / sizeof( lwGradKey );
-            tex->param.grad.key = _pico_calloc( nkeys, sizeof( lwGradKey ));
-            if ( !tex->param.grad.key ) return 0;
-            for ( i = 0; i < nkeys; i++ ) {
-               tex->param.grad.key[ i ].value = getF4( fp );
-               for ( j = 0; j < 4; j++ )
-                  tex->param.grad.key[ i ].rgba[ j ] = getF4( fp );
-            }
-            break;
-
-         case ID_IKEY:
-            nkeys = sz / 2;
-            tex->param.grad.ikey = _pico_calloc( nkeys, sizeof( short ));
-            if ( !tex->param.grad.ikey ) return 0;
-            for ( i = 0; i < nkeys; i++ )
-               tex->param.grad.ikey[ i ] = getU2( fp );
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading the current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) return 0;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the gradient? */
-
-      if ( rsz <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) return 0;
-   }
-
-   set_flen( _pico_memstream_tell( fp ) - pos );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetTexture()
-
-Read an lwTexture from a SURF.BLOK in an LWO2 file.
-====================================================================== */
-
-lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type )
-{
-   lwTexture *tex;
-   unsigned short sz;
-   int ok;
-
-   tex = _pico_calloc( 1, sizeof( lwTexture ));
-   if ( !tex ) return NULL;
-
-   tex->type = type;
-   tex->tmap.size.val[ 0 ] =
-   tex->tmap.size.val[ 1 ] =
-   tex->tmap.size.val[ 2 ] = 1.0f;
-   tex->opacity.val = 1.0f;
-   tex->enabled = 1;
-
-   sz = getU2( fp );
-   if ( !lwGetTHeader( fp, sz, tex )) {
-      _pico_free( tex );
-      return NULL;
-   }
-
-   sz = bloksz - sz - 6;
-   switch ( type ) {
-      case ID_IMAP:  ok = lwGetImageMap( fp, sz, tex );  break;
-      case ID_PROC:  ok = lwGetProcedural( fp, sz, tex );  break;
-      case ID_GRAD:  ok = lwGetGradient( fp, sz, tex );  break;
-      default:
-         ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
-   }
-
-   if ( !ok ) {
-      lwFreeTexture( tex );
-      return NULL;
-   }
-
-   set_flen( bloksz );
-   return tex;
-}
-
-
-/*
-======================================================================
-lwGetShader()
-
-Read a shader record from a SURF.BLOK in an LWO2 file.
-====================================================================== */
-
-lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz )
-{
-   lwPlugin *shdr;
-   unsigned int id;
-   unsigned short sz;
-   int hsz, rlen, pos;
-
-   shdr = _pico_calloc( 1, sizeof( lwPlugin ));
-   if ( !shdr ) return NULL;
-
-   pos = _pico_memstream_tell( fp );
-   set_flen( 0 );
-   hsz = getU2( fp );
-   shdr->ord = getS0( fp );
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   while ( hsz > 0 ) {
-      sz += sz & 1;
-      hsz -= sz;
-      if ( id == ID_ENAB ) {
-         shdr->flags = getU2( fp );
-         break;
-      }
-      else {
-         _pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
-         id = getU4( fp );
-         sz = getU2( fp );
-      }
-   }
-
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_FUNC:
-            shdr->name = getS0( fp );
-            rlen = get_flen();
-            shdr->data = getbytes( fp, sz - rlen );
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading the current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) goto Fail;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the shader block? */
-
-      if ( bloksz <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) goto Fail;
-   }
-
-   set_flen( _pico_memstream_tell( fp ) - pos );
-   return shdr;
-
-Fail:
-   lwFreePlugin( shdr );
-   return NULL;
-}
-
-
-/*
-======================================================================
-compare_textures()
-compare_shaders()
-
-Callbacks for the lwListInsert() function, which is called to add
-textures to surface channels and shaders to surfaces.
-====================================================================== */
-
-static int compare_textures( lwTexture *a, lwTexture *b )
-{
-   return strcmp( a->ord, b->ord );
-}
-
-
-static int compare_shaders( lwPlugin *a, lwPlugin *b )
-{
-   return strcmp( a->ord, b->ord );
-}
-
-
-/*
-======================================================================
-add_texture()
-
-Finds the surface channel (lwTParam or lwCParam) to which a texture is
-applied, then calls lwListInsert().
-====================================================================== */
-
-static int add_texture( lwSurface *surf, lwTexture *tex )
-{
-   lwTexture **list;
-
-   switch ( tex->chan ) {
-      case ID_COLR:  list = &surf->color.tex;             break;
-      case ID_LUMI:  list = &surf->luminosity.tex;        break;
-      case ID_DIFF:  list = &surf->diffuse.tex;           break;
-      case ID_SPEC:  list = &surf->specularity.tex;       break;
-      case ID_GLOS:  list = &surf->glossiness.tex;        break;
-      case ID_REFL:  list = &surf->reflection.val.tex;    break;
-      case ID_TRAN:  list = &surf->transparency.val.tex;  break;
-      case ID_RIND:  list = &surf->eta.tex;               break;
-      case ID_TRNL:  list = &surf->translucency.tex;      break;
-      case ID_BUMP:  list = &surf->bump.tex;              break;
-      default:  return 0;
-   }
-
-   lwListInsert( list, tex, compare_textures );
-   return 1;
-}
-
-
-/*
-======================================================================
-lwDefaultSurface()
-
-Allocate and initialize a surface.
-====================================================================== */
-
-lwSurface *lwDefaultSurface( void )
-{
-   lwSurface *surf;
-
-   surf = _pico_calloc( 1, sizeof( lwSurface ));
-   if ( !surf ) return NULL;
-
-   surf->color.rgb[ 0 ] = 0.78431f;
-   surf->color.rgb[ 1 ] = 0.78431f;
-   surf->color.rgb[ 2 ] = 0.78431f;
-   surf->diffuse.val    = 1.0f;
-   surf->glossiness.val = 0.4f;
-   surf->bump.val       = 1.0f;
-   surf->eta.val        = 1.0f;
-   surf->sideflags      = 1;
-
-   return surf;
-}
-
-
-/*
-======================================================================
-lwGetSurface()
-
-Read an lwSurface from an LWO2 file.
-====================================================================== */
-
-lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize )
-{
-   lwSurface *surf;
-   lwTexture *tex;
-   lwPlugin *shdr;
-   unsigned int id, type;
-   unsigned short sz;
-   int pos, rlen;
-
-
-   /* allocate the Surface structure */
-
-   surf = _pico_calloc( 1, sizeof( lwSurface ));
-   if ( !surf ) goto Fail;
-
-   /* non-zero defaults */
-
-   surf->color.rgb[ 0 ] = 0.78431f;
-   surf->color.rgb[ 1 ] = 0.78431f;
-   surf->color.rgb[ 2 ] = 0.78431f;
-   surf->diffuse.val    = 1.0f;
-   surf->glossiness.val = 0.4f;
-   surf->bump.val       = 1.0f;
-   surf->eta.val        = 1.0f;
-   surf->sideflags      = 1;
-
-   /* remember where we started */
-
-   set_flen( 0 );
-   pos = _pico_memstream_tell( fp );
-
-   /* names */
-
-   surf->name = getS0( fp );
-   surf->srcname = getS0( fp );
-
-   /* first subchunk header */
-
-   id = getU4( fp );
-   sz = getU2( fp );
-   if ( 0 > get_flen() ) goto Fail;
-
-   /* process subchunks as they're encountered */
-
-   while ( 1 ) {
-      sz += sz & 1;
-      set_flen( 0 );
-
-      switch ( id ) {
-         case ID_COLR:
-            surf->color.rgb[ 0 ] = getF4( fp );
-            surf->color.rgb[ 1 ] = getF4( fp );
-            surf->color.rgb[ 2 ] = getF4( fp );
-            surf->color.eindex = getVX( fp );
-            break;
-
-         case ID_LUMI:
-            surf->luminosity.val = getF4( fp );
-            surf->luminosity.eindex = getVX( fp );
-            break;
-
-         case ID_DIFF:
-            surf->diffuse.val = getF4( fp );
-            surf->diffuse.eindex = getVX( fp );
-            break;
-
-         case ID_SPEC:
-            surf->specularity.val = getF4( fp );
-            surf->specularity.eindex = getVX( fp );
-            break;
-
-         case ID_GLOS:
-            surf->glossiness.val = getF4( fp );
-            surf->glossiness.eindex = getVX( fp );
-            break;
-
-         case ID_REFL:
-            surf->reflection.val.val = getF4( fp );
-            surf->reflection.val.eindex = getVX( fp );
-            break;
-
-         case ID_RFOP:
-            surf->reflection.options = getU2( fp );
-            break;
-
-         case ID_RIMG:
-            surf->reflection.cindex = getVX( fp );
-            break;
-
-         case ID_RSAN:
-            surf->reflection.seam_angle = getF4( fp );
-            break;
-
-         case ID_TRAN:
-            surf->transparency.val.val = getF4( fp );
-            surf->transparency.val.eindex = getVX( fp );
-            break;
-
-         case ID_TROP:
-            surf->transparency.options = getU2( fp );
-            break;
-
-         case ID_TIMG:
-            surf->transparency.cindex = getVX( fp );
-            break;
-
-         case ID_RIND:
-            surf->eta.val = getF4( fp );
-            surf->eta.eindex = getVX( fp );
-            break;
-
-         case ID_TRNL:
-            surf->translucency.val = getF4( fp );
-            surf->translucency.eindex = getVX( fp );
-            break;
-
-         case ID_BUMP:
-            surf->bump.val = getF4( fp );
-            surf->bump.eindex = getVX( fp );
-            break;
-
-         case ID_SMAN:
-            surf->smooth = getF4( fp );
-            break;
-
-         case ID_SIDE:
-            surf->sideflags = getU2( fp );
-            break;
-
-         case ID_CLRH:
-            surf->color_hilite.val = getF4( fp );
-            surf->color_hilite.eindex = getVX( fp );
-            break;
-
-         case ID_CLRF:
-            surf->color_filter.val = getF4( fp );
-            surf->color_filter.eindex = getVX( fp );
-            break;
-
-         case ID_ADTR:
-            surf->add_trans.val = getF4( fp );
-            surf->add_trans.eindex = getVX( fp );
-            break;
-
-         case ID_SHRP:
-            surf->dif_sharp.val = getF4( fp );
-            surf->dif_sharp.eindex = getVX( fp );
-            break;
-
-         case ID_GVAL:
-            surf->glow.val = getF4( fp );
-            surf->glow.eindex = getVX( fp );
-            break;
-
-         case ID_LINE:
-            surf->line.enabled = 1;
-            if ( sz >= 2 ) surf->line.flags = getU2( fp );
-            if ( sz >= 6 ) surf->line.size.val = getF4( fp );
-            if ( sz >= 8 ) surf->line.size.eindex = getVX( fp );
-            break;
-
-         case ID_ALPH:
-            surf->alpha_mode = getU2( fp );
-            surf->alpha = getF4( fp );
-            break;
-
-         case ID_AVAL:
-            surf->alpha = getF4( fp );
-            break;
-
-         case ID_BLOK:
-            type = getU4( fp );
-
-            switch ( type ) {
-               case ID_IMAP:
-               case ID_PROC:
-               case ID_GRAD:
-                  tex = lwGetTexture( fp, sz - 4, type );
-                  if ( !tex ) goto Fail;
-                  if ( !add_texture( surf, tex ))
-                     lwFreeTexture( tex );
-                  set_flen( 4 + get_flen() );
-                  break;
-               case ID_SHDR:
-                  shdr = lwGetShader( fp, sz - 4 );
-                  if ( !shdr ) goto Fail;
-                  lwListInsert( &surf->shader, shdr, compare_shaders );
-                  ++surf->nshaders;
-                  set_flen( 4 + get_flen() );
-                  break;
-            }
-            break;
-
-         default:
-            break;
-      }
-
-      /* error while reading current subchunk? */
-
-      rlen = get_flen();
-      if ( rlen < 0 || rlen > sz ) goto Fail;
-
-      /* skip unread parts of the current subchunk */
-
-      if ( rlen < sz )
-         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
-
-      /* end of the SURF chunk? */
-
-      if ( cksize <= _pico_memstream_tell( fp ) - pos )
-         break;
-
-      /* get the next subchunk header */
-
-      set_flen( 0 );
-      id = getU4( fp );
-      sz = getU2( fp );
-      if ( 6 != get_flen() ) goto Fail;
-   }
-
-   return surf;
-
-Fail:
-   if ( surf ) lwFreeSurface( surf );
-   return NULL;
-}
+/*
+======================================================================
+surface.c
+
+Surface functions for an LWO2 reader.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+
+/*
+======================================================================
+lwFreePlugin()
+
+Free the memory used by an lwPlugin.
+====================================================================== */
+
+void lwFreePlugin( lwPlugin *p )
+{
+   if ( p ) {
+      if ( p->ord ) _pico_free( p->ord );
+      if ( p->name ) _pico_free( p->name );
+      if ( p->data ) _pico_free( p->data );
+      _pico_free( p );
+   }
+}
+
+
+/*
+======================================================================
+lwFreeTexture()
+
+Free the memory used by an lwTexture.
+====================================================================== */
+
+void lwFreeTexture( lwTexture *t )
+{
+   if ( t ) {
+      if ( t->ord ) _pico_free( t->ord );
+      switch ( t->type ) {
+         case ID_IMAP:
+            if ( t->param.imap.vmap_name ) _pico_free( t->param.imap.vmap_name );
+            break;
+         case ID_PROC:
+            if ( t->param.proc.name ) _pico_free( t->param.proc.name );
+            if ( t->param.proc.data ) _pico_free( t->param.proc.data );
+            break;
+         case ID_GRAD:
+            if ( t->param.grad.key ) _pico_free( t->param.grad.key );
+            if ( t->param.grad.ikey ) _pico_free( t->param.grad.ikey );
+            break;
+      }
+      _pico_free( t );
+   }
+}
+
+
+/*
+======================================================================
+lwFreeSurface()
+
+Free the memory used by an lwSurface.
+====================================================================== */
+
+void lwFreeSurface( lwSurface *surf )
+{
+   if ( surf ) {
+      if ( surf->name ) _pico_free( surf->name );
+      if ( surf->srcname ) _pico_free( surf->srcname );
+
+      lwListFree( surf->shader, lwFreePlugin );
+
+      lwListFree( surf->color.tex, lwFreeTexture );
+      lwListFree( surf->luminosity.tex, lwFreeTexture );
+      lwListFree( surf->diffuse.tex, lwFreeTexture );
+      lwListFree( surf->specularity.tex, lwFreeTexture );
+      lwListFree( surf->glossiness.tex, lwFreeTexture );
+      lwListFree( surf->reflection.val.tex, lwFreeTexture );
+      lwListFree( surf->transparency.val.tex, lwFreeTexture );
+      lwListFree( surf->eta.tex, lwFreeTexture );
+      lwListFree( surf->translucency.tex, lwFreeTexture );
+      lwListFree( surf->bump.tex, lwFreeTexture );
+
+      _pico_free( surf );
+   }
+}
+
+
+/*
+======================================================================
+lwGetTHeader()
+
+Read a texture map header from a SURF.BLOK in an LWO2 file.  This is
+the first subchunk in a BLOK, and its contents are common to all three
+texture types.
+====================================================================== */
+
+int lwGetTHeader( picoMemStream_t *fp, int hsz, lwTexture *tex )
+{
+   unsigned int id;
+   unsigned short sz;
+   int pos, rlen;
+
+
+   /* remember where we started */
+
+   set_flen( 0 );
+   pos = _pico_memstream_tell( fp );
+
+   /* ordinal string */
+
+   tex->ord = getS0( fp );
+
+   /* first subchunk header */
+
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) return 0;
+
+   /* process subchunks as they're encountered */
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_CHAN:
+            tex->chan = getU4( fp );
+            break;
+
+         case ID_OPAC:
+            tex->opac_type = getU2( fp );
+            tex->opacity.val = getF4( fp );
+            tex->opacity.eindex = getVX( fp );
+            break;
+
+         case ID_ENAB:
+            tex->enabled = getU2( fp );
+            break;
+
+         case ID_NEGA:
+            tex->negative = getU2( fp );
+            break;
+
+         case ID_AXIS:
+            tex->axis = getU2( fp );
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) return 0;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the texture header subchunk? */
+
+      if ( hsz <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) return 0;
+   }
+
+   set_flen( _pico_memstream_tell( fp ) - pos );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetTMap()
+
+Read a texture map from a SURF.BLOK in an LWO2 file.  The TMAP
+defines the mapping from texture to world or object coordinates.
+====================================================================== */
+
+int lwGetTMap( picoMemStream_t *fp, int tmapsz, lwTMap *tmap )
+{
+   unsigned int id;
+   unsigned short sz;
+   int rlen, pos, i;
+
+   pos = _pico_memstream_tell( fp );
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) return 0;
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_SIZE:
+            for ( i = 0; i < 3; i++ )
+               tmap->size.val[ i ] = getF4( fp );
+            tmap->size.eindex = getVX( fp );
+            break;
+
+         case ID_CNTR:
+            for ( i = 0; i < 3; i++ )
+               tmap->center.val[ i ] = getF4( fp );
+            tmap->center.eindex = getVX( fp );
+            break;
+
+         case ID_ROTA:
+            for ( i = 0; i < 3; i++ )
+               tmap->rotate.val[ i ] = getF4( fp );
+            tmap->rotate.eindex = getVX( fp );
+            break;
+
+         case ID_FALL:
+            tmap->fall_type = getU2( fp );
+            for ( i = 0; i < 3; i++ )
+               tmap->falloff.val[ i ] = getF4( fp );
+            tmap->falloff.eindex = getVX( fp );
+            break;
+
+         case ID_OREF:
+            tmap->ref_object = getS0( fp );
+            break;
+
+         case ID_CSYS:
+            tmap->coord_sys = getU2( fp );
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading the current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) return 0;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the TMAP subchunk? */
+
+      if ( tmapsz <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) return 0;
+   }
+
+   set_flen( _pico_memstream_tell( fp ) - pos );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetImageMap()
+
+Read an lwImageMap from a SURF.BLOK in an LWO2 file.
+====================================================================== */
+
+int lwGetImageMap( picoMemStream_t *fp, int rsz, lwTexture *tex )
+{
+   unsigned int id;
+   unsigned short sz;
+   int rlen, pos;
+
+   pos = _pico_memstream_tell( fp );
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) return 0;
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_TMAP:
+            if ( !lwGetTMap( fp, sz, &tex->tmap )) return 0;
+            break;
+
+         case ID_PROJ:
+            tex->param.imap.projection = getU2( fp );
+            break;
+
+         case ID_VMAP:
+            tex->param.imap.vmap_name = getS0( fp );
+            break;
+
+         case ID_AXIS:
+            tex->param.imap.axis = getU2( fp );
+            break;
+
+         case ID_IMAG:
+            tex->param.imap.cindex = getVX( fp );
+            break;
+
+         case ID_WRAP:
+            tex->param.imap.wrapw_type = getU2( fp );
+            tex->param.imap.wraph_type = getU2( fp );
+            break;
+
+         case ID_WRPW:
+            tex->param.imap.wrapw.val = getF4( fp );
+            tex->param.imap.wrapw.eindex = getVX( fp );
+            break;
+
+         case ID_WRPH:
+            tex->param.imap.wraph.val = getF4( fp );
+            tex->param.imap.wraph.eindex = getVX( fp );
+            break;
+
+         case ID_AAST:
+            tex->param.imap.aas_flags = getU2( fp );
+            tex->param.imap.aa_strength = getF4( fp );
+            break;
+
+         case ID_PIXB:
+            tex->param.imap.pblend = getU2( fp );
+            break;
+
+         case ID_STCK:
+            tex->param.imap.stck.val = getF4( fp );
+            tex->param.imap.stck.eindex = getVX( fp );
+            break;
+
+         case ID_TAMP:
+            tex->param.imap.amplitude.val = getF4( fp );
+            tex->param.imap.amplitude.eindex = getVX( fp );
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading the current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) return 0;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the image map? */
+
+      if ( rsz <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) return 0;
+   }
+
+   set_flen( _pico_memstream_tell( fp ) - pos );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetProcedural()
+
+Read an lwProcedural from a SURF.BLOK in an LWO2 file.
+====================================================================== */
+
+int lwGetProcedural( picoMemStream_t *fp, int rsz, lwTexture *tex )
+{
+   unsigned int id;
+   unsigned short sz;
+   int rlen, pos;
+
+   pos = _pico_memstream_tell( fp );
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) return 0;
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_TMAP:
+            if ( !lwGetTMap( fp, sz, &tex->tmap )) return 0;
+            break;
+
+         case ID_AXIS:
+            tex->param.proc.axis = getU2( fp );
+            break;
+
+         case ID_VALU:
+            tex->param.proc.value[ 0 ] = getF4( fp );
+            if ( sz >= 8 ) tex->param.proc.value[ 1 ] = getF4( fp );
+            if ( sz >= 12 ) tex->param.proc.value[ 2 ] = getF4( fp );
+            break;
+
+         case ID_FUNC:
+            tex->param.proc.name = getS0( fp );
+            rlen = get_flen();
+            tex->param.proc.data = getbytes( fp, sz - rlen );
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading the current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) return 0;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the procedural block? */
+
+      if ( rsz <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) return 0;
+   }
+
+   set_flen( _pico_memstream_tell( fp ) - pos );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetGradient()
+
+Read an lwGradient from a SURF.BLOK in an LWO2 file.
+====================================================================== */
+
+int lwGetGradient( picoMemStream_t *fp, int rsz, lwTexture *tex )
+{
+   unsigned int id;
+   unsigned short sz;
+   int rlen, pos, i, j, nkeys;
+
+   pos = _pico_memstream_tell( fp );
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) return 0;
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_TMAP:
+            if ( !lwGetTMap( fp, sz, &tex->tmap )) return 0;
+            break;
+
+         case ID_PNAM:
+            tex->param.grad.paramname = getS0( fp );
+            break;
+
+         case ID_INAM:
+            tex->param.grad.itemname = getS0( fp );
+            break;
+
+         case ID_GRST:
+            tex->param.grad.start = getF4( fp );
+            break;
+
+         case ID_GREN:
+            tex->param.grad.end = getF4( fp );
+            break;
+
+         case ID_GRPT:
+            tex->param.grad.repeat = getU2( fp );
+            break;
+
+         case ID_FKEY:
+            nkeys = sz / sizeof( lwGradKey );
+            tex->param.grad.key = _pico_calloc( nkeys, sizeof( lwGradKey ));
+            if ( !tex->param.grad.key ) return 0;
+            for ( i = 0; i < nkeys; i++ ) {
+               tex->param.grad.key[ i ].value = getF4( fp );
+               for ( j = 0; j < 4; j++ )
+                  tex->param.grad.key[ i ].rgba[ j ] = getF4( fp );
+            }
+            break;
+
+         case ID_IKEY:
+            nkeys = sz / 2;
+            tex->param.grad.ikey = _pico_calloc( nkeys, sizeof( short ));
+            if ( !tex->param.grad.ikey ) return 0;
+            for ( i = 0; i < nkeys; i++ )
+               tex->param.grad.ikey[ i ] = getU2( fp );
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading the current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) return 0;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the gradient? */
+
+      if ( rsz <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) return 0;
+   }
+
+   set_flen( _pico_memstream_tell( fp ) - pos );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetTexture()
+
+Read an lwTexture from a SURF.BLOK in an LWO2 file.
+====================================================================== */
+
+lwTexture *lwGetTexture( picoMemStream_t *fp, int bloksz, unsigned int type )
+{
+   lwTexture *tex;
+   unsigned short sz;
+   int ok;
+
+   tex = _pico_calloc( 1, sizeof( lwTexture ));
+   if ( !tex ) return NULL;
+
+   tex->type = type;
+   tex->tmap.size.val[ 0 ] =
+   tex->tmap.size.val[ 1 ] =
+   tex->tmap.size.val[ 2 ] = 1.0f;
+   tex->opacity.val = 1.0f;
+   tex->enabled = 1;
+
+   sz = getU2( fp );
+   if ( !lwGetTHeader( fp, sz, tex )) {
+      _pico_free( tex );
+      return NULL;
+   }
+
+   sz = bloksz - sz - 6;
+   switch ( type ) {
+      case ID_IMAP:  ok = lwGetImageMap( fp, sz, tex );  break;
+      case ID_PROC:  ok = lwGetProcedural( fp, sz, tex );  break;
+      case ID_GRAD:  ok = lwGetGradient( fp, sz, tex );  break;
+      default:
+         ok = !_pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
+   }
+
+   if ( !ok ) {
+      lwFreeTexture( tex );
+      return NULL;
+   }
+
+   set_flen( bloksz );
+   return tex;
+}
+
+
+/*
+======================================================================
+lwGetShader()
+
+Read a shader record from a SURF.BLOK in an LWO2 file.
+====================================================================== */
+
+lwPlugin *lwGetShader( picoMemStream_t *fp, int bloksz )
+{
+   lwPlugin *shdr;
+   unsigned int id;
+   unsigned short sz;
+   int hsz, rlen, pos;
+
+   shdr = _pico_calloc( 1, sizeof( lwPlugin ));
+   if ( !shdr ) return NULL;
+
+   pos = _pico_memstream_tell( fp );
+   set_flen( 0 );
+   hsz = getU2( fp );
+   shdr->ord = getS0( fp );
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   while ( hsz > 0 ) {
+      sz += sz & 1;
+      hsz -= sz;
+      if ( id == ID_ENAB ) {
+         shdr->flags = getU2( fp );
+         break;
+      }
+      else {
+         _pico_memstream_seek( fp, sz, PICO_SEEK_CUR );
+         id = getU4( fp );
+         sz = getU2( fp );
+      }
+   }
+
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_FUNC:
+            shdr->name = getS0( fp );
+            rlen = get_flen();
+            shdr->data = getbytes( fp, sz - rlen );
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading the current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) goto Fail;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the shader block? */
+
+      if ( bloksz <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) goto Fail;
+   }
+
+   set_flen( _pico_memstream_tell( fp ) - pos );
+   return shdr;
+
+Fail:
+   lwFreePlugin( shdr );
+   return NULL;
+}
+
+
+/*
+======================================================================
+compare_textures()
+compare_shaders()
+
+Callbacks for the lwListInsert() function, which is called to add
+textures to surface channels and shaders to surfaces.
+====================================================================== */
+
+static int compare_textures( lwTexture *a, lwTexture *b )
+{
+   return strcmp( a->ord, b->ord );
+}
+
+
+static int compare_shaders( lwPlugin *a, lwPlugin *b )
+{
+   return strcmp( a->ord, b->ord );
+}
+
+
+/*
+======================================================================
+add_texture()
+
+Finds the surface channel (lwTParam or lwCParam) to which a texture is
+applied, then calls lwListInsert().
+====================================================================== */
+
+static int add_texture( lwSurface *surf, lwTexture *tex )
+{
+   lwTexture **list;
+
+   switch ( tex->chan ) {
+      case ID_COLR:  list = &surf->color.tex;             break;
+      case ID_LUMI:  list = &surf->luminosity.tex;        break;
+      case ID_DIFF:  list = &surf->diffuse.tex;           break;
+      case ID_SPEC:  list = &surf->specularity.tex;       break;
+      case ID_GLOS:  list = &surf->glossiness.tex;        break;
+      case ID_REFL:  list = &surf->reflection.val.tex;    break;
+      case ID_TRAN:  list = &surf->transparency.val.tex;  break;
+      case ID_RIND:  list = &surf->eta.tex;               break;
+      case ID_TRNL:  list = &surf->translucency.tex;      break;
+      case ID_BUMP:  list = &surf->bump.tex;              break;
+      default:  return 0;
+   }
+
+   lwListInsert( list, tex, compare_textures );
+   return 1;
+}
+
+
+/*
+======================================================================
+lwDefaultSurface()
+
+Allocate and initialize a surface.
+====================================================================== */
+
+lwSurface *lwDefaultSurface( void )
+{
+   lwSurface *surf;
+
+   surf = _pico_calloc( 1, sizeof( lwSurface ));
+   if ( !surf ) return NULL;
+
+   surf->color.rgb[ 0 ] = 0.78431f;
+   surf->color.rgb[ 1 ] = 0.78431f;
+   surf->color.rgb[ 2 ] = 0.78431f;
+   surf->diffuse.val    = 1.0f;
+   surf->glossiness.val = 0.4f;
+   surf->bump.val       = 1.0f;
+   surf->eta.val        = 1.0f;
+   surf->sideflags      = 1;
+
+   return surf;
+}
+
+
+/*
+======================================================================
+lwGetSurface()
+
+Read an lwSurface from an LWO2 file.
+====================================================================== */
+
+lwSurface *lwGetSurface( picoMemStream_t *fp, int cksize )
+{
+   lwSurface *surf;
+   lwTexture *tex;
+   lwPlugin *shdr;
+   unsigned int id, type;
+   unsigned short sz;
+   int pos, rlen;
+
+
+   /* allocate the Surface structure */
+
+   surf = _pico_calloc( 1, sizeof( lwSurface ));
+   if ( !surf ) goto Fail;
+
+   /* non-zero defaults */
+
+   surf->color.rgb[ 0 ] = 0.78431f;
+   surf->color.rgb[ 1 ] = 0.78431f;
+   surf->color.rgb[ 2 ] = 0.78431f;
+   surf->diffuse.val    = 1.0f;
+   surf->glossiness.val = 0.4f;
+   surf->bump.val       = 1.0f;
+   surf->eta.val        = 1.0f;
+   surf->sideflags      = 1;
+
+   /* remember where we started */
+
+   set_flen( 0 );
+   pos = _pico_memstream_tell( fp );
+
+   /* names */
+
+   surf->name = getS0( fp );
+   surf->srcname = getS0( fp );
+
+   /* first subchunk header */
+
+   id = getU4( fp );
+   sz = getU2( fp );
+   if ( 0 > get_flen() ) goto Fail;
+
+   /* process subchunks as they're encountered */
+
+   while ( 1 ) {
+      sz += sz & 1;
+      set_flen( 0 );
+
+      switch ( id ) {
+         case ID_COLR:
+            surf->color.rgb[ 0 ] = getF4( fp );
+            surf->color.rgb[ 1 ] = getF4( fp );
+            surf->color.rgb[ 2 ] = getF4( fp );
+            surf->color.eindex = getVX( fp );
+            break;
+
+         case ID_LUMI:
+            surf->luminosity.val = getF4( fp );
+            surf->luminosity.eindex = getVX( fp );
+            break;
+
+         case ID_DIFF:
+            surf->diffuse.val = getF4( fp );
+            surf->diffuse.eindex = getVX( fp );
+            break;
+
+         case ID_SPEC:
+            surf->specularity.val = getF4( fp );
+            surf->specularity.eindex = getVX( fp );
+            break;
+
+         case ID_GLOS:
+            surf->glossiness.val = getF4( fp );
+            surf->glossiness.eindex = getVX( fp );
+            break;
+
+         case ID_REFL:
+            surf->reflection.val.val = getF4( fp );
+            surf->reflection.val.eindex = getVX( fp );
+            break;
+
+         case ID_RFOP:
+            surf->reflection.options = getU2( fp );
+            break;
+
+         case ID_RIMG:
+            surf->reflection.cindex = getVX( fp );
+            break;
+
+         case ID_RSAN:
+            surf->reflection.seam_angle = getF4( fp );
+            break;
+
+         case ID_TRAN:
+            surf->transparency.val.val = getF4( fp );
+            surf->transparency.val.eindex = getVX( fp );
+            break;
+
+         case ID_TROP:
+            surf->transparency.options = getU2( fp );
+            break;
+
+         case ID_TIMG:
+            surf->transparency.cindex = getVX( fp );
+            break;
+
+         case ID_RIND:
+            surf->eta.val = getF4( fp );
+            surf->eta.eindex = getVX( fp );
+            break;
+
+         case ID_TRNL:
+            surf->translucency.val = getF4( fp );
+            surf->translucency.eindex = getVX( fp );
+            break;
+
+         case ID_BUMP:
+            surf->bump.val = getF4( fp );
+            surf->bump.eindex = getVX( fp );
+            break;
+
+         case ID_SMAN:
+            surf->smooth = getF4( fp );
+            break;
+
+         case ID_SIDE:
+            surf->sideflags = getU2( fp );
+            break;
+
+         case ID_CLRH:
+            surf->color_hilite.val = getF4( fp );
+            surf->color_hilite.eindex = getVX( fp );
+            break;
+
+         case ID_CLRF:
+            surf->color_filter.val = getF4( fp );
+            surf->color_filter.eindex = getVX( fp );
+            break;
+
+         case ID_ADTR:
+            surf->add_trans.val = getF4( fp );
+            surf->add_trans.eindex = getVX( fp );
+            break;
+
+         case ID_SHRP:
+            surf->dif_sharp.val = getF4( fp );
+            surf->dif_sharp.eindex = getVX( fp );
+            break;
+
+         case ID_GVAL:
+            surf->glow.val = getF4( fp );
+            surf->glow.eindex = getVX( fp );
+            break;
+
+         case ID_LINE:
+            surf->line.enabled = 1;
+            if ( sz >= 2 ) surf->line.flags = getU2( fp );
+            if ( sz >= 6 ) surf->line.size.val = getF4( fp );
+            if ( sz >= 8 ) surf->line.size.eindex = getVX( fp );
+            break;
+
+         case ID_ALPH:
+            surf->alpha_mode = getU2( fp );
+            surf->alpha = getF4( fp );
+            break;
+
+         case ID_AVAL:
+            surf->alpha = getF4( fp );
+            break;
+
+         case ID_BLOK:
+            type = getU4( fp );
+
+            switch ( type ) {
+               case ID_IMAP:
+               case ID_PROC:
+               case ID_GRAD:
+                  tex = lwGetTexture( fp, sz - 4, type );
+                  if ( !tex ) goto Fail;
+                  if ( !add_texture( surf, tex ))
+                     lwFreeTexture( tex );
+                  set_flen( 4 + get_flen() );
+                  break;
+               case ID_SHDR:
+                  shdr = lwGetShader( fp, sz - 4 );
+                  if ( !shdr ) goto Fail;
+                  lwListInsert( &surf->shader, shdr, compare_shaders );
+                  ++surf->nshaders;
+                  set_flen( 4 + get_flen() );
+                  break;
+            }
+            break;
+
+         default:
+            break;
+      }
+
+      /* error while reading current subchunk? */
+
+      rlen = get_flen();
+      if ( rlen < 0 || rlen > sz ) goto Fail;
+
+      /* skip unread parts of the current subchunk */
+
+      if ( rlen < sz )
+         _pico_memstream_seek( fp, sz - rlen, PICO_SEEK_CUR );
+
+      /* end of the SURF chunk? */
+
+      if ( cksize <= _pico_memstream_tell( fp ) - pos )
+         break;
+
+      /* get the next subchunk header */
+
+      set_flen( 0 );
+      id = getU4( fp );
+      sz = getU2( fp );
+      if ( 6 != get_flen() ) goto Fail;
+   }
+
+   return surf;
+
+Fail:
+   if ( surf ) lwFreeSurface( surf );
+   return NULL;
+}
diff --git a/libs/picomodel/lwo/vecmath.c b/libs/picomodel/lwo/vecmath.c
index 44d317b0..eaa1e8fc 100644
--- a/libs/picomodel/lwo/vecmath.c
+++ b/libs/picomodel/lwo/vecmath.c
@@ -1,37 +1,37 @@
-/*
-======================================================================
-vecmath.c
-
-Basic vector and matrix functions.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include <math.h>
-
-
-float dot( float a[], float b[] )
-{
-   return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
-}
-
-
-void cross( float a[], float b[], float c[] )
-{
-   c[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
-   c[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
-   c[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
-}
-
-
-void normalize( float v[] )
-{
-   float r;
-
-   r = ( float ) sqrt( dot( v, v ));
-   if ( r > 0 ) {
-      v[ 0 ] /= r;
-      v[ 1 ] /= r;
-      v[ 2 ] /= r;
-   }
-}
+/*
+======================================================================
+vecmath.c
+
+Basic vector and matrix functions.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include <math.h>
+
+
+float dot( float a[], float b[] )
+{
+   return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
+}
+
+
+void cross( float a[], float b[], float c[] )
+{
+   c[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
+   c[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
+   c[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
+}
+
+
+void normalize( float v[] )
+{
+   float r;
+
+   r = ( float ) sqrt( dot( v, v ));
+   if ( r > 0 ) {
+      v[ 0 ] /= r;
+      v[ 1 ] /= r;
+      v[ 2 ] /= r;
+   }
+}
diff --git a/libs/picomodel/lwo/vmap.c b/libs/picomodel/lwo/vmap.c
index 1a24bee0..69f87cf9 100644
--- a/libs/picomodel/lwo/vmap.c
+++ b/libs/picomodel/lwo/vmap.c
@@ -1,243 +1,243 @@
-/*
-======================================================================
-vmap.c
-
-Vertex map functions for an LWO2 reader.
-
-Ernie Wright  17 Sep 00
-====================================================================== */
-
-#include "../picointernal.h"
-#include "lwo2.h"
-
-
-/*
-======================================================================
-lwFreeVMap()
-
-Free memory used by an lwVMap.
-====================================================================== */
-
-void lwFreeVMap( lwVMap *vmap )
-{
-   if ( vmap ) {
-      if ( vmap->name ) _pico_free( vmap->name );
-      if ( vmap->vindex ) _pico_free( vmap->vindex );
-      if ( vmap->pindex ) _pico_free( vmap->pindex );
-      if ( vmap->val ) {
-         if ( vmap->val[ 0 ] ) _pico_free( vmap->val[ 0 ] );
-         _pico_free( vmap->val );
-      }
-      _pico_free( vmap );
-   }
-}
-
-
-/*
-======================================================================
-lwGetVMap()
-
-Read an lwVMap from a VMAP or VMAD chunk in an LWO2.
-====================================================================== */
-
-lwVMap *lwGetVMap( picoMemStream_t *fp, int cksize, int ptoffset, int poloffset,
-   int perpoly )
-{
-   unsigned char *buf, *bp;
-   lwVMap *vmap;
-   float *f;
-   int i, j, npts, rlen;
-
-
-   /* read the whole chunk */
-
-   set_flen( 0 );
-   buf = getbytes( fp, cksize );
-   if ( !buf ) return NULL;
-
-   vmap = _pico_calloc( 1, sizeof( lwVMap ));
-   if ( !vmap ) {
-      _pico_free( buf );
-      return NULL;
-   }
-
-   /* initialize the vmap */
-
-   vmap->perpoly = perpoly;
-
-   bp = buf;
-   set_flen( 0 );
-   vmap->type = sgetU4( &bp );
-   vmap->dim  = sgetU2( &bp );
-   vmap->name = sgetS0( &bp );
-   rlen = get_flen();
-
-   /* count the vmap records */
-
-   npts = 0;
-   while ( bp < buf + cksize ) {
-      i = sgetVX( &bp );
-      if ( perpoly )
-         i = sgetVX( &bp );
-      bp += vmap->dim * sizeof( float );
-      ++npts;
-   }
-
-   /* allocate the vmap */
-
-   vmap->nverts = npts;
-   vmap->vindex = _pico_calloc( npts, sizeof( int ));
-   if ( !vmap->vindex ) goto Fail;
-   if ( perpoly ) {
-      vmap->pindex = _pico_calloc( npts, sizeof( int ));
-      if ( !vmap->pindex ) goto Fail;
-   }
-
-   if ( vmap->dim > 0 ) {
-      vmap->val = _pico_calloc( npts, sizeof( float * ));
-      if ( !vmap->val ) goto Fail;
-      f = _pico_alloc( npts * vmap->dim * sizeof( float ));
-      if ( !f ) goto Fail;
-      for ( i = 0; i < npts; i++ )
-         vmap->val[ i ] = f + i * vmap->dim;
-   }
-
-   /* fill in the vmap values */
-
-   bp = buf + rlen;
-   for ( i = 0; i < npts; i++ ) {
-      vmap->vindex[ i ] = sgetVX( &bp );
-      if ( perpoly )
-         vmap->pindex[ i ] = sgetVX( &bp );
-      for ( j = 0; j < vmap->dim; j++ )
-         vmap->val[ i ][ j ] = sgetF4( &bp );
-   }
-
-   _pico_free( buf );
-   return vmap;
-
-Fail:
-   if ( buf ) _pico_free( buf );
-   lwFreeVMap( vmap );
-   return NULL;
-}
-
-
-/*
-======================================================================
-lwGetPointVMaps()
-
-Fill in the lwVMapPt structure for each point.
-====================================================================== */
-
-int lwGetPointVMaps( lwPointList *point, lwVMap *vmap )
-{
-   lwVMap *vm;
-   int i, j, n;
-
-   /* count the number of vmap values for each point */
-
-   vm = vmap;
-   while ( vm ) {
-      if ( !vm->perpoly )
-         for ( i = 0; i < vm->nverts; i++ )
-            ++point->pt[ vm->vindex[ i ]].nvmaps;
-      vm = vm->next;
-   }
-
-   /* allocate vmap references for each mapped point */
-
-   for ( i = 0; i < point->count; i++ ) {
-      if ( point->pt[ i ].nvmaps ) {
-         point->pt[ i ].vm = _pico_calloc( point->pt[ i ].nvmaps, sizeof( lwVMapPt ));
-         if ( !point->pt[ i ].vm ) return 0;
-         point->pt[ i ].nvmaps = 0;
-      }
-   }
-
-   /* fill in vmap references for each mapped point */
-
-   vm = vmap;
-   while ( vm ) {
-      if ( !vm->perpoly ) {
-         for ( i = 0; i < vm->nverts; i++ ) {
-            j = vm->vindex[ i ];
-            n = point->pt[ j ].nvmaps;
-            point->pt[ j ].vm[ n ].vmap = vm;
-            point->pt[ j ].vm[ n ].index = i;
-            ++point->pt[ j ].nvmaps;
-         }
-      }
-      vm = vm->next;
-   }
-
-   return 1;
-}
-
-
-/*
-======================================================================
-lwGetPolyVMaps()
-
-Fill in the lwVMapPt structure for each polygon vertex.
-====================================================================== */
-
-int lwGetPolyVMaps( lwPolygonList *polygon, lwVMap *vmap )
-{
-   lwVMap *vm;
-   lwPolVert *pv;
-   int i, j;
-
-   /* count the number of vmap values for each polygon vertex */
-
-   vm = vmap;
-   while ( vm ) {
-      if ( vm->perpoly ) {
-         for ( i = 0; i < vm->nverts; i++ ) {
-            for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) {
-               pv = &polygon->pol[ vm->pindex[ i ]].v[ j ];
-               if ( vm->vindex[ i ] == pv->index ) {
-                  ++pv->nvmaps;
-                  break;
-               }
-            }
-         }
-      }
-      vm = vm->next;
-   }
-
-   /* allocate vmap references for each mapped vertex */
-
-   for ( i = 0; i < polygon->count; i++ ) {
-      for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) {
-         pv = &polygon->pol[ i ].v[ j ];
-         if ( pv->nvmaps ) {
-            pv->vm = _pico_calloc( pv->nvmaps, sizeof( lwVMapPt ));
-            if ( !pv->vm ) return 0;
-            pv->nvmaps = 0;
-         }
-      }
-   }
-
-   /* fill in vmap references for each mapped point */
-
-   vm = vmap;
-   while ( vm ) {
-      if ( vm->perpoly ) {
-         for ( i = 0; i < vm->nverts; i++ ) {
-            for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) {
-               pv = &polygon->pol[ vm->pindex[ i ]].v[ j ];
-               if ( vm->vindex[ i ] == pv->index ) {
-                  pv->vm[ pv->nvmaps ].vmap = vm;
-                  pv->vm[ pv->nvmaps ].index = i;
-                  ++pv->nvmaps;
-                  break;
-               }
-            }
-         }
-      }
-      vm = vm->next;
-   }
-
-   return 1;
-}
+/*
+======================================================================
+vmap.c
+
+Vertex map functions for an LWO2 reader.
+
+Ernie Wright  17 Sep 00
+====================================================================== */
+
+#include "../picointernal.h"
+#include "lwo2.h"
+
+
+/*
+======================================================================
+lwFreeVMap()
+
+Free memory used by an lwVMap.
+====================================================================== */
+
+void lwFreeVMap( lwVMap *vmap )
+{
+   if ( vmap ) {
+      if ( vmap->name ) _pico_free( vmap->name );
+      if ( vmap->vindex ) _pico_free( vmap->vindex );
+      if ( vmap->pindex ) _pico_free( vmap->pindex );
+      if ( vmap->val ) {
+         if ( vmap->val[ 0 ] ) _pico_free( vmap->val[ 0 ] );
+         _pico_free( vmap->val );
+      }
+      _pico_free( vmap );
+   }
+}
+
+
+/*
+======================================================================
+lwGetVMap()
+
+Read an lwVMap from a VMAP or VMAD chunk in an LWO2.
+====================================================================== */
+
+lwVMap *lwGetVMap( picoMemStream_t *fp, int cksize, int ptoffset, int poloffset,
+   int perpoly )
+{
+   unsigned char *buf, *bp;
+   lwVMap *vmap;
+   float *f;
+   int i, j, npts, rlen;
+
+
+   /* read the whole chunk */
+
+   set_flen( 0 );
+   buf = getbytes( fp, cksize );
+   if ( !buf ) return NULL;
+
+   vmap = _pico_calloc( 1, sizeof( lwVMap ));
+   if ( !vmap ) {
+      _pico_free( buf );
+      return NULL;
+   }
+
+   /* initialize the vmap */
+
+   vmap->perpoly = perpoly;
+
+   bp = buf;
+   set_flen( 0 );
+   vmap->type = sgetU4( &bp );
+   vmap->dim  = sgetU2( &bp );
+   vmap->name = sgetS0( &bp );
+   rlen = get_flen();
+
+   /* count the vmap records */
+
+   npts = 0;
+   while ( bp < buf + cksize ) {
+      i = sgetVX( &bp );
+      if ( perpoly )
+         i = sgetVX( &bp );
+      bp += vmap->dim * sizeof( float );
+      ++npts;
+   }
+
+   /* allocate the vmap */
+
+   vmap->nverts = npts;
+   vmap->vindex = _pico_calloc( npts, sizeof( int ));
+   if ( !vmap->vindex ) goto Fail;
+   if ( perpoly ) {
+      vmap->pindex = _pico_calloc( npts, sizeof( int ));
+      if ( !vmap->pindex ) goto Fail;
+   }
+
+   if ( vmap->dim > 0 ) {
+      vmap->val = _pico_calloc( npts, sizeof( float * ));
+      if ( !vmap->val ) goto Fail;
+      f = _pico_alloc( npts * vmap->dim * sizeof( float ));
+      if ( !f ) goto Fail;
+      for ( i = 0; i < npts; i++ )
+         vmap->val[ i ] = f + i * vmap->dim;
+   }
+
+   /* fill in the vmap values */
+
+   bp = buf + rlen;
+   for ( i = 0; i < npts; i++ ) {
+      vmap->vindex[ i ] = sgetVX( &bp );
+      if ( perpoly )
+         vmap->pindex[ i ] = sgetVX( &bp );
+      for ( j = 0; j < vmap->dim; j++ )
+         vmap->val[ i ][ j ] = sgetF4( &bp );
+   }
+
+   _pico_free( buf );
+   return vmap;
+
+Fail:
+   if ( buf ) _pico_free( buf );
+   lwFreeVMap( vmap );
+   return NULL;
+}
+
+
+/*
+======================================================================
+lwGetPointVMaps()
+
+Fill in the lwVMapPt structure for each point.
+====================================================================== */
+
+int lwGetPointVMaps( lwPointList *point, lwVMap *vmap )
+{
+   lwVMap *vm;
+   int i, j, n;
+
+   /* count the number of vmap values for each point */
+
+   vm = vmap;
+   while ( vm ) {
+      if ( !vm->perpoly )
+         for ( i = 0; i < vm->nverts; i++ )
+            ++point->pt[ vm->vindex[ i ]].nvmaps;
+      vm = vm->next;
+   }
+
+   /* allocate vmap references for each mapped point */
+
+   for ( i = 0; i < point->count; i++ ) {
+      if ( point->pt[ i ].nvmaps ) {
+         point->pt[ i ].vm = _pico_calloc( point->pt[ i ].nvmaps, sizeof( lwVMapPt ));
+         if ( !point->pt[ i ].vm ) return 0;
+         point->pt[ i ].nvmaps = 0;
+      }
+   }
+
+   /* fill in vmap references for each mapped point */
+
+   vm = vmap;
+   while ( vm ) {
+      if ( !vm->perpoly ) {
+         for ( i = 0; i < vm->nverts; i++ ) {
+            j = vm->vindex[ i ];
+            n = point->pt[ j ].nvmaps;
+            point->pt[ j ].vm[ n ].vmap = vm;
+            point->pt[ j ].vm[ n ].index = i;
+            ++point->pt[ j ].nvmaps;
+         }
+      }
+      vm = vm->next;
+   }
+
+   return 1;
+}
+
+
+/*
+======================================================================
+lwGetPolyVMaps()
+
+Fill in the lwVMapPt structure for each polygon vertex.
+====================================================================== */
+
+int lwGetPolyVMaps( lwPolygonList *polygon, lwVMap *vmap )
+{
+   lwVMap *vm;
+   lwPolVert *pv;
+   int i, j;
+
+   /* count the number of vmap values for each polygon vertex */
+
+   vm = vmap;
+   while ( vm ) {
+      if ( vm->perpoly ) {
+         for ( i = 0; i < vm->nverts; i++ ) {
+            for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) {
+               pv = &polygon->pol[ vm->pindex[ i ]].v[ j ];
+               if ( vm->vindex[ i ] == pv->index ) {
+                  ++pv->nvmaps;
+                  break;
+               }
+            }
+         }
+      }
+      vm = vm->next;
+   }
+
+   /* allocate vmap references for each mapped vertex */
+
+   for ( i = 0; i < polygon->count; i++ ) {
+      for ( j = 0; j < polygon->pol[ i ].nverts; j++ ) {
+         pv = &polygon->pol[ i ].v[ j ];
+         if ( pv->nvmaps ) {
+            pv->vm = _pico_calloc( pv->nvmaps, sizeof( lwVMapPt ));
+            if ( !pv->vm ) return 0;
+            pv->nvmaps = 0;
+         }
+      }
+   }
+
+   /* fill in vmap references for each mapped point */
+
+   vm = vmap;
+   while ( vm ) {
+      if ( vm->perpoly ) {
+         for ( i = 0; i < vm->nverts; i++ ) {
+            for ( j = 0; j < polygon->pol[ vm->pindex[ i ]].nverts; j++ ) {
+               pv = &polygon->pol[ vm->pindex[ i ]].v[ j ];
+               if ( vm->vindex[ i ] == pv->index ) {
+                  pv->vm[ pv->nvmaps ].vmap = vm;
+                  pv->vm[ pv->nvmaps ].index = i;
+                  ++pv->nvmaps;
+                  break;
+               }
+            }
+         }
+      }
+      vm = vm->next;
+   }
+
+   return 1;
+}
diff --git a/libs/picomodel/picointernal.c b/libs/picomodel/picointernal.c
index 6afae90a..3e32dd08 100644
--- a/libs/picomodel/picointernal.c
+++ b/libs/picomodel/picointernal.c
@@ -1,1353 +1,1353 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PICOINTERNAL_C
-
-
-
-/* todo:
- * - fix p->curLine for parser routines. increased twice
- */
-
-/* dependencies */
-#include <string.h>
-#include "picointernal.h"
-
-
-
-/* function pointers */
-void *(*_pico_ptr_malloc	)( size_t ) = malloc;
-void  (*_pico_ptr_free		)( void* ) = free;
-void  (*_pico_ptr_load_file	)( char*, unsigned char**, int* ) = NULL;
-void  (*_pico_ptr_free_file	)( void* ) = NULL;
-void  (*_pico_ptr_print		)( int, const char* ) = NULL;
-
-typedef union
-{
-	float	f;
-	char	c[4];
-}
-floatSwapUnion;
-
-/* _pico_alloc:
- *  kludged memory allocation wrapper
- */
-void *_pico_alloc( size_t size )
-{
-	void *ptr;
-
-	/* some sanity checks */
-	if( size == 0 )
-		return NULL;
-	if (_pico_ptr_malloc == NULL)
-		return NULL;
-
-	/* allocate memory */
-	ptr = _pico_ptr_malloc(size);
-	if (ptr == NULL)
-		return NULL;
-
-	/* zero out allocated memory */
-	memset(ptr,0,size);
-
-	/* return pointer to allocated memory */
-	return ptr;
-}
-
-/* _pico_calloc:
- *  _pico_calloc wrapper
- */
-void *_pico_calloc( size_t num, size_t size )
-{
-	void *ptr;
-
-	/* some sanity checks */
-	if( num == 0 || size == 0 )
-		return NULL;
-	if (_pico_ptr_malloc == NULL)
-		return NULL;
-
-	/* allocate memory */
-	ptr = _pico_ptr_malloc(num*size);
-	if (ptr == NULL)
-		return NULL;
-
-	/* zero out allocated memory */
-	memset(ptr,0,num*size);
-
-	/* return pointer to allocated memory */
-	return ptr;
-}
-
-/* _pico_realloc:
- *  memory reallocation wrapper (note: only grows,
- *  but never shrinks or frees)
- */
-void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize )
-{
-	void *ptr2;
-	
-	/* sanity checks */
-	if( ptr == NULL )
-		return NULL;
-	if( newSize < oldSize )
-		return *ptr;
-	if (_pico_ptr_malloc == NULL)
-		return NULL;
-
-	/* allocate new pointer */
-	ptr2 = _pico_alloc( newSize );
-	if( ptr2 == NULL )
-		return NULL;
-
-	/* copy */
-	if( *ptr != NULL )
-	{
-		memcpy( ptr2, *ptr, oldSize );
-		_pico_free( *ptr );
-	}
-	
-	/* fix up and return */
-	*ptr = ptr2;
-	return *ptr;
-}
-
-/* _pico_clone_alloc:
- *  handy function for quick string allocation/copy. it clones
- *  the given string and returns a pointer to the new allocated
- *  clone (which must be freed by caller of course) or returns
- *  NULL on memory alloc or param errors. if 'size' is -1 the
- *  length of the input string is used, otherwise 'size' is used
- *  as custom clone size (the string is cropped to fit into mem
- *  if needed). -sea
- */
-char *_pico_clone_alloc( char *str, int size )
-{
-	char  *cloned;
-	size_t cloneSize;
-
-	/* sanity check */
-	if (str == NULL) return NULL;
-
-	/* set real size of cloned string */
-	cloneSize = (size < 0) ? strlen(str) : size;
-
-	/* allocate memory */
-	cloned = _pico_alloc( cloneSize+1 ); /* bugfix! */
-	if (cloned == NULL)
-		return NULL;
-
-	/* zero out memory allocated by cloned string */
-	memset( cloned,0,cloneSize );
-
-	/* copy input string to cloned string */
-	if (cloneSize < strlen( str )) {
-		memcpy( cloned,str,cloneSize );
-		cloned[ cloneSize ] = '\0';
-	} else {
-		strcpy( cloned,str );
-	}
-	/* return ptr to cloned string */
-	return cloned;
-}
-
-/* _pico_free:
- * wrapper around the free function pointer
- */
-void _pico_free( void *ptr )
-{
-	/* sanity checks */
-	if( ptr == NULL )
-		return;
-	if (_pico_ptr_free == NULL)
-		return;
-
-	/* free the allocated memory */
-		_pico_ptr_free( ptr );
-}
-
-/* _pico_load_file:
- * wrapper around the loadfile function pointer
- */
-void _pico_load_file( char *name, unsigned char **buffer, int *bufSize )
-{
-	/* sanity checks */
-	if( name == NULL )
-	{
-		*bufSize = -1;
-		return;
-	}
-	if (_pico_ptr_load_file == NULL)
-	{
-		*bufSize = -1;
-		return;
-	}
-	/* do the actual call to read in the file; */
-	/* BUFFER IS ALLOCATED BY THE EXTERNAL LOADFILE FUNC */
-	_pico_ptr_load_file( name,buffer,bufSize );
-}
-
-/* _pico_free_file:
- * wrapper around the file free function pointer
- */
-void _pico_free_file( void *buffer )
-{
-	/* sanity checks */
-	if( buffer == NULL )
-		return;
-
-	/* use default free */
-	if( _pico_ptr_free_file == NULL )
-	{
-		free( buffer );
-		return;
-	}
-	/* free the allocated file */
-	_pico_ptr_free_file( buffer );
-}
-
-/* _pico_printf:
- * wrapper around the print function pointer -sea
- */
-void _pico_printf( int level, const char *format, ...)
-{
-	char	str[4096];
-	va_list	argptr;
-
-	/* sanity checks */
-	if( format == NULL )
-		return;
-	if (_pico_ptr_print == NULL)
-		return;
-
-	/* format string */
-	va_start( argptr,format );
-	vsprintf( str,format,argptr );
-	va_end( argptr );
-
-	/* remove linefeeds */
-	if (str[ strlen(str)-1 ] == '\n')
-		str[ strlen(str)-1 ] = '\0';
-
-	/* do the actual call */
-	_pico_ptr_print( level,str );
-}
-
-/* _pico_strltrim:
- *   left trims the given string -sea
- */
-char *_pico_strltrim( char *str )
-{
-	char *str1 = str, *str2 = str;
-
-	while (isspace(*str2)) str2++;
-	if( str2 != str )
-		while( *str2 != '\0' ) /* fix: ydnar */
-			*str1++ = *str2++;
-	return str;
-}
-
-/* _pico_strrtrim:
- *   right trims the given string -sea
- */
-char *_pico_strrtrim( char *str )
-{
-	if (str && *str)
-	{
-		char *str1 = str;
-		int allspace = 1;
-
-		while (*str1)
-		{
-			if (allspace && !isspace(*str1)) allspace = 0;
-			str1++;
-		}
-		if (allspace) *str = '\0';
-		else {
-			str1--;
-			while ((isspace(*str1)) && (str1 >= str))
-				*str1-- = '\0';
-		}
-	}
-    return str;
-}
-
-/* _pico_strlwr:
- *  pico internal string-to-lower routine.
- */
-char *_pico_strlwr( char *str )
-{
-	char *cp;
-	for (cp=str; *cp; ++cp)
-	{
-		if ('A' <= *cp && *cp <= 'Z')
-		{
-			*cp += ('a' - 'A');
-		}
-	}
-	return str;
-}
-
-/* _pico_strchcount:
- *  counts how often the given char appears in str. -sea
- */
-int _pico_strchcount( char *str, int ch )
-{
-	int count = 0;
-	while (*str++) if (*str == ch) count++;
-	return count;
-}
-
-void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs )
-{
-	int i;
-	for (i=0; i<3; i++)
-	{
-		mins[i] = +999999;
-		maxs[i] = -999999;
-	}
-}
-
-void _pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs )
-{
-	int i;
-	for (i=0; i<3; i++)
-	{
-		float value = p[i];
-		if (value < mins[i]) mins[i] = value;
-		if (value > maxs[i]) maxs[i] = value;
-	}
-}
-
-void _pico_zero_vec( picoVec3_t vec )
-{
-	vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = 0;
-}
-
-void _pico_zero_vec2( picoVec2_t vec )
-{
-	vec[ 0 ] = vec[ 1 ] = 0;
-}
-
-void _pico_zero_vec4( picoVec4_t vec )
-{
-	vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = vec[ 3 ] = 0;
-}
-
-void _pico_set_vec( picoVec3_t v, float a, float b, float c )
-{
-	v[ 0 ] = a;
-	v[ 1 ] = b;
-	v[ 2 ] = c;
-}
-
-void _pico_set_vec4( picoVec4_t v, float a, float b, float c, float d )
-{
-	v[ 0 ] = a;
-	v[ 1 ] = b;
-	v[ 2 ] = c;
-	v[ 3 ] = d;
-}
-
-void _pico_copy_vec( picoVec3_t src, picoVec3_t dest )
-{
-	dest[ 0 ] = src[ 0 ];
-	dest[ 1 ] = src[ 1 ];
-	dest[ 2 ] = src[ 2 ];
-}
-
-void _pico_copy_vec2( picoVec2_t src, picoVec2_t dest )
-{
-	dest[ 0 ] = src[ 0 ];
-	dest[ 1 ] = src[ 1 ];
-}
-
-void _pico_copy_vec4( picoVec4_t src, picoVec4_t dest )
-{
-	dest[ 0 ] = src[ 0 ];
-	dest[ 1 ] = src[ 1 ];
-	dest[ 2 ] = src[ 2 ];
-	dest[ 3 ] = src[ 3 ];
-}
-
-/* ydnar */
-picoVec_t _pico_normalize_vec( picoVec3_t vec )
-{
-	double	len, ilen;
-	
-	len = sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
-	if( len == 0.0 ) return 0.0;
-	ilen = 1.0 / len;
-	vec[ 0 ] *= (picoVec_t) ilen;
-	vec[ 1 ] *= (picoVec_t) ilen;
-	vec[ 2 ] *= (picoVec_t) ilen;
-	return (picoVec_t) len;
-}
-
-void _pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
-{
-	dest[ 0 ] = a[ 0 ] + b[ 0 ];
-	dest[ 1 ] = a[ 1 ] + b[ 1 ];
-	dest[ 2 ] = a[ 2 ] + b[ 2 ];
-}
-
-void _pico_subtract_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
-{
-	dest[ 0 ] = a[ 0 ] - b[ 0 ];
-	dest[ 1 ] = a[ 1 ] - b[ 1 ];
-	dest[ 2 ] = a[ 2 ] - b[ 2 ];
-}
-
-void _pico_scale_vec( picoVec3_t v, float scale, picoVec3_t dest )
-{
-	dest[ 0 ] = v[ 0 ] * scale;
-	dest[ 1 ] = v[ 1 ] * scale;
-	dest[ 2 ] = v[ 2 ] * scale;
-}
-
-void _pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest )
-{
-	dest[ 0 ] = v[ 0 ] * scale;
-	dest[ 1 ] = v[ 1 ] * scale;
-	dest[ 2 ] = v[ 2 ] * scale;
-	dest[ 3 ] = v[ 3 ] * scale;
-}
-
-picoVec_t _pico_dot_vec( picoVec3_t a, picoVec3_t b )
-{
-	return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
-}
-
-void _pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
-{
-	dest[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
-	dest[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
-	dest[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
-}
-
-picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c )
-{
-	picoVec3_t	ba, ca;
-
-	_pico_subtract_vec( b, a, ba );
-	_pico_subtract_vec( c, a, ca );
-	_pico_cross_vec( ca, ba, plane );
-	plane[ 3 ] = _pico_dot_vec( a, plane );
-	return _pico_normalize_vec( plane );
-}
-
-/* separate from _pico_set_vec4 */
-void _pico_set_color( picoColor_t c, int r, int g, int b, int a )
-{
-	c[ 0 ] = r;
-	c[ 1 ] = g;
-	c[ 2 ] = b;
-	c[ 3 ] = a;
-}
-
-void _pico_copy_color( picoColor_t src, picoColor_t dest )
-{
-	dest[ 0 ] = src[ 0 ];
-	dest[ 1 ] = src[ 1 ];
-	dest[ 2 ] = src[ 2 ];
-	dest[ 3 ] = src[ 3 ];
-}
-
-#ifdef __BIG_ENDIAN__
-
-int   _pico_big_long ( int   src ) { return src; }
-short _pico_big_short( short src ) { return src; }
-float _pico_big_float( float src ) { return src; }
-
-int _pico_little_long( int src )
-{
-	return ((src & 0xFF000000) >> 24) |
-		   ((src & 0x00FF0000) >> 8) |
-		   ((src & 0x0000FF00) << 8) |
-		   ((src & 0x000000FF) << 24);
-}
-
-short _pico_little_short( short src )
-{
-	return ((src & 0xFF00) >> 8) |
-		   ((src & 0x00FF) << 8);
-}
-
-float _pico_little_float( float src )
-{
-	floatSwapUnion in,out;
-	in.f = src;
-	out.c[ 0 ] = in.c[ 3 ];
-	out.c[ 1 ] = in.c[ 2 ];
-	out.c[ 2 ] = in.c[ 1 ];
-	out.c[ 3 ] = in.c[ 0 ];
-	return out.f;
-}
-#else /*__BIG_ENDIAN__*/
-
-int   _pico_little_long ( int   src ) { return src; }
-short _pico_little_short( short src ) { return src; }
-float _pico_little_float( float src ) { return src; }
-	
-int _pico_big_long( int src )
-{
-	return ((src & 0xFF000000) >> 24) |
-		   ((src & 0x00FF0000) >> 8) |
-		   ((src & 0x0000FF00) << 8) |
-		   ((src & 0x000000FF) << 24);
-}
-	
-short _pico_big_short( short src )
-{
-	return ((src & 0xFF00) >> 8) |
-		   ((src & 0x00FF) << 8);
-}
-	
-float _pico_big_float( float src )
-{
-	floatSwapUnion in,out;
-	in.f = src;
-	out.c[ 0 ] = in.c[ 3 ];
-	out.c[ 1 ] = in.c[ 2 ];
-	out.c[ 2 ] = in.c[ 1 ];
-	out.c[ 3 ] = in.c[ 0 ];
-	return out.f;
-}
-#endif /*__BIG_ENDIAN__*/
-
-/* _pico_stristr:
- *  case-insensitive strstr. -sea
- */
-char *_pico_stristr( char *str, const char *substr )
-{
-	const int sublen = strlen(substr);
-	while (*str)
-	{
-		if (!_pico_strnicmp(str,substr,sublen)) break;
-		str++;
-	}
-	if (!(*str)) str = NULL;
-	return str;
-}
-
-/*
-_pico_unixify()
-changes dos \ style path separators to /
-*/
-
-void _pico_unixify( char *path )
-{
-	if( path == NULL )
-		return;
-	while( *path )
-	{
-		if( *path == '\\' )
-			*path = '/';
-		path++;
-	}
-}
-
-/* _pico_nofname:
- *  removes file name portion from given file path and converts
- *  the directory separators to un*x style. returns 1 on success
- *  or 0 when 'destSize' was exceeded. -sea
- */
-int _pico_nofname( const char *path, char *dest, int destSize )
-{
-	int   left  = destSize;
-	char *temp  = dest;
-
-	while ((*dest = *path) != '\0')
-	{
-		if (*dest == '/' || *dest == '\\')
-		{
-			temp = (dest + 1);
-			*dest = '/';
-		}
-		dest++; path++;
-
-		if (--left < 1)
-		{
-			*temp = '\0';
-			return 0;
-		}
-	}
-	*temp = '\0';
-	return 1;
-}
-
-/* _pico_nopath:
- *  returns ptr to filename portion in given path or an empty
- *  string otherwise. given 'path' is not altered. -sea
- */
-char *_pico_nopath( const char *path )
-{
-	char *src;
-	src = (char *)path + (strlen(path) - 1);
-
-	if (path == NULL) return (char *)"";
-	if (!strchr((char *)path,'/') && !strchr((char *)path,'\\'))
-		return ((char *)path);
-
-	while ((src--) != path)
-	{
-		if (*src == '/' || *src == '\\')
-			return (++src);
-	}
-	return (char *)"";
-}
-
-/* _pico_setfext:
- *  sets/changes the file extension for the given filename
- *  or filepath's filename portion. the given 'path' *is*
- *  altered. leave 'ext' empty to remove extension. -sea
- */
-char *_pico_setfext( char *path, const char *ext )
-{
-	char *src;
-	int   remfext = 0;
-
-	src = path + (strlen(path) - 1);
-
-	if (ext == NULL) ext = "";
-	if (strlen(ext ) < 1) remfext = 1;
-	if (strlen(path) < 1)
-		return path;
-
-	while ((src--) != path)
-	{
-		if (*src == '/' || *src == '\\')
-			return path;
-
-		if (*src == '.')
-		{
-			if (remfext)
-			{
-				*src = '\0';
-				return path;
-			}
-			*(++src) = '\0';
-			break;
-		}
-	}
-	strcat(path,ext);
-	return path;
-}
-
-/* _pico_getline:
- *  extracts one line from the given buffer and stores it in dest.
- *  returns -1 on error or the length of the line on success. i've
- *  removed string trimming here. this can be done manually by the
- *  calling func.
- */
-int _pico_getline( char *buf, int bufsize, char *dest, int destsize )
-{
-	int pos;
-
-	/* check output */
-	if (dest == NULL || destsize < 1) return -1;
-	memset( dest,0,destsize );
-
-	/* check input */
-	if (buf == NULL || bufsize < 1)
-		return -1;
-
-	/* get next line */
-	for (pos=0; pos<bufsize && pos<destsize; pos++)
-	{
-		if (buf[pos] == '\n') { pos++; break; }
-		dest[pos] = buf[pos];
-	}
-	/* terminate dest and return */
-	dest[pos] = '\0';
-	return pos;
-}
-
-/* _pico_parse_skip_white:
- *  skips white spaces in current pico parser, sets *hasLFs
- *  to 1 if linefeeds were skipped, and either returns the
- *  parser's cursor pointer or NULL on error. -sea
- */
-void _pico_parse_skip_white( picoParser_t *p, int *hasLFs )
-{
-	/* sanity checks */
-	if (p == NULL || p->cursor == NULL)
-		return;
-
-	/* skin white spaces */
-	while( 1 )
-	{
-		/* sanity checks */
-		if (p->cursor <  p->buffer ||
-			p->cursor >= p->max)
-		{
-			return;
-		}
-		/* break for chars other than white spaces */
-		if (*p->cursor >  0x20) break;
-		if (*p->cursor == 0x00) return;
-
-		/* a bit of linefeed handling */
-		if (*p->cursor == '\n')
-		{
-			*hasLFs = 1;
-			p->curLine++;
-		}
-		/* go to next character */
-		p->cursor++;
-	}
-}
-
-/* _pico_new_parser:
- *  allocates a new ascii parser object.
- */
-picoParser_t *_pico_new_parser( picoByte_t *buffer, int bufSize )
-{
-	picoParser_t *p;
-	
-	/* sanity check */
-	if( buffer == NULL || bufSize <= 0 )
-		return NULL;
-	
-	/* allocate reader */
-	p = _pico_alloc( sizeof(picoParser_t) );
-	if (p == NULL) return NULL;
-	memset( p,0,sizeof(picoParser_t) );
-
-	/* allocate token space */
-	p->tokenSize = 0;
-	p->tokenMax = 1024;
-	p->token = _pico_alloc( p->tokenMax );
-	if( p->token == NULL )
-	{
-		_pico_free( p );
-		return NULL;
-	}
-	/* setup */
-	p->buffer 	= buffer;
-	p->cursor 	= buffer;
-	p->bufSize	= bufSize;
-	p->max    	= p->buffer + bufSize;
-	p->curLine = 1; /* sea: new */
-
-	/* return ptr to parser */
-	return p;
-}
-
-/* _pico_free_parser:
- *  frees an existing pico parser object.
- */
-void _pico_free_parser( picoParser_t *p )
-{
-	/* sanity check */
-	if (p == NULL) return;
-
-	/* free the parser */
-	if (p->token != NULL)
-	{
-		_pico_free( p->token );
-	}
-	_pico_free( p );
-}
-
-/* _pico_parse_ex:
- *  reads the next token from given pico parser object. if param
- * 'allowLFs' is 1 it will read beyond linefeeds and return 0 when
- *  the EOF is reached. if 'allowLFs' is 0 it will return 0 when
- *  the EOL is reached. if 'handleQuoted' is 1 the parser function
- *  will handle "quoted" strings and return the data between the
- *  quotes as token. returns 0 on end/error or 1 on success. -sea
- */
-int _pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted )
-{
-	int hasLFs = 0;
-	char *old;
-
-	/* sanity checks */
-	if( p == NULL || p->buffer == NULL ||
-		p->cursor <  p->buffer ||
-		p->cursor >= p->max )
-	{
-		return 0;
-	}
-	/* clear parser token */
-	p->tokenSize = 0;
-	p->token[ 0 ] = '\0';
-	old = p->cursor;
-
-	/* skip whitespaces */
-	while( p->cursor < p->max && *p->cursor <= 32 )
-	{
-		if (*p->cursor == '\n')
-		{
-			p->curLine++;
-			hasLFs++;
-		}
-		p->cursor++;
-	}
-	/* return if we're not allowed to go beyond lfs */
-	if ((hasLFs > 0) && !allowLFs)
-	{
-		p->cursor = old;
-		return 0;
-	}
-	/* get next quoted string */
-	if (*p->cursor == '\"' && handleQuoted)
-	{
-		p->cursor++;
-		while (p->cursor < p->max && *p->cursor)
-		{
-			if (*p->cursor == '\\')
-			{
-				if (*(p->cursor+1) == '"')
-				{
-					p->cursor++;
-				}
-				p->token[ p->tokenSize++ ] = *p->cursor++;
-				continue;
-			}
-			else if (*p->cursor == '\"')
-			{
-				p->cursor++;
-				break;
-			}
-			else if (*p->cursor == '\n')
-			{
-				p->curLine++;
-			}
-			p->token[ p->tokenSize++ ] = *p->cursor++;
-		}
-		/* terminate token */
-		p->token[ p->tokenSize ] = '\0';
-		return 1;
-	}
-	/* otherwise get next word */
-	while( p->cursor < p->max && *p->cursor > 32 )
-	{
-		if (*p->cursor == '\n')
-		{
-			p->curLine++;
-		}
-		p->token[ p->tokenSize++ ] = *p->cursor++;
-	}
-	/* terminate token */
-	p->token[ p->tokenSize ] = '\0';
-	return 1;
-}
-
-/* _pico_parse_first:
- *  reads the first token from the next line and returns
- *  a pointer to it. returns NULL on EOL or EOF. -sea
- */
-char *_pico_parse_first( picoParser_t *p )
-{
-	/* sanity check */
-	if (p == NULL) return NULL;
-
-	/* try to read next token (with lfs & quots) */
-	if (!_pico_parse_ex( p,1,1 ))
-		return NULL;
-
-	/* return ptr to the token string */
-	return p->token;
-}
-
-/* _pico_parse:
- *  reads the next token from the parser and returns a pointer
- *  to it. quoted strings are handled as usual. returns NULL
- *  on EOL or EOF. -sea
- */
-char *_pico_parse( picoParser_t *p, int allowLFs )
-{
-	/* sanity check */
-	if (p == NULL) return NULL;
-
-	/* try to read next token (with quots) */
-	if (!_pico_parse_ex( p,allowLFs,1 ))
-		return NULL;
-
-	/* return ptr to the token string */
-	return p->token;
-}
-
-/* _pico_parse_skip_rest:
- *  skips the rest of the current line in parser.
- */
-void _pico_parse_skip_rest( picoParser_t *p )
-{
-	while( _pico_parse_ex( p,0,0 ) ) ;
-}
-
-/* _pico_parse_skip_braced:
- *  parses/skips over a braced section. returns 1 on success
- *  or 0 on error (when there was no closing bracket and the
- *  end of buffer was reached or when the opening bracket was
- *  missing).
- */
-int _pico_parse_skip_braced( picoParser_t *p )
-{
-	int firstToken = 1;
-	int level;
-
-	/* sanity check */
-	if (p == NULL) return 0;
-
-	/* set the initial level for parsing */
-	level = 0;
-
-	/* skip braced section */
-	while( 1 )
-	{
-		/* read next token (lfs allowed) */
-		if (!_pico_parse_ex( p,1,1 ))
-		{
-			/* end of parser buffer reached */
-			return 0;
-		}
-		/* first token must be an opening bracket */
-		if (firstToken && p->token[0] != '{')
-		{
-			/* opening bracket missing */
-			return 0;
-		}
-		/* we only check this once */
-		firstToken = 0;
-
-		/* update level */
-		if (p->token[1] == '\0')
-		{
-			if (p->token[0] == '{') level++;
-			if (p->token[0] == '}') level--;
-		}
-		/* break if we're back at our starting level */
-		if (level == 0) break;
-	}
-	/* successfully skipped braced section */
-	return 1;
-}
-
-int _pico_parse_check( picoParser_t *p, int allowLFs, char *str )
-{
-	if (!_pico_parse_ex( p,allowLFs,1 ))
-		return 0;
-	if (!strcmp(p->token,str))
-		return 1;
-		return 0;
-}
-
-int _pico_parse_checki( picoParser_t *p, int allowLFs, char *str )
-{
-	if (!_pico_parse_ex( p,allowLFs,1 ))
-		return 0;
-	if (!_pico_stricmp(p->token,str))
-		return 1;
-		return 0;
-}
-
-int _pico_parse_int( picoParser_t *p, int *out )
-{
-	char *token;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* get token and turn it into an integer */
-	*out = 0;
-	token = _pico_parse( p,0 );
-	if (token == NULL) return 0;
-	*out = atoi( token );
-
-	/* success */
-	return 1;
-}
-
-int _pico_parse_int_def( picoParser_t *p, int *out, int def )
-{
-	char *token;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* get token and turn it into an integer */
-	*out = def;
-	token = _pico_parse( p,0 );
-	if (token == NULL) return 0;
-	*out = atoi( token );
-
-	/* success */
-	return 1;
-}
-
-int _pico_parse_float( picoParser_t *p, float *out )
-{
-	char *token;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* get token and turn it into a float */
-	*out = 0.0f;
-	token = _pico_parse( p,0 );
-	if (token == NULL) return 0;
-	*out = (float) atof( token );
-
-	/* success */
-	return 1;
-}
-
-int _pico_parse_float_def( picoParser_t *p, float *out, float def )
-{
-	char *token;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* get token and turn it into a float */
-	*out = def;
-	token = _pico_parse( p,0 );
-	if (token == NULL) return 0;
-	*out = (float) atof( token );
-
-	/* success */
-	return 1;
-}
-
-int _pico_parse_vec( picoParser_t *p, picoVec3_t out )
-{
-	char *token;
-	int	  i;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* zero out outination vector */
-	_pico_zero_vec( out );
-
-	/* parse three vector components */
-	for (i=0; i<3; i++)
-	{
-		token = _pico_parse( p,0 );
-		if (token == NULL)
-		{
-			_pico_zero_vec( out );
-			return 0;
-		}
-		out[ i ] = (float) atof( token );
-	}
-	/* success */
-	return 1;
-}
-
-int _pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def )
-{
-	char *token;
-	int	  i;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* assign default vector value */
-	_pico_copy_vec( def,out );
-
-	/* parse three vector components */
-	for (i=0; i<3; i++)
-	{
-		token = _pico_parse( p,0 );
-		if (token == NULL)
-		{
-			_pico_copy_vec( def,out );
-			return 0;
-		}
-		out[ i ] = (float) atof( token );
-	}
-	/* success */
-	return 1;
-}
-
-int _pico_parse_vec2( picoParser_t *p, picoVec2_t out )
-{
-	char *token;
-	int	  i;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* zero out outination vector */
-	_pico_zero_vec2( out );
-
-	/* parse two vector components */
-	for (i=0; i<2; i++)
-	{
-		token = _pico_parse( p,0 );
-		if (token == NULL)
-		{
-			_pico_zero_vec2( out );
-			return 0;
-		}
-		out[ i ] = (float) atof( token );
-	}
-	/* success */
-	return 1;
-}
-
-int _pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def )
-{
-	char *token;
-	int	  i;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* assign default vector value */
-	_pico_copy_vec2( def,out );
-
-	/* parse two vector components */
-	for (i=0; i<2; i++)
-	{
-		token = _pico_parse( p,0 );
-		if (token == NULL)
-		{
-			_pico_copy_vec2( def,out );
-			return 0;
-		}
-		out[ i ] = (float) atof( token );
-	}
-	/* success */
-	return 1;
-}
-
-int _pico_parse_vec4( picoParser_t *p, picoVec4_t out )
-{
-	char *token;
-	int	  i;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* zero out outination vector */
-	_pico_zero_vec4( out );
-
-	/* parse four vector components */
-	for (i=0; i<4; i++)
-	{
-		token = _pico_parse( p,0 );
-		if (token == NULL)
-		{
-			_pico_zero_vec4( out );
-			return 0;
-		}
-		out[ i ] = (float) atof( token );
-	}
-	/* success */
-	return 1;
-}
-
-int _pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def )
-{
-	char *token;
-	int	  i;
-
-	/* sanity checks */
-	if (p == NULL || out == NULL)
-		return 0;
-
-	/* assign default vector value */
-	_pico_copy_vec4( def,out );
-
-	/* parse four vector components */
-	for (i=0; i<4; i++)
-	{
-		token = _pico_parse( p,0 );
-		if (token == NULL)
-		{
-			_pico_copy_vec4( def,out );
-			return 0;
-		}
-		out[ i ] = (float) atof( token );
-	}
-	/* success */
-	return 1;
-}
-
-/* _pico_new_memstream:
- *  allocates a new memorystream object.
- */
-picoMemStream_t *_pico_new_memstream( picoByte_t *buffer, int bufSize )
-{
-	picoMemStream_t *s;
-	
-	/* sanity check */
-	if( buffer == NULL || bufSize <= 0 )
-		return NULL;
-	
-	/* allocate stream */
-	s = _pico_alloc( sizeof(picoMemStream_t) );
-	if (s == NULL) return NULL;
-	memset( s,0,sizeof(picoMemStream_t) );
-
-	/* setup */
-	s->buffer 	= buffer;
-	s->curPos 	= buffer;
-	s->bufSize	= bufSize;
-	s->flag		= 0;
-
-	/* return ptr to stream */
-	return s;
-}
-
-/* _pico_free_memstream:
- *  frees an existing pico memorystream object.
- */
-void _pico_free_memstream( picoMemStream_t *s )
-{
-	/* sanity check */
-	if (s == NULL) return;
-
-	/* free the stream */
-	_pico_free( s );
-}
-
-/* _pico_memstream_read:
- *  reads data from a pico memorystream into a buffer.
- */
-int _pico_memstream_read( picoMemStream_t *s, void *buffer, int len )
-{
-	int ret = 1;
-
-	/* sanity checks */
-	if (s == NULL || buffer == NULL)
-		return 0;
-
-	if (s->curPos + len > s->buffer + s->bufSize)
-	{
-		s->flag |= PICO_IOEOF;
-		len = s->buffer + s->bufSize - s->curPos;
-		ret = 0;
-	}
-
-	/* read the data */
-	memcpy( buffer, s->curPos, len );
-	s->curPos += len;
-	return ret;
-}
-
-/* _pico_memstream_read:
- *  reads a character from a pico memorystream
- */
-int _pico_memstream_getc( picoMemStream_t *s )
-{
-	int c = 0;
-
-	/* sanity check */
-	if (s == NULL)
-		return -1;
-
-	/* read the character */
-	if (_pico_memstream_read( s, &c, 1) == 0)
-		return -1;
-
-	return c;
-}
-
-/* _pico_memstream_seek:
- *  sets the current read position to a different location
- */
-int _pico_memstream_seek( picoMemStream_t *s, long offset, int origin )
-{
-	int overflow;
-
-	/* sanity check */
-	if (s == NULL)
-		return -1;
-
-	if (origin == PICO_SEEK_SET)
-	{
-		s->curPos = s->buffer + offset;
-		overflow = s->curPos - ( s->buffer + s->bufSize );
-		if (overflow > 0)
-		{
-			s->curPos = s->buffer + s->bufSize;
-			return offset - overflow;
-		}
-		return 0;
-	}
-	else if (origin == PICO_SEEK_CUR)
-	{
-		s->curPos += offset;
-		overflow = s->curPos - ( s->buffer + s->bufSize );
-		if (overflow > 0)
-		{
-			s->curPos = s->buffer + s->bufSize;
-			return offset - overflow;
-		}
-		return 0;
-	}
-	else if (origin == PICO_SEEK_END)
-	{
-		s->curPos = ( s->buffer + s->bufSize ) - offset;
-		overflow = s->buffer - s->curPos;
-		if (overflow > 0)
-		{
-			s->curPos = s->buffer;
-			return offset - overflow;
-		}
-		return 0;
-	}
-
-	return -1;
-}
-
-/* _pico_memstream_tell:
- *  returns the current read position in the pico memorystream
- */
-long _pico_memstream_tell( picoMemStream_t *s )
-{
-	/* sanity check */
-	if (s == NULL)
-		return -1;
-
-	return s->curPos - s->buffer;
-}
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PICOINTERNAL_C
+
+
+
+/* todo:
+ * - fix p->curLine for parser routines. increased twice
+ */
+
+/* dependencies */
+#include <string.h>
+#include "picointernal.h"
+
+
+
+/* function pointers */
+void *(*_pico_ptr_malloc	)( size_t ) = malloc;
+void  (*_pico_ptr_free		)( void* ) = free;
+void  (*_pico_ptr_load_file	)( char*, unsigned char**, int* ) = NULL;
+void  (*_pico_ptr_free_file	)( void* ) = NULL;
+void  (*_pico_ptr_print		)( int, const char* ) = NULL;
+
+typedef union
+{
+	float	f;
+	char	c[4];
+}
+floatSwapUnion;
+
+/* _pico_alloc:
+ *  kludged memory allocation wrapper
+ */
+void *_pico_alloc( size_t size )
+{
+	void *ptr;
+
+	/* some sanity checks */
+	if( size == 0 )
+		return NULL;
+	if (_pico_ptr_malloc == NULL)
+		return NULL;
+
+	/* allocate memory */
+	ptr = _pico_ptr_malloc(size);
+	if (ptr == NULL)
+		return NULL;
+
+	/* zero out allocated memory */
+	memset(ptr,0,size);
+
+	/* return pointer to allocated memory */
+	return ptr;
+}
+
+/* _pico_calloc:
+ *  _pico_calloc wrapper
+ */
+void *_pico_calloc( size_t num, size_t size )
+{
+	void *ptr;
+
+	/* some sanity checks */
+	if( num == 0 || size == 0 )
+		return NULL;
+	if (_pico_ptr_malloc == NULL)
+		return NULL;
+
+	/* allocate memory */
+	ptr = _pico_ptr_malloc(num*size);
+	if (ptr == NULL)
+		return NULL;
+
+	/* zero out allocated memory */
+	memset(ptr,0,num*size);
+
+	/* return pointer to allocated memory */
+	return ptr;
+}
+
+/* _pico_realloc:
+ *  memory reallocation wrapper (note: only grows,
+ *  but never shrinks or frees)
+ */
+void *_pico_realloc( void **ptr, size_t oldSize, size_t newSize )
+{
+	void *ptr2;
+	
+	/* sanity checks */
+	if( ptr == NULL )
+		return NULL;
+	if( newSize < oldSize )
+		return *ptr;
+	if (_pico_ptr_malloc == NULL)
+		return NULL;
+
+	/* allocate new pointer */
+	ptr2 = _pico_alloc( newSize );
+	if( ptr2 == NULL )
+		return NULL;
+
+	/* copy */
+	if( *ptr != NULL )
+	{
+		memcpy( ptr2, *ptr, oldSize );
+		_pico_free( *ptr );
+	}
+	
+	/* fix up and return */
+	*ptr = ptr2;
+	return *ptr;
+}
+
+/* _pico_clone_alloc:
+ *  handy function for quick string allocation/copy. it clones
+ *  the given string and returns a pointer to the new allocated
+ *  clone (which must be freed by caller of course) or returns
+ *  NULL on memory alloc or param errors. if 'size' is -1 the
+ *  length of the input string is used, otherwise 'size' is used
+ *  as custom clone size (the string is cropped to fit into mem
+ *  if needed). -sea
+ */
+char *_pico_clone_alloc( char *str, int size )
+{
+	char  *cloned;
+	size_t cloneSize;
+
+	/* sanity check */
+	if (str == NULL) return NULL;
+
+	/* set real size of cloned string */
+	cloneSize = (size < 0) ? strlen(str) : size;
+
+	/* allocate memory */
+	cloned = _pico_alloc( cloneSize+1 ); /* bugfix! */
+	if (cloned == NULL)
+		return NULL;
+
+	/* zero out memory allocated by cloned string */
+	memset( cloned,0,cloneSize );
+
+	/* copy input string to cloned string */
+	if (cloneSize < strlen( str )) {
+		memcpy( cloned,str,cloneSize );
+		cloned[ cloneSize ] = '\0';
+	} else {
+		strcpy( cloned,str );
+	}
+	/* return ptr to cloned string */
+	return cloned;
+}
+
+/* _pico_free:
+ * wrapper around the free function pointer
+ */
+void _pico_free( void *ptr )
+{
+	/* sanity checks */
+	if( ptr == NULL )
+		return;
+	if (_pico_ptr_free == NULL)
+		return;
+
+	/* free the allocated memory */
+		_pico_ptr_free( ptr );
+}
+
+/* _pico_load_file:
+ * wrapper around the loadfile function pointer
+ */
+void _pico_load_file( char *name, unsigned char **buffer, int *bufSize )
+{
+	/* sanity checks */
+	if( name == NULL )
+	{
+		*bufSize = -1;
+		return;
+	}
+	if (_pico_ptr_load_file == NULL)
+	{
+		*bufSize = -1;
+		return;
+	}
+	/* do the actual call to read in the file; */
+	/* BUFFER IS ALLOCATED BY THE EXTERNAL LOADFILE FUNC */
+	_pico_ptr_load_file( name,buffer,bufSize );
+}
+
+/* _pico_free_file:
+ * wrapper around the file free function pointer
+ */
+void _pico_free_file( void *buffer )
+{
+	/* sanity checks */
+	if( buffer == NULL )
+		return;
+
+	/* use default free */
+	if( _pico_ptr_free_file == NULL )
+	{
+		free( buffer );
+		return;
+	}
+	/* free the allocated file */
+	_pico_ptr_free_file( buffer );
+}
+
+/* _pico_printf:
+ * wrapper around the print function pointer -sea
+ */
+void _pico_printf( int level, const char *format, ...)
+{
+	char	str[4096];
+	va_list	argptr;
+
+	/* sanity checks */
+	if( format == NULL )
+		return;
+	if (_pico_ptr_print == NULL)
+		return;
+
+	/* format string */
+	va_start( argptr,format );
+	vsprintf( str,format,argptr );
+	va_end( argptr );
+
+	/* remove linefeeds */
+	if (str[ strlen(str)-1 ] == '\n')
+		str[ strlen(str)-1 ] = '\0';
+
+	/* do the actual call */
+	_pico_ptr_print( level,str );
+}
+
+/* _pico_strltrim:
+ *   left trims the given string -sea
+ */
+char *_pico_strltrim( char *str )
+{
+	char *str1 = str, *str2 = str;
+
+	while (isspace(*str2)) str2++;
+	if( str2 != str )
+		while( *str2 != '\0' ) /* fix: ydnar */
+			*str1++ = *str2++;
+	return str;
+}
+
+/* _pico_strrtrim:
+ *   right trims the given string -sea
+ */
+char *_pico_strrtrim( char *str )
+{
+	if (str && *str)
+	{
+		char *str1 = str;
+		int allspace = 1;
+
+		while (*str1)
+		{
+			if (allspace && !isspace(*str1)) allspace = 0;
+			str1++;
+		}
+		if (allspace) *str = '\0';
+		else {
+			str1--;
+			while ((isspace(*str1)) && (str1 >= str))
+				*str1-- = '\0';
+		}
+	}
+    return str;
+}
+
+/* _pico_strlwr:
+ *  pico internal string-to-lower routine.
+ */
+char *_pico_strlwr( char *str )
+{
+	char *cp;
+	for (cp=str; *cp; ++cp)
+	{
+		if ('A' <= *cp && *cp <= 'Z')
+		{
+			*cp += ('a' - 'A');
+		}
+	}
+	return str;
+}
+
+/* _pico_strchcount:
+ *  counts how often the given char appears in str. -sea
+ */
+int _pico_strchcount( char *str, int ch )
+{
+	int count = 0;
+	while (*str++) if (*str == ch) count++;
+	return count;
+}
+
+void _pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs )
+{
+	int i;
+	for (i=0; i<3; i++)
+	{
+		mins[i] = +999999;
+		maxs[i] = -999999;
+	}
+}
+
+void _pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs )
+{
+	int i;
+	for (i=0; i<3; i++)
+	{
+		float value = p[i];
+		if (value < mins[i]) mins[i] = value;
+		if (value > maxs[i]) maxs[i] = value;
+	}
+}
+
+void _pico_zero_vec( picoVec3_t vec )
+{
+	vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = 0;
+}
+
+void _pico_zero_vec2( picoVec2_t vec )
+{
+	vec[ 0 ] = vec[ 1 ] = 0;
+}
+
+void _pico_zero_vec4( picoVec4_t vec )
+{
+	vec[ 0 ] = vec[ 1 ] = vec[ 2 ] = vec[ 3 ] = 0;
+}
+
+void _pico_set_vec( picoVec3_t v, float a, float b, float c )
+{
+	v[ 0 ] = a;
+	v[ 1 ] = b;
+	v[ 2 ] = c;
+}
+
+void _pico_set_vec4( picoVec4_t v, float a, float b, float c, float d )
+{
+	v[ 0 ] = a;
+	v[ 1 ] = b;
+	v[ 2 ] = c;
+	v[ 3 ] = d;
+}
+
+void _pico_copy_vec( picoVec3_t src, picoVec3_t dest )
+{
+	dest[ 0 ] = src[ 0 ];
+	dest[ 1 ] = src[ 1 ];
+	dest[ 2 ] = src[ 2 ];
+}
+
+void _pico_copy_vec2( picoVec2_t src, picoVec2_t dest )
+{
+	dest[ 0 ] = src[ 0 ];
+	dest[ 1 ] = src[ 1 ];
+}
+
+void _pico_copy_vec4( picoVec4_t src, picoVec4_t dest )
+{
+	dest[ 0 ] = src[ 0 ];
+	dest[ 1 ] = src[ 1 ];
+	dest[ 2 ] = src[ 2 ];
+	dest[ 3 ] = src[ 3 ];
+}
+
+/* ydnar */
+picoVec_t _pico_normalize_vec( picoVec3_t vec )
+{
+	double	len, ilen;
+	
+	len = sqrt( vec[ 0 ] * vec[ 0 ] + vec[ 1 ] * vec[ 1 ] + vec[ 2 ] * vec[ 2 ] );
+	if( len == 0.0 ) return 0.0;
+	ilen = 1.0 / len;
+	vec[ 0 ] *= (picoVec_t) ilen;
+	vec[ 1 ] *= (picoVec_t) ilen;
+	vec[ 2 ] *= (picoVec_t) ilen;
+	return (picoVec_t) len;
+}
+
+void _pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
+{
+	dest[ 0 ] = a[ 0 ] + b[ 0 ];
+	dest[ 1 ] = a[ 1 ] + b[ 1 ];
+	dest[ 2 ] = a[ 2 ] + b[ 2 ];
+}
+
+void _pico_subtract_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
+{
+	dest[ 0 ] = a[ 0 ] - b[ 0 ];
+	dest[ 1 ] = a[ 1 ] - b[ 1 ];
+	dest[ 2 ] = a[ 2 ] - b[ 2 ];
+}
+
+void _pico_scale_vec( picoVec3_t v, float scale, picoVec3_t dest )
+{
+	dest[ 0 ] = v[ 0 ] * scale;
+	dest[ 1 ] = v[ 1 ] * scale;
+	dest[ 2 ] = v[ 2 ] * scale;
+}
+
+void _pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest )
+{
+	dest[ 0 ] = v[ 0 ] * scale;
+	dest[ 1 ] = v[ 1 ] * scale;
+	dest[ 2 ] = v[ 2 ] * scale;
+	dest[ 3 ] = v[ 3 ] * scale;
+}
+
+picoVec_t _pico_dot_vec( picoVec3_t a, picoVec3_t b )
+{
+	return a[ 0 ] * b[ 0 ] + a[ 1 ] * b[ 1 ] + a[ 2 ] * b[ 2 ];
+}
+
+void _pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest )
+{
+	dest[ 0 ] = a[ 1 ] * b[ 2 ] - a[ 2 ] * b[ 1 ];
+	dest[ 1 ] = a[ 2 ] * b[ 0 ] - a[ 0 ] * b[ 2 ];
+	dest[ 2 ] = a[ 0 ] * b[ 1 ] - a[ 1 ] * b[ 0 ];
+}
+
+picoVec_t _pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c )
+{
+	picoVec3_t	ba, ca;
+
+	_pico_subtract_vec( b, a, ba );
+	_pico_subtract_vec( c, a, ca );
+	_pico_cross_vec( ca, ba, plane );
+	plane[ 3 ] = _pico_dot_vec( a, plane );
+	return _pico_normalize_vec( plane );
+}
+
+/* separate from _pico_set_vec4 */
+void _pico_set_color( picoColor_t c, int r, int g, int b, int a )
+{
+	c[ 0 ] = r;
+	c[ 1 ] = g;
+	c[ 2 ] = b;
+	c[ 3 ] = a;
+}
+
+void _pico_copy_color( picoColor_t src, picoColor_t dest )
+{
+	dest[ 0 ] = src[ 0 ];
+	dest[ 1 ] = src[ 1 ];
+	dest[ 2 ] = src[ 2 ];
+	dest[ 3 ] = src[ 3 ];
+}
+
+#ifdef __BIG_ENDIAN__
+
+int   _pico_big_long ( int   src ) { return src; }
+short _pico_big_short( short src ) { return src; }
+float _pico_big_float( float src ) { return src; }
+
+int _pico_little_long( int src )
+{
+	return ((src & 0xFF000000) >> 24) |
+		   ((src & 0x00FF0000) >> 8) |
+		   ((src & 0x0000FF00) << 8) |
+		   ((src & 0x000000FF) << 24);
+}
+
+short _pico_little_short( short src )
+{
+	return ((src & 0xFF00) >> 8) |
+		   ((src & 0x00FF) << 8);
+}
+
+float _pico_little_float( float src )
+{
+	floatSwapUnion in,out;
+	in.f = src;
+	out.c[ 0 ] = in.c[ 3 ];
+	out.c[ 1 ] = in.c[ 2 ];
+	out.c[ 2 ] = in.c[ 1 ];
+	out.c[ 3 ] = in.c[ 0 ];
+	return out.f;
+}
+#else /*__BIG_ENDIAN__*/
+
+int   _pico_little_long ( int   src ) { return src; }
+short _pico_little_short( short src ) { return src; }
+float _pico_little_float( float src ) { return src; }
+	
+int _pico_big_long( int src )
+{
+	return ((src & 0xFF000000) >> 24) |
+		   ((src & 0x00FF0000) >> 8) |
+		   ((src & 0x0000FF00) << 8) |
+		   ((src & 0x000000FF) << 24);
+}
+	
+short _pico_big_short( short src )
+{
+	return ((src & 0xFF00) >> 8) |
+		   ((src & 0x00FF) << 8);
+}
+	
+float _pico_big_float( float src )
+{
+	floatSwapUnion in,out;
+	in.f = src;
+	out.c[ 0 ] = in.c[ 3 ];
+	out.c[ 1 ] = in.c[ 2 ];
+	out.c[ 2 ] = in.c[ 1 ];
+	out.c[ 3 ] = in.c[ 0 ];
+	return out.f;
+}
+#endif /*__BIG_ENDIAN__*/
+
+/* _pico_stristr:
+ *  case-insensitive strstr. -sea
+ */
+char *_pico_stristr( char *str, const char *substr )
+{
+	const int sublen = strlen(substr);
+	while (*str)
+	{
+		if (!_pico_strnicmp(str,substr,sublen)) break;
+		str++;
+	}
+	if (!(*str)) str = NULL;
+	return str;
+}
+
+/*
+_pico_unixify()
+changes dos \ style path separators to /
+*/
+
+void _pico_unixify( char *path )
+{
+	if( path == NULL )
+		return;
+	while( *path )
+	{
+		if( *path == '\\' )
+			*path = '/';
+		path++;
+	}
+}
+
+/* _pico_nofname:
+ *  removes file name portion from given file path and converts
+ *  the directory separators to un*x style. returns 1 on success
+ *  or 0 when 'destSize' was exceeded. -sea
+ */
+int _pico_nofname( const char *path, char *dest, int destSize )
+{
+	int   left  = destSize;
+	char *temp  = dest;
+
+	while ((*dest = *path) != '\0')
+	{
+		if (*dest == '/' || *dest == '\\')
+		{
+			temp = (dest + 1);
+			*dest = '/';
+		}
+		dest++; path++;
+
+		if (--left < 1)
+		{
+			*temp = '\0';
+			return 0;
+		}
+	}
+	*temp = '\0';
+	return 1;
+}
+
+/* _pico_nopath:
+ *  returns ptr to filename portion in given path or an empty
+ *  string otherwise. given 'path' is not altered. -sea
+ */
+char *_pico_nopath( const char *path )
+{
+	char *src;
+	src = (char *)path + (strlen(path) - 1);
+
+	if (path == NULL) return (char *)"";
+	if (!strchr((char *)path,'/') && !strchr((char *)path,'\\'))
+		return ((char *)path);
+
+	while ((src--) != path)
+	{
+		if (*src == '/' || *src == '\\')
+			return (++src);
+	}
+	return (char *)"";
+}
+
+/* _pico_setfext:
+ *  sets/changes the file extension for the given filename
+ *  or filepath's filename portion. the given 'path' *is*
+ *  altered. leave 'ext' empty to remove extension. -sea
+ */
+char *_pico_setfext( char *path, const char *ext )
+{
+	char *src;
+	int   remfext = 0;
+
+	src = path + (strlen(path) - 1);
+
+	if (ext == NULL) ext = "";
+	if (strlen(ext ) < 1) remfext = 1;
+	if (strlen(path) < 1)
+		return path;
+
+	while ((src--) != path)
+	{
+		if (*src == '/' || *src == '\\')
+			return path;
+
+		if (*src == '.')
+		{
+			if (remfext)
+			{
+				*src = '\0';
+				return path;
+			}
+			*(++src) = '\0';
+			break;
+		}
+	}
+	strcat(path,ext);
+	return path;
+}
+
+/* _pico_getline:
+ *  extracts one line from the given buffer and stores it in dest.
+ *  returns -1 on error or the length of the line on success. i've
+ *  removed string trimming here. this can be done manually by the
+ *  calling func.
+ */
+int _pico_getline( char *buf, int bufsize, char *dest, int destsize )
+{
+	int pos;
+
+	/* check output */
+	if (dest == NULL || destsize < 1) return -1;
+	memset( dest,0,destsize );
+
+	/* check input */
+	if (buf == NULL || bufsize < 1)
+		return -1;
+
+	/* get next line */
+	for (pos=0; pos<bufsize && pos<destsize; pos++)
+	{
+		if (buf[pos] == '\n') { pos++; break; }
+		dest[pos] = buf[pos];
+	}
+	/* terminate dest and return */
+	dest[pos] = '\0';
+	return pos;
+}
+
+/* _pico_parse_skip_white:
+ *  skips white spaces in current pico parser, sets *hasLFs
+ *  to 1 if linefeeds were skipped, and either returns the
+ *  parser's cursor pointer or NULL on error. -sea
+ */
+void _pico_parse_skip_white( picoParser_t *p, int *hasLFs )
+{
+	/* sanity checks */
+	if (p == NULL || p->cursor == NULL)
+		return;
+
+	/* skin white spaces */
+	while( 1 )
+	{
+		/* sanity checks */
+		if (p->cursor <  p->buffer ||
+			p->cursor >= p->max)
+		{
+			return;
+		}
+		/* break for chars other than white spaces */
+		if (*p->cursor >  0x20) break;
+		if (*p->cursor == 0x00) return;
+
+		/* a bit of linefeed handling */
+		if (*p->cursor == '\n')
+		{
+			*hasLFs = 1;
+			p->curLine++;
+		}
+		/* go to next character */
+		p->cursor++;
+	}
+}
+
+/* _pico_new_parser:
+ *  allocates a new ascii parser object.
+ */
+picoParser_t *_pico_new_parser( picoByte_t *buffer, int bufSize )
+{
+	picoParser_t *p;
+	
+	/* sanity check */
+	if( buffer == NULL || bufSize <= 0 )
+		return NULL;
+	
+	/* allocate reader */
+	p = _pico_alloc( sizeof(picoParser_t) );
+	if (p == NULL) return NULL;
+	memset( p,0,sizeof(picoParser_t) );
+
+	/* allocate token space */
+	p->tokenSize = 0;
+	p->tokenMax = 1024;
+	p->token = _pico_alloc( p->tokenMax );
+	if( p->token == NULL )
+	{
+		_pico_free( p );
+		return NULL;
+	}
+	/* setup */
+	p->buffer 	= buffer;
+	p->cursor 	= buffer;
+	p->bufSize	= bufSize;
+	p->max    	= p->buffer + bufSize;
+	p->curLine = 1; /* sea: new */
+
+	/* return ptr to parser */
+	return p;
+}
+
+/* _pico_free_parser:
+ *  frees an existing pico parser object.
+ */
+void _pico_free_parser( picoParser_t *p )
+{
+	/* sanity check */
+	if (p == NULL) return;
+
+	/* free the parser */
+	if (p->token != NULL)
+	{
+		_pico_free( p->token );
+	}
+	_pico_free( p );
+}
+
+/* _pico_parse_ex:
+ *  reads the next token from given pico parser object. if param
+ * 'allowLFs' is 1 it will read beyond linefeeds and return 0 when
+ *  the EOF is reached. if 'allowLFs' is 0 it will return 0 when
+ *  the EOL is reached. if 'handleQuoted' is 1 the parser function
+ *  will handle "quoted" strings and return the data between the
+ *  quotes as token. returns 0 on end/error or 1 on success. -sea
+ */
+int _pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted )
+{
+	int hasLFs = 0;
+	char *old;
+
+	/* sanity checks */
+	if( p == NULL || p->buffer == NULL ||
+		p->cursor <  p->buffer ||
+		p->cursor >= p->max )
+	{
+		return 0;
+	}
+	/* clear parser token */
+	p->tokenSize = 0;
+	p->token[ 0 ] = '\0';
+	old = p->cursor;
+
+	/* skip whitespaces */
+	while( p->cursor < p->max && *p->cursor <= 32 )
+	{
+		if (*p->cursor == '\n')
+		{
+			p->curLine++;
+			hasLFs++;
+		}
+		p->cursor++;
+	}
+	/* return if we're not allowed to go beyond lfs */
+	if ((hasLFs > 0) && !allowLFs)
+	{
+		p->cursor = old;
+		return 0;
+	}
+	/* get next quoted string */
+	if (*p->cursor == '\"' && handleQuoted)
+	{
+		p->cursor++;
+		while (p->cursor < p->max && *p->cursor)
+		{
+			if (*p->cursor == '\\')
+			{
+				if (*(p->cursor+1) == '"')
+				{
+					p->cursor++;
+				}
+				p->token[ p->tokenSize++ ] = *p->cursor++;
+				continue;
+			}
+			else if (*p->cursor == '\"')
+			{
+				p->cursor++;
+				break;
+			}
+			else if (*p->cursor == '\n')
+			{
+				p->curLine++;
+			}
+			p->token[ p->tokenSize++ ] = *p->cursor++;
+		}
+		/* terminate token */
+		p->token[ p->tokenSize ] = '\0';
+		return 1;
+	}
+	/* otherwise get next word */
+	while( p->cursor < p->max && *p->cursor > 32 )
+	{
+		if (*p->cursor == '\n')
+		{
+			p->curLine++;
+		}
+		p->token[ p->tokenSize++ ] = *p->cursor++;
+	}
+	/* terminate token */
+	p->token[ p->tokenSize ] = '\0';
+	return 1;
+}
+
+/* _pico_parse_first:
+ *  reads the first token from the next line and returns
+ *  a pointer to it. returns NULL on EOL or EOF. -sea
+ */
+char *_pico_parse_first( picoParser_t *p )
+{
+	/* sanity check */
+	if (p == NULL) return NULL;
+
+	/* try to read next token (with lfs & quots) */
+	if (!_pico_parse_ex( p,1,1 ))
+		return NULL;
+
+	/* return ptr to the token string */
+	return p->token;
+}
+
+/* _pico_parse:
+ *  reads the next token from the parser and returns a pointer
+ *  to it. quoted strings are handled as usual. returns NULL
+ *  on EOL or EOF. -sea
+ */
+char *_pico_parse( picoParser_t *p, int allowLFs )
+{
+	/* sanity check */
+	if (p == NULL) return NULL;
+
+	/* try to read next token (with quots) */
+	if (!_pico_parse_ex( p,allowLFs,1 ))
+		return NULL;
+
+	/* return ptr to the token string */
+	return p->token;
+}
+
+/* _pico_parse_skip_rest:
+ *  skips the rest of the current line in parser.
+ */
+void _pico_parse_skip_rest( picoParser_t *p )
+{
+	while( _pico_parse_ex( p,0,0 ) ) ;
+}
+
+/* _pico_parse_skip_braced:
+ *  parses/skips over a braced section. returns 1 on success
+ *  or 0 on error (when there was no closing bracket and the
+ *  end of buffer was reached or when the opening bracket was
+ *  missing).
+ */
+int _pico_parse_skip_braced( picoParser_t *p )
+{
+	int firstToken = 1;
+	int level;
+
+	/* sanity check */
+	if (p == NULL) return 0;
+
+	/* set the initial level for parsing */
+	level = 0;
+
+	/* skip braced section */
+	while( 1 )
+	{
+		/* read next token (lfs allowed) */
+		if (!_pico_parse_ex( p,1,1 ))
+		{
+			/* end of parser buffer reached */
+			return 0;
+		}
+		/* first token must be an opening bracket */
+		if (firstToken && p->token[0] != '{')
+		{
+			/* opening bracket missing */
+			return 0;
+		}
+		/* we only check this once */
+		firstToken = 0;
+
+		/* update level */
+		if (p->token[1] == '\0')
+		{
+			if (p->token[0] == '{') level++;
+			if (p->token[0] == '}') level--;
+		}
+		/* break if we're back at our starting level */
+		if (level == 0) break;
+	}
+	/* successfully skipped braced section */
+	return 1;
+}
+
+int _pico_parse_check( picoParser_t *p, int allowLFs, char *str )
+{
+	if (!_pico_parse_ex( p,allowLFs,1 ))
+		return 0;
+	if (!strcmp(p->token,str))
+		return 1;
+		return 0;
+}
+
+int _pico_parse_checki( picoParser_t *p, int allowLFs, char *str )
+{
+	if (!_pico_parse_ex( p,allowLFs,1 ))
+		return 0;
+	if (!_pico_stricmp(p->token,str))
+		return 1;
+		return 0;
+}
+
+int _pico_parse_int( picoParser_t *p, int *out )
+{
+	char *token;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* get token and turn it into an integer */
+	*out = 0;
+	token = _pico_parse( p,0 );
+	if (token == NULL) return 0;
+	*out = atoi( token );
+
+	/* success */
+	return 1;
+}
+
+int _pico_parse_int_def( picoParser_t *p, int *out, int def )
+{
+	char *token;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* get token and turn it into an integer */
+	*out = def;
+	token = _pico_parse( p,0 );
+	if (token == NULL) return 0;
+	*out = atoi( token );
+
+	/* success */
+	return 1;
+}
+
+int _pico_parse_float( picoParser_t *p, float *out )
+{
+	char *token;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* get token and turn it into a float */
+	*out = 0.0f;
+	token = _pico_parse( p,0 );
+	if (token == NULL) return 0;
+	*out = (float) atof( token );
+
+	/* success */
+	return 1;
+}
+
+int _pico_parse_float_def( picoParser_t *p, float *out, float def )
+{
+	char *token;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* get token and turn it into a float */
+	*out = def;
+	token = _pico_parse( p,0 );
+	if (token == NULL) return 0;
+	*out = (float) atof( token );
+
+	/* success */
+	return 1;
+}
+
+int _pico_parse_vec( picoParser_t *p, picoVec3_t out )
+{
+	char *token;
+	int	  i;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* zero out outination vector */
+	_pico_zero_vec( out );
+
+	/* parse three vector components */
+	for (i=0; i<3; i++)
+	{
+		token = _pico_parse( p,0 );
+		if (token == NULL)
+		{
+			_pico_zero_vec( out );
+			return 0;
+		}
+		out[ i ] = (float) atof( token );
+	}
+	/* success */
+	return 1;
+}
+
+int _pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def )
+{
+	char *token;
+	int	  i;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* assign default vector value */
+	_pico_copy_vec( def,out );
+
+	/* parse three vector components */
+	for (i=0; i<3; i++)
+	{
+		token = _pico_parse( p,0 );
+		if (token == NULL)
+		{
+			_pico_copy_vec( def,out );
+			return 0;
+		}
+		out[ i ] = (float) atof( token );
+	}
+	/* success */
+	return 1;
+}
+
+int _pico_parse_vec2( picoParser_t *p, picoVec2_t out )
+{
+	char *token;
+	int	  i;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* zero out outination vector */
+	_pico_zero_vec2( out );
+
+	/* parse two vector components */
+	for (i=0; i<2; i++)
+	{
+		token = _pico_parse( p,0 );
+		if (token == NULL)
+		{
+			_pico_zero_vec2( out );
+			return 0;
+		}
+		out[ i ] = (float) atof( token );
+	}
+	/* success */
+	return 1;
+}
+
+int _pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def )
+{
+	char *token;
+	int	  i;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* assign default vector value */
+	_pico_copy_vec2( def,out );
+
+	/* parse two vector components */
+	for (i=0; i<2; i++)
+	{
+		token = _pico_parse( p,0 );
+		if (token == NULL)
+		{
+			_pico_copy_vec2( def,out );
+			return 0;
+		}
+		out[ i ] = (float) atof( token );
+	}
+	/* success */
+	return 1;
+}
+
+int _pico_parse_vec4( picoParser_t *p, picoVec4_t out )
+{
+	char *token;
+	int	  i;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* zero out outination vector */
+	_pico_zero_vec4( out );
+
+	/* parse four vector components */
+	for (i=0; i<4; i++)
+	{
+		token = _pico_parse( p,0 );
+		if (token == NULL)
+		{
+			_pico_zero_vec4( out );
+			return 0;
+		}
+		out[ i ] = (float) atof( token );
+	}
+	/* success */
+	return 1;
+}
+
+int _pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def )
+{
+	char *token;
+	int	  i;
+
+	/* sanity checks */
+	if (p == NULL || out == NULL)
+		return 0;
+
+	/* assign default vector value */
+	_pico_copy_vec4( def,out );
+
+	/* parse four vector components */
+	for (i=0; i<4; i++)
+	{
+		token = _pico_parse( p,0 );
+		if (token == NULL)
+		{
+			_pico_copy_vec4( def,out );
+			return 0;
+		}
+		out[ i ] = (float) atof( token );
+	}
+	/* success */
+	return 1;
+}
+
+/* _pico_new_memstream:
+ *  allocates a new memorystream object.
+ */
+picoMemStream_t *_pico_new_memstream( picoByte_t *buffer, int bufSize )
+{
+	picoMemStream_t *s;
+	
+	/* sanity check */
+	if( buffer == NULL || bufSize <= 0 )
+		return NULL;
+	
+	/* allocate stream */
+	s = _pico_alloc( sizeof(picoMemStream_t) );
+	if (s == NULL) return NULL;
+	memset( s,0,sizeof(picoMemStream_t) );
+
+	/* setup */
+	s->buffer 	= buffer;
+	s->curPos 	= buffer;
+	s->bufSize	= bufSize;
+	s->flag		= 0;
+
+	/* return ptr to stream */
+	return s;
+}
+
+/* _pico_free_memstream:
+ *  frees an existing pico memorystream object.
+ */
+void _pico_free_memstream( picoMemStream_t *s )
+{
+	/* sanity check */
+	if (s == NULL) return;
+
+	/* free the stream */
+	_pico_free( s );
+}
+
+/* _pico_memstream_read:
+ *  reads data from a pico memorystream into a buffer.
+ */
+int _pico_memstream_read( picoMemStream_t *s, void *buffer, int len )
+{
+	int ret = 1;
+
+	/* sanity checks */
+	if (s == NULL || buffer == NULL)
+		return 0;
+
+	if (s->curPos + len > s->buffer + s->bufSize)
+	{
+		s->flag |= PICO_IOEOF;
+		len = s->buffer + s->bufSize - s->curPos;
+		ret = 0;
+	}
+
+	/* read the data */
+	memcpy( buffer, s->curPos, len );
+	s->curPos += len;
+	return ret;
+}
+
+/* _pico_memstream_read:
+ *  reads a character from a pico memorystream
+ */
+int _pico_memstream_getc( picoMemStream_t *s )
+{
+	int c = 0;
+
+	/* sanity check */
+	if (s == NULL)
+		return -1;
+
+	/* read the character */
+	if (_pico_memstream_read( s, &c, 1) == 0)
+		return -1;
+
+	return c;
+}
+
+/* _pico_memstream_seek:
+ *  sets the current read position to a different location
+ */
+int _pico_memstream_seek( picoMemStream_t *s, long offset, int origin )
+{
+	int overflow;
+
+	/* sanity check */
+	if (s == NULL)
+		return -1;
+
+	if (origin == PICO_SEEK_SET)
+	{
+		s->curPos = s->buffer + offset;
+		overflow = s->curPos - ( s->buffer + s->bufSize );
+		if (overflow > 0)
+		{
+			s->curPos = s->buffer + s->bufSize;
+			return offset - overflow;
+		}
+		return 0;
+	}
+	else if (origin == PICO_SEEK_CUR)
+	{
+		s->curPos += offset;
+		overflow = s->curPos - ( s->buffer + s->bufSize );
+		if (overflow > 0)
+		{
+			s->curPos = s->buffer + s->bufSize;
+			return offset - overflow;
+		}
+		return 0;
+	}
+	else if (origin == PICO_SEEK_END)
+	{
+		s->curPos = ( s->buffer + s->bufSize ) - offset;
+		overflow = s->buffer - s->curPos;
+		if (overflow > 0)
+		{
+			s->curPos = s->buffer;
+			return offset - overflow;
+		}
+		return 0;
+	}
+
+	return -1;
+}
+
+/* _pico_memstream_tell:
+ *  returns the current read position in the pico memorystream
+ */
+long _pico_memstream_tell( picoMemStream_t *s )
+{
+	/* sanity check */
+	if (s == NULL)
+		return -1;
+
+	return s->curPos - s->buffer;
+}
diff --git a/libs/picomodel/picointernal.h b/libs/picomodel/picointernal.h
index 37686ce1..8a3ee68d 100644
--- a/libs/picomodel/picointernal.h
+++ b/libs/picomodel/picointernal.h
@@ -1,205 +1,205 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#ifndef PICOINTERNAL_H
-#define PICOINTERNAL_H
-
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-
-/* dependencies */
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <string.h>
-#include <ctype.h>
-#include <math.h>
-
-#include "picomodel.h"
-
-
-/* os dependant replacements */
-#if WIN32 || _WIN32
-	#define _pico_stricmp stricmp
-	#define _pico_strnicmp strnicmp
-#else
-	#define _pico_stricmp strcasecmp
-	#define _pico_strnicmp strncasecmp
-#endif
-
-
-/* constants */
-#define	PICO_PI	3.14159265358979323846
-
-#define PICO_SEEK_SET    0
-#define PICO_SEEK_CUR    1
-#define PICO_SEEK_END    2
-
-#define PICO_IOEOF	1
-#define PICO_IOERR	2
-
-/* types */
-typedef struct picoParser_s
-{
-	char	*buffer;
-	int		 bufSize;
-	char	*token;
-	int		 tokenSize;
-	int		 tokenMax;
-	char	*cursor;
-	char	*max;
-	int		 curLine;
-}
-picoParser_t;
-
-typedef struct picoMemStream_s
-{
-	picoByte_t	*buffer;
-	int			bufSize;
-	picoByte_t	*curPos;
-	int			flag;
-}
-picoMemStream_t;
-
-
-/* variables */
-extern const picoModule_t	*picoModules[];
-
-extern void					*(*_pico_ptr_malloc)( size_t );
-extern void					(*_pico_ptr_free)( void* );
-extern void					(*_pico_ptr_load_file)( char*, unsigned char**, int* );
-extern void					(*_pico_ptr_free_file)( void* );
-extern void					(*_pico_ptr_print)( int, const char* );
-
-
-
-/* prototypes */
-
-/* memory */
-void			*_pico_alloc( size_t size );
-void			*_pico_calloc( size_t num, size_t size );
-void			*_pico_realloc( void **ptr, size_t oldSize, size_t newSize );
-char 			*_pico_clone_alloc( char *str, int size );
-void			_pico_free( void *ptr );
-
-/* files */
-void			_pico_load_file( char *name, unsigned char **buffer, int *bufSize );
-void			_pico_free_file( void *buffer );
-
-/* strings */
-char			*_pico_strltrim( char *str );
-char			*_pico_strrtrim( char *str );
-int				_pico_strchcount( char *str, int ch );
-void 			_pico_printf( int level, const char *format, ... );
-char			*_pico_stristr( char *str, const char *substr );
-void			_pico_unixify( char *path );
-int				_pico_nofname( const char *path, char *dest, int destSize );
-char			*_pico_nopath( const char *path );
-char			*_pico_setfext( char *path, const char *ext );
-int				_pico_getline( char *buf, int bufsize, char *dest, int destsize );
-char			*_pico_strlwr( char *str );
-
-/* vectors */
-void 			_pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs );
-void 			_pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs );
-void 			_pico_zero_vec( picoVec3_t vec );
-void 			_pico_zero_vec2( picoVec2_t vec );
-void 			_pico_zero_vec4( picoVec4_t vec );
-void 			_pico_set_vec( picoVec3_t v, float a, float b, float c );
-void 			_pico_set_vec4( picoVec4_t v, float a, float b, float c, float d );
-void			_pico_set_color( picoColor_t c, int r, int g, int b, int a );
-void 			_pico_copy_color( picoColor_t src, picoColor_t dest );
-void 			_pico_copy_vec( picoVec3_t src, picoVec3_t dest );
-void 			_pico_copy_vec2( picoVec2_t src, picoVec2_t dest );
-picoVec_t		_pico_normalize_vec( picoVec3_t vec );
-void			_pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest );
-void			_pico_subtract_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest );
-picoVec_t		_pico_dot_vec( picoVec3_t a, picoVec3_t b );
-void			_pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest );
-picoVec_t		_pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c );
-void 			_pico_scale_vec( picoVec3_t v, float scale, picoVec3_t dest );
-void 			_pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest );
-
-/* endian */
-int 			_pico_big_long( int src );
-short 			_pico_big_short( short src );
-float			_pico_big_float( float src );
-
-int 			_pico_little_long( int src );
-short 			_pico_little_short( short src );
-float 			_pico_little_float( float src );
-
-/* pico ascii parser */
-picoParser_t 	*_pico_new_parser( picoByte_t *buffer, int bufSize );
-void 			_pico_free_parser( picoParser_t *p );
-int				_pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted );
-char 			*_pico_parse_first( picoParser_t *p );
-char 			*_pico_parse( picoParser_t *p, int allowLFs );
-void 			_pico_parse_skip_rest( picoParser_t *p );
-int				_pico_parse_skip_braced( picoParser_t *p );
-int 			_pico_parse_check( picoParser_t *p, int allowLFs, char *str );
-int 			_pico_parse_checki( picoParser_t *p, int allowLFs, char *str );
-int 			_pico_parse_int( picoParser_t *p, int *out );
-int 			_pico_parse_int_def( picoParser_t *p, int *out, int def );
-int 			_pico_parse_float( picoParser_t *p, float *out );
-int 			_pico_parse_float_def( picoParser_t *p, float *out, float def );
-int 			_pico_parse_vec( picoParser_t *p, picoVec3_t out);
-int 			_pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def);
-int 			_pico_parse_vec2( picoParser_t *p, picoVec2_t out );
-int 			_pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def );
-int 			_pico_parse_vec4( picoParser_t *p, picoVec4_t out);
-int 			_pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def);
-
-/* pico memory stream */
-picoMemStream_t	*_pico_new_memstream( picoByte_t *buffer, int bufSize );
-void 			_pico_free_memstream( picoMemStream_t *s );
-int				_pico_memstream_read( picoMemStream_t *s, void *buffer, int len );
-int				_pico_memstream_getc( picoMemStream_t *s );
-int				_pico_memstream_seek( picoMemStream_t *s, long offset, int origin );
-long			_pico_memstream_tell( picoMemStream_t *s );
-#define			_pico_memstream_eof( _pico_memstream )		((_pico_memstream)->flag & PICO_IOEOF)
-#define			_pico_memstream_error( _pico_memstream )	((_pico_memstream)->flag & PICO_IOERR)
-
-/* end marker */
-#ifdef __cplusplus
-}
-#endif
-
-#endif
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef PICOINTERNAL_H
+#define PICOINTERNAL_H
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+
+/* dependencies */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+#include "picomodel.h"
+
+
+/* os dependant replacements */
+#if WIN32 || _WIN32
+	#define _pico_stricmp stricmp
+	#define _pico_strnicmp strnicmp
+#else
+	#define _pico_stricmp strcasecmp
+	#define _pico_strnicmp strncasecmp
+#endif
+
+
+/* constants */
+#define	PICO_PI	3.14159265358979323846
+
+#define PICO_SEEK_SET    0
+#define PICO_SEEK_CUR    1
+#define PICO_SEEK_END    2
+
+#define PICO_IOEOF	1
+#define PICO_IOERR	2
+
+/* types */
+typedef struct picoParser_s
+{
+	char	*buffer;
+	int		 bufSize;
+	char	*token;
+	int		 tokenSize;
+	int		 tokenMax;
+	char	*cursor;
+	char	*max;
+	int		 curLine;
+}
+picoParser_t;
+
+typedef struct picoMemStream_s
+{
+	picoByte_t	*buffer;
+	int			bufSize;
+	picoByte_t	*curPos;
+	int			flag;
+}
+picoMemStream_t;
+
+
+/* variables */
+extern const picoModule_t	*picoModules[];
+
+extern void					*(*_pico_ptr_malloc)( size_t );
+extern void					(*_pico_ptr_free)( void* );
+extern void					(*_pico_ptr_load_file)( char*, unsigned char**, int* );
+extern void					(*_pico_ptr_free_file)( void* );
+extern void					(*_pico_ptr_print)( int, const char* );
+
+
+
+/* prototypes */
+
+/* memory */
+void			*_pico_alloc( size_t size );
+void			*_pico_calloc( size_t num, size_t size );
+void			*_pico_realloc( void **ptr, size_t oldSize, size_t newSize );
+char 			*_pico_clone_alloc( char *str, int size );
+void			_pico_free( void *ptr );
+
+/* files */
+void			_pico_load_file( char *name, unsigned char **buffer, int *bufSize );
+void			_pico_free_file( void *buffer );
+
+/* strings */
+char			*_pico_strltrim( char *str );
+char			*_pico_strrtrim( char *str );
+int				_pico_strchcount( char *str, int ch );
+void 			_pico_printf( int level, const char *format, ... );
+char			*_pico_stristr( char *str, const char *substr );
+void			_pico_unixify( char *path );
+int				_pico_nofname( const char *path, char *dest, int destSize );
+char			*_pico_nopath( const char *path );
+char			*_pico_setfext( char *path, const char *ext );
+int				_pico_getline( char *buf, int bufsize, char *dest, int destsize );
+char			*_pico_strlwr( char *str );
+
+/* vectors */
+void 			_pico_zero_bounds( picoVec3_t mins, picoVec3_t maxs );
+void 			_pico_expand_bounds( picoVec3_t p, picoVec3_t mins, picoVec3_t maxs );
+void 			_pico_zero_vec( picoVec3_t vec );
+void 			_pico_zero_vec2( picoVec2_t vec );
+void 			_pico_zero_vec4( picoVec4_t vec );
+void 			_pico_set_vec( picoVec3_t v, float a, float b, float c );
+void 			_pico_set_vec4( picoVec4_t v, float a, float b, float c, float d );
+void			_pico_set_color( picoColor_t c, int r, int g, int b, int a );
+void 			_pico_copy_color( picoColor_t src, picoColor_t dest );
+void 			_pico_copy_vec( picoVec3_t src, picoVec3_t dest );
+void 			_pico_copy_vec2( picoVec2_t src, picoVec2_t dest );
+picoVec_t		_pico_normalize_vec( picoVec3_t vec );
+void			_pico_add_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest );
+void			_pico_subtract_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest );
+picoVec_t		_pico_dot_vec( picoVec3_t a, picoVec3_t b );
+void			_pico_cross_vec( picoVec3_t a, picoVec3_t b, picoVec3_t dest );
+picoVec_t		_pico_calc_plane( picoVec4_t plane, picoVec3_t a, picoVec3_t b, picoVec3_t c );
+void 			_pico_scale_vec( picoVec3_t v, float scale, picoVec3_t dest );
+void 			_pico_scale_vec4( picoVec4_t v, float scale, picoVec4_t dest );
+
+/* endian */
+int 			_pico_big_long( int src );
+short 			_pico_big_short( short src );
+float			_pico_big_float( float src );
+
+int 			_pico_little_long( int src );
+short 			_pico_little_short( short src );
+float 			_pico_little_float( float src );
+
+/* pico ascii parser */
+picoParser_t 	*_pico_new_parser( picoByte_t *buffer, int bufSize );
+void 			_pico_free_parser( picoParser_t *p );
+int				_pico_parse_ex( picoParser_t *p, int allowLFs, int handleQuoted );
+char 			*_pico_parse_first( picoParser_t *p );
+char 			*_pico_parse( picoParser_t *p, int allowLFs );
+void 			_pico_parse_skip_rest( picoParser_t *p );
+int				_pico_parse_skip_braced( picoParser_t *p );
+int 			_pico_parse_check( picoParser_t *p, int allowLFs, char *str );
+int 			_pico_parse_checki( picoParser_t *p, int allowLFs, char *str );
+int 			_pico_parse_int( picoParser_t *p, int *out );
+int 			_pico_parse_int_def( picoParser_t *p, int *out, int def );
+int 			_pico_parse_float( picoParser_t *p, float *out );
+int 			_pico_parse_float_def( picoParser_t *p, float *out, float def );
+int 			_pico_parse_vec( picoParser_t *p, picoVec3_t out);
+int 			_pico_parse_vec_def( picoParser_t *p, picoVec3_t out, picoVec3_t def);
+int 			_pico_parse_vec2( picoParser_t *p, picoVec2_t out );
+int 			_pico_parse_vec2_def( picoParser_t *p, picoVec2_t out, picoVec2_t def );
+int 			_pico_parse_vec4( picoParser_t *p, picoVec4_t out);
+int 			_pico_parse_vec4_def( picoParser_t *p, picoVec4_t out, picoVec4_t def);
+
+/* pico memory stream */
+picoMemStream_t	*_pico_new_memstream( picoByte_t *buffer, int bufSize );
+void 			_pico_free_memstream( picoMemStream_t *s );
+int				_pico_memstream_read( picoMemStream_t *s, void *buffer, int len );
+int				_pico_memstream_getc( picoMemStream_t *s );
+int				_pico_memstream_seek( picoMemStream_t *s, long offset, int origin );
+long			_pico_memstream_tell( picoMemStream_t *s );
+#define			_pico_memstream_eof( _pico_memstream )		((_pico_memstream)->flag & PICO_IOEOF)
+#define			_pico_memstream_error( _pico_memstream )	((_pico_memstream)->flag & PICO_IOERR)
+
+/* end marker */
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/libs/picomodel/picomodel.c b/libs/picomodel/picomodel.c
index ed4f8b21..d7790c37 100644
--- a/libs/picomodel/picomodel.c
+++ b/libs/picomodel/picomodel.c
@@ -1,1995 +1,1995 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PICOMODEL_C
-
-
-
-/* dependencies */
-#include "picointernal.h"
-
-
-
-/*
-PicoInit()
-initializes the picomodel library
-*/
-
-int PicoInit( void )
-{
-	/* successfully initialized -sea */
-	return 1;
-}
-
-
-
-/*
-PicoShutdown()
-shuts the pico model library down
-*/
-
-void PicoShutdown( void )
-{
-	/* do something interesting here in the future */
-	return;
-}
-
-
-
-/*
-PicoError()
-returns last picomodel error code (see PME_* defines)
-*/
-
-int PicoError( void )
-{
-	/* todo: do something here */
-	return 0;
-}
-
-
-
-/*
-PicoSetMallocFunc()
-sets the ptr to the malloc function
-*/
-
-void PicoSetMallocFunc( void *(*func)( size_t ) )
-{
-	if( func != NULL )
-		_pico_ptr_malloc = func;
-}
-
-
-
-/*
-PicoSetFreeFunc()
-sets the ptr to the free function
-*/
-
-void PicoSetFreeFunc( void (*func)( void* ) )
-{
-	if( func != NULL )
-		_pico_ptr_free = func;
-}
-
-
-
-/*
-PicoSetLoadFileFunc()
-sets the ptr to the file load function
-*/
-
-void PicoSetLoadFileFunc( void (*func)( char*, unsigned char**, int* ) )
-{
-	if( func != NULL )
-		_pico_ptr_load_file = func;
-}
-
-
-
-/*
-PicoSetFreeFileFunc()
-sets the ptr to the free function
-*/
-
-void PicoSetFreeFileFunc( void (*func)( void* ) )
-{
-	if( func != NULL )
-		_pico_ptr_free_file = func;
-}
-
-
-
-/*
-PicoSetPrintFunc()
-sets the ptr to the print function
-*/
-
-void PicoSetPrintFunc( void (*func)( int, const char* ) )
-{
-	if( func != NULL )
-		_pico_ptr_print = func;
-}
-
-
-
-/*
-PicoLoadModel()
-the meat and potatoes function
-*/
-
-picoModel_t	*PicoLoadModel( char *fileName, int frameNum )
-{
-	const picoModule_t	**modules, *pm;
-	picoModel_t			*model;
-	picoByte_t			*buffer;
-	int					bufSize;
-	char				*modelFileName, *remapFileName;
-
-	
-	/* init */
-	model = NULL;
-	
-	/* make sure we've got a file name */
-	if( fileName == NULL )
-	{
-		_pico_printf( PICO_ERROR, "PicoLoadModel: No filename given (fileName == NULL)" );
-		return NULL;
-	}
-	
-	/* load file data (buffer is allocated by host app) */
-	_pico_load_file( fileName, &buffer, &bufSize );
-	if( bufSize < 0 )
-	{
-		_pico_printf( PICO_ERROR, "PicoLoadModel: Failed loading model %s", fileName );
-		return NULL;
-	}
-
-	/* get ptr to list of supported modules */
-	modules = PicoModuleList( NULL );
-	
-	/* run it through the various loader functions and try */
-	/* to find a loader that fits the given file data */
-	for( ; *modules != NULL; modules++ )
-	{
-		/* get module */
-		pm = *modules;
-		
-		/* sanity check */
-		if( pm == NULL)
-			break;
-
-		/* module must be able to load */
-		if( pm->canload == NULL || pm->load == NULL )
-			continue;
-		
-		/* see whether this module can load the model file or not */
-		if( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK )
-		{
-			/* use loader provided by module to read the model data */
-			model = pm->load( fileName, frameNum, buffer, bufSize );
-			if( model == NULL )
-			{
-				_pico_free_file( buffer );
-				return NULL;
-			}
-			
-			/* assign pointer to file format module */
-			model->module = pm;
-			
-			/* get model file name */
-			modelFileName = PicoGetModelFileName( model );
-			
-			/* apply model remappings from <model>.remap */
-			if( strlen( modelFileName ) )
-			{
-				/* alloc copy of model file name */
-				remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
-				if( remapFileName != NULL )
-				{
-					/* copy model file name and change extension */
-					strcpy( remapFileName, modelFileName );
-					_pico_setfext( remapFileName, "remap" );
-
-					/* try to remap model; we don't handle the result */
-					PicoRemapModel( model, remapFileName );
-
-					/* free the remap file name string */
-					_pico_free( remapFileName );
-				}
-			}
-			
-			/* model was loaded, so break out of loop */
-			break;
-		}
-	}
-	
-	/* free memory used by file buffer */
-	if( buffer)
-		_pico_free_file( buffer );
-
-	/* return */
-	return model;
-}
-
-
-
-/* ----------------------------------------------------------------------------
-models
----------------------------------------------------------------------------- */
-
-/*
-PicoNewModel()
-creates a new pico model
-*/
-
-picoModel_t *PicoNewModel( void )
-{
-	picoModel_t	*model;
-	
-	/* allocate */
-	model = _pico_alloc( sizeof(picoModel_t) );
-	if( model == NULL )
-		return NULL;
-
-	/* clear */
-	memset( model,0,sizeof(picoModel_t) );
-	
-	/* model set up */
-	_pico_zero_bounds( model->mins,model->maxs );
-
-	/* set initial frame count to 1 -sea */
-	model->numFrames = 1;
-
-	/* return ptr to new model */
-	return model;
-}
-
-
-
-/*
-PicoFreeModel()
-frees a model and all associated data
-*/
-
-void PicoFreeModel( picoModel_t *model )
-{
-	int				i;
-	
-
-	/* sanity check */
-	if( model == NULL )
-		return;
-	
-	/* free bits */
-	if( model->name )
-		_pico_free( model->name );
-	
-	/* free shaders */
-	for( i = 0; i < model->numShaders; i++ )
-		PicoFreeShader( model->shader[ i ] );
-	free( model->shader );
-	
-	/* free surfaces */
-	for( i = 0; i < model->numSurfaces; i++ )
-		PicoFreeSurface( model->surface[ i ] );
-	free( model->surface );
-	
-	/* free the model */
-	_pico_free( model );
-}
-
-
-
-/*
-PicoAdjustModel()
-adjusts a models's memory allocations to handle the requested sizes.
-will always grow, never shrink
-*/
-
-int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
-{
-	/* dummy check */
-	if( model == NULL )
-		return 0;
-	
-	/* bare minimums */
-	/* sea: null surface/shader fix (1s=>0s) */
-	if( numShaders < 0 )
-		numShaders = 0;
-	if( numSurfaces < 0 )
-		numSurfaces = 0;
-
-	/* additional shaders? */
-	while( numShaders > model->maxShaders )
-	{
-		model->maxShaders += PICO_GROW_SHADERS;
-		if( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) )
-			return 0;
-	}
-	
-	/* set shader count to higher */
-	if( numShaders > model->numShaders )
-		model->numShaders = numShaders;
-	
-	/* additional surfaces? */
-	while( numSurfaces > model->maxSurfaces )
-	{
-		model->maxSurfaces += PICO_GROW_SURFACES;
-		if( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) )
-			return 0;
-	}
-	
-	/* set shader count to higher */
-	if( numSurfaces > model->numSurfaces )
-		model->numSurfaces = numSurfaces;
-	
-	/* return ok */
-	return 1;
-}
-
-
-
-/* ----------------------------------------------------------------------------
-shaders
----------------------------------------------------------------------------- */
-
-/*
-PicoNewShader()
-creates a new pico shader and returns its index. -sea
-*/
-
-picoShader_t *PicoNewShader( picoModel_t *model )
-{
-	picoShader_t	*shader;
-	
-
-	/* allocate and clear */
-	shader = _pico_alloc( sizeof(picoShader_t) );
-	if( shader == NULL )
-		return NULL;
-	memset( shader, 0, sizeof(picoShader_t) );
-	
-	/* attach it to the model */
-	if( model != NULL )
-	{
-		/* adjust model */
-		if( !PicoAdjustModel( model, model->numShaders + 1, 0 ) )
-		{
-			_pico_free( shader );
-			return NULL;
-		}
-		/* attach */
-		model->shader[ model->numShaders - 1 ] = shader;
-		shader->model = model;
-	}
-	/* setup default shader colors */
-	_pico_set_color( shader->ambientColor,0,0,0,0 );
-	_pico_set_color( shader->diffuseColor,255,255,255,1 );
-	_pico_set_color( shader->specularColor,0,0,0,0 );
-
-	/* no need to do this, but i do it anyway */
-	shader->transparency = 0;
-	shader->shininess = 0;
-
-	/* return the newly created shader */
-	return shader;
-}
-
-
-
-/*
-PicoFreeShader()
-frees a shader and all associated data -sea
-*/
-
-void PicoFreeShader( picoShader_t *shader )
-{
-	/* dummy check */
-	if( shader == NULL )
-		return;
-	
-	/* free bits */
-	if( shader->name )
-		_pico_free( shader->name );
-	if( shader->mapName )
-		_pico_free( shader->mapName );
-	
-	/* free the shader */
-	_pico_free( shader );
-}
-
-
-
-/*
-PicoFindShader()
-finds a named shader in a model
-*/
-
-picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive )
-{
-	int		i;
-	
-	
-	/* sanity checks */
-	if( model == NULL || name == NULL )	/* sea: null name fix */
-		return NULL;
-	
-	/* walk list */
-	for( i = 0; i < model->numShaders; i++ )
-	{
-		/* skip null shaders or shaders with null names */
-		if( model->shader[ i ] == NULL ||
-			model->shader[ i ]->name == NULL )
-			continue;
-
-		/* compare the shader name with name we're looking for */
-		if( caseSensitive )
-		{
-			if( !strcmp( name, model->shader[ i ]->name ) )
-				return model->shader[ i ];
-		}
-		else if( !_pico_stricmp( name, model->shader[ i ]->name ) )
-				return model->shader[ i ];
-	}
-	
-	/* named shader not found */
-	return NULL;
-}
-
-
-
-/* ----------------------------------------------------------------------------
-surfaces
----------------------------------------------------------------------------- */
-
-/*
-PicoNewSurface()
-creates a new pico surface
-*/
-
-picoSurface_t *PicoNewSurface( picoModel_t *model )
-{
-	picoSurface_t	*surface;
-	char surfaceName[64];
-	
-	/* allocate and clear */
-	surface = _pico_alloc( sizeof( *surface ) );
-	if( surface == NULL )
-		return NULL;
-	memset( surface, 0, sizeof( *surface ) );
-	
-	/* attach it to the model */
-	if( model != NULL )
-	{
-		/* adjust model */
-		if( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) )
-		{
-			_pico_free( surface );
-			return NULL;
-		}
-		
-		/* attach */
-		model->surface[ model->numSurfaces - 1 ] = surface;
-		surface->model = model;
-		
-		/* set default name */
-		sprintf( surfaceName, "Unnamed_%d", model->numSurfaces );
-		PicoSetSurfaceName( surface, surfaceName );
-	}
-	
-	/* return */
-	return surface;
-}
-
-
-
-/*
-PicoFreeSurface()
-frees a surface and all associated data
-*/
-void PicoFreeSurface( picoSurface_t *surface )
-{
-	int		i;
-	
-	
-	/* dummy check */
-	if( surface == NULL )
-		return;
-	
-	/* free bits */
-	_pico_free( surface->xyz );
-	_pico_free( surface->normal );
-	_pico_free( surface->index );
-	_pico_free( surface->faceNormal );
-	
-	/* free arrays */
-	for( i = 0; i < surface->numSTArrays; i++ )
-		_pico_free( surface->st[ i ] );
-	free( surface->st );
-	for( i = 0; i < surface->numColorArrays; i++ )
-		_pico_free( surface->color[ i ] );
-	free( surface->color );
-	
-	/* free the surface */
-	_pico_free( surface );
-}
-
-
-
-/*
-PicoAdjustSurface()
-adjusts a surface's memory allocations to handle the requested sizes.
-will always grow, never shrink
-*/
-
-int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals )
-{
-	int		i;
-	
-	
-	/* dummy check */
-	if( surface == NULL )
-		return 0;
-	
-	/* bare minimums */
-	if( numVertexes < 1 )
-		numVertexes = 1;
-	if( numSTArrays < 1 )
-		numSTArrays = 1;
-	if( numColorArrays < 1 )
-		numColorArrays = 1;
-	if( numIndexes < 1 )
-		numIndexes = 1;
-	
-	/* additional vertexes? */
-	while( numVertexes > surface->maxVertexes ) /* fix */
-	{
-		surface->maxVertexes += PICO_GROW_VERTEXES;
-		if( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) )
-			return 0;
-		if( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) )
-			return 0;
-		for( i = 0; i < surface->numSTArrays; i++ )
-			if( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) )
-			return 0;
-		for( i = 0; i < surface->numColorArrays; i++ )
-			if( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) )
-			return 0;
-	}
-	
-	/* set vertex count to higher */
-	if( numVertexes > surface->numVertexes )
-		surface->numVertexes = numVertexes;
-	
-	/* additional st arrays? */
-	while( numSTArrays > surface->maxSTArrays ) /* fix */
-	{
-		surface->maxSTArrays += PICO_GROW_ARRAYS;
-		if( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) )
-			return 0;
-		while( surface->numSTArrays < numSTArrays )
-		{
-			surface->st[ surface->numSTArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
-			memset( surface->st[ surface->numSTArrays ], 0, surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
-			surface->numSTArrays++;
-		}
-	}
-	
-	/* additional color arrays? */
-	while( numColorArrays > surface->maxColorArrays ) /* fix */
-	{
-		surface->maxColorArrays += PICO_GROW_ARRAYS;
-		if( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) )
-			return 0;
-		while( surface->numColorArrays < numColorArrays )
-		{
-			surface->color[ surface->numColorArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
-			memset( surface->color[ surface->numColorArrays ], 0, surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
-			surface->numColorArrays++;
-		}
-	}
-	
-	/* additional indexes? */
-	while( numIndexes > surface->maxIndexes ) /* fix */
-	{
-		surface->maxIndexes += PICO_GROW_INDEXES;
-		if( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) )
-			return 0;
-	}
-	
-	/* set index count to higher */
-	if( numIndexes > surface->numIndexes )
-		surface->numIndexes = numIndexes;
-
-	/* additional face normals? */
-	while( numFaceNormals > surface->maxFaceNormals ) /* fix */
-	{
-		surface->maxFaceNormals += PICO_GROW_FACES;
-		if( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) )
-			return 0;
-	}
-
-	/* set face normal count to higher */
-	if( numFaceNormals > surface->numFaceNormals )
-		surface->numFaceNormals = numFaceNormals;
-
-	/* return ok */
-	return 1;
-}
-
-
-/* PicoFindSurface:
- *   Finds first matching named surface in a model.
- */
-picoSurface_t *PicoFindSurface(
-	picoModel_t *model, char *name, int caseSensitive )
-{
-	int		i;
-
-	/* sanity check */
-	if( model == NULL || name == NULL )
-		return NULL;
-	
-	/* walk list */
-	for( i = 0; i < model->numSurfaces; i++ )
-	{
-		/* skip null surfaces or surfaces with null names */
-		if( model->surface[ i ] == NULL ||
-			model->surface[ i ]->name == NULL )
-			continue;
-
-		/* compare the surface name with name we're looking for */
-		if (caseSensitive) {
-			if( !strcmp(name,model->surface[ i ]->name) )
-				return model->surface[ i ];
-		} else {
-			if( !_pico_stricmp(name,model->surface[ i ]->name) )
-				return model->surface[ i ];
-		}
-	}
-	/* named surface not found */
-	return NULL;
-}
-
-
-
-/*----------------------------------------------------------------------------
-  PicoSet*() Setter Functions
-----------------------------------------------------------------------------*/
-
-void PicoSetModelName( picoModel_t *model, char *name )
-{
-	if( model == NULL || name == NULL )
-		return;
-	if( model->name != NULL )
-		_pico_free( model->name );
-
-	model->name = _pico_clone_alloc( name,-1 );
-}
-
-
-
-void PicoSetModelFileName( picoModel_t *model, char *fileName )
-{
-	if( model == NULL || fileName == NULL )
-		return;
-	if( model->fileName != NULL )
-		_pico_free( model->fileName );
-
-	model->fileName = _pico_clone_alloc( fileName,-1 );
-}
-
-
-
-void PicoSetModelFrameNum( picoModel_t *model, int frameNum )
-{
-	if( model == NULL )
-		return;
-	model->frameNum = frameNum;
-}
-
-
-
-void PicoSetModelNumFrames( picoModel_t *model, int numFrames )
-{
-	if( model == NULL )
-		return;
-	model->numFrames = numFrames;
-}
-
-
-
-void PicoSetModelData( picoModel_t *model, void *data )
-{
-	if( model == NULL )
-		return;
-	model->data = data;
-}
-
-
-
-void PicoSetShaderName( picoShader_t *shader, char *name )
-{
-	if( shader == NULL || name == NULL )
-		return;
-	if( shader->name != NULL )
-		_pico_free( shader->name );
-
-	shader->name = _pico_clone_alloc( name,-1 );
-}
-
-
-
-void PicoSetShaderMapName( picoShader_t *shader, char *mapName )
-{
-	if( shader == NULL || mapName == NULL )
-		return;
-	if( shader->mapName != NULL )
-		_pico_free( shader->mapName );
-
-	shader->mapName = _pico_clone_alloc( mapName,-1 );
-}
-
-
-
-void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
-{
-	if( shader == NULL || color == NULL )
-		return;
-	shader->ambientColor[ 0 ] = color[ 0 ];
-	shader->ambientColor[ 1 ] = color[ 1 ];
-	shader->ambientColor[ 2 ] = color[ 2 ];
-	shader->ambientColor[ 3 ] = color[ 3 ];
-}
-
-
-
-void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
-{
-	if( shader == NULL || color == NULL )
-		return;
-	shader->diffuseColor[ 0 ] = color[ 0 ];
-	shader->diffuseColor[ 1 ] = color[ 1 ];
-	shader->diffuseColor[ 2 ] = color[ 2 ];
-	shader->diffuseColor[ 3 ] = color[ 3 ];
-}
-
-
-
-void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
-{
-	if( shader == NULL || color == NULL )
-		return;
-	shader->specularColor[ 0 ] = color[ 0 ];
-	shader->specularColor[ 1 ] = color[ 1 ];
-	shader->specularColor[ 2 ] = color[ 2 ];
-	shader->specularColor[ 3 ] = color[ 3 ];
-}
-
-
-
-void PicoSetShaderTransparency( picoShader_t *shader, float value )
-{
-	if( shader == NULL )
-		return;
-	shader->transparency = value;
-
-	/* cap to 0..1 range */
-	if (shader->transparency < 0.0)
-		shader->transparency = 0.0;
-	if (shader->transparency > 1.0)
-		shader->transparency = 1.0;
-}
-
-
-
-void PicoSetShaderShininess( picoShader_t *shader, float value )
-{
-	if( shader == NULL )
-		return;
-	shader->shininess = value;
-
-	/* cap to 0..127 range */
-	if (shader->shininess < 0.0)
-		shader->shininess = 0.0;
-	if (shader->shininess > 127.0)
-		shader->shininess = 127.0;
-}
-
-
-
-void PicoSetSurfaceData( picoSurface_t *surface, void *data )
-{
-	if( surface == NULL )
-		return;
-	surface->data = data;
-}
-
-
-
-void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type )
-{
-	if( surface == NULL )
-		return;
-	surface->type = type;
-}
-
-
-
-void PicoSetSurfaceName( picoSurface_t *surface, char *name )
-{
-	if( surface == NULL || name == NULL )
-		return;
-	if( surface->name != NULL )
-		_pico_free( surface->name );
-
-	surface->name = _pico_clone_alloc( name,-1 );
-}
-
-
-
-void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader )
-{
-	if( surface == NULL )
-		return;
-	surface->shader = shader;
-}
-
-
-
-void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz )
-{
-	if( surface == NULL || num < 0 || xyz == NULL )
-		return;
-	if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
-		return;
-	_pico_copy_vec( xyz, surface->xyz[ num ] );
-	if( surface->model != NULL )
-		_pico_expand_bounds( xyz, surface->model->mins, surface->model->maxs );
-}
-
-
-
-void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
-{
-	if( surface == NULL || num < 0 || normal == NULL )
-		return;
-	if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
-		return;
-	_pico_copy_vec( normal, surface->normal[ num ] );
-}
-
-
-
-void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st )
-{
-	if( surface == NULL || num < 0 || st == NULL )
-		return;
-	if( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) )
-		return;
-	surface->st[ array ][ num ][ 0 ] = st[ 0 ];
-	surface->st[ array ][ num ][ 1 ] = st[ 1 ];
-}
-
-
-
-void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color )
-{
-	if( surface == NULL || num < 0 || color == NULL )
-		return;
-	if( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) )
-		return;
-	surface->color[ array ][ num ][ 0 ] = color[ 0 ];
-	surface->color[ array ][ num ][ 1 ] = color[ 1 ];
-	surface->color[ array ][ num ][ 2 ] = color[ 2 ];
-	surface->color[ array ][ num ][ 3 ] = color[ 3 ];
-}
-
-
-
-void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index )
-{
-	if( surface == NULL || num < 0 )
-		return;
-	if( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) )
-		return;
-	surface->index[ num ] = index;
-}
-
-
-
-void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count )
-{
-	if( num < 0 || index == NULL || count < 1 )
-		return;
-	if( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) )
-		return;
-	memcpy( &surface->index[ num ], index, count * sizeof( surface->index[ num ] ) );
-}
-
-
-
-void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
-{
-	if( surface == NULL || num < 0 || normal == NULL )
-		return;
-	if( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) )
-		return;
-	_pico_copy_vec( normal, surface->faceNormal[ num ] );
-}
-
-
-void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special )
-{
-	if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
-		return;
-	surface->special[ num ] = special;
-}
-
-
-
-/*----------------------------------------------------------------------------
-  PicoGet*() Getter Functions
-----------------------------------------------------------------------------*/
-
-char *PicoGetModelName( picoModel_t *model )
-{
-	if( model == NULL )
-		return NULL;
-	if( model->name == NULL)
-		return (char*) "";
-	return model->name;
-}
-
-
-
-char *PicoGetModelFileName( picoModel_t *model )
-{
-	if( model == NULL )
-		return NULL;
-	if( model->fileName == NULL)
-		return (char*) "";
-	return model->fileName;
-}
-
-
-
-int PicoGetModelFrameNum( picoModel_t *model )
-{
-	if( model == NULL )
-		return 0;
-	return model->frameNum;
-}
-
-
-
-int PicoGetModelNumFrames( picoModel_t *model )
-{
-	if( model == NULL )
-		return 0;
-	return model->numFrames;
-}
-
-
-
-void *PicoGetModelData( picoModel_t *model )
-{
-	if( model == NULL )
-		return NULL;
-	return model->data;
-}
-
-
-
-int PicoGetModelNumShaders( picoModel_t *model )
-{
-	if( model == NULL )
-		return 0;
-	return model->numShaders;
-}
-
-
-
-picoShader_t *PicoGetModelShader( picoModel_t *model, int num )
-{
-	/* a few sanity checks */
-	if( model == NULL )
-		return NULL;
-	if( model->shader == NULL)
-		return NULL;
-	if( num < 0 || num >= model->numShaders )
-		return NULL;
-	
-	/* return the shader */
-	return model->shader[ num ];
-}
-
-
-
-int PicoGetModelNumSurfaces( picoModel_t *model )
-{
-	if( model == NULL )
-		return 0;
-	return model->numSurfaces;
-}
-
-
-
-picoSurface_t *PicoGetModelSurface( picoModel_t *model, int num )
-{
-	/* a few sanity checks */
-	if( model == NULL )
-		return NULL;
-	if( model->surface == NULL)
-		return NULL;
-	if( num < 0 || num >= model->numSurfaces )
-		return NULL;
-	
-	/* return the surface */
-	return model->surface[ num ];
-}
-
-
-
-int PicoGetModelTotalVertexes( picoModel_t *model )
-{
-	int		i, count;
-	
-	
-	if( model == NULL )
-		return 0;
-	if( model->surface == NULL )
-		return 0;
-	
-	count = 0;
-	for( i = 0; i < model->numSurfaces; i++ )
-		 count += PicoGetSurfaceNumVertexes( model->surface[ i ] );
-	
-	return count;
-}
-
-
-
-int PicoGetModelTotalIndexes( picoModel_t *model )
-{
-	int		i, count;
-	
-	
-	if( model == NULL )
-		return 0;
-	if( model->surface == NULL )
-		return 0;
-	
-	count = 0;
-	for( i = 0; i < model->numSurfaces; i++ )
-		 count += PicoGetSurfaceNumIndexes( model->surface[ i ] );
-	
-	return count;
-}
-
-
-
-char *PicoGetShaderName( picoShader_t *shader )
-{
-	if( shader == NULL )
-		return NULL;
-	if( shader->name == NULL)
-		return (char*) "";
-	return shader->name;
-}
-
-
-
-char *PicoGetShaderMapName( picoShader_t *shader )
-{
-	if( shader == NULL )
-		return NULL;
-	if( shader->mapName == NULL)
-		return (char*) "";
-	return shader->mapName;
-}
-
-
-
-picoByte_t *PicoGetShaderAmbientColor( picoShader_t *shader )
-{
-	if( shader == NULL )
-		return NULL;
-	return shader->ambientColor;
-}
-
-
-
-picoByte_t *PicoGetShaderDiffuseColor( picoShader_t *shader )
-{
-	if( shader == NULL )
-		return NULL;
-	return shader->diffuseColor;
-}
-
-
-
-picoByte_t *PicoGetShaderSpecularColor( picoShader_t *shader )
-{
-	if( shader == NULL )
-		return NULL;
-	return shader->specularColor;
-}
-
-
-
-float PicoGetShaderTransparency( picoShader_t *shader )
-{
-	if( shader == NULL )
-		return 0.0f;
-	return shader->transparency;
-}
-
-
-
-float PicoGetShaderShininess( picoShader_t *shader )
-{
-	if( shader == NULL )
-		return 0.0f;
-	return shader->shininess;
-}
-
-
-
-void *PicoGetSurfaceData( picoSurface_t *surface )
-{
-	if( surface == NULL )
-		return NULL;
-	return surface->data;
-}
-
-
-
-picoSurfaceType_t PicoGetSurfaceType( picoSurface_t *surface )
-{
-	if( surface == NULL )
-		return PICO_BAD;
-	return surface->type;
-}
-
-
-
-char *PicoGetSurfaceName( picoSurface_t *surface )
-{
-	if( surface == NULL )
-		return NULL;
-	if( surface->name == NULL )
-		return (char*) "";
-	return surface->name;
-}
-
-
-
-picoShader_t *PicoGetSurfaceShader( picoSurface_t *surface )
-{
-	if( surface == NULL )
-		return NULL;
-	return surface->shader;
-}
-
-
-
-int PicoGetSurfaceNumVertexes( picoSurface_t *surface )
-{
-	if( surface == NULL )
-		return 0;
-	return surface->numVertexes;
-}
-
-
-
-picoVec_t *PicoGetSurfaceXYZ( picoSurface_t *surface, int num )
-{
-	if( surface == NULL || num < 0 || num > surface->numVertexes )
-		return NULL;
-	return surface->xyz[ num ];
-}
-
-
-
-picoVec_t *PicoGetSurfaceNormal( picoSurface_t *surface, int num )
-{
-	if( surface == NULL || num < 0 || num > surface->numVertexes )
-		return NULL;
-	return surface->normal[ num ];
-}
-
-
-
-picoVec_t *PicoGetSurfaceST( picoSurface_t *surface, int array, int num  )
-{
-	if( surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes )
-		return NULL;
-	return surface->st[ array ][ num ];
-}
-
-
-
-picoByte_t *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num )
-{
-	if( surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes )
-		return NULL;
-	return surface->color[ array ][ num ];
-}
-
-
-
-int PicoGetSurfaceNumIndexes( picoSurface_t *surface )
-{
-	if( surface == NULL )
-		return 0;
-	return surface->numIndexes;
-}
-
-
-
-picoIndex_t PicoGetSurfaceIndex( picoSurface_t *surface, int num )
-{
-	if( surface == NULL || num < 0 || num > surface->numIndexes )
-		return 0;
-	return surface->index[ num ];
-}
-
-
-
-picoIndex_t *PicoGetSurfaceIndexes( picoSurface_t *surface, int num )
-{
-	if( surface == NULL || num < 0 || num > surface->numIndexes )
-		return NULL;
-	return &surface->index[ num ];
-}
-
-
-picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num )
-{
-	if( surface == NULL || num < 0 || num > surface->numFaceNormals )
-		return NULL;
-	return surface->faceNormal[ num ];
-}
-
-
-int PicoGetSurfaceSpecial( picoSurface_t *surface, int num )
-{
-	if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
-		return 0;
-	return surface->special[ num ];
-}
-
-
-
-/* ----------------------------------------------------------------------------
-hashtable related functions
----------------------------------------------------------------------------- */
-
-/* hashtable code for faster vertex lookups */
-//#define HASHTABLE_SIZE 32768 // 2048			/* power of 2, use & */
-#define HASHTABLE_SIZE 7919 // 32749 // 2039 	/* prime, use % */
-
-int PicoGetHashTableSize( void )
-{
-	return HASHTABLE_SIZE;
-}
-
-#define HASH_USE_EPSILON
-
-#ifdef HASH_USE_EPSILON
-#define HASH_XYZ_EPSILON					0.01f
-#define HASH_XYZ_EPSILONSPACE_MULTIPLIER	1.f / HASH_XYZ_EPSILON
-#define HASH_ST_EPSILON						0.0001f
-#define HASH_NORMAL_EPSILON					0.02f
-#endif
-
-unsigned int PicoVertexCoordGenerateHash( picoVec3_t xyz )
-{
-	unsigned int hash = 0;
-
-#ifndef HASH_USE_EPSILON
-	hash += ~(*((unsigned int*) &xyz[ 0 ]) << 15);
-	hash ^= (*((unsigned int*) &xyz[ 0 ]) >> 10);
-	hash += (*((unsigned int*) &xyz[ 1 ]) << 3);
-	hash ^= (*((unsigned int*) &xyz[ 1 ]) >> 6);
-	hash += ~(*((unsigned int*) &xyz[ 2 ]) << 11);
-	hash ^= (*((unsigned int*) &xyz[ 2 ]) >> 16);
-#else
-	picoVec3_t xyz_epsilonspace;
-
-	_pico_scale_vec( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace );
-	xyz_epsilonspace[ 0 ] = (float)floor(xyz_epsilonspace[ 0 ]);
-	xyz_epsilonspace[ 1 ] = (float)floor(xyz_epsilonspace[ 1 ]);
-	xyz_epsilonspace[ 2 ] = (float)floor(xyz_epsilonspace[ 2 ]);
-
-	hash += ~(*((unsigned int*) &xyz_epsilonspace[ 0 ]) << 15);
-	hash ^= (*((unsigned int*) &xyz_epsilonspace[ 0 ]) >> 10);
-	hash += (*((unsigned int*) &xyz_epsilonspace[ 1 ]) << 3);
-	hash ^= (*((unsigned int*) &xyz_epsilonspace[ 1 ]) >> 6);
-	hash += ~(*((unsigned int*) &xyz_epsilonspace[ 2 ]) << 11);
-	hash ^= (*((unsigned int*) &xyz_epsilonspace[ 2 ]) >> 16);
-#endif
-
-	//hash = hash & (HASHTABLE_SIZE-1);
-	hash = hash % (HASHTABLE_SIZE);
-	return hash;
-}
-
-picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void )
-{
-	picoVertexCombinationHash_t	**hashTable = _pico_alloc( HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
-
-	memset( hashTable, 0, HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
-
-	return hashTable;
-}
-
-void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable )
-{
-	int							i;
-	picoVertexCombinationHash_t	*vertexCombinationHash;
-	picoVertexCombinationHash_t *nextVertexCombinationHash;
-
-	/* dummy check */
-	if (hashTable == NULL)
-		return;
-
-	for( i = 0; i < HASHTABLE_SIZE; i++ )
-	{
-		if (hashTable[ i ])
-		{
-			nextVertexCombinationHash = NULL;
-
-			for( vertexCombinationHash = hashTable[ i ]; vertexCombinationHash; vertexCombinationHash = nextVertexCombinationHash )
-			{
-				nextVertexCombinationHash = vertexCombinationHash->next;
-				if (vertexCombinationHash->data != NULL)
-				{
-					_pico_free( vertexCombinationHash->data );
-				}
-				_pico_free( vertexCombinationHash );
-			}
-		}
-	}
-
-	_pico_free( hashTable );
-}
-
-picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color )
-{
-	unsigned int				hash;
-	picoVertexCombinationHash_t	*vertexCombinationHash;
-
-	/* dumy check */
-	if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
-		return NULL;
-
-	hash = PicoVertexCoordGenerateHash( xyz );
-
-	for( vertexCombinationHash = hashTable[ hash ]; vertexCombinationHash; vertexCombinationHash = vertexCombinationHash->next )
-	{
-#ifndef HASH_USE_EPSILON
-		/* check xyz */
-		if( (vertexCombinationHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexCombinationHash->vcd.xyz[ 1 ] != xyz[ 1 ] || vertexCombinationHash->vcd.xyz[ 2 ] != xyz[ 2 ]) )
-			continue;
-
-		/* check normal */
-		if( (vertexCombinationHash->vcd.normal[ 0 ] != normal[ 0 ] || vertexCombinationHash->vcd.normal[ 1 ] != normal[ 1 ] || vertexCombinationHash->vcd.normal[ 2 ] != normal[ 2 ]) )
-			continue;
-		
-		/* check st */
-		if( vertexCombinationHash->vcd.st[ 0 ] != st[ 0 ] || vertexCombinationHash->vcd.st[ 1 ] != st[ 1 ] )
-			continue;
-#else
-		/* check xyz */
-		if( ( fabs(xyz[ 0 ] - vertexCombinationHash->vcd.xyz[ 0 ]) ) > HASH_XYZ_EPSILON ||
-			( fabs(xyz[ 1 ] - vertexCombinationHash->vcd.xyz[ 1 ]) ) > HASH_XYZ_EPSILON ||
-			( fabs(xyz[ 2 ] - vertexCombinationHash->vcd.xyz[ 2 ]) ) > HASH_XYZ_EPSILON )
-			continue;
-
-		/* check normal */
-		if( ( fabs(normal[ 0 ] - vertexCombinationHash->vcd.normal[ 0 ]) ) > HASH_NORMAL_EPSILON ||
-			( fabs(normal[ 1 ] - vertexCombinationHash->vcd.normal[ 1 ]) ) > HASH_NORMAL_EPSILON ||
-			( fabs(normal[ 2 ] - vertexCombinationHash->vcd.normal[ 2 ]) ) > HASH_NORMAL_EPSILON )
-			continue;
-		
-		/* check st */
-		if( ( fabs(st[ 0 ] - vertexCombinationHash->vcd.st[ 0 ]) ) > HASH_ST_EPSILON ||
-			( fabs(st[ 1 ] - vertexCombinationHash->vcd.st[ 1 ]) ) > HASH_ST_EPSILON )
-			continue;
-#endif
-
-		/* check color */
-		if( *((int*) vertexCombinationHash->vcd.color) != *((int*) color) )
-			continue;
-
-		/* gotcha */
-		return vertexCombinationHash;
-	}
-
-	return NULL;
-}
-
-picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index )
-{
-	unsigned int				hash;
-	picoVertexCombinationHash_t	*vertexCombinationHash;
-
-	/* dumy check */
-	if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
-		return NULL;
-
-	vertexCombinationHash = _pico_alloc( sizeof(picoVertexCombinationHash_t) );
-
-	if (!vertexCombinationHash)
-		return NULL;
-
-	hash = PicoVertexCoordGenerateHash( xyz );
-
-	_pico_copy_vec( xyz, vertexCombinationHash->vcd.xyz );
-	_pico_copy_vec( normal, vertexCombinationHash->vcd.normal );
-	_pico_copy_vec2( st, vertexCombinationHash->vcd.st );
-	_pico_copy_color( color, vertexCombinationHash->vcd.color );
-	vertexCombinationHash->index = index;
-	vertexCombinationHash->data = NULL;
-	vertexCombinationHash->next = hashTable[ hash ];
-	hashTable[ hash ] = vertexCombinationHash;
-
-	return vertexCombinationHash;
-}
-
-/* ----------------------------------------------------------------------------
-specialized routines
----------------------------------------------------------------------------- */
-
-/*
-PicoFindSurfaceVertex()
-finds a vertex matching the set parameters
-fixme: needs non-naive algorithm
-*/
-
-int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color )
-{
-	int		i, j;
-	
-	
-	/* dummy check */
-	if( surface == NULL || surface->numVertexes <= 0 )
-		return -1;
-	
-	/* walk vertex list */
-	for( i = 0; i < surface->numVertexes; i++ )
-	{
-		/* check xyz */
-		if( xyz != NULL && (surface->xyz[ i ][ 0 ] != xyz[ 0 ] || surface->xyz[ i ][ 1 ] != xyz[ 1 ] || surface->xyz[ i ][ 2 ] != xyz[ 2 ]) )
-			continue;
-		
-		/* check normal */
-		if( normal != NULL && (surface->normal[ i ][ 0 ] != normal[ 0 ] || surface->normal[ i ][ 1 ] != normal[ 1 ] || surface->normal[ i ][ 2 ] != normal[ 2 ]) )
-			continue;
-		
-		/* check st */
-		if( numSTs > 0 && st != NULL )
-		{
-			for( j = 0; j < numSTs; j++ )
-			{
-				if( surface->st[ j ][ i ][ 0 ] != st[ j ][ 0 ] || surface->st[ j ][ i ][ 1 ] != st[ j ][ 1 ] )
-					break;
-			}
-			if( j != numSTs )
-				continue;
-		}
-		
-		/* check color */
-		if( numColors > 0 && color != NULL )
-		{
-			for( j = 0; j < numSTs; j++ )
-			{
-				if( *((int*) surface->color[ j ]) != *((int*) color[ j ]) )
-					break;
-			}
-			if( j != numColors )
-				continue;
-		}
-		
-		/* vertex matches */
-		return i;
-	}
-	
-	/* nada */
-	return -1;
-}
-
-
-
-/*
-PicoFixSurfaceNormals()
-fixes broken normals (certain formats bork normals)
-*/
-
-#define MAX_NORMAL_VOTES		128
-#define EQUAL_NORMAL_EPSILON	0.01
-#define BAD_NORMAL_EPSILON		0.5
-
-void PicoFixSurfaceNormals( picoSurface_t *surface )
-{
-	int				i, j, k, a, b, c, numVotes, faceIndex;
-	picoVec3_t		votes[ MAX_NORMAL_VOTES ];
-	picoVec3_t		*normals, diff;
-	picoVec4_t		plane;
-	
-	
-	/* dummy check */
-	if( surface == NULL || surface->numVertexes == 0 )
-		return;
-	
-	/* fixme: handle other surface types */
-	if( surface->type != PICO_TRIANGLES )
-		return;
-	
-	/* allocate normal storage */
-	normals = _pico_alloc( surface->numVertexes * sizeof( *normals ) );
-	if( normals == NULL )
-	{
-		_pico_printf( PICO_ERROR, "PicoFixSurfaceNormals: Unable to allocate memory for temporary normal storage" );
-		return;
-	}
-	
-	/* zero it out */
-	memset( normals, 0, surface->numVertexes * sizeof( *normals ) );
-	
-	/* walk vertex list */
-	for( i = 0; i < surface->numVertexes; i++ )
-	{
-		/* zero out votes */
-		numVotes = 0;
-		
-		/* find all the triangles that reference this vertex */
-		for( j = 0, faceIndex = 0; j < surface->numIndexes; j += 3, faceIndex++ )
-		{
-			/* get triangle */
-			a = surface->index[ j ];
-			b = surface->index[ j + 1 ];
-			c = surface->index[ j + 2 ];
-			
-			/* ignore degenerate triangles */
-			if( a == b || b == c || c == a )
-				continue;
-			
-			/* ignore indexes out of range */
-			if( a < 0 || a >= surface->numVertexes ||
-				b < 0 || b >= surface->numVertexes ||
-				c < 0 || c >= surface->numVertexes )
-				continue;
-			
-			/* test triangle */
-			if( a == i || b == i || c == i )
-			{
-				/* if this surface has face normals */
-				if( surface->numFaceNormals && faceIndex < surface->numFaceNormals )
-				{
-					_pico_copy_vec( surface->faceNormal[ faceIndex ], plane );
-					if( plane[ 0 ] == 0.f && plane[ 1 ] == 0.f && plane[ 2 ] == 0.f )
-					{
-						/* if null normal, make plane from the 3 points */
-						if( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 )
-						{
-							continue;
-						}
-					}
-				}
-				/* make a plane from the 3 points */
-				else if( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 )
-				{
-					continue;
-				}
-
-				/* see if this normal has already been voted */
-				for( k = 0; k < numVotes; k++ )
-				{
-					_pico_subtract_vec( plane, votes[ k ], diff );
-					if( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
-						fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
-						fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON )
-						break;
-				}
-				
-				/* add a new vote? */
-				if( k == numVotes && numVotes < MAX_NORMAL_VOTES )
-				{
-					_pico_copy_vec( plane, votes[ numVotes ] );
-					numVotes++;
-				}
-			}
-		}
-		
-		/* tally votes */
-		if( numVotes > 0 )
-		{
-			/* create average normal */
-			_pico_zero_vec( normals[ i ] );
-			for( k = 0; k < numVotes; k++ )
-				_pico_add_vec( normals[ i ], votes[ k ], normals[ i ] );
-			
-			/* normalize it */
-			if( _pico_normalize_vec( normals[ i ] ) )
-			{
-				/* test against actual normal */
-				if( fabs( _pico_dot_vec( normals[ i ], surface->normal[ i ] ) - 1 ) > BAD_NORMAL_EPSILON )
-				{
-					//%	printf( "Normal %8d: (%f %f %f) -> (%f %f %f)\n", i,
-					//%		surface->normal[ i ][ 0 ], surface->normal[ i ][ 1 ], surface->normal[ i ][ 2 ],
-					//%		normals[ i ][ 0 ], normals[ i ][ 1 ], normals[ i ][ 2 ] );
-					_pico_copy_vec( normals[ i ], surface->normal[ i ] );
-				}
-			}
-		}
-	}
-	
-	/* free normal storage */
-	_pico_free( normals );
-}
-
-
-
-
-/*
-PicoRemapModel() - sea
-remaps model material/etc. information using the remappings
-contained in the given 'remapFile' (full path to the ascii file to open)
-returns 1 on success or 0 on error
-*/
-
-#define _prm_error_return \
-{ \
-	_pico_free_parser( p ); \
-	_pico_free_file( remapBuffer ); \
-	return 0; \
-}
-
-int PicoRemapModel( picoModel_t *model, char *remapFile )
-{
-	picoParser_t	*p;
-	picoByte_t		*remapBuffer;
-	int				remapBufSize;
-	
-	
-	/* sanity checks */
-	if( model == NULL || remapFile == NULL )
-		return 0;
-	
-	/* load remap file contents */
-	_pico_load_file( remapFile,&remapBuffer,&remapBufSize );
-	
-	/* check result */
-	if( remapBufSize == 0 )
-		return 1;	/* file is empty: no error */
-	if( remapBufSize < 0 )
-		return 0;	/* load failed: error */
-	
-	/* create a new pico parser */
-	p = _pico_new_parser( remapBuffer, remapBufSize );
-	if (p == NULL)
-	{
-		/* ram is really cheap nowadays... */
-		_prm_error_return;
-	}
-	
-	/* doo teh parse */
-	while( 1 )
-	{
-		/* get next token in remap file */
-		if (!_pico_parse( p,1 ))
-			break;
-
-		/* skip over c++ style comment lines */
-		if (!_pico_stricmp(p->token,"//"))
-		{
-			_pico_parse_skip_rest( p );
-			continue;
-		}
-		
-		/* block for quick material shader name remapping */
-		/* materials { "m" (=>|->|=) "s" } */
-		if( !_pico_stricmp(p->token, "materials" ) )
-		{
-			int level = 1;
-
-			/* check bracket */
-			if (!_pico_parse_check( p,1,"{" ))
-				_prm_error_return;
-
-			/* process assignments */
-			while( 1 )
-			{
-				picoShader_t	*shader;
-				char			*materialName;
-				
-				
-				/* get material name */
-				if (_pico_parse( p,1 ) == NULL) break;
-				if (!strlen(p->token)) continue;
-				materialName = _pico_clone_alloc( p->token,-1 );
-				if (materialName == NULL)
-					_prm_error_return;
-
-				/* handle levels */
-				if (p->token[0] == '{') level++;
-				if (p->token[0] == '}') level--;
-				if (!level) break;
-
-				/* get next token (assignment token or shader name) */
-				if (!_pico_parse( p,0 ))
-				{
-					_pico_free( materialName );
-					_prm_error_return;
-				}
-				/* skip assignment token (if present) */
-				if (!strcmp(p->token,"=>") ||
-					!strcmp(p->token,"->") ||
-					!strcmp(p->token,"="))
-				{
-					/* simply grab the next token */
-					if (!_pico_parse( p,0 ))
-					{
-						_pico_free( materialName );
-						_prm_error_return;
-					}
-				}
-				/* try to find material by name */
-				shader = PicoFindShader( model,materialName,0 );
-
-				/* we've found a material matching the name */
-				if (shader != NULL)
-				{
-					PicoSetShaderName( shader,p->token );
-				}
-				/* free memory used by material name */
-				_pico_free( materialName );
-
-				/* skip rest */
-				_pico_parse_skip_rest( p );
-			}
-		}
-		/* block for detailed single material remappings */
-		/* materials[ "m" ] { key data... } */
-		else if (!_pico_stricmp(p->token,"materials["))
-		{
-			picoShader_t *shader;
-			char *tempMaterialName;
-			int level = 1;
-
-			/* get material name */
-			if (!_pico_parse( p,0 ))
-				_prm_error_return;
-
-			/* temporary copy of material name */
-			tempMaterialName = _pico_clone_alloc( p->token,-1 );
-			if (tempMaterialName == NULL)
-				_prm_error_return;
-
-			/* check square closing bracket */
-			if (!_pico_parse_check( p,0,"]" ))
-				_prm_error_return;			
-
-			/* try to find material by name */
-			shader = PicoFindShader( model,tempMaterialName,0 );
-
-			/* free memory used by temporary material name */
-			_pico_free( tempMaterialName );
-
-			/* we haven't found a material matching the name */
-			/* so we simply skip the braced section now and */
-			/* continue parsing with the next main token */
-			if (shader == NULL)
-			{
-				_pico_parse_skip_braced( p );
-				continue;
-			}
-			/* check opening bracket */
-			if (!_pico_parse_check( p,1,"{" ))
-				_prm_error_return;
-
-			/* process material info keys */
-			while( 1 )
-			{
-				/* get key name */
-				if (_pico_parse( p,1 ) == NULL) break;
-				if (!strlen(p->token)) continue;
-
-				/* handle levels */
-				if (p->token[0] == '{') level++;
-				if (p->token[0] == '}') level--;
-				if (!level) break;
-
-				/* remap shader name */
-				if (!_pico_stricmp(p->token,"shader"))
-				{
-					if (!_pico_parse( p,0 )) _prm_error_return;
-					PicoSetShaderName( shader,p->token );
-				}
-				/* remap shader map name */
-				else if (!_pico_stricmp(p->token,"mapname"))
-				{
-					if (!_pico_parse( p,0 )) _prm_error_return;
-					PicoSetShaderMapName( shader,p->token );
-				}
-				/* remap shader's ambient color */
-				else if (!_pico_stricmp(p->token,"ambient"))
-				{
-					picoColor_t color;
-					picoVec3_t  v;
-
-					/* get vector from parser */
-					if (!_pico_parse_vec( p,v )) _prm_error_return;
-
-					/* store as color */
-					color[ 0 ] = (picoByte_t)v[ 0 ];
-					color[ 1 ] = (picoByte_t)v[ 1 ];
-					color[ 2 ] = (picoByte_t)v[ 2 ];
-
-					/* set new ambient color */
-					PicoSetShaderAmbientColor( shader,color );
-				}
-				/* remap shader's diffuse color */
-				else if (!_pico_stricmp(p->token,"diffuse"))
-				{
-					picoColor_t color;
-					picoVec3_t  v;
-
-					/* get vector from parser */
-					if (!_pico_parse_vec( p,v )) _prm_error_return;
-
-					/* store as color */
-					color[ 0 ] = (picoByte_t)v[ 0 ];
-					color[ 1 ] = (picoByte_t)v[ 1 ];
-					color[ 2 ] = (picoByte_t)v[ 2 ];
-
-					/* set new ambient color */
-					PicoSetShaderDiffuseColor( shader,color );
-				}
-				/* remap shader's specular color */
-				else if (!_pico_stricmp(p->token,"specular"))
-				{
-					picoColor_t color;
-					picoVec3_t  v;
-
-					/* get vector from parser */
-					if (!_pico_parse_vec( p,v )) _prm_error_return;
-
-					/* store as color */
-					color[ 0 ] = (picoByte_t)v[ 0 ];
-					color[ 1 ] = (picoByte_t)v[ 1 ];
-					color[ 2 ] = (picoByte_t)v[ 2 ];
-
-					/* set new ambient color */
-					PicoSetShaderSpecularColor( shader,color );
-				}
-				/* skip rest */
-				_pico_parse_skip_rest( p );
-			}
-		}
-		/* end 'materials[' */
-	}
-	
-	/* free both parser and file buffer */
-	_pico_free_parser( p );
-	_pico_free_file( remapBuffer );
-
-	/* return with success */
-	return 1;
-}
-
-
-/*
-PicoAddTriangleToModel() - jhefty
-A nice way to add individual triangles to the model.
-Chooses an appropriate surface based on the shader, or adds a new surface if necessary
-*/
-
-void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, 
-							int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
-							picoShader_t* shader )
-{
-	int i,j;
-	int vertDataIndex;
-	picoSurface_t* workSurface = NULL;
-
-	/* see if a surface already has the shader */
-	for ( i = 0 ; i < model->numSurfaces ; i++ )
-	{
-		workSurface = model->surface[i];
-		if ( workSurface->shader == shader )
-		{			
-			break;
-		}
-	}
-
-	/* no surface uses this shader yet, so create a new surface */
-	if ( !workSurface || i >=model->numSurfaces )
-	{
-		/* create a new surface in the model for the unique shader */
-		workSurface = PicoNewSurface(model);
-		if ( !workSurface )
-		{
-			_pico_printf ( PICO_ERROR , "Could not allocate a new surface!\n" );
-			return;
-		}
-
-		/* do surface setup */
-		PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
-		PicoSetSurfaceName( workSurface, shader->name );
-		PicoSetSurfaceShader( workSurface, shader );
-	}
-
-	/* add the triangle data to the surface */
-	for ( i = 0 ; i < 3 ; i++ )	
-	{
-		/* get the next free spot in the index array */
-		int newVertIndex = PicoGetSurfaceNumIndexes ( workSurface );
-
-		/* get the index of the vertex that we're going to store at newVertIndex */
-		vertDataIndex = PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i]);
-
-		/* the vertex wasn't found, so create a new vertex in the pool from the data we have */
-		if ( vertDataIndex == -1 )
-		{			
-			/* find the next spot for a new vertex */
-			vertDataIndex = PicoGetSurfaceNumVertexes ( workSurface );			
-
-			/* assign the data to it */
-			PicoSetSurfaceXYZ ( workSurface ,vertDataIndex , *xyz[i] );
-			PicoSetSurfaceNormal ( workSurface , vertDataIndex , *normals[i] );			
-
-			/* make sure to copy over all available ST's and colors for the vertex */
-			for ( j = 0 ; j < numColors ; j++ )
-			{
-				PicoSetSurfaceColor( workSurface , j , vertDataIndex , colors[i][j] );
-			}
-			for ( j = 0 ; j < numSTs ; j++ )
-			{
-				PicoSetSurfaceST ( workSurface , j , vertDataIndex , st[i][j] );
-			}
-		}
-
-		/* add this vertex to the triangle */		
-		PicoSetSurfaceIndex ( workSurface , newVertIndex , vertDataIndex );
-	}	
-}
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PICOMODEL_C
+
+
+
+/* dependencies */
+#include "picointernal.h"
+
+
+
+/*
+PicoInit()
+initializes the picomodel library
+*/
+
+int PicoInit( void )
+{
+	/* successfully initialized -sea */
+	return 1;
+}
+
+
+
+/*
+PicoShutdown()
+shuts the pico model library down
+*/
+
+void PicoShutdown( void )
+{
+	/* do something interesting here in the future */
+	return;
+}
+
+
+
+/*
+PicoError()
+returns last picomodel error code (see PME_* defines)
+*/
+
+int PicoError( void )
+{
+	/* todo: do something here */
+	return 0;
+}
+
+
+
+/*
+PicoSetMallocFunc()
+sets the ptr to the malloc function
+*/
+
+void PicoSetMallocFunc( void *(*func)( size_t ) )
+{
+	if( func != NULL )
+		_pico_ptr_malloc = func;
+}
+
+
+
+/*
+PicoSetFreeFunc()
+sets the ptr to the free function
+*/
+
+void PicoSetFreeFunc( void (*func)( void* ) )
+{
+	if( func != NULL )
+		_pico_ptr_free = func;
+}
+
+
+
+/*
+PicoSetLoadFileFunc()
+sets the ptr to the file load function
+*/
+
+void PicoSetLoadFileFunc( void (*func)( char*, unsigned char**, int* ) )
+{
+	if( func != NULL )
+		_pico_ptr_load_file = func;
+}
+
+
+
+/*
+PicoSetFreeFileFunc()
+sets the ptr to the free function
+*/
+
+void PicoSetFreeFileFunc( void (*func)( void* ) )
+{
+	if( func != NULL )
+		_pico_ptr_free_file = func;
+}
+
+
+
+/*
+PicoSetPrintFunc()
+sets the ptr to the print function
+*/
+
+void PicoSetPrintFunc( void (*func)( int, const char* ) )
+{
+	if( func != NULL )
+		_pico_ptr_print = func;
+}
+
+
+
+/*
+PicoLoadModel()
+the meat and potatoes function
+*/
+
+picoModel_t	*PicoLoadModel( char *fileName, int frameNum )
+{
+	const picoModule_t	**modules, *pm;
+	picoModel_t			*model;
+	picoByte_t			*buffer;
+	int					bufSize;
+	char				*modelFileName, *remapFileName;
+
+	
+	/* init */
+	model = NULL;
+	
+	/* make sure we've got a file name */
+	if( fileName == NULL )
+	{
+		_pico_printf( PICO_ERROR, "PicoLoadModel: No filename given (fileName == NULL)" );
+		return NULL;
+	}
+	
+	/* load file data (buffer is allocated by host app) */
+	_pico_load_file( fileName, &buffer, &bufSize );
+	if( bufSize < 0 )
+	{
+		_pico_printf( PICO_ERROR, "PicoLoadModel: Failed loading model %s", fileName );
+		return NULL;
+	}
+
+	/* get ptr to list of supported modules */
+	modules = PicoModuleList( NULL );
+	
+	/* run it through the various loader functions and try */
+	/* to find a loader that fits the given file data */
+	for( ; *modules != NULL; modules++ )
+	{
+		/* get module */
+		pm = *modules;
+		
+		/* sanity check */
+		if( pm == NULL)
+			break;
+
+		/* module must be able to load */
+		if( pm->canload == NULL || pm->load == NULL )
+			continue;
+		
+		/* see whether this module can load the model file or not */
+		if( pm->canload( fileName, buffer, bufSize ) == PICO_PMV_OK )
+		{
+			/* use loader provided by module to read the model data */
+			model = pm->load( fileName, frameNum, buffer, bufSize );
+			if( model == NULL )
+			{
+				_pico_free_file( buffer );
+				return NULL;
+			}
+			
+			/* assign pointer to file format module */
+			model->module = pm;
+			
+			/* get model file name */
+			modelFileName = PicoGetModelFileName( model );
+			
+			/* apply model remappings from <model>.remap */
+			if( strlen( modelFileName ) )
+			{
+				/* alloc copy of model file name */
+				remapFileName = _pico_alloc( strlen( modelFileName ) + 20 );
+				if( remapFileName != NULL )
+				{
+					/* copy model file name and change extension */
+					strcpy( remapFileName, modelFileName );
+					_pico_setfext( remapFileName, "remap" );
+
+					/* try to remap model; we don't handle the result */
+					PicoRemapModel( model, remapFileName );
+
+					/* free the remap file name string */
+					_pico_free( remapFileName );
+				}
+			}
+			
+			/* model was loaded, so break out of loop */
+			break;
+		}
+	}
+	
+	/* free memory used by file buffer */
+	if( buffer)
+		_pico_free_file( buffer );
+
+	/* return */
+	return model;
+}
+
+
+
+/* ----------------------------------------------------------------------------
+models
+---------------------------------------------------------------------------- */
+
+/*
+PicoNewModel()
+creates a new pico model
+*/
+
+picoModel_t *PicoNewModel( void )
+{
+	picoModel_t	*model;
+	
+	/* allocate */
+	model = _pico_alloc( sizeof(picoModel_t) );
+	if( model == NULL )
+		return NULL;
+
+	/* clear */
+	memset( model,0,sizeof(picoModel_t) );
+	
+	/* model set up */
+	_pico_zero_bounds( model->mins,model->maxs );
+
+	/* set initial frame count to 1 -sea */
+	model->numFrames = 1;
+
+	/* return ptr to new model */
+	return model;
+}
+
+
+
+/*
+PicoFreeModel()
+frees a model and all associated data
+*/
+
+void PicoFreeModel( picoModel_t *model )
+{
+	int				i;
+	
+
+	/* sanity check */
+	if( model == NULL )
+		return;
+	
+	/* free bits */
+	if( model->name )
+		_pico_free( model->name );
+	
+	/* free shaders */
+	for( i = 0; i < model->numShaders; i++ )
+		PicoFreeShader( model->shader[ i ] );
+	free( model->shader );
+	
+	/* free surfaces */
+	for( i = 0; i < model->numSurfaces; i++ )
+		PicoFreeSurface( model->surface[ i ] );
+	free( model->surface );
+	
+	/* free the model */
+	_pico_free( model );
+}
+
+
+
+/*
+PicoAdjustModel()
+adjusts a models's memory allocations to handle the requested sizes.
+will always grow, never shrink
+*/
+
+int PicoAdjustModel( picoModel_t *model, int numShaders, int numSurfaces )
+{
+	/* dummy check */
+	if( model == NULL )
+		return 0;
+	
+	/* bare minimums */
+	/* sea: null surface/shader fix (1s=>0s) */
+	if( numShaders < 0 )
+		numShaders = 0;
+	if( numSurfaces < 0 )
+		numSurfaces = 0;
+
+	/* additional shaders? */
+	while( numShaders > model->maxShaders )
+	{
+		model->maxShaders += PICO_GROW_SHADERS;
+		if( !_pico_realloc( (void *) &model->shader, model->numShaders * sizeof( *model->shader ), model->maxShaders * sizeof( *model->shader ) ) )
+			return 0;
+	}
+	
+	/* set shader count to higher */
+	if( numShaders > model->numShaders )
+		model->numShaders = numShaders;
+	
+	/* additional surfaces? */
+	while( numSurfaces > model->maxSurfaces )
+	{
+		model->maxSurfaces += PICO_GROW_SURFACES;
+		if( !_pico_realloc( (void *) &model->surface, model->numSurfaces * sizeof( *model->surface ), model->maxSurfaces * sizeof( *model->surface ) ) )
+			return 0;
+	}
+	
+	/* set shader count to higher */
+	if( numSurfaces > model->numSurfaces )
+		model->numSurfaces = numSurfaces;
+	
+	/* return ok */
+	return 1;
+}
+
+
+
+/* ----------------------------------------------------------------------------
+shaders
+---------------------------------------------------------------------------- */
+
+/*
+PicoNewShader()
+creates a new pico shader and returns its index. -sea
+*/
+
+picoShader_t *PicoNewShader( picoModel_t *model )
+{
+	picoShader_t	*shader;
+	
+
+	/* allocate and clear */
+	shader = _pico_alloc( sizeof(picoShader_t) );
+	if( shader == NULL )
+		return NULL;
+	memset( shader, 0, sizeof(picoShader_t) );
+	
+	/* attach it to the model */
+	if( model != NULL )
+	{
+		/* adjust model */
+		if( !PicoAdjustModel( model, model->numShaders + 1, 0 ) )
+		{
+			_pico_free( shader );
+			return NULL;
+		}
+		/* attach */
+		model->shader[ model->numShaders - 1 ] = shader;
+		shader->model = model;
+	}
+	/* setup default shader colors */
+	_pico_set_color( shader->ambientColor,0,0,0,0 );
+	_pico_set_color( shader->diffuseColor,255,255,255,1 );
+	_pico_set_color( shader->specularColor,0,0,0,0 );
+
+	/* no need to do this, but i do it anyway */
+	shader->transparency = 0;
+	shader->shininess = 0;
+
+	/* return the newly created shader */
+	return shader;
+}
+
+
+
+/*
+PicoFreeShader()
+frees a shader and all associated data -sea
+*/
+
+void PicoFreeShader( picoShader_t *shader )
+{
+	/* dummy check */
+	if( shader == NULL )
+		return;
+	
+	/* free bits */
+	if( shader->name )
+		_pico_free( shader->name );
+	if( shader->mapName )
+		_pico_free( shader->mapName );
+	
+	/* free the shader */
+	_pico_free( shader );
+}
+
+
+
+/*
+PicoFindShader()
+finds a named shader in a model
+*/
+
+picoShader_t *PicoFindShader( picoModel_t *model, char *name, int caseSensitive )
+{
+	int		i;
+	
+	
+	/* sanity checks */
+	if( model == NULL || name == NULL )	/* sea: null name fix */
+		return NULL;
+	
+	/* walk list */
+	for( i = 0; i < model->numShaders; i++ )
+	{
+		/* skip null shaders or shaders with null names */
+		if( model->shader[ i ] == NULL ||
+			model->shader[ i ]->name == NULL )
+			continue;
+
+		/* compare the shader name with name we're looking for */
+		if( caseSensitive )
+		{
+			if( !strcmp( name, model->shader[ i ]->name ) )
+				return model->shader[ i ];
+		}
+		else if( !_pico_stricmp( name, model->shader[ i ]->name ) )
+				return model->shader[ i ];
+	}
+	
+	/* named shader not found */
+	return NULL;
+}
+
+
+
+/* ----------------------------------------------------------------------------
+surfaces
+---------------------------------------------------------------------------- */
+
+/*
+PicoNewSurface()
+creates a new pico surface
+*/
+
+picoSurface_t *PicoNewSurface( picoModel_t *model )
+{
+	picoSurface_t	*surface;
+	char surfaceName[64];
+	
+	/* allocate and clear */
+	surface = _pico_alloc( sizeof( *surface ) );
+	if( surface == NULL )
+		return NULL;
+	memset( surface, 0, sizeof( *surface ) );
+	
+	/* attach it to the model */
+	if( model != NULL )
+	{
+		/* adjust model */
+		if( !PicoAdjustModel( model, 0, model->numSurfaces + 1 ) )
+		{
+			_pico_free( surface );
+			return NULL;
+		}
+		
+		/* attach */
+		model->surface[ model->numSurfaces - 1 ] = surface;
+		surface->model = model;
+		
+		/* set default name */
+		sprintf( surfaceName, "Unnamed_%d", model->numSurfaces );
+		PicoSetSurfaceName( surface, surfaceName );
+	}
+	
+	/* return */
+	return surface;
+}
+
+
+
+/*
+PicoFreeSurface()
+frees a surface and all associated data
+*/
+void PicoFreeSurface( picoSurface_t *surface )
+{
+	int		i;
+	
+	
+	/* dummy check */
+	if( surface == NULL )
+		return;
+	
+	/* free bits */
+	_pico_free( surface->xyz );
+	_pico_free( surface->normal );
+	_pico_free( surface->index );
+	_pico_free( surface->faceNormal );
+	
+	/* free arrays */
+	for( i = 0; i < surface->numSTArrays; i++ )
+		_pico_free( surface->st[ i ] );
+	free( surface->st );
+	for( i = 0; i < surface->numColorArrays; i++ )
+		_pico_free( surface->color[ i ] );
+	free( surface->color );
+	
+	/* free the surface */
+	_pico_free( surface );
+}
+
+
+
+/*
+PicoAdjustSurface()
+adjusts a surface's memory allocations to handle the requested sizes.
+will always grow, never shrink
+*/
+
+int PicoAdjustSurface( picoSurface_t *surface, int numVertexes, int numSTArrays, int numColorArrays, int numIndexes, int numFaceNormals )
+{
+	int		i;
+	
+	
+	/* dummy check */
+	if( surface == NULL )
+		return 0;
+	
+	/* bare minimums */
+	if( numVertexes < 1 )
+		numVertexes = 1;
+	if( numSTArrays < 1 )
+		numSTArrays = 1;
+	if( numColorArrays < 1 )
+		numColorArrays = 1;
+	if( numIndexes < 1 )
+		numIndexes = 1;
+	
+	/* additional vertexes? */
+	while( numVertexes > surface->maxVertexes ) /* fix */
+	{
+		surface->maxVertexes += PICO_GROW_VERTEXES;
+		if( !_pico_realloc( (void *) &surface->xyz, surface->numVertexes * sizeof( *surface->xyz ), surface->maxVertexes * sizeof( *surface->xyz ) ) )
+			return 0;
+		if( !_pico_realloc( (void *) &surface->normal, surface->numVertexes * sizeof( *surface->normal ), surface->maxVertexes * sizeof( *surface->normal ) ) )
+			return 0;
+		for( i = 0; i < surface->numSTArrays; i++ )
+			if( !_pico_realloc( (void*) &surface->st[ i ], surface->numVertexes * sizeof( *surface->st[ i ] ), surface->maxVertexes * sizeof( *surface->st[ i ] ) ) )
+			return 0;
+		for( i = 0; i < surface->numColorArrays; i++ )
+			if( !_pico_realloc( (void*) &surface->color[ i ], surface->numVertexes * sizeof( *surface->color[ i ] ), surface->maxVertexes * sizeof( *surface->color[ i ] ) ) )
+			return 0;
+	}
+	
+	/* set vertex count to higher */
+	if( numVertexes > surface->numVertexes )
+		surface->numVertexes = numVertexes;
+	
+	/* additional st arrays? */
+	while( numSTArrays > surface->maxSTArrays ) /* fix */
+	{
+		surface->maxSTArrays += PICO_GROW_ARRAYS;
+		if( !_pico_realloc( (void*) &surface->st, surface->numSTArrays * sizeof( *surface->st ), surface->maxSTArrays * sizeof( *surface->st ) ) )
+			return 0;
+		while( surface->numSTArrays < numSTArrays )
+		{
+			surface->st[ surface->numSTArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
+			memset( surface->st[ surface->numSTArrays ], 0, surface->maxVertexes * sizeof( *surface->st[ 0 ] ) );
+			surface->numSTArrays++;
+		}
+	}
+	
+	/* additional color arrays? */
+	while( numColorArrays > surface->maxColorArrays ) /* fix */
+	{
+		surface->maxColorArrays += PICO_GROW_ARRAYS;
+		if( !_pico_realloc( (void*) &surface->color, surface->numColorArrays * sizeof( *surface->color ), surface->maxColorArrays * sizeof( *surface->color ) ) )
+			return 0;
+		while( surface->numColorArrays < numColorArrays )
+		{
+			surface->color[ surface->numColorArrays ] = _pico_alloc( surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
+			memset( surface->color[ surface->numColorArrays ], 0, surface->maxVertexes * sizeof( *surface->color[ 0 ] ) );
+			surface->numColorArrays++;
+		}
+	}
+	
+	/* additional indexes? */
+	while( numIndexes > surface->maxIndexes ) /* fix */
+	{
+		surface->maxIndexes += PICO_GROW_INDEXES;
+		if( !_pico_realloc( (void*) &surface->index, surface->numIndexes * sizeof( *surface->index ), surface->maxIndexes * sizeof( *surface->index ) ) )
+			return 0;
+	}
+	
+	/* set index count to higher */
+	if( numIndexes > surface->numIndexes )
+		surface->numIndexes = numIndexes;
+
+	/* additional face normals? */
+	while( numFaceNormals > surface->maxFaceNormals ) /* fix */
+	{
+		surface->maxFaceNormals += PICO_GROW_FACES;
+		if( !_pico_realloc( (void *) &surface->faceNormal, surface->numFaceNormals * sizeof( *surface->faceNormal ), surface->maxFaceNormals * sizeof( *surface->faceNormal ) ) )
+			return 0;
+	}
+
+	/* set face normal count to higher */
+	if( numFaceNormals > surface->numFaceNormals )
+		surface->numFaceNormals = numFaceNormals;
+
+	/* return ok */
+	return 1;
+}
+
+
+/* PicoFindSurface:
+ *   Finds first matching named surface in a model.
+ */
+picoSurface_t *PicoFindSurface(
+	picoModel_t *model, char *name, int caseSensitive )
+{
+	int		i;
+
+	/* sanity check */
+	if( model == NULL || name == NULL )
+		return NULL;
+	
+	/* walk list */
+	for( i = 0; i < model->numSurfaces; i++ )
+	{
+		/* skip null surfaces or surfaces with null names */
+		if( model->surface[ i ] == NULL ||
+			model->surface[ i ]->name == NULL )
+			continue;
+
+		/* compare the surface name with name we're looking for */
+		if (caseSensitive) {
+			if( !strcmp(name,model->surface[ i ]->name) )
+				return model->surface[ i ];
+		} else {
+			if( !_pico_stricmp(name,model->surface[ i ]->name) )
+				return model->surface[ i ];
+		}
+	}
+	/* named surface not found */
+	return NULL;
+}
+
+
+
+/*----------------------------------------------------------------------------
+  PicoSet*() Setter Functions
+----------------------------------------------------------------------------*/
+
+void PicoSetModelName( picoModel_t *model, char *name )
+{
+	if( model == NULL || name == NULL )
+		return;
+	if( model->name != NULL )
+		_pico_free( model->name );
+
+	model->name = _pico_clone_alloc( name,-1 );
+}
+
+
+
+void PicoSetModelFileName( picoModel_t *model, char *fileName )
+{
+	if( model == NULL || fileName == NULL )
+		return;
+	if( model->fileName != NULL )
+		_pico_free( model->fileName );
+
+	model->fileName = _pico_clone_alloc( fileName,-1 );
+}
+
+
+
+void PicoSetModelFrameNum( picoModel_t *model, int frameNum )
+{
+	if( model == NULL )
+		return;
+	model->frameNum = frameNum;
+}
+
+
+
+void PicoSetModelNumFrames( picoModel_t *model, int numFrames )
+{
+	if( model == NULL )
+		return;
+	model->numFrames = numFrames;
+}
+
+
+
+void PicoSetModelData( picoModel_t *model, void *data )
+{
+	if( model == NULL )
+		return;
+	model->data = data;
+}
+
+
+
+void PicoSetShaderName( picoShader_t *shader, char *name )
+{
+	if( shader == NULL || name == NULL )
+		return;
+	if( shader->name != NULL )
+		_pico_free( shader->name );
+
+	shader->name = _pico_clone_alloc( name,-1 );
+}
+
+
+
+void PicoSetShaderMapName( picoShader_t *shader, char *mapName )
+{
+	if( shader == NULL || mapName == NULL )
+		return;
+	if( shader->mapName != NULL )
+		_pico_free( shader->mapName );
+
+	shader->mapName = _pico_clone_alloc( mapName,-1 );
+}
+
+
+
+void PicoSetShaderAmbientColor( picoShader_t *shader, picoColor_t color )
+{
+	if( shader == NULL || color == NULL )
+		return;
+	shader->ambientColor[ 0 ] = color[ 0 ];
+	shader->ambientColor[ 1 ] = color[ 1 ];
+	shader->ambientColor[ 2 ] = color[ 2 ];
+	shader->ambientColor[ 3 ] = color[ 3 ];
+}
+
+
+
+void PicoSetShaderDiffuseColor( picoShader_t *shader, picoColor_t color )
+{
+	if( shader == NULL || color == NULL )
+		return;
+	shader->diffuseColor[ 0 ] = color[ 0 ];
+	shader->diffuseColor[ 1 ] = color[ 1 ];
+	shader->diffuseColor[ 2 ] = color[ 2 ];
+	shader->diffuseColor[ 3 ] = color[ 3 ];
+}
+
+
+
+void PicoSetShaderSpecularColor( picoShader_t *shader, picoColor_t color )
+{
+	if( shader == NULL || color == NULL )
+		return;
+	shader->specularColor[ 0 ] = color[ 0 ];
+	shader->specularColor[ 1 ] = color[ 1 ];
+	shader->specularColor[ 2 ] = color[ 2 ];
+	shader->specularColor[ 3 ] = color[ 3 ];
+}
+
+
+
+void PicoSetShaderTransparency( picoShader_t *shader, float value )
+{
+	if( shader == NULL )
+		return;
+	shader->transparency = value;
+
+	/* cap to 0..1 range */
+	if (shader->transparency < 0.0)
+		shader->transparency = 0.0;
+	if (shader->transparency > 1.0)
+		shader->transparency = 1.0;
+}
+
+
+
+void PicoSetShaderShininess( picoShader_t *shader, float value )
+{
+	if( shader == NULL )
+		return;
+	shader->shininess = value;
+
+	/* cap to 0..127 range */
+	if (shader->shininess < 0.0)
+		shader->shininess = 0.0;
+	if (shader->shininess > 127.0)
+		shader->shininess = 127.0;
+}
+
+
+
+void PicoSetSurfaceData( picoSurface_t *surface, void *data )
+{
+	if( surface == NULL )
+		return;
+	surface->data = data;
+}
+
+
+
+void PicoSetSurfaceType( picoSurface_t *surface, picoSurfaceType_t type )
+{
+	if( surface == NULL )
+		return;
+	surface->type = type;
+}
+
+
+
+void PicoSetSurfaceName( picoSurface_t *surface, char *name )
+{
+	if( surface == NULL || name == NULL )
+		return;
+	if( surface->name != NULL )
+		_pico_free( surface->name );
+
+	surface->name = _pico_clone_alloc( name,-1 );
+}
+
+
+
+void PicoSetSurfaceShader( picoSurface_t *surface, picoShader_t *shader )
+{
+	if( surface == NULL )
+		return;
+	surface->shader = shader;
+}
+
+
+
+void PicoSetSurfaceXYZ( picoSurface_t *surface, int num, picoVec3_t xyz )
+{
+	if( surface == NULL || num < 0 || xyz == NULL )
+		return;
+	if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
+		return;
+	_pico_copy_vec( xyz, surface->xyz[ num ] );
+	if( surface->model != NULL )
+		_pico_expand_bounds( xyz, surface->model->mins, surface->model->maxs );
+}
+
+
+
+void PicoSetSurfaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
+{
+	if( surface == NULL || num < 0 || normal == NULL )
+		return;
+	if( !PicoAdjustSurface( surface, num + 1, 0, 0, 0, 0 ) )
+		return;
+	_pico_copy_vec( normal, surface->normal[ num ] );
+}
+
+
+
+void PicoSetSurfaceST( picoSurface_t *surface, int array, int num, picoVec2_t st )
+{
+	if( surface == NULL || num < 0 || st == NULL )
+		return;
+	if( !PicoAdjustSurface( surface, num + 1, array + 1, 0, 0, 0 ) )
+		return;
+	surface->st[ array ][ num ][ 0 ] = st[ 0 ];
+	surface->st[ array ][ num ][ 1 ] = st[ 1 ];
+}
+
+
+
+void PicoSetSurfaceColor( picoSurface_t *surface, int array, int num, picoColor_t color )
+{
+	if( surface == NULL || num < 0 || color == NULL )
+		return;
+	if( !PicoAdjustSurface( surface, num + 1, 0, array + 1, 0, 0 ) )
+		return;
+	surface->color[ array ][ num ][ 0 ] = color[ 0 ];
+	surface->color[ array ][ num ][ 1 ] = color[ 1 ];
+	surface->color[ array ][ num ][ 2 ] = color[ 2 ];
+	surface->color[ array ][ num ][ 3 ] = color[ 3 ];
+}
+
+
+
+void PicoSetSurfaceIndex( picoSurface_t *surface, int num, picoIndex_t index )
+{
+	if( surface == NULL || num < 0 )
+		return;
+	if( !PicoAdjustSurface( surface, 0, 0, 0, num + 1, 0 ) )
+		return;
+	surface->index[ num ] = index;
+}
+
+
+
+void PicoSetSurfaceIndexes( picoSurface_t *surface, int num, picoIndex_t *index, int count )
+{
+	if( num < 0 || index == NULL || count < 1 )
+		return;
+	if( !PicoAdjustSurface( surface, 0, 0, 0, num + count, 0 ) )
+		return;
+	memcpy( &surface->index[ num ], index, count * sizeof( surface->index[ num ] ) );
+}
+
+
+
+void PicoSetFaceNormal( picoSurface_t *surface, int num, picoVec3_t normal )
+{
+	if( surface == NULL || num < 0 || normal == NULL )
+		return;
+	if( !PicoAdjustSurface( surface, 0, 0, 0, 0, num + 1 ) )
+		return;
+	_pico_copy_vec( normal, surface->faceNormal[ num ] );
+}
+
+
+void PicoSetSurfaceSpecial( picoSurface_t *surface, int num, int special )
+{
+	if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
+		return;
+	surface->special[ num ] = special;
+}
+
+
+
+/*----------------------------------------------------------------------------
+  PicoGet*() Getter Functions
+----------------------------------------------------------------------------*/
+
+char *PicoGetModelName( picoModel_t *model )
+{
+	if( model == NULL )
+		return NULL;
+	if( model->name == NULL)
+		return (char*) "";
+	return model->name;
+}
+
+
+
+char *PicoGetModelFileName( picoModel_t *model )
+{
+	if( model == NULL )
+		return NULL;
+	if( model->fileName == NULL)
+		return (char*) "";
+	return model->fileName;
+}
+
+
+
+int PicoGetModelFrameNum( picoModel_t *model )
+{
+	if( model == NULL )
+		return 0;
+	return model->frameNum;
+}
+
+
+
+int PicoGetModelNumFrames( picoModel_t *model )
+{
+	if( model == NULL )
+		return 0;
+	return model->numFrames;
+}
+
+
+
+void *PicoGetModelData( picoModel_t *model )
+{
+	if( model == NULL )
+		return NULL;
+	return model->data;
+}
+
+
+
+int PicoGetModelNumShaders( picoModel_t *model )
+{
+	if( model == NULL )
+		return 0;
+	return model->numShaders;
+}
+
+
+
+picoShader_t *PicoGetModelShader( picoModel_t *model, int num )
+{
+	/* a few sanity checks */
+	if( model == NULL )
+		return NULL;
+	if( model->shader == NULL)
+		return NULL;
+	if( num < 0 || num >= model->numShaders )
+		return NULL;
+	
+	/* return the shader */
+	return model->shader[ num ];
+}
+
+
+
+int PicoGetModelNumSurfaces( picoModel_t *model )
+{
+	if( model == NULL )
+		return 0;
+	return model->numSurfaces;
+}
+
+
+
+picoSurface_t *PicoGetModelSurface( picoModel_t *model, int num )
+{
+	/* a few sanity checks */
+	if( model == NULL )
+		return NULL;
+	if( model->surface == NULL)
+		return NULL;
+	if( num < 0 || num >= model->numSurfaces )
+		return NULL;
+	
+	/* return the surface */
+	return model->surface[ num ];
+}
+
+
+
+int PicoGetModelTotalVertexes( picoModel_t *model )
+{
+	int		i, count;
+	
+	
+	if( model == NULL )
+		return 0;
+	if( model->surface == NULL )
+		return 0;
+	
+	count = 0;
+	for( i = 0; i < model->numSurfaces; i++ )
+		 count += PicoGetSurfaceNumVertexes( model->surface[ i ] );
+	
+	return count;
+}
+
+
+
+int PicoGetModelTotalIndexes( picoModel_t *model )
+{
+	int		i, count;
+	
+	
+	if( model == NULL )
+		return 0;
+	if( model->surface == NULL )
+		return 0;
+	
+	count = 0;
+	for( i = 0; i < model->numSurfaces; i++ )
+		 count += PicoGetSurfaceNumIndexes( model->surface[ i ] );
+	
+	return count;
+}
+
+
+
+char *PicoGetShaderName( picoShader_t *shader )
+{
+	if( shader == NULL )
+		return NULL;
+	if( shader->name == NULL)
+		return (char*) "";
+	return shader->name;
+}
+
+
+
+char *PicoGetShaderMapName( picoShader_t *shader )
+{
+	if( shader == NULL )
+		return NULL;
+	if( shader->mapName == NULL)
+		return (char*) "";
+	return shader->mapName;
+}
+
+
+
+picoByte_t *PicoGetShaderAmbientColor( picoShader_t *shader )
+{
+	if( shader == NULL )
+		return NULL;
+	return shader->ambientColor;
+}
+
+
+
+picoByte_t *PicoGetShaderDiffuseColor( picoShader_t *shader )
+{
+	if( shader == NULL )
+		return NULL;
+	return shader->diffuseColor;
+}
+
+
+
+picoByte_t *PicoGetShaderSpecularColor( picoShader_t *shader )
+{
+	if( shader == NULL )
+		return NULL;
+	return shader->specularColor;
+}
+
+
+
+float PicoGetShaderTransparency( picoShader_t *shader )
+{
+	if( shader == NULL )
+		return 0.0f;
+	return shader->transparency;
+}
+
+
+
+float PicoGetShaderShininess( picoShader_t *shader )
+{
+	if( shader == NULL )
+		return 0.0f;
+	return shader->shininess;
+}
+
+
+
+void *PicoGetSurfaceData( picoSurface_t *surface )
+{
+	if( surface == NULL )
+		return NULL;
+	return surface->data;
+}
+
+
+
+picoSurfaceType_t PicoGetSurfaceType( picoSurface_t *surface )
+{
+	if( surface == NULL )
+		return PICO_BAD;
+	return surface->type;
+}
+
+
+
+char *PicoGetSurfaceName( picoSurface_t *surface )
+{
+	if( surface == NULL )
+		return NULL;
+	if( surface->name == NULL )
+		return (char*) "";
+	return surface->name;
+}
+
+
+
+picoShader_t *PicoGetSurfaceShader( picoSurface_t *surface )
+{
+	if( surface == NULL )
+		return NULL;
+	return surface->shader;
+}
+
+
+
+int PicoGetSurfaceNumVertexes( picoSurface_t *surface )
+{
+	if( surface == NULL )
+		return 0;
+	return surface->numVertexes;
+}
+
+
+
+picoVec_t *PicoGetSurfaceXYZ( picoSurface_t *surface, int num )
+{
+	if( surface == NULL || num < 0 || num > surface->numVertexes )
+		return NULL;
+	return surface->xyz[ num ];
+}
+
+
+
+picoVec_t *PicoGetSurfaceNormal( picoSurface_t *surface, int num )
+{
+	if( surface == NULL || num < 0 || num > surface->numVertexes )
+		return NULL;
+	return surface->normal[ num ];
+}
+
+
+
+picoVec_t *PicoGetSurfaceST( picoSurface_t *surface, int array, int num  )
+{
+	if( surface == NULL || array < 0 || array > surface->numSTArrays || num < 0 || num > surface->numVertexes )
+		return NULL;
+	return surface->st[ array ][ num ];
+}
+
+
+
+picoByte_t *PicoGetSurfaceColor( picoSurface_t *surface, int array, int num )
+{
+	if( surface == NULL || array < 0 || array > surface->numColorArrays || num < 0 || num > surface->numVertexes )
+		return NULL;
+	return surface->color[ array ][ num ];
+}
+
+
+
+int PicoGetSurfaceNumIndexes( picoSurface_t *surface )
+{
+	if( surface == NULL )
+		return 0;
+	return surface->numIndexes;
+}
+
+
+
+picoIndex_t PicoGetSurfaceIndex( picoSurface_t *surface, int num )
+{
+	if( surface == NULL || num < 0 || num > surface->numIndexes )
+		return 0;
+	return surface->index[ num ];
+}
+
+
+
+picoIndex_t *PicoGetSurfaceIndexes( picoSurface_t *surface, int num )
+{
+	if( surface == NULL || num < 0 || num > surface->numIndexes )
+		return NULL;
+	return &surface->index[ num ];
+}
+
+
+picoVec_t *PicoGetFaceNormal( picoSurface_t *surface, int num )
+{
+	if( surface == NULL || num < 0 || num > surface->numFaceNormals )
+		return NULL;
+	return surface->faceNormal[ num ];
+}
+
+
+int PicoGetSurfaceSpecial( picoSurface_t *surface, int num )
+{
+	if( surface == NULL || num < 0 || num >= PICO_MAX_SPECIAL )
+		return 0;
+	return surface->special[ num ];
+}
+
+
+
+/* ----------------------------------------------------------------------------
+hashtable related functions
+---------------------------------------------------------------------------- */
+
+/* hashtable code for faster vertex lookups */
+//#define HASHTABLE_SIZE 32768 // 2048			/* power of 2, use & */
+#define HASHTABLE_SIZE 7919 // 32749 // 2039 	/* prime, use % */
+
+int PicoGetHashTableSize( void )
+{
+	return HASHTABLE_SIZE;
+}
+
+#define HASH_USE_EPSILON
+
+#ifdef HASH_USE_EPSILON
+#define HASH_XYZ_EPSILON					0.01f
+#define HASH_XYZ_EPSILONSPACE_MULTIPLIER	1.f / HASH_XYZ_EPSILON
+#define HASH_ST_EPSILON						0.0001f
+#define HASH_NORMAL_EPSILON					0.02f
+#endif
+
+unsigned int PicoVertexCoordGenerateHash( picoVec3_t xyz )
+{
+	unsigned int hash = 0;
+
+#ifndef HASH_USE_EPSILON
+	hash += ~(*((unsigned int*) &xyz[ 0 ]) << 15);
+	hash ^= (*((unsigned int*) &xyz[ 0 ]) >> 10);
+	hash += (*((unsigned int*) &xyz[ 1 ]) << 3);
+	hash ^= (*((unsigned int*) &xyz[ 1 ]) >> 6);
+	hash += ~(*((unsigned int*) &xyz[ 2 ]) << 11);
+	hash ^= (*((unsigned int*) &xyz[ 2 ]) >> 16);
+#else
+	picoVec3_t xyz_epsilonspace;
+
+	_pico_scale_vec( xyz, HASH_XYZ_EPSILONSPACE_MULTIPLIER, xyz_epsilonspace );
+	xyz_epsilonspace[ 0 ] = (float)floor(xyz_epsilonspace[ 0 ]);
+	xyz_epsilonspace[ 1 ] = (float)floor(xyz_epsilonspace[ 1 ]);
+	xyz_epsilonspace[ 2 ] = (float)floor(xyz_epsilonspace[ 2 ]);
+
+	hash += ~(*((unsigned int*) &xyz_epsilonspace[ 0 ]) << 15);
+	hash ^= (*((unsigned int*) &xyz_epsilonspace[ 0 ]) >> 10);
+	hash += (*((unsigned int*) &xyz_epsilonspace[ 1 ]) << 3);
+	hash ^= (*((unsigned int*) &xyz_epsilonspace[ 1 ]) >> 6);
+	hash += ~(*((unsigned int*) &xyz_epsilonspace[ 2 ]) << 11);
+	hash ^= (*((unsigned int*) &xyz_epsilonspace[ 2 ]) >> 16);
+#endif
+
+	//hash = hash & (HASHTABLE_SIZE-1);
+	hash = hash % (HASHTABLE_SIZE);
+	return hash;
+}
+
+picoVertexCombinationHash_t **PicoNewVertexCombinationHashTable( void )
+{
+	picoVertexCombinationHash_t	**hashTable = _pico_alloc( HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
+
+	memset( hashTable, 0, HASHTABLE_SIZE * sizeof(picoVertexCombinationHash_t*) );
+
+	return hashTable;
+}
+
+void PicoFreeVertexCombinationHashTable( picoVertexCombinationHash_t **hashTable )
+{
+	int							i;
+	picoVertexCombinationHash_t	*vertexCombinationHash;
+	picoVertexCombinationHash_t *nextVertexCombinationHash;
+
+	/* dummy check */
+	if (hashTable == NULL)
+		return;
+
+	for( i = 0; i < HASHTABLE_SIZE; i++ )
+	{
+		if (hashTable[ i ])
+		{
+			nextVertexCombinationHash = NULL;
+
+			for( vertexCombinationHash = hashTable[ i ]; vertexCombinationHash; vertexCombinationHash = nextVertexCombinationHash )
+			{
+				nextVertexCombinationHash = vertexCombinationHash->next;
+				if (vertexCombinationHash->data != NULL)
+				{
+					_pico_free( vertexCombinationHash->data );
+				}
+				_pico_free( vertexCombinationHash );
+			}
+		}
+	}
+
+	_pico_free( hashTable );
+}
+
+picoVertexCombinationHash_t *PicoFindVertexCombinationInHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color )
+{
+	unsigned int				hash;
+	picoVertexCombinationHash_t	*vertexCombinationHash;
+
+	/* dumy check */
+	if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
+		return NULL;
+
+	hash = PicoVertexCoordGenerateHash( xyz );
+
+	for( vertexCombinationHash = hashTable[ hash ]; vertexCombinationHash; vertexCombinationHash = vertexCombinationHash->next )
+	{
+#ifndef HASH_USE_EPSILON
+		/* check xyz */
+		if( (vertexCombinationHash->vcd.xyz[ 0 ] != xyz[ 0 ] || vertexCombinationHash->vcd.xyz[ 1 ] != xyz[ 1 ] || vertexCombinationHash->vcd.xyz[ 2 ] != xyz[ 2 ]) )
+			continue;
+
+		/* check normal */
+		if( (vertexCombinationHash->vcd.normal[ 0 ] != normal[ 0 ] || vertexCombinationHash->vcd.normal[ 1 ] != normal[ 1 ] || vertexCombinationHash->vcd.normal[ 2 ] != normal[ 2 ]) )
+			continue;
+		
+		/* check st */
+		if( vertexCombinationHash->vcd.st[ 0 ] != st[ 0 ] || vertexCombinationHash->vcd.st[ 1 ] != st[ 1 ] )
+			continue;
+#else
+		/* check xyz */
+		if( ( fabs(xyz[ 0 ] - vertexCombinationHash->vcd.xyz[ 0 ]) ) > HASH_XYZ_EPSILON ||
+			( fabs(xyz[ 1 ] - vertexCombinationHash->vcd.xyz[ 1 ]) ) > HASH_XYZ_EPSILON ||
+			( fabs(xyz[ 2 ] - vertexCombinationHash->vcd.xyz[ 2 ]) ) > HASH_XYZ_EPSILON )
+			continue;
+
+		/* check normal */
+		if( ( fabs(normal[ 0 ] - vertexCombinationHash->vcd.normal[ 0 ]) ) > HASH_NORMAL_EPSILON ||
+			( fabs(normal[ 1 ] - vertexCombinationHash->vcd.normal[ 1 ]) ) > HASH_NORMAL_EPSILON ||
+			( fabs(normal[ 2 ] - vertexCombinationHash->vcd.normal[ 2 ]) ) > HASH_NORMAL_EPSILON )
+			continue;
+		
+		/* check st */
+		if( ( fabs(st[ 0 ] - vertexCombinationHash->vcd.st[ 0 ]) ) > HASH_ST_EPSILON ||
+			( fabs(st[ 1 ] - vertexCombinationHash->vcd.st[ 1 ]) ) > HASH_ST_EPSILON )
+			continue;
+#endif
+
+		/* check color */
+		if( *((int*) vertexCombinationHash->vcd.color) != *((int*) color) )
+			continue;
+
+		/* gotcha */
+		return vertexCombinationHash;
+	}
+
+	return NULL;
+}
+
+picoVertexCombinationHash_t *PicoAddVertexCombinationToHashTable( picoVertexCombinationHash_t **hashTable, picoVec3_t xyz, picoVec3_t normal, picoVec3_t st, picoColor_t color, picoIndex_t index )
+{
+	unsigned int				hash;
+	picoVertexCombinationHash_t	*vertexCombinationHash;
+
+	/* dumy check */
+	if (hashTable == NULL || xyz == NULL || normal == NULL || st == NULL || color == NULL )
+		return NULL;
+
+	vertexCombinationHash = _pico_alloc( sizeof(picoVertexCombinationHash_t) );
+
+	if (!vertexCombinationHash)
+		return NULL;
+
+	hash = PicoVertexCoordGenerateHash( xyz );
+
+	_pico_copy_vec( xyz, vertexCombinationHash->vcd.xyz );
+	_pico_copy_vec( normal, vertexCombinationHash->vcd.normal );
+	_pico_copy_vec2( st, vertexCombinationHash->vcd.st );
+	_pico_copy_color( color, vertexCombinationHash->vcd.color );
+	vertexCombinationHash->index = index;
+	vertexCombinationHash->data = NULL;
+	vertexCombinationHash->next = hashTable[ hash ];
+	hashTable[ hash ] = vertexCombinationHash;
+
+	return vertexCombinationHash;
+}
+
+/* ----------------------------------------------------------------------------
+specialized routines
+---------------------------------------------------------------------------- */
+
+/*
+PicoFindSurfaceVertex()
+finds a vertex matching the set parameters
+fixme: needs non-naive algorithm
+*/
+
+int PicoFindSurfaceVertexNum( picoSurface_t *surface, picoVec3_t xyz, picoVec3_t normal, int numSTs, picoVec2_t *st, int numColors, picoColor_t *color )
+{
+	int		i, j;
+	
+	
+	/* dummy check */
+	if( surface == NULL || surface->numVertexes <= 0 )
+		return -1;
+	
+	/* walk vertex list */
+	for( i = 0; i < surface->numVertexes; i++ )
+	{
+		/* check xyz */
+		if( xyz != NULL && (surface->xyz[ i ][ 0 ] != xyz[ 0 ] || surface->xyz[ i ][ 1 ] != xyz[ 1 ] || surface->xyz[ i ][ 2 ] != xyz[ 2 ]) )
+			continue;
+		
+		/* check normal */
+		if( normal != NULL && (surface->normal[ i ][ 0 ] != normal[ 0 ] || surface->normal[ i ][ 1 ] != normal[ 1 ] || surface->normal[ i ][ 2 ] != normal[ 2 ]) )
+			continue;
+		
+		/* check st */
+		if( numSTs > 0 && st != NULL )
+		{
+			for( j = 0; j < numSTs; j++ )
+			{
+				if( surface->st[ j ][ i ][ 0 ] != st[ j ][ 0 ] || surface->st[ j ][ i ][ 1 ] != st[ j ][ 1 ] )
+					break;
+			}
+			if( j != numSTs )
+				continue;
+		}
+		
+		/* check color */
+		if( numColors > 0 && color != NULL )
+		{
+			for( j = 0; j < numSTs; j++ )
+			{
+				if( *((int*) surface->color[ j ]) != *((int*) color[ j ]) )
+					break;
+			}
+			if( j != numColors )
+				continue;
+		}
+		
+		/* vertex matches */
+		return i;
+	}
+	
+	/* nada */
+	return -1;
+}
+
+
+
+/*
+PicoFixSurfaceNormals()
+fixes broken normals (certain formats bork normals)
+*/
+
+#define MAX_NORMAL_VOTES		128
+#define EQUAL_NORMAL_EPSILON	0.01
+#define BAD_NORMAL_EPSILON		0.5
+
+void PicoFixSurfaceNormals( picoSurface_t *surface )
+{
+	int				i, j, k, a, b, c, numVotes, faceIndex;
+	picoVec3_t		votes[ MAX_NORMAL_VOTES ];
+	picoVec3_t		*normals, diff;
+	picoVec4_t		plane;
+	
+	
+	/* dummy check */
+	if( surface == NULL || surface->numVertexes == 0 )
+		return;
+	
+	/* fixme: handle other surface types */
+	if( surface->type != PICO_TRIANGLES )
+		return;
+	
+	/* allocate normal storage */
+	normals = _pico_alloc( surface->numVertexes * sizeof( *normals ) );
+	if( normals == NULL )
+	{
+		_pico_printf( PICO_ERROR, "PicoFixSurfaceNormals: Unable to allocate memory for temporary normal storage" );
+		return;
+	}
+	
+	/* zero it out */
+	memset( normals, 0, surface->numVertexes * sizeof( *normals ) );
+	
+	/* walk vertex list */
+	for( i = 0; i < surface->numVertexes; i++ )
+	{
+		/* zero out votes */
+		numVotes = 0;
+		
+		/* find all the triangles that reference this vertex */
+		for( j = 0, faceIndex = 0; j < surface->numIndexes; j += 3, faceIndex++ )
+		{
+			/* get triangle */
+			a = surface->index[ j ];
+			b = surface->index[ j + 1 ];
+			c = surface->index[ j + 2 ];
+			
+			/* ignore degenerate triangles */
+			if( a == b || b == c || c == a )
+				continue;
+			
+			/* ignore indexes out of range */
+			if( a < 0 || a >= surface->numVertexes ||
+				b < 0 || b >= surface->numVertexes ||
+				c < 0 || c >= surface->numVertexes )
+				continue;
+			
+			/* test triangle */
+			if( a == i || b == i || c == i )
+			{
+				/* if this surface has face normals */
+				if( surface->numFaceNormals && faceIndex < surface->numFaceNormals )
+				{
+					_pico_copy_vec( surface->faceNormal[ faceIndex ], plane );
+					if( plane[ 0 ] == 0.f && plane[ 1 ] == 0.f && plane[ 2 ] == 0.f )
+					{
+						/* if null normal, make plane from the 3 points */
+						if( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 )
+						{
+							continue;
+						}
+					}
+				}
+				/* make a plane from the 3 points */
+				else if( _pico_calc_plane( plane, surface->xyz[ a ], surface->xyz[ b ], surface->xyz[ c ] ) == 0 )
+				{
+					continue;
+				}
+
+				/* see if this normal has already been voted */
+				for( k = 0; k < numVotes; k++ )
+				{
+					_pico_subtract_vec( plane, votes[ k ], diff );
+					if( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
+						fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
+						fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON )
+						break;
+				}
+				
+				/* add a new vote? */
+				if( k == numVotes && numVotes < MAX_NORMAL_VOTES )
+				{
+					_pico_copy_vec( plane, votes[ numVotes ] );
+					numVotes++;
+				}
+			}
+		}
+		
+		/* tally votes */
+		if( numVotes > 0 )
+		{
+			/* create average normal */
+			_pico_zero_vec( normals[ i ] );
+			for( k = 0; k < numVotes; k++ )
+				_pico_add_vec( normals[ i ], votes[ k ], normals[ i ] );
+			
+			/* normalize it */
+			if( _pico_normalize_vec( normals[ i ] ) )
+			{
+				/* test against actual normal */
+				if( fabs( _pico_dot_vec( normals[ i ], surface->normal[ i ] ) - 1 ) > BAD_NORMAL_EPSILON )
+				{
+					//%	printf( "Normal %8d: (%f %f %f) -> (%f %f %f)\n", i,
+					//%		surface->normal[ i ][ 0 ], surface->normal[ i ][ 1 ], surface->normal[ i ][ 2 ],
+					//%		normals[ i ][ 0 ], normals[ i ][ 1 ], normals[ i ][ 2 ] );
+					_pico_copy_vec( normals[ i ], surface->normal[ i ] );
+				}
+			}
+		}
+	}
+	
+	/* free normal storage */
+	_pico_free( normals );
+}
+
+
+
+
+/*
+PicoRemapModel() - sea
+remaps model material/etc. information using the remappings
+contained in the given 'remapFile' (full path to the ascii file to open)
+returns 1 on success or 0 on error
+*/
+
+#define _prm_error_return \
+{ \
+	_pico_free_parser( p ); \
+	_pico_free_file( remapBuffer ); \
+	return 0; \
+}
+
+int PicoRemapModel( picoModel_t *model, char *remapFile )
+{
+	picoParser_t	*p;
+	picoByte_t		*remapBuffer;
+	int				remapBufSize;
+	
+	
+	/* sanity checks */
+	if( model == NULL || remapFile == NULL )
+		return 0;
+	
+	/* load remap file contents */
+	_pico_load_file( remapFile,&remapBuffer,&remapBufSize );
+	
+	/* check result */
+	if( remapBufSize == 0 )
+		return 1;	/* file is empty: no error */
+	if( remapBufSize < 0 )
+		return 0;	/* load failed: error */
+	
+	/* create a new pico parser */
+	p = _pico_new_parser( remapBuffer, remapBufSize );
+	if (p == NULL)
+	{
+		/* ram is really cheap nowadays... */
+		_prm_error_return;
+	}
+	
+	/* doo teh parse */
+	while( 1 )
+	{
+		/* get next token in remap file */
+		if (!_pico_parse( p,1 ))
+			break;
+
+		/* skip over c++ style comment lines */
+		if (!_pico_stricmp(p->token,"//"))
+		{
+			_pico_parse_skip_rest( p );
+			continue;
+		}
+		
+		/* block for quick material shader name remapping */
+		/* materials { "m" (=>|->|=) "s" } */
+		if( !_pico_stricmp(p->token, "materials" ) )
+		{
+			int level = 1;
+
+			/* check bracket */
+			if (!_pico_parse_check( p,1,"{" ))
+				_prm_error_return;
+
+			/* process assignments */
+			while( 1 )
+			{
+				picoShader_t	*shader;
+				char			*materialName;
+				
+				
+				/* get material name */
+				if (_pico_parse( p,1 ) == NULL) break;
+				if (!strlen(p->token)) continue;
+				materialName = _pico_clone_alloc( p->token,-1 );
+				if (materialName == NULL)
+					_prm_error_return;
+
+				/* handle levels */
+				if (p->token[0] == '{') level++;
+				if (p->token[0] == '}') level--;
+				if (!level) break;
+
+				/* get next token (assignment token or shader name) */
+				if (!_pico_parse( p,0 ))
+				{
+					_pico_free( materialName );
+					_prm_error_return;
+				}
+				/* skip assignment token (if present) */
+				if (!strcmp(p->token,"=>") ||
+					!strcmp(p->token,"->") ||
+					!strcmp(p->token,"="))
+				{
+					/* simply grab the next token */
+					if (!_pico_parse( p,0 ))
+					{
+						_pico_free( materialName );
+						_prm_error_return;
+					}
+				}
+				/* try to find material by name */
+				shader = PicoFindShader( model,materialName,0 );
+
+				/* we've found a material matching the name */
+				if (shader != NULL)
+				{
+					PicoSetShaderName( shader,p->token );
+				}
+				/* free memory used by material name */
+				_pico_free( materialName );
+
+				/* skip rest */
+				_pico_parse_skip_rest( p );
+			}
+		}
+		/* block for detailed single material remappings */
+		/* materials[ "m" ] { key data... } */
+		else if (!_pico_stricmp(p->token,"materials["))
+		{
+			picoShader_t *shader;
+			char *tempMaterialName;
+			int level = 1;
+
+			/* get material name */
+			if (!_pico_parse( p,0 ))
+				_prm_error_return;
+
+			/* temporary copy of material name */
+			tempMaterialName = _pico_clone_alloc( p->token,-1 );
+			if (tempMaterialName == NULL)
+				_prm_error_return;
+
+			/* check square closing bracket */
+			if (!_pico_parse_check( p,0,"]" ))
+				_prm_error_return;			
+
+			/* try to find material by name */
+			shader = PicoFindShader( model,tempMaterialName,0 );
+
+			/* free memory used by temporary material name */
+			_pico_free( tempMaterialName );
+
+			/* we haven't found a material matching the name */
+			/* so we simply skip the braced section now and */
+			/* continue parsing with the next main token */
+			if (shader == NULL)
+			{
+				_pico_parse_skip_braced( p );
+				continue;
+			}
+			/* check opening bracket */
+			if (!_pico_parse_check( p,1,"{" ))
+				_prm_error_return;
+
+			/* process material info keys */
+			while( 1 )
+			{
+				/* get key name */
+				if (_pico_parse( p,1 ) == NULL) break;
+				if (!strlen(p->token)) continue;
+
+				/* handle levels */
+				if (p->token[0] == '{') level++;
+				if (p->token[0] == '}') level--;
+				if (!level) break;
+
+				/* remap shader name */
+				if (!_pico_stricmp(p->token,"shader"))
+				{
+					if (!_pico_parse( p,0 )) _prm_error_return;
+					PicoSetShaderName( shader,p->token );
+				}
+				/* remap shader map name */
+				else if (!_pico_stricmp(p->token,"mapname"))
+				{
+					if (!_pico_parse( p,0 )) _prm_error_return;
+					PicoSetShaderMapName( shader,p->token );
+				}
+				/* remap shader's ambient color */
+				else if (!_pico_stricmp(p->token,"ambient"))
+				{
+					picoColor_t color;
+					picoVec3_t  v;
+
+					/* get vector from parser */
+					if (!_pico_parse_vec( p,v )) _prm_error_return;
+
+					/* store as color */
+					color[ 0 ] = (picoByte_t)v[ 0 ];
+					color[ 1 ] = (picoByte_t)v[ 1 ];
+					color[ 2 ] = (picoByte_t)v[ 2 ];
+
+					/* set new ambient color */
+					PicoSetShaderAmbientColor( shader,color );
+				}
+				/* remap shader's diffuse color */
+				else if (!_pico_stricmp(p->token,"diffuse"))
+				{
+					picoColor_t color;
+					picoVec3_t  v;
+
+					/* get vector from parser */
+					if (!_pico_parse_vec( p,v )) _prm_error_return;
+
+					/* store as color */
+					color[ 0 ] = (picoByte_t)v[ 0 ];
+					color[ 1 ] = (picoByte_t)v[ 1 ];
+					color[ 2 ] = (picoByte_t)v[ 2 ];
+
+					/* set new ambient color */
+					PicoSetShaderDiffuseColor( shader,color );
+				}
+				/* remap shader's specular color */
+				else if (!_pico_stricmp(p->token,"specular"))
+				{
+					picoColor_t color;
+					picoVec3_t  v;
+
+					/* get vector from parser */
+					if (!_pico_parse_vec( p,v )) _prm_error_return;
+
+					/* store as color */
+					color[ 0 ] = (picoByte_t)v[ 0 ];
+					color[ 1 ] = (picoByte_t)v[ 1 ];
+					color[ 2 ] = (picoByte_t)v[ 2 ];
+
+					/* set new ambient color */
+					PicoSetShaderSpecularColor( shader,color );
+				}
+				/* skip rest */
+				_pico_parse_skip_rest( p );
+			}
+		}
+		/* end 'materials[' */
+	}
+	
+	/* free both parser and file buffer */
+	_pico_free_parser( p );
+	_pico_free_file( remapBuffer );
+
+	/* return with success */
+	return 1;
+}
+
+
+/*
+PicoAddTriangleToModel() - jhefty
+A nice way to add individual triangles to the model.
+Chooses an appropriate surface based on the shader, or adds a new surface if necessary
+*/
+
+void PicoAddTriangleToModel( picoModel_t *model, picoVec3_t** xyz, picoVec3_t** normals, 
+							int numSTs, picoVec2_t **st, int numColors, picoColor_t **colors,
+							picoShader_t* shader )
+{
+	int i,j;
+	int vertDataIndex;
+	picoSurface_t* workSurface = NULL;
+
+	/* see if a surface already has the shader */
+	for ( i = 0 ; i < model->numSurfaces ; i++ )
+	{
+		workSurface = model->surface[i];
+		if ( workSurface->shader == shader )
+		{			
+			break;
+		}
+	}
+
+	/* no surface uses this shader yet, so create a new surface */
+	if ( !workSurface || i >=model->numSurfaces )
+	{
+		/* create a new surface in the model for the unique shader */
+		workSurface = PicoNewSurface(model);
+		if ( !workSurface )
+		{
+			_pico_printf ( PICO_ERROR , "Could not allocate a new surface!\n" );
+			return;
+		}
+
+		/* do surface setup */
+		PicoSetSurfaceType( workSurface, PICO_TRIANGLES );
+		PicoSetSurfaceName( workSurface, shader->name );
+		PicoSetSurfaceShader( workSurface, shader );
+	}
+
+	/* add the triangle data to the surface */
+	for ( i = 0 ; i < 3 ; i++ )	
+	{
+		/* get the next free spot in the index array */
+		int newVertIndex = PicoGetSurfaceNumIndexes ( workSurface );
+
+		/* get the index of the vertex that we're going to store at newVertIndex */
+		vertDataIndex = PicoFindSurfaceVertexNum ( workSurface , *xyz[i] , *normals[i] , numSTs , st[i] , numColors , colors[i]);
+
+		/* the vertex wasn't found, so create a new vertex in the pool from the data we have */
+		if ( vertDataIndex == -1 )
+		{			
+			/* find the next spot for a new vertex */
+			vertDataIndex = PicoGetSurfaceNumVertexes ( workSurface );			
+
+			/* assign the data to it */
+			PicoSetSurfaceXYZ ( workSurface ,vertDataIndex , *xyz[i] );
+			PicoSetSurfaceNormal ( workSurface , vertDataIndex , *normals[i] );			
+
+			/* make sure to copy over all available ST's and colors for the vertex */
+			for ( j = 0 ; j < numColors ; j++ )
+			{
+				PicoSetSurfaceColor( workSurface , j , vertDataIndex , colors[i][j] );
+			}
+			for ( j = 0 ; j < numSTs ; j++ )
+			{
+				PicoSetSurfaceST ( workSurface , j , vertDataIndex , st[i][j] );
+			}
+		}
+
+		/* add this vertex to the triangle */		
+		PicoSetSurfaceIndex ( workSurface , newVertIndex , vertDataIndex );
+	}	
+}
diff --git a/libs/picomodel/picomodules.c b/libs/picomodel/picomodules.c
index 060912f5..add477b5 100644
--- a/libs/picomodel/picomodules.c
+++ b/libs/picomodel/picomodules.c
@@ -1,92 +1,92 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PICOMODULES_C
-
-
-
-/* dependencies */
-#include "picointernal.h"
-
-
-
-/* external modules */
-extern const picoModule_t picoModuleMD3;
-extern const picoModule_t picoModule3DS;
-extern const picoModule_t picoModuleASE;
-extern const picoModule_t picoModuleOBJ;
-extern const picoModule_t picoModuleMS3D;
-extern const picoModule_t picoModuleMDC;
-extern const picoModule_t picoModuleMD2;
-extern const picoModule_t picoModuleFM;
-extern const picoModule_t picoModuleLWO;
-
-
-
-/* list of all supported file format modules */
-const picoModule_t *picoModules[] =
-{
-	&picoModuleMD3,		/* quake3 arena md3 */
-	&picoModule3DS,		/* autodesk 3ds */
-	&picoModuleASE,		/* autodesk ase */
-	&picoModuleMS3D,	/* milkshape3d */
-	&picoModuleMDC,		/* return to castle wolfenstein mdc */
-	&picoModuleMD2,		/* quake2 md2 */
-	&picoModuleFM,		/* heretic2 fm */
-	&picoModuleOBJ,		/* wavefront object */
-	&picoModuleLWO,		/* lightwave object */
-	NULL				/* arnold */
-};
-
-
-
-/*
-PicoModuleList()
-returns a pointer to the module list and optionally stores
-the number of supported modules in 'numModules'. Note that
-this param can be NULL when the count is not needed.
-*/
-
-const picoModule_t **PicoModuleList( int *numModules )
-{
-	/* get module count */
-	if( numModules != NULL )
-		for( (*numModules) = 0; picoModules[ *numModules ] != NULL; (*numModules)++ );
-	
-	/* return list of modules */
-	return (const picoModule_t**) picoModules;
-}
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PICOMODULES_C
+
+
+
+/* dependencies */
+#include "picointernal.h"
+
+
+
+/* external modules */
+extern const picoModule_t picoModuleMD3;
+extern const picoModule_t picoModule3DS;
+extern const picoModule_t picoModuleASE;
+extern const picoModule_t picoModuleOBJ;
+extern const picoModule_t picoModuleMS3D;
+extern const picoModule_t picoModuleMDC;
+extern const picoModule_t picoModuleMD2;
+extern const picoModule_t picoModuleFM;
+extern const picoModule_t picoModuleLWO;
+
+
+
+/* list of all supported file format modules */
+const picoModule_t *picoModules[] =
+{
+	&picoModuleMD3,		/* quake3 arena md3 */
+	&picoModule3DS,		/* autodesk 3ds */
+	&picoModuleASE,		/* autodesk ase */
+	&picoModuleMS3D,	/* milkshape3d */
+	&picoModuleMDC,		/* return to castle wolfenstein mdc */
+	&picoModuleMD2,		/* quake2 md2 */
+	&picoModuleFM,		/* heretic2 fm */
+	&picoModuleOBJ,		/* wavefront object */
+	&picoModuleLWO,		/* lightwave object */
+	NULL				/* arnold */
+};
+
+
+
+/*
+PicoModuleList()
+returns a pointer to the module list and optionally stores
+the number of supported modules in 'numModules'. Note that
+this param can be NULL when the count is not needed.
+*/
+
+const picoModule_t **PicoModuleList( int *numModules )
+{
+	/* get module count */
+	if( numModules != NULL )
+		for( (*numModules) = 0; picoModules[ *numModules ] != NULL; (*numModules)++ );
+	
+	/* return list of modules */
+	return (const picoModule_t**) picoModules;
+}
diff --git a/libs/picomodel/pm_3ds.c b/libs/picomodel/pm_3ds.c
index 1ad95b1c..0f2b41f7 100644
--- a/libs/picomodel/pm_3ds.c
+++ b/libs/picomodel/pm_3ds.c
@@ -1,771 +1,771 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PM_3DS_C
-
-/* dependencies */
-#include "picointernal.h"
-
-/* ydnar */
-static picoColor_t white = { 255,255,255,255 };
-
-/* remarks:
- * - 3ds file version is stored in pico special field 0 on load (ydnar: removed)
- * todo:
- * - sometimes there is one unnamed surface 0 having 0 verts as
- *   well as 0 faces. this error occurs since pm 0.6 (ydnar?)
- */
-/* uncomment when debugging this module */
-/* #define DEBUG_PM_3DS
-#define DEBUG_PM_3DS_EX */
-
-/* structure holding persistent 3ds loader specific data used */
-/* to store formerly static vars to keep the module reentrant */
-/* safe. put everything that needs to be static in here. */
-typedef struct S3dsLoaderPers
-{
-	picoModel_t	   *model;			/* ptr to output model */
-	picoSurface_t  *surface;		/* ptr to current surface */
-	picoShader_t   *shader;			/* ptr to current shader */
-	picoByte_t	   *bufptr;			/* ptr to raw data */
-	char		   *basename;		/* ptr to model base name (eg. jeep) */
-	int	 			cofs;
-	int	 			maxofs;
-}
-T3dsLoaderPers;
-
-/* 3ds chunk types that we use */
-enum {
-    /* primary chunk */
-    CHUNK_MAIN				= 0x4D4D,
-
-	/* main chunks */
-	CHUNK_VERSION       	= 0x0002,
-	CHUNK_EDITOR_CONFIG		= 0x3D3E,
-	CHUNK_EDITOR_DATA   	= 0x3D3D,
-	CHUNK_KEYFRAME_DATA		= 0xB000,
-
-	/* editor data sub chunks */
-	CHUNK_MATERIAL			= 0xAFFF,
-	CHUNK_OBJECT        	= 0x4000,
-
-	/* material sub chunks */
-	CHUNK_MATNAME			= 0xA000,
-	CHUNK_MATDIFFUSE		= 0xA020,
-	CHUNK_MATMAP			= 0xA200,
-	CHUNK_MATMAPFILE		= 0xA300,
-
-	/* lets us know we're reading a new object */
-	CHUNK_OBJECT_MESH		= 0x4100,
-
-	/* object mesh sub chunks */
-	CHUNK_OBJECT_VERTICES	= 0x4110,
-	CHUNK_OBJECT_FACES		= 0x4120,
-	CHUNK_OBJECT_MATERIAL	= 0x4130,
-	CHUNK_OBJECT_UV			= 0x4140,
-};
-#ifdef DEBUG_PM_3DS
-static struct
-{
-	int 	id;
-	char   *name;
-}
-debugChunkNames[] =
-{
-	{ CHUNK_MAIN			, "CHUNK_MAIN" 				},
-	{ CHUNK_VERSION			, "CHUNK_VERSION" 			},
-	{ CHUNK_EDITOR_CONFIG	, "CHUNK_EDITOR_CONFIG" 	},
-	{ CHUNK_EDITOR_DATA		, "CHUNK_EDITOR_DATA" 		},
-	{ CHUNK_KEYFRAME_DATA	, "CHUNK_KEYFRAME_DATA" 	},
-	{ CHUNK_MATERIAL		, "CHUNK_MATERIAL"			},
-	{ CHUNK_OBJECT			, "CHUNK_OBJECT"			},
-	{ CHUNK_MATNAME			, "CHUNK_MATNAME"			},
-	{ CHUNK_MATDIFFUSE		, "CHUNK_MATDIFFUSE"		},
-	{ CHUNK_MATMAP			, "CHUNK_MATMAP"			},
-	{ CHUNK_MATMAPFILE		, "CHUNK_MATMAPFILE"		},
-	{ CHUNK_OBJECT_MESH		, "CHUNK_OBJECT_MESH"		},
-	{ CHUNK_OBJECT_VERTICES	, "CHUNK_OBJECT_VERTICES"	},
-	{ CHUNK_OBJECT_FACES	, "CHUNK_OBJECT_FACES"		},
-	{ CHUNK_OBJECT_MATERIAL	, "CHUNK_OBJECT_MATERIAL"	},
-	{ CHUNK_OBJECT_UV		, "CHUNK_OBJECT_UV"			},
-	{ 0						,  NULL						}
-};
-static char *DebugGetChunkName (int id)
-{
-	int i,max;	/* imax? ;) */
-	max = sizeof(debugChunkNames) / sizeof(debugChunkNames[0]);
-
-	for (i=0; i<max; i++)
-	{
-		if (debugChunkNames[i].id == id)
-		{
-			/* gaynux update -sea */
-			return _pico_strlwr( debugChunkNames[i].name );
-		}
-	}
-	return "chunk_unknown";
-}
-#endif /*DEBUG_PM_3DS*/
-
-/* this funky loader needs byte alignment */
-#pragma pack(push, 1)
-
-typedef struct S3dsIndices
-{
-	unsigned short 	a,b,c;
-	unsigned short 	visible;
-}
-T3dsIndices;
-
-typedef struct S3dsChunk
-{
-	unsigned short 	id;
-	unsigned int	len;
-}
-T3dsChunk;
-
-/* restore previous data alignment */
-#pragma pack(pop)
-
-/* _3ds_canload:
- *  validates an autodesk 3ds model file.
- */
-static int _3ds_canload( PM_PARAMS_CANLOAD )
-{
-	T3dsChunk *chunk;
-
-	/* to keep the compiler happy */
-	*fileName = *fileName;
-
-	/* sanity check */
-	if (bufSize < sizeof(T3dsChunk))
-		return PICO_PMV_ERROR_SIZE;
-
-	/* get pointer to 3ds header chunk */
-	chunk = (T3dsChunk *)buffer;
-
-	/* check data length */
-	if (bufSize < _pico_little_long(chunk->len))
-		return PICO_PMV_ERROR_SIZE;
-
-	/* check 3ds magic */
-	if (_pico_little_short(chunk->id) != CHUNK_MAIN)
-		return PICO_PMV_ERROR_IDENT;
-
-	/* file seems to be a valid 3ds */
-	return PICO_PMV_OK;
-}
-
-static T3dsChunk *GetChunk (T3dsLoaderPers *pers)
-{
-	T3dsChunk *chunk;
-
-	/* sanity check */
-	if (pers->cofs > pers->maxofs) return 0;
-
-#ifdef DEBUG_PM_3DS
-/*	printf("GetChunk: pers->cofs %x\n",pers->cofs); */
-#endif
-	/* fill in pointer to chunk */
-	chunk = (T3dsChunk *)&pers->bufptr[ pers->cofs ];
-	if (!chunk) return NULL;
-
-	chunk->id  = _pico_little_short(chunk->id );
-	chunk->len = _pico_little_long (chunk->len);
-
-	/* advance in buffer */
-	pers->cofs += sizeof(T3dsChunk);
-
-	/* this means yay */
-	return chunk;
-}
-
-static int GetASCIIZ (T3dsLoaderPers *pers, char *dest, int max)
-{
-	int pos = 0;
-	int ch;
-
-	for (;;)
-	{
-		ch = pers->bufptr[ pers->cofs++ ];
-		if (ch == '\0') break;
-		if (pers->cofs >= pers->maxofs)
-		{
-			dest[ pos ] = '\0';
-			return 0;
-		}
-		dest[ pos++ ] = ch;
-		if (pos >= max) break;
-	}
-	dest[ pos ] = '\0';
-	return 1;
-}
-
-static picoByte_t GetByte (T3dsLoaderPers *pers)
-{
-	picoByte_t *value;
-
-	/* sanity check */
-	if (pers->cofs > pers->maxofs) return 0;
-
-	/* get and return value */
-	value = (picoByte_t *)(pers->bufptr + pers->cofs);
-	pers->cofs += 1;
-	return *value;
-}
-
-static int GetWord (T3dsLoaderPers *pers)
-{
-	unsigned short *value;
-
-	/* sanity check */
-	if (pers->cofs > pers->maxofs) return 0;
-
-	/* get and return value */
-	value = (unsigned short *)(pers->bufptr + pers->cofs);
-	pers->cofs += 2;
-	return _pico_little_short(*value);
-}
-
-static float GetFloat (T3dsLoaderPers *pers)
-{
-	float *value;
-
-	/* sanity check */
-	if (pers->cofs > pers->maxofs) return 0;
-
-	/* get and return value */
-	value = (float *)(pers->bufptr + pers->cofs);
-	pers->cofs += 4;
-	return _pico_little_float(*value);
-}
-
-static int GetMeshVertices (T3dsLoaderPers *pers)
-{
-	int numVerts;
-	int i;
-
-	/* get number of verts for this surface */
-	numVerts = GetWord(pers);
-
-#ifdef DEBUG_PM_3DS
-	printf("GetMeshVertices: numverts %d\n",numVerts);
-#endif
-	/* read in vertices for current surface */
-	for (i=0; i<numVerts; i++)
-	{
-		picoVec3_t v;
-		v[0] = GetFloat( pers );
-		v[1] = GetFloat( pers );	/* ydnar: unflipped */
-		v[2] = GetFloat( pers );	/* ydnar: unflipped and negated */
-		
-		/* add current vertex */
-		PicoSetSurfaceXYZ( pers->surface,i,v );
-		PicoSetSurfaceColor( pers->surface,0,i,white );	/* ydnar */
-
-#ifdef DEBUG_PM_3DS_EX
-		printf("Vertex: x: %f y: %f z: %f\n",v[0],v[1],v[2]);
-#endif
-	}
-	/* success (no errors occured) */
-	return 1;
-}
-
-static int GetMeshFaces (T3dsLoaderPers *pers)
-{
-	int numFaces;
-	int i;
-
-	/* get number of faces for this surface */
-	numFaces = GetWord(pers);
-
-#ifdef DEBUG_PM_3DS
-	printf("GetMeshFaces: numfaces %d\n",numFaces);
-#endif
-	/* read in vertex indices for current surface */
-	for (i=0; i<numFaces; i++)
-	{
-		/* remember, we only need 3 of 4 values read in for each */
-		/* face. the 4th value is a vis flag for 3dsmax which is */
-		/* being ignored by us here */
-		T3dsIndices face;
-		face.a		 = GetWord(pers);
-		face.c		 = GetWord(pers);	/* ydnar: flipped order */
-		face.b		 = GetWord(pers);	/* ydnar: flipped order */
-		face.visible = GetWord(pers);
-
-		/* copy indexes */
-		PicoSetSurfaceIndex( pers->surface, (i * 3 + 0), (picoIndex_t)face.a );
-		PicoSetSurfaceIndex( pers->surface, (i * 3 + 1), (picoIndex_t)face.b );
-		PicoSetSurfaceIndex( pers->surface, (i * 3 + 2), (picoIndex_t)face.c );
-
-#ifdef DEBUG_PM_3DS_EX
-		printf("Face: a: %d b: %d c: %d (%d)\n",face.a,face.b,face.c,face.visible);
-#endif
-	}
-	/* success (no errors occured) */
-	return 1;
-}
-
-static int GetMeshTexCoords (T3dsLoaderPers *pers)
-{
-	int numTexCoords;
-	int i;
-
-	/* get number of uv coords for this surface */
-	numTexCoords = GetWord(pers);
-
-#ifdef DEBUG_PM_3DS
-	printf("GetMeshTexCoords: numcoords %d\n",numTexCoords);
-#endif
-	/* read in uv coords for current surface */
-	for (i=0; i<numTexCoords; i++)
-	{
-		picoVec2_t uv;
-		uv[0] =  GetFloat( pers );
-		uv[1] = -GetFloat( pers );	/* ydnar: we use origin at bottom */
-
-		/* to make sure we don't mess up memory */
-		if (pers->surface == NULL)
-			continue;
-		
-		/* add current uv */
-		PicoSetSurfaceST( pers->surface,0,i,uv );
-
-#ifdef DEBUG_PM_3DS_EX
-		printf("u: %f v: %f\n",uv[0],uv[1]);
-#endif
-	}
-	/* success (no errors occured) */
-	return 1;
-}
-
-static int GetMeshShader (T3dsLoaderPers *pers)
-{
-	char shaderName[255] = { 0 };
-	picoShader_t  *shader;
-	int  numSharedVerts;
-	int  setShaderName = 0;
-	int  i;
-	
-	/* the shader is either the color or the texture map of the */
-	/* object. it can also hold other information like the brightness, */
-	/* shine, etc. stuff we don't really care about. we just want the */
-	/* color, or the texture map file name really */
-
-	/* get in the shader name */
-	if (!GetASCIIZ(pers,shaderName,sizeof(shaderName)))
-		return 0;
-
-	/* now that we have the shader name we need to go through all of */
-	/* the shaders and check the name against each shader. when we */
-	/* find a shader in our shader list that matches this name we */
-	/* just read in, then we assign the shader's id of the object to */
-	/* that shader */
-
-	/* get shader id for shader name */
-	shader = PicoFindShader( pers->model, shaderName, 1 );
-
-	/* we've found a matching shader */
-	if ((shader != NULL) && pers->surface)
-	{
-		char  mapName[1024+1];
-		char *mapNamePtr;
-		memset( mapName,0,sizeof(mapName) );
-
-		/* get ptr to shader's map name */
-		mapNamePtr = PicoGetShaderMapName( shader );
-
-		/* we have a valid map name ptr */
-		if (mapNamePtr != NULL)
-		{
-			char  temp[128];
-			char *name;
-
-			/* copy map name to local buffer */
-			strcpy( mapName,mapNamePtr );
-
-			/* extract file name */
-			name = _pico_nopath( mapName );
-			strncpy( temp, name, sizeof(temp) );
-
-			/* remove file extension */
-			/* name = _pico_setfext( name,"" ); */
-
-			/* assign default name if no name available */
-			if (strlen(temp) < 1)
-				strcpy(temp,pers->basename);
-
-			/* build shader name */
-			_pico_strlwr( temp ); /* gaynux update -sea */
-			sprintf( mapName,"models/mapobjects/%s/%s",pers->basename,temp );
-
-			/* set shader name */
-			/* PicoSetShaderName( shader,mapName ); */	/* ydnar: this will screw up the named shader */
-
-			/* set surface's shader index */
-			PicoSetSurfaceShader( pers->surface, shader );
-
-			setShaderName = 1;
-		}
-	}
-	/* we didn't set a shader name; throw out warning */
-	if (!setShaderName)
-	{
-		_pico_printf( PICO_WARNING,"3DS mesh is missing shader name");
-	}
-	/* we don't process the list of shared vertices here; there is a */
-	/* short int that gives the number of faces of the mesh concerned */
-	/* by this shader, then there is the list itself of these faces. */
-	/* 0000 means the first face of the (4120) face list */
-
-	/* get number of shared verts */
-	numSharedVerts = GetWord(pers);
-
-#ifdef DEBUG_PM_3DS
-	printf("GetMeshShader: uses shader '%s' (nsv %d)\n",shaderName,numSharedVerts);
-#endif
-	/* skip list of shared verts */
-	for (i=0; i<numSharedVerts; i++)
-	{
-		GetWord(pers);
-	}
-	/* success (no errors occured) */
-	return 1;
-}
-
-static int GetDiffuseColor (T3dsLoaderPers *pers)
-{
-	/* todo: support all 3ds specific color formats; */
-	/* that means: rgb,tru,trug,rgbg */
-
-	/* get rgb color (range 0..255; 3 bytes) */
-	picoColor_t color;
-
-	color[0] = GetByte(pers);
-	color[1] = GetByte(pers);
-	color[2] = GetByte(pers);
-	color[3] = 255;
-
-	/* store this as the current shader's diffuse color */
-	if( pers->shader )
-	{
-		PicoSetShaderDiffuseColor( pers->shader,color );
-	}
-#ifdef DEBUG_PM_3DS
-	printf("GetDiffuseColor: %d %d %d\n",color[0],color[1],color[2]);
-#endif
-	/* success (no errors occured) */
-	return 1;
-}
-
-static int DoNextEditorDataChunk (T3dsLoaderPers *pers, long endofs)
-{
-	T3dsChunk *chunk;
-
-#ifdef DEBUG_PM_3DS_EX
-	printf("DoNextEditorDataChunk: endofs %d\n",endofs);
-#endif
-	while (pers->cofs < endofs)
-	{
-		long nextofs = pers->cofs;
-		if ((chunk = GetChunk(pers)) == NULL) return 0;
-		if (!chunk->len) return 0;
-		nextofs += chunk->len;
-
-#ifdef DEBUG_PM_3DS_EX
-		printf("Chunk %04x (%s), len %d pers->cofs %x\n",chunk->id,DebugGetChunkName(chunk->id),chunk->len,pers->cofs);
-#endif
-		/*** meshes ***/
-		if (chunk->id == CHUNK_OBJECT)
-		{
-			picoSurface_t *surface;
-			char surfaceName[ 0xff ] = { 0 };
-
-			/* read in surface name */
-			if( !GetASCIIZ(pers,surfaceName,sizeof(surfaceName)) )
-				return 0; /* this is bad */
-
-//PicoGetSurfaceName
-			/* ignore NULL name surfaces */
-//			if( surfaceName
-
-			/* allocate a pico surface */
-			surface = PicoNewSurface( pers->model );
-			if( surface == NULL )
-			{
-				pers->surface = NULL;
-				return 0; /* this is bad too */
-			}
-			/* assign ptr to current surface */
-			pers->surface = surface;
-
-			/* 3ds models surfaces are all triangle meshes */
-			PicoSetSurfaceType( pers->surface,PICO_TRIANGLES );
-
-			/* set surface name */
-			PicoSetSurfaceName( pers->surface,surfaceName );
-
-			/* continue mess with object's sub chunks */
-			DoNextEditorDataChunk(pers,nextofs);
-			continue;
-		}
-		if (chunk->id == CHUNK_OBJECT_MESH)
-		{
-			/* continue mess with mesh's sub chunks */
-			if (!DoNextEditorDataChunk(pers,nextofs)) return 0;
-			continue;
-		}
-		if (chunk->id == CHUNK_OBJECT_VERTICES)
-		{
-			if (!GetMeshVertices(pers)) return 0;
-			continue;
-		}
-		if (chunk->id == CHUNK_OBJECT_FACES)
-		{
-			if (!GetMeshFaces(pers)) return 0;
-			continue;
-		}
-		if (chunk->id == CHUNK_OBJECT_UV)
-		{
-			if (!GetMeshTexCoords(pers)) return 0;
-			continue;
-		}
-		if (chunk->id == CHUNK_OBJECT_MATERIAL)
-		{
-			if (!GetMeshShader(pers)) return 0;
-			continue;
-		}
-		/*** materials ***/
-		if (chunk->id == CHUNK_MATERIAL)
-		{
-			/* new shader specific things should be */
-			/* initialized right here */
-			picoShader_t *shader;
-
-			/* allocate a pico shader */
-			shader = PicoNewShader( pers->model );	/* ydnar */
-			if( shader == NULL )
-			{
-				pers->shader = NULL;
-				return 0; /* this is bad too */
-			}
-			
-			/* assign ptr to current shader */
-			pers->shader = shader;
-
-			/* continue and process the material's sub chunks */
-			DoNextEditorDataChunk(pers,nextofs);
-			continue;
-		}
-		if (chunk->id == CHUNK_MATNAME)
-		{
-			/* new material's names should be stored here. note that */
-			/* GetMeshMaterial returns the name of the material that */
-			/* is used by the mesh. new material names are set HERE. */
-			/* but for now we skip the new material's name ... */
-			if (pers->shader)
-			{
-				char *name = (char *)(pers->bufptr + pers->cofs);
-				PicoSetShaderName( pers->shader,name );
-#ifdef DEBUG_PM_3DS
-				printf("NewShader: '%s'\n",name);
-#endif
-			}
-		}
-		if (chunk->id == CHUNK_MATDIFFUSE)
-		{
-			/* todo: color for last inserted new material should be */
-			/* stored somewhere by GetDiffuseColor */
-			if (!GetDiffuseColor(pers)) return 0;
-
-			/* rest of chunk is skipped here */
-		}
-		if (chunk->id == CHUNK_MATMAP)
-		{
-			/* continue and process the material map sub chunks */
-			DoNextEditorDataChunk(pers,nextofs);
-			continue;
-		}
-		if (chunk->id == CHUNK_MATMAPFILE)
-		{
-			/* map file name for last inserted new material should */
-			/* be stored here. but for now we skip this too ... */
-			if( pers->shader )
-			{
-				char *name = (char *)(pers->bufptr + pers->cofs);
-				PicoSetShaderMapName( pers->shader,name );
-#ifdef DEBUG_PM_3DS
-				printf("NewShaderMapfile: '%s'\n",name);
-#endif
-			}
-		}
-		/*** keyframes ***/
-		if (chunk->id == CHUNK_KEYFRAME_DATA)
-		{
-			/* well umm, this is a bit too much since we don't really */
-			/* need model animation sequences right now. we skip this */
-#ifdef DEBUG_PM_3DS
-			printf("KeyframeData: len %d\n",chunk->len);
-#endif
-		}
-		/* skip unknown chunk */
-		pers->cofs = nextofs;
-		if (pers->cofs >= pers->maxofs) break;
-	}
-	return 1;
-}
-
-static int DoNextChunk (T3dsLoaderPers *pers, int endofs)
-{
-	T3dsChunk *chunk;
-
-#ifdef DEBUG_PM_3DS
-	printf("DoNextChunk: endofs %d\n",endofs);
-#endif
-	while (pers->cofs < endofs)
-	{
-		long nextofs = pers->cofs;
-		if ((chunk = GetChunk(pers)) == NULL) return 0;
-		if (!chunk->len) return 0;
-		nextofs += chunk->len;
-
-#ifdef DEBUG_PM_3DS_EX
-		printf("Chunk %04x (%s), len %d pers->cofs %x\n",chunk->id,DebugGetChunkName(chunk->id),chunk->len,pers->cofs);
-#endif
-		/*** version ***/
-		if (chunk->id == CHUNK_VERSION)
-		{
-			/* at this point i get the 3ds file version. since there */
-			/* might be new additions to the 3ds file format in 4.0 */
-			/* it might be a good idea to store the version somewhere */
-			/* for later handling or message displaying */
-
-			/* get the version */
-			int version;
-			version = GetWord(pers);
-			GetWord(pers);
-#ifdef DEBUG_PM_3DS
-			printf("FileVersion: %d\n",version);
-#endif
-
-			/* throw out a warning for version 4 models */
-			if (version == 4)
-			{
-				_pico_printf( PICO_WARNING,
-					"3DS version is 4. Model might load incorrectly.");
-			}
-			/* store the 3ds file version in pico special field 0 */
-			/* PicoSetSurfaceSpecial(pers->surface,0,version); */		/* ydnar: this was causing a crash accessing uninitialized surface */
-			
-			/* rest of chunk is skipped here */
-		}
-		/*** editor data ***/
-		if (chunk->id == CHUNK_EDITOR_DATA)
-		{
-			if (!DoNextEditorDataChunk(pers,nextofs)) return 0;
-			continue;
-		}
-		/* skip unknown chunk */
-		pers->cofs = nextofs;
-		if (pers->cofs >= pers->maxofs) break;
-	}
-	return 1;
-}
-
-/* _3ds_load:
- *  loads an autodesk 3ds model file.
-*/
-static picoModel_t *_3ds_load( PM_PARAMS_LOAD )
-{
-	T3dsLoaderPers	pers;
-	picoModel_t	   *model;
-	char			basename[128];
-
-	/* create a new pico model */
-	model = PicoNewModel();
-	if (model == NULL)
-	{
-		/* user must have some serious ram problems ;) */
-		return NULL;
-	}
-	/* get model's base name (eg. jeep from c:\models\jeep.3ds) */
-	memset( basename,0,sizeof(basename) );
-	strncpy( basename,_pico_nopath(fileName),sizeof(basename) );
-	_pico_setfext( basename,"" );
-
-	/* initialize persistant vars (formerly static) */
-	pers.model    =  model;
-	pers.bufptr   = (picoByte_t *)buffer;
-	pers.basename = (char *)basename;
-	pers.maxofs   =  bufSize;
-	pers.cofs     =  0L;
-
-	/* do model setup */
-	PicoSetModelFrameNum( model,frameNum );
-	PicoSetModelName( model,fileName );
-	PicoSetModelFileName( model,fileName );
-
-	/* skip first chunk in file (magic) */
-	GetChunk(&pers);
-
-	/* process chunks */
-	if (!DoNextChunk(&pers,pers.maxofs))
-	{
-		/* well, bleh i guess */
-		PicoFreeModel(model);
-		return NULL;
-	}
-	/* return allocated pico model */
-	return model;
-}
-
-/* pico file format module definition */
-const picoModule_t picoModule3DS =
-{
-	"0.86-b",					/* module version string */
-	"Autodesk 3Dstudio",		/* module display name */
-	"seaw0lf",					/* author's name */
-	"2002 seaw0lf",				/* module copyright */
-	{
-		"3ds",NULL,NULL,NULL	/* default extensions to use */
-	},
-	_3ds_canload,				/* validation routine */
-	_3ds_load,					/* load routine */
-	 NULL,						/* save validation routine */
-	 NULL						/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PM_3DS_C
+
+/* dependencies */
+#include "picointernal.h"
+
+/* ydnar */
+static picoColor_t white = { 255,255,255,255 };
+
+/* remarks:
+ * - 3ds file version is stored in pico special field 0 on load (ydnar: removed)
+ * todo:
+ * - sometimes there is one unnamed surface 0 having 0 verts as
+ *   well as 0 faces. this error occurs since pm 0.6 (ydnar?)
+ */
+/* uncomment when debugging this module */
+/* #define DEBUG_PM_3DS
+#define DEBUG_PM_3DS_EX */
+
+/* structure holding persistent 3ds loader specific data used */
+/* to store formerly static vars to keep the module reentrant */
+/* safe. put everything that needs to be static in here. */
+typedef struct S3dsLoaderPers
+{
+	picoModel_t	   *model;			/* ptr to output model */
+	picoSurface_t  *surface;		/* ptr to current surface */
+	picoShader_t   *shader;			/* ptr to current shader */
+	picoByte_t	   *bufptr;			/* ptr to raw data */
+	char		   *basename;		/* ptr to model base name (eg. jeep) */
+	int	 			cofs;
+	int	 			maxofs;
+}
+T3dsLoaderPers;
+
+/* 3ds chunk types that we use */
+enum {
+    /* primary chunk */
+    CHUNK_MAIN				= 0x4D4D,
+
+	/* main chunks */
+	CHUNK_VERSION       	= 0x0002,
+	CHUNK_EDITOR_CONFIG		= 0x3D3E,
+	CHUNK_EDITOR_DATA   	= 0x3D3D,
+	CHUNK_KEYFRAME_DATA		= 0xB000,
+
+	/* editor data sub chunks */
+	CHUNK_MATERIAL			= 0xAFFF,
+	CHUNK_OBJECT        	= 0x4000,
+
+	/* material sub chunks */
+	CHUNK_MATNAME			= 0xA000,
+	CHUNK_MATDIFFUSE		= 0xA020,
+	CHUNK_MATMAP			= 0xA200,
+	CHUNK_MATMAPFILE		= 0xA300,
+
+	/* lets us know we're reading a new object */
+	CHUNK_OBJECT_MESH		= 0x4100,
+
+	/* object mesh sub chunks */
+	CHUNK_OBJECT_VERTICES	= 0x4110,
+	CHUNK_OBJECT_FACES		= 0x4120,
+	CHUNK_OBJECT_MATERIAL	= 0x4130,
+	CHUNK_OBJECT_UV			= 0x4140,
+};
+#ifdef DEBUG_PM_3DS
+static struct
+{
+	int 	id;
+	char   *name;
+}
+debugChunkNames[] =
+{
+	{ CHUNK_MAIN			, "CHUNK_MAIN" 				},
+	{ CHUNK_VERSION			, "CHUNK_VERSION" 			},
+	{ CHUNK_EDITOR_CONFIG	, "CHUNK_EDITOR_CONFIG" 	},
+	{ CHUNK_EDITOR_DATA		, "CHUNK_EDITOR_DATA" 		},
+	{ CHUNK_KEYFRAME_DATA	, "CHUNK_KEYFRAME_DATA" 	},
+	{ CHUNK_MATERIAL		, "CHUNK_MATERIAL"			},
+	{ CHUNK_OBJECT			, "CHUNK_OBJECT"			},
+	{ CHUNK_MATNAME			, "CHUNK_MATNAME"			},
+	{ CHUNK_MATDIFFUSE		, "CHUNK_MATDIFFUSE"		},
+	{ CHUNK_MATMAP			, "CHUNK_MATMAP"			},
+	{ CHUNK_MATMAPFILE		, "CHUNK_MATMAPFILE"		},
+	{ CHUNK_OBJECT_MESH		, "CHUNK_OBJECT_MESH"		},
+	{ CHUNK_OBJECT_VERTICES	, "CHUNK_OBJECT_VERTICES"	},
+	{ CHUNK_OBJECT_FACES	, "CHUNK_OBJECT_FACES"		},
+	{ CHUNK_OBJECT_MATERIAL	, "CHUNK_OBJECT_MATERIAL"	},
+	{ CHUNK_OBJECT_UV		, "CHUNK_OBJECT_UV"			},
+	{ 0						,  NULL						}
+};
+static char *DebugGetChunkName (int id)
+{
+	int i,max;	/* imax? ;) */
+	max = sizeof(debugChunkNames) / sizeof(debugChunkNames[0]);
+
+	for (i=0; i<max; i++)
+	{
+		if (debugChunkNames[i].id == id)
+		{
+			/* gaynux update -sea */
+			return _pico_strlwr( debugChunkNames[i].name );
+		}
+	}
+	return "chunk_unknown";
+}
+#endif /*DEBUG_PM_3DS*/
+
+/* this funky loader needs byte alignment */
+#pragma pack(push, 1)
+
+typedef struct S3dsIndices
+{
+	unsigned short 	a,b,c;
+	unsigned short 	visible;
+}
+T3dsIndices;
+
+typedef struct S3dsChunk
+{
+	unsigned short 	id;
+	unsigned int	len;
+}
+T3dsChunk;
+
+/* restore previous data alignment */
+#pragma pack(pop)
+
+/* _3ds_canload:
+ *  validates an autodesk 3ds model file.
+ */
+static int _3ds_canload( PM_PARAMS_CANLOAD )
+{
+	T3dsChunk *chunk;
+
+	/* to keep the compiler happy */
+	*fileName = *fileName;
+
+	/* sanity check */
+	if (bufSize < sizeof(T3dsChunk))
+		return PICO_PMV_ERROR_SIZE;
+
+	/* get pointer to 3ds header chunk */
+	chunk = (T3dsChunk *)buffer;
+
+	/* check data length */
+	if (bufSize < _pico_little_long(chunk->len))
+		return PICO_PMV_ERROR_SIZE;
+
+	/* check 3ds magic */
+	if (_pico_little_short(chunk->id) != CHUNK_MAIN)
+		return PICO_PMV_ERROR_IDENT;
+
+	/* file seems to be a valid 3ds */
+	return PICO_PMV_OK;
+}
+
+static T3dsChunk *GetChunk (T3dsLoaderPers *pers)
+{
+	T3dsChunk *chunk;
+
+	/* sanity check */
+	if (pers->cofs > pers->maxofs) return 0;
+
+#ifdef DEBUG_PM_3DS
+/*	printf("GetChunk: pers->cofs %x\n",pers->cofs); */
+#endif
+	/* fill in pointer to chunk */
+	chunk = (T3dsChunk *)&pers->bufptr[ pers->cofs ];
+	if (!chunk) return NULL;
+
+	chunk->id  = _pico_little_short(chunk->id );
+	chunk->len = _pico_little_long (chunk->len);
+
+	/* advance in buffer */
+	pers->cofs += sizeof(T3dsChunk);
+
+	/* this means yay */
+	return chunk;
+}
+
+static int GetASCIIZ (T3dsLoaderPers *pers, char *dest, int max)
+{
+	int pos = 0;
+	int ch;
+
+	for (;;)
+	{
+		ch = pers->bufptr[ pers->cofs++ ];
+		if (ch == '\0') break;
+		if (pers->cofs >= pers->maxofs)
+		{
+			dest[ pos ] = '\0';
+			return 0;
+		}
+		dest[ pos++ ] = ch;
+		if (pos >= max) break;
+	}
+	dest[ pos ] = '\0';
+	return 1;
+}
+
+static picoByte_t GetByte (T3dsLoaderPers *pers)
+{
+	picoByte_t *value;
+
+	/* sanity check */
+	if (pers->cofs > pers->maxofs) return 0;
+
+	/* get and return value */
+	value = (picoByte_t *)(pers->bufptr + pers->cofs);
+	pers->cofs += 1;
+	return *value;
+}
+
+static int GetWord (T3dsLoaderPers *pers)
+{
+	unsigned short *value;
+
+	/* sanity check */
+	if (pers->cofs > pers->maxofs) return 0;
+
+	/* get and return value */
+	value = (unsigned short *)(pers->bufptr + pers->cofs);
+	pers->cofs += 2;
+	return _pico_little_short(*value);
+}
+
+static float GetFloat (T3dsLoaderPers *pers)
+{
+	float *value;
+
+	/* sanity check */
+	if (pers->cofs > pers->maxofs) return 0;
+
+	/* get and return value */
+	value = (float *)(pers->bufptr + pers->cofs);
+	pers->cofs += 4;
+	return _pico_little_float(*value);
+}
+
+static int GetMeshVertices (T3dsLoaderPers *pers)
+{
+	int numVerts;
+	int i;
+
+	/* get number of verts for this surface */
+	numVerts = GetWord(pers);
+
+#ifdef DEBUG_PM_3DS
+	printf("GetMeshVertices: numverts %d\n",numVerts);
+#endif
+	/* read in vertices for current surface */
+	for (i=0; i<numVerts; i++)
+	{
+		picoVec3_t v;
+		v[0] = GetFloat( pers );
+		v[1] = GetFloat( pers );	/* ydnar: unflipped */
+		v[2] = GetFloat( pers );	/* ydnar: unflipped and negated */
+		
+		/* add current vertex */
+		PicoSetSurfaceXYZ( pers->surface,i,v );
+		PicoSetSurfaceColor( pers->surface,0,i,white );	/* ydnar */
+
+#ifdef DEBUG_PM_3DS_EX
+		printf("Vertex: x: %f y: %f z: %f\n",v[0],v[1],v[2]);
+#endif
+	}
+	/* success (no errors occured) */
+	return 1;
+}
+
+static int GetMeshFaces (T3dsLoaderPers *pers)
+{
+	int numFaces;
+	int i;
+
+	/* get number of faces for this surface */
+	numFaces = GetWord(pers);
+
+#ifdef DEBUG_PM_3DS
+	printf("GetMeshFaces: numfaces %d\n",numFaces);
+#endif
+	/* read in vertex indices for current surface */
+	for (i=0; i<numFaces; i++)
+	{
+		/* remember, we only need 3 of 4 values read in for each */
+		/* face. the 4th value is a vis flag for 3dsmax which is */
+		/* being ignored by us here */
+		T3dsIndices face;
+		face.a		 = GetWord(pers);
+		face.c		 = GetWord(pers);	/* ydnar: flipped order */
+		face.b		 = GetWord(pers);	/* ydnar: flipped order */
+		face.visible = GetWord(pers);
+
+		/* copy indexes */
+		PicoSetSurfaceIndex( pers->surface, (i * 3 + 0), (picoIndex_t)face.a );
+		PicoSetSurfaceIndex( pers->surface, (i * 3 + 1), (picoIndex_t)face.b );
+		PicoSetSurfaceIndex( pers->surface, (i * 3 + 2), (picoIndex_t)face.c );
+
+#ifdef DEBUG_PM_3DS_EX
+		printf("Face: a: %d b: %d c: %d (%d)\n",face.a,face.b,face.c,face.visible);
+#endif
+	}
+	/* success (no errors occured) */
+	return 1;
+}
+
+static int GetMeshTexCoords (T3dsLoaderPers *pers)
+{
+	int numTexCoords;
+	int i;
+
+	/* get number of uv coords for this surface */
+	numTexCoords = GetWord(pers);
+
+#ifdef DEBUG_PM_3DS
+	printf("GetMeshTexCoords: numcoords %d\n",numTexCoords);
+#endif
+	/* read in uv coords for current surface */
+	for (i=0; i<numTexCoords; i++)
+	{
+		picoVec2_t uv;
+		uv[0] =  GetFloat( pers );
+		uv[1] = -GetFloat( pers );	/* ydnar: we use origin at bottom */
+
+		/* to make sure we don't mess up memory */
+		if (pers->surface == NULL)
+			continue;
+		
+		/* add current uv */
+		PicoSetSurfaceST( pers->surface,0,i,uv );
+
+#ifdef DEBUG_PM_3DS_EX
+		printf("u: %f v: %f\n",uv[0],uv[1]);
+#endif
+	}
+	/* success (no errors occured) */
+	return 1;
+}
+
+static int GetMeshShader (T3dsLoaderPers *pers)
+{
+	char shaderName[255] = { 0 };
+	picoShader_t  *shader;
+	int  numSharedVerts;
+	int  setShaderName = 0;
+	int  i;
+	
+	/* the shader is either the color or the texture map of the */
+	/* object. it can also hold other information like the brightness, */
+	/* shine, etc. stuff we don't really care about. we just want the */
+	/* color, or the texture map file name really */
+
+	/* get in the shader name */
+	if (!GetASCIIZ(pers,shaderName,sizeof(shaderName)))
+		return 0;
+
+	/* now that we have the shader name we need to go through all of */
+	/* the shaders and check the name against each shader. when we */
+	/* find a shader in our shader list that matches this name we */
+	/* just read in, then we assign the shader's id of the object to */
+	/* that shader */
+
+	/* get shader id for shader name */
+	shader = PicoFindShader( pers->model, shaderName, 1 );
+
+	/* we've found a matching shader */
+	if ((shader != NULL) && pers->surface)
+	{
+		char  mapName[1024+1];
+		char *mapNamePtr;
+		memset( mapName,0,sizeof(mapName) );
+
+		/* get ptr to shader's map name */
+		mapNamePtr = PicoGetShaderMapName( shader );
+
+		/* we have a valid map name ptr */
+		if (mapNamePtr != NULL)
+		{
+			char  temp[128];
+			char *name;
+
+			/* copy map name to local buffer */
+			strcpy( mapName,mapNamePtr );
+
+			/* extract file name */
+			name = _pico_nopath( mapName );
+			strncpy( temp, name, sizeof(temp) );
+
+			/* remove file extension */
+			/* name = _pico_setfext( name,"" ); */
+
+			/* assign default name if no name available */
+			if (strlen(temp) < 1)
+				strcpy(temp,pers->basename);
+
+			/* build shader name */
+			_pico_strlwr( temp ); /* gaynux update -sea */
+			sprintf( mapName,"models/mapobjects/%s/%s",pers->basename,temp );
+
+			/* set shader name */
+			/* PicoSetShaderName( shader,mapName ); */	/* ydnar: this will screw up the named shader */
+
+			/* set surface's shader index */
+			PicoSetSurfaceShader( pers->surface, shader );
+
+			setShaderName = 1;
+		}
+	}
+	/* we didn't set a shader name; throw out warning */
+	if (!setShaderName)
+	{
+		_pico_printf( PICO_WARNING,"3DS mesh is missing shader name");
+	}
+	/* we don't process the list of shared vertices here; there is a */
+	/* short int that gives the number of faces of the mesh concerned */
+	/* by this shader, then there is the list itself of these faces. */
+	/* 0000 means the first face of the (4120) face list */
+
+	/* get number of shared verts */
+	numSharedVerts = GetWord(pers);
+
+#ifdef DEBUG_PM_3DS
+	printf("GetMeshShader: uses shader '%s' (nsv %d)\n",shaderName,numSharedVerts);
+#endif
+	/* skip list of shared verts */
+	for (i=0; i<numSharedVerts; i++)
+	{
+		GetWord(pers);
+	}
+	/* success (no errors occured) */
+	return 1;
+}
+
+static int GetDiffuseColor (T3dsLoaderPers *pers)
+{
+	/* todo: support all 3ds specific color formats; */
+	/* that means: rgb,tru,trug,rgbg */
+
+	/* get rgb color (range 0..255; 3 bytes) */
+	picoColor_t color;
+
+	color[0] = GetByte(pers);
+	color[1] = GetByte(pers);
+	color[2] = GetByte(pers);
+	color[3] = 255;
+
+	/* store this as the current shader's diffuse color */
+	if( pers->shader )
+	{
+		PicoSetShaderDiffuseColor( pers->shader,color );
+	}
+#ifdef DEBUG_PM_3DS
+	printf("GetDiffuseColor: %d %d %d\n",color[0],color[1],color[2]);
+#endif
+	/* success (no errors occured) */
+	return 1;
+}
+
+static int DoNextEditorDataChunk (T3dsLoaderPers *pers, long endofs)
+{
+	T3dsChunk *chunk;
+
+#ifdef DEBUG_PM_3DS_EX
+	printf("DoNextEditorDataChunk: endofs %d\n",endofs);
+#endif
+	while (pers->cofs < endofs)
+	{
+		long nextofs = pers->cofs;
+		if ((chunk = GetChunk(pers)) == NULL) return 0;
+		if (!chunk->len) return 0;
+		nextofs += chunk->len;
+
+#ifdef DEBUG_PM_3DS_EX
+		printf("Chunk %04x (%s), len %d pers->cofs %x\n",chunk->id,DebugGetChunkName(chunk->id),chunk->len,pers->cofs);
+#endif
+		/*** meshes ***/
+		if (chunk->id == CHUNK_OBJECT)
+		{
+			picoSurface_t *surface;
+			char surfaceName[ 0xff ] = { 0 };
+
+			/* read in surface name */
+			if( !GetASCIIZ(pers,surfaceName,sizeof(surfaceName)) )
+				return 0; /* this is bad */
+
+//PicoGetSurfaceName
+			/* ignore NULL name surfaces */
+//			if( surfaceName
+
+			/* allocate a pico surface */
+			surface = PicoNewSurface( pers->model );
+			if( surface == NULL )
+			{
+				pers->surface = NULL;
+				return 0; /* this is bad too */
+			}
+			/* assign ptr to current surface */
+			pers->surface = surface;
+
+			/* 3ds models surfaces are all triangle meshes */
+			PicoSetSurfaceType( pers->surface,PICO_TRIANGLES );
+
+			/* set surface name */
+			PicoSetSurfaceName( pers->surface,surfaceName );
+
+			/* continue mess with object's sub chunks */
+			DoNextEditorDataChunk(pers,nextofs);
+			continue;
+		}
+		if (chunk->id == CHUNK_OBJECT_MESH)
+		{
+			/* continue mess with mesh's sub chunks */
+			if (!DoNextEditorDataChunk(pers,nextofs)) return 0;
+			continue;
+		}
+		if (chunk->id == CHUNK_OBJECT_VERTICES)
+		{
+			if (!GetMeshVertices(pers)) return 0;
+			continue;
+		}
+		if (chunk->id == CHUNK_OBJECT_FACES)
+		{
+			if (!GetMeshFaces(pers)) return 0;
+			continue;
+		}
+		if (chunk->id == CHUNK_OBJECT_UV)
+		{
+			if (!GetMeshTexCoords(pers)) return 0;
+			continue;
+		}
+		if (chunk->id == CHUNK_OBJECT_MATERIAL)
+		{
+			if (!GetMeshShader(pers)) return 0;
+			continue;
+		}
+		/*** materials ***/
+		if (chunk->id == CHUNK_MATERIAL)
+		{
+			/* new shader specific things should be */
+			/* initialized right here */
+			picoShader_t *shader;
+
+			/* allocate a pico shader */
+			shader = PicoNewShader( pers->model );	/* ydnar */
+			if( shader == NULL )
+			{
+				pers->shader = NULL;
+				return 0; /* this is bad too */
+			}
+			
+			/* assign ptr to current shader */
+			pers->shader = shader;
+
+			/* continue and process the material's sub chunks */
+			DoNextEditorDataChunk(pers,nextofs);
+			continue;
+		}
+		if (chunk->id == CHUNK_MATNAME)
+		{
+			/* new material's names should be stored here. note that */
+			/* GetMeshMaterial returns the name of the material that */
+			/* is used by the mesh. new material names are set HERE. */
+			/* but for now we skip the new material's name ... */
+			if (pers->shader)
+			{
+				char *name = (char *)(pers->bufptr + pers->cofs);
+				PicoSetShaderName( pers->shader,name );
+#ifdef DEBUG_PM_3DS
+				printf("NewShader: '%s'\n",name);
+#endif
+			}
+		}
+		if (chunk->id == CHUNK_MATDIFFUSE)
+		{
+			/* todo: color for last inserted new material should be */
+			/* stored somewhere by GetDiffuseColor */
+			if (!GetDiffuseColor(pers)) return 0;
+
+			/* rest of chunk is skipped here */
+		}
+		if (chunk->id == CHUNK_MATMAP)
+		{
+			/* continue and process the material map sub chunks */
+			DoNextEditorDataChunk(pers,nextofs);
+			continue;
+		}
+		if (chunk->id == CHUNK_MATMAPFILE)
+		{
+			/* map file name for last inserted new material should */
+			/* be stored here. but for now we skip this too ... */
+			if( pers->shader )
+			{
+				char *name = (char *)(pers->bufptr + pers->cofs);
+				PicoSetShaderMapName( pers->shader,name );
+#ifdef DEBUG_PM_3DS
+				printf("NewShaderMapfile: '%s'\n",name);
+#endif
+			}
+		}
+		/*** keyframes ***/
+		if (chunk->id == CHUNK_KEYFRAME_DATA)
+		{
+			/* well umm, this is a bit too much since we don't really */
+			/* need model animation sequences right now. we skip this */
+#ifdef DEBUG_PM_3DS
+			printf("KeyframeData: len %d\n",chunk->len);
+#endif
+		}
+		/* skip unknown chunk */
+		pers->cofs = nextofs;
+		if (pers->cofs >= pers->maxofs) break;
+	}
+	return 1;
+}
+
+static int DoNextChunk (T3dsLoaderPers *pers, int endofs)
+{
+	T3dsChunk *chunk;
+
+#ifdef DEBUG_PM_3DS
+	printf("DoNextChunk: endofs %d\n",endofs);
+#endif
+	while (pers->cofs < endofs)
+	{
+		long nextofs = pers->cofs;
+		if ((chunk = GetChunk(pers)) == NULL) return 0;
+		if (!chunk->len) return 0;
+		nextofs += chunk->len;
+
+#ifdef DEBUG_PM_3DS_EX
+		printf("Chunk %04x (%s), len %d pers->cofs %x\n",chunk->id,DebugGetChunkName(chunk->id),chunk->len,pers->cofs);
+#endif
+		/*** version ***/
+		if (chunk->id == CHUNK_VERSION)
+		{
+			/* at this point i get the 3ds file version. since there */
+			/* might be new additions to the 3ds file format in 4.0 */
+			/* it might be a good idea to store the version somewhere */
+			/* for later handling or message displaying */
+
+			/* get the version */
+			int version;
+			version = GetWord(pers);
+			GetWord(pers);
+#ifdef DEBUG_PM_3DS
+			printf("FileVersion: %d\n",version);
+#endif
+
+			/* throw out a warning for version 4 models */
+			if (version == 4)
+			{
+				_pico_printf( PICO_WARNING,
+					"3DS version is 4. Model might load incorrectly.");
+			}
+			/* store the 3ds file version in pico special field 0 */
+			/* PicoSetSurfaceSpecial(pers->surface,0,version); */		/* ydnar: this was causing a crash accessing uninitialized surface */
+			
+			/* rest of chunk is skipped here */
+		}
+		/*** editor data ***/
+		if (chunk->id == CHUNK_EDITOR_DATA)
+		{
+			if (!DoNextEditorDataChunk(pers,nextofs)) return 0;
+			continue;
+		}
+		/* skip unknown chunk */
+		pers->cofs = nextofs;
+		if (pers->cofs >= pers->maxofs) break;
+	}
+	return 1;
+}
+
+/* _3ds_load:
+ *  loads an autodesk 3ds model file.
+*/
+static picoModel_t *_3ds_load( PM_PARAMS_LOAD )
+{
+	T3dsLoaderPers	pers;
+	picoModel_t	   *model;
+	char			basename[128];
+
+	/* create a new pico model */
+	model = PicoNewModel();
+	if (model == NULL)
+	{
+		/* user must have some serious ram problems ;) */
+		return NULL;
+	}
+	/* get model's base name (eg. jeep from c:\models\jeep.3ds) */
+	memset( basename,0,sizeof(basename) );
+	strncpy( basename,_pico_nopath(fileName),sizeof(basename) );
+	_pico_setfext( basename,"" );
+
+	/* initialize persistant vars (formerly static) */
+	pers.model    =  model;
+	pers.bufptr   = (picoByte_t *)buffer;
+	pers.basename = (char *)basename;
+	pers.maxofs   =  bufSize;
+	pers.cofs     =  0L;
+
+	/* do model setup */
+	PicoSetModelFrameNum( model,frameNum );
+	PicoSetModelName( model,fileName );
+	PicoSetModelFileName( model,fileName );
+
+	/* skip first chunk in file (magic) */
+	GetChunk(&pers);
+
+	/* process chunks */
+	if (!DoNextChunk(&pers,pers.maxofs))
+	{
+		/* well, bleh i guess */
+		PicoFreeModel(model);
+		return NULL;
+	}
+	/* return allocated pico model */
+	return model;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModule3DS =
+{
+	"0.86-b",					/* module version string */
+	"Autodesk 3Dstudio",		/* module display name */
+	"seaw0lf",					/* author's name */
+	"2002 seaw0lf",				/* module copyright */
+	{
+		"3ds",NULL,NULL,NULL	/* default extensions to use */
+	},
+	_3ds_canload,				/* validation routine */
+	_3ds_load,					/* load routine */
+	 NULL,						/* save validation routine */
+	 NULL						/* save routine */
+};
diff --git a/libs/picomodel/pm_ase.c b/libs/picomodel/pm_ase.c
index e8c5751d..ae5698df 100644
--- a/libs/picomodel/pm_ase.c
+++ b/libs/picomodel/pm_ase.c
@@ -1,1001 +1,1001 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other aseMaterialList provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-/* marker */
-#define PM_ASE_C
-
-/* uncomment when debugging this module */
-//#define DEBUG_PM_ASE 
-//#define DEBUG_PM_ASE_EX
-
-
-/* dependencies */
-#include "picointernal.h"
-
-#ifdef DEBUG_PM_ASE
-#include "time.h"
-#endif
-
-/* plain white */
-static picoColor_t white = { 255, 255, 255, 255 };
-
-/* jhefty - multi-subobject material support */
-
-/* Material/SubMaterial management */
-/* A material should have 1..n submaterials assigned to it */
-
-typedef struct aseSubMaterial_s
-{
-	struct aseSubMaterial_s* next;
-	int subMtlId;
-	picoShader_t* shader;
-	
-} aseSubMaterial_t;
-
-typedef struct aseMaterial_s
-{
-	struct aseMaterial_s* next;
-	struct aseSubMaterial_s* subMtls;
-	int mtlId;		
-} aseMaterial_t;
-
-/* Material/SubMaterial management functions */
-static aseMaterial_t* _ase_get_material ( aseMaterial_t* list , int mtlIdParent )
-{
-	aseMaterial_t* mtl = list;
-
-	while ( mtl )
-	{
-		if ( mtlIdParent == mtl->mtlId )
-		{
-			break;
-		}
-		mtl = mtl->next;
-	}
-	return mtl;
-}
-
-static aseSubMaterial_t* _ase_get_submaterial ( aseMaterial_t* list, int  mtlIdParent , int subMtlId )
-{
-	aseMaterial_t* parent = _ase_get_material ( list , mtlIdParent );
-	aseSubMaterial_t* subMtl = NULL;
-
-	if ( !parent )
-	{
-		_pico_printf ( PICO_ERROR , "No ASE material exists with id %i\n" , mtlIdParent );
-		return NULL;
-	}
-
-	subMtl = parent->subMtls;
-	while ( subMtl )
-	{
-		if ( subMtlId == subMtl->subMtlId )
-		{
-			break;
-		}
-		subMtl = subMtl->next;
-	}
-	return subMtl;
-}
-
-static aseMaterial_t* _ase_add_material( aseMaterial_t **list, int mtlIdParent )
-{
-	aseMaterial_t *mtl = _pico_calloc( 1, sizeof( aseMaterial_t ) );
-	mtl->mtlId = mtlIdParent;
-	mtl->subMtls = NULL;
-	mtl->next = *list;
-	*list = mtl;
-
-	return mtl;
-}
-
-static aseSubMaterial_t* _ase_add_submaterial( aseMaterial_t **list, int mtlIdParent, int subMtlId, picoShader_t* shader )
-{
-	aseMaterial_t *parent = _ase_get_material( *list,  mtlIdParent );
-	aseSubMaterial_t *subMtl = _pico_calloc( 1, sizeof ( aseSubMaterial_t ) );
-
-	if ( !parent )
-	{
-		parent = _ase_add_material ( list , mtlIdParent );
-	}
-
-	subMtl->shader = shader;
-	subMtl->subMtlId = subMtlId;
-	subMtl->next = parent->subMtls;
-	parent->subMtls = subMtl;
-
-	return subMtl;
-}
-
-static void _ase_free_materials( aseMaterial_t **list )
-{
-	aseMaterial_t* mtl = *list;
-	aseSubMaterial_t* subMtl = NULL;
-
-	aseMaterial_t* mtlTemp = NULL;
-	aseSubMaterial_t* subMtlTemp = NULL;
-
-	while ( mtl )
-	{
-		subMtl = mtl->subMtls;
-		while ( subMtl )
-		{
-			subMtlTemp = subMtl->next;
-			_pico_free ( subMtl );
-			subMtl = subMtlTemp;
-		}
-		mtlTemp = mtl->next;
-		_pico_free ( mtl );
-		mtl = mtlTemp;
-	}
-	(*list) = NULL;
-}
-
-#ifdef DEBUG_PM_ASE
-static void _ase_print_materials( aseMaterial_t *list )
-{
-	aseMaterial_t* mtl = list;
-	aseSubMaterial_t* subMtl = NULL;
-
-	while ( mtl )
-	{
-		_pico_printf ( PICO_NORMAL ,  "ASE Material %i" , mtl->mtlId );
-		subMtl = mtl->subMtls;
-		while ( subMtl )
-		{
-			_pico_printf ( PICO_NORMAL ,  " -- ASE SubMaterial %i - %s\n" , subMtl->subMtlId , subMtl->shader->name );
-			subMtl = subMtl->next;
-		}
-		mtl = mtl->next;
-	}
-}
-#endif //DEBUG_PM_ASE
-
-/* ASE Face management */
-/* These are used to keep an association between a submaterial and a face definition */
-/* They are kept in parallel with the current picoSurface, */
-/* and are used by _ase_submit_triangles to lookup the proper material/submaterial IDs */
-typedef struct aseFace_s
-{
-	struct aseFace_s* next;
-	int mtlId;
-	int subMtlId;
-	int index[9];
-} aseFace_t;
-
-/* ASE Face management functions */
-void _ase_add_face( aseFace_t **list, aseFace_t **tail, aseFace_t *newFace )
-{
-	aseFace_t* face = *list;
-	aseFace_t* tempFace = NULL;
-
-	/* insert as head of list */
-	if ( !(*list) )
-	{
-		*list = newFace;
-	}
-	else
-	{
-		(*tail)->next = newFace;
-	}	
-
-	*tail = newFace;
-	newFace->next = NULL;
-	
-	//tag the color indices so we can detect them and apply the default color to them
-	newFace->index[6] = -1;
-	newFace->index[7] = -1;
-	newFace->index[8] = -1;
-}
-
-aseFace_t* _ase_get_face_for_index( aseFace_t *list, int index )
-{
-	int counter = 0;
-	aseFace_t* face = list;
-
-	while ( counter < index )
-	{
-		face = face->next;
-		counter++;
-	}
-	return face;
-}
-static void _ase_free_faces (aseFace_t** list, aseFace_t** tail )
-{
-	aseFace_t* face = *list;
-	aseFace_t* tempFace = NULL;
-
-	while ( face )
-	{
-		tempFace = face->next;
-		_pico_free ( face );
-		face = tempFace;
-	}
-
-	(*list) = NULL;
-	(*tail) = NULL;
-}
-
-/* todo:
- * - apply material specific uv offsets to uv coordinates
- */
-
-/* _ase_canload:
- *  validates a 3dsmax ase model file.
- */
-static int _ase_canload( PM_PARAMS_CANLOAD )
-{
-	picoParser_t *p;
-	
-	
-	/* quick data length validation */
-	if( bufSize < 80 )
-		return PICO_PMV_ERROR_SIZE;
-	
-	/* keep the friggin compiler happy */
-	*fileName = *fileName;
-	
-	/* create pico parser */
-	p = _pico_new_parser( (picoByte_t*) buffer, bufSize );
-	if( p == NULL )
-		return PICO_PMV_ERROR_MEMORY;
-	
-	/* get first token */
-	if( _pico_parse_first( p ) == NULL)
-	{
-		return PICO_PMV_ERROR_IDENT;
-	}
-	
-	/* check first token */
-	if( _pico_stricmp( p->token, "*3dsmax_asciiexport" ) )
-	{
-		_pico_free_parser( p );
-		return PICO_PMV_ERROR_IDENT;
-	}
-	
-	/* free the pico parser object */
-	_pico_free_parser( p );
-	
-	/* file seems to be a valid ase file */
-	return PICO_PMV_OK;
-}
-
-
-
-/* _ase_submit_triangles - jhefty
- use the surface and the current face list to look up material/submaterial IDs
- and submit them to the model for proper processing
-
-The following still holds from ydnar's _ase_make_surface:
- indexes 0 1 2 = vert indexes
- indexes 3 4 5 = st indexes
- indexes 6 7 8 = color indexes (new)
-*/
-
-static void _ase_submit_triangles ( picoSurface_t* surface , picoModel_t* model , aseMaterial_t* materials , aseFace_t* faces )
-{
-	aseFace_t* face;
-	aseSubMaterial_t* subMtl;
-	picoVec3_t* xyz[3];
-	picoVec3_t* normal[3];
-	picoVec2_t* st[3];
-	picoColor_t* color[3];
-	int i;
-
-	face = faces;
-	while ( face != NULL )
-	{
-		/* look up the shader for the material/submaterial pair */
-		subMtl = _ase_get_submaterial( materials, face->mtlId, face->subMtlId );
-		if( subMtl == NULL )
-		{
-			/* ydnar: trying default submaterial */
-			subMtl = _ase_get_submaterial( materials, face->mtlId, 0 );
-			if( subMtl == NULL )
-			{
-				_pico_printf( PICO_ERROR, "Could not find material/submaterial for id %d/%d\n", face->mtlId, face->subMtlId );
-				return;
-			}
-		}
-		
-		/* we pull the data from the surface using the facelist data */
-		for ( i = 0 ; i < 3 ; i ++ )
-		{
-			xyz[i]    = (picoVec3_t*) PicoGetSurfaceXYZ   ( surface, face->index[ i ] );
-			normal[i] = (picoVec3_t*) PicoGetSurfaceNormal( surface, face->index[ i ] );								
-			st[i]     = (picoVec2_t*) PicoGetSurfaceST    ( surface, 0, face->index[ i + 3 ] );
-			
-			if ( face->index [ i + 6] >= 0 )
-			{
-				color[i]  = (picoColor_t*)PicoGetSurfaceColor ( surface, 0, face->index[ i + 6 ] );
-			}
-			else
-			{
-				color[i] = &white;
-			}
-			
-		}
-
-		/* submit the triangle to the model */
-		PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader );
-
-		/* advance to the next face */
-		face = face->next;		
-	}	
-}
-
-/* _ase_load:
- *  loads a 3dsmax ase model file.
-*/
-static picoModel_t *_ase_load( PM_PARAMS_LOAD )
-{
-	picoModel_t    *model;
-	picoSurface_t  *surface = NULL;
-	picoParser_t   *p;
-	char			lastNodeName[ 1024 ];
-
-	aseFace_t* faces = NULL;
-	aseFace_t* facesTail = NULL;
-	aseMaterial_t* materials = NULL;
-
-#ifdef DEBUG_PM_ASE
-	clock_t start, finish;
-	double elapsed;
-	start = clock();
-#endif
-
-	/* helper */
-	#define _ase_error_return(m) \
-	{ \
-		_pico_printf( PICO_ERROR,"%s in ASE, line %d.",m,p->curLine); \
-		_pico_free_parser( p ); \
-		PicoFreeModel( model ); \
-		return NULL; \
-	}
-	/* create a new pico parser */
-	p = _pico_new_parser( (picoByte_t *)buffer,bufSize );
-	if (p == NULL) return NULL;
-
-	/* create a new pico model */
-	model = PicoNewModel();
-	if (model == NULL)
-	{
-		_pico_free_parser( p );
-		return NULL;
-	}
-	/* do model setup */
-	PicoSetModelFrameNum( model, frameNum );
-	PicoSetModelName( model, fileName );
-	PicoSetModelFileName( model, fileName );
-
-	/* initialize some stuff */
-	memset( lastNodeName,0,sizeof(lastNodeName) );
-
-	/* parse ase model file */
-	while( 1 )
-	{
-		/* get first token on line */
-		if (_pico_parse_first( p ) == NULL)
-			break;
-
-		/* we just skip empty lines */
-		if (p->token == NULL || !strlen( p->token ))
-			continue;
-
-		/* we skip invalid ase statements */
-		if (p->token[0] != '*' && p->token[0] != '{' && p->token[0] != '}')
-		{
-			_pico_parse_skip_rest( p );
-			continue;
-		}
-		/* remember node name */
-		if (!_pico_stricmp(p->token,"*node_name"))
-		{
-			/* read node name */
-			char *ptr = _pico_parse( p,0 );
-			if (ptr == NULL)
-				_ase_error_return("Node name parse error");
-
-			/* remember node name */
-			strncpy( lastNodeName,ptr,sizeof(lastNodeName) );
-		}
-		/* model mesh (originally contained within geomobject) */
-		else if (!_pico_stricmp(p->token,"*mesh"))
-		{
-			/* finish existing surface */
-			//_ase_make_surface( model, &surface );
-			_ase_submit_triangles (surface, model ,materials,faces);
-			_ase_free_faces (&faces,&facesTail);
-						
-			/* allocate new pico surface */
-			surface = PicoNewSurface( NULL );
-			if (surface == NULL)
-			{
-				PicoFreeModel( model );
-				return NULL;
-			}
-		}
-		/* mesh material reference. this usually comes at the end of */
-		/* geomobjects after the mesh blocks. we must assume that the */
-		/* new mesh was already created so all we can do here is assign */
-		/* the material reference id (shader index) now. */
-		else if (!_pico_stricmp(p->token,"*material_ref"))
-		{
-			int mtlId;
-			aseFace_t* face;
-
-			/* we must have a valid surface */
-			if( surface == NULL )
-				_ase_error_return("Missing mesh for material reference");
-
-			/* get the material ref (0..n) */
-			if (!_pico_parse_int( p,&mtlId) )
-				_ase_error_return("Missing material reference ID");
-
-			/* fix up all of the aseFaceList in the surface to point to the parent material */
-			/* we've already saved off their subMtl */
-			face = faces;
-			while ( face != NULL )
-			{
-				face->mtlId = mtlId;
-				face = face->next;
-			}
-		}
-		/* model mesh vertex */
-		else if (!_pico_stricmp(p->token,"*mesh_vertex"))
-		{
-			picoVec3_t	v;
-			int			index;
-
-			/* we must have a valid surface */
-			if( surface == NULL )
-				continue;
-
-			/* get vertex data (orig: index +y -x +z) */
-			if (!_pico_parse_int( p,&index ))
-				_ase_error_return("Vertex parse error");
-			if (!_pico_parse_vec( p,v ))
-				_ase_error_return("Vertex parse error");
-
-			/* set vertex */
-			PicoSetSurfaceXYZ( surface,index,v );
-		}
-		/* model mesh vertex normal */
-		else if (!_pico_stricmp(p->token,"*mesh_vertexnormal"))
-		{
-			picoVec3_t	v;
-			int			index;
-
-			/* we must have a valid surface */
-			if( surface == NULL )
-				continue;
-
-			/* get vertex data (orig: index +y -x +z) */
-			if (!_pico_parse_int( p,&index ))
-				_ase_error_return("Vertex parse error");
-			if (!_pico_parse_vec( p,v ))
-				_ase_error_return("Vertex parse error");
-
-			/* set vertex */
-			PicoSetSurfaceNormal( surface,index,v );
-		}
-		/* model mesh face */
-		else if (!_pico_stricmp(p->token,"*mesh_face"))
-		{
-			picoIndex_t indexes[3];
-			int			index;
-
-			/* we must have a valid surface */
-			if( surface == NULL )
-				continue;
-
-			/* get face index */
-			if (!_pico_parse_int( p,&index ))
-				_ase_error_return("Face parse error");
-
-			/* get 1st vertex index */
-			_pico_parse( p,0 );
-			if (!_pico_parse_int( p,&indexes[0] ))
-				_ase_error_return("Face parse error");
-
-			/* get 2nd vertex index */
-			_pico_parse( p,0 );
-			if (!_pico_parse_int( p,&indexes[1] ))
-				_ase_error_return("Face parse error");
-
-			/* get 3rd vertex index */
-			_pico_parse( p,0 );
-			if (!_pico_parse_int( p,&indexes[2] ))
-				_ase_error_return("Face parse error");
-
-			/* set face indexes (note interleaved offset!) */
-			PicoSetSurfaceIndex( surface, (index * 9 + 0), indexes[2] );
-			PicoSetSurfaceIndex( surface, (index * 9 + 1), indexes[1] );
-			PicoSetSurfaceIndex( surface, (index * 9 + 2), indexes[0] );
-			
-			/* parse to the subMaterial ID */
-			while ( 1 )
-			{
-				_pico_parse (p,0);
-				if (!_pico_stricmp (p->token,"*MESH_MTLID" ))
-				{
-					aseFace_t* newFace;
-					int subMtlId;
-					
-					_pico_parse_int ( p , &subMtlId );
-					newFace = _pico_calloc ( 1 , sizeof ( aseFace_t ));
-					
-					/* we fix up the mtlId later when we parse the material_ref */
-					newFace->mtlId = 0;	
-					newFace->subMtlId = subMtlId;
-					newFace->index[0] = indexes[2];
-					newFace->index[1] = indexes[1];
-					newFace->index[2] = indexes[0];
-
-					_ase_add_face ( &faces,&facesTail,newFace );
-					break;
-				}
-			}
-			
-		}
-		/* model texture vertex */
-		else if (!_pico_stricmp(p->token,"*mesh_tvert"))
-		{
-			picoVec2_t	uv;
-			int			index;
-
-			/* we must have a valid surface */
-			if( surface == NULL )
-				continue;
-
-			/* get uv vertex index */
-			if (!_pico_parse_int( p,&index ))
-				_ase_error_return("UV vertex parse error");
-
-			/* get uv vertex s */
-			if (!_pico_parse_float( p,&uv[0] ))
-				_ase_error_return("UV vertex parse error");
-
-			/* get uv vertex t */
-			if (!_pico_parse_float( p,&uv[1] ))
-				_ase_error_return("UV vertex parse error");
-			
-			/* ydnar: invert t */
-			uv[ 1 ] = 1.0f - uv[ 1 ];
-			
-			/* set texture vertex */
-			PicoSetSurfaceST( surface,0,index,uv );
-		}
-		/* ydnar: model mesh texture face */
-		else if( !_pico_stricmp( p->token, "*mesh_tface" ) )
-		{
-			picoIndex_t indexes[3];
-			int			index;
-			aseFace_t* face;
-			
-			/* we must have a valid surface */
-			if( surface == NULL )
-				continue;
-			
-			/* get face index */
-			if (!_pico_parse_int( p,&index ))
-				_ase_error_return("Texture face parse error");
-			
-			/* get 1st vertex index */
-			if (!_pico_parse_int( p,&indexes[0] ))
-				_ase_error_return("Texture face parse error");
-			
-			/* get 2nd vertex index */
-			if (!_pico_parse_int( p,&indexes[1] ))
-				_ase_error_return("Texture face parse error");
-			
-			/* get 3rd vertex index */
-			if (!_pico_parse_int( p,&indexes[2] ))
-				_ase_error_return("Texture face parse error");
-			
-			/* set face indexes (note interleaved offset!) */
-			PicoSetSurfaceIndex( surface, (index * 9 + 3), indexes[2] );
-			PicoSetSurfaceIndex( surface, (index * 9 + 4), indexes[1] );
-			PicoSetSurfaceIndex( surface, (index * 9 + 5), indexes[0] );
-
-			face = _ase_get_face_for_index(faces,index);
-			face->index[3] = indexes[2];
-			face->index[4] = indexes[1];
-			face->index[5] = indexes[0];
-		}
-		/* model color vertex */
-		else if (!_pico_stricmp(p->token,"*mesh_vertcol"))
-		{
-			picoColor_t	color;
-			int			index;
-			float		colorInput;
-
-			/* we must have a valid surface */
-			if( surface == NULL )
-				continue;
-
-			/* get color vertex index */
-			if (!_pico_parse_int( p,&index ))
-				_ase_error_return("UV vertex parse error");
-
-			/* get R component */
-			if (!_pico_parse_float( p,&colorInput ))
-				_ase_error_return("color vertex parse error");
-			color[0] = (picoByte_t)(colorInput * 255);
-
-			/* get G component */
-			if (!_pico_parse_float( p,&colorInput ))
-				_ase_error_return("color vertex parse error");
-			color[1] = (picoByte_t)(colorInput * 255);
-
-			/* get B component */
-			if (!_pico_parse_float( p,&colorInput ))
-				_ase_error_return("color vertex parse error");
-			color[2] = (picoByte_t)(colorInput * 255);
-			
-			/* leave alpha alone since we don't get any data from the ASE format */
-			color[3] = 255;
-
-			/* set texture vertex */
-			PicoSetSurfaceColor( surface,0,index,color );
-		}
-		/* model color face */
-		else if (!_pico_stricmp(p->token,"*mesh_cface"))
-		{
-			picoIndex_t indexes[3];
-			int			index;
-			aseFace_t*  face;
-
-			/* we must have a valid surface */
-			if( surface == NULL )
-				continue;
-
-			/* get face index */
-			if (!_pico_parse_int( p,&index ))
-				_ase_error_return("Face parse error");
-
-			/* get 1st cvertex index */
-			//			_pico_parse( p,0 );
-			if (!_pico_parse_int( p,&indexes[0] ))
-				_ase_error_return("Face parse error");
-
-			/* get 2nd cvertex index */
-			//			_pico_parse( p,0 );
-			if (!_pico_parse_int( p,&indexes[1] ))
-				_ase_error_return("Face parse error");
-
-			/* get 3rd cvertex index */
-			//			_pico_parse( p,0 );
-			if (!_pico_parse_int( p,&indexes[2] ))
-				_ase_error_return("Face parse error");
-
-			/* set face indexes (note interleaved offset!) */
-			PicoSetSurfaceIndex( surface, (index * 9 + 6), indexes[2] );
-			PicoSetSurfaceIndex( surface, (index * 9 + 7), indexes[1] );
-			PicoSetSurfaceIndex( surface, (index * 9 + 8), indexes[0] );
-
-			face = _ase_get_face_for_index(faces,index);
-			face->index[6] = indexes[2];
-			face->index[7] = indexes[1];
-			face->index[8] = indexes[0];
-		}
-		/* model material */
-		else if( !_pico_stricmp( p->token, "*material" ) )
-		{
-			aseSubMaterial_t*	subMaterial = NULL;
-			picoShader_t		*shader;
-			int					level = 1, index;
-			char				materialName[ 1024 ];
-			float				transValue = 0.0f, shineValue = 1.0f;
-			picoColor_t			ambientColor, diffuseColor, specularColor;
-			char				*mapname = NULL;
-			int					subMtlId, subMaterialLevel = -1;
-			
-			
-			/* get material index */
-			_pico_parse_int( p,&index );
-			
-			/* check brace */
-			if (!_pico_parse_check(p,1,"{"))
-				_ase_error_return("Material missing opening brace");
-			
-			/* parse material block */
-			while( 1 )
-			{
-				/* get next token */
-				if (_pico_parse(p,1) == NULL) break;
-				if (!strlen(p->token)) continue;
-
-				/* handle levels */
-				if (p->token[0] == '{') level++;
-				if (p->token[0] == '}') level--;
-				if (!level) break;
-
-				if( level == subMaterialLevel )
-				{
-					/* set material name */
-					PicoSetShaderName( shader, materialName);
-
-					/* set shader's transparency */
-					PicoSetShaderTransparency( shader,transValue );
-
-					/* set shader's ambient color */
-					PicoSetShaderAmbientColor( shader,ambientColor );
-
-					/* set diffuse alpha to transparency */
-					diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
-
-					/* set shader's diffuse color */
-					PicoSetShaderDiffuseColor( shader,diffuseColor );
-
-					/* set shader's specular color */
-					PicoSetShaderSpecularColor( shader,specularColor );
-
-					/* set shader's shininess */
-					PicoSetShaderShininess( shader,shineValue );
-
-					/* set material map name */
-					PicoSetShaderMapName( shader, mapname );
-
-					subMaterial = _ase_add_submaterial( &materials, index, subMtlId, shader );
-					subMaterialLevel = -1;
-				}
-
-				/* parse submaterial index */
-				if (!_pico_stricmp(p->token,"*submaterial"))
-				{											
-					/* allocate new pico shader */
-					_pico_parse_int( p , &subMtlId );
-
-					shader = PicoNewShader( model );
-					if (shader == NULL)
-					{
-						PicoFreeModel( model );
-						return NULL;
-					}			
-					subMaterialLevel = level;
-				}
-				/* parse material name */
-				else if (!_pico_stricmp(p->token,"*material_name"))
-				{
-					char* name = _pico_parse(p,0);
-					if ( name == NULL)
-						_ase_error_return("Missing material name");
-					
-					strcpy ( materialName , name );
-					/* skip rest and continue with next token */
-					_pico_parse_skip_rest( p );
-					continue;
-				}
-				/* parse material transparency */
-				else if (!_pico_stricmp(p->token,"*material_transparency"))
-				{
-					/* get transparency value from ase */
-					if (!_pico_parse_float( p,&transValue ))
-						_ase_error_return("Material transparency parse error");
-
-					/* skip rest and continue with next token */
-					_pico_parse_skip_rest( p );
-					continue;
-				}
-				/* parse material shininess */
-				else if (!_pico_stricmp(p->token,"*material_shine"))
-				{
-					/* remark:
-					 * - not sure but instead of '*material_shine' i might
-					 *   need to use '*material_shinestrength' */
-
-					/* get shine value from ase */
-					if (!_pico_parse_float( p,&shineValue ))
-						_ase_error_return("Material shine parse error");
-
-					/* scale ase shine range 0..1 to pico range 0..127 */
-					shineValue *= 128.0;
-
-					/* skip rest and continue with next token */
-					_pico_parse_skip_rest( p );
-					continue;
-				}
-				/* parse ambient material color */
-				else if (!_pico_stricmp(p->token,"*material_ambient"))
-				{
-					picoVec3_t  vec;
-					/* get r,g,b float values from ase */
-					if (!_pico_parse_vec( p,vec ))
-						_ase_error_return("Material color parse error");
-
-					/* setup 0..255 range color values */
-					ambientColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
-					ambientColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
-					ambientColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
-					ambientColor[ 3 ] = (int)( 255 );
-
-					/* skip rest and continue with next token */
-					_pico_parse_skip_rest( p );
-					continue;
-				}
-				/* parse diffuse material color */
-				else if (!_pico_stricmp(p->token,"*material_diffuse"))
-				{
-					picoVec3_t  vec;
-
-					/* get r,g,b float values from ase */
-					if (!_pico_parse_vec( p,vec ))
-						_ase_error_return("Material color parse error");
-
-					/* setup 0..255 range color */
-					diffuseColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
-					diffuseColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
-					diffuseColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
-					diffuseColor[ 3 ] = (int)( 255 );
-
-					/* skip rest and continue with next token */
-					_pico_parse_skip_rest( p );
-					continue;
-				}
-				/* parse specular material color */
-				else if (!_pico_stricmp(p->token,"*material_specular"))
-				{
-					picoVec3_t  vec;
-
-					/* get r,g,b float values from ase */
-					if (!_pico_parse_vec( p,vec ))
-						_ase_error_return("Material color parse error");
-
-					/* setup 0..255 range color */
-					specularColor[ 0 ] = (int)( vec[ 0 ] * 255 );
-					specularColor[ 1 ] = (int)( vec[ 1 ] * 255 );
-					specularColor[ 2 ] = (int)( vec[ 2 ] * 255 );
-					specularColor[ 3 ] = (int)( 255 );
-
-					/* skip rest and continue with next token */
-					_pico_parse_skip_rest( p );
-					continue;
-				}
-				/* material diffuse map */
-				else if (!_pico_stricmp(p->token,"*map_diffuse") )
-				{
-					int sublevel = 0;
-
-					/* parse material block */
-					while( 1 )
-					{
-						/* get next token */
-						if (_pico_parse(p,1) == NULL) break;
-						if (!strlen(p->token)) continue;
-						
-						/* handle levels */
-						if (p->token[0] == '{') sublevel++;
-						if (p->token[0] == '}') sublevel--;
-						if (!sublevel) break;
-						
-						/* parse diffuse map bitmap */
-						if (!_pico_stricmp(p->token,"*bitmap"))
-						{
-							char* name = _pico_parse(p,0);
-							if (name == NULL)
-								_ase_error_return("Missing material map bitmap name");
-							mapname = _pico_alloc ( strlen ( name ) + 1 );
-							strcpy ( mapname, name );
-							/* skip rest and continue with next token */
-							_pico_parse_skip_rest( p );
-							continue;
-						}
-					}
-				}
-				/* end map_diffuse block */
-			}
-			/* end material block */
-
-			if( subMaterial == NULL )
-			{
-				/* allocate new pico shader */
-				shader = PicoNewShader( model );
-				if (shader == NULL)
-				{
-					PicoFreeModel( model );
-					return NULL;
-				}
-
-				/* set material name */
-				PicoSetShaderName( shader,materialName );
-
-				/* set shader's transparency */
-				PicoSetShaderTransparency( shader,transValue );
-
-				/* set shader's ambient color */
-				PicoSetShaderAmbientColor( shader,ambientColor );
-
-				/* set diffuse alpha to transparency */
-				diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
-
-				/* set shader's diffuse color */
-				PicoSetShaderDiffuseColor( shader,diffuseColor );
-
-				/* set shader's specular color */
-				PicoSetShaderSpecularColor( shader,specularColor );
-
-				/* set shader's shininess */
-				PicoSetShaderShininess( shader,shineValue );
-
-				/* set material map name */
-				PicoSetShaderMapName( shader, mapname );
-
-				/* this is just a material with 1 submaterial */
-				subMaterial = _ase_add_submaterial( &materials, index, 0, shader );
-			}
-			
-			/* ydnar: free mapname */
-			if( mapname != NULL )
-				_pico_free( mapname );
-		}	// !_pico_stricmp ( "*material" )
-
-		/* skip unparsed rest of line and continue */
-		_pico_parse_skip_rest( p );
-	}
-	
-	/* ydnar: finish existing surface */
-//	_ase_make_surface( model, &surface );
-	_ase_submit_triangles (surface, model ,materials,faces);
-	_ase_free_faces (&faces,&facesTail);
-
-#ifdef DEBUG_PM_ASE
-	_ase_print_materials(materials);
-	finish = clock();
-	elapsed = (double)(finish - start) / CLOCKS_PER_SEC;
-	_pico_printf( PICO_NORMAL, "Loaded model in in %-.2f second(s)\n", elapsed );
-#endif //DEBUG_PM_ASE
-
-	_ase_free_materials(&materials);
-
-	/* return allocated pico model */
-	return model;
-}
-
-/* pico file format module definition */
-const picoModule_t picoModuleASE =
-{
-	"1.0",					/* module version string */
-	"Autodesk 3DSMAX ASCII",	/* module display name */
-	"Jared Hefty, seaw0lf",					/* author's name */
-	"2003 Jared Hefty, 2002 seaw0lf",				/* module copyright */
-	{
-		"ase",NULL,NULL,NULL	/* default extensions to use */
-	},
-	_ase_canload,				/* validation routine */
-	_ase_load,					/* load routine */
-	 NULL,						/* save validation routine */
-	 NULL						/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other aseMaterialList provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+/* marker */
+#define PM_ASE_C
+
+/* uncomment when debugging this module */
+//#define DEBUG_PM_ASE 
+//#define DEBUG_PM_ASE_EX
+
+
+/* dependencies */
+#include "picointernal.h"
+
+#ifdef DEBUG_PM_ASE
+#include "time.h"
+#endif
+
+/* plain white */
+static picoColor_t white = { 255, 255, 255, 255 };
+
+/* jhefty - multi-subobject material support */
+
+/* Material/SubMaterial management */
+/* A material should have 1..n submaterials assigned to it */
+
+typedef struct aseSubMaterial_s
+{
+	struct aseSubMaterial_s* next;
+	int subMtlId;
+	picoShader_t* shader;
+	
+} aseSubMaterial_t;
+
+typedef struct aseMaterial_s
+{
+	struct aseMaterial_s* next;
+	struct aseSubMaterial_s* subMtls;
+	int mtlId;		
+} aseMaterial_t;
+
+/* Material/SubMaterial management functions */
+static aseMaterial_t* _ase_get_material ( aseMaterial_t* list , int mtlIdParent )
+{
+	aseMaterial_t* mtl = list;
+
+	while ( mtl )
+	{
+		if ( mtlIdParent == mtl->mtlId )
+		{
+			break;
+		}
+		mtl = mtl->next;
+	}
+	return mtl;
+}
+
+static aseSubMaterial_t* _ase_get_submaterial ( aseMaterial_t* list, int  mtlIdParent , int subMtlId )
+{
+	aseMaterial_t* parent = _ase_get_material ( list , mtlIdParent );
+	aseSubMaterial_t* subMtl = NULL;
+
+	if ( !parent )
+	{
+		_pico_printf ( PICO_ERROR , "No ASE material exists with id %i\n" , mtlIdParent );
+		return NULL;
+	}
+
+	subMtl = parent->subMtls;
+	while ( subMtl )
+	{
+		if ( subMtlId == subMtl->subMtlId )
+		{
+			break;
+		}
+		subMtl = subMtl->next;
+	}
+	return subMtl;
+}
+
+static aseMaterial_t* _ase_add_material( aseMaterial_t **list, int mtlIdParent )
+{
+	aseMaterial_t *mtl = _pico_calloc( 1, sizeof( aseMaterial_t ) );
+	mtl->mtlId = mtlIdParent;
+	mtl->subMtls = NULL;
+	mtl->next = *list;
+	*list = mtl;
+
+	return mtl;
+}
+
+static aseSubMaterial_t* _ase_add_submaterial( aseMaterial_t **list, int mtlIdParent, int subMtlId, picoShader_t* shader )
+{
+	aseMaterial_t *parent = _ase_get_material( *list,  mtlIdParent );
+	aseSubMaterial_t *subMtl = _pico_calloc( 1, sizeof ( aseSubMaterial_t ) );
+
+	if ( !parent )
+	{
+		parent = _ase_add_material ( list , mtlIdParent );
+	}
+
+	subMtl->shader = shader;
+	subMtl->subMtlId = subMtlId;
+	subMtl->next = parent->subMtls;
+	parent->subMtls = subMtl;
+
+	return subMtl;
+}
+
+static void _ase_free_materials( aseMaterial_t **list )
+{
+	aseMaterial_t* mtl = *list;
+	aseSubMaterial_t* subMtl = NULL;
+
+	aseMaterial_t* mtlTemp = NULL;
+	aseSubMaterial_t* subMtlTemp = NULL;
+
+	while ( mtl )
+	{
+		subMtl = mtl->subMtls;
+		while ( subMtl )
+		{
+			subMtlTemp = subMtl->next;
+			_pico_free ( subMtl );
+			subMtl = subMtlTemp;
+		}
+		mtlTemp = mtl->next;
+		_pico_free ( mtl );
+		mtl = mtlTemp;
+	}
+	(*list) = NULL;
+}
+
+#ifdef DEBUG_PM_ASE
+static void _ase_print_materials( aseMaterial_t *list )
+{
+	aseMaterial_t* mtl = list;
+	aseSubMaterial_t* subMtl = NULL;
+
+	while ( mtl )
+	{
+		_pico_printf ( PICO_NORMAL ,  "ASE Material %i" , mtl->mtlId );
+		subMtl = mtl->subMtls;
+		while ( subMtl )
+		{
+			_pico_printf ( PICO_NORMAL ,  " -- ASE SubMaterial %i - %s\n" , subMtl->subMtlId , subMtl->shader->name );
+			subMtl = subMtl->next;
+		}
+		mtl = mtl->next;
+	}
+}
+#endif //DEBUG_PM_ASE
+
+/* ASE Face management */
+/* These are used to keep an association between a submaterial and a face definition */
+/* They are kept in parallel with the current picoSurface, */
+/* and are used by _ase_submit_triangles to lookup the proper material/submaterial IDs */
+typedef struct aseFace_s
+{
+	struct aseFace_s* next;
+	int mtlId;
+	int subMtlId;
+	int index[9];
+} aseFace_t;
+
+/* ASE Face management functions */
+void _ase_add_face( aseFace_t **list, aseFace_t **tail, aseFace_t *newFace )
+{
+	aseFace_t* face = *list;
+	aseFace_t* tempFace = NULL;
+
+	/* insert as head of list */
+	if ( !(*list) )
+	{
+		*list = newFace;
+	}
+	else
+	{
+		(*tail)->next = newFace;
+	}	
+
+	*tail = newFace;
+	newFace->next = NULL;
+	
+	//tag the color indices so we can detect them and apply the default color to them
+	newFace->index[6] = -1;
+	newFace->index[7] = -1;
+	newFace->index[8] = -1;
+}
+
+aseFace_t* _ase_get_face_for_index( aseFace_t *list, int index )
+{
+	int counter = 0;
+	aseFace_t* face = list;
+
+	while ( counter < index )
+	{
+		face = face->next;
+		counter++;
+	}
+	return face;
+}
+static void _ase_free_faces (aseFace_t** list, aseFace_t** tail )
+{
+	aseFace_t* face = *list;
+	aseFace_t* tempFace = NULL;
+
+	while ( face )
+	{
+		tempFace = face->next;
+		_pico_free ( face );
+		face = tempFace;
+	}
+
+	(*list) = NULL;
+	(*tail) = NULL;
+}
+
+/* todo:
+ * - apply material specific uv offsets to uv coordinates
+ */
+
+/* _ase_canload:
+ *  validates a 3dsmax ase model file.
+ */
+static int _ase_canload( PM_PARAMS_CANLOAD )
+{
+	picoParser_t *p;
+	
+	
+	/* quick data length validation */
+	if( bufSize < 80 )
+		return PICO_PMV_ERROR_SIZE;
+	
+	/* keep the friggin compiler happy */
+	*fileName = *fileName;
+	
+	/* create pico parser */
+	p = _pico_new_parser( (picoByte_t*) buffer, bufSize );
+	if( p == NULL )
+		return PICO_PMV_ERROR_MEMORY;
+	
+	/* get first token */
+	if( _pico_parse_first( p ) == NULL)
+	{
+		return PICO_PMV_ERROR_IDENT;
+	}
+	
+	/* check first token */
+	if( _pico_stricmp( p->token, "*3dsmax_asciiexport" ) )
+	{
+		_pico_free_parser( p );
+		return PICO_PMV_ERROR_IDENT;
+	}
+	
+	/* free the pico parser object */
+	_pico_free_parser( p );
+	
+	/* file seems to be a valid ase file */
+	return PICO_PMV_OK;
+}
+
+
+
+/* _ase_submit_triangles - jhefty
+ use the surface and the current face list to look up material/submaterial IDs
+ and submit them to the model for proper processing
+
+The following still holds from ydnar's _ase_make_surface:
+ indexes 0 1 2 = vert indexes
+ indexes 3 4 5 = st indexes
+ indexes 6 7 8 = color indexes (new)
+*/
+
+static void _ase_submit_triangles ( picoSurface_t* surface , picoModel_t* model , aseMaterial_t* materials , aseFace_t* faces )
+{
+	aseFace_t* face;
+	aseSubMaterial_t* subMtl;
+	picoVec3_t* xyz[3];
+	picoVec3_t* normal[3];
+	picoVec2_t* st[3];
+	picoColor_t* color[3];
+	int i;
+
+	face = faces;
+	while ( face != NULL )
+	{
+		/* look up the shader for the material/submaterial pair */
+		subMtl = _ase_get_submaterial( materials, face->mtlId, face->subMtlId );
+		if( subMtl == NULL )
+		{
+			/* ydnar: trying default submaterial */
+			subMtl = _ase_get_submaterial( materials, face->mtlId, 0 );
+			if( subMtl == NULL )
+			{
+				_pico_printf( PICO_ERROR, "Could not find material/submaterial for id %d/%d\n", face->mtlId, face->subMtlId );
+				return;
+			}
+		}
+		
+		/* we pull the data from the surface using the facelist data */
+		for ( i = 0 ; i < 3 ; i ++ )
+		{
+			xyz[i]    = (picoVec3_t*) PicoGetSurfaceXYZ   ( surface, face->index[ i ] );
+			normal[i] = (picoVec3_t*) PicoGetSurfaceNormal( surface, face->index[ i ] );								
+			st[i]     = (picoVec2_t*) PicoGetSurfaceST    ( surface, 0, face->index[ i + 3 ] );
+			
+			if ( face->index [ i + 6] >= 0 )
+			{
+				color[i]  = (picoColor_t*)PicoGetSurfaceColor ( surface, 0, face->index[ i + 6 ] );
+			}
+			else
+			{
+				color[i] = &white;
+			}
+			
+		}
+
+		/* submit the triangle to the model */
+		PicoAddTriangleToModel ( model , xyz , normal , 1 , st , 1 , color , subMtl->shader );
+
+		/* advance to the next face */
+		face = face->next;		
+	}	
+}
+
+/* _ase_load:
+ *  loads a 3dsmax ase model file.
+*/
+static picoModel_t *_ase_load( PM_PARAMS_LOAD )
+{
+	picoModel_t    *model;
+	picoSurface_t  *surface = NULL;
+	picoParser_t   *p;
+	char			lastNodeName[ 1024 ];
+
+	aseFace_t* faces = NULL;
+	aseFace_t* facesTail = NULL;
+	aseMaterial_t* materials = NULL;
+
+#ifdef DEBUG_PM_ASE
+	clock_t start, finish;
+	double elapsed;
+	start = clock();
+#endif
+
+	/* helper */
+	#define _ase_error_return(m) \
+	{ \
+		_pico_printf( PICO_ERROR,"%s in ASE, line %d.",m,p->curLine); \
+		_pico_free_parser( p ); \
+		PicoFreeModel( model ); \
+		return NULL; \
+	}
+	/* create a new pico parser */
+	p = _pico_new_parser( (picoByte_t *)buffer,bufSize );
+	if (p == NULL) return NULL;
+
+	/* create a new pico model */
+	model = PicoNewModel();
+	if (model == NULL)
+	{
+		_pico_free_parser( p );
+		return NULL;
+	}
+	/* do model setup */
+	PicoSetModelFrameNum( model, frameNum );
+	PicoSetModelName( model, fileName );
+	PicoSetModelFileName( model, fileName );
+
+	/* initialize some stuff */
+	memset( lastNodeName,0,sizeof(lastNodeName) );
+
+	/* parse ase model file */
+	while( 1 )
+	{
+		/* get first token on line */
+		if (_pico_parse_first( p ) == NULL)
+			break;
+
+		/* we just skip empty lines */
+		if (p->token == NULL || !strlen( p->token ))
+			continue;
+
+		/* we skip invalid ase statements */
+		if (p->token[0] != '*' && p->token[0] != '{' && p->token[0] != '}')
+		{
+			_pico_parse_skip_rest( p );
+			continue;
+		}
+		/* remember node name */
+		if (!_pico_stricmp(p->token,"*node_name"))
+		{
+			/* read node name */
+			char *ptr = _pico_parse( p,0 );
+			if (ptr == NULL)
+				_ase_error_return("Node name parse error");
+
+			/* remember node name */
+			strncpy( lastNodeName,ptr,sizeof(lastNodeName) );
+		}
+		/* model mesh (originally contained within geomobject) */
+		else if (!_pico_stricmp(p->token,"*mesh"))
+		{
+			/* finish existing surface */
+			//_ase_make_surface( model, &surface );
+			_ase_submit_triangles (surface, model ,materials,faces);
+			_ase_free_faces (&faces,&facesTail);
+						
+			/* allocate new pico surface */
+			surface = PicoNewSurface( NULL );
+			if (surface == NULL)
+			{
+				PicoFreeModel( model );
+				return NULL;
+			}
+		}
+		/* mesh material reference. this usually comes at the end of */
+		/* geomobjects after the mesh blocks. we must assume that the */
+		/* new mesh was already created so all we can do here is assign */
+		/* the material reference id (shader index) now. */
+		else if (!_pico_stricmp(p->token,"*material_ref"))
+		{
+			int mtlId;
+			aseFace_t* face;
+
+			/* we must have a valid surface */
+			if( surface == NULL )
+				_ase_error_return("Missing mesh for material reference");
+
+			/* get the material ref (0..n) */
+			if (!_pico_parse_int( p,&mtlId) )
+				_ase_error_return("Missing material reference ID");
+
+			/* fix up all of the aseFaceList in the surface to point to the parent material */
+			/* we've already saved off their subMtl */
+			face = faces;
+			while ( face != NULL )
+			{
+				face->mtlId = mtlId;
+				face = face->next;
+			}
+		}
+		/* model mesh vertex */
+		else if (!_pico_stricmp(p->token,"*mesh_vertex"))
+		{
+			picoVec3_t	v;
+			int			index;
+
+			/* we must have a valid surface */
+			if( surface == NULL )
+				continue;
+
+			/* get vertex data (orig: index +y -x +z) */
+			if (!_pico_parse_int( p,&index ))
+				_ase_error_return("Vertex parse error");
+			if (!_pico_parse_vec( p,v ))
+				_ase_error_return("Vertex parse error");
+
+			/* set vertex */
+			PicoSetSurfaceXYZ( surface,index,v );
+		}
+		/* model mesh vertex normal */
+		else if (!_pico_stricmp(p->token,"*mesh_vertexnormal"))
+		{
+			picoVec3_t	v;
+			int			index;
+
+			/* we must have a valid surface */
+			if( surface == NULL )
+				continue;
+
+			/* get vertex data (orig: index +y -x +z) */
+			if (!_pico_parse_int( p,&index ))
+				_ase_error_return("Vertex parse error");
+			if (!_pico_parse_vec( p,v ))
+				_ase_error_return("Vertex parse error");
+
+			/* set vertex */
+			PicoSetSurfaceNormal( surface,index,v );
+		}
+		/* model mesh face */
+		else if (!_pico_stricmp(p->token,"*mesh_face"))
+		{
+			picoIndex_t indexes[3];
+			int			index;
+
+			/* we must have a valid surface */
+			if( surface == NULL )
+				continue;
+
+			/* get face index */
+			if (!_pico_parse_int( p,&index ))
+				_ase_error_return("Face parse error");
+
+			/* get 1st vertex index */
+			_pico_parse( p,0 );
+			if (!_pico_parse_int( p,&indexes[0] ))
+				_ase_error_return("Face parse error");
+
+			/* get 2nd vertex index */
+			_pico_parse( p,0 );
+			if (!_pico_parse_int( p,&indexes[1] ))
+				_ase_error_return("Face parse error");
+
+			/* get 3rd vertex index */
+			_pico_parse( p,0 );
+			if (!_pico_parse_int( p,&indexes[2] ))
+				_ase_error_return("Face parse error");
+
+			/* set face indexes (note interleaved offset!) */
+			PicoSetSurfaceIndex( surface, (index * 9 + 0), indexes[2] );
+			PicoSetSurfaceIndex( surface, (index * 9 + 1), indexes[1] );
+			PicoSetSurfaceIndex( surface, (index * 9 + 2), indexes[0] );
+			
+			/* parse to the subMaterial ID */
+			while ( 1 )
+			{
+				_pico_parse (p,0);
+				if (!_pico_stricmp (p->token,"*MESH_MTLID" ))
+				{
+					aseFace_t* newFace;
+					int subMtlId;
+					
+					_pico_parse_int ( p , &subMtlId );
+					newFace = _pico_calloc ( 1 , sizeof ( aseFace_t ));
+					
+					/* we fix up the mtlId later when we parse the material_ref */
+					newFace->mtlId = 0;	
+					newFace->subMtlId = subMtlId;
+					newFace->index[0] = indexes[2];
+					newFace->index[1] = indexes[1];
+					newFace->index[2] = indexes[0];
+
+					_ase_add_face ( &faces,&facesTail,newFace );
+					break;
+				}
+			}
+			
+		}
+		/* model texture vertex */
+		else if (!_pico_stricmp(p->token,"*mesh_tvert"))
+		{
+			picoVec2_t	uv;
+			int			index;
+
+			/* we must have a valid surface */
+			if( surface == NULL )
+				continue;
+
+			/* get uv vertex index */
+			if (!_pico_parse_int( p,&index ))
+				_ase_error_return("UV vertex parse error");
+
+			/* get uv vertex s */
+			if (!_pico_parse_float( p,&uv[0] ))
+				_ase_error_return("UV vertex parse error");
+
+			/* get uv vertex t */
+			if (!_pico_parse_float( p,&uv[1] ))
+				_ase_error_return("UV vertex parse error");
+			
+			/* ydnar: invert t */
+			uv[ 1 ] = 1.0f - uv[ 1 ];
+			
+			/* set texture vertex */
+			PicoSetSurfaceST( surface,0,index,uv );
+		}
+		/* ydnar: model mesh texture face */
+		else if( !_pico_stricmp( p->token, "*mesh_tface" ) )
+		{
+			picoIndex_t indexes[3];
+			int			index;
+			aseFace_t* face;
+			
+			/* we must have a valid surface */
+			if( surface == NULL )
+				continue;
+			
+			/* get face index */
+			if (!_pico_parse_int( p,&index ))
+				_ase_error_return("Texture face parse error");
+			
+			/* get 1st vertex index */
+			if (!_pico_parse_int( p,&indexes[0] ))
+				_ase_error_return("Texture face parse error");
+			
+			/* get 2nd vertex index */
+			if (!_pico_parse_int( p,&indexes[1] ))
+				_ase_error_return("Texture face parse error");
+			
+			/* get 3rd vertex index */
+			if (!_pico_parse_int( p,&indexes[2] ))
+				_ase_error_return("Texture face parse error");
+			
+			/* set face indexes (note interleaved offset!) */
+			PicoSetSurfaceIndex( surface, (index * 9 + 3), indexes[2] );
+			PicoSetSurfaceIndex( surface, (index * 9 + 4), indexes[1] );
+			PicoSetSurfaceIndex( surface, (index * 9 + 5), indexes[0] );
+
+			face = _ase_get_face_for_index(faces,index);
+			face->index[3] = indexes[2];
+			face->index[4] = indexes[1];
+			face->index[5] = indexes[0];
+		}
+		/* model color vertex */
+		else if (!_pico_stricmp(p->token,"*mesh_vertcol"))
+		{
+			picoColor_t	color;
+			int			index;
+			float		colorInput;
+
+			/* we must have a valid surface */
+			if( surface == NULL )
+				continue;
+
+			/* get color vertex index */
+			if (!_pico_parse_int( p,&index ))
+				_ase_error_return("UV vertex parse error");
+
+			/* get R component */
+			if (!_pico_parse_float( p,&colorInput ))
+				_ase_error_return("color vertex parse error");
+			color[0] = (picoByte_t)(colorInput * 255);
+
+			/* get G component */
+			if (!_pico_parse_float( p,&colorInput ))
+				_ase_error_return("color vertex parse error");
+			color[1] = (picoByte_t)(colorInput * 255);
+
+			/* get B component */
+			if (!_pico_parse_float( p,&colorInput ))
+				_ase_error_return("color vertex parse error");
+			color[2] = (picoByte_t)(colorInput * 255);
+			
+			/* leave alpha alone since we don't get any data from the ASE format */
+			color[3] = 255;
+
+			/* set texture vertex */
+			PicoSetSurfaceColor( surface,0,index,color );
+		}
+		/* model color face */
+		else if (!_pico_stricmp(p->token,"*mesh_cface"))
+		{
+			picoIndex_t indexes[3];
+			int			index;
+			aseFace_t*  face;
+
+			/* we must have a valid surface */
+			if( surface == NULL )
+				continue;
+
+			/* get face index */
+			if (!_pico_parse_int( p,&index ))
+				_ase_error_return("Face parse error");
+
+			/* get 1st cvertex index */
+			//			_pico_parse( p,0 );
+			if (!_pico_parse_int( p,&indexes[0] ))
+				_ase_error_return("Face parse error");
+
+			/* get 2nd cvertex index */
+			//			_pico_parse( p,0 );
+			if (!_pico_parse_int( p,&indexes[1] ))
+				_ase_error_return("Face parse error");
+
+			/* get 3rd cvertex index */
+			//			_pico_parse( p,0 );
+			if (!_pico_parse_int( p,&indexes[2] ))
+				_ase_error_return("Face parse error");
+
+			/* set face indexes (note interleaved offset!) */
+			PicoSetSurfaceIndex( surface, (index * 9 + 6), indexes[2] );
+			PicoSetSurfaceIndex( surface, (index * 9 + 7), indexes[1] );
+			PicoSetSurfaceIndex( surface, (index * 9 + 8), indexes[0] );
+
+			face = _ase_get_face_for_index(faces,index);
+			face->index[6] = indexes[2];
+			face->index[7] = indexes[1];
+			face->index[8] = indexes[0];
+		}
+		/* model material */
+		else if( !_pico_stricmp( p->token, "*material" ) )
+		{
+			aseSubMaterial_t*	subMaterial = NULL;
+			picoShader_t		*shader;
+			int					level = 1, index;
+			char				materialName[ 1024 ];
+			float				transValue = 0.0f, shineValue = 1.0f;
+			picoColor_t			ambientColor, diffuseColor, specularColor;
+			char				*mapname = NULL;
+			int					subMtlId, subMaterialLevel = -1;
+			
+			
+			/* get material index */
+			_pico_parse_int( p,&index );
+			
+			/* check brace */
+			if (!_pico_parse_check(p,1,"{"))
+				_ase_error_return("Material missing opening brace");
+			
+			/* parse material block */
+			while( 1 )
+			{
+				/* get next token */
+				if (_pico_parse(p,1) == NULL) break;
+				if (!strlen(p->token)) continue;
+
+				/* handle levels */
+				if (p->token[0] == '{') level++;
+				if (p->token[0] == '}') level--;
+				if (!level) break;
+
+				if( level == subMaterialLevel )
+				{
+					/* set material name */
+					PicoSetShaderName( shader, materialName);
+
+					/* set shader's transparency */
+					PicoSetShaderTransparency( shader,transValue );
+
+					/* set shader's ambient color */
+					PicoSetShaderAmbientColor( shader,ambientColor );
+
+					/* set diffuse alpha to transparency */
+					diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
+
+					/* set shader's diffuse color */
+					PicoSetShaderDiffuseColor( shader,diffuseColor );
+
+					/* set shader's specular color */
+					PicoSetShaderSpecularColor( shader,specularColor );
+
+					/* set shader's shininess */
+					PicoSetShaderShininess( shader,shineValue );
+
+					/* set material map name */
+					PicoSetShaderMapName( shader, mapname );
+
+					subMaterial = _ase_add_submaterial( &materials, index, subMtlId, shader );
+					subMaterialLevel = -1;
+				}
+
+				/* parse submaterial index */
+				if (!_pico_stricmp(p->token,"*submaterial"))
+				{											
+					/* allocate new pico shader */
+					_pico_parse_int( p , &subMtlId );
+
+					shader = PicoNewShader( model );
+					if (shader == NULL)
+					{
+						PicoFreeModel( model );
+						return NULL;
+					}			
+					subMaterialLevel = level;
+				}
+				/* parse material name */
+				else if (!_pico_stricmp(p->token,"*material_name"))
+				{
+					char* name = _pico_parse(p,0);
+					if ( name == NULL)
+						_ase_error_return("Missing material name");
+					
+					strcpy ( materialName , name );
+					/* skip rest and continue with next token */
+					_pico_parse_skip_rest( p );
+					continue;
+				}
+				/* parse material transparency */
+				else if (!_pico_stricmp(p->token,"*material_transparency"))
+				{
+					/* get transparency value from ase */
+					if (!_pico_parse_float( p,&transValue ))
+						_ase_error_return("Material transparency parse error");
+
+					/* skip rest and continue with next token */
+					_pico_parse_skip_rest( p );
+					continue;
+				}
+				/* parse material shininess */
+				else if (!_pico_stricmp(p->token,"*material_shine"))
+				{
+					/* remark:
+					 * - not sure but instead of '*material_shine' i might
+					 *   need to use '*material_shinestrength' */
+
+					/* get shine value from ase */
+					if (!_pico_parse_float( p,&shineValue ))
+						_ase_error_return("Material shine parse error");
+
+					/* scale ase shine range 0..1 to pico range 0..127 */
+					shineValue *= 128.0;
+
+					/* skip rest and continue with next token */
+					_pico_parse_skip_rest( p );
+					continue;
+				}
+				/* parse ambient material color */
+				else if (!_pico_stricmp(p->token,"*material_ambient"))
+				{
+					picoVec3_t  vec;
+					/* get r,g,b float values from ase */
+					if (!_pico_parse_vec( p,vec ))
+						_ase_error_return("Material color parse error");
+
+					/* setup 0..255 range color values */
+					ambientColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
+					ambientColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
+					ambientColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
+					ambientColor[ 3 ] = (int)( 255 );
+
+					/* skip rest and continue with next token */
+					_pico_parse_skip_rest( p );
+					continue;
+				}
+				/* parse diffuse material color */
+				else if (!_pico_stricmp(p->token,"*material_diffuse"))
+				{
+					picoVec3_t  vec;
+
+					/* get r,g,b float values from ase */
+					if (!_pico_parse_vec( p,vec ))
+						_ase_error_return("Material color parse error");
+
+					/* setup 0..255 range color */
+					diffuseColor[ 0 ] = (int)( vec[ 0 ] * 255.0 );
+					diffuseColor[ 1 ] = (int)( vec[ 1 ] * 255.0 );
+					diffuseColor[ 2 ] = (int)( vec[ 2 ] * 255.0 );
+					diffuseColor[ 3 ] = (int)( 255 );
+
+					/* skip rest and continue with next token */
+					_pico_parse_skip_rest( p );
+					continue;
+				}
+				/* parse specular material color */
+				else if (!_pico_stricmp(p->token,"*material_specular"))
+				{
+					picoVec3_t  vec;
+
+					/* get r,g,b float values from ase */
+					if (!_pico_parse_vec( p,vec ))
+						_ase_error_return("Material color parse error");
+
+					/* setup 0..255 range color */
+					specularColor[ 0 ] = (int)( vec[ 0 ] * 255 );
+					specularColor[ 1 ] = (int)( vec[ 1 ] * 255 );
+					specularColor[ 2 ] = (int)( vec[ 2 ] * 255 );
+					specularColor[ 3 ] = (int)( 255 );
+
+					/* skip rest and continue with next token */
+					_pico_parse_skip_rest( p );
+					continue;
+				}
+				/* material diffuse map */
+				else if (!_pico_stricmp(p->token,"*map_diffuse") )
+				{
+					int sublevel = 0;
+
+					/* parse material block */
+					while( 1 )
+					{
+						/* get next token */
+						if (_pico_parse(p,1) == NULL) break;
+						if (!strlen(p->token)) continue;
+						
+						/* handle levels */
+						if (p->token[0] == '{') sublevel++;
+						if (p->token[0] == '}') sublevel--;
+						if (!sublevel) break;
+						
+						/* parse diffuse map bitmap */
+						if (!_pico_stricmp(p->token,"*bitmap"))
+						{
+							char* name = _pico_parse(p,0);
+							if (name == NULL)
+								_ase_error_return("Missing material map bitmap name");
+							mapname = _pico_alloc ( strlen ( name ) + 1 );
+							strcpy ( mapname, name );
+							/* skip rest and continue with next token */
+							_pico_parse_skip_rest( p );
+							continue;
+						}
+					}
+				}
+				/* end map_diffuse block */
+			}
+			/* end material block */
+
+			if( subMaterial == NULL )
+			{
+				/* allocate new pico shader */
+				shader = PicoNewShader( model );
+				if (shader == NULL)
+				{
+					PicoFreeModel( model );
+					return NULL;
+				}
+
+				/* set material name */
+				PicoSetShaderName( shader,materialName );
+
+				/* set shader's transparency */
+				PicoSetShaderTransparency( shader,transValue );
+
+				/* set shader's ambient color */
+				PicoSetShaderAmbientColor( shader,ambientColor );
+
+				/* set diffuse alpha to transparency */
+				diffuseColor[3] = (picoByte_t)( transValue * 255.0 );
+
+				/* set shader's diffuse color */
+				PicoSetShaderDiffuseColor( shader,diffuseColor );
+
+				/* set shader's specular color */
+				PicoSetShaderSpecularColor( shader,specularColor );
+
+				/* set shader's shininess */
+				PicoSetShaderShininess( shader,shineValue );
+
+				/* set material map name */
+				PicoSetShaderMapName( shader, mapname );
+
+				/* this is just a material with 1 submaterial */
+				subMaterial = _ase_add_submaterial( &materials, index, 0, shader );
+			}
+			
+			/* ydnar: free mapname */
+			if( mapname != NULL )
+				_pico_free( mapname );
+		}	// !_pico_stricmp ( "*material" )
+
+		/* skip unparsed rest of line and continue */
+		_pico_parse_skip_rest( p );
+	}
+	
+	/* ydnar: finish existing surface */
+//	_ase_make_surface( model, &surface );
+	_ase_submit_triangles (surface, model ,materials,faces);
+	_ase_free_faces (&faces,&facesTail);
+
+#ifdef DEBUG_PM_ASE
+	_ase_print_materials(materials);
+	finish = clock();
+	elapsed = (double)(finish - start) / CLOCKS_PER_SEC;
+	_pico_printf( PICO_NORMAL, "Loaded model in in %-.2f second(s)\n", elapsed );
+#endif //DEBUG_PM_ASE
+
+	_ase_free_materials(&materials);
+
+	/* return allocated pico model */
+	return model;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModuleASE =
+{
+	"1.0",					/* module version string */
+	"Autodesk 3DSMAX ASCII",	/* module display name */
+	"Jared Hefty, seaw0lf",					/* author's name */
+	"2003 Jared Hefty, 2002 seaw0lf",				/* module copyright */
+	{
+		"ase",NULL,NULL,NULL	/* default extensions to use */
+	},
+	_ase_canload,				/* validation routine */
+	_ase_load,					/* load routine */
+	 NULL,						/* save validation routine */
+	 NULL						/* save routine */
+};
diff --git a/libs/picomodel/pm_fm.c b/libs/picomodel/pm_fm.c
index c6f8e538..bb3216c3 100644
--- a/libs/picomodel/pm_fm.c
+++ b/libs/picomodel/pm_fm.c
@@ -1,670 +1,670 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-/*
-Nurail: Used pm_md3.c (Randy Reddig) as a template.
-*/
-
-/* marker */
-#define PM_FM_C
-
-/* dependencies */
-#include "pm_fm.h"
-
-//#define FM_VERBOSE_DBG	0
-#undef FM_VERBOSE_DBG
-#undef FM_DBG
-
-typedef struct index_LUT_s
-{
-	short	Vert;
-	short	ST;
-	struct	index_LUT_s	*next;
-
-} index_LUT_t;
-
-typedef struct index_DUP_LUT_s
-{
-	short			ST;
-	short			OldVert;
-
-} index_DUP_LUT_t;
-
-
-// _fm_canload()
-static int _fm_canload( PM_PARAMS_CANLOAD )
-{
-	fm_t		fm;
-	unsigned char	*bb;
-	int		fm_file_pos;
-
-	bb = (unsigned char *) buffer;
-
-	// Header
-	fm.fm_header_hdr = (fm_chunk_header_t *) bb;
-	fm_file_pos = sizeof(fm_chunk_header_t) + fm.fm_header_hdr->size;
-#ifdef FM_VERBOSE_DBG
-	_pico_printf( PICO_VERBOSE, "IDENT: %s\n", (unsigned char *) fm.fm_header_hdr->ident );
-#endif
-	if( (strcmp(fm.fm_header_hdr->ident, FM_HEADERCHUNKNAME))  )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Header Ident incorrect\n");
-#endif
-		return PICO_PMV_ERROR_IDENT;
-	}
-
-	// check fm
-	if( _pico_little_long( fm.fm_header_hdr->version ) != FM_HEADERCHUNKVER )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Header Version incorrect\n");
-#endif
-		return PICO_PMV_ERROR_VERSION;
-	}
-
-	// Skin
-	fm.fm_skin_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_skin_hdr->size;
-#ifdef FM_VERBOSE_DBG
-	_pico_printf( PICO_VERBOSE, "SKIN: %s\n", (unsigned char *) fm.fm_skin_hdr->ident );
-#endif
-	if( (strcmp(fm.fm_skin_hdr->ident, FM_SKINCHUNKNAME)) )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Skin Ident incorrect\n");
-#endif
-		return PICO_PMV_ERROR_IDENT;
-	}
-
-	// check fm
-	if( _pico_little_long( fm.fm_skin_hdr->version ) != FM_SKINCHUNKVER )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Skin Version incorrect\n");
-#endif
-		return PICO_PMV_ERROR_VERSION;
-	}
-
-	// st
-	fm.fm_st_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_st_hdr->size;
-#ifdef FM_VERBOSE_DBG
-	_pico_printf( PICO_VERBOSE, "ST: %s\n", (unsigned char *) fm.fm_st_hdr->ident );
-#endif
-	if( (strcmp(fm.fm_st_hdr->ident, FM_STCOORDCHUNKNAME)) )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM ST Ident incorrect\n");
-#endif
-		return PICO_PMV_ERROR_IDENT;
-	}
-
-	// check fm
-	if( _pico_little_long( fm.fm_st_hdr->version ) != FM_STCOORDCHUNKVER )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM ST Version incorrect\n");
-#endif
-		return PICO_PMV_ERROR_VERSION;
-	}
-
-	// tri
-	fm.fm_tri_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_tri_hdr->size;
-#ifdef FM_VERBOSE_DBG
-	_pico_printf( PICO_VERBOSE, "TRI: %s\n", (unsigned char *) fm.fm_tri_hdr->ident );
-#endif
-	if( (strcmp(fm.fm_tri_hdr->ident, FM_TRISCHUNKNAME)) )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Tri Ident incorrect\n");
-#endif
-		return PICO_PMV_ERROR_IDENT;
-	}
-
-	// check fm
-	if( _pico_little_long( fm.fm_tri_hdr->version ) != FM_TRISCHUNKVER )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Tri Version incorrect\n");
-#endif
-		return PICO_PMV_ERROR_VERSION;
-	}
-
-	// frame
-	fm.fm_frame_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t);
-#ifdef FM_VERBOSE_DBG
-	_pico_printf( PICO_VERBOSE, "FRAME: %s\n", (unsigned char *) fm.fm_frame_hdr->ident );
-#endif
-	if( (strcmp(fm.fm_frame_hdr->ident, FM_FRAMESCHUNKNAME)) )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Frame Ident incorrect\n");
-#endif
-		return PICO_PMV_ERROR_IDENT;
-	}
-
-	// check fm
-	if( _pico_little_long( fm.fm_frame_hdr->version ) != FM_FRAMESCHUNKVER )
-	{
-#ifdef FM_DBG
-		_pico_printf( PICO_WARNING, "FM Frame Version incorrect\n");
-#endif
-		return PICO_PMV_ERROR_VERSION;
-	}
-
-	// file seems to be a valid fm
-	return PICO_PMV_OK;
-}
-
-
-
-// _fm_load() loads a Heretic 2 model file.
-static picoModel_t *_fm_load( PM_PARAMS_LOAD )
-{
-	int				i, j, dups, dup_index;
-	int				fm_file_pos;
-	short			tot_numVerts;
-	index_LUT_t		*p_index_LUT, *p_index_LUT2, *p_index_LUT3;
-	index_DUP_LUT_t	*p_index_LUT_DUPS;
-
-	fm_vert_normal_t	*vert;
-
-	char			skinname[FM_SKINPATHSIZE];
- 	fm_t			fm;
-	fm_header_t		*fm_head;
-	fm_st_t			*texCoord;
-	fm_xyz_st_t		*tri_verts;
-	fm_xyz_st_t		*triangle;
-	fm_frame_t		*frame;
-
-	picoByte_t      *bb;
-	picoModel_t	*picoModel;
-	picoSurface_t	*picoSurface;
-	picoShader_t	*picoShader;
-	picoVec3_t	xyz, normal;
-	picoVec2_t	st;
-	picoColor_t	color;
-	
-
-	// fm loading
- 	_pico_printf( PICO_NORMAL, "Loading \"%s\"", fileName );
-
-	bb = (picoByte_t*) buffer;
-
-	// Header Header
-	fm.fm_header_hdr = (fm_chunk_header_t *) bb;
-	fm_file_pos = sizeof(fm_chunk_header_t) + fm.fm_header_hdr->size;
-	if( (strcmp(fm.fm_header_hdr->ident, FM_HEADERCHUNKNAME))  )
-	{
-		_pico_printf( PICO_WARNING, "FM Header Ident incorrect\n");
-		return NULL;
-	}
-
-	if( _pico_little_long( fm.fm_header_hdr->version ) != FM_HEADERCHUNKVER )
-	{
-		_pico_printf( PICO_WARNING, "FM Header Version incorrect\n");
-		return NULL;
-	}
-
-	// Skin Header
-	fm.fm_skin_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_skin_hdr->size;
-	if( (strcmp(fm.fm_skin_hdr->ident, FM_SKINCHUNKNAME)) )
-	{
-		_pico_printf( PICO_WARNING, "FM Skin Ident incorrect\n");
-		return NULL;
-	}
-
-	if( _pico_little_long( fm.fm_skin_hdr->version ) != FM_SKINCHUNKVER )
-	{
-		_pico_printf( PICO_WARNING, "FM Skin Version incorrect\n");
-		return NULL;
-	}
-
-	// ST Header
-	fm.fm_st_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_st_hdr->size;
-	if( (strcmp(fm.fm_st_hdr->ident, FM_STCOORDCHUNKNAME)) )
-	{
-		_pico_printf( PICO_WARNING, "FM ST Ident incorrect\n");
-		return NULL;
-	}
-
-	if( _pico_little_long( fm.fm_st_hdr->version ) != FM_STCOORDCHUNKVER )
-	{
-		_pico_printf( PICO_WARNING, "FM ST Version incorrect\n");
-		return NULL;
-	}
-
-	// Tris Header
-	fm.fm_tri_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_tri_hdr->size;
-	if( (strcmp(fm.fm_tri_hdr->ident, FM_TRISCHUNKNAME)) )
-	{
-		_pico_printf( PICO_WARNING, "FM Tri Ident incorrect\n");
-		return NULL;
-	}
-
-	if( _pico_little_long( fm.fm_tri_hdr->version ) != FM_TRISCHUNKVER )
-	{
-		_pico_printf( PICO_WARNING, "FM Tri Version incorrect\n");
-		return NULL;
-	}
-
-	// Frame Header
-	fm.fm_frame_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
-	fm_file_pos += sizeof(fm_chunk_header_t);
-	if( (strcmp(fm.fm_frame_hdr->ident, FM_FRAMESCHUNKNAME)) )
-	{
-		_pico_printf( PICO_WARNING, "FM Frame Ident incorrect\n");
-		return NULL;
-	}
-
-	if( _pico_little_long( fm.fm_frame_hdr->version ) != FM_FRAMESCHUNKVER )
-	{
-		_pico_printf( PICO_WARNING, "FM Frame Version incorrect\n");
-		return NULL;
-	}
-
-	// Header
-	fm_file_pos = sizeof(fm_chunk_header_t);
-	fm_head = fm.fm_header = (fm_header_t *) (bb + fm_file_pos);
-	fm_file_pos += fm.fm_header_hdr->size;
-
-	// Skin
-	fm_file_pos += sizeof(fm_chunk_header_t);
-	fm.fm_skin = (fm_skinpath_t *) (bb + fm_file_pos);
-	fm_file_pos += fm.fm_skin_hdr->size;
-
-	// ST
-	fm_file_pos += sizeof(fm_chunk_header_t);
-	texCoord = fm.fm_st = (fm_st_t *) (bb + fm_file_pos);
-	fm_file_pos += fm.fm_st_hdr->size;
-
-	// Tri
-	fm_file_pos += sizeof(fm_chunk_header_t);
-	tri_verts = fm.fm_tri = (fm_xyz_st_t *) (bb + fm_file_pos);
-	fm_file_pos += fm.fm_tri_hdr->size;
-
-	// Frame
-	fm_file_pos += sizeof(fm_chunk_header_t);
-	frame = fm.fm_frame = (fm_frame_t *) (bb + fm_file_pos);
-
-	// do frame check
-	if( fm_head->numFrames < 1 )
-	{
-		_pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
-		return NULL;
-	}
-	
-	if( frameNum < 0 || frameNum >= fm_head->numFrames )
-	{
-		_pico_printf( PICO_ERROR, "Invalid or out-of-range FM frame specified" );
-		return NULL;
-	}
-
-	// swap fm
-	fm_head->skinWidth = _pico_little_long( fm_head->skinWidth );
-	fm_head->skinHeight = _pico_little_long( fm_head->skinHeight );
-	fm_head->frameSize = _pico_little_long( fm_head->frameSize );
-
-	fm_head->numSkins = _pico_little_long( fm_head->numSkins );
-	fm_head->numXYZ = _pico_little_long( fm_head->numXYZ );
-	fm_head->numST = _pico_little_long( fm_head->numST );
-	fm_head->numTris = _pico_little_long( fm_head->numTris );
-	fm_head->numGLCmds = _pico_little_long( fm_head->numGLCmds );
-	fm_head->numFrames = _pico_little_long( fm_head->numFrames );
-
-	// swap frame scale and translation
-	for( i = 0; i < 3; i++ )
-	{
-		frame->header.scale[ i ] = _pico_little_float( frame->header.scale[ i ] );
-		frame->header.translate[ i ] = _pico_little_float( frame->header.translate[ i ] );
-	}
-
-	// swap triangles
-	triangle = tri_verts;
-	for( i = 0; i < fm_head->numTris; i++, triangle++ )
-	{
-		for( j = 0; j < 3; j++ )
-		{
-			triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
-			triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
-		}
-	}
-
-	// swap st coords
-	for( i = 0; i < fm_head->numST; i++ )
-	{
-		texCoord->s = _pico_little_short( texCoord[i].s );
-		texCoord->t = _pico_little_short( texCoord[i].t );
-	}
-	// set Skin Name
-	strncpy(skinname, (unsigned char *) fm.fm_skin, FM_SKINPATHSIZE );
-
-#ifdef FM_VERBOSE_DBG
-	// Print out md2 values
-	_pico_printf(PICO_VERBOSE,"numSkins->%d  numXYZ->%d  numST->%d  numTris->%d  numFrames->%d\nSkin Name \"%s\"\n", fm_head->numSkins, fm_head->numXYZ, fm_head->numST, fm_head->numTris, fm_head->numFrames, &skinname );
-#endif
-
-	// detox Skin name
-	_pico_setfext( skinname, "" );
-	_pico_unixify( skinname );
-
-	/* create new pico model */
-	picoModel = PicoNewModel();
-	if( picoModel == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
-		return NULL;
-	}
-
-	/* do model setup */
-	PicoSetModelFrameNum( picoModel, frameNum );
-	PicoSetModelNumFrames( picoModel, fm_head->numFrames ); /* sea */
-	PicoSetModelName( picoModel, fileName );
-	PicoSetModelFileName( picoModel, fileName );
-
-	// allocate new pico surface
-	picoSurface = PicoNewSurface( picoModel );
-	if( picoSurface == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
-		PicoFreeModel( picoModel );
-		return NULL;
-	}
-
-
-	PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
-	PicoSetSurfaceName( picoSurface, frame->header.name );
-	picoShader = PicoNewShader( picoModel );
-	if( picoShader == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
-		PicoFreeModel( picoModel );
-		return NULL;
-	}
-
-	PicoSetShaderName( picoShader, skinname );
-
-	// associate current surface with newly created shader
-	PicoSetSurfaceShader( picoSurface, picoShader );
-
-	// Init LUT for Verts
-	p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * fm_head->numXYZ);
-	for(i=0; i<fm_head->numXYZ; i++)
-	{
-		p_index_LUT[i].Vert = -1;
-		p_index_LUT[i].ST = -1;
-		p_index_LUT[i].next = NULL;
-	}
-
-	// Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
-	tot_numVerts = fm_head->numXYZ;
-	dups = 0;
-	triangle = tri_verts;
-
-	for(i=0; i<fm_head->numTris; i++)
-	{
-		for(j=0; j<3; j++)
-		{
-			if (p_index_LUT[triangle->index_xyz[j]].ST == -1) // No Main Entry
-				p_index_LUT[triangle->index_xyz[j]].ST = triangle->index_st[j];
-
-			else if (triangle->index_st[j] == p_index_LUT[triangle->index_xyz[j]].ST ) // Equal to Main Entry
-			{
-#ifdef FM_VERBOSE_DBG
-				_pico_printf( PICO_NORMAL, "-> Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
-#endif
-				continue;
-			}
-			else if ( (p_index_LUT[triangle->index_xyz[j]].next == NULL) )  // Not equal to Main entry, and no LL entry
-			{	// Add first entry of LL from Main
-				p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
-				if (p_index_LUT2 == NULL)
-					_pico_printf( PICO_NORMAL, " Couldn't allocate memory!\n");
-				p_index_LUT[triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
-				p_index_LUT2->Vert = dups;
-				p_index_LUT2->ST = triangle->index_st[j];
-				p_index_LUT2->next = NULL;
-#ifdef FM_VERBOSE_DBG
-				_pico_printf( PICO_NORMAL, " ADDING first LL XYZ:%d DUP:%d ST:%d\n", triangle->index_xyz[j], dups, triangle->index_st[j]);
-#endif
-				triangle->index_xyz[j] = dups + fm_head->numXYZ; // Make change in Tri hunk
-				dups++;
-			}
-			else // Try to find in LL from Main Entry
-			{
-				p_index_LUT3 = p_index_LUT2 = p_index_LUT[triangle->index_xyz[j]].next;
-				while ( (p_index_LUT2 != NULL) && (triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
-				{
-					p_index_LUT3 = p_index_LUT2;
-					p_index_LUT2 = p_index_LUT2->next;
-				}
-				p_index_LUT2 = p_index_LUT3;
-
-				if ( triangle->index_st[j] == p_index_LUT2->ST ) // Found it
-				{
-					triangle->index_xyz[j] = p_index_LUT2->Vert + fm_head->numXYZ; // Make change in Tri hunk
-#ifdef FM_VERBOSE_DBG
-					_pico_printf( PICO_NORMAL, "--> Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
-#endif
-					continue;
-				}
-
-				if ( p_index_LUT2->next == NULL)  // Didn't find it. Add entry to LL.
-				{
-					// Add the Entry
-					p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
-					if (p_index_LUT3 == NULL)
-						_pico_printf( PICO_NORMAL, " Couldn't allocate memory!\n");
-					p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
-					p_index_LUT3->Vert = dups;
-					p_index_LUT3->ST = triangle->index_st[j];
-					p_index_LUT3->next = NULL;
-#ifdef FM_VERBOSE_DBG
-					_pico_printf( PICO_NORMAL, " ADDING additional LL XYZ:%d DUP:%d NewXYZ:%d ST:%d\n", triangle->index_xyz[j], dups, dups + (fm_head->numXYZ), triangle->index_st[j]);
-#endif
-					triangle->index_xyz[j] = dups + fm_head->numXYZ; // Make change in Tri hunk
-					dups++;
-				}
-			}
-#ifdef FM_VERBOSE_DBG
-			_pico_printf( PICO_NORMAL, "---> Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
-#endif
-		}
-		triangle++;
-	}
-
-	// malloc and build array for Dup STs
-	p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
-	if (p_index_LUT_DUPS == NULL)
-		_pico_printf( PICO_NORMAL, " Couldn't allocate memory!\n");
-
-	dup_index = 0;
-	for(i=0; i<fm_head->numXYZ; i++)
-	{
-		p_index_LUT2 = p_index_LUT[i].next;
-		while (p_index_LUT2 != NULL)
-		{
-			p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
-			p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
-			dup_index++;
-			p_index_LUT2 = p_index_LUT2->next;
-		}
-	}
-#ifdef FM_VERBOSE_DBG
-	_pico_printf( PICO_NORMAL, " Dups = %d\n", dups);
-	_pico_printf( PICO_NORMAL, " Dup Index = %d\n", dup_index);
-#endif
-	for(i=0; i<fm_head->numXYZ; i++)
-	{
-#ifdef FM_VERBOSE_DBG
-		_pico_printf( PICO_NORMAL, "Vert: %4d\t%4d",i, p_index_LUT[i].ST);
-#endif
-		if (p_index_LUT[i].next != NULL)
-		{
-
-			p_index_LUT2 = p_index_LUT[i].next;
-			do {
-#ifdef FM_VERBOSE_DBG
-				_pico_printf( PICO_NORMAL, " %4d %4d", p_index_LUT2->Vert, p_index_LUT2->ST);
-#endif
-				p_index_LUT2 = p_index_LUT2->next;
-			} while ( p_index_LUT2 != NULL);
-
-		}
-#ifdef FM_VERBOSE_DBG
-		_pico_printf( PICO_NORMAL, "\n");
-#endif
-	}
-
-
-#ifdef FM_VERBOSE_DBG
-	for(i=0; i<dup_index; i++)
-		_pico_printf( PICO_NORMAL, " Dup Index #%d  OldVert: %d  ST: %d\n", i, p_index_LUT_DUPS[i].OldVert, p_index_LUT_DUPS[i].ST);
-
-	triangle = tri_verts;
-	for(i=0; i<fm_head->numTris; i++)
-	{
-		for(j=0; j<3; j++)
-			_pico_printf( PICO_NORMAL, "Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
-		_pico_printf( PICO_NORMAL, "\n");
-		triangle++;
-	}
-#endif
-	// Build Picomodel
-	triangle = tri_verts;
-	for( j = 0; j < fm_head->numTris; j++, triangle++ )
-	{
-		PicoSetSurfaceIndex( picoSurface, j*3   , triangle->index_xyz[0] );
-		PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
-		PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
-	}
-
-	vert = (fm_vert_normal_t*) ((picoByte_t*) (frame->verts) );
-	for(i=0; i< fm_head->numXYZ; i++, vert++)
-	{
-		/* set vertex origin */
-		xyz[ 0 ] = vert->v[0] * frame->header.scale[0] + frame->header.translate[0];
-		xyz[ 1 ] = vert->v[1] * frame->header.scale[1] + frame->header.translate[1];
-		xyz[ 2 ] = vert->v[2] * frame->header.scale[2] + frame->header.translate[2];
-		PicoSetSurfaceXYZ( picoSurface, i , xyz );
-
-		/* set normal */
-		normal[ 0 ] = fm_normals[vert->lightnormalindex][0];
-		normal[ 1 ] = fm_normals[vert->lightnormalindex][1];
-		normal[ 2 ] = fm_normals[vert->lightnormalindex][2];
-		PicoSetSurfaceNormal( picoSurface, i , normal );
-
-		/* set st coords */
-		st[ 0 ] =  ((texCoord[p_index_LUT[i].ST].s) / ((float)fm_head->skinWidth));
-		st[ 1 ] =  (texCoord[p_index_LUT[i].ST].t / ((float)fm_head->skinHeight));
-		PicoSetSurfaceST( picoSurface, 0, i , st );
-	}
-
-	if (dups)
-	{
-		for(i=0; i<dups; i++)
-		{
-			j = p_index_LUT_DUPS[i].OldVert;
-			/* set vertex origin */
-			xyz[ 0 ] = frame->verts[j].v[0] * frame->header.scale[0] + frame->header.translate[0];
-			xyz[ 1 ] = frame->verts[j].v[1] * frame->header.scale[1] + frame->header.translate[1];
-			xyz[ 2 ] = frame->verts[j].v[2] * frame->header.scale[2] + frame->header.translate[2];
-			PicoSetSurfaceXYZ( picoSurface, i + fm_head->numXYZ , xyz );
-
-			/* set normal */
-			normal[ 0 ] = fm_normals[frame->verts[j].lightnormalindex][0];
-			normal[ 1 ] = fm_normals[frame->verts[j].lightnormalindex][1];
-			normal[ 2 ] = fm_normals[frame->verts[j].lightnormalindex][2];
-			PicoSetSurfaceNormal( picoSurface, i + fm_head->numXYZ , normal );
-
-			/* set st coords */
-			st[ 0 ] =  ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)fm_head->skinWidth));
-			st[ 1 ] =  (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)fm_head->skinHeight));
-			PicoSetSurfaceST( picoSurface, 0, i + fm_head->numXYZ , st );
-		}
-	}
-
-	/* set color */
-	PicoSetSurfaceColor( picoSurface, 0, 0, color );
-
-	// Free up malloc'ed LL entries
-	for(i=0; i<fm_head->numXYZ; i++)
-	{
-		if(p_index_LUT[i].next != NULL)
-		{
-			p_index_LUT2 = p_index_LUT[i].next;
-			do {
-				p_index_LUT3 = p_index_LUT2->next;
-				_pico_free(p_index_LUT2);
-				p_index_LUT2 = p_index_LUT3;
-				dups--;
-			} while (p_index_LUT2 != NULL);
-		}
-	}
-
-	if (dups)
-		_pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
-
-	// Free malloc'ed LUTs
- 	_pico_free(p_index_LUT);
-	_pico_free(p_index_LUT_DUPS);
-
-	/* return the new pico model */
-	return picoModel;
-
-}
-
-
-
-/* pico file format module definition */
-const picoModule_t picoModuleFM =
-{
-	"0.85",						/* module version string */
-	"Heretic 2 FM",				/* module display name */
-	"Nurail",					/* author's name */
-	"2003 Nurail",				/* module copyright */
-	{
-		"fm", NULL, NULL, NULL	/* default extensions to use */
-	},
-	_fm_canload,				/* validation routine */
-	_fm_load,					/* load routine */
-	 NULL,						/* save validation routine */
-	 NULL						/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+/*
+Nurail: Used pm_md3.c (Randy Reddig) as a template.
+*/
+
+/* marker */
+#define PM_FM_C
+
+/* dependencies */
+#include "pm_fm.h"
+
+//#define FM_VERBOSE_DBG	0
+#undef FM_VERBOSE_DBG
+#undef FM_DBG
+
+typedef struct index_LUT_s
+{
+	short	Vert;
+	short	ST;
+	struct	index_LUT_s	*next;
+
+} index_LUT_t;
+
+typedef struct index_DUP_LUT_s
+{
+	short			ST;
+	short			OldVert;
+
+} index_DUP_LUT_t;
+
+
+// _fm_canload()
+static int _fm_canload( PM_PARAMS_CANLOAD )
+{
+	fm_t		fm;
+	unsigned char	*bb;
+	int		fm_file_pos;
+
+	bb = (unsigned char *) buffer;
+
+	// Header
+	fm.fm_header_hdr = (fm_chunk_header_t *) bb;
+	fm_file_pos = sizeof(fm_chunk_header_t) + fm.fm_header_hdr->size;
+#ifdef FM_VERBOSE_DBG
+	_pico_printf( PICO_VERBOSE, "IDENT: %s\n", (unsigned char *) fm.fm_header_hdr->ident );
+#endif
+	if( (strcmp(fm.fm_header_hdr->ident, FM_HEADERCHUNKNAME))  )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Header Ident incorrect\n");
+#endif
+		return PICO_PMV_ERROR_IDENT;
+	}
+
+	// check fm
+	if( _pico_little_long( fm.fm_header_hdr->version ) != FM_HEADERCHUNKVER )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Header Version incorrect\n");
+#endif
+		return PICO_PMV_ERROR_VERSION;
+	}
+
+	// Skin
+	fm.fm_skin_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_skin_hdr->size;
+#ifdef FM_VERBOSE_DBG
+	_pico_printf( PICO_VERBOSE, "SKIN: %s\n", (unsigned char *) fm.fm_skin_hdr->ident );
+#endif
+	if( (strcmp(fm.fm_skin_hdr->ident, FM_SKINCHUNKNAME)) )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Skin Ident incorrect\n");
+#endif
+		return PICO_PMV_ERROR_IDENT;
+	}
+
+	// check fm
+	if( _pico_little_long( fm.fm_skin_hdr->version ) != FM_SKINCHUNKVER )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Skin Version incorrect\n");
+#endif
+		return PICO_PMV_ERROR_VERSION;
+	}
+
+	// st
+	fm.fm_st_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_st_hdr->size;
+#ifdef FM_VERBOSE_DBG
+	_pico_printf( PICO_VERBOSE, "ST: %s\n", (unsigned char *) fm.fm_st_hdr->ident );
+#endif
+	if( (strcmp(fm.fm_st_hdr->ident, FM_STCOORDCHUNKNAME)) )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM ST Ident incorrect\n");
+#endif
+		return PICO_PMV_ERROR_IDENT;
+	}
+
+	// check fm
+	if( _pico_little_long( fm.fm_st_hdr->version ) != FM_STCOORDCHUNKVER )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM ST Version incorrect\n");
+#endif
+		return PICO_PMV_ERROR_VERSION;
+	}
+
+	// tri
+	fm.fm_tri_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_tri_hdr->size;
+#ifdef FM_VERBOSE_DBG
+	_pico_printf( PICO_VERBOSE, "TRI: %s\n", (unsigned char *) fm.fm_tri_hdr->ident );
+#endif
+	if( (strcmp(fm.fm_tri_hdr->ident, FM_TRISCHUNKNAME)) )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Tri Ident incorrect\n");
+#endif
+		return PICO_PMV_ERROR_IDENT;
+	}
+
+	// check fm
+	if( _pico_little_long( fm.fm_tri_hdr->version ) != FM_TRISCHUNKVER )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Tri Version incorrect\n");
+#endif
+		return PICO_PMV_ERROR_VERSION;
+	}
+
+	// frame
+	fm.fm_frame_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t);
+#ifdef FM_VERBOSE_DBG
+	_pico_printf( PICO_VERBOSE, "FRAME: %s\n", (unsigned char *) fm.fm_frame_hdr->ident );
+#endif
+	if( (strcmp(fm.fm_frame_hdr->ident, FM_FRAMESCHUNKNAME)) )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Frame Ident incorrect\n");
+#endif
+		return PICO_PMV_ERROR_IDENT;
+	}
+
+	// check fm
+	if( _pico_little_long( fm.fm_frame_hdr->version ) != FM_FRAMESCHUNKVER )
+	{
+#ifdef FM_DBG
+		_pico_printf( PICO_WARNING, "FM Frame Version incorrect\n");
+#endif
+		return PICO_PMV_ERROR_VERSION;
+	}
+
+	// file seems to be a valid fm
+	return PICO_PMV_OK;
+}
+
+
+
+// _fm_load() loads a Heretic 2 model file.
+static picoModel_t *_fm_load( PM_PARAMS_LOAD )
+{
+	int				i, j, dups, dup_index;
+	int				fm_file_pos;
+	short			tot_numVerts;
+	index_LUT_t		*p_index_LUT, *p_index_LUT2, *p_index_LUT3;
+	index_DUP_LUT_t	*p_index_LUT_DUPS;
+
+	fm_vert_normal_t	*vert;
+
+	char			skinname[FM_SKINPATHSIZE];
+ 	fm_t			fm;
+	fm_header_t		*fm_head;
+	fm_st_t			*texCoord;
+	fm_xyz_st_t		*tri_verts;
+	fm_xyz_st_t		*triangle;
+	fm_frame_t		*frame;
+
+	picoByte_t      *bb;
+	picoModel_t	*picoModel;
+	picoSurface_t	*picoSurface;
+	picoShader_t	*picoShader;
+	picoVec3_t	xyz, normal;
+	picoVec2_t	st;
+	picoColor_t	color;
+	
+
+	// fm loading
+ 	_pico_printf( PICO_NORMAL, "Loading \"%s\"", fileName );
+
+	bb = (picoByte_t*) buffer;
+
+	// Header Header
+	fm.fm_header_hdr = (fm_chunk_header_t *) bb;
+	fm_file_pos = sizeof(fm_chunk_header_t) + fm.fm_header_hdr->size;
+	if( (strcmp(fm.fm_header_hdr->ident, FM_HEADERCHUNKNAME))  )
+	{
+		_pico_printf( PICO_WARNING, "FM Header Ident incorrect\n");
+		return NULL;
+	}
+
+	if( _pico_little_long( fm.fm_header_hdr->version ) != FM_HEADERCHUNKVER )
+	{
+		_pico_printf( PICO_WARNING, "FM Header Version incorrect\n");
+		return NULL;
+	}
+
+	// Skin Header
+	fm.fm_skin_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_skin_hdr->size;
+	if( (strcmp(fm.fm_skin_hdr->ident, FM_SKINCHUNKNAME)) )
+	{
+		_pico_printf( PICO_WARNING, "FM Skin Ident incorrect\n");
+		return NULL;
+	}
+
+	if( _pico_little_long( fm.fm_skin_hdr->version ) != FM_SKINCHUNKVER )
+	{
+		_pico_printf( PICO_WARNING, "FM Skin Version incorrect\n");
+		return NULL;
+	}
+
+	// ST Header
+	fm.fm_st_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_st_hdr->size;
+	if( (strcmp(fm.fm_st_hdr->ident, FM_STCOORDCHUNKNAME)) )
+	{
+		_pico_printf( PICO_WARNING, "FM ST Ident incorrect\n");
+		return NULL;
+	}
+
+	if( _pico_little_long( fm.fm_st_hdr->version ) != FM_STCOORDCHUNKVER )
+	{
+		_pico_printf( PICO_WARNING, "FM ST Version incorrect\n");
+		return NULL;
+	}
+
+	// Tris Header
+	fm.fm_tri_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t) + fm.fm_tri_hdr->size;
+	if( (strcmp(fm.fm_tri_hdr->ident, FM_TRISCHUNKNAME)) )
+	{
+		_pico_printf( PICO_WARNING, "FM Tri Ident incorrect\n");
+		return NULL;
+	}
+
+	if( _pico_little_long( fm.fm_tri_hdr->version ) != FM_TRISCHUNKVER )
+	{
+		_pico_printf( PICO_WARNING, "FM Tri Version incorrect\n");
+		return NULL;
+	}
+
+	// Frame Header
+	fm.fm_frame_hdr = (fm_chunk_header_t *) (bb + fm_file_pos);
+	fm_file_pos += sizeof(fm_chunk_header_t);
+	if( (strcmp(fm.fm_frame_hdr->ident, FM_FRAMESCHUNKNAME)) )
+	{
+		_pico_printf( PICO_WARNING, "FM Frame Ident incorrect\n");
+		return NULL;
+	}
+
+	if( _pico_little_long( fm.fm_frame_hdr->version ) != FM_FRAMESCHUNKVER )
+	{
+		_pico_printf( PICO_WARNING, "FM Frame Version incorrect\n");
+		return NULL;
+	}
+
+	// Header
+	fm_file_pos = sizeof(fm_chunk_header_t);
+	fm_head = fm.fm_header = (fm_header_t *) (bb + fm_file_pos);
+	fm_file_pos += fm.fm_header_hdr->size;
+
+	// Skin
+	fm_file_pos += sizeof(fm_chunk_header_t);
+	fm.fm_skin = (fm_skinpath_t *) (bb + fm_file_pos);
+	fm_file_pos += fm.fm_skin_hdr->size;
+
+	// ST
+	fm_file_pos += sizeof(fm_chunk_header_t);
+	texCoord = fm.fm_st = (fm_st_t *) (bb + fm_file_pos);
+	fm_file_pos += fm.fm_st_hdr->size;
+
+	// Tri
+	fm_file_pos += sizeof(fm_chunk_header_t);
+	tri_verts = fm.fm_tri = (fm_xyz_st_t *) (bb + fm_file_pos);
+	fm_file_pos += fm.fm_tri_hdr->size;
+
+	// Frame
+	fm_file_pos += sizeof(fm_chunk_header_t);
+	frame = fm.fm_frame = (fm_frame_t *) (bb + fm_file_pos);
+
+	// do frame check
+	if( fm_head->numFrames < 1 )
+	{
+		_pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
+		return NULL;
+	}
+	
+	if( frameNum < 0 || frameNum >= fm_head->numFrames )
+	{
+		_pico_printf( PICO_ERROR, "Invalid or out-of-range FM frame specified" );
+		return NULL;
+	}
+
+	// swap fm
+	fm_head->skinWidth = _pico_little_long( fm_head->skinWidth );
+	fm_head->skinHeight = _pico_little_long( fm_head->skinHeight );
+	fm_head->frameSize = _pico_little_long( fm_head->frameSize );
+
+	fm_head->numSkins = _pico_little_long( fm_head->numSkins );
+	fm_head->numXYZ = _pico_little_long( fm_head->numXYZ );
+	fm_head->numST = _pico_little_long( fm_head->numST );
+	fm_head->numTris = _pico_little_long( fm_head->numTris );
+	fm_head->numGLCmds = _pico_little_long( fm_head->numGLCmds );
+	fm_head->numFrames = _pico_little_long( fm_head->numFrames );
+
+	// swap frame scale and translation
+	for( i = 0; i < 3; i++ )
+	{
+		frame->header.scale[ i ] = _pico_little_float( frame->header.scale[ i ] );
+		frame->header.translate[ i ] = _pico_little_float( frame->header.translate[ i ] );
+	}
+
+	// swap triangles
+	triangle = tri_verts;
+	for( i = 0; i < fm_head->numTris; i++, triangle++ )
+	{
+		for( j = 0; j < 3; j++ )
+		{
+			triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
+			triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
+		}
+	}
+
+	// swap st coords
+	for( i = 0; i < fm_head->numST; i++ )
+	{
+		texCoord->s = _pico_little_short( texCoord[i].s );
+		texCoord->t = _pico_little_short( texCoord[i].t );
+	}
+	// set Skin Name
+	strncpy(skinname, (unsigned char *) fm.fm_skin, FM_SKINPATHSIZE );
+
+#ifdef FM_VERBOSE_DBG
+	// Print out md2 values
+	_pico_printf(PICO_VERBOSE,"numSkins->%d  numXYZ->%d  numST->%d  numTris->%d  numFrames->%d\nSkin Name \"%s\"\n", fm_head->numSkins, fm_head->numXYZ, fm_head->numST, fm_head->numTris, fm_head->numFrames, &skinname );
+#endif
+
+	// detox Skin name
+	_pico_setfext( skinname, "" );
+	_pico_unixify( skinname );
+
+	/* create new pico model */
+	picoModel = PicoNewModel();
+	if( picoModel == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+		return NULL;
+	}
+
+	/* do model setup */
+	PicoSetModelFrameNum( picoModel, frameNum );
+	PicoSetModelNumFrames( picoModel, fm_head->numFrames ); /* sea */
+	PicoSetModelName( picoModel, fileName );
+	PicoSetModelFileName( picoModel, fileName );
+
+	// allocate new pico surface
+	picoSurface = PicoNewSurface( picoModel );
+	if( picoSurface == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+		PicoFreeModel( picoModel );
+		return NULL;
+	}
+
+
+	PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+	PicoSetSurfaceName( picoSurface, frame->header.name );
+	picoShader = PicoNewShader( picoModel );
+	if( picoShader == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+		PicoFreeModel( picoModel );
+		return NULL;
+	}
+
+	PicoSetShaderName( picoShader, skinname );
+
+	// associate current surface with newly created shader
+	PicoSetSurfaceShader( picoSurface, picoShader );
+
+	// Init LUT for Verts
+	p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * fm_head->numXYZ);
+	for(i=0; i<fm_head->numXYZ; i++)
+	{
+		p_index_LUT[i].Vert = -1;
+		p_index_LUT[i].ST = -1;
+		p_index_LUT[i].next = NULL;
+	}
+
+	// Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
+	tot_numVerts = fm_head->numXYZ;
+	dups = 0;
+	triangle = tri_verts;
+
+	for(i=0; i<fm_head->numTris; i++)
+	{
+		for(j=0; j<3; j++)
+		{
+			if (p_index_LUT[triangle->index_xyz[j]].ST == -1) // No Main Entry
+				p_index_LUT[triangle->index_xyz[j]].ST = triangle->index_st[j];
+
+			else if (triangle->index_st[j] == p_index_LUT[triangle->index_xyz[j]].ST ) // Equal to Main Entry
+			{
+#ifdef FM_VERBOSE_DBG
+				_pico_printf( PICO_NORMAL, "-> Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
+#endif
+				continue;
+			}
+			else if ( (p_index_LUT[triangle->index_xyz[j]].next == NULL) )  // Not equal to Main entry, and no LL entry
+			{	// Add first entry of LL from Main
+				p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
+				if (p_index_LUT2 == NULL)
+					_pico_printf( PICO_NORMAL, " Couldn't allocate memory!\n");
+				p_index_LUT[triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
+				p_index_LUT2->Vert = dups;
+				p_index_LUT2->ST = triangle->index_st[j];
+				p_index_LUT2->next = NULL;
+#ifdef FM_VERBOSE_DBG
+				_pico_printf( PICO_NORMAL, " ADDING first LL XYZ:%d DUP:%d ST:%d\n", triangle->index_xyz[j], dups, triangle->index_st[j]);
+#endif
+				triangle->index_xyz[j] = dups + fm_head->numXYZ; // Make change in Tri hunk
+				dups++;
+			}
+			else // Try to find in LL from Main Entry
+			{
+				p_index_LUT3 = p_index_LUT2 = p_index_LUT[triangle->index_xyz[j]].next;
+				while ( (p_index_LUT2 != NULL) && (triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
+				{
+					p_index_LUT3 = p_index_LUT2;
+					p_index_LUT2 = p_index_LUT2->next;
+				}
+				p_index_LUT2 = p_index_LUT3;
+
+				if ( triangle->index_st[j] == p_index_LUT2->ST ) // Found it
+				{
+					triangle->index_xyz[j] = p_index_LUT2->Vert + fm_head->numXYZ; // Make change in Tri hunk
+#ifdef FM_VERBOSE_DBG
+					_pico_printf( PICO_NORMAL, "--> Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
+#endif
+					continue;
+				}
+
+				if ( p_index_LUT2->next == NULL)  // Didn't find it. Add entry to LL.
+				{
+					// Add the Entry
+					p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
+					if (p_index_LUT3 == NULL)
+						_pico_printf( PICO_NORMAL, " Couldn't allocate memory!\n");
+					p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
+					p_index_LUT3->Vert = dups;
+					p_index_LUT3->ST = triangle->index_st[j];
+					p_index_LUT3->next = NULL;
+#ifdef FM_VERBOSE_DBG
+					_pico_printf( PICO_NORMAL, " ADDING additional LL XYZ:%d DUP:%d NewXYZ:%d ST:%d\n", triangle->index_xyz[j], dups, dups + (fm_head->numXYZ), triangle->index_st[j]);
+#endif
+					triangle->index_xyz[j] = dups + fm_head->numXYZ; // Make change in Tri hunk
+					dups++;
+				}
+			}
+#ifdef FM_VERBOSE_DBG
+			_pico_printf( PICO_NORMAL, "---> Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
+#endif
+		}
+		triangle++;
+	}
+
+	// malloc and build array for Dup STs
+	p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
+	if (p_index_LUT_DUPS == NULL)
+		_pico_printf( PICO_NORMAL, " Couldn't allocate memory!\n");
+
+	dup_index = 0;
+	for(i=0; i<fm_head->numXYZ; i++)
+	{
+		p_index_LUT2 = p_index_LUT[i].next;
+		while (p_index_LUT2 != NULL)
+		{
+			p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
+			p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
+			dup_index++;
+			p_index_LUT2 = p_index_LUT2->next;
+		}
+	}
+#ifdef FM_VERBOSE_DBG
+	_pico_printf( PICO_NORMAL, " Dups = %d\n", dups);
+	_pico_printf( PICO_NORMAL, " Dup Index = %d\n", dup_index);
+#endif
+	for(i=0; i<fm_head->numXYZ; i++)
+	{
+#ifdef FM_VERBOSE_DBG
+		_pico_printf( PICO_NORMAL, "Vert: %4d\t%4d",i, p_index_LUT[i].ST);
+#endif
+		if (p_index_LUT[i].next != NULL)
+		{
+
+			p_index_LUT2 = p_index_LUT[i].next;
+			do {
+#ifdef FM_VERBOSE_DBG
+				_pico_printf( PICO_NORMAL, " %4d %4d", p_index_LUT2->Vert, p_index_LUT2->ST);
+#endif
+				p_index_LUT2 = p_index_LUT2->next;
+			} while ( p_index_LUT2 != NULL);
+
+		}
+#ifdef FM_VERBOSE_DBG
+		_pico_printf( PICO_NORMAL, "\n");
+#endif
+	}
+
+
+#ifdef FM_VERBOSE_DBG
+	for(i=0; i<dup_index; i++)
+		_pico_printf( PICO_NORMAL, " Dup Index #%d  OldVert: %d  ST: %d\n", i, p_index_LUT_DUPS[i].OldVert, p_index_LUT_DUPS[i].ST);
+
+	triangle = tri_verts;
+	for(i=0; i<fm_head->numTris; i++)
+	{
+		for(j=0; j<3; j++)
+			_pico_printf( PICO_NORMAL, "Tri #%d, Vert %d:\t XYZ:%d   ST:%d\n", i, j, triangle->index_xyz[j], triangle->index_st[j]);
+		_pico_printf( PICO_NORMAL, "\n");
+		triangle++;
+	}
+#endif
+	// Build Picomodel
+	triangle = tri_verts;
+	for( j = 0; j < fm_head->numTris; j++, triangle++ )
+	{
+		PicoSetSurfaceIndex( picoSurface, j*3   , triangle->index_xyz[0] );
+		PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
+		PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
+	}
+
+	vert = (fm_vert_normal_t*) ((picoByte_t*) (frame->verts) );
+	for(i=0; i< fm_head->numXYZ; i++, vert++)
+	{
+		/* set vertex origin */
+		xyz[ 0 ] = vert->v[0] * frame->header.scale[0] + frame->header.translate[0];
+		xyz[ 1 ] = vert->v[1] * frame->header.scale[1] + frame->header.translate[1];
+		xyz[ 2 ] = vert->v[2] * frame->header.scale[2] + frame->header.translate[2];
+		PicoSetSurfaceXYZ( picoSurface, i , xyz );
+
+		/* set normal */
+		normal[ 0 ] = fm_normals[vert->lightnormalindex][0];
+		normal[ 1 ] = fm_normals[vert->lightnormalindex][1];
+		normal[ 2 ] = fm_normals[vert->lightnormalindex][2];
+		PicoSetSurfaceNormal( picoSurface, i , normal );
+
+		/* set st coords */
+		st[ 0 ] =  ((texCoord[p_index_LUT[i].ST].s) / ((float)fm_head->skinWidth));
+		st[ 1 ] =  (texCoord[p_index_LUT[i].ST].t / ((float)fm_head->skinHeight));
+		PicoSetSurfaceST( picoSurface, 0, i , st );
+	}
+
+	if (dups)
+	{
+		for(i=0; i<dups; i++)
+		{
+			j = p_index_LUT_DUPS[i].OldVert;
+			/* set vertex origin */
+			xyz[ 0 ] = frame->verts[j].v[0] * frame->header.scale[0] + frame->header.translate[0];
+			xyz[ 1 ] = frame->verts[j].v[1] * frame->header.scale[1] + frame->header.translate[1];
+			xyz[ 2 ] = frame->verts[j].v[2] * frame->header.scale[2] + frame->header.translate[2];
+			PicoSetSurfaceXYZ( picoSurface, i + fm_head->numXYZ , xyz );
+
+			/* set normal */
+			normal[ 0 ] = fm_normals[frame->verts[j].lightnormalindex][0];
+			normal[ 1 ] = fm_normals[frame->verts[j].lightnormalindex][1];
+			normal[ 2 ] = fm_normals[frame->verts[j].lightnormalindex][2];
+			PicoSetSurfaceNormal( picoSurface, i + fm_head->numXYZ , normal );
+
+			/* set st coords */
+			st[ 0 ] =  ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)fm_head->skinWidth));
+			st[ 1 ] =  (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)fm_head->skinHeight));
+			PicoSetSurfaceST( picoSurface, 0, i + fm_head->numXYZ , st );
+		}
+	}
+
+	/* set color */
+	PicoSetSurfaceColor( picoSurface, 0, 0, color );
+
+	// Free up malloc'ed LL entries
+	for(i=0; i<fm_head->numXYZ; i++)
+	{
+		if(p_index_LUT[i].next != NULL)
+		{
+			p_index_LUT2 = p_index_LUT[i].next;
+			do {
+				p_index_LUT3 = p_index_LUT2->next;
+				_pico_free(p_index_LUT2);
+				p_index_LUT2 = p_index_LUT3;
+				dups--;
+			} while (p_index_LUT2 != NULL);
+		}
+	}
+
+	if (dups)
+		_pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
+
+	// Free malloc'ed LUTs
+ 	_pico_free(p_index_LUT);
+	_pico_free(p_index_LUT_DUPS);
+
+	/* return the new pico model */
+	return picoModel;
+
+}
+
+
+
+/* pico file format module definition */
+const picoModule_t picoModuleFM =
+{
+	"0.85",						/* module version string */
+	"Heretic 2 FM",				/* module display name */
+	"Nurail",					/* author's name */
+	"2003 Nurail",				/* module copyright */
+	{
+		"fm", NULL, NULL, NULL	/* default extensions to use */
+	},
+	_fm_canload,				/* validation routine */
+	_fm_load,					/* load routine */
+	 NULL,						/* save validation routine */
+	 NULL						/* save routine */
+};
diff --git a/libs/picomodel/pm_fm.h b/libs/picomodel/pm_fm.h
index ce43d334..3fd5148e 100644
--- a/libs/picomodel/pm_fm.h
+++ b/libs/picomodel/pm_fm.h
@@ -1,367 +1,367 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-// This header file is based from the following:
-
-/*
-	FlexModel.H - Header file for FlexModel file structure
-
-	By Chris Burke
-	serotonin@earthlink.net
-*/
-
-#ifndef	__PM_FM_H__
-#define	__PM_FM_H__
-
-#include "picointernal.h"
-
-
-//
-//	Absolute limits (from QData / QMView source)
-//
-#define	MAX_FM_TRIANGLES	2048
-#define MAX_FM_VERTS		2048
-#define MAX_FM_FRAMES		2048
-#define MAX_FM_SKINS		64
-#define	MAX_FM_SKINNAME		64
-#define MAX_FM_MESH_NODES	16
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-#define SKINPAGE_WIDTH 640
-#define SKINPAGE_HEIGHT 480
-
-#define ENCODED_WIDTH_X 92
-#define ENCODED_WIDTH_Y 475
-#define ENCODED_HEIGHT_X 128
-#define ENCODED_HEIGHT_Y 475
-
-#define SCALE_ADJUST_FACTOR 0.96
-
-#define INFO_HEIGHT 5
-#define INFO_Y (SKINPAGE_HEIGHT-INFO_HEIGHT)
-
-#ifndef byte
-	#define byte unsigned char
-#endif
-
-
-//
-//	Generic header on every chunk
-//
-#define	FM_MAXCHUNKIDENT	32L
-typedef struct
-{
-	char			ident[FM_MAXCHUNKIDENT];
-	unsigned int		version;
-	unsigned int		size;
-} fm_chunk_header_t;
-
-//
-//	The format of the "header" chunk
-//
-#define	FM_HEADERCHUNKNAME	"header"
-#define	FM_HEADERCHUNKVER	2
-#define	FM_HEADERCHUNKSIZE	40
-typedef struct
-{
-	int			skinWidth;		// in pixels
-	int			skinHeight;		// in pixels
-	int			frameSize;		// size of each frame (in bytes)
-	int			numSkins;		// number of skins
-	int			numXYZ;			// number of unique vertices in 3D space
-	int			numST;			// number of unique vertices in texture space
-	int			numTris;		// number of unique triangles
-	int			numGLCmds;		// # 32-bit elements in strip/fan command list
-	int			numFrames;		// number of animation frames
-	int			numMeshNodes;		// number of mesh nodes
-} fm_header_t;
-
-//
-//	The format of an entry in the "skin" chunk.
-//	The number of entries is given in the fmheader chunk
-//
-#define	FM_SKINCHUNKNAME	"skin"
-#define	FM_SKINCHUNKVER		1
-#define	FM_MAXPATHLENGTH	64L
-#define	FM_SKINPATHSIZE	(FM_MAXPATHLENGTH)
-typedef struct
-{
-	char				path[FM_SKINPATHSIZE];	//	path, relative to 'base'
-} fm_skinpath_t;
-
-//
-//	The format of the "st coord" chunk. This is a list
-//	of unique skin texture (u, v) coordinates to be mapped
-//	to verteces of the model
-//
-#define FM_STCOORDCHUNKNAME	"st coord"
-#define FM_STCOORDCHUNKVER	1
-#define	FM_STCOORDUVSIZE	(2L + 2L)
-
-typedef struct
-{
-	short	s;
-	short	t;
-} fm_st_t;
-
-//
-//	The format of the "tris" chunk. This is a list of vertex indeces
-//	in 3D space, and the corresponding vertex indeces in texture space.
-//
-#define FM_TRISCHUNKNAME	"tris"
-#define FM_TRISCHUNKVER		1
-#define	FM_TRISINFOSIZE		(2L*3 + 2L*3)
-
-typedef struct
-{
-	short	index_xyz[3];
-	short	index_st[3];
-} fm_xyz_st_t;
-
-
-//
-//	The format of the "frames" chunk. This is a list of animation
-//	frames, each specifying the coordinates and "light normal" index
-//	of every vertex of the model in 3D space.
-//
-#define FM_FRAMESCHUNKNAME	"frames"
-#define FM_FRAMESCHUNKVER	1
-
-#define FM_NUMVERTEXNORMALS	162
-
-// Frame info
-typedef struct
-{
-	byte			v[3];				//	scaled by header info
-	byte			lightnormalindex;	//	index in canned table of closest vertex normal
-} fm_vert_normal_t;
-
-typedef struct
-{
-	float			scale[3];			//	multiply byte verts by this
-	float			translate[3];		//	then add this
-	char			name[16];			//	frame name
-} fm_framehdr_t;
-
-typedef struct
-{
-	fm_framehdr_t		header;				//	One header per frame
-	fm_vert_normal_t	verts[1];			//	variable number of these
-} fm_frame_t;
-
-typedef struct
-{
-	fm_chunk_header_t	*fm_header_hdr;
-	fm_header_t		*fm_header;
-	fm_chunk_header_t	*fm_skin_hdr;
-	fm_skinpath_t		*fm_skin;
-	fm_chunk_header_t	*fm_st_hdr;
-	fm_st_t			*fm_st;
-	fm_chunk_header_t	*fm_tri_hdr;
-	fm_xyz_st_t		*fm_tri;
-	fm_chunk_header_t	*fm_frame_hdr;
-	fm_frame_t		*fm_frame;
-} fm_t;
-
-float	fm_normals[FM_NUMVERTEXNORMALS][3] = {
-  {-0.525731f, 0.000000f, 0.850651f},
-  {-0.442863f, 0.238856f, 0.864188f},
-  {-0.295242f, 0.000000f, 0.955423f},
-  {-0.309017f, 0.500000f, 0.809017f},
-  {-0.162460f, 0.262866f, 0.951056f},
-  {0.000000f, 0.000000f, 1.000000f},
-  {0.000000f, 0.850651f, 0.525731f},
-  {-0.147621f, 0.716567f, 0.681718f},
-  {0.147621f, 0.716567f, 0.681718f},
-  {0.000000f, 0.525731f, 0.850651f},
-  {0.309017f, 0.500000f, 0.809017f},
-  {0.525731f, 0.000000f, 0.850651f},
-  {0.295242f, 0.000000f, 0.955423f},
-  {0.442863f, 0.238856f, 0.864188f},
-  {0.162460f, 0.262866f, 0.951056f},
-  {-0.681718f, 0.147621f, 0.716567f},
-  {-0.809017f, 0.309017f, 0.500000f},
-  {-0.587785f, 0.425325f, 0.688191f},
-  {-0.850651f, 0.525731f, 0.000000f},
-  {-0.864188f, 0.442863f, 0.238856f},
-  {-0.716567f, 0.681718f, 0.147621f},
-  {-0.688191f, 0.587785f, 0.425325f},
-  {-0.500000f, 0.809017f, 0.309017f},
-  {-0.238856f, 0.864188f, 0.442863f},
-  {-0.425325f, 0.688191f, 0.587785f},
-  {-0.716567f, 0.681718f, -0.147621f},
-  {-0.500000f, 0.809017f, -0.309017f},
-  {-0.525731f, 0.850651f, 0.000000f},
-  {0.000000f, 0.850651f, -0.525731f},
-  {-0.238856f, 0.864188f, -0.442863f},
-  {0.000000f, 0.955423f, -0.295242f},
-  {-0.262866f, 0.951056f, -0.162460f},
-  {0.000000f, 1.000000f, 0.000000f}, 
-  {0.000000f, 0.955423f, 0.295242f},
-  {-0.262866f, 0.951056f, 0.162460f},
-  {0.238856f, 0.864188f, 0.442863f},
-  {0.262866f, 0.951056f, 0.162460f}, 
-  {0.500000f, 0.809017f, 0.309017f},
-  {0.238856f, 0.864188f, -0.442863f},
-  {0.262866f, 0.951056f, -0.162460f},
-  {0.500000f, 0.809017f, -0.309017f},
-  {0.850651f, 0.525731f, 0.000000f},
-  {0.716567f, 0.681718f, 0.147621f},
-  {0.716567f, 0.681718f, -0.147621f},
-  {0.525731f, 0.850651f, 0.000000f}, 
-  {0.425325f, 0.688191f, 0.587785f},
-  {0.864188f, 0.442863f, 0.238856f}, 
-  {0.688191f, 0.587785f, 0.425325f},
-  {0.809017f, 0.309017f, 0.500000f}, 
-  {0.681718f, 0.147621f, 0.716567f},
-  {0.587785f, 0.425325f, 0.688191f}, 
-  {0.955423f, 0.295242f, 0.000000f},
-  {1.000000f, 0.000000f, 0.000000f}, 
-  {0.951056f, 0.162460f, 0.262866f},
-  {0.850651f, -0.525731f, 0.000000f}, 
-  {0.955423f, -0.295242f, 0.000000f},
-  {0.864188f, -0.442863f, 0.238856f}, 
-  {0.951056f, -0.162460f, 0.262866f},
-  {0.809017f, -0.309017f, 0.500000f}, 
-  {0.681718f, -0.147621f, 0.716567f},
-  {0.850651f, 0.000000f, 0.525731f},
-  {0.864188f, 0.442863f, -0.238856f}, 
-  {0.809017f, 0.309017f, -0.500000f},
-  {0.951056f, 0.162460f, -0.262866f}, 
-  {0.525731f, 0.000000f, -0.850651f},
-  {0.681718f, 0.147621f, -0.716567f},
-  {0.681718f, -0.147621f, -0.716567f}, 
-  {0.850651f, 0.000000f, -0.525731f},
-  {0.809017f, -0.309017f, -0.500000f}, 
-  {0.864188f, -0.442863f, -0.238856f},
-  {0.951056f, -0.162460f, -0.262866f}, 
-  {0.147621f, 0.716567f, -0.681718f},
-  {0.309017f, 0.500000f, -0.809017f}, 
-  {0.425325f, 0.688191f, -0.587785f},
-  {0.442863f, 0.238856f, -0.864188f}, 
-  {0.587785f, 0.425325f, -0.688191f},
-  {0.688191f, 0.587785f, -0.425325f}, 
-  {-0.147621f, 0.716567f, -0.681718f},
-  {-0.309017f, 0.500000f, -0.809017f}, 
-  {0.000000f, 0.525731f, -0.850651f},
-  {-0.525731f, 0.000000f, -0.850651f}, 
-  {-0.442863f, 0.238856f, -0.864188f},
-  {-0.295242f, 0.000000f, -0.955423f}, 
-  {-0.162460f, 0.262866f, -0.951056f},
-  {0.000000f, 0.000000f, -1.000000f}, 
-  {0.295242f, 0.000000f, -0.955423f},
-  {0.162460f, 0.262866f, -0.951056f}, 
-  {-0.442863f, -0.238856f, -0.864188f},
-  {-0.309017f, -0.500000f, -0.809017f}, 
-  {-0.162460f, -0.262866f, -0.951056f},
-  {0.000000f, -0.850651f, -0.525731f}, 
-  {-0.147621f, -0.716567f, -0.681718f},
-  {0.147621f, -0.716567f, -0.681718f}, 
-  {0.000000f, -0.525731f, -0.850651f},
-  {0.309017f, -0.500000f, -0.809017f}, 
-  {0.442863f, -0.238856f, -0.864188f},
-  {0.162460f, -0.262866f, -0.951056f}, 
-  {0.238856f, -0.864188f, -0.442863f},
-  {0.500000f, -0.809017f, -0.309017f}, 
-  {0.425325f, -0.688191f, -0.587785f},
-  {0.716567f, -0.681718f, -0.147621f}, 
-  {0.688191f, -0.587785f, -0.425325f},
-  {0.587785f, -0.425325f, -0.688191f}, 
-  {0.000000f, -0.955423f, -0.295242f},
-  {0.000000f, -1.000000f, 0.000000f}, 
-  {0.262866f, -0.951056f, -0.162460f},
-  {0.000000f, -0.850651f, 0.525731f}, 
-  {0.000000f, -0.955423f, 0.295242f},
-  {0.238856f, -0.864188f, 0.442863f}, 
-  {0.262866f, -0.951056f, 0.162460f},
-  {0.500000f, -0.809017f, 0.309017f}, 
-  {0.716567f, -0.681718f, 0.147621f},
-  {0.525731f, -0.850651f, 0.000000f}, 
-  {-0.238856f, -0.864188f, -0.442863f},
-  {-0.500000f, -0.809017f, -0.309017f}, 
-  {-0.262866f, -0.951056f, -0.162460f},
-  {-0.850651f, -0.525731f, 0.000000f}, 
-  {-0.716567f, -0.681718f, -0.147621f},
-  {-0.716567f, -0.681718f, 0.147621f}, 
-  {-0.525731f, -0.850651f, 0.000000f},
-  {-0.500000f, -0.809017f, 0.309017f}, 
-  {-0.238856f, -0.864188f, 0.442863f},
-  {-0.262866f, -0.951056f, 0.162460f}, 
-  {-0.864188f, -0.442863f, 0.238856f},
-  {-0.809017f, -0.309017f, 0.500000f}, 
-  {-0.688191f, -0.587785f, 0.425325f},
-  {-0.681718f, -0.147621f, 0.716567f}, 
-  {-0.442863f, -0.238856f, 0.864188f},
-  {-0.587785f, -0.425325f, 0.688191f}, 
-  {-0.309017f, -0.500000f, 0.809017f},
-  {-0.147621f, -0.716567f, 0.681718f}, 
-  {-0.425325f, -0.688191f, 0.587785f},
-  {-0.162460f, -0.262866f, 0.951056f}, 
-  {0.442863f, -0.238856f, 0.864188f},
-  {0.162460f, -0.262866f, 0.951056f}, 
-  {0.309017f, -0.500000f, 0.809017f},
-  {0.147621f, -0.716567f, 0.681718f}, 
-  {0.000000f, -0.525731f, 0.850651f},
-  {0.425325f, -0.688191f, 0.587785f}, 
-  {0.587785f, -0.425325f, 0.688191f},
-  {0.688191f, -0.587785f, 0.425325f}, 
-  {-0.955423f, 0.295242f, 0.000000f},
-  {-0.951056f, 0.162460f, 0.262866f}, 
-  {-1.000000f, 0.000000f, 0.000000f},
-  {-0.850651f, 0.000000f, 0.525731f}, 
-  {-0.955423f, -0.295242f, 0.000000f},
-  {-0.951056f, -0.162460f, 0.262866f}, 
-  {-0.864188f, 0.442863f, -0.238856f},
-  {-0.951056f, 0.162460f, -0.262866f}, 
-  {-0.809017f, 0.309017f, -0.500000f},
-  {-0.864188f, -0.442863f, -0.238856f},
-  {-0.951056f, -0.162460f, -0.262866f},
-  {-0.809017f, -0.309017f, -0.500000f}, 
-  {-0.681718f, 0.147621f, -0.716567f},
-  {-0.681718f, -0.147621f, -0.716567f}, 
-  {-0.850651f, 0.000000f, -0.525731f},
-  {-0.688191f, 0.587785f, -0.425325f}, 
-  {-0.587785f, 0.425325f, -0.688191f},
-  {-0.425325f, 0.688191f, -0.587785f}, 
-  {-0.425325f, -0.688191f, -0.587785f},
-  {-0.587785f, -0.425325f, -0.688191f}, 
-  {-0.688191f, -0.587785f, -0.425325f},
-};
-
-#endif
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+// This header file is based from the following:
+
+/*
+	FlexModel.H - Header file for FlexModel file structure
+
+	By Chris Burke
+	serotonin@earthlink.net
+*/
+
+#ifndef	__PM_FM_H__
+#define	__PM_FM_H__
+
+#include "picointernal.h"
+
+
+//
+//	Absolute limits (from QData / QMView source)
+//
+#define	MAX_FM_TRIANGLES	2048
+#define MAX_FM_VERTS		2048
+#define MAX_FM_FRAMES		2048
+#define MAX_FM_SKINS		64
+#define	MAX_FM_SKINNAME		64
+#define MAX_FM_MESH_NODES	16
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+#define SKINPAGE_WIDTH 640
+#define SKINPAGE_HEIGHT 480
+
+#define ENCODED_WIDTH_X 92
+#define ENCODED_WIDTH_Y 475
+#define ENCODED_HEIGHT_X 128
+#define ENCODED_HEIGHT_Y 475
+
+#define SCALE_ADJUST_FACTOR 0.96
+
+#define INFO_HEIGHT 5
+#define INFO_Y (SKINPAGE_HEIGHT-INFO_HEIGHT)
+
+#ifndef byte
+	#define byte unsigned char
+#endif
+
+
+//
+//	Generic header on every chunk
+//
+#define	FM_MAXCHUNKIDENT	32L
+typedef struct
+{
+	char			ident[FM_MAXCHUNKIDENT];
+	unsigned int		version;
+	unsigned int		size;
+} fm_chunk_header_t;
+
+//
+//	The format of the "header" chunk
+//
+#define	FM_HEADERCHUNKNAME	"header"
+#define	FM_HEADERCHUNKVER	2
+#define	FM_HEADERCHUNKSIZE	40
+typedef struct
+{
+	int			skinWidth;		// in pixels
+	int			skinHeight;		// in pixels
+	int			frameSize;		// size of each frame (in bytes)
+	int			numSkins;		// number of skins
+	int			numXYZ;			// number of unique vertices in 3D space
+	int			numST;			// number of unique vertices in texture space
+	int			numTris;		// number of unique triangles
+	int			numGLCmds;		// # 32-bit elements in strip/fan command list
+	int			numFrames;		// number of animation frames
+	int			numMeshNodes;		// number of mesh nodes
+} fm_header_t;
+
+//
+//	The format of an entry in the "skin" chunk.
+//	The number of entries is given in the fmheader chunk
+//
+#define	FM_SKINCHUNKNAME	"skin"
+#define	FM_SKINCHUNKVER		1
+#define	FM_MAXPATHLENGTH	64L
+#define	FM_SKINPATHSIZE	(FM_MAXPATHLENGTH)
+typedef struct
+{
+	char				path[FM_SKINPATHSIZE];	//	path, relative to 'base'
+} fm_skinpath_t;
+
+//
+//	The format of the "st coord" chunk. This is a list
+//	of unique skin texture (u, v) coordinates to be mapped
+//	to verteces of the model
+//
+#define FM_STCOORDCHUNKNAME	"st coord"
+#define FM_STCOORDCHUNKVER	1
+#define	FM_STCOORDUVSIZE	(2L + 2L)
+
+typedef struct
+{
+	short	s;
+	short	t;
+} fm_st_t;
+
+//
+//	The format of the "tris" chunk. This is a list of vertex indeces
+//	in 3D space, and the corresponding vertex indeces in texture space.
+//
+#define FM_TRISCHUNKNAME	"tris"
+#define FM_TRISCHUNKVER		1
+#define	FM_TRISINFOSIZE		(2L*3 + 2L*3)
+
+typedef struct
+{
+	short	index_xyz[3];
+	short	index_st[3];
+} fm_xyz_st_t;
+
+
+//
+//	The format of the "frames" chunk. This is a list of animation
+//	frames, each specifying the coordinates and "light normal" index
+//	of every vertex of the model in 3D space.
+//
+#define FM_FRAMESCHUNKNAME	"frames"
+#define FM_FRAMESCHUNKVER	1
+
+#define FM_NUMVERTEXNORMALS	162
+
+// Frame info
+typedef struct
+{
+	byte			v[3];				//	scaled by header info
+	byte			lightnormalindex;	//	index in canned table of closest vertex normal
+} fm_vert_normal_t;
+
+typedef struct
+{
+	float			scale[3];			//	multiply byte verts by this
+	float			translate[3];		//	then add this
+	char			name[16];			//	frame name
+} fm_framehdr_t;
+
+typedef struct
+{
+	fm_framehdr_t		header;				//	One header per frame
+	fm_vert_normal_t	verts[1];			//	variable number of these
+} fm_frame_t;
+
+typedef struct
+{
+	fm_chunk_header_t	*fm_header_hdr;
+	fm_header_t		*fm_header;
+	fm_chunk_header_t	*fm_skin_hdr;
+	fm_skinpath_t		*fm_skin;
+	fm_chunk_header_t	*fm_st_hdr;
+	fm_st_t			*fm_st;
+	fm_chunk_header_t	*fm_tri_hdr;
+	fm_xyz_st_t		*fm_tri;
+	fm_chunk_header_t	*fm_frame_hdr;
+	fm_frame_t		*fm_frame;
+} fm_t;
+
+float	fm_normals[FM_NUMVERTEXNORMALS][3] = {
+  {-0.525731f, 0.000000f, 0.850651f},
+  {-0.442863f, 0.238856f, 0.864188f},
+  {-0.295242f, 0.000000f, 0.955423f},
+  {-0.309017f, 0.500000f, 0.809017f},
+  {-0.162460f, 0.262866f, 0.951056f},
+  {0.000000f, 0.000000f, 1.000000f},
+  {0.000000f, 0.850651f, 0.525731f},
+  {-0.147621f, 0.716567f, 0.681718f},
+  {0.147621f, 0.716567f, 0.681718f},
+  {0.000000f, 0.525731f, 0.850651f},
+  {0.309017f, 0.500000f, 0.809017f},
+  {0.525731f, 0.000000f, 0.850651f},
+  {0.295242f, 0.000000f, 0.955423f},
+  {0.442863f, 0.238856f, 0.864188f},
+  {0.162460f, 0.262866f, 0.951056f},
+  {-0.681718f, 0.147621f, 0.716567f},
+  {-0.809017f, 0.309017f, 0.500000f},
+  {-0.587785f, 0.425325f, 0.688191f},
+  {-0.850651f, 0.525731f, 0.000000f},
+  {-0.864188f, 0.442863f, 0.238856f},
+  {-0.716567f, 0.681718f, 0.147621f},
+  {-0.688191f, 0.587785f, 0.425325f},
+  {-0.500000f, 0.809017f, 0.309017f},
+  {-0.238856f, 0.864188f, 0.442863f},
+  {-0.425325f, 0.688191f, 0.587785f},
+  {-0.716567f, 0.681718f, -0.147621f},
+  {-0.500000f, 0.809017f, -0.309017f},
+  {-0.525731f, 0.850651f, 0.000000f},
+  {0.000000f, 0.850651f, -0.525731f},
+  {-0.238856f, 0.864188f, -0.442863f},
+  {0.000000f, 0.955423f, -0.295242f},
+  {-0.262866f, 0.951056f, -0.162460f},
+  {0.000000f, 1.000000f, 0.000000f}, 
+  {0.000000f, 0.955423f, 0.295242f},
+  {-0.262866f, 0.951056f, 0.162460f},
+  {0.238856f, 0.864188f, 0.442863f},
+  {0.262866f, 0.951056f, 0.162460f}, 
+  {0.500000f, 0.809017f, 0.309017f},
+  {0.238856f, 0.864188f, -0.442863f},
+  {0.262866f, 0.951056f, -0.162460f},
+  {0.500000f, 0.809017f, -0.309017f},
+  {0.850651f, 0.525731f, 0.000000f},
+  {0.716567f, 0.681718f, 0.147621f},
+  {0.716567f, 0.681718f, -0.147621f},
+  {0.525731f, 0.850651f, 0.000000f}, 
+  {0.425325f, 0.688191f, 0.587785f},
+  {0.864188f, 0.442863f, 0.238856f}, 
+  {0.688191f, 0.587785f, 0.425325f},
+  {0.809017f, 0.309017f, 0.500000f}, 
+  {0.681718f, 0.147621f, 0.716567f},
+  {0.587785f, 0.425325f, 0.688191f}, 
+  {0.955423f, 0.295242f, 0.000000f},
+  {1.000000f, 0.000000f, 0.000000f}, 
+  {0.951056f, 0.162460f, 0.262866f},
+  {0.850651f, -0.525731f, 0.000000f}, 
+  {0.955423f, -0.295242f, 0.000000f},
+  {0.864188f, -0.442863f, 0.238856f}, 
+  {0.951056f, -0.162460f, 0.262866f},
+  {0.809017f, -0.309017f, 0.500000f}, 
+  {0.681718f, -0.147621f, 0.716567f},
+  {0.850651f, 0.000000f, 0.525731f},
+  {0.864188f, 0.442863f, -0.238856f}, 
+  {0.809017f, 0.309017f, -0.500000f},
+  {0.951056f, 0.162460f, -0.262866f}, 
+  {0.525731f, 0.000000f, -0.850651f},
+  {0.681718f, 0.147621f, -0.716567f},
+  {0.681718f, -0.147621f, -0.716567f}, 
+  {0.850651f, 0.000000f, -0.525731f},
+  {0.809017f, -0.309017f, -0.500000f}, 
+  {0.864188f, -0.442863f, -0.238856f},
+  {0.951056f, -0.162460f, -0.262866f}, 
+  {0.147621f, 0.716567f, -0.681718f},
+  {0.309017f, 0.500000f, -0.809017f}, 
+  {0.425325f, 0.688191f, -0.587785f},
+  {0.442863f, 0.238856f, -0.864188f}, 
+  {0.587785f, 0.425325f, -0.688191f},
+  {0.688191f, 0.587785f, -0.425325f}, 
+  {-0.147621f, 0.716567f, -0.681718f},
+  {-0.309017f, 0.500000f, -0.809017f}, 
+  {0.000000f, 0.525731f, -0.850651f},
+  {-0.525731f, 0.000000f, -0.850651f}, 
+  {-0.442863f, 0.238856f, -0.864188f},
+  {-0.295242f, 0.000000f, -0.955423f}, 
+  {-0.162460f, 0.262866f, -0.951056f},
+  {0.000000f, 0.000000f, -1.000000f}, 
+  {0.295242f, 0.000000f, -0.955423f},
+  {0.162460f, 0.262866f, -0.951056f}, 
+  {-0.442863f, -0.238856f, -0.864188f},
+  {-0.309017f, -0.500000f, -0.809017f}, 
+  {-0.162460f, -0.262866f, -0.951056f},
+  {0.000000f, -0.850651f, -0.525731f}, 
+  {-0.147621f, -0.716567f, -0.681718f},
+  {0.147621f, -0.716567f, -0.681718f}, 
+  {0.000000f, -0.525731f, -0.850651f},
+  {0.309017f, -0.500000f, -0.809017f}, 
+  {0.442863f, -0.238856f, -0.864188f},
+  {0.162460f, -0.262866f, -0.951056f}, 
+  {0.238856f, -0.864188f, -0.442863f},
+  {0.500000f, -0.809017f, -0.309017f}, 
+  {0.425325f, -0.688191f, -0.587785f},
+  {0.716567f, -0.681718f, -0.147621f}, 
+  {0.688191f, -0.587785f, -0.425325f},
+  {0.587785f, -0.425325f, -0.688191f}, 
+  {0.000000f, -0.955423f, -0.295242f},
+  {0.000000f, -1.000000f, 0.000000f}, 
+  {0.262866f, -0.951056f, -0.162460f},
+  {0.000000f, -0.850651f, 0.525731f}, 
+  {0.000000f, -0.955423f, 0.295242f},
+  {0.238856f, -0.864188f, 0.442863f}, 
+  {0.262866f, -0.951056f, 0.162460f},
+  {0.500000f, -0.809017f, 0.309017f}, 
+  {0.716567f, -0.681718f, 0.147621f},
+  {0.525731f, -0.850651f, 0.000000f}, 
+  {-0.238856f, -0.864188f, -0.442863f},
+  {-0.500000f, -0.809017f, -0.309017f}, 
+  {-0.262866f, -0.951056f, -0.162460f},
+  {-0.850651f, -0.525731f, 0.000000f}, 
+  {-0.716567f, -0.681718f, -0.147621f},
+  {-0.716567f, -0.681718f, 0.147621f}, 
+  {-0.525731f, -0.850651f, 0.000000f},
+  {-0.500000f, -0.809017f, 0.309017f}, 
+  {-0.238856f, -0.864188f, 0.442863f},
+  {-0.262866f, -0.951056f, 0.162460f}, 
+  {-0.864188f, -0.442863f, 0.238856f},
+  {-0.809017f, -0.309017f, 0.500000f}, 
+  {-0.688191f, -0.587785f, 0.425325f},
+  {-0.681718f, -0.147621f, 0.716567f}, 
+  {-0.442863f, -0.238856f, 0.864188f},
+  {-0.587785f, -0.425325f, 0.688191f}, 
+  {-0.309017f, -0.500000f, 0.809017f},
+  {-0.147621f, -0.716567f, 0.681718f}, 
+  {-0.425325f, -0.688191f, 0.587785f},
+  {-0.162460f, -0.262866f, 0.951056f}, 
+  {0.442863f, -0.238856f, 0.864188f},
+  {0.162460f, -0.262866f, 0.951056f}, 
+  {0.309017f, -0.500000f, 0.809017f},
+  {0.147621f, -0.716567f, 0.681718f}, 
+  {0.000000f, -0.525731f, 0.850651f},
+  {0.425325f, -0.688191f, 0.587785f}, 
+  {0.587785f, -0.425325f, 0.688191f},
+  {0.688191f, -0.587785f, 0.425325f}, 
+  {-0.955423f, 0.295242f, 0.000000f},
+  {-0.951056f, 0.162460f, 0.262866f}, 
+  {-1.000000f, 0.000000f, 0.000000f},
+  {-0.850651f, 0.000000f, 0.525731f}, 
+  {-0.955423f, -0.295242f, 0.000000f},
+  {-0.951056f, -0.162460f, 0.262866f}, 
+  {-0.864188f, 0.442863f, -0.238856f},
+  {-0.951056f, 0.162460f, -0.262866f}, 
+  {-0.809017f, 0.309017f, -0.500000f},
+  {-0.864188f, -0.442863f, -0.238856f},
+  {-0.951056f, -0.162460f, -0.262866f},
+  {-0.809017f, -0.309017f, -0.500000f}, 
+  {-0.681718f, 0.147621f, -0.716567f},
+  {-0.681718f, -0.147621f, -0.716567f}, 
+  {-0.850651f, 0.000000f, -0.525731f},
+  {-0.688191f, 0.587785f, -0.425325f}, 
+  {-0.587785f, 0.425325f, -0.688191f},
+  {-0.425325f, 0.688191f, -0.587785f}, 
+  {-0.425325f, -0.688191f, -0.587785f},
+  {-0.587785f, -0.425325f, -0.688191f}, 
+  {-0.688191f, -0.587785f, -0.425325f},
+};
+
+#endif
diff --git a/libs/picomodel/pm_lwo.c b/libs/picomodel/pm_lwo.c
index ba83ceb5..d7b3bc8a 100644
--- a/libs/picomodel/pm_lwo.c
+++ b/libs/picomodel/pm_lwo.c
@@ -1,430 +1,430 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library 
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-/* marker */
-#define PM_LWO_C
-
-/* dependencies */
-#include "picointernal.h"
-#include "lwo/lwo2.h"
-
-/* uncomment when debugging this module */
-/*#define DEBUG_PM_LWO*/
-
-#ifdef DEBUG_PM_LWO
-#include "time.h"
-#endif
-
-/* helper functions */
-static const char *lwo_lwIDToStr( unsigned int lwID )
-{
-	static char lwIDStr[5];
-
-	if (!lwID)
-	{
-		return "n/a";
-	}
-
-	lwIDStr[ 0 ] = (char)((lwID) >> 24);
-	lwIDStr[ 1 ] = (char)((lwID) >> 16);
-	lwIDStr[ 2 ] = (char)((lwID) >> 8);
-	lwIDStr[ 3 ] = (char)((lwID));
-	lwIDStr[ 4 ] = '\0';
-
-	return lwIDStr;
-}
-
-/*
-_lwo_canload()
-validates a LightWave Object model file. btw, i use the
-preceding underscore cause it's a static func referenced
-by one structure only.
-*/
-static int _lwo_canload( PM_PARAMS_CANLOAD )
-{
-	picoMemStream_t *s;
-	unsigned int failID = 0;
-	int failpos = -1;
-	int ret;
-
-	/* create a new pico memorystream */
-	s = _pico_new_memstream( (picoByte_t *)buffer, bufSize );
-	if (s == NULL)
-	{
-		return PICO_PMV_ERROR_MEMORY;
-	}
-
-	ret = lwValidateObject( fileName, s, &failID, &failpos );
-
-	_pico_free_memstream( s );
-
-	return ret;
-}
-
-/*
-_lwo_load()
-loads a LightWave Object model file.
-*/
-static picoModel_t *_lwo_load( PM_PARAMS_LOAD )
-{
-	picoMemStream_t	*s;
-	unsigned int	failID = 0;
-	int				failpos = -1;
-	lwObject		*obj;
-	lwSurface		*surface;
-	lwLayer			*layer;
-	lwPoint			*pt;
-	lwPolygon		*pol;
-	lwPolVert		*v;
-	lwVMapPt		*vm;
-	char			name[ 64 ];
-	int				i, j, k, numverts;
-
-	picoModel_t		*picoModel;
-	picoSurface_t	*picoSurface;
-	picoShader_t	*picoShader;
-	picoVec3_t		xyz, normal;
-	picoVec2_t		st;
-	picoColor_t		color;
-
-	int				defaultSTAxis[ 2 ];
-	picoVec2_t		defaultXYZtoSTScale;
-
-	picoVertexCombinationHash_t **hashTable;
-	picoVertexCombinationHash_t	*vertexCombinationHash;
-
-#ifdef DEBUG_PM_LWO
-	clock_t load_start, load_finish, convert_start, convert_finish;
-	double load_elapsed, convert_elapsed;
-
-	load_start = clock();
-#endif
-
-	/* do frame check */
-	if( frameNum < 0 || frameNum >= 1 )
-	{
-		_pico_printf( PICO_ERROR, "Invalid or out-of-range LWO frame specified" );
-		return NULL;
-	}
-
-	/* create a new pico memorystream */
-	s = _pico_new_memstream( (picoByte_t *)buffer, bufSize );
-	if (s == NULL)
-	{
-		return NULL;
-	}
-
-	obj = lwGetObject( fileName, s, &failID, &failpos );
-
-	_pico_free_memstream( s );
-
-	if( !obj ) {
-		_pico_printf( PICO_ERROR, "Couldn't load LWO file, failed on ID '%s', position %d", lwo_lwIDToStr( failID ), failpos );
-		return NULL;
-	}
-
-#ifdef DEBUG_PM_LWO
-	convert_start = load_finish = clock();
-	load_elapsed = (double)(load_finish - load_start) / CLOCKS_PER_SEC;
-#endif
-
-	/* -------------------------------------------------
-	pico model creation
-	------------------------------------------------- */
-	
-	/* create a new pico model */
-	picoModel = PicoNewModel();
-	if (picoModel == NULL)
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
-		return NULL;
-	}
-
-	/* do model setup */
-	PicoSetModelFrameNum( picoModel, frameNum );
-	PicoSetModelNumFrames( picoModel, 1 );
-	PicoSetModelName( picoModel, fileName );
-	PicoSetModelFileName( picoModel, fileName );
-
-	/* create all polygons from layer[ 0 ] that belong to this surface */
-	layer = &obj->layer[0];
-
-	/* warn the user that other layers are discarded */
-	if (obj->nlayers > 1)
-	{
-		_pico_printf( PICO_WARNING, "LWO loader discards any geometry data not in Layer 1 (%d layers found)", obj->nlayers );
-	}
-
-	/* initialize dummy normal */
-	normal[ 0 ] = normal[ 1 ] = normal[ 2 ] = 0.f;
-
-	/* setup default st map */
-	st[ 0 ] = st[ 1 ] = 0.f;	/* st[0] holds max, st[1] holds max par one */
-	defaultSTAxis[ 0 ] = 0;
-	defaultSTAxis[ 1 ] = 1;
-	for( i = 0; i < 3; i++ )
-	{
-		float min = layer->bbox[ i ];
-		float max = layer->bbox[ i + 3 ];
-		float size = max - min;
-		
-		if (size > st[ 0 ])
-		{
-			defaultSTAxis[ 1 ] = defaultSTAxis[ 0 ];
-			defaultSTAxis[ 0 ] = i;
-
-			st[ 1 ] = st[ 0 ];
-			st[ 0 ] = size;
-		}
-		else if (size > st[ 1 ])
-		{
-			defaultSTAxis[ 1 ] = i;
-			st[ 1 ] = size;
-		}
-	}
-	defaultXYZtoSTScale[ 0 ] = 4.f / st[ 0 ];
-	defaultXYZtoSTScale[ 1 ] = 4.f / st[ 1 ];
-
-	/* LWO surfaces become pico surfaces */
-	surface = obj->surf;
-	while (surface)
-	{
-		/* allocate new pico surface */
-		picoSurface = PicoNewSurface( picoModel );
-		if (picoSurface == NULL)
-		{
-			_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
-			PicoFreeModel( picoModel );
-			lwFreeObject( obj );
-			return NULL;
-		}
-
-		/* LWO model surfaces are all triangle meshes */
-		PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
-
-		/* set surface name */
-		PicoSetSurfaceName( picoSurface, surface->name );
-
-		/* create new pico shader */
-		picoShader = PicoNewShader( picoModel );
-		if (picoShader == NULL)
-		{
-			_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
-			PicoFreeModel( picoModel );
-			lwFreeObject( obj );
-			return NULL;
-		}
-
-		/* detox and set shader name */
-		strncpy( name, surface->name, sizeof(name) );
-		_pico_setfext( name, "" );
-		_pico_unixify( name );
-		PicoSetShaderName( picoShader, name );
-
-		/* associate current surface with newly created shader */
-		PicoSetSurfaceShader( picoSurface, picoShader );
-
-		/* copy indices and vertex data */
-		numverts = 0;
-
-		hashTable = PicoNewVertexCombinationHashTable();
-
-		if (hashTable == NULL)
-		{
-			_pico_printf( PICO_ERROR, "Unable to allocate hash table" );
-			PicoFreeModel( picoModel );
-			lwFreeObject( obj );
-			return NULL;
-		}
-
-		for( i = 0, pol = layer->polygon.pol; i < layer->polygon.count; i++, pol++ )
-		{
-			/* does this polygon belong to this surface? */
-			if (pol->surf != surface)
-				continue;
-
-			/* we only support polygons of the FACE type */
-			if (pol->type != ID_FACE)
-			{
-				_pico_printf( PICO_WARNING, "LWO loader discarded a polygon because it's type != FACE (%s)", lwo_lwIDToStr( pol->type ) );
-				continue;
-			}
-
-			/* NOTE: LWO has support for non-convex polygons, do we want to store them as well? */
-			if (pol->nverts != 3)
-			{
-				_pico_printf( PICO_WARNING, "LWO loader discarded a polygon because it has != 3 verts (%d)", pol->nverts );
-				continue;
-			}
-
-			for( j = 0, v = pol->v; j < 3; j++, v++ )
-			{
-				pt = &layer->point.pt[ v->index ];
-
-				/* setup data */
-				xyz[ 0 ] = pt->pos[ 0 ];
-				xyz[ 1 ] = pt->pos[ 2 ];
-				xyz[ 2 ] = pt->pos[ 1 ];
-
-				normal[ 0 ] = v->norm[ 0 ];
-				normal[ 1 ] = v->norm[ 2 ];
-				normal[ 2 ] = v->norm[ 1 ];
-
-				st[ 0 ] = xyz[ defaultSTAxis[ 0 ] ] * defaultXYZtoSTScale[ 0 ];
-				st[ 1 ] = xyz[ defaultSTAxis[ 1 ] ] * defaultXYZtoSTScale[ 1 ];
-
-				color[ 0 ] = (picoByte_t)(surface->color.rgb[ 0 ] * surface->diffuse.val * 0xFF);
-				color[ 1 ] = (picoByte_t)(surface->color.rgb[ 1 ] * surface->diffuse.val * 0xFF);
-				color[ 2 ] = (picoByte_t)(surface->color.rgb[ 2 ] * surface->diffuse.val * 0xFF);
-				color[ 3 ] = 0xFF;
-
-				/* set from points */
-				for( k = 0, vm = pt->vm; k < pt->nvmaps; k++, vm++ )
-				{
-					if (vm->vmap->type == LWID_('T','X','U','V'))
-					{
-						/* set st coords */
-						st[ 0 ] = vm->vmap->val[ vm->index ][ 0 ];
-						st[ 1 ] = 1.f - vm->vmap->val[ vm->index ][ 1 ];
-					}
-					else if (vm->vmap->type == LWID_('R','G','B','A'))
-					{
-						/* set rgba */
-						color[ 0 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 0 ] * surface->color.rgb[ 0 ] * surface->diffuse.val * 0xFF);
-						color[ 1 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 1 ] * surface->color.rgb[ 1 ] * surface->diffuse.val * 0xFF);
-						color[ 2 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 2 ] * surface->color.rgb[ 2 ] * surface->diffuse.val * 0xFF);
-						color[ 3 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 3 ] * 0xFF);
-					}
-				}
-
-				/* override with polygon data */
-				for( k = 0, vm = v->vm; k < v->nvmaps; k++, vm++ )
-				{
-					if (vm->vmap->type == LWID_('T','X','U','V'))
-					{
-						/* set st coords */
-						st[ 0 ] = vm->vmap->val[ vm->index ][ 0 ];
-						st[ 1 ] = 1.f - vm->vmap->val[ vm->index ][ 1 ];
-					}
-					else if (vm->vmap->type == LWID_('R','G','B','A'))
-					{
-						/* set rgba */
-						color[ 0 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 0 ] * surface->color.rgb[ 0 ] * surface->diffuse.val * 0xFF);
-						color[ 1 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 1 ] * surface->color.rgb[ 1 ] * surface->diffuse.val * 0xFF);
-						color[ 2 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 2 ] * surface->color.rgb[ 2 ] * surface->diffuse.val * 0xFF);
-						color[ 3 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 3 ] * 0xFF);
-					}
-				}
-
-				/* find vertex in this surface and if we can't find it there create it */
-				vertexCombinationHash = PicoFindVertexCombinationInHashTable( hashTable, xyz, normal, st, color );
-
-				if (vertexCombinationHash)
-				{
-					/* found an existing one */
-					PicoSetSurfaceIndex( picoSurface, (i * 3 + j ), vertexCombinationHash->index );
-				}
-				else
-				{
-					/* it is a new one */
-					vertexCombinationHash = PicoAddVertexCombinationToHashTable( hashTable, xyz, normal, st, color, (picoIndex_t) numverts );
-
-					if (vertexCombinationHash == NULL)
-					{
-						_pico_printf( PICO_ERROR, "Unable to allocate hash bucket entry table" );
-						PicoFreeVertexCombinationHashTable( hashTable );
-						PicoFreeModel( picoModel );
-						lwFreeObject( obj );
-						return NULL;
-					}
-
-					/* add the vertex to this surface */
-					PicoSetSurfaceXYZ( picoSurface, numverts, xyz );
-
-					/* set dummy normal */
-					PicoSetSurfaceNormal( picoSurface, numverts, normal );
-
-					/* set color */
-					PicoSetSurfaceColor( picoSurface, 0, numverts, color );
-
-					/* set st coords */
-					PicoSetSurfaceST( picoSurface, 0, numverts, st );
-
-					/* set index */
-					PicoSetSurfaceIndex( picoSurface, (i * 3 + j ), (picoIndex_t) numverts );
-
-					numverts++;
-				}
-			}
-		}
-
-		/* free the hashtable */
-		PicoFreeVertexCombinationHashTable( hashTable );
-
-		/* get next surface */		
-		surface = surface->next;
-	}
-
-#ifdef DEBUG_PM_LWO
-	load_start = convert_finish = clock();
-#endif
-
-	lwFreeObject( obj );
-
-#ifdef DEBUG_PM_LWO
-	load_finish = clock();
-	load_elapsed += (double)(load_finish - load_start) / CLOCKS_PER_SEC;
-	convert_elapsed = (double)(convert_finish - convert_start) / CLOCKS_PER_SEC;
-	_pico_printf( PICO_NORMAL, "Loaded model in in %-.2f second(s) (loading: %-.2fs converting: %-.2fs)\n", load_elapsed + convert_elapsed, load_elapsed, convert_elapsed  );
-#endif
-
-	/* return the new pico model */
-	return picoModel;
-}
-
-/* pico file format module definition */
-const picoModule_t picoModuleLWO =
-{
-	"1.0",						/* module version string */
-	"LightWave Object",			/* module display name */
-	"Arnout van Meer",			/* author's name */
-	"2003 Arnout van Meer, 2000 Ernie Wright",		/* module copyright */
-	{
-		"lwo", NULL, NULL, NULL	/* default extensions to use */
-	},
-	_lwo_canload,				/* validation routine */
-	_lwo_load,					/* load routine */
-	 NULL,						/* save validation routine */
-	 NULL						/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library 
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+/* marker */
+#define PM_LWO_C
+
+/* dependencies */
+#include "picointernal.h"
+#include "lwo/lwo2.h"
+
+/* uncomment when debugging this module */
+/*#define DEBUG_PM_LWO*/
+
+#ifdef DEBUG_PM_LWO
+#include "time.h"
+#endif
+
+/* helper functions */
+static const char *lwo_lwIDToStr( unsigned int lwID )
+{
+	static char lwIDStr[5];
+
+	if (!lwID)
+	{
+		return "n/a";
+	}
+
+	lwIDStr[ 0 ] = (char)((lwID) >> 24);
+	lwIDStr[ 1 ] = (char)((lwID) >> 16);
+	lwIDStr[ 2 ] = (char)((lwID) >> 8);
+	lwIDStr[ 3 ] = (char)((lwID));
+	lwIDStr[ 4 ] = '\0';
+
+	return lwIDStr;
+}
+
+/*
+_lwo_canload()
+validates a LightWave Object model file. btw, i use the
+preceding underscore cause it's a static func referenced
+by one structure only.
+*/
+static int _lwo_canload( PM_PARAMS_CANLOAD )
+{
+	picoMemStream_t *s;
+	unsigned int failID = 0;
+	int failpos = -1;
+	int ret;
+
+	/* create a new pico memorystream */
+	s = _pico_new_memstream( (picoByte_t *)buffer, bufSize );
+	if (s == NULL)
+	{
+		return PICO_PMV_ERROR_MEMORY;
+	}
+
+	ret = lwValidateObject( fileName, s, &failID, &failpos );
+
+	_pico_free_memstream( s );
+
+	return ret;
+}
+
+/*
+_lwo_load()
+loads a LightWave Object model file.
+*/
+static picoModel_t *_lwo_load( PM_PARAMS_LOAD )
+{
+	picoMemStream_t	*s;
+	unsigned int	failID = 0;
+	int				failpos = -1;
+	lwObject		*obj;
+	lwSurface		*surface;
+	lwLayer			*layer;
+	lwPoint			*pt;
+	lwPolygon		*pol;
+	lwPolVert		*v;
+	lwVMapPt		*vm;
+	char			name[ 64 ];
+	int				i, j, k, numverts;
+
+	picoModel_t		*picoModel;
+	picoSurface_t	*picoSurface;
+	picoShader_t	*picoShader;
+	picoVec3_t		xyz, normal;
+	picoVec2_t		st;
+	picoColor_t		color;
+
+	int				defaultSTAxis[ 2 ];
+	picoVec2_t		defaultXYZtoSTScale;
+
+	picoVertexCombinationHash_t **hashTable;
+	picoVertexCombinationHash_t	*vertexCombinationHash;
+
+#ifdef DEBUG_PM_LWO
+	clock_t load_start, load_finish, convert_start, convert_finish;
+	double load_elapsed, convert_elapsed;
+
+	load_start = clock();
+#endif
+
+	/* do frame check */
+	if( frameNum < 0 || frameNum >= 1 )
+	{
+		_pico_printf( PICO_ERROR, "Invalid or out-of-range LWO frame specified" );
+		return NULL;
+	}
+
+	/* create a new pico memorystream */
+	s = _pico_new_memstream( (picoByte_t *)buffer, bufSize );
+	if (s == NULL)
+	{
+		return NULL;
+	}
+
+	obj = lwGetObject( fileName, s, &failID, &failpos );
+
+	_pico_free_memstream( s );
+
+	if( !obj ) {
+		_pico_printf( PICO_ERROR, "Couldn't load LWO file, failed on ID '%s', position %d", lwo_lwIDToStr( failID ), failpos );
+		return NULL;
+	}
+
+#ifdef DEBUG_PM_LWO
+	convert_start = load_finish = clock();
+	load_elapsed = (double)(load_finish - load_start) / CLOCKS_PER_SEC;
+#endif
+
+	/* -------------------------------------------------
+	pico model creation
+	------------------------------------------------- */
+	
+	/* create a new pico model */
+	picoModel = PicoNewModel();
+	if (picoModel == NULL)
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+		return NULL;
+	}
+
+	/* do model setup */
+	PicoSetModelFrameNum( picoModel, frameNum );
+	PicoSetModelNumFrames( picoModel, 1 );
+	PicoSetModelName( picoModel, fileName );
+	PicoSetModelFileName( picoModel, fileName );
+
+	/* create all polygons from layer[ 0 ] that belong to this surface */
+	layer = &obj->layer[0];
+
+	/* warn the user that other layers are discarded */
+	if (obj->nlayers > 1)
+	{
+		_pico_printf( PICO_WARNING, "LWO loader discards any geometry data not in Layer 1 (%d layers found)", obj->nlayers );
+	}
+
+	/* initialize dummy normal */
+	normal[ 0 ] = normal[ 1 ] = normal[ 2 ] = 0.f;
+
+	/* setup default st map */
+	st[ 0 ] = st[ 1 ] = 0.f;	/* st[0] holds max, st[1] holds max par one */
+	defaultSTAxis[ 0 ] = 0;
+	defaultSTAxis[ 1 ] = 1;
+	for( i = 0; i < 3; i++ )
+	{
+		float min = layer->bbox[ i ];
+		float max = layer->bbox[ i + 3 ];
+		float size = max - min;
+		
+		if (size > st[ 0 ])
+		{
+			defaultSTAxis[ 1 ] = defaultSTAxis[ 0 ];
+			defaultSTAxis[ 0 ] = i;
+
+			st[ 1 ] = st[ 0 ];
+			st[ 0 ] = size;
+		}
+		else if (size > st[ 1 ])
+		{
+			defaultSTAxis[ 1 ] = i;
+			st[ 1 ] = size;
+		}
+	}
+	defaultXYZtoSTScale[ 0 ] = 4.f / st[ 0 ];
+	defaultXYZtoSTScale[ 1 ] = 4.f / st[ 1 ];
+
+	/* LWO surfaces become pico surfaces */
+	surface = obj->surf;
+	while (surface)
+	{
+		/* allocate new pico surface */
+		picoSurface = PicoNewSurface( picoModel );
+		if (picoSurface == NULL)
+		{
+			_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+			PicoFreeModel( picoModel );
+			lwFreeObject( obj );
+			return NULL;
+		}
+
+		/* LWO model surfaces are all triangle meshes */
+		PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+
+		/* set surface name */
+		PicoSetSurfaceName( picoSurface, surface->name );
+
+		/* create new pico shader */
+		picoShader = PicoNewShader( picoModel );
+		if (picoShader == NULL)
+		{
+			_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+			PicoFreeModel( picoModel );
+			lwFreeObject( obj );
+			return NULL;
+		}
+
+		/* detox and set shader name */
+		strncpy( name, surface->name, sizeof(name) );
+		_pico_setfext( name, "" );
+		_pico_unixify( name );
+		PicoSetShaderName( picoShader, name );
+
+		/* associate current surface with newly created shader */
+		PicoSetSurfaceShader( picoSurface, picoShader );
+
+		/* copy indices and vertex data */
+		numverts = 0;
+
+		hashTable = PicoNewVertexCombinationHashTable();
+
+		if (hashTable == NULL)
+		{
+			_pico_printf( PICO_ERROR, "Unable to allocate hash table" );
+			PicoFreeModel( picoModel );
+			lwFreeObject( obj );
+			return NULL;
+		}
+
+		for( i = 0, pol = layer->polygon.pol; i < layer->polygon.count; i++, pol++ )
+		{
+			/* does this polygon belong to this surface? */
+			if (pol->surf != surface)
+				continue;
+
+			/* we only support polygons of the FACE type */
+			if (pol->type != ID_FACE)
+			{
+				_pico_printf( PICO_WARNING, "LWO loader discarded a polygon because it's type != FACE (%s)", lwo_lwIDToStr( pol->type ) );
+				continue;
+			}
+
+			/* NOTE: LWO has support for non-convex polygons, do we want to store them as well? */
+			if (pol->nverts != 3)
+			{
+				_pico_printf( PICO_WARNING, "LWO loader discarded a polygon because it has != 3 verts (%d)", pol->nverts );
+				continue;
+			}
+
+			for( j = 0, v = pol->v; j < 3; j++, v++ )
+			{
+				pt = &layer->point.pt[ v->index ];
+
+				/* setup data */
+				xyz[ 0 ] = pt->pos[ 0 ];
+				xyz[ 1 ] = pt->pos[ 2 ];
+				xyz[ 2 ] = pt->pos[ 1 ];
+
+				normal[ 0 ] = v->norm[ 0 ];
+				normal[ 1 ] = v->norm[ 2 ];
+				normal[ 2 ] = v->norm[ 1 ];
+
+				st[ 0 ] = xyz[ defaultSTAxis[ 0 ] ] * defaultXYZtoSTScale[ 0 ];
+				st[ 1 ] = xyz[ defaultSTAxis[ 1 ] ] * defaultXYZtoSTScale[ 1 ];
+
+				color[ 0 ] = (picoByte_t)(surface->color.rgb[ 0 ] * surface->diffuse.val * 0xFF);
+				color[ 1 ] = (picoByte_t)(surface->color.rgb[ 1 ] * surface->diffuse.val * 0xFF);
+				color[ 2 ] = (picoByte_t)(surface->color.rgb[ 2 ] * surface->diffuse.val * 0xFF);
+				color[ 3 ] = 0xFF;
+
+				/* set from points */
+				for( k = 0, vm = pt->vm; k < pt->nvmaps; k++, vm++ )
+				{
+					if (vm->vmap->type == LWID_('T','X','U','V'))
+					{
+						/* set st coords */
+						st[ 0 ] = vm->vmap->val[ vm->index ][ 0 ];
+						st[ 1 ] = 1.f - vm->vmap->val[ vm->index ][ 1 ];
+					}
+					else if (vm->vmap->type == LWID_('R','G','B','A'))
+					{
+						/* set rgba */
+						color[ 0 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 0 ] * surface->color.rgb[ 0 ] * surface->diffuse.val * 0xFF);
+						color[ 1 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 1 ] * surface->color.rgb[ 1 ] * surface->diffuse.val * 0xFF);
+						color[ 2 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 2 ] * surface->color.rgb[ 2 ] * surface->diffuse.val * 0xFF);
+						color[ 3 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 3 ] * 0xFF);
+					}
+				}
+
+				/* override with polygon data */
+				for( k = 0, vm = v->vm; k < v->nvmaps; k++, vm++ )
+				{
+					if (vm->vmap->type == LWID_('T','X','U','V'))
+					{
+						/* set st coords */
+						st[ 0 ] = vm->vmap->val[ vm->index ][ 0 ];
+						st[ 1 ] = 1.f - vm->vmap->val[ vm->index ][ 1 ];
+					}
+					else if (vm->vmap->type == LWID_('R','G','B','A'))
+					{
+						/* set rgba */
+						color[ 0 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 0 ] * surface->color.rgb[ 0 ] * surface->diffuse.val * 0xFF);
+						color[ 1 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 1 ] * surface->color.rgb[ 1 ] * surface->diffuse.val * 0xFF);
+						color[ 2 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 2 ] * surface->color.rgb[ 2 ] * surface->diffuse.val * 0xFF);
+						color[ 3 ] = (picoByte_t)(vm->vmap->val[ vm->index ][ 3 ] * 0xFF);
+					}
+				}
+
+				/* find vertex in this surface and if we can't find it there create it */
+				vertexCombinationHash = PicoFindVertexCombinationInHashTable( hashTable, xyz, normal, st, color );
+
+				if (vertexCombinationHash)
+				{
+					/* found an existing one */
+					PicoSetSurfaceIndex( picoSurface, (i * 3 + j ), vertexCombinationHash->index );
+				}
+				else
+				{
+					/* it is a new one */
+					vertexCombinationHash = PicoAddVertexCombinationToHashTable( hashTable, xyz, normal, st, color, (picoIndex_t) numverts );
+
+					if (vertexCombinationHash == NULL)
+					{
+						_pico_printf( PICO_ERROR, "Unable to allocate hash bucket entry table" );
+						PicoFreeVertexCombinationHashTable( hashTable );
+						PicoFreeModel( picoModel );
+						lwFreeObject( obj );
+						return NULL;
+					}
+
+					/* add the vertex to this surface */
+					PicoSetSurfaceXYZ( picoSurface, numverts, xyz );
+
+					/* set dummy normal */
+					PicoSetSurfaceNormal( picoSurface, numverts, normal );
+
+					/* set color */
+					PicoSetSurfaceColor( picoSurface, 0, numverts, color );
+
+					/* set st coords */
+					PicoSetSurfaceST( picoSurface, 0, numverts, st );
+
+					/* set index */
+					PicoSetSurfaceIndex( picoSurface, (i * 3 + j ), (picoIndex_t) numverts );
+
+					numverts++;
+				}
+			}
+		}
+
+		/* free the hashtable */
+		PicoFreeVertexCombinationHashTable( hashTable );
+
+		/* get next surface */		
+		surface = surface->next;
+	}
+
+#ifdef DEBUG_PM_LWO
+	load_start = convert_finish = clock();
+#endif
+
+	lwFreeObject( obj );
+
+#ifdef DEBUG_PM_LWO
+	load_finish = clock();
+	load_elapsed += (double)(load_finish - load_start) / CLOCKS_PER_SEC;
+	convert_elapsed = (double)(convert_finish - convert_start) / CLOCKS_PER_SEC;
+	_pico_printf( PICO_NORMAL, "Loaded model in in %-.2f second(s) (loading: %-.2fs converting: %-.2fs)\n", load_elapsed + convert_elapsed, load_elapsed, convert_elapsed  );
+#endif
+
+	/* return the new pico model */
+	return picoModel;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModuleLWO =
+{
+	"1.0",						/* module version string */
+	"LightWave Object",			/* module display name */
+	"Arnout van Meer",			/* author's name */
+	"2003 Arnout van Meer, 2000 Ernie Wright",		/* module copyright */
+	{
+		"lwo", NULL, NULL, NULL	/* default extensions to use */
+	},
+	_lwo_canload,				/* validation routine */
+	_lwo_load,					/* load routine */
+	 NULL,						/* save validation routine */
+	 NULL						/* save routine */
+};
diff --git a/libs/picomodel/pm_md2.c b/libs/picomodel/pm_md2.c
index 2351ea58..8a603a5d 100644
--- a/libs/picomodel/pm_md2.c
+++ b/libs/picomodel/pm_md2.c
@@ -1,670 +1,670 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library 
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-/*
-Nurail: Used pm_md3.c (Randy Reddig) as a template.
-*/
-
-
-/* marker */
-#define PM_MD2_C
-
-/* dependencies */
-#include "picointernal.h"
-
-
-/* md2 model format */
-#define MD2_MAGIC				"IDP2"
-#define MD2_VERSION				8
-
-#define MD2_NUMVERTEXNORMALS	162
-#define MD2_MAX_SKINNAME		64
-#define MD2_MAX_TRIANGLES		4096
-#define MD2_MAX_VERTS			2048
-#define MD2_MAX_FRAMES			512
-#define MD2_MAX_MD2SKINS		32
-#define MD2_MAX_SKINNAME		64
-
-#ifndef byte
-	#define byte unsigned char
-#endif
-
-typedef struct index_LUT_s
-{
-	short	Vert;
-	short	ST;
-	struct	index_LUT_s	*next;
-
-} index_LUT_t;
-
-typedef struct index_DUP_LUT_s
-{
-	short			ST;
-	short			OldVert;
-
-} index_DUP_LUT_t;
-
-typedef struct
-{
-        short   s;
-        short   t;
-} md2St_t;
-
-typedef struct
-{
-        short   index_xyz[3];
-        short   index_st[3];
-} md2Triangle_t;
-
-typedef struct
-{
-        byte	v[3];                   // scaled byte to fit in frame mins/maxs
-        byte	lightnormalindex;
-} md2XyzNormal_t;
-
-typedef struct md2Frame_s
-{
-        float           scale[3];       // multiply byte verts by this
-        float           translate[3];   // then add this
-        char            name[16];       // frame name from grabbing
-        md2XyzNormal_t  verts[1];       // variable sized
-}
-md2Frame_t;
-
-
-/* md2 model file md2 structure */
-typedef struct md2_s
-{
-	char	magic[ 4 ];
-	int	version;
-
-	int	skinWidth;
-	int	skinHeight;
-	int	frameSize;
-
-	int	numSkins;
-	int	numXYZ;
-	int	numST;
-	int	numTris;
-	int	numGLCmds;
-	int	numFrames;
-
-	int	ofsSkins;
-	int	ofsST;
-	int	ofsTris;
-	int	ofsFrames;
-	int	ofsGLCmds;
-	int	ofsEnd;
-}
-md2_t;
-
-float	md2_normals[ MD2_NUMVERTEXNORMALS ][ 3 ] =
-{
-	{ -0.525731f, 0.000000f, 0.850651f },
-	{ -0.442863f, 0.238856f, 0.864188f }, 
-	{ -0.295242f, 0.000000f, 0.955423f }, 
-	{ -0.309017f, 0.500000f, 0.809017f }, 
-	{ -0.162460f, 0.262866f, 0.951056f }, 
-	{ 0.000000f, 0.000000f, 1.000000f },
-	{ 0.000000f, 0.850651f, 0.525731f },
-	{ -0.147621f, 0.716567f, 0.681718f },
-	{ 0.147621f, 0.716567f, 0.681718f }, 
-	{ 0.000000f, 0.525731f, 0.850651f }, 
-	{ 0.309017f, 0.500000f, 0.809017f }, 
-	{ 0.525731f, 0.000000f, 0.850651f }, 
-	{ 0.295242f, 0.000000f, 0.955423f }, 
-	{ 0.442863f, 0.238856f, 0.864188f }, 
-	{ 0.162460f, 0.262866f, 0.951056f }, 
-	{ -0.681718f, 0.147621f, 0.716567f }, 
-	{ -0.809017f, 0.309017f, 0.500000f }, 
-	{ -0.587785f, 0.425325f, 0.688191f }, 
-	{ -0.850651f, 0.525731f, 0.000000f }, 
-	{ -0.864188f, 0.442863f, 0.238856f }, 
-	{ -0.716567f, 0.681718f, 0.147621f }, 
-	{ -0.688191f, 0.587785f, 0.425325f }, 
-	{ -0.500000f, 0.809017f, 0.309017f }, 
-	{ -0.238856f, 0.864188f, 0.442863f }, 
-	{ -0.425325f, 0.688191f, 0.587785f }, 
-	{ -0.716567f, 0.681718f, -0.147621f }, 
-	{ -0.500000f, 0.809017f, -0.309017f }, 
-	{ -0.525731f, 0.850651f, 0.000000f }, 
-	{ 0.000000f, 0.850651f, -0.525731f }, 
-	{ -0.238856f, 0.864188f, -0.442863f }, 
-	{ 0.000000f, 0.955423f, -0.295242f }, 
-	{ -0.262866f, 0.951056f, -0.162460f }, 
-	{ 0.000000f, 1.000000f, 0.000000f }, 
-	{ 0.000000f, 0.955423f, 0.295242f }, 
-	{ -0.262866f, 0.951056f, 0.162460f }, 
-	{ 0.238856f, 0.864188f, 0.442863f }, 
-	{ 0.262866f, 0.951056f, 0.162460f }, 
-	{ 0.500000f, 0.809017f, 0.309017f }, 
-	{ 0.238856f, 0.864188f, -0.442863f }, 
-	{ 0.262866f, 0.951056f, -0.162460f }, 
-	{ 0.500000f, 0.809017f, -0.309017f }, 
-	{ 0.850651f, 0.525731f, 0.000000f }, 
-	{ 0.716567f, 0.681718f, 0.147621f }, 
-	{ 0.716567f, 0.681718f, -0.147621f }, 
-	{ 0.525731f, 0.850651f, 0.000000f }, 
-	{ 0.425325f, 0.688191f, 0.587785f }, 
-	{ 0.864188f, 0.442863f, 0.238856f }, 
-	{ 0.688191f, 0.587785f, 0.425325f }, 
-	{ 0.809017f, 0.309017f, 0.500000f }, 
-	{ 0.681718f, 0.147621f, 0.716567f }, 
-	{ 0.587785f, 0.425325f, 0.688191f }, 
-	{ 0.955423f, 0.295242f, 0.000000f }, 
-	{ 1.000000f, 0.000000f, 0.000000f }, 
-	{ 0.951056f, 0.162460f, 0.262866f }, 
-	{ 0.850651f, -0.525731f, 0.000000f }, 
-	{ 0.955423f, -0.295242f, 0.000000f }, 
-	{ 0.864188f, -0.442863f, 0.238856f }, 
-	{ 0.951056f, -0.162460f, 0.262866f }, 
-	{ 0.809017f, -0.309017f, 0.500000f }, 
-	{ 0.681718f, -0.147621f, 0.716567f }, 
-	{ 0.850651f, 0.000000f, 0.525731f }, 
-	{ 0.864188f, 0.442863f, -0.238856f }, 
-	{ 0.809017f, 0.309017f, -0.500000f }, 
-	{ 0.951056f, 0.162460f, -0.262866f }, 
-	{ 0.525731f, 0.000000f, -0.850651f }, 
-	{ 0.681718f, 0.147621f, -0.716567f }, 
-	{ 0.681718f, -0.147621f, -0.716567f }, 
-	{ 0.850651f, 0.000000f, -0.525731f }, 
-	{ 0.809017f, -0.309017f, -0.500000f }, 
-	{ 0.864188f, -0.442863f, -0.238856f }, 
-	{ 0.951056f, -0.162460f, -0.262866f }, 
-	{ 0.147621f, 0.716567f, -0.681718f }, 
-	{ 0.309017f, 0.500000f, -0.809017f }, 
-	{ 0.425325f, 0.688191f, -0.587785f }, 
-	{ 0.442863f, 0.238856f, -0.864188f }, 
-	{ 0.587785f, 0.425325f, -0.688191f }, 
-	{ 0.688191f, 0.587785f, -0.425325f }, 
-	{ -0.147621f, 0.716567f, -0.681718f }, 
-	{ -0.309017f, 0.500000f, -0.809017f }, 
-	{ 0.000000f, 0.525731f, -0.850651f }, 
-	{ -0.525731f, 0.000000f, -0.850651f }, 
-	{ -0.442863f, 0.238856f, -0.864188f }, 
-	{ -0.295242f, 0.000000f, -0.955423f }, 
-	{ -0.162460f, 0.262866f, -0.951056f }, 
-	{ 0.000000f, 0.000000f, -1.000000f }, 
-	{ 0.295242f, 0.000000f, -0.955423f }, 
-	{ 0.162460f, 0.262866f, -0.951056f }, 
-	{ -0.442863f, -0.238856f, -0.864188f }, 
-	{ -0.309017f, -0.500000f, -0.809017f }, 
-	{ -0.162460f, -0.262866f, -0.951056f }, 
-	{ 0.000000f, -0.850651f, -0.525731f }, 
-	{ -0.147621f, -0.716567f, -0.681718f }, 
-	{ 0.147621f, -0.716567f, -0.681718f }, 
-	{ 0.000000f, -0.525731f, -0.850651f }, 
-	{ 0.309017f, -0.500000f, -0.809017f }, 
-	{ 0.442863f, -0.238856f, -0.864188f }, 
-	{ 0.162460f, -0.262866f, -0.951056f }, 
-	{ 0.238856f, -0.864188f, -0.442863f }, 
-	{ 0.500000f, -0.809017f, -0.309017f }, 
-	{ 0.425325f, -0.688191f, -0.587785f }, 
-	{ 0.716567f, -0.681718f, -0.147621f }, 
-	{ 0.688191f, -0.587785f, -0.425325f }, 
-	{ 0.587785f, -0.425325f, -0.688191f }, 
-	{ 0.000000f, -0.955423f, -0.295242f }, 
-	{ 0.000000f, -1.000000f, 0.000000f }, 
-	{ 0.262866f, -0.951056f, -0.162460f }, 
-	{ 0.000000f, -0.850651f, 0.525731f }, 
-	{ 0.000000f, -0.955423f, 0.295242f }, 
-	{ 0.238856f, -0.864188f, 0.442863f }, 
-	{ 0.262866f, -0.951056f, 0.162460f }, 
-	{ 0.500000f, -0.809017f, 0.309017f }, 
-	{ 0.716567f, -0.681718f, 0.147621f }, 
-	{ 0.525731f, -0.850651f, 0.000000f }, 
-	{ -0.238856f, -0.864188f, -0.442863f }, 
-	{ -0.500000f, -0.809017f, -0.309017f }, 
-	{ -0.262866f, -0.951056f, -0.162460f }, 
-	{ -0.850651f, -0.525731f, 0.000000f }, 
-	{ -0.716567f, -0.681718f, -0.147621f }, 
-	{ -0.716567f, -0.681718f, 0.147621f }, 
-	{ -0.525731f, -0.850651f, 0.000000f }, 
-	{ -0.500000f, -0.809017f, 0.309017f }, 
-	{ -0.238856f, -0.864188f, 0.442863f }, 
-	{ -0.262866f, -0.951056f, 0.162460f }, 
-	{ -0.864188f, -0.442863f, 0.238856f }, 
-	{ -0.809017f, -0.309017f, 0.500000f }, 
-	{ -0.688191f, -0.587785f, 0.425325f }, 
-	{ -0.681718f, -0.147621f, 0.716567f }, 
-	{ -0.442863f, -0.238856f, 0.864188f }, 
-	{ -0.587785f, -0.425325f, 0.688191f }, 
-	{ -0.309017f, -0.500000f, 0.809017f }, 
-	{ -0.147621f, -0.716567f, 0.681718f }, 
-	{ -0.425325f, -0.688191f, 0.587785f }, 
-	{ -0.162460f, -0.262866f, 0.951056f }, 
-	{ 0.442863f, -0.238856f, 0.864188f }, 
-	{ 0.162460f, -0.262866f, 0.951056f }, 
-	{ 0.309017f, -0.500000f, 0.809017f }, 
-	{ 0.147621f, -0.716567f, 0.681718f }, 
-	{ 0.000000f, -0.525731f, 0.850651f }, 
-	{ 0.425325f, -0.688191f, 0.587785f }, 
-	{ 0.587785f, -0.425325f, 0.688191f }, 
-	{ 0.688191f, -0.587785f, 0.425325f }, 
-	{ -0.955423f, 0.295242f, 0.000000f }, 
-	{ -0.951056f, 0.162460f, 0.262866f }, 
-	{ -1.000000f, 0.000000f, 0.000000f }, 
-	{ -0.850651f, 0.000000f, 0.525731f }, 
-	{ -0.955423f, -0.295242f, 0.000000f }, 
-	{ -0.951056f, -0.162460f, 0.262866f }, 
-	{ -0.864188f, 0.442863f, -0.238856f }, 
-	{ -0.951056f, 0.162460f, -0.262866f }, 
-	{ -0.809017f, 0.309017f, -0.500000f }, 
-	{ -0.864188f, -0.442863f, -0.238856f },
-	{ -0.951056f, -0.162460f, -0.262866f }, 
-	{ -0.809017f, -0.309017f, -0.500000f }, 
-	{ -0.681718f, 0.147621f, -0.716567f }, 
-	{ -0.681718f, -0.147621f, -0.716567f }, 
-	{ -0.850651f, 0.000000f, -0.525731f }, 
-	{ -0.688191f, 0.587785f, -0.425325f }, 
-	{ -0.587785f, 0.425325f, -0.688191f }, 
-	{ -0.425325f, 0.688191f, -0.587785f }, 
-	{ -0.425325f, -0.688191f, -0.587785f }, 
-	{ -0.587785f, -0.425325f, -0.688191f }, 
-	{ -0.688191f, -0.587785f, -0.425325f }, 
-};
-
-
-// _md2_canload()
-
-static int _md2_canload( PM_PARAMS_CANLOAD )
-{
-	md2_t	*md2;
-
- 	/* to keep the compiler happy */
-	*fileName = *fileName;
-
-	/* sanity check */
-	if( bufSize < ( sizeof( *md2 ) * 2) )
-		return PICO_PMV_ERROR_SIZE;
-	
-	/* set as md2 */
-	md2 = (md2_t*) buffer;
-	
-	/* check md2 magic */
-	if( *((int*) md2->magic) != *((int*) MD2_MAGIC) ) 
-		return PICO_PMV_ERROR_IDENT;
-	
-	/* check md2 version */
-	if( _pico_little_long( md2->version ) != MD2_VERSION )
-		return PICO_PMV_ERROR_VERSION;
-
- 	/* file seems to be a valid md2 */
-	return PICO_PMV_OK;
-}
-
-
-
-// _md2_load() loads a quake2 md2 model file.
-
-
-static picoModel_t *_md2_load( PM_PARAMS_LOAD )
-{
-	int				i, j, dups, dup_index;
-	short			tot_numVerts;
-	index_LUT_t		*p_index_LUT, *p_index_LUT2, *p_index_LUT3;
-	index_DUP_LUT_t	*p_index_LUT_DUPS;
-	md2Triangle_t	*p_md2Triangle;
-
-	char			skinname[ MD2_MAX_SKINNAME ];
- 	md2_t			*md2;
- 	md2St_t			*texCoord;
-	md2Frame_t		*frame;
-	md2Triangle_t	*triangle;
-	md2XyzNormal_t	*vertex;
-
-	picoByte_t      *bb;
-	picoModel_t		*picoModel;
-	picoSurface_t	*picoSurface;
-	picoShader_t	*picoShader;
-	picoVec3_t		xyz, normal;
-	picoVec2_t		st;
-	picoColor_t		color;
-	
-
-	// md2 loading
- 	_pico_printf( PICO_NORMAL, "Loading \"%s\"", fileName );
-
-	/* set as md2 */
-	bb = (picoByte_t*) buffer;
-	md2	= (md2_t*) buffer;
-
-	/* check ident and version */
-	if( *((int*) md2->magic) != *((int*) MD2_MAGIC) || _pico_little_long( md2->version ) != MD2_VERSION )
-	{
-		/* not an md2 file (todo: set error) */
-		_pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
-		return NULL;
-	}
-	
-	// swap md2
-	md2->version = _pico_little_long( md2->version );
-
-	md2->skinWidth = _pico_little_long( md2->skinWidth );
-	md2->skinHeight = _pico_little_long( md2->skinHeight );
-	md2->frameSize = _pico_little_long( md2->frameSize );
-
-	md2->numSkins = _pico_little_long( md2->numSkins );
-	md2->numXYZ = _pico_little_long( md2->numXYZ );
-	md2->numST = _pico_little_long( md2->numST );
-	md2->numTris = _pico_little_long( md2->numTris );
-	md2->numGLCmds = _pico_little_long( md2->numGLCmds );
-	md2->numFrames = _pico_little_long( md2->numFrames );
-
-	md2->ofsSkins = _pico_little_long( md2->ofsSkins );
-	md2->ofsST = _pico_little_long( md2->ofsST );
-	md2->ofsTris = _pico_little_long( md2->ofsTris );
-	md2->ofsFrames = _pico_little_long( md2->ofsFrames );
-	md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
-	md2->ofsEnd = _pico_little_long( md2->ofsEnd );
-
-	// do frame check
-	if( md2->numFrames < 1 )
-	{
-		_pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
-		return NULL;
-	}
-	
-	if( frameNum < 0 || frameNum >= md2->numFrames )
-	{
-		_pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
-		return NULL;
-	}
-
-	// Setup Frame
-	frame = (md2Frame_t *) (bb + md2->ofsFrames + (sizeof(md2Frame_t) * frameNum));
-
-	// swap frame scale and translation
-	for( i = 0; i < 3; i++ )
-	{
-		frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
-		frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
-	}
-
-	// swap triangles
-	triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
-	for( i = 0; i < md2->numTris; i++, triangle++ )
-	{
-		for( j = 0; j < 3; j++ )
-		{
-			triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
-			triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
-		}
-	}
-
-	// swap st coords
-	texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
-	for( i = 0; i < md2->numST; i++, texCoord++ )
-	{
-		texCoord->s = _pico_little_short( texCoord->s );
-		texCoord->t = _pico_little_short( texCoord->t );
-	}
-
-	// set Skin Name
-	strncpy(skinname, (bb + md2->ofsSkins), MD2_MAX_SKINNAME );
-
-	// Print out md2 values
-	_pico_printf(PICO_VERBOSE,"Skins: %d  Verts: %d  STs: %d  Triangles: %d  Frames: %d\nSkin Name \"%s\"\n", md2->numSkins, md2->numXYZ, md2->numST, md2->numTris, md2->numFrames, &skinname );
-
-	// detox Skin name
-	_pico_setfext( skinname, "" );
-	_pico_unixify( skinname );
-
-	/* create new pico model */
-	picoModel = PicoNewModel();
-	if( picoModel == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
-		return NULL;
-	}
-
-	/* do model setup */
-	PicoSetModelFrameNum( picoModel, frameNum );
-	PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
-	PicoSetModelName( picoModel, fileName );
-	PicoSetModelFileName( picoModel, fileName );
-
-	// allocate new pico surface
-	picoSurface = PicoNewSurface( picoModel );
-	if( picoSurface == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
-		PicoFreeModel( picoModel );
-		return NULL;
-	}
-
-
-	PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
-	PicoSetSurfaceName( picoSurface, frame->name );
-	picoShader = PicoNewShader( picoModel );
-	if( picoShader == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
-		PicoFreeModel( picoModel );
-		return NULL;
-	}
-
-	PicoSetShaderName( picoShader, skinname );
-
-	// associate current surface with newly created shader
-	PicoSetSurfaceShader( picoSurface, picoShader );
-
-	// Init LUT for Verts
-	p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * md2->numXYZ);
-	for(i=0; i<md2->numXYZ; i++)
-	{
-		p_index_LUT[i].Vert = -1;
-		p_index_LUT[i].ST = -1;
-		p_index_LUT[i].next = NULL;
-	}
-
-	// Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
-	tot_numVerts = md2->numXYZ;
-	dups = 0;
-	for(i=0; i<md2->numTris; i++)
-	{
-		p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + (sizeof(md2Triangle_t)*i));
-		for(j=0; j<3; j++)
-		{
-			if (p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1) // No Main Entry
-				p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
-
-			else if (p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) // Equal to Main Entry
-				continue;
-
-			else if ( (p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL) )  // Not equal to Main entry, and no LL entry
-			{	// Add first entry of LL from Main
-				p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
-				if (p_index_LUT2 == NULL)
-					_pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
-				p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
-				p_index_LUT2->Vert = dups;
-				p_index_LUT2->ST = p_md2Triangle->index_st[j];
-				p_index_LUT2->next = NULL;
-				p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
-				dups++;
-			}
-			else // Try to find in LL from Main Entry
-			{
-				p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
-				while ( (p_index_LUT2 != NULL) && (p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
-				{
-					p_index_LUT3 = p_index_LUT2;
-					p_index_LUT2 = p_index_LUT2->next;
-				}
-				p_index_LUT2 = p_index_LUT3;
-
-				if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) // Found it
-				{
-					p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
-					continue;
-				}
-
-				if ( p_index_LUT2->next == NULL)  // Didn't find it. Add entry to LL.
-				{
-					// Add the Entry
-					p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
-					if (p_index_LUT3 == NULL)
-						_pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
-					p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
-					p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
-					p_index_LUT3->ST = p_md2Triangle->index_st[j];
-					p_index_LUT3->next = NULL;
-					p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
-					dups++;
-				}
-			}
-		}
-	}
-
-	// malloc and build array for Dup STs
-	p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
-	if (p_index_LUT_DUPS == NULL)
-		_pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
-
-	dup_index = 0;
-	for(i=0; i<md2->numXYZ; i++)
-	{
-		p_index_LUT2 = p_index_LUT[i].next;
-		while (p_index_LUT2 != NULL)
-		{
-			p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
-			p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
-			dup_index++;
-			p_index_LUT2 = p_index_LUT2->next;
-		}
-	}
-
-	// Build Picomodel
-	triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
-	texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
-	vertex = (md2XyzNormal_t*) ((picoByte_t*) (frame->verts) );
-	for( j = 0; j < md2->numTris; j++, triangle++ )
-	{
-		PicoSetSurfaceIndex( picoSurface, j*3   , triangle->index_xyz[0] );
-		PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
-		PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
-	}
-
-	for(i=0; i< md2->numXYZ; i++, vertex++)
-	{
-		/* set vertex origin */
-		xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
-		xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
-		xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
-		PicoSetSurfaceXYZ( picoSurface, i , xyz );
-
-		/* set normal */
-		normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
-		normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
-		normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
-		PicoSetSurfaceNormal( picoSurface, i , normal );
-
-		/* set st coords */
-		st[ 0 ] =  ((texCoord[p_index_LUT[i].ST].s) / ((float)md2->skinWidth));
-		st[ 1 ] =  (texCoord[p_index_LUT[i].ST].t / ((float)md2->skinHeight));
-		PicoSetSurfaceST( picoSurface, 0, i , st );
-	}
-
-	if (dups)
-	{
-		for(i=0; i<dups; i++)
-		{
-			j = p_index_LUT_DUPS[i].OldVert;
-			/* set vertex origin */
-			xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
-			xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
-			xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
-			PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ , xyz );
-
-			/* set normal */
-			normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
-			normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
-			normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
-			PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ , normal );
-
-			/* set st coords */
-			st[ 0 ] =  ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)md2->skinWidth));
-			st[ 1 ] =  (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)md2->skinHeight));
-			PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ , st );
-		}
-	}
-
-	/* set color */
-	PicoSetSurfaceColor( picoSurface, 0, 0, color );
-
-	// Free up malloc'ed LL entries
-	for(i=0; i<md2->numXYZ; i++)
-	{
-		if(p_index_LUT[i].next != NULL)
-		{
-			p_index_LUT2 = p_index_LUT[i].next;
-			do {
-				p_index_LUT3 = p_index_LUT2->next;
-				_pico_free(p_index_LUT2);
-				p_index_LUT2 = p_index_LUT3;
-				dups--;
-			} while (p_index_LUT2 != NULL);
-		}
-	}
-
-	if (dups)
-		_pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
-
-	// Free malloc'ed LUTs
- 	_pico_free(p_index_LUT);
-	_pico_free(p_index_LUT_DUPS);
-
-	/* return the new pico model */
-	return picoModel;
-
-}
-
-
-
-/* pico file format module definition */
-const picoModule_t picoModuleMD2 =
-{
-	"0.875",						/* module version string */
-	"Quake 2 MD2",					/* module display name */
-	"Nurail",						/* author's name */
-	"2003 Nurail",					/* module copyright */
-	{
-		"md2", NULL, NULL, NULL		/* default extensions to use */
-	},
-	_md2_canload,					/* validation routine */
-	_md2_load,						/* load routine */
-	 NULL,							/* save validation routine */
-	 NULL							/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library 
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+/*
+Nurail: Used pm_md3.c (Randy Reddig) as a template.
+*/
+
+
+/* marker */
+#define PM_MD2_C
+
+/* dependencies */
+#include "picointernal.h"
+
+
+/* md2 model format */
+#define MD2_MAGIC				"IDP2"
+#define MD2_VERSION				8
+
+#define MD2_NUMVERTEXNORMALS	162
+#define MD2_MAX_SKINNAME		64
+#define MD2_MAX_TRIANGLES		4096
+#define MD2_MAX_VERTS			2048
+#define MD2_MAX_FRAMES			512
+#define MD2_MAX_MD2SKINS		32
+#define MD2_MAX_SKINNAME		64
+
+#ifndef byte
+	#define byte unsigned char
+#endif
+
+typedef struct index_LUT_s
+{
+	short	Vert;
+	short	ST;
+	struct	index_LUT_s	*next;
+
+} index_LUT_t;
+
+typedef struct index_DUP_LUT_s
+{
+	short			ST;
+	short			OldVert;
+
+} index_DUP_LUT_t;
+
+typedef struct
+{
+        short   s;
+        short   t;
+} md2St_t;
+
+typedef struct
+{
+        short   index_xyz[3];
+        short   index_st[3];
+} md2Triangle_t;
+
+typedef struct
+{
+        byte	v[3];                   // scaled byte to fit in frame mins/maxs
+        byte	lightnormalindex;
+} md2XyzNormal_t;
+
+typedef struct md2Frame_s
+{
+        float           scale[3];       // multiply byte verts by this
+        float           translate[3];   // then add this
+        char            name[16];       // frame name from grabbing
+        md2XyzNormal_t  verts[1];       // variable sized
+}
+md2Frame_t;
+
+
+/* md2 model file md2 structure */
+typedef struct md2_s
+{
+	char	magic[ 4 ];
+	int	version;
+
+	int	skinWidth;
+	int	skinHeight;
+	int	frameSize;
+
+	int	numSkins;
+	int	numXYZ;
+	int	numST;
+	int	numTris;
+	int	numGLCmds;
+	int	numFrames;
+
+	int	ofsSkins;
+	int	ofsST;
+	int	ofsTris;
+	int	ofsFrames;
+	int	ofsGLCmds;
+	int	ofsEnd;
+}
+md2_t;
+
+float	md2_normals[ MD2_NUMVERTEXNORMALS ][ 3 ] =
+{
+	{ -0.525731f, 0.000000f, 0.850651f },
+	{ -0.442863f, 0.238856f, 0.864188f }, 
+	{ -0.295242f, 0.000000f, 0.955423f }, 
+	{ -0.309017f, 0.500000f, 0.809017f }, 
+	{ -0.162460f, 0.262866f, 0.951056f }, 
+	{ 0.000000f, 0.000000f, 1.000000f },
+	{ 0.000000f, 0.850651f, 0.525731f },
+	{ -0.147621f, 0.716567f, 0.681718f },
+	{ 0.147621f, 0.716567f, 0.681718f }, 
+	{ 0.000000f, 0.525731f, 0.850651f }, 
+	{ 0.309017f, 0.500000f, 0.809017f }, 
+	{ 0.525731f, 0.000000f, 0.850651f }, 
+	{ 0.295242f, 0.000000f, 0.955423f }, 
+	{ 0.442863f, 0.238856f, 0.864188f }, 
+	{ 0.162460f, 0.262866f, 0.951056f }, 
+	{ -0.681718f, 0.147621f, 0.716567f }, 
+	{ -0.809017f, 0.309017f, 0.500000f }, 
+	{ -0.587785f, 0.425325f, 0.688191f }, 
+	{ -0.850651f, 0.525731f, 0.000000f }, 
+	{ -0.864188f, 0.442863f, 0.238856f }, 
+	{ -0.716567f, 0.681718f, 0.147621f }, 
+	{ -0.688191f, 0.587785f, 0.425325f }, 
+	{ -0.500000f, 0.809017f, 0.309017f }, 
+	{ -0.238856f, 0.864188f, 0.442863f }, 
+	{ -0.425325f, 0.688191f, 0.587785f }, 
+	{ -0.716567f, 0.681718f, -0.147621f }, 
+	{ -0.500000f, 0.809017f, -0.309017f }, 
+	{ -0.525731f, 0.850651f, 0.000000f }, 
+	{ 0.000000f, 0.850651f, -0.525731f }, 
+	{ -0.238856f, 0.864188f, -0.442863f }, 
+	{ 0.000000f, 0.955423f, -0.295242f }, 
+	{ -0.262866f, 0.951056f, -0.162460f }, 
+	{ 0.000000f, 1.000000f, 0.000000f }, 
+	{ 0.000000f, 0.955423f, 0.295242f }, 
+	{ -0.262866f, 0.951056f, 0.162460f }, 
+	{ 0.238856f, 0.864188f, 0.442863f }, 
+	{ 0.262866f, 0.951056f, 0.162460f }, 
+	{ 0.500000f, 0.809017f, 0.309017f }, 
+	{ 0.238856f, 0.864188f, -0.442863f }, 
+	{ 0.262866f, 0.951056f, -0.162460f }, 
+	{ 0.500000f, 0.809017f, -0.309017f }, 
+	{ 0.850651f, 0.525731f, 0.000000f }, 
+	{ 0.716567f, 0.681718f, 0.147621f }, 
+	{ 0.716567f, 0.681718f, -0.147621f }, 
+	{ 0.525731f, 0.850651f, 0.000000f }, 
+	{ 0.425325f, 0.688191f, 0.587785f }, 
+	{ 0.864188f, 0.442863f, 0.238856f }, 
+	{ 0.688191f, 0.587785f, 0.425325f }, 
+	{ 0.809017f, 0.309017f, 0.500000f }, 
+	{ 0.681718f, 0.147621f, 0.716567f }, 
+	{ 0.587785f, 0.425325f, 0.688191f }, 
+	{ 0.955423f, 0.295242f, 0.000000f }, 
+	{ 1.000000f, 0.000000f, 0.000000f }, 
+	{ 0.951056f, 0.162460f, 0.262866f }, 
+	{ 0.850651f, -0.525731f, 0.000000f }, 
+	{ 0.955423f, -0.295242f, 0.000000f }, 
+	{ 0.864188f, -0.442863f, 0.238856f }, 
+	{ 0.951056f, -0.162460f, 0.262866f }, 
+	{ 0.809017f, -0.309017f, 0.500000f }, 
+	{ 0.681718f, -0.147621f, 0.716567f }, 
+	{ 0.850651f, 0.000000f, 0.525731f }, 
+	{ 0.864188f, 0.442863f, -0.238856f }, 
+	{ 0.809017f, 0.309017f, -0.500000f }, 
+	{ 0.951056f, 0.162460f, -0.262866f }, 
+	{ 0.525731f, 0.000000f, -0.850651f }, 
+	{ 0.681718f, 0.147621f, -0.716567f }, 
+	{ 0.681718f, -0.147621f, -0.716567f }, 
+	{ 0.850651f, 0.000000f, -0.525731f }, 
+	{ 0.809017f, -0.309017f, -0.500000f }, 
+	{ 0.864188f, -0.442863f, -0.238856f }, 
+	{ 0.951056f, -0.162460f, -0.262866f }, 
+	{ 0.147621f, 0.716567f, -0.681718f }, 
+	{ 0.309017f, 0.500000f, -0.809017f }, 
+	{ 0.425325f, 0.688191f, -0.587785f }, 
+	{ 0.442863f, 0.238856f, -0.864188f }, 
+	{ 0.587785f, 0.425325f, -0.688191f }, 
+	{ 0.688191f, 0.587785f, -0.425325f }, 
+	{ -0.147621f, 0.716567f, -0.681718f }, 
+	{ -0.309017f, 0.500000f, -0.809017f }, 
+	{ 0.000000f, 0.525731f, -0.850651f }, 
+	{ -0.525731f, 0.000000f, -0.850651f }, 
+	{ -0.442863f, 0.238856f, -0.864188f }, 
+	{ -0.295242f, 0.000000f, -0.955423f }, 
+	{ -0.162460f, 0.262866f, -0.951056f }, 
+	{ 0.000000f, 0.000000f, -1.000000f }, 
+	{ 0.295242f, 0.000000f, -0.955423f }, 
+	{ 0.162460f, 0.262866f, -0.951056f }, 
+	{ -0.442863f, -0.238856f, -0.864188f }, 
+	{ -0.309017f, -0.500000f, -0.809017f }, 
+	{ -0.162460f, -0.262866f, -0.951056f }, 
+	{ 0.000000f, -0.850651f, -0.525731f }, 
+	{ -0.147621f, -0.716567f, -0.681718f }, 
+	{ 0.147621f, -0.716567f, -0.681718f }, 
+	{ 0.000000f, -0.525731f, -0.850651f }, 
+	{ 0.309017f, -0.500000f, -0.809017f }, 
+	{ 0.442863f, -0.238856f, -0.864188f }, 
+	{ 0.162460f, -0.262866f, -0.951056f }, 
+	{ 0.238856f, -0.864188f, -0.442863f }, 
+	{ 0.500000f, -0.809017f, -0.309017f }, 
+	{ 0.425325f, -0.688191f, -0.587785f }, 
+	{ 0.716567f, -0.681718f, -0.147621f }, 
+	{ 0.688191f, -0.587785f, -0.425325f }, 
+	{ 0.587785f, -0.425325f, -0.688191f }, 
+	{ 0.000000f, -0.955423f, -0.295242f }, 
+	{ 0.000000f, -1.000000f, 0.000000f }, 
+	{ 0.262866f, -0.951056f, -0.162460f }, 
+	{ 0.000000f, -0.850651f, 0.525731f }, 
+	{ 0.000000f, -0.955423f, 0.295242f }, 
+	{ 0.238856f, -0.864188f, 0.442863f }, 
+	{ 0.262866f, -0.951056f, 0.162460f }, 
+	{ 0.500000f, -0.809017f, 0.309017f }, 
+	{ 0.716567f, -0.681718f, 0.147621f }, 
+	{ 0.525731f, -0.850651f, 0.000000f }, 
+	{ -0.238856f, -0.864188f, -0.442863f }, 
+	{ -0.500000f, -0.809017f, -0.309017f }, 
+	{ -0.262866f, -0.951056f, -0.162460f }, 
+	{ -0.850651f, -0.525731f, 0.000000f }, 
+	{ -0.716567f, -0.681718f, -0.147621f }, 
+	{ -0.716567f, -0.681718f, 0.147621f }, 
+	{ -0.525731f, -0.850651f, 0.000000f }, 
+	{ -0.500000f, -0.809017f, 0.309017f }, 
+	{ -0.238856f, -0.864188f, 0.442863f }, 
+	{ -0.262866f, -0.951056f, 0.162460f }, 
+	{ -0.864188f, -0.442863f, 0.238856f }, 
+	{ -0.809017f, -0.309017f, 0.500000f }, 
+	{ -0.688191f, -0.587785f, 0.425325f }, 
+	{ -0.681718f, -0.147621f, 0.716567f }, 
+	{ -0.442863f, -0.238856f, 0.864188f }, 
+	{ -0.587785f, -0.425325f, 0.688191f }, 
+	{ -0.309017f, -0.500000f, 0.809017f }, 
+	{ -0.147621f, -0.716567f, 0.681718f }, 
+	{ -0.425325f, -0.688191f, 0.587785f }, 
+	{ -0.162460f, -0.262866f, 0.951056f }, 
+	{ 0.442863f, -0.238856f, 0.864188f }, 
+	{ 0.162460f, -0.262866f, 0.951056f }, 
+	{ 0.309017f, -0.500000f, 0.809017f }, 
+	{ 0.147621f, -0.716567f, 0.681718f }, 
+	{ 0.000000f, -0.525731f, 0.850651f }, 
+	{ 0.425325f, -0.688191f, 0.587785f }, 
+	{ 0.587785f, -0.425325f, 0.688191f }, 
+	{ 0.688191f, -0.587785f, 0.425325f }, 
+	{ -0.955423f, 0.295242f, 0.000000f }, 
+	{ -0.951056f, 0.162460f, 0.262866f }, 
+	{ -1.000000f, 0.000000f, 0.000000f }, 
+	{ -0.850651f, 0.000000f, 0.525731f }, 
+	{ -0.955423f, -0.295242f, 0.000000f }, 
+	{ -0.951056f, -0.162460f, 0.262866f }, 
+	{ -0.864188f, 0.442863f, -0.238856f }, 
+	{ -0.951056f, 0.162460f, -0.262866f }, 
+	{ -0.809017f, 0.309017f, -0.500000f }, 
+	{ -0.864188f, -0.442863f, -0.238856f },
+	{ -0.951056f, -0.162460f, -0.262866f }, 
+	{ -0.809017f, -0.309017f, -0.500000f }, 
+	{ -0.681718f, 0.147621f, -0.716567f }, 
+	{ -0.681718f, -0.147621f, -0.716567f }, 
+	{ -0.850651f, 0.000000f, -0.525731f }, 
+	{ -0.688191f, 0.587785f, -0.425325f }, 
+	{ -0.587785f, 0.425325f, -0.688191f }, 
+	{ -0.425325f, 0.688191f, -0.587785f }, 
+	{ -0.425325f, -0.688191f, -0.587785f }, 
+	{ -0.587785f, -0.425325f, -0.688191f }, 
+	{ -0.688191f, -0.587785f, -0.425325f }, 
+};
+
+
+// _md2_canload()
+
+static int _md2_canload( PM_PARAMS_CANLOAD )
+{
+	md2_t	*md2;
+
+ 	/* to keep the compiler happy */
+	*fileName = *fileName;
+
+	/* sanity check */
+	if( bufSize < ( sizeof( *md2 ) * 2) )
+		return PICO_PMV_ERROR_SIZE;
+	
+	/* set as md2 */
+	md2 = (md2_t*) buffer;
+	
+	/* check md2 magic */
+	if( *((int*) md2->magic) != *((int*) MD2_MAGIC) ) 
+		return PICO_PMV_ERROR_IDENT;
+	
+	/* check md2 version */
+	if( _pico_little_long( md2->version ) != MD2_VERSION )
+		return PICO_PMV_ERROR_VERSION;
+
+ 	/* file seems to be a valid md2 */
+	return PICO_PMV_OK;
+}
+
+
+
+// _md2_load() loads a quake2 md2 model file.
+
+
+static picoModel_t *_md2_load( PM_PARAMS_LOAD )
+{
+	int				i, j, dups, dup_index;
+	short			tot_numVerts;
+	index_LUT_t		*p_index_LUT, *p_index_LUT2, *p_index_LUT3;
+	index_DUP_LUT_t	*p_index_LUT_DUPS;
+	md2Triangle_t	*p_md2Triangle;
+
+	char			skinname[ MD2_MAX_SKINNAME ];
+ 	md2_t			*md2;
+ 	md2St_t			*texCoord;
+	md2Frame_t		*frame;
+	md2Triangle_t	*triangle;
+	md2XyzNormal_t	*vertex;
+
+	picoByte_t      *bb;
+	picoModel_t		*picoModel;
+	picoSurface_t	*picoSurface;
+	picoShader_t	*picoShader;
+	picoVec3_t		xyz, normal;
+	picoVec2_t		st;
+	picoColor_t		color;
+	
+
+	// md2 loading
+ 	_pico_printf( PICO_NORMAL, "Loading \"%s\"", fileName );
+
+	/* set as md2 */
+	bb = (picoByte_t*) buffer;
+	md2	= (md2_t*) buffer;
+
+	/* check ident and version */
+	if( *((int*) md2->magic) != *((int*) MD2_MAGIC) || _pico_little_long( md2->version ) != MD2_VERSION )
+	{
+		/* not an md2 file (todo: set error) */
+		_pico_printf( PICO_ERROR, "%s is not an MD2 File!", fileName );
+		return NULL;
+	}
+	
+	// swap md2
+	md2->version = _pico_little_long( md2->version );
+
+	md2->skinWidth = _pico_little_long( md2->skinWidth );
+	md2->skinHeight = _pico_little_long( md2->skinHeight );
+	md2->frameSize = _pico_little_long( md2->frameSize );
+
+	md2->numSkins = _pico_little_long( md2->numSkins );
+	md2->numXYZ = _pico_little_long( md2->numXYZ );
+	md2->numST = _pico_little_long( md2->numST );
+	md2->numTris = _pico_little_long( md2->numTris );
+	md2->numGLCmds = _pico_little_long( md2->numGLCmds );
+	md2->numFrames = _pico_little_long( md2->numFrames );
+
+	md2->ofsSkins = _pico_little_long( md2->ofsSkins );
+	md2->ofsST = _pico_little_long( md2->ofsST );
+	md2->ofsTris = _pico_little_long( md2->ofsTris );
+	md2->ofsFrames = _pico_little_long( md2->ofsFrames );
+	md2->ofsGLCmds = _pico_little_long( md2->ofsGLCmds );
+	md2->ofsEnd = _pico_little_long( md2->ofsEnd );
+
+	// do frame check
+	if( md2->numFrames < 1 )
+	{
+		_pico_printf( PICO_ERROR, "%s has 0 frames!", fileName );
+		return NULL;
+	}
+	
+	if( frameNum < 0 || frameNum >= md2->numFrames )
+	{
+		_pico_printf( PICO_ERROR, "Invalid or out-of-range MD2 frame specified" );
+		return NULL;
+	}
+
+	// Setup Frame
+	frame = (md2Frame_t *) (bb + md2->ofsFrames + (sizeof(md2Frame_t) * frameNum));
+
+	// swap frame scale and translation
+	for( i = 0; i < 3; i++ )
+	{
+		frame->scale[ i ] = _pico_little_float( frame->scale[ i ] );
+		frame->translate[ i ] = _pico_little_float( frame->translate[ i ] );
+	}
+
+	// swap triangles
+	triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
+	for( i = 0; i < md2->numTris; i++, triangle++ )
+	{
+		for( j = 0; j < 3; j++ )
+		{
+			triangle->index_xyz[ j ] = _pico_little_short( triangle->index_xyz[ j ] );
+			triangle->index_st[ j ] = _pico_little_short( triangle->index_st[ j ] );
+		}
+	}
+
+	// swap st coords
+	texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
+	for( i = 0; i < md2->numST; i++, texCoord++ )
+	{
+		texCoord->s = _pico_little_short( texCoord->s );
+		texCoord->t = _pico_little_short( texCoord->t );
+	}
+
+	// set Skin Name
+	strncpy(skinname, (bb + md2->ofsSkins), MD2_MAX_SKINNAME );
+
+	// Print out md2 values
+	_pico_printf(PICO_VERBOSE,"Skins: %d  Verts: %d  STs: %d  Triangles: %d  Frames: %d\nSkin Name \"%s\"\n", md2->numSkins, md2->numXYZ, md2->numST, md2->numTris, md2->numFrames, &skinname );
+
+	// detox Skin name
+	_pico_setfext( skinname, "" );
+	_pico_unixify( skinname );
+
+	/* create new pico model */
+	picoModel = PicoNewModel();
+	if( picoModel == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+		return NULL;
+	}
+
+	/* do model setup */
+	PicoSetModelFrameNum( picoModel, frameNum );
+	PicoSetModelNumFrames( picoModel, md2->numFrames ); /* sea */
+	PicoSetModelName( picoModel, fileName );
+	PicoSetModelFileName( picoModel, fileName );
+
+	// allocate new pico surface
+	picoSurface = PicoNewSurface( picoModel );
+	if( picoSurface == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+		PicoFreeModel( picoModel );
+		return NULL;
+	}
+
+
+	PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+	PicoSetSurfaceName( picoSurface, frame->name );
+	picoShader = PicoNewShader( picoModel );
+	if( picoShader == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+		PicoFreeModel( picoModel );
+		return NULL;
+	}
+
+	PicoSetShaderName( picoShader, skinname );
+
+	// associate current surface with newly created shader
+	PicoSetSurfaceShader( picoSurface, picoShader );
+
+	// Init LUT for Verts
+	p_index_LUT = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t) * md2->numXYZ);
+	for(i=0; i<md2->numXYZ; i++)
+	{
+		p_index_LUT[i].Vert = -1;
+		p_index_LUT[i].ST = -1;
+		p_index_LUT[i].next = NULL;
+	}
+
+	// Fill in Look Up Table, and allocate/fill Linked List from vert array as needed for dup STs per Vert.
+	tot_numVerts = md2->numXYZ;
+	dups = 0;
+	for(i=0; i<md2->numTris; i++)
+	{
+		p_md2Triangle = (md2Triangle_t *) ( bb + md2->ofsTris + (sizeof(md2Triangle_t)*i));
+		for(j=0; j<3; j++)
+		{
+			if (p_index_LUT[p_md2Triangle->index_xyz[j]].ST == -1) // No Main Entry
+				p_index_LUT[p_md2Triangle->index_xyz[j]].ST = p_md2Triangle->index_st[j];
+
+			else if (p_md2Triangle->index_st[j] == p_index_LUT[p_md2Triangle->index_xyz[j]].ST ) // Equal to Main Entry
+				continue;
+
+			else if ( (p_index_LUT[p_md2Triangle->index_xyz[j]].next == NULL) )  // Not equal to Main entry, and no LL entry
+			{	// Add first entry of LL from Main
+				p_index_LUT2 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
+				if (p_index_LUT2 == NULL)
+					_pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
+				p_index_LUT[p_md2Triangle->index_xyz[j]].next = (index_LUT_t *)p_index_LUT2;
+				p_index_LUT2->Vert = dups;
+				p_index_LUT2->ST = p_md2Triangle->index_st[j];
+				p_index_LUT2->next = NULL;
+				p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
+				dups++;
+			}
+			else // Try to find in LL from Main Entry
+			{
+				p_index_LUT3 = p_index_LUT2 = p_index_LUT[p_md2Triangle->index_xyz[j]].next;
+				while ( (p_index_LUT2 != NULL) && (p_md2Triangle->index_xyz[j] != p_index_LUT2->Vert) ) // Walk down LL
+				{
+					p_index_LUT3 = p_index_LUT2;
+					p_index_LUT2 = p_index_LUT2->next;
+				}
+				p_index_LUT2 = p_index_LUT3;
+
+				if ( p_md2Triangle->index_st[j] == p_index_LUT2->ST ) // Found it
+				{
+					p_md2Triangle->index_xyz[j] = p_index_LUT2->Vert + md2->numXYZ; // Make change in Tri hunk
+					continue;
+				}
+
+				if ( p_index_LUT2->next == NULL)  // Didn't find it. Add entry to LL.
+				{
+					// Add the Entry
+					p_index_LUT3 = (index_LUT_t *)_pico_alloc(sizeof(index_LUT_t));
+					if (p_index_LUT3 == NULL)
+						_pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
+					p_index_LUT2->next = (index_LUT_t *)p_index_LUT3;
+					p_index_LUT3->Vert = p_md2Triangle->index_xyz[j];
+					p_index_LUT3->ST = p_md2Triangle->index_st[j];
+					p_index_LUT3->next = NULL;
+					p_md2Triangle->index_xyz[j] = dups + md2->numXYZ; // Make change in Tri hunk
+					dups++;
+				}
+			}
+		}
+	}
+
+	// malloc and build array for Dup STs
+	p_index_LUT_DUPS = (index_DUP_LUT_t *)_pico_alloc(sizeof(index_DUP_LUT_t) * dups);
+	if (p_index_LUT_DUPS == NULL)
+		_pico_printf( PICO_ERROR," Couldn't allocate memory!\n");
+
+	dup_index = 0;
+	for(i=0; i<md2->numXYZ; i++)
+	{
+		p_index_LUT2 = p_index_LUT[i].next;
+		while (p_index_LUT2 != NULL)
+		{
+			p_index_LUT_DUPS[p_index_LUT2->Vert].OldVert = i;
+			p_index_LUT_DUPS[p_index_LUT2->Vert].ST = p_index_LUT2->ST;
+			dup_index++;
+			p_index_LUT2 = p_index_LUT2->next;
+		}
+	}
+
+	// Build Picomodel
+	triangle = (md2Triangle_t *) ((picoByte_t *) (bb + md2->ofsTris) );
+	texCoord = (md2St_t*) ((picoByte_t *) (bb + md2->ofsST) );
+	vertex = (md2XyzNormal_t*) ((picoByte_t*) (frame->verts) );
+	for( j = 0; j < md2->numTris; j++, triangle++ )
+	{
+		PicoSetSurfaceIndex( picoSurface, j*3   , triangle->index_xyz[0] );
+		PicoSetSurfaceIndex( picoSurface, j*3+1 , triangle->index_xyz[1] );
+		PicoSetSurfaceIndex( picoSurface, j*3+2 , triangle->index_xyz[2] );
+	}
+
+	for(i=0; i< md2->numXYZ; i++, vertex++)
+	{
+		/* set vertex origin */
+		xyz[ 0 ] = vertex->v[0] * frame->scale[0] + frame->translate[0];
+		xyz[ 1 ] = vertex->v[1] * frame->scale[1] + frame->translate[1];
+		xyz[ 2 ] = vertex->v[2] * frame->scale[2] + frame->translate[2];
+		PicoSetSurfaceXYZ( picoSurface, i , xyz );
+
+		/* set normal */
+		normal[ 0 ] = md2_normals[vertex->lightnormalindex][0];
+		normal[ 1 ] = md2_normals[vertex->lightnormalindex][1];
+		normal[ 2 ] = md2_normals[vertex->lightnormalindex][2];
+		PicoSetSurfaceNormal( picoSurface, i , normal );
+
+		/* set st coords */
+		st[ 0 ] =  ((texCoord[p_index_LUT[i].ST].s) / ((float)md2->skinWidth));
+		st[ 1 ] =  (texCoord[p_index_LUT[i].ST].t / ((float)md2->skinHeight));
+		PicoSetSurfaceST( picoSurface, 0, i , st );
+	}
+
+	if (dups)
+	{
+		for(i=0; i<dups; i++)
+		{
+			j = p_index_LUT_DUPS[i].OldVert;
+			/* set vertex origin */
+			xyz[ 0 ] = frame->verts[j].v[0] * frame->scale[0] + frame->translate[0];
+			xyz[ 1 ] = frame->verts[j].v[1] * frame->scale[1] + frame->translate[1];
+			xyz[ 2 ] = frame->verts[j].v[2] * frame->scale[2] + frame->translate[2];
+			PicoSetSurfaceXYZ( picoSurface, i + md2->numXYZ , xyz );
+
+			/* set normal */
+			normal[ 0 ] = md2_normals[frame->verts[j].lightnormalindex][0];
+			normal[ 1 ] = md2_normals[frame->verts[j].lightnormalindex][1];
+			normal[ 2 ] = md2_normals[frame->verts[j].lightnormalindex][2];
+			PicoSetSurfaceNormal( picoSurface, i + md2->numXYZ , normal );
+
+			/* set st coords */
+			st[ 0 ] =  ((texCoord[p_index_LUT_DUPS[i].ST].s) / ((float)md2->skinWidth));
+			st[ 1 ] =  (texCoord[p_index_LUT_DUPS[i].ST].t / ((float)md2->skinHeight));
+			PicoSetSurfaceST( picoSurface, 0, i + md2->numXYZ , st );
+		}
+	}
+
+	/* set color */
+	PicoSetSurfaceColor( picoSurface, 0, 0, color );
+
+	// Free up malloc'ed LL entries
+	for(i=0; i<md2->numXYZ; i++)
+	{
+		if(p_index_LUT[i].next != NULL)
+		{
+			p_index_LUT2 = p_index_LUT[i].next;
+			do {
+				p_index_LUT3 = p_index_LUT2->next;
+				_pico_free(p_index_LUT2);
+				p_index_LUT2 = p_index_LUT3;
+				dups--;
+			} while (p_index_LUT2 != NULL);
+		}
+	}
+
+	if (dups)
+		_pico_printf(PICO_WARNING, " Not all LL mallocs freed\n");
+
+	// Free malloc'ed LUTs
+ 	_pico_free(p_index_LUT);
+	_pico_free(p_index_LUT_DUPS);
+
+	/* return the new pico model */
+	return picoModel;
+
+}
+
+
+
+/* pico file format module definition */
+const picoModule_t picoModuleMD2 =
+{
+	"0.875",						/* module version string */
+	"Quake 2 MD2",					/* module display name */
+	"Nurail",						/* author's name */
+	"2003 Nurail",					/* module copyright */
+	{
+		"md2", NULL, NULL, NULL		/* default extensions to use */
+	},
+	_md2_canload,					/* validation routine */
+	_md2_load,						/* load routine */
+	 NULL,							/* save validation routine */
+	 NULL							/* save routine */
+};
diff --git a/libs/picomodel/pm_md3.c b/libs/picomodel/pm_md3.c
index 6d87469d..55022b28 100644
--- a/libs/picomodel/pm_md3.c
+++ b/libs/picomodel/pm_md3.c
@@ -1,425 +1,425 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library 
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PM_MD3_C
-
-
-
-/* dependencies */
-#include "picointernal.h"
-
-
-
-/* md3 model format */
-#define MD3_MAGIC			"IDP3"
-#define MD3_VERSION			15
-
-/* md3 vertex scale */
-#define MD3_SCALE		  (1.0f / 64.0f)
-
-/* md3 model frame information */
-typedef struct md3Frame_s
-{
-	float		bounds[ 2 ][ 3 ];
-	float		localOrigin[ 3 ];
-	float		radius;
-	char		creator[ 16 ];
-}
-md3Frame_t;
-
-/* md3 model tag information */
-typedef struct md3Tag_s
-{
-	char		name[ 64 ];
-	float		origin[ 3 ];
-	float		axis[ 3 ][ 3 ];
-}
-md3Tag_t;
-
-/* md3 surface md3 (one object mesh) */
-typedef struct md3Surface_s
-{
-	char		magic[ 4 ];
-	char		name[ 64 ];		/* polyset name */
-	int			flags;
-	int			numFrames;		/* all model surfaces should have the same */
-	int			numShaders;		/* all model surfaces should have the same */
-	int			numVerts;
-	int			numTriangles;
-	int			ofsTriangles;
-	int			ofsShaders;		/* offset from start of md3Surface_t */
-	int			ofsSt;			/* texture coords are common for all frames */
-	int			ofsVertexes;	/* numVerts * numFrames */
-	int			ofsEnd;			/* next surface follows */
-}
-md3Surface_t;
-
-typedef struct md3Shader_s
-{
-	char		name[ 64 ];
-	int			shaderIndex;	/* for ingame use */
-}
-md3Shader_t;
-
-typedef struct md3Triangle_s
-{
-	int			indexes[ 3 ];
-}
-md3Triangle_t;
-
-typedef struct md3TexCoord_s
-{
-	float		st[ 2 ];
-}
-md3TexCoord_t;
-
-typedef struct md3Vertex_s
-{
-	short		xyz[ 3 ];
-	short		normal;
-}
-md3Vertex_t;
-
-
-/* md3 model file md3 structure */
-typedef struct md3_s
-{
-	char		magic[ 4 ];		/* MD3_MAGIC */
-	int			version;
-	char		name[ 64 ];		/* model name */
-	int			flags;
-	int			numFrames;
-	int			numTags;
-	int			numSurfaces;
-	int			numSkins;		/* number of skins for the mesh */
-	int			ofsFrames;		/* offset for first frame */
-	int			ofsTags;		/* numFrames * numTags */
-	int			ofsSurfaces;	/* first surface, others follow */
-	int			ofsEnd;			/* end of file */
-}
-md3_t;
-
-
-
-
-/*
-_md3_canload()
-validates a quake3 arena md3 model file. btw, i use the
-preceding underscore cause it's a static func referenced
-by one structure only.
-*/
-
-static int _md3_canload( PM_PARAMS_CANLOAD )
-{
-	md3_t	*md3;
-	
-
-	/* to keep the compiler happy */
-	*fileName = *fileName;
-	
-	/* sanity check */
-	if( bufSize < ( sizeof( *md3 ) * 2) )
-		return PICO_PMV_ERROR_SIZE;
-	
-	/* set as md3 */
-	md3	= (md3_t*) buffer;
-	
-	/* check md3 magic */
-	if( *((int*) md3->magic) != *((int*) MD3_MAGIC) ) 
-		return PICO_PMV_ERROR_IDENT;
-	
-	/* check md3 version */
-	if( _pico_little_long( md3->version ) != MD3_VERSION )
-		return PICO_PMV_ERROR_VERSION;
-	
-	/* file seems to be a valid md3 */
-	return PICO_PMV_OK;
-}
-
-
-
-/*
-_md3_load()
-loads a quake3 arena md3 model file.
-*/
-
-static picoModel_t *_md3_load( PM_PARAMS_LOAD )
-{
-	int				i, j;
-	picoByte_t		*bb;
-	md3_t			*md3;
-	md3Surface_t	*surface;
-	md3Shader_t		*shader;
-	md3TexCoord_t	*texCoord;
-	md3Frame_t		*frame;
-	md3Triangle_t	*triangle;
-	md3Vertex_t		*vertex;
-	double			lat, lng;
-	
-	picoModel_t		*picoModel;
-	picoSurface_t	*picoSurface;
-	picoShader_t	*picoShader;
-	picoVec3_t		xyz, normal;
-	picoVec2_t		st;
-	picoColor_t		color;
-	
-	
-	/* -------------------------------------------------
-	md3 loading
-	------------------------------------------------- */
-
-
-	/* set as md3 */
-	bb = (picoByte_t*) buffer;
-	md3	= (md3_t*) buffer;
-	
-	/* check ident and version */
-	if( *((int*) md3->magic) != *((int*) MD3_MAGIC) || _pico_little_long( md3->version ) != MD3_VERSION )
-	{
-		/* not an md3 file (todo: set error) */
-		return NULL;
-	}
-	
-	/* swap md3; sea: swaps fixed */
-	md3->version = _pico_little_long( md3->version );
-	md3->numFrames = _pico_little_long( md3->numFrames );
-	md3->numTags = _pico_little_long( md3->numTags );
-	md3->numSurfaces = _pico_little_long( md3->numSurfaces );
-	md3->numSkins = _pico_little_long( md3->numSkins );
-	md3->ofsFrames = _pico_little_long( md3->ofsFrames );
-	md3->ofsTags = _pico_little_long( md3->ofsTags );
-	md3->ofsSurfaces = _pico_little_long( md3->ofsSurfaces );
-	md3->ofsEnd = _pico_little_long( md3->ofsEnd );
-	
-	/* do frame check */
-	if( md3->numFrames < 1 )
-	{
-		_pico_printf( PICO_ERROR, "MD3 with 0 frames" );
-		return NULL;
-	}
-	
-	if( frameNum < 0 || frameNum >= md3->numFrames )
-	{
-		_pico_printf( PICO_ERROR, "Invalid or out-of-range MD3 frame specified" );
-		return NULL;
-	}
-	
-	/* swap frames */
-	frame = (md3Frame_t*) (bb + md3->ofsFrames );
-	for( i = 0; i < md3->numFrames; i++, frame++ )
-	{
-		frame->radius = _pico_little_float( frame->radius );
-		for( j = 0; j < 3; j++ )
-		{
-			frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
-			frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
-			frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
-		}
-	}
-	
-	/* swap surfaces */
-	surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
-	for( i = 0; i < md3->numSurfaces; i++ )
-	{
-		/* swap surface md3; sea: swaps fixed */
-		surface->flags = _pico_little_long( surface->flags );
-		surface->numFrames = _pico_little_long( surface->numFrames );
-		surface->numShaders = _pico_little_long( surface->numShaders );
-		surface->numTriangles = _pico_little_long( surface->numTriangles );
-		surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
-		surface->numVerts = _pico_little_long( surface->numVerts );
-		surface->ofsShaders = _pico_little_long( surface->ofsShaders );
-		surface->ofsSt = _pico_little_long( surface->ofsSt );
-		surface->ofsVertexes = _pico_little_long( surface->ofsVertexes );
-		surface->ofsEnd = _pico_little_long( surface->ofsEnd );
-		
-		/* swap triangles */
-		triangle = (md3Triangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);
-		for( j = 0; j < surface->numTriangles; j++, triangle++ )
-		{
-			/* sea: swaps fixed */
-			triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
-			triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
-			triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
-		}
-		
-		/* swap st coords */
-		texCoord = (md3TexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);
-		for( j = 0; j < surface->numVerts; j++, texCoord++ )
-		{
-			texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
-			texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
-		}
-		
-		/* swap xyz/normals */
-		vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes);
-		for( j = 0; j < (surface->numVerts * surface->numFrames); j++, vertex++)
-		{
-			vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
-			vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
-			vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
-			vertex->normal	 = _pico_little_short( vertex->normal );
-		}
-		
-		/* get next surface */
-		surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
-	}
-	
-	/* -------------------------------------------------
-	pico model creation
-	------------------------------------------------- */
-	
-	/* create new pico model */
-	picoModel = PicoNewModel();
-	if( picoModel == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
-		return NULL;
-	}
-	
-	/* do model setup */
-	PicoSetModelFrameNum( picoModel, frameNum );
-	PicoSetModelNumFrames( picoModel, md3->numFrames ); /* sea */
-	PicoSetModelName( picoModel, fileName );
-	PicoSetModelFileName( picoModel, fileName );
-	
-	/* md3 surfaces become picomodel surfaces */
-	surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
-	
-	/* run through md3 surfaces */
-	for( i = 0; i < md3->numSurfaces; i++ )
-	{
-		/* allocate new pico surface */
-		picoSurface = PicoNewSurface( picoModel );
-		if( picoSurface == NULL )
-		{
-			_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
-			PicoFreeModel( picoModel ); /* sea */
-			return NULL;
-		}
-		
-		/* md3 model surfaces are all triangle meshes */
-		PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
-		
-		/* set surface name */
-		PicoSetSurfaceName( picoSurface, surface->name );
-		
-		/* create new pico shader -sea */
-		picoShader = PicoNewShader( picoModel );
-		if( picoShader == NULL )
-		{
-			_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
-			PicoFreeModel( picoModel );
-			return NULL;
-		}
-		
-		/* detox and set shader name */
-		shader = (md3Shader_t*) ((picoByte_t*) surface + surface->ofsShaders);
-		_pico_setfext( shader->name, "" );
-		_pico_unixify( shader->name );
-		PicoSetShaderName( picoShader, shader->name );
-		
-		/* associate current surface with newly created shader */
-		PicoSetSurfaceShader( picoSurface, picoShader );
-		
-		/* copy indexes */
-		triangle = (md3Triangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);
-		
-		for( j = 0; j < surface->numTriangles; j++, triangle++ )
-		{
-			PicoSetSurfaceIndex( picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[ 0 ] );
-			PicoSetSurfaceIndex( picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[ 1 ] );
-			PicoSetSurfaceIndex( picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[ 2 ] );
-		}
-		
-		/* copy vertexes */
-		texCoord = (md3TexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);
-		vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes + surface->numVerts * frameNum * sizeof( md3Vertex_t ) );
-		_pico_set_color( color, 255, 255, 255, 255 );
-		
-		for( j = 0; j < surface->numVerts; j++, texCoord++, vertex++ )
-		{
-			/* set vertex origin */
-			xyz[ 0 ] = MD3_SCALE * vertex->xyz[ 0 ];
-			xyz[ 1 ] = MD3_SCALE * vertex->xyz[ 1 ];
-			xyz[ 2 ] = MD3_SCALE * vertex->xyz[ 2 ];
-			PicoSetSurfaceXYZ( picoSurface, j, xyz );
-			
-			/* decode lat/lng normal to 3 float normal */
-			lat = (float) ((vertex->normal >> 8) & 0xff);
-			lng = (float) (vertex->normal & 0xff);
-			lat *= PICO_PI / 128;
-			lng *= PICO_PI / 128;
-			normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
-			normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
-			normal[ 2 ] = (picoVec_t) cos( lng );
-			PicoSetSurfaceNormal( picoSurface, j, normal );
-			
-			/* set st coords */
-			st[ 0 ] = texCoord->st[ 0 ];
-			st[ 1 ] = texCoord->st[ 1 ];
-			PicoSetSurfaceST( picoSurface, 0, j, st );
-
-			/* set color */
-			PicoSetSurfaceColor( picoSurface, 0, j, color );
-		}
-		
-		/* get next surface */
-		surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
-	}
-	
-	/* return the new pico model */
-	return picoModel;
-}
-
-
-
-/* pico file format module definition */
-const picoModule_t picoModuleMD3 =
-{
-	"1.3",						/* module version string */
-	"Quake 3 Arena",			/* module display name */
-	"Randy Reddig",				/* author's name */
-	"2002 Randy Reddig",		/* module copyright */
-	{
-		"md3", NULL, NULL, NULL	/* default extensions to use */
-	},
-	_md3_canload,				/* validation routine */
-	_md3_load,					/* load routine */
-	 NULL,						/* save validation routine */
-	 NULL						/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library 
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PM_MD3_C
+
+
+
+/* dependencies */
+#include "picointernal.h"
+
+
+
+/* md3 model format */
+#define MD3_MAGIC			"IDP3"
+#define MD3_VERSION			15
+
+/* md3 vertex scale */
+#define MD3_SCALE		  (1.0f / 64.0f)
+
+/* md3 model frame information */
+typedef struct md3Frame_s
+{
+	float		bounds[ 2 ][ 3 ];
+	float		localOrigin[ 3 ];
+	float		radius;
+	char		creator[ 16 ];
+}
+md3Frame_t;
+
+/* md3 model tag information */
+typedef struct md3Tag_s
+{
+	char		name[ 64 ];
+	float		origin[ 3 ];
+	float		axis[ 3 ][ 3 ];
+}
+md3Tag_t;
+
+/* md3 surface md3 (one object mesh) */
+typedef struct md3Surface_s
+{
+	char		magic[ 4 ];
+	char		name[ 64 ];		/* polyset name */
+	int			flags;
+	int			numFrames;		/* all model surfaces should have the same */
+	int			numShaders;		/* all model surfaces should have the same */
+	int			numVerts;
+	int			numTriangles;
+	int			ofsTriangles;
+	int			ofsShaders;		/* offset from start of md3Surface_t */
+	int			ofsSt;			/* texture coords are common for all frames */
+	int			ofsVertexes;	/* numVerts * numFrames */
+	int			ofsEnd;			/* next surface follows */
+}
+md3Surface_t;
+
+typedef struct md3Shader_s
+{
+	char		name[ 64 ];
+	int			shaderIndex;	/* for ingame use */
+}
+md3Shader_t;
+
+typedef struct md3Triangle_s
+{
+	int			indexes[ 3 ];
+}
+md3Triangle_t;
+
+typedef struct md3TexCoord_s
+{
+	float		st[ 2 ];
+}
+md3TexCoord_t;
+
+typedef struct md3Vertex_s
+{
+	short		xyz[ 3 ];
+	short		normal;
+}
+md3Vertex_t;
+
+
+/* md3 model file md3 structure */
+typedef struct md3_s
+{
+	char		magic[ 4 ];		/* MD3_MAGIC */
+	int			version;
+	char		name[ 64 ];		/* model name */
+	int			flags;
+	int			numFrames;
+	int			numTags;
+	int			numSurfaces;
+	int			numSkins;		/* number of skins for the mesh */
+	int			ofsFrames;		/* offset for first frame */
+	int			ofsTags;		/* numFrames * numTags */
+	int			ofsSurfaces;	/* first surface, others follow */
+	int			ofsEnd;			/* end of file */
+}
+md3_t;
+
+
+
+
+/*
+_md3_canload()
+validates a quake3 arena md3 model file. btw, i use the
+preceding underscore cause it's a static func referenced
+by one structure only.
+*/
+
+static int _md3_canload( PM_PARAMS_CANLOAD )
+{
+	md3_t	*md3;
+	
+
+	/* to keep the compiler happy */
+	*fileName = *fileName;
+	
+	/* sanity check */
+	if( bufSize < ( sizeof( *md3 ) * 2) )
+		return PICO_PMV_ERROR_SIZE;
+	
+	/* set as md3 */
+	md3	= (md3_t*) buffer;
+	
+	/* check md3 magic */
+	if( *((int*) md3->magic) != *((int*) MD3_MAGIC) ) 
+		return PICO_PMV_ERROR_IDENT;
+	
+	/* check md3 version */
+	if( _pico_little_long( md3->version ) != MD3_VERSION )
+		return PICO_PMV_ERROR_VERSION;
+	
+	/* file seems to be a valid md3 */
+	return PICO_PMV_OK;
+}
+
+
+
+/*
+_md3_load()
+loads a quake3 arena md3 model file.
+*/
+
+static picoModel_t *_md3_load( PM_PARAMS_LOAD )
+{
+	int				i, j;
+	picoByte_t		*bb;
+	md3_t			*md3;
+	md3Surface_t	*surface;
+	md3Shader_t		*shader;
+	md3TexCoord_t	*texCoord;
+	md3Frame_t		*frame;
+	md3Triangle_t	*triangle;
+	md3Vertex_t		*vertex;
+	double			lat, lng;
+	
+	picoModel_t		*picoModel;
+	picoSurface_t	*picoSurface;
+	picoShader_t	*picoShader;
+	picoVec3_t		xyz, normal;
+	picoVec2_t		st;
+	picoColor_t		color;
+	
+	
+	/* -------------------------------------------------
+	md3 loading
+	------------------------------------------------- */
+
+
+	/* set as md3 */
+	bb = (picoByte_t*) buffer;
+	md3	= (md3_t*) buffer;
+	
+	/* check ident and version */
+	if( *((int*) md3->magic) != *((int*) MD3_MAGIC) || _pico_little_long( md3->version ) != MD3_VERSION )
+	{
+		/* not an md3 file (todo: set error) */
+		return NULL;
+	}
+	
+	/* swap md3; sea: swaps fixed */
+	md3->version = _pico_little_long( md3->version );
+	md3->numFrames = _pico_little_long( md3->numFrames );
+	md3->numTags = _pico_little_long( md3->numTags );
+	md3->numSurfaces = _pico_little_long( md3->numSurfaces );
+	md3->numSkins = _pico_little_long( md3->numSkins );
+	md3->ofsFrames = _pico_little_long( md3->ofsFrames );
+	md3->ofsTags = _pico_little_long( md3->ofsTags );
+	md3->ofsSurfaces = _pico_little_long( md3->ofsSurfaces );
+	md3->ofsEnd = _pico_little_long( md3->ofsEnd );
+	
+	/* do frame check */
+	if( md3->numFrames < 1 )
+	{
+		_pico_printf( PICO_ERROR, "MD3 with 0 frames" );
+		return NULL;
+	}
+	
+	if( frameNum < 0 || frameNum >= md3->numFrames )
+	{
+		_pico_printf( PICO_ERROR, "Invalid or out-of-range MD3 frame specified" );
+		return NULL;
+	}
+	
+	/* swap frames */
+	frame = (md3Frame_t*) (bb + md3->ofsFrames );
+	for( i = 0; i < md3->numFrames; i++, frame++ )
+	{
+		frame->radius = _pico_little_float( frame->radius );
+		for( j = 0; j < 3; j++ )
+		{
+			frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
+			frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
+			frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
+		}
+	}
+	
+	/* swap surfaces */
+	surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
+	for( i = 0; i < md3->numSurfaces; i++ )
+	{
+		/* swap surface md3; sea: swaps fixed */
+		surface->flags = _pico_little_long( surface->flags );
+		surface->numFrames = _pico_little_long( surface->numFrames );
+		surface->numShaders = _pico_little_long( surface->numShaders );
+		surface->numTriangles = _pico_little_long( surface->numTriangles );
+		surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
+		surface->numVerts = _pico_little_long( surface->numVerts );
+		surface->ofsShaders = _pico_little_long( surface->ofsShaders );
+		surface->ofsSt = _pico_little_long( surface->ofsSt );
+		surface->ofsVertexes = _pico_little_long( surface->ofsVertexes );
+		surface->ofsEnd = _pico_little_long( surface->ofsEnd );
+		
+		/* swap triangles */
+		triangle = (md3Triangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);
+		for( j = 0; j < surface->numTriangles; j++, triangle++ )
+		{
+			/* sea: swaps fixed */
+			triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
+			triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
+			triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
+		}
+		
+		/* swap st coords */
+		texCoord = (md3TexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);
+		for( j = 0; j < surface->numVerts; j++, texCoord++ )
+		{
+			texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
+			texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
+		}
+		
+		/* swap xyz/normals */
+		vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes);
+		for( j = 0; j < (surface->numVerts * surface->numFrames); j++, vertex++)
+		{
+			vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
+			vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
+			vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
+			vertex->normal	 = _pico_little_short( vertex->normal );
+		}
+		
+		/* get next surface */
+		surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
+	}
+	
+	/* -------------------------------------------------
+	pico model creation
+	------------------------------------------------- */
+	
+	/* create new pico model */
+	picoModel = PicoNewModel();
+	if( picoModel == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+		return NULL;
+	}
+	
+	/* do model setup */
+	PicoSetModelFrameNum( picoModel, frameNum );
+	PicoSetModelNumFrames( picoModel, md3->numFrames ); /* sea */
+	PicoSetModelName( picoModel, fileName );
+	PicoSetModelFileName( picoModel, fileName );
+	
+	/* md3 surfaces become picomodel surfaces */
+	surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
+	
+	/* run through md3 surfaces */
+	for( i = 0; i < md3->numSurfaces; i++ )
+	{
+		/* allocate new pico surface */
+		picoSurface = PicoNewSurface( picoModel );
+		if( picoSurface == NULL )
+		{
+			_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+			PicoFreeModel( picoModel ); /* sea */
+			return NULL;
+		}
+		
+		/* md3 model surfaces are all triangle meshes */
+		PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+		
+		/* set surface name */
+		PicoSetSurfaceName( picoSurface, surface->name );
+		
+		/* create new pico shader -sea */
+		picoShader = PicoNewShader( picoModel );
+		if( picoShader == NULL )
+		{
+			_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+			PicoFreeModel( picoModel );
+			return NULL;
+		}
+		
+		/* detox and set shader name */
+		shader = (md3Shader_t*) ((picoByte_t*) surface + surface->ofsShaders);
+		_pico_setfext( shader->name, "" );
+		_pico_unixify( shader->name );
+		PicoSetShaderName( picoShader, shader->name );
+		
+		/* associate current surface with newly created shader */
+		PicoSetSurfaceShader( picoSurface, picoShader );
+		
+		/* copy indexes */
+		triangle = (md3Triangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);
+		
+		for( j = 0; j < surface->numTriangles; j++, triangle++ )
+		{
+			PicoSetSurfaceIndex( picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[ 0 ] );
+			PicoSetSurfaceIndex( picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[ 1 ] );
+			PicoSetSurfaceIndex( picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[ 2 ] );
+		}
+		
+		/* copy vertexes */
+		texCoord = (md3TexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);
+		vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes + surface->numVerts * frameNum * sizeof( md3Vertex_t ) );
+		_pico_set_color( color, 255, 255, 255, 255 );
+		
+		for( j = 0; j < surface->numVerts; j++, texCoord++, vertex++ )
+		{
+			/* set vertex origin */
+			xyz[ 0 ] = MD3_SCALE * vertex->xyz[ 0 ];
+			xyz[ 1 ] = MD3_SCALE * vertex->xyz[ 1 ];
+			xyz[ 2 ] = MD3_SCALE * vertex->xyz[ 2 ];
+			PicoSetSurfaceXYZ( picoSurface, j, xyz );
+			
+			/* decode lat/lng normal to 3 float normal */
+			lat = (float) ((vertex->normal >> 8) & 0xff);
+			lng = (float) (vertex->normal & 0xff);
+			lat *= PICO_PI / 128;
+			lng *= PICO_PI / 128;
+			normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
+			normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
+			normal[ 2 ] = (picoVec_t) cos( lng );
+			PicoSetSurfaceNormal( picoSurface, j, normal );
+			
+			/* set st coords */
+			st[ 0 ] = texCoord->st[ 0 ];
+			st[ 1 ] = texCoord->st[ 1 ];
+			PicoSetSurfaceST( picoSurface, 0, j, st );
+
+			/* set color */
+			PicoSetSurfaceColor( picoSurface, 0, j, color );
+		}
+		
+		/* get next surface */
+		surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
+	}
+	
+	/* return the new pico model */
+	return picoModel;
+}
+
+
+
+/* pico file format module definition */
+const picoModule_t picoModuleMD3 =
+{
+	"1.3",						/* module version string */
+	"Quake 3 Arena",			/* module display name */
+	"Randy Reddig",				/* author's name */
+	"2002 Randy Reddig",		/* module copyright */
+	{
+		"md3", NULL, NULL, NULL	/* default extensions to use */
+	},
+	_md3_canload,				/* validation routine */
+	_md3_load,					/* load routine */
+	 NULL,						/* save validation routine */
+	 NULL						/* save routine */
+};
diff --git a/libs/picomodel/pm_mdc.c b/libs/picomodel/pm_mdc.c
index 3036d112..27e612e8 100644
--- a/libs/picomodel/pm_mdc.c
+++ b/libs/picomodel/pm_mdc.c
@@ -1,750 +1,750 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library 
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PM_MDC_C
-
-
-
-/* dependencies */
-#include "picointernal.h"
-
-/* mdc model format */
-#define MDC_MAGIC			"IDPC"
-#define MDC_VERSION			2
-
-/* mdc vertex scale */
-#define MDC_SCALE			(1.0f / 64.0f)
-#define	MDC_MAX_OFS			127.0f
-#define	MDC_DIST_SCALE		0.05f
-
-/* mdc decoding normal table */
-double mdcNormals[ 256 ][ 3 ] =
-{
-	{ 1.000000, 0.000000, 0.000000 },
-	{ 0.980785, 0.195090, 0.000000 },
-	{ 0.923880, 0.382683, 0.000000 },
-	{ 0.831470, 0.555570, 0.000000 },
-	{ 0.707107, 0.707107, 0.000000 },
-	{ 0.555570, 0.831470, 0.000000 },
-	{ 0.382683, 0.923880, 0.000000 },
-	{ 0.195090, 0.980785, 0.000000 },
-	{ -0.000000, 1.000000, 0.000000 },
-	{ -0.195090, 0.980785, 0.000000 },
-	{ -0.382683, 0.923880, 0.000000 },
-	{ -0.555570, 0.831470, 0.000000 },
-	{ -0.707107, 0.707107, 0.000000 },
-	{ -0.831470, 0.555570, 0.000000 },
-	{ -0.923880, 0.382683, 0.000000 },
-	{ -0.980785, 0.195090, 0.000000 },
-	{ -1.000000, -0.000000, 0.000000 },
-	{ -0.980785, -0.195090, 0.000000 },
-	{ -0.923880, -0.382683, 0.000000 },
-	{ -0.831470, -0.555570, 0.000000 },
-	{ -0.707107, -0.707107, 0.000000 },
-	{ -0.555570, -0.831469, 0.000000 },
-	{ -0.382684, -0.923880, 0.000000 },
-	{ -0.195090, -0.980785, 0.000000 },
-	{ 0.000000, -1.000000, 0.000000 },
-	{ 0.195090, -0.980785, 0.000000 },
-	{ 0.382684, -0.923879, 0.000000 },
-	{ 0.555570, -0.831470, 0.000000 },
-	{ 0.707107, -0.707107, 0.000000 },
-	{ 0.831470, -0.555570, 0.000000 },
-	{ 0.923880, -0.382683, 0.000000 },
-	{ 0.980785, -0.195090, 0.000000 },
-	{ 0.980785, 0.000000, -0.195090 },
-	{ 0.956195, 0.218245, -0.195090 },
-	{ 0.883657, 0.425547, -0.195090 },
-	{ 0.766809, 0.611510, -0.195090 },
-	{ 0.611510, 0.766809, -0.195090 },
-	{ 0.425547, 0.883657, -0.195090 },
-	{ 0.218245, 0.956195, -0.195090 },
-	{ -0.000000, 0.980785, -0.195090 },
-	{ -0.218245, 0.956195, -0.195090 },
-	{ -0.425547, 0.883657, -0.195090 },
-	{ -0.611510, 0.766809, -0.195090 },
-	{ -0.766809, 0.611510, -0.195090 },
-	{ -0.883657, 0.425547, -0.195090 },
-	{ -0.956195, 0.218245, -0.195090 },
-	{ -0.980785, -0.000000, -0.195090 },
-	{ -0.956195, -0.218245, -0.195090 },
-	{ -0.883657, -0.425547, -0.195090 },
-	{ -0.766809, -0.611510, -0.195090 },
-	{ -0.611510, -0.766809, -0.195090 },
-	{ -0.425547, -0.883657, -0.195090 },
-	{ -0.218245, -0.956195, -0.195090 },
-	{ 0.000000, -0.980785, -0.195090 },
-	{ 0.218245, -0.956195, -0.195090 },
-	{ 0.425547, -0.883657, -0.195090 },
-	{ 0.611510, -0.766809, -0.195090 },
-	{ 0.766809, -0.611510, -0.195090 },
-	{ 0.883657, -0.425547, -0.195090 },
-	{ 0.956195, -0.218245, -0.195090 },
-	{ 0.923880, 0.000000, -0.382683 },
-	{ 0.892399, 0.239118, -0.382683 },
-	{ 0.800103, 0.461940, -0.382683 },
-	{ 0.653281, 0.653281, -0.382683 },
-	{ 0.461940, 0.800103, -0.382683 },
-	{ 0.239118, 0.892399, -0.382683 },
-	{ -0.000000, 0.923880, -0.382683 },
-	{ -0.239118, 0.892399, -0.382683 },
-	{ -0.461940, 0.800103, -0.382683 },
-	{ -0.653281, 0.653281, -0.382683 },
-	{ -0.800103, 0.461940, -0.382683 },
-	{ -0.892399, 0.239118, -0.382683 },
-	{ -0.923880, -0.000000, -0.382683 },
-	{ -0.892399, -0.239118, -0.382683 },
-	{ -0.800103, -0.461940, -0.382683 },
-	{ -0.653282, -0.653281, -0.382683 },
-	{ -0.461940, -0.800103, -0.382683 },
-	{ -0.239118, -0.892399, -0.382683 },
-	{ 0.000000, -0.923880, -0.382683 },
-	{ 0.239118, -0.892399, -0.382683 },
-	{ 0.461940, -0.800103, -0.382683 },
-	{ 0.653281, -0.653282, -0.382683 },
-	{ 0.800103, -0.461940, -0.382683 },
-	{ 0.892399, -0.239117, -0.382683 },
-	{ 0.831470, 0.000000, -0.555570 },
-	{ 0.790775, 0.256938, -0.555570 },
-	{ 0.672673, 0.488726, -0.555570 },
-	{ 0.488726, 0.672673, -0.555570 },
-	{ 0.256938, 0.790775, -0.555570 },
-	{ -0.000000, 0.831470, -0.555570 },
-	{ -0.256938, 0.790775, -0.555570 },
-	{ -0.488726, 0.672673, -0.555570 },
-	{ -0.672673, 0.488726, -0.555570 },
-	{ -0.790775, 0.256938, -0.555570 },
-	{ -0.831470, -0.000000, -0.555570 },
-	{ -0.790775, -0.256938, -0.555570 },
-	{ -0.672673, -0.488726, -0.555570 },
-	{ -0.488725, -0.672673, -0.555570 },
-	{ -0.256938, -0.790775, -0.555570 },
-	{ 0.000000, -0.831470, -0.555570 },
-	{ 0.256938, -0.790775, -0.555570 },
-	{ 0.488725, -0.672673, -0.555570 },
-	{ 0.672673, -0.488726, -0.555570 },
-	{ 0.790775, -0.256938, -0.555570 },
-	{ 0.707107, 0.000000, -0.707107 },
-	{ 0.653281, 0.270598, -0.707107 },
-	{ 0.500000, 0.500000, -0.707107 },
-	{ 0.270598, 0.653281, -0.707107 },
-	{ -0.000000, 0.707107, -0.707107 },
-	{ -0.270598, 0.653282, -0.707107 },
-	{ -0.500000, 0.500000, -0.707107 },
-	{ -0.653281, 0.270598, -0.707107 },
-	{ -0.707107, -0.000000, -0.707107 },
-	{ -0.653281, -0.270598, -0.707107 },
-	{ -0.500000, -0.500000, -0.707107 },
-	{ -0.270598, -0.653281, -0.707107 },
-	{ 0.000000, -0.707107, -0.707107 },
-	{ 0.270598, -0.653281, -0.707107 },
-	{ 0.500000, -0.500000, -0.707107 },
-	{ 0.653282, -0.270598, -0.707107 },
-	{ 0.555570, 0.000000, -0.831470 },
-	{ 0.481138, 0.277785, -0.831470 },
-	{ 0.277785, 0.481138, -0.831470 },
-	{ -0.000000, 0.555570, -0.831470 },
-	{ -0.277785, 0.481138, -0.831470 },
-	{ -0.481138, 0.277785, -0.831470 },
-	{ -0.555570, -0.000000, -0.831470 },
-	{ -0.481138, -0.277785, -0.831470 },
-	{ -0.277785, -0.481138, -0.831470 },
-	{ 0.000000, -0.555570, -0.831470 },
-	{ 0.277785, -0.481138, -0.831470 },
-	{ 0.481138, -0.277785, -0.831470 },
-	{ 0.382683, 0.000000, -0.923880 },
-	{ 0.270598, 0.270598, -0.923880 },
-	{ -0.000000, 0.382683, -0.923880 },
-	{ -0.270598, 0.270598, -0.923880 },
-	{ -0.382683, -0.000000, -0.923880 },
-	{ -0.270598, -0.270598, -0.923880 },
-	{ 0.000000, -0.382683, -0.923880 },
-	{ 0.270598, -0.270598, -0.923880 },
-	{ 0.195090, 0.000000, -0.980785 },
-	{ -0.000000, 0.195090, -0.980785 },
-	{ -0.195090, -0.000000, -0.980785 },
-	{ 0.000000, -0.195090, -0.980785 },
-	{ 0.980785, 0.000000, 0.195090 },
-	{ 0.956195, 0.218245, 0.195090 },
-	{ 0.883657, 0.425547, 0.195090 },
-	{ 0.766809, 0.611510, 0.195090 },
-	{ 0.611510, 0.766809, 0.195090 },
-	{ 0.425547, 0.883657, 0.195090 },
-	{ 0.218245, 0.956195, 0.195090 },
-	{ -0.000000, 0.980785, 0.195090 },
-	{ -0.218245, 0.956195, 0.195090 },
-	{ -0.425547, 0.883657, 0.195090 },
-	{ -0.611510, 0.766809, 0.195090 },
-	{ -0.766809, 0.611510, 0.195090 },
-	{ -0.883657, 0.425547, 0.195090 },
-	{ -0.956195, 0.218245, 0.195090 },
-	{ -0.980785, -0.000000, 0.195090 },
-	{ -0.956195, -0.218245, 0.195090 },
-	{ -0.883657, -0.425547, 0.195090 },
-	{ -0.766809, -0.611510, 0.195090 },
-	{ -0.611510, -0.766809, 0.195090 },
-	{ -0.425547, -0.883657, 0.195090 },
-	{ -0.218245, -0.956195, 0.195090 },
-	{ 0.000000, -0.980785, 0.195090 },
-	{ 0.218245, -0.956195, 0.195090 },
-	{ 0.425547, -0.883657, 0.195090 },
-	{ 0.611510, -0.766809, 0.195090 },
-	{ 0.766809, -0.611510, 0.195090 },
-	{ 0.883657, -0.425547, 0.195090 },
-	{ 0.956195, -0.218245, 0.195090 },
-	{ 0.923880, 0.000000, 0.382683 },
-	{ 0.892399, 0.239118, 0.382683 },
-	{ 0.800103, 0.461940, 0.382683 },
-	{ 0.653281, 0.653281, 0.382683 },
-	{ 0.461940, 0.800103, 0.382683 },
-	{ 0.239118, 0.892399, 0.382683 },
-	{ -0.000000, 0.923880, 0.382683 },
-	{ -0.239118, 0.892399, 0.382683 },
-	{ -0.461940, 0.800103, 0.382683 },
-	{ -0.653281, 0.653281, 0.382683 },
-	{ -0.800103, 0.461940, 0.382683 },
-	{ -0.892399, 0.239118, 0.382683 },
-	{ -0.923880, -0.000000, 0.382683 },
-	{ -0.892399, -0.239118, 0.382683 },
-	{ -0.800103, -0.461940, 0.382683 },
-	{ -0.653282, -0.653281, 0.382683 },
-	{ -0.461940, -0.800103, 0.382683 },
-	{ -0.239118, -0.892399, 0.382683 },
-	{ 0.000000, -0.923880, 0.382683 },
-	{ 0.239118, -0.892399, 0.382683 },
-	{ 0.461940, -0.800103, 0.382683 },
-	{ 0.653281, -0.653282, 0.382683 },
-	{ 0.800103, -0.461940, 0.382683 },
-	{ 0.892399, -0.239117, 0.382683 },
-	{ 0.831470, 0.000000, 0.555570 },
-	{ 0.790775, 0.256938, 0.555570 },
-	{ 0.672673, 0.488726, 0.555570 },
-	{ 0.488726, 0.672673, 0.555570 },
-	{ 0.256938, 0.790775, 0.555570 },
-	{ -0.000000, 0.831470, 0.555570 },
-	{ -0.256938, 0.790775, 0.555570 },
-	{ -0.488726, 0.672673, 0.555570 },
-	{ -0.672673, 0.488726, 0.555570 },
-	{ -0.790775, 0.256938, 0.555570 },
-	{ -0.831470, -0.000000, 0.555570 },
-	{ -0.790775, -0.256938, 0.555570 },
-	{ -0.672673, -0.488726, 0.555570 },
-	{ -0.488725, -0.672673, 0.555570 },
-	{ -0.256938, -0.790775, 0.555570 },
-	{ 0.000000, -0.831470, 0.555570 },
-	{ 0.256938, -0.790775, 0.555570 },
-	{ 0.488725, -0.672673, 0.555570 },
-	{ 0.672673, -0.488726, 0.555570 },
-	{ 0.790775, -0.256938, 0.555570 },
-	{ 0.707107, 0.000000, 0.707107 },
-	{ 0.653281, 0.270598, 0.707107 },
-	{ 0.500000, 0.500000, 0.707107 },
-	{ 0.270598, 0.653281, 0.707107 },
-	{ -0.000000, 0.707107, 0.707107 },
-	{ -0.270598, 0.653282, 0.707107 },
-	{ -0.500000, 0.500000, 0.707107 },
-	{ -0.653281, 0.270598, 0.707107 },
-	{ -0.707107, -0.000000, 0.707107 },
-	{ -0.653281, -0.270598, 0.707107 },
-	{ -0.500000, -0.500000, 0.707107 },
-	{ -0.270598, -0.653281, 0.707107 },
-	{ 0.000000, -0.707107, 0.707107 },
-	{ 0.270598, -0.653281, 0.707107 },
-	{ 0.500000, -0.500000, 0.707107 },
-	{ 0.653282, -0.270598, 0.707107 },
-	{ 0.555570, 0.000000, 0.831470 },
-	{ 0.481138, 0.277785, 0.831470 },
-	{ 0.277785, 0.481138, 0.831470 },
-	{ -0.000000, 0.555570, 0.831470 },
-	{ -0.277785, 0.481138, 0.831470 },
-	{ -0.481138, 0.277785, 0.831470 },
-	{ -0.555570, -0.000000, 0.831470 },
-	{ -0.481138, -0.277785, 0.831470 },
-	{ -0.277785, -0.481138, 0.831470 },
-	{ 0.000000, -0.555570, 0.831470 },
-	{ 0.277785, -0.481138, 0.831470 },
-	{ 0.481138, -0.277785, 0.831470 },
-	{ 0.382683, 0.000000, 0.923880 },
-	{ 0.270598, 0.270598, 0.923880 },
-	{ -0.000000, 0.382683, 0.923880 },
-	{ -0.270598, 0.270598, 0.923880 },
-	{ -0.382683, -0.000000, 0.923880 },
-	{ -0.270598, -0.270598, 0.923880 },
-	{ 0.000000, -0.382683, 0.923880 },
-	{ 0.270598, -0.270598, 0.923880 },
-	{ 0.195090, 0.000000, 0.980785 },
-	{ -0.000000, 0.195090, 0.980785 },
-	{ -0.195090, -0.000000, 0.980785 },
-	{ 0.000000, -0.195090, 0.980785 }
-};
-
-/* mdc model frame information */
-typedef struct mdcFrame_s
-{
-	float		bounds[ 2 ][ 3 ];
-	float		localOrigin[ 3 ];
-	float		radius;
-	char		creator[ 16 ];
-}
-mdcFrame_t;
-
-/* mdc model tag information */
-typedef struct mdcTag_s
-{
-	short		xyz[3];
-	short		angles[3];
-}
-mdcTag_t;
-
-/* mdc surface mdc (one object mesh) */
-typedef struct mdcSurface_s
-{
-	char		magic[ 4 ];
-	char		name[ 64 ];			/* polyset name */
-	int			flags;
-	int			numCompFrames;		/* all surfaces in a model should have the same */
-	int			numBaseFrames;		/* ditto */
-	int			numShaders;			/* all model surfaces should have the same */
-	int			numVerts;
-	int			numTriangles;
-	int			ofsTriangles;
-	int			ofsShaders;			/* offset from start of mdcSurface_t */
-	int			ofsSt;				/* texture coords are common for all frames */
-	int			ofsXyzNormals;		/* numVerts * numBaseFrames */
-	int			ofsXyzCompressed;	/* numVerts * numCompFrames */
-
-	int			ofsFrameBaseFrames;	/* numFrames */
-	int			ofsFrameCompFrames;	/* numFrames */
-	int			ofsEnd;				/* next surface follows */
-}
-mdcSurface_t;
-
-typedef struct mdcShader_s
-{
-	char		name[ 64 ];
-	int			shaderIndex;	/* for ingame use */
-}
-mdcShader_t;
-
-typedef struct mdcTriangle_s
-{
-	int			indexes[ 3 ];
-}
-mdcTriangle_t;
-
-typedef struct mdcTexCoord_s
-{
-	float		st[ 2 ];
-}
-mdcTexCoord_t;
-
-typedef struct mdcVertex_s
-{
-	short		xyz[ 3 ];
-	short		normal;
-}
-mdcVertex_t;
-
-typedef struct mdcXyzCompressed_s
-{
-	unsigned int	ofsVec;		/* offset direction from the last base frame */
-}
-mdcXyzCompressed_t;
-
-
-/* mdc model file mdc structure */
-typedef struct mdc_s
-{
-	char		magic[ 4 ];		/* MDC_MAGIC */
-	int			version;
-	char		name[ 64 ];		/* model name */
-	int			flags;
-	int			numFrames;
-	int			numTags;
-	int			numSurfaces;
-	int			numSkins;		/* number of skins for the mesh */
-	int			ofsFrames;		/* offset for first frame */
-	int			ofsTagNames;	/* numTags */
-	int			ofsTags;		/* numFrames * numTags */
-	int			ofsSurfaces;	/* first surface, others follow */
-	int			ofsEnd;			/* end of file */
-}
-mdc_t;
-
-
-
-
-/*
-_mdc_canload()
-validates a Return to Castle Wolfenstein model file. btw, i use the
-preceding underscore cause it's a static func referenced
-by one structure only.
-*/
-
-static int _mdc_canload( PM_PARAMS_CANLOAD )
-{
-	mdc_t	*mdc;
-	
-
-	/* to keep the compiler happy */
-	*fileName = *fileName;
-	
-	/* sanity check */
-	if( bufSize < ( sizeof( *mdc ) * 2) )
-		return PICO_PMV_ERROR_SIZE;
-	
-	/* set as mdc */
-	mdc	= (mdc_t*) buffer;
-	
-	/* check mdc magic */
-	if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) ) 
-		return PICO_PMV_ERROR_IDENT;
-	
-	/* check mdc version */
-	if( _pico_little_long( mdc->version ) != MDC_VERSION )
-		return PICO_PMV_ERROR_VERSION;
-	
-	/* file seems to be a valid mdc */
-	return PICO_PMV_OK;
-}
-
-
-
-/*
-_mdc_load()
-loads a Return to Castle Wolfenstein mdc model file.
-*/
-
-static picoModel_t *_mdc_load( PM_PARAMS_LOAD )
-{
-	int					i, j;
-	picoByte_t			*bb;
-	mdc_t				*mdc;
-	mdcSurface_t		*surface;
-	mdcShader_t			*shader;
-	mdcTexCoord_t		*texCoord;
-	mdcFrame_t			*frame;
-	mdcTriangle_t		*triangle;
-	mdcVertex_t			*vertex;
-	mdcXyzCompressed_t	*vertexComp;
-	short				*mdcShort, *mdcCompVert;
-	double				lat, lng;
-	
-	picoModel_t			*picoModel;
-	picoSurface_t		*picoSurface;
-	picoShader_t		*picoShader;
-	picoVec3_t			xyz, normal;
-	picoVec2_t			st;
-	picoColor_t			color;
-	
-	
-	/* -------------------------------------------------
-	mdc loading
-	------------------------------------------------- */
-
-
-	/* set as mdc */
-	bb = (picoByte_t*) buffer;
-	mdc	= (mdc_t*) buffer;
-	
-	/* check ident and version */
-	if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) || _pico_little_long( mdc->version ) != MDC_VERSION )
-	{
-		/* not an mdc file (todo: set error) */
-		return NULL;
-	}
-	
-	/* swap mdc */
-	mdc->version = _pico_little_long( mdc->version );
-	mdc->numFrames = _pico_little_long( mdc->numFrames );
-	mdc->numTags = _pico_little_long( mdc->numTags );
-	mdc->numSurfaces = _pico_little_long( mdc->numSurfaces );
-	mdc->numSkins = _pico_little_long( mdc->numSkins );
-	mdc->ofsFrames = _pico_little_long( mdc->ofsFrames );
-	mdc->ofsTags = _pico_little_long( mdc->ofsTags );
-	mdc->ofsTagNames = _pico_little_long( mdc->ofsTagNames );
-	mdc->ofsSurfaces = _pico_little_long( mdc->ofsSurfaces );
-	mdc->ofsEnd = _pico_little_long( mdc->ofsEnd );
-	
-	/* do frame check */
-	if( mdc->numFrames < 1 )
-	{
-		_pico_printf( PICO_ERROR, "MDC with 0 frames" );
-		return NULL;
-	}
-	
-	if( frameNum < 0 || frameNum >= mdc->numFrames )
-	{
-		_pico_printf( PICO_ERROR, "Invalid or out-of-range MDC frame specified" );
-		return NULL;
-	}
-	
-	/* swap frames */
-	frame = (mdcFrame_t*) (bb + mdc->ofsFrames );
-	for( i = 0; i < mdc->numFrames; i++, frame++ )
-	{
-		frame->radius = _pico_little_float( frame->radius );
-		for( j = 0; j < 3; j++ )
-		{
-			frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
-			frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
-			frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
-		}
-	}
-	
-	/* swap surfaces */
-	surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);
-	for( i = 0; i < mdc->numSurfaces; i++ )
-	{
-		/* swap surface mdc */
-		surface->flags = _pico_little_long( surface->flags );
-		surface->numBaseFrames = _pico_little_long( surface->numBaseFrames );
-		surface->numCompFrames = _pico_little_long( surface->numCompFrames );
-		surface->numShaders = _pico_little_long( surface->numShaders );
-		surface->numTriangles = _pico_little_long( surface->numTriangles );
-		surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
-		surface->numVerts = _pico_little_long( surface->numVerts );
-		surface->ofsShaders = _pico_little_long( surface->ofsShaders );
-		surface->ofsSt = _pico_little_long( surface->ofsSt );
-		surface->ofsXyzNormals = _pico_little_long( surface->ofsXyzNormals );
-		surface->ofsXyzCompressed = _pico_little_long( surface->ofsXyzCompressed );
-		surface->ofsFrameBaseFrames = _pico_little_long( surface->ofsFrameBaseFrames );
-		surface->ofsFrameCompFrames = _pico_little_long( surface->ofsFrameCompFrames );
-		surface->ofsEnd = _pico_little_long( surface->ofsEnd );
-		
-		/* swap triangles */
-		triangle = (mdcTriangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);
-		for( j = 0; j < surface->numTriangles; j++, triangle++ )
-		{
-			/* sea: swaps fixed */
-			triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
-			triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
-			triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
-		}
-		
-		/* swap st coords */
-		texCoord = (mdcTexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);
-		for( j = 0; j < surface->numVerts; j++, texCoord++ )
-		{
-			texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
-			texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
-		}
-		
-		/* swap xyz/normals */
-		vertex = (mdcVertex_t*) ((picoByte_t*) surface + surface->ofsXyzNormals);
-		for( j = 0; j < (surface->numVerts * surface->numBaseFrames); j++, vertex++)
-		{
-			vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
-			vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
-			vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
-			vertex->normal	 = _pico_little_short( vertex->normal );
-		}
-
-		/* swap xyz/compressed */
-		vertexComp = (mdcXyzCompressed_t*) ((picoByte_t*) surface + surface->ofsXyzCompressed);
-		for( j = 0; j < (surface->numVerts * surface->numCompFrames); j++, vertexComp++)
-		{
-			vertexComp->ofsVec	= _pico_little_long( vertexComp->ofsVec );
-		}
-
-		/* swap base frames */
-		mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameBaseFrames);
-		for( j = 0; j < mdc->numFrames; j++, mdcShort++)
-		{
-			*mdcShort	= _pico_little_short( *mdcShort );
-		}
-
-		/* swap compressed frames */
-		mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameCompFrames);
-		for( j = 0; j < mdc->numFrames; j++, mdcShort++)
-		{
-			*mdcShort	= _pico_little_short( *mdcShort );
-		}
-		
-		/* get next surface */
-		surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);
-	}
-	
-	/* -------------------------------------------------
-	pico model creation
-	------------------------------------------------- */
-	
-	/* create new pico model */
-	picoModel = PicoNewModel();
-	if( picoModel == NULL )
-	{
-		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
-		return NULL;
-	}
-	
-	/* do model setup */
-	PicoSetModelFrameNum( picoModel, frameNum );
-	PicoSetModelNumFrames( picoModel, mdc->numFrames ); /* sea */
-	PicoSetModelName( picoModel, fileName );
-	PicoSetModelFileName( picoModel, fileName );
-	
-	/* mdc surfaces become picomodel surfaces */
-	surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);
-	
-	/* run through mdc surfaces */
-	for( i = 0; i < mdc->numSurfaces; i++ )
-	{
-		/* allocate new pico surface */
-		picoSurface = PicoNewSurface( picoModel );
-		if( picoSurface == NULL )
-		{
-			_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
-			PicoFreeModel( picoModel ); /* sea */
-			return NULL;
-		}
-		
-		/* mdc model surfaces are all triangle meshes */
-		PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
-		
-		/* set surface name */
-		PicoSetSurfaceName( picoSurface, surface->name );
-		
-		/* create new pico shader -sea */
-		picoShader = PicoNewShader( picoModel );
-		if( picoShader == NULL )
-		{
-			_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
-			PicoFreeModel( picoModel );
-			return NULL;
-		}
-		
-		/* detox and set shader name */
-		shader = (mdcShader_t*) ((picoByte_t*) surface + surface->ofsShaders);
-		_pico_setfext( shader->name, "" );
-		_pico_unixify( shader->name );
-		PicoSetShaderName( picoShader, shader->name );
-		
-		/* associate current surface with newly created shader */
-		PicoSetSurfaceShader( picoSurface, picoShader );
-		
-		/* copy indexes */
-		triangle = (mdcTriangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);
-		
-		for( j = 0; j < surface->numTriangles; j++, triangle++ )
-		{
-			PicoSetSurfaceIndex( picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[ 0 ] );
-			PicoSetSurfaceIndex( picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[ 1 ] );
-			PicoSetSurfaceIndex( picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[ 2 ] );
-		}
-		
-		/* copy vertexes */
-		texCoord = (mdcTexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);
-    mdcShort = (short *) ((picoByte_t *) surface + surface->ofsXyzNormals) + ((int)*((short *) ((picoByte_t *) surface + surface->ofsFrameBaseFrames) + frameNum) * surface->numVerts * 4);
-		if( surface->numCompFrames > 0 )
-		{
-			mdcCompVert = (short *) ((picoByte_t *) surface + surface->ofsFrameCompFrames) + frameNum;
-			if( *mdcCompVert >= 0 )
-				vertexComp = (mdcXyzCompressed_t *) ((picoByte_t *) surface + surface->ofsXyzCompressed) + (*mdcCompVert * surface->numVerts);
-		}
-		_pico_set_color( color, 255, 255, 255, 255 );
-		
-		for( j = 0; j < surface->numVerts; j++, texCoord++, mdcShort+=4 )
-		{
-			/* set vertex origin */
-			xyz[ 0 ] = MDC_SCALE * mdcShort[ 0 ];
-			xyz[ 1 ] = MDC_SCALE * mdcShort[ 1 ];
-			xyz[ 2 ] = MDC_SCALE * mdcShort[ 2 ];
-
-			/* add compressed ofsVec */
-			if( surface->numCompFrames > 0 && *mdcCompVert >= 0 )
-			{		
-				xyz[ 0 ] += ((float) ((vertexComp->ofsVec) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
-				xyz[ 1 ] += ((float) ((vertexComp->ofsVec >> 8) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
-				xyz[ 2 ] += ((float) ((vertexComp->ofsVec >> 16) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
-				PicoSetSurfaceXYZ( picoSurface, j, xyz );
-
-				normal[ 0 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 0 ];
-				normal[ 1 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 1 ];
-				normal[ 2 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 2 ];
-				PicoSetSurfaceNormal( picoSurface, j, normal );
-
-				vertexComp++;
-			}
-			else
-			{			
-				PicoSetSurfaceXYZ( picoSurface, j, xyz );
-
-				/* decode lat/lng normal to 3 float normal */
-				lat = (float) ((*(mdcShort + 3) >> 8) & 0xff);
-				lng = (float) (*(mdcShort + 3) & 0xff);
-				lat *= PICO_PI / 128;
-				lng *= PICO_PI / 128;
-				normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
-				normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
-				normal[ 2 ] = (picoVec_t) cos( lng );
-				PicoSetSurfaceNormal( picoSurface, j, normal );
-			}
-			
-			/* set st coords */
-			st[ 0 ] = texCoord->st[ 0 ];
-			st[ 1 ] = texCoord->st[ 1 ];
-			PicoSetSurfaceST( picoSurface, 0, j, st );
-
-			/* set color */
-			PicoSetSurfaceColor( picoSurface, 0, j, color );
-		}
-		
-		/* get next surface */
-		surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);
-	}
-	
-	/* return the new pico model */
-	return picoModel;
-}
-
-
-
-/* pico file format module definition */
-const picoModule_t picoModuleMDC =
-{
-	"1.3",							/* module version string */
-	"RtCW MDC",						/* module display name */
-	"Arnout van Meer",				/* author's name */
-	"2002 Arnout van Meer",			/* module copyright */
-	{
-		"mdc", NULL, NULL, NULL		/* default extensions to use */
-	},
-	_mdc_canload,					/* validation routine */
-	_mdc_load,						/* load routine */
-	 NULL,							/* save validation routine */
-	 NULL							/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library 
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PM_MDC_C
+
+
+
+/* dependencies */
+#include "picointernal.h"
+
+/* mdc model format */
+#define MDC_MAGIC			"IDPC"
+#define MDC_VERSION			2
+
+/* mdc vertex scale */
+#define MDC_SCALE			(1.0f / 64.0f)
+#define	MDC_MAX_OFS			127.0f
+#define	MDC_DIST_SCALE		0.05f
+
+/* mdc decoding normal table */
+double mdcNormals[ 256 ][ 3 ] =
+{
+	{ 1.000000, 0.000000, 0.000000 },
+	{ 0.980785, 0.195090, 0.000000 },
+	{ 0.923880, 0.382683, 0.000000 },
+	{ 0.831470, 0.555570, 0.000000 },
+	{ 0.707107, 0.707107, 0.000000 },
+	{ 0.555570, 0.831470, 0.000000 },
+	{ 0.382683, 0.923880, 0.000000 },
+	{ 0.195090, 0.980785, 0.000000 },
+	{ -0.000000, 1.000000, 0.000000 },
+	{ -0.195090, 0.980785, 0.000000 },
+	{ -0.382683, 0.923880, 0.000000 },
+	{ -0.555570, 0.831470, 0.000000 },
+	{ -0.707107, 0.707107, 0.000000 },
+	{ -0.831470, 0.555570, 0.000000 },
+	{ -0.923880, 0.382683, 0.000000 },
+	{ -0.980785, 0.195090, 0.000000 },
+	{ -1.000000, -0.000000, 0.000000 },
+	{ -0.980785, -0.195090, 0.000000 },
+	{ -0.923880, -0.382683, 0.000000 },
+	{ -0.831470, -0.555570, 0.000000 },
+	{ -0.707107, -0.707107, 0.000000 },
+	{ -0.555570, -0.831469, 0.000000 },
+	{ -0.382684, -0.923880, 0.000000 },
+	{ -0.195090, -0.980785, 0.000000 },
+	{ 0.000000, -1.000000, 0.000000 },
+	{ 0.195090, -0.980785, 0.000000 },
+	{ 0.382684, -0.923879, 0.000000 },
+	{ 0.555570, -0.831470, 0.000000 },
+	{ 0.707107, -0.707107, 0.000000 },
+	{ 0.831470, -0.555570, 0.000000 },
+	{ 0.923880, -0.382683, 0.000000 },
+	{ 0.980785, -0.195090, 0.000000 },
+	{ 0.980785, 0.000000, -0.195090 },
+	{ 0.956195, 0.218245, -0.195090 },
+	{ 0.883657, 0.425547, -0.195090 },
+	{ 0.766809, 0.611510, -0.195090 },
+	{ 0.611510, 0.766809, -0.195090 },
+	{ 0.425547, 0.883657, -0.195090 },
+	{ 0.218245, 0.956195, -0.195090 },
+	{ -0.000000, 0.980785, -0.195090 },
+	{ -0.218245, 0.956195, -0.195090 },
+	{ -0.425547, 0.883657, -0.195090 },
+	{ -0.611510, 0.766809, -0.195090 },
+	{ -0.766809, 0.611510, -0.195090 },
+	{ -0.883657, 0.425547, -0.195090 },
+	{ -0.956195, 0.218245, -0.195090 },
+	{ -0.980785, -0.000000, -0.195090 },
+	{ -0.956195, -0.218245, -0.195090 },
+	{ -0.883657, -0.425547, -0.195090 },
+	{ -0.766809, -0.611510, -0.195090 },
+	{ -0.611510, -0.766809, -0.195090 },
+	{ -0.425547, -0.883657, -0.195090 },
+	{ -0.218245, -0.956195, -0.195090 },
+	{ 0.000000, -0.980785, -0.195090 },
+	{ 0.218245, -0.956195, -0.195090 },
+	{ 0.425547, -0.883657, -0.195090 },
+	{ 0.611510, -0.766809, -0.195090 },
+	{ 0.766809, -0.611510, -0.195090 },
+	{ 0.883657, -0.425547, -0.195090 },
+	{ 0.956195, -0.218245, -0.195090 },
+	{ 0.923880, 0.000000, -0.382683 },
+	{ 0.892399, 0.239118, -0.382683 },
+	{ 0.800103, 0.461940, -0.382683 },
+	{ 0.653281, 0.653281, -0.382683 },
+	{ 0.461940, 0.800103, -0.382683 },
+	{ 0.239118, 0.892399, -0.382683 },
+	{ -0.000000, 0.923880, -0.382683 },
+	{ -0.239118, 0.892399, -0.382683 },
+	{ -0.461940, 0.800103, -0.382683 },
+	{ -0.653281, 0.653281, -0.382683 },
+	{ -0.800103, 0.461940, -0.382683 },
+	{ -0.892399, 0.239118, -0.382683 },
+	{ -0.923880, -0.000000, -0.382683 },
+	{ -0.892399, -0.239118, -0.382683 },
+	{ -0.800103, -0.461940, -0.382683 },
+	{ -0.653282, -0.653281, -0.382683 },
+	{ -0.461940, -0.800103, -0.382683 },
+	{ -0.239118, -0.892399, -0.382683 },
+	{ 0.000000, -0.923880, -0.382683 },
+	{ 0.239118, -0.892399, -0.382683 },
+	{ 0.461940, -0.800103, -0.382683 },
+	{ 0.653281, -0.653282, -0.382683 },
+	{ 0.800103, -0.461940, -0.382683 },
+	{ 0.892399, -0.239117, -0.382683 },
+	{ 0.831470, 0.000000, -0.555570 },
+	{ 0.790775, 0.256938, -0.555570 },
+	{ 0.672673, 0.488726, -0.555570 },
+	{ 0.488726, 0.672673, -0.555570 },
+	{ 0.256938, 0.790775, -0.555570 },
+	{ -0.000000, 0.831470, -0.555570 },
+	{ -0.256938, 0.790775, -0.555570 },
+	{ -0.488726, 0.672673, -0.555570 },
+	{ -0.672673, 0.488726, -0.555570 },
+	{ -0.790775, 0.256938, -0.555570 },
+	{ -0.831470, -0.000000, -0.555570 },
+	{ -0.790775, -0.256938, -0.555570 },
+	{ -0.672673, -0.488726, -0.555570 },
+	{ -0.488725, -0.672673, -0.555570 },
+	{ -0.256938, -0.790775, -0.555570 },
+	{ 0.000000, -0.831470, -0.555570 },
+	{ 0.256938, -0.790775, -0.555570 },
+	{ 0.488725, -0.672673, -0.555570 },
+	{ 0.672673, -0.488726, -0.555570 },
+	{ 0.790775, -0.256938, -0.555570 },
+	{ 0.707107, 0.000000, -0.707107 },
+	{ 0.653281, 0.270598, -0.707107 },
+	{ 0.500000, 0.500000, -0.707107 },
+	{ 0.270598, 0.653281, -0.707107 },
+	{ -0.000000, 0.707107, -0.707107 },
+	{ -0.270598, 0.653282, -0.707107 },
+	{ -0.500000, 0.500000, -0.707107 },
+	{ -0.653281, 0.270598, -0.707107 },
+	{ -0.707107, -0.000000, -0.707107 },
+	{ -0.653281, -0.270598, -0.707107 },
+	{ -0.500000, -0.500000, -0.707107 },
+	{ -0.270598, -0.653281, -0.707107 },
+	{ 0.000000, -0.707107, -0.707107 },
+	{ 0.270598, -0.653281, -0.707107 },
+	{ 0.500000, -0.500000, -0.707107 },
+	{ 0.653282, -0.270598, -0.707107 },
+	{ 0.555570, 0.000000, -0.831470 },
+	{ 0.481138, 0.277785, -0.831470 },
+	{ 0.277785, 0.481138, -0.831470 },
+	{ -0.000000, 0.555570, -0.831470 },
+	{ -0.277785, 0.481138, -0.831470 },
+	{ -0.481138, 0.277785, -0.831470 },
+	{ -0.555570, -0.000000, -0.831470 },
+	{ -0.481138, -0.277785, -0.831470 },
+	{ -0.277785, -0.481138, -0.831470 },
+	{ 0.000000, -0.555570, -0.831470 },
+	{ 0.277785, -0.481138, -0.831470 },
+	{ 0.481138, -0.277785, -0.831470 },
+	{ 0.382683, 0.000000, -0.923880 },
+	{ 0.270598, 0.270598, -0.923880 },
+	{ -0.000000, 0.382683, -0.923880 },
+	{ -0.270598, 0.270598, -0.923880 },
+	{ -0.382683, -0.000000, -0.923880 },
+	{ -0.270598, -0.270598, -0.923880 },
+	{ 0.000000, -0.382683, -0.923880 },
+	{ 0.270598, -0.270598, -0.923880 },
+	{ 0.195090, 0.000000, -0.980785 },
+	{ -0.000000, 0.195090, -0.980785 },
+	{ -0.195090, -0.000000, -0.980785 },
+	{ 0.000000, -0.195090, -0.980785 },
+	{ 0.980785, 0.000000, 0.195090 },
+	{ 0.956195, 0.218245, 0.195090 },
+	{ 0.883657, 0.425547, 0.195090 },
+	{ 0.766809, 0.611510, 0.195090 },
+	{ 0.611510, 0.766809, 0.195090 },
+	{ 0.425547, 0.883657, 0.195090 },
+	{ 0.218245, 0.956195, 0.195090 },
+	{ -0.000000, 0.980785, 0.195090 },
+	{ -0.218245, 0.956195, 0.195090 },
+	{ -0.425547, 0.883657, 0.195090 },
+	{ -0.611510, 0.766809, 0.195090 },
+	{ -0.766809, 0.611510, 0.195090 },
+	{ -0.883657, 0.425547, 0.195090 },
+	{ -0.956195, 0.218245, 0.195090 },
+	{ -0.980785, -0.000000, 0.195090 },
+	{ -0.956195, -0.218245, 0.195090 },
+	{ -0.883657, -0.425547, 0.195090 },
+	{ -0.766809, -0.611510, 0.195090 },
+	{ -0.611510, -0.766809, 0.195090 },
+	{ -0.425547, -0.883657, 0.195090 },
+	{ -0.218245, -0.956195, 0.195090 },
+	{ 0.000000, -0.980785, 0.195090 },
+	{ 0.218245, -0.956195, 0.195090 },
+	{ 0.425547, -0.883657, 0.195090 },
+	{ 0.611510, -0.766809, 0.195090 },
+	{ 0.766809, -0.611510, 0.195090 },
+	{ 0.883657, -0.425547, 0.195090 },
+	{ 0.956195, -0.218245, 0.195090 },
+	{ 0.923880, 0.000000, 0.382683 },
+	{ 0.892399, 0.239118, 0.382683 },
+	{ 0.800103, 0.461940, 0.382683 },
+	{ 0.653281, 0.653281, 0.382683 },
+	{ 0.461940, 0.800103, 0.382683 },
+	{ 0.239118, 0.892399, 0.382683 },
+	{ -0.000000, 0.923880, 0.382683 },
+	{ -0.239118, 0.892399, 0.382683 },
+	{ -0.461940, 0.800103, 0.382683 },
+	{ -0.653281, 0.653281, 0.382683 },
+	{ -0.800103, 0.461940, 0.382683 },
+	{ -0.892399, 0.239118, 0.382683 },
+	{ -0.923880, -0.000000, 0.382683 },
+	{ -0.892399, -0.239118, 0.382683 },
+	{ -0.800103, -0.461940, 0.382683 },
+	{ -0.653282, -0.653281, 0.382683 },
+	{ -0.461940, -0.800103, 0.382683 },
+	{ -0.239118, -0.892399, 0.382683 },
+	{ 0.000000, -0.923880, 0.382683 },
+	{ 0.239118, -0.892399, 0.382683 },
+	{ 0.461940, -0.800103, 0.382683 },
+	{ 0.653281, -0.653282, 0.382683 },
+	{ 0.800103, -0.461940, 0.382683 },
+	{ 0.892399, -0.239117, 0.382683 },
+	{ 0.831470, 0.000000, 0.555570 },
+	{ 0.790775, 0.256938, 0.555570 },
+	{ 0.672673, 0.488726, 0.555570 },
+	{ 0.488726, 0.672673, 0.555570 },
+	{ 0.256938, 0.790775, 0.555570 },
+	{ -0.000000, 0.831470, 0.555570 },
+	{ -0.256938, 0.790775, 0.555570 },
+	{ -0.488726, 0.672673, 0.555570 },
+	{ -0.672673, 0.488726, 0.555570 },
+	{ -0.790775, 0.256938, 0.555570 },
+	{ -0.831470, -0.000000, 0.555570 },
+	{ -0.790775, -0.256938, 0.555570 },
+	{ -0.672673, -0.488726, 0.555570 },
+	{ -0.488725, -0.672673, 0.555570 },
+	{ -0.256938, -0.790775, 0.555570 },
+	{ 0.000000, -0.831470, 0.555570 },
+	{ 0.256938, -0.790775, 0.555570 },
+	{ 0.488725, -0.672673, 0.555570 },
+	{ 0.672673, -0.488726, 0.555570 },
+	{ 0.790775, -0.256938, 0.555570 },
+	{ 0.707107, 0.000000, 0.707107 },
+	{ 0.653281, 0.270598, 0.707107 },
+	{ 0.500000, 0.500000, 0.707107 },
+	{ 0.270598, 0.653281, 0.707107 },
+	{ -0.000000, 0.707107, 0.707107 },
+	{ -0.270598, 0.653282, 0.707107 },
+	{ -0.500000, 0.500000, 0.707107 },
+	{ -0.653281, 0.270598, 0.707107 },
+	{ -0.707107, -0.000000, 0.707107 },
+	{ -0.653281, -0.270598, 0.707107 },
+	{ -0.500000, -0.500000, 0.707107 },
+	{ -0.270598, -0.653281, 0.707107 },
+	{ 0.000000, -0.707107, 0.707107 },
+	{ 0.270598, -0.653281, 0.707107 },
+	{ 0.500000, -0.500000, 0.707107 },
+	{ 0.653282, -0.270598, 0.707107 },
+	{ 0.555570, 0.000000, 0.831470 },
+	{ 0.481138, 0.277785, 0.831470 },
+	{ 0.277785, 0.481138, 0.831470 },
+	{ -0.000000, 0.555570, 0.831470 },
+	{ -0.277785, 0.481138, 0.831470 },
+	{ -0.481138, 0.277785, 0.831470 },
+	{ -0.555570, -0.000000, 0.831470 },
+	{ -0.481138, -0.277785, 0.831470 },
+	{ -0.277785, -0.481138, 0.831470 },
+	{ 0.000000, -0.555570, 0.831470 },
+	{ 0.277785, -0.481138, 0.831470 },
+	{ 0.481138, -0.277785, 0.831470 },
+	{ 0.382683, 0.000000, 0.923880 },
+	{ 0.270598, 0.270598, 0.923880 },
+	{ -0.000000, 0.382683, 0.923880 },
+	{ -0.270598, 0.270598, 0.923880 },
+	{ -0.382683, -0.000000, 0.923880 },
+	{ -0.270598, -0.270598, 0.923880 },
+	{ 0.000000, -0.382683, 0.923880 },
+	{ 0.270598, -0.270598, 0.923880 },
+	{ 0.195090, 0.000000, 0.980785 },
+	{ -0.000000, 0.195090, 0.980785 },
+	{ -0.195090, -0.000000, 0.980785 },
+	{ 0.000000, -0.195090, 0.980785 }
+};
+
+/* mdc model frame information */
+typedef struct mdcFrame_s
+{
+	float		bounds[ 2 ][ 3 ];
+	float		localOrigin[ 3 ];
+	float		radius;
+	char		creator[ 16 ];
+}
+mdcFrame_t;
+
+/* mdc model tag information */
+typedef struct mdcTag_s
+{
+	short		xyz[3];
+	short		angles[3];
+}
+mdcTag_t;
+
+/* mdc surface mdc (one object mesh) */
+typedef struct mdcSurface_s
+{
+	char		magic[ 4 ];
+	char		name[ 64 ];			/* polyset name */
+	int			flags;
+	int			numCompFrames;		/* all surfaces in a model should have the same */
+	int			numBaseFrames;		/* ditto */
+	int			numShaders;			/* all model surfaces should have the same */
+	int			numVerts;
+	int			numTriangles;
+	int			ofsTriangles;
+	int			ofsShaders;			/* offset from start of mdcSurface_t */
+	int			ofsSt;				/* texture coords are common for all frames */
+	int			ofsXyzNormals;		/* numVerts * numBaseFrames */
+	int			ofsXyzCompressed;	/* numVerts * numCompFrames */
+
+	int			ofsFrameBaseFrames;	/* numFrames */
+	int			ofsFrameCompFrames;	/* numFrames */
+	int			ofsEnd;				/* next surface follows */
+}
+mdcSurface_t;
+
+typedef struct mdcShader_s
+{
+	char		name[ 64 ];
+	int			shaderIndex;	/* for ingame use */
+}
+mdcShader_t;
+
+typedef struct mdcTriangle_s
+{
+	int			indexes[ 3 ];
+}
+mdcTriangle_t;
+
+typedef struct mdcTexCoord_s
+{
+	float		st[ 2 ];
+}
+mdcTexCoord_t;
+
+typedef struct mdcVertex_s
+{
+	short		xyz[ 3 ];
+	short		normal;
+}
+mdcVertex_t;
+
+typedef struct mdcXyzCompressed_s
+{
+	unsigned int	ofsVec;		/* offset direction from the last base frame */
+}
+mdcXyzCompressed_t;
+
+
+/* mdc model file mdc structure */
+typedef struct mdc_s
+{
+	char		magic[ 4 ];		/* MDC_MAGIC */
+	int			version;
+	char		name[ 64 ];		/* model name */
+	int			flags;
+	int			numFrames;
+	int			numTags;
+	int			numSurfaces;
+	int			numSkins;		/* number of skins for the mesh */
+	int			ofsFrames;		/* offset for first frame */
+	int			ofsTagNames;	/* numTags */
+	int			ofsTags;		/* numFrames * numTags */
+	int			ofsSurfaces;	/* first surface, others follow */
+	int			ofsEnd;			/* end of file */
+}
+mdc_t;
+
+
+
+
+/*
+_mdc_canload()
+validates a Return to Castle Wolfenstein model file. btw, i use the
+preceding underscore cause it's a static func referenced
+by one structure only.
+*/
+
+static int _mdc_canload( PM_PARAMS_CANLOAD )
+{
+	mdc_t	*mdc;
+	
+
+	/* to keep the compiler happy */
+	*fileName = *fileName;
+	
+	/* sanity check */
+	if( bufSize < ( sizeof( *mdc ) * 2) )
+		return PICO_PMV_ERROR_SIZE;
+	
+	/* set as mdc */
+	mdc	= (mdc_t*) buffer;
+	
+	/* check mdc magic */
+	if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) ) 
+		return PICO_PMV_ERROR_IDENT;
+	
+	/* check mdc version */
+	if( _pico_little_long( mdc->version ) != MDC_VERSION )
+		return PICO_PMV_ERROR_VERSION;
+	
+	/* file seems to be a valid mdc */
+	return PICO_PMV_OK;
+}
+
+
+
+/*
+_mdc_load()
+loads a Return to Castle Wolfenstein mdc model file.
+*/
+
+static picoModel_t *_mdc_load( PM_PARAMS_LOAD )
+{
+	int					i, j;
+	picoByte_t			*bb;
+	mdc_t				*mdc;
+	mdcSurface_t		*surface;
+	mdcShader_t			*shader;
+	mdcTexCoord_t		*texCoord;
+	mdcFrame_t			*frame;
+	mdcTriangle_t		*triangle;
+	mdcVertex_t			*vertex;
+	mdcXyzCompressed_t	*vertexComp;
+	short				*mdcShort, *mdcCompVert;
+	double				lat, lng;
+	
+	picoModel_t			*picoModel;
+	picoSurface_t		*picoSurface;
+	picoShader_t		*picoShader;
+	picoVec3_t			xyz, normal;
+	picoVec2_t			st;
+	picoColor_t			color;
+	
+	
+	/* -------------------------------------------------
+	mdc loading
+	------------------------------------------------- */
+
+
+	/* set as mdc */
+	bb = (picoByte_t*) buffer;
+	mdc	= (mdc_t*) buffer;
+	
+	/* check ident and version */
+	if( *((int*) mdc->magic) != *((int*) MDC_MAGIC) || _pico_little_long( mdc->version ) != MDC_VERSION )
+	{
+		/* not an mdc file (todo: set error) */
+		return NULL;
+	}
+	
+	/* swap mdc */
+	mdc->version = _pico_little_long( mdc->version );
+	mdc->numFrames = _pico_little_long( mdc->numFrames );
+	mdc->numTags = _pico_little_long( mdc->numTags );
+	mdc->numSurfaces = _pico_little_long( mdc->numSurfaces );
+	mdc->numSkins = _pico_little_long( mdc->numSkins );
+	mdc->ofsFrames = _pico_little_long( mdc->ofsFrames );
+	mdc->ofsTags = _pico_little_long( mdc->ofsTags );
+	mdc->ofsTagNames = _pico_little_long( mdc->ofsTagNames );
+	mdc->ofsSurfaces = _pico_little_long( mdc->ofsSurfaces );
+	mdc->ofsEnd = _pico_little_long( mdc->ofsEnd );
+	
+	/* do frame check */
+	if( mdc->numFrames < 1 )
+	{
+		_pico_printf( PICO_ERROR, "MDC with 0 frames" );
+		return NULL;
+	}
+	
+	if( frameNum < 0 || frameNum >= mdc->numFrames )
+	{
+		_pico_printf( PICO_ERROR, "Invalid or out-of-range MDC frame specified" );
+		return NULL;
+	}
+	
+	/* swap frames */
+	frame = (mdcFrame_t*) (bb + mdc->ofsFrames );
+	for( i = 0; i < mdc->numFrames; i++, frame++ )
+	{
+		frame->radius = _pico_little_float( frame->radius );
+		for( j = 0; j < 3; j++ )
+		{
+			frame->bounds[ 0 ][ j ] = _pico_little_float( frame->bounds[ 0 ][ j ] );
+			frame->bounds[ 1 ][ j ] = _pico_little_float( frame->bounds[ 1 ][ j ] );
+			frame->localOrigin[ j ] = _pico_little_float( frame->localOrigin[ j ] );
+		}
+	}
+	
+	/* swap surfaces */
+	surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);
+	for( i = 0; i < mdc->numSurfaces; i++ )
+	{
+		/* swap surface mdc */
+		surface->flags = _pico_little_long( surface->flags );
+		surface->numBaseFrames = _pico_little_long( surface->numBaseFrames );
+		surface->numCompFrames = _pico_little_long( surface->numCompFrames );
+		surface->numShaders = _pico_little_long( surface->numShaders );
+		surface->numTriangles = _pico_little_long( surface->numTriangles );
+		surface->ofsTriangles = _pico_little_long( surface->ofsTriangles );
+		surface->numVerts = _pico_little_long( surface->numVerts );
+		surface->ofsShaders = _pico_little_long( surface->ofsShaders );
+		surface->ofsSt = _pico_little_long( surface->ofsSt );
+		surface->ofsXyzNormals = _pico_little_long( surface->ofsXyzNormals );
+		surface->ofsXyzCompressed = _pico_little_long( surface->ofsXyzCompressed );
+		surface->ofsFrameBaseFrames = _pico_little_long( surface->ofsFrameBaseFrames );
+		surface->ofsFrameCompFrames = _pico_little_long( surface->ofsFrameCompFrames );
+		surface->ofsEnd = _pico_little_long( surface->ofsEnd );
+		
+		/* swap triangles */
+		triangle = (mdcTriangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);
+		for( j = 0; j < surface->numTriangles; j++, triangle++ )
+		{
+			/* sea: swaps fixed */
+			triangle->indexes[ 0 ] = _pico_little_long( triangle->indexes[ 0 ] );
+			triangle->indexes[ 1 ] = _pico_little_long( triangle->indexes[ 1 ] );
+			triangle->indexes[ 2 ] = _pico_little_long( triangle->indexes[ 2 ] );
+		}
+		
+		/* swap st coords */
+		texCoord = (mdcTexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);
+		for( j = 0; j < surface->numVerts; j++, texCoord++ )
+		{
+			texCoord->st[ 0 ] = _pico_little_float( texCoord->st[ 0 ] );
+			texCoord->st[ 1 ] = _pico_little_float( texCoord->st[ 1 ] );
+		}
+		
+		/* swap xyz/normals */
+		vertex = (mdcVertex_t*) ((picoByte_t*) surface + surface->ofsXyzNormals);
+		for( j = 0; j < (surface->numVerts * surface->numBaseFrames); j++, vertex++)
+		{
+			vertex->xyz[ 0 ] = _pico_little_short( vertex->xyz[ 0 ] );
+			vertex->xyz[ 1 ] = _pico_little_short( vertex->xyz[ 1 ] );
+			vertex->xyz[ 2 ] = _pico_little_short( vertex->xyz[ 2 ] );
+			vertex->normal	 = _pico_little_short( vertex->normal );
+		}
+
+		/* swap xyz/compressed */
+		vertexComp = (mdcXyzCompressed_t*) ((picoByte_t*) surface + surface->ofsXyzCompressed);
+		for( j = 0; j < (surface->numVerts * surface->numCompFrames); j++, vertexComp++)
+		{
+			vertexComp->ofsVec	= _pico_little_long( vertexComp->ofsVec );
+		}
+
+		/* swap base frames */
+		mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameBaseFrames);
+		for( j = 0; j < mdc->numFrames; j++, mdcShort++)
+		{
+			*mdcShort	= _pico_little_short( *mdcShort );
+		}
+
+		/* swap compressed frames */
+		mdcShort = (short *) ((picoByte_t*) surface + surface->ofsFrameCompFrames);
+		for( j = 0; j < mdc->numFrames; j++, mdcShort++)
+		{
+			*mdcShort	= _pico_little_short( *mdcShort );
+		}
+		
+		/* get next surface */
+		surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);
+	}
+	
+	/* -------------------------------------------------
+	pico model creation
+	------------------------------------------------- */
+	
+	/* create new pico model */
+	picoModel = PicoNewModel();
+	if( picoModel == NULL )
+	{
+		_pico_printf( PICO_ERROR, "Unable to allocate a new model" );
+		return NULL;
+	}
+	
+	/* do model setup */
+	PicoSetModelFrameNum( picoModel, frameNum );
+	PicoSetModelNumFrames( picoModel, mdc->numFrames ); /* sea */
+	PicoSetModelName( picoModel, fileName );
+	PicoSetModelFileName( picoModel, fileName );
+	
+	/* mdc surfaces become picomodel surfaces */
+	surface = (mdcSurface_t*) (bb + mdc->ofsSurfaces);
+	
+	/* run through mdc surfaces */
+	for( i = 0; i < mdc->numSurfaces; i++ )
+	{
+		/* allocate new pico surface */
+		picoSurface = PicoNewSurface( picoModel );
+		if( picoSurface == NULL )
+		{
+			_pico_printf( PICO_ERROR, "Unable to allocate a new model surface" );
+			PicoFreeModel( picoModel ); /* sea */
+			return NULL;
+		}
+		
+		/* mdc model surfaces are all triangle meshes */
+		PicoSetSurfaceType( picoSurface, PICO_TRIANGLES );
+		
+		/* set surface name */
+		PicoSetSurfaceName( picoSurface, surface->name );
+		
+		/* create new pico shader -sea */
+		picoShader = PicoNewShader( picoModel );
+		if( picoShader == NULL )
+		{
+			_pico_printf( PICO_ERROR, "Unable to allocate a new model shader" );
+			PicoFreeModel( picoModel );
+			return NULL;
+		}
+		
+		/* detox and set shader name */
+		shader = (mdcShader_t*) ((picoByte_t*) surface + surface->ofsShaders);
+		_pico_setfext( shader->name, "" );
+		_pico_unixify( shader->name );
+		PicoSetShaderName( picoShader, shader->name );
+		
+		/* associate current surface with newly created shader */
+		PicoSetSurfaceShader( picoSurface, picoShader );
+		
+		/* copy indexes */
+		triangle = (mdcTriangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);
+		
+		for( j = 0; j < surface->numTriangles; j++, triangle++ )
+		{
+			PicoSetSurfaceIndex( picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[ 0 ] );
+			PicoSetSurfaceIndex( picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[ 1 ] );
+			PicoSetSurfaceIndex( picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[ 2 ] );
+		}
+		
+		/* copy vertexes */
+		texCoord = (mdcTexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);
+    mdcShort = (short *) ((picoByte_t *) surface + surface->ofsXyzNormals) + ((int)*((short *) ((picoByte_t *) surface + surface->ofsFrameBaseFrames) + frameNum) * surface->numVerts * 4);
+		if( surface->numCompFrames > 0 )
+		{
+			mdcCompVert = (short *) ((picoByte_t *) surface + surface->ofsFrameCompFrames) + frameNum;
+			if( *mdcCompVert >= 0 )
+				vertexComp = (mdcXyzCompressed_t *) ((picoByte_t *) surface + surface->ofsXyzCompressed) + (*mdcCompVert * surface->numVerts);
+		}
+		_pico_set_color( color, 255, 255, 255, 255 );
+		
+		for( j = 0; j < surface->numVerts; j++, texCoord++, mdcShort+=4 )
+		{
+			/* set vertex origin */
+			xyz[ 0 ] = MDC_SCALE * mdcShort[ 0 ];
+			xyz[ 1 ] = MDC_SCALE * mdcShort[ 1 ];
+			xyz[ 2 ] = MDC_SCALE * mdcShort[ 2 ];
+
+			/* add compressed ofsVec */
+			if( surface->numCompFrames > 0 && *mdcCompVert >= 0 )
+			{		
+				xyz[ 0 ] += ((float) ((vertexComp->ofsVec) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
+				xyz[ 1 ] += ((float) ((vertexComp->ofsVec >> 8) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
+				xyz[ 2 ] += ((float) ((vertexComp->ofsVec >> 16) & 255) - MDC_MAX_OFS) * MDC_DIST_SCALE;
+				PicoSetSurfaceXYZ( picoSurface, j, xyz );
+
+				normal[ 0 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 0 ];
+				normal[ 1 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 1 ];
+				normal[ 2 ] = (float) mdcNormals[ (vertexComp->ofsVec >> 24) ][ 2 ];
+				PicoSetSurfaceNormal( picoSurface, j, normal );
+
+				vertexComp++;
+			}
+			else
+			{			
+				PicoSetSurfaceXYZ( picoSurface, j, xyz );
+
+				/* decode lat/lng normal to 3 float normal */
+				lat = (float) ((*(mdcShort + 3) >> 8) & 0xff);
+				lng = (float) (*(mdcShort + 3) & 0xff);
+				lat *= PICO_PI / 128;
+				lng *= PICO_PI / 128;
+				normal[ 0 ] = (picoVec_t) cos( lat ) * (picoVec_t) sin( lng );
+				normal[ 1 ] = (picoVec_t) sin( lat ) * (picoVec_t) sin( lng );
+				normal[ 2 ] = (picoVec_t) cos( lng );
+				PicoSetSurfaceNormal( picoSurface, j, normal );
+			}
+			
+			/* set st coords */
+			st[ 0 ] = texCoord->st[ 0 ];
+			st[ 1 ] = texCoord->st[ 1 ];
+			PicoSetSurfaceST( picoSurface, 0, j, st );
+
+			/* set color */
+			PicoSetSurfaceColor( picoSurface, 0, j, color );
+		}
+		
+		/* get next surface */
+		surface = (mdcSurface_t*) ((picoByte_t*) surface + surface->ofsEnd);
+	}
+	
+	/* return the new pico model */
+	return picoModel;
+}
+
+
+
+/* pico file format module definition */
+const picoModule_t picoModuleMDC =
+{
+	"1.3",							/* module version string */
+	"RtCW MDC",						/* module display name */
+	"Arnout van Meer",				/* author's name */
+	"2002 Arnout van Meer",			/* module copyright */
+	{
+		"mdc", NULL, NULL, NULL		/* default extensions to use */
+	},
+	_mdc_canload,					/* validation routine */
+	_mdc_load,						/* load routine */
+	 NULL,							/* save validation routine */
+	 NULL							/* save routine */
+};
diff --git a/libs/picomodel/pm_ms3d.c b/libs/picomodel/pm_ms3d.c
index 4bbd9b38..27147bc0 100644
--- a/libs/picomodel/pm_ms3d.c
+++ b/libs/picomodel/pm_ms3d.c
@@ -1,494 +1,494 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PM_MS3D_C
-
-/* dependencies */
-#include "picointernal.h"
-
-/* disable warnings */
-#ifdef _WIN32
-#pragma warning( disable:4100 )		/* unref param */
-#endif
-
-/* remarks:
- * - loader seems stable
- * todo:
- * - fix uv coordinate problem
- * - check for buffer overflows ('bufptr' accesses)
- */
-/* uncomment when debugging this module */
- #define DEBUG_PM_MS3D
- #define DEBUG_PM_MS3D_EX
-
-/* plain white */
-static picoColor_t white = { 255,255,255,255 };
-
-/* ms3d limits */
-#define MS3D_MAX_VERTS		8192
-#define MS3D_MAX_TRIS		16384
-#define MS3D_MAX_GROUPS		128
-#define MS3D_MAX_MATERIALS	128
-#define MS3D_MAX_JOINTS		128
-#define MS3D_MAX_KEYFRAMES	216
-
-/* ms3d flags */
-#define MS3D_SELECTED		1
-#define MS3D_HIDDEN			2
-#define MS3D_SELECTED2		4
-#define MS3D_DIRTY			8
-
-/* this freaky loader needs byte alignment */
-#pragma pack(push, 1)
-
-/* ms3d header */
-typedef struct SMsHeader
-{
-	char			magic[10];
-	int				version;
-}
-TMsHeader;
-
-/* ms3d vertex */
-typedef struct SMsVertex
-{
-	unsigned char	flags;				/* sel, sel2, or hidden */
-	float			xyz[3];
-	char			boneID;				/* -1 means 'no bone' */
-	unsigned char	refCount;
-}
-TMsVertex;
-
-/* ms3d triangle */
-typedef struct SMsTriangle
-{
-	unsigned short	flags;				/* sel, sel2, or hidden */
-	unsigned short	vertexIndices[3];
-	float			vertexNormals[3][3];
-	float			s[3];
-	float			t[3];
-	unsigned char	smoothingGroup;		/* 1 - 32 */
-	unsigned char	groupIndex;
-}
-TMsTriangle;
-
-/* ms3d material */
-typedef struct SMsMaterial
-{
-	char			name[32];
-	float			ambient[4];
-	float			diffuse[4];
-	float			specular[4];
-	float			emissive[4];
-	float			shininess;			/* range 0..128 */
-	float			transparency;		/* range 0..1 */
-	unsigned char	mode;
-	char			texture [128];		/* texture.bmp */
-	char			alphamap[128];		/* alpha.bmp */
-}
-TMsMaterial;
-
-// ms3d group (static part)
-// followed by a variable size block (see below)
-typedef struct SMsGroup
-{
-	unsigned char	flags;				// sel, hidden
-	char			name[32];
-	unsigned short	numTriangles;
-/*
-	unsigned short	triangleIndices[ numTriangles ];
-	char			materialIndex;		// -1 means 'no material'
-*/
-}
-TMsGroup;
-
-// ms3d joint
-typedef struct SMsJoint
-{
-	unsigned char	flags;
-	char			name[32];
-	char			parentName[32];
-	float			rotation[3];
-	float			translation[3];
-	unsigned short	numRotationKeyframes;
-	unsigned short	numTranslationKeyframes;
-}
-TMsJoint;
-
-// ms3d keyframe
-typedef struct SMsKeyframe
-{
-	float			time;
-	float			parameter[3];
-}
-TMsKeyframe;
-
-/* restore previous data alignment */
-#pragma pack(pop)
-
-/* _ms3d_canload:
- *	validates a milkshape3d model file.
- */
-static int _ms3d_canload( PM_PARAMS_CANLOAD )
-{
-	TMsHeader *hdr;
-	
-	
-	/* to keep the compiler happy */
-	*fileName = *fileName;
-
-	/* sanity check */
-	if (bufSize < sizeof(TMsHeader))
-		return PICO_PMV_ERROR_SIZE;
-
-	/* get ms3d header */
-	hdr = (TMsHeader *)buffer;
-
-	/* check ms3d magic */
-	if (strncmp(hdr->magic,"MS3D000000",10) != 0)
-		return PICO_PMV_ERROR_IDENT;
-
-	/* check ms3d version */
-	if (_pico_little_long(hdr->version) < 3 ||
-		_pico_little_long(hdr->version) > 4)
-	{
-		_pico_printf( PICO_ERROR,"MS3D file ignored. Only MS3D 1.3 and 1.4 is supported." );
-		return PICO_PMV_ERROR_VERSION;
-	}
-	/* file seems to be a valid ms3d */
-	return PICO_PMV_OK;
-}
-
-static unsigned char *GetWord( unsigned char *bufptr, int *out )
-{
-	if (bufptr == NULL) return NULL;
-	*out = _pico_little_short( *(unsigned short *)bufptr );
-	return( bufptr + 2 );
-}
-
-/* _ms3d_load:
- *	loads a milkshape3d model file.
-*/
-static picoModel_t *_ms3d_load( PM_PARAMS_LOAD )
-{
-	picoModel_t	   *model;
-	unsigned char  *bufptr;
-	int				shaderRefs[ MS3D_MAX_GROUPS ];
-	int				numGroups;
-	int				numMaterials;
-//	unsigned char  *ptrToGroups;
-	int				numVerts;
-	unsigned char  *ptrToVerts;
-	int				numTris;
-	unsigned char  *ptrToTris;
-	int				i,k,m;
-
-	/* create new pico model */
-	model = PicoNewModel();
-	if (model == NULL) return NULL;
-
-	/* do model setup */
-	PicoSetModelFrameNum( model, frameNum );
-	PicoSetModelName( model, fileName );
-	PicoSetModelFileName( model, fileName );
-
-	/* skip header */
-	bufptr = (unsigned char *)buffer + sizeof(TMsHeader);
-
-	/* get number of vertices */
-	bufptr = GetWord( bufptr,&numVerts );
-	ptrToVerts = bufptr;
-
-#ifdef DEBUG_PM_MS3D
-	printf("NumVertices: %d\n",numVerts);
-#endif
-	/* swap verts */
-	for (i=0; i<numVerts; i++)
-	{
-		TMsVertex *vertex;
-		vertex = (TMsVertex *)bufptr;
-		bufptr += sizeof( TMsVertex );
-
-		vertex->xyz[ 0 ] = _pico_little_float( vertex->xyz[ 0 ] );
-		vertex->xyz[ 1 ] = _pico_little_float( vertex->xyz[ 1 ] );
-		vertex->xyz[ 2 ] = _pico_little_float( vertex->xyz[ 2 ] );
-
-#ifdef DEBUG_PM_MS3D_EX_
-		printf("Vertex: x: %f y: %f z: %f\n",
-			msvd[i]->vertex[0],
-			msvd[i]->vertex[1],
-			msvd[i]->vertex[2]);
-#endif
-	}
-	/* get number of triangles */
-	bufptr = GetWord( bufptr,&numTris );
-	ptrToTris = bufptr;
-
-#ifdef DEBUG_PM_MS3D
-	printf("NumTriangles: %d\n",numTris);
-#endif
-	/* swap tris */
-	for (i=0; i<numTris; i++)
-	{
-		TMsTriangle *triangle;
-		triangle = (TMsTriangle *)bufptr;
-		bufptr += sizeof( TMsTriangle );
-
-		triangle->flags = _pico_little_short( triangle->flags );
-
-		/* run through all tri verts */
-		for (k=0; k<3; k++)
-		{
-			/* swap tex coords */
-			triangle->s[ k ] = _pico_little_float( triangle->s[ k ] );
-			triangle->t[ k ] = _pico_little_float( triangle->t[ k ] );
-
-			/* swap fields */
-			triangle->vertexIndices[ k ]      = _pico_little_short( triangle->vertexIndices[ k ] );
-			triangle->vertexNormals[ 0 ][ k ] = _pico_little_float( triangle->vertexNormals[ 0 ][ k ] );
-			triangle->vertexNormals[ 1 ][ k ] = _pico_little_float( triangle->vertexNormals[ 1 ][ k ] );
-			triangle->vertexNormals[ 2 ][ k ] = _pico_little_float( triangle->vertexNormals[ 2 ][ k ] );
-
-			/* check for out of range indices */
-			if (triangle->vertexIndices[ k ] >= numVerts)
-			{
-				_pico_printf( PICO_ERROR,"Vertex %d index %d out of range (%d, max %d)",i,k,triangle->vertexIndices[k],numVerts-1);
-				PicoFreeModel( model );
-				return NULL; /* yuck */
-			}
-		}
-	}
-	/* get number of groups */
-	bufptr = GetWord( bufptr,&numGroups );
-//	ptrToGroups = bufptr;
-
-#ifdef DEBUG_PM_MS3D
-	printf("NumGroups: %d\n",numGroups);
-#endif
-	/* run through all groups in model */
-	for (i=0; i<numGroups && i<MS3D_MAX_GROUPS; i++)
-	{
-		picoSurface_t *surface;
-		TMsGroup	  *group;
-
-		group = (TMsGroup *)bufptr;
-		bufptr += sizeof( TMsGroup );
-
-		/* we ignore hidden groups */
-		if (group->flags & MS3D_HIDDEN)
-		{
-			bufptr += (group->numTriangles * 2) + 1;
-			continue;
-		}
-		/* forced null term of group name */
-		group->name[ 31 ] = '\0';
-
-		/* create new pico surface */
-		surface = PicoNewSurface( model );
-		if (surface == NULL)
-		{
-			PicoFreeModel( model );
-			return NULL;
-		}
-		/* do surface setup */
-		PicoSetSurfaceType( surface,PICO_TRIANGLES );
-		PicoSetSurfaceName( surface,group->name );
-
-		/* process triangle indices */
-		for (k=0; k<group->numTriangles; k++)
-		{
-			TMsTriangle *triangle;
-			unsigned int triangleIndex;
-
-			/* get triangle index */
-			bufptr = GetWord( bufptr,(int *)&triangleIndex );
-
-			/* get ptr to triangle data */
-			triangle = (TMsTriangle *)(ptrToTris + (sizeof(TMsTriangle) * triangleIndex));
-
-			/* run through triangle vertices */
-			for (m=0; m<3; m++)
-			{
-				TMsVertex   *vertex;
-				unsigned int vertexIndex;
-				picoVec2_t   texCoord;
-
-				/* get ptr to vertex data */
-				vertexIndex = triangle->vertexIndices[ m ];
-				vertex = (TMsVertex *)(ptrToVerts + (sizeof(TMsVertex) * vertexIndex));
-
-				/* store vertex origin */
-				PicoSetSurfaceXYZ( surface,vertexIndex,vertex->xyz );
-
-				/* store vertex color */
-				PicoSetSurfaceColor( surface,0,vertexIndex,white );
-
-				/* store vertex normal */
-				PicoSetSurfaceNormal( surface,vertexIndex,triangle->vertexNormals[ m ] );
-
-				/* store current face vertex index */
-				PicoSetSurfaceIndex( surface,(k * 3 + (2 - m)),(picoIndex_t)vertexIndex );
-
-				/* get texture vertex coord */
-				texCoord[ 0 ] = triangle->s[ m ];
-				texCoord[ 1 ] = -triangle->t[ m ];	/* flip t */
-
-				/* store texture vertex coord */
-				PicoSetSurfaceST( surface,0,vertexIndex,texCoord );
-			}
-		}
-		/* store material */
-		shaderRefs[ i ] = *bufptr++;
-
-#ifdef DEBUG_PM_MS3D
-		printf("Group %d: '%s' (%d tris)\n",i,group->name,group->numTriangles);
-#endif
-	}
-	/* get number of materials */
-	bufptr = GetWord( bufptr,&numMaterials );
-
-#ifdef DEBUG_PM_MS3D
-	printf("NumMaterials: %d\n",numMaterials);
-#endif
-	/* run through all materials in model */
-	for (i=0; i<numMaterials; i++)
-	{
-		picoShader_t *shader;
-		picoColor_t   ambient,diffuse,specular;
-		TMsMaterial  *material;
-		int           k;
-
-		material = (TMsMaterial *)bufptr;
-		bufptr += sizeof( TMsMaterial );
-
-		/* null term strings */
-		material->name	  [  31 ] = '\0';
-		material->texture [ 127 ] = '\0';
-		material->alphamap[ 127 ] = '\0';
-
-		/* ltrim strings */
-		_pico_strltrim( material->name );
-		_pico_strltrim( material->texture );
-		_pico_strltrim( material->alphamap );
-
-		/* rtrim strings */
-		_pico_strrtrim( material->name );
-		_pico_strrtrim( material->texture );
-		_pico_strrtrim( material->alphamap );
-
-		/* create new pico shader */
-		shader = PicoNewShader( model );
-		if (shader == NULL)
-		{
-			PicoFreeModel( model );
-			return NULL;
-		}
-		/* scale shader colors */
-		for (k=0; k<4; k++)
-		{
-			ambient [ k ] = (picoByte_t) (material->ambient[ k ] * 255);
-			diffuse [ k ] = (picoByte_t) (material->diffuse[ k ] * 255);
-			specular[ k ] = (picoByte_t) (material->specular[ k ] * 255);
-		}
-		/* set shader colors */
-		PicoSetShaderAmbientColor( shader,ambient );
-		PicoSetShaderDiffuseColor( shader,diffuse );
-		PicoSetShaderSpecularColor( shader,specular );
-
-		/* set shader transparency */
-		PicoSetShaderTransparency( shader,material->transparency );
-
-		/* set shader shininess (0..127) */
-		PicoSetShaderShininess( shader,material->shininess );
-
-		/* set shader name */
-		PicoSetShaderName( shader,material->name );
-
-		/* set shader texture map name */
-		PicoSetShaderMapName( shader,material->texture );
-
-#ifdef DEBUG_PM_MS3D
-		printf("Material %d: '%s' ('%s','%s')\n",i,material->name,material->texture,material->alphamap);
-#endif
-	}
-	/* assign shaders to surfaces */
-	for (i=0; i<numGroups && i<MS3D_MAX_GROUPS; i++)
-	{
-		picoSurface_t *surface;
-		picoShader_t  *shader;
-
-		/* sanity check */
-		if (shaderRefs[ i ] >= MS3D_MAX_MATERIALS ||
-			shaderRefs[ i ] < 0)
-			continue;
-
-		/* get surface */
-		surface = PicoGetModelSurface( model,i );
-		if (surface == NULL) continue;
-
-		/* get shader */
-		shader = PicoGetModelShader( model,shaderRefs[ i ] );
-		if (shader == NULL) continue;
-
-		/* assign shader */
-		PicoSetSurfaceShader( surface,shader );
-
-#ifdef DEBUG_PM_MS3D
-		printf("Mapped: %d ('%s') to %d (%s)\n",
-			shaderRefs[i],shader->name,i,surface->name);
-#endif
-	}
-	/* return allocated pico model */
-	return model;
-//	return NULL;
-}
-
-/* pico file format module definition */
-const picoModule_t picoModuleMS3D =
-{
-	"0.4-a",					/* module version string */
-	"Milkshape 3D",				/* module display name */
-	"seaw0lf",					/* author's name */
-	"2002 seaw0lf",				/* module copyright */
-	{
-		"ms3d",NULL,NULL,NULL	/* default extensions to use */
-	},
-	_ms3d_canload,				/* validation routine */
-	_ms3d_load,					/* load routine */
-	 NULL,						/* save validation routine */
-	 NULL						/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PM_MS3D_C
+
+/* dependencies */
+#include "picointernal.h"
+
+/* disable warnings */
+#ifdef _WIN32
+#pragma warning( disable:4100 )		/* unref param */
+#endif
+
+/* remarks:
+ * - loader seems stable
+ * todo:
+ * - fix uv coordinate problem
+ * - check for buffer overflows ('bufptr' accesses)
+ */
+/* uncomment when debugging this module */
+ #define DEBUG_PM_MS3D
+ #define DEBUG_PM_MS3D_EX
+
+/* plain white */
+static picoColor_t white = { 255,255,255,255 };
+
+/* ms3d limits */
+#define MS3D_MAX_VERTS		8192
+#define MS3D_MAX_TRIS		16384
+#define MS3D_MAX_GROUPS		128
+#define MS3D_MAX_MATERIALS	128
+#define MS3D_MAX_JOINTS		128
+#define MS3D_MAX_KEYFRAMES	216
+
+/* ms3d flags */
+#define MS3D_SELECTED		1
+#define MS3D_HIDDEN			2
+#define MS3D_SELECTED2		4
+#define MS3D_DIRTY			8
+
+/* this freaky loader needs byte alignment */
+#pragma pack(push, 1)
+
+/* ms3d header */
+typedef struct SMsHeader
+{
+	char			magic[10];
+	int				version;
+}
+TMsHeader;
+
+/* ms3d vertex */
+typedef struct SMsVertex
+{
+	unsigned char	flags;				/* sel, sel2, or hidden */
+	float			xyz[3];
+	char			boneID;				/* -1 means 'no bone' */
+	unsigned char	refCount;
+}
+TMsVertex;
+
+/* ms3d triangle */
+typedef struct SMsTriangle
+{
+	unsigned short	flags;				/* sel, sel2, or hidden */
+	unsigned short	vertexIndices[3];
+	float			vertexNormals[3][3];
+	float			s[3];
+	float			t[3];
+	unsigned char	smoothingGroup;		/* 1 - 32 */
+	unsigned char	groupIndex;
+}
+TMsTriangle;
+
+/* ms3d material */
+typedef struct SMsMaterial
+{
+	char			name[32];
+	float			ambient[4];
+	float			diffuse[4];
+	float			specular[4];
+	float			emissive[4];
+	float			shininess;			/* range 0..128 */
+	float			transparency;		/* range 0..1 */
+	unsigned char	mode;
+	char			texture [128];		/* texture.bmp */
+	char			alphamap[128];		/* alpha.bmp */
+}
+TMsMaterial;
+
+// ms3d group (static part)
+// followed by a variable size block (see below)
+typedef struct SMsGroup
+{
+	unsigned char	flags;				// sel, hidden
+	char			name[32];
+	unsigned short	numTriangles;
+/*
+	unsigned short	triangleIndices[ numTriangles ];
+	char			materialIndex;		// -1 means 'no material'
+*/
+}
+TMsGroup;
+
+// ms3d joint
+typedef struct SMsJoint
+{
+	unsigned char	flags;
+	char			name[32];
+	char			parentName[32];
+	float			rotation[3];
+	float			translation[3];
+	unsigned short	numRotationKeyframes;
+	unsigned short	numTranslationKeyframes;
+}
+TMsJoint;
+
+// ms3d keyframe
+typedef struct SMsKeyframe
+{
+	float			time;
+	float			parameter[3];
+}
+TMsKeyframe;
+
+/* restore previous data alignment */
+#pragma pack(pop)
+
+/* _ms3d_canload:
+ *	validates a milkshape3d model file.
+ */
+static int _ms3d_canload( PM_PARAMS_CANLOAD )
+{
+	TMsHeader *hdr;
+	
+	
+	/* to keep the compiler happy */
+	*fileName = *fileName;
+
+	/* sanity check */
+	if (bufSize < sizeof(TMsHeader))
+		return PICO_PMV_ERROR_SIZE;
+
+	/* get ms3d header */
+	hdr = (TMsHeader *)buffer;
+
+	/* check ms3d magic */
+	if (strncmp(hdr->magic,"MS3D000000",10) != 0)
+		return PICO_PMV_ERROR_IDENT;
+
+	/* check ms3d version */
+	if (_pico_little_long(hdr->version) < 3 ||
+		_pico_little_long(hdr->version) > 4)
+	{
+		_pico_printf( PICO_ERROR,"MS3D file ignored. Only MS3D 1.3 and 1.4 is supported." );
+		return PICO_PMV_ERROR_VERSION;
+	}
+	/* file seems to be a valid ms3d */
+	return PICO_PMV_OK;
+}
+
+static unsigned char *GetWord( unsigned char *bufptr, int *out )
+{
+	if (bufptr == NULL) return NULL;
+	*out = _pico_little_short( *(unsigned short *)bufptr );
+	return( bufptr + 2 );
+}
+
+/* _ms3d_load:
+ *	loads a milkshape3d model file.
+*/
+static picoModel_t *_ms3d_load( PM_PARAMS_LOAD )
+{
+	picoModel_t	   *model;
+	unsigned char  *bufptr;
+	int				shaderRefs[ MS3D_MAX_GROUPS ];
+	int				numGroups;
+	int				numMaterials;
+//	unsigned char  *ptrToGroups;
+	int				numVerts;
+	unsigned char  *ptrToVerts;
+	int				numTris;
+	unsigned char  *ptrToTris;
+	int				i,k,m;
+
+	/* create new pico model */
+	model = PicoNewModel();
+	if (model == NULL) return NULL;
+
+	/* do model setup */
+	PicoSetModelFrameNum( model, frameNum );
+	PicoSetModelName( model, fileName );
+	PicoSetModelFileName( model, fileName );
+
+	/* skip header */
+	bufptr = (unsigned char *)buffer + sizeof(TMsHeader);
+
+	/* get number of vertices */
+	bufptr = GetWord( bufptr,&numVerts );
+	ptrToVerts = bufptr;
+
+#ifdef DEBUG_PM_MS3D
+	printf("NumVertices: %d\n",numVerts);
+#endif
+	/* swap verts */
+	for (i=0; i<numVerts; i++)
+	{
+		TMsVertex *vertex;
+		vertex = (TMsVertex *)bufptr;
+		bufptr += sizeof( TMsVertex );
+
+		vertex->xyz[ 0 ] = _pico_little_float( vertex->xyz[ 0 ] );
+		vertex->xyz[ 1 ] = _pico_little_float( vertex->xyz[ 1 ] );
+		vertex->xyz[ 2 ] = _pico_little_float( vertex->xyz[ 2 ] );
+
+#ifdef DEBUG_PM_MS3D_EX_
+		printf("Vertex: x: %f y: %f z: %f\n",
+			msvd[i]->vertex[0],
+			msvd[i]->vertex[1],
+			msvd[i]->vertex[2]);
+#endif
+	}
+	/* get number of triangles */
+	bufptr = GetWord( bufptr,&numTris );
+	ptrToTris = bufptr;
+
+#ifdef DEBUG_PM_MS3D
+	printf("NumTriangles: %d\n",numTris);
+#endif
+	/* swap tris */
+	for (i=0; i<numTris; i++)
+	{
+		TMsTriangle *triangle;
+		triangle = (TMsTriangle *)bufptr;
+		bufptr += sizeof( TMsTriangle );
+
+		triangle->flags = _pico_little_short( triangle->flags );
+
+		/* run through all tri verts */
+		for (k=0; k<3; k++)
+		{
+			/* swap tex coords */
+			triangle->s[ k ] = _pico_little_float( triangle->s[ k ] );
+			triangle->t[ k ] = _pico_little_float( triangle->t[ k ] );
+
+			/* swap fields */
+			triangle->vertexIndices[ k ]      = _pico_little_short( triangle->vertexIndices[ k ] );
+			triangle->vertexNormals[ 0 ][ k ] = _pico_little_float( triangle->vertexNormals[ 0 ][ k ] );
+			triangle->vertexNormals[ 1 ][ k ] = _pico_little_float( triangle->vertexNormals[ 1 ][ k ] );
+			triangle->vertexNormals[ 2 ][ k ] = _pico_little_float( triangle->vertexNormals[ 2 ][ k ] );
+
+			/* check for out of range indices */
+			if (triangle->vertexIndices[ k ] >= numVerts)
+			{
+				_pico_printf( PICO_ERROR,"Vertex %d index %d out of range (%d, max %d)",i,k,triangle->vertexIndices[k],numVerts-1);
+				PicoFreeModel( model );
+				return NULL; /* yuck */
+			}
+		}
+	}
+	/* get number of groups */
+	bufptr = GetWord( bufptr,&numGroups );
+//	ptrToGroups = bufptr;
+
+#ifdef DEBUG_PM_MS3D
+	printf("NumGroups: %d\n",numGroups);
+#endif
+	/* run through all groups in model */
+	for (i=0; i<numGroups && i<MS3D_MAX_GROUPS; i++)
+	{
+		picoSurface_t *surface;
+		TMsGroup	  *group;
+
+		group = (TMsGroup *)bufptr;
+		bufptr += sizeof( TMsGroup );
+
+		/* we ignore hidden groups */
+		if (group->flags & MS3D_HIDDEN)
+		{
+			bufptr += (group->numTriangles * 2) + 1;
+			continue;
+		}
+		/* forced null term of group name */
+		group->name[ 31 ] = '\0';
+
+		/* create new pico surface */
+		surface = PicoNewSurface( model );
+		if (surface == NULL)
+		{
+			PicoFreeModel( model );
+			return NULL;
+		}
+		/* do surface setup */
+		PicoSetSurfaceType( surface,PICO_TRIANGLES );
+		PicoSetSurfaceName( surface,group->name );
+
+		/* process triangle indices */
+		for (k=0; k<group->numTriangles; k++)
+		{
+			TMsTriangle *triangle;
+			unsigned int triangleIndex;
+
+			/* get triangle index */
+			bufptr = GetWord( bufptr,(int *)&triangleIndex );
+
+			/* get ptr to triangle data */
+			triangle = (TMsTriangle *)(ptrToTris + (sizeof(TMsTriangle) * triangleIndex));
+
+			/* run through triangle vertices */
+			for (m=0; m<3; m++)
+			{
+				TMsVertex   *vertex;
+				unsigned int vertexIndex;
+				picoVec2_t   texCoord;
+
+				/* get ptr to vertex data */
+				vertexIndex = triangle->vertexIndices[ m ];
+				vertex = (TMsVertex *)(ptrToVerts + (sizeof(TMsVertex) * vertexIndex));
+
+				/* store vertex origin */
+				PicoSetSurfaceXYZ( surface,vertexIndex,vertex->xyz );
+
+				/* store vertex color */
+				PicoSetSurfaceColor( surface,0,vertexIndex,white );
+
+				/* store vertex normal */
+				PicoSetSurfaceNormal( surface,vertexIndex,triangle->vertexNormals[ m ] );
+
+				/* store current face vertex index */
+				PicoSetSurfaceIndex( surface,(k * 3 + (2 - m)),(picoIndex_t)vertexIndex );
+
+				/* get texture vertex coord */
+				texCoord[ 0 ] = triangle->s[ m ];
+				texCoord[ 1 ] = -triangle->t[ m ];	/* flip t */
+
+				/* store texture vertex coord */
+				PicoSetSurfaceST( surface,0,vertexIndex,texCoord );
+			}
+		}
+		/* store material */
+		shaderRefs[ i ] = *bufptr++;
+
+#ifdef DEBUG_PM_MS3D
+		printf("Group %d: '%s' (%d tris)\n",i,group->name,group->numTriangles);
+#endif
+	}
+	/* get number of materials */
+	bufptr = GetWord( bufptr,&numMaterials );
+
+#ifdef DEBUG_PM_MS3D
+	printf("NumMaterials: %d\n",numMaterials);
+#endif
+	/* run through all materials in model */
+	for (i=0; i<numMaterials; i++)
+	{
+		picoShader_t *shader;
+		picoColor_t   ambient,diffuse,specular;
+		TMsMaterial  *material;
+		int           k;
+
+		material = (TMsMaterial *)bufptr;
+		bufptr += sizeof( TMsMaterial );
+
+		/* null term strings */
+		material->name	  [  31 ] = '\0';
+		material->texture [ 127 ] = '\0';
+		material->alphamap[ 127 ] = '\0';
+
+		/* ltrim strings */
+		_pico_strltrim( material->name );
+		_pico_strltrim( material->texture );
+		_pico_strltrim( material->alphamap );
+
+		/* rtrim strings */
+		_pico_strrtrim( material->name );
+		_pico_strrtrim( material->texture );
+		_pico_strrtrim( material->alphamap );
+
+		/* create new pico shader */
+		shader = PicoNewShader( model );
+		if (shader == NULL)
+		{
+			PicoFreeModel( model );
+			return NULL;
+		}
+		/* scale shader colors */
+		for (k=0; k<4; k++)
+		{
+			ambient [ k ] = (picoByte_t) (material->ambient[ k ] * 255);
+			diffuse [ k ] = (picoByte_t) (material->diffuse[ k ] * 255);
+			specular[ k ] = (picoByte_t) (material->specular[ k ] * 255);
+		}
+		/* set shader colors */
+		PicoSetShaderAmbientColor( shader,ambient );
+		PicoSetShaderDiffuseColor( shader,diffuse );
+		PicoSetShaderSpecularColor( shader,specular );
+
+		/* set shader transparency */
+		PicoSetShaderTransparency( shader,material->transparency );
+
+		/* set shader shininess (0..127) */
+		PicoSetShaderShininess( shader,material->shininess );
+
+		/* set shader name */
+		PicoSetShaderName( shader,material->name );
+
+		/* set shader texture map name */
+		PicoSetShaderMapName( shader,material->texture );
+
+#ifdef DEBUG_PM_MS3D
+		printf("Material %d: '%s' ('%s','%s')\n",i,material->name,material->texture,material->alphamap);
+#endif
+	}
+	/* assign shaders to surfaces */
+	for (i=0; i<numGroups && i<MS3D_MAX_GROUPS; i++)
+	{
+		picoSurface_t *surface;
+		picoShader_t  *shader;
+
+		/* sanity check */
+		if (shaderRefs[ i ] >= MS3D_MAX_MATERIALS ||
+			shaderRefs[ i ] < 0)
+			continue;
+
+		/* get surface */
+		surface = PicoGetModelSurface( model,i );
+		if (surface == NULL) continue;
+
+		/* get shader */
+		shader = PicoGetModelShader( model,shaderRefs[ i ] );
+		if (shader == NULL) continue;
+
+		/* assign shader */
+		PicoSetSurfaceShader( surface,shader );
+
+#ifdef DEBUG_PM_MS3D
+		printf("Mapped: %d ('%s') to %d (%s)\n",
+			shaderRefs[i],shader->name,i,surface->name);
+#endif
+	}
+	/* return allocated pico model */
+	return model;
+//	return NULL;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModuleMS3D =
+{
+	"0.4-a",					/* module version string */
+	"Milkshape 3D",				/* module display name */
+	"seaw0lf",					/* author's name */
+	"2002 seaw0lf",				/* module copyright */
+	{
+		"ms3d",NULL,NULL,NULL	/* default extensions to use */
+	},
+	_ms3d_canload,				/* validation routine */
+	_ms3d_load,					/* load routine */
+	 NULL,						/* save validation routine */
+	 NULL						/* save routine */
+};
diff --git a/libs/picomodel/pm_obj.c b/libs/picomodel/pm_obj.c
index 2dc27e1d..6cb40668 100644
--- a/libs/picomodel/pm_obj.c
+++ b/libs/picomodel/pm_obj.c
@@ -1,858 +1,858 @@
-/* -----------------------------------------------------------------------------
-
-PicoModel Library
-
-Copyright (c) 2002, Randy Reddig & seaw0lf
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the names of the copyright holders nor the names of its contributors may
-be used to endorse or promote products derived from this software without
-specific prior written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
------------------------------------------------------------------------------ */
-
-
-
-/* marker */
-#define PM_OBJ_C
-
-/* dependencies */
-#include "picointernal.h"
-
-/* disable warnings */
-#ifdef _WIN32
-#pragma warning( disable:4100 )		/* unref param */
-#endif
-
-/* todo:
- * - '_obj_load' code crashes in a weird way after
- *   '_obj_mtl_load' for a few .mtl files
- * - process 'mtllib' rather than using <model>.mtl
- * - handle 'usemtl' statements
- */
-/* uncomment when debugging this module */
-/* #define DEBUG_PM_OBJ */
-/* #define DEBUG_PM_OBJ_EX */
-
-/* this holds temporary vertex data read by parser */
-typedef struct SObjVertexData
-{
-	picoVec3_t	v;			/* geometric vertices */
-	picoVec2_t	vt;			/* texture vertices */
-	picoVec3_t	vn;			/* vertex normals (optional) */
-}
-TObjVertexData;
-
-/* _obj_canload:
- *  validates a wavefront obj model file.
- */
-static int _obj_canload( PM_PARAMS_CANLOAD )
-{
-	picoParser_t *p;
-
-	/* check data length */
-	if (bufSize < 30)
-		return PICO_PMV_ERROR_SIZE;
-
-	/* first check file extension. we have to do this for objs */
-	/* cause there is no good way to identify the contents */
-	if (_pico_stristr(fileName,".obj") != NULL ||
-		_pico_stristr(fileName,".wf" ) != NULL)
-	{
-		return PICO_PMV_OK;
-	}
-	/* if the extension check failed we parse through the first */
-	/* few lines in file and look for common keywords often */
-	/* appearing at the beginning of wavefront objects */
-
-	/* alllocate a new pico parser */
-	p = _pico_new_parser( (picoByte_t *)buffer,bufSize );
-	if (p == NULL)
-		return PICO_PMV_ERROR_MEMORY;
-
-	/* parse obj head line by line for type check */
-	while( 1 )
-	{
-		/* get first token on line */
-		if (_pico_parse_first( p ) == NULL)
-			break;
-
-		/* we only parse the first few lines, say 80 */
-		if (p->curLine > 80)
-			break;
-
-		/* skip empty lines */
-		if (p->token == NULL || !strlen( p->token ))
-			continue;
-
-		/* material library keywords are teh good */
-		if (!_pico_stricmp(p->token,"usemtl") ||
-			!_pico_stricmp(p->token,"mtllib") ||
-			!_pico_stricmp(p->token,"g") ||
-			!_pico_stricmp(p->token,"v"))	/* v,g bit fishy, but uh... */
-		{
-			/* free the pico parser thing */
-			_pico_free_parser( p );
-
-			/* seems to be a valid wavefront obj */
-			return PICO_PMV_OK;
-		}
-		/* skip rest of line */
-		_pico_parse_skip_rest( p );
-	}
-	/* free the pico parser thing */
-	_pico_free_parser( p );
-
-	/* doesn't really look like an obj to us */
-	return PICO_PMV_ERROR;
-}
-
-/* SizeObjVertexData:
- *   This pretty piece of 'alloc ahead' code dynamically
- *   allocates - and reallocates as soon as required -
- *   my vertex data array in even steps.
- */
-#define SIZE_OBJ_STEP  4096
-
-static TObjVertexData *SizeObjVertexData(
-	TObjVertexData *vertexData, int reqEntries,
-	int *entries, int *allocated)
-{
-	int newAllocated;
-
-	/* sanity checks */
-	if (reqEntries < 1)
-		return NULL;
-	if (entries == NULL || allocated == NULL)
-		return NULL; /* must have */
-
-	/* no need to grow yet */
-	if (vertexData && (reqEntries < *allocated))
-	{
-		*entries = reqEntries;
-		return vertexData;
-	}
-	/* given vertex data ptr not allocated yet */
-	if (vertexData == NULL)
-	{
-		/* how many entries to allocate */
-		newAllocated = (reqEntries > SIZE_OBJ_STEP) ?
-						reqEntries : SIZE_OBJ_STEP;
-
-		/* throw out an extended debug message */
-#ifdef DEBUG_PM_OBJ_EX
-		printf("SizeObjVertexData: allocate (%d entries)\n",
-			newAllocated);
-#endif
-		/* first time allocation */
-		vertexData = (TObjVertexData *)
-			_pico_alloc( sizeof(TObjVertexData) * newAllocated );
-
-		/* allocation failed */
-		if (vertexData == NULL)
-			return NULL;
-
-		/* allocation succeeded */
-		*allocated = newAllocated;
-		*entries   = reqEntries;
-		return vertexData;
-	}
-	/* given vertex data ptr needs to be resized */
-	if (reqEntries == *allocated)
-	{
-		newAllocated = (*allocated + SIZE_OBJ_STEP);
-
-		/* throw out an extended debug message */
-#ifdef DEBUG_PM_OBJ_EX
-		printf("SizeObjVertexData: reallocate (%d entries)\n",
-			newAllocated);
-#endif
-		/* try to reallocate */
-		vertexData = (TObjVertexData *)
-			_pico_realloc( (void *)&vertexData,
-				sizeof(TObjVertexData) * (*allocated),
-				sizeof(TObjVertexData) * (newAllocated));
-
-		/* reallocation failed */
-		if (vertexData == NULL)
-			return NULL;
-
-		/* reallocation succeeded */
-		*allocated = newAllocated;
-		*entries   = reqEntries;
-		return vertexData;
-	}
-	/* we're b0rked when we reach this */
-	return NULL;
-}
-
-static void FreeObjVertexData( TObjVertexData *vertexData )
-{
-	if (vertexData != NULL)
-	{
-		free( (TObjVertexData *)vertexData );
-	}
-}
-
-static int _obj_mtl_load( picoModel_t *model )
-{
-	picoShader_t *curShader = NULL;
-	picoParser_t *p;
-	picoByte_t   *mtlBuffer;
-	int			  mtlBufSize;
-	char		 *fileName;
-
-	/* sanity checks */
-	if( model == NULL || model->fileName == NULL )
-		return 0;
-
-	/* skip if we have a zero length model file name */
-	if (!strlen( model->fileName ))
-		return 0;
-
-	/* helper */
-	#define _obj_mtl_error_return \
-	{ \
-		_pico_free_parser( p ); \
-		_pico_free_file( mtlBuffer ); \
-		_pico_free( fileName ); \
-		return 0; \
-	}
-	/* alloc copy of model file name */
-	fileName = _pico_clone_alloc( model->fileName,-1 );
-	if (fileName == NULL)
-		return 0;
-
-	/* change extension of model file to .mtl */
-	_pico_setfext( fileName, "mtl" );
-
-	/* load .mtl file contents */
-	_pico_load_file( fileName,&mtlBuffer,&mtlBufSize );
-
-	/* check result */
-	if (mtlBufSize == 0) return 1;		/* file is empty: no error */
-	if (mtlBufSize  < 0) return 0;		/* load failed: error */
-
-	/* create a new pico parser */
-	p = _pico_new_parser( mtlBuffer, mtlBufSize );
-	if (p == NULL)
-		_obj_mtl_error_return;
-	
-	/* doo teh .mtl parse */
-	while( 1 )
-	{
-		/* get next token in material file */
-		if (_pico_parse( p,1 ) == NULL)
-			break;
-#if 0
-
-		/* skip empty lines */
-		if (p->token == NULL || !strlen( p->token ))
-			continue;
-
-		/* skip comment lines */
-		if (p->token[0] == '#')
-		{
-			_pico_parse_skip_rest( p );
-			continue;
-		}
-		/* new material */
-		if (!_pico_stricmp(p->token,"newmtl"))
-		{
-			picoShader_t *shader;
-			char *name;
-
-			/* get material name */
-			name = _pico_parse( p,0 );
-
-			/* validate material name */
-			if (name == NULL || !strlen(name))
-			{
-				_pico_printf( PICO_ERROR,"Missing material name in MTL, line %d.",p->curLine);
-				_obj_mtl_error_return;
-			}
-			/* create a new pico shader */
-			shader = PicoNewShader( model );
-			if (shader == NULL)
-				_obj_mtl_error_return;
-
-			/* set shader name */
-			PicoSetShaderName( shader,name );
-
-			/* assign pointer to current shader */
-			curShader = shader;
-		}
-		/* diffuse map name */
-		else if (!_pico_stricmp(p->token,"map_kd"))
-		{
-			char *mapName;
-
-			/* pointer to current shader must be valid */
-			if (curShader == NULL)
-				_obj_mtl_error_return;
-
-			/* get material's diffuse map name */
-			mapName = _pico_parse( p,0 );
-
-			/* validate map name */
-			if (mapName == NULL || !strlen(mapName))
-			{
-				_pico_printf( PICO_ERROR,"Missing material map name in MTL, line %d.",p->curLine);
-				_obj_mtl_error_return;
-			}
-			/* set shader map name */
-			PicoSetShaderMapName( shader,mapName );
-		}
-		/* dissolve factor (pseudo transparency 0..1) */
-		/* where 0 means 100% transparent and 1 means opaque */
-		else if (!_pico_stricmp(p->token,"d"))
-		{
-			picoByte_t *diffuse;
-			float value;
-
-
-			/* get dissolve factor */
-			if (!_pico_parse_float( p,&value ))
-				_obj_mtl_error_return;
-
-			/* set shader transparency */
-			PicoSetShaderTransparency( curShader,value );
-
-			/* get shader's diffuse color */
-			diffuse = PicoGetShaderDiffuseColor( curShader );
-
-			/* set diffuse alpha to transparency */
-			diffuse[ 3 ] = (picoByte_t)( value * 255.0 );
-
-			/* set shader's new diffuse color */
-			PicoSetShaderDiffuseColor( curShader,diffuse );
-		}
-		/* shininess (phong specular component) */
-		else if (!_pico_stricmp(p->token,"ns"))
-		{
-			/* remark:
-			 * - well, this is some major obj spec fuckup once again. some
-			 *   apps store this in 0..1 range, others use 0..100 range,
-			 *   even others use 0..2048 range, and again others use the
-			 *   range 0..128, some even use 0..1000, 0..200, 400..700,
-			 *   honestly, what's up with the 3d app coders? happens when
-			 *   you smoke too much weed i guess. -sea
-			 */
-			float value;
-
-			/* pointer to current shader must be valid */
-			if (curShader == NULL)
-				_obj_mtl_error_return;
-
-			/* get totally screwed up shininess (a random value in fact ;) */
-			if (!_pico_parse_float( p,&value ))
-				_obj_mtl_error_return;
-
-			/* okay, there is no way to set this correctly, so we simply */
-			/* try to guess a few ranges (most common ones i have seen) */
-
-			/* assume 0..2048 range */
-			if (value > 1000)
-				value = 128.0 * (value / 2048.0);
-			/* assume 0..1000 range */
-			else if (value > 200)
-				value = 128.0 * (value / 1000.0);
-			/* assume 0..200 range */
-			else if (value > 100)
-				value = 128.0 * (value / 200.0);
-			/* assume 0..100 range */
-			else if (value > 1)
-				value = 128.0 * (value / 100.0);
-			/* assume 0..1 range */
-			else {
-				value *= 128.0;
-			}
-			/* negative shininess is bad (yes, i have seen it...) */
-			if (value < 0.0) value = 0.0;
-
-			/* set the pico shininess value in range 0..127 */
-			/* geez, .obj is such a mess... */
-			PicoSetShaderShininess( curShader,value );
-		}
-		/* kol0r ambient (wut teh fuk does "ka" stand for?) */
-		else if (!_pico_stricmp(p->token,"ka"))
-		{
-			picoColor_t color;
-			picoVec3_t  v;
-
-			/* pointer to current shader must be valid */
-			if (curShader == NULL)
-				_obj_mtl_error_return;
-
-			/* get color vector */
-			if (!_pico_parse_vec( p,v ))
-				_obj_mtl_error_return;
-
-			/* scale to byte range */
-			color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 );
-			color[ 1 ] = (picoByte_t)( v[ 1 ] * 255 );
-			color[ 2 ] = (picoByte_t)( v[ 2 ] * 255 );
-			color[ 3 ] = (picoByte_t)( 255 );
-
-			/* set ambient color */
-			PicoSetShaderAmbientColor( curShader,color );
-		}
-		/* kol0r diffuse */
-		else if (!_pico_stricmp(p->token,"kd"))
-		{
-			picoColor_t color;
-			picoVec3_t  v;
-
-			/* pointer to current shader must be valid */
-			if (curShader == NULL)
-				_obj_mtl_error_return;
-
-			/* get color vector */
-			if (!_pico_parse_vec( p,v ))
-				_obj_mtl_error_return;
-
-			/* scale to byte range */
-			color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 );
-			color[ 1 ] = (picoByte_t)( v[ 1 ] * 255 );
-			color[ 2 ] = (picoByte_t)( v[ 2 ] * 255 );
-			color[ 3 ] = (picoByte_t)( 255 );
-
-			/* set diffuse color */
-			PicoSetShaderDiffuseColor( curShader,color );
-		}
-		/* kol0r specular */
-		else if (!_pico_stricmp(p->token,"ks"))
-		{
-			picoColor_t color;
-			picoVec3_t  v;
-
-			/* pointer to current shader must be valid */
-			if (curShader == NULL)
-				_obj_mtl_error_return;
-
-			/* get color vector */
-			if (!_pico_parse_vec( p,v ))
-				_obj_mtl_error_return;
-
-			/* scale to byte range */
-			color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 );
-			color[ 1 ] = (picoByte_t)( v[ 1 ] * 255 );
-			color[ 2 ] = (picoByte_t)( v[ 2 ] * 255 );
-			color[ 3 ] = (picoByte_t)( 255 );
-
-			/* set specular color */
-			PicoSetShaderSpecularColor( curShader,color );
-		}
-#endif
-		/* skip rest of line */
-		_pico_parse_skip_rest( p );
-	}
-
-	/* free parser, file buffer, and file name */
-	_pico_free_parser( p );
-	_pico_free_file( mtlBuffer );
-	_pico_free( fileName );
-
-	/* return with success */
-	return 1;
-}
-
-/* _obj_load:
- *  loads a wavefront obj model file.
-*/
-static picoModel_t *_obj_load( PM_PARAMS_LOAD )
-{
-	TObjVertexData *vertexData  = NULL;
-	picoModel_t    *model;
-	picoSurface_t  *curSurface  = NULL;
-	picoParser_t   *p;
-	int				allocated;
-	int			    entries;
-	int				numVerts   	= 0;
-	int				numNormals 	= 0;
-	int				numUVs	   	= 0;
-	int				curVertex	= 0;
-	int				curFace		= 0;
-
-	/* helper */
-	#define _obj_error_return(m) \
-	{ \
-		_pico_printf( PICO_ERROR,"%s in OBJ, line %d.",m,p->curLine); \
-		_pico_free_parser( p ); \
-		FreeObjVertexData( vertexData ); \
-		PicoFreeModel( model ); \
-		return NULL; \
-	}
-	/* alllocate a new pico parser */
-	p = _pico_new_parser( (picoByte_t *)buffer,bufSize );
-	if (p == NULL) return NULL;
-
-	/* create a new pico model */
-	model = PicoNewModel();
-	if (model == NULL)
-	{
-		_pico_free_parser( p );
-		return NULL;
-	}
-	/* do model setup */
-	PicoSetModelFrameNum( model,frameNum );
-	PicoSetModelName( model,fileName );
-	PicoSetModelFileName( model,fileName );
-
-	/* try loading the materials; we don't handle the result */
-#if 0
-	_obj_mtl_load( model );
-#endif
-
-	/* parse obj line by line */
-	while( 1 )
-	{
-		/* get first token on line */
-		if (_pico_parse_first( p ) == NULL)
-			break;
-
-		/* skip empty lines */
-		if (p->token == NULL || !strlen( p->token ))
-			continue;
-
-		/* skip comment lines */
-		if (p->token[0] == '#')
-		{
-			_pico_parse_skip_rest( p );
-			continue;
-		}
-		/* vertex */
-		if (!_pico_stricmp(p->token,"v"))
-		{
-			TObjVertexData *data;
-			picoVec3_t v;
-
-			vertexData = SizeObjVertexData( vertexData,numVerts+1,&entries,&allocated );
-			if (vertexData == NULL)
-				_obj_error_return("Realloc of vertex data failed (1)");
-
-			data = &vertexData[ numVerts++ ];
-
-			/* get and copy vertex */
-			if (!_pico_parse_vec( p,v ))
-				_obj_error_return("Vertex parse error");
-
-			_pico_copy_vec( v,data->v );
-
-#ifdef DEBUG_PM_OBJ_EX
-			printf("Vertex: x: %f y: %f z: %f\n",v[0],v[1],v[2]);
-#endif
-		}
-		/* uv coord */
-		else if (!_pico_stricmp(p->token,"vt"))
-		{
-			TObjVertexData *data;
-			picoVec2_t coord;
-
-			vertexData = SizeObjVertexData( vertexData,numUVs+1,&entries,&allocated );
-			if (vertexData == NULL)
-				_obj_error_return("Realloc of vertex data failed (2)");
-
-			data = &vertexData[ numUVs++ ];
-
-			/* get and copy tex coord */
-			if (!_pico_parse_vec2( p,coord ))
-				_obj_error_return("UV coord parse error");
-
-			_pico_copy_vec2( coord,data->vt );
-
-#ifdef DEBUG_PM_OBJ_EX
-			printf("TexCoord: u: %f v: %f\n",coord[0],coord[1]);
-#endif
-		}
-		/* vertex normal */
-		else if (!_pico_stricmp(p->token,"vn"))
-		{
-			TObjVertexData *data;
-			picoVec3_t n;
-
-			vertexData = SizeObjVertexData( vertexData,numNormals+1,&entries,&allocated );
-			if (vertexData == NULL)
-				_obj_error_return("Realloc of vertex data failed (3)");
-
-			data = &vertexData[ numNormals++ ];
-
-			/* get and copy vertex normal */
-			if (!_pico_parse_vec( p,n ))
-				_obj_error_return("Vertex normal parse error");
-
-			_pico_copy_vec( n,data->vn );
-
-#ifdef DEBUG_PM_OBJ_EX
-			printf("Normal: x: %f y: %f z: %f\n",n[0],n[1],n[2]);
-#endif
-		}
-		/* new group (for us this means a new surface) */
-		else if (!_pico_stricmp(p->token,"g"))
-		{
-			picoSurface_t *newSurface;
-			char *groupName;
-
-			/* get first group name (ignore 2nd,3rd,etc.) */
-			groupName = _pico_parse( p,0 );
-			if (groupName == NULL || !strlen(groupName))
-			{
-				/* some obj exporters feel like they don't need to */
-				/* supply a group name. so we gotta handle it here */
-#if 1
-				strcpy( p->token,"default" );
-				groupName = p->token;
-#else
-				_obj_error_return("Invalid or missing group name");
-#endif
-			}
-			/* allocate a pico surface */
-			newSurface = PicoNewSurface( model );
-			if (newSurface == NULL)
-				_obj_error_return("Error allocating surface");
-
-			/* reset face index for surface */
-			curFace = 0;
-
-			/* set ptr to current surface */
-			curSurface = newSurface;
-
-			/* we use triangle meshes */
-			PicoSetSurfaceType( newSurface,PICO_TRIANGLES );
-
-			/* set surface name */
-			PicoSetSurfaceName( newSurface,groupName );
-
-#ifdef DEBUG_PM_OBJ_EX
-			printf("Group: '%s'\n",groupName);
-#endif
-		}
-		/* face (oh jesus, hopefully this will do the job right ;) */
-		else if (!_pico_stricmp(p->token,"f"))
-		{
-			/* okay, this is a mess. some 3d apps seem to try being unique, */
-			/* hello cinema4d & 3d exploration, feel good today?, and save */
-			/* this crap in tons of different formats. gah, those screwed */
-			/* coders. tho the wavefront obj standard defines exactly two */
-			/* ways of storing face information. so, i really won't support */
-			/* such stupid extravaganza here! */
-
-			picoVec3_t verts  [ 4 ];
-			picoVec3_t normals[ 4 ];
-			picoVec2_t coords [ 4 ];
-
-			int iv [ 4 ], has_v;
-			int ivt[ 4 ], has_vt = 0;
-			int ivn[ 4 ], has_vn = 0;
-			int have_quad = 0;
-			int slashcount;
-			int doubleslash;
-			int i;
-
-			/* group defs *must* come before faces */
-			if (curSurface == NULL)
-				_obj_error_return("No group defined for faces");
-
-#ifdef DEBUG_PM_OBJ_EX
-			printf("Face: ");
-#endif
-			/* read vertex/uv/normal indices for the first three face */
-			/* vertices (cause we only support triangles) into 'i*[]' */
-			/* store the actual vertex/uv/normal data in three arrays */
-			/* called 'verts','coords' and 'normals'. */
-			for (i=0; i<4; i++)
-			{
-				char *str;
-
-				/* get next vertex index string (different */
-				/* formats are handled below) */
-				str = _pico_parse( p,0 );
-				if (str == NULL)
-				{
-					/* just break for quads */
-					if (i == 3) break;
-
-					/* error otherwise */
-					_obj_error_return("Face parse error");
-				}
-				/* if this is the fourth index string we're */
-				/* parsing we assume that we have a quad */
-				if (i == 3)
-					have_quad = 1;
-
-				/* get slash count once */
-				if (i == 0)
-				{
-					slashcount  = _pico_strchcount( str,'/' );
-					doubleslash =  strstr(str,"//") != NULL;
-				}
-				/* handle format 'v//vn' */
-				if (doubleslash && (slashcount == 2))
-				{
-					has_v = has_vn = 1;
-					sscanf( str,"%d//%d",&iv[ i ],&ivn[ i ] );
-				}
-				/* handle format 'v/vt/vn' */
-				else if (!doubleslash && (slashcount == 2))
-				{
-					has_v = has_vt = has_vn = 1;
-					sscanf( str,"%d/%d/%d",&iv[ i ],&ivt[ i ],&ivn[ i ] );
-				}
-				/* handle format 'v/vt' (non-standard fuckage) */
-				else if (!doubleslash && (slashcount == 1))
-				{
-					has_v = has_vt = 1;
-					sscanf( str,"%d/%d",&iv[ i ],&ivt[ i ] );
-				}
-				/* else assume face format 'v' */
-				/* (must have been invented by some bored granny) */
-				else {
-					/* get single vertex index */
-					has_v = 1;
-					iv[ i ] = atoi( str );
-
-					/* either invalid face format or out of range */
-					if (iv[ i ] == 0)
-						_obj_error_return("Invalid face format");
-				}
-				/* fix useless back references */
-				/* todo: check if this works as it is supposed to */
-
-				/* assign new indices */
-				if (iv [ i ] < 0) iv [ i ] = (numVerts   - iv [ i ]);
-				if (ivt[ i ] < 0) ivt[ i ] = (numUVs	 - ivt[ i ]);
-				if (ivn[ i ] < 0) ivn[ i ] = (numNormals - ivn[ i ]);
-
-				/* validate indices */
-				/* - commented out. index range checks will trigger
-				if (iv [ i ] < 1) iv [ i ] = 1;
-				if (ivt[ i ] < 1) ivt[ i ] = 1;
-				if (ivn[ i ] < 1) ivn[ i ] = 1;
-				*/
-				/* set vertex origin */
-				if (has_v)
-				{
-					/* check vertex index range */
-					if (iv[ i ] < 1 || iv[ i ] > numVerts)
-						_obj_error_return("Vertex index out of range");
-
-					/* get vertex data */
-					verts[ i ][ 0 ] = vertexData[ iv[ i ] - 1 ].v[ 0 ];
-					verts[ i ][ 1 ] = vertexData[ iv[ i ] - 1 ].v[ 1 ];
-					verts[ i ][ 2 ] = vertexData[ iv[ i ] - 1 ].v[ 2 ];
-				}
-				/* set vertex normal */
-				if (has_vn)
-				{
-					/* check normal index range */
-					if (ivn[ i ] < 1 || ivn[ i ] > numNormals)
-						_obj_error_return("Normal index out of range");
-
-					/* get normal data */
-					normals[ i ][ 0 ] = vertexData[ ivn[ i ] - 1 ].vn[ 0 ];
-					normals[ i ][ 1 ] = vertexData[ ivn[ i ] - 1 ].vn[ 1 ];
-					normals[ i ][ 2 ] = vertexData[ ivn[ i ] - 1 ].vn[ 2 ];
-				}
-				/* set texture coordinate */
-				if (has_vt)
-				{
-					/* check uv index range */
-					if (ivt[ i ] < 1 || ivt[ i ] > numUVs)
-						_obj_error_return("UV coord index out of range");
-
-					/* get uv coord data */
-					coords[ i ][ 0 ] = vertexData[ ivt[ i ] - 1 ].vt[ 0 ];
-					coords[ i ][ 1 ] = vertexData[ ivt[ i ] - 1 ].vt[ 1 ];
-					coords[ i ][ 1 ] = -coords[ i ][ 1 ];
-				}
-#ifdef DEBUG_PM_OBJ_EX
-				printf("(%4d",iv[ i ]);
-				if (has_vt) printf(" %4d",ivt[ i ]);
-				if (has_vn) printf(" %4d",ivn[ i ]);
-				printf(") ");
-#endif
-			}
-#ifdef DEBUG_PM_OBJ_EX
-			printf("\n");
-#endif
-			/* now that we have extracted all the indices and have */
-			/* read the actual data we need to assign all the crap */
-			/* to our current pico surface */
-			if (has_v)
-			{
-				int max = 3;
-				if (have_quad) max = 4;
-
-				/* assign all surface information */
-				for (i=0; i<max; i++)
-				{
-					/*if( has_v  )*/ PicoSetSurfaceXYZ	 ( curSurface,  (curVertex + i), verts  [ i ] );
-					/*if( has_vt )*/ PicoSetSurfaceST	 ( curSurface,0,(curVertex + i), coords [ i ] );
-					/*if( has_vn )*/ PicoSetSurfaceNormal( curSurface,  (curVertex + i), normals[ i ] );
-				}
-				/* add our triangle (A B C) */
-				PicoSetSurfaceIndex( curSurface,(curFace * 3 + 2),(picoIndex_t)( curVertex + 0 ) );
-				PicoSetSurfaceIndex( curSurface,(curFace * 3 + 1),(picoIndex_t)( curVertex + 1 ) );
-				PicoSetSurfaceIndex( curSurface,(curFace * 3 + 0),(picoIndex_t)( curVertex + 2 ) );
-				curFace++;
-
-				/* if we don't have a simple triangle, but a quad... */
-				if (have_quad)
-				{
-					/* we have to add another triangle (2nd half of quad which is A C D) */
-					PicoSetSurfaceIndex( curSurface,(curFace * 3 + 2),(picoIndex_t)( curVertex + 0 ) );
-					PicoSetSurfaceIndex( curSurface,(curFace * 3 + 1),(picoIndex_t)( curVertex + 2 ) );
-					PicoSetSurfaceIndex( curSurface,(curFace * 3 + 0),(picoIndex_t)( curVertex + 3 ) );
-					curFace++;
-				}
-				/* increase vertex count */
-				curVertex += max;
-			}
-		}
-		/* skip unparsed rest of line and continue */
-		_pico_parse_skip_rest( p );
-	}
-	/* free memory used by temporary vertexdata */
-	FreeObjVertexData( vertexData );
-
-	/* return allocated pico model */
-	return model;
-//	return NULL;
-}
-
-/* pico file format module definition */
-const picoModule_t picoModuleOBJ =
-{
-	"0.6-b",					/* module version string */
-	"Wavefront ASCII",			/* module display name */
-	"seaw0lf",					/* author's name */
-	"2002 seaw0lf",				/* module copyright */
-	{
-		"obj",NULL,NULL,NULL	/* default extensions to use */
-	},
-	_obj_canload,				/* validation routine */
-	_obj_load,					/* load routine */
-	 NULL,						/* save validation routine */
-	 NULL						/* save routine */
-};
+/* -----------------------------------------------------------------------------
+
+PicoModel Library
+
+Copyright (c) 2002, Randy Reddig & seaw0lf
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the names of the copyright holders nor the names of its contributors may
+be used to endorse or promote products derived from this software without
+specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
+ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+----------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PM_OBJ_C
+
+/* dependencies */
+#include "picointernal.h"
+
+/* disable warnings */
+#ifdef _WIN32
+#pragma warning( disable:4100 )		/* unref param */
+#endif
+
+/* todo:
+ * - '_obj_load' code crashes in a weird way after
+ *   '_obj_mtl_load' for a few .mtl files
+ * - process 'mtllib' rather than using <model>.mtl
+ * - handle 'usemtl' statements
+ */
+/* uncomment when debugging this module */
+/* #define DEBUG_PM_OBJ */
+/* #define DEBUG_PM_OBJ_EX */
+
+/* this holds temporary vertex data read by parser */
+typedef struct SObjVertexData
+{
+	picoVec3_t	v;			/* geometric vertices */
+	picoVec2_t	vt;			/* texture vertices */
+	picoVec3_t	vn;			/* vertex normals (optional) */
+}
+TObjVertexData;
+
+/* _obj_canload:
+ *  validates a wavefront obj model file.
+ */
+static int _obj_canload( PM_PARAMS_CANLOAD )
+{
+	picoParser_t *p;
+
+	/* check data length */
+	if (bufSize < 30)
+		return PICO_PMV_ERROR_SIZE;
+
+	/* first check file extension. we have to do this for objs */
+	/* cause there is no good way to identify the contents */
+	if (_pico_stristr(fileName,".obj") != NULL ||
+		_pico_stristr(fileName,".wf" ) != NULL)
+	{
+		return PICO_PMV_OK;
+	}
+	/* if the extension check failed we parse through the first */
+	/* few lines in file and look for common keywords often */
+	/* appearing at the beginning of wavefront objects */
+
+	/* alllocate a new pico parser */
+	p = _pico_new_parser( (picoByte_t *)buffer,bufSize );
+	if (p == NULL)
+		return PICO_PMV_ERROR_MEMORY;
+
+	/* parse obj head line by line for type check */
+	while( 1 )
+	{
+		/* get first token on line */
+		if (_pico_parse_first( p ) == NULL)
+			break;
+
+		/* we only parse the first few lines, say 80 */
+		if (p->curLine > 80)
+			break;
+
+		/* skip empty lines */
+		if (p->token == NULL || !strlen( p->token ))
+			continue;
+
+		/* material library keywords are teh good */
+		if (!_pico_stricmp(p->token,"usemtl") ||
+			!_pico_stricmp(p->token,"mtllib") ||
+			!_pico_stricmp(p->token,"g") ||
+			!_pico_stricmp(p->token,"v"))	/* v,g bit fishy, but uh... */
+		{
+			/* free the pico parser thing */
+			_pico_free_parser( p );
+
+			/* seems to be a valid wavefront obj */
+			return PICO_PMV_OK;
+		}
+		/* skip rest of line */
+		_pico_parse_skip_rest( p );
+	}
+	/* free the pico parser thing */
+	_pico_free_parser( p );
+
+	/* doesn't really look like an obj to us */
+	return PICO_PMV_ERROR;
+}
+
+/* SizeObjVertexData:
+ *   This pretty piece of 'alloc ahead' code dynamically
+ *   allocates - and reallocates as soon as required -
+ *   my vertex data array in even steps.
+ */
+#define SIZE_OBJ_STEP  4096
+
+static TObjVertexData *SizeObjVertexData(
+	TObjVertexData *vertexData, int reqEntries,
+	int *entries, int *allocated)
+{
+	int newAllocated;
+
+	/* sanity checks */
+	if (reqEntries < 1)
+		return NULL;
+	if (entries == NULL || allocated == NULL)
+		return NULL; /* must have */
+
+	/* no need to grow yet */
+	if (vertexData && (reqEntries < *allocated))
+	{
+		*entries = reqEntries;
+		return vertexData;
+	}
+	/* given vertex data ptr not allocated yet */
+	if (vertexData == NULL)
+	{
+		/* how many entries to allocate */
+		newAllocated = (reqEntries > SIZE_OBJ_STEP) ?
+						reqEntries : SIZE_OBJ_STEP;
+
+		/* throw out an extended debug message */
+#ifdef DEBUG_PM_OBJ_EX
+		printf("SizeObjVertexData: allocate (%d entries)\n",
+			newAllocated);
+#endif
+		/* first time allocation */
+		vertexData = (TObjVertexData *)
+			_pico_alloc( sizeof(TObjVertexData) * newAllocated );
+
+		/* allocation failed */
+		if (vertexData == NULL)
+			return NULL;
+
+		/* allocation succeeded */
+		*allocated = newAllocated;
+		*entries   = reqEntries;
+		return vertexData;
+	}
+	/* given vertex data ptr needs to be resized */
+	if (reqEntries == *allocated)
+	{
+		newAllocated = (*allocated + SIZE_OBJ_STEP);
+
+		/* throw out an extended debug message */
+#ifdef DEBUG_PM_OBJ_EX
+		printf("SizeObjVertexData: reallocate (%d entries)\n",
+			newAllocated);
+#endif
+		/* try to reallocate */
+		vertexData = (TObjVertexData *)
+			_pico_realloc( (void *)&vertexData,
+				sizeof(TObjVertexData) * (*allocated),
+				sizeof(TObjVertexData) * (newAllocated));
+
+		/* reallocation failed */
+		if (vertexData == NULL)
+			return NULL;
+
+		/* reallocation succeeded */
+		*allocated = newAllocated;
+		*entries   = reqEntries;
+		return vertexData;
+	}
+	/* we're b0rked when we reach this */
+	return NULL;
+}
+
+static void FreeObjVertexData( TObjVertexData *vertexData )
+{
+	if (vertexData != NULL)
+	{
+		free( (TObjVertexData *)vertexData );
+	}
+}
+
+static int _obj_mtl_load( picoModel_t *model )
+{
+	picoShader_t *curShader = NULL;
+	picoParser_t *p;
+	picoByte_t   *mtlBuffer;
+	int			  mtlBufSize;
+	char		 *fileName;
+
+	/* sanity checks */
+	if( model == NULL || model->fileName == NULL )
+		return 0;
+
+	/* skip if we have a zero length model file name */
+	if (!strlen( model->fileName ))
+		return 0;
+
+	/* helper */
+	#define _obj_mtl_error_return \
+	{ \
+		_pico_free_parser( p ); \
+		_pico_free_file( mtlBuffer ); \
+		_pico_free( fileName ); \
+		return 0; \
+	}
+	/* alloc copy of model file name */
+	fileName = _pico_clone_alloc( model->fileName,-1 );
+	if (fileName == NULL)
+		return 0;
+
+	/* change extension of model file to .mtl */
+	_pico_setfext( fileName, "mtl" );
+
+	/* load .mtl file contents */
+	_pico_load_file( fileName,&mtlBuffer,&mtlBufSize );
+
+	/* check result */
+	if (mtlBufSize == 0) return 1;		/* file is empty: no error */
+	if (mtlBufSize  < 0) return 0;		/* load failed: error */
+
+	/* create a new pico parser */
+	p = _pico_new_parser( mtlBuffer, mtlBufSize );
+	if (p == NULL)
+		_obj_mtl_error_return;
+	
+	/* doo teh .mtl parse */
+	while( 1 )
+	{
+		/* get next token in material file */
+		if (_pico_parse( p,1 ) == NULL)
+			break;
+#if 0
+
+		/* skip empty lines */
+		if (p->token == NULL || !strlen( p->token ))
+			continue;
+
+		/* skip comment lines */
+		if (p->token[0] == '#')
+		{
+			_pico_parse_skip_rest( p );
+			continue;
+		}
+		/* new material */
+		if (!_pico_stricmp(p->token,"newmtl"))
+		{
+			picoShader_t *shader;
+			char *name;
+
+			/* get material name */
+			name = _pico_parse( p,0 );
+
+			/* validate material name */
+			if (name == NULL || !strlen(name))
+			{
+				_pico_printf( PICO_ERROR,"Missing material name in MTL, line %d.",p->curLine);
+				_obj_mtl_error_return;
+			}
+			/* create a new pico shader */
+			shader = PicoNewShader( model );
+			if (shader == NULL)
+				_obj_mtl_error_return;
+
+			/* set shader name */
+			PicoSetShaderName( shader,name );
+
+			/* assign pointer to current shader */
+			curShader = shader;
+		}
+		/* diffuse map name */
+		else if (!_pico_stricmp(p->token,"map_kd"))
+		{
+			char *mapName;
+
+			/* pointer to current shader must be valid */
+			if (curShader == NULL)
+				_obj_mtl_error_return;
+
+			/* get material's diffuse map name */
+			mapName = _pico_parse( p,0 );
+
+			/* validate map name */
+			if (mapName == NULL || !strlen(mapName))
+			{
+				_pico_printf( PICO_ERROR,"Missing material map name in MTL, line %d.",p->curLine);
+				_obj_mtl_error_return;
+			}
+			/* set shader map name */
+			PicoSetShaderMapName( shader,mapName );
+		}
+		/* dissolve factor (pseudo transparency 0..1) */
+		/* where 0 means 100% transparent and 1 means opaque */
+		else if (!_pico_stricmp(p->token,"d"))
+		{
+			picoByte_t *diffuse;
+			float value;
+
+
+			/* get dissolve factor */
+			if (!_pico_parse_float( p,&value ))
+				_obj_mtl_error_return;
+
+			/* set shader transparency */
+			PicoSetShaderTransparency( curShader,value );
+
+			/* get shader's diffuse color */
+			diffuse = PicoGetShaderDiffuseColor( curShader );
+
+			/* set diffuse alpha to transparency */
+			diffuse[ 3 ] = (picoByte_t)( value * 255.0 );
+
+			/* set shader's new diffuse color */
+			PicoSetShaderDiffuseColor( curShader,diffuse );
+		}
+		/* shininess (phong specular component) */
+		else if (!_pico_stricmp(p->token,"ns"))
+		{
+			/* remark:
+			 * - well, this is some major obj spec fuckup once again. some
+			 *   apps store this in 0..1 range, others use 0..100 range,
+			 *   even others use 0..2048 range, and again others use the
+			 *   range 0..128, some even use 0..1000, 0..200, 400..700,
+			 *   honestly, what's up with the 3d app coders? happens when
+			 *   you smoke too much weed i guess. -sea
+			 */
+			float value;
+
+			/* pointer to current shader must be valid */
+			if (curShader == NULL)
+				_obj_mtl_error_return;
+
+			/* get totally screwed up shininess (a random value in fact ;) */
+			if (!_pico_parse_float( p,&value ))
+				_obj_mtl_error_return;
+
+			/* okay, there is no way to set this correctly, so we simply */
+			/* try to guess a few ranges (most common ones i have seen) */
+
+			/* assume 0..2048 range */
+			if (value > 1000)
+				value = 128.0 * (value / 2048.0);
+			/* assume 0..1000 range */
+			else if (value > 200)
+				value = 128.0 * (value / 1000.0);
+			/* assume 0..200 range */
+			else if (value > 100)
+				value = 128.0 * (value / 200.0);
+			/* assume 0..100 range */
+			else if (value > 1)
+				value = 128.0 * (value / 100.0);
+			/* assume 0..1 range */
+			else {
+				value *= 128.0;
+			}
+			/* negative shininess is bad (yes, i have seen it...) */
+			if (value < 0.0) value = 0.0;
+
+			/* set the pico shininess value in range 0..127 */
+			/* geez, .obj is such a mess... */
+			PicoSetShaderShininess( curShader,value );
+		}
+		/* kol0r ambient (wut teh fuk does "ka" stand for?) */
+		else if (!_pico_stricmp(p->token,"ka"))
+		{
+			picoColor_t color;
+			picoVec3_t  v;
+
+			/* pointer to current shader must be valid */
+			if (curShader == NULL)
+				_obj_mtl_error_return;
+
+			/* get color vector */
+			if (!_pico_parse_vec( p,v ))
+				_obj_mtl_error_return;
+
+			/* scale to byte range */
+			color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 );
+			color[ 1 ] = (picoByte_t)( v[ 1 ] * 255 );
+			color[ 2 ] = (picoByte_t)( v[ 2 ] * 255 );
+			color[ 3 ] = (picoByte_t)( 255 );
+
+			/* set ambient color */
+			PicoSetShaderAmbientColor( curShader,color );
+		}
+		/* kol0r diffuse */
+		else if (!_pico_stricmp(p->token,"kd"))
+		{
+			picoColor_t color;
+			picoVec3_t  v;
+
+			/* pointer to current shader must be valid */
+			if (curShader == NULL)
+				_obj_mtl_error_return;
+
+			/* get color vector */
+			if (!_pico_parse_vec( p,v ))
+				_obj_mtl_error_return;
+
+			/* scale to byte range */
+			color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 );
+			color[ 1 ] = (picoByte_t)( v[ 1 ] * 255 );
+			color[ 2 ] = (picoByte_t)( v[ 2 ] * 255 );
+			color[ 3 ] = (picoByte_t)( 255 );
+
+			/* set diffuse color */
+			PicoSetShaderDiffuseColor( curShader,color );
+		}
+		/* kol0r specular */
+		else if (!_pico_stricmp(p->token,"ks"))
+		{
+			picoColor_t color;
+			picoVec3_t  v;
+
+			/* pointer to current shader must be valid */
+			if (curShader == NULL)
+				_obj_mtl_error_return;
+
+			/* get color vector */
+			if (!_pico_parse_vec( p,v ))
+				_obj_mtl_error_return;
+
+			/* scale to byte range */
+			color[ 0 ] = (picoByte_t)( v[ 0 ] * 255 );
+			color[ 1 ] = (picoByte_t)( v[ 1 ] * 255 );
+			color[ 2 ] = (picoByte_t)( v[ 2 ] * 255 );
+			color[ 3 ] = (picoByte_t)( 255 );
+
+			/* set specular color */
+			PicoSetShaderSpecularColor( curShader,color );
+		}
+#endif
+		/* skip rest of line */
+		_pico_parse_skip_rest( p );
+	}
+
+	/* free parser, file buffer, and file name */
+	_pico_free_parser( p );
+	_pico_free_file( mtlBuffer );
+	_pico_free( fileName );
+
+	/* return with success */
+	return 1;
+}
+
+/* _obj_load:
+ *  loads a wavefront obj model file.
+*/
+static picoModel_t *_obj_load( PM_PARAMS_LOAD )
+{
+	TObjVertexData *vertexData  = NULL;
+	picoModel_t    *model;
+	picoSurface_t  *curSurface  = NULL;
+	picoParser_t   *p;
+	int				allocated;
+	int			    entries;
+	int				numVerts   	= 0;
+	int				numNormals 	= 0;
+	int				numUVs	   	= 0;
+	int				curVertex	= 0;
+	int				curFace		= 0;
+
+	/* helper */
+	#define _obj_error_return(m) \
+	{ \
+		_pico_printf( PICO_ERROR,"%s in OBJ, line %d.",m,p->curLine); \
+		_pico_free_parser( p ); \
+		FreeObjVertexData( vertexData ); \
+		PicoFreeModel( model ); \
+		return NULL; \
+	}
+	/* alllocate a new pico parser */
+	p = _pico_new_parser( (picoByte_t *)buffer,bufSize );
+	if (p == NULL) return NULL;
+
+	/* create a new pico model */
+	model = PicoNewModel();
+	if (model == NULL)
+	{
+		_pico_free_parser( p );
+		return NULL;
+	}
+	/* do model setup */
+	PicoSetModelFrameNum( model,frameNum );
+	PicoSetModelName( model,fileName );
+	PicoSetModelFileName( model,fileName );
+
+	/* try loading the materials; we don't handle the result */
+#if 0
+	_obj_mtl_load( model );
+#endif
+
+	/* parse obj line by line */
+	while( 1 )
+	{
+		/* get first token on line */
+		if (_pico_parse_first( p ) == NULL)
+			break;
+
+		/* skip empty lines */
+		if (p->token == NULL || !strlen( p->token ))
+			continue;
+
+		/* skip comment lines */
+		if (p->token[0] == '#')
+		{
+			_pico_parse_skip_rest( p );
+			continue;
+		}
+		/* vertex */
+		if (!_pico_stricmp(p->token,"v"))
+		{
+			TObjVertexData *data;
+			picoVec3_t v;
+
+			vertexData = SizeObjVertexData( vertexData,numVerts+1,&entries,&allocated );
+			if (vertexData == NULL)
+				_obj_error_return("Realloc of vertex data failed (1)");
+
+			data = &vertexData[ numVerts++ ];
+
+			/* get and copy vertex */
+			if (!_pico_parse_vec( p,v ))
+				_obj_error_return("Vertex parse error");
+
+			_pico_copy_vec( v,data->v );
+
+#ifdef DEBUG_PM_OBJ_EX
+			printf("Vertex: x: %f y: %f z: %f\n",v[0],v[1],v[2]);
+#endif
+		}
+		/* uv coord */
+		else if (!_pico_stricmp(p->token,"vt"))
+		{
+			TObjVertexData *data;
+			picoVec2_t coord;
+
+			vertexData = SizeObjVertexData( vertexData,numUVs+1,&entries,&allocated );
+			if (vertexData == NULL)
+				_obj_error_return("Realloc of vertex data failed (2)");
+
+			data = &vertexData[ numUVs++ ];
+
+			/* get and copy tex coord */
+			if (!_pico_parse_vec2( p,coord ))
+				_obj_error_return("UV coord parse error");
+
+			_pico_copy_vec2( coord,data->vt );
+
+#ifdef DEBUG_PM_OBJ_EX
+			printf("TexCoord: u: %f v: %f\n",coord[0],coord[1]);
+#endif
+		}
+		/* vertex normal */
+		else if (!_pico_stricmp(p->token,"vn"))
+		{
+			TObjVertexData *data;
+			picoVec3_t n;
+
+			vertexData = SizeObjVertexData( vertexData,numNormals+1,&entries,&allocated );
+			if (vertexData == NULL)
+				_obj_error_return("Realloc of vertex data failed (3)");
+
+			data = &vertexData[ numNormals++ ];
+
+			/* get and copy vertex normal */
+			if (!_pico_parse_vec( p,n ))
+				_obj_error_return("Vertex normal parse error");
+
+			_pico_copy_vec( n,data->vn );
+
+#ifdef DEBUG_PM_OBJ_EX
+			printf("Normal: x: %f y: %f z: %f\n",n[0],n[1],n[2]);
+#endif
+		}
+		/* new group (for us this means a new surface) */
+		else if (!_pico_stricmp(p->token,"g"))
+		{
+			picoSurface_t *newSurface;
+			char *groupName;
+
+			/* get first group name (ignore 2nd,3rd,etc.) */
+			groupName = _pico_parse( p,0 );
+			if (groupName == NULL || !strlen(groupName))
+			{
+				/* some obj exporters feel like they don't need to */
+				/* supply a group name. so we gotta handle it here */
+#if 1
+				strcpy( p->token,"default" );
+				groupName = p->token;
+#else
+				_obj_error_return("Invalid or missing group name");
+#endif
+			}
+			/* allocate a pico surface */
+			newSurface = PicoNewSurface( model );
+			if (newSurface == NULL)
+				_obj_error_return("Error allocating surface");
+
+			/* reset face index for surface */
+			curFace = 0;
+
+			/* set ptr to current surface */
+			curSurface = newSurface;
+
+			/* we use triangle meshes */
+			PicoSetSurfaceType( newSurface,PICO_TRIANGLES );
+
+			/* set surface name */
+			PicoSetSurfaceName( newSurface,groupName );
+
+#ifdef DEBUG_PM_OBJ_EX
+			printf("Group: '%s'\n",groupName);
+#endif
+		}
+		/* face (oh jesus, hopefully this will do the job right ;) */
+		else if (!_pico_stricmp(p->token,"f"))
+		{
+			/* okay, this is a mess. some 3d apps seem to try being unique, */
+			/* hello cinema4d & 3d exploration, feel good today?, and save */
+			/* this crap in tons of different formats. gah, those screwed */
+			/* coders. tho the wavefront obj standard defines exactly two */
+			/* ways of storing face information. so, i really won't support */
+			/* such stupid extravaganza here! */
+
+			picoVec3_t verts  [ 4 ];
+			picoVec3_t normals[ 4 ];
+			picoVec2_t coords [ 4 ];
+
+			int iv [ 4 ], has_v;
+			int ivt[ 4 ], has_vt = 0;
+			int ivn[ 4 ], has_vn = 0;
+			int have_quad = 0;
+			int slashcount;
+			int doubleslash;
+			int i;
+
+			/* group defs *must* come before faces */
+			if (curSurface == NULL)
+				_obj_error_return("No group defined for faces");
+
+#ifdef DEBUG_PM_OBJ_EX
+			printf("Face: ");
+#endif
+			/* read vertex/uv/normal indices for the first three face */
+			/* vertices (cause we only support triangles) into 'i*[]' */
+			/* store the actual vertex/uv/normal data in three arrays */
+			/* called 'verts','coords' and 'normals'. */
+			for (i=0; i<4; i++)
+			{
+				char *str;
+
+				/* get next vertex index string (different */
+				/* formats are handled below) */
+				str = _pico_parse( p,0 );
+				if (str == NULL)
+				{
+					/* just break for quads */
+					if (i == 3) break;
+
+					/* error otherwise */
+					_obj_error_return("Face parse error");
+				}
+				/* if this is the fourth index string we're */
+				/* parsing we assume that we have a quad */
+				if (i == 3)
+					have_quad = 1;
+
+				/* get slash count once */
+				if (i == 0)
+				{
+					slashcount  = _pico_strchcount( str,'/' );
+					doubleslash =  strstr(str,"//") != NULL;
+				}
+				/* handle format 'v//vn' */
+				if (doubleslash && (slashcount == 2))
+				{
+					has_v = has_vn = 1;
+					sscanf( str,"%d//%d",&iv[ i ],&ivn[ i ] );
+				}
+				/* handle format 'v/vt/vn' */
+				else if (!doubleslash && (slashcount == 2))
+				{
+					has_v = has_vt = has_vn = 1;
+					sscanf( str,"%d/%d/%d",&iv[ i ],&ivt[ i ],&ivn[ i ] );
+				}
+				/* handle format 'v/vt' (non-standard fuckage) */
+				else if (!doubleslash && (slashcount == 1))
+				{
+					has_v = has_vt = 1;
+					sscanf( str,"%d/%d",&iv[ i ],&ivt[ i ] );
+				}
+				/* else assume face format 'v' */
+				/* (must have been invented by some bored granny) */
+				else {
+					/* get single vertex index */
+					has_v = 1;
+					iv[ i ] = atoi( str );
+
+					/* either invalid face format or out of range */
+					if (iv[ i ] == 0)
+						_obj_error_return("Invalid face format");
+				}
+				/* fix useless back references */
+				/* todo: check if this works as it is supposed to */
+
+				/* assign new indices */
+				if (iv [ i ] < 0) iv [ i ] = (numVerts   - iv [ i ]);
+				if (ivt[ i ] < 0) ivt[ i ] = (numUVs	 - ivt[ i ]);
+				if (ivn[ i ] < 0) ivn[ i ] = (numNormals - ivn[ i ]);
+
+				/* validate indices */
+				/* - commented out. index range checks will trigger
+				if (iv [ i ] < 1) iv [ i ] = 1;
+				if (ivt[ i ] < 1) ivt[ i ] = 1;
+				if (ivn[ i ] < 1) ivn[ i ] = 1;
+				*/
+				/* set vertex origin */
+				if (has_v)
+				{
+					/* check vertex index range */
+					if (iv[ i ] < 1 || iv[ i ] > numVerts)
+						_obj_error_return("Vertex index out of range");
+
+					/* get vertex data */
+					verts[ i ][ 0 ] = vertexData[ iv[ i ] - 1 ].v[ 0 ];
+					verts[ i ][ 1 ] = vertexData[ iv[ i ] - 1 ].v[ 1 ];
+					verts[ i ][ 2 ] = vertexData[ iv[ i ] - 1 ].v[ 2 ];
+				}
+				/* set vertex normal */
+				if (has_vn)
+				{
+					/* check normal index range */
+					if (ivn[ i ] < 1 || ivn[ i ] > numNormals)
+						_obj_error_return("Normal index out of range");
+
+					/* get normal data */
+					normals[ i ][ 0 ] = vertexData[ ivn[ i ] - 1 ].vn[ 0 ];
+					normals[ i ][ 1 ] = vertexData[ ivn[ i ] - 1 ].vn[ 1 ];
+					normals[ i ][ 2 ] = vertexData[ ivn[ i ] - 1 ].vn[ 2 ];
+				}
+				/* set texture coordinate */
+				if (has_vt)
+				{
+					/* check uv index range */
+					if (ivt[ i ] < 1 || ivt[ i ] > numUVs)
+						_obj_error_return("UV coord index out of range");
+
+					/* get uv coord data */
+					coords[ i ][ 0 ] = vertexData[ ivt[ i ] - 1 ].vt[ 0 ];
+					coords[ i ][ 1 ] = vertexData[ ivt[ i ] - 1 ].vt[ 1 ];
+					coords[ i ][ 1 ] = -coords[ i ][ 1 ];
+				}
+#ifdef DEBUG_PM_OBJ_EX
+				printf("(%4d",iv[ i ]);
+				if (has_vt) printf(" %4d",ivt[ i ]);
+				if (has_vn) printf(" %4d",ivn[ i ]);
+				printf(") ");
+#endif
+			}
+#ifdef DEBUG_PM_OBJ_EX
+			printf("\n");
+#endif
+			/* now that we have extracted all the indices and have */
+			/* read the actual data we need to assign all the crap */
+			/* to our current pico surface */
+			if (has_v)
+			{
+				int max = 3;
+				if (have_quad) max = 4;
+
+				/* assign all surface information */
+				for (i=0; i<max; i++)
+				{
+					/*if( has_v  )*/ PicoSetSurfaceXYZ	 ( curSurface,  (curVertex + i), verts  [ i ] );
+					/*if( has_vt )*/ PicoSetSurfaceST	 ( curSurface,0,(curVertex + i), coords [ i ] );
+					/*if( has_vn )*/ PicoSetSurfaceNormal( curSurface,  (curVertex + i), normals[ i ] );
+				}
+				/* add our triangle (A B C) */
+				PicoSetSurfaceIndex( curSurface,(curFace * 3 + 2),(picoIndex_t)( curVertex + 0 ) );
+				PicoSetSurfaceIndex( curSurface,(curFace * 3 + 1),(picoIndex_t)( curVertex + 1 ) );
+				PicoSetSurfaceIndex( curSurface,(curFace * 3 + 0),(picoIndex_t)( curVertex + 2 ) );
+				curFace++;
+
+				/* if we don't have a simple triangle, but a quad... */
+				if (have_quad)
+				{
+					/* we have to add another triangle (2nd half of quad which is A C D) */
+					PicoSetSurfaceIndex( curSurface,(curFace * 3 + 2),(picoIndex_t)( curVertex + 0 ) );
+					PicoSetSurfaceIndex( curSurface,(curFace * 3 + 1),(picoIndex_t)( curVertex + 2 ) );
+					PicoSetSurfaceIndex( curSurface,(curFace * 3 + 0),(picoIndex_t)( curVertex + 3 ) );
+					curFace++;
+				}
+				/* increase vertex count */
+				curVertex += max;
+			}
+		}
+		/* skip unparsed rest of line and continue */
+		_pico_parse_skip_rest( p );
+	}
+	/* free memory used by temporary vertexdata */
+	FreeObjVertexData( vertexData );
+
+	/* return allocated pico model */
+	return model;
+//	return NULL;
+}
+
+/* pico file format module definition */
+const picoModule_t picoModuleOBJ =
+{
+	"0.6-b",					/* module version string */
+	"Wavefront ASCII",			/* module display name */
+	"seaw0lf",					/* author's name */
+	"2002 seaw0lf",				/* module copyright */
+	{
+		"obj",NULL,NULL,NULL	/* default extensions to use */
+	},
+	_obj_canload,				/* validation routine */
+	_obj_load,					/* load routine */
+	 NULL,						/* save validation routine */
+	 NULL						/* save routine */
+};
diff --git a/libs/splines/math_angles.h b/libs/splines/math_angles.h
index 17e3fbfa..b095fae3 100644
--- a/libs/splines/math_angles.h
+++ b/libs/splines/math_angles.h
@@ -1,195 +1,195 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __MATH_ANGLES_H__
-#define __MATH_ANGLES_H__
-
-#include <stdlib.h>
-#include <assert.h>
-
-#include "math_vector.h"
-
-class mat3_t;
-class quat_t;
-class idVec3;
-typedef idVec3 &vec3_p;
-
-class angles_t {
-public:
-	float			pitch;
-	float			yaw;
-	float			roll;
-
-					angles_t();
-					angles_t( float pitch, float yaw, float roll );
-					angles_t( const idVec3 &vec );
-
-	friend void		toAngles( idVec3 &src, angles_t &dst );
-	friend void		toAngles( quat_t &src, angles_t &dst );
-	friend void		toAngles( mat3_t &src, angles_t &dst );
-
-					operator vec3_p();
-
-	float			operator[]( int index ) const;
-	float&			operator[]( int index );
-
-	void 			set( float pitch, float yaw, float roll );
-
-	void			operator=( angles_t const &a );
-	void			operator=( idVec3 const &a );
-
-	friend angles_t	operator+( const angles_t &a, const angles_t &b );
-	angles_t		&operator+=( angles_t const &a );
-	angles_t		&operator+=( idVec3 const &a );
-
-	friend angles_t	operator-( angles_t &a, angles_t &b );
-	angles_t		&operator-=( angles_t &a );
-
-	friend angles_t	operator*( const angles_t &a, float b );
-	friend angles_t	operator*( float a, const angles_t &b );
-	angles_t		&operator*=( float a );
-
-	friend int		operator==(	angles_t &a, angles_t &b );
-					
-	friend int		operator!=(	angles_t &a, angles_t &b );
-
-	void			toVectors( idVec3 *forward, idVec3 *right = NULL, idVec3 *up = NULL );
-	idVec3			toForward( void );
-
-	angles_t		&Zero( void );
-
-	angles_t		&Normalize360( void );
-	angles_t		&Normalize180( void );
-};
-
-extern angles_t ang_zero;
-
-inline angles_t::angles_t() {}
-
-inline angles_t::angles_t( float pitch, float yaw, float roll ) {
-	this->pitch = pitch;
-	this->yaw	= yaw;
-	this->roll	= roll;
-}
-
-inline angles_t::angles_t( const idVec3 &vec ) {
-	this->pitch = vec.x;
-	this->yaw	= vec.y;
-	this->roll	= vec.z;
-}
-
-inline float angles_t::operator[]( int index ) const {
-	assert( ( index >= 0 ) && ( index < 3 ) );
-	return ( &pitch )[ index ];
-}
-
-inline float& angles_t::operator[]( int index ) {
-	assert( ( index >= 0 ) && ( index < 3 ) );
-	return ( &pitch )[ index ];
-}
-
-inline angles_t::operator vec3_p( void ) {
-	return *( idVec3 * )&pitch;
-}
-
-inline void angles_t::set( float pitch, float yaw, float roll ) {
-	this->pitch = pitch;
-	this->yaw	= yaw;
-	this->roll	= roll;
-}
-
-inline void angles_t::operator=( angles_t const &a ) {
-	pitch	= a.pitch;
-	yaw		= a.yaw;
-	roll	= a.roll;
-}
-
-inline void angles_t::operator=( idVec3 const &a ) {
-	pitch	= a[ 0 ];
-	yaw		= a[ 1 ];
-	roll	= a[ 2 ];
-}
-
-inline angles_t operator+( const angles_t &a, const angles_t &b ) {
-	return angles_t( a.pitch + b.pitch, a.yaw + b.yaw, a.roll + b.roll );
-}
-
-inline angles_t& angles_t::operator+=( angles_t const &a ) {
-	pitch	+= a.pitch;
-	yaw		+= a.yaw;
-	roll	+= a.roll;
-
-	return *this;
-}
-
-inline angles_t& angles_t::operator+=( idVec3 const &a ) {
-	pitch	+= a.x;
-	yaw	+= a.y;
-	roll	+= a.z;
-
-	return *this;
-}
-
-inline angles_t operator-( angles_t &a, angles_t &b ) {
-	return angles_t( a.pitch - b.pitch, a.yaw - b.yaw, a.roll - b.roll );
-}
-
-inline angles_t& angles_t::operator-=( angles_t &a ) {
-	pitch	-= a.pitch;
-	yaw		-= a.yaw;
-	roll	-= a.roll;
-
-	return *this;
-}
-
-inline angles_t operator*( const angles_t &a, float b ) {
-	return angles_t( a.pitch * b, a.yaw * b, a.roll * b );
-}
-
-inline angles_t operator*( float a, const angles_t &b ) {
-	return angles_t( a * b.pitch, a * b.yaw, a * b.roll );
-}
-
-inline angles_t& angles_t::operator*=( float a ) {
-	pitch	*= a;
-	yaw		*= a;
-	roll	*= a;
-
-	return *this;
-}
-
-inline int operator==( angles_t &a, angles_t &b ) {
-	return ( ( a.pitch == b.pitch ) && ( a.yaw == b.yaw ) && ( a.roll == b.roll ) );
-}
-
-inline int operator!=( angles_t &a, angles_t &b ) {
-	return ( ( a.pitch != b.pitch ) || ( a.yaw != b.yaw ) || ( a.roll != b.roll ) );
-}
-
-inline angles_t& angles_t::Zero( void ) {
-	pitch	= 0.0f;
-	yaw		= 0.0f;
-	roll	= 0.0f;
-
-	return *this;
-}
-
-#endif /* !__MATH_ANGLES_H__ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __MATH_ANGLES_H__
+#define __MATH_ANGLES_H__
+
+#include <stdlib.h>
+#include <assert.h>
+
+#include "math_vector.h"
+
+class mat3_t;
+class quat_t;
+class idVec3;
+typedef idVec3 &vec3_p;
+
+class angles_t {
+public:
+	float			pitch;
+	float			yaw;
+	float			roll;
+
+					angles_t();
+					angles_t( float pitch, float yaw, float roll );
+					angles_t( const idVec3 &vec );
+
+	friend void		toAngles( idVec3 &src, angles_t &dst );
+	friend void		toAngles( quat_t &src, angles_t &dst );
+	friend void		toAngles( mat3_t &src, angles_t &dst );
+
+					operator vec3_p();
+
+	float			operator[]( int index ) const;
+	float&			operator[]( int index );
+
+	void 			set( float pitch, float yaw, float roll );
+
+	void			operator=( angles_t const &a );
+	void			operator=( idVec3 const &a );
+
+	friend angles_t	operator+( const angles_t &a, const angles_t &b );
+	angles_t		&operator+=( angles_t const &a );
+	angles_t		&operator+=( idVec3 const &a );
+
+	friend angles_t	operator-( angles_t &a, angles_t &b );
+	angles_t		&operator-=( angles_t &a );
+
+	friend angles_t	operator*( const angles_t &a, float b );
+	friend angles_t	operator*( float a, const angles_t &b );
+	angles_t		&operator*=( float a );
+
+	friend int		operator==(	angles_t &a, angles_t &b );
+					
+	friend int		operator!=(	angles_t &a, angles_t &b );
+
+	void			toVectors( idVec3 *forward, idVec3 *right = NULL, idVec3 *up = NULL );
+	idVec3			toForward( void );
+
+	angles_t		&Zero( void );
+
+	angles_t		&Normalize360( void );
+	angles_t		&Normalize180( void );
+};
+
+extern angles_t ang_zero;
+
+inline angles_t::angles_t() {}
+
+inline angles_t::angles_t( float pitch, float yaw, float roll ) {
+	this->pitch = pitch;
+	this->yaw	= yaw;
+	this->roll	= roll;
+}
+
+inline angles_t::angles_t( const idVec3 &vec ) {
+	this->pitch = vec.x;
+	this->yaw	= vec.y;
+	this->roll	= vec.z;
+}
+
+inline float angles_t::operator[]( int index ) const {
+	assert( ( index >= 0 ) && ( index < 3 ) );
+	return ( &pitch )[ index ];
+}
+
+inline float& angles_t::operator[]( int index ) {
+	assert( ( index >= 0 ) && ( index < 3 ) );
+	return ( &pitch )[ index ];
+}
+
+inline angles_t::operator vec3_p( void ) {
+	return *( idVec3 * )&pitch;
+}
+
+inline void angles_t::set( float pitch, float yaw, float roll ) {
+	this->pitch = pitch;
+	this->yaw	= yaw;
+	this->roll	= roll;
+}
+
+inline void angles_t::operator=( angles_t const &a ) {
+	pitch	= a.pitch;
+	yaw		= a.yaw;
+	roll	= a.roll;
+}
+
+inline void angles_t::operator=( idVec3 const &a ) {
+	pitch	= a[ 0 ];
+	yaw		= a[ 1 ];
+	roll	= a[ 2 ];
+}
+
+inline angles_t operator+( const angles_t &a, const angles_t &b ) {
+	return angles_t( a.pitch + b.pitch, a.yaw + b.yaw, a.roll + b.roll );
+}
+
+inline angles_t& angles_t::operator+=( angles_t const &a ) {
+	pitch	+= a.pitch;
+	yaw		+= a.yaw;
+	roll	+= a.roll;
+
+	return *this;
+}
+
+inline angles_t& angles_t::operator+=( idVec3 const &a ) {
+	pitch	+= a.x;
+	yaw	+= a.y;
+	roll	+= a.z;
+
+	return *this;
+}
+
+inline angles_t operator-( angles_t &a, angles_t &b ) {
+	return angles_t( a.pitch - b.pitch, a.yaw - b.yaw, a.roll - b.roll );
+}
+
+inline angles_t& angles_t::operator-=( angles_t &a ) {
+	pitch	-= a.pitch;
+	yaw		-= a.yaw;
+	roll	-= a.roll;
+
+	return *this;
+}
+
+inline angles_t operator*( const angles_t &a, float b ) {
+	return angles_t( a.pitch * b, a.yaw * b, a.roll * b );
+}
+
+inline angles_t operator*( float a, const angles_t &b ) {
+	return angles_t( a * b.pitch, a * b.yaw, a * b.roll );
+}
+
+inline angles_t& angles_t::operator*=( float a ) {
+	pitch	*= a;
+	yaw		*= a;
+	roll	*= a;
+
+	return *this;
+}
+
+inline int operator==( angles_t &a, angles_t &b ) {
+	return ( ( a.pitch == b.pitch ) && ( a.yaw == b.yaw ) && ( a.roll == b.roll ) );
+}
+
+inline int operator!=( angles_t &a, angles_t &b ) {
+	return ( ( a.pitch != b.pitch ) || ( a.yaw != b.yaw ) || ( a.roll != b.roll ) );
+}
+
+inline angles_t& angles_t::Zero( void ) {
+	pitch	= 0.0f;
+	yaw		= 0.0f;
+	roll	= 0.0f;
+
+	return *this;
+}
+
+#endif /* !__MATH_ANGLES_H__ */
diff --git a/libs/splines/math_matrix.h b/libs/splines/math_matrix.h
index f2cfae0d..a039945c 100644
--- a/libs/splines/math_matrix.h
+++ b/libs/splines/math_matrix.h
@@ -1,223 +1,223 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __MATH_MATRIX_H__
-#define __MATH_MATRIX_H__
-
-#include <string.h>
-#include "math_vector.h"
-
-#ifndef ID_INLINE
-#ifdef _WIN32
-#define ID_INLINE __inline 
-#else
-#define ID_INLINE inline
-#endif
-#endif
-
-class quat_t;
-class angles_t;
-
-class mat3_t {
-public:
-	idVec3			mat[ 3 ];
-
-					mat3_t();
-					mat3_t( float src[ 3 ][ 3 ] );
-					mat3_t( idVec3 const &x, idVec3 const &y, idVec3 const &z );
-					mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz );
-
-	friend void		toMatrix( quat_t const &src, mat3_t &dst );
-	friend void		toMatrix( angles_t const &src, mat3_t &dst );
-	friend void		toMatrix( idVec3 const &src, mat3_t &dst );
-
-	idVec3			operator[]( int index ) const;
-	idVec3			&operator[]( int index );
-
-	idVec3			operator*( const idVec3 &vec ) const;
-	mat3_t			operator*( const mat3_t &a ) const;
-	mat3_t			operator*( float a ) const;
-	mat3_t			operator+( mat3_t const &a ) const;
-	mat3_t			operator-( mat3_t const &a ) const;
-
-	friend idVec3	operator*( const idVec3 &vec, const mat3_t &mat );
-	friend mat3_t	operator*( float a, mat3_t const &b );
-
-	mat3_t			&operator*=( float a );
-	mat3_t			&operator+=( mat3_t const &a );
-	mat3_t			&operator-=( mat3_t const &a );
-
-	void			Clear( void );
-
-	void			ProjectVector( const idVec3 &src, idVec3 &dst ) const;
-	void			UnprojectVector( const idVec3 &src, idVec3 &dst ) const;
-
-	void			OrthoNormalize( void );
-	void			Transpose( mat3_t &matrix );
-	void			Transpose( void );
-	mat3_t			Inverse( void ) const;
-	void			Identity( void );
-
-	friend void		InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst );
-	friend mat3_t	SkewSymmetric( idVec3 const &src );
-};
-
-ID_INLINE mat3_t::mat3_t() {
-}
-
-ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
-	memcpy( mat, src, sizeof( src ) );
-}
-
-ID_INLINE mat3_t::mat3_t( idVec3 const &x, idVec3 const &y, idVec3 const &z ) {
-	mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z;
-	mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z;
-	mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z;
-}
-
-ID_INLINE mat3_t::mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) {
-	mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz;
-	mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz;
-	mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz;
-}
-
-ID_INLINE idVec3 mat3_t::operator[]( int index ) const {
-	assert( ( index >= 0 ) && ( index < 3 ) );
-	return mat[ index ];
-}
-
-ID_INLINE idVec3& mat3_t::operator[]( int index ) {
-	assert( ( index >= 0 ) && ( index < 3 ) );
-	return mat[ index ];
-}
-
-ID_INLINE idVec3 mat3_t::operator*( const idVec3 &vec ) const {
-	return idVec3( 
-		mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
-		mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
-		mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
-}
-
-ID_INLINE mat3_t mat3_t::operator*( const mat3_t &a ) const {
-	return mat3_t( 
-		mat[0].x * a[0].x + mat[0].y * a[1].x + mat[0].z * a[2].x,
-		mat[0].x * a[0].y + mat[0].y * a[1].y + mat[0].z * a[2].y,
-		mat[0].x * a[0].z + mat[0].y * a[1].z + mat[0].z * a[2].z,
-		mat[1].x * a[0].x + mat[1].y * a[1].x + mat[1].z * a[2].x,
-		mat[1].x * a[0].y + mat[1].y * a[1].y + mat[1].z * a[2].y,
-		mat[1].x * a[0].z + mat[1].y * a[1].z + mat[1].z * a[2].z,
-		mat[2].x * a[0].x + mat[2].y * a[1].x + mat[2].z * a[2].x,
-		mat[2].x * a[0].y + mat[2].y * a[1].y + mat[2].z * a[2].y,
-		mat[2].x * a[0].z + mat[2].y * a[1].z + mat[2].z * a[2].z );
-}
-
-ID_INLINE mat3_t mat3_t::operator*( float a ) const {
-	return mat3_t( 
-		mat[0].x * a, mat[0].y * a, mat[0].z * a, 
-		mat[1].x * a, mat[1].y * a, mat[1].z * a, 
-		mat[2].x * a, mat[2].y * a, mat[2].z * a );
-}
-
-ID_INLINE mat3_t mat3_t::operator+( mat3_t const &a ) const {
-	return mat3_t( 
-		mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z, 
-		mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z, 
-		mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z );
-}
-    
-ID_INLINE mat3_t mat3_t::operator-( mat3_t const &a ) const {
-	return mat3_t( 
-		mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z, 
-		mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z, 
-		mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z );
-}
-
-ID_INLINE idVec3 operator*( const idVec3 &vec, const mat3_t &mat ) {
-	return idVec3( 
-		mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
-		mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
-		mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
-}
-
-ID_INLINE mat3_t operator*( float a, mat3_t const &b ) {
-	return mat3_t( 
-		b[0].x * a, b[0].y * a, b[0].z * a, 
-		b[1].x * a, b[1].y * a, b[1].z * a, 
-		b[2].x * a, b[2].y * a, b[2].z * a );
-}
-
-ID_INLINE mat3_t &mat3_t::operator*=( float a ) {
-	mat[0].x *= a; mat[0].y *= a; mat[0].z *= a;
-	mat[1].x *= a; mat[1].y *= a; mat[1].z *= a; 
-	mat[2].x *= a; mat[2].y *= a; mat[2].z *= a;
-
-    return *this;
-}
-
-ID_INLINE mat3_t &mat3_t::operator+=( mat3_t const &a ) {
-	mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z;
-	mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z;
-	mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z;
-
-    return *this;
-}
-
-ID_INLINE mat3_t &mat3_t::operator-=( mat3_t const &a ) {
-	mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z;
-	mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z;
-	mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z;
-
-    return *this;
-}
-
-ID_INLINE void mat3_t::OrthoNormalize( void ) {
-	mat[ 0 ].Normalize();
-	mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] );
-	mat[ 2 ].Normalize();
-	mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] );
-	mat[ 1 ].Normalize();
-}
-
-ID_INLINE void mat3_t::Identity( void ) {
-	mat[ 0 ].x = 1.f; mat[ 0 ].y = 0.f; mat[ 0 ].z = 0.f;
-	mat[ 1 ].x = 0.f; mat[ 1 ].y = 1.f; mat[ 1 ].z = 0.f;
-	mat[ 2 ].x = 0.f; mat[ 2 ].y = 0.f; mat[ 2 ].z = 1.f;
-}
-
-ID_INLINE void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst ) {
-	dst[0].x = inv[0].x * b[0].x + inv[1].x * b[1].x + inv[2].x * b[2].x;
-	dst[0].y = inv[0].x * b[0].y + inv[1].x * b[1].y + inv[2].x * b[2].y;
-	dst[0].z = inv[0].x * b[0].z + inv[1].x * b[1].z + inv[2].x * b[2].z;
-	dst[1].x = inv[0].y * b[0].x + inv[1].y * b[1].x + inv[2].y * b[2].x;
-	dst[1].y = inv[0].y * b[0].y + inv[1].y * b[1].y + inv[2].y * b[2].y;
-	dst[1].z = inv[0].y * b[0].z + inv[1].y * b[1].z + inv[2].y * b[2].z;
-	dst[2].x = inv[0].z * b[0].x + inv[1].z * b[1].x + inv[2].z * b[2].x;
-	dst[2].y = inv[0].z * b[0].y + inv[1].z * b[1].y + inv[2].z * b[2].y;
-	dst[2].z = inv[0].z * b[0].z + inv[1].z * b[1].z + inv[2].z * b[2].z;
-}
-
-ID_INLINE mat3_t SkewSymmetric( idVec3 const &src ) {
-	return mat3_t( 0.0f, -src.z,  src.y, src.z,   0.0f, -src.x, -src.y,  src.x,   0.0f );
-}
-
-extern mat3_t mat3_default;
-
-#endif /* !__MATH_MATRIX_H__ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __MATH_MATRIX_H__
+#define __MATH_MATRIX_H__
+
+#include <string.h>
+#include "math_vector.h"
+
+#ifndef ID_INLINE
+#ifdef _WIN32
+#define ID_INLINE __inline 
+#else
+#define ID_INLINE inline
+#endif
+#endif
+
+class quat_t;
+class angles_t;
+
+class mat3_t {
+public:
+	idVec3			mat[ 3 ];
+
+					mat3_t();
+					mat3_t( float src[ 3 ][ 3 ] );
+					mat3_t( idVec3 const &x, idVec3 const &y, idVec3 const &z );
+					mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz );
+
+	friend void		toMatrix( quat_t const &src, mat3_t &dst );
+	friend void		toMatrix( angles_t const &src, mat3_t &dst );
+	friend void		toMatrix( idVec3 const &src, mat3_t &dst );
+
+	idVec3			operator[]( int index ) const;
+	idVec3			&operator[]( int index );
+
+	idVec3			operator*( const idVec3 &vec ) const;
+	mat3_t			operator*( const mat3_t &a ) const;
+	mat3_t			operator*( float a ) const;
+	mat3_t			operator+( mat3_t const &a ) const;
+	mat3_t			operator-( mat3_t const &a ) const;
+
+	friend idVec3	operator*( const idVec3 &vec, const mat3_t &mat );
+	friend mat3_t	operator*( float a, mat3_t const &b );
+
+	mat3_t			&operator*=( float a );
+	mat3_t			&operator+=( mat3_t const &a );
+	mat3_t			&operator-=( mat3_t const &a );
+
+	void			Clear( void );
+
+	void			ProjectVector( const idVec3 &src, idVec3 &dst ) const;
+	void			UnprojectVector( const idVec3 &src, idVec3 &dst ) const;
+
+	void			OrthoNormalize( void );
+	void			Transpose( mat3_t &matrix );
+	void			Transpose( void );
+	mat3_t			Inverse( void ) const;
+	void			Identity( void );
+
+	friend void		InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst );
+	friend mat3_t	SkewSymmetric( idVec3 const &src );
+};
+
+ID_INLINE mat3_t::mat3_t() {
+}
+
+ID_INLINE mat3_t::mat3_t( float src[ 3 ][ 3 ] ) {
+	memcpy( mat, src, sizeof( src ) );
+}
+
+ID_INLINE mat3_t::mat3_t( idVec3 const &x, idVec3 const &y, idVec3 const &z ) {
+	mat[ 0 ].x = x.x; mat[ 0 ].y = x.y; mat[ 0 ].z = x.z;
+	mat[ 1 ].x = y.x; mat[ 1 ].y = y.y; mat[ 1 ].z = y.z;
+	mat[ 2 ].x = z.x; mat[ 2 ].y = z.y; mat[ 2 ].z = z.z;
+}
+
+ID_INLINE mat3_t::mat3_t( const float xx, const float xy, const float xz, const float yx, const float yy, const float yz, const float zx, const float zy, const float zz ) {
+	mat[ 0 ].x = xx; mat[ 0 ].y = xy; mat[ 0 ].z = xz;
+	mat[ 1 ].x = yx; mat[ 1 ].y = yy; mat[ 1 ].z = yz;
+	mat[ 2 ].x = zx; mat[ 2 ].y = zy; mat[ 2 ].z = zz;
+}
+
+ID_INLINE idVec3 mat3_t::operator[]( int index ) const {
+	assert( ( index >= 0 ) && ( index < 3 ) );
+	return mat[ index ];
+}
+
+ID_INLINE idVec3& mat3_t::operator[]( int index ) {
+	assert( ( index >= 0 ) && ( index < 3 ) );
+	return mat[ index ];
+}
+
+ID_INLINE idVec3 mat3_t::operator*( const idVec3 &vec ) const {
+	return idVec3( 
+		mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
+		mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
+		mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
+}
+
+ID_INLINE mat3_t mat3_t::operator*( const mat3_t &a ) const {
+	return mat3_t( 
+		mat[0].x * a[0].x + mat[0].y * a[1].x + mat[0].z * a[2].x,
+		mat[0].x * a[0].y + mat[0].y * a[1].y + mat[0].z * a[2].y,
+		mat[0].x * a[0].z + mat[0].y * a[1].z + mat[0].z * a[2].z,
+		mat[1].x * a[0].x + mat[1].y * a[1].x + mat[1].z * a[2].x,
+		mat[1].x * a[0].y + mat[1].y * a[1].y + mat[1].z * a[2].y,
+		mat[1].x * a[0].z + mat[1].y * a[1].z + mat[1].z * a[2].z,
+		mat[2].x * a[0].x + mat[2].y * a[1].x + mat[2].z * a[2].x,
+		mat[2].x * a[0].y + mat[2].y * a[1].y + mat[2].z * a[2].y,
+		mat[2].x * a[0].z + mat[2].y * a[1].z + mat[2].z * a[2].z );
+}
+
+ID_INLINE mat3_t mat3_t::operator*( float a ) const {
+	return mat3_t( 
+		mat[0].x * a, mat[0].y * a, mat[0].z * a, 
+		mat[1].x * a, mat[1].y * a, mat[1].z * a, 
+		mat[2].x * a, mat[2].y * a, mat[2].z * a );
+}
+
+ID_INLINE mat3_t mat3_t::operator+( mat3_t const &a ) const {
+	return mat3_t( 
+		mat[0].x + a[0].x, mat[0].y + a[0].y, mat[0].z + a[0].z, 
+		mat[1].x + a[1].x, mat[1].y + a[1].y, mat[1].z + a[1].z, 
+		mat[2].x + a[2].x, mat[2].y + a[2].y, mat[2].z + a[2].z );
+}
+    
+ID_INLINE mat3_t mat3_t::operator-( mat3_t const &a ) const {
+	return mat3_t( 
+		mat[0].x - a[0].x, mat[0].y - a[0].y, mat[0].z - a[0].z, 
+		mat[1].x - a[1].x, mat[1].y - a[1].y, mat[1].z - a[1].z, 
+		mat[2].x - a[2].x, mat[2].y - a[2].y, mat[2].z - a[2].z );
+}
+
+ID_INLINE idVec3 operator*( const idVec3 &vec, const mat3_t &mat ) {
+	return idVec3( 
+		mat[ 0 ].x * vec.x + mat[ 1 ].x * vec.y + mat[ 2 ].x * vec.z,
+		mat[ 0 ].y * vec.x + mat[ 1 ].y * vec.y + mat[ 2 ].y * vec.z,
+		mat[ 0 ].z * vec.x + mat[ 1 ].z * vec.y + mat[ 2 ].z * vec.z );
+}
+
+ID_INLINE mat3_t operator*( float a, mat3_t const &b ) {
+	return mat3_t( 
+		b[0].x * a, b[0].y * a, b[0].z * a, 
+		b[1].x * a, b[1].y * a, b[1].z * a, 
+		b[2].x * a, b[2].y * a, b[2].z * a );
+}
+
+ID_INLINE mat3_t &mat3_t::operator*=( float a ) {
+	mat[0].x *= a; mat[0].y *= a; mat[0].z *= a;
+	mat[1].x *= a; mat[1].y *= a; mat[1].z *= a; 
+	mat[2].x *= a; mat[2].y *= a; mat[2].z *= a;
+
+    return *this;
+}
+
+ID_INLINE mat3_t &mat3_t::operator+=( mat3_t const &a ) {
+	mat[0].x += a[0].x; mat[0].y += a[0].y; mat[0].z += a[0].z;
+	mat[1].x += a[1].x; mat[1].y += a[1].y; mat[1].z += a[1].z;
+	mat[2].x += a[2].x; mat[2].y += a[2].y; mat[2].z += a[2].z;
+
+    return *this;
+}
+
+ID_INLINE mat3_t &mat3_t::operator-=( mat3_t const &a ) {
+	mat[0].x -= a[0].x; mat[0].y -= a[0].y; mat[0].z -= a[0].z;
+	mat[1].x -= a[1].x; mat[1].y -= a[1].y; mat[1].z -= a[1].z;
+	mat[2].x -= a[2].x; mat[2].y -= a[2].y; mat[2].z -= a[2].z;
+
+    return *this;
+}
+
+ID_INLINE void mat3_t::OrthoNormalize( void ) {
+	mat[ 0 ].Normalize();
+	mat[ 2 ].Cross( mat[ 0 ], mat[ 1 ] );
+	mat[ 2 ].Normalize();
+	mat[ 1 ].Cross( mat[ 2 ], mat[ 0 ] );
+	mat[ 1 ].Normalize();
+}
+
+ID_INLINE void mat3_t::Identity( void ) {
+	mat[ 0 ].x = 1.f; mat[ 0 ].y = 0.f; mat[ 0 ].z = 0.f;
+	mat[ 1 ].x = 0.f; mat[ 1 ].y = 1.f; mat[ 1 ].z = 0.f;
+	mat[ 2 ].x = 0.f; mat[ 2 ].y = 0.f; mat[ 2 ].z = 1.f;
+}
+
+ID_INLINE void InverseMultiply( const mat3_t &inv, const mat3_t &b, mat3_t &dst ) {
+	dst[0].x = inv[0].x * b[0].x + inv[1].x * b[1].x + inv[2].x * b[2].x;
+	dst[0].y = inv[0].x * b[0].y + inv[1].x * b[1].y + inv[2].x * b[2].y;
+	dst[0].z = inv[0].x * b[0].z + inv[1].x * b[1].z + inv[2].x * b[2].z;
+	dst[1].x = inv[0].y * b[0].x + inv[1].y * b[1].x + inv[2].y * b[2].x;
+	dst[1].y = inv[0].y * b[0].y + inv[1].y * b[1].y + inv[2].y * b[2].y;
+	dst[1].z = inv[0].y * b[0].z + inv[1].y * b[1].z + inv[2].y * b[2].z;
+	dst[2].x = inv[0].z * b[0].x + inv[1].z * b[1].x + inv[2].z * b[2].x;
+	dst[2].y = inv[0].z * b[0].y + inv[1].z * b[1].y + inv[2].z * b[2].y;
+	dst[2].z = inv[0].z * b[0].z + inv[1].z * b[1].z + inv[2].z * b[2].z;
+}
+
+ID_INLINE mat3_t SkewSymmetric( idVec3 const &src ) {
+	return mat3_t( 0.0f, -src.z,  src.y, src.z,   0.0f, -src.x, -src.y,  src.x,   0.0f );
+}
+
+extern mat3_t mat3_default;
+
+#endif /* !__MATH_MATRIX_H__ */
diff --git a/libs/splines/math_quaternion.h b/libs/splines/math_quaternion.h
index 6ff2c1ee..1d2e2907 100644
--- a/libs/splines/math_quaternion.h
+++ b/libs/splines/math_quaternion.h
@@ -1,190 +1,190 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __MATH_QUATERNION_H__
-#define __MATH_QUATERNION_H__
-
-#include <assert.h>
-#include <math.h>
-
-class idVec3_t;
-class angles_t;
-class mat3_t;
-
-class quat_t {
-public:
-	float			x;
-	float			y;
-	float			z;
-	float			w;
-
-					quat_t();
-					quat_t( float x, float y, float z, float w );
-
-	friend void		toQuat( idVec3_t &src, quat_t &dst );
-	friend void		toQuat( angles_t &src, quat_t &dst );
-	friend void		toQuat( mat3_t &src, quat_t &dst );
-
-	float			*vec4( void );
-			
-	float			operator[]( int index ) const;
-	float			&operator[]( int index );
-
-	void 			set( float x, float y, float z, float w );
-
-	void			operator=( quat_t a );
-
-	friend quat_t	operator+( quat_t a, quat_t b );
-	quat_t			&operator+=( quat_t a );
-
-	friend quat_t	operator-( quat_t a, quat_t b );
-	quat_t			&operator-=( quat_t a );
-
-	friend quat_t	operator*( quat_t a, float b );
-	friend quat_t	operator*( float a, quat_t b );
-	quat_t			&operator*=( float a );
-
-	friend int		operator==(	quat_t a, quat_t b );
-	friend int		operator!=(	quat_t a, quat_t b );
-
-	float			Length( void );
-	quat_t			&Normalize( void );
-
-	quat_t			operator-();
-};
-
-inline quat_t::quat_t() {
-}
-
-inline quat_t::quat_t( float x, float y, float z, float w ) {
-	this->x = x;
-	this->y = y;
-	this->z = z;
-	this->w = w;
-}
-
-inline float *quat_t::vec4( void ) {
-	return &x;
-}
-
-inline float quat_t::operator[]( int index ) const {
-	assert( ( index >= 0 ) && ( index < 4 ) );
-	return ( &x )[ index ];
-}
-
-inline float& quat_t::operator[]( int index ) {
-	assert( ( index >= 0 ) && ( index < 4 ) );
-	return ( &x )[ index ];
-}
-
-inline void quat_t::set( float x, float y, float z, float w ) {
-	this->x = x;
-	this->y = y;
-	this->z = z;
-	this->w = w;
-}
-
-inline void quat_t::operator=( quat_t a ) {
-	x = a.x;
-	y = a.y;
-	z = a.z;
-	w = a.w;
-}
-
-inline quat_t operator+( quat_t a, quat_t b ) {
-	return quat_t( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w );
-}
-
-inline quat_t& quat_t::operator+=( quat_t a ) {
-	x += a.x;
-	y += a.y;
-	z += a.z;
-	w += a.w;
-
-	return *this;
-}
-
-inline quat_t operator-( quat_t a, quat_t b ) {
-	return quat_t( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w );
-}
-
-inline quat_t& quat_t::operator-=( quat_t a ) {
-	x -= a.x;
-	y -= a.y;
-	z -= a.z;
-	w -= a.w;
-
-	return *this;
-}
-
-inline quat_t operator*( quat_t a, float b ) {
-	return quat_t( a.x * b, a.y * b, a.z * b, a.w * b );
-}
-
-inline quat_t operator*( float a, quat_t b ) {
-	return b * a;
-}
-
-inline quat_t& quat_t::operator*=( float a ) {
-	x *= a;
-	y *= a;
-	z *= a;
-	w *= a;
-
-	return *this;
-}
-
-inline int operator==( quat_t a, quat_t b ) {
-	return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) );
-}
-
-inline int operator!=( quat_t a, quat_t b ) {
-	return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) );
-}
-
-inline float quat_t::Length( void ) {
-	float length;
-	
-	length = x * x + y * y + z * z + w * w;
-	return ( float )sqrt( length );
-}
-
-inline quat_t& quat_t::Normalize( void ) {
-	float length;
-	float ilength;
-
-	length = this->Length();
-	if ( length ) {
-		ilength = 1 / length;
-		x *= ilength;
-		y *= ilength;
-		z *= ilength;
-		w *= ilength;
-	}
-		
-	return *this;
-}
-
-inline quat_t quat_t::operator-() {
-	return quat_t( -x, -y, -z, -w );
-}
-
-#endif /* !__MATH_QUATERNION_H__ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __MATH_QUATERNION_H__
+#define __MATH_QUATERNION_H__
+
+#include <assert.h>
+#include <math.h>
+
+class idVec3_t;
+class angles_t;
+class mat3_t;
+
+class quat_t {
+public:
+	float			x;
+	float			y;
+	float			z;
+	float			w;
+
+					quat_t();
+					quat_t( float x, float y, float z, float w );
+
+	friend void		toQuat( idVec3_t &src, quat_t &dst );
+	friend void		toQuat( angles_t &src, quat_t &dst );
+	friend void		toQuat( mat3_t &src, quat_t &dst );
+
+	float			*vec4( void );
+			
+	float			operator[]( int index ) const;
+	float			&operator[]( int index );
+
+	void 			set( float x, float y, float z, float w );
+
+	void			operator=( quat_t a );
+
+	friend quat_t	operator+( quat_t a, quat_t b );
+	quat_t			&operator+=( quat_t a );
+
+	friend quat_t	operator-( quat_t a, quat_t b );
+	quat_t			&operator-=( quat_t a );
+
+	friend quat_t	operator*( quat_t a, float b );
+	friend quat_t	operator*( float a, quat_t b );
+	quat_t			&operator*=( float a );
+
+	friend int		operator==(	quat_t a, quat_t b );
+	friend int		operator!=(	quat_t a, quat_t b );
+
+	float			Length( void );
+	quat_t			&Normalize( void );
+
+	quat_t			operator-();
+};
+
+inline quat_t::quat_t() {
+}
+
+inline quat_t::quat_t( float x, float y, float z, float w ) {
+	this->x = x;
+	this->y = y;
+	this->z = z;
+	this->w = w;
+}
+
+inline float *quat_t::vec4( void ) {
+	return &x;
+}
+
+inline float quat_t::operator[]( int index ) const {
+	assert( ( index >= 0 ) && ( index < 4 ) );
+	return ( &x )[ index ];
+}
+
+inline float& quat_t::operator[]( int index ) {
+	assert( ( index >= 0 ) && ( index < 4 ) );
+	return ( &x )[ index ];
+}
+
+inline void quat_t::set( float x, float y, float z, float w ) {
+	this->x = x;
+	this->y = y;
+	this->z = z;
+	this->w = w;
+}
+
+inline void quat_t::operator=( quat_t a ) {
+	x = a.x;
+	y = a.y;
+	z = a.z;
+	w = a.w;
+}
+
+inline quat_t operator+( quat_t a, quat_t b ) {
+	return quat_t( a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w );
+}
+
+inline quat_t& quat_t::operator+=( quat_t a ) {
+	x += a.x;
+	y += a.y;
+	z += a.z;
+	w += a.w;
+
+	return *this;
+}
+
+inline quat_t operator-( quat_t a, quat_t b ) {
+	return quat_t( a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w );
+}
+
+inline quat_t& quat_t::operator-=( quat_t a ) {
+	x -= a.x;
+	y -= a.y;
+	z -= a.z;
+	w -= a.w;
+
+	return *this;
+}
+
+inline quat_t operator*( quat_t a, float b ) {
+	return quat_t( a.x * b, a.y * b, a.z * b, a.w * b );
+}
+
+inline quat_t operator*( float a, quat_t b ) {
+	return b * a;
+}
+
+inline quat_t& quat_t::operator*=( float a ) {
+	x *= a;
+	y *= a;
+	z *= a;
+	w *= a;
+
+	return *this;
+}
+
+inline int operator==( quat_t a, quat_t b ) {
+	return ( ( a.x == b.x ) && ( a.y == b.y ) && ( a.z == b.z ) && ( a.w == b.w ) );
+}
+
+inline int operator!=( quat_t a, quat_t b ) {
+	return ( ( a.x != b.x ) || ( a.y != b.y ) || ( a.z != b.z ) && ( a.w != b.w ) );
+}
+
+inline float quat_t::Length( void ) {
+	float length;
+	
+	length = x * x + y * y + z * z + w * w;
+	return ( float )sqrt( length );
+}
+
+inline quat_t& quat_t::Normalize( void ) {
+	float length;
+	float ilength;
+
+	length = this->Length();
+	if ( length ) {
+		ilength = 1 / length;
+		x *= ilength;
+		y *= ilength;
+		z *= ilength;
+		w *= ilength;
+	}
+		
+	return *this;
+}
+
+inline quat_t quat_t::operator-() {
+	return quat_t( -x, -y, -z, -w );
+}
+
+#endif /* !__MATH_QUATERNION_H__ */
diff --git a/libs/splines/math_vector.h b/libs/splines/math_vector.h
index 6e1f765a..60e86a5f 100644
--- a/libs/splines/math_vector.h
+++ b/libs/splines/math_vector.h
@@ -1,574 +1,574 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __MATH_VECTOR_H__
-#define __MATH_VECTOR_H__
-
-#ifdef _WIN32
-#pragma warning(disable : 4244)
-#endif
-
-#include <math.h>
-#include <assert.h>
-
-//#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
-//#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
-//#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
-//#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
-//#define VectorCopy(a,b)			((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
-
-//#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
-#define	__VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
-//#define CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
-
-#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
-#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
-#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
-#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
-#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
-#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
-
-
-//#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0)
-#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
-//#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
-#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
-
-#define	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
-
-
-//#include "util_heap.h"
-
-#ifndef EQUAL_EPSILON
-#define EQUAL_EPSILON	0.001
-#endif
-
-float Q_fabs( float f );
-
-#ifndef ID_INLINE
-#ifdef _WIN32
-#define ID_INLINE __inline 
-#else
-#define ID_INLINE inline
-#endif
-#endif
-
-// if this is defined, vec3 will take four elements, which may allow
-// easier SIMD optimizations
-//#define	FAT_VEC3
-//#ifdef __ppc__
-//#pragma align(16)
-//#endif
-
-class angles_t;
-#ifdef __ppc__
-// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, 
-// runs *much* faster than calling sqrt(). We'll use two Newton-Raphson 
-// refinement steps to get bunch more precision in the 1/sqrt() value for very little cost. 
-// We'll then multiply 1/sqrt times the original value to get the sqrt. 
-// This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive) 
-// it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments). 
-
-static inline float idSqrt(float x) {
-    const float half = 0.5;
-    const float one = 1.0;
-    float B, y0, y1;
-
-    // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
-    if (fabs(x) == 0.0)
-        return x;
-    B = x;
-    
-#ifdef __GNUC__
-    asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
-#else
-    y0 = __frsqrte(B);
-#endif
-    /* First refinement step */
-    
-    y1 = y0 + half*y0*(one - B*y0*y0);
-    
-    /* Second refinement step -- copy the output of the last step to the input of this step */
-    
-    y0 = y1;
-    y1 = y0 + half*y0*(one - B*y0*y0);
-    
-    /* Get sqrt(x) from x * 1/sqrt(x) */
-    return x * y1;
-}
-#else
-static inline double idSqrt(double x) {
-    return sqrt(x);
-}
-#endif
-
-
-//class idVec3  : public idHeap<idVec3> {
-class idVec3 {
-public:	
-#ifndef	FAT_VEC3
-	    float x,y,z;
-#else
-	    float x,y,z,dist;
-#endif
-
-#ifndef	FAT_VEC3
-					idVec3() {};
-#else
-					idVec3() {dist = 0.0f;};
-#endif
-					idVec3( const float x, const float y, const float z );
-
-					operator float *();
-
-	float			operator[]( const int index ) const;
-	float			&operator[]( const int index );
-
-	void 			set( const float x, const float y, const float z );
-
-	idVec3			operator-() const;
-
-	idVec3			&operator=( const idVec3 &a );
-
-	float			operator*( const idVec3 &a ) const;
-	idVec3			operator*( const float a ) const;
-	friend idVec3	operator*( float a, idVec3 b );
-
-	idVec3			operator+( const idVec3 &a ) const;
-	idVec3			operator-( const idVec3 &a ) const;
-	
-	idVec3			&operator+=( const idVec3 &a );
-	idVec3			&operator-=( const idVec3 &a );
-	idVec3			&operator*=( const float a );
-
-	int				operator==(	const idVec3 &a ) const;
-	int				operator!=(	const idVec3 &a ) const;
-
-	idVec3			Cross( const idVec3 &a ) const;
-	idVec3			&Cross( const idVec3 &a, const idVec3 &b );
-
-	float			Length( void ) const;
-	float			Normalize( void );
-
-	void			Zero( void );
-	void			Snap( void );
-	void			SnapTowards( const idVec3 &to );
-
-	float			toYaw( void );
-	float			toPitch( void );
-	angles_t		toAngles( void );
-	friend idVec3	LerpVector( const idVec3 &w1, const idVec3 &w2, const float t );
-
-	char			*string( void );
-};
-
-extern idVec3 vec_zero;
-
-ID_INLINE idVec3::idVec3( const float x, const float y, const float z ) {
-	this->x = x;
-	this->y = y;
-	this->z = z;
-#ifdef	FAT_VEC3
-	this->dist = 0.0f;
-#endif
-}
-
-ID_INLINE float idVec3::operator[]( const int index ) const {
-	return ( &x )[ index ];
-}
-
-ID_INLINE float &idVec3::operator[]( const int index ) {
-	return ( &x )[ index ];
-}
-
-ID_INLINE idVec3::operator float *( void ) {
-	return &x;
-}
-
-ID_INLINE idVec3 idVec3::operator-() const {
-	return idVec3( -x, -y, -z );
-}
-	
-ID_INLINE idVec3 &idVec3::operator=( const idVec3 &a ) { 
-	x = a.x;
-	y = a.y;
-	z = a.z;
-	
-	return *this;
-}
-
-ID_INLINE void idVec3::set( const float x, const float y, const float z ) {
-	this->x = x;
-	this->y = y;
-	this->z = z;
-}
-
-ID_INLINE idVec3 idVec3::operator-( const idVec3 &a ) const {
-	return idVec3( x - a.x, y - a.y, z - a.z );
-}
-
-ID_INLINE float idVec3::operator*( const idVec3 &a ) const {
-	return x * a.x + y * a.y + z * a.z;
-}
-
-ID_INLINE idVec3 idVec3::operator*( const float a ) const {
-	return idVec3( x * a, y * a, z * a );
-}
-
-ID_INLINE idVec3 operator*( const float a, const idVec3 b ) {
-	return idVec3( b.x * a, b.y * a, b.z * a );
-}
-
-ID_INLINE idVec3 idVec3::operator+( const idVec3 &a ) const {
-	return idVec3( x + a.x, y + a.y, z + a.z );
-}
-
-ID_INLINE idVec3 &idVec3::operator+=( const idVec3 &a ) {
-	x += a.x;
-	y += a.y;
-	z += a.z;
-
-	return *this;
-}
-
-ID_INLINE idVec3 &idVec3::operator-=( const idVec3 &a ) {
-	x -= a.x;
-	y -= a.y;
-	z -= a.z;
-
-	return *this;
-}
-
-ID_INLINE idVec3 &idVec3::operator*=( const float a ) {
-	x *= a;
-	y *= a;
-	z *= a;
-
-	return *this;
-}
-
-ID_INLINE int idVec3::operator==( const idVec3 &a ) const {
-	if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
-		return false;
-	}
-			
-	if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
-		return false;
-	}
-
-	if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
-		return false;
-	}
-
-	return true;
-}
-
-ID_INLINE int idVec3::operator!=( const idVec3 &a ) const {
-	if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
-		return true;
-	}
-			
-	if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
-		return true;
-	}
-
-	if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
-		return true;
-	}
-
-	return false;
-}
-
-ID_INLINE idVec3 idVec3::Cross( const idVec3 &a ) const {
-	return idVec3( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
-}
-
-ID_INLINE idVec3 &idVec3::Cross( const idVec3 &a, const idVec3 &b ) {
-	x = a.y * b.z - a.z * b.y;
-	y = a.z * b.x - a.x * b.z;
-	z = a.x * b.y - a.y * b.x;
-
-	return *this;
-}
-
-ID_INLINE float idVec3::Length( void ) const {
-	float length;
-	
-	length = x * x + y * y + z * z;
-	return ( float )idSqrt( length );
-}
-
-ID_INLINE float idVec3::Normalize( void ) {
-	float length;
-	float ilength;
-
-	length = this->Length();
-	if ( length ) {
-		ilength = 1.0f / length;
-		x *= ilength;
-		y *= ilength;
-		z *= ilength;
-	}
-		
-	return length;
-}
-
-ID_INLINE void idVec3::Zero( void ) {
-	x = 0.0f;
-	y = 0.0f;
-	z = 0.0f;
-}
-
-ID_INLINE void idVec3::Snap( void ) {
-	x = float( int( x ) );
-	y = float( int( y ) );
-	z = float( int( z ) );
-}
-
-/*
-======================
-SnapTowards
-
-Round a vector to integers for more efficient network
-transmission, but make sure that it rounds towards a given point
-rather than blindly truncating.  This prevents it from truncating 
-into a wall.
-======================
-*/
-ID_INLINE void idVec3::SnapTowards( const idVec3 &to ) {
-	if ( to.x <= x ) {
-		x = float( int( x ) );
-	} else {
-		x = float( int( x ) + 1 );
-	}
-
-	if ( to.y <= y ) {
-		y = float( int( y ) );
-	} else {
-		y = float( int( y ) + 1 );
-	}
-
-	if ( to.z <= z ) {
-		z = float( int( z ) );
-	} else {
-		z = float( int( z ) + 1 );
-	}
-}
-
-//===============================================================
-
-class Bounds {
-public:
-	idVec3	b[2];
-
-			Bounds();
-			Bounds( const idVec3 &mins, const idVec3 &maxs );
-
-	void	Clear();
-	void	Zero();
-	float	Radius();		// radius from origin, not from center
-	idVec3	Center();
-	void	AddPoint( const idVec3 &v );
-	void	AddBounds( const Bounds &bb );
-	bool	IsCleared();
-	bool	ContainsPoint( const idVec3 &p );
-	bool	IntersectsBounds( const Bounds &b2 );	// touching is NOT intersecting
-};
-
-extern Bounds	boundsZero;
-
-ID_INLINE Bounds::Bounds(){
-}
-
-ID_INLINE bool Bounds::IsCleared() {
-	return b[0][0] > b[1][0];
-}
-
-ID_INLINE bool Bounds::ContainsPoint( const idVec3 &p ) {
-	if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
-		|| p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
-		return false;
-	}
-	return true;
-}
-
-ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
-	if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
-		|| b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
-		return false;
-	}
-	return true;
-}
-
-ID_INLINE Bounds::Bounds( const idVec3 &mins, const idVec3 &maxs ) {
-	b[0] = mins;
-	b[1] = maxs;
-}
-
-ID_INLINE idVec3 Bounds::Center() {
-	return idVec3( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
-}
-
-ID_INLINE void Bounds::Clear() {
-	b[0][0] = b[0][1] = b[0][2] = 99999;
-	b[1][0] = b[1][1] = b[1][2] = -99999;
-}
-
-ID_INLINE void Bounds::Zero() {
-	b[0][0] = b[0][1] = b[0][2] =
-	b[1][0] = b[1][1] = b[1][2] = 0;
-}
-
-ID_INLINE void Bounds::AddPoint( const idVec3 &v ) {
-	if ( v[0] < b[0][0]) {
-		b[0][0] = v[0];
-	}
-	if ( v[0] > b[1][0]) {
-		b[1][0] = v[0];
-	}
-	if ( v[1] < b[0][1] ) {
-		b[0][1] = v[1];
-	}
-	if ( v[1] > b[1][1]) {
-		b[1][1] = v[1];
-	}
-	if ( v[2] < b[0][2] ) {
-		b[0][2] = v[2];
-	}
-	if ( v[2] > b[1][2]) {
-		b[1][2] = v[2];
-	}
-}
-
-
-ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
-	if ( bb.b[0][0] < b[0][0]) {
-		b[0][0] = bb.b[0][0];
-	}
-	if ( bb.b[0][1] < b[0][1]) {
-		b[0][1] = bb.b[0][1];
-	}
-	if ( bb.b[0][2] < b[0][2]) {
-		b[0][2] = bb.b[0][2];
-	}
-
-	if ( bb.b[1][0] > b[1][0]) {
-		b[1][0] = bb.b[1][0];
-	}
-	if ( bb.b[1][1] > b[1][1]) {
-		b[1][1] = bb.b[1][1];
-	}
-	if ( bb.b[1][2] > b[1][2]) {
-		b[1][2] = bb.b[1][2];
-	}
-}
-
-ID_INLINE float Bounds::Radius( ) {
-	int		i;
-	float	total;
-	float	a, aa;
-
-	total = 0;
-	for (i=0 ; i<3 ; i++) {
-		a = (float)fabs( b[0][i] );
-		aa = (float)fabs( b[1][i] );
-		if ( aa > a ) {
-			a = aa;
-		}
-		total += a * a;
-	}
-
-	return (float)idSqrt( total );
-}
-
-//===============================================================
-
-
-class idVec2 {
-public:
-	float			x;
-	float			y;
-
-					operator float *();
-	float			operator[]( int index ) const;
-	float			&operator[]( int index );
-};
-
-ID_INLINE float idVec2::operator[]( int index ) const {
-	return ( &x )[ index ];
-}
-
-ID_INLINE float& idVec2::operator[]( int index ) {
-	return ( &x )[ index ];
-}
-
-ID_INLINE idVec2::operator float *( void ) {
-	return &x;
-}
-
-class idVec4 : public idVec3 {
-public:
-#ifndef	FAT_VEC3
-	float			dist;
-#endif
-	idVec4();
-	~idVec4() {};
-	
-	idVec4( float x, float y, float z, float dist );
-	float			operator[]( int index ) const;
-	float			&operator[]( int index );
-};
-
-ID_INLINE idVec4::idVec4() {}
-ID_INLINE idVec4::idVec4( float x, float y, float z, float dist ) {
-	this->x = x;
-	this->y = y;
-	this->z = z;
-	this->dist = dist;
-}
-
-ID_INLINE float idVec4::operator[]( int index ) const {
-	return ( &x )[ index ];
-}
-
-ID_INLINE float& idVec4::operator[]( int index ) {
-	return ( &x )[ index ];
-}
-
-
-class idVec5_t : public idVec3 {
-public:
-	float			s;
-	float			t;
-	float			operator[]( int index ) const;
-	float			&operator[]( int index );
-};
-
-
-ID_INLINE float idVec5_t::operator[]( int index ) const {
-	return ( &x )[ index ];
-}
-
-ID_INLINE float& idVec5_t::operator[]( int index ) {
-	return ( &x )[ index ];
-}
-
-#endif /* !__MATH_VECTOR_H__ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __MATH_VECTOR_H__
+#define __MATH_VECTOR_H__
+
+#ifdef _WIN32
+#pragma warning(disable : 4244)
+#endif
+
+#include <math.h>
+#include <assert.h>
+
+//#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+//#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+//#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+//#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+//#define VectorCopy(a,b)			((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
+
+//#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
+#define	__VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
+//#define CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+
+#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
+#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
+#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
+#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
+#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
+
+
+//#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0)
+#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
+//#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
+#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+
+#define	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
+
+
+//#include "util_heap.h"
+
+#ifndef EQUAL_EPSILON
+#define EQUAL_EPSILON	0.001
+#endif
+
+float Q_fabs( float f );
+
+#ifndef ID_INLINE
+#ifdef _WIN32
+#define ID_INLINE __inline 
+#else
+#define ID_INLINE inline
+#endif
+#endif
+
+// if this is defined, vec3 will take four elements, which may allow
+// easier SIMD optimizations
+//#define	FAT_VEC3
+//#ifdef __ppc__
+//#pragma align(16)
+//#endif
+
+class angles_t;
+#ifdef __ppc__
+// Vanilla PPC code, but since PPC has a reciprocal square root estimate instruction, 
+// runs *much* faster than calling sqrt(). We'll use two Newton-Raphson 
+// refinement steps to get bunch more precision in the 1/sqrt() value for very little cost. 
+// We'll then multiply 1/sqrt times the original value to get the sqrt. 
+// This is about 12.4 times faster than sqrt() and according to my testing (not exhaustive) 
+// it returns fairly accurate results (error below 1.0e-5 up to 100000.0 in 0.1 increments). 
+
+static inline float idSqrt(float x) {
+    const float half = 0.5;
+    const float one = 1.0;
+    float B, y0, y1;
+
+    // This'll NaN if it hits frsqrte. Handle both +0.0 and -0.0
+    if (fabs(x) == 0.0)
+        return x;
+    B = x;
+    
+#ifdef __GNUC__
+    asm("frsqrte %0,%1" : "=f" (y0) : "f" (B));
+#else
+    y0 = __frsqrte(B);
+#endif
+    /* First refinement step */
+    
+    y1 = y0 + half*y0*(one - B*y0*y0);
+    
+    /* Second refinement step -- copy the output of the last step to the input of this step */
+    
+    y0 = y1;
+    y1 = y0 + half*y0*(one - B*y0*y0);
+    
+    /* Get sqrt(x) from x * 1/sqrt(x) */
+    return x * y1;
+}
+#else
+static inline double idSqrt(double x) {
+    return sqrt(x);
+}
+#endif
+
+
+//class idVec3  : public idHeap<idVec3> {
+class idVec3 {
+public:	
+#ifndef	FAT_VEC3
+	    float x,y,z;
+#else
+	    float x,y,z,dist;
+#endif
+
+#ifndef	FAT_VEC3
+					idVec3() {};
+#else
+					idVec3() {dist = 0.0f;};
+#endif
+					idVec3( const float x, const float y, const float z );
+
+					operator float *();
+
+	float			operator[]( const int index ) const;
+	float			&operator[]( const int index );
+
+	void 			set( const float x, const float y, const float z );
+
+	idVec3			operator-() const;
+
+	idVec3			&operator=( const idVec3 &a );
+
+	float			operator*( const idVec3 &a ) const;
+	idVec3			operator*( const float a ) const;
+	friend idVec3	operator*( float a, idVec3 b );
+
+	idVec3			operator+( const idVec3 &a ) const;
+	idVec3			operator-( const idVec3 &a ) const;
+	
+	idVec3			&operator+=( const idVec3 &a );
+	idVec3			&operator-=( const idVec3 &a );
+	idVec3			&operator*=( const float a );
+
+	int				operator==(	const idVec3 &a ) const;
+	int				operator!=(	const idVec3 &a ) const;
+
+	idVec3			Cross( const idVec3 &a ) const;
+	idVec3			&Cross( const idVec3 &a, const idVec3 &b );
+
+	float			Length( void ) const;
+	float			Normalize( void );
+
+	void			Zero( void );
+	void			Snap( void );
+	void			SnapTowards( const idVec3 &to );
+
+	float			toYaw( void );
+	float			toPitch( void );
+	angles_t		toAngles( void );
+	friend idVec3	LerpVector( const idVec3 &w1, const idVec3 &w2, const float t );
+
+	char			*string( void );
+};
+
+extern idVec3 vec_zero;
+
+ID_INLINE idVec3::idVec3( const float x, const float y, const float z ) {
+	this->x = x;
+	this->y = y;
+	this->z = z;
+#ifdef	FAT_VEC3
+	this->dist = 0.0f;
+#endif
+}
+
+ID_INLINE float idVec3::operator[]( const int index ) const {
+	return ( &x )[ index ];
+}
+
+ID_INLINE float &idVec3::operator[]( const int index ) {
+	return ( &x )[ index ];
+}
+
+ID_INLINE idVec3::operator float *( void ) {
+	return &x;
+}
+
+ID_INLINE idVec3 idVec3::operator-() const {
+	return idVec3( -x, -y, -z );
+}
+	
+ID_INLINE idVec3 &idVec3::operator=( const idVec3 &a ) { 
+	x = a.x;
+	y = a.y;
+	z = a.z;
+	
+	return *this;
+}
+
+ID_INLINE void idVec3::set( const float x, const float y, const float z ) {
+	this->x = x;
+	this->y = y;
+	this->z = z;
+}
+
+ID_INLINE idVec3 idVec3::operator-( const idVec3 &a ) const {
+	return idVec3( x - a.x, y - a.y, z - a.z );
+}
+
+ID_INLINE float idVec3::operator*( const idVec3 &a ) const {
+	return x * a.x + y * a.y + z * a.z;
+}
+
+ID_INLINE idVec3 idVec3::operator*( const float a ) const {
+	return idVec3( x * a, y * a, z * a );
+}
+
+ID_INLINE idVec3 operator*( const float a, const idVec3 b ) {
+	return idVec3( b.x * a, b.y * a, b.z * a );
+}
+
+ID_INLINE idVec3 idVec3::operator+( const idVec3 &a ) const {
+	return idVec3( x + a.x, y + a.y, z + a.z );
+}
+
+ID_INLINE idVec3 &idVec3::operator+=( const idVec3 &a ) {
+	x += a.x;
+	y += a.y;
+	z += a.z;
+
+	return *this;
+}
+
+ID_INLINE idVec3 &idVec3::operator-=( const idVec3 &a ) {
+	x -= a.x;
+	y -= a.y;
+	z -= a.z;
+
+	return *this;
+}
+
+ID_INLINE idVec3 &idVec3::operator*=( const float a ) {
+	x *= a;
+	y *= a;
+	z *= a;
+
+	return *this;
+}
+
+ID_INLINE int idVec3::operator==( const idVec3 &a ) const {
+	if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
+		return false;
+	}
+			
+	if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
+		return false;
+	}
+
+	if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
+		return false;
+	}
+
+	return true;
+}
+
+ID_INLINE int idVec3::operator!=( const idVec3 &a ) const {
+	if ( Q_fabs( x - a.x ) > EQUAL_EPSILON ) {
+		return true;
+	}
+			
+	if ( Q_fabs( y - a.y ) > EQUAL_EPSILON ) {
+		return true;
+	}
+
+	if ( Q_fabs( z - a.z ) > EQUAL_EPSILON ) {
+		return true;
+	}
+
+	return false;
+}
+
+ID_INLINE idVec3 idVec3::Cross( const idVec3 &a ) const {
+	return idVec3( y * a.z - z * a.y, z * a.x - x * a.z, x * a.y - y * a.x );
+}
+
+ID_INLINE idVec3 &idVec3::Cross( const idVec3 &a, const idVec3 &b ) {
+	x = a.y * b.z - a.z * b.y;
+	y = a.z * b.x - a.x * b.z;
+	z = a.x * b.y - a.y * b.x;
+
+	return *this;
+}
+
+ID_INLINE float idVec3::Length( void ) const {
+	float length;
+	
+	length = x * x + y * y + z * z;
+	return ( float )idSqrt( length );
+}
+
+ID_INLINE float idVec3::Normalize( void ) {
+	float length;
+	float ilength;
+
+	length = this->Length();
+	if ( length ) {
+		ilength = 1.0f / length;
+		x *= ilength;
+		y *= ilength;
+		z *= ilength;
+	}
+		
+	return length;
+}
+
+ID_INLINE void idVec3::Zero( void ) {
+	x = 0.0f;
+	y = 0.0f;
+	z = 0.0f;
+}
+
+ID_INLINE void idVec3::Snap( void ) {
+	x = float( int( x ) );
+	y = float( int( y ) );
+	z = float( int( z ) );
+}
+
+/*
+======================
+SnapTowards
+
+Round a vector to integers for more efficient network
+transmission, but make sure that it rounds towards a given point
+rather than blindly truncating.  This prevents it from truncating 
+into a wall.
+======================
+*/
+ID_INLINE void idVec3::SnapTowards( const idVec3 &to ) {
+	if ( to.x <= x ) {
+		x = float( int( x ) );
+	} else {
+		x = float( int( x ) + 1 );
+	}
+
+	if ( to.y <= y ) {
+		y = float( int( y ) );
+	} else {
+		y = float( int( y ) + 1 );
+	}
+
+	if ( to.z <= z ) {
+		z = float( int( z ) );
+	} else {
+		z = float( int( z ) + 1 );
+	}
+}
+
+//===============================================================
+
+class Bounds {
+public:
+	idVec3	b[2];
+
+			Bounds();
+			Bounds( const idVec3 &mins, const idVec3 &maxs );
+
+	void	Clear();
+	void	Zero();
+	float	Radius();		// radius from origin, not from center
+	idVec3	Center();
+	void	AddPoint( const idVec3 &v );
+	void	AddBounds( const Bounds &bb );
+	bool	IsCleared();
+	bool	ContainsPoint( const idVec3 &p );
+	bool	IntersectsBounds( const Bounds &b2 );	// touching is NOT intersecting
+};
+
+extern Bounds	boundsZero;
+
+ID_INLINE Bounds::Bounds(){
+}
+
+ID_INLINE bool Bounds::IsCleared() {
+	return b[0][0] > b[1][0];
+}
+
+ID_INLINE bool Bounds::ContainsPoint( const idVec3 &p ) {
+	if ( p[0] < b[0][0] || p[1] < b[0][1] || p[2] < b[0][2]
+		|| p[0] > b[1][0] || p[1] > b[1][1] || p[2] > b[1][2] ) {
+		return false;
+	}
+	return true;
+}
+
+ID_INLINE bool Bounds::IntersectsBounds( const Bounds &b2 ) {
+	if ( b2.b[1][0] < b[0][0] || b2.b[1][1] < b[0][1] || b2.b[1][2] < b[0][2]
+		|| b2.b[0][0] > b[1][0] || b2.b[0][1] > b[1][1] || b2.b[0][2] > b[1][2] ) {
+		return false;
+	}
+	return true;
+}
+
+ID_INLINE Bounds::Bounds( const idVec3 &mins, const idVec3 &maxs ) {
+	b[0] = mins;
+	b[1] = maxs;
+}
+
+ID_INLINE idVec3 Bounds::Center() {
+	return idVec3( ( b[1][0] + b[0][0] ) * 0.5f, ( b[1][1] + b[0][1] ) * 0.5f, ( b[1][2] + b[0][2] ) * 0.5f );
+}
+
+ID_INLINE void Bounds::Clear() {
+	b[0][0] = b[0][1] = b[0][2] = 99999;
+	b[1][0] = b[1][1] = b[1][2] = -99999;
+}
+
+ID_INLINE void Bounds::Zero() {
+	b[0][0] = b[0][1] = b[0][2] =
+	b[1][0] = b[1][1] = b[1][2] = 0;
+}
+
+ID_INLINE void Bounds::AddPoint( const idVec3 &v ) {
+	if ( v[0] < b[0][0]) {
+		b[0][0] = v[0];
+	}
+	if ( v[0] > b[1][0]) {
+		b[1][0] = v[0];
+	}
+	if ( v[1] < b[0][1] ) {
+		b[0][1] = v[1];
+	}
+	if ( v[1] > b[1][1]) {
+		b[1][1] = v[1];
+	}
+	if ( v[2] < b[0][2] ) {
+		b[0][2] = v[2];
+	}
+	if ( v[2] > b[1][2]) {
+		b[1][2] = v[2];
+	}
+}
+
+
+ID_INLINE void Bounds::AddBounds( const Bounds &bb ) {
+	if ( bb.b[0][0] < b[0][0]) {
+		b[0][0] = bb.b[0][0];
+	}
+	if ( bb.b[0][1] < b[0][1]) {
+		b[0][1] = bb.b[0][1];
+	}
+	if ( bb.b[0][2] < b[0][2]) {
+		b[0][2] = bb.b[0][2];
+	}
+
+	if ( bb.b[1][0] > b[1][0]) {
+		b[1][0] = bb.b[1][0];
+	}
+	if ( bb.b[1][1] > b[1][1]) {
+		b[1][1] = bb.b[1][1];
+	}
+	if ( bb.b[1][2] > b[1][2]) {
+		b[1][2] = bb.b[1][2];
+	}
+}
+
+ID_INLINE float Bounds::Radius( ) {
+	int		i;
+	float	total;
+	float	a, aa;
+
+	total = 0;
+	for (i=0 ; i<3 ; i++) {
+		a = (float)fabs( b[0][i] );
+		aa = (float)fabs( b[1][i] );
+		if ( aa > a ) {
+			a = aa;
+		}
+		total += a * a;
+	}
+
+	return (float)idSqrt( total );
+}
+
+//===============================================================
+
+
+class idVec2 {
+public:
+	float			x;
+	float			y;
+
+					operator float *();
+	float			operator[]( int index ) const;
+	float			&operator[]( int index );
+};
+
+ID_INLINE float idVec2::operator[]( int index ) const {
+	return ( &x )[ index ];
+}
+
+ID_INLINE float& idVec2::operator[]( int index ) {
+	return ( &x )[ index ];
+}
+
+ID_INLINE idVec2::operator float *( void ) {
+	return &x;
+}
+
+class idVec4 : public idVec3 {
+public:
+#ifndef	FAT_VEC3
+	float			dist;
+#endif
+	idVec4();
+	~idVec4() {};
+	
+	idVec4( float x, float y, float z, float dist );
+	float			operator[]( int index ) const;
+	float			&operator[]( int index );
+};
+
+ID_INLINE idVec4::idVec4() {}
+ID_INLINE idVec4::idVec4( float x, float y, float z, float dist ) {
+	this->x = x;
+	this->y = y;
+	this->z = z;
+	this->dist = dist;
+}
+
+ID_INLINE float idVec4::operator[]( int index ) const {
+	return ( &x )[ index ];
+}
+
+ID_INLINE float& idVec4::operator[]( int index ) {
+	return ( &x )[ index ];
+}
+
+
+class idVec5_t : public idVec3 {
+public:
+	float			s;
+	float			t;
+	float			operator[]( int index ) const;
+	float			&operator[]( int index );
+};
+
+
+ID_INLINE float idVec5_t::operator[]( int index ) const {
+	return ( &x )[ index ];
+}
+
+ID_INLINE float& idVec5_t::operator[]( int index ) {
+	return ( &x )[ index ];
+}
+
+#endif /* !__MATH_VECTOR_H__ */
diff --git a/libs/splines/q_shared.h b/libs/splines/q_shared.h
index 1fc7d818..60261cb4 100644
--- a/libs/splines/q_shared.h
+++ b/libs/splines/q_shared.h
@@ -1,796 +1,796 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __Q_SHARED_H
-#define __Q_SHARED_H
-
-// q_shared.h -- included first by ALL program modules.
-// these are the definitions that have no dependance on
-// central system services, and can be used by any part
-// of the program without any state issues.
-
-// A user mod should never modify this file
-
-#define	Q3_VERSION		"DOOM 0.01"
-
-// alignment macros for SIMD
-#define	ALIGN_ON
-#define	ALIGN_OFF
-
-#ifdef _WIN32
-
-#pragma warning(disable : 4018)     // signed/unsigned mismatch
-#pragma warning(disable : 4032)
-#pragma warning(disable : 4051)
-#pragma warning(disable : 4057)		// slightly different base types
-#pragma warning(disable : 4100)		// unreferenced formal parameter
-#pragma warning(disable : 4115)
-#pragma warning(disable : 4125)		// decimal digit terminates octal escape sequence
-#pragma warning(disable : 4127)		// conditional expression is constant
-#pragma warning(disable : 4136)
-#pragma warning(disable : 4201)
-#pragma warning(disable : 4214)
-#pragma warning(disable : 4244)
-#pragma warning(disable : 4305)		// truncation from const double to float
-#pragma warning(disable : 4310)		// cast truncates constant value
-#pragma warning(disable : 4514)
-#pragma warning(disable : 4711)		// selected for automatic inline expansion
-#pragma warning(disable : 4220)		// varargs matches remaining parameters
-
-#endif
-
-#include <assert.h>
-#include <math.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <stdlib.h>
-#include <time.h>
-#include <ctype.h>
-#ifdef _WIN32				// mac doesn't have malloc.h
-#include <malloc.h>			// for _alloca()
-#endif
-#ifdef _WIN32
-
-//#pragma intrinsic( memset, memcpy )
-
-#endif
-
-
-// this is the define for determining if we have an asm version of a C function
-#if (defined _M_IX86 || defined __i386__) && !defined __sun__  && !defined __LCC__
-#define id386	1
-#else
-#define id386	0
-#endif
-
-// for windows fastcall option
-
-#define	QDECL
-
-//======================= WIN32 DEFINES =================================
-
-#ifdef _WIN32
-
-#define	MAC_STATIC
-
-#undef QDECL
-#define	QDECL	__cdecl
-
-// buildstring will be incorporated into the version string
-#ifdef NDEBUG
-#ifdef _M_IX86
-#define	CPUSTRING	"win-x86"
-#elif defined _M_ALPHA
-#define	CPUSTRING	"win-AXP"
-#endif
-#else
-#ifdef _M_IX86
-#define	CPUSTRING	"win-x86-debug"
-#elif defined _M_ALPHA
-#define	CPUSTRING	"win-AXP-debug"
-#endif
-#endif
-
-
-#define	PATH_SEP '\\'
-
-#endif
-
-//======================= MAC OS X SERVER DEFINES =====================
-
-#if defined(__MACH__) && defined(__APPLE__)
-
-#define MAC_STATIC
-
-#ifdef __ppc__
-#define CPUSTRING	"MacOSXS-ppc"
-#elif defined __i386__
-#define CPUSTRING	"MacOSXS-i386"
-#else
-#define CPUSTRING	"MacOSXS-other"
-#endif
-
-#define	PATH_SEP	'/'
-
-#define	GAME_HARD_LINKED
-#define	CGAME_HARD_LINKED
-#define	UI_HARD_LINKED
-#define _alloca alloca
-
-#undef ALIGN_ON
-#undef ALIGN_OFF
-#define	ALIGN_ON		#pragma align(16)
-#define	ALIGN_OFF		#pragma align()
-
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-void *osxAllocateMemory(long size);
-void osxFreeMemory(void *pointer);
-
-#ifdef __cplusplus
-        }
-#endif
-
-#endif
-
-//======================= MAC DEFINES =================================
-
-#ifdef __MACOS__
-
-#define	MAC_STATIC static
-
-#define	CPUSTRING	"MacOS-PPC"
-
-#define	PATH_SEP ':'
-
-void Sys_PumpEvents( void );
-
-#endif
-
-#ifdef __MRC__
-
-#define	MAC_STATIC
-
-#define	CPUSTRING	"MacOS-PPC"
-
-#define	PATH_SEP ':'
-
-void Sys_PumpEvents( void );
-
-#undef QDECL
-#define	QDECL	__cdecl
-
-#define _alloca alloca
-#endif
-
-//======================= LINUX DEFINES =================================
-
-// the mac compiler can't handle >32k of locals, so we
-// just waste space and make big arrays static...
-#ifdef __linux__
-
-#define	MAC_STATIC
-
-#ifdef __i386__
-#define	CPUSTRING	"linux-i386"
-#elif defined __axp__
-#define	CPUSTRING	"linux-alpha"
-#else
-#define	CPUSTRING	"linux-other"
-#endif
-
-#define	PATH_SEP '/'
-
-#endif
-
-//=============================================================
-  
-typedef enum {qfalse, qtrue}	qboolean;
-
-typedef unsigned char 		byte;
-
-#define	EQUAL_EPSILON	0.001
-
-typedef int		qhandle_t;
-typedef int		sfxHandle_t;
-typedef int		fileHandle_t;
-typedef int		clipHandle_t;
-
-typedef enum {
-	INVALID_JOINT = -1
-} jointHandle_t;
-
-#ifndef NULL
-#define NULL ((void *)0)
-#endif
-
-#define	MAX_QINT			0x7fffffff
-#define	MIN_QINT			(-MAX_QINT-1)
-
-#ifndef max
-#define max( x, y ) ( ( ( x ) > ( y ) ) ? ( x ) : ( y ) )
-#define min( x, y ) ( ( ( x ) < ( y ) ) ? ( x ) : ( y ) )
-#endif
-
-#ifndef sign
-#define sign( f )	( ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ) )
-#endif
-
-// angle indexes
-#define	PITCH				0		// up / down
-#define	YAW					1		// left / right
-#define	ROLL				2		// fall over
-
-// the game guarantees that no string from the network will ever
-// exceed MAX_STRING_CHARS
-#define	MAX_STRING_CHARS	1024	// max length of a string passed to Cmd_TokenizeString
-#define	MAX_STRING_TOKENS	256		// max tokens resulting from Cmd_TokenizeString
-#define	MAX_TOKEN_CHARS		1024	// max length of an individual token
-
-#define	MAX_INFO_STRING		1024
-#define	MAX_INFO_KEY		1024
-#define	MAX_INFO_VALUE		1024
-
-
-#define	MAX_QPATH			64		// max length of a quake game pathname
-#define	MAX_OSPATH			128		// max length of a filesystem pathname
-
-#define	MAX_NAME_LENGTH		32		// max length of a client name
-
-// paramters for command buffer stuffing
-typedef enum {
-	EXEC_NOW,			// don't return until completed, a VM should NEVER use this,
-						// because some commands might cause the VM to be unloaded...
-	EXEC_INSERT,		// insert at current position, but don't run yet
-	EXEC_APPEND			// add to end of the command buffer (normal case)
-} cbufExec_t;
-
-
-//
-// these aren't needed by any of the VMs.  put in another header?
-//
-#define	MAX_MAP_AREA_BYTES		32		// bit vector of area visibility
-
-#undef ERR_FATAL						// malloc.h on unix
-
-// parameters to the main Error routine
-typedef enum {
-	ERR_NONE,
-	ERR_FATAL,					// exit the entire game with a popup window
-	ERR_DROP,					// print to console and disconnect from game
-	ERR_DISCONNECT,				// don't kill server
-	ERR_NEED_CD					// pop up the need-cd dialog
-} errorParm_t;
-
-
-// font rendering values used by ui and cgame
-
-#define PROP_GAP_WIDTH			3
-#define PROP_SPACE_WIDTH		8
-#define PROP_HEIGHT				27
-#define PROP_SMALL_SIZE_SCALE	0.75
-
-#define BLINK_DIVISOR			200
-#define PULSE_DIVISOR			75
-
-#define UI_LEFT			0x00000000	// default
-#define UI_CENTER		0x00000001
-#define UI_RIGHT		0x00000002
-#define UI_FORMATMASK	0x00000007
-#define UI_SMALLFONT	0x00000010
-#define UI_BIGFONT		0x00000020	// default
-#define UI_GIANTFONT	0x00000040
-#define UI_DROPSHADOW	0x00000800
-#define UI_BLINK		0x00001000
-#define UI_INVERSE		0x00002000
-#define UI_PULSE		0x00004000
-
-
-/*
-==============================================================
-
-MATHLIB
-
-==============================================================
-*/
-#ifdef __cplusplus			// so we can include this in C code
-#define	SIDE_FRONT		0
-#define	SIDE_BACK		1
-#define	SIDE_ON			2
-#define	SIDE_CROSS		3
-
-#define	Q_PI	3.14159265358979323846
-#ifndef M_PI
-#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
-#endif
-
-#include "math_vector.h"
-#include "math_angles.h"
-#include "math_matrix.h"
-#include "math_quaternion.h"
-
-class idVec3;						// for defining vectors
-typedef idVec3 &vec3_p;				// for passing vectors as function arguments
-typedef const idVec3 &vec3_c;		// for passing vectors as const function arguments
-									
-class angles_t;						// for defining angle vectors
-typedef angles_t &angles_p;			// for passing angles as function arguments
-typedef const angles_t &angles_c;	// for passing angles as const function arguments
-
-class mat3_t;						// for defining matrices
-typedef mat3_t &mat3_p;				// for passing matrices as function arguments
-typedef const mat3_t &mat3_c;		// for passing matrices as const function arguments
-
-
-
-#define NUMVERTEXNORMALS	162
-extern	idVec3	bytedirs[NUMVERTEXNORMALS];
-
-// all drawing is done to a 640*480 virtual screen size
-// and will be automatically scaled to the real resolution
-#define	SCREEN_WIDTH		640
-#define	SCREEN_HEIGHT		480
-
-#define TINYCHAR_WIDTH		(SMALLCHAR_WIDTH)
-#define TINYCHAR_HEIGHT		(SMALLCHAR_HEIGHT/2)
-
-#define SMALLCHAR_WIDTH		8
-#define SMALLCHAR_HEIGHT	16
-
-#define BIGCHAR_WIDTH		16
-#define BIGCHAR_HEIGHT		16
-
-#define	GIANTCHAR_WIDTH		32
-#define	GIANTCHAR_HEIGHT	48
-
-extern	idVec4		colorBlack;
-extern	idVec4		colorRed;
-extern	idVec4		colorGreen;
-extern	idVec4		colorBlue;
-extern	idVec4		colorYellow;
-extern	idVec4		colorMagenta;
-extern	idVec4		colorCyan;
-extern	idVec4		colorWhite;
-extern	idVec4		colorLtGrey;
-extern	idVec4		colorMdGrey;
-extern	idVec4		colorDkGrey;
-
-#define Q_COLOR_ESCAPE	'^'
-#define Q_IsColorString(p)	( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE )
-
-#define COLOR_BLACK		'0'
-#define COLOR_RED		'1'
-#define COLOR_GREEN		'2'
-#define COLOR_YELLOW	'3'
-#define COLOR_BLUE		'4'
-#define COLOR_CYAN		'5'
-#define COLOR_MAGENTA	'6'
-#define COLOR_WHITE		'7'
-#define ColorIndex(c)	( ( (c) - '0' ) & 7 )
-
-#define S_COLOR_BLACK	"^0"
-#define S_COLOR_RED		"^1"
-#define S_COLOR_GREEN	"^2"
-#define S_COLOR_YELLOW	"^3"
-#define S_COLOR_BLUE	"^4"
-#define S_COLOR_CYAN	"^5"
-#define S_COLOR_MAGENTA	"^6"
-#define S_COLOR_WHITE	"^7"
-
-extern idVec4	g_color_table[8];
-
-#define	MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b
-#define	MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a
-
-#define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F )
-#define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI )
-
-struct cplane_s;
-
-extern	idVec3	vec3_origin;
-extern	idVec4	vec4_origin;
-extern	mat3_t	axisDefault;
-
-#define	nanmask (255<<23)
-
-#define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
-
-float Q_fabs( float f );
-float Q_rsqrt( float f );		// reciprocal square root
-
-#define SQRTFAST( x ) ( 1.0f / Q_rsqrt( x ) )
-
-signed char ClampChar( int i );
-signed short ClampShort( int i );
-
-// this isn't a real cheap function to call!
-int DirToByte( const idVec3 &dir );
-void ByteToDir( int b, vec3_p dir );
-
-#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
-#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
-#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
-#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
-//#define VectorCopy(a,b)			((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
-
-#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
-#define	VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
-#define CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
-
-#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
-#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
-#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
-#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
-#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
-#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
-
-
-#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0)
-#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
-#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
-#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
-
-#define	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
-
-float NormalizeColor( vec3_c in, vec3_p out );
-
-int VectorCompare( vec3_c v1, vec3_c v2 );
-float VectorLength( vec3_c v );
-float Distance( vec3_c p1, vec3_c p2 );
-float DistanceSquared( vec3_c p1, vec3_c p2 );
-float VectorNormalize (vec3_p v);		// returns vector length
-void VectorNormalizeFast(vec3_p v);		// does NOT return vector length, uses rsqrt approximation
-float VectorNormalize2( vec3_c v, vec3_p out );
-void VectorInverse (vec3_p v);
-void VectorRotate( vec3_c in, mat3_c matrix, vec3_p out );
-void VectorPolar(vec3_p v, float radius, float theta, float phi);
-void VectorSnap(vec3_p v);
-void Vector53Copy( const idVec5_t &in, vec3_p out);
-void Vector5Scale( const idVec5_t &v, float scale, idVec5_t &out);
-void Vector5Add( const idVec5_t &va, const idVec5_t &vb, idVec5_t &out);
-void VectorRotate3( vec3_c vIn, vec3_c vRotation, vec3_p out);
-void VectorRotate3Origin(vec3_c vIn, vec3_c vRotation, vec3_c vOrigin, vec3_p out);
-
-
-int Q_log2(int val);
-
-int		Q_rand( int *seed );
-float	Q_random( int *seed );
-float	Q_crandom( int *seed );
-
-#define random()	((rand () & 0x7fff) / ((float)0x7fff))
-#define crandom()	(2.0 * (random() - 0.5))
-
-float Q_rint( float in );
-
-void vectoangles( vec3_c value1, angles_p angles);
-void AnglesToAxis( angles_c angles, mat3_p axis );
-
-void AxisCopy( mat3_c in, mat3_p out );
-qboolean AxisRotated( mat3_c in );			// assumes a non-degenerate axis
-
-int SignbitsForNormal( vec3_c normal );
-int BoxOnPlaneSide( const Bounds &b, struct cplane_s *p );
-
-float	AngleMod(float a);
-float	LerpAngle (float from, float to, float frac);
-float	AngleSubtract( float a1, float a2 );
-void	AnglesSubtract( angles_c v1, angles_c v2, angles_p v3 );
-
-float AngleNormalize360 ( float angle );
-float AngleNormalize180 ( float angle );
-float AngleDelta ( float angle1, float angle2 );
-
-qboolean PlaneFromPoints( idVec4 &plane, vec3_c a, vec3_c b, vec3_c c );
-void ProjectPointOnPlane( vec3_p dst, vec3_c p, vec3_c normal );
-void RotatePointAroundVector( vec3_p dst, vec3_c dir, vec3_c point, float degrees );
-void RotateAroundDirection( mat3_p axis, float yaw );
-void MakeNormalVectors( vec3_c forward, vec3_p right, vec3_p up );
-// perpendicular vector could be replaced by this
-
-int	PlaneTypeForNormal( vec3_c normal );
-
-void MatrixMultiply( mat3_c in1, mat3_c in2, mat3_p out );
-void MatrixInverseMultiply( mat3_c in1, mat3_c in2, mat3_p out );	// in2 is transposed during multiply
-void MatrixTransformVector( vec3_c in, mat3_c matrix, vec3_p out );
-void MatrixProjectVector( vec3_c in, mat3_c matrix, vec3_p out ); // Places the vector into a new coordinate system.
-void AngleVectors( angles_c angles, vec3_p forward, vec3_p right, vec3_p up);
-void PerpendicularVector( vec3_p dst, vec3_c src );
-
-float TriangleArea( vec3_c a, vec3_c b, vec3_c c );
-#endif										// __cplusplus
-
-//=============================================
-
-float Com_Clamp( float min, float max, float value );
-
-#define FILE_HASH_SIZE		1024
-int Com_HashString( const char *fname );
-
-char	*Com_SkipPath( char *pathname );
-
-// it is ok for out == in
-void	Com_StripExtension( const char *in, char *out );
-
-// "extension" should include the dot: ".map"
-void	Com_DefaultExtension( char *path, int maxSize, const char *extension );
-
-int		Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] );
-
-/*
-=====================================================================================
-
-SCRIPT PARSING
-
-=====================================================================================
-*/
-
-// this just controls the comment printing, it doesn't actually load a file
-void Com_BeginParseSession( const char *filename );
-void Com_EndParseSession( void );
-
-int Com_GetCurrentParseLine( void );
-
-// Will never return NULL, just empty strings.
-// An empty string will only be returned at end of file.
-// ParseOnLine will return empty if there isn't another token on this line
-
-// this funny typedef just means a moving pointer into a const char * buffer
-const char *Com_Parse( const char *(*data_p) );
-const char *Com_ParseOnLine( const char *(*data_p) );
-const char *Com_ParseRestOfLine( const char *(*data_p) );
-
-void Com_UngetToken( void );
-
-#ifdef __cplusplus
-void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning = qfalse );
-#else
-void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning );
-#endif
-
-void Com_ScriptError( const char *msg, ... );
-void Com_ScriptWarning( const char *msg, ... );
-
-void Com_SkipBracedSection( const char *(*program) );
-void Com_SkipRestOfLine( const char *(*data) );
-
-float Com_ParseFloat( const char *(*buf_p) );
-int	Com_ParseInt( const char *(*buf_p) );
-
-void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m );
-void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m );
-void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m );
-
-//=====================================================================================
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-void	QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
-
-
-// mode parm for FS_FOpenFile
-typedef enum {
-	FS_READ,
-	FS_WRITE,
-	FS_APPEND,
-	FS_APPEND_SYNC
-} fsMode_t;
-
-typedef enum {
-	FS_SEEK_CUR,
-	FS_SEEK_END,
-	FS_SEEK_SET
-} fsOrigin_t;
-
-//=============================================
-
-int Q_isprint( int c );
-int Q_islower( int c );
-int Q_isupper( int c );
-int Q_isalpha( int c );
-
-// portable case insensitive compare
-int		Q_stricmp (const char *s1, const char *s2);
-int		Q_strncmp (const char *s1, const char *s2, int n);
-int		Q_stricmpn (const char *s1, const char *s2, int n);
-char	*Q_strlwr( char *s1 );
-char	*Q_strupr( char *s1 );
-char	*Q_strrchr( const char* string, int c );
-
-// buffer size safe library replacements
-void	Q_strncpyz( char *dest, const char *src, int destsize );
-void	Q_strcat( char *dest, int size, const char *src );
-
-// strlen that discounts Quake color sequences
-int Q_PrintStrlen( const char *string );
-// removes color sequences from string
-char *Q_CleanStr( char *string );
-
-int			Com_Filter( const char *filter, const char *name, int casesensitive );
-const char *Com_StringContains( const char *str1, const char *str2, int casesensitive );
-
-
-//=============================================
-
-short	BigShort(short l);
-short	LittleShort(short l);
-int		BigLong (int l);
-int		LittleLong (int l);
-float	BigFloat (float l);
-float	LittleFloat (float l);
-
-void	Swap_Init (void);
-char	* QDECL va(char *format, ...);
-
-#ifdef __cplusplus
-    }
-#endif
-
-
-//=============================================
-#ifdef __cplusplus
-//
-// mapfile parsing
-//
-typedef struct ePair_s {
-	char	*key;
-	char	*value;
-} ePair_t;
-
-typedef struct mapSide_s {
-	char		material[MAX_QPATH];
-	idVec4		plane;
-	idVec4		textureVectors[2];
-} mapSide_t;
-
-typedef struct {
-	int			numSides;
-	mapSide_t	**sides;
-} mapBrush_t;
-
-typedef struct {
-	idVec3		xyz;
-	float		st[2];
-} patchVertex_t;
-
-typedef struct {
-	char		material[MAX_QPATH];
-	int			width, height;
-	patchVertex_t	*patchVerts;
-} mapPatch_t;
-
-typedef struct {
-	char		modelName[MAX_QPATH];
-	float		matrix[16];
-} mapModel_t;
-
-typedef struct mapPrimitive_s {
-	int				numEpairs;
-	ePair_t			**ePairs;
-
-	// only one of these will be non-NULL
-	mapBrush_t		*brush;
-	mapPatch_t		*patch;
-	mapModel_t		*model;
-} mapPrimitive_t;
-
-typedef struct mapEntity_s {
-	int				numPrimitives;
-	mapPrimitive_t	**primitives;
-
-	int				numEpairs;
-	ePair_t			**ePairs;
-} mapEntity_t;
-
-typedef struct {
-	int				numEntities;
-	mapEntity_t		**entities;
-} mapFile_t;
-
-
-// the order of entities, brushes, and sides will be maintained, the
-// lists won't be swapped on each load or save
-mapFile_t *ParseMapFile( const char *text );
-void FreeMapFile( mapFile_t *mapFile );
-void WriteMapFile( const mapFile_t *mapFile, FILE *f );
-
-// key names are case-insensitive
-const char 	*ValueForMapEntityKey( const mapEntity_t *ent, const char *key );
-float	FloatForMapEntityKey( const mapEntity_t *ent, const char *key );
-qboolean 	GetVectorForMapEntityKey( const mapEntity_t *ent, const char *key, idVec3 &vec );
-
-typedef struct {
-	idVec3		xyz;
-	idVec2		st;
-	idVec3		normal;
-	idVec3		tangents[2];
-	byte		smoothing[4];		// colors for silhouette smoothing
-} drawVert_t;
-
-typedef struct {
-	int			width, height;
-	drawVert_t	*verts;
-} drawVertMesh_t;
-
-// Tesselate a map patch into smoothed, drawable vertexes
-// MaxError of around 4 is reasonable
-drawVertMesh_t *SubdivideMapPatch( const mapPatch_t *patch, float maxError );
-#endif			// __cplusplus
-
-//=========================================
-
-#ifdef __cplusplus
-	extern "C" {
-#endif
-
-void	QDECL Com_Error( int level, const char *error, ... );
-void	QDECL Com_Printf( const char *msg, ... );
-void	QDECL Com_DPrintf( const char *msg, ... );
-
-#ifdef __cplusplus
-	}
-#endif
-
-
-typedef struct {
-	qboolean	frameMemory;
-	int		currentElements;
-	int		maxElements;		// will reallocate and move when exceeded
-	void	**elements;
-} growList_t;
-
-// you don't need to init the growlist if you don't mind it growing and moving
-// the list as it expands
-void		Com_InitGrowList( growList_t *list, int maxElements );
-int			Com_AddToGrowList( growList_t *list, void *data );
-void		*Com_GrowListElement( const growList_t *list, int index );
-int			Com_IndexForGrowListElement( const growList_t *list, const void *element );
-
-
-//
-// key / value info strings
-//
-char *Info_ValueForKey( const char *s, const char *key );
-void Info_RemoveKey( char *s, const char *key );
-void Info_SetValueForKey( char *s, const char *key, const char *value );
-qboolean Info_Validate( const char *s );
-void Info_NextPair( const char *(*s), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] );
-
-// get cvar defs, collision defs, etc
-//#include "../shared/interface.h"
-
-// get key code numbers for events
-//#include "../shared/keycodes.h"
-
-#ifdef __cplusplus
-// get the polygon winding functions
-//#include "../shared/windings.h"
-
-// get the flags class
-//#include "../shared/idflags.h"
-#endif	// __cplusplus
-
-#endif	// __Q_SHARED_H
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __Q_SHARED_H
+#define __Q_SHARED_H
+
+// q_shared.h -- included first by ALL program modules.
+// these are the definitions that have no dependance on
+// central system services, and can be used by any part
+// of the program without any state issues.
+
+// A user mod should never modify this file
+
+#define	Q3_VERSION		"DOOM 0.01"
+
+// alignment macros for SIMD
+#define	ALIGN_ON
+#define	ALIGN_OFF
+
+#ifdef _WIN32
+
+#pragma warning(disable : 4018)     // signed/unsigned mismatch
+#pragma warning(disable : 4032)
+#pragma warning(disable : 4051)
+#pragma warning(disable : 4057)		// slightly different base types
+#pragma warning(disable : 4100)		// unreferenced formal parameter
+#pragma warning(disable : 4115)
+#pragma warning(disable : 4125)		// decimal digit terminates octal escape sequence
+#pragma warning(disable : 4127)		// conditional expression is constant
+#pragma warning(disable : 4136)
+#pragma warning(disable : 4201)
+#pragma warning(disable : 4214)
+#pragma warning(disable : 4244)
+#pragma warning(disable : 4305)		// truncation from const double to float
+#pragma warning(disable : 4310)		// cast truncates constant value
+#pragma warning(disable : 4514)
+#pragma warning(disable : 4711)		// selected for automatic inline expansion
+#pragma warning(disable : 4220)		// varargs matches remaining parameters
+
+#endif
+
+#include <assert.h>
+#include <math.h>
+#include <stdio.h>
+#include <stdarg.h>
+#include <string.h>
+#include <stdlib.h>
+#include <time.h>
+#include <ctype.h>
+#ifdef _WIN32				// mac doesn't have malloc.h
+#include <malloc.h>			// for _alloca()
+#endif
+#ifdef _WIN32
+
+//#pragma intrinsic( memset, memcpy )
+
+#endif
+
+
+// this is the define for determining if we have an asm version of a C function
+#if (defined _M_IX86 || defined __i386__) && !defined __sun__  && !defined __LCC__
+#define id386	1
+#else
+#define id386	0
+#endif
+
+// for windows fastcall option
+
+#define	QDECL
+
+//======================= WIN32 DEFINES =================================
+
+#ifdef _WIN32
+
+#define	MAC_STATIC
+
+#undef QDECL
+#define	QDECL	__cdecl
+
+// buildstring will be incorporated into the version string
+#ifdef NDEBUG
+#ifdef _M_IX86
+#define	CPUSTRING	"win-x86"
+#elif defined _M_ALPHA
+#define	CPUSTRING	"win-AXP"
+#endif
+#else
+#ifdef _M_IX86
+#define	CPUSTRING	"win-x86-debug"
+#elif defined _M_ALPHA
+#define	CPUSTRING	"win-AXP-debug"
+#endif
+#endif
+
+
+#define	PATH_SEP '\\'
+
+#endif
+
+//======================= MAC OS X SERVER DEFINES =====================
+
+#if defined(__MACH__) && defined(__APPLE__)
+
+#define MAC_STATIC
+
+#ifdef __ppc__
+#define CPUSTRING	"MacOSXS-ppc"
+#elif defined __i386__
+#define CPUSTRING	"MacOSXS-i386"
+#else
+#define CPUSTRING	"MacOSXS-other"
+#endif
+
+#define	PATH_SEP	'/'
+
+#define	GAME_HARD_LINKED
+#define	CGAME_HARD_LINKED
+#define	UI_HARD_LINKED
+#define _alloca alloca
+
+#undef ALIGN_ON
+#undef ALIGN_OFF
+#define	ALIGN_ON		#pragma align(16)
+#define	ALIGN_OFF		#pragma align()
+
+#ifdef __cplusplus
+	extern "C" {
+#endif
+
+void *osxAllocateMemory(long size);
+void osxFreeMemory(void *pointer);
+
+#ifdef __cplusplus
+        }
+#endif
+
+#endif
+
+//======================= MAC DEFINES =================================
+
+#ifdef __MACOS__
+
+#define	MAC_STATIC static
+
+#define	CPUSTRING	"MacOS-PPC"
+
+#define	PATH_SEP ':'
+
+void Sys_PumpEvents( void );
+
+#endif
+
+#ifdef __MRC__
+
+#define	MAC_STATIC
+
+#define	CPUSTRING	"MacOS-PPC"
+
+#define	PATH_SEP ':'
+
+void Sys_PumpEvents( void );
+
+#undef QDECL
+#define	QDECL	__cdecl
+
+#define _alloca alloca
+#endif
+
+//======================= LINUX DEFINES =================================
+
+// the mac compiler can't handle >32k of locals, so we
+// just waste space and make big arrays static...
+#ifdef __linux__
+
+#define	MAC_STATIC
+
+#ifdef __i386__
+#define	CPUSTRING	"linux-i386"
+#elif defined __axp__
+#define	CPUSTRING	"linux-alpha"
+#else
+#define	CPUSTRING	"linux-other"
+#endif
+
+#define	PATH_SEP '/'
+
+#endif
+
+//=============================================================
+  
+typedef enum {qfalse, qtrue}	qboolean;
+
+typedef unsigned char 		byte;
+
+#define	EQUAL_EPSILON	0.001
+
+typedef int		qhandle_t;
+typedef int		sfxHandle_t;
+typedef int		fileHandle_t;
+typedef int		clipHandle_t;
+
+typedef enum {
+	INVALID_JOINT = -1
+} jointHandle_t;
+
+#ifndef NULL
+#define NULL ((void *)0)
+#endif
+
+#define	MAX_QINT			0x7fffffff
+#define	MIN_QINT			(-MAX_QINT-1)
+
+#ifndef max
+#define max( x, y ) ( ( ( x ) > ( y ) ) ? ( x ) : ( y ) )
+#define min( x, y ) ( ( ( x ) < ( y ) ) ? ( x ) : ( y ) )
+#endif
+
+#ifndef sign
+#define sign( f )	( ( f > 0 ) ? 1 : ( ( f < 0 ) ? -1 : 0 ) )
+#endif
+
+// angle indexes
+#define	PITCH				0		// up / down
+#define	YAW					1		// left / right
+#define	ROLL				2		// fall over
+
+// the game guarantees that no string from the network will ever
+// exceed MAX_STRING_CHARS
+#define	MAX_STRING_CHARS	1024	// max length of a string passed to Cmd_TokenizeString
+#define	MAX_STRING_TOKENS	256		// max tokens resulting from Cmd_TokenizeString
+#define	MAX_TOKEN_CHARS		1024	// max length of an individual token
+
+#define	MAX_INFO_STRING		1024
+#define	MAX_INFO_KEY		1024
+#define	MAX_INFO_VALUE		1024
+
+
+#define	MAX_QPATH			64		// max length of a quake game pathname
+#define	MAX_OSPATH			128		// max length of a filesystem pathname
+
+#define	MAX_NAME_LENGTH		32		// max length of a client name
+
+// paramters for command buffer stuffing
+typedef enum {
+	EXEC_NOW,			// don't return until completed, a VM should NEVER use this,
+						// because some commands might cause the VM to be unloaded...
+	EXEC_INSERT,		// insert at current position, but don't run yet
+	EXEC_APPEND			// add to end of the command buffer (normal case)
+} cbufExec_t;
+
+
+//
+// these aren't needed by any of the VMs.  put in another header?
+//
+#define	MAX_MAP_AREA_BYTES		32		// bit vector of area visibility
+
+#undef ERR_FATAL						// malloc.h on unix
+
+// parameters to the main Error routine
+typedef enum {
+	ERR_NONE,
+	ERR_FATAL,					// exit the entire game with a popup window
+	ERR_DROP,					// print to console and disconnect from game
+	ERR_DISCONNECT,				// don't kill server
+	ERR_NEED_CD					// pop up the need-cd dialog
+} errorParm_t;
+
+
+// font rendering values used by ui and cgame
+
+#define PROP_GAP_WIDTH			3
+#define PROP_SPACE_WIDTH		8
+#define PROP_HEIGHT				27
+#define PROP_SMALL_SIZE_SCALE	0.75
+
+#define BLINK_DIVISOR			200
+#define PULSE_DIVISOR			75
+
+#define UI_LEFT			0x00000000	// default
+#define UI_CENTER		0x00000001
+#define UI_RIGHT		0x00000002
+#define UI_FORMATMASK	0x00000007
+#define UI_SMALLFONT	0x00000010
+#define UI_BIGFONT		0x00000020	// default
+#define UI_GIANTFONT	0x00000040
+#define UI_DROPSHADOW	0x00000800
+#define UI_BLINK		0x00001000
+#define UI_INVERSE		0x00002000
+#define UI_PULSE		0x00004000
+
+
+/*
+==============================================================
+
+MATHLIB
+
+==============================================================
+*/
+#ifdef __cplusplus			// so we can include this in C code
+#define	SIDE_FRONT		0
+#define	SIDE_BACK		1
+#define	SIDE_ON			2
+#define	SIDE_CROSS		3
+
+#define	Q_PI	3.14159265358979323846
+#ifndef M_PI
+#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
+#endif
+
+#include "math_vector.h"
+#include "math_angles.h"
+#include "math_matrix.h"
+#include "math_quaternion.h"
+
+class idVec3;						// for defining vectors
+typedef idVec3 &vec3_p;				// for passing vectors as function arguments
+typedef const idVec3 &vec3_c;		// for passing vectors as const function arguments
+									
+class angles_t;						// for defining angle vectors
+typedef angles_t &angles_p;			// for passing angles as function arguments
+typedef const angles_t &angles_c;	// for passing angles as const function arguments
+
+class mat3_t;						// for defining matrices
+typedef mat3_t &mat3_p;				// for passing matrices as function arguments
+typedef const mat3_t &mat3_c;		// for passing matrices as const function arguments
+
+
+
+#define NUMVERTEXNORMALS	162
+extern	idVec3	bytedirs[NUMVERTEXNORMALS];
+
+// all drawing is done to a 640*480 virtual screen size
+// and will be automatically scaled to the real resolution
+#define	SCREEN_WIDTH		640
+#define	SCREEN_HEIGHT		480
+
+#define TINYCHAR_WIDTH		(SMALLCHAR_WIDTH)
+#define TINYCHAR_HEIGHT		(SMALLCHAR_HEIGHT/2)
+
+#define SMALLCHAR_WIDTH		8
+#define SMALLCHAR_HEIGHT	16
+
+#define BIGCHAR_WIDTH		16
+#define BIGCHAR_HEIGHT		16
+
+#define	GIANTCHAR_WIDTH		32
+#define	GIANTCHAR_HEIGHT	48
+
+extern	idVec4		colorBlack;
+extern	idVec4		colorRed;
+extern	idVec4		colorGreen;
+extern	idVec4		colorBlue;
+extern	idVec4		colorYellow;
+extern	idVec4		colorMagenta;
+extern	idVec4		colorCyan;
+extern	idVec4		colorWhite;
+extern	idVec4		colorLtGrey;
+extern	idVec4		colorMdGrey;
+extern	idVec4		colorDkGrey;
+
+#define Q_COLOR_ESCAPE	'^'
+#define Q_IsColorString(p)	( p && *(p) == Q_COLOR_ESCAPE && *((p)+1) && *((p)+1) != Q_COLOR_ESCAPE )
+
+#define COLOR_BLACK		'0'
+#define COLOR_RED		'1'
+#define COLOR_GREEN		'2'
+#define COLOR_YELLOW	'3'
+#define COLOR_BLUE		'4'
+#define COLOR_CYAN		'5'
+#define COLOR_MAGENTA	'6'
+#define COLOR_WHITE		'7'
+#define ColorIndex(c)	( ( (c) - '0' ) & 7 )
+
+#define S_COLOR_BLACK	"^0"
+#define S_COLOR_RED		"^1"
+#define S_COLOR_GREEN	"^2"
+#define S_COLOR_YELLOW	"^3"
+#define S_COLOR_BLUE	"^4"
+#define S_COLOR_CYAN	"^5"
+#define S_COLOR_MAGENTA	"^6"
+#define S_COLOR_WHITE	"^7"
+
+extern idVec4	g_color_table[8];
+
+#define	MAKERGB( v, r, g, b ) v[0]=r;v[1]=g;v[2]=b
+#define	MAKERGBA( v, r, g, b, a ) v[0]=r;v[1]=g;v[2]=b;v[3]=a
+
+#define DEG2RAD( a ) ( ( (a) * M_PI ) / 180.0F )
+#define RAD2DEG( a ) ( ( (a) * 180.0f ) / M_PI )
+
+struct cplane_s;
+
+extern	idVec3	vec3_origin;
+extern	idVec4	vec4_origin;
+extern	mat3_t	axisDefault;
+
+#define	nanmask (255<<23)
+
+#define	IS_NAN(x) (((*(int *)&x)&nanmask)==nanmask)
+
+float Q_fabs( float f );
+float Q_rsqrt( float f );		// reciprocal square root
+
+#define SQRTFAST( x ) ( 1.0f / Q_rsqrt( x ) )
+
+signed char ClampChar( int i );
+signed short ClampShort( int i );
+
+// this isn't a real cheap function to call!
+int DirToByte( const idVec3 &dir );
+void ByteToDir( int b, vec3_p dir );
+
+#define DotProduct(a,b)			((a)[0]*(b)[0]+(a)[1]*(b)[1]+(a)[2]*(b)[2])
+#define VectorSubtract(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2])
+#define VectorAdd(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2])
+#define VectorCopy(a,b)			((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2])
+//#define VectorCopy(a,b)			((b).x=(a).x,(b).y=(a).y,(b).z=(a).z])
+
+#define	VectorScale(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s))
+#define	VectorMA(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s))
+#define CrossProduct(a,b,c)		((c)[0]=(a)[1]*(b)[2]-(a)[2]*(b)[1],(c)[1]=(a)[2]*(b)[0]-(a)[0]*(b)[2],(c)[2]=(a)[0]*(b)[1]-(a)[1]*(b)[0])
+
+#define DotProduct4(x,y)		((x)[0]*(y)[0]+(x)[1]*(y)[1]+(x)[2]*(y)[2]+(x)[3]*(y)[3])
+#define VectorSubtract4(a,b,c)	((c)[0]=(a)[0]-(b)[0],(c)[1]=(a)[1]-(b)[1],(c)[2]=(a)[2]-(b)[2],(c)[3]=(a)[3]-(b)[3])
+#define VectorAdd4(a,b,c)		((c)[0]=(a)[0]+(b)[0],(c)[1]=(a)[1]+(b)[1],(c)[2]=(a)[2]+(b)[2],(c)[3]=(a)[3]+(b)[3])
+#define VectorCopy4(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+#define	VectorScale4(v, s, o)	((o)[0]=(v)[0]*(s),(o)[1]=(v)[1]*(s),(o)[2]=(v)[2]*(s),(o)[3]=(v)[3]*(s))
+#define	VectorMA4(v, s, b, o)	((o)[0]=(v)[0]+(b)[0]*(s),(o)[1]=(v)[1]+(b)[1]*(s),(o)[2]=(v)[2]+(b)[2]*(s),(o)[3]=(v)[3]+(b)[3]*(s))
+
+
+#define VectorClear(a)			((a)[0]=(a)[1]=(a)[2]=0)
+#define VectorNegate(a,b)		((b)[0]=-(a)[0],(b)[1]=-(a)[1],(b)[2]=-(a)[2])
+#define VectorSet(v, x, y, z)	((v)[0]=(x), (v)[1]=(y), (v)[2]=(z))
+#define Vector4Copy(a,b)		((b)[0]=(a)[0],(b)[1]=(a)[1],(b)[2]=(a)[2],(b)[3]=(a)[3])
+
+#define	SnapVector(v) {v[0]=(int)v[0];v[1]=(int)v[1];v[2]=(int)v[2];}
+
+float NormalizeColor( vec3_c in, vec3_p out );
+
+int VectorCompare( vec3_c v1, vec3_c v2 );
+float VectorLength( vec3_c v );
+float Distance( vec3_c p1, vec3_c p2 );
+float DistanceSquared( vec3_c p1, vec3_c p2 );
+float VectorNormalize (vec3_p v);		// returns vector length
+void VectorNormalizeFast(vec3_p v);		// does NOT return vector length, uses rsqrt approximation
+float VectorNormalize2( vec3_c v, vec3_p out );
+void VectorInverse (vec3_p v);
+void VectorRotate( vec3_c in, mat3_c matrix, vec3_p out );
+void VectorPolar(vec3_p v, float radius, float theta, float phi);
+void VectorSnap(vec3_p v);
+void Vector53Copy( const idVec5_t &in, vec3_p out);
+void Vector5Scale( const idVec5_t &v, float scale, idVec5_t &out);
+void Vector5Add( const idVec5_t &va, const idVec5_t &vb, idVec5_t &out);
+void VectorRotate3( vec3_c vIn, vec3_c vRotation, vec3_p out);
+void VectorRotate3Origin(vec3_c vIn, vec3_c vRotation, vec3_c vOrigin, vec3_p out);
+
+
+int Q_log2(int val);
+
+int		Q_rand( int *seed );
+float	Q_random( int *seed );
+float	Q_crandom( int *seed );
+
+#define random()	((rand () & 0x7fff) / ((float)0x7fff))
+#define crandom()	(2.0 * (random() - 0.5))
+
+float Q_rint( float in );
+
+void vectoangles( vec3_c value1, angles_p angles);
+void AnglesToAxis( angles_c angles, mat3_p axis );
+
+void AxisCopy( mat3_c in, mat3_p out );
+qboolean AxisRotated( mat3_c in );			// assumes a non-degenerate axis
+
+int SignbitsForNormal( vec3_c normal );
+int BoxOnPlaneSide( const Bounds &b, struct cplane_s *p );
+
+float	AngleMod(float a);
+float	LerpAngle (float from, float to, float frac);
+float	AngleSubtract( float a1, float a2 );
+void	AnglesSubtract( angles_c v1, angles_c v2, angles_p v3 );
+
+float AngleNormalize360 ( float angle );
+float AngleNormalize180 ( float angle );
+float AngleDelta ( float angle1, float angle2 );
+
+qboolean PlaneFromPoints( idVec4 &plane, vec3_c a, vec3_c b, vec3_c c );
+void ProjectPointOnPlane( vec3_p dst, vec3_c p, vec3_c normal );
+void RotatePointAroundVector( vec3_p dst, vec3_c dir, vec3_c point, float degrees );
+void RotateAroundDirection( mat3_p axis, float yaw );
+void MakeNormalVectors( vec3_c forward, vec3_p right, vec3_p up );
+// perpendicular vector could be replaced by this
+
+int	PlaneTypeForNormal( vec3_c normal );
+
+void MatrixMultiply( mat3_c in1, mat3_c in2, mat3_p out );
+void MatrixInverseMultiply( mat3_c in1, mat3_c in2, mat3_p out );	// in2 is transposed during multiply
+void MatrixTransformVector( vec3_c in, mat3_c matrix, vec3_p out );
+void MatrixProjectVector( vec3_c in, mat3_c matrix, vec3_p out ); // Places the vector into a new coordinate system.
+void AngleVectors( angles_c angles, vec3_p forward, vec3_p right, vec3_p up);
+void PerpendicularVector( vec3_p dst, vec3_c src );
+
+float TriangleArea( vec3_c a, vec3_c b, vec3_c c );
+#endif										// __cplusplus
+
+//=============================================
+
+float Com_Clamp( float min, float max, float value );
+
+#define FILE_HASH_SIZE		1024
+int Com_HashString( const char *fname );
+
+char	*Com_SkipPath( char *pathname );
+
+// it is ok for out == in
+void	Com_StripExtension( const char *in, char *out );
+
+// "extension" should include the dot: ".map"
+void	Com_DefaultExtension( char *path, int maxSize, const char *extension );
+
+int		Com_ParseInfos( const char *buf, int max, char infos[][MAX_INFO_STRING] );
+
+/*
+=====================================================================================
+
+SCRIPT PARSING
+
+=====================================================================================
+*/
+
+// this just controls the comment printing, it doesn't actually load a file
+void Com_BeginParseSession( const char *filename );
+void Com_EndParseSession( void );
+
+int Com_GetCurrentParseLine( void );
+
+// Will never return NULL, just empty strings.
+// An empty string will only be returned at end of file.
+// ParseOnLine will return empty if there isn't another token on this line
+
+// this funny typedef just means a moving pointer into a const char * buffer
+const char *Com_Parse( const char *(*data_p) );
+const char *Com_ParseOnLine( const char *(*data_p) );
+const char *Com_ParseRestOfLine( const char *(*data_p) );
+
+void Com_UngetToken( void );
+
+#ifdef __cplusplus
+void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning = qfalse );
+#else
+void Com_MatchToken( const char *(*buf_p), const char *match, qboolean warning );
+#endif
+
+void Com_ScriptError( const char *msg, ... );
+void Com_ScriptWarning( const char *msg, ... );
+
+void Com_SkipBracedSection( const char *(*program) );
+void Com_SkipRestOfLine( const char *(*data) );
+
+float Com_ParseFloat( const char *(*buf_p) );
+int	Com_ParseInt( const char *(*buf_p) );
+
+void Com_Parse1DMatrix( const char *(*buf_p), int x, float *m );
+void Com_Parse2DMatrix( const char *(*buf_p), int y, int x, float *m );
+void Com_Parse3DMatrix( const char *(*buf_p), int z, int y, int x, float *m );
+
+//=====================================================================================
+#ifdef __cplusplus
+	extern "C" {
+#endif
+
+void	QDECL Com_sprintf (char *dest, int size, const char *fmt, ...);
+
+
+// mode parm for FS_FOpenFile
+typedef enum {
+	FS_READ,
+	FS_WRITE,
+	FS_APPEND,
+	FS_APPEND_SYNC
+} fsMode_t;
+
+typedef enum {
+	FS_SEEK_CUR,
+	FS_SEEK_END,
+	FS_SEEK_SET
+} fsOrigin_t;
+
+//=============================================
+
+int Q_isprint( int c );
+int Q_islower( int c );
+int Q_isupper( int c );
+int Q_isalpha( int c );
+
+// portable case insensitive compare
+int		Q_stricmp (const char *s1, const char *s2);
+int		Q_strncmp (const char *s1, const char *s2, int n);
+int		Q_stricmpn (const char *s1, const char *s2, int n);
+char	*Q_strlwr( char *s1 );
+char	*Q_strupr( char *s1 );
+char	*Q_strrchr( const char* string, int c );
+
+// buffer size safe library replacements
+void	Q_strncpyz( char *dest, const char *src, int destsize );
+void	Q_strcat( char *dest, int size, const char *src );
+
+// strlen that discounts Quake color sequences
+int Q_PrintStrlen( const char *string );
+// removes color sequences from string
+char *Q_CleanStr( char *string );
+
+int			Com_Filter( const char *filter, const char *name, int casesensitive );
+const char *Com_StringContains( const char *str1, const char *str2, int casesensitive );
+
+
+//=============================================
+
+short	BigShort(short l);
+short	LittleShort(short l);
+int		BigLong (int l);
+int		LittleLong (int l);
+float	BigFloat (float l);
+float	LittleFloat (float l);
+
+void	Swap_Init (void);
+char	* QDECL va(char *format, ...);
+
+#ifdef __cplusplus
+    }
+#endif
+
+
+//=============================================
+#ifdef __cplusplus
+//
+// mapfile parsing
+//
+typedef struct ePair_s {
+	char	*key;
+	char	*value;
+} ePair_t;
+
+typedef struct mapSide_s {
+	char		material[MAX_QPATH];
+	idVec4		plane;
+	idVec4		textureVectors[2];
+} mapSide_t;
+
+typedef struct {
+	int			numSides;
+	mapSide_t	**sides;
+} mapBrush_t;
+
+typedef struct {
+	idVec3		xyz;
+	float		st[2];
+} patchVertex_t;
+
+typedef struct {
+	char		material[MAX_QPATH];
+	int			width, height;
+	patchVertex_t	*patchVerts;
+} mapPatch_t;
+
+typedef struct {
+	char		modelName[MAX_QPATH];
+	float		matrix[16];
+} mapModel_t;
+
+typedef struct mapPrimitive_s {
+	int				numEpairs;
+	ePair_t			**ePairs;
+
+	// only one of these will be non-NULL
+	mapBrush_t		*brush;
+	mapPatch_t		*patch;
+	mapModel_t		*model;
+} mapPrimitive_t;
+
+typedef struct mapEntity_s {
+	int				numPrimitives;
+	mapPrimitive_t	**primitives;
+
+	int				numEpairs;
+	ePair_t			**ePairs;
+} mapEntity_t;
+
+typedef struct {
+	int				numEntities;
+	mapEntity_t		**entities;
+} mapFile_t;
+
+
+// the order of entities, brushes, and sides will be maintained, the
+// lists won't be swapped on each load or save
+mapFile_t *ParseMapFile( const char *text );
+void FreeMapFile( mapFile_t *mapFile );
+void WriteMapFile( const mapFile_t *mapFile, FILE *f );
+
+// key names are case-insensitive
+const char 	*ValueForMapEntityKey( const mapEntity_t *ent, const char *key );
+float	FloatForMapEntityKey( const mapEntity_t *ent, const char *key );
+qboolean 	GetVectorForMapEntityKey( const mapEntity_t *ent, const char *key, idVec3 &vec );
+
+typedef struct {
+	idVec3		xyz;
+	idVec2		st;
+	idVec3		normal;
+	idVec3		tangents[2];
+	byte		smoothing[4];		// colors for silhouette smoothing
+} drawVert_t;
+
+typedef struct {
+	int			width, height;
+	drawVert_t	*verts;
+} drawVertMesh_t;
+
+// Tesselate a map patch into smoothed, drawable vertexes
+// MaxError of around 4 is reasonable
+drawVertMesh_t *SubdivideMapPatch( const mapPatch_t *patch, float maxError );
+#endif			// __cplusplus
+
+//=========================================
+
+#ifdef __cplusplus
+	extern "C" {
+#endif
+
+void	QDECL Com_Error( int level, const char *error, ... );
+void	QDECL Com_Printf( const char *msg, ... );
+void	QDECL Com_DPrintf( const char *msg, ... );
+
+#ifdef __cplusplus
+	}
+#endif
+
+
+typedef struct {
+	qboolean	frameMemory;
+	int		currentElements;
+	int		maxElements;		// will reallocate and move when exceeded
+	void	**elements;
+} growList_t;
+
+// you don't need to init the growlist if you don't mind it growing and moving
+// the list as it expands
+void		Com_InitGrowList( growList_t *list, int maxElements );
+int			Com_AddToGrowList( growList_t *list, void *data );
+void		*Com_GrowListElement( const growList_t *list, int index );
+int			Com_IndexForGrowListElement( const growList_t *list, const void *element );
+
+
+//
+// key / value info strings
+//
+char *Info_ValueForKey( const char *s, const char *key );
+void Info_RemoveKey( char *s, const char *key );
+void Info_SetValueForKey( char *s, const char *key, const char *value );
+qboolean Info_Validate( const char *s );
+void Info_NextPair( const char *(*s), char key[MAX_INFO_KEY], char value[MAX_INFO_VALUE] );
+
+// get cvar defs, collision defs, etc
+//#include "../shared/interface.h"
+
+// get key code numbers for events
+//#include "../shared/keycodes.h"
+
+#ifdef __cplusplus
+// get the polygon winding functions
+//#include "../shared/windings.h"
+
+// get the flags class
+//#include "../shared/idflags.h"
+#endif	// __cplusplus
+
+#endif	// __Q_SHARED_H
+
diff --git a/libs/splines/splines.h b/libs/splines/splines.h
index da7c2e5b..54808492 100644
--- a/libs/splines/splines.h
+++ b/libs/splines/splines.h
@@ -1,1102 +1,1102 @@
-#ifndef __SPLINES_H
-#define __SPLINES_H
-
-#define GTKRADIANT
-
-#ifndef CAMERA_PLUGIN
-#ifdef GTKRADIANT
-#include "misc_def.h"
-#include "igl_to_qgl.h"
-#endif
-#endif
-
-#include "util_list.h"
-#include "util_str.h"
-#include "math_vector.h"
-
-typedef int fileHandle_t;
-
-extern void glBox(idVec3 &color, idVec3 &point, float size);
-extern void glLabeledPoint(idVec3 &color, idVec3 &point, float size, const char *label);
-
-static idVec4 blue(0, 0, 1, 1);
-static idVec4 red(1, 0, 0, 1);
-
-class idPointListInterface {
-public:
-	idPointListInterface() {
-		selectedPoints.Clear();
-	};
-	virtual ~idPointListInterface() {};
-	
-	virtual int numPoints() {
-		return 0;
-	}
-	
-	virtual void addPoint(const float x, const float y, const float z) {}
-	virtual void addPoint(const idVec3 &v) {}
-	virtual void removePoint(int index) {}
-	virtual idVec3 *getPoint(int index) { return NULL; }
-	
-	int	selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
-		idVec3 origin(ox, oy, oz);
-		idVec3 dir(dx, dy, dz);
-		return selectPointByRay(origin, dir, single);
-	}
-
-	int	selectPointByRay(const idVec3 origin, const idVec3 direction, bool single) {
-		int		i, besti, count;
-		float	d, bestd;
-		idVec3	temp, temp2;
-
-		// find the point closest to the ray
-		besti = -1;
-		bestd = 8;
-		count = numPoints();
-
-		for (i=0; i < count; i++) {
-			temp = *getPoint(i);
-			temp2 = temp;
-			temp -= origin;
-			d = DotProduct(temp, direction);
-			__VectorMA (origin, d, direction, temp);
-			temp2 -= temp;
-			d = temp2.Length();
-			if (d <= bestd) {
-				bestd = d;
-				besti = i;
-			}
-		}
-
-		if (besti >= 0) {
-			selectPoint(besti, single);
-		}
-
-		return besti;
-	}
-
-	int isPointSelected(int index) {
-		int count = selectedPoints.Num();
-		for (int i = 0; i < count; i++) {
-			if (selectedPoints[i] == index) {
-				return i;
-			}
-		}
-		return -1;
-	}
-	
-	int selectPoint(int index, bool single) {
-		if (index >= 0 && index < numPoints()) {
-			if (single) {
-				deselectAll();
-			} else {
-				if (isPointSelected(index) >= 0) {
-					selectedPoints.Remove(index);
-				}
-			}
-			return selectedPoints.Append(index);
-		}
-		return -1;
-	}
-	
-	void selectAll() {
-		selectedPoints.Clear();
-		for (int i = 0; i < numPoints(); i++) {
-			selectedPoints.Append(i);
-		}
-	}
-
-	void deselectAll() {
-		selectedPoints.Clear();
-	}
-
-	int numSelectedPoints();
-    
-	idVec3 *getSelectedPoint(int index) {
-		assert(index >= 0 && index < numSelectedPoints());
-		return getPoint(selectedPoints[index]);
-	}
-	
-	virtual void updateSelection(float x, float y, float z) {
-		idVec3 move(x, y, z);
-		updateSelection(move);
-	}
-
-	virtual void updateSelection(const idVec3 &move) {
-		int count = selectedPoints.Num();
-		for (int i = 0; i < count; i++) {
-			*getPoint(selectedPoints[i]) += move;
-		}
-	}
-
-	void drawSelection() {
-		int count = selectedPoints.Num();
-		for (int i = 0; i < count; i++) {
-			glBox(red, *getPoint(selectedPoints[i]), 4);
-		}
-	}
-
-protected:
-	idList<int> selectedPoints;
-
-};
-
-
-class idSplineList {
-
-public:
-
-	idSplineList() {
-		clear();
-	}
-
-	idSplineList(const char *p) {
-		clear();
-		name = p;
-	};
-
-	~idSplineList() {
-		clear();
-	};
-
-	void clearControl() {
-		for (int i = 0; i < controlPoints.Num(); i++) {
-			delete controlPoints[i];
-		}
-		controlPoints.Clear();
-	}
-
-	void clearSpline() {
-		for (int i = 0; i < splinePoints.Num(); i++) {
-			delete splinePoints[i];
-		}
-		splinePoints.Clear();
-	}
-
-	void parse(const char *(*text));
-	void write(fileHandle_t file, const char *name);
-
-	void clear() {
-		clearControl();
-		clearSpline();
-		splineTime.Clear();
-		selected = NULL;
-		dirty = true;
-		activeSegment = 0;
-		granularity = 0.025f;
-		pathColor.set(1.0f, 0.5f, 0.0f);
-		controlColor.set(0.7f, 0.0f, 1.0f);
-		segmentColor.set(0.0f, 0.0f, 1.0f);
-		activeColor.set(1.0f, 0.0f, 0.0f);
-	}
-
-	void initPosition(long startTime, long totalTime);
-	const idVec3 *getPosition(long time);
-
-
-	void draw(bool editMode);
-	void addToRenderer();
-
-	void setSelectedPoint(idVec3 *p);
-	idVec3 *getSelectedPoint() {
-	  return selected;
-	}
-
-	void addPoint(const idVec3 &v) {
-		controlPoints.Append(new idVec3(v));
-		dirty = true;
-	}
-
-	void addPoint(float x, float y, float z) {
-		controlPoints.Append(new idVec3(x, y, z));
-		dirty = true;
-	}
-
-	void updateSelection(const idVec3 &move);
-
-	void startEdit() {
-		editMode = true;
-	}
-		
-	void stopEdit() {
-		editMode = false;
-	}
-
-	void buildSpline();
-
-	void setGranularity(float f) {
-		granularity = f;
-	}
-
-	float getGranularity() {
-		return granularity;
-	}
-
-	int numPoints() {
-		return controlPoints.Num();
-	}
-
-	idVec3 *getPoint(int index) {
-		assert(index >= 0 && index < controlPoints.Num());
-		return controlPoints[index];
-	}
-
-	idVec3 *getSegmentPoint(int index) {
-		assert(index >= 0 && index < splinePoints.Num());
-		return splinePoints[index];
-	}
-
-
-	void setSegmentTime(int index, int time) {
-		assert(index >= 0 && index < splinePoints.Num());
-		splineTime[index] = time;
-	}
-
-	int getSegmentTime(int index) {
-		assert(index >= 0 && index < splinePoints.Num());
-		return (int)splineTime[index];
-	}
-	void addSegmentTime(int index, int time) {
-		assert(index >= 0 && index < splinePoints.Num());
-		splineTime[index] += time;
-	}
-
-	float totalDistance();
-
-	static idVec3 zero;
-
-	int getActiveSegment() {
-		return activeSegment;
-	}
-
-	void setActiveSegment(int i) {
-		//assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
-		activeSegment = i;
-	}
-
-	int numSegments() {
-		return splinePoints.Num();
-	}
-
-	void setColors(idVec3 &path, idVec3 &segment, idVec3 &control, idVec3 &active) {
-		pathColor = path;
-		segmentColor = segment;
-		controlColor = control;
-		activeColor = active;
-	}
-
-	const char *getName() {
-		return name.c_str();
-	}
-
-	void setName(const char *p) {
-		name = p;
-	}
-
-	bool validTime() {
-		if (dirty) {
-			buildSpline();
-		}
-		// gcc doesn't allow static casting away from bools
-		// why?  I've no idea...
-		return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
-	}
-
-	void setTime(long t) {
-		time = t;
-	}
-
-	void setBaseTime(long t) {
-		baseTime = t;
-	}
-
-protected:
-	idStr name;
-	float calcSpline(int step, float tension);
-	idList<idVec3*> controlPoints;
-	idList<idVec3*> splinePoints;
-	idList<double> splineTime;
-	idVec3 *selected;
-	idVec3 pathColor, segmentColor, controlColor, activeColor;
-	float granularity;
-	bool editMode;
-	bool dirty;
-	int activeSegment;
-	long baseTime;
-	long time;
-	friend class idCamera;
-};
-
-// time in milliseconds 
-// velocity where 1.0 equal rough walking speed
-struct idVelocity {
-	idVelocity(long start, long duration, float s) {
-		startTime = start;
-		time = duration;
-		speed = s;
-	}
-	long	startTime;
-	long	time;
-	float	speed;
-};
-
-// can either be a look at or origin position for a camera
-// 
-class idCameraPosition : public idPointListInterface {
-public:
-	
-	virtual void clearVelocities() {
-		for (int i = 0; i < velocities.Num(); i++) {
-			delete velocities[i];
-			velocities[i] = NULL;
-		}
-		velocities.Clear();
-	}
-
-	virtual void clear() {
-		editMode = false;
-		clearVelocities();
-	}
-
-	idCameraPosition(const char *p) {
-		name = p;
-	}
-
-	idCameraPosition() {
-		time = 0;
-		name = "position";
-	}
-
-	idCameraPosition(long t) {
-		time = t;
-	}
-
-	virtual ~idCameraPosition() {
-		clear();
-	}
-
-	
-	// this can be done with RTTI syntax but i like the derived classes setting a type
-	// makes serialization a bit easier to see
-	//
-	enum positionType {
-		FIXED = 0x00,
-		INTERPOLATED,
-		SPLINE,
-		POSITION_COUNT
-	};
-
-
-	virtual void start(long t) {
-		startTime = t;
-	}
-
-	long getTime() {
-		return time;
-	}
-
-	virtual void setTime(long t) {
-		time = t;
-	}
-
-	float getBaseVelocity() {
-		return baseVelocity;
-	}
-
-	float getVelocity(long t) {
-		long check = t - startTime;
-		for (int i = 0; i < velocities.Num(); i++) {
-			if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
-				return velocities[i]->speed;
-			}
-		}
-		return baseVelocity;
-	}
-
-	void addVelocity(long start, long duration, float speed) {
-		velocities.Append(new idVelocity(start, duration, speed));
-	}
-
-	virtual const idVec3 *getPosition(long t) { 
-		assert(true);
-		return NULL;
-	}
-
-	virtual void draw(bool editMode) {};
-
-	virtual void parse(const char *(*text)) {};
-	virtual void write(fileHandle_t file, const char *name);
-	virtual bool parseToken(const char *key, const char *(*text));
-
-	const char *getName() {
-		return name.c_str();
-	}
-
-	void setName(const char *p) {
-		name = p;
-	}
-
-	virtual void startEdit() {
-		editMode = true;
-	}
-
-	virtual void stopEdit() {
-		editMode = false;
-	}
-
-	virtual void draw() {};
-
-	const char *typeStr() {
-		return positionStr[static_cast<int>(type)];
-	}
-
-	void calcVelocity(float distance) {
-		float secs = (float)time / 1000;
-		baseVelocity = distance / secs;
-	}
-
-protected:
-	static const char* positionStr[POSITION_COUNT];
-	long		startTime;
-	long		time;
-	idCameraPosition::positionType type;
-	idStr		name;
-	bool	editMode;
-	idList<idVelocity*> velocities;
-	float		baseVelocity;
-};
-
-class idFixedPosition : public idCameraPosition {
-public:
-
-	void init() {
-		pos.Zero();
-		type = idCameraPosition::FIXED;
-	}
-	
-	idFixedPosition() : idCameraPosition() {
-		init();
-	}
-	
-	idFixedPosition(idVec3 p) : idCameraPosition() {
-		init();
-		pos = p;
-	}
-
-	virtual void addPoint(const idVec3 &v) {
-		pos = v;
-	}
-	
-	virtual void addPoint(const float x, const float y, const float z) {
-		pos.set(x, y, z);
-	}
-
-
-	~idFixedPosition() {
-	}
-
-	virtual const idVec3 *getPosition(long t) { 
-		return &pos;
-	}
-
-	void parse(const char *(*text));
-	void write(fileHandle_t file, const char *name);
-
-	virtual int numPoints() {
-		return 1;
-	}
-
-	virtual idVec3 *getPoint(int index) {
-		if (index != 0) {
-			assert(true);
-		};
-		return &pos;
-	}
-
-	virtual void draw(bool editMode) {
-		glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
-	}
-
-protected:
-	idVec3 pos;
-};
-
-class idInterpolatedPosition : public idCameraPosition {
-public:
-
-	void init() {
-		type = idCameraPosition::INTERPOLATED;
-		first = true;
-		startPos.Zero();
-		endPos.Zero();
-	}
-	
-	idInterpolatedPosition() : idCameraPosition() {
-		init();
-	}
-	
-	idInterpolatedPosition(idVec3 start, idVec3 end, long time) : idCameraPosition(time) {
-		init();
-		startPos = start;
-		endPos = end;
-	}
-
-	~idInterpolatedPosition() {
-	}
-
-	virtual const idVec3 *getPosition(long t);
-
-	void parse(const char *(*text));
-	void write(fileHandle_t file, const char *name);
-
-	virtual int numPoints() {
-		return 2;
-	}
-
-	virtual idVec3 *getPoint(int index) {
-		assert(index >= 0 && index < 2);
-		if (index == 0) {
-			return &startPos;
-		}
-		return &endPos;
-	}
-
-	virtual void addPoint(const float x, const float y, const float z) {
-		if (first) {
-			startPos.set(x, y, z);
-			first = false;
-		} else {
-			endPos.set(x, y, z);
-			first = true;
-		}
-	}
-
-	virtual void addPoint(const idVec3 &v) {
-		if (first) {
-			startPos = v;
-			first = false;
-		} else {
-			endPos = v;
-			first = true;
-		}
-	}
-
-	virtual void draw(bool editMode) {
-		glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
-		glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
-		qglBegin(GL_LINES);
-		qglVertex3fv(startPos);
-		qglVertex3fv(endPos);
-		qglEnd();
-	}
-
-	virtual void start(long t) {
-		idCameraPosition::start(t);
-		lastTime = startTime;
-		distSoFar = 0.0;
-		idVec3 temp = startPos;
-		temp -= endPos;
-		calcVelocity(temp.Length());
-	}
-
-protected:
-	bool first;
-	idVec3 startPos;
-	idVec3 endPos;
-	long lastTime;
-	float distSoFar;
-};
-
-class idSplinePosition : public idCameraPosition {
-public:
-
-	void init() {
-		type = idCameraPosition::SPLINE;
-	}
-	
-	idSplinePosition() : idCameraPosition() {
-		init();
-	}
-	
-	idSplinePosition(long time) : idCameraPosition(time) {
-		init();
-	}
-
-	~idSplinePosition() {
-	}
-
-	virtual void start(long t) {
-		idCameraPosition::start(t);
-		target.initPosition(t, time);
-		lastTime = startTime;
-		distSoFar = 0.0;
-		calcVelocity(target.totalDistance());
-	}
-
-	//virtual const idVec3 *getPosition(long t) { 
-	//	return target.getPosition(t);
-	//}
-	virtual const idVec3 *getPosition(long t);
-
-
-	//virtual const idVec3 *getPosition(long t) const { 
-
-	void addControlPoint(idVec3 &v) {
-		target.addPoint(v);
-	}
-
-	void parse(const char *(*text));
-	void write(fileHandle_t file, const char *name);
-
-	virtual int numPoints() {
-		return target.numPoints();
-	}
-
-	virtual idVec3 *getPoint(int index) {
-		return target.getPoint(index);
-	}
-
-	virtual void addPoint(const idVec3 &v) {
-		target.addPoint(v);
-	}
-
-	virtual void addPoint(const float x, const float y, const float z) {
-		target.addPoint(x, y, z);
-	}
-
-	virtual void draw(bool editMode) {
-		target.draw(editMode);
-	}
-
-	virtual void updateSelection(const idVec3 &move) {
-		idCameraPosition::updateSelection(move);
-		target.buildSpline();
-	}
-
-protected:
-	idSplineList target;
-	long lastTime;
-	float distSoFar;
-};
-
-class idCameraFOV {
-public:
-	
-	idCameraFOV() {
-		time = 0;
-		length = 0;
-		fov = 90;
-	}
-
-	idCameraFOV(int v) {
-		time = 0;
-		length = 0;
-		fov = v;
-	}
-
-	idCameraFOV(int s, int e, long t) {
-		startFOV = s;
-		endFOV = e;
-		length = t;
-	}
-
-
-	~idCameraFOV(){}
-
-	void setFOV(float f) {
-		fov = f;
-	}
-
-	float getFOV(long t) {
-		if (length) {
-			float percent = (t - startTime) / length;
-			if (percent < 0.0) {
-				percent = 0.0;
-			} else if (percent > 1.0) {
-				percent = 1.0;
-			}
-			float temp = endFOV - startFOV;
-			temp *= percent;
-			fov = startFOV + temp;
-
-			if (percent == 1.0) {
-				length = 0.0;
-			}
-		}
-		return fov;
-	}
-
-	void start(long t) {
-		startTime = t;
-	}
-
-	void reset(float startfov, float endfov, int start, float len) {
-		startFOV = startfov;
-		endFOV = endfov;
-		startTime = start;
-		length = len * 1000;
-	}
-
-	void parse(const char *(*text));
-	void write(fileHandle_t file, const char *name);
-
-protected:
-	float fov;
-	float startFOV;
-	float endFOV;
-	int startTime;
-	int time;
-	float length;
-};
-
-
-
-
-class idCameraEvent {
-public:						// parameters
-	enum eventType {
-		EVENT_NA = 0x00,
-		EVENT_WAIT,			// 
-		EVENT_TARGETWAIT,	// 
-		EVENT_SPEED,		// 
-		EVENT_TARGET,		// char(name)
-		EVENT_SNAPTARGET,	// 
-		EVENT_FOV,			// int(time), int(targetfov)
-		EVENT_CMD,			// 
-		EVENT_TRIGGER,		// 
-		EVENT_STOP,			// 
-		EVENT_CAMERA,		// 
-		EVENT_FADEOUT,		// int(time)
-		EVENT_FADEIN,		// int(time)
-		EVENT_FEATHER,		// 
-		EVENT_COUNT			
-	};
-
-	static const char* eventStr[EVENT_COUNT];
-
-	idCameraEvent() {
-		paramStr = "";
-		type = EVENT_NA;
-		time = 0;
-	}
-
-	idCameraEvent(eventType t, const char *param, long n) {
-		type = t;
-		paramStr = param;
-		time = n;
-	}
-
-	~idCameraEvent() {};
-
-	eventType getType() {
-		return type;
-	}
-
-	const char *typeStr() {
-		return eventStr[static_cast<int>(type)];
-	}
-
-	const char *getParam() {
-		return paramStr.c_str();
-	}
-
-	long getTime() {
-		return time;
-	}
-
-	void setTime(long n) {
-		time = n;
-	}
-
-	void parse(const char *(*text));
-	void write(fileHandle_t file, const char *name);
-
-	void setTriggered(bool b) {
-		triggered = b;
-	}
-
-	bool getTriggered() {
-		return triggered;
-	}
-
-protected:
-	eventType type;
-	idStr paramStr;
-	long time;
-	bool triggered;
-
-};
-
-class idCameraDef {
-public:
-
-	void clear() {
-		currentCameraPosition = 0;
-		cameraRunning = false;
-		lastDirection.Zero();
-		baseTime = 30;
-		activeTarget = 0;
-		name = "camera01";
-		fov.setFOV(90);
-		int i;
-		for (i = 0; i < targetPositions.Num(); i++) {
-			delete targetPositions[i];
-		}
-		for (i = 0; i < events.Num(); i++) {
-			delete events[i];
-		}
-		delete cameraPosition;
-		cameraPosition = NULL;
-		events.Clear();
-		targetPositions.Clear();
-	}
-
-	idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
-		clear();
-		if (type == idCameraPosition::SPLINE) {
-			cameraPosition = new idSplinePosition();
-		} else if (type == idCameraPosition::INTERPOLATED) {
-			cameraPosition = new idInterpolatedPosition();
-		} else {
-			cameraPosition = new idFixedPosition();
-		}
-		return cameraPosition;
-	}
-
-	idCameraDef() {
-		cameraPosition = NULL;
-		clear();
-	}
-
-	~idCameraDef() {
-		clear();
-	}
-
-	void addEvent(idCameraEvent::eventType t, const char *param, long time);
-
-	void addEvent(idCameraEvent *event);
-
-	void removeEvent( int index);
-
-	static int sortEvents(const void *p1, const void *p2);
-
-	int numEvents() {
-		return events.Num();
-	}
-
-	idCameraEvent *getEvent(int index) {
-		assert(index >= 0 && index < events.Num());
-		return events[index];
-	}
-
-	void parse(const char *(*text));
-	bool load(const char *filename);
-	void save(const char *filename);
-
-	void buildCamera();
-
-	//idSplineList *getcameraPosition() {
-	//	return &cameraPosition;
-	//}
-
-	static idCameraPosition *newFromType(idCameraPosition::positionType t) {
-		switch (t) {
-			case idCameraPosition::FIXED : return new idFixedPosition();
-			case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
-			case idCameraPosition::SPLINE : return new idSplinePosition();
-      default:
-        break;
-		};
-		return NULL;
-	}
-
-	void addTarget(const char *name, idCameraPosition::positionType type);
-
-	idCameraPosition *getActiveTarget() {
-		if (targetPositions.Num() == 0) {
-			addTarget(NULL, idCameraPosition::FIXED);
-		}
-		return targetPositions[activeTarget];
-	}
-
-	idCameraPosition *getActiveTarget(int index) {
-		if (targetPositions.Num() == 0) {
-			addTarget(NULL, idCameraPosition::FIXED);
-			return targetPositions[0];
-		}
-		return targetPositions[index];
-	}
-
-	int numTargets() {
-		return targetPositions.Num();
-	}
-
-
-	void setActiveTargetByName(const char *name) {
-		for (int i = 0; i < targetPositions.Num(); i++) {
-			if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {
-				setActiveTarget(i);
-				return;
-			}
-		}
-	}
-
-	void setActiveTarget(int index) {
-		assert(index >= 0 && index < targetPositions.Num());
-		activeTarget = index;
-	}
-
-	void setRunning(bool b) {
-		cameraRunning = b;
-	}
-
-	void setBaseTime(float f) {
-		baseTime = f;
-	}
-
-	float getBaseTime() {
-		return baseTime;
-	}
-
-	float getTotalTime() {
-		return totalTime;
-	}
-	
-	void startCamera(long t);
-	void stopCamera() {
-		cameraRunning = true;
-	}
-	void getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fv);
-
-	bool getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv);
-	bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
-		idVec3 org, dir;
-		org[0] = origin[0];
-		org[1] = origin[1];
-		org[2] = origin[2];
-		dir[0] = direction[0];
-		dir[1] = direction[1];
-		dir[2] = direction[2];
-		bool b = getCameraInfo(time, org, dir, fv);
-		origin[0] = org[0];
-		origin[1] = org[1];
-		origin[2] = org[2];
-		direction[0] = dir[0];
-		direction[1] = dir[1];
-		direction[2] = dir[2];
-		return b;
-	}
-
-	void draw(bool editMode) {
-                // gcc doesn't allow casting away from bools
-                // why?  I've no idea...
-		if (cameraPosition) {
-			cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
-			int count = targetPositions.Num();
-			for (int i = 0; i < count; i++) {
-				targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
-			}
-		}
-	}
-
-/*
-	int numSegments() {
-		if (cameraEdit) {
-			return cameraPosition.numSegments();
-		}
-		return getTargetSpline()->numSegments();
-	}
-
-	int getActiveSegment() {
-		if (cameraEdit) {
-			return cameraPosition.getActiveSegment();
-		}
-		return getTargetSpline()->getActiveSegment();
-	}
-
-	void setActiveSegment(int i) {
-		if (cameraEdit) {
-			cameraPosition.setActiveSegment(i);
-		} else {
-			getTargetSpline()->setActiveSegment(i);
-		}
-	}
-*/
-	int numPoints() {
-		if (cameraEdit) {
-			return cameraPosition->numPoints();
-		}
-		return getActiveTarget()->numPoints();
-	}
-
-	const idVec3 *getPoint(int index) {
-		if (cameraEdit) {
-			return cameraPosition->getPoint(index);
-		}
-		return getActiveTarget()->getPoint(index);
-	}
-
-	void stopEdit() {
-		editMode = false;
-		if (cameraEdit) {
-			cameraPosition->stopEdit();
-		} else {
-			getActiveTarget()->stopEdit();
-		}
-	}
-
-	void startEdit(bool camera) {
-		cameraEdit = camera;
-		if (camera) {
-			cameraPosition->startEdit();
-			for (int i = 0; i < targetPositions.Num(); i++) {
-				targetPositions[i]->stopEdit();
-			}
-		} else {
-			getActiveTarget()->startEdit();
-			cameraPosition->stopEdit();
-		}
-		editMode = true;
-	}
-
-	bool waitEvent(int index);
-
-	const char *getName() {
-		return name.c_str();
-	}
-
-	void setName(const char *p) {
-		name = p;
-	}
-
-	idCameraPosition *getPositionObj() {
-		if (cameraPosition == NULL) {
-			cameraPosition = new idFixedPosition();
-		}
-		return cameraPosition;
-	}
-
-protected:
-	idStr name;
-	int currentCameraPosition;
-	idVec3 lastDirection;
-	bool cameraRunning;
-	idCameraPosition *cameraPosition;
-	idList<idCameraPosition*> targetPositions;
-	idList<idCameraEvent*> events;
-	idCameraFOV fov;
-	int activeTarget;
-	float totalTime;
-	float baseTime;
-	long startTime;
-
-	bool cameraEdit;
-	bool editMode;
-};
-
-extern bool g_splineMode;
-
-extern idCameraDef *g_splineList;
-
-
-#endif
+#ifndef __SPLINES_H
+#define __SPLINES_H
+
+#define GTKRADIANT
+
+#ifndef CAMERA_PLUGIN
+#ifdef GTKRADIANT
+#include "misc_def.h"
+#include "igl_to_qgl.h"
+#endif
+#endif
+
+#include "util_list.h"
+#include "util_str.h"
+#include "math_vector.h"
+
+typedef int fileHandle_t;
+
+extern void glBox(idVec3 &color, idVec3 &point, float size);
+extern void glLabeledPoint(idVec3 &color, idVec3 &point, float size, const char *label);
+
+static idVec4 blue(0, 0, 1, 1);
+static idVec4 red(1, 0, 0, 1);
+
+class idPointListInterface {
+public:
+	idPointListInterface() {
+		selectedPoints.Clear();
+	};
+	virtual ~idPointListInterface() {};
+	
+	virtual int numPoints() {
+		return 0;
+	}
+	
+	virtual void addPoint(const float x, const float y, const float z) {}
+	virtual void addPoint(const idVec3 &v) {}
+	virtual void removePoint(int index) {}
+	virtual idVec3 *getPoint(int index) { return NULL; }
+	
+	int	selectPointByRay(float ox, float oy, float oz, float dx, float dy, float dz, bool single) {
+		idVec3 origin(ox, oy, oz);
+		idVec3 dir(dx, dy, dz);
+		return selectPointByRay(origin, dir, single);
+	}
+
+	int	selectPointByRay(const idVec3 origin, const idVec3 direction, bool single) {
+		int		i, besti, count;
+		float	d, bestd;
+		idVec3	temp, temp2;
+
+		// find the point closest to the ray
+		besti = -1;
+		bestd = 8;
+		count = numPoints();
+
+		for (i=0; i < count; i++) {
+			temp = *getPoint(i);
+			temp2 = temp;
+			temp -= origin;
+			d = DotProduct(temp, direction);
+			__VectorMA (origin, d, direction, temp);
+			temp2 -= temp;
+			d = temp2.Length();
+			if (d <= bestd) {
+				bestd = d;
+				besti = i;
+			}
+		}
+
+		if (besti >= 0) {
+			selectPoint(besti, single);
+		}
+
+		return besti;
+	}
+
+	int isPointSelected(int index) {
+		int count = selectedPoints.Num();
+		for (int i = 0; i < count; i++) {
+			if (selectedPoints[i] == index) {
+				return i;
+			}
+		}
+		return -1;
+	}
+	
+	int selectPoint(int index, bool single) {
+		if (index >= 0 && index < numPoints()) {
+			if (single) {
+				deselectAll();
+			} else {
+				if (isPointSelected(index) >= 0) {
+					selectedPoints.Remove(index);
+				}
+			}
+			return selectedPoints.Append(index);
+		}
+		return -1;
+	}
+	
+	void selectAll() {
+		selectedPoints.Clear();
+		for (int i = 0; i < numPoints(); i++) {
+			selectedPoints.Append(i);
+		}
+	}
+
+	void deselectAll() {
+		selectedPoints.Clear();
+	}
+
+	int numSelectedPoints();
+    
+	idVec3 *getSelectedPoint(int index) {
+		assert(index >= 0 && index < numSelectedPoints());
+		return getPoint(selectedPoints[index]);
+	}
+	
+	virtual void updateSelection(float x, float y, float z) {
+		idVec3 move(x, y, z);
+		updateSelection(move);
+	}
+
+	virtual void updateSelection(const idVec3 &move) {
+		int count = selectedPoints.Num();
+		for (int i = 0; i < count; i++) {
+			*getPoint(selectedPoints[i]) += move;
+		}
+	}
+
+	void drawSelection() {
+		int count = selectedPoints.Num();
+		for (int i = 0; i < count; i++) {
+			glBox(red, *getPoint(selectedPoints[i]), 4);
+		}
+	}
+
+protected:
+	idList<int> selectedPoints;
+
+};
+
+
+class idSplineList {
+
+public:
+
+	idSplineList() {
+		clear();
+	}
+
+	idSplineList(const char *p) {
+		clear();
+		name = p;
+	};
+
+	~idSplineList() {
+		clear();
+	};
+
+	void clearControl() {
+		for (int i = 0; i < controlPoints.Num(); i++) {
+			delete controlPoints[i];
+		}
+		controlPoints.Clear();
+	}
+
+	void clearSpline() {
+		for (int i = 0; i < splinePoints.Num(); i++) {
+			delete splinePoints[i];
+		}
+		splinePoints.Clear();
+	}
+
+	void parse(const char *(*text));
+	void write(fileHandle_t file, const char *name);
+
+	void clear() {
+		clearControl();
+		clearSpline();
+		splineTime.Clear();
+		selected = NULL;
+		dirty = true;
+		activeSegment = 0;
+		granularity = 0.025f;
+		pathColor.set(1.0f, 0.5f, 0.0f);
+		controlColor.set(0.7f, 0.0f, 1.0f);
+		segmentColor.set(0.0f, 0.0f, 1.0f);
+		activeColor.set(1.0f, 0.0f, 0.0f);
+	}
+
+	void initPosition(long startTime, long totalTime);
+	const idVec3 *getPosition(long time);
+
+
+	void draw(bool editMode);
+	void addToRenderer();
+
+	void setSelectedPoint(idVec3 *p);
+	idVec3 *getSelectedPoint() {
+	  return selected;
+	}
+
+	void addPoint(const idVec3 &v) {
+		controlPoints.Append(new idVec3(v));
+		dirty = true;
+	}
+
+	void addPoint(float x, float y, float z) {
+		controlPoints.Append(new idVec3(x, y, z));
+		dirty = true;
+	}
+
+	void updateSelection(const idVec3 &move);
+
+	void startEdit() {
+		editMode = true;
+	}
+		
+	void stopEdit() {
+		editMode = false;
+	}
+
+	void buildSpline();
+
+	void setGranularity(float f) {
+		granularity = f;
+	}
+
+	float getGranularity() {
+		return granularity;
+	}
+
+	int numPoints() {
+		return controlPoints.Num();
+	}
+
+	idVec3 *getPoint(int index) {
+		assert(index >= 0 && index < controlPoints.Num());
+		return controlPoints[index];
+	}
+
+	idVec3 *getSegmentPoint(int index) {
+		assert(index >= 0 && index < splinePoints.Num());
+		return splinePoints[index];
+	}
+
+
+	void setSegmentTime(int index, int time) {
+		assert(index >= 0 && index < splinePoints.Num());
+		splineTime[index] = time;
+	}
+
+	int getSegmentTime(int index) {
+		assert(index >= 0 && index < splinePoints.Num());
+		return (int)splineTime[index];
+	}
+	void addSegmentTime(int index, int time) {
+		assert(index >= 0 && index < splinePoints.Num());
+		splineTime[index] += time;
+	}
+
+	float totalDistance();
+
+	static idVec3 zero;
+
+	int getActiveSegment() {
+		return activeSegment;
+	}
+
+	void setActiveSegment(int i) {
+		//assert(i >= 0 && (splinePoints.Num() > 0 && i < splinePoints.Num()));
+		activeSegment = i;
+	}
+
+	int numSegments() {
+		return splinePoints.Num();
+	}
+
+	void setColors(idVec3 &path, idVec3 &segment, idVec3 &control, idVec3 &active) {
+		pathColor = path;
+		segmentColor = segment;
+		controlColor = control;
+		activeColor = active;
+	}
+
+	const char *getName() {
+		return name.c_str();
+	}
+
+	void setName(const char *p) {
+		name = p;
+	}
+
+	bool validTime() {
+		if (dirty) {
+			buildSpline();
+		}
+		// gcc doesn't allow static casting away from bools
+		// why?  I've no idea...
+		return (bool)(splineTime.Num() > 0 && splineTime.Num() == splinePoints.Num());
+	}
+
+	void setTime(long t) {
+		time = t;
+	}
+
+	void setBaseTime(long t) {
+		baseTime = t;
+	}
+
+protected:
+	idStr name;
+	float calcSpline(int step, float tension);
+	idList<idVec3*> controlPoints;
+	idList<idVec3*> splinePoints;
+	idList<double> splineTime;
+	idVec3 *selected;
+	idVec3 pathColor, segmentColor, controlColor, activeColor;
+	float granularity;
+	bool editMode;
+	bool dirty;
+	int activeSegment;
+	long baseTime;
+	long time;
+	friend class idCamera;
+};
+
+// time in milliseconds 
+// velocity where 1.0 equal rough walking speed
+struct idVelocity {
+	idVelocity(long start, long duration, float s) {
+		startTime = start;
+		time = duration;
+		speed = s;
+	}
+	long	startTime;
+	long	time;
+	float	speed;
+};
+
+// can either be a look at or origin position for a camera
+// 
+class idCameraPosition : public idPointListInterface {
+public:
+	
+	virtual void clearVelocities() {
+		for (int i = 0; i < velocities.Num(); i++) {
+			delete velocities[i];
+			velocities[i] = NULL;
+		}
+		velocities.Clear();
+	}
+
+	virtual void clear() {
+		editMode = false;
+		clearVelocities();
+	}
+
+	idCameraPosition(const char *p) {
+		name = p;
+	}
+
+	idCameraPosition() {
+		time = 0;
+		name = "position";
+	}
+
+	idCameraPosition(long t) {
+		time = t;
+	}
+
+	virtual ~idCameraPosition() {
+		clear();
+	}
+
+	
+	// this can be done with RTTI syntax but i like the derived classes setting a type
+	// makes serialization a bit easier to see
+	//
+	enum positionType {
+		FIXED = 0x00,
+		INTERPOLATED,
+		SPLINE,
+		POSITION_COUNT
+	};
+
+
+	virtual void start(long t) {
+		startTime = t;
+	}
+
+	long getTime() {
+		return time;
+	}
+
+	virtual void setTime(long t) {
+		time = t;
+	}
+
+	float getBaseVelocity() {
+		return baseVelocity;
+	}
+
+	float getVelocity(long t) {
+		long check = t - startTime;
+		for (int i = 0; i < velocities.Num(); i++) {
+			if (check >= velocities[i]->startTime && check <= velocities[i]->startTime + velocities[i]->time) {
+				return velocities[i]->speed;
+			}
+		}
+		return baseVelocity;
+	}
+
+	void addVelocity(long start, long duration, float speed) {
+		velocities.Append(new idVelocity(start, duration, speed));
+	}
+
+	virtual const idVec3 *getPosition(long t) { 
+		assert(true);
+		return NULL;
+	}
+
+	virtual void draw(bool editMode) {};
+
+	virtual void parse(const char *(*text)) {};
+	virtual void write(fileHandle_t file, const char *name);
+	virtual bool parseToken(const char *key, const char *(*text));
+
+	const char *getName() {
+		return name.c_str();
+	}
+
+	void setName(const char *p) {
+		name = p;
+	}
+
+	virtual void startEdit() {
+		editMode = true;
+	}
+
+	virtual void stopEdit() {
+		editMode = false;
+	}
+
+	virtual void draw() {};
+
+	const char *typeStr() {
+		return positionStr[static_cast<int>(type)];
+	}
+
+	void calcVelocity(float distance) {
+		float secs = (float)time / 1000;
+		baseVelocity = distance / secs;
+	}
+
+protected:
+	static const char* positionStr[POSITION_COUNT];
+	long		startTime;
+	long		time;
+	idCameraPosition::positionType type;
+	idStr		name;
+	bool	editMode;
+	idList<idVelocity*> velocities;
+	float		baseVelocity;
+};
+
+class idFixedPosition : public idCameraPosition {
+public:
+
+	void init() {
+		pos.Zero();
+		type = idCameraPosition::FIXED;
+	}
+	
+	idFixedPosition() : idCameraPosition() {
+		init();
+	}
+	
+	idFixedPosition(idVec3 p) : idCameraPosition() {
+		init();
+		pos = p;
+	}
+
+	virtual void addPoint(const idVec3 &v) {
+		pos = v;
+	}
+	
+	virtual void addPoint(const float x, const float y, const float z) {
+		pos.set(x, y, z);
+	}
+
+
+	~idFixedPosition() {
+	}
+
+	virtual const idVec3 *getPosition(long t) { 
+		return &pos;
+	}
+
+	void parse(const char *(*text));
+	void write(fileHandle_t file, const char *name);
+
+	virtual int numPoints() {
+		return 1;
+	}
+
+	virtual idVec3 *getPoint(int index) {
+		if (index != 0) {
+			assert(true);
+		};
+		return &pos;
+	}
+
+	virtual void draw(bool editMode) {
+		glLabeledPoint(blue, pos, (editMode) ? 5 : 3, "Fixed point");
+	}
+
+protected:
+	idVec3 pos;
+};
+
+class idInterpolatedPosition : public idCameraPosition {
+public:
+
+	void init() {
+		type = idCameraPosition::INTERPOLATED;
+		first = true;
+		startPos.Zero();
+		endPos.Zero();
+	}
+	
+	idInterpolatedPosition() : idCameraPosition() {
+		init();
+	}
+	
+	idInterpolatedPosition(idVec3 start, idVec3 end, long time) : idCameraPosition(time) {
+		init();
+		startPos = start;
+		endPos = end;
+	}
+
+	~idInterpolatedPosition() {
+	}
+
+	virtual const idVec3 *getPosition(long t);
+
+	void parse(const char *(*text));
+	void write(fileHandle_t file, const char *name);
+
+	virtual int numPoints() {
+		return 2;
+	}
+
+	virtual idVec3 *getPoint(int index) {
+		assert(index >= 0 && index < 2);
+		if (index == 0) {
+			return &startPos;
+		}
+		return &endPos;
+	}
+
+	virtual void addPoint(const float x, const float y, const float z) {
+		if (first) {
+			startPos.set(x, y, z);
+			first = false;
+		} else {
+			endPos.set(x, y, z);
+			first = true;
+		}
+	}
+
+	virtual void addPoint(const idVec3 &v) {
+		if (first) {
+			startPos = v;
+			first = false;
+		} else {
+			endPos = v;
+			first = true;
+		}
+	}
+
+	virtual void draw(bool editMode) {
+		glLabeledPoint(blue, startPos, (editMode) ? 5 : 3, "Start interpolated");
+		glLabeledPoint(blue, endPos, (editMode) ? 5 : 3, "End interpolated");
+		qglBegin(GL_LINES);
+		qglVertex3fv(startPos);
+		qglVertex3fv(endPos);
+		qglEnd();
+	}
+
+	virtual void start(long t) {
+		idCameraPosition::start(t);
+		lastTime = startTime;
+		distSoFar = 0.0;
+		idVec3 temp = startPos;
+		temp -= endPos;
+		calcVelocity(temp.Length());
+	}
+
+protected:
+	bool first;
+	idVec3 startPos;
+	idVec3 endPos;
+	long lastTime;
+	float distSoFar;
+};
+
+class idSplinePosition : public idCameraPosition {
+public:
+
+	void init() {
+		type = idCameraPosition::SPLINE;
+	}
+	
+	idSplinePosition() : idCameraPosition() {
+		init();
+	}
+	
+	idSplinePosition(long time) : idCameraPosition(time) {
+		init();
+	}
+
+	~idSplinePosition() {
+	}
+
+	virtual void start(long t) {
+		idCameraPosition::start(t);
+		target.initPosition(t, time);
+		lastTime = startTime;
+		distSoFar = 0.0;
+		calcVelocity(target.totalDistance());
+	}
+
+	//virtual const idVec3 *getPosition(long t) { 
+	//	return target.getPosition(t);
+	//}
+	virtual const idVec3 *getPosition(long t);
+
+
+	//virtual const idVec3 *getPosition(long t) const { 
+
+	void addControlPoint(idVec3 &v) {
+		target.addPoint(v);
+	}
+
+	void parse(const char *(*text));
+	void write(fileHandle_t file, const char *name);
+
+	virtual int numPoints() {
+		return target.numPoints();
+	}
+
+	virtual idVec3 *getPoint(int index) {
+		return target.getPoint(index);
+	}
+
+	virtual void addPoint(const idVec3 &v) {
+		target.addPoint(v);
+	}
+
+	virtual void addPoint(const float x, const float y, const float z) {
+		target.addPoint(x, y, z);
+	}
+
+	virtual void draw(bool editMode) {
+		target.draw(editMode);
+	}
+
+	virtual void updateSelection(const idVec3 &move) {
+		idCameraPosition::updateSelection(move);
+		target.buildSpline();
+	}
+
+protected:
+	idSplineList target;
+	long lastTime;
+	float distSoFar;
+};
+
+class idCameraFOV {
+public:
+	
+	idCameraFOV() {
+		time = 0;
+		length = 0;
+		fov = 90;
+	}
+
+	idCameraFOV(int v) {
+		time = 0;
+		length = 0;
+		fov = v;
+	}
+
+	idCameraFOV(int s, int e, long t) {
+		startFOV = s;
+		endFOV = e;
+		length = t;
+	}
+
+
+	~idCameraFOV(){}
+
+	void setFOV(float f) {
+		fov = f;
+	}
+
+	float getFOV(long t) {
+		if (length) {
+			float percent = (t - startTime) / length;
+			if (percent < 0.0) {
+				percent = 0.0;
+			} else if (percent > 1.0) {
+				percent = 1.0;
+			}
+			float temp = endFOV - startFOV;
+			temp *= percent;
+			fov = startFOV + temp;
+
+			if (percent == 1.0) {
+				length = 0.0;
+			}
+		}
+		return fov;
+	}
+
+	void start(long t) {
+		startTime = t;
+	}
+
+	void reset(float startfov, float endfov, int start, float len) {
+		startFOV = startfov;
+		endFOV = endfov;
+		startTime = start;
+		length = len * 1000;
+	}
+
+	void parse(const char *(*text));
+	void write(fileHandle_t file, const char *name);
+
+protected:
+	float fov;
+	float startFOV;
+	float endFOV;
+	int startTime;
+	int time;
+	float length;
+};
+
+
+
+
+class idCameraEvent {
+public:						// parameters
+	enum eventType {
+		EVENT_NA = 0x00,
+		EVENT_WAIT,			// 
+		EVENT_TARGETWAIT,	// 
+		EVENT_SPEED,		// 
+		EVENT_TARGET,		// char(name)
+		EVENT_SNAPTARGET,	// 
+		EVENT_FOV,			// int(time), int(targetfov)
+		EVENT_CMD,			// 
+		EVENT_TRIGGER,		// 
+		EVENT_STOP,			// 
+		EVENT_CAMERA,		// 
+		EVENT_FADEOUT,		// int(time)
+		EVENT_FADEIN,		// int(time)
+		EVENT_FEATHER,		// 
+		EVENT_COUNT			
+	};
+
+	static const char* eventStr[EVENT_COUNT];
+
+	idCameraEvent() {
+		paramStr = "";
+		type = EVENT_NA;
+		time = 0;
+	}
+
+	idCameraEvent(eventType t, const char *param, long n) {
+		type = t;
+		paramStr = param;
+		time = n;
+	}
+
+	~idCameraEvent() {};
+
+	eventType getType() {
+		return type;
+	}
+
+	const char *typeStr() {
+		return eventStr[static_cast<int>(type)];
+	}
+
+	const char *getParam() {
+		return paramStr.c_str();
+	}
+
+	long getTime() {
+		return time;
+	}
+
+	void setTime(long n) {
+		time = n;
+	}
+
+	void parse(const char *(*text));
+	void write(fileHandle_t file, const char *name);
+
+	void setTriggered(bool b) {
+		triggered = b;
+	}
+
+	bool getTriggered() {
+		return triggered;
+	}
+
+protected:
+	eventType type;
+	idStr paramStr;
+	long time;
+	bool triggered;
+
+};
+
+class idCameraDef {
+public:
+
+	void clear() {
+		currentCameraPosition = 0;
+		cameraRunning = false;
+		lastDirection.Zero();
+		baseTime = 30;
+		activeTarget = 0;
+		name = "camera01";
+		fov.setFOV(90);
+		int i;
+		for (i = 0; i < targetPositions.Num(); i++) {
+			delete targetPositions[i];
+		}
+		for (i = 0; i < events.Num(); i++) {
+			delete events[i];
+		}
+		delete cameraPosition;
+		cameraPosition = NULL;
+		events.Clear();
+		targetPositions.Clear();
+	}
+
+	idCameraPosition *startNewCamera(idCameraPosition::positionType type) {
+		clear();
+		if (type == idCameraPosition::SPLINE) {
+			cameraPosition = new idSplinePosition();
+		} else if (type == idCameraPosition::INTERPOLATED) {
+			cameraPosition = new idInterpolatedPosition();
+		} else {
+			cameraPosition = new idFixedPosition();
+		}
+		return cameraPosition;
+	}
+
+	idCameraDef() {
+		cameraPosition = NULL;
+		clear();
+	}
+
+	~idCameraDef() {
+		clear();
+	}
+
+	void addEvent(idCameraEvent::eventType t, const char *param, long time);
+
+	void addEvent(idCameraEvent *event);
+
+	void removeEvent( int index);
+
+	static int sortEvents(const void *p1, const void *p2);
+
+	int numEvents() {
+		return events.Num();
+	}
+
+	idCameraEvent *getEvent(int index) {
+		assert(index >= 0 && index < events.Num());
+		return events[index];
+	}
+
+	void parse(const char *(*text));
+	bool load(const char *filename);
+	void save(const char *filename);
+
+	void buildCamera();
+
+	//idSplineList *getcameraPosition() {
+	//	return &cameraPosition;
+	//}
+
+	static idCameraPosition *newFromType(idCameraPosition::positionType t) {
+		switch (t) {
+			case idCameraPosition::FIXED : return new idFixedPosition();
+			case idCameraPosition::INTERPOLATED : return new idInterpolatedPosition();
+			case idCameraPosition::SPLINE : return new idSplinePosition();
+      default:
+        break;
+		};
+		return NULL;
+	}
+
+	void addTarget(const char *name, idCameraPosition::positionType type);
+
+	idCameraPosition *getActiveTarget() {
+		if (targetPositions.Num() == 0) {
+			addTarget(NULL, idCameraPosition::FIXED);
+		}
+		return targetPositions[activeTarget];
+	}
+
+	idCameraPosition *getActiveTarget(int index) {
+		if (targetPositions.Num() == 0) {
+			addTarget(NULL, idCameraPosition::FIXED);
+			return targetPositions[0];
+		}
+		return targetPositions[index];
+	}
+
+	int numTargets() {
+		return targetPositions.Num();
+	}
+
+
+	void setActiveTargetByName(const char *name) {
+		for (int i = 0; i < targetPositions.Num(); i++) {
+			if (Q_stricmp(name, targetPositions[i]->getName()) == 0) {
+				setActiveTarget(i);
+				return;
+			}
+		}
+	}
+
+	void setActiveTarget(int index) {
+		assert(index >= 0 && index < targetPositions.Num());
+		activeTarget = index;
+	}
+
+	void setRunning(bool b) {
+		cameraRunning = b;
+	}
+
+	void setBaseTime(float f) {
+		baseTime = f;
+	}
+
+	float getBaseTime() {
+		return baseTime;
+	}
+
+	float getTotalTime() {
+		return totalTime;
+	}
+	
+	void startCamera(long t);
+	void stopCamera() {
+		cameraRunning = true;
+	}
+	void getActiveSegmentInfo(int segment, idVec3 &origin, idVec3 &direction, float *fv);
+
+	bool getCameraInfo(long time, idVec3 &origin, idVec3 &direction, float *fv);
+	bool getCameraInfo(long time, float *origin, float *direction, float *fv) {
+		idVec3 org, dir;
+		org[0] = origin[0];
+		org[1] = origin[1];
+		org[2] = origin[2];
+		dir[0] = direction[0];
+		dir[1] = direction[1];
+		dir[2] = direction[2];
+		bool b = getCameraInfo(time, org, dir, fv);
+		origin[0] = org[0];
+		origin[1] = org[1];
+		origin[2] = org[2];
+		direction[0] = dir[0];
+		direction[1] = dir[1];
+		direction[2] = dir[2];
+		return b;
+	}
+
+	void draw(bool editMode) {
+                // gcc doesn't allow casting away from bools
+                // why?  I've no idea...
+		if (cameraPosition) {
+			cameraPosition->draw((bool)((editMode || cameraRunning) && cameraEdit));
+			int count = targetPositions.Num();
+			for (int i = 0; i < count; i++) {
+				targetPositions[i]->draw((bool)((editMode || cameraRunning) && i == activeTarget && !cameraEdit));
+			}
+		}
+	}
+
+/*
+	int numSegments() {
+		if (cameraEdit) {
+			return cameraPosition.numSegments();
+		}
+		return getTargetSpline()->numSegments();
+	}
+
+	int getActiveSegment() {
+		if (cameraEdit) {
+			return cameraPosition.getActiveSegment();
+		}
+		return getTargetSpline()->getActiveSegment();
+	}
+
+	void setActiveSegment(int i) {
+		if (cameraEdit) {
+			cameraPosition.setActiveSegment(i);
+		} else {
+			getTargetSpline()->setActiveSegment(i);
+		}
+	}
+*/
+	int numPoints() {
+		if (cameraEdit) {
+			return cameraPosition->numPoints();
+		}
+		return getActiveTarget()->numPoints();
+	}
+
+	const idVec3 *getPoint(int index) {
+		if (cameraEdit) {
+			return cameraPosition->getPoint(index);
+		}
+		return getActiveTarget()->getPoint(index);
+	}
+
+	void stopEdit() {
+		editMode = false;
+		if (cameraEdit) {
+			cameraPosition->stopEdit();
+		} else {
+			getActiveTarget()->stopEdit();
+		}
+	}
+
+	void startEdit(bool camera) {
+		cameraEdit = camera;
+		if (camera) {
+			cameraPosition->startEdit();
+			for (int i = 0; i < targetPositions.Num(); i++) {
+				targetPositions[i]->stopEdit();
+			}
+		} else {
+			getActiveTarget()->startEdit();
+			cameraPosition->stopEdit();
+		}
+		editMode = true;
+	}
+
+	bool waitEvent(int index);
+
+	const char *getName() {
+		return name.c_str();
+	}
+
+	void setName(const char *p) {
+		name = p;
+	}
+
+	idCameraPosition *getPositionObj() {
+		if (cameraPosition == NULL) {
+			cameraPosition = new idFixedPosition();
+		}
+		return cameraPosition;
+	}
+
+protected:
+	idStr name;
+	int currentCameraPosition;
+	idVec3 lastDirection;
+	bool cameraRunning;
+	idCameraPosition *cameraPosition;
+	idList<idCameraPosition*> targetPositions;
+	idList<idCameraEvent*> events;
+	idCameraFOV fov;
+	int activeTarget;
+	float totalTime;
+	float baseTime;
+	long startTime;
+
+	bool cameraEdit;
+	bool editMode;
+};
+
+extern bool g_splineMode;
+
+extern idCameraDef *g_splineList;
+
+
+#endif
diff --git a/libs/splines/util_list.h b/libs/splines/util_list.h
index 7dc72491..7776e87c 100644
--- a/libs/splines/util_list.h
+++ b/libs/splines/util_list.h
@@ -1,346 +1,346 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __UTIL_LIST_H__
-#define __UTIL_LIST_H__
-
-#include <stdlib.h>
-#include <assert.h>
-
-template< class type >
-class idList {
-private:
-	int			m_num;
-	int			m_size;
-	int			m_granularity;
-	type		*m_list;
-
-public:
-				idList( int granularity = 16 );
-				~idList<type>();
-	void		Clear( void );
-	int			Num( void );
-	void		SetNum( int num );
-	void		SetGranularity( int granularity );
-	void		Condense( void );
-	int			Size( void );
-	void		Resize( int size );
-	type		operator[]( int index ) const;
-	type		&operator[]( int index );
-	int			Append( type const & obj );
-	int			AddUnique( type const & obj );
-	type		*Find( type const & obj, int *index = NULL );
-	bool		RemoveIndex( int index );
-	bool		Remove( type const & obj );
-	typedef int cmp_t(const void *, const void *);
-	void		Sort( cmp_t *compare );
-};
-
-/*
-================
-idList<type>::idList( int )
-================
-*/
-template< class type >
-inline idList<type>::idList( int granularity ) {
-	assert( granularity > 0 );
-
-	m_list			= NULL;
-	m_granularity	= granularity;
-	Clear();
-}
-
-/*
-================
-idList<type>::~idList<type>
-================
-*/
-template< class type >
-inline idList<type>::~idList() {
-	Clear();
-}
-
-/*
-================
-idList<type>::Clear
-================
-*/
-template< class type >
-inline void idList<type>::Clear( void ) {
-	if ( m_list ) {
-		delete[] m_list;
-	}
-
-	m_list	= NULL;
-	m_num	= 0;
-	m_size	= 0;
-}
-
-/*
-================
-idList<type>::Num
-================
-*/
-template< class type >
-inline int idList<type>::Num( void ) {
-	return m_num;
-}
-
-/*
-================
-idList<type>::SetNum
-================
-*/
-template< class type >
-inline void idList<type>::SetNum( int num ) {
-	assert( num >= 0 );
-	if ( num > m_size ) {
-		// resize it up to the closest level of granularity
-		Resize( ( ( num + m_granularity - 1 ) / m_granularity ) * m_granularity );
-	}
-	m_num = num;
-}
-
-/*
-================
-idList<type>::SetGranularity
-================
-*/
-template< class type >
-inline void idList<type>::SetGranularity( int granularity ) {
-	int newsize;
-
-	assert( granularity > 0 );
-	m_granularity = granularity;
-
-	if ( m_list ) {
-		// resize it to the closest level of granularity
-		newsize = ( ( m_num + m_granularity - 1 ) / m_granularity ) * m_granularity;
-		if ( newsize != m_size ) {
-			Resize( newsize );
-		}
-	}
-}
-
-/*
-================
-idList<type>::Condense
-
-Resizes the array to exactly the number of elements it contains
-================
-*/
-template< class type >
-inline void idList<type>::Condense( void ) {
-	if ( m_list ) {
-		if ( m_num ) {
-			Resize( m_num );
-		} else {
-			Clear();
-		}
-	}
-}
-
-/*
-================
-idList<type>::Size
-================
-*/
-template< class type >
-inline int idList<type>::Size( void ) {
-	return m_size;
-}
-
-/*
-================
-idList<type>::Resize
-================
-*/
-template< class type >
-inline void idList<type>::Resize( int size ) {
-	type	*temp;
-	int		i;
-
-	assert( size > 0 );
-
-	if ( size <= 0 ) {
-		Clear();
-		return;
-	}
-
-	temp	= m_list;
-	m_size	= size;
-	if ( m_size < m_num ) {
-		m_num = m_size;
-	}
-
-	m_list = new type[ m_size ];
-	for( i = 0; i < m_num; i++ ) {
-		m_list[ i ] = temp[ i ];
-	}
-
-	if ( temp ) {
-		delete[] temp;
-	}
-}
-
-/*
-================
-idList<type>::operator[] const
-================
-*/
-template< class type >
-inline type idList<type>::operator[]( int index ) const {
-	assert( index >= 0 );
-	assert( index < m_num );
-
-	return m_list[ index ];
-}
-
-/*
-================
-idList<type>::operator[]
-================
-*/
-template< class type >
-inline type &idList<type>::operator[]( int index ) {
-	assert( index >= 0 );
-	assert( index < m_num );
-
-	return m_list[ index ];
-}
-
-/*
-================
-idList<type>::Append
-================
-*/
-template< class type >
-inline int idList<type>::Append( type const & obj ) {
-	if ( !m_list ) {
-		Resize( m_granularity );
-	}
-
-	if ( m_num == m_size ) {
-		Resize( m_size + m_granularity );
-	}
-
-	m_list[ m_num ] = obj;
-	m_num++;
-
-	return m_num - 1;
-}
-
-/*
-================
-idList<type>::AddUnique
-================
-*/
-template< class type >
-inline int idList<type>::AddUnique( type const & obj ) {
-	int index;
-
-	if ( !Find( obj, &index ) ) {
-		index = Append( obj );
-	}
-
-	return index;
-}
-
-/*
-================
-idList<type>::Find
-================
-*/
-template< class type >
-inline type *idList<type>::Find( type const & obj, int *index ) {
-	int i;
-
-	for( i = 0; i < m_num; i++ ) {
-		if ( m_list[ i ] == obj ) {
-			if ( index ) {
-				*index = i;
-			}
-			return &m_list[ i ];
-		}
-	}
-
-	return NULL;
-}
-
-/*
-================
-idList<type>::RemoveIndex
-================
-*/
-template< class type >
-inline bool idList<type>::RemoveIndex( int index ) {
-	int i;
-
-	if ( !m_list || !m_num ) {
-		return false;
-	}
-
-	assert( index >= 0 );
-	assert( index < m_num );
-
-	if ( ( index < 0 ) || ( index >= m_num ) ) {
-		return false;
-	}
-
-	m_num--;
-	for( i = index; i < m_num; i++ ) {
-		m_list[ i ] = m_list[ i + 1 ];
-	}
-
-	return true;
-}
-
-/*
-================
-idList<type>::Remove
-================
-*/
-template< class type >
-inline bool idList<type>::Remove( type const & obj ) {
-	int index;
-
-	if ( Find( obj, &index ) ) {
-		return RemoveIndex( index );
-	}
-	
-	return false;
-}
-
-/*
-================
-idList<type>::Sort
-================
-*/
-template< class type >
-inline void idList<type>::Sort( cmp_t *compare ) {
-	if ( !m_list ) {
-		return;
-	}
-
-	qsort( ( void * )m_list, ( size_t )m_num, sizeof( type ), compare );
-}
-
-#endif /* !__UTIL_LIST_H__ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __UTIL_LIST_H__
+#define __UTIL_LIST_H__
+
+#include <stdlib.h>
+#include <assert.h>
+
+template< class type >
+class idList {
+private:
+	int			m_num;
+	int			m_size;
+	int			m_granularity;
+	type		*m_list;
+
+public:
+				idList( int granularity = 16 );
+				~idList<type>();
+	void		Clear( void );
+	int			Num( void );
+	void		SetNum( int num );
+	void		SetGranularity( int granularity );
+	void		Condense( void );
+	int			Size( void );
+	void		Resize( int size );
+	type		operator[]( int index ) const;
+	type		&operator[]( int index );
+	int			Append( type const & obj );
+	int			AddUnique( type const & obj );
+	type		*Find( type const & obj, int *index = NULL );
+	bool		RemoveIndex( int index );
+	bool		Remove( type const & obj );
+	typedef int cmp_t(const void *, const void *);
+	void		Sort( cmp_t *compare );
+};
+
+/*
+================
+idList<type>::idList( int )
+================
+*/
+template< class type >
+inline idList<type>::idList( int granularity ) {
+	assert( granularity > 0 );
+
+	m_list			= NULL;
+	m_granularity	= granularity;
+	Clear();
+}
+
+/*
+================
+idList<type>::~idList<type>
+================
+*/
+template< class type >
+inline idList<type>::~idList() {
+	Clear();
+}
+
+/*
+================
+idList<type>::Clear
+================
+*/
+template< class type >
+inline void idList<type>::Clear( void ) {
+	if ( m_list ) {
+		delete[] m_list;
+	}
+
+	m_list	= NULL;
+	m_num	= 0;
+	m_size	= 0;
+}
+
+/*
+================
+idList<type>::Num
+================
+*/
+template< class type >
+inline int idList<type>::Num( void ) {
+	return m_num;
+}
+
+/*
+================
+idList<type>::SetNum
+================
+*/
+template< class type >
+inline void idList<type>::SetNum( int num ) {
+	assert( num >= 0 );
+	if ( num > m_size ) {
+		// resize it up to the closest level of granularity
+		Resize( ( ( num + m_granularity - 1 ) / m_granularity ) * m_granularity );
+	}
+	m_num = num;
+}
+
+/*
+================
+idList<type>::SetGranularity
+================
+*/
+template< class type >
+inline void idList<type>::SetGranularity( int granularity ) {
+	int newsize;
+
+	assert( granularity > 0 );
+	m_granularity = granularity;
+
+	if ( m_list ) {
+		// resize it to the closest level of granularity
+		newsize = ( ( m_num + m_granularity - 1 ) / m_granularity ) * m_granularity;
+		if ( newsize != m_size ) {
+			Resize( newsize );
+		}
+	}
+}
+
+/*
+================
+idList<type>::Condense
+
+Resizes the array to exactly the number of elements it contains
+================
+*/
+template< class type >
+inline void idList<type>::Condense( void ) {
+	if ( m_list ) {
+		if ( m_num ) {
+			Resize( m_num );
+		} else {
+			Clear();
+		}
+	}
+}
+
+/*
+================
+idList<type>::Size
+================
+*/
+template< class type >
+inline int idList<type>::Size( void ) {
+	return m_size;
+}
+
+/*
+================
+idList<type>::Resize
+================
+*/
+template< class type >
+inline void idList<type>::Resize( int size ) {
+	type	*temp;
+	int		i;
+
+	assert( size > 0 );
+
+	if ( size <= 0 ) {
+		Clear();
+		return;
+	}
+
+	temp	= m_list;
+	m_size	= size;
+	if ( m_size < m_num ) {
+		m_num = m_size;
+	}
+
+	m_list = new type[ m_size ];
+	for( i = 0; i < m_num; i++ ) {
+		m_list[ i ] = temp[ i ];
+	}
+
+	if ( temp ) {
+		delete[] temp;
+	}
+}
+
+/*
+================
+idList<type>::operator[] const
+================
+*/
+template< class type >
+inline type idList<type>::operator[]( int index ) const {
+	assert( index >= 0 );
+	assert( index < m_num );
+
+	return m_list[ index ];
+}
+
+/*
+================
+idList<type>::operator[]
+================
+*/
+template< class type >
+inline type &idList<type>::operator[]( int index ) {
+	assert( index >= 0 );
+	assert( index < m_num );
+
+	return m_list[ index ];
+}
+
+/*
+================
+idList<type>::Append
+================
+*/
+template< class type >
+inline int idList<type>::Append( type const & obj ) {
+	if ( !m_list ) {
+		Resize( m_granularity );
+	}
+
+	if ( m_num == m_size ) {
+		Resize( m_size + m_granularity );
+	}
+
+	m_list[ m_num ] = obj;
+	m_num++;
+
+	return m_num - 1;
+}
+
+/*
+================
+idList<type>::AddUnique
+================
+*/
+template< class type >
+inline int idList<type>::AddUnique( type const & obj ) {
+	int index;
+
+	if ( !Find( obj, &index ) ) {
+		index = Append( obj );
+	}
+
+	return index;
+}
+
+/*
+================
+idList<type>::Find
+================
+*/
+template< class type >
+inline type *idList<type>::Find( type const & obj, int *index ) {
+	int i;
+
+	for( i = 0; i < m_num; i++ ) {
+		if ( m_list[ i ] == obj ) {
+			if ( index ) {
+				*index = i;
+			}
+			return &m_list[ i ];
+		}
+	}
+
+	return NULL;
+}
+
+/*
+================
+idList<type>::RemoveIndex
+================
+*/
+template< class type >
+inline bool idList<type>::RemoveIndex( int index ) {
+	int i;
+
+	if ( !m_list || !m_num ) {
+		return false;
+	}
+
+	assert( index >= 0 );
+	assert( index < m_num );
+
+	if ( ( index < 0 ) || ( index >= m_num ) ) {
+		return false;
+	}
+
+	m_num--;
+	for( i = index; i < m_num; i++ ) {
+		m_list[ i ] = m_list[ i + 1 ];
+	}
+
+	return true;
+}
+
+/*
+================
+idList<type>::Remove
+================
+*/
+template< class type >
+inline bool idList<type>::Remove( type const & obj ) {
+	int index;
+
+	if ( Find( obj, &index ) ) {
+		return RemoveIndex( index );
+	}
+	
+	return false;
+}
+
+/*
+================
+idList<type>::Sort
+================
+*/
+template< class type >
+inline void idList<type>::Sort( cmp_t *compare ) {
+	if ( !m_list ) {
+		return;
+	}
+
+	qsort( ( void * )m_list, ( size_t )m_num, sizeof( type ), compare );
+}
+
+#endif /* !__UTIL_LIST_H__ */
diff --git a/libs/splines/util_str.h b/libs/splines/util_str.h
index 26dfa42d..0ce1ecb4 100644
--- a/libs/splines/util_str.h
+++ b/libs/splines/util_str.h
@@ -1,817 +1,817 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//need to rewrite this
-
-#ifndef __UTIL_STR_H__
-#define __UTIL_STR_H__
-
-#include <assert.h>
-#include <string.h>
-#include <stdio.h>
-
-#ifdef _WIN32
-#pragma warning(disable : 4710)     // function 'blah' not inlined
-#endif
-
-void TestStringClass ();
-
-class strdata
-   {
-   public:
-      strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
-      ~strdata () 
-         {
-         if ( data )
-            delete [] data;
-         }
-
-      void AddRef () { refcount++; }
-      bool DelRef () // True if killed
-         {
-         refcount--;
-         if ( refcount < 0 )
-            {
-            delete this;
-            return true;
-            }
-         
-         return false;
-         }
-
-      int len;
-      int refcount;
-      char *data;
-      int alloced;
-   };
-
-class idStr {
-protected:
-	strdata	*m_data;
-	void EnsureAlloced ( int, bool keepold = true );
-	void EnsureDataWritable ();
-
-public:
-	~idStr();
-	idStr();
-	idStr( const char *text );
-	idStr( const idStr& string );
-	idStr( const idStr string, int start, int end );
-	idStr( const char ch );
-	idStr( const int num );
-	idStr( const float num );
-	idStr( const unsigned num );
-	int	length( void ) const;
-	int	allocated( void ) const;
-	const char * c_str( void ) const;
-
-	void		append( const char *text );
-	void		append( const idStr& text );
-	char		operator[]( int index ) const;
-	char&		operator[]( int index );
-
-	void		operator=( const idStr& text );
-	void		operator=( const char *text );
-
-	friend	idStr		operator+( const idStr& a, const idStr& b );
-	friend	idStr		operator+( const idStr& a, const char *b );
-	friend	idStr		operator+( const char *a, const idStr& b );
-
-    friend	idStr		operator+( const idStr& a, const float b );
-    friend	idStr		operator+( const idStr& a, const int b );
-    friend	idStr		operator+( const idStr& a, const unsigned b );
-    friend	idStr		operator+( const idStr& a, const bool b );
-    friend	idStr		operator+( const idStr& a, const char b );
-
-	idStr&		operator+=( const idStr& a );
-	idStr&		operator+=( const char *a );
-	idStr&		operator+=( const float a );
-	idStr&		operator+=( const char a );
-	idStr&		operator+=( const int a );
-	idStr&		operator+=( const unsigned a );
-	idStr&		operator+=( const bool a );
-
-	friend	bool		operator==(	const idStr& a, const idStr& b );
-	friend	bool		operator==(	const idStr& a, const char *b );
-	friend	bool		operator==(	const char *a, const idStr& b );
-
-	friend	bool		operator!=(	const idStr& a, const idStr& b );
-	friend	bool		operator!=(	const idStr& a, const char *b );
-	friend	bool		operator!=(	const char *a, const idStr& b );
-
-	operator const char * () const;
-	operator const char * ();
-
-    int      icmpn( const char *text, int n ) const;
-	int      icmpn( const idStr& text, int n ) const;
-	int      icmp( const char *text ) const;
-	int      icmp( const idStr& text ) const;
-	int      cmpn( const char *text, int n ) const;
-	int      cmpn( const idStr& text, int n ) const;
-	int      cmp( const char *text ) const;
-	int      cmp( const idStr& text ) const;
-
-	void     tolower( void );
-	void     toupper( void );
-
-	static   char     *tolower( char *s1 );
-	static   char     *toupper( char *s1 );
-
-	static   int      icmpn( const char *s1, const char *s2, int n );
-	static   int      icmp( const char *s1, const char *s2 );
-	static   int      cmpn( const char *s1, const char *s2, int n );
-	static   int      cmp( const char *s1, const char *s2 );
-
-	static   void     snprintf ( char *dst, int size, const char *fmt, ... );
-
-	static   bool	   isNumeric( const char *str );
-    bool    isNumeric( void ) const;
-
-	void     CapLength ( int );
-
-	void     BackSlashesToSlashes ();
-
-};
-
-inline idStr::~idStr()
-	{
-   if ( m_data )
-      {
-      m_data->DelRef ();
-      m_data = NULL;
-      }
-	}
-
-inline idStr::idStr() : m_data ( NULL )
-	{
-   EnsureAlloced ( 1 );
-	m_data->data[ 0 ] = 0;
-	}
-
-inline idStr::idStr
-	(
-	const char *text
-   ) : m_data ( NULL )
-
-	{
-   int len;
-
-	assert( text );
-
-	if ( text )
-		{
-      len = strlen( text );
-		EnsureAlloced ( len + 1 );
-		strcpy( m_data->data, text );
-      m_data->len = len;
-		}
-	else
-		{
-      EnsureAlloced ( 1 );
-		m_data->data[ 0 ] = 0;
-		m_data->len = 0;
-		}
-	}
-
-inline idStr::idStr
-	(
-	const idStr& text
-   ) : m_data ( NULL )
-
-	{
-   m_data = text.m_data;
-   m_data->AddRef ();
-   }
-
-inline idStr::idStr
-	(
-	const idStr text, 
-	int start,
-	int end
-   ) : m_data ( NULL )
-
-	{
-	int i;
-   int len;
-
-	if ( end > text.length() )
-		{
-		end = text.length();
-		}
-
-	if ( start > text.length() )
-		{
-		start = text.length();
-		}
-
-	len = end - start;
-	if ( len < 0 )
-		{
-		len = 0;
-		}
-
-   EnsureAlloced ( len + 1 );
-
-	for( i = 0; i < len; i++ )
-		{
-		m_data->data[ i ] = text[ start + i ];
-		}
-
-	m_data->data[ len ] = 0;
-   m_data->len = len;
-	}
-
-inline idStr::idStr
-   (
-   const char ch
-   ) : m_data ( NULL )
-
-   {
-   EnsureAlloced ( 2 );
-
-   m_data->data[ 0 ] = ch;
-   m_data->data[ 1 ] = 0;
-   m_data->len = 1;
-   }
-
-inline idStr::idStr
-   (
-   const float num
-   ) : m_data ( NULL )
-
-   {
-   char text[ 32 ];
-   int len;
-
-   sprintf( text, "%.3f", num );
-   len = strlen( text );
-   EnsureAlloced( len + 1 );
-   strcpy( m_data->data, text );
-   m_data->len = len;
-   }
-
-inline idStr::idStr
-   (
-   const int num
-   ) : m_data ( NULL )
-
-   {
-   char text[ 32 ];
-   int len;
-
-   sprintf( text, "%d", num );
-   len = strlen( text );
-   EnsureAlloced( len + 1 );
-   strcpy( m_data->data, text );
-   m_data->len = len;
-   }
-
-inline idStr::idStr
-   (
-   const unsigned num
-   ) : m_data ( NULL )
-
-   {
-   char text[ 32 ];
-   int len;
-
-   sprintf( text, "%u", num );
-   len = strlen( text );
-   EnsureAlloced( len + 1 );
-   strcpy( m_data->data, text );
-   m_data->len = len;
-   }
-
-inline int idStr::length( void ) const
-	{
-   return ( m_data != NULL ) ? m_data->len : 0;
-	}
-
-inline int idStr::allocated( void ) const
-	{
-   return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
-	}
-
-inline const char *idStr::c_str( void ) const
-	{
-	assert( m_data );
-
-	return m_data->data;
-	}
-
-inline void idStr::append
-	(
-	const char *text
-	)
-
-	{
-   int len;
-
-	assert( text );
-
-	if ( text )
-		{
-		len = length() + strlen( text );
-		EnsureAlloced( len + 1 );
-
-      strcat( m_data->data, text );
-      m_data->len = len;
-		}
-	}
-
-inline void idStr::append
-	(
-	const idStr& text
-	)
-
-	{
-   int len;
-
-   len = length() + text.length();
-   EnsureAlloced ( len + 1 );
-
-   strcat ( m_data->data, text.c_str () );
-   m_data->len = len;
-	}
-
-inline char idStr::operator[]( int index ) const
-	{
-   assert ( m_data );
-   
-   if ( !m_data )
-      return 0;
-
-	// don't include the '/0' in the test, because technically, it's out of bounds
-	assert( ( index >= 0 ) && ( index < m_data->len ) );
-
-	// In release mode, give them a null character
-	// don't include the '/0' in the test, because technically, it's out of bounds
-	if ( ( index < 0 ) || ( index >= m_data->len ) )
-		{
-		return 0;
-		}
-
-	return m_data->data[ index ];
-	}
-
-inline char& idStr::operator[]
-	(
-	int index
-	)
-
-	{
-	// Used for result for invalid indices
-	static char dummy = 0;
-   assert ( m_data );
-
-   // We don't know if they'll write to it or not
-   // if it's not a const object
-   EnsureDataWritable ();
-
-   if ( !m_data )
-      return dummy;
-
-	// don't include the '/0' in the test, because technically, it's out of bounds
-	assert( ( index >= 0 ) && ( index < m_data->len ) );
-
-	// In release mode, let them change a safe variable
-	// don't include the '/0' in the test, because technically, it's out of bounds
-	if ( ( index < 0 ) || ( index >= m_data->len ) )
-		{
-		return dummy;
-		}
-
-	return m_data->data[ index ];
-	}
-
-inline void idStr::operator=
-	(
-	const idStr& text
-	)
-
-	{
-   // adding the reference before deleting our current reference prevents
-   // us from deleting our string if we are copying from ourself
-   text.m_data->AddRef();
-   m_data->DelRef();
-   m_data = text.m_data;
-   }
-
-inline void idStr::operator=
-	(
-	const char *text
-	)
-
-	{
-   int len;
-
-	assert( text );
-
-	if ( !text )
-		{
-		// safe behaviour if NULL
-		EnsureAlloced ( 1, false );
-      m_data->data[0] = 0;
-      m_data->len = 0;
-      return;
-		}
-
-   if ( !m_data )
-      {
-      len = strlen ( text );
-      EnsureAlloced( len + 1, false );
-      strcpy ( m_data->data, text );
-      m_data->len = len;
-      return;
-      }
-
-   if ( text == m_data->data )
-      return; // Copying same thing.  Punt.
-
-   // If we alias and I don't do this, I could corrupt other strings...  This 
-   // will get called with EnsureAlloced anyway
-   EnsureDataWritable ();
-
-   // Now we need to check if we're aliasing..
-   if ( text >= m_data->data && text <= m_data->data + m_data->len )
-      {
-      // Great, we're aliasing.  We're copying from inside ourselves.
-      // This means that I don't have to ensure that anything is alloced,
-      // though I'll assert just in case.
-      int diff = text - m_data->data;
-      int i;
-
-      assert ( strlen ( text ) < (unsigned) m_data->len );
-      
-      for ( i = 0; text[i]; i++ )
-         {
-         m_data->data[i] = text[i];
-         }
-
-      m_data->data[i] = 0;
-
-      m_data->len -= diff;
-
-      return;
-      }
-
-	len = strlen( text );
-   EnsureAlloced ( len + 1, false );
-	strcpy( m_data->data, text );
-   m_data->len = len;
-	}
-
-inline idStr operator+
-	(
-	const idStr& a,
-	const idStr& b
-	)
-
-	{
-	idStr result( a );
-
-	result.append( b );
-
-	return result;
-	}
-
-inline idStr operator+
-	(
-	const idStr& a,
-	const char *b
-	)
-
-	{
-	idStr result( a );
-
-	result.append( b );
-
-	return result;
-	}
-
-inline idStr operator+
-	(
-	const char *a,
-	const idStr& b
-	)
-
-	{
-	idStr result( a );
-
-	result.append( b );
-
-	return result;
-	}
-
-inline idStr operator+
-   (
-   const idStr& a,
-   const bool b
-   )
-
-   {
-	idStr result( a );
-
-   result.append( b ? "true" : "false" );
-
-	return result;
-   }
-
-inline idStr operator+
-	(
-   const idStr& a,
-	const char b
-	)
-
-	{
-   char text[ 2 ];
-
-   text[ 0 ] = b;
-   text[ 1 ] = 0;
-
-	return a + text;
-	}
-
-inline idStr& idStr::operator+=
-	(
-	const idStr& a
-	)
-
-	{
-	append( a );
-	return *this;
-	}
-
-inline idStr& idStr::operator+=
-	(
-	const char *a
-	)
-
-	{
-	append( a );
-	return *this;
-	}
-
-inline idStr& idStr::operator+=
-	(
-	const char a
-	)
-
-	{
-   char text[ 2 ];
-
-   text[ 0 ] = a;
-   text[ 1 ] = 0;
-	append( text );
-
-   return *this;
-	}
-
-inline idStr& idStr::operator+=
-	(
-	const bool a
-	)
-
-	{
-   append( a ? "true" : "false" );
-	return *this;
-	}
-
-inline bool operator==
-	(
-	const idStr& a,
-	const idStr& b
-	)
-
-	{
-	return ( !strcmp( a.c_str(), b.c_str() ) );
-	}
-
-inline bool operator==
-	(
-	const idStr& a,
-	const char *b
-	)
-
-	{
-	assert( b );
-	if ( !b )
-		{
-		return false;
-		}
-	return ( !strcmp( a.c_str(), b ) );
-	}
-
-inline bool operator==
-	(
-	const char *a,
-	const idStr& b
-	)
-
-	{
-	assert( a );
-	if ( !a )
-		{
-		return false;
-		}
-	return ( !strcmp( a, b.c_str() ) );
-	}
-
-inline bool operator!=
-	(
-	const idStr& a,
-	const idStr& b
-	)
-
-	{
-	return !( a == b );
-	}
-
-inline bool operator!=
-	(
-	const idStr& a,
-	const char *b
-	)
-
-	{
-	return !( a == b );
-	}
-
-inline bool operator!=
-	(
-	const char *a,
-	const idStr& b
-	)
-
-	{
-	return !( a == b );
-	}
-
-inline int idStr::icmpn
-   (
-   const char *text, 
-   int n
-   ) const
-
-   {
-	assert( m_data );
-	assert( text );
-
-   return idStr::icmpn( m_data->data, text, n );
-   }
-
-inline int idStr::icmpn
-   (
-   const idStr& text, 
-   int n
-   ) const
-
-   {
-	assert( m_data );
-	assert( text.m_data );
-
-   return idStr::icmpn( m_data->data, text.m_data->data, n );
-   }
-
-inline int idStr::icmp
-   (
-   const char *text
-   ) const
-
-   {
-	assert( m_data );
-	assert( text );
-
-   return idStr::icmp( m_data->data, text );
-   }
-
-inline int idStr::icmp
-   (
-   const idStr& text
-   ) const
-
-   {
-	assert( c_str () );
-	assert( text.c_str () );
-
-   return idStr::icmp( c_str () , text.c_str () );
-   }
-
-inline int idStr::cmp
-   (
-   const char *text
-   ) const
-
-   {
-	assert( m_data );
-	assert( text );
-
-   return idStr::cmp( m_data->data, text );
-   }
-
-inline int idStr::cmp
-   (
-   const idStr& text
-   ) const
-
-   {
-	assert( c_str () );
-	assert( text.c_str () );
-
-   return idStr::cmp( c_str () , text.c_str () );
-   }
-
-inline int idStr::cmpn
-   (
-   const char *text, 
-   int n
-   ) const
-
-   {
-	assert( c_str () );
-	assert( text );
-
-   return idStr::cmpn( c_str () , text, n );
-   }
-
-inline int idStr::cmpn
-   (
-   const idStr& text, 
-   int n
-   ) const
-
-   {
-	assert( c_str () );
-	assert( text.c_str ()  );
-
-   return idStr::cmpn( c_str () , text.c_str () , n );
-   }
-
-inline void idStr::tolower
-   (
-   void
-   )
-
-   {
-   assert( m_data );
-
-   EnsureDataWritable ();
-
-   idStr::tolower( m_data->data );
-   }
-
-inline void idStr::toupper
-   (
-   void
-   )
-
-   {
-   assert( m_data );
-
-   EnsureDataWritable ();
-
-   idStr::toupper( m_data->data );
-   }
-
-inline bool idStr::isNumeric
-   (
-   void
-   ) const
-
-   {
-   assert( m_data );
-   return idStr::isNumeric( m_data->data );
-   }
-
-inline idStr::operator const char *() {
-	return c_str();
-}
-
-inline idStr::operator const char *
-   (
-   void
-   ) const
-
-   {
-   return c_str ();
-   }
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//need to rewrite this
+
+#ifndef __UTIL_STR_H__
+#define __UTIL_STR_H__
+
+#include <assert.h>
+#include <string.h>
+#include <stdio.h>
+
+#ifdef _WIN32
+#pragma warning(disable : 4710)     // function 'blah' not inlined
+#endif
+
+void TestStringClass ();
+
+class strdata
+   {
+   public:
+      strdata () : len( 0 ), refcount ( 0 ), data ( NULL ), alloced ( 0 ) {}
+      ~strdata () 
+         {
+         if ( data )
+            delete [] data;
+         }
+
+      void AddRef () { refcount++; }
+      bool DelRef () // True if killed
+         {
+         refcount--;
+         if ( refcount < 0 )
+            {
+            delete this;
+            return true;
+            }
+         
+         return false;
+         }
+
+      int len;
+      int refcount;
+      char *data;
+      int alloced;
+   };
+
+class idStr {
+protected:
+	strdata	*m_data;
+	void EnsureAlloced ( int, bool keepold = true );
+	void EnsureDataWritable ();
+
+public:
+	~idStr();
+	idStr();
+	idStr( const char *text );
+	idStr( const idStr& string );
+	idStr( const idStr string, int start, int end );
+	idStr( const char ch );
+	idStr( const int num );
+	idStr( const float num );
+	idStr( const unsigned num );
+	int	length( void ) const;
+	int	allocated( void ) const;
+	const char * c_str( void ) const;
+
+	void		append( const char *text );
+	void		append( const idStr& text );
+	char		operator[]( int index ) const;
+	char&		operator[]( int index );
+
+	void		operator=( const idStr& text );
+	void		operator=( const char *text );
+
+	friend	idStr		operator+( const idStr& a, const idStr& b );
+	friend	idStr		operator+( const idStr& a, const char *b );
+	friend	idStr		operator+( const char *a, const idStr& b );
+
+    friend	idStr		operator+( const idStr& a, const float b );
+    friend	idStr		operator+( const idStr& a, const int b );
+    friend	idStr		operator+( const idStr& a, const unsigned b );
+    friend	idStr		operator+( const idStr& a, const bool b );
+    friend	idStr		operator+( const idStr& a, const char b );
+
+	idStr&		operator+=( const idStr& a );
+	idStr&		operator+=( const char *a );
+	idStr&		operator+=( const float a );
+	idStr&		operator+=( const char a );
+	idStr&		operator+=( const int a );
+	idStr&		operator+=( const unsigned a );
+	idStr&		operator+=( const bool a );
+
+	friend	bool		operator==(	const idStr& a, const idStr& b );
+	friend	bool		operator==(	const idStr& a, const char *b );
+	friend	bool		operator==(	const char *a, const idStr& b );
+
+	friend	bool		operator!=(	const idStr& a, const idStr& b );
+	friend	bool		operator!=(	const idStr& a, const char *b );
+	friend	bool		operator!=(	const char *a, const idStr& b );
+
+	operator const char * () const;
+	operator const char * ();
+
+    int      icmpn( const char *text, int n ) const;
+	int      icmpn( const idStr& text, int n ) const;
+	int      icmp( const char *text ) const;
+	int      icmp( const idStr& text ) const;
+	int      cmpn( const char *text, int n ) const;
+	int      cmpn( const idStr& text, int n ) const;
+	int      cmp( const char *text ) const;
+	int      cmp( const idStr& text ) const;
+
+	void     tolower( void );
+	void     toupper( void );
+
+	static   char     *tolower( char *s1 );
+	static   char     *toupper( char *s1 );
+
+	static   int      icmpn( const char *s1, const char *s2, int n );
+	static   int      icmp( const char *s1, const char *s2 );
+	static   int      cmpn( const char *s1, const char *s2, int n );
+	static   int      cmp( const char *s1, const char *s2 );
+
+	static   void     snprintf ( char *dst, int size, const char *fmt, ... );
+
+	static   bool	   isNumeric( const char *str );
+    bool    isNumeric( void ) const;
+
+	void     CapLength ( int );
+
+	void     BackSlashesToSlashes ();
+
+};
+
+inline idStr::~idStr()
+	{
+   if ( m_data )
+      {
+      m_data->DelRef ();
+      m_data = NULL;
+      }
+	}
+
+inline idStr::idStr() : m_data ( NULL )
+	{
+   EnsureAlloced ( 1 );
+	m_data->data[ 0 ] = 0;
+	}
+
+inline idStr::idStr
+	(
+	const char *text
+   ) : m_data ( NULL )
+
+	{
+   int len;
+
+	assert( text );
+
+	if ( text )
+		{
+      len = strlen( text );
+		EnsureAlloced ( len + 1 );
+		strcpy( m_data->data, text );
+      m_data->len = len;
+		}
+	else
+		{
+      EnsureAlloced ( 1 );
+		m_data->data[ 0 ] = 0;
+		m_data->len = 0;
+		}
+	}
+
+inline idStr::idStr
+	(
+	const idStr& text
+   ) : m_data ( NULL )
+
+	{
+   m_data = text.m_data;
+   m_data->AddRef ();
+   }
+
+inline idStr::idStr
+	(
+	const idStr text, 
+	int start,
+	int end
+   ) : m_data ( NULL )
+
+	{
+	int i;
+   int len;
+
+	if ( end > text.length() )
+		{
+		end = text.length();
+		}
+
+	if ( start > text.length() )
+		{
+		start = text.length();
+		}
+
+	len = end - start;
+	if ( len < 0 )
+		{
+		len = 0;
+		}
+
+   EnsureAlloced ( len + 1 );
+
+	for( i = 0; i < len; i++ )
+		{
+		m_data->data[ i ] = text[ start + i ];
+		}
+
+	m_data->data[ len ] = 0;
+   m_data->len = len;
+	}
+
+inline idStr::idStr
+   (
+   const char ch
+   ) : m_data ( NULL )
+
+   {
+   EnsureAlloced ( 2 );
+
+   m_data->data[ 0 ] = ch;
+   m_data->data[ 1 ] = 0;
+   m_data->len = 1;
+   }
+
+inline idStr::idStr
+   (
+   const float num
+   ) : m_data ( NULL )
+
+   {
+   char text[ 32 ];
+   int len;
+
+   sprintf( text, "%.3f", num );
+   len = strlen( text );
+   EnsureAlloced( len + 1 );
+   strcpy( m_data->data, text );
+   m_data->len = len;
+   }
+
+inline idStr::idStr
+   (
+   const int num
+   ) : m_data ( NULL )
+
+   {
+   char text[ 32 ];
+   int len;
+
+   sprintf( text, "%d", num );
+   len = strlen( text );
+   EnsureAlloced( len + 1 );
+   strcpy( m_data->data, text );
+   m_data->len = len;
+   }
+
+inline idStr::idStr
+   (
+   const unsigned num
+   ) : m_data ( NULL )
+
+   {
+   char text[ 32 ];
+   int len;
+
+   sprintf( text, "%u", num );
+   len = strlen( text );
+   EnsureAlloced( len + 1 );
+   strcpy( m_data->data, text );
+   m_data->len = len;
+   }
+
+inline int idStr::length( void ) const
+	{
+   return ( m_data != NULL ) ? m_data->len : 0;
+	}
+
+inline int idStr::allocated( void ) const
+	{
+   return ( m_data != NULL ) ? m_data->alloced + sizeof( *m_data ) : 0;
+	}
+
+inline const char *idStr::c_str( void ) const
+	{
+	assert( m_data );
+
+	return m_data->data;
+	}
+
+inline void idStr::append
+	(
+	const char *text
+	)
+
+	{
+   int len;
+
+	assert( text );
+
+	if ( text )
+		{
+		len = length() + strlen( text );
+		EnsureAlloced( len + 1 );
+
+      strcat( m_data->data, text );
+      m_data->len = len;
+		}
+	}
+
+inline void idStr::append
+	(
+	const idStr& text
+	)
+
+	{
+   int len;
+
+   len = length() + text.length();
+   EnsureAlloced ( len + 1 );
+
+   strcat ( m_data->data, text.c_str () );
+   m_data->len = len;
+	}
+
+inline char idStr::operator[]( int index ) const
+	{
+   assert ( m_data );
+   
+   if ( !m_data )
+      return 0;
+
+	// don't include the '/0' in the test, because technically, it's out of bounds
+	assert( ( index >= 0 ) && ( index < m_data->len ) );
+
+	// In release mode, give them a null character
+	// don't include the '/0' in the test, because technically, it's out of bounds
+	if ( ( index < 0 ) || ( index >= m_data->len ) )
+		{
+		return 0;
+		}
+
+	return m_data->data[ index ];
+	}
+
+inline char& idStr::operator[]
+	(
+	int index
+	)
+
+	{
+	// Used for result for invalid indices
+	static char dummy = 0;
+   assert ( m_data );
+
+   // We don't know if they'll write to it or not
+   // if it's not a const object
+   EnsureDataWritable ();
+
+   if ( !m_data )
+      return dummy;
+
+	// don't include the '/0' in the test, because technically, it's out of bounds
+	assert( ( index >= 0 ) && ( index < m_data->len ) );
+
+	// In release mode, let them change a safe variable
+	// don't include the '/0' in the test, because technically, it's out of bounds
+	if ( ( index < 0 ) || ( index >= m_data->len ) )
+		{
+		return dummy;
+		}
+
+	return m_data->data[ index ];
+	}
+
+inline void idStr::operator=
+	(
+	const idStr& text
+	)
+
+	{
+   // adding the reference before deleting our current reference prevents
+   // us from deleting our string if we are copying from ourself
+   text.m_data->AddRef();
+   m_data->DelRef();
+   m_data = text.m_data;
+   }
+
+inline void idStr::operator=
+	(
+	const char *text
+	)
+
+	{
+   int len;
+
+	assert( text );
+
+	if ( !text )
+		{
+		// safe behaviour if NULL
+		EnsureAlloced ( 1, false );
+      m_data->data[0] = 0;
+      m_data->len = 0;
+      return;
+		}
+
+   if ( !m_data )
+      {
+      len = strlen ( text );
+      EnsureAlloced( len + 1, false );
+      strcpy ( m_data->data, text );
+      m_data->len = len;
+      return;
+      }
+
+   if ( text == m_data->data )
+      return; // Copying same thing.  Punt.
+
+   // If we alias and I don't do this, I could corrupt other strings...  This 
+   // will get called with EnsureAlloced anyway
+   EnsureDataWritable ();
+
+   // Now we need to check if we're aliasing..
+   if ( text >= m_data->data && text <= m_data->data + m_data->len )
+      {
+      // Great, we're aliasing.  We're copying from inside ourselves.
+      // This means that I don't have to ensure that anything is alloced,
+      // though I'll assert just in case.
+      int diff = text - m_data->data;
+      int i;
+
+      assert ( strlen ( text ) < (unsigned) m_data->len );
+      
+      for ( i = 0; text[i]; i++ )
+         {
+         m_data->data[i] = text[i];
+         }
+
+      m_data->data[i] = 0;
+
+      m_data->len -= diff;
+
+      return;
+      }
+
+	len = strlen( text );
+   EnsureAlloced ( len + 1, false );
+	strcpy( m_data->data, text );
+   m_data->len = len;
+	}
+
+inline idStr operator+
+	(
+	const idStr& a,
+	const idStr& b
+	)
+
+	{
+	idStr result( a );
+
+	result.append( b );
+
+	return result;
+	}
+
+inline idStr operator+
+	(
+	const idStr& a,
+	const char *b
+	)
+
+	{
+	idStr result( a );
+
+	result.append( b );
+
+	return result;
+	}
+
+inline idStr operator+
+	(
+	const char *a,
+	const idStr& b
+	)
+
+	{
+	idStr result( a );
+
+	result.append( b );
+
+	return result;
+	}
+
+inline idStr operator+
+   (
+   const idStr& a,
+   const bool b
+   )
+
+   {
+	idStr result( a );
+
+   result.append( b ? "true" : "false" );
+
+	return result;
+   }
+
+inline idStr operator+
+	(
+   const idStr& a,
+	const char b
+	)
+
+	{
+   char text[ 2 ];
+
+   text[ 0 ] = b;
+   text[ 1 ] = 0;
+
+	return a + text;
+	}
+
+inline idStr& idStr::operator+=
+	(
+	const idStr& a
+	)
+
+	{
+	append( a );
+	return *this;
+	}
+
+inline idStr& idStr::operator+=
+	(
+	const char *a
+	)
+
+	{
+	append( a );
+	return *this;
+	}
+
+inline idStr& idStr::operator+=
+	(
+	const char a
+	)
+
+	{
+   char text[ 2 ];
+
+   text[ 0 ] = a;
+   text[ 1 ] = 0;
+	append( text );
+
+   return *this;
+	}
+
+inline idStr& idStr::operator+=
+	(
+	const bool a
+	)
+
+	{
+   append( a ? "true" : "false" );
+	return *this;
+	}
+
+inline bool operator==
+	(
+	const idStr& a,
+	const idStr& b
+	)
+
+	{
+	return ( !strcmp( a.c_str(), b.c_str() ) );
+	}
+
+inline bool operator==
+	(
+	const idStr& a,
+	const char *b
+	)
+
+	{
+	assert( b );
+	if ( !b )
+		{
+		return false;
+		}
+	return ( !strcmp( a.c_str(), b ) );
+	}
+
+inline bool operator==
+	(
+	const char *a,
+	const idStr& b
+	)
+
+	{
+	assert( a );
+	if ( !a )
+		{
+		return false;
+		}
+	return ( !strcmp( a, b.c_str() ) );
+	}
+
+inline bool operator!=
+	(
+	const idStr& a,
+	const idStr& b
+	)
+
+	{
+	return !( a == b );
+	}
+
+inline bool operator!=
+	(
+	const idStr& a,
+	const char *b
+	)
+
+	{
+	return !( a == b );
+	}
+
+inline bool operator!=
+	(
+	const char *a,
+	const idStr& b
+	)
+
+	{
+	return !( a == b );
+	}
+
+inline int idStr::icmpn
+   (
+   const char *text, 
+   int n
+   ) const
+
+   {
+	assert( m_data );
+	assert( text );
+
+   return idStr::icmpn( m_data->data, text, n );
+   }
+
+inline int idStr::icmpn
+   (
+   const idStr& text, 
+   int n
+   ) const
+
+   {
+	assert( m_data );
+	assert( text.m_data );
+
+   return idStr::icmpn( m_data->data, text.m_data->data, n );
+   }
+
+inline int idStr::icmp
+   (
+   const char *text
+   ) const
+
+   {
+	assert( m_data );
+	assert( text );
+
+   return idStr::icmp( m_data->data, text );
+   }
+
+inline int idStr::icmp
+   (
+   const idStr& text
+   ) const
+
+   {
+	assert( c_str () );
+	assert( text.c_str () );
+
+   return idStr::icmp( c_str () , text.c_str () );
+   }
+
+inline int idStr::cmp
+   (
+   const char *text
+   ) const
+
+   {
+	assert( m_data );
+	assert( text );
+
+   return idStr::cmp( m_data->data, text );
+   }
+
+inline int idStr::cmp
+   (
+   const idStr& text
+   ) const
+
+   {
+	assert( c_str () );
+	assert( text.c_str () );
+
+   return idStr::cmp( c_str () , text.c_str () );
+   }
+
+inline int idStr::cmpn
+   (
+   const char *text, 
+   int n
+   ) const
+
+   {
+	assert( c_str () );
+	assert( text );
+
+   return idStr::cmpn( c_str () , text, n );
+   }
+
+inline int idStr::cmpn
+   (
+   const idStr& text, 
+   int n
+   ) const
+
+   {
+	assert( c_str () );
+	assert( text.c_str ()  );
+
+   return idStr::cmpn( c_str () , text.c_str () , n );
+   }
+
+inline void idStr::tolower
+   (
+   void
+   )
+
+   {
+   assert( m_data );
+
+   EnsureDataWritable ();
+
+   idStr::tolower( m_data->data );
+   }
+
+inline void idStr::toupper
+   (
+   void
+   )
+
+   {
+   assert( m_data );
+
+   EnsureDataWritable ();
+
+   idStr::toupper( m_data->data );
+   }
+
+inline bool idStr::isNumeric
+   (
+   void
+   ) const
+
+   {
+   assert( m_data );
+   return idStr::isNumeric( m_data->data );
+   }
+
+inline idStr::operator const char *() {
+	return c_str();
+}
+
+inline idStr::operator const char *
+   (
+   void
+   ) const
+
+   {
+   return c_str ();
+   }
+
+#endif
diff --git a/libs/str.h b/libs/str.h
index 8bb56ea9..8cb8a716 100644
--- a/libs/str.h
+++ b/libs/str.h
@@ -1,479 +1,479 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef __STR__
-#define __STR__
-
-//
-// class Str
-// loose replacement for CString from MFC
-//
-
-#include <string.h>
-#include <ctype.h>
-#include <stdarg.h>
-
-#ifdef __APPLE__
-  #ifdef NULL
-    #undef NULL
-    #define NULL 0
-  #endif
-#endif
-
-
-#ifdef _WIN32
-#define strcasecmp strcmpi
-#endif
-
-// NOTE TTimo __StrDup was initially implemented in pakstuff.cpp
-//   causing a bunch of issues for broader targets that use Str.h (such as plugins and modules)
-//   Q_StrDup should be used now, using a #define __StrDup for easy transition
-
-#define __StrDup Q_StrDup
-
-inline char* Q_StrDup(char* pStr)
-{
-  if (pStr == NULL)
-    pStr = "";
-
-  return strcpy(new char[strlen(pStr)+1], pStr); 
-}
-
-inline char* Q_StrDup(const char* pStr)
-{ 
-  if (pStr == NULL)
-    pStr = "";
-
-  return strcpy(new char[strlen(pStr)+1], pStr); 
-}
-
-#if defined (__linux__) || defined (__APPLE__)
-#define strcmpi strcasecmp
-#define stricmp strcasecmp
-#define strnicmp strncasecmp
-
-inline char* strlwr(char* string)
-{
-  char *cp;
-  for (cp = string; *cp; ++cp)
-  {
-    if ('A' <= *cp && *cp <= 'Z')
-      *cp += 'a' - 'A';
-  }
-
-  return string;
-}
-
-inline char* strupr(char* string)
-{
-  char *cp;
-  for (cp = string; *cp; ++cp)
-  {
-    if ('a' <= *cp && *cp <= 'z')
-      *cp += 'A' - 'a';
-  }
-
-  return string;
-}
-#endif
-
-static char *g_pStrWork = NULL;
-
-class Str
-{
-protected:
-  bool m_bIgnoreCase;
-  char *m_pStr;
-
-public:
-  Str()
-  {
-    m_bIgnoreCase = true;
-    m_pStr = new char[1];
-    m_pStr[0] = '\0';
-  }
-
-  Str(char *p)
-  {
-    m_bIgnoreCase = true;
-    m_pStr = __StrDup(p);
-  }
-
-  Str(const char *p)
-  {
-    m_bIgnoreCase = true;
-    m_pStr = __StrDup(p);
-  }
-
-  Str(const unsigned char *p)
-  {
-    m_bIgnoreCase = true;
-    m_pStr = __StrDup((const char *)p);
-  }
-
-  Str(const char c)
-  {
-    m_bIgnoreCase = true;
-    m_pStr = new char[2];
-    m_pStr[0] = c;
-    m_pStr[1] = '\0';    
-  }
-
-  const char* GetBuffer() const
-  {
-    return m_pStr;
-  }
-
-  Str(const Str &s)
-  {
-    m_bIgnoreCase = true;
-    m_pStr = __StrDup(s.GetBuffer());
-  }
-
-  void Deallocate()
-  {
-    delete []m_pStr;
-    m_pStr = NULL;
-  }
-
-  void Allocate(int n)
-  {
-    Deallocate();
-    m_pStr = new char[n];
-  }
-
-  void MakeEmpty()
-  {
-    Deallocate();
-    m_pStr = __StrDup("");
-  }
-
-  virtual ~Str()
-  {
-    Deallocate();
-    // NOTE TTimo: someone explain this g_pStrWork to me?
-    if (g_pStrWork)
-      delete []g_pStrWork;
-    g_pStrWork = NULL;
-  }
-
-  void MakeLower()
-  {
-    if (m_pStr)
-    {
-      strlwr(m_pStr);
-    }
-  }
-
-  void MakeUpper()
-  {
-    if (m_pStr)
-    {
-      strupr(m_pStr);
-    }
-  }
-
-  void TrimRight()
-    {
-      char* lpsz = m_pStr;
-      char* lpszLast = NULL;
-      while (*lpsz != '\0')
-      {
-	if (isspace(*lpsz))
-	{
-	  if (lpszLast == NULL)
-	    lpszLast = lpsz;
-	}
-	else
-	  lpszLast = NULL;
-	lpsz++;
-      }
- 
-      if (lpszLast != NULL)
-      {
-	// truncate at trailing space start
-	*lpszLast = '\0';
-      }
-    }
-
-  void TrimLeft()
-    {
-      // find first non-space character
-      char* lpsz = m_pStr;
-      while (isspace(*lpsz))
-	lpsz++;
- 
-      // fix up data and length
-      int nDataLength = GetLength() - (lpsz - m_pStr);
-      memmove(m_pStr, lpsz, (nDataLength+1));
-    }
-
-  int Find(const char *p)
-  {
-    char *pf = strstr(m_pStr, p);
-    return (pf) ? (pf - m_pStr) : -1;
-  }
-
-  // search starting at a given offset
-  int Find(const char *p, int offset)
-  {
-    char *pf = strstr(m_pStr+offset, p);
-    return (pf) ? (pf - m_pStr) : -1;
-  }
-
-  int Find(const char ch)
-  {
-    char *pf = strchr (m_pStr, ch);
-    return (pf) ? (pf - m_pStr) : -1;
-  }
-
-  int ReverseFind(const char ch)
-  {
-    char *pf = strrchr(m_pStr, ch);
-    return (pf) ? (pf - m_pStr) : -1;
-  }
-
-  int Compare (const char* str) const
-  {
-    return strcmp (m_pStr, str);
-  }
-  
-  int CompareNoCase (const char* str) const
-  {
-    return strcasecmp (m_pStr, str);
-  }
-
-  int GetLength()
-  {
-    return (m_pStr) ? strlen(m_pStr) : 0;
-  }
-
-  const char* Left(int n)
-  {
-    delete []g_pStrWork;
-    if (n > 0)
-    {
-      g_pStrWork = new char[n+1];
-      strncpy(g_pStrWork, m_pStr, n);
-      g_pStrWork[n] = '\0';
-    }
-    else
-    {
-      g_pStrWork = "";
-      g_pStrWork = new char[1];
-      g_pStrWork[0] = '\0';
-    }
-    return g_pStrWork;
-  }
-
-  const char* Right(int n)
-  {
-    delete []g_pStrWork;
-    if (n > 0)
-    {
-      g_pStrWork = new char[n+1];
-      int nStart = GetLength() - n;
-      strncpy(g_pStrWork, &m_pStr[nStart], n);
-      g_pStrWork[n] = '\0';
-    }
-    else
-    {
-      g_pStrWork = new char[1];
-      g_pStrWork[0] = '\0';
-    }
-    return g_pStrWork;
-  }
-
-  const char* Mid(int nFirst) const
-    {
-      return Mid(nFirst, strlen (m_pStr) - nFirst);
-    }
-
-  const char* Mid(int first, int n) const
-  {
-    delete []g_pStrWork;
-    if (n > 0)
-    {
-      g_pStrWork = new char[n+1];
-      strncpy(g_pStrWork, m_pStr+first, n);
-      g_pStrWork[n] = '\0';
-    }
-    else
-    {
-      g_pStrWork = "";
-      g_pStrWork = new char[1];
-      g_pStrWork[0] = '\0';
-    }
-    return g_pStrWork;
-  }
-
-#ifdef __G_LIB_H__
-  void Format(const char* fmt, ...)
-  {
-    va_list args;
-    char *buffer;
-  
-    va_start (args, fmt);
-    buffer = g_strdup_vprintf (fmt, args);
-    va_end (args);
-
-    delete[] m_pStr;
-    m_pStr = __StrDup(buffer);
-    g_free (buffer);
-  }
-#else
-  void Format(const char* fmt, ...)
-  {
-    va_list args;
-    m_pStr = new char[1024];
-
-    va_start (args, fmt);
-    vsprintf (m_pStr, fmt, args);
-    va_end (args);
-  }
-#endif
-
-  void SetAt(int n, char ch)
-  {
-    if (n >= 0 && n < GetLength ())
-      m_pStr[n] = ch;
-  }
-
-	// NOTE: unlike CString, this looses the pointer
-  void ReleaseBuffer(int n = -1)
-  {
-    if (n == -1)
-      n = GetLength ();
-
-    char* tmp = m_pStr;
-    tmp[n] = '\0';
-    m_pStr = __StrDup(tmp);
-    delete []tmp;
-  }
-
-  char* GetBufferSetLength(int n)
-  {
-    if (n < 0)
-      n = 0;
-
-    char *p = new char[n+1];
-    strncpy (p, m_pStr, n);
-		p[n] = '\0';
-    delete []m_pStr;
-    m_pStr = p;
-    return m_pStr;
-  }
-
-  //  char& operator *() { return *m_pStr; }
-  //  char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }
-  operator void*() { return m_pStr; }
-  operator char*() { return m_pStr; }
-  operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }
-  operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }
-  operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }
-  Str& operator =(const Str& rhs)
-  {
-    if (&rhs != this)
-    {
-      delete[] m_pStr;
-      m_pStr = __StrDup(rhs.m_pStr);
-    }
-    return *this;
-  }
-  
-  Str& operator =(const char* pStr)
-  {
-    if (m_pStr != pStr)
-    {
-      delete[] m_pStr;
-      m_pStr = __StrDup(pStr);
-    }
-    return *this;
-  }
-
-  Str& operator +=(const char ch)
-  {
-    int len = GetLength ();
-    char *p = new char[len + 1 + 1];
-
-    if (m_pStr)
-    {
-      strcpy(p, m_pStr);
-      delete[] m_pStr;
-    }
-
-    m_pStr = p;
-    m_pStr[len] = ch;
-    m_pStr[len+1] = '\0';
-
-    return *this;
-  }
-
-  Str& operator +=(const char *pStr)
-  {
-    if (pStr)
-    {
-      if (m_pStr)
-      {
-        char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];
-        strcpy(p, m_pStr);
-        strcat(p, pStr);
-        delete[] m_pStr;
-        m_pStr = p;
-      }
-      else
-      {
-        m_pStr = __StrDup(pStr);
-      }
-    }
-    return *this;
-  }
-  
-
-  bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }
-  bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
-  bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
-  bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }
-  bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
-  bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
-  bool operator <(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) < 0 : strcmp(m_pStr, rhs.m_pStr) < 0; }
-  bool operator <(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
-  bool operator <(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
-  bool operator >(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) > 0 : strcmp(m_pStr, rhs.m_pStr) > 0; }
-  bool operator >(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
-  bool operator >(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
-  char& operator [](int nIndex) { return m_pStr[nIndex]; }
-  char& operator [](int nIndex) const { return m_pStr[nIndex]; }
-  const char GetAt (int nIndex) { return m_pStr[nIndex]; }
-};
-
-
-
-#endif
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef __STR__
+#define __STR__
+
+//
+// class Str
+// loose replacement for CString from MFC
+//
+
+#include <string.h>
+#include <ctype.h>
+#include <stdarg.h>
+
+#ifdef __APPLE__
+  #ifdef NULL
+    #undef NULL
+    #define NULL 0
+  #endif
+#endif
+
+
+#ifdef _WIN32
+#define strcasecmp strcmpi
+#endif
+
+// NOTE TTimo __StrDup was initially implemented in pakstuff.cpp
+//   causing a bunch of issues for broader targets that use Str.h (such as plugins and modules)
+//   Q_StrDup should be used now, using a #define __StrDup for easy transition
+
+#define __StrDup Q_StrDup
+
+inline char* Q_StrDup(char* pStr)
+{
+  if (pStr == NULL)
+    pStr = "";
+
+  return strcpy(new char[strlen(pStr)+1], pStr); 
+}
+
+inline char* Q_StrDup(const char* pStr)
+{ 
+  if (pStr == NULL)
+    pStr = "";
+
+  return strcpy(new char[strlen(pStr)+1], pStr); 
+}
+
+#if defined (__linux__) || defined (__APPLE__)
+#define strcmpi strcasecmp
+#define stricmp strcasecmp
+#define strnicmp strncasecmp
+
+inline char* strlwr(char* string)
+{
+  char *cp;
+  for (cp = string; *cp; ++cp)
+  {
+    if ('A' <= *cp && *cp <= 'Z')
+      *cp += 'a' - 'A';
+  }
+
+  return string;
+}
+
+inline char* strupr(char* string)
+{
+  char *cp;
+  for (cp = string; *cp; ++cp)
+  {
+    if ('a' <= *cp && *cp <= 'z')
+      *cp += 'A' - 'a';
+  }
+
+  return string;
+}
+#endif
+
+static char *g_pStrWork = NULL;
+
+class Str
+{
+protected:
+  bool m_bIgnoreCase;
+  char *m_pStr;
+
+public:
+  Str()
+  {
+    m_bIgnoreCase = true;
+    m_pStr = new char[1];
+    m_pStr[0] = '\0';
+  }
+
+  Str(char *p)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup(p);
+  }
+
+  Str(const char *p)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup(p);
+  }
+
+  Str(const unsigned char *p)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup((const char *)p);
+  }
+
+  Str(const char c)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = new char[2];
+    m_pStr[0] = c;
+    m_pStr[1] = '\0';    
+  }
+
+  const char* GetBuffer() const
+  {
+    return m_pStr;
+  }
+
+  Str(const Str &s)
+  {
+    m_bIgnoreCase = true;
+    m_pStr = __StrDup(s.GetBuffer());
+  }
+
+  void Deallocate()
+  {
+    delete []m_pStr;
+    m_pStr = NULL;
+  }
+
+  void Allocate(int n)
+  {
+    Deallocate();
+    m_pStr = new char[n];
+  }
+
+  void MakeEmpty()
+  {
+    Deallocate();
+    m_pStr = __StrDup("");
+  }
+
+  virtual ~Str()
+  {
+    Deallocate();
+    // NOTE TTimo: someone explain this g_pStrWork to me?
+    if (g_pStrWork)
+      delete []g_pStrWork;
+    g_pStrWork = NULL;
+  }
+
+  void MakeLower()
+  {
+    if (m_pStr)
+    {
+      strlwr(m_pStr);
+    }
+  }
+
+  void MakeUpper()
+  {
+    if (m_pStr)
+    {
+      strupr(m_pStr);
+    }
+  }
+
+  void TrimRight()
+    {
+      char* lpsz = m_pStr;
+      char* lpszLast = NULL;
+      while (*lpsz != '\0')
+      {
+	if (isspace(*lpsz))
+	{
+	  if (lpszLast == NULL)
+	    lpszLast = lpsz;
+	}
+	else
+	  lpszLast = NULL;
+	lpsz++;
+      }
+ 
+      if (lpszLast != NULL)
+      {
+	// truncate at trailing space start
+	*lpszLast = '\0';
+      }
+    }
+
+  void TrimLeft()
+    {
+      // find first non-space character
+      char* lpsz = m_pStr;
+      while (isspace(*lpsz))
+	lpsz++;
+ 
+      // fix up data and length
+      int nDataLength = GetLength() - (lpsz - m_pStr);
+      memmove(m_pStr, lpsz, (nDataLength+1));
+    }
+
+  int Find(const char *p)
+  {
+    char *pf = strstr(m_pStr, p);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  // search starting at a given offset
+  int Find(const char *p, int offset)
+  {
+    char *pf = strstr(m_pStr+offset, p);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  int Find(const char ch)
+  {
+    char *pf = strchr (m_pStr, ch);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  int ReverseFind(const char ch)
+  {
+    char *pf = strrchr(m_pStr, ch);
+    return (pf) ? (pf - m_pStr) : -1;
+  }
+
+  int Compare (const char* str) const
+  {
+    return strcmp (m_pStr, str);
+  }
+  
+  int CompareNoCase (const char* str) const
+  {
+    return strcasecmp (m_pStr, str);
+  }
+
+  int GetLength()
+  {
+    return (m_pStr) ? strlen(m_pStr) : 0;
+  }
+
+  const char* Left(int n)
+  {
+    delete []g_pStrWork;
+    if (n > 0)
+    {
+      g_pStrWork = new char[n+1];
+      strncpy(g_pStrWork, m_pStr, n);
+      g_pStrWork[n] = '\0';
+    }
+    else
+    {
+      g_pStrWork = "";
+      g_pStrWork = new char[1];
+      g_pStrWork[0] = '\0';
+    }
+    return g_pStrWork;
+  }
+
+  const char* Right(int n)
+  {
+    delete []g_pStrWork;
+    if (n > 0)
+    {
+      g_pStrWork = new char[n+1];
+      int nStart = GetLength() - n;
+      strncpy(g_pStrWork, &m_pStr[nStart], n);
+      g_pStrWork[n] = '\0';
+    }
+    else
+    {
+      g_pStrWork = new char[1];
+      g_pStrWork[0] = '\0';
+    }
+    return g_pStrWork;
+  }
+
+  const char* Mid(int nFirst) const
+    {
+      return Mid(nFirst, strlen (m_pStr) - nFirst);
+    }
+
+  const char* Mid(int first, int n) const
+  {
+    delete []g_pStrWork;
+    if (n > 0)
+    {
+      g_pStrWork = new char[n+1];
+      strncpy(g_pStrWork, m_pStr+first, n);
+      g_pStrWork[n] = '\0';
+    }
+    else
+    {
+      g_pStrWork = "";
+      g_pStrWork = new char[1];
+      g_pStrWork[0] = '\0';
+    }
+    return g_pStrWork;
+  }
+
+#ifdef __G_LIB_H__
+  void Format(const char* fmt, ...)
+  {
+    va_list args;
+    char *buffer;
+  
+    va_start (args, fmt);
+    buffer = g_strdup_vprintf (fmt, args);
+    va_end (args);
+
+    delete[] m_pStr;
+    m_pStr = __StrDup(buffer);
+    g_free (buffer);
+  }
+#else
+  void Format(const char* fmt, ...)
+  {
+    va_list args;
+    m_pStr = new char[1024];
+
+    va_start (args, fmt);
+    vsprintf (m_pStr, fmt, args);
+    va_end (args);
+  }
+#endif
+
+  void SetAt(int n, char ch)
+  {
+    if (n >= 0 && n < GetLength ())
+      m_pStr[n] = ch;
+  }
+
+	// NOTE: unlike CString, this looses the pointer
+  void ReleaseBuffer(int n = -1)
+  {
+    if (n == -1)
+      n = GetLength ();
+
+    char* tmp = m_pStr;
+    tmp[n] = '\0';
+    m_pStr = __StrDup(tmp);
+    delete []tmp;
+  }
+
+  char* GetBufferSetLength(int n)
+  {
+    if (n < 0)
+      n = 0;
+
+    char *p = new char[n+1];
+    strncpy (p, m_pStr, n);
+		p[n] = '\0';
+    delete []m_pStr;
+    m_pStr = p;
+    return m_pStr;
+  }
+
+  //  char& operator *() { return *m_pStr; }
+  //  char& operator *() const { return *const_cast<Str*>(this)->m_pStr; }
+  operator void*() { return m_pStr; }
+  operator char*() { return m_pStr; }
+  operator const char*(){ return reinterpret_cast<const char*>(m_pStr); }
+  operator unsigned char*() { return reinterpret_cast<unsigned char*>(m_pStr); }
+  operator const unsigned char*() { return reinterpret_cast<const unsigned char*>(m_pStr); }
+  Str& operator =(const Str& rhs)
+  {
+    if (&rhs != this)
+    {
+      delete[] m_pStr;
+      m_pStr = __StrDup(rhs.m_pStr);
+    }
+    return *this;
+  }
+  
+  Str& operator =(const char* pStr)
+  {
+    if (m_pStr != pStr)
+    {
+      delete[] m_pStr;
+      m_pStr = __StrDup(pStr);
+    }
+    return *this;
+  }
+
+  Str& operator +=(const char ch)
+  {
+    int len = GetLength ();
+    char *p = new char[len + 1 + 1];
+
+    if (m_pStr)
+    {
+      strcpy(p, m_pStr);
+      delete[] m_pStr;
+    }
+
+    m_pStr = p;
+    m_pStr[len] = ch;
+    m_pStr[len+1] = '\0';
+
+    return *this;
+  }
+
+  Str& operator +=(const char *pStr)
+  {
+    if (pStr)
+    {
+      if (m_pStr)
+      {
+        char *p = new char[strlen(m_pStr) + strlen(pStr) + 1];
+        strcpy(p, m_pStr);
+        strcat(p, pStr);
+        delete[] m_pStr;
+        m_pStr = p;
+      }
+      else
+      {
+        m_pStr = __StrDup(pStr);
+      }
+    }
+    return *this;
+  }
+  
+
+  bool operator ==(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) == 0 : strcmp(m_pStr, rhs.m_pStr) == 0; }
+  bool operator ==(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
+  bool operator ==(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) == 0 : strcmp(m_pStr, pStr) == 0; }
+  bool operator !=(Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) != 0 : strcmp(m_pStr, rhs.m_pStr) != 0; }
+  bool operator !=(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
+  bool operator !=(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) != 0 : strcmp(m_pStr, pStr) != 0; }
+  bool operator <(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) < 0 : strcmp(m_pStr, rhs.m_pStr) < 0; }
+  bool operator <(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
+  bool operator <(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) < 0 : strcmp(m_pStr, pStr) < 0; }
+  bool operator >(const Str& rhs) const { return (m_bIgnoreCase) ? stricmp(m_pStr, rhs.m_pStr) > 0 : strcmp(m_pStr, rhs.m_pStr) > 0; }
+  bool operator >(char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
+  bool operator >(const char* pStr) const { return (m_bIgnoreCase) ? stricmp(m_pStr, pStr) > 0 : strcmp(m_pStr, pStr) > 0; }
+  char& operator [](int nIndex) { return m_pStr[nIndex]; }
+  char& operator [](int nIndex) const { return m_pStr[nIndex]; }
+  const char GetAt (int nIndex) { return m_pStr[nIndex]; }
+};
+
+
+
+#endif
diff --git a/libs/synapse.h b/libs/synapse.h
index b01688fc..0478eb95 100644
--- a/libs/synapse.h
+++ b/libs/synapse.h
@@ -1,661 +1,661 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __SYNAPSE_H__
-#define __SYNAPSE_H__
-
-/*!
-synapse library
-code and utilities to deal with dynamic components programming
-
-"the point at which a nervous impulse passes from one neuron to another"
-
-dependencies:
-  libxml for parsing
-  STL for some algorithms and data structures
-  glib for Str.h (Str class)
-  
-this is a utility library, it provides typical synapse client and server
-could be split into two independant libraries actually, the server part and the client part
-(that's just a matter of reducing binary size)  
-*/
-
-// compile time settings
-#ifdef _DEBUG
-  #define SYNAPSE_VERBOSE // be verbosive about the loading process
-#endif
-
-// ydnar: required for os x
-#if defined (__APPLE__)
-  #include <sys/types.h>
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-  #include <dlfcn.h>
-  #include <dirent.h>  
-#endif
-
-#if defined(_WIN32)
-  #include <windows.h>
-#endif
-
-#if defined(_WIN32)
-  #define SYNAPSE_DLL_EXPORT WINAPI
-#elif defined(__linux__) || defined(__APPLE__)	/* ydnar */
-//  #define SYNAPSE_DLL_EXPORT __attribute__ ((visibility ("protected")))
-  #define SYNAPSE_DLL_EXPORT
-#else
-  #error unknown architecture
-#endif
-
-// NOTE TTimo: VC6 crap, gets confused when some variable names in function declarations
-//   are 'allocator' or 'list'
-//   if you #include glib *after* STL, you get those errors .. better be safe then
-#include <glib.h>
-
-#include "libxml/parser.h"
-
-#include "irefcount.h"
-#include "gtkr_list.h"
-#include "gtkr_vector.h"
-
-#include "str.h"
-
-/*!
-use when API change make things incompatible at synapse level
-i.e. entry point and classes API changes
-*/
-#define SYNAPSE_VERSION "3"
-
-/*!
-=======================================================================
-diagnostic printing facility
-independently from any API negociation stuff,
-we need a diagnostic facility that's available at all times
-=======================================================================
-*/
-extern "C"
-{
-/*!
-prototype to provide to synapse to redirect the output appropriately  
-*/  
-typedef void (* PFN_SYN_PRINTF_VA) (const char *text, va_list args);
-void Set_Syn_Printf(PFN_SYN_PRINTF_VA pf); ///< change the handler, set back to NULL for default
-/*!
-use this for synapse code diagnostics, it will be piped through the handler if necessary
-*/
-void Syn_Printf (const char *text, ...);
-};
-  
-/*
-=======================================================================
-client
-=======================================================================
-*/
-
-/*!
-description of an API:
-a module requires and provides several APIs
-the basic rule is that we will avoid asking an API from a module if the APIs it requires are not filled in yet
-the exception being the 'resolve' operation of a given client, which we 'activate'
-(that is we make the interfaces it provides available, leave the ones it requires unsolved, and try to get back to a stable situation)
-*/
-
-typedef enum { SYN_UNKNOWN = 0, SYN_PROVIDE, SYN_REQUIRE, SYN_REQUIRE_ANY } EAPIType;
-
-#define MAX_APINAME 128
-typedef struct APIDescriptor_s
-{
-  /*!
-  major version, this must be UNIQUE for each API
-  NOTE: we used to rely on GUID for this, that was a good solution to make sure we never get conflicts
-  but it was a bit overkill, so we dropped and use a string now
-  */
-  char major_name[MAX_APINAME];
-  /*!
-  what kind of interface
-  for instance for "image" API, "tga" "jpg" etc.
-  */
-  char minor_name[MAX_APINAME];
-  EAPIType mType; ///< is this an API we provide or an API we require
-  /*!
-  pointer to the table to be filled in
-  this is valid for SYN_REQUIRE APIs only
-  */
-  void *mpTable;
-  bool mbTableInitDone; ///< turned to true by the server after the function table has been filled in
-  /*!
-  gives the size of the expected function table  
-  */
-  int mSize;
-  /*!
-  refcounts how many times this API is being used through the app
-  this is valid for SYN_PROVIDE APIs only
-  */
-  int mRefCount;
-} APIDescriptor_t;
-
-typedef struct XMLConfigEntry_s {
-  const char *api;
-  EAPIType type;
-  int size;
-  void *pTable;
-} XMLConfigEntry_t;
-
-/*!
-\class CSynapseAPIManager
-derive from this class if you want to manage several APIs through the same object
-(typically, loading plugins, or an unknown number of APIs that match some criterions)
-this class has some pure virtual members that need to be implemented by the childs
-
-we deal with two types of API managers:
-- the 'loose' ones have a matching pattern and load everything that matches criterions
-  typically used for plugins
-- the 'list' ones have a fixed list of things they require. They are used to provide
-  easy access to multiple interfaces
-
-those two types of managers are not stored in the same structs, and not handled the
-same way. For instance the 'list' manager will require ALL it's APIs to be loaded, or
-the init will fail. They also play a role in the client activation.
-
-apart from the multiple API management facility, the main difference with static tables
-and individual calls to CSynapseClient::AddAPI is the fact that the APIDescriptor_t are
-allocated on demand
-*/
-
-/* we do some matching, or store minors list, the strings need to be bigger */
-#define MAX_PATTERN_STRING 512
-
-/*! \enum EAPIManagerType
-  \brief type of this manager, loosely matching with "*", or a fixed list of required interfaces
-*/
-typedef enum { API_MATCH = 0,  API_LIST } EAPIManagerType;
-
-class CSynapseAPIManager : public IRefCounted
-{
-  EAPIManagerType mType;
-  
-  // the list of APIs we have obtained (SYN_REQUIRE_ANY)
-  vector< APIDescriptor_t * > mAPIs;
-  /*!
-  pattern for matching the major version
-  NOTE: only supported for now: exact match
-  */
-  char major_pattern[MAX_PATTERN_STRING];
-  /*!
-  pattern for matching the minor
-  */
-  char minor_pattern[MAX_PATTERN_STRING];  
-  
-public:
-  CSynapseAPIManager() { mType = API_MATCH; }
-  virtual ~CSynapseAPIManager();
-
-  EAPIManagerType GetType() { return mType; }
-  void SetType(EAPIManagerType type) { mType = type; }
-  
-  /*!
-  set the API matching pattern
-  supported syntax:
-  any minor for a given major, for instance: PLUGIN_MAJOR, "*"
-  a space seperated list of minors for a given major: IMAGE_MAJOR, "tga jpg"
-  */
-  void SetMatchAPI(const char *major, const char *minor);
-  
-  /*!
-  utility function
-  start building a SYN_REQUIRE_ANY descriptor from a SYN_PROVIDE interface that we found matching
-  */
-  static APIDescriptor_t* PrepareRequireAPI(APIDescriptor_t *pAPI);  
-  
-  /*!
-  for managers that require a fixed list of things, we are not active until everything has been loaded up
-  managers that work on a loose pattern like "*" are always active (since they don't know what they want for sure)
-  */
-  bool CheckSetActive();
-  
-  /*!
-  the manager answers wether it wants to load this or not
-  we provide a default implementation, but this can be completely overriden if needed
-  see SetMatchAPI for the documentation of the default implementation
-  NOTE: this should only be called on API_MATCH type of managers
-  */
-  virtual bool MatchAPI(const char *major, const char *minor);
-  
-  /*!
-  build an APIDescriptor_t configured as SYN_REQUIRE_ANY from the SYN_PROVIDE API we found
-  used when we scan the available interfaces for a match that would be interesting to this manager
-  NOTE: only for API_MATCH managers
-  */
-  virtual APIDescriptor_t *BuildRequireAPI(APIDescriptor_t *pAPI) { return NULL; }
-  
-  /*!
-  below is relevant to API_LIST only ---------------------------------------------------------------------
-  */
-
-  /*!
-  fill in the table info to this descriptor, store it as a new slot
-  NOTE: only for API_LIST
-  */
-  virtual void FillAPITable(APIDescriptor_t *pAPI) { }
-  
-  /*!
-  initialize the list of APIDescriptor_t* with all the stuff we expect
-  */
-  void InitializeAPIList();
-  
-  /*!
-  access the API descriptors
-  */
-  int GetAPICount();
-  APIDescriptor_t *GetAPI(int);
-};
-
-/*!
-\class CSynapseClient
-*/
-class CSynapseServer; // forward declare
-class CSynapseClient : public IRefCounted
-{
-  /*!
-  this flag indicates wether this client is active
-  i.e. wether you can ask it for interfaces
-  this is either a client for which all required interfaces have been filled in
-  or a client we are trying to resolve (i.e. load with all it's stuff)
-  */
-  bool mbActive;
-  
-  /*!
-  we store APIDescriptor_t*, the module fills that in at startup
-  */
-  vector<APIDescriptor_t *> mAPIDescriptors;
-  
-  /*!
-  managers for multiple APIs management
-  mManagersMatch are managers with loose matching / undefined number of APIs
-  mManagersList are managers with a fixed list of required interfaces
-  */
-  vector<CSynapseAPIManager *> mManagersMatch;
-  vector<CSynapseAPIManager *> mManagersList;
-  
-protected:
-  friend class CSynapseServer;
-  /*!
-  use of this is restricted to the server, expecting it knows what it is doing
-  will make the client we are trying to resolve able to provide interfaces even though all interfaces it requires have not been filled in yet.
-  */
-  void ForceSetActive() { mbActive = true; }
-  
-public:
-  CSynapseClient();
-  virtual ~CSynapseClient();
-
-  int GetAPICount(); ///< returns the number of APIs that this module provides
-  APIDescriptor_t* GetAPIDescriptor(int); ///< retrieve specific information about on of the APIs
-
-  /*!
-  Add the API to the CSynapseClient information
-  
-  \param minor
-  minor can be NULL, some APIs don't need to have a 'minor' description  
-  
-  \param type
-  SYN_PROVIDE: means this is an API we provide if anyone needs it
-  SYN_REQUIRE: means this is an API we will require for operation
-  SYN_REQUIRE_ANY: means this is an API we want to load *any* minor found
-     (for instance a list of image fornats, or the plugins)
-     
-  \param pTable 
-  the function table
-  only valid for SYN_REQUIRE APIs
-  
-  \param size
-  the size of the function table
-  if SYN_REQUIRE, you should set the size in pTable and AddAPI will work it out
-  if SYN_PROVIDE, you need to provide this parameter
-  
-  returns a bool:
-  operation may fail, since we have a few safe checks  
-  */
-  bool AddAPI(const char *major, const char *minor = NULL, int size = 0, EAPIType type = SYN_PROVIDE, void *pTable = NULL);
-  
-  /*!
-  Add an API manager to the client
-  this class is designed to handle multiple APIs
-  is not memory managed by CSynapseClient (should it? or ref counted maybe?)
-  writing it with support for multiple managers, that may be a bit overkill right now
-  */
-  void AddManager(CSynapseAPIManager *pManager);
-  
-  int GetManagerMatchCount(); ///< how many API managers
-  CSynapseAPIManager* GetManagerMatch(int); ///< get corresponding API manager
-
-  int GetManagerListCount(); ///< how many API managers
-  CSynapseAPIManager* GetManagerList(int); ///< get corresponding API manager
-  
-  /*!
-  each client has to implement this function itself
-  it will fill in the function table
-  and increment the ref counting in it's own SYN_PROVIDE descriptor
-  returns a bool, false if you ask for an API that's not available
-  */
-  virtual bool RequestAPI(APIDescriptor_t *pAPI) = 0;
-  
-  /*!
-  return the build date, can be overriden by client module
-  */
-  virtual const char* GetInfo();
-  
-  /*!
-  \brief a shirt name to identify the client
-  we use this string to identify individual clients, for instance when some XML configuration nodes are required
-  should be unique, the synapse server should't accept multiple occurences?  
-  */
-  virtual const char* GetName() { return ""; }
-  
-  bool IsActive() { return mbActive; }
-  /*!
-  check wether all interfaces have been filled in
-  in which case we will switch to 'activated' state, that is this client can provide interfaces to others now
-  */
-  bool CheckSetActive();
-  
-  /*!
-  \brief called when the client is being shutdown, before the dlclose happens
-  this is the last call before the dlclose, there's no turning back
-  just do what you have to do before you die.. decref and stuff
-  */
-  void Shutdown();
-  
-  /*!
-  override this one in clients that need to proceed through some init steps when activated
-  if returning false, the init will abort
-  */
-  virtual bool OnActivate() { return true; }
-  
-  /*!
-  \brief walk the XML config and initialize from structures
-  when you use this function, OnActivate will also make sure all the interfaces listed were properly initialized
-  two tables, one for the regular single interface, one for the listings
-  need to store for later and check in OnActivate
-  
-  \param pServer, pass the server to talk to
-  NOTE: might want to store it in the class if that's needed too often
-  
-  \param client_name, the name of the client node to look for. If NULL, use GetName()
-  
-  \return wether all APIs given were successfully found in the config
-  */
-  bool ConfigXML( CSynapseServer *pServer, const char *client_name, const XMLConfigEntry_t entries[] );
-};
-
-/*!
-prototype for the only exported function needed in a synapse client
-*/
-#define NAME_SYNAPSE_ENUMERATEINTERFACES "Synapse_EnumerateInterfaces"
-
-class CSynapseServer; // forward declare
-typedef CSynapseClient* (SYNAPSE_DLL_EXPORT *PFN_SYNAPSE_ENUMERATEINTERFACES)(const char *version, CSynapseServer *server);
-
-/*!
-a derived version of CSynapseClient that can be used to provide builtin module without having to go through DLLs
-this is useful for things we want to isolate behind an abstract API, but that we feel better about having present at all times (such as .def class loader)
-*/
-class CSynapseBuiltinClient : public CSynapseClient
-{
-  public:
-  CSynapseBuiltinClient() {}
-  virtual ~CSynapseBuiltinClient() {}
-  
-  virtual void EnumerateInterfaces(CSynapseServer *server) = 0;
-  
-};
-
-/*
-=======================================================================
-server
-=======================================================================
-*/
-
-/*!
-  \enum EClientType
-  \brief we can have clients that are builtin to a server
-*/
-typedef enum { SYN_SO, SYN_BUILTIN } EClientType;
-
-/*!
-server side slot for a synapse client
-is OS dependant, except for the ISynapseClient part
-*/
-class CSynapseClientSlot
-{
-public:
-  /*!
-  \todo cleanup, make that private with accessors
-  */
-#if defined(__linux__) || defined(__APPLE__)
-  void *mpDLL; ///< handle to the shared object (invalid if SYN_BUILTIN)
-#elif defined(_WIN32)
-  HMODULE mpDLL; ///< handle to the shared object (invalid if SYN_BUILTIN)
-#endif
-  PFN_SYNAPSE_ENUMERATEINTERFACES mpEnumerate; ///< function pointer to the enumeration entry point (invalid if SYN_BUILTIN)
-
-  CSynapseClient *mpClient; ///< the full client API
-  Str mFileName; ///< path to the file
-  
-  EClientType mType;
-
-  /*!
-  \brief release the shared object. NOTE: OS dependent  
-  */
-  void ReleaseSO();
-  
-  CSynapseClientSlot() { mpDLL = NULL; mpEnumerate = NULL; mpClient = NULL; mType = SYN_SO; }
-  /*!
-  NOTE: the slot is stored as static object, and copy constructors used  
-  */
-  virtual ~CSynapseClientSlot() { }
-
-};
-
-/*!
-\class CSynapseServer
-dynamic modules manager class
-this class provides the server functionality:
-initialize, get a list of modules, load them, link them together..
-*/
-class CSynapseServer : public IRefCounted
-{
-  list<char *> mSearchPaths;
-  list<CSynapseClientSlot> mClients;
-	  
-  /*!
-  used for resolve operations
-  */
-  list<APIDescriptor_t*> mStack;
-  /*!
-  set this when mStack is modified with new stuff to resolve
-  NOTE: if this hack becomes too tricky to use we could just encapsulate mStack
-  */
-  bool mbStackChanged;
-  
-  xmlDocPtr mpDoc;
-  xmlNodePtr mpFocusedNode; ///< currently focused node while we are scanning the config (strictly for GetNextConfig usage)
-  xmlNodePtr mpCurrentClientConfig;
-  /*!
-  stores the allocated strings for each call to GetNextConfig
-  need to be freed if != NULL
-  */
-  xmlChar *m_api_name;
-  gchar *m_content;
-    
-  /*!
-  push required interfaces for this client into the stack of things to be resolved
-  it is possible that several mathing interfaces be in the stack at the same time
-  (for instance several modules that want to get the VFS)
-  but we should never have the same APIDescriptor_t twice
-  NOTE: as this function is called repeatedly during the resolve (because the list of required things is refining),
-    we often have to drop APIDescriptor_t requests that are already there.
-  NOTE CSynapseAPIManager: if there are CSynapseAPIManager objects in the CSynapseClient,
-    we will scan and push all the matching APIs too
-  */
-  void PushRequired(CSynapseClient *pClient);
-  
-  /*!
-  work on resolving this particular APIDescriptor_t
-  returns true if we were able to resolve the interface
-  returns false otherwise
-  if the API was found, but not requested because of more required APIs, we push them in mStack
-  */
-  bool ResolveAPI(APIDescriptor_t* pAPI);
-  
-  /*!
-  push an APIDescriptor_t* into the stack of things to be resolved
-  will check that this is not already present first
-  will update the mbStackChanged flag
-  */
-  void TryPushStack(APIDescriptor_t *);
-	
-  /*!
-  \brief 'client shutdown' (see libs/synapse/docs/unload.txt)
-  performs a 'client shutdown'
-  will free the DLL module
-  before calling here, the client must be in a 'non active' state
-  (i.e. it was not used at all during startup, or we have properly done a 'release' already)
-  we scan the mStack for the SYN_REQUIRE that this client owns, and remove them
-  \param iSlot is an mClients iterator, invalid when the function returns as the item will have been removed from the list
-  \return the iterator afer erase call so that the caller iteration can continue
-  */
-  list<CSynapseClientSlot>::iterator ShutdownClient(list<CSynapseClientSlot>::iterator iSlot);
-  
-  /*!
-  \brief actual implementation of the Resolve function
-  */
-  bool DoResolve(CSynapseClient *pClient);  
-    
-public:
-  CSynapseServer();
-  virtual ~CSynapseServer();
-
-  void AddSearchPath(char*); ///< add a new directory to the module search path
-  /*!
-  do the big thing, scan for modules, scan their APIs, load up everything
-  providing pf is optional, will set the diagnostics printing
-  \param conf_file is the XML configuration file for the intialization (see docs/runtime.txt)
-  \return false if the init failed (for instance not found/invalid conf file
-  */
-  bool Initialize(const char* conf_file = NULL, PFN_SYN_PRINTF_VA pf = NULL);
-
-  /*!
-  enumerate the interfaces for a given module
-  this will load it, query it's entry point, and request the APIs
-  */
-  void EnumerateInterfaces(Str &);
-  
-  /*!
-  enumerate the interfaces for a module that is builtin to the server
-  */
-  void EnumerateBuiltinModule(CSynapseBuiltinClient *);
-  
-  /*!
-  \brief resolve the function table loading for this client
-  if the client is not listed in the known slots yet, it will be added
-  wraps around internal DoResolve implementation to unload the unused modules
-  \return wether the resolution has been successful  
-  */
-  bool Resolve(CSynapseClient *pClient);
-  
-  /*!
-  \brief shutdown all the clients. Should only be called when the core is about to exit
-  this will force all clients to shutdown. it may destroy refcounted APIs and stuff
-  \todo hafta use the release/refresh code before doing actual shutdown
-  (i.e. when that code is written later on)
-  we need to 'broadcast' to all the clients .. that all the modules are going to be reloaded sorta
-  should clear up as many interfaces as possible to avoid unexpected crashes in the final stages of app exit
-  */
-  void Shutdown();
-  
-  /*!
-  diagnostic print function
-  NOTE:
-    it is essential that those functions should be virtual,
-    otherwise when accessing the g_pPrintf global we could mismatch
-    (happens because the same library is linked into server and client)
-  */
-  virtual PFN_SYN_PRINTF_VA Get_Syn_Printf();
-  
-  /*!
-  \return true if those APIs are matching
-  we provide two APIs for convenience, actual implementation is MatchAPI
-  the minors have to be both NULL, or equal, or one the minors be '*'
-  NOTE: the '*' minor should ONLY be used on an API that will be unique. It is hackish and kinda dangerous
-  */
-  static bool MatchAPI( APIDescriptor_t *p1, APIDescriptor_t *p2 );
-  static bool MatchAPI( const char* major1, const char* minor1, const char* major2, const char* minor2 );
-  
-#if defined(_WIN32)
-  /*!
-  utility function to retrieve formatted GetLastError message
-  ANSI text, static string
-  */
-  static const char* FormatGetLastError();
-#endif
-
-  /*!
-  dump the stack of interfaces to be solved
-  this is used when synapse initialization failed to quickly identify the missing/broken pieces
-  */
-  void DumpStack();
-  
-  /*!
-  general purpose information, list what modules are loaded up
-  */
-  void DumpActiveClients();
-  
-  /*!
-  \brief select the config node that has this name
-  call this to locate the right node in XML config
-  this will focus and get ready to walk through the api nodes
-  \return wether the config node was correctly selected
-  */
-  bool SelectClientConfig(const char *client_name);
-  
-  /*!
-  \brief walk through the apis
-  the pointers don't need to be freed
-  you need to copy them over as they are invalidated between each call to GetNextConfig
-  \return false when all apis have been parsed
-  */
-  bool GetNextConfig(char **api_name, char **minor);
-  
-  /*!
-  \brief read the minor for a given api in the current config
-  \return false if this node doesn't exist
-  */
-  bool GetConfigForAPI( const char *api, char **minor );
-
-  /*!
-  returns the filename of the module that the passed on client exists in
-  */
-  const char *GetModuleFilename(CSynapseClient *pClient);
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __SYNAPSE_H__
+#define __SYNAPSE_H__
+
+/*!
+synapse library
+code and utilities to deal with dynamic components programming
+
+"the point at which a nervous impulse passes from one neuron to another"
+
+dependencies:
+  libxml for parsing
+  STL for some algorithms and data structures
+  glib for Str.h (Str class)
+  
+this is a utility library, it provides typical synapse client and server
+could be split into two independant libraries actually, the server part and the client part
+(that's just a matter of reducing binary size)  
+*/
+
+// compile time settings
+#ifdef _DEBUG
+  #define SYNAPSE_VERBOSE // be verbosive about the loading process
+#endif
+
+// ydnar: required for os x
+#if defined (__APPLE__)
+  #include <sys/types.h>
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+  #include <dlfcn.h>
+  #include <dirent.h>  
+#endif
+
+#if defined(_WIN32)
+  #include <windows.h>
+#endif
+
+#if defined(_WIN32)
+  #define SYNAPSE_DLL_EXPORT WINAPI
+#elif defined(__linux__) || defined(__APPLE__)	/* ydnar */
+//  #define SYNAPSE_DLL_EXPORT __attribute__ ((visibility ("protected")))
+  #define SYNAPSE_DLL_EXPORT
+#else
+  #error unknown architecture
+#endif
+
+// NOTE TTimo: VC6 crap, gets confused when some variable names in function declarations
+//   are 'allocator' or 'list'
+//   if you #include glib *after* STL, you get those errors .. better be safe then
+#include <glib.h>
+
+#include "libxml/parser.h"
+
+#include "irefcount.h"
+#include "gtkr_list.h"
+#include "gtkr_vector.h"
+
+#include "str.h"
+
+/*!
+use when API change make things incompatible at synapse level
+i.e. entry point and classes API changes
+*/
+#define SYNAPSE_VERSION "3"
+
+/*!
+=======================================================================
+diagnostic printing facility
+independently from any API negociation stuff,
+we need a diagnostic facility that's available at all times
+=======================================================================
+*/
+extern "C"
+{
+/*!
+prototype to provide to synapse to redirect the output appropriately  
+*/  
+typedef void (* PFN_SYN_PRINTF_VA) (const char *text, va_list args);
+void Set_Syn_Printf(PFN_SYN_PRINTF_VA pf); ///< change the handler, set back to NULL for default
+/*!
+use this for synapse code diagnostics, it will be piped through the handler if necessary
+*/
+void Syn_Printf (const char *text, ...);
+};
+  
+/*
+=======================================================================
+client
+=======================================================================
+*/
+
+/*!
+description of an API:
+a module requires and provides several APIs
+the basic rule is that we will avoid asking an API from a module if the APIs it requires are not filled in yet
+the exception being the 'resolve' operation of a given client, which we 'activate'
+(that is we make the interfaces it provides available, leave the ones it requires unsolved, and try to get back to a stable situation)
+*/
+
+typedef enum { SYN_UNKNOWN = 0, SYN_PROVIDE, SYN_REQUIRE, SYN_REQUIRE_ANY } EAPIType;
+
+#define MAX_APINAME 128
+typedef struct APIDescriptor_s
+{
+  /*!
+  major version, this must be UNIQUE for each API
+  NOTE: we used to rely on GUID for this, that was a good solution to make sure we never get conflicts
+  but it was a bit overkill, so we dropped and use a string now
+  */
+  char major_name[MAX_APINAME];
+  /*!
+  what kind of interface
+  for instance for "image" API, "tga" "jpg" etc.
+  */
+  char minor_name[MAX_APINAME];
+  EAPIType mType; ///< is this an API we provide or an API we require
+  /*!
+  pointer to the table to be filled in
+  this is valid for SYN_REQUIRE APIs only
+  */
+  void *mpTable;
+  bool mbTableInitDone; ///< turned to true by the server after the function table has been filled in
+  /*!
+  gives the size of the expected function table  
+  */
+  int mSize;
+  /*!
+  refcounts how many times this API is being used through the app
+  this is valid for SYN_PROVIDE APIs only
+  */
+  int mRefCount;
+} APIDescriptor_t;
+
+typedef struct XMLConfigEntry_s {
+  const char *api;
+  EAPIType type;
+  int size;
+  void *pTable;
+} XMLConfigEntry_t;
+
+/*!
+\class CSynapseAPIManager
+derive from this class if you want to manage several APIs through the same object
+(typically, loading plugins, or an unknown number of APIs that match some criterions)
+this class has some pure virtual members that need to be implemented by the childs
+
+we deal with two types of API managers:
+- the 'loose' ones have a matching pattern and load everything that matches criterions
+  typically used for plugins
+- the 'list' ones have a fixed list of things they require. They are used to provide
+  easy access to multiple interfaces
+
+those two types of managers are not stored in the same structs, and not handled the
+same way. For instance the 'list' manager will require ALL it's APIs to be loaded, or
+the init will fail. They also play a role in the client activation.
+
+apart from the multiple API management facility, the main difference with static tables
+and individual calls to CSynapseClient::AddAPI is the fact that the APIDescriptor_t are
+allocated on demand
+*/
+
+/* we do some matching, or store minors list, the strings need to be bigger */
+#define MAX_PATTERN_STRING 512
+
+/*! \enum EAPIManagerType
+  \brief type of this manager, loosely matching with "*", or a fixed list of required interfaces
+*/
+typedef enum { API_MATCH = 0,  API_LIST } EAPIManagerType;
+
+class CSynapseAPIManager : public IRefCounted
+{
+  EAPIManagerType mType;
+  
+  // the list of APIs we have obtained (SYN_REQUIRE_ANY)
+  vector< APIDescriptor_t * > mAPIs;
+  /*!
+  pattern for matching the major version
+  NOTE: only supported for now: exact match
+  */
+  char major_pattern[MAX_PATTERN_STRING];
+  /*!
+  pattern for matching the minor
+  */
+  char minor_pattern[MAX_PATTERN_STRING];  
+  
+public:
+  CSynapseAPIManager() { mType = API_MATCH; }
+  virtual ~CSynapseAPIManager();
+
+  EAPIManagerType GetType() { return mType; }
+  void SetType(EAPIManagerType type) { mType = type; }
+  
+  /*!
+  set the API matching pattern
+  supported syntax:
+  any minor for a given major, for instance: PLUGIN_MAJOR, "*"
+  a space seperated list of minors for a given major: IMAGE_MAJOR, "tga jpg"
+  */
+  void SetMatchAPI(const char *major, const char *minor);
+  
+  /*!
+  utility function
+  start building a SYN_REQUIRE_ANY descriptor from a SYN_PROVIDE interface that we found matching
+  */
+  static APIDescriptor_t* PrepareRequireAPI(APIDescriptor_t *pAPI);  
+  
+  /*!
+  for managers that require a fixed list of things, we are not active until everything has been loaded up
+  managers that work on a loose pattern like "*" are always active (since they don't know what they want for sure)
+  */
+  bool CheckSetActive();
+  
+  /*!
+  the manager answers wether it wants to load this or not
+  we provide a default implementation, but this can be completely overriden if needed
+  see SetMatchAPI for the documentation of the default implementation
+  NOTE: this should only be called on API_MATCH type of managers
+  */
+  virtual bool MatchAPI(const char *major, const char *minor);
+  
+  /*!
+  build an APIDescriptor_t configured as SYN_REQUIRE_ANY from the SYN_PROVIDE API we found
+  used when we scan the available interfaces for a match that would be interesting to this manager
+  NOTE: only for API_MATCH managers
+  */
+  virtual APIDescriptor_t *BuildRequireAPI(APIDescriptor_t *pAPI) { return NULL; }
+  
+  /*!
+  below is relevant to API_LIST only ---------------------------------------------------------------------
+  */
+
+  /*!
+  fill in the table info to this descriptor, store it as a new slot
+  NOTE: only for API_LIST
+  */
+  virtual void FillAPITable(APIDescriptor_t *pAPI) { }
+  
+  /*!
+  initialize the list of APIDescriptor_t* with all the stuff we expect
+  */
+  void InitializeAPIList();
+  
+  /*!
+  access the API descriptors
+  */
+  int GetAPICount();
+  APIDescriptor_t *GetAPI(int);
+};
+
+/*!
+\class CSynapseClient
+*/
+class CSynapseServer; // forward declare
+class CSynapseClient : public IRefCounted
+{
+  /*!
+  this flag indicates wether this client is active
+  i.e. wether you can ask it for interfaces
+  this is either a client for which all required interfaces have been filled in
+  or a client we are trying to resolve (i.e. load with all it's stuff)
+  */
+  bool mbActive;
+  
+  /*!
+  we store APIDescriptor_t*, the module fills that in at startup
+  */
+  vector<APIDescriptor_t *> mAPIDescriptors;
+  
+  /*!
+  managers for multiple APIs management
+  mManagersMatch are managers with loose matching / undefined number of APIs
+  mManagersList are managers with a fixed list of required interfaces
+  */
+  vector<CSynapseAPIManager *> mManagersMatch;
+  vector<CSynapseAPIManager *> mManagersList;
+  
+protected:
+  friend class CSynapseServer;
+  /*!
+  use of this is restricted to the server, expecting it knows what it is doing
+  will make the client we are trying to resolve able to provide interfaces even though all interfaces it requires have not been filled in yet.
+  */
+  void ForceSetActive() { mbActive = true; }
+  
+public:
+  CSynapseClient();
+  virtual ~CSynapseClient();
+
+  int GetAPICount(); ///< returns the number of APIs that this module provides
+  APIDescriptor_t* GetAPIDescriptor(int); ///< retrieve specific information about on of the APIs
+
+  /*!
+  Add the API to the CSynapseClient information
+  
+  \param minor
+  minor can be NULL, some APIs don't need to have a 'minor' description  
+  
+  \param type
+  SYN_PROVIDE: means this is an API we provide if anyone needs it
+  SYN_REQUIRE: means this is an API we will require for operation
+  SYN_REQUIRE_ANY: means this is an API we want to load *any* minor found
+     (for instance a list of image fornats, or the plugins)
+     
+  \param pTable 
+  the function table
+  only valid for SYN_REQUIRE APIs
+  
+  \param size
+  the size of the function table
+  if SYN_REQUIRE, you should set the size in pTable and AddAPI will work it out
+  if SYN_PROVIDE, you need to provide this parameter
+  
+  returns a bool:
+  operation may fail, since we have a few safe checks  
+  */
+  bool AddAPI(const char *major, const char *minor = NULL, int size = 0, EAPIType type = SYN_PROVIDE, void *pTable = NULL);
+  
+  /*!
+  Add an API manager to the client
+  this class is designed to handle multiple APIs
+  is not memory managed by CSynapseClient (should it? or ref counted maybe?)
+  writing it with support for multiple managers, that may be a bit overkill right now
+  */
+  void AddManager(CSynapseAPIManager *pManager);
+  
+  int GetManagerMatchCount(); ///< how many API managers
+  CSynapseAPIManager* GetManagerMatch(int); ///< get corresponding API manager
+
+  int GetManagerListCount(); ///< how many API managers
+  CSynapseAPIManager* GetManagerList(int); ///< get corresponding API manager
+  
+  /*!
+  each client has to implement this function itself
+  it will fill in the function table
+  and increment the ref counting in it's own SYN_PROVIDE descriptor
+  returns a bool, false if you ask for an API that's not available
+  */
+  virtual bool RequestAPI(APIDescriptor_t *pAPI) = 0;
+  
+  /*!
+  return the build date, can be overriden by client module
+  */
+  virtual const char* GetInfo();
+  
+  /*!
+  \brief a shirt name to identify the client
+  we use this string to identify individual clients, for instance when some XML configuration nodes are required
+  should be unique, the synapse server should't accept multiple occurences?  
+  */
+  virtual const char* GetName() { return ""; }
+  
+  bool IsActive() { return mbActive; }
+  /*!
+  check wether all interfaces have been filled in
+  in which case we will switch to 'activated' state, that is this client can provide interfaces to others now
+  */
+  bool CheckSetActive();
+  
+  /*!
+  \brief called when the client is being shutdown, before the dlclose happens
+  this is the last call before the dlclose, there's no turning back
+  just do what you have to do before you die.. decref and stuff
+  */
+  void Shutdown();
+  
+  /*!
+  override this one in clients that need to proceed through some init steps when activated
+  if returning false, the init will abort
+  */
+  virtual bool OnActivate() { return true; }
+  
+  /*!
+  \brief walk the XML config and initialize from structures
+  when you use this function, OnActivate will also make sure all the interfaces listed were properly initialized
+  two tables, one for the regular single interface, one for the listings
+  need to store for later and check in OnActivate
+  
+  \param pServer, pass the server to talk to
+  NOTE: might want to store it in the class if that's needed too often
+  
+  \param client_name, the name of the client node to look for. If NULL, use GetName()
+  
+  \return wether all APIs given were successfully found in the config
+  */
+  bool ConfigXML( CSynapseServer *pServer, const char *client_name, const XMLConfigEntry_t entries[] );
+};
+
+/*!
+prototype for the only exported function needed in a synapse client
+*/
+#define NAME_SYNAPSE_ENUMERATEINTERFACES "Synapse_EnumerateInterfaces"
+
+class CSynapseServer; // forward declare
+typedef CSynapseClient* (SYNAPSE_DLL_EXPORT *PFN_SYNAPSE_ENUMERATEINTERFACES)(const char *version, CSynapseServer *server);
+
+/*!
+a derived version of CSynapseClient that can be used to provide builtin module without having to go through DLLs
+this is useful for things we want to isolate behind an abstract API, but that we feel better about having present at all times (such as .def class loader)
+*/
+class CSynapseBuiltinClient : public CSynapseClient
+{
+  public:
+  CSynapseBuiltinClient() {}
+  virtual ~CSynapseBuiltinClient() {}
+  
+  virtual void EnumerateInterfaces(CSynapseServer *server) = 0;
+  
+};
+
+/*
+=======================================================================
+server
+=======================================================================
+*/
+
+/*!
+  \enum EClientType
+  \brief we can have clients that are builtin to a server
+*/
+typedef enum { SYN_SO, SYN_BUILTIN } EClientType;
+
+/*!
+server side slot for a synapse client
+is OS dependant, except for the ISynapseClient part
+*/
+class CSynapseClientSlot
+{
+public:
+  /*!
+  \todo cleanup, make that private with accessors
+  */
+#if defined(__linux__) || defined(__APPLE__)
+  void *mpDLL; ///< handle to the shared object (invalid if SYN_BUILTIN)
+#elif defined(_WIN32)
+  HMODULE mpDLL; ///< handle to the shared object (invalid if SYN_BUILTIN)
+#endif
+  PFN_SYNAPSE_ENUMERATEINTERFACES mpEnumerate; ///< function pointer to the enumeration entry point (invalid if SYN_BUILTIN)
+
+  CSynapseClient *mpClient; ///< the full client API
+  Str mFileName; ///< path to the file
+  
+  EClientType mType;
+
+  /*!
+  \brief release the shared object. NOTE: OS dependent  
+  */
+  void ReleaseSO();
+  
+  CSynapseClientSlot() { mpDLL = NULL; mpEnumerate = NULL; mpClient = NULL; mType = SYN_SO; }
+  /*!
+  NOTE: the slot is stored as static object, and copy constructors used  
+  */
+  virtual ~CSynapseClientSlot() { }
+
+};
+
+/*!
+\class CSynapseServer
+dynamic modules manager class
+this class provides the server functionality:
+initialize, get a list of modules, load them, link them together..
+*/
+class CSynapseServer : public IRefCounted
+{
+  list<char *> mSearchPaths;
+  list<CSynapseClientSlot> mClients;
+	  
+  /*!
+  used for resolve operations
+  */
+  list<APIDescriptor_t*> mStack;
+  /*!
+  set this when mStack is modified with new stuff to resolve
+  NOTE: if this hack becomes too tricky to use we could just encapsulate mStack
+  */
+  bool mbStackChanged;
+  
+  xmlDocPtr mpDoc;
+  xmlNodePtr mpFocusedNode; ///< currently focused node while we are scanning the config (strictly for GetNextConfig usage)
+  xmlNodePtr mpCurrentClientConfig;
+  /*!
+  stores the allocated strings for each call to GetNextConfig
+  need to be freed if != NULL
+  */
+  xmlChar *m_api_name;
+  gchar *m_content;
+    
+  /*!
+  push required interfaces for this client into the stack of things to be resolved
+  it is possible that several mathing interfaces be in the stack at the same time
+  (for instance several modules that want to get the VFS)
+  but we should never have the same APIDescriptor_t twice
+  NOTE: as this function is called repeatedly during the resolve (because the list of required things is refining),
+    we often have to drop APIDescriptor_t requests that are already there.
+  NOTE CSynapseAPIManager: if there are CSynapseAPIManager objects in the CSynapseClient,
+    we will scan and push all the matching APIs too
+  */
+  void PushRequired(CSynapseClient *pClient);
+  
+  /*!
+  work on resolving this particular APIDescriptor_t
+  returns true if we were able to resolve the interface
+  returns false otherwise
+  if the API was found, but not requested because of more required APIs, we push them in mStack
+  */
+  bool ResolveAPI(APIDescriptor_t* pAPI);
+  
+  /*!
+  push an APIDescriptor_t* into the stack of things to be resolved
+  will check that this is not already present first
+  will update the mbStackChanged flag
+  */
+  void TryPushStack(APIDescriptor_t *);
+	
+  /*!
+  \brief 'client shutdown' (see libs/synapse/docs/unload.txt)
+  performs a 'client shutdown'
+  will free the DLL module
+  before calling here, the client must be in a 'non active' state
+  (i.e. it was not used at all during startup, or we have properly done a 'release' already)
+  we scan the mStack for the SYN_REQUIRE that this client owns, and remove them
+  \param iSlot is an mClients iterator, invalid when the function returns as the item will have been removed from the list
+  \return the iterator afer erase call so that the caller iteration can continue
+  */
+  list<CSynapseClientSlot>::iterator ShutdownClient(list<CSynapseClientSlot>::iterator iSlot);
+  
+  /*!
+  \brief actual implementation of the Resolve function
+  */
+  bool DoResolve(CSynapseClient *pClient);  
+    
+public:
+  CSynapseServer();
+  virtual ~CSynapseServer();
+
+  void AddSearchPath(char*); ///< add a new directory to the module search path
+  /*!
+  do the big thing, scan for modules, scan their APIs, load up everything
+  providing pf is optional, will set the diagnostics printing
+  \param conf_file is the XML configuration file for the intialization (see docs/runtime.txt)
+  \return false if the init failed (for instance not found/invalid conf file
+  */
+  bool Initialize(const char* conf_file = NULL, PFN_SYN_PRINTF_VA pf = NULL);
+
+  /*!
+  enumerate the interfaces for a given module
+  this will load it, query it's entry point, and request the APIs
+  */
+  void EnumerateInterfaces(Str &);
+  
+  /*!
+  enumerate the interfaces for a module that is builtin to the server
+  */
+  void EnumerateBuiltinModule(CSynapseBuiltinClient *);
+  
+  /*!
+  \brief resolve the function table loading for this client
+  if the client is not listed in the known slots yet, it will be added
+  wraps around internal DoResolve implementation to unload the unused modules
+  \return wether the resolution has been successful  
+  */
+  bool Resolve(CSynapseClient *pClient);
+  
+  /*!
+  \brief shutdown all the clients. Should only be called when the core is about to exit
+  this will force all clients to shutdown. it may destroy refcounted APIs and stuff
+  \todo hafta use the release/refresh code before doing actual shutdown
+  (i.e. when that code is written later on)
+  we need to 'broadcast' to all the clients .. that all the modules are going to be reloaded sorta
+  should clear up as many interfaces as possible to avoid unexpected crashes in the final stages of app exit
+  */
+  void Shutdown();
+  
+  /*!
+  diagnostic print function
+  NOTE:
+    it is essential that those functions should be virtual,
+    otherwise when accessing the g_pPrintf global we could mismatch
+    (happens because the same library is linked into server and client)
+  */
+  virtual PFN_SYN_PRINTF_VA Get_Syn_Printf();
+  
+  /*!
+  \return true if those APIs are matching
+  we provide two APIs for convenience, actual implementation is MatchAPI
+  the minors have to be both NULL, or equal, or one the minors be '*'
+  NOTE: the '*' minor should ONLY be used on an API that will be unique. It is hackish and kinda dangerous
+  */
+  static bool MatchAPI( APIDescriptor_t *p1, APIDescriptor_t *p2 );
+  static bool MatchAPI( const char* major1, const char* minor1, const char* major2, const char* minor2 );
+  
+#if defined(_WIN32)
+  /*!
+  utility function to retrieve formatted GetLastError message
+  ANSI text, static string
+  */
+  static const char* FormatGetLastError();
+#endif
+
+  /*!
+  dump the stack of interfaces to be solved
+  this is used when synapse initialization failed to quickly identify the missing/broken pieces
+  */
+  void DumpStack();
+  
+  /*!
+  general purpose information, list what modules are loaded up
+  */
+  void DumpActiveClients();
+  
+  /*!
+  \brief select the config node that has this name
+  call this to locate the right node in XML config
+  this will focus and get ready to walk through the api nodes
+  \return wether the config node was correctly selected
+  */
+  bool SelectClientConfig(const char *client_name);
+  
+  /*!
+  \brief walk through the apis
+  the pointers don't need to be freed
+  you need to copy them over as they are invalidated between each call to GetNextConfig
+  \return false when all apis have been parsed
+  */
+  bool GetNextConfig(char **api_name, char **minor);
+  
+  /*!
+  \brief read the minor for a given api in the current config
+  \return false if this node doesn't exist
+  */
+  bool GetConfigForAPI( const char *api, char **minor );
+
+  /*!
+  returns the filename of the module that the passed on client exists in
+  */
+  const char *GetModuleFilename(CSynapseClient *pClient);
+};
+
+#endif
diff --git a/plugins/eclassfgd/plugin.h b/plugins/eclassfgd/plugin.h
index 4b707f49..5f402c17 100644
--- a/plugins/eclassfgd/plugin.h
+++ b/plugins/eclassfgd/plugin.h
@@ -1,49 +1,49 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "synapse.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#define USE_ECLASSMANAGER_DEFINE
-#include "ieclass.h"
-#define USE_SCRIPLIBTABLE_DEFINE
-#include "iscriplib.h"
-#define USE_VFSTABLE_DEFINE
-#include "ifilesystem.h"
-
-class CSynapseClientFGD : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  
-  CSynapseClientFGD() { }
-  virtual ~CSynapseClientFGD() { }
-};
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "synapse.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#define USE_ECLASSMANAGER_DEFINE
+#include "ieclass.h"
+#define USE_SCRIPLIBTABLE_DEFINE
+#include "iscriplib.h"
+#define USE_VFSTABLE_DEFINE
+#include "ifilesystem.h"
+
+class CSynapseClientFGD : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  
+  CSynapseClientFGD() { }
+  virtual ~CSynapseClientFGD() { }
+};
+
+#endif // _PLUGIN_H_
diff --git a/plugins/entity/entity.h b/plugins/entity/entity.h
index 25a925d0..6ae14603 100644
--- a/plugins/entity/entity.h
+++ b/plugins/entity/entity.h
@@ -1,52 +1,52 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// entity.h
-
-// external API
-
-// construct
-entity_t* Entity_Alloc();
-// destruct
-void Entity_Free (entity_t *e);
-// construct from entity
-entity_t* Entity_Clone (entity_t *e);
-
-// epair interface
-void  SetKeyValue (entity_t *ent, const char *key, const char *value);
-void  DeleteKey (entity_t *ent, const char *key);
-const char* ValueForKey (entity_t *ent, const char *key);
-float FloatForKey (entity_t *ent, const char *key);
-int   IntForKey (entity_t *ent, const char *key);
-void  GetVectorForKey (entity_t *ent, const char *key, vec3_t vec);
-
-void Entity_AddToList(entity_t *e, entity_t *lst);
-void Entity_RemoveFromList(entity_t *e);
-
-void Entity_LinkBrush (entity_t *e, brush_t *b);
-void Entity_UnlinkBrush (brush_t *b);
-
-// for undo
-int Entity_MemorySize(entity_t *e);
-
-epair_t* Entity_AllocateEpair(const char *key, const char *value);
-epair_t** Entity_GetKeyValList(entity_t *e);
-void Entity_SetKeyValList(entity_t *e, epair_t* ep);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// entity.h
+
+// external API
+
+// construct
+entity_t* Entity_Alloc();
+// destruct
+void Entity_Free (entity_t *e);
+// construct from entity
+entity_t* Entity_Clone (entity_t *e);
+
+// epair interface
+void  SetKeyValue (entity_t *ent, const char *key, const char *value);
+void  DeleteKey (entity_t *ent, const char *key);
+const char* ValueForKey (entity_t *ent, const char *key);
+float FloatForKey (entity_t *ent, const char *key);
+int   IntForKey (entity_t *ent, const char *key);
+void  GetVectorForKey (entity_t *ent, const char *key, vec3_t vec);
+
+void Entity_AddToList(entity_t *e, entity_t *lst);
+void Entity_RemoveFromList(entity_t *e);
+
+void Entity_LinkBrush (entity_t *e, brush_t *b);
+void Entity_UnlinkBrush (brush_t *b);
+
+// for undo
+int Entity_MemorySize(entity_t *e);
+
+epair_t* Entity_AllocateEpair(const char *key, const char *value);
+epair_t** Entity_GetKeyValList(entity_t *e);
+void Entity_SetKeyValList(entity_t *e, epair_t* ep);
diff --git a/plugins/entity/entity_entitymodel.h b/plugins/entity/entity_entitymodel.h
index a805c219..dca34ae8 100644
--- a/plugins/entity/entity_entitymodel.h
+++ b/plugins/entity/entity_entitymodel.h
@@ -1,150 +1,150 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _ENTITYMODEL_H_
-#define _ENTITYMODEL_H_
-
-#include "plugin.h"
-
-/*! simulates misc_model entity behaviours for rendering/selection/editing */
-class CEntityMiscModel : public IRender, public ISelect, public IEdit
-{
-public:
-  CEntityMiscModel (entity_t *e);
-  virtual ~CEntityMiscModel ();
-
-  void IncRef() { refCount++; }
-  void DecRef() { if(--refCount == 0) delete this; }
-
-  // IRender
-  void Draw(int state, int rflags) const;
-  const aabb_t *GetAABB() const { return &m_BBox; }
-
-  // ISelect
-  bool TestRay(const ray_t *ray, vec_t *dist) const;
-  //bool TestBox(const aabb_t aabb) const;
-
-  // ITransform
-  void Translate(const vec3_t translation);
-  void Rotate(const vec3_t pivot, const vec3_t rotation);
-  const vec_t *GetTranslation() const { return m_translate; }
-  const vec_t *GetRotation() const { return m_euler; }
-  void OnKeyValueChanged(entity_t *e, const char *key, const char* value);
-
-  void SetName(const char *name);
-private:
-  void BuildCacheRequestString(const char *name);
-  /*! updates the AABB and transformation matrix */
-  void UpdateCachedData();
-  entity_interfaces_t *m_model;
-
-  entity_t *m_entity;
-
-  int refCount;
-  string_t m_version;
-
-  Str m_cachereq;
-
-   /*! AABB in local space */
-  aabb_t m_BBox;
-
-  /*! worldspace-to-localspace translation */
-  vec3_t m_translate;
-
-  /*! worldspace-to-localspace euler rotation angles */
-  vec3_t m_euler;
-
-  /*! worldspace-to-localspace scale */
-  vec3_t m_scale;
-
-  /*! localspace origin, effectively rotation & scale pivot point */
-  vec3_t m_pivot;
-
-  /*! worldspace-to-localspace transform, generated from translate/euler/scale/pivot */
-  m4x4_t m_transform;
-
-  /*! localspace-to-worldspace transform */
-  m4x4_t m_inverse_transform;
-};
-
-/*! simulates eclass-model entity behaviours for rendering/selection/editing */
-class CEntityEclassModel : public IRender, public ISelect, public IEdit
-{
-public:
-  CEntityEclassModel ();
-  virtual ~CEntityEclassModel ();
-
-  void IncRef() { refCount++; }
-  void DecRef() { if(--refCount == 0) delete this; }
-
-  // IRender
-  void Draw(int state, int rflags) const;
-  const aabb_t *GetAABB() const { return &m_BBox; }
-
-  // ISelect
-  bool TestRay(const ray_t *ray, vec_t *dist) const;
-  //bool TestBox(const aabb_t aabb) const;
-
-  // ITransform
-  void Translate(const vec3_t translation);
-  void Rotate(const vec3_t pivot, const vec3_t rotation);
-  const vec_t *GetTranslation() const { return m_translate; }
-  const vec_t *GetRotation() const { return m_euler; }
-  void OnKeyValueChanged(entity_t *e, const char *key, const char* value);
-
-  void SetName(const char *name);
-  void SetEclass(const eclass_t* eclass);
-private:
-  /*! updates the AABB and transformation matrix */
-  void UpdateCachedData();
-  entity_interfaces_t *m_model;
-
-  int refCount;
-  string_t m_name;
-  string_t m_version;
-  const eclass_t *m_eclass;
-
-  /*! AABB in local space */
-  aabb_t m_BBox;
-
-  /*! worldspace-to-localspace translation */
-  vec3_t m_translate;
-
-  /*! worldspace-to-localspace euler rotation angles */
-  vec3_t m_euler;
-
-  /*! worldspace-to-localspace scale */
-  vec3_t m_scale;
-
-  /*! localspace origin, effectively rotation & scale pivot point */
-  vec3_t m_pivot;
-
-  /*! worldspace-to-localspace transform, generated from translate/euler/scale/pivot */
-  m4x4_t m_transform;
-
-  /*! localspace-to-worldspace transform */
-  m4x4_t m_inverse_transform;
-};
-
-void pivot_draw(const vec3_t pivot);
-void Entity_UpdateClass(entity_t *e, const char* value);
-
-#endif /* _ENTITYMODEL_H_ */
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _ENTITYMODEL_H_
+#define _ENTITYMODEL_H_
+
+#include "plugin.h"
+
+/*! simulates misc_model entity behaviours for rendering/selection/editing */
+class CEntityMiscModel : public IRender, public ISelect, public IEdit
+{
+public:
+  CEntityMiscModel (entity_t *e);
+  virtual ~CEntityMiscModel ();
+
+  void IncRef() { refCount++; }
+  void DecRef() { if(--refCount == 0) delete this; }
+
+  // IRender
+  void Draw(int state, int rflags) const;
+  const aabb_t *GetAABB() const { return &m_BBox; }
+
+  // ISelect
+  bool TestRay(const ray_t *ray, vec_t *dist) const;
+  //bool TestBox(const aabb_t aabb) const;
+
+  // ITransform
+  void Translate(const vec3_t translation);
+  void Rotate(const vec3_t pivot, const vec3_t rotation);
+  const vec_t *GetTranslation() const { return m_translate; }
+  const vec_t *GetRotation() const { return m_euler; }
+  void OnKeyValueChanged(entity_t *e, const char *key, const char* value);
+
+  void SetName(const char *name);
+private:
+  void BuildCacheRequestString(const char *name);
+  /*! updates the AABB and transformation matrix */
+  void UpdateCachedData();
+  entity_interfaces_t *m_model;
+
+  entity_t *m_entity;
+
+  int refCount;
+  string_t m_version;
+
+  Str m_cachereq;
+
+   /*! AABB in local space */
+  aabb_t m_BBox;
+
+  /*! worldspace-to-localspace translation */
+  vec3_t m_translate;
+
+  /*! worldspace-to-localspace euler rotation angles */
+  vec3_t m_euler;
+
+  /*! worldspace-to-localspace scale */
+  vec3_t m_scale;
+
+  /*! localspace origin, effectively rotation & scale pivot point */
+  vec3_t m_pivot;
+
+  /*! worldspace-to-localspace transform, generated from translate/euler/scale/pivot */
+  m4x4_t m_transform;
+
+  /*! localspace-to-worldspace transform */
+  m4x4_t m_inverse_transform;
+};
+
+/*! simulates eclass-model entity behaviours for rendering/selection/editing */
+class CEntityEclassModel : public IRender, public ISelect, public IEdit
+{
+public:
+  CEntityEclassModel ();
+  virtual ~CEntityEclassModel ();
+
+  void IncRef() { refCount++; }
+  void DecRef() { if(--refCount == 0) delete this; }
+
+  // IRender
+  void Draw(int state, int rflags) const;
+  const aabb_t *GetAABB() const { return &m_BBox; }
+
+  // ISelect
+  bool TestRay(const ray_t *ray, vec_t *dist) const;
+  //bool TestBox(const aabb_t aabb) const;
+
+  // ITransform
+  void Translate(const vec3_t translation);
+  void Rotate(const vec3_t pivot, const vec3_t rotation);
+  const vec_t *GetTranslation() const { return m_translate; }
+  const vec_t *GetRotation() const { return m_euler; }
+  void OnKeyValueChanged(entity_t *e, const char *key, const char* value);
+
+  void SetName(const char *name);
+  void SetEclass(const eclass_t* eclass);
+private:
+  /*! updates the AABB and transformation matrix */
+  void UpdateCachedData();
+  entity_interfaces_t *m_model;
+
+  int refCount;
+  string_t m_name;
+  string_t m_version;
+  const eclass_t *m_eclass;
+
+  /*! AABB in local space */
+  aabb_t m_BBox;
+
+  /*! worldspace-to-localspace translation */
+  vec3_t m_translate;
+
+  /*! worldspace-to-localspace euler rotation angles */
+  vec3_t m_euler;
+
+  /*! worldspace-to-localspace scale */
+  vec3_t m_scale;
+
+  /*! localspace origin, effectively rotation & scale pivot point */
+  vec3_t m_pivot;
+
+  /*! worldspace-to-localspace transform, generated from translate/euler/scale/pivot */
+  m4x4_t m_transform;
+
+  /*! localspace-to-worldspace transform */
+  m4x4_t m_inverse_transform;
+};
+
+void pivot_draw(const vec3_t pivot);
+void Entity_UpdateClass(entity_t *e, const char* value);
+
+#endif /* _ENTITYMODEL_H_ */
diff --git a/plugins/entity/light.h b/plugins/entity/light.h
index 9beea359..37b714f2 100644
--- a/plugins/entity/light.h
+++ b/plugins/entity/light.h
@@ -1,26 +1,26 @@
-
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-bool Entity_IsLight(entity_t *e);
-void Light_OnKeyValueChanged(entity_t *e, const char *key, const char* value);
-void DrawLight(entity_t* e, int nGLState, int pref, int nViewType);
-
+
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+bool Entity_IsLight(entity_t *e);
+void Light_OnKeyValueChanged(entity_t *e, const char *key, const char* value);
+void DrawLight(entity_t* e, int nGLState, int pref, int nViewType);
+
diff --git a/plugins/entity/plugin.h b/plugins/entity/plugin.h
index 5bf34364..1c997440 100644
--- a/plugins/entity/plugin.h
+++ b/plugins/entity/plugin.h
@@ -1,58 +1,58 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-/*!
-\todo need general notice about lib purpose etc.
-and the external dependencies (such as GLib, STL, mathlib etc.)
-*/
-
-/*!
-\todo not sure about what should be used for common data structures, GLib or STL
-I think STL would be better since I intend on using STL in synapse
-*/
-
-#include <stdio.h>
-
-#include "synapse.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#include "ientity.h"
-#define USE_ECLASSMANAGER_DEFINE
-#include "ieclass.h"
-#define USE_BRUSHTABLE_DEFINE
-#include "ibrush.h"
-#define USE_UNDOTABLE_DEFINE
-#include "iundo.h"
-#include "imodel.h"
-#include "igl.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERQglTable g_QglTable;
-extern _QERBrushTable __BRUSHTABLENAME;
-extern _QERUndoTable __UNDOTABLENAME;
-extern _EClassManagerTable __ECLASSMANAGERTABLENAME;
-
-#define Error g_FuncTable.m_pfnError
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+/*!
+\todo need general notice about lib purpose etc.
+and the external dependencies (such as GLib, STL, mathlib etc.)
+*/
+
+/*!
+\todo not sure about what should be used for common data structures, GLib or STL
+I think STL would be better since I intend on using STL in synapse
+*/
+
+#include <stdio.h>
+
+#include "synapse.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#include "ientity.h"
+#define USE_ECLASSMANAGER_DEFINE
+#include "ieclass.h"
+#define USE_BRUSHTABLE_DEFINE
+#include "ibrush.h"
+#define USE_UNDOTABLE_DEFINE
+#include "iundo.h"
+#include "imodel.h"
+#include "igl.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERQglTable g_QglTable;
+extern _QERBrushTable __BRUSHTABLENAME;
+extern _QERUndoTable __UNDOTABLENAME;
+extern _EClassManagerTable __ECLASSMANAGERTABLENAME;
+
+#define Error g_FuncTable.m_pfnError
+
+#endif // _PLUGIN_H_
diff --git a/plugins/image/bmp.h b/plugins/image/bmp.h
index c246f172..63667ea5 100644
--- a/plugins/image/bmp.h
+++ b/plugins/image/bmp.h
@@ -1,101 +1,101 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _BMP_H
-#define _BMP_H
-
-#define xBI_NONE  0
-#define xBI_RGB   0
-#define xBI_RLE4  2
-#define xBI_RLE8  1
-
-#define BMP_SIGNATURE_WORD  0x4d42
-
-#pragma pack(1)
-
-
-
-typedef struct {
-    unsigned short    bfType;       // signature - 'BM'
-    unsigned long     bfSize;       // file size in bytes
-    unsigned short    bfReserved1;  // 0
-    unsigned short    bfReserved2;  // 0
-    unsigned long     bfOffBits;    // offset to bitmap
-} bmphd_t;
-
-
-
-typedef struct {
-    unsigned long     biSize;       // size of this struct
-    long              biWidth;      // bmap width in pixels
-    long              biHeight;     // bmap height in pixels
-    unsigned short    biPlanes;     // num planes - always 1
-    unsigned short    biBitCount;   // bits perpixel
-    unsigned long     biCompression; // compression flag
-    unsigned long     biSizeImage;   // image size in bytes
-    long              biXPelsPerMeter; // horz resolution
-    long              biYPelsPerMeter; // vert resolution
-    unsigned long     biClrUsed;       // 0 -> color table size
-    unsigned long     biClrImportant;  // important color count
-} binfo_t;
-
-
-typedef struct {
-    unsigned char blue;
-    unsigned char green;
-    unsigned char red;
-    unsigned char reserved;
-} drgb_t;
-
-
-// quake expects its palette to be bgr
-// this is totally backwards but what can you do
-typedef struct {
-    unsigned char r;
-    unsigned char g;
-    unsigned char b;
-} rgb_t;
-
-
-typedef struct {
-    unsigned char b;
-    unsigned char g;
-    unsigned char r;
-} bgr_t;
-
-
-typedef struct {
-	int            bpp;        // bits per pixel
-    int            width;
-    int            height;
-    unsigned char *data;
-    rgb_t         *palette;
-} bitmap_t;
-
-
-void LoadBMP(char *filename, bitmap_t *bit);
-void FreeBMP(bitmap_t *bitmap);
-void WriteBMP(char *filename, bitmap_t *bit);
-void NewBMP(int width, int height, int bpp, bitmap_t *bit);
-
-
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _BMP_H
+#define _BMP_H
+
+#define xBI_NONE  0
+#define xBI_RGB   0
+#define xBI_RLE4  2
+#define xBI_RLE8  1
+
+#define BMP_SIGNATURE_WORD  0x4d42
+
+#pragma pack(1)
+
+
+
+typedef struct {
+    unsigned short    bfType;       // signature - 'BM'
+    unsigned long     bfSize;       // file size in bytes
+    unsigned short    bfReserved1;  // 0
+    unsigned short    bfReserved2;  // 0
+    unsigned long     bfOffBits;    // offset to bitmap
+} bmphd_t;
+
+
+
+typedef struct {
+    unsigned long     biSize;       // size of this struct
+    long              biWidth;      // bmap width in pixels
+    long              biHeight;     // bmap height in pixels
+    unsigned short    biPlanes;     // num planes - always 1
+    unsigned short    biBitCount;   // bits perpixel
+    unsigned long     biCompression; // compression flag
+    unsigned long     biSizeImage;   // image size in bytes
+    long              biXPelsPerMeter; // horz resolution
+    long              biYPelsPerMeter; // vert resolution
+    unsigned long     biClrUsed;       // 0 -> color table size
+    unsigned long     biClrImportant;  // important color count
+} binfo_t;
+
+
+typedef struct {
+    unsigned char blue;
+    unsigned char green;
+    unsigned char red;
+    unsigned char reserved;
+} drgb_t;
+
+
+// quake expects its palette to be bgr
+// this is totally backwards but what can you do
+typedef struct {
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+} rgb_t;
+
+
+typedef struct {
+    unsigned char b;
+    unsigned char g;
+    unsigned char r;
+} bgr_t;
+
+
+typedef struct {
+	int            bpp;        // bits per pixel
+    int            width;
+    int            height;
+    unsigned char *data;
+    rgb_t         *palette;
+} bitmap_t;
+
+
+void LoadBMP(char *filename, bitmap_t *bit);
+void FreeBMP(bitmap_t *bitmap);
+void WriteBMP(char *filename, bitmap_t *bit);
+void NewBMP(int width, int height, int bpp, bitmap_t *bit);
+
+
+
+#endif
diff --git a/plugins/image/image.h b/plugins/image/image.h
index f50e5a3e..f209fd59 100644
--- a/plugins/image/image.h
+++ b/plugins/image/image.h
@@ -1,68 +1,68 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _IMAGE_H_
-#define _IMAGE_H_
-
-#include "synapse.h"
-#include "qerplugin.h"
-#include "ifilesystem.h"
-#include "iimage.h"
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERFileSystemTable g_FileSystemTable;
-void LoadJPG (const char *filename, unsigned char **pic, int *width, int *height);
-
-#define Error g_FuncTable.m_pfnError
-#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
-#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
-
-class CSynapseClientImage : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  bool OnActivate();
-  const char* GetName() { return "image"; }
-
-  CSynapseClientImage() { }
-  virtual ~CSynapseClientImage() { }
-};
-
-#endif // _IMAGE_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _IMAGE_H_
+#define _IMAGE_H_
+
+#include "synapse.h"
+#include "qerplugin.h"
+#include "ifilesystem.h"
+#include "iimage.h"
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERFileSystemTable g_FileSystemTable;
+void LoadJPG (const char *filename, unsigned char **pic, int *width, int *height);
+
+#define Error g_FuncTable.m_pfnError
+#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
+#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
+
+class CSynapseClientImage : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  bool OnActivate();
+  const char* GetName() { return "image"; }
+
+  CSynapseClientImage() { }
+  virtual ~CSynapseClientImage() { }
+};
+
+#endif // _IMAGE_H_
diff --git a/plugins/image/lbmlib.h b/plugins/image/lbmlib.h
index f0dccd4a..a8892be6 100644
--- a/plugins/image/lbmlib.h
+++ b/plugins/image/lbmlib.h
@@ -1,46 +1,46 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// piclib.h
-
-#ifdef __linux__
-#define WINAPI
-#endif
-
-typedef unsigned char byte;
-
-void LoadLBM (char *filename, byte **picture, byte **palette);
-void WriteLBMfile (char *filename, byte *data, int width, int height
-	, byte *palette);
-void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
-void WritePCXfile (char *filename, byte *data, int width, int height
-	, byte *palette);
-
-// loads / saves either lbm or pcx, depending on extension
-void Load256Image (char *name, byte **pixels, byte **palette,
-				   int *width, int *height);
-void Save256Image (char *name, byte *pixels, byte *palette,
-				   int width, int height);
-
-
-void LoadTGA (char *filename, byte **pixels, int *width, int *height);
-// LoadImage will rely on file extension to call LoadTGA LoadPCX32 LoadBMP LoadJPG
-void LoadImage( const char *name, byte **pic, int *width, int *height );
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// piclib.h
+
+#ifdef __linux__
+#define WINAPI
+#endif
+
+typedef unsigned char byte;
+
+void LoadLBM (char *filename, byte **picture, byte **palette);
+void WriteLBMfile (char *filename, byte *data, int width, int height
+	, byte *palette);
+void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
+void WritePCXfile (char *filename, byte *data, int width, int height
+	, byte *palette);
+
+// loads / saves either lbm or pcx, depending on extension
+void Load256Image (char *name, byte **pixels, byte **palette,
+				   int *width, int *height);
+void Save256Image (char *name, byte *pixels, byte *palette,
+				   int width, int height);
+
+
+void LoadTGA (char *filename, byte **pixels, int *width, int *height);
+// LoadImage will rely on file extension to call LoadTGA LoadPCX32 LoadBMP LoadJPG
+void LoadImage( const char *name, byte **pic, int *width, int *height );
diff --git a/plugins/imagehl/imagehl.h b/plugins/imagehl/imagehl.h
index 26d82964..5042e7e2 100644
--- a/plugins/imagehl/imagehl.h
+++ b/plugins/imagehl/imagehl.h
@@ -1,80 +1,80 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used
-to endorse or promote products derived from this software without specific prior
-written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef _IMAGEHL_H_
-#define _IMAGEHL_H_
-
-// here we can turn on and off which image formats this .dll will provide.
-// just comment the define out to completly remove the code from the .dll.
-#define USE_TARGA //Hydra: USE_TARGA is NOT required for HL support. but it might be useful to mappers. remove ?
-#define USE_IDSP
-#define USE_HLW
-#define USE_MIP
-
-// on with the usual stuff...
-#include "synapse.h"
-#include "qerplugin.h"
-#include "ifilesystem.h"
-#include "iimage.h"
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERFileSystemTable g_FileSystemTable;
-
-#define Error g_FuncTable.m_pfnError
-#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
-#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
-
-#define LittleLong(a) GINT32_FROM_LE(a)
-#define LittleShort(a) GINT16_FROM_LE(a)
-
-class CSynapseClientImageHL : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-
-  CSynapseClientImageHL() { }
-  virtual ~CSynapseClientImageHL() { }
-};
-
-#define DWORD unsigned int
-#define BYTE unsigned char
-#define WORD unsigned short int
-
-#endif // _IMAGEHL_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used
+to endorse or promote products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _IMAGEHL_H_
+#define _IMAGEHL_H_
+
+// here we can turn on and off which image formats this .dll will provide.
+// just comment the define out to completly remove the code from the .dll.
+#define USE_TARGA //Hydra: USE_TARGA is NOT required for HL support. but it might be useful to mappers. remove ?
+#define USE_IDSP
+#define USE_HLW
+#define USE_MIP
+
+// on with the usual stuff...
+#include "synapse.h"
+#include "qerplugin.h"
+#include "ifilesystem.h"
+#include "iimage.h"
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERFileSystemTable g_FileSystemTable;
+
+#define Error g_FuncTable.m_pfnError
+#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
+#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
+
+#define LittleLong(a) GINT32_FROM_LE(a)
+#define LittleShort(a) GINT16_FROM_LE(a)
+
+class CSynapseClientImageHL : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+
+  CSynapseClientImageHL() { }
+  virtual ~CSynapseClientImageHL() { }
+};
+
+#define DWORD unsigned int
+#define BYTE unsigned char
+#define WORD unsigned short int
+
+#endif // _IMAGEHL_H_
diff --git a/plugins/imagehl/lbmlib.h b/plugins/imagehl/lbmlib.h
index 2ea0ec5d..c50318bf 100644
--- a/plugins/imagehl/lbmlib.h
+++ b/plugins/imagehl/lbmlib.h
@@ -1,35 +1,35 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// lbmlib.h
-
-#ifdef __linux__
-#define WINAPI
-#endif
-
-typedef unsigned char byte;
-
-#ifdef USE_TARGA
-void LoadTGA (char *filename, byte **pixels, int *width, int *height);
-#endif
-
-// LoadImage will rely on file extension to call LoadTGA loadHLW
-void LoadImage( const char *name, byte **pic, int *width, int *height );
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// lbmlib.h
+
+#ifdef __linux__
+#define WINAPI
+#endif
+
+typedef unsigned char byte;
+
+#ifdef USE_TARGA
+void LoadTGA (char *filename, byte **pixels, int *width, int *height);
+#endif
+
+// LoadImage will rely on file extension to call LoadTGA loadHLW
+void LoadImage( const char *name, byte **pic, int *width, int *height );
diff --git a/plugins/imagem8/imagem8.h b/plugins/imagem8/imagem8.h
index 9864256c..2ba99e89 100644
--- a/plugins/imagem8/imagem8.h
+++ b/plugins/imagem8/imagem8.h
@@ -1,70 +1,70 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _IMAGEM8_H_
-#define _IMAGEM8_H_
-
-#include "synapse.h"
-#include "qerplugin.h"
-#include "ifilesystem.h"
-#include "iimage.h"
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERFileSystemTable g_FileSystemTable;
-void LoadM8 (const char *name, unsigned char **pic, int *width, int *height);
-void LoadM32 (const char *name, unsigned char **pic, int *width, int *height);
-
-#define Error g_FuncTable.m_pfnError
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
-#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
-
-class CSynapseClientImage : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  bool OnActivate();
-  const char* GetName() { return "image"; }
-
-  CSynapseClientImage() { }
-  virtual ~CSynapseClientImage() { }
-};
-
-#endif // _IMAGEM8_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _IMAGEM8_H_
+#define _IMAGEM8_H_
+
+#include "synapse.h"
+#include "qerplugin.h"
+#include "ifilesystem.h"
+#include "iimage.h"
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERFileSystemTable g_FileSystemTable;
+void LoadM8 (const char *name, unsigned char **pic, int *width, int *height);
+void LoadM32 (const char *name, unsigned char **pic, int *width, int *height);
+
+#define Error g_FuncTable.m_pfnError
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
+#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
+
+class CSynapseClientImage : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  bool OnActivate();
+  const char* GetName() { return "image"; }
+
+  CSynapseClientImage() { }
+  virtual ~CSynapseClientImage() { }
+};
+
+#endif // _IMAGEM8_H_
diff --git a/plugins/imagem8/m32.h b/plugins/imagem8/m32.h
index 3b754130..4e49f4e5 100644
--- a/plugins/imagem8/m32.h
+++ b/plugins/imagem8/m32.h
@@ -1,64 +1,64 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _M32_H
-#define _M32_H
-
-#include "imagem8.h"
-
-#define M32_VERSION  	4
-#define M32_MIP_LEVELS	16
-
-typedef struct {
-    unsigned char r;
-    unsigned char g;
-    unsigned char b;
-} rgb_t;
-
-typedef struct 
-{
-	int		version;
-	char		name[128];
-	char		altname[128];                   // texture substitution
-	char		animname[128];                  // next frame in animation chain
-	char		damagename[128];                // image that should be shown when damaged
-	unsigned	width[M32_MIP_LEVELS], height[M32_MIP_LEVELS];
-	unsigned	offsets[M32_MIP_LEVELS];
-	int		flags;
-	int		contents;
-	int		value;
-	float		scale_x, scale_y;
-	int		mip_scale;
-
-	// detail texturing info
-	char		dt_name[128];           // detailed texture name
-	float		dt_scale_x, dt_scale_y;
-	float		dt_u, dt_v;
-	float		dt_alpha;
-	int		dt_src_blend_mode, dt_dst_blend_mode;
-
-	int		unused[20];                             // future expansion to maintain compatibility with h2
-} m32_header_t;
-
-void LoadM32(const char *name, unsigned char **pic, int *width, int *height);
-
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _M32_H
+#define _M32_H
+
+#include "imagem8.h"
+
+#define M32_VERSION  	4
+#define M32_MIP_LEVELS	16
+
+typedef struct {
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+} rgb_t;
+
+typedef struct 
+{
+	int		version;
+	char		name[128];
+	char		altname[128];                   // texture substitution
+	char		animname[128];                  // next frame in animation chain
+	char		damagename[128];                // image that should be shown when damaged
+	unsigned	width[M32_MIP_LEVELS], height[M32_MIP_LEVELS];
+	unsigned	offsets[M32_MIP_LEVELS];
+	int		flags;
+	int		contents;
+	int		value;
+	float		scale_x, scale_y;
+	int		mip_scale;
+
+	// detail texturing info
+	char		dt_name[128];           // detailed texture name
+	float		dt_scale_x, dt_scale_y;
+	float		dt_u, dt_v;
+	float		dt_alpha;
+	int		dt_src_blend_mode, dt_dst_blend_mode;
+
+	int		unused[20];                             // future expansion to maintain compatibility with h2
+} m32_header_t;
+
+void LoadM32(const char *name, unsigned char **pic, int *width, int *height);
+
+
+#endif
diff --git a/plugins/imagem8/m8.h b/plugins/imagem8/m8.h
index da187eff..d3c1caec 100644
--- a/plugins/imagem8/m8.h
+++ b/plugins/imagem8/m8.h
@@ -1,61 +1,61 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _M8_H
-#define _M8_H
-
-#include "imagem8.h"
-
-#define M8_VERSION  	2
-#define PALETTE_SIZE	256
-#define MIP_LEVELS	16
-
-typedef struct {
-    unsigned char r;
-    unsigned char g;
-    unsigned char b;
-} rgb_t;
-
-typedef struct 
-{
-        int             version;
-        char            name[32];
-        unsigned        width[MIP_LEVELS], height[MIP_LEVELS];
-        unsigned        offsets[MIP_LEVELS];  
-        char            animname[32];       
-	rgb_t		palette[PALETTE_SIZE];
-        int             flags;
-        int             contents;
-        int             value;
-} m8_header_t;
-/*
-typedef struct {
-    int            bpp;
-    int            width;
-    int            height;
-    unsigned char *data;
-    rgb_t         *palette;
-} m8_t;
-*/
-void LoadM8(const char *name, unsigned char **pic, int *width, int *height);
-
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _M8_H
+#define _M8_H
+
+#include "imagem8.h"
+
+#define M8_VERSION  	2
+#define PALETTE_SIZE	256
+#define MIP_LEVELS	16
+
+typedef struct {
+    unsigned char r;
+    unsigned char g;
+    unsigned char b;
+} rgb_t;
+
+typedef struct 
+{
+        int             version;
+        char            name[32];
+        unsigned        width[MIP_LEVELS], height[MIP_LEVELS];
+        unsigned        offsets[MIP_LEVELS];  
+        char            animname[32];       
+	rgb_t		palette[PALETTE_SIZE];
+        int             flags;
+        int             contents;
+        int             value;
+} m8_header_t;
+/*
+typedef struct {
+    int            bpp;
+    int            width;
+    int            height;
+    unsigned char *data;
+    rgb_t         *palette;
+} m8_t;
+*/
+void LoadM8(const char *name, unsigned char **pic, int *width, int *height);
+
+
+#endif
diff --git a/plugins/imagepng/plugin.h b/plugins/imagepng/plugin.h
index e0ef4b2e..c52b50bb 100644
--- a/plugins/imagepng/plugin.h
+++ b/plugins/imagepng/plugin.h
@@ -1,31 +1,31 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-#include "qerplugin.h"
-#include "iimage.h"
-#include "ifilesystem.h"
-
-void LoadImage (const char *filename, unsigned char **pic, int *width, int *height);
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include "qerplugin.h"
+#include "iimage.h"
+#include "ifilesystem.h"
+
+void LoadImage (const char *filename, unsigned char **pic, int *width, int *height);
+
+#endif // _PLUGIN_H_
diff --git a/plugins/imagewal/imagewal.h b/plugins/imagewal/imagewal.h
index cf5332b0..b9c8081b 100644
--- a/plugins/imagewal/imagewal.h
+++ b/plugins/imagewal/imagewal.h
@@ -1,60 +1,60 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _IMAGEWAL_H_
-#define _IMAGEWAL_H_
-
-#include "synapse.h"
-#include "qerplugin.h"
-#include "ifilesystem.h"
-#include "iimage.h"
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERFileSystemTable g_FileSystemTable;
-void LoadWAL (const char *filename, unsigned char **pic, int *width, int *height);
-
-#define Error g_FuncTable.m_pfnError
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
-#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
-
-class CSynapseClientImage : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  bool OnActivate();
-  const char* GetName() { return "image"; }
-
-  CSynapseClientImage() { }
-  virtual ~CSynapseClientImage() { }
-};
-
-#endif // _IMAGEWAL_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _IMAGEWAL_H_
+#define _IMAGEWAL_H_
+
+#include "synapse.h"
+#include "qerplugin.h"
+#include "ifilesystem.h"
+#include "iimage.h"
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERFileSystemTable g_FileSystemTable;
+void LoadWAL (const char *filename, unsigned char **pic, int *width, int *height);
+
+#define Error g_FuncTable.m_pfnError
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
+#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
+
+class CSynapseClientImage : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  bool OnActivate();
+  const char* GetName() { return "image"; }
+
+  CSynapseClientImage() { }
+  virtual ~CSynapseClientImage() { }
+};
+
+#endif // _IMAGEWAL_H_
diff --git a/plugins/imagewal/q2_palette.h b/plugins/imagewal/q2_palette.h
index 7c0bb02f..7479d3c4 100644
--- a/plugins/imagewal/q2_palette.h
+++ b/plugins/imagewal/q2_palette.h
@@ -1,66 +1,66 @@
-unsigned char quake2_palette[256][3] = {
-{ 0x0, 0x0 , 0x0 }, { 0xF, 0xF , 0xF }, { 0x1F, 0x1F , 0x1F }, { 0x2F, 0x2F , 0x2F },
-{ 0x3F, 0x3F , 0x3F }, { 0x4B, 0x4B , 0x4B }, { 0x5B, 0x5B , 0x5B }, { 0x6B, 0x6B , 0x6B },
-{ 0x7B, 0x7B , 0x7B }, { 0x8B, 0x8B , 0x8B }, { 0x9B, 0x9B , 0x9B }, { 0xAB, 0xAB , 0xAB },
-{ 0xBB, 0xBB , 0xBB }, { 0xCB, 0xCB , 0xCB }, { 0xDB, 0xDB , 0xDB }, { 0xEB, 0xEB , 0xEB },
-{ 0x63, 0x4B , 0x23 }, { 0x5B, 0x43 , 0x1F }, { 0x53, 0x3F , 0x1F }, { 0x4F, 0x3B , 0x1B },
-{ 0x47, 0x37 , 0x1B }, { 0x3F, 0x2F , 0x17 }, { 0x3B, 0x2B , 0x17 }, { 0x33, 0x27 , 0x13 },
-{ 0x2F, 0x23 , 0x13 }, { 0x2B, 0x1F , 0x13 }, { 0x27, 0x1B , 0xF }, { 0x23, 0x17 , 0xF },
-{ 0x1B, 0x13 , 0xB }, { 0x17, 0xF , 0xB }, { 0x13, 0xF , 0x7 }, { 0xF, 0xB , 0x7 },
-{ 0x5F, 0x5F , 0x6F }, { 0x5B, 0x5B , 0x67 }, { 0x5B, 0x53 , 0x5F }, { 0x57, 0x4F , 0x5B },
-{ 0x53, 0x4B , 0x53 }, { 0x4F, 0x47 , 0x4B }, { 0x47, 0x3F , 0x43 }, { 0x3F, 0x3B , 0x3B },
-{ 0x3B, 0x37 , 0x37 }, { 0x33, 0x2F , 0x2F }, { 0x2F, 0x2B , 0x2B }, { 0x27, 0x27 , 0x27 },
-{ 0x23, 0x23 , 0x23 }, { 0x1B, 0x1B , 0x1B }, { 0x17, 0x17 , 0x17 }, { 0x13, 0x13 , 0x13 },
-{ 0x8F, 0x77 , 0x53 }, { 0x7B, 0x63 , 0x43 }, { 0x73, 0x5B , 0x3B }, { 0x67, 0x4F , 0x2F },
-{ 0xCF, 0x97 , 0x4B }, { 0xA7, 0x7B , 0x3B }, { 0x8B, 0x67 , 0x2F }, { 0x6F, 0x53 , 0x27 },
-{ 0xEB, 0x9F , 0x27 }, { 0xCB, 0x8B , 0x23 }, { 0xAF, 0x77 , 0x1F }, { 0x93, 0x63 , 0x1B },
-{ 0x77, 0x4F , 0x17 }, { 0x5B, 0x3B , 0xF }, { 0x3F, 0x27 , 0xB }, { 0x23, 0x17 , 0x7 },
-{ 0xA7, 0x3B , 0x2B }, { 0x9F, 0x2F , 0x23 }, { 0x97, 0x2B , 0x1B }, { 0x8B, 0x27 , 0x13 },
-{ 0x7F, 0x1F , 0xF }, { 0x73, 0x17 , 0xB }, { 0x67, 0x17 , 0x7 }, { 0x57, 0x13 , 0x0 },
-{ 0x4B, 0xF , 0x0 }, { 0x43, 0xF , 0x0 }, { 0x3B, 0xF , 0x0 }, { 0x33, 0xB , 0x0 },
-{ 0x2B, 0xB , 0x0 }, { 0x23, 0xB , 0x0 }, { 0x1B, 0x7 , 0x0 }, { 0x13, 0x7 , 0x0 },
-{ 0x7B, 0x5F , 0x4B }, { 0x73, 0x57 , 0x43 }, { 0x6B, 0x53 , 0x3F }, { 0x67, 0x4F , 0x3B },
-{ 0x5F, 0x47 , 0x37 }, { 0x57, 0x43 , 0x33 }, { 0x53, 0x3F , 0x2F }, { 0x4B, 0x37 , 0x2B },
-{ 0x43, 0x33 , 0x27 }, { 0x3F, 0x2F , 0x23 }, { 0x37, 0x27 , 0x1B }, { 0x2F, 0x23 , 0x17 },
-{ 0x27, 0x1B , 0x13 }, { 0x1F, 0x17 , 0xF }, { 0x17, 0xF , 0xB }, { 0xF, 0xB , 0x7 },
-{ 0x6F, 0x3B , 0x17 }, { 0x5F, 0x37 , 0x17 }, { 0x53, 0x2F , 0x17 }, { 0x43, 0x2B , 0x17 },
-{ 0x37, 0x23 , 0x13 }, { 0x27, 0x1B , 0xF }, { 0x1B, 0x13 , 0xB }, { 0xF, 0xB , 0x7 },
-{ 0xB3, 0x5B , 0x4F }, { 0xBF, 0x7B , 0x6F }, { 0xCB, 0x9B , 0x93 }, { 0xD7, 0xBB , 0xB7 },
-{ 0xCB, 0xD7 , 0xDF }, { 0xB3, 0xC7 , 0xD3 }, { 0x9F, 0xB7 , 0xC3 }, { 0x87, 0xA7 , 0xB7 },
-{ 0x73, 0x97 , 0xA7 }, { 0x5B, 0x87 , 0x9B }, { 0x47, 0x77 , 0x8B }, { 0x2F, 0x67 , 0x7F },
-{ 0x17, 0x53 , 0x6F }, { 0x13, 0x4B , 0x67 }, { 0xF, 0x43 , 0x5B }, { 0xB, 0x3F , 0x53 },
-{ 0x7, 0x37 , 0x4B }, { 0x7, 0x2F , 0x3F }, { 0x7, 0x27 , 0x33 }, { 0x0, 0x1F , 0x2B },
-{ 0x0, 0x17 , 0x1F }, { 0x0, 0xF , 0x13 }, { 0x0, 0x7 , 0xB }, { 0x0, 0x0 , 0x0 },
-{ 0x8B, 0x57 , 0x57 }, { 0x83, 0x4F , 0x4F }, { 0x7B, 0x47 , 0x47 }, { 0x73, 0x43 , 0x43 },
-{ 0x6B, 0x3B , 0x3B }, { 0x63, 0x33 , 0x33 }, { 0x5B, 0x2F , 0x2F }, { 0x57, 0x2B , 0x2B },
-{ 0x4B, 0x23 , 0x23 }, { 0x3F, 0x1F , 0x1F }, { 0x33, 0x1B , 0x1B }, { 0x2B, 0x13 , 0x13 },
-{ 0x1F, 0xF , 0xF }, { 0x13, 0xB , 0xB }, { 0xB, 0x7 , 0x7 }, { 0x0, 0x0 , 0x0 },
-{ 0x97, 0x9F , 0x7B }, { 0x8F, 0x97 , 0x73 }, { 0x87, 0x8B , 0x6B }, { 0x7F, 0x83 , 0x63 },
-{ 0x77, 0x7B , 0x5F }, { 0x73, 0x73 , 0x57 }, { 0x6B, 0x6B , 0x4F }, { 0x63, 0x63 , 0x47 },
-{ 0x5B, 0x5B , 0x43 }, { 0x4F, 0x4F , 0x3B }, { 0x43, 0x43 , 0x33 }, { 0x37, 0x37 , 0x2B },
-{ 0x2F, 0x2F , 0x23 }, { 0x23, 0x23 , 0x1B }, { 0x17, 0x17 , 0x13 }, { 0xF, 0xF , 0xB },
-{ 0x9F, 0x4B , 0x3F }, { 0x93, 0x43 , 0x37 }, { 0x8B, 0x3B , 0x2F }, { 0x7F, 0x37 , 0x27 },
-{ 0x77, 0x2F , 0x23 }, { 0x6B, 0x2B , 0x1B }, { 0x63, 0x23 , 0x17 }, { 0x57, 0x1F , 0x13 },
-{ 0x4F, 0x1B , 0xF }, { 0x43, 0x17 , 0xB }, { 0x37, 0x13 , 0xB }, { 0x2B, 0xF , 0x7 },
-{ 0x1F, 0xB , 0x7 }, { 0x17, 0x7 , 0x0 }, { 0xB, 0x0 , 0x0 }, { 0x0, 0x0 , 0x0 },
-{ 0x77, 0x7B , 0xCF }, { 0x6F, 0x73 , 0xC3 }, { 0x67, 0x6B , 0xB7 }, { 0x63, 0x63 , 0xA7 },
-{ 0x5B, 0x5B , 0x9B }, { 0x53, 0x57 , 0x8F }, { 0x4B, 0x4F , 0x7F }, { 0x47, 0x47 , 0x73 },
-{ 0x3F, 0x3F , 0x67 }, { 0x37, 0x37 , 0x57 }, { 0x2F, 0x2F , 0x4B }, { 0x27, 0x27 , 0x3F },
-{ 0x23, 0x1F , 0x2F }, { 0x1B, 0x17 , 0x23 }, { 0x13, 0xF , 0x17 }, { 0xB, 0x7 , 0x7 },
-{ 0x9B, 0xAB , 0x7B }, { 0x8F, 0x9F , 0x6F }, { 0x87, 0x97 , 0x63 }, { 0x7B, 0x8B , 0x57 },
-{ 0x73, 0x83 , 0x4B }, { 0x67, 0x77 , 0x43 }, { 0x5F, 0x6F , 0x3B }, { 0x57, 0x67 , 0x33 },
-{ 0x4B, 0x5B , 0x27 }, { 0x3F, 0x4F , 0x1B }, { 0x37, 0x43 , 0x13 }, { 0x2F, 0x3B , 0xB },
-{ 0x23, 0x2F , 0x7 }, { 0x1B, 0x23 , 0x0 }, { 0x13, 0x17 , 0x0 }, { 0xB, 0xF , 0x0 },
-{ 0x0, 0xFF , 0x0 }, { 0x23, 0xE7 , 0xF }, { 0x3F, 0xD3 , 0x1B }, { 0x53, 0xBB , 0x27 },
-{ 0x5F, 0xA7 , 0x2F }, { 0x5F, 0x8F , 0x33 }, { 0x5F, 0x7B , 0x33 }, { 0xFF, 0xFF , 0xFF },
-{ 0xFF, 0xFF , 0xD3 }, { 0xFF, 0xFF , 0xA7 }, { 0xFF, 0xFF , 0x7F }, { 0xFF, 0xFF , 0x53 },
-{ 0xFF, 0xFF , 0x27 }, { 0xFF, 0xEB , 0x1F }, { 0xFF, 0xD7 , 0x17 }, { 0xFF, 0xBF , 0xF },
-{ 0xFF, 0xAB , 0x7 }, { 0xFF, 0x93 , 0x0 }, { 0xEF, 0x7F , 0x0 }, { 0xE3, 0x6B , 0x0 },
-{ 0xD3, 0x57 , 0x0 }, { 0xC7, 0x47 , 0x0 }, { 0xB7, 0x3B , 0x0 }, { 0xAB, 0x2B , 0x0 },
-{ 0x9B, 0x1F , 0x0 }, { 0x8F, 0x17 , 0x0 }, { 0x7F, 0xF , 0x0 }, { 0x73, 0x7 , 0x0 },
-{ 0x5F, 0x0 , 0x0 }, { 0x47, 0x0 , 0x0 }, { 0x2F, 0x0 , 0x0 }, { 0x1B, 0x0 , 0x0 },
-{ 0xEF, 0x0 , 0x0 }, { 0x37, 0x37 , 0xFF }, { 0xFF, 0x0 , 0x0 }, { 0x0, 0x0 , 0xFF },
-{ 0x2B, 0x2B , 0x23 }, { 0x1B, 0x1B , 0x17 }, { 0x13, 0x13 , 0xF }, { 0xEB, 0x97 , 0x7F },
-{ 0xC3, 0x73 , 0x53 }, { 0x9F, 0x57 , 0x33 }, { 0x7B, 0x3F , 0x1B }, { 0xEB, 0xD3 , 0xC7 },
-{ 0xC7, 0xAB , 0x9B }, { 0xA7, 0x8B , 0x77 }, { 0x87, 0x6B , 0x57 }, { 0x9F, 0x5B , 0x53 }
-};
+unsigned char quake2_palette[256][3] = {
+{ 0x0, 0x0 , 0x0 }, { 0xF, 0xF , 0xF }, { 0x1F, 0x1F , 0x1F }, { 0x2F, 0x2F , 0x2F },
+{ 0x3F, 0x3F , 0x3F }, { 0x4B, 0x4B , 0x4B }, { 0x5B, 0x5B , 0x5B }, { 0x6B, 0x6B , 0x6B },
+{ 0x7B, 0x7B , 0x7B }, { 0x8B, 0x8B , 0x8B }, { 0x9B, 0x9B , 0x9B }, { 0xAB, 0xAB , 0xAB },
+{ 0xBB, 0xBB , 0xBB }, { 0xCB, 0xCB , 0xCB }, { 0xDB, 0xDB , 0xDB }, { 0xEB, 0xEB , 0xEB },
+{ 0x63, 0x4B , 0x23 }, { 0x5B, 0x43 , 0x1F }, { 0x53, 0x3F , 0x1F }, { 0x4F, 0x3B , 0x1B },
+{ 0x47, 0x37 , 0x1B }, { 0x3F, 0x2F , 0x17 }, { 0x3B, 0x2B , 0x17 }, { 0x33, 0x27 , 0x13 },
+{ 0x2F, 0x23 , 0x13 }, { 0x2B, 0x1F , 0x13 }, { 0x27, 0x1B , 0xF }, { 0x23, 0x17 , 0xF },
+{ 0x1B, 0x13 , 0xB }, { 0x17, 0xF , 0xB }, { 0x13, 0xF , 0x7 }, { 0xF, 0xB , 0x7 },
+{ 0x5F, 0x5F , 0x6F }, { 0x5B, 0x5B , 0x67 }, { 0x5B, 0x53 , 0x5F }, { 0x57, 0x4F , 0x5B },
+{ 0x53, 0x4B , 0x53 }, { 0x4F, 0x47 , 0x4B }, { 0x47, 0x3F , 0x43 }, { 0x3F, 0x3B , 0x3B },
+{ 0x3B, 0x37 , 0x37 }, { 0x33, 0x2F , 0x2F }, { 0x2F, 0x2B , 0x2B }, { 0x27, 0x27 , 0x27 },
+{ 0x23, 0x23 , 0x23 }, { 0x1B, 0x1B , 0x1B }, { 0x17, 0x17 , 0x17 }, { 0x13, 0x13 , 0x13 },
+{ 0x8F, 0x77 , 0x53 }, { 0x7B, 0x63 , 0x43 }, { 0x73, 0x5B , 0x3B }, { 0x67, 0x4F , 0x2F },
+{ 0xCF, 0x97 , 0x4B }, { 0xA7, 0x7B , 0x3B }, { 0x8B, 0x67 , 0x2F }, { 0x6F, 0x53 , 0x27 },
+{ 0xEB, 0x9F , 0x27 }, { 0xCB, 0x8B , 0x23 }, { 0xAF, 0x77 , 0x1F }, { 0x93, 0x63 , 0x1B },
+{ 0x77, 0x4F , 0x17 }, { 0x5B, 0x3B , 0xF }, { 0x3F, 0x27 , 0xB }, { 0x23, 0x17 , 0x7 },
+{ 0xA7, 0x3B , 0x2B }, { 0x9F, 0x2F , 0x23 }, { 0x97, 0x2B , 0x1B }, { 0x8B, 0x27 , 0x13 },
+{ 0x7F, 0x1F , 0xF }, { 0x73, 0x17 , 0xB }, { 0x67, 0x17 , 0x7 }, { 0x57, 0x13 , 0x0 },
+{ 0x4B, 0xF , 0x0 }, { 0x43, 0xF , 0x0 }, { 0x3B, 0xF , 0x0 }, { 0x33, 0xB , 0x0 },
+{ 0x2B, 0xB , 0x0 }, { 0x23, 0xB , 0x0 }, { 0x1B, 0x7 , 0x0 }, { 0x13, 0x7 , 0x0 },
+{ 0x7B, 0x5F , 0x4B }, { 0x73, 0x57 , 0x43 }, { 0x6B, 0x53 , 0x3F }, { 0x67, 0x4F , 0x3B },
+{ 0x5F, 0x47 , 0x37 }, { 0x57, 0x43 , 0x33 }, { 0x53, 0x3F , 0x2F }, { 0x4B, 0x37 , 0x2B },
+{ 0x43, 0x33 , 0x27 }, { 0x3F, 0x2F , 0x23 }, { 0x37, 0x27 , 0x1B }, { 0x2F, 0x23 , 0x17 },
+{ 0x27, 0x1B , 0x13 }, { 0x1F, 0x17 , 0xF }, { 0x17, 0xF , 0xB }, { 0xF, 0xB , 0x7 },
+{ 0x6F, 0x3B , 0x17 }, { 0x5F, 0x37 , 0x17 }, { 0x53, 0x2F , 0x17 }, { 0x43, 0x2B , 0x17 },
+{ 0x37, 0x23 , 0x13 }, { 0x27, 0x1B , 0xF }, { 0x1B, 0x13 , 0xB }, { 0xF, 0xB , 0x7 },
+{ 0xB3, 0x5B , 0x4F }, { 0xBF, 0x7B , 0x6F }, { 0xCB, 0x9B , 0x93 }, { 0xD7, 0xBB , 0xB7 },
+{ 0xCB, 0xD7 , 0xDF }, { 0xB3, 0xC7 , 0xD3 }, { 0x9F, 0xB7 , 0xC3 }, { 0x87, 0xA7 , 0xB7 },
+{ 0x73, 0x97 , 0xA7 }, { 0x5B, 0x87 , 0x9B }, { 0x47, 0x77 , 0x8B }, { 0x2F, 0x67 , 0x7F },
+{ 0x17, 0x53 , 0x6F }, { 0x13, 0x4B , 0x67 }, { 0xF, 0x43 , 0x5B }, { 0xB, 0x3F , 0x53 },
+{ 0x7, 0x37 , 0x4B }, { 0x7, 0x2F , 0x3F }, { 0x7, 0x27 , 0x33 }, { 0x0, 0x1F , 0x2B },
+{ 0x0, 0x17 , 0x1F }, { 0x0, 0xF , 0x13 }, { 0x0, 0x7 , 0xB }, { 0x0, 0x0 , 0x0 },
+{ 0x8B, 0x57 , 0x57 }, { 0x83, 0x4F , 0x4F }, { 0x7B, 0x47 , 0x47 }, { 0x73, 0x43 , 0x43 },
+{ 0x6B, 0x3B , 0x3B }, { 0x63, 0x33 , 0x33 }, { 0x5B, 0x2F , 0x2F }, { 0x57, 0x2B , 0x2B },
+{ 0x4B, 0x23 , 0x23 }, { 0x3F, 0x1F , 0x1F }, { 0x33, 0x1B , 0x1B }, { 0x2B, 0x13 , 0x13 },
+{ 0x1F, 0xF , 0xF }, { 0x13, 0xB , 0xB }, { 0xB, 0x7 , 0x7 }, { 0x0, 0x0 , 0x0 },
+{ 0x97, 0x9F , 0x7B }, { 0x8F, 0x97 , 0x73 }, { 0x87, 0x8B , 0x6B }, { 0x7F, 0x83 , 0x63 },
+{ 0x77, 0x7B , 0x5F }, { 0x73, 0x73 , 0x57 }, { 0x6B, 0x6B , 0x4F }, { 0x63, 0x63 , 0x47 },
+{ 0x5B, 0x5B , 0x43 }, { 0x4F, 0x4F , 0x3B }, { 0x43, 0x43 , 0x33 }, { 0x37, 0x37 , 0x2B },
+{ 0x2F, 0x2F , 0x23 }, { 0x23, 0x23 , 0x1B }, { 0x17, 0x17 , 0x13 }, { 0xF, 0xF , 0xB },
+{ 0x9F, 0x4B , 0x3F }, { 0x93, 0x43 , 0x37 }, { 0x8B, 0x3B , 0x2F }, { 0x7F, 0x37 , 0x27 },
+{ 0x77, 0x2F , 0x23 }, { 0x6B, 0x2B , 0x1B }, { 0x63, 0x23 , 0x17 }, { 0x57, 0x1F , 0x13 },
+{ 0x4F, 0x1B , 0xF }, { 0x43, 0x17 , 0xB }, { 0x37, 0x13 , 0xB }, { 0x2B, 0xF , 0x7 },
+{ 0x1F, 0xB , 0x7 }, { 0x17, 0x7 , 0x0 }, { 0xB, 0x0 , 0x0 }, { 0x0, 0x0 , 0x0 },
+{ 0x77, 0x7B , 0xCF }, { 0x6F, 0x73 , 0xC3 }, { 0x67, 0x6B , 0xB7 }, { 0x63, 0x63 , 0xA7 },
+{ 0x5B, 0x5B , 0x9B }, { 0x53, 0x57 , 0x8F }, { 0x4B, 0x4F , 0x7F }, { 0x47, 0x47 , 0x73 },
+{ 0x3F, 0x3F , 0x67 }, { 0x37, 0x37 , 0x57 }, { 0x2F, 0x2F , 0x4B }, { 0x27, 0x27 , 0x3F },
+{ 0x23, 0x1F , 0x2F }, { 0x1B, 0x17 , 0x23 }, { 0x13, 0xF , 0x17 }, { 0xB, 0x7 , 0x7 },
+{ 0x9B, 0xAB , 0x7B }, { 0x8F, 0x9F , 0x6F }, { 0x87, 0x97 , 0x63 }, { 0x7B, 0x8B , 0x57 },
+{ 0x73, 0x83 , 0x4B }, { 0x67, 0x77 , 0x43 }, { 0x5F, 0x6F , 0x3B }, { 0x57, 0x67 , 0x33 },
+{ 0x4B, 0x5B , 0x27 }, { 0x3F, 0x4F , 0x1B }, { 0x37, 0x43 , 0x13 }, { 0x2F, 0x3B , 0xB },
+{ 0x23, 0x2F , 0x7 }, { 0x1B, 0x23 , 0x0 }, { 0x13, 0x17 , 0x0 }, { 0xB, 0xF , 0x0 },
+{ 0x0, 0xFF , 0x0 }, { 0x23, 0xE7 , 0xF }, { 0x3F, 0xD3 , 0x1B }, { 0x53, 0xBB , 0x27 },
+{ 0x5F, 0xA7 , 0x2F }, { 0x5F, 0x8F , 0x33 }, { 0x5F, 0x7B , 0x33 }, { 0xFF, 0xFF , 0xFF },
+{ 0xFF, 0xFF , 0xD3 }, { 0xFF, 0xFF , 0xA7 }, { 0xFF, 0xFF , 0x7F }, { 0xFF, 0xFF , 0x53 },
+{ 0xFF, 0xFF , 0x27 }, { 0xFF, 0xEB , 0x1F }, { 0xFF, 0xD7 , 0x17 }, { 0xFF, 0xBF , 0xF },
+{ 0xFF, 0xAB , 0x7 }, { 0xFF, 0x93 , 0x0 }, { 0xEF, 0x7F , 0x0 }, { 0xE3, 0x6B , 0x0 },
+{ 0xD3, 0x57 , 0x0 }, { 0xC7, 0x47 , 0x0 }, { 0xB7, 0x3B , 0x0 }, { 0xAB, 0x2B , 0x0 },
+{ 0x9B, 0x1F , 0x0 }, { 0x8F, 0x17 , 0x0 }, { 0x7F, 0xF , 0x0 }, { 0x73, 0x7 , 0x0 },
+{ 0x5F, 0x0 , 0x0 }, { 0x47, 0x0 , 0x0 }, { 0x2F, 0x0 , 0x0 }, { 0x1B, 0x0 , 0x0 },
+{ 0xEF, 0x0 , 0x0 }, { 0x37, 0x37 , 0xFF }, { 0xFF, 0x0 , 0x0 }, { 0x0, 0x0 , 0xFF },
+{ 0x2B, 0x2B , 0x23 }, { 0x1B, 0x1B , 0x17 }, { 0x13, 0x13 , 0xF }, { 0xEB, 0x97 , 0x7F },
+{ 0xC3, 0x73 , 0x53 }, { 0x9F, 0x57 , 0x33 }, { 0x7B, 0x3F , 0x1B }, { 0xEB, 0xD3 , 0xC7 },
+{ 0xC7, 0xAB , 0x9B }, { 0xA7, 0x8B , 0x77 }, { 0x87, 0x6B , 0x57 }, { 0x9F, 0x5B , 0x53 }
+};
diff --git a/plugins/imagewal/wal.h b/plugins/imagewal/wal.h
index 40b1778b..a0afcbc0 100644
--- a/plugins/imagewal/wal.h
+++ b/plugins/imagewal/wal.h
@@ -1,51 +1,51 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _WAL_H
-#define _WAL_H
-
-#include "imagewal.h"
-
-#define PALETTE_SIZE	256
-#define	MIPLEVELS	4
-
-typedef struct {
-  unsigned char r;
-  unsigned char g;
-  unsigned char b;
-} rgb_t;
-
-
-typedef struct miptex_s
-{
-	char		name[32];
-	unsigned	width, height;
-	unsigned	offsets[MIPLEVELS];		// four mip maps stored
-	char		animname[32];			// next frame in animation chain
-	int			flags;
-	int			contents;
-	int			value;
-} miptex_t;
-
-void LoadWAL(const char *name, unsigned char **pic, int *width, int *height);
-
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _WAL_H
+#define _WAL_H
+
+#include "imagewal.h"
+
+#define PALETTE_SIZE	256
+#define	MIPLEVELS	4
+
+typedef struct {
+  unsigned char r;
+  unsigned char g;
+  unsigned char b;
+} rgb_t;
+
+
+typedef struct miptex_s
+{
+	char		name[32];
+	unsigned	width, height;
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+	char		animname[32];			// next frame in animation chain
+	int			flags;
+	int			contents;
+	int			value;
+} miptex_t;
+
+void LoadWAL(const char *name, unsigned char **pic, int *width, int *height);
+
+
+#endif
diff --git a/plugins/map/plugin.h b/plugins/map/plugin.h
index 89e586b0..e568135e 100644
--- a/plugins/map/plugin.h
+++ b/plugins/map/plugin.h
@@ -1,92 +1,92 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "synapse.h"
-
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#define USE_VFSTABLE_DEFINE
-#define USE_SCRIPLIBTABLE_DEFINE
-#include "iscriplib.h"
-#include "imap.h"
-#include "ishaders.h"
-#define USE_ENTITYTABLE_DEFINE
-#include "ientity.h"
-#define USE_BRUSHTABLE_DEFINE
-#include "ibrush.h"
-#define USE_PATCHTABLE_DEFINE
-#include "ipatch.h"
-#define USE_VFSTABLE_DEFINE
-#include "ifilesystem.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERScripLibTable g_ScripLibTable;
-extern _QERShadersTable g_ShadersTable;
-extern _QEREntityTable __ENTITYTABLENAME;
-extern _QERBrushTable g_BrushTable;
-extern _QERPatchTable g_PatchTable;
-extern _QERFileSystemTable g_FileSystemTable;
-
-#define Error g_FuncTable.m_pfnError
-#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
-
-// a bunch of globals to the module
-extern void *g_pRadiantWnd;
-
-#define MAPVERSION_Q3 1
-#define MAPVERSION_HL 2
-#define MAPVERSION_Q2 3
-//#define MAPVERSION_Q1
-
-#define MAP_NOERROR 0
-#define MAP_ABORTED 1
-#define MAP_WRONGVERSION 2
-
-void Map_ReadQ3 (IDataStream *in, CPtrArray *map);
-void Map_WriteQ3 (CPtrArray *map, IDataStream *out);
-void Map_ReadHL (IDataStream *in, CPtrArray *map);
-void Map_WriteHL (CPtrArray *map, IDataStream *out);
-void Map_ReadQ2 (IDataStream *in, CPtrArray *map);
-void Map_WriteQ2 (CPtrArray *map, IDataStream *out);
-
-extern CSynapseServer* g_pSynapseServer;
-
-class CSynapseClientMap : public CSynapseClient
-{
-  bool mbMapHL;
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName(); ///< required for runtime configuration
-  bool OnActivate();
-  
-  CSynapseClientMap() { mbMapHL = false; }
-  virtual ~CSynapseClientMap() { }
-};
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "synapse.h"
+
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#define USE_VFSTABLE_DEFINE
+#define USE_SCRIPLIBTABLE_DEFINE
+#include "iscriplib.h"
+#include "imap.h"
+#include "ishaders.h"
+#define USE_ENTITYTABLE_DEFINE
+#include "ientity.h"
+#define USE_BRUSHTABLE_DEFINE
+#include "ibrush.h"
+#define USE_PATCHTABLE_DEFINE
+#include "ipatch.h"
+#define USE_VFSTABLE_DEFINE
+#include "ifilesystem.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERScripLibTable g_ScripLibTable;
+extern _QERShadersTable g_ShadersTable;
+extern _QEREntityTable __ENTITYTABLENAME;
+extern _QERBrushTable g_BrushTable;
+extern _QERPatchTable g_PatchTable;
+extern _QERFileSystemTable g_FileSystemTable;
+
+#define Error g_FuncTable.m_pfnError
+#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
+
+// a bunch of globals to the module
+extern void *g_pRadiantWnd;
+
+#define MAPVERSION_Q3 1
+#define MAPVERSION_HL 2
+#define MAPVERSION_Q2 3
+//#define MAPVERSION_Q1
+
+#define MAP_NOERROR 0
+#define MAP_ABORTED 1
+#define MAP_WRONGVERSION 2
+
+void Map_ReadQ3 (IDataStream *in, CPtrArray *map);
+void Map_WriteQ3 (CPtrArray *map, IDataStream *out);
+void Map_ReadHL (IDataStream *in, CPtrArray *map);
+void Map_WriteHL (CPtrArray *map, IDataStream *out);
+void Map_ReadQ2 (IDataStream *in, CPtrArray *map);
+void Map_WriteQ2 (CPtrArray *map, IDataStream *out);
+
+extern CSynapseServer* g_pSynapseServer;
+
+class CSynapseClientMap : public CSynapseClient
+{
+  bool mbMapHL;
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName(); ///< required for runtime configuration
+  bool OnActivate();
+  
+  CSynapseClientMap() { mbMapHL = false; }
+  virtual ~CSynapseClientMap() { }
+};
+
+#endif // _PLUGIN_H_
diff --git a/plugins/mapxml/plugin.h b/plugins/mapxml/plugin.h
index 4529a651..a129b400 100644
--- a/plugins/mapxml/plugin.h
+++ b/plugins/mapxml/plugin.h
@@ -1,49 +1,49 @@
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-#include <stdlib.h>
-#include <stdio.h>
-
-#include "libxml/parser.h"
-
-#include "synapse.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#include "imap.h"
-#include "ishaders.h"
-#define USE_ENTITYTABLE_DEFINE
-#include "ientity.h"
-#define USE_BRUSHTABLE_DEFINE
-#include "ibrush.h"
-#define USE_PATCHTABLE_DEFINE
-#include "ipatch.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERShadersTable g_ShadersTable;
-extern _QEREntityTable g_EntityTable;
-extern _QERBrushTable g_BrushTable;
-extern _QERPatchTable g_PatchTable;
-
-#define Error g_FuncTable.m_pfnError
-#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
-
-extern void *g_pRadiantWnd;
-
-void Map_Read (IDataStream *in, CPtrArray *map);
-void Map_Write (CPtrArray *map, IDataStream *out);
-
-extern CSynapseServer* g_pSynapseServer;
-
-class CSynapseClientXMap : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName(); ///< required for XML runtime config
-  
-  CSynapseClientXMap() { }
-  virtual ~CSynapseClientXMap() { }
-};
-
-#endif // _PLUGIN_H_
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "libxml/parser.h"
+
+#include "synapse.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#include "imap.h"
+#include "ishaders.h"
+#define USE_ENTITYTABLE_DEFINE
+#include "ientity.h"
+#define USE_BRUSHTABLE_DEFINE
+#include "ibrush.h"
+#define USE_PATCHTABLE_DEFINE
+#include "ipatch.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERShadersTable g_ShadersTable;
+extern _QEREntityTable g_EntityTable;
+extern _QERBrushTable g_BrushTable;
+extern _QERPatchTable g_PatchTable;
+
+#define Error g_FuncTable.m_pfnError
+#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
+
+extern void *g_pRadiantWnd;
+
+void Map_Read (IDataStream *in, CPtrArray *map);
+void Map_Write (CPtrArray *map, IDataStream *out);
+
+extern CSynapseServer* g_pSynapseServer;
+
+class CSynapseClientXMap : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName(); ///< required for XML runtime config
+  
+  CSynapseClientXMap() { }
+  virtual ~CSynapseClientXMap() { }
+};
+
+#endif // _PLUGIN_H_
diff --git a/plugins/model/cpicomodel.h b/plugins/model/cpicomodel.h
index 13ebfe1e..938cede0 100644
--- a/plugins/model/cpicomodel.h
+++ b/plugins/model/cpicomodel.h
@@ -1,94 +1,94 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _CPICOMODEL_H_
-#define _CPICOMODEL_H_
-
-#include "plugin.h"
-#include "picomodel.h"
-
-#include "gtkr_vector.h"
-
-class CPicoParent
-{
-public:
-  virtual void UpdateShaders( void ) = 0;
-};
-
-class CModelManager;  // forward declaration
-
-//typedef std::pair<Str, int> PicoModelKey;
-typedef pair<Str, int> PicoModelKey;
-
-class CPicoModel : public IRender, public ISelect
-{
-  friend class CModelManager;
-public:
-  CPicoModel(const PicoModelKey& key);
-  CPicoModel(const Str& name);
-  CPicoModel(const Str& name, const int frame);
-	CPicoModel(const char *name, const int frame);
-	~CPicoModel(); 
-  void CPicoModel::load(const char *name, const int frame);
-	
-  void IncRef()
-  {
-    ++m_refcount;
-  }
-  void DecRef()
-  {
-    if(--m_refcount == 0)
-      delete this;
-  }
-
-  void AddParent( CPicoParent *parent );
-  void RemoveParent( CPicoParent *parent );
-
-  void Reload( void );
-
-  void Draw(int state, vector<IShader*> shaders, int rflags) const;
-  //IRender
-  virtual void Draw( int state, int rflags ) const;
-  virtual const aabb_t *GetAABB() const { return &m_BBox; }
-
-  //ISelect
-  virtual bool TestRay( const ray_t *ray, vec_t *dist ) const;
-
-  int GetNumSurfaces( void );
-  char *GetShaderNameForSurface( const unsigned int surf );
-
-private:
-	void AccumulateBBox();
-
-  char *m_name;
-  int m_frame;
-  picoModel_t *m_pModel;
-  unsigned int m_refcount;
-	aabb_t m_BBox;
-  GPtrArray *m_children; // array of CPicoSurface
-  GPtrArray *m_parents; // array of CPicoParent
-
-  GPtrArray* m_shaders;
-
-  bool m_bReloaded; // managed by CModelManager
-};
-
-#endif // _CPICOMODEL_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CPICOMODEL_H_
+#define _CPICOMODEL_H_
+
+#include "plugin.h"
+#include "picomodel.h"
+
+#include "gtkr_vector.h"
+
+class CPicoParent
+{
+public:
+  virtual void UpdateShaders( void ) = 0;
+};
+
+class CModelManager;  // forward declaration
+
+//typedef std::pair<Str, int> PicoModelKey;
+typedef pair<Str, int> PicoModelKey;
+
+class CPicoModel : public IRender, public ISelect
+{
+  friend class CModelManager;
+public:
+  CPicoModel(const PicoModelKey& key);
+  CPicoModel(const Str& name);
+  CPicoModel(const Str& name, const int frame);
+	CPicoModel(const char *name, const int frame);
+	~CPicoModel(); 
+  void CPicoModel::load(const char *name, const int frame);
+	
+  void IncRef()
+  {
+    ++m_refcount;
+  }
+  void DecRef()
+  {
+    if(--m_refcount == 0)
+      delete this;
+  }
+
+  void AddParent( CPicoParent *parent );
+  void RemoveParent( CPicoParent *parent );
+
+  void Reload( void );
+
+  void Draw(int state, vector<IShader*> shaders, int rflags) const;
+  //IRender
+  virtual void Draw( int state, int rflags ) const;
+  virtual const aabb_t *GetAABB() const { return &m_BBox; }
+
+  //ISelect
+  virtual bool TestRay( const ray_t *ray, vec_t *dist ) const;
+
+  int GetNumSurfaces( void );
+  char *GetShaderNameForSurface( const unsigned int surf );
+
+private:
+	void AccumulateBBox();
+
+  char *m_name;
+  int m_frame;
+  picoModel_t *m_pModel;
+  unsigned int m_refcount;
+	aabb_t m_BBox;
+  GPtrArray *m_children; // array of CPicoSurface
+  GPtrArray *m_parents; // array of CPicoParent
+
+  GPtrArray* m_shaders;
+
+  bool m_bReloaded; // managed by CModelManager
+};
+
+#endif // _CPICOMODEL_H_
diff --git a/plugins/model/cpicosurface.h b/plugins/model/cpicosurface.h
index 51f6d7fc..41f523d2 100644
--- a/plugins/model/cpicosurface.h
+++ b/plugins/model/cpicosurface.h
@@ -1,55 +1,55 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "plugin.h"
-#include "picomodel.h"
-
-/*! Largest (potentially) selectable leaf of a Pico model */
-class CPicoSurface
-{
-public:
-	CPicoSurface(picoSurface_t *surf); // creates a new surface from a picoSurface_t
-	~CPicoSurface();
-	
-  void IncRef() { refCount++; }
-  void DecRef() { if(--refCount == 0) delete this; }
-
-	void Draw(int state, IShader *pShader, int rflags);
-  //IRender
-	void Draw(int state, int rflags);
-  const aabb_t *GetAABB() const { return &m_BBox; }
-
-  //ISelect
-  bool TestRay (const ray_t *ray, vec_t *dist) const;
-
-  char *GetShaderName( void )
-  {
-    return PicoGetShaderName(m_pSurface->shader);
-  }
-
-private:
-  int refCount;
-	aabb_t m_BBox;
-  picoSurface_t *m_pSurface;
-  IShader* m_shader;
-
-	void AccumulateBBox(); // accumulate local bbox.. generally created from control handles
-};
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "plugin.h"
+#include "picomodel.h"
+
+/*! Largest (potentially) selectable leaf of a Pico model */
+class CPicoSurface
+{
+public:
+	CPicoSurface(picoSurface_t *surf); // creates a new surface from a picoSurface_t
+	~CPicoSurface();
+	
+  void IncRef() { refCount++; }
+  void DecRef() { if(--refCount == 0) delete this; }
+
+	void Draw(int state, IShader *pShader, int rflags);
+  //IRender
+	void Draw(int state, int rflags);
+  const aabb_t *GetAABB() const { return &m_BBox; }
+
+  //ISelect
+  bool TestRay (const ray_t *ray, vec_t *dist) const;
+
+  char *GetShaderName( void )
+  {
+    return PicoGetShaderName(m_pSurface->shader);
+  }
+
+private:
+  int refCount;
+	aabb_t m_BBox;
+  picoSurface_t *m_pSurface;
+  IShader* m_shader;
+
+	void AccumulateBBox(); // accumulate local bbox.. generally created from control handles
+};
diff --git a/plugins/model/plugin.h b/plugins/model/plugin.h
index 06158646..b2ccccda 100644
--- a/plugins/model/plugin.h
+++ b/plugins/model/plugin.h
@@ -1,76 +1,76 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-/*!
-\todo need general notice about lib purpose etc.
-and the external dependencies (such as GLib, STL, mathlib etc.)
-*/
-
-/*!
-\todo not sure about what should be used for common data structures, GLib or STL
-I think STL would be better since I intend on using STL in synapse
-*/
-
-#include <stdio.h>
-
-#include "synapse.h"
-#include "iplugin.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#include "imodel.h"
-#include "igl.h"
-#include "ifilesystem.h"
-#include "ishaders.h"
-#include "itoolbar.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERQglTable g_QglTable;
-extern _QERShadersTable g_ShadersTable;
-extern _QERFileSystemTable g_FileSystemTable;
-
-#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
-#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
-#define vfsBasePromptPath g_FileSystemTable.m_pfnBasePromptPath
-#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
-
-void DoFlushReloadSelected();
-void DoFlushReloadAll();
-
-void LoadModel(entity_interfaces_t *model, const char *name);
-
-extern CSynapseServer* g_pSynapseServer;
-
-class CSynapseClientModel : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName();
-  
-  CSynapseClientModel() { }
-  virtual ~CSynapseClientModel() { }
-};
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+/*!
+\todo need general notice about lib purpose etc.
+and the external dependencies (such as GLib, STL, mathlib etc.)
+*/
+
+/*!
+\todo not sure about what should be used for common data structures, GLib or STL
+I think STL would be better since I intend on using STL in synapse
+*/
+
+#include <stdio.h>
+
+#include "synapse.h"
+#include "iplugin.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#include "imodel.h"
+#include "igl.h"
+#include "ifilesystem.h"
+#include "ishaders.h"
+#include "itoolbar.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERQglTable g_QglTable;
+extern _QERShadersTable g_ShadersTable;
+extern _QERFileSystemTable g_FileSystemTable;
+
+#define vfsLoadFile g_FileSystemTable.m_pfnLoadFile
+#define vfsFreeFile g_FileSystemTable.m_pfnFreeFile
+#define vfsBasePromptPath g_FileSystemTable.m_pfnBasePromptPath
+#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
+
+void DoFlushReloadSelected();
+void DoFlushReloadAll();
+
+void LoadModel(entity_interfaces_t *model, const char *name);
+
+extern CSynapseServer* g_pSynapseServer;
+
+class CSynapseClientModel : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName();
+  
+  CSynapseClientModel() { }
+  virtual ~CSynapseClientModel() { }
+};
+
+#endif // _PLUGIN_H_
diff --git a/plugins/model/surface.h b/plugins/model/surface.h
index 33c5d2f7..43d9b276 100644
--- a/plugins/model/surface.h
+++ b/plugins/model/surface.h
@@ -1,38 +1,38 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-class CSurface : public ISurface
-{
-public:
-  CSurface() { refCount = 0; aabb_clear(&m_BBox); m_pShader = NULL; }
-  ~CSurface() { if(m_pShader != NULL) m_pShader->DecRef(); }
-	void IncRef() { refCount++; }
-	void DecRef() { if ( --refCount <= 0 ) delete this; }
-
-  const aabb_t *getBBox() const { return &m_BBox; }
-  IShader *getShader() const { return m_pShader; }
-  void setShader(const char *name) { if (getShader()) getShader()->DecRef(); m_pShader = QERApp_Shader_ForName(name); getShader()->IncRef(); }
-
-protected:
-	int refCount;
-	aabb_t m_BBox;
-	IShader *m_pShader;
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+class CSurface : public ISurface
+{
+public:
+  CSurface() { refCount = 0; aabb_clear(&m_BBox); m_pShader = NULL; }
+  ~CSurface() { if(m_pShader != NULL) m_pShader->DecRef(); }
+	void IncRef() { refCount++; }
+	void DecRef() { if ( --refCount <= 0 ) delete this; }
+
+  const aabb_t *getBBox() const { return &m_BBox; }
+  IShader *getShader() const { return m_pShader; }
+  void setShader(const char *name) { if (getShader()) getShader()->DecRef(); m_pShader = QERApp_Shader_ForName(name); getShader()->IncRef(); }
+
+protected:
+	int refCount;
+	aabb_t m_BBox;
+	IShader *m_pShader;
 };
\ No newline at end of file
diff --git a/plugins/shaders/plugin.h b/plugins/shaders/plugin.h
index 6a4a547d..509e5e43 100644
--- a/plugins/shaders/plugin.h
+++ b/plugins/shaders/plugin.h
@@ -1,69 +1,69 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-#include "synapse.h"
-#include "qerplugin.h"
-#include "missing.h"
-#include "igl.h"
-#include "ishaders.h"
-#include "idata.h"
-#include "ifilesystem.h"
-#include "iscriplib.h"
-#define USE_BRUSHTABLE_DEFINE
-#include "ibrush.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERAppDataTable g_DataTable;
-extern _QERQglTable g_QglTable;
-extern _QERAppShadersTable g_ShadersTable;
-extern _QERFileSystemTable g_VFSTable;
-extern _QERScripLibTable g_ScripLibTable;
-extern _QERBrushTable g_BrushTable;
-
-#define vfsGetFileCount g_VFSTable.m_pfnGetFileCount
-#define vfsLoadFile g_VFSTable.m_pfnLoadFile
-#define vfsFreeFile g_VFSTable.m_pfnFreeFile
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-
-class CSynapseClientShaders : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName();
-  
-  CSynapseClientShaders() { }
-  virtual ~CSynapseClientShaders() { }
-};
-
-#endif // _PLUGIN_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+#include "synapse.h"
+#include "qerplugin.h"
+#include "missing.h"
+#include "igl.h"
+#include "ishaders.h"
+#include "idata.h"
+#include "ifilesystem.h"
+#include "iscriplib.h"
+#define USE_BRUSHTABLE_DEFINE
+#include "ibrush.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERAppDataTable g_DataTable;
+extern _QERQglTable g_QglTable;
+extern _QERAppShadersTable g_ShadersTable;
+extern _QERFileSystemTable g_VFSTable;
+extern _QERScripLibTable g_ScripLibTable;
+extern _QERBrushTable g_BrushTable;
+
+#define vfsGetFileCount g_VFSTable.m_pfnGetFileCount
+#define vfsLoadFile g_VFSTable.m_pfnLoadFile
+#define vfsFreeFile g_VFSTable.m_pfnFreeFile
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+
+class CSynapseClientShaders : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName();
+  
+  CSynapseClientShaders() { }
+  virtual ~CSynapseClientShaders() { }
+};
+
+#endif // _PLUGIN_H_
diff --git a/plugins/shaders/shaders.h b/plugins/shaders/shaders.h
index 04792a59..253f87ec 100644
--- a/plugins/shaders/shaders.h
+++ b/plugins/shaders/shaders.h
@@ -1,167 +1,167 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// internal implementation of IShaders related stuff
-//
-
-#ifndef __SHADERS_H_
-#define __SHADERS_H_
-
-//++timo TODO: track all the calls to IncRef and look for not-called DecRef bugs
-//++timo TODO: move all needed stuff into the IShader interface
-
-// Radiant's internal implementation of the IShader object
-class CShader : public IShader
-{
-	int refCount;
-	qtexture_t *m_pTexture;
-	// name is shader / texture name (if not a real shader) reletive to "textures/" directory
-	char m_Name[QER_MAX_NAMELEN];
-	char m_ShaderFileName[QER_MAX_NAMELEN];
-	int m_nFlags;
-  float m_fTrans;
-  // the name of the texture file to be used to represent the shader
-	//++timo FIXME?
-	// must fit the qtexture_t convention or not? I think so ..
-  // ((old .. NOTE: may be a straight copy of the .shader file, doesn't fit the qtexture_t naming requirements))
-	CString m_strTextureName;
-  bool m_bDisplayed;
-	bool m_bInUse;
-	// color stuff
-	bool m_bColor;
-	vec3_t m_vColor;
-  // alphafunc stuff
-  int m_nAlphaFunc;
-  float m_fAlphaRef;
-  // cull stuff
-  int m_nCull;
-
-	// will hook itself in g_ActiveShaders and increment ref count
-	// will also update the underlying qtexture_t with some information about the shader name etc.
-	void RegisterActivate();
-
-public:
-	CShader() { refCount = 0; m_pTexture = NULL; m_Name[0]='\0'; m_ShaderFileName[0]='\0'; m_nFlags = 0; m_bInUse = false; m_bDisplayed = false; m_bColor = false; m_fTrans = 1.0f; m_nAlphaFunc = 0; m_fAlphaRef = 0.f; m_nCull = 0; }
-	virtual ~CShader() { }
-
-	// IShaders implementation -----------------
-	// Increment the number of references to this object
-	void IncRef () { refCount++; }
-	// Decrement the reference count
-	void DecRef () 
-  { if ( --refCount <= 0 ) 
-		delete this;
-	}
-	// get/set the qtexture_t* Radiant uses to represent this shader object
-	qtexture_t* getTexture() const { return m_pTexture; }
-	void setTexture(qtexture_t *pTex) { m_pTexture = pTex; }
-	// get shader name
-	const char* getName() const { return m_Name; }
-  bool IsDisplayed() const { return m_bDisplayed; }
-  void SetDisplayed(bool b) { m_bDisplayed = b; }
-  // setting in use also sets the display flag on
-	bool IsInUse() const { return m_bInUse; }
-	void SetInUse(bool b) { m_bInUse = b; if (m_pTexture) m_pTexture->inuse = true; if (b) m_bDisplayed = true; }
-  // get the shader flags
-  int getFlags() { return m_nFlags; }
-  // get the transparency value
-  float getTrans() { return m_fTrans; }
-	// test if it's a true shader, or a default shader created to wrap around a texture
-	bool IsDefault() { return m_ShaderFileName[0] == '\0'; }
-	// test if it's a plain color shader, i.e. a shader we use on plain color stuff (like info_playerstart)
-	bool IsColor() { return m_bColor; }
-	// get the related color then!
-	void getColor( vec3_t v) { VectorCopy( m_vColor, v); }
-  // get the alphaFunc
-  void getAlphaFunc(int *func, float *ref) { *func = m_nAlphaFunc; *ref = m_fAlphaRef; };
-  // get the cull type
-  int getCull() { return m_nCull; };
-	// get/set shader file name (ie the file where this one is defined)
-	const char* getShaderFileName() const { return m_ShaderFileName; }
-	// -----------------------------------------
-
-	// parse yourself!
-	bool Parse();
-
-	// search / load the texture to be used when displaying the shader
-	// after a successfull call to one of these the shader will get displayed in the tex wnd
-	// if m_strTextureName could not be loaded will set m_pTexture to NULL
-	void Try_Activate();
-	// if m_strTextureName could not be loaded will use a default qtexture
-  // FIXME TTimo: Activate forces activation, always true
-	bool Activate();
-	
-	// set shader name
-	void setName(const char* name) { strcpy(m_Name, name); }
-	void setShaderFileName(const char* name) { strcpy(m_ShaderFileName, name); }
-  // create a default shader for a given texture name
-  // will not activate!
-	// NOTE: CreateDefault expects a texture name reletive to the base path. Adding a "textures/" may be needed
-  void CreateDefault(const char* name);
-  const char* getTextureName() { return m_strTextureName; }
-
-	//++timo clean
-	// color stuff
-//	void setColor( vec3_t c ) { VectorCopy( c, m_vColor ); m_bColor = true; }
-	// create a color shader
-	void CreateColor(const char* name);
-};
-
-// the classical CPtrArray with some enhancements
-class CShaderArray : public CPtrArray
-{
-public:
-	CShaderArray() { }
-	virtual ~CShaderArray() { }
-  // look for a shader with a given name (may return NULL)
-	CShader* Shader_ForName( const char * ) const;
-  // look for a shader with a given texture name (may return NULL)
-  // NOTE: the texture name is supposed to fit qtexture_t naming conventions .. _DEBUG builds will check
-  CShader* Shader_ForTextureName( const char * ) const;
-	// will Add the given object if not already in
-	void AddSingle(void*);
-	// will copy / add another CShaderArray, and IncRef
-	void operator = (const class CShaderArray &);
-	// will empty the array, decreasing the refcount by 1
-	void ReleaseAll();
-  // will empty all shaders that match a given filename, decreasing the refcount by 1
-  void ReleaseForShaderFile( const char * );
-	// sort the array by shader name
-	void SortShaders();
-	// set the IsDisplayed flag for all shaders stored
-	void SetDisplayed(bool b);
-	// set the InUse flag for all shaders stored
-	void SetInUse(bool b);
-};
-
-#endif
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// internal implementation of IShaders related stuff
+//
+
+#ifndef __SHADERS_H_
+#define __SHADERS_H_
+
+//++timo TODO: track all the calls to IncRef and look for not-called DecRef bugs
+//++timo TODO: move all needed stuff into the IShader interface
+
+// Radiant's internal implementation of the IShader object
+class CShader : public IShader
+{
+	int refCount;
+	qtexture_t *m_pTexture;
+	// name is shader / texture name (if not a real shader) reletive to "textures/" directory
+	char m_Name[QER_MAX_NAMELEN];
+	char m_ShaderFileName[QER_MAX_NAMELEN];
+	int m_nFlags;
+  float m_fTrans;
+  // the name of the texture file to be used to represent the shader
+	//++timo FIXME?
+	// must fit the qtexture_t convention or not? I think so ..
+  // ((old .. NOTE: may be a straight copy of the .shader file, doesn't fit the qtexture_t naming requirements))
+	CString m_strTextureName;
+  bool m_bDisplayed;
+	bool m_bInUse;
+	// color stuff
+	bool m_bColor;
+	vec3_t m_vColor;
+  // alphafunc stuff
+  int m_nAlphaFunc;
+  float m_fAlphaRef;
+  // cull stuff
+  int m_nCull;
+
+	// will hook itself in g_ActiveShaders and increment ref count
+	// will also update the underlying qtexture_t with some information about the shader name etc.
+	void RegisterActivate();
+
+public:
+	CShader() { refCount = 0; m_pTexture = NULL; m_Name[0]='\0'; m_ShaderFileName[0]='\0'; m_nFlags = 0; m_bInUse = false; m_bDisplayed = false; m_bColor = false; m_fTrans = 1.0f; m_nAlphaFunc = 0; m_fAlphaRef = 0.f; m_nCull = 0; }
+	virtual ~CShader() { }
+
+	// IShaders implementation -----------------
+	// Increment the number of references to this object
+	void IncRef () { refCount++; }
+	// Decrement the reference count
+	void DecRef () 
+  { if ( --refCount <= 0 ) 
+		delete this;
+	}
+	// get/set the qtexture_t* Radiant uses to represent this shader object
+	qtexture_t* getTexture() const { return m_pTexture; }
+	void setTexture(qtexture_t *pTex) { m_pTexture = pTex; }
+	// get shader name
+	const char* getName() const { return m_Name; }
+  bool IsDisplayed() const { return m_bDisplayed; }
+  void SetDisplayed(bool b) { m_bDisplayed = b; }
+  // setting in use also sets the display flag on
+	bool IsInUse() const { return m_bInUse; }
+	void SetInUse(bool b) { m_bInUse = b; if (m_pTexture) m_pTexture->inuse = true; if (b) m_bDisplayed = true; }
+  // get the shader flags
+  int getFlags() { return m_nFlags; }
+  // get the transparency value
+  float getTrans() { return m_fTrans; }
+	// test if it's a true shader, or a default shader created to wrap around a texture
+	bool IsDefault() { return m_ShaderFileName[0] == '\0'; }
+	// test if it's a plain color shader, i.e. a shader we use on plain color stuff (like info_playerstart)
+	bool IsColor() { return m_bColor; }
+	// get the related color then!
+	void getColor( vec3_t v) { VectorCopy( m_vColor, v); }
+  // get the alphaFunc
+  void getAlphaFunc(int *func, float *ref) { *func = m_nAlphaFunc; *ref = m_fAlphaRef; };
+  // get the cull type
+  int getCull() { return m_nCull; };
+	// get/set shader file name (ie the file where this one is defined)
+	const char* getShaderFileName() const { return m_ShaderFileName; }
+	// -----------------------------------------
+
+	// parse yourself!
+	bool Parse();
+
+	// search / load the texture to be used when displaying the shader
+	// after a successfull call to one of these the shader will get displayed in the tex wnd
+	// if m_strTextureName could not be loaded will set m_pTexture to NULL
+	void Try_Activate();
+	// if m_strTextureName could not be loaded will use a default qtexture
+  // FIXME TTimo: Activate forces activation, always true
+	bool Activate();
+	
+	// set shader name
+	void setName(const char* name) { strcpy(m_Name, name); }
+	void setShaderFileName(const char* name) { strcpy(m_ShaderFileName, name); }
+  // create a default shader for a given texture name
+  // will not activate!
+	// NOTE: CreateDefault expects a texture name reletive to the base path. Adding a "textures/" may be needed
+  void CreateDefault(const char* name);
+  const char* getTextureName() { return m_strTextureName; }
+
+	//++timo clean
+	// color stuff
+//	void setColor( vec3_t c ) { VectorCopy( c, m_vColor ); m_bColor = true; }
+	// create a color shader
+	void CreateColor(const char* name);
+};
+
+// the classical CPtrArray with some enhancements
+class CShaderArray : public CPtrArray
+{
+public:
+	CShaderArray() { }
+	virtual ~CShaderArray() { }
+  // look for a shader with a given name (may return NULL)
+	CShader* Shader_ForName( const char * ) const;
+  // look for a shader with a given texture name (may return NULL)
+  // NOTE: the texture name is supposed to fit qtexture_t naming conventions .. _DEBUG builds will check
+  CShader* Shader_ForTextureName( const char * ) const;
+	// will Add the given object if not already in
+	void AddSingle(void*);
+	// will copy / add another CShaderArray, and IncRef
+	void operator = (const class CShaderArray &);
+	// will empty the array, decreasing the refcount by 1
+	void ReleaseAll();
+  // will empty all shaders that match a given filename, decreasing the refcount by 1
+  void ReleaseForShaderFile( const char * );
+	// sort the array by shader name
+	void SortShaders();
+	// set the IsDisplayed flag for all shaders stored
+	void SetDisplayed(bool b);
+	// set the InUse flag for all shaders stored
+	void SetInUse(bool b);
+};
+
+#endif
diff --git a/plugins/spritemodel/plugin.h b/plugins/spritemodel/plugin.h
index e8ebe054..5dca12ee 100644
--- a/plugins/spritemodel/plugin.h
+++ b/plugins/spritemodel/plugin.h
@@ -1,78 +1,78 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// Sprite Model Plugin
-//
-// Code by Hydra aka Dominic Clifton
-//
-// Based on MD3Model source code by SPoG
-//
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-/*!
-\todo need general notice about lib purpose etc.
-and the external dependencies (such as GLib, STL, mathlib etc.)
-*/
-
-/*!
-\todo not sure about what should be used for common data structures, GLib or STL
-I think STL would be better since I intend on using STL in synapse
-*/
-
-#include <stdio.h>
-
-#include "synapse.h"
-#include "iplugin.h"
-#define USE_QERTABLE_DEFINE
-#include "qerplugin.h"
-#include "imodel.h"
-#include "igl.h"
-#include "ifilesystem.h"
-#include "ishaders.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern _QERQglTable g_QglTable;
-extern _QERShadersTable g_ShadersTable;
-
-#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
-#define QERApp_Try_Shader_ForName g_ShadersTable.m_pfnTry_Shader_ForName
-
-void LoadSpriteModel(entity_interfaces_t *interfaces, const char *name);
-
-extern CSynapseServer* g_pSynapseServer;
-
-class CSynapseClientModel : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName();
-
-  CSynapseClientModel() { }
-  virtual ~CSynapseClientModel() { }
-};
-
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// Sprite Model Plugin
+//
+// Code by Hydra aka Dominic Clifton
+//
+// Based on MD3Model source code by SPoG
+//
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+/*!
+\todo need general notice about lib purpose etc.
+and the external dependencies (such as GLib, STL, mathlib etc.)
+*/
+
+/*!
+\todo not sure about what should be used for common data structures, GLib or STL
+I think STL would be better since I intend on using STL in synapse
+*/
+
+#include <stdio.h>
+
+#include "synapse.h"
+#include "iplugin.h"
+#define USE_QERTABLE_DEFINE
+#include "qerplugin.h"
+#include "imodel.h"
+#include "igl.h"
+#include "ifilesystem.h"
+#include "ishaders.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern _QERQglTable g_QglTable;
+extern _QERShadersTable g_ShadersTable;
+
+#define QERApp_Shader_ForName g_ShadersTable.m_pfnShader_ForName
+#define QERApp_Try_Shader_ForName g_ShadersTable.m_pfnTry_Shader_ForName
+
+void LoadSpriteModel(entity_interfaces_t *interfaces, const char *name);
+
+extern CSynapseServer* g_pSynapseServer;
+
+class CSynapseClientModel : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName();
+
+  CSynapseClientModel() { }
+  virtual ~CSynapseClientModel() { }
+};
+
+
+#endif // _PLUGIN_H_
diff --git a/plugins/spritemodel/spritemodel.h b/plugins/spritemodel/spritemodel.h
index 688c0e6a..c6c26305 100644
--- a/plugins/spritemodel/spritemodel.h
+++ b/plugins/spritemodel/spritemodel.h
@@ -1,57 +1,57 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// Sprite Model Plugin
-//
-// Code by Hydra aka Dominic Clifton
-//
-// Based on MD3Model source code by SPoG
-//
-
-#include "plugin.h"
-
-/*! i guess a description should go here... */
-class CSpriteModel: public IRender//, public ISelect
-{
-public:
-  CSpriteModel();
-  ~CSpriteModel();
-
-  void IncRef() { refCount++; }
-  void DecRef() { if(--refCount == 0) delete this; }
-
-  //IRender
-	void Draw(int state, int rflags) const;
-  const aabb_t *GetAABB() const { return &m_BBox; }
-
-  //ISelect
-  //bool TestRay (const ray_t *ray, vec_t *dist) const;
-
-  void Construct(IShader *pShader);
-
-protected:
-  IShader *m_pShader;
-
-private:
-  int refCount;
-	aabb_t m_BBox;
-};
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// Sprite Model Plugin
+//
+// Code by Hydra aka Dominic Clifton
+//
+// Based on MD3Model source code by SPoG
+//
+
+#include "plugin.h"
+
+/*! i guess a description should go here... */
+class CSpriteModel: public IRender//, public ISelect
+{
+public:
+  CSpriteModel();
+  ~CSpriteModel();
+
+  void IncRef() { refCount++; }
+  void DecRef() { if(--refCount == 0) delete this; }
+
+  //IRender
+	void Draw(int state, int rflags) const;
+  const aabb_t *GetAABB() const { return &m_BBox; }
+
+  //ISelect
+  //bool TestRay (const ray_t *ray, vec_t *dist) const;
+
+  void Construct(IShader *pShader);
+
+protected:
+  IShader *m_pShader;
+
+private:
+  int refCount;
+	aabb_t m_BBox;
+};
diff --git a/plugins/surface/surfacedialog.h b/plugins/surface/surfacedialog.h
index 96ab3c79..4a5b815b 100644
--- a/plugins/surface/surfacedialog.h
+++ b/plugins/surface/surfacedialog.h
@@ -1,31 +1,31 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _SURFACEDIALOG_H_
-#define _SURFACEDIALOG_H_
-
-void UpdateSurfaceDialog ();
-void DoSurface ();
-void ToggleSurface ();
-void SurfaceDlgFitAll ();
-GtkWidget *Get_SI_Module_Widget ();
-
-#endif // _SURFACEDIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SURFACEDIALOG_H_
+#define _SURFACEDIALOG_H_
+
+void UpdateSurfaceDialog ();
+void DoSurface ();
+void ToggleSurface ();
+void SurfaceDlgFitAll ();
+GtkWidget *Get_SI_Module_Widget ();
+
+#endif // _SURFACEDIALOG_H_
diff --git a/plugins/surface/surfdlg_plugin.h b/plugins/surface/surfdlg_plugin.h
index 89129d45..f5391344 100644
--- a/plugins/surface/surfdlg_plugin.h
+++ b/plugins/surface/surfdlg_plugin.h
@@ -1,94 +1,94 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _SURFDLG_PLUGIN_H_
-#define _SURFDLG_PLUGIN_H_
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-#include "qerplugin.h"
-#include "synapse.h"
-#include "iselectedface.h"
-#include "iundo.h"
-#include "ishaders.h"
-#include "mathlib.h"
-#include "missing.h"
-#include "idata.h"
-
-#include "isurfaceplugin.h"
-
-class SurfaceDialog : public IPluginTexdef
-{
-	int refCount;
-public:
-	// Increment the number of references to this object
-	void IncRef () { refCount++; }
-	// Decrement the reference count
-	void DecRef () { if ( --refCount <= 0 ) delete this; }
-};
-
-extern _QERFuncTable_1 	g_FuncTable;
-extern _QERUndoTable g_UndoTable;
-extern _QERAppSurfaceTable g_AppSurfaceTable;
-extern _QERSelectedFaceTable g_SelectedFaceTable;
-extern _QERShadersTable g_ShadersTable;
-extern _QERAppShadersTable g_AppShadersTable;
-extern _QERAppDataTable g_AppDataTable;
-
-#define GetSelectedFaceCount g_SelectedFaceTable.m_pfnGetSelectedFaceCount
-
-#define Undo_Undo g_UndoTable.m_pfnUndo_Undo
-#define Undo_GetUndoId g_UndoTable.m_pfnUndo_GetUndoId
-
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
-#define Sys_UpdateWindows g_FuncTable.m_pfnSysUpdateWindows
-
-
-#define Select_FitTexture g_AppSurfaceTable.m_pfnSelect_FitTexture
-#define Get_SI_Inc g_AppSurfaceTable.m_pfnQERApp_QeglobalsSavedinfo_SIInc
-#define GridSize g_AppSurfaceTable.m_pfnQeglobalsGetGridSize
-#define FaceList_FitTexture g_AppSurfaceTable.m_pfnFaceList_FitTexture
-#define GetMainWindow g_AppSurfaceTable.m_pfnGetMainWindow
-#define GetSelectedFaceCountfromBrushes g_AppSurfaceTable.m_pfnGetSelectedFaceCountfromBrushes
-#define GetSelFacesTexdef g_AppSurfaceTable.m_pfnGetSelFacesTexdef
-#define SetTexdef_FaceList g_AppSurfaceTable.m_pfnSetTexdef_FaceList
-#define SetWinPos_from_Prefs g_AppSurfaceTable.m_pfnSetWinPos_From_Prefs
-
-#define Texturewin g_AppShadersTable.m_pfnQeglobalsTexturewin
-
-#endif // _SURFDLG_PLUGIN_H_
-
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _SURFDLG_PLUGIN_H_
+#define _SURFDLG_PLUGIN_H_
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+#include "qerplugin.h"
+#include "synapse.h"
+#include "iselectedface.h"
+#include "iundo.h"
+#include "ishaders.h"
+#include "mathlib.h"
+#include "missing.h"
+#include "idata.h"
+
+#include "isurfaceplugin.h"
+
+class SurfaceDialog : public IPluginTexdef
+{
+	int refCount;
+public:
+	// Increment the number of references to this object
+	void IncRef () { refCount++; }
+	// Decrement the reference count
+	void DecRef () { if ( --refCount <= 0 ) delete this; }
+};
+
+extern _QERFuncTable_1 	g_FuncTable;
+extern _QERUndoTable g_UndoTable;
+extern _QERAppSurfaceTable g_AppSurfaceTable;
+extern _QERSelectedFaceTable g_SelectedFaceTable;
+extern _QERShadersTable g_ShadersTable;
+extern _QERAppShadersTable g_AppShadersTable;
+extern _QERAppDataTable g_AppDataTable;
+
+#define GetSelectedFaceCount g_SelectedFaceTable.m_pfnGetSelectedFaceCount
+
+#define Undo_Undo g_UndoTable.m_pfnUndo_Undo
+#define Undo_GetUndoId g_UndoTable.m_pfnUndo_GetUndoId
+
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+#define Sys_UpdateWindows g_FuncTable.m_pfnSysUpdateWindows
+
+
+#define Select_FitTexture g_AppSurfaceTable.m_pfnSelect_FitTexture
+#define Get_SI_Inc g_AppSurfaceTable.m_pfnQERApp_QeglobalsSavedinfo_SIInc
+#define GridSize g_AppSurfaceTable.m_pfnQeglobalsGetGridSize
+#define FaceList_FitTexture g_AppSurfaceTable.m_pfnFaceList_FitTexture
+#define GetMainWindow g_AppSurfaceTable.m_pfnGetMainWindow
+#define GetSelectedFaceCountfromBrushes g_AppSurfaceTable.m_pfnGetSelectedFaceCountfromBrushes
+#define GetSelFacesTexdef g_AppSurfaceTable.m_pfnGetSelFacesTexdef
+#define SetTexdef_FaceList g_AppSurfaceTable.m_pfnSetTexdef_FaceList
+#define SetWinPos_from_Prefs g_AppSurfaceTable.m_pfnSetWinPos_From_Prefs
+
+#define Texturewin g_AppShadersTable.m_pfnQeglobalsTexturewin
+
+#endif // _SURFDLG_PLUGIN_H_
+
diff --git a/plugins/surface_heretic2/surfacedialog.h b/plugins/surface_heretic2/surfacedialog.h
index 96ab3c79..4a5b815b 100644
--- a/plugins/surface_heretic2/surfacedialog.h
+++ b/plugins/surface_heretic2/surfacedialog.h
@@ -1,31 +1,31 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _SURFACEDIALOG_H_
-#define _SURFACEDIALOG_H_
-
-void UpdateSurfaceDialog ();
-void DoSurface ();
-void ToggleSurface ();
-void SurfaceDlgFitAll ();
-GtkWidget *Get_SI_Module_Widget ();
-
-#endif // _SURFACEDIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SURFACEDIALOG_H_
+#define _SURFACEDIALOG_H_
+
+void UpdateSurfaceDialog ();
+void DoSurface ();
+void ToggleSurface ();
+void SurfaceDlgFitAll ();
+GtkWidget *Get_SI_Module_Widget ();
+
+#endif // _SURFACEDIALOG_H_
diff --git a/plugins/surface_heretic2/surfaceflagsdialog_heretic2.h b/plugins/surface_heretic2/surfaceflagsdialog_heretic2.h
index 1b00e1a3..c074906e 100644
--- a/plugins/surface_heretic2/surfaceflagsdialog_heretic2.h
+++ b/plugins/surface_heretic2/surfaceflagsdialog_heretic2.h
@@ -1,76 +1,76 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _SURFACEFLAGSDIALOG_HERETIC2_H
-  #define _SURFACEFLAGSDIALOG_HERETIC2_H
-
-// 12
-#define HERETIC2_SURF_LIGHT              0x1
-#define HERETIC2_SURF_SLICK              0x2
-#define HERETIC2_SURF_SKY                0x4
-#define HERETIC2_SURF_WARP               0x8
-#define HERETIC2_SURF_TRANS33    	0x10
-#define HERETIC2_SURF_TRANS66    	0x20
-#define HERETIC2_SURF_FLOWING    	0x40
-#define HERETIC2_SURF_NODRAW            0x80
-
-#define	HERETIC2_SURF_TALL_WALL		0x400
-#define HERETIC2_SURF_ALPHA_TEXTURE    	0x800
-#define	HERETIC2_SURF_ANIMSPEED		0x1000
-#define HERETIC2_SURF_UNDULATE		0x2000
-
-#define HERETIC2_SURF_TYPE_GRAVEL       0x00000000
-#define HERETIC2_SURF_TYPE_METAL        0x01000000
-#define HERETIC2_SURF_TYPE_STONE        0x02000000
-#define HERETIC2_SURF_TYPE_WOOD         0x03000000
-
-#define HERETIC2_SURF_MATERIAL_MASK	0xFCFFFFFF
-
-
-// 20
-#define HERETIC2_CONTENTS_SOLID		0x1
-#define HERETIC2_CONTENTS_WINDOW	0x2
-#define HERETIC2_CONTENTS_ILLUSIONARY	0x4
-#define HERETIC2_CONTENTS_LAVA		0x8
-#define HERETIC2_CONTENTS_SLIME		0x10
-#define HERETIC2_CONTENTS_WATER		0x20
-#define HERETIC2_CONTENTS_MIST		0x40
-
-#define HERETIC2_CONTENTS_AREAPORTAL	0x8000
-#define HERETIC2_CONTENTS_PLAYERCLIP	0x10000
-#define HERETIC2_CONTENTS_MONSTERCLIP    0x20000
-#define HERETIC2_CONTENTS_CURRENT_0	0x40000
-#define HERETIC2_CONTENTS_CURRENT_90	0x80000
-#define HERETIC2_CONTENTS_CURRENT_180	0x100000
-#define HERETIC2_CONTENTS_CURRENT_270	0x200000
-#define HERETIC2_CONTENTS_CURRENT_UP	0x400000
-#define HERETIC2_CONTENTS_CURRENT_DOWN	0x800000
-#define HERETIC2_CONTENTS_ORIGIN	0x1000000
-
-#define HERETIC2_CONTENTS_DETAIL	0x8000000
-
-#define HERETIC2_CONTENTS_LADDER        0x20000000
-
-#define HERETIC2_CONTENTS_CAMERANOBLOCK	0x40000000
-
-
-
-#endif // _SURFACEFLAGSDIALOG_HERETIC2_H
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SURFACEFLAGSDIALOG_HERETIC2_H
+  #define _SURFACEFLAGSDIALOG_HERETIC2_H
+
+// 12
+#define HERETIC2_SURF_LIGHT              0x1
+#define HERETIC2_SURF_SLICK              0x2
+#define HERETIC2_SURF_SKY                0x4
+#define HERETIC2_SURF_WARP               0x8
+#define HERETIC2_SURF_TRANS33    	0x10
+#define HERETIC2_SURF_TRANS66    	0x20
+#define HERETIC2_SURF_FLOWING    	0x40
+#define HERETIC2_SURF_NODRAW            0x80
+
+#define	HERETIC2_SURF_TALL_WALL		0x400
+#define HERETIC2_SURF_ALPHA_TEXTURE    	0x800
+#define	HERETIC2_SURF_ANIMSPEED		0x1000
+#define HERETIC2_SURF_UNDULATE		0x2000
+
+#define HERETIC2_SURF_TYPE_GRAVEL       0x00000000
+#define HERETIC2_SURF_TYPE_METAL        0x01000000
+#define HERETIC2_SURF_TYPE_STONE        0x02000000
+#define HERETIC2_SURF_TYPE_WOOD         0x03000000
+
+#define HERETIC2_SURF_MATERIAL_MASK	0xFCFFFFFF
+
+
+// 20
+#define HERETIC2_CONTENTS_SOLID		0x1
+#define HERETIC2_CONTENTS_WINDOW	0x2
+#define HERETIC2_CONTENTS_ILLUSIONARY	0x4
+#define HERETIC2_CONTENTS_LAVA		0x8
+#define HERETIC2_CONTENTS_SLIME		0x10
+#define HERETIC2_CONTENTS_WATER		0x20
+#define HERETIC2_CONTENTS_MIST		0x40
+
+#define HERETIC2_CONTENTS_AREAPORTAL	0x8000
+#define HERETIC2_CONTENTS_PLAYERCLIP	0x10000
+#define HERETIC2_CONTENTS_MONSTERCLIP    0x20000
+#define HERETIC2_CONTENTS_CURRENT_0	0x40000
+#define HERETIC2_CONTENTS_CURRENT_90	0x80000
+#define HERETIC2_CONTENTS_CURRENT_180	0x100000
+#define HERETIC2_CONTENTS_CURRENT_270	0x200000
+#define HERETIC2_CONTENTS_CURRENT_UP	0x400000
+#define HERETIC2_CONTENTS_CURRENT_DOWN	0x800000
+#define HERETIC2_CONTENTS_ORIGIN	0x1000000
+
+#define HERETIC2_CONTENTS_DETAIL	0x8000000
+
+#define HERETIC2_CONTENTS_LADDER        0x20000000
+
+#define HERETIC2_CONTENTS_CAMERANOBLOCK	0x40000000
+
+
+
+#endif // _SURFACEFLAGSDIALOG_HERETIC2_H
diff --git a/plugins/surface_heretic2/surfdlg_plugin.h b/plugins/surface_heretic2/surfdlg_plugin.h
index 89129d45..f5391344 100644
--- a/plugins/surface_heretic2/surfdlg_plugin.h
+++ b/plugins/surface_heretic2/surfdlg_plugin.h
@@ -1,94 +1,94 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _SURFDLG_PLUGIN_H_
-#define _SURFDLG_PLUGIN_H_
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-#include "qerplugin.h"
-#include "synapse.h"
-#include "iselectedface.h"
-#include "iundo.h"
-#include "ishaders.h"
-#include "mathlib.h"
-#include "missing.h"
-#include "idata.h"
-
-#include "isurfaceplugin.h"
-
-class SurfaceDialog : public IPluginTexdef
-{
-	int refCount;
-public:
-	// Increment the number of references to this object
-	void IncRef () { refCount++; }
-	// Decrement the reference count
-	void DecRef () { if ( --refCount <= 0 ) delete this; }
-};
-
-extern _QERFuncTable_1 	g_FuncTable;
-extern _QERUndoTable g_UndoTable;
-extern _QERAppSurfaceTable g_AppSurfaceTable;
-extern _QERSelectedFaceTable g_SelectedFaceTable;
-extern _QERShadersTable g_ShadersTable;
-extern _QERAppShadersTable g_AppShadersTable;
-extern _QERAppDataTable g_AppDataTable;
-
-#define GetSelectedFaceCount g_SelectedFaceTable.m_pfnGetSelectedFaceCount
-
-#define Undo_Undo g_UndoTable.m_pfnUndo_Undo
-#define Undo_GetUndoId g_UndoTable.m_pfnUndo_GetUndoId
-
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
-#define Sys_UpdateWindows g_FuncTable.m_pfnSysUpdateWindows
-
-
-#define Select_FitTexture g_AppSurfaceTable.m_pfnSelect_FitTexture
-#define Get_SI_Inc g_AppSurfaceTable.m_pfnQERApp_QeglobalsSavedinfo_SIInc
-#define GridSize g_AppSurfaceTable.m_pfnQeglobalsGetGridSize
-#define FaceList_FitTexture g_AppSurfaceTable.m_pfnFaceList_FitTexture
-#define GetMainWindow g_AppSurfaceTable.m_pfnGetMainWindow
-#define GetSelectedFaceCountfromBrushes g_AppSurfaceTable.m_pfnGetSelectedFaceCountfromBrushes
-#define GetSelFacesTexdef g_AppSurfaceTable.m_pfnGetSelFacesTexdef
-#define SetTexdef_FaceList g_AppSurfaceTable.m_pfnSetTexdef_FaceList
-#define SetWinPos_from_Prefs g_AppSurfaceTable.m_pfnSetWinPos_From_Prefs
-
-#define Texturewin g_AppShadersTable.m_pfnQeglobalsTexturewin
-
-#endif // _SURFDLG_PLUGIN_H_
-
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _SURFDLG_PLUGIN_H_
+#define _SURFDLG_PLUGIN_H_
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+#include "qerplugin.h"
+#include "synapse.h"
+#include "iselectedface.h"
+#include "iundo.h"
+#include "ishaders.h"
+#include "mathlib.h"
+#include "missing.h"
+#include "idata.h"
+
+#include "isurfaceplugin.h"
+
+class SurfaceDialog : public IPluginTexdef
+{
+	int refCount;
+public:
+	// Increment the number of references to this object
+	void IncRef () { refCount++; }
+	// Decrement the reference count
+	void DecRef () { if ( --refCount <= 0 ) delete this; }
+};
+
+extern _QERFuncTable_1 	g_FuncTable;
+extern _QERUndoTable g_UndoTable;
+extern _QERAppSurfaceTable g_AppSurfaceTable;
+extern _QERSelectedFaceTable g_SelectedFaceTable;
+extern _QERShadersTable g_ShadersTable;
+extern _QERAppShadersTable g_AppShadersTable;
+extern _QERAppDataTable g_AppDataTable;
+
+#define GetSelectedFaceCount g_SelectedFaceTable.m_pfnGetSelectedFaceCount
+
+#define Undo_Undo g_UndoTable.m_pfnUndo_Undo
+#define Undo_GetUndoId g_UndoTable.m_pfnUndo_GetUndoId
+
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+#define Sys_UpdateWindows g_FuncTable.m_pfnSysUpdateWindows
+
+
+#define Select_FitTexture g_AppSurfaceTable.m_pfnSelect_FitTexture
+#define Get_SI_Inc g_AppSurfaceTable.m_pfnQERApp_QeglobalsSavedinfo_SIInc
+#define GridSize g_AppSurfaceTable.m_pfnQeglobalsGetGridSize
+#define FaceList_FitTexture g_AppSurfaceTable.m_pfnFaceList_FitTexture
+#define GetMainWindow g_AppSurfaceTable.m_pfnGetMainWindow
+#define GetSelectedFaceCountfromBrushes g_AppSurfaceTable.m_pfnGetSelectedFaceCountfromBrushes
+#define GetSelFacesTexdef g_AppSurfaceTable.m_pfnGetSelFacesTexdef
+#define SetTexdef_FaceList g_AppSurfaceTable.m_pfnSetTexdef_FaceList
+#define SetWinPos_from_Prefs g_AppSurfaceTable.m_pfnSetWinPos_From_Prefs
+
+#define Texturewin g_AppShadersTable.m_pfnQeglobalsTexturewin
+
+#endif // _SURFDLG_PLUGIN_H_
+
diff --git a/plugins/surface_quake2/surfacedialog.h b/plugins/surface_quake2/surfacedialog.h
index 96ab3c79..4a5b815b 100644
--- a/plugins/surface_quake2/surfacedialog.h
+++ b/plugins/surface_quake2/surfacedialog.h
@@ -1,31 +1,31 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _SURFACEDIALOG_H_
-#define _SURFACEDIALOG_H_
-
-void UpdateSurfaceDialog ();
-void DoSurface ();
-void ToggleSurface ();
-void SurfaceDlgFitAll ();
-GtkWidget *Get_SI_Module_Widget ();
-
-#endif // _SURFACEDIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SURFACEDIALOG_H_
+#define _SURFACEDIALOG_H_
+
+void UpdateSurfaceDialog ();
+void DoSurface ();
+void ToggleSurface ();
+void SurfaceDlgFitAll ();
+GtkWidget *Get_SI_Module_Widget ();
+
+#endif // _SURFACEDIALOG_H_
diff --git a/plugins/surface_quake2/surfaceflagsdialog_quake2.h b/plugins/surface_quake2/surfaceflagsdialog_quake2.h
index 04e745f2..985c3708 100644
--- a/plugins/surface_quake2/surfaceflagsdialog_quake2.h
+++ b/plugins/surface_quake2/surfaceflagsdialog_quake2.h
@@ -1,108 +1,108 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _SURFACEFLAGSDIALOG_QUAKE2_H
-  #define _SURFACEFLAGSDIALOG_QUAKE2_H
-
-
-#define QUAKE2_SURF_LIGHT              0x1
-#define QUAKE2_SURF_SLICK              0x2
-#define QUAKE2_SURF_SKY                0x4
-#define QUAKE2_SURF_WARP               0x8
-#define QUAKE2_SURF_TRANS33    	0x10
-#define QUAKE2_SURF_TRANS66    	0x20
-#define QUAKE2_SURF_FLOWING    	0x40
-#define QUAKE2_SURF_NODRAW             0x80
-#define QUAKE2_SURF_HINT               0x100
-#define QUAKE2_SURF_SKIP               0x200
-
-
-#define QUAKE2_CONTENTS_SOLID		0x1
-#define QUAKE2_CONTENTS_WINDOW		0x2
-#define QUAKE2_CONTENTS_AUX		0x4
-#define QUAKE2_CONTENTS_LAVA		0x8
-#define QUAKE2_CONTENTS_SLIME		0x10
-#define QUAKE2_CONTENTS_WATER		0x20
-#define QUAKE2_CONTENTS_MIST		0x40
-
-#define QUAKE2_CONTENTS_AREAPORTAL	0x8000
-#define QUAKE2_CONTENTS_PLAYERCLIP	0x10000
-#define QUAKE2_CONTENTS_MONSTERCLIP    0x20000
-#define QUAKE2_CONTENTS_CURRENT_0	0x40000
-#define QUAKE2_CONTENTS_CURRENT_90	0x80000
-#define QUAKE2_CONTENTS_CURRENT_180	0x100000
-#define QUAKE2_CONTENTS_CURRENT_270	0x200000
-#define QUAKE2_CONTENTS_CURRENT_UP	0x400000
-#define QUAKE2_CONTENTS_CURRENT_DOWN	0x800000
-#define QUAKE2_CONTENTS_ORIGIN		0x1000000
-
-#define QUAKE2_CONTENTS_DETAIL		0x8000000
-#define QUAKE2_CONTENTS_TRANSLUCENT	0x10000000
-#define QUAKE2_CONTENTS_LADDER		0x20000000
-/*
-extern GtkWidget *notebook1;
-
-extern  GtkWidget *surface_lightbutton;
-extern  GtkWidget *surface_slickbutton;
-extern  GtkWidget *surface_skybutton;
-extern  GtkWidget *surface_warpbutton;
-extern  GtkWidget *surface_trans33button;
-extern  GtkWidget *surface_trans66button;
-extern  GtkWidget *surface_flowingbutton;
-extern  GtkWidget *surface_nodrawbutton;
-extern  GtkWidget *surface_hintbutton;
-extern  GtkWidget *surface_skipbutton;
-
-extern GtkWidget *content_solidbutton;
-extern GtkWidget *content_windowbutton;
-extern GtkWidget *content_auxbutton;
-extern GtkWidget *content_lavabutton;
-extern GtkWidget *content_slimebutton;
-extern GtkWidget *content_waterbutton;
-extern GtkWidget *content_mistbutton;
-extern GtkWidget *content_areaportalbutton;
-extern GtkWidget *content_playerclipbutton;
-extern GtkWidget *content_monsterclipbutton;
-extern GtkWidget *content_current0button;
-extern GtkWidget *content_current90button;
-extern GtkWidget *content_current180button;
-extern GtkWidget *content_current270button;
-extern GtkWidget *content_currentUPbutton;
-extern GtkWidget *content_currentDOWNbutton;
-extern GtkWidget *content_originbutton;
-extern GtkWidget *content_detailbutton;
-extern GtkWidget *content_translucentbutton;
-extern GtkWidget *content_ladderbutton;
-
-extern  GtkWidget *surfacebutton;
-extern  GtkWidget *contentbutton;
-
-extern  GtkWidget *value_entry;
-extern  gboolean setup_buttons;
-
-extern  int working_surface_flags;
-extern  int surface_mask;
-extern  int working_content_flags;
-extern  int content_mask;
-extern  int working_value;
-*/
-
-#endif // _SURFACEFLAGSDIALOG_QUAKE2_H
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SURFACEFLAGSDIALOG_QUAKE2_H
+  #define _SURFACEFLAGSDIALOG_QUAKE2_H
+
+
+#define QUAKE2_SURF_LIGHT              0x1
+#define QUAKE2_SURF_SLICK              0x2
+#define QUAKE2_SURF_SKY                0x4
+#define QUAKE2_SURF_WARP               0x8
+#define QUAKE2_SURF_TRANS33    	0x10
+#define QUAKE2_SURF_TRANS66    	0x20
+#define QUAKE2_SURF_FLOWING    	0x40
+#define QUAKE2_SURF_NODRAW             0x80
+#define QUAKE2_SURF_HINT               0x100
+#define QUAKE2_SURF_SKIP               0x200
+
+
+#define QUAKE2_CONTENTS_SOLID		0x1
+#define QUAKE2_CONTENTS_WINDOW		0x2
+#define QUAKE2_CONTENTS_AUX		0x4
+#define QUAKE2_CONTENTS_LAVA		0x8
+#define QUAKE2_CONTENTS_SLIME		0x10
+#define QUAKE2_CONTENTS_WATER		0x20
+#define QUAKE2_CONTENTS_MIST		0x40
+
+#define QUAKE2_CONTENTS_AREAPORTAL	0x8000
+#define QUAKE2_CONTENTS_PLAYERCLIP	0x10000
+#define QUAKE2_CONTENTS_MONSTERCLIP    0x20000
+#define QUAKE2_CONTENTS_CURRENT_0	0x40000
+#define QUAKE2_CONTENTS_CURRENT_90	0x80000
+#define QUAKE2_CONTENTS_CURRENT_180	0x100000
+#define QUAKE2_CONTENTS_CURRENT_270	0x200000
+#define QUAKE2_CONTENTS_CURRENT_UP	0x400000
+#define QUAKE2_CONTENTS_CURRENT_DOWN	0x800000
+#define QUAKE2_CONTENTS_ORIGIN		0x1000000
+
+#define QUAKE2_CONTENTS_DETAIL		0x8000000
+#define QUAKE2_CONTENTS_TRANSLUCENT	0x10000000
+#define QUAKE2_CONTENTS_LADDER		0x20000000
+/*
+extern GtkWidget *notebook1;
+
+extern  GtkWidget *surface_lightbutton;
+extern  GtkWidget *surface_slickbutton;
+extern  GtkWidget *surface_skybutton;
+extern  GtkWidget *surface_warpbutton;
+extern  GtkWidget *surface_trans33button;
+extern  GtkWidget *surface_trans66button;
+extern  GtkWidget *surface_flowingbutton;
+extern  GtkWidget *surface_nodrawbutton;
+extern  GtkWidget *surface_hintbutton;
+extern  GtkWidget *surface_skipbutton;
+
+extern GtkWidget *content_solidbutton;
+extern GtkWidget *content_windowbutton;
+extern GtkWidget *content_auxbutton;
+extern GtkWidget *content_lavabutton;
+extern GtkWidget *content_slimebutton;
+extern GtkWidget *content_waterbutton;
+extern GtkWidget *content_mistbutton;
+extern GtkWidget *content_areaportalbutton;
+extern GtkWidget *content_playerclipbutton;
+extern GtkWidget *content_monsterclipbutton;
+extern GtkWidget *content_current0button;
+extern GtkWidget *content_current90button;
+extern GtkWidget *content_current180button;
+extern GtkWidget *content_current270button;
+extern GtkWidget *content_currentUPbutton;
+extern GtkWidget *content_currentDOWNbutton;
+extern GtkWidget *content_originbutton;
+extern GtkWidget *content_detailbutton;
+extern GtkWidget *content_translucentbutton;
+extern GtkWidget *content_ladderbutton;
+
+extern  GtkWidget *surfacebutton;
+extern  GtkWidget *contentbutton;
+
+extern  GtkWidget *value_entry;
+extern  gboolean setup_buttons;
+
+extern  int working_surface_flags;
+extern  int surface_mask;
+extern  int working_content_flags;
+extern  int content_mask;
+extern  int working_value;
+*/
+
+#endif // _SURFACEFLAGSDIALOG_QUAKE2_H
diff --git a/plugins/surface_quake2/surfdlg_plugin.h b/plugins/surface_quake2/surfdlg_plugin.h
index 89129d45..f5391344 100644
--- a/plugins/surface_quake2/surfdlg_plugin.h
+++ b/plugins/surface_quake2/surfdlg_plugin.h
@@ -1,94 +1,94 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _SURFDLG_PLUGIN_H_
-#define _SURFDLG_PLUGIN_H_
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-#include "qerplugin.h"
-#include "synapse.h"
-#include "iselectedface.h"
-#include "iundo.h"
-#include "ishaders.h"
-#include "mathlib.h"
-#include "missing.h"
-#include "idata.h"
-
-#include "isurfaceplugin.h"
-
-class SurfaceDialog : public IPluginTexdef
-{
-	int refCount;
-public:
-	// Increment the number of references to this object
-	void IncRef () { refCount++; }
-	// Decrement the reference count
-	void DecRef () { if ( --refCount <= 0 ) delete this; }
-};
-
-extern _QERFuncTable_1 	g_FuncTable;
-extern _QERUndoTable g_UndoTable;
-extern _QERAppSurfaceTable g_AppSurfaceTable;
-extern _QERSelectedFaceTable g_SelectedFaceTable;
-extern _QERShadersTable g_ShadersTable;
-extern _QERAppShadersTable g_AppShadersTable;
-extern _QERAppDataTable g_AppDataTable;
-
-#define GetSelectedFaceCount g_SelectedFaceTable.m_pfnGetSelectedFaceCount
-
-#define Undo_Undo g_UndoTable.m_pfnUndo_Undo
-#define Undo_GetUndoId g_UndoTable.m_pfnUndo_GetUndoId
-
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
-#define Sys_UpdateWindows g_FuncTable.m_pfnSysUpdateWindows
-
-
-#define Select_FitTexture g_AppSurfaceTable.m_pfnSelect_FitTexture
-#define Get_SI_Inc g_AppSurfaceTable.m_pfnQERApp_QeglobalsSavedinfo_SIInc
-#define GridSize g_AppSurfaceTable.m_pfnQeglobalsGetGridSize
-#define FaceList_FitTexture g_AppSurfaceTable.m_pfnFaceList_FitTexture
-#define GetMainWindow g_AppSurfaceTable.m_pfnGetMainWindow
-#define GetSelectedFaceCountfromBrushes g_AppSurfaceTable.m_pfnGetSelectedFaceCountfromBrushes
-#define GetSelFacesTexdef g_AppSurfaceTable.m_pfnGetSelFacesTexdef
-#define SetTexdef_FaceList g_AppSurfaceTable.m_pfnSetTexdef_FaceList
-#define SetWinPos_from_Prefs g_AppSurfaceTable.m_pfnSetWinPos_From_Prefs
-
-#define Texturewin g_AppShadersTable.m_pfnQeglobalsTexturewin
-
-#endif // _SURFDLG_PLUGIN_H_
-
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _SURFDLG_PLUGIN_H_
+#define _SURFDLG_PLUGIN_H_
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+#include "qerplugin.h"
+#include "synapse.h"
+#include "iselectedface.h"
+#include "iundo.h"
+#include "ishaders.h"
+#include "mathlib.h"
+#include "missing.h"
+#include "idata.h"
+
+#include "isurfaceplugin.h"
+
+class SurfaceDialog : public IPluginTexdef
+{
+	int refCount;
+public:
+	// Increment the number of references to this object
+	void IncRef () { refCount++; }
+	// Decrement the reference count
+	void DecRef () { if ( --refCount <= 0 ) delete this; }
+};
+
+extern _QERFuncTable_1 	g_FuncTable;
+extern _QERUndoTable g_UndoTable;
+extern _QERAppSurfaceTable g_AppSurfaceTable;
+extern _QERSelectedFaceTable g_SelectedFaceTable;
+extern _QERShadersTable g_ShadersTable;
+extern _QERAppShadersTable g_AppShadersTable;
+extern _QERAppDataTable g_AppDataTable;
+
+#define GetSelectedFaceCount g_SelectedFaceTable.m_pfnGetSelectedFaceCount
+
+#define Undo_Undo g_UndoTable.m_pfnUndo_Undo
+#define Undo_GetUndoId g_UndoTable.m_pfnUndo_GetUndoId
+
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+#define Sys_UpdateWindows g_FuncTable.m_pfnSysUpdateWindows
+
+
+#define Select_FitTexture g_AppSurfaceTable.m_pfnSelect_FitTexture
+#define Get_SI_Inc g_AppSurfaceTable.m_pfnQERApp_QeglobalsSavedinfo_SIInc
+#define GridSize g_AppSurfaceTable.m_pfnQeglobalsGetGridSize
+#define FaceList_FitTexture g_AppSurfaceTable.m_pfnFaceList_FitTexture
+#define GetMainWindow g_AppSurfaceTable.m_pfnGetMainWindow
+#define GetSelectedFaceCountfromBrushes g_AppSurfaceTable.m_pfnGetSelectedFaceCountfromBrushes
+#define GetSelFacesTexdef g_AppSurfaceTable.m_pfnGetSelFacesTexdef
+#define SetTexdef_FaceList g_AppSurfaceTable.m_pfnSetTexdef_FaceList
+#define SetWinPos_from_Prefs g_AppSurfaceTable.m_pfnSetWinPos_From_Prefs
+
+#define Texturewin g_AppShadersTable.m_pfnQeglobalsTexturewin
+
+#endif // _SURFDLG_PLUGIN_H_
+
diff --git a/plugins/textool/2DView.h b/plugins/textool/2DView.h
index 4f8eac97..59163f80 100644
--- a/plugins/textool/2DView.h
+++ b/plugins/textool/2DView.h
@@ -1,70 +1,70 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// a class to provide basic services for 2D view of a world
-// window <-> local 2D space transforms
-// snap to grid
-// TODO: this one could be placed under an interface, and provided to the editor as a service
-
-#ifndef _2DVIEW_H_
-#define _2DVIEW_H_
-
-class C2DView
-{
-  enum		E2DViewState { View_Idle, View_Move } ViewState;
-  int			m_xPosMove, m_yPosMove;
-  float		m_MinsMove[2], m_MaxsMove[2];
-  qboolean	m_bDoGrid;
-  float		m_GridStep[2];
-  qboolean m_bPopup;
-public:
-  RECT m_rect;
-  float m_Mins[2],m_Maxs[2],m_Center[2];
-  C2DView()
-    {
-      ViewState = View_Idle; 
-      m_bDoGrid = false;
-      m_bPopup = false;
-    }
-  ~C2DView() { }
-  void SetGrid( float xGridStep, float yGridStep )
-    {	m_bDoGrid = true; m_GridStep[0] = xGridStep; m_GridStep[1] = yGridStep;	}
-
-  // get window coordinates for space coordinates
-  void WindowForSpace( int &x, int &y, const float c[2]);
-  void SpaceForWindow( float c[2], int x, int y);
-  void GridForWindow( float c[2], int x, int y);
-  qboolean DoesSelect( int x, int y, float c[2] );
-  void PreparePaint();
-
-  bool OnRButtonDown (int x, int y);
-  bool OnMouseMove (int x, int y);
-  bool OnRButtonUp (int x, int y);
-  bool OnKeyDown (char *s);
-
-  void ZoomIn();
-  void ZoomOut();
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// a class to provide basic services for 2D view of a world
+// window <-> local 2D space transforms
+// snap to grid
+// TODO: this one could be placed under an interface, and provided to the editor as a service
+
+#ifndef _2DVIEW_H_
+#define _2DVIEW_H_
+
+class C2DView
+{
+  enum		E2DViewState { View_Idle, View_Move } ViewState;
+  int			m_xPosMove, m_yPosMove;
+  float		m_MinsMove[2], m_MaxsMove[2];
+  qboolean	m_bDoGrid;
+  float		m_GridStep[2];
+  qboolean m_bPopup;
+public:
+  RECT m_rect;
+  float m_Mins[2],m_Maxs[2],m_Center[2];
+  C2DView()
+    {
+      ViewState = View_Idle; 
+      m_bDoGrid = false;
+      m_bPopup = false;
+    }
+  ~C2DView() { }
+  void SetGrid( float xGridStep, float yGridStep )
+    {	m_bDoGrid = true; m_GridStep[0] = xGridStep; m_GridStep[1] = yGridStep;	}
+
+  // get window coordinates for space coordinates
+  void WindowForSpace( int &x, int &y, const float c[2]);
+  void SpaceForWindow( float c[2], int x, int y);
+  void GridForWindow( float c[2], int x, int y);
+  qboolean DoesSelect( int x, int y, float c[2] );
+  void PreparePaint();
+
+  bool OnRButtonDown (int x, int y);
+  bool OnMouseMove (int x, int y);
+  bool OnRButtonUp (int x, int y);
+  bool OnKeyDown (char *s);
+
+  void ZoomIn();
+  void ZoomOut();
+};
+
+#endif
diff --git a/plugins/textool/ControlPointsManager.h b/plugins/textool/ControlPointsManager.h
index 00502c37..70374005 100644
--- a/plugins/textool/ControlPointsManager.h
+++ b/plugins/textool/ControlPointsManager.h
@@ -1,133 +1,133 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// a class to handle control points in a 2D view
-// TODO: this one can be placed under an interface, and provided to the editor as service
-//
-// NOTE: the C2DView *m_p2DView is the orthogonal mapping between window and ST space
-// in Drag mode (for rotation) we need an orthonormal XY space
-// we do ST <-> XY transformations using the texture size
-// ( for translation-only moves, orthogonal is enough )
-// FIXME: is there a better way to deal between Window space <-> ST space <-> XY space ?
-//
-// NOTE: ControlPointsManagers are a bit different between brush faces and patches
-// so there's a base virtual class, and we have two versions
-
-#ifndef _CONTROLPOINTSMANAGER_H_
-#define _CONTROLPOINTSMANAGER_H_
-
-class CControlPointsManager
-{
-protected:
-  // used by Render
-  _QERQglTable *m_pQglTable;
-  C2DView		*m_p2DView;
-public:
-  CControlPointsManager() { m_pQglTable = NULL; m_p2DView = NULL; }
-  virtual ~CControlPointsManager() { }
-  void Init( C2DView *p2DView, _QERQglTable *pQglTable ) { m_pQglTable = pQglTable; m_p2DView = p2DView; }
-
-  virtual bool OnLButtonDown (int x, int y) = 0;
-  virtual bool OnMouseMove (int x, int y) = 0;
-  virtual bool OnLButtonUp (int x, int y) = 0;
-
-  virtual void Render() = 0;
-  virtual void Commit() = 0;
-};
-
-// brush face manager
-class CControlPointsManagerBFace : public CControlPointsManager
-{
-  enum		EManagerState { Idle, Drag } ManagerState;
-  int			m_NumPoints;
-  // initial geometry
-  CtrlPts_t	m_RefPts;
-  // current geometry
-  CtrlPts_t	*m_pPts;
-  // transform matrix ( 2DView is Window <-> ST )
-  float		m_TM[2][3];
-  // texture size for ST <-> XY
-  int			m_TexSize[2];
-  // used when translating
-  float		m_TransOffset[2];
-  // dragged point index
-  int			m_iDragPoint;
-  // do we have an anchor ?
-  bool		m_bGotAnchor;
-  // anchor point index
-  int			m_iAnchorPoint;
-  // coordinates of Anchor
-  float		m_Anchor[2];
-  // used for commit
-  _QERFaceData	*m_pFaceData;
-
-public:
-  // construction / init -------------------------------------------------
-  CControlPointsManagerBFace() { ManagerState = Idle; }
-  virtual ~CControlPointsManagerBFace() { }
-  // NOTE: pQglTable is sent to CControlPointsManager::Init
-  void Init(int iPts, CtrlPts_t *Pts, C2DView *p2DView, int TexSize[2], _QERFaceData* pFaceData, _QERQglTable *pQglTable);
-  // CControlPointsManager interface -------------------------------------
-
-  virtual bool OnLButtonDown (int x, int y);
-  virtual bool OnMouseMove (int x, int y);
-  virtual bool OnLButtonUp (int x, int y);
-
-  virtual void Render();
-  virtual void Commit();
-
-private:
-  // internal members
-  void UpdateCtrlPts();
-  void ComputeTransOffset(int i);
-  void XYSpaceForSTSpace( float xy[2], const float st[2] );
-};
-
-// patch manager
-class CControlPointsManagerPatch : public CControlPointsManager
-{
-  enum		EManagerState { Idle, Drag } ManagerState;
-  // reference data, used for commits
-  patchMesh_t* m_pPatch;
-  // work patch, holds current data
-  patchMesh_t* m_pWorkPatch;
-  int			m_iDragPoint[2];
-
-public:
-  // construction / init -------------------------------------------------
-  CControlPointsManagerPatch() { ManagerState = Idle; }
-  virtual ~CControlPointsManagerPatch() { }
-  // NOTE: pQglTable is sent to CControlPointsManager::Init
-  void Init( patchMesh_t* pWorkPatch, C2DView *p2DView, _QERQglTable *pQglTable, patchMesh_t* pPatch );
-  // CControlPointsManager interface -------------------------------------
-
-  virtual bool OnLButtonDown (int x, int y);
-  virtual bool OnMouseMove (int x, int y);
-  virtual bool OnLButtonUp (int x, int y);
-
-  virtual void Render();
-  virtual void Commit();
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// a class to handle control points in a 2D view
+// TODO: this one can be placed under an interface, and provided to the editor as service
+//
+// NOTE: the C2DView *m_p2DView is the orthogonal mapping between window and ST space
+// in Drag mode (for rotation) we need an orthonormal XY space
+// we do ST <-> XY transformations using the texture size
+// ( for translation-only moves, orthogonal is enough )
+// FIXME: is there a better way to deal between Window space <-> ST space <-> XY space ?
+//
+// NOTE: ControlPointsManagers are a bit different between brush faces and patches
+// so there's a base virtual class, and we have two versions
+
+#ifndef _CONTROLPOINTSMANAGER_H_
+#define _CONTROLPOINTSMANAGER_H_
+
+class CControlPointsManager
+{
+protected:
+  // used by Render
+  _QERQglTable *m_pQglTable;
+  C2DView		*m_p2DView;
+public:
+  CControlPointsManager() { m_pQglTable = NULL; m_p2DView = NULL; }
+  virtual ~CControlPointsManager() { }
+  void Init( C2DView *p2DView, _QERQglTable *pQglTable ) { m_pQglTable = pQglTable; m_p2DView = p2DView; }
+
+  virtual bool OnLButtonDown (int x, int y) = 0;
+  virtual bool OnMouseMove (int x, int y) = 0;
+  virtual bool OnLButtonUp (int x, int y) = 0;
+
+  virtual void Render() = 0;
+  virtual void Commit() = 0;
+};
+
+// brush face manager
+class CControlPointsManagerBFace : public CControlPointsManager
+{
+  enum		EManagerState { Idle, Drag } ManagerState;
+  int			m_NumPoints;
+  // initial geometry
+  CtrlPts_t	m_RefPts;
+  // current geometry
+  CtrlPts_t	*m_pPts;
+  // transform matrix ( 2DView is Window <-> ST )
+  float		m_TM[2][3];
+  // texture size for ST <-> XY
+  int			m_TexSize[2];
+  // used when translating
+  float		m_TransOffset[2];
+  // dragged point index
+  int			m_iDragPoint;
+  // do we have an anchor ?
+  bool		m_bGotAnchor;
+  // anchor point index
+  int			m_iAnchorPoint;
+  // coordinates of Anchor
+  float		m_Anchor[2];
+  // used for commit
+  _QERFaceData	*m_pFaceData;
+
+public:
+  // construction / init -------------------------------------------------
+  CControlPointsManagerBFace() { ManagerState = Idle; }
+  virtual ~CControlPointsManagerBFace() { }
+  // NOTE: pQglTable is sent to CControlPointsManager::Init
+  void Init(int iPts, CtrlPts_t *Pts, C2DView *p2DView, int TexSize[2], _QERFaceData* pFaceData, _QERQglTable *pQglTable);
+  // CControlPointsManager interface -------------------------------------
+
+  virtual bool OnLButtonDown (int x, int y);
+  virtual bool OnMouseMove (int x, int y);
+  virtual bool OnLButtonUp (int x, int y);
+
+  virtual void Render();
+  virtual void Commit();
+
+private:
+  // internal members
+  void UpdateCtrlPts();
+  void ComputeTransOffset(int i);
+  void XYSpaceForSTSpace( float xy[2], const float st[2] );
+};
+
+// patch manager
+class CControlPointsManagerPatch : public CControlPointsManager
+{
+  enum		EManagerState { Idle, Drag } ManagerState;
+  // reference data, used for commits
+  patchMesh_t* m_pPatch;
+  // work patch, holds current data
+  patchMesh_t* m_pWorkPatch;
+  int			m_iDragPoint[2];
+
+public:
+  // construction / init -------------------------------------------------
+  CControlPointsManagerPatch() { ManagerState = Idle; }
+  virtual ~CControlPointsManagerPatch() { }
+  // NOTE: pQglTable is sent to CControlPointsManager::Init
+  void Init( patchMesh_t* pWorkPatch, C2DView *p2DView, _QERQglTable *pQglTable, patchMesh_t* pPatch );
+  // CControlPointsManager interface -------------------------------------
+
+  virtual bool OnLButtonDown (int x, int y);
+  virtual bool OnMouseMove (int x, int y);
+  virtual bool OnLButtonUp (int x, int y);
+
+  virtual void Render();
+  virtual void Commit();
+};
+
+#endif
diff --git a/plugins/textool/StdAfx.h b/plugins/textool/StdAfx.h
index 2a2da9c3..f54bb591 100644
--- a/plugins/textool/StdAfx.h
+++ b/plugins/textool/StdAfx.h
@@ -1,154 +1,154 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// stdafx.h
-// precompiled headers
-
-// standard headers
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtk.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#if defined(__linux__) || defined(__APPLE__)
-
-// Necessary for proper boolean type declaration
-#include "qertypes.h"
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#define MB_OK                       0x00000000L
-#define MB_OKCANCEL                 0x00000001L
-#define MB_ABORTRETRYIGNORE         0x00000002L
-#define MB_YESNOCANCEL              0x00000003L
-#define MB_YESNO                    0x00000004L
-#define MB_RETRYCANCEL              0x00000005L
- 
- 
-#define MB_ICONHAND                 0x00000010L
-#define MB_ICONQUESTION             0x00000020L
-#define MB_ICONEXCLAMATION          0x00000030L
-#define MB_ICONASTERISK             0x00000040L
- 
-#define MB_USERICON                 0x00000080L
-#define MB_ICONWARNING              MB_ICONEXCLAMATION
-#define MB_ICONERROR                MB_ICONHAND
-#define MB_ICONINFORMATION          MB_ICONASTERISK
-#define MB_ICONSTOP                 MB_ICONHAND
- 
-#define MB_TYPEMASK                 0x0000000FL
-#define MB_ICONMASK                 0x000000F0L
-#define MB_DEFMASK                  0x00000F00L
-#define MB_MODEMASK                 0x00003000L
-#define MB_MISCMASK                 0x0000C000L
- 
-#define IDOK                1
-#define IDCANCEL            2
-#define IDABORT             3
-#define IDRETRY             4
-#define IDIGNORE            5
-#define IDYES               6
-#define IDNO                7
-
-typedef struct tagRECT
-{
-    long    left;
-    long    top;
-    long    right;
-    long    bottom;
-} RECT, *PRECT, *LPRECT;
-
-#endif // __linux__
-
-// plugin
-// FIXME TTimo: drop this
-extern "C" void Sys_Printf (char *text, ...);
-
-#include "synapse.h"
-#include "iplugin.h"
-#include "qerplugin.h"
-#include "mathlib.h"
-#include "igl.h"
-#include "iselectedface.h"
-#include "isurfaceplugin.h"
-#include "iui.h"
-
-// internals
-// the implementation of a IWindowListener interface to use with the native UI
-// TODO: move in it's own set of files?
-// NOTE: I'm not too sure about the bool flags being any use.. they are supposed to tell if we handle the event or not
-class CWindowListener : public IWindowListener
-{
-  int refCount;
-public:
-  // Increment the number of references to this object
-  void IncRef () { refCount++; }
-  // Decrement the reference count
-  void DecRef () { if ( --refCount <= 0 ) delete this; }
-  // IWindowListener ---------------------------------------
-  bool OnLButtonDown(guint32 nFlags, double x, double y);
-	bool OnMButtonDown(guint32 nFlags, double x, double y) { return false; }
-	bool OnRButtonDown(guint32 nFlags, double x, double y);
-  bool OnLButtonUp(guint32 nFlags, double x, double y);
-	bool OnMButtonUp(guint32 nFlags, double x, double y) { return false; }
-	bool OnRButtonUp(guint32 nFlags, double x, double y);
-  bool OnMouseMove(guint32 nFlags, double x, double y);
-  bool OnKeyPressed(char *s);
-  bool Paint();
-  void Close();
-};
-
-#include "2DView.h"
-typedef struct
-{
-	float	data[MAX_POINTS_ON_WINDING][2];
-} CtrlPts_t;
-#include "ControlPointsManager.h"
-
-extern _QERQglTable		        g_QglTable;
-extern _QERFuncTable_1			g_FuncTable;
-// prefs globals
-// NOTE: these are used by the CControlPointsManager classes, not very C++ish
-extern bool						g_bPrefsUpdateCameraView;
-extern _QERSelectedFaceTable	g_SelectedFaceTable;
-extern _QERFaceData				g_CancelFaceData;
-
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
-
-// call to validate the current changes into the editor
-extern void Textool_Validate();
-extern void Textool_Cancel();
-
-class CSynapseClientTexTool : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  
-  CSynapseClientTexTool() { }
-  virtual ~CSynapseClientTexTool() { }
-};
-
-extern IWindow *g_pToolWnd;
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// stdafx.h
+// precompiled headers
+
+// standard headers
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtk.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#if defined(__linux__) || defined(__APPLE__)
+
+// Necessary for proper boolean type declaration
+#include "qertypes.h"
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#define MB_OK                       0x00000000L
+#define MB_OKCANCEL                 0x00000001L
+#define MB_ABORTRETRYIGNORE         0x00000002L
+#define MB_YESNOCANCEL              0x00000003L
+#define MB_YESNO                    0x00000004L
+#define MB_RETRYCANCEL              0x00000005L
+ 
+ 
+#define MB_ICONHAND                 0x00000010L
+#define MB_ICONQUESTION             0x00000020L
+#define MB_ICONEXCLAMATION          0x00000030L
+#define MB_ICONASTERISK             0x00000040L
+ 
+#define MB_USERICON                 0x00000080L
+#define MB_ICONWARNING              MB_ICONEXCLAMATION
+#define MB_ICONERROR                MB_ICONHAND
+#define MB_ICONINFORMATION          MB_ICONASTERISK
+#define MB_ICONSTOP                 MB_ICONHAND
+ 
+#define MB_TYPEMASK                 0x0000000FL
+#define MB_ICONMASK                 0x000000F0L
+#define MB_DEFMASK                  0x00000F00L
+#define MB_MODEMASK                 0x00003000L
+#define MB_MISCMASK                 0x0000C000L
+ 
+#define IDOK                1
+#define IDCANCEL            2
+#define IDABORT             3
+#define IDRETRY             4
+#define IDIGNORE            5
+#define IDYES               6
+#define IDNO                7
+
+typedef struct tagRECT
+{
+    long    left;
+    long    top;
+    long    right;
+    long    bottom;
+} RECT, *PRECT, *LPRECT;
+
+#endif // __linux__
+
+// plugin
+// FIXME TTimo: drop this
+extern "C" void Sys_Printf (char *text, ...);
+
+#include "synapse.h"
+#include "iplugin.h"
+#include "qerplugin.h"
+#include "mathlib.h"
+#include "igl.h"
+#include "iselectedface.h"
+#include "isurfaceplugin.h"
+#include "iui.h"
+
+// internals
+// the implementation of a IWindowListener interface to use with the native UI
+// TODO: move in it's own set of files?
+// NOTE: I'm not too sure about the bool flags being any use.. they are supposed to tell if we handle the event or not
+class CWindowListener : public IWindowListener
+{
+  int refCount;
+public:
+  // Increment the number of references to this object
+  void IncRef () { refCount++; }
+  // Decrement the reference count
+  void DecRef () { if ( --refCount <= 0 ) delete this; }
+  // IWindowListener ---------------------------------------
+  bool OnLButtonDown(guint32 nFlags, double x, double y);
+	bool OnMButtonDown(guint32 nFlags, double x, double y) { return false; }
+	bool OnRButtonDown(guint32 nFlags, double x, double y);
+  bool OnLButtonUp(guint32 nFlags, double x, double y);
+	bool OnMButtonUp(guint32 nFlags, double x, double y) { return false; }
+	bool OnRButtonUp(guint32 nFlags, double x, double y);
+  bool OnMouseMove(guint32 nFlags, double x, double y);
+  bool OnKeyPressed(char *s);
+  bool Paint();
+  void Close();
+};
+
+#include "2DView.h"
+typedef struct
+{
+	float	data[MAX_POINTS_ON_WINDING][2];
+} CtrlPts_t;
+#include "ControlPointsManager.h"
+
+extern _QERQglTable		        g_QglTable;
+extern _QERFuncTable_1			g_FuncTable;
+// prefs globals
+// NOTE: these are used by the CControlPointsManager classes, not very C++ish
+extern bool						g_bPrefsUpdateCameraView;
+extern _QERSelectedFaceTable	g_SelectedFaceTable;
+extern _QERFaceData				g_CancelFaceData;
+
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+
+// call to validate the current changes into the editor
+extern void Textool_Validate();
+extern void Textool_Cancel();
+
+class CSynapseClientTexTool : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  
+  CSynapseClientTexTool() { }
+  virtual ~CSynapseClientTexTool() { }
+};
+
+extern IWindow *g_pToolWnd;
diff --git a/plugins/textool/resource.h b/plugins/textool/resource.h
index 22f6e86c..85ba8d7d 100644
--- a/plugins/textool/resource.h
+++ b/plugins/textool/resource.h
@@ -1,23 +1,23 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by TexTool.rc
-//
-#define IDUNDO                          3
-#define IDD_DIALOG                      101
-#define IDD_DIALOG2                     102
-#define IDR_DROP_MENU                   103
-#define ID_DROP_VALIDATE                40001
-#define ID_DROP_ZOOMIN                  40002
-#define ID_DROP_ZOOMOUT                 40003
-#define ID_DROP_CANCEL                  40004
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        104
-#define _APS_NEXT_COMMAND_VALUE         40005
-#define _APS_NEXT_CONTROL_VALUE         1001
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by TexTool.rc
+//
+#define IDUNDO                          3
+#define IDD_DIALOG                      101
+#define IDD_DIALOG2                     102
+#define IDR_DROP_MENU                   103
+#define ID_DROP_VALIDATE                40001
+#define ID_DROP_ZOOMIN                  40002
+#define ID_DROP_ZOOMOUT                 40003
+#define ID_DROP_CANCEL                  40004
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        104
+#define _APS_NEXT_COMMAND_VALUE         40005
+#define _APS_NEXT_CONTROL_VALUE         1001
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/plugins/vfspak/vfs.h b/plugins/vfspak/vfs.h
index a206a1fc..6e595cc9 100644
--- a/plugins/vfspak/vfs.h
+++ b/plugins/vfspak/vfs.h
@@ -1,52 +1,52 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _VFS_H_
-#define _VFS_H_
-
-#define VFS_MAXDIRS 8
-
-void vfsInitDirectory (const char *path);
-void vfsShutdown ();
-
-GSList* vfsGetFileList (const char *dir, const char *ext);
-GSList* vfsGetDirList (const char *dir);
-void vfsClearFileDirList (GSList **lst);
-int vfsGetFileCount (const char *filename, int flag);
-int vfsLoadFile (const char *filename, void **buffer, int index = 0);
-
-void vfsFreeFile (void *p);
-int vfsLoadFullPathFile (const char *filename, void **buffer);
-void vfsCleanFileName(char *);
-const char* vfsBasePromptPath();
-char* vfsExtractRelativePath(const char *in);
-char* vfsGetFullPath(const char*, int index = 0, int flag = 0);
-
-#endif // _VFS_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _VFS_H_
+#define _VFS_H_
+
+#define VFS_MAXDIRS 8
+
+void vfsInitDirectory (const char *path);
+void vfsShutdown ();
+
+GSList* vfsGetFileList (const char *dir, const char *ext);
+GSList* vfsGetDirList (const char *dir);
+void vfsClearFileDirList (GSList **lst);
+int vfsGetFileCount (const char *filename, int flag);
+int vfsLoadFile (const char *filename, void **buffer, int index = 0);
+
+void vfsFreeFile (void *p);
+int vfsLoadFullPathFile (const char *filename, void **buffer);
+void vfsCleanFileName(char *);
+const char* vfsBasePromptPath();
+char* vfsExtractRelativePath(const char *in);
+char* vfsGetFullPath(const char*, int index = 0, int flag = 0);
+
+#endif // _VFS_H_
diff --git a/plugins/vfspak/vfspak.h b/plugins/vfspak/vfspak.h
index 4676ac37..2e10ca62 100644
--- a/plugins/vfspak/vfspak.h
+++ b/plugins/vfspak/vfspak.h
@@ -1,64 +1,64 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _VFSPAK_H_
-#define _VFSPAK_H_
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-#include "synapse.h"
-#include "qerplugin.h"
-#include "ifilesystem.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern CSynapseServer* g_pSynapseServer;
-
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
-
-class CSynapseClientVFS : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName();
-  
-  CSynapseClientVFS() { }
-  virtual ~CSynapseClientVFS() { }
-};
-
-#endif // _VFSPAK_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _VFSPAK_H_
+#define _VFSPAK_H_
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+#include "synapse.h"
+#include "qerplugin.h"
+#include "ifilesystem.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern CSynapseServer* g_pSynapseServer;
+
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+
+class CSynapseClientVFS : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName();
+  
+  CSynapseClientVFS() { }
+  virtual ~CSynapseClientVFS() { }
+};
+
+#endif // _VFSPAK_H_
diff --git a/plugins/vfspk3/unzip-vfspk3.h b/plugins/vfspk3/unzip-vfspk3.h
index 930de283..001a1f54 100644
--- a/plugins/vfspk3/unzip-vfspk3.h
+++ b/plugins/vfspk3/unzip-vfspk3.h
@@ -1,299 +1,299 @@
-#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
-/* like the STRICT of WIN32, we define a pointer that cannot be converted
-    from (void*) without cast */
-typedef struct TagunzFile__ { int unused; } unzFile__; 
-typedef unzFile__ *unzFile;
-#else
-typedef void* unzFile;
-#endif
-
-
-/* tm_unz contain date/time info */
-typedef struct tm_unz_s 
-{
-	unsigned int tm_sec;            /* seconds after the minute - [0,59] */
-	unsigned int tm_min;            /* minutes after the hour - [0,59] */
-	unsigned int tm_hour;           /* hours since midnight - [0,23] */
-	unsigned int tm_mday;           /* day of the month - [1,31] */
-	unsigned int tm_mon;            /* months since January - [0,11] */
-	unsigned int tm_year;           /* years - [1980..2044] */
-} tm_unz;
-
-/* unz_global_info structure contain global data about the ZIPfile
-   These data comes from the end of central dir */
-typedef struct unz_global_info_s
-{
-	unsigned long number_entry;         /* total number of entries in the central dir on this disk */
-	unsigned long size_comment;         /* size of the global comment of the zipfile */
-} unz_global_info;
-
-
-/* unz_file_info contain information about a file in the zipfile */
-typedef struct unz_file_info_s
-{
-    unsigned long version;              /* version made by                 2 unsigned chars */
-    unsigned long version_needed;       /* version needed to extract       2 unsigned chars */
-    unsigned long flag;                 /* general purpose bit flag        2 unsigned chars */
-    unsigned long compression_method;   /* compression method              2 unsigned chars */
-    unsigned long dosDate;              /* last mod file date in Dos fmt   4 unsigned chars */
-    unsigned long crc;                  /* crc-32                          4 unsigned chars */
-    unsigned long compressed_size;      /* compressed size                 4 unsigned chars */ 
-    unsigned long uncompressed_size;    /* uncompressed size               4 unsigned chars */ 
-    unsigned long size_filename;        /* filename length                 2 unsigned chars */
-    unsigned long size_file_extra;      /* extra field length              2 unsigned chars */
-    unsigned long size_file_comment;    /* file comment length             2 unsigned chars */
-
-    unsigned long disk_num_start;       /* disk number start               2 unsigned chars */
-    unsigned long internal_fa;          /* internal file attributes        2 unsigned chars */
-    unsigned long external_fa;          /* external file attributes        4 unsigned chars */
-
-    tm_unz tmu_date;
-} unz_file_info;
-
-/* unz_file_info_interntal contain internal info about a file in zipfile*/
-typedef struct unz_file_info_internal_s
-{
-    unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
-} unz_file_info_internal;
-
-typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
-typedef void   (*free_func) (void* opaque, void* address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    unsigned char    *next_in;  /* next input unsigned char */
-    unsigned int     avail_in;  /* number of unsigned chars available at next_in */
-    unsigned long    total_in;  /* total nb of input unsigned chars read so */
-
-    unsigned char    *next_out; /* next output unsigned char should be put there */
-    unsigned int     avail_out; /* remaining free space at next_out */
-    unsigned long    total_out; /* total nb of unsigned chars output so */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    unsigned char*     opaque;  /* private data object passed to zalloc and zfree */
-
-    int     data_type;  /* best guess about the data type: ascii or binary */
-    unsigned long   adler;      /* adler32 value of the uncompressed data */
-    unsigned long   reserved;   /* reserved for future use */
-} z_stream;
-
-typedef z_stream *z_streamp;
-
-
-/* file_in_zip_read_info_s contain internal information about a file in zipfile,
-    when reading and decompress it */
-typedef struct
-{
-	char  *read_buffer;         /* internal buffer for compressed data */
-	z_stream stream;            /* zLib stream structure for inflate */
-
-	unsigned long pos_in_zipfile;       /* position in unsigned char on the zipfile, for fseek*/
-	unsigned long stream_initialised;   /* flag set if stream structure is initialised*/
-
-	unsigned long offset_local_extrafield;/* offset of the static extra field */
-	unsigned int  size_local_extrafield;/* size of the static extra field */
-	unsigned long pos_local_extrafield;   /* position in the static extra field in read*/
-
-	unsigned long crc32;                /* crc32 of all data uncompressed */
-	unsigned long crc32_wait;           /* crc32 we must obtain after decompress all */
-	unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
-	unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
-	FILE* file;                 /* io structore of the zipfile */
-	unsigned long compression_method;   /* compression method (0==store) */
-	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
-} file_in_zip_read_info_s;
-
-
-/* unz_s contain internal information about the zipfile
-*/
-typedef struct
-{
-	FILE* file;                 /* io structore of the zipfile */
-	unz_global_info gi;       /* public global information */
-	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
-	unsigned long num_file;             /* number of the current file in the zipfile*/
-	unsigned long pos_in_central_dir;   /* pos of the current file in the central dir*/
-	unsigned long current_file_ok;      /* flag about the usability of the current file*/
-	unsigned long central_pos;          /* position of the beginning of the central dir*/
-
-	unsigned long size_central_dir;     /* size of the central directory  */
-	unsigned long offset_central_dir;   /* offset of start of central directory with
-								   respect to the starting disk number */
-
-	unz_file_info cur_file_info; /* public info about the current file in zip*/
-	unz_file_info_internal cur_file_info_internal; /* private info about it*/
-    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
-	                                    file if we are decompressing it */
-} unz_s;
-
-#define UNZ_OK                                  (0)
-#define UNZ_END_OF_LIST_OF_FILE (-100)
-#define UNZ_ERRNO               (Z_ERRNO)
-#define UNZ_EOF                 (0)
-#define UNZ_PARAMERROR                  (-102)
-#define UNZ_BADZIPFILE                  (-103)
-#define UNZ_INTERNALERROR               (-104)
-#define UNZ_CRCERROR                    (-105)
-
-#define UNZ_CASESENSITIVE		1
-#define UNZ_NOTCASESENSITIVE	2
-#define UNZ_OSDEFAULTCASE		0
-
-extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
-
-/*
-   Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-								or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
-	(like 1 on Unix, 2 on Windows)
-*/
-
-extern unzFile unzOpen (const char *path);
-extern unzFile unzReOpen (const char* path, unzFile file);
-
-/*
-  Open a Zip file. path contain the full pathname (by example,
-     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
-	 "zlib/zlib111.zip".
-	 If the zipfile cannot be opened (file don't exist or in not valid), the
-	   return value is NULL.
-     Else, the return value is a unzFile Handle, usable with other function
-	   of this unzip package.
-*/
-
-extern int unzClose (unzFile file);
-
-/*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
-  return UNZ_OK if there is no problem. */
-
-extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
-
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem. */
-
-
-extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
-
-/*
-  Get the global comment string of the ZipFile, in the szComment buffer.
-  uSizeBuf is the size of the szComment buffer.
-  return the number of unsigned char copied or an error code <0
-*/
-
-
-/***************************************************************************/
-/* Unzip package allow you browse the directory of the zipfile */
-
-extern int unzGoToFirstFile (unzFile file);
-
-/*
-  Set the current file of the zipfile to the first file.
-  return UNZ_OK if there is no problem
-*/
-
-extern int unzGoToNextFile (unzFile file);
-
-/*
-  Set the current file of the zipfile to the next file.
-  return UNZ_OK if there is no problem
-  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
-*/
-
-extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
-
-/*
-  Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzStringFileNameCompare
-
-  return value :
-  UNZ_OK if the file is found. It becomes the current file.
-  UNZ_END_OF_LIST_OF_FILE if the file is not found
-*/
-
-
-extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
-
-/*
-  Get Info about the current file
-  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
-	    the current file
-  if szFileName!=NULL, the filemane string will be copied in szFileName
-			(fileNameBufferSize is the size of the buffer)
-  if extraField!=NULL, the extra field information will be copied in extraField
-			(extraFieldBufferSize is the size of the buffer).
-			This is the Central-header version of the extra field
-  if szComment!=NULL, the comment string of the file will be copied in szComment
-			(commentBufferSize is the size of the buffer)
-*/
-
-/***************************************************************************/
-/* for reading the content of the current zipfile, you can open it, read data
-   from it, and close it (you can close it before reading all the file)
-   */
-
-extern int unzOpenCurrentFile (unzFile file);
-
-/*
-  Open for reading data the current file in the zipfile.
-  If there is no error, the return value is UNZ_OK.
-*/
-
-extern int unzCloseCurrentFile (unzFile file);
-
-/*
-  Close the file in zip opened with unzOpenCurrentFile
-  Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-
-												
-extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
-
-/*
-  Read unsigned chars from the current file (opened by unzOpenCurrentFile)
-  buf contain buffer where data must be copied
-  len the size of buf.
-
-  return the number of unsigned char copied if somes unsigned chars are copied
-  return 0 if the end of file was reached
-  return <0 with error code if there is an error
-    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-
-extern long unztell(unzFile file);
-
-/*
-  Give the current position in uncompressed data
-*/
-
-extern int unzeof (unzFile file);
-
-/*
-  return 1 if the end of file was reached, 0 elsewhere 
-*/
-
-extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
-
-/*
-  Read extra field from the current file (opened by unzOpenCurrentFile)
-  This is the local-header version of the extra field (sometimes, there is
-    more info in the local-header version than in the central-header)
-
-  if buf==NULL, it return the size of the local extra field
-
-  if buf!=NULL, len is the size of the buffer, the extra header is copied in
-	buf.
-  the return value is the number of unsigned chars copied in buf, or (if <0) 
-	the error code
-*/
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__; 
+typedef unzFile__ *unzFile;
+#else
+typedef void* unzFile;
+#endif
+
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s 
+{
+	unsigned int tm_sec;            /* seconds after the minute - [0,59] */
+	unsigned int tm_min;            /* minutes after the hour - [0,59] */
+	unsigned int tm_hour;           /* hours since midnight - [0,23] */
+	unsigned int tm_mday;           /* day of the month - [1,31] */
+	unsigned int tm_mon;            /* months since January - [0,11] */
+	unsigned int tm_year;           /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+   These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+	unsigned long number_entry;         /* total number of entries in the central dir on this disk */
+	unsigned long size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+    unsigned long version;              /* version made by                 2 unsigned chars */
+    unsigned long version_needed;       /* version needed to extract       2 unsigned chars */
+    unsigned long flag;                 /* general purpose bit flag        2 unsigned chars */
+    unsigned long compression_method;   /* compression method              2 unsigned chars */
+    unsigned long dosDate;              /* last mod file date in Dos fmt   4 unsigned chars */
+    unsigned long crc;                  /* crc-32                          4 unsigned chars */
+    unsigned long compressed_size;      /* compressed size                 4 unsigned chars */ 
+    unsigned long uncompressed_size;    /* uncompressed size               4 unsigned chars */ 
+    unsigned long size_filename;        /* filename length                 2 unsigned chars */
+    unsigned long size_file_extra;      /* extra field length              2 unsigned chars */
+    unsigned long size_file_comment;    /* file comment length             2 unsigned chars */
+
+    unsigned long disk_num_start;       /* disk number start               2 unsigned chars */
+    unsigned long internal_fa;          /* internal file attributes        2 unsigned chars */
+    unsigned long external_fa;          /* external file attributes        4 unsigned chars */
+
+    tm_unz tmu_date;
+} unz_file_info;
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+    unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
+} unz_file_info_internal;
+
+typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
+typedef void   (*free_func) (void* opaque, void* address);
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    unsigned char    *next_in;  /* next input unsigned char */
+    unsigned int     avail_in;  /* number of unsigned chars available at next_in */
+    unsigned long    total_in;  /* total nb of input unsigned chars read so */
+
+    unsigned char    *next_out; /* next output unsigned char should be put there */
+    unsigned int     avail_out; /* remaining free space at next_out */
+    unsigned long    total_out; /* total nb of unsigned chars output so */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    unsigned char*     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    unsigned long   adler;      /* adler32 value of the uncompressed data */
+    unsigned long   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream *z_streamp;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+    when reading and decompress it */
+typedef struct
+{
+	char  *read_buffer;         /* internal buffer for compressed data */
+	z_stream stream;            /* zLib stream structure for inflate */
+
+	unsigned long pos_in_zipfile;       /* position in unsigned char on the zipfile, for fseek*/
+	unsigned long stream_initialised;   /* flag set if stream structure is initialised*/
+
+	unsigned long offset_local_extrafield;/* offset of the static extra field */
+	unsigned int  size_local_extrafield;/* size of the static extra field */
+	unsigned long pos_local_extrafield;   /* position in the static extra field in read*/
+
+	unsigned long crc32;                /* crc32 of all data uncompressed */
+	unsigned long crc32_wait;           /* crc32 we must obtain after decompress all */
+	unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
+	unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
+	FILE* file;                 /* io structore of the zipfile */
+	unsigned long compression_method;   /* compression method (0==store) */
+	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+	FILE* file;                 /* io structore of the zipfile */
+	unz_global_info gi;       /* public global information */
+	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
+	unsigned long num_file;             /* number of the current file in the zipfile*/
+	unsigned long pos_in_central_dir;   /* pos of the current file in the central dir*/
+	unsigned long current_file_ok;      /* flag about the usability of the current file*/
+	unsigned long central_pos;          /* position of the beginning of the central dir*/
+
+	unsigned long size_central_dir;     /* size of the central directory  */
+	unsigned long offset_central_dir;   /* offset of start of central directory with
+								   respect to the starting disk number */
+
+	unz_file_info cur_file_info; /* public info about the current file in zip*/
+	unz_file_info_internal cur_file_info_internal; /* private info about it*/
+    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+	                                    file if we are decompressing it */
+} unz_s;
+
+#define UNZ_OK                                  (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO               (Z_ERRNO)
+#define UNZ_EOF                 (0)
+#define UNZ_PARAMERROR                  (-102)
+#define UNZ_BADZIPFILE                  (-103)
+#define UNZ_INTERNALERROR               (-104)
+#define UNZ_CRCERROR                    (-105)
+
+#define UNZ_CASESENSITIVE		1
+#define UNZ_NOTCASESENSITIVE	2
+#define UNZ_OSDEFAULTCASE		0
+
+extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
+
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+								or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+	(like 1 on Unix, 2 on Windows)
+*/
+
+extern unzFile unzOpen (const char *path);
+extern unzFile unzReOpen (const char* path, unzFile file);
+
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
+	 "zlib/zlib111.zip".
+	 If the zipfile cannot be opened (file don't exist or in not valid), the
+	   return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+	   of this unzip package.
+*/
+
+extern int unzClose (unzFile file);
+
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+
+extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+
+
+extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
+
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of unsigned char copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int unzGoToFirstFile (unzFile file);
+
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+
+extern int unzGoToNextFile (unzFile file);
+
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
+
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
+
+/*
+  Get Info about the current file
+  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+	    the current file
+  if szFileName!=NULL, the filemane string will be copied in szFileName
+			(fileNameBufferSize is the size of the buffer)
+  if extraField!=NULL, the extra field information will be copied in extraField
+			(extraFieldBufferSize is the size of the buffer).
+			This is the Central-header version of the extra field
+  if szComment!=NULL, the comment string of the file will be copied in szComment
+			(commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+   from it, and close it (you can close it before reading all the file)
+   */
+
+extern int unzOpenCurrentFile (unzFile file);
+
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int unzCloseCurrentFile (unzFile file);
+
+/*
+  Close the file in zip opened with unzOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+												
+extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
+
+/*
+  Read unsigned chars from the current file (opened by unzOpenCurrentFile)
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of unsigned char copied if somes unsigned chars are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern long unztell(unzFile file);
+
+/*
+  Give the current position in uncompressed data
+*/
+
+extern int unzeof (unzFile file);
+
+/*
+  return 1 if the end of file was reached, 0 elsewhere 
+*/
+
+extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
+
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+	buf.
+  the return value is the number of unsigned chars copied in buf, or (if <0) 
+	the error code
+*/
diff --git a/plugins/vfspk3/vfs.h b/plugins/vfspk3/vfs.h
index 8ab7cddd..bfb3479e 100644
--- a/plugins/vfspk3/vfs.h
+++ b/plugins/vfspk3/vfs.h
@@ -1,68 +1,68 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _VFS_H_
-#define _VFS_H_
-
-#define VFS_MAXDIRS 8
-
-void vfsInitDirectory (const char *path);
-void vfsShutdown ();
-void vfsFreeFile (void *p);
-GSList* vfsGetFileList (const char *dir, const char *ext);
-GSList* vfsGetDirList (const char *dir);
-void vfsClearFileDirList (GSList **lst);
-int vfsGetFileCount (const char *filename, int flag);
-int vfsLoadFile (const char *filename, void **buffer, int index = 0);
-int vfsLoadFullPathFile (const char *filename, void **buffer);
-
-// some useful functions
-// clean a file name to a unique representation
-// very usefull if you have to do some weird manips on the files
-// works on regular files and dirs
-// will convert to lowercase, unix path ('/' filename seperator)
-// on win32, will build the short path name
-// directories will be cleaned, no ending filename seperator
-// we modify the entry directly, the size of the string can only go down
-void vfsCleanFileName(char *);
-// these return a static char*, doesn't need to be freed or anything
-// get the base path to use when raising file dialogs
-// we manually add "maps/" or "sounds/" or "mapobjects/models/" etc.
-const char* vfsBasePromptPath();
-// extract the relative path from a full path
-// will match against any of the base paths we have
-// returns NULL if not found
-char* vfsExtractRelativePath(const char *in);
-// returns the full path (in a static buff) to a file given it's relative path
-// returns the first file in the list or NULL if not found
-// see ifilesystem.h for more notes
-char* vfsGetFullPath(const char*, int index = 0, int flag = 0);
-
-#endif // _VFS_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _VFS_H_
+#define _VFS_H_
+
+#define VFS_MAXDIRS 8
+
+void vfsInitDirectory (const char *path);
+void vfsShutdown ();
+void vfsFreeFile (void *p);
+GSList* vfsGetFileList (const char *dir, const char *ext);
+GSList* vfsGetDirList (const char *dir);
+void vfsClearFileDirList (GSList **lst);
+int vfsGetFileCount (const char *filename, int flag);
+int vfsLoadFile (const char *filename, void **buffer, int index = 0);
+int vfsLoadFullPathFile (const char *filename, void **buffer);
+
+// some useful functions
+// clean a file name to a unique representation
+// very usefull if you have to do some weird manips on the files
+// works on regular files and dirs
+// will convert to lowercase, unix path ('/' filename seperator)
+// on win32, will build the short path name
+// directories will be cleaned, no ending filename seperator
+// we modify the entry directly, the size of the string can only go down
+void vfsCleanFileName(char *);
+// these return a static char*, doesn't need to be freed or anything
+// get the base path to use when raising file dialogs
+// we manually add "maps/" or "sounds/" or "mapobjects/models/" etc.
+const char* vfsBasePromptPath();
+// extract the relative path from a full path
+// will match against any of the base paths we have
+// returns NULL if not found
+char* vfsExtractRelativePath(const char *in);
+// returns the full path (in a static buff) to a file given it's relative path
+// returns the first file in the list or NULL if not found
+// see ifilesystem.h for more notes
+char* vfsGetFullPath(const char*, int index = 0, int flag = 0);
+
+#endif // _VFS_H_
diff --git a/plugins/vfspk3/vfspk3.h b/plugins/vfspk3/vfspk3.h
index 1462656f..20dc95fe 100644
--- a/plugins/vfspk3/vfspk3.h
+++ b/plugins/vfspk3/vfspk3.h
@@ -1,63 +1,63 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _VFSPK3_H_
-#define _VFSPK3_H_
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-#include "synapse.h"
-#include "qerplugin.h"
-#include "ifilesystem.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern CSynapseServer* g_pSynapseServer;
-
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
-
-class CSynapseClientVFS : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  
-  CSynapseClientVFS() { }
-  virtual ~CSynapseClientVFS() { }
-};
-
-#endif // _VFSPK3_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _VFSPK3_H_
+#define _VFSPK3_H_
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+#include "synapse.h"
+#include "qerplugin.h"
+#include "ifilesystem.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern CSynapseServer* g_pSynapseServer;
+
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+
+class CSynapseClientVFS : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  
+  CSynapseClientVFS() { }
+  virtual ~CSynapseClientVFS() { }
+};
+
+#endif // _VFSPK3_H_
diff --git a/plugins/vfswad/unwad.h b/plugins/vfswad/unwad.h
index e1170531..074a75ea 100644
--- a/plugins/vfswad/unwad.h
+++ b/plugins/vfswad/unwad.h
@@ -1,111 +1,111 @@
-
-#ifndef _WAD3_H_
-#define _WAD3_H_
-
-// WAD3 (Half-Life) Header and mip structs
-// WAD2 (Quake) Header and mip structs added by LordHavoc
-
-#define WADBUFSIZE 32768
-
-#define WAD2_TYPE_MIP	0x44
-#define WAD2_ID			('W' | 'A' << 8 | 'D' << 16 | '2' << 24)
-#define WAD3_TYPE_MIP	0x43
-#define WAD3_ID			('W' | 'A' << 8 | 'D' << 16 | '3' << 24)
-#define GET_MIP_DATA_SIZE(WIDTH, HEIGHT)		((WIDTH * HEIGHT) + (WIDTH * HEIGHT / 4) + (WIDTH * HEIGHT / 16) + (WIDTH * HEIGHT / 64))
-
-/*
-
-  WAD3 pseudo-structure:
-
-	WAD3 Header
-	Mip section
-		First mip
-			Mip header
-			First mip (width * height)
-			Second mip (width * height / 4)
-			Third mip (width * height / 16)
-			Fourth mip (width * height / 64)
-			Palette size (WORD)
-			Palette (Palette size * 3)
-			Padding (WORD)
-		[...]
-		Last mip
-	Lump table
-		First lump entry
-			Lump header
-		[...]
-		Last lump entry
-
-  WAD2 pseudo-structure:
-
-	WAD2 Header
-	Mip section
-		First mip
-			Mip header
-			First mip (width * height)
-			Second mip (width * height / 4)
-			Third mip (width * height / 16)
-			Fourth mip (width * height / 64)
-		[...]
-		Last mip
-	Lump table
-		First lump entry
-			Lump header
-		[...]
-		Last lump entry
-*/
-
-#define DWORD unsigned int
-#define BYTE unsigned char
-#define WORD unsigned short int
-
-typedef struct
-{
-	DWORD		identification;
-	DWORD		numlumps;
-	DWORD		infotableofs;			// Lump table
-} WAD3_HEADER, *LPWAD3_HEADER;
-
-typedef struct
-{
-	DWORD		filepos;
-	DWORD		disksize;
-	DWORD		size;					// uncompressed
-	BYTE		type;
-	BYTE		compression;
-	BYTE		pad1, pad2;
-	char		name[16];				// must be null terminated
-} WAD3_LUMP, *LPWAD3_LUMP;
-
-typedef struct
-{
-	char		name[16];
-	DWORD		width, height;
-	DWORD		offsets[4];		// four mip maps stored
-} WAD3_MIP, *LPWAD3_MIP;
-
-
-typedef struct wadFile_s
-{
-	FILE * fin;
-	LPWAD3_HEADER	lpHeader;
-	LPWAD3_LUMP		lpLump;
-	LPWAD3_MIP		lpMip;
-
-	DWORD FileSize;
-  unsigned long currentfile;
-  char *wadfilename;
-} wadFile_t;
-
-
-wadFile_t *wadOpen(const char* path);
-wadFile_t *wadCleanup(wadFile_t *wf);
-int wadGoToFirstFile(wadFile_t *wf);
-int wadGetCurrentFileInfo (	wadFile_t *wf, char *szFileName, unsigned long fileNameBufferSize, unsigned long *filesize);
-int wadGoToNextFile(wadFile_t *wf);
-
-int wadOpenCurrentFileByNum (wadFile_t *wf, unsigned long filenumber);
-void wadCloseCurrentFile (wadFile_t *wf);
-unsigned long wadReadCurrentFile (wadFile_t *wf , char *bufferptr, unsigned long size);
-
-#endif		// #ifndef _WAD3_H_
+
+#ifndef _WAD3_H_
+#define _WAD3_H_
+
+// WAD3 (Half-Life) Header and mip structs
+// WAD2 (Quake) Header and mip structs added by LordHavoc
+
+#define WADBUFSIZE 32768
+
+#define WAD2_TYPE_MIP	0x44
+#define WAD2_ID			('W' | 'A' << 8 | 'D' << 16 | '2' << 24)
+#define WAD3_TYPE_MIP	0x43
+#define WAD3_ID			('W' | 'A' << 8 | 'D' << 16 | '3' << 24)
+#define GET_MIP_DATA_SIZE(WIDTH, HEIGHT)		((WIDTH * HEIGHT) + (WIDTH * HEIGHT / 4) + (WIDTH * HEIGHT / 16) + (WIDTH * HEIGHT / 64))
+
+/*
+
+  WAD3 pseudo-structure:
+
+	WAD3 Header
+	Mip section
+		First mip
+			Mip header
+			First mip (width * height)
+			Second mip (width * height / 4)
+			Third mip (width * height / 16)
+			Fourth mip (width * height / 64)
+			Palette size (WORD)
+			Palette (Palette size * 3)
+			Padding (WORD)
+		[...]
+		Last mip
+	Lump table
+		First lump entry
+			Lump header
+		[...]
+		Last lump entry
+
+  WAD2 pseudo-structure:
+
+	WAD2 Header
+	Mip section
+		First mip
+			Mip header
+			First mip (width * height)
+			Second mip (width * height / 4)
+			Third mip (width * height / 16)
+			Fourth mip (width * height / 64)
+		[...]
+		Last mip
+	Lump table
+		First lump entry
+			Lump header
+		[...]
+		Last lump entry
+*/
+
+#define DWORD unsigned int
+#define BYTE unsigned char
+#define WORD unsigned short int
+
+typedef struct
+{
+	DWORD		identification;
+	DWORD		numlumps;
+	DWORD		infotableofs;			// Lump table
+} WAD3_HEADER, *LPWAD3_HEADER;
+
+typedef struct
+{
+	DWORD		filepos;
+	DWORD		disksize;
+	DWORD		size;					// uncompressed
+	BYTE		type;
+	BYTE		compression;
+	BYTE		pad1, pad2;
+	char		name[16];				// must be null terminated
+} WAD3_LUMP, *LPWAD3_LUMP;
+
+typedef struct
+{
+	char		name[16];
+	DWORD		width, height;
+	DWORD		offsets[4];		// four mip maps stored
+} WAD3_MIP, *LPWAD3_MIP;
+
+
+typedef struct wadFile_s
+{
+	FILE * fin;
+	LPWAD3_HEADER	lpHeader;
+	LPWAD3_LUMP		lpLump;
+	LPWAD3_MIP		lpMip;
+
+	DWORD FileSize;
+  unsigned long currentfile;
+  char *wadfilename;
+} wadFile_t;
+
+
+wadFile_t *wadOpen(const char* path);
+wadFile_t *wadCleanup(wadFile_t *wf);
+int wadGoToFirstFile(wadFile_t *wf);
+int wadGetCurrentFileInfo (	wadFile_t *wf, char *szFileName, unsigned long fileNameBufferSize, unsigned long *filesize);
+int wadGoToNextFile(wadFile_t *wf);
+
+int wadOpenCurrentFileByNum (wadFile_t *wf, unsigned long filenumber);
+void wadCloseCurrentFile (wadFile_t *wf);
+unsigned long wadReadCurrentFile (wadFile_t *wf , char *bufferptr, unsigned long size);
+
+#endif		// #ifndef _WAD3_H_
diff --git a/plugins/vfswad/vfs.h b/plugins/vfswad/vfs.h
index 155e993d..ec9791f8 100644
--- a/plugins/vfswad/vfs.h
+++ b/plugins/vfswad/vfs.h
@@ -1,69 +1,69 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used
-to endorse or promote products derived from this software without specific prior
-written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef _VFS_H_
-#define _VFS_H_
-
-#define VFS_MAXDIRS 8
-
-void vfsInitDirectory (const char *path);
-void vfsShutdown ();
-void vfsFreeFile (void *p);
-GSList* vfsGetFileList (const char *dir, const char *ext);
-GSList* vfsGetDirList (const char *dir);
-void vfsClearFileDirList (GSList **lst);
-int vfsGetFileCount (const char *filename, int flag);
-int vfsLoadFile (const char *filename, void **buffer, int index = 0);
-int vfsLoadFullPathFile (const char *filename, void **buffer);
-
-// some useful functions
-// clean a file name to a unique representation
-// very usefull if you have to do some weird manips on the files
-// works on regular files and dirs
-// will convert to lowercase, unix path ('/' filename seperator)
-// on win32, will build the short path name
-// directories will be cleaned, no ending filename seperator
-// we modify the entry directly, the size of the string can only go down
-void vfsCleanFileName(char *);
-// these return a static char*, doesn't need to be freed or anything
-// get the base path to use when raising file dialogs
-// we manually add "maps/" or "sounds/" or "mapobjects/models/" etc.
-const char* vfsBasePromptPath();
-// extract the relative path from a full path
-// will match against any of the base paths we have
-// returns NULL if not found
-char* vfsExtractRelativePath(const char *in);
-// returns the full path (in a static buff) to a file given it's relative path
-// returns the first file in the list or NULL if not found
-// see ifilesystem.h for more notes
-char* vfsGetFullPath(const char*, int index = 0, int flag = 0);
-
-
-#endif // _VFS_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used
+to endorse or promote products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _VFS_H_
+#define _VFS_H_
+
+#define VFS_MAXDIRS 8
+
+void vfsInitDirectory (const char *path);
+void vfsShutdown ();
+void vfsFreeFile (void *p);
+GSList* vfsGetFileList (const char *dir, const char *ext);
+GSList* vfsGetDirList (const char *dir);
+void vfsClearFileDirList (GSList **lst);
+int vfsGetFileCount (const char *filename, int flag);
+int vfsLoadFile (const char *filename, void **buffer, int index = 0);
+int vfsLoadFullPathFile (const char *filename, void **buffer);
+
+// some useful functions
+// clean a file name to a unique representation
+// very usefull if you have to do some weird manips on the files
+// works on regular files and dirs
+// will convert to lowercase, unix path ('/' filename seperator)
+// on win32, will build the short path name
+// directories will be cleaned, no ending filename seperator
+// we modify the entry directly, the size of the string can only go down
+void vfsCleanFileName(char *);
+// these return a static char*, doesn't need to be freed or anything
+// get the base path to use when raising file dialogs
+// we manually add "maps/" or "sounds/" or "mapobjects/models/" etc.
+const char* vfsBasePromptPath();
+// extract the relative path from a full path
+// will match against any of the base paths we have
+// returns NULL if not found
+char* vfsExtractRelativePath(const char *in);
+// returns the full path (in a static buff) to a file given it's relative path
+// returns the first file in the list or NULL if not found
+// see ifilesystem.h for more notes
+char* vfsGetFullPath(const char*, int index = 0, int flag = 0);
+
+
+#endif // _VFS_H_
diff --git a/plugins/vfswad/vfswad.h b/plugins/vfswad/vfswad.h
index 7e8cbb85..4845d591 100644
--- a/plugins/vfswad/vfswad.h
+++ b/plugins/vfswad/vfswad.h
@@ -1,63 +1,63 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used
-to endorse or promote products derived from this software without specific prior
-written permission.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifndef _VFSWAD_H_
-#define _VFSWAD_H_
-
-#ifdef __linux__
-
-typedef void* HMODULE;
-typedef void* LPVOID;
-typedef char* LPCSTR;
-
-#endif // __linux__
-
-#include "synapse.h"
-#include "qerplugin.h"
-#include "ifilesystem.h"
-
-extern _QERFuncTable_1 g_FuncTable;
-extern CSynapseServer* g_pSynapseServer;
-
-#define Sys_Printf g_FuncTable.m_pfnSysPrintf
-#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
-
-class CSynapseClientVFS : public CSynapseClient
-{
-public:
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  
-  CSynapseClientVFS() { }
-  virtual ~CSynapseClientVFS() { }
-};
-
-#endif // _VFSWAD_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used
+to endorse or promote products derived from this software without specific prior
+written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#ifndef _VFSWAD_H_
+#define _VFSWAD_H_
+
+#ifdef __linux__
+
+typedef void* HMODULE;
+typedef void* LPVOID;
+typedef char* LPCSTR;
+
+#endif // __linux__
+
+#include "synapse.h"
+#include "qerplugin.h"
+#include "ifilesystem.h"
+
+extern _QERFuncTable_1 g_FuncTable;
+extern CSynapseServer* g_pSynapseServer;
+
+#define Sys_Printf g_FuncTable.m_pfnSysPrintf
+#define Sys_FPrintf g_FuncTable.m_pfnSysFPrintf
+
+class CSynapseClientVFS : public CSynapseClient
+{
+public:
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  
+  CSynapseClientVFS() { }
+  virtual ~CSynapseClientVFS() { }
+};
+
+#endif // _VFSWAD_H_
diff --git a/radiant/brush.h b/radiant/brush.h
index dc0a6641..08a5e057 100644
--- a/radiant/brush.h
+++ b/radiant/brush.h
@@ -1,89 +1,89 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-// brush.h
-
-// some usefull flags to control the behaviour of Brush_Build
-extern bool g_bBuildWindingsNoTexBuild;
-
-void		Brush_AddToList (brush_t *b, brush_t *lst);
-void		Brush_Build(brush_t *b, bool bSnap = true, bool bMarkMap = true, bool bConvert = false, bool bFilterTest = true);
-void    Brush_SetBuildWindingsNoTexBuild(bool bBuild);
-void		Brush_BuildWindings( brush_t *b, bool bSnap = true );
-brush_t*	Brush_Clone (brush_t *b);
-brush_t*	Brush_FullClone(brush_t *b);
-brush_t*	Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef);
-void    Brush_Resize(brush_t *b, vec3_t vMin, vec3_t vMax);
-void    Brush_FaceDraw(face_t *face, int nGLState);
-void		Brush_Draw( brush_t *b );
-void		Brush_DrawXY(brush_t *b, int nViewType);
-// set bRemoveNode to false to avoid trying to delete the item in group view tree control
-void		Brush_Free (brush_t *b, bool bRemoveNode = true);
-int			Brush_MemorySize(brush_t *b);
-void		Brush_MakeSided (int sides);
-void		Brush_MakeSidedCone (int sides);
-void		Brush_Move (brush_t *b, const vec3_t move, bool bSnap = true);
-int		Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap = true);
-void		Brush_ResetFaceOriginals(brush_t *b);
-face_t*		Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist, int nFlags = 0);
-void		Brush_RemoveFromList (brush_t *b);
-// bCaulk means the faces created during the operation will be caulked, this is used in conjunction with g_PrefsDlg.m_bClipCaulk
-void		Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back, boolean bCaulk = false);
-void		Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear);
-void		Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef* pPlugTexdef= (IPluginTexdef*)NULL);
-void		Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir, qboolean shear);
-void		Brush_SnapToGrid(brush_t *pb);
-void		Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild = true);
-void		Brush_MakeSidedSphere(int sides);
-//void		Brush_Write (brush_t *b, FILE *f);
-//void		Brush_Write (brush_t *b, MemStream* pMemFile);
-void		Brush_RemoveEmptyFaces ( brush_t *b );
-winding_t*	Brush_MakeFaceWinding (brush_t *b, face_t *face);
-
-void Brush_RefreshShader(brush_t *b);
-
-int			AddPlanept (float *f);
-float		SetShadeForPlane (plane_t *p);
-
-face_t* Face_Alloc( void );
-void		Face_Free( face_t *f );
-face_t* Face_Clone (face_t *f);
-void    Face_SetShader(face_t *face, const char *name);
-/*!
-faster version if you know the IShader already
-(instead of hash table lookup by name)
-*/
-void    Face_SetShader(face_t *face, IShader *shader);
-void    Face_MakePlane (face_t *f);
-void		Face_Draw( face_t *face );
-void		Face_TextureVectors (face_t *f, float STfromXYZ[2][4]);
-void		SetFaceTexdef (face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef* pPlugTexdef = NULL );
-
-void Face_FitTexture( face_t * face, int nHeight, int nWidth );
-void Brush_FitTexture( brush_t *b, int nHeight, int nWidth );
-//void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue);
-//const char* Brush_GetKeyValue(brush_t *b, const char *pKey);
-brush_t *Brush_Alloc();
-const char* Brush_Name(brush_t *b);
-
-//eclass_t* HasModel(brush_t *b);
-void aabb_draw(const aabb_t *aabb, int mode);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+// brush.h
+
+// some usefull flags to control the behaviour of Brush_Build
+extern bool g_bBuildWindingsNoTexBuild;
+
+void		Brush_AddToList (brush_t *b, brush_t *lst);
+void		Brush_Build(brush_t *b, bool bSnap = true, bool bMarkMap = true, bool bConvert = false, bool bFilterTest = true);
+void    Brush_SetBuildWindingsNoTexBuild(bool bBuild);
+void		Brush_BuildWindings( brush_t *b, bool bSnap = true );
+brush_t*	Brush_Clone (brush_t *b);
+brush_t*	Brush_FullClone(brush_t *b);
+brush_t*	Brush_Create (vec3_t mins, vec3_t maxs, texdef_t *texdef);
+void    Brush_Resize(brush_t *b, vec3_t vMin, vec3_t vMax);
+void    Brush_FaceDraw(face_t *face, int nGLState);
+void		Brush_Draw( brush_t *b );
+void		Brush_DrawXY(brush_t *b, int nViewType);
+// set bRemoveNode to false to avoid trying to delete the item in group view tree control
+void		Brush_Free (brush_t *b, bool bRemoveNode = true);
+int			Brush_MemorySize(brush_t *b);
+void		Brush_MakeSided (int sides);
+void		Brush_MakeSidedCone (int sides);
+void		Brush_Move (brush_t *b, const vec3_t move, bool bSnap = true);
+int		Brush_MoveVertex(brush_t *b, vec3_t vertex, vec3_t delta, vec3_t end, bool bSnap = true);
+void		Brush_ResetFaceOriginals(brush_t *b);
+face_t*		Brush_Ray (vec3_t origin, vec3_t dir, brush_t *b, float *dist, int nFlags = 0);
+void		Brush_RemoveFromList (brush_t *b);
+// bCaulk means the faces created during the operation will be caulked, this is used in conjunction with g_PrefsDlg.m_bClipCaulk
+void		Brush_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back, boolean bCaulk = false);
+void		Brush_SelectFaceForDragging (brush_t *b, face_t *f, qboolean shear);
+void		Brush_SetTexture (brush_t *b, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef* pPlugTexdef= (IPluginTexdef*)NULL);
+void		Brush_SideSelect (brush_t *b, vec3_t origin, vec3_t dir, qboolean shear);
+void		Brush_SnapToGrid(brush_t *pb);
+void		Brush_Rotate(brush_t *b, vec3_t vAngle, vec3_t vOrigin, bool bBuild = true);
+void		Brush_MakeSidedSphere(int sides);
+//void		Brush_Write (brush_t *b, FILE *f);
+//void		Brush_Write (brush_t *b, MemStream* pMemFile);
+void		Brush_RemoveEmptyFaces ( brush_t *b );
+winding_t*	Brush_MakeFaceWinding (brush_t *b, face_t *face);
+
+void Brush_RefreshShader(brush_t *b);
+
+int			AddPlanept (float *f);
+float		SetShadeForPlane (plane_t *p);
+
+face_t* Face_Alloc( void );
+void		Face_Free( face_t *f );
+face_t* Face_Clone (face_t *f);
+void    Face_SetShader(face_t *face, const char *name);
+/*!
+faster version if you know the IShader already
+(instead of hash table lookup by name)
+*/
+void    Face_SetShader(face_t *face, IShader *shader);
+void    Face_MakePlane (face_t *f);
+void		Face_Draw( face_t *face );
+void		Face_TextureVectors (face_t *f, float STfromXYZ[2][4]);
+void		SetFaceTexdef (face_t *f, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef* pPlugTexdef = NULL );
+
+void Face_FitTexture( face_t * face, int nHeight, int nWidth );
+void Brush_FitTexture( brush_t *b, int nHeight, int nWidth );
+//void Brush_SetEpair(brush_t *b, const char *pKey, const char *pValue);
+//const char* Brush_GetKeyValue(brush_t *b, const char *pKey);
+brush_t *Brush_Alloc();
+const char* Brush_Name(brush_t *b);
+
+//eclass_t* HasModel(brush_t *b);
+void aabb_draw(const aabb_t *aabb, int mode);
diff --git a/radiant/camera.h b/radiant/camera.h
index f7c90dd0..57a9fae2 100644
--- a/radiant/camera.h
+++ b/radiant/camera.h
@@ -1,83 +1,83 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// window system independent camera view code
-
-typedef enum
-{
-  cd_wire,
-  cd_solid,
-  cd_texture,
-  cd_light,
-//  cd_blend
-} camera_draw_mode;
-
-#define DRAW_GL_FILL          0x0001
-#define DRAW_GL_LIGHTING      0x0010
-#define DRAW_GL_TEXTURE_2D    0x0100
-#define DRAW_GL_BLEND         0x1000
-
-#define DRAW_GL_WIRE					0x0000
-#define DRAW_GL_FLAT					0x0001
-#define DRAW_GL_SOLID					0x0011
-#define DRAW_GL_TEXTURED			0x0111
-
-#define DRAW_WIRE							0
-#define DRAW_SOLID						1
-#define DRAW_TEXTURED					2
-
-// TTimo: camera code is a huge mess
-//   someone courageous should clean it up
-//   this will probably happen when we have new rendering code
-
-#define MOVE_FORWARD      0x001
-#define MOVE_BACK         0x002
-#define MOVE_ROTRIGHT     0x004
-#define MOVE_ROTLEFT      0x008
-#define MOVE_STRAFERIGHT  0x010
-#define MOVE_STRAFELEFT   0x020
-
-typedef struct
-{
-  int		width, height;
-
-  qboolean	timing;
-
-  vec3_t	origin;
-  // TTimo
-  // indexes: PITCH = 0 YAW = 1 ROLL = 3
-  // AFAIK in Radiant we always have ROLL=0
-  vec3_t	angles;
-
-  camera_draw_mode	draw_mode;
-  int draw_glstate;
-
-  vec3_t	color;			// background 
-
-  vec3_t  forward, right; // move matrix (TTimo: used to have up but it was not updated)
-  vec3_t	vup, vpn, vright;	// view matrix (taken from the GL_PROJECTION matrix)
-
-  float projection[4][4];
-  float modelview[4][4];
-
-  unsigned int movementflags;  // movement flags
-
-} camera_t;
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// window system independent camera view code
+
+typedef enum
+{
+  cd_wire,
+  cd_solid,
+  cd_texture,
+  cd_light,
+//  cd_blend
+} camera_draw_mode;
+
+#define DRAW_GL_FILL          0x0001
+#define DRAW_GL_LIGHTING      0x0010
+#define DRAW_GL_TEXTURE_2D    0x0100
+#define DRAW_GL_BLEND         0x1000
+
+#define DRAW_GL_WIRE					0x0000
+#define DRAW_GL_FLAT					0x0001
+#define DRAW_GL_SOLID					0x0011
+#define DRAW_GL_TEXTURED			0x0111
+
+#define DRAW_WIRE							0
+#define DRAW_SOLID						1
+#define DRAW_TEXTURED					2
+
+// TTimo: camera code is a huge mess
+//   someone courageous should clean it up
+//   this will probably happen when we have new rendering code
+
+#define MOVE_FORWARD      0x001
+#define MOVE_BACK         0x002
+#define MOVE_ROTRIGHT     0x004
+#define MOVE_ROTLEFT      0x008
+#define MOVE_STRAFERIGHT  0x010
+#define MOVE_STRAFELEFT   0x020
+
+typedef struct
+{
+  int		width, height;
+
+  qboolean	timing;
+
+  vec3_t	origin;
+  // TTimo
+  // indexes: PITCH = 0 YAW = 1 ROLL = 3
+  // AFAIK in Radiant we always have ROLL=0
+  vec3_t	angles;
+
+  camera_draw_mode	draw_mode;
+  int draw_glstate;
+
+  vec3_t	color;			// background 
+
+  vec3_t  forward, right; // move matrix (TTimo: used to have up but it was not updated)
+  vec3_t	vup, vpn, vright;	// view matrix (taken from the GL_PROJECTION matrix)
+
+  float projection[4][4];
+  float modelview[4][4];
+
+  unsigned int movementflags;  // movement flags
+
+} camera_t;
diff --git a/radiant/camwindow.h b/radiant/camwindow.h
index 98556b00..b8d1be75 100644
--- a/radiant/camwindow.h
+++ b/radiant/camwindow.h
@@ -1,171 +1,171 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _CAMWINDOW_H_
-#define _CAMWINDOW_H_
-
-class XYWnd;
-
-#include "glwindow.h"
-
-class rectangle_t
-{
-public:
-  rectangle_t()
-    : x(0), y(0), w(0), h(0)
-  {}
-  rectangle_t(float _x, float _y, float _w, float _h)
-    : x(_x), y(_y), w(_w), h(_h)
-  {}
-  float x;
-  float y;
-  float w;
-  float h;
-};
-
-class XORRectangle
-{
-public:
-  XORRectangle(GtkWidget* widget)
-    : m_widget(widget), m_gc(NULL)
-  {}
-  ~XORRectangle()
-  {
-    if(initialised())
-      gdk_gc_unref(m_gc);
-  }
-  void set(rectangle_t rectangle)
-  {
-    lazy_init();
-    draw();
-    m_rectangle = rectangle;
-    draw();
-  }
-private:
-  bool initialised() const
-  {
-    return m_gc != NULL;
-  }
-  void lazy_init()
-  {
-    if(!initialised())
-    {
-      m_gc = gdk_gc_new(m_widget->window);
-
-      GdkColor color = { 0, 0xffff, 0xffff, 0xffff, };
-      GdkColormap* colormap = gdk_window_get_colormap(m_widget->window);
-      gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE);
-      gdk_gc_copy(m_gc, m_widget->style->white_gc);
-      gdk_gc_set_foreground(m_gc, &color);
-      gdk_gc_set_background(m_gc, &color);
-
-      gdk_gc_set_function(m_gc, GDK_XOR);
-    }
-  }
-  void draw() const
-  {
-    const int x = (int)m_rectangle.x;
-    const int y = (int)m_rectangle.y;
-    const int w = (int)m_rectangle.w;
-    const int h = (int)m_rectangle.h;
-    gdk_draw_rectangle(m_widget->window, m_gc, TRUE, x, -(h) - (y - m_widget->allocation.height), w, h);
-  }
-
-  rectangle_t m_rectangle;
-
-  GdkGC* m_gc;
-  GtkWidget* m_widget;
-};
-
-class CamWnd : public GLWindow
-{
-public:
-  void MatchViewAxes(const vec3_t P, const vec3_t vec, int &axis, float &sgn);
-  void ReInitGL();
-  void BenchMark();
-  CamWnd();
-  virtual ~CamWnd();
-  camera_t *Camera(){return &m_Camera;};
-  void Cam_MouseControl(float dtime);
-  void Cam_ChangeFloor(qboolean up);
-  void ToggleFreeMove();
-  bool m_bFreeMove;
-
-protected:
-  void Cam_Init();
-  void Cam_BuildMatrix();
-  void Cam_PositionDrag();
-  void Cam_KeyControl(float dtime);
-  void Cam_MouseDown(int x, int y, int buttons);
-  void Cam_MouseUp (int x, int y, int buttons);
-  void Cam_MouseMoved (int x, int y, int buttons);
-  void InitCull();
-  qboolean CullBrush (brush_t *b);
-  void Cam_Draw();
-  void Cam_DrawStuff();
-  void Cam_DrawBrushes(int mode);
-  void Cam_DrawBrush(brush_t *b, int mode);
-
-  brush_t* m_TransBrushes[MAX_MAP_BRUSHES];
-  int m_nNumTransBrushes;
-  camera_t m_Camera;
-  int	m_nCambuttonstate;
-  int m_ptButtonX;
-  int m_ptCursorX;
-  int m_ptLastCursorX;
-  int m_ptLastCamCursorX;
-  int m_ptButtonY;
-  int m_ptCursorY;
-  int m_ptLastCursorY;
-  int m_ptLastCamCursorY;
-  face_t* m_pSide_select;
-  vec3_t m_vCull1;
-  vec3_t m_vCull2;
-  int m_nCullv1[3];
-  int m_nCullv2[3];
-  bool m_bClipMode;
-  guint m_FocusOutHandler_id;
-
-  void OnCreate ();
-  void OnExpose ();
-  void OnLButtonDown (guint32 flags, int x, int y);
-  void OnRButtonDown (guint32 flags, int x, int y);
-  void OnMButtonDown (guint32 flags, int x, int y);
-  void OnLButtonUp (guint32 flags, int pointx, int pointy);
-  void OnRButtonUp (guint32 flags, int pointx, int pointy);
-  void OnMButtonUp (guint32 flags, int pointx, int pointy);
-  void OnMouseMove (guint32 flags, int pointx, int pointy);
-  void OnMouseWheel(bool bUp);
-  void OnSize(int cx, int cy);
-
-protected:
-  void OriginalMouseDown (guint32 nFlags, int pointX, int pointY);
-  void OriginalMouseUp (guint32 nFlags, int pointX, int pointY);
-
-private:
-  XORRectangle m_XORRectangle;
-
-  // project a point in geometric space into camera space
-  void ProjectCamera(const vec3_t A, vec_t B[2]);
-};
-
-
-#endif // _CAMWINDOW_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _CAMWINDOW_H_
+#define _CAMWINDOW_H_
+
+class XYWnd;
+
+#include "glwindow.h"
+
+class rectangle_t
+{
+public:
+  rectangle_t()
+    : x(0), y(0), w(0), h(0)
+  {}
+  rectangle_t(float _x, float _y, float _w, float _h)
+    : x(_x), y(_y), w(_w), h(_h)
+  {}
+  float x;
+  float y;
+  float w;
+  float h;
+};
+
+class XORRectangle
+{
+public:
+  XORRectangle(GtkWidget* widget)
+    : m_widget(widget), m_gc(NULL)
+  {}
+  ~XORRectangle()
+  {
+    if(initialised())
+      gdk_gc_unref(m_gc);
+  }
+  void set(rectangle_t rectangle)
+  {
+    lazy_init();
+    draw();
+    m_rectangle = rectangle;
+    draw();
+  }
+private:
+  bool initialised() const
+  {
+    return m_gc != NULL;
+  }
+  void lazy_init()
+  {
+    if(!initialised())
+    {
+      m_gc = gdk_gc_new(m_widget->window);
+
+      GdkColor color = { 0, 0xffff, 0xffff, 0xffff, };
+      GdkColormap* colormap = gdk_window_get_colormap(m_widget->window);
+      gdk_colormap_alloc_color (colormap, &color, FALSE, TRUE);
+      gdk_gc_copy(m_gc, m_widget->style->white_gc);
+      gdk_gc_set_foreground(m_gc, &color);
+      gdk_gc_set_background(m_gc, &color);
+
+      gdk_gc_set_function(m_gc, GDK_XOR);
+    }
+  }
+  void draw() const
+  {
+    const int x = (int)m_rectangle.x;
+    const int y = (int)m_rectangle.y;
+    const int w = (int)m_rectangle.w;
+    const int h = (int)m_rectangle.h;
+    gdk_draw_rectangle(m_widget->window, m_gc, TRUE, x, -(h) - (y - m_widget->allocation.height), w, h);
+  }
+
+  rectangle_t m_rectangle;
+
+  GdkGC* m_gc;
+  GtkWidget* m_widget;
+};
+
+class CamWnd : public GLWindow
+{
+public:
+  void MatchViewAxes(const vec3_t P, const vec3_t vec, int &axis, float &sgn);
+  void ReInitGL();
+  void BenchMark();
+  CamWnd();
+  virtual ~CamWnd();
+  camera_t *Camera(){return &m_Camera;};
+  void Cam_MouseControl(float dtime);
+  void Cam_ChangeFloor(qboolean up);
+  void ToggleFreeMove();
+  bool m_bFreeMove;
+
+protected:
+  void Cam_Init();
+  void Cam_BuildMatrix();
+  void Cam_PositionDrag();
+  void Cam_KeyControl(float dtime);
+  void Cam_MouseDown(int x, int y, int buttons);
+  void Cam_MouseUp (int x, int y, int buttons);
+  void Cam_MouseMoved (int x, int y, int buttons);
+  void InitCull();
+  qboolean CullBrush (brush_t *b);
+  void Cam_Draw();
+  void Cam_DrawStuff();
+  void Cam_DrawBrushes(int mode);
+  void Cam_DrawBrush(brush_t *b, int mode);
+
+  brush_t* m_TransBrushes[MAX_MAP_BRUSHES];
+  int m_nNumTransBrushes;
+  camera_t m_Camera;
+  int	m_nCambuttonstate;
+  int m_ptButtonX;
+  int m_ptCursorX;
+  int m_ptLastCursorX;
+  int m_ptLastCamCursorX;
+  int m_ptButtonY;
+  int m_ptCursorY;
+  int m_ptLastCursorY;
+  int m_ptLastCamCursorY;
+  face_t* m_pSide_select;
+  vec3_t m_vCull1;
+  vec3_t m_vCull2;
+  int m_nCullv1[3];
+  int m_nCullv2[3];
+  bool m_bClipMode;
+  guint m_FocusOutHandler_id;
+
+  void OnCreate ();
+  void OnExpose ();
+  void OnLButtonDown (guint32 flags, int x, int y);
+  void OnRButtonDown (guint32 flags, int x, int y);
+  void OnMButtonDown (guint32 flags, int x, int y);
+  void OnLButtonUp (guint32 flags, int pointx, int pointy);
+  void OnRButtonUp (guint32 flags, int pointx, int pointy);
+  void OnMButtonUp (guint32 flags, int pointx, int pointy);
+  void OnMouseMove (guint32 flags, int pointx, int pointy);
+  void OnMouseWheel(bool bUp);
+  void OnSize(int cx, int cy);
+
+protected:
+  void OriginalMouseDown (guint32 nFlags, int pointX, int pointY);
+  void OriginalMouseUp (guint32 nFlags, int pointX, int pointY);
+
+private:
+  XORRectangle m_XORRectangle;
+
+  // project a point in geometric space into camera space
+  void ProjectCamera(const vec3_t A, vec_t B[2]);
+};
+
+
+#endif // _CAMWINDOW_H_
diff --git a/radiant/dialog.h b/radiant/dialog.h
index f9450efe..8ca4b27d 100644
--- a/radiant/dialog.h
+++ b/radiant/dialog.h
@@ -1,85 +1,85 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _DIALOG_H_
-#define _DIALOG_H_
-
-#include <gtk/gtk.h>
-#include "str.h"
-#include "gtkmisc.h"
-
-typedef enum
-{
-  DLG_CHECK_BOOL,
-  DLG_RADIO_INT,
-  DLG_ENTRY_TEXT,
-  DLG_ENTRY_FLOAT,
-  DLG_ENTRY_INT,
-  DLG_SPIN_FLOAT,
-  DLG_SPIN_INT,
-  DLG_ADJ_INT,
-  DLG_COMBO_INT
-} DLG_DATA_TYPE;
-
-class Dialog
-{
- public:
-  Dialog ();
-  virtual ~Dialog ();
-
-  /*! 
-  start modal dialog box
-  you need to use AddModalButton to select IDOK IDCANCEL buttons
-  */
-  int DoModal ();
-  void EndModal (int code);
-  virtual void BuildDialog () = 0;
-  virtual void UpdateData (bool retrieve);
-  virtual void PreModal () { };
-  virtual void PostModal (int code) { };
-  virtual void ShowDlg ();
-  virtual void HideDlg ();
-  void Create ();
-  void Destroy ();
-  GtkWidget* GetDlgWidget (const char* name)
-    { return GTK_WIDGET (g_object_get_data (G_OBJECT (m_pWidget), name)); }
-  GtkWidget* GetWidget ()
-    { return m_pWidget; }
-
- protected:
-  GtkWidget *m_pWidget;
-  int m_nLoop;
-  int m_nReturn;
-
-  void AddDialogData (GtkWidget *widget, void *buf, DLG_DATA_TYPE type)
-    { AddDialogData (GTK_OBJECT (widget), buf, type); };
-  void AddDialogData (GtkObject *object, void *buf, DLG_DATA_TYPE type);
-  /*!
-  used in overloaded BuildDialog implementations to configure modal behaviour easily
-  */
-  void AddModalButton (GtkWidget *widget, int ret);
-
- private:
-  GSList* m_pDataList;
-  bool    m_bNeedBuild;
-};
-
-#endif // _DIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _DIALOG_H_
+#define _DIALOG_H_
+
+#include <gtk/gtk.h>
+#include "str.h"
+#include "gtkmisc.h"
+
+typedef enum
+{
+  DLG_CHECK_BOOL,
+  DLG_RADIO_INT,
+  DLG_ENTRY_TEXT,
+  DLG_ENTRY_FLOAT,
+  DLG_ENTRY_INT,
+  DLG_SPIN_FLOAT,
+  DLG_SPIN_INT,
+  DLG_ADJ_INT,
+  DLG_COMBO_INT
+} DLG_DATA_TYPE;
+
+class Dialog
+{
+ public:
+  Dialog ();
+  virtual ~Dialog ();
+
+  /*! 
+  start modal dialog box
+  you need to use AddModalButton to select IDOK IDCANCEL buttons
+  */
+  int DoModal ();
+  void EndModal (int code);
+  virtual void BuildDialog () = 0;
+  virtual void UpdateData (bool retrieve);
+  virtual void PreModal () { };
+  virtual void PostModal (int code) { };
+  virtual void ShowDlg ();
+  virtual void HideDlg ();
+  void Create ();
+  void Destroy ();
+  GtkWidget* GetDlgWidget (const char* name)
+    { return GTK_WIDGET (g_object_get_data (G_OBJECT (m_pWidget), name)); }
+  GtkWidget* GetWidget ()
+    { return m_pWidget; }
+
+ protected:
+  GtkWidget *m_pWidget;
+  int m_nLoop;
+  int m_nReturn;
+
+  void AddDialogData (GtkWidget *widget, void *buf, DLG_DATA_TYPE type)
+    { AddDialogData (GTK_OBJECT (widget), buf, type); };
+  void AddDialogData (GtkObject *object, void *buf, DLG_DATA_TYPE type);
+  /*!
+  used in overloaded BuildDialog implementations to configure modal behaviour easily
+  */
+  void AddModalButton (GtkWidget *widget, int ret);
+
+ private:
+  GSList* m_pDataList;
+  bool    m_bNeedBuild;
+};
+
+#endif // _DIALOG_H_
diff --git a/radiant/eclass_def.h b/radiant/eclass_def.h
index b8738ac5..e7a6f07a 100644
--- a/radiant/eclass_def.h
+++ b/radiant/eclass_def.h
@@ -1,44 +1,44 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*! \file eclass_def.h
-    \brief the part shared between radiant core and it's builtin module eclass_def.cpp
-*/
-
-#ifndef _ECLASS_DEF_H_
-#define _ECLASS_DEF_H_
-
-class CSynapseBuiltinClientDef : public CSynapseBuiltinClient
-{
-  public:
-  CSynapseBuiltinClientDef() {}
-  virtual ~CSynapseBuiltinClientDef() {}
-
-  // CSynapseClient API
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-    
-  // CSynapseBuiltinClient API
-  void EnumerateInterfaces(CSynapseServer *server);
-  
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*! \file eclass_def.h
+    \brief the part shared between radiant core and it's builtin module eclass_def.cpp
+*/
+
+#ifndef _ECLASS_DEF_H_
+#define _ECLASS_DEF_H_
+
+class CSynapseBuiltinClientDef : public CSynapseBuiltinClient
+{
+  public:
+  CSynapseBuiltinClientDef() {}
+  virtual ~CSynapseBuiltinClientDef() {}
+
+  // CSynapseClient API
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+    
+  // CSynapseBuiltinClient API
+  void EnumerateInterfaces(CSynapseServer *server);
+  
+};
+
+#endif
diff --git a/radiant/feedback.h b/radiant/feedback.h
index 687fe94b..6fb93b6a 100644
--- a/radiant/feedback.h
+++ b/radiant/feedback.h
@@ -1,125 +1,125 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// classes used for describing geometry information from q3map feedback
-//
-
-#ifndef __Q3MAP_FEEDBACK__
-#define __Q3MAP_FEEDBACK__
-
-#include "libxml/parser.h"
-
-// a select message with a brush/entity select information
-class CSelectMsg : public ISAXHandler
-{
-  enum { SELECT_MESSAGE, SELECT_BRUSH } ESelectState;
-  GString *message;
-  int entitynum, brushnum;
-public:
-  CSelectMsg() { ESelectState = SELECT_MESSAGE; }
-  // SAX interface
-  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
-  void saxEndElement (message_info_t *ctx, const xmlChar *name);
-  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
-  // for use in the dialog window
-  char *getName() { return message->str; }
-  void Highlight();
-  void DropHighlight() { }
-};
-
-class CPointMsg : public ISAXHandler, public IGL2DWindow
-{
-  enum { POINT_MESSAGE, POINT_POINT } EPointState;
-  GString *message;
-  vec3_t pt;
-  int refCount;
-public:
-  CPointMsg() { EPointState = POINT_MESSAGE; refCount = 0; }
-  // SAX interface
-  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
-  void saxEndElement (message_info_t *ctx, const xmlChar *name);
-  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
-  // for use in the dialog window
-  char *getName() { return message->str; }
-  void Highlight();
-  void DropHighlight();
-
-  // IGL2DWindow interface --------------------------------
-	// Increment the number of references to this object
-  void IncRef () { refCount++; }
-	// Decrement the reference count
-  void DecRef () { refCount--; if (refCount <= 0) delete this; }
-	void Draw2D( VIEWTYPE vt );
-};
-
-class CWindingMsg : public ISAXHandler, public IGL2DWindow
-{
-  enum { WINDING_MESSAGE, WINDING_WINDING } EPointState;
-  GString *message;
-  vec3_t wt[256];
-  int numpoints;
-  int refCount;
-public:
-  CWindingMsg() { EPointState = WINDING_MESSAGE; refCount = 0; numpoints = 0; }
-  // SAX interface
-  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
-  void saxEndElement (message_info_t *ctx, const xmlChar *name);
-  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
-  // for use in the dialog window
-  char *getName() { return message->str; }
-  void Highlight();
-  void DropHighlight();
-
-  // IGL2DWindow interface --------------------------------
-	// Increment the number of references to this object
-  void IncRef () { refCount++; }
-	// Decrement the reference count
-  void DecRef () { refCount--; if (refCount <= 0) delete this; }
-	void Draw2D( VIEWTYPE vt );
-};
-
-class CDbgDlg : public Dialog
-{
-  GPtrArray *m_pFeedbackElements;
-  // the list widget we use in the dialog
-  GtkListStore* m_clist;
-  ISAXHandler *m_pHighlight;
-public:
-  CDbgDlg() { m_pFeedbackElements = g_ptr_array_new (); m_pHighlight = NULL; }
-  virtual ~CDbgDlg() { }
-  // refresh items
-  void Push (ISAXHandler *);
-  // clean the debug window, release all ISAXHanlders we have
-  void Init();
-  ISAXHandler *GetElement(gint row);
-  void SetHighlight(gint row);
-  void DropHighlight();
-//  void HideDlg();
-protected:
-  void BuildDialog ();
-};
-
-extern CDbgDlg g_DbgDlg;
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// classes used for describing geometry information from q3map feedback
+//
+
+#ifndef __Q3MAP_FEEDBACK__
+#define __Q3MAP_FEEDBACK__
+
+#include "libxml/parser.h"
+
+// a select message with a brush/entity select information
+class CSelectMsg : public ISAXHandler
+{
+  enum { SELECT_MESSAGE, SELECT_BRUSH } ESelectState;
+  GString *message;
+  int entitynum, brushnum;
+public:
+  CSelectMsg() { ESelectState = SELECT_MESSAGE; }
+  // SAX interface
+  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
+  void saxEndElement (message_info_t *ctx, const xmlChar *name);
+  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
+  // for use in the dialog window
+  char *getName() { return message->str; }
+  void Highlight();
+  void DropHighlight() { }
+};
+
+class CPointMsg : public ISAXHandler, public IGL2DWindow
+{
+  enum { POINT_MESSAGE, POINT_POINT } EPointState;
+  GString *message;
+  vec3_t pt;
+  int refCount;
+public:
+  CPointMsg() { EPointState = POINT_MESSAGE; refCount = 0; }
+  // SAX interface
+  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
+  void saxEndElement (message_info_t *ctx, const xmlChar *name);
+  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
+  // for use in the dialog window
+  char *getName() { return message->str; }
+  void Highlight();
+  void DropHighlight();
+
+  // IGL2DWindow interface --------------------------------
+	// Increment the number of references to this object
+  void IncRef () { refCount++; }
+	// Decrement the reference count
+  void DecRef () { refCount--; if (refCount <= 0) delete this; }
+	void Draw2D( VIEWTYPE vt );
+};
+
+class CWindingMsg : public ISAXHandler, public IGL2DWindow
+{
+  enum { WINDING_MESSAGE, WINDING_WINDING } EPointState;
+  GString *message;
+  vec3_t wt[256];
+  int numpoints;
+  int refCount;
+public:
+  CWindingMsg() { EPointState = WINDING_MESSAGE; refCount = 0; numpoints = 0; }
+  // SAX interface
+  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
+  void saxEndElement (message_info_t *ctx, const xmlChar *name);
+  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
+  // for use in the dialog window
+  char *getName() { return message->str; }
+  void Highlight();
+  void DropHighlight();
+
+  // IGL2DWindow interface --------------------------------
+	// Increment the number of references to this object
+  void IncRef () { refCount++; }
+	// Decrement the reference count
+  void DecRef () { refCount--; if (refCount <= 0) delete this; }
+	void Draw2D( VIEWTYPE vt );
+};
+
+class CDbgDlg : public Dialog
+{
+  GPtrArray *m_pFeedbackElements;
+  // the list widget we use in the dialog
+  GtkListStore* m_clist;
+  ISAXHandler *m_pHighlight;
+public:
+  CDbgDlg() { m_pFeedbackElements = g_ptr_array_new (); m_pHighlight = NULL; }
+  virtual ~CDbgDlg() { }
+  // refresh items
+  void Push (ISAXHandler *);
+  // clean the debug window, release all ISAXHanlders we have
+  void Init();
+  ISAXHandler *GetElement(gint row);
+  void SetHighlight(gint row);
+  void DropHighlight();
+//  void HideDlg();
+protected:
+  void BuildDialog ();
+};
+
+extern CDbgDlg g_DbgDlg;
+
+#endif
diff --git a/radiant/file.h b/radiant/file.h
index d9f1bd7e..03ec33fc 100644
--- a/radiant/file.h
+++ b/radiant/file.h
@@ -1,119 +1,119 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-//
-//	file.h
-////////////////////////////////////////////////////
-
-#ifndef _FILE_H_
-#define _FILE_H_
-
-//#include <stdio.h>
-
-class MemStream : public IDataStream
-{
-public:
-	MemStream();
-	MemStream(unsigned long nLen);
-	virtual ~MemStream();
-
-	int refCount;
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-protected:
-	// MemFile specific:
-	unsigned long m_nGrowBytes;
-	unsigned long m_nPosition;
-	unsigned long m_nBufferSize;
-	unsigned long m_nFileSize;
-	unsigned char* m_pBuffer;
-	bool m_bAutoDelete;
-	void GrowFile(unsigned long nNewLen);
-
-public:
-	unsigned long GetPosition() const;
-	unsigned long Seek(long lOff, int nFrom);
-	void SetLength(unsigned long nNewLen);
-	unsigned long GetLength() const;
-
-	unsigned char* GetBuffer () const
-	  { return m_pBuffer; }
-
-	char* ReadString(char* pBuf, unsigned long nMax);
-	unsigned long Read(void* pBuf, unsigned long nCount);
-	unsigned long Write(const void* pBuf, unsigned long nCount);
-	int GetChar();
-	int PutChar(int c);
-  
-  void printf(const char*, ...); ///< \todo implement on MemStream
-
-	void Abort();
-	void Flush();
-	void Close();
-	bool Open(const char *filename, const char *mode);
-};
-
-class FileStream : public IDataStream
-{
-public:
-	FileStream();
-	virtual ~FileStream();
-
-	int refCount;
-	void IncRef() { refCount++; }
-	void DecRef() { refCount--; if (refCount <= 0) delete this; }
-
-protected:
-	// DiscFile specific:
-	FILE* m_hFile;
-	bool m_bCloseOnDelete;
-
-public:
-	unsigned long GetPosition() const;
-	unsigned long Seek(long lOff, int nFrom);
-	void SetLength(unsigned long nNewLen);
-	unsigned long GetLength() const;
-
-	char* ReadString(char* pBuf, unsigned long nMax);
-	unsigned long Read(void* pBuf, unsigned long nCount);
-	unsigned long Write(const void* pBuf, unsigned long nCount);
-	int GetChar();
-	int PutChar(int c);
-
-  void printf(const char*, ...); ///< completely matches the usual printf behaviour
-
-	void Abort();
-	void Flush();
-	void Close();
-	bool Open(const char *filename, const char *mode);
-};
-
-#endif // _FILE_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+//
+//	file.h
+////////////////////////////////////////////////////
+
+#ifndef _FILE_H_
+#define _FILE_H_
+
+//#include <stdio.h>
+
+class MemStream : public IDataStream
+{
+public:
+	MemStream();
+	MemStream(unsigned long nLen);
+	virtual ~MemStream();
+
+	int refCount;
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+
+protected:
+	// MemFile specific:
+	unsigned long m_nGrowBytes;
+	unsigned long m_nPosition;
+	unsigned long m_nBufferSize;
+	unsigned long m_nFileSize;
+	unsigned char* m_pBuffer;
+	bool m_bAutoDelete;
+	void GrowFile(unsigned long nNewLen);
+
+public:
+	unsigned long GetPosition() const;
+	unsigned long Seek(long lOff, int nFrom);
+	void SetLength(unsigned long nNewLen);
+	unsigned long GetLength() const;
+
+	unsigned char* GetBuffer () const
+	  { return m_pBuffer; }
+
+	char* ReadString(char* pBuf, unsigned long nMax);
+	unsigned long Read(void* pBuf, unsigned long nCount);
+	unsigned long Write(const void* pBuf, unsigned long nCount);
+	int GetChar();
+	int PutChar(int c);
+  
+  void printf(const char*, ...); ///< \todo implement on MemStream
+
+	void Abort();
+	void Flush();
+	void Close();
+	bool Open(const char *filename, const char *mode);
+};
+
+class FileStream : public IDataStream
+{
+public:
+	FileStream();
+	virtual ~FileStream();
+
+	int refCount;
+	void IncRef() { refCount++; }
+	void DecRef() { refCount--; if (refCount <= 0) delete this; }
+
+protected:
+	// DiscFile specific:
+	FILE* m_hFile;
+	bool m_bCloseOnDelete;
+
+public:
+	unsigned long GetPosition() const;
+	unsigned long Seek(long lOff, int nFrom);
+	void SetLength(unsigned long nNewLen);
+	unsigned long GetLength() const;
+
+	char* ReadString(char* pBuf, unsigned long nMax);
+	unsigned long Read(void* pBuf, unsigned long nCount);
+	unsigned long Write(const void* pBuf, unsigned long nCount);
+	int GetChar();
+	int PutChar(int c);
+
+  void printf(const char*, ...); ///< completely matches the usual printf behaviour
+
+	void Abort();
+	void Flush();
+	void Close();
+	bool Open(const char *filename, const char *mode);
+};
+
+#endif // _FILE_H_
diff --git a/radiant/filters.h b/radiant/filters.h
index 5f467f1d..b09d36f3 100644
--- a/radiant/filters.h
+++ b/radiant/filters.h
@@ -1,30 +1,30 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _FILTERS_H_
-#define _FILTERS_H_
-
-bfilter_t *FilterAdd(bfilter_t *pFilter, int type, int bmask, char *str, int exclude);
-bfilter_t *FilterListDelete(bfilter_t *pFilter);
-bfilter_t *FilterUpdate(bfilter_t *pFilter);
-bool FilterBrush(brush_t *pb);
-
-#endif // _FILTERS_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _FILTERS_H_
+#define _FILTERS_H_
+
+bfilter_t *FilterAdd(bfilter_t *pFilter, int type, int bmask, char *str, int exclude);
+bfilter_t *FilterListDelete(bfilter_t *pFilter);
+bfilter_t *FilterUpdate(bfilter_t *pFilter);
+bool FilterBrush(brush_t *pb);
+
+#endif // _FILTERS_H_
diff --git a/radiant/findtexturedialog.h b/radiant/findtexturedialog.h
index 96060ea2..eb1e61e1 100644
--- a/radiant/findtexturedialog.h
+++ b/radiant/findtexturedialog.h
@@ -1,49 +1,49 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _FINDTEXTUREDIALOG_H_
-#define _FINDTEXTUREDIALOG_H_
-
-#include "dialog.h"
-
-class FindTextureDialog : public Dialog
-{
- public:
-  static void setReplaceStr(const char* p);
-  static void setFindStr(const char* p);
-  static bool isOpen();
-  static void show();
-  static void updateTextures(const char* p);
-
-  FindTextureDialog ();
-  virtual ~FindTextureDialog ();
-  void BuildDialog ();
-
-  bool	m_bSelectedOnly;
-  Str	m_strFind;
-  Str	m_strReplace;
-  bool	m_bForce;
-  bool	m_bLive;
-
-};
-
-
-#endif //_FINDTEXTUREDIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _FINDTEXTUREDIALOG_H_
+#define _FINDTEXTUREDIALOG_H_
+
+#include "dialog.h"
+
+class FindTextureDialog : public Dialog
+{
+ public:
+  static void setReplaceStr(const char* p);
+  static void setFindStr(const char* p);
+  static bool isOpen();
+  static void show();
+  static void updateTextures(const char* p);
+
+  FindTextureDialog ();
+  virtual ~FindTextureDialog ();
+  void BuildDialog ();
+
+  bool	m_bSelectedOnly;
+  Str	m_strFind;
+  Str	m_strReplace;
+  bool	m_bForce;
+  bool	m_bLive;
+
+};
+
+
+#endif //_FINDTEXTUREDIALOG_H_
diff --git a/radiant/glwidget.h b/radiant/glwidget.h
index 1ce7f140..582a5ddb 100644
--- a/radiant/glwidget.h
+++ b/radiant/glwidget.h
@@ -1,45 +1,45 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _GLWIDGET_H_
-#define _GLWIDGET_H_
-
-GtkWidget* WINAPI gtk_glwidget_new          (gboolean zbufffer, GtkWidget* share);
-void       WINAPI gtk_glwidget_swap_buffers (GtkWidget *widget);
-gboolean   WINAPI gtk_glwidget_make_current (GtkWidget *widget);
-void       WINAPI gtk_glwidget_destroy_context (GtkWidget *widget);
-void       WINAPI gtk_glwidget_create_context (GtkWidget *widget);
-void       gtk_glwidget_create_font (GtkWidget *widget);
-
-void       gtk_glwidget_print_string(const char *s);
-void       gtk_glwidget_print_char(char s);
-
-
-#endif /* _GLWIDGET_H_ */
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _GLWIDGET_H_
+#define _GLWIDGET_H_
+
+GtkWidget* WINAPI gtk_glwidget_new          (gboolean zbufffer, GtkWidget* share);
+void       WINAPI gtk_glwidget_swap_buffers (GtkWidget *widget);
+gboolean   WINAPI gtk_glwidget_make_current (GtkWidget *widget);
+void       WINAPI gtk_glwidget_destroy_context (GtkWidget *widget);
+void       WINAPI gtk_glwidget_create_context (GtkWidget *widget);
+void       gtk_glwidget_create_font (GtkWidget *widget);
+
+void       gtk_glwidget_print_string(const char *s);
+void       gtk_glwidget_print_char(char s);
+
+
+#endif /* _GLWIDGET_H_ */
diff --git a/radiant/glwindow.h b/radiant/glwindow.h
index 209b94d3..a6bac087 100644
--- a/radiant/glwindow.h
+++ b/radiant/glwindow.h
@@ -1,108 +1,108 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _GLWINDOW_H_
-#define _GLWINDOW_H_
-
-class GLWindow
-{
- public:
-  GLWindow (bool zbuffer);
-  virtual ~GLWindow ();
-
-  bool MakeCurrent ();
-  void SwapBuffers ();
-  void SetTimer (guint millisec);
-  void KillTimer ();
-  bool HasTimer ()
-    { return m_nTimer != 0; }
-  void DestroyContext ();
-  void CreateContext ();
-
-  virtual void OnCreate () { }
-  virtual void OnExpose () { }
-
-  virtual void OnLButtonDown (guint32 flags, int x, int y) { }
-  virtual void OnRButtonDown (guint32 flags, int x, int y) { }
-  virtual void OnMButtonDown (guint32 flags, int x, int y) { }
-  virtual void OnLButtonUp (guint32 flags, int pointx, int pointy) { }
-  virtual void OnRButtonUp (guint32 flags, int pointx, int pointy) { }
-  virtual void OnMButtonUp (guint32 flags, int pointx, int pointy) { }
-  virtual void OnMouseMove (guint32 flags, int pointx, int pointy) { }
-
-  
-  virtual void OnSize (int cx, int cy) { }
-  virtual void OnTimer () { }
-
-  virtual void OnMouseWheel (bool bUp) { }
-
-  void RedrawWindow ()
-  {
-    gtk_widget_queue_draw(m_pWidget);
-  }
-
-  void SetFocus ()
-  {
-    /* gdk_window_raise (m_pWidget->window); */
-  }
-
-  void SetCapture ()
-  {
-    m_bMouseCapture = TRUE;
-  }
-
-  void ReleaseCapture ()
-  {
-    m_bMouseCapture = FALSE;
-  }
-
-  bool HasCapture ()
-  {
-    return m_bMouseCapture;
-  }
-
-  GtkWidget* GetWidget ()
-  {
-    return m_pWidget;
-  }
-
-  // member variables
- public:
-  GtkWidget* m_pParent; // for floating windows only
-
- protected:
-  bool       m_bMouseCapture;
-  GtkWidget* m_pWidget;
-
- private:
-  guint      m_nTimer; // only one timer supported
-};
-
-#endif //_GLWINDOW_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _GLWINDOW_H_
+#define _GLWINDOW_H_
+
+class GLWindow
+{
+ public:
+  GLWindow (bool zbuffer);
+  virtual ~GLWindow ();
+
+  bool MakeCurrent ();
+  void SwapBuffers ();
+  void SetTimer (guint millisec);
+  void KillTimer ();
+  bool HasTimer ()
+    { return m_nTimer != 0; }
+  void DestroyContext ();
+  void CreateContext ();
+
+  virtual void OnCreate () { }
+  virtual void OnExpose () { }
+
+  virtual void OnLButtonDown (guint32 flags, int x, int y) { }
+  virtual void OnRButtonDown (guint32 flags, int x, int y) { }
+  virtual void OnMButtonDown (guint32 flags, int x, int y) { }
+  virtual void OnLButtonUp (guint32 flags, int pointx, int pointy) { }
+  virtual void OnRButtonUp (guint32 flags, int pointx, int pointy) { }
+  virtual void OnMButtonUp (guint32 flags, int pointx, int pointy) { }
+  virtual void OnMouseMove (guint32 flags, int pointx, int pointy) { }
+
+  
+  virtual void OnSize (int cx, int cy) { }
+  virtual void OnTimer () { }
+
+  virtual void OnMouseWheel (bool bUp) { }
+
+  void RedrawWindow ()
+  {
+    gtk_widget_queue_draw(m_pWidget);
+  }
+
+  void SetFocus ()
+  {
+    /* gdk_window_raise (m_pWidget->window); */
+  }
+
+  void SetCapture ()
+  {
+    m_bMouseCapture = TRUE;
+  }
+
+  void ReleaseCapture ()
+  {
+    m_bMouseCapture = FALSE;
+  }
+
+  bool HasCapture ()
+  {
+    return m_bMouseCapture;
+  }
+
+  GtkWidget* GetWidget ()
+  {
+    return m_pWidget;
+  }
+
+  // member variables
+ public:
+  GtkWidget* m_pParent; // for floating windows only
+
+ protected:
+  bool       m_bMouseCapture;
+  GtkWidget* m_pWidget;
+
+ private:
+  guint      m_nTimer; // only one timer supported
+};
+
+#endif //_GLWINDOW_H_
diff --git a/radiant/groupdialog.h b/radiant/groupdialog.h
index a2531071..33e3640c 100644
--- a/radiant/groupdialog.h
+++ b/radiant/groupdialog.h
@@ -1,108 +1,108 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _GROUPDIALOG_H_
-#define _GROUPDIALOG_H_
-
-#define DlgXBorder 5
-#define DlgYBorder 5
-
-
-enum
-{
-  EntList,
-  EntComment,
-// Spawnflags
-  EntCheck1,
-  EntCheck2,
-  EntCheck3,
-  EntCheck4,
-  EntCheck5,
-  EntCheck6,
-  EntCheck7,
-  EntCheck8,
-// Extra Spawnflags for Halflife Support
-  EntCheck9,
-  EntCheck10,
-  EntCheck11,
-  EntCheck12,
-  EntCheck13,
-  EntCheck14,
-  EntCheck15,
-  EntCheck16,
-
-/*
-  EntCheck17,
-  EntCheck18,
-  EntCheck19,
-  EntCheck20,
-*/
-  EntProps,
-  EntDir0,
-  EntDir45,
-  EntDir90,
-  EntDir135,
-  EntDir180,
-  EntDir225,
-  EntDir270,
-  EntDir315,
-  EntDirUp,
-  EntDirDown,
-  EntDelProp,
-  EntKeyLabel,
-  EntKeyField,
-  EntValueLabel,
-  EntValueField,
-  EntColor,
-  EntAssignSounds,
-  EntAssignModels,
-  EntTab,
-
-  EntLast,
-};
-
-// 17..20 where used for spawnflags (!Easy !Medium !Hard etc.), empty now..
-extern GtkWidget* EntWidgets[EntLast];
-
-//extern int rgIds[EntLast];
-
-
-class GroupDlg 
-{
- public:
-  GroupDlg ();
-  void Create ();
-
-  void Show ()
-    { gtk_widget_show (m_pWidget); };
-  void Hide ()
-    { gtk_widget_hide (m_pWidget); };
-
- public:
-  GtkWidget* m_pNotebook;
-  GtkWidget* m_pWidget;
-  GtkWidget* m_pTree;
-  GtkCTreeNode* m_hWorld; //leo: not used keeping because of the win32 version
-};
-
-extern GroupDlg *g_pGroupDlg;
-
-#endif // _GROUPDIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _GROUPDIALOG_H_
+#define _GROUPDIALOG_H_
+
+#define DlgXBorder 5
+#define DlgYBorder 5
+
+
+enum
+{
+  EntList,
+  EntComment,
+// Spawnflags
+  EntCheck1,
+  EntCheck2,
+  EntCheck3,
+  EntCheck4,
+  EntCheck5,
+  EntCheck6,
+  EntCheck7,
+  EntCheck8,
+// Extra Spawnflags for Halflife Support
+  EntCheck9,
+  EntCheck10,
+  EntCheck11,
+  EntCheck12,
+  EntCheck13,
+  EntCheck14,
+  EntCheck15,
+  EntCheck16,
+
+/*
+  EntCheck17,
+  EntCheck18,
+  EntCheck19,
+  EntCheck20,
+*/
+  EntProps,
+  EntDir0,
+  EntDir45,
+  EntDir90,
+  EntDir135,
+  EntDir180,
+  EntDir225,
+  EntDir270,
+  EntDir315,
+  EntDirUp,
+  EntDirDown,
+  EntDelProp,
+  EntKeyLabel,
+  EntKeyField,
+  EntValueLabel,
+  EntValueField,
+  EntColor,
+  EntAssignSounds,
+  EntAssignModels,
+  EntTab,
+
+  EntLast,
+};
+
+// 17..20 where used for spawnflags (!Easy !Medium !Hard etc.), empty now..
+extern GtkWidget* EntWidgets[EntLast];
+
+//extern int rgIds[EntLast];
+
+
+class GroupDlg 
+{
+ public:
+  GroupDlg ();
+  void Create ();
+
+  void Show ()
+    { gtk_widget_show (m_pWidget); };
+  void Hide ()
+    { gtk_widget_hide (m_pWidget); };
+
+ public:
+  GtkWidget* m_pNotebook;
+  GtkWidget* m_pWidget;
+  GtkWidget* m_pTree;
+  GtkCTreeNode* m_hWorld; //leo: not used keeping because of the win32 version
+};
+
+extern GroupDlg *g_pGroupDlg;
+
+#endif // _GROUPDIALOG_H_
diff --git a/radiant/gtkfilesel-darwin.c b/radiant/gtkfilesel-darwin.c
index 2076423c..65c8bd0d 100644
--- a/radiant/gtkfilesel-darwin.c
+++ b/radiant/gtkfilesel-darwin.c
@@ -1,3360 +1,3360 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-
-// leo FIXME: if we keep this file then we'll need to ask permission to the author, this is LGPL
-// This file is from the Advanced File Selector widget 
-// by Michael Torrie  <torriem@byu.edu>
-// http://students.cs.byu.edu/~torriem/gtk/
-
-// common files win32/linux
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-// TTimo
-// NOTE: the mkdir stuff etc. is in <direct.h> .. but I don't know what's the best strategy yet.
-// just including <direct.h> here doesn't cut it
-
-#if defined (__linux__) || (__APPLE__)
-#include <sys/param.h>
-#include <dirent.h>
-#include <unistd.h>
-#include <pwd.h>
-#include "fnmatch.h"
-#endif
-
-// leo: added "gtk/"
-#include "gdk/gdkkeysyms.h"
-#include "gtk/gtkbutton.h"
-#include "gtk/gtkentry.h"
-#include "gtkfilesel-darwin.h"
-#include "gtk/gtkhbox.h"
-#include "gtk/gtkhbbox.h"
-#include "gtk/gtklabel.h"
-#include "gtk/gtklist.h"
-#include "gtk/gtklistitem.h"
-#include "gtk/gtkmain.h"
-#include "gtk/gtkscrolledwindow.h"
-#include "gtk/gtksignal.h"
-#include "gtk/gtkvbox.h"
-#include "gtk/gtkmenu.h"
-#include "gtk/gtkmenuitem.h"
-#include "gtk/gtkoptionmenu.h"
-#include "gtk/gtkclist.h"
-#include "gtk/gtkdialog.h"
-#include "gtk/gtkcombo.h"
-#include "gtk/gtkframe.h"
-
-// leo: disable NLS
-//#include "gtk/gtkintl.h"
-#define _(String) (String)
-
-#define DIR_LIST_WIDTH   180
-#define DIR_LIST_HEIGHT  180
-#define FILE_LIST_WIDTH  180
-#define FILE_LIST_HEIGHT 180
-
-/* I've put this here so it doesn't get confused with the 
- * file completion interface */
-typedef struct _HistoryCallbackArg HistoryCallbackArg;
-
-struct _HistoryCallbackArg
-{
-  gchar *directory;
-  GtkWidget *menu_item;
-};
-
-
-typedef struct _CompletionState    CompletionState;
-typedef struct _CompletionDir      CompletionDir;
-typedef struct _CompletionDirSent  CompletionDirSent;
-typedef struct _CompletionDirEntry CompletionDirEntry;
-typedef struct _CompletionUserDir  CompletionUserDir;
-typedef struct _PossibleCompletion PossibleCompletion;
-
-/* Non-external file completion decls and structures */
-
-/* A contant telling PRCS how many directories to cache.  Its actually
- * kept in a list, so the geometry isn't important. */
-#define CMPL_DIRECTORY_CACHE_SIZE 10
-
-/* A constant used to determine whether a substring was an exact
- * match by first_diff_index()
- */
-#define PATTERN_MATCH -1
-/* The arguments used by all fnmatch() calls below
- */
-#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
-
-#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
-
-/* This structure contains all the useful information about a directory
- * for the purposes of filename completion.  These structures are cached
- * in the CompletionState struct.  CompletionDir's are reference counted.
- */
-struct _CompletionDirSent
-{
-  ino_t inode;
-  time_t mtime;
-  dev_t device;
-
-  gint entry_count;
-  gchar *name_buffer; /* memory segment containing names of all entries */
-
-  struct _CompletionDirEntry *entries;
-};
-
-struct _CompletionDir
-{
-  CompletionDirSent *sent;
-
-  gchar *fullname;
-  gint fullname_len;
-
-  struct _CompletionDir *cmpl_parent;
-  gint cmpl_index;
-  gchar *cmpl_text;
-};
-
-/* This structure contains pairs of directory entry names with a flag saying
- * whether or not they are a valid directory.  NOTE: This information is used
- * to provide the caller with information about whether to update its completions
- * or try to open a file.  Since directories are cached by the directory mtime,
- * a symlink which points to an invalid file (which will not be a directory),
- * will not be reevaluated if that file is created, unless the containing
- * directory is touched.  I consider this case to be worth ignoring (josh).
- */
-struct _CompletionDirEntry
-{
-  gint is_dir;
-  gchar *entry_name;
-};
-
-struct _CompletionUserDir
-{
-  gchar *login;
-  gchar *homedir;
-};
-
-struct _PossibleCompletion
-{
-  /* accessible fields, all are accessed externally by functions
-   * declared above
-   */
-  gchar *text;
-  gint is_a_completion;
-  gint is_directory;
-
-  gint file_size;
-  gint file_time;
-  gint uid;
-  gint gid;
-  /* Private fields
-   */
-  gint text_alloc;
-};
-
-struct _CompletionState
-{
-  gint last_valid_char;
-  gchar *updated_text;
-  gint updated_text_len;
-  gint updated_text_alloc;
-  gint re_complete;
-
-  gchar *user_dir_name_buffer;
-  gint user_directories_len;
-
-  gchar *last_completion_text;
-
-  gint user_completion_index; /* if >= 0, currently completing ~user */
-
-  struct _CompletionDir *completion_dir; /* directory completing from */
-  struct _CompletionDir *active_completion_dir;
-
-  struct _PossibleCompletion the_completion;
-
-  struct _CompletionDir *reference_dir; /* initial directory */
-
-  GList* directory_storage;
-  GList* directory_sent_storage;
-
-  struct _CompletionUserDir *user_directories;
-};
-
-
-/* File completion functions which would be external, were they used
- * outside of this file.
- */
-
-static CompletionState*    cmpl_init_state        (void);
-static void                cmpl_free_state        (CompletionState *cmpl_state);
-static gint                cmpl_state_okay        (CompletionState* cmpl_state);
-static gchar*              cmpl_strerror          (gint);
-
-static PossibleCompletion* cmpl_completion_matches(gchar           *text_to_complete,
-						   gchar          **remaining_text,
-						   CompletionState *cmpl_state);
-
-/* Returns a name for consideration, possibly a completion, this name
- * will be invalid after the next call to cmpl_next_completion.
- */
-static char*               cmpl_this_completion   (PossibleCompletion*);
-
-/* True if this completion matches the given text.  Otherwise, this
- * output can be used to have a list of non-completions.
- */
-static gint                cmpl_is_a_completion   (PossibleCompletion*);
-
-/* True if the completion is a directory
- */
-static gint                cmpl_is_directory      (PossibleCompletion*);
-
-/* Obtains the next completion, or NULL
- */
-static PossibleCompletion* cmpl_next_completion   (CompletionState*);
-
-/* Updating completions: the return value of cmpl_updated_text() will
- * be text_to_complete completed as much as possible after the most
- * recent call to cmpl_completion_matches.  For the present
- * application, this is the suggested replacement for the user's input
- * string.  You must CALL THIS AFTER ALL cmpl_text_completions have
- * been received.
- */
-static gchar*              cmpl_updated_text       (CompletionState* cmpl_state);
-
-/* After updating, to see if the completion was a directory, call
- * this.  If it was, you should consider re-calling completion_matches.
- */
-static gint                cmpl_updated_dir        (CompletionState* cmpl_state);
-
-/* Current location: if using file completion, return the current
- * directory, from which file completion begins.  More specifically,
- * the cwd concatenated with all exact completions up to the last
- * directory delimiter('/').
- */
-static gchar*              cmpl_reference_position (CompletionState* cmpl_state);
-
-/* backing up: if cmpl_completion_matches returns NULL, you may query
- * the index of the last completable character into cmpl_updated_text.
- */
-static gint                cmpl_last_valid_char    (CompletionState* cmpl_state);
-
-/* When the user selects a non-directory, call cmpl_completion_fullname
- * to get the full name of the selected file.
- */
-static gchar*              cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);
-
-
-/* Directory operations. */
-static CompletionDir* open_ref_dir         (gchar* text_to_complete,
-					    gchar** remaining_text,
-					    CompletionState* cmpl_state);
-static gboolean       check_dir            (gchar *dir_name, 
-					    struct stat *result, 
-					    gboolean *stat_subdirs);
-static CompletionDir* open_dir             (gchar* dir_name,
-					    CompletionState* cmpl_state);
-static CompletionDir* open_user_dir        (gchar* text_to_complete,
-					    CompletionState *cmpl_state);
-static CompletionDir* open_relative_dir    (gchar* dir_name, CompletionDir* dir,
-					    CompletionState *cmpl_state);
-static CompletionDirSent* open_new_dir     (gchar* dir_name, 
-					    struct stat* sbuf,
-					    gboolean stat_subdirs);
-static gint           correct_dir_fullname (CompletionDir* cmpl_dir);
-static gint           correct_parent       (CompletionDir* cmpl_dir,
-					    struct stat *sbuf);
-static gchar*         find_parent_dir_fullname    (gchar* dirname);
-static CompletionDir* attach_dir           (CompletionDirSent* sent,
-					    gchar* dir_name,
-					    CompletionState *cmpl_state);
-static void           free_dir_sent (CompletionDirSent* sent);
-static void           free_dir      (CompletionDir  *dir);
-static void           prune_memory_usage(CompletionState *cmpl_state);
-
-/* Completion operations */
-static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,
-						      CompletionState *cmpl_state);
-static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);
-static CompletionDir* find_completion_dir(gchar* text_to_complete,
-					  gchar** remaining_text,
-					  CompletionState* cmpl_state);
-static PossibleCompletion* append_completion_text(gchar* text,
-						  CompletionState* cmpl_state);
-static gint get_pwdb(CompletionState* cmpl_state);
-static gint first_diff_index(gchar* pat, gchar* text);
-static gint compare_user_dir(const void* a, const void* b);
-static gint compare_cmpl_dir(const void* a, const void* b);
-static void update_cmpl(PossibleCompletion* poss,
-			CompletionState* cmpl_state);
-
-static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);
-static void gtk_file_selection_init          (GtkFileSelection      *filesel);
-static void gtk_file_selection_destroy       (GtkObject             *object);
-static gint gtk_file_selection_key_press     (GtkWidget             *widget,
-					      GdkEventKey           *event,
-					      gpointer               user_data);
-
-static void gtk_file_selection_file_button (GtkWidget *widget,
-					    gint row, 
-					    gint column, 
-					    GdkEventButton *bevent,
-					    gpointer user_data);
-
-static void gtk_file_selection_dir_button (GtkWidget *widget,
-					   gint row,
-					   gint column,
-					   GdkEventButton *bevent,
-					   gpointer data);
-
-static void gtk_file_selection_undir_button (GtkWidget *widget,
-					     gint row,
-					     gint column,
-					     GdkEventButton *bevent,
-					     gpointer data);
-
-static void gtk_file_selection_populate      (GtkFileSelection      *fs,
-					      gchar                 *rel_path,
-					      gint                   try_complete);
-static void gtk_file_selection_abort         (GtkFileSelection      *fs);
-
-static void gtk_file_selection_update_history_menu (GtkFileSelection       *fs,
-						    gchar                  *current_dir);
-
-static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
-
-static gboolean gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
-static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
-																							GdkEventKey *event,
-																							gpointer user_data);
-static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
-																							GdkEventButton *event,
-																							gpointer user_data);
-static void gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_home_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_up_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_prev_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_next_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data);
-
-static gint gtk_file_selection_match_char (gchar, gchar *mask);
-static gint gtk_file_selection_match_mask (gchar *,gchar *);
-
-
-static GtkWindowClass *parent_class = NULL;
-
-/* Saves errno when something cmpl does fails. */
-static gint cmpl_errno;
-
-
-void gtk_file_selection_clear_masks (GtkFileSelection *filesel)
-{
-  GList *list;
-
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-
-  list = filesel->masks;
-  while (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  filesel->masks = NULL;
-
-  gtk_list_clear_items (GTK_LIST (GTK_COMBO (filesel->mask_entry)->list), 0, -1);
-}
-
-void gtk_file_selection_set_masks (GtkFileSelection *filesel, const gchar **masks)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-
-  while (*masks)
-    {
-      filesel->masks = g_list_append (filesel->masks, (gpointer)*masks);
-      masks++;
-    }
-
-  if (filesel->masks)
-    gtk_combo_set_popdown_strings (GTK_COMBO (filesel->mask_entry), filesel->masks);
-}
-
-
-/* General notes:
- * Make prev and next inactive if their respective *
- *   histories are empty.
- * Add facilities for handling hidden files and    *
- * directories                                     *
- * Add an api to access the mask, and hidden files *
- * check box?  (prob not in 1.2.x series)          *
- */
-
-/* Routine for applying mask to filenames         *
- *   Need to be optimized to minimize recursion   *
- *     help the for loop by looking for the next  *
- *     instance of the mask character following   *
- *     the '*'.  ei *.c -- look for '.'           *
- *     Also, swap all *? pairs (-> ?*), as that   *
- *     will make it possible to look ahead (?     *
- *     makes it very nondeterministic as in *?.c  *
- *     which really is ?*.c                       *
- *   Allow multiply masks, separted by commas     *
- *   Allow more flexible [] handling (ie [a-zA-Z] *
- *                                                *
- */
-static gint gtk_file_selection_match_char (gchar text, gchar *mask){
-  gchar *maskc;
-  gint x;
-  gint s;
-	
-  if (mask[0] == '[')
-    {
-      if (!strchr (mask,']')) return 0;
-      maskc = g_strdup(mask + 1); /* get the portion of mask inside []*/
-		
-      (*(strchr (maskc,']'))) = 0;
-      s = strlen ((char *)maskc);
-
-      for (x = 0; x < s; x++){
-	if (text == maskc[x])
-	  {
-	    g_free (maskc);
-	    return s + 2;
-	  }
-      }
-      g_free (maskc);
-      return 0;
-    }
-
-  if (mask[0] == '?') return 1;
-  if (mask[0] == text) return 1;
-
-  return 0;
-}
-
-
-static gint gtk_file_selection_match_mask (gchar *text, gchar *mask){
-
-  int mc;
-  int tc;
-
-  tc = 0; mc = 0;
-	
-  if (mask[0] == 0 && text[0] == 0) return 1;
-	
-  if (mask[0] == '*')
-    {
-      for (tc = 0; tc <= strlen(text); tc++)
-	{
-	  if (gtk_file_selection_match_mask (text + tc, mask + 1))
-	    return 1;
-	}
-      return 0;
-    }
-  mc = gtk_file_selection_match_char (text[0], mask);
-
-  if(mc)
-    return gtk_file_selection_match_mask (text + 1, mask + mc);
-  else
-    return 0;
-}
-
-GtkType
-gtk_file_selection_get_type (void)
-{
-  static GtkType file_selection_type = 0;
-
-  if (!file_selection_type)
-    {
-      static const GtkTypeInfo filesel_info =
-      {
-	"GtkFileSelection",
-	sizeof (GtkFileSelection),
-	sizeof (GtkFileSelectionClass),
-	(GtkClassInitFunc) gtk_file_selection_class_init,
-	(GtkObjectInitFunc) gtk_file_selection_init,
-	/* reserved_1 */ NULL,
-	/* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
-      };
-
-      file_selection_type = gtk_type_unique (GTK_TYPE_WINDOW, &filesel_info);
-    }
-
-  return file_selection_type;
-}
-
-static void
-gtk_file_selection_class_init (GtkFileSelectionClass *klass)	//tigital
-{
-  GtkObjectClass *object_class;
-
-  object_class = (GtkObjectClass*) klass;
-
-  parent_class = gtk_type_class (GTK_TYPE_WINDOW);
-
-  object_class->destroy = gtk_file_selection_destroy;
-}
-
-static void
-gtk_file_selection_init (GtkFileSelection *filesel)
-{
-  GtkWidget *entry_vbox;
-  GtkWidget *label;
-  GtkWidget *list_hbox;
-  GtkWidget *confirm_area;
-  GtkWidget *vbox;
-  GtkWidget *hbox;
-  GtkWidget *pulldown_hbox;
-  GtkWidget *scrolled_win;
-  GtkWidget *mask_label;
-  GtkWidget *bigframe;
-  GtkWidget *label_lookingin;
-  GtkWidget *up_button;
-  GtkWidget *home_button;
-  GtkWidget *prev_button;
-  GtkWidget *next_button;
-  GtkWidget *refresh_button;
-
-  char *dir_title [2];
-  char *file_title [2];
-  
-  filesel->cmpl_state = cmpl_init_state ();
-
-  filesel->mask=NULL;
-  filesel->prev_history=NULL;
-  filesel->next_history=NULL;
-  filesel->saved_entry=NULL;
-
-  /* The dialog-sized vertical box  */
-  filesel->main_vbox = gtk_vbox_new (FALSE, 10);
-  gtk_container_set_border_width (GTK_CONTAINER (filesel), 10);
-  gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
-  gtk_widget_show (filesel->main_vbox);
-
-  /* The horizontal box containing create, rename etc. buttons */
-  filesel->button_area = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(filesel->button_area), GTK_BUTTONBOX_START);
-  gtk_button_box_set_spacing(GTK_BUTTON_BOX(filesel->button_area), 0);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->button_area, 
-		      FALSE, FALSE, 0);
-  gtk_widget_show (filesel->button_area);
-  
-  gtk_file_selection_show_fileop_buttons(filesel);
-
-  /* hbox for pulldown menu */
-  pulldown_hbox = gtk_hbox_new (FALSE, 5);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);
-  gtk_widget_show (pulldown_hbox);
-  
-  /* The combo box that replaces the pulldown menu */
-  label_lookingin = gtk_label_new (_("Looking in:"));
-  gtk_widget_show (label_lookingin);
-  gtk_box_pack_start (GTK_BOX (pulldown_hbox), label_lookingin, FALSE, FALSE, 0);
-
-  filesel->history_combo = gtk_combo_new();
-  gtk_widget_show(filesel->history_combo);
-  gtk_combo_set_value_in_list(GTK_COMBO(filesel->history_combo),FALSE,FALSE);
-  gtk_box_pack_start (GTK_BOX(pulldown_hbox),filesel->history_combo,
-  				TRUE,TRUE, 0);
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->entry),"key-press-event",				    
-		     (GtkSignalFunc) gtk_file_selection_history_combo_callback,
-		     (gpointer) filesel);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"button-press-event",
-		     (GtkSignalFunc) gtk_file_selection_history_combo_list_callback,
-		     (gpointer) filesel);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"key-press-event",
-		     (GtkSignalFunc) gtk_file_selection_history_combo_list_key_handler,
-		     (gpointer) filesel);
-
-  /*  frame to put the following hbox in  */
-  bigframe = gtk_frame_new (NULL);
-  gtk_widget_show (bigframe);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), bigframe, TRUE, TRUE, 0);
-
-  /*  The horizontal box containing the directory and file listboxes  */
-  list_hbox = gtk_hbox_new (FALSE, 5);
-  gtk_container_add (GTK_CONTAINER(bigframe), list_hbox);
-  gtk_container_set_border_width (GTK_CONTAINER (list_hbox), 5);
-  gtk_widget_show (list_hbox);
-
-  /* vbox to put the buttons and directory listing in  */
-  vbox = gtk_vbox_new (FALSE, 0);
-  gtk_widget_show (vbox);
-  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, FALSE, FALSE, 0);
-
-  hbox = gtk_hbox_new (FALSE, 0);
-  gtk_widget_show (hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-  home_button = gtk_button_new_with_label (_("Home"));
-  gtk_widget_show (home_button);
-  gtk_signal_connect (GTK_OBJECT (home_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_home_button,
-		      (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox), home_button, TRUE,TRUE, 0);
-
-  prev_button = gtk_button_new_with_label (_("Prev"));
-  gtk_signal_connect (GTK_OBJECT (prev_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_prev_button,
-		      (gpointer) filesel);
-  gtk_widget_show (prev_button);
-  gtk_box_pack_start (GTK_BOX (hbox), prev_button, TRUE,TRUE, 0);
-
-  up_button = gtk_button_new_with_label (_("Up"));
-  gtk_signal_connect (GTK_OBJECT (up_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_up_button,
-		      (gpointer) filesel);
-  gtk_widget_show (up_button);
-  gtk_box_pack_start (GTK_BOX (hbox), up_button, TRUE,TRUE, 0);
-
-  next_button = gtk_button_new_with_label (_("Next"));
-  gtk_widget_show (next_button);
-  gtk_signal_connect (GTK_OBJECT (next_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_next_button,
-		      (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox), next_button, TRUE,TRUE, 0);
-
-  refresh_button = gtk_button_new_with_label (_("Refresh"));
-  gtk_widget_show (refresh_button);
-  gtk_signal_connect (GTK_OBJECT (refresh_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_refresh_button,
-		      (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox), refresh_button, TRUE, TRUE, 0);
-
-  /* The directories clist */
-  dir_title[0] = _("Directories");
-  dir_title[1] = NULL;
-  filesel->dir_list = gtk_clist_new_with_titles (1, (gchar**) dir_title);
-  gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
-  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",
-		      (GtkSignalFunc) gtk_file_selection_dir_button,
-		      (gpointer) filesel);
-  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "unselect_row",
-		      (GtkSignalFunc) gtk_file_selection_undir_button,
-		      (gpointer) filesel);
-  gtk_clist_column_titles_passive (GTK_CLIST (filesel->dir_list));
-
-  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->dir_list);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE,TRUE, 5);
-  gtk_widget_show (filesel->dir_list);
-  gtk_widget_show (scrolled_win);
-
-  /* vbox area for mask entry and files clist  */
-  vbox = gtk_vbox_new (FALSE, 0);
-  gtk_widget_show (vbox);
-  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, TRUE, TRUE, 0);
-
-  hbox = gtk_hbox_new (FALSE, 5);
-  gtk_widget_show (hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-  mask_label = gtk_label_new (_("Mask:"));
-  gtk_widget_show (mask_label);
-  gtk_box_pack_start (GTK_BOX (hbox), mask_label, FALSE, FALSE, 0);
-
-  filesel->mask_entry = gtk_entry_new ();
-  gtk_widget_show (filesel->mask_entry);
-  gtk_signal_connect(GTK_OBJECT(filesel->mask_entry),"activate",
-		     (GtkSignalFunc) gtk_file_selection_mask_entry_callback,
-		     (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
-
-
-  /* The files clist */
-  file_title[0] = _("Files");
-  file_title[1] = NULL;
-  filesel->file_list = gtk_clist_new_with_titles (1, (gchar**) file_title);
-  gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
-  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
-		      (GtkSignalFunc) gtk_file_selection_file_button, 
-		      (gpointer) filesel);
-  gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));
-
-  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->file_list);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 5);
-  gtk_widget_show (filesel->file_list);
-  gtk_widget_show (scrolled_win);
-
-  /* action area for packing buttons into. */
-  filesel->action_area = gtk_hbox_new (TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->action_area, 
-		      FALSE, FALSE, 0);
-  gtk_widget_show (filesel->action_area);
-  
-  /*  The OK/Cancel button area */
-  confirm_area = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);
-  gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);
-  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), confirm_area, FALSE, FALSE, 0);
-  gtk_widget_show (confirm_area);
-
-  /*  The OK button  */
-  filesel->ok_button = gtk_button_new_with_label (_("OK"));
-  GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->ok_button, TRUE, TRUE, 0);
-  gtk_widget_grab_default (filesel->ok_button);
-  gtk_widget_show (filesel->ok_button);
-
-  /*  The Cancel button  */
-  filesel->cancel_button = gtk_button_new_with_label (_("Cancel"));
-  GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->cancel_button, TRUE, TRUE, 0);
-  gtk_widget_show (filesel->cancel_button);
-
-  /*  The selection entry widget  */
-  entry_vbox = gtk_vbox_new (FALSE, 2);
-  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
-  gtk_widget_show (entry_vbox);
-
-  filesel->selection_text = label = gtk_label_new ("");
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
-  gtk_widget_show (label);
-
-  filesel->selection_entry = gtk_entry_new ();
-  gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
-		      (GtkSignalFunc) gtk_file_selection_key_press, filesel);
-  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
-			     (GtkSignalFunc) gtk_widget_grab_default,
-			     GTK_OBJECT (filesel->ok_button));
-  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
-                             (GtkSignalFunc) gtk_button_clicked,
-                             GTK_OBJECT (filesel->ok_button));
-  gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
-  gtk_widget_show (filesel->selection_entry);
-
-  if (!cmpl_state_okay (filesel->cmpl_state))
-    {
-      gchar err_buf[256];
-
-      sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
-
-      gtk_label_set_text (GTK_LABEL (filesel->selection_text), err_buf);
-    }
-  else
-    {
-      gtk_file_selection_populate (filesel, "", FALSE);
-    }
-
-  gtk_widget_grab_focus (filesel->selection_entry);
-}
-
-GtkWidget*
-gtk_file_selection_new (const gchar *title)
-{
-  GtkFileSelection *filesel;
-
-  filesel = gtk_type_new (GTK_TYPE_FILE_SELECTION);
-  gtk_window_set_title (GTK_WINDOW (filesel), title);
-
-  return GTK_WIDGET (filesel);
-}
-
-void
-gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-    
-  /* delete, create directory, and rename */
-  if (!filesel->fileop_c_dir) 
-    {
-      filesel->fileop_c_dir = gtk_button_new_with_label (_("Create Dir"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_c_dir), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_create_dir, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_c_dir, TRUE, TRUE, 0);
-      gtk_widget_show (filesel->fileop_c_dir);
-    }
-	
-  if (!filesel->fileop_del_file) 
-    {
-      filesel->fileop_del_file = gtk_button_new_with_label (_("Delete File"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_del_file), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_delete_file, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_del_file, TRUE, TRUE, 0);
-      gtk_widget_show (filesel->fileop_del_file);
-    }
-
-  if (!filesel->fileop_ren_file)
-    {
-      filesel->fileop_ren_file = gtk_button_new_with_label (_("Rename File"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_ren_file), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_rename_file, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_ren_file, TRUE, TRUE, 0);
-      gtk_widget_show (filesel->fileop_ren_file);
-    }
-
-  gtk_widget_queue_resize(GTK_WIDGET(filesel));
-}
-
-void       
-gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-    
-  if (filesel->fileop_ren_file) 
-    {
-      gtk_widget_destroy (filesel->fileop_ren_file);
-      filesel->fileop_ren_file = NULL;
-    }
-
-  if (filesel->fileop_del_file)
-    {
-      gtk_widget_destroy (filesel->fileop_del_file);
-      filesel->fileop_del_file = NULL;
-    }
-
-  if (filesel->fileop_c_dir)
-    {
-      gtk_widget_destroy (filesel->fileop_c_dir);
-      filesel->fileop_c_dir = NULL;
-    }
-}
-
-
-
-void
-gtk_file_selection_set_filename (GtkFileSelection *filesel,
-				 const gchar      *filename)
-{
-  char  buf[MAXPATHLEN];
-  const char *name, *last_slash;
-
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-  g_return_if_fail (filename != NULL);
-
-  last_slash = strrchr (filename, '/');
-
-  if (!last_slash)
-    {
-      buf[0] = 0;
-      name = filename;
-    }
-  else
-    {
-      gint len = MIN (MAXPATHLEN - 1, last_slash - filename + 1);
-
-      strncpy (buf, filename, len);
-      buf[len] = 0;
-
-      name = last_slash + 1;
-    }
-
-  gtk_file_selection_populate (filesel, buf, FALSE);
-
-  if (filesel->selection_entry)
-    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
-}
-
-gchar*
-gtk_file_selection_get_filename (GtkFileSelection *filesel)
-{
-  static char nothing[2] = "";
-  char *text;
-  char *filename;
-
-  g_return_val_if_fail (filesel != NULL, nothing);
-  g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), nothing);
-
-  text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
-  if (text)
-    {
-      filename = cmpl_completion_fullname (text, filesel->cmpl_state);
-      return filename;
-    }
-
-  return nothing;
-}
-
-void
-gtk_file_selection_complete (GtkFileSelection *filesel,
-			     const gchar      *pattern)
-{
-  gchar *new_pattern;
-  gint x;
-	
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-  g_return_if_fail (pattern != NULL);
-
-  if (filesel->selection_entry)
-    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), pattern);
-	
-  if(strchr(pattern,'*') || strchr(pattern,'?'))
-    {
-      for(x=strlen(pattern);x>=0;x--)
-	{
-	  if(pattern[x]=='/') break;
-	}
-      gtk_entry_set_text(GTK_ENTRY(filesel->mask_entry),g_strdup(pattern+x+1));
-      
-      if(filesel->mask) g_free(filesel->mask);
-      
-      filesel->mask=g_strdup(pattern+x+1);
-      new_pattern=g_strdup(pattern);
-      new_pattern[x+1]=0;
-      gtk_file_selection_populate (filesel, (gchar*) new_pattern, TRUE);
-      g_free(new_pattern);
-    }
-  else
-    {
-      gtk_file_selection_populate (filesel, (gchar*) pattern, TRUE);
-    }
-}
-
-static void
-gtk_file_selection_destroy (GtkObject *object)
-{
-  GtkFileSelection *filesel;
-  GList *list;
-
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (object));
-
-  filesel = GTK_FILE_SELECTION (object);
-  
-  if (filesel->fileop_dialog)
-    gtk_widget_destroy (filesel->fileop_dialog);
-  
-  if (filesel->next_history)
-    {
-      list = filesel->next_history;
-      while (list)
-  	{
-	  g_free (list->data);
-	  list = list->next;
-  	}
-    }
-  g_list_free (filesel->next_history);
-  filesel->next_history = NULL;
-
-  if (filesel->prev_history)
-    {
-      list = filesel->prev_history;
-      while (list)
-  	{
-	  g_free (list->data);
-	  list = list->next;
-  	}
-    }
-  g_list_free (filesel->prev_history);
-  filesel->prev_history = NULL;
-
-  if (filesel->mask)
-    {
-      g_free (filesel->mask);
-      filesel->mask = NULL;
-    }
-  
-  cmpl_free_state (filesel->cmpl_state);
-  filesel->cmpl_state = NULL;
-
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
-/* Begin file operations callbacks */
-
-static void
-gtk_file_selection_fileop_error (GtkFileSelection *fs, gchar *error_message)
-{
-  GtkWidget *label;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  GtkWidget *dialog;
-  
-  g_return_if_fail (error_message != NULL);
-  
-  /* main dialog */
-  dialog = gtk_dialog_new ();
-  /*
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  */
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-  
-  /* If file dialog is grabbed, make this dialog modal too */
-  /* When error dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-
-  label = gtk_label_new(error_message);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-
-  /* yes, we free it */
-  g_free (error_message);
-  
-  /* close button */
-  button = gtk_button_new_with_label (_("Close"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-static void
-gtk_file_selection_fileop_destroy (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  fs->fileop_dialog = NULL;
-}
-
-
-static void
-gtk_file_selection_create_dir_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  gchar *dirname;
-  gchar *path;
-  gchar *full_path;
-  gchar *buf;
-  CompletionState *cmpl_state;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  dirname = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  full_path = g_strconcat (path, "/", dirname, NULL);
-  if ( (mkdir (full_path, 0755) < 0) ) 
-    {
-      buf = g_strconcat ("Error creating directory \"", dirname, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (full_path);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-  
-static void
-gtk_file_selection_create_dir (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *button;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Create Directory"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-  
-  label = gtk_label_new(_("Directory name:"));
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-
-  /*  The directory entry widget  */
-  fs->fileop_entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
-		      TRUE, TRUE, 5);
-  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
-  gtk_widget_show (fs->fileop_entry);
-  
-  /* buttons */
-  button = gtk_button_new_with_label (_("Create"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_create_dir_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-static void
-gtk_file_selection_delete_file_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  CompletionState *cmpl_state;
-  gchar *path;
-  gchar *full_path;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  full_path = g_strconcat (path, "/", fs->fileop_file, NULL);
-  if ( (unlink (full_path) < 0) ) 
-    {
-      buf = g_strconcat ("Error deleting file \"", fs->fileop_file, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (full_path);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-
-static void
-gtk_file_selection_delete_file (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  GtkWidget *dialog;
-  gchar *filename;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-
-  filename = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-  if (strlen(filename) < 1)
-	  return;
-
-  fs->fileop_file = filename;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Delete File"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-  
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-
-  buf = g_strconcat ("Really delete file \"", filename, "\" ?", NULL);
-  label = gtk_label_new(buf);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-  g_free(buf);
-  
-  /* buttons */
-  button = gtk_button_new_with_label (_("Delete"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_delete_file_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-
-}
-
-static void
-gtk_file_selection_rename_file_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  gchar *buf;
-  gchar *file;
-  gchar *path;
-  gchar *new_filename;
-  gchar *old_filename;
-  CompletionState *cmpl_state;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  new_filename = g_strconcat (path, "/", file, NULL);
-  old_filename = g_strconcat (path, "/", fs->fileop_file, NULL);
-
-  if ( (rename (old_filename, new_filename)) < 0) 
-    {
-      buf = g_strconcat ("Error renaming file \"", file, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (new_filename);
-  g_free (old_filename);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-  
-static void
-gtk_file_selection_rename_file (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-
-  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-  if (strlen(fs->fileop_file) < 1)
-	  return;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Rename File"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog  closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-  
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-  
-  buf = g_strconcat ("Rename file \"", fs->fileop_file, "\" to:", NULL);
-  label = gtk_label_new(buf);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-  g_free(buf);
-
-  /* New filename entry */
-  fs->fileop_entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
-		      TRUE, TRUE, 5);
-  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
-  gtk_widget_show (fs->fileop_entry);
-  
-  gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
-  gtk_editable_select_region (GTK_EDITABLE (fs->fileop_entry),
-			      0, strlen (fs->fileop_file));
-
-  /* buttons */
-  button = gtk_button_new_with_label (_("Rename"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-
-static gint
-gtk_file_selection_key_press (GtkWidget   *widget,
-			      GdkEventKey *event,
-			      gpointer     user_data)
-{
-  GtkFileSelection *fs;
-  char *text;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  fs = GTK_FILE_SELECTION (user_data);
-
-  if (event->keyval == GDK_Tab)
-    {
-      text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-
-      text = g_strdup (text);
-
-      gtk_file_selection_populate (fs, text, TRUE);
-
-      g_free (text);
-
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-
-      return TRUE;
-    }
-  if (fs->saved_entry)
-    {
-      gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
-      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
-      g_free (fs->saved_entry);
-      fs->saved_entry = NULL;
-    }
-
-
-  return FALSE;
-}
-
-static void
-gtk_file_selection_home_button (GtkWidget *widget, gpointer data){
-  GList *list;
-	
-  GtkFileSelection *fs=data;
-
-  list = fs->next_history;
-  if (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-		
-  gtk_file_selection_populate (fs,"~/",FALSE);
-}
-
-static void
-gtk_file_selection_up_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->next_history;
-  if (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-
-  gtk_file_selection_populate (fs, "../", FALSE); /*change directories. */
-		
-}
-
-static void
-gtk_file_selection_prev_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-  GList *first;
-  gchar *path;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->prev_history;
-
-  if (list && g_list_length(list) > 1)
-    {
-      first = list;            /* get first element */
-      list = list->next;       /* pop off current directory */
-
-      list->prev = NULL;       /* make this the new head. */
-  	
-      fs->prev_history = list; /* update prev_history list */
-      fs->next_history = g_list_prepend(fs->next_history,first->data); /* put it on next_history */
-  	
-      first->next = NULL;      /* orphan the old first node */
-      g_list_free (first);     /* free the node (data is now in use by next_history) */
-
-
-  	
-      path = g_malloc(strlen(list->data)+4); /* plenty of space */
-      strcpy(path,list->data);               /* get the 2nd path in the history */
-      strcat(path,"/");                      /* append a '/' */
-      gtk_file_selection_populate (fs, path, FALSE); /* change directories. */
-      g_free (path);
-    }
-}	
-
-static void
-gtk_file_selection_next_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-  GList *first;
-  gchar *path;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->next_history;
-
-  if (list && g_list_length(list) > 0)
-    {
-      first = list;            /*get first element*/
-      list = list->next;       /*pop off current directory*/
-      
-      if (list)
-	list->prev = NULL;
-      
-      fs->next_history = list;                       /*update prev_history list*/
-  	
-      path = g_malloc(strlen(first->data)+4);        /*plenty of space*/
-      strcpy(path,first->data);
-      strcat(path,"/");                              /*append a /   */
-      gtk_file_selection_populate (fs, path, FALSE); /*change directories.*/
-      g_free(path);
-  	
-      first->next = NULL;     /* orphan the old first node */
-      g_list_free (first);    /* free the node (data is now in use by next_history) */
-      
-    }
-}	
-
-void static
-gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_file_selection_populate (fs,"",FALSE);
-}
-
-static void
-gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-
-  if(fs->mask)
-    g_free (fs->mask);
-		
-  fs->mask = g_strdup(gtk_entry_get_text (GTK_ENTRY(fs->mask_entry)));
-	
-  if (strlen(fs->mask) == 0)
-    {
-      g_free (fs->mask);
-      fs->mask = NULL;
-    }
-	
-  gtk_file_selection_refresh_button (widget,data);
-}
-
-static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
-								  GdkEventKey *event,
-								  gpointer user_data)
-{
-  /*
-  g_print("Key pressed! \n");
-  */
-	
-  return TRUE;
-}
-
-static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
-								GdkEventButton *event,
-								gpointer user_data)
-{
-
-  GtkFileSelection *fs = user_data;
-  GList *list;
-  gchar *path;
-		
-  list = fs->next_history;
-  if(list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-			
-  path = g_malloc(strlen(gtk_entry_get_text(GTK_ENTRY (((GtkCombo *)fs->history_combo)->entry)))+4);
-  strcpy (path,gtk_entry_get_text(GTK_ENTRY( ((GtkCombo *)fs->history_combo)->entry)));
-  strcat (path,"/");
-	
-  gtk_file_selection_populate (fs,path,TRUE);
-	
-  g_free (path);
-
-  return TRUE;
-}
-
-static gboolean
-gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
-{
-  GtkEntry *entry=(GtkEntry *)widget;
-  GtkFileSelection *fs=data;
-  GList *list;
-  gchar *path;
-	
-  g_return_val_if_fail (fs != NULL,FALSE);
-  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
-	
-
-  if (event->keyval == GDK_Return)
-    {
-      list = fs->next_history;
-      if (list)
-	{
-	  g_free (list->data);
-	  list = list->next;
-	}
-      g_list_free (fs->next_history);
-      fs->next_history = NULL;
-      
-      path = g_malloc(strlen(gtk_entry_get_text(entry))+4);
-      strcpy (path,gtk_entry_get_text(entry));
-      strcat (path,"/");
-      gtk_file_selection_populate (fs,path,TRUE);
-      g_free (path);
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-      return TRUE;
-    }
-  else
-    {
-      return FALSE;
-    }
-
-}
-
-static void
-gtk_file_selection_update_history_menu (GtkFileSelection *fs,
-					gchar *current_directory)
-{
-  gchar *current_dir;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  g_return_if_fail (current_directory != NULL);
-  
-  current_dir = g_strdup (current_directory);
-
-  if(fs->prev_history)
-    {
-      if (strcmp((fs->prev_history)->data,current_dir))
-	{ /*if this item isn't on the top of the list */
-	  fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
-	}
-    } else {
-      fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
-    }
-  
-  gtk_combo_set_popdown_strings (GTK_COMBO (fs->history_combo),fs->prev_history);
-  
-  g_free (current_dir);
-}
-
-static void
-gtk_file_selection_file_button (GtkWidget *widget,
-			       gint row, 
-			       gint column, 
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-  
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = user_data;
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  gtk_clist_get_text (GTK_CLIST (fs->file_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  case GDK_2BUTTON_PRESS:
-	    gtk_button_clicked (GTK_BUTTON (fs->ok_button));
-	    break;
-	    
-	  default:
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-      
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_dir_button (GtkWidget *widget,
-			       gint row, 
-			       gint column, 
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GList *list;
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = GTK_FILE_SELECTION (user_data);
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  case GDK_2BUTTON_PRESS:
-	    list = fs->next_history;
-	    if (list)
-	      {
-		g_free (list->data);
-		list = list->next;
-	      }
-	    g_list_free (fs->next_history);
-	    fs->next_history = NULL;
-	
-	    gtk_file_selection_populate (fs, filename, FALSE);
-	    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
-	    g_free (fs->saved_entry);
-	    fs->saved_entry = NULL;
-	    break;
-	    
-	  default:
-	    /* here we need to add the "filename" to the beginning of what's already
-	       in the entry.  Save what's in the entry, then restore it on the double click
-	    */
-	    if (fs->saved_entry) g_free (fs->saved_entry);
-	    fs->saved_entry=g_strdup(gtk_entry_get_text(GTK_ENTRY (fs->selection_entry)));
-	
-	    temp=g_strconcat(filename,fs->saved_entry,NULL);
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), temp);
-	    g_free (temp);
-	
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-      
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_undir_button (GtkWidget *widget,
-			       gint row,
-			       gint column,
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = GTK_FILE_SELECTION (user_data);
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  default:
-	    /* here we need to add the "filename" to the beginning of what's already
-	       in the entry.  Save what's in the entry, then restore it on the double click
-	    */
-	    if (fs->saved_entry)
-	      {
-	        gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),fs->saved_entry);
-		g_free (fs->saved_entry);
-		fs->saved_entry = NULL;
-	      }
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename); //?????
-
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_populate (GtkFileSelection *fs,
-			     gchar            *rel_path,
-			     gint              try_complete)
-{
-  CompletionState *cmpl_state;
-  PossibleCompletion* poss;
-  gchar* filename;
-  gint row;
-  gchar* rem_path = rel_path;
-  gchar* sel_text;
-  gchar* text[2];
-  gint did_recurse = FALSE;
-  gint possible_count = 0;
-  gint selection_index = -1;
-  gint file_list_width;
-  gint dir_list_width;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
-
-  if (!cmpl_state_okay (cmpl_state))
-    {
-      /* Something went wrong. */
-      gtk_file_selection_abort (fs);
-      return;
-    }
-
-  g_assert (cmpl_state->reference_dir);
-
-  gtk_clist_freeze (GTK_CLIST (fs->dir_list));
-  gtk_clist_clear (GTK_CLIST (fs->dir_list));
-  gtk_clist_freeze (GTK_CLIST (fs->file_list));
-  gtk_clist_clear (GTK_CLIST (fs->file_list));
-
-  /* Set the dir_list to include ./ and ../ */
-  text[1] = NULL;
-  text[0] = "./";
-  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-
-  text[0] = "../";
-  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-
-  /*reset the max widths of the lists*/
-  dir_list_width = gdk_string_width(fs->dir_list->style->font,"../");
-  gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,dir_list_width);
-  file_list_width = 1;
-  gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,file_list_width);
-
-  while (poss)
-    {
-      if (cmpl_is_a_completion (poss))
-  	{
-	  possible_count += 1;
-	  
-	  filename = cmpl_this_completion (poss);
-
-	  text[0] = filename;
-	  
-	  if (cmpl_is_directory (poss))
-	    {
-	      if (strcmp (filename, "./") != 0 &&
-		  strcmp (filename, "../") != 0)
-		{
-		  int width = gdk_string_width(fs->dir_list->style->font,
-					       filename);
-		  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-		  if(width > dir_list_width)
-		    {
-		      dir_list_width = width;
-		      gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,
-						 width);
-		    }
-		}
-	    }
-	  else
-	    {
-	      if(fs->mask)
-		{
-		  if (gtk_file_selection_match_mask(filename,fs->mask))
-		    {
-		      int width = gdk_string_width(fs->file_list->style->font,
-						   filename);
-		      row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
-		      if(width > file_list_width)
-		        {
-		          file_list_width = width;
-		          gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
-						     width);
-		        }
-		    }
-		}
-	      else
-		{
-		  int width = gdk_string_width(fs->file_list->style->font,
-					       filename);
-		  row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
-		  if(width > file_list_width)
-		    {
-		      file_list_width = width;
-		      gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
-						 width);
-		    }
-		}
-	    }
-	}
-
-      poss = cmpl_next_completion (cmpl_state);
-    }
-
-  gtk_clist_thaw (GTK_CLIST (fs->dir_list));
-  gtk_clist_thaw (GTK_CLIST (fs->file_list));
-
-  /* File lists are set. */
-
-  g_assert (cmpl_state->reference_dir);
-
-  if (try_complete)
-    {
-
-      /* User is trying to complete filenames, so advance the user's input
-       * string to the updated_text, which is the common leading substring
-       * of all possible completions, and if its a directory attempt
-       * attempt completions in it. */
-
-      if (cmpl_updated_text (cmpl_state)[0])
-        {
-
-          if (cmpl_updated_dir (cmpl_state))
-            {
-	      gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
-
-              did_recurse = TRUE;
-
-              gtk_file_selection_populate (fs, dir_name, TRUE);
-
-              g_free (dir_name);
-            }
-          else
-            {
-	      if (fs->selection_entry)
-		      gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
-					  cmpl_updated_text (cmpl_state));
-            }
-        }
-      else
-        {
-          selection_index = cmpl_last_valid_char (cmpl_state) -
-                            (strlen (rel_path) - strlen (rem_path));
-	  if (fs->selection_entry)
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
-        }
-    }
-  else
-    {
-      if (fs->selection_entry)
-      /* Here we need to take the old filename and keep it!*/
-	/*gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");*/
-	;
-    }
-
-  if (!did_recurse)
-    {
-      if (fs->selection_entry)
-	gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
-
-      if (fs->selection_entry)
-	{
-	  sel_text = g_strconcat (_("Selection: "),
-				  cmpl_reference_position (cmpl_state),
-				  NULL);
-
-	  gtk_label_set_text (GTK_LABEL (fs->selection_text), sel_text);
-	  g_free (sel_text);
-	}
-
-  gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state));
-
-    }
-}
-
-static void
-gtk_file_selection_abort (GtkFileSelection *fs)
-{
-  gchar err_buf[256];
-
-  sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
-
-  /*  BEEP gdk_beep();  */
-
-  if (fs->selection_entry)
-    gtk_label_set_text (GTK_LABEL (fs->selection_text), err_buf);
-}
-
-/**********************************************************************/
-/*			  External Interface                          */
-/**********************************************************************/
-
-/* The four completion state selectors
- */
-static gchar*
-cmpl_updated_text (CompletionState* cmpl_state)
-{
-  return cmpl_state->updated_text;
-}
-
-static gint
-cmpl_updated_dir (CompletionState* cmpl_state)
-{
-  return cmpl_state->re_complete;
-}
-
-static gchar*
-cmpl_reference_position (CompletionState* cmpl_state)
-{
-  return cmpl_state->reference_dir->fullname;
-}
-
-static gint
-cmpl_last_valid_char (CompletionState* cmpl_state)
-{
-  return cmpl_state->last_valid_char;
-}
-
-static gchar*
-cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state)
-{
-  static char nothing[2] = "";
-
-  if (!cmpl_state_okay (cmpl_state))
-    {
-      return nothing;
-    }
-  else if (text[0] == '/')
-    {
-      strcpy (cmpl_state->updated_text, text);
-    }
-  else if (text[0] == '~')
-    {
-      CompletionDir* dir;
-      char* slash;
-
-      dir = open_user_dir (text, cmpl_state);
-
-      if (!dir)
-	{
-	  /* spencer says just return ~something, so
-	   * for now just do it. */
-	  strcpy (cmpl_state->updated_text, text);
-	}
-      else
-	{
-
-	  strcpy (cmpl_state->updated_text, dir->fullname);
-
-	  slash = strchr (text, '/');
-
-	  if (slash)
-	    strcat (cmpl_state->updated_text, slash);
-	}
-    }
-  else
-    {
-      strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
-      if (strcmp (cmpl_state->reference_dir->fullname, "/") != 0)
-	strcat (cmpl_state->updated_text, "/");
-      strcat (cmpl_state->updated_text, text);
-    }
-
-  return cmpl_state->updated_text;
-}
-
-/* The three completion selectors
- */
-static gchar*
-cmpl_this_completion (PossibleCompletion* pc)
-{
-  return pc->text;
-}
-
-static gint
-cmpl_is_directory (PossibleCompletion* pc)
-{
-  return pc->is_directory;
-}
-
-static gint
-cmpl_is_a_completion (PossibleCompletion* pc)
-{
-  return pc->is_a_completion;
-}
-
-/**********************************************************************/
-/*	                 Construction, deletion                       */
-/**********************************************************************/
-
-static CompletionState*
-cmpl_init_state (void)
-{
-  gchar getcwd_buf[2*MAXPATHLEN];
-  CompletionState *new_state;
-
-  new_state = g_new (CompletionState, 1);
-
-  /* We don't use getcwd() on SUNOS, because, it does a popen("pwd")
-   * and, if that wasn't bad enough, hangs in doing so.
-   */
-#if defined(sun) && !defined(__SVR4)
-  if (!getwd (getcwd_buf))
-#else    
-  if (!getcwd (getcwd_buf, MAXPATHLEN))
-#endif    
-    {
-      /* Oh joy, we can't get the current directory. Um..., we should have
-       * a root directory, right? Right? (Probably not portable to non-Unix)
-       */
-      strcpy (getcwd_buf, "/");
-    }
-
-tryagain:
-
-  new_state->reference_dir = NULL;
-  new_state->completion_dir = NULL;
-  new_state->active_completion_dir = NULL;
-  new_state->directory_storage = NULL;
-  new_state->directory_sent_storage = NULL;
-  new_state->last_valid_char = 0;
-  new_state->updated_text = g_new (gchar, MAXPATHLEN);
-  new_state->updated_text_alloc = MAXPATHLEN;
-  new_state->the_completion.text = g_new (gchar, MAXPATHLEN);
-  new_state->the_completion.text_alloc = MAXPATHLEN;
-  new_state->user_dir_name_buffer = NULL;
-  new_state->user_directories = NULL;
-
-  new_state->reference_dir =  open_dir (getcwd_buf, new_state);
-
-  if (!new_state->reference_dir)
-    {
-      /* Directories changing from underneath us, grumble */
-      strcpy (getcwd_buf, "/");
-      goto tryagain;
-    }
-
-  return new_state;
-}
-
-static void
-cmpl_free_dir_list(GList* dp0)
-{
-  GList *dp = dp0;
-
-  while (dp) {
-    free_dir (dp->data);
-    dp = dp->next;
-  }
-
-  g_list_free(dp0);
-}
-
-static void
-cmpl_free_dir_sent_list(GList* dp0)
-{
-  GList *dp = dp0;
-
-  while (dp) {
-    free_dir_sent (dp->data);
-    dp = dp->next;
-  }
-
-  g_list_free(dp0);
-}
-
-static void
-cmpl_free_state (CompletionState* cmpl_state)
-{
-  cmpl_free_dir_list (cmpl_state->directory_storage);
-  cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage);
-
-  if (cmpl_state->user_dir_name_buffer)
-    g_free (cmpl_state->user_dir_name_buffer);
-  if (cmpl_state->user_directories)
-    g_free (cmpl_state->user_directories);
-  if (cmpl_state->the_completion.text)
-    g_free (cmpl_state->the_completion.text);
-  if (cmpl_state->updated_text)
-    g_free (cmpl_state->updated_text);
-
-  g_free (cmpl_state);
-}
-
-static void
-free_dir(CompletionDir* dir)
-{
-  g_free(dir->fullname);
-  g_free(dir);
-}
-
-static void
-free_dir_sent(CompletionDirSent* sent)
-{
-  g_free(sent->name_buffer);
-  g_free(sent->entries);
-  g_free(sent);
-}
-
-static void
-prune_memory_usage(CompletionState *cmpl_state)
-{
-  GList* cdsl = cmpl_state->directory_sent_storage;
-  GList* cdl = cmpl_state->directory_storage;
-  GList* cdl0 = cdl;
-  gint len = 0;
-
-  for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1)
-    cdsl = cdsl->next;
-
-  if (cdsl) {
-    cmpl_free_dir_sent_list(cdsl->next);
-    cdsl->next = NULL;
-  }
-
-  cmpl_state->directory_storage = NULL;
-  while (cdl) {
-    if (cdl->data == cmpl_state->reference_dir)
-      cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data);
-    else
-      free_dir (cdl->data);
-    cdl = cdl->next;
-  }
-
-  g_list_free(cdl0);
-}
-
-/**********************************************************************/
-/*                        The main entrances.                         */
-/**********************************************************************/
-
-static PossibleCompletion*
-cmpl_completion_matches (gchar* text_to_complete,
-			 gchar** remaining_text,
-			 CompletionState* cmpl_state)
-{
-  gchar* first_slash;
-  PossibleCompletion *poss;
-
-  prune_memory_usage(cmpl_state);
-
-  g_assert (text_to_complete != NULL);
-
-  cmpl_state->user_completion_index = -1;
-  cmpl_state->last_completion_text = text_to_complete;
-  cmpl_state->the_completion.text[0] = 0;
-  cmpl_state->last_valid_char = 0;
-  cmpl_state->updated_text_len = -1;
-  cmpl_state->updated_text[0] = 0;
-  cmpl_state->re_complete = FALSE;
-
-  first_slash = strchr (text_to_complete, '/');
-
-  if (text_to_complete[0] == '~' && !first_slash)
-    {
-      /* Text starts with ~ and there is no slash, show all the
-       * home directory completions.
-       */
-      poss = attempt_homedir_completion (text_to_complete, cmpl_state);
-
-      update_cmpl(poss, cmpl_state);
-
-      return poss;
-    }
-
-  cmpl_state->reference_dir =
-    open_ref_dir (text_to_complete, remaining_text, cmpl_state);
-
-  if(!cmpl_state->reference_dir)
-    return NULL;
-
-  cmpl_state->completion_dir =
-    find_completion_dir (*remaining_text, remaining_text, cmpl_state);
-
-  cmpl_state->last_valid_char = *remaining_text - text_to_complete;
-
-  if(!cmpl_state->completion_dir)
-    return NULL;
-
-  cmpl_state->completion_dir->cmpl_index = -1;
-  cmpl_state->completion_dir->cmpl_parent = NULL;
-  cmpl_state->completion_dir->cmpl_text = *remaining_text;
-
-  cmpl_state->active_completion_dir = cmpl_state->completion_dir;
-
-  cmpl_state->reference_dir = cmpl_state->completion_dir;
-
-  poss = attempt_file_completion(cmpl_state);
-
-  update_cmpl(poss, cmpl_state);
-
-  return poss;
-}
-
-static PossibleCompletion*
-cmpl_next_completion (CompletionState* cmpl_state)
-{
-  PossibleCompletion* poss = NULL;
-
-  cmpl_state->the_completion.text[0] = 0;
-
-  if(cmpl_state->user_completion_index >= 0)
-    poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state);
-  else
-    poss = attempt_file_completion(cmpl_state);
-
-  update_cmpl(poss, cmpl_state);
-
-  return poss;
-}
-
-/**********************************************************************/
-/*			 Directory Operations                         */
-/**********************************************************************/
-
-/* Open the directory where completion will begin from, if possible. */
-static CompletionDir*
-open_ref_dir(gchar* text_to_complete,
-	     gchar** remaining_text,
-	     CompletionState* cmpl_state)
-{
-  gchar* first_slash;
-  CompletionDir *new_dir;
-
-  first_slash = strchr(text_to_complete, '/');
-
-  if (text_to_complete[0] == '~')
-    {
-      new_dir = open_user_dir(text_to_complete, cmpl_state);
-
-      if(new_dir)
-	{
-	  if(first_slash)
-	    *remaining_text = first_slash + 1;
-	  else
-	    *remaining_text = text_to_complete + strlen(text_to_complete);
-	}
-      else
-	{
-	  return NULL;
-	}
-    }
-  else if (text_to_complete[0] == '/' || !cmpl_state->reference_dir)
-    {
-      gchar *tmp = g_strdup(text_to_complete);
-      gchar *p;
-
-      p = tmp;
-      while (*p && *p != '*' && *p != '?')
-	p++;
-
-      *p = '\0';
-      p = strrchr(tmp, '/');
-      if (p)
-	{
-	  if (p == tmp)
-	    p++;
-      
-	  *p = '\0';
-
-	  new_dir = open_dir(tmp, cmpl_state);
-
-	  if(new_dir)
-	    *remaining_text = text_to_complete + 
-	      ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
-	}
-      else
-	{
-	  /* If no possible candidates, use the cwd */
-	  gchar *curdir = g_get_current_dir ();
-	  
-	  new_dir = open_dir(curdir, cmpl_state);
-
-	  if (new_dir)
-	    *remaining_text = text_to_complete;
-
-	  g_free (curdir);
-	}
-
-      g_free (tmp);
-    }
-  else
-    {
-      *remaining_text = text_to_complete;
-
-      new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state);
-    }
-
-  if(new_dir)
-    {
-      new_dir->cmpl_index = -1;
-      new_dir->cmpl_parent = NULL;
-    }
-
-  return new_dir;
-}
-
-/* open a directory by user name */
-static CompletionDir*
-open_user_dir(gchar* text_to_complete,
-	      CompletionState *cmpl_state)
-{
-  gchar *first_slash;
-  gint cmp_len;
-
-  g_assert(text_to_complete && text_to_complete[0] == '~');
-
-  first_slash = strchr(text_to_complete, '/');
-
-  if (first_slash)
-    cmp_len = first_slash - text_to_complete - 1;
-  else
-    cmp_len = strlen(text_to_complete + 1);
-
-  if(!cmp_len)
-    {
-      /* ~/ */
-      gchar *homedir = g_get_home_dir ();
-
-      if (homedir)
-	return open_dir(homedir, cmpl_state);
-      else
-	return NULL;
-    }
-  else
-    {
-      /* ~user/ */
-      char* copy = g_new(char, cmp_len + 1);
-      struct passwd *pwd;
-      strncpy(copy, text_to_complete + 1, cmp_len);
-      copy[cmp_len] = 0;
-      pwd = getpwnam(copy);
-      g_free(copy);
-      if (!pwd)
-	{
-	  cmpl_errno = errno;
-	  return NULL;
-	}
-
-      return open_dir(pwd->pw_dir, cmpl_state);
-    }
-}
-
-/* open a directory relative the the current relative directory */
-static CompletionDir*
-open_relative_dir(gchar* dir_name,
-		  CompletionDir* dir,
-		  CompletionState *cmpl_state)
-{
-  gchar path_buf[2*MAXPATHLEN];
-
-  if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN)
-    {
-      cmpl_errno = CMPL_ERRNO_TOO_LONG;
-      return NULL;
-    }
-
-  strcpy(path_buf, dir->fullname);
-
-  if(dir->fullname_len > 1)
-    {
-      path_buf[dir->fullname_len] = '/';
-      strcpy(path_buf + dir->fullname_len + 1, dir_name);
-    }
-  else
-    {
-      strcpy(path_buf + dir->fullname_len, dir_name);
-    }
-
-  return open_dir(path_buf, cmpl_state);
-}
-
-/* after the cache lookup fails, really open a new directory */
-static CompletionDirSent*
-open_new_dir(gchar* dir_name, struct stat* sbuf, gboolean stat_subdirs)
-{
-  CompletionDirSent* sent;
-  DIR* directory;
-  gchar *buffer_ptr;
-  struct dirent *dirent_ptr;
-  gint buffer_size = 0;
-  gint entry_count = 0;
-  gint i;
-  struct stat ent_sbuf;
-  char path_buf[MAXPATHLEN*2];
-  gint path_buf_len;
-
-  sent = g_new(CompletionDirSent, 1);
-  sent->mtime = sbuf->st_mtime;
-  sent->inode = sbuf->st_ino;
-  sent->device = sbuf->st_dev;
-
-  path_buf_len = strlen(dir_name);
-
-  if (path_buf_len > MAXPATHLEN)
-    {
-      cmpl_errno = CMPL_ERRNO_TOO_LONG;
-      return NULL;
-    }
-
-  strcpy(path_buf, dir_name);
-
-  directory = opendir(dir_name);
-
-  if(!directory)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  while((dirent_ptr = readdir(directory)) != NULL)
-    {
-      int entry_len = strlen(dirent_ptr->d_name);
-      buffer_size += entry_len + 1;
-      entry_count += 1;
-
-      if(path_buf_len + entry_len + 2 >= MAXPATHLEN)
-	{
-	  cmpl_errno = CMPL_ERRNO_TOO_LONG;
- 	  closedir(directory);
-	  return NULL;
-	}
-    }
-
-  sent->name_buffer = g_new(gchar, buffer_size);
-  sent->entries = g_new(CompletionDirEntry, entry_count);
-  sent->entry_count = entry_count;
-
-  buffer_ptr = sent->name_buffer;
-
-  rewinddir(directory);
-
-  for(i = 0; i < entry_count; i += 1)
-    {
-      dirent_ptr = readdir(directory);
-
-      if(!dirent_ptr)
-	{
-	  cmpl_errno = errno;
-	  closedir(directory);
-	  return NULL;
-	}
-
-      strcpy(buffer_ptr, dirent_ptr->d_name);
-      sent->entries[i].entry_name = buffer_ptr;
-      buffer_ptr += strlen(dirent_ptr->d_name);
-      *buffer_ptr = 0;
-      buffer_ptr += 1;
-
-      path_buf[path_buf_len] = '/';
-      strcpy(path_buf + path_buf_len + 1, dirent_ptr->d_name);
-
-      if (stat_subdirs)
-	{
-	  if(stat(path_buf, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
-	    sent->entries[i].is_dir = 1;
-	  else
-	    /* stat may fail, and we don't mind, since it could be a
-	     * dangling symlink. */
-	    sent->entries[i].is_dir = 0;
-	}
-      else
-	sent->entries[i].is_dir = 1;
-    }
-
-  qsort(sent->entries, sent->entry_count, sizeof(CompletionDirEntry), compare_cmpl_dir);
-
-  closedir(directory);
-
-  return sent;
-}
-
-static gboolean
-check_dir(gchar *dir_name, struct stat *result, gboolean *stat_subdirs)
-{
-  /* A list of directories that we know only contain other directories.
-   * Trying to stat every file in these directories would be very
-   * expensive.
-   */
-
-  static struct {
-    gchar *name;
-    gboolean present;
-    struct stat statbuf;
-  } no_stat_dirs[] = {
-    { "/afs", FALSE, { 0 } },
-    { "/net", FALSE, { 0 } }
-  };
-
-  static const gint n_no_stat_dirs = sizeof(no_stat_dirs) / sizeof(no_stat_dirs[0]);
-  static gboolean initialized = FALSE;
-
-  gint i;
-
-  if (!initialized)
-    {
-      initialized = TRUE;
-      for (i = 0; i < n_no_stat_dirs; i++)
-	{
-	  if (stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
-	    no_stat_dirs[i].present = TRUE;
-	}
-    }
-
-  if(stat(dir_name, result) < 0)
-    {
-      cmpl_errno = errno;
-      return FALSE;
-    }
-
-  *stat_subdirs = TRUE;
-  for (i=0; i<n_no_stat_dirs; i++)
-    {
-      if (no_stat_dirs[i].present &&
-	  (no_stat_dirs[i].statbuf.st_dev == result->st_dev) &&
-	  (no_stat_dirs[i].statbuf.st_ino == result->st_ino))
-	{
-	  *stat_subdirs = FALSE;
-	  break;
-	}
-    }
-
-  return TRUE;
-}
-
-/* open a directory by absolute pathname */
-static CompletionDir*
-open_dir(gchar* dir_name, CompletionState* cmpl_state)
-{
-  struct stat sbuf;
-  gboolean stat_subdirs;
-  CompletionDirSent *sent;
-  GList* cdsl;
-
-  if (!check_dir (dir_name, &sbuf, &stat_subdirs))
-    return NULL;
-
-  cdsl = cmpl_state->directory_sent_storage;
-
-  while (cdsl)
-    {
-      sent = cdsl->data;
-
-      if(sent->inode == sbuf.st_ino &&
-	 sent->mtime == sbuf.st_mtime &&
-	 sent->device == sbuf.st_dev)
-	return attach_dir(sent, dir_name, cmpl_state);
-
-      cdsl = cdsl->next;
-    }
-
-  sent = open_new_dir(dir_name, &sbuf, stat_subdirs);
-
-  if (sent) {
-    cmpl_state->directory_sent_storage =
-      g_list_prepend(cmpl_state->directory_sent_storage, sent);
-
-    return attach_dir(sent, dir_name, cmpl_state);
-  }
-
-  return NULL;
-}
-
-static CompletionDir*
-attach_dir(CompletionDirSent* sent, gchar* dir_name, CompletionState *cmpl_state)
-{
-  CompletionDir* new_dir;
-
-  new_dir = g_new(CompletionDir, 1);
-
-  cmpl_state->directory_storage =
-    g_list_prepend(cmpl_state->directory_storage, new_dir);
-
-  new_dir->sent = sent;
-  new_dir->fullname = g_strdup(dir_name);
-  new_dir->fullname_len = strlen(dir_name);
-
-  return new_dir;
-}
-
-static gint
-correct_dir_fullname(CompletionDir* cmpl_dir)
-{
-  gint length = strlen(cmpl_dir->fullname);
-  struct stat sbuf;
-
-  if (strcmp(cmpl_dir->fullname + length - 2, "/.") == 0)
-    {
-      if (length == 2) 
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	} else {
-	  cmpl_dir->fullname[length - 2] = 0;
-	}
-    }
-  else if (strcmp(cmpl_dir->fullname + length - 3, "/./") == 0)
-    cmpl_dir->fullname[length - 2] = 0;
-  else if (strcmp(cmpl_dir->fullname + length - 3, "/..") == 0)
-    {
-      if(length == 3)
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	}
-
-      if(stat(cmpl_dir->fullname, &sbuf) < 0)
-	{
-	  cmpl_errno = errno;
-	  return FALSE;
-	}
-
-      cmpl_dir->fullname[length - 2] = 0;
-
-      if(!correct_parent(cmpl_dir, &sbuf))
-	return FALSE;
-    }
-  else if (strcmp(cmpl_dir->fullname + length - 4, "/../") == 0)
-    {
-      if(length == 4)
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	}
-
-      if(stat(cmpl_dir->fullname, &sbuf) < 0)
-	{
-	  cmpl_errno = errno;
-	  return FALSE;
-	}
-
-      cmpl_dir->fullname[length - 3] = 0;
-
-      if(!correct_parent(cmpl_dir, &sbuf))
-	return FALSE;
-    }
-
-  cmpl_dir->fullname_len = strlen(cmpl_dir->fullname);
-
-  return TRUE;
-}
-
-static gint
-correct_parent(CompletionDir* cmpl_dir, struct stat *sbuf)
-{
-  struct stat parbuf;
-  gchar *last_slash;
-  gchar *new_name;
-  gchar c = 0;
-
-  last_slash = strrchr(cmpl_dir->fullname, '/');
-
-  g_assert(last_slash);
-
-  if(last_slash != cmpl_dir->fullname)
-    { /* last_slash[0] = 0; */ }
-  else
-    {
-      c = last_slash[1];
-      last_slash[1] = 0;
-    }
-
-  if (stat(cmpl_dir->fullname, &parbuf) < 0)
-    {
-      cmpl_errno = errno;
-      return FALSE;
-    }
-
-  if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
-    /* it wasn't a link */
-    return TRUE;
-
-  if(c)
-    last_slash[1] = c;
-  /* else
-    last_slash[0] = '/'; */
-
-  /* it was a link, have to figure it out the hard way */
-
-  new_name = find_parent_dir_fullname(cmpl_dir->fullname);
-
-  if (!new_name)
-    return FALSE;
-
-  g_free(cmpl_dir->fullname);
-
-  cmpl_dir->fullname = new_name;
-
-  return TRUE;
-}
-
-static gchar*
-find_parent_dir_fullname(gchar* dirname)
-{
-  gchar buffer[MAXPATHLEN];
-  gchar buffer2[MAXPATHLEN];
-
-#if defined(sun) && !defined(__SVR4)
-  if(!getwd(buffer))
-#else
-  if(!getcwd(buffer, MAXPATHLEN))
-#endif    
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  if(chdir(dirname) != 0 || chdir("..") != 0)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-#if defined(sun) && !defined(__SVR4)
-  if(!getwd(buffer2))
-#else
-  if(!getcwd(buffer2, MAXPATHLEN))
-#endif
-    {
-      chdir(buffer);
-      cmpl_errno = errno;
-
-      return NULL;
-    }
-
-  if(chdir(buffer) != 0)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  return g_strdup(buffer2);
-}
-
-/**********************************************************************/
-/*                        Completion Operations                       */
-/**********************************************************************/
-
-static PossibleCompletion*
-attempt_homedir_completion(gchar* text_to_complete,
-			   CompletionState *cmpl_state)
-{
-  gint index, length;
-
-  if (!cmpl_state->user_dir_name_buffer &&
-      !get_pwdb(cmpl_state))
-    return NULL;
-  length = strlen(text_to_complete) - 1;
-
-  cmpl_state->user_completion_index += 1;
-
-  while(cmpl_state->user_completion_index < cmpl_state->user_directories_len)
-    {
-      index = first_diff_index(text_to_complete + 1,
-			       cmpl_state->user_directories
-			       [cmpl_state->user_completion_index].login);
-
-      switch(index)
-	{
-	case PATTERN_MATCH:
-	  break;
-	default:
-	  if(cmpl_state->last_valid_char < (index + 1))
-	    cmpl_state->last_valid_char = index + 1;
-	  cmpl_state->user_completion_index += 1;
-	  continue;
-	}
-
-      cmpl_state->the_completion.is_a_completion = 1;
-      cmpl_state->the_completion.is_directory = 1;
-
-      append_completion_text("~", cmpl_state);
-
-      append_completion_text(cmpl_state->
-			      user_directories[cmpl_state->user_completion_index].login,
-			     cmpl_state);
-
-      return append_completion_text("/", cmpl_state);
-    }
-
-  if(text_to_complete[1] ||
-     cmpl_state->user_completion_index > cmpl_state->user_directories_len)
-    {
-      cmpl_state->user_completion_index = -1;
-      return NULL;
-    }
-  else
-    {
-      cmpl_state->user_completion_index += 1;
-      cmpl_state->the_completion.is_a_completion = 1;
-      cmpl_state->the_completion.is_directory = 1;
-
-      return append_completion_text("~/", cmpl_state);
-    }
-}
-
-/* returns the index (>= 0) of the first differing character,
- * PATTERN_MATCH if the completion matches */
-static gint
-first_diff_index(gchar* pat, gchar* text)
-{
-  gint diff = 0;
-
-  while(*pat && *text && *text == *pat)
-    {
-      pat += 1;
-      text += 1;
-      diff += 1;
-    }
-
-  if(*pat)
-    return diff;
-
-  return PATTERN_MATCH;
-}
-
-static PossibleCompletion*
-append_completion_text(gchar* text, CompletionState* cmpl_state)
-{
-  gint len, i = 1;
-
-  if(!cmpl_state->the_completion.text)
-    return NULL;
-
-  len = strlen(text) + strlen(cmpl_state->the_completion.text) + 1;
-
-  if(cmpl_state->the_completion.text_alloc > len)
-    {
-      strcat(cmpl_state->the_completion.text, text);
-      return &cmpl_state->the_completion;
-    }
-
-  while(i < len) { i <<= 1; }
-
-  cmpl_state->the_completion.text_alloc = i;
-
-  cmpl_state->the_completion.text = (gchar*)g_realloc(cmpl_state->the_completion.text, i);
-
-  if(!cmpl_state->the_completion.text)
-    return NULL;
-  else
-    {
-      strcat(cmpl_state->the_completion.text, text);
-      return &cmpl_state->the_completion;
-    }
-}
-
-static CompletionDir*
-find_completion_dir(gchar* text_to_complete,
-		    gchar** remaining_text,
-		    CompletionState* cmpl_state)
-{
-  gchar* first_slash = strchr(text_to_complete, '/');
-  CompletionDir* dir = cmpl_state->reference_dir;
-  CompletionDir* next;
-  *remaining_text = text_to_complete;
-
-  while(first_slash)
-    {
-      gint len = first_slash - *remaining_text;
-      gint found = 0;
-      gchar *found_name = NULL;         /* Quiet gcc */
-      gint i;
-      gchar* pat_buf = g_new (gchar, len + 1);
-
-      strncpy(pat_buf, *remaining_text, len);
-      pat_buf[len] = 0;
-
-      for(i = 0; i < dir->sent->entry_count; i += 1)
-	{
-	  if(dir->sent->entries[i].is_dir &&
-	     fnmatch(pat_buf, dir->sent->entries[i].entry_name,
-		     FNMATCH_FLAGS)!= FNM_NOMATCH)
-	    {
-	      if(found)
-		{
-		  g_free (pat_buf);
-		  return dir;
-		}
-	      else
-		{
-		  found = 1;
-		  found_name = dir->sent->entries[i].entry_name;
-		}
-	    }
-	}
-
-      if (!found)
-	{
-	  /* Perhaps we are trying to open an automount directory */
-	  found_name = pat_buf;
-	}
-
-      next = open_relative_dir(found_name, dir, cmpl_state);
-      
-      if(!next)
-	{
-	  g_free (pat_buf);
-	  return NULL;
-	}
-      
-      next->cmpl_parent = dir;
-      
-      dir = next;
-      
-      if(!correct_dir_fullname(dir))
-	{
-	  g_free(pat_buf);
-	  return NULL;
-	}
-      
-      *remaining_text = first_slash + 1;
-      first_slash = strchr(*remaining_text, '/');
-
-      g_free (pat_buf);
-    }
-
-  return dir;
-}
-
-static void
-update_cmpl(PossibleCompletion* poss, CompletionState* cmpl_state)
-{
-  gint cmpl_len;
-
-  if(!poss || !cmpl_is_a_completion(poss))
-    return;
-
-  cmpl_len = strlen(cmpl_this_completion(poss));
-
-  if(cmpl_state->updated_text_alloc < cmpl_len + 1)
-    {
-      cmpl_state->updated_text =
-	(gchar*)g_realloc(cmpl_state->updated_text,
-			  cmpl_state->updated_text_alloc);
-      cmpl_state->updated_text_alloc = 2*cmpl_len;
-    }
-
-  if(cmpl_state->updated_text_len < 0)
-    {
-      strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
-      cmpl_state->updated_text_len = cmpl_len;
-      cmpl_state->re_complete = cmpl_is_directory(poss);
-    }
-  else if(cmpl_state->updated_text_len == 0)
-    {
-      cmpl_state->re_complete = FALSE;
-    }
-  else
-    {
-      gint first_diff =
-	first_diff_index(cmpl_state->updated_text,
-			 cmpl_this_completion(poss));
-
-      cmpl_state->re_complete = FALSE;
-
-      if(first_diff == PATTERN_MATCH)
-	return;
-
-      if(first_diff > cmpl_state->updated_text_len)
-	strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
-
-      cmpl_state->updated_text_len = first_diff;
-      cmpl_state->updated_text[first_diff] = 0;
-    }
-}
-
-static PossibleCompletion*
-attempt_file_completion(CompletionState *cmpl_state)
-{
-  gchar *pat_buf, *first_slash;
-  CompletionDir *dir = cmpl_state->active_completion_dir;
-
-  dir->cmpl_index += 1;
-
-  if(dir->cmpl_index == dir->sent->entry_count)
-    {
-      if(dir->cmpl_parent == NULL)
-	{
-	  cmpl_state->active_completion_dir = NULL;
-
-	  return NULL;
-	}
-      else
-	{
-	  cmpl_state->active_completion_dir = dir->cmpl_parent;
-
-	  return attempt_file_completion(cmpl_state);
-	}
-    }
-
-  g_assert(dir->cmpl_text);
-
-  first_slash = strchr(dir->cmpl_text, '/');
-
-  if(first_slash)
-    {
-      gint len = first_slash - dir->cmpl_text;
-
-      pat_buf = g_new (gchar, len + 1);
-      strncpy(pat_buf, dir->cmpl_text, len);
-      pat_buf[len] = 0;
-    }
-  else
-    {
-      gint len = strlen(dir->cmpl_text);
-
-      pat_buf = g_new (gchar, len + 2);
-      strcpy(pat_buf, dir->cmpl_text);
-      strcpy(pat_buf + len, "*");
-    }
-
-  if(first_slash)
-    {
-      if(dir->sent->entries[dir->cmpl_index].is_dir)
-	{
-	  if(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
-		     FNMATCH_FLAGS) != FNM_NOMATCH)
-	    {
-	      CompletionDir* new_dir;
-
-	      new_dir = open_relative_dir(dir->sent->entries[dir->cmpl_index].entry_name,
-					  dir, cmpl_state);
-
-	      if(!new_dir)
-		{
-		  g_free (pat_buf);
-		  return NULL;
-		}
-
-	      new_dir->cmpl_parent = dir;
-
-	      new_dir->cmpl_index = -1;
-	      new_dir->cmpl_text = first_slash + 1;
-
-	      cmpl_state->active_completion_dir = new_dir;
-
-	      g_free (pat_buf);
-	      return attempt_file_completion(cmpl_state);
-	    }
-	  else
-	    {
-	      g_free (pat_buf);
-	      return attempt_file_completion(cmpl_state);
-	    }
-	}
-      else
-	{
-	  g_free (pat_buf);
-	  return attempt_file_completion(cmpl_state);
-	}
-    }
-  else
-    {
-      if(dir->cmpl_parent != NULL)
-	{
-	  append_completion_text(dir->fullname +
-				 strlen(cmpl_state->completion_dir->fullname) + 1,
-				 cmpl_state);
-	  append_completion_text("/", cmpl_state);
-	}
-
-      append_completion_text(dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
-
-      cmpl_state->the_completion.is_a_completion =
-	(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
-		 FNMATCH_FLAGS) != FNM_NOMATCH);
-
-      cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
-      if(dir->sent->entries[dir->cmpl_index].is_dir)
-	append_completion_text("/", cmpl_state);
-
-      g_free (pat_buf);
-      return &cmpl_state->the_completion;
-    }
-}
-
-
-static gint
-get_pwdb(CompletionState* cmpl_state)
-{
-  struct passwd *pwd_ptr;
-  gchar* buf_ptr;
-  gint len = 0, i, count = 0;
-
-  if(cmpl_state->user_dir_name_buffer)
-    return TRUE;
-  setpwent ();
-
-  while ((pwd_ptr = getpwent()) != NULL)
-    {
-      len += strlen(pwd_ptr->pw_name);
-      len += strlen(pwd_ptr->pw_dir);
-      len += 2;
-      count += 1;
-    }
-
-  setpwent ();
-
-  cmpl_state->user_dir_name_buffer = g_new(gchar, len);
-  cmpl_state->user_directories = g_new(CompletionUserDir, count);
-  cmpl_state->user_directories_len = count;
-
-  buf_ptr = cmpl_state->user_dir_name_buffer;
-
-  for(i = 0; i < count; i += 1)
-    {
-      pwd_ptr = getpwent();
-      if(!pwd_ptr)
-	{
-	  cmpl_errno = errno;
-	  goto error;
-	}
-
-      strcpy(buf_ptr, pwd_ptr->pw_name);
-      cmpl_state->user_directories[i].login = buf_ptr;
-      buf_ptr += strlen(buf_ptr);
-      buf_ptr += 1;
-      strcpy(buf_ptr, pwd_ptr->pw_dir);
-      cmpl_state->user_directories[i].homedir = buf_ptr;
-      buf_ptr += strlen(buf_ptr);
-      buf_ptr += 1;
-    }
-
-  qsort(cmpl_state->user_directories,
-	cmpl_state->user_directories_len,
-	sizeof(CompletionUserDir),
-	compare_user_dir);
-
-  endpwent();
-
-  return TRUE;
-
-error:
-
-  if(cmpl_state->user_dir_name_buffer)
-    g_free(cmpl_state->user_dir_name_buffer);
-  if(cmpl_state->user_directories)
-    g_free(cmpl_state->user_directories);
-
-  cmpl_state->user_dir_name_buffer = NULL;
-  cmpl_state->user_directories = NULL;
-
-  return FALSE;
-}
-
-static gint
-compare_user_dir(const void* a, const void* b)
-{
-  return strcmp((((CompletionUserDir*)a))->login,
-		(((CompletionUserDir*)b))->login);
-}
-
-static gint
-compare_cmpl_dir(const void* a, const void* b)
-{
-  return strcmp((((CompletionDirEntry*)a))->entry_name,
-		(((CompletionDirEntry*)b))->entry_name);
-}
-
-static gint
-cmpl_state_okay(CompletionState* cmpl_state)
-{
-  return  cmpl_state && cmpl_state->reference_dir;
-}
-
-static gchar*
-cmpl_strerror(gint err)
-{
-  if(err == CMPL_ERRNO_TOO_LONG)
-    return "Name too long";
-  else
-    return g_strerror (err);
-}
-
-
-/* Testing area */
-#ifdef TORRIE_DEBUG
-
-/* Get the selected filename and print it to the console */
-void file_ok_sel( GtkWidget        *w,
-                  GtkFileSelection *fs )
-{
-    g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
-}
-
-void destroy( GtkWidget *widget,
-              gpointer   data )
-{
-    gtk_main_quit ();
-}
-
-int main( int   argc,
-          char *argv[] )
-{
-    GtkWidget *filew;
-
-    gtk_init (&argc, &argv);
-
-    /* Create a new file selection widget */
-    filew = gtk_file_selection_new ("Michael's Glorious File Selector");
-//    gtk_file_selection_complete(GTK_FILE_SELECTION(filew),"bob");
-
-		
-    gtk_signal_connect (GTK_OBJECT (filew), "destroy",
-			(GtkSignalFunc) destroy, &filew);
-    /* Connect the ok_button to file_ok_sel function */
-    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
-			"clicked", (GtkSignalFunc) file_ok_sel, filew );
-
-    /* Connect the cancel_button to destroy the widget */
-    gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
-                                            (filew)->cancel_button),
-			       "clicked", (GtkSignalFunc) gtk_widget_destroy,
-			       GTK_OBJECT (filew));
-
-
-    gtk_widget_show(filew);
-
-/*
-    g_print("%d",gtk_file_selection_match_mask("mask.c","m*.c"));
-    g_print("%d",gtk_file_selection_match_mask("mask.c","m???.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.c","m??*.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c???"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c*"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","n*.c???"));
-		g_print("%d",gtk_file_selection_match_mask("mask.c","[mn]*"));
-		g_print("%d",gtk_file_selection_match_mask("COPYING","*.xpm"));
-*/	
-    gtk_main ();
-
-    return 0;
-}
-
-/* example-end */
-#endif
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+
+// leo FIXME: if we keep this file then we'll need to ask permission to the author, this is LGPL
+// This file is from the Advanced File Selector widget 
+// by Michael Torrie  <torriem@byu.edu>
+// http://students.cs.byu.edu/~torriem/gtk/
+
+// common files win32/linux
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+
+// TTimo
+// NOTE: the mkdir stuff etc. is in <direct.h> .. but I don't know what's the best strategy yet.
+// just including <direct.h> here doesn't cut it
+
+#if defined (__linux__) || (__APPLE__)
+#include <sys/param.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <pwd.h>
+#include "fnmatch.h"
+#endif
+
+// leo: added "gtk/"
+#include "gdk/gdkkeysyms.h"
+#include "gtk/gtkbutton.h"
+#include "gtk/gtkentry.h"
+#include "gtkfilesel-darwin.h"
+#include "gtk/gtkhbox.h"
+#include "gtk/gtkhbbox.h"
+#include "gtk/gtklabel.h"
+#include "gtk/gtklist.h"
+#include "gtk/gtklistitem.h"
+#include "gtk/gtkmain.h"
+#include "gtk/gtkscrolledwindow.h"
+#include "gtk/gtksignal.h"
+#include "gtk/gtkvbox.h"
+#include "gtk/gtkmenu.h"
+#include "gtk/gtkmenuitem.h"
+#include "gtk/gtkoptionmenu.h"
+#include "gtk/gtkclist.h"
+#include "gtk/gtkdialog.h"
+#include "gtk/gtkcombo.h"
+#include "gtk/gtkframe.h"
+
+// leo: disable NLS
+//#include "gtk/gtkintl.h"
+#define _(String) (String)
+
+#define DIR_LIST_WIDTH   180
+#define DIR_LIST_HEIGHT  180
+#define FILE_LIST_WIDTH  180
+#define FILE_LIST_HEIGHT 180
+
+/* I've put this here so it doesn't get confused with the 
+ * file completion interface */
+typedef struct _HistoryCallbackArg HistoryCallbackArg;
+
+struct _HistoryCallbackArg
+{
+  gchar *directory;
+  GtkWidget *menu_item;
+};
+
+
+typedef struct _CompletionState    CompletionState;
+typedef struct _CompletionDir      CompletionDir;
+typedef struct _CompletionDirSent  CompletionDirSent;
+typedef struct _CompletionDirEntry CompletionDirEntry;
+typedef struct _CompletionUserDir  CompletionUserDir;
+typedef struct _PossibleCompletion PossibleCompletion;
+
+/* Non-external file completion decls and structures */
+
+/* A contant telling PRCS how many directories to cache.  Its actually
+ * kept in a list, so the geometry isn't important. */
+#define CMPL_DIRECTORY_CACHE_SIZE 10
+
+/* A constant used to determine whether a substring was an exact
+ * match by first_diff_index()
+ */
+#define PATTERN_MATCH -1
+/* The arguments used by all fnmatch() calls below
+ */
+#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
+
+#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
+
+/* This structure contains all the useful information about a directory
+ * for the purposes of filename completion.  These structures are cached
+ * in the CompletionState struct.  CompletionDir's are reference counted.
+ */
+struct _CompletionDirSent
+{
+  ino_t inode;
+  time_t mtime;
+  dev_t device;
+
+  gint entry_count;
+  gchar *name_buffer; /* memory segment containing names of all entries */
+
+  struct _CompletionDirEntry *entries;
+};
+
+struct _CompletionDir
+{
+  CompletionDirSent *sent;
+
+  gchar *fullname;
+  gint fullname_len;
+
+  struct _CompletionDir *cmpl_parent;
+  gint cmpl_index;
+  gchar *cmpl_text;
+};
+
+/* This structure contains pairs of directory entry names with a flag saying
+ * whether or not they are a valid directory.  NOTE: This information is used
+ * to provide the caller with information about whether to update its completions
+ * or try to open a file.  Since directories are cached by the directory mtime,
+ * a symlink which points to an invalid file (which will not be a directory),
+ * will not be reevaluated if that file is created, unless the containing
+ * directory is touched.  I consider this case to be worth ignoring (josh).
+ */
+struct _CompletionDirEntry
+{
+  gint is_dir;
+  gchar *entry_name;
+};
+
+struct _CompletionUserDir
+{
+  gchar *login;
+  gchar *homedir;
+};
+
+struct _PossibleCompletion
+{
+  /* accessible fields, all are accessed externally by functions
+   * declared above
+   */
+  gchar *text;
+  gint is_a_completion;
+  gint is_directory;
+
+  gint file_size;
+  gint file_time;
+  gint uid;
+  gint gid;
+  /* Private fields
+   */
+  gint text_alloc;
+};
+
+struct _CompletionState
+{
+  gint last_valid_char;
+  gchar *updated_text;
+  gint updated_text_len;
+  gint updated_text_alloc;
+  gint re_complete;
+
+  gchar *user_dir_name_buffer;
+  gint user_directories_len;
+
+  gchar *last_completion_text;
+
+  gint user_completion_index; /* if >= 0, currently completing ~user */
+
+  struct _CompletionDir *completion_dir; /* directory completing from */
+  struct _CompletionDir *active_completion_dir;
+
+  struct _PossibleCompletion the_completion;
+
+  struct _CompletionDir *reference_dir; /* initial directory */
+
+  GList* directory_storage;
+  GList* directory_sent_storage;
+
+  struct _CompletionUserDir *user_directories;
+};
+
+
+/* File completion functions which would be external, were they used
+ * outside of this file.
+ */
+
+static CompletionState*    cmpl_init_state        (void);
+static void                cmpl_free_state        (CompletionState *cmpl_state);
+static gint                cmpl_state_okay        (CompletionState* cmpl_state);
+static gchar*              cmpl_strerror          (gint);
+
+static PossibleCompletion* cmpl_completion_matches(gchar           *text_to_complete,
+						   gchar          **remaining_text,
+						   CompletionState *cmpl_state);
+
+/* Returns a name for consideration, possibly a completion, this name
+ * will be invalid after the next call to cmpl_next_completion.
+ */
+static char*               cmpl_this_completion   (PossibleCompletion*);
+
+/* True if this completion matches the given text.  Otherwise, this
+ * output can be used to have a list of non-completions.
+ */
+static gint                cmpl_is_a_completion   (PossibleCompletion*);
+
+/* True if the completion is a directory
+ */
+static gint                cmpl_is_directory      (PossibleCompletion*);
+
+/* Obtains the next completion, or NULL
+ */
+static PossibleCompletion* cmpl_next_completion   (CompletionState*);
+
+/* Updating completions: the return value of cmpl_updated_text() will
+ * be text_to_complete completed as much as possible after the most
+ * recent call to cmpl_completion_matches.  For the present
+ * application, this is the suggested replacement for the user's input
+ * string.  You must CALL THIS AFTER ALL cmpl_text_completions have
+ * been received.
+ */
+static gchar*              cmpl_updated_text       (CompletionState* cmpl_state);
+
+/* After updating, to see if the completion was a directory, call
+ * this.  If it was, you should consider re-calling completion_matches.
+ */
+static gint                cmpl_updated_dir        (CompletionState* cmpl_state);
+
+/* Current location: if using file completion, return the current
+ * directory, from which file completion begins.  More specifically,
+ * the cwd concatenated with all exact completions up to the last
+ * directory delimiter('/').
+ */
+static gchar*              cmpl_reference_position (CompletionState* cmpl_state);
+
+/* backing up: if cmpl_completion_matches returns NULL, you may query
+ * the index of the last completable character into cmpl_updated_text.
+ */
+static gint                cmpl_last_valid_char    (CompletionState* cmpl_state);
+
+/* When the user selects a non-directory, call cmpl_completion_fullname
+ * to get the full name of the selected file.
+ */
+static gchar*              cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);
+
+
+/* Directory operations. */
+static CompletionDir* open_ref_dir         (gchar* text_to_complete,
+					    gchar** remaining_text,
+					    CompletionState* cmpl_state);
+static gboolean       check_dir            (gchar *dir_name, 
+					    struct stat *result, 
+					    gboolean *stat_subdirs);
+static CompletionDir* open_dir             (gchar* dir_name,
+					    CompletionState* cmpl_state);
+static CompletionDir* open_user_dir        (gchar* text_to_complete,
+					    CompletionState *cmpl_state);
+static CompletionDir* open_relative_dir    (gchar* dir_name, CompletionDir* dir,
+					    CompletionState *cmpl_state);
+static CompletionDirSent* open_new_dir     (gchar* dir_name, 
+					    struct stat* sbuf,
+					    gboolean stat_subdirs);
+static gint           correct_dir_fullname (CompletionDir* cmpl_dir);
+static gint           correct_parent       (CompletionDir* cmpl_dir,
+					    struct stat *sbuf);
+static gchar*         find_parent_dir_fullname    (gchar* dirname);
+static CompletionDir* attach_dir           (CompletionDirSent* sent,
+					    gchar* dir_name,
+					    CompletionState *cmpl_state);
+static void           free_dir_sent (CompletionDirSent* sent);
+static void           free_dir      (CompletionDir  *dir);
+static void           prune_memory_usage(CompletionState *cmpl_state);
+
+/* Completion operations */
+static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,
+						      CompletionState *cmpl_state);
+static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);
+static CompletionDir* find_completion_dir(gchar* text_to_complete,
+					  gchar** remaining_text,
+					  CompletionState* cmpl_state);
+static PossibleCompletion* append_completion_text(gchar* text,
+						  CompletionState* cmpl_state);
+static gint get_pwdb(CompletionState* cmpl_state);
+static gint first_diff_index(gchar* pat, gchar* text);
+static gint compare_user_dir(const void* a, const void* b);
+static gint compare_cmpl_dir(const void* a, const void* b);
+static void update_cmpl(PossibleCompletion* poss,
+			CompletionState* cmpl_state);
+
+static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);
+static void gtk_file_selection_init          (GtkFileSelection      *filesel);
+static void gtk_file_selection_destroy       (GtkObject             *object);
+static gint gtk_file_selection_key_press     (GtkWidget             *widget,
+					      GdkEventKey           *event,
+					      gpointer               user_data);
+
+static void gtk_file_selection_file_button (GtkWidget *widget,
+					    gint row, 
+					    gint column, 
+					    GdkEventButton *bevent,
+					    gpointer user_data);
+
+static void gtk_file_selection_dir_button (GtkWidget *widget,
+					   gint row,
+					   gint column,
+					   GdkEventButton *bevent,
+					   gpointer data);
+
+static void gtk_file_selection_undir_button (GtkWidget *widget,
+					     gint row,
+					     gint column,
+					     GdkEventButton *bevent,
+					     gpointer data);
+
+static void gtk_file_selection_populate      (GtkFileSelection      *fs,
+					      gchar                 *rel_path,
+					      gint                   try_complete);
+static void gtk_file_selection_abort         (GtkFileSelection      *fs);
+
+static void gtk_file_selection_update_history_menu (GtkFileSelection       *fs,
+						    gchar                  *current_dir);
+
+static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
+
+static gboolean gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
+static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
+																							GdkEventKey *event,
+																							gpointer user_data);
+static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
+																							GdkEventButton *event,
+																							gpointer user_data);
+static void gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_home_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_up_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_prev_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_next_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data);
+
+static gint gtk_file_selection_match_char (gchar, gchar *mask);
+static gint gtk_file_selection_match_mask (gchar *,gchar *);
+
+
+static GtkWindowClass *parent_class = NULL;
+
+/* Saves errno when something cmpl does fails. */
+static gint cmpl_errno;
+
+
+void gtk_file_selection_clear_masks (GtkFileSelection *filesel)
+{
+  GList *list;
+
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+
+  list = filesel->masks;
+  while (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  filesel->masks = NULL;
+
+  gtk_list_clear_items (GTK_LIST (GTK_COMBO (filesel->mask_entry)->list), 0, -1);
+}
+
+void gtk_file_selection_set_masks (GtkFileSelection *filesel, const gchar **masks)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+
+  while (*masks)
+    {
+      filesel->masks = g_list_append (filesel->masks, (gpointer)*masks);
+      masks++;
+    }
+
+  if (filesel->masks)
+    gtk_combo_set_popdown_strings (GTK_COMBO (filesel->mask_entry), filesel->masks);
+}
+
+
+/* General notes:
+ * Make prev and next inactive if their respective *
+ *   histories are empty.
+ * Add facilities for handling hidden files and    *
+ * directories                                     *
+ * Add an api to access the mask, and hidden files *
+ * check box?  (prob not in 1.2.x series)          *
+ */
+
+/* Routine for applying mask to filenames         *
+ *   Need to be optimized to minimize recursion   *
+ *     help the for loop by looking for the next  *
+ *     instance of the mask character following   *
+ *     the '*'.  ei *.c -- look for '.'           *
+ *     Also, swap all *? pairs (-> ?*), as that   *
+ *     will make it possible to look ahead (?     *
+ *     makes it very nondeterministic as in *?.c  *
+ *     which really is ?*.c                       *
+ *   Allow multiply masks, separted by commas     *
+ *   Allow more flexible [] handling (ie [a-zA-Z] *
+ *                                                *
+ */
+static gint gtk_file_selection_match_char (gchar text, gchar *mask){
+  gchar *maskc;
+  gint x;
+  gint s;
+	
+  if (mask[0] == '[')
+    {
+      if (!strchr (mask,']')) return 0;
+      maskc = g_strdup(mask + 1); /* get the portion of mask inside []*/
+		
+      (*(strchr (maskc,']'))) = 0;
+      s = strlen ((char *)maskc);
+
+      for (x = 0; x < s; x++){
+	if (text == maskc[x])
+	  {
+	    g_free (maskc);
+	    return s + 2;
+	  }
+      }
+      g_free (maskc);
+      return 0;
+    }
+
+  if (mask[0] == '?') return 1;
+  if (mask[0] == text) return 1;
+
+  return 0;
+}
+
+
+static gint gtk_file_selection_match_mask (gchar *text, gchar *mask){
+
+  int mc;
+  int tc;
+
+  tc = 0; mc = 0;
+	
+  if (mask[0] == 0 && text[0] == 0) return 1;
+	
+  if (mask[0] == '*')
+    {
+      for (tc = 0; tc <= strlen(text); tc++)
+	{
+	  if (gtk_file_selection_match_mask (text + tc, mask + 1))
+	    return 1;
+	}
+      return 0;
+    }
+  mc = gtk_file_selection_match_char (text[0], mask);
+
+  if(mc)
+    return gtk_file_selection_match_mask (text + 1, mask + mc);
+  else
+    return 0;
+}
+
+GtkType
+gtk_file_selection_get_type (void)
+{
+  static GtkType file_selection_type = 0;
+
+  if (!file_selection_type)
+    {
+      static const GtkTypeInfo filesel_info =
+      {
+	"GtkFileSelection",
+	sizeof (GtkFileSelection),
+	sizeof (GtkFileSelectionClass),
+	(GtkClassInitFunc) gtk_file_selection_class_init,
+	(GtkObjectInitFunc) gtk_file_selection_init,
+	/* reserved_1 */ NULL,
+	/* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
+      };
+
+      file_selection_type = gtk_type_unique (GTK_TYPE_WINDOW, &filesel_info);
+    }
+
+  return file_selection_type;
+}
+
+static void
+gtk_file_selection_class_init (GtkFileSelectionClass *klass)	//tigital
+{
+  GtkObjectClass *object_class;
+
+  object_class = (GtkObjectClass*) klass;
+
+  parent_class = gtk_type_class (GTK_TYPE_WINDOW);
+
+  object_class->destroy = gtk_file_selection_destroy;
+}
+
+static void
+gtk_file_selection_init (GtkFileSelection *filesel)
+{
+  GtkWidget *entry_vbox;
+  GtkWidget *label;
+  GtkWidget *list_hbox;
+  GtkWidget *confirm_area;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *pulldown_hbox;
+  GtkWidget *scrolled_win;
+  GtkWidget *mask_label;
+  GtkWidget *bigframe;
+  GtkWidget *label_lookingin;
+  GtkWidget *up_button;
+  GtkWidget *home_button;
+  GtkWidget *prev_button;
+  GtkWidget *next_button;
+  GtkWidget *refresh_button;
+
+  char *dir_title [2];
+  char *file_title [2];
+  
+  filesel->cmpl_state = cmpl_init_state ();
+
+  filesel->mask=NULL;
+  filesel->prev_history=NULL;
+  filesel->next_history=NULL;
+  filesel->saved_entry=NULL;
+
+  /* The dialog-sized vertical box  */
+  filesel->main_vbox = gtk_vbox_new (FALSE, 10);
+  gtk_container_set_border_width (GTK_CONTAINER (filesel), 10);
+  gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
+  gtk_widget_show (filesel->main_vbox);
+
+  /* The horizontal box containing create, rename etc. buttons */
+  filesel->button_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(filesel->button_area), GTK_BUTTONBOX_START);
+  gtk_button_box_set_spacing(GTK_BUTTON_BOX(filesel->button_area), 0);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->button_area, 
+		      FALSE, FALSE, 0);
+  gtk_widget_show (filesel->button_area);
+  
+  gtk_file_selection_show_fileop_buttons(filesel);
+
+  /* hbox for pulldown menu */
+  pulldown_hbox = gtk_hbox_new (FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);
+  gtk_widget_show (pulldown_hbox);
+  
+  /* The combo box that replaces the pulldown menu */
+  label_lookingin = gtk_label_new (_("Looking in:"));
+  gtk_widget_show (label_lookingin);
+  gtk_box_pack_start (GTK_BOX (pulldown_hbox), label_lookingin, FALSE, FALSE, 0);
+
+  filesel->history_combo = gtk_combo_new();
+  gtk_widget_show(filesel->history_combo);
+  gtk_combo_set_value_in_list(GTK_COMBO(filesel->history_combo),FALSE,FALSE);
+  gtk_box_pack_start (GTK_BOX(pulldown_hbox),filesel->history_combo,
+  				TRUE,TRUE, 0);
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->entry),"key-press-event",				    
+		     (GtkSignalFunc) gtk_file_selection_history_combo_callback,
+		     (gpointer) filesel);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"button-press-event",
+		     (GtkSignalFunc) gtk_file_selection_history_combo_list_callback,
+		     (gpointer) filesel);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"key-press-event",
+		     (GtkSignalFunc) gtk_file_selection_history_combo_list_key_handler,
+		     (gpointer) filesel);
+
+  /*  frame to put the following hbox in  */
+  bigframe = gtk_frame_new (NULL);
+  gtk_widget_show (bigframe);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), bigframe, TRUE, TRUE, 0);
+
+  /*  The horizontal box containing the directory and file listboxes  */
+  list_hbox = gtk_hbox_new (FALSE, 5);
+  gtk_container_add (GTK_CONTAINER(bigframe), list_hbox);
+  gtk_container_set_border_width (GTK_CONTAINER (list_hbox), 5);
+  gtk_widget_show (list_hbox);
+
+  /* vbox to put the buttons and directory listing in  */
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (vbox);
+  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, FALSE, FALSE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  home_button = gtk_button_new_with_label (_("Home"));
+  gtk_widget_show (home_button);
+  gtk_signal_connect (GTK_OBJECT (home_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_home_button,
+		      (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox), home_button, TRUE,TRUE, 0);
+
+  prev_button = gtk_button_new_with_label (_("Prev"));
+  gtk_signal_connect (GTK_OBJECT (prev_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_prev_button,
+		      (gpointer) filesel);
+  gtk_widget_show (prev_button);
+  gtk_box_pack_start (GTK_BOX (hbox), prev_button, TRUE,TRUE, 0);
+
+  up_button = gtk_button_new_with_label (_("Up"));
+  gtk_signal_connect (GTK_OBJECT (up_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_up_button,
+		      (gpointer) filesel);
+  gtk_widget_show (up_button);
+  gtk_box_pack_start (GTK_BOX (hbox), up_button, TRUE,TRUE, 0);
+
+  next_button = gtk_button_new_with_label (_("Next"));
+  gtk_widget_show (next_button);
+  gtk_signal_connect (GTK_OBJECT (next_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_next_button,
+		      (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox), next_button, TRUE,TRUE, 0);
+
+  refresh_button = gtk_button_new_with_label (_("Refresh"));
+  gtk_widget_show (refresh_button);
+  gtk_signal_connect (GTK_OBJECT (refresh_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_refresh_button,
+		      (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox), refresh_button, TRUE, TRUE, 0);
+
+  /* The directories clist */
+  dir_title[0] = _("Directories");
+  dir_title[1] = NULL;
+  filesel->dir_list = gtk_clist_new_with_titles (1, (gchar**) dir_title);
+  gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
+  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",
+		      (GtkSignalFunc) gtk_file_selection_dir_button,
+		      (gpointer) filesel);
+  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "unselect_row",
+		      (GtkSignalFunc) gtk_file_selection_undir_button,
+		      (gpointer) filesel);
+  gtk_clist_column_titles_passive (GTK_CLIST (filesel->dir_list));
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->dir_list);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE,TRUE, 5);
+  gtk_widget_show (filesel->dir_list);
+  gtk_widget_show (scrolled_win);
+
+  /* vbox area for mask entry and files clist  */
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (vbox);
+  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, TRUE, TRUE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 5);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  mask_label = gtk_label_new (_("Mask:"));
+  gtk_widget_show (mask_label);
+  gtk_box_pack_start (GTK_BOX (hbox), mask_label, FALSE, FALSE, 0);
+
+  filesel->mask_entry = gtk_entry_new ();
+  gtk_widget_show (filesel->mask_entry);
+  gtk_signal_connect(GTK_OBJECT(filesel->mask_entry),"activate",
+		     (GtkSignalFunc) gtk_file_selection_mask_entry_callback,
+		     (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
+
+
+  /* The files clist */
+  file_title[0] = _("Files");
+  file_title[1] = NULL;
+  filesel->file_list = gtk_clist_new_with_titles (1, (gchar**) file_title);
+  gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
+  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
+		      (GtkSignalFunc) gtk_file_selection_file_button, 
+		      (gpointer) filesel);
+  gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->file_list);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 5);
+  gtk_widget_show (filesel->file_list);
+  gtk_widget_show (scrolled_win);
+
+  /* action area for packing buttons into. */
+  filesel->action_area = gtk_hbox_new (TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->action_area, 
+		      FALSE, FALSE, 0);
+  gtk_widget_show (filesel->action_area);
+  
+  /*  The OK/Cancel button area */
+  confirm_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);
+  gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);
+  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), confirm_area, FALSE, FALSE, 0);
+  gtk_widget_show (confirm_area);
+
+  /*  The OK button  */
+  filesel->ok_button = gtk_button_new_with_label (_("OK"));
+  GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->ok_button, TRUE, TRUE, 0);
+  gtk_widget_grab_default (filesel->ok_button);
+  gtk_widget_show (filesel->ok_button);
+
+  /*  The Cancel button  */
+  filesel->cancel_button = gtk_button_new_with_label (_("Cancel"));
+  GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->cancel_button, TRUE, TRUE, 0);
+  gtk_widget_show (filesel->cancel_button);
+
+  /*  The selection entry widget  */
+  entry_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
+  gtk_widget_show (entry_vbox);
+
+  filesel->selection_text = label = gtk_label_new ("");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+  filesel->selection_entry = gtk_entry_new ();
+  gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
+		      (GtkSignalFunc) gtk_file_selection_key_press, filesel);
+  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
+			     (GtkSignalFunc) gtk_widget_grab_default,
+			     GTK_OBJECT (filesel->ok_button));
+  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
+                             (GtkSignalFunc) gtk_button_clicked,
+                             GTK_OBJECT (filesel->ok_button));
+  gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
+  gtk_widget_show (filesel->selection_entry);
+
+  if (!cmpl_state_okay (filesel->cmpl_state))
+    {
+      gchar err_buf[256];
+
+      sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
+
+      gtk_label_set_text (GTK_LABEL (filesel->selection_text), err_buf);
+    }
+  else
+    {
+      gtk_file_selection_populate (filesel, "", FALSE);
+    }
+
+  gtk_widget_grab_focus (filesel->selection_entry);
+}
+
+GtkWidget*
+gtk_file_selection_new (const gchar *title)
+{
+  GtkFileSelection *filesel;
+
+  filesel = gtk_type_new (GTK_TYPE_FILE_SELECTION);
+  gtk_window_set_title (GTK_WINDOW (filesel), title);
+
+  return GTK_WIDGET (filesel);
+}
+
+void
+gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+    
+  /* delete, create directory, and rename */
+  if (!filesel->fileop_c_dir) 
+    {
+      filesel->fileop_c_dir = gtk_button_new_with_label (_("Create Dir"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_c_dir), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_create_dir, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_c_dir, TRUE, TRUE, 0);
+      gtk_widget_show (filesel->fileop_c_dir);
+    }
+	
+  if (!filesel->fileop_del_file) 
+    {
+      filesel->fileop_del_file = gtk_button_new_with_label (_("Delete File"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_del_file), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_delete_file, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_del_file, TRUE, TRUE, 0);
+      gtk_widget_show (filesel->fileop_del_file);
+    }
+
+  if (!filesel->fileop_ren_file)
+    {
+      filesel->fileop_ren_file = gtk_button_new_with_label (_("Rename File"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_ren_file), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_rename_file, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_ren_file, TRUE, TRUE, 0);
+      gtk_widget_show (filesel->fileop_ren_file);
+    }
+
+  gtk_widget_queue_resize(GTK_WIDGET(filesel));
+}
+
+void       
+gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+    
+  if (filesel->fileop_ren_file) 
+    {
+      gtk_widget_destroy (filesel->fileop_ren_file);
+      filesel->fileop_ren_file = NULL;
+    }
+
+  if (filesel->fileop_del_file)
+    {
+      gtk_widget_destroy (filesel->fileop_del_file);
+      filesel->fileop_del_file = NULL;
+    }
+
+  if (filesel->fileop_c_dir)
+    {
+      gtk_widget_destroy (filesel->fileop_c_dir);
+      filesel->fileop_c_dir = NULL;
+    }
+}
+
+
+
+void
+gtk_file_selection_set_filename (GtkFileSelection *filesel,
+				 const gchar      *filename)
+{
+  char  buf[MAXPATHLEN];
+  const char *name, *last_slash;
+
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+  g_return_if_fail (filename != NULL);
+
+  last_slash = strrchr (filename, '/');
+
+  if (!last_slash)
+    {
+      buf[0] = 0;
+      name = filename;
+    }
+  else
+    {
+      gint len = MIN (MAXPATHLEN - 1, last_slash - filename + 1);
+
+      strncpy (buf, filename, len);
+      buf[len] = 0;
+
+      name = last_slash + 1;
+    }
+
+  gtk_file_selection_populate (filesel, buf, FALSE);
+
+  if (filesel->selection_entry)
+    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
+}
+
+gchar*
+gtk_file_selection_get_filename (GtkFileSelection *filesel)
+{
+  static char nothing[2] = "";
+  char *text;
+  char *filename;
+
+  g_return_val_if_fail (filesel != NULL, nothing);
+  g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), nothing);
+
+  text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
+  if (text)
+    {
+      filename = cmpl_completion_fullname (text, filesel->cmpl_state);
+      return filename;
+    }
+
+  return nothing;
+}
+
+void
+gtk_file_selection_complete (GtkFileSelection *filesel,
+			     const gchar      *pattern)
+{
+  gchar *new_pattern;
+  gint x;
+	
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+  g_return_if_fail (pattern != NULL);
+
+  if (filesel->selection_entry)
+    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), pattern);
+	
+  if(strchr(pattern,'*') || strchr(pattern,'?'))
+    {
+      for(x=strlen(pattern);x>=0;x--)
+	{
+	  if(pattern[x]=='/') break;
+	}
+      gtk_entry_set_text(GTK_ENTRY(filesel->mask_entry),g_strdup(pattern+x+1));
+      
+      if(filesel->mask) g_free(filesel->mask);
+      
+      filesel->mask=g_strdup(pattern+x+1);
+      new_pattern=g_strdup(pattern);
+      new_pattern[x+1]=0;
+      gtk_file_selection_populate (filesel, (gchar*) new_pattern, TRUE);
+      g_free(new_pattern);
+    }
+  else
+    {
+      gtk_file_selection_populate (filesel, (gchar*) pattern, TRUE);
+    }
+}
+
+static void
+gtk_file_selection_destroy (GtkObject *object)
+{
+  GtkFileSelection *filesel;
+  GList *list;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (object));
+
+  filesel = GTK_FILE_SELECTION (object);
+  
+  if (filesel->fileop_dialog)
+    gtk_widget_destroy (filesel->fileop_dialog);
+  
+  if (filesel->next_history)
+    {
+      list = filesel->next_history;
+      while (list)
+  	{
+	  g_free (list->data);
+	  list = list->next;
+  	}
+    }
+  g_list_free (filesel->next_history);
+  filesel->next_history = NULL;
+
+  if (filesel->prev_history)
+    {
+      list = filesel->prev_history;
+      while (list)
+  	{
+	  g_free (list->data);
+	  list = list->next;
+  	}
+    }
+  g_list_free (filesel->prev_history);
+  filesel->prev_history = NULL;
+
+  if (filesel->mask)
+    {
+      g_free (filesel->mask);
+      filesel->mask = NULL;
+    }
+  
+  cmpl_free_state (filesel->cmpl_state);
+  filesel->cmpl_state = NULL;
+
+  if (GTK_OBJECT_CLASS (parent_class)->destroy)
+    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/* Begin file operations callbacks */
+
+static void
+gtk_file_selection_fileop_error (GtkFileSelection *fs, gchar *error_message)
+{
+  GtkWidget *label;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *dialog;
+  
+  g_return_if_fail (error_message != NULL);
+  
+  /* main dialog */
+  dialog = gtk_dialog_new ();
+  /*
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  */
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+  
+  /* If file dialog is grabbed, make this dialog modal too */
+  /* When error dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+
+  label = gtk_label_new(error_message);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+
+  /* yes, we free it */
+  g_free (error_message);
+  
+  /* close button */
+  button = gtk_button_new_with_label (_("Close"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_fileop_destroy (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  fs->fileop_dialog = NULL;
+}
+
+
+static void
+gtk_file_selection_create_dir_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  gchar *dirname;
+  gchar *path;
+  gchar *full_path;
+  gchar *buf;
+  CompletionState *cmpl_state;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  dirname = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  full_path = g_strconcat (path, "/", dirname, NULL);
+  if ( (mkdir (full_path, 0755) < 0) ) 
+    {
+      buf = g_strconcat ("Error creating directory \"", dirname, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (full_path);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+  
+static void
+gtk_file_selection_create_dir (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *button;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Create Directory"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+  
+  label = gtk_label_new(_("Directory name:"));
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+
+  /*  The directory entry widget  */
+  fs->fileop_entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
+		      TRUE, TRUE, 5);
+  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+  gtk_widget_show (fs->fileop_entry);
+  
+  /* buttons */
+  button = gtk_button_new_with_label (_("Create"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_create_dir_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_delete_file_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  CompletionState *cmpl_state;
+  gchar *path;
+  gchar *full_path;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  full_path = g_strconcat (path, "/", fs->fileop_file, NULL);
+  if ( (unlink (full_path) < 0) ) 
+    {
+      buf = g_strconcat ("Error deleting file \"", fs->fileop_file, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (full_path);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+
+static void
+gtk_file_selection_delete_file (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *dialog;
+  gchar *filename;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+
+  filename = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+  if (strlen(filename) < 1)
+	  return;
+
+  fs->fileop_file = filename;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Delete File"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+  
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+
+  buf = g_strconcat ("Really delete file \"", filename, "\" ?", NULL);
+  label = gtk_label_new(buf);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+  g_free(buf);
+  
+  /* buttons */
+  button = gtk_button_new_with_label (_("Delete"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_delete_file_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+
+}
+
+static void
+gtk_file_selection_rename_file_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  gchar *buf;
+  gchar *file;
+  gchar *path;
+  gchar *new_filename;
+  gchar *old_filename;
+  CompletionState *cmpl_state;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  new_filename = g_strconcat (path, "/", file, NULL);
+  old_filename = g_strconcat (path, "/", fs->fileop_file, NULL);
+
+  if ( (rename (old_filename, new_filename)) < 0) 
+    {
+      buf = g_strconcat ("Error renaming file \"", file, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (new_filename);
+  g_free (old_filename);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+  
+static void
+gtk_file_selection_rename_file (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+
+  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+  if (strlen(fs->fileop_file) < 1)
+	  return;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Rename File"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog  closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+  
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+  
+  buf = g_strconcat ("Rename file \"", fs->fileop_file, "\" to:", NULL);
+  label = gtk_label_new(buf);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+  g_free(buf);
+
+  /* New filename entry */
+  fs->fileop_entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
+		      TRUE, TRUE, 5);
+  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+  gtk_widget_show (fs->fileop_entry);
+  
+  gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
+  gtk_editable_select_region (GTK_EDITABLE (fs->fileop_entry),
+			      0, strlen (fs->fileop_file));
+
+  /* buttons */
+  button = gtk_button_new_with_label (_("Rename"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+
+static gint
+gtk_file_selection_key_press (GtkWidget   *widget,
+			      GdkEventKey *event,
+			      gpointer     user_data)
+{
+  GtkFileSelection *fs;
+  char *text;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  fs = GTK_FILE_SELECTION (user_data);
+
+  if (event->keyval == GDK_Tab)
+    {
+      text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+
+      text = g_strdup (text);
+
+      gtk_file_selection_populate (fs, text, TRUE);
+
+      g_free (text);
+
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+
+      return TRUE;
+    }
+  if (fs->saved_entry)
+    {
+      gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
+      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
+      g_free (fs->saved_entry);
+      fs->saved_entry = NULL;
+    }
+
+
+  return FALSE;
+}
+
+static void
+gtk_file_selection_home_button (GtkWidget *widget, gpointer data){
+  GList *list;
+	
+  GtkFileSelection *fs=data;
+
+  list = fs->next_history;
+  if (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+		
+  gtk_file_selection_populate (fs,"~/",FALSE);
+}
+
+static void
+gtk_file_selection_up_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->next_history;
+  if (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+
+  gtk_file_selection_populate (fs, "../", FALSE); /*change directories. */
+		
+}
+
+static void
+gtk_file_selection_prev_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+  GList *first;
+  gchar *path;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->prev_history;
+
+  if (list && g_list_length(list) > 1)
+    {
+      first = list;            /* get first element */
+      list = list->next;       /* pop off current directory */
+
+      list->prev = NULL;       /* make this the new head. */
+  	
+      fs->prev_history = list; /* update prev_history list */
+      fs->next_history = g_list_prepend(fs->next_history,first->data); /* put it on next_history */
+  	
+      first->next = NULL;      /* orphan the old first node */
+      g_list_free (first);     /* free the node (data is now in use by next_history) */
+
+
+  	
+      path = g_malloc(strlen(list->data)+4); /* plenty of space */
+      strcpy(path,list->data);               /* get the 2nd path in the history */
+      strcat(path,"/");                      /* append a '/' */
+      gtk_file_selection_populate (fs, path, FALSE); /* change directories. */
+      g_free (path);
+    }
+}	
+
+static void
+gtk_file_selection_next_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+  GList *first;
+  gchar *path;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->next_history;
+
+  if (list && g_list_length(list) > 0)
+    {
+      first = list;            /*get first element*/
+      list = list->next;       /*pop off current directory*/
+      
+      if (list)
+	list->prev = NULL;
+      
+      fs->next_history = list;                       /*update prev_history list*/
+  	
+      path = g_malloc(strlen(first->data)+4);        /*plenty of space*/
+      strcpy(path,first->data);
+      strcat(path,"/");                              /*append a /   */
+      gtk_file_selection_populate (fs, path, FALSE); /*change directories.*/
+      g_free(path);
+  	
+      first->next = NULL;     /* orphan the old first node */
+      g_list_free (first);    /* free the node (data is now in use by next_history) */
+      
+    }
+}	
+
+void static
+gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_file_selection_populate (fs,"",FALSE);
+}
+
+static void
+gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+
+  if(fs->mask)
+    g_free (fs->mask);
+		
+  fs->mask = g_strdup(gtk_entry_get_text (GTK_ENTRY(fs->mask_entry)));
+	
+  if (strlen(fs->mask) == 0)
+    {
+      g_free (fs->mask);
+      fs->mask = NULL;
+    }
+	
+  gtk_file_selection_refresh_button (widget,data);
+}
+
+static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
+								  GdkEventKey *event,
+								  gpointer user_data)
+{
+  /*
+  g_print("Key pressed! \n");
+  */
+	
+  return TRUE;
+}
+
+static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
+								GdkEventButton *event,
+								gpointer user_data)
+{
+
+  GtkFileSelection *fs = user_data;
+  GList *list;
+  gchar *path;
+		
+  list = fs->next_history;
+  if(list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+			
+  path = g_malloc(strlen(gtk_entry_get_text(GTK_ENTRY (((GtkCombo *)fs->history_combo)->entry)))+4);
+  strcpy (path,gtk_entry_get_text(GTK_ENTRY( ((GtkCombo *)fs->history_combo)->entry)));
+  strcat (path,"/");
+	
+  gtk_file_selection_populate (fs,path,TRUE);
+	
+  g_free (path);
+
+  return TRUE;
+}
+
+static gboolean
+gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+  GtkEntry *entry=(GtkEntry *)widget;
+  GtkFileSelection *fs=data;
+  GList *list;
+  gchar *path;
+	
+  g_return_val_if_fail (fs != NULL,FALSE);
+  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
+	
+
+  if (event->keyval == GDK_Return)
+    {
+      list = fs->next_history;
+      if (list)
+	{
+	  g_free (list->data);
+	  list = list->next;
+	}
+      g_list_free (fs->next_history);
+      fs->next_history = NULL;
+      
+      path = g_malloc(strlen(gtk_entry_get_text(entry))+4);
+      strcpy (path,gtk_entry_get_text(entry));
+      strcat (path,"/");
+      gtk_file_selection_populate (fs,path,TRUE);
+      g_free (path);
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
+
+}
+
+static void
+gtk_file_selection_update_history_menu (GtkFileSelection *fs,
+					gchar *current_directory)
+{
+  gchar *current_dir;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  g_return_if_fail (current_directory != NULL);
+  
+  current_dir = g_strdup (current_directory);
+
+  if(fs->prev_history)
+    {
+      if (strcmp((fs->prev_history)->data,current_dir))
+	{ /*if this item isn't on the top of the list */
+	  fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
+	}
+    } else {
+      fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
+    }
+  
+  gtk_combo_set_popdown_strings (GTK_COMBO (fs->history_combo),fs->prev_history);
+  
+  g_free (current_dir);
+}
+
+static void
+gtk_file_selection_file_button (GtkWidget *widget,
+			       gint row, 
+			       gint column, 
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+  
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = user_data;
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  gtk_clist_get_text (GTK_CLIST (fs->file_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  case GDK_2BUTTON_PRESS:
+	    gtk_button_clicked (GTK_BUTTON (fs->ok_button));
+	    break;
+	    
+	  default:
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+      
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_dir_button (GtkWidget *widget,
+			       gint row, 
+			       gint column, 
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GList *list;
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = GTK_FILE_SELECTION (user_data);
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  case GDK_2BUTTON_PRESS:
+	    list = fs->next_history;
+	    if (list)
+	      {
+		g_free (list->data);
+		list = list->next;
+	      }
+	    g_list_free (fs->next_history);
+	    fs->next_history = NULL;
+	
+	    gtk_file_selection_populate (fs, filename, FALSE);
+	    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
+	    g_free (fs->saved_entry);
+	    fs->saved_entry = NULL;
+	    break;
+	    
+	  default:
+	    /* here we need to add the "filename" to the beginning of what's already
+	       in the entry.  Save what's in the entry, then restore it on the double click
+	    */
+	    if (fs->saved_entry) g_free (fs->saved_entry);
+	    fs->saved_entry=g_strdup(gtk_entry_get_text(GTK_ENTRY (fs->selection_entry)));
+	
+	    temp=g_strconcat(filename,fs->saved_entry,NULL);
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), temp);
+	    g_free (temp);
+	
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+      
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_undir_button (GtkWidget *widget,
+			       gint row,
+			       gint column,
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = GTK_FILE_SELECTION (user_data);
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  default:
+	    /* here we need to add the "filename" to the beginning of what's already
+	       in the entry.  Save what's in the entry, then restore it on the double click
+	    */
+	    if (fs->saved_entry)
+	      {
+	        gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),fs->saved_entry);
+		g_free (fs->saved_entry);
+		fs->saved_entry = NULL;
+	      }
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename); //?????
+
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_populate (GtkFileSelection *fs,
+			     gchar            *rel_path,
+			     gint              try_complete)
+{
+  CompletionState *cmpl_state;
+  PossibleCompletion* poss;
+  gchar* filename;
+  gint row;
+  gchar* rem_path = rel_path;
+  gchar* sel_text;
+  gchar* text[2];
+  gint did_recurse = FALSE;
+  gint possible_count = 0;
+  gint selection_index = -1;
+  gint file_list_width;
+  gint dir_list_width;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
+
+  if (!cmpl_state_okay (cmpl_state))
+    {
+      /* Something went wrong. */
+      gtk_file_selection_abort (fs);
+      return;
+    }
+
+  g_assert (cmpl_state->reference_dir);
+
+  gtk_clist_freeze (GTK_CLIST (fs->dir_list));
+  gtk_clist_clear (GTK_CLIST (fs->dir_list));
+  gtk_clist_freeze (GTK_CLIST (fs->file_list));
+  gtk_clist_clear (GTK_CLIST (fs->file_list));
+
+  /* Set the dir_list to include ./ and ../ */
+  text[1] = NULL;
+  text[0] = "./";
+  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+
+  text[0] = "../";
+  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+
+  /*reset the max widths of the lists*/
+  dir_list_width = gdk_string_width(fs->dir_list->style->font,"../");
+  gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,dir_list_width);
+  file_list_width = 1;
+  gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,file_list_width);
+
+  while (poss)
+    {
+      if (cmpl_is_a_completion (poss))
+  	{
+	  possible_count += 1;
+	  
+	  filename = cmpl_this_completion (poss);
+
+	  text[0] = filename;
+	  
+	  if (cmpl_is_directory (poss))
+	    {
+	      if (strcmp (filename, "./") != 0 &&
+		  strcmp (filename, "../") != 0)
+		{
+		  int width = gdk_string_width(fs->dir_list->style->font,
+					       filename);
+		  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+		  if(width > dir_list_width)
+		    {
+		      dir_list_width = width;
+		      gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,
+						 width);
+		    }
+		}
+	    }
+	  else
+	    {
+	      if(fs->mask)
+		{
+		  if (gtk_file_selection_match_mask(filename,fs->mask))
+		    {
+		      int width = gdk_string_width(fs->file_list->style->font,
+						   filename);
+		      row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
+		      if(width > file_list_width)
+		        {
+		          file_list_width = width;
+		          gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
+						     width);
+		        }
+		    }
+		}
+	      else
+		{
+		  int width = gdk_string_width(fs->file_list->style->font,
+					       filename);
+		  row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
+		  if(width > file_list_width)
+		    {
+		      file_list_width = width;
+		      gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
+						 width);
+		    }
+		}
+	    }
+	}
+
+      poss = cmpl_next_completion (cmpl_state);
+    }
+
+  gtk_clist_thaw (GTK_CLIST (fs->dir_list));
+  gtk_clist_thaw (GTK_CLIST (fs->file_list));
+
+  /* File lists are set. */
+
+  g_assert (cmpl_state->reference_dir);
+
+  if (try_complete)
+    {
+
+      /* User is trying to complete filenames, so advance the user's input
+       * string to the updated_text, which is the common leading substring
+       * of all possible completions, and if its a directory attempt
+       * attempt completions in it. */
+
+      if (cmpl_updated_text (cmpl_state)[0])
+        {
+
+          if (cmpl_updated_dir (cmpl_state))
+            {
+	      gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
+
+              did_recurse = TRUE;
+
+              gtk_file_selection_populate (fs, dir_name, TRUE);
+
+              g_free (dir_name);
+            }
+          else
+            {
+	      if (fs->selection_entry)
+		      gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
+					  cmpl_updated_text (cmpl_state));
+            }
+        }
+      else
+        {
+          selection_index = cmpl_last_valid_char (cmpl_state) -
+                            (strlen (rel_path) - strlen (rem_path));
+	  if (fs->selection_entry)
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
+        }
+    }
+  else
+    {
+      if (fs->selection_entry)
+      /* Here we need to take the old filename and keep it!*/
+	/*gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");*/
+	;
+    }
+
+  if (!did_recurse)
+    {
+      if (fs->selection_entry)
+	gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
+
+      if (fs->selection_entry)
+	{
+	  sel_text = g_strconcat (_("Selection: "),
+				  cmpl_reference_position (cmpl_state),
+				  NULL);
+
+	  gtk_label_set_text (GTK_LABEL (fs->selection_text), sel_text);
+	  g_free (sel_text);
+	}
+
+  gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state));
+
+    }
+}
+
+static void
+gtk_file_selection_abort (GtkFileSelection *fs)
+{
+  gchar err_buf[256];
+
+  sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
+
+  /*  BEEP gdk_beep();  */
+
+  if (fs->selection_entry)
+    gtk_label_set_text (GTK_LABEL (fs->selection_text), err_buf);
+}
+
+/**********************************************************************/
+/*			  External Interface                          */
+/**********************************************************************/
+
+/* The four completion state selectors
+ */
+static gchar*
+cmpl_updated_text (CompletionState* cmpl_state)
+{
+  return cmpl_state->updated_text;
+}
+
+static gint
+cmpl_updated_dir (CompletionState* cmpl_state)
+{
+  return cmpl_state->re_complete;
+}
+
+static gchar*
+cmpl_reference_position (CompletionState* cmpl_state)
+{
+  return cmpl_state->reference_dir->fullname;
+}
+
+static gint
+cmpl_last_valid_char (CompletionState* cmpl_state)
+{
+  return cmpl_state->last_valid_char;
+}
+
+static gchar*
+cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state)
+{
+  static char nothing[2] = "";
+
+  if (!cmpl_state_okay (cmpl_state))
+    {
+      return nothing;
+    }
+  else if (text[0] == '/')
+    {
+      strcpy (cmpl_state->updated_text, text);
+    }
+  else if (text[0] == '~')
+    {
+      CompletionDir* dir;
+      char* slash;
+
+      dir = open_user_dir (text, cmpl_state);
+
+      if (!dir)
+	{
+	  /* spencer says just return ~something, so
+	   * for now just do it. */
+	  strcpy (cmpl_state->updated_text, text);
+	}
+      else
+	{
+
+	  strcpy (cmpl_state->updated_text, dir->fullname);
+
+	  slash = strchr (text, '/');
+
+	  if (slash)
+	    strcat (cmpl_state->updated_text, slash);
+	}
+    }
+  else
+    {
+      strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
+      if (strcmp (cmpl_state->reference_dir->fullname, "/") != 0)
+	strcat (cmpl_state->updated_text, "/");
+      strcat (cmpl_state->updated_text, text);
+    }
+
+  return cmpl_state->updated_text;
+}
+
+/* The three completion selectors
+ */
+static gchar*
+cmpl_this_completion (PossibleCompletion* pc)
+{
+  return pc->text;
+}
+
+static gint
+cmpl_is_directory (PossibleCompletion* pc)
+{
+  return pc->is_directory;
+}
+
+static gint
+cmpl_is_a_completion (PossibleCompletion* pc)
+{
+  return pc->is_a_completion;
+}
+
+/**********************************************************************/
+/*	                 Construction, deletion                       */
+/**********************************************************************/
+
+static CompletionState*
+cmpl_init_state (void)
+{
+  gchar getcwd_buf[2*MAXPATHLEN];
+  CompletionState *new_state;
+
+  new_state = g_new (CompletionState, 1);
+
+  /* We don't use getcwd() on SUNOS, because, it does a popen("pwd")
+   * and, if that wasn't bad enough, hangs in doing so.
+   */
+#if defined(sun) && !defined(__SVR4)
+  if (!getwd (getcwd_buf))
+#else    
+  if (!getcwd (getcwd_buf, MAXPATHLEN))
+#endif    
+    {
+      /* Oh joy, we can't get the current directory. Um..., we should have
+       * a root directory, right? Right? (Probably not portable to non-Unix)
+       */
+      strcpy (getcwd_buf, "/");
+    }
+
+tryagain:
+
+  new_state->reference_dir = NULL;
+  new_state->completion_dir = NULL;
+  new_state->active_completion_dir = NULL;
+  new_state->directory_storage = NULL;
+  new_state->directory_sent_storage = NULL;
+  new_state->last_valid_char = 0;
+  new_state->updated_text = g_new (gchar, MAXPATHLEN);
+  new_state->updated_text_alloc = MAXPATHLEN;
+  new_state->the_completion.text = g_new (gchar, MAXPATHLEN);
+  new_state->the_completion.text_alloc = MAXPATHLEN;
+  new_state->user_dir_name_buffer = NULL;
+  new_state->user_directories = NULL;
+
+  new_state->reference_dir =  open_dir (getcwd_buf, new_state);
+
+  if (!new_state->reference_dir)
+    {
+      /* Directories changing from underneath us, grumble */
+      strcpy (getcwd_buf, "/");
+      goto tryagain;
+    }
+
+  return new_state;
+}
+
+static void
+cmpl_free_dir_list(GList* dp0)
+{
+  GList *dp = dp0;
+
+  while (dp) {
+    free_dir (dp->data);
+    dp = dp->next;
+  }
+
+  g_list_free(dp0);
+}
+
+static void
+cmpl_free_dir_sent_list(GList* dp0)
+{
+  GList *dp = dp0;
+
+  while (dp) {
+    free_dir_sent (dp->data);
+    dp = dp->next;
+  }
+
+  g_list_free(dp0);
+}
+
+static void
+cmpl_free_state (CompletionState* cmpl_state)
+{
+  cmpl_free_dir_list (cmpl_state->directory_storage);
+  cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage);
+
+  if (cmpl_state->user_dir_name_buffer)
+    g_free (cmpl_state->user_dir_name_buffer);
+  if (cmpl_state->user_directories)
+    g_free (cmpl_state->user_directories);
+  if (cmpl_state->the_completion.text)
+    g_free (cmpl_state->the_completion.text);
+  if (cmpl_state->updated_text)
+    g_free (cmpl_state->updated_text);
+
+  g_free (cmpl_state);
+}
+
+static void
+free_dir(CompletionDir* dir)
+{
+  g_free(dir->fullname);
+  g_free(dir);
+}
+
+static void
+free_dir_sent(CompletionDirSent* sent)
+{
+  g_free(sent->name_buffer);
+  g_free(sent->entries);
+  g_free(sent);
+}
+
+static void
+prune_memory_usage(CompletionState *cmpl_state)
+{
+  GList* cdsl = cmpl_state->directory_sent_storage;
+  GList* cdl = cmpl_state->directory_storage;
+  GList* cdl0 = cdl;
+  gint len = 0;
+
+  for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1)
+    cdsl = cdsl->next;
+
+  if (cdsl) {
+    cmpl_free_dir_sent_list(cdsl->next);
+    cdsl->next = NULL;
+  }
+
+  cmpl_state->directory_storage = NULL;
+  while (cdl) {
+    if (cdl->data == cmpl_state->reference_dir)
+      cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data);
+    else
+      free_dir (cdl->data);
+    cdl = cdl->next;
+  }
+
+  g_list_free(cdl0);
+}
+
+/**********************************************************************/
+/*                        The main entrances.                         */
+/**********************************************************************/
+
+static PossibleCompletion*
+cmpl_completion_matches (gchar* text_to_complete,
+			 gchar** remaining_text,
+			 CompletionState* cmpl_state)
+{
+  gchar* first_slash;
+  PossibleCompletion *poss;
+
+  prune_memory_usage(cmpl_state);
+
+  g_assert (text_to_complete != NULL);
+
+  cmpl_state->user_completion_index = -1;
+  cmpl_state->last_completion_text = text_to_complete;
+  cmpl_state->the_completion.text[0] = 0;
+  cmpl_state->last_valid_char = 0;
+  cmpl_state->updated_text_len = -1;
+  cmpl_state->updated_text[0] = 0;
+  cmpl_state->re_complete = FALSE;
+
+  first_slash = strchr (text_to_complete, '/');
+
+  if (text_to_complete[0] == '~' && !first_slash)
+    {
+      /* Text starts with ~ and there is no slash, show all the
+       * home directory completions.
+       */
+      poss = attempt_homedir_completion (text_to_complete, cmpl_state);
+
+      update_cmpl(poss, cmpl_state);
+
+      return poss;
+    }
+
+  cmpl_state->reference_dir =
+    open_ref_dir (text_to_complete, remaining_text, cmpl_state);
+
+  if(!cmpl_state->reference_dir)
+    return NULL;
+
+  cmpl_state->completion_dir =
+    find_completion_dir (*remaining_text, remaining_text, cmpl_state);
+
+  cmpl_state->last_valid_char = *remaining_text - text_to_complete;
+
+  if(!cmpl_state->completion_dir)
+    return NULL;
+
+  cmpl_state->completion_dir->cmpl_index = -1;
+  cmpl_state->completion_dir->cmpl_parent = NULL;
+  cmpl_state->completion_dir->cmpl_text = *remaining_text;
+
+  cmpl_state->active_completion_dir = cmpl_state->completion_dir;
+
+  cmpl_state->reference_dir = cmpl_state->completion_dir;
+
+  poss = attempt_file_completion(cmpl_state);
+
+  update_cmpl(poss, cmpl_state);
+
+  return poss;
+}
+
+static PossibleCompletion*
+cmpl_next_completion (CompletionState* cmpl_state)
+{
+  PossibleCompletion* poss = NULL;
+
+  cmpl_state->the_completion.text[0] = 0;
+
+  if(cmpl_state->user_completion_index >= 0)
+    poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state);
+  else
+    poss = attempt_file_completion(cmpl_state);
+
+  update_cmpl(poss, cmpl_state);
+
+  return poss;
+}
+
+/**********************************************************************/
+/*			 Directory Operations                         */
+/**********************************************************************/
+
+/* Open the directory where completion will begin from, if possible. */
+static CompletionDir*
+open_ref_dir(gchar* text_to_complete,
+	     gchar** remaining_text,
+	     CompletionState* cmpl_state)
+{
+  gchar* first_slash;
+  CompletionDir *new_dir;
+
+  first_slash = strchr(text_to_complete, '/');
+
+  if (text_to_complete[0] == '~')
+    {
+      new_dir = open_user_dir(text_to_complete, cmpl_state);
+
+      if(new_dir)
+	{
+	  if(first_slash)
+	    *remaining_text = first_slash + 1;
+	  else
+	    *remaining_text = text_to_complete + strlen(text_to_complete);
+	}
+      else
+	{
+	  return NULL;
+	}
+    }
+  else if (text_to_complete[0] == '/' || !cmpl_state->reference_dir)
+    {
+      gchar *tmp = g_strdup(text_to_complete);
+      gchar *p;
+
+      p = tmp;
+      while (*p && *p != '*' && *p != '?')
+	p++;
+
+      *p = '\0';
+      p = strrchr(tmp, '/');
+      if (p)
+	{
+	  if (p == tmp)
+	    p++;
+      
+	  *p = '\0';
+
+	  new_dir = open_dir(tmp, cmpl_state);
+
+	  if(new_dir)
+	    *remaining_text = text_to_complete + 
+	      ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
+	}
+      else
+	{
+	  /* If no possible candidates, use the cwd */
+	  gchar *curdir = g_get_current_dir ();
+	  
+	  new_dir = open_dir(curdir, cmpl_state);
+
+	  if (new_dir)
+	    *remaining_text = text_to_complete;
+
+	  g_free (curdir);
+	}
+
+      g_free (tmp);
+    }
+  else
+    {
+      *remaining_text = text_to_complete;
+
+      new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state);
+    }
+
+  if(new_dir)
+    {
+      new_dir->cmpl_index = -1;
+      new_dir->cmpl_parent = NULL;
+    }
+
+  return new_dir;
+}
+
+/* open a directory by user name */
+static CompletionDir*
+open_user_dir(gchar* text_to_complete,
+	      CompletionState *cmpl_state)
+{
+  gchar *first_slash;
+  gint cmp_len;
+
+  g_assert(text_to_complete && text_to_complete[0] == '~');
+
+  first_slash = strchr(text_to_complete, '/');
+
+  if (first_slash)
+    cmp_len = first_slash - text_to_complete - 1;
+  else
+    cmp_len = strlen(text_to_complete + 1);
+
+  if(!cmp_len)
+    {
+      /* ~/ */
+      gchar *homedir = g_get_home_dir ();
+
+      if (homedir)
+	return open_dir(homedir, cmpl_state);
+      else
+	return NULL;
+    }
+  else
+    {
+      /* ~user/ */
+      char* copy = g_new(char, cmp_len + 1);
+      struct passwd *pwd;
+      strncpy(copy, text_to_complete + 1, cmp_len);
+      copy[cmp_len] = 0;
+      pwd = getpwnam(copy);
+      g_free(copy);
+      if (!pwd)
+	{
+	  cmpl_errno = errno;
+	  return NULL;
+	}
+
+      return open_dir(pwd->pw_dir, cmpl_state);
+    }
+}
+
+/* open a directory relative the the current relative directory */
+static CompletionDir*
+open_relative_dir(gchar* dir_name,
+		  CompletionDir* dir,
+		  CompletionState *cmpl_state)
+{
+  gchar path_buf[2*MAXPATHLEN];
+
+  if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN)
+    {
+      cmpl_errno = CMPL_ERRNO_TOO_LONG;
+      return NULL;
+    }
+
+  strcpy(path_buf, dir->fullname);
+
+  if(dir->fullname_len > 1)
+    {
+      path_buf[dir->fullname_len] = '/';
+      strcpy(path_buf + dir->fullname_len + 1, dir_name);
+    }
+  else
+    {
+      strcpy(path_buf + dir->fullname_len, dir_name);
+    }
+
+  return open_dir(path_buf, cmpl_state);
+}
+
+/* after the cache lookup fails, really open a new directory */
+static CompletionDirSent*
+open_new_dir(gchar* dir_name, struct stat* sbuf, gboolean stat_subdirs)
+{
+  CompletionDirSent* sent;
+  DIR* directory;
+  gchar *buffer_ptr;
+  struct dirent *dirent_ptr;
+  gint buffer_size = 0;
+  gint entry_count = 0;
+  gint i;
+  struct stat ent_sbuf;
+  char path_buf[MAXPATHLEN*2];
+  gint path_buf_len;
+
+  sent = g_new(CompletionDirSent, 1);
+  sent->mtime = sbuf->st_mtime;
+  sent->inode = sbuf->st_ino;
+  sent->device = sbuf->st_dev;
+
+  path_buf_len = strlen(dir_name);
+
+  if (path_buf_len > MAXPATHLEN)
+    {
+      cmpl_errno = CMPL_ERRNO_TOO_LONG;
+      return NULL;
+    }
+
+  strcpy(path_buf, dir_name);
+
+  directory = opendir(dir_name);
+
+  if(!directory)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  while((dirent_ptr = readdir(directory)) != NULL)
+    {
+      int entry_len = strlen(dirent_ptr->d_name);
+      buffer_size += entry_len + 1;
+      entry_count += 1;
+
+      if(path_buf_len + entry_len + 2 >= MAXPATHLEN)
+	{
+	  cmpl_errno = CMPL_ERRNO_TOO_LONG;
+ 	  closedir(directory);
+	  return NULL;
+	}
+    }
+
+  sent->name_buffer = g_new(gchar, buffer_size);
+  sent->entries = g_new(CompletionDirEntry, entry_count);
+  sent->entry_count = entry_count;
+
+  buffer_ptr = sent->name_buffer;
+
+  rewinddir(directory);
+
+  for(i = 0; i < entry_count; i += 1)
+    {
+      dirent_ptr = readdir(directory);
+
+      if(!dirent_ptr)
+	{
+	  cmpl_errno = errno;
+	  closedir(directory);
+	  return NULL;
+	}
+
+      strcpy(buffer_ptr, dirent_ptr->d_name);
+      sent->entries[i].entry_name = buffer_ptr;
+      buffer_ptr += strlen(dirent_ptr->d_name);
+      *buffer_ptr = 0;
+      buffer_ptr += 1;
+
+      path_buf[path_buf_len] = '/';
+      strcpy(path_buf + path_buf_len + 1, dirent_ptr->d_name);
+
+      if (stat_subdirs)
+	{
+	  if(stat(path_buf, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
+	    sent->entries[i].is_dir = 1;
+	  else
+	    /* stat may fail, and we don't mind, since it could be a
+	     * dangling symlink. */
+	    sent->entries[i].is_dir = 0;
+	}
+      else
+	sent->entries[i].is_dir = 1;
+    }
+
+  qsort(sent->entries, sent->entry_count, sizeof(CompletionDirEntry), compare_cmpl_dir);
+
+  closedir(directory);
+
+  return sent;
+}
+
+static gboolean
+check_dir(gchar *dir_name, struct stat *result, gboolean *stat_subdirs)
+{
+  /* A list of directories that we know only contain other directories.
+   * Trying to stat every file in these directories would be very
+   * expensive.
+   */
+
+  static struct {
+    gchar *name;
+    gboolean present;
+    struct stat statbuf;
+  } no_stat_dirs[] = {
+    { "/afs", FALSE, { 0 } },
+    { "/net", FALSE, { 0 } }
+  };
+
+  static const gint n_no_stat_dirs = sizeof(no_stat_dirs) / sizeof(no_stat_dirs[0]);
+  static gboolean initialized = FALSE;
+
+  gint i;
+
+  if (!initialized)
+    {
+      initialized = TRUE;
+      for (i = 0; i < n_no_stat_dirs; i++)
+	{
+	  if (stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
+	    no_stat_dirs[i].present = TRUE;
+	}
+    }
+
+  if(stat(dir_name, result) < 0)
+    {
+      cmpl_errno = errno;
+      return FALSE;
+    }
+
+  *stat_subdirs = TRUE;
+  for (i=0; i<n_no_stat_dirs; i++)
+    {
+      if (no_stat_dirs[i].present &&
+	  (no_stat_dirs[i].statbuf.st_dev == result->st_dev) &&
+	  (no_stat_dirs[i].statbuf.st_ino == result->st_ino))
+	{
+	  *stat_subdirs = FALSE;
+	  break;
+	}
+    }
+
+  return TRUE;
+}
+
+/* open a directory by absolute pathname */
+static CompletionDir*
+open_dir(gchar* dir_name, CompletionState* cmpl_state)
+{
+  struct stat sbuf;
+  gboolean stat_subdirs;
+  CompletionDirSent *sent;
+  GList* cdsl;
+
+  if (!check_dir (dir_name, &sbuf, &stat_subdirs))
+    return NULL;
+
+  cdsl = cmpl_state->directory_sent_storage;
+
+  while (cdsl)
+    {
+      sent = cdsl->data;
+
+      if(sent->inode == sbuf.st_ino &&
+	 sent->mtime == sbuf.st_mtime &&
+	 sent->device == sbuf.st_dev)
+	return attach_dir(sent, dir_name, cmpl_state);
+
+      cdsl = cdsl->next;
+    }
+
+  sent = open_new_dir(dir_name, &sbuf, stat_subdirs);
+
+  if (sent) {
+    cmpl_state->directory_sent_storage =
+      g_list_prepend(cmpl_state->directory_sent_storage, sent);
+
+    return attach_dir(sent, dir_name, cmpl_state);
+  }
+
+  return NULL;
+}
+
+static CompletionDir*
+attach_dir(CompletionDirSent* sent, gchar* dir_name, CompletionState *cmpl_state)
+{
+  CompletionDir* new_dir;
+
+  new_dir = g_new(CompletionDir, 1);
+
+  cmpl_state->directory_storage =
+    g_list_prepend(cmpl_state->directory_storage, new_dir);
+
+  new_dir->sent = sent;
+  new_dir->fullname = g_strdup(dir_name);
+  new_dir->fullname_len = strlen(dir_name);
+
+  return new_dir;
+}
+
+static gint
+correct_dir_fullname(CompletionDir* cmpl_dir)
+{
+  gint length = strlen(cmpl_dir->fullname);
+  struct stat sbuf;
+
+  if (strcmp(cmpl_dir->fullname + length - 2, "/.") == 0)
+    {
+      if (length == 2) 
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	} else {
+	  cmpl_dir->fullname[length - 2] = 0;
+	}
+    }
+  else if (strcmp(cmpl_dir->fullname + length - 3, "/./") == 0)
+    cmpl_dir->fullname[length - 2] = 0;
+  else if (strcmp(cmpl_dir->fullname + length - 3, "/..") == 0)
+    {
+      if(length == 3)
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	}
+
+      if(stat(cmpl_dir->fullname, &sbuf) < 0)
+	{
+	  cmpl_errno = errno;
+	  return FALSE;
+	}
+
+      cmpl_dir->fullname[length - 2] = 0;
+
+      if(!correct_parent(cmpl_dir, &sbuf))
+	return FALSE;
+    }
+  else if (strcmp(cmpl_dir->fullname + length - 4, "/../") == 0)
+    {
+      if(length == 4)
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	}
+
+      if(stat(cmpl_dir->fullname, &sbuf) < 0)
+	{
+	  cmpl_errno = errno;
+	  return FALSE;
+	}
+
+      cmpl_dir->fullname[length - 3] = 0;
+
+      if(!correct_parent(cmpl_dir, &sbuf))
+	return FALSE;
+    }
+
+  cmpl_dir->fullname_len = strlen(cmpl_dir->fullname);
+
+  return TRUE;
+}
+
+static gint
+correct_parent(CompletionDir* cmpl_dir, struct stat *sbuf)
+{
+  struct stat parbuf;
+  gchar *last_slash;
+  gchar *new_name;
+  gchar c = 0;
+
+  last_slash = strrchr(cmpl_dir->fullname, '/');
+
+  g_assert(last_slash);
+
+  if(last_slash != cmpl_dir->fullname)
+    { /* last_slash[0] = 0; */ }
+  else
+    {
+      c = last_slash[1];
+      last_slash[1] = 0;
+    }
+
+  if (stat(cmpl_dir->fullname, &parbuf) < 0)
+    {
+      cmpl_errno = errno;
+      return FALSE;
+    }
+
+  if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
+    /* it wasn't a link */
+    return TRUE;
+
+  if(c)
+    last_slash[1] = c;
+  /* else
+    last_slash[0] = '/'; */
+
+  /* it was a link, have to figure it out the hard way */
+
+  new_name = find_parent_dir_fullname(cmpl_dir->fullname);
+
+  if (!new_name)
+    return FALSE;
+
+  g_free(cmpl_dir->fullname);
+
+  cmpl_dir->fullname = new_name;
+
+  return TRUE;
+}
+
+static gchar*
+find_parent_dir_fullname(gchar* dirname)
+{
+  gchar buffer[MAXPATHLEN];
+  gchar buffer2[MAXPATHLEN];
+
+#if defined(sun) && !defined(__SVR4)
+  if(!getwd(buffer))
+#else
+  if(!getcwd(buffer, MAXPATHLEN))
+#endif    
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  if(chdir(dirname) != 0 || chdir("..") != 0)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+#if defined(sun) && !defined(__SVR4)
+  if(!getwd(buffer2))
+#else
+  if(!getcwd(buffer2, MAXPATHLEN))
+#endif
+    {
+      chdir(buffer);
+      cmpl_errno = errno;
+
+      return NULL;
+    }
+
+  if(chdir(buffer) != 0)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  return g_strdup(buffer2);
+}
+
+/**********************************************************************/
+/*                        Completion Operations                       */
+/**********************************************************************/
+
+static PossibleCompletion*
+attempt_homedir_completion(gchar* text_to_complete,
+			   CompletionState *cmpl_state)
+{
+  gint index, length;
+
+  if (!cmpl_state->user_dir_name_buffer &&
+      !get_pwdb(cmpl_state))
+    return NULL;
+  length = strlen(text_to_complete) - 1;
+
+  cmpl_state->user_completion_index += 1;
+
+  while(cmpl_state->user_completion_index < cmpl_state->user_directories_len)
+    {
+      index = first_diff_index(text_to_complete + 1,
+			       cmpl_state->user_directories
+			       [cmpl_state->user_completion_index].login);
+
+      switch(index)
+	{
+	case PATTERN_MATCH:
+	  break;
+	default:
+	  if(cmpl_state->last_valid_char < (index + 1))
+	    cmpl_state->last_valid_char = index + 1;
+	  cmpl_state->user_completion_index += 1;
+	  continue;
+	}
+
+      cmpl_state->the_completion.is_a_completion = 1;
+      cmpl_state->the_completion.is_directory = 1;
+
+      append_completion_text("~", cmpl_state);
+
+      append_completion_text(cmpl_state->
+			      user_directories[cmpl_state->user_completion_index].login,
+			     cmpl_state);
+
+      return append_completion_text("/", cmpl_state);
+    }
+
+  if(text_to_complete[1] ||
+     cmpl_state->user_completion_index > cmpl_state->user_directories_len)
+    {
+      cmpl_state->user_completion_index = -1;
+      return NULL;
+    }
+  else
+    {
+      cmpl_state->user_completion_index += 1;
+      cmpl_state->the_completion.is_a_completion = 1;
+      cmpl_state->the_completion.is_directory = 1;
+
+      return append_completion_text("~/", cmpl_state);
+    }
+}
+
+/* returns the index (>= 0) of the first differing character,
+ * PATTERN_MATCH if the completion matches */
+static gint
+first_diff_index(gchar* pat, gchar* text)
+{
+  gint diff = 0;
+
+  while(*pat && *text && *text == *pat)
+    {
+      pat += 1;
+      text += 1;
+      diff += 1;
+    }
+
+  if(*pat)
+    return diff;
+
+  return PATTERN_MATCH;
+}
+
+static PossibleCompletion*
+append_completion_text(gchar* text, CompletionState* cmpl_state)
+{
+  gint len, i = 1;
+
+  if(!cmpl_state->the_completion.text)
+    return NULL;
+
+  len = strlen(text) + strlen(cmpl_state->the_completion.text) + 1;
+
+  if(cmpl_state->the_completion.text_alloc > len)
+    {
+      strcat(cmpl_state->the_completion.text, text);
+      return &cmpl_state->the_completion;
+    }
+
+  while(i < len) { i <<= 1; }
+
+  cmpl_state->the_completion.text_alloc = i;
+
+  cmpl_state->the_completion.text = (gchar*)g_realloc(cmpl_state->the_completion.text, i);
+
+  if(!cmpl_state->the_completion.text)
+    return NULL;
+  else
+    {
+      strcat(cmpl_state->the_completion.text, text);
+      return &cmpl_state->the_completion;
+    }
+}
+
+static CompletionDir*
+find_completion_dir(gchar* text_to_complete,
+		    gchar** remaining_text,
+		    CompletionState* cmpl_state)
+{
+  gchar* first_slash = strchr(text_to_complete, '/');
+  CompletionDir* dir = cmpl_state->reference_dir;
+  CompletionDir* next;
+  *remaining_text = text_to_complete;
+
+  while(first_slash)
+    {
+      gint len = first_slash - *remaining_text;
+      gint found = 0;
+      gchar *found_name = NULL;         /* Quiet gcc */
+      gint i;
+      gchar* pat_buf = g_new (gchar, len + 1);
+
+      strncpy(pat_buf, *remaining_text, len);
+      pat_buf[len] = 0;
+
+      for(i = 0; i < dir->sent->entry_count; i += 1)
+	{
+	  if(dir->sent->entries[i].is_dir &&
+	     fnmatch(pat_buf, dir->sent->entries[i].entry_name,
+		     FNMATCH_FLAGS)!= FNM_NOMATCH)
+	    {
+	      if(found)
+		{
+		  g_free (pat_buf);
+		  return dir;
+		}
+	      else
+		{
+		  found = 1;
+		  found_name = dir->sent->entries[i].entry_name;
+		}
+	    }
+	}
+
+      if (!found)
+	{
+	  /* Perhaps we are trying to open an automount directory */
+	  found_name = pat_buf;
+	}
+
+      next = open_relative_dir(found_name, dir, cmpl_state);
+      
+      if(!next)
+	{
+	  g_free (pat_buf);
+	  return NULL;
+	}
+      
+      next->cmpl_parent = dir;
+      
+      dir = next;
+      
+      if(!correct_dir_fullname(dir))
+	{
+	  g_free(pat_buf);
+	  return NULL;
+	}
+      
+      *remaining_text = first_slash + 1;
+      first_slash = strchr(*remaining_text, '/');
+
+      g_free (pat_buf);
+    }
+
+  return dir;
+}
+
+static void
+update_cmpl(PossibleCompletion* poss, CompletionState* cmpl_state)
+{
+  gint cmpl_len;
+
+  if(!poss || !cmpl_is_a_completion(poss))
+    return;
+
+  cmpl_len = strlen(cmpl_this_completion(poss));
+
+  if(cmpl_state->updated_text_alloc < cmpl_len + 1)
+    {
+      cmpl_state->updated_text =
+	(gchar*)g_realloc(cmpl_state->updated_text,
+			  cmpl_state->updated_text_alloc);
+      cmpl_state->updated_text_alloc = 2*cmpl_len;
+    }
+
+  if(cmpl_state->updated_text_len < 0)
+    {
+      strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+      cmpl_state->updated_text_len = cmpl_len;
+      cmpl_state->re_complete = cmpl_is_directory(poss);
+    }
+  else if(cmpl_state->updated_text_len == 0)
+    {
+      cmpl_state->re_complete = FALSE;
+    }
+  else
+    {
+      gint first_diff =
+	first_diff_index(cmpl_state->updated_text,
+			 cmpl_this_completion(poss));
+
+      cmpl_state->re_complete = FALSE;
+
+      if(first_diff == PATTERN_MATCH)
+	return;
+
+      if(first_diff > cmpl_state->updated_text_len)
+	strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+
+      cmpl_state->updated_text_len = first_diff;
+      cmpl_state->updated_text[first_diff] = 0;
+    }
+}
+
+static PossibleCompletion*
+attempt_file_completion(CompletionState *cmpl_state)
+{
+  gchar *pat_buf, *first_slash;
+  CompletionDir *dir = cmpl_state->active_completion_dir;
+
+  dir->cmpl_index += 1;
+
+  if(dir->cmpl_index == dir->sent->entry_count)
+    {
+      if(dir->cmpl_parent == NULL)
+	{
+	  cmpl_state->active_completion_dir = NULL;
+
+	  return NULL;
+	}
+      else
+	{
+	  cmpl_state->active_completion_dir = dir->cmpl_parent;
+
+	  return attempt_file_completion(cmpl_state);
+	}
+    }
+
+  g_assert(dir->cmpl_text);
+
+  first_slash = strchr(dir->cmpl_text, '/');
+
+  if(first_slash)
+    {
+      gint len = first_slash - dir->cmpl_text;
+
+      pat_buf = g_new (gchar, len + 1);
+      strncpy(pat_buf, dir->cmpl_text, len);
+      pat_buf[len] = 0;
+    }
+  else
+    {
+      gint len = strlen(dir->cmpl_text);
+
+      pat_buf = g_new (gchar, len + 2);
+      strcpy(pat_buf, dir->cmpl_text);
+      strcpy(pat_buf + len, "*");
+    }
+
+  if(first_slash)
+    {
+      if(dir->sent->entries[dir->cmpl_index].is_dir)
+	{
+	  if(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+		     FNMATCH_FLAGS) != FNM_NOMATCH)
+	    {
+	      CompletionDir* new_dir;
+
+	      new_dir = open_relative_dir(dir->sent->entries[dir->cmpl_index].entry_name,
+					  dir, cmpl_state);
+
+	      if(!new_dir)
+		{
+		  g_free (pat_buf);
+		  return NULL;
+		}
+
+	      new_dir->cmpl_parent = dir;
+
+	      new_dir->cmpl_index = -1;
+	      new_dir->cmpl_text = first_slash + 1;
+
+	      cmpl_state->active_completion_dir = new_dir;
+
+	      g_free (pat_buf);
+	      return attempt_file_completion(cmpl_state);
+	    }
+	  else
+	    {
+	      g_free (pat_buf);
+	      return attempt_file_completion(cmpl_state);
+	    }
+	}
+      else
+	{
+	  g_free (pat_buf);
+	  return attempt_file_completion(cmpl_state);
+	}
+    }
+  else
+    {
+      if(dir->cmpl_parent != NULL)
+	{
+	  append_completion_text(dir->fullname +
+				 strlen(cmpl_state->completion_dir->fullname) + 1,
+				 cmpl_state);
+	  append_completion_text("/", cmpl_state);
+	}
+
+      append_completion_text(dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
+
+      cmpl_state->the_completion.is_a_completion =
+	(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+		 FNMATCH_FLAGS) != FNM_NOMATCH);
+
+      cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
+      if(dir->sent->entries[dir->cmpl_index].is_dir)
+	append_completion_text("/", cmpl_state);
+
+      g_free (pat_buf);
+      return &cmpl_state->the_completion;
+    }
+}
+
+
+static gint
+get_pwdb(CompletionState* cmpl_state)
+{
+  struct passwd *pwd_ptr;
+  gchar* buf_ptr;
+  gint len = 0, i, count = 0;
+
+  if(cmpl_state->user_dir_name_buffer)
+    return TRUE;
+  setpwent ();
+
+  while ((pwd_ptr = getpwent()) != NULL)
+    {
+      len += strlen(pwd_ptr->pw_name);
+      len += strlen(pwd_ptr->pw_dir);
+      len += 2;
+      count += 1;
+    }
+
+  setpwent ();
+
+  cmpl_state->user_dir_name_buffer = g_new(gchar, len);
+  cmpl_state->user_directories = g_new(CompletionUserDir, count);
+  cmpl_state->user_directories_len = count;
+
+  buf_ptr = cmpl_state->user_dir_name_buffer;
+
+  for(i = 0; i < count; i += 1)
+    {
+      pwd_ptr = getpwent();
+      if(!pwd_ptr)
+	{
+	  cmpl_errno = errno;
+	  goto error;
+	}
+
+      strcpy(buf_ptr, pwd_ptr->pw_name);
+      cmpl_state->user_directories[i].login = buf_ptr;
+      buf_ptr += strlen(buf_ptr);
+      buf_ptr += 1;
+      strcpy(buf_ptr, pwd_ptr->pw_dir);
+      cmpl_state->user_directories[i].homedir = buf_ptr;
+      buf_ptr += strlen(buf_ptr);
+      buf_ptr += 1;
+    }
+
+  qsort(cmpl_state->user_directories,
+	cmpl_state->user_directories_len,
+	sizeof(CompletionUserDir),
+	compare_user_dir);
+
+  endpwent();
+
+  return TRUE;
+
+error:
+
+  if(cmpl_state->user_dir_name_buffer)
+    g_free(cmpl_state->user_dir_name_buffer);
+  if(cmpl_state->user_directories)
+    g_free(cmpl_state->user_directories);
+
+  cmpl_state->user_dir_name_buffer = NULL;
+  cmpl_state->user_directories = NULL;
+
+  return FALSE;
+}
+
+static gint
+compare_user_dir(const void* a, const void* b)
+{
+  return strcmp((((CompletionUserDir*)a))->login,
+		(((CompletionUserDir*)b))->login);
+}
+
+static gint
+compare_cmpl_dir(const void* a, const void* b)
+{
+  return strcmp((((CompletionDirEntry*)a))->entry_name,
+		(((CompletionDirEntry*)b))->entry_name);
+}
+
+static gint
+cmpl_state_okay(CompletionState* cmpl_state)
+{
+  return  cmpl_state && cmpl_state->reference_dir;
+}
+
+static gchar*
+cmpl_strerror(gint err)
+{
+  if(err == CMPL_ERRNO_TOO_LONG)
+    return "Name too long";
+  else
+    return g_strerror (err);
+}
+
+
+/* Testing area */
+#ifdef TORRIE_DEBUG
+
+/* Get the selected filename and print it to the console */
+void file_ok_sel( GtkWidget        *w,
+                  GtkFileSelection *fs )
+{
+    g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
+}
+
+void destroy( GtkWidget *widget,
+              gpointer   data )
+{
+    gtk_main_quit ();
+}
+
+int main( int   argc,
+          char *argv[] )
+{
+    GtkWidget *filew;
+
+    gtk_init (&argc, &argv);
+
+    /* Create a new file selection widget */
+    filew = gtk_file_selection_new ("Michael's Glorious File Selector");
+//    gtk_file_selection_complete(GTK_FILE_SELECTION(filew),"bob");
+
+		
+    gtk_signal_connect (GTK_OBJECT (filew), "destroy",
+			(GtkSignalFunc) destroy, &filew);
+    /* Connect the ok_button to file_ok_sel function */
+    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
+			"clicked", (GtkSignalFunc) file_ok_sel, filew );
+
+    /* Connect the cancel_button to destroy the widget */
+    gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
+                                            (filew)->cancel_button),
+			       "clicked", (GtkSignalFunc) gtk_widget_destroy,
+			       GTK_OBJECT (filew));
+
+
+    gtk_widget_show(filew);
+
+/*
+    g_print("%d",gtk_file_selection_match_mask("mask.c","m*.c"));
+    g_print("%d",gtk_file_selection_match_mask("mask.c","m???.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.c","m??*.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c???"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c*"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","n*.c???"));
+		g_print("%d",gtk_file_selection_match_mask("mask.c","[mn]*"));
+		g_print("%d",gtk_file_selection_match_mask("COPYING","*.xpm"));
+*/	
+    gtk_main ();
+
+    return 0;
+}
+
+/* example-end */
+#endif
diff --git a/radiant/gtkfilesel-darwin.h b/radiant/gtkfilesel-darwin.h
index e264e1b2..135a1fa5 100644
--- a/radiant/gtkfilesel-darwin.h
+++ b/radiant/gtkfilesel-darwin.h
@@ -1,129 +1,129 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GTK_FILESEL_H__
-#define __GTK_FILESEL_H__
-
-
-#include <gdk/gdk.h>
-#include <gtk/gtkwindow.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define GTK_TYPE_FILE_SELECTION            (gtk_file_selection_get_type ())
-#define GTK_FILE_SELECTION(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_FILE_SELECTION, GtkFileSelection))
-#define GTK_FILE_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
-#define GTK_IS_FILE_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
-#define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
-
-
-typedef struct _GtkFileSelection       GtkFileSelection;
-typedef struct _GtkFileSelectionClass  GtkFileSelectionClass;
-
-struct _GtkFileSelection
-{
-  GtkWindow window;
-
-  GtkWidget *dir_list;
-  GtkWidget *file_list;
-  GtkWidget *selection_entry;
-  GtkWidget *selection_text;
-  GtkWidget *main_vbox;
-  GtkWidget *ok_button;
-  GtkWidget *cancel_button;
-  GtkWidget *help_button;
-
-  /* These are not used.  Just fillers in the class structure */
-  GtkWidget *history_pulldown;
-  GtkWidget *history_menu;
-  GList     *history_list;
-  /* ***************** */
-	
-  GtkWidget *fileop_dialog;
-  GtkWidget *fileop_entry;
-  gchar     *fileop_file;
-  gpointer   cmpl_state;
-  
-  GtkWidget *fileop_c_dir;
-  GtkWidget *fileop_del_file;
-  GtkWidget *fileop_ren_file;
-  
-  GtkWidget *button_area;
-  GtkWidget *action_area;
-
-  GtkWidget *history_combo;
-  GList     *prev_history;
-  GList     *next_history;
-  GtkWidget *mask_entry;
-  gchar     *mask;
-  gchar     *saved_entry;
-
-  GList     *masks;
-
-};
-
-struct _GtkFileSelectionClass
-{
-  GtkWindowClass parent_class;
-};
-
-
-GtkType    gtk_file_selection_get_type            (void);
-GtkWidget* gtk_file_selection_new                 (const gchar      *title);
-void       gtk_file_selection_set_filename        (GtkFileSelection *filesel,
-						   const gchar      *filename);
-gchar*     gtk_file_selection_get_filename        (GtkFileSelection *filesel);
-void	   gtk_file_selection_complete		  (GtkFileSelection *filesel,
-						   const gchar	    *pattern);
-void       gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
-void       gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
-
-/* proposed interface */
-void       gtk_file_selection_clear_masks         (GtkFileSelection *filesel);
-void       gtk_file_selection_set_masks           (GtkFileSelection *filesel,
-                                                   const gchar      **masks);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* __GTK_FILESEL_H__ */
-
-
-
-
-
-
-
-
-
-
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_FILESEL_H__
+#define __GTK_FILESEL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwindow.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TYPE_FILE_SELECTION            (gtk_file_selection_get_type ())
+#define GTK_FILE_SELECTION(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_FILE_SELECTION, GtkFileSelection))
+#define GTK_FILE_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
+#define GTK_IS_FILE_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
+#define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
+
+
+typedef struct _GtkFileSelection       GtkFileSelection;
+typedef struct _GtkFileSelectionClass  GtkFileSelectionClass;
+
+struct _GtkFileSelection
+{
+  GtkWindow window;
+
+  GtkWidget *dir_list;
+  GtkWidget *file_list;
+  GtkWidget *selection_entry;
+  GtkWidget *selection_text;
+  GtkWidget *main_vbox;
+  GtkWidget *ok_button;
+  GtkWidget *cancel_button;
+  GtkWidget *help_button;
+
+  /* These are not used.  Just fillers in the class structure */
+  GtkWidget *history_pulldown;
+  GtkWidget *history_menu;
+  GList     *history_list;
+  /* ***************** */
+	
+  GtkWidget *fileop_dialog;
+  GtkWidget *fileop_entry;
+  gchar     *fileop_file;
+  gpointer   cmpl_state;
+  
+  GtkWidget *fileop_c_dir;
+  GtkWidget *fileop_del_file;
+  GtkWidget *fileop_ren_file;
+  
+  GtkWidget *button_area;
+  GtkWidget *action_area;
+
+  GtkWidget *history_combo;
+  GList     *prev_history;
+  GList     *next_history;
+  GtkWidget *mask_entry;
+  gchar     *mask;
+  gchar     *saved_entry;
+
+  GList     *masks;
+
+};
+
+struct _GtkFileSelectionClass
+{
+  GtkWindowClass parent_class;
+};
+
+
+GtkType    gtk_file_selection_get_type            (void);
+GtkWidget* gtk_file_selection_new                 (const gchar      *title);
+void       gtk_file_selection_set_filename        (GtkFileSelection *filesel,
+						   const gchar      *filename);
+gchar*     gtk_file_selection_get_filename        (GtkFileSelection *filesel);
+void	   gtk_file_selection_complete		  (GtkFileSelection *filesel,
+						   const gchar	    *pattern);
+void       gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
+void       gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
+
+/* proposed interface */
+void       gtk_file_selection_clear_masks         (GtkFileSelection *filesel);
+void       gtk_file_selection_set_masks           (GtkFileSelection *filesel,
+                                                   const gchar      **masks);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_FILESEL_H__ */
+
+
+
+
+
+
+
+
+
+
diff --git a/radiant/gtkfilesel-linux.c b/radiant/gtkfilesel-linux.c
index 58af1801..16fe0b56 100644
--- a/radiant/gtkfilesel-linux.c
+++ b/radiant/gtkfilesel-linux.c
@@ -1,4987 +1,4987 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-#define LEO
-
-#ifdef LEO
-#define _(a) a
-
-static char * back_xpm[] = {
-"14 14 33 1",
-" 	c None",
-".	c #000000",
-"+	c #C6D7C6",
-"@	c #E7EBE7",
-"#	c #FFFFFF",
-"$	c #DEEBDE",
-"%	c #F7F7F7",
-"&	c #DEE7DE",
-"*	c #EFF3EF",
-"=	c #101810",
-"-	c #B5C7AD",
-";	c #EFEFEF",
-">	c #D6E3D6",
-",	c #213021",
-"'	c #315931",
-")	c #52824A",
-"!	c #739A6B",
-"~	c #84A673",
-"{	c #7BA673",
-"]	c #84AA73",
-"^	c #84AA7B",
-"/	c #84AE7B",
-"(	c #63925A",
-"_	c #526D4A",
-":	c #4A7D42",
-"<	c #739E6B",
-"[	c #739A63",
-"}	c #4A7539",
-"|	c #638E52",
-"1	c #427139",
-"2	c #6BA663",
-"3	c #5A8A52",
-"4	c #315929",
-"            ..",
-"          ..+.",
-"        ..@#+.",
-"      ..$#%%+.",
-"    ..&#%*%%+.",
-"  .=&#******+.",
-"..-#;>&@****+,",
-"..')!~{]^/^/(.",
-"  .._:<^~^/^(.",
-"    ..':[]~/(.",
-"      ..}:[~|.",
-"        ..123.",
-"          ..4.",
-"            .."};
-
-static char * up_xpm[] = {
-"14 14 36 1",
-" 	c None",
-".	c #000000",
-"+	c #181C18",
-"@	c #D6DBD6",
-"#	c #94AA8C",
-"$	c #000400",
-"%	c #DEDFDE",
-"&	c #94AA84",
-"*	c #E7E3E7",
-"=	c #94B28C",
-"-	c #6B865A",
-";	c #EFEBEF",
-">	c #9CB694",
-",	c #8CA684",
-"'	c #EFEFEF",
-")	c #F7EFF7",
-"!	c #9CB68C",
-"~	c #63865A",
-"{	c #94B684",
-"]	c #94AE84",
-"^	c #739263",
-"/	c #F7F3F7",
-"(	c #94B284",
-"_	c #849E73",
-":	c #8CAE7B",
-"<	c #8CAA84",
-"[	c #7B966B",
-"}	c #8CA67B",
-"|	c #DEDBD6",
-"1	c #E7E7E7",
-"2	c #8CAE84",
-"3	c #8CAA7B",
-"4	c #738E63",
-"5	c #BDBEB5",
-"6	c #BDC3BD",
-"7	c #637D52",
-"      ..      ",
-"      ..      ",
-"     +@#$     ",
-"     .%&.     ",
-"    .**=-.    ",
-"    .;;>,.    ",
-"   .*')!&~.   ",
-"   .;)){]^.   ",
-"  .*')/(]_-.  ",
-"  .;)//::<[.  ",
-" .*')//:::}-. ",
-" .|1;;12]3}4. ",
-".556666^^^^-7.",
-".............."};
-
-static char * forward_xpm[] = {
-"14 14 36 1",
-" 	c None",
-".	c #000000",
-"+	c #E7EBDE",
-"@	c #FFFFFF",
-"#	c #F7F7EF",
-"$	c #D6E3D6",
-"%	c #F7F7F7",
-"&	c #EFF3EF",
-"*	c #CEDFCE",
-"=	c #CEDBC6",
-"-	c #E7EFE7",
-";	c #181818",
-">	c #292829",
-",	c #E7EBE7",
-"'	c #DEE7DE",
-")	c #B5C7AD",
-"!	c #9CBA94",
-"~	c #8CAE84",
-"{	c #84AA7B",
-"]	c #7BA673",
-"^	c #84A67B",
-"/	c #739A6B",
-"(	c #5A824A",
-"_	c #395931",
-":	c #9CBA8C",
-"<	c #84AE7B",
-"[	c #739E6B",
-"}	c #527D4A",
-"|	c #425942",
-"1	c #84A673",
-"2	c #4A7142",
-"3	c #94B284",
-"4	c #395D31",
-"5	c #5A8652",
-"6	c #315929",
-"7	c #396531",
-"..            ",
-".+..          ",
-".@#$..        ",
-".@%&#*..      ",
-".@%%&&%=..    ",
-".@&&&&&-#=;.  ",
-">@&&&&,'$'&)..",
-".!~{~{{]^/(_..",
-".:{<{^{[}|..  ",
-".:<1{/}2..    ",
-".31/}4..      ",
-".{56..        ",
-".7..          ",
-"..            "};
-
-static char * refresh_xpm[] = {
-"16 16 11 1",
-" 	c None",
-".	c #000000",
-"+	c #526942",
-"@	c #4A6139",
-"#	c #526542",
-"$	c #5A7142",
-"%	c #425531",
-"&	c #314529",
-"*	c #425131",
-"=	c #425931",
-"-	c #5A754A",
-"       .        ",
-"      ..        ",
-"     .+@...     ",
-"    .#$##@%..   ",
-"     .+#...%%.  ",
-"   .  ..   .&.  ",
-"  .    .    .&. ",
-" ..          .. ",
-" ..          .. ",
-" .*.    .    .  ",
-"  .*.   ..  .   ",
-"  .%@...#=.     ",
-"   ..##-#@#.    ",
-"     ...@%.     ",
-"        ..      ",
-"        .       "};
-
-#endif
-
-#ifndef LEO
-#include "config.h"
-#endif
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <pwd.h>
-#include <grp.h>
-#include <time.h>
-
-#include "fnmatch.h"
-
-#if (defined TORRIE_DEBUG || defined LEO)
-#include <gdk/gdkkeysyms.h>
-#include <gtk/gtkbutton.h>
-#include <gtk/gtkentry.h>
-#include "gtkfilesel-linux.h"
-#include <gtk/gtkhbox.h>
-#include <gtk/gtkhbbox.h>
-#include <gtk/gtklabel.h>
-#include <gtk/gtklist.h>
-#include <gtk/gtklistitem.h>
-#include <gtk/gtkmain.h>
-#include <gtk/gtkscrolledwindow.h>
-#include <gtk/gtksignal.h>
-#include <gtk/gtkvbox.h>
-#include <gtk/gtkmenu.h>
-#include <gtk/gtkmenuitem.h>
-#include <gtk/gtkoptionmenu.h>
-#include <gtk/gtkclist.h>
-#include <gtk/gtkdialog.h>
-#include <gtk/gtkcombo.h>
-#include <gtk/gtkframe.h>
-#include <gtk/gtkhpaned.h>
-#include <gtk/gtktable.h>
-#include <gtk/gtkpixmap.h>
-#include <gtk/gtknotebook.h>
-#include <gtk/gtkhseparator.h>
-#include <gtk/gtktogglebutton.h>
-#else
-#include "gdk/gdkkeysyms.h"
-#include "gtkbutton.h"
-#include "gtkentry.h"
-#include "gtkfilesel.h"
-#include "gtkhbox.h"
-#include "gtkhbbox.h"
-#include "gtklabel.h"
-#include "gtklist.h"
-#include "gtklistitem.h"
-#include "gtkmain.h"
-#include "gtkscrolledwindow.h"
-#include "gtksignal.h"
-#include "gtkvbox.h"
-#include "gtkmenu.h"
-#include "gtkmenuitem.h"
-#include "gtkoptionmenu.h"
-#include "gtkclist.h"
-#include "gtkdialog.h"
-#include "gtkcombo.h"
-#include "gtkframe.h"
-#include "gtkhpaned.h"
-#include "gtktable.h"
-#include "gtkpixmap.h"
-#include "gtknotebook.h"
-#include "gtkhseparator.h"
-#include "gtktogglebutton.h"
-#endif
-
-#ifndef LEO
-#include "gtkintl.h"
-
-#include "back.xpm"
-#include "up.xpm"
-#include "forward.xpm"
-#include "refresh.xpm"
-#endif
-
-#define DIR_LIST_WIDTH   180
-#define DIR_LIST_HEIGHT  180
-#define FILE_LIST_WIDTH  180
-#define FILE_LIST_HEIGHT 180
-#define BOOKMARK_FILE "/.gtkfilesel_bookmarks"
-#define MASK_FILE "/.gtkfilesel_masks"
-#define TIME_STRING_BUF 50
-
-/* I've put this here so it doesn't get confused with the 
- * file completion interface */
-typedef struct _HistoryCallbackArg HistoryCallbackArg;
-
-struct _HistoryCallbackArg
-{
-  gchar *directory;
-  GtkWidget *menu_item;
-};
-
-
-typedef struct _BookmarkMenuStruct BookmarkMenuStruct;
-struct _BookmarkMenuStruct {
-  GtkWidget *menu_item;
-  gchar     *desc;
-  gchar     *path;
-};
-
-typedef struct _CompletionState    CompletionState;
-typedef struct _CompletionDir      CompletionDir;
-typedef struct _CompletionDirSent  CompletionDirSent;
-typedef struct _CompletionDirEntry CompletionDirEntry;
-typedef struct _CompletionUserDir  CompletionUserDir;
-typedef struct _PossibleCompletion PossibleCompletion;
-
-/* Non-external file completion decls and structures */
-
-/* A contant telling PRCS how many directories to cache.  Its actually
- * kept in a list, so the geometry isn't important. */
-#define CMPL_DIRECTORY_CACHE_SIZE 10
-
-/* A constant used to determine whether a substring was an exact
- * match by first_diff_index()
- */
-#define PATTERN_MATCH -1
-/* The arguments used by all fnmatch() calls below
- */
-#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
-
-#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
-
-/* This structure contains all the useful information about a directory
- * for the purposes of filename completion.  These structures are cached
- * in the CompletionState struct.  CompletionDir's are reference counted.
- */
-struct _CompletionDirSent
-{
-  ino_t inode;
-  time_t mtime;
-  dev_t device;
-
-  gint entry_count;
-  gchar *name_buffer; /* memory segment containing names of all entries */
-
-  struct _CompletionDirEntry *entries;
-};
-
-struct _CompletionDir
-{
-  CompletionDirSent *sent;
-
-  gchar *fullname;
-  gint fullname_len;
-
-  struct _CompletionDir *cmpl_parent;
-  gint cmpl_index;
-  gchar *cmpl_text;
-};
-
-/* This structure contains pairs of directory entry names with a flag saying
- * whether or not they are a valid directory.  NOTE: This information is used
- * to provide the caller with information about whether to update its completions
- * or try to open a file.  Since directories are cached by the directory mtime,
- * a symlink which points to an invalid file (which will not be a directory),
- * will not be reevaluated if that file is created, unless the containing
- * directory is touched.  I consider this case to be worth ignoring (josh).
- */
-struct _CompletionDirEntry
-{
-  gint is_dir;
-  gchar *entry_name;
-};
-
-struct _CompletionUserDir
-{
-  gchar *login;
-  gchar *homedir;
-};
-
-struct _PossibleCompletion
-{
-  /* accessible fields, all are accessed externally by functions
-   * declared above
-   */
-  gchar *text;
-  gint is_a_completion;
-  gint is_directory;
-
-  gint file_size;
-  gint file_time;
-  gint uid;
-  gint gid;
-  /* Private fields
-   */
-  gint text_alloc;
-};
-
-struct _CompletionState
-{
-  gint last_valid_char;
-  gchar *updated_text;
-  gint updated_text_len;
-  gint updated_text_alloc;
-  gint re_complete;
-
-  gchar *user_dir_name_buffer;
-  gint user_directories_len;
-
-  gchar *last_completion_text;
-
-  gint user_completion_index; /* if >= 0, currently completing ~user */
-
-  struct _CompletionDir *completion_dir; /* directory completing from */
-  struct _CompletionDir *active_completion_dir;
-
-  struct _PossibleCompletion the_completion;
-
-  struct _CompletionDir *reference_dir; /* initial directory */
-
-  GList* directory_storage;
-  GList* directory_sent_storage;
-
-  struct _CompletionUserDir *user_directories;
-};
-
-/* Widgets from the Properties Dialog */
-typedef struct _PropertiesPrivate PropertiesPrivate;
-
-struct _PropertiesPrivate
-{
-  GtkWidget *mode_label;
-  GtkWidget *mode_buttons[12];
-};
-
-/* pixmap creation function */
-GtkWidget*                 create_pixmap          (GtkWidget *widget, 
-						   const gchar *pixmap_char);
-
-/* File completion functions which would be external, were they used
- * outside of this file.
- */
-
-static CompletionState*    cmpl_init_state        (void);
-static void                cmpl_free_state        (CompletionState *cmpl_state);
-static gint                cmpl_state_okay        (CompletionState* cmpl_state);
-static gchar*              cmpl_strerror          (gint);
-
-static PossibleCompletion* cmpl_completion_matches(gchar           *text_to_complete,
-						   gchar          **remaining_text,
-						   CompletionState *cmpl_state);
-
-/* Returns a name for consideration, possibly a completion, this name
- * will be invalid after the next call to cmpl_next_completion.
- */
-static char*               cmpl_this_completion   (PossibleCompletion*);
-
-/* True if this completion matches the given text.  Otherwise, this
- * output can be used to have a list of non-completions.
- */
-static gint                cmpl_is_a_completion   (PossibleCompletion*);
-
-/* True if the completion is a directory
- */
-static gint                cmpl_is_directory      (PossibleCompletion*);
-
-/* Obtains the next completion, or NULL
- */
-static PossibleCompletion* cmpl_next_completion   (CompletionState*);
-
-/* Updating completions: the return value of cmpl_updated_text() will
- * be text_to_complete completed as much as possible after the most
- * recent call to cmpl_completion_matches.  For the present
- * application, this is the suggested replacement for the user's input
- * string.  You must CALL THIS AFTER ALL cmpl_text_completions have
- * been received.
- */
-static gchar*              cmpl_updated_text       (CompletionState* cmpl_state);
-
-/* After updating, to see if the completion was a directory, call
- * this.  If it was, you should consider re-calling completion_matches.
- */
-static gint                cmpl_updated_dir        (CompletionState* cmpl_state);
-
-/* Current location: if using file completion, return the current
- * directory, from which file completion begins.  More specifically,
- * the cwd concatenated with all exact completions up to the last
- * directory delimiter('/').
- */
-static gchar*              cmpl_reference_position (CompletionState* cmpl_state);
-
-/* backing up: if cmpl_completion_matches returns NULL, you may query
- * the index of the last completable character into cmpl_updated_text.
- */
-static gint                cmpl_last_valid_char    (CompletionState* cmpl_state);
-
-/* When the user selects a non-directory, call cmpl_completion_fullname
- * to get the full name of the selected file.
- */
-static gchar*              cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);
-
-
-/* Directory operations. */
-static CompletionDir* open_ref_dir         (gchar* text_to_complete,
-					    gchar** remaining_text,
-					    CompletionState* cmpl_state);
-static gboolean       check_dir            (gchar *dir_name, 
-					    struct stat *result, 
-					    gboolean *stat_subdirs);
-static CompletionDir* open_dir             (gchar* dir_name,
-					    CompletionState* cmpl_state);
-static CompletionDir* open_user_dir        (gchar* text_to_complete,
-					    CompletionState *cmpl_state);
-static CompletionDir* open_relative_dir    (gchar* dir_name, CompletionDir* dir,
-					    CompletionState *cmpl_state);
-static CompletionDirSent* open_new_dir     (gchar* dir_name, 
-					    struct stat* sbuf,
-					    gboolean stat_subdirs);
-static gint           correct_dir_fullname (CompletionDir* cmpl_dir);
-static gint           correct_parent       (CompletionDir* cmpl_dir,
-					    struct stat *sbuf);
-static gchar*         find_parent_dir_fullname    (gchar* dirname);
-static CompletionDir* attach_dir           (CompletionDirSent* sent,
-					    gchar* dir_name,
-					    CompletionState *cmpl_state);
-static void           free_dir_sent (CompletionDirSent* sent);
-static void           free_dir      (CompletionDir  *dir);
-static void           prune_memory_usage(CompletionState *cmpl_state);
-
-/* Completion operations */
-static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,
-						      CompletionState *cmpl_state);
-static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);
-static CompletionDir* find_completion_dir(gchar* text_to_complete,
-					  gchar** remaining_text,
-					  CompletionState* cmpl_state);
-static PossibleCompletion* append_completion_text(gchar* text,
-						  CompletionState* cmpl_state);
-static gint get_pwdb(CompletionState* cmpl_state);
-static gint first_diff_index(gchar* pat, gchar* text);
-static gint compare_user_dir(const void* a, const void* b);
-static gint compare_cmpl_dir(const void* a, const void* b);
-static void update_cmpl(PossibleCompletion* poss,
-			CompletionState* cmpl_state);
-
-static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);
-static void gtk_file_selection_init          (GtkFileSelection      *filesel);
-static void gtk_file_selection_realize       (GtkWidget             *widget);
-static void gtk_file_selection_destroy       (GtkObject             *object);
-static gint gtk_file_selection_key_press     (GtkWidget             *widget,
-					      GdkEventKey           *event,
-					      gpointer               user_data);
-
-static void gtk_file_selection_file_button (GtkWidget *widget,
-					    gint row, 
-					    gint column, 
-					    GdkEventButton *bevent,
-					    gpointer user_data);
-
-static void gtk_file_selection_dir_button (GtkWidget *widget,
-					   gint row,
-					   gint column,
-					   GdkEventButton *bevent,
-					   gpointer data);
-
-static void gtk_file_selection_undir_button (GtkWidget *widget,
-					     gint row,
-					     gint column,
-					     GdkEventButton *bevent,
-					     gpointer data);
-
-static void gtk_file_selection_populate      (GtkFileSelection      *fs,
-					      gchar                 *rel_path,
-					      gint                   try_complete);
-static void gtk_file_selection_abort         (GtkFileSelection      *fs);
-
-static void gtk_file_selection_update_history_menu (GtkFileSelection       *fs,
-						    gchar                  *current_dir);
-
-static void gtk_file_selection_create_dir (gpointer data);
-static void gtk_file_selection_delete_file (gpointer data);
-static void gtk_file_selection_rename_file (gpointer data);
-static void gtk_file_selection_properties (gpointer data);
-static void gtk_file_selection_properties_update_mode (GtkWidget *widget, gpointer data);
-static mode_t gtk_file_selection_properties_get_mode (PropertiesPrivate* private);
-
-static gboolean gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
-static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
-																							GdkEventKey *event,
-																							gpointer user_data);
-static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
-																							GdkEventButton *event,
-
-																							gpointer user_data);
-static void gtk_file_selection_bookmark_callback (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data);
-static gint gtk_file_selection_mask_entry_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
-static gint gtk_file_selection_mask_entry_button_callback (GtkWidget *widget, GdkEventButton *event, gpointer data);
-
-//static void gtk_file_selection_home_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_bookmark_button (GtkWidget *widget, 
-	      	                   GtkFileSelection *fs);
-
-static void gtk_file_selection_up_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_prev_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_next_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data);
-
-static gint gtk_file_selection_files_list_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
-
-
-static gint gtk_file_selection_match_char (gchar, gchar *mask);
-static gint gtk_file_selection_match_mask (gchar *,gchar *);
-
-static void gtk_file_selection_load_bookmarks(GtkFileSelection *fs);
-static void gtk_file_selection_add_bookmark (GtkFileSelection *fs, gchar *desc, gchar *path);
-gint gtk_file_selection_save_bookmarks (GtkFileSelection *fs);
-
-static void gtk_file_selection_load_masks(GtkFileSelection *fs);
-
-static gint gtk_file_selection_show_fileop_menu (GtkCList *clist, 
-						 GdkEvent *event, 
-						 GtkFileSelection *fs);
-
-						 
-static GtkWindowClass *parent_class = NULL;
-
-/* Saves errno when something cmpl does fails. */
-static gint cmpl_errno;
-
-#ifdef G_WITH_CYGWIN
-/*
- * Take the path currently in the file selection
- * entry field and translate as necessary from
- * a WIN32 style to CYGWIN32 style path.  For
- * instance translate:
- * x:\somepath\file.jpg
- * to:
- * //x/somepath/file.jpg
- *
- * Replace the path in the selection text field.
- * Return a boolean value concerning whether a
- * translation had to be made.
- */
-int
-translate_win32_path (GtkFileSelection *filesel)
-{
-  int updated = 0;
-  gchar *path;
-
-  /*
-   * Retrieve the current path
-   */
-  path = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
-
-  /*
-   * Translate only if this looks like a DOS-ish
-   * path... First handle any drive letters.
-   */
-  if (isalpha (path[0]) && (path[1] == ':')) {
-    /*
-     * This part kind of stinks... It isn't possible
-     * to know if there is enough space in the current
-     * string for the extra character required in this
-     * conversion.  Assume that there isn't enough space
-     * and use the set function on the text field to
-     * set the newly created string.
-     */
-    gchar *newPath = g_strdup_printf ("//%c/%s", path[0], (path + 3));
-    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), newPath);
-
-    path = newPath;
-    updated = 1;
-  }
-
-  /*
-   * Now, replace backslashes with forward slashes 
-   * if necessary.
-   */
-  if (strchr (path, '\\'))
-    {
-      int index;
-      for (index = 0; path[index] != '\0'; index++)
-	if (path[index] == '\\')
-	  path[index] = '/';
-      
-      updated = 1;
-    }
-    
-  return updated;
-}
-#endif
-
-/* General notes:
- * Make prev and next inactive if their respective *
- *   histories are empty.
- * Add facilities for handling hidden files and    *
- * directories                                     *
- * Add an api to access the mask, and hidden files *
- * check box?  (prob not in 1.2.x series)          *
- */
-
-/* Routine for applying mask to filenames         *
- *   Need to be optimized to minimize recursion   *
- *     help the for loop by looking for the next  *
- *     instance of the mask character following   *
- *     the '*'.  ei *.c -- look for '.'           *
- *     Also, swap all *? pairs (-> ?*), as that   *
- *     will make it possible to look ahead (?     *
- *     makes it very nondeterministic as in *?.c  *
- *     which really is ?*.c                       *
- *                                                *
- */
-static gint gtk_file_selection_match_char (gchar text, gchar *mask)
-{
-  gchar *maskc;
-  gint x;
-  gint s;
-  gchar lastc;
-  gchar nextc;
-
-  if (mask[0] == '[')
-    {
-      if (!strchr (mask,']')) return 0;
-      lastc = 0;
-
-      maskc = g_strdup(mask + 1); /* get the portion of mask inside []*/
-      (*(strchr (maskc + 1,']'))) = 0;
-      s = strlen ((char *)maskc);
-
-      for (x = 0 ; x < s ; x ++){
-        if (maskc[x] == '-')
-          {
-            if (x == s) return 1;
-            nextc = maskc[x + 1];
-
-            if (nextc > lastc)
-            {
-              if ((lastc <= text) && (nextc >= text))
-              {
-                g_free (maskc);
-                return s + 2;
-              }
-            }
-            else if ((lastc >= text) && (nextc <= text))
-              {
-                g_free (maskc);
-                return s + 2;
-              }
-          }
-        else if (text == maskc[x])
-          {
-            g_free (maskc);
-            return s + 2;
-          }
-        lastc = maskc[x];
-      }
-      g_free (maskc);
-
-      return 0;
-    }
-
-  if (mask[0] == '?') return 1;
-  if (mask[0] == text) return 1;
-
-  return 0;
-}
-
-
-static gint gtk_file_selection_match_mask1 (gchar *text, gchar *mask)
-{
-
-  int mc;
-  int tc;
-
-  tc = 0; mc = 0;
-	
-  if (mask[0] == 0 && text[0] == 0) return 1;
-	
-  if (mask[0] == '*')
-    {
-      for (tc = 0; tc <= strlen(text); tc++)
-	{
-	  if (gtk_file_selection_match_mask1 (text + tc, mask + 1))
-	    return 1;
-	}
-      return 0;
-    }
-  mc = gtk_file_selection_match_char (text[0], mask);
-
-  if(mc)
-    return gtk_file_selection_match_mask1 (text + 1, mask + mc);
-  else
-    return 0;
-}
-
-static gint gtk_file_selection_match_mask (gchar *text, gchar *mask)
-{
-  gchar *masks;
-  gchar *bmask;
-  gchar *emask;
-
-  masks=g_strdup(mask);
-
-  emask=strchr(masks,'<');
-  if(emask){
-    bmask=emask+1;
-    emask=strchr(bmask,'>');
-    if(emask){
-      *emask=0;
-    }
-  }else{
-    bmask=masks;
-  }
-
-  do{
-    if((emask=strchr(bmask,',')) || (emask=strchr(bmask,';'))){
-      *emask=0;
-      if (gtk_file_selection_match_mask1 (text, bmask)){
-      	g_free(masks);
-	return 1;
-      }
-
-      bmask=emask+1;
-    }
-  }while(emask);
-
-  if(gtk_file_selection_match_mask1 (text, bmask)){
-    g_free(masks);
-    return 1;
-  }
-  g_free(masks);
-  return 0;
-}
-
-static void
-gtk_file_selection_load_bookmarks(GtkFileSelection *fs)
-{
-  GList *list;
-  gchar *bookmark_file;
-  gchar *bookmark_data;
-  struct stat file_info;
-  gint   file;
-  gint   lp;
-  gint   cp;
-  BookmarkMenuStruct *item;
-
-
-  if(fs->bookmark_list){  //erase
-    list=fs->bookmark_list;
-    while(list){
-      item=list->data;
-      g_free(item->desc);
-      g_free(item->path);
-      g_free(item);
-      list=list->next;
-    }
-    g_list_free (fs->bookmark_list);
-    fs->bookmark_list = NULL;
-    gtk_widget_destroy (fs->bookmark_menu);
-  }
-
-  fs->bookmark_menu=gtk_menu_new();
-
-  /* spacer */
-  item=g_malloc(sizeof(item));
-  item->menu_item = gtk_menu_item_new();
-  gtk_widget_show(item->menu_item);
-  gtk_menu_append (GTK_MENU(fs->bookmark_menu), item->menu_item);
-
-  item=g_malloc(sizeof(item));
-  item->desc=g_strdup("Add bookmark");
-  item->path=g_strdup(".");
-  item->menu_item=gtk_menu_item_new_with_label (item->desc);
-  gtk_widget_show(item->menu_item);
-  //fs->bookmark_list=g_list_append(fs->bookmark_list,item);
-  //set signal here!!
-  gtk_menu_append (GTK_MENU(fs->bookmark_menu), item->menu_item);
-
-  item=g_malloc(sizeof(item));
-  item->desc=g_strdup("Edit bookmark");
-  item->path=g_strdup(".");
-  item->menu_item=gtk_menu_item_new_with_label (item->desc);
-  gtk_widget_show(item->menu_item);
-  //fs->bookmark_list=g_list_append(fs->bookmark_list,item);
-  //set signal here!!
-  gtk_menu_append (GTK_MENU(fs->bookmark_menu), item->menu_item);
-
-  bookmark_file=g_strconcat(g_get_home_dir(), BOOKMARK_FILE ,NULL);
-  if(!stat(bookmark_file,&file_info) && (file = open(bookmark_file,  O_RDONLY )) > 0)
-  {
-    if(file_info.st_size <65536 )
-    {
-      bookmark_data=g_malloc(file_info.st_size);
-
-      if(file && read(file, bookmark_data, file_info.st_size))
-      {
-        cp=lp=0;
-
-        while (cp < file_info.st_size)
-        {
-          while (cp < file_info.st_size && bookmark_data[cp] != '<' )
-            cp++;
-	  bookmark_data[cp]=0;
-	  item=g_malloc(sizeof(BookmarkMenuStruct));
-	  item->desc=g_strdup(bookmark_data+lp);
-	  lp=++cp;
-	  
-          while (cp < file_info.st_size && bookmark_data[cp] != '>' )
-            cp++;
-
-          bookmark_data[cp]=0;
-          //create menu items
-	  item->path=g_strdup(bookmark_data+lp);
-	  gtk_file_selection_add_bookmark ((gpointer) fs, (gpointer) item->desc, (gpointer) item->path);
-
-	  cp++;
-
-          while(cp < file_info.st_size && bookmark_data[cp] < 33 )
-            cp++;
-          lp=cp;
-        }
-      }
-
-      close(file);
-    }
-  } else {
-
-    /* Add some default items, then save off to bookmarks file */
-
-    gtk_file_selection_add_bookmark ((gpointer) fs, "Home", "~/");
-    gtk_file_selection_add_bookmark ((gpointer) fs, "Root", "/");
-
-    gtk_file_selection_save_bookmarks ((gpointer) fs);
-  }
-}
-
-static void 
-gtk_file_selection_add_bookmark (GtkFileSelection *fs, gchar *desc, gchar *path) 
-{
-  /* Add item to menu */
-  BookmarkMenuStruct *item;
-  item=g_malloc(sizeof(item));
-  item->desc = (gpointer) desc;
-  item->path = (gpointer) path;
-  item->menu_item=gtk_menu_item_new_with_label (item->desc);
-  gtk_widget_show(item->menu_item);
-  fs->bookmark_list=g_list_append(fs->bookmark_list,item);
-  gtk_signal_connect (GTK_OBJECT(item->menu_item), "activate",
-		      (GtkSignalFunc) gtk_file_selection_bookmark_callback,
-		      (gpointer) fs);
-  gtk_menu_insert (GTK_MENU(fs->bookmark_menu), item->menu_item, g_list_length(fs->bookmark_list) -1);
-}
-
-gint 
-gtk_file_selection_save_bookmarks (GtkFileSelection *fs)
-{
-  BookmarkMenuStruct *item;
-  gchar *bookmark_file;
-  gchar *item_data;
-  gint   file;
-  GList *list;
-
-  bookmark_file=g_strconcat(g_get_home_dir(), BOOKMARK_FILE ,NULL);
-
-  if ((file = open(bookmark_file, O_CREAT | O_WRONLY | O_TRUNC, 0600)) > 0)
-  {
-    for (list = g_list_first (fs->bookmark_list); list != NULL; list = g_list_next(list)) {
-      item = list->data;
-      item_data = g_strconcat(item->desc, " <", item->path, ">\n", NULL);
-      if (write (file, item_data, strlen(item_data)) != strlen(item_data)) {
-	return TRUE;
-      }
-      g_free(item_data);
-    }
-    
-    close(file);
-  } else {
-    return TRUE;
-  }
-
-  return FALSE;
-}
-
-static void
-gtk_file_selection_load_masks(GtkFileSelection *fs)
-{
-  /*
-  GList *list;
-  gchar *masks_file;
-  gchar *masks_data;
-  struct stat file_info;
-  gint   file;
-  gint   lp;
-  gint   cp;
-
-  if(fs->masks){
-    list=fs->masks;
-    while(list){
-      g_free(list->data);
-      list=list->next;
-    }
-    fs->masks = NULL;
-  }
-
-  masks_file=g_strconcat(g_get_home_dir(), MASK_FILE,NULL); //put in #define
-  if(!stat(masks_file,&file_info))
-  {
-    if(file_info.st_size <65536 )
-    {
-      masks_data=g_malloc(file_info.st_size);
-
-      file = open(masks_file,  O_RDONLY );
-
-      if(file && read(file, masks_data, file_info.st_size))
-      {
-        cp=lp=0;
-
-        while (cp < file_info.st_size)
-        {
-          while (cp < file_info.st_size && masks_data[cp] != '>' )
-            cp++;
-
-          masks_data[++cp]=0;
-          if (masks_data[lp]=='<') { //if there was no description, strip off brackets
-            lp++;
-            masks_data[cp-1]=0;
-          }
-//          g_print("%s\n",masks_data+lp);
-          fs->masks = g_list_append(fs->masks, g_strdup(masks_data+lp));
-
-          while(cp < file_info.st_size && masks_data[cp] < 33 )
-            cp++;
-          lp=cp;
-        }
-      }
-
-      close(file);
-    }
-  }
-  */
-  if (!fs->masks) {
-    /* masks is still null, fill it with default data... */
-    /*
-    fs->masks = g_list_append(fs->masks, "all files <*>");
-    fs->masks = g_list_append(fs->masks, "mp3s/playlists <*.mp3,*.m3u>");
-    fs->masks = g_list_append(fs->masks, "src/hdr <*.[CcHh],*.[Cc][Cc],*.[Hh][Hh],*.cpp>");
-    fs->masks = g_list_append(fs->masks, "html docs <*.html,*.htm,*.HTM,*.php*,*.inc>");
-    fs->masks = g_list_append(fs->masks, "images <*.png,*.jpg,*.jpeg,*.gif,*.xpm,*.tiff>");
-    fs->masks = g_list_append(fs->masks, "package <*.rpm,*.deb>");
-    fs->masks = g_list_append(fs->masks, "archive <*.tgz,*.tb2,*.tar*,*.zip,*.rar>");
-    fs->masks = g_list_append(fs->masks, "compressed <*.Z,*.gz,*.bz2>");
-    */
-  }
-}
-
-void gtk_file_selection_clear_masks (GtkFileSelection *filesel)
-{
-  GList *list;
-
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-
-  list = filesel->masks;
-  while (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  filesel->masks = NULL;
-
-  gtk_list_clear_items (GTK_LIST (GTK_COMBO (filesel->mask_entry)->list), 0, -1);
-}
-
-void gtk_file_selection_set_masks (GtkFileSelection *filesel, const gchar **masks)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-
-  while (*masks)
-    {
-      filesel->masks = g_list_append (filesel->masks, (gpointer)*masks);
-      masks++;
-    }
-
-  if (filesel->masks)
-    gtk_combo_set_popdown_strings (GTK_COMBO (filesel->mask_entry), filesel->masks);
-}
-
-GtkType
-gtk_file_selection_get_type (void)
-{
-  static GtkType file_selection_type = 0;
-
-  if (!file_selection_type)
-    {
-      static const GtkTypeInfo filesel_info =
-      {
-	"GtkFileSelection",
-	sizeof (GtkFileSelection),
-	sizeof (GtkFileSelectionClass),
-	(GtkClassInitFunc) gtk_file_selection_class_init,
-	(GtkObjectInitFunc) gtk_file_selection_init,
-	/* reserved_1 */ NULL,
-	/* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
-      };
-
-      file_selection_type = gtk_type_unique (GTK_TYPE_WINDOW, &filesel_info);
-    }
-
-  return file_selection_type;
-}
-
-static void
-gtk_file_selection_class_init (GtkFileSelectionClass *class)
-{
-  GtkObjectClass *object_class;
-  GtkWidgetClass *widget_class;
-
-  object_class = (GtkObjectClass*) class;
-
-  parent_class = gtk_type_class (GTK_TYPE_WINDOW);
-
-  widget_class = GTK_WIDGET_CLASS (class);
-
-  widget_class->realize = gtk_file_selection_realize;
-  object_class->destroy = gtk_file_selection_destroy;
-}
-
-static void
-gtk_file_selection_init (GtkFileSelection *filesel)
-{
-  GtkWidget *entry_vbox;
-  GtkWidget *label;
-  GtkWidget *list_vbox;
-  GtkWidget *confirm_area;
-  GtkWidget *vbox;
-  GtkWidget *hbox;
-  GtkWidget *hbox2;
-  GtkWidget *table;
-  GtkWidget *pulldown_hbox;
-  GtkWidget *scrolled_win;
-  GtkWidget *mask_label;
-  GtkWidget *bigframe;
-  GtkWidget *button;
-  GtkWidget *hpaned;
-  GtkWidget *menu_item;
-  GtkWidget *pixmap;
-
-  char *dir_title [2];
-  char *file_title [2];
-  
-  filesel->cmpl_state = cmpl_init_state ();
-
-  filesel->mask=NULL;
-  filesel->prev_history=NULL;
-  filesel->next_history=NULL;
-  filesel->saved_entry=NULL;
-  filesel->bookmark_list=NULL;
-  filesel->masks=NULL;
-  filesel->selection_text = NULL;
-  filesel->fileop_data = NULL;
-
-  gtk_file_selection_load_masks(filesel);
-  gtk_file_selection_load_bookmarks(filesel);
-
-  /* The dialog-sized vertical box  */
-  filesel->main_vbox = gtk_vbox_new (FALSE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER (filesel), 0);
-  gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
-  gtk_widget_show (filesel->main_vbox);
-
-  /* hbox for pulldown menu */
-  pulldown_hbox = gtk_hbox_new (FALSE, 0);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);
-  gtk_widget_show (pulldown_hbox);
-  
-  /* The horizontal box containing create, rename etc. buttons */
-
-/*
-  filesel->button_area = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(filesel->button_area), GTK_BUTTONBOX_START);
-  gtk_button_box_set_spacing(GTK_BUTTON_BOX(filesel->button_area), 0);
-  gtk_box_pack_start (GTK_BOX (pulldown_hbox), filesel->button_area,
-		      FALSE, FALSE, 0);
-  gtk_button_box_set_child_size(GTK_BUTTON_BOX(filesel->button_area),0,0);
-  gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX(filesel->button_area),0,0);
-  */
-
-  filesel->button_area = gtk_hbox_new (TRUE,0);
-  //gtk_box_pack_start (GTK_BOX (pulldown_hbox), filesel->button_area,
-  //		      FALSE, FALSE, 0);
-
-  //gtk_widget_show (filesel->button_area);
-
-  gtk_file_selection_show_fileop_buttons(filesel);
-  /*  frame to put the following hbox in  */
-  bigframe = gtk_frame_new (NULL);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), bigframe, TRUE, TRUE, 0);
-  gtk_frame_set_shadow_type (GTK_FRAME (bigframe), GTK_SHADOW_OUT);
-  gtk_widget_show (bigframe);
-
-
-  list_vbox = gtk_vbox_new (FALSE,3);
-  gtk_widget_show(list_vbox);
-  gtk_container_add (GTK_CONTAINER(bigframe), list_vbox);
-  gtk_container_set_border_width (GTK_CONTAINER (list_vbox),2);
-  gtk_widget_show (list_vbox);
-  
-  /*  The horizontal box containing the directory and file listboxes  */
-//  list_hbox = gtk_hbox_new (FALSE, 3);
-  //gtk_container_add (GTK_CONTAINER(bigframe), list_hbox);
-  //gtk_container_set_border_width (GTK_CONTAINER (list_hbox), 3);
-//  gtk_box_pack_start(GTK_BOX(list_vbox), list_hbox, FALSE,FALSE,0);
-//  gtk_widget_show (list_hbox);
-
-  hpaned=gtk_hpaned_new();
-  gtk_widget_show(hpaned);
-  gtk_container_set_border_width (GTK_CONTAINER (hpaned), 1);
-  gtk_paned_set_gutter_size (GTK_PANED (hpaned), 10);
-  gtk_box_pack_start (GTK_BOX(list_vbox), hpaned,TRUE,TRUE,0);
-
-  /* vbox to put the buttons and directory listing in  */
-  vbox = gtk_vbox_new (FALSE, 3);
-  gtk_widget_show (vbox);
-  gtk_container_add(GTK_CONTAINER(hpaned),vbox);
-  //gtk_box_pack_start (GTK_BOX (hpaned), vbox, FALSE, FALSE, 0);
-
-  hbox = gtk_hbox_new (FALSE, 4);
-  gtk_widget_show (hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-//  home_button = gtk_button_new_with_label (_("Home"));
-//  gtk_widget_show (home_button);
-//  gtk_signal_connect (GTK_OBJECT (home_button), "clicked",
-//		      (GtkSignalFunc) gtk_file_selection_home_button,
-//		      (gpointer) filesel);
-//  gtk_box_pack_start (GTK_BOX (hbox), home_button, TRUE,TRUE, 0);
-
-  /* Here we add the bookmark menu button */
-  #define If we're going to make bookmark a menu, we don't need 
-  #define   to keep it in the filesel structure
-  button=gtk_button_new_with_label(_("Bookmarks"));
-  gtk_widget_show(button);
-  gtk_box_pack_start (GTK_BOX(hbox), button, FALSE,FALSE,0);
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_bookmark_button,
-		      (gpointer) filesel);
-  
-  hbox2 = gtk_hbox_new (FALSE, 2);
-  gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
-  gtk_widget_show(hbox2);
-
-  /* Prev button */
-  button = gtk_button_new ();
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_prev_button,
-		      (gpointer) filesel);
-  gtk_widget_show (button);
-  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE,FALSE, 0);
-  pixmap = create_pixmap (filesel->main_vbox, (gpointer) back_xpm);
-  gtk_widget_show (pixmap);
-  gtk_container_add (GTK_CONTAINER (button), pixmap);
-
-  /* Up button */
-  button = gtk_button_new ();
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_up_button,
-		      (gpointer) filesel);
-  gtk_widget_show (button);
-  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE,FALSE, 0);
-  pixmap = create_pixmap (filesel->main_vbox, (gpointer) up_xpm);
-  gtk_widget_show (pixmap);
-  gtk_container_add (GTK_CONTAINER (button), pixmap);
-
-  /* next button */
-  button = gtk_button_new ();
-  gtk_widget_show (button);
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_next_button,
-		      (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE,FALSE, 0);
-  pixmap = create_pixmap (filesel->main_vbox, (gpointer) forward_xpm);
-  gtk_widget_show (pixmap);
-  gtk_container_add (GTK_CONTAINER (button), pixmap);
-
-  /* refresh button */
-  button = gtk_button_new ();
-  gtk_widget_show (button);
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_refresh_button,
-		      (gpointer) filesel);
-  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE,FALSE, 0);
-  pixmap = create_pixmap (filesel->main_vbox, (gpointer) refresh_xpm);
-  gtk_widget_show (pixmap);
-  gtk_container_add (GTK_CONTAINER (button), pixmap);
-
-  /* menu for right click file operations */
-  filesel->fileop_menu = gtk_menu_new();
-  
-  menu_item = gtk_menu_item_new_with_label ("Rename...");
-  gtk_widget_show(menu_item);
-  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
-			     (GtkSignalFunc) gtk_file_selection_rename_file,
-			     (gpointer) filesel);
-  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
-
-  menu_item = gtk_menu_item_new_with_label ("Delete");
-  gtk_widget_show(menu_item);
-  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
-  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
-			     (GtkSignalFunc) gtk_file_selection_delete_file,
-			     (gpointer) filesel);
-
-  menu_item = gtk_menu_item_new ();
-  gtk_widget_show(menu_item);
-  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
-
-  menu_item = gtk_menu_item_new_with_label ("Create Directory...");
-  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
-			     (GtkSignalFunc) gtk_file_selection_create_dir, 
-			     (gpointer) filesel);
-  gtk_widget_show(menu_item);
-  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
-
-  menu_item = gtk_menu_item_new ();
-  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
-  gtk_widget_show(menu_item);
-
-  menu_item = gtk_menu_item_new_with_label ("Properties...");
-  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
-			     (GtkSignalFunc) gtk_file_selection_properties,
-			     (gpointer) filesel);
-  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
-  gtk_widget_show(menu_item);
-
-  /* The directories clist */
-  dir_title[0] = _("Directories");
-  dir_title[1] = NULL;
-  filesel->dir_list = gtk_clist_new_with_titles (1, (gchar**) dir_title);
-  gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
-  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",
-		      (GtkSignalFunc) gtk_file_selection_dir_button,
-		      (gpointer) filesel);
-  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "unselect_row",
-		      (GtkSignalFunc) gtk_file_selection_undir_button,
-		      (gpointer) filesel);
-  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "button_press_event",
-		      GTK_SIGNAL_FUNC(gtk_file_selection_show_fileop_menu), 
-		      (gpointer) filesel);
-
-  gtk_clist_column_titles_passive (GTK_CLIST (filesel->dir_list));
-
-  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->dir_list);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE,TRUE, 0);
-  //gtk_container_add(GTK_CONTAINER(hpaned), scrolled_win);
-  
-  gtk_widget_show (filesel->dir_list);
-  gtk_widget_show (scrolled_win);
-
-  vbox = gtk_vbox_new (FALSE, 3);
-  gtk_widget_show (vbox);
-  gtk_container_add(GTK_CONTAINER(hpaned),vbox);
-  /* vbox area for mask entry and files clist  */
-
-  hbox = gtk_hbox_new (FALSE, 2);
-  gtk_widget_show (hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-  mask_label = gtk_label_new (_("Mask:"));
-  gtk_widget_show (mask_label);
-  gtk_box_pack_start (GTK_BOX (hbox), mask_label, FALSE, FALSE, 2);
-
-/*
-  filesel->mask_entry = gtk_entry_new ();
-  gtk_widget_show (filesel->mask_entry);
-  gtk_signal_connect(GTK_OBJECT(filesel->mask_entry),"activate",
-		     (GtkSignalFunc) gtk_file_4_mask_entry_callback,
-		     (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
-  */
-
-  filesel->mask_entry = gtk_combo_new ();
-  gtk_widget_show (filesel->mask_entry);
-  gtk_combo_set_value_in_list(GTK_COMBO(filesel->mask_entry),FALSE,FALSE);
-  gtk_signal_connect(GTK_OBJECT(GTK_COMBO(filesel->mask_entry)->entry),"activate",
-		     (GtkSignalFunc) gtk_file_selection_mask_entry_callback,
-		     (gpointer) filesel);
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->mask_entry)->entry),"key-press-event",				
-		     (GtkSignalFunc) gtk_file_selection_mask_entry_key_callback,
-		     (gpointer) filesel);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->mask_entry)->list),"button-release-event",
-		     (GtkSignalFunc) gtk_file_selection_mask_entry_button_callback,
-		     (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
-
-  if (filesel->masks)
-    gtk_combo_set_popdown_strings (GTK_COMBO (filesel->mask_entry), filesel->masks);
-
-
-  /* The files clist */
-  file_title[0] = _("Files");
-  file_title[1] = NULL;
-  filesel->file_list = gtk_clist_new_with_titles (1, (gchar**) file_title);
-  gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
-  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
-		      (GtkSignalFunc) gtk_file_selection_file_button, 
-		      (gpointer) filesel);
-  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "key-press-event",
-		      (GtkSignalFunc) gtk_file_selection_files_list_key_callback,
-		      (gpointer) filesel);
-  
-  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "button_press_event",
-		      GTK_SIGNAL_FUNC(gtk_file_selection_show_fileop_menu), 
-		      (gpointer) filesel);
-
-  gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));
-
-  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->file_list);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
-  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
-  gtk_widget_show (filesel->file_list);
-  gtk_widget_show (scrolled_win);
-
-  /* action area for packing buttons into. */
-  filesel->action_area = gtk_hbox_new (TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->action_area, 
-		      FALSE, FALSE, 2);
-  gtk_widget_show (filesel->action_area);
-
-  /*
-  hbox=gtk_hbox_new(FALSE,0);
-  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), hbox, FALSE,FALSE, 0);
-  gtk_widget_show (hbox);
-  */
-
-  /*  The selection entry widget  */
-  
-  entry_vbox = gtk_vbox_new (FALSE, 0);
-  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
-  gtk_widget_show (entry_vbox);
-
-  table = gtk_table_new ( 2, 2, FALSE );
-  gtk_box_pack_start (GTK_BOX (entry_vbox), table, TRUE, TRUE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER (table), 4);
-  gtk_table_set_row_spacings (GTK_TABLE (table), 2);
-  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
-
-
-  label = gtk_label_new (_("Selection:"));
-  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
-                    (GtkAttachOptions) (0),
-                    (GtkAttachOptions) (0), 0, 0);
-  gtk_widget_show (label);
-
-
-  filesel->selection_entry = gtk_entry_new ();
-  gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
-		      (GtkSignalFunc) gtk_file_selection_key_press, filesel);
-  gtk_table_attach (GTK_TABLE (table), filesel->selection_entry, 1, 2, 0, 1,
-                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-                    (GtkAttachOptions) (0), 0, 0);
-  gtk_widget_show (filesel->selection_entry);
-
-
-  label = gtk_label_new (_("Directory:"));
-  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
-                    (GtkAttachOptions) (0),
-                    (GtkAttachOptions) (0), 0, 0);
-  gtk_widget_show (label);
-  
-
-  filesel->history_combo = gtk_combo_new();
-  gtk_combo_set_value_in_list(GTK_COMBO(filesel->history_combo),FALSE,FALSE);
-  gtk_table_attach (GTK_TABLE (table), filesel->history_combo, 1, 2, 1, 2,
-                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-                    (GtkAttachOptions) (0), 0, 0);
-  gtk_widget_show(filesel->history_combo);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->entry),"key-press-event",				    
-		     (GtkSignalFunc) gtk_file_selection_history_combo_callback,
-		     (gpointer) filesel);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"button-press-event",
-		     (GtkSignalFunc) gtk_file_selection_history_combo_list_callback,
-		     (gpointer) filesel);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"key-press-event",
-		     (GtkSignalFunc) gtk_file_selection_history_combo_list_key_handler,
-		     (gpointer) filesel);
-
-  filesel->selection_text = NULL;
-
-
-  /*  The OK/Cancel button area */
-  confirm_area = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);
-  gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);
-  gtk_box_pack_end (GTK_BOX (entry_vbox), confirm_area, FALSE, FALSE, 0);
-  gtk_widget_show (confirm_area);
-
-  /*  The OK button  */
-  filesel->ok_button = gtk_button_new_with_label (_("OK"));
-  GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->ok_button, TRUE, TRUE, 0);
-  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
-			     (GtkSignalFunc) gtk_widget_grab_default,
-			     GTK_OBJECT (filesel->ok_button));
-  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
-                             (GtkSignalFunc) gtk_button_clicked,
-                             GTK_OBJECT (filesel->ok_button));
-  gtk_widget_grab_default (filesel->ok_button);
-  gtk_widget_show (filesel->ok_button);
-
-  /*  The Cancel button  */
-  filesel->cancel_button = gtk_button_new_with_label (_("Cancel"));
-  GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->cancel_button, TRUE, TRUE, 0);
-  gtk_widget_show (filesel->cancel_button);
-
-  gtk_widget_show(table);
-
-
-  /*
-  filesel->selection_text = label = gtk_label_new ("");
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
-  gtk_widget_show (label);
-  */
-
-
-  if (!cmpl_state_okay (filesel->cmpl_state))
-    {
-      gchar err_buf[256];
-
-      sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
-
-      /*
-      gtk_label_set_text (GTK_LABEL (filesel->selection_text), err_buf);
-      */
-    }
-  else
-    {
-      gtk_file_selection_populate (filesel, "", FALSE);
-    }
-
-  gtk_widget_grab_focus (filesel->selection_entry);
-}
-
-GtkWidget*
-gtk_file_selection_new (const gchar *title)
-{
-  GtkFileSelection *filesel;
-
-  filesel = gtk_type_new (GTK_TYPE_FILE_SELECTION);
-  gtk_window_set_title (GTK_WINDOW (filesel), title);
-  /* !!! put check here to figure out if screen > 640x480, if true
-     We need to make the file selection dialog bigger. much bigger.. 
-     or maybe we should keep it at a certan percentage of the screen
-     size? */
-
-  gtk_window_set_default_size(GTK_WINDOW (filesel), 520, 420);
-  return GTK_WIDGET (filesel);
-}
-
-void
-gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-
-  return;
-	
-  /* delete, create directory, and rename */
-/*
-  if (!filesel->fileop_c_dir) 
-    {
-      filesel->fileop_c_dir = gtk_button_new_with_label (_("MkDir"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_c_dir), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_create_dir, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_c_dir, TRUE,TRUE, 0);
-      gtk_widget_show (filesel->fileop_c_dir);
-    }
-	
-  if (!filesel->fileop_del_file) 
-    {
-      filesel->fileop_del_file = gtk_button_new_with_label (_("Delete"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_del_file), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_delete_file, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_del_file, TRUE,TRUE, 0);
-      gtk_widget_show (filesel->fileop_del_file);
-    }
-
-  if (!filesel->fileop_ren_file)
-    {
-      filesel->fileop_ren_file = gtk_button_new_with_label (_("Rename"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_ren_file), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_rename_file, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_ren_file, TRUE,TRUE, 0);
-      gtk_widget_show (filesel->fileop_ren_file);
-    }
-
-  gtk_widget_queue_resize(GTK_WIDGET(filesel));
-  */
-}
-
-void       
-gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-  
-  return;
-  /*
-  if (filesel->fileop_ren_file) 
-    {
-      gtk_widget_destroy (filesel->fileop_ren_file);
-      filesel->fileop_ren_file = NULL;
-    }
-
-  if (filesel->fileop_del_file)
-    {
-      gtk_widget_destroy (filesel->fileop_del_file);
-      filesel->fileop_del_file = NULL;
-    }
-
-  if (filesel->fileop_c_dir)
-    {
-      gtk_widget_destroy (filesel->fileop_c_dir);
-      filesel->fileop_c_dir = NULL;
-    }
-  */
-}
-
-
-
-void
-gtk_file_selection_set_filename (GtkFileSelection *filesel,
-				 const gchar      *filename)
-{
-  char  buf[MAXPATHLEN];
-  const char *name, *last_slash;
-
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-  g_return_if_fail (filename != NULL);
-
-  last_slash = strrchr (filename, '/');
-
-  if (!last_slash)
-    {
-      buf[0] = 0;
-      name = filename;
-    }
-  else
-    {
-      gint len = MIN (MAXPATHLEN - 1, last_slash - filename + 1);
-
-      strncpy (buf, filename, len);
-      buf[len] = 0;
-
-      name = last_slash + 1;
-    }
-
-  gtk_file_selection_populate (filesel, buf, FALSE);
-
-  if (filesel->selection_entry)
-    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
-}
-
-gchar*
-gtk_file_selection_get_filename (GtkFileSelection *filesel)
-{
-  static char nothing[2] = "";
-  char *text;
-  char *filename;
-
-  g_return_val_if_fail (filesel != NULL, nothing);
-  g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), nothing);
-
-  text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
-  if (text)
-    {
-      filename = cmpl_completion_fullname (text, filesel->cmpl_state);
-      return filename;
-    }
-
-  return nothing;
-}
-
-void
-gtk_file_selection_complete (GtkFileSelection *filesel,
-			     const gchar      *pattern)
-{
-  gchar *new_pattern;
-  gint x;
-	
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-  g_return_if_fail (pattern != NULL);
-
-  if (filesel->selection_entry)
-    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), pattern);
-	
-  if(strchr(pattern,'*') || strchr(pattern,'?'))
-    {
-      for(x=strlen(pattern);x>=0;x--)
-	{
-	  if(pattern[x]=='/') break;
-	}
-      gtk_entry_set_text(GTK_ENTRY(filesel->mask_entry),g_strdup(pattern+x+1));
-      
-      if(filesel->mask) g_free(filesel->mask);
-      
-      filesel->mask=g_strdup(pattern+x+1);
-      new_pattern=g_strdup(pattern);
-      new_pattern[x+1]=0;
-      gtk_file_selection_populate (filesel, (gchar*) new_pattern, TRUE);
-      g_free(new_pattern);
-    }
-  else
-    {
-      gtk_file_selection_populate (filesel, (gchar*) pattern, TRUE);
-    }
-}
-
-static void
-gtk_file_selection_realize (GtkWidget *widget)
-{
-  GtkFileSelection *filesel;
-  const gchar *masks[] = { "All Files <*>", NULL };
-
-  g_return_if_fail (widget != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (widget));
-
-  filesel = GTK_FILE_SELECTION (widget);
-
-  /* make sure that we have at least one mask */
-  if (!filesel->masks)
-    gtk_file_selection_set_masks (filesel, masks);
-
-  filesel->mask = g_strdup ((gchar*) filesel->masks->data);
-  gtk_file_selection_populate (filesel, "", FALSE);
-
-
-  if (GTK_WIDGET_CLASS (parent_class)->realize)
-    (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
-}
-
-static void
-gtk_file_selection_destroy (GtkObject *object)
-{
-  GtkFileSelection *filesel;
-  GList *list;
-
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (object));
-
-  filesel = GTK_FILE_SELECTION (object);
-  
-  if (filesel->fileop_dialog)
-    gtk_widget_destroy (filesel->fileop_dialog);
-  
-  if (filesel->next_history)
-    {
-      list = filesel->next_history;
-      while (list)
-  	{
-	  g_free (list->data);
-	  list = list->next;
-  	}
-    }
-  g_list_free (filesel->next_history);
-  filesel->next_history = NULL;
-
-  if (filesel->prev_history)
-    {
-      list = filesel->prev_history;
-      while (list)
-  	{
-	  g_free (list->data);
-	  list = list->next;
-  	}
-    }
-  g_list_free (filesel->prev_history);
-  filesel->prev_history = NULL;
-
-  if (filesel->mask)
-    {
-      g_free (filesel->mask);
-      filesel->mask = NULL;
-    }
-  
-  cmpl_free_state (filesel->cmpl_state);
-  filesel->cmpl_state = NULL;
-
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
-/* Begin file operations callbacks */
-
-static gint
-gtk_file_selection_show_fileop_menu (GtkCList *clist, GdkEvent *event, GtkFileSelection *fs)
-{
-  GdkEventButton *event_button;
-
-  g_return_val_if_fail (clist != NULL, FALSE);
-  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-  g_return_val_if_fail (fs != NULL, FALSE);
-  g_return_val_if_fail (GTK_FILE_SELECTION (fs), FALSE);
-  
-  if (event->type == GDK_BUTTON_PRESS)
-    {
-      event_button = (GdkEventButton *) event;
-      if (event_button->button == 3)
-	{
-
-	  gtk_menu_popup (GTK_MENU (fs->fileop_menu), NULL, NULL, NULL, NULL, 
-			  event_button->button, event_button->time);
-	  return TRUE;
-	}
-    }
-  
-  return FALSE;
-}
-
-static void
-gtk_file_selection_fileop_error (GtkFileSelection *fs, gchar *error_message)
-{
-  GtkWidget *label;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  GtkWidget *dialog;
-  
-  g_return_if_fail (error_message != NULL);
-  
-  /* main dialog */
-  dialog = gtk_dialog_new ();
-  /*
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  */
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-  
-  /* If file dialog is grabbed, make this dialog modal too */
-  /* When error dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-
-  label = gtk_label_new(error_message);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-
-  /* yes, we free it */
-  g_free (error_message);
-  
-  /* close button */
-  button = gtk_button_new_with_label (_("Close"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-static void
-gtk_file_selection_fileop_destroy (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  fs->fileop_dialog = NULL;
-  g_free (fs->fileop_data);
-  fs->fileop_data = NULL;
-}
-
-
-static void
-gtk_file_selection_create_dir_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  gchar *dirname;
-  gchar *path;
-  gchar *full_path;
-  gchar *buf;
-  CompletionState *cmpl_state;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  dirname = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  full_path = g_strconcat (path, "/", dirname, NULL);
-  if ( (mkdir (full_path, 0755) < 0) ) 
-    {
-      buf = g_strconcat ("Error creating directory \"", dirname, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (full_path);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-  
-static void
-gtk_file_selection_create_dir (gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *button;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Create Directory"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-  
-  label = gtk_label_new(_("Directory name:"));
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-
-  /*  The directory entry widget  */
-  fs->fileop_entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
-		      TRUE, TRUE, 5);
-  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
-  gtk_widget_show (fs->fileop_entry);
-  
-  /* buttons */
-  button = gtk_button_new_with_label (_("Create"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_create_dir_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-static void
-gtk_file_selection_delete_file_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  CompletionState *cmpl_state;
-  gchar *path;
-  gchar *full_path;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  full_path = g_strconcat (path, "/", fs->fileop_file, NULL);
-  if ( (unlink (full_path) < 0) ) 
-    {
-      buf = g_strconcat ("Error deleting file \"", fs->fileop_file, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (full_path);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-
-static void
-gtk_file_selection_delete_file (gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  GtkWidget *dialog;
-  gchar *filename;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-
-  filename = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-  if (strlen(filename) < 1)
-	  return;
-
-  fs->fileop_file = filename;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Delete File"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-  
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-
-  buf = g_strconcat ("Really delete file \"", filename, "\" ?", NULL);
-  label = gtk_label_new(buf);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-  g_free(buf);
-  
-  /* buttons */
-  button = gtk_button_new_with_label (_("Delete"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_delete_file_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-
-}
-
-static void
-gtk_file_selection_rename_file_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  gchar *buf;
-  gchar *file;
-  gchar *path;
-  gchar *new_filename;
-  gchar *old_filename;
-  CompletionState *cmpl_state;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  new_filename = g_strconcat (path, "/", file, NULL);
-  old_filename = g_strconcat (path, "/", fs->fileop_file, NULL);
-
-  if (strcmp (new_filename, old_filename))
-    if ((rename (old_filename, new_filename)) < 0) 
-      {
-        buf = g_strconcat ("Error renaming file \"", file, "\":  ", 
-                           g_strerror(errno), NULL);
-        gtk_file_selection_fileop_error (fs, buf);
-      }
-  g_free (new_filename);
-  g_free (old_filename);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-  
-static void
-gtk_file_selection_file_mode_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  PropertiesPrivate *priv = fs->fileop_data;
-  CompletionState *cmpl_state;
-  gchar *filename, *file, *path;
-  mode_t mode;
-
-  mode = gtk_file_selection_properties_get_mode (priv);
-
-  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-
-  filename = g_strconcat (path, "/", file, NULL);
-  if (chmod (filename, mode) == -1)
-    {
-      gchar *buf = g_strconcat ("Error changing file mode of \"", filename, "\":  ", 
-                                g_strerror (errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-      gtk_widget_destroy (fs->fileop_dialog);
-      gtk_file_selection_populate (fs, "", FALSE);
-    }
-  else
-    gtk_file_selection_rename_file_confirmed (widget, data);
-
-  g_free (filename);
-}
-
-static void
-gtk_file_selection_rename_file (gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-
-  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-  if (strlen(fs->fileop_file) < 1)
-	  return;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Rename File"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog  closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-  
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-  
-  buf = g_strconcat ("Rename file \"", fs->fileop_file, "\" to:", NULL);
-  label = gtk_label_new(buf);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-  g_free(buf);
-
-  /* New filename entry */
-  fs->fileop_entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
-		      TRUE, TRUE, 5);
-  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
-  gtk_widget_show (fs->fileop_entry);
-  
-  gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
-  gtk_editable_select_region (GTK_EDITABLE (fs->fileop_entry),
-			      0, strlen (fs->fileop_file));
-
-  /* buttons */
-  button = gtk_button_new_with_label (_("Rename"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-static mode_t
-gtk_file_selection_properties_get_mode (PropertiesPrivate* priv)
-{
-  mode_t mode = 0;
-
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[0])))
-    mode |= S_IRUSR;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[1])))
-    mode |= S_IWUSR;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[2])))
-    mode |= S_IXUSR;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[3])))
-    mode |= S_ISUID;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[4])))
-    mode |= S_IRGRP;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[5])))
-    mode |= S_IWGRP;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[6])))
-    mode |= S_IXGRP;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[7])))
-    mode |= S_ISGID;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[8])))
-    mode |= S_IROTH;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[9])))
-    mode |= S_IWOTH;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[10])))
-    mode |= S_IXOTH;
-  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[11])))
-    mode |= S_ISVTX;
-
-  return mode;
-}
-
-static void
-gtk_file_selection_properties_update_mode (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  PropertiesPrivate *priv = fs->fileop_data;
-  gchar str[8];
-
-  sprintf (str, "(%.4o)", gtk_file_selection_properties_get_mode (priv));
-  gtk_label_set (GTK_LABEL (priv->mode_label), str);
-}
-
-static void
-gtk_file_selection_properties (gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *hbox;
-  GtkWidget *button;
-  GtkWidget *notebook;
-  GtkWidget *table;
-  GtkWidget *hseparator;
-  GtkWidget *entry;
-  GtkWidget *togglebutton;
-  struct stat statbuf;
-  struct passwd *pw;
-  struct group *gp;
-  gchar *buf;
-  gchar *path;
-  gchar *filename;
-  gchar timeBuf[TIME_STRING_BUF];
-  gint pagenum = 0;
-  PropertiesPrivate *priv;
-  int i;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  priv = fs->fileop_data = g_malloc (sizeof (PropertiesPrivate));
-
-  gtk_window_set_title (GTK_WINDOW (dialog), ("Properties"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog  closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-  
-  /* Dialog guts go here */
-  notebook = gtk_notebook_new ();
-  gtk_widget_show (notebook);
-  gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), notebook, TRUE, TRUE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER (notebook), 8);
-
-  path = cmpl_reference_position(fs->cmpl_state);
-  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-  filename = g_strconcat(path, "/", fs->fileop_file, NULL);
-  if (strlen(fs->fileop_file) > 0 && !(stat(filename, &statbuf))) 
-  {
-    /* stats page */
-    table = gtk_table_new (9, 2, FALSE);
-    gtk_widget_show (table);
-    gtk_container_add (GTK_CONTAINER (notebook), table);
-    gtk_container_set_border_width (GTK_CONTAINER (table), 5);
-    gtk_table_set_row_spacings (GTK_TABLE (table), 4);
-    gtk_table_set_col_spacings (GTK_TABLE (table), 6);
-    
-    label = gtk_label_new (_("Statistics"));
-    gtk_widget_show (label);
-    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), pagenum), label);
-    pagenum++;
-    /* path and filename */
-    label = gtk_label_new (_("Path:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    label = gtk_label_new (_(path));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    label = gtk_label_new (_("File Name:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    fs->fileop_entry = entry = gtk_entry_new ();
-    gtk_widget_show (entry);
-    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_entry_set_text (GTK_ENTRY (entry), fs->fileop_file);
-    if (access (filename, W_OK))
-      gtk_widget_set_sensitive( GTK_WIDGET (entry), FALSE);
-    
-    hseparator = gtk_hseparator_new ();
-    gtk_widget_show (hseparator);
-    gtk_table_attach (GTK_TABLE (table), hseparator, 0, 2, 2, 3,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (GTK_FILL), 0, 0);
-    
-    /* file type and size */
-    label = gtk_label_new (_("Type:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-
-    switch (statbuf.st_mode & S_IFMT)
-    {
-    case S_IFSOCK:
-      buf = g_strdup ("Socket");
-      break;
-    case S_IFLNK:
-      buf = g_strdup ("Symbolic link");
-      break;
-    case S_IFREG:
-      buf = g_strdup ("File");
-      break;
-    case S_IFBLK:
-      buf = g_strdup ("Block device");
-      break;
-    case S_IFDIR:
-      buf = g_strdup ("Directory");
-      break;
-    case S_IFCHR:
-      buf = g_strdup ("Character device");
-      break;
-    case S_IFIFO:
-      buf = g_strdup ("First-in/first-out pipe");
-      break;
-    default:
-      buf = g_strdup ("Unknown");
-    }
-
-
-    label = gtk_label_new (buf);
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 3, 4,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    label = gtk_label_new (_("Size:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    label = gtk_label_new (_(g_strdup_printf ("%ld bytes", statbuf.st_size)));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 4, 5,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    hseparator = gtk_hseparator_new ();
-    gtk_widget_show (hseparator);
-    gtk_table_attach (GTK_TABLE (table), hseparator, 0, 2, 5, 6,
-		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		      (GtkAttachOptions) (GTK_FILL), 0, 0);
-    
-    /* file dates */
-    label = gtk_label_new (_("Created:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 6, 7,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    strftime (timeBuf, TIME_STRING_BUF, "%a %b %d %X %Y", localtime(&statbuf.st_mtime));
-    label = gtk_label_new (_(timeBuf));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 6, 7,
-		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    
-    
-    label = gtk_label_new (_("Modified:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 7, 8,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    strftime (timeBuf, TIME_STRING_BUF, "%a %b %d %X %Y", localtime(&statbuf.st_mtime));
-    label = gtk_label_new (_(timeBuf));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 7, 8,
-		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    
-    label = gtk_label_new (_("Accessed:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 8, 9,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    strftime (timeBuf, TIME_STRING_BUF, "%a %b %d %X %Y", localtime(&statbuf.st_atime));
-    label = gtk_label_new (_(timeBuf));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 8, 9,
-		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);  
-    
-    /* permissions page */
-    vbox = gtk_vbox_new (FALSE, 4);
-    gtk_widget_show (vbox);
-    gtk_container_add (GTK_CONTAINER (notebook), vbox);
-    gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
-    
-    label = gtk_label_new (_("Permissions"));
-    gtk_widget_show (label);
-    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), pagenum), label);
-    pagenum++;
-
-    /* owner / group */
-    table = gtk_table_new (2, 2, FALSE);
-    gtk_widget_show (table);
-    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
-    gtk_table_set_row_spacings (GTK_TABLE (table), 2);
-    gtk_table_set_col_spacings (GTK_TABLE (table), 8);
-    
-    label = gtk_label_new (_("Owner:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-
-    entry = gtk_entry_new();
-    gtk_widget_show (entry);
-    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
-		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((pw = getpwuid(statbuf.st_uid)))
-      gtk_entry_set_text(GTK_ENTRY (entry), pw->pw_name);
-    else
-      gtk_entry_set_text(GTK_ENTRY (entry), (gpointer) statbuf.st_uid);
-    if (access (filename, W_OK) || (getuid() != 0))
-      gtk_widget_set_sensitive( GTK_WIDGET (entry), FALSE);
-
-
-    label = gtk_label_new (_("Group:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    entry = gtk_entry_new();
-    gtk_widget_show (entry);
-    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
-		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((gp = getgrgid(statbuf.st_gid)))
-      gtk_entry_set_text(GTK_ENTRY (entry), gp->gr_name);
-    else
-      gtk_entry_set_text(GTK_ENTRY (entry), (gpointer) statbuf.st_gid);
-    if (access (filename, W_OK) || (getuid() != 0))
-      gtk_widget_set_sensitive( GTK_WIDGET (entry), FALSE);
-
-    
-    hseparator = gtk_hseparator_new ();
-    gtk_widget_show (hseparator);
-    gtk_box_pack_start (GTK_BOX (vbox), hseparator, FALSE, TRUE, 0);
-    
-    /* permissions */
-    table = gtk_table_new (4, 5, TRUE);
-    gtk_widget_show (table);
-    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
-    gtk_table_set_row_spacings (GTK_TABLE (table), 2);
-    gtk_table_set_col_spacings (GTK_TABLE (table), 4);
-    if (access (filename, W_OK) || ((getuid() != statbuf.st_uid) && getuid() != 0))
-      gtk_widget_set_sensitive (GTK_WIDGET (table), FALSE);
-    
-    hbox = gtk_hbox_new (FALSE, 1);
-    gtk_widget_show (hbox);
-    gtk_table_attach (GTK_TABLE (table), hbox, 0, 1, 0, 1,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (GTK_FILL), 0, 0);
-    
-    priv->mode_label = label = gtk_label_new ("(0000)");
-    gtk_widget_show (label);
-    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
-
-    label = gtk_label_new (_("Read"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
-		      (GtkAttachOptions) (0),
-		      (GtkAttachOptions) (0), 0, 0);
-    
-    label = gtk_label_new (_("Write"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
-		      (GtkAttachOptions) (0),
-		      (GtkAttachOptions) (0), 0, 0);
-    
-    label = gtk_label_new (_("Exec"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 3, 4, 0, 1,
-		      (GtkAttachOptions) (0),
-		      (GtkAttachOptions) (0), 0, 0);
-    
-    label = gtk_label_new (_("Special"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 4, 5, 0, 1,
-		      (GtkAttachOptions) (0),
-		      (GtkAttachOptions) (0), 0, 0);
-    
-    
-    label = gtk_label_new (_("User:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    priv->mode_buttons[0] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 1, 2, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IRUSR)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-
-    priv->mode_buttons[1] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 2, 3, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IWUSR)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    priv->mode_buttons[2] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 3, 4, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IXUSR)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    priv->mode_buttons[3] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 4, 5, 1, 2,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_ISUID)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-
-
-    
-    label = gtk_label_new (_("Group:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    priv->mode_buttons[4] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 1, 2, 2, 3,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IRGRP)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    priv->mode_buttons[5] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 2, 3, 2, 3,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IWGRP)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    priv->mode_buttons[6] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 3, 4, 2, 3,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IXGRP)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    priv->mode_buttons[7] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 4, 5, 2, 3,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_ISGID)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    label = gtk_label_new (_("Other:"));
-    gtk_widget_show (label);
-    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
-    
-    priv->mode_buttons[8] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 1, 2, 3, 4,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IROTH)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-
-    priv->mode_buttons[9] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 2, 3, 3, 4,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IWOTH)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    priv->mode_buttons[10] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 3, 4, 3, 4,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_IXOTH)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-    
-    priv->mode_buttons[11] = togglebutton = gtk_toggle_button_new_with_label ("");
-    gtk_widget_show (togglebutton);
-    gtk_table_attach (GTK_TABLE (table), togglebutton, 4, 5, 3, 4,
-		      (GtkAttachOptions) (GTK_FILL),
-		      (GtkAttachOptions) (0), 0, 0);
-    if ((statbuf.st_mode & ~(S_IFMT)) & S_ISVTX)
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
-
-    for (i = 0; i < 12; i++)
-      gtk_signal_connect (GTK_OBJECT (priv->mode_buttons[i]), "toggled",
-                          GTK_SIGNAL_FUNC (gtk_file_selection_properties_update_mode), fs);
-    gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (priv->mode_buttons[0]));
-  }
-  /* global page */
-  vbox = gtk_vbox_new (FALSE, 0);
-  gtk_widget_show (vbox);
-  gtk_container_add (GTK_CONTAINER (notebook), vbox);
-
-  label = gtk_label_new (_("Global"));
-  gtk_widget_show (label);
-  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), pagenum), label);
-  pagenum++;
-
-  label = gtk_label_new (_("dialog preferances will go here"));
-  gtk_widget_show (label);
-  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
-
-  /* end of dialog guts */
-
-  /* buttons */
-  button = gtk_button_new_with_label (_("OK"));
-  //  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-  //		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
-  //		      (gpointer) fs);
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_file_mode_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  g_free (filename);
-  gtk_widget_show (dialog);
-}
-
-static gint
-gtk_file_selection_key_press (GtkWidget   *widget,
-			      GdkEventKey *event,
-			      gpointer     user_data)
-{
-	
-  GtkFileSelection *fs;
-  char *text;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  fs = GTK_FILE_SELECTION (user_data);
-
-  if (fs->saved_entry)
-    {
-      gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
-      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
-      g_free (fs->saved_entry);
-      fs->saved_entry = NULL;
-    }
-  if (event->keyval == GDK_Tab)
-    {
-      text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-
-      text = g_strdup (text);
-
-      gtk_file_selection_populate (fs, text, TRUE);
-
-      g_free (text);
-
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-
-      return TRUE;
-    }
-
-
-  return FALSE;
-}
-
-/*
-static void
-gtk_file_selection_home_button (GtkWidget *widget, gpointer data){
-  GList *list;
-	
-  GtkFileSelection *fs=data;
-
-  list = fs->next_history;
-  if (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-		
-  gtk_file_selection_populate (fs,"~/",FALSE);
-}
-*/
-static void
-gtk_file_selection_bookmark_button (GtkWidget *widget, 
-                                    GtkFileSelection *fs)
-{
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_FILE_SELECTION (fs));
-	 
-  gtk_menu_popup (GTK_MENU (fs->bookmark_menu), NULL, NULL, NULL, NULL, 
-		  0, 0);
-  
-}
-
-static void
-gtk_file_selection_up_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->next_history;
-  if (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-
-  gtk_file_selection_populate (fs, "../", FALSE); /*change directories. */
-		
-}
-
-static void
-gtk_file_selection_prev_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-  GList *first;
-  gchar *path;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->prev_history;
-
-  if (list && g_list_length(list) > 1)
-    {
-      first = list;            /* get first element */
-      list = list->next;       /* pop off current directory */
-
-      list->prev = NULL;       /* make this the new head. */
-  	
-      fs->prev_history = list; /* update prev_history list */
-      fs->next_history = g_list_prepend(fs->next_history,first->data); /* put it on next_history */
-  	
-      first->next = NULL;      /* orphan the old first node */
-      g_list_free (first);     /* free the node (data is now in use by next_history) */
-
-
-  	
-      path = g_malloc(strlen(list->data)+4); /* plenty of space */
-      strcpy(path,list->data);               /* get the 2nd path in the history */
-      strcat(path,"/");                      /* append a '/' */
-      gtk_file_selection_populate (fs, path, FALSE); /* change directories. */
-      g_free (path);
-    }
-}	
-
-static void
-gtk_file_selection_next_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-  GList *first;
-  gchar *path;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->next_history;
-
-  if (list && g_list_length(list) > 0)
-    {
-      first = list;            /*get first element*/
-      list = list->next;       /*pop off current directory*/
-      
-      if (list)
-	list->prev = NULL;
-      
-      fs->next_history = list;                       /*update prev_history list*/
-  	
-      path = g_malloc(strlen(first->data)+4);        /*plenty of space*/
-      strcpy(path,first->data);
-      strcat(path,"/");                              /*append a /   */
-      gtk_file_selection_populate (fs, path, FALSE); /*change directories.*/
-      g_free(path);
-  	
-      first->next = NULL;     /* orphan the old first node */
-      g_list_free (first);    /* free the node (data is now in use by next_history) */
-      
-    }
-}	
-
-void static
-gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_file_selection_populate (fs,"",FALSE);
-}
-
-static void
-gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-
-  if(fs->mask)
-    g_free (fs->mask);
-		
-  fs->mask = g_strdup(gtk_entry_get_text (GTK_ENTRY(GTK_COMBO(fs->mask_entry)->entry)));
-	
-  if (strlen(fs->mask) == 0)
-    {
-      g_free (fs->mask);
-      fs->mask = NULL;
-    }
-	
-  gtk_file_selection_refresh_button (widget,data);
-}
-
-static gint gtk_file_selection_files_list_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data){
-  GtkFileSelection *fs=data;
-  gchar *saved;
-  gchar key[2];
-
-//  g_print("Key event: %d\n",event->keyval);
-  //we need some sort of timeout.
-
-  //if the key is a normal character then
-  //add to our saved_entry1
-  //if it's backspace then remove one character
-  //otherwise let it through (and erase our buffer.
-
-  if(event->keyval > GDK_space && event->keyval <=  GDK_Korean_Won) {
-    key[1]=0;
-    key[0]=event->keyval;
-    saved=fs->saved_entry1;
-    if(fs->saved_entry1){
-      fs->saved_entry1=g_strconcat(saved,key,NULL);
-      g_free(saved);
-    }else{
-      fs->saved_entry1=g_strdup(key);
-    }
-    g_print("complete: %s\n",fs->saved_entry1);
-    /*gtk_label_set_text(GTK_LABEL(fs->completion_label), fs->saved_entry1); */
-
-    saved=g_strdup(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
-    gtk_file_selection_complete(fs,fs->saved_entry1);
-    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),saved);
-    g_free(saved);
-  }else if (event->keyval ==  GDK_BackSpace) {
-    if(strlen(fs->saved_entry1)){
-      fs->saved_entry1[strlen(fs->saved_entry1)-1]=0;
-      g_print("complete: %s\n",fs->saved_entry1);
-      /*gtk_label_set_text(GTK_LABEL(fs->completion_label),fs->saved_entry1); */
-      saved=g_strdup(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
-      gtk_file_selection_complete(fs,fs->saved_entry1);
-      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),saved);
-      g_free(saved);
-    }
-  }else if (event->keyval == GDK_Tab) {
-    saved=g_strdup(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
-    gtk_file_selection_populate(fs,fs->saved_entry1,TRUE);
-    g_free(fs->saved_entry1);
-    fs->saved_entry1=gtk_entry_get_text(GTK_ENTRY(fs->selection_entry));
-    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),saved);
-    g_free(saved);
-
-    g_print("complete: %s\n",fs->saved_entry1);
-    /* gtk_label_set_text(GTK_LABEL(fs->completion_label),fs->saved_entry1);*/
-
-    gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-  }else {
-    if(fs->saved_entry1){
-      g_free(fs->saved_entry1);
-      fs->saved_entry1=NULL;
-    }
-    /* gtk_label_set_text(GTK_LABEL(fs->completion_label)," "); */
-  }
-
-  return TRUE;
-}
-
-
-static gint gtk_file_selection_mask_entry_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
-{
-  GtkEntry *entry=(GtkEntry *)widget;
-  GtkFileSelection *fs=data;
-	
-  g_return_val_if_fail (fs != NULL,FALSE);
-  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
-	
-
-  if (event->keyval == GDK_Return || event->keyval == GDK_Tab)
-    {
-      if(fs->mask)
-        g_free(fs->mask);
-
-      fs->mask=g_strdup(gtk_entry_get_text(entry));
-      gtk_file_selection_refresh_button(widget,fs);
-
-      if (event->keyval == GDK_Return)
-        gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-      return TRUE;
-    }
-  else
-    {
-      return FALSE;
-    }
-}
-
-static gint gtk_file_selection_mask_entry_button_callback (GtkWidget *widget, GdkEventButton *event, gpointer data)
-{
-  GtkFileSelection *fs = data;
-		
-  if(fs->mask)
-    g_free(fs->mask);
-
-  fs->mask=g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(fs->mask_entry)->entry)));
-  gtk_file_selection_refresh_button(widget,fs);
-
-  return TRUE;
-
-}
-
-static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
-								  GdkEventKey *event,
-								  gpointer user_data)
-{
-  /*
-  g_print("Key pressed! \n");
-  */
-	
-  return TRUE;
-}
-
-static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
-								GdkEventButton *event,
-								gpointer user_data)
-{
-
-  GtkFileSelection *fs = user_data;
-  GList *list;
-  gchar *path;
-		
-  list = fs->next_history;
-  if(list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-			
-  path = g_malloc(strlen(gtk_entry_get_text(GTK_ENTRY (((GtkCombo *)fs->history_combo)->entry)))+4);
-  strcpy (path,gtk_entry_get_text(GTK_ENTRY( ((GtkCombo *)fs->history_combo)->entry)));
-  strcat (path,"/");
-	
-  gtk_file_selection_populate (fs,path,TRUE);
-	
-  g_free (path);
-
-  return TRUE;
-}
-
-static gboolean
-gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
-{
-  GtkEntry *entry=(GtkEntry *)widget;
-  GtkFileSelection *fs=data;
-  GList *list;
-  gchar *path;
-	
-  g_return_val_if_fail (fs != NULL,FALSE);
-  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
-	
-
-  if (event->keyval == GDK_Return)
-    {
-      list = fs->next_history;
-      if (list)
-	{
-	  g_free (list->data);
-	  list = list->next;
-	}
-      g_list_free (fs->next_history);
-      fs->next_history = NULL;
-      
-      path = g_malloc(strlen(gtk_entry_get_text(entry))+4);
-      strcpy (path,gtk_entry_get_text(entry));
-      strcat (path,"/");
-      gtk_file_selection_populate (fs,path,TRUE);
-      g_free (path);
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-      return TRUE;
-    }
-  else
-    {
-      return FALSE;
-    }
-
-}
-
-
-static void gtk_file_selection_bookmark_callback (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  BookmarkMenuStruct *item;
-  GList *list;
-	
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-//g_print ("Callback\n");
-  list = fs->bookmark_list;
-  while(list) {
-    item = list->data;
-    if (item->menu_item == widget) {
-      if(strcmp(item->path,"./")) {
-        gtk_file_selection_populate (fs, item->path, FALSE);
-      }
-      break;
-    }
-    list=list->next;
-  } 
-}
-
-static void
-gtk_file_selection_update_history_menu (GtkFileSelection *fs,
-					gchar *current_directory)
-{
-  gchar *current_dir;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  g_return_if_fail (current_directory != NULL);
-  
-  current_dir = g_strdup (current_directory);
-
-  if(fs->prev_history)
-    {
-      if (strcmp((fs->prev_history)->data,current_dir))
-	{ /*if this item isn't on the top of the list */
-	  fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
-	}
-    } else {
-      fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
-    }
-  
-  gtk_combo_set_popdown_strings (GTK_COMBO (fs->history_combo),fs->prev_history);
-  
-  g_free (current_dir);
-}
-
-static void
-gtk_file_selection_file_button (GtkWidget *widget,
-			       gint row, 
-			       gint column, 
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-  
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = user_data;
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  gtk_clist_get_text (GTK_CLIST (fs->file_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (fs->saved_entry)
-      {
-        gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
-        gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
-        g_free (fs->saved_entry);
-        fs->saved_entry = NULL;
-      }
-      if(fs->saved_entry1){
-        g_free(fs->saved_entry1);
-        fs->saved_entry1=NULL;
-      }
-      /* gtk_label_set_text(GTK_LABEL(fs->completion_label)," "); */
-
-
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  case GDK_2BUTTON_PRESS:
-	    gtk_button_clicked (GTK_BUTTON (fs->ok_button));
-	    break;
-	    
-	  default:
-/*	
-	    if (bevent->button && GDK_BUTTON2_MASK)
-	      {
-	        g_print("Right click! -- %d\n",bevent->button);
-	      }
-	      else
-	      {
-	      */
-	
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-	      /*}*/
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_dir_button (GtkWidget *widget,
-			       gint row, 
-			       gint column, 
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GList *list;
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = GTK_FILE_SELECTION (user_data);
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  case GDK_2BUTTON_PRESS:
-	    list = fs->next_history;
-	    if (list)
-	      {
-		g_free (list->data);
-		list = list->next;
-	      }
-	    g_list_free (fs->next_history);
-	    fs->next_history = NULL;
-	
-	    gtk_file_selection_populate (fs, filename, FALSE);
-	    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
-	    g_free (fs->saved_entry);
-	    fs->saved_entry = NULL;
-	    break;
-	    
-	  default:
-	    /* here we need to add the "filename" to the beginning of what's already
-	       in the entry.  Save what's in the entry, then restore it on the double click
-	    */
-	    if (fs->saved_entry) g_free (fs->saved_entry);
-	    fs->saved_entry=g_strdup(gtk_entry_get_text(GTK_ENTRY (fs->selection_entry)));
-	
-	    temp=g_strconcat(filename,fs->saved_entry,NULL);
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), temp);
-	    g_free (temp);
-	
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-      
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_undir_button (GtkWidget *widget,
-			       gint row,
-			       gint column,
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = GTK_FILE_SELECTION (user_data);
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  default:
-	    /* here we need to add the "filename" to the beginning of what's already
-	       in the entry.  Save what's in the entry, then restore it on the double click
-	    */
-	    if (fs->saved_entry)
-	      {
-	        gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),fs->saved_entry);
-		g_free (fs->saved_entry);
-		fs->saved_entry = NULL;
-	      }
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename); //?????
-
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_populate (GtkFileSelection *fs,
-			     gchar            *rel_path,
-			     gint              try_complete)
-{
-  CompletionState *cmpl_state;
-  PossibleCompletion* poss;
-  gchar* filename;
-  gint row;
-  gchar* rem_path = rel_path;
-  gchar* sel_text;
-  gchar* text[2];
-  gint did_recurse = FALSE;
-  gint possible_count = 0;
-  gint selection_index = -1;
-  gint file_list_width;
-  gint dir_list_width;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
-
-  if (!cmpl_state_okay (cmpl_state))
-    {
-      /* Something went wrong. */
-      gtk_file_selection_abort (fs);
-      return;
-    }
-
-  g_assert (cmpl_state->reference_dir);
-
-  gtk_clist_freeze (GTK_CLIST (fs->dir_list));
-  gtk_clist_clear (GTK_CLIST (fs->dir_list));
-  gtk_clist_freeze (GTK_CLIST (fs->file_list));
-  gtk_clist_clear (GTK_CLIST (fs->file_list));
-
-  /* Set the dir_list to include ./ and ../ */
-  /* Actually, no let's not.
-  text[1] = NULL;
-  text[0] = "./";
-  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-  */
-
-  text[0] = "../";  //Do we need ..?
-  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-
-  /*reset the max widths of the lists*/
-  dir_list_width = gdk_string_width(fs->dir_list->style->font,"../");
-  gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,dir_list_width);
-  file_list_width = 1;
-  gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,file_list_width);
-
-  while (poss)
-    {
-      if (cmpl_is_a_completion (poss))
-  	{
-	  possible_count += 1;
-	  
-	  filename = cmpl_this_completion (poss);
-
-	  text[0] = filename;
-	  
-	  if (cmpl_is_directory (poss))
-	    {
-	      if (strcmp (filename, "./") != 0 &&
-		  strcmp (filename, "../") != 0)
-		{
-		  int width = gdk_string_width(fs->dir_list->style->font,
-					       filename);
-		  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-		  if(width > dir_list_width)
-		    {
-		      dir_list_width = width;
-		      gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,
-						 width);
-		    }
-		}
-	    }
-	  else
-	    {
-	      if(fs->mask)
-		{
-		  if (gtk_file_selection_match_mask(filename,fs->mask))
-		    {
-		      int width = gdk_string_width(fs->file_list->style->font,
-						   filename);
-		      row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
-		      if(width > file_list_width)
-		        {
-		          file_list_width = width;
-		          gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
-						     width);
-		        }
-		    }
-		}
-	      else
-		{
-		  int width = gdk_string_width(fs->file_list->style->font,
-					       filename);
-		  row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
-		  if(width > file_list_width)
-		    {
-		      file_list_width = width;
-		      gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
-						 width);
-		    }
-		}
-	    }
-	}
-
-      poss = cmpl_next_completion (cmpl_state);
-    }
-
-  gtk_clist_thaw (GTK_CLIST (fs->dir_list));
-  gtk_clist_thaw (GTK_CLIST (fs->file_list));
-
-  /* File lists are set. */
-
-  g_assert (cmpl_state->reference_dir);
-
-  if (try_complete)
-    {
-
-      /* User is trying to complete filenames, so advance the user's input
-       * string to the updated_text, which is the common leading substring
-       * of all possible completions, and if its a directory attempt
-       * attempt completions in it. */
-
-      if (cmpl_updated_text (cmpl_state)[0])
-        {
-
-          if (cmpl_updated_dir (cmpl_state))
-            {
-	      gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
-
-              did_recurse = TRUE;
-
-              gtk_file_selection_populate (fs, dir_name, TRUE);
-
-              g_free (dir_name);
-            }
-          else
-            {
-	      if (fs->selection_entry)
-		      gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
-					  cmpl_updated_text (cmpl_state));
-            }
-        }
-      else
-        {
-          selection_index = cmpl_last_valid_char (cmpl_state) -
-                            (strlen (rel_path) - strlen (rem_path));
-	  if (fs->selection_entry)
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
-        }
-    }
-  else
-    {
-      if (fs->selection_entry)
-      /* Here we need to take the old filename and keep it!*/
-	/*gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");*/
-	;
-    }
-
-  if (!did_recurse)
-    {
-      if (fs->selection_entry)
-	gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
-
-      if (fs->selection_entry)
-	{
-	  sel_text = g_strconcat (_("Selection: "),
-				  cmpl_reference_position (cmpl_state),
-				  NULL);
-
-/*
-		gtk_label_set_text (GTK_LABEL (fs->selection_text), sel_text);
-*/
-		g_free (sel_text);
-	}
-
-  gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state));
-
-    }
-}
-
-static void
-gtk_file_selection_abort (GtkFileSelection *fs)
-{
-  gchar err_buf[256];
-
-  sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
-
-  /*  BEEP gdk_beep();  */
-
-/*
-  if (fs->selection_entry)
-    gtk_label_set_text (GTK_LABEL (fs->selection_text), err_buf);
-*/
-}
-
-/**********************************************************************/
-/*			  External Interface                          */
-/**********************************************************************/
-
-/* The four completion state selectors
- */
-static gchar*
-cmpl_updated_text (CompletionState* cmpl_state)
-{
-  return cmpl_state->updated_text;
-}
-
-static gint
-cmpl_updated_dir (CompletionState* cmpl_state)
-{
-  return cmpl_state->re_complete;
-}
-
-static gchar*
-cmpl_reference_position (CompletionState* cmpl_state)
-{
-  return cmpl_state->reference_dir->fullname;
-}
-
-static gint
-cmpl_last_valid_char (CompletionState* cmpl_state)
-{
-  return cmpl_state->last_valid_char;
-}
-
-static gchar*
-cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state)
-{
-  static char nothing[2] = "";
-
-  if (!cmpl_state_okay (cmpl_state))
-    {
-      return nothing;
-    }
-  else if (text[0] == '/')
-    {
-      strcpy (cmpl_state->updated_text, text);
-    }
-  else if (text[0] == '~')
-    {
-      CompletionDir* dir;
-      char* slash;
-
-      dir = open_user_dir (text, cmpl_state);
-
-      if (!dir)
-	{
-	  /* spencer says just return ~something, so
-	   * for now just do it. */
-	  strcpy (cmpl_state->updated_text, text);
-	}
-      else
-	{
-
-	  strcpy (cmpl_state->updated_text, dir->fullname);
-
-	  slash = strchr (text, '/');
-
-	  if (slash)
-	    strcat (cmpl_state->updated_text, slash);
-	}
-    }
-  else
-    {
-      strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
-      if (strcmp (cmpl_state->reference_dir->fullname, "/") != 0)
-	strcat (cmpl_state->updated_text, "/");
-      strcat (cmpl_state->updated_text, text);
-    }
-
-  return cmpl_state->updated_text;
-}
-
-/* The three completion selectors
- */
-static gchar*
-cmpl_this_completion (PossibleCompletion* pc)
-{
-  return pc->text;
-}
-
-static gint
-cmpl_is_directory (PossibleCompletion* pc)
-{
-  return pc->is_directory;
-}
-
-static gint
-cmpl_is_a_completion (PossibleCompletion* pc)
-{
-  return pc->is_a_completion;
-}
-
-/**********************************************************************/
-/*	                 Construction, deletion                       */
-/**********************************************************************/
-
-static CompletionState*
-cmpl_init_state (void)
-{
-  gchar getcwd_buf[2*MAXPATHLEN];
-  CompletionState *new_state;
-
-  new_state = g_new (CompletionState, 1);
-
-  /* We don't use getcwd() on SUNOS, because, it does a popen("pwd")
-   * and, if that wasn't bad enough, hangs in doing so.
-   */
-#if defined(sun) && !defined(__SVR4)
-  if (!getwd (getcwd_buf))
-#else    
-  if (!getcwd (getcwd_buf, MAXPATHLEN))
-#endif    
-    {
-      /* Oh joy, we can't get the current directory. Um..., we should have
-       * a root directory, right? Right? (Probably not portable to non-Unix)
-       */
-      strcpy (getcwd_buf, "/");
-    }
-
-tryagain:
-
-  new_state->reference_dir = NULL;
-  new_state->completion_dir = NULL;
-  new_state->active_completion_dir = NULL;
-  new_state->directory_storage = NULL;
-  new_state->directory_sent_storage = NULL;
-  new_state->last_valid_char = 0;
-  new_state->updated_text = g_new (gchar, MAXPATHLEN);
-  new_state->updated_text_alloc = MAXPATHLEN;
-  new_state->the_completion.text = g_new (gchar, MAXPATHLEN);
-  new_state->the_completion.text_alloc = MAXPATHLEN;
-  new_state->user_dir_name_buffer = NULL;
-  new_state->user_directories = NULL;
-
-  new_state->reference_dir =  open_dir (getcwd_buf, new_state);
-
-  if (!new_state->reference_dir)
-    {
-      /* Directories changing from underneath us, grumble */
-      strcpy (getcwd_buf, "/");
-      goto tryagain;
-    }
-
-  return new_state;
-}
-
-static void
-cmpl_free_dir_list(GList* dp0)
-{
-  GList *dp = dp0;
-
-  while (dp) {
-    free_dir (dp->data);
-    dp = dp->next;
-  }
-
-  g_list_free(dp0);
-}
-
-static void
-cmpl_free_dir_sent_list(GList* dp0)
-{
-  GList *dp = dp0;
-
-  while (dp) {
-    free_dir_sent (dp->data);
-    dp = dp->next;
-  }
-
-  g_list_free(dp0);
-}
-
-static void
-cmpl_free_state (CompletionState* cmpl_state)
-{
-  cmpl_free_dir_list (cmpl_state->directory_storage);
-  cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage);
-
-  if (cmpl_state->user_dir_name_buffer)
-    g_free (cmpl_state->user_dir_name_buffer);
-  if (cmpl_state->user_directories)
-    g_free (cmpl_state->user_directories);
-  if (cmpl_state->the_completion.text)
-    g_free (cmpl_state->the_completion.text);
-  if (cmpl_state->updated_text)
-    g_free (cmpl_state->updated_text);
-
-  g_free (cmpl_state);
-}
-
-static void
-free_dir(CompletionDir* dir)
-{
-  g_free(dir->fullname);
-  g_free(dir);
-}
-
-static void
-free_dir_sent(CompletionDirSent* sent)
-{
-  g_free(sent->name_buffer);
-  g_free(sent->entries);
-  g_free(sent);
-}
-
-static void
-prune_memory_usage(CompletionState *cmpl_state)
-{
-  GList* cdsl = cmpl_state->directory_sent_storage;
-  GList* cdl = cmpl_state->directory_storage;
-  GList* cdl0 = cdl;
-  gint len = 0;
-
-  for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1)
-    cdsl = cdsl->next;
-
-  if (cdsl) {
-    cmpl_free_dir_sent_list(cdsl->next);
-    cdsl->next = NULL;
-  }
-
-  cmpl_state->directory_storage = NULL;
-  while (cdl) {
-    if (cdl->data == cmpl_state->reference_dir)
-      cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data);
-    else
-      free_dir (cdl->data);
-    cdl = cdl->next;
-  }
-
-  g_list_free(cdl0);
-}
-
-/**********************************************************************/
-/*                        The main entrances.                         */
-/**********************************************************************/
-
-static PossibleCompletion*
-cmpl_completion_matches (gchar* text_to_complete,
-			 gchar** remaining_text,
-			 CompletionState* cmpl_state)
-{
-  gchar* first_slash;
-  PossibleCompletion *poss;
-
-  prune_memory_usage(cmpl_state);
-
-  g_assert (text_to_complete != NULL);
-
-  cmpl_state->user_completion_index = -1;
-  cmpl_state->last_completion_text = text_to_complete;
-  cmpl_state->the_completion.text[0] = 0;
-  cmpl_state->last_valid_char = 0;
-  cmpl_state->updated_text_len = -1;
-  cmpl_state->updated_text[0] = 0;
-  cmpl_state->re_complete = FALSE;
-
-  first_slash = strchr (text_to_complete, '/');
-
-  if (text_to_complete[0] == '~' && !first_slash)
-    {
-      /* Text starts with ~ and there is no slash, show all the
-       * home directory completions.
-       */
-      poss = attempt_homedir_completion (text_to_complete, cmpl_state);
-
-      update_cmpl(poss, cmpl_state);
-
-      return poss;
-    }
-
-  cmpl_state->reference_dir =
-    open_ref_dir (text_to_complete, remaining_text, cmpl_state);
-
-  if(!cmpl_state->reference_dir)
-    return NULL;
-
-  cmpl_state->completion_dir =
-    find_completion_dir (*remaining_text, remaining_text, cmpl_state);
-
-  cmpl_state->last_valid_char = *remaining_text - text_to_complete;
-
-  if(!cmpl_state->completion_dir)
-    return NULL;
-
-  cmpl_state->completion_dir->cmpl_index = -1;
-  cmpl_state->completion_dir->cmpl_parent = NULL;
-  cmpl_state->completion_dir->cmpl_text = *remaining_text;
-
-  cmpl_state->active_completion_dir = cmpl_state->completion_dir;
-
-  cmpl_state->reference_dir = cmpl_state->completion_dir;
-
-  poss = attempt_file_completion(cmpl_state);
-
-  update_cmpl(poss, cmpl_state);
-
-  return poss;
-}
-
-static PossibleCompletion*
-cmpl_next_completion (CompletionState* cmpl_state)
-{
-  PossibleCompletion* poss = NULL;
-
-  cmpl_state->the_completion.text[0] = 0;
-
-  if(cmpl_state->user_completion_index >= 0)
-    poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state);
-  else
-    poss = attempt_file_completion(cmpl_state);
-
-  update_cmpl(poss, cmpl_state);
-
-  return poss;
-}
-
-/**********************************************************************/
-/*			 Directory Operations                         */
-/**********************************************************************/
-
-/* Open the directory where completion will begin from, if possible. */
-static CompletionDir*
-open_ref_dir(gchar* text_to_complete,
-	     gchar** remaining_text,
-	     CompletionState* cmpl_state)
-{
-  gchar* first_slash;
-  CompletionDir *new_dir;
-
-  first_slash = strchr(text_to_complete, '/');
-
-  if (text_to_complete[0] == '~')
-    {
-      new_dir = open_user_dir(text_to_complete, cmpl_state);
-
-      if(new_dir)
-	{
-	  if(first_slash)
-	    *remaining_text = first_slash + 1;
-	  else
-	    *remaining_text = text_to_complete + strlen(text_to_complete);
-	}
-      else
-	{
-	  return NULL;
-	}
-    }
-  else if (text_to_complete[0] == '/' || !cmpl_state->reference_dir)
-    {
-      gchar *tmp = g_strdup(text_to_complete);
-      gchar *p;
-
-      p = tmp;
-      while (*p && *p != '*' && *p != '?')
-	p++;
-
-      *p = '\0';
-      p = strrchr(tmp, '/');
-      if (p)
-	{
-	  if (p == tmp)
-	    p++;
-      
-	  *p = '\0';
-
-	  new_dir = open_dir(tmp, cmpl_state);
-
-	  if(new_dir)
-	    *remaining_text = text_to_complete + 
-	      ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
-	}
-      else
-	{
-	  /* If no possible candidates, use the cwd */
-	  gchar *curdir = g_get_current_dir ();
-	  
-	  new_dir = open_dir(curdir, cmpl_state);
-
-	  if (new_dir)
-	    *remaining_text = text_to_complete;
-
-	  g_free (curdir);
-	}
-
-      g_free (tmp);
-    }
-  else
-    {
-      *remaining_text = text_to_complete;
-
-      new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state);
-    }
-
-  if(new_dir)
-    {
-      new_dir->cmpl_index = -1;
-      new_dir->cmpl_parent = NULL;
-    }
-
-  return new_dir;
-}
-
-/* open a directory by user name */
-static CompletionDir*
-open_user_dir(gchar* text_to_complete,
-	      CompletionState *cmpl_state)
-{
-  gchar *first_slash;
-  gint cmp_len;
-
-  g_assert(text_to_complete && text_to_complete[0] == '~');
-
-  first_slash = strchr(text_to_complete, '/');
-
-  if (first_slash)
-    cmp_len = first_slash - text_to_complete - 1;
-  else
-    cmp_len = strlen(text_to_complete + 1);
-
-  if(!cmp_len)
-    {
-      /* ~/ */
-      gchar *homedir = g_get_home_dir ();
-
-      if (homedir)
-	return open_dir(homedir, cmpl_state);
-      else
-	return NULL;
-    }
-  else
-    {
-      /* ~user/ */
-      char* copy = g_new(char, cmp_len + 1);
-      struct passwd *pwd;
-      strncpy(copy, text_to_complete + 1, cmp_len);
-      copy[cmp_len] = 0;
-      pwd = getpwnam(copy);
-      g_free(copy);
-      if (!pwd)
-	{
-	  cmpl_errno = errno;
-	  return NULL;
-	}
-
-      return open_dir(pwd->pw_dir, cmpl_state);
-    }
-}
-
-/* open a directory relative the the current relative directory */
-static CompletionDir*
-open_relative_dir(gchar* dir_name,
-		  CompletionDir* dir,
-		  CompletionState *cmpl_state)
-{
-  gchar path_buf[2*MAXPATHLEN];
-
-  if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN)
-    {
-      cmpl_errno = CMPL_ERRNO_TOO_LONG;
-      return NULL;
-    }
-
-  strcpy(path_buf, dir->fullname);
-
-  if(dir->fullname_len > 1)
-    {
-      path_buf[dir->fullname_len] = '/';
-      strcpy(path_buf + dir->fullname_len + 1, dir_name);
-    }
-  else
-    {
-      strcpy(path_buf + dir->fullname_len, dir_name);
-    }
-
-  return open_dir(path_buf, cmpl_state);
-}
-
-/* after the cache lookup fails, really open a new directory */
-static CompletionDirSent*
-open_new_dir(gchar* dir_name, struct stat* sbuf, gboolean stat_subdirs)
-{
-  CompletionDirSent* sent;
-  DIR* directory;
-  gchar *buffer_ptr;
-  struct dirent *dirent_ptr;
-  gint buffer_size = 0;
-  gint entry_count = 0;
-  gint i;
-  struct stat ent_sbuf;
-  char path_buf[MAXPATHLEN*2];
-  gint path_buf_len;
-
-  sent = g_new(CompletionDirSent, 1);
-  sent->mtime = sbuf->st_mtime;
-  sent->inode = sbuf->st_ino;
-  sent->device = sbuf->st_dev;
-
-  path_buf_len = strlen(dir_name);
-
-  if (path_buf_len > MAXPATHLEN)
-    {
-      cmpl_errno = CMPL_ERRNO_TOO_LONG;
-      return NULL;
-    }
-
-  strcpy(path_buf, dir_name);
-
-  directory = opendir(dir_name);
-
-  if(!directory)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  while((dirent_ptr = readdir(directory)) != NULL)
-    {
-      int entry_len = strlen(dirent_ptr->d_name);
-      buffer_size += entry_len + 1;
-      entry_count += 1;
-
-      if(path_buf_len + entry_len + 2 >= MAXPATHLEN)
-	{
-	  cmpl_errno = CMPL_ERRNO_TOO_LONG;
- 	  closedir(directory);
-	  return NULL;
-	}
-    }
-
-  sent->name_buffer = g_new(gchar, buffer_size);
-  sent->entries = g_new(CompletionDirEntry, entry_count);
-  sent->entry_count = entry_count;
-
-  buffer_ptr = sent->name_buffer;
-
-  rewinddir(directory);
-
-  for(i = 0; i < entry_count; i += 1)
-    {
-      dirent_ptr = readdir(directory);
-
-      if(!dirent_ptr)
-	{
-	  cmpl_errno = errno;
-	  closedir(directory);
-	  return NULL;
-	}
-
-      strcpy(buffer_ptr, dirent_ptr->d_name);
-      sent->entries[i].entry_name = buffer_ptr;
-      buffer_ptr += strlen(dirent_ptr->d_name);
-      *buffer_ptr = 0;
-      buffer_ptr += 1;
-
-      path_buf[path_buf_len] = '/';
-      strcpy(path_buf + path_buf_len + 1, dirent_ptr->d_name);
-
-      if (stat_subdirs)
-	{
-	  if(stat(path_buf, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
-	    sent->entries[i].is_dir = 1;
-	  else
-	    /* stat may fail, and we don't mind, since it could be a
-	     * dangling symlink. */
-	    sent->entries[i].is_dir = 0;
-	}
-      else
-	sent->entries[i].is_dir = 1;
-    }
-
-  qsort(sent->entries, sent->entry_count, sizeof(CompletionDirEntry), compare_cmpl_dir);
-
-  closedir(directory);
-
-  return sent;
-}
-
-static gboolean
-check_dir(gchar *dir_name, struct stat *result, gboolean *stat_subdirs)
-{
-  /* A list of directories that we know only contain other directories.
-   * Trying to stat every file in these directories would be very
-   * expensive.
-   */
-
-  static struct {
-    gchar *name;
-    gboolean present;
-    struct stat statbuf;
-  } no_stat_dirs[] = {
-    { "/afs", FALSE, { 0 } },
-    { "/net", FALSE, { 0 } }
-  };
-
-  static const gint n_no_stat_dirs = sizeof(no_stat_dirs) / sizeof(no_stat_dirs[0]);
-  static gboolean initialized = FALSE;
-
-  gint i;
-
-  if (!initialized)
-    {
-      initialized = TRUE;
-      for (i = 0; i < n_no_stat_dirs; i++)
-	{
-	  if (stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
-	    no_stat_dirs[i].present = TRUE;
-	}
-    }
-
-  if(stat(dir_name, result) < 0)
-    {
-      cmpl_errno = errno;
-      return FALSE;
-    }
-
-  *stat_subdirs = TRUE;
-  for (i=0; i<n_no_stat_dirs; i++)
-    {
-      if (no_stat_dirs[i].present &&
-	  (no_stat_dirs[i].statbuf.st_dev == result->st_dev) &&
-	  (no_stat_dirs[i].statbuf.st_ino == result->st_ino))
-	{
-	  *stat_subdirs = FALSE;
-	  break;
-	}
-    }
-
-  return TRUE;
-}
-
-/* open a directory by absolute pathname */
-static CompletionDir*
-open_dir(gchar* dir_name, CompletionState* cmpl_state)
-{
-  struct stat sbuf;
-  gboolean stat_subdirs;
-  CompletionDirSent *sent;
-  GList* cdsl;
-
-  if (!check_dir (dir_name, &sbuf, &stat_subdirs))
-    return NULL;
-
-  cdsl = cmpl_state->directory_sent_storage;
-
-  while (cdsl)
-    {
-      sent = cdsl->data;
-
-      if(sent->inode == sbuf.st_ino &&
-	 sent->mtime == sbuf.st_mtime &&
-	 sent->device == sbuf.st_dev)
-	return attach_dir(sent, dir_name, cmpl_state);
-
-      cdsl = cdsl->next;
-    }
-
-  sent = open_new_dir(dir_name, &sbuf, stat_subdirs);
-
-  if (sent) {
-    cmpl_state->directory_sent_storage =
-      g_list_prepend(cmpl_state->directory_sent_storage, sent);
-
-    return attach_dir(sent, dir_name, cmpl_state);
-  }
-
-  return NULL;
-}
-
-static CompletionDir*
-attach_dir(CompletionDirSent* sent, gchar* dir_name, CompletionState *cmpl_state)
-{
-  CompletionDir* new_dir;
-
-  new_dir = g_new(CompletionDir, 1);
-
-  cmpl_state->directory_storage =
-    g_list_prepend(cmpl_state->directory_storage, new_dir);
-
-  new_dir->sent = sent;
-  new_dir->fullname = g_strdup(dir_name);
-  new_dir->fullname_len = strlen(dir_name);
-
-  return new_dir;
-}
-
-static gint
-correct_dir_fullname(CompletionDir* cmpl_dir)
-{
-  gint length = strlen(cmpl_dir->fullname);
-  struct stat sbuf;
-
-  if (strcmp(cmpl_dir->fullname + length - 2, "/.") == 0)
-    {
-      if (length == 2) 
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	} else {
-	  cmpl_dir->fullname[length - 2] = 0;
-	}
-    }
-  else if (strcmp(cmpl_dir->fullname + length - 3, "/./") == 0)
-    cmpl_dir->fullname[length - 2] = 0;
-  else if (strcmp(cmpl_dir->fullname + length - 3, "/..") == 0)
-    {
-      if(length == 3)
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	}
-
-      if(stat(cmpl_dir->fullname, &sbuf) < 0)
-	{
-	  cmpl_errno = errno;
-	  return FALSE;
-	}
-
-      cmpl_dir->fullname[length - 2] = 0;
-
-      if(!correct_parent(cmpl_dir, &sbuf))
-	return FALSE;
-    }
-  else if (strcmp(cmpl_dir->fullname + length - 4, "/../") == 0)
-    {
-      if(length == 4)
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	}
-
-      if(stat(cmpl_dir->fullname, &sbuf) < 0)
-	{
-	  cmpl_errno = errno;
-	  return FALSE;
-	}
-
-      cmpl_dir->fullname[length - 3] = 0;
-
-      if(!correct_parent(cmpl_dir, &sbuf))
-	return FALSE;
-    }
-
-  cmpl_dir->fullname_len = strlen(cmpl_dir->fullname);
-
-  return TRUE;
-}
-
-static gint
-correct_parent(CompletionDir* cmpl_dir, struct stat *sbuf)
-{
-  struct stat parbuf;
-  gchar *last_slash;
-  gchar *new_name;
-  gchar c = 0;
-
-  last_slash = strrchr(cmpl_dir->fullname, '/');
-
-  g_assert(last_slash);
-
-  if(last_slash != cmpl_dir->fullname)
-    { /* last_slash[0] = 0; */ }
-  else
-    {
-      c = last_slash[1];
-      last_slash[1] = 0;
-    }
-
-  if (stat(cmpl_dir->fullname, &parbuf) < 0)
-    {
-      cmpl_errno = errno;
-      return FALSE;
-    }
-
-  if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
-    /* it wasn't a link */
-    return TRUE;
-
-  if(c)
-    last_slash[1] = c;
-  /* else
-    last_slash[0] = '/'; */
-
-  /* it was a link, have to figure it out the hard way */
-
-  new_name = find_parent_dir_fullname(cmpl_dir->fullname);
-
-  if (!new_name)
-    return FALSE;
-
-  g_free(cmpl_dir->fullname);
-
-  cmpl_dir->fullname = new_name;
-
-  return TRUE;
-}
-
-static gchar*
-find_parent_dir_fullname(gchar* dirname)
-{
-  gchar buffer[MAXPATHLEN];
-  gchar buffer2[MAXPATHLEN];
-
-#if defined(sun) && !defined(__SVR4)
-  if(!getwd(buffer))
-#else
-  if(!getcwd(buffer, MAXPATHLEN))
-#endif    
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  if(chdir(dirname) != 0 || chdir("..") != 0)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-#if defined(sun) && !defined(__SVR4)
-  if(!getwd(buffer2))
-#else
-  if(!getcwd(buffer2, MAXPATHLEN))
-#endif
-    {
-      chdir(buffer);
-      cmpl_errno = errno;
-
-      return NULL;
-    }
-
-  if(chdir(buffer) != 0)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  return g_strdup(buffer2);
-}
-
-/**********************************************************************/
-/*                        Completion Operations                       */
-/**********************************************************************/
-
-static PossibleCompletion*
-attempt_homedir_completion(gchar* text_to_complete,
-			   CompletionState *cmpl_state)
-{
-  gint index, length;
-
-  if (!cmpl_state->user_dir_name_buffer &&
-      !get_pwdb(cmpl_state))
-    return NULL;
-  length = strlen(text_to_complete) - 1;
-
-  cmpl_state->user_completion_index += 1;
-
-  while(cmpl_state->user_completion_index < cmpl_state->user_directories_len)
-    {
-      index = first_diff_index(text_to_complete + 1,
-			       cmpl_state->user_directories
-			       [cmpl_state->user_completion_index].login);
-
-      switch(index)
-	{
-	case PATTERN_MATCH:
-	  break;
-	default:
-	  if(cmpl_state->last_valid_char < (index + 1))
-	    cmpl_state->last_valid_char = index + 1;
-	  cmpl_state->user_completion_index += 1;
-	  continue;
-	}
-
-      cmpl_state->the_completion.is_a_completion = 1;
-      cmpl_state->the_completion.is_directory = 1;
-
-      append_completion_text("~", cmpl_state);
-
-      append_completion_text(cmpl_state->
-			      user_directories[cmpl_state->user_completion_index].login,
-			     cmpl_state);
-
-      return append_completion_text("/", cmpl_state);
-    }
-
-  if(text_to_complete[1] ||
-     cmpl_state->user_completion_index > cmpl_state->user_directories_len)
-    {
-      cmpl_state->user_completion_index = -1;
-      return NULL;
-    }
-  else
-    {
-      cmpl_state->user_completion_index += 1;
-      cmpl_state->the_completion.is_a_completion = 1;
-      cmpl_state->the_completion.is_directory = 1;
-
-      return append_completion_text("~/", cmpl_state);
-    }
-}
-
-/* returns the index (>= 0) of the first differing character,
- * PATTERN_MATCH if the completion matches */
-static gint
-first_diff_index(gchar* pat, gchar* text)
-{
-  gint diff = 0;
-
-  while(*pat && *text && *text == *pat)
-    {
-      pat += 1;
-      text += 1;
-      diff += 1;
-    }
-
-  if(*pat)
-    return diff;
-
-  return PATTERN_MATCH;
-}
-
-static PossibleCompletion*
-append_completion_text(gchar* text, CompletionState* cmpl_state)
-{
-  gint len, i = 1;
-
-  if(!cmpl_state->the_completion.text)
-    return NULL;
-
-  len = strlen(text) + strlen(cmpl_state->the_completion.text) + 1;
-
-  if(cmpl_state->the_completion.text_alloc > len)
-    {
-      strcat(cmpl_state->the_completion.text, text);
-      return &cmpl_state->the_completion;
-    }
-
-  while(i < len) { i <<= 1; }
-
-  cmpl_state->the_completion.text_alloc = i;
-
-  cmpl_state->the_completion.text = (gchar*)g_realloc(cmpl_state->the_completion.text, i);
-
-  if(!cmpl_state->the_completion.text)
-    return NULL;
-  else
-    {
-      strcat(cmpl_state->the_completion.text, text);
-      return &cmpl_state->the_completion;
-    }
-}
-
-static CompletionDir*
-find_completion_dir(gchar* text_to_complete,
-		    gchar** remaining_text,
-		    CompletionState* cmpl_state)
-{
-  gchar* first_slash = strchr(text_to_complete, '/');
-  CompletionDir* dir = cmpl_state->reference_dir;
-  CompletionDir* next;
-  *remaining_text = text_to_complete;
-
-  while(first_slash)
-    {
-      gint len = first_slash - *remaining_text;
-      gint found = 0;
-      gchar *found_name = NULL;         /* Quiet gcc */
-      gint i;
-      gchar* pat_buf = g_new (gchar, len + 1);
-
-      strncpy(pat_buf, *remaining_text, len);
-      pat_buf[len] = 0;
-
-      for(i = 0; i < dir->sent->entry_count; i += 1)
-	{
-	  if(dir->sent->entries[i].is_dir &&
-	     fnmatch(pat_buf, dir->sent->entries[i].entry_name,
-		     FNMATCH_FLAGS)!= FNM_NOMATCH)
-	    {
-	      if(found)
-		{
-		  g_free (pat_buf);
-		  return dir;
-		}
-	      else
-		{
-		  found = 1;
-		  found_name = dir->sent->entries[i].entry_name;
-		}
-	    }
-	}
-
-      if (!found)
-	{
-	  /* Perhaps we are trying to open an automount directory */
-	  found_name = pat_buf;
-	}
-
-      next = open_relative_dir(found_name, dir, cmpl_state);
-      
-      if(!next)
-	{
-	  g_free (pat_buf);
-	  return NULL;
-	}
-      
-      next->cmpl_parent = dir;
-      
-      dir = next;
-      
-      if(!correct_dir_fullname(dir))
-	{
-	  g_free(pat_buf);
-	  return NULL;
-	}
-      
-      *remaining_text = first_slash + 1;
-      first_slash = strchr(*remaining_text, '/');
-
-      g_free (pat_buf);
-    }
-
-  return dir;
-}
-
-static void
-update_cmpl(PossibleCompletion* poss, CompletionState* cmpl_state)
-{
-  gint cmpl_len;
-
-  if(!poss || !cmpl_is_a_completion(poss))
-    return;
-
-  cmpl_len = strlen(cmpl_this_completion(poss));
-
-  if(cmpl_state->updated_text_alloc < cmpl_len + 1)
-    {
-      cmpl_state->updated_text =
-	(gchar*)g_realloc(cmpl_state->updated_text,
-			  cmpl_state->updated_text_alloc);
-      cmpl_state->updated_text_alloc = 2*cmpl_len;
-    }
-
-  if(cmpl_state->updated_text_len < 0)
-    {
-      strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
-      cmpl_state->updated_text_len = cmpl_len;
-      cmpl_state->re_complete = cmpl_is_directory(poss);
-    }
-  else if(cmpl_state->updated_text_len == 0)
-    {
-      cmpl_state->re_complete = FALSE;
-    }
-  else
-    {
-      gint first_diff =
-	first_diff_index(cmpl_state->updated_text,
-			 cmpl_this_completion(poss));
-
-      cmpl_state->re_complete = FALSE;
-
-      if(first_diff == PATTERN_MATCH)
-	return;
-
-      if(first_diff > cmpl_state->updated_text_len)
-	strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
-
-      cmpl_state->updated_text_len = first_diff;
-      cmpl_state->updated_text[first_diff] = 0;
-    }
-}
-
-static PossibleCompletion*
-attempt_file_completion(CompletionState *cmpl_state)
-{
-  gchar *pat_buf, *first_slash;
-  CompletionDir *dir = cmpl_state->active_completion_dir;
-
-  dir->cmpl_index += 1;
-
-  if(dir->cmpl_index == dir->sent->entry_count)
-    {
-      if(dir->cmpl_parent == NULL)
-	{
-	  cmpl_state->active_completion_dir = NULL;
-
-	  return NULL;
-	}
-      else
-	{
-	  cmpl_state->active_completion_dir = dir->cmpl_parent;
-
-	  return attempt_file_completion(cmpl_state);
-	}
-    }
-
-  g_assert(dir->cmpl_text);
-
-  first_slash = strchr(dir->cmpl_text, '/');
-
-  if(first_slash)
-    {
-      gint len = first_slash - dir->cmpl_text;
-
-      pat_buf = g_new (gchar, len + 1);
-      strncpy(pat_buf, dir->cmpl_text, len);
-      pat_buf[len] = 0;
-    }
-  else
-    {
-      gint len = strlen(dir->cmpl_text);
-
-      pat_buf = g_new (gchar, len + 2);
-      strcpy(pat_buf, dir->cmpl_text);
-      strcpy(pat_buf + len, "*");
-    }
-
-  if(first_slash)
-    {
-      if(dir->sent->entries[dir->cmpl_index].is_dir)
-	{
-	  if(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
-		     FNMATCH_FLAGS) != FNM_NOMATCH)
-	    {
-	      CompletionDir* new_dir;
-
-	      new_dir = open_relative_dir(dir->sent->entries[dir->cmpl_index].entry_name,
-					  dir, cmpl_state);
-
-	      if(!new_dir)
-		{
-		  g_free (pat_buf);
-		  return NULL;
-		}
-
-	      new_dir->cmpl_parent = dir;
-
-	      new_dir->cmpl_index = -1;
-	      new_dir->cmpl_text = first_slash + 1;
-
-	      cmpl_state->active_completion_dir = new_dir;
-
-	      g_free (pat_buf);
-	      return attempt_file_completion(cmpl_state);
-	    }
-	  else
-	    {
-	      g_free (pat_buf);
-	      return attempt_file_completion(cmpl_state);
-	    }
-	}
-      else
-	{
-	  g_free (pat_buf);
-	  return attempt_file_completion(cmpl_state);
-	}
-    }
-  else
-    {
-      if(dir->cmpl_parent != NULL)
-	{
-	  append_completion_text(dir->fullname +
-				 strlen(cmpl_state->completion_dir->fullname) + 1,
-				 cmpl_state);
-	  append_completion_text("/", cmpl_state);
-	}
-
-      append_completion_text(dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
-
-      cmpl_state->the_completion.is_a_completion =
-	(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
-		 FNMATCH_FLAGS) != FNM_NOMATCH);
-
-      cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
-      if(dir->sent->entries[dir->cmpl_index].is_dir)
-	append_completion_text("/", cmpl_state);
-
-      g_free (pat_buf);
-      return &cmpl_state->the_completion;
-    }
-}
-
-
-static gint
-get_pwdb(CompletionState* cmpl_state)
-{
-  struct passwd *pwd_ptr;
-  gchar* buf_ptr;
-  gint len = 0, i, count = 0;
-
-  if(cmpl_state->user_dir_name_buffer)
-    return TRUE;
-  setpwent ();
-
-  while ((pwd_ptr = getpwent()) != NULL)
-    {
-      len += strlen(pwd_ptr->pw_name);
-      len += strlen(pwd_ptr->pw_dir);
-      len += 2;
-      count += 1;
-    }
-
-  setpwent ();
-
-  cmpl_state->user_dir_name_buffer = g_new(gchar, len);
-  cmpl_state->user_directories = g_new(CompletionUserDir, count);
-  cmpl_state->user_directories_len = count;
-
-  buf_ptr = cmpl_state->user_dir_name_buffer;
-
-  for(i = 0; i < count; i += 1)
-    {
-      pwd_ptr = getpwent();
-      if(!pwd_ptr)
-	{
-	  cmpl_errno = errno;
-	  goto error;
-	}
-
-      strcpy(buf_ptr, pwd_ptr->pw_name);
-      cmpl_state->user_directories[i].login = buf_ptr;
-      buf_ptr += strlen(buf_ptr);
-      buf_ptr += 1;
-      strcpy(buf_ptr, pwd_ptr->pw_dir);
-      cmpl_state->user_directories[i].homedir = buf_ptr;
-      buf_ptr += strlen(buf_ptr);
-      buf_ptr += 1;
-    }
-
-  qsort(cmpl_state->user_directories,
-	cmpl_state->user_directories_len,
-	sizeof(CompletionUserDir),
-	compare_user_dir);
-
-  endpwent();
-
-  return TRUE;
-
-error:
-
-  if(cmpl_state->user_dir_name_buffer)
-    g_free(cmpl_state->user_dir_name_buffer);
-  if(cmpl_state->user_directories)
-    g_free(cmpl_state->user_directories);
-
-  cmpl_state->user_dir_name_buffer = NULL;
-  cmpl_state->user_directories = NULL;
-
-  return FALSE;
-}
-
-static gint
-compare_user_dir(const void* a, const void* b)
-{
-  return strcmp((((CompletionUserDir*)a))->login,
-		(((CompletionUserDir*)b))->login);
-}
-
-static gint
-compare_cmpl_dir(const void* a, const void* b)
-{
-  return strcmp((((CompletionDirEntry*)a))->entry_name,
-		(((CompletionDirEntry*)b))->entry_name);
-}
-
-static gint
-cmpl_state_okay(CompletionState* cmpl_state)
-{
-  return  cmpl_state && cmpl_state->reference_dir;
-}
-
-static gchar*
-cmpl_strerror(gint err)
-{
-  if(err == CMPL_ERRNO_TOO_LONG)
-    return "Name too long";
-  else
-    return g_strerror (err);
-}
-
-/* This is an internally used function to create pixmaps. */
-GtkWidget*
-create_pixmap(GtkWidget *widget, const gchar *pixmap_char)
-{
-  GdkPixmap *gdkpixmap;
-  GdkBitmap *mask;
-  GtkWidget *pixmap;
-  GdkColormap *colormap;
-
-  colormap = gtk_widget_get_colormap (widget);
-
-  gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (GTK_WIDGET(widget)->window,
-						     colormap,
-						     &mask,
-						     NULL, 
-						     (gpointer) pixmap_char);
-  if (gdkpixmap == NULL)
-    {
-      g_warning ("Error loading pixmap: %s", pixmap_char);
-      return NULL;
-    }
-  pixmap = gtk_pixmap_new (gdkpixmap, mask);
-  gdk_pixmap_unref (gdkpixmap);
-  gdk_bitmap_unref (mask);
-  return pixmap;
-}
-
-
-/* Testing area */
-#ifdef TORRIE_DEBUG
-
-/* Get the selected filename and print it to the console */
-void file_ok_sel( GtkWidget        *w,
-                  GtkFileSelection *fs )
-{
-    g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
-}
-
-void destroy( GtkWidget *widget,
-              gpointer   data )
-{
-    gtk_main_quit ();
-}
-
-int main( int   argc,
-          char *argv[] )
-{
-    GtkWidget *filew;
-    const gchar *masks[] = { "mp3s/playlists <*.mp3,*.m3u>",
-                             "src/hdr <*.[CcHh],*.[Cc][Cc],*.[Hh][Hh],*.cpp>",
-                             NULL };
-
-    gtk_init (&argc, &argv);
-
-    /* Create a new file selection widget */
-    filew = gtk_file_selection_new ("Spiffy File Selector");
-//    gtk_file_selection_complete(GTK_FILE_SELECTION(filew),"bob");
-
-    gtk_file_selection_set_masks (GTK_FILE_SELECTION (filew), masks);
-		
-    gtk_signal_connect (GTK_OBJECT (filew), "destroy",
-			(GtkSignalFunc) destroy, &filew);
-    /* Connect the ok_button to file_ok_sel function */
-    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
-			"clicked", (GtkSignalFunc) file_ok_sel, filew );
-
-    /* Connect the cancel_button to destroy the widget */
-    gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
-                                            (filew)->cancel_button),
-			       "clicked", (GtkSignalFunc) gtk_widget_destroy,
-			       GTK_OBJECT (filew));
-
-
-    gtk_widget_show(filew);
-
-/*
-    g_print("%d",gtk_file_selection_match_mask("mask.c","m*.c"));
-    g_print("%d",gtk_file_selection_match_mask("mask.c","m???.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.c","m??*.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c???"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c*"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","n*.c???"));
-		g_print("%d",gtk_file_selection_match_mask("mask.c","[mn]*"));
-		g_print("%d",gtk_file_selection_match_mask("COPYING","*.xpm"));
-*/	
-    gtk_main ();
-
-    return 0;
-}
-/* example-end */
-#endif
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+#define LEO
+
+#ifdef LEO
+#define _(a) a
+
+static char * back_xpm[] = {
+"14 14 33 1",
+" 	c None",
+".	c #000000",
+"+	c #C6D7C6",
+"@	c #E7EBE7",
+"#	c #FFFFFF",
+"$	c #DEEBDE",
+"%	c #F7F7F7",
+"&	c #DEE7DE",
+"*	c #EFF3EF",
+"=	c #101810",
+"-	c #B5C7AD",
+";	c #EFEFEF",
+">	c #D6E3D6",
+",	c #213021",
+"'	c #315931",
+")	c #52824A",
+"!	c #739A6B",
+"~	c #84A673",
+"{	c #7BA673",
+"]	c #84AA73",
+"^	c #84AA7B",
+"/	c #84AE7B",
+"(	c #63925A",
+"_	c #526D4A",
+":	c #4A7D42",
+"<	c #739E6B",
+"[	c #739A63",
+"}	c #4A7539",
+"|	c #638E52",
+"1	c #427139",
+"2	c #6BA663",
+"3	c #5A8A52",
+"4	c #315929",
+"            ..",
+"          ..+.",
+"        ..@#+.",
+"      ..$#%%+.",
+"    ..&#%*%%+.",
+"  .=&#******+.",
+"..-#;>&@****+,",
+"..')!~{]^/^/(.",
+"  .._:<^~^/^(.",
+"    ..':[]~/(.",
+"      ..}:[~|.",
+"        ..123.",
+"          ..4.",
+"            .."};
+
+static char * up_xpm[] = {
+"14 14 36 1",
+" 	c None",
+".	c #000000",
+"+	c #181C18",
+"@	c #D6DBD6",
+"#	c #94AA8C",
+"$	c #000400",
+"%	c #DEDFDE",
+"&	c #94AA84",
+"*	c #E7E3E7",
+"=	c #94B28C",
+"-	c #6B865A",
+";	c #EFEBEF",
+">	c #9CB694",
+",	c #8CA684",
+"'	c #EFEFEF",
+")	c #F7EFF7",
+"!	c #9CB68C",
+"~	c #63865A",
+"{	c #94B684",
+"]	c #94AE84",
+"^	c #739263",
+"/	c #F7F3F7",
+"(	c #94B284",
+"_	c #849E73",
+":	c #8CAE7B",
+"<	c #8CAA84",
+"[	c #7B966B",
+"}	c #8CA67B",
+"|	c #DEDBD6",
+"1	c #E7E7E7",
+"2	c #8CAE84",
+"3	c #8CAA7B",
+"4	c #738E63",
+"5	c #BDBEB5",
+"6	c #BDC3BD",
+"7	c #637D52",
+"      ..      ",
+"      ..      ",
+"     +@#$     ",
+"     .%&.     ",
+"    .**=-.    ",
+"    .;;>,.    ",
+"   .*')!&~.   ",
+"   .;)){]^.   ",
+"  .*')/(]_-.  ",
+"  .;)//::<[.  ",
+" .*')//:::}-. ",
+" .|1;;12]3}4. ",
+".556666^^^^-7.",
+".............."};
+
+static char * forward_xpm[] = {
+"14 14 36 1",
+" 	c None",
+".	c #000000",
+"+	c #E7EBDE",
+"@	c #FFFFFF",
+"#	c #F7F7EF",
+"$	c #D6E3D6",
+"%	c #F7F7F7",
+"&	c #EFF3EF",
+"*	c #CEDFCE",
+"=	c #CEDBC6",
+"-	c #E7EFE7",
+";	c #181818",
+">	c #292829",
+",	c #E7EBE7",
+"'	c #DEE7DE",
+")	c #B5C7AD",
+"!	c #9CBA94",
+"~	c #8CAE84",
+"{	c #84AA7B",
+"]	c #7BA673",
+"^	c #84A67B",
+"/	c #739A6B",
+"(	c #5A824A",
+"_	c #395931",
+":	c #9CBA8C",
+"<	c #84AE7B",
+"[	c #739E6B",
+"}	c #527D4A",
+"|	c #425942",
+"1	c #84A673",
+"2	c #4A7142",
+"3	c #94B284",
+"4	c #395D31",
+"5	c #5A8652",
+"6	c #315929",
+"7	c #396531",
+"..            ",
+".+..          ",
+".@#$..        ",
+".@%&#*..      ",
+".@%%&&%=..    ",
+".@&&&&&-#=;.  ",
+">@&&&&,'$'&)..",
+".!~{~{{]^/(_..",
+".:{<{^{[}|..  ",
+".:<1{/}2..    ",
+".31/}4..      ",
+".{56..        ",
+".7..          ",
+"..            "};
+
+static char * refresh_xpm[] = {
+"16 16 11 1",
+" 	c None",
+".	c #000000",
+"+	c #526942",
+"@	c #4A6139",
+"#	c #526542",
+"$	c #5A7142",
+"%	c #425531",
+"&	c #314529",
+"*	c #425131",
+"=	c #425931",
+"-	c #5A754A",
+"       .        ",
+"      ..        ",
+"     .+@...     ",
+"    .#$##@%..   ",
+"     .+#...%%.  ",
+"   .  ..   .&.  ",
+"  .    .    .&. ",
+" ..          .. ",
+" ..          .. ",
+" .*.    .    .  ",
+"  .*.   ..  .   ",
+"  .%@...#=.     ",
+"   ..##-#@#.    ",
+"     ...@%.     ",
+"        ..      ",
+"        .       "};
+
+#endif
+
+#ifndef LEO
+#include "config.h"
+#endif
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include <grp.h>
+#include <time.h>
+
+#include "fnmatch.h"
+
+#if (defined TORRIE_DEBUG || defined LEO)
+#include <gdk/gdkkeysyms.h>
+#include <gtk/gtkbutton.h>
+#include <gtk/gtkentry.h>
+#include "gtkfilesel-linux.h"
+#include <gtk/gtkhbox.h>
+#include <gtk/gtkhbbox.h>
+#include <gtk/gtklabel.h>
+#include <gtk/gtklist.h>
+#include <gtk/gtklistitem.h>
+#include <gtk/gtkmain.h>
+#include <gtk/gtkscrolledwindow.h>
+#include <gtk/gtksignal.h>
+#include <gtk/gtkvbox.h>
+#include <gtk/gtkmenu.h>
+#include <gtk/gtkmenuitem.h>
+#include <gtk/gtkoptionmenu.h>
+#include <gtk/gtkclist.h>
+#include <gtk/gtkdialog.h>
+#include <gtk/gtkcombo.h>
+#include <gtk/gtkframe.h>
+#include <gtk/gtkhpaned.h>
+#include <gtk/gtktable.h>
+#include <gtk/gtkpixmap.h>
+#include <gtk/gtknotebook.h>
+#include <gtk/gtkhseparator.h>
+#include <gtk/gtktogglebutton.h>
+#else
+#include "gdk/gdkkeysyms.h"
+#include "gtkbutton.h"
+#include "gtkentry.h"
+#include "gtkfilesel.h"
+#include "gtkhbox.h"
+#include "gtkhbbox.h"
+#include "gtklabel.h"
+#include "gtklist.h"
+#include "gtklistitem.h"
+#include "gtkmain.h"
+#include "gtkscrolledwindow.h"
+#include "gtksignal.h"
+#include "gtkvbox.h"
+#include "gtkmenu.h"
+#include "gtkmenuitem.h"
+#include "gtkoptionmenu.h"
+#include "gtkclist.h"
+#include "gtkdialog.h"
+#include "gtkcombo.h"
+#include "gtkframe.h"
+#include "gtkhpaned.h"
+#include "gtktable.h"
+#include "gtkpixmap.h"
+#include "gtknotebook.h"
+#include "gtkhseparator.h"
+#include "gtktogglebutton.h"
+#endif
+
+#ifndef LEO
+#include "gtkintl.h"
+
+#include "back.xpm"
+#include "up.xpm"
+#include "forward.xpm"
+#include "refresh.xpm"
+#endif
+
+#define DIR_LIST_WIDTH   180
+#define DIR_LIST_HEIGHT  180
+#define FILE_LIST_WIDTH  180
+#define FILE_LIST_HEIGHT 180
+#define BOOKMARK_FILE "/.gtkfilesel_bookmarks"
+#define MASK_FILE "/.gtkfilesel_masks"
+#define TIME_STRING_BUF 50
+
+/* I've put this here so it doesn't get confused with the 
+ * file completion interface */
+typedef struct _HistoryCallbackArg HistoryCallbackArg;
+
+struct _HistoryCallbackArg
+{
+  gchar *directory;
+  GtkWidget *menu_item;
+};
+
+
+typedef struct _BookmarkMenuStruct BookmarkMenuStruct;
+struct _BookmarkMenuStruct {
+  GtkWidget *menu_item;
+  gchar     *desc;
+  gchar     *path;
+};
+
+typedef struct _CompletionState    CompletionState;
+typedef struct _CompletionDir      CompletionDir;
+typedef struct _CompletionDirSent  CompletionDirSent;
+typedef struct _CompletionDirEntry CompletionDirEntry;
+typedef struct _CompletionUserDir  CompletionUserDir;
+typedef struct _PossibleCompletion PossibleCompletion;
+
+/* Non-external file completion decls and structures */
+
+/* A contant telling PRCS how many directories to cache.  Its actually
+ * kept in a list, so the geometry isn't important. */
+#define CMPL_DIRECTORY_CACHE_SIZE 10
+
+/* A constant used to determine whether a substring was an exact
+ * match by first_diff_index()
+ */
+#define PATTERN_MATCH -1
+/* The arguments used by all fnmatch() calls below
+ */
+#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
+
+#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
+
+/* This structure contains all the useful information about a directory
+ * for the purposes of filename completion.  These structures are cached
+ * in the CompletionState struct.  CompletionDir's are reference counted.
+ */
+struct _CompletionDirSent
+{
+  ino_t inode;
+  time_t mtime;
+  dev_t device;
+
+  gint entry_count;
+  gchar *name_buffer; /* memory segment containing names of all entries */
+
+  struct _CompletionDirEntry *entries;
+};
+
+struct _CompletionDir
+{
+  CompletionDirSent *sent;
+
+  gchar *fullname;
+  gint fullname_len;
+
+  struct _CompletionDir *cmpl_parent;
+  gint cmpl_index;
+  gchar *cmpl_text;
+};
+
+/* This structure contains pairs of directory entry names with a flag saying
+ * whether or not they are a valid directory.  NOTE: This information is used
+ * to provide the caller with information about whether to update its completions
+ * or try to open a file.  Since directories are cached by the directory mtime,
+ * a symlink which points to an invalid file (which will not be a directory),
+ * will not be reevaluated if that file is created, unless the containing
+ * directory is touched.  I consider this case to be worth ignoring (josh).
+ */
+struct _CompletionDirEntry
+{
+  gint is_dir;
+  gchar *entry_name;
+};
+
+struct _CompletionUserDir
+{
+  gchar *login;
+  gchar *homedir;
+};
+
+struct _PossibleCompletion
+{
+  /* accessible fields, all are accessed externally by functions
+   * declared above
+   */
+  gchar *text;
+  gint is_a_completion;
+  gint is_directory;
+
+  gint file_size;
+  gint file_time;
+  gint uid;
+  gint gid;
+  /* Private fields
+   */
+  gint text_alloc;
+};
+
+struct _CompletionState
+{
+  gint last_valid_char;
+  gchar *updated_text;
+  gint updated_text_len;
+  gint updated_text_alloc;
+  gint re_complete;
+
+  gchar *user_dir_name_buffer;
+  gint user_directories_len;
+
+  gchar *last_completion_text;
+
+  gint user_completion_index; /* if >= 0, currently completing ~user */
+
+  struct _CompletionDir *completion_dir; /* directory completing from */
+  struct _CompletionDir *active_completion_dir;
+
+  struct _PossibleCompletion the_completion;
+
+  struct _CompletionDir *reference_dir; /* initial directory */
+
+  GList* directory_storage;
+  GList* directory_sent_storage;
+
+  struct _CompletionUserDir *user_directories;
+};
+
+/* Widgets from the Properties Dialog */
+typedef struct _PropertiesPrivate PropertiesPrivate;
+
+struct _PropertiesPrivate
+{
+  GtkWidget *mode_label;
+  GtkWidget *mode_buttons[12];
+};
+
+/* pixmap creation function */
+GtkWidget*                 create_pixmap          (GtkWidget *widget, 
+						   const gchar *pixmap_char);
+
+/* File completion functions which would be external, were they used
+ * outside of this file.
+ */
+
+static CompletionState*    cmpl_init_state        (void);
+static void                cmpl_free_state        (CompletionState *cmpl_state);
+static gint                cmpl_state_okay        (CompletionState* cmpl_state);
+static gchar*              cmpl_strerror          (gint);
+
+static PossibleCompletion* cmpl_completion_matches(gchar           *text_to_complete,
+						   gchar          **remaining_text,
+						   CompletionState *cmpl_state);
+
+/* Returns a name for consideration, possibly a completion, this name
+ * will be invalid after the next call to cmpl_next_completion.
+ */
+static char*               cmpl_this_completion   (PossibleCompletion*);
+
+/* True if this completion matches the given text.  Otherwise, this
+ * output can be used to have a list of non-completions.
+ */
+static gint                cmpl_is_a_completion   (PossibleCompletion*);
+
+/* True if the completion is a directory
+ */
+static gint                cmpl_is_directory      (PossibleCompletion*);
+
+/* Obtains the next completion, or NULL
+ */
+static PossibleCompletion* cmpl_next_completion   (CompletionState*);
+
+/* Updating completions: the return value of cmpl_updated_text() will
+ * be text_to_complete completed as much as possible after the most
+ * recent call to cmpl_completion_matches.  For the present
+ * application, this is the suggested replacement for the user's input
+ * string.  You must CALL THIS AFTER ALL cmpl_text_completions have
+ * been received.
+ */
+static gchar*              cmpl_updated_text       (CompletionState* cmpl_state);
+
+/* After updating, to see if the completion was a directory, call
+ * this.  If it was, you should consider re-calling completion_matches.
+ */
+static gint                cmpl_updated_dir        (CompletionState* cmpl_state);
+
+/* Current location: if using file completion, return the current
+ * directory, from which file completion begins.  More specifically,
+ * the cwd concatenated with all exact completions up to the last
+ * directory delimiter('/').
+ */
+static gchar*              cmpl_reference_position (CompletionState* cmpl_state);
+
+/* backing up: if cmpl_completion_matches returns NULL, you may query
+ * the index of the last completable character into cmpl_updated_text.
+ */
+static gint                cmpl_last_valid_char    (CompletionState* cmpl_state);
+
+/* When the user selects a non-directory, call cmpl_completion_fullname
+ * to get the full name of the selected file.
+ */
+static gchar*              cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);
+
+
+/* Directory operations. */
+static CompletionDir* open_ref_dir         (gchar* text_to_complete,
+					    gchar** remaining_text,
+					    CompletionState* cmpl_state);
+static gboolean       check_dir            (gchar *dir_name, 
+					    struct stat *result, 
+					    gboolean *stat_subdirs);
+static CompletionDir* open_dir             (gchar* dir_name,
+					    CompletionState* cmpl_state);
+static CompletionDir* open_user_dir        (gchar* text_to_complete,
+					    CompletionState *cmpl_state);
+static CompletionDir* open_relative_dir    (gchar* dir_name, CompletionDir* dir,
+					    CompletionState *cmpl_state);
+static CompletionDirSent* open_new_dir     (gchar* dir_name, 
+					    struct stat* sbuf,
+					    gboolean stat_subdirs);
+static gint           correct_dir_fullname (CompletionDir* cmpl_dir);
+static gint           correct_parent       (CompletionDir* cmpl_dir,
+					    struct stat *sbuf);
+static gchar*         find_parent_dir_fullname    (gchar* dirname);
+static CompletionDir* attach_dir           (CompletionDirSent* sent,
+					    gchar* dir_name,
+					    CompletionState *cmpl_state);
+static void           free_dir_sent (CompletionDirSent* sent);
+static void           free_dir      (CompletionDir  *dir);
+static void           prune_memory_usage(CompletionState *cmpl_state);
+
+/* Completion operations */
+static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,
+						      CompletionState *cmpl_state);
+static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);
+static CompletionDir* find_completion_dir(gchar* text_to_complete,
+					  gchar** remaining_text,
+					  CompletionState* cmpl_state);
+static PossibleCompletion* append_completion_text(gchar* text,
+						  CompletionState* cmpl_state);
+static gint get_pwdb(CompletionState* cmpl_state);
+static gint first_diff_index(gchar* pat, gchar* text);
+static gint compare_user_dir(const void* a, const void* b);
+static gint compare_cmpl_dir(const void* a, const void* b);
+static void update_cmpl(PossibleCompletion* poss,
+			CompletionState* cmpl_state);
+
+static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);
+static void gtk_file_selection_init          (GtkFileSelection      *filesel);
+static void gtk_file_selection_realize       (GtkWidget             *widget);
+static void gtk_file_selection_destroy       (GtkObject             *object);
+static gint gtk_file_selection_key_press     (GtkWidget             *widget,
+					      GdkEventKey           *event,
+					      gpointer               user_data);
+
+static void gtk_file_selection_file_button (GtkWidget *widget,
+					    gint row, 
+					    gint column, 
+					    GdkEventButton *bevent,
+					    gpointer user_data);
+
+static void gtk_file_selection_dir_button (GtkWidget *widget,
+					   gint row,
+					   gint column,
+					   GdkEventButton *bevent,
+					   gpointer data);
+
+static void gtk_file_selection_undir_button (GtkWidget *widget,
+					     gint row,
+					     gint column,
+					     GdkEventButton *bevent,
+					     gpointer data);
+
+static void gtk_file_selection_populate      (GtkFileSelection      *fs,
+					      gchar                 *rel_path,
+					      gint                   try_complete);
+static void gtk_file_selection_abort         (GtkFileSelection      *fs);
+
+static void gtk_file_selection_update_history_menu (GtkFileSelection       *fs,
+						    gchar                  *current_dir);
+
+static void gtk_file_selection_create_dir (gpointer data);
+static void gtk_file_selection_delete_file (gpointer data);
+static void gtk_file_selection_rename_file (gpointer data);
+static void gtk_file_selection_properties (gpointer data);
+static void gtk_file_selection_properties_update_mode (GtkWidget *widget, gpointer data);
+static mode_t gtk_file_selection_properties_get_mode (PropertiesPrivate* private);
+
+static gboolean gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
+static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
+																							GdkEventKey *event,
+																							gpointer user_data);
+static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
+																							GdkEventButton *event,
+
+																							gpointer user_data);
+static void gtk_file_selection_bookmark_callback (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data);
+static gint gtk_file_selection_mask_entry_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
+static gint gtk_file_selection_mask_entry_button_callback (GtkWidget *widget, GdkEventButton *event, gpointer data);
+
+//static void gtk_file_selection_home_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_bookmark_button (GtkWidget *widget, 
+	      	                   GtkFileSelection *fs);
+
+static void gtk_file_selection_up_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_prev_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_next_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data);
+
+static gint gtk_file_selection_files_list_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
+
+
+static gint gtk_file_selection_match_char (gchar, gchar *mask);
+static gint gtk_file_selection_match_mask (gchar *,gchar *);
+
+static void gtk_file_selection_load_bookmarks(GtkFileSelection *fs);
+static void gtk_file_selection_add_bookmark (GtkFileSelection *fs, gchar *desc, gchar *path);
+gint gtk_file_selection_save_bookmarks (GtkFileSelection *fs);
+
+static void gtk_file_selection_load_masks(GtkFileSelection *fs);
+
+static gint gtk_file_selection_show_fileop_menu (GtkCList *clist, 
+						 GdkEvent *event, 
+						 GtkFileSelection *fs);
+
+						 
+static GtkWindowClass *parent_class = NULL;
+
+/* Saves errno when something cmpl does fails. */
+static gint cmpl_errno;
+
+#ifdef G_WITH_CYGWIN
+/*
+ * Take the path currently in the file selection
+ * entry field and translate as necessary from
+ * a WIN32 style to CYGWIN32 style path.  For
+ * instance translate:
+ * x:\somepath\file.jpg
+ * to:
+ * //x/somepath/file.jpg
+ *
+ * Replace the path in the selection text field.
+ * Return a boolean value concerning whether a
+ * translation had to be made.
+ */
+int
+translate_win32_path (GtkFileSelection *filesel)
+{
+  int updated = 0;
+  gchar *path;
+
+  /*
+   * Retrieve the current path
+   */
+  path = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
+
+  /*
+   * Translate only if this looks like a DOS-ish
+   * path... First handle any drive letters.
+   */
+  if (isalpha (path[0]) && (path[1] == ':')) {
+    /*
+     * This part kind of stinks... It isn't possible
+     * to know if there is enough space in the current
+     * string for the extra character required in this
+     * conversion.  Assume that there isn't enough space
+     * and use the set function on the text field to
+     * set the newly created string.
+     */
+    gchar *newPath = g_strdup_printf ("//%c/%s", path[0], (path + 3));
+    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), newPath);
+
+    path = newPath;
+    updated = 1;
+  }
+
+  /*
+   * Now, replace backslashes with forward slashes 
+   * if necessary.
+   */
+  if (strchr (path, '\\'))
+    {
+      int index;
+      for (index = 0; path[index] != '\0'; index++)
+	if (path[index] == '\\')
+	  path[index] = '/';
+      
+      updated = 1;
+    }
+    
+  return updated;
+}
+#endif
+
+/* General notes:
+ * Make prev and next inactive if their respective *
+ *   histories are empty.
+ * Add facilities for handling hidden files and    *
+ * directories                                     *
+ * Add an api to access the mask, and hidden files *
+ * check box?  (prob not in 1.2.x series)          *
+ */
+
+/* Routine for applying mask to filenames         *
+ *   Need to be optimized to minimize recursion   *
+ *     help the for loop by looking for the next  *
+ *     instance of the mask character following   *
+ *     the '*'.  ei *.c -- look for '.'           *
+ *     Also, swap all *? pairs (-> ?*), as that   *
+ *     will make it possible to look ahead (?     *
+ *     makes it very nondeterministic as in *?.c  *
+ *     which really is ?*.c                       *
+ *                                                *
+ */
+static gint gtk_file_selection_match_char (gchar text, gchar *mask)
+{
+  gchar *maskc;
+  gint x;
+  gint s;
+  gchar lastc;
+  gchar nextc;
+
+  if (mask[0] == '[')
+    {
+      if (!strchr (mask,']')) return 0;
+      lastc = 0;
+
+      maskc = g_strdup(mask + 1); /* get the portion of mask inside []*/
+      (*(strchr (maskc + 1,']'))) = 0;
+      s = strlen ((char *)maskc);
+
+      for (x = 0 ; x < s ; x ++){
+        if (maskc[x] == '-')
+          {
+            if (x == s) return 1;
+            nextc = maskc[x + 1];
+
+            if (nextc > lastc)
+            {
+              if ((lastc <= text) && (nextc >= text))
+              {
+                g_free (maskc);
+                return s + 2;
+              }
+            }
+            else if ((lastc >= text) && (nextc <= text))
+              {
+                g_free (maskc);
+                return s + 2;
+              }
+          }
+        else if (text == maskc[x])
+          {
+            g_free (maskc);
+            return s + 2;
+          }
+        lastc = maskc[x];
+      }
+      g_free (maskc);
+
+      return 0;
+    }
+
+  if (mask[0] == '?') return 1;
+  if (mask[0] == text) return 1;
+
+  return 0;
+}
+
+
+static gint gtk_file_selection_match_mask1 (gchar *text, gchar *mask)
+{
+
+  int mc;
+  int tc;
+
+  tc = 0; mc = 0;
+	
+  if (mask[0] == 0 && text[0] == 0) return 1;
+	
+  if (mask[0] == '*')
+    {
+      for (tc = 0; tc <= strlen(text); tc++)
+	{
+	  if (gtk_file_selection_match_mask1 (text + tc, mask + 1))
+	    return 1;
+	}
+      return 0;
+    }
+  mc = gtk_file_selection_match_char (text[0], mask);
+
+  if(mc)
+    return gtk_file_selection_match_mask1 (text + 1, mask + mc);
+  else
+    return 0;
+}
+
+static gint gtk_file_selection_match_mask (gchar *text, gchar *mask)
+{
+  gchar *masks;
+  gchar *bmask;
+  gchar *emask;
+
+  masks=g_strdup(mask);
+
+  emask=strchr(masks,'<');
+  if(emask){
+    bmask=emask+1;
+    emask=strchr(bmask,'>');
+    if(emask){
+      *emask=0;
+    }
+  }else{
+    bmask=masks;
+  }
+
+  do{
+    if((emask=strchr(bmask,',')) || (emask=strchr(bmask,';'))){
+      *emask=0;
+      if (gtk_file_selection_match_mask1 (text, bmask)){
+      	g_free(masks);
+	return 1;
+      }
+
+      bmask=emask+1;
+    }
+  }while(emask);
+
+  if(gtk_file_selection_match_mask1 (text, bmask)){
+    g_free(masks);
+    return 1;
+  }
+  g_free(masks);
+  return 0;
+}
+
+static void
+gtk_file_selection_load_bookmarks(GtkFileSelection *fs)
+{
+  GList *list;
+  gchar *bookmark_file;
+  gchar *bookmark_data;
+  struct stat file_info;
+  gint   file;
+  gint   lp;
+  gint   cp;
+  BookmarkMenuStruct *item;
+
+
+  if(fs->bookmark_list){  //erase
+    list=fs->bookmark_list;
+    while(list){
+      item=list->data;
+      g_free(item->desc);
+      g_free(item->path);
+      g_free(item);
+      list=list->next;
+    }
+    g_list_free (fs->bookmark_list);
+    fs->bookmark_list = NULL;
+    gtk_widget_destroy (fs->bookmark_menu);
+  }
+
+  fs->bookmark_menu=gtk_menu_new();
+
+  /* spacer */
+  item=g_malloc(sizeof(item));
+  item->menu_item = gtk_menu_item_new();
+  gtk_widget_show(item->menu_item);
+  gtk_menu_append (GTK_MENU(fs->bookmark_menu), item->menu_item);
+
+  item=g_malloc(sizeof(item));
+  item->desc=g_strdup("Add bookmark");
+  item->path=g_strdup(".");
+  item->menu_item=gtk_menu_item_new_with_label (item->desc);
+  gtk_widget_show(item->menu_item);
+  //fs->bookmark_list=g_list_append(fs->bookmark_list,item);
+  //set signal here!!
+  gtk_menu_append (GTK_MENU(fs->bookmark_menu), item->menu_item);
+
+  item=g_malloc(sizeof(item));
+  item->desc=g_strdup("Edit bookmark");
+  item->path=g_strdup(".");
+  item->menu_item=gtk_menu_item_new_with_label (item->desc);
+  gtk_widget_show(item->menu_item);
+  //fs->bookmark_list=g_list_append(fs->bookmark_list,item);
+  //set signal here!!
+  gtk_menu_append (GTK_MENU(fs->bookmark_menu), item->menu_item);
+
+  bookmark_file=g_strconcat(g_get_home_dir(), BOOKMARK_FILE ,NULL);
+  if(!stat(bookmark_file,&file_info) && (file = open(bookmark_file,  O_RDONLY )) > 0)
+  {
+    if(file_info.st_size <65536 )
+    {
+      bookmark_data=g_malloc(file_info.st_size);
+
+      if(file && read(file, bookmark_data, file_info.st_size))
+      {
+        cp=lp=0;
+
+        while (cp < file_info.st_size)
+        {
+          while (cp < file_info.st_size && bookmark_data[cp] != '<' )
+            cp++;
+	  bookmark_data[cp]=0;
+	  item=g_malloc(sizeof(BookmarkMenuStruct));
+	  item->desc=g_strdup(bookmark_data+lp);
+	  lp=++cp;
+	  
+          while (cp < file_info.st_size && bookmark_data[cp] != '>' )
+            cp++;
+
+          bookmark_data[cp]=0;
+          //create menu items
+	  item->path=g_strdup(bookmark_data+lp);
+	  gtk_file_selection_add_bookmark ((gpointer) fs, (gpointer) item->desc, (gpointer) item->path);
+
+	  cp++;
+
+          while(cp < file_info.st_size && bookmark_data[cp] < 33 )
+            cp++;
+          lp=cp;
+        }
+      }
+
+      close(file);
+    }
+  } else {
+
+    /* Add some default items, then save off to bookmarks file */
+
+    gtk_file_selection_add_bookmark ((gpointer) fs, "Home", "~/");
+    gtk_file_selection_add_bookmark ((gpointer) fs, "Root", "/");
+
+    gtk_file_selection_save_bookmarks ((gpointer) fs);
+  }
+}
+
+static void 
+gtk_file_selection_add_bookmark (GtkFileSelection *fs, gchar *desc, gchar *path) 
+{
+  /* Add item to menu */
+  BookmarkMenuStruct *item;
+  item=g_malloc(sizeof(item));
+  item->desc = (gpointer) desc;
+  item->path = (gpointer) path;
+  item->menu_item=gtk_menu_item_new_with_label (item->desc);
+  gtk_widget_show(item->menu_item);
+  fs->bookmark_list=g_list_append(fs->bookmark_list,item);
+  gtk_signal_connect (GTK_OBJECT(item->menu_item), "activate",
+		      (GtkSignalFunc) gtk_file_selection_bookmark_callback,
+		      (gpointer) fs);
+  gtk_menu_insert (GTK_MENU(fs->bookmark_menu), item->menu_item, g_list_length(fs->bookmark_list) -1);
+}
+
+gint 
+gtk_file_selection_save_bookmarks (GtkFileSelection *fs)
+{
+  BookmarkMenuStruct *item;
+  gchar *bookmark_file;
+  gchar *item_data;
+  gint   file;
+  GList *list;
+
+  bookmark_file=g_strconcat(g_get_home_dir(), BOOKMARK_FILE ,NULL);
+
+  if ((file = open(bookmark_file, O_CREAT | O_WRONLY | O_TRUNC, 0600)) > 0)
+  {
+    for (list = g_list_first (fs->bookmark_list); list != NULL; list = g_list_next(list)) {
+      item = list->data;
+      item_data = g_strconcat(item->desc, " <", item->path, ">\n", NULL);
+      if (write (file, item_data, strlen(item_data)) != strlen(item_data)) {
+	return TRUE;
+      }
+      g_free(item_data);
+    }
+    
+    close(file);
+  } else {
+    return TRUE;
+  }
+
+  return FALSE;
+}
+
+static void
+gtk_file_selection_load_masks(GtkFileSelection *fs)
+{
+  /*
+  GList *list;
+  gchar *masks_file;
+  gchar *masks_data;
+  struct stat file_info;
+  gint   file;
+  gint   lp;
+  gint   cp;
+
+  if(fs->masks){
+    list=fs->masks;
+    while(list){
+      g_free(list->data);
+      list=list->next;
+    }
+    fs->masks = NULL;
+  }
+
+  masks_file=g_strconcat(g_get_home_dir(), MASK_FILE,NULL); //put in #define
+  if(!stat(masks_file,&file_info))
+  {
+    if(file_info.st_size <65536 )
+    {
+      masks_data=g_malloc(file_info.st_size);
+
+      file = open(masks_file,  O_RDONLY );
+
+      if(file && read(file, masks_data, file_info.st_size))
+      {
+        cp=lp=0;
+
+        while (cp < file_info.st_size)
+        {
+          while (cp < file_info.st_size && masks_data[cp] != '>' )
+            cp++;
+
+          masks_data[++cp]=0;
+          if (masks_data[lp]=='<') { //if there was no description, strip off brackets
+            lp++;
+            masks_data[cp-1]=0;
+          }
+//          g_print("%s\n",masks_data+lp);
+          fs->masks = g_list_append(fs->masks, g_strdup(masks_data+lp));
+
+          while(cp < file_info.st_size && masks_data[cp] < 33 )
+            cp++;
+          lp=cp;
+        }
+      }
+
+      close(file);
+    }
+  }
+  */
+  if (!fs->masks) {
+    /* masks is still null, fill it with default data... */
+    /*
+    fs->masks = g_list_append(fs->masks, "all files <*>");
+    fs->masks = g_list_append(fs->masks, "mp3s/playlists <*.mp3,*.m3u>");
+    fs->masks = g_list_append(fs->masks, "src/hdr <*.[CcHh],*.[Cc][Cc],*.[Hh][Hh],*.cpp>");
+    fs->masks = g_list_append(fs->masks, "html docs <*.html,*.htm,*.HTM,*.php*,*.inc>");
+    fs->masks = g_list_append(fs->masks, "images <*.png,*.jpg,*.jpeg,*.gif,*.xpm,*.tiff>");
+    fs->masks = g_list_append(fs->masks, "package <*.rpm,*.deb>");
+    fs->masks = g_list_append(fs->masks, "archive <*.tgz,*.tb2,*.tar*,*.zip,*.rar>");
+    fs->masks = g_list_append(fs->masks, "compressed <*.Z,*.gz,*.bz2>");
+    */
+  }
+}
+
+void gtk_file_selection_clear_masks (GtkFileSelection *filesel)
+{
+  GList *list;
+
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+
+  list = filesel->masks;
+  while (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  filesel->masks = NULL;
+
+  gtk_list_clear_items (GTK_LIST (GTK_COMBO (filesel->mask_entry)->list), 0, -1);
+}
+
+void gtk_file_selection_set_masks (GtkFileSelection *filesel, const gchar **masks)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+
+  while (*masks)
+    {
+      filesel->masks = g_list_append (filesel->masks, (gpointer)*masks);
+      masks++;
+    }
+
+  if (filesel->masks)
+    gtk_combo_set_popdown_strings (GTK_COMBO (filesel->mask_entry), filesel->masks);
+}
+
+GtkType
+gtk_file_selection_get_type (void)
+{
+  static GtkType file_selection_type = 0;
+
+  if (!file_selection_type)
+    {
+      static const GtkTypeInfo filesel_info =
+      {
+	"GtkFileSelection",
+	sizeof (GtkFileSelection),
+	sizeof (GtkFileSelectionClass),
+	(GtkClassInitFunc) gtk_file_selection_class_init,
+	(GtkObjectInitFunc) gtk_file_selection_init,
+	/* reserved_1 */ NULL,
+	/* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
+      };
+
+      file_selection_type = gtk_type_unique (GTK_TYPE_WINDOW, &filesel_info);
+    }
+
+  return file_selection_type;
+}
+
+static void
+gtk_file_selection_class_init (GtkFileSelectionClass *class)
+{
+  GtkObjectClass *object_class;
+  GtkWidgetClass *widget_class;
+
+  object_class = (GtkObjectClass*) class;
+
+  parent_class = gtk_type_class (GTK_TYPE_WINDOW);
+
+  widget_class = GTK_WIDGET_CLASS (class);
+
+  widget_class->realize = gtk_file_selection_realize;
+  object_class->destroy = gtk_file_selection_destroy;
+}
+
+static void
+gtk_file_selection_init (GtkFileSelection *filesel)
+{
+  GtkWidget *entry_vbox;
+  GtkWidget *label;
+  GtkWidget *list_vbox;
+  GtkWidget *confirm_area;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *hbox2;
+  GtkWidget *table;
+  GtkWidget *pulldown_hbox;
+  GtkWidget *scrolled_win;
+  GtkWidget *mask_label;
+  GtkWidget *bigframe;
+  GtkWidget *button;
+  GtkWidget *hpaned;
+  GtkWidget *menu_item;
+  GtkWidget *pixmap;
+
+  char *dir_title [2];
+  char *file_title [2];
+  
+  filesel->cmpl_state = cmpl_init_state ();
+
+  filesel->mask=NULL;
+  filesel->prev_history=NULL;
+  filesel->next_history=NULL;
+  filesel->saved_entry=NULL;
+  filesel->bookmark_list=NULL;
+  filesel->masks=NULL;
+  filesel->selection_text = NULL;
+  filesel->fileop_data = NULL;
+
+  gtk_file_selection_load_masks(filesel);
+  gtk_file_selection_load_bookmarks(filesel);
+
+  /* The dialog-sized vertical box  */
+  filesel->main_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (filesel), 0);
+  gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
+  gtk_widget_show (filesel->main_vbox);
+
+  /* hbox for pulldown menu */
+  pulldown_hbox = gtk_hbox_new (FALSE, 0);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);
+  gtk_widget_show (pulldown_hbox);
+  
+  /* The horizontal box containing create, rename etc. buttons */
+
+/*
+  filesel->button_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(filesel->button_area), GTK_BUTTONBOX_START);
+  gtk_button_box_set_spacing(GTK_BUTTON_BOX(filesel->button_area), 0);
+  gtk_box_pack_start (GTK_BOX (pulldown_hbox), filesel->button_area,
+		      FALSE, FALSE, 0);
+  gtk_button_box_set_child_size(GTK_BUTTON_BOX(filesel->button_area),0,0);
+  gtk_button_box_set_child_ipadding(GTK_BUTTON_BOX(filesel->button_area),0,0);
+  */
+
+  filesel->button_area = gtk_hbox_new (TRUE,0);
+  //gtk_box_pack_start (GTK_BOX (pulldown_hbox), filesel->button_area,
+  //		      FALSE, FALSE, 0);
+
+  //gtk_widget_show (filesel->button_area);
+
+  gtk_file_selection_show_fileop_buttons(filesel);
+  /*  frame to put the following hbox in  */
+  bigframe = gtk_frame_new (NULL);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), bigframe, TRUE, TRUE, 0);
+  gtk_frame_set_shadow_type (GTK_FRAME (bigframe), GTK_SHADOW_OUT);
+  gtk_widget_show (bigframe);
+
+
+  list_vbox = gtk_vbox_new (FALSE,3);
+  gtk_widget_show(list_vbox);
+  gtk_container_add (GTK_CONTAINER(bigframe), list_vbox);
+  gtk_container_set_border_width (GTK_CONTAINER (list_vbox),2);
+  gtk_widget_show (list_vbox);
+  
+  /*  The horizontal box containing the directory and file listboxes  */
+//  list_hbox = gtk_hbox_new (FALSE, 3);
+  //gtk_container_add (GTK_CONTAINER(bigframe), list_hbox);
+  //gtk_container_set_border_width (GTK_CONTAINER (list_hbox), 3);
+//  gtk_box_pack_start(GTK_BOX(list_vbox), list_hbox, FALSE,FALSE,0);
+//  gtk_widget_show (list_hbox);
+
+  hpaned=gtk_hpaned_new();
+  gtk_widget_show(hpaned);
+  gtk_container_set_border_width (GTK_CONTAINER (hpaned), 1);
+  gtk_paned_set_gutter_size (GTK_PANED (hpaned), 10);
+  gtk_box_pack_start (GTK_BOX(list_vbox), hpaned,TRUE,TRUE,0);
+
+  /* vbox to put the buttons and directory listing in  */
+  vbox = gtk_vbox_new (FALSE, 3);
+  gtk_widget_show (vbox);
+  gtk_container_add(GTK_CONTAINER(hpaned),vbox);
+  //gtk_box_pack_start (GTK_BOX (hpaned), vbox, FALSE, FALSE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 4);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+//  home_button = gtk_button_new_with_label (_("Home"));
+//  gtk_widget_show (home_button);
+//  gtk_signal_connect (GTK_OBJECT (home_button), "clicked",
+//		      (GtkSignalFunc) gtk_file_selection_home_button,
+//		      (gpointer) filesel);
+//  gtk_box_pack_start (GTK_BOX (hbox), home_button, TRUE,TRUE, 0);
+
+  /* Here we add the bookmark menu button */
+  #define If we're going to make bookmark a menu, we don't need 
+  #define   to keep it in the filesel structure
+  button=gtk_button_new_with_label(_("Bookmarks"));
+  gtk_widget_show(button);
+  gtk_box_pack_start (GTK_BOX(hbox), button, FALSE,FALSE,0);
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_bookmark_button,
+		      (gpointer) filesel);
+  
+  hbox2 = gtk_hbox_new (FALSE, 2);
+  gtk_box_pack_start (GTK_BOX (hbox), hbox2, FALSE, FALSE, 0);
+  gtk_widget_show(hbox2);
+
+  /* Prev button */
+  button = gtk_button_new ();
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_prev_button,
+		      (gpointer) filesel);
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE,FALSE, 0);
+  pixmap = create_pixmap (filesel->main_vbox, (gpointer) back_xpm);
+  gtk_widget_show (pixmap);
+  gtk_container_add (GTK_CONTAINER (button), pixmap);
+
+  /* Up button */
+  button = gtk_button_new ();
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_up_button,
+		      (gpointer) filesel);
+  gtk_widget_show (button);
+  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE,FALSE, 0);
+  pixmap = create_pixmap (filesel->main_vbox, (gpointer) up_xpm);
+  gtk_widget_show (pixmap);
+  gtk_container_add (GTK_CONTAINER (button), pixmap);
+
+  /* next button */
+  button = gtk_button_new ();
+  gtk_widget_show (button);
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_next_button,
+		      (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox2), button, FALSE,FALSE, 0);
+  pixmap = create_pixmap (filesel->main_vbox, (gpointer) forward_xpm);
+  gtk_widget_show (pixmap);
+  gtk_container_add (GTK_CONTAINER (button), pixmap);
+
+  /* refresh button */
+  button = gtk_button_new ();
+  gtk_widget_show (button);
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_refresh_button,
+		      (gpointer) filesel);
+  gtk_box_pack_end (GTK_BOX (hbox), button, FALSE,FALSE, 0);
+  pixmap = create_pixmap (filesel->main_vbox, (gpointer) refresh_xpm);
+  gtk_widget_show (pixmap);
+  gtk_container_add (GTK_CONTAINER (button), pixmap);
+
+  /* menu for right click file operations */
+  filesel->fileop_menu = gtk_menu_new();
+  
+  menu_item = gtk_menu_item_new_with_label ("Rename...");
+  gtk_widget_show(menu_item);
+  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
+			     (GtkSignalFunc) gtk_file_selection_rename_file,
+			     (gpointer) filesel);
+  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
+
+  menu_item = gtk_menu_item_new_with_label ("Delete");
+  gtk_widget_show(menu_item);
+  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
+  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
+			     (GtkSignalFunc) gtk_file_selection_delete_file,
+			     (gpointer) filesel);
+
+  menu_item = gtk_menu_item_new ();
+  gtk_widget_show(menu_item);
+  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
+
+  menu_item = gtk_menu_item_new_with_label ("Create Directory...");
+  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
+			     (GtkSignalFunc) gtk_file_selection_create_dir, 
+			     (gpointer) filesel);
+  gtk_widget_show(menu_item);
+  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
+
+  menu_item = gtk_menu_item_new ();
+  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
+  gtk_widget_show(menu_item);
+
+  menu_item = gtk_menu_item_new_with_label ("Properties...");
+  gtk_signal_connect_object (GTK_OBJECT (menu_item), "activate",
+			     (GtkSignalFunc) gtk_file_selection_properties,
+			     (gpointer) filesel);
+  gtk_menu_append (GTK_MENU (filesel->fileop_menu), menu_item);
+  gtk_widget_show(menu_item);
+
+  /* The directories clist */
+  dir_title[0] = _("Directories");
+  dir_title[1] = NULL;
+  filesel->dir_list = gtk_clist_new_with_titles (1, (gchar**) dir_title);
+  gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
+  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",
+		      (GtkSignalFunc) gtk_file_selection_dir_button,
+		      (gpointer) filesel);
+  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "unselect_row",
+		      (GtkSignalFunc) gtk_file_selection_undir_button,
+		      (gpointer) filesel);
+  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "button_press_event",
+		      GTK_SIGNAL_FUNC(gtk_file_selection_show_fileop_menu), 
+		      (gpointer) filesel);
+
+  gtk_clist_column_titles_passive (GTK_CLIST (filesel->dir_list));
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->dir_list);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE,TRUE, 0);
+  //gtk_container_add(GTK_CONTAINER(hpaned), scrolled_win);
+  
+  gtk_widget_show (filesel->dir_list);
+  gtk_widget_show (scrolled_win);
+
+  vbox = gtk_vbox_new (FALSE, 3);
+  gtk_widget_show (vbox);
+  gtk_container_add(GTK_CONTAINER(hpaned),vbox);
+  /* vbox area for mask entry and files clist  */
+
+  hbox = gtk_hbox_new (FALSE, 2);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  mask_label = gtk_label_new (_("Mask:"));
+  gtk_widget_show (mask_label);
+  gtk_box_pack_start (GTK_BOX (hbox), mask_label, FALSE, FALSE, 2);
+
+/*
+  filesel->mask_entry = gtk_entry_new ();
+  gtk_widget_show (filesel->mask_entry);
+  gtk_signal_connect(GTK_OBJECT(filesel->mask_entry),"activate",
+		     (GtkSignalFunc) gtk_file_4_mask_entry_callback,
+		     (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
+  */
+
+  filesel->mask_entry = gtk_combo_new ();
+  gtk_widget_show (filesel->mask_entry);
+  gtk_combo_set_value_in_list(GTK_COMBO(filesel->mask_entry),FALSE,FALSE);
+  gtk_signal_connect(GTK_OBJECT(GTK_COMBO(filesel->mask_entry)->entry),"activate",
+		     (GtkSignalFunc) gtk_file_selection_mask_entry_callback,
+		     (gpointer) filesel);
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->mask_entry)->entry),"key-press-event",				
+		     (GtkSignalFunc) gtk_file_selection_mask_entry_key_callback,
+		     (gpointer) filesel);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->mask_entry)->list),"button-release-event",
+		     (GtkSignalFunc) gtk_file_selection_mask_entry_button_callback,
+		     (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
+
+  if (filesel->masks)
+    gtk_combo_set_popdown_strings (GTK_COMBO (filesel->mask_entry), filesel->masks);
+
+
+  /* The files clist */
+  file_title[0] = _("Files");
+  file_title[1] = NULL;
+  filesel->file_list = gtk_clist_new_with_titles (1, (gchar**) file_title);
+  gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
+  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
+		      (GtkSignalFunc) gtk_file_selection_file_button, 
+		      (gpointer) filesel);
+  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "key-press-event",
+		      (GtkSignalFunc) gtk_file_selection_files_list_key_callback,
+		      (gpointer) filesel);
+  
+  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "button_press_event",
+		      GTK_SIGNAL_FUNC(gtk_file_selection_show_fileop_menu), 
+		      (gpointer) filesel);
+
+  gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->file_list);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 0);
+  gtk_widget_show (filesel->file_list);
+  gtk_widget_show (scrolled_win);
+
+  /* action area for packing buttons into. */
+  filesel->action_area = gtk_hbox_new (TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->action_area, 
+		      FALSE, FALSE, 2);
+  gtk_widget_show (filesel->action_area);
+
+  /*
+  hbox=gtk_hbox_new(FALSE,0);
+  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), hbox, FALSE,FALSE, 0);
+  gtk_widget_show (hbox);
+  */
+
+  /*  The selection entry widget  */
+  
+  entry_vbox = gtk_vbox_new (FALSE, 0);
+  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
+  gtk_widget_show (entry_vbox);
+
+  table = gtk_table_new ( 2, 2, FALSE );
+  gtk_box_pack_start (GTK_BOX (entry_vbox), table, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (table), 4);
+  gtk_table_set_row_spacings (GTK_TABLE (table), 2);
+  gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+
+
+  label = gtk_label_new (_("Selection:"));
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
+                    (GtkAttachOptions) (0),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_widget_show (label);
+
+
+  filesel->selection_entry = gtk_entry_new ();
+  gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
+		      (GtkSignalFunc) gtk_file_selection_key_press, filesel);
+  gtk_table_attach (GTK_TABLE (table), filesel->selection_entry, 1, 2, 0, 1,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_widget_show (filesel->selection_entry);
+
+
+  label = gtk_label_new (_("Directory:"));
+  gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+                    (GtkAttachOptions) (0),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_widget_show (label);
+  
+
+  filesel->history_combo = gtk_combo_new();
+  gtk_combo_set_value_in_list(GTK_COMBO(filesel->history_combo),FALSE,FALSE);
+  gtk_table_attach (GTK_TABLE (table), filesel->history_combo, 1, 2, 1, 2,
+                    (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+                    (GtkAttachOptions) (0), 0, 0);
+  gtk_widget_show(filesel->history_combo);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->entry),"key-press-event",				    
+		     (GtkSignalFunc) gtk_file_selection_history_combo_callback,
+		     (gpointer) filesel);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"button-press-event",
+		     (GtkSignalFunc) gtk_file_selection_history_combo_list_callback,
+		     (gpointer) filesel);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"key-press-event",
+		     (GtkSignalFunc) gtk_file_selection_history_combo_list_key_handler,
+		     (gpointer) filesel);
+
+  filesel->selection_text = NULL;
+
+
+  /*  The OK/Cancel button area */
+  confirm_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);
+  gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);
+  gtk_box_pack_end (GTK_BOX (entry_vbox), confirm_area, FALSE, FALSE, 0);
+  gtk_widget_show (confirm_area);
+
+  /*  The OK button  */
+  filesel->ok_button = gtk_button_new_with_label (_("OK"));
+  GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->ok_button, TRUE, TRUE, 0);
+  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
+			     (GtkSignalFunc) gtk_widget_grab_default,
+			     GTK_OBJECT (filesel->ok_button));
+  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
+                             (GtkSignalFunc) gtk_button_clicked,
+                             GTK_OBJECT (filesel->ok_button));
+  gtk_widget_grab_default (filesel->ok_button);
+  gtk_widget_show (filesel->ok_button);
+
+  /*  The Cancel button  */
+  filesel->cancel_button = gtk_button_new_with_label (_("Cancel"));
+  GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->cancel_button, TRUE, TRUE, 0);
+  gtk_widget_show (filesel->cancel_button);
+
+  gtk_widget_show(table);
+
+
+  /*
+  filesel->selection_text = label = gtk_label_new ("");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+  */
+
+
+  if (!cmpl_state_okay (filesel->cmpl_state))
+    {
+      gchar err_buf[256];
+
+      sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
+
+      /*
+      gtk_label_set_text (GTK_LABEL (filesel->selection_text), err_buf);
+      */
+    }
+  else
+    {
+      gtk_file_selection_populate (filesel, "", FALSE);
+    }
+
+  gtk_widget_grab_focus (filesel->selection_entry);
+}
+
+GtkWidget*
+gtk_file_selection_new (const gchar *title)
+{
+  GtkFileSelection *filesel;
+
+  filesel = gtk_type_new (GTK_TYPE_FILE_SELECTION);
+  gtk_window_set_title (GTK_WINDOW (filesel), title);
+  /* !!! put check here to figure out if screen > 640x480, if true
+     We need to make the file selection dialog bigger. much bigger.. 
+     or maybe we should keep it at a certan percentage of the screen
+     size? */
+
+  gtk_window_set_default_size(GTK_WINDOW (filesel), 520, 420);
+  return GTK_WIDGET (filesel);
+}
+
+void
+gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+
+  return;
+	
+  /* delete, create directory, and rename */
+/*
+  if (!filesel->fileop_c_dir) 
+    {
+      filesel->fileop_c_dir = gtk_button_new_with_label (_("MkDir"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_c_dir), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_create_dir, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_c_dir, TRUE,TRUE, 0);
+      gtk_widget_show (filesel->fileop_c_dir);
+    }
+	
+  if (!filesel->fileop_del_file) 
+    {
+      filesel->fileop_del_file = gtk_button_new_with_label (_("Delete"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_del_file), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_delete_file, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_del_file, TRUE,TRUE, 0);
+      gtk_widget_show (filesel->fileop_del_file);
+    }
+
+  if (!filesel->fileop_ren_file)
+    {
+      filesel->fileop_ren_file = gtk_button_new_with_label (_("Rename"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_ren_file), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_rename_file, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_ren_file, TRUE,TRUE, 0);
+      gtk_widget_show (filesel->fileop_ren_file);
+    }
+
+  gtk_widget_queue_resize(GTK_WIDGET(filesel));
+  */
+}
+
+void       
+gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+  
+  return;
+  /*
+  if (filesel->fileop_ren_file) 
+    {
+      gtk_widget_destroy (filesel->fileop_ren_file);
+      filesel->fileop_ren_file = NULL;
+    }
+
+  if (filesel->fileop_del_file)
+    {
+      gtk_widget_destroy (filesel->fileop_del_file);
+      filesel->fileop_del_file = NULL;
+    }
+
+  if (filesel->fileop_c_dir)
+    {
+      gtk_widget_destroy (filesel->fileop_c_dir);
+      filesel->fileop_c_dir = NULL;
+    }
+  */
+}
+
+
+
+void
+gtk_file_selection_set_filename (GtkFileSelection *filesel,
+				 const gchar      *filename)
+{
+  char  buf[MAXPATHLEN];
+  const char *name, *last_slash;
+
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+  g_return_if_fail (filename != NULL);
+
+  last_slash = strrchr (filename, '/');
+
+  if (!last_slash)
+    {
+      buf[0] = 0;
+      name = filename;
+    }
+  else
+    {
+      gint len = MIN (MAXPATHLEN - 1, last_slash - filename + 1);
+
+      strncpy (buf, filename, len);
+      buf[len] = 0;
+
+      name = last_slash + 1;
+    }
+
+  gtk_file_selection_populate (filesel, buf, FALSE);
+
+  if (filesel->selection_entry)
+    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
+}
+
+gchar*
+gtk_file_selection_get_filename (GtkFileSelection *filesel)
+{
+  static char nothing[2] = "";
+  char *text;
+  char *filename;
+
+  g_return_val_if_fail (filesel != NULL, nothing);
+  g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), nothing);
+
+  text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
+  if (text)
+    {
+      filename = cmpl_completion_fullname (text, filesel->cmpl_state);
+      return filename;
+    }
+
+  return nothing;
+}
+
+void
+gtk_file_selection_complete (GtkFileSelection *filesel,
+			     const gchar      *pattern)
+{
+  gchar *new_pattern;
+  gint x;
+	
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+  g_return_if_fail (pattern != NULL);
+
+  if (filesel->selection_entry)
+    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), pattern);
+	
+  if(strchr(pattern,'*') || strchr(pattern,'?'))
+    {
+      for(x=strlen(pattern);x>=0;x--)
+	{
+	  if(pattern[x]=='/') break;
+	}
+      gtk_entry_set_text(GTK_ENTRY(filesel->mask_entry),g_strdup(pattern+x+1));
+      
+      if(filesel->mask) g_free(filesel->mask);
+      
+      filesel->mask=g_strdup(pattern+x+1);
+      new_pattern=g_strdup(pattern);
+      new_pattern[x+1]=0;
+      gtk_file_selection_populate (filesel, (gchar*) new_pattern, TRUE);
+      g_free(new_pattern);
+    }
+  else
+    {
+      gtk_file_selection_populate (filesel, (gchar*) pattern, TRUE);
+    }
+}
+
+static void
+gtk_file_selection_realize (GtkWidget *widget)
+{
+  GtkFileSelection *filesel;
+  const gchar *masks[] = { "All Files <*>", NULL };
+
+  g_return_if_fail (widget != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (widget));
+
+  filesel = GTK_FILE_SELECTION (widget);
+
+  /* make sure that we have at least one mask */
+  if (!filesel->masks)
+    gtk_file_selection_set_masks (filesel, masks);
+
+  filesel->mask = g_strdup ((gchar*) filesel->masks->data);
+  gtk_file_selection_populate (filesel, "", FALSE);
+
+
+  if (GTK_WIDGET_CLASS (parent_class)->realize)
+    (* GTK_WIDGET_CLASS (parent_class)->realize) (widget);
+}
+
+static void
+gtk_file_selection_destroy (GtkObject *object)
+{
+  GtkFileSelection *filesel;
+  GList *list;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (object));
+
+  filesel = GTK_FILE_SELECTION (object);
+  
+  if (filesel->fileop_dialog)
+    gtk_widget_destroy (filesel->fileop_dialog);
+  
+  if (filesel->next_history)
+    {
+      list = filesel->next_history;
+      while (list)
+  	{
+	  g_free (list->data);
+	  list = list->next;
+  	}
+    }
+  g_list_free (filesel->next_history);
+  filesel->next_history = NULL;
+
+  if (filesel->prev_history)
+    {
+      list = filesel->prev_history;
+      while (list)
+  	{
+	  g_free (list->data);
+	  list = list->next;
+  	}
+    }
+  g_list_free (filesel->prev_history);
+  filesel->prev_history = NULL;
+
+  if (filesel->mask)
+    {
+      g_free (filesel->mask);
+      filesel->mask = NULL;
+    }
+  
+  cmpl_free_state (filesel->cmpl_state);
+  filesel->cmpl_state = NULL;
+
+  if (GTK_OBJECT_CLASS (parent_class)->destroy)
+    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/* Begin file operations callbacks */
+
+static gint
+gtk_file_selection_show_fileop_menu (GtkCList *clist, GdkEvent *event, GtkFileSelection *fs)
+{
+  GdkEventButton *event_button;
+
+  g_return_val_if_fail (clist != NULL, FALSE);
+  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+  g_return_val_if_fail (fs != NULL, FALSE);
+  g_return_val_if_fail (GTK_FILE_SELECTION (fs), FALSE);
+  
+  if (event->type == GDK_BUTTON_PRESS)
+    {
+      event_button = (GdkEventButton *) event;
+      if (event_button->button == 3)
+	{
+
+	  gtk_menu_popup (GTK_MENU (fs->fileop_menu), NULL, NULL, NULL, NULL, 
+			  event_button->button, event_button->time);
+	  return TRUE;
+	}
+    }
+  
+  return FALSE;
+}
+
+static void
+gtk_file_selection_fileop_error (GtkFileSelection *fs, gchar *error_message)
+{
+  GtkWidget *label;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *dialog;
+  
+  g_return_if_fail (error_message != NULL);
+  
+  /* main dialog */
+  dialog = gtk_dialog_new ();
+  /*
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  */
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+  
+  /* If file dialog is grabbed, make this dialog modal too */
+  /* When error dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+
+  label = gtk_label_new(error_message);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+
+  /* yes, we free it */
+  g_free (error_message);
+  
+  /* close button */
+  button = gtk_button_new_with_label (_("Close"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_fileop_destroy (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  fs->fileop_dialog = NULL;
+  g_free (fs->fileop_data);
+  fs->fileop_data = NULL;
+}
+
+
+static void
+gtk_file_selection_create_dir_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  gchar *dirname;
+  gchar *path;
+  gchar *full_path;
+  gchar *buf;
+  CompletionState *cmpl_state;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  dirname = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  full_path = g_strconcat (path, "/", dirname, NULL);
+  if ( (mkdir (full_path, 0755) < 0) ) 
+    {
+      buf = g_strconcat ("Error creating directory \"", dirname, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (full_path);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+  
+static void
+gtk_file_selection_create_dir (gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *button;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Create Directory"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+  
+  label = gtk_label_new(_("Directory name:"));
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+
+  /*  The directory entry widget  */
+  fs->fileop_entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
+		      TRUE, TRUE, 5);
+  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+  gtk_widget_show (fs->fileop_entry);
+  
+  /* buttons */
+  button = gtk_button_new_with_label (_("Create"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_create_dir_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_delete_file_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  CompletionState *cmpl_state;
+  gchar *path;
+  gchar *full_path;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  full_path = g_strconcat (path, "/", fs->fileop_file, NULL);
+  if ( (unlink (full_path) < 0) ) 
+    {
+      buf = g_strconcat ("Error deleting file \"", fs->fileop_file, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (full_path);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+
+static void
+gtk_file_selection_delete_file (gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *dialog;
+  gchar *filename;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+
+  filename = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+  if (strlen(filename) < 1)
+	  return;
+
+  fs->fileop_file = filename;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Delete File"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+  
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+
+  buf = g_strconcat ("Really delete file \"", filename, "\" ?", NULL);
+  label = gtk_label_new(buf);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+  g_free(buf);
+  
+  /* buttons */
+  button = gtk_button_new_with_label (_("Delete"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_delete_file_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+
+}
+
+static void
+gtk_file_selection_rename_file_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  gchar *buf;
+  gchar *file;
+  gchar *path;
+  gchar *new_filename;
+  gchar *old_filename;
+  CompletionState *cmpl_state;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  new_filename = g_strconcat (path, "/", file, NULL);
+  old_filename = g_strconcat (path, "/", fs->fileop_file, NULL);
+
+  if (strcmp (new_filename, old_filename))
+    if ((rename (old_filename, new_filename)) < 0) 
+      {
+        buf = g_strconcat ("Error renaming file \"", file, "\":  ", 
+                           g_strerror(errno), NULL);
+        gtk_file_selection_fileop_error (fs, buf);
+      }
+  g_free (new_filename);
+  g_free (old_filename);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+  
+static void
+gtk_file_selection_file_mode_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  PropertiesPrivate *priv = fs->fileop_data;
+  CompletionState *cmpl_state;
+  gchar *filename, *file, *path;
+  mode_t mode;
+
+  mode = gtk_file_selection_properties_get_mode (priv);
+
+  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+
+  filename = g_strconcat (path, "/", file, NULL);
+  if (chmod (filename, mode) == -1)
+    {
+      gchar *buf = g_strconcat ("Error changing file mode of \"", filename, "\":  ", 
+                                g_strerror (errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+      gtk_widget_destroy (fs->fileop_dialog);
+      gtk_file_selection_populate (fs, "", FALSE);
+    }
+  else
+    gtk_file_selection_rename_file_confirmed (widget, data);
+
+  g_free (filename);
+}
+
+static void
+gtk_file_selection_rename_file (gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+
+  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+  if (strlen(fs->fileop_file) < 1)
+	  return;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Rename File"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog  closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+  
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+  
+  buf = g_strconcat ("Rename file \"", fs->fileop_file, "\" to:", NULL);
+  label = gtk_label_new(buf);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+  g_free(buf);
+
+  /* New filename entry */
+  fs->fileop_entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
+		      TRUE, TRUE, 5);
+  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+  gtk_widget_show (fs->fileop_entry);
+  
+  gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
+  gtk_editable_select_region (GTK_EDITABLE (fs->fileop_entry),
+			      0, strlen (fs->fileop_file));
+
+  /* buttons */
+  button = gtk_button_new_with_label (_("Rename"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+static mode_t
+gtk_file_selection_properties_get_mode (PropertiesPrivate* priv)
+{
+  mode_t mode = 0;
+
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[0])))
+    mode |= S_IRUSR;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[1])))
+    mode |= S_IWUSR;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[2])))
+    mode |= S_IXUSR;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[3])))
+    mode |= S_ISUID;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[4])))
+    mode |= S_IRGRP;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[5])))
+    mode |= S_IWGRP;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[6])))
+    mode |= S_IXGRP;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[7])))
+    mode |= S_ISGID;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[8])))
+    mode |= S_IROTH;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[9])))
+    mode |= S_IWOTH;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[10])))
+    mode |= S_IXOTH;
+  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->mode_buttons[11])))
+    mode |= S_ISVTX;
+
+  return mode;
+}
+
+static void
+gtk_file_selection_properties_update_mode (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  PropertiesPrivate *priv = fs->fileop_data;
+  gchar str[8];
+
+  sprintf (str, "(%.4o)", gtk_file_selection_properties_get_mode (priv));
+  gtk_label_set (GTK_LABEL (priv->mode_label), str);
+}
+
+static void
+gtk_file_selection_properties (gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *button;
+  GtkWidget *notebook;
+  GtkWidget *table;
+  GtkWidget *hseparator;
+  GtkWidget *entry;
+  GtkWidget *togglebutton;
+  struct stat statbuf;
+  struct passwd *pw;
+  struct group *gp;
+  gchar *buf;
+  gchar *path;
+  gchar *filename;
+  gchar timeBuf[TIME_STRING_BUF];
+  gint pagenum = 0;
+  PropertiesPrivate *priv;
+  int i;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  priv = fs->fileop_data = g_malloc (sizeof (PropertiesPrivate));
+
+  gtk_window_set_title (GTK_WINDOW (dialog), ("Properties"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog  closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+  
+  /* Dialog guts go here */
+  notebook = gtk_notebook_new ();
+  gtk_widget_show (notebook);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->vbox), notebook, TRUE, TRUE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER (notebook), 8);
+
+  path = cmpl_reference_position(fs->cmpl_state);
+  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+  filename = g_strconcat(path, "/", fs->fileop_file, NULL);
+  if (strlen(fs->fileop_file) > 0 && !(stat(filename, &statbuf))) 
+  {
+    /* stats page */
+    table = gtk_table_new (9, 2, FALSE);
+    gtk_widget_show (table);
+    gtk_container_add (GTK_CONTAINER (notebook), table);
+    gtk_container_set_border_width (GTK_CONTAINER (table), 5);
+    gtk_table_set_row_spacings (GTK_TABLE (table), 4);
+    gtk_table_set_col_spacings (GTK_TABLE (table), 6);
+    
+    label = gtk_label_new (_("Statistics"));
+    gtk_widget_show (label);
+    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), pagenum), label);
+    pagenum++;
+    /* path and filename */
+    label = gtk_label_new (_("Path:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    label = gtk_label_new (_(path));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    label = gtk_label_new (_("File Name:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    fs->fileop_entry = entry = gtk_entry_new ();
+    gtk_widget_show (entry);
+    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_entry_set_text (GTK_ENTRY (entry), fs->fileop_file);
+    if (access (filename, W_OK))
+      gtk_widget_set_sensitive( GTK_WIDGET (entry), FALSE);
+    
+    hseparator = gtk_hseparator_new ();
+    gtk_widget_show (hseparator);
+    gtk_table_attach (GTK_TABLE (table), hseparator, 0, 2, 2, 3,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (GTK_FILL), 0, 0);
+    
+    /* file type and size */
+    label = gtk_label_new (_("Type:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+    switch (statbuf.st_mode & S_IFMT)
+    {
+    case S_IFSOCK:
+      buf = g_strdup ("Socket");
+      break;
+    case S_IFLNK:
+      buf = g_strdup ("Symbolic link");
+      break;
+    case S_IFREG:
+      buf = g_strdup ("File");
+      break;
+    case S_IFBLK:
+      buf = g_strdup ("Block device");
+      break;
+    case S_IFDIR:
+      buf = g_strdup ("Directory");
+      break;
+    case S_IFCHR:
+      buf = g_strdup ("Character device");
+      break;
+    case S_IFIFO:
+      buf = g_strdup ("First-in/first-out pipe");
+      break;
+    default:
+      buf = g_strdup ("Unknown");
+    }
+
+
+    label = gtk_label_new (buf);
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 3, 4,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    label = gtk_label_new (_("Size:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 4, 5,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    label = gtk_label_new (_(g_strdup_printf ("%ld bytes", statbuf.st_size)));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 4, 5,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    hseparator = gtk_hseparator_new ();
+    gtk_widget_show (hseparator);
+    gtk_table_attach (GTK_TABLE (table), hseparator, 0, 2, 5, 6,
+		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+		      (GtkAttachOptions) (GTK_FILL), 0, 0);
+    
+    /* file dates */
+    label = gtk_label_new (_("Created:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 6, 7,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    strftime (timeBuf, TIME_STRING_BUF, "%a %b %d %X %Y", localtime(&statbuf.st_mtime));
+    label = gtk_label_new (_(timeBuf));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 6, 7,
+		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    
+    
+    label = gtk_label_new (_("Modified:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 7, 8,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    strftime (timeBuf, TIME_STRING_BUF, "%a %b %d %X %Y", localtime(&statbuf.st_mtime));
+    label = gtk_label_new (_(timeBuf));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 7, 8,
+		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    
+    label = gtk_label_new (_("Accessed:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 8, 9,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    strftime (timeBuf, TIME_STRING_BUF, "%a %b %d %X %Y", localtime(&statbuf.st_atime));
+    label = gtk_label_new (_(timeBuf));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 8, 9,
+		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_label_set_justify (GTK_LABEL (label), GTK_JUSTIFY_LEFT);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);  
+    
+    /* permissions page */
+    vbox = gtk_vbox_new (FALSE, 4);
+    gtk_widget_show (vbox);
+    gtk_container_add (GTK_CONTAINER (notebook), vbox);
+    gtk_container_set_border_width (GTK_CONTAINER (vbox), 5);
+    
+    label = gtk_label_new (_("Permissions"));
+    gtk_widget_show (label);
+    gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), pagenum), label);
+    pagenum++;
+
+    /* owner / group */
+    table = gtk_table_new (2, 2, FALSE);
+    gtk_widget_show (table);
+    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, TRUE, 0);
+    gtk_table_set_row_spacings (GTK_TABLE (table), 2);
+    gtk_table_set_col_spacings (GTK_TABLE (table), 8);
+    
+    label = gtk_label_new (_("Owner:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 0, 1,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+
+    entry = gtk_entry_new();
+    gtk_widget_show (entry);
+    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 0, 1,
+		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((pw = getpwuid(statbuf.st_uid)))
+      gtk_entry_set_text(GTK_ENTRY (entry), pw->pw_name);
+    else
+      gtk_entry_set_text(GTK_ENTRY (entry), (gpointer) statbuf.st_uid);
+    if (access (filename, W_OK) || (getuid() != 0))
+      gtk_widget_set_sensitive( GTK_WIDGET (entry), FALSE);
+
+
+    label = gtk_label_new (_("Group:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    entry = gtk_entry_new();
+    gtk_widget_show (entry);
+    gtk_table_attach (GTK_TABLE (table), entry, 1, 2, 1, 2,
+		      (GtkAttachOptions) (GTK_EXPAND | GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((gp = getgrgid(statbuf.st_gid)))
+      gtk_entry_set_text(GTK_ENTRY (entry), gp->gr_name);
+    else
+      gtk_entry_set_text(GTK_ENTRY (entry), (gpointer) statbuf.st_gid);
+    if (access (filename, W_OK) || (getuid() != 0))
+      gtk_widget_set_sensitive( GTK_WIDGET (entry), FALSE);
+
+    
+    hseparator = gtk_hseparator_new ();
+    gtk_widget_show (hseparator);
+    gtk_box_pack_start (GTK_BOX (vbox), hseparator, FALSE, TRUE, 0);
+    
+    /* permissions */
+    table = gtk_table_new (4, 5, TRUE);
+    gtk_widget_show (table);
+    gtk_box_pack_start (GTK_BOX (vbox), table, FALSE, FALSE, 0);
+    gtk_table_set_row_spacings (GTK_TABLE (table), 2);
+    gtk_table_set_col_spacings (GTK_TABLE (table), 4);
+    if (access (filename, W_OK) || ((getuid() != statbuf.st_uid) && getuid() != 0))
+      gtk_widget_set_sensitive (GTK_WIDGET (table), FALSE);
+    
+    hbox = gtk_hbox_new (FALSE, 1);
+    gtk_widget_show (hbox);
+    gtk_table_attach (GTK_TABLE (table), hbox, 0, 1, 0, 1,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (GTK_FILL), 0, 0);
+    
+    priv->mode_label = label = gtk_label_new ("(0000)");
+    gtk_widget_show (label);
+    gtk_box_pack_start (GTK_BOX (hbox), label, FALSE, FALSE, 0);
+
+    label = gtk_label_new (_("Read"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 1, 2, 0, 1,
+		      (GtkAttachOptions) (0),
+		      (GtkAttachOptions) (0), 0, 0);
+    
+    label = gtk_label_new (_("Write"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 2, 3, 0, 1,
+		      (GtkAttachOptions) (0),
+		      (GtkAttachOptions) (0), 0, 0);
+    
+    label = gtk_label_new (_("Exec"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 3, 4, 0, 1,
+		      (GtkAttachOptions) (0),
+		      (GtkAttachOptions) (0), 0, 0);
+    
+    label = gtk_label_new (_("Special"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 4, 5, 0, 1,
+		      (GtkAttachOptions) (0),
+		      (GtkAttachOptions) (0), 0, 0);
+    
+    
+    label = gtk_label_new (_("User:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    priv->mode_buttons[0] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 1, 2, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IRUSR)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+
+    priv->mode_buttons[1] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 2, 3, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IWUSR)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    priv->mode_buttons[2] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 3, 4, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IXUSR)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    priv->mode_buttons[3] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 4, 5, 1, 2,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_ISUID)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+
+
+    
+    label = gtk_label_new (_("Group:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 2, 3,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    priv->mode_buttons[4] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 1, 2, 2, 3,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IRGRP)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    priv->mode_buttons[5] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 2, 3, 2, 3,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IWGRP)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    priv->mode_buttons[6] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 3, 4, 2, 3,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IXGRP)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    priv->mode_buttons[7] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 4, 5, 2, 3,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_ISGID)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    label = gtk_label_new (_("Other:"));
+    gtk_widget_show (label);
+    gtk_table_attach (GTK_TABLE (table), label, 0, 1, 3, 4,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    gtk_misc_set_alignment (GTK_MISC (label), 0, 0.5);
+    
+    priv->mode_buttons[8] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 1, 2, 3, 4,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IROTH)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+
+    priv->mode_buttons[9] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 2, 3, 3, 4,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IWOTH)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    priv->mode_buttons[10] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 3, 4, 3, 4,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_IXOTH)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+    
+    priv->mode_buttons[11] = togglebutton = gtk_toggle_button_new_with_label ("");
+    gtk_widget_show (togglebutton);
+    gtk_table_attach (GTK_TABLE (table), togglebutton, 4, 5, 3, 4,
+		      (GtkAttachOptions) (GTK_FILL),
+		      (GtkAttachOptions) (0), 0, 0);
+    if ((statbuf.st_mode & ~(S_IFMT)) & S_ISVTX)
+      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (togglebutton), TRUE);
+
+    for (i = 0; i < 12; i++)
+      gtk_signal_connect (GTK_OBJECT (priv->mode_buttons[i]), "toggled",
+                          GTK_SIGNAL_FUNC (gtk_file_selection_properties_update_mode), fs);
+    gtk_toggle_button_toggled (GTK_TOGGLE_BUTTON (priv->mode_buttons[0]));
+  }
+  /* global page */
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (vbox);
+  gtk_container_add (GTK_CONTAINER (notebook), vbox);
+
+  label = gtk_label_new (_("Global"));
+  gtk_widget_show (label);
+  gtk_notebook_set_tab_label (GTK_NOTEBOOK (notebook), gtk_notebook_get_nth_page (GTK_NOTEBOOK (notebook), pagenum), label);
+  pagenum++;
+
+  label = gtk_label_new (_("dialog preferances will go here"));
+  gtk_widget_show (label);
+  gtk_box_pack_start (GTK_BOX (vbox), label, FALSE, FALSE, 0);
+
+  /* end of dialog guts */
+
+  /* buttons */
+  button = gtk_button_new_with_label (_("OK"));
+  //  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+  //		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
+  //		      (gpointer) fs);
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_file_mode_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  g_free (filename);
+  gtk_widget_show (dialog);
+}
+
+static gint
+gtk_file_selection_key_press (GtkWidget   *widget,
+			      GdkEventKey *event,
+			      gpointer     user_data)
+{
+	
+  GtkFileSelection *fs;
+  char *text;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  fs = GTK_FILE_SELECTION (user_data);
+
+  if (fs->saved_entry)
+    {
+      gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
+      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
+      g_free (fs->saved_entry);
+      fs->saved_entry = NULL;
+    }
+  if (event->keyval == GDK_Tab)
+    {
+      text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+
+      text = g_strdup (text);
+
+      gtk_file_selection_populate (fs, text, TRUE);
+
+      g_free (text);
+
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+
+      return TRUE;
+    }
+
+
+  return FALSE;
+}
+
+/*
+static void
+gtk_file_selection_home_button (GtkWidget *widget, gpointer data){
+  GList *list;
+	
+  GtkFileSelection *fs=data;
+
+  list = fs->next_history;
+  if (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+		
+  gtk_file_selection_populate (fs,"~/",FALSE);
+}
+*/
+static void
+gtk_file_selection_bookmark_button (GtkWidget *widget, 
+                                    GtkFileSelection *fs)
+{
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_FILE_SELECTION (fs));
+	 
+  gtk_menu_popup (GTK_MENU (fs->bookmark_menu), NULL, NULL, NULL, NULL, 
+		  0, 0);
+  
+}
+
+static void
+gtk_file_selection_up_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->next_history;
+  if (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+
+  gtk_file_selection_populate (fs, "../", FALSE); /*change directories. */
+		
+}
+
+static void
+gtk_file_selection_prev_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+  GList *first;
+  gchar *path;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->prev_history;
+
+  if (list && g_list_length(list) > 1)
+    {
+      first = list;            /* get first element */
+      list = list->next;       /* pop off current directory */
+
+      list->prev = NULL;       /* make this the new head. */
+  	
+      fs->prev_history = list; /* update prev_history list */
+      fs->next_history = g_list_prepend(fs->next_history,first->data); /* put it on next_history */
+  	
+      first->next = NULL;      /* orphan the old first node */
+      g_list_free (first);     /* free the node (data is now in use by next_history) */
+
+
+  	
+      path = g_malloc(strlen(list->data)+4); /* plenty of space */
+      strcpy(path,list->data);               /* get the 2nd path in the history */
+      strcat(path,"/");                      /* append a '/' */
+      gtk_file_selection_populate (fs, path, FALSE); /* change directories. */
+      g_free (path);
+    }
+}	
+
+static void
+gtk_file_selection_next_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+  GList *first;
+  gchar *path;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->next_history;
+
+  if (list && g_list_length(list) > 0)
+    {
+      first = list;            /*get first element*/
+      list = list->next;       /*pop off current directory*/
+      
+      if (list)
+	list->prev = NULL;
+      
+      fs->next_history = list;                       /*update prev_history list*/
+  	
+      path = g_malloc(strlen(first->data)+4);        /*plenty of space*/
+      strcpy(path,first->data);
+      strcat(path,"/");                              /*append a /   */
+      gtk_file_selection_populate (fs, path, FALSE); /*change directories.*/
+      g_free(path);
+  	
+      first->next = NULL;     /* orphan the old first node */
+      g_list_free (first);    /* free the node (data is now in use by next_history) */
+      
+    }
+}	
+
+void static
+gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_file_selection_populate (fs,"",FALSE);
+}
+
+static void
+gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+
+  if(fs->mask)
+    g_free (fs->mask);
+		
+  fs->mask = g_strdup(gtk_entry_get_text (GTK_ENTRY(GTK_COMBO(fs->mask_entry)->entry)));
+	
+  if (strlen(fs->mask) == 0)
+    {
+      g_free (fs->mask);
+      fs->mask = NULL;
+    }
+	
+  gtk_file_selection_refresh_button (widget,data);
+}
+
+static gint gtk_file_selection_files_list_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data){
+  GtkFileSelection *fs=data;
+  gchar *saved;
+  gchar key[2];
+
+//  g_print("Key event: %d\n",event->keyval);
+  //we need some sort of timeout.
+
+  //if the key is a normal character then
+  //add to our saved_entry1
+  //if it's backspace then remove one character
+  //otherwise let it through (and erase our buffer.
+
+  if(event->keyval > GDK_space && event->keyval <=  GDK_Korean_Won) {
+    key[1]=0;
+    key[0]=event->keyval;
+    saved=fs->saved_entry1;
+    if(fs->saved_entry1){
+      fs->saved_entry1=g_strconcat(saved,key,NULL);
+      g_free(saved);
+    }else{
+      fs->saved_entry1=g_strdup(key);
+    }
+    g_print("complete: %s\n",fs->saved_entry1);
+    /*gtk_label_set_text(GTK_LABEL(fs->completion_label), fs->saved_entry1); */
+
+    saved=g_strdup(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
+    gtk_file_selection_complete(fs,fs->saved_entry1);
+    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),saved);
+    g_free(saved);
+  }else if (event->keyval ==  GDK_BackSpace) {
+    if(strlen(fs->saved_entry1)){
+      fs->saved_entry1[strlen(fs->saved_entry1)-1]=0;
+      g_print("complete: %s\n",fs->saved_entry1);
+      /*gtk_label_set_text(GTK_LABEL(fs->completion_label),fs->saved_entry1); */
+      saved=g_strdup(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
+      gtk_file_selection_complete(fs,fs->saved_entry1);
+      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),saved);
+      g_free(saved);
+    }
+  }else if (event->keyval == GDK_Tab) {
+    saved=g_strdup(gtk_entry_get_text(GTK_ENTRY(fs->selection_entry)));
+    gtk_file_selection_populate(fs,fs->saved_entry1,TRUE);
+    g_free(fs->saved_entry1);
+    fs->saved_entry1=gtk_entry_get_text(GTK_ENTRY(fs->selection_entry));
+    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),saved);
+    g_free(saved);
+
+    g_print("complete: %s\n",fs->saved_entry1);
+    /* gtk_label_set_text(GTK_LABEL(fs->completion_label),fs->saved_entry1);*/
+
+    gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+  }else {
+    if(fs->saved_entry1){
+      g_free(fs->saved_entry1);
+      fs->saved_entry1=NULL;
+    }
+    /* gtk_label_set_text(GTK_LABEL(fs->completion_label)," "); */
+  }
+
+  return TRUE;
+}
+
+
+static gint gtk_file_selection_mask_entry_key_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+  GtkEntry *entry=(GtkEntry *)widget;
+  GtkFileSelection *fs=data;
+	
+  g_return_val_if_fail (fs != NULL,FALSE);
+  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
+	
+
+  if (event->keyval == GDK_Return || event->keyval == GDK_Tab)
+    {
+      if(fs->mask)
+        g_free(fs->mask);
+
+      fs->mask=g_strdup(gtk_entry_get_text(entry));
+      gtk_file_selection_refresh_button(widget,fs);
+
+      if (event->keyval == GDK_Return)
+        gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
+}
+
+static gint gtk_file_selection_mask_entry_button_callback (GtkWidget *widget, GdkEventButton *event, gpointer data)
+{
+  GtkFileSelection *fs = data;
+		
+  if(fs->mask)
+    g_free(fs->mask);
+
+  fs->mask=g_strdup(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(fs->mask_entry)->entry)));
+  gtk_file_selection_refresh_button(widget,fs);
+
+  return TRUE;
+
+}
+
+static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
+								  GdkEventKey *event,
+								  gpointer user_data)
+{
+  /*
+  g_print("Key pressed! \n");
+  */
+	
+  return TRUE;
+}
+
+static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
+								GdkEventButton *event,
+								gpointer user_data)
+{
+
+  GtkFileSelection *fs = user_data;
+  GList *list;
+  gchar *path;
+		
+  list = fs->next_history;
+  if(list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+			
+  path = g_malloc(strlen(gtk_entry_get_text(GTK_ENTRY (((GtkCombo *)fs->history_combo)->entry)))+4);
+  strcpy (path,gtk_entry_get_text(GTK_ENTRY( ((GtkCombo *)fs->history_combo)->entry)));
+  strcat (path,"/");
+	
+  gtk_file_selection_populate (fs,path,TRUE);
+	
+  g_free (path);
+
+  return TRUE;
+}
+
+static gboolean
+gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+  GtkEntry *entry=(GtkEntry *)widget;
+  GtkFileSelection *fs=data;
+  GList *list;
+  gchar *path;
+	
+  g_return_val_if_fail (fs != NULL,FALSE);
+  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
+	
+
+  if (event->keyval == GDK_Return)
+    {
+      list = fs->next_history;
+      if (list)
+	{
+	  g_free (list->data);
+	  list = list->next;
+	}
+      g_list_free (fs->next_history);
+      fs->next_history = NULL;
+      
+      path = g_malloc(strlen(gtk_entry_get_text(entry))+4);
+      strcpy (path,gtk_entry_get_text(entry));
+      strcat (path,"/");
+      gtk_file_selection_populate (fs,path,TRUE);
+      g_free (path);
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
+
+}
+
+
+static void gtk_file_selection_bookmark_callback (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  BookmarkMenuStruct *item;
+  GList *list;
+	
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+//g_print ("Callback\n");
+  list = fs->bookmark_list;
+  while(list) {
+    item = list->data;
+    if (item->menu_item == widget) {
+      if(strcmp(item->path,"./")) {
+        gtk_file_selection_populate (fs, item->path, FALSE);
+      }
+      break;
+    }
+    list=list->next;
+  } 
+}
+
+static void
+gtk_file_selection_update_history_menu (GtkFileSelection *fs,
+					gchar *current_directory)
+{
+  gchar *current_dir;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  g_return_if_fail (current_directory != NULL);
+  
+  current_dir = g_strdup (current_directory);
+
+  if(fs->prev_history)
+    {
+      if (strcmp((fs->prev_history)->data,current_dir))
+	{ /*if this item isn't on the top of the list */
+	  fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
+	}
+    } else {
+      fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
+    }
+  
+  gtk_combo_set_popdown_strings (GTK_COMBO (fs->history_combo),fs->prev_history);
+  
+  g_free (current_dir);
+}
+
+static void
+gtk_file_selection_file_button (GtkWidget *widget,
+			       gint row, 
+			       gint column, 
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+  
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = user_data;
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  gtk_clist_get_text (GTK_CLIST (fs->file_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (fs->saved_entry)
+      {
+        gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
+        gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
+        g_free (fs->saved_entry);
+        fs->saved_entry = NULL;
+      }
+      if(fs->saved_entry1){
+        g_free(fs->saved_entry1);
+        fs->saved_entry1=NULL;
+      }
+      /* gtk_label_set_text(GTK_LABEL(fs->completion_label)," "); */
+
+
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  case GDK_2BUTTON_PRESS:
+	    gtk_button_clicked (GTK_BUTTON (fs->ok_button));
+	    break;
+	    
+	  default:
+/*	
+	    if (bevent->button && GDK_BUTTON2_MASK)
+	      {
+	        g_print("Right click! -- %d\n",bevent->button);
+	      }
+	      else
+	      {
+	      */
+	
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+	      /*}*/
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_dir_button (GtkWidget *widget,
+			       gint row, 
+			       gint column, 
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GList *list;
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = GTK_FILE_SELECTION (user_data);
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  case GDK_2BUTTON_PRESS:
+	    list = fs->next_history;
+	    if (list)
+	      {
+		g_free (list->data);
+		list = list->next;
+	      }
+	    g_list_free (fs->next_history);
+	    fs->next_history = NULL;
+	
+	    gtk_file_selection_populate (fs, filename, FALSE);
+	    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
+	    g_free (fs->saved_entry);
+	    fs->saved_entry = NULL;
+	    break;
+	    
+	  default:
+	    /* here we need to add the "filename" to the beginning of what's already
+	       in the entry.  Save what's in the entry, then restore it on the double click
+	    */
+	    if (fs->saved_entry) g_free (fs->saved_entry);
+	    fs->saved_entry=g_strdup(gtk_entry_get_text(GTK_ENTRY (fs->selection_entry)));
+	
+	    temp=g_strconcat(filename,fs->saved_entry,NULL);
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), temp);
+	    g_free (temp);
+	
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+      
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_undir_button (GtkWidget *widget,
+			       gint row,
+			       gint column,
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = GTK_FILE_SELECTION (user_data);
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  default:
+	    /* here we need to add the "filename" to the beginning of what's already
+	       in the entry.  Save what's in the entry, then restore it on the double click
+	    */
+	    if (fs->saved_entry)
+	      {
+	        gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),fs->saved_entry);
+		g_free (fs->saved_entry);
+		fs->saved_entry = NULL;
+	      }
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename); //?????
+
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_populate (GtkFileSelection *fs,
+			     gchar            *rel_path,
+			     gint              try_complete)
+{
+  CompletionState *cmpl_state;
+  PossibleCompletion* poss;
+  gchar* filename;
+  gint row;
+  gchar* rem_path = rel_path;
+  gchar* sel_text;
+  gchar* text[2];
+  gint did_recurse = FALSE;
+  gint possible_count = 0;
+  gint selection_index = -1;
+  gint file_list_width;
+  gint dir_list_width;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
+
+  if (!cmpl_state_okay (cmpl_state))
+    {
+      /* Something went wrong. */
+      gtk_file_selection_abort (fs);
+      return;
+    }
+
+  g_assert (cmpl_state->reference_dir);
+
+  gtk_clist_freeze (GTK_CLIST (fs->dir_list));
+  gtk_clist_clear (GTK_CLIST (fs->dir_list));
+  gtk_clist_freeze (GTK_CLIST (fs->file_list));
+  gtk_clist_clear (GTK_CLIST (fs->file_list));
+
+  /* Set the dir_list to include ./ and ../ */
+  /* Actually, no let's not.
+  text[1] = NULL;
+  text[0] = "./";
+  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+  */
+
+  text[0] = "../";  //Do we need ..?
+  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+
+  /*reset the max widths of the lists*/
+  dir_list_width = gdk_string_width(fs->dir_list->style->font,"../");
+  gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,dir_list_width);
+  file_list_width = 1;
+  gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,file_list_width);
+
+  while (poss)
+    {
+      if (cmpl_is_a_completion (poss))
+  	{
+	  possible_count += 1;
+	  
+	  filename = cmpl_this_completion (poss);
+
+	  text[0] = filename;
+	  
+	  if (cmpl_is_directory (poss))
+	    {
+	      if (strcmp (filename, "./") != 0 &&
+		  strcmp (filename, "../") != 0)
+		{
+		  int width = gdk_string_width(fs->dir_list->style->font,
+					       filename);
+		  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+		  if(width > dir_list_width)
+		    {
+		      dir_list_width = width;
+		      gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,
+						 width);
+		    }
+		}
+	    }
+	  else
+	    {
+	      if(fs->mask)
+		{
+		  if (gtk_file_selection_match_mask(filename,fs->mask))
+		    {
+		      int width = gdk_string_width(fs->file_list->style->font,
+						   filename);
+		      row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
+		      if(width > file_list_width)
+		        {
+		          file_list_width = width;
+		          gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
+						     width);
+		        }
+		    }
+		}
+	      else
+		{
+		  int width = gdk_string_width(fs->file_list->style->font,
+					       filename);
+		  row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
+		  if(width > file_list_width)
+		    {
+		      file_list_width = width;
+		      gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
+						 width);
+		    }
+		}
+	    }
+	}
+
+      poss = cmpl_next_completion (cmpl_state);
+    }
+
+  gtk_clist_thaw (GTK_CLIST (fs->dir_list));
+  gtk_clist_thaw (GTK_CLIST (fs->file_list));
+
+  /* File lists are set. */
+
+  g_assert (cmpl_state->reference_dir);
+
+  if (try_complete)
+    {
+
+      /* User is trying to complete filenames, so advance the user's input
+       * string to the updated_text, which is the common leading substring
+       * of all possible completions, and if its a directory attempt
+       * attempt completions in it. */
+
+      if (cmpl_updated_text (cmpl_state)[0])
+        {
+
+          if (cmpl_updated_dir (cmpl_state))
+            {
+	      gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
+
+              did_recurse = TRUE;
+
+              gtk_file_selection_populate (fs, dir_name, TRUE);
+
+              g_free (dir_name);
+            }
+          else
+            {
+	      if (fs->selection_entry)
+		      gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
+					  cmpl_updated_text (cmpl_state));
+            }
+        }
+      else
+        {
+          selection_index = cmpl_last_valid_char (cmpl_state) -
+                            (strlen (rel_path) - strlen (rem_path));
+	  if (fs->selection_entry)
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
+        }
+    }
+  else
+    {
+      if (fs->selection_entry)
+      /* Here we need to take the old filename and keep it!*/
+	/*gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");*/
+	;
+    }
+
+  if (!did_recurse)
+    {
+      if (fs->selection_entry)
+	gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
+
+      if (fs->selection_entry)
+	{
+	  sel_text = g_strconcat (_("Selection: "),
+				  cmpl_reference_position (cmpl_state),
+				  NULL);
+
+/*
+		gtk_label_set_text (GTK_LABEL (fs->selection_text), sel_text);
+*/
+		g_free (sel_text);
+	}
+
+  gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state));
+
+    }
+}
+
+static void
+gtk_file_selection_abort (GtkFileSelection *fs)
+{
+  gchar err_buf[256];
+
+  sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
+
+  /*  BEEP gdk_beep();  */
+
+/*
+  if (fs->selection_entry)
+    gtk_label_set_text (GTK_LABEL (fs->selection_text), err_buf);
+*/
+}
+
+/**********************************************************************/
+/*			  External Interface                          */
+/**********************************************************************/
+
+/* The four completion state selectors
+ */
+static gchar*
+cmpl_updated_text (CompletionState* cmpl_state)
+{
+  return cmpl_state->updated_text;
+}
+
+static gint
+cmpl_updated_dir (CompletionState* cmpl_state)
+{
+  return cmpl_state->re_complete;
+}
+
+static gchar*
+cmpl_reference_position (CompletionState* cmpl_state)
+{
+  return cmpl_state->reference_dir->fullname;
+}
+
+static gint
+cmpl_last_valid_char (CompletionState* cmpl_state)
+{
+  return cmpl_state->last_valid_char;
+}
+
+static gchar*
+cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state)
+{
+  static char nothing[2] = "";
+
+  if (!cmpl_state_okay (cmpl_state))
+    {
+      return nothing;
+    }
+  else if (text[0] == '/')
+    {
+      strcpy (cmpl_state->updated_text, text);
+    }
+  else if (text[0] == '~')
+    {
+      CompletionDir* dir;
+      char* slash;
+
+      dir = open_user_dir (text, cmpl_state);
+
+      if (!dir)
+	{
+	  /* spencer says just return ~something, so
+	   * for now just do it. */
+	  strcpy (cmpl_state->updated_text, text);
+	}
+      else
+	{
+
+	  strcpy (cmpl_state->updated_text, dir->fullname);
+
+	  slash = strchr (text, '/');
+
+	  if (slash)
+	    strcat (cmpl_state->updated_text, slash);
+	}
+    }
+  else
+    {
+      strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
+      if (strcmp (cmpl_state->reference_dir->fullname, "/") != 0)
+	strcat (cmpl_state->updated_text, "/");
+      strcat (cmpl_state->updated_text, text);
+    }
+
+  return cmpl_state->updated_text;
+}
+
+/* The three completion selectors
+ */
+static gchar*
+cmpl_this_completion (PossibleCompletion* pc)
+{
+  return pc->text;
+}
+
+static gint
+cmpl_is_directory (PossibleCompletion* pc)
+{
+  return pc->is_directory;
+}
+
+static gint
+cmpl_is_a_completion (PossibleCompletion* pc)
+{
+  return pc->is_a_completion;
+}
+
+/**********************************************************************/
+/*	                 Construction, deletion                       */
+/**********************************************************************/
+
+static CompletionState*
+cmpl_init_state (void)
+{
+  gchar getcwd_buf[2*MAXPATHLEN];
+  CompletionState *new_state;
+
+  new_state = g_new (CompletionState, 1);
+
+  /* We don't use getcwd() on SUNOS, because, it does a popen("pwd")
+   * and, if that wasn't bad enough, hangs in doing so.
+   */
+#if defined(sun) && !defined(__SVR4)
+  if (!getwd (getcwd_buf))
+#else    
+  if (!getcwd (getcwd_buf, MAXPATHLEN))
+#endif    
+    {
+      /* Oh joy, we can't get the current directory. Um..., we should have
+       * a root directory, right? Right? (Probably not portable to non-Unix)
+       */
+      strcpy (getcwd_buf, "/");
+    }
+
+tryagain:
+
+  new_state->reference_dir = NULL;
+  new_state->completion_dir = NULL;
+  new_state->active_completion_dir = NULL;
+  new_state->directory_storage = NULL;
+  new_state->directory_sent_storage = NULL;
+  new_state->last_valid_char = 0;
+  new_state->updated_text = g_new (gchar, MAXPATHLEN);
+  new_state->updated_text_alloc = MAXPATHLEN;
+  new_state->the_completion.text = g_new (gchar, MAXPATHLEN);
+  new_state->the_completion.text_alloc = MAXPATHLEN;
+  new_state->user_dir_name_buffer = NULL;
+  new_state->user_directories = NULL;
+
+  new_state->reference_dir =  open_dir (getcwd_buf, new_state);
+
+  if (!new_state->reference_dir)
+    {
+      /* Directories changing from underneath us, grumble */
+      strcpy (getcwd_buf, "/");
+      goto tryagain;
+    }
+
+  return new_state;
+}
+
+static void
+cmpl_free_dir_list(GList* dp0)
+{
+  GList *dp = dp0;
+
+  while (dp) {
+    free_dir (dp->data);
+    dp = dp->next;
+  }
+
+  g_list_free(dp0);
+}
+
+static void
+cmpl_free_dir_sent_list(GList* dp0)
+{
+  GList *dp = dp0;
+
+  while (dp) {
+    free_dir_sent (dp->data);
+    dp = dp->next;
+  }
+
+  g_list_free(dp0);
+}
+
+static void
+cmpl_free_state (CompletionState* cmpl_state)
+{
+  cmpl_free_dir_list (cmpl_state->directory_storage);
+  cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage);
+
+  if (cmpl_state->user_dir_name_buffer)
+    g_free (cmpl_state->user_dir_name_buffer);
+  if (cmpl_state->user_directories)
+    g_free (cmpl_state->user_directories);
+  if (cmpl_state->the_completion.text)
+    g_free (cmpl_state->the_completion.text);
+  if (cmpl_state->updated_text)
+    g_free (cmpl_state->updated_text);
+
+  g_free (cmpl_state);
+}
+
+static void
+free_dir(CompletionDir* dir)
+{
+  g_free(dir->fullname);
+  g_free(dir);
+}
+
+static void
+free_dir_sent(CompletionDirSent* sent)
+{
+  g_free(sent->name_buffer);
+  g_free(sent->entries);
+  g_free(sent);
+}
+
+static void
+prune_memory_usage(CompletionState *cmpl_state)
+{
+  GList* cdsl = cmpl_state->directory_sent_storage;
+  GList* cdl = cmpl_state->directory_storage;
+  GList* cdl0 = cdl;
+  gint len = 0;
+
+  for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1)
+    cdsl = cdsl->next;
+
+  if (cdsl) {
+    cmpl_free_dir_sent_list(cdsl->next);
+    cdsl->next = NULL;
+  }
+
+  cmpl_state->directory_storage = NULL;
+  while (cdl) {
+    if (cdl->data == cmpl_state->reference_dir)
+      cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data);
+    else
+      free_dir (cdl->data);
+    cdl = cdl->next;
+  }
+
+  g_list_free(cdl0);
+}
+
+/**********************************************************************/
+/*                        The main entrances.                         */
+/**********************************************************************/
+
+static PossibleCompletion*
+cmpl_completion_matches (gchar* text_to_complete,
+			 gchar** remaining_text,
+			 CompletionState* cmpl_state)
+{
+  gchar* first_slash;
+  PossibleCompletion *poss;
+
+  prune_memory_usage(cmpl_state);
+
+  g_assert (text_to_complete != NULL);
+
+  cmpl_state->user_completion_index = -1;
+  cmpl_state->last_completion_text = text_to_complete;
+  cmpl_state->the_completion.text[0] = 0;
+  cmpl_state->last_valid_char = 0;
+  cmpl_state->updated_text_len = -1;
+  cmpl_state->updated_text[0] = 0;
+  cmpl_state->re_complete = FALSE;
+
+  first_slash = strchr (text_to_complete, '/');
+
+  if (text_to_complete[0] == '~' && !first_slash)
+    {
+      /* Text starts with ~ and there is no slash, show all the
+       * home directory completions.
+       */
+      poss = attempt_homedir_completion (text_to_complete, cmpl_state);
+
+      update_cmpl(poss, cmpl_state);
+
+      return poss;
+    }
+
+  cmpl_state->reference_dir =
+    open_ref_dir (text_to_complete, remaining_text, cmpl_state);
+
+  if(!cmpl_state->reference_dir)
+    return NULL;
+
+  cmpl_state->completion_dir =
+    find_completion_dir (*remaining_text, remaining_text, cmpl_state);
+
+  cmpl_state->last_valid_char = *remaining_text - text_to_complete;
+
+  if(!cmpl_state->completion_dir)
+    return NULL;
+
+  cmpl_state->completion_dir->cmpl_index = -1;
+  cmpl_state->completion_dir->cmpl_parent = NULL;
+  cmpl_state->completion_dir->cmpl_text = *remaining_text;
+
+  cmpl_state->active_completion_dir = cmpl_state->completion_dir;
+
+  cmpl_state->reference_dir = cmpl_state->completion_dir;
+
+  poss = attempt_file_completion(cmpl_state);
+
+  update_cmpl(poss, cmpl_state);
+
+  return poss;
+}
+
+static PossibleCompletion*
+cmpl_next_completion (CompletionState* cmpl_state)
+{
+  PossibleCompletion* poss = NULL;
+
+  cmpl_state->the_completion.text[0] = 0;
+
+  if(cmpl_state->user_completion_index >= 0)
+    poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state);
+  else
+    poss = attempt_file_completion(cmpl_state);
+
+  update_cmpl(poss, cmpl_state);
+
+  return poss;
+}
+
+/**********************************************************************/
+/*			 Directory Operations                         */
+/**********************************************************************/
+
+/* Open the directory where completion will begin from, if possible. */
+static CompletionDir*
+open_ref_dir(gchar* text_to_complete,
+	     gchar** remaining_text,
+	     CompletionState* cmpl_state)
+{
+  gchar* first_slash;
+  CompletionDir *new_dir;
+
+  first_slash = strchr(text_to_complete, '/');
+
+  if (text_to_complete[0] == '~')
+    {
+      new_dir = open_user_dir(text_to_complete, cmpl_state);
+
+      if(new_dir)
+	{
+	  if(first_slash)
+	    *remaining_text = first_slash + 1;
+	  else
+	    *remaining_text = text_to_complete + strlen(text_to_complete);
+	}
+      else
+	{
+	  return NULL;
+	}
+    }
+  else if (text_to_complete[0] == '/' || !cmpl_state->reference_dir)
+    {
+      gchar *tmp = g_strdup(text_to_complete);
+      gchar *p;
+
+      p = tmp;
+      while (*p && *p != '*' && *p != '?')
+	p++;
+
+      *p = '\0';
+      p = strrchr(tmp, '/');
+      if (p)
+	{
+	  if (p == tmp)
+	    p++;
+      
+	  *p = '\0';
+
+	  new_dir = open_dir(tmp, cmpl_state);
+
+	  if(new_dir)
+	    *remaining_text = text_to_complete + 
+	      ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
+	}
+      else
+	{
+	  /* If no possible candidates, use the cwd */
+	  gchar *curdir = g_get_current_dir ();
+	  
+	  new_dir = open_dir(curdir, cmpl_state);
+
+	  if (new_dir)
+	    *remaining_text = text_to_complete;
+
+	  g_free (curdir);
+	}
+
+      g_free (tmp);
+    }
+  else
+    {
+      *remaining_text = text_to_complete;
+
+      new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state);
+    }
+
+  if(new_dir)
+    {
+      new_dir->cmpl_index = -1;
+      new_dir->cmpl_parent = NULL;
+    }
+
+  return new_dir;
+}
+
+/* open a directory by user name */
+static CompletionDir*
+open_user_dir(gchar* text_to_complete,
+	      CompletionState *cmpl_state)
+{
+  gchar *first_slash;
+  gint cmp_len;
+
+  g_assert(text_to_complete && text_to_complete[0] == '~');
+
+  first_slash = strchr(text_to_complete, '/');
+
+  if (first_slash)
+    cmp_len = first_slash - text_to_complete - 1;
+  else
+    cmp_len = strlen(text_to_complete + 1);
+
+  if(!cmp_len)
+    {
+      /* ~/ */
+      gchar *homedir = g_get_home_dir ();
+
+      if (homedir)
+	return open_dir(homedir, cmpl_state);
+      else
+	return NULL;
+    }
+  else
+    {
+      /* ~user/ */
+      char* copy = g_new(char, cmp_len + 1);
+      struct passwd *pwd;
+      strncpy(copy, text_to_complete + 1, cmp_len);
+      copy[cmp_len] = 0;
+      pwd = getpwnam(copy);
+      g_free(copy);
+      if (!pwd)
+	{
+	  cmpl_errno = errno;
+	  return NULL;
+	}
+
+      return open_dir(pwd->pw_dir, cmpl_state);
+    }
+}
+
+/* open a directory relative the the current relative directory */
+static CompletionDir*
+open_relative_dir(gchar* dir_name,
+		  CompletionDir* dir,
+		  CompletionState *cmpl_state)
+{
+  gchar path_buf[2*MAXPATHLEN];
+
+  if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN)
+    {
+      cmpl_errno = CMPL_ERRNO_TOO_LONG;
+      return NULL;
+    }
+
+  strcpy(path_buf, dir->fullname);
+
+  if(dir->fullname_len > 1)
+    {
+      path_buf[dir->fullname_len] = '/';
+      strcpy(path_buf + dir->fullname_len + 1, dir_name);
+    }
+  else
+    {
+      strcpy(path_buf + dir->fullname_len, dir_name);
+    }
+
+  return open_dir(path_buf, cmpl_state);
+}
+
+/* after the cache lookup fails, really open a new directory */
+static CompletionDirSent*
+open_new_dir(gchar* dir_name, struct stat* sbuf, gboolean stat_subdirs)
+{
+  CompletionDirSent* sent;
+  DIR* directory;
+  gchar *buffer_ptr;
+  struct dirent *dirent_ptr;
+  gint buffer_size = 0;
+  gint entry_count = 0;
+  gint i;
+  struct stat ent_sbuf;
+  char path_buf[MAXPATHLEN*2];
+  gint path_buf_len;
+
+  sent = g_new(CompletionDirSent, 1);
+  sent->mtime = sbuf->st_mtime;
+  sent->inode = sbuf->st_ino;
+  sent->device = sbuf->st_dev;
+
+  path_buf_len = strlen(dir_name);
+
+  if (path_buf_len > MAXPATHLEN)
+    {
+      cmpl_errno = CMPL_ERRNO_TOO_LONG;
+      return NULL;
+    }
+
+  strcpy(path_buf, dir_name);
+
+  directory = opendir(dir_name);
+
+  if(!directory)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  while((dirent_ptr = readdir(directory)) != NULL)
+    {
+      int entry_len = strlen(dirent_ptr->d_name);
+      buffer_size += entry_len + 1;
+      entry_count += 1;
+
+      if(path_buf_len + entry_len + 2 >= MAXPATHLEN)
+	{
+	  cmpl_errno = CMPL_ERRNO_TOO_LONG;
+ 	  closedir(directory);
+	  return NULL;
+	}
+    }
+
+  sent->name_buffer = g_new(gchar, buffer_size);
+  sent->entries = g_new(CompletionDirEntry, entry_count);
+  sent->entry_count = entry_count;
+
+  buffer_ptr = sent->name_buffer;
+
+  rewinddir(directory);
+
+  for(i = 0; i < entry_count; i += 1)
+    {
+      dirent_ptr = readdir(directory);
+
+      if(!dirent_ptr)
+	{
+	  cmpl_errno = errno;
+	  closedir(directory);
+	  return NULL;
+	}
+
+      strcpy(buffer_ptr, dirent_ptr->d_name);
+      sent->entries[i].entry_name = buffer_ptr;
+      buffer_ptr += strlen(dirent_ptr->d_name);
+      *buffer_ptr = 0;
+      buffer_ptr += 1;
+
+      path_buf[path_buf_len] = '/';
+      strcpy(path_buf + path_buf_len + 1, dirent_ptr->d_name);
+
+      if (stat_subdirs)
+	{
+	  if(stat(path_buf, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
+	    sent->entries[i].is_dir = 1;
+	  else
+	    /* stat may fail, and we don't mind, since it could be a
+	     * dangling symlink. */
+	    sent->entries[i].is_dir = 0;
+	}
+      else
+	sent->entries[i].is_dir = 1;
+    }
+
+  qsort(sent->entries, sent->entry_count, sizeof(CompletionDirEntry), compare_cmpl_dir);
+
+  closedir(directory);
+
+  return sent;
+}
+
+static gboolean
+check_dir(gchar *dir_name, struct stat *result, gboolean *stat_subdirs)
+{
+  /* A list of directories that we know only contain other directories.
+   * Trying to stat every file in these directories would be very
+   * expensive.
+   */
+
+  static struct {
+    gchar *name;
+    gboolean present;
+    struct stat statbuf;
+  } no_stat_dirs[] = {
+    { "/afs", FALSE, { 0 } },
+    { "/net", FALSE, { 0 } }
+  };
+
+  static const gint n_no_stat_dirs = sizeof(no_stat_dirs) / sizeof(no_stat_dirs[0]);
+  static gboolean initialized = FALSE;
+
+  gint i;
+
+  if (!initialized)
+    {
+      initialized = TRUE;
+      for (i = 0; i < n_no_stat_dirs; i++)
+	{
+	  if (stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
+	    no_stat_dirs[i].present = TRUE;
+	}
+    }
+
+  if(stat(dir_name, result) < 0)
+    {
+      cmpl_errno = errno;
+      return FALSE;
+    }
+
+  *stat_subdirs = TRUE;
+  for (i=0; i<n_no_stat_dirs; i++)
+    {
+      if (no_stat_dirs[i].present &&
+	  (no_stat_dirs[i].statbuf.st_dev == result->st_dev) &&
+	  (no_stat_dirs[i].statbuf.st_ino == result->st_ino))
+	{
+	  *stat_subdirs = FALSE;
+	  break;
+	}
+    }
+
+  return TRUE;
+}
+
+/* open a directory by absolute pathname */
+static CompletionDir*
+open_dir(gchar* dir_name, CompletionState* cmpl_state)
+{
+  struct stat sbuf;
+  gboolean stat_subdirs;
+  CompletionDirSent *sent;
+  GList* cdsl;
+
+  if (!check_dir (dir_name, &sbuf, &stat_subdirs))
+    return NULL;
+
+  cdsl = cmpl_state->directory_sent_storage;
+
+  while (cdsl)
+    {
+      sent = cdsl->data;
+
+      if(sent->inode == sbuf.st_ino &&
+	 sent->mtime == sbuf.st_mtime &&
+	 sent->device == sbuf.st_dev)
+	return attach_dir(sent, dir_name, cmpl_state);
+
+      cdsl = cdsl->next;
+    }
+
+  sent = open_new_dir(dir_name, &sbuf, stat_subdirs);
+
+  if (sent) {
+    cmpl_state->directory_sent_storage =
+      g_list_prepend(cmpl_state->directory_sent_storage, sent);
+
+    return attach_dir(sent, dir_name, cmpl_state);
+  }
+
+  return NULL;
+}
+
+static CompletionDir*
+attach_dir(CompletionDirSent* sent, gchar* dir_name, CompletionState *cmpl_state)
+{
+  CompletionDir* new_dir;
+
+  new_dir = g_new(CompletionDir, 1);
+
+  cmpl_state->directory_storage =
+    g_list_prepend(cmpl_state->directory_storage, new_dir);
+
+  new_dir->sent = sent;
+  new_dir->fullname = g_strdup(dir_name);
+  new_dir->fullname_len = strlen(dir_name);
+
+  return new_dir;
+}
+
+static gint
+correct_dir_fullname(CompletionDir* cmpl_dir)
+{
+  gint length = strlen(cmpl_dir->fullname);
+  struct stat sbuf;
+
+  if (strcmp(cmpl_dir->fullname + length - 2, "/.") == 0)
+    {
+      if (length == 2) 
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	} else {
+	  cmpl_dir->fullname[length - 2] = 0;
+	}
+    }
+  else if (strcmp(cmpl_dir->fullname + length - 3, "/./") == 0)
+    cmpl_dir->fullname[length - 2] = 0;
+  else if (strcmp(cmpl_dir->fullname + length - 3, "/..") == 0)
+    {
+      if(length == 3)
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	}
+
+      if(stat(cmpl_dir->fullname, &sbuf) < 0)
+	{
+	  cmpl_errno = errno;
+	  return FALSE;
+	}
+
+      cmpl_dir->fullname[length - 2] = 0;
+
+      if(!correct_parent(cmpl_dir, &sbuf))
+	return FALSE;
+    }
+  else if (strcmp(cmpl_dir->fullname + length - 4, "/../") == 0)
+    {
+      if(length == 4)
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	}
+
+      if(stat(cmpl_dir->fullname, &sbuf) < 0)
+	{
+	  cmpl_errno = errno;
+	  return FALSE;
+	}
+
+      cmpl_dir->fullname[length - 3] = 0;
+
+      if(!correct_parent(cmpl_dir, &sbuf))
+	return FALSE;
+    }
+
+  cmpl_dir->fullname_len = strlen(cmpl_dir->fullname);
+
+  return TRUE;
+}
+
+static gint
+correct_parent(CompletionDir* cmpl_dir, struct stat *sbuf)
+{
+  struct stat parbuf;
+  gchar *last_slash;
+  gchar *new_name;
+  gchar c = 0;
+
+  last_slash = strrchr(cmpl_dir->fullname, '/');
+
+  g_assert(last_slash);
+
+  if(last_slash != cmpl_dir->fullname)
+    { /* last_slash[0] = 0; */ }
+  else
+    {
+      c = last_slash[1];
+      last_slash[1] = 0;
+    }
+
+  if (stat(cmpl_dir->fullname, &parbuf) < 0)
+    {
+      cmpl_errno = errno;
+      return FALSE;
+    }
+
+  if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
+    /* it wasn't a link */
+    return TRUE;
+
+  if(c)
+    last_slash[1] = c;
+  /* else
+    last_slash[0] = '/'; */
+
+  /* it was a link, have to figure it out the hard way */
+
+  new_name = find_parent_dir_fullname(cmpl_dir->fullname);
+
+  if (!new_name)
+    return FALSE;
+
+  g_free(cmpl_dir->fullname);
+
+  cmpl_dir->fullname = new_name;
+
+  return TRUE;
+}
+
+static gchar*
+find_parent_dir_fullname(gchar* dirname)
+{
+  gchar buffer[MAXPATHLEN];
+  gchar buffer2[MAXPATHLEN];
+
+#if defined(sun) && !defined(__SVR4)
+  if(!getwd(buffer))
+#else
+  if(!getcwd(buffer, MAXPATHLEN))
+#endif    
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  if(chdir(dirname) != 0 || chdir("..") != 0)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+#if defined(sun) && !defined(__SVR4)
+  if(!getwd(buffer2))
+#else
+  if(!getcwd(buffer2, MAXPATHLEN))
+#endif
+    {
+      chdir(buffer);
+      cmpl_errno = errno;
+
+      return NULL;
+    }
+
+  if(chdir(buffer) != 0)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  return g_strdup(buffer2);
+}
+
+/**********************************************************************/
+/*                        Completion Operations                       */
+/**********************************************************************/
+
+static PossibleCompletion*
+attempt_homedir_completion(gchar* text_to_complete,
+			   CompletionState *cmpl_state)
+{
+  gint index, length;
+
+  if (!cmpl_state->user_dir_name_buffer &&
+      !get_pwdb(cmpl_state))
+    return NULL;
+  length = strlen(text_to_complete) - 1;
+
+  cmpl_state->user_completion_index += 1;
+
+  while(cmpl_state->user_completion_index < cmpl_state->user_directories_len)
+    {
+      index = first_diff_index(text_to_complete + 1,
+			       cmpl_state->user_directories
+			       [cmpl_state->user_completion_index].login);
+
+      switch(index)
+	{
+	case PATTERN_MATCH:
+	  break;
+	default:
+	  if(cmpl_state->last_valid_char < (index + 1))
+	    cmpl_state->last_valid_char = index + 1;
+	  cmpl_state->user_completion_index += 1;
+	  continue;
+	}
+
+      cmpl_state->the_completion.is_a_completion = 1;
+      cmpl_state->the_completion.is_directory = 1;
+
+      append_completion_text("~", cmpl_state);
+
+      append_completion_text(cmpl_state->
+			      user_directories[cmpl_state->user_completion_index].login,
+			     cmpl_state);
+
+      return append_completion_text("/", cmpl_state);
+    }
+
+  if(text_to_complete[1] ||
+     cmpl_state->user_completion_index > cmpl_state->user_directories_len)
+    {
+      cmpl_state->user_completion_index = -1;
+      return NULL;
+    }
+  else
+    {
+      cmpl_state->user_completion_index += 1;
+      cmpl_state->the_completion.is_a_completion = 1;
+      cmpl_state->the_completion.is_directory = 1;
+
+      return append_completion_text("~/", cmpl_state);
+    }
+}
+
+/* returns the index (>= 0) of the first differing character,
+ * PATTERN_MATCH if the completion matches */
+static gint
+first_diff_index(gchar* pat, gchar* text)
+{
+  gint diff = 0;
+
+  while(*pat && *text && *text == *pat)
+    {
+      pat += 1;
+      text += 1;
+      diff += 1;
+    }
+
+  if(*pat)
+    return diff;
+
+  return PATTERN_MATCH;
+}
+
+static PossibleCompletion*
+append_completion_text(gchar* text, CompletionState* cmpl_state)
+{
+  gint len, i = 1;
+
+  if(!cmpl_state->the_completion.text)
+    return NULL;
+
+  len = strlen(text) + strlen(cmpl_state->the_completion.text) + 1;
+
+  if(cmpl_state->the_completion.text_alloc > len)
+    {
+      strcat(cmpl_state->the_completion.text, text);
+      return &cmpl_state->the_completion;
+    }
+
+  while(i < len) { i <<= 1; }
+
+  cmpl_state->the_completion.text_alloc = i;
+
+  cmpl_state->the_completion.text = (gchar*)g_realloc(cmpl_state->the_completion.text, i);
+
+  if(!cmpl_state->the_completion.text)
+    return NULL;
+  else
+    {
+      strcat(cmpl_state->the_completion.text, text);
+      return &cmpl_state->the_completion;
+    }
+}
+
+static CompletionDir*
+find_completion_dir(gchar* text_to_complete,
+		    gchar** remaining_text,
+		    CompletionState* cmpl_state)
+{
+  gchar* first_slash = strchr(text_to_complete, '/');
+  CompletionDir* dir = cmpl_state->reference_dir;
+  CompletionDir* next;
+  *remaining_text = text_to_complete;
+
+  while(first_slash)
+    {
+      gint len = first_slash - *remaining_text;
+      gint found = 0;
+      gchar *found_name = NULL;         /* Quiet gcc */
+      gint i;
+      gchar* pat_buf = g_new (gchar, len + 1);
+
+      strncpy(pat_buf, *remaining_text, len);
+      pat_buf[len] = 0;
+
+      for(i = 0; i < dir->sent->entry_count; i += 1)
+	{
+	  if(dir->sent->entries[i].is_dir &&
+	     fnmatch(pat_buf, dir->sent->entries[i].entry_name,
+		     FNMATCH_FLAGS)!= FNM_NOMATCH)
+	    {
+	      if(found)
+		{
+		  g_free (pat_buf);
+		  return dir;
+		}
+	      else
+		{
+		  found = 1;
+		  found_name = dir->sent->entries[i].entry_name;
+		}
+	    }
+	}
+
+      if (!found)
+	{
+	  /* Perhaps we are trying to open an automount directory */
+	  found_name = pat_buf;
+	}
+
+      next = open_relative_dir(found_name, dir, cmpl_state);
+      
+      if(!next)
+	{
+	  g_free (pat_buf);
+	  return NULL;
+	}
+      
+      next->cmpl_parent = dir;
+      
+      dir = next;
+      
+      if(!correct_dir_fullname(dir))
+	{
+	  g_free(pat_buf);
+	  return NULL;
+	}
+      
+      *remaining_text = first_slash + 1;
+      first_slash = strchr(*remaining_text, '/');
+
+      g_free (pat_buf);
+    }
+
+  return dir;
+}
+
+static void
+update_cmpl(PossibleCompletion* poss, CompletionState* cmpl_state)
+{
+  gint cmpl_len;
+
+  if(!poss || !cmpl_is_a_completion(poss))
+    return;
+
+  cmpl_len = strlen(cmpl_this_completion(poss));
+
+  if(cmpl_state->updated_text_alloc < cmpl_len + 1)
+    {
+      cmpl_state->updated_text =
+	(gchar*)g_realloc(cmpl_state->updated_text,
+			  cmpl_state->updated_text_alloc);
+      cmpl_state->updated_text_alloc = 2*cmpl_len;
+    }
+
+  if(cmpl_state->updated_text_len < 0)
+    {
+      strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+      cmpl_state->updated_text_len = cmpl_len;
+      cmpl_state->re_complete = cmpl_is_directory(poss);
+    }
+  else if(cmpl_state->updated_text_len == 0)
+    {
+      cmpl_state->re_complete = FALSE;
+    }
+  else
+    {
+      gint first_diff =
+	first_diff_index(cmpl_state->updated_text,
+			 cmpl_this_completion(poss));
+
+      cmpl_state->re_complete = FALSE;
+
+      if(first_diff == PATTERN_MATCH)
+	return;
+
+      if(first_diff > cmpl_state->updated_text_len)
+	strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+
+      cmpl_state->updated_text_len = first_diff;
+      cmpl_state->updated_text[first_diff] = 0;
+    }
+}
+
+static PossibleCompletion*
+attempt_file_completion(CompletionState *cmpl_state)
+{
+  gchar *pat_buf, *first_slash;
+  CompletionDir *dir = cmpl_state->active_completion_dir;
+
+  dir->cmpl_index += 1;
+
+  if(dir->cmpl_index == dir->sent->entry_count)
+    {
+      if(dir->cmpl_parent == NULL)
+	{
+	  cmpl_state->active_completion_dir = NULL;
+
+	  return NULL;
+	}
+      else
+	{
+	  cmpl_state->active_completion_dir = dir->cmpl_parent;
+
+	  return attempt_file_completion(cmpl_state);
+	}
+    }
+
+  g_assert(dir->cmpl_text);
+
+  first_slash = strchr(dir->cmpl_text, '/');
+
+  if(first_slash)
+    {
+      gint len = first_slash - dir->cmpl_text;
+
+      pat_buf = g_new (gchar, len + 1);
+      strncpy(pat_buf, dir->cmpl_text, len);
+      pat_buf[len] = 0;
+    }
+  else
+    {
+      gint len = strlen(dir->cmpl_text);
+
+      pat_buf = g_new (gchar, len + 2);
+      strcpy(pat_buf, dir->cmpl_text);
+      strcpy(pat_buf + len, "*");
+    }
+
+  if(first_slash)
+    {
+      if(dir->sent->entries[dir->cmpl_index].is_dir)
+	{
+	  if(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+		     FNMATCH_FLAGS) != FNM_NOMATCH)
+	    {
+	      CompletionDir* new_dir;
+
+	      new_dir = open_relative_dir(dir->sent->entries[dir->cmpl_index].entry_name,
+					  dir, cmpl_state);
+
+	      if(!new_dir)
+		{
+		  g_free (pat_buf);
+		  return NULL;
+		}
+
+	      new_dir->cmpl_parent = dir;
+
+	      new_dir->cmpl_index = -1;
+	      new_dir->cmpl_text = first_slash + 1;
+
+	      cmpl_state->active_completion_dir = new_dir;
+
+	      g_free (pat_buf);
+	      return attempt_file_completion(cmpl_state);
+	    }
+	  else
+	    {
+	      g_free (pat_buf);
+	      return attempt_file_completion(cmpl_state);
+	    }
+	}
+      else
+	{
+	  g_free (pat_buf);
+	  return attempt_file_completion(cmpl_state);
+	}
+    }
+  else
+    {
+      if(dir->cmpl_parent != NULL)
+	{
+	  append_completion_text(dir->fullname +
+				 strlen(cmpl_state->completion_dir->fullname) + 1,
+				 cmpl_state);
+	  append_completion_text("/", cmpl_state);
+	}
+
+      append_completion_text(dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
+
+      cmpl_state->the_completion.is_a_completion =
+	(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+		 FNMATCH_FLAGS) != FNM_NOMATCH);
+
+      cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
+      if(dir->sent->entries[dir->cmpl_index].is_dir)
+	append_completion_text("/", cmpl_state);
+
+      g_free (pat_buf);
+      return &cmpl_state->the_completion;
+    }
+}
+
+
+static gint
+get_pwdb(CompletionState* cmpl_state)
+{
+  struct passwd *pwd_ptr;
+  gchar* buf_ptr;
+  gint len = 0, i, count = 0;
+
+  if(cmpl_state->user_dir_name_buffer)
+    return TRUE;
+  setpwent ();
+
+  while ((pwd_ptr = getpwent()) != NULL)
+    {
+      len += strlen(pwd_ptr->pw_name);
+      len += strlen(pwd_ptr->pw_dir);
+      len += 2;
+      count += 1;
+    }
+
+  setpwent ();
+
+  cmpl_state->user_dir_name_buffer = g_new(gchar, len);
+  cmpl_state->user_directories = g_new(CompletionUserDir, count);
+  cmpl_state->user_directories_len = count;
+
+  buf_ptr = cmpl_state->user_dir_name_buffer;
+
+  for(i = 0; i < count; i += 1)
+    {
+      pwd_ptr = getpwent();
+      if(!pwd_ptr)
+	{
+	  cmpl_errno = errno;
+	  goto error;
+	}
+
+      strcpy(buf_ptr, pwd_ptr->pw_name);
+      cmpl_state->user_directories[i].login = buf_ptr;
+      buf_ptr += strlen(buf_ptr);
+      buf_ptr += 1;
+      strcpy(buf_ptr, pwd_ptr->pw_dir);
+      cmpl_state->user_directories[i].homedir = buf_ptr;
+      buf_ptr += strlen(buf_ptr);
+      buf_ptr += 1;
+    }
+
+  qsort(cmpl_state->user_directories,
+	cmpl_state->user_directories_len,
+	sizeof(CompletionUserDir),
+	compare_user_dir);
+
+  endpwent();
+
+  return TRUE;
+
+error:
+
+  if(cmpl_state->user_dir_name_buffer)
+    g_free(cmpl_state->user_dir_name_buffer);
+  if(cmpl_state->user_directories)
+    g_free(cmpl_state->user_directories);
+
+  cmpl_state->user_dir_name_buffer = NULL;
+  cmpl_state->user_directories = NULL;
+
+  return FALSE;
+}
+
+static gint
+compare_user_dir(const void* a, const void* b)
+{
+  return strcmp((((CompletionUserDir*)a))->login,
+		(((CompletionUserDir*)b))->login);
+}
+
+static gint
+compare_cmpl_dir(const void* a, const void* b)
+{
+  return strcmp((((CompletionDirEntry*)a))->entry_name,
+		(((CompletionDirEntry*)b))->entry_name);
+}
+
+static gint
+cmpl_state_okay(CompletionState* cmpl_state)
+{
+  return  cmpl_state && cmpl_state->reference_dir;
+}
+
+static gchar*
+cmpl_strerror(gint err)
+{
+  if(err == CMPL_ERRNO_TOO_LONG)
+    return "Name too long";
+  else
+    return g_strerror (err);
+}
+
+/* This is an internally used function to create pixmaps. */
+GtkWidget*
+create_pixmap(GtkWidget *widget, const gchar *pixmap_char)
+{
+  GdkPixmap *gdkpixmap;
+  GdkBitmap *mask;
+  GtkWidget *pixmap;
+  GdkColormap *colormap;
+
+  colormap = gtk_widget_get_colormap (widget);
+
+  gdkpixmap = gdk_pixmap_colormap_create_from_xpm_d (GTK_WIDGET(widget)->window,
+						     colormap,
+						     &mask,
+						     NULL, 
+						     (gpointer) pixmap_char);
+  if (gdkpixmap == NULL)
+    {
+      g_warning ("Error loading pixmap: %s", pixmap_char);
+      return NULL;
+    }
+  pixmap = gtk_pixmap_new (gdkpixmap, mask);
+  gdk_pixmap_unref (gdkpixmap);
+  gdk_bitmap_unref (mask);
+  return pixmap;
+}
+
+
+/* Testing area */
+#ifdef TORRIE_DEBUG
+
+/* Get the selected filename and print it to the console */
+void file_ok_sel( GtkWidget        *w,
+                  GtkFileSelection *fs )
+{
+    g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
+}
+
+void destroy( GtkWidget *widget,
+              gpointer   data )
+{
+    gtk_main_quit ();
+}
+
+int main( int   argc,
+          char *argv[] )
+{
+    GtkWidget *filew;
+    const gchar *masks[] = { "mp3s/playlists <*.mp3,*.m3u>",
+                             "src/hdr <*.[CcHh],*.[Cc][Cc],*.[Hh][Hh],*.cpp>",
+                             NULL };
+
+    gtk_init (&argc, &argv);
+
+    /* Create a new file selection widget */
+    filew = gtk_file_selection_new ("Spiffy File Selector");
+//    gtk_file_selection_complete(GTK_FILE_SELECTION(filew),"bob");
+
+    gtk_file_selection_set_masks (GTK_FILE_SELECTION (filew), masks);
+		
+    gtk_signal_connect (GTK_OBJECT (filew), "destroy",
+			(GtkSignalFunc) destroy, &filew);
+    /* Connect the ok_button to file_ok_sel function */
+    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
+			"clicked", (GtkSignalFunc) file_ok_sel, filew );
+
+    /* Connect the cancel_button to destroy the widget */
+    gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
+                                            (filew)->cancel_button),
+			       "clicked", (GtkSignalFunc) gtk_widget_destroy,
+			       GTK_OBJECT (filew));
+
+
+    gtk_widget_show(filew);
+
+/*
+    g_print("%d",gtk_file_selection_match_mask("mask.c","m*.c"));
+    g_print("%d",gtk_file_selection_match_mask("mask.c","m???.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.c","m??*.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c???"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c*"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","n*.c???"));
+		g_print("%d",gtk_file_selection_match_mask("mask.c","[mn]*"));
+		g_print("%d",gtk_file_selection_match_mask("COPYING","*.xpm"));
+*/	
+    gtk_main ();
+
+    return 0;
+}
+/* example-end */
+#endif
diff --git a/radiant/gtkfilesel-linux.h b/radiant/gtkfilesel-linux.h
index 5fb1c29e..b9ab49b7 100644
--- a/radiant/gtkfilesel-linux.h
+++ b/radiant/gtkfilesel-linux.h
@@ -1,143 +1,143 @@
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GTK_FILESEL_H__
-#define __GTK_FILESEL_H__
-
-
-#include <gdk/gdk.h>
-#include <gtk/gtkwindow.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define GTK_TYPE_FILE_SELECTION            (gtk_file_selection_get_type ())
-#define GTK_FILE_SELECTION(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_FILE_SELECTION, GtkFileSelection))
-#define GTK_FILE_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
-#define GTK_IS_FILE_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
-#define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
-
-
-typedef struct _GtkFileSelection       GtkFileSelection;
-typedef struct _GtkFileSelectionClass  GtkFileSelectionClass;
-
-struct _GtkFileSelection
-{
-  GtkWindow window;
-
-  GtkWidget *dir_list;
-  GtkWidget *file_list;
-  GtkWidget *selection_entry;
-  GtkWidget *selection_text;
-  GtkWidget *main_vbox;
-  GtkWidget *ok_button;
-  GtkWidget *cancel_button;
-  GtkWidget *help_button;
-
-  /* These are not used.  Just fillers in the class structure */
-  GtkWidget *history_pulldown;
-  GtkWidget *history_menu;
-  GList     *history_list;
-  /* ***************** */
-	
-  GtkWidget *fileop_dialog;
-  GtkWidget *fileop_entry;
-  gchar     *fileop_file;
-  gpointer   cmpl_state;
-  gpointer   fileop_data;
-
-  GtkWidget *fileop_c_dir;
-  GtkWidget *fileop_del_file;
-  GtkWidget *fileop_ren_file;
-  
-  GtkWidget *button_area;
-  GtkWidget *action_area;
-
-  GtkWidget *history_combo;
-  GList     *prev_history;
-  GList     *next_history;
-  GtkWidget *mask_entry;
-  gchar     *mask;
-  gchar     *saved_entry;
-  gchar     *saved_entry1;
-  GtkWidget *completion_label;
-
-  GtkWidget *bookmark_menu;
-  GList     *bookmark_list;
-  GList     *masks;
-
-  GtkWidget *fileop_menu;
-
-};
-
-struct _GtkFileSelectionClass
-{
-  GtkWindowClass parent_class;
-};
-
-
-GtkType    gtk_file_selection_get_type            (void);
-GtkWidget* gtk_file_selection_new                 (const gchar      *title);
-void       gtk_file_selection_set_filename        (GtkFileSelection *filesel,
-						   const gchar      *filename);
-gchar*     gtk_file_selection_get_filename        (GtkFileSelection *filesel);
-void	   gtk_file_selection_complete		  (GtkFileSelection *filesel,
-						   const gchar	    *pattern);
-void       gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
-void       gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
-
-/* proposed interface */
-void       gtk_file_selection_clear_masks         (GtkFileSelection *filesel);
-void       gtk_file_selection_set_masks           (GtkFileSelection *filesel,
-                                                   const gchar      **masks);
-/*
-  where masks is a NULL-terminated array of strings of the format:
-
-  "DESCRIPTION <MASK>" or simply "MASK"
-  ie: "C,C++ files <*.[Cc],*.cc,*.cpp>" or simply
-  "*.jpg,*.gif" etc
-
-*/
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* __GTK_FILESEL_H__ */
-
-
-
-
-
-
-
-
-
-
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_FILESEL_H__
+#define __GTK_FILESEL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwindow.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TYPE_FILE_SELECTION            (gtk_file_selection_get_type ())
+#define GTK_FILE_SELECTION(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_FILE_SELECTION, GtkFileSelection))
+#define GTK_FILE_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
+#define GTK_IS_FILE_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
+#define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
+
+
+typedef struct _GtkFileSelection       GtkFileSelection;
+typedef struct _GtkFileSelectionClass  GtkFileSelectionClass;
+
+struct _GtkFileSelection
+{
+  GtkWindow window;
+
+  GtkWidget *dir_list;
+  GtkWidget *file_list;
+  GtkWidget *selection_entry;
+  GtkWidget *selection_text;
+  GtkWidget *main_vbox;
+  GtkWidget *ok_button;
+  GtkWidget *cancel_button;
+  GtkWidget *help_button;
+
+  /* These are not used.  Just fillers in the class structure */
+  GtkWidget *history_pulldown;
+  GtkWidget *history_menu;
+  GList     *history_list;
+  /* ***************** */
+	
+  GtkWidget *fileop_dialog;
+  GtkWidget *fileop_entry;
+  gchar     *fileop_file;
+  gpointer   cmpl_state;
+  gpointer   fileop_data;
+
+  GtkWidget *fileop_c_dir;
+  GtkWidget *fileop_del_file;
+  GtkWidget *fileop_ren_file;
+  
+  GtkWidget *button_area;
+  GtkWidget *action_area;
+
+  GtkWidget *history_combo;
+  GList     *prev_history;
+  GList     *next_history;
+  GtkWidget *mask_entry;
+  gchar     *mask;
+  gchar     *saved_entry;
+  gchar     *saved_entry1;
+  GtkWidget *completion_label;
+
+  GtkWidget *bookmark_menu;
+  GList     *bookmark_list;
+  GList     *masks;
+
+  GtkWidget *fileop_menu;
+
+};
+
+struct _GtkFileSelectionClass
+{
+  GtkWindowClass parent_class;
+};
+
+
+GtkType    gtk_file_selection_get_type            (void);
+GtkWidget* gtk_file_selection_new                 (const gchar      *title);
+void       gtk_file_selection_set_filename        (GtkFileSelection *filesel,
+						   const gchar      *filename);
+gchar*     gtk_file_selection_get_filename        (GtkFileSelection *filesel);
+void	   gtk_file_selection_complete		  (GtkFileSelection *filesel,
+						   const gchar	    *pattern);
+void       gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
+void       gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
+
+/* proposed interface */
+void       gtk_file_selection_clear_masks         (GtkFileSelection *filesel);
+void       gtk_file_selection_set_masks           (GtkFileSelection *filesel,
+                                                   const gchar      **masks);
+/*
+  where masks is a NULL-terminated array of strings of the format:
+
+  "DESCRIPTION <MASK>" or simply "MASK"
+  ie: "C,C++ files <*.[Cc],*.cc,*.cpp>" or simply
+  "*.jpg,*.gif" etc
+
+*/
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_FILESEL_H__ */
+
+
+
+
+
+
+
+
+
+
diff --git a/radiant/gtkfilesel.c b/radiant/gtkfilesel.c
index 58fde0bb..aacc3b99 100644
--- a/radiant/gtkfilesel.c
+++ b/radiant/gtkfilesel.c
@@ -1,3337 +1,3337 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-
-// leo FIXME: if we keep this file then we'll need to ask permission to the author, this is LGPL
-// This file is from the Advanced File Selector widget 
-// by Michael Torrie  <torriem@byu.edu>
-// http://students.cs.byu.edu/~torriem/gtk/
-
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <sys/param.h>
-#include <dirent.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <errno.h>
-#include <pwd.h>
-#include "fnmatch.h"
-
-// leo: added "gtk/"
-#include "gdk/gdkkeysyms.h"
-#include "gtk/gtkbutton.h"
-#include "gtk/gtkentry.h"
-#include "gtkfilesel.h"
-#include "gtk/gtkhbox.h"
-#include "gtk/gtkhbbox.h"
-#include "gtk/gtklabel.h"
-#include "gtk/gtklist.h"
-#include "gtk/gtklistitem.h"
-#include "gtk/gtkmain.h"
-#include "gtk/gtkscrolledwindow.h"
-#include "gtk/gtksignal.h"
-#include "gtk/gtkvbox.h"
-#include "gtk/gtkmenu.h"
-#include "gtk/gtkmenuitem.h"
-#include "gtk/gtkoptionmenu.h"
-#include "gtk/gtkclist.h"
-#include "gtk/gtkdialog.h"
-#include "gtk/gtkcombo.h"
-#include "gtk/gtkframe.h"
-
-// leo: disable NLS
-//#include "gtk/gtkintl.h"
-#define _(String) (String)
-
-#define DIR_LIST_WIDTH   180
-#define DIR_LIST_HEIGHT  180
-#define FILE_LIST_WIDTH  180
-#define FILE_LIST_HEIGHT 180
-
-/* I've put this here so it doesn't get confused with the 
- * file completion interface */
-typedef struct _HistoryCallbackArg HistoryCallbackArg;
-
-struct _HistoryCallbackArg
-{
-  gchar *directory;
-  GtkWidget *menu_item;
-};
-
-
-typedef struct _CompletionState    CompletionState;
-typedef struct _CompletionDir      CompletionDir;
-typedef struct _CompletionDirSent  CompletionDirSent;
-typedef struct _CompletionDirEntry CompletionDirEntry;
-typedef struct _CompletionUserDir  CompletionUserDir;
-typedef struct _PossibleCompletion PossibleCompletion;
-
-/* Non-external file completion decls and structures */
-
-/* A contant telling PRCS how many directories to cache.  Its actually
- * kept in a list, so the geometry isn't important. */
-#define CMPL_DIRECTORY_CACHE_SIZE 10
-
-/* A constant used to determine whether a substring was an exact
- * match by first_diff_index()
- */
-#define PATTERN_MATCH -1
-/* The arguments used by all fnmatch() calls below
- */
-#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
-
-#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
-
-/* This structure contains all the useful information about a directory
- * for the purposes of filename completion.  These structures are cached
- * in the CompletionState struct.  CompletionDir's are reference counted.
- */
-struct _CompletionDirSent
-{
-  ino_t inode;
-  time_t mtime;
-  dev_t device;
-
-  gint entry_count;
-  gchar *name_buffer; /* memory segment containing names of all entries */
-
-  struct _CompletionDirEntry *entries;
-};
-
-struct _CompletionDir
-{
-  CompletionDirSent *sent;
-
-  gchar *fullname;
-  gint fullname_len;
-
-  struct _CompletionDir *cmpl_parent;
-  gint cmpl_index;
-  gchar *cmpl_text;
-};
-
-/* This structure contains pairs of directory entry names with a flag saying
- * whether or not they are a valid directory.  NOTE: This information is used
- * to provide the caller with information about whether to update its completions
- * or try to open a file.  Since directories are cached by the directory mtime,
- * a symlink which points to an invalid file (which will not be a directory),
- * will not be reevaluated if that file is created, unless the containing
- * directory is touched.  I consider this case to be worth ignoring (josh).
- */
-struct _CompletionDirEntry
-{
-  gint is_dir;
-  gchar *entry_name;
-};
-
-struct _CompletionUserDir
-{
-  gchar *login;
-  gchar *homedir;
-};
-
-struct _PossibleCompletion
-{
-  /* accessible fields, all are accessed externally by functions
-   * declared above
-   */
-  gchar *text;
-  gint is_a_completion;
-  gint is_directory;
-
-  gint file_size;
-  gint file_time;
-  gint uid;
-  gint gid;
-  /* Private fields
-   */
-  gint text_alloc;
-};
-
-struct _CompletionState
-{
-  gint last_valid_char;
-  gchar *updated_text;
-  gint updated_text_len;
-  gint updated_text_alloc;
-  gint re_complete;
-
-  gchar *user_dir_name_buffer;
-  gint user_directories_len;
-
-  gchar *last_completion_text;
-
-  gint user_completion_index; /* if >= 0, currently completing ~user */
-
-  struct _CompletionDir *completion_dir; /* directory completing from */
-  struct _CompletionDir *active_completion_dir;
-
-  struct _PossibleCompletion the_completion;
-
-  struct _CompletionDir *reference_dir; /* initial directory */
-
-  GList* directory_storage;
-  GList* directory_sent_storage;
-
-  struct _CompletionUserDir *user_directories;
-};
-
-
-/* File completion functions which would be external, were they used
- * outside of this file.
- */
-
-static CompletionState*    cmpl_init_state        (void);
-static void                cmpl_free_state        (CompletionState *cmpl_state);
-static gint                cmpl_state_okay        (CompletionState* cmpl_state);
-static gchar*              cmpl_strerror          (gint);
-
-static PossibleCompletion* cmpl_completion_matches(gchar           *text_to_complete,
-						   gchar          **remaining_text,
-						   CompletionState *cmpl_state);
-
-/* Returns a name for consideration, possibly a completion, this name
- * will be invalid after the next call to cmpl_next_completion.
- */
-static char*               cmpl_this_completion   (PossibleCompletion*);
-
-/* True if this completion matches the given text.  Otherwise, this
- * output can be used to have a list of non-completions.
- */
-static gint                cmpl_is_a_completion   (PossibleCompletion*);
-
-/* True if the completion is a directory
- */
-static gint                cmpl_is_directory      (PossibleCompletion*);
-
-/* Obtains the next completion, or NULL
- */
-static PossibleCompletion* cmpl_next_completion   (CompletionState*);
-
-/* Updating completions: the return value of cmpl_updated_text() will
- * be text_to_complete completed as much as possible after the most
- * recent call to cmpl_completion_matches.  For the present
- * application, this is the suggested replacement for the user's input
- * string.  You must CALL THIS AFTER ALL cmpl_text_completions have
- * been received.
- */
-static gchar*              cmpl_updated_text       (CompletionState* cmpl_state);
-
-/* After updating, to see if the completion was a directory, call
- * this.  If it was, you should consider re-calling completion_matches.
- */
-static gint                cmpl_updated_dir        (CompletionState* cmpl_state);
-
-/* Current location: if using file completion, return the current
- * directory, from which file completion begins.  More specifically,
- * the cwd concatenated with all exact completions up to the last
- * directory delimiter('/').
- */
-static gchar*              cmpl_reference_position (CompletionState* cmpl_state);
-
-/* backing up: if cmpl_completion_matches returns NULL, you may query
- * the index of the last completable character into cmpl_updated_text.
- */
-static gint                cmpl_last_valid_char    (CompletionState* cmpl_state);
-
-/* When the user selects a non-directory, call cmpl_completion_fullname
- * to get the full name of the selected file.
- */
-static gchar*              cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);
-
-
-/* Directory operations. */
-static CompletionDir* open_ref_dir         (gchar* text_to_complete,
-					    gchar** remaining_text,
-					    CompletionState* cmpl_state);
-static gboolean       check_dir            (gchar *dir_name, 
-					    struct stat *result, 
-					    gboolean *stat_subdirs);
-static CompletionDir* open_dir             (gchar* dir_name,
-					    CompletionState* cmpl_state);
-static CompletionDir* open_user_dir        (gchar* text_to_complete,
-					    CompletionState *cmpl_state);
-static CompletionDir* open_relative_dir    (gchar* dir_name, CompletionDir* dir,
-					    CompletionState *cmpl_state);
-static CompletionDirSent* open_new_dir     (gchar* dir_name, 
-					    struct stat* sbuf,
-					    gboolean stat_subdirs);
-static gint           correct_dir_fullname (CompletionDir* cmpl_dir);
-static gint           correct_parent       (CompletionDir* cmpl_dir,
-					    struct stat *sbuf);
-static gchar*         find_parent_dir_fullname    (gchar* dirname);
-static CompletionDir* attach_dir           (CompletionDirSent* sent,
-					    gchar* dir_name,
-					    CompletionState *cmpl_state);
-static void           free_dir_sent (CompletionDirSent* sent);
-static void           free_dir      (CompletionDir  *dir);
-static void           prune_memory_usage(CompletionState *cmpl_state);
-
-/* Completion operations */
-static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,
-						      CompletionState *cmpl_state);
-static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);
-static CompletionDir* find_completion_dir(gchar* text_to_complete,
-					  gchar** remaining_text,
-					  CompletionState* cmpl_state);
-static PossibleCompletion* append_completion_text(gchar* text,
-						  CompletionState* cmpl_state);
-static gint get_pwdb(CompletionState* cmpl_state);
-static gint first_diff_index(gchar* pat, gchar* text);
-static gint compare_user_dir(const void* a, const void* b);
-static gint compare_cmpl_dir(const void* a, const void* b);
-static void update_cmpl(PossibleCompletion* poss,
-			CompletionState* cmpl_state);
-
-static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);
-static void gtk_file_selection_init          (GtkFileSelection      *filesel);
-static void gtk_file_selection_destroy       (GtkObject             *object);
-static gint gtk_file_selection_key_press     (GtkWidget             *widget,
-					      GdkEventKey           *event,
-					      gpointer               user_data);
-
-static void gtk_file_selection_file_button (GtkWidget *widget,
-					    gint row, 
-					    gint column, 
-					    GdkEventButton *bevent,
-					    gpointer user_data);
-
-static void gtk_file_selection_dir_button (GtkWidget *widget,
-					   gint row,
-					   gint column,
-					   GdkEventButton *bevent,
-					   gpointer data);
-
-static void gtk_file_selection_undir_button (GtkWidget *widget,
-					     gint row,
-					     gint column,
-					     GdkEventButton *bevent,
-					     gpointer data);
-
-static void gtk_file_selection_populate      (GtkFileSelection      *fs,
-					      gchar                 *rel_path,
-					      gint                   try_complete);
-static void gtk_file_selection_abort         (GtkFileSelection      *fs);
-
-static void gtk_file_selection_update_history_menu (GtkFileSelection       *fs,
-						    gchar                  *current_dir);
-
-static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
-
-static gboolean gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
-static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
-																							GdkEventKey *event,
-																							gpointer user_data);
-static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
-																							GdkEventButton *event,
-																							gpointer user_data);
-static void gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_home_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_up_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_prev_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_next_button (GtkWidget *widget, gpointer data);
-static void gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data);
-
-static gint gtk_file_selection_match_char (gchar, gchar *mask);
-static gint gtk_file_selection_match_mask (gchar *,gchar *);
-
-
-static GtkWindowClass *parent_class = NULL;
-
-/* Saves errno when something cmpl does fails. */
-static gint cmpl_errno;
-
-/* General notes:
- * Make prev and next inactive if their respective *
- *   histories are empty.
- * Add facilities for handling hidden files and    *
- * directories                                     *
- * Add an api to access the mask, and hidden files *
- * check box?  (prob not in 1.2.x series)          *
- */
-
-/* Routine for applying mask to filenames         *
- *   Need to be optimized to minimize recursion   *
- *     help the for loop by looking for the next  *
- *     instance of the mask character following   *
- *     the '*'.  ei *.c -- look for '.'           *
- *     Also, swap all *? pairs (-> ?*), as that   *
- *     will make it possible to look ahead (?     *
- *     makes it very nondeterministic as in *?.c  *
- *     which really is ?*.c                       *
- *   Allow multiply masks, separted by commas     *
- *   Allow more flexible [] handling (ie [a-zA-Z] *
- *                                                *
- */
-static gint gtk_file_selection_match_char (gchar text, gchar *mask){
-  gchar *maskc;
-  gint x;
-  gint s;
-	
-  if (mask[0] == '[')
-    {
-      if (!strchr (mask,']')) return 0;
-      maskc = g_strdup(mask + 1); /* get the portion of mask inside []*/
-		
-      (*(strchr (maskc,']'))) = 0;
-      s = strlen ((char *)maskc);
-
-      for (x = 0; x < s; x++){
-	if (text == maskc[x])
-	  {
-	    g_free (maskc);
-	    return s + 2;
-	  }
-      }
-      g_free (maskc);
-      return 0;
-    }
-
-  if (mask[0] == '?') return 1;
-  if (mask[0] == text) return 1;
-
-  return 0;
-}
-
-
-static gint gtk_file_selection_match_mask (gchar *text, gchar *mask){
-
-  int mc;
-  int tc;
-
-  tc = 0; mc = 0;
-	
-  if (mask[0] == 0 && text[0] == 0) return 1;
-	
-  if (mask[0] == '*')
-    {
-      for (tc = 0; tc <= strlen(text); tc++)
-	{
-	  if (gtk_file_selection_match_mask (text + tc, mask + 1))
-	    return 1;
-	}
-      return 0;
-    }
-  mc = gtk_file_selection_match_char (text[0], mask);
-
-  if(mc)
-    return gtk_file_selection_match_mask (text + 1, mask + mc);
-  else
-    return 0;
-}
-
-GtkType
-gtk_file_selection_get_type (void)
-{
-  static GtkType file_selection_type = 0;
-
-  if (!file_selection_type)
-    {
-      static const GtkTypeInfo filesel_info =
-      {
-	"GtkFileSelection",
-	sizeof (GtkFileSelection),
-	sizeof (GtkFileSelectionClass),
-	(GtkClassInitFunc) gtk_file_selection_class_init,
-	(GtkObjectInitFunc) gtk_file_selection_init,
-	/* reserved_1 */ NULL,
-	/* reserved_2 */ NULL,
-        (GtkClassInitFunc) NULL,
-      };
-
-      file_selection_type = gtk_type_unique (GTK_TYPE_WINDOW, &filesel_info);
-    }
-
-  return file_selection_type;
-}
-
-static void
-gtk_file_selection_class_init (GtkFileSelectionClass *class)
-{
-  GtkObjectClass *object_class;
-
-  object_class = (GtkObjectClass*) class;
-
-  parent_class = gtk_type_class (GTK_TYPE_WINDOW);
-
-  object_class->destroy = gtk_file_selection_destroy;
-}
-
-static void
-gtk_file_selection_init (GtkFileSelection *filesel)
-{
-  GtkWidget *entry_vbox;
-  GtkWidget *label;
-  GtkWidget *list_hbox;
-  GtkWidget *confirm_area;
-  GtkWidget *vbox;
-  GtkWidget *hbox;
-  GtkWidget *pulldown_hbox;
-  GtkWidget *scrolled_win;
-  GtkWidget *mask_label;
-  GtkWidget *bigframe;
-  GtkWidget *label_lookingin;
-  GtkWidget *up_button;
-  GtkWidget *home_button;
-  GtkWidget *prev_button;
-  GtkWidget *next_button;
-  GtkWidget *refresh_button;
-
-  char *dir_title [2];
-  char *file_title [2];
-  
-  filesel->cmpl_state = cmpl_init_state ();
-
-  filesel->mask=NULL;
-  filesel->prev_history=NULL;
-  filesel->next_history=NULL;
-  filesel->saved_entry=NULL;
-
-  /* The dialog-sized vertical box  */
-  filesel->main_vbox = gtk_vbox_new (FALSE, 10);
-  gtk_container_set_border_width (GTK_CONTAINER (filesel), 10);
-  gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
-  gtk_widget_show (filesel->main_vbox);
-
-  /* The horizontal box containing create, rename etc. buttons */
-  filesel->button_area = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(filesel->button_area), GTK_BUTTONBOX_START);
-  gtk_button_box_set_spacing(GTK_BUTTON_BOX(filesel->button_area), 0);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->button_area, 
-		      FALSE, FALSE, 0);
-  gtk_widget_show (filesel->button_area);
-  
-  gtk_file_selection_show_fileop_buttons(filesel);
-
-  /* hbox for pulldown menu */
-  pulldown_hbox = gtk_hbox_new (FALSE, 5);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);
-  gtk_widget_show (pulldown_hbox);
-  
-  /* The combo box that replaces the pulldown menu */
-  label_lookingin = gtk_label_new (_("Looking in:"));
-  gtk_widget_show (label_lookingin);
-  gtk_box_pack_start (GTK_BOX (pulldown_hbox), label_lookingin, FALSE, FALSE, 0);
-
-  filesel->history_combo = gtk_combo_new();
-  gtk_widget_show(filesel->history_combo);
-  gtk_combo_set_value_in_list(GTK_COMBO(filesel->history_combo),FALSE,FALSE);
-  gtk_box_pack_start (GTK_BOX(pulldown_hbox),filesel->history_combo,
-  				TRUE,TRUE, 0);
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->entry),"key-press-event",				    
-		     (GtkSignalFunc) gtk_file_selection_history_combo_callback,
-		     (gpointer) filesel);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"button-press-event",
-		     (GtkSignalFunc) gtk_file_selection_history_combo_list_callback,
-		     (gpointer) filesel);
-
-  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"key-press-event",
-		     (GtkSignalFunc) gtk_file_selection_history_combo_list_key_handler,
-		     (gpointer) filesel);
-
-  /*  frame to put the following hbox in  */
-  bigframe = gtk_frame_new (NULL);
-  gtk_widget_show (bigframe);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), bigframe, TRUE, TRUE, 0);
-
-  /*  The horizontal box containing the directory and file listboxes  */
-  list_hbox = gtk_hbox_new (FALSE, 5);
-  gtk_container_add (GTK_CONTAINER(bigframe), list_hbox);
-  gtk_container_set_border_width (GTK_CONTAINER (list_hbox), 5);
-  gtk_widget_show (list_hbox);
-
-  /* vbox to put the buttons and directory listing in  */
-  vbox = gtk_vbox_new (FALSE, 0);
-  gtk_widget_show (vbox);
-  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, FALSE, FALSE, 0);
-
-  hbox = gtk_hbox_new (FALSE, 0);
-  gtk_widget_show (hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-  home_button = gtk_button_new_with_label (_("Home"));
-  gtk_widget_show (home_button);
-  gtk_signal_connect (GTK_OBJECT (home_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_home_button,
-		      (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox), home_button, TRUE,TRUE, 0);
-
-  prev_button = gtk_button_new_with_label (_("Prev"));
-  gtk_signal_connect (GTK_OBJECT (prev_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_prev_button,
-		      (gpointer) filesel);
-  gtk_widget_show (prev_button);
-  gtk_box_pack_start (GTK_BOX (hbox), prev_button, TRUE,TRUE, 0);
-
-  up_button = gtk_button_new_with_label (_("Up"));
-  gtk_signal_connect (GTK_OBJECT (up_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_up_button,
-		      (gpointer) filesel);
-  gtk_widget_show (up_button);
-  gtk_box_pack_start (GTK_BOX (hbox), up_button, TRUE,TRUE, 0);
-
-  next_button = gtk_button_new_with_label (_("Next"));
-  gtk_widget_show (next_button);
-  gtk_signal_connect (GTK_OBJECT (next_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_next_button,
-		      (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox), next_button, TRUE,TRUE, 0);
-
-  refresh_button = gtk_button_new_with_label (_("Refresh"));
-  gtk_widget_show (refresh_button);
-  gtk_signal_connect (GTK_OBJECT (refresh_button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_refresh_button,
-		      (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox), refresh_button, TRUE, TRUE, 0);
-
-  /* The directories clist */
-  dir_title[0] = _("Directories");
-  dir_title[1] = NULL;
-  filesel->dir_list = gtk_clist_new_with_titles (1, (gchar**) dir_title);
-  gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
-  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",
-		      (GtkSignalFunc) gtk_file_selection_dir_button,
-		      (gpointer) filesel);
-  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "unselect_row",
-		      (GtkSignalFunc) gtk_file_selection_undir_button,
-		      (gpointer) filesel);
-  gtk_clist_column_titles_passive (GTK_CLIST (filesel->dir_list));
-
-  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->dir_list);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE,TRUE, 5);
-  gtk_widget_show (filesel->dir_list);
-  gtk_widget_show (scrolled_win);
-
-  /* vbox area for mask entry and files clist  */
-  vbox = gtk_vbox_new (FALSE, 0);
-  gtk_widget_show (vbox);
-  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, TRUE, TRUE, 0);
-
-  hbox = gtk_hbox_new (FALSE, 5);
-  gtk_widget_show (hbox);
-  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
-
-  mask_label = gtk_label_new (_("Mask:"));
-  gtk_widget_show (mask_label);
-  gtk_box_pack_start (GTK_BOX (hbox), mask_label, FALSE, FALSE, 0);
-
-  filesel->mask_entry = gtk_entry_new ();
-  gtk_widget_show (filesel->mask_entry);
-  gtk_signal_connect(GTK_OBJECT(filesel->mask_entry),"activate",
-		     (GtkSignalFunc) gtk_file_selection_mask_entry_callback,
-		     (gpointer) filesel);
-  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
-
-
-  /* The files clist */
-  file_title[0] = _("Files");
-  file_title[1] = NULL;
-  filesel->file_list = gtk_clist_new_with_titles (1, (gchar**) file_title);
-  gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
-  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
-		      (GtkSignalFunc) gtk_file_selection_file_button, 
-		      (gpointer) filesel);
-  gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));
-
-  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
-  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->file_list);
-  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
-				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
-  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 5);
-  gtk_widget_show (filesel->file_list);
-  gtk_widget_show (scrolled_win);
-
-  /* action area for packing buttons into. */
-  filesel->action_area = gtk_hbox_new (TRUE, 0);
-  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->action_area, 
-		      FALSE, FALSE, 0);
-  gtk_widget_show (filesel->action_area);
-  
-  /*  The OK/Cancel button area */
-  confirm_area = gtk_hbutton_box_new ();
-  gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);
-  gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);
-  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), confirm_area, FALSE, FALSE, 0);
-  gtk_widget_show (confirm_area);
-
-  /*  The OK button  */
-  filesel->ok_button = gtk_button_new_with_label (_("OK"));
-  GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->ok_button, TRUE, TRUE, 0);
-  gtk_widget_grab_default (filesel->ok_button);
-  gtk_widget_show (filesel->ok_button);
-
-  /*  The Cancel button  */
-  filesel->cancel_button = gtk_button_new_with_label (_("Cancel"));
-  GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);
-  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->cancel_button, TRUE, TRUE, 0);
-  gtk_widget_show (filesel->cancel_button);
-
-  /*  The selection entry widget  */
-  entry_vbox = gtk_vbox_new (FALSE, 2);
-  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
-  gtk_widget_show (entry_vbox);
-
-  filesel->selection_text = label = gtk_label_new ("");
-  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
-  gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
-  gtk_widget_show (label);
-
-  filesel->selection_entry = gtk_entry_new ();
-  gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
-		      (GtkSignalFunc) gtk_file_selection_key_press, filesel);
-  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
-			     (GtkSignalFunc) gtk_widget_grab_default,
-			     GTK_OBJECT (filesel->ok_button));
-  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
-                             (GtkSignalFunc) gtk_button_clicked,
-                             GTK_OBJECT (filesel->ok_button));
-  gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
-  gtk_widget_show (filesel->selection_entry);
-
-  if (!cmpl_state_okay (filesel->cmpl_state))
-    {
-      gchar err_buf[256];
-
-      sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
-
-      gtk_label_set_text (GTK_LABEL (filesel->selection_text), err_buf);
-    }
-  else
-    {
-      gtk_file_selection_populate (filesel, "", FALSE);
-    }
-
-  gtk_widget_grab_focus (filesel->selection_entry);
-}
-
-GtkWidget*
-gtk_file_selection_new (const gchar *title)
-{
-  GtkFileSelection *filesel;
-
-  filesel = gtk_type_new (GTK_TYPE_FILE_SELECTION);
-  gtk_window_set_title (GTK_WINDOW (filesel), title);
-
-  return GTK_WIDGET (filesel);
-}
-
-void
-gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-    
-  /* delete, create directory, and rename */
-  if (!filesel->fileop_c_dir) 
-    {
-      filesel->fileop_c_dir = gtk_button_new_with_label (_("Create Dir"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_c_dir), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_create_dir, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_c_dir, TRUE, TRUE, 0);
-      gtk_widget_show (filesel->fileop_c_dir);
-    }
-	
-  if (!filesel->fileop_del_file) 
-    {
-      filesel->fileop_del_file = gtk_button_new_with_label (_("Delete File"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_del_file), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_delete_file, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_del_file, TRUE, TRUE, 0);
-      gtk_widget_show (filesel->fileop_del_file);
-    }
-
-  if (!filesel->fileop_ren_file)
-    {
-      filesel->fileop_ren_file = gtk_button_new_with_label (_("Rename File"));
-      gtk_signal_connect (GTK_OBJECT (filesel->fileop_ren_file), "clicked",
-			  (GtkSignalFunc) gtk_file_selection_rename_file, 
-			  (gpointer) filesel);
-      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
-			  filesel->fileop_ren_file, TRUE, TRUE, 0);
-      gtk_widget_show (filesel->fileop_ren_file);
-    }
-
-  gtk_widget_queue_resize(GTK_WIDGET(filesel));
-}
-
-void       
-gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
-{
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-    
-  if (filesel->fileop_ren_file) 
-    {
-      gtk_widget_destroy (filesel->fileop_ren_file);
-      filesel->fileop_ren_file = NULL;
-    }
-
-  if (filesel->fileop_del_file)
-    {
-      gtk_widget_destroy (filesel->fileop_del_file);
-      filesel->fileop_del_file = NULL;
-    }
-
-  if (filesel->fileop_c_dir)
-    {
-      gtk_widget_destroy (filesel->fileop_c_dir);
-      filesel->fileop_c_dir = NULL;
-    }
-}
-
-
-
-void
-gtk_file_selection_set_filename (GtkFileSelection *filesel,
-				 const gchar      *filename)
-{
-  char  buf[MAXPATHLEN];
-  const char *name, *last_slash;
-
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-  g_return_if_fail (filename != NULL);
-
-  last_slash = strrchr (filename, '/');
-
-  if (!last_slash)
-    {
-      buf[0] = 0;
-      name = filename;
-    }
-  else
-    {
-      gint len = MIN (MAXPATHLEN - 1, last_slash - filename + 1);
-
-      strncpy (buf, filename, len);
-      buf[len] = 0;
-
-      name = last_slash + 1;
-    }
-
-  gtk_file_selection_populate (filesel, buf, FALSE);
-
-  if (filesel->selection_entry)
-    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
-}
-
-gchar*
-gtk_file_selection_get_filename (GtkFileSelection *filesel)
-{
-  static char nothing[2] = "";
-  char *text;
-  char *filename;
-
-  g_return_val_if_fail (filesel != NULL, nothing);
-  g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), nothing);
-
-  text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
-  if (text)
-    {
-      filename = cmpl_completion_fullname (text, filesel->cmpl_state);
-      return filename;
-    }
-
-  return nothing;
-}
-
-void
-gtk_file_selection_complete (GtkFileSelection *filesel,
-			     const gchar      *pattern)
-{
-  gchar *new_pattern;
-  gint x;
-	
-  g_return_if_fail (filesel != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
-  g_return_if_fail (pattern != NULL);
-
-  if (filesel->selection_entry)
-    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), pattern);
-	
-  if(strchr(pattern,'*') || strchr(pattern,'?'))
-    {
-      for(x=strlen(pattern);x>=0;x--)
-	{
-	  if(pattern[x]=='/') break;
-	}
-      gtk_entry_set_text(GTK_ENTRY(filesel->mask_entry),g_strdup(pattern+x+1));
-      
-      if(filesel->mask) g_free(filesel->mask);
-      
-      filesel->mask=g_strdup(pattern+x+1);
-      new_pattern=g_strdup(pattern);
-      new_pattern[x+1]=0;
-      gtk_file_selection_populate (filesel, (gchar*) new_pattern, TRUE);
-      g_free(new_pattern);
-    }
-  else
-    {
-      gtk_file_selection_populate (filesel, (gchar*) pattern, TRUE);
-    }
-}
-
-static void
-gtk_file_selection_destroy (GtkObject *object)
-{
-  GtkFileSelection *filesel;
-  GList *list;
-
-  g_return_if_fail (object != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (object));
-
-  filesel = GTK_FILE_SELECTION (object);
-  
-  if (filesel->fileop_dialog)
-    gtk_widget_destroy (filesel->fileop_dialog);
-  
-  if (filesel->next_history)
-    {
-      list = filesel->next_history;
-      while (list)
-  	{
-	  g_free (list->data);
-	  list = list->next;
-  	}
-    }
-  g_list_free (filesel->next_history);
-  filesel->next_history = NULL;
-
-  if (filesel->prev_history)
-    {
-      list = filesel->prev_history;
-      while (list)
-  	{
-	  g_free (list->data);
-	  list = list->next;
-  	}
-    }
-  g_list_free (filesel->prev_history);
-  filesel->prev_history = NULL;
-
-  if (filesel->mask)
-    {
-      g_free (filesel->mask);
-      filesel->mask = NULL;
-    }
-  
-  cmpl_free_state (filesel->cmpl_state);
-  filesel->cmpl_state = NULL;
-
-  if (GTK_OBJECT_CLASS (parent_class)->destroy)
-    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
-/* Begin file operations callbacks */
-
-static void
-gtk_file_selection_fileop_error (GtkFileSelection *fs, gchar *error_message)
-{
-  GtkWidget *label;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  GtkWidget *dialog;
-  
-  g_return_if_fail (error_message != NULL);
-  
-  /* main dialog */
-  dialog = gtk_dialog_new ();
-  /*
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  */
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-  
-  /* If file dialog is grabbed, make this dialog modal too */
-  /* When error dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-
-  label = gtk_label_new(error_message);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-
-  /* yes, we free it */
-  g_free (error_message);
-  
-  /* close button */
-  button = gtk_button_new_with_label (_("Close"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-static void
-gtk_file_selection_fileop_destroy (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  fs->fileop_dialog = NULL;
-}
-
-
-static void
-gtk_file_selection_create_dir_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  gchar *dirname;
-  gchar *path;
-  gchar *full_path;
-  gchar *buf;
-  CompletionState *cmpl_state;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  dirname = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  full_path = g_strconcat (path, "/", dirname, NULL);
-  if ( (mkdir (full_path, 0755) < 0) ) 
-    {
-      buf = g_strconcat ("Error creating directory \"", dirname, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (full_path);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-  
-static void
-gtk_file_selection_create_dir (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *button;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Create Directory"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-  
-  label = gtk_label_new(_("Directory name:"));
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-
-  /*  The directory entry widget  */
-  fs->fileop_entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
-		      TRUE, TRUE, 5);
-  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
-  gtk_widget_show (fs->fileop_entry);
-  
-  /* buttons */
-  button = gtk_button_new_with_label (_("Create"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_create_dir_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-static void
-gtk_file_selection_delete_file_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  CompletionState *cmpl_state;
-  gchar *path;
-  gchar *full_path;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  full_path = g_strconcat (path, "/", fs->fileop_file, NULL);
-  if ( (unlink (full_path) < 0) ) 
-    {
-      buf = g_strconcat ("Error deleting file \"", fs->fileop_file, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (full_path);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-
-static void
-gtk_file_selection_delete_file (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  GtkWidget *dialog;
-  gchar *filename;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-
-  filename = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-  if (strlen(filename) < 1)
-	  return;
-
-  fs->fileop_file = filename;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Delete File"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog is closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-  
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-
-  buf = g_strconcat ("Really delete file \"", filename, "\" ?", NULL);
-  label = gtk_label_new(buf);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-  g_free(buf);
-  
-  /* buttons */
-  button = gtk_button_new_with_label (_("Delete"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_delete_file_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-
-}
-
-static void
-gtk_file_selection_rename_file_confirmed (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  gchar *buf;
-  gchar *file;
-  gchar *path;
-  gchar *new_filename;
-  gchar *old_filename;
-  CompletionState *cmpl_state;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  path = cmpl_reference_position (cmpl_state);
-  
-  new_filename = g_strconcat (path, "/", file, NULL);
-  old_filename = g_strconcat (path, "/", fs->fileop_file, NULL);
-
-  if ( (rename (old_filename, new_filename)) < 0) 
-    {
-      buf = g_strconcat ("Error renaming file \"", file, "\":  ", 
-			 g_strerror(errno), NULL);
-      gtk_file_selection_fileop_error (fs, buf);
-    }
-  g_free (new_filename);
-  g_free (old_filename);
-  
-  gtk_widget_destroy (fs->fileop_dialog);
-  gtk_file_selection_populate (fs, "", FALSE);
-}
-  
-static void
-gtk_file_selection_rename_file (GtkWidget *widget, gpointer data)
-{
-  GtkFileSelection *fs = data;
-  GtkWidget *label;
-  GtkWidget *dialog;
-  GtkWidget *vbox;
-  GtkWidget *button;
-  gchar *buf;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  if (fs->fileop_dialog)
-	  return;
-
-  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-  if (strlen(fs->fileop_file) < 1)
-	  return;
-  
-  /* main dialog */
-  fs->fileop_dialog = dialog = gtk_dialog_new ();
-  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
-		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
-		      (gpointer) fs);
-  gtk_window_set_title (GTK_WINDOW (dialog), _("Rename File"));
-  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
-
-  /* If file dialog is grabbed, grab option dialog */
-  /* When option dialog  closed, file dialog will be grabbed again */
-  if (GTK_WINDOW(fs)->modal)
-    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
-  
-  vbox = gtk_vbox_new(FALSE, 0);
-  gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
-		     FALSE, FALSE, 0);
-  gtk_widget_show(vbox);
-  
-  buf = g_strconcat ("Rename file \"", fs->fileop_file, "\" to:", NULL);
-  label = gtk_label_new(buf);
-  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
-  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
-  gtk_widget_show(label);
-  g_free(buf);
-
-  /* New filename entry */
-  fs->fileop_entry = gtk_entry_new ();
-  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
-		      TRUE, TRUE, 5);
-  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
-  gtk_widget_show (fs->fileop_entry);
-  
-  gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
-  gtk_editable_select_region (GTK_EDITABLE (fs->fileop_entry),
-			      0, strlen (fs->fileop_file));
-
-  /* buttons */
-  button = gtk_button_new_with_label (_("Rename"));
-  gtk_signal_connect (GTK_OBJECT (button), "clicked",
-		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
-		      (gpointer) fs);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_show(button);
-  
-  button = gtk_button_new_with_label (_("Cancel"));
-  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
-			     (GtkSignalFunc) gtk_widget_destroy, 
-			     (gpointer) dialog);
-  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
-		     button, TRUE, TRUE, 0);
-  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
-  gtk_widget_grab_default(button);
-  gtk_widget_show (button);
-
-  gtk_widget_show (dialog);
-}
-
-
-static gint
-gtk_file_selection_key_press (GtkWidget   *widget,
-			      GdkEventKey *event,
-			      gpointer     user_data)
-{
-  GtkFileSelection *fs;
-  char *text;
-
-  g_return_val_if_fail (widget != NULL, FALSE);
-  g_return_val_if_fail (event != NULL, FALSE);
-
-  fs = GTK_FILE_SELECTION (user_data);
-
-  if (event->keyval == GDK_Tab)
-    {
-      text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
-
-      text = g_strdup (text);
-
-      gtk_file_selection_populate (fs, text, TRUE);
-
-      g_free (text);
-
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-
-      return TRUE;
-    }
-  if (fs->saved_entry)
-    {
-      gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
-      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
-      g_free (fs->saved_entry);
-      fs->saved_entry = NULL;
-    }
-
-
-  return FALSE;
-}
-
-static void
-gtk_file_selection_home_button (GtkWidget *widget, gpointer data){
-  GList *list;
-	
-  GtkFileSelection *fs=data;
-
-  list = fs->next_history;
-  if (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-		
-  gtk_file_selection_populate (fs,"~/",FALSE);
-}
-
-static void
-gtk_file_selection_up_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->next_history;
-  if (list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-
-  gtk_file_selection_populate (fs, "../", FALSE); /*change directories. */
-		
-}
-
-static void
-gtk_file_selection_prev_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-  GList *first;
-  gchar *path;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->prev_history;
-
-  if (list && g_list_length(list) > 1)
-    {
-      first = list;            /* get first element */
-      list = list->next;       /* pop off current directory */
-
-      list->prev = NULL;       /* make this the new head. */
-  	
-      fs->prev_history = list; /* update prev_history list */
-      fs->next_history = g_list_prepend(fs->next_history,first->data); /* put it on next_history */
-  	
-      first->next = NULL;      /* orphan the old first node */
-      g_list_free (first);     /* free the node (data is now in use by next_history) */
-
-
-  	
-      path = g_malloc(strlen(list->data)+4); /* plenty of space */
-      strcpy(path,list->data);               /* get the 2nd path in the history */
-      strcat(path,"/");                      /* append a '/' */
-      gtk_file_selection_populate (fs, path, FALSE); /* change directories. */
-      g_free (path);
-    }
-}	
-
-static void
-gtk_file_selection_next_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-  GList *list;
-  GList *first;
-  gchar *path;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  list = fs->next_history;
-
-  if (list && g_list_length(list) > 0)
-    {
-      first = list;            /*get first element*/
-      list = list->next;       /*pop off current directory*/
-      
-      if (list)
-	list->prev = NULL;
-      
-      fs->next_history = list;                       /*update prev_history list*/
-  	
-      path = g_malloc(strlen(first->data)+4);        /*plenty of space*/
-      strcpy(path,first->data);
-      strcat(path,"/");                              /*append a /   */
-      gtk_file_selection_populate (fs, path, FALSE); /*change directories.*/
-      g_free(path);
-  	
-      first->next = NULL;     /* orphan the old first node */
-      g_list_free (first);    /* free the node (data is now in use by next_history) */
-      
-    }
-}	
-
-void static
-gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_file_selection_populate (fs,"",FALSE);
-}
-
-static void
-gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data){
-  GtkFileSelection *fs = data;
-
-  if(fs->mask)
-    g_free (fs->mask);
-		
-  fs->mask = g_strdup(gtk_entry_get_text (GTK_ENTRY(fs->mask_entry)));
-	
-  if (strlen(fs->mask) == 0)
-    {
-      g_free (fs->mask);
-      fs->mask = NULL;
-    }
-	
-  gtk_file_selection_refresh_button (widget,data);
-}
-
-static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
-								  GdkEventKey *event,
-								  gpointer user_data)
-{
-  /*
-  g_print("Key pressed! \n");
-  */
-	
-  return TRUE;
-}
-
-static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
-								GdkEventButton *event,
-								gpointer user_data)
-{
-
-  GtkFileSelection *fs = user_data;
-  GList *list;
-  gchar *path;
-		
-  list = fs->next_history;
-  if(list)
-    {
-      g_free (list->data);
-      list = list->next;
-    }
-  g_list_free (fs->next_history);
-  fs->next_history = NULL;
-			
-  path = g_malloc(strlen(gtk_entry_get_text(GTK_ENTRY (((GtkCombo *)fs->history_combo)->entry)))+4);
-  strcpy (path,gtk_entry_get_text(GTK_ENTRY( ((GtkCombo *)fs->history_combo)->entry)));
-  strcat (path,"/");
-	
-  gtk_file_selection_populate (fs,path,TRUE);
-	
-  g_free (path);
-
-  return TRUE;
-}
-
-static gboolean
-gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
-{
-  GtkEntry *entry=(GtkEntry *)widget;
-  GtkFileSelection *fs=data;
-  GList *list;
-  gchar *path;
-	
-  g_return_val_if_fail (fs != NULL,FALSE);
-  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
-	
-
-  if (event->keyval == GDK_Return)
-    {
-      list = fs->next_history;
-      if (list)
-	{
-	  g_free (list->data);
-	  list = list->next;
-	}
-      g_list_free (fs->next_history);
-      fs->next_history = NULL;
-      
-      path = g_malloc(strlen(gtk_entry_get_text(entry))+4);
-      strcpy (path,gtk_entry_get_text(entry));
-      strcat (path,"/");
-      gtk_file_selection_populate (fs,path,TRUE);
-      g_free (path);
-      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
-      return TRUE;
-    }
-  else
-    {
-      return FALSE;
-    }
-
-}
-
-static void
-gtk_file_selection_update_history_menu (GtkFileSelection *fs,
-					gchar *current_directory)
-{
-  gchar *current_dir;
-
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  g_return_if_fail (current_directory != NULL);
-  
-  current_dir = g_strdup (current_directory);
-
-  if(fs->prev_history)
-    {
-      if (strcmp((fs->prev_history)->data,current_dir))
-	{ /*if this item isn't on the top of the list */
-	  fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
-	}
-    } else {
-      fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
-    }
-  
-  gtk_combo_set_popdown_strings (GTK_COMBO (fs->history_combo),fs->prev_history);
-  
-  g_free (current_dir);
-}
-
-static void
-gtk_file_selection_file_button (GtkWidget *widget,
-			       gint row, 
-			       gint column, 
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-  
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = user_data;
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  gtk_clist_get_text (GTK_CLIST (fs->file_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  case GDK_2BUTTON_PRESS:
-	    gtk_button_clicked (GTK_BUTTON (fs->ok_button));
-	    break;
-	    
-	  default:
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-      
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_dir_button (GtkWidget *widget,
-			       gint row, 
-			       gint column, 
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GList *list;
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = GTK_FILE_SELECTION (user_data);
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  case GDK_2BUTTON_PRESS:
-	    list = fs->next_history;
-	    if (list)
-	      {
-		g_free (list->data);
-		list = list->next;
-	      }
-	    g_list_free (fs->next_history);
-	    fs->next_history = NULL;
-	
-	    gtk_file_selection_populate (fs, filename, FALSE);
-	    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
-	    g_free (fs->saved_entry);
-	    fs->saved_entry = NULL;
-	    break;
-	    
-	  default:
-	    /* here we need to add the "filename" to the beginning of what's already
-	       in the entry.  Save what's in the entry, then restore it on the double click
-	    */
-	    if (fs->saved_entry) g_free (fs->saved_entry);
-	    fs->saved_entry=g_strdup(gtk_entry_get_text(GTK_ENTRY (fs->selection_entry)));
-	
-	    temp=g_strconcat(filename,fs->saved_entry,NULL);
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), temp);
-	    g_free (temp);
-	
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
-      
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_undir_button (GtkWidget *widget,
-			       gint row,
-			       gint column,
-			       GdkEventButton *bevent,
-			       gpointer user_data)
-{
-  GtkFileSelection *fs = NULL;
-  gchar *filename, *temp = NULL;
-
-  g_return_if_fail (GTK_IS_CLIST (widget));
-
-  fs = GTK_FILE_SELECTION (user_data);
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-
-  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
-  filename = g_strdup (temp);
-
-  if (filename)
-    {
-      if (bevent)
-	switch (bevent->type)
-	  {
-	  default:
-	    /* here we need to add the "filename" to the beginning of what's already
-	       in the entry.  Save what's in the entry, then restore it on the double click
-	    */
-	    if (fs->saved_entry)
-	      {
-	        gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),fs->saved_entry);
-		g_free (fs->saved_entry);
-		fs->saved_entry = NULL;
-	      }
-	    break;
-	  }
-      else
-	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename); //?????
-
-      g_free (filename);
-    }
-}
-
-static void
-gtk_file_selection_populate (GtkFileSelection *fs,
-			     gchar            *rel_path,
-			     gint              try_complete)
-{
-  CompletionState *cmpl_state;
-  PossibleCompletion* poss;
-  gchar* filename;
-  gint row;
-  gchar* rem_path = rel_path;
-  gchar* sel_text;
-  gchar* text[2];
-  gint did_recurse = FALSE;
-  gint possible_count = 0;
-  gint selection_index = -1;
-  gint file_list_width;
-  gint dir_list_width;
-  
-  g_return_if_fail (fs != NULL);
-  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
-  
-  cmpl_state = (CompletionState*) fs->cmpl_state;
-  poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
-
-  if (!cmpl_state_okay (cmpl_state))
-    {
-      /* Something went wrong. */
-      gtk_file_selection_abort (fs);
-      return;
-    }
-
-  g_assert (cmpl_state->reference_dir);
-
-  gtk_clist_freeze (GTK_CLIST (fs->dir_list));
-  gtk_clist_clear (GTK_CLIST (fs->dir_list));
-  gtk_clist_freeze (GTK_CLIST (fs->file_list));
-  gtk_clist_clear (GTK_CLIST (fs->file_list));
-
-  /* Set the dir_list to include ./ and ../ */
-  text[1] = NULL;
-  text[0] = "./";
-  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-
-  text[0] = "../";
-  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-
-  /*reset the max widths of the lists*/
-  dir_list_width = gdk_string_width(fs->dir_list->style->font,"../");
-  gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,dir_list_width);
-  file_list_width = 1;
-  gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,file_list_width);
-
-  while (poss)
-    {
-      if (cmpl_is_a_completion (poss))
-  	{
-	  possible_count += 1;
-	  
-	  filename = cmpl_this_completion (poss);
-
-	  text[0] = filename;
-	  
-	  if (cmpl_is_directory (poss))
-	    {
-	      if (strcmp (filename, "./") != 0 &&
-		  strcmp (filename, "../") != 0)
-		{
-		  int width = gdk_string_width(fs->dir_list->style->font,
-					       filename);
-		  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
-		  if(width > dir_list_width)
-		    {
-		      dir_list_width = width;
-		      gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,
-						 width);
-		    }
-		}
-	    }
-	  else
-	    {
-	      if(fs->mask)
-		{
-		  if (gtk_file_selection_match_mask(filename,fs->mask))
-		    {
-		      int width = gdk_string_width(fs->file_list->style->font,
-						   filename);
-		      row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
-		      if(width > file_list_width)
-		        {
-		          file_list_width = width;
-		          gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
-						     width);
-		        }
-		    }
-		}
-	      else
-		{
-		  int width = gdk_string_width(fs->file_list->style->font,
-					       filename);
-		  row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
-		  if(width > file_list_width)
-		    {
-		      file_list_width = width;
-		      gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
-						 width);
-		    }
-		}
-	    }
-	}
-
-      poss = cmpl_next_completion (cmpl_state);
-    }
-
-  gtk_clist_thaw (GTK_CLIST (fs->dir_list));
-  gtk_clist_thaw (GTK_CLIST (fs->file_list));
-
-  /* File lists are set. */
-
-  g_assert (cmpl_state->reference_dir);
-
-  if (try_complete)
-    {
-
-      /* User is trying to complete filenames, so advance the user's input
-       * string to the updated_text, which is the common leading substring
-       * of all possible completions, and if its a directory attempt
-       * attempt completions in it. */
-
-      if (cmpl_updated_text (cmpl_state)[0])
-        {
-
-          if (cmpl_updated_dir (cmpl_state))
-            {
-	      gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
-
-              did_recurse = TRUE;
-
-              gtk_file_selection_populate (fs, dir_name, TRUE);
-
-              g_free (dir_name);
-            }
-          else
-            {
-	      if (fs->selection_entry)
-		      gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
-					  cmpl_updated_text (cmpl_state));
-            }
-        }
-      else
-        {
-          selection_index = cmpl_last_valid_char (cmpl_state) -
-                            (strlen (rel_path) - strlen (rem_path));
-	  if (fs->selection_entry)
-	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
-        }
-    }
-  else
-    {
-      if (fs->selection_entry)
-      /* Here we need to take the old filename and keep it!*/
-	/*gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");*/
-	;
-    }
-
-  if (!did_recurse)
-    {
-      if (fs->selection_entry)
-	gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
-
-      if (fs->selection_entry)
-	{
-	  sel_text = g_strconcat (_("Selection: "),
-				  cmpl_reference_position (cmpl_state),
-				  NULL);
-
-	  gtk_label_set_text (GTK_LABEL (fs->selection_text), sel_text);
-	  g_free (sel_text);
-	}
-
-  gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state));
-
-    }
-}
-
-static void
-gtk_file_selection_abort (GtkFileSelection *fs)
-{
-  gchar err_buf[256];
-
-  sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
-
-  /*  BEEP gdk_beep();  */
-
-  if (fs->selection_entry)
-    gtk_label_set_text (GTK_LABEL (fs->selection_text), err_buf);
-}
-
-/**********************************************************************/
-/*			  External Interface                          */
-/**********************************************************************/
-
-/* The four completion state selectors
- */
-static gchar*
-cmpl_updated_text (CompletionState* cmpl_state)
-{
-  return cmpl_state->updated_text;
-}
-
-static gint
-cmpl_updated_dir (CompletionState* cmpl_state)
-{
-  return cmpl_state->re_complete;
-}
-
-static gchar*
-cmpl_reference_position (CompletionState* cmpl_state)
-{
-  return cmpl_state->reference_dir->fullname;
-}
-
-static gint
-cmpl_last_valid_char (CompletionState* cmpl_state)
-{
-  return cmpl_state->last_valid_char;
-}
-
-static gchar*
-cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state)
-{
-  static char nothing[2] = "";
-
-  if (!cmpl_state_okay (cmpl_state))
-    {
-      return nothing;
-    }
-  else if (text[0] == '/')
-    {
-      strcpy (cmpl_state->updated_text, text);
-    }
-  else if (text[0] == '~')
-    {
-      CompletionDir* dir;
-      char* slash;
-
-      dir = open_user_dir (text, cmpl_state);
-
-      if (!dir)
-	{
-	  /* spencer says just return ~something, so
-	   * for now just do it. */
-	  strcpy (cmpl_state->updated_text, text);
-	}
-      else
-	{
-
-	  strcpy (cmpl_state->updated_text, dir->fullname);
-
-	  slash = strchr (text, '/');
-
-	  if (slash)
-	    strcat (cmpl_state->updated_text, slash);
-	}
-    }
-  else
-    {
-      strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
-      if (strcmp (cmpl_state->reference_dir->fullname, "/") != 0)
-	strcat (cmpl_state->updated_text, "/");
-      strcat (cmpl_state->updated_text, text);
-    }
-
-  return cmpl_state->updated_text;
-}
-
-/* The three completion selectors
- */
-static gchar*
-cmpl_this_completion (PossibleCompletion* pc)
-{
-  return pc->text;
-}
-
-static gint
-cmpl_is_directory (PossibleCompletion* pc)
-{
-  return pc->is_directory;
-}
-
-static gint
-cmpl_is_a_completion (PossibleCompletion* pc)
-{
-  return pc->is_a_completion;
-}
-
-/**********************************************************************/
-/*	                 Construction, deletion                       */
-/**********************************************************************/
-
-static CompletionState*
-cmpl_init_state (void)
-{
-  gchar getcwd_buf[2*MAXPATHLEN];
-  CompletionState *new_state;
-
-  new_state = g_new (CompletionState, 1);
-
-  /* We don't use getcwd() on SUNOS, because, it does a popen("pwd")
-   * and, if that wasn't bad enough, hangs in doing so.
-   */
-#if defined(sun) && !defined(__SVR4)
-  if (!getwd (getcwd_buf))
-#else    
-  if (!getcwd (getcwd_buf, MAXPATHLEN))
-#endif    
-    {
-      /* Oh joy, we can't get the current directory. Um..., we should have
-       * a root directory, right? Right? (Probably not portable to non-Unix)
-       */
-      strcpy (getcwd_buf, "/");
-    }
-
-tryagain:
-
-  new_state->reference_dir = NULL;
-  new_state->completion_dir = NULL;
-  new_state->active_completion_dir = NULL;
-  new_state->directory_storage = NULL;
-  new_state->directory_sent_storage = NULL;
-  new_state->last_valid_char = 0;
-  new_state->updated_text = g_new (gchar, MAXPATHLEN);
-  new_state->updated_text_alloc = MAXPATHLEN;
-  new_state->the_completion.text = g_new (gchar, MAXPATHLEN);
-  new_state->the_completion.text_alloc = MAXPATHLEN;
-  new_state->user_dir_name_buffer = NULL;
-  new_state->user_directories = NULL;
-
-  new_state->reference_dir =  open_dir (getcwd_buf, new_state);
-
-  if (!new_state->reference_dir)
-    {
-      /* Directories changing from underneath us, grumble */
-      strcpy (getcwd_buf, "/");
-      goto tryagain;
-    }
-
-  return new_state;
-}
-
-static void
-cmpl_free_dir_list(GList* dp0)
-{
-  GList *dp = dp0;
-
-  while (dp) {
-    free_dir (dp->data);
-    dp = dp->next;
-  }
-
-  g_list_free(dp0);
-}
-
-static void
-cmpl_free_dir_sent_list(GList* dp0)
-{
-  GList *dp = dp0;
-
-  while (dp) {
-    free_dir_sent (dp->data);
-    dp = dp->next;
-  }
-
-  g_list_free(dp0);
-}
-
-static void
-cmpl_free_state (CompletionState* cmpl_state)
-{
-  cmpl_free_dir_list (cmpl_state->directory_storage);
-  cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage);
-
-  if (cmpl_state->user_dir_name_buffer)
-    g_free (cmpl_state->user_dir_name_buffer);
-  if (cmpl_state->user_directories)
-    g_free (cmpl_state->user_directories);
-  if (cmpl_state->the_completion.text)
-    g_free (cmpl_state->the_completion.text);
-  if (cmpl_state->updated_text)
-    g_free (cmpl_state->updated_text);
-
-  g_free (cmpl_state);
-}
-
-static void
-free_dir(CompletionDir* dir)
-{
-  g_free(dir->fullname);
-  g_free(dir);
-}
-
-static void
-free_dir_sent(CompletionDirSent* sent)
-{
-  g_free(sent->name_buffer);
-  g_free(sent->entries);
-  g_free(sent);
-}
-
-static void
-prune_memory_usage(CompletionState *cmpl_state)
-{
-  GList* cdsl = cmpl_state->directory_sent_storage;
-  GList* cdl = cmpl_state->directory_storage;
-  GList* cdl0 = cdl;
-  gint len = 0;
-
-  for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1)
-    cdsl = cdsl->next;
-
-  if (cdsl) {
-    cmpl_free_dir_sent_list(cdsl->next);
-    cdsl->next = NULL;
-  }
-
-  cmpl_state->directory_storage = NULL;
-  while (cdl) {
-    if (cdl->data == cmpl_state->reference_dir)
-      cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data);
-    else
-      free_dir (cdl->data);
-    cdl = cdl->next;
-  }
-
-  g_list_free(cdl0);
-}
-
-/**********************************************************************/
-/*                        The main entrances.                         */
-/**********************************************************************/
-
-static PossibleCompletion*
-cmpl_completion_matches (gchar* text_to_complete,
-			 gchar** remaining_text,
-			 CompletionState* cmpl_state)
-{
-  gchar* first_slash;
-  PossibleCompletion *poss;
-
-  prune_memory_usage(cmpl_state);
-
-  g_assert (text_to_complete != NULL);
-
-  cmpl_state->user_completion_index = -1;
-  cmpl_state->last_completion_text = text_to_complete;
-  cmpl_state->the_completion.text[0] = 0;
-  cmpl_state->last_valid_char = 0;
-  cmpl_state->updated_text_len = -1;
-  cmpl_state->updated_text[0] = 0;
-  cmpl_state->re_complete = FALSE;
-
-  first_slash = strchr (text_to_complete, '/');
-
-  if (text_to_complete[0] == '~' && !first_slash)
-    {
-      /* Text starts with ~ and there is no slash, show all the
-       * home directory completions.
-       */
-      poss = attempt_homedir_completion (text_to_complete, cmpl_state);
-
-      update_cmpl(poss, cmpl_state);
-
-      return poss;
-    }
-
-  cmpl_state->reference_dir =
-    open_ref_dir (text_to_complete, remaining_text, cmpl_state);
-
-  if(!cmpl_state->reference_dir)
-    return NULL;
-
-  cmpl_state->completion_dir =
-    find_completion_dir (*remaining_text, remaining_text, cmpl_state);
-
-  cmpl_state->last_valid_char = *remaining_text - text_to_complete;
-
-  if(!cmpl_state->completion_dir)
-    return NULL;
-
-  cmpl_state->completion_dir->cmpl_index = -1;
-  cmpl_state->completion_dir->cmpl_parent = NULL;
-  cmpl_state->completion_dir->cmpl_text = *remaining_text;
-
-  cmpl_state->active_completion_dir = cmpl_state->completion_dir;
-
-  cmpl_state->reference_dir = cmpl_state->completion_dir;
-
-  poss = attempt_file_completion(cmpl_state);
-
-  update_cmpl(poss, cmpl_state);
-
-  return poss;
-}
-
-static PossibleCompletion*
-cmpl_next_completion (CompletionState* cmpl_state)
-{
-  PossibleCompletion* poss = NULL;
-
-  cmpl_state->the_completion.text[0] = 0;
-
-  if(cmpl_state->user_completion_index >= 0)
-    poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state);
-  else
-    poss = attempt_file_completion(cmpl_state);
-
-  update_cmpl(poss, cmpl_state);
-
-  return poss;
-}
-
-/**********************************************************************/
-/*			 Directory Operations                         */
-/**********************************************************************/
-
-/* Open the directory where completion will begin from, if possible. */
-static CompletionDir*
-open_ref_dir(gchar* text_to_complete,
-	     gchar** remaining_text,
-	     CompletionState* cmpl_state)
-{
-  gchar* first_slash;
-  CompletionDir *new_dir;
-
-  first_slash = strchr(text_to_complete, '/');
-
-  if (text_to_complete[0] == '~')
-    {
-      new_dir = open_user_dir(text_to_complete, cmpl_state);
-
-      if(new_dir)
-	{
-	  if(first_slash)
-	    *remaining_text = first_slash + 1;
-	  else
-	    *remaining_text = text_to_complete + strlen(text_to_complete);
-	}
-      else
-	{
-	  return NULL;
-	}
-    }
-  else if (text_to_complete[0] == '/' || !cmpl_state->reference_dir)
-    {
-      gchar *tmp = g_strdup(text_to_complete);
-      gchar *p;
-
-      p = tmp;
-      while (*p && *p != '*' && *p != '?')
-	p++;
-
-      *p = '\0';
-      p = strrchr(tmp, '/');
-      if (p)
-	{
-	  if (p == tmp)
-	    p++;
-      
-	  *p = '\0';
-
-	  new_dir = open_dir(tmp, cmpl_state);
-
-	  if(new_dir)
-	    *remaining_text = text_to_complete + 
-	      ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
-	}
-      else
-	{
-	  /* If no possible candidates, use the cwd */
-	  gchar *curdir = g_get_current_dir ();
-	  
-	  new_dir = open_dir(curdir, cmpl_state);
-
-	  if (new_dir)
-	    *remaining_text = text_to_complete;
-
-	  g_free (curdir);
-	}
-
-      g_free (tmp);
-    }
-  else
-    {
-      *remaining_text = text_to_complete;
-
-      new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state);
-    }
-
-  if(new_dir)
-    {
-      new_dir->cmpl_index = -1;
-      new_dir->cmpl_parent = NULL;
-    }
-
-  return new_dir;
-}
-
-/* open a directory by user name */
-static CompletionDir*
-open_user_dir(gchar* text_to_complete,
-	      CompletionState *cmpl_state)
-{
-  gchar *first_slash;
-  gint cmp_len;
-
-  g_assert(text_to_complete && text_to_complete[0] == '~');
-
-  first_slash = strchr(text_to_complete, '/');
-
-  if (first_slash)
-    cmp_len = first_slash - text_to_complete - 1;
-  else
-    cmp_len = strlen(text_to_complete + 1);
-
-  if(!cmp_len)
-    {
-      /* ~/ */
-      gchar *homedir = g_get_home_dir ();
-
-      if (homedir)
-	return open_dir(homedir, cmpl_state);
-      else
-	return NULL;
-    }
-  else
-    {
-      /* ~user/ */
-      char* copy = g_new(char, cmp_len + 1);
-      struct passwd *pwd;
-      strncpy(copy, text_to_complete + 1, cmp_len);
-      copy[cmp_len] = 0;
-      pwd = getpwnam(copy);
-      g_free(copy);
-      if (!pwd)
-	{
-	  cmpl_errno = errno;
-	  return NULL;
-	}
-
-      return open_dir(pwd->pw_dir, cmpl_state);
-    }
-}
-
-/* open a directory relative the the current relative directory */
-static CompletionDir*
-open_relative_dir(gchar* dir_name,
-		  CompletionDir* dir,
-		  CompletionState *cmpl_state)
-{
-  gchar path_buf[2*MAXPATHLEN];
-
-  if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN)
-    {
-      cmpl_errno = CMPL_ERRNO_TOO_LONG;
-      return NULL;
-    }
-
-  strcpy(path_buf, dir->fullname);
-
-  if(dir->fullname_len > 1)
-    {
-      path_buf[dir->fullname_len] = '/';
-      strcpy(path_buf + dir->fullname_len + 1, dir_name);
-    }
-  else
-    {
-      strcpy(path_buf + dir->fullname_len, dir_name);
-    }
-
-  return open_dir(path_buf, cmpl_state);
-}
-
-/* after the cache lookup fails, really open a new directory */
-static CompletionDirSent*
-open_new_dir(gchar* dir_name, struct stat* sbuf, gboolean stat_subdirs)
-{
-  CompletionDirSent* sent;
-  DIR* directory;
-  gchar *buffer_ptr;
-  struct dirent *dirent_ptr;
-  gint buffer_size = 0;
-  gint entry_count = 0;
-  gint i;
-  struct stat ent_sbuf;
-  char path_buf[MAXPATHLEN*2];
-  gint path_buf_len;
-
-  sent = g_new(CompletionDirSent, 1);
-  sent->mtime = sbuf->st_mtime;
-  sent->inode = sbuf->st_ino;
-  sent->device = sbuf->st_dev;
-
-  path_buf_len = strlen(dir_name);
-
-  if (path_buf_len > MAXPATHLEN)
-    {
-      cmpl_errno = CMPL_ERRNO_TOO_LONG;
-      return NULL;
-    }
-
-  strcpy(path_buf, dir_name);
-
-  directory = opendir(dir_name);
-
-  if(!directory)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  while((dirent_ptr = readdir(directory)) != NULL)
-    {
-      int entry_len = strlen(dirent_ptr->d_name);
-      buffer_size += entry_len + 1;
-      entry_count += 1;
-
-      if(path_buf_len + entry_len + 2 >= MAXPATHLEN)
-	{
-	  cmpl_errno = CMPL_ERRNO_TOO_LONG;
- 	  closedir(directory);
-	  return NULL;
-	}
-    }
-
-  sent->name_buffer = g_new(gchar, buffer_size);
-  sent->entries = g_new(CompletionDirEntry, entry_count);
-  sent->entry_count = entry_count;
-
-  buffer_ptr = sent->name_buffer;
-
-  rewinddir(directory);
-
-  for(i = 0; i < entry_count; i += 1)
-    {
-      dirent_ptr = readdir(directory);
-
-      if(!dirent_ptr)
-	{
-	  cmpl_errno = errno;
-	  closedir(directory);
-	  return NULL;
-	}
-
-      strcpy(buffer_ptr, dirent_ptr->d_name);
-      sent->entries[i].entry_name = buffer_ptr;
-      buffer_ptr += strlen(dirent_ptr->d_name);
-      *buffer_ptr = 0;
-      buffer_ptr += 1;
-
-      path_buf[path_buf_len] = '/';
-      strcpy(path_buf + path_buf_len + 1, dirent_ptr->d_name);
-
-      if (stat_subdirs)
-	{
-	  if(stat(path_buf, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
-	    sent->entries[i].is_dir = 1;
-	  else
-	    /* stat may fail, and we don't mind, since it could be a
-	     * dangling symlink. */
-	    sent->entries[i].is_dir = 0;
-	}
-      else
-	sent->entries[i].is_dir = 1;
-    }
-
-  qsort(sent->entries, sent->entry_count, sizeof(CompletionDirEntry), compare_cmpl_dir);
-
-  closedir(directory);
-
-  return sent;
-}
-
-static gboolean
-check_dir(gchar *dir_name, struct stat *result, gboolean *stat_subdirs)
-{
-  /* A list of directories that we know only contain other directories.
-   * Trying to stat every file in these directories would be very
-   * expensive.
-   */
-
-  static struct {
-    gchar *name;
-    gboolean present;
-    struct stat statbuf;
-  } no_stat_dirs[] = {
-    { "/afs", FALSE, { 0 } },
-    { "/net", FALSE, { 0 } }
-  };
-
-  static const gint n_no_stat_dirs = sizeof(no_stat_dirs) / sizeof(no_stat_dirs[0]);
-  static gboolean initialized = FALSE;
-
-  gint i;
-
-  if (!initialized)
-    {
-      initialized = TRUE;
-      for (i = 0; i < n_no_stat_dirs; i++)
-	{
-	  if (stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
-	    no_stat_dirs[i].present = TRUE;
-	}
-    }
-
-  if(stat(dir_name, result) < 0)
-    {
-      cmpl_errno = errno;
-      return FALSE;
-    }
-
-  *stat_subdirs = TRUE;
-  for (i=0; i<n_no_stat_dirs; i++)
-    {
-      if (no_stat_dirs[i].present &&
-	  (no_stat_dirs[i].statbuf.st_dev == result->st_dev) &&
-	  (no_stat_dirs[i].statbuf.st_ino == result->st_ino))
-	{
-	  *stat_subdirs = FALSE;
-	  break;
-	}
-    }
-
-  return TRUE;
-}
-
-/* open a directory by absolute pathname */
-static CompletionDir*
-open_dir(gchar* dir_name, CompletionState* cmpl_state)
-{
-  struct stat sbuf;
-  gboolean stat_subdirs;
-  CompletionDirSent *sent;
-  GList* cdsl;
-
-  if (!check_dir (dir_name, &sbuf, &stat_subdirs))
-    return NULL;
-
-  cdsl = cmpl_state->directory_sent_storage;
-
-  while (cdsl)
-    {
-      sent = cdsl->data;
-
-      if(sent->inode == sbuf.st_ino &&
-	 sent->mtime == sbuf.st_mtime &&
-	 sent->device == sbuf.st_dev)
-	return attach_dir(sent, dir_name, cmpl_state);
-
-      cdsl = cdsl->next;
-    }
-
-  sent = open_new_dir(dir_name, &sbuf, stat_subdirs);
-
-  if (sent) {
-    cmpl_state->directory_sent_storage =
-      g_list_prepend(cmpl_state->directory_sent_storage, sent);
-
-    return attach_dir(sent, dir_name, cmpl_state);
-  }
-
-  return NULL;
-}
-
-static CompletionDir*
-attach_dir(CompletionDirSent* sent, gchar* dir_name, CompletionState *cmpl_state)
-{
-  CompletionDir* new_dir;
-
-  new_dir = g_new(CompletionDir, 1);
-
-  cmpl_state->directory_storage =
-    g_list_prepend(cmpl_state->directory_storage, new_dir);
-
-  new_dir->sent = sent;
-  new_dir->fullname = g_strdup(dir_name);
-  new_dir->fullname_len = strlen(dir_name);
-
-  return new_dir;
-}
-
-static gint
-correct_dir_fullname(CompletionDir* cmpl_dir)
-{
-  gint length = strlen(cmpl_dir->fullname);
-  struct stat sbuf;
-
-  if (strcmp(cmpl_dir->fullname + length - 2, "/.") == 0)
-    {
-      if (length == 2) 
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	} else {
-	  cmpl_dir->fullname[length - 2] = 0;
-	}
-    }
-  else if (strcmp(cmpl_dir->fullname + length - 3, "/./") == 0)
-    cmpl_dir->fullname[length - 2] = 0;
-  else if (strcmp(cmpl_dir->fullname + length - 3, "/..") == 0)
-    {
-      if(length == 3)
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	}
-
-      if(stat(cmpl_dir->fullname, &sbuf) < 0)
-	{
-	  cmpl_errno = errno;
-	  return FALSE;
-	}
-
-      cmpl_dir->fullname[length - 2] = 0;
-
-      if(!correct_parent(cmpl_dir, &sbuf))
-	return FALSE;
-    }
-  else if (strcmp(cmpl_dir->fullname + length - 4, "/../") == 0)
-    {
-      if(length == 4)
-	{
-	  strcpy(cmpl_dir->fullname, "/");
-	  cmpl_dir->fullname_len = 1;
-	  return TRUE;
-	}
-
-      if(stat(cmpl_dir->fullname, &sbuf) < 0)
-	{
-	  cmpl_errno = errno;
-	  return FALSE;
-	}
-
-      cmpl_dir->fullname[length - 3] = 0;
-
-      if(!correct_parent(cmpl_dir, &sbuf))
-	return FALSE;
-    }
-
-  cmpl_dir->fullname_len = strlen(cmpl_dir->fullname);
-
-  return TRUE;
-}
-
-static gint
-correct_parent(CompletionDir* cmpl_dir, struct stat *sbuf)
-{
-  struct stat parbuf;
-  gchar *last_slash;
-  gchar *new_name;
-  gchar c = 0;
-
-  last_slash = strrchr(cmpl_dir->fullname, '/');
-
-  g_assert(last_slash);
-
-  if(last_slash != cmpl_dir->fullname)
-    { /* last_slash[0] = 0; */ }
-  else
-    {
-      c = last_slash[1];
-      last_slash[1] = 0;
-    }
-
-  if (stat(cmpl_dir->fullname, &parbuf) < 0)
-    {
-      cmpl_errno = errno;
-      return FALSE;
-    }
-
-  if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
-    /* it wasn't a link */
-    return TRUE;
-
-  if(c)
-    last_slash[1] = c;
-  /* else
-    last_slash[0] = '/'; */
-
-  /* it was a link, have to figure it out the hard way */
-
-  new_name = find_parent_dir_fullname(cmpl_dir->fullname);
-
-  if (!new_name)
-    return FALSE;
-
-  g_free(cmpl_dir->fullname);
-
-  cmpl_dir->fullname = new_name;
-
-  return TRUE;
-}
-
-static gchar*
-find_parent_dir_fullname(gchar* dirname)
-{
-  gchar buffer[MAXPATHLEN];
-  gchar buffer2[MAXPATHLEN];
-
-#if defined(sun) && !defined(__SVR4)
-  if(!getwd(buffer))
-#else
-  if(!getcwd(buffer, MAXPATHLEN))
-#endif    
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  if(chdir(dirname) != 0 || chdir("..") != 0)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-#if defined(sun) && !defined(__SVR4)
-  if(!getwd(buffer2))
-#else
-  if(!getcwd(buffer2, MAXPATHLEN))
-#endif
-    {
-      chdir(buffer);
-      cmpl_errno = errno;
-
-      return NULL;
-    }
-
-  if(chdir(buffer) != 0)
-    {
-      cmpl_errno = errno;
-      return NULL;
-    }
-
-  return g_strdup(buffer2);
-}
-
-/**********************************************************************/
-/*                        Completion Operations                       */
-/**********************************************************************/
-
-static PossibleCompletion*
-attempt_homedir_completion(gchar* text_to_complete,
-			   CompletionState *cmpl_state)
-{
-  gint index, length;
-
-  if (!cmpl_state->user_dir_name_buffer &&
-      !get_pwdb(cmpl_state))
-    return NULL;
-  length = strlen(text_to_complete) - 1;
-
-  cmpl_state->user_completion_index += 1;
-
-  while(cmpl_state->user_completion_index < cmpl_state->user_directories_len)
-    {
-      index = first_diff_index(text_to_complete + 1,
-			       cmpl_state->user_directories
-			       [cmpl_state->user_completion_index].login);
-
-      switch(index)
-	{
-	case PATTERN_MATCH:
-	  break;
-	default:
-	  if(cmpl_state->last_valid_char < (index + 1))
-	    cmpl_state->last_valid_char = index + 1;
-	  cmpl_state->user_completion_index += 1;
-	  continue;
-	}
-
-      cmpl_state->the_completion.is_a_completion = 1;
-      cmpl_state->the_completion.is_directory = 1;
-
-      append_completion_text("~", cmpl_state);
-
-      append_completion_text(cmpl_state->
-			      user_directories[cmpl_state->user_completion_index].login,
-			     cmpl_state);
-
-      return append_completion_text("/", cmpl_state);
-    }
-
-  if(text_to_complete[1] ||
-     cmpl_state->user_completion_index > cmpl_state->user_directories_len)
-    {
-      cmpl_state->user_completion_index = -1;
-      return NULL;
-    }
-  else
-    {
-      cmpl_state->user_completion_index += 1;
-      cmpl_state->the_completion.is_a_completion = 1;
-      cmpl_state->the_completion.is_directory = 1;
-
-      return append_completion_text("~/", cmpl_state);
-    }
-}
-
-/* returns the index (>= 0) of the first differing character,
- * PATTERN_MATCH if the completion matches */
-static gint
-first_diff_index(gchar* pat, gchar* text)
-{
-  gint diff = 0;
-
-  while(*pat && *text && *text == *pat)
-    {
-      pat += 1;
-      text += 1;
-      diff += 1;
-    }
-
-  if(*pat)
-    return diff;
-
-  return PATTERN_MATCH;
-}
-
-static PossibleCompletion*
-append_completion_text(gchar* text, CompletionState* cmpl_state)
-{
-  gint len, i = 1;
-
-  if(!cmpl_state->the_completion.text)
-    return NULL;
-
-  len = strlen(text) + strlen(cmpl_state->the_completion.text) + 1;
-
-  if(cmpl_state->the_completion.text_alloc > len)
-    {
-      strcat(cmpl_state->the_completion.text, text);
-      return &cmpl_state->the_completion;
-    }
-
-  while(i < len) { i <<= 1; }
-
-  cmpl_state->the_completion.text_alloc = i;
-
-  cmpl_state->the_completion.text = (gchar*)g_realloc(cmpl_state->the_completion.text, i);
-
-  if(!cmpl_state->the_completion.text)
-    return NULL;
-  else
-    {
-      strcat(cmpl_state->the_completion.text, text);
-      return &cmpl_state->the_completion;
-    }
-}
-
-static CompletionDir*
-find_completion_dir(gchar* text_to_complete,
-		    gchar** remaining_text,
-		    CompletionState* cmpl_state)
-{
-  gchar* first_slash = strchr(text_to_complete, '/');
-  CompletionDir* dir = cmpl_state->reference_dir;
-  CompletionDir* next;
-  *remaining_text = text_to_complete;
-
-  while(first_slash)
-    {
-      gint len = first_slash - *remaining_text;
-      gint found = 0;
-      gchar *found_name = NULL;         /* Quiet gcc */
-      gint i;
-      gchar* pat_buf = g_new (gchar, len + 1);
-
-      strncpy(pat_buf, *remaining_text, len);
-      pat_buf[len] = 0;
-
-      for(i = 0; i < dir->sent->entry_count; i += 1)
-	{
-	  if(dir->sent->entries[i].is_dir &&
-	     fnmatch(pat_buf, dir->sent->entries[i].entry_name,
-		     FNMATCH_FLAGS)!= FNM_NOMATCH)
-	    {
-	      if(found)
-		{
-		  g_free (pat_buf);
-		  return dir;
-		}
-	      else
-		{
-		  found = 1;
-		  found_name = dir->sent->entries[i].entry_name;
-		}
-	    }
-	}
-
-      if (!found)
-	{
-	  /* Perhaps we are trying to open an automount directory */
-	  found_name = pat_buf;
-	}
-
-      next = open_relative_dir(found_name, dir, cmpl_state);
-      
-      if(!next)
-	{
-	  g_free (pat_buf);
-	  return NULL;
-	}
-      
-      next->cmpl_parent = dir;
-      
-      dir = next;
-      
-      if(!correct_dir_fullname(dir))
-	{
-	  g_free(pat_buf);
-	  return NULL;
-	}
-      
-      *remaining_text = first_slash + 1;
-      first_slash = strchr(*remaining_text, '/');
-
-      g_free (pat_buf);
-    }
-
-  return dir;
-}
-
-static void
-update_cmpl(PossibleCompletion* poss, CompletionState* cmpl_state)
-{
-  gint cmpl_len;
-
-  if(!poss || !cmpl_is_a_completion(poss))
-    return;
-
-  cmpl_len = strlen(cmpl_this_completion(poss));
-
-  if(cmpl_state->updated_text_alloc < cmpl_len + 1)
-    {
-      cmpl_state->updated_text =
-	(gchar*)g_realloc(cmpl_state->updated_text,
-			  cmpl_state->updated_text_alloc);
-      cmpl_state->updated_text_alloc = 2*cmpl_len;
-    }
-
-  if(cmpl_state->updated_text_len < 0)
-    {
-      strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
-      cmpl_state->updated_text_len = cmpl_len;
-      cmpl_state->re_complete = cmpl_is_directory(poss);
-    }
-  else if(cmpl_state->updated_text_len == 0)
-    {
-      cmpl_state->re_complete = FALSE;
-    }
-  else
-    {
-      gint first_diff =
-	first_diff_index(cmpl_state->updated_text,
-			 cmpl_this_completion(poss));
-
-      cmpl_state->re_complete = FALSE;
-
-      if(first_diff == PATTERN_MATCH)
-	return;
-
-      if(first_diff > cmpl_state->updated_text_len)
-	strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
-
-      cmpl_state->updated_text_len = first_diff;
-      cmpl_state->updated_text[first_diff] = 0;
-    }
-}
-
-static PossibleCompletion*
-attempt_file_completion(CompletionState *cmpl_state)
-{
-  gchar *pat_buf, *first_slash;
-  CompletionDir *dir = cmpl_state->active_completion_dir;
-
-  dir->cmpl_index += 1;
-
-  if(dir->cmpl_index == dir->sent->entry_count)
-    {
-      if(dir->cmpl_parent == NULL)
-	{
-	  cmpl_state->active_completion_dir = NULL;
-
-	  return NULL;
-	}
-      else
-	{
-	  cmpl_state->active_completion_dir = dir->cmpl_parent;
-
-	  return attempt_file_completion(cmpl_state);
-	}
-    }
-
-  g_assert(dir->cmpl_text);
-
-  first_slash = strchr(dir->cmpl_text, '/');
-
-  if(first_slash)
-    {
-      gint len = first_slash - dir->cmpl_text;
-
-      pat_buf = g_new (gchar, len + 1);
-      strncpy(pat_buf, dir->cmpl_text, len);
-      pat_buf[len] = 0;
-    }
-  else
-    {
-      gint len = strlen(dir->cmpl_text);
-
-      pat_buf = g_new (gchar, len + 2);
-      strcpy(pat_buf, dir->cmpl_text);
-      strcpy(pat_buf + len, "*");
-    }
-
-  if(first_slash)
-    {
-      if(dir->sent->entries[dir->cmpl_index].is_dir)
-	{
-	  if(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
-		     FNMATCH_FLAGS) != FNM_NOMATCH)
-	    {
-	      CompletionDir* new_dir;
-
-	      new_dir = open_relative_dir(dir->sent->entries[dir->cmpl_index].entry_name,
-					  dir, cmpl_state);
-
-	      if(!new_dir)
-		{
-		  g_free (pat_buf);
-		  return NULL;
-		}
-
-	      new_dir->cmpl_parent = dir;
-
-	      new_dir->cmpl_index = -1;
-	      new_dir->cmpl_text = first_slash + 1;
-
-	      cmpl_state->active_completion_dir = new_dir;
-
-	      g_free (pat_buf);
-	      return attempt_file_completion(cmpl_state);
-	    }
-	  else
-	    {
-	      g_free (pat_buf);
-	      return attempt_file_completion(cmpl_state);
-	    }
-	}
-      else
-	{
-	  g_free (pat_buf);
-	  return attempt_file_completion(cmpl_state);
-	}
-    }
-  else
-    {
-      if(dir->cmpl_parent != NULL)
-	{
-	  append_completion_text(dir->fullname +
-				 strlen(cmpl_state->completion_dir->fullname) + 1,
-				 cmpl_state);
-	  append_completion_text("/", cmpl_state);
-	}
-
-      append_completion_text(dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
-
-      cmpl_state->the_completion.is_a_completion =
-	(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
-		 FNMATCH_FLAGS) != FNM_NOMATCH);
-
-      cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
-      if(dir->sent->entries[dir->cmpl_index].is_dir)
-	append_completion_text("/", cmpl_state);
-
-      g_free (pat_buf);
-      return &cmpl_state->the_completion;
-    }
-}
-
-
-static gint
-get_pwdb(CompletionState* cmpl_state)
-{
-  struct passwd *pwd_ptr;
-  gchar* buf_ptr;
-  gint len = 0, i, count = 0;
-
-  if(cmpl_state->user_dir_name_buffer)
-    return TRUE;
-  setpwent ();
-
-  while ((pwd_ptr = getpwent()) != NULL)
-    {
-      len += strlen(pwd_ptr->pw_name);
-      len += strlen(pwd_ptr->pw_dir);
-      len += 2;
-      count += 1;
-    }
-
-  setpwent ();
-
-  cmpl_state->user_dir_name_buffer = g_new(gchar, len);
-  cmpl_state->user_directories = g_new(CompletionUserDir, count);
-  cmpl_state->user_directories_len = count;
-
-  buf_ptr = cmpl_state->user_dir_name_buffer;
-
-  for(i = 0; i < count; i += 1)
-    {
-      pwd_ptr = getpwent();
-      if(!pwd_ptr)
-	{
-	  cmpl_errno = errno;
-	  goto error;
-	}
-
-      strcpy(buf_ptr, pwd_ptr->pw_name);
-      cmpl_state->user_directories[i].login = buf_ptr;
-      buf_ptr += strlen(buf_ptr);
-      buf_ptr += 1;
-      strcpy(buf_ptr, pwd_ptr->pw_dir);
-      cmpl_state->user_directories[i].homedir = buf_ptr;
-      buf_ptr += strlen(buf_ptr);
-      buf_ptr += 1;
-    }
-
-  qsort(cmpl_state->user_directories,
-	cmpl_state->user_directories_len,
-	sizeof(CompletionUserDir),
-	compare_user_dir);
-
-  endpwent();
-
-  return TRUE;
-
-error:
-
-  if(cmpl_state->user_dir_name_buffer)
-    g_free(cmpl_state->user_dir_name_buffer);
-  if(cmpl_state->user_directories)
-    g_free(cmpl_state->user_directories);
-
-  cmpl_state->user_dir_name_buffer = NULL;
-  cmpl_state->user_directories = NULL;
-
-  return FALSE;
-}
-
-static gint
-compare_user_dir(const void* a, const void* b)
-{
-  return strcmp((((CompletionUserDir*)a))->login,
-		(((CompletionUserDir*)b))->login);
-}
-
-static gint
-compare_cmpl_dir(const void* a, const void* b)
-{
-  return strcmp((((CompletionDirEntry*)a))->entry_name,
-		(((CompletionDirEntry*)b))->entry_name);
-}
-
-static gint
-cmpl_state_okay(CompletionState* cmpl_state)
-{
-  return  cmpl_state && cmpl_state->reference_dir;
-}
-
-static gchar*
-cmpl_strerror(gint err)
-{
-  if(err == CMPL_ERRNO_TOO_LONG)
-    return "Name too long";
-  else
-    return g_strerror (err);
-}
-
-
-/* Testing area */
-#ifdef TORRIE_DEBUG
-
-/* Get the selected filename and print it to the console */
-void file_ok_sel( GtkWidget        *w,
-                  GtkFileSelection *fs )
-{
-    g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
-}
-
-void destroy( GtkWidget *widget,
-              gpointer   data )
-{
-    gtk_main_quit ();
-}
-
-int main( int   argc,
-          char *argv[] )
-{
-    GtkWidget *filew;
-
-    gtk_init (&argc, &argv);
-
-    /* Create a new file selection widget */
-    filew = gtk_file_selection_new ("Michael's Glorious File Selector");
-//    gtk_file_selection_complete(GTK_FILE_SELECTION(filew),"bob");
-
-		
-    gtk_signal_connect (GTK_OBJECT (filew), "destroy",
-			(GtkSignalFunc) destroy, &filew);
-    /* Connect the ok_button to file_ok_sel function */
-    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
-			"clicked", (GtkSignalFunc) file_ok_sel, filew );
-
-    /* Connect the cancel_button to destroy the widget */
-    gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
-                                            (filew)->cancel_button),
-			       "clicked", (GtkSignalFunc) gtk_widget_destroy,
-			       GTK_OBJECT (filew));
-
-
-    gtk_widget_show(filew);
-
-/*
-    g_print("%d",gtk_file_selection_match_mask("mask.c","m*.c"));
-    g_print("%d",gtk_file_selection_match_mask("mask.c","m???.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.c","m??*.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c???"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c*"));
-		g_print("%d",gtk_file_selection_match_mask("mask.cout","n*.c???"));
-		g_print("%d",gtk_file_selection_match_mask("mask.c","[mn]*"));
-		g_print("%d",gtk_file_selection_match_mask("COPYING","*.xpm"));
-*/	
-    gtk_main ();
-
-    return 0;
-}
-/* example-end */
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+
+// leo FIXME: if we keep this file then we'll need to ask permission to the author, this is LGPL
+// This file is from the Advanced File Selector widget 
+// by Michael Torrie  <torriem@byu.edu>
+// http://students.cs.byu.edu/~torriem/gtk/
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <dirent.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <pwd.h>
+#include "fnmatch.h"
+
+// leo: added "gtk/"
+#include "gdk/gdkkeysyms.h"
+#include "gtk/gtkbutton.h"
+#include "gtk/gtkentry.h"
+#include "gtkfilesel.h"
+#include "gtk/gtkhbox.h"
+#include "gtk/gtkhbbox.h"
+#include "gtk/gtklabel.h"
+#include "gtk/gtklist.h"
+#include "gtk/gtklistitem.h"
+#include "gtk/gtkmain.h"
+#include "gtk/gtkscrolledwindow.h"
+#include "gtk/gtksignal.h"
+#include "gtk/gtkvbox.h"
+#include "gtk/gtkmenu.h"
+#include "gtk/gtkmenuitem.h"
+#include "gtk/gtkoptionmenu.h"
+#include "gtk/gtkclist.h"
+#include "gtk/gtkdialog.h"
+#include "gtk/gtkcombo.h"
+#include "gtk/gtkframe.h"
+
+// leo: disable NLS
+//#include "gtk/gtkintl.h"
+#define _(String) (String)
+
+#define DIR_LIST_WIDTH   180
+#define DIR_LIST_HEIGHT  180
+#define FILE_LIST_WIDTH  180
+#define FILE_LIST_HEIGHT 180
+
+/* I've put this here so it doesn't get confused with the 
+ * file completion interface */
+typedef struct _HistoryCallbackArg HistoryCallbackArg;
+
+struct _HistoryCallbackArg
+{
+  gchar *directory;
+  GtkWidget *menu_item;
+};
+
+
+typedef struct _CompletionState    CompletionState;
+typedef struct _CompletionDir      CompletionDir;
+typedef struct _CompletionDirSent  CompletionDirSent;
+typedef struct _CompletionDirEntry CompletionDirEntry;
+typedef struct _CompletionUserDir  CompletionUserDir;
+typedef struct _PossibleCompletion PossibleCompletion;
+
+/* Non-external file completion decls and structures */
+
+/* A contant telling PRCS how many directories to cache.  Its actually
+ * kept in a list, so the geometry isn't important. */
+#define CMPL_DIRECTORY_CACHE_SIZE 10
+
+/* A constant used to determine whether a substring was an exact
+ * match by first_diff_index()
+ */
+#define PATTERN_MATCH -1
+/* The arguments used by all fnmatch() calls below
+ */
+#define FNMATCH_FLAGS (FNM_PATHNAME | FNM_PERIOD)
+
+#define CMPL_ERRNO_TOO_LONG ((1<<16)-1)
+
+/* This structure contains all the useful information about a directory
+ * for the purposes of filename completion.  These structures are cached
+ * in the CompletionState struct.  CompletionDir's are reference counted.
+ */
+struct _CompletionDirSent
+{
+  ino_t inode;
+  time_t mtime;
+  dev_t device;
+
+  gint entry_count;
+  gchar *name_buffer; /* memory segment containing names of all entries */
+
+  struct _CompletionDirEntry *entries;
+};
+
+struct _CompletionDir
+{
+  CompletionDirSent *sent;
+
+  gchar *fullname;
+  gint fullname_len;
+
+  struct _CompletionDir *cmpl_parent;
+  gint cmpl_index;
+  gchar *cmpl_text;
+};
+
+/* This structure contains pairs of directory entry names with a flag saying
+ * whether or not they are a valid directory.  NOTE: This information is used
+ * to provide the caller with information about whether to update its completions
+ * or try to open a file.  Since directories are cached by the directory mtime,
+ * a symlink which points to an invalid file (which will not be a directory),
+ * will not be reevaluated if that file is created, unless the containing
+ * directory is touched.  I consider this case to be worth ignoring (josh).
+ */
+struct _CompletionDirEntry
+{
+  gint is_dir;
+  gchar *entry_name;
+};
+
+struct _CompletionUserDir
+{
+  gchar *login;
+  gchar *homedir;
+};
+
+struct _PossibleCompletion
+{
+  /* accessible fields, all are accessed externally by functions
+   * declared above
+   */
+  gchar *text;
+  gint is_a_completion;
+  gint is_directory;
+
+  gint file_size;
+  gint file_time;
+  gint uid;
+  gint gid;
+  /* Private fields
+   */
+  gint text_alloc;
+};
+
+struct _CompletionState
+{
+  gint last_valid_char;
+  gchar *updated_text;
+  gint updated_text_len;
+  gint updated_text_alloc;
+  gint re_complete;
+
+  gchar *user_dir_name_buffer;
+  gint user_directories_len;
+
+  gchar *last_completion_text;
+
+  gint user_completion_index; /* if >= 0, currently completing ~user */
+
+  struct _CompletionDir *completion_dir; /* directory completing from */
+  struct _CompletionDir *active_completion_dir;
+
+  struct _PossibleCompletion the_completion;
+
+  struct _CompletionDir *reference_dir; /* initial directory */
+
+  GList* directory_storage;
+  GList* directory_sent_storage;
+
+  struct _CompletionUserDir *user_directories;
+};
+
+
+/* File completion functions which would be external, were they used
+ * outside of this file.
+ */
+
+static CompletionState*    cmpl_init_state        (void);
+static void                cmpl_free_state        (CompletionState *cmpl_state);
+static gint                cmpl_state_okay        (CompletionState* cmpl_state);
+static gchar*              cmpl_strerror          (gint);
+
+static PossibleCompletion* cmpl_completion_matches(gchar           *text_to_complete,
+						   gchar          **remaining_text,
+						   CompletionState *cmpl_state);
+
+/* Returns a name for consideration, possibly a completion, this name
+ * will be invalid after the next call to cmpl_next_completion.
+ */
+static char*               cmpl_this_completion   (PossibleCompletion*);
+
+/* True if this completion matches the given text.  Otherwise, this
+ * output can be used to have a list of non-completions.
+ */
+static gint                cmpl_is_a_completion   (PossibleCompletion*);
+
+/* True if the completion is a directory
+ */
+static gint                cmpl_is_directory      (PossibleCompletion*);
+
+/* Obtains the next completion, or NULL
+ */
+static PossibleCompletion* cmpl_next_completion   (CompletionState*);
+
+/* Updating completions: the return value of cmpl_updated_text() will
+ * be text_to_complete completed as much as possible after the most
+ * recent call to cmpl_completion_matches.  For the present
+ * application, this is the suggested replacement for the user's input
+ * string.  You must CALL THIS AFTER ALL cmpl_text_completions have
+ * been received.
+ */
+static gchar*              cmpl_updated_text       (CompletionState* cmpl_state);
+
+/* After updating, to see if the completion was a directory, call
+ * this.  If it was, you should consider re-calling completion_matches.
+ */
+static gint                cmpl_updated_dir        (CompletionState* cmpl_state);
+
+/* Current location: if using file completion, return the current
+ * directory, from which file completion begins.  More specifically,
+ * the cwd concatenated with all exact completions up to the last
+ * directory delimiter('/').
+ */
+static gchar*              cmpl_reference_position (CompletionState* cmpl_state);
+
+/* backing up: if cmpl_completion_matches returns NULL, you may query
+ * the index of the last completable character into cmpl_updated_text.
+ */
+static gint                cmpl_last_valid_char    (CompletionState* cmpl_state);
+
+/* When the user selects a non-directory, call cmpl_completion_fullname
+ * to get the full name of the selected file.
+ */
+static gchar*              cmpl_completion_fullname (gchar*, CompletionState* cmpl_state);
+
+
+/* Directory operations. */
+static CompletionDir* open_ref_dir         (gchar* text_to_complete,
+					    gchar** remaining_text,
+					    CompletionState* cmpl_state);
+static gboolean       check_dir            (gchar *dir_name, 
+					    struct stat *result, 
+					    gboolean *stat_subdirs);
+static CompletionDir* open_dir             (gchar* dir_name,
+					    CompletionState* cmpl_state);
+static CompletionDir* open_user_dir        (gchar* text_to_complete,
+					    CompletionState *cmpl_state);
+static CompletionDir* open_relative_dir    (gchar* dir_name, CompletionDir* dir,
+					    CompletionState *cmpl_state);
+static CompletionDirSent* open_new_dir     (gchar* dir_name, 
+					    struct stat* sbuf,
+					    gboolean stat_subdirs);
+static gint           correct_dir_fullname (CompletionDir* cmpl_dir);
+static gint           correct_parent       (CompletionDir* cmpl_dir,
+					    struct stat *sbuf);
+static gchar*         find_parent_dir_fullname    (gchar* dirname);
+static CompletionDir* attach_dir           (CompletionDirSent* sent,
+					    gchar* dir_name,
+					    CompletionState *cmpl_state);
+static void           free_dir_sent (CompletionDirSent* sent);
+static void           free_dir      (CompletionDir  *dir);
+static void           prune_memory_usage(CompletionState *cmpl_state);
+
+/* Completion operations */
+static PossibleCompletion* attempt_homedir_completion(gchar* text_to_complete,
+						      CompletionState *cmpl_state);
+static PossibleCompletion* attempt_file_completion(CompletionState *cmpl_state);
+static CompletionDir* find_completion_dir(gchar* text_to_complete,
+					  gchar** remaining_text,
+					  CompletionState* cmpl_state);
+static PossibleCompletion* append_completion_text(gchar* text,
+						  CompletionState* cmpl_state);
+static gint get_pwdb(CompletionState* cmpl_state);
+static gint first_diff_index(gchar* pat, gchar* text);
+static gint compare_user_dir(const void* a, const void* b);
+static gint compare_cmpl_dir(const void* a, const void* b);
+static void update_cmpl(PossibleCompletion* poss,
+			CompletionState* cmpl_state);
+
+static void gtk_file_selection_class_init    (GtkFileSelectionClass *klass);
+static void gtk_file_selection_init          (GtkFileSelection      *filesel);
+static void gtk_file_selection_destroy       (GtkObject             *object);
+static gint gtk_file_selection_key_press     (GtkWidget             *widget,
+					      GdkEventKey           *event,
+					      gpointer               user_data);
+
+static void gtk_file_selection_file_button (GtkWidget *widget,
+					    gint row, 
+					    gint column, 
+					    GdkEventButton *bevent,
+					    gpointer user_data);
+
+static void gtk_file_selection_dir_button (GtkWidget *widget,
+					   gint row,
+					   gint column,
+					   GdkEventButton *bevent,
+					   gpointer data);
+
+static void gtk_file_selection_undir_button (GtkWidget *widget,
+					     gint row,
+					     gint column,
+					     GdkEventButton *bevent,
+					     gpointer data);
+
+static void gtk_file_selection_populate      (GtkFileSelection      *fs,
+					      gchar                 *rel_path,
+					      gint                   try_complete);
+static void gtk_file_selection_abort         (GtkFileSelection      *fs);
+
+static void gtk_file_selection_update_history_menu (GtkFileSelection       *fs,
+						    gchar                  *current_dir);
+
+static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
+
+static gboolean gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data);
+static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
+																							GdkEventKey *event,
+																							gpointer user_data);
+static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
+																							GdkEventButton *event,
+																							gpointer user_data);
+static void gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_create_dir (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_delete_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_rename_file (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_home_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_up_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_prev_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_next_button (GtkWidget *widget, gpointer data);
+static void gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data);
+
+static gint gtk_file_selection_match_char (gchar, gchar *mask);
+static gint gtk_file_selection_match_mask (gchar *,gchar *);
+
+
+static GtkWindowClass *parent_class = NULL;
+
+/* Saves errno when something cmpl does fails. */
+static gint cmpl_errno;
+
+/* General notes:
+ * Make prev and next inactive if their respective *
+ *   histories are empty.
+ * Add facilities for handling hidden files and    *
+ * directories                                     *
+ * Add an api to access the mask, and hidden files *
+ * check box?  (prob not in 1.2.x series)          *
+ */
+
+/* Routine for applying mask to filenames         *
+ *   Need to be optimized to minimize recursion   *
+ *     help the for loop by looking for the next  *
+ *     instance of the mask character following   *
+ *     the '*'.  ei *.c -- look for '.'           *
+ *     Also, swap all *? pairs (-> ?*), as that   *
+ *     will make it possible to look ahead (?     *
+ *     makes it very nondeterministic as in *?.c  *
+ *     which really is ?*.c                       *
+ *   Allow multiply masks, separted by commas     *
+ *   Allow more flexible [] handling (ie [a-zA-Z] *
+ *                                                *
+ */
+static gint gtk_file_selection_match_char (gchar text, gchar *mask){
+  gchar *maskc;
+  gint x;
+  gint s;
+	
+  if (mask[0] == '[')
+    {
+      if (!strchr (mask,']')) return 0;
+      maskc = g_strdup(mask + 1); /* get the portion of mask inside []*/
+		
+      (*(strchr (maskc,']'))) = 0;
+      s = strlen ((char *)maskc);
+
+      for (x = 0; x < s; x++){
+	if (text == maskc[x])
+	  {
+	    g_free (maskc);
+	    return s + 2;
+	  }
+      }
+      g_free (maskc);
+      return 0;
+    }
+
+  if (mask[0] == '?') return 1;
+  if (mask[0] == text) return 1;
+
+  return 0;
+}
+
+
+static gint gtk_file_selection_match_mask (gchar *text, gchar *mask){
+
+  int mc;
+  int tc;
+
+  tc = 0; mc = 0;
+	
+  if (mask[0] == 0 && text[0] == 0) return 1;
+	
+  if (mask[0] == '*')
+    {
+      for (tc = 0; tc <= strlen(text); tc++)
+	{
+	  if (gtk_file_selection_match_mask (text + tc, mask + 1))
+	    return 1;
+	}
+      return 0;
+    }
+  mc = gtk_file_selection_match_char (text[0], mask);
+
+  if(mc)
+    return gtk_file_selection_match_mask (text + 1, mask + mc);
+  else
+    return 0;
+}
+
+GtkType
+gtk_file_selection_get_type (void)
+{
+  static GtkType file_selection_type = 0;
+
+  if (!file_selection_type)
+    {
+      static const GtkTypeInfo filesel_info =
+      {
+	"GtkFileSelection",
+	sizeof (GtkFileSelection),
+	sizeof (GtkFileSelectionClass),
+	(GtkClassInitFunc) gtk_file_selection_class_init,
+	(GtkObjectInitFunc) gtk_file_selection_init,
+	/* reserved_1 */ NULL,
+	/* reserved_2 */ NULL,
+        (GtkClassInitFunc) NULL,
+      };
+
+      file_selection_type = gtk_type_unique (GTK_TYPE_WINDOW, &filesel_info);
+    }
+
+  return file_selection_type;
+}
+
+static void
+gtk_file_selection_class_init (GtkFileSelectionClass *class)
+{
+  GtkObjectClass *object_class;
+
+  object_class = (GtkObjectClass*) class;
+
+  parent_class = gtk_type_class (GTK_TYPE_WINDOW);
+
+  object_class->destroy = gtk_file_selection_destroy;
+}
+
+static void
+gtk_file_selection_init (GtkFileSelection *filesel)
+{
+  GtkWidget *entry_vbox;
+  GtkWidget *label;
+  GtkWidget *list_hbox;
+  GtkWidget *confirm_area;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  GtkWidget *pulldown_hbox;
+  GtkWidget *scrolled_win;
+  GtkWidget *mask_label;
+  GtkWidget *bigframe;
+  GtkWidget *label_lookingin;
+  GtkWidget *up_button;
+  GtkWidget *home_button;
+  GtkWidget *prev_button;
+  GtkWidget *next_button;
+  GtkWidget *refresh_button;
+
+  char *dir_title [2];
+  char *file_title [2];
+  
+  filesel->cmpl_state = cmpl_init_state ();
+
+  filesel->mask=NULL;
+  filesel->prev_history=NULL;
+  filesel->next_history=NULL;
+  filesel->saved_entry=NULL;
+
+  /* The dialog-sized vertical box  */
+  filesel->main_vbox = gtk_vbox_new (FALSE, 10);
+  gtk_container_set_border_width (GTK_CONTAINER (filesel), 10);
+  gtk_container_add (GTK_CONTAINER (filesel), filesel->main_vbox);
+  gtk_widget_show (filesel->main_vbox);
+
+  /* The horizontal box containing create, rename etc. buttons */
+  filesel->button_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(filesel->button_area), GTK_BUTTONBOX_START);
+  gtk_button_box_set_spacing(GTK_BUTTON_BOX(filesel->button_area), 0);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->button_area, 
+		      FALSE, FALSE, 0);
+  gtk_widget_show (filesel->button_area);
+  
+  gtk_file_selection_show_fileop_buttons(filesel);
+
+  /* hbox for pulldown menu */
+  pulldown_hbox = gtk_hbox_new (FALSE, 5);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), pulldown_hbox, FALSE, FALSE, 0);
+  gtk_widget_show (pulldown_hbox);
+  
+  /* The combo box that replaces the pulldown menu */
+  label_lookingin = gtk_label_new (_("Looking in:"));
+  gtk_widget_show (label_lookingin);
+  gtk_box_pack_start (GTK_BOX (pulldown_hbox), label_lookingin, FALSE, FALSE, 0);
+
+  filesel->history_combo = gtk_combo_new();
+  gtk_widget_show(filesel->history_combo);
+  gtk_combo_set_value_in_list(GTK_COMBO(filesel->history_combo),FALSE,FALSE);
+  gtk_box_pack_start (GTK_BOX(pulldown_hbox),filesel->history_combo,
+  				TRUE,TRUE, 0);
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->entry),"key-press-event",				    
+		     (GtkSignalFunc) gtk_file_selection_history_combo_callback,
+		     (gpointer) filesel);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"button-press-event",
+		     (GtkSignalFunc) gtk_file_selection_history_combo_list_callback,
+		     (gpointer) filesel);
+
+  gtk_signal_connect(GTK_OBJECT(((GtkCombo *)filesel->history_combo)->list),"key-press-event",
+		     (GtkSignalFunc) gtk_file_selection_history_combo_list_key_handler,
+		     (gpointer) filesel);
+
+  /*  frame to put the following hbox in  */
+  bigframe = gtk_frame_new (NULL);
+  gtk_widget_show (bigframe);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), bigframe, TRUE, TRUE, 0);
+
+  /*  The horizontal box containing the directory and file listboxes  */
+  list_hbox = gtk_hbox_new (FALSE, 5);
+  gtk_container_add (GTK_CONTAINER(bigframe), list_hbox);
+  gtk_container_set_border_width (GTK_CONTAINER (list_hbox), 5);
+  gtk_widget_show (list_hbox);
+
+  /* vbox to put the buttons and directory listing in  */
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (vbox);
+  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, FALSE, FALSE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 0);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  home_button = gtk_button_new_with_label (_("Home"));
+  gtk_widget_show (home_button);
+  gtk_signal_connect (GTK_OBJECT (home_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_home_button,
+		      (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox), home_button, TRUE,TRUE, 0);
+
+  prev_button = gtk_button_new_with_label (_("Prev"));
+  gtk_signal_connect (GTK_OBJECT (prev_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_prev_button,
+		      (gpointer) filesel);
+  gtk_widget_show (prev_button);
+  gtk_box_pack_start (GTK_BOX (hbox), prev_button, TRUE,TRUE, 0);
+
+  up_button = gtk_button_new_with_label (_("Up"));
+  gtk_signal_connect (GTK_OBJECT (up_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_up_button,
+		      (gpointer) filesel);
+  gtk_widget_show (up_button);
+  gtk_box_pack_start (GTK_BOX (hbox), up_button, TRUE,TRUE, 0);
+
+  next_button = gtk_button_new_with_label (_("Next"));
+  gtk_widget_show (next_button);
+  gtk_signal_connect (GTK_OBJECT (next_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_next_button,
+		      (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox), next_button, TRUE,TRUE, 0);
+
+  refresh_button = gtk_button_new_with_label (_("Refresh"));
+  gtk_widget_show (refresh_button);
+  gtk_signal_connect (GTK_OBJECT (refresh_button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_refresh_button,
+		      (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox), refresh_button, TRUE, TRUE, 0);
+
+  /* The directories clist */
+  dir_title[0] = _("Directories");
+  dir_title[1] = NULL;
+  filesel->dir_list = gtk_clist_new_with_titles (1, (gchar**) dir_title);
+  gtk_widget_set_usize (filesel->dir_list, DIR_LIST_WIDTH, DIR_LIST_HEIGHT);
+  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "select_row",
+		      (GtkSignalFunc) gtk_file_selection_dir_button,
+		      (gpointer) filesel);
+  gtk_signal_connect (GTK_OBJECT (filesel->dir_list), "unselect_row",
+		      (GtkSignalFunc) gtk_file_selection_undir_button,
+		      (gpointer) filesel);
+  gtk_clist_column_titles_passive (GTK_CLIST (filesel->dir_list));
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->dir_list);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE,TRUE, 5);
+  gtk_widget_show (filesel->dir_list);
+  gtk_widget_show (scrolled_win);
+
+  /* vbox area for mask entry and files clist  */
+  vbox = gtk_vbox_new (FALSE, 0);
+  gtk_widget_show (vbox);
+  gtk_box_pack_start (GTK_BOX (list_hbox), vbox, TRUE, TRUE, 0);
+
+  hbox = gtk_hbox_new (FALSE, 5);
+  gtk_widget_show (hbox);
+  gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
+
+  mask_label = gtk_label_new (_("Mask:"));
+  gtk_widget_show (mask_label);
+  gtk_box_pack_start (GTK_BOX (hbox), mask_label, FALSE, FALSE, 0);
+
+  filesel->mask_entry = gtk_entry_new ();
+  gtk_widget_show (filesel->mask_entry);
+  gtk_signal_connect(GTK_OBJECT(filesel->mask_entry),"activate",
+		     (GtkSignalFunc) gtk_file_selection_mask_entry_callback,
+		     (gpointer) filesel);
+  gtk_box_pack_start (GTK_BOX (hbox),filesel->mask_entry, TRUE, TRUE, 0);
+
+
+  /* The files clist */
+  file_title[0] = _("Files");
+  file_title[1] = NULL;
+  filesel->file_list = gtk_clist_new_with_titles (1, (gchar**) file_title);
+  gtk_widget_set_usize (filesel->file_list, FILE_LIST_WIDTH, FILE_LIST_HEIGHT);
+  gtk_signal_connect (GTK_OBJECT (filesel->file_list), "select_row",
+		      (GtkSignalFunc) gtk_file_selection_file_button, 
+		      (gpointer) filesel);
+  gtk_clist_column_titles_passive (GTK_CLIST (filesel->file_list));
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), filesel->file_list);
+  gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (scrolled_win),
+				  GTK_POLICY_AUTOMATIC, GTK_POLICY_ALWAYS);
+  gtk_box_pack_start (GTK_BOX (vbox), scrolled_win, TRUE, TRUE, 5);
+  gtk_widget_show (filesel->file_list);
+  gtk_widget_show (scrolled_win);
+
+  /* action area for packing buttons into. */
+  filesel->action_area = gtk_hbox_new (TRUE, 0);
+  gtk_box_pack_start (GTK_BOX (filesel->main_vbox), filesel->action_area, 
+		      FALSE, FALSE, 0);
+  gtk_widget_show (filesel->action_area);
+  
+  /*  The OK/Cancel button area */
+  confirm_area = gtk_hbutton_box_new ();
+  gtk_button_box_set_layout(GTK_BUTTON_BOX(confirm_area), GTK_BUTTONBOX_END);
+  gtk_button_box_set_spacing(GTK_BUTTON_BOX(confirm_area), 5);
+  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), confirm_area, FALSE, FALSE, 0);
+  gtk_widget_show (confirm_area);
+
+  /*  The OK button  */
+  filesel->ok_button = gtk_button_new_with_label (_("OK"));
+  GTK_WIDGET_SET_FLAGS (filesel->ok_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->ok_button, TRUE, TRUE, 0);
+  gtk_widget_grab_default (filesel->ok_button);
+  gtk_widget_show (filesel->ok_button);
+
+  /*  The Cancel button  */
+  filesel->cancel_button = gtk_button_new_with_label (_("Cancel"));
+  GTK_WIDGET_SET_FLAGS (filesel->cancel_button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (confirm_area), filesel->cancel_button, TRUE, TRUE, 0);
+  gtk_widget_show (filesel->cancel_button);
+
+  /*  The selection entry widget  */
+  entry_vbox = gtk_vbox_new (FALSE, 2);
+  gtk_box_pack_end (GTK_BOX (filesel->main_vbox), entry_vbox, FALSE, FALSE, 0);
+  gtk_widget_show (entry_vbox);
+
+  filesel->selection_text = label = gtk_label_new ("");
+  gtk_misc_set_alignment (GTK_MISC (label), 0.0, 0.5);
+  gtk_box_pack_start (GTK_BOX (entry_vbox), label, FALSE, FALSE, 0);
+  gtk_widget_show (label);
+
+  filesel->selection_entry = gtk_entry_new ();
+  gtk_signal_connect (GTK_OBJECT (filesel->selection_entry), "key_press_event",
+		      (GtkSignalFunc) gtk_file_selection_key_press, filesel);
+  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "focus_in_event",
+			     (GtkSignalFunc) gtk_widget_grab_default,
+			     GTK_OBJECT (filesel->ok_button));
+  gtk_signal_connect_object (GTK_OBJECT (filesel->selection_entry), "activate",
+                             (GtkSignalFunc) gtk_button_clicked,
+                             GTK_OBJECT (filesel->ok_button));
+  gtk_box_pack_start (GTK_BOX (entry_vbox), filesel->selection_entry, TRUE, TRUE, 0);
+  gtk_widget_show (filesel->selection_entry);
+
+  if (!cmpl_state_okay (filesel->cmpl_state))
+    {
+      gchar err_buf[256];
+
+      sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
+
+      gtk_label_set_text (GTK_LABEL (filesel->selection_text), err_buf);
+    }
+  else
+    {
+      gtk_file_selection_populate (filesel, "", FALSE);
+    }
+
+  gtk_widget_grab_focus (filesel->selection_entry);
+}
+
+GtkWidget*
+gtk_file_selection_new (const gchar *title)
+{
+  GtkFileSelection *filesel;
+
+  filesel = gtk_type_new (GTK_TYPE_FILE_SELECTION);
+  gtk_window_set_title (GTK_WINDOW (filesel), title);
+
+  return GTK_WIDGET (filesel);
+}
+
+void
+gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+    
+  /* delete, create directory, and rename */
+  if (!filesel->fileop_c_dir) 
+    {
+      filesel->fileop_c_dir = gtk_button_new_with_label (_("Create Dir"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_c_dir), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_create_dir, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_c_dir, TRUE, TRUE, 0);
+      gtk_widget_show (filesel->fileop_c_dir);
+    }
+	
+  if (!filesel->fileop_del_file) 
+    {
+      filesel->fileop_del_file = gtk_button_new_with_label (_("Delete File"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_del_file), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_delete_file, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_del_file, TRUE, TRUE, 0);
+      gtk_widget_show (filesel->fileop_del_file);
+    }
+
+  if (!filesel->fileop_ren_file)
+    {
+      filesel->fileop_ren_file = gtk_button_new_with_label (_("Rename File"));
+      gtk_signal_connect (GTK_OBJECT (filesel->fileop_ren_file), "clicked",
+			  (GtkSignalFunc) gtk_file_selection_rename_file, 
+			  (gpointer) filesel);
+      gtk_box_pack_start (GTK_BOX (filesel->button_area), 
+			  filesel->fileop_ren_file, TRUE, TRUE, 0);
+      gtk_widget_show (filesel->fileop_ren_file);
+    }
+
+  gtk_widget_queue_resize(GTK_WIDGET(filesel));
+}
+
+void       
+gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel)
+{
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+    
+  if (filesel->fileop_ren_file) 
+    {
+      gtk_widget_destroy (filesel->fileop_ren_file);
+      filesel->fileop_ren_file = NULL;
+    }
+
+  if (filesel->fileop_del_file)
+    {
+      gtk_widget_destroy (filesel->fileop_del_file);
+      filesel->fileop_del_file = NULL;
+    }
+
+  if (filesel->fileop_c_dir)
+    {
+      gtk_widget_destroy (filesel->fileop_c_dir);
+      filesel->fileop_c_dir = NULL;
+    }
+}
+
+
+
+void
+gtk_file_selection_set_filename (GtkFileSelection *filesel,
+				 const gchar      *filename)
+{
+  char  buf[MAXPATHLEN];
+  const char *name, *last_slash;
+
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+  g_return_if_fail (filename != NULL);
+
+  last_slash = strrchr (filename, '/');
+
+  if (!last_slash)
+    {
+      buf[0] = 0;
+      name = filename;
+    }
+  else
+    {
+      gint len = MIN (MAXPATHLEN - 1, last_slash - filename + 1);
+
+      strncpy (buf, filename, len);
+      buf[len] = 0;
+
+      name = last_slash + 1;
+    }
+
+  gtk_file_selection_populate (filesel, buf, FALSE);
+
+  if (filesel->selection_entry)
+    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), name);
+}
+
+gchar*
+gtk_file_selection_get_filename (GtkFileSelection *filesel)
+{
+  static char nothing[2] = "";
+  char *text;
+  char *filename;
+
+  g_return_val_if_fail (filesel != NULL, nothing);
+  g_return_val_if_fail (GTK_IS_FILE_SELECTION (filesel), nothing);
+
+  text = gtk_entry_get_text (GTK_ENTRY (filesel->selection_entry));
+  if (text)
+    {
+      filename = cmpl_completion_fullname (text, filesel->cmpl_state);
+      return filename;
+    }
+
+  return nothing;
+}
+
+void
+gtk_file_selection_complete (GtkFileSelection *filesel,
+			     const gchar      *pattern)
+{
+  gchar *new_pattern;
+  gint x;
+	
+  g_return_if_fail (filesel != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (filesel));
+  g_return_if_fail (pattern != NULL);
+
+  if (filesel->selection_entry)
+    gtk_entry_set_text (GTK_ENTRY (filesel->selection_entry), pattern);
+	
+  if(strchr(pattern,'*') || strchr(pattern,'?'))
+    {
+      for(x=strlen(pattern);x>=0;x--)
+	{
+	  if(pattern[x]=='/') break;
+	}
+      gtk_entry_set_text(GTK_ENTRY(filesel->mask_entry),g_strdup(pattern+x+1));
+      
+      if(filesel->mask) g_free(filesel->mask);
+      
+      filesel->mask=g_strdup(pattern+x+1);
+      new_pattern=g_strdup(pattern);
+      new_pattern[x+1]=0;
+      gtk_file_selection_populate (filesel, (gchar*) new_pattern, TRUE);
+      g_free(new_pattern);
+    }
+  else
+    {
+      gtk_file_selection_populate (filesel, (gchar*) pattern, TRUE);
+    }
+}
+
+static void
+gtk_file_selection_destroy (GtkObject *object)
+{
+  GtkFileSelection *filesel;
+  GList *list;
+
+  g_return_if_fail (object != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (object));
+
+  filesel = GTK_FILE_SELECTION (object);
+  
+  if (filesel->fileop_dialog)
+    gtk_widget_destroy (filesel->fileop_dialog);
+  
+  if (filesel->next_history)
+    {
+      list = filesel->next_history;
+      while (list)
+  	{
+	  g_free (list->data);
+	  list = list->next;
+  	}
+    }
+  g_list_free (filesel->next_history);
+  filesel->next_history = NULL;
+
+  if (filesel->prev_history)
+    {
+      list = filesel->prev_history;
+      while (list)
+  	{
+	  g_free (list->data);
+	  list = list->next;
+  	}
+    }
+  g_list_free (filesel->prev_history);
+  filesel->prev_history = NULL;
+
+  if (filesel->mask)
+    {
+      g_free (filesel->mask);
+      filesel->mask = NULL;
+    }
+  
+  cmpl_free_state (filesel->cmpl_state);
+  filesel->cmpl_state = NULL;
+
+  if (GTK_OBJECT_CLASS (parent_class)->destroy)
+    (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
+}
+
+/* Begin file operations callbacks */
+
+static void
+gtk_file_selection_fileop_error (GtkFileSelection *fs, gchar *error_message)
+{
+  GtkWidget *label;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *dialog;
+  
+  g_return_if_fail (error_message != NULL);
+  
+  /* main dialog */
+  dialog = gtk_dialog_new ();
+  /*
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  */
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Error"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+  
+  /* If file dialog is grabbed, make this dialog modal too */
+  /* When error dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+
+  label = gtk_label_new(error_message);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+
+  /* yes, we free it */
+  g_free (error_message);
+  
+  /* close button */
+  button = gtk_button_new_with_label (_("Close"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_fileop_destroy (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  fs->fileop_dialog = NULL;
+}
+
+
+static void
+gtk_file_selection_create_dir_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  gchar *dirname;
+  gchar *path;
+  gchar *full_path;
+  gchar *buf;
+  CompletionState *cmpl_state;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  dirname = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  full_path = g_strconcat (path, "/", dirname, NULL);
+  if ( (mkdir (full_path, 0755) < 0) ) 
+    {
+      buf = g_strconcat ("Error creating directory \"", dirname, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (full_path);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+  
+static void
+gtk_file_selection_create_dir (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *button;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Create Directory"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+  
+  label = gtk_label_new(_("Directory name:"));
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+
+  /*  The directory entry widget  */
+  fs->fileop_entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
+		      TRUE, TRUE, 5);
+  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+  gtk_widget_show (fs->fileop_entry);
+  
+  /* buttons */
+  button = gtk_button_new_with_label (_("Create"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_create_dir_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+static void
+gtk_file_selection_delete_file_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  CompletionState *cmpl_state;
+  gchar *path;
+  gchar *full_path;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  full_path = g_strconcat (path, "/", fs->fileop_file, NULL);
+  if ( (unlink (full_path) < 0) ) 
+    {
+      buf = g_strconcat ("Error deleting file \"", fs->fileop_file, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (full_path);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+
+static void
+gtk_file_selection_delete_file (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  GtkWidget *dialog;
+  gchar *filename;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+
+  filename = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+  if (strlen(filename) < 1)
+	  return;
+
+  fs->fileop_file = filename;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Delete File"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog is closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+      gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+  
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width(GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+
+  buf = g_strconcat ("Really delete file \"", filename, "\" ?", NULL);
+  label = gtk_label_new(buf);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+  g_free(buf);
+  
+  /* buttons */
+  button = gtk_button_new_with_label (_("Delete"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_delete_file_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+
+}
+
+static void
+gtk_file_selection_rename_file_confirmed (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  gchar *buf;
+  gchar *file;
+  gchar *path;
+  gchar *new_filename;
+  gchar *old_filename;
+  CompletionState *cmpl_state;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  file = gtk_entry_get_text (GTK_ENTRY (fs->fileop_entry));
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  path = cmpl_reference_position (cmpl_state);
+  
+  new_filename = g_strconcat (path, "/", file, NULL);
+  old_filename = g_strconcat (path, "/", fs->fileop_file, NULL);
+
+  if ( (rename (old_filename, new_filename)) < 0) 
+    {
+      buf = g_strconcat ("Error renaming file \"", file, "\":  ", 
+			 g_strerror(errno), NULL);
+      gtk_file_selection_fileop_error (fs, buf);
+    }
+  g_free (new_filename);
+  g_free (old_filename);
+  
+  gtk_widget_destroy (fs->fileop_dialog);
+  gtk_file_selection_populate (fs, "", FALSE);
+}
+  
+static void
+gtk_file_selection_rename_file (GtkWidget *widget, gpointer data)
+{
+  GtkFileSelection *fs = data;
+  GtkWidget *label;
+  GtkWidget *dialog;
+  GtkWidget *vbox;
+  GtkWidget *button;
+  gchar *buf;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  if (fs->fileop_dialog)
+	  return;
+
+  fs->fileop_file = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+  if (strlen(fs->fileop_file) < 1)
+	  return;
+  
+  /* main dialog */
+  fs->fileop_dialog = dialog = gtk_dialog_new ();
+  gtk_signal_connect (GTK_OBJECT (dialog), "destroy",
+		      (GtkSignalFunc) gtk_file_selection_fileop_destroy, 
+		      (gpointer) fs);
+  gtk_window_set_title (GTK_WINDOW (dialog), _("Rename File"));
+  gtk_window_set_position (GTK_WINDOW (dialog), GTK_WIN_POS_MOUSE);
+
+  /* If file dialog is grabbed, grab option dialog */
+  /* When option dialog  closed, file dialog will be grabbed again */
+  if (GTK_WINDOW(fs)->modal)
+    gtk_window_set_modal (GTK_WINDOW(dialog), TRUE);
+  
+  vbox = gtk_vbox_new(FALSE, 0);
+  gtk_container_set_border_width (GTK_CONTAINER(vbox), 8);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), vbox,
+		     FALSE, FALSE, 0);
+  gtk_widget_show(vbox);
+  
+  buf = g_strconcat ("Rename file \"", fs->fileop_file, "\" to:", NULL);
+  label = gtk_label_new(buf);
+  gtk_misc_set_alignment(GTK_MISC(label), 0.0, 0.0);
+  gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 5);
+  gtk_widget_show(label);
+  g_free(buf);
+
+  /* New filename entry */
+  fs->fileop_entry = gtk_entry_new ();
+  gtk_box_pack_start (GTK_BOX (vbox), fs->fileop_entry, 
+		      TRUE, TRUE, 5);
+  GTK_WIDGET_SET_FLAGS(fs->fileop_entry, GTK_CAN_DEFAULT);
+  gtk_widget_show (fs->fileop_entry);
+  
+  gtk_entry_set_text (GTK_ENTRY (fs->fileop_entry), fs->fileop_file);
+  gtk_editable_select_region (GTK_EDITABLE (fs->fileop_entry),
+			      0, strlen (fs->fileop_file));
+
+  /* buttons */
+  button = gtk_button_new_with_label (_("Rename"));
+  gtk_signal_connect (GTK_OBJECT (button), "clicked",
+		      (GtkSignalFunc) gtk_file_selection_rename_file_confirmed, 
+		      (gpointer) fs);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_show(button);
+  
+  button = gtk_button_new_with_label (_("Cancel"));
+  gtk_signal_connect_object (GTK_OBJECT (button), "clicked",
+			     (GtkSignalFunc) gtk_widget_destroy, 
+			     (gpointer) dialog);
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->action_area),
+		     button, TRUE, TRUE, 0);
+  GTK_WIDGET_SET_FLAGS(button, GTK_CAN_DEFAULT);
+  gtk_widget_grab_default(button);
+  gtk_widget_show (button);
+
+  gtk_widget_show (dialog);
+}
+
+
+static gint
+gtk_file_selection_key_press (GtkWidget   *widget,
+			      GdkEventKey *event,
+			      gpointer     user_data)
+{
+  GtkFileSelection *fs;
+  char *text;
+
+  g_return_val_if_fail (widget != NULL, FALSE);
+  g_return_val_if_fail (event != NULL, FALSE);
+
+  fs = GTK_FILE_SELECTION (user_data);
+
+  if (event->keyval == GDK_Tab)
+    {
+      text = gtk_entry_get_text (GTK_ENTRY (fs->selection_entry));
+
+      text = g_strdup (text);
+
+      gtk_file_selection_populate (fs, text, TRUE);
+
+      g_free (text);
+
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+
+      return TRUE;
+    }
+  if (fs->saved_entry)
+    {
+      gtk_clist_unselect_all ((GtkCList *) (fs->dir_list));
+      gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
+      g_free (fs->saved_entry);
+      fs->saved_entry = NULL;
+    }
+
+
+  return FALSE;
+}
+
+static void
+gtk_file_selection_home_button (GtkWidget *widget, gpointer data){
+  GList *list;
+	
+  GtkFileSelection *fs=data;
+
+  list = fs->next_history;
+  if (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+		
+  gtk_file_selection_populate (fs,"~/",FALSE);
+}
+
+static void
+gtk_file_selection_up_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->next_history;
+  if (list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+
+  gtk_file_selection_populate (fs, "../", FALSE); /*change directories. */
+		
+}
+
+static void
+gtk_file_selection_prev_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+  GList *first;
+  gchar *path;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->prev_history;
+
+  if (list && g_list_length(list) > 1)
+    {
+      first = list;            /* get first element */
+      list = list->next;       /* pop off current directory */
+
+      list->prev = NULL;       /* make this the new head. */
+  	
+      fs->prev_history = list; /* update prev_history list */
+      fs->next_history = g_list_prepend(fs->next_history,first->data); /* put it on next_history */
+  	
+      first->next = NULL;      /* orphan the old first node */
+      g_list_free (first);     /* free the node (data is now in use by next_history) */
+
+
+  	
+      path = g_malloc(strlen(list->data)+4); /* plenty of space */
+      strcpy(path,list->data);               /* get the 2nd path in the history */
+      strcat(path,"/");                      /* append a '/' */
+      gtk_file_selection_populate (fs, path, FALSE); /* change directories. */
+      g_free (path);
+    }
+}	
+
+static void
+gtk_file_selection_next_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+  GList *list;
+  GList *first;
+  gchar *path;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  list = fs->next_history;
+
+  if (list && g_list_length(list) > 0)
+    {
+      first = list;            /*get first element*/
+      list = list->next;       /*pop off current directory*/
+      
+      if (list)
+	list->prev = NULL;
+      
+      fs->next_history = list;                       /*update prev_history list*/
+  	
+      path = g_malloc(strlen(first->data)+4);        /*plenty of space*/
+      strcpy(path,first->data);
+      strcat(path,"/");                              /*append a /   */
+      gtk_file_selection_populate (fs, path, FALSE); /*change directories.*/
+      g_free(path);
+  	
+      first->next = NULL;     /* orphan the old first node */
+      g_list_free (first);    /* free the node (data is now in use by next_history) */
+      
+    }
+}	
+
+void static
+gtk_file_selection_refresh_button (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_file_selection_populate (fs,"",FALSE);
+}
+
+static void
+gtk_file_selection_mask_entry_callback (GtkWidget *widget, gpointer data){
+  GtkFileSelection *fs = data;
+
+  if(fs->mask)
+    g_free (fs->mask);
+		
+  fs->mask = g_strdup(gtk_entry_get_text (GTK_ENTRY(fs->mask_entry)));
+	
+  if (strlen(fs->mask) == 0)
+    {
+      g_free (fs->mask);
+      fs->mask = NULL;
+    }
+	
+  gtk_file_selection_refresh_button (widget,data);
+}
+
+static gboolean gtk_file_selection_history_combo_list_key_handler(GtkWidget *widget,
+								  GdkEventKey *event,
+								  gpointer user_data)
+{
+  /*
+  g_print("Key pressed! \n");
+  */
+	
+  return TRUE;
+}
+
+static gboolean gtk_file_selection_history_combo_list_callback (GtkWidget *thelist,
+								GdkEventButton *event,
+								gpointer user_data)
+{
+
+  GtkFileSelection *fs = user_data;
+  GList *list;
+  gchar *path;
+		
+  list = fs->next_history;
+  if(list)
+    {
+      g_free (list->data);
+      list = list->next;
+    }
+  g_list_free (fs->next_history);
+  fs->next_history = NULL;
+			
+  path = g_malloc(strlen(gtk_entry_get_text(GTK_ENTRY (((GtkCombo *)fs->history_combo)->entry)))+4);
+  strcpy (path,gtk_entry_get_text(GTK_ENTRY( ((GtkCombo *)fs->history_combo)->entry)));
+  strcat (path,"/");
+	
+  gtk_file_selection_populate (fs,path,TRUE);
+	
+  g_free (path);
+
+  return TRUE;
+}
+
+static gboolean
+gtk_file_selection_history_combo_callback (GtkWidget *widget, GdkEventKey *event, gpointer data)
+{
+  GtkEntry *entry=(GtkEntry *)widget;
+  GtkFileSelection *fs=data;
+  GList *list;
+  gchar *path;
+	
+  g_return_val_if_fail (fs != NULL,FALSE);
+  g_return_val_if_fail (GTK_IS_FILE_SELECTION (fs),FALSE);
+	
+
+  if (event->keyval == GDK_Return)
+    {
+      list = fs->next_history;
+      if (list)
+	{
+	  g_free (list->data);
+	  list = list->next;
+	}
+      g_list_free (fs->next_history);
+      fs->next_history = NULL;
+      
+      path = g_malloc(strlen(gtk_entry_get_text(entry))+4);
+      strcpy (path,gtk_entry_get_text(entry));
+      strcat (path,"/");
+      gtk_file_selection_populate (fs,path,TRUE);
+      g_free (path);
+      gtk_signal_emit_stop_by_name (GTK_OBJECT (widget), "key_press_event");
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
+
+}
+
+static void
+gtk_file_selection_update_history_menu (GtkFileSelection *fs,
+					gchar *current_directory)
+{
+  gchar *current_dir;
+
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  g_return_if_fail (current_directory != NULL);
+  
+  current_dir = g_strdup (current_directory);
+
+  if(fs->prev_history)
+    {
+      if (strcmp((fs->prev_history)->data,current_dir))
+	{ /*if this item isn't on the top of the list */
+	  fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
+	}
+    } else {
+      fs->prev_history = g_list_prepend(fs->prev_history,g_strdup(current_dir));
+    }
+  
+  gtk_combo_set_popdown_strings (GTK_COMBO (fs->history_combo),fs->prev_history);
+  
+  g_free (current_dir);
+}
+
+static void
+gtk_file_selection_file_button (GtkWidget *widget,
+			       gint row, 
+			       gint column, 
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+  
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = user_data;
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  gtk_clist_get_text (GTK_CLIST (fs->file_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  case GDK_2BUTTON_PRESS:
+	    gtk_button_clicked (GTK_BUTTON (fs->ok_button));
+	    break;
+	    
+	  default:
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+      
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_dir_button (GtkWidget *widget,
+			       gint row, 
+			       gint column, 
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GList *list;
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = GTK_FILE_SELECTION (user_data);
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  case GDK_2BUTTON_PRESS:
+	    list = fs->next_history;
+	    if (list)
+	      {
+		g_free (list->data);
+		list = list->next;
+	      }
+	    g_list_free (fs->next_history);
+	    fs->next_history = NULL;
+	
+	    gtk_file_selection_populate (fs, filename, FALSE);
+	    gtk_entry_set_text(GTK_ENTRY(fs->selection_entry),fs->saved_entry);
+	    g_free (fs->saved_entry);
+	    fs->saved_entry = NULL;
+	    break;
+	    
+	  default:
+	    /* here we need to add the "filename" to the beginning of what's already
+	       in the entry.  Save what's in the entry, then restore it on the double click
+	    */
+	    if (fs->saved_entry) g_free (fs->saved_entry);
+	    fs->saved_entry=g_strdup(gtk_entry_get_text(GTK_ENTRY (fs->selection_entry)));
+	
+	    temp=g_strconcat(filename,fs->saved_entry,NULL);
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), temp);
+	    g_free (temp);
+	
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename);
+      
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_undir_button (GtkWidget *widget,
+			       gint row,
+			       gint column,
+			       GdkEventButton *bevent,
+			       gpointer user_data)
+{
+  GtkFileSelection *fs = NULL;
+  gchar *filename, *temp = NULL;
+
+  g_return_if_fail (GTK_IS_CLIST (widget));
+
+  fs = GTK_FILE_SELECTION (user_data);
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+
+  gtk_clist_get_text (GTK_CLIST (fs->dir_list), row, 0, &temp);
+  filename = g_strdup (temp);
+
+  if (filename)
+    {
+      if (bevent)
+	switch (bevent->type)
+	  {
+	  default:
+	    /* here we need to add the "filename" to the beginning of what's already
+	       in the entry.  Save what's in the entry, then restore it on the double click
+	    */
+	    if (fs->saved_entry)
+	      {
+	        gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),fs->saved_entry);
+		g_free (fs->saved_entry);
+		fs->saved_entry = NULL;
+	      }
+	    break;
+	  }
+      else
+	gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), filename); //?????
+
+      g_free (filename);
+    }
+}
+
+static void
+gtk_file_selection_populate (GtkFileSelection *fs,
+			     gchar            *rel_path,
+			     gint              try_complete)
+{
+  CompletionState *cmpl_state;
+  PossibleCompletion* poss;
+  gchar* filename;
+  gint row;
+  gchar* rem_path = rel_path;
+  gchar* sel_text;
+  gchar* text[2];
+  gint did_recurse = FALSE;
+  gint possible_count = 0;
+  gint selection_index = -1;
+  gint file_list_width;
+  gint dir_list_width;
+  
+  g_return_if_fail (fs != NULL);
+  g_return_if_fail (GTK_IS_FILE_SELECTION (fs));
+  
+  cmpl_state = (CompletionState*) fs->cmpl_state;
+  poss = cmpl_completion_matches (rel_path, &rem_path, cmpl_state);
+
+  if (!cmpl_state_okay (cmpl_state))
+    {
+      /* Something went wrong. */
+      gtk_file_selection_abort (fs);
+      return;
+    }
+
+  g_assert (cmpl_state->reference_dir);
+
+  gtk_clist_freeze (GTK_CLIST (fs->dir_list));
+  gtk_clist_clear (GTK_CLIST (fs->dir_list));
+  gtk_clist_freeze (GTK_CLIST (fs->file_list));
+  gtk_clist_clear (GTK_CLIST (fs->file_list));
+
+  /* Set the dir_list to include ./ and ../ */
+  text[1] = NULL;
+  text[0] = "./";
+  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+
+  text[0] = "../";
+  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+
+  /*reset the max widths of the lists*/
+  dir_list_width = gdk_string_width(fs->dir_list->style->font,"../");
+  gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,dir_list_width);
+  file_list_width = 1;
+  gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,file_list_width);
+
+  while (poss)
+    {
+      if (cmpl_is_a_completion (poss))
+  	{
+	  possible_count += 1;
+	  
+	  filename = cmpl_this_completion (poss);
+
+	  text[0] = filename;
+	  
+	  if (cmpl_is_directory (poss))
+	    {
+	      if (strcmp (filename, "./") != 0 &&
+		  strcmp (filename, "../") != 0)
+		{
+		  int width = gdk_string_width(fs->dir_list->style->font,
+					       filename);
+		  row = gtk_clist_append (GTK_CLIST (fs->dir_list), text);
+		  if(width > dir_list_width)
+		    {
+		      dir_list_width = width;
+		      gtk_clist_set_column_width(GTK_CLIST(fs->dir_list),0,
+						 width);
+		    }
+		}
+	    }
+	  else
+	    {
+	      if(fs->mask)
+		{
+		  if (gtk_file_selection_match_mask(filename,fs->mask))
+		    {
+		      int width = gdk_string_width(fs->file_list->style->font,
+						   filename);
+		      row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
+		      if(width > file_list_width)
+		        {
+		          file_list_width = width;
+		          gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
+						     width);
+		        }
+		    }
+		}
+	      else
+		{
+		  int width = gdk_string_width(fs->file_list->style->font,
+					       filename);
+		  row = gtk_clist_append (GTK_CLIST (fs->file_list), text);
+		  if(width > file_list_width)
+		    {
+		      file_list_width = width;
+		      gtk_clist_set_column_width(GTK_CLIST(fs->file_list),0,
+						 width);
+		    }
+		}
+	    }
+	}
+
+      poss = cmpl_next_completion (cmpl_state);
+    }
+
+  gtk_clist_thaw (GTK_CLIST (fs->dir_list));
+  gtk_clist_thaw (GTK_CLIST (fs->file_list));
+
+  /* File lists are set. */
+
+  g_assert (cmpl_state->reference_dir);
+
+  if (try_complete)
+    {
+
+      /* User is trying to complete filenames, so advance the user's input
+       * string to the updated_text, which is the common leading substring
+       * of all possible completions, and if its a directory attempt
+       * attempt completions in it. */
+
+      if (cmpl_updated_text (cmpl_state)[0])
+        {
+
+          if (cmpl_updated_dir (cmpl_state))
+            {
+	      gchar* dir_name = g_strdup (cmpl_updated_text (cmpl_state));
+
+              did_recurse = TRUE;
+
+              gtk_file_selection_populate (fs, dir_name, TRUE);
+
+              g_free (dir_name);
+            }
+          else
+            {
+	      if (fs->selection_entry)
+		      gtk_entry_set_text (GTK_ENTRY (fs->selection_entry),
+					  cmpl_updated_text (cmpl_state));
+            }
+        }
+      else
+        {
+          selection_index = cmpl_last_valid_char (cmpl_state) -
+                            (strlen (rel_path) - strlen (rem_path));
+	  if (fs->selection_entry)
+	    gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), rem_path);
+        }
+    }
+  else
+    {
+      if (fs->selection_entry)
+      /* Here we need to take the old filename and keep it!*/
+	/*gtk_entry_set_text (GTK_ENTRY (fs->selection_entry), "");*/
+	;
+    }
+
+  if (!did_recurse)
+    {
+      if (fs->selection_entry)
+	gtk_entry_set_position (GTK_ENTRY (fs->selection_entry), selection_index);
+
+      if (fs->selection_entry)
+	{
+	  sel_text = g_strconcat (_("Selection: "),
+				  cmpl_reference_position (cmpl_state),
+				  NULL);
+
+	  gtk_label_set_text (GTK_LABEL (fs->selection_text), sel_text);
+	  g_free (sel_text);
+	}
+
+  gtk_file_selection_update_history_menu (fs, cmpl_reference_position (cmpl_state));
+
+    }
+}
+
+static void
+gtk_file_selection_abort (GtkFileSelection *fs)
+{
+  gchar err_buf[256];
+
+  sprintf (err_buf, _("Directory unreadable: %s"), cmpl_strerror (cmpl_errno));
+
+  /*  BEEP gdk_beep();  */
+
+  if (fs->selection_entry)
+    gtk_label_set_text (GTK_LABEL (fs->selection_text), err_buf);
+}
+
+/**********************************************************************/
+/*			  External Interface                          */
+/**********************************************************************/
+
+/* The four completion state selectors
+ */
+static gchar*
+cmpl_updated_text (CompletionState* cmpl_state)
+{
+  return cmpl_state->updated_text;
+}
+
+static gint
+cmpl_updated_dir (CompletionState* cmpl_state)
+{
+  return cmpl_state->re_complete;
+}
+
+static gchar*
+cmpl_reference_position (CompletionState* cmpl_state)
+{
+  return cmpl_state->reference_dir->fullname;
+}
+
+static gint
+cmpl_last_valid_char (CompletionState* cmpl_state)
+{
+  return cmpl_state->last_valid_char;
+}
+
+static gchar*
+cmpl_completion_fullname (gchar* text, CompletionState* cmpl_state)
+{
+  static char nothing[2] = "";
+
+  if (!cmpl_state_okay (cmpl_state))
+    {
+      return nothing;
+    }
+  else if (text[0] == '/')
+    {
+      strcpy (cmpl_state->updated_text, text);
+    }
+  else if (text[0] == '~')
+    {
+      CompletionDir* dir;
+      char* slash;
+
+      dir = open_user_dir (text, cmpl_state);
+
+      if (!dir)
+	{
+	  /* spencer says just return ~something, so
+	   * for now just do it. */
+	  strcpy (cmpl_state->updated_text, text);
+	}
+      else
+	{
+
+	  strcpy (cmpl_state->updated_text, dir->fullname);
+
+	  slash = strchr (text, '/');
+
+	  if (slash)
+	    strcat (cmpl_state->updated_text, slash);
+	}
+    }
+  else
+    {
+      strcpy (cmpl_state->updated_text, cmpl_state->reference_dir->fullname);
+      if (strcmp (cmpl_state->reference_dir->fullname, "/") != 0)
+	strcat (cmpl_state->updated_text, "/");
+      strcat (cmpl_state->updated_text, text);
+    }
+
+  return cmpl_state->updated_text;
+}
+
+/* The three completion selectors
+ */
+static gchar*
+cmpl_this_completion (PossibleCompletion* pc)
+{
+  return pc->text;
+}
+
+static gint
+cmpl_is_directory (PossibleCompletion* pc)
+{
+  return pc->is_directory;
+}
+
+static gint
+cmpl_is_a_completion (PossibleCompletion* pc)
+{
+  return pc->is_a_completion;
+}
+
+/**********************************************************************/
+/*	                 Construction, deletion                       */
+/**********************************************************************/
+
+static CompletionState*
+cmpl_init_state (void)
+{
+  gchar getcwd_buf[2*MAXPATHLEN];
+  CompletionState *new_state;
+
+  new_state = g_new (CompletionState, 1);
+
+  /* We don't use getcwd() on SUNOS, because, it does a popen("pwd")
+   * and, if that wasn't bad enough, hangs in doing so.
+   */
+#if defined(sun) && !defined(__SVR4)
+  if (!getwd (getcwd_buf))
+#else    
+  if (!getcwd (getcwd_buf, MAXPATHLEN))
+#endif    
+    {
+      /* Oh joy, we can't get the current directory. Um..., we should have
+       * a root directory, right? Right? (Probably not portable to non-Unix)
+       */
+      strcpy (getcwd_buf, "/");
+    }
+
+tryagain:
+
+  new_state->reference_dir = NULL;
+  new_state->completion_dir = NULL;
+  new_state->active_completion_dir = NULL;
+  new_state->directory_storage = NULL;
+  new_state->directory_sent_storage = NULL;
+  new_state->last_valid_char = 0;
+  new_state->updated_text = g_new (gchar, MAXPATHLEN);
+  new_state->updated_text_alloc = MAXPATHLEN;
+  new_state->the_completion.text = g_new (gchar, MAXPATHLEN);
+  new_state->the_completion.text_alloc = MAXPATHLEN;
+  new_state->user_dir_name_buffer = NULL;
+  new_state->user_directories = NULL;
+
+  new_state->reference_dir =  open_dir (getcwd_buf, new_state);
+
+  if (!new_state->reference_dir)
+    {
+      /* Directories changing from underneath us, grumble */
+      strcpy (getcwd_buf, "/");
+      goto tryagain;
+    }
+
+  return new_state;
+}
+
+static void
+cmpl_free_dir_list(GList* dp0)
+{
+  GList *dp = dp0;
+
+  while (dp) {
+    free_dir (dp->data);
+    dp = dp->next;
+  }
+
+  g_list_free(dp0);
+}
+
+static void
+cmpl_free_dir_sent_list(GList* dp0)
+{
+  GList *dp = dp0;
+
+  while (dp) {
+    free_dir_sent (dp->data);
+    dp = dp->next;
+  }
+
+  g_list_free(dp0);
+}
+
+static void
+cmpl_free_state (CompletionState* cmpl_state)
+{
+  cmpl_free_dir_list (cmpl_state->directory_storage);
+  cmpl_free_dir_sent_list (cmpl_state->directory_sent_storage);
+
+  if (cmpl_state->user_dir_name_buffer)
+    g_free (cmpl_state->user_dir_name_buffer);
+  if (cmpl_state->user_directories)
+    g_free (cmpl_state->user_directories);
+  if (cmpl_state->the_completion.text)
+    g_free (cmpl_state->the_completion.text);
+  if (cmpl_state->updated_text)
+    g_free (cmpl_state->updated_text);
+
+  g_free (cmpl_state);
+}
+
+static void
+free_dir(CompletionDir* dir)
+{
+  g_free(dir->fullname);
+  g_free(dir);
+}
+
+static void
+free_dir_sent(CompletionDirSent* sent)
+{
+  g_free(sent->name_buffer);
+  g_free(sent->entries);
+  g_free(sent);
+}
+
+static void
+prune_memory_usage(CompletionState *cmpl_state)
+{
+  GList* cdsl = cmpl_state->directory_sent_storage;
+  GList* cdl = cmpl_state->directory_storage;
+  GList* cdl0 = cdl;
+  gint len = 0;
+
+  for(; cdsl && len < CMPL_DIRECTORY_CACHE_SIZE; len += 1)
+    cdsl = cdsl->next;
+
+  if (cdsl) {
+    cmpl_free_dir_sent_list(cdsl->next);
+    cdsl->next = NULL;
+  }
+
+  cmpl_state->directory_storage = NULL;
+  while (cdl) {
+    if (cdl->data == cmpl_state->reference_dir)
+      cmpl_state->directory_storage = g_list_prepend(NULL, cdl->data);
+    else
+      free_dir (cdl->data);
+    cdl = cdl->next;
+  }
+
+  g_list_free(cdl0);
+}
+
+/**********************************************************************/
+/*                        The main entrances.                         */
+/**********************************************************************/
+
+static PossibleCompletion*
+cmpl_completion_matches (gchar* text_to_complete,
+			 gchar** remaining_text,
+			 CompletionState* cmpl_state)
+{
+  gchar* first_slash;
+  PossibleCompletion *poss;
+
+  prune_memory_usage(cmpl_state);
+
+  g_assert (text_to_complete != NULL);
+
+  cmpl_state->user_completion_index = -1;
+  cmpl_state->last_completion_text = text_to_complete;
+  cmpl_state->the_completion.text[0] = 0;
+  cmpl_state->last_valid_char = 0;
+  cmpl_state->updated_text_len = -1;
+  cmpl_state->updated_text[0] = 0;
+  cmpl_state->re_complete = FALSE;
+
+  first_slash = strchr (text_to_complete, '/');
+
+  if (text_to_complete[0] == '~' && !first_slash)
+    {
+      /* Text starts with ~ and there is no slash, show all the
+       * home directory completions.
+       */
+      poss = attempt_homedir_completion (text_to_complete, cmpl_state);
+
+      update_cmpl(poss, cmpl_state);
+
+      return poss;
+    }
+
+  cmpl_state->reference_dir =
+    open_ref_dir (text_to_complete, remaining_text, cmpl_state);
+
+  if(!cmpl_state->reference_dir)
+    return NULL;
+
+  cmpl_state->completion_dir =
+    find_completion_dir (*remaining_text, remaining_text, cmpl_state);
+
+  cmpl_state->last_valid_char = *remaining_text - text_to_complete;
+
+  if(!cmpl_state->completion_dir)
+    return NULL;
+
+  cmpl_state->completion_dir->cmpl_index = -1;
+  cmpl_state->completion_dir->cmpl_parent = NULL;
+  cmpl_state->completion_dir->cmpl_text = *remaining_text;
+
+  cmpl_state->active_completion_dir = cmpl_state->completion_dir;
+
+  cmpl_state->reference_dir = cmpl_state->completion_dir;
+
+  poss = attempt_file_completion(cmpl_state);
+
+  update_cmpl(poss, cmpl_state);
+
+  return poss;
+}
+
+static PossibleCompletion*
+cmpl_next_completion (CompletionState* cmpl_state)
+{
+  PossibleCompletion* poss = NULL;
+
+  cmpl_state->the_completion.text[0] = 0;
+
+  if(cmpl_state->user_completion_index >= 0)
+    poss = attempt_homedir_completion(cmpl_state->last_completion_text, cmpl_state);
+  else
+    poss = attempt_file_completion(cmpl_state);
+
+  update_cmpl(poss, cmpl_state);
+
+  return poss;
+}
+
+/**********************************************************************/
+/*			 Directory Operations                         */
+/**********************************************************************/
+
+/* Open the directory where completion will begin from, if possible. */
+static CompletionDir*
+open_ref_dir(gchar* text_to_complete,
+	     gchar** remaining_text,
+	     CompletionState* cmpl_state)
+{
+  gchar* first_slash;
+  CompletionDir *new_dir;
+
+  first_slash = strchr(text_to_complete, '/');
+
+  if (text_to_complete[0] == '~')
+    {
+      new_dir = open_user_dir(text_to_complete, cmpl_state);
+
+      if(new_dir)
+	{
+	  if(first_slash)
+	    *remaining_text = first_slash + 1;
+	  else
+	    *remaining_text = text_to_complete + strlen(text_to_complete);
+	}
+      else
+	{
+	  return NULL;
+	}
+    }
+  else if (text_to_complete[0] == '/' || !cmpl_state->reference_dir)
+    {
+      gchar *tmp = g_strdup(text_to_complete);
+      gchar *p;
+
+      p = tmp;
+      while (*p && *p != '*' && *p != '?')
+	p++;
+
+      *p = '\0';
+      p = strrchr(tmp, '/');
+      if (p)
+	{
+	  if (p == tmp)
+	    p++;
+      
+	  *p = '\0';
+
+	  new_dir = open_dir(tmp, cmpl_state);
+
+	  if(new_dir)
+	    *remaining_text = text_to_complete + 
+	      ((p == tmp + 1) ? (p - tmp) : (p + 1 - tmp));
+	}
+      else
+	{
+	  /* If no possible candidates, use the cwd */
+	  gchar *curdir = g_get_current_dir ();
+	  
+	  new_dir = open_dir(curdir, cmpl_state);
+
+	  if (new_dir)
+	    *remaining_text = text_to_complete;
+
+	  g_free (curdir);
+	}
+
+      g_free (tmp);
+    }
+  else
+    {
+      *remaining_text = text_to_complete;
+
+      new_dir = open_dir(cmpl_state->reference_dir->fullname, cmpl_state);
+    }
+
+  if(new_dir)
+    {
+      new_dir->cmpl_index = -1;
+      new_dir->cmpl_parent = NULL;
+    }
+
+  return new_dir;
+}
+
+/* open a directory by user name */
+static CompletionDir*
+open_user_dir(gchar* text_to_complete,
+	      CompletionState *cmpl_state)
+{
+  gchar *first_slash;
+  gint cmp_len;
+
+  g_assert(text_to_complete && text_to_complete[0] == '~');
+
+  first_slash = strchr(text_to_complete, '/');
+
+  if (first_slash)
+    cmp_len = first_slash - text_to_complete - 1;
+  else
+    cmp_len = strlen(text_to_complete + 1);
+
+  if(!cmp_len)
+    {
+      /* ~/ */
+      gchar *homedir = g_get_home_dir ();
+
+      if (homedir)
+	return open_dir(homedir, cmpl_state);
+      else
+	return NULL;
+    }
+  else
+    {
+      /* ~user/ */
+      char* copy = g_new(char, cmp_len + 1);
+      struct passwd *pwd;
+      strncpy(copy, text_to_complete + 1, cmp_len);
+      copy[cmp_len] = 0;
+      pwd = getpwnam(copy);
+      g_free(copy);
+      if (!pwd)
+	{
+	  cmpl_errno = errno;
+	  return NULL;
+	}
+
+      return open_dir(pwd->pw_dir, cmpl_state);
+    }
+}
+
+/* open a directory relative the the current relative directory */
+static CompletionDir*
+open_relative_dir(gchar* dir_name,
+		  CompletionDir* dir,
+		  CompletionState *cmpl_state)
+{
+  gchar path_buf[2*MAXPATHLEN];
+
+  if(dir->fullname_len + strlen(dir_name) + 2 >= MAXPATHLEN)
+    {
+      cmpl_errno = CMPL_ERRNO_TOO_LONG;
+      return NULL;
+    }
+
+  strcpy(path_buf, dir->fullname);
+
+  if(dir->fullname_len > 1)
+    {
+      path_buf[dir->fullname_len] = '/';
+      strcpy(path_buf + dir->fullname_len + 1, dir_name);
+    }
+  else
+    {
+      strcpy(path_buf + dir->fullname_len, dir_name);
+    }
+
+  return open_dir(path_buf, cmpl_state);
+}
+
+/* after the cache lookup fails, really open a new directory */
+static CompletionDirSent*
+open_new_dir(gchar* dir_name, struct stat* sbuf, gboolean stat_subdirs)
+{
+  CompletionDirSent* sent;
+  DIR* directory;
+  gchar *buffer_ptr;
+  struct dirent *dirent_ptr;
+  gint buffer_size = 0;
+  gint entry_count = 0;
+  gint i;
+  struct stat ent_sbuf;
+  char path_buf[MAXPATHLEN*2];
+  gint path_buf_len;
+
+  sent = g_new(CompletionDirSent, 1);
+  sent->mtime = sbuf->st_mtime;
+  sent->inode = sbuf->st_ino;
+  sent->device = sbuf->st_dev;
+
+  path_buf_len = strlen(dir_name);
+
+  if (path_buf_len > MAXPATHLEN)
+    {
+      cmpl_errno = CMPL_ERRNO_TOO_LONG;
+      return NULL;
+    }
+
+  strcpy(path_buf, dir_name);
+
+  directory = opendir(dir_name);
+
+  if(!directory)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  while((dirent_ptr = readdir(directory)) != NULL)
+    {
+      int entry_len = strlen(dirent_ptr->d_name);
+      buffer_size += entry_len + 1;
+      entry_count += 1;
+
+      if(path_buf_len + entry_len + 2 >= MAXPATHLEN)
+	{
+	  cmpl_errno = CMPL_ERRNO_TOO_LONG;
+ 	  closedir(directory);
+	  return NULL;
+	}
+    }
+
+  sent->name_buffer = g_new(gchar, buffer_size);
+  sent->entries = g_new(CompletionDirEntry, entry_count);
+  sent->entry_count = entry_count;
+
+  buffer_ptr = sent->name_buffer;
+
+  rewinddir(directory);
+
+  for(i = 0; i < entry_count; i += 1)
+    {
+      dirent_ptr = readdir(directory);
+
+      if(!dirent_ptr)
+	{
+	  cmpl_errno = errno;
+	  closedir(directory);
+	  return NULL;
+	}
+
+      strcpy(buffer_ptr, dirent_ptr->d_name);
+      sent->entries[i].entry_name = buffer_ptr;
+      buffer_ptr += strlen(dirent_ptr->d_name);
+      *buffer_ptr = 0;
+      buffer_ptr += 1;
+
+      path_buf[path_buf_len] = '/';
+      strcpy(path_buf + path_buf_len + 1, dirent_ptr->d_name);
+
+      if (stat_subdirs)
+	{
+	  if(stat(path_buf, &ent_sbuf) >= 0 && S_ISDIR(ent_sbuf.st_mode))
+	    sent->entries[i].is_dir = 1;
+	  else
+	    /* stat may fail, and we don't mind, since it could be a
+	     * dangling symlink. */
+	    sent->entries[i].is_dir = 0;
+	}
+      else
+	sent->entries[i].is_dir = 1;
+    }
+
+  qsort(sent->entries, sent->entry_count, sizeof(CompletionDirEntry), compare_cmpl_dir);
+
+  closedir(directory);
+
+  return sent;
+}
+
+static gboolean
+check_dir(gchar *dir_name, struct stat *result, gboolean *stat_subdirs)
+{
+  /* A list of directories that we know only contain other directories.
+   * Trying to stat every file in these directories would be very
+   * expensive.
+   */
+
+  static struct {
+    gchar *name;
+    gboolean present;
+    struct stat statbuf;
+  } no_stat_dirs[] = {
+    { "/afs", FALSE, { 0 } },
+    { "/net", FALSE, { 0 } }
+  };
+
+  static const gint n_no_stat_dirs = sizeof(no_stat_dirs) / sizeof(no_stat_dirs[0]);
+  static gboolean initialized = FALSE;
+
+  gint i;
+
+  if (!initialized)
+    {
+      initialized = TRUE;
+      for (i = 0; i < n_no_stat_dirs; i++)
+	{
+	  if (stat (no_stat_dirs[i].name, &no_stat_dirs[i].statbuf) == 0)
+	    no_stat_dirs[i].present = TRUE;
+	}
+    }
+
+  if(stat(dir_name, result) < 0)
+    {
+      cmpl_errno = errno;
+      return FALSE;
+    }
+
+  *stat_subdirs = TRUE;
+  for (i=0; i<n_no_stat_dirs; i++)
+    {
+      if (no_stat_dirs[i].present &&
+	  (no_stat_dirs[i].statbuf.st_dev == result->st_dev) &&
+	  (no_stat_dirs[i].statbuf.st_ino == result->st_ino))
+	{
+	  *stat_subdirs = FALSE;
+	  break;
+	}
+    }
+
+  return TRUE;
+}
+
+/* open a directory by absolute pathname */
+static CompletionDir*
+open_dir(gchar* dir_name, CompletionState* cmpl_state)
+{
+  struct stat sbuf;
+  gboolean stat_subdirs;
+  CompletionDirSent *sent;
+  GList* cdsl;
+
+  if (!check_dir (dir_name, &sbuf, &stat_subdirs))
+    return NULL;
+
+  cdsl = cmpl_state->directory_sent_storage;
+
+  while (cdsl)
+    {
+      sent = cdsl->data;
+
+      if(sent->inode == sbuf.st_ino &&
+	 sent->mtime == sbuf.st_mtime &&
+	 sent->device == sbuf.st_dev)
+	return attach_dir(sent, dir_name, cmpl_state);
+
+      cdsl = cdsl->next;
+    }
+
+  sent = open_new_dir(dir_name, &sbuf, stat_subdirs);
+
+  if (sent) {
+    cmpl_state->directory_sent_storage =
+      g_list_prepend(cmpl_state->directory_sent_storage, sent);
+
+    return attach_dir(sent, dir_name, cmpl_state);
+  }
+
+  return NULL;
+}
+
+static CompletionDir*
+attach_dir(CompletionDirSent* sent, gchar* dir_name, CompletionState *cmpl_state)
+{
+  CompletionDir* new_dir;
+
+  new_dir = g_new(CompletionDir, 1);
+
+  cmpl_state->directory_storage =
+    g_list_prepend(cmpl_state->directory_storage, new_dir);
+
+  new_dir->sent = sent;
+  new_dir->fullname = g_strdup(dir_name);
+  new_dir->fullname_len = strlen(dir_name);
+
+  return new_dir;
+}
+
+static gint
+correct_dir_fullname(CompletionDir* cmpl_dir)
+{
+  gint length = strlen(cmpl_dir->fullname);
+  struct stat sbuf;
+
+  if (strcmp(cmpl_dir->fullname + length - 2, "/.") == 0)
+    {
+      if (length == 2) 
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	} else {
+	  cmpl_dir->fullname[length - 2] = 0;
+	}
+    }
+  else if (strcmp(cmpl_dir->fullname + length - 3, "/./") == 0)
+    cmpl_dir->fullname[length - 2] = 0;
+  else if (strcmp(cmpl_dir->fullname + length - 3, "/..") == 0)
+    {
+      if(length == 3)
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	}
+
+      if(stat(cmpl_dir->fullname, &sbuf) < 0)
+	{
+	  cmpl_errno = errno;
+	  return FALSE;
+	}
+
+      cmpl_dir->fullname[length - 2] = 0;
+
+      if(!correct_parent(cmpl_dir, &sbuf))
+	return FALSE;
+    }
+  else if (strcmp(cmpl_dir->fullname + length - 4, "/../") == 0)
+    {
+      if(length == 4)
+	{
+	  strcpy(cmpl_dir->fullname, "/");
+	  cmpl_dir->fullname_len = 1;
+	  return TRUE;
+	}
+
+      if(stat(cmpl_dir->fullname, &sbuf) < 0)
+	{
+	  cmpl_errno = errno;
+	  return FALSE;
+	}
+
+      cmpl_dir->fullname[length - 3] = 0;
+
+      if(!correct_parent(cmpl_dir, &sbuf))
+	return FALSE;
+    }
+
+  cmpl_dir->fullname_len = strlen(cmpl_dir->fullname);
+
+  return TRUE;
+}
+
+static gint
+correct_parent(CompletionDir* cmpl_dir, struct stat *sbuf)
+{
+  struct stat parbuf;
+  gchar *last_slash;
+  gchar *new_name;
+  gchar c = 0;
+
+  last_slash = strrchr(cmpl_dir->fullname, '/');
+
+  g_assert(last_slash);
+
+  if(last_slash != cmpl_dir->fullname)
+    { /* last_slash[0] = 0; */ }
+  else
+    {
+      c = last_slash[1];
+      last_slash[1] = 0;
+    }
+
+  if (stat(cmpl_dir->fullname, &parbuf) < 0)
+    {
+      cmpl_errno = errno;
+      return FALSE;
+    }
+
+  if (parbuf.st_ino == sbuf->st_ino && parbuf.st_dev == sbuf->st_dev)
+    /* it wasn't a link */
+    return TRUE;
+
+  if(c)
+    last_slash[1] = c;
+  /* else
+    last_slash[0] = '/'; */
+
+  /* it was a link, have to figure it out the hard way */
+
+  new_name = find_parent_dir_fullname(cmpl_dir->fullname);
+
+  if (!new_name)
+    return FALSE;
+
+  g_free(cmpl_dir->fullname);
+
+  cmpl_dir->fullname = new_name;
+
+  return TRUE;
+}
+
+static gchar*
+find_parent_dir_fullname(gchar* dirname)
+{
+  gchar buffer[MAXPATHLEN];
+  gchar buffer2[MAXPATHLEN];
+
+#if defined(sun) && !defined(__SVR4)
+  if(!getwd(buffer))
+#else
+  if(!getcwd(buffer, MAXPATHLEN))
+#endif    
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  if(chdir(dirname) != 0 || chdir("..") != 0)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+#if defined(sun) && !defined(__SVR4)
+  if(!getwd(buffer2))
+#else
+  if(!getcwd(buffer2, MAXPATHLEN))
+#endif
+    {
+      chdir(buffer);
+      cmpl_errno = errno;
+
+      return NULL;
+    }
+
+  if(chdir(buffer) != 0)
+    {
+      cmpl_errno = errno;
+      return NULL;
+    }
+
+  return g_strdup(buffer2);
+}
+
+/**********************************************************************/
+/*                        Completion Operations                       */
+/**********************************************************************/
+
+static PossibleCompletion*
+attempt_homedir_completion(gchar* text_to_complete,
+			   CompletionState *cmpl_state)
+{
+  gint index, length;
+
+  if (!cmpl_state->user_dir_name_buffer &&
+      !get_pwdb(cmpl_state))
+    return NULL;
+  length = strlen(text_to_complete) - 1;
+
+  cmpl_state->user_completion_index += 1;
+
+  while(cmpl_state->user_completion_index < cmpl_state->user_directories_len)
+    {
+      index = first_diff_index(text_to_complete + 1,
+			       cmpl_state->user_directories
+			       [cmpl_state->user_completion_index].login);
+
+      switch(index)
+	{
+	case PATTERN_MATCH:
+	  break;
+	default:
+	  if(cmpl_state->last_valid_char < (index + 1))
+	    cmpl_state->last_valid_char = index + 1;
+	  cmpl_state->user_completion_index += 1;
+	  continue;
+	}
+
+      cmpl_state->the_completion.is_a_completion = 1;
+      cmpl_state->the_completion.is_directory = 1;
+
+      append_completion_text("~", cmpl_state);
+
+      append_completion_text(cmpl_state->
+			      user_directories[cmpl_state->user_completion_index].login,
+			     cmpl_state);
+
+      return append_completion_text("/", cmpl_state);
+    }
+
+  if(text_to_complete[1] ||
+     cmpl_state->user_completion_index > cmpl_state->user_directories_len)
+    {
+      cmpl_state->user_completion_index = -1;
+      return NULL;
+    }
+  else
+    {
+      cmpl_state->user_completion_index += 1;
+      cmpl_state->the_completion.is_a_completion = 1;
+      cmpl_state->the_completion.is_directory = 1;
+
+      return append_completion_text("~/", cmpl_state);
+    }
+}
+
+/* returns the index (>= 0) of the first differing character,
+ * PATTERN_MATCH if the completion matches */
+static gint
+first_diff_index(gchar* pat, gchar* text)
+{
+  gint diff = 0;
+
+  while(*pat && *text && *text == *pat)
+    {
+      pat += 1;
+      text += 1;
+      diff += 1;
+    }
+
+  if(*pat)
+    return diff;
+
+  return PATTERN_MATCH;
+}
+
+static PossibleCompletion*
+append_completion_text(gchar* text, CompletionState* cmpl_state)
+{
+  gint len, i = 1;
+
+  if(!cmpl_state->the_completion.text)
+    return NULL;
+
+  len = strlen(text) + strlen(cmpl_state->the_completion.text) + 1;
+
+  if(cmpl_state->the_completion.text_alloc > len)
+    {
+      strcat(cmpl_state->the_completion.text, text);
+      return &cmpl_state->the_completion;
+    }
+
+  while(i < len) { i <<= 1; }
+
+  cmpl_state->the_completion.text_alloc = i;
+
+  cmpl_state->the_completion.text = (gchar*)g_realloc(cmpl_state->the_completion.text, i);
+
+  if(!cmpl_state->the_completion.text)
+    return NULL;
+  else
+    {
+      strcat(cmpl_state->the_completion.text, text);
+      return &cmpl_state->the_completion;
+    }
+}
+
+static CompletionDir*
+find_completion_dir(gchar* text_to_complete,
+		    gchar** remaining_text,
+		    CompletionState* cmpl_state)
+{
+  gchar* first_slash = strchr(text_to_complete, '/');
+  CompletionDir* dir = cmpl_state->reference_dir;
+  CompletionDir* next;
+  *remaining_text = text_to_complete;
+
+  while(first_slash)
+    {
+      gint len = first_slash - *remaining_text;
+      gint found = 0;
+      gchar *found_name = NULL;         /* Quiet gcc */
+      gint i;
+      gchar* pat_buf = g_new (gchar, len + 1);
+
+      strncpy(pat_buf, *remaining_text, len);
+      pat_buf[len] = 0;
+
+      for(i = 0; i < dir->sent->entry_count; i += 1)
+	{
+	  if(dir->sent->entries[i].is_dir &&
+	     fnmatch(pat_buf, dir->sent->entries[i].entry_name,
+		     FNMATCH_FLAGS)!= FNM_NOMATCH)
+	    {
+	      if(found)
+		{
+		  g_free (pat_buf);
+		  return dir;
+		}
+	      else
+		{
+		  found = 1;
+		  found_name = dir->sent->entries[i].entry_name;
+		}
+	    }
+	}
+
+      if (!found)
+	{
+	  /* Perhaps we are trying to open an automount directory */
+	  found_name = pat_buf;
+	}
+
+      next = open_relative_dir(found_name, dir, cmpl_state);
+      
+      if(!next)
+	{
+	  g_free (pat_buf);
+	  return NULL;
+	}
+      
+      next->cmpl_parent = dir;
+      
+      dir = next;
+      
+      if(!correct_dir_fullname(dir))
+	{
+	  g_free(pat_buf);
+	  return NULL;
+	}
+      
+      *remaining_text = first_slash + 1;
+      first_slash = strchr(*remaining_text, '/');
+
+      g_free (pat_buf);
+    }
+
+  return dir;
+}
+
+static void
+update_cmpl(PossibleCompletion* poss, CompletionState* cmpl_state)
+{
+  gint cmpl_len;
+
+  if(!poss || !cmpl_is_a_completion(poss))
+    return;
+
+  cmpl_len = strlen(cmpl_this_completion(poss));
+
+  if(cmpl_state->updated_text_alloc < cmpl_len + 1)
+    {
+      cmpl_state->updated_text =
+	(gchar*)g_realloc(cmpl_state->updated_text,
+			  cmpl_state->updated_text_alloc);
+      cmpl_state->updated_text_alloc = 2*cmpl_len;
+    }
+
+  if(cmpl_state->updated_text_len < 0)
+    {
+      strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+      cmpl_state->updated_text_len = cmpl_len;
+      cmpl_state->re_complete = cmpl_is_directory(poss);
+    }
+  else if(cmpl_state->updated_text_len == 0)
+    {
+      cmpl_state->re_complete = FALSE;
+    }
+  else
+    {
+      gint first_diff =
+	first_diff_index(cmpl_state->updated_text,
+			 cmpl_this_completion(poss));
+
+      cmpl_state->re_complete = FALSE;
+
+      if(first_diff == PATTERN_MATCH)
+	return;
+
+      if(first_diff > cmpl_state->updated_text_len)
+	strcpy(cmpl_state->updated_text, cmpl_this_completion(poss));
+
+      cmpl_state->updated_text_len = first_diff;
+      cmpl_state->updated_text[first_diff] = 0;
+    }
+}
+
+static PossibleCompletion*
+attempt_file_completion(CompletionState *cmpl_state)
+{
+  gchar *pat_buf, *first_slash;
+  CompletionDir *dir = cmpl_state->active_completion_dir;
+
+  dir->cmpl_index += 1;
+
+  if(dir->cmpl_index == dir->sent->entry_count)
+    {
+      if(dir->cmpl_parent == NULL)
+	{
+	  cmpl_state->active_completion_dir = NULL;
+
+	  return NULL;
+	}
+      else
+	{
+	  cmpl_state->active_completion_dir = dir->cmpl_parent;
+
+	  return attempt_file_completion(cmpl_state);
+	}
+    }
+
+  g_assert(dir->cmpl_text);
+
+  first_slash = strchr(dir->cmpl_text, '/');
+
+  if(first_slash)
+    {
+      gint len = first_slash - dir->cmpl_text;
+
+      pat_buf = g_new (gchar, len + 1);
+      strncpy(pat_buf, dir->cmpl_text, len);
+      pat_buf[len] = 0;
+    }
+  else
+    {
+      gint len = strlen(dir->cmpl_text);
+
+      pat_buf = g_new (gchar, len + 2);
+      strcpy(pat_buf, dir->cmpl_text);
+      strcpy(pat_buf + len, "*");
+    }
+
+  if(first_slash)
+    {
+      if(dir->sent->entries[dir->cmpl_index].is_dir)
+	{
+	  if(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+		     FNMATCH_FLAGS) != FNM_NOMATCH)
+	    {
+	      CompletionDir* new_dir;
+
+	      new_dir = open_relative_dir(dir->sent->entries[dir->cmpl_index].entry_name,
+					  dir, cmpl_state);
+
+	      if(!new_dir)
+		{
+		  g_free (pat_buf);
+		  return NULL;
+		}
+
+	      new_dir->cmpl_parent = dir;
+
+	      new_dir->cmpl_index = -1;
+	      new_dir->cmpl_text = first_slash + 1;
+
+	      cmpl_state->active_completion_dir = new_dir;
+
+	      g_free (pat_buf);
+	      return attempt_file_completion(cmpl_state);
+	    }
+	  else
+	    {
+	      g_free (pat_buf);
+	      return attempt_file_completion(cmpl_state);
+	    }
+	}
+      else
+	{
+	  g_free (pat_buf);
+	  return attempt_file_completion(cmpl_state);
+	}
+    }
+  else
+    {
+      if(dir->cmpl_parent != NULL)
+	{
+	  append_completion_text(dir->fullname +
+				 strlen(cmpl_state->completion_dir->fullname) + 1,
+				 cmpl_state);
+	  append_completion_text("/", cmpl_state);
+	}
+
+      append_completion_text(dir->sent->entries[dir->cmpl_index].entry_name, cmpl_state);
+
+      cmpl_state->the_completion.is_a_completion =
+	(fnmatch(pat_buf, dir->sent->entries[dir->cmpl_index].entry_name,
+		 FNMATCH_FLAGS) != FNM_NOMATCH);
+
+      cmpl_state->the_completion.is_directory = dir->sent->entries[dir->cmpl_index].is_dir;
+      if(dir->sent->entries[dir->cmpl_index].is_dir)
+	append_completion_text("/", cmpl_state);
+
+      g_free (pat_buf);
+      return &cmpl_state->the_completion;
+    }
+}
+
+
+static gint
+get_pwdb(CompletionState* cmpl_state)
+{
+  struct passwd *pwd_ptr;
+  gchar* buf_ptr;
+  gint len = 0, i, count = 0;
+
+  if(cmpl_state->user_dir_name_buffer)
+    return TRUE;
+  setpwent ();
+
+  while ((pwd_ptr = getpwent()) != NULL)
+    {
+      len += strlen(pwd_ptr->pw_name);
+      len += strlen(pwd_ptr->pw_dir);
+      len += 2;
+      count += 1;
+    }
+
+  setpwent ();
+
+  cmpl_state->user_dir_name_buffer = g_new(gchar, len);
+  cmpl_state->user_directories = g_new(CompletionUserDir, count);
+  cmpl_state->user_directories_len = count;
+
+  buf_ptr = cmpl_state->user_dir_name_buffer;
+
+  for(i = 0; i < count; i += 1)
+    {
+      pwd_ptr = getpwent();
+      if(!pwd_ptr)
+	{
+	  cmpl_errno = errno;
+	  goto error;
+	}
+
+      strcpy(buf_ptr, pwd_ptr->pw_name);
+      cmpl_state->user_directories[i].login = buf_ptr;
+      buf_ptr += strlen(buf_ptr);
+      buf_ptr += 1;
+      strcpy(buf_ptr, pwd_ptr->pw_dir);
+      cmpl_state->user_directories[i].homedir = buf_ptr;
+      buf_ptr += strlen(buf_ptr);
+      buf_ptr += 1;
+    }
+
+  qsort(cmpl_state->user_directories,
+	cmpl_state->user_directories_len,
+	sizeof(CompletionUserDir),
+	compare_user_dir);
+
+  endpwent();
+
+  return TRUE;
+
+error:
+
+  if(cmpl_state->user_dir_name_buffer)
+    g_free(cmpl_state->user_dir_name_buffer);
+  if(cmpl_state->user_directories)
+    g_free(cmpl_state->user_directories);
+
+  cmpl_state->user_dir_name_buffer = NULL;
+  cmpl_state->user_directories = NULL;
+
+  return FALSE;
+}
+
+static gint
+compare_user_dir(const void* a, const void* b)
+{
+  return strcmp((((CompletionUserDir*)a))->login,
+		(((CompletionUserDir*)b))->login);
+}
+
+static gint
+compare_cmpl_dir(const void* a, const void* b)
+{
+  return strcmp((((CompletionDirEntry*)a))->entry_name,
+		(((CompletionDirEntry*)b))->entry_name);
+}
+
+static gint
+cmpl_state_okay(CompletionState* cmpl_state)
+{
+  return  cmpl_state && cmpl_state->reference_dir;
+}
+
+static gchar*
+cmpl_strerror(gint err)
+{
+  if(err == CMPL_ERRNO_TOO_LONG)
+    return "Name too long";
+  else
+    return g_strerror (err);
+}
+
+
+/* Testing area */
+#ifdef TORRIE_DEBUG
+
+/* Get the selected filename and print it to the console */
+void file_ok_sel( GtkWidget        *w,
+                  GtkFileSelection *fs )
+{
+    g_print ("%s\n", gtk_file_selection_get_filename (GTK_FILE_SELECTION (fs)));
+}
+
+void destroy( GtkWidget *widget,
+              gpointer   data )
+{
+    gtk_main_quit ();
+}
+
+int main( int   argc,
+          char *argv[] )
+{
+    GtkWidget *filew;
+
+    gtk_init (&argc, &argv);
+
+    /* Create a new file selection widget */
+    filew = gtk_file_selection_new ("Michael's Glorious File Selector");
+//    gtk_file_selection_complete(GTK_FILE_SELECTION(filew),"bob");
+
+		
+    gtk_signal_connect (GTK_OBJECT (filew), "destroy",
+			(GtkSignalFunc) destroy, &filew);
+    /* Connect the ok_button to file_ok_sel function */
+    gtk_signal_connect (GTK_OBJECT (GTK_FILE_SELECTION (filew)->ok_button),
+			"clicked", (GtkSignalFunc) file_ok_sel, filew );
+
+    /* Connect the cancel_button to destroy the widget */
+    gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION
+                                            (filew)->cancel_button),
+			       "clicked", (GtkSignalFunc) gtk_widget_destroy,
+			       GTK_OBJECT (filew));
+
+
+    gtk_widget_show(filew);
+
+/*
+    g_print("%d",gtk_file_selection_match_mask("mask.c","m*.c"));
+    g_print("%d",gtk_file_selection_match_mask("mask.c","m???.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.c","m??*.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c???"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","m*.c*"));
+		g_print("%d",gtk_file_selection_match_mask("mask.cout","n*.c???"));
+		g_print("%d",gtk_file_selection_match_mask("mask.c","[mn]*"));
+		g_print("%d",gtk_file_selection_match_mask("COPYING","*.xpm"));
+*/	
+    gtk_main ();
+
+    return 0;
+}
+/* example-end */
+#endif
diff --git a/radiant/gtkfilesel.h b/radiant/gtkfilesel.h
index b5c2a697..098cf27d 100644
--- a/radiant/gtkfilesel.h
+++ b/radiant/gtkfilesel.h
@@ -1,143 +1,143 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/* GTK - The GIMP Toolkit
- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Library General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library 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
- * Library General Public License for more details.
- *
- * You should have received a copy of the GNU Library General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-/*
- * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
- * file for a list of people on the GTK+ Team.  See the ChangeLog
- * files for a list of changes.  These files are distributed with
- * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
- */
-
-#ifndef __GTK_FILESEL_H__
-#define __GTK_FILESEL_H__
-
-
-#include <gdk/gdk.h>
-#include <gtk/gtkwindow.h>
-
-
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
-
-
-#define GTK_TYPE_FILE_SELECTION            (gtk_file_selection_get_type ())
-#define GTK_FILE_SELECTION(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_FILE_SELECTION, GtkFileSelection))
-#define GTK_FILE_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
-#define GTK_IS_FILE_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
-#define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
-
-
-typedef struct _GtkFileSelection       GtkFileSelection;
-typedef struct _GtkFileSelectionClass  GtkFileSelectionClass;
-
-struct _GtkFileSelection
-{
-  GtkWindow window;
-
-  GtkWidget *dir_list;
-  GtkWidget *file_list;
-  GtkWidget *selection_entry;
-  GtkWidget *selection_text;
-  GtkWidget *main_vbox;
-  GtkWidget *ok_button;
-  GtkWidget *cancel_button;
-  GtkWidget *help_button;
-
-  /* These are not used.  Just fillers in the class structure */
-  GtkWidget *history_pulldown;
-  GtkWidget *history_menu;
-  GList     *history_list;
-  /* ***************** */
-	
-  GtkWidget *fileop_dialog;
-  GtkWidget *fileop_entry;
-  gchar     *fileop_file;
-  gpointer   cmpl_state;
-  
-  GtkWidget *fileop_c_dir;
-  GtkWidget *fileop_del_file;
-  GtkWidget *fileop_ren_file;
-  
-  GtkWidget *button_area;
-  GtkWidget *action_area;
-
-  GtkWidget *history_combo;
-  GList     *prev_history;
-  GList     *next_history;
-  GtkWidget *mask_entry;
-  gchar     *mask;
-  gchar     *saved_entry;
-
-};
-
-struct _GtkFileSelectionClass
-{
-  GtkWindowClass parent_class;
-};
-
-
-GtkType    gtk_file_selection_get_type            (void);
-GtkWidget* gtk_file_selection_new                 (const gchar      *title);
-void       gtk_file_selection_set_filename        (GtkFileSelection *filesel,
-						   const gchar      *filename);
-gchar*     gtk_file_selection_get_filename        (GtkFileSelection *filesel);
-void	   gtk_file_selection_complete		  (GtkFileSelection *filesel,
-						   const gchar	    *pattern);
-void       gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
-void       gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
-
-
-#ifdef __cplusplus
-}
-#endif /* __cplusplus */
-
-
-#endif /* __GTK_FILESEL_H__ */
-
-
-
-
-
-
-
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* GTK - The GIMP Toolkit
+ * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/*
+ * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
+ * file for a list of people on the GTK+ Team.  See the ChangeLog
+ * files for a list of changes.  These files are distributed with
+ * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
+ */
+
+#ifndef __GTK_FILESEL_H__
+#define __GTK_FILESEL_H__
+
+
+#include <gdk/gdk.h>
+#include <gtk/gtkwindow.h>
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+
+#define GTK_TYPE_FILE_SELECTION            (gtk_file_selection_get_type ())
+#define GTK_FILE_SELECTION(obj)            (GTK_CHECK_CAST ((obj), GTK_TYPE_FILE_SELECTION, GtkFileSelection))
+#define GTK_FILE_SELECTION_CLASS(klass)    (GTK_CHECK_CLASS_CAST ((klass), GTK_TYPE_FILE_SELECTION, GtkFileSelectionClass))
+#define GTK_IS_FILE_SELECTION(obj)         (GTK_CHECK_TYPE ((obj), GTK_TYPE_FILE_SELECTION))
+#define GTK_IS_FILE_SELECTION_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), GTK_TYPE_FILE_SELECTION))
+
+
+typedef struct _GtkFileSelection       GtkFileSelection;
+typedef struct _GtkFileSelectionClass  GtkFileSelectionClass;
+
+struct _GtkFileSelection
+{
+  GtkWindow window;
+
+  GtkWidget *dir_list;
+  GtkWidget *file_list;
+  GtkWidget *selection_entry;
+  GtkWidget *selection_text;
+  GtkWidget *main_vbox;
+  GtkWidget *ok_button;
+  GtkWidget *cancel_button;
+  GtkWidget *help_button;
+
+  /* These are not used.  Just fillers in the class structure */
+  GtkWidget *history_pulldown;
+  GtkWidget *history_menu;
+  GList     *history_list;
+  /* ***************** */
+	
+  GtkWidget *fileop_dialog;
+  GtkWidget *fileop_entry;
+  gchar     *fileop_file;
+  gpointer   cmpl_state;
+  
+  GtkWidget *fileop_c_dir;
+  GtkWidget *fileop_del_file;
+  GtkWidget *fileop_ren_file;
+  
+  GtkWidget *button_area;
+  GtkWidget *action_area;
+
+  GtkWidget *history_combo;
+  GList     *prev_history;
+  GList     *next_history;
+  GtkWidget *mask_entry;
+  gchar     *mask;
+  gchar     *saved_entry;
+
+};
+
+struct _GtkFileSelectionClass
+{
+  GtkWindowClass parent_class;
+};
+
+
+GtkType    gtk_file_selection_get_type            (void);
+GtkWidget* gtk_file_selection_new                 (const gchar      *title);
+void       gtk_file_selection_set_filename        (GtkFileSelection *filesel,
+						   const gchar      *filename);
+gchar*     gtk_file_selection_get_filename        (GtkFileSelection *filesel);
+void	   gtk_file_selection_complete		  (GtkFileSelection *filesel,
+						   const gchar	    *pattern);
+void       gtk_file_selection_show_fileop_buttons (GtkFileSelection *filesel);
+void       gtk_file_selection_hide_fileop_buttons (GtkFileSelection *filesel);
+
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+
+#endif /* __GTK_FILESEL_H__ */
+
+
+
+
+
+
+
+
+
+
diff --git a/radiant/gtkmisc.h b/radiant/gtkmisc.h
index ee6bc5fd..c8446d6f 100644
--- a/radiant/gtkmisc.h
+++ b/radiant/gtkmisc.h
@@ -1,100 +1,100 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _GTK_MISC_H_
-#define _GTK_MISC_H_
-
-#ifdef _WIN32
-
-void win32_get_window_pos(GtkWidget *widget, gint *x, gint *y);
-
-inline void get_window_pos(GtkWidget *wnd, int* x, int* y)
-{
-  win32_get_window_pos(wnd, x, y);
-}
-
-#else
-
-inline void get_window_pos(GtkWidget *wnd, int* x, int* y)
-{
-  gdk_window_get_root_origin (wnd->window, x, y);
-}
-
-#endif
-
-
-struct window_position_t
-{
-  int x, y, w, h;
-};
-
-void save_window_pos (GtkWidget *wnd, window_position_t& pos);
-void load_window_pos (GtkWidget *wnd, window_position_t& pos);
-gint widget_delete_hide (GtkWidget *widget);
-
-// GdkPixmap **gdkpixmap, GdkBitmap **mask
-bool WINAPI load_plugin_bitmap (const char* filename, void **gdkpixmap, void **mask);
-void load_pixmap (const char* filename, GtkWidget* widget, GdkPixmap **gdkpixmap, GdkBitmap **mask);
-GtkWidget* new_pixmap (GtkWidget* widget, char* filename);
-
-GtkWidget* menu_separator (GtkWidget *menu);
-GtkWidget* menu_tearoff (GtkWidget *menu);
-GtkWidget* create_sub_menu_with_mnemonic (GtkWidget *bar, char *mnemonic);
-GtkWidget* create_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id);
-GtkWidget* create_check_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id, gboolean active);
-GtkWidget* create_radio_menu_item_with_mnemonic (GtkWidget *menu, GtkWidget *last, gchar *mnemonic, GtkSignalFunc func, int id, gboolean state);
-GtkWidget* create_menu_in_menu_with_mnemonic (GtkWidget *menu, const gchar *mnemonic);
-
-
-/*!
-\fn gtk_MessageBox
-do various message boxes, IDOK .. IDNO
-URL adds an optional 'go to URL' button
-*/
-int WINAPI gtk_MessageBox (void *parent, const char* lpText, const char* lpCaption = "Radiant", guint32 uType = MB_OK, const char* URL = NULL);
-// NOTE: the returned filename is allocated with g_malloc and MUST be freed with g_free (both for win32 and Gtk dialogs)
-// GtkWidget *parent
-const char* file_dialog (void *parent, gboolean open, const char* title, const char* path = (char*)NULL, const char* pattern = NULL);
-
-/*!
-\fn dir_dialog, prompts for a directory
-*/
-char* WINAPI dir_dialog (void *parent, const char* title = "Choose Directory", const char* path = (char*)NULL);
-// GtkWidget *parent
-bool WINAPI color_dialog (void *parent, float *color, const char* title = "Choose Color");
-
-void dialog_button_callback (GtkWidget *widget, gpointer data);
-gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data);
-
-void OpenURL(const char *url);
-
-void CheckMenuSplitting (GtkWidget *&menu);
-
-#endif // _GTK_MISC_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _GTK_MISC_H_
+#define _GTK_MISC_H_
+
+#ifdef _WIN32
+
+void win32_get_window_pos(GtkWidget *widget, gint *x, gint *y);
+
+inline void get_window_pos(GtkWidget *wnd, int* x, int* y)
+{
+  win32_get_window_pos(wnd, x, y);
+}
+
+#else
+
+inline void get_window_pos(GtkWidget *wnd, int* x, int* y)
+{
+  gdk_window_get_root_origin (wnd->window, x, y);
+}
+
+#endif
+
+
+struct window_position_t
+{
+  int x, y, w, h;
+};
+
+void save_window_pos (GtkWidget *wnd, window_position_t& pos);
+void load_window_pos (GtkWidget *wnd, window_position_t& pos);
+gint widget_delete_hide (GtkWidget *widget);
+
+// GdkPixmap **gdkpixmap, GdkBitmap **mask
+bool WINAPI load_plugin_bitmap (const char* filename, void **gdkpixmap, void **mask);
+void load_pixmap (const char* filename, GtkWidget* widget, GdkPixmap **gdkpixmap, GdkBitmap **mask);
+GtkWidget* new_pixmap (GtkWidget* widget, char* filename);
+
+GtkWidget* menu_separator (GtkWidget *menu);
+GtkWidget* menu_tearoff (GtkWidget *menu);
+GtkWidget* create_sub_menu_with_mnemonic (GtkWidget *bar, char *mnemonic);
+GtkWidget* create_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id);
+GtkWidget* create_check_menu_item_with_mnemonic (GtkWidget *menu, gchar *mnemonic, GtkSignalFunc func, int id, gboolean active);
+GtkWidget* create_radio_menu_item_with_mnemonic (GtkWidget *menu, GtkWidget *last, gchar *mnemonic, GtkSignalFunc func, int id, gboolean state);
+GtkWidget* create_menu_in_menu_with_mnemonic (GtkWidget *menu, const gchar *mnemonic);
+
+
+/*!
+\fn gtk_MessageBox
+do various message boxes, IDOK .. IDNO
+URL adds an optional 'go to URL' button
+*/
+int WINAPI gtk_MessageBox (void *parent, const char* lpText, const char* lpCaption = "Radiant", guint32 uType = MB_OK, const char* URL = NULL);
+// NOTE: the returned filename is allocated with g_malloc and MUST be freed with g_free (both for win32 and Gtk dialogs)
+// GtkWidget *parent
+const char* file_dialog (void *parent, gboolean open, const char* title, const char* path = (char*)NULL, const char* pattern = NULL);
+
+/*!
+\fn dir_dialog, prompts for a directory
+*/
+char* WINAPI dir_dialog (void *parent, const char* title = "Choose Directory", const char* path = (char*)NULL);
+// GtkWidget *parent
+bool WINAPI color_dialog (void *parent, float *color, const char* title = "Choose Color");
+
+void dialog_button_callback (GtkWidget *widget, gpointer data);
+gint dialog_delete_callback (GtkWidget *widget, GdkEvent* event, gpointer data);
+
+void OpenURL(const char *url);
+
+void CheckMenuSplitting (GtkWidget *&menu);
+
+#endif // _GTK_MISC_H_
diff --git a/radiant/mainframe.h b/radiant/mainframe.h
index 7b2cb63f..23a42642 100644
--- a/radiant/mainframe.h
+++ b/radiant/mainframe.h
@@ -1,909 +1,909 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _MAINFRAME_H_
-#define _MAINFRAME_H_
-
-#include "xywindow.h"
-#include "texwindow.h"
-#include "zwindow.h"
-#include "camwindow.h"
-#include "watchbsp.h"
-
-#include "pluginmanager.h"
-#include "plugin.h"
-
-#include "gtkr_vector.h"
-
-#ifdef __APPLE__
-#define __toascii(c)    ((c) & 0x7f) 
-#endif
-
-const int RAD_SHIFT =   0x01;
-const int RAD_ALT =     0x02;
-const int RAD_CONTROL = 0x04;
-const int RAD_PRESS   = 0x08;
-
-struct SCommandInfo
-{
-  char* m_strCommand;
-  unsigned int   m_nKey;
-  unsigned int   m_nModifiers;
-  unsigned int m_nCommand;
-  char* m_strMenu;
-};
-
-struct SKeyInfo
-{
-  char* m_strName;
-  unsigned int m_nVKKey;
-};
-
-#define ID_FILE_NEW 0xE100
-#define ID_FILE_OPEN 0xE101
-#define ID_FILE_SAVE 0xE103
-#define ID_EDIT_UNDO 0xE12B
-#define ID_EDIT_REDO 0xE12C
-#define ID_HELP 0xE146
-#define ID_FILE_RECENT1 0xE110
-#define ID_FILE_RECENT2 0xE111
-#define ID_FILE_RECENT3 0xE112
-#define ID_FILE_RECENT4 0xE113
-
-#define IDC_BTN_FACEFIT                 1143
-#define ID_ENTITY_START                 22800
-#define ID_ENTITY_END                   32000 //leo
-//#define ID_ENTITY_END                   33500
-#define ID_VIEW_XY                      32772
-#define ID_VIEW_SIDE                    32773
-#define ID_VIEW_FRONT                   32774
-#define ID_CAMERATOGGLE                 32775
-#define ID_VIEW_CAMERATOGGLE            32776
-#define ID_BUTTON32777                  32777
-#define ID_BUTTON32778                  32778
-#define ID_TEXTURES_POPUP               32780
-#define ID_POPUP_SELECTION              32782
-#define ID_VIEW_CHANGE                  32783
-#define ID_VIEW_CAMERAUPDATE            32784
-#define ID_VIEW_CLIPPER                 32785
-#define ID_PREFS                        32786
-#define ID_TOGGLE_LOCK                  32787
-#define ID_EDIT_MAPINFO                 32788
-#define ID_EDIT_ENTITYINFO              32789
-#define ID_BRUSH_SCRIPTS                32790
-#define ID_VIEW_NEXTVIEW                32791
-#define ID_HELP_COMMANDLIST             32792
-#define ID_FILE_NEWPROJECT              32793
-#define ID_SNAPTOGRID                   32795
-#define ID_VIEW_CENTERVIEW              32796
-#define ID_SPLIT_SELECTED               32823
-#define ID_CLIP_SELECTED                32824
-#define ID_FLIP_CLIP                    32825
-#define ID_TOGGLEVIEW_YZ                32831
-#define ID_TOGGLEVIEW_XZ                32832
-#define ID_COLORS_GRIDTEXT              32833
-#define ID_COLORS_BRUSH                 32834
-#define ID_COLORS_SELECTEDBRUSH         32835
-#define ID_COLORS_CLIPPER               32836
-#define ID_COLORS_GRIDBLOCK             32837
-#define ID_COLORS_VIEWNAME              32838
-#define ID_COLOR_SETORIGINAL            32839
-#define ID_COLOR_SETQER                 32840
-#define ID_COLOR_SETBLACK               32841
-#define ID_COLOR_SETYDNAR               37001  /* ydnar */
-#define ID_BYEBYE                       32842
-#define ID_SELECT_SCALE                 32843
-#define ID_SELECT_MOUSEROTATE           32844
-#define ID_COLORS_SELECTEDBRUSH3D       32845
-#define ID_COLORS_CAMERABACK            32846
-#define ID_TEXTURE_REPLACESELECTED      32859
-#define ID_TEXTURE_REPLACEALL           32860
-#define ID_SELECT_MOUSESCALE            32866
-#define ID_SCALELOCKX                   32867
-#define ID_SCALELOCKY                   32868
-#define ID_SCALELOCKZ                   32869
-#define ID_VIEW_CUBICCLIPPING           32870
-#define ID_FILE_PROJECTSETTINGS         32875
-#define ID_VIEW_CUBEOUT                 32876
-#define ID_VIEW_CUBEIN                  32877
-#define ID_NODES_LOADNODES              32878
-#define ID_NODES_SHOWNODES              32879
-#define ID_NODES_SHOWLINKS              32880
-#define ID_NODES_REMOVEALLNODES         32881
-#define ID_NODES_COUNTNODES             32882
-#define ID_NODES_GIVEMONEYTONELNO       32883
-#define ID_FILE_SAVEREGION              32887
-#define ID_FILE_LOADREGION              32888
-#define ID_SELECTION_MOVEDOWN           32890
-#define ID_TOOLBAR_MAIN                 32891
-#define ID_SELECTION_MOVEUP             32892
-//#define ID_TOOLBAR_TEXTURE              32892
-#define ID_BRUSH_MAKECONE               32896
-#define ID_TEXTURES_LOAD                32897
-#define ID_TOGGLE_ROTATELOCK            32898
-#define ID_FILE_IMPORTMAP               32911
-#define ID_FILE_EXPORTMAP               32912
-#define ID_EDIT_LOADPREFAB              32913
-#define ID_SELECTION_SELECT_NUDGELEFT   32916
-#define ID_SELECTION_SELECT_NUDGERIGHT  32917
-#define ID_SELECTION_SELECT_NUDGEUP     32918
-#define ID_SELECTION_SELECT_NUDGEDOWN   32919
-#define ID_TEXTURES_LOADLIST            32920
-#define ID_DONTSELECTCURVE              32923
-#define ID_CONVERTCURVES                32924
-#define ID_PATCH_SHOWBOUNDINGBOX        32926
-#define ID_CURVE_SIMPLEPATCHMESH        32927
-#define ID_PATCH_WIREFRAME              32928
-#define ID_PATCH_WELD                   32929
-#define ID_CURVE_PATCHTUBE              32930
-#define ID_CURVE_PATCHCONE              32931
-#define ID_CURVE_PATCHENDCAP            32932
-#define ID_CURVE_PATCHBEVEL             32933
-#define ID_PATCH_DRILLDOWN              32936
-#define ID_CURVE_LOADPATCHFILE          32937
-#define ID_CURVE_INSERTROW              32938
-#define ID_CURVE_INSERTCOLUMN           32939
-#define ID_CURVE_DELETEROW              32940
-#define ID_CURVE_DELETECOLUMN           32941
-#define ID_BUTTON32942                  32942
-//#define ID_PATCH_INSDEL                 32942
-#define ID_CURVE_INSERT_ADDCOLUMN       32943
-#define ID_CURVE_INSERT_INSERTCOLUMN    32944
-#define ID_CURVE_INSERT_ADDROW          32945
-#define ID_CURVE_INSERT_INSERTROW       32946
-#define ID_CURVE_DELETE_FIRSTCOLUMN     32947
-#define ID_CURVE_DELETE_LASTCOLUMN      32948
-#define ID_CURVE_DELETE_FIRSTROW        32949
-#define ID_CURVE_DELETE_LASTROW         32950
-#define ID_CURVE_NEGATIVE               32951
-#define ID_PATCH_BEND                   32952
-#define ID_CURVE_PATCHDENSETUBE         32955
-#define ID_CURVE_PATCHVERYDENSETUBE     32956
-#define ID_CURVE_CAP                    32957
-#define ID_CURVE_REDISPERSE_ROWS        32961
-#define ID_PATCH_NATURALIZE             32963
-#define ID_CURVE_PATCHSQUARE            32964
-#define ID_BRUSH_PRIMITIVES_SPHERE      32965
-#define ID_BRUSH_PRIMITIVES_TORUS       32966
-#define ID_TEXTURES_TEXTUREWINDOWSCALE_200 32967
-#define ID_TEXTURES_TEXTUREWINDOWSCALE_100 32968
-#define ID_TEXTURES_TEXTUREWINDOWSCALE_50 32969
-#define ID_TEXTURES_TEXTUREWINDOWSCALE_25 32970
-#define ID_TEXTURES_TEXTUREWINDOWSCALE_10 32971
-#define ID_CURVE_NEGATIVETEXTUREX       32972
-#define ID_TEXTURES_FLUSH               32973
-#define ID_CURVE_OVERLAY_SET            32974
-#define ID_CURVE_OVERLAY_CLEAR          32975
-#define ID_CURVE_NEGATIVETEXTUREY       32976
-#define ID_CURVE_THICKEN                32977
-#define ID_CURVE_CYCLECAP               32978
-#define ID_CURVE_MATRIX_TRANSPOSE       32981
-#define ID_PLUGINS_REFRESH              32982
-#define ID_TEXTURES_RELOADSHADERS       32983
-#define ID_VIEW_ENTITIESAS_BOUNDINGBOX  32984
-#define ID_VIEW_ENTITIESAS_WRITEFRAME   32985
-#define ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME 32986
-#define ID_VIEW_ENTITIESAS_SELECTEDSKINNED 32987
-#define ID_VIEW_ENTITIESAS_SKINNED      32988
-#define ID_VIEW_ENTITIESAS_SKINNEDANDBOXED 32989
-#define ID_SHOW_ENTITIES                32990
-#define ID_VIEW_ENTITIESAS_WIREFRAME    32991
-#define ID_VIEW_OPENGLLIGHTING          32998
-#define ID_EDIT_SAVEPREFAB              33001
-#define ID_CURVE_MOREENDCAPSBEVELS_SQUAREENDCAP 33002
-#define ID_CURVE_MOREENDCAPSBEVELS_SQUAREBEVEL 33003
-#define ID_CURVE_PRIMITIVES_SPHERE      33005
-#define ID_VIEW_HIDESHOW_HIDESELECTED   33006
-#define ID_VIEW_HIDESHOW_SHOWHIDDEN     33007
-#define ID_TEXTURES_SHADERS_SHOW        33008
-//#define ID_SELECTION_CSGADD             33009
-#define ID_SELECTION_CSGMERGE           33011
-#define ID_TEXTURES_FLUSH_UNUSED        33014
-#define ID_DROP_GROUP_REMOVE            33016
-#define ID_DROP_GROUP_ADDTO_WORLD       33017
-#define ID_DROP_GROUP_NEWGROUP          33018
-#define ID_DROP_GROUP_NAME              33019
-#define ID_DROP_GROUP_ADDTO             33020
-#define ID_VIEW_SHOWANGLES              33021
-#define ID_VIEW_SHOWWORKZONE            33022
-#define ID_TEXTURE_FLUSH                33023
-#define ID_TEXTURES_SHOWSHADERS         33025
-#define ID_DONTSELECTMODEL              33027
-#define ID_TEXTURES_SHADERLISTONLY      33030
-#define ID_PLUGIN_START                 33800
-#define ID_PLUGIN_END                   33999
-#define ID_FILE_EXIT                    40002
-#define ID_FILE_SAVEAS                  40004
-#define ID_VIEW_CENTER                  40005
-#define ID_VIEW_UPFLOOR                 40006
-#define ID_VIEW_DOWNFLOOR               40007
-#define ID_BRUSH_FLIPX                  40008
-#define ID_BRUSH_FLIPY                  40009
-#define ID_BRUSH_FLIPZ                  40010
-#define ID_BRUSH_ROTATEX                40011
-#define ID_BRUSH_ROTATEY                40012
-#define ID_BRUSH_ROTATEZ                40013
-#define ID_BSP_FULLVIS                  40016
-#define ID_BSP_FASTVIS                  40017
-#define ID_BSP_NOVIS                    40018
-#define ID_BSP_RELIGHT                  40019
-#define ID_BSP_ENTITIES                 40020
-#define ID_FILE_POINTFILE               40021
-#define ID_VIEW_100                     40022
-#define ID_VIEW_75                      40023
-#define ID_VIEW_50                      40024
-#define ID_VIEW_25                      40025
-#define ID_VIEW_12                      40026
-#define ID_TEXTURES_SHOWALL             40033
-#define ID_TEXTURES_SHOWINUSE           40034
-#define ID_TEXTURES_TOGGLEVIEW          40037
-#define ID_SELECTION_CREATEENTITY       40039
-#define ID_SELECTION_EDITENTITY         40040
-#define ID_MISC_BENCHMARK               40041
-#define ID_REGION_OFF                   40043
-#define ID_REGION_SETXY                 40044
-#define ID_REGION_SETBRUSH              40045
-#define ID_SELECTION_MAKEHOLLOW         40046
-#define ID_SELECTION_SELECTPARTIALTALL  40047
-#define ID_SELECTION_SELECTCOMPLETETALL 40048
-#define ID_SELECTION_CSGSUBTRACT        40049
-#define ID_SELECTION_SELECTTOUCHING     40050
-#define ID_VIEW_NEAREST                 40052
-#define ID_VIEW_NEARESTMIPMAP           40053
-#define ID_VIEW_LINEAR                  40054
-#define ID_VIEW_BILINEAR                40055
-#define ID_VIEW_BILINEARMIPMAP          40056
-#define ID_VIEW_TRILINEAR               40057
-#define ID_TEXTURES_WIREFRAME           40058
-#define ID_TEXTURES_FLATSHADE           40059
-#define ID_VIEW_SHOWNAMES               40060
-#define ID_VIEW_ZOOMIN                  40061
-#define ID_VIEW_ZOOMOUT                 40062
-#define ID_VIEW_SHOWCOORDINATES         40063
-#define ID_VIEW_Z100                    40064
-#define ID_VIEW_ZZOOMIN                 40065
-#define ID_VIEW_ZZOOMOUT                40066
-#define ID_SELECTION_CLONE              40067
-#define ID_SELECTION_DESELECT           40068
-#define ID_SELECTION_DELETE             40069
-#define ID_BUTTON40068                  40070
-#define ID_SELECTION_DRAGVERTECIES      40074
-#define ID_SELECTION_DRAGEDGES          40075
-#define ID_REGION_SETTALLBRUSH          40076
-#define ID_SELECTION_SELECTINSIDE       40092
-#define ID_PROJECT_RELEAD               40094
-#define ID_PROJECT_CHANGE               40095
-#define ID_MISC_GAMMA                   40097
-#define ID_MISC_TEXTUREBACKGROUN        40104
-#define ID_TEXTUREBK                    40105
-#define ID_COLORS_XYBK                  40106
-#define ID_FILE_ABOUT                   40107
-#define ID_VIEW_CONSOLE                 40108
-#define ID_VIEW_ENTITY                  40109
-#define ID_VIEW_TEXTURE                 40110
-#define ID_COLORS_MAJOR                 40111
-#define ID_COLORS_MINOR                 40113
-#define ID_SELECTION_CONNECT            40114
-#define ID_FILE_LOADPROJECT             40115
-#define ID_MISC_FINDBRUSH               40116
-#define ID_MISC_NEXTLEAKSPOT            40117
-#define ID_MISC_PREVIOUSLEAKSPOT        40118
-#define ID_BRUSH_3SIDED                 40119
-#define ID_BRUSH_4SIDED                 40120
-#define ID_BRUSH_5SIDED                 40121
-#define ID_BRUSH_6SIDED                 40122
-#define ID_BRUSH_7SIDED                 40123
-#define ID_BRUSH_8SIDED                 40124
-#define ID_BRUSH_9SIDED                 40125
-#define ID_SELECTION_ARBITRARYROTATION  40126
-#define ID_BRUSH_ARBITRARYSIDED         40127
-#define ID_SELECTION_UNGROUPENTITY      40130
-#define ID_MISC_SELECTENTITYCOLOR       40131
-#define ID_MISC_PRINTXY                 40132
-#define ID_HELP_ABOUT                   40134
-#define ID_EDIT_COPYBRUSH               40135
-#define ID_EDIT_PASTEBRUSH              40136
-#define ID_TEXTURES_INSPECTOR           40137
-#define ID_SELECTION_MAKE_DETAIL        40139
-#define ID_SELECTION_MAKE_STRUCTURAL    40140
-#define ID_REGION_SETSELECTION          40141
-#define ID_VIEW_SHOWBLOCKS              40142
-#define ID_CAMERA_UP                    40152
-#define ID_CAMERA_DOWN                  40153
-#define ID_CAMERA_LEFT                  40154
-#define ID_CAMERA_RIGHT                 40155
-#define ID_CAMERA_FORWARD               40156
-#define ID_CAMERA_BACK                  40157
-#define ID_CAMERA_ANGLEUP               40158
-#define ID_CAMERA_ANGLEDOWN             40159
-#define ID_CAMERA_STRAFELEFT            40160
-#define ID_CAMERA_STRAFERIGHT           40161
-#define ID_GRID_TOGGLE                  40162
-#define ID_ENTITYLIST                   40163
-#define ID_MAPINFO                      40164
-#define ID_TOGGLECONSOLE                40165
-#define ID_TOGGLECAMERA                 40166
-#define ID_TOGGLEZ                      40167
-#define ID_TOGGLEVIEW                   40168
-#define ID_SELECTION_TEXTURE_FIT        40171
-#define ID_SELECTION_TEXTURE_ROTATECLOCK 40172
-#define ID_SELECTION_TEXTURE_ROTATECOUNTER 40173
-#define ID_SELECTION_TEXTURE_SCALEUP    40174
-#define ID_SELECTION_TEXTURE_SCALEDOWN  40175
-#define ID_SELECTION_TEXTURE_SHIFTLEFT  40176
-#define ID_SELECTION_TEXTURE_SHIFTRIGHT 40177
-#define ID_SELECTION_TEXTURE_SHIFTUP    40178
-#define ID_SELECTION_TEXTURE_SHIFTDOWN  40179
-#define ID_GRID_NEXT                    40180
-#define ID_GRID_PREV                    40181
-#define ID_SELECTION_TEXTURE_SCALELEFT  40182
-#define ID_SELECTION_TEXTURE_SCALERIGHT 40183
-#define ID_SELECTION_PRINT              40184
-#define ID_SELECTION_TOGGLESIZEPAINT    40185
-#define ID_PATCH_TAB                    40186
-#define ID_PATCH_ENTER                  40187
-#define ID_SELECT_SNAPTOGRID            40188
-#define ID_PATCH_INSPECTOR              40189
-#define ID_SELECT_ALL                   40190
-#define ID_CURVE_FREEZE                 40191
-#define ID_CURVE_UNFREEZE               40192
-#define ID_CURVE_UNFREEZEALL            40193
-#define ID_SELECT_RESELECT              40194
-#define ID_FITFACE                      40196
-#define ID_VIEW_CROSSHAIR               40197
-#define ID_SELECTION_INVERT             40198
-#define ID_VIEW_GROUPS                  40199
-#define ID_FILE_SLEEP                   40200
-#define ID_HELP_LINKS                   40201
-#define ID_VIEW_SHOWOUTLINE             40202 // TTimo: outline as in colored outline around the window to quickly guess the orientation
-#define ID_VIEW_SHOWAXES                40203
-#define ID_SELECTION_NOOUTLINE          40204 // TTimo: outline as in zbuffered outline toggle on camera view (TA Q3Radiant 200f addition)
-#define ID_SELECTION_OUTLINESTYLE       40205 // Arnout: cycles through selection styles (extended 'nooutline')
-#define ID_SELECTION_SEPERATE           40206 // TTimo: split brushes out of an entity back into worldspawn
-#define ID_SELECTION_MERGE              40207 // TTimo: merge brushes from worldspawn into entity
-#define ID_HELP_BUGREPORT               40208
-
-#define ID_FILTER_WORLD                 40209
-#define ID_FILTER_PATCHES               40210
-#define ID_FILTER_DETAILS               40211
-#define ID_FILTER_ENTITIES              40212
-#define ID_FILTER_MODELS                40213
-#define ID_FILTER_HINTSSKIPS            40214
-#define ID_FILTER_CLIPS                 40215
-#define ID_FILTER_LIQUIDS               40216
-#define ID_FILTER_TRIGGERS              40217
-#define ID_FILTER_AREAPORTALS           40218
-#define ID_FILTER_TRANSLUCENT           40219
-#define ID_FILTER_CAULK                 40220
-#define ID_FILTER_LIGHTS                40221
-#define ID_FILTER_PATHS                 40223
-#define ID_FILTER_CLUSTERPORTALS        40224
-#define ID_FILTER_LIGHTGRID             40225
-#define ID_FILTER_STRUCTURAL            40226
-#define ID_FILTER_BOTCLIPS							40227
-
-#define ID_CURVE_REDISPERSE_INTERMEDIATE_COLS	40230
-#define ID_CURVE_REDISPERSE_INTERMEDIATE_ROWS	40231
-#define ID_EDIT_PASTEBRUSHTOCAMERA      40232
-
-#define ID_COLORS_MINOR_ALT             40230
-#define ID_COLORS_MAJOR_ALT             40231
-
-// those must have their own ID chunk ID_GRID_025 <= ID_GRID <= ID_GRID_256
-#define ID_GRID_025                     40300
-#define ID_GRID_05                      40301
-#define ID_GRID_1                       40302
-#define ID_GRID_2                       40303
-#define ID_GRID_4                       40304
-#define ID_GRID_8                       40305
-#define ID_GRID_16                      40306
-#define ID_GRID_32                      40307
-#define ID_GRID_64                      40308
-#define ID_GRID_128                     40309
-#define ID_GRID_256                     40310
-
-#define ID_FILE_CHECKUPDATE             40320
-
-#define ID_TEXTUREWINDOW_SCALEUP        40321
-#define ID_TEXTUREWINDOW_SCALEDOWN      40322
-
-class CSynapseClientRadiant : public CSynapseClient
-{
-public:
-  bool RequestAPI(APIDescriptor_t *pAPI);
-  const char* GetInfo();
-  const char* GetName();
-      
-  void ImportMap(IDataStream *in, CPtrArray *ents, const char *type);
-  void ExportMap(CPtrArray *ents, IDataStream *out, const char *type);
-
-  CSynapseClientRadiant() { }
-  virtual ~CSynapseClientRadiant() { }
-};  
-
-class MainFrame
-{
-public:
-  enum EViewStyle
-  {
-    eRegular,
-    eFloating,
-    eSplit,
-    eRegularLeft,
-  };
-
-  MainFrame();
-  GtkWidget *m_pWidget;
-
-  /*!
-  called to fire up the help links
-  */
-  void handle_help_command(int id);
-
-protected:
-
-  /*!
-  the urls to fire up in the game packs help menus
-  */
-  vector<Str *> mHelpURLs;
-
-  /*!
-  scan the .game files for game install packs
-  look there for help description nodes
-  build the corresponding menus in Radiant
-  */
-  void create_game_help_menu (GtkWidget *menu, GtkAccelGroup *accel);
-
-  /*!
-  build the menu once the filename is found
-  */
-  void process_xlink (Str &FileName, char *menu_name, const char *base_url, GtkWidget *menu, GtkAccelGroup *accel);
-
-  void Create ();
-  void create_main_menu (GtkWidget *window, GtkWidget *vbox);
-  void create_main_toolbar (GtkWidget *window, GtkWidget *vbox);
-  void create_plugin_toolbar (GtkWidget *window, GtkWidget *vbox);
-  void create_main_statusbar (GtkWidget *window, GtkWidget *vbox);
-  GtkWidget *m_pStatusLabel[6];
-  GtkWidget *m_pSplits[4];
-  XYWnd* m_pXYWnd;
-  XYWnd* m_pYZWnd;
-  XYWnd* m_pXZWnd;
-  CamWnd* m_pCamWnd;
-  TexWnd* m_pTexWnd;
-  ZWnd* m_pZWnd;
-  CWatchBSP* m_pWatchBSP;
-
-  XYWnd* m_pActiveXY;
-  bool m_bCamPreview;
-  CPlugInManager m_PlugInMgr;
-  int m_nNextPlugInID;
-  guint m_nTimer;
-  bool m_bSleeping;
-
-  CString m_strStatus[15];
-  bool m_bNeedStatusUpdate;
-
-  /*!
-  synapse server
-  deals with dynamically loading the modules, initializing them, requesting the APIs
-  */
-  CSynapseServer m_SynapseServer;
-  /*!
-  we are also a synapse client in that we provide and require some APIs as well
-  */
-  CSynapseClientRadiant m_SynapseClient;
-
-public:
-
-  // BSP window
-  // trigger network listen
-  void DoWatchBSP();
-  bool IsSleeping ()
-    { return m_bSleeping; }
-
-  void UpdatePatchToolbarButtons();
-  // Gef: Changed to float for sub-integer grid size
-  void NudgeSelection(int nDirection, float nAmount);
-  void SetButtonMenuStates();
-  void SetGridStatus();
-  void RoutineProcessing();
-  XYWnd* ActiveXY() { return m_pActiveXY; };
-  void UpdateWindows(int nBits);
-  void SetStatusText(int nPane, const char* pText);
-  void UpdateStatusText();
-  void SetWindowStyle(int nStyle);
-  virtual ~MainFrame();
-  XYWnd* GetXYWnd() {return m_pXYWnd;}
-  XYWnd* GetXZWnd() {return m_pXZWnd;}
-  XYWnd* GetYZWnd() {return m_pYZWnd;}
-  ZWnd* GetZWnd() {return m_pZWnd;}
-  CamWnd* GetCamWnd() {return m_pCamWnd;}
-  TexWnd* GetTexWnd() {return m_pTexWnd;}
-  CWatchBSP *GetWatchBSP() { return m_pWatchBSP; }
-  void ReleaseContexts ();
-  void CreateContexts ();
-
-  void SetActiveXY(XYWnd* p) 
-  {
-    if (m_pActiveXY)
-      m_pActiveXY->SetActive(false);
-
-    m_pActiveXY = p;
-
-    if (m_pActiveXY)
-      m_pActiveXY->SetActive(true);
-
-  };
-
-  EViewStyle CurrentStyle()
-  {
-    return m_nCurrentStyle;
-  };
-
-  bool FloatingGroupDialog()
-  {
-    return CurrentStyle() == eFloating || CurrentStyle() == eSplit;
-  };
-
-#ifdef _WIN32
-  const GdkRectangle & GetPrimaryMonitorRect( void ) const { return primaryMonitorRect; }
-  const int GetGDKOffsetX( void ) const { return gdk_offset_x; }
-  const int GetGDKOffsetY( void ) const { return gdk_offset_y; }
-#endif
-
-protected:
-  bool m_bDoLoop;
-  bool m_bSplittersOK;
-  void CreateQEChildren();
-  void LoadCommandMap();
-  void ShowMenuItemKeyBindings(GtkWidget* window);
-
-public:
-  void Copy();
-  void Paste();
-  void Nudge(int nDim, float fNudge);
-  CPlugInManager &GetPlugInMgr() {return m_PlugInMgr;};
-  CSynapseServer &GetSynapseServer() {return m_SynapseServer;};
-  CSynapseClientRadiant &GetSynapseClient() {return m_SynapseClient;};
-  void AddPlugInToolbarButton(const IToolbarButton* button);
-  void AddPlugInMenuItem(IPlugIn* pPlugIn);
-  void CleanPlugInMenu();
-
-  // these are public so i can easily reflect messages
-  // from child windows..
-  void OnTimer();
-  void OnDelete();
-  void OnDestroy();
-  void ToggleCamera();
-
-  void OnFileExit();
-  void OnFileLoadproject();
-  void OnFileNew();
-  void OnFileOpen();
-  void OnFilePointfile();
-  void OnFileSave();
-  void OnFileSaveas();
-  void OnFileCheckUpdate();
-  void OnView100();
-  void OnViewCenter();
-  void OnViewConsole();
-  void OnViewDownfloor();
-  void OnViewEntity();
-  void OnViewFront();
-  void OnViewShowblocks();
-  void OnViewShowclip();
-  void OnViewShowcoordinates();
-  void OnViewShowOutline();
-  void OnViewShowAxes();
-  void OnViewShowdetail();
-  void OnViewShowent();
-  void OnViewShowlights();
-  void OnViewShownames();
-  void OnViewShowpath();
-  void OnViewShowwater();
-  void OnViewShowworld();
-  void OnViewTexture();
-  void OnViewUpfloor();
-  void OnViewXy();
-  void OnViewZ100();
-  void OnViewZoomin();
-  void OnViewZoomout();
-  void OnViewZzoomin();
-  void OnViewZzoomout();
-  void OnViewSide();
-  void OnTexturesShowinuse();
-  void OnTexturesInspector();
-  void OnMiscBenchmark();
-  void OnMiscFindbrush();
-  void OnMiscGamma();
-  void OnMiscNextleakspot();
-  void OnMiscPreviousleakspot();
-  void OnMiscPrintxy();
-  void OnMiscSelectentitycolor();
-  void OnTexturebk();
-  void OnColorsMajor();
-  void OnColorsMinor();
-  void OnColorsMajor_Alt();
-  void OnColorsMinor_Alt();
-  void OnColorsXybk();
-  void OnBrush3sided();
-  void OnBrush4sided();
-  void OnBrush5sided();
-  void OnBrush6sided();
-  void OnBrush7sided();
-  void OnBrush8sided();
-  void OnBrush9sided();
-  void OnBrushArbitrarysided();
-  void OnBrushFlipx();
-  void OnBrushFlipy();
-  void OnBrushFlipz();
-  void OnBrushRotatex();
-  void OnBrushRotatey();
-  void OnBrushRotatez();
-  void OnRegionOff();
-  void OnRegionSetbrush();
-  void OnRegionSetselection();
-  void OnRegionSettallbrush();
-  void OnRegionSetxy();
-  void OnSelectionArbitraryrotation();
-  void OnSelectionClone();
-  void OnSelectionConnect();
-  void OnSelectionCsgsubtract();
-  void OnSelectionCsgmerge();
-  void OnSelectionNoOutline();
-  void OnSelectionOutlineStyle();
-  void OnSelectionDelete();
-  void OnSelectionDeselect();
-  void OnSelectionDragedges();
-  void OnSelectionDragvertecies();
-  void OnSelectionMakeDetail();
-  void OnSelectionMakeStructural();
-  void OnSelectionMakehollow();
-  void OnSelectionSelectcompletetall();
-  void OnSelectionSelectinside();
-  void OnSelectionSelectpartialtall();
-  void OnSelectionSelecttouching();
-  void OnSelectionUngroupentity();
-  void OnSelectionMergeentity();
-  void OnSelectionGroupworld();
-  void OnTexturesPopup();
-  void OnPopupSelection();
-  void OnViewChange();
-  void OnViewCameraupdate();
-  void OnHelpAbout();
-  void OnHelp();
-  void OnHelpLinks();
-  void OnHelpBugreport();
-  void OnViewClipper();
-  void OnCameraAngledown();
-  void OnCameraAngleup();
-  void OnCameraBack(bool keydown);
-  void OnCameraDown();
-  void OnCameraForward(bool keydown);
-  void OnCameraLeft(bool keydown);
-  void OnCameraRight(bool keydown);
-  void OnCameraStrafeleft(bool keydown);
-  void OnCameraStraferight(bool keydown);
-  void OnCameraUp();
-  void OnGridToggle();
-  void OnPrefs();
-  void OnTogglecamera();
-  void OnToggleconsole();
-  void OnToggleview();
-  void OnTogglez();
-  void OnToggleLock();
-  void OnEditMapinfo();
-  void OnEditEntityinfo();
-  void OnBrushScripts();
-  void OnViewCenterview();
-  void OnViewNextview();
-  void OnHelpCommandlist();
-  void OnFileNewproject();
-  void OnFlipClip();
-  void OnClipSelected();
-  void OnSplitSelected();
-  void OnToggleviewXz();
-  void OnToggleviewYz();
-  void OnColorsBrush();
-  void OnColorsClipper();
-  void OnColorsGridtext();
-  void OnColorsSelectedbrush();
-  void OnColorsSelectedbrush3D();
-  void OnColorsCameraBack();
-  void OnColorsGridblock();
-  void OnColorsViewname();
-  void OnColorSetoriginal();
-  void OnColorSetqer();
-  void OnColorSetblack();
-  void OnColorSetydnar();  /* ydnar */
-  void OnSnaptogrid();
-  void OnSelectScale();
-  void OnSelectMouserotate();
-  void OnEditCopybrush();
-  void OnEditPastebrush();
-  void OnEditPastebrushToCamera();
-  void OnEditUndo();
-  void OnEditRedo();
-  void OnSelectionInvert();
-//  void OnSelectionTextureDec();
-  void OnSelectionTextureFit();
-//  void OnSelectionTextureInc();
-  void OnSelectionTextureRotateclock();
-  void OnSelectionTextureRotatecounter();
-  void OnSelectionTextureScaledown();
-  void OnSelectionTextureScaleup();
-  void OnSelectionTextureShiftdown();
-  void OnSelectionTextureShiftleft();
-  void OnSelectionTextureShiftright();
-  void OnSelectionTextureShiftup();
-  void OnGridNext();
-  void OnGridPrev();
-  void OnSelectionTextureScaleLeft();
-  void OnSelectionTextureScaleRight();
-  void OnTextureReplaceall();
-  void OnScalelockx();
-  void OnScalelocky();
-  void OnScalelockz();
-  void OnSelectMousescale();
-  void OnViewCubicclipping();
-  void OnFileProjectsettings();
-  void OnViewCubein();
-  void OnViewCubeout();
-  void OnFileSaveregion();
-  void OnSelectionMovedown();
-  void OnSelectionMoveup();
-  void OnToolbarMain();
-  void OnToolbarTexture();
-  void OnSelectionPrint();
-  void OnSelectionTogglesizepaint();
-  void OnBrushMakecone();
-  void OnTexturesLoad();
-  void OnToggleRotatelock();
-  void OnFileImportmap();
-  void OnFileExportmap();
-  void OnEditLoadprefab();
-  void OnSelectionSelectNudgedown();
-  void OnSelectionSelectNudgeleft();
-  void OnSelectionSelectNudgeright();
-  void OnSelectionSelectNudgeup();
-  void OnTexturesLoadlist();
-  void OnDontselectcurve();
-  void OnConvertcurves();
-  void OnCurveSimplepatchmesh();
-  void OnPatchToggleBox();
-  void OnPatchWireframe();
-  void OnCurvePatchcone();
-  void OnCurvePatchtube();
-  void OnPatchWeld();
-  void OnCurvePatchbevel();
-  void OnCurvePatchendcap();
-  void OnPatchDrilldown();
-  void OnCurveInsertcolumn();
-  void OnCurveInsertrow();
-  void OnCurveDeletecolumn();
-  void OnCurveDeleterow();
-  void OnCurveInsertAddcolumn();
-  void OnCurveInsertAddrow();
-  void OnCurveInsertInsertcolumn();
-  void OnCurveInsertInsertrow();
-  void OnCurveNegative();
-  void OnCurveNegativeTextureX();
-  void OnCurveNegativeTextureY();
-  void OnCurveDeleteFirstcolumn();
-  void OnCurveDeleteFirstrow();
-  void OnCurveDeleteLastcolumn();
-  void OnCurveDeleteLastrow();
-  void OnPatchBend();
-//  void OnPatchInsdel();
-  void OnPatchEnter();
-  void OnPatchTab();
-  void OnCurvePatchdensetube();
-  void OnCurvePatchverydensetube();
-  void OnCurveCap();
-  void OnCurveCapInvertedbevel();
-  void OnCurveCapInvertedendcap();
-  void OnCurveRedisperseRows();
-  void OnCurveRedisperseIntermediateCols();
-  void OnCurveRedisperseIntermediateRows();
-  void OnPatchNaturalize();
-  void OnSnapToGrid();
-  void OnCurvePatchsquare();
-  void OnTexturewindowScaleup();
-  void OnTexturewindowScaledown();
-  void OnCurveOverlayClear();
-  void OnCurveOverlaySet();
-  void OnCurveThicken();
-  void OnCurveCyclecap();
-  void OnCurveMatrixTranspose();
-  void OnTexturesReloadshaders();
-  void OnShowEntities();
-  // will set the view mode right, don't set the value for mode if you only want to update the radio item
-  void OnEntitiesSetViewAs(int mode = 0);
-  void OnPluginsRefresh();
-  void OnTexturesShowall();
-  void OnPatchInspector();
-  void OnViewOpengllighting();
-  void OnSelectAll();
-  void OnCurveFreeze();
-  void OnCurveUnFreeze();
-  void OnCurveUnFreezeAll();
-  void OnSelectReselect();
-  void OnEditSaveprefab();
-  void OnCurveMoreendcapsbevelsSquarebevel();
-  void OnCurveMoreendcapsbevelsSquareendcap();
-  void OnBrushPrimitivesSphere();
-  void OnViewCrosshair();
-  void OnViewHideshowHideselected();
-  void OnViewHideshowShowhidden();
-  void OnTexturesShadersShow();
-  void OnViewGroups();
-  void OnDropGroupAddtoWorld();
-  void OnDropGroupName();
-  void OnDropGroupNewgroup();
-  void OnDropGroupRemove();
-  void OnViewShowWorkzone();
-  void OnViewShowAngles();
-  void OnMru(unsigned int nID);
-  void OnViewNearest(unsigned int nID);
-  void OnTextureWad(unsigned int nID);
-  void OnBspCommand(unsigned int nID);
-  void OnGrid(unsigned int nID);
-  void OnPlugIn(unsigned int nID, char *str);
-  void OnFaceFit();
-  void SetTextureScale(int id);
-  void OnDontselectmodel();
-  void OnTexturesShaderlistonly();
-  void OnSleep();
-  void OnFilterAreaportals();
-  void OnFilterCaulk();
-  void OnFilterStructural();
-  void OnFilterClips();
-  void OnFilterBotClips();
-  void OnFilterDetails();
-  void OnFilterEntities();
-  void OnFilterHintsskips();
-  void OnFilterLights();
-  void OnFilterLiquids();
-  void OnFilterModels();
-  void OnFilterPatches();
-  void OnFilterTranslucent();
-  void OnFilterTriggers();
-  void OnFilterWorld();
-  void OnFilterPaths();
-  void OnFilterClusterportals();
-  void OnFilterLightgrid();
-
-private:
-  EViewStyle m_nCurrentStyle;
-
-#ifdef _WIN32
-  GdkRectangle primaryMonitorRect;
-  int gdk_offset_x;
-  int gdk_offset_y;
-#endif
-
-};
-
-// some C API to the mainframe functions
-void WINAPI QERApp_Sleep();
-
-#endif // _MAINFRAME_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _MAINFRAME_H_
+#define _MAINFRAME_H_
+
+#include "xywindow.h"
+#include "texwindow.h"
+#include "zwindow.h"
+#include "camwindow.h"
+#include "watchbsp.h"
+
+#include "pluginmanager.h"
+#include "plugin.h"
+
+#include "gtkr_vector.h"
+
+#ifdef __APPLE__
+#define __toascii(c)    ((c) & 0x7f) 
+#endif
+
+const int RAD_SHIFT =   0x01;
+const int RAD_ALT =     0x02;
+const int RAD_CONTROL = 0x04;
+const int RAD_PRESS   = 0x08;
+
+struct SCommandInfo
+{
+  char* m_strCommand;
+  unsigned int   m_nKey;
+  unsigned int   m_nModifiers;
+  unsigned int m_nCommand;
+  char* m_strMenu;
+};
+
+struct SKeyInfo
+{
+  char* m_strName;
+  unsigned int m_nVKKey;
+};
+
+#define ID_FILE_NEW 0xE100
+#define ID_FILE_OPEN 0xE101
+#define ID_FILE_SAVE 0xE103
+#define ID_EDIT_UNDO 0xE12B
+#define ID_EDIT_REDO 0xE12C
+#define ID_HELP 0xE146
+#define ID_FILE_RECENT1 0xE110
+#define ID_FILE_RECENT2 0xE111
+#define ID_FILE_RECENT3 0xE112
+#define ID_FILE_RECENT4 0xE113
+
+#define IDC_BTN_FACEFIT                 1143
+#define ID_ENTITY_START                 22800
+#define ID_ENTITY_END                   32000 //leo
+//#define ID_ENTITY_END                   33500
+#define ID_VIEW_XY                      32772
+#define ID_VIEW_SIDE                    32773
+#define ID_VIEW_FRONT                   32774
+#define ID_CAMERATOGGLE                 32775
+#define ID_VIEW_CAMERATOGGLE            32776
+#define ID_BUTTON32777                  32777
+#define ID_BUTTON32778                  32778
+#define ID_TEXTURES_POPUP               32780
+#define ID_POPUP_SELECTION              32782
+#define ID_VIEW_CHANGE                  32783
+#define ID_VIEW_CAMERAUPDATE            32784
+#define ID_VIEW_CLIPPER                 32785
+#define ID_PREFS                        32786
+#define ID_TOGGLE_LOCK                  32787
+#define ID_EDIT_MAPINFO                 32788
+#define ID_EDIT_ENTITYINFO              32789
+#define ID_BRUSH_SCRIPTS                32790
+#define ID_VIEW_NEXTVIEW                32791
+#define ID_HELP_COMMANDLIST             32792
+#define ID_FILE_NEWPROJECT              32793
+#define ID_SNAPTOGRID                   32795
+#define ID_VIEW_CENTERVIEW              32796
+#define ID_SPLIT_SELECTED               32823
+#define ID_CLIP_SELECTED                32824
+#define ID_FLIP_CLIP                    32825
+#define ID_TOGGLEVIEW_YZ                32831
+#define ID_TOGGLEVIEW_XZ                32832
+#define ID_COLORS_GRIDTEXT              32833
+#define ID_COLORS_BRUSH                 32834
+#define ID_COLORS_SELECTEDBRUSH         32835
+#define ID_COLORS_CLIPPER               32836
+#define ID_COLORS_GRIDBLOCK             32837
+#define ID_COLORS_VIEWNAME              32838
+#define ID_COLOR_SETORIGINAL            32839
+#define ID_COLOR_SETQER                 32840
+#define ID_COLOR_SETBLACK               32841
+#define ID_COLOR_SETYDNAR               37001  /* ydnar */
+#define ID_BYEBYE                       32842
+#define ID_SELECT_SCALE                 32843
+#define ID_SELECT_MOUSEROTATE           32844
+#define ID_COLORS_SELECTEDBRUSH3D       32845
+#define ID_COLORS_CAMERABACK            32846
+#define ID_TEXTURE_REPLACESELECTED      32859
+#define ID_TEXTURE_REPLACEALL           32860
+#define ID_SELECT_MOUSESCALE            32866
+#define ID_SCALELOCKX                   32867
+#define ID_SCALELOCKY                   32868
+#define ID_SCALELOCKZ                   32869
+#define ID_VIEW_CUBICCLIPPING           32870
+#define ID_FILE_PROJECTSETTINGS         32875
+#define ID_VIEW_CUBEOUT                 32876
+#define ID_VIEW_CUBEIN                  32877
+#define ID_NODES_LOADNODES              32878
+#define ID_NODES_SHOWNODES              32879
+#define ID_NODES_SHOWLINKS              32880
+#define ID_NODES_REMOVEALLNODES         32881
+#define ID_NODES_COUNTNODES             32882
+#define ID_NODES_GIVEMONEYTONELNO       32883
+#define ID_FILE_SAVEREGION              32887
+#define ID_FILE_LOADREGION              32888
+#define ID_SELECTION_MOVEDOWN           32890
+#define ID_TOOLBAR_MAIN                 32891
+#define ID_SELECTION_MOVEUP             32892
+//#define ID_TOOLBAR_TEXTURE              32892
+#define ID_BRUSH_MAKECONE               32896
+#define ID_TEXTURES_LOAD                32897
+#define ID_TOGGLE_ROTATELOCK            32898
+#define ID_FILE_IMPORTMAP               32911
+#define ID_FILE_EXPORTMAP               32912
+#define ID_EDIT_LOADPREFAB              32913
+#define ID_SELECTION_SELECT_NUDGELEFT   32916
+#define ID_SELECTION_SELECT_NUDGERIGHT  32917
+#define ID_SELECTION_SELECT_NUDGEUP     32918
+#define ID_SELECTION_SELECT_NUDGEDOWN   32919
+#define ID_TEXTURES_LOADLIST            32920
+#define ID_DONTSELECTCURVE              32923
+#define ID_CONVERTCURVES                32924
+#define ID_PATCH_SHOWBOUNDINGBOX        32926
+#define ID_CURVE_SIMPLEPATCHMESH        32927
+#define ID_PATCH_WIREFRAME              32928
+#define ID_PATCH_WELD                   32929
+#define ID_CURVE_PATCHTUBE              32930
+#define ID_CURVE_PATCHCONE              32931
+#define ID_CURVE_PATCHENDCAP            32932
+#define ID_CURVE_PATCHBEVEL             32933
+#define ID_PATCH_DRILLDOWN              32936
+#define ID_CURVE_LOADPATCHFILE          32937
+#define ID_CURVE_INSERTROW              32938
+#define ID_CURVE_INSERTCOLUMN           32939
+#define ID_CURVE_DELETEROW              32940
+#define ID_CURVE_DELETECOLUMN           32941
+#define ID_BUTTON32942                  32942
+//#define ID_PATCH_INSDEL                 32942
+#define ID_CURVE_INSERT_ADDCOLUMN       32943
+#define ID_CURVE_INSERT_INSERTCOLUMN    32944
+#define ID_CURVE_INSERT_ADDROW          32945
+#define ID_CURVE_INSERT_INSERTROW       32946
+#define ID_CURVE_DELETE_FIRSTCOLUMN     32947
+#define ID_CURVE_DELETE_LASTCOLUMN      32948
+#define ID_CURVE_DELETE_FIRSTROW        32949
+#define ID_CURVE_DELETE_LASTROW         32950
+#define ID_CURVE_NEGATIVE               32951
+#define ID_PATCH_BEND                   32952
+#define ID_CURVE_PATCHDENSETUBE         32955
+#define ID_CURVE_PATCHVERYDENSETUBE     32956
+#define ID_CURVE_CAP                    32957
+#define ID_CURVE_REDISPERSE_ROWS        32961
+#define ID_PATCH_NATURALIZE             32963
+#define ID_CURVE_PATCHSQUARE            32964
+#define ID_BRUSH_PRIMITIVES_SPHERE      32965
+#define ID_BRUSH_PRIMITIVES_TORUS       32966
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_200 32967
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_100 32968
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_50 32969
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_25 32970
+#define ID_TEXTURES_TEXTUREWINDOWSCALE_10 32971
+#define ID_CURVE_NEGATIVETEXTUREX       32972
+#define ID_TEXTURES_FLUSH               32973
+#define ID_CURVE_OVERLAY_SET            32974
+#define ID_CURVE_OVERLAY_CLEAR          32975
+#define ID_CURVE_NEGATIVETEXTUREY       32976
+#define ID_CURVE_THICKEN                32977
+#define ID_CURVE_CYCLECAP               32978
+#define ID_CURVE_MATRIX_TRANSPOSE       32981
+#define ID_PLUGINS_REFRESH              32982
+#define ID_TEXTURES_RELOADSHADERS       32983
+#define ID_VIEW_ENTITIESAS_BOUNDINGBOX  32984
+#define ID_VIEW_ENTITIESAS_WRITEFRAME   32985
+#define ID_VIEW_ENTITIESAS_SELECTEDWIREFRAME 32986
+#define ID_VIEW_ENTITIESAS_SELECTEDSKINNED 32987
+#define ID_VIEW_ENTITIESAS_SKINNED      32988
+#define ID_VIEW_ENTITIESAS_SKINNEDANDBOXED 32989
+#define ID_SHOW_ENTITIES                32990
+#define ID_VIEW_ENTITIESAS_WIREFRAME    32991
+#define ID_VIEW_OPENGLLIGHTING          32998
+#define ID_EDIT_SAVEPREFAB              33001
+#define ID_CURVE_MOREENDCAPSBEVELS_SQUAREENDCAP 33002
+#define ID_CURVE_MOREENDCAPSBEVELS_SQUAREBEVEL 33003
+#define ID_CURVE_PRIMITIVES_SPHERE      33005
+#define ID_VIEW_HIDESHOW_HIDESELECTED   33006
+#define ID_VIEW_HIDESHOW_SHOWHIDDEN     33007
+#define ID_TEXTURES_SHADERS_SHOW        33008
+//#define ID_SELECTION_CSGADD             33009
+#define ID_SELECTION_CSGMERGE           33011
+#define ID_TEXTURES_FLUSH_UNUSED        33014
+#define ID_DROP_GROUP_REMOVE            33016
+#define ID_DROP_GROUP_ADDTO_WORLD       33017
+#define ID_DROP_GROUP_NEWGROUP          33018
+#define ID_DROP_GROUP_NAME              33019
+#define ID_DROP_GROUP_ADDTO             33020
+#define ID_VIEW_SHOWANGLES              33021
+#define ID_VIEW_SHOWWORKZONE            33022
+#define ID_TEXTURE_FLUSH                33023
+#define ID_TEXTURES_SHOWSHADERS         33025
+#define ID_DONTSELECTMODEL              33027
+#define ID_TEXTURES_SHADERLISTONLY      33030
+#define ID_PLUGIN_START                 33800
+#define ID_PLUGIN_END                   33999
+#define ID_FILE_EXIT                    40002
+#define ID_FILE_SAVEAS                  40004
+#define ID_VIEW_CENTER                  40005
+#define ID_VIEW_UPFLOOR                 40006
+#define ID_VIEW_DOWNFLOOR               40007
+#define ID_BRUSH_FLIPX                  40008
+#define ID_BRUSH_FLIPY                  40009
+#define ID_BRUSH_FLIPZ                  40010
+#define ID_BRUSH_ROTATEX                40011
+#define ID_BRUSH_ROTATEY                40012
+#define ID_BRUSH_ROTATEZ                40013
+#define ID_BSP_FULLVIS                  40016
+#define ID_BSP_FASTVIS                  40017
+#define ID_BSP_NOVIS                    40018
+#define ID_BSP_RELIGHT                  40019
+#define ID_BSP_ENTITIES                 40020
+#define ID_FILE_POINTFILE               40021
+#define ID_VIEW_100                     40022
+#define ID_VIEW_75                      40023
+#define ID_VIEW_50                      40024
+#define ID_VIEW_25                      40025
+#define ID_VIEW_12                      40026
+#define ID_TEXTURES_SHOWALL             40033
+#define ID_TEXTURES_SHOWINUSE           40034
+#define ID_TEXTURES_TOGGLEVIEW          40037
+#define ID_SELECTION_CREATEENTITY       40039
+#define ID_SELECTION_EDITENTITY         40040
+#define ID_MISC_BENCHMARK               40041
+#define ID_REGION_OFF                   40043
+#define ID_REGION_SETXY                 40044
+#define ID_REGION_SETBRUSH              40045
+#define ID_SELECTION_MAKEHOLLOW         40046
+#define ID_SELECTION_SELECTPARTIALTALL  40047
+#define ID_SELECTION_SELECTCOMPLETETALL 40048
+#define ID_SELECTION_CSGSUBTRACT        40049
+#define ID_SELECTION_SELECTTOUCHING     40050
+#define ID_VIEW_NEAREST                 40052
+#define ID_VIEW_NEARESTMIPMAP           40053
+#define ID_VIEW_LINEAR                  40054
+#define ID_VIEW_BILINEAR                40055
+#define ID_VIEW_BILINEARMIPMAP          40056
+#define ID_VIEW_TRILINEAR               40057
+#define ID_TEXTURES_WIREFRAME           40058
+#define ID_TEXTURES_FLATSHADE           40059
+#define ID_VIEW_SHOWNAMES               40060
+#define ID_VIEW_ZOOMIN                  40061
+#define ID_VIEW_ZOOMOUT                 40062
+#define ID_VIEW_SHOWCOORDINATES         40063
+#define ID_VIEW_Z100                    40064
+#define ID_VIEW_ZZOOMIN                 40065
+#define ID_VIEW_ZZOOMOUT                40066
+#define ID_SELECTION_CLONE              40067
+#define ID_SELECTION_DESELECT           40068
+#define ID_SELECTION_DELETE             40069
+#define ID_BUTTON40068                  40070
+#define ID_SELECTION_DRAGVERTECIES      40074
+#define ID_SELECTION_DRAGEDGES          40075
+#define ID_REGION_SETTALLBRUSH          40076
+#define ID_SELECTION_SELECTINSIDE       40092
+#define ID_PROJECT_RELEAD               40094
+#define ID_PROJECT_CHANGE               40095
+#define ID_MISC_GAMMA                   40097
+#define ID_MISC_TEXTUREBACKGROUN        40104
+#define ID_TEXTUREBK                    40105
+#define ID_COLORS_XYBK                  40106
+#define ID_FILE_ABOUT                   40107
+#define ID_VIEW_CONSOLE                 40108
+#define ID_VIEW_ENTITY                  40109
+#define ID_VIEW_TEXTURE                 40110
+#define ID_COLORS_MAJOR                 40111
+#define ID_COLORS_MINOR                 40113
+#define ID_SELECTION_CONNECT            40114
+#define ID_FILE_LOADPROJECT             40115
+#define ID_MISC_FINDBRUSH               40116
+#define ID_MISC_NEXTLEAKSPOT            40117
+#define ID_MISC_PREVIOUSLEAKSPOT        40118
+#define ID_BRUSH_3SIDED                 40119
+#define ID_BRUSH_4SIDED                 40120
+#define ID_BRUSH_5SIDED                 40121
+#define ID_BRUSH_6SIDED                 40122
+#define ID_BRUSH_7SIDED                 40123
+#define ID_BRUSH_8SIDED                 40124
+#define ID_BRUSH_9SIDED                 40125
+#define ID_SELECTION_ARBITRARYROTATION  40126
+#define ID_BRUSH_ARBITRARYSIDED         40127
+#define ID_SELECTION_UNGROUPENTITY      40130
+#define ID_MISC_SELECTENTITYCOLOR       40131
+#define ID_MISC_PRINTXY                 40132
+#define ID_HELP_ABOUT                   40134
+#define ID_EDIT_COPYBRUSH               40135
+#define ID_EDIT_PASTEBRUSH              40136
+#define ID_TEXTURES_INSPECTOR           40137
+#define ID_SELECTION_MAKE_DETAIL        40139
+#define ID_SELECTION_MAKE_STRUCTURAL    40140
+#define ID_REGION_SETSELECTION          40141
+#define ID_VIEW_SHOWBLOCKS              40142
+#define ID_CAMERA_UP                    40152
+#define ID_CAMERA_DOWN                  40153
+#define ID_CAMERA_LEFT                  40154
+#define ID_CAMERA_RIGHT                 40155
+#define ID_CAMERA_FORWARD               40156
+#define ID_CAMERA_BACK                  40157
+#define ID_CAMERA_ANGLEUP               40158
+#define ID_CAMERA_ANGLEDOWN             40159
+#define ID_CAMERA_STRAFELEFT            40160
+#define ID_CAMERA_STRAFERIGHT           40161
+#define ID_GRID_TOGGLE                  40162
+#define ID_ENTITYLIST                   40163
+#define ID_MAPINFO                      40164
+#define ID_TOGGLECONSOLE                40165
+#define ID_TOGGLECAMERA                 40166
+#define ID_TOGGLEZ                      40167
+#define ID_TOGGLEVIEW                   40168
+#define ID_SELECTION_TEXTURE_FIT        40171
+#define ID_SELECTION_TEXTURE_ROTATECLOCK 40172
+#define ID_SELECTION_TEXTURE_ROTATECOUNTER 40173
+#define ID_SELECTION_TEXTURE_SCALEUP    40174
+#define ID_SELECTION_TEXTURE_SCALEDOWN  40175
+#define ID_SELECTION_TEXTURE_SHIFTLEFT  40176
+#define ID_SELECTION_TEXTURE_SHIFTRIGHT 40177
+#define ID_SELECTION_TEXTURE_SHIFTUP    40178
+#define ID_SELECTION_TEXTURE_SHIFTDOWN  40179
+#define ID_GRID_NEXT                    40180
+#define ID_GRID_PREV                    40181
+#define ID_SELECTION_TEXTURE_SCALELEFT  40182
+#define ID_SELECTION_TEXTURE_SCALERIGHT 40183
+#define ID_SELECTION_PRINT              40184
+#define ID_SELECTION_TOGGLESIZEPAINT    40185
+#define ID_PATCH_TAB                    40186
+#define ID_PATCH_ENTER                  40187
+#define ID_SELECT_SNAPTOGRID            40188
+#define ID_PATCH_INSPECTOR              40189
+#define ID_SELECT_ALL                   40190
+#define ID_CURVE_FREEZE                 40191
+#define ID_CURVE_UNFREEZE               40192
+#define ID_CURVE_UNFREEZEALL            40193
+#define ID_SELECT_RESELECT              40194
+#define ID_FITFACE                      40196
+#define ID_VIEW_CROSSHAIR               40197
+#define ID_SELECTION_INVERT             40198
+#define ID_VIEW_GROUPS                  40199
+#define ID_FILE_SLEEP                   40200
+#define ID_HELP_LINKS                   40201
+#define ID_VIEW_SHOWOUTLINE             40202 // TTimo: outline as in colored outline around the window to quickly guess the orientation
+#define ID_VIEW_SHOWAXES                40203
+#define ID_SELECTION_NOOUTLINE          40204 // TTimo: outline as in zbuffered outline toggle on camera view (TA Q3Radiant 200f addition)
+#define ID_SELECTION_OUTLINESTYLE       40205 // Arnout: cycles through selection styles (extended 'nooutline')
+#define ID_SELECTION_SEPERATE           40206 // TTimo: split brushes out of an entity back into worldspawn
+#define ID_SELECTION_MERGE              40207 // TTimo: merge brushes from worldspawn into entity
+#define ID_HELP_BUGREPORT               40208
+
+#define ID_FILTER_WORLD                 40209
+#define ID_FILTER_PATCHES               40210
+#define ID_FILTER_DETAILS               40211
+#define ID_FILTER_ENTITIES              40212
+#define ID_FILTER_MODELS                40213
+#define ID_FILTER_HINTSSKIPS            40214
+#define ID_FILTER_CLIPS                 40215
+#define ID_FILTER_LIQUIDS               40216
+#define ID_FILTER_TRIGGERS              40217
+#define ID_FILTER_AREAPORTALS           40218
+#define ID_FILTER_TRANSLUCENT           40219
+#define ID_FILTER_CAULK                 40220
+#define ID_FILTER_LIGHTS                40221
+#define ID_FILTER_PATHS                 40223
+#define ID_FILTER_CLUSTERPORTALS        40224
+#define ID_FILTER_LIGHTGRID             40225
+#define ID_FILTER_STRUCTURAL            40226
+#define ID_FILTER_BOTCLIPS							40227
+
+#define ID_CURVE_REDISPERSE_INTERMEDIATE_COLS	40230
+#define ID_CURVE_REDISPERSE_INTERMEDIATE_ROWS	40231
+#define ID_EDIT_PASTEBRUSHTOCAMERA      40232
+
+#define ID_COLORS_MINOR_ALT             40230
+#define ID_COLORS_MAJOR_ALT             40231
+
+// those must have their own ID chunk ID_GRID_025 <= ID_GRID <= ID_GRID_256
+#define ID_GRID_025                     40300
+#define ID_GRID_05                      40301
+#define ID_GRID_1                       40302
+#define ID_GRID_2                       40303
+#define ID_GRID_4                       40304
+#define ID_GRID_8                       40305
+#define ID_GRID_16                      40306
+#define ID_GRID_32                      40307
+#define ID_GRID_64                      40308
+#define ID_GRID_128                     40309
+#define ID_GRID_256                     40310
+
+#define ID_FILE_CHECKUPDATE             40320
+
+#define ID_TEXTUREWINDOW_SCALEUP        40321
+#define ID_TEXTUREWINDOW_SCALEDOWN      40322
+
+class CSynapseClientRadiant : public CSynapseClient
+{
+public:
+  bool RequestAPI(APIDescriptor_t *pAPI);
+  const char* GetInfo();
+  const char* GetName();
+      
+  void ImportMap(IDataStream *in, CPtrArray *ents, const char *type);
+  void ExportMap(CPtrArray *ents, IDataStream *out, const char *type);
+
+  CSynapseClientRadiant() { }
+  virtual ~CSynapseClientRadiant() { }
+};  
+
+class MainFrame
+{
+public:
+  enum EViewStyle
+  {
+    eRegular,
+    eFloating,
+    eSplit,
+    eRegularLeft,
+  };
+
+  MainFrame();
+  GtkWidget *m_pWidget;
+
+  /*!
+  called to fire up the help links
+  */
+  void handle_help_command(int id);
+
+protected:
+
+  /*!
+  the urls to fire up in the game packs help menus
+  */
+  vector<Str *> mHelpURLs;
+
+  /*!
+  scan the .game files for game install packs
+  look there for help description nodes
+  build the corresponding menus in Radiant
+  */
+  void create_game_help_menu (GtkWidget *menu, GtkAccelGroup *accel);
+
+  /*!
+  build the menu once the filename is found
+  */
+  void process_xlink (Str &FileName, char *menu_name, const char *base_url, GtkWidget *menu, GtkAccelGroup *accel);
+
+  void Create ();
+  void create_main_menu (GtkWidget *window, GtkWidget *vbox);
+  void create_main_toolbar (GtkWidget *window, GtkWidget *vbox);
+  void create_plugin_toolbar (GtkWidget *window, GtkWidget *vbox);
+  void create_main_statusbar (GtkWidget *window, GtkWidget *vbox);
+  GtkWidget *m_pStatusLabel[6];
+  GtkWidget *m_pSplits[4];
+  XYWnd* m_pXYWnd;
+  XYWnd* m_pYZWnd;
+  XYWnd* m_pXZWnd;
+  CamWnd* m_pCamWnd;
+  TexWnd* m_pTexWnd;
+  ZWnd* m_pZWnd;
+  CWatchBSP* m_pWatchBSP;
+
+  XYWnd* m_pActiveXY;
+  bool m_bCamPreview;
+  CPlugInManager m_PlugInMgr;
+  int m_nNextPlugInID;
+  guint m_nTimer;
+  bool m_bSleeping;
+
+  CString m_strStatus[15];
+  bool m_bNeedStatusUpdate;
+
+  /*!
+  synapse server
+  deals with dynamically loading the modules, initializing them, requesting the APIs
+  */
+  CSynapseServer m_SynapseServer;
+  /*!
+  we are also a synapse client in that we provide and require some APIs as well
+  */
+  CSynapseClientRadiant m_SynapseClient;
+
+public:
+
+  // BSP window
+  // trigger network listen
+  void DoWatchBSP();
+  bool IsSleeping ()
+    { return m_bSleeping; }
+
+  void UpdatePatchToolbarButtons();
+  // Gef: Changed to float for sub-integer grid size
+  void NudgeSelection(int nDirection, float nAmount);
+  void SetButtonMenuStates();
+  void SetGridStatus();
+  void RoutineProcessing();
+  XYWnd* ActiveXY() { return m_pActiveXY; };
+  void UpdateWindows(int nBits);
+  void SetStatusText(int nPane, const char* pText);
+  void UpdateStatusText();
+  void SetWindowStyle(int nStyle);
+  virtual ~MainFrame();
+  XYWnd* GetXYWnd() {return m_pXYWnd;}
+  XYWnd* GetXZWnd() {return m_pXZWnd;}
+  XYWnd* GetYZWnd() {return m_pYZWnd;}
+  ZWnd* GetZWnd() {return m_pZWnd;}
+  CamWnd* GetCamWnd() {return m_pCamWnd;}
+  TexWnd* GetTexWnd() {return m_pTexWnd;}
+  CWatchBSP *GetWatchBSP() { return m_pWatchBSP; }
+  void ReleaseContexts ();
+  void CreateContexts ();
+
+  void SetActiveXY(XYWnd* p) 
+  {
+    if (m_pActiveXY)
+      m_pActiveXY->SetActive(false);
+
+    m_pActiveXY = p;
+
+    if (m_pActiveXY)
+      m_pActiveXY->SetActive(true);
+
+  };
+
+  EViewStyle CurrentStyle()
+  {
+    return m_nCurrentStyle;
+  };
+
+  bool FloatingGroupDialog()
+  {
+    return CurrentStyle() == eFloating || CurrentStyle() == eSplit;
+  };
+
+#ifdef _WIN32
+  const GdkRectangle & GetPrimaryMonitorRect( void ) const { return primaryMonitorRect; }
+  const int GetGDKOffsetX( void ) const { return gdk_offset_x; }
+  const int GetGDKOffsetY( void ) const { return gdk_offset_y; }
+#endif
+
+protected:
+  bool m_bDoLoop;
+  bool m_bSplittersOK;
+  void CreateQEChildren();
+  void LoadCommandMap();
+  void ShowMenuItemKeyBindings(GtkWidget* window);
+
+public:
+  void Copy();
+  void Paste();
+  void Nudge(int nDim, float fNudge);
+  CPlugInManager &GetPlugInMgr() {return m_PlugInMgr;};
+  CSynapseServer &GetSynapseServer() {return m_SynapseServer;};
+  CSynapseClientRadiant &GetSynapseClient() {return m_SynapseClient;};
+  void AddPlugInToolbarButton(const IToolbarButton* button);
+  void AddPlugInMenuItem(IPlugIn* pPlugIn);
+  void CleanPlugInMenu();
+
+  // these are public so i can easily reflect messages
+  // from child windows..
+  void OnTimer();
+  void OnDelete();
+  void OnDestroy();
+  void ToggleCamera();
+
+  void OnFileExit();
+  void OnFileLoadproject();
+  void OnFileNew();
+  void OnFileOpen();
+  void OnFilePointfile();
+  void OnFileSave();
+  void OnFileSaveas();
+  void OnFileCheckUpdate();
+  void OnView100();
+  void OnViewCenter();
+  void OnViewConsole();
+  void OnViewDownfloor();
+  void OnViewEntity();
+  void OnViewFront();
+  void OnViewShowblocks();
+  void OnViewShowclip();
+  void OnViewShowcoordinates();
+  void OnViewShowOutline();
+  void OnViewShowAxes();
+  void OnViewShowdetail();
+  void OnViewShowent();
+  void OnViewShowlights();
+  void OnViewShownames();
+  void OnViewShowpath();
+  void OnViewShowwater();
+  void OnViewShowworld();
+  void OnViewTexture();
+  void OnViewUpfloor();
+  void OnViewXy();
+  void OnViewZ100();
+  void OnViewZoomin();
+  void OnViewZoomout();
+  void OnViewZzoomin();
+  void OnViewZzoomout();
+  void OnViewSide();
+  void OnTexturesShowinuse();
+  void OnTexturesInspector();
+  void OnMiscBenchmark();
+  void OnMiscFindbrush();
+  void OnMiscGamma();
+  void OnMiscNextleakspot();
+  void OnMiscPreviousleakspot();
+  void OnMiscPrintxy();
+  void OnMiscSelectentitycolor();
+  void OnTexturebk();
+  void OnColorsMajor();
+  void OnColorsMinor();
+  void OnColorsMajor_Alt();
+  void OnColorsMinor_Alt();
+  void OnColorsXybk();
+  void OnBrush3sided();
+  void OnBrush4sided();
+  void OnBrush5sided();
+  void OnBrush6sided();
+  void OnBrush7sided();
+  void OnBrush8sided();
+  void OnBrush9sided();
+  void OnBrushArbitrarysided();
+  void OnBrushFlipx();
+  void OnBrushFlipy();
+  void OnBrushFlipz();
+  void OnBrushRotatex();
+  void OnBrushRotatey();
+  void OnBrushRotatez();
+  void OnRegionOff();
+  void OnRegionSetbrush();
+  void OnRegionSetselection();
+  void OnRegionSettallbrush();
+  void OnRegionSetxy();
+  void OnSelectionArbitraryrotation();
+  void OnSelectionClone();
+  void OnSelectionConnect();
+  void OnSelectionCsgsubtract();
+  void OnSelectionCsgmerge();
+  void OnSelectionNoOutline();
+  void OnSelectionOutlineStyle();
+  void OnSelectionDelete();
+  void OnSelectionDeselect();
+  void OnSelectionDragedges();
+  void OnSelectionDragvertecies();
+  void OnSelectionMakeDetail();
+  void OnSelectionMakeStructural();
+  void OnSelectionMakehollow();
+  void OnSelectionSelectcompletetall();
+  void OnSelectionSelectinside();
+  void OnSelectionSelectpartialtall();
+  void OnSelectionSelecttouching();
+  void OnSelectionUngroupentity();
+  void OnSelectionMergeentity();
+  void OnSelectionGroupworld();
+  void OnTexturesPopup();
+  void OnPopupSelection();
+  void OnViewChange();
+  void OnViewCameraupdate();
+  void OnHelpAbout();
+  void OnHelp();
+  void OnHelpLinks();
+  void OnHelpBugreport();
+  void OnViewClipper();
+  void OnCameraAngledown();
+  void OnCameraAngleup();
+  void OnCameraBack(bool keydown);
+  void OnCameraDown();
+  void OnCameraForward(bool keydown);
+  void OnCameraLeft(bool keydown);
+  void OnCameraRight(bool keydown);
+  void OnCameraStrafeleft(bool keydown);
+  void OnCameraStraferight(bool keydown);
+  void OnCameraUp();
+  void OnGridToggle();
+  void OnPrefs();
+  void OnTogglecamera();
+  void OnToggleconsole();
+  void OnToggleview();
+  void OnTogglez();
+  void OnToggleLock();
+  void OnEditMapinfo();
+  void OnEditEntityinfo();
+  void OnBrushScripts();
+  void OnViewCenterview();
+  void OnViewNextview();
+  void OnHelpCommandlist();
+  void OnFileNewproject();
+  void OnFlipClip();
+  void OnClipSelected();
+  void OnSplitSelected();
+  void OnToggleviewXz();
+  void OnToggleviewYz();
+  void OnColorsBrush();
+  void OnColorsClipper();
+  void OnColorsGridtext();
+  void OnColorsSelectedbrush();
+  void OnColorsSelectedbrush3D();
+  void OnColorsCameraBack();
+  void OnColorsGridblock();
+  void OnColorsViewname();
+  void OnColorSetoriginal();
+  void OnColorSetqer();
+  void OnColorSetblack();
+  void OnColorSetydnar();  /* ydnar */
+  void OnSnaptogrid();
+  void OnSelectScale();
+  void OnSelectMouserotate();
+  void OnEditCopybrush();
+  void OnEditPastebrush();
+  void OnEditPastebrushToCamera();
+  void OnEditUndo();
+  void OnEditRedo();
+  void OnSelectionInvert();
+//  void OnSelectionTextureDec();
+  void OnSelectionTextureFit();
+//  void OnSelectionTextureInc();
+  void OnSelectionTextureRotateclock();
+  void OnSelectionTextureRotatecounter();
+  void OnSelectionTextureScaledown();
+  void OnSelectionTextureScaleup();
+  void OnSelectionTextureShiftdown();
+  void OnSelectionTextureShiftleft();
+  void OnSelectionTextureShiftright();
+  void OnSelectionTextureShiftup();
+  void OnGridNext();
+  void OnGridPrev();
+  void OnSelectionTextureScaleLeft();
+  void OnSelectionTextureScaleRight();
+  void OnTextureReplaceall();
+  void OnScalelockx();
+  void OnScalelocky();
+  void OnScalelockz();
+  void OnSelectMousescale();
+  void OnViewCubicclipping();
+  void OnFileProjectsettings();
+  void OnViewCubein();
+  void OnViewCubeout();
+  void OnFileSaveregion();
+  void OnSelectionMovedown();
+  void OnSelectionMoveup();
+  void OnToolbarMain();
+  void OnToolbarTexture();
+  void OnSelectionPrint();
+  void OnSelectionTogglesizepaint();
+  void OnBrushMakecone();
+  void OnTexturesLoad();
+  void OnToggleRotatelock();
+  void OnFileImportmap();
+  void OnFileExportmap();
+  void OnEditLoadprefab();
+  void OnSelectionSelectNudgedown();
+  void OnSelectionSelectNudgeleft();
+  void OnSelectionSelectNudgeright();
+  void OnSelectionSelectNudgeup();
+  void OnTexturesLoadlist();
+  void OnDontselectcurve();
+  void OnConvertcurves();
+  void OnCurveSimplepatchmesh();
+  void OnPatchToggleBox();
+  void OnPatchWireframe();
+  void OnCurvePatchcone();
+  void OnCurvePatchtube();
+  void OnPatchWeld();
+  void OnCurvePatchbevel();
+  void OnCurvePatchendcap();
+  void OnPatchDrilldown();
+  void OnCurveInsertcolumn();
+  void OnCurveInsertrow();
+  void OnCurveDeletecolumn();
+  void OnCurveDeleterow();
+  void OnCurveInsertAddcolumn();
+  void OnCurveInsertAddrow();
+  void OnCurveInsertInsertcolumn();
+  void OnCurveInsertInsertrow();
+  void OnCurveNegative();
+  void OnCurveNegativeTextureX();
+  void OnCurveNegativeTextureY();
+  void OnCurveDeleteFirstcolumn();
+  void OnCurveDeleteFirstrow();
+  void OnCurveDeleteLastcolumn();
+  void OnCurveDeleteLastrow();
+  void OnPatchBend();
+//  void OnPatchInsdel();
+  void OnPatchEnter();
+  void OnPatchTab();
+  void OnCurvePatchdensetube();
+  void OnCurvePatchverydensetube();
+  void OnCurveCap();
+  void OnCurveCapInvertedbevel();
+  void OnCurveCapInvertedendcap();
+  void OnCurveRedisperseRows();
+  void OnCurveRedisperseIntermediateCols();
+  void OnCurveRedisperseIntermediateRows();
+  void OnPatchNaturalize();
+  void OnSnapToGrid();
+  void OnCurvePatchsquare();
+  void OnTexturewindowScaleup();
+  void OnTexturewindowScaledown();
+  void OnCurveOverlayClear();
+  void OnCurveOverlaySet();
+  void OnCurveThicken();
+  void OnCurveCyclecap();
+  void OnCurveMatrixTranspose();
+  void OnTexturesReloadshaders();
+  void OnShowEntities();
+  // will set the view mode right, don't set the value for mode if you only want to update the radio item
+  void OnEntitiesSetViewAs(int mode = 0);
+  void OnPluginsRefresh();
+  void OnTexturesShowall();
+  void OnPatchInspector();
+  void OnViewOpengllighting();
+  void OnSelectAll();
+  void OnCurveFreeze();
+  void OnCurveUnFreeze();
+  void OnCurveUnFreezeAll();
+  void OnSelectReselect();
+  void OnEditSaveprefab();
+  void OnCurveMoreendcapsbevelsSquarebevel();
+  void OnCurveMoreendcapsbevelsSquareendcap();
+  void OnBrushPrimitivesSphere();
+  void OnViewCrosshair();
+  void OnViewHideshowHideselected();
+  void OnViewHideshowShowhidden();
+  void OnTexturesShadersShow();
+  void OnViewGroups();
+  void OnDropGroupAddtoWorld();
+  void OnDropGroupName();
+  void OnDropGroupNewgroup();
+  void OnDropGroupRemove();
+  void OnViewShowWorkzone();
+  void OnViewShowAngles();
+  void OnMru(unsigned int nID);
+  void OnViewNearest(unsigned int nID);
+  void OnTextureWad(unsigned int nID);
+  void OnBspCommand(unsigned int nID);
+  void OnGrid(unsigned int nID);
+  void OnPlugIn(unsigned int nID, char *str);
+  void OnFaceFit();
+  void SetTextureScale(int id);
+  void OnDontselectmodel();
+  void OnTexturesShaderlistonly();
+  void OnSleep();
+  void OnFilterAreaportals();
+  void OnFilterCaulk();
+  void OnFilterStructural();
+  void OnFilterClips();
+  void OnFilterBotClips();
+  void OnFilterDetails();
+  void OnFilterEntities();
+  void OnFilterHintsskips();
+  void OnFilterLights();
+  void OnFilterLiquids();
+  void OnFilterModels();
+  void OnFilterPatches();
+  void OnFilterTranslucent();
+  void OnFilterTriggers();
+  void OnFilterWorld();
+  void OnFilterPaths();
+  void OnFilterClusterportals();
+  void OnFilterLightgrid();
+
+private:
+  EViewStyle m_nCurrentStyle;
+
+#ifdef _WIN32
+  GdkRectangle primaryMonitorRect;
+  int gdk_offset_x;
+  int gdk_offset_y;
+#endif
+
+};
+
+// some C API to the mainframe functions
+void WINAPI QERApp_Sleep();
+
+#endif // _MAINFRAME_H_
diff --git a/radiant/map.h b/radiant/map.h
index efc8f68a..39b96ff5 100644
--- a/radiant/map.h
+++ b/radiant/map.h
@@ -1,72 +1,72 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// map.h -- the state of the current world that all views are displaying
-
-extern	char		currentmap[1024];
-
-// head/tail of doubly linked lists
-extern	brush_t	active_brushes;	// brushes currently being displayed
-extern	brush_t	selected_brushes;	// highlighted
-
-extern CPtrArray& g_ptrSelectedFaces;
-extern CPtrArray& g_ptrSelectedFaceBrushes;
-
-extern	brush_t	filtered_brushes;	// brushes that have been filtered or regioned
-
-extern	entity_t	entities;
-extern	entity_t	*world_entity;	// the world entity is NOT included in
-									// the entities chain
-
-extern	int	modified;		// for quit confirmations
-
-extern	vec3_t	region_mins, region_maxs;
-extern	qboolean	region_active;
-
-extern brush_t	  *region_sides[6];
-
-void Map_Init();
-
-void 	Map_LoadFile (const char *filename);
-void 	Map_SaveFile (const char *filename, qboolean use_region);
-
-void	Map_New (void);
-void  Map_Free (void);
-void	Map_BuildBrushData(void);
-
-void	Map_RegionOff (void);
-void	Map_RegionXY (void);
-void	Map_RegionTallBrush (void);
-void	Map_RegionBrush (void);
-void	Map_RegionSelectedBrushes (void);
-qboolean Map_IsBrushFiltered (brush_t *b);
-
-void Map_ImportFile (const char *filename);
-void Map_SaveSelected(const char* filename);
-//void Map_SaveSelected(MemStream* pMemFile, MemStream* pPatchFile = NULL);
-//void Map_ImportBuffer (char* buf);
-
-void  Map_StartPosition(void);
-void Region_SpawnPoint(FILE *f);
-
-void Map_Import(IDataStream *in, const char* type, bool bAddSelected = false);
-void Map_Export(IDataStream *out, const char* type, bool bRegionOnly = false , bool bSelectedOnly = false);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// map.h -- the state of the current world that all views are displaying
+
+extern	char		currentmap[1024];
+
+// head/tail of doubly linked lists
+extern	brush_t	active_brushes;	// brushes currently being displayed
+extern	brush_t	selected_brushes;	// highlighted
+
+extern CPtrArray& g_ptrSelectedFaces;
+extern CPtrArray& g_ptrSelectedFaceBrushes;
+
+extern	brush_t	filtered_brushes;	// brushes that have been filtered or regioned
+
+extern	entity_t	entities;
+extern	entity_t	*world_entity;	// the world entity is NOT included in
+									// the entities chain
+
+extern	int	modified;		// for quit confirmations
+
+extern	vec3_t	region_mins, region_maxs;
+extern	qboolean	region_active;
+
+extern brush_t	  *region_sides[6];
+
+void Map_Init();
+
+void 	Map_LoadFile (const char *filename);
+void 	Map_SaveFile (const char *filename, qboolean use_region);
+
+void	Map_New (void);
+void  Map_Free (void);
+void	Map_BuildBrushData(void);
+
+void	Map_RegionOff (void);
+void	Map_RegionXY (void);
+void	Map_RegionTallBrush (void);
+void	Map_RegionBrush (void);
+void	Map_RegionSelectedBrushes (void);
+qboolean Map_IsBrushFiltered (brush_t *b);
+
+void Map_ImportFile (const char *filename);
+void Map_SaveSelected(const char* filename);
+//void Map_SaveSelected(MemStream* pMemFile, MemStream* pPatchFile = NULL);
+//void Map_ImportBuffer (char* buf);
+
+void  Map_StartPosition(void);
+void Region_SpawnPoint(FILE *f);
+
+void Map_Import(IDataStream *in, const char* type, bool bAddSelected = false);
+void Map_Export(IDataStream *out, const char* type, bool bRegionOnly = false , bool bSelectedOnly = false);
+
diff --git a/radiant/parse.h b/radiant/parse.h
index de679de2..ce9e55ba 100644
--- a/radiant/parse.h
+++ b/radiant/parse.h
@@ -1,35 +1,35 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// parse.h -- text file parsing routines
-
-#define	MAXTOKEN	1024
-
-extern	char	token[MAXTOKEN];
-extern	int	scriptline;
-
-// NOTE: added WINAPI call syntax to export these for plugins in _QERScripLibTable
-void	    StartTokenParsing (char *data);
-qboolean  GetToken (qboolean crossline);
-void      UngetToken (void);
-qboolean  TokenAvailable (void);
-qboolean  GetTokenExtra (qboolean crossline,char *delimiters,qboolean keepdelimiter); // Hydra: added support for GetTokenExtra()
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// parse.h -- text file parsing routines
+
+#define	MAXTOKEN	1024
+
+extern	char	token[MAXTOKEN];
+extern	int	scriptline;
+
+// NOTE: added WINAPI call syntax to export these for plugins in _QERScripLibTable
+void	    StartTokenParsing (char *data);
+qboolean  GetToken (qboolean crossline);
+void      UngetToken (void);
+qboolean  TokenAvailable (void);
+qboolean  GetTokenExtra (qboolean crossline,char *delimiters,qboolean keepdelimiter); // Hydra: added support for GetTokenExtra()
+
diff --git a/radiant/patchdialog.h b/radiant/patchdialog.h
index 04c4f6b6..7316b88c 100644
--- a/radiant/patchdialog.h
+++ b/radiant/patchdialog.h
@@ -1,85 +1,85 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PATCHDIALOG_H_
-#define _PATCHDIALOG_H_
-
-#include "dialog.h"
-
-#ifdef _DEBUG
-//#define DBG_PI
-#endif
-
-class PatchDialog : public Dialog
-{
- public:
-  // overrides from Dialog
-  void HideDlg();
-  void ShowDlg();
-
-//  void UpdateInfo();
-//  void SetPatchInfo();
-  void GetPatchInfo();
-  void UpdateSpinners(bool bUp, int nID);
-  // read the current patch on map and initialize m_fX m_fY accordingly
-  void UpdateRowColInfo();
-  // sync the dialog our internal data structures
-  // depending on the flag it will read or write
-  // we use m_nCol m_nRow m_fX m_fY m_fZ m_fS m_fT m_strName
-  // (NOTE: this doesn't actually commit stuff to the map or read from it)
-  void UpdateData (bool retrieve);
-
-  void InitDefaultIncrement(texdef_t *);
-
-  PatchDialog();
-  patchMesh_t *m_Patch;
-
-  Str	m_strName;
-  float	m_fS;
-  float	m_fT;
-  float	m_fX;
-  float	m_fY;
-  float	m_fZ;
-/*  float	m_fHScale;
-  float	m_fHShift;
-  float	m_fRotate;
-  float	m_fVScale;
-  float	m_fVShift; */
-  int   m_nCol;
-  int   m_nRow;
-  GtkWidget *m_pRowCombo;
-  GtkWidget *m_pColCombo;
-
-  GtkWidget *GetWidget () { return m_pWidget; }
-
-  // 0 is invalid, otherwise it's the Id of the last 'do' we are responsible for
-//  int m_nUndoId;
-  
-  // turn on/off processing of the "changed" "value_changed" messages
-  // (need to turn off when we are feeding data in)
-  // NOTE: much more simple than blocking signals
-  bool m_bListenChanged;
-
-protected:
-  void BuildDialog ();
-};
-
-#endif // _PATCHDIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PATCHDIALOG_H_
+#define _PATCHDIALOG_H_
+
+#include "dialog.h"
+
+#ifdef _DEBUG
+//#define DBG_PI
+#endif
+
+class PatchDialog : public Dialog
+{
+ public:
+  // overrides from Dialog
+  void HideDlg();
+  void ShowDlg();
+
+//  void UpdateInfo();
+//  void SetPatchInfo();
+  void GetPatchInfo();
+  void UpdateSpinners(bool bUp, int nID);
+  // read the current patch on map and initialize m_fX m_fY accordingly
+  void UpdateRowColInfo();
+  // sync the dialog our internal data structures
+  // depending on the flag it will read or write
+  // we use m_nCol m_nRow m_fX m_fY m_fZ m_fS m_fT m_strName
+  // (NOTE: this doesn't actually commit stuff to the map or read from it)
+  void UpdateData (bool retrieve);
+
+  void InitDefaultIncrement(texdef_t *);
+
+  PatchDialog();
+  patchMesh_t *m_Patch;
+
+  Str	m_strName;
+  float	m_fS;
+  float	m_fT;
+  float	m_fX;
+  float	m_fY;
+  float	m_fZ;
+/*  float	m_fHScale;
+  float	m_fHShift;
+  float	m_fRotate;
+  float	m_fVScale;
+  float	m_fVShift; */
+  int   m_nCol;
+  int   m_nRow;
+  GtkWidget *m_pRowCombo;
+  GtkWidget *m_pColCombo;
+
+  GtkWidget *GetWidget () { return m_pWidget; }
+
+  // 0 is invalid, otherwise it's the Id of the last 'do' we are responsible for
+//  int m_nUndoId;
+  
+  // turn on/off processing of the "changed" "value_changed" messages
+  // (need to turn off when we are feeding data in)
+  // NOTE: much more simple than blocking signals
+  bool m_bListenChanged;
+
+protected:
+  void BuildDialog ();
+};
+
+#endif // _PATCHDIALOG_H_
diff --git a/radiant/plugin.h b/radiant/plugin.h
index 9c903891..060ddb56 100644
--- a/radiant/plugin.h
+++ b/radiant/plugin.h
@@ -1,45 +1,45 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGIN_H_
-#define _PLUGIN_H_
-
-/*!
-\class IPlugin
-pure virtual interface for a plugin
-temporary solution for migration from old plugin tech to synapse plugins
-FIXME/TODO: plugin toolbar
-*/
-class IPlugIn
-{
-
-public:
-  IPlugIn() { }
-  virtual ~IPlugIn() { }  
-  
-  virtual const char* getMenuName() = 0;
-  virtual int getCommandCount() = 0;
-  virtual const char* getCommand(int) = 0;
-  virtual void addMenuID(int) = 0;
-  virtual bool ownsCommandID(int n) = 0;
-};
-
-#endif // _PLUGIN_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGIN_H_
+#define _PLUGIN_H_
+
+/*!
+\class IPlugin
+pure virtual interface for a plugin
+temporary solution for migration from old plugin tech to synapse plugins
+FIXME/TODO: plugin toolbar
+*/
+class IPlugIn
+{
+
+public:
+  IPlugIn() { }
+  virtual ~IPlugIn() { }  
+  
+  virtual const char* getMenuName() = 0;
+  virtual int getCommandCount() = 0;
+  virtual const char* getCommand(int) = 0;
+  virtual void addMenuID(int) = 0;
+  virtual bool ownsCommandID(int n) = 0;
+};
+
+#endif // _PLUGIN_H_
diff --git a/radiant/pluginmanager.h b/radiant/pluginmanager.h
index fe096e77..96e2ac98 100644
--- a/radiant/pluginmanager.h
+++ b/radiant/pluginmanager.h
@@ -1,212 +1,212 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PLUGINMANAGER_H_
-#define _PLUGINMANAGER_H_
-
-#include "plugin.h"
-
-// global interfaces we are using
-extern _QERShadersTable g_ShadersTable;
-
-// NOTE: it's actually a module manager, the name should change to ModuleManager..
-class CPlugInManager  
-{
-private:
-  GSList* m_PlugIns;
-  CPtrArray m_BrushHandles;
-  CPtrArray m_SelectedBrushHandles;
-  CPtrArray m_ActiveBrushHandles;
-
-  // v1.70
-  //! brushes of the current entity ( see m_SelectedBrushHandles and m_ActiveBrushHandles )
-  CPtrArray m_EntityBrushHandles;
-  //! allocated entities, not commited yet ( see m_BrushHandles )
-  CPtrArray m_EntityHandles;
-
-  //! tells in which array to look when given a patch index
-  enum EPatchesMode { EActivePatches, ESelectedPatches, EAllocatedPatches } PatchesMode;
-  //! patches handles (brush_t*)
-  CPtrArray m_PatchesHandles;
-  //! plugin-allocated patches, not commited yet (patchMesh_t*)
-  CPtrArray m_PluginPatches;
-
-  void InitForDir(const Str &dir); ///< init for plguins/modules below this directory
-
-public:
-  CPtrArray& GetActiveHandles() {return m_ActiveBrushHandles; };
-  CPtrArray& GetSelectedHandles() {return m_SelectedBrushHandles; };
-  CPtrArray& GetPluginPatches() {return m_PluginPatches; };
-  brush_t* FindBrushHandle(void *vp);
-  patchMesh_t* FindPatchHandle(int index);
-  int CreatePatchHandle();
-  int AllocateActivePatchHandles();
-  int AllocateSelectedPatchHandles();
-  void CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName);
-  void CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void *vpEntity);
-  void ReleasePatchesHandles() { m_PatchesHandles.RemoveAll(); m_PluginPatches.RemoveAll(); }
-  void AddFaceToBrushHandle(void *vp, vec3_t v1, vec3_t v2, vec3_t v3);
-  void CommitBrushHandleToMap(void *vp);
-  void DeleteBrushHandle(void* vp);
-  void* CreateBrushHandle();
-  void Dispatch(int n, const char *p);
-  void Cleanup(); ///< cleanup of data structures allocated for plugins, not a plugin reload
-  void Init(); ///< go through the path where we will find modules and plugins
-  void LoadImage (const char *name, unsigned char **pic, int *width, int *height);
-  void ImportMap (IDataStream *in, CPtrArray *ents, const char *type);
-  void ExportMap (CPtrArray *ents, IDataStream *out, const char *type);
-  void Shutdown(); ///< shutdown all the plugins/module subsystem
-  CPlugInManager();
-  virtual ~CPlugInManager();
-
-  /*! 
-  the texture manager front ends the single load
-  addins (texture, model, map formats.. etc.)
-  */
-  _QERTextureInfo* GetTextureInfo();
-  void LoadTexture(const char *pFilename);
-	
-void* GetSurfaceFlags();
-	
-  // v1.70
-  CPtrArray& GetEntityBrushHandles() {return m_EntityBrushHandles; };
-  CPtrArray& GetEntityHandles() {return m_EntityHandles; };
-  //! the vpBrush needs to be in m_BrushHandles
-  void CommitBrushHandleToEntity(void* vpBrush, void* vpEntity );
-  //! the vpEntity needs to be in m_EntityHandles
-  void CommitEntityHandleToMap( void* vpEntity );
-
-protected:
-  //! read the interfaces this plugin implements
-  void LoadFromPath(const char *path); ///< load all modules/plugins in specified path
-  void RegisterInterfaces();
-};
-
-class CPluginSlot : public IPlugIn
-{
-  APIDescriptor_t *mpAPI;
-  _QERPluginTable *mpTable;
-  /*!
-  is false until Init() happened
-  */
-  bool m_bReady;
-  /*!
-  below is valid only if m_bReady = true
-  */
-  GSList *m_CommandStrings;
-  GSList *m_CommandIDs;
-  
-public:
-  /*!
-  build directly from a SYN_PROVIDE interface
-  */
-  CPluginSlot(APIDescriptor_t *pAPI);
-  virtual ~CPluginSlot();
-  
-  APIDescriptor_t* GetDescriptor() { return mpAPI; }
-  /*!
-  initialize some management data after the synapse interfaces have been hooked up
-  */
-  void Init();
-  /*!
-  dispatching a command by name to the plugin
-  */
-  void Dispatch(const char *p);
-  
-  // IPlugIn ------------------------------------------------------------
-  const char* getMenuName();
-  int getCommandCount();
-  const char* getCommand(int n);  
-  void addMenuID(int n);
-  bool ownsCommandID(int n);
-  
-};
-
-class CRadiantPluginManager : public CSynapseAPIManager
-{
-  list<CPluginSlot *> mSlots;
-public:
-  CRadiantPluginManager() {}
-  virtual ~CRadiantPluginManager();
-  
-  // CSynapseAPIManager interface -------------------
-  APIDescriptor_t *BuildRequireAPI(APIDescriptor_t *pAPI);
-  
-  // CRadiantPluginManager --------------------------
-  void PopulateMenu();
-  bool Dispatch(int n, const char* p);
-};
-
-class CImageTableSlot
-{
-  /*!
-  \todo this is a duplicate from the APIDescriptor_t* list that privately stored inside CSynapseAPIManager
-  this is probably useless to us in here?
-  */
-  APIDescriptor_t *mpAPI;
-  /*!
-  shortcut to mpAPI->mpTable, with correct typing
-  this is what we allocate and should free locally
-  */
-  _QERPlugImageTable *mpTable;
-public:
-  CImageTableSlot() { }
-  virtual ~CImageTableSlot() { } ///\ \todo need to correctly free and release still..
-  
-  APIDescriptor_t* GetDescriptor() { return mpAPI; }
-  _QERPlugImageTable* GetTable() { return mpTable; }
-  
-  /*!
-  don't go through PrepareRequireAPI for init, just get this API and add the table info
-  */
-  void InitForFillAPITable(APIDescriptor_t *pAPI);
-};
-
-class CRadiantImageManager : public CSynapseAPIManager
-{
-  list<CImageTableSlot *> mSlots;
-  
-  list<CImageTableSlot *>::iterator mExtScanSlot;
-public:
-  CRadiantImageManager() {}
-  virtual ~CRadiantImageManager();
-  
-  // CSynapseAPIManager interface --------------------
-  void FillAPITable(APIDescriptor_t *pAPI);
-
-  // CRadiantImageManager ----------------------------
-  /*!
-  extract the extension, go through the list of image interfaces, and load
-  */
-  void LoadImage(const char *name, byte **pic, int *width, int *height);
-    
-  /*!
-  we often need to walk through the extensions
-  this used to be hardcoded in texwindow.cpp
-  the two functions are related, they use a static to go through the list
-  */
-  void BeginExtensionsScan();
-  const char* GetNextExtension(); ///< \return NULL when the list has been completely scanned
-};
-
-extern CRadiantImageManager g_ImageManager;
-
-#endif // _PLUGINMANAGER_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PLUGINMANAGER_H_
+#define _PLUGINMANAGER_H_
+
+#include "plugin.h"
+
+// global interfaces we are using
+extern _QERShadersTable g_ShadersTable;
+
+// NOTE: it's actually a module manager, the name should change to ModuleManager..
+class CPlugInManager  
+{
+private:
+  GSList* m_PlugIns;
+  CPtrArray m_BrushHandles;
+  CPtrArray m_SelectedBrushHandles;
+  CPtrArray m_ActiveBrushHandles;
+
+  // v1.70
+  //! brushes of the current entity ( see m_SelectedBrushHandles and m_ActiveBrushHandles )
+  CPtrArray m_EntityBrushHandles;
+  //! allocated entities, not commited yet ( see m_BrushHandles )
+  CPtrArray m_EntityHandles;
+
+  //! tells in which array to look when given a patch index
+  enum EPatchesMode { EActivePatches, ESelectedPatches, EAllocatedPatches } PatchesMode;
+  //! patches handles (brush_t*)
+  CPtrArray m_PatchesHandles;
+  //! plugin-allocated patches, not commited yet (patchMesh_t*)
+  CPtrArray m_PluginPatches;
+
+  void InitForDir(const Str &dir); ///< init for plguins/modules below this directory
+
+public:
+  CPtrArray& GetActiveHandles() {return m_ActiveBrushHandles; };
+  CPtrArray& GetSelectedHandles() {return m_SelectedBrushHandles; };
+  CPtrArray& GetPluginPatches() {return m_PluginPatches; };
+  brush_t* FindBrushHandle(void *vp);
+  patchMesh_t* FindPatchHandle(int index);
+  int CreatePatchHandle();
+  int AllocateActivePatchHandles();
+  int AllocateSelectedPatchHandles();
+  void CommitPatchHandleToMap(int index, patchMesh_t *pMesh, char *texName);
+  void CommitPatchHandleToEntity(int index, patchMesh_t *pMesh, char *texName, void *vpEntity);
+  void ReleasePatchesHandles() { m_PatchesHandles.RemoveAll(); m_PluginPatches.RemoveAll(); }
+  void AddFaceToBrushHandle(void *vp, vec3_t v1, vec3_t v2, vec3_t v3);
+  void CommitBrushHandleToMap(void *vp);
+  void DeleteBrushHandle(void* vp);
+  void* CreateBrushHandle();
+  void Dispatch(int n, const char *p);
+  void Cleanup(); ///< cleanup of data structures allocated for plugins, not a plugin reload
+  void Init(); ///< go through the path where we will find modules and plugins
+  void LoadImage (const char *name, unsigned char **pic, int *width, int *height);
+  void ImportMap (IDataStream *in, CPtrArray *ents, const char *type);
+  void ExportMap (CPtrArray *ents, IDataStream *out, const char *type);
+  void Shutdown(); ///< shutdown all the plugins/module subsystem
+  CPlugInManager();
+  virtual ~CPlugInManager();
+
+  /*! 
+  the texture manager front ends the single load
+  addins (texture, model, map formats.. etc.)
+  */
+  _QERTextureInfo* GetTextureInfo();
+  void LoadTexture(const char *pFilename);
+	
+void* GetSurfaceFlags();
+	
+  // v1.70
+  CPtrArray& GetEntityBrushHandles() {return m_EntityBrushHandles; };
+  CPtrArray& GetEntityHandles() {return m_EntityHandles; };
+  //! the vpBrush needs to be in m_BrushHandles
+  void CommitBrushHandleToEntity(void* vpBrush, void* vpEntity );
+  //! the vpEntity needs to be in m_EntityHandles
+  void CommitEntityHandleToMap( void* vpEntity );
+
+protected:
+  //! read the interfaces this plugin implements
+  void LoadFromPath(const char *path); ///< load all modules/plugins in specified path
+  void RegisterInterfaces();
+};
+
+class CPluginSlot : public IPlugIn
+{
+  APIDescriptor_t *mpAPI;
+  _QERPluginTable *mpTable;
+  /*!
+  is false until Init() happened
+  */
+  bool m_bReady;
+  /*!
+  below is valid only if m_bReady = true
+  */
+  GSList *m_CommandStrings;
+  GSList *m_CommandIDs;
+  
+public:
+  /*!
+  build directly from a SYN_PROVIDE interface
+  */
+  CPluginSlot(APIDescriptor_t *pAPI);
+  virtual ~CPluginSlot();
+  
+  APIDescriptor_t* GetDescriptor() { return mpAPI; }
+  /*!
+  initialize some management data after the synapse interfaces have been hooked up
+  */
+  void Init();
+  /*!
+  dispatching a command by name to the plugin
+  */
+  void Dispatch(const char *p);
+  
+  // IPlugIn ------------------------------------------------------------
+  const char* getMenuName();
+  int getCommandCount();
+  const char* getCommand(int n);  
+  void addMenuID(int n);
+  bool ownsCommandID(int n);
+  
+};
+
+class CRadiantPluginManager : public CSynapseAPIManager
+{
+  list<CPluginSlot *> mSlots;
+public:
+  CRadiantPluginManager() {}
+  virtual ~CRadiantPluginManager();
+  
+  // CSynapseAPIManager interface -------------------
+  APIDescriptor_t *BuildRequireAPI(APIDescriptor_t *pAPI);
+  
+  // CRadiantPluginManager --------------------------
+  void PopulateMenu();
+  bool Dispatch(int n, const char* p);
+};
+
+class CImageTableSlot
+{
+  /*!
+  \todo this is a duplicate from the APIDescriptor_t* list that privately stored inside CSynapseAPIManager
+  this is probably useless to us in here?
+  */
+  APIDescriptor_t *mpAPI;
+  /*!
+  shortcut to mpAPI->mpTable, with correct typing
+  this is what we allocate and should free locally
+  */
+  _QERPlugImageTable *mpTable;
+public:
+  CImageTableSlot() { }
+  virtual ~CImageTableSlot() { } ///\ \todo need to correctly free and release still..
+  
+  APIDescriptor_t* GetDescriptor() { return mpAPI; }
+  _QERPlugImageTable* GetTable() { return mpTable; }
+  
+  /*!
+  don't go through PrepareRequireAPI for init, just get this API and add the table info
+  */
+  void InitForFillAPITable(APIDescriptor_t *pAPI);
+};
+
+class CRadiantImageManager : public CSynapseAPIManager
+{
+  list<CImageTableSlot *> mSlots;
+  
+  list<CImageTableSlot *>::iterator mExtScanSlot;
+public:
+  CRadiantImageManager() {}
+  virtual ~CRadiantImageManager();
+  
+  // CSynapseAPIManager interface --------------------
+  void FillAPITable(APIDescriptor_t *pAPI);
+
+  // CRadiantImageManager ----------------------------
+  /*!
+  extract the extension, go through the list of image interfaces, and load
+  */
+  void LoadImage(const char *name, byte **pic, int *width, int *height);
+    
+  /*!
+  we often need to walk through the extensions
+  this used to be hardcoded in texwindow.cpp
+  the two functions are related, they use a static to go through the list
+  */
+  void BeginExtensionsScan();
+  const char* GetNextExtension(); ///< \return NULL when the list has been completely scanned
+};
+
+extern CRadiantImageManager g_ImageManager;
+
+#endif // _PLUGINMANAGER_H_
diff --git a/radiant/points.h b/radiant/points.h
index bc44cb8a..cb7641c7 100644
--- a/radiant/points.h
+++ b/radiant/points.h
@@ -1,57 +1,57 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// header for Pointfile stuff (adding a C++ class to wrap the pointfile thing in the SAX parser)
-//
-
-#ifndef __POINTS__
-#define __POINTS__
-
-void Pointfile_Delete (void);
-void WINAPI Pointfile_Check (void);
-void Pointfile_Next (void);
-void Pointfile_Prev (void);
-void Pointfile_Clear (void);
-void Pointfile_Draw( void );
-void Pointfile_Load( void );
-
-class CPointfile : public ISAXHandler
-{
-public:
-  CPointfile() { }
-  void Init();
-  void PushPoint (vec3_t v);
-  void GenerateDisplayList();
-  // SAX interface
-  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
-  void saxEndElement (message_info_t *ctx, const xmlChar *name);
-  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
-  char *getName();
-};
-
-// instead of using Pointfile_Load you can do it by hand through g_pointfile
-// but the usual pointfile mechanism remains the same, use Pointfile_Draw etc.
-extern CPointfile g_pointfile;
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// header for Pointfile stuff (adding a C++ class to wrap the pointfile thing in the SAX parser)
+//
+
+#ifndef __POINTS__
+#define __POINTS__
+
+void Pointfile_Delete (void);
+void WINAPI Pointfile_Check (void);
+void Pointfile_Next (void);
+void Pointfile_Prev (void);
+void Pointfile_Clear (void);
+void Pointfile_Draw( void );
+void Pointfile_Load( void );
+
+class CPointfile : public ISAXHandler
+{
+public:
+  CPointfile() { }
+  void Init();
+  void PushPoint (vec3_t v);
+  void GenerateDisplayList();
+  // SAX interface
+  void saxStartElement (message_info_t *ctx, const xmlChar *name, const xmlChar **attrs);
+  void saxEndElement (message_info_t *ctx, const xmlChar *name);
+  void saxCharacters (message_info_t *ctx, const xmlChar *ch, int len);
+  char *getName();
+};
+
+// instead of using Pointfile_Load you can do it by hand through g_pointfile
+// but the usual pointfile mechanism remains the same, use Pointfile_Draw etc.
+extern CPointfile g_pointfile;
+
+#endif
diff --git a/radiant/preferences.h b/radiant/preferences.h
index 7abd86eb..581c8fe7 100644
--- a/radiant/preferences.h
+++ b/radiant/preferences.h
@@ -1,628 +1,628 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _PREFERENCES_H_
-#define _PREFERENCES_H_
-
-#include "dialog.h"
-#include "gtkr_list.h"
-//#include "profile.h"
-
-#define MAX_TEXTURE_QUALITY 3
-
-enum PrefTypes_t
-{
-  PREF_STR,
-  PREF_INT,
-  PREF_BOOL,
-  PREF_FLOAT,
-  PREF_VEC3,
-  PREF_WNDPOS,
-};
-
-/*!
-a preference assignment, name, type and pointer to value
-we don't store the xmlNodePtr because the document itself can be thrown away upon any LoadPref
-(see CGameDialog::UpdatePrefTree)
-*/
-class CPrefAssignment
-{
-public:
-  Str mName;
-  PrefTypes_t mType;
-  void *mVal;
-
-  CPrefAssignment(char *name, PrefTypes_t Type, void *Val)
-  {
-    mName = name; mType = Type; mVal = Val;
-  }
-  CPrefAssignment() { mVal = NULL; }
-  CPrefAssignment(const CPrefAssignment& ass);
-  virtual ~CPrefAssignment() { }
-  virtual CPrefAssignment& operator =(const CPrefAssignment& ass);
-};
-
-
-/*!
-generic preferences storage class, using xml files
-*/
-class CXMLPropertyBag
-{
-private:
-  /*!
-  local prefs file
-  */
-  xmlDocPtr mpDoc;
-  xmlNodePtr mpDocNode;
-
-  /*!
-  prefs assignments (what pref name, what type, what variable)
-  */
-  list<CPrefAssignment> mPrefAssignments;
-
-  /*!
-  name of file to load/save as
-  */
-  Str mStrFilename;
-
-  /*!
-  store assignment in the property list if not already there
-  */
-  void PushAssignment(char *name, PrefTypes_t type, void *pV);
-
-  /*!
-  find the xmlnode relating to the epair name
-  */
-  xmlNodePtr EpairForName(const char *name);
-
-public:
-  CXMLPropertyBag();
-  virtual ~CXMLPropertyBag() 
-  {
-    if (InUse())
-      Clear();
-  };
-
-  /*!
-  read a pref setting, if doesn't exist, will add it to the xml tree (using default value provided)
-  \arg name the name of the pref
-  \arg pV pointer to the value
-  \arg V default value
-  those functions will fill in the list of preferences assignments
-    (name, type and pointer to value)
-    this is used in UpdatePrefTree
-  */
-  void GetPref(char *name, Str *pV, char *V);
-  void GetPref(char *name, int *pV, int V);
-  void GetPref(char *name, bool *pV, bool V);
-  void GetPref(char *name, float *pV, float V);
-  void GetPref(char *name, float *pV, float* V);
-  void GetPref(char *name, window_position_t* pV, window_position_t V);
-
-  /*!
-  returns whether or not the property bag is already open
-  */
-  qboolean InUse() { return (mpDoc != NULL); };
-
-  /*!
-  unload the xml doc, and free the tree
-  */
-  void Clear();
-
-  /*|
-  read data from our XML file
-  */
-  void ReadXMLFile(const char* pFilename);
-
-  /*|
-  write out the property bag to an XML data file
-  return is success/fail
-  */
-  qboolean WriteXMLFile(const char* pFilename);
-
-  /*!
-  update the xml tree with data form the property list, usually in preparation for a write
-  */
-  void UpdatePrefTree();
-
-  /*!
-  did the file have any data or not?
-  */
-  qboolean mbEmpty;
-};
-
-/*!
-holds information for a given game
-I'm a bit unclear on that still
-it holds game specific configuration stuff
-such as base names, engine names, some game specific features to activate in the various modules
-it is not strictly a prefs thing since the user is not supposed to edit that (unless he is hacking
-support for a new game)
-
-what we do now is fully generate the information for this during the setup. We might want to
-generate a piece that just says "the game pack is there", but put the rest of the config somwhere
-else (i.e. not generated, copied over during setup .. for instance in the game tools directory)
-*/
-class CGameDescription
-{
-public:
-  xmlDocPtr mpDoc; ///< the game description xml tree
-  Str mGameToolsPath; ///< the explicit path to the game-dependent modules
-  Str mGameName; ///< name of the game used in dialogs
-  Str mGameFile; ///< the .game file that describes this game
-  Str mBaseGame; ///< basegame directory
-  Str mEnginePath; ///< path to the engine
-  Str mEngine; ///< engine name
-#if defined (__linux__) || defined (__APPLE__)
-  Str mUserPathPrefix; ///< prefix for ~/.q3a ~/.wolf init, only on *nix
-#endif
-  Str mShaderPath; ///< the path in which to look for shaders
-  Str mShaderlist; ///< shaderlist file
-  float mTextureDefaultScale; ///< default scale (0.5 in q3, 1.0 in q1/q2, 0.25 in JK2 ..)
-  bool mEClassSingleLoad; ///< only load a single eclass definition file
-  bool mNoPatch; ///< this game doesn't support patch technology
-  Str mCaulkShader; ///< the shader to use for caulking
-
-  CGameDescription() { mpDoc = NULL; }
-  /*!
-  \todo parse basic info from the node
-  user-friendly name of the game
-  essential parameters (such as the start dir)
-  */
-  CGameDescription(xmlDocPtr pDoc, const Str &GameFile);
-  virtual ~CGameDescription() { xmlFreeDoc(mpDoc); }
-
-  void Dump();
-};
-
-/*!
-standalone dialog for games selection, and more generally global settings
-*/
-class CGameDialog : public Dialog
-{
-  GtkWidget *mFrame; ///< this is built on-demand first time it's used
-  GtkWidget *mTopBox; ///< top level box used to store the dialog frame, must unhook after modal use
-
-
-  /*!
-  global prefs storage
-  */
-  CXMLPropertyBag mGlobalPrefs;
-
-#ifdef _WIN32
-  /*!
-  run from a network share
-  this one is not being saved out in prefs, since we need to know before we load prefs
-  we use a dummy file NETRUN_FILENAME as flag
-  all done with static stuff
-  */
-  static bool m_bNetRun;
-#endif
-
-protected:
-  
-  int m_nComboSelect; ///< intermediate int value for combo in dialog box
-
-public:
-
-  /*! 
-  those settings are saved in the global prefs file 
-  I'm too lazy to wrap behind protected access, not sure this needs to be public
-  NOTE: those are preference settings. if you change them it is likely that you would
-  have to restart the editor for them to take effect
-  */
-  /*@{*/
-  /*!
-  what game has been selected
-  this is the name of the .game file
-  */
-  Str m_sGameFile;
-  /*!
-  auto-load the game on startup
-  this is linked to auto-load checkbox
-  */
-  bool m_bAutoLoadGame;
-  /*!
-  log console to radiant.log
-  m_bForceLogConsole is an obscure forced latching situation
-  */
-  bool m_bLogConsole;
-  bool m_bForceLogConsole;
-  /*@}*/
-
-  /*!
-  points somewhere in mGames, set once at startup
-  */
-  CGameDescription *m_pCurrentGameDescription;
-
-  /*!
-  the list of game descriptions we scanned from the game/ dir
-  */
-  list<CGameDescription *> mGames;
-
-  CGameDialog() { mFrame = NULL; m_pCurrentGameDescription = NULL; m_bLogConsole = false; m_bForceLogConsole = false; }
-  virtual ~CGameDialog(); 
-
-  void AddPacksURL(Str &s);  
-    
-  /*!
-  intialize the game dialog, called at CPrefsDlg::Init
-  will scan for games, load prefs, and do game selection dialog if needed
-  */
-  void Init();
-
-  /*!
-  reset the global settings by removing the file
-  */
-  void Reset();
-
-  /*!
-  run the dialog UI for the list of games 
-  */
-  void DoGameDialog();
-
-  /*!
-  Dialog API
-  this is only called when the dialog is built at startup for main engine select
-  */
-  void BuildDialog ();
-  void UpdateData (bool retrieve);
-
-  /*!
-  construction of the dialog frame
-  this is the part to be re-used in prefs dialog
-  for the standalone dialog, we include this in a modal box
-  for prefs, we hook the frame in the main notebook
-  build the frame on-demand (only once)
-  */
-  GtkWidget *GetGlobalFrame();
-
-  /*!
-  global preferences subsystem
-  XML-based this time, hopefully this will generalize to other prefs
-  LoadPrefs has hardcoded defaults
-  NOTE: it may not be strictly 'CGameDialog' to put the global prefs here
-    could have named the class differently I guess
-  */
-  /*@{*/
-  void LoadPrefs(); ///< load from file into variables
-  void SavePrefs(); ///< save pref variables to file
-  /*@}*/
-
-  /*!
-  read or set netrun (check file)
-  \param retrieve 
-    if false, will check if netrun file is present and will set m_bNetRun
-    if true, will create/erase the netrun file depending on m_bNetRun
-    NOTE: this is not backwards, 'retrieve' means 'retrieve from settings dialog' - in terms of UI
-  */
-  static void UpdateNetrun(bool retrieve);
-  /*!
-  get current netrun setting
-  */
-  static bool GetNetrun();
-
-private:
-  /*!
-  scan for .game files, load them
-  */
-  void ScanForGames();
-
-  /*!
-  inits g_PrefsDlg.m_global_rc_path
-  */
-  void InitGlobalPrefPath();
-
-  /*!
-  uses m_nComboItem to find the right mGames
-  */
-  CGameDescription *GameDescriptionForComboItem();
-};
-
-typedef struct {
-  int nEntitySplit1;
-  int nEntitySplit2;
-  
-  window_position_t position;
-
-  window_position_t posEntityWnd;
-  window_position_t posMapInfoWnd;
-  window_position_t posCamWnd;
-  window_position_t posZWnd;
-  window_position_t posXYWnd;
-  window_position_t posXZWnd;
-  window_position_t posYZWnd;
-  window_position_t posPatchWnd;
-  window_position_t posSurfaceWnd;
-  window_position_t posEntityInfoWnd;
-
-  int nXYHeight;
-  int nZWidth;
-  int nXYWidth;
-  int nCamWidth;
-  int nCamHeight;
-  int nZFloatWidth;
-  int nState;
-} windowPosInfo_t;
-
-class PrefsDlg : public Dialog
-{
-  
-public:
-  /*!
-  local prefs file
-  */
-  CXMLPropertyBag mLocalPrefs;
-
-  // will enable/disable stuff according to the situation
-  void DoSensitivity();
-  void PreModal() { DoSensitivity(); }
-  
-  // enable/disable custom editor entry
-  void DoEditorSensitivity();
-  
-  /*!
-  this holds global level preferences
-  */
-  CGameDialog mGamesDialog;
-protected:
-  // warning about old project files
-  bool m_bWarn;
-  list<CGameDescription *> mGames;
-  
-public:
-  // last light intensity used in the CLightPrompt dialog, stored in registry
-  int m_iLastLightIntensity;
-  // these mirror what goes in the combo box
-  // see PrefDlg::m_nShader, tells wether to load NONE / COMMON or ALL shaders at parsing stage
-  enum {SHADER_NONE = 0, SHADER_COMMON, SHADER_ALL};
-
-  // Gef: updated preferences dialog
-  /*! Preference notebook page numbers */
-  enum {PTAB_FRONT = 0, PTAB_GAME_SETTINGS, PTAB_2D, PTAB_CAMERA, PTAB_TEXTURE, PTAB_LAYOUT, PTAB_MOUSE,
-        PTAB_EDITING, PTAB_STARTUP, PTAB_PATHS, PTAB_MISC, PTAB_BSPMONITOR} pref_tabs;
-  
-  GtkWidget *notebook;
-       
-  void UpdateTextureCompression();
-
-#ifdef ATIHACK_812
-  void UpdateATIHack();
-#endif
-        
-  void LoadPrefs();
-  void SavePrefs();
-  void LoadTexdefPref(texdef_t* pTexdef, char* pName);
-
-  PrefsDlg ();
-  virtual ~PrefsDlg ()
-  {
-    g_string_free (m_rc_path, true );
-    g_string_free (m_inipath, true );
-  }
-
-  /*!
-  path for global settings
-  win32: g_strAppPath
-  linux: ~/.radiant/<version>/
-  */
-  GString *m_global_rc_path;
-
-  /*!
-  path to per-game settings
-  used for various game dependant storage
-  win32: g_strGameToolsPath
-  linux: ~/.radiant/<version>/<gamename>/
-  */
-  GString *m_rc_path;
-
-  /*!
-  holds per-game settings
-  m_rc_path+"local.pref"
-  \todo FIXME at some point this should become XML property bag code too
-  */
-  GString *m_inipath;
-
-  // initialize the above paths
-  void Init();
-
-#if 0
-  // DEPRECATED: use engine path from the current game description instead
-	// path to the top-level installation
-	Str 	m_strEnginePath;
-  // name of executable
-  // quake2 quake3 etc
-	Str 	m_strEngine;
-  // we use this Str to store the full path to the engine: m_strEnginePath + m_strEngine
-  // it's not stored in the registry or anything, just ued for display in prefs
-  Str   m_strPrefsDlgEngine;
-#endif
-
-  // Dialog Data
-  int   m_nMouse;
-  MainFrame::EViewStyle m_nView;
-  bool  m_bTextureLock;
-  bool  m_bLoadLast;
-	// path to the project loaded at startup
-	// if g_PrefsDlg can't find the information in the ini file
-	// it will try to guess and eventually ask the user
-  Str   m_strLastProject;  
-  /*!
-  version of last loaded project file
-  says -1 if there's no version loaded
-  if it's a manually constructed project file, will be 0
-  otherwise the actual 'version' epair
-  */
-  int   m_nLastProjectVer;
-  Str   m_strLastMap;
-  bool  m_bInternalBSP;
-  bool  m_bRightClick;
-  bool  m_bSetGame;
-  bool  m_bAutoSave;
-  bool  m_bLoadLastMap;
-  bool  m_bTextureWindow;
-  bool  m_bSnapShots;
-  float m_fTinySize;
-  bool  m_bCleanTiny;
-  bool  m_bCamXYUpdate;
-  int   m_nCamDragMultiSelect;
-  bool  m_bCamDragMultiSelect;
-  bool  m_bCamFreeLook;
-  bool  m_bCamFreeLookStrafe;
-  bool	m_bCamInverseMouse;
-  bool	m_bCamDiscrete;
-  bool  m_bNewLightDraw;
-  Str   m_strPrefabPath;
-  int   m_nWhatGame;
-  bool  m_bALTEdge;
-  bool  m_bFaceColors;
-  bool  m_bXZVis;
-  bool  m_bYZVis;
-  bool  m_bZVis;
-  bool  m_bSizePaint;
-  bool  m_bDLLEntities;
-  bool  m_bRotateLock;
-  bool  m_bDetachableMenus;
-  bool  m_bPatchToolbar;
-  bool  m_bWideToolbar;
-  bool  m_bPluginToolbar;
-  bool  m_bNoClamp;
-	//++timo this is most likely broken, I don't know what it's supposed to do
-  Str   m_strUserPath;
-  int   m_nRotation;
-  bool  m_bChaseMouse;
-  bool  m_bTextureScrollbar;
-  bool  m_bDisplayLists;
-  bool	m_bAntialiasedPointsAndLines; // Fishman - Add antialiazed points and lines support. 09/03/00
-  bool  m_bShowShaders;
-  int   m_nShader;
-  bool  m_bNoStipple;
-  int   m_nUndoLevels;
-  bool  m_bVertexSplit;
-
-  int   m_nMouseButtons;
-  int   m_nAngleSpeed;
-  int   m_nMoveSpeed;
-  int   m_nAutoSave;
-  bool  m_bCubicClipping;
-  int   m_nCubicScale;
-  bool  m_bSelectCurves;
-  bool  m_bSelectModels;
-  int   m_nEntityShowState;
-  int   m_nTextureScale;
-  bool  m_bNormalizeColors;
-  bool  m_bSwitchClip;
-  bool  m_bSelectWholeEntities;
-  int   m_nTextureQuality;
-  bool  m_bGLLighting;
-  bool  m_bTexturesShaderlistOnly;
-  int   m_nSubdivisions;
-  bool  m_bFloatingZ;
-  bool  m_bLatchedFloatingZ;
-  // Gef: Kyro GL_POINT workaround
-  bool	m_bGlPtWorkaround;
-
-  // how many menus in the texture thing before we split?
-  int   m_nTextureMenuSplit;
-
-  // watch the BSP process through network connections
-  // true: trigger the BSP steps one by one and monitor them through the network
-  // false: create a BAT / .sh file and execute it. don't bother monitoring it.
-  bool  m_bWatchBSP;
-  // do we stop the compilation process if we come accross a leak?
-  bool  m_bLeakStop;
-  // timeout when beginning a step (in seconds)
-  // if we don't get a connection quick enough we assume something failed and go back to idling
-  int   m_iTimeout;
-  bool  m_bRunQuake;
-  // store prefs setting for automatic sleep mode activation
-  bool  m_bDoSleep;
-  
-  bool m_bClipCaulk;
-
-  // make the texture increments match the grid changes
-  bool m_bSnapTToGrid;
-
-  // try to fix the target/targetname conflicts when importing a map (default true)
-  bool m_bDoTargetFix;
-
-  // the increment step we use against the wheel mouse
-  int m_nWheelInc;
-
-#ifdef _WIN32
-  // use the file associations to open files instead of builtin Gtk editor
-  bool m_bUseWin32Editor;
-#else
-  // custom shader editor
-  bool m_bUseCustomEditor;
-  Str  m_strEditorCommand;  // this is the command executed
-#endif
-
-#ifdef _WIN32
-  bool m_bNativeGUI;
-  bool m_bStartOnPrimMon;
-#endif
-
-  bool m_bPatchBBoxSelect;
-
-  // RR2DO2: latched data, for settings that require a restart. We don't want to set
-  // these directly in case users set them under preferences and then continue working
-  // with the editor.
-  MainFrame::EViewStyle m_nLatchedView;
-  int m_nMRUCount;
-  Str m_strMRUFiles[4];
-
-  windowPosInfo_t mWindowInfo;
-
-  bool  m_bLatchedDetachableMenus;
-  bool  m_bLatchedPatchToolbar;
-  bool  m_bLatchedWideToolbar;
-  bool  m_bLatchedPluginToolbar;
-  int   m_nLatchedShader;
-  int   m_nLatchedTextureQuality;
-
-  // RIANT
-  // texture compression format
-  int m_nTextureCompressionFormat;
-
-  int m_nLightRadiuses;
-  
-  bool m_bQ3Map2Texturing;
-
-#ifdef ATIHACK_812
-	bool m_bGlATIHack;
-#endif
-
-  void UpdateData (bool retrieve);
-
-  /*! Utility function for swapping notebook pages for tree list selections */
-  void showPrefPage(int prefpage);
-
-protected:
-  /*! Scan for game description files and build a list */
-  void ScanForGames();
-
-  /*! Dialog API */
-  void BuildDialog ();
-  void PostModal (int code);
-};
-
-#endif // _PREFERENCES_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _PREFERENCES_H_
+#define _PREFERENCES_H_
+
+#include "dialog.h"
+#include "gtkr_list.h"
+//#include "profile.h"
+
+#define MAX_TEXTURE_QUALITY 3
+
+enum PrefTypes_t
+{
+  PREF_STR,
+  PREF_INT,
+  PREF_BOOL,
+  PREF_FLOAT,
+  PREF_VEC3,
+  PREF_WNDPOS,
+};
+
+/*!
+a preference assignment, name, type and pointer to value
+we don't store the xmlNodePtr because the document itself can be thrown away upon any LoadPref
+(see CGameDialog::UpdatePrefTree)
+*/
+class CPrefAssignment
+{
+public:
+  Str mName;
+  PrefTypes_t mType;
+  void *mVal;
+
+  CPrefAssignment(char *name, PrefTypes_t Type, void *Val)
+  {
+    mName = name; mType = Type; mVal = Val;
+  }
+  CPrefAssignment() { mVal = NULL; }
+  CPrefAssignment(const CPrefAssignment& ass);
+  virtual ~CPrefAssignment() { }
+  virtual CPrefAssignment& operator =(const CPrefAssignment& ass);
+};
+
+
+/*!
+generic preferences storage class, using xml files
+*/
+class CXMLPropertyBag
+{
+private:
+  /*!
+  local prefs file
+  */
+  xmlDocPtr mpDoc;
+  xmlNodePtr mpDocNode;
+
+  /*!
+  prefs assignments (what pref name, what type, what variable)
+  */
+  list<CPrefAssignment> mPrefAssignments;
+
+  /*!
+  name of file to load/save as
+  */
+  Str mStrFilename;
+
+  /*!
+  store assignment in the property list if not already there
+  */
+  void PushAssignment(char *name, PrefTypes_t type, void *pV);
+
+  /*!
+  find the xmlnode relating to the epair name
+  */
+  xmlNodePtr EpairForName(const char *name);
+
+public:
+  CXMLPropertyBag();
+  virtual ~CXMLPropertyBag() 
+  {
+    if (InUse())
+      Clear();
+  };
+
+  /*!
+  read a pref setting, if doesn't exist, will add it to the xml tree (using default value provided)
+  \arg name the name of the pref
+  \arg pV pointer to the value
+  \arg V default value
+  those functions will fill in the list of preferences assignments
+    (name, type and pointer to value)
+    this is used in UpdatePrefTree
+  */
+  void GetPref(char *name, Str *pV, char *V);
+  void GetPref(char *name, int *pV, int V);
+  void GetPref(char *name, bool *pV, bool V);
+  void GetPref(char *name, float *pV, float V);
+  void GetPref(char *name, float *pV, float* V);
+  void GetPref(char *name, window_position_t* pV, window_position_t V);
+
+  /*!
+  returns whether or not the property bag is already open
+  */
+  qboolean InUse() { return (mpDoc != NULL); };
+
+  /*!
+  unload the xml doc, and free the tree
+  */
+  void Clear();
+
+  /*|
+  read data from our XML file
+  */
+  void ReadXMLFile(const char* pFilename);
+
+  /*|
+  write out the property bag to an XML data file
+  return is success/fail
+  */
+  qboolean WriteXMLFile(const char* pFilename);
+
+  /*!
+  update the xml tree with data form the property list, usually in preparation for a write
+  */
+  void UpdatePrefTree();
+
+  /*!
+  did the file have any data or not?
+  */
+  qboolean mbEmpty;
+};
+
+/*!
+holds information for a given game
+I'm a bit unclear on that still
+it holds game specific configuration stuff
+such as base names, engine names, some game specific features to activate in the various modules
+it is not strictly a prefs thing since the user is not supposed to edit that (unless he is hacking
+support for a new game)
+
+what we do now is fully generate the information for this during the setup. We might want to
+generate a piece that just says "the game pack is there", but put the rest of the config somwhere
+else (i.e. not generated, copied over during setup .. for instance in the game tools directory)
+*/
+class CGameDescription
+{
+public:
+  xmlDocPtr mpDoc; ///< the game description xml tree
+  Str mGameToolsPath; ///< the explicit path to the game-dependent modules
+  Str mGameName; ///< name of the game used in dialogs
+  Str mGameFile; ///< the .game file that describes this game
+  Str mBaseGame; ///< basegame directory
+  Str mEnginePath; ///< path to the engine
+  Str mEngine; ///< engine name
+#if defined (__linux__) || defined (__APPLE__)
+  Str mUserPathPrefix; ///< prefix for ~/.q3a ~/.wolf init, only on *nix
+#endif
+  Str mShaderPath; ///< the path in which to look for shaders
+  Str mShaderlist; ///< shaderlist file
+  float mTextureDefaultScale; ///< default scale (0.5 in q3, 1.0 in q1/q2, 0.25 in JK2 ..)
+  bool mEClassSingleLoad; ///< only load a single eclass definition file
+  bool mNoPatch; ///< this game doesn't support patch technology
+  Str mCaulkShader; ///< the shader to use for caulking
+
+  CGameDescription() { mpDoc = NULL; }
+  /*!
+  \todo parse basic info from the node
+  user-friendly name of the game
+  essential parameters (such as the start dir)
+  */
+  CGameDescription(xmlDocPtr pDoc, const Str &GameFile);
+  virtual ~CGameDescription() { xmlFreeDoc(mpDoc); }
+
+  void Dump();
+};
+
+/*!
+standalone dialog for games selection, and more generally global settings
+*/
+class CGameDialog : public Dialog
+{
+  GtkWidget *mFrame; ///< this is built on-demand first time it's used
+  GtkWidget *mTopBox; ///< top level box used to store the dialog frame, must unhook after modal use
+
+
+  /*!
+  global prefs storage
+  */
+  CXMLPropertyBag mGlobalPrefs;
+
+#ifdef _WIN32
+  /*!
+  run from a network share
+  this one is not being saved out in prefs, since we need to know before we load prefs
+  we use a dummy file NETRUN_FILENAME as flag
+  all done with static stuff
+  */
+  static bool m_bNetRun;
+#endif
+
+protected:
+  
+  int m_nComboSelect; ///< intermediate int value for combo in dialog box
+
+public:
+
+  /*! 
+  those settings are saved in the global prefs file 
+  I'm too lazy to wrap behind protected access, not sure this needs to be public
+  NOTE: those are preference settings. if you change them it is likely that you would
+  have to restart the editor for them to take effect
+  */
+  /*@{*/
+  /*!
+  what game has been selected
+  this is the name of the .game file
+  */
+  Str m_sGameFile;
+  /*!
+  auto-load the game on startup
+  this is linked to auto-load checkbox
+  */
+  bool m_bAutoLoadGame;
+  /*!
+  log console to radiant.log
+  m_bForceLogConsole is an obscure forced latching situation
+  */
+  bool m_bLogConsole;
+  bool m_bForceLogConsole;
+  /*@}*/
+
+  /*!
+  points somewhere in mGames, set once at startup
+  */
+  CGameDescription *m_pCurrentGameDescription;
+
+  /*!
+  the list of game descriptions we scanned from the game/ dir
+  */
+  list<CGameDescription *> mGames;
+
+  CGameDialog() { mFrame = NULL; m_pCurrentGameDescription = NULL; m_bLogConsole = false; m_bForceLogConsole = false; }
+  virtual ~CGameDialog(); 
+
+  void AddPacksURL(Str &s);  
+    
+  /*!
+  intialize the game dialog, called at CPrefsDlg::Init
+  will scan for games, load prefs, and do game selection dialog if needed
+  */
+  void Init();
+
+  /*!
+  reset the global settings by removing the file
+  */
+  void Reset();
+
+  /*!
+  run the dialog UI for the list of games 
+  */
+  void DoGameDialog();
+
+  /*!
+  Dialog API
+  this is only called when the dialog is built at startup for main engine select
+  */
+  void BuildDialog ();
+  void UpdateData (bool retrieve);
+
+  /*!
+  construction of the dialog frame
+  this is the part to be re-used in prefs dialog
+  for the standalone dialog, we include this in a modal box
+  for prefs, we hook the frame in the main notebook
+  build the frame on-demand (only once)
+  */
+  GtkWidget *GetGlobalFrame();
+
+  /*!
+  global preferences subsystem
+  XML-based this time, hopefully this will generalize to other prefs
+  LoadPrefs has hardcoded defaults
+  NOTE: it may not be strictly 'CGameDialog' to put the global prefs here
+    could have named the class differently I guess
+  */
+  /*@{*/
+  void LoadPrefs(); ///< load from file into variables
+  void SavePrefs(); ///< save pref variables to file
+  /*@}*/
+
+  /*!
+  read or set netrun (check file)
+  \param retrieve 
+    if false, will check if netrun file is present and will set m_bNetRun
+    if true, will create/erase the netrun file depending on m_bNetRun
+    NOTE: this is not backwards, 'retrieve' means 'retrieve from settings dialog' - in terms of UI
+  */
+  static void UpdateNetrun(bool retrieve);
+  /*!
+  get current netrun setting
+  */
+  static bool GetNetrun();
+
+private:
+  /*!
+  scan for .game files, load them
+  */
+  void ScanForGames();
+
+  /*!
+  inits g_PrefsDlg.m_global_rc_path
+  */
+  void InitGlobalPrefPath();
+
+  /*!
+  uses m_nComboItem to find the right mGames
+  */
+  CGameDescription *GameDescriptionForComboItem();
+};
+
+typedef struct {
+  int nEntitySplit1;
+  int nEntitySplit2;
+  
+  window_position_t position;
+
+  window_position_t posEntityWnd;
+  window_position_t posMapInfoWnd;
+  window_position_t posCamWnd;
+  window_position_t posZWnd;
+  window_position_t posXYWnd;
+  window_position_t posXZWnd;
+  window_position_t posYZWnd;
+  window_position_t posPatchWnd;
+  window_position_t posSurfaceWnd;
+  window_position_t posEntityInfoWnd;
+
+  int nXYHeight;
+  int nZWidth;
+  int nXYWidth;
+  int nCamWidth;
+  int nCamHeight;
+  int nZFloatWidth;
+  int nState;
+} windowPosInfo_t;
+
+class PrefsDlg : public Dialog
+{
+  
+public:
+  /*!
+  local prefs file
+  */
+  CXMLPropertyBag mLocalPrefs;
+
+  // will enable/disable stuff according to the situation
+  void DoSensitivity();
+  void PreModal() { DoSensitivity(); }
+  
+  // enable/disable custom editor entry
+  void DoEditorSensitivity();
+  
+  /*!
+  this holds global level preferences
+  */
+  CGameDialog mGamesDialog;
+protected:
+  // warning about old project files
+  bool m_bWarn;
+  list<CGameDescription *> mGames;
+  
+public:
+  // last light intensity used in the CLightPrompt dialog, stored in registry
+  int m_iLastLightIntensity;
+  // these mirror what goes in the combo box
+  // see PrefDlg::m_nShader, tells wether to load NONE / COMMON or ALL shaders at parsing stage
+  enum {SHADER_NONE = 0, SHADER_COMMON, SHADER_ALL};
+
+  // Gef: updated preferences dialog
+  /*! Preference notebook page numbers */
+  enum {PTAB_FRONT = 0, PTAB_GAME_SETTINGS, PTAB_2D, PTAB_CAMERA, PTAB_TEXTURE, PTAB_LAYOUT, PTAB_MOUSE,
+        PTAB_EDITING, PTAB_STARTUP, PTAB_PATHS, PTAB_MISC, PTAB_BSPMONITOR} pref_tabs;
+  
+  GtkWidget *notebook;
+       
+  void UpdateTextureCompression();
+
+#ifdef ATIHACK_812
+  void UpdateATIHack();
+#endif
+        
+  void LoadPrefs();
+  void SavePrefs();
+  void LoadTexdefPref(texdef_t* pTexdef, char* pName);
+
+  PrefsDlg ();
+  virtual ~PrefsDlg ()
+  {
+    g_string_free (m_rc_path, true );
+    g_string_free (m_inipath, true );
+  }
+
+  /*!
+  path for global settings
+  win32: g_strAppPath
+  linux: ~/.radiant/<version>/
+  */
+  GString *m_global_rc_path;
+
+  /*!
+  path to per-game settings
+  used for various game dependant storage
+  win32: g_strGameToolsPath
+  linux: ~/.radiant/<version>/<gamename>/
+  */
+  GString *m_rc_path;
+
+  /*!
+  holds per-game settings
+  m_rc_path+"local.pref"
+  \todo FIXME at some point this should become XML property bag code too
+  */
+  GString *m_inipath;
+
+  // initialize the above paths
+  void Init();
+
+#if 0
+  // DEPRECATED: use engine path from the current game description instead
+	// path to the top-level installation
+	Str 	m_strEnginePath;
+  // name of executable
+  // quake2 quake3 etc
+	Str 	m_strEngine;
+  // we use this Str to store the full path to the engine: m_strEnginePath + m_strEngine
+  // it's not stored in the registry or anything, just ued for display in prefs
+  Str   m_strPrefsDlgEngine;
+#endif
+
+  // Dialog Data
+  int   m_nMouse;
+  MainFrame::EViewStyle m_nView;
+  bool  m_bTextureLock;
+  bool  m_bLoadLast;
+	// path to the project loaded at startup
+	// if g_PrefsDlg can't find the information in the ini file
+	// it will try to guess and eventually ask the user
+  Str   m_strLastProject;  
+  /*!
+  version of last loaded project file
+  says -1 if there's no version loaded
+  if it's a manually constructed project file, will be 0
+  otherwise the actual 'version' epair
+  */
+  int   m_nLastProjectVer;
+  Str   m_strLastMap;
+  bool  m_bInternalBSP;
+  bool  m_bRightClick;
+  bool  m_bSetGame;
+  bool  m_bAutoSave;
+  bool  m_bLoadLastMap;
+  bool  m_bTextureWindow;
+  bool  m_bSnapShots;
+  float m_fTinySize;
+  bool  m_bCleanTiny;
+  bool  m_bCamXYUpdate;
+  int   m_nCamDragMultiSelect;
+  bool  m_bCamDragMultiSelect;
+  bool  m_bCamFreeLook;
+  bool  m_bCamFreeLookStrafe;
+  bool	m_bCamInverseMouse;
+  bool	m_bCamDiscrete;
+  bool  m_bNewLightDraw;
+  Str   m_strPrefabPath;
+  int   m_nWhatGame;
+  bool  m_bALTEdge;
+  bool  m_bFaceColors;
+  bool  m_bXZVis;
+  bool  m_bYZVis;
+  bool  m_bZVis;
+  bool  m_bSizePaint;
+  bool  m_bDLLEntities;
+  bool  m_bRotateLock;
+  bool  m_bDetachableMenus;
+  bool  m_bPatchToolbar;
+  bool  m_bWideToolbar;
+  bool  m_bPluginToolbar;
+  bool  m_bNoClamp;
+	//++timo this is most likely broken, I don't know what it's supposed to do
+  Str   m_strUserPath;
+  int   m_nRotation;
+  bool  m_bChaseMouse;
+  bool  m_bTextureScrollbar;
+  bool  m_bDisplayLists;
+  bool	m_bAntialiasedPointsAndLines; // Fishman - Add antialiazed points and lines support. 09/03/00
+  bool  m_bShowShaders;
+  int   m_nShader;
+  bool  m_bNoStipple;
+  int   m_nUndoLevels;
+  bool  m_bVertexSplit;
+
+  int   m_nMouseButtons;
+  int   m_nAngleSpeed;
+  int   m_nMoveSpeed;
+  int   m_nAutoSave;
+  bool  m_bCubicClipping;
+  int   m_nCubicScale;
+  bool  m_bSelectCurves;
+  bool  m_bSelectModels;
+  int   m_nEntityShowState;
+  int   m_nTextureScale;
+  bool  m_bNormalizeColors;
+  bool  m_bSwitchClip;
+  bool  m_bSelectWholeEntities;
+  int   m_nTextureQuality;
+  bool  m_bGLLighting;
+  bool  m_bTexturesShaderlistOnly;
+  int   m_nSubdivisions;
+  bool  m_bFloatingZ;
+  bool  m_bLatchedFloatingZ;
+  // Gef: Kyro GL_POINT workaround
+  bool	m_bGlPtWorkaround;
+
+  // how many menus in the texture thing before we split?
+  int   m_nTextureMenuSplit;
+
+  // watch the BSP process through network connections
+  // true: trigger the BSP steps one by one and monitor them through the network
+  // false: create a BAT / .sh file and execute it. don't bother monitoring it.
+  bool  m_bWatchBSP;
+  // do we stop the compilation process if we come accross a leak?
+  bool  m_bLeakStop;
+  // timeout when beginning a step (in seconds)
+  // if we don't get a connection quick enough we assume something failed and go back to idling
+  int   m_iTimeout;
+  bool  m_bRunQuake;
+  // store prefs setting for automatic sleep mode activation
+  bool  m_bDoSleep;
+  
+  bool m_bClipCaulk;
+
+  // make the texture increments match the grid changes
+  bool m_bSnapTToGrid;
+
+  // try to fix the target/targetname conflicts when importing a map (default true)
+  bool m_bDoTargetFix;
+
+  // the increment step we use against the wheel mouse
+  int m_nWheelInc;
+
+#ifdef _WIN32
+  // use the file associations to open files instead of builtin Gtk editor
+  bool m_bUseWin32Editor;
+#else
+  // custom shader editor
+  bool m_bUseCustomEditor;
+  Str  m_strEditorCommand;  // this is the command executed
+#endif
+
+#ifdef _WIN32
+  bool m_bNativeGUI;
+  bool m_bStartOnPrimMon;
+#endif
+
+  bool m_bPatchBBoxSelect;
+
+  // RR2DO2: latched data, for settings that require a restart. We don't want to set
+  // these directly in case users set them under preferences and then continue working
+  // with the editor.
+  MainFrame::EViewStyle m_nLatchedView;
+  int m_nMRUCount;
+  Str m_strMRUFiles[4];
+
+  windowPosInfo_t mWindowInfo;
+
+  bool  m_bLatchedDetachableMenus;
+  bool  m_bLatchedPatchToolbar;
+  bool  m_bLatchedWideToolbar;
+  bool  m_bLatchedPluginToolbar;
+  int   m_nLatchedShader;
+  int   m_nLatchedTextureQuality;
+
+  // RIANT
+  // texture compression format
+  int m_nTextureCompressionFormat;
+
+  int m_nLightRadiuses;
+  
+  bool m_bQ3Map2Texturing;
+
+#ifdef ATIHACK_812
+	bool m_bGlATIHack;
+#endif
+
+  void UpdateData (bool retrieve);
+
+  /*! Utility function for swapping notebook pages for tree list selections */
+  void showPrefPage(int prefpage);
+
+protected:
+  /*! Scan for game description files and build a list */
+  void ScanForGames();
+
+  /*! Dialog API */
+  void BuildDialog ();
+  void PostModal (int code);
+};
+
+#endif // _PREFERENCES_H_
diff --git a/radiant/qe3.h b/radiant/qe3.h
index 5f8c815d..e1b9d2bc 100644
--- a/radiant/qe3.h
+++ b/radiant/qe3.h
@@ -1,912 +1,912 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _QE3_H_
-#define _QE3_H_
-
-#ifdef _WIN32
-
-// disable data conversion warnings for gl
-#pragma warning(disable : 4244)     // MIPS
-#pragma warning(disable : 4136)     // X86
-#pragma warning(disable : 4051)     // ALPHA
-#pragma warning(disable : 4800)
-#endif
-
-// for interfaces, we require main plugin header included
-#include "iplugin.h"
-#include "qerplugin.h"
-#include "qertypes.h"
-
-#include "missing.h" // temporary stuff, needs to be removed
-#include "idatastream.h"
-#include "file.h"
-
-#include "qgl.h"
-
-#include <gtk/gtk.h>
-#include <math.h>
-#include <stdlib.h>
-
-#include <stdio.h>
-
-// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=672
-// this is the version to expect from template projects
-#define PROJECT_VERSION 2
-
-//#define MEM_DEBUG
-#ifdef MEM_DEBUG
-
-#define malloc(a) debug_malloc(a, __FILE__, __LINE__)
-#define free(a) debug_free(a, __FILE__, __LINE__)
-
-void* debug_malloc (size_t size, const char* file, int line);
-void debug_free (void *buf, const char* file, int line);
-
-#endif
-
-#ifdef _DEBUG
-//#define DBG_WINDOWPOS
-#endif
-
-#ifdef DBG_WINDOWPOS
-void CheckWatchit(char *msg);
-#endif
-
-// those two files are generated
-// if they are missing, you NEED to run makeversion.sh
-// NOTE: for win32 users, cygwin installation is REQUIRED to run makeversion.sh
-// NOTE TTimo if any of those changes (they might change a lot), then the whole app is rebuilt.
-//   very often it's not necessary
-#include "version.h"
-#include "aboutmsg.h"
-
-// synapse is our utility lib for dynamic shared objects management
-#include "synapse.h"
-
-#include "qertypes.h"
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "parse.h"
-
-#include "qedefs.h"
-#include "qfiles.h"
-#include "textures.h"
-#include "brush.h"
-//#include "entity.h"
-#define USE_ENTITYTABLE_DEFINE
-#include "ientity.h"
-extern _QEREntityTable __ENTITYTABLENAME;
-// wrappers for brush access
-#include "ibrush.h"
-// wrappers for patch access
-#include "ipatch.h"
-
-#include "imodel.h"
-
-#include "imap.h"
-
-#include "iundo.h"
-
-extern _QERPlugMapTable g_MapTable;
-
-//++timo for BP conversion escaping FIXME: remove when mixing two formats!
-extern bool g_bCancel_Map_LoadFile;
-// used to be #defines, multiple engine support suggests we should go towards dynamic
-extern int g_MaxWorldCoord;
-extern int g_MinWorldCoord;
-extern int g_MaxBrushSize;
-/*
-// set to true when we are parsing a terrain entity
-extern bool g_bParseTerrain;
-extern IShader *g_pTerrainShader, *g_pCaulk;
-*/
-#include "map.h"
-
-#include "select.h"
-
-#include "camera.h"
-#include "z.h"
-
-#include "undo.h"
-#include "glwidget.h"
-
-// the dec offsetof macro doesn't work very well...
-#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
-
-// set these before calling CheckParm
-extern int myargc;
-extern char **myargv;
-
-// our own implementation of Q_int, clamping can be disabled on prefs
-vec_t Rad_rint (vec_t in);
-
-double I_FloatTime (void);
-
-void   Error (char *error, ...);
-int    CheckParm (char *check);
-void   ParseCommandLine (char *lpCmdLine);
-
-int    ParseNum (char *str);
-
-char*  COM_Parse (char *data);
-char*  Get_COM_Token();
-
-extern	char		com_token[1024];
-extern	qboolean	com_eof;
-
-#define	MAX_NUM_ARGVS	32
-extern	int		argc;
-extern	char	        *argv[MAX_NUM_ARGVS];
-
-//
-// system functions
-//
-// TTimo NOTE: WINAPI funcs can be accessed by plugins
-void    Sys_UpdateStatusBar( void );
-void    WINAPI Sys_UpdateWindows (int bits);
-void    Sys_Beep (void);
-void    Sys_ClearPrintf (void);
-double	Sys_DoubleTime (void);
-void    Sys_GetCursorPos (int *x, int *y);
-void    Sys_SetCursorPos (int x, int y);
-void    Sys_SetTitle (const char *text);
-void    WINAPI Sys_BeginWait (void);
-void    WINAPI Sys_EndWait (void);
-void    Sys_Status(const char *psz, int part);
-bool    Sys_AltDown ();
-bool    Sys_ShiftDown ();
-// will open/close/check the log file based on the following globals:
-// g_PrefsDlg.m_bLogConsole g_qeglobals.hLogFile
-void    Sys_LogFile (void);
-
-extern  qboolean verbose;
-#include "qsysprintf.h"
-
-// NOTE TTimo I split out the GUI-depependant stuff from QEGlobals_t into a seperate struct
-typedef struct
-{
-  // GL widget of the camera view
-  // all textures are binded in this context and shared with the others
-  GtkWidget *d_glBase;
-
-  GtkWidget *d_main_window; // d_hwndMain
-  GtkWidget *d_edit;        // d_hwndEdit
-  GtkWidget *d_entity;      // d_hwndEntity
-  GtkWidget *d_camera;      // d_hwndCamera;
-  GtkWidget *d_texture;     // d_hwndTexture;
-  GtkWidget *d_texture_scroll;
-  GtkWidget *d_z;           // d_hwndZ;
-
-} QEGlobals_GUI_t;
-
-// usefull portability stuff
-//++timo move them somewhere
-bool DoesFileExist(const char* pBuff, long& lSize);
-
-char *copystring (char *s);
-char *ExpandReletivePath (char *p);
-
-#include "xmlstuff.h"
-#include "points.h"
-
-//
-// drag.c
-//
-void Drag_Begin (int x, int y, int buttons, vec3_t xaxis, vec3_t yaxis, vec3_t origin, vec3_t dir, bool sf_camera = false);
-void Drag_MouseMoved (int x, int y, int buttons);
-void Drag_MouseUp (int nButtons = 0);
-
-//
-// csg.c
-//
-void CSG_MakeHollow (void);
-void CSG_Subtract (void);
-void CSG_Merge (void);
-
-//
-// vertsel.c
-//
-
-void SetupVertexSelection (void);
-void SelectEdgeByRay (vec3_t org, vec3_t dir);
-void SelectVertexByRay (vec3_t org, vec3_t dir);
-
-void ConnectEntities (void);
-
-extern	int	update_bits;
-
-extern	int	screen_width;
-extern	int	screen_height;
-
-char *TranslateString (char *buf);
-
-//
-// linux_qe3.cc
-//
-//void OpenDialog ();
-//void SaveAsDialog (bool bRegion);
-void ProjectDialog (void);
-void MRU_Load ();
-void MRU_Save ();
-void MRU_AddWidget (GtkWidget *widget, int pos);
-void MRU_AddFile (const char *str);
-void MRU_Activate (int index);
-
-
-void FillTextureMenu (GSList** pArray = NULL);
-void FillBSPMenu (void);
-
-// profile functions - kind of utility lib
-// they are kind of dumb, they expect to get the path to the .ini file or to the prefs directory when called
-// load_buffer and save_buffer expect the path only, theyll build a $(pszName).bin file
-bool WINAPI profile_save_int (const char *filename, const char *section, const char *key, int value);
-bool WINAPI profile_save_float (const char *filename, const char *section, const char *key, float value);
-bool WINAPI profile_save_string (const char *filename, const char *section, const char *key, const char *value);
-bool profile_save_buffer (const char *rc_path, const char *pszName, void *pvBuf, guint32 lSize);
-bool profile_load_buffer (const char *rc_path, const char *pszName, void *pvBuf, guint32 *plSize);
-int WINAPI profile_load_int (const char *filename, const char *section, const char *key, int default_value);
-float WINAPI profile_load_float (const char *filename, const char *section, const char *key, float default_value);
-char* WINAPI profile_load_string (const char *filename, const char *section, const char *key, const char *default_value);
-// used in the command map code
-bool read_var (const char *filename, const char *section, const char *key, char *value);
-
-//
-// entityw.c
-//
-void FillClassList (void);
-bool UpdateEntitySel(eclass_t *pec);	
-void SetInspectorMode(int iType);
-void SetSpawnFlags(void);
-void GetSpawnFlags(void);
-void SetKeyValuePairs(bool bClearMD3 = false);
-extern void BuildGammaTable(float g);
-bool GetSelectAllCriteria(CString &strKey, CString &strVal);
-
-// linux_dlg.c
-
-typedef enum {
-  BEVEL = 0,
-  ENDCAP,
-  IBEVEL,
-  IENDCAP
-} CapDialog;
-
-int DoCapDlg (int *type, bool *b_GroupResul);
-int DoBSInputDlg (const char *fields[5], float values[5]);
-int DoTextureLayout (float *fx, float *fy);
-char* DoNameDlg (const char* title);
-char* DoNewProjectDlg ();
-/*
-text editor, open filename at given line
-opening at line works only for win32 / editpad and builtin Gtk editor
-
-we only allow one instance of the Gtk editor widget opened at a given time
-if we get called with an existing instance, switch to new file ..
-*/
-void DoTextEditor (const char* filename, int cursorpos);
-int DoLightIntensityDlg (int *intensity);
-
-void DoMapInfo ();
-void DoEntityList ();
-void DoGamma();
-void DoFind();
-void DoRotateDlg ();
-void DoSides(bool bCone = false, bool bSphere = false, bool bTorus = false);
-void DoAbout();
-void DoSnapTToGrid(float hscale = 0.0f, float vscale = 0.0f);
-void DoSurface();
-void ToggleSurface(); // will show/hide depending on the current state
-void DoNewPatchDlg ();
-void DoThickenDlg ();
-void DoCommandListDlg ();
-void DoScaleDlg ();;
-void DoTextureListDlg ();
-void DoScriptsDlg ();
-
-// QE function declarations
-void     QE_CheckAutoSave( void );
-void     WINAPI QE_ConvertDOSToUnixName( char *dst, const char *src );
-void     QE_CountBrushesAndUpdateStatusBar( void );
-void     WINAPI QE_CheckOpenGLForErrors(void);
-void     QE_ExpandBspString (char *bspaction, GPtrArray & out, char *mapname);
-// initialise the VFS from current project settings
-void     QE_InitVFS();
-// do all initialisations that should happen after a project is load (during startup or project change)
-void     QE_Init (void);
-qboolean QE_KeyDown (int key, int nFlags = 0);
-// does some sanity checks on the project entity, such as removing ending filename seperators from paths
-// (this usually gets propagated to the actual project file since most of the time we save right after calling the check)
-void     QE_CheckProjectEntity();
-// this will load a new project entity in memory, and potentially process it from a template
-// NOTE TTimo calling QE_LoadProject won't take care of the various initialisation that are performed depending on the project settings
-//   you should then call QE_Init for that
-#define PROJECT_TEMPLATE_NAME "default_project.proj"
-#define PROJECT_USER_NAME "user_project.proj"
-#define PROJECT_FILETYPE "proj"
-qboolean QE_LoadProject (const char *projectfile);
-qboolean QE_SingleBrush (bool bQuiet = false);
-
-
-// sys stuff
-void Sys_MarkMapModified (void);
-
-#if 0 // no longer used
-
-// QE Win32 function declarations
-#ifdef _WIN32
-int  WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer );
-void QEW_StopGL( HWND hWnd, HGLRC hGLRC, HDC hDC );
-#endif
-
-#endif
-
-// extern declarations
-extern QEGlobals_t   g_qeglobals;
-extern QEGlobals_GUI_t g_qeglobals_gui;
-
-qboolean IsBrushSelected(brush_t* bSel);
-
-// curve brushes
-
-void Curve_MakeCurvedBrush (qboolean negative, qboolean top, qboolean bottom, 
-					qboolean s1, qboolean s2, qboolean s3, qboolean s4);
-
-void Curve_Invert (void);
-
-void Curve_AddFakePlanes( brush_t *B );
-void Curve_StripFakePlanes( brush_t *B );
-void Curve_BuildPoints (brush_t *b);
-void Curve_XYDraw (brush_t *b);
-void Curve_CameraDraw (brush_t *b);
-
-void Curve_WriteFile (char *name);
-
-
-// patch stuff
-patchMesh_t *Patch_Alloc();
-patchMesh_t* MakeNewPatch();
-brush_t* AddBrushForPatch(patchMesh_t *pm, bool bLinkToWorld = true);
-brush_t* Patch_GenericMesh(int nWidth, int nHeight, int nOrientation = 2, bool bDeleteSource = true, bool bOverride = false);
-//void Patch_ReadFile (char *name);
-//void Patch_WriteFile (char *name); 
-void Patch_BuildPoints (brush_t *b);
-void Patch_Move(patchMesh_t *p, const vec3_t vMove, bool bRebuild = false);
-//++timo had to add a default value for bSnap (see Patch_ApplyMatrix call from Select_ApplyMatrix in select.cpp)
-void Patch_ApplyMatrix(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vMatrix[3], bool bSnap = false);
-void Patch_EditPatch();
-void Patch_Deselect();
-void Patch_Deselect(patchMesh_t *p);
-void Patch_Delete(patchMesh_t *p);
-int  Patch_MemorySize(patchMesh_t *p);
-void Patch_Select(patchMesh_t *p);
-void Patch_Scale(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vAmt, bool bRebuilt = true);
-void Patch_Cleanup();
-void Patch_SetView(int n);
-void Patch_SetTexture(patchMesh_t *p, texdef_t *tex_def, IPluginTexdef* pPlugTexdef = NULL);
-void Patch_BrushToMesh(bool bCone = false, bool bBevel = false, bool bEndcap = false, bool bSquare = false, int nHeight = 3);
-bool Patch_DragScale(patchMesh_t *p, vec3_t vAmt, vec3_t vMove);
-//void Patch_ReadBuffer(char* pBuff, bool bSelect = false);
-//void Patch_WriteFile (MemStream* pMemFile);
-void Patch_UpdateSelected(vec3_t vMove);
-//brush_t* Patch_Parse(bool bOld);
-//void Patch_Write (patchMesh_t *p, FILE *f);
-//void Patch_Write (patchMesh_t *p, MemStream *file);
-//void Patch_AdjustColumns(patchMesh_t *p, int nCols);
-//void Patch_AdjustRows(patchMesh_t *p, int nRows);
-void Patch_AdjustSelected(bool bInsert, bool bColumn, bool bFlag);
-patchMesh_t* Patch_Duplicate(patchMesh_t *pFrom);
-void Patch_RotateTexture(patchMesh_t *p, float fAngle);
-void Patch_ScaleTexture(patchMesh_t *p, float fx, float fy, bool bFixup = true);
-// shift of some pixel amount
-void Patch_ShiftTexture(patchMesh_t *p, float fx, float fy);
-// shift of ST increments
-void Patch_ShiftTextureST(patchMesh_t *p, float fx, float fy);
-void Patch_DrawCam(patchMesh_t *p);
-void Patch_DrawXY(patchMesh_t *p);
-void Patch_InsertColumn(patchMesh_t *p, bool bAdd);
-void Patch_InsertRow(patchMesh_t *p, bool bAdd);
-void Patch_RemoveRow(patchMesh_t *p, bool bFirst);
-void Patch_RemoveColumn(patchMesh_t *p, bool bFirst);
-void Patch_ToggleInverted();
-void Patch_Restore(patchMesh_t *p);
-void Patch_Save(patchMesh_t *p);
-void Patch_SetTextureInfo(texdef_t* pt);
-void Patch_NaturalTexturing();
-void Patch_ResetTexturing(float fx, float fy);
-void Patch_FitTexturing();
-void Patch_BendToggle();
-//void Patch_StartInsDel();
-void Patch_BendHandleTAB();
-void Patch_BendHandleENTER();
-void Patch_SelectBendNormal();
-void Patch_SelectBendAxis();
-bool OnlyPatchesSelected();
-bool AnyPatchesSelected();
-patchMesh_t* SinglePatchSelected();
-void Patch_CapCurrent();
-void Patch_DisperseRows();
-void Patch_DisperseIntermediateRows();
-void Patch_DisperseIntermediateColumns();
-void Patch_CycleCapSelected();
-void Patch_NaturalizeSelected(bool bCap = false);//, bool bCycleCap = false);
-void Patch_SelectAreaPoints(bool bMulti);
-void Patch_InvertTexture(bool bY);
-void patchInvert(patchMesh_t *p);
-//void Patch_InsDelToggle();
-//void Patch_InsDelHandleTAB();
-//void Patch_InsDelHandleENTER();
-void Patch_SetOverlays();
-void Patch_ClearOverlays();
-void Patch_Thicken(int nAmount, bool bSeam, qboolean bGroupResult);
-void Patch_Transpose();
-void Patch_Freeze();
-void Patch_UnFreeze(bool bAll);
-const char* Patch_GetTextureName();
-void Patch_FindReplaceTexture(brush_t *pb, const char *pFind, const char *pReplace, bool bForce);
-void Patch_SnapToGrid(patchMesh_t *p);
-extern bool g_bPatchShowBounds;
-extern bool g_bPatchWireFrame;
-extern bool g_bPatchWeld;
-extern bool g_bPatchDrillDown;
-//extern bool g_bPatchInsertMode;
-extern bool g_bPatchBendMode;
-extern vec3_t g_vBendOrigin;
-//void Patch_FromTriangle(vec5_t vx, vec5_t vy, vec5_t vz);
-const char* Patch_GetKeyValue(patchMesh_t *p, const char *pKey);
-void Patch_SetEpair(patchMesh_t *p, const char *pKey, const char *pValue);
-void Patch_LODMatchAll();
-void Patch_CalcBounds(patchMesh_t *p, vec3_t& vMin, vec3_t& vMax);
-
-
-
-
-// group stuff
-// group_t are loaded / saved through "group_info" entities
-// they hold epairs for group settings and additionnal access info (tree nodes)
-typedef struct group_s
-{
-  struct group_s *next;
-  epair_t *epairs;
-#if 0 //! Deprecated in gtk 2.x.
-  GtkCTreeNode *itemOwner;
-#endif
-} group_t;
-
-// NOTES: grouping only enabled in brush primitives mode
-// grouping works by naming brushes and setting display properties
-// the group hierarchy is not related with the map hierarchy (entity list, brushes etc.)
-// brushes with no group are under the "world" node (default for all brushes)
-// void Group_GetListFromWorld(CStringArray *pArray);
-void Group_RemoveListFromWorld();
-// void Group_SetListToWorld(CStringArray *pArray);
-// void Group_BuildTree(CTreeCtrl *pTree);
-// void Group_DecomposeTree(CTreeCtrl *pTree);
-// save group_t as "classname" "group_info" things
-void Group_Save(FILE *f);
-// clean the brushes ownerItem, clean the treeview and rebuild everything
-// is usually called when loading a new map, but may be called anytime
-void Group_Init();
-void Group_Add(entity_t *e);
-
-// remove a brush from it's current group, will erase the "group" epair if any, and delete the tree control node
-void Group_RemoveBrush(brush_t *b);
-void Group_AddToWorld(brush_t *b);
-// will remove brush of it's current group if any, and will add it wherever needed according to it's "group" key
-void Group_AddToProperGroup(brush_t *b);
-void Group_AddToSelected(brush_t *b);
-// allocate a new group, set name
-group_t* Group_Alloc(const char *name);
-// we use entities to store information about the groups
-// these entities are not linked into the world, and they have no brushes
-// only loaded / saved in map file
-group_t* Group_ForName(const char *name);
-
-// TTimo
-// new brush primitive stuff
-
-#ifdef _DEBUG
-//#define DBG_BP
-#endif
-
-// get the relative axes of the current texturing
-void BrushPrimit_GetRelativeAxes(face_t *f, vec3_t vecS, vec3_t vecT);
-// brush primitive stuff
-void ComputeAxisBase(vec3_t normal, vec3_t texS, vec3_t texT );
-void FaceToBrushPrimitFace(face_t *f);
-void BrushPrimitFaceToFace(face_t *f);
-void EmitBrushPrimitTextureCoordinates(face_t *, winding_t *);
-// EmitTextureCoordinates, is old code used for brush to brush primitive conversion
-void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f);
-//void BrushPrimit_Parse(brush_t *);
-// compute a fake shift scale rot representation from the texture matrix
-void TexMatToFakeTexCoords( vec_t texMat[2][3], float shift[2], float *rot, float scale[2] );
-void FakeTexCoordsToTexMat( float shift[2], float rot, float scale[2], vec_t texMat[2][3] );
-void ConvertTexMatWithQTexture( vec_t texMat1[2][3], qtexture_t *qtex1, vec_t texMat2[2][3], qtexture_t *qtex2 );
-// NOTE: this is a wrapper over the vec_t mat[2][3] version
-void ConvertTexMatWithQTexture( brushprimit_texdef_t *texMat1, qtexture_t *qtex1, brushprimit_texdef_t *texMat2, qtexture_t *qtex2 );
-// texture locking
-void ShiftTextureGeometric_BrushPrimit(face_t *f, vec3_t delta);
-void ShiftTextureRelative_BrushPrimit( face_t *f, float x, float y );
-void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, vec3_t vOrigin );
-// used in CCamWnd::ShiftTexture_BrushPrimit
-void ComputeBest2DVector( vec3_t v, vec3_t X, vec3_t Y, int &x, int &y );
-void Face_FitTexture_BrushPrimit( face_t *face, vec3_t minx, vec3_t maxs, int nHeight, int nWidth );
-// lock textures on a random transformation
-void ApplyMatrix_BrushPrimit(face_t *f, vec3_t matrix[3], vec3_t origin);
-// low level functions .. put in mathlib?
-#define BPMatCopy(a,b) {b[0][0] = a[0][0]; b[0][1] = a[0][1]; b[0][2] = a[0][2]; b[1][0] = a[1][0]; b[1][1] = a[1][1]; b[1][2] = a[1][2];}
-// apply a scale transformation to the BP matrix
-#define BPMatScale(m,sS,sT) {m[0][0]*=sS; m[1][0]*=sS; m[0][1]*=sT; m[1][1]*=sT;}
-// apply a translation transformation to a BP matrix
-#define BPMatTranslate(m,s,t) {m[0][2] += m[0][0]*s + m[0][1]*t; m[1][2] += m[1][0]*s+m[1][1]*t;}
-// 2D homogeneous matrix product C = A*B
-void BPMatMul(vec_t A[2][3], vec_t B[2][3], vec_t C[2][3]);
-// apply a rotation (degrees)
-void BPMatRotate(vec_t A[2][3], float theta);
-#ifdef _DEBUG
-void BPMatDump(vec_t A[2][3]);
-#endif
-// GL matrix product
-void GLMatMul(vec_t M[4][4], vec_t A[4], vec_t B[4]);
-qboolean IsBrushPrimitMode();
-//
-// eclass.cpp
-//
-#include "ieclass.h"  
-
-/*!
-  \todo those are at the eclass manager level, but some documentation about what they do will be helpful
-*/
-extern qboolean parsing_single;
-extern qboolean eclass_found;
-extern eclass_t *eclass_e;
-extern eclass_t *g_md3Cache;
-
-/*!
-eclass manager API
-*/
-void Eclass_InsertAlphabetized(eclass_t *e);
-eclass_t** Get_EClass_E();
-void Set_Eclass_Found(qboolean);
-qboolean Get_Parsing_Single();
-
-// .def loading, builtin module  
-#include "eclass_def.h"
-extern CSynapseBuiltinClientDef eclass_def;
-
-/*!
-global table to .def entity class description
-this is a builtin module, even if we rely on fgd, we still use this one in cases such as entities not found etc.
-*/
-extern _EClassTable g_EClassDefTable;
-
-/*!
-support for one additional/optional entity format
-*/
-extern bool g_bHaveEClassExt;
-extern _EClassTable g_EClassExtTable;
-
-  
-#include "iplugin.h"
-// for interfaces, we require main plugin header included
-#include "qerplugin.h"
-
-//
-// SurfaceDlg.cpp and surface properties plugin
-//
-//++timo some patch in/out stuff is in there, needs to be moved out in a dedicated interface
-#include "isurfaceplugin.h"
-#include "surfaceplugin.h"
-void WINAPI Patch_Rebuild(patchMesh_t *p);
-#include "isurfaceplugin.h"
-extern _QERPlugSurfaceTable g_SurfaceTable;
-void SurfaceDlgFitAll();
-
-//
-// OpenGL interface
-//
-#include "igl.h"
-
-GtkWidget* WINAPI QERApp_GetQeglobalsGLWidget();
-void WINAPI QERApp_HookGL2DWindow(IGL2DWindow* pGLW);
-void WINAPI QERApp_UnHookGL2DWindow(IGL2DWindow* pGLW);
-void WINAPI QERApp_HookGL3DWindow(IGL3DWindow* pGLW);
-void WINAPI QERApp_UnHookGL3DWindow(IGL3DWindow* pGLW);
-void Draw2DPluginEntities( VIEWTYPE vt );
-void Draw3DPluginEntities();
-
-//
-// IShaders interface
-//
-#define USE_SHADERSTABLE_DEFINE
-#include "ishaders.h"
-extern _QERShadersTable g_ShadersTable;
-
-//
-// ISelectedFace interface
-//
-#include "iselectedface.h"
-int WINAPI QERApp_GetSelectedFaceCount();
-// NOTE: it's the brush corresponding to the selected face below!
-brush_t* WINAPI QERApp_GetSelectedFaceBrush(int iface);
-face_t* WINAPI QERApp_GetSelectedFace(int iface);
-int WINAPI QERApp_GetFaceInfo(int iface, _QERFaceData *pFaceData, winding_t *pWinding);
-int WINAPI QERApp_SetFaceInfo(int iface, _QERFaceData *pFaceData);
-int WINAPI QERApp_ISelectedFace_GetTextureNumber(int iface);
-void WINAPI QERApp_GetTextureSize(int iface, int Size[2]);
-
-//
-// IEpairs interface
-//
-//#include "iepairs.h"
-//#include "epairswrapper.h"
-
-//
-// IImage interface
-//
-#include "iimage.h"
-
-//
-// IFileSystem interface
-//
-#define USE_VFSTABLE_DEFINE
-#include "ifilesystem.h"
-
-extern _QERFileSystemTable g_FileSystemTable;
-
-//
-// TexWnd.cpp
-//
-extern qboolean g_bShowAllShaders;
-
-//
-// texwindow.cpp
-//
-//++timo TODO: we can probably raise the MAX_TEXTUREDIRS limit?
-#define		MAX_TEXTUREDIRS	256
-
-extern CPtrArray g_lstSkinCache;
-qtexture_t *QERApp_LoadTextureRGBA(unsigned char* pPixels, int nWidth, int nHeight);
-
-//
-// IScripLib interface
-// GetToken, UnGetToken, etc.
-#include "iscriplib.h"
-extern FILE *g_File;
-void WINAPI QERApp_MapPrintf_FILE( char *text, ... );
-
-//
-// ISurfacePlugin interface
-//
-void QERApp_GetTwoSelectedPatch( patchMesh_t **p1, patchMesh_t **p2 );
-
-//
-// IBSPFrontend interface
-//
-#include "ibspfrontend.h"
-extern _QERPlugBSPFrontendTable g_BSPFrontendTable;
-extern GSList *g_BSPFrontendCommands;
-
-//
-// IToolbar
-//
-#include "itoolbar.h"
-
-//
-// IMessaging interface
-#include "iui.h"
-#include "iui_gtk.h"
-#include "ui.h"
-IWindow* WINAPI QERApp_CreateGLWindow();
-void WINAPI QERApp_HookWindow(IWindowListener* pListen);
-void WINAPI QERApp_UnHookWindow(IWindowListener* pListen);
-IXYWndWrapper* WINAPI QERApp_GetXYWndWrapper();
-void WINAPI QERApp_HookListener(IListener* pListen, int Msg);
-int  WINAPI QERApp_UnHookListener(IListener* pListen);
-void DispatchRadiantMsg( int Msg );
-// dispatch for IWindowListener entities
-void DispatchOnMouseMove(guint32 nFlags, int x, int y);
-bool DispatchOnLButtonDown(guint32 nFlags, int x, int y);
-bool DispatchOnLButtonUp(guint32 nFlags, int x, int y);
-
-//
-// IData interface
-//
-#include "idata.h"
-
-//
-// ICamera interface
-//
-#include "icamera.h"
-
-// Some declarations that were in stdafx.h
-
-// main.cpp
-extern gint try_destroy_splash(gpointer);
-
-#include "mainframe.h"
-#include "preferences.h"
-#include "findtexturedialog.h"
-#include "surfacedialog.h"
-#include "patchdialog.h"
-
-class MainFrame;
-class ClipPoint;
-
-extern MainFrame* g_pParentWnd;
-extern CString g_strAppPath;
-extern CString g_strDTDPath;
-extern CString g_pidFile;
-extern CString g_pidGameFile;
-extern CString g_strBitmapsPath;
-extern CString g_strPluginsDir;
-extern CString g_strModulesDir;
-
-extern CGameDescription *g_pGameDescription;
-extern CString g_strGameToolsPath;
-
-extern CString g_strTempPath;
-extern PrefsDlg& g_PrefsDlg;
-extern FindTextureDialog& g_dlgFind;
-extern SurfaceDlg g_dlgSurface;
-extern PatchDialog g_PatchDialog;
-
-extern int g_bIgnoreCommands;
-
-void HideInfoDialog();
-void ShowInfoDialog(const char* pText);
-
-// externs
-//extern void HandleCommand (GtkWidget *widget, gpointer data, bool keydown);
-extern gint HandleCommand (GtkWidget *widget, gpointer data);
-extern void AddSlash(CString&);
-extern void DLLBuildDone();
-extern void CleanUpEntities();
-extern void FindReplace(CString& strContents, const char* pTag, const char* pValue);
-extern void CheckBspProcess();
-extern void QE_CountBrushesAndUpdateStatusBar();
-extern void	QE_CheckAutoSave();
-extern qtexture_t	*current_texture;
-extern void SaveWithRegion(char *name); // save the current map, sets the map name in the name buffer (deals with regioning)
-extern void RunBsp (char *command);
-extern void Map_Snapshot();
-//extern void WXY_Print();
-extern void AddProp( void );
-extern qboolean DoColor(int iIndex);
-extern entity_t	*edit_entity;
-extern int inspector_mode;
-extern bool g_bRotateMode;
-extern bool g_bClipMode;
-extern bool g_bScaleMode;
-extern int g_nScaleHow;
-extern bool g_bPathMode;
-extern void RunScript(char* pBuffer);
-extern bool ExtractPath_and_Filename(const char* pPath, CString& strPath, CString& strFilename);
-extern void Select_Scale(float x, float y, float z);
-extern void Select_RotateTexture(int amt);
-extern void Select_ScaleTexture(float x, float y);
-extern void Select_ShiftTexture(int x, int y);
-extern void FindReplaceTextures(const char* pFind, const char* pReplace, bool bSelected, bool bForce, bool bSelectMatchingFaces);
-/*!
-\fn DoProjectSettings shows the dialog for per-game configurable settings by the user
-typically this sets up things like mod editing configuration
-those a per-project, not the same thing as preferences which are global to the game conf
-this is still being worked on, as we have several issues with how things are configured
-we also have a number of behaviours defined in the .game, which can't be edited graphically
-we dump those properties to the console when the project settings dialog shows up
-*/
-extern void DoProjectSettings();
-extern qboolean region_active;
-extern void Brush_Print(brush_t* b);
-extern void Texture_ShowStartupShaders();
-extern void Map_ImportFile (char *filename);
-extern void Map_SaveSelected(char* pFilename);
-extern void UpdateSurfaceDialog();
-extern void Select_GetTrueMid (vec3_t mid);
-extern bool g_bSwitch;
-extern brush_t g_brFrontSplits;
-extern brush_t g_brBackSplits;
-extern ClipPoint g_Clip1;
-extern ClipPoint g_Clip2;
-extern brush_t* g_pSplitList;
-extern ClipPoint g_PathPoints[256];
-extern void AcquirePath(int nCount, PFNPathCallback* pFunc);
-extern bool g_bScreenUpdates;
-extern SCommandInfo g_Commands[];
-extern int g_nCommandCount;
-extern SKeyInfo g_Keys[];
-extern int g_nKeyCount;
-extern int inspector_mode;
-extern char	*bsp_commands[256];
-extern void RunScriptByName(char*, bool);
-extern void DoNewColor(int* i1, int* i2, int* i3);
-extern void UpdateSurfaceDialog();
-extern void CSG_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back);
-//extern void HandlePopup(CWnd* pWindow, unsigned int uId);
-extern z_t z;
-extern void Select_Scale(float x, float y, float z);
-extern void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv);
-//extern void VectorRotate (vec3_t va, vec3_t vb, vec3_t out);
-//extern void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out);
-extern qboolean QE_SaveProject (const char* pProjectFile);
-//extern void NewBSP(char* pCommandLine, HWND);
-//extern void NewVIS(char* pCommandLine, HWND);
-//extern void NewRAD(char* pCommandLine, HWND);
-extern void RunTools(char* pCommandLine, GtkWidget* hwnd, const char* pPAKFile);
-extern void Clamp(float& f, int nClamp);
-extern void MemFile_fprintf(MemStream* pMemFile, const char* pText, ...);
-//extern void SaveWindowPlacement(HWND hwnd, const char* pName);
-//extern bool LoadWindowPlacement(HWND hwnd, const char* pName);
-extern qboolean ConfirmModified (void);
-extern void DoPatchInspector();
-extern void TogglePatchInspector();
-void UpdatePatchInspector();
-extern int BuildShortPathName(const char* pPath, char* pBuffer, int nBufferLen);
-extern int g_nBrushId;
-
-// defined in gtkdlgs.cpp, we might want to move declaration and implementatin with other Select_ stuff..
-// NOTE: there's also a Select_Brush(brush_t *b) function.. unrelated
-extern void SelectBrush (int entitynum, int brushnum);
-
-// bp_dlg.cpp
-// ret: 0 = abort, 1 = load and convert, 2 = changed project settings, load and don't convert
-// the user might decide to switch the BP mode in project settings
-// status: 0 = loading regular, got conflict 1 = loading BP, got conflict
-extern int BP_MessageBox (int status);
-
-// main.cpp
-extern gint try_destroy_splash(gpointer);
-
-// SPoG
-// targetname.cpp
-void Entity_Connect(entity_t *e1, entity_t *e2);
-int GetUniqueTargetId(int iHint);
-
-// xywindow.cpp
-void CreateEntityFromName(const char* name, const vec3_t origin);
-
-// eclass.cpp
-/*!
-\brief initialization of the eclass manager
-general guidelines about eclass.cpp implementation:
-- we don't support unlimited number of eclass file formats together
-  currently limited to two
-  support for .def is builtin to the core, but you may choose not to activate it
-- search and load of the files:
-  the manager is in charge of scanning for eclass definition files to load
-  there is a general configuration setting for games which use a different set of
-    entities between single player mode and multiplayer mode (TODO: the code doing
-    this needs to be abstracted some more)
-- duplicate files / multiple files:
-  if two files with the same name exist (for instance in the basegame, and in fs_game)
-  then only the first one found in the scan order is loaded
-  if several files are found, they are all loaded
-  this allows mods to either replace or extend the list of eclass
-- if eclass_singleload prop is used in the .game, then there is no multiple files check
-  the first file found is loaded, and there is no further search for the given extension
-  (this was an addition for HL support)
-*/
-void Eclass_Init ();
-eclass_t *Eclass_ForName (const char *name, qboolean has_brushes);
-eclass_t * EClass_Create( const char *name, float col1, float col2, float col3, const vec3_t *mins, const vec3_t *maxs, const char *comments );
-
-#endif // _QE3_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _QE3_H_
+#define _QE3_H_
+
+#ifdef _WIN32
+
+// disable data conversion warnings for gl
+#pragma warning(disable : 4244)     // MIPS
+#pragma warning(disable : 4136)     // X86
+#pragma warning(disable : 4051)     // ALPHA
+#pragma warning(disable : 4800)
+#endif
+
+// for interfaces, we require main plugin header included
+#include "iplugin.h"
+#include "qerplugin.h"
+#include "qertypes.h"
+
+#include "missing.h" // temporary stuff, needs to be removed
+#include "idatastream.h"
+#include "file.h"
+
+#include "qgl.h"
+
+#include <gtk/gtk.h>
+#include <math.h>
+#include <stdlib.h>
+
+#include <stdio.h>
+
+// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=672
+// this is the version to expect from template projects
+#define PROJECT_VERSION 2
+
+//#define MEM_DEBUG
+#ifdef MEM_DEBUG
+
+#define malloc(a) debug_malloc(a, __FILE__, __LINE__)
+#define free(a) debug_free(a, __FILE__, __LINE__)
+
+void* debug_malloc (size_t size, const char* file, int line);
+void debug_free (void *buf, const char* file, int line);
+
+#endif
+
+#ifdef _DEBUG
+//#define DBG_WINDOWPOS
+#endif
+
+#ifdef DBG_WINDOWPOS
+void CheckWatchit(char *msg);
+#endif
+
+// those two files are generated
+// if they are missing, you NEED to run makeversion.sh
+// NOTE: for win32 users, cygwin installation is REQUIRED to run makeversion.sh
+// NOTE TTimo if any of those changes (they might change a lot), then the whole app is rebuilt.
+//   very often it's not necessary
+#include "version.h"
+#include "aboutmsg.h"
+
+// synapse is our utility lib for dynamic shared objects management
+#include "synapse.h"
+
+#include "qertypes.h"
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "parse.h"
+
+#include "qedefs.h"
+#include "qfiles.h"
+#include "textures.h"
+#include "brush.h"
+//#include "entity.h"
+#define USE_ENTITYTABLE_DEFINE
+#include "ientity.h"
+extern _QEREntityTable __ENTITYTABLENAME;
+// wrappers for brush access
+#include "ibrush.h"
+// wrappers for patch access
+#include "ipatch.h"
+
+#include "imodel.h"
+
+#include "imap.h"
+
+#include "iundo.h"
+
+extern _QERPlugMapTable g_MapTable;
+
+//++timo for BP conversion escaping FIXME: remove when mixing two formats!
+extern bool g_bCancel_Map_LoadFile;
+// used to be #defines, multiple engine support suggests we should go towards dynamic
+extern int g_MaxWorldCoord;
+extern int g_MinWorldCoord;
+extern int g_MaxBrushSize;
+/*
+// set to true when we are parsing a terrain entity
+extern bool g_bParseTerrain;
+extern IShader *g_pTerrainShader, *g_pCaulk;
+*/
+#include "map.h"
+
+#include "select.h"
+
+#include "camera.h"
+#include "z.h"
+
+#include "undo.h"
+#include "glwidget.h"
+
+// the dec offsetof macro doesn't work very well...
+#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+// our own implementation of Q_int, clamping can be disabled on prefs
+vec_t Rad_rint (vec_t in);
+
+double I_FloatTime (void);
+
+void   Error (char *error, ...);
+int    CheckParm (char *check);
+void   ParseCommandLine (char *lpCmdLine);
+
+int    ParseNum (char *str);
+
+char*  COM_Parse (char *data);
+char*  Get_COM_Token();
+
+extern	char		com_token[1024];
+extern	qboolean	com_eof;
+
+#define	MAX_NUM_ARGVS	32
+extern	int		argc;
+extern	char	        *argv[MAX_NUM_ARGVS];
+
+//
+// system functions
+//
+// TTimo NOTE: WINAPI funcs can be accessed by plugins
+void    Sys_UpdateStatusBar( void );
+void    WINAPI Sys_UpdateWindows (int bits);
+void    Sys_Beep (void);
+void    Sys_ClearPrintf (void);
+double	Sys_DoubleTime (void);
+void    Sys_GetCursorPos (int *x, int *y);
+void    Sys_SetCursorPos (int x, int y);
+void    Sys_SetTitle (const char *text);
+void    WINAPI Sys_BeginWait (void);
+void    WINAPI Sys_EndWait (void);
+void    Sys_Status(const char *psz, int part);
+bool    Sys_AltDown ();
+bool    Sys_ShiftDown ();
+// will open/close/check the log file based on the following globals:
+// g_PrefsDlg.m_bLogConsole g_qeglobals.hLogFile
+void    Sys_LogFile (void);
+
+extern  qboolean verbose;
+#include "qsysprintf.h"
+
+// NOTE TTimo I split out the GUI-depependant stuff from QEGlobals_t into a seperate struct
+typedef struct
+{
+  // GL widget of the camera view
+  // all textures are binded in this context and shared with the others
+  GtkWidget *d_glBase;
+
+  GtkWidget *d_main_window; // d_hwndMain
+  GtkWidget *d_edit;        // d_hwndEdit
+  GtkWidget *d_entity;      // d_hwndEntity
+  GtkWidget *d_camera;      // d_hwndCamera;
+  GtkWidget *d_texture;     // d_hwndTexture;
+  GtkWidget *d_texture_scroll;
+  GtkWidget *d_z;           // d_hwndZ;
+
+} QEGlobals_GUI_t;
+
+// usefull portability stuff
+//++timo move them somewhere
+bool DoesFileExist(const char* pBuff, long& lSize);
+
+char *copystring (char *s);
+char *ExpandReletivePath (char *p);
+
+#include "xmlstuff.h"
+#include "points.h"
+
+//
+// drag.c
+//
+void Drag_Begin (int x, int y, int buttons, vec3_t xaxis, vec3_t yaxis, vec3_t origin, vec3_t dir, bool sf_camera = false);
+void Drag_MouseMoved (int x, int y, int buttons);
+void Drag_MouseUp (int nButtons = 0);
+
+//
+// csg.c
+//
+void CSG_MakeHollow (void);
+void CSG_Subtract (void);
+void CSG_Merge (void);
+
+//
+// vertsel.c
+//
+
+void SetupVertexSelection (void);
+void SelectEdgeByRay (vec3_t org, vec3_t dir);
+void SelectVertexByRay (vec3_t org, vec3_t dir);
+
+void ConnectEntities (void);
+
+extern	int	update_bits;
+
+extern	int	screen_width;
+extern	int	screen_height;
+
+char *TranslateString (char *buf);
+
+//
+// linux_qe3.cc
+//
+//void OpenDialog ();
+//void SaveAsDialog (bool bRegion);
+void ProjectDialog (void);
+void MRU_Load ();
+void MRU_Save ();
+void MRU_AddWidget (GtkWidget *widget, int pos);
+void MRU_AddFile (const char *str);
+void MRU_Activate (int index);
+
+
+void FillTextureMenu (GSList** pArray = NULL);
+void FillBSPMenu (void);
+
+// profile functions - kind of utility lib
+// they are kind of dumb, they expect to get the path to the .ini file or to the prefs directory when called
+// load_buffer and save_buffer expect the path only, theyll build a $(pszName).bin file
+bool WINAPI profile_save_int (const char *filename, const char *section, const char *key, int value);
+bool WINAPI profile_save_float (const char *filename, const char *section, const char *key, float value);
+bool WINAPI profile_save_string (const char *filename, const char *section, const char *key, const char *value);
+bool profile_save_buffer (const char *rc_path, const char *pszName, void *pvBuf, guint32 lSize);
+bool profile_load_buffer (const char *rc_path, const char *pszName, void *pvBuf, guint32 *plSize);
+int WINAPI profile_load_int (const char *filename, const char *section, const char *key, int default_value);
+float WINAPI profile_load_float (const char *filename, const char *section, const char *key, float default_value);
+char* WINAPI profile_load_string (const char *filename, const char *section, const char *key, const char *default_value);
+// used in the command map code
+bool read_var (const char *filename, const char *section, const char *key, char *value);
+
+//
+// entityw.c
+//
+void FillClassList (void);
+bool UpdateEntitySel(eclass_t *pec);	
+void SetInspectorMode(int iType);
+void SetSpawnFlags(void);
+void GetSpawnFlags(void);
+void SetKeyValuePairs(bool bClearMD3 = false);
+extern void BuildGammaTable(float g);
+bool GetSelectAllCriteria(CString &strKey, CString &strVal);
+
+// linux_dlg.c
+
+typedef enum {
+  BEVEL = 0,
+  ENDCAP,
+  IBEVEL,
+  IENDCAP
+} CapDialog;
+
+int DoCapDlg (int *type, bool *b_GroupResul);
+int DoBSInputDlg (const char *fields[5], float values[5]);
+int DoTextureLayout (float *fx, float *fy);
+char* DoNameDlg (const char* title);
+char* DoNewProjectDlg ();
+/*
+text editor, open filename at given line
+opening at line works only for win32 / editpad and builtin Gtk editor
+
+we only allow one instance of the Gtk editor widget opened at a given time
+if we get called with an existing instance, switch to new file ..
+*/
+void DoTextEditor (const char* filename, int cursorpos);
+int DoLightIntensityDlg (int *intensity);
+
+void DoMapInfo ();
+void DoEntityList ();
+void DoGamma();
+void DoFind();
+void DoRotateDlg ();
+void DoSides(bool bCone = false, bool bSphere = false, bool bTorus = false);
+void DoAbout();
+void DoSnapTToGrid(float hscale = 0.0f, float vscale = 0.0f);
+void DoSurface();
+void ToggleSurface(); // will show/hide depending on the current state
+void DoNewPatchDlg ();
+void DoThickenDlg ();
+void DoCommandListDlg ();
+void DoScaleDlg ();;
+void DoTextureListDlg ();
+void DoScriptsDlg ();
+
+// QE function declarations
+void     QE_CheckAutoSave( void );
+void     WINAPI QE_ConvertDOSToUnixName( char *dst, const char *src );
+void     QE_CountBrushesAndUpdateStatusBar( void );
+void     WINAPI QE_CheckOpenGLForErrors(void);
+void     QE_ExpandBspString (char *bspaction, GPtrArray & out, char *mapname);
+// initialise the VFS from current project settings
+void     QE_InitVFS();
+// do all initialisations that should happen after a project is load (during startup or project change)
+void     QE_Init (void);
+qboolean QE_KeyDown (int key, int nFlags = 0);
+// does some sanity checks on the project entity, such as removing ending filename seperators from paths
+// (this usually gets propagated to the actual project file since most of the time we save right after calling the check)
+void     QE_CheckProjectEntity();
+// this will load a new project entity in memory, and potentially process it from a template
+// NOTE TTimo calling QE_LoadProject won't take care of the various initialisation that are performed depending on the project settings
+//   you should then call QE_Init for that
+#define PROJECT_TEMPLATE_NAME "default_project.proj"
+#define PROJECT_USER_NAME "user_project.proj"
+#define PROJECT_FILETYPE "proj"
+qboolean QE_LoadProject (const char *projectfile);
+qboolean QE_SingleBrush (bool bQuiet = false);
+
+
+// sys stuff
+void Sys_MarkMapModified (void);
+
+#if 0 // no longer used
+
+// QE Win32 function declarations
+#ifdef _WIN32
+int  WINAPI QEW_SetupPixelFormat(HDC hDC, qboolean zbuffer );
+void QEW_StopGL( HWND hWnd, HGLRC hGLRC, HDC hDC );
+#endif
+
+#endif
+
+// extern declarations
+extern QEGlobals_t   g_qeglobals;
+extern QEGlobals_GUI_t g_qeglobals_gui;
+
+qboolean IsBrushSelected(brush_t* bSel);
+
+// curve brushes
+
+void Curve_MakeCurvedBrush (qboolean negative, qboolean top, qboolean bottom, 
+					qboolean s1, qboolean s2, qboolean s3, qboolean s4);
+
+void Curve_Invert (void);
+
+void Curve_AddFakePlanes( brush_t *B );
+void Curve_StripFakePlanes( brush_t *B );
+void Curve_BuildPoints (brush_t *b);
+void Curve_XYDraw (brush_t *b);
+void Curve_CameraDraw (brush_t *b);
+
+void Curve_WriteFile (char *name);
+
+
+// patch stuff
+patchMesh_t *Patch_Alloc();
+patchMesh_t* MakeNewPatch();
+brush_t* AddBrushForPatch(patchMesh_t *pm, bool bLinkToWorld = true);
+brush_t* Patch_GenericMesh(int nWidth, int nHeight, int nOrientation = 2, bool bDeleteSource = true, bool bOverride = false);
+//void Patch_ReadFile (char *name);
+//void Patch_WriteFile (char *name); 
+void Patch_BuildPoints (brush_t *b);
+void Patch_Move(patchMesh_t *p, const vec3_t vMove, bool bRebuild = false);
+//++timo had to add a default value for bSnap (see Patch_ApplyMatrix call from Select_ApplyMatrix in select.cpp)
+void Patch_ApplyMatrix(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vMatrix[3], bool bSnap = false);
+void Patch_EditPatch();
+void Patch_Deselect();
+void Patch_Deselect(patchMesh_t *p);
+void Patch_Delete(patchMesh_t *p);
+int  Patch_MemorySize(patchMesh_t *p);
+void Patch_Select(patchMesh_t *p);
+void Patch_Scale(patchMesh_t *p, const vec3_t vOrigin, const vec3_t vAmt, bool bRebuilt = true);
+void Patch_Cleanup();
+void Patch_SetView(int n);
+void Patch_SetTexture(patchMesh_t *p, texdef_t *tex_def, IPluginTexdef* pPlugTexdef = NULL);
+void Patch_BrushToMesh(bool bCone = false, bool bBevel = false, bool bEndcap = false, bool bSquare = false, int nHeight = 3);
+bool Patch_DragScale(patchMesh_t *p, vec3_t vAmt, vec3_t vMove);
+//void Patch_ReadBuffer(char* pBuff, bool bSelect = false);
+//void Patch_WriteFile (MemStream* pMemFile);
+void Patch_UpdateSelected(vec3_t vMove);
+//brush_t* Patch_Parse(bool bOld);
+//void Patch_Write (patchMesh_t *p, FILE *f);
+//void Patch_Write (patchMesh_t *p, MemStream *file);
+//void Patch_AdjustColumns(patchMesh_t *p, int nCols);
+//void Patch_AdjustRows(patchMesh_t *p, int nRows);
+void Patch_AdjustSelected(bool bInsert, bool bColumn, bool bFlag);
+patchMesh_t* Patch_Duplicate(patchMesh_t *pFrom);
+void Patch_RotateTexture(patchMesh_t *p, float fAngle);
+void Patch_ScaleTexture(patchMesh_t *p, float fx, float fy, bool bFixup = true);
+// shift of some pixel amount
+void Patch_ShiftTexture(patchMesh_t *p, float fx, float fy);
+// shift of ST increments
+void Patch_ShiftTextureST(patchMesh_t *p, float fx, float fy);
+void Patch_DrawCam(patchMesh_t *p);
+void Patch_DrawXY(patchMesh_t *p);
+void Patch_InsertColumn(patchMesh_t *p, bool bAdd);
+void Patch_InsertRow(patchMesh_t *p, bool bAdd);
+void Patch_RemoveRow(patchMesh_t *p, bool bFirst);
+void Patch_RemoveColumn(patchMesh_t *p, bool bFirst);
+void Patch_ToggleInverted();
+void Patch_Restore(patchMesh_t *p);
+void Patch_Save(patchMesh_t *p);
+void Patch_SetTextureInfo(texdef_t* pt);
+void Patch_NaturalTexturing();
+void Patch_ResetTexturing(float fx, float fy);
+void Patch_FitTexturing();
+void Patch_BendToggle();
+//void Patch_StartInsDel();
+void Patch_BendHandleTAB();
+void Patch_BendHandleENTER();
+void Patch_SelectBendNormal();
+void Patch_SelectBendAxis();
+bool OnlyPatchesSelected();
+bool AnyPatchesSelected();
+patchMesh_t* SinglePatchSelected();
+void Patch_CapCurrent();
+void Patch_DisperseRows();
+void Patch_DisperseIntermediateRows();
+void Patch_DisperseIntermediateColumns();
+void Patch_CycleCapSelected();
+void Patch_NaturalizeSelected(bool bCap = false);//, bool bCycleCap = false);
+void Patch_SelectAreaPoints(bool bMulti);
+void Patch_InvertTexture(bool bY);
+void patchInvert(patchMesh_t *p);
+//void Patch_InsDelToggle();
+//void Patch_InsDelHandleTAB();
+//void Patch_InsDelHandleENTER();
+void Patch_SetOverlays();
+void Patch_ClearOverlays();
+void Patch_Thicken(int nAmount, bool bSeam, qboolean bGroupResult);
+void Patch_Transpose();
+void Patch_Freeze();
+void Patch_UnFreeze(bool bAll);
+const char* Patch_GetTextureName();
+void Patch_FindReplaceTexture(brush_t *pb, const char *pFind, const char *pReplace, bool bForce);
+void Patch_SnapToGrid(patchMesh_t *p);
+extern bool g_bPatchShowBounds;
+extern bool g_bPatchWireFrame;
+extern bool g_bPatchWeld;
+extern bool g_bPatchDrillDown;
+//extern bool g_bPatchInsertMode;
+extern bool g_bPatchBendMode;
+extern vec3_t g_vBendOrigin;
+//void Patch_FromTriangle(vec5_t vx, vec5_t vy, vec5_t vz);
+const char* Patch_GetKeyValue(patchMesh_t *p, const char *pKey);
+void Patch_SetEpair(patchMesh_t *p, const char *pKey, const char *pValue);
+void Patch_LODMatchAll();
+void Patch_CalcBounds(patchMesh_t *p, vec3_t& vMin, vec3_t& vMax);
+
+
+
+
+// group stuff
+// group_t are loaded / saved through "group_info" entities
+// they hold epairs for group settings and additionnal access info (tree nodes)
+typedef struct group_s
+{
+  struct group_s *next;
+  epair_t *epairs;
+#if 0 //! Deprecated in gtk 2.x.
+  GtkCTreeNode *itemOwner;
+#endif
+} group_t;
+
+// NOTES: grouping only enabled in brush primitives mode
+// grouping works by naming brushes and setting display properties
+// the group hierarchy is not related with the map hierarchy (entity list, brushes etc.)
+// brushes with no group are under the "world" node (default for all brushes)
+// void Group_GetListFromWorld(CStringArray *pArray);
+void Group_RemoveListFromWorld();
+// void Group_SetListToWorld(CStringArray *pArray);
+// void Group_BuildTree(CTreeCtrl *pTree);
+// void Group_DecomposeTree(CTreeCtrl *pTree);
+// save group_t as "classname" "group_info" things
+void Group_Save(FILE *f);
+// clean the brushes ownerItem, clean the treeview and rebuild everything
+// is usually called when loading a new map, but may be called anytime
+void Group_Init();
+void Group_Add(entity_t *e);
+
+// remove a brush from it's current group, will erase the "group" epair if any, and delete the tree control node
+void Group_RemoveBrush(brush_t *b);
+void Group_AddToWorld(brush_t *b);
+// will remove brush of it's current group if any, and will add it wherever needed according to it's "group" key
+void Group_AddToProperGroup(brush_t *b);
+void Group_AddToSelected(brush_t *b);
+// allocate a new group, set name
+group_t* Group_Alloc(const char *name);
+// we use entities to store information about the groups
+// these entities are not linked into the world, and they have no brushes
+// only loaded / saved in map file
+group_t* Group_ForName(const char *name);
+
+// TTimo
+// new brush primitive stuff
+
+#ifdef _DEBUG
+//#define DBG_BP
+#endif
+
+// get the relative axes of the current texturing
+void BrushPrimit_GetRelativeAxes(face_t *f, vec3_t vecS, vec3_t vecT);
+// brush primitive stuff
+void ComputeAxisBase(vec3_t normal, vec3_t texS, vec3_t texT );
+void FaceToBrushPrimitFace(face_t *f);
+void BrushPrimitFaceToFace(face_t *f);
+void EmitBrushPrimitTextureCoordinates(face_t *, winding_t *);
+// EmitTextureCoordinates, is old code used for brush to brush primitive conversion
+void EmitTextureCoordinates ( float *xyzst, qtexture_t *q, face_t *f);
+//void BrushPrimit_Parse(brush_t *);
+// compute a fake shift scale rot representation from the texture matrix
+void TexMatToFakeTexCoords( vec_t texMat[2][3], float shift[2], float *rot, float scale[2] );
+void FakeTexCoordsToTexMat( float shift[2], float rot, float scale[2], vec_t texMat[2][3] );
+void ConvertTexMatWithQTexture( vec_t texMat1[2][3], qtexture_t *qtex1, vec_t texMat2[2][3], qtexture_t *qtex2 );
+// NOTE: this is a wrapper over the vec_t mat[2][3] version
+void ConvertTexMatWithQTexture( brushprimit_texdef_t *texMat1, qtexture_t *qtex1, brushprimit_texdef_t *texMat2, qtexture_t *qtex2 );
+// texture locking
+void ShiftTextureGeometric_BrushPrimit(face_t *f, vec3_t delta);
+void ShiftTextureRelative_BrushPrimit( face_t *f, float x, float y );
+void RotateFaceTexture_BrushPrimit(face_t *f, int nAxis, float fDeg, vec3_t vOrigin );
+// used in CCamWnd::ShiftTexture_BrushPrimit
+void ComputeBest2DVector( vec3_t v, vec3_t X, vec3_t Y, int &x, int &y );
+void Face_FitTexture_BrushPrimit( face_t *face, vec3_t minx, vec3_t maxs, int nHeight, int nWidth );
+// lock textures on a random transformation
+void ApplyMatrix_BrushPrimit(face_t *f, vec3_t matrix[3], vec3_t origin);
+// low level functions .. put in mathlib?
+#define BPMatCopy(a,b) {b[0][0] = a[0][0]; b[0][1] = a[0][1]; b[0][2] = a[0][2]; b[1][0] = a[1][0]; b[1][1] = a[1][1]; b[1][2] = a[1][2];}
+// apply a scale transformation to the BP matrix
+#define BPMatScale(m,sS,sT) {m[0][0]*=sS; m[1][0]*=sS; m[0][1]*=sT; m[1][1]*=sT;}
+// apply a translation transformation to a BP matrix
+#define BPMatTranslate(m,s,t) {m[0][2] += m[0][0]*s + m[0][1]*t; m[1][2] += m[1][0]*s+m[1][1]*t;}
+// 2D homogeneous matrix product C = A*B
+void BPMatMul(vec_t A[2][3], vec_t B[2][3], vec_t C[2][3]);
+// apply a rotation (degrees)
+void BPMatRotate(vec_t A[2][3], float theta);
+#ifdef _DEBUG
+void BPMatDump(vec_t A[2][3]);
+#endif
+// GL matrix product
+void GLMatMul(vec_t M[4][4], vec_t A[4], vec_t B[4]);
+qboolean IsBrushPrimitMode();
+//
+// eclass.cpp
+//
+#include "ieclass.h"  
+
+/*!
+  \todo those are at the eclass manager level, but some documentation about what they do will be helpful
+*/
+extern qboolean parsing_single;
+extern qboolean eclass_found;
+extern eclass_t *eclass_e;
+extern eclass_t *g_md3Cache;
+
+/*!
+eclass manager API
+*/
+void Eclass_InsertAlphabetized(eclass_t *e);
+eclass_t** Get_EClass_E();
+void Set_Eclass_Found(qboolean);
+qboolean Get_Parsing_Single();
+
+// .def loading, builtin module  
+#include "eclass_def.h"
+extern CSynapseBuiltinClientDef eclass_def;
+
+/*!
+global table to .def entity class description
+this is a builtin module, even if we rely on fgd, we still use this one in cases such as entities not found etc.
+*/
+extern _EClassTable g_EClassDefTable;
+
+/*!
+support for one additional/optional entity format
+*/
+extern bool g_bHaveEClassExt;
+extern _EClassTable g_EClassExtTable;
+
+  
+#include "iplugin.h"
+// for interfaces, we require main plugin header included
+#include "qerplugin.h"
+
+//
+// SurfaceDlg.cpp and surface properties plugin
+//
+//++timo some patch in/out stuff is in there, needs to be moved out in a dedicated interface
+#include "isurfaceplugin.h"
+#include "surfaceplugin.h"
+void WINAPI Patch_Rebuild(patchMesh_t *p);
+#include "isurfaceplugin.h"
+extern _QERPlugSurfaceTable g_SurfaceTable;
+void SurfaceDlgFitAll();
+
+//
+// OpenGL interface
+//
+#include "igl.h"
+
+GtkWidget* WINAPI QERApp_GetQeglobalsGLWidget();
+void WINAPI QERApp_HookGL2DWindow(IGL2DWindow* pGLW);
+void WINAPI QERApp_UnHookGL2DWindow(IGL2DWindow* pGLW);
+void WINAPI QERApp_HookGL3DWindow(IGL3DWindow* pGLW);
+void WINAPI QERApp_UnHookGL3DWindow(IGL3DWindow* pGLW);
+void Draw2DPluginEntities( VIEWTYPE vt );
+void Draw3DPluginEntities();
+
+//
+// IShaders interface
+//
+#define USE_SHADERSTABLE_DEFINE
+#include "ishaders.h"
+extern _QERShadersTable g_ShadersTable;
+
+//
+// ISelectedFace interface
+//
+#include "iselectedface.h"
+int WINAPI QERApp_GetSelectedFaceCount();
+// NOTE: it's the brush corresponding to the selected face below!
+brush_t* WINAPI QERApp_GetSelectedFaceBrush(int iface);
+face_t* WINAPI QERApp_GetSelectedFace(int iface);
+int WINAPI QERApp_GetFaceInfo(int iface, _QERFaceData *pFaceData, winding_t *pWinding);
+int WINAPI QERApp_SetFaceInfo(int iface, _QERFaceData *pFaceData);
+int WINAPI QERApp_ISelectedFace_GetTextureNumber(int iface);
+void WINAPI QERApp_GetTextureSize(int iface, int Size[2]);
+
+//
+// IEpairs interface
+//
+//#include "iepairs.h"
+//#include "epairswrapper.h"
+
+//
+// IImage interface
+//
+#include "iimage.h"
+
+//
+// IFileSystem interface
+//
+#define USE_VFSTABLE_DEFINE
+#include "ifilesystem.h"
+
+extern _QERFileSystemTable g_FileSystemTable;
+
+//
+// TexWnd.cpp
+//
+extern qboolean g_bShowAllShaders;
+
+//
+// texwindow.cpp
+//
+//++timo TODO: we can probably raise the MAX_TEXTUREDIRS limit?
+#define		MAX_TEXTUREDIRS	256
+
+extern CPtrArray g_lstSkinCache;
+qtexture_t *QERApp_LoadTextureRGBA(unsigned char* pPixels, int nWidth, int nHeight);
+
+//
+// IScripLib interface
+// GetToken, UnGetToken, etc.
+#include "iscriplib.h"
+extern FILE *g_File;
+void WINAPI QERApp_MapPrintf_FILE( char *text, ... );
+
+//
+// ISurfacePlugin interface
+//
+void QERApp_GetTwoSelectedPatch( patchMesh_t **p1, patchMesh_t **p2 );
+
+//
+// IBSPFrontend interface
+//
+#include "ibspfrontend.h"
+extern _QERPlugBSPFrontendTable g_BSPFrontendTable;
+extern GSList *g_BSPFrontendCommands;
+
+//
+// IToolbar
+//
+#include "itoolbar.h"
+
+//
+// IMessaging interface
+#include "iui.h"
+#include "iui_gtk.h"
+#include "ui.h"
+IWindow* WINAPI QERApp_CreateGLWindow();
+void WINAPI QERApp_HookWindow(IWindowListener* pListen);
+void WINAPI QERApp_UnHookWindow(IWindowListener* pListen);
+IXYWndWrapper* WINAPI QERApp_GetXYWndWrapper();
+void WINAPI QERApp_HookListener(IListener* pListen, int Msg);
+int  WINAPI QERApp_UnHookListener(IListener* pListen);
+void DispatchRadiantMsg( int Msg );
+// dispatch for IWindowListener entities
+void DispatchOnMouseMove(guint32 nFlags, int x, int y);
+bool DispatchOnLButtonDown(guint32 nFlags, int x, int y);
+bool DispatchOnLButtonUp(guint32 nFlags, int x, int y);
+
+//
+// IData interface
+//
+#include "idata.h"
+
+//
+// ICamera interface
+//
+#include "icamera.h"
+
+// Some declarations that were in stdafx.h
+
+// main.cpp
+extern gint try_destroy_splash(gpointer);
+
+#include "mainframe.h"
+#include "preferences.h"
+#include "findtexturedialog.h"
+#include "surfacedialog.h"
+#include "patchdialog.h"
+
+class MainFrame;
+class ClipPoint;
+
+extern MainFrame* g_pParentWnd;
+extern CString g_strAppPath;
+extern CString g_strDTDPath;
+extern CString g_pidFile;
+extern CString g_pidGameFile;
+extern CString g_strBitmapsPath;
+extern CString g_strPluginsDir;
+extern CString g_strModulesDir;
+
+extern CGameDescription *g_pGameDescription;
+extern CString g_strGameToolsPath;
+
+extern CString g_strTempPath;
+extern PrefsDlg& g_PrefsDlg;
+extern FindTextureDialog& g_dlgFind;
+extern SurfaceDlg g_dlgSurface;
+extern PatchDialog g_PatchDialog;
+
+extern int g_bIgnoreCommands;
+
+void HideInfoDialog();
+void ShowInfoDialog(const char* pText);
+
+// externs
+//extern void HandleCommand (GtkWidget *widget, gpointer data, bool keydown);
+extern gint HandleCommand (GtkWidget *widget, gpointer data);
+extern void AddSlash(CString&);
+extern void DLLBuildDone();
+extern void CleanUpEntities();
+extern void FindReplace(CString& strContents, const char* pTag, const char* pValue);
+extern void CheckBspProcess();
+extern void QE_CountBrushesAndUpdateStatusBar();
+extern void	QE_CheckAutoSave();
+extern qtexture_t	*current_texture;
+extern void SaveWithRegion(char *name); // save the current map, sets the map name in the name buffer (deals with regioning)
+extern void RunBsp (char *command);
+extern void Map_Snapshot();
+//extern void WXY_Print();
+extern void AddProp( void );
+extern qboolean DoColor(int iIndex);
+extern entity_t	*edit_entity;
+extern int inspector_mode;
+extern bool g_bRotateMode;
+extern bool g_bClipMode;
+extern bool g_bScaleMode;
+extern int g_nScaleHow;
+extern bool g_bPathMode;
+extern void RunScript(char* pBuffer);
+extern bool ExtractPath_and_Filename(const char* pPath, CString& strPath, CString& strFilename);
+extern void Select_Scale(float x, float y, float z);
+extern void Select_RotateTexture(int amt);
+extern void Select_ScaleTexture(float x, float y);
+extern void Select_ShiftTexture(int x, int y);
+extern void FindReplaceTextures(const char* pFind, const char* pReplace, bool bSelected, bool bForce, bool bSelectMatchingFaces);
+/*!
+\fn DoProjectSettings shows the dialog for per-game configurable settings by the user
+typically this sets up things like mod editing configuration
+those a per-project, not the same thing as preferences which are global to the game conf
+this is still being worked on, as we have several issues with how things are configured
+we also have a number of behaviours defined in the .game, which can't be edited graphically
+we dump those properties to the console when the project settings dialog shows up
+*/
+extern void DoProjectSettings();
+extern qboolean region_active;
+extern void Brush_Print(brush_t* b);
+extern void Texture_ShowStartupShaders();
+extern void Map_ImportFile (char *filename);
+extern void Map_SaveSelected(char* pFilename);
+extern void UpdateSurfaceDialog();
+extern void Select_GetTrueMid (vec3_t mid);
+extern bool g_bSwitch;
+extern brush_t g_brFrontSplits;
+extern brush_t g_brBackSplits;
+extern ClipPoint g_Clip1;
+extern ClipPoint g_Clip2;
+extern brush_t* g_pSplitList;
+extern ClipPoint g_PathPoints[256];
+extern void AcquirePath(int nCount, PFNPathCallback* pFunc);
+extern bool g_bScreenUpdates;
+extern SCommandInfo g_Commands[];
+extern int g_nCommandCount;
+extern SKeyInfo g_Keys[];
+extern int g_nKeyCount;
+extern int inspector_mode;
+extern char	*bsp_commands[256];
+extern void RunScriptByName(char*, bool);
+extern void DoNewColor(int* i1, int* i2, int* i3);
+extern void UpdateSurfaceDialog();
+extern void CSG_SplitBrushByFace (brush_t *in, face_t *f, brush_t **front, brush_t **back);
+//extern void HandlePopup(CWnd* pWindow, unsigned int uId);
+extern z_t z;
+extern void Select_Scale(float x, float y, float z);
+extern void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv);
+//extern void VectorRotate (vec3_t va, vec3_t vb, vec3_t out);
+//extern void VectorRotate (vec3_t vIn, vec3_t vRotation, vec3_t vOrigin, vec3_t out);
+extern qboolean QE_SaveProject (const char* pProjectFile);
+//extern void NewBSP(char* pCommandLine, HWND);
+//extern void NewVIS(char* pCommandLine, HWND);
+//extern void NewRAD(char* pCommandLine, HWND);
+extern void RunTools(char* pCommandLine, GtkWidget* hwnd, const char* pPAKFile);
+extern void Clamp(float& f, int nClamp);
+extern void MemFile_fprintf(MemStream* pMemFile, const char* pText, ...);
+//extern void SaveWindowPlacement(HWND hwnd, const char* pName);
+//extern bool LoadWindowPlacement(HWND hwnd, const char* pName);
+extern qboolean ConfirmModified (void);
+extern void DoPatchInspector();
+extern void TogglePatchInspector();
+void UpdatePatchInspector();
+extern int BuildShortPathName(const char* pPath, char* pBuffer, int nBufferLen);
+extern int g_nBrushId;
+
+// defined in gtkdlgs.cpp, we might want to move declaration and implementatin with other Select_ stuff..
+// NOTE: there's also a Select_Brush(brush_t *b) function.. unrelated
+extern void SelectBrush (int entitynum, int brushnum);
+
+// bp_dlg.cpp
+// ret: 0 = abort, 1 = load and convert, 2 = changed project settings, load and don't convert
+// the user might decide to switch the BP mode in project settings
+// status: 0 = loading regular, got conflict 1 = loading BP, got conflict
+extern int BP_MessageBox (int status);
+
+// main.cpp
+extern gint try_destroy_splash(gpointer);
+
+// SPoG
+// targetname.cpp
+void Entity_Connect(entity_t *e1, entity_t *e2);
+int GetUniqueTargetId(int iHint);
+
+// xywindow.cpp
+void CreateEntityFromName(const char* name, const vec3_t origin);
+
+// eclass.cpp
+/*!
+\brief initialization of the eclass manager
+general guidelines about eclass.cpp implementation:
+- we don't support unlimited number of eclass file formats together
+  currently limited to two
+  support for .def is builtin to the core, but you may choose not to activate it
+- search and load of the files:
+  the manager is in charge of scanning for eclass definition files to load
+  there is a general configuration setting for games which use a different set of
+    entities between single player mode and multiplayer mode (TODO: the code doing
+    this needs to be abstracted some more)
+- duplicate files / multiple files:
+  if two files with the same name exist (for instance in the basegame, and in fs_game)
+  then only the first one found in the scan order is loaded
+  if several files are found, they are all loaded
+  this allows mods to either replace or extend the list of eclass
+- if eclass_singleload prop is used in the .game, then there is no multiple files check
+  the first file found is loaded, and there is no further search for the given extension
+  (this was an addition for HL support)
+*/
+void Eclass_Init ();
+eclass_t *Eclass_ForName (const char *name, qboolean has_brushes);
+eclass_t * EClass_Create( const char *name, float col1, float col2, float col3, const vec3_t *mins, const vec3_t *maxs, const char *comments );
+
+#endif // _QE3_H_
diff --git a/radiant/qedefs.h b/radiant/qedefs.h
index 463fcc29..23a3d28b 100644
--- a/radiant/qedefs.h
+++ b/radiant/qedefs.h
@@ -1,128 +1,128 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __QEDEFS_H__
-#define __QEDEFS_H__
-
-#define	_3DFXCAMERA_WINDOW_CLASS	"Q3DFXCamera"
-#define	CAMERA_WINDOW_CLASS	"QCamera"
-#define	XY_WINDOW_CLASS	    "QXY"
-#define	Z_WINDOW_CLASS   	"QZ"
-#define	ENT_WINDOW_CLASS	"QENT"
-#define	TEXTURE_WINDOW_CLASS	"QTEX"
-
-#define	ZWIN_WIDTH	40
-#define CWIN_SIZE	(0.4)
-
-#define	MAX_EDGES	512
-#define	MAX_POINTS	1024
-
-#define	CMD_TEXTUREWAD	60000
-#define	CMD_BSPCOMMAND	61000
-
-#define	PITCH	0
-#define	YAW		1
-#define	ROLL	2
-
-#define QE_TIMER0   1
-
-#define	PLANE_X		0
-#define	PLANE_Y		1
-#define	PLANE_Z		2
-#define	PLANE_ANYX	3
-#define	PLANE_ANYY	4
-#define	PLANE_ANYZ	5
-
-#define	ON_EPSILON	0.01
-
-#define	KEY_FORWARD		1
-#define	KEY_BACK		2
-#define	KEY_TURNLEFT	4
-#define	KEY_TURNRIGHT	8
-#define	KEY_LEFT		16
-#define	KEY_RIGHT		32
-#define	KEY_LOOKUP		64
-#define	KEY_LOOKDOWN	128
-#define	KEY_UP			256
-#define	KEY_DOWN		512
-
-// xy.c
-#define EXCLUDE_WORLD           0x00000001
-#define EXCLUDE_ENT             0x00000002
-#define EXCLUDE_CURVES          0x00000004
-#define EXCLUDE_TRANSLUCENT     0x00000008
-#define EXCLUDE_LIQUIDS         0x00000010
-#define EXCLUDE_CAULK           0x00000020
-#define EXCLUDE_CLIP            0x00000040
-#define EXCLUDE_PATHS           0x00000080
-#define EXCLUDE_LIGHTS          0x00000100
-#define EXCLUDE_DETAILS         0x00000200
-#define EXCLUDE_HINTSSKIPS      0x00000400
-#define EXCLUDE_MODELS          0x00000800
-#define EXCLUDE_AREAPORTALS     0x00001000
-#define EXCLUDE_TRIGGERS        0x00002000
-#define EXCLUDE_CLUSTERPORTALS	0x00004000
-#define EXCLUDE_TERRAIN         0x00008000
-#define EXCLUDE_LIGHTGRID       0x00010000
-#define EXCLUDE_STRUCTURAL      0x00020000
-#define EXCLUDE_BOTCLIP		      0x00040000
-
-#define	INCLUDE_EASY            0x00000001
-#define	INCLUDE_NORMAL          0x00000002
-#define	INCLUDE_HARD            0x00000004
-#define	INCLUDE_DEATHMATCH      0x00000008
-#define INCLUDE_NAMES           0x00000010
-#define INCLUDE_COORDS          0x00000020
-#define INCLUDE_BLOCKS          0x00000040
-#define INCLUDE_ANGLES          0x00000080
-#define INCLUDE_PATCHBBOXES     0x00000100
-#define INCLUDE_PATCHWIREFRAME  0x00000200
-#define INCLUDE_CAMERATINT      0x00000400
-#define INCLUDE_MODELBOXONLY    0x00000800
-
-//
-// menu indexes for modifying menus
-//
-#define	MENU_VIEW		2
-#define	MENU_BSP		4
-#define	MENU_TEXTURE	6
-#define	MENU_PLUGIN	11
-
-// odd things not in windows header...
-#define	VK_COMMA		188
-#define	VK_PERIOD		190
-
-// ShowEntitiesAs flags
-// used in camera code, not menus
-#define ENTITY_WIREFRAME		0x00001
-#define ENTITY_SKIN_MODEL		0x00010
-#define ENTITY_SELECTED_ONLY	0x00100
-#define ENTITY_BOXED			0x01000
-
-// ShowEntitiesAs menu settings .. combinations of the above settings
-#define ENTITY_BOX				0x01000
-#define ENTITY_WIRE				0x00001
-#define ENTITY_SELECTED			0x00101
-#define ENTITY_SKINNED 			0x00010
-#define ENTITY_SKINNED_BOXED	0x01010
-#define ENTITY_SELECTED_SKIN	0x00110
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __QEDEFS_H__
+#define __QEDEFS_H__
+
+#define	_3DFXCAMERA_WINDOW_CLASS	"Q3DFXCamera"
+#define	CAMERA_WINDOW_CLASS	"QCamera"
+#define	XY_WINDOW_CLASS	    "QXY"
+#define	Z_WINDOW_CLASS   	"QZ"
+#define	ENT_WINDOW_CLASS	"QENT"
+#define	TEXTURE_WINDOW_CLASS	"QTEX"
+
+#define	ZWIN_WIDTH	40
+#define CWIN_SIZE	(0.4)
+
+#define	MAX_EDGES	512
+#define	MAX_POINTS	1024
+
+#define	CMD_TEXTUREWAD	60000
+#define	CMD_BSPCOMMAND	61000
+
+#define	PITCH	0
+#define	YAW		1
+#define	ROLL	2
+
+#define QE_TIMER0   1
+
+#define	PLANE_X		0
+#define	PLANE_Y		1
+#define	PLANE_Z		2
+#define	PLANE_ANYX	3
+#define	PLANE_ANYY	4
+#define	PLANE_ANYZ	5
+
+#define	ON_EPSILON	0.01
+
+#define	KEY_FORWARD		1
+#define	KEY_BACK		2
+#define	KEY_TURNLEFT	4
+#define	KEY_TURNRIGHT	8
+#define	KEY_LEFT		16
+#define	KEY_RIGHT		32
+#define	KEY_LOOKUP		64
+#define	KEY_LOOKDOWN	128
+#define	KEY_UP			256
+#define	KEY_DOWN		512
+
+// xy.c
+#define EXCLUDE_WORLD           0x00000001
+#define EXCLUDE_ENT             0x00000002
+#define EXCLUDE_CURVES          0x00000004
+#define EXCLUDE_TRANSLUCENT     0x00000008
+#define EXCLUDE_LIQUIDS         0x00000010
+#define EXCLUDE_CAULK           0x00000020
+#define EXCLUDE_CLIP            0x00000040
+#define EXCLUDE_PATHS           0x00000080
+#define EXCLUDE_LIGHTS          0x00000100
+#define EXCLUDE_DETAILS         0x00000200
+#define EXCLUDE_HINTSSKIPS      0x00000400
+#define EXCLUDE_MODELS          0x00000800
+#define EXCLUDE_AREAPORTALS     0x00001000
+#define EXCLUDE_TRIGGERS        0x00002000
+#define EXCLUDE_CLUSTERPORTALS	0x00004000
+#define EXCLUDE_TERRAIN         0x00008000
+#define EXCLUDE_LIGHTGRID       0x00010000
+#define EXCLUDE_STRUCTURAL      0x00020000
+#define EXCLUDE_BOTCLIP		      0x00040000
+
+#define	INCLUDE_EASY            0x00000001
+#define	INCLUDE_NORMAL          0x00000002
+#define	INCLUDE_HARD            0x00000004
+#define	INCLUDE_DEATHMATCH      0x00000008
+#define INCLUDE_NAMES           0x00000010
+#define INCLUDE_COORDS          0x00000020
+#define INCLUDE_BLOCKS          0x00000040
+#define INCLUDE_ANGLES          0x00000080
+#define INCLUDE_PATCHBBOXES     0x00000100
+#define INCLUDE_PATCHWIREFRAME  0x00000200
+#define INCLUDE_CAMERATINT      0x00000400
+#define INCLUDE_MODELBOXONLY    0x00000800
+
+//
+// menu indexes for modifying menus
+//
+#define	MENU_VIEW		2
+#define	MENU_BSP		4
+#define	MENU_TEXTURE	6
+#define	MENU_PLUGIN	11
+
+// odd things not in windows header...
+#define	VK_COMMA		188
+#define	VK_PERIOD		190
+
+// ShowEntitiesAs flags
+// used in camera code, not menus
+#define ENTITY_WIREFRAME		0x00001
+#define ENTITY_SKIN_MODEL		0x00010
+#define ENTITY_SELECTED_ONLY	0x00100
+#define ENTITY_BOXED			0x01000
+
+// ShowEntitiesAs menu settings .. combinations of the above settings
+#define ENTITY_BOX				0x01000
+#define ENTITY_WIRE				0x00001
+#define ENTITY_SELECTED			0x00101
+#define ENTITY_SKINNED 			0x00010
+#define ENTITY_SKINNED_BOXED	0x01010
+#define ENTITY_SELECTED_SKIN	0x00110
+
+#endif
diff --git a/radiant/qfiles.h b/radiant/qfiles.h
index b339d3d1..c602ec84 100644
--- a/radiant/qfiles.h
+++ b/radiant/qfiles.h
@@ -1,480 +1,480 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-/*
-========================================================================
-
-.MD2 triangle model file format
-
-========================================================================
-*/
-
-#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
-#define ALIAS_VERSION	8
-
-#define	MAX_TRIANGLES	4096
-#define MAX_VERTS		2048
-#define MAX_FRAMES		512
-#define MAX_MD2SKINS	32
-#define	MAX_SKINNAME	64
-
-typedef struct
-{
-	short	s;
-	short	t;
-} dstvert_t;
-
-typedef struct 
-{
-	short	index_xyz[3];
-	short	index_st[3];
-} dtriangle_t;
-
-typedef struct
-{
-	byte	v[3];			// scaled byte to fit in frame mins/maxs
-	byte	lightnormalindex;
-} dtrivertx_t;
-
-typedef struct
-{
-	float		scale[3];	// multiply byte verts by this
-	float		translate[3];	// then add this
-	char		name[16];	// frame name from grabbing
-	dtrivertx_t	verts[1];	// variable sized
-} daliasframe_t;
-
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-typedef struct
-{
-	int			ident;
-	int			version;
-
-	int			skinwidth;
-	int			skinheight;
-	int			framesize;		// byte size of each frame
-
-	int			num_skins;
-	int			num_xyz;
-	int			num_st;			// greater than num_xyz for seams
-	int			num_tris;
-	int			num_glcmds;		// dwords in strip/fan command list
-	int			num_frames;
-
-	int			ofs_skins;		// each skin is a MAX_SKINNAME string
-	int			ofs_st;			// byte offset from start for stverts
-	int			ofs_tris;		// offset for dtriangles
-	int			ofs_frames;		// offset for first frame
-	int			ofs_glcmds;	
-	int			ofs_end;		// end of file
-
-} dmdl_t;
-
-#define MD3_IDENT			(('3'<<24)+('P'<<16)+('D'<<8)+'I')
-#define	MAX_QPATH			64		// max length of a quake game pathname
-#define	MD3_XYZ_SCALE		(1.0/64)
-
-typedef struct {
-	int			ident;
-	int			version;
-
-	char		name[MAX_QPATH];	// model name
-
-	int			flags;
-
-	int			numFrames;
-	int			numTags;			
-	int			numSurfaces;
-
-	int			numSkins;
-
-	int			ofsFrames;			// offset for first frame
-	int			ofsTags;			// numFrames * numTags
-	int			ofsSurfaces;		// first surface, others follow
-
-	int			ofsEnd;				// end of file
-} md3Header_t;
-
-typedef struct {
-	int		ident;				// 
-
-	char	name[MAX_QPATH];	// polyset name
-
-	int		flags;
-	int		numFrames;			// all surfaces in a model should have the same
-
-	int		numShaders;			// all surfaces in a model should have the same
-	int		numVerts;
-
-	int		numTriangles;
-	int		ofsTriangles;
-
-	int		ofsShaders;			// offset from start of md3Surface_t
-	int		ofsSt;				// texture coords are common for all frames
-	int		ofsXyzNormals;		// numVerts * numFrames
-
-	int		ofsEnd;				// next surface follows
-
-} md3Surface_t;
-
-typedef struct {
-	char			name[MAX_QPATH];
-	int				shaderIndex;	// for in-game use
-} md3Shader_t;
-
-typedef struct {
-	int			indexes[3];
-} md3Triangle_t;
-
-typedef struct {
-	float		st[2];
-} md3St_t;
-
-typedef struct {
-	short		xyz[3];
-	short		normal;
-} md3XyzNormal_t;
-
-
-typedef struct
-{
-  float st[2];
-  int   nVertIndex;
-} glst_t;
-
-typedef struct
-{
-  int     nCount;
-  int     ObjectIndex;
-  glst_t  GlSt;
-} gl_t;
-
-/*
-========================================================================
-
-.SP2 sprite file format
-
-========================================================================
-*/
-
-#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
-		// little-endian "IDS2"
-#define SPRITE_VERSION	2
-
-typedef struct
-{
-	int		width, height;
-	int		origin_x, origin_y;		// raster coordinates inside pic
-	char	name[MAX_SKINNAME];		// name of pcx file
-} dsprframe_t;
-
-typedef struct {
-	int			ident;
-	int			version;
-	int			numframes;
-	dsprframe_t	frames[1];			// variable sized
-} dsprite_t;
-
-/*
-==============================================================================
-
-  .WAL texture file format
-
-==============================================================================
-*/
-
-
-#define	MIPLEVELS	4
-#ifndef __MIPTEX_S_
-#define __MIPTEX_S_
-typedef struct miptex_s
-{
-	char		name[32];
-	unsigned	width, height;
-	unsigned	offsets[MIPLEVELS];		// four mip maps stored
-	char		animname[32];			// next frame in animation chain
-	int			flags;
-	int			contents;
-	int			value;
-} miptex_t;
-#endif
-
-
-/*
-==============================================================================
-
-  .BSP file format
-
-==============================================================================
-*/
-
-#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
-		// little-endian "IBSP"
-
-#define BSPVERSION	36
-
-
-// upper design bounds
-// leaffaces, leafbrushes, planes, and verts are still bounded by
-// 16 bit short limits
-#define	MAX_MAP_MODELS		1024
-#define	MAX_MAP_BRUSHES		8192
-#define	MAX_MAP_ENTITIES	2048
-#define	MAX_MAP_ENTSTRING	0x20000
-#define	MAX_MAP_TEXINFO		8192
-
-#define	MAX_MAP_PLANES		65536
-#define	MAX_MAP_NODES		65536
-#define	MAX_MAP_BRUSHSIDES	65536
-#define	MAX_MAP_LEAFS		65536
-#define	MAX_MAP_VERTS		65536
-#define	MAX_MAP_FACES		65536
-#define	MAX_MAP_LEAFFACES	65536
-#define	MAX_MAP_LEAFBRUSHES 65536
-#define	MAX_MAP_PORTALS		65536
-#define	MAX_MAP_EDGES		128000
-#define	MAX_MAP_SURFEDGES	256000
-#define	MAX_MAP_LIGHTING	0x200000
-#define	MAX_MAP_VISIBILITY	0x100000
-
-// we are using g_MaxBrushSize now, cleanme
-/* #define MAX_BRUSH_SIZE 8192 */
-
-// key / value pair sizes
-
-#define	MAX_KEY		32
-#define	MAX_VALUE	1024
-
-//=============================================================================
-
-typedef struct
-{
-	int		fileofs, filelen;
-} lump_t;
-
-#define	LUMP_ENTITIES		0
-#define	LUMP_PLANES			1
-#define	LUMP_VERTEXES		2
-#define	LUMP_VISIBILITY		3
-#define	LUMP_NODES			4
-#define	LUMP_TEXINFO		5
-#define	LUMP_FACES			6
-#define	LUMP_LIGHTING		7
-#define	LUMP_LEAFS			8
-#define	LUMP_LEAFFACES		9
-#define	LUMP_LEAFBRUSHES	10
-#define	LUMP_EDGES			11
-#define	LUMP_SURFEDGES		12
-#define	LUMP_MODELS			13
-#define	LUMP_BRUSHES		14
-#define	LUMP_BRUSHSIDES		15
-#define	LUMP_POP			16
-
-#define	HEADER_LUMPS		17
-
-typedef struct
-{
-	int			ident;
-	int			version;	
-	lump_t		lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct
-{
-	float		mins[3], maxs[3];
-	float		origin[3];		// for sounds or lights
-	int			headnode;
-	int			firstface, numfaces;	// submodels just draw faces
-										// without walking the bsp tree
-} dmodel_t;
-
-
-typedef struct
-{
-	float	point[3];
-} dvertex_t;
-
-
-// 0-2 are axial planes
-#define	PLANE_X			0
-#define	PLANE_Y			1
-#define	PLANE_Z			2
-
-// 3-5 are non-axial planes snapped to the nearest
-#define	PLANE_ANYX		3
-#define	PLANE_ANYY		4
-#define	PLANE_ANYZ		5
-
-// planes (x&~1) and (x&~1)+1 are allways opposites
-
-typedef struct
-{
-	float	normal[3];
-	float	dist;
-	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
-} dplane_t;
-
-
-// contents flags are seperate bits
-// a given brush can contribute multiple content bits
-// multiple brushes can be in a single leaf
-
-// lower bits are stronger, and will eat weaker brushes completely
-#define	CONTENTS_SOLID			1		// an eye is never valid in a solid
-#define	CONTENTS_WINDOW			2		// translucent, but not watery
-#define	CONTENTS_AUX			4
-#define	CONTENTS_LAVA			8
-#define	CONTENTS_SLIME			16
-#define	CONTENTS_WATER			32
-#define	CONTENTS_MIST			64
-#define	LAST_VISIBLE_CONTENTS	64
-
-// remaining contents are non-visible, and don't eat brushes
-#define	CONTENTS_PLAYERCLIP		0x10000
-#define	CONTENTS_MONSTERCLIP	0x20000
-
-// currents can be added to any other contents, and may be mixed
-#define	CONTENTS_CURRENT_0		0x40000
-#define	CONTENTS_CURRENT_90		0x80000
-#define	CONTENTS_CURRENT_180	0x100000
-#define	CONTENTS_CURRENT_270	0x200000
-#define	CONTENTS_CURRENT_UP		0x400000
-#define	CONTENTS_CURRENT_DOWN	0x800000
-
-#define	CONTENTS_ORIGIN			    0x1000000	  // removed before bsping an entity
-
-#define	CONTENTS_MONSTER		    0x2000000	  // should never be on a brush, only in game
-#define	CONTENTS_DEADMONSTER	  0x4000000   // corpse
-#define	CONTENTS_DETAIL			    0x8000000	  // brushes to be added after vis leafs
-#define	CONTENTS_TRANSLUCENT	  0x10000000	// auto set if any surface has trans
-#define	CONTENTS_LADDER         0x20000000	// ladder
-#define	CONTENTS_NEGATIVE_CURVE 0x40000000	// reverse inside / outside
-
-#define	CONTENTS_KEEP	(CONTENTS_DETAIL | CONTENTS_NEGATIVE_CURVE)
-
-
-typedef struct
-{
-	int			planenum;
-	int			children[2];	// negative numbers are -(leafs+1), not nodes
-	short		mins[3];		// for frustom culling
-	short		maxs[3];
-	unsigned short	firstface;
-	unsigned short	numfaces;	// counting both sides
-} dnode_t;
-
-
-typedef struct texinfo_s
-{
-	float		vecs[2][4];		// [s/t][xyz offset]
-	int			flags;			// miptex flags + overrides
-	int			value;			// light emission, etc
-	char		texture[32];	// texture name (textures/*.wal)
-	int			nexttexinfo;	// for animations, -1 = end of chain
-} texinfo_t;
-
-
-#define	SURF_LIGHT		0x1		// value will hold the light strength
-
-#define	SURF_SLICK		0x2		// effects game physics
-
-#define	SURF_SKY		0x4		// don't draw, but add to skybox
-#define	SURF_WARP		0x8		// turbulent water warp
-#define	SURF_TRANS33	0x10
-#define	SURF_TRANS66	0x20
-#define	SURF_FLOWING	0x40	// scroll towards angle
-#define	SURF_NODRAW		0x80	// don't bother referencing the texture
-
-#define SURF_PATCH        0x20000000
-#define	SURF_CURVE_FAKE		0x40000000
-#define	SURF_CURVE		    0x80000000
-#define	SURF_KEEP		(SURF_CURVE | SURF_CURVE_FAKE | SURF_PATCH)
-
-// note that edge 0 is never used, because negative edge nums are used for
-// counterclockwise use of the edge in a face
-typedef struct
-{
-	unsigned short	v[2];		// vertex numbers
-} dedge_t;
-
-#define	MAXLIGHTMAPS	4
-typedef struct
-{
-	unsigned short	planenum;
-	short		side;
-
-	int			firstedge;		// we must support > 64k edges
-	short		numedges;	
-	short		texinfo;
-
-// lighting info
-	byte		styles[MAXLIGHTMAPS];
-	int			lightofs;		// start of [numstyles*surfsize] samples
-} dface_t;
-
-typedef struct
-{
-	int			contents;			// OR of all brushes (not needed?)
-
-	int			pvsofs;				// -1 = no info
-	int			phsofs;				// -1 = no info
-
-	short		mins[3];			// for frustum culling
-	short		maxs[3];
-
-	unsigned short		firstleafface;
-	unsigned short		numleaffaces;
-
-	unsigned short		firstleafbrush;
-	unsigned short		numleafbrushes;
-} dleaf_t;
-
-typedef struct
-{
-	unsigned short	planenum;		// facing out of the leaf
-	short	texinfo;
-} dbrushside_t;
-
-typedef struct
-{
-	int			firstside;
-	int			numsides;
-	int			contents;
-} dbrush_t;
-
-#define	ANGLE_UP	-1
-#define	ANGLE_DOWN	-2
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+/*
+========================================================================
+
+.MD2 triangle model file format
+
+========================================================================
+*/
+
+#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
+#define ALIAS_VERSION	8
+
+#define	MAX_TRIANGLES	4096
+#define MAX_VERTS		2048
+#define MAX_FRAMES		512
+#define MAX_MD2SKINS	32
+#define	MAX_SKINNAME	64
+
+typedef struct
+{
+	short	s;
+	short	t;
+} dstvert_t;
+
+typedef struct 
+{
+	short	index_xyz[3];
+	short	index_st[3];
+} dtriangle_t;
+
+typedef struct
+{
+	byte	v[3];			// scaled byte to fit in frame mins/maxs
+	byte	lightnormalindex;
+} dtrivertx_t;
+
+typedef struct
+{
+	float		scale[3];	// multiply byte verts by this
+	float		translate[3];	// then add this
+	char		name[16];	// frame name from grabbing
+	dtrivertx_t	verts[1];	// variable sized
+} daliasframe_t;
+
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+typedef struct
+{
+	int			ident;
+	int			version;
+
+	int			skinwidth;
+	int			skinheight;
+	int			framesize;		// byte size of each frame
+
+	int			num_skins;
+	int			num_xyz;
+	int			num_st;			// greater than num_xyz for seams
+	int			num_tris;
+	int			num_glcmds;		// dwords in strip/fan command list
+	int			num_frames;
+
+	int			ofs_skins;		// each skin is a MAX_SKINNAME string
+	int			ofs_st;			// byte offset from start for stverts
+	int			ofs_tris;		// offset for dtriangles
+	int			ofs_frames;		// offset for first frame
+	int			ofs_glcmds;	
+	int			ofs_end;		// end of file
+
+} dmdl_t;
+
+#define MD3_IDENT			(('3'<<24)+('P'<<16)+('D'<<8)+'I')
+#define	MAX_QPATH			64		// max length of a quake game pathname
+#define	MD3_XYZ_SCALE		(1.0/64)
+
+typedef struct {
+	int			ident;
+	int			version;
+
+	char		name[MAX_QPATH];	// model name
+
+	int			flags;
+
+	int			numFrames;
+	int			numTags;			
+	int			numSurfaces;
+
+	int			numSkins;
+
+	int			ofsFrames;			// offset for first frame
+	int			ofsTags;			// numFrames * numTags
+	int			ofsSurfaces;		// first surface, others follow
+
+	int			ofsEnd;				// end of file
+} md3Header_t;
+
+typedef struct {
+	int		ident;				// 
+
+	char	name[MAX_QPATH];	// polyset name
+
+	int		flags;
+	int		numFrames;			// all surfaces in a model should have the same
+
+	int		numShaders;			// all surfaces in a model should have the same
+	int		numVerts;
+
+	int		numTriangles;
+	int		ofsTriangles;
+
+	int		ofsShaders;			// offset from start of md3Surface_t
+	int		ofsSt;				// texture coords are common for all frames
+	int		ofsXyzNormals;		// numVerts * numFrames
+
+	int		ofsEnd;				// next surface follows
+
+} md3Surface_t;
+
+typedef struct {
+	char			name[MAX_QPATH];
+	int				shaderIndex;	// for in-game use
+} md3Shader_t;
+
+typedef struct {
+	int			indexes[3];
+} md3Triangle_t;
+
+typedef struct {
+	float		st[2];
+} md3St_t;
+
+typedef struct {
+	short		xyz[3];
+	short		normal;
+} md3XyzNormal_t;
+
+
+typedef struct
+{
+  float st[2];
+  int   nVertIndex;
+} glst_t;
+
+typedef struct
+{
+  int     nCount;
+  int     ObjectIndex;
+  glst_t  GlSt;
+} gl_t;
+
+/*
+========================================================================
+
+.SP2 sprite file format
+
+========================================================================
+*/
+
+#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
+		// little-endian "IDS2"
+#define SPRITE_VERSION	2
+
+typedef struct
+{
+	int		width, height;
+	int		origin_x, origin_y;		// raster coordinates inside pic
+	char	name[MAX_SKINNAME];		// name of pcx file
+} dsprframe_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+	int			numframes;
+	dsprframe_t	frames[1];			// variable sized
+} dsprite_t;
+
+/*
+==============================================================================
+
+  .WAL texture file format
+
+==============================================================================
+*/
+
+
+#define	MIPLEVELS	4
+#ifndef __MIPTEX_S_
+#define __MIPTEX_S_
+typedef struct miptex_s
+{
+	char		name[32];
+	unsigned	width, height;
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+	char		animname[32];			// next frame in animation chain
+	int			flags;
+	int			contents;
+	int			value;
+} miptex_t;
+#endif
+
+
+/*
+==============================================================================
+
+  .BSP file format
+
+==============================================================================
+*/
+
+#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
+		// little-endian "IBSP"
+
+#define BSPVERSION	36
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define	MAX_MAP_MODELS		1024
+#define	MAX_MAP_BRUSHES		8192
+#define	MAX_MAP_ENTITIES	2048
+#define	MAX_MAP_ENTSTRING	0x20000
+#define	MAX_MAP_TEXINFO		8192
+
+#define	MAX_MAP_PLANES		65536
+#define	MAX_MAP_NODES		65536
+#define	MAX_MAP_BRUSHSIDES	65536
+#define	MAX_MAP_LEAFS		65536
+#define	MAX_MAP_VERTS		65536
+#define	MAX_MAP_FACES		65536
+#define	MAX_MAP_LEAFFACES	65536
+#define	MAX_MAP_LEAFBRUSHES 65536
+#define	MAX_MAP_PORTALS		65536
+#define	MAX_MAP_EDGES		128000
+#define	MAX_MAP_SURFEDGES	256000
+#define	MAX_MAP_LIGHTING	0x200000
+#define	MAX_MAP_VISIBILITY	0x100000
+
+// we are using g_MaxBrushSize now, cleanme
+/* #define MAX_BRUSH_SIZE 8192 */
+
+// key / value pair sizes
+
+#define	MAX_KEY		32
+#define	MAX_VALUE	1024
+
+//=============================================================================
+
+typedef struct
+{
+	int		fileofs, filelen;
+} lump_t;
+
+#define	LUMP_ENTITIES		0
+#define	LUMP_PLANES			1
+#define	LUMP_VERTEXES		2
+#define	LUMP_VISIBILITY		3
+#define	LUMP_NODES			4
+#define	LUMP_TEXINFO		5
+#define	LUMP_FACES			6
+#define	LUMP_LIGHTING		7
+#define	LUMP_LEAFS			8
+#define	LUMP_LEAFFACES		9
+#define	LUMP_LEAFBRUSHES	10
+#define	LUMP_EDGES			11
+#define	LUMP_SURFEDGES		12
+#define	LUMP_MODELS			13
+#define	LUMP_BRUSHES		14
+#define	LUMP_BRUSHSIDES		15
+#define	LUMP_POP			16
+
+#define	HEADER_LUMPS		17
+
+typedef struct
+{
+	int			ident;
+	int			version;	
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+	float		mins[3], maxs[3];
+	float		origin[3];		// for sounds or lights
+	int			headnode;
+	int			firstface, numfaces;	// submodels just draw faces
+										// without walking the bsp tree
+} dmodel_t;
+
+
+typedef struct
+{
+	float	point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define	PLANE_X			0
+#define	PLANE_Y			1
+#define	PLANE_Z			2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define	PLANE_ANYX		3
+#define	PLANE_ANYY		4
+#define	PLANE_ANYZ		5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+	float	normal[3];
+	float	dist;
+	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// lower bits are stronger, and will eat weaker brushes completely
+#define	CONTENTS_SOLID			1		// an eye is never valid in a solid
+#define	CONTENTS_WINDOW			2		// translucent, but not watery
+#define	CONTENTS_AUX			4
+#define	CONTENTS_LAVA			8
+#define	CONTENTS_SLIME			16
+#define	CONTENTS_WATER			32
+#define	CONTENTS_MIST			64
+#define	LAST_VISIBLE_CONTENTS	64
+
+// remaining contents are non-visible, and don't eat brushes
+#define	CONTENTS_PLAYERCLIP		0x10000
+#define	CONTENTS_MONSTERCLIP	0x20000
+
+// currents can be added to any other contents, and may be mixed
+#define	CONTENTS_CURRENT_0		0x40000
+#define	CONTENTS_CURRENT_90		0x80000
+#define	CONTENTS_CURRENT_180	0x100000
+#define	CONTENTS_CURRENT_270	0x200000
+#define	CONTENTS_CURRENT_UP		0x400000
+#define	CONTENTS_CURRENT_DOWN	0x800000
+
+#define	CONTENTS_ORIGIN			    0x1000000	  // removed before bsping an entity
+
+#define	CONTENTS_MONSTER		    0x2000000	  // should never be on a brush, only in game
+#define	CONTENTS_DEADMONSTER	  0x4000000   // corpse
+#define	CONTENTS_DETAIL			    0x8000000	  // brushes to be added after vis leafs
+#define	CONTENTS_TRANSLUCENT	  0x10000000	// auto set if any surface has trans
+#define	CONTENTS_LADDER         0x20000000	// ladder
+#define	CONTENTS_NEGATIVE_CURVE 0x40000000	// reverse inside / outside
+
+#define	CONTENTS_KEEP	(CONTENTS_DETAIL | CONTENTS_NEGATIVE_CURVE)
+
+
+typedef struct
+{
+	int			planenum;
+	int			children[2];	// negative numbers are -(leafs+1), not nodes
+	short		mins[3];		// for frustom culling
+	short		maxs[3];
+	unsigned short	firstface;
+	unsigned short	numfaces;	// counting both sides
+} dnode_t;
+
+
+typedef struct texinfo_s
+{
+	float		vecs[2][4];		// [s/t][xyz offset]
+	int			flags;			// miptex flags + overrides
+	int			value;			// light emission, etc
+	char		texture[32];	// texture name (textures/*.wal)
+	int			nexttexinfo;	// for animations, -1 = end of chain
+} texinfo_t;
+
+
+#define	SURF_LIGHT		0x1		// value will hold the light strength
+
+#define	SURF_SLICK		0x2		// effects game physics
+
+#define	SURF_SKY		0x4		// don't draw, but add to skybox
+#define	SURF_WARP		0x8		// turbulent water warp
+#define	SURF_TRANS33	0x10
+#define	SURF_TRANS66	0x20
+#define	SURF_FLOWING	0x40	// scroll towards angle
+#define	SURF_NODRAW		0x80	// don't bother referencing the texture
+
+#define SURF_PATCH        0x20000000
+#define	SURF_CURVE_FAKE		0x40000000
+#define	SURF_CURVE		    0x80000000
+#define	SURF_KEEP		(SURF_CURVE | SURF_CURVE_FAKE | SURF_PATCH)
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+	unsigned short	v[2];		// vertex numbers
+} dedge_t;
+
+#define	MAXLIGHTMAPS	4
+typedef struct
+{
+	unsigned short	planenum;
+	short		side;
+
+	int			firstedge;		// we must support > 64k edges
+	short		numedges;	
+	short		texinfo;
+
+// lighting info
+	byte		styles[MAXLIGHTMAPS];
+	int			lightofs;		// start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+	int			contents;			// OR of all brushes (not needed?)
+
+	int			pvsofs;				// -1 = no info
+	int			phsofs;				// -1 = no info
+
+	short		mins[3];			// for frustum culling
+	short		maxs[3];
+
+	unsigned short		firstleafface;
+	unsigned short		numleaffaces;
+
+	unsigned short		firstleafbrush;
+	unsigned short		numleafbrushes;
+} dleaf_t;
+
+typedef struct
+{
+	unsigned short	planenum;		// facing out of the leaf
+	short	texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+	int			firstside;
+	int			numsides;
+	int			contents;
+} dbrush_t;
+
+#define	ANGLE_UP	-1
+#define	ANGLE_DOWN	-2
+
diff --git a/radiant/qgl-mac.c b/radiant/qgl-mac.c
index 5b769090..105f21e3 100644
--- a/radiant/qgl-mac.c
+++ b/radiant/qgl-mac.c
@@ -1,1775 +1,1775 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-** QGL_WIN.C
-**
-** This file implements the operating system binding of GL to QGL function
-** pointers.  When doing a port of Quake2 you must implement the following
-** two functions:
-**
-** QGL_Init() - loads libraries, assigns function pointers, etc.
-** QGL_Shutdown() - unloads libraries, NULLs function pointers
-*/
-#include <stdio.h>
-#include <float.h>
-#include <string.h>
-#if defined (__linux__) || defined (__APPLE__)
-//#include <dlfcn.h>
-#endif
-#ifdef _WIN32
-#include <windows.h>
-#endif
-#include "qgl.h"
-#include <GL/glu.h>
-void Sys_Printf(const char *format, ...);
-
-#ifdef _WIN32
-HMODULE g_hGLDLL = NULL;
-
-#pragma warning (disable : 4113 4133 4047 4018 )
-
-int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
-int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
-int   ( WINAPI * qwglGetPixelFormat)(HDC);
-BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
-BOOL  ( WINAPI * qwglSwapBuffers)(HDC);
-
-BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
-HGLRC ( WINAPI * qwglCreateContext)(HDC);
-HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
-BOOL  ( WINAPI * qwglDeleteContext)(HGLRC);
-HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
-HDC   ( WINAPI * qwglGetCurrentDC)(VOID);
-PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR);
-BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
-BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
-BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
-
-BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
-				      FLOAT, int, LPGLYPHMETRICSFLOAT);
-
-BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
-int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int, CONST COLORREF *);
-int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int, COLORREF *);
-BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
-BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
-
-BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * );
-BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *,
-					    const unsigned char * );
-BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
-
-#else
-#define WINAPI
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-void* g_hGLDLL;
-
-XVisualInfo* (*qglXChooseVisual)(Display *dpy, int screen, int *attribList);
-GLXContext   (*qglXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
-void         (*qglXDestroyContext)(Display *dpy, GLXContext ctx);
-Bool         (*qglXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
-void         (*qglXCopyContext)(Display *dpy, GLXContext src, GLXContext dst, GLuint mask);
-void         (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable );
-GLXPixmap    (*qglXCreateGLXPixmap)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
-void         (*qglXDestroyGLXPixmap)( Display *dpy, GLXPixmap pixmap );
-Bool         (*qglXQueryExtension)( Display *dpy, int *errorb, int *event );
-Bool         (*qglXQueryVersion)( Display *dpy, int *maj, int *min );
-Bool         (*qglXIsDirect)( Display *dpy, GLXContext ctx );
-int          (*qglXGetConfig)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
-GLXContext   (*qglXGetCurrentContext)( void );
-GLXDrawable  (*qglXGetCurrentDrawable)( void );
-void         (*qglXWaitGL)( void );
-void         (*qglXWaitX)( void );
-void         (*qglXUseXFont)( Font font, int first, int count, int list );
-void*        (*qglXGetProcAddressARB) (const GLubyte *procName);
-#endif
-
-void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
-void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
-GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
-void ( APIENTRY * qglArrayElement )(GLint i);
-void ( APIENTRY * qglBegin )(GLenum mode);
-void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
-void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
-void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
-void ( APIENTRY * qglCallList )(GLuint list);
-void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
-void ( APIENTRY * qglClear )(GLbitfield mask);
-void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-void ( APIENTRY * qglClearDepth )(GLclampd depth);
-void ( APIENTRY * qglClearIndex )(GLfloat c);
-void ( APIENTRY * qglClearStencil )(GLint s);
-void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
-void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
-void ( APIENTRY * qglColor3bv )(const GLbyte *v);
-void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
-void ( APIENTRY * qglColor3dv )(const GLdouble *v);
-void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
-void ( APIENTRY * qglColor3fv )(const GLfloat *v);
-void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
-void ( APIENTRY * qglColor3iv )(const GLint *v);
-void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
-void ( APIENTRY * qglColor3sv )(const GLshort *v);
-void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
-void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
-void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
-void ( APIENTRY * qglColor3uiv )(const GLuint *v);
-void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
-void ( APIENTRY * qglColor3usv )(const GLushort *v);
-void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
-void ( APIENTRY * qglColor4bv )(const GLbyte *v);
-void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
-void ( APIENTRY * qglColor4dv )(const GLdouble *v);
-void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void ( APIENTRY * qglColor4fv )(const GLfloat *v);
-void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
-void ( APIENTRY * qglColor4iv )(const GLint *v);
-void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
-void ( APIENTRY * qglColor4sv )(const GLshort *v);
-void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
-void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
-void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
-void ( APIENTRY * qglColor4uiv )(const GLuint *v);
-void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
-void ( APIENTRY * qglColor4usv )(const GLushort *v);
-void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
-void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
-void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
-void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-void ( APIENTRY * qglCullFace )(GLenum mode);
-void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
-void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
-void ( APIENTRY * qglDepthFunc )(GLenum func);
-void ( APIENTRY * qglDepthMask )(GLboolean flag);
-void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
-void ( APIENTRY * qglDisable )(GLenum cap);
-void ( APIENTRY * qglDisableClientState )(GLenum array);
-void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
-void ( APIENTRY * qglDrawBuffer )(GLenum mode);
-void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
-void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
-void ( APIENTRY * qglEnable )(GLenum cap);
-void ( APIENTRY * qglEnableClientState )(GLenum array);
-void ( APIENTRY * qglEnd )(void);
-void ( APIENTRY * qglEndList )(void);
-void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
-void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
-void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
-void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
-void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
-void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
-void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
-void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
-void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
-void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
-void ( APIENTRY * qglEvalPoint1 )(GLint i);
-void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
-void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
-void ( APIENTRY * qglFinish )(void);
-void ( APIENTRY * qglFlush )(void);
-void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
-void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
-void ( APIENTRY * qglFrontFace )(GLenum mode);
-void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-GLuint ( APIENTRY * qglGenLists )(GLsizei range);
-void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
-void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
-void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
-void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
-GLenum ( APIENTRY * qglGetError )(void);
-void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
-void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
-void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
-void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
-void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
-void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
-void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
-void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
-void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
-const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
-void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
-void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
-void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
-void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
-void ( APIENTRY * qglIndexMask )(GLuint mask);
-void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglIndexd )(GLdouble c);
-void ( APIENTRY * qglIndexdv )(const GLdouble *c);
-void ( APIENTRY * qglIndexf )(GLfloat c);
-void ( APIENTRY * qglIndexfv )(const GLfloat *c);
-void ( APIENTRY * qglIndexi )(GLint c);
-void ( APIENTRY * qglIndexiv )(const GLint *c);
-void ( APIENTRY * qglIndexs )(GLshort c);
-void ( APIENTRY * qglIndexsv )(const GLshort *c);
-void ( APIENTRY * qglIndexub )(GLubyte c);
-void ( APIENTRY * qglIndexubv )(const GLubyte *c);
-void ( APIENTRY * qglInitNames )(void);
-void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
-GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
-GLboolean ( APIENTRY * qglIsList )(GLuint list);
-GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
-void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
-void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
-void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
-void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
-void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
-void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
-void ( APIENTRY * qglLineWidth )(GLfloat width);
-void ( APIENTRY * qglListBase )(GLuint base);
-void ( APIENTRY * qglLoadIdentity )(void);
-void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
-void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
-void ( APIENTRY * qglLoadName )(GLuint name);
-void ( APIENTRY * qglLogicOp )(GLenum opcode);
-void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
-void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
-void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
-void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
-void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
-void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
-void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
-void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
-void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
-void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
-void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
-void ( APIENTRY * qglMatrixMode )(GLenum mode);
-void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
-void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
-void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
-void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
-void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
-void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
-void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
-void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
-void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
-void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
-void ( APIENTRY * qglNormal3iv )(const GLint *v);
-void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
-void ( APIENTRY * qglNormal3sv )(const GLshort *v);
-void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-void ( APIENTRY * qglPassThrough )(GLfloat token);
-void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
-void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
-void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
-void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
-void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
-void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
-void ( APIENTRY * qglPointSize )(GLfloat size);
-void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
-void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
-void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
-void ( APIENTRY * qglPopAttrib )(void);
-void ( APIENTRY * qglPopClientAttrib )(void);
-void ( APIENTRY * qglPopMatrix )(void);
-void ( APIENTRY * qglPopName )(void);
-void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
-void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
-void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
-void ( APIENTRY * qglPushMatrix )(void);
-void ( APIENTRY * qglPushName )(GLuint name);
-void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
-void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
-void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
-void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
-void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
-void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
-void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
-void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
-void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
-void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
-void ( APIENTRY * qglReadBuffer )(GLenum mode);
-void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
-void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
-void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
-void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
-void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
-void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
-void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
-void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
-void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
-GLint ( APIENTRY * qglRenderMode )(GLenum mode);
-void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
-void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
-void ( APIENTRY * qglShadeModel )(GLenum mode);
-void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
-void ( APIENTRY * qglStencilMask )(GLuint mask);
-void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
-void ( APIENTRY * qglTexCoord1d )(GLdouble s);
-void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord1f )(GLfloat s);
-void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord1i )(GLint s);
-void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord1s )(GLshort s);
-void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
-void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
-void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
-void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
-void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
-void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
-void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
-void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
-void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
-void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
-void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
-void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
-void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
-void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
-void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
-void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
-void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
-void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
-void ( APIENTRY * qglVertex2iv )(const GLint *v);
-void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
-void ( APIENTRY * qglVertex2sv )(const GLshort *v);
-void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
-void ( APIENTRY * qglVertex3iv )(const GLint *v);
-void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
-void ( APIENTRY * qglVertex3sv )(const GLshort *v);
-void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
-void ( APIENTRY * qglVertex4iv )(const GLint *v);
-void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-void ( APIENTRY * qglVertex4sv )(const GLshort *v);
-void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
-
-void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
-void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
-void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
-void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
-void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
-
-void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
-void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
-void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
-
-// glu stuff
-void (APIENTRY * qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
-int  (APIENTRY * qgluBuild2DMipmaps) (GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum      type, const void  *data);
-// added for plugins
-void (APIENTRY * qgluLookAt)(
-  GLdouble eyex,
-  GLdouble eyey,
-  GLdouble eyez,
-  GLdouble centerx,
-  GLdouble centery,
-  GLdouble centerz,
-  GLdouble upx,
-  GLdouble upy,
-  GLdouble upz);
-const GLubyte* (APIENTRY * qgluErrorString) (GLenum errCode );
-
-/*
-** QGL_Shutdown
-**
-** Unloads the specified DLL then nulls out all the proc pointers.
-*/
-void QGL_Shutdown()
-{
-  Sys_Printf("Shutting down GL ...");
-
-  if (g_hGLDLL)
-  {
-#ifdef _WIN32
-    FreeLibrary(g_hGLDLL);
-#endif
-
-//#if defined (__linux__) || defined (__APPLE__)
-//    dlclose (g_hGLDLL);
-//#endif
-
-    g_hGLDLL = NULL;
-  }
-
-  Sys_Printf("Done.\n");
-
-  qglAccum                     = NULL;
-  qglAlphaFunc                 = NULL;
-  qglAreTexturesResident       = NULL;
-  qglArrayElement              = NULL;
-  qglBegin                     = NULL;
-  qglBindTexture               = NULL;
-  qglBitmap                    = NULL;
-  qglBlendFunc                 = NULL;
-  qglCallList                  = NULL;
-  qglCallLists                 = NULL;
-  qglClear                     = NULL;
-  qglClearAccum                = NULL;
-  qglClearColor                = NULL;
-  qglClearDepth                = NULL;
-  qglClearIndex                = NULL;
-  qglClearStencil              = NULL;
-  qglClipPlane                 = NULL;
-  qglColor3b                   = NULL;
-  qglColor3bv                  = NULL;
-  qglColor3d                   = NULL;
-  qglColor3dv                  = NULL;
-  qglColor3f                   = NULL;
-  qglColor3fv                  = NULL;
-  qglColor3i                   = NULL;
-  qglColor3iv                  = NULL;
-  qglColor3s                   = NULL;
-  qglColor3sv                  = NULL;
-  qglColor3ub                  = NULL;
-  qglColor3ubv                 = NULL;
-  qglColor3ui                  = NULL;
-  qglColor3uiv                 = NULL;
-  qglColor3us                  = NULL;
-  qglColor3usv                 = NULL;
-  qglColor4b                   = NULL;
-  qglColor4bv                  = NULL;
-  qglColor4d                   = NULL;
-  qglColor4dv                  = NULL;
-  qglColor4f                   = NULL;
-  qglColor4fv                  = NULL;
-  qglColor4i                   = NULL;
-  qglColor4iv                  = NULL;
-  qglColor4s                   = NULL;
-  qglColor4sv                  = NULL;
-  qglColor4ub                  = NULL;
-  qglColor4ubv                 = NULL;
-  qglColor4ui                  = NULL;
-  qglColor4uiv                 = NULL;
-  qglColor4us                  = NULL;
-  qglColor4usv                 = NULL;
-  qglColorMask                 = NULL;
-  qglColorMaterial             = NULL;
-  qglColorPointer              = NULL;
-  qglCopyPixels                = NULL;
-  qglCopyTexImage1D            = NULL;
-  qglCopyTexImage2D            = NULL;
-  qglCopyTexSubImage1D         = NULL;
-  qglCopyTexSubImage2D         = NULL;
-  qglCullFace                  = NULL;
-  qglDeleteLists               = NULL;
-  qglDeleteTextures            = NULL;
-  qglDepthFunc                 = NULL;
-  qglDepthMask                 = NULL;
-  qglDepthRange                = NULL;
-  qglDisable                   = NULL;
-  qglDisableClientState        = NULL;
-  qglDrawArrays                = NULL;
-  qglDrawBuffer                = NULL;
-  qglDrawElements              = NULL;
-  qglDrawPixels                = NULL;
-  qglEdgeFlag                  = NULL;
-  qglEdgeFlagPointer           = NULL;
-  qglEdgeFlagv                 = NULL;
-  qglEnable                    = NULL;
-  qglEnableClientState         = NULL;
-  qglEnd                       = NULL;
-  qglEndList                   = NULL;
-  qglEvalCoord1d               = NULL;
-  qglEvalCoord1dv              = NULL;
-  qglEvalCoord1f               = NULL;
-  qglEvalCoord1fv              = NULL;
-  qglEvalCoord2d               = NULL;
-  qglEvalCoord2dv              = NULL;
-  qglEvalCoord2f               = NULL;
-  qglEvalCoord2fv              = NULL;
-  qglEvalMesh1                 = NULL;
-  qglEvalMesh2                 = NULL;
-  qglEvalPoint1                = NULL;
-  qglEvalPoint2                = NULL;
-  qglFeedbackBuffer            = NULL;
-  qglFinish                    = NULL;
-  qglFlush                     = NULL;
-  qglFogf                      = NULL;
-  qglFogfv                     = NULL;
-  qglFogi                      = NULL;
-  qglFogiv                     = NULL;
-  qglFrontFace                 = NULL;
-  qglFrustum                   = NULL;
-  qglGenLists                  = NULL;
-  qglGenTextures               = NULL;
-  qglGetBooleanv               = NULL;
-  qglGetClipPlane              = NULL;
-  qglGetDoublev                = NULL;
-  qglGetError                  = NULL;
-  qglGetFloatv                 = NULL;
-  qglGetIntegerv               = NULL;
-  qglGetLightfv                = NULL;
-  qglGetLightiv                = NULL;
-  qglGetMapdv                  = NULL;
-  qglGetMapfv                  = NULL;
-  qglGetMapiv                  = NULL;
-  qglGetMaterialfv             = NULL;
-  qglGetMaterialiv             = NULL;
-  qglGetPixelMapfv             = NULL;
-  qglGetPixelMapuiv            = NULL;
-  qglGetPixelMapusv            = NULL;
-  qglGetPointerv               = NULL;
-  qglGetPolygonStipple         = NULL;
-  qglGetString                 = NULL;
-  qglGetTexEnvfv               = NULL;
-  qglGetTexEnviv               = NULL;
-  qglGetTexGendv               = NULL;
-  qglGetTexGenfv               = NULL;
-  qglGetTexGeniv               = NULL;
-  qglGetTexImage               = NULL;
-  qglGetTexLevelParameterfv    = NULL;
-  qglGetTexLevelParameteriv    = NULL;
-  qglGetTexParameterfv         = NULL;
-  qglGetTexParameteriv         = NULL;
-  qglHint                      = NULL;
-  qglIndexMask                 = NULL;
-  qglIndexPointer              = NULL;
-  qglIndexd                    = NULL;
-  qglIndexdv                   = NULL;
-  qglIndexf                    = NULL;
-  qglIndexfv                   = NULL;
-  qglIndexi                    = NULL;
-  qglIndexiv                   = NULL;
-  qglIndexs                    = NULL;
-  qglIndexsv                   = NULL;
-  qglIndexub                   = NULL;
-  qglIndexubv                  = NULL;
-  qglInitNames                 = NULL;
-  qglInterleavedArrays         = NULL;
-  qglIsEnabled                 = NULL;
-  qglIsList                    = NULL;
-  qglIsTexture                 = NULL;
-  qglLightModelf               = NULL;
-  qglLightModelfv              = NULL;
-  qglLightModeli               = NULL;
-  qglLightModeliv              = NULL;
-  qglLightf                    = NULL;
-  qglLightfv                   = NULL;
-  qglLighti                    = NULL;
-  qglLightiv                   = NULL;
-  qglLineStipple               = NULL;
-  qglLineWidth                 = NULL;
-  qglListBase                  = NULL;
-  qglLoadIdentity              = NULL;
-  qglLoadMatrixd               = NULL;
-  qglLoadMatrixf               = NULL;
-  qglLoadName                  = NULL;
-  qglLogicOp                   = NULL;
-  qglMap1d                     = NULL;
-  qglMap1f                     = NULL;
-  qglMap2d                     = NULL;
-  qglMap2f                     = NULL;
-  qglMapGrid1d                 = NULL;
-  qglMapGrid1f                 = NULL;
-  qglMapGrid2d                 = NULL;
-  qglMapGrid2f                 = NULL;
-  qglMaterialf                 = NULL;
-  qglMaterialfv                = NULL;
-  qglMateriali                 = NULL;
-  qglMaterialiv                = NULL;
-  qglMatrixMode                = NULL;
-  qglMultMatrixd               = NULL;
-  qglMultMatrixf               = NULL;
-  qglNewList                   = NULL;
-  qglNormal3b                  = NULL;
-  qglNormal3bv                 = NULL;
-  qglNormal3d                  = NULL;
-  qglNormal3dv                 = NULL;
-  qglNormal3f                  = NULL;
-  qglNormal3fv                 = NULL;
-  qglNormal3i                  = NULL;
-  qglNormal3iv                 = NULL;
-  qglNormal3s                  = NULL;
-  qglNormal3sv                 = NULL;
-  qglNormalPointer             = NULL;
-  qglOrtho                     = NULL;
-  qglPassThrough               = NULL;
-  qglPixelMapfv                = NULL;
-  qglPixelMapuiv               = NULL;
-  qglPixelMapusv               = NULL;
-  qglPixelStoref               = NULL;
-  qglPixelStorei               = NULL;
-  qglPixelTransferf            = NULL;
-  qglPixelTransferi            = NULL;
-  qglPixelZoom                 = NULL;
-  qglPointSize                 = NULL;
-  qglPolygonMode               = NULL;
-  qglPolygonOffset             = NULL;
-  qglPolygonStipple            = NULL;
-  qglPopAttrib                 = NULL;
-  qglPopClientAttrib           = NULL;
-  qglPopMatrix                 = NULL;
-  qglPopName                   = NULL;
-  qglPrioritizeTextures        = NULL;
-  qglPushAttrib                = NULL;
-  qglPushClientAttrib          = NULL;
-  qglPushMatrix                = NULL;
-  qglPushName                  = NULL;
-  qglRasterPos2d               = NULL;
-  qglRasterPos2dv              = NULL;
-  qglRasterPos2f               = NULL;
-  qglRasterPos2fv              = NULL;
-  qglRasterPos2i               = NULL;
-  qglRasterPos2iv              = NULL;
-  qglRasterPos2s               = NULL;
-  qglRasterPos2sv              = NULL;
-  qglRasterPos3d               = NULL;
-  qglRasterPos3dv              = NULL;
-  qglRasterPos3f               = NULL;
-  qglRasterPos3fv              = NULL;
-  qglRasterPos3i               = NULL;
-  qglRasterPos3iv              = NULL;
-  qglRasterPos3s               = NULL;
-  qglRasterPos3sv              = NULL;
-  qglRasterPos4d               = NULL;
-  qglRasterPos4dv              = NULL;
-  qglRasterPos4f               = NULL;
-  qglRasterPos4fv              = NULL;
-  qglRasterPos4i               = NULL;
-  qglRasterPos4iv              = NULL;
-  qglRasterPos4s               = NULL;
-  qglRasterPos4sv              = NULL;
-  qglReadBuffer                = NULL;
-  qglReadPixels                = NULL;
-  qglRectd                     = NULL;
-  qglRectdv                    = NULL;
-  qglRectf                     = NULL;
-  qglRectfv                    = NULL;
-  qglRecti                     = NULL;
-  qglRectiv                    = NULL;
-  qglRects                     = NULL;
-  qglRectsv                    = NULL;
-  qglRenderMode                = NULL;
-  qglRotated                   = NULL;
-  qglRotatef                   = NULL;
-  qglScaled                    = NULL;
-  qglScalef                    = NULL;
-  qglScissor                   = NULL;
-  qglSelectBuffer              = NULL;
-  qglShadeModel                = NULL;
-  qglStencilFunc               = NULL;
-  qglStencilMask               = NULL;
-  qglStencilOp                 = NULL;
-  qglTexCoord1d                = NULL;
-  qglTexCoord1dv               = NULL;
-  qglTexCoord1f                = NULL;
-  qglTexCoord1fv               = NULL;
-  qglTexCoord1i                = NULL;
-  qglTexCoord1iv               = NULL;
-  qglTexCoord1s                = NULL;
-  qglTexCoord1sv               = NULL;
-  qglTexCoord2d                = NULL;
-  qglTexCoord2dv               = NULL;
-  qglTexCoord2f                = NULL;
-  qglTexCoord2fv               = NULL;
-  qglTexCoord2i                = NULL;
-  qglTexCoord2iv               = NULL;
-  qglTexCoord2s                = NULL;
-  qglTexCoord2sv               = NULL;
-  qglTexCoord3d                = NULL;
-  qglTexCoord3dv               = NULL;
-  qglTexCoord3f                = NULL;
-  qglTexCoord3fv               = NULL;
-  qglTexCoord3i                = NULL;
-  qglTexCoord3iv               = NULL;
-  qglTexCoord3s                = NULL;
-  qglTexCoord3sv               = NULL;
-  qglTexCoord4d                = NULL;
-  qglTexCoord4dv               = NULL;
-  qglTexCoord4f                = NULL;
-  qglTexCoord4fv               = NULL;
-  qglTexCoord4i                = NULL;
-  qglTexCoord4iv               = NULL;
-  qglTexCoord4s                = NULL;
-  qglTexCoord4sv               = NULL;
-  qglTexCoordPointer           = NULL;
-  qglTexEnvf                   = NULL;
-  qglTexEnvfv                  = NULL;
-  qglTexEnvi                   = NULL;
-  qglTexEnviv                  = NULL;
-  qglTexGend                   = NULL;
-  qglTexGendv                  = NULL;
-  qglTexGenf                   = NULL;
-  qglTexGenfv                  = NULL;
-  qglTexGeni                   = NULL;
-  qglTexGeniv                  = NULL;
-  qglTexImage1D                = NULL;
-  qglTexImage2D                = NULL;
-  qglTexParameterf             = NULL;
-  qglTexParameterfv            = NULL;
-  qglTexParameteri             = NULL;
-  qglTexParameteriv            = NULL;
-  qglTexSubImage1D             = NULL;
-  qglTexSubImage2D             = NULL;
-  qglTranslated                = NULL;
-  qglTranslatef                = NULL;
-  qglVertex2d                  = NULL;
-  qglVertex2dv                 = NULL;
-  qglVertex2f                  = NULL;
-  qglVertex2fv                 = NULL;
-  qglVertex2i                  = NULL;
-  qglVertex2iv                 = NULL;
-  qglVertex2s                  = NULL;
-  qglVertex2sv                 = NULL;
-  qglVertex3d                  = NULL;
-  qglVertex3dv                 = NULL;
-  qglVertex3f                  = NULL;
-  qglVertex3fv                 = NULL;
-  qglVertex3i                  = NULL;
-  qglVertex3iv                 = NULL;
-  qglVertex3s                  = NULL;
-  qglVertex3sv                 = NULL;
-  qglVertex4d                  = NULL;
-  qglVertex4dv                 = NULL;
-  qglVertex4f                  = NULL;
-  qglVertex4fv                 = NULL;
-  qglVertex4i                  = NULL;
-  qglVertex4iv                 = NULL;
-  qglVertex4s                  = NULL;
-  qglVertex4sv                 = NULL;
-  qglVertexPointer             = NULL;
-  qglViewport                  = NULL;
-
-  qglActiveTextureARB = NULL;
-  qglClientActiveTextureARB = NULL;
-  qglMultiTexCoord1dARB = NULL;
-  qglMultiTexCoord1dvARB = NULL;
-  qglMultiTexCoord1fARB = NULL;
-  qglMultiTexCoord1fvARB = NULL;
-  qglMultiTexCoord1iARB = NULL;
-  qglMultiTexCoord1ivARB = NULL;
-  qglMultiTexCoord1sARB = NULL;
-  qglMultiTexCoord1svARB = NULL;
-  qglMultiTexCoord2dARB = NULL;
-  qglMultiTexCoord2dvARB = NULL;
-  qglMultiTexCoord2fARB = NULL;
-  qglMultiTexCoord2fvARB = NULL;
-  qglMultiTexCoord2iARB = NULL;
-  qglMultiTexCoord2ivARB = NULL;
-  qglMultiTexCoord2sARB = NULL;
-  qglMultiTexCoord2svARB = NULL;
-  qglMultiTexCoord3dARB = NULL;
-  qglMultiTexCoord3dvARB = NULL;
-  qglMultiTexCoord3fARB = NULL;
-  qglMultiTexCoord3fvARB = NULL;
-  qglMultiTexCoord3iARB = NULL;
-  qglMultiTexCoord3ivARB = NULL;
-  qglMultiTexCoord3sARB = NULL;
-  qglMultiTexCoord3svARB = NULL;
-  qglMultiTexCoord4dARB = NULL;
-  qglMultiTexCoord4dvARB = NULL;
-  qglMultiTexCoord4fARB = NULL;
-  qglMultiTexCoord4fvARB = NULL;
-  qglMultiTexCoord4iARB = NULL;
-  qglMultiTexCoord4ivARB = NULL;
-  qglMultiTexCoord4sARB = NULL;
-  qglMultiTexCoord4svARB = NULL;
-
-#ifdef _WIN32
-  qwglCopyContext              = NULL;
-  qwglCreateContext            = NULL;
-  qwglCreateLayerContext       = NULL;
-  qwglDeleteContext            = NULL;
-  qwglDescribeLayerPlane       = NULL;
-  qwglGetCurrentContext        = NULL;
-  qwglGetCurrentDC             = NULL;
-  qwglGetLayerPaletteEntries   = NULL;
-  qwglGetProcAddress           = NULL;
-  qwglMakeCurrent              = NULL;
-  qwglRealizeLayerPalette      = NULL;
-  qwglSetLayerPaletteEntries   = NULL;
-  qwglShareLists               = NULL;
-  qwglSwapLayerBuffers         = NULL;
-  qwglUseFontBitmaps           = NULL;
-  qwglUseFontOutlines          = NULL;
-
-  qwglChoosePixelFormat        = NULL;
-  qwglDescribePixelFormat      = NULL;
-  qwglGetPixelFormat           = NULL;
-  qwglSetPixelFormat           = NULL;
-  qwglSwapBuffers              = NULL;
-
-  qwglSwapIntervalEXT          = NULL;
-
-  qwglGetDeviceGammaRampEXT    = NULL;
-  qwglSetDeviceGammaRampEXT    = NULL;
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-  qglXChooseVisual             = NULL;
-  qglXCreateContext            = NULL;
-  qglXDestroyContext           = NULL;
-  qglXMakeCurrent              = NULL;
-  qglXCopyContext              = NULL;
-  qglXSwapBuffers              = NULL;
-  qglXCreateGLXPixmap          = NULL;
-  qglXDestroyGLXPixmap         = NULL;
-  qglXQueryExtension           = NULL;
-  qglXQueryVersion             = NULL;
-  qglXIsDirect                 = NULL;
-  qglXGetConfig                = NULL;
-  qglXGetCurrentContext        = NULL;
-  qglXGetCurrentDrawable       = NULL;
-  qglXWaitGL                   = NULL;
-  qglXWaitX                    = NULL;
-  qglXUseXFont                 = NULL;
-  qglXGetProcAddressARB        = NULL;
-#endif
-
-  qgluPerspective = NULL;
-  qgluBuild2DMipmaps = NULL;
-  qgluErrorString = NULL;
-  qgluLookAt = NULL;
-}
-
-/*
-** QGL_Init
-**
-** This is responsible for binding our qgl function pointers to 
-** the appropriate GL stuff.  In Windows this means doing a 
-** LoadLibrary and a bunch of calls to GetProcAddress.  On other
-** operating systems we need to do the right thing, whatever that
-** might be.
-** 
-*/
-static int init_error;
-
-//static void* safe_dlsym (void *handle, char *symbol)
-//{
-//#ifdef _WIN32
-//  return GetProcAddress (handle, symbol);
-//#endif
-
-//#if defined (__linux__) || defined (__APPLE__)
-//  void* ret = dlsym (handle, symbol);
-//  char *err = dlerror();
-//  if (err)
-//{
-//    init_error = 1;
-//    printf ("Error loading OpenGL libraries: %s %s\n", err, symbol);
-//  }
-//  return ret;
-//#endif
-//}
-
-#include <math.h>
-#include <stdlib.h>
-#ifdef _WIN32
-#define M_PI 3.14159
-#endif
-
-void WINAPI gluLookAt2 (GLdouble ex, GLdouble ey, GLdouble ez, GLdouble cx, GLdouble cy, GLdouble cz,
-		 GLdouble ux, GLdouble uy, GLdouble uz)
-{
-   GLdouble x[3], y[3], z[3] = { ex-cx, ey-cy, ez-cz };
-   GLdouble inv;
-
-   inv = sqrt (z[0]*z[0] + z[1]*z[1] + z[2]*z[2]);
-   if (inv)
-   {
-     inv = 1.0/inv;
-     z[0] *= inv;
-     z[1] *= inv;
-     z[2] *= inv;
-   }
-
-   x[0] =  uy*z[2] - uz*z[1];
-   x[1] = -ux*z[2] + uz*z[0];
-   x[2] =  ux*z[1] - uy*z[0];
-
-   y[0] =  z[1]*x[2] - z[2]*x[1];
-   y[1] = -z[0]*x[2] + z[2]*x[0];
-   y[2] =  z[0]*x[1] - z[1]*x[0];
-
-   inv = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
-   if (inv)
-   {
-     x[0] *= inv;
-     x[1] *= inv;
-     x[2] *= inv;
-   }
-
-   inv = sqrt(y[0]*y[0] + y[1]*y[1] + y[2]*y[2]);
-   if (inv)
-   {
-      y[0] *= inv;
-      y[1] *= inv;
-      y[2] *= inv;
-   }
-
-   {
-   GLdouble m[16] = { x[0], y[0], z[0], 0, x[1], y[1], z[1], 0, x[2], y[2], z[2], 0, 0, 0, 0, 1 };
-   qglMultMatrixd(m);
-   qglTranslated(-ex, -ey, -ez);
-   }
-}
-
-void WINAPI gluPerspective2 (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
-{
-   GLdouble y = zNear * tan (fovy * M_PI / 360.0);
-   qglFrustum (-y*aspect, y*aspect, -y, y, zNear, zFar);
-}
-
-static void* WINAPI ResizeImage (GLubyte* old_image, int srcw, int srch, int destw, int desth)
-{
-  int i, j;
-  float sx, sy;
-
-  GLubyte* new_image = malloc (destw*desth*4*sizeof(GLubyte));
-  if (new_image == NULL)
-    return NULL;
-
-  if (destw > 1)
-    sx = (GLfloat) (srcw-1) / (GLfloat) (destw-1);
-  else
-    sx = (GLfloat) (srcw-1);
-  if (desth > 1)
-    sy = (GLfloat) (srch-1) / (GLfloat) (desth-1);
-  else
-    sy = (GLfloat) (srch-1);
-
-  for (i = 0; i < desth; i++)
-  {
-    GLint ii = (GLint)(i * sy);
-    for (j = 0; j < destw; j++)
-    {
-      GLint jj = (GLint)(j * sx);
-      GLubyte *src = old_image + (ii * srcw + jj) * 4;
-      GLubyte *dst = new_image + (i * destw + j) * 4;
-
-      *dst++ = *src++;
-      *dst++ = *src++;
-      *dst++ = *src++;
-      *dst++ = *src++;
-    }
-  }
-
-  return new_image;
-}
-
-#define CEILING(A, B)  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
-
-// NOTE: only supports RGBA, UNSIGNED_BYTE images.
-GLint WINAPI gluBuild2DMipmaps2 (GLenum target, GLint components, GLsizei width, GLsizei height, GLenum format,
-			  GLenum type, const void *data)
-{
-  GLint w, h, level, maxsize, sizein = 1;
-  GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
-  GLint packrowlength, packalignment, packskiprows, packskippixels;
-  GLint rowstride, rowlen;
-  GLuint i, j, k, pow2;
-  GLubyte *image, *tmp;
-
-  if (width < 1 || height < 1)
-    return GLU_INVALID_VALUE;
-
-  qglGetIntegerv (GL_UNPACK_ROW_LENGTH, &unpackrowlength);
-  qglGetIntegerv (GL_UNPACK_ALIGNMENT, &unpackalignment);
-  qglGetIntegerv (GL_UNPACK_SKIP_ROWS, &unpackskiprows);
-  qglGetIntegerv (GL_UNPACK_SKIP_PIXELS, &unpackskippixels);
-  qglGetIntegerv (GL_PACK_ROW_LENGTH, &packrowlength);
-  qglGetIntegerv (GL_PACK_ALIGNMENT, &packalignment);
-  qglGetIntegerv (GL_PACK_SKIP_ROWS, &packskiprows);
-  qglGetIntegerv (GL_PACK_SKIP_PIXELS, &packskippixels);
-  qglGetIntegerv (GL_MAX_TEXTURE_SIZE, &maxsize);
-
-  for (pow2 = 1; pow2 < width; pow2 = pow2 << 1);
-  w = (pow2 == width) ? width : (pow2 << 1);
- 
-  for (pow2 = 1; pow2 < height; pow2 = pow2 << 1);
-  h = (pow2 == height) ? height : (pow2 << 1);
-
-  if (w > maxsize) w = maxsize;
-  if (h > maxsize) h = maxsize;
-
-  // Build RGBA packed image
-  image = malloc (width*height*4);
-  if (image == NULL)
-    return GLU_OUT_OF_MEMORY;
-
-  if ((format != GL_RGBA) || (type != GL_UNSIGNED_BYTE))
-    return GLU_INVALID_ENUM;
-
-  rowlen = (unpackrowlength > 0) ? unpackrowlength : width;
-
-  if (sizein >= unpackalignment)
-    rowstride = components * rowlen;
-  else
-    rowstride = unpackalignment/sizein * CEILING (components * rowlen * sizein, unpackalignment);
-
-  k = 0;
-  for (i = 0; i < height; i++)
-  {
-    GLubyte *ubptr = (GLubyte*)data + i * rowstride
-      + unpackskiprows * rowstride + unpackskippixels * components;
-
-    for (j = 0; j < width*components; j++)
-      image[k++] = *ubptr++;
-  }
-
-  if (w != width || h != height)
-  {
-    tmp = ResizeImage (image, width, height, w, h);
-    free (image);
-    image = tmp;
-
-    if (image == NULL)
-      return GLU_OUT_OF_MEMORY;
-  }
-
-  qglPixelStorei (GL_PACK_ROW_LENGTH, 0);
-  qglPixelStorei (GL_PACK_ALIGNMENT, 1);
-  qglPixelStorei (GL_PACK_SKIP_ROWS, 0);
-  qglPixelStorei (GL_PACK_SKIP_PIXELS, 0);
-  qglPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
-  qglPixelStorei (GL_UNPACK_ALIGNMENT, 1);
-  qglPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
-  qglPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
-
-  qglTexImage2D (target, 0, components, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
-
-  for (level = 1; ((w != 1) || (h != 1)); level++)
-  {
-    GLubyte *out, *in;
-    int row;
-
-    row = w * 4;
-    if (w != 1) w >>= 1;
-    if (h != 1) h >>= 1;
-    in = out = image;
-
-    for (i = 0; i < h; i++, in+=row)
-      for (j = 0; j < w; j++, out+=4, in+=8)
-      {
-	out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
-	out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
-	out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
-	out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
-      }
-
-    qglTexImage2D (target, level, components, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
-  }
-
-  free (image);
-  qglPixelStorei (GL_UNPACK_ROW_LENGTH, unpackrowlength);
-  qglPixelStorei (GL_UNPACK_ALIGNMENT, unpackalignment);
-  qglPixelStorei (GL_UNPACK_SKIP_ROWS, unpackskiprows);
-  qglPixelStorei (GL_UNPACK_SKIP_PIXELS, unpackskippixels);
-  qglPixelStorei (GL_PACK_ROW_LENGTH, packrowlength);
-  qglPixelStorei (GL_PACK_ALIGNMENT, packalignment);
-  qglPixelStorei (GL_PACK_SKIP_ROWS, packskiprows);
-  qglPixelStorei (GL_PACK_SKIP_PIXELS, packskippixels);
-
-  return 0;
-}
-
-typedef struct glu_error_struct
-{
-    int     errnum;
-    const char *errstr;
-} GLU_ERROR_STRUCT;
-
-GLU_ERROR_STRUCT glu_errlist[] = {
-  {GL_NO_ERROR, "GL_NO_ERROR - no error"},
-  {GL_INVALID_ENUM, "GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument."},
-  {GL_INVALID_VALUE, "GL_INVALID_VALUE - A numeric argument is out of range."},
-  {GL_INVALID_OPERATION, "GL_INVALID_OPERATION - The specified operation is not allowed in the current state."},
-  {GL_STACK_OVERFLOW, "GL_STACK_OVERFLOW - Function would cause a stack overflow."},
-  {GL_STACK_UNDERFLOW, "GL_STACK_UNDERFLOW - Function would cause a stack underflow."},
-  {GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY - There is not enough memory left to execute the function."},
-  {-1, NULL}
-};
-
-const GLubyte* WINAPI gluErrorString(GLenum errCode )
-{
-  int search = 0;
-  for (search = 0; glu_errlist[search].errstr; search++)
-  {
-    if (errCode == glu_errlist[search].errnum)
-      return (const char *)glu_errlist[search].errstr;
-  } //end for
-  return "Unknown error";
-}
-
-int QGL_Init(const char *dllname, const char* gluname)
-{
-#ifdef _WIN32
-  g_hGLDLL = LoadLibrary(dllname); 
-#endif
-
-#if defined (__linux__)
-  char* err;
-
-  g_hGLDLL = dlopen(dllname, RTLD_LAZY|RTLD_GLOBAL);
-  err = dlerror();
-  if (err)
-    printf ("Error loading GL lib:\n%s\n", err);
-#endif
-  init_error = 0;
-
-#ifndef __APPLE__
-  if (g_hGLDLL == NULL)
-    return 0;
-#endif
-
-  Sys_Printf("Loading GL library: %s ...", dllname);
-
-  qgluPerspective              = &gluPerspective2;
-  qgluBuild2DMipmaps           = &gluBuild2DMipmaps2;
-  qgluLookAt                   = &gluLookAt2;
-  qgluErrorString              = &gluErrorString;
-
-  qglAccum                     = glAccum;
-  qglAlphaFunc                 = glAlphaFunc;
-  qglAreTexturesResident       = glAreTexturesResident;
-  qglArrayElement              = glArrayElement;
-  qglBegin                     = glBegin;
-  qglBindTexture               = glBindTexture;
-  qglBitmap                    = glBitmap;
-  qglBlendFunc                 = glBlendFunc;
-  qglCallList                  = glCallList;
-  qglCallLists                 = glCallLists;
-  qglClear                     = glClear;
-  qglClearAccum                = glClearAccum;
-  qglClearColor                = glClearColor;
-  qglClearDepth                = glClearDepth;
-  qglClearIndex                = glClearIndex;
-  qglClearStencil              = glClearStencil;
-  qglClipPlane                 = glClipPlane;
-  qglColor3b                   = glColor3b;
-  qglColor3bv                  = glColor3bv;
-  qglColor3d                   = glColor3d;
-  qglColor3dv                  = glColor3dv;
-  qglColor3f                   = glColor3f;
-  qglColor3fv                  = glColor3fv;
-  qglColor3i                   = glColor3i;
-  qglColor3iv                  = glColor3iv;
-  qglColor3s                   = glColor3s;
-  qglColor3sv                  = glColor3sv;
-  qglColor3ub                  = glColor3ub;
-  qglColor3ubv                 = glColor3ubv;
-  qglColor3ui                  = glColor3ui;
-  qglColor3uiv                 = glColor3uiv;
-  qglColor3us                  = glColor3us;
-  qglColor3usv                 = glColor3usv;
-  qglColor4b                   = glColor4b;
-  qglColor4bv                  = glColor4bv;
-  qglColor4d                   = glColor4d;
-  qglColor4dv                  = glColor4dv;
-  qglColor4f                   = glColor4f;
-  qglColor4fv                  = glColor4fv;
-  qglColor4i                   = glColor4i;
-  qglColor4iv                  = glColor4iv;
-  qglColor4s                   = glColor4s;
-  qglColor4sv                  = glColor4sv;
-  qglColor4ub                  = glColor4ub;
-  qglColor4ubv                 = glColor4ubv;
-  qglColor4ui                  = glColor4ui;
-  qglColor4uiv                 = glColor4uiv;
-  qglColor4us                  = glColor4us;
-  qglColor4usv                 = glColor4usv;
-  qglColorMask                 = glColorMask;
-  qglColorMaterial             = glColorMaterial;
-  qglColorPointer              = glColorPointer;
-  qglCopyPixels                = glCopyPixels;
-  qglCopyTexImage1D            = glCopyTexImage1D;
-  qglCopyTexImage2D            = glCopyTexImage2D;
-  qglCopyTexSubImage1D         = glCopyTexSubImage1D;
-  qglCopyTexSubImage2D         = glCopyTexSubImage2D;
-  qglCullFace                  = glCullFace;
-  qglDeleteLists               = glDeleteLists;
-  qglDeleteTextures            = glDeleteTextures;
-  qglDepthFunc                 = glDepthFunc;
-  qglDepthMask                 = glDepthMask;
-  qglDepthRange                = glDepthRange;
-  qglDisable                   = glDisable;
-  qglDisableClientState        = glDisableClientState;
-  qglDrawArrays                = glDrawArrays;
-  qglDrawBuffer                = glDrawBuffer;
-  qglDrawElements              = glDrawElements;
-  qglDrawPixels                = glDrawPixels;
-  qglEdgeFlag                  = glEdgeFlag;
-  qglEdgeFlagPointer           = glEdgeFlagPointer;
-  qglEdgeFlagv                 = glEdgeFlagv;
-  qglEnable                    = glEnable;
-  qglEnableClientState         = glEnableClientState;
-  qglEnd                       = glEnd;
-  qglEndList                   = glEndList;
-  qglEvalCoord1d	       = glEvalCoord1d;
-  qglEvalCoord1dv              = glEvalCoord1dv;
-  qglEvalCoord1f               = glEvalCoord1f;
-  qglEvalCoord1fv              = glEvalCoord1fv;
-  qglEvalCoord2d               = glEvalCoord2d;
-  qglEvalCoord2dv              = glEvalCoord2dv;
-  qglEvalCoord2f               = glEvalCoord2f;
-  qglEvalCoord2fv              = glEvalCoord2fv;
-  qglEvalMesh1                 = glEvalMesh1;
-  qglEvalMesh2                 = glEvalMesh2;
-  qglEvalPoint1                = glEvalPoint1;
-  qglEvalPoint2                = glEvalPoint2;
-  qglFeedbackBuffer            = glFeedbackBuffer;
-  qglFinish                    = glFinish;
-  qglFlush                     = glFlush;
-  qglFogf                      = glFogf;
-  qglFogfv                     = glFogfv;
-  qglFogi                      = glFogi;
-  qglFogiv                     = glFogiv;
-  qglFrontFace                 = glFrontFace;
-  qglFrustum                   = glFrustum;
-  qglGenLists                  = glGenLists;
-  qglGenTextures               = glGenTextures;
-  qglGetBooleanv               = glGetBooleanv;
-  qglGetClipPlane              = glGetClipPlane;
-  qglGetDoublev                = glGetDoublev;
-  qglGetError                  = glGetError;
-  qglGetFloatv                 = glGetFloatv;
-  qglGetIntegerv               = glGetIntegerv;
-  qglGetLightfv                = glGetLightfv;
-  qglGetLightiv                = glGetLightiv;
-  qglGetMapdv                  = glGetMapdv;
-  qglGetMapfv                  = glGetMapfv;
-  qglGetMapiv                  = glGetMapiv;
-  qglGetMaterialfv             = glGetMaterialfv;
-  qglGetMaterialiv             = glGetMaterialiv;
-  qglGetPixelMapfv             = glGetPixelMapfv;
-  qglGetPixelMapuiv            = glGetPixelMapuiv;
-  qglGetPixelMapusv            = glGetPixelMapusv;
-  qglGetPointerv               = glGetPointerv;
-  qglGetPolygonStipple         = glGetPolygonStipple;
-  qglGetString                 = glGetString;
-  qglGetTexEnvfv               = glGetTexEnvfv;
-  qglGetTexEnviv               = glGetTexEnviv;
-  qglGetTexGendv               = glGetTexGendv;
-  qglGetTexGenfv               = glGetTexGenfv;
-  qglGetTexGeniv               = glGetTexGeniv;
-  qglGetTexImage               = glGetTexImage;
-  qglGetTexLevelParameterfv    = glGetTexLevelParameterfv;
-  qglGetTexLevelParameteriv    = glGetTexLevelParameteriv;
-  qglGetTexParameterfv         = glGetTexParameterfv;
-  qglGetTexParameteriv         = glGetTexParameteriv;
-  qglHint                      = glHint;
-  qglIndexMask                 = glIndexMask;
-  qglIndexPointer              = glIndexPointer;
-  qglIndexd                    = glIndexd;
-  qglIndexdv                   = glIndexdv;
-  qglIndexf                    = glIndexf;
-  qglIndexfv                   = glIndexfv;
-  qglIndexi                    = glIndexi;
-  qglIndexiv                   = glIndexiv;
-  qglIndexs                    = glIndexs;
-  qglIndexsv                   = glIndexsv;
-  qglIndexub                   = glIndexub;
-  qglIndexubv                  = glIndexubv;
-  qglInitNames                 = glInitNames;
-  qglInterleavedArrays         = glInterleavedArrays;
-  qglIsEnabled                 = glIsEnabled;
-  qglIsList                    = glIsList;
-  qglIsTexture                 = glIsTexture;
-  qglLightModelf               = glLightModelf;
-  qglLightModelfv              = glLightModelfv;
-  qglLightModeli               = glLightModeli;
-  qglLightModeliv              = glLightModeliv;
-  qglLightf                    = glLightf;
-  qglLightfv                   = glLightfv;
-  qglLighti                    = glLighti;
-  qglLightiv                   = glLightiv;
-  qglLineStipple               = glLineStipple;
-  qglLineWidth                 = glLineWidth;
-  qglListBase                  = glListBase;
-  qglLoadIdentity              = glLoadIdentity;
-  qglLoadMatrixd               = glLoadMatrixd;
-  qglLoadMatrixf               = glLoadMatrixf;
-  qglLoadName                  = glLoadName;
-  qglLogicOp                   = glLogicOp;
-  qglMap1d                     = glMap1d;
-  qglMap1f                     = glMap1f;
-  qglMap2d                     = glMap2d;
-  qglMap2f                     = glMap2f;
-  qglMapGrid1d                 = glMapGrid1d;
-  qglMapGrid1f                 = glMapGrid1f;
-  qglMapGrid2d                 = glMapGrid2d;
-  qglMapGrid2f                 = glMapGrid2f;
-  qglMaterialf                 = glMaterialf;
-  qglMaterialfv                = glMaterialfv;
-  qglMateriali                 = glMateriali;
-  qglMaterialiv                = glMaterialiv;
-  qglMatrixMode                = glMatrixMode;
-  qglMultMatrixd               = glMultMatrixd;
-  qglMultMatrixf               = glMultMatrixf;
-  qglNewList                   = glNewList;
-  qglNormal3b                  = glNormal3b;
-  qglNormal3bv                 = glNormal3bv;
-  qglNormal3d                  = glNormal3d;
-  qglNormal3dv                 = glNormal3dv;
-  qglNormal3f                  = glNormal3f;
-  qglNormal3fv                 = glNormal3fv;
-  qglNormal3i                  = glNormal3i;
-  qglNormal3iv                 = glNormal3iv;
-  qglNormal3s                  = glNormal3s;
-  qglNormal3sv                 = glNormal3sv;
-  qglNormalPointer             = glNormalPointer;
-  qglOrtho                     = glOrtho;
-  qglPassThrough               = glPassThrough;
-  qglPixelMapfv                = glPixelMapfv;
-  qglPixelMapuiv               = glPixelMapuiv;
-  qglPixelMapusv               = glPixelMapusv;
-  qglPixelStoref               = glPixelStoref;
-  qglPixelStorei               = glPixelStorei;
-  qglPixelTransferf            = glPixelTransferf;
-  qglPixelTransferi            = glPixelTransferi;
-  qglPixelZoom                 = glPixelZoom;
-  qglPointSize                 = glPointSize;
-  qglPolygonMode               = glPolygonMode;
-  qglPolygonOffset             = glPolygonOffset;
-  qglPolygonStipple            = glPolygonStipple;
-  qglPopAttrib                 = glPopAttrib;
-  qglPopClientAttrib           = glPopClientAttrib;
-  qglPopMatrix                 = glPopMatrix;
-  qglPopName                   = glPopName;
-  qglPrioritizeTextures        = glPrioritizeTextures;
-  qglPushAttrib                = glPushAttrib;
-  qglPushClientAttrib          = glPushClientAttrib;
-  qglPushMatrix                = glPushMatrix;
-  qglPushName                  = glPushName;
-  qglRasterPos2d               = glRasterPos2d;
-  qglRasterPos2dv              = glRasterPos2dv;
-  qglRasterPos2f               = glRasterPos2f;
-  qglRasterPos2fv              = glRasterPos2fv;
-  qglRasterPos2i               = glRasterPos2i;
-  qglRasterPos2iv              = glRasterPos2iv;
-  qglRasterPos2s               = glRasterPos2s;
-  qglRasterPos2sv              = glRasterPos2sv;
-  qglRasterPos3d               = glRasterPos3d;
-  qglRasterPos3dv              = glRasterPos3dv;
-  qglRasterPos3f               = glRasterPos3f;
-  qglRasterPos3fv              = glRasterPos3fv;
-  qglRasterPos3i               = glRasterPos3i;
-  qglRasterPos3iv              = glRasterPos3iv;
-  qglRasterPos3s               = glRasterPos3s;
-  qglRasterPos3sv              = glRasterPos3sv;
-  qglRasterPos4d               = glRasterPos4d;
-  qglRasterPos4dv              = glRasterPos4dv;
-  qglRasterPos4f               = glRasterPos4f;
-  qglRasterPos4fv              = glRasterPos4fv;
-  qglRasterPos4i               = glRasterPos4i;
-  qglRasterPos4iv              = glRasterPos4iv;
-  qglRasterPos4s               = glRasterPos4s;
-  qglRasterPos4sv              = glRasterPos4sv;
-  qglReadBuffer                = glReadBuffer;
-  qglReadPixels                = glReadPixels;
-  qglRectd                     = glRectd;
-  qglRectdv                    = glRectdv;
-  qglRectf                     = glRectf;
-  qglRectfv                    = glRectfv;
-  qglRecti                     = glRecti;
-  qglRectiv                    = glRectiv;
-  qglRects                     = glRects;
-  qglRectsv                    = glRectsv;
-  qglRenderMode                = glRenderMode;
-  qglRotated                   = glRotated;
-  qglRotatef                   = glRotatef;
-  qglScaled                    = glScaled;
-  qglScalef                    = glScalef;
-  qglScissor                   = glScissor;
-  qglSelectBuffer              = glSelectBuffer;
-  qglShadeModel                = glShadeModel;
-  qglStencilFunc               = glStencilFunc;
-  qglStencilMask               = glStencilMask;
-  qglStencilOp                 = glStencilOp;
-  qglTexCoord1d                = glTexCoord1d;
-  qglTexCoord1dv               = glTexCoord1dv;
-  qglTexCoord1f                = glTexCoord1f;
-  qglTexCoord1fv               = glTexCoord1fv;
-  qglTexCoord1i                = glTexCoord1i;
-  qglTexCoord1iv               = glTexCoord1iv;
-  qglTexCoord1s                = glTexCoord1s;
-  qglTexCoord1sv               = glTexCoord1sv;
-  qglTexCoord2d                = glTexCoord2d;
-  qglTexCoord2dv               = glTexCoord2dv;
-  qglTexCoord2f                = glTexCoord2f;
-  qglTexCoord2fv               = glTexCoord2fv;
-  qglTexCoord2i                = glTexCoord2i;
-  qglTexCoord2iv               = glTexCoord2iv;
-  qglTexCoord2s                = glTexCoord2s;
-  qglTexCoord2sv               = glTexCoord2sv;
-  qglTexCoord3d                = glTexCoord3d;
-  qglTexCoord3dv               = glTexCoord3dv;
-  qglTexCoord3f                = glTexCoord3f;
-  qglTexCoord3fv               = glTexCoord3fv;
-  qglTexCoord3i                = glTexCoord3i;
-  qglTexCoord3iv               = glTexCoord3iv;
-  qglTexCoord3s                = glTexCoord3s;
-  qglTexCoord3sv               = glTexCoord3sv;
-  qglTexCoord4d                = glTexCoord4d;
-  qglTexCoord4dv               = glTexCoord4dv;
-  qglTexCoord4f                = glTexCoord4f;
-  qglTexCoord4fv               = glTexCoord4fv;
-  qglTexCoord4i                = glTexCoord4i;
-  qglTexCoord4iv               = glTexCoord4iv;
-  qglTexCoord4s                = glTexCoord4s;
-  qglTexCoord4sv               = glTexCoord4sv;
-  qglTexCoordPointer           = glTexCoordPointer;
-  qglTexEnvf                   = glTexEnvf;
-  qglTexEnvfv                  = glTexEnvfv;
-  qglTexEnvi                   = glTexEnvi;
-  qglTexEnviv                  = glTexEnviv;
-  qglTexGend                   = glTexGend;
-  qglTexGendv                  = glTexGendv;
-  qglTexGenf                   = glTexGenf;
-  qglTexGenfv                  = glTexGenfv;
-  qglTexGeni                   = glTexGeni;
-  qglTexGeniv                  = glTexGeniv;
-  qglTexImage1D                = glTexImage1D;
-  qglTexImage2D                = glTexImage2D;
-  qglTexParameterf             = glTexParameterf;
-  qglTexParameterfv            = glTexParameterfv;
-  qglTexParameteri             = glTexParameteri;
-  qglTexParameteriv            = glTexParameteriv;
-  qglTexSubImage1D             = glTexSubImage1D;
-  qglTexSubImage2D             = glTexSubImage2D;
-  qglTranslated                = glTranslated;
-  qglTranslatef                = glTranslatef;
-  qglVertex2d                  = glVertex2d;
-  qglVertex2dv                 = glVertex2dv;
-  qglVertex2f                  = glVertex2f;
-  qglVertex2fv                 = glVertex2fv;
-  qglVertex2i                  = glVertex2i;
-  qglVertex2iv                 = glVertex2iv;
-  qglVertex2s                  = glVertex2s;
-  qglVertex2sv                 = glVertex2sv;
-  qglVertex3d                  = glVertex3d;
-  qglVertex3dv                 = glVertex3dv;
-  qglVertex3f                  = glVertex3f;
-  qglVertex3fv                 = glVertex3fv;
-  qglVertex3i                  = glVertex3i;
-  qglVertex3iv                 = glVertex3iv;
-  qglVertex3s                  = glVertex3s;
-  qglVertex3sv                 = glVertex3sv;
-  qglVertex4d                  = glVertex4d;
-  qglVertex4dv                 = glVertex4dv;
-  qglVertex4f                  = glVertex4f;
-  qglVertex4fv                 = glVertex4fv;
-  qglVertex4i                  = glVertex4i;
-  qglVertex4iv                 = glVertex4iv;
-  qglVertex4s                  = glVertex4s;
-  qglVertex4sv                 = glVertex4sv;
-  qglVertexPointer             = glVertexPointer;
-  qglViewport                  = glViewport;
-
-  // must be init with an active context
-  qglActiveTextureARB = NULL;
-  qglClientActiveTextureARB = NULL;
-  qglMultiTexCoord1dARB = NULL;
-  qglMultiTexCoord1dvARB = NULL;
-  qglMultiTexCoord1fARB = NULL;
-  qglMultiTexCoord1fvARB = NULL;
-  qglMultiTexCoord1iARB = NULL;
-  qglMultiTexCoord1ivARB = NULL;
-  qglMultiTexCoord1sARB = NULL;
-  qglMultiTexCoord1svARB = NULL;
-  qglMultiTexCoord2dARB = NULL;
-  qglMultiTexCoord2dvARB = NULL;
-  qglMultiTexCoord2fARB = NULL;
-  qglMultiTexCoord2fvARB = NULL;
-  qglMultiTexCoord2iARB = NULL;
-  qglMultiTexCoord2ivARB = NULL;
-  qglMultiTexCoord2sARB = NULL;
-  qglMultiTexCoord2svARB = NULL;
-  qglMultiTexCoord3dARB = NULL;
-  qglMultiTexCoord3dvARB = NULL;
-  qglMultiTexCoord3fARB = NULL;
-  qglMultiTexCoord3fvARB = NULL;
-  qglMultiTexCoord3iARB = NULL;
-  qglMultiTexCoord3ivARB = NULL;
-  qglMultiTexCoord3sARB = NULL;
-  qglMultiTexCoord3svARB = NULL;
-  qglMultiTexCoord4dARB = NULL;
-  qglMultiTexCoord4dvARB = NULL;
-  qglMultiTexCoord4fARB = NULL;
-  qglMultiTexCoord4fvARB = NULL;
-  qglMultiTexCoord4iARB = NULL;
-  qglMultiTexCoord4ivARB = NULL;
-  qglMultiTexCoord4sARB = NULL;
-  qglMultiTexCoord4svARB = NULL;
-
-#ifdef _WIN32
-    qwglCopyContext              = safe_dlsym(g_hGLDLL, "wglCopyContext" );
-    qwglCreateContext            = safe_dlsym(g_hGLDLL, "wglCreateContext");
-    qwglCreateLayerContext       = safe_dlsym(g_hGLDLL, "wglCreateLayerContext" );
-    qwglDeleteContext            = safe_dlsym(g_hGLDLL, "wglDeleteContext");
-    qwglDescribeLayerPlane       = safe_dlsym(g_hGLDLL, "wglDescribeLayerPlane" );
-    qwglGetCurrentContext        = safe_dlsym(g_hGLDLL, "wglGetCurrentContext" );
-    qwglGetCurrentDC             = safe_dlsym(g_hGLDLL, "wglGetCurrentDC" );
-    qwglGetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglGetLayerPaletteEntries" );
-    qwglGetProcAddress           = safe_dlsym(g_hGLDLL, "wglGetProcAddress" );
-    qwglMakeCurrent              = safe_dlsym(g_hGLDLL, "wglMakeCurrent" );
-    qwglRealizeLayerPalette      = safe_dlsym(g_hGLDLL, "wglRealizeLayerPalette" );
-    qwglSetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglSetLayerPaletteEntries" );
-    qwglShareLists               = safe_dlsym(g_hGLDLL, "wglShareLists" );
-    qwglSwapLayerBuffers         = safe_dlsym(g_hGLDLL, "wglSwapLayerBuffers" );
-    qwglUseFontBitmaps           = safe_dlsym(g_hGLDLL, "wglUseFontBitmapsA" );
-    qwglUseFontOutlines          = safe_dlsym(g_hGLDLL, "wglUseFontOutlinesA" );
-
-    qwglChoosePixelFormat        = safe_dlsym(g_hGLDLL, "wglChoosePixelFormat" );
-    qwglDescribePixelFormat      = safe_dlsym(g_hGLDLL, "wglDescribePixelFormat" );
-    qwglGetPixelFormat           = safe_dlsym(g_hGLDLL, "wglGetPixelFormat" );
-    qwglSetPixelFormat           = safe_dlsym(g_hGLDLL, "wglSetPixelFormat" );
-    qwglSwapBuffers              = safe_dlsym(g_hGLDLL, "wglSwapBuffers" );
-
-    qwglSwapIntervalEXT = 0;
-    qglPointParameterfEXT = 0;
-    qglPointParameterfvEXT = 0;
-    qglColorTableEXT = 0;
-    qglSelectTextureSGIS = 0;
-    qglMTexCoord2fSGIS = 0;
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-  qglXChooseVisual             = glXChooseVisual;
-  qglXCreateContext            = glXCreateContext;
-  qglXDestroyContext           = glXDestroyContext;
-  qglXMakeCurrent              = glXMakeCurrent;
-  qglXCopyContext              = glXCopyContext;
-  qglXSwapBuffers              = glXSwapBuffers;
-  qglXCreateGLXPixmap          = glXCreateGLXPixmap;
-  qglXDestroyGLXPixmap         = glXDestroyGLXPixmap;
-  qglXQueryExtension           = glXQueryExtension;
-  qglXQueryVersion             = glXQueryVersion;
-  qglXIsDirect                 = glXIsDirect;
-  qglXGetConfig                = glXGetConfig;
-  qglXGetCurrentContext        = glXGetCurrentContext;
-  qglXGetCurrentDrawable       = glXGetCurrentDrawable;
-  qglXWaitGL                   = glXWaitGL;
-  qglXWaitX                    = glXWaitX;
-  qglXUseXFont                 = glXUseXFont;
-  qglXGetProcAddressARB        = glXGetProcAddressARB; // Utah-GLX fix
-#endif
-
-  qglPointParameterfEXT = 0;
-  qglPointParameterfvEXT = 0;
-  qglColorTableEXT = 0;
-  qglSelectTextureSGIS = 0;
-  qglMTexCoord2fSGIS = 0;
-
-  Sys_Printf("Done.\n");
-
-  if (init_error == 1)
-    return 0;
-
-  return 1;
-}
-
-static int GL_ExtensionSupported (const char *extension)
-{
-  const GLubyte *extensions = NULL;
-  const GLubyte *start;
-  GLubyte *where, *terminator;
-
-  // Extension names should not have spaces.
-  where = (GLubyte *) strchr (extension, ' ');
-  if (where || *extension == '\0')
-    return 0;
-
-  extensions = qglGetString (GL_EXTENSIONS);
-
-  // It takes a bit of care to be fool-proof about parsing the
-  // OpenGL extensions string. Don't be fooled by sub-strings, etc.
-  for (start = extensions; ;)
-  {
-    where = (GLubyte *) strstr ((const char *) start, extension);
-    if (!where)
-      break;
-
-    terminator = where + strlen (extension);
-    if (where == start || *(where - 1) == ' ')
-      if (*terminator == ' ' || *terminator == '\0')
-	return 1;
-
-    start = terminator;
-  }
-
-  return 0;
-}
-
-void* Sys_GLGetExtension (const char *symbol)
-{
-#if defined (__linux__) || defined (__APPLE__)
-  if (qglXGetProcAddressARB == NULL)
-    return NULL;
-  else
-    return qglXGetProcAddressARB ((GLubyte*)symbol);
-#else
-  return qwglGetProcAddress (symbol);
-#endif
-}
-
-void QGL_InitExtensions ()
-{
-  if (GL_ExtensionSupported ("GL_ARB_multitexture"))
-  {
-    qglActiveTextureARB = Sys_GLGetExtension ("glActiveTextureARB");
-    qglClientActiveTextureARB = Sys_GLGetExtension ("glClientActiveTextureARB");
-    qglMultiTexCoord1dARB = Sys_GLGetExtension ("glMultiTexCoord1dARB");
-    qglMultiTexCoord1dvARB = Sys_GLGetExtension ("glMultiTexCoord1dvARB");
-    qglMultiTexCoord1fARB = Sys_GLGetExtension ("glMultiTexCoord1fARB");
-    qglMultiTexCoord1fvARB = Sys_GLGetExtension ("glMultiTexCoord1fvARB");
-    qglMultiTexCoord1iARB = Sys_GLGetExtension ("glMultiTexCoord1iARB");
-    qglMultiTexCoord1ivARB = Sys_GLGetExtension ("glMultiTexCoord1ivARB");
-    qglMultiTexCoord1sARB = Sys_GLGetExtension ("glMultiTexCoord1sARB");
-    qglMultiTexCoord1svARB = Sys_GLGetExtension ("glMultiTexCoord1svARB");
-    qglMultiTexCoord2dARB = Sys_GLGetExtension ("glMultiTexCoord2dARB");
-    qglMultiTexCoord2dvARB = Sys_GLGetExtension ("glMultiTexCoord2dvARB");
-    qglMultiTexCoord2fARB = Sys_GLGetExtension ("glMultiTexCoord2fARB");
-    qglMultiTexCoord2fvARB = Sys_GLGetExtension ("glMultiTexCoord2fvARB");
-    qglMultiTexCoord2iARB = Sys_GLGetExtension ("glMultiTexCoord2iARB");
-    qglMultiTexCoord2ivARB = Sys_GLGetExtension ("glMultiTexCoord2ivARB");
-    qglMultiTexCoord2sARB = Sys_GLGetExtension ("glMultiTexCoord2sARB");
-    qglMultiTexCoord2svARB = Sys_GLGetExtension ("glMultiTexCoord2svARB");
-    qglMultiTexCoord3dARB = Sys_GLGetExtension ("glMultiTexCoord3dARB");
-    qglMultiTexCoord3dvARB = Sys_GLGetExtension ("glMultiTexCoord3dvARB");
-    qglMultiTexCoord3fARB = Sys_GLGetExtension ("glMultiTexCoord3fARB");
-    qglMultiTexCoord3fvARB = Sys_GLGetExtension ("glMultiTexCoord3fvARB");
-    qglMultiTexCoord3iARB = Sys_GLGetExtension ("glMultiTexCoord3iARB");
-    qglMultiTexCoord3ivARB = Sys_GLGetExtension ("glMultiTexCoord3ivARB");
-    qglMultiTexCoord3sARB = Sys_GLGetExtension ("glMultiTexCoord3sARB");
-    qglMultiTexCoord3svARB = Sys_GLGetExtension ("glMultiTexCoord3svARB");
-    qglMultiTexCoord4dARB = Sys_GLGetExtension ("glMultiTexCoord4dARB");
-    qglMultiTexCoord4dvARB = Sys_GLGetExtension ("glMultiTexCoord4dvARB");
-    qglMultiTexCoord4fARB = Sys_GLGetExtension ("glMultiTexCoord4fARB");
-    qglMultiTexCoord4fvARB = Sys_GLGetExtension ("glMultiTexCoord4fvARB");
-    qglMultiTexCoord4iARB = Sys_GLGetExtension ("glMultiTexCoord4iARB");
-    qglMultiTexCoord4ivARB = Sys_GLGetExtension ("glMultiTexCoord4ivARB");
-    qglMultiTexCoord4sARB = Sys_GLGetExtension ("glMultiTexCoord4sARB");
-    qglMultiTexCoord4svARB = Sys_GLGetExtension ("glMultiTexCoord4svARB");
-  }
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+** QGL_WIN.C
+**
+** This file implements the operating system binding of GL to QGL function
+** pointers.  When doing a port of Quake2 you must implement the following
+** two functions:
+**
+** QGL_Init() - loads libraries, assigns function pointers, etc.
+** QGL_Shutdown() - unloads libraries, NULLs function pointers
+*/
+#include <stdio.h>
+#include <float.h>
+#include <string.h>
+#if defined (__linux__) || defined (__APPLE__)
+//#include <dlfcn.h>
+#endif
+#ifdef _WIN32
+#include <windows.h>
+#endif
+#include "qgl.h"
+#include <GL/glu.h>
+void Sys_Printf(const char *format, ...);
+
+#ifdef _WIN32
+HMODULE g_hGLDLL = NULL;
+
+#pragma warning (disable : 4113 4133 4047 4018 )
+
+int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
+int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+int   ( WINAPI * qwglGetPixelFormat)(HDC);
+BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
+BOOL  ( WINAPI * qwglSwapBuffers)(HDC);
+
+BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
+HGLRC ( WINAPI * qwglCreateContext)(HDC);
+HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
+BOOL  ( WINAPI * qwglDeleteContext)(HGLRC);
+HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
+HDC   ( WINAPI * qwglGetCurrentDC)(VOID);
+PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR);
+BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
+BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
+BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
+
+BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
+				      FLOAT, int, LPGLYPHMETRICSFLOAT);
+
+BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
+int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int, CONST COLORREF *);
+int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int, COLORREF *);
+BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
+BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
+
+BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * );
+BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *,
+					    const unsigned char * );
+BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
+
+#else
+#define WINAPI
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+void* g_hGLDLL;
+
+XVisualInfo* (*qglXChooseVisual)(Display *dpy, int screen, int *attribList);
+GLXContext   (*qglXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+void         (*qglXDestroyContext)(Display *dpy, GLXContext ctx);
+Bool         (*qglXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
+void         (*qglXCopyContext)(Display *dpy, GLXContext src, GLXContext dst, GLuint mask);
+void         (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable );
+GLXPixmap    (*qglXCreateGLXPixmap)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
+void         (*qglXDestroyGLXPixmap)( Display *dpy, GLXPixmap pixmap );
+Bool         (*qglXQueryExtension)( Display *dpy, int *errorb, int *event );
+Bool         (*qglXQueryVersion)( Display *dpy, int *maj, int *min );
+Bool         (*qglXIsDirect)( Display *dpy, GLXContext ctx );
+int          (*qglXGetConfig)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
+GLXContext   (*qglXGetCurrentContext)( void );
+GLXDrawable  (*qglXGetCurrentDrawable)( void );
+void         (*qglXWaitGL)( void );
+void         (*qglXWaitX)( void );
+void         (*qglXUseXFont)( Font font, int first, int count, int list );
+void*        (*qglXGetProcAddressARB) (const GLubyte *procName);
+#endif
+
+void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
+void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
+GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+void ( APIENTRY * qglArrayElement )(GLint i);
+void ( APIENTRY * qglBegin )(GLenum mode);
+void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
+void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
+void ( APIENTRY * qglCallList )(GLuint list);
+void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+void ( APIENTRY * qglClear )(GLbitfield mask);
+void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+void ( APIENTRY * qglClearDepth )(GLclampd depth);
+void ( APIENTRY * qglClearIndex )(GLfloat c);
+void ( APIENTRY * qglClearStencil )(GLint s);
+void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
+void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+void ( APIENTRY * qglColor3bv )(const GLbyte *v);
+void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+void ( APIENTRY * qglColor3dv )(const GLdouble *v);
+void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+void ( APIENTRY * qglColor3fv )(const GLfloat *v);
+void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
+void ( APIENTRY * qglColor3iv )(const GLint *v);
+void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
+void ( APIENTRY * qglColor3sv )(const GLshort *v);
+void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
+void ( APIENTRY * qglColor3uiv )(const GLuint *v);
+void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
+void ( APIENTRY * qglColor3usv )(const GLushort *v);
+void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+void ( APIENTRY * qglColor4bv )(const GLbyte *v);
+void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+void ( APIENTRY * qglColor4dv )(const GLdouble *v);
+void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglColor4fv )(const GLfloat *v);
+void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+void ( APIENTRY * qglColor4iv )(const GLint *v);
+void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+void ( APIENTRY * qglColor4sv )(const GLshort *v);
+void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+void ( APIENTRY * qglColor4uiv )(const GLuint *v);
+void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+void ( APIENTRY * qglColor4usv )(const GLushort *v);
+void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
+void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglCullFace )(GLenum mode);
+void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
+void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
+void ( APIENTRY * qglDepthFunc )(GLenum func);
+void ( APIENTRY * qglDepthMask )(GLboolean flag);
+void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
+void ( APIENTRY * qglDisable )(GLenum cap);
+void ( APIENTRY * qglDisableClientState )(GLenum array);
+void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
+void ( APIENTRY * qglDrawBuffer )(GLenum mode);
+void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
+void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
+void ( APIENTRY * qglEnable )(GLenum cap);
+void ( APIENTRY * qglEnableClientState )(GLenum array);
+void ( APIENTRY * qglEnd )(void);
+void ( APIENTRY * qglEndList )(void);
+void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
+void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
+void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
+void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
+void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+void ( APIENTRY * qglEvalPoint1 )(GLint i);
+void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
+void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+void ( APIENTRY * qglFinish )(void);
+void ( APIENTRY * qglFlush )(void);
+void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
+void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglFrontFace )(GLenum mode);
+void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLuint ( APIENTRY * qglGenLists )(GLsizei range);
+void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
+void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
+void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
+void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
+GLenum ( APIENTRY * qglGetError )(void);
+void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
+void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
+void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
+void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
+void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
+void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
+void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
+const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
+void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
+void ( APIENTRY * qglIndexMask )(GLuint mask);
+void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglIndexd )(GLdouble c);
+void ( APIENTRY * qglIndexdv )(const GLdouble *c);
+void ( APIENTRY * qglIndexf )(GLfloat c);
+void ( APIENTRY * qglIndexfv )(const GLfloat *c);
+void ( APIENTRY * qglIndexi )(GLint c);
+void ( APIENTRY * qglIndexiv )(const GLint *c);
+void ( APIENTRY * qglIndexs )(GLshort c);
+void ( APIENTRY * qglIndexsv )(const GLshort *c);
+void ( APIENTRY * qglIndexub )(GLubyte c);
+void ( APIENTRY * qglIndexubv )(const GLubyte *c);
+void ( APIENTRY * qglInitNames )(void);
+void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
+GLboolean ( APIENTRY * qglIsList )(GLuint list);
+GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
+void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
+void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
+void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
+void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
+void ( APIENTRY * qglLineWidth )(GLfloat width);
+void ( APIENTRY * qglListBase )(GLuint base);
+void ( APIENTRY * qglLoadIdentity )(void);
+void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglLoadName )(GLuint name);
+void ( APIENTRY * qglLogicOp )(GLenum opcode);
+void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
+void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
+void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+void ( APIENTRY * qglMatrixMode )(GLenum mode);
+void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
+void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
+void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
+void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
+void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
+void ( APIENTRY * qglNormal3iv )(const GLint *v);
+void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+void ( APIENTRY * qglNormal3sv )(const GLshort *v);
+void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+void ( APIENTRY * qglPassThrough )(GLfloat token);
+void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+void ( APIENTRY * qglPointSize )(GLfloat size);
+void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
+void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
+void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
+void ( APIENTRY * qglPopAttrib )(void);
+void ( APIENTRY * qglPopClientAttrib )(void);
+void ( APIENTRY * qglPopMatrix )(void);
+void ( APIENTRY * qglPopName )(void);
+void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushMatrix )(void);
+void ( APIENTRY * qglPushName )(GLuint name);
+void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
+void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
+void ( APIENTRY * qglReadBuffer )(GLenum mode);
+void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
+void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
+void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
+void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
+GLint ( APIENTRY * qglRenderMode )(GLenum mode);
+void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
+void ( APIENTRY * qglShadeModel )(GLenum mode);
+void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
+void ( APIENTRY * qglStencilMask )(GLuint mask);
+void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+void ( APIENTRY * qglTexCoord1d )(GLdouble s);
+void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord1f )(GLfloat s);
+void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord1i )(GLint s);
+void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord1s )(GLshort s);
+void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
+void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
+void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
+void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
+void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
+void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
+void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
+void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
+void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
+void ( APIENTRY * qglVertex2iv )(const GLint *v);
+void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglVertex2sv )(const GLshort *v);
+void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglVertex3iv )(const GLint *v);
+void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglVertex3sv )(const GLshort *v);
+void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglVertex4iv )(const GLint *v);
+void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglVertex4sv )(const GLshort *v);
+void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
+void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
+void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
+void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
+void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
+
+void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
+void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
+void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
+
+// glu stuff
+void (APIENTRY * qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+int  (APIENTRY * qgluBuild2DMipmaps) (GLenum target, GLint components, GLint width, GLint height, GLenum format, GLenum      type, const void  *data);
+// added for plugins
+void (APIENTRY * qgluLookAt)(
+  GLdouble eyex,
+  GLdouble eyey,
+  GLdouble eyez,
+  GLdouble centerx,
+  GLdouble centery,
+  GLdouble centerz,
+  GLdouble upx,
+  GLdouble upy,
+  GLdouble upz);
+const GLubyte* (APIENTRY * qgluErrorString) (GLenum errCode );
+
+/*
+** QGL_Shutdown
+**
+** Unloads the specified DLL then nulls out all the proc pointers.
+*/
+void QGL_Shutdown()
+{
+  Sys_Printf("Shutting down GL ...");
+
+  if (g_hGLDLL)
+  {
+#ifdef _WIN32
+    FreeLibrary(g_hGLDLL);
+#endif
+
+//#if defined (__linux__) || defined (__APPLE__)
+//    dlclose (g_hGLDLL);
+//#endif
+
+    g_hGLDLL = NULL;
+  }
+
+  Sys_Printf("Done.\n");
+
+  qglAccum                     = NULL;
+  qglAlphaFunc                 = NULL;
+  qglAreTexturesResident       = NULL;
+  qglArrayElement              = NULL;
+  qglBegin                     = NULL;
+  qglBindTexture               = NULL;
+  qglBitmap                    = NULL;
+  qglBlendFunc                 = NULL;
+  qglCallList                  = NULL;
+  qglCallLists                 = NULL;
+  qglClear                     = NULL;
+  qglClearAccum                = NULL;
+  qglClearColor                = NULL;
+  qglClearDepth                = NULL;
+  qglClearIndex                = NULL;
+  qglClearStencil              = NULL;
+  qglClipPlane                 = NULL;
+  qglColor3b                   = NULL;
+  qglColor3bv                  = NULL;
+  qglColor3d                   = NULL;
+  qglColor3dv                  = NULL;
+  qglColor3f                   = NULL;
+  qglColor3fv                  = NULL;
+  qglColor3i                   = NULL;
+  qglColor3iv                  = NULL;
+  qglColor3s                   = NULL;
+  qglColor3sv                  = NULL;
+  qglColor3ub                  = NULL;
+  qglColor3ubv                 = NULL;
+  qglColor3ui                  = NULL;
+  qglColor3uiv                 = NULL;
+  qglColor3us                  = NULL;
+  qglColor3usv                 = NULL;
+  qglColor4b                   = NULL;
+  qglColor4bv                  = NULL;
+  qglColor4d                   = NULL;
+  qglColor4dv                  = NULL;
+  qglColor4f                   = NULL;
+  qglColor4fv                  = NULL;
+  qglColor4i                   = NULL;
+  qglColor4iv                  = NULL;
+  qglColor4s                   = NULL;
+  qglColor4sv                  = NULL;
+  qglColor4ub                  = NULL;
+  qglColor4ubv                 = NULL;
+  qglColor4ui                  = NULL;
+  qglColor4uiv                 = NULL;
+  qglColor4us                  = NULL;
+  qglColor4usv                 = NULL;
+  qglColorMask                 = NULL;
+  qglColorMaterial             = NULL;
+  qglColorPointer              = NULL;
+  qglCopyPixels                = NULL;
+  qglCopyTexImage1D            = NULL;
+  qglCopyTexImage2D            = NULL;
+  qglCopyTexSubImage1D         = NULL;
+  qglCopyTexSubImage2D         = NULL;
+  qglCullFace                  = NULL;
+  qglDeleteLists               = NULL;
+  qglDeleteTextures            = NULL;
+  qglDepthFunc                 = NULL;
+  qglDepthMask                 = NULL;
+  qglDepthRange                = NULL;
+  qglDisable                   = NULL;
+  qglDisableClientState        = NULL;
+  qglDrawArrays                = NULL;
+  qglDrawBuffer                = NULL;
+  qglDrawElements              = NULL;
+  qglDrawPixels                = NULL;
+  qglEdgeFlag                  = NULL;
+  qglEdgeFlagPointer           = NULL;
+  qglEdgeFlagv                 = NULL;
+  qglEnable                    = NULL;
+  qglEnableClientState         = NULL;
+  qglEnd                       = NULL;
+  qglEndList                   = NULL;
+  qglEvalCoord1d               = NULL;
+  qglEvalCoord1dv              = NULL;
+  qglEvalCoord1f               = NULL;
+  qglEvalCoord1fv              = NULL;
+  qglEvalCoord2d               = NULL;
+  qglEvalCoord2dv              = NULL;
+  qglEvalCoord2f               = NULL;
+  qglEvalCoord2fv              = NULL;
+  qglEvalMesh1                 = NULL;
+  qglEvalMesh2                 = NULL;
+  qglEvalPoint1                = NULL;
+  qglEvalPoint2                = NULL;
+  qglFeedbackBuffer            = NULL;
+  qglFinish                    = NULL;
+  qglFlush                     = NULL;
+  qglFogf                      = NULL;
+  qglFogfv                     = NULL;
+  qglFogi                      = NULL;
+  qglFogiv                     = NULL;
+  qglFrontFace                 = NULL;
+  qglFrustum                   = NULL;
+  qglGenLists                  = NULL;
+  qglGenTextures               = NULL;
+  qglGetBooleanv               = NULL;
+  qglGetClipPlane              = NULL;
+  qglGetDoublev                = NULL;
+  qglGetError                  = NULL;
+  qglGetFloatv                 = NULL;
+  qglGetIntegerv               = NULL;
+  qglGetLightfv                = NULL;
+  qglGetLightiv                = NULL;
+  qglGetMapdv                  = NULL;
+  qglGetMapfv                  = NULL;
+  qglGetMapiv                  = NULL;
+  qglGetMaterialfv             = NULL;
+  qglGetMaterialiv             = NULL;
+  qglGetPixelMapfv             = NULL;
+  qglGetPixelMapuiv            = NULL;
+  qglGetPixelMapusv            = NULL;
+  qglGetPointerv               = NULL;
+  qglGetPolygonStipple         = NULL;
+  qglGetString                 = NULL;
+  qglGetTexEnvfv               = NULL;
+  qglGetTexEnviv               = NULL;
+  qglGetTexGendv               = NULL;
+  qglGetTexGenfv               = NULL;
+  qglGetTexGeniv               = NULL;
+  qglGetTexImage               = NULL;
+  qglGetTexLevelParameterfv    = NULL;
+  qglGetTexLevelParameteriv    = NULL;
+  qglGetTexParameterfv         = NULL;
+  qglGetTexParameteriv         = NULL;
+  qglHint                      = NULL;
+  qglIndexMask                 = NULL;
+  qglIndexPointer              = NULL;
+  qglIndexd                    = NULL;
+  qglIndexdv                   = NULL;
+  qglIndexf                    = NULL;
+  qglIndexfv                   = NULL;
+  qglIndexi                    = NULL;
+  qglIndexiv                   = NULL;
+  qglIndexs                    = NULL;
+  qglIndexsv                   = NULL;
+  qglIndexub                   = NULL;
+  qglIndexubv                  = NULL;
+  qglInitNames                 = NULL;
+  qglInterleavedArrays         = NULL;
+  qglIsEnabled                 = NULL;
+  qglIsList                    = NULL;
+  qglIsTexture                 = NULL;
+  qglLightModelf               = NULL;
+  qglLightModelfv              = NULL;
+  qglLightModeli               = NULL;
+  qglLightModeliv              = NULL;
+  qglLightf                    = NULL;
+  qglLightfv                   = NULL;
+  qglLighti                    = NULL;
+  qglLightiv                   = NULL;
+  qglLineStipple               = NULL;
+  qglLineWidth                 = NULL;
+  qglListBase                  = NULL;
+  qglLoadIdentity              = NULL;
+  qglLoadMatrixd               = NULL;
+  qglLoadMatrixf               = NULL;
+  qglLoadName                  = NULL;
+  qglLogicOp                   = NULL;
+  qglMap1d                     = NULL;
+  qglMap1f                     = NULL;
+  qglMap2d                     = NULL;
+  qglMap2f                     = NULL;
+  qglMapGrid1d                 = NULL;
+  qglMapGrid1f                 = NULL;
+  qglMapGrid2d                 = NULL;
+  qglMapGrid2f                 = NULL;
+  qglMaterialf                 = NULL;
+  qglMaterialfv                = NULL;
+  qglMateriali                 = NULL;
+  qglMaterialiv                = NULL;
+  qglMatrixMode                = NULL;
+  qglMultMatrixd               = NULL;
+  qglMultMatrixf               = NULL;
+  qglNewList                   = NULL;
+  qglNormal3b                  = NULL;
+  qglNormal3bv                 = NULL;
+  qglNormal3d                  = NULL;
+  qglNormal3dv                 = NULL;
+  qglNormal3f                  = NULL;
+  qglNormal3fv                 = NULL;
+  qglNormal3i                  = NULL;
+  qglNormal3iv                 = NULL;
+  qglNormal3s                  = NULL;
+  qglNormal3sv                 = NULL;
+  qglNormalPointer             = NULL;
+  qglOrtho                     = NULL;
+  qglPassThrough               = NULL;
+  qglPixelMapfv                = NULL;
+  qglPixelMapuiv               = NULL;
+  qglPixelMapusv               = NULL;
+  qglPixelStoref               = NULL;
+  qglPixelStorei               = NULL;
+  qglPixelTransferf            = NULL;
+  qglPixelTransferi            = NULL;
+  qglPixelZoom                 = NULL;
+  qglPointSize                 = NULL;
+  qglPolygonMode               = NULL;
+  qglPolygonOffset             = NULL;
+  qglPolygonStipple            = NULL;
+  qglPopAttrib                 = NULL;
+  qglPopClientAttrib           = NULL;
+  qglPopMatrix                 = NULL;
+  qglPopName                   = NULL;
+  qglPrioritizeTextures        = NULL;
+  qglPushAttrib                = NULL;
+  qglPushClientAttrib          = NULL;
+  qglPushMatrix                = NULL;
+  qglPushName                  = NULL;
+  qglRasterPos2d               = NULL;
+  qglRasterPos2dv              = NULL;
+  qglRasterPos2f               = NULL;
+  qglRasterPos2fv              = NULL;
+  qglRasterPos2i               = NULL;
+  qglRasterPos2iv              = NULL;
+  qglRasterPos2s               = NULL;
+  qglRasterPos2sv              = NULL;
+  qglRasterPos3d               = NULL;
+  qglRasterPos3dv              = NULL;
+  qglRasterPos3f               = NULL;
+  qglRasterPos3fv              = NULL;
+  qglRasterPos3i               = NULL;
+  qglRasterPos3iv              = NULL;
+  qglRasterPos3s               = NULL;
+  qglRasterPos3sv              = NULL;
+  qglRasterPos4d               = NULL;
+  qglRasterPos4dv              = NULL;
+  qglRasterPos4f               = NULL;
+  qglRasterPos4fv              = NULL;
+  qglRasterPos4i               = NULL;
+  qglRasterPos4iv              = NULL;
+  qglRasterPos4s               = NULL;
+  qglRasterPos4sv              = NULL;
+  qglReadBuffer                = NULL;
+  qglReadPixels                = NULL;
+  qglRectd                     = NULL;
+  qglRectdv                    = NULL;
+  qglRectf                     = NULL;
+  qglRectfv                    = NULL;
+  qglRecti                     = NULL;
+  qglRectiv                    = NULL;
+  qglRects                     = NULL;
+  qglRectsv                    = NULL;
+  qglRenderMode                = NULL;
+  qglRotated                   = NULL;
+  qglRotatef                   = NULL;
+  qglScaled                    = NULL;
+  qglScalef                    = NULL;
+  qglScissor                   = NULL;
+  qglSelectBuffer              = NULL;
+  qglShadeModel                = NULL;
+  qglStencilFunc               = NULL;
+  qglStencilMask               = NULL;
+  qglStencilOp                 = NULL;
+  qglTexCoord1d                = NULL;
+  qglTexCoord1dv               = NULL;
+  qglTexCoord1f                = NULL;
+  qglTexCoord1fv               = NULL;
+  qglTexCoord1i                = NULL;
+  qglTexCoord1iv               = NULL;
+  qglTexCoord1s                = NULL;
+  qglTexCoord1sv               = NULL;
+  qglTexCoord2d                = NULL;
+  qglTexCoord2dv               = NULL;
+  qglTexCoord2f                = NULL;
+  qglTexCoord2fv               = NULL;
+  qglTexCoord2i                = NULL;
+  qglTexCoord2iv               = NULL;
+  qglTexCoord2s                = NULL;
+  qglTexCoord2sv               = NULL;
+  qglTexCoord3d                = NULL;
+  qglTexCoord3dv               = NULL;
+  qglTexCoord3f                = NULL;
+  qglTexCoord3fv               = NULL;
+  qglTexCoord3i                = NULL;
+  qglTexCoord3iv               = NULL;
+  qglTexCoord3s                = NULL;
+  qglTexCoord3sv               = NULL;
+  qglTexCoord4d                = NULL;
+  qglTexCoord4dv               = NULL;
+  qglTexCoord4f                = NULL;
+  qglTexCoord4fv               = NULL;
+  qglTexCoord4i                = NULL;
+  qglTexCoord4iv               = NULL;
+  qglTexCoord4s                = NULL;
+  qglTexCoord4sv               = NULL;
+  qglTexCoordPointer           = NULL;
+  qglTexEnvf                   = NULL;
+  qglTexEnvfv                  = NULL;
+  qglTexEnvi                   = NULL;
+  qglTexEnviv                  = NULL;
+  qglTexGend                   = NULL;
+  qglTexGendv                  = NULL;
+  qglTexGenf                   = NULL;
+  qglTexGenfv                  = NULL;
+  qglTexGeni                   = NULL;
+  qglTexGeniv                  = NULL;
+  qglTexImage1D                = NULL;
+  qglTexImage2D                = NULL;
+  qglTexParameterf             = NULL;
+  qglTexParameterfv            = NULL;
+  qglTexParameteri             = NULL;
+  qglTexParameteriv            = NULL;
+  qglTexSubImage1D             = NULL;
+  qglTexSubImage2D             = NULL;
+  qglTranslated                = NULL;
+  qglTranslatef                = NULL;
+  qglVertex2d                  = NULL;
+  qglVertex2dv                 = NULL;
+  qglVertex2f                  = NULL;
+  qglVertex2fv                 = NULL;
+  qglVertex2i                  = NULL;
+  qglVertex2iv                 = NULL;
+  qglVertex2s                  = NULL;
+  qglVertex2sv                 = NULL;
+  qglVertex3d                  = NULL;
+  qglVertex3dv                 = NULL;
+  qglVertex3f                  = NULL;
+  qglVertex3fv                 = NULL;
+  qglVertex3i                  = NULL;
+  qglVertex3iv                 = NULL;
+  qglVertex3s                  = NULL;
+  qglVertex3sv                 = NULL;
+  qglVertex4d                  = NULL;
+  qglVertex4dv                 = NULL;
+  qglVertex4f                  = NULL;
+  qglVertex4fv                 = NULL;
+  qglVertex4i                  = NULL;
+  qglVertex4iv                 = NULL;
+  qglVertex4s                  = NULL;
+  qglVertex4sv                 = NULL;
+  qglVertexPointer             = NULL;
+  qglViewport                  = NULL;
+
+  qglActiveTextureARB = NULL;
+  qglClientActiveTextureARB = NULL;
+  qglMultiTexCoord1dARB = NULL;
+  qglMultiTexCoord1dvARB = NULL;
+  qglMultiTexCoord1fARB = NULL;
+  qglMultiTexCoord1fvARB = NULL;
+  qglMultiTexCoord1iARB = NULL;
+  qglMultiTexCoord1ivARB = NULL;
+  qglMultiTexCoord1sARB = NULL;
+  qglMultiTexCoord1svARB = NULL;
+  qglMultiTexCoord2dARB = NULL;
+  qglMultiTexCoord2dvARB = NULL;
+  qglMultiTexCoord2fARB = NULL;
+  qglMultiTexCoord2fvARB = NULL;
+  qglMultiTexCoord2iARB = NULL;
+  qglMultiTexCoord2ivARB = NULL;
+  qglMultiTexCoord2sARB = NULL;
+  qglMultiTexCoord2svARB = NULL;
+  qglMultiTexCoord3dARB = NULL;
+  qglMultiTexCoord3dvARB = NULL;
+  qglMultiTexCoord3fARB = NULL;
+  qglMultiTexCoord3fvARB = NULL;
+  qglMultiTexCoord3iARB = NULL;
+  qglMultiTexCoord3ivARB = NULL;
+  qglMultiTexCoord3sARB = NULL;
+  qglMultiTexCoord3svARB = NULL;
+  qglMultiTexCoord4dARB = NULL;
+  qglMultiTexCoord4dvARB = NULL;
+  qglMultiTexCoord4fARB = NULL;
+  qglMultiTexCoord4fvARB = NULL;
+  qglMultiTexCoord4iARB = NULL;
+  qglMultiTexCoord4ivARB = NULL;
+  qglMultiTexCoord4sARB = NULL;
+  qglMultiTexCoord4svARB = NULL;
+
+#ifdef _WIN32
+  qwglCopyContext              = NULL;
+  qwglCreateContext            = NULL;
+  qwglCreateLayerContext       = NULL;
+  qwglDeleteContext            = NULL;
+  qwglDescribeLayerPlane       = NULL;
+  qwglGetCurrentContext        = NULL;
+  qwglGetCurrentDC             = NULL;
+  qwglGetLayerPaletteEntries   = NULL;
+  qwglGetProcAddress           = NULL;
+  qwglMakeCurrent              = NULL;
+  qwglRealizeLayerPalette      = NULL;
+  qwglSetLayerPaletteEntries   = NULL;
+  qwglShareLists               = NULL;
+  qwglSwapLayerBuffers         = NULL;
+  qwglUseFontBitmaps           = NULL;
+  qwglUseFontOutlines          = NULL;
+
+  qwglChoosePixelFormat        = NULL;
+  qwglDescribePixelFormat      = NULL;
+  qwglGetPixelFormat           = NULL;
+  qwglSetPixelFormat           = NULL;
+  qwglSwapBuffers              = NULL;
+
+  qwglSwapIntervalEXT          = NULL;
+
+  qwglGetDeviceGammaRampEXT    = NULL;
+  qwglSetDeviceGammaRampEXT    = NULL;
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+  qglXChooseVisual             = NULL;
+  qglXCreateContext            = NULL;
+  qglXDestroyContext           = NULL;
+  qglXMakeCurrent              = NULL;
+  qglXCopyContext              = NULL;
+  qglXSwapBuffers              = NULL;
+  qglXCreateGLXPixmap          = NULL;
+  qglXDestroyGLXPixmap         = NULL;
+  qglXQueryExtension           = NULL;
+  qglXQueryVersion             = NULL;
+  qglXIsDirect                 = NULL;
+  qglXGetConfig                = NULL;
+  qglXGetCurrentContext        = NULL;
+  qglXGetCurrentDrawable       = NULL;
+  qglXWaitGL                   = NULL;
+  qglXWaitX                    = NULL;
+  qglXUseXFont                 = NULL;
+  qglXGetProcAddressARB        = NULL;
+#endif
+
+  qgluPerspective = NULL;
+  qgluBuild2DMipmaps = NULL;
+  qgluErrorString = NULL;
+  qgluLookAt = NULL;
+}
+
+/*
+** QGL_Init
+**
+** This is responsible for binding our qgl function pointers to 
+** the appropriate GL stuff.  In Windows this means doing a 
+** LoadLibrary and a bunch of calls to GetProcAddress.  On other
+** operating systems we need to do the right thing, whatever that
+** might be.
+** 
+*/
+static int init_error;
+
+//static void* safe_dlsym (void *handle, char *symbol)
+//{
+//#ifdef _WIN32
+//  return GetProcAddress (handle, symbol);
+//#endif
+
+//#if defined (__linux__) || defined (__APPLE__)
+//  void* ret = dlsym (handle, symbol);
+//  char *err = dlerror();
+//  if (err)
+//{
+//    init_error = 1;
+//    printf ("Error loading OpenGL libraries: %s %s\n", err, symbol);
+//  }
+//  return ret;
+//#endif
+//}
+
+#include <math.h>
+#include <stdlib.h>
+#ifdef _WIN32
+#define M_PI 3.14159
+#endif
+
+void WINAPI gluLookAt2 (GLdouble ex, GLdouble ey, GLdouble ez, GLdouble cx, GLdouble cy, GLdouble cz,
+		 GLdouble ux, GLdouble uy, GLdouble uz)
+{
+   GLdouble x[3], y[3], z[3] = { ex-cx, ey-cy, ez-cz };
+   GLdouble inv;
+
+   inv = sqrt (z[0]*z[0] + z[1]*z[1] + z[2]*z[2]);
+   if (inv)
+   {
+     inv = 1.0/inv;
+     z[0] *= inv;
+     z[1] *= inv;
+     z[2] *= inv;
+   }
+
+   x[0] =  uy*z[2] - uz*z[1];
+   x[1] = -ux*z[2] + uz*z[0];
+   x[2] =  ux*z[1] - uy*z[0];
+
+   y[0] =  z[1]*x[2] - z[2]*x[1];
+   y[1] = -z[0]*x[2] + z[2]*x[0];
+   y[2] =  z[0]*x[1] - z[1]*x[0];
+
+   inv = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
+   if (inv)
+   {
+     x[0] *= inv;
+     x[1] *= inv;
+     x[2] *= inv;
+   }
+
+   inv = sqrt(y[0]*y[0] + y[1]*y[1] + y[2]*y[2]);
+   if (inv)
+   {
+      y[0] *= inv;
+      y[1] *= inv;
+      y[2] *= inv;
+   }
+
+   {
+   GLdouble m[16] = { x[0], y[0], z[0], 0, x[1], y[1], z[1], 0, x[2], y[2], z[2], 0, 0, 0, 0, 1 };
+   qglMultMatrixd(m);
+   qglTranslated(-ex, -ey, -ez);
+   }
+}
+
+void WINAPI gluPerspective2 (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
+{
+   GLdouble y = zNear * tan (fovy * M_PI / 360.0);
+   qglFrustum (-y*aspect, y*aspect, -y, y, zNear, zFar);
+}
+
+static void* WINAPI ResizeImage (GLubyte* old_image, int srcw, int srch, int destw, int desth)
+{
+  int i, j;
+  float sx, sy;
+
+  GLubyte* new_image = malloc (destw*desth*4*sizeof(GLubyte));
+  if (new_image == NULL)
+    return NULL;
+
+  if (destw > 1)
+    sx = (GLfloat) (srcw-1) / (GLfloat) (destw-1);
+  else
+    sx = (GLfloat) (srcw-1);
+  if (desth > 1)
+    sy = (GLfloat) (srch-1) / (GLfloat) (desth-1);
+  else
+    sy = (GLfloat) (srch-1);
+
+  for (i = 0; i < desth; i++)
+  {
+    GLint ii = (GLint)(i * sy);
+    for (j = 0; j < destw; j++)
+    {
+      GLint jj = (GLint)(j * sx);
+      GLubyte *src = old_image + (ii * srcw + jj) * 4;
+      GLubyte *dst = new_image + (i * destw + j) * 4;
+
+      *dst++ = *src++;
+      *dst++ = *src++;
+      *dst++ = *src++;
+      *dst++ = *src++;
+    }
+  }
+
+  return new_image;
+}
+
+#define CEILING(A, B)  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
+
+// NOTE: only supports RGBA, UNSIGNED_BYTE images.
+GLint WINAPI gluBuild2DMipmaps2 (GLenum target, GLint components, GLsizei width, GLsizei height, GLenum format,
+			  GLenum type, const void *data)
+{
+  GLint w, h, level, maxsize, sizein = 1;
+  GLint unpackrowlength, unpackalignment, unpackskiprows, unpackskippixels;
+  GLint packrowlength, packalignment, packskiprows, packskippixels;
+  GLint rowstride, rowlen;
+  GLuint i, j, k, pow2;
+  GLubyte *image, *tmp;
+
+  if (width < 1 || height < 1)
+    return GLU_INVALID_VALUE;
+
+  qglGetIntegerv (GL_UNPACK_ROW_LENGTH, &unpackrowlength);
+  qglGetIntegerv (GL_UNPACK_ALIGNMENT, &unpackalignment);
+  qglGetIntegerv (GL_UNPACK_SKIP_ROWS, &unpackskiprows);
+  qglGetIntegerv (GL_UNPACK_SKIP_PIXELS, &unpackskippixels);
+  qglGetIntegerv (GL_PACK_ROW_LENGTH, &packrowlength);
+  qglGetIntegerv (GL_PACK_ALIGNMENT, &packalignment);
+  qglGetIntegerv (GL_PACK_SKIP_ROWS, &packskiprows);
+  qglGetIntegerv (GL_PACK_SKIP_PIXELS, &packskippixels);
+  qglGetIntegerv (GL_MAX_TEXTURE_SIZE, &maxsize);
+
+  for (pow2 = 1; pow2 < width; pow2 = pow2 << 1);
+  w = (pow2 == width) ? width : (pow2 << 1);
+ 
+  for (pow2 = 1; pow2 < height; pow2 = pow2 << 1);
+  h = (pow2 == height) ? height : (pow2 << 1);
+
+  if (w > maxsize) w = maxsize;
+  if (h > maxsize) h = maxsize;
+
+  // Build RGBA packed image
+  image = malloc (width*height*4);
+  if (image == NULL)
+    return GLU_OUT_OF_MEMORY;
+
+  if ((format != GL_RGBA) || (type != GL_UNSIGNED_BYTE))
+    return GLU_INVALID_ENUM;
+
+  rowlen = (unpackrowlength > 0) ? unpackrowlength : width;
+
+  if (sizein >= unpackalignment)
+    rowstride = components * rowlen;
+  else
+    rowstride = unpackalignment/sizein * CEILING (components * rowlen * sizein, unpackalignment);
+
+  k = 0;
+  for (i = 0; i < height; i++)
+  {
+    GLubyte *ubptr = (GLubyte*)data + i * rowstride
+      + unpackskiprows * rowstride + unpackskippixels * components;
+
+    for (j = 0; j < width*components; j++)
+      image[k++] = *ubptr++;
+  }
+
+  if (w != width || h != height)
+  {
+    tmp = ResizeImage (image, width, height, w, h);
+    free (image);
+    image = tmp;
+
+    if (image == NULL)
+      return GLU_OUT_OF_MEMORY;
+  }
+
+  qglPixelStorei (GL_PACK_ROW_LENGTH, 0);
+  qglPixelStorei (GL_PACK_ALIGNMENT, 1);
+  qglPixelStorei (GL_PACK_SKIP_ROWS, 0);
+  qglPixelStorei (GL_PACK_SKIP_PIXELS, 0);
+  qglPixelStorei (GL_UNPACK_ROW_LENGTH, 0);
+  qglPixelStorei (GL_UNPACK_ALIGNMENT, 1);
+  qglPixelStorei (GL_UNPACK_SKIP_ROWS, 0);
+  qglPixelStorei (GL_UNPACK_SKIP_PIXELS, 0);
+
+  qglTexImage2D (target, 0, components, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
+
+  for (level = 1; ((w != 1) || (h != 1)); level++)
+  {
+    GLubyte *out, *in;
+    int row;
+
+    row = w * 4;
+    if (w != 1) w >>= 1;
+    if (h != 1) h >>= 1;
+    in = out = image;
+
+    for (i = 0; i < h; i++, in+=row)
+      for (j = 0; j < w; j++, out+=4, in+=8)
+      {
+	out[0] = (in[0] + in[4] + in[row+0] + in[row+4])>>2;
+	out[1] = (in[1] + in[5] + in[row+1] + in[row+5])>>2;
+	out[2] = (in[2] + in[6] + in[row+2] + in[row+6])>>2;
+	out[3] = (in[3] + in[7] + in[row+3] + in[row+7])>>2;
+      }
+
+    qglTexImage2D (target, level, components, w, h, 0, GL_RGBA, GL_UNSIGNED_BYTE, image);
+  }
+
+  free (image);
+  qglPixelStorei (GL_UNPACK_ROW_LENGTH, unpackrowlength);
+  qglPixelStorei (GL_UNPACK_ALIGNMENT, unpackalignment);
+  qglPixelStorei (GL_UNPACK_SKIP_ROWS, unpackskiprows);
+  qglPixelStorei (GL_UNPACK_SKIP_PIXELS, unpackskippixels);
+  qglPixelStorei (GL_PACK_ROW_LENGTH, packrowlength);
+  qglPixelStorei (GL_PACK_ALIGNMENT, packalignment);
+  qglPixelStorei (GL_PACK_SKIP_ROWS, packskiprows);
+  qglPixelStorei (GL_PACK_SKIP_PIXELS, packskippixels);
+
+  return 0;
+}
+
+typedef struct glu_error_struct
+{
+    int     errnum;
+    const char *errstr;
+} GLU_ERROR_STRUCT;
+
+GLU_ERROR_STRUCT glu_errlist[] = {
+  {GL_NO_ERROR, "GL_NO_ERROR - no error"},
+  {GL_INVALID_ENUM, "GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument."},
+  {GL_INVALID_VALUE, "GL_INVALID_VALUE - A numeric argument is out of range."},
+  {GL_INVALID_OPERATION, "GL_INVALID_OPERATION - The specified operation is not allowed in the current state."},
+  {GL_STACK_OVERFLOW, "GL_STACK_OVERFLOW - Function would cause a stack overflow."},
+  {GL_STACK_UNDERFLOW, "GL_STACK_UNDERFLOW - Function would cause a stack underflow."},
+  {GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY - There is not enough memory left to execute the function."},
+  {-1, NULL}
+};
+
+const GLubyte* WINAPI gluErrorString(GLenum errCode )
+{
+  int search = 0;
+  for (search = 0; glu_errlist[search].errstr; search++)
+  {
+    if (errCode == glu_errlist[search].errnum)
+      return (const char *)glu_errlist[search].errstr;
+  } //end for
+  return "Unknown error";
+}
+
+int QGL_Init(const char *dllname, const char* gluname)
+{
+#ifdef _WIN32
+  g_hGLDLL = LoadLibrary(dllname); 
+#endif
+
+#if defined (__linux__)
+  char* err;
+
+  g_hGLDLL = dlopen(dllname, RTLD_LAZY|RTLD_GLOBAL);
+  err = dlerror();
+  if (err)
+    printf ("Error loading GL lib:\n%s\n", err);
+#endif
+  init_error = 0;
+
+#ifndef __APPLE__
+  if (g_hGLDLL == NULL)
+    return 0;
+#endif
+
+  Sys_Printf("Loading GL library: %s ...", dllname);
+
+  qgluPerspective              = &gluPerspective2;
+  qgluBuild2DMipmaps           = &gluBuild2DMipmaps2;
+  qgluLookAt                   = &gluLookAt2;
+  qgluErrorString              = &gluErrorString;
+
+  qglAccum                     = glAccum;
+  qglAlphaFunc                 = glAlphaFunc;
+  qglAreTexturesResident       = glAreTexturesResident;
+  qglArrayElement              = glArrayElement;
+  qglBegin                     = glBegin;
+  qglBindTexture               = glBindTexture;
+  qglBitmap                    = glBitmap;
+  qglBlendFunc                 = glBlendFunc;
+  qglCallList                  = glCallList;
+  qglCallLists                 = glCallLists;
+  qglClear                     = glClear;
+  qglClearAccum                = glClearAccum;
+  qglClearColor                = glClearColor;
+  qglClearDepth                = glClearDepth;
+  qglClearIndex                = glClearIndex;
+  qglClearStencil              = glClearStencil;
+  qglClipPlane                 = glClipPlane;
+  qglColor3b                   = glColor3b;
+  qglColor3bv                  = glColor3bv;
+  qglColor3d                   = glColor3d;
+  qglColor3dv                  = glColor3dv;
+  qglColor3f                   = glColor3f;
+  qglColor3fv                  = glColor3fv;
+  qglColor3i                   = glColor3i;
+  qglColor3iv                  = glColor3iv;
+  qglColor3s                   = glColor3s;
+  qglColor3sv                  = glColor3sv;
+  qglColor3ub                  = glColor3ub;
+  qglColor3ubv                 = glColor3ubv;
+  qglColor3ui                  = glColor3ui;
+  qglColor3uiv                 = glColor3uiv;
+  qglColor3us                  = glColor3us;
+  qglColor3usv                 = glColor3usv;
+  qglColor4b                   = glColor4b;
+  qglColor4bv                  = glColor4bv;
+  qglColor4d                   = glColor4d;
+  qglColor4dv                  = glColor4dv;
+  qglColor4f                   = glColor4f;
+  qglColor4fv                  = glColor4fv;
+  qglColor4i                   = glColor4i;
+  qglColor4iv                  = glColor4iv;
+  qglColor4s                   = glColor4s;
+  qglColor4sv                  = glColor4sv;
+  qglColor4ub                  = glColor4ub;
+  qglColor4ubv                 = glColor4ubv;
+  qglColor4ui                  = glColor4ui;
+  qglColor4uiv                 = glColor4uiv;
+  qglColor4us                  = glColor4us;
+  qglColor4usv                 = glColor4usv;
+  qglColorMask                 = glColorMask;
+  qglColorMaterial             = glColorMaterial;
+  qglColorPointer              = glColorPointer;
+  qglCopyPixels                = glCopyPixels;
+  qglCopyTexImage1D            = glCopyTexImage1D;
+  qglCopyTexImage2D            = glCopyTexImage2D;
+  qglCopyTexSubImage1D         = glCopyTexSubImage1D;
+  qglCopyTexSubImage2D         = glCopyTexSubImage2D;
+  qglCullFace                  = glCullFace;
+  qglDeleteLists               = glDeleteLists;
+  qglDeleteTextures            = glDeleteTextures;
+  qglDepthFunc                 = glDepthFunc;
+  qglDepthMask                 = glDepthMask;
+  qglDepthRange                = glDepthRange;
+  qglDisable                   = glDisable;
+  qglDisableClientState        = glDisableClientState;
+  qglDrawArrays                = glDrawArrays;
+  qglDrawBuffer                = glDrawBuffer;
+  qglDrawElements              = glDrawElements;
+  qglDrawPixels                = glDrawPixels;
+  qglEdgeFlag                  = glEdgeFlag;
+  qglEdgeFlagPointer           = glEdgeFlagPointer;
+  qglEdgeFlagv                 = glEdgeFlagv;
+  qglEnable                    = glEnable;
+  qglEnableClientState         = glEnableClientState;
+  qglEnd                       = glEnd;
+  qglEndList                   = glEndList;
+  qglEvalCoord1d	       = glEvalCoord1d;
+  qglEvalCoord1dv              = glEvalCoord1dv;
+  qglEvalCoord1f               = glEvalCoord1f;
+  qglEvalCoord1fv              = glEvalCoord1fv;
+  qglEvalCoord2d               = glEvalCoord2d;
+  qglEvalCoord2dv              = glEvalCoord2dv;
+  qglEvalCoord2f               = glEvalCoord2f;
+  qglEvalCoord2fv              = glEvalCoord2fv;
+  qglEvalMesh1                 = glEvalMesh1;
+  qglEvalMesh2                 = glEvalMesh2;
+  qglEvalPoint1                = glEvalPoint1;
+  qglEvalPoint2                = glEvalPoint2;
+  qglFeedbackBuffer            = glFeedbackBuffer;
+  qglFinish                    = glFinish;
+  qglFlush                     = glFlush;
+  qglFogf                      = glFogf;
+  qglFogfv                     = glFogfv;
+  qglFogi                      = glFogi;
+  qglFogiv                     = glFogiv;
+  qglFrontFace                 = glFrontFace;
+  qglFrustum                   = glFrustum;
+  qglGenLists                  = glGenLists;
+  qglGenTextures               = glGenTextures;
+  qglGetBooleanv               = glGetBooleanv;
+  qglGetClipPlane              = glGetClipPlane;
+  qglGetDoublev                = glGetDoublev;
+  qglGetError                  = glGetError;
+  qglGetFloatv                 = glGetFloatv;
+  qglGetIntegerv               = glGetIntegerv;
+  qglGetLightfv                = glGetLightfv;
+  qglGetLightiv                = glGetLightiv;
+  qglGetMapdv                  = glGetMapdv;
+  qglGetMapfv                  = glGetMapfv;
+  qglGetMapiv                  = glGetMapiv;
+  qglGetMaterialfv             = glGetMaterialfv;
+  qglGetMaterialiv             = glGetMaterialiv;
+  qglGetPixelMapfv             = glGetPixelMapfv;
+  qglGetPixelMapuiv            = glGetPixelMapuiv;
+  qglGetPixelMapusv            = glGetPixelMapusv;
+  qglGetPointerv               = glGetPointerv;
+  qglGetPolygonStipple         = glGetPolygonStipple;
+  qglGetString                 = glGetString;
+  qglGetTexEnvfv               = glGetTexEnvfv;
+  qglGetTexEnviv               = glGetTexEnviv;
+  qglGetTexGendv               = glGetTexGendv;
+  qglGetTexGenfv               = glGetTexGenfv;
+  qglGetTexGeniv               = glGetTexGeniv;
+  qglGetTexImage               = glGetTexImage;
+  qglGetTexLevelParameterfv    = glGetTexLevelParameterfv;
+  qglGetTexLevelParameteriv    = glGetTexLevelParameteriv;
+  qglGetTexParameterfv         = glGetTexParameterfv;
+  qglGetTexParameteriv         = glGetTexParameteriv;
+  qglHint                      = glHint;
+  qglIndexMask                 = glIndexMask;
+  qglIndexPointer              = glIndexPointer;
+  qglIndexd                    = glIndexd;
+  qglIndexdv                   = glIndexdv;
+  qglIndexf                    = glIndexf;
+  qglIndexfv                   = glIndexfv;
+  qglIndexi                    = glIndexi;
+  qglIndexiv                   = glIndexiv;
+  qglIndexs                    = glIndexs;
+  qglIndexsv                   = glIndexsv;
+  qglIndexub                   = glIndexub;
+  qglIndexubv                  = glIndexubv;
+  qglInitNames                 = glInitNames;
+  qglInterleavedArrays         = glInterleavedArrays;
+  qglIsEnabled                 = glIsEnabled;
+  qglIsList                    = glIsList;
+  qglIsTexture                 = glIsTexture;
+  qglLightModelf               = glLightModelf;
+  qglLightModelfv              = glLightModelfv;
+  qglLightModeli               = glLightModeli;
+  qglLightModeliv              = glLightModeliv;
+  qglLightf                    = glLightf;
+  qglLightfv                   = glLightfv;
+  qglLighti                    = glLighti;
+  qglLightiv                   = glLightiv;
+  qglLineStipple               = glLineStipple;
+  qglLineWidth                 = glLineWidth;
+  qglListBase                  = glListBase;
+  qglLoadIdentity              = glLoadIdentity;
+  qglLoadMatrixd               = glLoadMatrixd;
+  qglLoadMatrixf               = glLoadMatrixf;
+  qglLoadName                  = glLoadName;
+  qglLogicOp                   = glLogicOp;
+  qglMap1d                     = glMap1d;
+  qglMap1f                     = glMap1f;
+  qglMap2d                     = glMap2d;
+  qglMap2f                     = glMap2f;
+  qglMapGrid1d                 = glMapGrid1d;
+  qglMapGrid1f                 = glMapGrid1f;
+  qglMapGrid2d                 = glMapGrid2d;
+  qglMapGrid2f                 = glMapGrid2f;
+  qglMaterialf                 = glMaterialf;
+  qglMaterialfv                = glMaterialfv;
+  qglMateriali                 = glMateriali;
+  qglMaterialiv                = glMaterialiv;
+  qglMatrixMode                = glMatrixMode;
+  qglMultMatrixd               = glMultMatrixd;
+  qglMultMatrixf               = glMultMatrixf;
+  qglNewList                   = glNewList;
+  qglNormal3b                  = glNormal3b;
+  qglNormal3bv                 = glNormal3bv;
+  qglNormal3d                  = glNormal3d;
+  qglNormal3dv                 = glNormal3dv;
+  qglNormal3f                  = glNormal3f;
+  qglNormal3fv                 = glNormal3fv;
+  qglNormal3i                  = glNormal3i;
+  qglNormal3iv                 = glNormal3iv;
+  qglNormal3s                  = glNormal3s;
+  qglNormal3sv                 = glNormal3sv;
+  qglNormalPointer             = glNormalPointer;
+  qglOrtho                     = glOrtho;
+  qglPassThrough               = glPassThrough;
+  qglPixelMapfv                = glPixelMapfv;
+  qglPixelMapuiv               = glPixelMapuiv;
+  qglPixelMapusv               = glPixelMapusv;
+  qglPixelStoref               = glPixelStoref;
+  qglPixelStorei               = glPixelStorei;
+  qglPixelTransferf            = glPixelTransferf;
+  qglPixelTransferi            = glPixelTransferi;
+  qglPixelZoom                 = glPixelZoom;
+  qglPointSize                 = glPointSize;
+  qglPolygonMode               = glPolygonMode;
+  qglPolygonOffset             = glPolygonOffset;
+  qglPolygonStipple            = glPolygonStipple;
+  qglPopAttrib                 = glPopAttrib;
+  qglPopClientAttrib           = glPopClientAttrib;
+  qglPopMatrix                 = glPopMatrix;
+  qglPopName                   = glPopName;
+  qglPrioritizeTextures        = glPrioritizeTextures;
+  qglPushAttrib                = glPushAttrib;
+  qglPushClientAttrib          = glPushClientAttrib;
+  qglPushMatrix                = glPushMatrix;
+  qglPushName                  = glPushName;
+  qglRasterPos2d               = glRasterPos2d;
+  qglRasterPos2dv              = glRasterPos2dv;
+  qglRasterPos2f               = glRasterPos2f;
+  qglRasterPos2fv              = glRasterPos2fv;
+  qglRasterPos2i               = glRasterPos2i;
+  qglRasterPos2iv              = glRasterPos2iv;
+  qglRasterPos2s               = glRasterPos2s;
+  qglRasterPos2sv              = glRasterPos2sv;
+  qglRasterPos3d               = glRasterPos3d;
+  qglRasterPos3dv              = glRasterPos3dv;
+  qglRasterPos3f               = glRasterPos3f;
+  qglRasterPos3fv              = glRasterPos3fv;
+  qglRasterPos3i               = glRasterPos3i;
+  qglRasterPos3iv              = glRasterPos3iv;
+  qglRasterPos3s               = glRasterPos3s;
+  qglRasterPos3sv              = glRasterPos3sv;
+  qglRasterPos4d               = glRasterPos4d;
+  qglRasterPos4dv              = glRasterPos4dv;
+  qglRasterPos4f               = glRasterPos4f;
+  qglRasterPos4fv              = glRasterPos4fv;
+  qglRasterPos4i               = glRasterPos4i;
+  qglRasterPos4iv              = glRasterPos4iv;
+  qglRasterPos4s               = glRasterPos4s;
+  qglRasterPos4sv              = glRasterPos4sv;
+  qglReadBuffer                = glReadBuffer;
+  qglReadPixels                = glReadPixels;
+  qglRectd                     = glRectd;
+  qglRectdv                    = glRectdv;
+  qglRectf                     = glRectf;
+  qglRectfv                    = glRectfv;
+  qglRecti                     = glRecti;
+  qglRectiv                    = glRectiv;
+  qglRects                     = glRects;
+  qglRectsv                    = glRectsv;
+  qglRenderMode                = glRenderMode;
+  qglRotated                   = glRotated;
+  qglRotatef                   = glRotatef;
+  qglScaled                    = glScaled;
+  qglScalef                    = glScalef;
+  qglScissor                   = glScissor;
+  qglSelectBuffer              = glSelectBuffer;
+  qglShadeModel                = glShadeModel;
+  qglStencilFunc               = glStencilFunc;
+  qglStencilMask               = glStencilMask;
+  qglStencilOp                 = glStencilOp;
+  qglTexCoord1d                = glTexCoord1d;
+  qglTexCoord1dv               = glTexCoord1dv;
+  qglTexCoord1f                = glTexCoord1f;
+  qglTexCoord1fv               = glTexCoord1fv;
+  qglTexCoord1i                = glTexCoord1i;
+  qglTexCoord1iv               = glTexCoord1iv;
+  qglTexCoord1s                = glTexCoord1s;
+  qglTexCoord1sv               = glTexCoord1sv;
+  qglTexCoord2d                = glTexCoord2d;
+  qglTexCoord2dv               = glTexCoord2dv;
+  qglTexCoord2f                = glTexCoord2f;
+  qglTexCoord2fv               = glTexCoord2fv;
+  qglTexCoord2i                = glTexCoord2i;
+  qglTexCoord2iv               = glTexCoord2iv;
+  qglTexCoord2s                = glTexCoord2s;
+  qglTexCoord2sv               = glTexCoord2sv;
+  qglTexCoord3d                = glTexCoord3d;
+  qglTexCoord3dv               = glTexCoord3dv;
+  qglTexCoord3f                = glTexCoord3f;
+  qglTexCoord3fv               = glTexCoord3fv;
+  qglTexCoord3i                = glTexCoord3i;
+  qglTexCoord3iv               = glTexCoord3iv;
+  qglTexCoord3s                = glTexCoord3s;
+  qglTexCoord3sv               = glTexCoord3sv;
+  qglTexCoord4d                = glTexCoord4d;
+  qglTexCoord4dv               = glTexCoord4dv;
+  qglTexCoord4f                = glTexCoord4f;
+  qglTexCoord4fv               = glTexCoord4fv;
+  qglTexCoord4i                = glTexCoord4i;
+  qglTexCoord4iv               = glTexCoord4iv;
+  qglTexCoord4s                = glTexCoord4s;
+  qglTexCoord4sv               = glTexCoord4sv;
+  qglTexCoordPointer           = glTexCoordPointer;
+  qglTexEnvf                   = glTexEnvf;
+  qglTexEnvfv                  = glTexEnvfv;
+  qglTexEnvi                   = glTexEnvi;
+  qglTexEnviv                  = glTexEnviv;
+  qglTexGend                   = glTexGend;
+  qglTexGendv                  = glTexGendv;
+  qglTexGenf                   = glTexGenf;
+  qglTexGenfv                  = glTexGenfv;
+  qglTexGeni                   = glTexGeni;
+  qglTexGeniv                  = glTexGeniv;
+  qglTexImage1D                = glTexImage1D;
+  qglTexImage2D                = glTexImage2D;
+  qglTexParameterf             = glTexParameterf;
+  qglTexParameterfv            = glTexParameterfv;
+  qglTexParameteri             = glTexParameteri;
+  qglTexParameteriv            = glTexParameteriv;
+  qglTexSubImage1D             = glTexSubImage1D;
+  qglTexSubImage2D             = glTexSubImage2D;
+  qglTranslated                = glTranslated;
+  qglTranslatef                = glTranslatef;
+  qglVertex2d                  = glVertex2d;
+  qglVertex2dv                 = glVertex2dv;
+  qglVertex2f                  = glVertex2f;
+  qglVertex2fv                 = glVertex2fv;
+  qglVertex2i                  = glVertex2i;
+  qglVertex2iv                 = glVertex2iv;
+  qglVertex2s                  = glVertex2s;
+  qglVertex2sv                 = glVertex2sv;
+  qglVertex3d                  = glVertex3d;
+  qglVertex3dv                 = glVertex3dv;
+  qglVertex3f                  = glVertex3f;
+  qglVertex3fv                 = glVertex3fv;
+  qglVertex3i                  = glVertex3i;
+  qglVertex3iv                 = glVertex3iv;
+  qglVertex3s                  = glVertex3s;
+  qglVertex3sv                 = glVertex3sv;
+  qglVertex4d                  = glVertex4d;
+  qglVertex4dv                 = glVertex4dv;
+  qglVertex4f                  = glVertex4f;
+  qglVertex4fv                 = glVertex4fv;
+  qglVertex4i                  = glVertex4i;
+  qglVertex4iv                 = glVertex4iv;
+  qglVertex4s                  = glVertex4s;
+  qglVertex4sv                 = glVertex4sv;
+  qglVertexPointer             = glVertexPointer;
+  qglViewport                  = glViewport;
+
+  // must be init with an active context
+  qglActiveTextureARB = NULL;
+  qglClientActiveTextureARB = NULL;
+  qglMultiTexCoord1dARB = NULL;
+  qglMultiTexCoord1dvARB = NULL;
+  qglMultiTexCoord1fARB = NULL;
+  qglMultiTexCoord1fvARB = NULL;
+  qglMultiTexCoord1iARB = NULL;
+  qglMultiTexCoord1ivARB = NULL;
+  qglMultiTexCoord1sARB = NULL;
+  qglMultiTexCoord1svARB = NULL;
+  qglMultiTexCoord2dARB = NULL;
+  qglMultiTexCoord2dvARB = NULL;
+  qglMultiTexCoord2fARB = NULL;
+  qglMultiTexCoord2fvARB = NULL;
+  qglMultiTexCoord2iARB = NULL;
+  qglMultiTexCoord2ivARB = NULL;
+  qglMultiTexCoord2sARB = NULL;
+  qglMultiTexCoord2svARB = NULL;
+  qglMultiTexCoord3dARB = NULL;
+  qglMultiTexCoord3dvARB = NULL;
+  qglMultiTexCoord3fARB = NULL;
+  qglMultiTexCoord3fvARB = NULL;
+  qglMultiTexCoord3iARB = NULL;
+  qglMultiTexCoord3ivARB = NULL;
+  qglMultiTexCoord3sARB = NULL;
+  qglMultiTexCoord3svARB = NULL;
+  qglMultiTexCoord4dARB = NULL;
+  qglMultiTexCoord4dvARB = NULL;
+  qglMultiTexCoord4fARB = NULL;
+  qglMultiTexCoord4fvARB = NULL;
+  qglMultiTexCoord4iARB = NULL;
+  qglMultiTexCoord4ivARB = NULL;
+  qglMultiTexCoord4sARB = NULL;
+  qglMultiTexCoord4svARB = NULL;
+
+#ifdef _WIN32
+    qwglCopyContext              = safe_dlsym(g_hGLDLL, "wglCopyContext" );
+    qwglCreateContext            = safe_dlsym(g_hGLDLL, "wglCreateContext");
+    qwglCreateLayerContext       = safe_dlsym(g_hGLDLL, "wglCreateLayerContext" );
+    qwglDeleteContext            = safe_dlsym(g_hGLDLL, "wglDeleteContext");
+    qwglDescribeLayerPlane       = safe_dlsym(g_hGLDLL, "wglDescribeLayerPlane" );
+    qwglGetCurrentContext        = safe_dlsym(g_hGLDLL, "wglGetCurrentContext" );
+    qwglGetCurrentDC             = safe_dlsym(g_hGLDLL, "wglGetCurrentDC" );
+    qwglGetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglGetLayerPaletteEntries" );
+    qwglGetProcAddress           = safe_dlsym(g_hGLDLL, "wglGetProcAddress" );
+    qwglMakeCurrent              = safe_dlsym(g_hGLDLL, "wglMakeCurrent" );
+    qwglRealizeLayerPalette      = safe_dlsym(g_hGLDLL, "wglRealizeLayerPalette" );
+    qwglSetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglSetLayerPaletteEntries" );
+    qwglShareLists               = safe_dlsym(g_hGLDLL, "wglShareLists" );
+    qwglSwapLayerBuffers         = safe_dlsym(g_hGLDLL, "wglSwapLayerBuffers" );
+    qwglUseFontBitmaps           = safe_dlsym(g_hGLDLL, "wglUseFontBitmapsA" );
+    qwglUseFontOutlines          = safe_dlsym(g_hGLDLL, "wglUseFontOutlinesA" );
+
+    qwglChoosePixelFormat        = safe_dlsym(g_hGLDLL, "wglChoosePixelFormat" );
+    qwglDescribePixelFormat      = safe_dlsym(g_hGLDLL, "wglDescribePixelFormat" );
+    qwglGetPixelFormat           = safe_dlsym(g_hGLDLL, "wglGetPixelFormat" );
+    qwglSetPixelFormat           = safe_dlsym(g_hGLDLL, "wglSetPixelFormat" );
+    qwglSwapBuffers              = safe_dlsym(g_hGLDLL, "wglSwapBuffers" );
+
+    qwglSwapIntervalEXT = 0;
+    qglPointParameterfEXT = 0;
+    qglPointParameterfvEXT = 0;
+    qglColorTableEXT = 0;
+    qglSelectTextureSGIS = 0;
+    qglMTexCoord2fSGIS = 0;
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+  qglXChooseVisual             = glXChooseVisual;
+  qglXCreateContext            = glXCreateContext;
+  qglXDestroyContext           = glXDestroyContext;
+  qglXMakeCurrent              = glXMakeCurrent;
+  qglXCopyContext              = glXCopyContext;
+  qglXSwapBuffers              = glXSwapBuffers;
+  qglXCreateGLXPixmap          = glXCreateGLXPixmap;
+  qglXDestroyGLXPixmap         = glXDestroyGLXPixmap;
+  qglXQueryExtension           = glXQueryExtension;
+  qglXQueryVersion             = glXQueryVersion;
+  qglXIsDirect                 = glXIsDirect;
+  qglXGetConfig                = glXGetConfig;
+  qglXGetCurrentContext        = glXGetCurrentContext;
+  qglXGetCurrentDrawable       = glXGetCurrentDrawable;
+  qglXWaitGL                   = glXWaitGL;
+  qglXWaitX                    = glXWaitX;
+  qglXUseXFont                 = glXUseXFont;
+  qglXGetProcAddressARB        = glXGetProcAddressARB; // Utah-GLX fix
+#endif
+
+  qglPointParameterfEXT = 0;
+  qglPointParameterfvEXT = 0;
+  qglColorTableEXT = 0;
+  qglSelectTextureSGIS = 0;
+  qglMTexCoord2fSGIS = 0;
+
+  Sys_Printf("Done.\n");
+
+  if (init_error == 1)
+    return 0;
+
+  return 1;
+}
+
+static int GL_ExtensionSupported (const char *extension)
+{
+  const GLubyte *extensions = NULL;
+  const GLubyte *start;
+  GLubyte *where, *terminator;
+
+  // Extension names should not have spaces.
+  where = (GLubyte *) strchr (extension, ' ');
+  if (where || *extension == '\0')
+    return 0;
+
+  extensions = qglGetString (GL_EXTENSIONS);
+
+  // It takes a bit of care to be fool-proof about parsing the
+  // OpenGL extensions string. Don't be fooled by sub-strings, etc.
+  for (start = extensions; ;)
+  {
+    where = (GLubyte *) strstr ((const char *) start, extension);
+    if (!where)
+      break;
+
+    terminator = where + strlen (extension);
+    if (where == start || *(where - 1) == ' ')
+      if (*terminator == ' ' || *terminator == '\0')
+	return 1;
+
+    start = terminator;
+  }
+
+  return 0;
+}
+
+void* Sys_GLGetExtension (const char *symbol)
+{
+#if defined (__linux__) || defined (__APPLE__)
+  if (qglXGetProcAddressARB == NULL)
+    return NULL;
+  else
+    return qglXGetProcAddressARB ((GLubyte*)symbol);
+#else
+  return qwglGetProcAddress (symbol);
+#endif
+}
+
+void QGL_InitExtensions ()
+{
+  if (GL_ExtensionSupported ("GL_ARB_multitexture"))
+  {
+    qglActiveTextureARB = Sys_GLGetExtension ("glActiveTextureARB");
+    qglClientActiveTextureARB = Sys_GLGetExtension ("glClientActiveTextureARB");
+    qglMultiTexCoord1dARB = Sys_GLGetExtension ("glMultiTexCoord1dARB");
+    qglMultiTexCoord1dvARB = Sys_GLGetExtension ("glMultiTexCoord1dvARB");
+    qglMultiTexCoord1fARB = Sys_GLGetExtension ("glMultiTexCoord1fARB");
+    qglMultiTexCoord1fvARB = Sys_GLGetExtension ("glMultiTexCoord1fvARB");
+    qglMultiTexCoord1iARB = Sys_GLGetExtension ("glMultiTexCoord1iARB");
+    qglMultiTexCoord1ivARB = Sys_GLGetExtension ("glMultiTexCoord1ivARB");
+    qglMultiTexCoord1sARB = Sys_GLGetExtension ("glMultiTexCoord1sARB");
+    qglMultiTexCoord1svARB = Sys_GLGetExtension ("glMultiTexCoord1svARB");
+    qglMultiTexCoord2dARB = Sys_GLGetExtension ("glMultiTexCoord2dARB");
+    qglMultiTexCoord2dvARB = Sys_GLGetExtension ("glMultiTexCoord2dvARB");
+    qglMultiTexCoord2fARB = Sys_GLGetExtension ("glMultiTexCoord2fARB");
+    qglMultiTexCoord2fvARB = Sys_GLGetExtension ("glMultiTexCoord2fvARB");
+    qglMultiTexCoord2iARB = Sys_GLGetExtension ("glMultiTexCoord2iARB");
+    qglMultiTexCoord2ivARB = Sys_GLGetExtension ("glMultiTexCoord2ivARB");
+    qglMultiTexCoord2sARB = Sys_GLGetExtension ("glMultiTexCoord2sARB");
+    qglMultiTexCoord2svARB = Sys_GLGetExtension ("glMultiTexCoord2svARB");
+    qglMultiTexCoord3dARB = Sys_GLGetExtension ("glMultiTexCoord3dARB");
+    qglMultiTexCoord3dvARB = Sys_GLGetExtension ("glMultiTexCoord3dvARB");
+    qglMultiTexCoord3fARB = Sys_GLGetExtension ("glMultiTexCoord3fARB");
+    qglMultiTexCoord3fvARB = Sys_GLGetExtension ("glMultiTexCoord3fvARB");
+    qglMultiTexCoord3iARB = Sys_GLGetExtension ("glMultiTexCoord3iARB");
+    qglMultiTexCoord3ivARB = Sys_GLGetExtension ("glMultiTexCoord3ivARB");
+    qglMultiTexCoord3sARB = Sys_GLGetExtension ("glMultiTexCoord3sARB");
+    qglMultiTexCoord3svARB = Sys_GLGetExtension ("glMultiTexCoord3svARB");
+    qglMultiTexCoord4dARB = Sys_GLGetExtension ("glMultiTexCoord4dARB");
+    qglMultiTexCoord4dvARB = Sys_GLGetExtension ("glMultiTexCoord4dvARB");
+    qglMultiTexCoord4fARB = Sys_GLGetExtension ("glMultiTexCoord4fARB");
+    qglMultiTexCoord4fvARB = Sys_GLGetExtension ("glMultiTexCoord4fvARB");
+    qglMultiTexCoord4iARB = Sys_GLGetExtension ("glMultiTexCoord4iARB");
+    qglMultiTexCoord4ivARB = Sys_GLGetExtension ("glMultiTexCoord4ivARB");
+    qglMultiTexCoord4sARB = Sys_GLGetExtension ("glMultiTexCoord4sARB");
+    qglMultiTexCoord4svARB = Sys_GLGetExtension ("glMultiTexCoord4svARB");
+  }
+}
diff --git a/radiant/qgl.c b/radiant/qgl.c
index 6fb4eb5d..d7fd7ce9 100644
--- a/radiant/qgl.c
+++ b/radiant/qgl.c
@@ -1,1797 +1,1797 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-** QGL_WIN.C
-**
-** This file implements the operating system binding of GL to QGL function
-** pointers.  When doing a port of Quake2 you must implement the following
-** two functions:
-**
-** QGL_Init() - loads libraries, assigns function pointers, etc.
-** QGL_Shutdown() - unloads libraries, NULLs function pointers
-*/
-
-/*
- * This causes glDisable(), glEnable(), glCullFace() and glPolygonMode() to
- * be wrapped in order to get around a bug in ATI's FireGL drivers.
- */
-#include <stdio.h>
-#include <float.h>
-#include <string.h>
-#if defined (__linux__) || defined (__APPLE__)
-#include <dlfcn.h>
-#endif
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include "qgl.h"
-void Sys_Printf(const char *format, ...);
-
-#ifdef _WIN32
-HMODULE g_hGLDLL = NULL;
-
-#pragma warning (disable : 4113 4133 4047 4018 )
-
-int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
-int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
-int   ( WINAPI * qwglGetPixelFormat)(HDC);
-BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
-BOOL  ( WINAPI * qwglSwapBuffers)(HDC);
-
-BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
-HGLRC ( WINAPI * qwglCreateContext)(HDC);
-HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
-BOOL  ( WINAPI * qwglDeleteContext)(HGLRC);
-HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
-HDC   ( WINAPI * qwglGetCurrentDC)(VOID);
-PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR);
-BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
-BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
-BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
-
-BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
-				      FLOAT, int, LPGLYPHMETRICSFLOAT);
-
-BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
-int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int, CONST COLORREF *);
-int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int, COLORREF *);
-BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
-BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
-
-BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * );
-BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *,
-					    const unsigned char * );
-BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
-
-#else
-#define WINAPI
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-void* g_hGLDLL;
-
-XVisualInfo* (*qglXChooseVisual)(Display *dpy, int screen, int *attribList);
-GLXContext   (*qglXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
-void         (*qglXDestroyContext)(Display *dpy, GLXContext ctx);
-Bool         (*qglXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
-void         (*qglXCopyContext)(Display *dpy, GLXContext src, GLXContext dst, GLuint mask);
-void         (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable );
-GLXPixmap    (*qglXCreateGLXPixmap)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
-void         (*qglXDestroyGLXPixmap)( Display *dpy, GLXPixmap pixmap );
-Bool         (*qglXQueryExtension)( Display *dpy, int *errorb, int *event );
-Bool         (*qglXQueryVersion)( Display *dpy, int *maj, int *min );
-Bool         (*qglXIsDirect)( Display *dpy, GLXContext ctx );
-int          (*qglXGetConfig)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
-GLXContext   (*qglXGetCurrentContext)( void );
-GLXDrawable  (*qglXGetCurrentDrawable)( void );
-void         (*qglXWaitGL)( void );
-void         (*qglXWaitX)( void );
-void         (*qglXUseXFont)( Font font, int first, int count, int list );
-void*        (*qglXGetProcAddressARB) (const GLubyte *procName);
-#endif
-
-void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
-void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
-GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
-void ( APIENTRY * qglArrayElement )(GLint i);
-void ( APIENTRY * qglBegin )(GLenum mode);
-void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
-void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
-void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
-void ( APIENTRY * qglCallList )(GLuint list);
-void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
-void ( APIENTRY * qglClear )(GLbitfield mask);
-void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-void ( APIENTRY * qglClearDepth )(GLclampd depth);
-void ( APIENTRY * qglClearIndex )(GLfloat c);
-void ( APIENTRY * qglClearStencil )(GLint s);
-void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
-void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
-void ( APIENTRY * qglColor3bv )(const GLbyte *v);
-void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
-void ( APIENTRY * qglColor3dv )(const GLdouble *v);
-void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
-void ( APIENTRY * qglColor3fv )(const GLfloat *v);
-void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
-void ( APIENTRY * qglColor3iv )(const GLint *v);
-void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
-void ( APIENTRY * qglColor3sv )(const GLshort *v);
-void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
-void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
-void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
-void ( APIENTRY * qglColor3uiv )(const GLuint *v);
-void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
-void ( APIENTRY * qglColor3usv )(const GLushort *v);
-void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
-void ( APIENTRY * qglColor4bv )(const GLbyte *v);
-void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
-void ( APIENTRY * qglColor4dv )(const GLdouble *v);
-void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-void ( APIENTRY * qglColor4fv )(const GLfloat *v);
-void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
-void ( APIENTRY * qglColor4iv )(const GLint *v);
-void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
-void ( APIENTRY * qglColor4sv )(const GLshort *v);
-void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
-void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
-void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
-void ( APIENTRY * qglColor4uiv )(const GLuint *v);
-void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
-void ( APIENTRY * qglColor4usv )(const GLushort *v);
-void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
-void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
-void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
-void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-void ( APIENTRY * qglCullFace )(GLenum mode);
-void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
-void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
-void ( APIENTRY * qglDepthFunc )(GLenum func);
-void ( APIENTRY * qglDepthMask )(GLboolean flag);
-void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
-void ( APIENTRY * qglDisable )(GLenum cap);
-void ( APIENTRY * qglDisableClientState )(GLenum array);
-void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
-void ( APIENTRY * qglDrawBuffer )(GLenum mode);
-void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
-void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
-void ( APIENTRY * qglEnable )(GLenum cap);
-void ( APIENTRY * qglEnableClientState )(GLenum array);
-void ( APIENTRY * qglEnd )(void);
-void ( APIENTRY * qglEndList )(void);
-void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
-void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
-void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
-void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
-void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
-void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
-void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
-void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
-void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
-void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
-void ( APIENTRY * qglEvalPoint1 )(GLint i);
-void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
-void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
-void ( APIENTRY * qglFinish )(void);
-void ( APIENTRY * qglFlush )(void);
-void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
-void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
-void ( APIENTRY * qglFrontFace )(GLenum mode);
-void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-GLuint ( APIENTRY * qglGenLists )(GLsizei range);
-void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
-void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
-void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
-void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
-GLenum ( APIENTRY * qglGetError )(void);
-void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
-void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
-void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
-void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
-void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
-void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
-void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
-void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
-void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
-const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
-void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
-void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
-void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
-void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
-void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
-void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
-void ( APIENTRY * qglIndexMask )(GLuint mask);
-void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglIndexd )(GLdouble c);
-void ( APIENTRY * qglIndexdv )(const GLdouble *c);
-void ( APIENTRY * qglIndexf )(GLfloat c);
-void ( APIENTRY * qglIndexfv )(const GLfloat *c);
-void ( APIENTRY * qglIndexi )(GLint c);
-void ( APIENTRY * qglIndexiv )(const GLint *c);
-void ( APIENTRY * qglIndexs )(GLshort c);
-void ( APIENTRY * qglIndexsv )(const GLshort *c);
-void ( APIENTRY * qglIndexub )(GLubyte c);
-void ( APIENTRY * qglIndexubv )(const GLubyte *c);
-void ( APIENTRY * qglInitNames )(void);
-void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
-GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
-GLboolean ( APIENTRY * qglIsList )(GLuint list);
-GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
-void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
-void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
-void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
-void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
-void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
-void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
-void ( APIENTRY * qglLineWidth )(GLfloat width);
-void ( APIENTRY * qglListBase )(GLuint base);
-void ( APIENTRY * qglLoadIdentity )(void);
-void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
-void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
-void ( APIENTRY * qglLoadName )(GLuint name);
-void ( APIENTRY * qglLogicOp )(GLenum opcode);
-void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
-void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
-void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
-void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
-void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
-void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
-void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
-void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
-void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
-void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
-void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
-void ( APIENTRY * qglMatrixMode )(GLenum mode);
-void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
-void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
-void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
-void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
-void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
-void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
-void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
-void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
-void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
-void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
-void ( APIENTRY * qglNormal3iv )(const GLint *v);
-void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
-void ( APIENTRY * qglNormal3sv )(const GLshort *v);
-void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-void ( APIENTRY * qglPassThrough )(GLfloat token);
-void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
-void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
-void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
-void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
-void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
-void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
-void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
-void ( APIENTRY * qglPointSize )(GLfloat size);
-void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
-void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
-void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
-void ( APIENTRY * qglPopAttrib )(void);
-void ( APIENTRY * qglPopClientAttrib )(void);
-void ( APIENTRY * qglPopMatrix )(void);
-void ( APIENTRY * qglPopName )(void);
-void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
-void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
-void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
-void ( APIENTRY * qglPushMatrix )(void);
-void ( APIENTRY * qglPushName )(GLuint name);
-void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
-void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
-void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
-void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
-void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
-void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
-void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
-void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
-void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
-void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
-void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
-void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
-void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
-void ( APIENTRY * qglReadBuffer )(GLenum mode);
-void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
-void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
-void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
-void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
-void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
-void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
-void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
-void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
-void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
-GLint ( APIENTRY * qglRenderMode )(GLenum mode);
-void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
-void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
-void ( APIENTRY * qglShadeModel )(GLenum mode);
-void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
-void ( APIENTRY * qglStencilMask )(GLuint mask);
-void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
-void ( APIENTRY * qglTexCoord1d )(GLdouble s);
-void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord1f )(GLfloat s);
-void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord1i )(GLint s);
-void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord1s )(GLshort s);
-void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
-void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
-void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
-void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
-void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
-void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
-void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
-void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
-void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
-void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
-void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
-void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
-void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
-void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
-void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
-void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
-void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
-void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
-void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
-void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
-void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
-void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
-void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
-void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
-void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
-void ( APIENTRY * qglVertex2iv )(const GLint *v);
-void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
-void ( APIENTRY * qglVertex2sv )(const GLshort *v);
-void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
-void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
-void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
-void ( APIENTRY * qglVertex3iv )(const GLint *v);
-void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
-void ( APIENTRY * qglVertex3sv )(const GLshort *v);
-void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
-void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
-void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
-void ( APIENTRY * qglVertex4iv )(const GLint *v);
-void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-void ( APIENTRY * qglVertex4sv )(const GLshort *v);
-void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
-
-void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
-void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
-void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
-void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
-void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
-
-void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
-void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
-void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
-void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
-void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
-void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
-void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
-void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
-void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
-void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
-void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
-
-// glu stuff
-void (APIENTRY * qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
-
-// added for plugins
-void (APIENTRY * qgluLookAt)(
-  GLdouble eyex,
-  GLdouble eyey,
-  GLdouble eyez,
-  GLdouble centerx,
-  GLdouble centery,
-  GLdouble centerz,
-  GLdouble upx,
-  GLdouble upy,
-  GLdouble upz);
-const GLubyte* (APIENTRY * qgluErrorString) (GLenum errCode );
-
-#ifdef ATIHACK_812
-void ( APIENTRY * qglCullFace_real )(GLenum mode);
-void ( APIENTRY * qglDisable_real )(GLenum cap);
-void ( APIENTRY * qglEnable_real )(GLenum cap);
-void ( APIENTRY * qglPolygonMode_real )(GLenum face, GLenum mode);
-#endif
-
-/*
-** QGL_Shutdown
-**
-** Unloads the specified DLL then nulls out all the proc pointers.
-*/
-void QGL_Shutdown()
-{
-  Sys_Printf("Shutting down GL ...");
-
-  if (g_hGLDLL)
-  {
-#ifdef _WIN32
-    FreeLibrary(g_hGLDLL);
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-    dlclose (g_hGLDLL);
-#endif
-
-    g_hGLDLL = NULL;
-  }
-
-  Sys_Printf("Done.\n");
-
-  qglAccum                     = NULL;
-  qglAlphaFunc                 = NULL;
-  qglAreTexturesResident       = NULL;
-  qglArrayElement              = NULL;
-  qglBegin                     = NULL;
-  qglBindTexture               = NULL;
-  qglBitmap                    = NULL;
-  qglBlendFunc                 = NULL;
-  qglCallList                  = NULL;
-  qglCallLists                 = NULL;
-  qglClear                     = NULL;
-  qglClearAccum                = NULL;
-  qglClearColor                = NULL;
-  qglClearDepth                = NULL;
-  qglClearIndex                = NULL;
-  qglClearStencil              = NULL;
-  qglClipPlane                 = NULL;
-  qglColor3b                   = NULL;
-  qglColor3bv                  = NULL;
-  qglColor3d                   = NULL;
-  qglColor3dv                  = NULL;
-  qglColor3f                   = NULL;
-  qglColor3fv                  = NULL;
-  qglColor3i                   = NULL;
-  qglColor3iv                  = NULL;
-  qglColor3s                   = NULL;
-  qglColor3sv                  = NULL;
-  qglColor3ub                  = NULL;
-  qglColor3ubv                 = NULL;
-  qglColor3ui                  = NULL;
-  qglColor3uiv                 = NULL;
-  qglColor3us                  = NULL;
-  qglColor3usv                 = NULL;
-  qglColor4b                   = NULL;
-  qglColor4bv                  = NULL;
-  qglColor4d                   = NULL;
-  qglColor4dv                  = NULL;
-  qglColor4f                   = NULL;
-  qglColor4fv                  = NULL;
-  qglColor4i                   = NULL;
-  qglColor4iv                  = NULL;
-  qglColor4s                   = NULL;
-  qglColor4sv                  = NULL;
-  qglColor4ub                  = NULL;
-  qglColor4ubv                 = NULL;
-  qglColor4ui                  = NULL;
-  qglColor4uiv                 = NULL;
-  qglColor4us                  = NULL;
-  qglColor4usv                 = NULL;
-  qglColorMask                 = NULL;
-  qglColorMaterial             = NULL;
-  qglColorPointer              = NULL;
-  qglCopyPixels                = NULL;
-  qglCopyTexImage1D            = NULL;
-  qglCopyTexImage2D            = NULL;
-  qglCopyTexSubImage1D         = NULL;
-  qglCopyTexSubImage2D         = NULL;
-  qglCullFace                  = NULL;
-  qglDeleteLists               = NULL;
-  qglDeleteTextures            = NULL;
-  qglDepthFunc                 = NULL;
-  qglDepthMask                 = NULL;
-  qglDepthRange                = NULL;
-  qglDisable                   = NULL;
-  qglDisableClientState        = NULL;
-  qglDrawArrays                = NULL;
-  qglDrawBuffer                = NULL;
-  qglDrawElements              = NULL;
-  qglDrawPixels                = NULL;
-  qglEdgeFlag                  = NULL;
-  qglEdgeFlagPointer           = NULL;
-  qglEdgeFlagv                 = NULL;
-  qglEnable                    = NULL;
-  qglEnableClientState         = NULL;
-  qglEnd                       = NULL;
-  qglEndList                   = NULL;
-  qglEvalCoord1d               = NULL;
-  qglEvalCoord1dv              = NULL;
-  qglEvalCoord1f               = NULL;
-  qglEvalCoord1fv              = NULL;
-  qglEvalCoord2d               = NULL;
-  qglEvalCoord2dv              = NULL;
-  qglEvalCoord2f               = NULL;
-  qglEvalCoord2fv              = NULL;
-  qglEvalMesh1                 = NULL;
-  qglEvalMesh2                 = NULL;
-  qglEvalPoint1                = NULL;
-  qglEvalPoint2                = NULL;
-  qglFeedbackBuffer            = NULL;
-  qglFinish                    = NULL;
-  qglFlush                     = NULL;
-  qglFogf                      = NULL;
-  qglFogfv                     = NULL;
-  qglFogi                      = NULL;
-  qglFogiv                     = NULL;
-  qglFrontFace                 = NULL;
-  qglFrustum                   = NULL;
-  qglGenLists                  = NULL;
-  qglGenTextures               = NULL;
-  qglGetBooleanv               = NULL;
-  qglGetClipPlane              = NULL;
-  qglGetDoublev                = NULL;
-  qglGetError                  = NULL;
-  qglGetFloatv                 = NULL;
-  qglGetIntegerv               = NULL;
-  qglGetLightfv                = NULL;
-  qglGetLightiv                = NULL;
-  qglGetMapdv                  = NULL;
-  qglGetMapfv                  = NULL;
-  qglGetMapiv                  = NULL;
-  qglGetMaterialfv             = NULL;
-  qglGetMaterialiv             = NULL;
-  qglGetPixelMapfv             = NULL;
-  qglGetPixelMapuiv            = NULL;
-  qglGetPixelMapusv            = NULL;
-  qglGetPointerv               = NULL;
-  qglGetPolygonStipple         = NULL;
-  qglGetString                 = NULL;
-  qglGetTexEnvfv               = NULL;
-  qglGetTexEnviv               = NULL;
-  qglGetTexGendv               = NULL;
-  qglGetTexGenfv               = NULL;
-  qglGetTexGeniv               = NULL;
-  qglGetTexImage               = NULL;
-  qglGetTexLevelParameterfv    = NULL;
-  qglGetTexLevelParameteriv    = NULL;
-  qglGetTexParameterfv         = NULL;
-  qglGetTexParameteriv         = NULL;
-  qglHint                      = NULL;
-  qglIndexMask                 = NULL;
-  qglIndexPointer              = NULL;
-  qglIndexd                    = NULL;
-  qglIndexdv                   = NULL;
-  qglIndexf                    = NULL;
-  qglIndexfv                   = NULL;
-  qglIndexi                    = NULL;
-  qglIndexiv                   = NULL;
-  qglIndexs                    = NULL;
-  qglIndexsv                   = NULL;
-  qglIndexub                   = NULL;
-  qglIndexubv                  = NULL;
-  qglInitNames                 = NULL;
-  qglInterleavedArrays         = NULL;
-  qglIsEnabled                 = NULL;
-  qglIsList                    = NULL;
-  qglIsTexture                 = NULL;
-  qglLightModelf               = NULL;
-  qglLightModelfv              = NULL;
-  qglLightModeli               = NULL;
-  qglLightModeliv              = NULL;
-  qglLightf                    = NULL;
-  qglLightfv                   = NULL;
-  qglLighti                    = NULL;
-  qglLightiv                   = NULL;
-  qglLineStipple               = NULL;
-  qglLineWidth                 = NULL;
-  qglListBase                  = NULL;
-  qglLoadIdentity              = NULL;
-  qglLoadMatrixd               = NULL;
-  qglLoadMatrixf               = NULL;
-  qglLoadName                  = NULL;
-  qglLogicOp                   = NULL;
-  qglMap1d                     = NULL;
-  qglMap1f                     = NULL;
-  qglMap2d                     = NULL;
-  qglMap2f                     = NULL;
-  qglMapGrid1d                 = NULL;
-  qglMapGrid1f                 = NULL;
-  qglMapGrid2d                 = NULL;
-  qglMapGrid2f                 = NULL;
-  qglMaterialf                 = NULL;
-  qglMaterialfv                = NULL;
-  qglMateriali                 = NULL;
-  qglMaterialiv                = NULL;
-  qglMatrixMode                = NULL;
-  qglMultMatrixd               = NULL;
-  qglMultMatrixf               = NULL;
-  qglNewList                   = NULL;
-  qglNormal3b                  = NULL;
-  qglNormal3bv                 = NULL;
-  qglNormal3d                  = NULL;
-  qglNormal3dv                 = NULL;
-  qglNormal3f                  = NULL;
-  qglNormal3fv                 = NULL;
-  qglNormal3i                  = NULL;
-  qglNormal3iv                 = NULL;
-  qglNormal3s                  = NULL;
-  qglNormal3sv                 = NULL;
-  qglNormalPointer             = NULL;
-  qglOrtho                     = NULL;
-  qglPassThrough               = NULL;
-  qglPixelMapfv                = NULL;
-  qglPixelMapuiv               = NULL;
-  qglPixelMapusv               = NULL;
-  qglPixelStoref               = NULL;
-  qglPixelStorei               = NULL;
-  qglPixelTransferf            = NULL;
-  qglPixelTransferi            = NULL;
-  qglPixelZoom                 = NULL;
-  qglPointSize                 = NULL;
-  qglPolygonMode               = NULL;
-  qglPolygonOffset             = NULL;
-  qglPolygonStipple            = NULL;
-  qglPopAttrib                 = NULL;
-  qglPopClientAttrib           = NULL;
-  qglPopMatrix                 = NULL;
-  qglPopName                   = NULL;
-  qglPrioritizeTextures        = NULL;
-  qglPushAttrib                = NULL;
-  qglPushClientAttrib          = NULL;
-  qglPushMatrix                = NULL;
-  qglPushName                  = NULL;
-  qglRasterPos2d               = NULL;
-  qglRasterPos2dv              = NULL;
-  qglRasterPos2f               = NULL;
-  qglRasterPos2fv              = NULL;
-  qglRasterPos2i               = NULL;
-  qglRasterPos2iv              = NULL;
-  qglRasterPos2s               = NULL;
-  qglRasterPos2sv              = NULL;
-  qglRasterPos3d               = NULL;
-  qglRasterPos3dv              = NULL;
-  qglRasterPos3f               = NULL;
-  qglRasterPos3fv              = NULL;
-  qglRasterPos3i               = NULL;
-  qglRasterPos3iv              = NULL;
-  qglRasterPos3s               = NULL;
-  qglRasterPos3sv              = NULL;
-  qglRasterPos4d               = NULL;
-  qglRasterPos4dv              = NULL;
-  qglRasterPos4f               = NULL;
-  qglRasterPos4fv              = NULL;
-  qglRasterPos4i               = NULL;
-  qglRasterPos4iv              = NULL;
-  qglRasterPos4s               = NULL;
-  qglRasterPos4sv              = NULL;
-  qglReadBuffer                = NULL;
-  qglReadPixels                = NULL;
-  qglRectd                     = NULL;
-  qglRectdv                    = NULL;
-  qglRectf                     = NULL;
-  qglRectfv                    = NULL;
-  qglRecti                     = NULL;
-  qglRectiv                    = NULL;
-  qglRects                     = NULL;
-  qglRectsv                    = NULL;
-  qglRenderMode                = NULL;
-  qglRotated                   = NULL;
-  qglRotatef                   = NULL;
-  qglScaled                    = NULL;
-  qglScalef                    = NULL;
-  qglScissor                   = NULL;
-  qglSelectBuffer              = NULL;
-  qglShadeModel                = NULL;
-  qglStencilFunc               = NULL;
-  qglStencilMask               = NULL;
-  qglStencilOp                 = NULL;
-  qglTexCoord1d                = NULL;
-  qglTexCoord1dv               = NULL;
-  qglTexCoord1f                = NULL;
-  qglTexCoord1fv               = NULL;
-  qglTexCoord1i                = NULL;
-  qglTexCoord1iv               = NULL;
-  qglTexCoord1s                = NULL;
-  qglTexCoord1sv               = NULL;
-  qglTexCoord2d                = NULL;
-  qglTexCoord2dv               = NULL;
-  qglTexCoord2f                = NULL;
-  qglTexCoord2fv               = NULL;
-  qglTexCoord2i                = NULL;
-  qglTexCoord2iv               = NULL;
-  qglTexCoord2s                = NULL;
-  qglTexCoord2sv               = NULL;
-  qglTexCoord3d                = NULL;
-  qglTexCoord3dv               = NULL;
-  qglTexCoord3f                = NULL;
-  qglTexCoord3fv               = NULL;
-  qglTexCoord3i                = NULL;
-  qglTexCoord3iv               = NULL;
-  qglTexCoord3s                = NULL;
-  qglTexCoord3sv               = NULL;
-  qglTexCoord4d                = NULL;
-  qglTexCoord4dv               = NULL;
-  qglTexCoord4f                = NULL;
-  qglTexCoord4fv               = NULL;
-  qglTexCoord4i                = NULL;
-  qglTexCoord4iv               = NULL;
-  qglTexCoord4s                = NULL;
-  qglTexCoord4sv               = NULL;
-  qglTexCoordPointer           = NULL;
-  qglTexEnvf                   = NULL;
-  qglTexEnvfv                  = NULL;
-  qglTexEnvi                   = NULL;
-  qglTexEnviv                  = NULL;
-  qglTexGend                   = NULL;
-  qglTexGendv                  = NULL;
-  qglTexGenf                   = NULL;
-  qglTexGenfv                  = NULL;
-  qglTexGeni                   = NULL;
-  qglTexGeniv                  = NULL;
-  qglTexImage1D                = NULL;
-  qglTexImage2D                = NULL;
-  qglTexParameterf             = NULL;
-  qglTexParameterfv            = NULL;
-  qglTexParameteri             = NULL;
-  qglTexParameteriv            = NULL;
-  qglTexSubImage1D             = NULL;
-  qglTexSubImage2D             = NULL;
-  qglTranslated                = NULL;
-  qglTranslatef                = NULL;
-  qglVertex2d                  = NULL;
-  qglVertex2dv                 = NULL;
-  qglVertex2f                  = NULL;
-  qglVertex2fv                 = NULL;
-  qglVertex2i                  = NULL;
-  qglVertex2iv                 = NULL;
-  qglVertex2s                  = NULL;
-  qglVertex2sv                 = NULL;
-  qglVertex3d                  = NULL;
-  qglVertex3dv                 = NULL;
-  qglVertex3f                  = NULL;
-  qglVertex3fv                 = NULL;
-  qglVertex3i                  = NULL;
-  qglVertex3iv                 = NULL;
-  qglVertex3s                  = NULL;
-  qglVertex3sv                 = NULL;
-  qglVertex4d                  = NULL;
-  qglVertex4dv                 = NULL;
-  qglVertex4f                  = NULL;
-  qglVertex4fv                 = NULL;
-  qglVertex4i                  = NULL;
-  qglVertex4iv                 = NULL;
-  qglVertex4s                  = NULL;
-  qglVertex4sv                 = NULL;
-  qglVertexPointer             = NULL;
-  qglViewport                  = NULL;
-
-  qglActiveTextureARB = NULL;
-  qglClientActiveTextureARB = NULL;
-  qglMultiTexCoord1dARB = NULL;
-  qglMultiTexCoord1dvARB = NULL;
-  qglMultiTexCoord1fARB = NULL;
-  qglMultiTexCoord1fvARB = NULL;
-  qglMultiTexCoord1iARB = NULL;
-  qglMultiTexCoord1ivARB = NULL;
-  qglMultiTexCoord1sARB = NULL;
-  qglMultiTexCoord1svARB = NULL;
-  qglMultiTexCoord2dARB = NULL;
-  qglMultiTexCoord2dvARB = NULL;
-  qglMultiTexCoord2fARB = NULL;
-  qglMultiTexCoord2fvARB = NULL;
-  qglMultiTexCoord2iARB = NULL;
-  qglMultiTexCoord2ivARB = NULL;
-  qglMultiTexCoord2sARB = NULL;
-  qglMultiTexCoord2svARB = NULL;
-  qglMultiTexCoord3dARB = NULL;
-  qglMultiTexCoord3dvARB = NULL;
-  qglMultiTexCoord3fARB = NULL;
-  qglMultiTexCoord3fvARB = NULL;
-  qglMultiTexCoord3iARB = NULL;
-  qglMultiTexCoord3ivARB = NULL;
-  qglMultiTexCoord3sARB = NULL;
-  qglMultiTexCoord3svARB = NULL;
-  qglMultiTexCoord4dARB = NULL;
-  qglMultiTexCoord4dvARB = NULL;
-  qglMultiTexCoord4fARB = NULL;
-  qglMultiTexCoord4fvARB = NULL;
-  qglMultiTexCoord4iARB = NULL;
-  qglMultiTexCoord4ivARB = NULL;
-  qglMultiTexCoord4sARB = NULL;
-  qglMultiTexCoord4svARB = NULL;
-
-#ifdef _WIN32
-  qwglCopyContext              = NULL;
-  qwglCreateContext            = NULL;
-  qwglCreateLayerContext       = NULL;
-  qwglDeleteContext            = NULL;
-  qwglDescribeLayerPlane       = NULL;
-  qwglGetCurrentContext        = NULL;
-  qwglGetCurrentDC             = NULL;
-  qwglGetLayerPaletteEntries   = NULL;
-  qwglGetProcAddress           = NULL;
-  qwglMakeCurrent              = NULL;
-  qwglRealizeLayerPalette      = NULL;
-  qwglSetLayerPaletteEntries   = NULL;
-  qwglShareLists               = NULL;
-  qwglSwapLayerBuffers         = NULL;
-  qwglUseFontBitmaps           = NULL;
-  qwglUseFontOutlines          = NULL;
-
-  qwglChoosePixelFormat        = NULL;
-  qwglDescribePixelFormat      = NULL;
-  qwglGetPixelFormat           = NULL;
-  qwglSetPixelFormat           = NULL;
-  qwglSwapBuffers              = NULL;
-
-  qwglSwapIntervalEXT          = NULL;
-
-  qwglGetDeviceGammaRampEXT    = NULL;
-  qwglSetDeviceGammaRampEXT    = NULL;
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-  qglXChooseVisual             = NULL;
-  qglXCreateContext            = NULL;
-  qglXDestroyContext           = NULL;
-  qglXMakeCurrent              = NULL;
-  qglXCopyContext              = NULL;
-  qglXSwapBuffers              = NULL;
-  qglXCreateGLXPixmap          = NULL;
-  qglXDestroyGLXPixmap         = NULL;
-  qglXQueryExtension           = NULL;
-  qglXQueryVersion             = NULL;
-  qglXIsDirect                 = NULL;
-  qglXGetConfig                = NULL;
-  qglXGetCurrentContext        = NULL;
-  qglXGetCurrentDrawable       = NULL;
-  qglXWaitGL                   = NULL;
-  qglXWaitX                    = NULL;
-  qglXUseXFont                 = NULL;
-  qglXGetProcAddressARB        = NULL;
-#endif
-
-  qgluPerspective = NULL;
-  qgluErrorString = NULL;
-  qgluLookAt = NULL;
-
-#ifdef ATIHACK_812
-  qglCullFace_real              = NULL;
-  qglDisable_real               = NULL;
-  qglEnable_real                = NULL;
-  qglPolygonMode_real           = NULL;
-#endif
-}
-
-/*
-** QGL_Init
-**
-** This is responsible for binding our qgl function pointers to 
-** the appropriate GL stuff.  In Windows this means doing a 
-** LoadLibrary and a bunch of calls to GetProcAddress.  On other
-** operating systems we need to do the right thing, whatever that
-** might be.
-** 
-*/
-static int init_error;
-
-static void* safe_dlsym (void *handle, char *symbol)
-{
-#ifdef _WIN32
-  return GetProcAddress (handle, symbol);
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-  void* ret = dlsym (handle, symbol);
-  const char *err = dlerror();
-  if (err)
-  {
-    init_error = 1;
-#ifndef __APPLE__
-    printf ("Error loading OpenGL libraries: %s\n", err);
-#else
-    printf ("Error loading OpenGL libraries: %s %s\n", err, symbol);
-#endif
-  }
-  return ret;
-#endif
-}
-
-#include <math.h>
-#include <stdlib.h>
-#ifdef _WIN32
-#define M_PI 3.14159
-#endif
-
-void WINAPI gluLookAt2 (GLdouble ex, GLdouble ey, GLdouble ez, GLdouble cx, GLdouble cy, GLdouble cz,
-		 GLdouble ux, GLdouble uy, GLdouble uz)
-{
-   GLdouble x[3], y[3], z[3] = { ex-cx, ey-cy, ez-cz };
-   GLdouble inv;
-
-   inv = sqrt (z[0]*z[0] + z[1]*z[1] + z[2]*z[2]);
-   if (inv)
-   {
-     inv = 1.0/inv;
-     z[0] *= inv;
-     z[1] *= inv;
-     z[2] *= inv;
-   }
-
-   x[0] =  uy*z[2] - uz*z[1];
-   x[1] = -ux*z[2] + uz*z[0];
-   x[2] =  ux*z[1] - uy*z[0];
-
-   y[0] =  z[1]*x[2] - z[2]*x[1];
-   y[1] = -z[0]*x[2] + z[2]*x[0];
-   y[2] =  z[0]*x[1] - z[1]*x[0];
-
-   inv = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
-   if (inv)
-   {
-     x[0] *= inv;
-     x[1] *= inv;
-     x[2] *= inv;
-   }
-
-   inv = sqrt(y[0]*y[0] + y[1]*y[1] + y[2]*y[2]);
-   if (inv)
-   {
-      y[0] *= inv;
-      y[1] *= inv;
-      y[2] *= inv;
-   }
-
-   {
-   GLdouble m[16] = { x[0], y[0], z[0], 0, x[1], y[1], z[1], 0, x[2], y[2], z[2], 0, 0, 0, 0, 1 };
-   qglMultMatrixd(m);
-   qglTranslated(-ex, -ey, -ez);
-   }
-}
-
-void WINAPI gluPerspective2 (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
-{
-   GLdouble y = zNear * tan (fovy * M_PI / 360.0);
-   qglFrustum (-y*aspect, y*aspect, -y, y, zNear, zFar);
-}
-
-static void* WINAPI ResizeImage (GLubyte* old_image, int srcw, int srch, int destw, int desth)
-{
-  int i, j;
-  float sx, sy;
-  GLubyte* new_image = (GLubyte *)malloc (destw*desth*4*sizeof(GLubyte));
-  if (new_image == NULL)
-    return NULL;
-
-  if (destw > 1)
-    sx = (GLfloat) (srcw-1) / (GLfloat) (destw-1);
-  else
-    sx = (GLfloat) (srcw-1);
-  if (desth > 1)
-    sy = (GLfloat) (srch-1) / (GLfloat) (desth-1);
-  else
-    sy = (GLfloat) (srch-1);
-
-  for (i = 0; i < desth; i++)
-  {
-    GLint ii = (GLint)(i * sy);
-    for (j = 0; j < destw; j++)
-    {
-      GLint jj = (GLint)(j * sx);
-      GLubyte *src = old_image + (ii * srcw + jj) * 4;
-      GLubyte *dst = new_image + (i * destw + j) * 4;
-
-      *dst++ = *src++;
-      *dst++ = *src++;
-      *dst++ = *src++;
-      *dst++ = *src++;
-    }
-  }
-
-  return new_image;
-}
-
-#define CEILING(A, B)  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
-
-typedef struct glu_error_struct
-{
-    int     errnum;
-    const char *errstr;
-} GLU_ERROR_STRUCT;
-
-GLU_ERROR_STRUCT glu_errlist[] = {
-  {GL_NO_ERROR, "GL_NO_ERROR - no error"},
-  {GL_INVALID_ENUM, "GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument."},
-  {GL_INVALID_VALUE, "GL_INVALID_VALUE - A numeric argument is out of range."},
-  {GL_INVALID_OPERATION, "GL_INVALID_OPERATION - The specified operation is not allowed in the current state."},
-  {GL_STACK_OVERFLOW, "GL_STACK_OVERFLOW - Function would cause a stack overflow."},
-  {GL_STACK_UNDERFLOW, "GL_STACK_UNDERFLOW - Function would cause a stack underflow."},
-  {GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY - There is not enough memory left to execute the function."},
-  {-1, NULL}
-};
-
-const GLubyte* WINAPI gluErrorString(GLenum errCode )
-{
-  int search = 0;
-  for (search = 0; glu_errlist[search].errstr; search++)
-  {
-    if (errCode == glu_errlist[search].errnum)
-      return (const char *)glu_errlist[search].errstr;
-  } //end for
-  return "Unknown error";
-}
-
-#ifdef ATIHACK_812
-int ATIhack_culling;
-GLenum ATIhack_cullmode;
-GLenum ATIhack_backmode;
-GLenum ATIhack_frontmode;
-
-static void ATIhack_update(void)
-{
-  if(!ATIhack_culling || (GL_FRONT_AND_BACK == ATIhack_cullmode))
-  {
-    qglPolygonMode_real(GL_FRONT, ATIhack_frontmode);
-    qglPolygonMode_real(GL_BACK, ATIhack_backmode);
-  }
-  else
-    switch(ATIhack_cullmode)
-    {
-      case GL_FRONT:
-        qglPolygonMode_real(GL_FRONT_AND_BACK, ATIhack_backmode);
-        break;
-      case GL_BACK:
-        qglPolygonMode_real(GL_FRONT_AND_BACK, ATIhack_frontmode);
-      default:
-        break;
-    }
-}
-
-void APIENTRY qglEnable_ATIHack(GLenum cap)
-{
-  qglEnable_real(cap);
-  if(GL_CULL_FACE != cap)
-    return;
-  if(ATIhack_culling)
-    return;
-  ATIhack_culling = 1;
-  ATIhack_update();
-}
-
-void APIENTRY qglDisable_ATIHack(GLenum cap)
-{
-  qglDisable_real(cap);
-  if(GL_CULL_FACE != cap)
-    return;
-  if(!ATIhack_culling)
-    return;
-  ATIhack_culling = 0;
-  ATIhack_update();
-}
-
-void APIENTRY qglCullFace_ATIHack(GLenum mode)
-{
-  if(ATIhack_cullmode == mode)
-    return;
-  qglCullFace_real(mode);
-  ATIhack_cullmode = mode;
-  ATIhack_update();
-}
-
-void APIENTRY qglPolygonMode_ATIHack(GLenum face, GLenum mode)
-{
-  switch(face)
-  {
-    case GL_FRONT:
-      if(ATIhack_frontmode == mode)
-        return;
-      ATIhack_frontmode = mode;
-      break;
-    case GL_BACK:
-      if(ATIhack_backmode == mode)
-        return;
-      ATIhack_backmode = mode;
-      break;
-    case GL_FRONT_AND_BACK:
-      if((ATIhack_frontmode == mode) && (ATIhack_backmode == mode))
-        return;
-      ATIhack_frontmode = ATIhack_backmode = mode;
-    default:
-      break;
-  }
-  ATIhack_update();
-}
-#endif
-
-int QGL_Init(const char *dllname, const char* gluname)
-{
-#ifdef _WIN32
-  g_hGLDLL = LoadLibrary(dllname); 
-#endif
-
-#if defined (__linux__) || (__APPLE__)
-  const char *err;
-
-  // NOTE TTimo
-  // I don't like RTLD_LAZY|RTLD_GLOBAL too much .. it's dangerous
-  // maybe try RTLD_NOW? or would that break compatibility .. you never know when that stuff is going to explode
-  g_hGLDLL = dlopen(dllname, RTLD_LAZY|RTLD_GLOBAL);
-  err = dlerror();
-  if (err)
-    printf ("Error loading GL lib:\n%s\n", err);
-#endif
-  init_error = 0;
-
-  if (g_hGLDLL == NULL)
-    return 0;
-
-  Sys_Printf ("Loading GL library: %s ...", dllname);
-
-  qgluPerspective              = &gluPerspective2;
-
-  qgluLookAt                   = &gluLookAt2;
-  qgluErrorString              = &gluErrorString;
-  qglAccum                     = safe_dlsym (g_hGLDLL, "glAccum" );
-  qglAlphaFunc                 = safe_dlsym (g_hGLDLL, "glAlphaFunc" );
-  qglAreTexturesResident       = safe_dlsym (g_hGLDLL, "glAreTexturesResident" );
-  qglArrayElement              = safe_dlsym (g_hGLDLL, "glArrayElement" );
-  qglBegin                     = safe_dlsym (g_hGLDLL, "glBegin" );
-  qglBindTexture               = safe_dlsym (g_hGLDLL, "glBindTexture" );
-  qglBitmap                    = safe_dlsym (g_hGLDLL, "glBitmap" );
-  qglBlendFunc                 = safe_dlsym (g_hGLDLL, "glBlendFunc" );
-  qglCallList                  = safe_dlsym (g_hGLDLL, "glCallList" );
-  qglCallLists                 = safe_dlsym (g_hGLDLL, "glCallLists" );
-  qglClear                     = safe_dlsym (g_hGLDLL, "glClear" );
-  qglClearAccum                = safe_dlsym (g_hGLDLL, "glClearAccum" );
-  qglClearColor                = safe_dlsym (g_hGLDLL, "glClearColor" );
-  qglClearDepth                = safe_dlsym (g_hGLDLL, "glClearDepth" );
-  qglClearIndex                = safe_dlsym (g_hGLDLL, "glClearIndex" );
-  qglClearStencil              = safe_dlsym (g_hGLDLL, "glClearStencil" );
-  qglClipPlane                 = safe_dlsym (g_hGLDLL, "glClipPlane" );
-  qglColor3b                   = safe_dlsym (g_hGLDLL, "glColor3b" );
-  qglColor3bv                  = safe_dlsym (g_hGLDLL, "glColor3bv" );
-  qglColor3d                   = safe_dlsym (g_hGLDLL, "glColor3d" );
-  qglColor3dv                  = safe_dlsym (g_hGLDLL, "glColor3dv" );
-  qglColor3f                   = safe_dlsym (g_hGLDLL, "glColor3f" );
-  qglColor3fv                  = safe_dlsym (g_hGLDLL, "glColor3fv" );
-  qglColor3i                   = safe_dlsym (g_hGLDLL, "glColor3i" );
-  qglColor3iv                  = safe_dlsym (g_hGLDLL, "glColor3iv" );
-  qglColor3s                   = safe_dlsym (g_hGLDLL, "glColor3s" );
-  qglColor3sv                  = safe_dlsym (g_hGLDLL, "glColor3sv" );
-  qglColor3ub                  = safe_dlsym (g_hGLDLL, "glColor3ub" );
-  qglColor3ubv                 = safe_dlsym (g_hGLDLL, "glColor3ubv" );
-  qglColor3ui                  = safe_dlsym (g_hGLDLL, "glColor3ui" );
-  qglColor3uiv                 = safe_dlsym (g_hGLDLL, "glColor3uiv" );
-  qglColor3us                  = safe_dlsym (g_hGLDLL, "glColor3us" );
-  qglColor3usv                 = safe_dlsym (g_hGLDLL, "glColor3usv" );
-  qglColor4b                   = safe_dlsym (g_hGLDLL, "glColor4b" );
-  qglColor4bv                  = safe_dlsym (g_hGLDLL, "glColor4bv" );
-  qglColor4d                   = safe_dlsym (g_hGLDLL, "glColor4d" );
-  qglColor4dv                  = safe_dlsym (g_hGLDLL, "glColor4dv" );
-  qglColor4f                   = safe_dlsym (g_hGLDLL, "glColor4f" );
-  qglColor4fv                  = safe_dlsym (g_hGLDLL, "glColor4fv" );
-  qglColor4i                   = safe_dlsym (g_hGLDLL, "glColor4i" );
-  qglColor4iv                  = safe_dlsym (g_hGLDLL, "glColor4iv" );
-  qglColor4s                   = safe_dlsym (g_hGLDLL, "glColor4s" );
-  qglColor4sv                  = safe_dlsym (g_hGLDLL, "glColor4sv" );
-  qglColor4ub                  = safe_dlsym (g_hGLDLL, "glColor4ub" );
-  qglColor4ubv                 = safe_dlsym (g_hGLDLL, "glColor4ubv" );
-  qglColor4ui                  = safe_dlsym (g_hGLDLL, "glColor4ui" );
-  qglColor4uiv                 = safe_dlsym (g_hGLDLL, "glColor4uiv" );
-  qglColor4us                  = safe_dlsym (g_hGLDLL, "glColor4us" );
-  qglColor4usv                 = safe_dlsym (g_hGLDLL, "glColor4usv" );
-  qglColorMask                 = safe_dlsym (g_hGLDLL, "glColorMask" );
-  qglColorMaterial             = safe_dlsym (g_hGLDLL, "glColorMaterial" );
-  qglColorPointer              = safe_dlsym (g_hGLDLL, "glColorPointer" );
-  qglCopyPixels                = safe_dlsym (g_hGLDLL, "glCopyPixels" );
-  qglCopyTexImage1D            = safe_dlsym (g_hGLDLL, "glCopyTexImage1D" );
-  qglCopyTexImage2D            = safe_dlsym (g_hGLDLL, "glCopyTexImage2D" );
-  qglCopyTexSubImage1D         = safe_dlsym (g_hGLDLL, "glCopyTexSubImage1D" );
-  qglCopyTexSubImage2D         = safe_dlsym (g_hGLDLL, "glCopyTexSubImage2D" );
-#ifdef ATIHACK_812
-  qglCullFace_real              = safe_dlsym (g_hGLDLL, "glCullFace" );
-  qglCullFace                  = qglCullFace_real;
-#else
-  qglCullFace                  = safe_dlsym (g_hGLDLL, "glCullFace" );
-#endif
-  qglDeleteLists               = safe_dlsym (g_hGLDLL, "glDeleteLists" );
-  qglDeleteTextures            = safe_dlsym (g_hGLDLL, "glDeleteTextures" );
-  qglDepthFunc                 = safe_dlsym (g_hGLDLL, "glDepthFunc" );
-  qglDepthMask                 = safe_dlsym (g_hGLDLL, "glDepthMask" );
-  qglDepthRange                = safe_dlsym (g_hGLDLL, "glDepthRange" );
-#ifdef ATIHACK_812
-  qglDisable_real               = safe_dlsym (g_hGLDLL, "glDisable" );
-  qglDisable                   = qglDisable_real;
-#else
-  qglDisable                   = safe_dlsym (g_hGLDLL, "glDisable" );
-#endif
-  qglDisableClientState        = safe_dlsym (g_hGLDLL, "glDisableClientState" );
-  qglDrawArrays                = safe_dlsym (g_hGLDLL, "glDrawArrays" );
-  qglDrawBuffer                = safe_dlsym (g_hGLDLL, "glDrawBuffer" );
-  qglDrawElements              = safe_dlsym (g_hGLDLL, "glDrawElements" );
-  qglDrawPixels                = safe_dlsym (g_hGLDLL, "glDrawPixels" );
-  qglEdgeFlag                  = safe_dlsym (g_hGLDLL, "glEdgeFlag" );
-  qglEdgeFlagPointer           = safe_dlsym (g_hGLDLL, "glEdgeFlagPointer" );
-  qglEdgeFlagv                 = safe_dlsym (g_hGLDLL, "glEdgeFlagv" );
-#ifdef ATIHACK_812
-  qglEnable_real                = safe_dlsym (g_hGLDLL, "glEnable" );
-  qglEnable                    = qglEnable_real;
-#else
-  qglEnable                    = safe_dlsym (g_hGLDLL, "glEnable" );
-#endif
-  qglEnableClientState         = safe_dlsym (g_hGLDLL, "glEnableClientState" );
-  qglEnd                       = safe_dlsym (g_hGLDLL, "glEnd" );
-  qglEndList                   = safe_dlsym (g_hGLDLL, "glEndList" );
-  qglEvalCoord1d               = safe_dlsym (g_hGLDLL, "glEvalCoord1d" );
-  qglEvalCoord1dv              = safe_dlsym (g_hGLDLL, "glEvalCoord1dv" );
-  qglEvalCoord1f               = safe_dlsym (g_hGLDLL, "glEvalCoord1f" );
-  qglEvalCoord1fv              = safe_dlsym (g_hGLDLL, "glEvalCoord1fv" );
-  qglEvalCoord2d               = safe_dlsym (g_hGLDLL, "glEvalCoord2d" );
-  qglEvalCoord2dv              = safe_dlsym (g_hGLDLL, "glEvalCoord2dv" );
-  qglEvalCoord2f               = safe_dlsym (g_hGLDLL, "glEvalCoord2f" );
-  qglEvalCoord2fv              = safe_dlsym (g_hGLDLL, "glEvalCoord2fv" );
-  qglEvalMesh1                 = safe_dlsym (g_hGLDLL, "glEvalMesh1" );
-  qglEvalMesh2                 = safe_dlsym (g_hGLDLL, "glEvalMesh2" );
-  qglEvalPoint1                = safe_dlsym (g_hGLDLL, "glEvalPoint1" );
-  qglEvalPoint2                = safe_dlsym (g_hGLDLL, "glEvalPoint2" );
-  qglFeedbackBuffer            = safe_dlsym (g_hGLDLL, "glFeedbackBuffer" );
-  qglFinish                    = safe_dlsym (g_hGLDLL, "glFinish" );
-  qglFlush                     = safe_dlsym (g_hGLDLL, "glFlush" );
-  qglFogf                      = safe_dlsym (g_hGLDLL, "glFogf" );
-  qglFogfv                     = safe_dlsym (g_hGLDLL, "glFogfv" );
-  qglFogi                      = safe_dlsym (g_hGLDLL, "glFogi" );
-  qglFogiv                     = safe_dlsym (g_hGLDLL, "glFogiv" );
-  qglFrontFace                 = safe_dlsym (g_hGLDLL, "glFrontFace" );
-  qglFrustum                   = safe_dlsym (g_hGLDLL, "glFrustum" );
-  qglGenLists                  = safe_dlsym (g_hGLDLL, "glGenLists" );
-  qglGenTextures               = safe_dlsym (g_hGLDLL, "glGenTextures" );
-  qglGetBooleanv               = safe_dlsym (g_hGLDLL, "glGetBooleanv" );
-  qglGetClipPlane              = safe_dlsym (g_hGLDLL, "glGetClipPlane" );
-  qglGetDoublev                = safe_dlsym (g_hGLDLL, "glGetDoublev" );
-  qglGetError                  = safe_dlsym (g_hGLDLL, "glGetError" );
-  qglGetFloatv                 = safe_dlsym (g_hGLDLL, "glGetFloatv" );
-  qglGetIntegerv               = safe_dlsym (g_hGLDLL, "glGetIntegerv" );
-  qglGetLightfv                = safe_dlsym (g_hGLDLL, "glGetLightfv" );
-  qglGetLightiv                = safe_dlsym (g_hGLDLL, "glGetLightiv" );
-  qglGetMapdv                  = safe_dlsym (g_hGLDLL, "glGetMapdv" );
-  qglGetMapfv                  = safe_dlsym (g_hGLDLL, "glGetMapfv" );
-  qglGetMapiv                  = safe_dlsym (g_hGLDLL, "glGetMapiv" );
-  qglGetMaterialfv             = safe_dlsym (g_hGLDLL, "glGetMaterialfv" );
-  qglGetMaterialiv             = safe_dlsym (g_hGLDLL, "glGetMaterialiv" );
-  qglGetPixelMapfv             = safe_dlsym (g_hGLDLL, "glGetPixelMapfv" );
-  qglGetPixelMapuiv            = safe_dlsym (g_hGLDLL, "glGetPixelMapuiv" );
-  qglGetPixelMapusv            = safe_dlsym (g_hGLDLL, "glGetPixelMapusv" );
-  qglGetPointerv               = safe_dlsym (g_hGLDLL, "glGetPointerv" );
-  qglGetPolygonStipple         = safe_dlsym (g_hGLDLL, "glGetPolygonStipple" );
-  qglGetString                 = safe_dlsym (g_hGLDLL, "glGetString" );
-  qglGetTexEnvfv               = safe_dlsym (g_hGLDLL, "glGetTexEnvfv" );
-  qglGetTexEnviv               = safe_dlsym (g_hGLDLL, "glGetTexEnviv" );
-  qglGetTexGendv               = safe_dlsym (g_hGLDLL, "glGetTexGendv" );
-  qglGetTexGenfv               = safe_dlsym (g_hGLDLL, "glGetTexGenfv" );
-  qglGetTexGeniv               = safe_dlsym (g_hGLDLL, "glGetTexGeniv" );
-  qglGetTexImage               = safe_dlsym (g_hGLDLL, "glGetTexImage" );
-  qglGetTexLevelParameterfv    = safe_dlsym (g_hGLDLL, "glGetTexLevelParameterfv" );
-  qglGetTexLevelParameteriv    = safe_dlsym (g_hGLDLL, "glGetTexLevelParameteriv" );
-  qglGetTexParameterfv         = safe_dlsym (g_hGLDLL, "glGetTexParameterfv" );
-  qglGetTexParameteriv         = safe_dlsym (g_hGLDLL, "glGetTexParameteriv" );
-  qglHint                      = safe_dlsym (g_hGLDLL, "glHint" );
-  qglIndexMask                 = safe_dlsym (g_hGLDLL, "glIndexMask" );
-  qglIndexPointer              = safe_dlsym (g_hGLDLL, "glIndexPointer" );
-  qglIndexd                    = safe_dlsym (g_hGLDLL, "glIndexd" );
-  qglIndexdv                   = safe_dlsym (g_hGLDLL, "glIndexdv" );
-  qglIndexf                    = safe_dlsym (g_hGLDLL, "glIndexf" );
-  qglIndexfv                   = safe_dlsym (g_hGLDLL, "glIndexfv" );
-  qglIndexi                    = safe_dlsym (g_hGLDLL, "glIndexi" );
-  qglIndexiv                   = safe_dlsym (g_hGLDLL, "glIndexiv" );
-  qglIndexs                    = safe_dlsym (g_hGLDLL, "glIndexs" );
-  qglIndexsv                   = safe_dlsym (g_hGLDLL, "glIndexsv" );
-  qglIndexub                   = safe_dlsym (g_hGLDLL, "glIndexub" );
-  qglIndexubv                  = safe_dlsym (g_hGLDLL, "glIndexubv" );
-  qglInitNames                 = safe_dlsym (g_hGLDLL, "glInitNames" );
-  qglInterleavedArrays         = safe_dlsym (g_hGLDLL, "glInterleavedArrays" );
-  qglIsEnabled                 = safe_dlsym (g_hGLDLL, "glIsEnabled" );
-  qglIsList                    = safe_dlsym (g_hGLDLL, "glIsList" );
-  qglIsTexture                 = safe_dlsym (g_hGLDLL, "glIsTexture" );
-  qglLightModelf               = safe_dlsym (g_hGLDLL, "glLightModelf" );
-  qglLightModelfv              = safe_dlsym (g_hGLDLL, "glLightModelfv" );
-  qglLightModeli               = safe_dlsym (g_hGLDLL, "glLightModeli" );
-  qglLightModeliv              = safe_dlsym (g_hGLDLL, "glLightModeliv" );
-  qglLightf                    = safe_dlsym (g_hGLDLL, "glLightf" );
-  qglLightfv                   = safe_dlsym (g_hGLDLL, "glLightfv" );
-  qglLighti                    = safe_dlsym (g_hGLDLL, "glLighti" );
-  qglLightiv                   = safe_dlsym (g_hGLDLL, "glLightiv" );
-  qglLineStipple               = safe_dlsym (g_hGLDLL, "glLineStipple" );
-  qglLineWidth                 = safe_dlsym (g_hGLDLL, "glLineWidth" );
-  qglListBase                  = safe_dlsym (g_hGLDLL, "glListBase" );
-  qglLoadIdentity              = safe_dlsym (g_hGLDLL, "glLoadIdentity" );
-  qglLoadMatrixd               = safe_dlsym (g_hGLDLL, "glLoadMatrixd" );
-  qglLoadMatrixf               = safe_dlsym (g_hGLDLL, "glLoadMatrixf" );
-  qglLoadName                  = safe_dlsym (g_hGLDLL, "glLoadName" );
-  qglLogicOp                   = safe_dlsym (g_hGLDLL, "glLogicOp" );
-  qglMap1d                     = safe_dlsym (g_hGLDLL, "glMap1d" );
-  qglMap1f                     = safe_dlsym (g_hGLDLL, "glMap1f" );
-  qglMap2d                     = safe_dlsym (g_hGLDLL, "glMap2d" );
-  qglMap2f                     = safe_dlsym (g_hGLDLL, "glMap2f" );
-  qglMapGrid1d                 = safe_dlsym (g_hGLDLL, "glMapGrid1d" );
-  qglMapGrid1f                 = safe_dlsym (g_hGLDLL, "glMapGrid1f" );
-  qglMapGrid2d                 = safe_dlsym (g_hGLDLL, "glMapGrid2d" );
-  qglMapGrid2f                 = safe_dlsym (g_hGLDLL, "glMapGrid2f" );
-  qglMaterialf                 = safe_dlsym (g_hGLDLL, "glMaterialf" );
-  qglMaterialfv                = safe_dlsym (g_hGLDLL, "glMaterialfv" );
-  qglMateriali                 = safe_dlsym (g_hGLDLL, "glMateriali" );
-  qglMaterialiv                = safe_dlsym (g_hGLDLL, "glMaterialiv" );
-  qglMatrixMode                = safe_dlsym (g_hGLDLL, "glMatrixMode" );
-  qglMultMatrixd               = safe_dlsym (g_hGLDLL, "glMultMatrixd" );
-  qglMultMatrixf               = safe_dlsym (g_hGLDLL, "glMultMatrixf" );
-  qglNewList                   = safe_dlsym (g_hGLDLL, "glNewList" );
-  qglNormal3b                  = safe_dlsym (g_hGLDLL, "glNormal3b" );
-  qglNormal3bv                 = safe_dlsym (g_hGLDLL, "glNormal3bv" );
-  qglNormal3d                  = safe_dlsym (g_hGLDLL, "glNormal3d" );
-  qglNormal3dv                 = safe_dlsym (g_hGLDLL, "glNormal3dv" );
-  qglNormal3f                  = safe_dlsym (g_hGLDLL, "glNormal3f" );
-  qglNormal3fv                 = safe_dlsym (g_hGLDLL, "glNormal3fv" );
-  qglNormal3i                  = safe_dlsym (g_hGLDLL, "glNormal3i" );
-  qglNormal3iv                 = safe_dlsym (g_hGLDLL, "glNormal3iv" );
-  qglNormal3s                  = safe_dlsym (g_hGLDLL, "glNormal3s" );
-  qglNormal3sv                 = safe_dlsym (g_hGLDLL, "glNormal3sv" );
-  qglNormalPointer             = safe_dlsym (g_hGLDLL, "glNormalPointer" );
-  qglOrtho                     = safe_dlsym (g_hGLDLL, "glOrtho" );
-  qglPassThrough               = safe_dlsym (g_hGLDLL, "glPassThrough" );
-  qglPixelMapfv                = safe_dlsym (g_hGLDLL, "glPixelMapfv" );
-  qglPixelMapuiv               = safe_dlsym (g_hGLDLL, "glPixelMapuiv" );
-  qglPixelMapusv               = safe_dlsym (g_hGLDLL, "glPixelMapusv" );
-  qglPixelStoref               = safe_dlsym (g_hGLDLL, "glPixelStoref" );
-  qglPixelStorei               = safe_dlsym (g_hGLDLL, "glPixelStorei" );
-  qglPixelTransferf            = safe_dlsym (g_hGLDLL, "glPixelTransferf" );
-  qglPixelTransferi            = safe_dlsym (g_hGLDLL, "glPixelTransferi" );
-  qglPixelZoom                 = safe_dlsym (g_hGLDLL, "glPixelZoom" );
-  qglPointSize                 = safe_dlsym (g_hGLDLL, "glPointSize" );
-#ifdef ATIHACK_812
-  qglPolygonMode_real           = safe_dlsym (g_hGLDLL, "glPolygonMode" );
-  qglPolygonMode               = qglPolygonMode_real;
-#else
-  qglPolygonMode               = safe_dlsym (g_hGLDLL, "glPolygonMode" );
-#endif
-  qglPolygonOffset             = safe_dlsym (g_hGLDLL, "glPolygonOffset" );
-  qglPolygonStipple            = safe_dlsym (g_hGLDLL, "glPolygonStipple" );
-  qglPopAttrib                 = safe_dlsym (g_hGLDLL, "glPopAttrib" );
-  qglPopClientAttrib           = safe_dlsym (g_hGLDLL, "glPopClientAttrib" );
-  qglPopMatrix                 = safe_dlsym (g_hGLDLL, "glPopMatrix" );
-  qglPopName                   = safe_dlsym (g_hGLDLL, "glPopName" );
-  qglPrioritizeTextures        = safe_dlsym (g_hGLDLL, "glPrioritizeTextures" );
-  qglPushAttrib                = safe_dlsym (g_hGLDLL, "glPushAttrib" );
-  qglPushClientAttrib          = safe_dlsym (g_hGLDLL, "glPushClientAttrib" );
-  qglPushMatrix                = safe_dlsym (g_hGLDLL, "glPushMatrix" );
-  qglPushName                  = safe_dlsym (g_hGLDLL, "glPushName" );
-  qglRasterPos2d               = safe_dlsym (g_hGLDLL, "glRasterPos2d" );
-  qglRasterPos2dv              = safe_dlsym (g_hGLDLL, "glRasterPos2dv" );
-  qglRasterPos2f               = safe_dlsym (g_hGLDLL, "glRasterPos2f" );
-  qglRasterPos2fv              = safe_dlsym (g_hGLDLL, "glRasterPos2fv" );
-  qglRasterPos2i               = safe_dlsym (g_hGLDLL, "glRasterPos2i" );
-  qglRasterPos2iv              = safe_dlsym (g_hGLDLL, "glRasterPos2iv" );
-  qglRasterPos2s               = safe_dlsym (g_hGLDLL, "glRasterPos2s" );
-  qglRasterPos2sv              = safe_dlsym (g_hGLDLL, "glRasterPos2sv" );
-  qglRasterPos3d               = safe_dlsym (g_hGLDLL, "glRasterPos3d" );
-  qglRasterPos3dv              = safe_dlsym (g_hGLDLL, "glRasterPos3dv" );
-  qglRasterPos3f               = safe_dlsym (g_hGLDLL, "glRasterPos3f" );
-  qglRasterPos3fv              = safe_dlsym (g_hGLDLL, "glRasterPos3fv" );
-  qglRasterPos3i               = safe_dlsym (g_hGLDLL, "glRasterPos3i" );
-  qglRasterPos3iv              = safe_dlsym (g_hGLDLL, "glRasterPos3iv" );
-  qglRasterPos3s               = safe_dlsym (g_hGLDLL, "glRasterPos3s" );
-  qglRasterPos3sv              = safe_dlsym (g_hGLDLL, "glRasterPos3sv" );
-  qglRasterPos4d               = safe_dlsym (g_hGLDLL, "glRasterPos4d" );
-  qglRasterPos4dv              = safe_dlsym (g_hGLDLL, "glRasterPos4dv" );
-  qglRasterPos4f               = safe_dlsym (g_hGLDLL, "glRasterPos4f" );
-  qglRasterPos4fv              = safe_dlsym (g_hGLDLL, "glRasterPos4fv" );
-  qglRasterPos4i               = safe_dlsym (g_hGLDLL, "glRasterPos4i" );
-  qglRasterPos4iv              = safe_dlsym (g_hGLDLL, "glRasterPos4iv" );
-  qglRasterPos4s               = safe_dlsym (g_hGLDLL, "glRasterPos4s" );
-  qglRasterPos4sv              = safe_dlsym (g_hGLDLL, "glRasterPos4sv" );
-  qglReadBuffer                = safe_dlsym (g_hGLDLL, "glReadBuffer" );
-  qglReadPixels                = safe_dlsym (g_hGLDLL, "glReadPixels" );
-  qglRectd                     = safe_dlsym (g_hGLDLL, "glRectd" );
-  qglRectdv                    = safe_dlsym (g_hGLDLL, "glRectdv" );
-  qglRectf                     = safe_dlsym (g_hGLDLL, "glRectf" );
-  qglRectfv                    = safe_dlsym (g_hGLDLL, "glRectfv" );
-  qglRecti                     = safe_dlsym (g_hGLDLL, "glRecti" );
-  qglRectiv                    = safe_dlsym (g_hGLDLL, "glRectiv" );
-  qglRects                     = safe_dlsym (g_hGLDLL, "glRects" );
-  qglRectsv                    = safe_dlsym (g_hGLDLL, "glRectsv" );
-  qglRenderMode                = safe_dlsym (g_hGLDLL, "glRenderMode" );
-  qglRotated                   = safe_dlsym (g_hGLDLL, "glRotated" );
-  qglRotatef                   = safe_dlsym (g_hGLDLL, "glRotatef" );
-  qglScaled                    = safe_dlsym (g_hGLDLL, "glScaled" );
-  qglScalef                    = safe_dlsym (g_hGLDLL, "glScalef" );
-  qglScissor                   = safe_dlsym (g_hGLDLL, "glScissor" );
-  qglSelectBuffer              = safe_dlsym (g_hGLDLL, "glSelectBuffer" );
-  qglShadeModel                = safe_dlsym (g_hGLDLL, "glShadeModel" );
-  qglStencilFunc               = safe_dlsym (g_hGLDLL, "glStencilFunc" );
-  qglStencilMask               = safe_dlsym (g_hGLDLL, "glStencilMask" );
-  qglStencilOp                 = safe_dlsym (g_hGLDLL, "glStencilOp" );
-  qglTexCoord1d                = safe_dlsym (g_hGLDLL, "glTexCoord1d" );
-  qglTexCoord1dv               = safe_dlsym (g_hGLDLL, "glTexCoord1dv" );
-  qglTexCoord1f                = safe_dlsym (g_hGLDLL, "glTexCoord1f" );
-  qglTexCoord1fv               = safe_dlsym (g_hGLDLL, "glTexCoord1fv" );
-  qglTexCoord1i                = safe_dlsym (g_hGLDLL, "glTexCoord1i" );
-  qglTexCoord1iv               = safe_dlsym (g_hGLDLL, "glTexCoord1iv" );
-  qglTexCoord1s                = safe_dlsym (g_hGLDLL, "glTexCoord1s" );
-  qglTexCoord1sv               = safe_dlsym (g_hGLDLL, "glTexCoord1sv" );
-  qglTexCoord2d                = safe_dlsym (g_hGLDLL, "glTexCoord2d" );
-  qglTexCoord2dv               = safe_dlsym (g_hGLDLL, "glTexCoord2dv" );
-  qglTexCoord2f                = safe_dlsym (g_hGLDLL, "glTexCoord2f" );
-  qglTexCoord2fv               = safe_dlsym (g_hGLDLL, "glTexCoord2fv" );
-  qglTexCoord2i                = safe_dlsym (g_hGLDLL, "glTexCoord2i" );
-  qglTexCoord2iv               = safe_dlsym (g_hGLDLL, "glTexCoord2iv" );
-  qglTexCoord2s                = safe_dlsym (g_hGLDLL, "glTexCoord2s" );
-  qglTexCoord2sv               = safe_dlsym (g_hGLDLL, "glTexCoord2sv" );
-  qglTexCoord3d                = safe_dlsym (g_hGLDLL, "glTexCoord3d" );
-  qglTexCoord3dv               = safe_dlsym (g_hGLDLL, "glTexCoord3dv" );
-  qglTexCoord3f                = safe_dlsym (g_hGLDLL, "glTexCoord3f" );
-  qglTexCoord3fv               = safe_dlsym (g_hGLDLL, "glTexCoord3fv" );
-  qglTexCoord3i                = safe_dlsym (g_hGLDLL, "glTexCoord3i" );
-  qglTexCoord3iv               = safe_dlsym (g_hGLDLL, "glTexCoord3iv" );
-  qglTexCoord3s                = safe_dlsym (g_hGLDLL, "glTexCoord3s" );
-  qglTexCoord3sv               = safe_dlsym (g_hGLDLL, "glTexCoord3sv" );
-  qglTexCoord4d                = safe_dlsym (g_hGLDLL, "glTexCoord4d" );
-  qglTexCoord4dv               = safe_dlsym (g_hGLDLL, "glTexCoord4dv" );
-  qglTexCoord4f                = safe_dlsym (g_hGLDLL, "glTexCoord4f" );
-  qglTexCoord4fv               = safe_dlsym (g_hGLDLL, "glTexCoord4fv" );
-  qglTexCoord4i                = safe_dlsym (g_hGLDLL, "glTexCoord4i" );
-  qglTexCoord4iv               = safe_dlsym (g_hGLDLL, "glTexCoord4iv" );
-  qglTexCoord4s                = safe_dlsym (g_hGLDLL, "glTexCoord4s" );
-  qglTexCoord4sv               = safe_dlsym (g_hGLDLL, "glTexCoord4sv" );
-  qglTexCoordPointer           = safe_dlsym (g_hGLDLL, "glTexCoordPointer" );
-  qglTexEnvf                   = safe_dlsym (g_hGLDLL, "glTexEnvf" );
-  qglTexEnvfv                  = safe_dlsym (g_hGLDLL, "glTexEnvfv" );
-  qglTexEnvi                   = safe_dlsym (g_hGLDLL, "glTexEnvi" );
-  qglTexEnviv                  = safe_dlsym (g_hGLDLL, "glTexEnviv" );
-  qglTexGend                   = safe_dlsym (g_hGLDLL, "glTexGend" );
-  qglTexGendv                  = safe_dlsym (g_hGLDLL, "glTexGendv" );
-  qglTexGenf                   = safe_dlsym (g_hGLDLL, "glTexGenf" );
-  qglTexGenfv                  = safe_dlsym (g_hGLDLL, "glTexGenfv" );
-  qglTexGeni                   = safe_dlsym (g_hGLDLL, "glTexGeni" );
-  qglTexGeniv                  = safe_dlsym (g_hGLDLL, "glTexGeniv" );
-  qglTexImage1D                = safe_dlsym (g_hGLDLL, "glTexImage1D" );
-  qglTexImage2D                = safe_dlsym (g_hGLDLL, "glTexImage2D" );
-  qglTexParameterf             = safe_dlsym (g_hGLDLL, "glTexParameterf" );
-  qglTexParameterfv            = safe_dlsym (g_hGLDLL, "glTexParameterfv" );
-  qglTexParameteri             = safe_dlsym (g_hGLDLL, "glTexParameteri" );
-  qglTexParameteriv            = safe_dlsym (g_hGLDLL, "glTexParameteriv" );
-  qglTexSubImage1D             = safe_dlsym (g_hGLDLL, "glTexSubImage1D" );
-  qglTexSubImage2D             = safe_dlsym (g_hGLDLL, "glTexSubImage2D" );
-  qglTranslated                = safe_dlsym (g_hGLDLL, "glTranslated" );
-  qglTranslatef                = safe_dlsym (g_hGLDLL, "glTranslatef" );
-  qglVertex2d                  = safe_dlsym (g_hGLDLL, "glVertex2d" );
-  qglVertex2dv                 = safe_dlsym (g_hGLDLL, "glVertex2dv" );
-  qglVertex2f                  = safe_dlsym (g_hGLDLL, "glVertex2f" );
-  qglVertex2fv                 = safe_dlsym (g_hGLDLL, "glVertex2fv" );
-  qglVertex2i                  = safe_dlsym (g_hGLDLL, "glVertex2i" );
-  qglVertex2iv                 = safe_dlsym (g_hGLDLL, "glVertex2iv" );
-  qglVertex2s                  = safe_dlsym (g_hGLDLL, "glVertex2s" );
-  qglVertex2sv                 = safe_dlsym (g_hGLDLL, "glVertex2sv" );
-  qglVertex3d                  = safe_dlsym (g_hGLDLL, "glVertex3d" );
-  qglVertex3dv                 = safe_dlsym (g_hGLDLL, "glVertex3dv" );
-  qglVertex3f                  = safe_dlsym (g_hGLDLL, "glVertex3f" );
-  qglVertex3fv                 = safe_dlsym (g_hGLDLL, "glVertex3fv" );
-  qglVertex3i                  = safe_dlsym (g_hGLDLL, "glVertex3i" );
-  qglVertex3iv                 = safe_dlsym (g_hGLDLL, "glVertex3iv" );
-  qglVertex3s                  = safe_dlsym (g_hGLDLL, "glVertex3s" );
-  qglVertex3sv                 = safe_dlsym (g_hGLDLL, "glVertex3sv" );
-  qglVertex4d                  = safe_dlsym (g_hGLDLL, "glVertex4d" );
-  qglVertex4dv                 = safe_dlsym (g_hGLDLL, "glVertex4dv" );
-  qglVertex4f                  = safe_dlsym (g_hGLDLL, "glVertex4f" );
-  qglVertex4fv                 = safe_dlsym (g_hGLDLL, "glVertex4fv" );
-  qglVertex4i                  = safe_dlsym (g_hGLDLL, "glVertex4i" );
-  qglVertex4iv                 = safe_dlsym (g_hGLDLL, "glVertex4iv" );
-  qglVertex4s                  = safe_dlsym (g_hGLDLL, "glVertex4s" );
-  qglVertex4sv                 = safe_dlsym (g_hGLDLL, "glVertex4sv" );
-  qglVertexPointer             = safe_dlsym (g_hGLDLL, "glVertexPointer" );
-  qglViewport                  = safe_dlsym (g_hGLDLL, "glViewport" );
-
-  // must be init with an active context
-  qglActiveTextureARB = NULL;
-  qglClientActiveTextureARB = NULL;
-  qglMultiTexCoord1dARB = NULL;
-  qglMultiTexCoord1dvARB = NULL;
-  qglMultiTexCoord1fARB = NULL;
-  qglMultiTexCoord1fvARB = NULL;
-  qglMultiTexCoord1iARB = NULL;
-  qglMultiTexCoord1ivARB = NULL;
-  qglMultiTexCoord1sARB = NULL;
-  qglMultiTexCoord1svARB = NULL;
-  qglMultiTexCoord2dARB = NULL;
-  qglMultiTexCoord2dvARB = NULL;
-  qglMultiTexCoord2fARB = NULL;
-  qglMultiTexCoord2fvARB = NULL;
-  qglMultiTexCoord2iARB = NULL;
-  qglMultiTexCoord2ivARB = NULL;
-  qglMultiTexCoord2sARB = NULL;
-  qglMultiTexCoord2svARB = NULL;
-  qglMultiTexCoord3dARB = NULL;
-  qglMultiTexCoord3dvARB = NULL;
-  qglMultiTexCoord3fARB = NULL;
-  qglMultiTexCoord3fvARB = NULL;
-  qglMultiTexCoord3iARB = NULL;
-  qglMultiTexCoord3ivARB = NULL;
-  qglMultiTexCoord3sARB = NULL;
-  qglMultiTexCoord3svARB = NULL;
-  qglMultiTexCoord4dARB = NULL;
-  qglMultiTexCoord4dvARB = NULL;
-  qglMultiTexCoord4fARB = NULL;
-  qglMultiTexCoord4fvARB = NULL;
-  qglMultiTexCoord4iARB = NULL;
-  qglMultiTexCoord4ivARB = NULL;
-  qglMultiTexCoord4sARB = NULL;
-  qglMultiTexCoord4svARB = NULL;
-
-#ifdef _WIN32
-    qwglCopyContext              = safe_dlsym(g_hGLDLL, "wglCopyContext" );
-    qwglCreateContext            = safe_dlsym(g_hGLDLL, "wglCreateContext");
-    qwglCreateLayerContext       = safe_dlsym(g_hGLDLL, "wglCreateLayerContext" );
-    qwglDeleteContext            = safe_dlsym(g_hGLDLL, "wglDeleteContext");
-    qwglDescribeLayerPlane       = safe_dlsym(g_hGLDLL, "wglDescribeLayerPlane" );
-    qwglGetCurrentContext        = safe_dlsym(g_hGLDLL, "wglGetCurrentContext" );
-    qwglGetCurrentDC             = safe_dlsym(g_hGLDLL, "wglGetCurrentDC" );
-    qwglGetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglGetLayerPaletteEntries" );
-    qwglGetProcAddress           = safe_dlsym(g_hGLDLL, "wglGetProcAddress" );
-    qwglMakeCurrent              = safe_dlsym(g_hGLDLL, "wglMakeCurrent" );
-    qwglRealizeLayerPalette      = safe_dlsym(g_hGLDLL, "wglRealizeLayerPalette" );
-    qwglSetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglSetLayerPaletteEntries" );
-    qwglShareLists               = safe_dlsym(g_hGLDLL, "wglShareLists" );
-    qwglSwapLayerBuffers         = safe_dlsym(g_hGLDLL, "wglSwapLayerBuffers" );
-    qwglUseFontBitmaps           = safe_dlsym(g_hGLDLL, "wglUseFontBitmapsA" );
-    qwglUseFontOutlines          = safe_dlsym(g_hGLDLL, "wglUseFontOutlinesA" );
-
-    qwglChoosePixelFormat        = safe_dlsym(g_hGLDLL, "wglChoosePixelFormat" );
-    qwglDescribePixelFormat      = safe_dlsym(g_hGLDLL, "wglDescribePixelFormat" );
-    qwglGetPixelFormat           = safe_dlsym(g_hGLDLL, "wglGetPixelFormat" );
-    qwglSetPixelFormat           = safe_dlsym(g_hGLDLL, "wglSetPixelFormat" );
-    qwglSwapBuffers              = safe_dlsym(g_hGLDLL, "wglSwapBuffers" );
-
-    qwglSwapIntervalEXT = 0;
-    qglPointParameterfEXT = 0;
-    qglPointParameterfvEXT = 0;
-    qglColorTableEXT = 0;
-    qglSelectTextureSGIS = 0;
-    qglMTexCoord2fSGIS = 0;
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-  qglXChooseVisual             = safe_dlsym (g_hGLDLL, "glXChooseVisual");
-  qglXCreateContext            = safe_dlsym (g_hGLDLL, "glXCreateContext");
-  qglXDestroyContext           = safe_dlsym (g_hGLDLL, "glXDestroyContext");
-  qglXMakeCurrent              = safe_dlsym (g_hGLDLL, "glXMakeCurrent");
-  qglXCopyContext              = safe_dlsym (g_hGLDLL, "glXCopyContext");
-  qglXSwapBuffers              = safe_dlsym (g_hGLDLL, "glXSwapBuffers");
-  qglXCreateGLXPixmap          = safe_dlsym (g_hGLDLL, "glXCreateGLXPixmap");
-  qglXDestroyGLXPixmap         = safe_dlsym (g_hGLDLL, "glXDestroyGLXPixmap");
-  qglXQueryExtension           = safe_dlsym (g_hGLDLL, "glXQueryExtension");
-  qglXQueryVersion             = safe_dlsym (g_hGLDLL, "glXQueryVersion");
-  qglXIsDirect                 = safe_dlsym (g_hGLDLL, "glXIsDirect");
-  qglXGetConfig                = safe_dlsym (g_hGLDLL, "glXGetConfig");
-  qglXGetCurrentContext        = safe_dlsym (g_hGLDLL, "glXGetCurrentContext");
-  qglXGetCurrentDrawable       = safe_dlsym (g_hGLDLL, "glXGetCurrentDrawable");
-  qglXWaitGL                   = safe_dlsym (g_hGLDLL, "glXWaitGL");
-  qglXWaitX                    = safe_dlsym (g_hGLDLL, "glXWaitX");
-  qglXUseXFont                 = safe_dlsym (g_hGLDLL, "glXUseXFont");
-//  qglXGetProcAddressARB        = dlsym (g_hGLDLL, "glXGetProcAddressARB"); // Utah-GLX fix
-#endif
-
-  qglPointParameterfEXT = 0;
-  qglPointParameterfvEXT = 0;
-  qglColorTableEXT = 0;
-  qglSelectTextureSGIS = 0;
-  qglMTexCoord2fSGIS = 0;
-
-  // texture compression 
-  Sys_Printf ("Done.\n");
-
-#ifdef ATIHACK_812
-  ATIhack_culling = 0;
-  ATIhack_cullmode = GL_BACK;
-  ATIhack_backmode = GL_FILL;
-  ATIhack_frontmode = GL_FILL;
-#endif
-
-  if (init_error == 1)
-    return 0;
-
-  return 1;
-}
-
-int GL_ExtensionSupported (const char *extension)
-{
-  const GLubyte *extensions = NULL;
-  const GLubyte *start;
-  GLubyte *where, *terminator;
-
-  // Extension names should not have spaces.
-  where = (GLubyte *) strchr (extension, ' ');
-  if (where || *extension == '\0')
-    return 0;
-
-  extensions = qglGetString (GL_EXTENSIONS);
-#ifndef __APPLE__
-  if (!extensions)
-    return 0;
-#endif
-
-  // It takes a bit of care to be fool-proof about parsing the
-  // OpenGL extensions string. Don't be fooled by sub-strings, etc.
-  for (start = extensions; ;)
-  {
-    where = (GLubyte *) strstr ((const char *) start, extension);
-    if (!where)
-      break;
-
-    terminator = where + strlen (extension);
-    if (where == start || *(where - 1) == ' ')
-      if (*terminator == ' ' || *terminator == '\0')
-        return 1;
-
-    start = terminator;
-  }
-
-  return 0;
-}
-
-void* Sys_GLGetExtension (const char *symbol)
-{
-#if defined (__linux__) || defined (__APPLE__)
-  if (qglXGetProcAddressARB == NULL)
-    return NULL;
-  else
-    return qglXGetProcAddressARB ((GLubyte*)symbol);
-#else
-  return qwglGetProcAddress (symbol);
-#endif
-}
-
-void QGL_InitExtensions ()
-{
-  if (GL_ExtensionSupported ("GL_ARB_multitexture"))
-  {
-    qglActiveTextureARB = Sys_GLGetExtension ("glActiveTextureARB");
-    qglClientActiveTextureARB = Sys_GLGetExtension ("glClientActiveTextureARB");
-    qglMultiTexCoord1dARB = Sys_GLGetExtension ("glMultiTexCoord1dARB");
-    qglMultiTexCoord1dvARB = Sys_GLGetExtension ("glMultiTexCoord1dvARB");
-    qglMultiTexCoord1fARB = Sys_GLGetExtension ("glMultiTexCoord1fARB");
-    qglMultiTexCoord1fvARB = Sys_GLGetExtension ("glMultiTexCoord1fvARB");
-    qglMultiTexCoord1iARB = Sys_GLGetExtension ("glMultiTexCoord1iARB");
-    qglMultiTexCoord1ivARB = Sys_GLGetExtension ("glMultiTexCoord1ivARB");
-    qglMultiTexCoord1sARB = Sys_GLGetExtension ("glMultiTexCoord1sARB");
-    qglMultiTexCoord1svARB = Sys_GLGetExtension ("glMultiTexCoord1svARB");
-    qglMultiTexCoord2dARB = Sys_GLGetExtension ("glMultiTexCoord2dARB");
-    qglMultiTexCoord2dvARB = Sys_GLGetExtension ("glMultiTexCoord2dvARB");
-    qglMultiTexCoord2fARB = Sys_GLGetExtension ("glMultiTexCoord2fARB");
-    qglMultiTexCoord2fvARB = Sys_GLGetExtension ("glMultiTexCoord2fvARB");
-    qglMultiTexCoord2iARB = Sys_GLGetExtension ("glMultiTexCoord2iARB");
-    qglMultiTexCoord2ivARB = Sys_GLGetExtension ("glMultiTexCoord2ivARB");
-    qglMultiTexCoord2sARB = Sys_GLGetExtension ("glMultiTexCoord2sARB");
-    qglMultiTexCoord2svARB = Sys_GLGetExtension ("glMultiTexCoord2svARB");
-    qglMultiTexCoord3dARB = Sys_GLGetExtension ("glMultiTexCoord3dARB");
-    qglMultiTexCoord3dvARB = Sys_GLGetExtension ("glMultiTexCoord3dvARB");
-    qglMultiTexCoord3fARB = Sys_GLGetExtension ("glMultiTexCoord3fARB");
-    qglMultiTexCoord3fvARB = Sys_GLGetExtension ("glMultiTexCoord3fvARB");
-    qglMultiTexCoord3iARB = Sys_GLGetExtension ("glMultiTexCoord3iARB");
-    qglMultiTexCoord3ivARB = Sys_GLGetExtension ("glMultiTexCoord3ivARB");
-    qglMultiTexCoord3sARB = Sys_GLGetExtension ("glMultiTexCoord3sARB");
-    qglMultiTexCoord3svARB = Sys_GLGetExtension ("glMultiTexCoord3svARB");
-    qglMultiTexCoord4dARB = Sys_GLGetExtension ("glMultiTexCoord4dARB");
-    qglMultiTexCoord4dvARB = Sys_GLGetExtension ("glMultiTexCoord4dvARB");
-    qglMultiTexCoord4fARB = Sys_GLGetExtension ("glMultiTexCoord4fARB");
-    qglMultiTexCoord4fvARB = Sys_GLGetExtension ("glMultiTexCoord4fvARB");
-    qglMultiTexCoord4iARB = Sys_GLGetExtension ("glMultiTexCoord4iARB");
-    qglMultiTexCoord4ivARB = Sys_GLGetExtension ("glMultiTexCoord4ivARB");
-    qglMultiTexCoord4sARB = Sys_GLGetExtension ("glMultiTexCoord4sARB");
-    qglMultiTexCoord4svARB = Sys_GLGetExtension ("glMultiTexCoord4svARB");
-  }
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+** QGL_WIN.C
+**
+** This file implements the operating system binding of GL to QGL function
+** pointers.  When doing a port of Quake2 you must implement the following
+** two functions:
+**
+** QGL_Init() - loads libraries, assigns function pointers, etc.
+** QGL_Shutdown() - unloads libraries, NULLs function pointers
+*/
+
+/*
+ * This causes glDisable(), glEnable(), glCullFace() and glPolygonMode() to
+ * be wrapped in order to get around a bug in ATI's FireGL drivers.
+ */
+#include <stdio.h>
+#include <float.h>
+#include <string.h>
+#if defined (__linux__) || defined (__APPLE__)
+#include <dlfcn.h>
+#endif
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#include "qgl.h"
+void Sys_Printf(const char *format, ...);
+
+#ifdef _WIN32
+HMODULE g_hGLDLL = NULL;
+
+#pragma warning (disable : 4113 4133 4047 4018 )
+
+int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
+int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+int   ( WINAPI * qwglGetPixelFormat)(HDC);
+BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
+BOOL  ( WINAPI * qwglSwapBuffers)(HDC);
+
+BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
+HGLRC ( WINAPI * qwglCreateContext)(HDC);
+HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
+BOOL  ( WINAPI * qwglDeleteContext)(HGLRC);
+HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
+HDC   ( WINAPI * qwglGetCurrentDC)(VOID);
+PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR);
+BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
+BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
+BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
+
+BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
+				      FLOAT, int, LPGLYPHMETRICSFLOAT);
+
+BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT, LPLAYERPLANEDESCRIPTOR);
+int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int, CONST COLORREF *);
+int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int, COLORREF *);
+BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
+BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
+
+BOOL ( WINAPI * qwglGetDeviceGammaRampEXT)( unsigned char *, unsigned char *, unsigned char * );
+BOOL ( WINAPI * qwglSetDeviceGammaRampEXT)( const unsigned char *, const unsigned char *,
+					    const unsigned char * );
+BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
+
+#else
+#define WINAPI
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+void* g_hGLDLL;
+
+XVisualInfo* (*qglXChooseVisual)(Display *dpy, int screen, int *attribList);
+GLXContext   (*qglXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+void         (*qglXDestroyContext)(Display *dpy, GLXContext ctx);
+Bool         (*qglXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
+void         (*qglXCopyContext)(Display *dpy, GLXContext src, GLXContext dst, GLuint mask);
+void         (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable );
+GLXPixmap    (*qglXCreateGLXPixmap)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
+void         (*qglXDestroyGLXPixmap)( Display *dpy, GLXPixmap pixmap );
+Bool         (*qglXQueryExtension)( Display *dpy, int *errorb, int *event );
+Bool         (*qglXQueryVersion)( Display *dpy, int *maj, int *min );
+Bool         (*qglXIsDirect)( Display *dpy, GLXContext ctx );
+int          (*qglXGetConfig)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
+GLXContext   (*qglXGetCurrentContext)( void );
+GLXDrawable  (*qglXGetCurrentDrawable)( void );
+void         (*qglXWaitGL)( void );
+void         (*qglXWaitX)( void );
+void         (*qglXUseXFont)( Font font, int first, int count, int list );
+void*        (*qglXGetProcAddressARB) (const GLubyte *procName);
+#endif
+
+void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
+void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
+GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+void ( APIENTRY * qglArrayElement )(GLint i);
+void ( APIENTRY * qglBegin )(GLenum mode);
+void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
+void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
+void ( APIENTRY * qglCallList )(GLuint list);
+void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+void ( APIENTRY * qglClear )(GLbitfield mask);
+void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+void ( APIENTRY * qglClearDepth )(GLclampd depth);
+void ( APIENTRY * qglClearIndex )(GLfloat c);
+void ( APIENTRY * qglClearStencil )(GLint s);
+void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
+void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+void ( APIENTRY * qglColor3bv )(const GLbyte *v);
+void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+void ( APIENTRY * qglColor3dv )(const GLdouble *v);
+void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+void ( APIENTRY * qglColor3fv )(const GLfloat *v);
+void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
+void ( APIENTRY * qglColor3iv )(const GLint *v);
+void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
+void ( APIENTRY * qglColor3sv )(const GLshort *v);
+void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
+void ( APIENTRY * qglColor3uiv )(const GLuint *v);
+void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
+void ( APIENTRY * qglColor3usv )(const GLushort *v);
+void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+void ( APIENTRY * qglColor4bv )(const GLbyte *v);
+void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+void ( APIENTRY * qglColor4dv )(const GLdouble *v);
+void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+void ( APIENTRY * qglColor4fv )(const GLfloat *v);
+void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+void ( APIENTRY * qglColor4iv )(const GLint *v);
+void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+void ( APIENTRY * qglColor4sv )(const GLshort *v);
+void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
+void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+void ( APIENTRY * qglColor4uiv )(const GLuint *v);
+void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+void ( APIENTRY * qglColor4usv )(const GLushort *v);
+void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
+void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglCullFace )(GLenum mode);
+void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
+void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
+void ( APIENTRY * qglDepthFunc )(GLenum func);
+void ( APIENTRY * qglDepthMask )(GLboolean flag);
+void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
+void ( APIENTRY * qglDisable )(GLenum cap);
+void ( APIENTRY * qglDisableClientState )(GLenum array);
+void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
+void ( APIENTRY * qglDrawBuffer )(GLenum mode);
+void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
+void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
+void ( APIENTRY * qglEnable )(GLenum cap);
+void ( APIENTRY * qglEnableClientState )(GLenum array);
+void ( APIENTRY * qglEnd )(void);
+void ( APIENTRY * qglEndList )(void);
+void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
+void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
+void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
+void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
+void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
+void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
+void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+void ( APIENTRY * qglEvalPoint1 )(GLint i);
+void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
+void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+void ( APIENTRY * qglFinish )(void);
+void ( APIENTRY * qglFlush )(void);
+void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
+void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglFrontFace )(GLenum mode);
+void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+GLuint ( APIENTRY * qglGenLists )(GLsizei range);
+void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
+void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
+void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
+void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
+GLenum ( APIENTRY * qglGetError )(void);
+void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
+void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
+void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
+void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
+void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
+void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
+void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
+const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
+void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
+void ( APIENTRY * qglIndexMask )(GLuint mask);
+void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglIndexd )(GLdouble c);
+void ( APIENTRY * qglIndexdv )(const GLdouble *c);
+void ( APIENTRY * qglIndexf )(GLfloat c);
+void ( APIENTRY * qglIndexfv )(const GLfloat *c);
+void ( APIENTRY * qglIndexi )(GLint c);
+void ( APIENTRY * qglIndexiv )(const GLint *c);
+void ( APIENTRY * qglIndexs )(GLshort c);
+void ( APIENTRY * qglIndexsv )(const GLshort *c);
+void ( APIENTRY * qglIndexub )(GLubyte c);
+void ( APIENTRY * qglIndexubv )(const GLubyte *c);
+void ( APIENTRY * qglInitNames )(void);
+void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
+GLboolean ( APIENTRY * qglIsList )(GLuint list);
+GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
+void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
+void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
+void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
+void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
+void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
+void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
+void ( APIENTRY * qglLineWidth )(GLfloat width);
+void ( APIENTRY * qglListBase )(GLuint base);
+void ( APIENTRY * qglLoadIdentity )(void);
+void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglLoadName )(GLuint name);
+void ( APIENTRY * qglLogicOp )(GLenum opcode);
+void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
+void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
+void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+void ( APIENTRY * qglMatrixMode )(GLenum mode);
+void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
+void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
+void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
+void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
+void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
+void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
+void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
+void ( APIENTRY * qglNormal3iv )(const GLint *v);
+void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+void ( APIENTRY * qglNormal3sv )(const GLshort *v);
+void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+void ( APIENTRY * qglPassThrough )(GLfloat token);
+void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
+void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
+void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+void ( APIENTRY * qglPointSize )(GLfloat size);
+void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
+void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
+void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
+void ( APIENTRY * qglPopAttrib )(void);
+void ( APIENTRY * qglPopClientAttrib )(void);
+void ( APIENTRY * qglPopMatrix )(void);
+void ( APIENTRY * qglPopName )(void);
+void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
+void ( APIENTRY * qglPushMatrix )(void);
+void ( APIENTRY * qglPushName )(GLuint name);
+void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
+void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
+void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
+void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
+void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
+void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
+void ( APIENTRY * qglReadBuffer )(GLenum mode);
+void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
+void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
+void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
+void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
+GLint ( APIENTRY * qglRenderMode )(GLenum mode);
+void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
+void ( APIENTRY * qglShadeModel )(GLenum mode);
+void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
+void ( APIENTRY * qglStencilMask )(GLuint mask);
+void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+void ( APIENTRY * qglTexCoord1d )(GLdouble s);
+void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord1f )(GLfloat s);
+void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord1i )(GLint s);
+void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord1s )(GLshort s);
+void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
+void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
+void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
+void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
+void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
+void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
+void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
+void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
+void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
+void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
+void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
+void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
+void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
+void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
+void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
+void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
+void ( APIENTRY * qglVertex2iv )(const GLint *v);
+void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
+void ( APIENTRY * qglVertex2sv )(const GLshort *v);
+void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
+void ( APIENTRY * qglVertex3iv )(const GLint *v);
+void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
+void ( APIENTRY * qglVertex3sv )(const GLshort *v);
+void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
+void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
+void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
+void ( APIENTRY * qglVertex4iv )(const GLint *v);
+void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+void ( APIENTRY * qglVertex4sv )(const GLshort *v);
+void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
+void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
+void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
+void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
+void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
+
+void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
+void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
+void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
+void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
+void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
+void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
+void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
+void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
+void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
+void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
+void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
+
+// glu stuff
+void (APIENTRY * qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+
+// added for plugins
+void (APIENTRY * qgluLookAt)(
+  GLdouble eyex,
+  GLdouble eyey,
+  GLdouble eyez,
+  GLdouble centerx,
+  GLdouble centery,
+  GLdouble centerz,
+  GLdouble upx,
+  GLdouble upy,
+  GLdouble upz);
+const GLubyte* (APIENTRY * qgluErrorString) (GLenum errCode );
+
+#ifdef ATIHACK_812
+void ( APIENTRY * qglCullFace_real )(GLenum mode);
+void ( APIENTRY * qglDisable_real )(GLenum cap);
+void ( APIENTRY * qglEnable_real )(GLenum cap);
+void ( APIENTRY * qglPolygonMode_real )(GLenum face, GLenum mode);
+#endif
+
+/*
+** QGL_Shutdown
+**
+** Unloads the specified DLL then nulls out all the proc pointers.
+*/
+void QGL_Shutdown()
+{
+  Sys_Printf("Shutting down GL ...");
+
+  if (g_hGLDLL)
+  {
+#ifdef _WIN32
+    FreeLibrary(g_hGLDLL);
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+    dlclose (g_hGLDLL);
+#endif
+
+    g_hGLDLL = NULL;
+  }
+
+  Sys_Printf("Done.\n");
+
+  qglAccum                     = NULL;
+  qglAlphaFunc                 = NULL;
+  qglAreTexturesResident       = NULL;
+  qglArrayElement              = NULL;
+  qglBegin                     = NULL;
+  qglBindTexture               = NULL;
+  qglBitmap                    = NULL;
+  qglBlendFunc                 = NULL;
+  qglCallList                  = NULL;
+  qglCallLists                 = NULL;
+  qglClear                     = NULL;
+  qglClearAccum                = NULL;
+  qglClearColor                = NULL;
+  qglClearDepth                = NULL;
+  qglClearIndex                = NULL;
+  qglClearStencil              = NULL;
+  qglClipPlane                 = NULL;
+  qglColor3b                   = NULL;
+  qglColor3bv                  = NULL;
+  qglColor3d                   = NULL;
+  qglColor3dv                  = NULL;
+  qglColor3f                   = NULL;
+  qglColor3fv                  = NULL;
+  qglColor3i                   = NULL;
+  qglColor3iv                  = NULL;
+  qglColor3s                   = NULL;
+  qglColor3sv                  = NULL;
+  qglColor3ub                  = NULL;
+  qglColor3ubv                 = NULL;
+  qglColor3ui                  = NULL;
+  qglColor3uiv                 = NULL;
+  qglColor3us                  = NULL;
+  qglColor3usv                 = NULL;
+  qglColor4b                   = NULL;
+  qglColor4bv                  = NULL;
+  qglColor4d                   = NULL;
+  qglColor4dv                  = NULL;
+  qglColor4f                   = NULL;
+  qglColor4fv                  = NULL;
+  qglColor4i                   = NULL;
+  qglColor4iv                  = NULL;
+  qglColor4s                   = NULL;
+  qglColor4sv                  = NULL;
+  qglColor4ub                  = NULL;
+  qglColor4ubv                 = NULL;
+  qglColor4ui                  = NULL;
+  qglColor4uiv                 = NULL;
+  qglColor4us                  = NULL;
+  qglColor4usv                 = NULL;
+  qglColorMask                 = NULL;
+  qglColorMaterial             = NULL;
+  qglColorPointer              = NULL;
+  qglCopyPixels                = NULL;
+  qglCopyTexImage1D            = NULL;
+  qglCopyTexImage2D            = NULL;
+  qglCopyTexSubImage1D         = NULL;
+  qglCopyTexSubImage2D         = NULL;
+  qglCullFace                  = NULL;
+  qglDeleteLists               = NULL;
+  qglDeleteTextures            = NULL;
+  qglDepthFunc                 = NULL;
+  qglDepthMask                 = NULL;
+  qglDepthRange                = NULL;
+  qglDisable                   = NULL;
+  qglDisableClientState        = NULL;
+  qglDrawArrays                = NULL;
+  qglDrawBuffer                = NULL;
+  qglDrawElements              = NULL;
+  qglDrawPixels                = NULL;
+  qglEdgeFlag                  = NULL;
+  qglEdgeFlagPointer           = NULL;
+  qglEdgeFlagv                 = NULL;
+  qglEnable                    = NULL;
+  qglEnableClientState         = NULL;
+  qglEnd                       = NULL;
+  qglEndList                   = NULL;
+  qglEvalCoord1d               = NULL;
+  qglEvalCoord1dv              = NULL;
+  qglEvalCoord1f               = NULL;
+  qglEvalCoord1fv              = NULL;
+  qglEvalCoord2d               = NULL;
+  qglEvalCoord2dv              = NULL;
+  qglEvalCoord2f               = NULL;
+  qglEvalCoord2fv              = NULL;
+  qglEvalMesh1                 = NULL;
+  qglEvalMesh2                 = NULL;
+  qglEvalPoint1                = NULL;
+  qglEvalPoint2                = NULL;
+  qglFeedbackBuffer            = NULL;
+  qglFinish                    = NULL;
+  qglFlush                     = NULL;
+  qglFogf                      = NULL;
+  qglFogfv                     = NULL;
+  qglFogi                      = NULL;
+  qglFogiv                     = NULL;
+  qglFrontFace                 = NULL;
+  qglFrustum                   = NULL;
+  qglGenLists                  = NULL;
+  qglGenTextures               = NULL;
+  qglGetBooleanv               = NULL;
+  qglGetClipPlane              = NULL;
+  qglGetDoublev                = NULL;
+  qglGetError                  = NULL;
+  qglGetFloatv                 = NULL;
+  qglGetIntegerv               = NULL;
+  qglGetLightfv                = NULL;
+  qglGetLightiv                = NULL;
+  qglGetMapdv                  = NULL;
+  qglGetMapfv                  = NULL;
+  qglGetMapiv                  = NULL;
+  qglGetMaterialfv             = NULL;
+  qglGetMaterialiv             = NULL;
+  qglGetPixelMapfv             = NULL;
+  qglGetPixelMapuiv            = NULL;
+  qglGetPixelMapusv            = NULL;
+  qglGetPointerv               = NULL;
+  qglGetPolygonStipple         = NULL;
+  qglGetString                 = NULL;
+  qglGetTexEnvfv               = NULL;
+  qglGetTexEnviv               = NULL;
+  qglGetTexGendv               = NULL;
+  qglGetTexGenfv               = NULL;
+  qglGetTexGeniv               = NULL;
+  qglGetTexImage               = NULL;
+  qglGetTexLevelParameterfv    = NULL;
+  qglGetTexLevelParameteriv    = NULL;
+  qglGetTexParameterfv         = NULL;
+  qglGetTexParameteriv         = NULL;
+  qglHint                      = NULL;
+  qglIndexMask                 = NULL;
+  qglIndexPointer              = NULL;
+  qglIndexd                    = NULL;
+  qglIndexdv                   = NULL;
+  qglIndexf                    = NULL;
+  qglIndexfv                   = NULL;
+  qglIndexi                    = NULL;
+  qglIndexiv                   = NULL;
+  qglIndexs                    = NULL;
+  qglIndexsv                   = NULL;
+  qglIndexub                   = NULL;
+  qglIndexubv                  = NULL;
+  qglInitNames                 = NULL;
+  qglInterleavedArrays         = NULL;
+  qglIsEnabled                 = NULL;
+  qglIsList                    = NULL;
+  qglIsTexture                 = NULL;
+  qglLightModelf               = NULL;
+  qglLightModelfv              = NULL;
+  qglLightModeli               = NULL;
+  qglLightModeliv              = NULL;
+  qglLightf                    = NULL;
+  qglLightfv                   = NULL;
+  qglLighti                    = NULL;
+  qglLightiv                   = NULL;
+  qglLineStipple               = NULL;
+  qglLineWidth                 = NULL;
+  qglListBase                  = NULL;
+  qglLoadIdentity              = NULL;
+  qglLoadMatrixd               = NULL;
+  qglLoadMatrixf               = NULL;
+  qglLoadName                  = NULL;
+  qglLogicOp                   = NULL;
+  qglMap1d                     = NULL;
+  qglMap1f                     = NULL;
+  qglMap2d                     = NULL;
+  qglMap2f                     = NULL;
+  qglMapGrid1d                 = NULL;
+  qglMapGrid1f                 = NULL;
+  qglMapGrid2d                 = NULL;
+  qglMapGrid2f                 = NULL;
+  qglMaterialf                 = NULL;
+  qglMaterialfv                = NULL;
+  qglMateriali                 = NULL;
+  qglMaterialiv                = NULL;
+  qglMatrixMode                = NULL;
+  qglMultMatrixd               = NULL;
+  qglMultMatrixf               = NULL;
+  qglNewList                   = NULL;
+  qglNormal3b                  = NULL;
+  qglNormal3bv                 = NULL;
+  qglNormal3d                  = NULL;
+  qglNormal3dv                 = NULL;
+  qglNormal3f                  = NULL;
+  qglNormal3fv                 = NULL;
+  qglNormal3i                  = NULL;
+  qglNormal3iv                 = NULL;
+  qglNormal3s                  = NULL;
+  qglNormal3sv                 = NULL;
+  qglNormalPointer             = NULL;
+  qglOrtho                     = NULL;
+  qglPassThrough               = NULL;
+  qglPixelMapfv                = NULL;
+  qglPixelMapuiv               = NULL;
+  qglPixelMapusv               = NULL;
+  qglPixelStoref               = NULL;
+  qglPixelStorei               = NULL;
+  qglPixelTransferf            = NULL;
+  qglPixelTransferi            = NULL;
+  qglPixelZoom                 = NULL;
+  qglPointSize                 = NULL;
+  qglPolygonMode               = NULL;
+  qglPolygonOffset             = NULL;
+  qglPolygonStipple            = NULL;
+  qglPopAttrib                 = NULL;
+  qglPopClientAttrib           = NULL;
+  qglPopMatrix                 = NULL;
+  qglPopName                   = NULL;
+  qglPrioritizeTextures        = NULL;
+  qglPushAttrib                = NULL;
+  qglPushClientAttrib          = NULL;
+  qglPushMatrix                = NULL;
+  qglPushName                  = NULL;
+  qglRasterPos2d               = NULL;
+  qglRasterPos2dv              = NULL;
+  qglRasterPos2f               = NULL;
+  qglRasterPos2fv              = NULL;
+  qglRasterPos2i               = NULL;
+  qglRasterPos2iv              = NULL;
+  qglRasterPos2s               = NULL;
+  qglRasterPos2sv              = NULL;
+  qglRasterPos3d               = NULL;
+  qglRasterPos3dv              = NULL;
+  qglRasterPos3f               = NULL;
+  qglRasterPos3fv              = NULL;
+  qglRasterPos3i               = NULL;
+  qglRasterPos3iv              = NULL;
+  qglRasterPos3s               = NULL;
+  qglRasterPos3sv              = NULL;
+  qglRasterPos4d               = NULL;
+  qglRasterPos4dv              = NULL;
+  qglRasterPos4f               = NULL;
+  qglRasterPos4fv              = NULL;
+  qglRasterPos4i               = NULL;
+  qglRasterPos4iv              = NULL;
+  qglRasterPos4s               = NULL;
+  qglRasterPos4sv              = NULL;
+  qglReadBuffer                = NULL;
+  qglReadPixels                = NULL;
+  qglRectd                     = NULL;
+  qglRectdv                    = NULL;
+  qglRectf                     = NULL;
+  qglRectfv                    = NULL;
+  qglRecti                     = NULL;
+  qglRectiv                    = NULL;
+  qglRects                     = NULL;
+  qglRectsv                    = NULL;
+  qglRenderMode                = NULL;
+  qglRotated                   = NULL;
+  qglRotatef                   = NULL;
+  qglScaled                    = NULL;
+  qglScalef                    = NULL;
+  qglScissor                   = NULL;
+  qglSelectBuffer              = NULL;
+  qglShadeModel                = NULL;
+  qglStencilFunc               = NULL;
+  qglStencilMask               = NULL;
+  qglStencilOp                 = NULL;
+  qglTexCoord1d                = NULL;
+  qglTexCoord1dv               = NULL;
+  qglTexCoord1f                = NULL;
+  qglTexCoord1fv               = NULL;
+  qglTexCoord1i                = NULL;
+  qglTexCoord1iv               = NULL;
+  qglTexCoord1s                = NULL;
+  qglTexCoord1sv               = NULL;
+  qglTexCoord2d                = NULL;
+  qglTexCoord2dv               = NULL;
+  qglTexCoord2f                = NULL;
+  qglTexCoord2fv               = NULL;
+  qglTexCoord2i                = NULL;
+  qglTexCoord2iv               = NULL;
+  qglTexCoord2s                = NULL;
+  qglTexCoord2sv               = NULL;
+  qglTexCoord3d                = NULL;
+  qglTexCoord3dv               = NULL;
+  qglTexCoord3f                = NULL;
+  qglTexCoord3fv               = NULL;
+  qglTexCoord3i                = NULL;
+  qglTexCoord3iv               = NULL;
+  qglTexCoord3s                = NULL;
+  qglTexCoord3sv               = NULL;
+  qglTexCoord4d                = NULL;
+  qglTexCoord4dv               = NULL;
+  qglTexCoord4f                = NULL;
+  qglTexCoord4fv               = NULL;
+  qglTexCoord4i                = NULL;
+  qglTexCoord4iv               = NULL;
+  qglTexCoord4s                = NULL;
+  qglTexCoord4sv               = NULL;
+  qglTexCoordPointer           = NULL;
+  qglTexEnvf                   = NULL;
+  qglTexEnvfv                  = NULL;
+  qglTexEnvi                   = NULL;
+  qglTexEnviv                  = NULL;
+  qglTexGend                   = NULL;
+  qglTexGendv                  = NULL;
+  qglTexGenf                   = NULL;
+  qglTexGenfv                  = NULL;
+  qglTexGeni                   = NULL;
+  qglTexGeniv                  = NULL;
+  qglTexImage1D                = NULL;
+  qglTexImage2D                = NULL;
+  qglTexParameterf             = NULL;
+  qglTexParameterfv            = NULL;
+  qglTexParameteri             = NULL;
+  qglTexParameteriv            = NULL;
+  qglTexSubImage1D             = NULL;
+  qglTexSubImage2D             = NULL;
+  qglTranslated                = NULL;
+  qglTranslatef                = NULL;
+  qglVertex2d                  = NULL;
+  qglVertex2dv                 = NULL;
+  qglVertex2f                  = NULL;
+  qglVertex2fv                 = NULL;
+  qglVertex2i                  = NULL;
+  qglVertex2iv                 = NULL;
+  qglVertex2s                  = NULL;
+  qglVertex2sv                 = NULL;
+  qglVertex3d                  = NULL;
+  qglVertex3dv                 = NULL;
+  qglVertex3f                  = NULL;
+  qglVertex3fv                 = NULL;
+  qglVertex3i                  = NULL;
+  qglVertex3iv                 = NULL;
+  qglVertex3s                  = NULL;
+  qglVertex3sv                 = NULL;
+  qglVertex4d                  = NULL;
+  qglVertex4dv                 = NULL;
+  qglVertex4f                  = NULL;
+  qglVertex4fv                 = NULL;
+  qglVertex4i                  = NULL;
+  qglVertex4iv                 = NULL;
+  qglVertex4s                  = NULL;
+  qglVertex4sv                 = NULL;
+  qglVertexPointer             = NULL;
+  qglViewport                  = NULL;
+
+  qglActiveTextureARB = NULL;
+  qglClientActiveTextureARB = NULL;
+  qglMultiTexCoord1dARB = NULL;
+  qglMultiTexCoord1dvARB = NULL;
+  qglMultiTexCoord1fARB = NULL;
+  qglMultiTexCoord1fvARB = NULL;
+  qglMultiTexCoord1iARB = NULL;
+  qglMultiTexCoord1ivARB = NULL;
+  qglMultiTexCoord1sARB = NULL;
+  qglMultiTexCoord1svARB = NULL;
+  qglMultiTexCoord2dARB = NULL;
+  qglMultiTexCoord2dvARB = NULL;
+  qglMultiTexCoord2fARB = NULL;
+  qglMultiTexCoord2fvARB = NULL;
+  qglMultiTexCoord2iARB = NULL;
+  qglMultiTexCoord2ivARB = NULL;
+  qglMultiTexCoord2sARB = NULL;
+  qglMultiTexCoord2svARB = NULL;
+  qglMultiTexCoord3dARB = NULL;
+  qglMultiTexCoord3dvARB = NULL;
+  qglMultiTexCoord3fARB = NULL;
+  qglMultiTexCoord3fvARB = NULL;
+  qglMultiTexCoord3iARB = NULL;
+  qglMultiTexCoord3ivARB = NULL;
+  qglMultiTexCoord3sARB = NULL;
+  qglMultiTexCoord3svARB = NULL;
+  qglMultiTexCoord4dARB = NULL;
+  qglMultiTexCoord4dvARB = NULL;
+  qglMultiTexCoord4fARB = NULL;
+  qglMultiTexCoord4fvARB = NULL;
+  qglMultiTexCoord4iARB = NULL;
+  qglMultiTexCoord4ivARB = NULL;
+  qglMultiTexCoord4sARB = NULL;
+  qglMultiTexCoord4svARB = NULL;
+
+#ifdef _WIN32
+  qwglCopyContext              = NULL;
+  qwglCreateContext            = NULL;
+  qwglCreateLayerContext       = NULL;
+  qwglDeleteContext            = NULL;
+  qwglDescribeLayerPlane       = NULL;
+  qwglGetCurrentContext        = NULL;
+  qwglGetCurrentDC             = NULL;
+  qwglGetLayerPaletteEntries   = NULL;
+  qwglGetProcAddress           = NULL;
+  qwglMakeCurrent              = NULL;
+  qwglRealizeLayerPalette      = NULL;
+  qwglSetLayerPaletteEntries   = NULL;
+  qwglShareLists               = NULL;
+  qwglSwapLayerBuffers         = NULL;
+  qwglUseFontBitmaps           = NULL;
+  qwglUseFontOutlines          = NULL;
+
+  qwglChoosePixelFormat        = NULL;
+  qwglDescribePixelFormat      = NULL;
+  qwglGetPixelFormat           = NULL;
+  qwglSetPixelFormat           = NULL;
+  qwglSwapBuffers              = NULL;
+
+  qwglSwapIntervalEXT          = NULL;
+
+  qwglGetDeviceGammaRampEXT    = NULL;
+  qwglSetDeviceGammaRampEXT    = NULL;
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+  qglXChooseVisual             = NULL;
+  qglXCreateContext            = NULL;
+  qglXDestroyContext           = NULL;
+  qglXMakeCurrent              = NULL;
+  qglXCopyContext              = NULL;
+  qglXSwapBuffers              = NULL;
+  qglXCreateGLXPixmap          = NULL;
+  qglXDestroyGLXPixmap         = NULL;
+  qglXQueryExtension           = NULL;
+  qglXQueryVersion             = NULL;
+  qglXIsDirect                 = NULL;
+  qglXGetConfig                = NULL;
+  qglXGetCurrentContext        = NULL;
+  qglXGetCurrentDrawable       = NULL;
+  qglXWaitGL                   = NULL;
+  qglXWaitX                    = NULL;
+  qglXUseXFont                 = NULL;
+  qglXGetProcAddressARB        = NULL;
+#endif
+
+  qgluPerspective = NULL;
+  qgluErrorString = NULL;
+  qgluLookAt = NULL;
+
+#ifdef ATIHACK_812
+  qglCullFace_real              = NULL;
+  qglDisable_real               = NULL;
+  qglEnable_real                = NULL;
+  qglPolygonMode_real           = NULL;
+#endif
+}
+
+/*
+** QGL_Init
+**
+** This is responsible for binding our qgl function pointers to 
+** the appropriate GL stuff.  In Windows this means doing a 
+** LoadLibrary and a bunch of calls to GetProcAddress.  On other
+** operating systems we need to do the right thing, whatever that
+** might be.
+** 
+*/
+static int init_error;
+
+static void* safe_dlsym (void *handle, char *symbol)
+{
+#ifdef _WIN32
+  return GetProcAddress (handle, symbol);
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+  void* ret = dlsym (handle, symbol);
+  const char *err = dlerror();
+  if (err)
+  {
+    init_error = 1;
+#ifndef __APPLE__
+    printf ("Error loading OpenGL libraries: %s\n", err);
+#else
+    printf ("Error loading OpenGL libraries: %s %s\n", err, symbol);
+#endif
+  }
+  return ret;
+#endif
+}
+
+#include <math.h>
+#include <stdlib.h>
+#ifdef _WIN32
+#define M_PI 3.14159
+#endif
+
+void WINAPI gluLookAt2 (GLdouble ex, GLdouble ey, GLdouble ez, GLdouble cx, GLdouble cy, GLdouble cz,
+		 GLdouble ux, GLdouble uy, GLdouble uz)
+{
+   GLdouble x[3], y[3], z[3] = { ex-cx, ey-cy, ez-cz };
+   GLdouble inv;
+
+   inv = sqrt (z[0]*z[0] + z[1]*z[1] + z[2]*z[2]);
+   if (inv)
+   {
+     inv = 1.0/inv;
+     z[0] *= inv;
+     z[1] *= inv;
+     z[2] *= inv;
+   }
+
+   x[0] =  uy*z[2] - uz*z[1];
+   x[1] = -ux*z[2] + uz*z[0];
+   x[2] =  ux*z[1] - uy*z[0];
+
+   y[0] =  z[1]*x[2] - z[2]*x[1];
+   y[1] = -z[0]*x[2] + z[2]*x[0];
+   y[2] =  z[0]*x[1] - z[1]*x[0];
+
+   inv = sqrt(x[0]*x[0] + x[1]*x[1] + x[2]*x[2]);
+   if (inv)
+   {
+     x[0] *= inv;
+     x[1] *= inv;
+     x[2] *= inv;
+   }
+
+   inv = sqrt(y[0]*y[0] + y[1]*y[1] + y[2]*y[2]);
+   if (inv)
+   {
+      y[0] *= inv;
+      y[1] *= inv;
+      y[2] *= inv;
+   }
+
+   {
+   GLdouble m[16] = { x[0], y[0], z[0], 0, x[1], y[1], z[1], 0, x[2], y[2], z[2], 0, 0, 0, 0, 1 };
+   qglMultMatrixd(m);
+   qglTranslated(-ex, -ey, -ez);
+   }
+}
+
+void WINAPI gluPerspective2 (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar)
+{
+   GLdouble y = zNear * tan (fovy * M_PI / 360.0);
+   qglFrustum (-y*aspect, y*aspect, -y, y, zNear, zFar);
+}
+
+static void* WINAPI ResizeImage (GLubyte* old_image, int srcw, int srch, int destw, int desth)
+{
+  int i, j;
+  float sx, sy;
+  GLubyte* new_image = (GLubyte *)malloc (destw*desth*4*sizeof(GLubyte));
+  if (new_image == NULL)
+    return NULL;
+
+  if (destw > 1)
+    sx = (GLfloat) (srcw-1) / (GLfloat) (destw-1);
+  else
+    sx = (GLfloat) (srcw-1);
+  if (desth > 1)
+    sy = (GLfloat) (srch-1) / (GLfloat) (desth-1);
+  else
+    sy = (GLfloat) (srch-1);
+
+  for (i = 0; i < desth; i++)
+  {
+    GLint ii = (GLint)(i * sy);
+    for (j = 0; j < destw; j++)
+    {
+      GLint jj = (GLint)(j * sx);
+      GLubyte *src = old_image + (ii * srcw + jj) * 4;
+      GLubyte *dst = new_image + (i * destw + j) * 4;
+
+      *dst++ = *src++;
+      *dst++ = *src++;
+      *dst++ = *src++;
+      *dst++ = *src++;
+    }
+  }
+
+  return new_image;
+}
+
+#define CEILING(A, B)  ( (A) % (B) == 0 ? (A)/(B) : (A)/(B)+1 )
+
+typedef struct glu_error_struct
+{
+    int     errnum;
+    const char *errstr;
+} GLU_ERROR_STRUCT;
+
+GLU_ERROR_STRUCT glu_errlist[] = {
+  {GL_NO_ERROR, "GL_NO_ERROR - no error"},
+  {GL_INVALID_ENUM, "GL_INVALID_ENUM - An unacceptable value is specified for an enumerated argument."},
+  {GL_INVALID_VALUE, "GL_INVALID_VALUE - A numeric argument is out of range."},
+  {GL_INVALID_OPERATION, "GL_INVALID_OPERATION - The specified operation is not allowed in the current state."},
+  {GL_STACK_OVERFLOW, "GL_STACK_OVERFLOW - Function would cause a stack overflow."},
+  {GL_STACK_UNDERFLOW, "GL_STACK_UNDERFLOW - Function would cause a stack underflow."},
+  {GL_OUT_OF_MEMORY, "GL_OUT_OF_MEMORY - There is not enough memory left to execute the function."},
+  {-1, NULL}
+};
+
+const GLubyte* WINAPI gluErrorString(GLenum errCode )
+{
+  int search = 0;
+  for (search = 0; glu_errlist[search].errstr; search++)
+  {
+    if (errCode == glu_errlist[search].errnum)
+      return (const char *)glu_errlist[search].errstr;
+  } //end for
+  return "Unknown error";
+}
+
+#ifdef ATIHACK_812
+int ATIhack_culling;
+GLenum ATIhack_cullmode;
+GLenum ATIhack_backmode;
+GLenum ATIhack_frontmode;
+
+static void ATIhack_update(void)
+{
+  if(!ATIhack_culling || (GL_FRONT_AND_BACK == ATIhack_cullmode))
+  {
+    qglPolygonMode_real(GL_FRONT, ATIhack_frontmode);
+    qglPolygonMode_real(GL_BACK, ATIhack_backmode);
+  }
+  else
+    switch(ATIhack_cullmode)
+    {
+      case GL_FRONT:
+        qglPolygonMode_real(GL_FRONT_AND_BACK, ATIhack_backmode);
+        break;
+      case GL_BACK:
+        qglPolygonMode_real(GL_FRONT_AND_BACK, ATIhack_frontmode);
+      default:
+        break;
+    }
+}
+
+void APIENTRY qglEnable_ATIHack(GLenum cap)
+{
+  qglEnable_real(cap);
+  if(GL_CULL_FACE != cap)
+    return;
+  if(ATIhack_culling)
+    return;
+  ATIhack_culling = 1;
+  ATIhack_update();
+}
+
+void APIENTRY qglDisable_ATIHack(GLenum cap)
+{
+  qglDisable_real(cap);
+  if(GL_CULL_FACE != cap)
+    return;
+  if(!ATIhack_culling)
+    return;
+  ATIhack_culling = 0;
+  ATIhack_update();
+}
+
+void APIENTRY qglCullFace_ATIHack(GLenum mode)
+{
+  if(ATIhack_cullmode == mode)
+    return;
+  qglCullFace_real(mode);
+  ATIhack_cullmode = mode;
+  ATIhack_update();
+}
+
+void APIENTRY qglPolygonMode_ATIHack(GLenum face, GLenum mode)
+{
+  switch(face)
+  {
+    case GL_FRONT:
+      if(ATIhack_frontmode == mode)
+        return;
+      ATIhack_frontmode = mode;
+      break;
+    case GL_BACK:
+      if(ATIhack_backmode == mode)
+        return;
+      ATIhack_backmode = mode;
+      break;
+    case GL_FRONT_AND_BACK:
+      if((ATIhack_frontmode == mode) && (ATIhack_backmode == mode))
+        return;
+      ATIhack_frontmode = ATIhack_backmode = mode;
+    default:
+      break;
+  }
+  ATIhack_update();
+}
+#endif
+
+int QGL_Init(const char *dllname, const char* gluname)
+{
+#ifdef _WIN32
+  g_hGLDLL = LoadLibrary(dllname); 
+#endif
+
+#if defined (__linux__) || (__APPLE__)
+  const char *err;
+
+  // NOTE TTimo
+  // I don't like RTLD_LAZY|RTLD_GLOBAL too much .. it's dangerous
+  // maybe try RTLD_NOW? or would that break compatibility .. you never know when that stuff is going to explode
+  g_hGLDLL = dlopen(dllname, RTLD_LAZY|RTLD_GLOBAL);
+  err = dlerror();
+  if (err)
+    printf ("Error loading GL lib:\n%s\n", err);
+#endif
+  init_error = 0;
+
+  if (g_hGLDLL == NULL)
+    return 0;
+
+  Sys_Printf ("Loading GL library: %s ...", dllname);
+
+  qgluPerspective              = &gluPerspective2;
+
+  qgluLookAt                   = &gluLookAt2;
+  qgluErrorString              = &gluErrorString;
+  qglAccum                     = safe_dlsym (g_hGLDLL, "glAccum" );
+  qglAlphaFunc                 = safe_dlsym (g_hGLDLL, "glAlphaFunc" );
+  qglAreTexturesResident       = safe_dlsym (g_hGLDLL, "glAreTexturesResident" );
+  qglArrayElement              = safe_dlsym (g_hGLDLL, "glArrayElement" );
+  qglBegin                     = safe_dlsym (g_hGLDLL, "glBegin" );
+  qglBindTexture               = safe_dlsym (g_hGLDLL, "glBindTexture" );
+  qglBitmap                    = safe_dlsym (g_hGLDLL, "glBitmap" );
+  qglBlendFunc                 = safe_dlsym (g_hGLDLL, "glBlendFunc" );
+  qglCallList                  = safe_dlsym (g_hGLDLL, "glCallList" );
+  qglCallLists                 = safe_dlsym (g_hGLDLL, "glCallLists" );
+  qglClear                     = safe_dlsym (g_hGLDLL, "glClear" );
+  qglClearAccum                = safe_dlsym (g_hGLDLL, "glClearAccum" );
+  qglClearColor                = safe_dlsym (g_hGLDLL, "glClearColor" );
+  qglClearDepth                = safe_dlsym (g_hGLDLL, "glClearDepth" );
+  qglClearIndex                = safe_dlsym (g_hGLDLL, "glClearIndex" );
+  qglClearStencil              = safe_dlsym (g_hGLDLL, "glClearStencil" );
+  qglClipPlane                 = safe_dlsym (g_hGLDLL, "glClipPlane" );
+  qglColor3b                   = safe_dlsym (g_hGLDLL, "glColor3b" );
+  qglColor3bv                  = safe_dlsym (g_hGLDLL, "glColor3bv" );
+  qglColor3d                   = safe_dlsym (g_hGLDLL, "glColor3d" );
+  qglColor3dv                  = safe_dlsym (g_hGLDLL, "glColor3dv" );
+  qglColor3f                   = safe_dlsym (g_hGLDLL, "glColor3f" );
+  qglColor3fv                  = safe_dlsym (g_hGLDLL, "glColor3fv" );
+  qglColor3i                   = safe_dlsym (g_hGLDLL, "glColor3i" );
+  qglColor3iv                  = safe_dlsym (g_hGLDLL, "glColor3iv" );
+  qglColor3s                   = safe_dlsym (g_hGLDLL, "glColor3s" );
+  qglColor3sv                  = safe_dlsym (g_hGLDLL, "glColor3sv" );
+  qglColor3ub                  = safe_dlsym (g_hGLDLL, "glColor3ub" );
+  qglColor3ubv                 = safe_dlsym (g_hGLDLL, "glColor3ubv" );
+  qglColor3ui                  = safe_dlsym (g_hGLDLL, "glColor3ui" );
+  qglColor3uiv                 = safe_dlsym (g_hGLDLL, "glColor3uiv" );
+  qglColor3us                  = safe_dlsym (g_hGLDLL, "glColor3us" );
+  qglColor3usv                 = safe_dlsym (g_hGLDLL, "glColor3usv" );
+  qglColor4b                   = safe_dlsym (g_hGLDLL, "glColor4b" );
+  qglColor4bv                  = safe_dlsym (g_hGLDLL, "glColor4bv" );
+  qglColor4d                   = safe_dlsym (g_hGLDLL, "glColor4d" );
+  qglColor4dv                  = safe_dlsym (g_hGLDLL, "glColor4dv" );
+  qglColor4f                   = safe_dlsym (g_hGLDLL, "glColor4f" );
+  qglColor4fv                  = safe_dlsym (g_hGLDLL, "glColor4fv" );
+  qglColor4i                   = safe_dlsym (g_hGLDLL, "glColor4i" );
+  qglColor4iv                  = safe_dlsym (g_hGLDLL, "glColor4iv" );
+  qglColor4s                   = safe_dlsym (g_hGLDLL, "glColor4s" );
+  qglColor4sv                  = safe_dlsym (g_hGLDLL, "glColor4sv" );
+  qglColor4ub                  = safe_dlsym (g_hGLDLL, "glColor4ub" );
+  qglColor4ubv                 = safe_dlsym (g_hGLDLL, "glColor4ubv" );
+  qglColor4ui                  = safe_dlsym (g_hGLDLL, "glColor4ui" );
+  qglColor4uiv                 = safe_dlsym (g_hGLDLL, "glColor4uiv" );
+  qglColor4us                  = safe_dlsym (g_hGLDLL, "glColor4us" );
+  qglColor4usv                 = safe_dlsym (g_hGLDLL, "glColor4usv" );
+  qglColorMask                 = safe_dlsym (g_hGLDLL, "glColorMask" );
+  qglColorMaterial             = safe_dlsym (g_hGLDLL, "glColorMaterial" );
+  qglColorPointer              = safe_dlsym (g_hGLDLL, "glColorPointer" );
+  qglCopyPixels                = safe_dlsym (g_hGLDLL, "glCopyPixels" );
+  qglCopyTexImage1D            = safe_dlsym (g_hGLDLL, "glCopyTexImage1D" );
+  qglCopyTexImage2D            = safe_dlsym (g_hGLDLL, "glCopyTexImage2D" );
+  qglCopyTexSubImage1D         = safe_dlsym (g_hGLDLL, "glCopyTexSubImage1D" );
+  qglCopyTexSubImage2D         = safe_dlsym (g_hGLDLL, "glCopyTexSubImage2D" );
+#ifdef ATIHACK_812
+  qglCullFace_real              = safe_dlsym (g_hGLDLL, "glCullFace" );
+  qglCullFace                  = qglCullFace_real;
+#else
+  qglCullFace                  = safe_dlsym (g_hGLDLL, "glCullFace" );
+#endif
+  qglDeleteLists               = safe_dlsym (g_hGLDLL, "glDeleteLists" );
+  qglDeleteTextures            = safe_dlsym (g_hGLDLL, "glDeleteTextures" );
+  qglDepthFunc                 = safe_dlsym (g_hGLDLL, "glDepthFunc" );
+  qglDepthMask                 = safe_dlsym (g_hGLDLL, "glDepthMask" );
+  qglDepthRange                = safe_dlsym (g_hGLDLL, "glDepthRange" );
+#ifdef ATIHACK_812
+  qglDisable_real               = safe_dlsym (g_hGLDLL, "glDisable" );
+  qglDisable                   = qglDisable_real;
+#else
+  qglDisable                   = safe_dlsym (g_hGLDLL, "glDisable" );
+#endif
+  qglDisableClientState        = safe_dlsym (g_hGLDLL, "glDisableClientState" );
+  qglDrawArrays                = safe_dlsym (g_hGLDLL, "glDrawArrays" );
+  qglDrawBuffer                = safe_dlsym (g_hGLDLL, "glDrawBuffer" );
+  qglDrawElements              = safe_dlsym (g_hGLDLL, "glDrawElements" );
+  qglDrawPixels                = safe_dlsym (g_hGLDLL, "glDrawPixels" );
+  qglEdgeFlag                  = safe_dlsym (g_hGLDLL, "glEdgeFlag" );
+  qglEdgeFlagPointer           = safe_dlsym (g_hGLDLL, "glEdgeFlagPointer" );
+  qglEdgeFlagv                 = safe_dlsym (g_hGLDLL, "glEdgeFlagv" );
+#ifdef ATIHACK_812
+  qglEnable_real                = safe_dlsym (g_hGLDLL, "glEnable" );
+  qglEnable                    = qglEnable_real;
+#else
+  qglEnable                    = safe_dlsym (g_hGLDLL, "glEnable" );
+#endif
+  qglEnableClientState         = safe_dlsym (g_hGLDLL, "glEnableClientState" );
+  qglEnd                       = safe_dlsym (g_hGLDLL, "glEnd" );
+  qglEndList                   = safe_dlsym (g_hGLDLL, "glEndList" );
+  qglEvalCoord1d               = safe_dlsym (g_hGLDLL, "glEvalCoord1d" );
+  qglEvalCoord1dv              = safe_dlsym (g_hGLDLL, "glEvalCoord1dv" );
+  qglEvalCoord1f               = safe_dlsym (g_hGLDLL, "glEvalCoord1f" );
+  qglEvalCoord1fv              = safe_dlsym (g_hGLDLL, "glEvalCoord1fv" );
+  qglEvalCoord2d               = safe_dlsym (g_hGLDLL, "glEvalCoord2d" );
+  qglEvalCoord2dv              = safe_dlsym (g_hGLDLL, "glEvalCoord2dv" );
+  qglEvalCoord2f               = safe_dlsym (g_hGLDLL, "glEvalCoord2f" );
+  qglEvalCoord2fv              = safe_dlsym (g_hGLDLL, "glEvalCoord2fv" );
+  qglEvalMesh1                 = safe_dlsym (g_hGLDLL, "glEvalMesh1" );
+  qglEvalMesh2                 = safe_dlsym (g_hGLDLL, "glEvalMesh2" );
+  qglEvalPoint1                = safe_dlsym (g_hGLDLL, "glEvalPoint1" );
+  qglEvalPoint2                = safe_dlsym (g_hGLDLL, "glEvalPoint2" );
+  qglFeedbackBuffer            = safe_dlsym (g_hGLDLL, "glFeedbackBuffer" );
+  qglFinish                    = safe_dlsym (g_hGLDLL, "glFinish" );
+  qglFlush                     = safe_dlsym (g_hGLDLL, "glFlush" );
+  qglFogf                      = safe_dlsym (g_hGLDLL, "glFogf" );
+  qglFogfv                     = safe_dlsym (g_hGLDLL, "glFogfv" );
+  qglFogi                      = safe_dlsym (g_hGLDLL, "glFogi" );
+  qglFogiv                     = safe_dlsym (g_hGLDLL, "glFogiv" );
+  qglFrontFace                 = safe_dlsym (g_hGLDLL, "glFrontFace" );
+  qglFrustum                   = safe_dlsym (g_hGLDLL, "glFrustum" );
+  qglGenLists                  = safe_dlsym (g_hGLDLL, "glGenLists" );
+  qglGenTextures               = safe_dlsym (g_hGLDLL, "glGenTextures" );
+  qglGetBooleanv               = safe_dlsym (g_hGLDLL, "glGetBooleanv" );
+  qglGetClipPlane              = safe_dlsym (g_hGLDLL, "glGetClipPlane" );
+  qglGetDoublev                = safe_dlsym (g_hGLDLL, "glGetDoublev" );
+  qglGetError                  = safe_dlsym (g_hGLDLL, "glGetError" );
+  qglGetFloatv                 = safe_dlsym (g_hGLDLL, "glGetFloatv" );
+  qglGetIntegerv               = safe_dlsym (g_hGLDLL, "glGetIntegerv" );
+  qglGetLightfv                = safe_dlsym (g_hGLDLL, "glGetLightfv" );
+  qglGetLightiv                = safe_dlsym (g_hGLDLL, "glGetLightiv" );
+  qglGetMapdv                  = safe_dlsym (g_hGLDLL, "glGetMapdv" );
+  qglGetMapfv                  = safe_dlsym (g_hGLDLL, "glGetMapfv" );
+  qglGetMapiv                  = safe_dlsym (g_hGLDLL, "glGetMapiv" );
+  qglGetMaterialfv             = safe_dlsym (g_hGLDLL, "glGetMaterialfv" );
+  qglGetMaterialiv             = safe_dlsym (g_hGLDLL, "glGetMaterialiv" );
+  qglGetPixelMapfv             = safe_dlsym (g_hGLDLL, "glGetPixelMapfv" );
+  qglGetPixelMapuiv            = safe_dlsym (g_hGLDLL, "glGetPixelMapuiv" );
+  qglGetPixelMapusv            = safe_dlsym (g_hGLDLL, "glGetPixelMapusv" );
+  qglGetPointerv               = safe_dlsym (g_hGLDLL, "glGetPointerv" );
+  qglGetPolygonStipple         = safe_dlsym (g_hGLDLL, "glGetPolygonStipple" );
+  qglGetString                 = safe_dlsym (g_hGLDLL, "glGetString" );
+  qglGetTexEnvfv               = safe_dlsym (g_hGLDLL, "glGetTexEnvfv" );
+  qglGetTexEnviv               = safe_dlsym (g_hGLDLL, "glGetTexEnviv" );
+  qglGetTexGendv               = safe_dlsym (g_hGLDLL, "glGetTexGendv" );
+  qglGetTexGenfv               = safe_dlsym (g_hGLDLL, "glGetTexGenfv" );
+  qglGetTexGeniv               = safe_dlsym (g_hGLDLL, "glGetTexGeniv" );
+  qglGetTexImage               = safe_dlsym (g_hGLDLL, "glGetTexImage" );
+  qglGetTexLevelParameterfv    = safe_dlsym (g_hGLDLL, "glGetTexLevelParameterfv" );
+  qglGetTexLevelParameteriv    = safe_dlsym (g_hGLDLL, "glGetTexLevelParameteriv" );
+  qglGetTexParameterfv         = safe_dlsym (g_hGLDLL, "glGetTexParameterfv" );
+  qglGetTexParameteriv         = safe_dlsym (g_hGLDLL, "glGetTexParameteriv" );
+  qglHint                      = safe_dlsym (g_hGLDLL, "glHint" );
+  qglIndexMask                 = safe_dlsym (g_hGLDLL, "glIndexMask" );
+  qglIndexPointer              = safe_dlsym (g_hGLDLL, "glIndexPointer" );
+  qglIndexd                    = safe_dlsym (g_hGLDLL, "glIndexd" );
+  qglIndexdv                   = safe_dlsym (g_hGLDLL, "glIndexdv" );
+  qglIndexf                    = safe_dlsym (g_hGLDLL, "glIndexf" );
+  qglIndexfv                   = safe_dlsym (g_hGLDLL, "glIndexfv" );
+  qglIndexi                    = safe_dlsym (g_hGLDLL, "glIndexi" );
+  qglIndexiv                   = safe_dlsym (g_hGLDLL, "glIndexiv" );
+  qglIndexs                    = safe_dlsym (g_hGLDLL, "glIndexs" );
+  qglIndexsv                   = safe_dlsym (g_hGLDLL, "glIndexsv" );
+  qglIndexub                   = safe_dlsym (g_hGLDLL, "glIndexub" );
+  qglIndexubv                  = safe_dlsym (g_hGLDLL, "glIndexubv" );
+  qglInitNames                 = safe_dlsym (g_hGLDLL, "glInitNames" );
+  qglInterleavedArrays         = safe_dlsym (g_hGLDLL, "glInterleavedArrays" );
+  qglIsEnabled                 = safe_dlsym (g_hGLDLL, "glIsEnabled" );
+  qglIsList                    = safe_dlsym (g_hGLDLL, "glIsList" );
+  qglIsTexture                 = safe_dlsym (g_hGLDLL, "glIsTexture" );
+  qglLightModelf               = safe_dlsym (g_hGLDLL, "glLightModelf" );
+  qglLightModelfv              = safe_dlsym (g_hGLDLL, "glLightModelfv" );
+  qglLightModeli               = safe_dlsym (g_hGLDLL, "glLightModeli" );
+  qglLightModeliv              = safe_dlsym (g_hGLDLL, "glLightModeliv" );
+  qglLightf                    = safe_dlsym (g_hGLDLL, "glLightf" );
+  qglLightfv                   = safe_dlsym (g_hGLDLL, "glLightfv" );
+  qglLighti                    = safe_dlsym (g_hGLDLL, "glLighti" );
+  qglLightiv                   = safe_dlsym (g_hGLDLL, "glLightiv" );
+  qglLineStipple               = safe_dlsym (g_hGLDLL, "glLineStipple" );
+  qglLineWidth                 = safe_dlsym (g_hGLDLL, "glLineWidth" );
+  qglListBase                  = safe_dlsym (g_hGLDLL, "glListBase" );
+  qglLoadIdentity              = safe_dlsym (g_hGLDLL, "glLoadIdentity" );
+  qglLoadMatrixd               = safe_dlsym (g_hGLDLL, "glLoadMatrixd" );
+  qglLoadMatrixf               = safe_dlsym (g_hGLDLL, "glLoadMatrixf" );
+  qglLoadName                  = safe_dlsym (g_hGLDLL, "glLoadName" );
+  qglLogicOp                   = safe_dlsym (g_hGLDLL, "glLogicOp" );
+  qglMap1d                     = safe_dlsym (g_hGLDLL, "glMap1d" );
+  qglMap1f                     = safe_dlsym (g_hGLDLL, "glMap1f" );
+  qglMap2d                     = safe_dlsym (g_hGLDLL, "glMap2d" );
+  qglMap2f                     = safe_dlsym (g_hGLDLL, "glMap2f" );
+  qglMapGrid1d                 = safe_dlsym (g_hGLDLL, "glMapGrid1d" );
+  qglMapGrid1f                 = safe_dlsym (g_hGLDLL, "glMapGrid1f" );
+  qglMapGrid2d                 = safe_dlsym (g_hGLDLL, "glMapGrid2d" );
+  qglMapGrid2f                 = safe_dlsym (g_hGLDLL, "glMapGrid2f" );
+  qglMaterialf                 = safe_dlsym (g_hGLDLL, "glMaterialf" );
+  qglMaterialfv                = safe_dlsym (g_hGLDLL, "glMaterialfv" );
+  qglMateriali                 = safe_dlsym (g_hGLDLL, "glMateriali" );
+  qglMaterialiv                = safe_dlsym (g_hGLDLL, "glMaterialiv" );
+  qglMatrixMode                = safe_dlsym (g_hGLDLL, "glMatrixMode" );
+  qglMultMatrixd               = safe_dlsym (g_hGLDLL, "glMultMatrixd" );
+  qglMultMatrixf               = safe_dlsym (g_hGLDLL, "glMultMatrixf" );
+  qglNewList                   = safe_dlsym (g_hGLDLL, "glNewList" );
+  qglNormal3b                  = safe_dlsym (g_hGLDLL, "glNormal3b" );
+  qglNormal3bv                 = safe_dlsym (g_hGLDLL, "glNormal3bv" );
+  qglNormal3d                  = safe_dlsym (g_hGLDLL, "glNormal3d" );
+  qglNormal3dv                 = safe_dlsym (g_hGLDLL, "glNormal3dv" );
+  qglNormal3f                  = safe_dlsym (g_hGLDLL, "glNormal3f" );
+  qglNormal3fv                 = safe_dlsym (g_hGLDLL, "glNormal3fv" );
+  qglNormal3i                  = safe_dlsym (g_hGLDLL, "glNormal3i" );
+  qglNormal3iv                 = safe_dlsym (g_hGLDLL, "glNormal3iv" );
+  qglNormal3s                  = safe_dlsym (g_hGLDLL, "glNormal3s" );
+  qglNormal3sv                 = safe_dlsym (g_hGLDLL, "glNormal3sv" );
+  qglNormalPointer             = safe_dlsym (g_hGLDLL, "glNormalPointer" );
+  qglOrtho                     = safe_dlsym (g_hGLDLL, "glOrtho" );
+  qglPassThrough               = safe_dlsym (g_hGLDLL, "glPassThrough" );
+  qglPixelMapfv                = safe_dlsym (g_hGLDLL, "glPixelMapfv" );
+  qglPixelMapuiv               = safe_dlsym (g_hGLDLL, "glPixelMapuiv" );
+  qglPixelMapusv               = safe_dlsym (g_hGLDLL, "glPixelMapusv" );
+  qglPixelStoref               = safe_dlsym (g_hGLDLL, "glPixelStoref" );
+  qglPixelStorei               = safe_dlsym (g_hGLDLL, "glPixelStorei" );
+  qglPixelTransferf            = safe_dlsym (g_hGLDLL, "glPixelTransferf" );
+  qglPixelTransferi            = safe_dlsym (g_hGLDLL, "glPixelTransferi" );
+  qglPixelZoom                 = safe_dlsym (g_hGLDLL, "glPixelZoom" );
+  qglPointSize                 = safe_dlsym (g_hGLDLL, "glPointSize" );
+#ifdef ATIHACK_812
+  qglPolygonMode_real           = safe_dlsym (g_hGLDLL, "glPolygonMode" );
+  qglPolygonMode               = qglPolygonMode_real;
+#else
+  qglPolygonMode               = safe_dlsym (g_hGLDLL, "glPolygonMode" );
+#endif
+  qglPolygonOffset             = safe_dlsym (g_hGLDLL, "glPolygonOffset" );
+  qglPolygonStipple            = safe_dlsym (g_hGLDLL, "glPolygonStipple" );
+  qglPopAttrib                 = safe_dlsym (g_hGLDLL, "glPopAttrib" );
+  qglPopClientAttrib           = safe_dlsym (g_hGLDLL, "glPopClientAttrib" );
+  qglPopMatrix                 = safe_dlsym (g_hGLDLL, "glPopMatrix" );
+  qglPopName                   = safe_dlsym (g_hGLDLL, "glPopName" );
+  qglPrioritizeTextures        = safe_dlsym (g_hGLDLL, "glPrioritizeTextures" );
+  qglPushAttrib                = safe_dlsym (g_hGLDLL, "glPushAttrib" );
+  qglPushClientAttrib          = safe_dlsym (g_hGLDLL, "glPushClientAttrib" );
+  qglPushMatrix                = safe_dlsym (g_hGLDLL, "glPushMatrix" );
+  qglPushName                  = safe_dlsym (g_hGLDLL, "glPushName" );
+  qglRasterPos2d               = safe_dlsym (g_hGLDLL, "glRasterPos2d" );
+  qglRasterPos2dv              = safe_dlsym (g_hGLDLL, "glRasterPos2dv" );
+  qglRasterPos2f               = safe_dlsym (g_hGLDLL, "glRasterPos2f" );
+  qglRasterPos2fv              = safe_dlsym (g_hGLDLL, "glRasterPos2fv" );
+  qglRasterPos2i               = safe_dlsym (g_hGLDLL, "glRasterPos2i" );
+  qglRasterPos2iv              = safe_dlsym (g_hGLDLL, "glRasterPos2iv" );
+  qglRasterPos2s               = safe_dlsym (g_hGLDLL, "glRasterPos2s" );
+  qglRasterPos2sv              = safe_dlsym (g_hGLDLL, "glRasterPos2sv" );
+  qglRasterPos3d               = safe_dlsym (g_hGLDLL, "glRasterPos3d" );
+  qglRasterPos3dv              = safe_dlsym (g_hGLDLL, "glRasterPos3dv" );
+  qglRasterPos3f               = safe_dlsym (g_hGLDLL, "glRasterPos3f" );
+  qglRasterPos3fv              = safe_dlsym (g_hGLDLL, "glRasterPos3fv" );
+  qglRasterPos3i               = safe_dlsym (g_hGLDLL, "glRasterPos3i" );
+  qglRasterPos3iv              = safe_dlsym (g_hGLDLL, "glRasterPos3iv" );
+  qglRasterPos3s               = safe_dlsym (g_hGLDLL, "glRasterPos3s" );
+  qglRasterPos3sv              = safe_dlsym (g_hGLDLL, "glRasterPos3sv" );
+  qglRasterPos4d               = safe_dlsym (g_hGLDLL, "glRasterPos4d" );
+  qglRasterPos4dv              = safe_dlsym (g_hGLDLL, "glRasterPos4dv" );
+  qglRasterPos4f               = safe_dlsym (g_hGLDLL, "glRasterPos4f" );
+  qglRasterPos4fv              = safe_dlsym (g_hGLDLL, "glRasterPos4fv" );
+  qglRasterPos4i               = safe_dlsym (g_hGLDLL, "glRasterPos4i" );
+  qglRasterPos4iv              = safe_dlsym (g_hGLDLL, "glRasterPos4iv" );
+  qglRasterPos4s               = safe_dlsym (g_hGLDLL, "glRasterPos4s" );
+  qglRasterPos4sv              = safe_dlsym (g_hGLDLL, "glRasterPos4sv" );
+  qglReadBuffer                = safe_dlsym (g_hGLDLL, "glReadBuffer" );
+  qglReadPixels                = safe_dlsym (g_hGLDLL, "glReadPixels" );
+  qglRectd                     = safe_dlsym (g_hGLDLL, "glRectd" );
+  qglRectdv                    = safe_dlsym (g_hGLDLL, "glRectdv" );
+  qglRectf                     = safe_dlsym (g_hGLDLL, "glRectf" );
+  qglRectfv                    = safe_dlsym (g_hGLDLL, "glRectfv" );
+  qglRecti                     = safe_dlsym (g_hGLDLL, "glRecti" );
+  qglRectiv                    = safe_dlsym (g_hGLDLL, "glRectiv" );
+  qglRects                     = safe_dlsym (g_hGLDLL, "glRects" );
+  qglRectsv                    = safe_dlsym (g_hGLDLL, "glRectsv" );
+  qglRenderMode                = safe_dlsym (g_hGLDLL, "glRenderMode" );
+  qglRotated                   = safe_dlsym (g_hGLDLL, "glRotated" );
+  qglRotatef                   = safe_dlsym (g_hGLDLL, "glRotatef" );
+  qglScaled                    = safe_dlsym (g_hGLDLL, "glScaled" );
+  qglScalef                    = safe_dlsym (g_hGLDLL, "glScalef" );
+  qglScissor                   = safe_dlsym (g_hGLDLL, "glScissor" );
+  qglSelectBuffer              = safe_dlsym (g_hGLDLL, "glSelectBuffer" );
+  qglShadeModel                = safe_dlsym (g_hGLDLL, "glShadeModel" );
+  qglStencilFunc               = safe_dlsym (g_hGLDLL, "glStencilFunc" );
+  qglStencilMask               = safe_dlsym (g_hGLDLL, "glStencilMask" );
+  qglStencilOp                 = safe_dlsym (g_hGLDLL, "glStencilOp" );
+  qglTexCoord1d                = safe_dlsym (g_hGLDLL, "glTexCoord1d" );
+  qglTexCoord1dv               = safe_dlsym (g_hGLDLL, "glTexCoord1dv" );
+  qglTexCoord1f                = safe_dlsym (g_hGLDLL, "glTexCoord1f" );
+  qglTexCoord1fv               = safe_dlsym (g_hGLDLL, "glTexCoord1fv" );
+  qglTexCoord1i                = safe_dlsym (g_hGLDLL, "glTexCoord1i" );
+  qglTexCoord1iv               = safe_dlsym (g_hGLDLL, "glTexCoord1iv" );
+  qglTexCoord1s                = safe_dlsym (g_hGLDLL, "glTexCoord1s" );
+  qglTexCoord1sv               = safe_dlsym (g_hGLDLL, "glTexCoord1sv" );
+  qglTexCoord2d                = safe_dlsym (g_hGLDLL, "glTexCoord2d" );
+  qglTexCoord2dv               = safe_dlsym (g_hGLDLL, "glTexCoord2dv" );
+  qglTexCoord2f                = safe_dlsym (g_hGLDLL, "glTexCoord2f" );
+  qglTexCoord2fv               = safe_dlsym (g_hGLDLL, "glTexCoord2fv" );
+  qglTexCoord2i                = safe_dlsym (g_hGLDLL, "glTexCoord2i" );
+  qglTexCoord2iv               = safe_dlsym (g_hGLDLL, "glTexCoord2iv" );
+  qglTexCoord2s                = safe_dlsym (g_hGLDLL, "glTexCoord2s" );
+  qglTexCoord2sv               = safe_dlsym (g_hGLDLL, "glTexCoord2sv" );
+  qglTexCoord3d                = safe_dlsym (g_hGLDLL, "glTexCoord3d" );
+  qglTexCoord3dv               = safe_dlsym (g_hGLDLL, "glTexCoord3dv" );
+  qglTexCoord3f                = safe_dlsym (g_hGLDLL, "glTexCoord3f" );
+  qglTexCoord3fv               = safe_dlsym (g_hGLDLL, "glTexCoord3fv" );
+  qglTexCoord3i                = safe_dlsym (g_hGLDLL, "glTexCoord3i" );
+  qglTexCoord3iv               = safe_dlsym (g_hGLDLL, "glTexCoord3iv" );
+  qglTexCoord3s                = safe_dlsym (g_hGLDLL, "glTexCoord3s" );
+  qglTexCoord3sv               = safe_dlsym (g_hGLDLL, "glTexCoord3sv" );
+  qglTexCoord4d                = safe_dlsym (g_hGLDLL, "glTexCoord4d" );
+  qglTexCoord4dv               = safe_dlsym (g_hGLDLL, "glTexCoord4dv" );
+  qglTexCoord4f                = safe_dlsym (g_hGLDLL, "glTexCoord4f" );
+  qglTexCoord4fv               = safe_dlsym (g_hGLDLL, "glTexCoord4fv" );
+  qglTexCoord4i                = safe_dlsym (g_hGLDLL, "glTexCoord4i" );
+  qglTexCoord4iv               = safe_dlsym (g_hGLDLL, "glTexCoord4iv" );
+  qglTexCoord4s                = safe_dlsym (g_hGLDLL, "glTexCoord4s" );
+  qglTexCoord4sv               = safe_dlsym (g_hGLDLL, "glTexCoord4sv" );
+  qglTexCoordPointer           = safe_dlsym (g_hGLDLL, "glTexCoordPointer" );
+  qglTexEnvf                   = safe_dlsym (g_hGLDLL, "glTexEnvf" );
+  qglTexEnvfv                  = safe_dlsym (g_hGLDLL, "glTexEnvfv" );
+  qglTexEnvi                   = safe_dlsym (g_hGLDLL, "glTexEnvi" );
+  qglTexEnviv                  = safe_dlsym (g_hGLDLL, "glTexEnviv" );
+  qglTexGend                   = safe_dlsym (g_hGLDLL, "glTexGend" );
+  qglTexGendv                  = safe_dlsym (g_hGLDLL, "glTexGendv" );
+  qglTexGenf                   = safe_dlsym (g_hGLDLL, "glTexGenf" );
+  qglTexGenfv                  = safe_dlsym (g_hGLDLL, "glTexGenfv" );
+  qglTexGeni                   = safe_dlsym (g_hGLDLL, "glTexGeni" );
+  qglTexGeniv                  = safe_dlsym (g_hGLDLL, "glTexGeniv" );
+  qglTexImage1D                = safe_dlsym (g_hGLDLL, "glTexImage1D" );
+  qglTexImage2D                = safe_dlsym (g_hGLDLL, "glTexImage2D" );
+  qglTexParameterf             = safe_dlsym (g_hGLDLL, "glTexParameterf" );
+  qglTexParameterfv            = safe_dlsym (g_hGLDLL, "glTexParameterfv" );
+  qglTexParameteri             = safe_dlsym (g_hGLDLL, "glTexParameteri" );
+  qglTexParameteriv            = safe_dlsym (g_hGLDLL, "glTexParameteriv" );
+  qglTexSubImage1D             = safe_dlsym (g_hGLDLL, "glTexSubImage1D" );
+  qglTexSubImage2D             = safe_dlsym (g_hGLDLL, "glTexSubImage2D" );
+  qglTranslated                = safe_dlsym (g_hGLDLL, "glTranslated" );
+  qglTranslatef                = safe_dlsym (g_hGLDLL, "glTranslatef" );
+  qglVertex2d                  = safe_dlsym (g_hGLDLL, "glVertex2d" );
+  qglVertex2dv                 = safe_dlsym (g_hGLDLL, "glVertex2dv" );
+  qglVertex2f                  = safe_dlsym (g_hGLDLL, "glVertex2f" );
+  qglVertex2fv                 = safe_dlsym (g_hGLDLL, "glVertex2fv" );
+  qglVertex2i                  = safe_dlsym (g_hGLDLL, "glVertex2i" );
+  qglVertex2iv                 = safe_dlsym (g_hGLDLL, "glVertex2iv" );
+  qglVertex2s                  = safe_dlsym (g_hGLDLL, "glVertex2s" );
+  qglVertex2sv                 = safe_dlsym (g_hGLDLL, "glVertex2sv" );
+  qglVertex3d                  = safe_dlsym (g_hGLDLL, "glVertex3d" );
+  qglVertex3dv                 = safe_dlsym (g_hGLDLL, "glVertex3dv" );
+  qglVertex3f                  = safe_dlsym (g_hGLDLL, "glVertex3f" );
+  qglVertex3fv                 = safe_dlsym (g_hGLDLL, "glVertex3fv" );
+  qglVertex3i                  = safe_dlsym (g_hGLDLL, "glVertex3i" );
+  qglVertex3iv                 = safe_dlsym (g_hGLDLL, "glVertex3iv" );
+  qglVertex3s                  = safe_dlsym (g_hGLDLL, "glVertex3s" );
+  qglVertex3sv                 = safe_dlsym (g_hGLDLL, "glVertex3sv" );
+  qglVertex4d                  = safe_dlsym (g_hGLDLL, "glVertex4d" );
+  qglVertex4dv                 = safe_dlsym (g_hGLDLL, "glVertex4dv" );
+  qglVertex4f                  = safe_dlsym (g_hGLDLL, "glVertex4f" );
+  qglVertex4fv                 = safe_dlsym (g_hGLDLL, "glVertex4fv" );
+  qglVertex4i                  = safe_dlsym (g_hGLDLL, "glVertex4i" );
+  qglVertex4iv                 = safe_dlsym (g_hGLDLL, "glVertex4iv" );
+  qglVertex4s                  = safe_dlsym (g_hGLDLL, "glVertex4s" );
+  qglVertex4sv                 = safe_dlsym (g_hGLDLL, "glVertex4sv" );
+  qglVertexPointer             = safe_dlsym (g_hGLDLL, "glVertexPointer" );
+  qglViewport                  = safe_dlsym (g_hGLDLL, "glViewport" );
+
+  // must be init with an active context
+  qglActiveTextureARB = NULL;
+  qglClientActiveTextureARB = NULL;
+  qglMultiTexCoord1dARB = NULL;
+  qglMultiTexCoord1dvARB = NULL;
+  qglMultiTexCoord1fARB = NULL;
+  qglMultiTexCoord1fvARB = NULL;
+  qglMultiTexCoord1iARB = NULL;
+  qglMultiTexCoord1ivARB = NULL;
+  qglMultiTexCoord1sARB = NULL;
+  qglMultiTexCoord1svARB = NULL;
+  qglMultiTexCoord2dARB = NULL;
+  qglMultiTexCoord2dvARB = NULL;
+  qglMultiTexCoord2fARB = NULL;
+  qglMultiTexCoord2fvARB = NULL;
+  qglMultiTexCoord2iARB = NULL;
+  qglMultiTexCoord2ivARB = NULL;
+  qglMultiTexCoord2sARB = NULL;
+  qglMultiTexCoord2svARB = NULL;
+  qglMultiTexCoord3dARB = NULL;
+  qglMultiTexCoord3dvARB = NULL;
+  qglMultiTexCoord3fARB = NULL;
+  qglMultiTexCoord3fvARB = NULL;
+  qglMultiTexCoord3iARB = NULL;
+  qglMultiTexCoord3ivARB = NULL;
+  qglMultiTexCoord3sARB = NULL;
+  qglMultiTexCoord3svARB = NULL;
+  qglMultiTexCoord4dARB = NULL;
+  qglMultiTexCoord4dvARB = NULL;
+  qglMultiTexCoord4fARB = NULL;
+  qglMultiTexCoord4fvARB = NULL;
+  qglMultiTexCoord4iARB = NULL;
+  qglMultiTexCoord4ivARB = NULL;
+  qglMultiTexCoord4sARB = NULL;
+  qglMultiTexCoord4svARB = NULL;
+
+#ifdef _WIN32
+    qwglCopyContext              = safe_dlsym(g_hGLDLL, "wglCopyContext" );
+    qwglCreateContext            = safe_dlsym(g_hGLDLL, "wglCreateContext");
+    qwglCreateLayerContext       = safe_dlsym(g_hGLDLL, "wglCreateLayerContext" );
+    qwglDeleteContext            = safe_dlsym(g_hGLDLL, "wglDeleteContext");
+    qwglDescribeLayerPlane       = safe_dlsym(g_hGLDLL, "wglDescribeLayerPlane" );
+    qwglGetCurrentContext        = safe_dlsym(g_hGLDLL, "wglGetCurrentContext" );
+    qwglGetCurrentDC             = safe_dlsym(g_hGLDLL, "wglGetCurrentDC" );
+    qwglGetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglGetLayerPaletteEntries" );
+    qwglGetProcAddress           = safe_dlsym(g_hGLDLL, "wglGetProcAddress" );
+    qwglMakeCurrent              = safe_dlsym(g_hGLDLL, "wglMakeCurrent" );
+    qwglRealizeLayerPalette      = safe_dlsym(g_hGLDLL, "wglRealizeLayerPalette" );
+    qwglSetLayerPaletteEntries   = safe_dlsym(g_hGLDLL, "wglSetLayerPaletteEntries" );
+    qwglShareLists               = safe_dlsym(g_hGLDLL, "wglShareLists" );
+    qwglSwapLayerBuffers         = safe_dlsym(g_hGLDLL, "wglSwapLayerBuffers" );
+    qwglUseFontBitmaps           = safe_dlsym(g_hGLDLL, "wglUseFontBitmapsA" );
+    qwglUseFontOutlines          = safe_dlsym(g_hGLDLL, "wglUseFontOutlinesA" );
+
+    qwglChoosePixelFormat        = safe_dlsym(g_hGLDLL, "wglChoosePixelFormat" );
+    qwglDescribePixelFormat      = safe_dlsym(g_hGLDLL, "wglDescribePixelFormat" );
+    qwglGetPixelFormat           = safe_dlsym(g_hGLDLL, "wglGetPixelFormat" );
+    qwglSetPixelFormat           = safe_dlsym(g_hGLDLL, "wglSetPixelFormat" );
+    qwglSwapBuffers              = safe_dlsym(g_hGLDLL, "wglSwapBuffers" );
+
+    qwglSwapIntervalEXT = 0;
+    qglPointParameterfEXT = 0;
+    qglPointParameterfvEXT = 0;
+    qglColorTableEXT = 0;
+    qglSelectTextureSGIS = 0;
+    qglMTexCoord2fSGIS = 0;
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+  qglXChooseVisual             = safe_dlsym (g_hGLDLL, "glXChooseVisual");
+  qglXCreateContext            = safe_dlsym (g_hGLDLL, "glXCreateContext");
+  qglXDestroyContext           = safe_dlsym (g_hGLDLL, "glXDestroyContext");
+  qglXMakeCurrent              = safe_dlsym (g_hGLDLL, "glXMakeCurrent");
+  qglXCopyContext              = safe_dlsym (g_hGLDLL, "glXCopyContext");
+  qglXSwapBuffers              = safe_dlsym (g_hGLDLL, "glXSwapBuffers");
+  qglXCreateGLXPixmap          = safe_dlsym (g_hGLDLL, "glXCreateGLXPixmap");
+  qglXDestroyGLXPixmap         = safe_dlsym (g_hGLDLL, "glXDestroyGLXPixmap");
+  qglXQueryExtension           = safe_dlsym (g_hGLDLL, "glXQueryExtension");
+  qglXQueryVersion             = safe_dlsym (g_hGLDLL, "glXQueryVersion");
+  qglXIsDirect                 = safe_dlsym (g_hGLDLL, "glXIsDirect");
+  qglXGetConfig                = safe_dlsym (g_hGLDLL, "glXGetConfig");
+  qglXGetCurrentContext        = safe_dlsym (g_hGLDLL, "glXGetCurrentContext");
+  qglXGetCurrentDrawable       = safe_dlsym (g_hGLDLL, "glXGetCurrentDrawable");
+  qglXWaitGL                   = safe_dlsym (g_hGLDLL, "glXWaitGL");
+  qglXWaitX                    = safe_dlsym (g_hGLDLL, "glXWaitX");
+  qglXUseXFont                 = safe_dlsym (g_hGLDLL, "glXUseXFont");
+//  qglXGetProcAddressARB        = dlsym (g_hGLDLL, "glXGetProcAddressARB"); // Utah-GLX fix
+#endif
+
+  qglPointParameterfEXT = 0;
+  qglPointParameterfvEXT = 0;
+  qglColorTableEXT = 0;
+  qglSelectTextureSGIS = 0;
+  qglMTexCoord2fSGIS = 0;
+
+  // texture compression 
+  Sys_Printf ("Done.\n");
+
+#ifdef ATIHACK_812
+  ATIhack_culling = 0;
+  ATIhack_cullmode = GL_BACK;
+  ATIhack_backmode = GL_FILL;
+  ATIhack_frontmode = GL_FILL;
+#endif
+
+  if (init_error == 1)
+    return 0;
+
+  return 1;
+}
+
+int GL_ExtensionSupported (const char *extension)
+{
+  const GLubyte *extensions = NULL;
+  const GLubyte *start;
+  GLubyte *where, *terminator;
+
+  // Extension names should not have spaces.
+  where = (GLubyte *) strchr (extension, ' ');
+  if (where || *extension == '\0')
+    return 0;
+
+  extensions = qglGetString (GL_EXTENSIONS);
+#ifndef __APPLE__
+  if (!extensions)
+    return 0;
+#endif
+
+  // It takes a bit of care to be fool-proof about parsing the
+  // OpenGL extensions string. Don't be fooled by sub-strings, etc.
+  for (start = extensions; ;)
+  {
+    where = (GLubyte *) strstr ((const char *) start, extension);
+    if (!where)
+      break;
+
+    terminator = where + strlen (extension);
+    if (where == start || *(where - 1) == ' ')
+      if (*terminator == ' ' || *terminator == '\0')
+        return 1;
+
+    start = terminator;
+  }
+
+  return 0;
+}
+
+void* Sys_GLGetExtension (const char *symbol)
+{
+#if defined (__linux__) || defined (__APPLE__)
+  if (qglXGetProcAddressARB == NULL)
+    return NULL;
+  else
+    return qglXGetProcAddressARB ((GLubyte*)symbol);
+#else
+  return qwglGetProcAddress (symbol);
+#endif
+}
+
+void QGL_InitExtensions ()
+{
+  if (GL_ExtensionSupported ("GL_ARB_multitexture"))
+  {
+    qglActiveTextureARB = Sys_GLGetExtension ("glActiveTextureARB");
+    qglClientActiveTextureARB = Sys_GLGetExtension ("glClientActiveTextureARB");
+    qglMultiTexCoord1dARB = Sys_GLGetExtension ("glMultiTexCoord1dARB");
+    qglMultiTexCoord1dvARB = Sys_GLGetExtension ("glMultiTexCoord1dvARB");
+    qglMultiTexCoord1fARB = Sys_GLGetExtension ("glMultiTexCoord1fARB");
+    qglMultiTexCoord1fvARB = Sys_GLGetExtension ("glMultiTexCoord1fvARB");
+    qglMultiTexCoord1iARB = Sys_GLGetExtension ("glMultiTexCoord1iARB");
+    qglMultiTexCoord1ivARB = Sys_GLGetExtension ("glMultiTexCoord1ivARB");
+    qglMultiTexCoord1sARB = Sys_GLGetExtension ("glMultiTexCoord1sARB");
+    qglMultiTexCoord1svARB = Sys_GLGetExtension ("glMultiTexCoord1svARB");
+    qglMultiTexCoord2dARB = Sys_GLGetExtension ("glMultiTexCoord2dARB");
+    qglMultiTexCoord2dvARB = Sys_GLGetExtension ("glMultiTexCoord2dvARB");
+    qglMultiTexCoord2fARB = Sys_GLGetExtension ("glMultiTexCoord2fARB");
+    qglMultiTexCoord2fvARB = Sys_GLGetExtension ("glMultiTexCoord2fvARB");
+    qglMultiTexCoord2iARB = Sys_GLGetExtension ("glMultiTexCoord2iARB");
+    qglMultiTexCoord2ivARB = Sys_GLGetExtension ("glMultiTexCoord2ivARB");
+    qglMultiTexCoord2sARB = Sys_GLGetExtension ("glMultiTexCoord2sARB");
+    qglMultiTexCoord2svARB = Sys_GLGetExtension ("glMultiTexCoord2svARB");
+    qglMultiTexCoord3dARB = Sys_GLGetExtension ("glMultiTexCoord3dARB");
+    qglMultiTexCoord3dvARB = Sys_GLGetExtension ("glMultiTexCoord3dvARB");
+    qglMultiTexCoord3fARB = Sys_GLGetExtension ("glMultiTexCoord3fARB");
+    qglMultiTexCoord3fvARB = Sys_GLGetExtension ("glMultiTexCoord3fvARB");
+    qglMultiTexCoord3iARB = Sys_GLGetExtension ("glMultiTexCoord3iARB");
+    qglMultiTexCoord3ivARB = Sys_GLGetExtension ("glMultiTexCoord3ivARB");
+    qglMultiTexCoord3sARB = Sys_GLGetExtension ("glMultiTexCoord3sARB");
+    qglMultiTexCoord3svARB = Sys_GLGetExtension ("glMultiTexCoord3svARB");
+    qglMultiTexCoord4dARB = Sys_GLGetExtension ("glMultiTexCoord4dARB");
+    qglMultiTexCoord4dvARB = Sys_GLGetExtension ("glMultiTexCoord4dvARB");
+    qglMultiTexCoord4fARB = Sys_GLGetExtension ("glMultiTexCoord4fARB");
+    qglMultiTexCoord4fvARB = Sys_GLGetExtension ("glMultiTexCoord4fvARB");
+    qglMultiTexCoord4iARB = Sys_GLGetExtension ("glMultiTexCoord4iARB");
+    qglMultiTexCoord4ivARB = Sys_GLGetExtension ("glMultiTexCoord4ivARB");
+    qglMultiTexCoord4sARB = Sys_GLGetExtension ("glMultiTexCoord4sARB");
+    qglMultiTexCoord4svARB = Sys_GLGetExtension ("glMultiTexCoord4svARB");
+  }
+}
diff --git a/radiant/qgl.h b/radiant/qgl.h
index 6f4decc6..faccdb2f 100644
--- a/radiant/qgl.h
+++ b/radiant/qgl.h
@@ -1,600 +1,600 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-** QGL.H
-*/
-
-#ifndef __QGL_H__
-#define __QGL_H__
-
-// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=812
-#define ATIHACK_812
-
-#include <GL/gl.h>
-
-#if defined (__linux__) || defined (__APPLE__)
-#include <GL/glx.h>
-#endif
-
-#if defined (__APPLE__)
-#include <GL/glu.h>
-#endif
-
-#ifndef GL_ARB_multitexture
-#define GL_TEXTURE0_ARB                   0x84C0
-#define GL_TEXTURE1_ARB                   0x84C1
-#define GL_TEXTURE2_ARB                   0x84C2
-#define GL_TEXTURE3_ARB                   0x84C3
-#define GL_TEXTURE4_ARB                   0x84C4
-#define GL_TEXTURE5_ARB                   0x84C5
-#define GL_TEXTURE6_ARB                   0x84C6
-#define GL_TEXTURE7_ARB                   0x84C7
-#define GL_TEXTURE8_ARB                   0x84C8
-#define GL_TEXTURE9_ARB                   0x84C9
-#define GL_TEXTURE10_ARB                  0x84CA
-#define GL_TEXTURE11_ARB                  0x84CB
-#define GL_TEXTURE12_ARB                  0x84CC
-#define GL_TEXTURE13_ARB                  0x84CD
-#define GL_TEXTURE14_ARB                  0x84CE
-#define GL_TEXTURE15_ARB                  0x84CF
-#define GL_TEXTURE16_ARB                  0x84D0
-#define GL_TEXTURE17_ARB                  0x84D1
-#define GL_TEXTURE18_ARB                  0x84D2
-#define GL_TEXTURE19_ARB                  0x84D3
-#define GL_TEXTURE20_ARB                  0x84D4
-#define GL_TEXTURE21_ARB                  0x84D5
-#define GL_TEXTURE22_ARB                  0x84D6
-#define GL_TEXTURE23_ARB                  0x84D7
-#define GL_TEXTURE24_ARB                  0x84D8
-#define GL_TEXTURE25_ARB                  0x84D9
-#define GL_TEXTURE26_ARB                  0x84DA
-#define GL_TEXTURE27_ARB                  0x84DB
-#define GL_TEXTURE28_ARB                  0x84DC
-#define GL_TEXTURE29_ARB                  0x84DD
-#define GL_TEXTURE30_ARB                  0x84DE
-#define GL_TEXTURE31_ARB                  0x84DF
-#define GL_ACTIVE_TEXTURE_ARB             0x84E0
-#define GL_CLIENT_ACTIVE_TEXTURE_ARB      0x84E1
-#define GL_MAX_TEXTURE_UNITS_ARB          0x84E2
-#endif
-
-#ifndef GL_VERSION_1_3
-// this is hacky, I'd recommend people having GL 1.3 headers instead
-#define GL_COMPRESSED_RGBA 0x84EE
-// RIANT
-// this would be the appropriate place for this
-#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
-#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
-#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
-
-#endif
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-int  QGL_Init( const char *dllname, const char* pGluName );
-void QGL_InitExtensions ();
-void QGL_Shutdown();
-
-// silent query, see Sys_QGL_ExtensionSupported
-int GL_ExtensionSupported (const char *extension);
-
-#ifndef APIENTRY
-#  define APIENTRY
-#endif
-
-extern  void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
-extern  void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
-extern  GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
-extern  void ( APIENTRY * qglArrayElement )(GLint i);
-extern  void ( APIENTRY * qglBegin )(GLenum mode);
-extern  void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
-extern  void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
-extern  void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
-extern  void ( APIENTRY * qglCallList )(GLuint list);
-extern  void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
-extern  void ( APIENTRY * qglClear )(GLbitfield mask);
-extern  void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-extern  void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
-extern  void ( APIENTRY * qglClearDepth )(GLclampd depth);
-extern  void ( APIENTRY * qglClearIndex )(GLfloat c);
-extern  void ( APIENTRY * qglClearStencil )(GLint s);
-extern  void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
-extern  void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
-extern  void ( APIENTRY * qglColor3bv )(const GLbyte *v);
-extern  void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
-extern  void ( APIENTRY * qglColor3dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
-extern  void ( APIENTRY * qglColor3fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
-extern  void ( APIENTRY * qglColor3iv )(const GLint *v);
-extern  void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
-extern  void ( APIENTRY * qglColor3sv )(const GLshort *v);
-extern  void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
-extern  void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
-extern  void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
-extern  void ( APIENTRY * qglColor3uiv )(const GLuint *v);
-extern  void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
-extern  void ( APIENTRY * qglColor3usv )(const GLushort *v);
-extern  void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
-extern  void ( APIENTRY * qglColor4bv )(const GLbyte *v);
-extern  void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
-extern  void ( APIENTRY * qglColor4dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
-extern  void ( APIENTRY * qglColor4fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
-extern  void ( APIENTRY * qglColor4iv )(const GLint *v);
-extern  void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
-extern  void ( APIENTRY * qglColor4sv )(const GLshort *v);
-extern  void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
-extern  void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
-extern  void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
-extern  void ( APIENTRY * qglColor4uiv )(const GLuint *v);
-extern  void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
-extern  void ( APIENTRY * qglColor4usv )(const GLushort *v);
-extern  void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
-extern  void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
-extern  void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-extern  void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
-extern  void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
-extern  void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
-extern  void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
-extern  void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
-extern  void ( APIENTRY * qglCullFace )(GLenum mode);
-extern  void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
-extern  void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
-extern  void ( APIENTRY * qglDepthFunc )(GLenum func);
-extern  void ( APIENTRY * qglDepthMask )(GLboolean flag);
-extern  void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
-extern  void ( APIENTRY * qglDisable )(GLenum cap);
-extern  void ( APIENTRY * qglDisableClientState )(GLenum array);
-extern  void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
-extern  void ( APIENTRY * qglDrawBuffer )(GLenum mode);
-extern  void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
-extern  void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-extern  void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
-extern  void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
-extern  void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
-extern  void ( APIENTRY * qglEnable )(GLenum cap);
-extern  void ( APIENTRY * qglEnableClientState )(GLenum array);
-extern  void ( APIENTRY * qglEnd )(void);
-extern  void ( APIENTRY * qglEndList )(void);
-extern  void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
-extern  void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
-extern  void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
-extern  void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
-extern  void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
-extern  void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
-extern  void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
-extern  void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
-extern  void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
-extern  void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
-extern  void ( APIENTRY * qglEvalPoint1 )(GLint i);
-extern  void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
-extern  void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
-extern  void ( APIENTRY * qglFinish )(void);
-extern  void ( APIENTRY * qglFlush )(void);
-extern  void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
-extern  void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
-extern  void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
-extern  void ( APIENTRY * qglFrontFace )(GLenum mode);
-extern  void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-extern  GLuint ( APIENTRY * qglGenLists )(GLsizei range);
-extern  void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
-extern  void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
-extern  void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
-extern  void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
-extern  GLenum ( APIENTRY * qglGetError )(void);
-extern  void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
-extern  void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
-extern  void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
-extern  void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
-extern  void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
-extern  void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
-extern  void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
-extern  void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
-extern  void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
-extern  void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
-extern  void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
-extern  void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
-extern  void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
-extern  void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
-extern  const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
-extern  void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
-extern  void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
-extern  void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
-extern  void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
-extern  void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
-extern  void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
-extern  void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
-extern  void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
-extern  void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
-extern  void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
-extern  void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
-extern  void ( APIENTRY * qglIndexMask )(GLuint mask);
-extern  void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-extern  void ( APIENTRY * qglIndexd )(GLdouble c);
-extern  void ( APIENTRY * qglIndexdv )(const GLdouble *c);
-extern  void ( APIENTRY * qglIndexf )(GLfloat c);
-extern  void ( APIENTRY * qglIndexfv )(const GLfloat *c);
-extern  void ( APIENTRY * qglIndexi )(GLint c);
-extern  void ( APIENTRY * qglIndexiv )(const GLint *c);
-extern  void ( APIENTRY * qglIndexs )(GLshort c);
-extern  void ( APIENTRY * qglIndexsv )(const GLshort *c);
-extern  void ( APIENTRY * qglIndexub )(GLubyte c);
-extern  void ( APIENTRY * qglIndexubv )(const GLubyte *c);
-extern  void ( APIENTRY * qglInitNames )(void);
-extern  void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
-extern  GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
-extern  GLboolean ( APIENTRY * qglIsList )(GLuint list);
-extern  GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
-extern  void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
-extern  void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
-extern  void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
-extern  void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
-extern  void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
-extern  void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
-extern  void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
-extern  void ( APIENTRY * qglLineWidth )(GLfloat width);
-extern  void ( APIENTRY * qglListBase )(GLuint base);
-extern  void ( APIENTRY * qglLoadIdentity )(void);
-extern  void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
-extern  void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
-extern  void ( APIENTRY * qglLoadName )(GLuint name);
-extern  void ( APIENTRY * qglLogicOp )(GLenum opcode);
-extern  void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
-extern  void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
-extern  void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
-extern  void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
-extern  void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
-extern  void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
-extern  void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
-extern  void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
-extern  void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
-extern  void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
-extern  void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
-extern  void ( APIENTRY * qglMatrixMode )(GLenum mode);
-extern  void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
-extern  void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
-extern  void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
-extern  void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
-extern  void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
-extern  void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
-extern  void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
-extern  void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
-extern  void ( APIENTRY * qglNormal3iv )(const GLint *v);
-extern  void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
-extern  void ( APIENTRY * qglNormal3sv )(const GLshort *v);
-extern  void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
-extern  void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
-extern  void ( APIENTRY * qglPassThrough )(GLfloat token);
-extern  void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
-extern  void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
-extern  void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
-extern  void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
-extern  void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
-extern  void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
-extern  void ( APIENTRY * qglPointSize )(GLfloat size);
-extern  void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
-extern  void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
-extern  void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
-extern  void ( APIENTRY * qglPopAttrib )(void);
-extern  void ( APIENTRY * qglPopClientAttrib )(void);
-extern  void ( APIENTRY * qglPopMatrix )(void);
-extern  void ( APIENTRY * qglPopName )(void);
-extern  void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
-extern  void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
-extern  void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
-extern  void ( APIENTRY * qglPushMatrix )(void);
-extern  void ( APIENTRY * qglPushName )(GLuint name);
-extern  void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
-extern  void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
-extern  void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
-extern  void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
-extern  void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
-extern  void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
-extern  void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
-extern  void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
-extern  void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
-extern  void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
-extern  void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
-extern  void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
-extern  void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-extern  void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-extern  void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
-extern  void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
-extern  void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-extern  void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
-extern  void ( APIENTRY * qglReadBuffer )(GLenum mode);
-extern  void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
-extern  void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
-extern  void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
-extern  void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
-extern  void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
-extern  void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
-extern  void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
-extern  void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
-extern  void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
-extern  GLint ( APIENTRY * qglRenderMode )(GLenum mode);
-extern  void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
-extern  void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
-extern  void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
-extern  void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
-extern  void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
-extern  void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
-extern  void ( APIENTRY * qglShadeModel )(GLenum mode);
-extern  void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
-extern  void ( APIENTRY * qglStencilMask )(GLuint mask);
-extern  void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
-extern  void ( APIENTRY * qglTexCoord1d )(GLdouble s);
-extern  void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglTexCoord1f )(GLfloat s);
-extern  void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglTexCoord1i )(GLint s);
-extern  void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
-extern  void ( APIENTRY * qglTexCoord1s )(GLshort s);
-extern  void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
-extern  void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
-extern  void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
-extern  void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
-extern  void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
-extern  void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
-extern  void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
-extern  void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
-extern  void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
-extern  void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
-extern  void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
-extern  void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
-extern  void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
-extern  void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
-extern  void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
-extern  void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
-extern  void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
-extern  void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
-extern  void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
-extern  void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-extern  void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
-extern  void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
-extern  void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
-extern  void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
-extern  void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
-extern  void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
-extern  void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
-extern  void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
-extern  void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-extern  void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
-extern  void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
-extern  void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
-extern  void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
-extern  void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
-extern  void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
-extern  void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
-extern  void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
-extern  void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
-extern  void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
-extern  void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
-extern  void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
-extern  void ( APIENTRY * qglVertex2iv )(const GLint *v);
-extern  void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
-extern  void ( APIENTRY * qglVertex2sv )(const GLshort *v);
-extern  void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
-extern  void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
-extern  void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
-extern  void ( APIENTRY * qglVertex3iv )(const GLint *v);
-extern  void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
-extern  void ( APIENTRY * qglVertex3sv )(const GLshort *v);
-extern  void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
-extern  void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
-extern  void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
-extern  void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
-extern  void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
-extern  void ( APIENTRY * qglVertex4iv )(const GLint *v);
-extern  void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
-extern  void ( APIENTRY * qglVertex4sv )(const GLshort *v);
-extern  void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
-extern  void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
-
-extern	void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
-extern	void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
-extern	void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
-
-extern	void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
-extern	void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
-
-extern	void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
-extern	void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
-extern	void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
-extern	void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
-extern	void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
-extern	void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
-extern	void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
-extern	void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
-extern	void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
-extern	void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
-extern	void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
-extern	void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
-extern	void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
-extern	void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
-extern	void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
-extern	void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
-extern	void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
-extern	void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
-extern	void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
-extern	void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
-extern	void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
-extern	void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
-extern	void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
-extern	void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
-extern	void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
-extern	void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
-extern	void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
-extern	void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
-extern	void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
-extern	void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
-extern	void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
-extern	void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
-extern	void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
-extern	void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
-
-
-
-#ifdef _WIN32
-
-extern  int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
-extern  int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
-extern  int   ( WINAPI * qwglGetPixelFormat)(HDC);
-extern  BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
-extern  BOOL  ( WINAPI * qwglSwapBuffers)(HDC);
-
-extern BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
-extern HGLRC ( WINAPI * qwglCreateContext)(HDC);
-extern HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
-extern BOOL  ( WINAPI * qwglDeleteContext)(HGLRC);
-extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
-extern HDC   ( WINAPI * qwglGetCurrentDC)(VOID);
-extern PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR);
-extern BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
-extern BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
-extern BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
-
-extern BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
-                                           FLOAT, int, LPGLYPHMETRICSFLOAT);
-
-extern BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
-                                            LPLAYERPLANEDESCRIPTOR);
-extern int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
-                                                CONST COLORREF *);
-extern int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
-                                                COLORREF *);
-extern BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
-extern BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
-
-extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
-
-extern BOOL ( WINAPI * qwglGetDeviceGammaRampEXT ) ( unsigned char *pRed, unsigned char *pGreen, unsigned char *pBlue );
-extern BOOL ( WINAPI * qwglSetDeviceGammaRampEXT ) ( const unsigned char *pRed, const unsigned char *pGreen, const unsigned char *pBlue );
-
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-extern XVisualInfo* (*qglXChooseVisual)(Display *dpy, int screen, int *attribList);
-extern GLXContext   (*qglXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
-extern void         (*qglXDestroyContext)(Display *dpy, GLXContext ctx);
-extern Bool         (*qglXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
-extern void         (*qglXCopyContext)(Display *dpy, GLXContext src, GLXContext dst, GLuint mask);
-extern void         (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable );
-extern GLXPixmap    (*qglXCreateGLXPixmap)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
-extern void         (*qglXDestroyGLXPixmap)( Display *dpy, GLXPixmap pixmap );
-extern Bool         (*qglXQueryExtension)( Display *dpy, int *errorb, int *event );
-extern Bool         (*qglXQueryVersion)( Display *dpy, int *maj, int *min );
-extern Bool         (*qglXIsDirect)( Display *dpy, GLXContext ctx );
-extern int          (*qglXGetConfig)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
-extern GLXContext   (*qglXGetCurrentContext)( void );
-extern GLXDrawable  (*qglXGetCurrentDrawable)( void );
-extern void         (*qglXWaitGL)( void );
-extern void         (*qglXWaitX)( void );
-extern void         (*qglXUseXFont)( Font font, int first, int count, int list );
-extern void*        (*qglXGetProcAddressARB) (const GLubyte *procName);
-#endif
-
-#ifdef ATIHACK_812
-extern  void ( APIENTRY * qglCullFace_real )(GLenum mode);
-extern  void ( APIENTRY * qglDisable_real )(GLenum cap);
-extern  void ( APIENTRY * qglEnable_real )(GLenum cap);
-extern  void ( APIENTRY * qglPolygonMode_real )(GLenum face, GLenum mode);
-
-extern  void APIENTRY qglCullFace_ATIHack(GLenum mode);
-extern  void APIENTRY qglDisable_ATIHack(GLenum cap);
-extern  void APIENTRY qglEnable_ATIHack(GLenum cap);
-extern  void APIENTRY qglPolygonMode_ATIHack(GLenum face, GLenum mode);
-#endif
-
-// glu stuff.. radiant only uses a couple
-extern void (APIENTRY* qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
-extern void (APIENTRY* qgluLookAt)(
-  GLdouble eyex,
-  GLdouble eyey,
-  GLdouble eyez,
-  GLdouble centerx,
-  GLdouble centery,
-  GLdouble centerz,
-  GLdouble upx,
-  GLdouble upy,
-  GLdouble upz);
-extern const GLubyte * (APIENTRY * qgluErrorString) (GLenum errCode );
-
-
-// end of glu stuff
-
-
-/*
-** extension constants
-*/
-#define GL_POINT_SIZE_MIN_EXT				0x8126
-#define GL_POINT_SIZE_MAX_EXT				0x8127
-#define GL_POINT_FADE_THRESHOLD_SIZE_EXT	0x8128
-#define GL_DISTANCE_ATTENUATION_EXT			0x8129
-
-#define GL_SHARED_TEXTURE_PALETTE_EXT		0x81FB
-
-#define GL_TEXTURE0_SGIS					0x835E
-#define GL_TEXTURE1_SGIS					0x835F
-
-
-#ifdef __cplusplus
-}
-#endif // extern "C"
-
-// -------------------------------------------------------------------------------------------
-// qgl_ext.cpp API
-// -------------------------------------------------------------------------------------------
-
-int Sys_QGL_ExtensionSupported (const char *extension);
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+** QGL.H
+*/
+
+#ifndef __QGL_H__
+#define __QGL_H__
+
+// http://zerowing.idsoftware.com/bugzilla/show_bug.cgi?id=812
+#define ATIHACK_812
+
+#include <GL/gl.h>
+
+#if defined (__linux__) || defined (__APPLE__)
+#include <GL/glx.h>
+#endif
+
+#if defined (__APPLE__)
+#include <GL/glu.h>
+#endif
+
+#ifndef GL_ARB_multitexture
+#define GL_TEXTURE0_ARB                   0x84C0
+#define GL_TEXTURE1_ARB                   0x84C1
+#define GL_TEXTURE2_ARB                   0x84C2
+#define GL_TEXTURE3_ARB                   0x84C3
+#define GL_TEXTURE4_ARB                   0x84C4
+#define GL_TEXTURE5_ARB                   0x84C5
+#define GL_TEXTURE6_ARB                   0x84C6
+#define GL_TEXTURE7_ARB                   0x84C7
+#define GL_TEXTURE8_ARB                   0x84C8
+#define GL_TEXTURE9_ARB                   0x84C9
+#define GL_TEXTURE10_ARB                  0x84CA
+#define GL_TEXTURE11_ARB                  0x84CB
+#define GL_TEXTURE12_ARB                  0x84CC
+#define GL_TEXTURE13_ARB                  0x84CD
+#define GL_TEXTURE14_ARB                  0x84CE
+#define GL_TEXTURE15_ARB                  0x84CF
+#define GL_TEXTURE16_ARB                  0x84D0
+#define GL_TEXTURE17_ARB                  0x84D1
+#define GL_TEXTURE18_ARB                  0x84D2
+#define GL_TEXTURE19_ARB                  0x84D3
+#define GL_TEXTURE20_ARB                  0x84D4
+#define GL_TEXTURE21_ARB                  0x84D5
+#define GL_TEXTURE22_ARB                  0x84D6
+#define GL_TEXTURE23_ARB                  0x84D7
+#define GL_TEXTURE24_ARB                  0x84D8
+#define GL_TEXTURE25_ARB                  0x84D9
+#define GL_TEXTURE26_ARB                  0x84DA
+#define GL_TEXTURE27_ARB                  0x84DB
+#define GL_TEXTURE28_ARB                  0x84DC
+#define GL_TEXTURE29_ARB                  0x84DD
+#define GL_TEXTURE30_ARB                  0x84DE
+#define GL_TEXTURE31_ARB                  0x84DF
+#define GL_ACTIVE_TEXTURE_ARB             0x84E0
+#define GL_CLIENT_ACTIVE_TEXTURE_ARB      0x84E1
+#define GL_MAX_TEXTURE_UNITS_ARB          0x84E2
+#endif
+
+#ifndef GL_VERSION_1_3
+// this is hacky, I'd recommend people having GL 1.3 headers instead
+#define GL_COMPRESSED_RGBA 0x84EE
+// RIANT
+// this would be the appropriate place for this
+#define GL_COMPRESSED_RGBA_S3TC_DXT1_EXT  0x83F1
+#define GL_COMPRESSED_RGBA_S3TC_DXT3_EXT  0x83F2
+#define GL_COMPRESSED_RGBA_S3TC_DXT5_EXT  0x83F3
+
+#endif
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int  QGL_Init( const char *dllname, const char* pGluName );
+void QGL_InitExtensions ();
+void QGL_Shutdown();
+
+// silent query, see Sys_QGL_ExtensionSupported
+int GL_ExtensionSupported (const char *extension);
+
+#ifndef APIENTRY
+#  define APIENTRY
+#endif
+
+extern  void ( APIENTRY * qglAccum )(GLenum op, GLfloat value);
+extern  void ( APIENTRY * qglAlphaFunc )(GLenum func, GLclampf ref);
+extern  GLboolean ( APIENTRY * qglAreTexturesResident )(GLsizei n, const GLuint *textures, GLboolean *residences);
+extern  void ( APIENTRY * qglArrayElement )(GLint i);
+extern  void ( APIENTRY * qglBegin )(GLenum mode);
+extern  void ( APIENTRY * qglBindTexture )(GLenum target, GLuint texture);
+extern  void ( APIENTRY * qglBitmap )(GLsizei width, GLsizei height, GLfloat xorig, GLfloat yorig, GLfloat xmove, GLfloat ymove, const GLubyte *bitmap);
+extern  void ( APIENTRY * qglBlendFunc )(GLenum sfactor, GLenum dfactor);
+extern  void ( APIENTRY * qglCallList )(GLuint list);
+extern  void ( APIENTRY * qglCallLists )(GLsizei n, GLenum type, const GLvoid *lists);
+extern  void ( APIENTRY * qglClear )(GLbitfield mask);
+extern  void ( APIENTRY * qglClearAccum )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+extern  void ( APIENTRY * qglClearColor )(GLclampf red, GLclampf green, GLclampf blue, GLclampf alpha);
+extern  void ( APIENTRY * qglClearDepth )(GLclampd depth);
+extern  void ( APIENTRY * qglClearIndex )(GLfloat c);
+extern  void ( APIENTRY * qglClearStencil )(GLint s);
+extern  void ( APIENTRY * qglClipPlane )(GLenum plane, const GLdouble *equation);
+extern  void ( APIENTRY * qglColor3b )(GLbyte red, GLbyte green, GLbyte blue);
+extern  void ( APIENTRY * qglColor3bv )(const GLbyte *v);
+extern  void ( APIENTRY * qglColor3d )(GLdouble red, GLdouble green, GLdouble blue);
+extern  void ( APIENTRY * qglColor3dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglColor3f )(GLfloat red, GLfloat green, GLfloat blue);
+extern  void ( APIENTRY * qglColor3fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglColor3i )(GLint red, GLint green, GLint blue);
+extern  void ( APIENTRY * qglColor3iv )(const GLint *v);
+extern  void ( APIENTRY * qglColor3s )(GLshort red, GLshort green, GLshort blue);
+extern  void ( APIENTRY * qglColor3sv )(const GLshort *v);
+extern  void ( APIENTRY * qglColor3ub )(GLubyte red, GLubyte green, GLubyte blue);
+extern  void ( APIENTRY * qglColor3ubv )(const GLubyte *v);
+extern  void ( APIENTRY * qglColor3ui )(GLuint red, GLuint green, GLuint blue);
+extern  void ( APIENTRY * qglColor3uiv )(const GLuint *v);
+extern  void ( APIENTRY * qglColor3us )(GLushort red, GLushort green, GLushort blue);
+extern  void ( APIENTRY * qglColor3usv )(const GLushort *v);
+extern  void ( APIENTRY * qglColor4b )(GLbyte red, GLbyte green, GLbyte blue, GLbyte alpha);
+extern  void ( APIENTRY * qglColor4bv )(const GLbyte *v);
+extern  void ( APIENTRY * qglColor4d )(GLdouble red, GLdouble green, GLdouble blue, GLdouble alpha);
+extern  void ( APIENTRY * qglColor4dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglColor4f )(GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha);
+extern  void ( APIENTRY * qglColor4fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglColor4i )(GLint red, GLint green, GLint blue, GLint alpha);
+extern  void ( APIENTRY * qglColor4iv )(const GLint *v);
+extern  void ( APIENTRY * qglColor4s )(GLshort red, GLshort green, GLshort blue, GLshort alpha);
+extern  void ( APIENTRY * qglColor4sv )(const GLshort *v);
+extern  void ( APIENTRY * qglColor4ub )(GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha);
+extern  void ( APIENTRY * qglColor4ubv )(const GLubyte *v);
+extern  void ( APIENTRY * qglColor4ui )(GLuint red, GLuint green, GLuint blue, GLuint alpha);
+extern  void ( APIENTRY * qglColor4uiv )(const GLuint *v);
+extern  void ( APIENTRY * qglColor4us )(GLushort red, GLushort green, GLushort blue, GLushort alpha);
+extern  void ( APIENTRY * qglColor4usv )(const GLushort *v);
+extern  void ( APIENTRY * qglColorMask )(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha);
+extern  void ( APIENTRY * qglColorMaterial )(GLenum face, GLenum mode);
+extern  void ( APIENTRY * qglColorPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+extern  void ( APIENTRY * qglCopyPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum type);
+extern  void ( APIENTRY * qglCopyTexImage1D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLint border);
+extern  void ( APIENTRY * qglCopyTexImage2D )(GLenum target, GLint level, GLenum internalFormat, GLint x, GLint y, GLsizei width, GLsizei height, GLint border);
+extern  void ( APIENTRY * qglCopyTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLint x, GLint y, GLsizei width);
+extern  void ( APIENTRY * qglCopyTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLint x, GLint y, GLsizei width, GLsizei height);
+extern  void ( APIENTRY * qglCullFace )(GLenum mode);
+extern  void ( APIENTRY * qglDeleteLists )(GLuint list, GLsizei range);
+extern  void ( APIENTRY * qglDeleteTextures )(GLsizei n, const GLuint *textures);
+extern  void ( APIENTRY * qglDepthFunc )(GLenum func);
+extern  void ( APIENTRY * qglDepthMask )(GLboolean flag);
+extern  void ( APIENTRY * qglDepthRange )(GLclampd zNear, GLclampd zFar);
+extern  void ( APIENTRY * qglDisable )(GLenum cap);
+extern  void ( APIENTRY * qglDisableClientState )(GLenum array);
+extern  void ( APIENTRY * qglDrawArrays )(GLenum mode, GLint first, GLsizei count);
+extern  void ( APIENTRY * qglDrawBuffer )(GLenum mode);
+extern  void ( APIENTRY * qglDrawElements )(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices);
+extern  void ( APIENTRY * qglDrawPixels )(GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+extern  void ( APIENTRY * qglEdgeFlag )(GLboolean flag);
+extern  void ( APIENTRY * qglEdgeFlagPointer )(GLsizei stride, const GLvoid *pointer);
+extern  void ( APIENTRY * qglEdgeFlagv )(const GLboolean *flag);
+extern  void ( APIENTRY * qglEnable )(GLenum cap);
+extern  void ( APIENTRY * qglEnableClientState )(GLenum array);
+extern  void ( APIENTRY * qglEnd )(void);
+extern  void ( APIENTRY * qglEndList )(void);
+extern  void ( APIENTRY * qglEvalCoord1d )(GLdouble u);
+extern  void ( APIENTRY * qglEvalCoord1dv )(const GLdouble *u);
+extern  void ( APIENTRY * qglEvalCoord1f )(GLfloat u);
+extern  void ( APIENTRY * qglEvalCoord1fv )(const GLfloat *u);
+extern  void ( APIENTRY * qglEvalCoord2d )(GLdouble u, GLdouble v);
+extern  void ( APIENTRY * qglEvalCoord2dv )(const GLdouble *u);
+extern  void ( APIENTRY * qglEvalCoord2f )(GLfloat u, GLfloat v);
+extern  void ( APIENTRY * qglEvalCoord2fv )(const GLfloat *u);
+extern  void ( APIENTRY * qglEvalMesh1 )(GLenum mode, GLint i1, GLint i2);
+extern  void ( APIENTRY * qglEvalMesh2 )(GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2);
+extern  void ( APIENTRY * qglEvalPoint1 )(GLint i);
+extern  void ( APIENTRY * qglEvalPoint2 )(GLint i, GLint j);
+extern  void ( APIENTRY * qglFeedbackBuffer )(GLsizei size, GLenum type, GLfloat *buffer);
+extern  void ( APIENTRY * qglFinish )(void);
+extern  void ( APIENTRY * qglFlush )(void);
+extern  void ( APIENTRY * qglFogf )(GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglFogfv )(GLenum pname, const GLfloat *params);
+extern  void ( APIENTRY * qglFogi )(GLenum pname, GLint param);
+extern  void ( APIENTRY * qglFogiv )(GLenum pname, const GLint *params);
+extern  void ( APIENTRY * qglFrontFace )(GLenum mode);
+extern  void ( APIENTRY * qglFrustum )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+extern  GLuint ( APIENTRY * qglGenLists )(GLsizei range);
+extern  void ( APIENTRY * qglGenTextures )(GLsizei n, GLuint *textures);
+extern  void ( APIENTRY * qglGetBooleanv )(GLenum pname, GLboolean *params);
+extern  void ( APIENTRY * qglGetClipPlane )(GLenum plane, GLdouble *equation);
+extern  void ( APIENTRY * qglGetDoublev )(GLenum pname, GLdouble *params);
+extern  GLenum ( APIENTRY * qglGetError )(void);
+extern  void ( APIENTRY * qglGetFloatv )(GLenum pname, GLfloat *params);
+extern  void ( APIENTRY * qglGetIntegerv )(GLenum pname, GLint *params);
+extern  void ( APIENTRY * qglGetLightfv )(GLenum light, GLenum pname, GLfloat *params);
+extern  void ( APIENTRY * qglGetLightiv )(GLenum light, GLenum pname, GLint *params);
+extern  void ( APIENTRY * qglGetMapdv )(GLenum target, GLenum query, GLdouble *v);
+extern  void ( APIENTRY * qglGetMapfv )(GLenum target, GLenum query, GLfloat *v);
+extern  void ( APIENTRY * qglGetMapiv )(GLenum target, GLenum query, GLint *v);
+extern  void ( APIENTRY * qglGetMaterialfv )(GLenum face, GLenum pname, GLfloat *params);
+extern  void ( APIENTRY * qglGetMaterialiv )(GLenum face, GLenum pname, GLint *params);
+extern  void ( APIENTRY * qglGetPixelMapfv )(GLenum map, GLfloat *values);
+extern  void ( APIENTRY * qglGetPixelMapuiv )(GLenum map, GLuint *values);
+extern  void ( APIENTRY * qglGetPixelMapusv )(GLenum map, GLushort *values);
+extern  void ( APIENTRY * qglGetPointerv )(GLenum pname, GLvoid* *params);
+extern  void ( APIENTRY * qglGetPolygonStipple )(GLubyte *mask);
+extern  const GLubyte * ( APIENTRY * qglGetString )(GLenum name);
+extern  void ( APIENTRY * qglGetTexEnvfv )(GLenum target, GLenum pname, GLfloat *params);
+extern  void ( APIENTRY * qglGetTexEnviv )(GLenum target, GLenum pname, GLint *params);
+extern  void ( APIENTRY * qglGetTexGendv )(GLenum coord, GLenum pname, GLdouble *params);
+extern  void ( APIENTRY * qglGetTexGenfv )(GLenum coord, GLenum pname, GLfloat *params);
+extern  void ( APIENTRY * qglGetTexGeniv )(GLenum coord, GLenum pname, GLint *params);
+extern  void ( APIENTRY * qglGetTexImage )(GLenum target, GLint level, GLenum format, GLenum type, GLvoid *pixels);
+extern  void ( APIENTRY * qglGetTexLevelParameterfv )(GLenum target, GLint level, GLenum pname, GLfloat *params);
+extern  void ( APIENTRY * qglGetTexLevelParameteriv )(GLenum target, GLint level, GLenum pname, GLint *params);
+extern  void ( APIENTRY * qglGetTexParameterfv )(GLenum target, GLenum pname, GLfloat *params);
+extern  void ( APIENTRY * qglGetTexParameteriv )(GLenum target, GLenum pname, GLint *params);
+extern  void ( APIENTRY * qglHint )(GLenum target, GLenum mode);
+extern  void ( APIENTRY * qglIndexMask )(GLuint mask);
+extern  void ( APIENTRY * qglIndexPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+extern  void ( APIENTRY * qglIndexd )(GLdouble c);
+extern  void ( APIENTRY * qglIndexdv )(const GLdouble *c);
+extern  void ( APIENTRY * qglIndexf )(GLfloat c);
+extern  void ( APIENTRY * qglIndexfv )(const GLfloat *c);
+extern  void ( APIENTRY * qglIndexi )(GLint c);
+extern  void ( APIENTRY * qglIndexiv )(const GLint *c);
+extern  void ( APIENTRY * qglIndexs )(GLshort c);
+extern  void ( APIENTRY * qglIndexsv )(const GLshort *c);
+extern  void ( APIENTRY * qglIndexub )(GLubyte c);
+extern  void ( APIENTRY * qglIndexubv )(const GLubyte *c);
+extern  void ( APIENTRY * qglInitNames )(void);
+extern  void ( APIENTRY * qglInterleavedArrays )(GLenum format, GLsizei stride, const GLvoid *pointer);
+extern  GLboolean ( APIENTRY * qglIsEnabled )(GLenum cap);
+extern  GLboolean ( APIENTRY * qglIsList )(GLuint list);
+extern  GLboolean ( APIENTRY * qglIsTexture )(GLuint texture);
+extern  void ( APIENTRY * qglLightModelf )(GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglLightModelfv )(GLenum pname, const GLfloat *params);
+extern  void ( APIENTRY * qglLightModeli )(GLenum pname, GLint param);
+extern  void ( APIENTRY * qglLightModeliv )(GLenum pname, const GLint *params);
+extern  void ( APIENTRY * qglLightf )(GLenum light, GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglLightfv )(GLenum light, GLenum pname, const GLfloat *params);
+extern  void ( APIENTRY * qglLighti )(GLenum light, GLenum pname, GLint param);
+extern  void ( APIENTRY * qglLightiv )(GLenum light, GLenum pname, const GLint *params);
+extern  void ( APIENTRY * qglLineStipple )(GLint factor, GLushort pattern);
+extern  void ( APIENTRY * qglLineWidth )(GLfloat width);
+extern  void ( APIENTRY * qglListBase )(GLuint base);
+extern  void ( APIENTRY * qglLoadIdentity )(void);
+extern  void ( APIENTRY * qglLoadMatrixd )(const GLdouble *m);
+extern  void ( APIENTRY * qglLoadMatrixf )(const GLfloat *m);
+extern  void ( APIENTRY * qglLoadName )(GLuint name);
+extern  void ( APIENTRY * qglLogicOp )(GLenum opcode);
+extern  void ( APIENTRY * qglMap1d )(GLenum target, GLdouble u1, GLdouble u2, GLint stride, GLint order, const GLdouble *points);
+extern  void ( APIENTRY * qglMap1f )(GLenum target, GLfloat u1, GLfloat u2, GLint stride, GLint order, const GLfloat *points);
+extern  void ( APIENTRY * qglMap2d )(GLenum target, GLdouble u1, GLdouble u2, GLint ustride, GLint uorder, GLdouble v1, GLdouble v2, GLint vstride, GLint vorder, const GLdouble *points);
+extern  void ( APIENTRY * qglMap2f )(GLenum target, GLfloat u1, GLfloat u2, GLint ustride, GLint uorder, GLfloat v1, GLfloat v2, GLint vstride, GLint vorder, const GLfloat *points);
+extern  void ( APIENTRY * qglMapGrid1d )(GLint un, GLdouble u1, GLdouble u2);
+extern  void ( APIENTRY * qglMapGrid1f )(GLint un, GLfloat u1, GLfloat u2);
+extern  void ( APIENTRY * qglMapGrid2d )(GLint un, GLdouble u1, GLdouble u2, GLint vn, GLdouble v1, GLdouble v2);
+extern  void ( APIENTRY * qglMapGrid2f )(GLint un, GLfloat u1, GLfloat u2, GLint vn, GLfloat v1, GLfloat v2);
+extern  void ( APIENTRY * qglMaterialf )(GLenum face, GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglMaterialfv )(GLenum face, GLenum pname, const GLfloat *params);
+extern  void ( APIENTRY * qglMateriali )(GLenum face, GLenum pname, GLint param);
+extern  void ( APIENTRY * qglMaterialiv )(GLenum face, GLenum pname, const GLint *params);
+extern  void ( APIENTRY * qglMatrixMode )(GLenum mode);
+extern  void ( APIENTRY * qglMultMatrixd )(const GLdouble *m);
+extern  void ( APIENTRY * qglMultMatrixf )(const GLfloat *m);
+extern  void ( APIENTRY * qglNewList )(GLuint list, GLenum mode);
+extern  void ( APIENTRY * qglNormal3b )(GLbyte nx, GLbyte ny, GLbyte nz);
+extern  void ( APIENTRY * qglNormal3bv )(const GLbyte *v);
+extern  void ( APIENTRY * qglNormal3d )(GLdouble nx, GLdouble ny, GLdouble nz);
+extern  void ( APIENTRY * qglNormal3dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglNormal3f )(GLfloat nx, GLfloat ny, GLfloat nz);
+extern  void ( APIENTRY * qglNormal3fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglNormal3i )(GLint nx, GLint ny, GLint nz);
+extern  void ( APIENTRY * qglNormal3iv )(const GLint *v);
+extern  void ( APIENTRY * qglNormal3s )(GLshort nx, GLshort ny, GLshort nz);
+extern  void ( APIENTRY * qglNormal3sv )(const GLshort *v);
+extern  void ( APIENTRY * qglNormalPointer )(GLenum type, GLsizei stride, const GLvoid *pointer);
+extern  void ( APIENTRY * qglOrtho )(GLdouble left, GLdouble right, GLdouble bottom, GLdouble top, GLdouble zNear, GLdouble zFar);
+extern  void ( APIENTRY * qglPassThrough )(GLfloat token);
+extern  void ( APIENTRY * qglPixelMapfv )(GLenum map, GLsizei mapsize, const GLfloat *values);
+extern  void ( APIENTRY * qglPixelMapuiv )(GLenum map, GLsizei mapsize, const GLuint *values);
+extern  void ( APIENTRY * qglPixelMapusv )(GLenum map, GLsizei mapsize, const GLushort *values);
+extern  void ( APIENTRY * qglPixelStoref )(GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglPixelStorei )(GLenum pname, GLint param);
+extern  void ( APIENTRY * qglPixelTransferf )(GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglPixelTransferi )(GLenum pname, GLint param);
+extern  void ( APIENTRY * qglPixelZoom )(GLfloat xfactor, GLfloat yfactor);
+extern  void ( APIENTRY * qglPointSize )(GLfloat size);
+extern  void ( APIENTRY * qglPolygonMode )(GLenum face, GLenum mode);
+extern  void ( APIENTRY * qglPolygonOffset )(GLfloat factor, GLfloat units);
+extern  void ( APIENTRY * qglPolygonStipple )(const GLubyte *mask);
+extern  void ( APIENTRY * qglPopAttrib )(void);
+extern  void ( APIENTRY * qglPopClientAttrib )(void);
+extern  void ( APIENTRY * qglPopMatrix )(void);
+extern  void ( APIENTRY * qglPopName )(void);
+extern  void ( APIENTRY * qglPrioritizeTextures )(GLsizei n, const GLuint *textures, const GLclampf *priorities);
+extern  void ( APIENTRY * qglPushAttrib )(GLbitfield mask);
+extern  void ( APIENTRY * qglPushClientAttrib )(GLbitfield mask);
+extern  void ( APIENTRY * qglPushMatrix )(void);
+extern  void ( APIENTRY * qglPushName )(GLuint name);
+extern  void ( APIENTRY * qglRasterPos2d )(GLdouble x, GLdouble y);
+extern  void ( APIENTRY * qglRasterPos2dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglRasterPos2f )(GLfloat x, GLfloat y);
+extern  void ( APIENTRY * qglRasterPos2fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglRasterPos2i )(GLint x, GLint y);
+extern  void ( APIENTRY * qglRasterPos2iv )(const GLint *v);
+extern  void ( APIENTRY * qglRasterPos2s )(GLshort x, GLshort y);
+extern  void ( APIENTRY * qglRasterPos2sv )(const GLshort *v);
+extern  void ( APIENTRY * qglRasterPos3d )(GLdouble x, GLdouble y, GLdouble z);
+extern  void ( APIENTRY * qglRasterPos3dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglRasterPos3f )(GLfloat x, GLfloat y, GLfloat z);
+extern  void ( APIENTRY * qglRasterPos3fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglRasterPos3i )(GLint x, GLint y, GLint z);
+extern  void ( APIENTRY * qglRasterPos3iv )(const GLint *v);
+extern  void ( APIENTRY * qglRasterPos3s )(GLshort x, GLshort y, GLshort z);
+extern  void ( APIENTRY * qglRasterPos3sv )(const GLshort *v);
+extern  void ( APIENTRY * qglRasterPos4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern  void ( APIENTRY * qglRasterPos4dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglRasterPos4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern  void ( APIENTRY * qglRasterPos4fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglRasterPos4i )(GLint x, GLint y, GLint z, GLint w);
+extern  void ( APIENTRY * qglRasterPos4iv )(const GLint *v);
+extern  void ( APIENTRY * qglRasterPos4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+extern  void ( APIENTRY * qglRasterPos4sv )(const GLshort *v);
+extern  void ( APIENTRY * qglReadBuffer )(GLenum mode);
+extern  void ( APIENTRY * qglReadPixels )(GLint x, GLint y, GLsizei width, GLsizei height, GLenum format, GLenum type, GLvoid *pixels);
+extern  void ( APIENTRY * qglRectd )(GLdouble x1, GLdouble y1, GLdouble x2, GLdouble y2);
+extern  void ( APIENTRY * qglRectdv )(const GLdouble *v1, const GLdouble *v2);
+extern  void ( APIENTRY * qglRectf )(GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2);
+extern  void ( APIENTRY * qglRectfv )(const GLfloat *v1, const GLfloat *v2);
+extern  void ( APIENTRY * qglRecti )(GLint x1, GLint y1, GLint x2, GLint y2);
+extern  void ( APIENTRY * qglRectiv )(const GLint *v1, const GLint *v2);
+extern  void ( APIENTRY * qglRects )(GLshort x1, GLshort y1, GLshort x2, GLshort y2);
+extern  void ( APIENTRY * qglRectsv )(const GLshort *v1, const GLshort *v2);
+extern  GLint ( APIENTRY * qglRenderMode )(GLenum mode);
+extern  void ( APIENTRY * qglRotated )(GLdouble angle, GLdouble x, GLdouble y, GLdouble z);
+extern  void ( APIENTRY * qglRotatef )(GLfloat angle, GLfloat x, GLfloat y, GLfloat z);
+extern  void ( APIENTRY * qglScaled )(GLdouble x, GLdouble y, GLdouble z);
+extern  void ( APIENTRY * qglScalef )(GLfloat x, GLfloat y, GLfloat z);
+extern  void ( APIENTRY * qglScissor )(GLint x, GLint y, GLsizei width, GLsizei height);
+extern  void ( APIENTRY * qglSelectBuffer )(GLsizei size, GLuint *buffer);
+extern  void ( APIENTRY * qglShadeModel )(GLenum mode);
+extern  void ( APIENTRY * qglStencilFunc )(GLenum func, GLint ref, GLuint mask);
+extern  void ( APIENTRY * qglStencilMask )(GLuint mask);
+extern  void ( APIENTRY * qglStencilOp )(GLenum fail, GLenum zfail, GLenum zpass);
+extern  void ( APIENTRY * qglTexCoord1d )(GLdouble s);
+extern  void ( APIENTRY * qglTexCoord1dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglTexCoord1f )(GLfloat s);
+extern  void ( APIENTRY * qglTexCoord1fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglTexCoord1i )(GLint s);
+extern  void ( APIENTRY * qglTexCoord1iv )(const GLint *v);
+extern  void ( APIENTRY * qglTexCoord1s )(GLshort s);
+extern  void ( APIENTRY * qglTexCoord1sv )(const GLshort *v);
+extern  void ( APIENTRY * qglTexCoord2d )(GLdouble s, GLdouble t);
+extern  void ( APIENTRY * qglTexCoord2dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglTexCoord2f )(GLfloat s, GLfloat t);
+extern  void ( APIENTRY * qglTexCoord2fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglTexCoord2i )(GLint s, GLint t);
+extern  void ( APIENTRY * qglTexCoord2iv )(const GLint *v);
+extern  void ( APIENTRY * qglTexCoord2s )(GLshort s, GLshort t);
+extern  void ( APIENTRY * qglTexCoord2sv )(const GLshort *v);
+extern  void ( APIENTRY * qglTexCoord3d )(GLdouble s, GLdouble t, GLdouble r);
+extern  void ( APIENTRY * qglTexCoord3dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglTexCoord3f )(GLfloat s, GLfloat t, GLfloat r);
+extern  void ( APIENTRY * qglTexCoord3fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglTexCoord3i )(GLint s, GLint t, GLint r);
+extern  void ( APIENTRY * qglTexCoord3iv )(const GLint *v);
+extern  void ( APIENTRY * qglTexCoord3s )(GLshort s, GLshort t, GLshort r);
+extern  void ( APIENTRY * qglTexCoord3sv )(const GLshort *v);
+extern  void ( APIENTRY * qglTexCoord4d )(GLdouble s, GLdouble t, GLdouble r, GLdouble q);
+extern  void ( APIENTRY * qglTexCoord4dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglTexCoord4f )(GLfloat s, GLfloat t, GLfloat r, GLfloat q);
+extern  void ( APIENTRY * qglTexCoord4fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglTexCoord4i )(GLint s, GLint t, GLint r, GLint q);
+extern  void ( APIENTRY * qglTexCoord4iv )(const GLint *v);
+extern  void ( APIENTRY * qglTexCoord4s )(GLshort s, GLshort t, GLshort r, GLshort q);
+extern  void ( APIENTRY * qglTexCoord4sv )(const GLshort *v);
+extern  void ( APIENTRY * qglTexCoordPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+extern  void ( APIENTRY * qglTexEnvf )(GLenum target, GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglTexEnvfv )(GLenum target, GLenum pname, const GLfloat *params);
+extern  void ( APIENTRY * qglTexEnvi )(GLenum target, GLenum pname, GLint param);
+extern  void ( APIENTRY * qglTexEnviv )(GLenum target, GLenum pname, const GLint *params);
+extern  void ( APIENTRY * qglTexGend )(GLenum coord, GLenum pname, GLdouble param);
+extern  void ( APIENTRY * qglTexGendv )(GLenum coord, GLenum pname, const GLdouble *params);
+extern  void ( APIENTRY * qglTexGenf )(GLenum coord, GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglTexGenfv )(GLenum coord, GLenum pname, const GLfloat *params);
+extern  void ( APIENTRY * qglTexGeni )(GLenum coord, GLenum pname, GLint param);
+extern  void ( APIENTRY * qglTexGeniv )(GLenum coord, GLenum pname, const GLint *params);
+extern  void ( APIENTRY * qglTexImage1D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+extern  void ( APIENTRY * qglTexImage2D )(GLenum target, GLint level, GLint internalformat, GLsizei width, GLsizei height, GLint border, GLenum format, GLenum type, const GLvoid *pixels);
+extern  void ( APIENTRY * qglTexParameterf )(GLenum target, GLenum pname, GLfloat param);
+extern  void ( APIENTRY * qglTexParameterfv )(GLenum target, GLenum pname, const GLfloat *params);
+extern  void ( APIENTRY * qglTexParameteri )(GLenum target, GLenum pname, GLint param);
+extern  void ( APIENTRY * qglTexParameteriv )(GLenum target, GLenum pname, const GLint *params);
+extern  void ( APIENTRY * qglTexSubImage1D )(GLenum target, GLint level, GLint xoffset, GLsizei width, GLenum format, GLenum type, const GLvoid *pixels);
+extern  void ( APIENTRY * qglTexSubImage2D )(GLenum target, GLint level, GLint xoffset, GLint yoffset, GLsizei width, GLsizei height, GLenum format, GLenum type, const GLvoid *pixels);
+extern  void ( APIENTRY * qglTranslated )(GLdouble x, GLdouble y, GLdouble z);
+extern  void ( APIENTRY * qglTranslatef )(GLfloat x, GLfloat y, GLfloat z);
+extern  void ( APIENTRY * qglVertex2d )(GLdouble x, GLdouble y);
+extern  void ( APIENTRY * qglVertex2dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglVertex2f )(GLfloat x, GLfloat y);
+extern  void ( APIENTRY * qglVertex2fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglVertex2i )(GLint x, GLint y);
+extern  void ( APIENTRY * qglVertex2iv )(const GLint *v);
+extern  void ( APIENTRY * qglVertex2s )(GLshort x, GLshort y);
+extern  void ( APIENTRY * qglVertex2sv )(const GLshort *v);
+extern  void ( APIENTRY * qglVertex3d )(GLdouble x, GLdouble y, GLdouble z);
+extern  void ( APIENTRY * qglVertex3dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglVertex3f )(GLfloat x, GLfloat y, GLfloat z);
+extern  void ( APIENTRY * qglVertex3fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglVertex3i )(GLint x, GLint y, GLint z);
+extern  void ( APIENTRY * qglVertex3iv )(const GLint *v);
+extern  void ( APIENTRY * qglVertex3s )(GLshort x, GLshort y, GLshort z);
+extern  void ( APIENTRY * qglVertex3sv )(const GLshort *v);
+extern  void ( APIENTRY * qglVertex4d )(GLdouble x, GLdouble y, GLdouble z, GLdouble w);
+extern  void ( APIENTRY * qglVertex4dv )(const GLdouble *v);
+extern  void ( APIENTRY * qglVertex4f )(GLfloat x, GLfloat y, GLfloat z, GLfloat w);
+extern  void ( APIENTRY * qglVertex4fv )(const GLfloat *v);
+extern  void ( APIENTRY * qglVertex4i )(GLint x, GLint y, GLint z, GLint w);
+extern  void ( APIENTRY * qglVertex4iv )(const GLint *v);
+extern  void ( APIENTRY * qglVertex4s )(GLshort x, GLshort y, GLshort z, GLshort w);
+extern  void ( APIENTRY * qglVertex4sv )(const GLshort *v);
+extern  void ( APIENTRY * qglVertexPointer )(GLint size, GLenum type, GLsizei stride, const GLvoid *pointer);
+extern  void ( APIENTRY * qglViewport )(GLint x, GLint y, GLsizei width, GLsizei height);
+
+extern	void ( APIENTRY * qglPointParameterfEXT)( GLenum param, GLfloat value );
+extern	void ( APIENTRY * qglPointParameterfvEXT)( GLenum param, const GLfloat *value );
+extern	void ( APIENTRY * qglColorTableEXT)( int, int, int, int, int, const void * );
+
+extern	void ( APIENTRY * qglMTexCoord2fSGIS)( GLenum, GLfloat, GLfloat );
+extern	void ( APIENTRY * qglSelectTextureSGIS)( GLenum );
+
+extern	void ( APIENTRY * qglActiveTextureARB) (GLenum texture);
+extern	void ( APIENTRY * qglClientActiveTextureARB) (GLenum texture);
+extern	void ( APIENTRY * qglMultiTexCoord1dARB) (GLenum target, GLdouble s);
+extern	void ( APIENTRY * qglMultiTexCoord1dvARB) (GLenum target, const GLdouble *v);
+extern	void ( APIENTRY * qglMultiTexCoord1fARB) (GLenum target, GLfloat s);
+extern	void ( APIENTRY * qglMultiTexCoord1fvARB) (GLenum target, const GLfloat *v);
+extern	void ( APIENTRY * qglMultiTexCoord1iARB) (GLenum target, GLint s);
+extern	void ( APIENTRY * qglMultiTexCoord1ivARB) (GLenum target, const GLint *v);
+extern	void ( APIENTRY * qglMultiTexCoord1sARB) (GLenum target, GLshort s);
+extern	void ( APIENTRY * qglMultiTexCoord1svARB) (GLenum target, const GLshort *v);
+extern	void ( APIENTRY * qglMultiTexCoord2dARB) (GLenum target, GLdouble s);
+extern	void ( APIENTRY * qglMultiTexCoord2dvARB) (GLenum target, const GLdouble *v);
+extern	void ( APIENTRY * qglMultiTexCoord2fARB) (GLenum target, GLfloat s);
+extern	void ( APIENTRY * qglMultiTexCoord2fvARB) (GLenum target, const GLfloat *v);
+extern	void ( APIENTRY * qglMultiTexCoord2iARB) (GLenum target, GLint s);
+extern	void ( APIENTRY * qglMultiTexCoord2ivARB) (GLenum target, const GLint *v);
+extern	void ( APIENTRY * qglMultiTexCoord2sARB) (GLenum target, GLshort s);
+extern	void ( APIENTRY * qglMultiTexCoord2svARB) (GLenum target, const GLshort *v);
+extern	void ( APIENTRY * qglMultiTexCoord3dARB) (GLenum target, GLdouble s);
+extern	void ( APIENTRY * qglMultiTexCoord3dvARB) (GLenum target, const GLdouble *v);
+extern	void ( APIENTRY * qglMultiTexCoord3fARB) (GLenum target, GLfloat s);
+extern	void ( APIENTRY * qglMultiTexCoord3fvARB) (GLenum target, const GLfloat *v);
+extern	void ( APIENTRY * qglMultiTexCoord3iARB) (GLenum target, GLint s);
+extern	void ( APIENTRY * qglMultiTexCoord3ivARB) (GLenum target, const GLint *v);
+extern	void ( APIENTRY * qglMultiTexCoord3sARB) (GLenum target, GLshort s);
+extern	void ( APIENTRY * qglMultiTexCoord3svARB) (GLenum target, const GLshort *v);
+extern	void ( APIENTRY * qglMultiTexCoord4dARB) (GLenum target, GLdouble s);
+extern	void ( APIENTRY * qglMultiTexCoord4dvARB) (GLenum target, const GLdouble *v);
+extern	void ( APIENTRY * qglMultiTexCoord4fARB) (GLenum target, GLfloat s);
+extern	void ( APIENTRY * qglMultiTexCoord4fvARB) (GLenum target, const GLfloat *v);
+extern	void ( APIENTRY * qglMultiTexCoord4iARB) (GLenum target, GLint s);
+extern	void ( APIENTRY * qglMultiTexCoord4ivARB) (GLenum target, const GLint *v);
+extern	void ( APIENTRY * qglMultiTexCoord4sARB) (GLenum target, GLshort s);
+extern	void ( APIENTRY * qglMultiTexCoord4svARB) (GLenum target, const GLshort *v);
+
+
+
+#ifdef _WIN32
+
+extern  int   ( WINAPI * qwglChoosePixelFormat )(HDC, CONST PIXELFORMATDESCRIPTOR *);
+extern  int   ( WINAPI * qwglDescribePixelFormat) (HDC, int, UINT, LPPIXELFORMATDESCRIPTOR);
+extern  int   ( WINAPI * qwglGetPixelFormat)(HDC);
+extern  BOOL  ( WINAPI * qwglSetPixelFormat)(HDC, int, CONST PIXELFORMATDESCRIPTOR *);
+extern  BOOL  ( WINAPI * qwglSwapBuffers)(HDC);
+
+extern BOOL  ( WINAPI * qwglCopyContext)(HGLRC, HGLRC, UINT);
+extern HGLRC ( WINAPI * qwglCreateContext)(HDC);
+extern HGLRC ( WINAPI * qwglCreateLayerContext)(HDC, int);
+extern BOOL  ( WINAPI * qwglDeleteContext)(HGLRC);
+extern HGLRC ( WINAPI * qwglGetCurrentContext)(VOID);
+extern HDC   ( WINAPI * qwglGetCurrentDC)(VOID);
+extern PROC  ( WINAPI * qwglGetProcAddress)(LPCSTR);
+extern BOOL  ( WINAPI * qwglMakeCurrent)(HDC, HGLRC);
+extern BOOL  ( WINAPI * qwglShareLists)(HGLRC, HGLRC);
+extern BOOL  ( WINAPI * qwglUseFontBitmaps)(HDC, DWORD, DWORD, DWORD);
+
+extern BOOL  ( WINAPI * qwglUseFontOutlines)(HDC, DWORD, DWORD, DWORD, FLOAT,
+                                           FLOAT, int, LPGLYPHMETRICSFLOAT);
+
+extern BOOL ( WINAPI * qwglDescribeLayerPlane)(HDC, int, int, UINT,
+                                            LPLAYERPLANEDESCRIPTOR);
+extern int  ( WINAPI * qwglSetLayerPaletteEntries)(HDC, int, int, int,
+                                                CONST COLORREF *);
+extern int  ( WINAPI * qwglGetLayerPaletteEntries)(HDC, int, int, int,
+                                                COLORREF *);
+extern BOOL ( WINAPI * qwglRealizeLayerPalette)(HDC, int, BOOL);
+extern BOOL ( WINAPI * qwglSwapLayerBuffers)(HDC, UINT);
+
+extern BOOL ( WINAPI * qwglSwapIntervalEXT)( int interval );
+
+extern BOOL ( WINAPI * qwglGetDeviceGammaRampEXT ) ( unsigned char *pRed, unsigned char *pGreen, unsigned char *pBlue );
+extern BOOL ( WINAPI * qwglSetDeviceGammaRampEXT ) ( const unsigned char *pRed, const unsigned char *pGreen, const unsigned char *pBlue );
+
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+extern XVisualInfo* (*qglXChooseVisual)(Display *dpy, int screen, int *attribList);
+extern GLXContext   (*qglXCreateContext)(Display *dpy, XVisualInfo *vis, GLXContext shareList, Bool direct);
+extern void         (*qglXDestroyContext)(Display *dpy, GLXContext ctx);
+extern Bool         (*qglXMakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx);
+extern void         (*qglXCopyContext)(Display *dpy, GLXContext src, GLXContext dst, GLuint mask);
+extern void         (*qglXSwapBuffers)( Display *dpy, GLXDrawable drawable );
+extern GLXPixmap    (*qglXCreateGLXPixmap)( Display *dpy, XVisualInfo *visual, Pixmap pixmap );
+extern void         (*qglXDestroyGLXPixmap)( Display *dpy, GLXPixmap pixmap );
+extern Bool         (*qglXQueryExtension)( Display *dpy, int *errorb, int *event );
+extern Bool         (*qglXQueryVersion)( Display *dpy, int *maj, int *min );
+extern Bool         (*qglXIsDirect)( Display *dpy, GLXContext ctx );
+extern int          (*qglXGetConfig)( Display *dpy, XVisualInfo *visual, int attrib, int *value );
+extern GLXContext   (*qglXGetCurrentContext)( void );
+extern GLXDrawable  (*qglXGetCurrentDrawable)( void );
+extern void         (*qglXWaitGL)( void );
+extern void         (*qglXWaitX)( void );
+extern void         (*qglXUseXFont)( Font font, int first, int count, int list );
+extern void*        (*qglXGetProcAddressARB) (const GLubyte *procName);
+#endif
+
+#ifdef ATIHACK_812
+extern  void ( APIENTRY * qglCullFace_real )(GLenum mode);
+extern  void ( APIENTRY * qglDisable_real )(GLenum cap);
+extern  void ( APIENTRY * qglEnable_real )(GLenum cap);
+extern  void ( APIENTRY * qglPolygonMode_real )(GLenum face, GLenum mode);
+
+extern  void APIENTRY qglCullFace_ATIHack(GLenum mode);
+extern  void APIENTRY qglDisable_ATIHack(GLenum cap);
+extern  void APIENTRY qglEnable_ATIHack(GLenum cap);
+extern  void APIENTRY qglPolygonMode_ATIHack(GLenum face, GLenum mode);
+#endif
+
+// glu stuff.. radiant only uses a couple
+extern void (APIENTRY* qgluPerspective) (GLdouble fovy, GLdouble aspect, GLdouble zNear, GLdouble zFar);
+extern void (APIENTRY* qgluLookAt)(
+  GLdouble eyex,
+  GLdouble eyey,
+  GLdouble eyez,
+  GLdouble centerx,
+  GLdouble centery,
+  GLdouble centerz,
+  GLdouble upx,
+  GLdouble upy,
+  GLdouble upz);
+extern const GLubyte * (APIENTRY * qgluErrorString) (GLenum errCode );
+
+
+// end of glu stuff
+
+
+/*
+** extension constants
+*/
+#define GL_POINT_SIZE_MIN_EXT				0x8126
+#define GL_POINT_SIZE_MAX_EXT				0x8127
+#define GL_POINT_FADE_THRESHOLD_SIZE_EXT	0x8128
+#define GL_DISTANCE_ATTENUATION_EXT			0x8129
+
+#define GL_SHARED_TEXTURE_PALETTE_EXT		0x81FB
+
+#define GL_TEXTURE0_SGIS					0x835E
+#define GL_TEXTURE1_SGIS					0x835F
+
+
+#ifdef __cplusplus
+}
+#endif // extern "C"
+
+// -------------------------------------------------------------------------------------------
+// qgl_ext.cpp API
+// -------------------------------------------------------------------------------------------
+
+int Sys_QGL_ExtensionSupported (const char *extension);
+
+#endif
diff --git a/radiant/resource.h b/radiant/resource.h
index 770c06b9..17099dac 100644
--- a/radiant/resource.h
+++ b/radiant/resource.h
@@ -1,37 +1,37 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by Q3Radiant.rc
-//
-#define IDI_RADIANT                     101
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NEXT_RESOURCE_VALUE        102
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Q3Radiant.rc
+//
+#define IDI_RADIANT                     101
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/radiant/select.h b/radiant/select.h
index 8bcafff1..42718162 100644
--- a/radiant/select.h
+++ b/radiant/select.h
@@ -1,82 +1,82 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-typedef struct
-{
-	brush_t		*brush;
-	face_t		*face;
-	float		dist;
-	qboolean	selected;
-} trace_t;
-
-#define SF_SELECTED_ONLY	0x0001
-#define SF_ENTITIES_FIRST	0x0002
-#define SF_SINGLEFACE			0x0004
-#define SF_IGNORECURVES		0x0008
-#define SF_IGNOREGROUPS		0x0010
-#define SF_CYCLE					0x0020
-#define SF_CAMERA         0x0040 // set when the operation happens through camera view, otherwise XY
-#define SF_DRAG_ON				0x0080
-#define SF_DRAG_OFF 			0x0100
-#define SF_DRAG						(SF_DRAG_ON | SF_DRAG_OFF)
-
-trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags);
-
-void Select_GetBounds (vec3_t mins, vec3_t maxs);
-void Select_GetMid (vec3_t mid);
-void Select_Brush (brush_t *b, bool bComplete = true, bool bStatus = true);
-void Select_Ray (vec3_t origin, vec3_t dir, int flags);
-void Select_Delete (void);
-void Select_Deselect (bool bDeselectFaces = true);
-void Select_Invert(void);
-void Select_Clone (void);
-void Select_Move (vec3_t delta, bool bSnap = true);
-void Select_NudgePoint(vec3_t delta, qboolean bSnap = true);
-void WINAPI Select_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, void* pPlugTexdef = NULL);
-void Select_FlipAxis (int axis);
-void Select_RotateAxis (int axis, float deg, bool bPaint = true, bool bMouse = false);
-void Select_RealCompleteTall(vec3_t mins, vec3_t maxs);
-void Select_CompleteTall (void);
-void Select_PartialTall (void);
-void Select_Touching (void);
-void Select_Inside (void);
-void Select_Seperate (void);
-void Select_MakeStructural (void);
-void Select_MakeDetail (void);
-void Select_AllOfType();
-void Select_Reselect();
-void Select_FitTexture(int nHeight = 1, int nWidth = 1);
-
-// absolute texture coordinates
-// TTimo NOTE: this is stuff for old brushes format and rotation texture lock .. sort of in-between with bush primitives
-void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3);
-void AbsoluteToLocal(plane_t normal2, face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3);
-void Select_Hide();
-void Select_ShowAllHidden();
-// add selected brushes to a group, update the tree
-//void Select_AddToGroup(const char *pName);
-//void Select_Name(const char *pName);
-
-// updating workzone to a given brush (depends on current view)
-void UpdateWorkzone_ForBrush( brush_t* b );
-
-void Select_GroupEntity(entity_t* e);
-void Select_MergeEntity();
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+typedef struct
+{
+	brush_t		*brush;
+	face_t		*face;
+	float		dist;
+	qboolean	selected;
+} trace_t;
+
+#define SF_SELECTED_ONLY	0x0001
+#define SF_ENTITIES_FIRST	0x0002
+#define SF_SINGLEFACE			0x0004
+#define SF_IGNORECURVES		0x0008
+#define SF_IGNOREGROUPS		0x0010
+#define SF_CYCLE					0x0020
+#define SF_CAMERA         0x0040 // set when the operation happens through camera view, otherwise XY
+#define SF_DRAG_ON				0x0080
+#define SF_DRAG_OFF 			0x0100
+#define SF_DRAG						(SF_DRAG_ON | SF_DRAG_OFF)
+
+trace_t Test_Ray (vec3_t origin, vec3_t dir, int flags);
+
+void Select_GetBounds (vec3_t mins, vec3_t maxs);
+void Select_GetMid (vec3_t mid);
+void Select_Brush (brush_t *b, bool bComplete = true, bool bStatus = true);
+void Select_Ray (vec3_t origin, vec3_t dir, int flags);
+void Select_Delete (void);
+void Select_Deselect (bool bDeselectFaces = true);
+void Select_Invert(void);
+void Select_Clone (void);
+void Select_Move (vec3_t delta, bool bSnap = true);
+void Select_NudgePoint(vec3_t delta, qboolean bSnap = true);
+void WINAPI Select_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, void* pPlugTexdef = NULL);
+void Select_FlipAxis (int axis);
+void Select_RotateAxis (int axis, float deg, bool bPaint = true, bool bMouse = false);
+void Select_RealCompleteTall(vec3_t mins, vec3_t maxs);
+void Select_CompleteTall (void);
+void Select_PartialTall (void);
+void Select_Touching (void);
+void Select_Inside (void);
+void Select_Seperate (void);
+void Select_MakeStructural (void);
+void Select_MakeDetail (void);
+void Select_AllOfType();
+void Select_Reselect();
+void Select_FitTexture(int nHeight = 1, int nWidth = 1);
+
+// absolute texture coordinates
+// TTimo NOTE: this is stuff for old brushes format and rotation texture lock .. sort of in-between with bush primitives
+void ComputeAbsolute(face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3);
+void AbsoluteToLocal(plane_t normal2, face_t* f, vec3_t& p1, vec3_t& p2, vec3_t& p3);
+void Select_Hide();
+void Select_ShowAllHidden();
+// add selected brushes to a group, update the tree
+//void Select_AddToGroup(const char *pName);
+//void Select_Name(const char *pName);
+
+// updating workzone to a given brush (depends on current view)
+void UpdateWorkzone_ForBrush( brush_t* b );
+
+void Select_GroupEntity(entity_t* e);
+void Select_MergeEntity();
diff --git a/radiant/stdafx.h b/radiant/stdafx.h
index cb6c327f..85d83e1c 100644
--- a/radiant/stdafx.h
+++ b/radiant/stdafx.h
@@ -1,39 +1,39 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-// TTimo
-// included by most files
-// on Win32 builds this one is used for precompiled headers
-
-#ifdef _WIN32
-#define WIN32_LEAN_AND_MEAN
-#include <windows.h>
-#endif
-#include "qe3.h"
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+// TTimo
+// included by most files
+// on Win32 builds this one is used for precompiled headers
+
+#ifdef _WIN32
+#define WIN32_LEAN_AND_MEAN
+#include <windows.h>
+#endif
+#include "qe3.h"
diff --git a/radiant/surfacedialog.h b/radiant/surfacedialog.h
index 6d5d48a1..71741b9e 100644
--- a/radiant/surfacedialog.h
+++ b/radiant/surfacedialog.h
@@ -1,69 +1,69 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _SURFACEDIALOG_H_
-#define _SURFACEDIALOG_H_
-
-#include "dialog.h"
-
-#ifdef _DEBUG
-//#define DBG_SI 1
-#endif
-
-class SurfaceDlg : public Dialog
-{
-  bool m_bPatchMode;
-  // brush primitive fake shift scale rot coords
-  float	m_shift[2];
-  float	m_rotate;
-  float	m_scale[2];
-    
-public:
-  SurfaceDlg ();
-
-  virtual void ShowDlg();
-  virtual void HideDlg();
-  void SetTexMods();
-  void GetTexMods();
-
-  void InitDefaultIncrement(texdef_t *);
-
-  // Dialog Data
-  int m_nHeight;
-  int m_nWidth;
-
-  // 0 is invalid, otherwise it's the Id of the last 'do' we are responsible for
-  int m_nUndoId;
-
-  // is the user editing the texture widget (that changes the behaviour of 'Enter' key from OnDone to OnApply
-  // reset to false at each SetTexMods or when dealing with Enter key
-  bool m_bEditingTextureWidget;
-
-protected:
-  void BuildDialog ();
-
-public:
-  // called to perform a fitting from the outside (shortcut key)
-  void FitAll();
-  GtkWidget *GetWidget (); // { return m_pWidget; }
-};
-
-#endif // _SURFACEDIALOG_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _SURFACEDIALOG_H_
+#define _SURFACEDIALOG_H_
+
+#include "dialog.h"
+
+#ifdef _DEBUG
+//#define DBG_SI 1
+#endif
+
+class SurfaceDlg : public Dialog
+{
+  bool m_bPatchMode;
+  // brush primitive fake shift scale rot coords
+  float	m_shift[2];
+  float	m_rotate;
+  float	m_scale[2];
+    
+public:
+  SurfaceDlg ();
+
+  virtual void ShowDlg();
+  virtual void HideDlg();
+  void SetTexMods();
+  void GetTexMods();
+
+  void InitDefaultIncrement(texdef_t *);
+
+  // Dialog Data
+  int m_nHeight;
+  int m_nWidth;
+
+  // 0 is invalid, otherwise it's the Id of the last 'do' we are responsible for
+  int m_nUndoId;
+
+  // is the user editing the texture widget (that changes the behaviour of 'Enter' key from OnDone to OnApply
+  // reset to false at each SetTexMods or when dealing with Enter key
+  bool m_bEditingTextureWidget;
+
+protected:
+  void BuildDialog ();
+
+public:
+  // called to perform a fitting from the outside (shortcut key)
+  void FitAll();
+  GtkWidget *GetWidget (); // { return m_pWidget; }
+};
+
+#endif // _SURFACEDIALOG_H_
diff --git a/radiant/surfaceplugin.h b/radiant/surfaceplugin.h
index 6f08c227..4e32e92f 100644
--- a/radiant/surfaceplugin.h
+++ b/radiant/surfaceplugin.h
@@ -1,11 +1,11 @@
-#ifndef _SURFACEPLUGIN_H
-#define _SURFACEPLUGIN_H
-
-int SI_GetSelectedFaceCountfromBrushes(void);
-void SI_GetSelFacesTexdef(texdef_to_face_t *allocd_block_texdef);
-void SI_SetTexdef_FaceList(texdef_to_face_t* texdef_face_list, bool b_SetUndoPoint = FALSE, bool bFit_to_Scale = FALSE);
-void SI_FaceList_FitTexture(texdef_to_face_t* si_texdef_face_list, int nHeight, int nWidth);
-GtkWindow* SI_GetMainWindow(void);
-void SI_SetWinPos_from_Prefs(GtkWidget *win);
-
-#endif // _SURFACEPLUGIN_H
+#ifndef _SURFACEPLUGIN_H
+#define _SURFACEPLUGIN_H
+
+int SI_GetSelectedFaceCountfromBrushes(void);
+void SI_GetSelFacesTexdef(texdef_to_face_t *allocd_block_texdef);
+void SI_SetTexdef_FaceList(texdef_to_face_t* texdef_face_list, bool b_SetUndoPoint = FALSE, bool bFit_to_Scale = FALSE);
+void SI_FaceList_FitTexture(texdef_to_face_t* si_texdef_face_list, int nHeight, int nWidth);
+GtkWindow* SI_GetMainWindow(void);
+void SI_SetWinPos_from_Prefs(GtkWidget *win);
+
+#endif // _SURFACEPLUGIN_H
diff --git a/radiant/texmanip.h b/radiant/texmanip.h
index f3e0b5c3..07548700 100644
--- a/radiant/texmanip.h
+++ b/radiant/texmanip.h
@@ -1,39 +1,39 @@
-/*
-Copyright (c) 2002 Forest "LordHavoc" Hale
-
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification,
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Forest Hale nor the names of other contributors may be used
-to endorse or promote products derived from this software without specific prior
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _TEXMANIP_H_
-#define _TEXMANIP_H_
-
-void R_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth, int bytesperpixel);
-void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight, int bytesperpixel);
-void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight);
-
-#endif // _TEXMANIP_H_
+/*
+Copyright (c) 2002 Forest "LordHavoc" Hale
+
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification,
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Forest Hale nor the names of other contributors may be used
+to endorse or promote products derived from this software without specific prior
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS''
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _TEXMANIP_H_
+#define _TEXMANIP_H_
+
+void R_ResampleTextureLerpLine (byte *in, byte *out, int inwidth, int outwidth, int bytesperpixel);
+void R_ResampleTexture (void *indata, int inwidth, int inheight, void *outdata,  int outwidth, int outheight, int bytesperpixel);
+void GL_MipReduce(byte *in, byte *out, int width, int height, int destwidth, int destheight);
+
+#endif // _TEXMANIP_H_
diff --git a/radiant/textures.h b/radiant/textures.h
index 571319a4..2261053a 100644
--- a/radiant/textures.h
+++ b/radiant/textures.h
@@ -1,52 +1,52 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-// a texturename of the form (0 0 0) will
-// create a solid color texture
-
-void Texture_Init();
-void	Texture_ShowDirectory (int menunum);
-void Texture_ShowDirectory ();
-void	Texture_ShowAll();
-void	WINAPI Texture_ShowInuse();
-extern char texture_directory[];
-
-// Timo
-// added an optional IPluginTexdef when one is available
-// we need a forward declaration, this is crap
-class IPluginTexdef;
-//++timo clean
-void	Texture_SetTexture2 (IShader *pShader, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef *pTexdef = NULL, bool bSetSelection = true);
-void	WINAPI Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef *pTexdef = (IPluginTexdef*)NULL, bool bSetSelection = true);
-
-void	Texture_SetMode(int iMenu);	// GL_TEXTURE_NEAREST, etc..
-void Texture_ResetPosition();
-
-// build the list of shader files used by PreloadShaders
-void BuildShaderList();
-// preload the shaders: build a list of shader names and properties .. don't load their assets
-void PreloadShaders();
-int WINAPI Texture_LoadSkin(char *pName, int *pnWidth, int *pnHeight);
-qtexture_t* Texture_LoadFromPlugIn(void* vp);
-void Texture_StartPos (void);
-IShader* Texture_NextPos (int *x, int *y);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+// a texturename of the form (0 0 0) will
+// create a solid color texture
+
+void Texture_Init();
+void	Texture_ShowDirectory (int menunum);
+void Texture_ShowDirectory ();
+void	Texture_ShowAll();
+void	WINAPI Texture_ShowInuse();
+extern char texture_directory[];
+
+// Timo
+// added an optional IPluginTexdef when one is available
+// we need a forward declaration, this is crap
+class IPluginTexdef;
+//++timo clean
+void	Texture_SetTexture2 (IShader *pShader, texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef *pTexdef = NULL, bool bSetSelection = true);
+void	WINAPI Texture_SetTexture (texdef_t *texdef, brushprimit_texdef_t *brushprimit_texdef, bool bFitScale = false, IPluginTexdef *pTexdef = (IPluginTexdef*)NULL, bool bSetSelection = true);
+
+void	Texture_SetMode(int iMenu);	// GL_TEXTURE_NEAREST, etc..
+void Texture_ResetPosition();
+
+// build the list of shader files used by PreloadShaders
+void BuildShaderList();
+// preload the shaders: build a list of shader names and properties .. don't load their assets
+void PreloadShaders();
+int WINAPI Texture_LoadSkin(char *pName, int *pnWidth, int *pnHeight);
+qtexture_t* Texture_LoadFromPlugIn(void* vp);
+void Texture_StartPos (void);
+IShader* Texture_NextPos (int *x, int *y);
+
diff --git a/radiant/texwindow.h b/radiant/texwindow.h
index 7f6e9260..f0f03daf 100644
--- a/radiant/texwindow.h
+++ b/radiant/texwindow.h
@@ -1,62 +1,62 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _TEXWINDOW_H_
-#define _TEXWINDOW_H_
-
-#include "glwindow.h"
-
-class TexWnd : public GLWindow
-{
-public:
-  TexWnd();
-  void UpdateFilter(const char* pFilter);
-  void UpdatePrefs();
-  void FocusEdit();
-  bool CheckFilter( const char* );
-  virtual ~TexWnd();
-
-  GtkWidget *m_pFilter;
-
-protected:
-  bool m_bNeedRange;
-
-  void OnCreate ();
-  void OnExpose ();
-  void OnLButtonDown (guint32 flags, int x, int y);
-  void OnRButtonDown (guint32 flags, int x, int y);
-  void OnMButtonDown (guint32 flags, int x, int y);
-  void OnLButtonUp (guint32 flags, int pointx, int pointy);
-  void OnRButtonUp (guint32 flags, int pointx, int pointy);
-  void OnMButtonUp (guint32 flags, int pointx, int pointy);
-  void OnMouseMove (guint32 flags, int pointx, int pointy);
-  void OnSize (int cx, int cy);
-
-  void OnMouseWheel(bool bUp);
-
- public:
-  void OnVScroll ();
-
- private:
-   void DragDropTexture (guint32 flags, int pointx, int pointy);
-};
-
-#endif // _TEXWINDOW_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _TEXWINDOW_H_
+#define _TEXWINDOW_H_
+
+#include "glwindow.h"
+
+class TexWnd : public GLWindow
+{
+public:
+  TexWnd();
+  void UpdateFilter(const char* pFilter);
+  void UpdatePrefs();
+  void FocusEdit();
+  bool CheckFilter( const char* );
+  virtual ~TexWnd();
+
+  GtkWidget *m_pFilter;
+
+protected:
+  bool m_bNeedRange;
+
+  void OnCreate ();
+  void OnExpose ();
+  void OnLButtonDown (guint32 flags, int x, int y);
+  void OnRButtonDown (guint32 flags, int x, int y);
+  void OnMButtonDown (guint32 flags, int x, int y);
+  void OnLButtonUp (guint32 flags, int pointx, int pointy);
+  void OnRButtonUp (guint32 flags, int pointx, int pointy);
+  void OnMButtonUp (guint32 flags, int pointx, int pointy);
+  void OnMouseMove (guint32 flags, int pointx, int pointy);
+  void OnSize (int cx, int cy);
+
+  void OnMouseWheel(bool bUp);
+
+ public:
+  void OnVScroll ();
+
+ private:
+   void DragDropTexture (guint32 flags, int pointx, int pointy);
+};
+
+#endif // _TEXWINDOW_H_
diff --git a/radiant/ui.h b/radiant/ui.h
index 135ed93e..7bc99c94 100644
--- a/radiant/ui.h
+++ b/radiant/ui.h
@@ -1,84 +1,84 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// headers for internal classes used in Messaging.cpp
-// 
-
-#ifndef __MESSAGING_H_
-#define __MESSAGING_H_
-
-class CXYWndWrapper : public IXYWndWrapper
-{
-public:
-  void SnapToGrid( int x1, int y1, vec3_t pt );
-  VIEWTYPE GetViewType( void );
-};
-
-// implementation of the IWindow API
-class CGtkWindow : public IWindow
-{
-  int refCount;
-  GtkWidget *m_pWnd;
-  GtkWidget *m_pGLWidget;
-  int m_nWidthParam,m_nHeightParam;
-  IWindowListener *m_pListen;
-  Str m_Name;
-public:
-  CGtkWindow() { refCount = 0; m_pWnd = NULL; m_pGLWidget = NULL; m_nWidthParam = 0; m_nHeightParam = 0; m_pListen = 0; m_Name = "CGtkWindow"; }
-  virtual ~CGtkWindow()
-  {
-    if (m_pListen) { m_pListen->DecRef(); m_pListen = NULL; }
-    if (m_pWnd) { gtk_widget_destroy(m_pWnd); m_pWnd = NULL; }
-  }
-  // refcounting ----------------------------------------
-	// Increment the number of references to this object
-	void IncRef () { refCount++; }
-	// Decrement the reference count
-	void DecRef ()
-	{ if ( --refCount <= 0 )
-		delete this;
-	}
-  // IWindow --------------------------------------------
-  // get pixel size
-  int getHeight() { return m_pWnd->allocation.height; }
-  int getWidth() { return m_pWnd->allocation.width; }
-  // set pixel size and other parameters before showing it
-  void setSizeParm(int width, int height) { m_nWidthParam = width; m_nHeightParam = height; }
-  // set the IWindowListener (implemented by the plugin using this window)
-  void setListener(IWindowListener * pListen) { m_pListen = pListen; m_pListen->IncRef(); }
-  // set the name (optional)
-  void setName(char *name) { m_Name = name; }
-  // will actually create the GL and the window based on the parameters
-  bool Show();
-  // CGtkWindow -----------------------------------------
-  // called upon a closure of the widget
-  void Close();
-  // called to manage GL context and buffer swapping before display
-  void DoExpose();
-  // commands -------------------------------------------
-  // call this to ask for a Redraw
-  void Redraw();
-};
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// headers for internal classes used in Messaging.cpp
+// 
+
+#ifndef __MESSAGING_H_
+#define __MESSAGING_H_
+
+class CXYWndWrapper : public IXYWndWrapper
+{
+public:
+  void SnapToGrid( int x1, int y1, vec3_t pt );
+  VIEWTYPE GetViewType( void );
+};
+
+// implementation of the IWindow API
+class CGtkWindow : public IWindow
+{
+  int refCount;
+  GtkWidget *m_pWnd;
+  GtkWidget *m_pGLWidget;
+  int m_nWidthParam,m_nHeightParam;
+  IWindowListener *m_pListen;
+  Str m_Name;
+public:
+  CGtkWindow() { refCount = 0; m_pWnd = NULL; m_pGLWidget = NULL; m_nWidthParam = 0; m_nHeightParam = 0; m_pListen = 0; m_Name = "CGtkWindow"; }
+  virtual ~CGtkWindow()
+  {
+    if (m_pListen) { m_pListen->DecRef(); m_pListen = NULL; }
+    if (m_pWnd) { gtk_widget_destroy(m_pWnd); m_pWnd = NULL; }
+  }
+  // refcounting ----------------------------------------
+	// Increment the number of references to this object
+	void IncRef () { refCount++; }
+	// Decrement the reference count
+	void DecRef ()
+	{ if ( --refCount <= 0 )
+		delete this;
+	}
+  // IWindow --------------------------------------------
+  // get pixel size
+  int getHeight() { return m_pWnd->allocation.height; }
+  int getWidth() { return m_pWnd->allocation.width; }
+  // set pixel size and other parameters before showing it
+  void setSizeParm(int width, int height) { m_nWidthParam = width; m_nHeightParam = height; }
+  // set the IWindowListener (implemented by the plugin using this window)
+  void setListener(IWindowListener * pListen) { m_pListen = pListen; m_pListen->IncRef(); }
+  // set the name (optional)
+  void setName(char *name) { m_Name = name; }
+  // will actually create the GL and the window based on the parameters
+  bool Show();
+  // CGtkWindow -----------------------------------------
+  // called upon a closure of the widget
+  void Close();
+  // called to manage GL context and buffer swapping before display
+  void DoExpose();
+  // commands -------------------------------------------
+  // call this to ask for a Redraw
+  void Redraw();
+};
+
+#endif
diff --git a/radiant/undo.h b/radiant/undo.h
index 21ec93f4..5973202a 100644
--- a/radiant/undo.h
+++ b/radiant/undo.h
@@ -1,66 +1,66 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-//
-// QERadiant Multilevel Undo/Redo
-//
-// 
-
-//start operation
-void Undo_Start(char *operation);
-//end operation
-void Undo_End(void);
-//add brush to the undo
-void Undo_AddBrush(brush_t *pBrush);
-//add a list with brushes to the undo
-void Undo_AddBrushList(brush_t *brushlist);
-//end a brush after the operation is performed
-void Undo_EndBrush(brush_t *pBrush);
-//end a list with brushes after the operation is performed
-void Undo_EndBrushList(brush_t *brushlist);
-//add entity to undo
-void Undo_AddEntity(entity_t *entity);
-//end an entity after the operation is performed
-void Undo_EndEntity(entity_t *entity);
-//undo last operation (bSilent == true -> will not print the "undone blah blah message")
-void Undo_Undo(boolean bSilent = false);
-//redo last undone operation
-void Undo_Redo(void);
-//get the undo Id of the next undo (0 if none available)
-int Undo_GetUndoId(void);
-//returns true if there is something to be undone available
-int  Undo_UndoAvailable(void);
-//returns true if there is something to redo available
-int  Undo_RedoAvailable(void);
-//clear the undo buffer
-void Undo_Clear(void);
-//set maximum undo size (default 64)
-void Undo_SetMaxSize(int size);
-//get maximum undo size
-int  Undo_GetMaxSize(void);
-//set maximum undo memory in bytes (default 2 MB)
-void Undo_SetMaxMemorySize(int size);
-//get maximum undo memory in bytes
-int  Undo_GetMaxMemorySize(void);
-//returns the amount of memory used by undo
-int  Undo_MemorySize(void);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+//
+// QERadiant Multilevel Undo/Redo
+//
+// 
+
+//start operation
+void Undo_Start(char *operation);
+//end operation
+void Undo_End(void);
+//add brush to the undo
+void Undo_AddBrush(brush_t *pBrush);
+//add a list with brushes to the undo
+void Undo_AddBrushList(brush_t *brushlist);
+//end a brush after the operation is performed
+void Undo_EndBrush(brush_t *pBrush);
+//end a list with brushes after the operation is performed
+void Undo_EndBrushList(brush_t *brushlist);
+//add entity to undo
+void Undo_AddEntity(entity_t *entity);
+//end an entity after the operation is performed
+void Undo_EndEntity(entity_t *entity);
+//undo last operation (bSilent == true -> will not print the "undone blah blah message")
+void Undo_Undo(boolean bSilent = false);
+//redo last undone operation
+void Undo_Redo(void);
+//get the undo Id of the next undo (0 if none available)
+int Undo_GetUndoId(void);
+//returns true if there is something to be undone available
+int  Undo_UndoAvailable(void);
+//returns true if there is something to redo available
+int  Undo_RedoAvailable(void);
+//clear the undo buffer
+void Undo_Clear(void);
+//set maximum undo size (default 64)
+void Undo_SetMaxSize(int size);
+//get maximum undo size
+int  Undo_GetMaxSize(void);
+//set maximum undo memory in bytes (default 2 MB)
+void Undo_SetMaxMemorySize(int size);
+//get maximum undo memory in bytes
+int  Undo_GetMaxMemorySize(void);
+//returns the amount of memory used by undo
+int  Undo_MemorySize(void);
+
diff --git a/radiant/watchbsp.h b/radiant/watchbsp.h
index c124c54f..dcf7dea5 100644
--- a/radiant/watchbsp.h
+++ b/radiant/watchbsp.h
@@ -1,91 +1,91 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _BSPWINDOW_H_
-#define _BSPWINDOW_H_
-
-#include "l_net/l_net.h"
-
-class CWatchBSP
-{
-private:
-  // a flag we have set to true when using an external BSP plugin
-  // the resulting code with that is a bit dirty, cleaner solution would be to seperate the succession of commands from the listening loop
-  // (in two seperate classes probably)
-  bool m_bBSPPlugin;
-
-  // EIdle: we are not listening
-  //   DoMonitoringLoop will change state to EBeginStep
-  // EBeginStep: the socket is up for listening, we are expecting incoming connection
-  //   incoming connection will change state to EWatching
-  // EWatching: we have a connection, monitor it
-  //   connection closed will see if we start a new step (EBeginStep) or launch Quake3 and end (EIdle)
-  enum EWatchBSPState { EIdle, EBeginStep, EWatching } m_eState;
-  socket_t *m_pListenSocket;
-  socket_t *m_pInSocket;
-  netmessage_t msg;
-  GPtrArray *m_pCmd;
-  // used to timeout EBeginStep
-  GTimer    *m_pTimer;
-  unsigned int m_iCurrentStep;
-  // name of the map so we can run the engine
-  char    *m_sBSPName;
-  // buffer we use in push mode to receive data directly from the network
-  xmlParserInputBufferPtr m_xmlInputBuffer;
-  xmlParserInputPtr m_xmlInput;
-  xmlParserCtxtPtr m_xmlParserCtxt;
-  // call this to switch the set listening mode
-  bool SetupListening();
-  // start a new EBeginStep
-  void DoEBeginStep();
-  // the xml and sax parser state
-  char m_xmlBuf[MAX_NETMESSAGE];
-  bool m_bNeedCtxtInit;
-  message_info_s m_message_info;
-
-public:
-  CWatchBSP() { m_bBSPPlugin = false; m_pListenSocket = NULL; m_pInSocket = NULL; m_eState = EIdle; m_pTimer = g_timer_new(); m_sBSPName = NULL; m_xmlInputBuffer = NULL; m_bNeedCtxtInit = true; }
-  virtual ~CWatchBSP();
-  bool HasBSPPlugin () const
-    { return m_bBSPPlugin; }
-
-  // called regularly to keep listening
-  void RoutineProcessing();
-  // start a monitoring loop with the following steps
-  void DoMonitoringLoop( GPtrArray *pCmd, char *sBSPName );
-  // close everything - may be called from the outside to abort the process
-  void Reset();
-  // start a listening loop for an external process, possibly a BSP plugin
-  void ExternalListen();
-};
-
-void WINAPI QERApp_Listen();
-
-#endif
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _BSPWINDOW_H_
+#define _BSPWINDOW_H_
+
+#include "l_net/l_net.h"
+
+class CWatchBSP
+{
+private:
+  // a flag we have set to true when using an external BSP plugin
+  // the resulting code with that is a bit dirty, cleaner solution would be to seperate the succession of commands from the listening loop
+  // (in two seperate classes probably)
+  bool m_bBSPPlugin;
+
+  // EIdle: we are not listening
+  //   DoMonitoringLoop will change state to EBeginStep
+  // EBeginStep: the socket is up for listening, we are expecting incoming connection
+  //   incoming connection will change state to EWatching
+  // EWatching: we have a connection, monitor it
+  //   connection closed will see if we start a new step (EBeginStep) or launch Quake3 and end (EIdle)
+  enum EWatchBSPState { EIdle, EBeginStep, EWatching } m_eState;
+  socket_t *m_pListenSocket;
+  socket_t *m_pInSocket;
+  netmessage_t msg;
+  GPtrArray *m_pCmd;
+  // used to timeout EBeginStep
+  GTimer    *m_pTimer;
+  unsigned int m_iCurrentStep;
+  // name of the map so we can run the engine
+  char    *m_sBSPName;
+  // buffer we use in push mode to receive data directly from the network
+  xmlParserInputBufferPtr m_xmlInputBuffer;
+  xmlParserInputPtr m_xmlInput;
+  xmlParserCtxtPtr m_xmlParserCtxt;
+  // call this to switch the set listening mode
+  bool SetupListening();
+  // start a new EBeginStep
+  void DoEBeginStep();
+  // the xml and sax parser state
+  char m_xmlBuf[MAX_NETMESSAGE];
+  bool m_bNeedCtxtInit;
+  message_info_s m_message_info;
+
+public:
+  CWatchBSP() { m_bBSPPlugin = false; m_pListenSocket = NULL; m_pInSocket = NULL; m_eState = EIdle; m_pTimer = g_timer_new(); m_sBSPName = NULL; m_xmlInputBuffer = NULL; m_bNeedCtxtInit = true; }
+  virtual ~CWatchBSP();
+  bool HasBSPPlugin () const
+    { return m_bBSPPlugin; }
+
+  // called regularly to keep listening
+  void RoutineProcessing();
+  // start a monitoring loop with the following steps
+  void DoMonitoringLoop( GPtrArray *pCmd, char *sBSPName );
+  // close everything - may be called from the outside to abort the process
+  void Reset();
+  // start a listening loop for an external process, possibly a BSP plugin
+  void ExternalListen();
+};
+
+void WINAPI QERApp_Listen();
+
+#endif
diff --git a/radiant/winding.h b/radiant/winding.h
index 3f21a204..426cad9b 100644
--- a/radiant/winding.h
+++ b/radiant/winding.h
@@ -1,70 +1,70 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-
-
-//returns true if the planes are equal
-int			Plane_Equal(plane_t *a, plane_t *b, int flip);
-//returns false if the points are colinear
-int			Plane_FromPoints(vec3_t p1, vec3_t p2, vec3_t p3, plane_t *plane);
-//returns true if the points are equal
-int			Point_Equal(vec3_t p1, vec3_t p2, float epsilon);
-
-//allocate a winding
-winding_t*	Winding_Alloc(int points);
-//free the winding
-void		Winding_Free(winding_t *w);
-//create a base winding for the plane
-winding_t*	Winding_BaseForPlane (plane_t *p);
-//make a winding clone
-winding_t*	Winding_Clone(winding_t *w );
-//creates the reversed winding
-winding_t*	Winding_Reverse(winding_t *w);
-//remove a point from the winding
-void		Winding_RemovePoint(winding_t *w, int point);
-//inserts a point to a winding, creating a new winding
-winding_t*	Winding_InsertPoint(winding_t *w, vec3_t point, int spot);
-//returns true if the planes are concave
-int			Winding_PlanesConcave(winding_t *w1, winding_t *w2,
-									 vec3_t normal1, vec3_t normal2,
-									 float dist1, float dist2);
-//returns true if the winding is tiny
-int			Winding_IsTiny(winding_t *w);
-//returns true if the winding is huge
-int			Winding_IsHuge(winding_t *w);
-//clip the winding with the plane
-winding_t*	Winding_Clip(winding_t *in, plane_t *split, qboolean keepon);
-//split the winding with the plane
-void		Winding_SplitEpsilon(winding_t *in, vec3_t normal, double dist, 
-								vec_t epsilon, winding_t **front, winding_t **back);
-//try to merge the windings, returns the new merged winding or NULL
-winding_t *Winding_TryMerge(winding_t *f1, winding_t *f2, vec3_t planenormal, int keep);
-//create a plane for the winding
-void		Winding_Plane(winding_t *w, vec3_t normal, double *dist);
-//returns the winding area
-float		Winding_Area(winding_t *w);
-//returns the bounds of the winding
-void		Winding_Bounds(winding_t *w, vec3_t mins, vec3_t maxs);
-//returns true if the point is inside the winding
-int			Winding_PointInside(winding_t *w, plane_t *plane, vec3_t point, float epsilon);
-//returns true if the vector intersects with the winding
-int			Winding_VectorIntersect(winding_t *w, plane_t *plane, vec3_t p1, vec3_t p2, float epsilon);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+
+
+//returns true if the planes are equal
+int			Plane_Equal(plane_t *a, plane_t *b, int flip);
+//returns false if the points are colinear
+int			Plane_FromPoints(vec3_t p1, vec3_t p2, vec3_t p3, plane_t *plane);
+//returns true if the points are equal
+int			Point_Equal(vec3_t p1, vec3_t p2, float epsilon);
+
+//allocate a winding
+winding_t*	Winding_Alloc(int points);
+//free the winding
+void		Winding_Free(winding_t *w);
+//create a base winding for the plane
+winding_t*	Winding_BaseForPlane (plane_t *p);
+//make a winding clone
+winding_t*	Winding_Clone(winding_t *w );
+//creates the reversed winding
+winding_t*	Winding_Reverse(winding_t *w);
+//remove a point from the winding
+void		Winding_RemovePoint(winding_t *w, int point);
+//inserts a point to a winding, creating a new winding
+winding_t*	Winding_InsertPoint(winding_t *w, vec3_t point, int spot);
+//returns true if the planes are concave
+int			Winding_PlanesConcave(winding_t *w1, winding_t *w2,
+									 vec3_t normal1, vec3_t normal2,
+									 float dist1, float dist2);
+//returns true if the winding is tiny
+int			Winding_IsTiny(winding_t *w);
+//returns true if the winding is huge
+int			Winding_IsHuge(winding_t *w);
+//clip the winding with the plane
+winding_t*	Winding_Clip(winding_t *in, plane_t *split, qboolean keepon);
+//split the winding with the plane
+void		Winding_SplitEpsilon(winding_t *in, vec3_t normal, double dist, 
+								vec_t epsilon, winding_t **front, winding_t **back);
+//try to merge the windings, returns the new merged winding or NULL
+winding_t *Winding_TryMerge(winding_t *f1, winding_t *f2, vec3_t planenormal, int keep);
+//create a plane for the winding
+void		Winding_Plane(winding_t *w, vec3_t normal, double *dist);
+//returns the winding area
+float		Winding_Area(winding_t *w);
+//returns the bounds of the winding
+void		Winding_Bounds(winding_t *w, vec3_t mins, vec3_t maxs);
+//returns true if the point is inside the winding
+int			Winding_PointInside(winding_t *w, plane_t *plane, vec3_t point, float epsilon);
+//returns true if the vector intersects with the winding
+int			Winding_VectorIntersect(winding_t *w, plane_t *plane, vec3_t p1, vec3_t p2, float epsilon);
diff --git a/radiant/xmlstuff.h b/radiant/xmlstuff.h
index dc23f644..7d69c169 100644
--- a/radiant/xmlstuff.h
+++ b/radiant/xmlstuff.h
@@ -1,70 +1,70 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-//-----------------------------------------------------------------------------
-//
-// DESCRIPTION:
-// header for xml stuff used in radiant
-//
-
-#ifndef __XMLSTUFF__
-#define __XMLSTUFF__
-
-#include "libxml/parser.h"
-
-struct message_info_s;
-
-class ISAXHandler
-{
-public:
-  virtual void saxStartElement (struct message_info_s *ctx, const xmlChar *name, const xmlChar **attrs) = 0;
-  virtual void saxEndElement (struct message_info_s *ctx, const xmlChar *name) = 0;
-  virtual void saxCharacters (struct message_info_s *ctx, const xmlChar *ch, int len) = 0;
-  virtual char *getName() { return NULL; }
-  virtual void Highlight() { }
-  virtual void DropHighlight() { }
-};
-
-// a 'user data' structure we pass along in the SAX callbacks to represent the current state
-// the recurse value tracks the current depth in the tree
-// message_info also stores information to exit the stream listening cleanly with an error:
-//   if msg_level == SYS_ERR, then we will reset the listening at the end of the current node
-//   the level for stopping the feed is stored in stop_depth
-// unkown nodes are ignored, we use ignore_depth to track the level we start ignoring from
-typedef struct message_info_s {
-  int msg_level; // current message level (SYS_MSG, SYS_WRN, SYS_ERR)
-  int recurse; // current recursion depth (used to track various things)
-  int ignore_depth; // the ignore depth limit when we are jumping over unknown nodes (0 means we are not ignoring)
-  int stop_depth; // the depth we need to stop at the end
-  bool bGeometry; // are we parsing some geometry information (i.e. do we forward the SAX calls?)
-  ISAXHandler *pGeometry; // the handler
-} message_info_t;
-
-#endif
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+//-----------------------------------------------------------------------------
+//
+// DESCRIPTION:
+// header for xml stuff used in radiant
+//
+
+#ifndef __XMLSTUFF__
+#define __XMLSTUFF__
+
+#include "libxml/parser.h"
+
+struct message_info_s;
+
+class ISAXHandler
+{
+public:
+  virtual void saxStartElement (struct message_info_s *ctx, const xmlChar *name, const xmlChar **attrs) = 0;
+  virtual void saxEndElement (struct message_info_s *ctx, const xmlChar *name) = 0;
+  virtual void saxCharacters (struct message_info_s *ctx, const xmlChar *ch, int len) = 0;
+  virtual char *getName() { return NULL; }
+  virtual void Highlight() { }
+  virtual void DropHighlight() { }
+};
+
+// a 'user data' structure we pass along in the SAX callbacks to represent the current state
+// the recurse value tracks the current depth in the tree
+// message_info also stores information to exit the stream listening cleanly with an error:
+//   if msg_level == SYS_ERR, then we will reset the listening at the end of the current node
+//   the level for stopping the feed is stored in stop_depth
+// unkown nodes are ignored, we use ignore_depth to track the level we start ignoring from
+typedef struct message_info_s {
+  int msg_level; // current message level (SYS_MSG, SYS_WRN, SYS_ERR)
+  int recurse; // current recursion depth (used to track various things)
+  int ignore_depth; // the ignore depth limit when we are jumping over unknown nodes (0 means we are not ignoring)
+  int stop_depth; // the depth we need to stop at the end
+  bool bGeometry; // are we parsing some geometry information (i.e. do we forward the SAX calls?)
+  ISAXHandler *pGeometry; // the handler
+} message_info_t;
+
+#endif
diff --git a/radiant/xywindow.h b/radiant/xywindow.h
index a81acadd..23aec2c4 100644
--- a/radiant/xywindow.h
+++ b/radiant/xywindow.h
@@ -1,194 +1,194 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _XYWINDOW_H_
-#define _XYWINDOW_H_
-
-#include "qe3.h"
-#include "camwindow.h"
-#include "glwindow.h"
-
-const int SCALE_X = 0x01;
-const int SCALE_Y = 0x02;
-const int SCALE_Z = 0x04;
-
-typedef void (PFNPathCallback)(bool, int);
-// as i didn't really encapsulate anything this
-// should really be a struct..
-class ClipPoint
-{
-public:
-  ClipPoint(){ Reset(); };
-  void Reset(){ m_ptClip[0] = m_ptClip[1] = m_ptClip[2] = 0.0; m_bSet = false; m_pVec3 = NULL;};
-  bool Set(){ return m_bSet; };
-  void Set(bool b) { m_bSet = b; };
-  void UpdatePointPtr() { if (m_pVec3) VectorCopy(m_ptClip, *m_pVec3); };
-  void SetPointPtr(vec3_t* p) { m_pVec3 = p; };
-  vec3_t m_ptClip;      // the 3d point
-  vec3_t* m_pVec3;      // optional ptr for 3rd party updates
-  int m_ptScreenX, m_ptScreenY;    // the onscreen xy point (for mousability)
-  bool m_bSet;
-  operator vec3_t&() {return m_ptClip;};
-  operator vec3_t*() {return &m_ptClip;};
-  
-  /*! Draw clip/path point with rasterized number label */
-  void Draw(float fScale, int num);
-  /*! Draw clip/path point with rasterized string label */
-  void Draw(float fScale, const char *label);
-};
-
-class XYWnd : public GLWindow
-{
-public:
-  XYWnd();
-  virtual ~XYWnd() { }
-
-public:
-  bool AreaSelectOK();
-  vec3_t& RotateOrigin();
-  vec3_t& Rotation();
-  void UndoClear();
-  bool UndoAvailable();
-  void KillPathMode();
-  void Undo();
-  void UndoCopy();
-  void Copy();
-  void Paste();
-  void Redraw(unsigned int nBits);
-  void VectorCopyXY(vec3_t in, vec3_t out);
-  void PositionView();
-  void FlipClip();
-  void SplitClip();
-  void Clip();
-  vec3_t& GetOrigin();
-  void SetOrigin(vec3_t org);		// PGM
-  void XY_Init();
-  void XY_Overlay();
-  void XY_Draw();
-  void DrawZIcon();
-  void DrawRotateIcon();
-  void DrawCameraIcon();
-  void XY_DrawBlockGrid();
-  void XY_DrawGrid();
-  void XY_MouseMoved (int x, int y, int buttons);
-// TTimo: FIXME: was experimental stuff to track possible endless loop issues
-//  void XY_MouseMovedRec (int x, int y, int buttons);
-  void NewBrushDrag (int x, int y);
-  qboolean DragDelta (int x, int y, vec3_t move);
-  void XY_MouseUp(int x, int y, int buttons);
-  void XY_MouseDown (int x, int y, int buttons);
-  void XY_ToGridPoint (int x, int y, vec3_t point);
-  void XY_ToPoint (int x, int y, vec3_t point);
-  void SnapToPoint (int x, int y, vec3_t point);
-  void SetActive(bool b) {m_bActive = b;};
-  bool Active() {return m_bActive;};
-
-  void DropClipPoint(guint32 nFlags, int pointx, int pointy);
-  bool RogueClipMode();
-  bool ClipMode();
-  void SetClipMode(bool bMode);
-  void RetainClipMode(bool bMode);
-
-  bool RotateMode();
-  bool SetRotateMode(bool bMode);
-  bool ScaleMode();
-  void SetScaleMode(bool bMode);
-
-  bool PathMode();
-  void DropPathPoint(guint32 nFlags, int pointx, int pointy);
-  bool PointMode();
-//  void AddPointPoint(guint32 nFlags, vec3_t* pVec);
-  void SetPointMode(bool b);
-
-  void SetViewType(int n);
-  bool m_bActive;
-
-protected:
-  int m_nUpdateBits;
-  int m_nWidth;
-  int m_nHeight;
-  bool m_bTiming;
-  float	m_fScale;
-  float	m_TopClip;
-  float m_BottomClip;
-  bool m_bDirty;
-  vec3_t m_vOrigin;
-
-  int m_ptCursorX, m_ptCursorY;
-  bool m_bRButtonDown;
-
-  int m_nButtonstate;
-  int m_nPressx;
-  int m_nPressy;
-  vec3_t m_vPressdelta;
-  bool m_bPress_selection;
-
-  friend class CamWnd;
-
-private:
-  // this is unique for all views
-  static GtkWidget* m_mnuDrop;
-
-  int m_nViewType;
-
-  int m_nScrollFlags;
-  int m_ptDragX, m_ptDragY;
-  int m_ptDragAdjX, m_ptDragAdjY;
-  int m_ptDragTotalX, m_ptDragTotalY;
-
-  void OriginalButtonUp(guint32 nFlags, int point, int pointy);
-  void OriginalButtonDown(guint32 nFlags, int point, int pointy);
-//  void ProduceSplits(brush_t** pFront, brush_t** pBack);
-  void PlanePointsFromClipPoints(vec3_t planepts[3], brush_t *pBrush);
-  void ProduceSplitLists();
-  void HandleDrop();
-  void PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds);
-
-  int m_ptDownX, m_ptDownY;
-
-public:
-  void OnEntityCreate(const char* item);
-  int GetViewType() {return m_nViewType; }
-  void SetScale(float f) {m_fScale = f;}
-  float Scale() {return m_fScale;}
-  int Width() {return m_nWidth;}
-  int Height() {return m_nHeight;}
-
-protected:
-
-  void OnCreate ();
-  void OnExpose ();
-  void OnLButtonDown(guint32 flags, int pointx, int pointy);
-  void OnRButtonDown(guint32 flags, int pointx, int pointy);
-  void OnMButtonDown(guint32 flags, int pointx, int pointy);
-  void OnLButtonUp(guint32 flags, int pointx, int pointy);
-  void OnRButtonUp(guint32 flags, int pointx, int pointy);
-  void OnMButtonUp(guint32 flags, int pointx, int pointy);
-  void OnMouseMove(guint32 nFlags, int pointx, int pointy);
-  void OnMouseWheel(bool bUp);
-  void OnSize (int cx, int cy);
-  void OnTimer();
-
-private:
-  XORRectangle m_XORRectangle;
-};
-
-#endif // _XYWINDOW_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _XYWINDOW_H_
+#define _XYWINDOW_H_
+
+#include "qe3.h"
+#include "camwindow.h"
+#include "glwindow.h"
+
+const int SCALE_X = 0x01;
+const int SCALE_Y = 0x02;
+const int SCALE_Z = 0x04;
+
+typedef void (PFNPathCallback)(bool, int);
+// as i didn't really encapsulate anything this
+// should really be a struct..
+class ClipPoint
+{
+public:
+  ClipPoint(){ Reset(); };
+  void Reset(){ m_ptClip[0] = m_ptClip[1] = m_ptClip[2] = 0.0; m_bSet = false; m_pVec3 = NULL;};
+  bool Set(){ return m_bSet; };
+  void Set(bool b) { m_bSet = b; };
+  void UpdatePointPtr() { if (m_pVec3) VectorCopy(m_ptClip, *m_pVec3); };
+  void SetPointPtr(vec3_t* p) { m_pVec3 = p; };
+  vec3_t m_ptClip;      // the 3d point
+  vec3_t* m_pVec3;      // optional ptr for 3rd party updates
+  int m_ptScreenX, m_ptScreenY;    // the onscreen xy point (for mousability)
+  bool m_bSet;
+  operator vec3_t&() {return m_ptClip;};
+  operator vec3_t*() {return &m_ptClip;};
+  
+  /*! Draw clip/path point with rasterized number label */
+  void Draw(float fScale, int num);
+  /*! Draw clip/path point with rasterized string label */
+  void Draw(float fScale, const char *label);
+};
+
+class XYWnd : public GLWindow
+{
+public:
+  XYWnd();
+  virtual ~XYWnd() { }
+
+public:
+  bool AreaSelectOK();
+  vec3_t& RotateOrigin();
+  vec3_t& Rotation();
+  void UndoClear();
+  bool UndoAvailable();
+  void KillPathMode();
+  void Undo();
+  void UndoCopy();
+  void Copy();
+  void Paste();
+  void Redraw(unsigned int nBits);
+  void VectorCopyXY(vec3_t in, vec3_t out);
+  void PositionView();
+  void FlipClip();
+  void SplitClip();
+  void Clip();
+  vec3_t& GetOrigin();
+  void SetOrigin(vec3_t org);		// PGM
+  void XY_Init();
+  void XY_Overlay();
+  void XY_Draw();
+  void DrawZIcon();
+  void DrawRotateIcon();
+  void DrawCameraIcon();
+  void XY_DrawBlockGrid();
+  void XY_DrawGrid();
+  void XY_MouseMoved (int x, int y, int buttons);
+// TTimo: FIXME: was experimental stuff to track possible endless loop issues
+//  void XY_MouseMovedRec (int x, int y, int buttons);
+  void NewBrushDrag (int x, int y);
+  qboolean DragDelta (int x, int y, vec3_t move);
+  void XY_MouseUp(int x, int y, int buttons);
+  void XY_MouseDown (int x, int y, int buttons);
+  void XY_ToGridPoint (int x, int y, vec3_t point);
+  void XY_ToPoint (int x, int y, vec3_t point);
+  void SnapToPoint (int x, int y, vec3_t point);
+  void SetActive(bool b) {m_bActive = b;};
+  bool Active() {return m_bActive;};
+
+  void DropClipPoint(guint32 nFlags, int pointx, int pointy);
+  bool RogueClipMode();
+  bool ClipMode();
+  void SetClipMode(bool bMode);
+  void RetainClipMode(bool bMode);
+
+  bool RotateMode();
+  bool SetRotateMode(bool bMode);
+  bool ScaleMode();
+  void SetScaleMode(bool bMode);
+
+  bool PathMode();
+  void DropPathPoint(guint32 nFlags, int pointx, int pointy);
+  bool PointMode();
+//  void AddPointPoint(guint32 nFlags, vec3_t* pVec);
+  void SetPointMode(bool b);
+
+  void SetViewType(int n);
+  bool m_bActive;
+
+protected:
+  int m_nUpdateBits;
+  int m_nWidth;
+  int m_nHeight;
+  bool m_bTiming;
+  float	m_fScale;
+  float	m_TopClip;
+  float m_BottomClip;
+  bool m_bDirty;
+  vec3_t m_vOrigin;
+
+  int m_ptCursorX, m_ptCursorY;
+  bool m_bRButtonDown;
+
+  int m_nButtonstate;
+  int m_nPressx;
+  int m_nPressy;
+  vec3_t m_vPressdelta;
+  bool m_bPress_selection;
+
+  friend class CamWnd;
+
+private:
+  // this is unique for all views
+  static GtkWidget* m_mnuDrop;
+
+  int m_nViewType;
+
+  int m_nScrollFlags;
+  int m_ptDragX, m_ptDragY;
+  int m_ptDragAdjX, m_ptDragAdjY;
+  int m_ptDragTotalX, m_ptDragTotalY;
+
+  void OriginalButtonUp(guint32 nFlags, int point, int pointy);
+  void OriginalButtonDown(guint32 nFlags, int point, int pointy);
+//  void ProduceSplits(brush_t** pFront, brush_t** pBack);
+  void PlanePointsFromClipPoints(vec3_t planepts[3], brush_t *pBrush);
+  void ProduceSplitLists();
+  void HandleDrop();
+  void PaintSizeInfo(int nDim1, int nDim2, vec3_t vMinBounds, vec3_t vMaxBounds);
+
+  int m_ptDownX, m_ptDownY;
+
+public:
+  void OnEntityCreate(const char* item);
+  int GetViewType() {return m_nViewType; }
+  void SetScale(float f) {m_fScale = f;}
+  float Scale() {return m_fScale;}
+  int Width() {return m_nWidth;}
+  int Height() {return m_nHeight;}
+
+protected:
+
+  void OnCreate ();
+  void OnExpose ();
+  void OnLButtonDown(guint32 flags, int pointx, int pointy);
+  void OnRButtonDown(guint32 flags, int pointx, int pointy);
+  void OnMButtonDown(guint32 flags, int pointx, int pointy);
+  void OnLButtonUp(guint32 flags, int pointx, int pointy);
+  void OnRButtonUp(guint32 flags, int pointx, int pointy);
+  void OnMButtonUp(guint32 flags, int pointx, int pointy);
+  void OnMouseMove(guint32 nFlags, int pointx, int pointy);
+  void OnMouseWheel(bool bUp);
+  void OnSize (int cx, int cy);
+  void OnTimer();
+
+private:
+  XORRectangle m_XORRectangle;
+};
+
+#endif // _XYWINDOW_H_
diff --git a/radiant/z.h b/radiant/z.h
index acf12a89..aee8bae2 100644
--- a/radiant/z.h
+++ b/radiant/z.h
@@ -1,42 +1,42 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-// window system independent camera view code
-
-typedef struct
-{
-  int	    width, height;
-
-  qboolean  timing;
-
-  vec3_t    origin;			// at center of window
-  float	    scale;
-} z_t;
-
-extern z_t z;
-
-void Z_Init (void);
-void Z_MouseDown (int x, int y, int buttons);
-void Z_MouseUp (int x, int y, int buttons);
-void Z_MouseMoved (int x, int y, int buttons);
-void Z_Draw (void);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+// window system independent camera view code
+
+typedef struct
+{
+  int	    width, height;
+
+  qboolean  timing;
+
+  vec3_t    origin;			// at center of window
+  float	    scale;
+} z_t;
+
+extern z_t z;
+
+void Z_Init (void);
+void Z_MouseDown (int x, int y, int buttons);
+void Z_MouseUp (int x, int y, int buttons);
+void Z_MouseMoved (int x, int y, int buttons);
+void Z_Draw (void);
+
diff --git a/radiant/zwindow.h b/radiant/zwindow.h
index d1f42bbd..90f3954b 100644
--- a/radiant/zwindow.h
+++ b/radiant/zwindow.h
@@ -1,46 +1,46 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _ZWINDOW_H_
-#define _ZWINDOW_H_
-
-#include "glwindow.h"
-
-class ZWnd : public GLWindow
-{
- public:
-  ZWnd ();
-  virtual ~ZWnd ();
-
-  void OnCreate ();
-  void OnExpose ();
-  void OnLButtonDown (guint32 flags, int x, int y);
-  void OnRButtonDown (guint32 flags, int x, int y);
-  void OnMButtonDown (guint32 flags, int x, int y);
-  void OnLButtonUp (guint32 flags, int pointx, int pointy);
-  void OnRButtonUp (guint32 flags, int pointx, int pointy);
-  void OnMButtonUp (guint32 flags, int pointx, int pointy);
-  void OnMouseMove (guint32 flags, int pointx, int pointy);
-  void OnSize (int cx, int cy);
-};
-
-
-#endif // _ZWINDOW_H_
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _ZWINDOW_H_
+#define _ZWINDOW_H_
+
+#include "glwindow.h"
+
+class ZWnd : public GLWindow
+{
+ public:
+  ZWnd ();
+  virtual ~ZWnd ();
+
+  void OnCreate ();
+  void OnExpose ();
+  void OnLButtonDown (guint32 flags, int x, int y);
+  void OnRButtonDown (guint32 flags, int x, int y);
+  void OnMButtonDown (guint32 flags, int x, int y);
+  void OnLButtonUp (guint32 flags, int pointx, int pointy);
+  void OnRButtonUp (guint32 flags, int pointx, int pointy);
+  void OnMButtonUp (guint32 flags, int pointx, int pointy);
+  void OnMouseMove (guint32 flags, int pointx, int pointy);
+  void OnSize (int cx, int cy);
+};
+
+
+#endif // _ZWINDOW_H_
diff --git a/tools/quake2/common/bspfile.c b/tools/quake2/common/bspfile.c
index eac27aff..df3f059b 100644
--- a/tools/quake2/common/bspfile.c
+++ b/tools/quake2/common/bspfile.c
@@ -1,789 +1,789 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "bspfile.h"
-#include "scriplib.h"
-#include "inout.h"
-
-void GetLeafNums (void);
-
-//=============================================================================
-
-int			nummodels;
-dmodel_t	dmodels[MAX_MAP_MODELS];
-
-int			visdatasize;
-byte		dvisdata[MAX_MAP_VISIBILITY];
-dvis_t		*dvis = (dvis_t *)dvisdata;
-
-int			lightdatasize;
-byte		dlightdata[MAX_MAP_LIGHTING];
-
-int			entdatasize;
-char		dentdata[MAX_MAP_ENTSTRING];
-
-int			numleafs;
-dleaf_t		dleafs[MAX_MAP_LEAFS];
-
-int			numplanes;
-dplane_t	dplanes[MAX_MAP_PLANES];
-
-int			numvertexes;
-dvertex_t	dvertexes[MAX_MAP_VERTS];
-
-int			numnodes;
-dnode_t		dnodes[MAX_MAP_NODES];
-
-int			numtexinfo;
-texinfo_t	texinfo[MAX_MAP_TEXINFO];
-
-int			numfaces;
-dface_t		dfaces[MAX_MAP_FACES];
-
-int			numedges;
-dedge_t		dedges[MAX_MAP_EDGES];
-
-int			numleaffaces;
-unsigned short		dleaffaces[MAX_MAP_LEAFFACES];
-
-int			numleafbrushes;
-unsigned short		dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-int			numsurfedges;
-int			dsurfedges[MAX_MAP_SURFEDGES];
-
-int			numbrushes;
-dbrush_t	dbrushes[MAX_MAP_BRUSHES];
-
-int			numbrushsides;
-dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
-
-int			numareas;
-darea_t		dareas[MAX_MAP_AREAS];
-
-int			numareaportals;
-dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
-
-byte		dpop[256];
-
-/*
-===============
-CompressVis
-
-===============
-*/
-int CompressVis (byte *vis, byte *dest)
-{
-	int		j;
-	int		rep;
-	int		visrow;
-	byte	*dest_p;
-	
-	dest_p = dest;
-//	visrow = (r_numvisleafs + 7)>>3;
-	visrow = (dvis->numclusters + 7)>>3;
-	
-	for (j=0 ; j<visrow ; j++)
-	{
-		*dest_p++ = vis[j];
-		if (vis[j])
-			continue;
-
-		rep = 1;
-		for ( j++; j<visrow ; j++)
-			if (vis[j] || rep == 255)
-				break;
-			else
-				rep++;
-		*dest_p++ = rep;
-		j--;
-	}
-	
-	return dest_p - dest;
-}
-
-
-/*
-===================
-DecompressVis
-===================
-*/
-void DecompressVis (byte *in, byte *decompressed)
-{
-	int		c;
-	byte	*out;
-	int		row;
-
-//	row = (r_numvisleafs+7)>>3;	
-	row = (dvis->numclusters+7)>>3;	
-	out = decompressed;
-
-	do
-	{
-		if (*in)
-		{
-			*out++ = *in++;
-			continue;
-		}
-	
-		c = in[1];
-		if (!c)
-			Error ("DecompressVis: 0 repeat");
-		in += 2;
-		while (c)
-		{
-			*out++ = 0;
-			c--;
-		}
-	} while (out - decompressed < row);
-}
-
-//=============================================================================
-
-/*
-=============
-SwapBSPFile
-
-Byte swaps all data in a bsp file.
-=============
-*/
-void SwapBSPFile (qboolean todisk)
-{
-	int				i, j;
-	dmodel_t		*d;
-
-	
-// models	
-	for (i=0 ; i<nummodels ; i++)
-	{
-		d = &dmodels[i];
-
-		d->firstface = LittleLong (d->firstface);
-		d->numfaces = LittleLong (d->numfaces);
-		d->headnode = LittleLong (d->headnode);
-		
-		for (j=0 ; j<3 ; j++)
-		{
-			d->mins[j] = LittleFloat(d->mins[j]);
-			d->maxs[j] = LittleFloat(d->maxs[j]);
-			d->origin[j] = LittleFloat(d->origin[j]);
-		}
-	}
-
-//
-// vertexes
-//
-	for (i=0 ; i<numvertexes ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-			dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
-	}
-		
-//
-// planes
-//	
-	for (i=0 ; i<numplanes ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-			dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
-		dplanes[i].dist = LittleFloat (dplanes[i].dist);
-		dplanes[i].type = LittleLong (dplanes[i].type);
-	}
-	
-//
-// texinfos
-//	
-	for (i=0 ; i<numtexinfo ; i++)
-	{
-		for (j=0 ; j<8 ; j++)
-			texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
-		texinfo[i].flags = LittleLong (texinfo[i].flags);
-		texinfo[i].value = LittleLong (texinfo[i].value);
-		texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
-	}
-	
-//
-// faces
-//
-	for (i=0 ; i<numfaces ; i++)
-	{
-		dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
-		dfaces[i].planenum = LittleShort (dfaces[i].planenum);
-		dfaces[i].side = LittleShort (dfaces[i].side);
-		dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
-		dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
-		dfaces[i].numedges = LittleShort (dfaces[i].numedges);
-	}
-
-//
-// nodes
-//
-	for (i=0 ; i<numnodes ; i++)
-	{
-		dnodes[i].planenum = LittleLong (dnodes[i].planenum);
-		for (j=0 ; j<3 ; j++)
-		{
-			dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
-			dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
-		}
-		dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
-		dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
-		dnodes[i].firstface = LittleShort (dnodes[i].firstface);
-		dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
-	}
-
-//
-// leafs
-//
-	for (i=0 ; i<numleafs ; i++)
-	{
-		dleafs[i].contents = LittleLong (dleafs[i].contents);
-		dleafs[i].cluster = LittleShort (dleafs[i].cluster);
-		dleafs[i].area = LittleShort (dleafs[i].area);
-		for (j=0 ; j<3 ; j++)
-		{
-			dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
-			dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
-		}
-
-		dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
-		dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
-		dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
-		dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
-	}
-
-//
-// leaffaces
-//
-	for (i=0 ; i<numleaffaces ; i++)
-		dleaffaces[i] = LittleShort (dleaffaces[i]);
-
-//
-// leafbrushes
-//
-	for (i=0 ; i<numleafbrushes ; i++)
-		dleafbrushes[i] = LittleShort (dleafbrushes[i]);
-
-//
-// surfedges
-//
-	for (i=0 ; i<numsurfedges ; i++)
-		dsurfedges[i] = LittleLong (dsurfedges[i]);
-
-//
-// edges
-//
-	for (i=0 ; i<numedges ; i++)
-	{
-		dedges[i].v[0] = LittleShort (dedges[i].v[0]);
-		dedges[i].v[1] = LittleShort (dedges[i].v[1]);
-	}
-
-//
-// brushes
-//
-	for (i=0 ; i<numbrushes ; i++)
-	{
-		dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
-		dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
-		dbrushes[i].contents = LittleLong (dbrushes[i].contents);
-	}
-
-//
-// areas
-//
-	for (i=0 ; i<numareas ; i++)
-	{
-		dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
-		dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
-	}
-
-//
-// areasportals
-//
-	for (i=0 ; i<numareaportals ; i++)
-	{
-		dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
-		dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
-	}
-
-//
-// brushsides
-//
-	for (i=0 ; i<numbrushsides ; i++)
-	{
-		dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
-		dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
-	}
-
-//
-// visibility
-//
-	if (todisk)
-		j = dvis->numclusters;
-	else
-		j = LittleLong(dvis->numclusters);
-	dvis->numclusters = LittleLong (dvis->numclusters);
-	for (i=0 ; i<j ; i++)
-	{
-		dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
-		dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
-	}
-}
-
-
-dheader_t	*header;
-
-int CopyLump (int lump, void *dest, int size)
-{
-	int		length, ofs;
-
-	length = header->lumps[lump].filelen;
-	ofs = header->lumps[lump].fileofs;
-	
-	if (length % size)
-		Error ("LoadBSPFile: odd lump size");
-	
-	memcpy (dest, (byte *)header + ofs, length);
-
-	return length / size;
-}
-
-/*
-=============
-LoadBSPFile
-=============
-*/
-void	LoadBSPFile (char *filename)
-{
-	int			i;
-	
-//
-// load the file header
-//
-	LoadFile (filename, (void **)&header);
-
-// swap the header
-	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
-		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
-
-	if (header->ident != IDBSPHEADER)
-		Error ("%s is not a IBSP file", filename);
-	if (header->version != BSPVERSION)
-		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
-
-	nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
-	numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
-	numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
-	numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
-	numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
-	numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
-	numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
-	numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]));
-	numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]));
-	numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
-	numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
-	numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t));
-	numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t));
-	numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t));
-	numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t));
-
-	visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
-	lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
-	entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
-
-	CopyLump (LUMP_POP, dpop, 1);
-
-	free (header);		// everything has been copied out
-		
-//
-// swap everything
-//	
-	SwapBSPFile (false);
-}
-
-
-/*
-=============
-LoadBSPFileTexinfo
-
-Only loads the texinfo lump, so qdata can scan for textures
-=============
-*/
-void	LoadBSPFileTexinfo (char *filename)
-{
-	int			i;
-	FILE		*f;
-	int		length, ofs;
-
-	header = malloc(sizeof(dheader_t));
-
-	f = fopen (filename, "rb");
-	fread (header, sizeof(dheader_t), 1, f);
-
-// swap the header
-	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
-		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
-
-	if (header->ident != IDBSPHEADER)
-		Error ("%s is not a IBSP file", filename);
-	if (header->version != BSPVERSION)
-		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
-
-
-	length = header->lumps[LUMP_TEXINFO].filelen;
-	ofs = header->lumps[LUMP_TEXINFO].fileofs;
-
-	fseek (f, ofs, SEEK_SET);
-	fread (texinfo, length, 1, f);
-	fclose (f);
-
-	numtexinfo = length / sizeof(texinfo_t);
-
-	free (header);		// everything has been copied out
-		
-	SwapBSPFile (false);
-}
-
-
-//============================================================================
-
-FILE		*wadfile;
-dheader_t	outheader;
-
-void AddLump (int lumpnum, void *data, int len)
-{
-	lump_t *lump;
-
-	lump = &header->lumps[lumpnum];
-	
-	lump->fileofs = LittleLong( ftell(wadfile) );
-	lump->filelen = LittleLong(len);
-	SafeWrite (wadfile, data, (len+3)&~3);
-}
-
-/*
-=============
-WriteBSPFile
-
-Swaps the bsp file in place, so it should not be referenced again
-=============
-*/
-void	WriteBSPFile (char *filename)
-{		
-	header = &outheader;
-	memset (header, 0, sizeof(dheader_t));
-	
-	SwapBSPFile (true);
-
-	header->ident = LittleLong (IDBSPHEADER);
-	header->version = LittleLong (BSPVERSION);
-	
-	wadfile = SafeOpenWrite (filename);
-	SafeWrite (wadfile, header, sizeof(dheader_t));	// overwritten later
-
-	AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
-	AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
-	AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
-	AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
-	AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
-	AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
-	AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
-	AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
-	AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
-	AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
-	AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
-	AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
-	AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
-	AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
-	AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
-
-	AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
-	AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
-	AddLump (LUMP_ENTITIES, dentdata, entdatasize);
-	AddLump (LUMP_POP, dpop, sizeof(dpop));
-	
-	fseek (wadfile, 0, SEEK_SET);
-	SafeWrite (wadfile, header, sizeof(dheader_t));
-	fclose (wadfile);	
-}
-
-//============================================================================
-
-/*
-=============
-PrintBSPFileSizes
-
-Dumps info about current file
-=============
-*/
-void PrintBSPFileSizes (void)
-{
-	if (!num_entities)
-		ParseEntities ();
-
-	printf ("%5i models       %7i\n"
-		,nummodels, (int)(nummodels*sizeof(dmodel_t)));
-	printf ("%5i brushes      %7i\n"
-		,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
-	printf ("%5i brushsides   %7i\n"
-		,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
-	printf ("%5i planes       %7i\n"
-		,numplanes, (int)(numplanes*sizeof(dplane_t)));
-	printf ("%5i texinfo      %7i\n"
-		,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
-	printf ("%5i entdata      %7i\n", num_entities, entdatasize);
-
-	printf ("\n");
-
-	printf ("%5i vertexes     %7i\n"
-		,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
-	printf ("%5i nodes        %7i\n"
-		,numnodes, (int)(numnodes*sizeof(dnode_t)));
-	printf ("%5i faces        %7i\n"
-		,numfaces, (int)(numfaces*sizeof(dface_t)));
-	printf ("%5i leafs        %7i\n"
-		,numleafs, (int)(numleafs*sizeof(dleaf_t)));
-	printf ("%5i leaffaces    %7i\n"
-		,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
-	printf ("%5i leafbrushes  %7i\n"
-		,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
-	printf ("%5i surfedges    %7i\n"
-		,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
-	printf ("%5i edges        %7i\n"
-		,numedges, (int)(numedges*sizeof(dedge_t)));
-	printf ("      lightdata    %7i\n", lightdatasize);
-	printf ("      visdata      %7i\n", visdatasize);
-}
-
-
-//============================================
-
-int			num_entities;
-entity_t	entities[MAX_MAP_ENTITIES];
-
-void StripTrailing (char *e)
-{
-	char	*s;
-
-	s = e + strlen(e)-1;
-	while (s >= e && *s <= 32)
-	{
-		*s = 0;
-		s--;
-	}
-}
-
-/*
-=================
-ParseEpair
-=================
-*/
-epair_t *ParseEpair (void)
-{
-	epair_t	*e;
-
-	e = malloc (sizeof(epair_t));
-	memset (e, 0, sizeof(epair_t));
-	
-	if (strlen(token) >= MAX_KEY-1)
-		Error ("ParseEpar: token too long");
-	e->key = copystring(token);
-	GetToken (false);
-	if (strlen(token) >= MAX_VALUE-1)
-		Error ("ParseEpar: token too long");
-	e->value = copystring(token);
-
-	// strip trailing spaces
-	StripTrailing (e->key);
-	StripTrailing (e->value);
-
-	return e;
-}
-
-
-/*
-================
-ParseEntity
-================
-*/
-qboolean	ParseEntity (void)
-{
-	epair_t		*e;
-	entity_t	*mapent;
-
-	if (!GetToken (true))
-		return false;
-
-	if (strcmp (token, "{") )
-		Error ("ParseEntity: { not found");
-	
-	if (num_entities == MAX_MAP_ENTITIES)
-		Error ("num_entities == MAX_MAP_ENTITIES");
-
-	mapent = &entities[num_entities];
-	num_entities++;
-
-	do
-	{
-		if (!GetToken (true))
-			Error ("ParseEntity: EOF without closing brace");
-		if (!strcmp (token, "}") )
-			break;
-		e = ParseEpair ();
-		e->next = mapent->epairs;
-		mapent->epairs = e;
-	} while (1);
-	
-	return true;
-}
-
-/*
-================
-ParseEntities
-
-Parses the dentdata string into entities
-================
-*/
-void ParseEntities (void)
-{
-	num_entities = 0;
-	ParseFromMemory (dentdata, entdatasize);
-
-	while (ParseEntity ())
-	{
-	}	
-}
-
-
-/*
-================
-UnparseEntities
-
-Generates the dentdata string from all the entities
-================
-*/
-void UnparseEntities (void)
-{
-	char	*buf, *end;
-	epair_t	*ep;
-	char	line[2048];
-	int		i;
-	char	key[1024], value[1024];
-
-	buf = dentdata;
-	end = buf;
-	*end = 0;
-	
-	for (i=0 ; i<num_entities ; i++)
-	{
-		ep = entities[i].epairs;
-		if (!ep)
-			continue;	// ent got removed
-		
-		strcat (end,"{\n");
-		end += 2;
-				
-		for (ep = entities[i].epairs ; ep ; ep=ep->next)
-		{
-			strcpy (key, ep->key);
-			StripTrailing (key);
-			strcpy (value, ep->value);
-			StripTrailing (value);
-				
-			sprintf (line, "\"%s\" \"%s\"\n", key, value);
-			strcat (end, line);
-			end += strlen(line);
-		}
-		strcat (end,"}\n");
-		end += 2;
-
-		if (end > buf + MAX_MAP_ENTSTRING)
-			Error ("Entity text too long");
-	}
-	entdatasize = end - buf + 1;
-}
-
-void PrintEntity (entity_t *ent)
-{
-	epair_t	*ep;
-	
-	printf ("------- entity %p -------\n", ent);
-	for (ep=ent->epairs ; ep ; ep=ep->next)
-	{
-		printf ("%s = %s\n", ep->key, ep->value);
-	}
-
-}
-
-void 	SetKeyValue (entity_t *ent, char *key, char *value)
-{
-	epair_t	*ep;
-	
-	for (ep=ent->epairs ; ep ; ep=ep->next)
-		if (!strcmp (ep->key, key) )
-		{
-			free (ep->value);
-			ep->value = copystring(value);
-			return;
-		}
-	ep = malloc (sizeof(*ep));
-	ep->next = ent->epairs;
-	ent->epairs = ep;
-	ep->key = copystring(key);
-	ep->value = copystring(value);
-}
-
-char 	*ValueForKey (entity_t *ent, char *key)
-{
-	epair_t	*ep;
-	
-	for (ep=ent->epairs ; ep ; ep=ep->next)
-		if (!strcmp (ep->key, key) )
-			return ep->value;
-	return "";
-}
-
-vec_t	FloatForKey (entity_t *ent, char *key)
-{
-	char	*k;
-	
-	k = ValueForKey (ent, key);
-	return atof(k);
-}
-
-void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
-{
-	char	*k;
-	double	v1, v2, v3;
-
-	k = ValueForKey (ent, key);
-// scanf into doubles, then assign, so it is vec_t size independent
-	v1 = v2 = v3 = 0;
-	sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
-	vec[0] = v1;
-	vec[1] = v2;
-	vec[2] = v3;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "bspfile.h"
+#include "scriplib.h"
+#include "inout.h"
+
+void GetLeafNums (void);
+
+//=============================================================================
+
+int			nummodels;
+dmodel_t	dmodels[MAX_MAP_MODELS];
+
+int			visdatasize;
+byte		dvisdata[MAX_MAP_VISIBILITY];
+dvis_t		*dvis = (dvis_t *)dvisdata;
+
+int			lightdatasize;
+byte		dlightdata[MAX_MAP_LIGHTING];
+
+int			entdatasize;
+char		dentdata[MAX_MAP_ENTSTRING];
+
+int			numleafs;
+dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+int			numplanes;
+dplane_t	dplanes[MAX_MAP_PLANES];
+
+int			numvertexes;
+dvertex_t	dvertexes[MAX_MAP_VERTS];
+
+int			numnodes;
+dnode_t		dnodes[MAX_MAP_NODES];
+
+int			numtexinfo;
+texinfo_t	texinfo[MAX_MAP_TEXINFO];
+
+int			numfaces;
+dface_t		dfaces[MAX_MAP_FACES];
+
+int			numedges;
+dedge_t		dedges[MAX_MAP_EDGES];
+
+int			numleaffaces;
+unsigned short		dleaffaces[MAX_MAP_LEAFFACES];
+
+int			numleafbrushes;
+unsigned short		dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+int			numsurfedges;
+int			dsurfedges[MAX_MAP_SURFEDGES];
+
+int			numbrushes;
+dbrush_t	dbrushes[MAX_MAP_BRUSHES];
+
+int			numbrushsides;
+dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
+
+int			numareas;
+darea_t		dareas[MAX_MAP_AREAS];
+
+int			numareaportals;
+dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
+
+byte		dpop[256];
+
+/*
+===============
+CompressVis
+
+===============
+*/
+int CompressVis (byte *vis, byte *dest)
+{
+	int		j;
+	int		rep;
+	int		visrow;
+	byte	*dest_p;
+	
+	dest_p = dest;
+//	visrow = (r_numvisleafs + 7)>>3;
+	visrow = (dvis->numclusters + 7)>>3;
+	
+	for (j=0 ; j<visrow ; j++)
+	{
+		*dest_p++ = vis[j];
+		if (vis[j])
+			continue;
+
+		rep = 1;
+		for ( j++; j<visrow ; j++)
+			if (vis[j] || rep == 255)
+				break;
+			else
+				rep++;
+		*dest_p++ = rep;
+		j--;
+	}
+	
+	return dest_p - dest;
+}
+
+
+/*
+===================
+DecompressVis
+===================
+*/
+void DecompressVis (byte *in, byte *decompressed)
+{
+	int		c;
+	byte	*out;
+	int		row;
+
+//	row = (r_numvisleafs+7)>>3;	
+	row = (dvis->numclusters+7)>>3;	
+	out = decompressed;
+
+	do
+	{
+		if (*in)
+		{
+			*out++ = *in++;
+			continue;
+		}
+	
+		c = in[1];
+		if (!c)
+			Error ("DecompressVis: 0 repeat");
+		in += 2;
+		while (c)
+		{
+			*out++ = 0;
+			c--;
+		}
+	} while (out - decompressed < row);
+}
+
+//=============================================================================
+
+/*
+=============
+SwapBSPFile
+
+Byte swaps all data in a bsp file.
+=============
+*/
+void SwapBSPFile (qboolean todisk)
+{
+	int				i, j;
+	dmodel_t		*d;
+
+	
+// models	
+	for (i=0 ; i<nummodels ; i++)
+	{
+		d = &dmodels[i];
+
+		d->firstface = LittleLong (d->firstface);
+		d->numfaces = LittleLong (d->numfaces);
+		d->headnode = LittleLong (d->headnode);
+		
+		for (j=0 ; j<3 ; j++)
+		{
+			d->mins[j] = LittleFloat(d->mins[j]);
+			d->maxs[j] = LittleFloat(d->maxs[j]);
+			d->origin[j] = LittleFloat(d->origin[j]);
+		}
+	}
+
+//
+// vertexes
+//
+	for (i=0 ; i<numvertexes ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+			dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
+	}
+		
+//
+// planes
+//	
+	for (i=0 ; i<numplanes ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+			dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
+		dplanes[i].dist = LittleFloat (dplanes[i].dist);
+		dplanes[i].type = LittleLong (dplanes[i].type);
+	}
+	
+//
+// texinfos
+//	
+	for (i=0 ; i<numtexinfo ; i++)
+	{
+		for (j=0 ; j<8 ; j++)
+			texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
+		texinfo[i].flags = LittleLong (texinfo[i].flags);
+		texinfo[i].value = LittleLong (texinfo[i].value);
+		texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
+	}
+	
+//
+// faces
+//
+	for (i=0 ; i<numfaces ; i++)
+	{
+		dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
+		dfaces[i].planenum = LittleShort (dfaces[i].planenum);
+		dfaces[i].side = LittleShort (dfaces[i].side);
+		dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
+		dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
+		dfaces[i].numedges = LittleShort (dfaces[i].numedges);
+	}
+
+//
+// nodes
+//
+	for (i=0 ; i<numnodes ; i++)
+	{
+		dnodes[i].planenum = LittleLong (dnodes[i].planenum);
+		for (j=0 ; j<3 ; j++)
+		{
+			dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
+			dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
+		}
+		dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
+		dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
+		dnodes[i].firstface = LittleShort (dnodes[i].firstface);
+		dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
+	}
+
+//
+// leafs
+//
+	for (i=0 ; i<numleafs ; i++)
+	{
+		dleafs[i].contents = LittleLong (dleafs[i].contents);
+		dleafs[i].cluster = LittleShort (dleafs[i].cluster);
+		dleafs[i].area = LittleShort (dleafs[i].area);
+		for (j=0 ; j<3 ; j++)
+		{
+			dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
+			dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
+		}
+
+		dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
+		dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
+		dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
+		dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
+	}
+
+//
+// leaffaces
+//
+	for (i=0 ; i<numleaffaces ; i++)
+		dleaffaces[i] = LittleShort (dleaffaces[i]);
+
+//
+// leafbrushes
+//
+	for (i=0 ; i<numleafbrushes ; i++)
+		dleafbrushes[i] = LittleShort (dleafbrushes[i]);
+
+//
+// surfedges
+//
+	for (i=0 ; i<numsurfedges ; i++)
+		dsurfedges[i] = LittleLong (dsurfedges[i]);
+
+//
+// edges
+//
+	for (i=0 ; i<numedges ; i++)
+	{
+		dedges[i].v[0] = LittleShort (dedges[i].v[0]);
+		dedges[i].v[1] = LittleShort (dedges[i].v[1]);
+	}
+
+//
+// brushes
+//
+	for (i=0 ; i<numbrushes ; i++)
+	{
+		dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
+		dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
+		dbrushes[i].contents = LittleLong (dbrushes[i].contents);
+	}
+
+//
+// areas
+//
+	for (i=0 ; i<numareas ; i++)
+	{
+		dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
+		dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
+	}
+
+//
+// areasportals
+//
+	for (i=0 ; i<numareaportals ; i++)
+	{
+		dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
+		dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
+	}
+
+//
+// brushsides
+//
+	for (i=0 ; i<numbrushsides ; i++)
+	{
+		dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
+		dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
+	}
+
+//
+// visibility
+//
+	if (todisk)
+		j = dvis->numclusters;
+	else
+		j = LittleLong(dvis->numclusters);
+	dvis->numclusters = LittleLong (dvis->numclusters);
+	for (i=0 ; i<j ; i++)
+	{
+		dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
+		dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
+	}
+}
+
+
+dheader_t	*header;
+
+int CopyLump (int lump, void *dest, int size)
+{
+	int		length, ofs;
+
+	length = header->lumps[lump].filelen;
+	ofs = header->lumps[lump].fileofs;
+	
+	if (length % size)
+		Error ("LoadBSPFile: odd lump size");
+	
+	memcpy (dest, (byte *)header + ofs, length);
+
+	return length / size;
+}
+
+/*
+=============
+LoadBSPFile
+=============
+*/
+void	LoadBSPFile (char *filename)
+{
+	int			i;
+	
+//
+// load the file header
+//
+	LoadFile (filename, (void **)&header);
+
+// swap the header
+	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+	if (header->ident != IDBSPHEADER)
+		Error ("%s is not a IBSP file", filename);
+	if (header->version != BSPVERSION)
+		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
+
+	nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
+	numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
+	numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
+	numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
+	numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
+	numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
+	numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
+	numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]));
+	numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]));
+	numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
+	numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
+	numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t));
+	numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t));
+	numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t));
+	numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t));
+
+	visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
+	lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
+	entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
+
+	CopyLump (LUMP_POP, dpop, 1);
+
+	free (header);		// everything has been copied out
+		
+//
+// swap everything
+//	
+	SwapBSPFile (false);
+}
+
+
+/*
+=============
+LoadBSPFileTexinfo
+
+Only loads the texinfo lump, so qdata can scan for textures
+=============
+*/
+void	LoadBSPFileTexinfo (char *filename)
+{
+	int			i;
+	FILE		*f;
+	int		length, ofs;
+
+	header = malloc(sizeof(dheader_t));
+
+	f = fopen (filename, "rb");
+	fread (header, sizeof(dheader_t), 1, f);
+
+// swap the header
+	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+	if (header->ident != IDBSPHEADER)
+		Error ("%s is not a IBSP file", filename);
+	if (header->version != BSPVERSION)
+		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
+
+
+	length = header->lumps[LUMP_TEXINFO].filelen;
+	ofs = header->lumps[LUMP_TEXINFO].fileofs;
+
+	fseek (f, ofs, SEEK_SET);
+	fread (texinfo, length, 1, f);
+	fclose (f);
+
+	numtexinfo = length / sizeof(texinfo_t);
+
+	free (header);		// everything has been copied out
+		
+	SwapBSPFile (false);
+}
+
+
+//============================================================================
+
+FILE		*wadfile;
+dheader_t	outheader;
+
+void AddLump (int lumpnum, void *data, int len)
+{
+	lump_t *lump;
+
+	lump = &header->lumps[lumpnum];
+	
+	lump->fileofs = LittleLong( ftell(wadfile) );
+	lump->filelen = LittleLong(len);
+	SafeWrite (wadfile, data, (len+3)&~3);
+}
+
+/*
+=============
+WriteBSPFile
+
+Swaps the bsp file in place, so it should not be referenced again
+=============
+*/
+void	WriteBSPFile (char *filename)
+{		
+	header = &outheader;
+	memset (header, 0, sizeof(dheader_t));
+	
+	SwapBSPFile (true);
+
+	header->ident = LittleLong (IDBSPHEADER);
+	header->version = LittleLong (BSPVERSION);
+	
+	wadfile = SafeOpenWrite (filename);
+	SafeWrite (wadfile, header, sizeof(dheader_t));	// overwritten later
+
+	AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
+	AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
+	AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
+	AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
+	AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
+	AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
+	AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
+	AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
+	AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
+	AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
+	AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
+	AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
+	AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
+	AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
+	AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
+
+	AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
+	AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
+	AddLump (LUMP_ENTITIES, dentdata, entdatasize);
+	AddLump (LUMP_POP, dpop, sizeof(dpop));
+	
+	fseek (wadfile, 0, SEEK_SET);
+	SafeWrite (wadfile, header, sizeof(dheader_t));
+	fclose (wadfile);	
+}
+
+//============================================================================
+
+/*
+=============
+PrintBSPFileSizes
+
+Dumps info about current file
+=============
+*/
+void PrintBSPFileSizes (void)
+{
+	if (!num_entities)
+		ParseEntities ();
+
+	printf ("%5i models       %7i\n"
+		,nummodels, (int)(nummodels*sizeof(dmodel_t)));
+	printf ("%5i brushes      %7i\n"
+		,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
+	printf ("%5i brushsides   %7i\n"
+		,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
+	printf ("%5i planes       %7i\n"
+		,numplanes, (int)(numplanes*sizeof(dplane_t)));
+	printf ("%5i texinfo      %7i\n"
+		,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
+	printf ("%5i entdata      %7i\n", num_entities, entdatasize);
+
+	printf ("\n");
+
+	printf ("%5i vertexes     %7i\n"
+		,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
+	printf ("%5i nodes        %7i\n"
+		,numnodes, (int)(numnodes*sizeof(dnode_t)));
+	printf ("%5i faces        %7i\n"
+		,numfaces, (int)(numfaces*sizeof(dface_t)));
+	printf ("%5i leafs        %7i\n"
+		,numleafs, (int)(numleafs*sizeof(dleaf_t)));
+	printf ("%5i leaffaces    %7i\n"
+		,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
+	printf ("%5i leafbrushes  %7i\n"
+		,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
+	printf ("%5i surfedges    %7i\n"
+		,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
+	printf ("%5i edges        %7i\n"
+		,numedges, (int)(numedges*sizeof(dedge_t)));
+	printf ("      lightdata    %7i\n", lightdatasize);
+	printf ("      visdata      %7i\n", visdatasize);
+}
+
+
+//============================================
+
+int			num_entities;
+entity_t	entities[MAX_MAP_ENTITIES];
+
+void StripTrailing (char *e)
+{
+	char	*s;
+
+	s = e + strlen(e)-1;
+	while (s >= e && *s <= 32)
+	{
+		*s = 0;
+		s--;
+	}
+}
+
+/*
+=================
+ParseEpair
+=================
+*/
+epair_t *ParseEpair (void)
+{
+	epair_t	*e;
+
+	e = malloc (sizeof(epair_t));
+	memset (e, 0, sizeof(epair_t));
+	
+	if (strlen(token) >= MAX_KEY-1)
+		Error ("ParseEpar: token too long");
+	e->key = copystring(token);
+	GetToken (false);
+	if (strlen(token) >= MAX_VALUE-1)
+		Error ("ParseEpar: token too long");
+	e->value = copystring(token);
+
+	// strip trailing spaces
+	StripTrailing (e->key);
+	StripTrailing (e->value);
+
+	return e;
+}
+
+
+/*
+================
+ParseEntity
+================
+*/
+qboolean	ParseEntity (void)
+{
+	epair_t		*e;
+	entity_t	*mapent;
+
+	if (!GetToken (true))
+		return false;
+
+	if (strcmp (token, "{") )
+		Error ("ParseEntity: { not found");
+	
+	if (num_entities == MAX_MAP_ENTITIES)
+		Error ("num_entities == MAX_MAP_ENTITIES");
+
+	mapent = &entities[num_entities];
+	num_entities++;
+
+	do
+	{
+		if (!GetToken (true))
+			Error ("ParseEntity: EOF without closing brace");
+		if (!strcmp (token, "}") )
+			break;
+		e = ParseEpair ();
+		e->next = mapent->epairs;
+		mapent->epairs = e;
+	} while (1);
+	
+	return true;
+}
+
+/*
+================
+ParseEntities
+
+Parses the dentdata string into entities
+================
+*/
+void ParseEntities (void)
+{
+	num_entities = 0;
+	ParseFromMemory (dentdata, entdatasize);
+
+	while (ParseEntity ())
+	{
+	}	
+}
+
+
+/*
+================
+UnparseEntities
+
+Generates the dentdata string from all the entities
+================
+*/
+void UnparseEntities (void)
+{
+	char	*buf, *end;
+	epair_t	*ep;
+	char	line[2048];
+	int		i;
+	char	key[1024], value[1024];
+
+	buf = dentdata;
+	end = buf;
+	*end = 0;
+	
+	for (i=0 ; i<num_entities ; i++)
+	{
+		ep = entities[i].epairs;
+		if (!ep)
+			continue;	// ent got removed
+		
+		strcat (end,"{\n");
+		end += 2;
+				
+		for (ep = entities[i].epairs ; ep ; ep=ep->next)
+		{
+			strcpy (key, ep->key);
+			StripTrailing (key);
+			strcpy (value, ep->value);
+			StripTrailing (value);
+				
+			sprintf (line, "\"%s\" \"%s\"\n", key, value);
+			strcat (end, line);
+			end += strlen(line);
+		}
+		strcat (end,"}\n");
+		end += 2;
+
+		if (end > buf + MAX_MAP_ENTSTRING)
+			Error ("Entity text too long");
+	}
+	entdatasize = end - buf + 1;
+}
+
+void PrintEntity (entity_t *ent)
+{
+	epair_t	*ep;
+	
+	printf ("------- entity %p -------\n", ent);
+	for (ep=ent->epairs ; ep ; ep=ep->next)
+	{
+		printf ("%s = %s\n", ep->key, ep->value);
+	}
+
+}
+
+void 	SetKeyValue (entity_t *ent, char *key, char *value)
+{
+	epair_t	*ep;
+	
+	for (ep=ent->epairs ; ep ; ep=ep->next)
+		if (!strcmp (ep->key, key) )
+		{
+			free (ep->value);
+			ep->value = copystring(value);
+			return;
+		}
+	ep = malloc (sizeof(*ep));
+	ep->next = ent->epairs;
+	ent->epairs = ep;
+	ep->key = copystring(key);
+	ep->value = copystring(value);
+}
+
+char 	*ValueForKey (entity_t *ent, char *key)
+{
+	epair_t	*ep;
+	
+	for (ep=ent->epairs ; ep ; ep=ep->next)
+		if (!strcmp (ep->key, key) )
+			return ep->value;
+	return "";
+}
+
+vec_t	FloatForKey (entity_t *ent, char *key)
+{
+	char	*k;
+	
+	k = ValueForKey (ent, key);
+	return atof(k);
+}
+
+void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
+{
+	char	*k;
+	double	v1, v2, v3;
+
+	k = ValueForKey (ent, key);
+// scanf into doubles, then assign, so it is vec_t size independent
+	v1 = v2 = v3 = 0;
+	sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
+	vec[0] = v1;
+	vec[1] = v2;
+	vec[2] = v3;
+}
+
+
diff --git a/tools/quake2/common/bspfile.h b/tools/quake2/common/bspfile.h
index b4d6b355..f25329fb 100644
--- a/tools/quake2/common/bspfile.h
+++ b/tools/quake2/common/bspfile.h
@@ -1,128 +1,128 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qfiles.h"
-
-
-extern	int			nummodels;
-extern	dmodel_t	dmodels[MAX_MAP_MODELS];
-
-extern	int			visdatasize;
-extern	byte		dvisdata[MAX_MAP_VISIBILITY];
-extern	dvis_t		*dvis;
-
-extern	int			lightdatasize;
-extern	byte		dlightdata[MAX_MAP_LIGHTING];
-
-extern	int			entdatasize;
-extern	char		dentdata[MAX_MAP_ENTSTRING];
-
-extern	int			numleafs;
-extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
-
-extern	int			numplanes;
-extern	dplane_t	dplanes[MAX_MAP_PLANES];
-
-extern	int			numvertexes;
-extern	dvertex_t	dvertexes[MAX_MAP_VERTS];
-
-extern	int			numnodes;
-extern	dnode_t		dnodes[MAX_MAP_NODES];
-
-extern	int			numtexinfo;
-extern	texinfo_t	texinfo[MAX_MAP_TEXINFO];
-
-extern	int			numfaces;
-extern	dface_t		dfaces[MAX_MAP_FACES];
-
-extern	int			numedges;
-extern	dedge_t		dedges[MAX_MAP_EDGES];
-
-extern	int			numleaffaces;
-extern	unsigned short	dleaffaces[MAX_MAP_LEAFFACES];
-
-extern	int			numleafbrushes;
-extern	unsigned short	dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-extern	int			numsurfedges;
-extern	int			dsurfedges[MAX_MAP_SURFEDGES];
-
-extern	int			numareas;
-extern	darea_t		dareas[MAX_MAP_AREAS];
-
-extern	int			numareaportals;
-extern	dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
-
-extern	int			numbrushes;
-extern	dbrush_t	dbrushes[MAX_MAP_BRUSHES];
-
-extern	int			numbrushsides;
-extern	dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
-
-extern	byte		dpop[256];
-
-void DecompressVis (byte *in, byte *decompressed);
-int CompressVis (byte *vis, byte *dest);
-
-void	LoadBSPFile (char *filename);
-void	LoadBSPFileTexinfo (char *filename);	// just for qdata
-void	WriteBSPFile (char *filename);
-void	PrintBSPFileSizes (void);
-
-//===============
-
-
-typedef struct epair_s
-{
-	struct epair_s	*next;
-	char	*key;
-	char	*value;
-} epair_t;
-
-typedef struct
-{
-	vec3_t		origin;
-	int			firstbrush;
-	int			numbrushes;
-	epair_t		*epairs;
-
-// only valid for func_areaportals
-	int			areaportalnum;
-	int			portalareas[2];
-} entity_t;
-
-extern	int			num_entities;
-extern	entity_t	entities[MAX_MAP_ENTITIES];
-
-void	ParseEntities (void);
-void	UnparseEntities (void);
-
-void 	SetKeyValue (entity_t *ent, char *key, char *value);
-char 	*ValueForKey (entity_t *ent, char *key);
-// will return "" if not present
-
-vec_t	FloatForKey (entity_t *ent, char *key);
-void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
-
-epair_t *ParseEpair (void);
-
-void PrintEntity (entity_t *ent);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qfiles.h"
+
+
+extern	int			nummodels;
+extern	dmodel_t	dmodels[MAX_MAP_MODELS];
+
+extern	int			visdatasize;
+extern	byte		dvisdata[MAX_MAP_VISIBILITY];
+extern	dvis_t		*dvis;
+
+extern	int			lightdatasize;
+extern	byte		dlightdata[MAX_MAP_LIGHTING];
+
+extern	int			entdatasize;
+extern	char		dentdata[MAX_MAP_ENTSTRING];
+
+extern	int			numleafs;
+extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+extern	int			numplanes;
+extern	dplane_t	dplanes[MAX_MAP_PLANES];
+
+extern	int			numvertexes;
+extern	dvertex_t	dvertexes[MAX_MAP_VERTS];
+
+extern	int			numnodes;
+extern	dnode_t		dnodes[MAX_MAP_NODES];
+
+extern	int			numtexinfo;
+extern	texinfo_t	texinfo[MAX_MAP_TEXINFO];
+
+extern	int			numfaces;
+extern	dface_t		dfaces[MAX_MAP_FACES];
+
+extern	int			numedges;
+extern	dedge_t		dedges[MAX_MAP_EDGES];
+
+extern	int			numleaffaces;
+extern	unsigned short	dleaffaces[MAX_MAP_LEAFFACES];
+
+extern	int			numleafbrushes;
+extern	unsigned short	dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+extern	int			numsurfedges;
+extern	int			dsurfedges[MAX_MAP_SURFEDGES];
+
+extern	int			numareas;
+extern	darea_t		dareas[MAX_MAP_AREAS];
+
+extern	int			numareaportals;
+extern	dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
+
+extern	int			numbrushes;
+extern	dbrush_t	dbrushes[MAX_MAP_BRUSHES];
+
+extern	int			numbrushsides;
+extern	dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
+
+extern	byte		dpop[256];
+
+void DecompressVis (byte *in, byte *decompressed);
+int CompressVis (byte *vis, byte *dest);
+
+void	LoadBSPFile (char *filename);
+void	LoadBSPFileTexinfo (char *filename);	// just for qdata
+void	WriteBSPFile (char *filename);
+void	PrintBSPFileSizes (void);
+
+//===============
+
+
+typedef struct epair_s
+{
+	struct epair_s	*next;
+	char	*key;
+	char	*value;
+} epair_t;
+
+typedef struct
+{
+	vec3_t		origin;
+	int			firstbrush;
+	int			numbrushes;
+	epair_t		*epairs;
+
+// only valid for func_areaportals
+	int			areaportalnum;
+	int			portalareas[2];
+} entity_t;
+
+extern	int			num_entities;
+extern	entity_t	entities[MAX_MAP_ENTITIES];
+
+void	ParseEntities (void);
+void	UnparseEntities (void);
+
+void 	SetKeyValue (entity_t *ent, char *key, char *value);
+char 	*ValueForKey (entity_t *ent, char *key);
+// will return "" if not present
+
+vec_t	FloatForKey (entity_t *ent, char *key);
+void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
+
+epair_t *ParseEpair (void);
+
+void PrintEntity (entity_t *ent);
+
diff --git a/tools/quake2/common/cmdlib.c b/tools/quake2/common/cmdlib.c
index 6a005e32..68a16d82 100644
--- a/tools/quake2/common/cmdlib.c
+++ b/tools/quake2/common/cmdlib.c
@@ -1,1221 +1,1221 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// Nurail: Swiped from quake3/common
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <windows.h>
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-#include <unistd.h>
-#endif
-
-#ifdef NeXT
-#include <libc.h>
-#endif
-
-#define	BASEDIRNAME	"quake"		// assumed to have a 2 or 3 following
-#define HERETIC2_BASEDIRNAME	"h"
-#define PATHSEPERATOR   '/'
-
-// qboolean verbose = false;
-
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size )
-{
-  void *p;
-
-  p = malloc(size);
-  if(!p)
-    Error ("safe_malloc failed on allocation of %i bytes", size);
-
-  memset(p, 0, size);
-  return p;
-}
-
-void *safe_malloc_info( size_t size, char* info )
-{
-  void *p;
-
-  p = malloc(size);
-  if(!p)
-    Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
-
-  memset(p, 0, size);
-  return p;
-}
-#endif
-
-// set these before calling CheckParm
-int myargc;
-char **myargv;
-
-char		com_token[1024];
-qboolean	com_eof;
-
-qboolean		archive;
-char			archivedir[1024];
-
-
-/*
-===================
-ExpandWildcards
-
-Mimic unix command line expansion
-===================
-*/
-#define	MAX_EX_ARGC	1024
-int		ex_argc;
-char	*ex_argv[MAX_EX_ARGC];
-#ifdef _WIN32
-#include "io.h"
-void ExpandWildcards( int *argc, char ***argv )
-{
-	struct _finddata_t fileinfo;
-	int		handle;
-	int		i;
-	char	filename[1024];
-	char	filebase[1024];
-	char	*path;
-
-	ex_argc = 0;
-	for (i=0 ; i<*argc ; i++)
-	{
-		path = (*argv)[i];
-		if ( path[0] == '-'
-			|| ( !strstr(path, "*") && !strstr(path, "?") ) )
-		{
-			ex_argv[ex_argc++] = path;
-			continue;
-		}
-
-		handle = _findfirst (path, &fileinfo);
-		if (handle == -1)
-			return;
-
-		ExtractFilePath (path, filebase);
-
-		do
-		{
-			sprintf (filename, "%s%s", filebase, fileinfo.name);
-			ex_argv[ex_argc++] = copystring (filename);
-		} while (_findnext( handle, &fileinfo ) != -1);
-
-		_findclose (handle);
-	}
-
-	*argc = ex_argc;
-	*argv = ex_argv;
-}
-#else
-void ExpandWildcards (int *argc, char ***argv)
-{
-}
-#endif
-
-/*
-
-qdir will hold the path up to the quake directory, including the slash
-
-  f:\quake\
-  /raid/quake/
-
-gamedir will hold qdir + the game directory (id1, id2, etc)
-
-*/
-
-char		qdir[1024];
-char		gamedir[1024];
-char		writedir[1024];
-
-void SetQdirFromPath( const char *path )
-{
-	char	temp[1024];
-	const char	*c;
-  const char *sep;
-	int		len, count;
-	char	basedirname[256];
-
-	if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
-	{	// path is partial
-		Q_getwd (temp);
-		strcat (temp, path);
-		path = temp;
-	}
-
-	// search for "quake2" in path
-
-	if ( !strcmp( game, "heretic2" ) )
-		strncpy(basedirname, HERETIC2_BASEDIRNAME, 256);
-	else
-		strncpy(basedirname, BASEDIRNAME, 256);
-	
-	len = strlen(basedirname);
-	for (c=path+strlen(path)-1 ; c != path ; c--)
-	{
-		int i;
-
-		if (!Q_strncasecmp (c, basedirname, len))
-		{
-      //
-			//strncpy (qdir, path, c+len+2-path);
-      // the +2 assumes a 2 or 3 following quake which is not the
-      // case with a retail install
-      // so we need to add up how much to the next separator
-      sep = c + len;
-      count = 1;
-      while (*sep && *sep != '/' && *sep != '\\')
-      {
-        sep++;
-        count++;
-      }
-			strncpy (qdir, path, c+len+count-path);
-			Sys_FPrintf( SYS_VRB, "qdir: %s\n", qdir);
-			for ( i = 0; i < strlen( qdir ); i++ )
-			{
-				if ( qdir[i] == '\\' ) 
-					qdir[i] = '/';
-			}
-
-			c += len+count;
-			while (*c)
-			{
-				if (*c == '/' || *c == '\\')
-				{
-					strncpy (gamedir, path, c+1-path);
-
-					for ( i = 0; i < strlen( gamedir ); i++ )
-					{
-						if ( gamedir[i] == '\\' ) 
-							gamedir[i] = '/';
-					}
-
-					Sys_FPrintf( SYS_VRB, "gamedir: %s\n", gamedir);
-
-					if ( !writedir[0] )
-						strcpy( writedir, gamedir );
-					else if ( writedir[strlen( writedir )-1] != '/' )
-					{
-						writedir[strlen( writedir )] = '/';
-						writedir[strlen( writedir )+1] = 0;
-					}
-
-					return;
-				}
-				c++;
-			}
-			Error ("No gamedir in %s", path);
-			return;
-		}
-	}
-	Error ("SetQdirFromPath: no '%s' in %s", basedirname, path);
-}
-
-char *ExpandArg (const char *path)
-{
-	static char full[1024];
-
-	if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
-	{
-		Q_getwd (full);
-		strcat (full, path);
-	}
-	else
-		strcpy (full, path);
-	return full;
-}
-
-char *ExpandPath (const char *path)
-{
-	static char full[1024];
-	if (!qdir)
-		Error ("ExpandPath called without qdir set");
-	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
-		strcpy( full, path );
-		return full;
-	}
-	sprintf (full, "%s%s", qdir, path);
-	return full;
-}
-
-char *ExpandGamePath (const char *path)
-{
-	static char full[1024];
-	if (!qdir)
-		Error ("ExpandGamePath called without qdir set");
-	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
-		strcpy( full, path );
-		return full;
-	}
-	sprintf (full, "%s%s", gamedir, path);
-	return full;
-}
-
-char *ExpandPathAndArchive (const char *path)
-{
-	char	*expanded;
-	char	archivename[1024];
-
-	expanded = ExpandPath (path);
-
-	if (archive)
-	{
-		sprintf (archivename, "%s/%s", archivedir, path);
-		QCopyFile (expanded, archivename);
-	}
-	return expanded;
-}
-
-
-char *copystring(const char *s)
-{
-	char	*b;
-	b = safe_malloc(strlen(s)+1);
-	strcpy (b, s);
-	return b;
-}
-
-
-
-/*
-================
-I_FloatTime
-================
-*/
-double I_FloatTime (void)
-{
-	time_t	t;
-	
-	time (&t);
-	
-	return t;
-#if 0
-// more precise, less portable
-	struct timeval tp;
-	struct timezone tzp;
-	static int		secbase;
-
-	gettimeofday(&tp, &tzp);
-	
-	if (!secbase)
-	{
-		secbase = tp.tv_sec;
-		return tp.tv_usec/1000000.0;
-	}
-	
-	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
-#endif
-}
-
-void Q_getwd (char *out)
-{
-	int i = 0;
-
-#ifdef _WIN32
-   _getcwd (out, 256);
-   strcat (out, "\\");
-#else
-   // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
-   getcwd (out, 256);
-   strcat (out, "/");
-#endif
-   while ( out[i] != 0 )
-   {
-	   if ( out[i] == '\\' )
-		   out[i] = '/';
-	   i++;
-   }
-}
-
-
-void Q_mkdir (const char *path)
-{
-#ifdef _WIN32
-	if (_mkdir (path) != -1)
-		return;
-#else
-	if (mkdir (path, 0777) != -1)
-		return;
-#endif
-	if (errno != EEXIST)
-		Error ("mkdir %s: %s",path, strerror(errno));
-}
-
-/*
-============
-FileTime
-
-returns -1 if not present
-============
-*/
-int	FileTime (const char *path)
-{
-	struct	stat	buf;
-	
-	if (stat (path,&buf) == -1)
-		return -1;
-	
-	return buf.st_mtime;
-}
-
-
-
-/*
-==============
-COM_Parse
-
-Parse a token out of a string
-==============
-*/
-char *COM_Parse (char *data)
-{
-	int		c;
-	int		len;
-	
-	len = 0;
-	com_token[0] = 0;
-	
-	if (!data)
-		return NULL;
-		
-// skip whitespace
-skipwhite:
-	while ( (c = *data) <= ' ')
-	{
-		if (c == 0)
-		{
-			com_eof = true;
-			return NULL;			// end of file;
-		}
-		data++;
-	}
-	
-// skip // comments
-	if (c=='/' && data[1] == '/')
-	{
-		while (*data && *data != '\n')
-			data++;
-		goto skipwhite;
-	}
-	
-
-// handle quoted strings specially
-	if (c == '\"')
-	{
-		data++;
-		do
-		{
-			c = *data++;
-			if (c=='\"')
-			{
-				com_token[len] = 0;
-				return data;
-			}
-			com_token[len] = c;
-			len++;
-		} while (1);
-	}
-
-// parse single characters
-	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
-	{
-		com_token[len] = c;
-		len++;
-		com_token[len] = 0;
-		return data+1;
-	}
-
-// parse a regular word
-	do
-	{
-		com_token[len] = c;
-		data++;
-		len++;
-		c = *data;
-	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
-			break;
-	} while (c>32);
-	
-	com_token[len] = 0;
-	return data;
-}
-
-int Q_strncasecmp (const char *s1, const char *s2, int n)
-{
-	int		c1, c2;
-	
-	do
-	{
-		c1 = *s1++;
-		c2 = *s2++;
-
-		if (!n--)
-			return 0;		// strings are equal until end point
-		
-		if (c1 != c2)
-		{
-			if (c1 >= 'a' && c1 <= 'z')
-				c1 -= ('a' - 'A');
-			if (c2 >= 'a' && c2 <= 'z')
-				c2 -= ('a' - 'A');
-			if (c1 != c2)
-				return -1;		// strings not equal
-		}
-	} while (c1);
-	
-	return 0;		// strings are equal
-}
-
-int Q_stricmp (const char *s1, const char *s2)
-{
-	return Q_strncasecmp (s1, s2, 99999);
-}
-
-int Q_strcasecmp (const char *s1, const char *s2)
-{
-	return Q_strncasecmp (s1, s2, 99999);
-}
-
-
-// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
-//   started getting warnings about that function, prolly a duplicate with the runtime function
-//   maybe we still need to have it in linux builds
-/*
-char *strupr (char *start)
-{
-	char	*in;
-	in = start;
-	while (*in)
-	{
-		*in = toupper(*in);
-		in++;
-	}
-	return start;
-}
-*/
-
-char *strlower (char *start)
-{
-	char	*in;
-	in = start;
-	while (*in)
-	{
-		*in = tolower(*in); 
-		in++;
-	}
-	return start;
-}
-
-
-/*
-=============================================================================
-
-						MISC FUNCTIONS
-
-=============================================================================
-*/
-
-
-/*
-=================
-CheckParm
-
-Checks for the given parameter in the program's command line arguments
-Returns the argument number (1 to argc-1) or 0 if not present
-=================
-*/
-int CheckParm (const char *check)
-{
-	int             i;
-
-	for (i = 1;i<myargc;i++)
-	{
-		if ( !Q_stricmp(check, myargv[i]) )
-			return i;
-	}
-
-	return 0;
-}
-
-
-
-/*
-================
-Q_filelength
-================
-*/
-int Q_filelength (FILE *f)
-{
-	int		pos;
-	int		end;
-
-	pos = ftell (f);
-	fseek (f, 0, SEEK_END);
-	end = ftell (f);
-	fseek (f, pos, SEEK_SET);
-
-	return end;
-}
-
-
-FILE *SafeOpenWrite (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen(filename, "wb");
-
-	if (!f)
-		Error ("Error opening %s: %s",filename,strerror(errno));
-
-	return f;
-}
-
-FILE *SafeOpenRead (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen(filename, "rb");
-
-	if (!f)
-		Error ("Error opening %s: %s",filename,strerror(errno));
-
-	return f;
-}
-
-
-void SafeRead (FILE *f, void *buffer, int count)
-{
-	if ( fread (buffer, 1, count, f) != (size_t)count)
-		Error ("File read failure");
-}
-
-
-void SafeWrite (FILE *f, const void *buffer, int count)
-{
-	if (fwrite (buffer, 1, count, f) != (size_t)count)
-		Error ("File write failure");
-}
-
-
-/*
-==============
-FileExists
-==============
-*/
-qboolean	FileExists (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen (filename, "r");
-	if (!f)
-		return false;
-	fclose (f);
-	return true;
-}
-
-/*
-==============
-LoadFile
-==============
-*/
-int    LoadFile( const char *filename, void **bufferptr )
-{
-	FILE	*f;
-	int    length;
-	void    *buffer;
-
-	f = SafeOpenRead (filename);
-	length = Q_filelength (f);
-	buffer = safe_malloc (length+1);
-	((char *)buffer)[length] = 0;
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-LoadFileBlock
--
-rounds up memory allocation to 4K boundry
--
-==============
-*/
-int    LoadFileBlock( const char *filename, void **bufferptr )
-{
-	FILE	*f;
-	int    length, nBlock, nAllocSize;
-	void    *buffer;
-
-	f = SafeOpenRead (filename);
-	length = Q_filelength (f);
-  nAllocSize = length;
-  nBlock = nAllocSize % MEM_BLOCKSIZE;
-  if ( nBlock > 0) {
-    nAllocSize += MEM_BLOCKSIZE - nBlock;
-  }
-	buffer = safe_malloc (nAllocSize+1);
-  memset(buffer, 0, nAllocSize+1);
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-TryLoadFile
-
-Allows failure
-==============
-*/
-int    TryLoadFile (const char *filename, void **bufferptr)
-{
-	FILE	*f;
-	int    length;
-	void    *buffer;
-
-	*bufferptr = NULL;
-
-	f = fopen (filename, "rb");
-	if (!f)
-		return -1;
-	length = Q_filelength (f);
-	buffer = safe_malloc (length+1);
-	((char *)buffer)[length] = 0;
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-SaveFile
-==============
-*/
-void    SaveFile (const char *filename, const void *buffer, int count)
-{
-	FILE	*f;
-
-	f = SafeOpenWrite (filename);
-	SafeWrite (f, buffer, count);
-	fclose (f);
-}
-
-
-
-void DefaultExtension (char *path, const char *extension)
-{
-	char    *src;
-//
-// if path doesnt have a .EXT, append extension
-// (extension should include the .)
-//
-	src = path + strlen(path) - 1;
-
-	while (*src != '/' && *src != '\\' && src != path)
-	{
-		if (*src == '.')
-			return;                 // it has an extension
-		src--;
-	}
-
-	strcat (path, extension);
-}
-
-
-void DefaultPath (char *path, const char *basepath)
-{
-	char    temp[128];
-
-	if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
-		return;                   // absolute path location
-	strcpy (temp,path);
-	strcpy (path,basepath);
-	strcat (path,temp);
-}
-
-
-void    StripFilename (char *path)
-{
-	int             length;
-
-	length = strlen(path)-1;
-	while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
-		length--;
-	path[length] = 0;
-}
-
-void    StripExtension (char *path)
-{
-	int             length;
-
-	length = strlen(path)-1;
-	while (length > 0 && path[length] != '.')
-	{
-		length--;
-		if (path[length] == '/' || path[ length ] == '\\' )
-			return;		// no extension
-	}
-	if (length)
-		path[length] = 0;
-}
-
-
-/*
-====================
-Extract file parts
-====================
-*/
-// FIXME: should include the slash, otherwise
-// backing to an empty path will be wrong when appending a slash
-void ExtractFilePath (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
-	while (src != path && *(src-1) != '\\' && *(src-1) != '/')
-		src--;
-
-	memcpy (dest, path, src-path);
-	dest[src-path] = 0;
-}
-
-void ExtractFileBase (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
-	while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
-		src--;
-
-	while (*src && *src != '.')
-	{
-		*dest++ = *src++;
-	}
-	*dest = 0;
-}
-
-void ExtractFileExtension (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a . or the start
-//
-	while (src != path && *(src-1) != '.')
-		src--;
-	if (src == path)
-	{
-		*dest = 0;	// no extension
-		return;
-	}
-
-	strcpy (dest,src);
-}
-
-
-/*
-==============
-ParseNum / ParseHex
-==============
-*/
-int ParseHex (const char *hex)
-{
-	const char    *str;
-	int    num;
-
-	num = 0;
-	str = hex;
-
-	while (*str)
-	{
-		num <<= 4;
-		if (*str >= '0' && *str <= '9')
-			num += *str-'0';
-		else if (*str >= 'a' && *str <= 'f')
-			num += 10 + *str-'a';
-		else if (*str >= 'A' && *str <= 'F')
-			num += 10 + *str-'A';
-		else
-			Error ("Bad hex number: %s",hex);
-		str++;
-	}
-
-	return num;
-}
-
-
-int ParseNum (const char *str)
-{
-	if (str[0] == '$')
-		return ParseHex (str+1);
-	if (str[0] == '0' && str[1] == 'x')
-		return ParseHex (str+2);
-	return atol (str);
-}
-/*
-// all output ends up through here
-void FPrintf (int flag, char *buf)
-{
-  printf(buf);
-
-}
-
-void Sys_FPrintf (int flag, const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-
-  if ((flag == SYS_VRB) && (verbose == false))
-    return;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-
-  FPrintf (flag, out_buffer);
-}
-
-void Sys_Printf (const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-
-  FPrintf (SYS_STD, out_buffer);
-}
-
-
-//=================
-//Error
-//
-//For abnormal program terminations
-//=================
-
-void Error( const char *error, ...)
-{
-  char out_buffer[4096];
-  char tmp[4096];
-	va_list argptr;
-
-	va_start (argptr,error);
-	vsprintf (tmp, error, argptr);
-	va_end (argptr);
-
-  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
-
-  FPrintf( SYS_ERR, out_buffer );
-
-	exit (1);
-}
-*/
-
-
-/*
-============================================================================
-
-					BYTE ORDER FUNCTIONS
-
-============================================================================
-*/
-
-#ifdef _SGI_SOURCE
-#define	__BIG_ENDIAN__
-#endif
-
-#ifdef __BIG_ENDIAN__
-
-short   LittleShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   BigShort (short l)
-{
-	return l;
-}
-
-
-int    LittleLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    BigLong (int l)
-{
-	return l;
-}
-
-
-float	LittleFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	BigFloat (float l)
-{
-	return l;
-}
-
-
-#else
-
-
-short   BigShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   LittleShort (short l)
-{
-	return l;
-}
-
-
-int    BigLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    LittleLong (int l)
-{
-	return l;
-}
-
-float	BigFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	LittleFloat (float l)
-{
-	return l;
-}
-
-
-#endif
-
-
-//=======================================================
-
-
-// FIXME: byte swap?
-
-// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
-// and the initial and final xor values shown below...  in other words, the
-// CCITT standard CRC used by XMODEM
-
-#define CRC_INIT_VALUE	0xffff
-#define CRC_XOR_VALUE	0x0000
-
-static unsigned short crctable[256] =
-{
-	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
-	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
-	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
-	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
-	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
-	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
-	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
-	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
-	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
-	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
-	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
-	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
-	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
-	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
-	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
-	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
-	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
-	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
-	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
-	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
-	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
-	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
-	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
-	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
-	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
-	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
-	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
-	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
-	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
-	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
-	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
-	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
-};
-
-void CRC_Init(unsigned short *crcvalue)
-{
-	*crcvalue = CRC_INIT_VALUE;
-}
-
-void CRC_ProcessByte(unsigned short *crcvalue, byte data)
-{
-	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
-}
-
-unsigned short CRC_Value(unsigned short crcvalue)
-{
-	return crcvalue ^ CRC_XOR_VALUE;
-}
-//=============================================================================
-
-/*
-============
-CreatePath
-============
-*/
-void	CreatePath (const char *path)
-{
-	const char	*ofs;
-	char		c;
-	char		dir[1024];
-
-#ifdef _WIN32
-	int		olddrive = -1;
-
-	if ( path[1] == ':' )
-	{
-		olddrive = _getdrive();
-		_chdrive( toupper( path[0] ) - 'A' + 1 );
-	}
-#endif
-
-	if (path[1] == ':')
-		path += 2;
-
-	for (ofs = path+1 ; *ofs ; ofs++)
-	{
-		c = *ofs;
-		if (c == '/' || c == '\\')
-		{	// create the directory
-			memcpy( dir, path, ofs - path );
-			dir[ ofs - path ] = 0;
-			Q_mkdir( dir );
-		}
-	}
-
-#ifdef _WIN32
-	if ( olddrive != -1 )
-	{
-		_chdrive( olddrive );
-	}
-#endif
-}
-
-
-/*
-============
-QCopyFile
-
-  Used to archive source files
-============
-*/
-void QCopyFile (const char *from, const char *to)
-{
-	void	*buffer;
-	int		length;
-
-	length = LoadFile (from, &buffer);
-	CreatePath (to);
-	SaveFile (to, buffer, length);
-	free (buffer);
-}
-
-void Sys_Sleep(int n)
-{
-#ifdef _WIN32
-  Sleep (n);
-#endif
-#if defined (__linux__) || defined (__APPLE__)
-  usleep (n * 1000);
-#endif
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Nurail: Swiped from quake3/common
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+#include <unistd.h>
+#endif
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+
+#define	BASEDIRNAME	"quake"		// assumed to have a 2 or 3 following
+#define HERETIC2_BASEDIRNAME	"h"
+#define PATHSEPERATOR   '/'
+
+// qboolean verbose = false;
+
+#ifdef SAFE_MALLOC
+void *safe_malloc( size_t size )
+{
+  void *p;
+
+  p = malloc(size);
+  if(!p)
+    Error ("safe_malloc failed on allocation of %i bytes", size);
+
+  memset(p, 0, size);
+  return p;
+}
+
+void *safe_malloc_info( size_t size, char* info )
+{
+  void *p;
+
+  p = malloc(size);
+  if(!p)
+    Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
+
+  memset(p, 0, size);
+  return p;
+}
+#endif
+
+// set these before calling CheckParm
+int myargc;
+char **myargv;
+
+char		com_token[1024];
+qboolean	com_eof;
+
+qboolean		archive;
+char			archivedir[1024];
+
+
+/*
+===================
+ExpandWildcards
+
+Mimic unix command line expansion
+===================
+*/
+#define	MAX_EX_ARGC	1024
+int		ex_argc;
+char	*ex_argv[MAX_EX_ARGC];
+#ifdef _WIN32
+#include "io.h"
+void ExpandWildcards( int *argc, char ***argv )
+{
+	struct _finddata_t fileinfo;
+	int		handle;
+	int		i;
+	char	filename[1024];
+	char	filebase[1024];
+	char	*path;
+
+	ex_argc = 0;
+	for (i=0 ; i<*argc ; i++)
+	{
+		path = (*argv)[i];
+		if ( path[0] == '-'
+			|| ( !strstr(path, "*") && !strstr(path, "?") ) )
+		{
+			ex_argv[ex_argc++] = path;
+			continue;
+		}
+
+		handle = _findfirst (path, &fileinfo);
+		if (handle == -1)
+			return;
+
+		ExtractFilePath (path, filebase);
+
+		do
+		{
+			sprintf (filename, "%s%s", filebase, fileinfo.name);
+			ex_argv[ex_argc++] = copystring (filename);
+		} while (_findnext( handle, &fileinfo ) != -1);
+
+		_findclose (handle);
+	}
+
+	*argc = ex_argc;
+	*argv = ex_argv;
+}
+#else
+void ExpandWildcards (int *argc, char ***argv)
+{
+}
+#endif
+
+/*
+
+qdir will hold the path up to the quake directory, including the slash
+
+  f:\quake\
+  /raid/quake/
+
+gamedir will hold qdir + the game directory (id1, id2, etc)
+
+*/
+
+char		qdir[1024];
+char		gamedir[1024];
+char		writedir[1024];
+
+void SetQdirFromPath( const char *path )
+{
+	char	temp[1024];
+	const char	*c;
+  const char *sep;
+	int		len, count;
+	char	basedirname[256];
+
+	if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
+	{	// path is partial
+		Q_getwd (temp);
+		strcat (temp, path);
+		path = temp;
+	}
+
+	// search for "quake2" in path
+
+	if ( !strcmp( game, "heretic2" ) )
+		strncpy(basedirname, HERETIC2_BASEDIRNAME, 256);
+	else
+		strncpy(basedirname, BASEDIRNAME, 256);
+	
+	len = strlen(basedirname);
+	for (c=path+strlen(path)-1 ; c != path ; c--)
+	{
+		int i;
+
+		if (!Q_strncasecmp (c, basedirname, len))
+		{
+      //
+			//strncpy (qdir, path, c+len+2-path);
+      // the +2 assumes a 2 or 3 following quake which is not the
+      // case with a retail install
+      // so we need to add up how much to the next separator
+      sep = c + len;
+      count = 1;
+      while (*sep && *sep != '/' && *sep != '\\')
+      {
+        sep++;
+        count++;
+      }
+			strncpy (qdir, path, c+len+count-path);
+			Sys_FPrintf( SYS_VRB, "qdir: %s\n", qdir);
+			for ( i = 0; i < strlen( qdir ); i++ )
+			{
+				if ( qdir[i] == '\\' ) 
+					qdir[i] = '/';
+			}
+
+			c += len+count;
+			while (*c)
+			{
+				if (*c == '/' || *c == '\\')
+				{
+					strncpy (gamedir, path, c+1-path);
+
+					for ( i = 0; i < strlen( gamedir ); i++ )
+					{
+						if ( gamedir[i] == '\\' ) 
+							gamedir[i] = '/';
+					}
+
+					Sys_FPrintf( SYS_VRB, "gamedir: %s\n", gamedir);
+
+					if ( !writedir[0] )
+						strcpy( writedir, gamedir );
+					else if ( writedir[strlen( writedir )-1] != '/' )
+					{
+						writedir[strlen( writedir )] = '/';
+						writedir[strlen( writedir )+1] = 0;
+					}
+
+					return;
+				}
+				c++;
+			}
+			Error ("No gamedir in %s", path);
+			return;
+		}
+	}
+	Error ("SetQdirFromPath: no '%s' in %s", basedirname, path);
+}
+
+char *ExpandArg (const char *path)
+{
+	static char full[1024];
+
+	if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
+	{
+		Q_getwd (full);
+		strcat (full, path);
+	}
+	else
+		strcpy (full, path);
+	return full;
+}
+
+char *ExpandPath (const char *path)
+{
+	static char full[1024];
+	if (!qdir)
+		Error ("ExpandPath called without qdir set");
+	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+		strcpy( full, path );
+		return full;
+	}
+	sprintf (full, "%s%s", qdir, path);
+	return full;
+}
+
+char *ExpandGamePath (const char *path)
+{
+	static char full[1024];
+	if (!qdir)
+		Error ("ExpandGamePath called without qdir set");
+	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+		strcpy( full, path );
+		return full;
+	}
+	sprintf (full, "%s%s", gamedir, path);
+	return full;
+}
+
+char *ExpandPathAndArchive (const char *path)
+{
+	char	*expanded;
+	char	archivename[1024];
+
+	expanded = ExpandPath (path);
+
+	if (archive)
+	{
+		sprintf (archivename, "%s/%s", archivedir, path);
+		QCopyFile (expanded, archivename);
+	}
+	return expanded;
+}
+
+
+char *copystring(const char *s)
+{
+	char	*b;
+	b = safe_malloc(strlen(s)+1);
+	strcpy (b, s);
+	return b;
+}
+
+
+
+/*
+================
+I_FloatTime
+================
+*/
+double I_FloatTime (void)
+{
+	time_t	t;
+	
+	time (&t);
+	
+	return t;
+#if 0
+// more precise, less portable
+	struct timeval tp;
+	struct timezone tzp;
+	static int		secbase;
+
+	gettimeofday(&tp, &tzp);
+	
+	if (!secbase)
+	{
+		secbase = tp.tv_sec;
+		return tp.tv_usec/1000000.0;
+	}
+	
+	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
+#endif
+}
+
+void Q_getwd (char *out)
+{
+	int i = 0;
+
+#ifdef _WIN32
+   _getcwd (out, 256);
+   strcat (out, "\\");
+#else
+   // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
+   getcwd (out, 256);
+   strcat (out, "/");
+#endif
+   while ( out[i] != 0 )
+   {
+	   if ( out[i] == '\\' )
+		   out[i] = '/';
+	   i++;
+   }
+}
+
+
+void Q_mkdir (const char *path)
+{
+#ifdef _WIN32
+	if (_mkdir (path) != -1)
+		return;
+#else
+	if (mkdir (path, 0777) != -1)
+		return;
+#endif
+	if (errno != EEXIST)
+		Error ("mkdir %s: %s",path, strerror(errno));
+}
+
+/*
+============
+FileTime
+
+returns -1 if not present
+============
+*/
+int	FileTime (const char *path)
+{
+	struct	stat	buf;
+	
+	if (stat (path,&buf) == -1)
+		return -1;
+	
+	return buf.st_mtime;
+}
+
+
+
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+	int		c;
+	int		len;
+	
+	len = 0;
+	com_token[0] = 0;
+	
+	if (!data)
+		return NULL;
+		
+// skip whitespace
+skipwhite:
+	while ( (c = *data) <= ' ')
+	{
+		if (c == 0)
+		{
+			com_eof = true;
+			return NULL;			// end of file;
+		}
+		data++;
+	}
+	
+// skip // comments
+	if (c=='/' && data[1] == '/')
+	{
+		while (*data && *data != '\n')
+			data++;
+		goto skipwhite;
+	}
+	
+
+// handle quoted strings specially
+	if (c == '\"')
+	{
+		data++;
+		do
+		{
+			c = *data++;
+			if (c=='\"')
+			{
+				com_token[len] = 0;
+				return data;
+			}
+			com_token[len] = c;
+			len++;
+		} while (1);
+	}
+
+// parse single characters
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+	{
+		com_token[len] = c;
+		len++;
+		com_token[len] = 0;
+		return data+1;
+	}
+
+// parse a regular word
+	do
+	{
+		com_token[len] = c;
+		data++;
+		len++;
+		c = *data;
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+			break;
+	} while (c>32);
+	
+	com_token[len] = 0;
+	return data;
+}
+
+int Q_strncasecmp (const char *s1, const char *s2, int n)
+{
+	int		c1, c2;
+	
+	do
+	{
+		c1 = *s1++;
+		c2 = *s2++;
+
+		if (!n--)
+			return 0;		// strings are equal until end point
+		
+		if (c1 != c2)
+		{
+			if (c1 >= 'a' && c1 <= 'z')
+				c1 -= ('a' - 'A');
+			if (c2 >= 'a' && c2 <= 'z')
+				c2 -= ('a' - 'A');
+			if (c1 != c2)
+				return -1;		// strings not equal
+		}
+	} while (c1);
+	
+	return 0;		// strings are equal
+}
+
+int Q_stricmp (const char *s1, const char *s2)
+{
+	return Q_strncasecmp (s1, s2, 99999);
+}
+
+int Q_strcasecmp (const char *s1, const char *s2)
+{
+	return Q_strncasecmp (s1, s2, 99999);
+}
+
+
+// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
+//   started getting warnings about that function, prolly a duplicate with the runtime function
+//   maybe we still need to have it in linux builds
+/*
+char *strupr (char *start)
+{
+	char	*in;
+	in = start;
+	while (*in)
+	{
+		*in = toupper(*in);
+		in++;
+	}
+	return start;
+}
+*/
+
+char *strlower (char *start)
+{
+	char	*in;
+	in = start;
+	while (*in)
+	{
+		*in = tolower(*in); 
+		in++;
+	}
+	return start;
+}
+
+
+/*
+=============================================================================
+
+						MISC FUNCTIONS
+
+=============================================================================
+*/
+
+
+/*
+=================
+CheckParm
+
+Checks for the given parameter in the program's command line arguments
+Returns the argument number (1 to argc-1) or 0 if not present
+=================
+*/
+int CheckParm (const char *check)
+{
+	int             i;
+
+	for (i = 1;i<myargc;i++)
+	{
+		if ( !Q_stricmp(check, myargv[i]) )
+			return i;
+	}
+
+	return 0;
+}
+
+
+
+/*
+================
+Q_filelength
+================
+*/
+int Q_filelength (FILE *f)
+{
+	int		pos;
+	int		end;
+
+	pos = ftell (f);
+	fseek (f, 0, SEEK_END);
+	end = ftell (f);
+	fseek (f, pos, SEEK_SET);
+
+	return end;
+}
+
+
+FILE *SafeOpenWrite (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen(filename, "wb");
+
+	if (!f)
+		Error ("Error opening %s: %s",filename,strerror(errno));
+
+	return f;
+}
+
+FILE *SafeOpenRead (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen(filename, "rb");
+
+	if (!f)
+		Error ("Error opening %s: %s",filename,strerror(errno));
+
+	return f;
+}
+
+
+void SafeRead (FILE *f, void *buffer, int count)
+{
+	if ( fread (buffer, 1, count, f) != (size_t)count)
+		Error ("File read failure");
+}
+
+
+void SafeWrite (FILE *f, const void *buffer, int count)
+{
+	if (fwrite (buffer, 1, count, f) != (size_t)count)
+		Error ("File write failure");
+}
+
+
+/*
+==============
+FileExists
+==============
+*/
+qboolean	FileExists (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen (filename, "r");
+	if (!f)
+		return false;
+	fclose (f);
+	return true;
+}
+
+/*
+==============
+LoadFile
+==============
+*/
+int    LoadFile( const char *filename, void **bufferptr )
+{
+	FILE	*f;
+	int    length;
+	void    *buffer;
+
+	f = SafeOpenRead (filename);
+	length = Q_filelength (f);
+	buffer = safe_malloc (length+1);
+	((char *)buffer)[length] = 0;
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+LoadFileBlock
+-
+rounds up memory allocation to 4K boundry
+-
+==============
+*/
+int    LoadFileBlock( const char *filename, void **bufferptr )
+{
+	FILE	*f;
+	int    length, nBlock, nAllocSize;
+	void    *buffer;
+
+	f = SafeOpenRead (filename);
+	length = Q_filelength (f);
+  nAllocSize = length;
+  nBlock = nAllocSize % MEM_BLOCKSIZE;
+  if ( nBlock > 0) {
+    nAllocSize += MEM_BLOCKSIZE - nBlock;
+  }
+	buffer = safe_malloc (nAllocSize+1);
+  memset(buffer, 0, nAllocSize+1);
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+TryLoadFile
+
+Allows failure
+==============
+*/
+int    TryLoadFile (const char *filename, void **bufferptr)
+{
+	FILE	*f;
+	int    length;
+	void    *buffer;
+
+	*bufferptr = NULL;
+
+	f = fopen (filename, "rb");
+	if (!f)
+		return -1;
+	length = Q_filelength (f);
+	buffer = safe_malloc (length+1);
+	((char *)buffer)[length] = 0;
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+SaveFile
+==============
+*/
+void    SaveFile (const char *filename, const void *buffer, int count)
+{
+	FILE	*f;
+
+	f = SafeOpenWrite (filename);
+	SafeWrite (f, buffer, count);
+	fclose (f);
+}
+
+
+
+void DefaultExtension (char *path, const char *extension)
+{
+	char    *src;
+//
+// if path doesnt have a .EXT, append extension
+// (extension should include the .)
+//
+	src = path + strlen(path) - 1;
+
+	while (*src != '/' && *src != '\\' && src != path)
+	{
+		if (*src == '.')
+			return;                 // it has an extension
+		src--;
+	}
+
+	strcat (path, extension);
+}
+
+
+void DefaultPath (char *path, const char *basepath)
+{
+	char    temp[128];
+
+	if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
+		return;                   // absolute path location
+	strcpy (temp,path);
+	strcpy (path,basepath);
+	strcat (path,temp);
+}
+
+
+void    StripFilename (char *path)
+{
+	int             length;
+
+	length = strlen(path)-1;
+	while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
+		length--;
+	path[length] = 0;
+}
+
+void    StripExtension (char *path)
+{
+	int             length;
+
+	length = strlen(path)-1;
+	while (length > 0 && path[length] != '.')
+	{
+		length--;
+		if (path[length] == '/' || path[ length ] == '\\' )
+			return;		// no extension
+	}
+	if (length)
+		path[length] = 0;
+}
+
+
+/*
+====================
+Extract file parts
+====================
+*/
+// FIXME: should include the slash, otherwise
+// backing to an empty path will be wrong when appending a slash
+void ExtractFilePath (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+	while (src != path && *(src-1) != '\\' && *(src-1) != '/')
+		src--;
+
+	memcpy (dest, path, src-path);
+	dest[src-path] = 0;
+}
+
+void ExtractFileBase (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+	while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
+		src--;
+
+	while (*src && *src != '.')
+	{
+		*dest++ = *src++;
+	}
+	*dest = 0;
+}
+
+void ExtractFileExtension (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a . or the start
+//
+	while (src != path && *(src-1) != '.')
+		src--;
+	if (src == path)
+	{
+		*dest = 0;	// no extension
+		return;
+	}
+
+	strcpy (dest,src);
+}
+
+
+/*
+==============
+ParseNum / ParseHex
+==============
+*/
+int ParseHex (const char *hex)
+{
+	const char    *str;
+	int    num;
+
+	num = 0;
+	str = hex;
+
+	while (*str)
+	{
+		num <<= 4;
+		if (*str >= '0' && *str <= '9')
+			num += *str-'0';
+		else if (*str >= 'a' && *str <= 'f')
+			num += 10 + *str-'a';
+		else if (*str >= 'A' && *str <= 'F')
+			num += 10 + *str-'A';
+		else
+			Error ("Bad hex number: %s",hex);
+		str++;
+	}
+
+	return num;
+}
+
+
+int ParseNum (const char *str)
+{
+	if (str[0] == '$')
+		return ParseHex (str+1);
+	if (str[0] == '0' && str[1] == 'x')
+		return ParseHex (str+2);
+	return atol (str);
+}
+/*
+// all output ends up through here
+void FPrintf (int flag, char *buf)
+{
+  printf(buf);
+
+}
+
+void Sys_FPrintf (int flag, const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+
+  if ((flag == SYS_VRB) && (verbose == false))
+    return;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+
+  FPrintf (flag, out_buffer);
+}
+
+void Sys_Printf (const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+
+  FPrintf (SYS_STD, out_buffer);
+}
+
+
+//=================
+//Error
+//
+//For abnormal program terminations
+//=================
+
+void Error( const char *error, ...)
+{
+  char out_buffer[4096];
+  char tmp[4096];
+	va_list argptr;
+
+	va_start (argptr,error);
+	vsprintf (tmp, error, argptr);
+	va_end (argptr);
+
+  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
+
+  FPrintf( SYS_ERR, out_buffer );
+
+	exit (1);
+}
+*/
+
+
+/*
+============================================================================
+
+					BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+#ifdef _SGI_SOURCE
+#define	__BIG_ENDIAN__
+#endif
+
+#ifdef __BIG_ENDIAN__
+
+short   LittleShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   BigShort (short l)
+{
+	return l;
+}
+
+
+int    LittleLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    BigLong (int l)
+{
+	return l;
+}
+
+
+float	LittleFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	BigFloat (float l)
+{
+	return l;
+}
+
+
+#else
+
+
+short   BigShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   LittleShort (short l)
+{
+	return l;
+}
+
+
+int    BigLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    LittleLong (int l)
+{
+	return l;
+}
+
+float	BigFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	LittleFloat (float l)
+{
+	return l;
+}
+
+
+#endif
+
+
+//=======================================================
+
+
+// FIXME: byte swap?
+
+// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
+// and the initial and final xor values shown below...  in other words, the
+// CCITT standard CRC used by XMODEM
+
+#define CRC_INIT_VALUE	0xffff
+#define CRC_XOR_VALUE	0x0000
+
+static unsigned short crctable[256] =
+{
+	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
+	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
+	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
+	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
+	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
+	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
+	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
+	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
+	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
+	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
+	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
+	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
+	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
+	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
+	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
+	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
+	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
+	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
+	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
+	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
+	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
+	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
+	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
+	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
+	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
+	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
+	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
+	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
+	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
+	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
+	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
+	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
+};
+
+void CRC_Init(unsigned short *crcvalue)
+{
+	*crcvalue = CRC_INIT_VALUE;
+}
+
+void CRC_ProcessByte(unsigned short *crcvalue, byte data)
+{
+	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
+}
+
+unsigned short CRC_Value(unsigned short crcvalue)
+{
+	return crcvalue ^ CRC_XOR_VALUE;
+}
+//=============================================================================
+
+/*
+============
+CreatePath
+============
+*/
+void	CreatePath (const char *path)
+{
+	const char	*ofs;
+	char		c;
+	char		dir[1024];
+
+#ifdef _WIN32
+	int		olddrive = -1;
+
+	if ( path[1] == ':' )
+	{
+		olddrive = _getdrive();
+		_chdrive( toupper( path[0] ) - 'A' + 1 );
+	}
+#endif
+
+	if (path[1] == ':')
+		path += 2;
+
+	for (ofs = path+1 ; *ofs ; ofs++)
+	{
+		c = *ofs;
+		if (c == '/' || c == '\\')
+		{	// create the directory
+			memcpy( dir, path, ofs - path );
+			dir[ ofs - path ] = 0;
+			Q_mkdir( dir );
+		}
+	}
+
+#ifdef _WIN32
+	if ( olddrive != -1 )
+	{
+		_chdrive( olddrive );
+	}
+#endif
+}
+
+
+/*
+============
+QCopyFile
+
+  Used to archive source files
+============
+*/
+void QCopyFile (const char *from, const char *to)
+{
+	void	*buffer;
+	int		length;
+
+	length = LoadFile (from, &buffer);
+	CreatePath (to);
+	SaveFile (to, buffer, length);
+	free (buffer);
+}
+
+void Sys_Sleep(int n)
+{
+#ifdef _WIN32
+  Sleep (n);
+#endif
+#if defined (__linux__) || defined (__APPLE__)
+  usleep (n * 1000);
+#endif
+}
diff --git a/tools/quake2/common/cmdlib.h b/tools/quake2/common/cmdlib.h
index c3a5698f..02ced5be 100644
--- a/tools/quake2/common/cmdlib.h
+++ b/tools/quake2/common/cmdlib.h
@@ -1,170 +1,170 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// cmdlib.h
-
-#ifndef __CMDLIB__
-#define __CMDLIB__
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-
-#ifdef _WIN32
-	#ifdef NDEBUG							// Don't show in a Release build
-		#pragma warning(disable : 4305)     // truncate from double to float
-		#pragma warning(disable : 4244)     // conversion from double to float
-		#pragma warning(disable : 4018)     // signed/unsigned mismatch
-	#endif
-#endif
-
-#ifdef _WIN32
-	#pragma intrinsic( memset, memcpy )
-#endif
-
-#ifndef __BYTEBOOL__
-  #define __BYTEBOOL__
-  typedef enum {false, true} qboolean;
-  typedef unsigned char byte;
-#endif
-
-#define	MAX_OS_PATH		1024
-#define MEM_BLOCKSIZE 4096
-
-/*
-extern	qboolean verbose;
-#define SYS_VRB 0 // verbose support (on/off)
-#define SYS_STD 1 // standard print level
-#define SYS_WRN 2 // warnings
-#define SYS_ERR 3 // error
-*/
-
-// the dec offsetof macro doesnt work very well...
-#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
-
-#define SAFE_MALLOC
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size );
-void *safe_malloc_info( size_t size, char* info );
-#else
-#define safe_malloc(a) malloc(a)
-#endif /* SAFE_MALLOC */
-
-// set these before calling CheckParm
-extern int myargc;
-extern char **myargv;
-
-char *strlower (char *in);
-int Q_strncasecmp( const char *s1, const char *s2, int n );
-int Q_strcasecmp( const char *s1, const char *s2 );
-int Q_stricmp( const char *s1, const char *s2 );
-void Q_getwd( char *out );
-
-int Q_filelength (FILE *f);
-int	FileTime( const char *path );
-
-void	Q_mkdir( const char *path );
-
-extern	char		qdir[1024];
-extern	char		gamedir[1024];
-extern  char		writedir[1024];
-extern  char    *moddirparam;
-void SetQdirFromPath( const char *path);
-char *ExpandArg( const char *path );	// from cmd line
-char *ExpandPath( const char *path );	// from scripts
-char *ExpandGamePath (const char *path);
-char *ExpandPathAndArchive( const char *path );
-void ExpandWildcards( int *argc, char ***argv );
-
-
-double I_FloatTime( void );
-
-int		CheckParm( const char *check );
-
-FILE	*SafeOpenWrite( const char *filename );
-FILE	*SafeOpenRead( const char *filename );
-void	SafeRead (FILE *f, void *buffer, int count);
-void	SafeWrite (FILE *f, const void *buffer, int count);
-
-int		LoadFile( const char *filename, void **bufferptr );
-int   LoadFileBlock( const char *filename, void **bufferptr );
-int		TryLoadFile( const char *filename, void **bufferptr );
-void	SaveFile( const char *filename, const void *buffer, int count );
-qboolean	FileExists( const char *filename );
-
-void 	DefaultExtension( char *path, const char *extension );
-void 	DefaultPath( char *path, const char *basepath );
-void 	StripFilename( char *path );
-void 	StripExtension( char *path );
-
-void 	ExtractFilePath( const char *path, char *dest );
-void 	ExtractFileBase( const char *path, char *dest );
-void	ExtractFileExtension( const char *path, char *dest );
-
-int 	ParseNum (const char *str);
-
-//void Sys_Printf (const char *text, ...);
-//void Sys_FPrintf (int flag, const char *text, ...);
-//void	Error( const char *error, ... );
-
-short	BigShort (short l);
-short	LittleShort (short l);
-int		BigLong (int l);
-int		LittleLong (int l);
-float	BigFloat (float l);
-float	LittleFloat (float l);
-
-
-char *COM_Parse (char *data);
-
-extern	char		com_token[1024];
-extern	qboolean	com_eof;
-
-char *copystring(const char *s);
-
-
-void CRC_Init(unsigned short *crcvalue);
-void CRC_ProcessByte(unsigned short *crcvalue, byte data);
-unsigned short CRC_Value(unsigned short crcvalue);
-
-void	CreatePath( const char *path );
-void	QCopyFile( const char *from, const char *to );
-
-extern	qboolean		archive;
-extern	char			archivedir[1024];
-
-// sleep for the given amount of milliseconds
-void Sys_Sleep(int n);
-
-// for compression routines
-typedef struct
-{
-	byte	*data;
-	int		count;
-} cblock_t;
-
-extern	char	game[64];
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// cmdlib.h
+
+#ifndef __CMDLIB__
+#define __CMDLIB__
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+	#ifdef NDEBUG							// Don't show in a Release build
+		#pragma warning(disable : 4305)     // truncate from double to float
+		#pragma warning(disable : 4244)     // conversion from double to float
+		#pragma warning(disable : 4018)     // signed/unsigned mismatch
+	#endif
+#endif
+
+#ifdef _WIN32
+	#pragma intrinsic( memset, memcpy )
+#endif
+
+#ifndef __BYTEBOOL__
+  #define __BYTEBOOL__
+  typedef enum {false, true} qboolean;
+  typedef unsigned char byte;
+#endif
+
+#define	MAX_OS_PATH		1024
+#define MEM_BLOCKSIZE 4096
+
+/*
+extern	qboolean verbose;
+#define SYS_VRB 0 // verbose support (on/off)
+#define SYS_STD 1 // standard print level
+#define SYS_WRN 2 // warnings
+#define SYS_ERR 3 // error
+*/
+
+// the dec offsetof macro doesnt work very well...
+#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
+
+#define SAFE_MALLOC
+#ifdef SAFE_MALLOC
+void *safe_malloc( size_t size );
+void *safe_malloc_info( size_t size, char* info );
+#else
+#define safe_malloc(a) malloc(a)
+#endif /* SAFE_MALLOC */
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+char *strlower (char *in);
+int Q_strncasecmp( const char *s1, const char *s2, int n );
+int Q_strcasecmp( const char *s1, const char *s2 );
+int Q_stricmp( const char *s1, const char *s2 );
+void Q_getwd( char *out );
+
+int Q_filelength (FILE *f);
+int	FileTime( const char *path );
+
+void	Q_mkdir( const char *path );
+
+extern	char		qdir[1024];
+extern	char		gamedir[1024];
+extern  char		writedir[1024];
+extern  char    *moddirparam;
+void SetQdirFromPath( const char *path);
+char *ExpandArg( const char *path );	// from cmd line
+char *ExpandPath( const char *path );	// from scripts
+char *ExpandGamePath (const char *path);
+char *ExpandPathAndArchive( const char *path );
+void ExpandWildcards( int *argc, char ***argv );
+
+
+double I_FloatTime( void );
+
+int		CheckParm( const char *check );
+
+FILE	*SafeOpenWrite( const char *filename );
+FILE	*SafeOpenRead( const char *filename );
+void	SafeRead (FILE *f, void *buffer, int count);
+void	SafeWrite (FILE *f, const void *buffer, int count);
+
+int		LoadFile( const char *filename, void **bufferptr );
+int   LoadFileBlock( const char *filename, void **bufferptr );
+int		TryLoadFile( const char *filename, void **bufferptr );
+void	SaveFile( const char *filename, const void *buffer, int count );
+qboolean	FileExists( const char *filename );
+
+void 	DefaultExtension( char *path, const char *extension );
+void 	DefaultPath( char *path, const char *basepath );
+void 	StripFilename( char *path );
+void 	StripExtension( char *path );
+
+void 	ExtractFilePath( const char *path, char *dest );
+void 	ExtractFileBase( const char *path, char *dest );
+void	ExtractFileExtension( const char *path, char *dest );
+
+int 	ParseNum (const char *str);
+
+//void Sys_Printf (const char *text, ...);
+//void Sys_FPrintf (int flag, const char *text, ...);
+//void	Error( const char *error, ... );
+
+short	BigShort (short l);
+short	LittleShort (short l);
+int		BigLong (int l);
+int		LittleLong (int l);
+float	BigFloat (float l);
+float	LittleFloat (float l);
+
+
+char *COM_Parse (char *data);
+
+extern	char		com_token[1024];
+extern	qboolean	com_eof;
+
+char *copystring(const char *s);
+
+
+void CRC_Init(unsigned short *crcvalue);
+void CRC_ProcessByte(unsigned short *crcvalue, byte data);
+unsigned short CRC_Value(unsigned short crcvalue);
+
+void	CreatePath( const char *path );
+void	QCopyFile( const char *from, const char *to );
+
+extern	qboolean		archive;
+extern	char			archivedir[1024];
+
+// sleep for the given amount of milliseconds
+void Sys_Sleep(int n);
+
+// for compression routines
+typedef struct
+{
+	byte	*data;
+	int		count;
+} cblock_t;
+
+extern	char	game[64];
+
+#endif
diff --git a/tools/quake2/common/inout.c b/tools/quake2/common/inout.c
index ef21edea..33eac651 100644
--- a/tools/quake2/common/inout.c
+++ b/tools/quake2/common/inout.c
@@ -1,367 +1,367 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-//
-// DESCRIPTION:
-// deal with in/out tasks, for either stdin/stdout or network/XML stream
-// 
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "polylib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <windows.h>
-#endif
-
-// network broadcasting
-#include "l_net/l_net.h"
-#include "libxml/tree.h"
-
-#ifdef _WIN32
-HWND hwndOut = NULL;
-qboolean lookedForServer = false;
-UINT wm_BroadcastCommand = -1;
-#endif
-
-socket_t *brdcst_socket;
-netmessage_t msg;
-
-qboolean verbose = false;
-
-// our main document
-// is streamed through the network to Radiant
-// possibly written to disk at the end of the run
-//++timo FIXME: need to be global, required when creating nodes?
-xmlDocPtr doc;
-xmlNodePtr tree;
-
-// some useful stuff
-xmlNodePtr xml_NodeForVec( vec3_t v )
-{
-  xmlNodePtr ret;
-  char buf[1024];
-  
-  sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
-  ret = xmlNewNode (NULL, "point");
-  xmlNodeSetContent (ret, buf);
-  return ret;
-}
-
-// send a node down the stream, add it to the document
-void xml_SendNode (xmlNodePtr node)
-{
-  xmlBufferPtr xml_buf;
-  char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
-  // this index loops through the node buffer
-  int pos = 0;
-  int size;
-
-  xmlAddChild( doc->children, node );
-
-  if (brdcst_socket)
-  {
-    xml_buf = xmlBufferCreate();
-    xmlNodeDump( xml_buf, doc, node, 0, 0 );
-
-    // the XML node might be too big to fit in a single network message
-    // l_net library defines an upper limit of MAX_NETMESSAGE
-    // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
-    // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
-    while (pos < xml_buf->use)
-    {
-      // what size are we gonna send now?
-      (xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
-      //++timo just a debug thing
-      if (size == MAX_NETMESSAGE - 10)
-        Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
-      memcpy( xmlbuf, xml_buf->content+pos, size);
-      xmlbuf[size] = '\0';
-      NMSG_Clear( &msg );
-      NMSG_WriteString (&msg, xmlbuf );
-      Net_Send(brdcst_socket, &msg );
-      // now that the thing is sent prepare to loop again
-      pos += size;
-    }
-
-#if 0
-    // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
-    // we will need to split into chunks
-    // (we could also go lower level, in the end it's using send and receiv which are not size limited)
-    //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
-    //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
-
-    //++timo we need to handle the case of a buffer too big to fit in a single message
-    // try without checks for now
-    if (xml_buf->use > MAX_NETMESSAGE-10 )
-    {
-      // if we send that we are probably gonna break the stream at the other end..
-      // and Error will call right there
-      //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
-      Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
-      xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
-      Sys_FPrintf (SYS_NOXML, xml_buf->content);
-
-    }
-
-    size = xml_buf->use;
-    memcpy( xmlbuf, xml_buf->content, size );
-    xmlbuf[size] = '\0';
-    NMSG_Clear( &msg );
-    NMSG_WriteString (&msg, xmlbuf );
-    Net_Send(brdcst_socket, &msg );
-#endif
-
-    xmlBufferFree( xml_buf );
-  }  
-}
-
-void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
-{
-  xmlNodePtr node, select;
-  char buf[1024];
-  char level[2];
-
-  // now build a proper "select" XML node
-  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
-  node = xmlNewNode (NULL, "select");
-  xmlNodeSetContent (node, buf);
-  level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN)  ;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'select' information
-  sprintf (buf, "%i %i", entitynum, brushnum);
-  select = xmlNewNode (NULL, "brush");
-  xmlNodeSetContent (select, buf);
-  xmlAddChild (node, select);
-  xml_SendNode (node);
-
-  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
-  if (bError)
-    Error(buf);
-  else
-    Sys_FPrintf (SYS_NOXML, "%s\n", buf);
-
-}
-
-void xml_Point (char *msg, vec3_t pt)
-{
-  xmlNodePtr node, point;
-  char buf[1024];
-  char level[2];
-
-  node = xmlNewNode (NULL, "pointmsg");
-  xmlNodeSetContent (node, msg);
-  level[0] = (int)'0' + SYS_ERR;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'point' node
-  sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
-  point = xmlNewNode (NULL, "point");
-  xmlNodeSetContent (point, buf);
-  xmlAddChild (node, point);
-  xml_SendNode (node);
-
-  sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
-  Error (buf);
-}
-
-#define WINDING_BUFSIZE 2048
-void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
-{
-  xmlNodePtr node, winding;
-  char buf[WINDING_BUFSIZE];
-  char smlbuf[128];
-  char level[2];
-  int i;
-
-  node = xmlNewNode (NULL, "windingmsg");
-  xmlNodeSetContent (node, msg);
-  level[0] = (int)'0' + SYS_ERR;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'winding' node
-  sprintf( buf, "%i ", numpoints);
-  for(i = 0; i < numpoints; i++)
-  {
-	  sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
-    // don't overflow
-    if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
-      break;
-	  strcat( buf, smlbuf);
-  }
-
-  winding = xmlNewNode (NULL, "winding");
-  xmlNodeSetContent (winding, buf);
-  xmlAddChild (node, winding);
-  xml_SendNode (node);
-
-  if(die)
-    Error (msg);
-  else
-  {
-    Sys_Printf(msg);
-    Sys_Printf("\n");
-  }
-}
-
-// in include
-#include "stream_version.h"
-
-void Broadcast_Setup( const char *dest )
-{
-	address_t address;
-  char sMsg[1024];
-
-	Net_Setup();
-	Net_StringToAddress((char *)dest, &address);
-  brdcst_socket = Net_Connect(&address, 0);
-  if (brdcst_socket)
-  {
-    // send in a header
-    sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
-    NMSG_Clear( &msg );
-    NMSG_WriteString(&msg, sMsg );
-    Net_Send(brdcst_socket, &msg );
-  }
-}
-
-void Broadcast_Shutdown()
-{
-  if (brdcst_socket)
-  {    
-    Sys_Printf("Disconnecting\n");
-    Net_Disconnect(brdcst_socket);
-    brdcst_socket = NULL;
-  }
-}
-
-// all output ends up through here
-void FPrintf (int flag, char *buf)
-{
-  xmlNodePtr node;
-  static qboolean bGotXML = false;
-  char level[2];
-
-  printf(buf);
-
-  // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
-  if (flag == SYS_NOXML)
-    return;
-
-  // ouput an XML file of the run
-  // use the DOM interface to build a tree
-  /*
-  <message level='flag'>
-    message string
-    .. various nodes to describe corresponding geometry ..
-  </message>
-  */
-  if (!bGotXML)
-  {
-    // initialize
-    doc = xmlNewDoc("1.0");
-    doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
-    bGotXML = true;
-  }
-  node = xmlNewNode (NULL, "message");
-  xmlNodeSetContent (node, buf);
-  level[0] = (int)'0' + flag;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level );
-  
-  xml_SendNode (node);
-}
-
-#ifdef DBG_XML
-void DumpXML()
-{
-  xmlSaveFile( "XMLDump.xml", doc );
-}
-#endif
-
-void Sys_FPrintf (int flag, const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-  
-  if ((flag == SYS_VRB) && (verbose == false))
-    return;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-
-  FPrintf (flag, out_buffer);
-}
-
-void Sys_Printf (const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-  
-  FPrintf (SYS_STD, out_buffer);
-}
-
-/*
-=================
-Error
-
-For abnormal program terminations
-=================
-*/
-void Error( const char *error, ...)
-{
-  char out_buffer[4096];
-  char tmp[4096];
-	va_list argptr;
-
-	va_start (argptr,error);
-	vsprintf (tmp, error, argptr);
-	va_end (argptr);
-
-  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
-
-  FPrintf( SYS_ERR, out_buffer );
-
-#ifdef DBG_XML  
-  DumpXML();
-#endif
-
-  //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
-  // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
-  Sys_Sleep( 1000 );
-  
-  Broadcast_Shutdown();
-
-	exit (1);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+//
+// DESCRIPTION:
+// deal with in/out tasks, for either stdin/stdout or network/XML stream
+// 
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "polylib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#endif
+
+// network broadcasting
+#include "l_net/l_net.h"
+#include "libxml/tree.h"
+
+#ifdef _WIN32
+HWND hwndOut = NULL;
+qboolean lookedForServer = false;
+UINT wm_BroadcastCommand = -1;
+#endif
+
+socket_t *brdcst_socket;
+netmessage_t msg;
+
+qboolean verbose = false;
+
+// our main document
+// is streamed through the network to Radiant
+// possibly written to disk at the end of the run
+//++timo FIXME: need to be global, required when creating nodes?
+xmlDocPtr doc;
+xmlNodePtr tree;
+
+// some useful stuff
+xmlNodePtr xml_NodeForVec( vec3_t v )
+{
+  xmlNodePtr ret;
+  char buf[1024];
+  
+  sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
+  ret = xmlNewNode (NULL, "point");
+  xmlNodeSetContent (ret, buf);
+  return ret;
+}
+
+// send a node down the stream, add it to the document
+void xml_SendNode (xmlNodePtr node)
+{
+  xmlBufferPtr xml_buf;
+  char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
+  // this index loops through the node buffer
+  int pos = 0;
+  int size;
+
+  xmlAddChild( doc->children, node );
+
+  if (brdcst_socket)
+  {
+    xml_buf = xmlBufferCreate();
+    xmlNodeDump( xml_buf, doc, node, 0, 0 );
+
+    // the XML node might be too big to fit in a single network message
+    // l_net library defines an upper limit of MAX_NETMESSAGE
+    // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
+    // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
+    while (pos < xml_buf->use)
+    {
+      // what size are we gonna send now?
+      (xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
+      //++timo just a debug thing
+      if (size == MAX_NETMESSAGE - 10)
+        Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
+      memcpy( xmlbuf, xml_buf->content+pos, size);
+      xmlbuf[size] = '\0';
+      NMSG_Clear( &msg );
+      NMSG_WriteString (&msg, xmlbuf );
+      Net_Send(brdcst_socket, &msg );
+      // now that the thing is sent prepare to loop again
+      pos += size;
+    }
+
+#if 0
+    // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
+    // we will need to split into chunks
+    // (we could also go lower level, in the end it's using send and receiv which are not size limited)
+    //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
+    //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
+
+    //++timo we need to handle the case of a buffer too big to fit in a single message
+    // try without checks for now
+    if (xml_buf->use > MAX_NETMESSAGE-10 )
+    {
+      // if we send that we are probably gonna break the stream at the other end..
+      // and Error will call right there
+      //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
+      Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
+      xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
+      Sys_FPrintf (SYS_NOXML, xml_buf->content);
+
+    }
+
+    size = xml_buf->use;
+    memcpy( xmlbuf, xml_buf->content, size );
+    xmlbuf[size] = '\0';
+    NMSG_Clear( &msg );
+    NMSG_WriteString (&msg, xmlbuf );
+    Net_Send(brdcst_socket, &msg );
+#endif
+
+    xmlBufferFree( xml_buf );
+  }  
+}
+
+void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
+{
+  xmlNodePtr node, select;
+  char buf[1024];
+  char level[2];
+
+  // now build a proper "select" XML node
+  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
+  node = xmlNewNode (NULL, "select");
+  xmlNodeSetContent (node, buf);
+  level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN)  ;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'select' information
+  sprintf (buf, "%i %i", entitynum, brushnum);
+  select = xmlNewNode (NULL, "brush");
+  xmlNodeSetContent (select, buf);
+  xmlAddChild (node, select);
+  xml_SendNode (node);
+
+  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
+  if (bError)
+    Error(buf);
+  else
+    Sys_FPrintf (SYS_NOXML, "%s\n", buf);
+
+}
+
+void xml_Point (char *msg, vec3_t pt)
+{
+  xmlNodePtr node, point;
+  char buf[1024];
+  char level[2];
+
+  node = xmlNewNode (NULL, "pointmsg");
+  xmlNodeSetContent (node, msg);
+  level[0] = (int)'0' + SYS_ERR;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'point' node
+  sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
+  point = xmlNewNode (NULL, "point");
+  xmlNodeSetContent (point, buf);
+  xmlAddChild (node, point);
+  xml_SendNode (node);
+
+  sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
+  Error (buf);
+}
+
+#define WINDING_BUFSIZE 2048
+void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
+{
+  xmlNodePtr node, winding;
+  char buf[WINDING_BUFSIZE];
+  char smlbuf[128];
+  char level[2];
+  int i;
+
+  node = xmlNewNode (NULL, "windingmsg");
+  xmlNodeSetContent (node, msg);
+  level[0] = (int)'0' + SYS_ERR;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'winding' node
+  sprintf( buf, "%i ", numpoints);
+  for(i = 0; i < numpoints; i++)
+  {
+	  sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
+    // don't overflow
+    if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
+      break;
+	  strcat( buf, smlbuf);
+  }
+
+  winding = xmlNewNode (NULL, "winding");
+  xmlNodeSetContent (winding, buf);
+  xmlAddChild (node, winding);
+  xml_SendNode (node);
+
+  if(die)
+    Error (msg);
+  else
+  {
+    Sys_Printf(msg);
+    Sys_Printf("\n");
+  }
+}
+
+// in include
+#include "stream_version.h"
+
+void Broadcast_Setup( const char *dest )
+{
+	address_t address;
+  char sMsg[1024];
+
+	Net_Setup();
+	Net_StringToAddress((char *)dest, &address);
+  brdcst_socket = Net_Connect(&address, 0);
+  if (brdcst_socket)
+  {
+    // send in a header
+    sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
+    NMSG_Clear( &msg );
+    NMSG_WriteString(&msg, sMsg );
+    Net_Send(brdcst_socket, &msg );
+  }
+}
+
+void Broadcast_Shutdown()
+{
+  if (brdcst_socket)
+  {    
+    Sys_Printf("Disconnecting\n");
+    Net_Disconnect(brdcst_socket);
+    brdcst_socket = NULL;
+  }
+}
+
+// all output ends up through here
+void FPrintf (int flag, char *buf)
+{
+  xmlNodePtr node;
+  static qboolean bGotXML = false;
+  char level[2];
+
+  printf(buf);
+
+  // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
+  if (flag == SYS_NOXML)
+    return;
+
+  // ouput an XML file of the run
+  // use the DOM interface to build a tree
+  /*
+  <message level='flag'>
+    message string
+    .. various nodes to describe corresponding geometry ..
+  </message>
+  */
+  if (!bGotXML)
+  {
+    // initialize
+    doc = xmlNewDoc("1.0");
+    doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
+    bGotXML = true;
+  }
+  node = xmlNewNode (NULL, "message");
+  xmlNodeSetContent (node, buf);
+  level[0] = (int)'0' + flag;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level );
+  
+  xml_SendNode (node);
+}
+
+#ifdef DBG_XML
+void DumpXML()
+{
+  xmlSaveFile( "XMLDump.xml", doc );
+}
+#endif
+
+void Sys_FPrintf (int flag, const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+  
+  if ((flag == SYS_VRB) && (verbose == false))
+    return;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+
+  FPrintf (flag, out_buffer);
+}
+
+void Sys_Printf (const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+  
+  FPrintf (SYS_STD, out_buffer);
+}
+
+/*
+=================
+Error
+
+For abnormal program terminations
+=================
+*/
+void Error( const char *error, ...)
+{
+  char out_buffer[4096];
+  char tmp[4096];
+	va_list argptr;
+
+	va_start (argptr,error);
+	vsprintf (tmp, error, argptr);
+	va_end (argptr);
+
+  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
+
+  FPrintf( SYS_ERR, out_buffer );
+
+#ifdef DBG_XML  
+  DumpXML();
+#endif
+
+  //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
+  // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
+  Sys_Sleep( 1000 );
+  
+  Broadcast_Shutdown();
+
+	exit (1);
+}
+
diff --git a/tools/quake2/common/inout.h b/tools/quake2/common/inout.h
index 4843a7b6..05b56a09 100644
--- a/tools/quake2/common/inout.h
+++ b/tools/quake2/common/inout.h
@@ -1,63 +1,63 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __INOUT__
-#define __INOUT__
-
-// inout is the only stuff relying on xml, include the headers there
-#include "libxml/tree.h"
-#include "mathlib.h"
-
-// some useful xml routines
-xmlNodePtr xml_NodeForVec( vec3_t v );
-void xml_SendNode (xmlNodePtr node);
-// print a message in q3map output and send the corresponding select information down the xml stream
-// bError: do we end with an error on this one or do we go ahead?
-void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
-// end q3map with an error message and send a point information in the xml stream
-// note: we might want to add a boolean to use this as a warning or an error thing..
-void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
-void xml_Point (char *msg, vec3_t pt);
-
-extern qboolean bNetworkBroadcast;
-void Broadcast_Setup( const char *dest );
-void Broadcast_Shutdown();
-
-#define SYS_VRB 0 // verbose support (on/off)
-#define SYS_STD 1 // standard print level
-#define SYS_WRN 2 // warnings
-#define SYS_ERR 3 // error
-#define SYS_NOXML 4 // don't send that down the XML stream
-
-extern	qboolean verbose;
-void Sys_Printf (const char *text, ...);
-void Sys_FPrintf (int flag, const char *text, ...);
-void Error( const char *error, ...);
-
-#ifdef _DEBUG
-#define DBG_XML 1
-#endif
-
-#ifdef DBG_XML
-void DumpXML();
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __INOUT__
+#define __INOUT__
+
+// inout is the only stuff relying on xml, include the headers there
+#include "libxml/tree.h"
+#include "mathlib.h"
+
+// some useful xml routines
+xmlNodePtr xml_NodeForVec( vec3_t v );
+void xml_SendNode (xmlNodePtr node);
+// print a message in q3map output and send the corresponding select information down the xml stream
+// bError: do we end with an error on this one or do we go ahead?
+void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
+// end q3map with an error message and send a point information in the xml stream
+// note: we might want to add a boolean to use this as a warning or an error thing..
+void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
+void xml_Point (char *msg, vec3_t pt);
+
+extern qboolean bNetworkBroadcast;
+void Broadcast_Setup( const char *dest );
+void Broadcast_Shutdown();
+
+#define SYS_VRB 0 // verbose support (on/off)
+#define SYS_STD 1 // standard print level
+#define SYS_WRN 2 // warnings
+#define SYS_ERR 3 // error
+#define SYS_NOXML 4 // don't send that down the XML stream
+
+extern	qboolean verbose;
+void Sys_Printf (const char *text, ...);
+void Sys_FPrintf (int flag, const char *text, ...);
+void Error( const char *error, ...);
+
+#ifdef _DEBUG
+#define DBG_XML 1
+#endif
+
+#ifdef DBG_XML
+void DumpXML();
+#endif
+
+#endif
diff --git a/tools/quake2/common/l3dslib.c b/tools/quake2/common/l3dslib.c
index 7a551b11..e9b25681 100644
--- a/tools/quake2/common/l3dslib.c
+++ b/tools/quake2/common/l3dslib.c
@@ -1,300 +1,300 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-//
-// l3dslib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "l3dslib.h"
-
-#define MAIN3DS       0x4D4D
-#define EDIT3DS       0x3D3D  // this is the start of the editor config
-#define EDIT_OBJECT   0x4000
-#define OBJ_TRIMESH   0x4100
-#define TRI_VERTEXL   0x4110
-#define TRI_FACEL1    0x4120
-
-#define MAXVERTS	2000
-
-typedef struct {
-	int	v[4];
-} tri;
-
-float	fverts[MAXVERTS][3];
-tri		tris[MAXTRIANGLES];
-
-int	bytesread, level, numtris, totaltris;
-int	vertsfound, trisfound;
-
-triangle_t	*ptri;
-
-
-// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
-// start out with a vertex pool and vertex indices for triangles, we have to convert
-// to raw, explicit triangles
-void StoreAliasTriangles (void)
-{
-	int		i, j, k;
-
-	if ((totaltris + numtris) > MAXTRIANGLES)
-		Error ("Error: Too many triangles");
-
-	for (i=0; i<numtris ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			for (k=0 ; k<3 ; k++)
-			{
-				ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
-			}
-		}
-	}
-	
-	totaltris += numtris;
-	numtris = 0;
-	vertsfound = 0;
-	trisfound = 0;
-}
-
-
-int ParseVertexL (FILE *input)
-{
-	int				i, j, startbytesread, numverts;
-	unsigned short	tshort;
-
-	if (vertsfound)
-		Error ("Error: Multiple vertex chunks");
-
-	vertsfound = 1;
-	startbytesread = bytesread;
-
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&tshort, sizeof(tshort), 1, input);
-	bytesread += sizeof(tshort);
-	numverts = (int)tshort;
-
-	if (numverts > MAXVERTS)
-		Error ("Error: Too many vertices");
-
-	for (i=0 ; i<numverts ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread(&fverts[i][j], sizeof(float), 1, input);
-			bytesread += sizeof(float);
-		}
-	}
-
-	if (vertsfound && trisfound)
-		StoreAliasTriangles ();
-
-	return bytesread - startbytesread;
-}
-
-
-int ParseFaceL1 (FILE *input)
-{
-
-	int				i, j, startbytesread;
-	unsigned short	tshort;
-
-	if (trisfound)
-		Error ("Error: Multiple face chunks");
-
-	trisfound = 1;
-	startbytesread = bytesread;
-
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&tshort, sizeof(tshort), 1, input);
-	bytesread += sizeof(tshort);
-	numtris = (int)tshort;
-
-	if (numtris > MAXTRIANGLES)
-		Error ("Error: Too many triangles");
-
-	for (i=0 ; i<numtris ; i++)
-	{
-		for (j=0 ; j<4 ; j++)
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread(&tshort, sizeof(tshort), 1, input);
-			bytesread += sizeof(tshort);
-			tris[i].v[j] = (int)tshort;
-		}
-	}
-
-	if (vertsfound && trisfound)
-		StoreAliasTriangles ();
-
-	return bytesread - startbytesread;
-}
-
-
-int ParseChunk (FILE *input)
-{
-#define BLOCK_SIZE	4096
-	char			temp[BLOCK_SIZE];
-	unsigned short	type;
-	int				i, length, w, t, retval;
-
-	level++;
-	retval = 0;
-
-// chunk type
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&type, sizeof(type), 1, input);
-	bytesread += sizeof(type);
-
-// chunk length
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread (&length, sizeof(length), 1, input);
-	bytesread += sizeof(length);
-	w = length - 6;
-
-// process chunk if we care about it, otherwise skip it
-	switch (type)
-	{
-	case TRI_VERTEXL:
-		w -= ParseVertexL (input);
-		goto ParseSubchunk;
-
-	case TRI_FACEL1:
-		w -= ParseFaceL1 (input);
-		goto ParseSubchunk;
-
-	case EDIT_OBJECT:
-	// read the name
-		i = 0;
-
-		do
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread (&temp[i], 1, 1, input);
-			i++;
-			w--;
-			bytesread++;
-		} while (temp[i-1]);
-
-	case MAIN3DS:
-	case OBJ_TRIMESH:
-	case EDIT3DS:
-	// parse through subchunks
-ParseSubchunk:
-		while (w > 0)
-		{
-			w -= ParseChunk (input);
-		}
-
-		retval = length;
-		goto Done;
-
-	default:
-	// skip other chunks
-		while (w > 0)
-		{
-			t = w;
-
-			if (t > BLOCK_SIZE)
-				t = BLOCK_SIZE;
-
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread (&temp, t, 1, input);
-			bytesread += t;
-
-			w -= t;
-		}
-
-		retval = length;
-		goto Done;
-	}
-
-Done:
-	level--;
-	return retval;
-}
-
-
-void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
-{
-	FILE        *input;
-	short int	tshort;
-
-	bytesread = 0;
-	level = 0;
-	numtris = 0;
-	totaltris = 0;
-	vertsfound = 0;
-	trisfound = 0;
-
-	if ((input = fopen(filename, "rb")) == 0) {
-		fprintf(stderr,"reader: could not open file '%s'\n", filename);
-		exit(0);
-	}
-
-	fread(&tshort, sizeof(tshort), 1, input);
-
-// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
-// no MAIN3DS
-	if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
-		fprintf(stderr,"File is not a 3DS file.\n");
-		exit(0);
-	}
-
-// back to top of file so we can parse the first chunk descriptor
-	fseek(input, 0, SEEK_SET);
-
-	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
-
-	*pptri = ptri;
-
-// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
-// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
-	ParseChunk (input);
-
-	if (vertsfound || trisfound)
-		Error ("Incomplete triangle set");
-
-	*numtriangles = totaltris;
-
-	fclose (input);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+//
+// l3dslib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "l3dslib.h"
+
+#define MAIN3DS       0x4D4D
+#define EDIT3DS       0x3D3D  // this is the start of the editor config
+#define EDIT_OBJECT   0x4000
+#define OBJ_TRIMESH   0x4100
+#define TRI_VERTEXL   0x4110
+#define TRI_FACEL1    0x4120
+
+#define MAXVERTS	2000
+
+typedef struct {
+	int	v[4];
+} tri;
+
+float	fverts[MAXVERTS][3];
+tri		tris[MAXTRIANGLES];
+
+int	bytesread, level, numtris, totaltris;
+int	vertsfound, trisfound;
+
+triangle_t	*ptri;
+
+
+// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
+// start out with a vertex pool and vertex indices for triangles, we have to convert
+// to raw, explicit triangles
+void StoreAliasTriangles (void)
+{
+	int		i, j, k;
+
+	if ((totaltris + numtris) > MAXTRIANGLES)
+		Error ("Error: Too many triangles");
+
+	for (i=0; i<numtris ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			for (k=0 ; k<3 ; k++)
+			{
+				ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
+			}
+		}
+	}
+	
+	totaltris += numtris;
+	numtris = 0;
+	vertsfound = 0;
+	trisfound = 0;
+}
+
+
+int ParseVertexL (FILE *input)
+{
+	int				i, j, startbytesread, numverts;
+	unsigned short	tshort;
+
+	if (vertsfound)
+		Error ("Error: Multiple vertex chunks");
+
+	vertsfound = 1;
+	startbytesread = bytesread;
+
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&tshort, sizeof(tshort), 1, input);
+	bytesread += sizeof(tshort);
+	numverts = (int)tshort;
+
+	if (numverts > MAXVERTS)
+		Error ("Error: Too many vertices");
+
+	for (i=0 ; i<numverts ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread(&fverts[i][j], sizeof(float), 1, input);
+			bytesread += sizeof(float);
+		}
+	}
+
+	if (vertsfound && trisfound)
+		StoreAliasTriangles ();
+
+	return bytesread - startbytesread;
+}
+
+
+int ParseFaceL1 (FILE *input)
+{
+
+	int				i, j, startbytesread;
+	unsigned short	tshort;
+
+	if (trisfound)
+		Error ("Error: Multiple face chunks");
+
+	trisfound = 1;
+	startbytesread = bytesread;
+
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&tshort, sizeof(tshort), 1, input);
+	bytesread += sizeof(tshort);
+	numtris = (int)tshort;
+
+	if (numtris > MAXTRIANGLES)
+		Error ("Error: Too many triangles");
+
+	for (i=0 ; i<numtris ; i++)
+	{
+		for (j=0 ; j<4 ; j++)
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread(&tshort, sizeof(tshort), 1, input);
+			bytesread += sizeof(tshort);
+			tris[i].v[j] = (int)tshort;
+		}
+	}
+
+	if (vertsfound && trisfound)
+		StoreAliasTriangles ();
+
+	return bytesread - startbytesread;
+}
+
+
+int ParseChunk (FILE *input)
+{
+#define BLOCK_SIZE	4096
+	char			temp[BLOCK_SIZE];
+	unsigned short	type;
+	int				i, length, w, t, retval;
+
+	level++;
+	retval = 0;
+
+// chunk type
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&type, sizeof(type), 1, input);
+	bytesread += sizeof(type);
+
+// chunk length
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread (&length, sizeof(length), 1, input);
+	bytesread += sizeof(length);
+	w = length - 6;
+
+// process chunk if we care about it, otherwise skip it
+	switch (type)
+	{
+	case TRI_VERTEXL:
+		w -= ParseVertexL (input);
+		goto ParseSubchunk;
+
+	case TRI_FACEL1:
+		w -= ParseFaceL1 (input);
+		goto ParseSubchunk;
+
+	case EDIT_OBJECT:
+	// read the name
+		i = 0;
+
+		do
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread (&temp[i], 1, 1, input);
+			i++;
+			w--;
+			bytesread++;
+		} while (temp[i-1]);
+
+	case MAIN3DS:
+	case OBJ_TRIMESH:
+	case EDIT3DS:
+	// parse through subchunks
+ParseSubchunk:
+		while (w > 0)
+		{
+			w -= ParseChunk (input);
+		}
+
+		retval = length;
+		goto Done;
+
+	default:
+	// skip other chunks
+		while (w > 0)
+		{
+			t = w;
+
+			if (t > BLOCK_SIZE)
+				t = BLOCK_SIZE;
+
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread (&temp, t, 1, input);
+			bytesread += t;
+
+			w -= t;
+		}
+
+		retval = length;
+		goto Done;
+	}
+
+Done:
+	level--;
+	return retval;
+}
+
+
+void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
+{
+	FILE        *input;
+	short int	tshort;
+
+	bytesread = 0;
+	level = 0;
+	numtris = 0;
+	totaltris = 0;
+	vertsfound = 0;
+	trisfound = 0;
+
+	if ((input = fopen(filename, "rb")) == 0) {
+		fprintf(stderr,"reader: could not open file '%s'\n", filename);
+		exit(0);
+	}
+
+	fread(&tshort, sizeof(tshort), 1, input);
+
+// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
+// no MAIN3DS
+	if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
+		fprintf(stderr,"File is not a 3DS file.\n");
+		exit(0);
+	}
+
+// back to top of file so we can parse the first chunk descriptor
+	fseek(input, 0, SEEK_SET);
+
+	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
+
+	*pptri = ptri;
+
+// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
+// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
+	ParseChunk (input);
+
+	if (vertsfound || trisfound)
+		Error ("Incomplete triangle set");
+
+	*numtriangles = totaltris;
+
+	fclose (input);
+}
+
diff --git a/tools/quake2/common/l3dslib.h b/tools/quake2/common/l3dslib.h
index 528adc1d..bb2c4991 100644
--- a/tools/quake2/common/l3dslib.h
+++ b/tools/quake2/common/l3dslib.h
@@ -1,25 +1,25 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-//
-// l3dslib.h: header file for loading triangles from a 3DS triangle file
-//
-void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+//
+// l3dslib.h: header file for loading triangles from a 3DS triangle file
+//
+void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles);
+
diff --git a/tools/quake2/common/lbmlib.c b/tools/quake2/common/lbmlib.c
index e157b94c..5039dab6 100644
--- a/tools/quake2/common/lbmlib.c
+++ b/tools/quake2/common/lbmlib.c
@@ -1,837 +1,837 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// lbmlib.c
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "lbmlib.h"
-
-
-
-/*
-============================================================================
-
-						LBM STUFF
-
-============================================================================
-*/
-
-
-typedef unsigned char	UBYTE;
-//conflicts with windows typedef short			WORD;
-typedef unsigned short	UWORD;
-typedef long			LONG;
-
-typedef enum
-{
-	ms_none,
-	ms_mask,
-	ms_transcolor,
-	ms_lasso
-} mask_t;
-
-typedef enum
-{
-	cm_none,
-	cm_rle1
-} compress_t;
-
-typedef struct
-{
-	UWORD		w,h;
-	short		x,y;
-	UBYTE		nPlanes;
-	UBYTE		masking;
-	UBYTE		compression;
-	UBYTE		pad1;
-	UWORD		transparentColor;
-	UBYTE		xAspect,yAspect;
-	short		pageWidth,pageHeight;
-} bmhd_t;
-
-extern	bmhd_t	bmhd;						// will be in native byte order
-
-
-
-#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
-#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
-#define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
-#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
-#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
-#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
-
-
-bmhd_t  bmhd;
-
-int    Align (int l)
-{
-	if (l&1)
-		return l+1;
-	return l;
-}
-
-
-
-/*
-================
-LBMRLEdecompress
-
-Source must be evenly aligned!
-================
-*/
-byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
-{
-	int     count;
-	byte    b,rept;
-
-	count = 0;
-
-	do
-	{
-		rept = *source++;
-
-		if (rept > 0x80)
-		{
-			rept = (rept^0xff)+2;
-			b = *source++;
-			memset(unpacked,b,rept);
-			unpacked += rept;
-		}
-		else if (rept < 0x80)
-		{
-			rept++;
-			memcpy(unpacked,source,rept);
-			unpacked += rept;
-			source += rept;
-		}
-		else
-			rept = 0;               // rept of 0x80 is NOP
-
-		count += rept;
-
-	} while (count<bpwidth);
-
-	if (count>bpwidth)
-		Error ("Decompression exceeded width!\n");
-
-
-	return source;
-}
-
-
-/*
-=================
-LoadLBM
-=================
-*/
-void LoadLBM (char *filename, byte **picture, byte **palette)
-{
-	byte    *LBMbuffer, *picbuffer, *cmapbuffer;
-	int             y;
-	byte    *LBM_P, *LBMEND_P;
-	byte    *pic_p;
-	byte    *body_p;
-
-	int    formtype,formlength;
-	int    chunktype,chunklength;
-
-// qiet compiler warnings
-	picbuffer = NULL;
-	cmapbuffer = NULL;
-
-//
-// load the LBM
-//
-	LoadFile (filename, (void **)&LBMbuffer);
-
-//
-// parse the LBM header
-//
-	LBM_P = LBMbuffer;
-	if ( *(int *)LBMbuffer != LittleLong(FORMID) )
-	   Error ("No FORM ID at start of file!\n");
-
-	LBM_P += 4;
-	formlength = BigLong( *(int *)LBM_P );
-	LBM_P += 4;
-	LBMEND_P = LBM_P + Align(formlength);
-
-	formtype = LittleLong(*(int *)LBM_P);
-
-	if (formtype != ILBMID && formtype != PBMID)
-		Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
-		,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
-
-	LBM_P += 4;
-
-//
-// parse chunks
-//
-
-	while (LBM_P < LBMEND_P)
-	{
-		chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
-		LBM_P += 4;
-		chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
-		LBM_P += 4;
-
-		switch ( chunktype )
-		{
-		case BMHDID:
-			memcpy (&bmhd,LBM_P,sizeof(bmhd));
-			bmhd.w = BigShort(bmhd.w);
-			bmhd.h = BigShort(bmhd.h);
-			bmhd.x = BigShort(bmhd.x);
-			bmhd.y = BigShort(bmhd.y);
-			bmhd.pageWidth = BigShort(bmhd.pageWidth);
-			bmhd.pageHeight = BigShort(bmhd.pageHeight);
-			break;
-
-		case CMAPID:
-			cmapbuffer = malloc (768);
-			memset (cmapbuffer, 0, 768);
-			memcpy (cmapbuffer, LBM_P, chunklength);
-			break;
-
-		case BODYID:
-			body_p = LBM_P;
-
-			pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
-			if (formtype == PBMID)
-			{
-			//
-			// unpack PBM
-			//
-				for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
-				{
-					if (bmhd.compression == cm_rle1)
-						body_p = LBMRLEDecompress ((byte *)body_p
-						, pic_p , bmhd.w);
-					else if (bmhd.compression == cm_none)
-					{
-						memcpy (pic_p,body_p,bmhd.w);
-						body_p += Align(bmhd.w);
-					}
-				}
-
-			}
-			else
-			{
-			//
-			// unpack ILBM
-			//
-				Error ("%s is an interlaced LBM, not packed", filename);
-			}
-			break;
-		}
-
-		LBM_P += Align(chunklength);
-	}
-
-	free (LBMbuffer);
-
-	*picture = picbuffer;
-
-	if (palette)
-		*palette = cmapbuffer;
-}
-
-
-/*
-============================================================================
-
-							WRITE LBM
-
-============================================================================
-*/
-
-/*
-==============
-WriteLBMfile
-==============
-*/
-void WriteLBMfile (char *filename, byte *data,
-				   int width, int height, byte *palette)
-{
-	byte    *lbm, *lbmptr;
-	int    *formlength, *bmhdlength, *cmaplength, *bodylength;
-	int    length;
-	bmhd_t  basebmhd;
-
-	lbm = lbmptr = malloc (width*height+1000);
-
-//
-// start FORM
-//
-	*lbmptr++ = 'F';
-	*lbmptr++ = 'O';
-	*lbmptr++ = 'R';
-	*lbmptr++ = 'M';
-
-	formlength = (int*)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	*lbmptr++ = 'P';
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'M';
-	*lbmptr++ = ' ';
-
-//
-// write BMHD
-//
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'M';
-	*lbmptr++ = 'H';
-	*lbmptr++ = 'D';
-
-	bmhdlength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memset (&basebmhd,0,sizeof(basebmhd));
-	basebmhd.w = BigShort((short)width);
-	basebmhd.h = BigShort((short)height);
-	basebmhd.nPlanes = BigShort(8);
-	basebmhd.xAspect = BigShort(5);
-	basebmhd.yAspect = BigShort(6);
-	basebmhd.pageWidth = BigShort((short)width);
-	basebmhd.pageHeight = BigShort((short)height);
-
-	memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
-	lbmptr += sizeof(basebmhd);
-
-	length = lbmptr-(byte *)bmhdlength-4;
-	*bmhdlength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write CMAP
-//
-	*lbmptr++ = 'C';
-	*lbmptr++ = 'M';
-	*lbmptr++ = 'A';
-	*lbmptr++ = 'P';
-
-	cmaplength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memcpy (lbmptr,palette,768);
-	lbmptr += 768;
-
-	length = lbmptr-(byte *)cmaplength-4;
-	*cmaplength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write BODY
-//
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'O';
-	*lbmptr++ = 'D';
-	*lbmptr++ = 'Y';
-
-	bodylength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memcpy (lbmptr,data,width*height);
-	lbmptr += width*height;
-
-	length = lbmptr-(byte *)bodylength-4;
-	*bodylength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// done
-//
-	length = lbmptr-(byte *)formlength-4;
-	*formlength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write output file
-//
-	SaveFile (filename, lbm, lbmptr-lbm);
-	free (lbm);
-}
-
-
-/*
-============================================================================
-
-LOAD PCX
-
-============================================================================
-*/
-
-typedef struct
-{
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
-
-
-/*
-==============
-LoadPCX
-==============
-*/
-void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
-{
-	byte	*raw;
-	pcx_t	*pcx;
-	int		x, y;
-	int		len;
-	int		dataByte, runLength;
-	byte	*out, *pix;
-
-	//
-	// load the file
-	//
-	len = LoadFile (filename, (void **)&raw);
-
-	//
-	// parse the PCX file
-	//
-	pcx = (pcx_t *)raw;
-	raw = &pcx->data;
-
-	pcx->xmin = LittleShort(pcx->xmin);
-	pcx->ymin = LittleShort(pcx->ymin);
-	pcx->xmax = LittleShort(pcx->xmax);
-	pcx->ymax = LittleShort(pcx->ymax);
-	pcx->hres = LittleShort(pcx->hres);
-	pcx->vres = LittleShort(pcx->vres);
-	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
-	pcx->palette_type = LittleShort(pcx->palette_type);
-
-	if (pcx->manufacturer != 0x0a
-		|| pcx->version != 5
-		|| pcx->encoding != 1
-		|| pcx->bits_per_pixel != 8
-		|| pcx->xmax >= 640
-		|| pcx->ymax >= 480)
-		Error ("Bad pcx file %s", filename);
-	
-	if (palette)
-	{
-		*palette = malloc(768);
-		memcpy (*palette, (byte *)pcx + len - 768, 768);
-	}
-
-	if (width)
-		*width = pcx->xmax+1;
-	if (height)
-		*height = pcx->ymax+1;
-
-	if (!pic)
-		return;
-
-	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
-	if (!out)
-		Error ("Skin_Cache: couldn't allocate");
-
-	*pic = out;
-
-	pix = out;
-
-	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
-	{
-		for (x=0 ; x<=pcx->xmax ; )
-		{
-			dataByte = *raw++;
-
-			if((dataByte & 0xC0) == 0xC0)
-			{
-				runLength = dataByte & 0x3F;
-				dataByte = *raw++;
-			}
-			else
-				runLength = 1;
-
-			while(runLength-- > 0)
-				pix[x++] = dataByte;
-		}
-
-	}
-
-	if ( raw - (byte *)pcx > len)
-		Error ("PCX file %s was malformed", filename);
-
-	free (pcx);
-}
-
-/* 
-============== 
-WritePCXfile 
-============== 
-*/ 
-void WritePCXfile (char *filename, byte *data, 
-				   int width, int height, byte *palette) 
-{
-	int		i, j, length;
-	pcx_t	*pcx;
-	byte		*pack;
-	  
-	pcx = malloc (width*height*2+1000);
-	memset (pcx, 0, sizeof(*pcx));
-
-	pcx->manufacturer = 0x0a;	// PCX id
-	pcx->version = 5;			// 256 color
- 	pcx->encoding = 1;		// uncompressed
-	pcx->bits_per_pixel = 8;		// 256 color
-	pcx->xmin = 0;
-	pcx->ymin = 0;
-	pcx->xmax = LittleShort((short)(width-1));
-	pcx->ymax = LittleShort((short)(height-1));
-	pcx->hres = LittleShort((short)width);
-	pcx->vres = LittleShort((short)height);
-	pcx->color_planes = 1;		// chunky image
-	pcx->bytes_per_line = LittleShort((short)width);
-	pcx->palette_type = LittleShort(2);		// not a grey scale
-
-	// pack the image
-	pack = &pcx->data;
-	
-	for (i=0 ; i<height ; i++)
-	{
-		for (j=0 ; j<width ; j++)
-		{
-			if ( (*data & 0xc0) != 0xc0)
-				*pack++ = *data++;
-			else
-			{
-				*pack++ = 0xc1;
-				*pack++ = *data++;
-			}
-		}
-	}
-			
-	// write the palette
-	*pack++ = 0x0c;	// palette ID byte
-	for (i=0 ; i<768 ; i++)
-		*pack++ = *palette++;
-		
-// write output file 
-	length = pack - (byte *)pcx;
-	SaveFile (filename, pcx, length);
-
-	free (pcx);
-} 
- 
-
-/*
-============================================================================
-
-LOAD IMAGE
-
-============================================================================
-*/
-
-/*
-==============
-Load256Image
-
-Will load either an lbm or pcx, depending on extension.
-Any of the return pointers can be NULL if you don't want them.
-==============
-*/
-void Load256Image (char *name, byte **pixels, byte **palette,
-				   int *width, int *height)
-{
-	char	ext[128];
-
-	ExtractFileExtension (name, ext);
-	if (!Q_strncasecmp (ext, "lbm", strlen(ext) ))
-	{
-		LoadLBM (name, pixels, palette);
-		if (width)
-			*width = bmhd.w;
-		if (height)
-			*height = bmhd.h;
-	}
-	else if (!Q_strncasecmp (ext, "pcx",strlen(ext)))
-	{
-		LoadPCX (name, pixels, palette, width, height);
-	}
-	else
-		Error ("%s doesn't have a known image extension", name);
-}
-
-
-/*
-==============
-Save256Image
-
-Will save either an lbm or pcx, depending on extension.
-==============
-*/
-void Save256Image (char *name, byte *pixels, byte *palette,
-				   int width, int height)
-{
-	char	ext[128];
-
-	ExtractFileExtension (name, ext);
-	if (!Q_strncasecmp (ext, "lbm",strlen(ext)))
-	{
-		WriteLBMfile (name, pixels, width, height, palette);
-	}
-	else if (!Q_strncasecmp (ext, "pcx",strlen(ext)))
-	{
-		WritePCXfile (name, pixels, width, height, palette);
-	}
-	else
-		Error ("%s doesn't have a known image extension", name);
-}
-
-
-
-
-/*
-============================================================================
-
-TARGA IMAGE
-
-============================================================================
-*/
-
-typedef struct _TargaHeader {
-	unsigned char 	id_length, colormap_type, image_type;
-	unsigned short	colormap_index, colormap_length;
-	unsigned char	colormap_size;
-	unsigned short	x_origin, y_origin, width, height;
-	unsigned char	pixel_size, attributes;
-} TargaHeader;
-
-int fgetLittleShort (FILE *f)
-{
-	byte	b1, b2;
-
-	b1 = fgetc(f);
-	b2 = fgetc(f);
-
-	return (short)(b1 + b2*256);
-}
-
-int fgetLittleLong (FILE *f)
-{
-	byte	b1, b2, b3, b4;
-
-	b1 = fgetc(f);
-	b2 = fgetc(f);
-	b3 = fgetc(f);
-	b4 = fgetc(f);
-
-	return b1 + (b2<<8) + (b3<<16) + (b4<<24);
-}
-
-
-/*
-=============
-LoadTGA
-=============
-*/
-void LoadTGA (char *name, byte **pixels, int *width, int *height)
-{
-	int				columns, rows, numPixels;
-	byte			*pixbuf;
-	int				row, column;
-	FILE			*fin;
-	byte			*targa_rgba;
-	TargaHeader		targa_header;
-
-	fin = fopen (name, "rb");
-	if (!fin)
-		Error ("Couldn't read %s", name);
-
-	targa_header.id_length = fgetc(fin);
-	targa_header.colormap_type = fgetc(fin);
-	targa_header.image_type = fgetc(fin);
-	
-	targa_header.colormap_index = fgetLittleShort(fin);
-	targa_header.colormap_length = fgetLittleShort(fin);
-	targa_header.colormap_size = fgetc(fin);
-	targa_header.x_origin = fgetLittleShort(fin);
-	targa_header.y_origin = fgetLittleShort(fin);
-	targa_header.width = fgetLittleShort(fin);
-	targa_header.height = fgetLittleShort(fin);
-	targa_header.pixel_size = fgetc(fin);
-	targa_header.attributes = fgetc(fin);
-
-	if (targa_header.image_type!=2 
-		&& targa_header.image_type!=10) 
-		Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
-
-	if (targa_header.colormap_type !=0 
-		|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
-		Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
-
-	columns = targa_header.width;
-	rows = targa_header.height;
-	numPixels = columns * rows;
-
-	if (width)
-		*width = columns;
-	if (height)
-		*height = rows;
-	targa_rgba = malloc(numPixels*4);
-	*pixels = targa_rgba;
-
-	if (targa_header.id_length != 0)
-		fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
-	
-	if (targa_header.image_type==2) {  // Uncompressed, RGB images
-		for(row=rows-1; row>=0; row--) {
-			pixbuf = targa_rgba + row*columns*4;
-			for(column=0; column<columns; column++) {
-				unsigned char red,green,blue,alphabyte;
-				switch (targa_header.pixel_size) {
-					case 24:
-							
-							blue = getc(fin);
-							green = getc(fin);
-							red = getc(fin);
-							*pixbuf++ = red;
-							*pixbuf++ = green;
-							*pixbuf++ = blue;
-							*pixbuf++ = 255;
-							break;
-					case 32:
-							blue = getc(fin);
-							green = getc(fin);
-							red = getc(fin);
-							alphabyte = getc(fin);
-							*pixbuf++ = red;
-							*pixbuf++ = green;
-							*pixbuf++ = blue;
-							*pixbuf++ = alphabyte;
-							break;
-				}
-			}
-		}
-	}
-	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
-		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
-		for(row=rows-1; row>=0; row--) {
-			pixbuf = targa_rgba + row*columns*4;
-			for(column=0; column<columns; ) {
-				packetHeader=getc(fin);
-				packetSize = 1 + (packetHeader & 0x7f);
-				if (packetHeader & 0x80) {        // run-length packet
-					switch (targa_header.pixel_size) {
-						case 24:
-								blue = getc(fin);
-								green = getc(fin);
-								red = getc(fin);
-								alphabyte = 255;
-								break;
-						case 32:
-								blue = getc(fin);
-								green = getc(fin);
-								red = getc(fin);
-								alphabyte = getc(fin);
-								break;
-					}
-	
-					for(j=0;j<packetSize;j++) {
-						*pixbuf++=red;
-						*pixbuf++=green;
-						*pixbuf++=blue;
-						*pixbuf++=alphabyte;
-						column++;
-						if (column==columns) { // run spans across rows
-							column=0;
-							if (row>0)
-								row--;
-							else
-								goto breakOut;
-							pixbuf = targa_rgba + row*columns*4;
-						}
-					}
-				}
-				else {                            // non run-length packet
-					for(j=0;j<packetSize;j++) {
-						switch (targa_header.pixel_size) {
-							case 24:
-									blue = getc(fin);
-									green = getc(fin);
-									red = getc(fin);
-									*pixbuf++ = red;
-									*pixbuf++ = green;
-									*pixbuf++ = blue;
-									*pixbuf++ = 255;
-									break;
-							case 32:
-									blue = getc(fin);
-									green = getc(fin);
-									red = getc(fin);
-									alphabyte = getc(fin);
-									*pixbuf++ = red;
-									*pixbuf++ = green;
-									*pixbuf++ = blue;
-									*pixbuf++ = alphabyte;
-									break;
-						}
-						column++;
-						if (column==columns) { // pixel packet run spans across rows
-							column=0;
-							if (row>0)
-								row--;
-							else
-								goto breakOut;
-							pixbuf = targa_rgba + row*columns*4;
-						}						
-					}
-				}
-			}
-			breakOut:;
-		}
-	}
-
-	// vertically flipped
-	if ( (targa_header.attributes & (1<<5)) ) {
-		int flip;
-		for (row = 0; row < .5f * rows; row++)
-		{
-			for (column = 0; column < columns; column++)
-			{
-				flip = *( (int*)targa_rgba + row * columns + column);
-				*( (int*)targa_rgba + row * columns + column) = *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column );
-				*( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column ) = flip;
-			}
-		}
-	}
-	
-	fclose(fin);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// lbmlib.c
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "lbmlib.h"
+
+
+
+/*
+============================================================================
+
+						LBM STUFF
+
+============================================================================
+*/
+
+
+typedef unsigned char	UBYTE;
+//conflicts with windows typedef short			WORD;
+typedef unsigned short	UWORD;
+typedef long			LONG;
+
+typedef enum
+{
+	ms_none,
+	ms_mask,
+	ms_transcolor,
+	ms_lasso
+} mask_t;
+
+typedef enum
+{
+	cm_none,
+	cm_rle1
+} compress_t;
+
+typedef struct
+{
+	UWORD		w,h;
+	short		x,y;
+	UBYTE		nPlanes;
+	UBYTE		masking;
+	UBYTE		compression;
+	UBYTE		pad1;
+	UWORD		transparentColor;
+	UBYTE		xAspect,yAspect;
+	short		pageWidth,pageHeight;
+} bmhd_t;
+
+extern	bmhd_t	bmhd;						// will be in native byte order
+
+
+
+#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
+#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
+#define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
+#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
+#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
+#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
+
+
+bmhd_t  bmhd;
+
+int    Align (int l)
+{
+	if (l&1)
+		return l+1;
+	return l;
+}
+
+
+
+/*
+================
+LBMRLEdecompress
+
+Source must be evenly aligned!
+================
+*/
+byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
+{
+	int     count;
+	byte    b,rept;
+
+	count = 0;
+
+	do
+	{
+		rept = *source++;
+
+		if (rept > 0x80)
+		{
+			rept = (rept^0xff)+2;
+			b = *source++;
+			memset(unpacked,b,rept);
+			unpacked += rept;
+		}
+		else if (rept < 0x80)
+		{
+			rept++;
+			memcpy(unpacked,source,rept);
+			unpacked += rept;
+			source += rept;
+		}
+		else
+			rept = 0;               // rept of 0x80 is NOP
+
+		count += rept;
+
+	} while (count<bpwidth);
+
+	if (count>bpwidth)
+		Error ("Decompression exceeded width!\n");
+
+
+	return source;
+}
+
+
+/*
+=================
+LoadLBM
+=================
+*/
+void LoadLBM (char *filename, byte **picture, byte **palette)
+{
+	byte    *LBMbuffer, *picbuffer, *cmapbuffer;
+	int             y;
+	byte    *LBM_P, *LBMEND_P;
+	byte    *pic_p;
+	byte    *body_p;
+
+	int    formtype,formlength;
+	int    chunktype,chunklength;
+
+// qiet compiler warnings
+	picbuffer = NULL;
+	cmapbuffer = NULL;
+
+//
+// load the LBM
+//
+	LoadFile (filename, (void **)&LBMbuffer);
+
+//
+// parse the LBM header
+//
+	LBM_P = LBMbuffer;
+	if ( *(int *)LBMbuffer != LittleLong(FORMID) )
+	   Error ("No FORM ID at start of file!\n");
+
+	LBM_P += 4;
+	formlength = BigLong( *(int *)LBM_P );
+	LBM_P += 4;
+	LBMEND_P = LBM_P + Align(formlength);
+
+	formtype = LittleLong(*(int *)LBM_P);
+
+	if (formtype != ILBMID && formtype != PBMID)
+		Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
+		,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
+
+	LBM_P += 4;
+
+//
+// parse chunks
+//
+
+	while (LBM_P < LBMEND_P)
+	{
+		chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
+		LBM_P += 4;
+		chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
+		LBM_P += 4;
+
+		switch ( chunktype )
+		{
+		case BMHDID:
+			memcpy (&bmhd,LBM_P,sizeof(bmhd));
+			bmhd.w = BigShort(bmhd.w);
+			bmhd.h = BigShort(bmhd.h);
+			bmhd.x = BigShort(bmhd.x);
+			bmhd.y = BigShort(bmhd.y);
+			bmhd.pageWidth = BigShort(bmhd.pageWidth);
+			bmhd.pageHeight = BigShort(bmhd.pageHeight);
+			break;
+
+		case CMAPID:
+			cmapbuffer = malloc (768);
+			memset (cmapbuffer, 0, 768);
+			memcpy (cmapbuffer, LBM_P, chunklength);
+			break;
+
+		case BODYID:
+			body_p = LBM_P;
+
+			pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
+			if (formtype == PBMID)
+			{
+			//
+			// unpack PBM
+			//
+				for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
+				{
+					if (bmhd.compression == cm_rle1)
+						body_p = LBMRLEDecompress ((byte *)body_p
+						, pic_p , bmhd.w);
+					else if (bmhd.compression == cm_none)
+					{
+						memcpy (pic_p,body_p,bmhd.w);
+						body_p += Align(bmhd.w);
+					}
+				}
+
+			}
+			else
+			{
+			//
+			// unpack ILBM
+			//
+				Error ("%s is an interlaced LBM, not packed", filename);
+			}
+			break;
+		}
+
+		LBM_P += Align(chunklength);
+	}
+
+	free (LBMbuffer);
+
+	*picture = picbuffer;
+
+	if (palette)
+		*palette = cmapbuffer;
+}
+
+
+/*
+============================================================================
+
+							WRITE LBM
+
+============================================================================
+*/
+
+/*
+==============
+WriteLBMfile
+==============
+*/
+void WriteLBMfile (char *filename, byte *data,
+				   int width, int height, byte *palette)
+{
+	byte    *lbm, *lbmptr;
+	int    *formlength, *bmhdlength, *cmaplength, *bodylength;
+	int    length;
+	bmhd_t  basebmhd;
+
+	lbm = lbmptr = malloc (width*height+1000);
+
+//
+// start FORM
+//
+	*lbmptr++ = 'F';
+	*lbmptr++ = 'O';
+	*lbmptr++ = 'R';
+	*lbmptr++ = 'M';
+
+	formlength = (int*)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	*lbmptr++ = 'P';
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'M';
+	*lbmptr++ = ' ';
+
+//
+// write BMHD
+//
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'M';
+	*lbmptr++ = 'H';
+	*lbmptr++ = 'D';
+
+	bmhdlength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memset (&basebmhd,0,sizeof(basebmhd));
+	basebmhd.w = BigShort((short)width);
+	basebmhd.h = BigShort((short)height);
+	basebmhd.nPlanes = BigShort(8);
+	basebmhd.xAspect = BigShort(5);
+	basebmhd.yAspect = BigShort(6);
+	basebmhd.pageWidth = BigShort((short)width);
+	basebmhd.pageHeight = BigShort((short)height);
+
+	memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
+	lbmptr += sizeof(basebmhd);
+
+	length = lbmptr-(byte *)bmhdlength-4;
+	*bmhdlength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write CMAP
+//
+	*lbmptr++ = 'C';
+	*lbmptr++ = 'M';
+	*lbmptr++ = 'A';
+	*lbmptr++ = 'P';
+
+	cmaplength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memcpy (lbmptr,palette,768);
+	lbmptr += 768;
+
+	length = lbmptr-(byte *)cmaplength-4;
+	*cmaplength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write BODY
+//
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'O';
+	*lbmptr++ = 'D';
+	*lbmptr++ = 'Y';
+
+	bodylength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memcpy (lbmptr,data,width*height);
+	lbmptr += width*height;
+
+	length = lbmptr-(byte *)bodylength-4;
+	*bodylength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// done
+//
+	length = lbmptr-(byte *)formlength-4;
+	*formlength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write output file
+//
+	SaveFile (filename, lbm, lbmptr-lbm);
+	free (lbm);
+}
+
+
+/*
+============================================================================
+
+LOAD PCX
+
+============================================================================
+*/
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+
+/*
+==============
+LoadPCX
+==============
+*/
+void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
+{
+	byte	*raw;
+	pcx_t	*pcx;
+	int		x, y;
+	int		len;
+	int		dataByte, runLength;
+	byte	*out, *pix;
+
+	//
+	// load the file
+	//
+	len = LoadFile (filename, (void **)&raw);
+
+	//
+	// parse the PCX file
+	//
+	pcx = (pcx_t *)raw;
+	raw = &pcx->data;
+
+	pcx->xmin = LittleShort(pcx->xmin);
+	pcx->ymin = LittleShort(pcx->ymin);
+	pcx->xmax = LittleShort(pcx->xmax);
+	pcx->ymax = LittleShort(pcx->ymax);
+	pcx->hres = LittleShort(pcx->hres);
+	pcx->vres = LittleShort(pcx->vres);
+	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
+	pcx->palette_type = LittleShort(pcx->palette_type);
+
+	if (pcx->manufacturer != 0x0a
+		|| pcx->version != 5
+		|| pcx->encoding != 1
+		|| pcx->bits_per_pixel != 8
+		|| pcx->xmax >= 640
+		|| pcx->ymax >= 480)
+		Error ("Bad pcx file %s", filename);
+	
+	if (palette)
+	{
+		*palette = malloc(768);
+		memcpy (*palette, (byte *)pcx + len - 768, 768);
+	}
+
+	if (width)
+		*width = pcx->xmax+1;
+	if (height)
+		*height = pcx->ymax+1;
+
+	if (!pic)
+		return;
+
+	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
+	if (!out)
+		Error ("Skin_Cache: couldn't allocate");
+
+	*pic = out;
+
+	pix = out;
+
+	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
+	{
+		for (x=0 ; x<=pcx->xmax ; )
+		{
+			dataByte = *raw++;
+
+			if((dataByte & 0xC0) == 0xC0)
+			{
+				runLength = dataByte & 0x3F;
+				dataByte = *raw++;
+			}
+			else
+				runLength = 1;
+
+			while(runLength-- > 0)
+				pix[x++] = dataByte;
+		}
+
+	}
+
+	if ( raw - (byte *)pcx > len)
+		Error ("PCX file %s was malformed", filename);
+
+	free (pcx);
+}
+
+/* 
+============== 
+WritePCXfile 
+============== 
+*/ 
+void WritePCXfile (char *filename, byte *data, 
+				   int width, int height, byte *palette) 
+{
+	int		i, j, length;
+	pcx_t	*pcx;
+	byte		*pack;
+	  
+	pcx = malloc (width*height*2+1000);
+	memset (pcx, 0, sizeof(*pcx));
+
+	pcx->manufacturer = 0x0a;	// PCX id
+	pcx->version = 5;			// 256 color
+ 	pcx->encoding = 1;		// uncompressed
+	pcx->bits_per_pixel = 8;		// 256 color
+	pcx->xmin = 0;
+	pcx->ymin = 0;
+	pcx->xmax = LittleShort((short)(width-1));
+	pcx->ymax = LittleShort((short)(height-1));
+	pcx->hres = LittleShort((short)width);
+	pcx->vres = LittleShort((short)height);
+	pcx->color_planes = 1;		// chunky image
+	pcx->bytes_per_line = LittleShort((short)width);
+	pcx->palette_type = LittleShort(2);		// not a grey scale
+
+	// pack the image
+	pack = &pcx->data;
+	
+	for (i=0 ; i<height ; i++)
+	{
+		for (j=0 ; j<width ; j++)
+		{
+			if ( (*data & 0xc0) != 0xc0)
+				*pack++ = *data++;
+			else
+			{
+				*pack++ = 0xc1;
+				*pack++ = *data++;
+			}
+		}
+	}
+			
+	// write the palette
+	*pack++ = 0x0c;	// palette ID byte
+	for (i=0 ; i<768 ; i++)
+		*pack++ = *palette++;
+		
+// write output file 
+	length = pack - (byte *)pcx;
+	SaveFile (filename, pcx, length);
+
+	free (pcx);
+} 
+ 
+
+/*
+============================================================================
+
+LOAD IMAGE
+
+============================================================================
+*/
+
+/*
+==============
+Load256Image
+
+Will load either an lbm or pcx, depending on extension.
+Any of the return pointers can be NULL if you don't want them.
+==============
+*/
+void Load256Image (char *name, byte **pixels, byte **palette,
+				   int *width, int *height)
+{
+	char	ext[128];
+
+	ExtractFileExtension (name, ext);
+	if (!Q_strncasecmp (ext, "lbm", strlen(ext) ))
+	{
+		LoadLBM (name, pixels, palette);
+		if (width)
+			*width = bmhd.w;
+		if (height)
+			*height = bmhd.h;
+	}
+	else if (!Q_strncasecmp (ext, "pcx",strlen(ext)))
+	{
+		LoadPCX (name, pixels, palette, width, height);
+	}
+	else
+		Error ("%s doesn't have a known image extension", name);
+}
+
+
+/*
+==============
+Save256Image
+
+Will save either an lbm or pcx, depending on extension.
+==============
+*/
+void Save256Image (char *name, byte *pixels, byte *palette,
+				   int width, int height)
+{
+	char	ext[128];
+
+	ExtractFileExtension (name, ext);
+	if (!Q_strncasecmp (ext, "lbm",strlen(ext)))
+	{
+		WriteLBMfile (name, pixels, width, height, palette);
+	}
+	else if (!Q_strncasecmp (ext, "pcx",strlen(ext)))
+	{
+		WritePCXfile (name, pixels, width, height, palette);
+	}
+	else
+		Error ("%s doesn't have a known image extension", name);
+}
+
+
+
+
+/*
+============================================================================
+
+TARGA IMAGE
+
+============================================================================
+*/
+
+typedef struct _TargaHeader {
+	unsigned char 	id_length, colormap_type, image_type;
+	unsigned short	colormap_index, colormap_length;
+	unsigned char	colormap_size;
+	unsigned short	x_origin, y_origin, width, height;
+	unsigned char	pixel_size, attributes;
+} TargaHeader;
+
+int fgetLittleShort (FILE *f)
+{
+	byte	b1, b2;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+
+	return (short)(b1 + b2*256);
+}
+
+int fgetLittleLong (FILE *f)
+{
+	byte	b1, b2, b3, b4;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+	b3 = fgetc(f);
+	b4 = fgetc(f);
+
+	return b1 + (b2<<8) + (b3<<16) + (b4<<24);
+}
+
+
+/*
+=============
+LoadTGA
+=============
+*/
+void LoadTGA (char *name, byte **pixels, int *width, int *height)
+{
+	int				columns, rows, numPixels;
+	byte			*pixbuf;
+	int				row, column;
+	FILE			*fin;
+	byte			*targa_rgba;
+	TargaHeader		targa_header;
+
+	fin = fopen (name, "rb");
+	if (!fin)
+		Error ("Couldn't read %s", name);
+
+	targa_header.id_length = fgetc(fin);
+	targa_header.colormap_type = fgetc(fin);
+	targa_header.image_type = fgetc(fin);
+	
+	targa_header.colormap_index = fgetLittleShort(fin);
+	targa_header.colormap_length = fgetLittleShort(fin);
+	targa_header.colormap_size = fgetc(fin);
+	targa_header.x_origin = fgetLittleShort(fin);
+	targa_header.y_origin = fgetLittleShort(fin);
+	targa_header.width = fgetLittleShort(fin);
+	targa_header.height = fgetLittleShort(fin);
+	targa_header.pixel_size = fgetc(fin);
+	targa_header.attributes = fgetc(fin);
+
+	if (targa_header.image_type!=2 
+		&& targa_header.image_type!=10) 
+		Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
+
+	if (targa_header.colormap_type !=0 
+		|| (targa_header.pixel_size!=32 && targa_header.pixel_size!=24))
+		Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+
+	columns = targa_header.width;
+	rows = targa_header.height;
+	numPixels = columns * rows;
+
+	if (width)
+		*width = columns;
+	if (height)
+		*height = rows;
+	targa_rgba = malloc(numPixels*4);
+	*pixels = targa_rgba;
+
+	if (targa_header.id_length != 0)
+		fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
+	
+	if (targa_header.image_type==2) {  // Uncompressed, RGB images
+		for(row=rows-1; row>=0; row--) {
+			pixbuf = targa_rgba + row*columns*4;
+			for(column=0; column<columns; column++) {
+				unsigned char red,green,blue,alphabyte;
+				switch (targa_header.pixel_size) {
+					case 24:
+							
+							blue = getc(fin);
+							green = getc(fin);
+							red = getc(fin);
+							*pixbuf++ = red;
+							*pixbuf++ = green;
+							*pixbuf++ = blue;
+							*pixbuf++ = 255;
+							break;
+					case 32:
+							blue = getc(fin);
+							green = getc(fin);
+							red = getc(fin);
+							alphabyte = getc(fin);
+							*pixbuf++ = red;
+							*pixbuf++ = green;
+							*pixbuf++ = blue;
+							*pixbuf++ = alphabyte;
+							break;
+				}
+			}
+		}
+	}
+	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
+		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
+		for(row=rows-1; row>=0; row--) {
+			pixbuf = targa_rgba + row*columns*4;
+			for(column=0; column<columns; ) {
+				packetHeader=getc(fin);
+				packetSize = 1 + (packetHeader & 0x7f);
+				if (packetHeader & 0x80) {        // run-length packet
+					switch (targa_header.pixel_size) {
+						case 24:
+								blue = getc(fin);
+								green = getc(fin);
+								red = getc(fin);
+								alphabyte = 255;
+								break;
+						case 32:
+								blue = getc(fin);
+								green = getc(fin);
+								red = getc(fin);
+								alphabyte = getc(fin);
+								break;
+					}
+	
+					for(j=0;j<packetSize;j++) {
+						*pixbuf++=red;
+						*pixbuf++=green;
+						*pixbuf++=blue;
+						*pixbuf++=alphabyte;
+						column++;
+						if (column==columns) { // run spans across rows
+							column=0;
+							if (row>0)
+								row--;
+							else
+								goto breakOut;
+							pixbuf = targa_rgba + row*columns*4;
+						}
+					}
+				}
+				else {                            // non run-length packet
+					for(j=0;j<packetSize;j++) {
+						switch (targa_header.pixel_size) {
+							case 24:
+									blue = getc(fin);
+									green = getc(fin);
+									red = getc(fin);
+									*pixbuf++ = red;
+									*pixbuf++ = green;
+									*pixbuf++ = blue;
+									*pixbuf++ = 255;
+									break;
+							case 32:
+									blue = getc(fin);
+									green = getc(fin);
+									red = getc(fin);
+									alphabyte = getc(fin);
+									*pixbuf++ = red;
+									*pixbuf++ = green;
+									*pixbuf++ = blue;
+									*pixbuf++ = alphabyte;
+									break;
+						}
+						column++;
+						if (column==columns) { // pixel packet run spans across rows
+							column=0;
+							if (row>0)
+								row--;
+							else
+								goto breakOut;
+							pixbuf = targa_rgba + row*columns*4;
+						}						
+					}
+				}
+			}
+			breakOut:;
+		}
+	}
+
+	// vertically flipped
+	if ( (targa_header.attributes & (1<<5)) ) {
+		int flip;
+		for (row = 0; row < .5f * rows; row++)
+		{
+			for (column = 0; column < columns; column++)
+			{
+				flip = *( (int*)targa_rgba + row * columns + column);
+				*( (int*)targa_rgba + row * columns + column) = *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column );
+				*( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column ) = flip;
+			}
+		}
+	}
+	
+	fclose(fin);
+}
diff --git a/tools/quake2/common/lbmlib.h b/tools/quake2/common/lbmlib.h
index b2055225..b51017da 100644
--- a/tools/quake2/common/lbmlib.h
+++ b/tools/quake2/common/lbmlib.h
@@ -1,38 +1,38 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// piclib.h
-
-
-void LoadLBM (char *filename, byte **picture, byte **palette);
-void WriteLBMfile (char *filename, byte *data, int width, int height
-	, byte *palette);
-void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
-void WritePCXfile (char *filename, byte *data, int width, int height
-	, byte *palette);
-
-// loads / saves either lbm or pcx, depending on extension
-void Load256Image (char *name, byte **pixels, byte **palette,
-				   int *width, int *height);
-void Save256Image (char *name, byte *pixels, byte *palette,
-				   int width, int height);
-
-
-void LoadTGA (char *filename, byte **pixels, int *width, int *height);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// piclib.h
+
+
+void LoadLBM (char *filename, byte **picture, byte **palette);
+void WriteLBMfile (char *filename, byte *data, int width, int height
+	, byte *palette);
+void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
+void WritePCXfile (char *filename, byte *data, int width, int height
+	, byte *palette);
+
+// loads / saves either lbm or pcx, depending on extension
+void Load256Image (char *name, byte **pixels, byte **palette,
+				   int *width, int *height);
+void Save256Image (char *name, byte *pixels, byte *palette,
+				   int width, int height);
+
+
+void LoadTGA (char *filename, byte **pixels, int *width, int *height);
diff --git a/tools/quake2/common/mathlib.c b/tools/quake2/common/mathlib.c
index 7c06a477..84ebb2d9 100644
--- a/tools/quake2/common/mathlib.c
+++ b/tools/quake2/common/mathlib.c
@@ -1,172 +1,172 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// mathlib.c -- math primitives
-
-#include "cmdlib.h"
-#include "mathlib.h"
-
-vec3_t vec3_origin = {0,0,0};
-
-
-double VectorLength(vec3_t v)
-{
-	int		i;
-	double	length;
-	
-	length = 0;
-	for (i=0 ; i< 3 ; i++)
-		length += v[i]*v[i];
-	length = sqrt (length);		// FIXME
-
-	return length;
-}
-
-qboolean VectorCompare (vec3_t v1, vec3_t v2)
-{
-	int		i;
-	
-	for (i=0 ; i<3 ; i++)
-		if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
-			return false;
-			
-	return true;
-}
-
-vec_t Q_rint (vec_t in)
-{
-	return floor (in + 0.5);
-}
-
-void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc)
-{
-	vc[0] = va[0] + scale*vb[0];
-	vc[1] = va[1] + scale*vb[1];
-	vc[2] = va[2] + scale*vb[2];
-}
-
-void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
-{
-	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
-	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
-	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
-}
-
-vec_t _DotProduct (vec3_t v1, vec3_t v2)
-{
-	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
-}
-
-void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
-{
-	out[0] = va[0]-vb[0];
-	out[1] = va[1]-vb[1];
-	out[2] = va[2]-vb[2];
-}
-
-void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
-{
-	out[0] = va[0]+vb[0];
-	out[1] = va[1]+vb[1];
-	out[2] = va[2]+vb[2];
-}
-
-void _VectorCopy (vec3_t in, vec3_t out)
-{
-	out[0] = in[0];
-	out[1] = in[1];
-	out[2] = in[2];
-}
-
-void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
-{
-	out[0] = v[0] * scale;
-	out[1] = v[1] * scale;
-	out[2] = v[2] * scale;
-}
-
-vec_t VectorNormalize (vec3_t in, vec3_t out)
-{
-	vec_t	length, ilength;
-
-	length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
-	if (length == 0)
-	{
-		VectorClear (out);
-		return 0;
-	}
-
-	ilength = 1.0/length;
-	out[0] = in[0]*ilength;
-	out[1] = in[1]*ilength;
-	out[2] = in[2]*ilength;
-
-	return length;
-}
-
-vec_t ColorNormalize (vec3_t in, vec3_t out)
-{
-	float	max, scale;
-
-	max = in[0];
-	if (in[1] > max)
-		max = in[1];
-	if (in[2] > max)
-		max = in[2];
-
-	if (max == 0)
-		return 0;
-
-	scale = 1.0 / max;
-
-	VectorScale (in, scale, out);
-
-	return max;
-}
-
-
-
-void VectorInverse (vec3_t v)
-{
-	v[0] = -v[0];
-	v[1] = -v[1];
-	v[2] = -v[2];
-}
-
-void ClearBounds (vec3_t mins, vec3_t maxs)
-{
-	mins[0] = mins[1] = mins[2] = 99999;
-	maxs[0] = maxs[1] = maxs[2] = -99999;
-}
-
-void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
-{
-	int		i;
-	vec_t	val;
-
-	for (i=0 ; i<3 ; i++)
-	{
-		val = v[i];
-		if (val < mins[i])
-			mins[i] = val;
-		if (val > maxs[i])
-			maxs[i] = val;
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// mathlib.c -- math primitives
+
+#include "cmdlib.h"
+#include "mathlib.h"
+
+vec3_t vec3_origin = {0,0,0};
+
+
+double VectorLength(vec3_t v)
+{
+	int		i;
+	double	length;
+	
+	length = 0;
+	for (i=0 ; i< 3 ; i++)
+		length += v[i]*v[i];
+	length = sqrt (length);		// FIXME
+
+	return length;
+}
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2)
+{
+	int		i;
+	
+	for (i=0 ; i<3 ; i++)
+		if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
+			return false;
+			
+	return true;
+}
+
+vec_t Q_rint (vec_t in)
+{
+	return floor (in + 0.5);
+}
+
+void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc)
+{
+	vc[0] = va[0] + scale*vb[0];
+	vc[1] = va[1] + scale*vb[1];
+	vc[2] = va[2] + scale*vb[2];
+}
+
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
+{
+	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
+	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
+	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+vec_t _DotProduct (vec3_t v1, vec3_t v2)
+{
+	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+}
+
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
+{
+	out[0] = va[0]-vb[0];
+	out[1] = va[1]-vb[1];
+	out[2] = va[2]-vb[2];
+}
+
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
+{
+	out[0] = va[0]+vb[0];
+	out[1] = va[1]+vb[1];
+	out[2] = va[2]+vb[2];
+}
+
+void _VectorCopy (vec3_t in, vec3_t out)
+{
+	out[0] = in[0];
+	out[1] = in[1];
+	out[2] = in[2];
+}
+
+void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
+{
+	out[0] = v[0] * scale;
+	out[1] = v[1] * scale;
+	out[2] = v[2] * scale;
+}
+
+vec_t VectorNormalize (vec3_t in, vec3_t out)
+{
+	vec_t	length, ilength;
+
+	length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
+	if (length == 0)
+	{
+		VectorClear (out);
+		return 0;
+	}
+
+	ilength = 1.0/length;
+	out[0] = in[0]*ilength;
+	out[1] = in[1]*ilength;
+	out[2] = in[2]*ilength;
+
+	return length;
+}
+
+vec_t ColorNormalize (vec3_t in, vec3_t out)
+{
+	float	max, scale;
+
+	max = in[0];
+	if (in[1] > max)
+		max = in[1];
+	if (in[2] > max)
+		max = in[2];
+
+	if (max == 0)
+		return 0;
+
+	scale = 1.0 / max;
+
+	VectorScale (in, scale, out);
+
+	return max;
+}
+
+
+
+void VectorInverse (vec3_t v)
+{
+	v[0] = -v[0];
+	v[1] = -v[1];
+	v[2] = -v[2];
+}
+
+void ClearBounds (vec3_t mins, vec3_t maxs)
+{
+	mins[0] = mins[1] = mins[2] = 99999;
+	maxs[0] = maxs[1] = maxs[2] = -99999;
+}
+
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
+{
+	int		i;
+	vec_t	val;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		val = v[i];
+		if (val < mins[i])
+			mins[i] = val;
+		if (val > maxs[i])
+			maxs[i] = val;
+	}
+}
diff --git a/tools/quake2/common/mathlib.h b/tools/quake2/common/mathlib.h
index f6d13483..dc350ba3 100644
--- a/tools/quake2/common/mathlib.h
+++ b/tools/quake2/common/mathlib.h
@@ -1,75 +1,75 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef __MATHLIB__
-#define __MATHLIB__
-
-// mathlib.h
-
-#include <math.h>
-
-#ifdef DOUBLEVEC_T
-typedef double vec_t;
-#else
-typedef float vec_t;
-#endif
-typedef vec_t vec3_t[3];
-
-#define	SIDE_FRONT		0
-#define	SIDE_ON			2
-#define	SIDE_BACK		1
-#define	SIDE_CROSS		-2
-
-#define	Q_PI	3.14159265358979323846
-
-extern vec3_t vec3_origin;
-
-#define	EQUAL_EPSILON	0.001
-
-qboolean VectorCompare (vec3_t v1, vec3_t v2);
-
-#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
-#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
-#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
-#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
-#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
-#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
-#define	VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
-
-vec_t Q_rint (vec_t in);
-vec_t _DotProduct (vec3_t v1, vec3_t v2);
-void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
-void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
-void _VectorCopy (vec3_t in, vec3_t out);
-void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
-
-double VectorLength(vec3_t v);
-
-void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc);
-
-void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
-vec_t VectorNormalize (vec3_t in, vec3_t out);
-vec_t ColorNormalize (vec3_t in, vec3_t out);
-void VectorInverse (vec3_t v);
-
-void ClearBounds (vec3_t mins, vec3_t maxs);
-void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#ifndef __MATHLIB__
+#define __MATHLIB__
+
+// mathlib.h
+
+#include <math.h>
+
+#ifdef DOUBLEVEC_T
+typedef double vec_t;
+#else
+typedef float vec_t;
+#endif
+typedef vec_t vec3_t[3];
+
+#define	SIDE_FRONT		0
+#define	SIDE_ON			2
+#define	SIDE_BACK		1
+#define	SIDE_CROSS		-2
+
+#define	Q_PI	3.14159265358979323846
+
+extern vec3_t vec3_origin;
+
+#define	EQUAL_EPSILON	0.001
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2);
+
+#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
+#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
+#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
+#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
+#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
+#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
+#define	VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
+
+vec_t Q_rint (vec_t in);
+vec_t _DotProduct (vec3_t v1, vec3_t v2);
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorCopy (vec3_t in, vec3_t out);
+void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
+
+double VectorLength(vec3_t v);
+
+void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc);
+
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
+vec_t VectorNormalize (vec3_t in, vec3_t out);
+vec_t ColorNormalize (vec3_t in, vec3_t out);
+void VectorInverse (vec3_t v);
+
+void ClearBounds (vec3_t mins, vec3_t maxs);
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
+
+#endif
diff --git a/tools/quake2/common/path_init.c b/tools/quake2/common/path_init.c
index 6e01d3fd..bf731c99 100644
--- a/tools/quake2/common/path_init.c
+++ b/tools/quake2/common/path_init.c
@@ -1,400 +1,400 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-
-/* marker */
-#define PATH_INIT_C
-
-#if defined( __linux__ ) || defined( __APPLE__ )
-	#define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
-	#include <unistd.h>
-	#include <pwd.h>
-	#include <limits.h>
-#endif
-
-
-/* dependencies */
-#include "cmdlib.h"
-#include "inout.h"
-
-
-
-/* path support */
-#define MAX_BASE_PATHS	10
-#define MAX_GAME_PATHS	10
-
-char					*homePath;
-char					installPath[ MAX_OS_PATH ];
-
-int						numBasePaths;
-char					*basePaths[ MAX_BASE_PATHS ];
-int						numGamePaths;
-char					*gamePaths[ MAX_GAME_PATHS ];
-
-/*
-some of this code is based off the original q3map port from loki
-and finds various paths. moved here from bsp.c for clarity.
-*/
-
-/*
-PathLokiGetHomeDir()
-gets the user's home dir (for ~/.q3a)
-*/
-
-char *LokiGetHomeDir( void )
-{
-	#ifndef Q_UNIX
-		return NULL;
-	#else
-		char			*home;
-		uid_t			id;
-		struct passwd	*pwd;
-		
-		
-		/* get the home environment variable */
-		home = getenv( "HOME" );
-		if( home == NULL )
-		{
-			/* do some more digging */
-			id = getuid();
-			setpwent();
-			while( (pwd = getpwent()) != NULL )
-			{
-				if( pwd->pw_uid == id )
-				{
-					home = pwd->pw_dir;
-					break;
-				}
-			}
-			endpwent();
-		}
-		
-		/* return it */
-		return home;
-	#endif
-}
-
-
-
-/*
-PathLokiInitPaths()
-initializes some paths on linux/os x
-*/
-
-void LokiInitPaths( char *argv0 )
-{
-	#ifndef Q_UNIX
-		/* this is kinda crap, but hey */
-		strcpy( installPath, "../" );
-	#else
-		char		temp[ MAX_OS_PATH ];
-		char		*home;
-		char		*path;
-		char		*last;
-		qboolean	found;
-		
-		
-		/* get home dir */
-		home = LokiGetHomeDir();
-		if( home == NULL )
-			home = ".";
-		
-		/* do some path divining */
-		strcpy( temp, argv0 );
-		if( strrchr( temp, '/' ) )
-			argv0 = strrchr( argv0, '/' ) + 1;
-		else
-		{
-			/* get path environment variable */
-			path = getenv( "PATH" );
-			
-			/* minor setup */
-			last[ 0 ] = path[ 0 ];
-			last[ 1 ] = '\0';
-			found = false;
-			
-			/* go through each : segment of path */
-			while( last[ 0 ] != '\0' && found == false )
-			{
-				/* null out temp */
-				temp[ 0 ] = '\0';
-				
-				/* find next chunk */
-				last = strchr( path, ':' );
-				if( last == NULL )
-					last = path + strlen( path );
-				
-				/* found home dir candidate */
-				if( *path == '~' )
-				{
-					strcpy( temp, home );
-					path++;
-				}
-				
-				/* concatenate */
-				if( last > (path + 1) )
-				{
-					strncat( temp, path, (last - path) );
-					strcat( temp, "/" );
-				}
-				strcat( temp, "./" );
-				strcat( temp, argv0 );
-				
-				/* verify the path */
-				if( access( temp, X_OK ) == 0 )
-					found++;
-				path = last + 1;
-			}
-		}
-		
-		/* flake */
-		if( realpath( temp, installPath ) )
-		{
-			/* q3map is in "tools/" */
-			*(strrchr( installPath, '/' )) = '\0';
-			*(strrchr( installPath, '/' ) + 1) = '\0';
-		}
-		
-		/* set home path */
-		homePath = home;
-	#endif
-}
-
-
-
-/*
-CleanPath() - ydnar
-cleans a dos path \ -> /
-*/
-
-void CleanPath( char *path )
-{
-	while( *path )
-	{
-		if( *path == '\\' )
-			*path = '/';
-		path++;
-	}
-}
-
-/*
-AddBasePath() - ydnar
-adds a base path to the list
-*/
-
-void AddBasePath( char *path )
-{
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
-		return;
-	
-	/* add it to the list */
-	basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
-	strcpy( basePaths[ numBasePaths ], path );
-	CleanPath( basePaths[ numBasePaths ] );
-	numBasePaths++;
-}
-
-
-
-/*
-AddHomeBasePath() - ydnar
-adds a base path to the beginning of the list, prefixed by ~/
-*/
-
-void AddHomeBasePath( char *path )
-{
-	#ifdef Q_UNIX
-		int		i;
-		char	temp[ MAX_OS_PATH ];
-
-
-		/* dummy check */
-		if( path == NULL || path[ 0 ] == '\0' )
-			return;
-
-		/* make a hole */
-		for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
-			basePaths[ i + 1 ] = basePaths[ i ];
-		
-		/* concatenate home dir and path */
-		sprintf( temp, "%s/%s", homePath, path );
-		
-		/* add it to the list */
-		basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
-		strcpy( basePaths[ 0 ], temp );
-		CleanPath( basePaths[ 0 ] );
-		numBasePaths++;
-	#endif
-}
-
-
-
-/*
-AddGamePath() - ydnar
-adds a game path to the list
-*/
-
-void AddGamePath( char *path )
-{
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
-		return;
-	
-	/* add it to the list */
-	gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
-	strcpy( gamePaths[ numGamePaths ], path );
-	CleanPath( gamePaths[ numGamePaths ] );
-	numGamePaths++;
-}
-
-
-
-
-/*
-InitPaths() - ydnar
-cleaned up some of the path initialization code from bsp.c
-will remove any arguments it uses
-*/
-
-void InitPaths( int *argc, char **argv )
-{
-	int		i, j, k, len, len2;
-	char	temp[ MAX_OS_PATH ];
-  char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
-
-  strcpy(gamePath, "baseq2");
-  strcpy(game_magic, "quake");
-  strcpy(homeBasePath, ".quake2");
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
-	
-	/* get the install path for backup */
-	LokiInitPaths( argv[ 0 ] );
-
-	/* set game to default (q3a) */
-	numBasePaths = 0;
-	numGamePaths = 0;
-
-	/* parse through the arguments and extract those relevant to paths */
-	for( i = 0; i < *argc; i++ )
-	{
-		/* check for null */
-		if( argv[ i ] == NULL )
-			continue;
-
-		/* -fs_basepath */
-		if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
-		{
-			if( ++i >= *argc )
-				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
-			argv[ i - 1 ] = NULL;
-			AddBasePath( argv[ i ] );
-			argv[ i ] = NULL;
-		}
-
-	}
-
-	/* remove processed arguments */
-	for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
-	{
-		for( j; j < *argc && argv[ j ] == NULL; j++ );
-		argv[ i ] = argv[ j ];
-		if( argv[ i ] != NULL )
-			k++;
-	}
-	*argc = k;
-
-	/* add standard game path */
-  AddGamePath( gamePath );
-
-	/* if there is no base path set, figure it out */
-	if( numBasePaths == 0 )
-	{
-		/* this is another crappy replacement for SetQdirFromPath() */
-    len2 = strlen( game_magic );
-		for( i = 0; i < *argc && numBasePaths == 0; i++ )
-		{
-			/* extract the arg */
-			strcpy( temp, argv[ i ] );
-			CleanPath( temp );
-			len = strlen( temp );
-			Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
-
-			/* this is slow, but only done once */
-			for( j = 0; j < (len - len2); j++ )
-			{
-				/* check for the game's magic word */
-				if( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 )
-				{
-					/* now find the next slash and nuke everything after it */
-					while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
-					temp[ j ] = '\0';
-
-					/* add this as a base path */
-					AddBasePath( temp );
-					break;
-				}
-			}
-		}
-
-		/* add install path */
-		if( numBasePaths == 0 )
-			AddBasePath( installPath );
-
-		/* check again */
-		if( numBasePaths == 0 )
-			Error( "Failed to find a valid base path." );
-	}
-
-	/* this only affects unix */
-	AddHomeBasePath( homeBasePath );
-
-	/* initialize vfs paths */
-	if( numBasePaths > MAX_BASE_PATHS )
-		numBasePaths = MAX_BASE_PATHS;
-	if( numGamePaths > MAX_GAME_PATHS )
-		numGamePaths = MAX_GAME_PATHS;
-	
-	/* walk the list of game paths */
-	//for( j = 0; j < numGamePaths; j++ )
-	//{
-		/* walk the list of base paths */
-	//	for( i = 0; i < numBasePaths; i++ )
-	//	{
-			/* create a full path and initialize it */
-	//		sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
-	//		vfsInitDirectory( temp );
-	//	}
-	//}
-	
-	/* done */
-	Sys_Printf( "\n" );
-}
-
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+
+/* marker */
+#define PATH_INIT_C
+
+#if defined( __linux__ ) || defined( __APPLE__ )
+	#define Q_UNIX
+#endif
+
+#ifdef Q_UNIX
+	#include <unistd.h>
+	#include <pwd.h>
+	#include <limits.h>
+#endif
+
+
+/* dependencies */
+#include "cmdlib.h"
+#include "inout.h"
+
+
+
+/* path support */
+#define MAX_BASE_PATHS	10
+#define MAX_GAME_PATHS	10
+
+char					*homePath;
+char					installPath[ MAX_OS_PATH ];
+
+int						numBasePaths;
+char					*basePaths[ MAX_BASE_PATHS ];
+int						numGamePaths;
+char					*gamePaths[ MAX_GAME_PATHS ];
+
+/*
+some of this code is based off the original q3map port from loki
+and finds various paths. moved here from bsp.c for clarity.
+*/
+
+/*
+PathLokiGetHomeDir()
+gets the user's home dir (for ~/.q3a)
+*/
+
+char *LokiGetHomeDir( void )
+{
+	#ifndef Q_UNIX
+		return NULL;
+	#else
+		char			*home;
+		uid_t			id;
+		struct passwd	*pwd;
+		
+		
+		/* get the home environment variable */
+		home = getenv( "HOME" );
+		if( home == NULL )
+		{
+			/* do some more digging */
+			id = getuid();
+			setpwent();
+			while( (pwd = getpwent()) != NULL )
+			{
+				if( pwd->pw_uid == id )
+				{
+					home = pwd->pw_dir;
+					break;
+				}
+			}
+			endpwent();
+		}
+		
+		/* return it */
+		return home;
+	#endif
+}
+
+
+
+/*
+PathLokiInitPaths()
+initializes some paths on linux/os x
+*/
+
+void LokiInitPaths( char *argv0 )
+{
+	#ifndef Q_UNIX
+		/* this is kinda crap, but hey */
+		strcpy( installPath, "../" );
+	#else
+		char		temp[ MAX_OS_PATH ];
+		char		*home;
+		char		*path;
+		char		*last;
+		qboolean	found;
+		
+		
+		/* get home dir */
+		home = LokiGetHomeDir();
+		if( home == NULL )
+			home = ".";
+		
+		/* do some path divining */
+		strcpy( temp, argv0 );
+		if( strrchr( temp, '/' ) )
+			argv0 = strrchr( argv0, '/' ) + 1;
+		else
+		{
+			/* get path environment variable */
+			path = getenv( "PATH" );
+			
+			/* minor setup */
+			last[ 0 ] = path[ 0 ];
+			last[ 1 ] = '\0';
+			found = false;
+			
+			/* go through each : segment of path */
+			while( last[ 0 ] != '\0' && found == false )
+			{
+				/* null out temp */
+				temp[ 0 ] = '\0';
+				
+				/* find next chunk */
+				last = strchr( path, ':' );
+				if( last == NULL )
+					last = path + strlen( path );
+				
+				/* found home dir candidate */
+				if( *path == '~' )
+				{
+					strcpy( temp, home );
+					path++;
+				}
+				
+				/* concatenate */
+				if( last > (path + 1) )
+				{
+					strncat( temp, path, (last - path) );
+					strcat( temp, "/" );
+				}
+				strcat( temp, "./" );
+				strcat( temp, argv0 );
+				
+				/* verify the path */
+				if( access( temp, X_OK ) == 0 )
+					found++;
+				path = last + 1;
+			}
+		}
+		
+		/* flake */
+		if( realpath( temp, installPath ) )
+		{
+			/* q3map is in "tools/" */
+			*(strrchr( installPath, '/' )) = '\0';
+			*(strrchr( installPath, '/' ) + 1) = '\0';
+		}
+		
+		/* set home path */
+		homePath = home;
+	#endif
+}
+
+
+
+/*
+CleanPath() - ydnar
+cleans a dos path \ -> /
+*/
+
+void CleanPath( char *path )
+{
+	while( *path )
+	{
+		if( *path == '\\' )
+			*path = '/';
+		path++;
+	}
+}
+
+/*
+AddBasePath() - ydnar
+adds a base path to the list
+*/
+
+void AddBasePath( char *path )
+{
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
+		return;
+	
+	/* add it to the list */
+	basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
+	strcpy( basePaths[ numBasePaths ], path );
+	CleanPath( basePaths[ numBasePaths ] );
+	numBasePaths++;
+}
+
+
+
+/*
+AddHomeBasePath() - ydnar
+adds a base path to the beginning of the list, prefixed by ~/
+*/
+
+void AddHomeBasePath( char *path )
+{
+	#ifdef Q_UNIX
+		int		i;
+		char	temp[ MAX_OS_PATH ];
+
+
+		/* dummy check */
+		if( path == NULL || path[ 0 ] == '\0' )
+			return;
+
+		/* make a hole */
+		for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
+			basePaths[ i + 1 ] = basePaths[ i ];
+		
+		/* concatenate home dir and path */
+		sprintf( temp, "%s/%s", homePath, path );
+		
+		/* add it to the list */
+		basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
+		strcpy( basePaths[ 0 ], temp );
+		CleanPath( basePaths[ 0 ] );
+		numBasePaths++;
+	#endif
+}
+
+
+
+/*
+AddGamePath() - ydnar
+adds a game path to the list
+*/
+
+void AddGamePath( char *path )
+{
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
+		return;
+	
+	/* add it to the list */
+	gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
+	strcpy( gamePaths[ numGamePaths ], path );
+	CleanPath( gamePaths[ numGamePaths ] );
+	numGamePaths++;
+}
+
+
+
+
+/*
+InitPaths() - ydnar
+cleaned up some of the path initialization code from bsp.c
+will remove any arguments it uses
+*/
+
+void InitPaths( int *argc, char **argv )
+{
+	int		i, j, k, len, len2;
+	char	temp[ MAX_OS_PATH ];
+  char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
+
+  strcpy(gamePath, "baseq2");
+  strcpy(game_magic, "quake");
+  strcpy(homeBasePath, ".quake2");
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
+	
+	/* get the install path for backup */
+	LokiInitPaths( argv[ 0 ] );
+
+	/* set game to default (q3a) */
+	numBasePaths = 0;
+	numGamePaths = 0;
+
+	/* parse through the arguments and extract those relevant to paths */
+	for( i = 0; i < *argc; i++ )
+	{
+		/* check for null */
+		if( argv[ i ] == NULL )
+			continue;
+
+		/* -fs_basepath */
+		if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
+		{
+			if( ++i >= *argc )
+				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+			argv[ i - 1 ] = NULL;
+			AddBasePath( argv[ i ] );
+			argv[ i ] = NULL;
+		}
+
+	}
+
+	/* remove processed arguments */
+	for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
+	{
+		for( j; j < *argc && argv[ j ] == NULL; j++ );
+		argv[ i ] = argv[ j ];
+		if( argv[ i ] != NULL )
+			k++;
+	}
+	*argc = k;
+
+	/* add standard game path */
+  AddGamePath( gamePath );
+
+	/* if there is no base path set, figure it out */
+	if( numBasePaths == 0 )
+	{
+		/* this is another crappy replacement for SetQdirFromPath() */
+    len2 = strlen( game_magic );
+		for( i = 0; i < *argc && numBasePaths == 0; i++ )
+		{
+			/* extract the arg */
+			strcpy( temp, argv[ i ] );
+			CleanPath( temp );
+			len = strlen( temp );
+			Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
+
+			/* this is slow, but only done once */
+			for( j = 0; j < (len - len2); j++ )
+			{
+				/* check for the game's magic word */
+				if( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 )
+				{
+					/* now find the next slash and nuke everything after it */
+					while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
+					temp[ j ] = '\0';
+
+					/* add this as a base path */
+					AddBasePath( temp );
+					break;
+				}
+			}
+		}
+
+		/* add install path */
+		if( numBasePaths == 0 )
+			AddBasePath( installPath );
+
+		/* check again */
+		if( numBasePaths == 0 )
+			Error( "Failed to find a valid base path." );
+	}
+
+	/* this only affects unix */
+	AddHomeBasePath( homeBasePath );
+
+	/* initialize vfs paths */
+	if( numBasePaths > MAX_BASE_PATHS )
+		numBasePaths = MAX_BASE_PATHS;
+	if( numGamePaths > MAX_GAME_PATHS )
+		numGamePaths = MAX_GAME_PATHS;
+	
+	/* walk the list of game paths */
+	//for( j = 0; j < numGamePaths; j++ )
+	//{
+		/* walk the list of base paths */
+	//	for( i = 0; i < numBasePaths; i++ )
+	//	{
+			/* create a full path and initialize it */
+	//		sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
+	//		vfsInitDirectory( temp );
+	//	}
+	//}
+	
+	/* done */
+	Sys_Printf( "\n" );
+}
+
+
+
+
diff --git a/tools/quake2/common/polylib.c b/tools/quake2/common/polylib.c
index 47b2007e..6639d241 100644
--- a/tools/quake2/common/polylib.c
+++ b/tools/quake2/common/polylib.c
@@ -1,642 +1,642 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "polylib.h"
-
-
-extern int numthreads;
-
-// counters are only bumped when running single threaded,
-// because they are an awefull coherence problem
-int	c_active_windings;
-int	c_peak_windings;
-int	c_winding_allocs;
-int	c_winding_points;
-
-#define	BOGUS_RANGE	8192
-
-void pw(winding_t *w)
-{
-	int		i;
-	for (i=0 ; i<w->numpoints ; i++)
-		printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
-}
-
-
-/*
-=============
-AllocWinding
-=============
-*/
-winding_t	*AllocWinding (int points)
-{
-	winding_t	*w;
-	int			s;
-
-	if (numthreads == 1)
-	{
-		c_winding_allocs++;
-		c_winding_points += points;
-		c_active_windings++;
-		if (c_active_windings > c_peak_windings)
-			c_peak_windings = c_active_windings;
-	}
-	s = sizeof(vec_t)*3*points + sizeof(int);
-	w = malloc (s);
-	memset (w, 0, s); 
-	return w;
-}
-
-void FreeWinding (winding_t *w)
-{
-	if (*(unsigned *)w == 0xdeaddead)
-		Error ("FreeWinding: freed a freed winding");
-	*(unsigned *)w = 0xdeaddead;
-
-	if (numthreads == 1)
-		c_active_windings--;
-	free (w);
-}
-
-/*
-============
-RemoveColinearPoints
-============
-*/
-int	c_removed;
-
-void	RemoveColinearPoints (winding_t *w)
-{
-	int		i, j, k;
-	vec3_t	v1, v2;
-	int		nump;
-	vec3_t	p[MAX_POINTS_ON_WINDING];
-
-	nump = 0;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		j = (i+1)%w->numpoints;
-		k = (i+w->numpoints-1)%w->numpoints;
-		VectorSubtract (w->p[j], w->p[i], v1);
-		VectorSubtract (w->p[i], w->p[k], v2);
-		VectorNormalize(v1,v1);
-		VectorNormalize(v2,v2);
-		if (DotProduct(v1, v2) < 0.999)
-		{
-			VectorCopy (w->p[i], p[nump]);
-			nump++;
-		}
-	}
-
-	if (nump == w->numpoints)
-		return;
-
-	if (numthreads == 1)
-		c_removed += w->numpoints - nump;
-	w->numpoints = nump;
-	memcpy (w->p, p, nump*sizeof(p[0]));
-}
-
-/*
-============
-WindingPlane
-============
-*/
-void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
-{
-	vec3_t	v1, v2;
-
-	VectorSubtract (w->p[1], w->p[0], v1);
-	VectorSubtract (w->p[2], w->p[0], v2);
-	CrossProduct (v2, v1, normal);
-	VectorNormalize (normal, normal);
-	*dist = DotProduct (w->p[0], normal);
-
-}
-
-/*
-=============
-WindingArea
-=============
-*/
-vec_t	WindingArea (winding_t *w)
-{
-	int		i;
-	vec3_t	d1, d2, cross;
-	vec_t	total;
-
-	total = 0;
-	for (i=2 ; i<w->numpoints ; i++)
-	{
-		VectorSubtract (w->p[i-1], w->p[0], d1);
-		VectorSubtract (w->p[i], w->p[0], d2);
-		CrossProduct (d1, d2, cross);
-		total += 0.5 * VectorLength ( cross );
-	}
-	return total;
-}
-
-void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
-{
-	vec_t	v;
-	int		i,j;
-
-	mins[0] = mins[1] = mins[2] = 99999;
-	maxs[0] = maxs[1] = maxs[2] = -99999;
-
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			v = w->p[i][j];
-			if (v < mins[j])
-				mins[j] = v;
-			if (v > maxs[j])
-				maxs[j] = v;
-		}
-	}
-}
-
-/*
-=============
-WindingCenter
-=============
-*/
-void	WindingCenter (winding_t *w, vec3_t center)
-{
-	int		i;
-	float	scale;
-
-	VectorCopy (vec3_origin, center);
-	for (i=0 ; i<w->numpoints ; i++)
-		VectorAdd (w->p[i], center, center);
-
-	scale = 1.0/w->numpoints;
-	VectorScale (center, scale, center);
-}
-
-/*
-=================
-BaseWindingForPlane
-=================
-*/
-winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
-{
-	int		i, x;
-	vec_t	max, v;
-	vec3_t	org, vright, vup;
-	winding_t	*w;
-	
-// find the major axis
-
-	max = -BOGUS_RANGE;
-	x = -1;
-	for (i=0 ; i<3; i++)
-	{
-		v = fabs(normal[i]);
-		if (v > max)
-		{
-			x = i;
-			max = v;
-		}
-	}
-	if (x==-1)
-		Error ("BaseWindingForPlane: no axis found");
-		
-	VectorCopy (vec3_origin, vup);	
-	switch (x)
-	{
-	case 0:
-	case 1:
-		vup[2] = 1;
-		break;		
-	case 2:
-		vup[0] = 1;
-		break;		
-	}
-
-	v = DotProduct (vup, normal);
-	VectorMA (vup, -v, normal, vup);
-	VectorNormalize (vup, vup);
-		
-	VectorScale (normal, dist, org);
-	
-	CrossProduct (vup, normal, vright);
-	
-	VectorScale (vup, 8192, vup);
-	VectorScale (vright, 8192, vright);
-
-// project a really big	axis aligned box onto the plane
-	w = AllocWinding (4);
-	
-	VectorSubtract (org, vright, w->p[0]);
-	VectorAdd (w->p[0], vup, w->p[0]);
-	
-	VectorAdd (org, vright, w->p[1]);
-	VectorAdd (w->p[1], vup, w->p[1]);
-	
-	VectorAdd (org, vright, w->p[2]);
-	VectorSubtract (w->p[2], vup, w->p[2]);
-	
-	VectorSubtract (org, vright, w->p[3]);
-	VectorSubtract (w->p[3], vup, w->p[3]);
-	
-	w->numpoints = 4;
-	
-	return w;	
-}
-
-/*
-==================
-CopyWinding
-==================
-*/
-winding_t	*CopyWinding (winding_t *w)
-{
-	int			size;
-	winding_t	*c;
-
-	c = AllocWinding (w->numpoints);
-	size = (int)((winding_t *)0)->p[w->numpoints];
-	memcpy (c, w, size);
-	return c;
-}
-
-/*
-==================
-ReverseWinding
-==================
-*/
-winding_t	*ReverseWinding (winding_t *w)
-{
-	int			i;
-	winding_t	*c;
-
-	c = AllocWinding (w->numpoints);
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
-	}
-	c->numpoints = w->numpoints;
-	return c;
-}
-
-
-/*
-=============
-ClipWindingEpsilon
-=============
-*/
-void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
-				vec_t epsilon, winding_t **front, winding_t **back)
-{
-	vec_t	dists[MAX_POINTS_ON_WINDING+4];
-	int		sides[MAX_POINTS_ON_WINDING+4];
-	int		counts[3];
-	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	winding_t	*f, *b;
-	int		maxpts;
-	
-	counts[0] = counts[1] = counts[2] = 0;
-
-// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->p[i], normal);
-		dot -= dist;
-		dists[i] = dot;
-		if (dot > epsilon)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -epsilon)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	*front = *back = NULL;
-
-	if (!counts[0])
-	{
-		*back = CopyWinding (in);
-		return;
-	}
-	if (!counts[1])
-	{
-		*front = CopyWinding (in);
-		return;
-	}
-
-	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
-								// of fp grouping errors
-
-	*front = f = AllocWinding (maxpts);
-	*back = b = AllocWinding (maxpts);
-		
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->p[i];
-		
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-			VectorCopy (p1, b->p[b->numpoints]);
-			b->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-		}
-		if (sides[i] == SIDE_BACK)
-		{
-			VectorCopy (p1, b->p[b->numpoints]);
-			b->numpoints++;
-		}
-
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-	// generate a split point
-		p2 = in->p[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (normal[j] == 1)
-				mid[j] = dist;
-			else if (normal[j] == -1)
-				mid[j] = -dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, f->p[f->numpoints]);
-		f->numpoints++;
-		VectorCopy (mid, b->p[b->numpoints]);
-		b->numpoints++;
-	}
-	
-	if (f->numpoints > maxpts || b->numpoints > maxpts)
-		Error ("ClipWinding: points exceeded estimate");
-	if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
-		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
-}
-
-
-/*
-=============
-ChopWindingInPlace
-=============
-*/
-void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
-{
-	winding_t	*in;
-	vec_t	dists[MAX_POINTS_ON_WINDING+4];
-	int		sides[MAX_POINTS_ON_WINDING+4];
-	int		counts[3];
-	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	winding_t	*f;
-	int		maxpts;
-
-	in = *inout;
-	counts[0] = counts[1] = counts[2] = 0;
-
-// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->p[i], normal);
-		dot -= dist;
-		dists[i] = dot;
-		if (dot > epsilon)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -epsilon)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	if (!counts[0])
-	{
-		FreeWinding (in);
-		*inout = NULL;
-		return;
-	}
-	if (!counts[1])
-		return;		// inout stays the same
-
-	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
-								// of fp grouping errors
-
-	f = AllocWinding (maxpts);
-		
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->p[i];
-		
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-		}
-
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-	// generate a split point
-		p2 = in->p[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (normal[j] == 1)
-				mid[j] = dist;
-			else if (normal[j] == -1)
-				mid[j] = -dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, f->p[f->numpoints]);
-		f->numpoints++;
-	}
-	
-	if (f->numpoints > maxpts)
-		Error ("ClipWinding: points exceeded estimate");
-	if (f->numpoints > MAX_POINTS_ON_WINDING)
-		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
-
-	FreeWinding (in);
-	*inout = f;
-}
-
-
-/*
-=================
-ChopWinding
-
-Returns the fragment of in that is on the front side
-of the cliping plane.  The original is freed.
-=================
-*/
-winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
-{
-	winding_t	*f, *b;
-
-	ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
-	FreeWinding (in);
-	if (b)
-		FreeWinding (b);
-	return f;
-}
-
-
-/*
-=================
-CheckWinding
-
-=================
-*/
-void CheckWinding (winding_t *w)
-{
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec_t	d, edgedist;
-	vec3_t	dir, edgenormal, facenormal;
-	vec_t	area;
-	vec_t	facedist;
-
-	if (w->numpoints < 3)
-		Error ("CheckWinding: %i points",w->numpoints);
-	
-	area = WindingArea(w);
-	if (area < 1)
-		Error ("CheckWinding: %f area", area);
-
-	WindingPlane (w, facenormal, &facedist);
-	
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		p1 = w->p[i];
-
-		for (j=0 ; j<3 ; j++)
-			if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
-				Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
-
-		j = i+1 == w->numpoints ? 0 : i+1;
-		
-	// check the point is on the face plane
-		d = DotProduct (p1, facenormal) - facedist;
-		if (d < -ON_EPSILON || d > ON_EPSILON)
-			Error ("CheckWinding: point off plane");
-	
-	// check the edge isnt degenerate
-		p2 = w->p[j];
-		VectorSubtract (p2, p1, dir);
-		
-		if (VectorLength (dir) < ON_EPSILON)
-			Error ("CheckWinding: degenerate edge");
-			
-		CrossProduct (facenormal, dir, edgenormal);
-		VectorNormalize (edgenormal, edgenormal);
-		edgedist = DotProduct (p1, edgenormal);
-		edgedist += ON_EPSILON;
-		
-	// all other points must be on front side
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			if (j == i)
-				continue;
-			d = DotProduct (w->p[j], edgenormal);
-			if (d > edgedist)
-				Error ("CheckWinding: non-convex");
-		}
-	}
-}
-
-
-/*
-============
-WindingOnPlaneSide
-============
-*/
-int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
-{
-	qboolean	front, back;
-	int			i;
-	vec_t		d;
-
-	front = false;
-	back = false;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		d = DotProduct (w->p[i], normal) - dist;
-		if (d < -ON_EPSILON)
-		{
-			if (front)
-				return SIDE_CROSS;
-			back = true;
-			continue;
-		}
-		if (d > ON_EPSILON)
-		{
-			if (back)
-				return SIDE_CROSS;
-			front = true;
-			continue;
-		}
-	}
-
-	if (back)
-		return SIDE_BACK;
-	if (front)
-		return SIDE_FRONT;
-	return SIDE_ON;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "polylib.h"
+
+
+extern int numthreads;
+
+// counters are only bumped when running single threaded,
+// because they are an awefull coherence problem
+int	c_active_windings;
+int	c_peak_windings;
+int	c_winding_allocs;
+int	c_winding_points;
+
+#define	BOGUS_RANGE	8192
+
+void pw(winding_t *w)
+{
+	int		i;
+	for (i=0 ; i<w->numpoints ; i++)
+		printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
+}
+
+
+/*
+=============
+AllocWinding
+=============
+*/
+winding_t	*AllocWinding (int points)
+{
+	winding_t	*w;
+	int			s;
+
+	if (numthreads == 1)
+	{
+		c_winding_allocs++;
+		c_winding_points += points;
+		c_active_windings++;
+		if (c_active_windings > c_peak_windings)
+			c_peak_windings = c_active_windings;
+	}
+	s = sizeof(vec_t)*3*points + sizeof(int);
+	w = malloc (s);
+	memset (w, 0, s); 
+	return w;
+}
+
+void FreeWinding (winding_t *w)
+{
+	if (*(unsigned *)w == 0xdeaddead)
+		Error ("FreeWinding: freed a freed winding");
+	*(unsigned *)w = 0xdeaddead;
+
+	if (numthreads == 1)
+		c_active_windings--;
+	free (w);
+}
+
+/*
+============
+RemoveColinearPoints
+============
+*/
+int	c_removed;
+
+void	RemoveColinearPoints (winding_t *w)
+{
+	int		i, j, k;
+	vec3_t	v1, v2;
+	int		nump;
+	vec3_t	p[MAX_POINTS_ON_WINDING];
+
+	nump = 0;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		j = (i+1)%w->numpoints;
+		k = (i+w->numpoints-1)%w->numpoints;
+		VectorSubtract (w->p[j], w->p[i], v1);
+		VectorSubtract (w->p[i], w->p[k], v2);
+		VectorNormalize(v1,v1);
+		VectorNormalize(v2,v2);
+		if (DotProduct(v1, v2) < 0.999)
+		{
+			VectorCopy (w->p[i], p[nump]);
+			nump++;
+		}
+	}
+
+	if (nump == w->numpoints)
+		return;
+
+	if (numthreads == 1)
+		c_removed += w->numpoints - nump;
+	w->numpoints = nump;
+	memcpy (w->p, p, nump*sizeof(p[0]));
+}
+
+/*
+============
+WindingPlane
+============
+*/
+void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
+{
+	vec3_t	v1, v2;
+
+	VectorSubtract (w->p[1], w->p[0], v1);
+	VectorSubtract (w->p[2], w->p[0], v2);
+	CrossProduct (v2, v1, normal);
+	VectorNormalize (normal, normal);
+	*dist = DotProduct (w->p[0], normal);
+
+}
+
+/*
+=============
+WindingArea
+=============
+*/
+vec_t	WindingArea (winding_t *w)
+{
+	int		i;
+	vec3_t	d1, d2, cross;
+	vec_t	total;
+
+	total = 0;
+	for (i=2 ; i<w->numpoints ; i++)
+	{
+		VectorSubtract (w->p[i-1], w->p[0], d1);
+		VectorSubtract (w->p[i], w->p[0], d2);
+		CrossProduct (d1, d2, cross);
+		total += 0.5 * VectorLength ( cross );
+	}
+	return total;
+}
+
+void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
+{
+	vec_t	v;
+	int		i,j;
+
+	mins[0] = mins[1] = mins[2] = 99999;
+	maxs[0] = maxs[1] = maxs[2] = -99999;
+
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			v = w->p[i][j];
+			if (v < mins[j])
+				mins[j] = v;
+			if (v > maxs[j])
+				maxs[j] = v;
+		}
+	}
+}
+
+/*
+=============
+WindingCenter
+=============
+*/
+void	WindingCenter (winding_t *w, vec3_t center)
+{
+	int		i;
+	float	scale;
+
+	VectorCopy (vec3_origin, center);
+	for (i=0 ; i<w->numpoints ; i++)
+		VectorAdd (w->p[i], center, center);
+
+	scale = 1.0/w->numpoints;
+	VectorScale (center, scale, center);
+}
+
+/*
+=================
+BaseWindingForPlane
+=================
+*/
+winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
+{
+	int		i, x;
+	vec_t	max, v;
+	vec3_t	org, vright, vup;
+	winding_t	*w;
+	
+// find the major axis
+
+	max = -BOGUS_RANGE;
+	x = -1;
+	for (i=0 ; i<3; i++)
+	{
+		v = fabs(normal[i]);
+		if (v > max)
+		{
+			x = i;
+			max = v;
+		}
+	}
+	if (x==-1)
+		Error ("BaseWindingForPlane: no axis found");
+		
+	VectorCopy (vec3_origin, vup);	
+	switch (x)
+	{
+	case 0:
+	case 1:
+		vup[2] = 1;
+		break;		
+	case 2:
+		vup[0] = 1;
+		break;		
+	}
+
+	v = DotProduct (vup, normal);
+	VectorMA (vup, -v, normal, vup);
+	VectorNormalize (vup, vup);
+		
+	VectorScale (normal, dist, org);
+	
+	CrossProduct (vup, normal, vright);
+	
+	VectorScale (vup, 8192, vup);
+	VectorScale (vright, 8192, vright);
+
+// project a really big	axis aligned box onto the plane
+	w = AllocWinding (4);
+	
+	VectorSubtract (org, vright, w->p[0]);
+	VectorAdd (w->p[0], vup, w->p[0]);
+	
+	VectorAdd (org, vright, w->p[1]);
+	VectorAdd (w->p[1], vup, w->p[1]);
+	
+	VectorAdd (org, vright, w->p[2]);
+	VectorSubtract (w->p[2], vup, w->p[2]);
+	
+	VectorSubtract (org, vright, w->p[3]);
+	VectorSubtract (w->p[3], vup, w->p[3]);
+	
+	w->numpoints = 4;
+	
+	return w;	
+}
+
+/*
+==================
+CopyWinding
+==================
+*/
+winding_t	*CopyWinding (winding_t *w)
+{
+	int			size;
+	winding_t	*c;
+
+	c = AllocWinding (w->numpoints);
+	size = (int)((winding_t *)0)->p[w->numpoints];
+	memcpy (c, w, size);
+	return c;
+}
+
+/*
+==================
+ReverseWinding
+==================
+*/
+winding_t	*ReverseWinding (winding_t *w)
+{
+	int			i;
+	winding_t	*c;
+
+	c = AllocWinding (w->numpoints);
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
+	}
+	c->numpoints = w->numpoints;
+	return c;
+}
+
+
+/*
+=============
+ClipWindingEpsilon
+=============
+*/
+void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
+				vec_t epsilon, winding_t **front, winding_t **back)
+{
+	vec_t	dists[MAX_POINTS_ON_WINDING+4];
+	int		sides[MAX_POINTS_ON_WINDING+4];
+	int		counts[3];
+	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	winding_t	*f, *b;
+	int		maxpts;
+	
+	counts[0] = counts[1] = counts[2] = 0;
+
+// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->p[i], normal);
+		dot -= dist;
+		dists[i] = dot;
+		if (dot > epsilon)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -epsilon)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	*front = *back = NULL;
+
+	if (!counts[0])
+	{
+		*back = CopyWinding (in);
+		return;
+	}
+	if (!counts[1])
+	{
+		*front = CopyWinding (in);
+		return;
+	}
+
+	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
+								// of fp grouping errors
+
+	*front = f = AllocWinding (maxpts);
+	*back = b = AllocWinding (maxpts);
+		
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->p[i];
+		
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+			VectorCopy (p1, b->p[b->numpoints]);
+			b->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+		}
+		if (sides[i] == SIDE_BACK)
+		{
+			VectorCopy (p1, b->p[b->numpoints]);
+			b->numpoints++;
+		}
+
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+	// generate a split point
+		p2 = in->p[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (normal[j] == 1)
+				mid[j] = dist;
+			else if (normal[j] == -1)
+				mid[j] = -dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, f->p[f->numpoints]);
+		f->numpoints++;
+		VectorCopy (mid, b->p[b->numpoints]);
+		b->numpoints++;
+	}
+	
+	if (f->numpoints > maxpts || b->numpoints > maxpts)
+		Error ("ClipWinding: points exceeded estimate");
+	if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
+		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
+}
+
+
+/*
+=============
+ChopWindingInPlace
+=============
+*/
+void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
+{
+	winding_t	*in;
+	vec_t	dists[MAX_POINTS_ON_WINDING+4];
+	int		sides[MAX_POINTS_ON_WINDING+4];
+	int		counts[3];
+	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	winding_t	*f;
+	int		maxpts;
+
+	in = *inout;
+	counts[0] = counts[1] = counts[2] = 0;
+
+// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->p[i], normal);
+		dot -= dist;
+		dists[i] = dot;
+		if (dot > epsilon)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -epsilon)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	if (!counts[0])
+	{
+		FreeWinding (in);
+		*inout = NULL;
+		return;
+	}
+	if (!counts[1])
+		return;		// inout stays the same
+
+	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
+								// of fp grouping errors
+
+	f = AllocWinding (maxpts);
+		
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->p[i];
+		
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+		}
+
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+	// generate a split point
+		p2 = in->p[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (normal[j] == 1)
+				mid[j] = dist;
+			else if (normal[j] == -1)
+				mid[j] = -dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, f->p[f->numpoints]);
+		f->numpoints++;
+	}
+	
+	if (f->numpoints > maxpts)
+		Error ("ClipWinding: points exceeded estimate");
+	if (f->numpoints > MAX_POINTS_ON_WINDING)
+		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
+
+	FreeWinding (in);
+	*inout = f;
+}
+
+
+/*
+=================
+ChopWinding
+
+Returns the fragment of in that is on the front side
+of the cliping plane.  The original is freed.
+=================
+*/
+winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
+{
+	winding_t	*f, *b;
+
+	ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
+	FreeWinding (in);
+	if (b)
+		FreeWinding (b);
+	return f;
+}
+
+
+/*
+=================
+CheckWinding
+
+=================
+*/
+void CheckWinding (winding_t *w)
+{
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec_t	d, edgedist;
+	vec3_t	dir, edgenormal, facenormal;
+	vec_t	area;
+	vec_t	facedist;
+
+	if (w->numpoints < 3)
+		Error ("CheckWinding: %i points",w->numpoints);
+	
+	area = WindingArea(w);
+	if (area < 1)
+		Error ("CheckWinding: %f area", area);
+
+	WindingPlane (w, facenormal, &facedist);
+	
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		p1 = w->p[i];
+
+		for (j=0 ; j<3 ; j++)
+			if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
+				Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
+
+		j = i+1 == w->numpoints ? 0 : i+1;
+		
+	// check the point is on the face plane
+		d = DotProduct (p1, facenormal) - facedist;
+		if (d < -ON_EPSILON || d > ON_EPSILON)
+			Error ("CheckWinding: point off plane");
+	
+	// check the edge isnt degenerate
+		p2 = w->p[j];
+		VectorSubtract (p2, p1, dir);
+		
+		if (VectorLength (dir) < ON_EPSILON)
+			Error ("CheckWinding: degenerate edge");
+			
+		CrossProduct (facenormal, dir, edgenormal);
+		VectorNormalize (edgenormal, edgenormal);
+		edgedist = DotProduct (p1, edgenormal);
+		edgedist += ON_EPSILON;
+		
+	// all other points must be on front side
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			if (j == i)
+				continue;
+			d = DotProduct (w->p[j], edgenormal);
+			if (d > edgedist)
+				Error ("CheckWinding: non-convex");
+		}
+	}
+}
+
+
+/*
+============
+WindingOnPlaneSide
+============
+*/
+int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
+{
+	qboolean	front, back;
+	int			i;
+	vec_t		d;
+
+	front = false;
+	back = false;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		d = DotProduct (w->p[i], normal) - dist;
+		if (d < -ON_EPSILON)
+		{
+			if (front)
+				return SIDE_CROSS;
+			back = true;
+			continue;
+		}
+		if (d > ON_EPSILON)
+		{
+			if (back)
+				return SIDE_CROSS;
+			front = true;
+			continue;
+		}
+	}
+
+	if (back)
+		return SIDE_BACK;
+	if (front)
+		return SIDE_FRONT;
+	return SIDE_ON;
+}
+
diff --git a/tools/quake2/common/polylib.h b/tools/quake2/common/polylib.h
index 6c21fc95..43515cf3 100644
--- a/tools/quake2/common/polylib.h
+++ b/tools/quake2/common/polylib.h
@@ -1,54 +1,54 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-typedef struct
-{
-	int		numpoints;
-	vec3_t	p[4];		// variable sized
-} winding_t;
-
-#define	MAX_POINTS_ON_WINDING	64
-
-// you can define on_epsilon in the makefile as tighter
-#ifndef	ON_EPSILON
-#define	ON_EPSILON	0.1
-#endif
-
-winding_t	*AllocWinding (int points);
-vec_t	WindingArea (winding_t *w);
-void	WindingCenter (winding_t *w, vec3_t center);
-void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
-				vec_t epsilon, winding_t **front, winding_t **back);
-winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
-winding_t	*CopyWinding (winding_t *w);
-winding_t	*ReverseWinding (winding_t *w);
-winding_t	*BaseWindingForPlane (vec3_t normal, vec_t dist);
-void	CheckWinding (winding_t *w);
-void	WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
-void	RemoveColinearPoints (winding_t *w);
-int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
-void	FreeWinding (winding_t *w);
-void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
-
-void	ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
-// frees the original if clipped
-
-void pw(winding_t *w);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+typedef struct
+{
+	int		numpoints;
+	vec3_t	p[4];		// variable sized
+} winding_t;
+
+#define	MAX_POINTS_ON_WINDING	64
+
+// you can define on_epsilon in the makefile as tighter
+#ifndef	ON_EPSILON
+#define	ON_EPSILON	0.1
+#endif
+
+winding_t	*AllocWinding (int points);
+vec_t	WindingArea (winding_t *w);
+void	WindingCenter (winding_t *w, vec3_t center);
+void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
+				vec_t epsilon, winding_t **front, winding_t **back);
+winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
+winding_t	*CopyWinding (winding_t *w);
+winding_t	*ReverseWinding (winding_t *w);
+winding_t	*BaseWindingForPlane (vec3_t normal, vec_t dist);
+void	CheckWinding (winding_t *w);
+void	WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
+void	RemoveColinearPoints (winding_t *w);
+int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
+void	FreeWinding (winding_t *w);
+void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
+
+void	ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
+// frees the original if clipped
+
+void pw(winding_t *w);
diff --git a/tools/quake2/common/q2_threads.h b/tools/quake2/common/q2_threads.h
index e919c264..2b20c8d7 100644
--- a/tools/quake2/common/q2_threads.h
+++ b/tools/quake2/common/q2_threads.h
@@ -1,34 +1,34 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef _THREADS_H
-
-#define _THREADS_H
-
-extern	int		numthreads;
-
-void ThreadSetDefault (void);
-int	GetThreadWork (void);
-void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
-void ThreadLock (void);
-void ThreadUnlock (void);
-
-#endif // _THREADS_H
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#ifndef _THREADS_H
+
+#define _THREADS_H
+
+extern	int		numthreads;
+
+void ThreadSetDefault (void);
+int	GetThreadWork (void);
+void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
+void ThreadLock (void);
+void ThreadUnlock (void);
+
+#endif // _THREADS_H
diff --git a/tools/quake2/common/qfiles.h b/tools/quake2/common/qfiles.h
index 434accc7..1dd9d0ae 100644
--- a/tools/quake2/common/qfiles.h
+++ b/tools/quake2/common/qfiles.h
@@ -1,563 +1,563 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-/*
-========================================================================
-
-The .pak files are just a linear collapse of a directory tree
-
-========================================================================
-*/
-
-#ifdef _WIN32
-	#ifdef NDEBUG							// Don't show in a Release build
-		#pragma warning(disable : 4305)     // truncate from double to float
-		#pragma warning(disable : 4244)     // conversion from double to float
-		#pragma warning(disable : 4018)     // signed/unsigned mismatch
-	#endif
-#endif
-
-#define IDPAKHEADER		(('K'<<24)+('C'<<16)+('A'<<8)+'P')
-
-typedef struct
-{
-	char	name[56];
-	int		filepos, filelen;
-} dpackfile_t;
-
-typedef struct
-{
-	int		ident;		// == IDPAKHEADER
-	int		dirofs;
-	int		dirlen;
-} dpackheader_t;
-
-#define	MAX_FILES_IN_PACK	4096
-
-
-/*
-========================================================================
-
-PCX files are used for as many images as possible
-
-========================================================================
-*/
-
-typedef struct
-{
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
-
-
-/*
-========================================================================
-
-.MD2 triangle model file format
-
-========================================================================
-*/
-
-#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
-#define ALIAS_VERSION	8
-
-#define	MAX_TRIANGLES	4096
-#define MAX_VERTS		2048
-#define MAX_FRAMES		512
-#define MAX_MD2SKINS	32
-#define	MAX_SKINNAME	64
-
-typedef struct
-{
-	short	s;
-	short	t;
-} dstvert_t;
-
-typedef struct 
-{
-	short	index_xyz[3];
-	short	index_st[3];
-} dtriangle_t;
-
-typedef struct
-{
-	byte	v[3];			// scaled byte to fit in frame mins/maxs
-	byte	lightnormalindex;
-} dtrivertx_t;
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-typedef struct
-{
-	float		scale[3];	// multiply byte verts by this
-	float		translate[3];	// then add this
-	char		name[16];	// frame name from grabbing
-	dtrivertx_t	verts[1];	// variable sized
-} daliasframe_t;
-
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-typedef struct
-{
-	int			ident;
-	int			version;
-
-	int			skinwidth;
-	int			skinheight;
-	int			framesize;		// byte size of each frame
-
-	int			num_skins;
-	int			num_xyz;
-	int			num_st;			// greater than num_xyz for seams
-	int			num_tris;
-	int			num_glcmds;		// dwords in strip/fan command list
-	int			num_frames;
-
-	int			ofs_skins;		// each skin is a MAX_SKINNAME string
-	int			ofs_st;			// byte offset from start for stverts
-	int			ofs_tris;		// offset for dtriangles
-	int			ofs_frames;		// offset for first frame
-	int			ofs_glcmds;	
-	int			ofs_end;		// end of file
-
-} dmdl_t;
-
-/*
-========================================================================
-
-.SP2 sprite file format
-
-========================================================================
-*/
-
-#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
-		// little-endian "IDS2"
-#define SPRITE_VERSION	2
-
-typedef struct
-{
-	int		width, height;
-	int		origin_x, origin_y;		// raster coordinates inside pic
-	char	name[MAX_SKINNAME];		// name of pcx file
-} dsprframe_t;
-
-typedef struct {
-	int			ident;
-	int			version;
-	int			numframes;
-	dsprframe_t	frames[1];			// variable sized
-} dsprite_t;
-
-/*
-==============================================================================
-
-  .WAL texture file format
-
-==============================================================================
-*/
-
-
-#define	MIPLEVELS	4
-typedef struct miptex_s
-{
-	char		name[32];
-	unsigned	width, height;
-	unsigned	offsets[MIPLEVELS];		// four mip maps stored
-	char		animname[32];			// next frame in animation chain
-	int			flags;
-	int			contents;
-	int			value;
-} miptex_t;
-
- /*
- ==============================================================================
- 
--  .WAL texture file format
-+  .M8 texture file format
- 
- ==============================================================================
- */
- 
-typedef struct palette_s
-{
-	union
-	{
-		struct
-		{
-			byte r,g,b;
-		};
-	};
-} palette_t;
-
-#define MIP_VERSION		2
-#define PAL_SIZE		256
-#define	H2_MIPLEVELS		16
- 
- typedef struct miptex_m8_s
- {
-	int		version;
- 	char		name[32];
-	unsigned	width[H2_MIPLEVELS], height[H2_MIPLEVELS];
- 	unsigned	offsets[H2_MIPLEVELS];		// four mip maps stored
- 	char		animname[32];			// next frame in animation chain
-	palette_t	palette[PAL_SIZE];
- 	int		flags;
- 	int		contents;
- 	int		value;
- } miptex_m8_t;
- 
- 
-#define MIP32_VERSION	4
-
-#define MIP32_NOMIP_FLAG2		0x00000001
-#define MIP32_DETAILER_FLAG2		0x00000002
-
-typedef struct miptex_m32_s
-{
-	int			version;
-	char		name[128];
-	char		altname[128];			// texture substitution
-	char		animname[128];			// next frame in animation chain
-	char		damagename[128];		// image that should be shown when damaged
-	unsigned	width[H2_MIPLEVELS], height[H2_MIPLEVELS];
-	unsigned	offsets[H2_MIPLEVELS];		
-	int			flags;
-	int			contents;
-	int			value;
-	float		scale_x, scale_y;
-	int			mip_scale;
-
-	// detail texturing info
-	char		dt_name[128];		// detailed texture name
-	float		dt_scale_x, dt_scale_y;
-	float		dt_u, dt_v;
-	float		dt_alpha;
-	int			dt_src_blend_mode, dt_dst_blend_mode;
-
-	int			flags2;
-	int			unused[19];				// future expansion to maintain compatibility with h2
-} miptex_m32_t;
-
-
-
-
-/*
-==============================================================================
-
-  .BSP file format
-
-==============================================================================
-*/
-
-#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
-		// little-endian "IBSP"
-
-#define BSPVERSION	38
-
-
-// upper design bounds
-// leaffaces, leafbrushes, planes, and verts are still bounded by
-// 16 bit short limits
-#define	MAX_MAP_MODELS		1024
-#define	MAX_MAP_BRUSHES		8192
-#define	MAX_MAP_ENTITIES	2048
-#define	MAX_MAP_ENTSTRING	0x40000
-#define	MAX_MAP_TEXINFO		8192
-
-#define	MAX_MAP_AREAS		256
-#define	MAX_MAP_AREAPORTALS	1024
-#define	MAX_MAP_PLANES		65536
-#define	MAX_MAP_NODES		65536
-#define	MAX_MAP_BRUSHSIDES	65536
-#define	MAX_MAP_LEAFS		65536
-#define	MAX_MAP_VERTS		65536
-#define	MAX_MAP_FACES		65536
-#define	MAX_MAP_LEAFFACES	65536
-#define	MAX_MAP_LEAFBRUSHES 65536
-#define	MAX_MAP_PORTALS		65536
-#define	MAX_MAP_EDGES		128000
-#define	MAX_MAP_SURFEDGES	256000
-#define	MAX_MAP_LIGHTING	0x200000
-#define	MAX_MAP_VISIBILITY	0x100000
-
-// key / value pair sizes
-
-#define	MAX_KEY		32
-#define	MAX_VALUE	1024
-
-//=============================================================================
-
-typedef struct
-{
-	int		fileofs, filelen;
-} lump_t;
-
-#define	LUMP_ENTITIES		0
-#define	LUMP_PLANES			1
-#define	LUMP_VERTEXES		2
-#define	LUMP_VISIBILITY		3
-#define	LUMP_NODES			4
-#define	LUMP_TEXINFO		5
-#define	LUMP_FACES			6
-#define	LUMP_LIGHTING		7
-#define	LUMP_LEAFS			8
-#define	LUMP_LEAFFACES		9
-#define	LUMP_LEAFBRUSHES	10
-#define	LUMP_EDGES			11
-#define	LUMP_SURFEDGES		12
-#define	LUMP_MODELS			13
-#define	LUMP_BRUSHES		14
-#define	LUMP_BRUSHSIDES		15
-#define	LUMP_POP			16
-#define	LUMP_AREAS			17
-#define	LUMP_AREAPORTALS	18
-#define	HEADER_LUMPS		19
-
-typedef struct
-{
-	int			ident;
-	int			version;	
-	lump_t		lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct
-{
-	float		mins[3], maxs[3];
-	float		origin[3];		// for sounds or lights
-	int			headnode;
-	int			firstface, numfaces;	// submodels just draw faces
-										// without walking the bsp tree
-} dmodel_t;
-
-
-typedef struct
-{
-	float	point[3];
-} dvertex_t;
-
-
-// 0-2 are axial planes
-#define	PLANE_X			0
-#define	PLANE_Y			1
-#define	PLANE_Z			2
-
-// 3-5 are non-axial planes snapped to the nearest
-#define	PLANE_ANYX		3
-#define	PLANE_ANYY		4
-#define	PLANE_ANYZ		5
-
-// planes (x&~1) and (x&~1)+1 are allways opposites
-
-typedef struct
-{
-	float	normal[3];
-	float	dist;
-	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
-} dplane_t;
-
-
-// contents flags are seperate bits
-// a given brush can contribute multiple content bits
-// multiple brushes can be in a single leaf
-
-// these definitions also need to be in q_shared.h!
-
-// lower bits are stronger, and will eat weaker brushes completely
-#define	CONTENTS_SOLID			1		// an eye is never valid in a solid
-#define	CONTENTS_WINDOW			2		// translucent, but not watery
-#define	CONTENTS_AUX			4
-#define	CONTENTS_LAVA			8
-#define	CONTENTS_SLIME			16
-#define	CONTENTS_WATER			32
-#define	CONTENTS_MIST			64
-#define	LAST_VISIBLE_CONTENTS	64
-
-// remaining contents are non-visible, and don't eat brushes
-
-#define	CONTENTS_AREAPORTAL		0x8000
-
-#define	CONTENTS_PLAYERCLIP		0x10000
-#define	CONTENTS_MONSTERCLIP	0x20000
-
-// currents can be added to any other contents, and may be mixed
-#define	CONTENTS_CURRENT_0		0x40000
-#define	CONTENTS_CURRENT_90		0x80000
-#define	CONTENTS_CURRENT_180	0x100000
-#define	CONTENTS_CURRENT_270	0x200000
-#define	CONTENTS_CURRENT_UP		0x400000
-#define	CONTENTS_CURRENT_DOWN	0x800000
-
-#define	CONTENTS_ORIGIN			0x1000000	// removed before bsping an entity
-
-#define	CONTENTS_MONSTER		0x2000000	// should never be on a brush, only in game
-#define	CONTENTS_DEADMONSTER	0x4000000
-#define	CONTENTS_DETAIL			0x8000000	// brushes to be added after vis leafs
-#define	CONTENTS_TRANSLUCENT	0x10000000	// auto set if any surface has trans
-#define	CONTENTS_LADDER			0x20000000
-
-
-
-#define	SURF_LIGHT		0x1		// value will hold the light strength
-
-#define	SURF_SLICK		0x2		// effects game physics
-
-#define	SURF_SKY		0x4		// don't draw, but add to skybox
-#define	SURF_WARP		0x8		// turbulent water warp
-#define	SURF_TRANS33	0x10
-#define	SURF_TRANS66	0x20
-#define	SURF_FLOWING	0x40	// scroll towards angle
-#define	SURF_NODRAW		0x80	// don't bother referencing the texture
-
-#define	SURF_HINT		0x100	// make a primary bsp splitter
-#define	SURF_SKIP		0x200	// completely ignore, allowing non-closed brushes
-
-
-
-typedef struct
-{
-	int			planenum;
-	int			children[2];	// negative numbers are -(leafs+1), not nodes
-	short		mins[3];		// for frustom culling
-	short		maxs[3];
-	unsigned short	firstface;
-	unsigned short	numfaces;	// counting both sides
-} dnode_t;
-
-
-typedef struct texinfo_s
-{
-	float		vecs[2][4];		// [s/t][xyz offset]
-	int			flags;			// miptex flags + overrides
-	int			value;			// light emission, etc
-	char		texture[32];	// texture name (textures/*.wal)
-	int			nexttexinfo;	// for animations, -1 = end of chain
-} texinfo_t;
-
-
-// note that edge 0 is never used, because negative edge nums are used for
-// counterclockwise use of the edge in a face
-typedef struct
-{
-	unsigned short	v[2];		// vertex numbers
-} dedge_t;
-
-#define	MAXLIGHTMAPS	4
-typedef struct
-{
-	unsigned short	planenum;
-	short		side;
-
-	int			firstedge;		// we must support > 64k edges
-	short		numedges;	
-	short		texinfo;
-
-// lighting info
-	byte		styles[MAXLIGHTMAPS];
-	int			lightofs;		// start of [numstyles*surfsize] samples
-} dface_t;
-
-typedef struct
-{
-	int				contents;			// OR of all brushes (not needed?)
-
-	short			cluster;
-	short			area;
-
-	short			mins[3];			// for frustum culling
-	short			maxs[3];
-
-	unsigned short	firstleafface;
-	unsigned short	numleaffaces;
-
-	unsigned short	firstleafbrush;
-	unsigned short	numleafbrushes;
-} dleaf_t;
-
-typedef struct
-{
-	unsigned short	planenum;		// facing out of the leaf
-	short	texinfo;
-} dbrushside_t;
-
-typedef struct
-{
-	int			firstside;
-	int			numsides;
-	int			contents;
-} dbrush_t;
-
-#define	ANGLE_UP	-1
-#define	ANGLE_DOWN	-2
-
-
-// the visibility lump consists of a header with a count, then
-// byte offsets for the PVS and PHS of each cluster, then the raw
-// compressed bit vectors
-#define	DVIS_PVS	0
-#define	DVIS_PHS	1
-typedef struct
-{
-	int			numclusters;
-	int			bitofs[8][2];	// bitofs[numclusters][2]
-} dvis_t;
-
-// each area has a list of portals that lead into other areas
-// when portals are closed, other areas may not be visible or
-// hearable even if the vis info says that it should be
-typedef struct
-{
-	int		portalnum;
-	int		otherarea;
-} dareaportal_t;
-
-typedef struct
-{
-	int		numareaportals;
-	int		firstareaportal;
-} darea_t;
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+/*
+========================================================================
+
+The .pak files are just a linear collapse of a directory tree
+
+========================================================================
+*/
+
+#ifdef _WIN32
+	#ifdef NDEBUG							// Don't show in a Release build
+		#pragma warning(disable : 4305)     // truncate from double to float
+		#pragma warning(disable : 4244)     // conversion from double to float
+		#pragma warning(disable : 4018)     // signed/unsigned mismatch
+	#endif
+#endif
+
+#define IDPAKHEADER		(('K'<<24)+('C'<<16)+('A'<<8)+'P')
+
+typedef struct
+{
+	char	name[56];
+	int		filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+	int		ident;		// == IDPAKHEADER
+	int		dirofs;
+	int		dirlen;
+} dpackheader_t;
+
+#define	MAX_FILES_IN_PACK	4096
+
+
+/*
+========================================================================
+
+PCX files are used for as many images as possible
+
+========================================================================
+*/
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+
+/*
+========================================================================
+
+.MD2 triangle model file format
+
+========================================================================
+*/
+
+#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
+#define ALIAS_VERSION	8
+
+#define	MAX_TRIANGLES	4096
+#define MAX_VERTS		2048
+#define MAX_FRAMES		512
+#define MAX_MD2SKINS	32
+#define	MAX_SKINNAME	64
+
+typedef struct
+{
+	short	s;
+	short	t;
+} dstvert_t;
+
+typedef struct 
+{
+	short	index_xyz[3];
+	short	index_st[3];
+} dtriangle_t;
+
+typedef struct
+{
+	byte	v[3];			// scaled byte to fit in frame mins/maxs
+	byte	lightnormalindex;
+} dtrivertx_t;
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+typedef struct
+{
+	float		scale[3];	// multiply byte verts by this
+	float		translate[3];	// then add this
+	char		name[16];	// frame name from grabbing
+	dtrivertx_t	verts[1];	// variable sized
+} daliasframe_t;
+
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+typedef struct
+{
+	int			ident;
+	int			version;
+
+	int			skinwidth;
+	int			skinheight;
+	int			framesize;		// byte size of each frame
+
+	int			num_skins;
+	int			num_xyz;
+	int			num_st;			// greater than num_xyz for seams
+	int			num_tris;
+	int			num_glcmds;		// dwords in strip/fan command list
+	int			num_frames;
+
+	int			ofs_skins;		// each skin is a MAX_SKINNAME string
+	int			ofs_st;			// byte offset from start for stverts
+	int			ofs_tris;		// offset for dtriangles
+	int			ofs_frames;		// offset for first frame
+	int			ofs_glcmds;	
+	int			ofs_end;		// end of file
+
+} dmdl_t;
+
+/*
+========================================================================
+
+.SP2 sprite file format
+
+========================================================================
+*/
+
+#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
+		// little-endian "IDS2"
+#define SPRITE_VERSION	2
+
+typedef struct
+{
+	int		width, height;
+	int		origin_x, origin_y;		// raster coordinates inside pic
+	char	name[MAX_SKINNAME];		// name of pcx file
+} dsprframe_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+	int			numframes;
+	dsprframe_t	frames[1];			// variable sized
+} dsprite_t;
+
+/*
+==============================================================================
+
+  .WAL texture file format
+
+==============================================================================
+*/
+
+
+#define	MIPLEVELS	4
+typedef struct miptex_s
+{
+	char		name[32];
+	unsigned	width, height;
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+	char		animname[32];			// next frame in animation chain
+	int			flags;
+	int			contents;
+	int			value;
+} miptex_t;
+
+ /*
+ ==============================================================================
+ 
+-  .WAL texture file format
++  .M8 texture file format
+ 
+ ==============================================================================
+ */
+ 
+typedef struct palette_s
+{
+	union
+	{
+		struct
+		{
+			byte r,g,b;
+		};
+	};
+} palette_t;
+
+#define MIP_VERSION		2
+#define PAL_SIZE		256
+#define	H2_MIPLEVELS		16
+ 
+ typedef struct miptex_m8_s
+ {
+	int		version;
+ 	char		name[32];
+	unsigned	width[H2_MIPLEVELS], height[H2_MIPLEVELS];
+ 	unsigned	offsets[H2_MIPLEVELS];		// four mip maps stored
+ 	char		animname[32];			// next frame in animation chain
+	palette_t	palette[PAL_SIZE];
+ 	int		flags;
+ 	int		contents;
+ 	int		value;
+ } miptex_m8_t;
+ 
+ 
+#define MIP32_VERSION	4
+
+#define MIP32_NOMIP_FLAG2		0x00000001
+#define MIP32_DETAILER_FLAG2		0x00000002
+
+typedef struct miptex_m32_s
+{
+	int			version;
+	char		name[128];
+	char		altname[128];			// texture substitution
+	char		animname[128];			// next frame in animation chain
+	char		damagename[128];		// image that should be shown when damaged
+	unsigned	width[H2_MIPLEVELS], height[H2_MIPLEVELS];
+	unsigned	offsets[H2_MIPLEVELS];		
+	int			flags;
+	int			contents;
+	int			value;
+	float		scale_x, scale_y;
+	int			mip_scale;
+
+	// detail texturing info
+	char		dt_name[128];		// detailed texture name
+	float		dt_scale_x, dt_scale_y;
+	float		dt_u, dt_v;
+	float		dt_alpha;
+	int			dt_src_blend_mode, dt_dst_blend_mode;
+
+	int			flags2;
+	int			unused[19];				// future expansion to maintain compatibility with h2
+} miptex_m32_t;
+
+
+
+
+/*
+==============================================================================
+
+  .BSP file format
+
+==============================================================================
+*/
+
+#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
+		// little-endian "IBSP"
+
+#define BSPVERSION	38
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define	MAX_MAP_MODELS		1024
+#define	MAX_MAP_BRUSHES		8192
+#define	MAX_MAP_ENTITIES	2048
+#define	MAX_MAP_ENTSTRING	0x40000
+#define	MAX_MAP_TEXINFO		8192
+
+#define	MAX_MAP_AREAS		256
+#define	MAX_MAP_AREAPORTALS	1024
+#define	MAX_MAP_PLANES		65536
+#define	MAX_MAP_NODES		65536
+#define	MAX_MAP_BRUSHSIDES	65536
+#define	MAX_MAP_LEAFS		65536
+#define	MAX_MAP_VERTS		65536
+#define	MAX_MAP_FACES		65536
+#define	MAX_MAP_LEAFFACES	65536
+#define	MAX_MAP_LEAFBRUSHES 65536
+#define	MAX_MAP_PORTALS		65536
+#define	MAX_MAP_EDGES		128000
+#define	MAX_MAP_SURFEDGES	256000
+#define	MAX_MAP_LIGHTING	0x200000
+#define	MAX_MAP_VISIBILITY	0x100000
+
+// key / value pair sizes
+
+#define	MAX_KEY		32
+#define	MAX_VALUE	1024
+
+//=============================================================================
+
+typedef struct
+{
+	int		fileofs, filelen;
+} lump_t;
+
+#define	LUMP_ENTITIES		0
+#define	LUMP_PLANES			1
+#define	LUMP_VERTEXES		2
+#define	LUMP_VISIBILITY		3
+#define	LUMP_NODES			4
+#define	LUMP_TEXINFO		5
+#define	LUMP_FACES			6
+#define	LUMP_LIGHTING		7
+#define	LUMP_LEAFS			8
+#define	LUMP_LEAFFACES		9
+#define	LUMP_LEAFBRUSHES	10
+#define	LUMP_EDGES			11
+#define	LUMP_SURFEDGES		12
+#define	LUMP_MODELS			13
+#define	LUMP_BRUSHES		14
+#define	LUMP_BRUSHSIDES		15
+#define	LUMP_POP			16
+#define	LUMP_AREAS			17
+#define	LUMP_AREAPORTALS	18
+#define	HEADER_LUMPS		19
+
+typedef struct
+{
+	int			ident;
+	int			version;	
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+	float		mins[3], maxs[3];
+	float		origin[3];		// for sounds or lights
+	int			headnode;
+	int			firstface, numfaces;	// submodels just draw faces
+										// without walking the bsp tree
+} dmodel_t;
+
+
+typedef struct
+{
+	float	point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define	PLANE_X			0
+#define	PLANE_Y			1
+#define	PLANE_Z			2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define	PLANE_ANYX		3
+#define	PLANE_ANYY		4
+#define	PLANE_ANYZ		5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+	float	normal[3];
+	float	dist;
+	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// these definitions also need to be in q_shared.h!
+
+// lower bits are stronger, and will eat weaker brushes completely
+#define	CONTENTS_SOLID			1		// an eye is never valid in a solid
+#define	CONTENTS_WINDOW			2		// translucent, but not watery
+#define	CONTENTS_AUX			4
+#define	CONTENTS_LAVA			8
+#define	CONTENTS_SLIME			16
+#define	CONTENTS_WATER			32
+#define	CONTENTS_MIST			64
+#define	LAST_VISIBLE_CONTENTS	64
+
+// remaining contents are non-visible, and don't eat brushes
+
+#define	CONTENTS_AREAPORTAL		0x8000
+
+#define	CONTENTS_PLAYERCLIP		0x10000
+#define	CONTENTS_MONSTERCLIP	0x20000
+
+// currents can be added to any other contents, and may be mixed
+#define	CONTENTS_CURRENT_0		0x40000
+#define	CONTENTS_CURRENT_90		0x80000
+#define	CONTENTS_CURRENT_180	0x100000
+#define	CONTENTS_CURRENT_270	0x200000
+#define	CONTENTS_CURRENT_UP		0x400000
+#define	CONTENTS_CURRENT_DOWN	0x800000
+
+#define	CONTENTS_ORIGIN			0x1000000	// removed before bsping an entity
+
+#define	CONTENTS_MONSTER		0x2000000	// should never be on a brush, only in game
+#define	CONTENTS_DEADMONSTER	0x4000000
+#define	CONTENTS_DETAIL			0x8000000	// brushes to be added after vis leafs
+#define	CONTENTS_TRANSLUCENT	0x10000000	// auto set if any surface has trans
+#define	CONTENTS_LADDER			0x20000000
+
+
+
+#define	SURF_LIGHT		0x1		// value will hold the light strength
+
+#define	SURF_SLICK		0x2		// effects game physics
+
+#define	SURF_SKY		0x4		// don't draw, but add to skybox
+#define	SURF_WARP		0x8		// turbulent water warp
+#define	SURF_TRANS33	0x10
+#define	SURF_TRANS66	0x20
+#define	SURF_FLOWING	0x40	// scroll towards angle
+#define	SURF_NODRAW		0x80	// don't bother referencing the texture
+
+#define	SURF_HINT		0x100	// make a primary bsp splitter
+#define	SURF_SKIP		0x200	// completely ignore, allowing non-closed brushes
+
+
+
+typedef struct
+{
+	int			planenum;
+	int			children[2];	// negative numbers are -(leafs+1), not nodes
+	short		mins[3];		// for frustom culling
+	short		maxs[3];
+	unsigned short	firstface;
+	unsigned short	numfaces;	// counting both sides
+} dnode_t;
+
+
+typedef struct texinfo_s
+{
+	float		vecs[2][4];		// [s/t][xyz offset]
+	int			flags;			// miptex flags + overrides
+	int			value;			// light emission, etc
+	char		texture[32];	// texture name (textures/*.wal)
+	int			nexttexinfo;	// for animations, -1 = end of chain
+} texinfo_t;
+
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+	unsigned short	v[2];		// vertex numbers
+} dedge_t;
+
+#define	MAXLIGHTMAPS	4
+typedef struct
+{
+	unsigned short	planenum;
+	short		side;
+
+	int			firstedge;		// we must support > 64k edges
+	short		numedges;	
+	short		texinfo;
+
+// lighting info
+	byte		styles[MAXLIGHTMAPS];
+	int			lightofs;		// start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+	int				contents;			// OR of all brushes (not needed?)
+
+	short			cluster;
+	short			area;
+
+	short			mins[3];			// for frustum culling
+	short			maxs[3];
+
+	unsigned short	firstleafface;
+	unsigned short	numleaffaces;
+
+	unsigned short	firstleafbrush;
+	unsigned short	numleafbrushes;
+} dleaf_t;
+
+typedef struct
+{
+	unsigned short	planenum;		// facing out of the leaf
+	short	texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+	int			firstside;
+	int			numsides;
+	int			contents;
+} dbrush_t;
+
+#define	ANGLE_UP	-1
+#define	ANGLE_DOWN	-2
+
+
+// the visibility lump consists of a header with a count, then
+// byte offsets for the PVS and PHS of each cluster, then the raw
+// compressed bit vectors
+#define	DVIS_PVS	0
+#define	DVIS_PHS	1
+typedef struct
+{
+	int			numclusters;
+	int			bitofs[8][2];	// bitofs[numclusters][2]
+} dvis_t;
+
+// each area has a list of portals that lead into other areas
+// when portals are closed, other areas may not be visible or
+// hearable even if the vis info says that it should be
+typedef struct
+{
+	int		portalnum;
+	int		otherarea;
+} dareaportal_t;
+
+typedef struct
+{
+	int		numareaportals;
+	int		firstareaportal;
+} darea_t;
diff --git a/tools/quake2/common/scriplib.c b/tools/quake2/common/scriplib.c
index 986f381c..07600a08 100644
--- a/tools/quake2/common/scriplib.c
+++ b/tools/quake2/common/scriplib.c
@@ -1,296 +1,296 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// scriplib.c
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "scriplib.h"
-
-/*
-=============================================================================
-
-						PARSING STUFF
-
-=============================================================================
-*/
-
-typedef struct
-{
-	char	filename[1024];
-	char    *buffer,*script_p,*end_p;
-	int     line;
-} script_t;
-
-#define	MAX_INCLUDES	8
-script_t	scriptstack[MAX_INCLUDES];
-script_t	*script;
-int			scriptline;
-
-char    token[MAXTOKEN];
-qboolean endofscript;
-qboolean tokenready;                     // only true if UnGetToken was just called
-
-/*
-==============
-AddScriptToStack
-==============
-*/
-void AddScriptToStack (char *filename)
-{
-	int            size;
-
-	script++;
-	if (script == &scriptstack[MAX_INCLUDES])
-		Error ("script file exceeded MAX_INCLUDES");
-	strcpy (script->filename, ExpandPath (filename) );
-
-	size = LoadFile (script->filename, (void **)&script->buffer);
-
-	printf ("entering %s\n", script->filename);
-
-	script->line = 1;
-
-	script->script_p = script->buffer;
-	script->end_p = script->buffer + size;
-}
-
-
-/*
-==============
-LoadScriptFile
-==============
-*/
-void LoadScriptFile (char *filename)
-{
-	script = scriptstack;
-	AddScriptToStack (filename);
-
-	endofscript = false;
-	tokenready = false;
-}
-
-
-/*
-==============
-ParseFromMemory
-==============
-*/
-void ParseFromMemory (char *buffer, int size)
-{
-	script = scriptstack;
-	script++;
-	if (script == &scriptstack[MAX_INCLUDES])
-		Error ("script file exceeded MAX_INCLUDES");
-	strcpy (script->filename, "memory buffer" );
-
-	script->buffer = buffer;
-	script->line = 1;
-	script->script_p = script->buffer;
-	script->end_p = script->buffer + size;
-
-	endofscript = false;
-	tokenready = false;
-}
-
-
-/*
-==============
-UnGetToken
-
-Signals that the current token was not used, and should be reported
-for the next GetToken.  Note that
-
-GetToken (true);
-UnGetToken ();
-GetToken (false);
-
-could cross a line boundary.
-==============
-*/
-void UnGetToken (void)
-{
-	tokenready = true;
-}
-
-
-qboolean EndOfScript (qboolean crossline)
-{
-	if (!crossline)
-		Error ("Line %i is incomplete\n",scriptline);
-
-	if (!strcmp (script->filename, "memory buffer"))
-	{
-		endofscript = true;
-		return false;
-	}
-
-	free (script->buffer);
-	if (script == scriptstack+1)
-	{
-		endofscript = true;
-		return false;
-	}
-	script--;
-	scriptline = script->line;
-	printf ("returning to %s\n", script->filename);
-	return GetToken (crossline);
-}
-
-/*
-==============
-GetToken
-==============
-*/
-qboolean GetToken (qboolean crossline)
-{
-	char    *token_p;
-
-	if (tokenready)                         // is a token allready waiting?
-	{
-		tokenready = false;
-		return true;
-	}
-
-	if (script->script_p >= script->end_p)
-		return EndOfScript (crossline);
-
-//
-// skip space
-//
-skipspace:
-	while (*script->script_p <= 32)
-	{
-		if (script->script_p >= script->end_p)
-			return EndOfScript (crossline);
-		if (*script->script_p++ == '\n')
-		{
-			if (!crossline)
-				Error ("Line %i is incomplete\n",scriptline);
-			scriptline = script->line++;
-		}
-	}
-
-	if (script->script_p >= script->end_p)
-		return EndOfScript (crossline);
-
-	// ; # // comments
-	if (*script->script_p == ';' || *script->script_p == '#'
-		|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
-	{
-		if (!crossline)
-			Error ("Line %i is incomplete\n",scriptline);
-		while (*script->script_p++ != '\n')
-			if (script->script_p >= script->end_p)
-				return EndOfScript (crossline);
-		goto skipspace;
-	}
-
-	// /* */ comments
-	if (script->script_p[0] == '/' && script->script_p[1] == '*')
-	{
-		if (!crossline)
-			Error ("Line %i is incomplete\n",scriptline);
-		script->script_p+=2;
-		while (script->script_p[0] != '*' && script->script_p[1] != '/')
-		{
-			script->script_p++;
-			if (script->script_p >= script->end_p)
-				return EndOfScript (crossline);
-		}
-		script->script_p += 2;
-		goto skipspace;
-	}
-
-//
-// copy token
-//
-	token_p = token;
-
-	if (*script->script_p == '"')
-	{
-		// quoted token
-		script->script_p++;
-		while (*script->script_p != '"')
-		{
-			*token_p++ = *script->script_p++;
-			if (script->script_p == script->end_p)
-				break;
-			if (token_p == &token[MAXTOKEN])
-				Error ("Token too large on line %i\n",scriptline);
-		}
-		script->script_p++;
-	}
-	else	// regular token
-	while ( *script->script_p > 32 && *script->script_p != ';')
-	{
-		*token_p++ = *script->script_p++;
-		if (script->script_p == script->end_p)
-			break;
-		if (token_p == &token[MAXTOKEN])
-			Error ("Token too large on line %i\n",scriptline);
-	}
-
-	*token_p = 0;
-
-	if (!strcmp (token, "$include"))
-	{
-		GetToken (false);
-		AddScriptToStack (token);
-		return GetToken (crossline);
-	}
-
-	return true;
-}
-
-
-/*
-==============
-TokenAvailable
-
-Returns true if there is another token on the line
-==============
-*/
-qboolean TokenAvailable (void)
-{
-	char    *search_p;
-
-	search_p = script->script_p;
-
-	if (search_p >= script->end_p)
-		return false;
-
-	while ( *search_p <= 32)
-	{
-		if (*search_p == '\n')
-			return false;
-		search_p++;
-		if (search_p == script->end_p)
-			return false;
-
-	}
-
-	if (*search_p == ';')
-		return false;
-
-	return true;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// scriplib.c
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "scriplib.h"
+
+/*
+=============================================================================
+
+						PARSING STUFF
+
+=============================================================================
+*/
+
+typedef struct
+{
+	char	filename[1024];
+	char    *buffer,*script_p,*end_p;
+	int     line;
+} script_t;
+
+#define	MAX_INCLUDES	8
+script_t	scriptstack[MAX_INCLUDES];
+script_t	*script;
+int			scriptline;
+
+char    token[MAXTOKEN];
+qboolean endofscript;
+qboolean tokenready;                     // only true if UnGetToken was just called
+
+/*
+==============
+AddScriptToStack
+==============
+*/
+void AddScriptToStack (char *filename)
+{
+	int            size;
+
+	script++;
+	if (script == &scriptstack[MAX_INCLUDES])
+		Error ("script file exceeded MAX_INCLUDES");
+	strcpy (script->filename, ExpandPath (filename) );
+
+	size = LoadFile (script->filename, (void **)&script->buffer);
+
+	printf ("entering %s\n", script->filename);
+
+	script->line = 1;
+
+	script->script_p = script->buffer;
+	script->end_p = script->buffer + size;
+}
+
+
+/*
+==============
+LoadScriptFile
+==============
+*/
+void LoadScriptFile (char *filename)
+{
+	script = scriptstack;
+	AddScriptToStack (filename);
+
+	endofscript = false;
+	tokenready = false;
+}
+
+
+/*
+==============
+ParseFromMemory
+==============
+*/
+void ParseFromMemory (char *buffer, int size)
+{
+	script = scriptstack;
+	script++;
+	if (script == &scriptstack[MAX_INCLUDES])
+		Error ("script file exceeded MAX_INCLUDES");
+	strcpy (script->filename, "memory buffer" );
+
+	script->buffer = buffer;
+	script->line = 1;
+	script->script_p = script->buffer;
+	script->end_p = script->buffer + size;
+
+	endofscript = false;
+	tokenready = false;
+}
+
+
+/*
+==============
+UnGetToken
+
+Signals that the current token was not used, and should be reported
+for the next GetToken.  Note that
+
+GetToken (true);
+UnGetToken ();
+GetToken (false);
+
+could cross a line boundary.
+==============
+*/
+void UnGetToken (void)
+{
+	tokenready = true;
+}
+
+
+qboolean EndOfScript (qboolean crossline)
+{
+	if (!crossline)
+		Error ("Line %i is incomplete\n",scriptline);
+
+	if (!strcmp (script->filename, "memory buffer"))
+	{
+		endofscript = true;
+		return false;
+	}
+
+	free (script->buffer);
+	if (script == scriptstack+1)
+	{
+		endofscript = true;
+		return false;
+	}
+	script--;
+	scriptline = script->line;
+	printf ("returning to %s\n", script->filename);
+	return GetToken (crossline);
+}
+
+/*
+==============
+GetToken
+==============
+*/
+qboolean GetToken (qboolean crossline)
+{
+	char    *token_p;
+
+	if (tokenready)                         // is a token allready waiting?
+	{
+		tokenready = false;
+		return true;
+	}
+
+	if (script->script_p >= script->end_p)
+		return EndOfScript (crossline);
+
+//
+// skip space
+//
+skipspace:
+	while (*script->script_p <= 32)
+	{
+		if (script->script_p >= script->end_p)
+			return EndOfScript (crossline);
+		if (*script->script_p++ == '\n')
+		{
+			if (!crossline)
+				Error ("Line %i is incomplete\n",scriptline);
+			scriptline = script->line++;
+		}
+	}
+
+	if (script->script_p >= script->end_p)
+		return EndOfScript (crossline);
+
+	// ; # // comments
+	if (*script->script_p == ';' || *script->script_p == '#'
+		|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
+	{
+		if (!crossline)
+			Error ("Line %i is incomplete\n",scriptline);
+		while (*script->script_p++ != '\n')
+			if (script->script_p >= script->end_p)
+				return EndOfScript (crossline);
+		goto skipspace;
+	}
+
+	// /* */ comments
+	if (script->script_p[0] == '/' && script->script_p[1] == '*')
+	{
+		if (!crossline)
+			Error ("Line %i is incomplete\n",scriptline);
+		script->script_p+=2;
+		while (script->script_p[0] != '*' && script->script_p[1] != '/')
+		{
+			script->script_p++;
+			if (script->script_p >= script->end_p)
+				return EndOfScript (crossline);
+		}
+		script->script_p += 2;
+		goto skipspace;
+	}
+
+//
+// copy token
+//
+	token_p = token;
+
+	if (*script->script_p == '"')
+	{
+		// quoted token
+		script->script_p++;
+		while (*script->script_p != '"')
+		{
+			*token_p++ = *script->script_p++;
+			if (script->script_p == script->end_p)
+				break;
+			if (token_p == &token[MAXTOKEN])
+				Error ("Token too large on line %i\n",scriptline);
+		}
+		script->script_p++;
+	}
+	else	// regular token
+	while ( *script->script_p > 32 && *script->script_p != ';')
+	{
+		*token_p++ = *script->script_p++;
+		if (script->script_p == script->end_p)
+			break;
+		if (token_p == &token[MAXTOKEN])
+			Error ("Token too large on line %i\n",scriptline);
+	}
+
+	*token_p = 0;
+
+	if (!strcmp (token, "$include"))
+	{
+		GetToken (false);
+		AddScriptToStack (token);
+		return GetToken (crossline);
+	}
+
+	return true;
+}
+
+
+/*
+==============
+TokenAvailable
+
+Returns true if there is another token on the line
+==============
+*/
+qboolean TokenAvailable (void)
+{
+	char    *search_p;
+
+	search_p = script->script_p;
+
+	if (search_p >= script->end_p)
+		return false;
+
+	while ( *search_p <= 32)
+	{
+		if (*search_p == '\n')
+			return false;
+		search_p++;
+		if (search_p == script->end_p)
+			return false;
+
+	}
+
+	if (*search_p == ';')
+		return false;
+
+	return true;
+}
+
+
diff --git a/tools/quake2/common/scriplib.h b/tools/quake2/common/scriplib.h
index 05b67ce0..48a75c6a 100644
--- a/tools/quake2/common/scriplib.h
+++ b/tools/quake2/common/scriplib.h
@@ -1,43 +1,43 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// scriplib.h
-
-#ifndef __CMDLIB__
-#include "cmdlib.h"
-#endif
-
-#define	MAXTOKEN	1024
-
-extern	char	token[MAXTOKEN];
-extern	char	*scriptbuffer,*script_p,*scriptend_p;
-extern	int		grabbed;
-extern	int		scriptline;
-extern	qboolean	endofscript;
-
-
-void LoadScriptFile (char *filename);
-void ParseFromMemory (char *buffer, int size);
-
-qboolean GetToken (qboolean crossline);
-void UnGetToken (void);
-qboolean TokenAvailable (void);
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// scriplib.h
+
+#ifndef __CMDLIB__
+#include "cmdlib.h"
+#endif
+
+#define	MAXTOKEN	1024
+
+extern	char	token[MAXTOKEN];
+extern	char	*scriptbuffer,*script_p,*scriptend_p;
+extern	int		grabbed;
+extern	int		scriptline;
+extern	qboolean	endofscript;
+
+
+void LoadScriptFile (char *filename);
+void ParseFromMemory (char *buffer, int size);
+
+qboolean GetToken (qboolean crossline);
+void UnGetToken (void);
+qboolean TokenAvailable (void);
+
+
diff --git a/tools/quake2/common/threads.c b/tools/quake2/common/threads.c
index 9de00199..a2e8a810 100644
--- a/tools/quake2/common/threads.c
+++ b/tools/quake2/common/threads.c
@@ -1,622 +1,622 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef WIN32
-// The below define is necessary to use
-// pthreads extensions like pthread_mutexattr_settype
-#define _GNU_SOURCE
-#include <pthread.h>
-#endif
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include "q2_threads.h"
-
-#define	MAX_THREADS	64
-
-int		dispatch;
-int		workcount;
-int		oldf;
-qboolean		pacifier;
-
-qboolean	threaded;
-
-/*
-=============
-GetThreadWork
-
-=============
-*/
-int	GetThreadWork (void)
-{
-	int	r;
-	int	f;
-
-	ThreadLock ();
-
-	if (dispatch == workcount)
-	{
-		ThreadUnlock ();
-		return -1;
-	}
-
-	f = 10*dispatch / workcount;
-	if (f != oldf)
-	{
-		oldf = f;
-		if (pacifier)
-		{
-			Sys_Printf ("%i...", f);
-			fflush( stdout );	/* ydnar */
-		}
-	}
-
-	r = dispatch;
-	dispatch++;
-	ThreadUnlock ();
-
-	return r;
-}
-
-
-void (*workfunction) (int);
-
-void ThreadWorkerFunction (int threadnum)
-{
-	int		work;
-
-	while (1)
-	{
-		work = GetThreadWork ();
-		if (work == -1)
-			break;
-		//Sys_FPrintf( SYS_VRB,"thread %i, work %i\n", threadnum, work);
-		workfunction(work);
-	}
-}
-
-void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	if (numthreads == -1)
-		ThreadSetDefault ();
-	workfunction = func;
-  RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
-}
-
-
-/*
-===================================================================
-
-WIN32
-
-===================================================================
-*/
-#ifdef _WIN32
-
-#define	USED
-
-#include <windows.h>
-
-// Setting default Threads to 1
-int		numthreads = 1;
-CRITICAL_SECTION		crit;
-static int enter;
-
-void ThreadSetDefault (void)
-{
-	SYSTEM_INFO info;
-
-	if (numthreads == -1)	// not set manually
-	{
-		GetSystemInfo (&info);
-		numthreads = info.dwNumberOfProcessors;
-		if (numthreads < 1 || numthreads > 32)
-			numthreads = 1;
-	}
-
-	Sys_Printf ("%i threads\n", numthreads);
-}
-
-
-void ThreadLock (void)
-{
-	if (!threaded)
-		return;
-	EnterCriticalSection (&crit);
-	if (enter)
-		Error ("Recursive ThreadLock\n");
-	enter = 1;
-}
-
-void ThreadUnlock (void)
-{
-	if (!threaded)
-		return;
-	if (!enter)
-		Error ("ThreadUnlock without lock\n");
-	enter = 0;
-	LeaveCriticalSection (&crit);
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		threadid[MAX_THREADS];
-	HANDLE	threadhandle[MAX_THREADS];
-	int		i;
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = true;
-
-	//
-	// run threads in parallel
-	//
-	InitializeCriticalSection (&crit);
-
-	if (numthreads == 1)
-	{	// use same thread
-		func (0);
-	}
-	else
-	{
-		for (i=0 ; i<numthreads ; i++)
-		{
-			threadhandle[i] = CreateThread(
-			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
-			   //0,		// DWORD cbStack,
-
-				/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
-				(4096 * 1024),
-
-			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
-			   (LPVOID)i,	// LPVOID lpvThreadParm,
-			   0,			//   DWORD fdwCreate,
-			   &threadid[i]);
-		}
-
-		for (i=0 ; i<numthreads ; i++)
-			WaitForSingleObject (threadhandle[i], INFINITE);
-	}
-	DeleteCriticalSection (&crit);
-
-	threaded = false;
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-/*
-===================================================================
-
-OSF1
-
-===================================================================
-*/
-
-#ifdef __osf__
-#define	USED
-
-int		numthreads = 4;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)	// not set manually
-	{
-		numthreads = 4;
-	}
-}
-
-
-#include <pthread.h>
-
-pthread_mutex_t	*my_mutex;
-
-void ThreadLock (void)
-{
-	if (my_mutex)
-		pthread_mutex_lock (my_mutex);
-}
-
-void ThreadUnlock (void)
-{
-	if (my_mutex)
-		pthread_mutex_unlock (my_mutex);
-}
-
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	pthread_t	work_threads[MAX_THREADS];
-	pthread_addr_t	status;
-	pthread_attr_t	attrib;
-	pthread_mutexattr_t	mattrib;
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = true;
-
-	if (pacifier)
-		setbuf (stdout, NULL);
-
-	if (!my_mutex)
-	{
-		my_mutex = safe_malloc (sizeof(*my_mutex));
-		if (pthread_mutexattr_create (&mattrib) == -1)
-			Error ("pthread_mutex_attr_create failed");
-		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
-			Error ("pthread_mutexattr_setkind_np failed");
-		if (pthread_mutex_init (my_mutex, mattrib) == -1)
-			Error ("pthread_mutex_init failed");
-	}
-
-	if (pthread_attr_create (&attrib) == -1)
-		Error ("pthread_attr_create failed");
-	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
-		Error ("pthread_attr_setstacksize failed");
-	
-	for (i=0 ; i<numthreads ; i++)
-	{
-  		if (pthread_create(&work_threads[i], attrib
-		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
-			Error ("pthread_create failed");
-	}
-		
-	for (i=0 ; i<numthreads ; i++)
-	{
-		if (pthread_join (work_threads[i], &status) == -1)
-			Error ("pthread_join failed");
-	}
-
-	threaded = false;
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-/*
-===================================================================
-
-IRIX
-
-===================================================================
-*/
-
-#ifdef _MIPS_ISA 
-#define	USED
-
-#include <task.h>
-#include <abi_mutex.h>
-#include <sys/types.h>
-#include <sys/prctl.h>
-
-
-int		numthreads = -1;
-abilock_t		lck;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)
-		numthreads = prctl(PR_MAXPPROCS);
-	Sys_Printf ("%i threads\n", numthreads);
-	usconfig (CONF_INITUSERS, numthreads);
-}
-
-
-void ThreadLock (void)
-{
-	spin_lock (&lck);
-}
-
-void ThreadUnlock (void)
-{
-	release_lock (&lck);
-}
-
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	int		pid[MAX_THREADS];
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = true;
-
-	if (pacifier)
-		setbuf (stdout, NULL);
-
-	init_lock (&lck);
-
-	for (i=0 ; i<numthreads-1 ; i++)
-	{
-		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
-			, NULL, 0x200000);		// 2 meg stacks
-		if (pid[i] == -1)
-		{
-			perror ("sproc");
-			Error ("sproc failed");
-		}
-	}
-		
-	func(i);
-			
-	for (i=0 ; i<numthreads-1 ; i++)
-		wait (NULL);
-
-	threaded = false;
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-
-/*
-=======================================================================
-
-  Linux pthreads
-
-=======================================================================
-*/
-
-#if defined( __linux__ ) || defined( __APPLE__ )
-#define USED
-
-// Setting default Threads to 1
-int		numthreads = 1;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)	// not set manually
-	{
-    /* default to one thread, only multi-thread when specifically told to */
-		numthreads = 1;
-	}
-  if(numthreads > 1)
-    Sys_Printf("threads: %d\n", numthreads);
-}
-
-#include <pthread.h>
-
-typedef struct pt_mutex_s
-{
-  pthread_t       *owner;
-  pthread_mutex_t a_mutex;
-  pthread_cond_t  cond;
-  unsigned int    lock;
-} pt_mutex_t;
-
-pt_mutex_t global_lock;
-
-void ThreadLock(void)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-
-  if(!threaded)
-    return;
-
-  pthread_mutex_lock(&pt_mutex->a_mutex);
-  if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner)) 
-    pt_mutex->lock++;
-  else
-  {
-    if((!pt_mutex->owner) && (pt_mutex->lock == 0))
-    {
-      pt_mutex->owner = (pthread_t *)pthread_self();
-      pt_mutex->lock  = 1;
-    }
-    else
-    {
-      while(1)
-      {
-        pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
-        if((!pt_mutex->owner) && (pt_mutex->lock == 0))
-        {
-          pt_mutex->owner = (pthread_t *)pthread_self();
-          pt_mutex->lock  = 1;
-          break;
-        }
-      }
-    }
-  }
-  pthread_mutex_unlock(&pt_mutex->a_mutex);
-}
-
-void ThreadUnlock(void)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-  
-  if(!threaded)
-    return;
-
-  pthread_mutex_lock(&pt_mutex->a_mutex);
-  pt_mutex->lock--;
-  
-  if(pt_mutex->lock == 0)
-  {
-    pt_mutex->owner = NULL;
-    pthread_cond_signal(&pt_mutex->cond);
-  }
-  
-  pthread_mutex_unlock(&pt_mutex->a_mutex);
-}
-
-void recursive_mutex_init(pthread_mutexattr_t attribs)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-  
-  pt_mutex->owner = NULL;
-  if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
-    Error("pthread_mutex_init failed\n");
-  if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
-    Error("pthread_cond_init failed\n");
-  
-  pt_mutex->lock = 0;
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-  pthread_mutexattr_t         mattrib;
-  pthread_t work_threads[MAX_THREADS];
-  
-  int	  start, end;
-  int   i=0, status=0;
-  
-  start     = I_FloatTime ();
-  pacifier  = showpacifier;
-  
-  dispatch  = 0;
-  oldf      = -1;
-  workcount = workcnt;
-  
-  if(numthreads == 1)
-    func(0);
-  else
-  {    
-    threaded  = true;
-      
-    if(pacifier)
-      setbuf(stdout, NULL);
-
-    if(pthread_mutexattr_init(&mattrib) != 0)
-      Error("pthread_mutexattr_init failed");
-#if __GLIBC_MINOR__ == 1
-    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
-#else
-    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
-#endif
-      Error ("pthread_mutexattr_settype failed");
-    recursive_mutex_init(mattrib);
-
-    for (i=0 ; i<numthreads ; i++)
-    {
-      /* Default pthread attributes: joinable & non-realtime scheduling */
-      if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
-        Error("pthread_create failed");
-    }
-    for (i=0 ; i<numthreads ; i++)
-    {
-      if(pthread_join(work_threads[i], (void **)&status) != 0)
-        Error("pthread_join failed");
-    }
-    pthread_mutexattr_destroy(&mattrib);
-    threaded = false;
-  }
-  
-  end = I_FloatTime ();
-  if (pacifier)
-    Sys_Printf (" (%i)\n", end-start);
-}
-#endif // ifdef __linux__
-
-
-/*
-=======================================================================
-
-  SINGLE THREAD
-
-=======================================================================
-*/
-
-#ifndef USED
-
-int		numthreads = 1;
-
-void ThreadSetDefault (void)
-{
-	numthreads = 1;
-}
-
-void ThreadLock (void)
-{
-}
-
-void ThreadUnlock (void)
-{
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	int		start, end;
-
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	start = I_FloatTime (); 
-	func(0);
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef WIN32
+// The below define is necessary to use
+// pthreads extensions like pthread_mutexattr_settype
+#define _GNU_SOURCE
+#include <pthread.h>
+#endif
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include "q2_threads.h"
+
+#define	MAX_THREADS	64
+
+int		dispatch;
+int		workcount;
+int		oldf;
+qboolean		pacifier;
+
+qboolean	threaded;
+
+/*
+=============
+GetThreadWork
+
+=============
+*/
+int	GetThreadWork (void)
+{
+	int	r;
+	int	f;
+
+	ThreadLock ();
+
+	if (dispatch == workcount)
+	{
+		ThreadUnlock ();
+		return -1;
+	}
+
+	f = 10*dispatch / workcount;
+	if (f != oldf)
+	{
+		oldf = f;
+		if (pacifier)
+		{
+			Sys_Printf ("%i...", f);
+			fflush( stdout );	/* ydnar */
+		}
+	}
+
+	r = dispatch;
+	dispatch++;
+	ThreadUnlock ();
+
+	return r;
+}
+
+
+void (*workfunction) (int);
+
+void ThreadWorkerFunction (int threadnum)
+{
+	int		work;
+
+	while (1)
+	{
+		work = GetThreadWork ();
+		if (work == -1)
+			break;
+		//Sys_FPrintf( SYS_VRB,"thread %i, work %i\n", threadnum, work);
+		workfunction(work);
+	}
+}
+
+void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	if (numthreads == -1)
+		ThreadSetDefault ();
+	workfunction = func;
+  RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
+}
+
+
+/*
+===================================================================
+
+WIN32
+
+===================================================================
+*/
+#ifdef _WIN32
+
+#define	USED
+
+#include <windows.h>
+
+// Setting default Threads to 1
+int		numthreads = 1;
+CRITICAL_SECTION		crit;
+static int enter;
+
+void ThreadSetDefault (void)
+{
+	SYSTEM_INFO info;
+
+	if (numthreads == -1)	// not set manually
+	{
+		GetSystemInfo (&info);
+		numthreads = info.dwNumberOfProcessors;
+		if (numthreads < 1 || numthreads > 32)
+			numthreads = 1;
+	}
+
+	Sys_Printf ("%i threads\n", numthreads);
+}
+
+
+void ThreadLock (void)
+{
+	if (!threaded)
+		return;
+	EnterCriticalSection (&crit);
+	if (enter)
+		Error ("Recursive ThreadLock\n");
+	enter = 1;
+}
+
+void ThreadUnlock (void)
+{
+	if (!threaded)
+		return;
+	if (!enter)
+		Error ("ThreadUnlock without lock\n");
+	enter = 0;
+	LeaveCriticalSection (&crit);
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		threadid[MAX_THREADS];
+	HANDLE	threadhandle[MAX_THREADS];
+	int		i;
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = true;
+
+	//
+	// run threads in parallel
+	//
+	InitializeCriticalSection (&crit);
+
+	if (numthreads == 1)
+	{	// use same thread
+		func (0);
+	}
+	else
+	{
+		for (i=0 ; i<numthreads ; i++)
+		{
+			threadhandle[i] = CreateThread(
+			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
+			   //0,		// DWORD cbStack,
+
+				/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
+				(4096 * 1024),
+
+			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
+			   (LPVOID)i,	// LPVOID lpvThreadParm,
+			   0,			//   DWORD fdwCreate,
+			   &threadid[i]);
+		}
+
+		for (i=0 ; i<numthreads ; i++)
+			WaitForSingleObject (threadhandle[i], INFINITE);
+	}
+	DeleteCriticalSection (&crit);
+
+	threaded = false;
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+/*
+===================================================================
+
+OSF1
+
+===================================================================
+*/
+
+#ifdef __osf__
+#define	USED
+
+int		numthreads = 4;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)	// not set manually
+	{
+		numthreads = 4;
+	}
+}
+
+
+#include <pthread.h>
+
+pthread_mutex_t	*my_mutex;
+
+void ThreadLock (void)
+{
+	if (my_mutex)
+		pthread_mutex_lock (my_mutex);
+}
+
+void ThreadUnlock (void)
+{
+	if (my_mutex)
+		pthread_mutex_unlock (my_mutex);
+}
+
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	pthread_t	work_threads[MAX_THREADS];
+	pthread_addr_t	status;
+	pthread_attr_t	attrib;
+	pthread_mutexattr_t	mattrib;
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = true;
+
+	if (pacifier)
+		setbuf (stdout, NULL);
+
+	if (!my_mutex)
+	{
+		my_mutex = safe_malloc (sizeof(*my_mutex));
+		if (pthread_mutexattr_create (&mattrib) == -1)
+			Error ("pthread_mutex_attr_create failed");
+		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
+			Error ("pthread_mutexattr_setkind_np failed");
+		if (pthread_mutex_init (my_mutex, mattrib) == -1)
+			Error ("pthread_mutex_init failed");
+	}
+
+	if (pthread_attr_create (&attrib) == -1)
+		Error ("pthread_attr_create failed");
+	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
+		Error ("pthread_attr_setstacksize failed");
+	
+	for (i=0 ; i<numthreads ; i++)
+	{
+  		if (pthread_create(&work_threads[i], attrib
+		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
+			Error ("pthread_create failed");
+	}
+		
+	for (i=0 ; i<numthreads ; i++)
+	{
+		if (pthread_join (work_threads[i], &status) == -1)
+			Error ("pthread_join failed");
+	}
+
+	threaded = false;
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+/*
+===================================================================
+
+IRIX
+
+===================================================================
+*/
+
+#ifdef _MIPS_ISA 
+#define	USED
+
+#include <task.h>
+#include <abi_mutex.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+
+
+int		numthreads = -1;
+abilock_t		lck;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)
+		numthreads = prctl(PR_MAXPPROCS);
+	Sys_Printf ("%i threads\n", numthreads);
+	usconfig (CONF_INITUSERS, numthreads);
+}
+
+
+void ThreadLock (void)
+{
+	spin_lock (&lck);
+}
+
+void ThreadUnlock (void)
+{
+	release_lock (&lck);
+}
+
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	int		pid[MAX_THREADS];
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = true;
+
+	if (pacifier)
+		setbuf (stdout, NULL);
+
+	init_lock (&lck);
+
+	for (i=0 ; i<numthreads-1 ; i++)
+	{
+		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
+			, NULL, 0x200000);		// 2 meg stacks
+		if (pid[i] == -1)
+		{
+			perror ("sproc");
+			Error ("sproc failed");
+		}
+	}
+		
+	func(i);
+			
+	for (i=0 ; i<numthreads-1 ; i++)
+		wait (NULL);
+
+	threaded = false;
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+
+/*
+=======================================================================
+
+  Linux pthreads
+
+=======================================================================
+*/
+
+#if defined( __linux__ ) || defined( __APPLE__ )
+#define USED
+
+// Setting default Threads to 1
+int		numthreads = 1;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)	// not set manually
+	{
+    /* default to one thread, only multi-thread when specifically told to */
+		numthreads = 1;
+	}
+  if(numthreads > 1)
+    Sys_Printf("threads: %d\n", numthreads);
+}
+
+#include <pthread.h>
+
+typedef struct pt_mutex_s
+{
+  pthread_t       *owner;
+  pthread_mutex_t a_mutex;
+  pthread_cond_t  cond;
+  unsigned int    lock;
+} pt_mutex_t;
+
+pt_mutex_t global_lock;
+
+void ThreadLock(void)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+
+  if(!threaded)
+    return;
+
+  pthread_mutex_lock(&pt_mutex->a_mutex);
+  if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner)) 
+    pt_mutex->lock++;
+  else
+  {
+    if((!pt_mutex->owner) && (pt_mutex->lock == 0))
+    {
+      pt_mutex->owner = (pthread_t *)pthread_self();
+      pt_mutex->lock  = 1;
+    }
+    else
+    {
+      while(1)
+      {
+        pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
+        if((!pt_mutex->owner) && (pt_mutex->lock == 0))
+        {
+          pt_mutex->owner = (pthread_t *)pthread_self();
+          pt_mutex->lock  = 1;
+          break;
+        }
+      }
+    }
+  }
+  pthread_mutex_unlock(&pt_mutex->a_mutex);
+}
+
+void ThreadUnlock(void)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+  
+  if(!threaded)
+    return;
+
+  pthread_mutex_lock(&pt_mutex->a_mutex);
+  pt_mutex->lock--;
+  
+  if(pt_mutex->lock == 0)
+  {
+    pt_mutex->owner = NULL;
+    pthread_cond_signal(&pt_mutex->cond);
+  }
+  
+  pthread_mutex_unlock(&pt_mutex->a_mutex);
+}
+
+void recursive_mutex_init(pthread_mutexattr_t attribs)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+  
+  pt_mutex->owner = NULL;
+  if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
+    Error("pthread_mutex_init failed\n");
+  if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
+    Error("pthread_cond_init failed\n");
+  
+  pt_mutex->lock = 0;
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+  pthread_mutexattr_t         mattrib;
+  pthread_t work_threads[MAX_THREADS];
+  
+  int	  start, end;
+  int   i=0, status=0;
+  
+  start     = I_FloatTime ();
+  pacifier  = showpacifier;
+  
+  dispatch  = 0;
+  oldf      = -1;
+  workcount = workcnt;
+  
+  if(numthreads == 1)
+    func(0);
+  else
+  {    
+    threaded  = true;
+      
+    if(pacifier)
+      setbuf(stdout, NULL);
+
+    if(pthread_mutexattr_init(&mattrib) != 0)
+      Error("pthread_mutexattr_init failed");
+#if __GLIBC_MINOR__ == 1
+    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
+#else
+    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
+#endif
+      Error ("pthread_mutexattr_settype failed");
+    recursive_mutex_init(mattrib);
+
+    for (i=0 ; i<numthreads ; i++)
+    {
+      /* Default pthread attributes: joinable & non-realtime scheduling */
+      if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
+        Error("pthread_create failed");
+    }
+    for (i=0 ; i<numthreads ; i++)
+    {
+      if(pthread_join(work_threads[i], (void **)&status) != 0)
+        Error("pthread_join failed");
+    }
+    pthread_mutexattr_destroy(&mattrib);
+    threaded = false;
+  }
+  
+  end = I_FloatTime ();
+  if (pacifier)
+    Sys_Printf (" (%i)\n", end-start);
+}
+#endif // ifdef __linux__
+
+
+/*
+=======================================================================
+
+  SINGLE THREAD
+
+=======================================================================
+*/
+
+#ifndef USED
+
+int		numthreads = 1;
+
+void ThreadSetDefault (void)
+{
+	numthreads = 1;
+}
+
+void ThreadLock (void)
+{
+}
+
+void ThreadUnlock (void)
+{
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	int		start, end;
+
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	start = I_FloatTime (); 
+	func(0);
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+#endif
diff --git a/tools/quake2/common/trilib.c b/tools/quake2/common/trilib.c
index 11f718f5..05b0cf36 100644
--- a/tools/quake2/common/trilib.c
+++ b/tools/quake2/common/trilib.c
@@ -1,186 +1,186 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-//
-// trilib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "trilib.h"
-
-// on disk representation of a face
-
-
-#define	FLOAT_START	99999.0
-#define	FLOAT_END	-FLOAT_START
-#define MAGIC       123322
-
-//#define NOISY 1
-
-typedef struct {
-	float v[3];
-} vector;
-
-typedef struct
-{
-	vector n;    /* normal */
-	vector p;    /* point */
-	vector c;    /* color */
-	float  u;    /* u */
-	float  v;    /* v */
-} aliaspoint_t;
-
-typedef struct {
-	aliaspoint_t	pt[3];
-} tf_triangle;
-
-
-void ByteSwapTri (tf_triangle *tri)
-{
-	int		i;
-	
-	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
-	{
-		((int *)tri)[i] = BigLong (((int *)tri)[i]);
-	}
-}
-
-void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
-{
-	FILE        *input;
-	float       start;
-	char        name[256], tex[256];
-	int         i, count, magic;
-	tf_triangle	tri;
-	triangle_t	*ptri;
-	int			iLevel;
-	int			exitpattern;
-	float		t;
-
-	t = -FLOAT_START;
-	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
-	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
-	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
-	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
-
-	if ((input = fopen(filename, "rb")) == 0)
-		Error ("reader: could not open file '%s'", filename);
-
-	iLevel = 0;
-
-	fread(&magic, sizeof(int), 1, input);
-	if (BigLong(magic) != MAGIC)
-		Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
-
-	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
-
-	*pptri = ptri;
-
-	while (feof(input) == 0) {
-		if (fread(&start,  sizeof(float), 1, input) < 1)
-			break;
-		*(int *)&start = BigLong(*(int *)&start);
-		if (*(int *)&start != exitpattern)
-		{
-			if (start == FLOAT_START) {
-				/* Start of an object or group of objects. */
-				i = -1;
-				do {
-					/* There are probably better ways to read a string from */
-					/* a file, but this does allow you to do error checking */
-					/* (which I'm not doing) on a per character basis.      */
-					++i;
-					fread( &(name[i]), sizeof( char ), 1, input);
-				} while( name[i] != '\0' );
-	
-//				indent();
-//				fprintf(stdout,"OBJECT START: %s\n",name);
-				fread( &count, sizeof(int), 1, input);
-				count = BigLong(count);
-				++iLevel;
-				if (count != 0) {
-//					indent();
-//					fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
-	
-					i = -1;
-					do {
-						++i;
-						fread( &(tex[i]), sizeof( char ), 1, input);
-					} while( tex[i] != '\0' );
-	
-//					indent();
-//					fprintf(stdout,"  Object texture name: '%s'\n",tex);
-				}
-	
-				/* Else (count == 0) this is the start of a group, and */
-				/* no texture name is present. */
-			}
-			else if (start == FLOAT_END) {
-				/* End of an object or group. Yes, the name should be */
-				/* obvious from context, but it is in here just to be */
-				/* safe and to provide a little extra information for */
-				/* those who do not wish to write a recursive reader. */
-				/* Mia culpa. */
-				--iLevel;
-				i = -1;
-				do {
-					++i;
-					fread( &(name[i]), sizeof( char ), 1, input);
-				} while( name[i] != '\0' );
-	
-//				indent();
-//				fprintf(stdout,"OBJECT END: %s\n",name);
-				continue;
-			}
-		}
-
-//
-// read the triangles
-//		
-		for (i = 0; i < count; ++i) {
-			int		j;
-
-			fread( &tri, sizeof(tf_triangle), 1, input );
-			ByteSwapTri (&tri);
-			for (j=0 ; j<3 ; j++)
-			{
-				int		k;
-
-				for (k=0 ; k<3 ; k++)
-				{
-					ptri->verts[j][k] = tri.pt[j].p.v[k];
-				}
-			}
-
-			ptri++;
-
-			if ((ptri - *pptri) >= MAXTRIANGLES)
-				Error ("Error: too many triangles; increase MAXTRIANGLES\n");
-		}
-	}
-
-	*numtriangles = ptri - *pptri;
-
-	fclose (input);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+//
+// trilib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "trilib.h"
+
+// on disk representation of a face
+
+
+#define	FLOAT_START	99999.0
+#define	FLOAT_END	-FLOAT_START
+#define MAGIC       123322
+
+//#define NOISY 1
+
+typedef struct {
+	float v[3];
+} vector;
+
+typedef struct
+{
+	vector n;    /* normal */
+	vector p;    /* point */
+	vector c;    /* color */
+	float  u;    /* u */
+	float  v;    /* v */
+} aliaspoint_t;
+
+typedef struct {
+	aliaspoint_t	pt[3];
+} tf_triangle;
+
+
+void ByteSwapTri (tf_triangle *tri)
+{
+	int		i;
+	
+	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
+	{
+		((int *)tri)[i] = BigLong (((int *)tri)[i]);
+	}
+}
+
+void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
+{
+	FILE        *input;
+	float       start;
+	char        name[256], tex[256];
+	int         i, count, magic;
+	tf_triangle	tri;
+	triangle_t	*ptri;
+	int			iLevel;
+	int			exitpattern;
+	float		t;
+
+	t = -FLOAT_START;
+	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
+	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
+	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
+	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
+
+	if ((input = fopen(filename, "rb")) == 0)
+		Error ("reader: could not open file '%s'", filename);
+
+	iLevel = 0;
+
+	fread(&magic, sizeof(int), 1, input);
+	if (BigLong(magic) != MAGIC)
+		Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
+
+	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
+
+	*pptri = ptri;
+
+	while (feof(input) == 0) {
+		if (fread(&start,  sizeof(float), 1, input) < 1)
+			break;
+		*(int *)&start = BigLong(*(int *)&start);
+		if (*(int *)&start != exitpattern)
+		{
+			if (start == FLOAT_START) {
+				/* Start of an object or group of objects. */
+				i = -1;
+				do {
+					/* There are probably better ways to read a string from */
+					/* a file, but this does allow you to do error checking */
+					/* (which I'm not doing) on a per character basis.      */
+					++i;
+					fread( &(name[i]), sizeof( char ), 1, input);
+				} while( name[i] != '\0' );
+	
+//				indent();
+//				fprintf(stdout,"OBJECT START: %s\n",name);
+				fread( &count, sizeof(int), 1, input);
+				count = BigLong(count);
+				++iLevel;
+				if (count != 0) {
+//					indent();
+//					fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
+	
+					i = -1;
+					do {
+						++i;
+						fread( &(tex[i]), sizeof( char ), 1, input);
+					} while( tex[i] != '\0' );
+	
+//					indent();
+//					fprintf(stdout,"  Object texture name: '%s'\n",tex);
+				}
+	
+				/* Else (count == 0) this is the start of a group, and */
+				/* no texture name is present. */
+			}
+			else if (start == FLOAT_END) {
+				/* End of an object or group. Yes, the name should be */
+				/* obvious from context, but it is in here just to be */
+				/* safe and to provide a little extra information for */
+				/* those who do not wish to write a recursive reader. */
+				/* Mia culpa. */
+				--iLevel;
+				i = -1;
+				do {
+					++i;
+					fread( &(name[i]), sizeof( char ), 1, input);
+				} while( name[i] != '\0' );
+	
+//				indent();
+//				fprintf(stdout,"OBJECT END: %s\n",name);
+				continue;
+			}
+		}
+
+//
+// read the triangles
+//		
+		for (i = 0; i < count; ++i) {
+			int		j;
+
+			fread( &tri, sizeof(tf_triangle), 1, input );
+			ByteSwapTri (&tri);
+			for (j=0 ; j<3 ; j++)
+			{
+				int		k;
+
+				for (k=0 ; k<3 ; k++)
+				{
+					ptri->verts[j][k] = tri.pt[j].p.v[k];
+				}
+			}
+
+			ptri++;
+
+			if ((ptri - *pptri) >= MAXTRIANGLES)
+				Error ("Error: too many triangles; increase MAXTRIANGLES\n");
+		}
+	}
+
+	*numtriangles = ptri - *pptri;
+
+	fclose (input);
+}
+
diff --git a/tools/quake2/common/trilib.h b/tools/quake2/common/trilib.h
index 406ae1d9..4cdad831 100644
--- a/tools/quake2/common/trilib.h
+++ b/tools/quake2/common/trilib.h
@@ -1,31 +1,31 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-//
-// trilib.h: header file for loading triangles from an Alias triangle file
-//
-#define MAXTRIANGLES	2048
-
-typedef struct {
-	vec3_t	verts[3];
-} triangle_t;
-
-void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+//
+// trilib.h: header file for loading triangles from an Alias triangle file
+//
+#define MAXTRIANGLES	2048
+
+typedef struct {
+	vec3_t	verts[3];
+} triangle_t;
+
+void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles);
+
diff --git a/tools/quake2/q2map/brushbsp.c b/tools/quake2/q2map/brushbsp.c
index 64ebd48e..63f861b7 100644
--- a/tools/quake2/q2map/brushbsp.c
+++ b/tools/quake2/q2map/brushbsp.c
@@ -1,1329 +1,1329 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-
-int		c_nodes;
-int		c_nonvis;
-int		c_active_brushes;
-
-// if a brush just barely pokes onto the other side,
-// let it slide by without chopping
-#define	PLANESIDE_EPSILON	0.001
-//0.1
-
-#define	PSIDE_FRONT			1
-#define	PSIDE_BACK			2
-#define	PSIDE_BOTH			(PSIDE_FRONT|PSIDE_BACK)
-#define	PSIDE_FACING		4
-
-
-void FindBrushInTree (node_t *node, int brushnum)
-{
-	bspbrush_t	*b;
-
-	if (node->planenum == PLANENUM_LEAF)
-	{
-		for (b=node->brushlist ; b ; b=b->next)
-			if (b->original->brushnum == brushnum)
-				Sys_Printf ("here\n");
-		return;
-	}
-	FindBrushInTree (node->children[0], brushnum);
-	FindBrushInTree (node->children[1], brushnum);
-}
-
-//==================================================
-
-/*
-================
-DrawBrushList
-================
-*/
-void DrawBrushList (bspbrush_t *brush, node_t *node)
-{
-	int		i;
-	side_t	*s;
-
-	GLS_BeginScene ();
-	for ( ; brush ; brush=brush->next)
-	{
-		for (i=0 ; i<brush->numsides ; i++)
-		{
-			s = &brush->sides[i];
-			if (!s->winding)
-				continue;
-			if (s->texinfo == TEXINFO_NODE)
-				GLS_Winding (s->winding, 1);
-			else if (!s->visible)
-				GLS_Winding (s->winding, 2);
-			else
-				GLS_Winding (s->winding, 0);
-		}
-	}
-	GLS_EndScene ();
-}
-
-/*
-================
-WriteBrushList
-================
-*/
-void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis)
-{
-	int		i;
-	side_t	*s;
-	FILE	*f;
-
-	Sys_FPrintf( SYS_VRB, "writing %s\n", name);
-	f = SafeOpenWrite (name);
-
-	for ( ; brush ; brush=brush->next)
-	{
-		for (i=0 ; i<brush->numsides ; i++)
-		{
-			s = &brush->sides[i];
-			if (!s->winding)
-				continue;
-			if (onlyvis && !s->visible)
-				continue;
-			OutputWinding (brush->sides[i].winding, f);
-		}
-	}
-
-	fclose (f);
-}
-
-void PrintBrush (bspbrush_t *brush)
-{
-	int		i;
-
-	Sys_Printf ("brush: %p\n", brush);
-	for (i=0;i<brush->numsides ; i++)
-	{
-		pw(brush->sides[i].winding);
-		Sys_Printf ("\n");
-	}
-}
-
-/*
-==================
-BoundBrush
-
-Sets the mins/maxs based on the windings
-==================
-*/
-void BoundBrush (bspbrush_t *brush)
-{
-	int			i, j;
-	winding_t	*w;
-
-	ClearBounds (brush->mins, brush->maxs);
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		for (j=0 ; j<w->numpoints ; j++)
-			AddPointToBounds (w->p[j], brush->mins, brush->maxs);
-	}
-}
-
-/*
-==================
-CreateBrushWindings
-
-==================
-*/
-void CreateBrushWindings (bspbrush_t *brush)
-{
-	int			i, j;
-	winding_t	*w;
-	side_t		*side;
-	plane_t		*plane;
-
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		side = &brush->sides[i];
-		plane = &mapplanes[side->planenum];
-		w = BaseWindingForPlane (plane->normal, plane->dist);
-		for (j=0 ; j<brush->numsides && w; j++)
-		{
-			if (i == j)
-				continue;
-			if (brush->sides[j].bevel)
-				continue;
-			plane = &mapplanes[brush->sides[j].planenum^1];
-			ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
-		}
-
-		side->winding = w;
-	}
-
-	BoundBrush (brush);
-}
-
-/*
-==================
-BrushFromBounds
-
-Creates a new axial brush
-==================
-*/
-bspbrush_t	*BrushFromBounds (vec3_t mins, vec3_t maxs)
-{
-	bspbrush_t	*b;
-	int			i;
-	vec3_t		normal;
-	vec_t		dist;
-
-	b = AllocBrush (6);
-	b->numsides = 6;
-	for (i=0 ; i<3 ; i++)
-	{
-		VectorClear (normal);
-		normal[i] = 1;
-		dist = maxs[i];
-		b->sides[i].planenum = FindFloatPlane (normal, dist);
-
-		normal[i] = -1;
-		dist = -mins[i];
-		b->sides[3+i].planenum = FindFloatPlane (normal, dist);
-	}
-
-	CreateBrushWindings (b);
-
-	return b;
-}
-
-/*
-==================
-BrushVolume
-
-==================
-*/
-vec_t BrushVolume (bspbrush_t *brush)
-{
-	int			i;
-	winding_t	*w;
-	vec3_t		corner;
-	vec_t		d, area, volume;
-	plane_t		*plane;
-
-	if (!brush)
-		return 0;
-
-	// grab the first valid point as the corner
-
-	w = NULL;
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (w)
-			break;
-	}
-	if (!w)
-		return 0;
-	VectorCopy (w->p[0], corner);
-
-	// make tetrahedrons to all other faces
-
-	volume = 0;
-	for ( ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		plane = &mapplanes[brush->sides[i].planenum];
-		d = -(DotProduct (corner, plane->normal) - plane->dist);
-		area = WindingArea (w);
-		volume += d*area;
-	}
-
-	volume /= 3;
-	return volume;
-}
-
-/*
-================
-CountBrushList
-================
-*/
-int	CountBrushList (bspbrush_t *brushes)
-{
-	int	c;
-
-	c = 0;
-	for ( ; brushes ; brushes = brushes->next)
-		c++;
-	return c;
-}
-
-/*
-================
-AllocTree
-================
-*/
-tree_t *AllocTree (void)
-{
-	tree_t	*tree;
-
-	tree = malloc(sizeof(*tree));
-	memset (tree, 0, sizeof(*tree));
-	ClearBounds (tree->mins, tree->maxs);
-
-	return tree;
-}
-
-/*
-================
-AllocNode
-================
-*/
-node_t *AllocNode (void)
-{
-	node_t	*node;
-
-	node = malloc(sizeof(*node));
-	memset (node, 0, sizeof(*node));
-
-	return node;
-}
-
-
-/*
-================
-AllocBrush
-================
-*/
-bspbrush_t *AllocBrush (int numsides)
-{
-	bspbrush_t	*bb;
-	int			c;
-
-	c = (int)&(((bspbrush_t *)0)->sides[numsides]);
-	bb = malloc(c);
-	memset (bb, 0, c);
-	if (numthreads == 1)
-		c_active_brushes++;
-	return bb;
-}
-
-/*
-================
-FreeBrush
-================
-*/
-void FreeBrush (bspbrush_t *brushes)
-{
-	int			i;
-
-	for (i=0 ; i<brushes->numsides ; i++)
-		if (brushes->sides[i].winding)
-			FreeWinding(brushes->sides[i].winding);
-	free (brushes);
-	if (numthreads == 1)
-		c_active_brushes--;
-}
-
-
-/*
-================
-FreeBrushList
-================
-*/
-void FreeBrushList (bspbrush_t *brushes)
-{
-	bspbrush_t	*next;
-
-	for ( ; brushes ; brushes = next)
-	{
-		next = brushes->next;
-
-		FreeBrush (brushes);
-	}		
-}
-
-/*
-==================
-CopyBrush
-
-Duplicates the brush, the sides, and the windings
-==================
-*/
-bspbrush_t *CopyBrush (bspbrush_t *brush)
-{
-	bspbrush_t *newbrush;
-	int			size;
-	int			i;
-	
-	size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]);
-
-	newbrush = AllocBrush (brush->numsides);
-	memcpy (newbrush, brush, size);
-
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		if (brush->sides[i].winding)
-			newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
-	}
-
-	return newbrush;
-}
-
-
-/*
-==================
-PointInLeaf
-
-==================
-*/
-node_t	*PointInLeaf (node_t *node, vec3_t point)
-{
-	vec_t		d;
-	plane_t		*plane;
-
-	while (node->planenum != PLANENUM_LEAF)
-	{
-		plane = &mapplanes[node->planenum];
-		d = DotProduct (point, plane->normal) - plane->dist;
-		if (d > 0)
-			node = node->children[0];
-		else
-			node = node->children[1];
-	}
-
-	return node;
-}
-
-//========================================================
-
-/*
-==============
-BoxOnPlaneSide
-
-Returns PSIDE_FRONT, PSIDE_BACK, or PSIDE_BOTH
-==============
-*/
-int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane)
-{
-	int		side;
-	int		i;
-	vec3_t	corners[2];
-	vec_t	dist1, dist2;
-
-	// axial planes are easy
-	if (plane->type < 3)
-	{
-		side = 0;
-		if (maxs[plane->type] > plane->dist+PLANESIDE_EPSILON)
-			side |= PSIDE_FRONT;
-		if (mins[plane->type] < plane->dist-PLANESIDE_EPSILON)
-			side |= PSIDE_BACK;
-		return side;
-	}
-
-	// create the proper leading and trailing verts for the box
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if (plane->normal[i] < 0)
-		{
-			corners[0][i] = mins[i];
-			corners[1][i] = maxs[i];
-		}
-		else
-		{
-			corners[1][i] = mins[i];
-			corners[0][i] = maxs[i];
-		}
-	}
-
-	dist1 = DotProduct (plane->normal, corners[0]) - plane->dist;
-	dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
-	side = 0;
-	if (dist1 >= PLANESIDE_EPSILON)
-		side = PSIDE_FRONT;
-	if (dist2 < PLANESIDE_EPSILON)
-		side |= PSIDE_BACK;
-
-	return side;
-}
-
-/*
-============
-QuickTestBrushToPlanenum
-
-============
-*/
-int	QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits)
-{
-	int			i, num;
-	plane_t		*plane;
-	int			s;
-
-	*numsplits = 0;
-
-	// if the brush actually uses the planenum,
-	// we can tell the side for sure
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		num = brush->sides[i].planenum;
-		if (num >= 0x10000)
-			Error ("bad planenum");
-		if (num == planenum)
-			return PSIDE_BACK|PSIDE_FACING;
-		if (num == (planenum ^ 1) )
-			return PSIDE_FRONT|PSIDE_FACING;
-	}
-
-	// box on plane side
-	plane = &mapplanes[planenum];
-	s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
-
-	// if both sides, count the visible faces split
-	if (s == PSIDE_BOTH)
-	{
-		*numsplits += 3;
-	}
-
-	return s;
-}
-
-/*
-============
-TestBrushToPlanenum
-
-============
-*/
-int	TestBrushToPlanenum (bspbrush_t *brush, int planenum,
-						 int *numsplits, qboolean *hintsplit, int *epsilonbrush)
-{
-	int			i, j, num;
-	plane_t		*plane;
-	int			s;
-	winding_t	*w;
-	vec_t		d, d_front, d_back;
-	int			front, back;
-
-	*numsplits = 0;
-	*hintsplit = false;
-
-	// if the brush actually uses the planenum,
-	// we can tell the side for sure
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		num = brush->sides[i].planenum;
-		if (num >= 0x10000)
-			Error ("bad planenum");
-		if (num == planenum)
-			return PSIDE_BACK|PSIDE_FACING;
-		if (num == (planenum ^ 1) )
-			return PSIDE_FRONT|PSIDE_FACING;
-	}
-
-	// box on plane side
-	plane = &mapplanes[planenum];
-	s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
-
-	if (s != PSIDE_BOTH)
-		return s;
-
-// if both sides, count the visible faces split
-	d_front = d_back = 0;
-
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		if (brush->sides[i].texinfo == TEXINFO_NODE)
-			continue;		// on node, don't worry about splits
-		if (!brush->sides[i].visible)
-			continue;		// we don't care about non-visible
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		front = back = 0;
-		for (j=0 ; j<w->numpoints; j++)
-		{
-			d = DotProduct (w->p[j], plane->normal) - plane->dist;
-			if (d > d_front)
-				d_front = d;
-			if (d < d_back)
-				d_back = d;
-
-			if (d > 0.1) // PLANESIDE_EPSILON)
-				front = 1;
-			if (d < -0.1) // PLANESIDE_EPSILON)
-				back = 1;
-		}
-		if (front && back)
-		{
-			if ( !(brush->sides[i].surf & SURF_SKIP) )
-			{
-				(*numsplits)++;
-				if (brush->sides[i].surf & SURF_HINT)
-					*hintsplit = true;
-			}
-		}
-	}
-
-	if ( (d_front > 0.0 && d_front < 1.0)
-		|| (d_back < 0.0 && d_back > -1.0) )
-		(*epsilonbrush)++;
-
-#if 0
-	if (*numsplits == 0)
-	{	//	didn't really need to be split
-		if (front)
-			s = PSIDE_FRONT;
-		else if (back)
-			s = PSIDE_BACK;
-		else
-			s = 0;
-	}
-#endif
-
-	return s;
-}
-
-//========================================================
-
-/*
-================
-WindingIsTiny
-
-Returns true if the winding would be crunched out of
-existance by the vertex snapping.
-================
-*/
-#define	EDGE_LENGTH	0.2
-qboolean WindingIsTiny (winding_t *w)
-{
-#if 0
-	if (WindingArea (w) < 1)
-		return true;
-	return false;
-#else
-	int		i, j;
-	vec_t	len;
-	vec3_t	delta;
-	int		edges;
-
-	edges = 0;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		j = i == w->numpoints - 1 ? 0 : i+1;
-		VectorSubtract (w->p[j], w->p[i], delta);
-		len = (float) VectorLength (delta);
-		if (len > EDGE_LENGTH)
-		{
-			if (++edges == 3)
-				return false;
-		}
-	}
-	return true;
-#endif
-}
-
-/*
-================
-WindingIsHuge
-
-Returns true if the winding still has one of the points
-from basewinding for plane
-================
-*/
-qboolean WindingIsHuge (winding_t *w)
-{
-	int		i, j;
-
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-			if (w->p[i][j] < -8000 || w->p[i][j] > 8000)
-				return true;
-	}
-	return false;
-}
-
-//============================================================
-
-/*
-================
-Leafnode
-================
-*/
-void LeafNode (node_t *node, bspbrush_t *brushes)
-{
-	bspbrush_t	*b;
-	int			i;
-
-	node->planenum = PLANENUM_LEAF;
-	node->contents = 0;
-
-	for (b=brushes ; b ; b=b->next)
-	{
-		// if the brush is solid and all of its sides are on nodes,
-		// it eats everything
-		if (b->original->contents & CONTENTS_SOLID)
-		{
-			for (i=0 ; i<b->numsides ; i++)
-				if (b->sides[i].texinfo != TEXINFO_NODE)
-					break;
-			if (i == b->numsides)
-			{
-				node->contents = CONTENTS_SOLID;
-				break;
-			}
-		}
-		node->contents |= b->original->contents;
-	}
-
-	node->brushlist = brushes;
-}
-
-
-//============================================================
-
-void CheckPlaneAgainstParents (int pnum, node_t *node)
-{
-	node_t	*p;
-
-	for (p=node->parent ; p ; p=p->parent)
-	{
-		if (p->planenum == pnum)
-			Error ("Tried parent");
-	}
-}
-
-qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
-{
-	bspbrush_t	*front, *back;
-	qboolean	good;
-
-	SplitBrush (node->volume, pnum, &front, &back);
-
-	good = (front && back);
-
-	if (front)
-		FreeBrush (front);
-	if (back)
-		FreeBrush (back);
-
-	return good;
-}
-
-/*
-================
-SelectSplitSide
-
-Using a hueristic, choses one of the sides out of the brushlist
-to partition the brushes with.
-Returns NULL if there are no valid planes to split with..
-================
-*/
-side_t *SelectSplitSide (bspbrush_t *brushes, node_t *node)
-{
-	int			value, bestvalue;
-	bspbrush_t	*brush, *test;
-	side_t		*side, *bestside;
-	int			i, j, pass, numpasses;
-	int			pnum;
-	int			s;
-	int			front, back, both, facing, splits;
-	int			bsplits;
-	int			bestsplits;
-	int			epsilonbrush;
-	qboolean	hintsplit;
-
-	bestside = NULL;
-	bestvalue = -99999;
-	bestsplits = 0;
-
-	// the search order goes: visible-structural, visible-detail,
-	// nonvisible-structural, nonvisible-detail.
-	// If any valid plane is available in a pass, no further
-	// passes will be tried.
-	numpasses = 4;
-	for (pass = 0 ; pass < numpasses ; pass++)
-	{
-		for (brush = brushes ; brush ; brush=brush->next)
-		{
-			if ( (pass & 1) && !(brush->original->contents & CONTENTS_DETAIL) )
-				continue;
-			if ( !(pass & 1) && (brush->original->contents & CONTENTS_DETAIL) )
-				continue;
-			for (i=0 ; i<brush->numsides ; i++)
-			{
-				side = brush->sides + i;
-				if (side->bevel)
-					continue;	// never use a bevel as a spliter
-				if (!side->winding)
-					continue;	// nothing visible, so it can't split
-				if (side->texinfo == TEXINFO_NODE)
-					continue;	// allready a node splitter
-				if (side->tested)
-					continue;	// we allready have metrics for this plane
-				if (side->surf & SURF_SKIP)
-					continue;	// skip surfaces are never chosen
-				if ( side->visible ^ (pass<2) )
-					continue;	// only check visible faces on first pass
-
-				pnum = side->planenum;
-				pnum &= ~1;	// allways use positive facing plane
-
-				CheckPlaneAgainstParents (pnum, node);
-
-				if (!CheckPlaneAgainstVolume (pnum, node))
-					continue;	// would produce a tiny volume
-
-				front = 0;
-				back = 0;
-				both = 0;
-				facing = 0;
-				splits = 0;
-				epsilonbrush = 0;
-
-				for (test = brushes ; test ; test=test->next)
-				{
-					s = TestBrushToPlanenum (test, pnum, &bsplits, &hintsplit, &epsilonbrush);
-
-					splits += bsplits;
-					if (bsplits && (s&PSIDE_FACING) )
-						Error ("PSIDE_FACING with splits");
-
-					test->testside = s;
-					// if the brush shares this face, don't bother
-					// testing that facenum as a splitter again
-					if (s & PSIDE_FACING)
-					{
-						facing++;
-						for (j=0 ; j<test->numsides ; j++)
-						{
-							if ( (test->sides[j].planenum&~1) == pnum)
-								test->sides[j].tested = true;
-						}
-					}
-					if (s & PSIDE_FRONT)
-						front++;
-					if (s & PSIDE_BACK)
-						back++;
-					if (s == PSIDE_BOTH)
-						both++;
-				}
-
-				// give a value estimate for using this plane
-
-				value =  5*facing - 5*splits - abs(front-back);
-//					value =  -5*splits;
-//					value =  5*facing - 5*splits;
-				if (mapplanes[pnum].type < 3)
-					value+=5;		// axial is better
-				value -= epsilonbrush*1000;	// avoid!
-
-				// never split a hint side except with another hint
-				if (hintsplit && !(side->surf & SURF_HINT) )
-					value = -9999999;
-
-				// save off the side test so we don't need
-				// to recalculate it when we actually seperate
-				// the brushes
-				if (value > bestvalue)
-				{
-					bestvalue = value;
-					bestside = side;
-					bestsplits = splits;
-					for (test = brushes ; test ; test=test->next)
-						test->side = test->testside;
-				}
-			}
-		}
-
-		// if we found a good plane, don't bother trying any
-		// other passes
-		if (bestside)
-		{
-			if (pass > 1)
-			{
-				if (numthreads == 1)
-					c_nonvis++;
-			}
-			if (pass > 0)
-				node->detail_seperator = true;	// not needed for vis
-			break;
-		}
-	}
-
-	//
-	// clear all the tested flags we set
-	//
-	for (brush = brushes ; brush ; brush=brush->next)
-	{
-		for (i=0 ; i<brush->numsides ; i++)
-			brush->sides[i].tested = false;
-	}
-
-	return bestside;
-}
-
-
-/*
-==================
-BrushMostlyOnSide
-
-==================
-*/
-int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane)
-{
-	int			i, j;
-	winding_t	*w;
-	vec_t		d, max;
-	int			side;
-
-	max = 0;
-	side = PSIDE_FRONT;
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			d = DotProduct (w->p[j], plane->normal) - plane->dist;
-			if (d > max)
-			{
-				max = d;
-				side = PSIDE_FRONT;
-			}
-			if (-d > max)
-			{
-				max = -d;
-				side = PSIDE_BACK;
-			}
-		}
-	}
-	return side;
-}
-
-/*
-================
-SplitBrush
-
-Generates two new brushes, leaving the original
-unchanged
-================
-*/
-void SplitBrush (bspbrush_t *brush, int planenum,
-	bspbrush_t **front, bspbrush_t **back)
-{
-	bspbrush_t	*b[2];
-	int			i, j;
-	winding_t	*w, *cw[2], *midwinding;
-	plane_t		*plane, *plane2;
-	side_t		*s, *cs;
-	float		d, d_front, d_back;
-
-	*front = *back = NULL;
-	plane = &mapplanes[planenum];
-
-	// check all points
-	d_front = d_back = 0;
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			d = DotProduct (w->p[j], plane->normal) - plane->dist;
-			if (d > 0 && d > d_front)
-				d_front = d;
-			if (d < 0 && d < d_back)
-				d_back = d;
-		}
-	}
-	if (d_front < 0.1) // PLANESIDE_EPSILON)
-	{	// only on back
-		*back = CopyBrush (brush);
-		return;
-	}
-	if (d_back > -0.1) // PLANESIDE_EPSILON)
-	{	// only on front
-		*front = CopyBrush (brush);
-		return;
-	}
-
-	// create a new winding from the split plane
-
-	w = BaseWindingForPlane (plane->normal, plane->dist);
-	for (i=0 ; i<brush->numsides && w ; i++)
-	{
-		plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
-		ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
-	}
-
-	if (!w || WindingIsTiny (w) )
-	{	// the brush isn't really split
-		int		side;
-
-		side = BrushMostlyOnSide (brush, plane);
-		if (side == PSIDE_FRONT)
-			*front = CopyBrush (brush);
-		if (side == PSIDE_BACK)
-			*back = CopyBrush (brush);
-		return;
-	}
-
-	if (WindingIsHuge (w))
-	{
-		Sys_FPrintf( SYS_VRB, "WARNING: huge winding\n");
-	}
-
-	midwinding = w;
-
-	// split it for real
-
-	for (i=0 ; i<2 ; i++)
-	{
-		b[i] = AllocBrush (brush->numsides+1);
-		b[i]->original = brush->original;
-	}
-
-	// split all the current windings
-
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		s = &brush->sides[i];
-		w = s->winding;
-		if (!w)
-			continue;
-		ClipWindingEpsilon (w, plane->normal, plane->dist,
-			0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
-		for (j=0 ; j<2 ; j++)
-		{
-			if (!cw[j])
-				continue;
-#if 0
-			if (WindingIsTiny (cw[j]))
-			{
-				FreeWinding (cw[j]);
-				continue;
-			}
-#endif
-			cs = &b[j]->sides[b[j]->numsides];
-			b[j]->numsides++;
-			*cs = *s;
-//			cs->planenum = s->planenum;
-//			cs->texinfo = s->texinfo;
-//			cs->visible = s->visible;
-//			cs->original = s->original;
-			cs->winding = cw[j];
-			cs->tested = false;
-		}
-	}
-
-
-	// see if we have valid polygons on both sides
-
-	for (i=0 ; i<2 ; i++)
-	{
-		BoundBrush (b[i]);
-		for (j=0 ; j<3 ; j++)
-		{
-			if (b[i]->mins[j] < -4096 || b[i]->maxs[j] > 4096)
-			{
-				Sys_FPrintf( SYS_VRB, "bogus brush after clip\n");
-				break;
-			}
-		}
-
-		if (b[i]->numsides < 3 || j < 3)
-		{
-			FreeBrush (b[i]);
-			b[i] = NULL;
-		}
-	}
-
-	if ( !(b[0] && b[1]) )
-	{
-		if (!b[0] && !b[1])
-			Sys_FPrintf( SYS_VRB, "split removed brush\n");
-		else
-			Sys_FPrintf( SYS_VRB, "split not on both sides\n");
-		if (b[0])
-		{
-			FreeBrush (b[0]);
-			*front = CopyBrush (brush);
-		}
-		if (b[1])
-		{
-			FreeBrush (b[1]);
-			*back = CopyBrush (brush);
-		}
-		return;
-	}
-
-	// add the midwinding to both sides
-	for (i=0 ; i<2 ; i++)
-	{
-		cs = &b[i]->sides[b[i]->numsides];
-		b[i]->numsides++;
-
-		cs->planenum = planenum^i^1;
-		cs->texinfo = TEXINFO_NODE;
-		cs->visible = false;
-		cs->tested = false;
-		if (i==0)
-			cs->winding = CopyWinding (midwinding);
-		else
-			cs->winding = midwinding;
-	}
-
-{
-	vec_t	v1;
-	int		i;
-
-	for (i=0 ; i<2 ; i++)
-	{
-		v1 = BrushVolume (b[i]);
-		if (v1 < 1.0)
-		{
-			FreeBrush (b[i]);
-			b[i] = NULL;
-			Sys_FPrintf( SYS_VRB, "tiny volume after clip\n");
-		}
-	}
-}
-
-	*front = b[0];
-	*back = b[1];
-}
-
-/*
-================
-SplitBrushList
-================
-*/
-void SplitBrushList (bspbrush_t *brushes, 
-	node_t *node, bspbrush_t **front, bspbrush_t **back)
-{
-	bspbrush_t	*brush, *newbrush, *newbrush2;
-	side_t		*side;
-	int			sides;
-	int			i;
-
-	*front = *back = NULL;
-
-	for (brush = brushes ; brush ; brush=brush->next)
-	{
-		sides = brush->side;
-
-		if (sides == PSIDE_BOTH)
-		{	// split into two brushes
-			SplitBrush (brush, node->planenum, &newbrush, &newbrush2);
-			if (newbrush)
-			{
-				newbrush->next = *front;
-				*front = newbrush;
-			}
-			if (newbrush2)
-			{
-				newbrush2->next = *back;
-				*back = newbrush2;
-			}
-			continue;
-		}
-
-		newbrush = CopyBrush (brush);
-
-		// if the planenum is actualy a part of the brush
-		// find the plane and flag it as used so it won't be tried
-		// as a splitter again
-		if (sides & PSIDE_FACING)
-		{
-			for (i=0 ; i<newbrush->numsides ; i++)
-			{
-				side = newbrush->sides + i;
-				if ( (side->planenum& ~1) == node->planenum)
-					side->texinfo = TEXINFO_NODE;
-			}
-		}
-
-
-		if (sides & PSIDE_FRONT)
-		{
-			newbrush->next = *front;
-			*front = newbrush;
-			continue;
-		}
-		if (sides & PSIDE_BACK)
-		{
-			newbrush->next = *back;
-			*back = newbrush;
-			continue;
-		}
-	}
-}
-
-
-/*
-================
-BuildTree_r
-================
-*/
-node_t *BuildTree_r (node_t *node, bspbrush_t *brushes)
-{
-	node_t		*newnode;
-	side_t		*bestside;
-	int			i;
-	bspbrush_t	*children[2];
-
-	if (numthreads == 1)
-		c_nodes++;
-
-	if (drawflag)
-		DrawBrushList (brushes, node);
-
-	// find the best plane to use as a splitter
-	bestside = SelectSplitSide (brushes, node);
-	if (!bestside)
-	{
-		// leaf node
-		node->side = NULL;
-		node->planenum = -1;
-		LeafNode (node, brushes);
-		return node;
-	}
-
-	// this is a splitplane node
-	node->side = bestside;
-	node->planenum = bestside->planenum & ~1;	// always use front facing
-
-	SplitBrushList (brushes, node, &children[0], &children[1]);
-	FreeBrushList (brushes);
-
-	// allocate children before recursing
-	for (i=0 ; i<2 ; i++)
-	{
-		newnode = AllocNode ();
-		newnode->parent = node;
-		node->children[i] = newnode;
-	}
-
-	SplitBrush (node->volume, node->planenum, &node->children[0]->volume,
-		&node->children[1]->volume);
-
-	// recursively process children
-	for (i=0 ; i<2 ; i++)
-	{
-		node->children[i] = BuildTree_r (node->children[i], children[i]);
-	}
-
-	return node;
-}
-
-//===========================================================
-
-/*
-=================
-BrushBSP
-
-The incoming list will be freed before exiting
-=================
-*/
-tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs)
-{
-	node_t		*node;
-	bspbrush_t	*b;
-	int			c_faces, c_nonvisfaces;
-	int			c_brushes;
-	tree_t		*tree;
-	int			i;
-	vec_t		volume;
-
-	Sys_FPrintf( SYS_VRB, "--- BrushBSP ---\n");
-
-	tree = AllocTree ();
-
-	c_faces = 0;
-	c_nonvisfaces = 0;
-	c_brushes = 0;
-	for (b=brushlist ; b ; b=b->next)
-	{
-		c_brushes++;
-
-		volume = BrushVolume (b);
-		if (volume < microvolume)
-		{
-			Sys_Printf ("WARNING: entity %i, brush %i: microbrush\n",
-				b->original->entitynum, b->original->brushnum);
-		}
-
-		for (i=0 ; i<b->numsides ; i++)
-		{
-			if (b->sides[i].bevel)
-				continue;
-			if (!b->sides[i].winding)
-				continue;
-			if (b->sides[i].texinfo == TEXINFO_NODE)
-				continue;
-			if (b->sides[i].visible)
-				c_faces++;
-			else
-				c_nonvisfaces++;
-		}
-
-		AddPointToBounds (b->mins, tree->mins, tree->maxs);
-		AddPointToBounds (b->maxs, tree->mins, tree->maxs);
-	}
-
-	Sys_FPrintf( SYS_VRB, "%5i brushes\n", c_brushes);
-	Sys_FPrintf( SYS_VRB, "%5i visible faces\n", c_faces);
-	Sys_FPrintf( SYS_VRB, "%5i nonvisible faces\n", c_nonvisfaces);
-
-	c_nodes = 0;
-	c_nonvis = 0;
-	node = AllocNode ();
-
-	node->volume = BrushFromBounds (mins, maxs);
-
-	tree->headnode = node;
-
-	node = BuildTree_r (node, brushlist);
-	Sys_FPrintf( SYS_VRB, "%5i visible nodes\n", c_nodes/2 - c_nonvis);
-	Sys_FPrintf( SYS_VRB, "%5i nonvis nodes\n", c_nonvis);
-	Sys_FPrintf( SYS_VRB, "%5i leafs\n", (c_nodes+1)/2);
-#if 0
-{	// debug code
-static node_t	*tnode;
-vec3_t	p;
-
-p[0] = -1469;
-p[1] = -118;
-p[2] = 119;
-tnode = PointInLeaf (tree->headnode, p);
-Sys_Printf ("contents: %i\n", tnode->contents);
-p[0] = 0;
-}
-#endif
-	return tree;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+
+int		c_nodes;
+int		c_nonvis;
+int		c_active_brushes;
+
+// if a brush just barely pokes onto the other side,
+// let it slide by without chopping
+#define	PLANESIDE_EPSILON	0.001
+//0.1
+
+#define	PSIDE_FRONT			1
+#define	PSIDE_BACK			2
+#define	PSIDE_BOTH			(PSIDE_FRONT|PSIDE_BACK)
+#define	PSIDE_FACING		4
+
+
+void FindBrushInTree (node_t *node, int brushnum)
+{
+	bspbrush_t	*b;
+
+	if (node->planenum == PLANENUM_LEAF)
+	{
+		for (b=node->brushlist ; b ; b=b->next)
+			if (b->original->brushnum == brushnum)
+				Sys_Printf ("here\n");
+		return;
+	}
+	FindBrushInTree (node->children[0], brushnum);
+	FindBrushInTree (node->children[1], brushnum);
+}
+
+//==================================================
+
+/*
+================
+DrawBrushList
+================
+*/
+void DrawBrushList (bspbrush_t *brush, node_t *node)
+{
+	int		i;
+	side_t	*s;
+
+	GLS_BeginScene ();
+	for ( ; brush ; brush=brush->next)
+	{
+		for (i=0 ; i<brush->numsides ; i++)
+		{
+			s = &brush->sides[i];
+			if (!s->winding)
+				continue;
+			if (s->texinfo == TEXINFO_NODE)
+				GLS_Winding (s->winding, 1);
+			else if (!s->visible)
+				GLS_Winding (s->winding, 2);
+			else
+				GLS_Winding (s->winding, 0);
+		}
+	}
+	GLS_EndScene ();
+}
+
+/*
+================
+WriteBrushList
+================
+*/
+void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis)
+{
+	int		i;
+	side_t	*s;
+	FILE	*f;
+
+	Sys_FPrintf( SYS_VRB, "writing %s\n", name);
+	f = SafeOpenWrite (name);
+
+	for ( ; brush ; brush=brush->next)
+	{
+		for (i=0 ; i<brush->numsides ; i++)
+		{
+			s = &brush->sides[i];
+			if (!s->winding)
+				continue;
+			if (onlyvis && !s->visible)
+				continue;
+			OutputWinding (brush->sides[i].winding, f);
+		}
+	}
+
+	fclose (f);
+}
+
+void PrintBrush (bspbrush_t *brush)
+{
+	int		i;
+
+	Sys_Printf ("brush: %p\n", brush);
+	for (i=0;i<brush->numsides ; i++)
+	{
+		pw(brush->sides[i].winding);
+		Sys_Printf ("\n");
+	}
+}
+
+/*
+==================
+BoundBrush
+
+Sets the mins/maxs based on the windings
+==================
+*/
+void BoundBrush (bspbrush_t *brush)
+{
+	int			i, j;
+	winding_t	*w;
+
+	ClearBounds (brush->mins, brush->maxs);
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		for (j=0 ; j<w->numpoints ; j++)
+			AddPointToBounds (w->p[j], brush->mins, brush->maxs);
+	}
+}
+
+/*
+==================
+CreateBrushWindings
+
+==================
+*/
+void CreateBrushWindings (bspbrush_t *brush)
+{
+	int			i, j;
+	winding_t	*w;
+	side_t		*side;
+	plane_t		*plane;
+
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		side = &brush->sides[i];
+		plane = &mapplanes[side->planenum];
+		w = BaseWindingForPlane (plane->normal, plane->dist);
+		for (j=0 ; j<brush->numsides && w; j++)
+		{
+			if (i == j)
+				continue;
+			if (brush->sides[j].bevel)
+				continue;
+			plane = &mapplanes[brush->sides[j].planenum^1];
+			ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
+		}
+
+		side->winding = w;
+	}
+
+	BoundBrush (brush);
+}
+
+/*
+==================
+BrushFromBounds
+
+Creates a new axial brush
+==================
+*/
+bspbrush_t	*BrushFromBounds (vec3_t mins, vec3_t maxs)
+{
+	bspbrush_t	*b;
+	int			i;
+	vec3_t		normal;
+	vec_t		dist;
+
+	b = AllocBrush (6);
+	b->numsides = 6;
+	for (i=0 ; i<3 ; i++)
+	{
+		VectorClear (normal);
+		normal[i] = 1;
+		dist = maxs[i];
+		b->sides[i].planenum = FindFloatPlane (normal, dist);
+
+		normal[i] = -1;
+		dist = -mins[i];
+		b->sides[3+i].planenum = FindFloatPlane (normal, dist);
+	}
+
+	CreateBrushWindings (b);
+
+	return b;
+}
+
+/*
+==================
+BrushVolume
+
+==================
+*/
+vec_t BrushVolume (bspbrush_t *brush)
+{
+	int			i;
+	winding_t	*w;
+	vec3_t		corner;
+	vec_t		d, area, volume;
+	plane_t		*plane;
+
+	if (!brush)
+		return 0;
+
+	// grab the first valid point as the corner
+
+	w = NULL;
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (w)
+			break;
+	}
+	if (!w)
+		return 0;
+	VectorCopy (w->p[0], corner);
+
+	// make tetrahedrons to all other faces
+
+	volume = 0;
+	for ( ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		plane = &mapplanes[brush->sides[i].planenum];
+		d = -(DotProduct (corner, plane->normal) - plane->dist);
+		area = WindingArea (w);
+		volume += d*area;
+	}
+
+	volume /= 3;
+	return volume;
+}
+
+/*
+================
+CountBrushList
+================
+*/
+int	CountBrushList (bspbrush_t *brushes)
+{
+	int	c;
+
+	c = 0;
+	for ( ; brushes ; brushes = brushes->next)
+		c++;
+	return c;
+}
+
+/*
+================
+AllocTree
+================
+*/
+tree_t *AllocTree (void)
+{
+	tree_t	*tree;
+
+	tree = malloc(sizeof(*tree));
+	memset (tree, 0, sizeof(*tree));
+	ClearBounds (tree->mins, tree->maxs);
+
+	return tree;
+}
+
+/*
+================
+AllocNode
+================
+*/
+node_t *AllocNode (void)
+{
+	node_t	*node;
+
+	node = malloc(sizeof(*node));
+	memset (node, 0, sizeof(*node));
+
+	return node;
+}
+
+
+/*
+================
+AllocBrush
+================
+*/
+bspbrush_t *AllocBrush (int numsides)
+{
+	bspbrush_t	*bb;
+	int			c;
+
+	c = (int)&(((bspbrush_t *)0)->sides[numsides]);
+	bb = malloc(c);
+	memset (bb, 0, c);
+	if (numthreads == 1)
+		c_active_brushes++;
+	return bb;
+}
+
+/*
+================
+FreeBrush
+================
+*/
+void FreeBrush (bspbrush_t *brushes)
+{
+	int			i;
+
+	for (i=0 ; i<brushes->numsides ; i++)
+		if (brushes->sides[i].winding)
+			FreeWinding(brushes->sides[i].winding);
+	free (brushes);
+	if (numthreads == 1)
+		c_active_brushes--;
+}
+
+
+/*
+================
+FreeBrushList
+================
+*/
+void FreeBrushList (bspbrush_t *brushes)
+{
+	bspbrush_t	*next;
+
+	for ( ; brushes ; brushes = next)
+	{
+		next = brushes->next;
+
+		FreeBrush (brushes);
+	}		
+}
+
+/*
+==================
+CopyBrush
+
+Duplicates the brush, the sides, and the windings
+==================
+*/
+bspbrush_t *CopyBrush (bspbrush_t *brush)
+{
+	bspbrush_t *newbrush;
+	int			size;
+	int			i;
+	
+	size = (int)&(((bspbrush_t *)0)->sides[brush->numsides]);
+
+	newbrush = AllocBrush (brush->numsides);
+	memcpy (newbrush, brush, size);
+
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		if (brush->sides[i].winding)
+			newbrush->sides[i].winding = CopyWinding (brush->sides[i].winding);
+	}
+
+	return newbrush;
+}
+
+
+/*
+==================
+PointInLeaf
+
+==================
+*/
+node_t	*PointInLeaf (node_t *node, vec3_t point)
+{
+	vec_t		d;
+	plane_t		*plane;
+
+	while (node->planenum != PLANENUM_LEAF)
+	{
+		plane = &mapplanes[node->planenum];
+		d = DotProduct (point, plane->normal) - plane->dist;
+		if (d > 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+
+	return node;
+}
+
+//========================================================
+
+/*
+==============
+BoxOnPlaneSide
+
+Returns PSIDE_FRONT, PSIDE_BACK, or PSIDE_BOTH
+==============
+*/
+int BoxOnPlaneSide (vec3_t mins, vec3_t maxs, plane_t *plane)
+{
+	int		side;
+	int		i;
+	vec3_t	corners[2];
+	vec_t	dist1, dist2;
+
+	// axial planes are easy
+	if (plane->type < 3)
+	{
+		side = 0;
+		if (maxs[plane->type] > plane->dist+PLANESIDE_EPSILON)
+			side |= PSIDE_FRONT;
+		if (mins[plane->type] < plane->dist-PLANESIDE_EPSILON)
+			side |= PSIDE_BACK;
+		return side;
+	}
+
+	// create the proper leading and trailing verts for the box
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (plane->normal[i] < 0)
+		{
+			corners[0][i] = mins[i];
+			corners[1][i] = maxs[i];
+		}
+		else
+		{
+			corners[1][i] = mins[i];
+			corners[0][i] = maxs[i];
+		}
+	}
+
+	dist1 = DotProduct (plane->normal, corners[0]) - plane->dist;
+	dist2 = DotProduct (plane->normal, corners[1]) - plane->dist;
+	side = 0;
+	if (dist1 >= PLANESIDE_EPSILON)
+		side = PSIDE_FRONT;
+	if (dist2 < PLANESIDE_EPSILON)
+		side |= PSIDE_BACK;
+
+	return side;
+}
+
+/*
+============
+QuickTestBrushToPlanenum
+
+============
+*/
+int	QuickTestBrushToPlanenum (bspbrush_t *brush, int planenum, int *numsplits)
+{
+	int			i, num;
+	plane_t		*plane;
+	int			s;
+
+	*numsplits = 0;
+
+	// if the brush actually uses the planenum,
+	// we can tell the side for sure
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		num = brush->sides[i].planenum;
+		if (num >= 0x10000)
+			Error ("bad planenum");
+		if (num == planenum)
+			return PSIDE_BACK|PSIDE_FACING;
+		if (num == (planenum ^ 1) )
+			return PSIDE_FRONT|PSIDE_FACING;
+	}
+
+	// box on plane side
+	plane = &mapplanes[planenum];
+	s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
+
+	// if both sides, count the visible faces split
+	if (s == PSIDE_BOTH)
+	{
+		*numsplits += 3;
+	}
+
+	return s;
+}
+
+/*
+============
+TestBrushToPlanenum
+
+============
+*/
+int	TestBrushToPlanenum (bspbrush_t *brush, int planenum,
+						 int *numsplits, qboolean *hintsplit, int *epsilonbrush)
+{
+	int			i, j, num;
+	plane_t		*plane;
+	int			s;
+	winding_t	*w;
+	vec_t		d, d_front, d_back;
+	int			front, back;
+
+	*numsplits = 0;
+	*hintsplit = false;
+
+	// if the brush actually uses the planenum,
+	// we can tell the side for sure
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		num = brush->sides[i].planenum;
+		if (num >= 0x10000)
+			Error ("bad planenum");
+		if (num == planenum)
+			return PSIDE_BACK|PSIDE_FACING;
+		if (num == (planenum ^ 1) )
+			return PSIDE_FRONT|PSIDE_FACING;
+	}
+
+	// box on plane side
+	plane = &mapplanes[planenum];
+	s = BoxOnPlaneSide (brush->mins, brush->maxs, plane);
+
+	if (s != PSIDE_BOTH)
+		return s;
+
+// if both sides, count the visible faces split
+	d_front = d_back = 0;
+
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		if (brush->sides[i].texinfo == TEXINFO_NODE)
+			continue;		// on node, don't worry about splits
+		if (!brush->sides[i].visible)
+			continue;		// we don't care about non-visible
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		front = back = 0;
+		for (j=0 ; j<w->numpoints; j++)
+		{
+			d = DotProduct (w->p[j], plane->normal) - plane->dist;
+			if (d > d_front)
+				d_front = d;
+			if (d < d_back)
+				d_back = d;
+
+			if (d > 0.1) // PLANESIDE_EPSILON)
+				front = 1;
+			if (d < -0.1) // PLANESIDE_EPSILON)
+				back = 1;
+		}
+		if (front && back)
+		{
+			if ( !(brush->sides[i].surf & SURF_SKIP) )
+			{
+				(*numsplits)++;
+				if (brush->sides[i].surf & SURF_HINT)
+					*hintsplit = true;
+			}
+		}
+	}
+
+	if ( (d_front > 0.0 && d_front < 1.0)
+		|| (d_back < 0.0 && d_back > -1.0) )
+		(*epsilonbrush)++;
+
+#if 0
+	if (*numsplits == 0)
+	{	//	didn't really need to be split
+		if (front)
+			s = PSIDE_FRONT;
+		else if (back)
+			s = PSIDE_BACK;
+		else
+			s = 0;
+	}
+#endif
+
+	return s;
+}
+
+//========================================================
+
+/*
+================
+WindingIsTiny
+
+Returns true if the winding would be crunched out of
+existance by the vertex snapping.
+================
+*/
+#define	EDGE_LENGTH	0.2
+qboolean WindingIsTiny (winding_t *w)
+{
+#if 0
+	if (WindingArea (w) < 1)
+		return true;
+	return false;
+#else
+	int		i, j;
+	vec_t	len;
+	vec3_t	delta;
+	int		edges;
+
+	edges = 0;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		j = i == w->numpoints - 1 ? 0 : i+1;
+		VectorSubtract (w->p[j], w->p[i], delta);
+		len = (float) VectorLength (delta);
+		if (len > EDGE_LENGTH)
+		{
+			if (++edges == 3)
+				return false;
+		}
+	}
+	return true;
+#endif
+}
+
+/*
+================
+WindingIsHuge
+
+Returns true if the winding still has one of the points
+from basewinding for plane
+================
+*/
+qboolean WindingIsHuge (winding_t *w)
+{
+	int		i, j;
+
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+			if (w->p[i][j] < -8000 || w->p[i][j] > 8000)
+				return true;
+	}
+	return false;
+}
+
+//============================================================
+
+/*
+================
+Leafnode
+================
+*/
+void LeafNode (node_t *node, bspbrush_t *brushes)
+{
+	bspbrush_t	*b;
+	int			i;
+
+	node->planenum = PLANENUM_LEAF;
+	node->contents = 0;
+
+	for (b=brushes ; b ; b=b->next)
+	{
+		// if the brush is solid and all of its sides are on nodes,
+		// it eats everything
+		if (b->original->contents & CONTENTS_SOLID)
+		{
+			for (i=0 ; i<b->numsides ; i++)
+				if (b->sides[i].texinfo != TEXINFO_NODE)
+					break;
+			if (i == b->numsides)
+			{
+				node->contents = CONTENTS_SOLID;
+				break;
+			}
+		}
+		node->contents |= b->original->contents;
+	}
+
+	node->brushlist = brushes;
+}
+
+
+//============================================================
+
+void CheckPlaneAgainstParents (int pnum, node_t *node)
+{
+	node_t	*p;
+
+	for (p=node->parent ; p ; p=p->parent)
+	{
+		if (p->planenum == pnum)
+			Error ("Tried parent");
+	}
+}
+
+qboolean CheckPlaneAgainstVolume (int pnum, node_t *node)
+{
+	bspbrush_t	*front, *back;
+	qboolean	good;
+
+	SplitBrush (node->volume, pnum, &front, &back);
+
+	good = (front && back);
+
+	if (front)
+		FreeBrush (front);
+	if (back)
+		FreeBrush (back);
+
+	return good;
+}
+
+/*
+================
+SelectSplitSide
+
+Using a hueristic, choses one of the sides out of the brushlist
+to partition the brushes with.
+Returns NULL if there are no valid planes to split with..
+================
+*/
+side_t *SelectSplitSide (bspbrush_t *brushes, node_t *node)
+{
+	int			value, bestvalue;
+	bspbrush_t	*brush, *test;
+	side_t		*side, *bestside;
+	int			i, j, pass, numpasses;
+	int			pnum;
+	int			s;
+	int			front, back, both, facing, splits;
+	int			bsplits;
+	int			bestsplits;
+	int			epsilonbrush;
+	qboolean	hintsplit;
+
+	bestside = NULL;
+	bestvalue = -99999;
+	bestsplits = 0;
+
+	// the search order goes: visible-structural, visible-detail,
+	// nonvisible-structural, nonvisible-detail.
+	// If any valid plane is available in a pass, no further
+	// passes will be tried.
+	numpasses = 4;
+	for (pass = 0 ; pass < numpasses ; pass++)
+	{
+		for (brush = brushes ; brush ; brush=brush->next)
+		{
+			if ( (pass & 1) && !(brush->original->contents & CONTENTS_DETAIL) )
+				continue;
+			if ( !(pass & 1) && (brush->original->contents & CONTENTS_DETAIL) )
+				continue;
+			for (i=0 ; i<brush->numsides ; i++)
+			{
+				side = brush->sides + i;
+				if (side->bevel)
+					continue;	// never use a bevel as a spliter
+				if (!side->winding)
+					continue;	// nothing visible, so it can't split
+				if (side->texinfo == TEXINFO_NODE)
+					continue;	// allready a node splitter
+				if (side->tested)
+					continue;	// we allready have metrics for this plane
+				if (side->surf & SURF_SKIP)
+					continue;	// skip surfaces are never chosen
+				if ( side->visible ^ (pass<2) )
+					continue;	// only check visible faces on first pass
+
+				pnum = side->planenum;
+				pnum &= ~1;	// allways use positive facing plane
+
+				CheckPlaneAgainstParents (pnum, node);
+
+				if (!CheckPlaneAgainstVolume (pnum, node))
+					continue;	// would produce a tiny volume
+
+				front = 0;
+				back = 0;
+				both = 0;
+				facing = 0;
+				splits = 0;
+				epsilonbrush = 0;
+
+				for (test = brushes ; test ; test=test->next)
+				{
+					s = TestBrushToPlanenum (test, pnum, &bsplits, &hintsplit, &epsilonbrush);
+
+					splits += bsplits;
+					if (bsplits && (s&PSIDE_FACING) )
+						Error ("PSIDE_FACING with splits");
+
+					test->testside = s;
+					// if the brush shares this face, don't bother
+					// testing that facenum as a splitter again
+					if (s & PSIDE_FACING)
+					{
+						facing++;
+						for (j=0 ; j<test->numsides ; j++)
+						{
+							if ( (test->sides[j].planenum&~1) == pnum)
+								test->sides[j].tested = true;
+						}
+					}
+					if (s & PSIDE_FRONT)
+						front++;
+					if (s & PSIDE_BACK)
+						back++;
+					if (s == PSIDE_BOTH)
+						both++;
+				}
+
+				// give a value estimate for using this plane
+
+				value =  5*facing - 5*splits - abs(front-back);
+//					value =  -5*splits;
+//					value =  5*facing - 5*splits;
+				if (mapplanes[pnum].type < 3)
+					value+=5;		// axial is better
+				value -= epsilonbrush*1000;	// avoid!
+
+				// never split a hint side except with another hint
+				if (hintsplit && !(side->surf & SURF_HINT) )
+					value = -9999999;
+
+				// save off the side test so we don't need
+				// to recalculate it when we actually seperate
+				// the brushes
+				if (value > bestvalue)
+				{
+					bestvalue = value;
+					bestside = side;
+					bestsplits = splits;
+					for (test = brushes ; test ; test=test->next)
+						test->side = test->testside;
+				}
+			}
+		}
+
+		// if we found a good plane, don't bother trying any
+		// other passes
+		if (bestside)
+		{
+			if (pass > 1)
+			{
+				if (numthreads == 1)
+					c_nonvis++;
+			}
+			if (pass > 0)
+				node->detail_seperator = true;	// not needed for vis
+			break;
+		}
+	}
+
+	//
+	// clear all the tested flags we set
+	//
+	for (brush = brushes ; brush ; brush=brush->next)
+	{
+		for (i=0 ; i<brush->numsides ; i++)
+			brush->sides[i].tested = false;
+	}
+
+	return bestside;
+}
+
+
+/*
+==================
+BrushMostlyOnSide
+
+==================
+*/
+int BrushMostlyOnSide (bspbrush_t *brush, plane_t *plane)
+{
+	int			i, j;
+	winding_t	*w;
+	vec_t		d, max;
+	int			side;
+
+	max = 0;
+	side = PSIDE_FRONT;
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			d = DotProduct (w->p[j], plane->normal) - plane->dist;
+			if (d > max)
+			{
+				max = d;
+				side = PSIDE_FRONT;
+			}
+			if (-d > max)
+			{
+				max = -d;
+				side = PSIDE_BACK;
+			}
+		}
+	}
+	return side;
+}
+
+/*
+================
+SplitBrush
+
+Generates two new brushes, leaving the original
+unchanged
+================
+*/
+void SplitBrush (bspbrush_t *brush, int planenum,
+	bspbrush_t **front, bspbrush_t **back)
+{
+	bspbrush_t	*b[2];
+	int			i, j;
+	winding_t	*w, *cw[2], *midwinding;
+	plane_t		*plane, *plane2;
+	side_t		*s, *cs;
+	float		d, d_front, d_back;
+
+	*front = *back = NULL;
+	plane = &mapplanes[planenum];
+
+	// check all points
+	d_front = d_back = 0;
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			d = DotProduct (w->p[j], plane->normal) - plane->dist;
+			if (d > 0 && d > d_front)
+				d_front = d;
+			if (d < 0 && d < d_back)
+				d_back = d;
+		}
+	}
+	if (d_front < 0.1) // PLANESIDE_EPSILON)
+	{	// only on back
+		*back = CopyBrush (brush);
+		return;
+	}
+	if (d_back > -0.1) // PLANESIDE_EPSILON)
+	{	// only on front
+		*front = CopyBrush (brush);
+		return;
+	}
+
+	// create a new winding from the split plane
+
+	w = BaseWindingForPlane (plane->normal, plane->dist);
+	for (i=0 ; i<brush->numsides && w ; i++)
+	{
+		plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
+		ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
+	}
+
+	if (!w || WindingIsTiny (w) )
+	{	// the brush isn't really split
+		int		side;
+
+		side = BrushMostlyOnSide (brush, plane);
+		if (side == PSIDE_FRONT)
+			*front = CopyBrush (brush);
+		if (side == PSIDE_BACK)
+			*back = CopyBrush (brush);
+		return;
+	}
+
+	if (WindingIsHuge (w))
+	{
+		Sys_FPrintf( SYS_VRB, "WARNING: huge winding\n");
+	}
+
+	midwinding = w;
+
+	// split it for real
+
+	for (i=0 ; i<2 ; i++)
+	{
+		b[i] = AllocBrush (brush->numsides+1);
+		b[i]->original = brush->original;
+	}
+
+	// split all the current windings
+
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		s = &brush->sides[i];
+		w = s->winding;
+		if (!w)
+			continue;
+		ClipWindingEpsilon (w, plane->normal, plane->dist,
+			0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
+		for (j=0 ; j<2 ; j++)
+		{
+			if (!cw[j])
+				continue;
+#if 0
+			if (WindingIsTiny (cw[j]))
+			{
+				FreeWinding (cw[j]);
+				continue;
+			}
+#endif
+			cs = &b[j]->sides[b[j]->numsides];
+			b[j]->numsides++;
+			*cs = *s;
+//			cs->planenum = s->planenum;
+//			cs->texinfo = s->texinfo;
+//			cs->visible = s->visible;
+//			cs->original = s->original;
+			cs->winding = cw[j];
+			cs->tested = false;
+		}
+	}
+
+
+	// see if we have valid polygons on both sides
+
+	for (i=0 ; i<2 ; i++)
+	{
+		BoundBrush (b[i]);
+		for (j=0 ; j<3 ; j++)
+		{
+			if (b[i]->mins[j] < -4096 || b[i]->maxs[j] > 4096)
+			{
+				Sys_FPrintf( SYS_VRB, "bogus brush after clip\n");
+				break;
+			}
+		}
+
+		if (b[i]->numsides < 3 || j < 3)
+		{
+			FreeBrush (b[i]);
+			b[i] = NULL;
+		}
+	}
+
+	if ( !(b[0] && b[1]) )
+	{
+		if (!b[0] && !b[1])
+			Sys_FPrintf( SYS_VRB, "split removed brush\n");
+		else
+			Sys_FPrintf( SYS_VRB, "split not on both sides\n");
+		if (b[0])
+		{
+			FreeBrush (b[0]);
+			*front = CopyBrush (brush);
+		}
+		if (b[1])
+		{
+			FreeBrush (b[1]);
+			*back = CopyBrush (brush);
+		}
+		return;
+	}
+
+	// add the midwinding to both sides
+	for (i=0 ; i<2 ; i++)
+	{
+		cs = &b[i]->sides[b[i]->numsides];
+		b[i]->numsides++;
+
+		cs->planenum = planenum^i^1;
+		cs->texinfo = TEXINFO_NODE;
+		cs->visible = false;
+		cs->tested = false;
+		if (i==0)
+			cs->winding = CopyWinding (midwinding);
+		else
+			cs->winding = midwinding;
+	}
+
+{
+	vec_t	v1;
+	int		i;
+
+	for (i=0 ; i<2 ; i++)
+	{
+		v1 = BrushVolume (b[i]);
+		if (v1 < 1.0)
+		{
+			FreeBrush (b[i]);
+			b[i] = NULL;
+			Sys_FPrintf( SYS_VRB, "tiny volume after clip\n");
+		}
+	}
+}
+
+	*front = b[0];
+	*back = b[1];
+}
+
+/*
+================
+SplitBrushList
+================
+*/
+void SplitBrushList (bspbrush_t *brushes, 
+	node_t *node, bspbrush_t **front, bspbrush_t **back)
+{
+	bspbrush_t	*brush, *newbrush, *newbrush2;
+	side_t		*side;
+	int			sides;
+	int			i;
+
+	*front = *back = NULL;
+
+	for (brush = brushes ; brush ; brush=brush->next)
+	{
+		sides = brush->side;
+
+		if (sides == PSIDE_BOTH)
+		{	// split into two brushes
+			SplitBrush (brush, node->planenum, &newbrush, &newbrush2);
+			if (newbrush)
+			{
+				newbrush->next = *front;
+				*front = newbrush;
+			}
+			if (newbrush2)
+			{
+				newbrush2->next = *back;
+				*back = newbrush2;
+			}
+			continue;
+		}
+
+		newbrush = CopyBrush (brush);
+
+		// if the planenum is actualy a part of the brush
+		// find the plane and flag it as used so it won't be tried
+		// as a splitter again
+		if (sides & PSIDE_FACING)
+		{
+			for (i=0 ; i<newbrush->numsides ; i++)
+			{
+				side = newbrush->sides + i;
+				if ( (side->planenum& ~1) == node->planenum)
+					side->texinfo = TEXINFO_NODE;
+			}
+		}
+
+
+		if (sides & PSIDE_FRONT)
+		{
+			newbrush->next = *front;
+			*front = newbrush;
+			continue;
+		}
+		if (sides & PSIDE_BACK)
+		{
+			newbrush->next = *back;
+			*back = newbrush;
+			continue;
+		}
+	}
+}
+
+
+/*
+================
+BuildTree_r
+================
+*/
+node_t *BuildTree_r (node_t *node, bspbrush_t *brushes)
+{
+	node_t		*newnode;
+	side_t		*bestside;
+	int			i;
+	bspbrush_t	*children[2];
+
+	if (numthreads == 1)
+		c_nodes++;
+
+	if (drawflag)
+		DrawBrushList (brushes, node);
+
+	// find the best plane to use as a splitter
+	bestside = SelectSplitSide (brushes, node);
+	if (!bestside)
+	{
+		// leaf node
+		node->side = NULL;
+		node->planenum = -1;
+		LeafNode (node, brushes);
+		return node;
+	}
+
+	// this is a splitplane node
+	node->side = bestside;
+	node->planenum = bestside->planenum & ~1;	// always use front facing
+
+	SplitBrushList (brushes, node, &children[0], &children[1]);
+	FreeBrushList (brushes);
+
+	// allocate children before recursing
+	for (i=0 ; i<2 ; i++)
+	{
+		newnode = AllocNode ();
+		newnode->parent = node;
+		node->children[i] = newnode;
+	}
+
+	SplitBrush (node->volume, node->planenum, &node->children[0]->volume,
+		&node->children[1]->volume);
+
+	// recursively process children
+	for (i=0 ; i<2 ; i++)
+	{
+		node->children[i] = BuildTree_r (node->children[i], children[i]);
+	}
+
+	return node;
+}
+
+//===========================================================
+
+/*
+=================
+BrushBSP
+
+The incoming list will be freed before exiting
+=================
+*/
+tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs)
+{
+	node_t		*node;
+	bspbrush_t	*b;
+	int			c_faces, c_nonvisfaces;
+	int			c_brushes;
+	tree_t		*tree;
+	int			i;
+	vec_t		volume;
+
+	Sys_FPrintf( SYS_VRB, "--- BrushBSP ---\n");
+
+	tree = AllocTree ();
+
+	c_faces = 0;
+	c_nonvisfaces = 0;
+	c_brushes = 0;
+	for (b=brushlist ; b ; b=b->next)
+	{
+		c_brushes++;
+
+		volume = BrushVolume (b);
+		if (volume < microvolume)
+		{
+			Sys_Printf ("WARNING: entity %i, brush %i: microbrush\n",
+				b->original->entitynum, b->original->brushnum);
+		}
+
+		for (i=0 ; i<b->numsides ; i++)
+		{
+			if (b->sides[i].bevel)
+				continue;
+			if (!b->sides[i].winding)
+				continue;
+			if (b->sides[i].texinfo == TEXINFO_NODE)
+				continue;
+			if (b->sides[i].visible)
+				c_faces++;
+			else
+				c_nonvisfaces++;
+		}
+
+		AddPointToBounds (b->mins, tree->mins, tree->maxs);
+		AddPointToBounds (b->maxs, tree->mins, tree->maxs);
+	}
+
+	Sys_FPrintf( SYS_VRB, "%5i brushes\n", c_brushes);
+	Sys_FPrintf( SYS_VRB, "%5i visible faces\n", c_faces);
+	Sys_FPrintf( SYS_VRB, "%5i nonvisible faces\n", c_nonvisfaces);
+
+	c_nodes = 0;
+	c_nonvis = 0;
+	node = AllocNode ();
+
+	node->volume = BrushFromBounds (mins, maxs);
+
+	tree->headnode = node;
+
+	node = BuildTree_r (node, brushlist);
+	Sys_FPrintf( SYS_VRB, "%5i visible nodes\n", c_nodes/2 - c_nonvis);
+	Sys_FPrintf( SYS_VRB, "%5i nonvis nodes\n", c_nonvis);
+	Sys_FPrintf( SYS_VRB, "%5i leafs\n", (c_nodes+1)/2);
+#if 0
+{	// debug code
+static node_t	*tnode;
+vec3_t	p;
+
+p[0] = -1469;
+p[1] = -118;
+p[2] = 119;
+tnode = PointInLeaf (tree->headnode, p);
+Sys_Printf ("contents: %i\n", tnode->contents);
+p[0] = 0;
+}
+#endif
+	return tree;
+}
+
diff --git a/tools/quake2/q2map/csg.c b/tools/quake2/q2map/csg.c
index 6e750be7..dc2bdab4 100644
--- a/tools/quake2/q2map/csg.c
+++ b/tools/quake2/q2map/csg.c
@@ -1,634 +1,634 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-/*
-
-tag all brushes with original contents
-brushes may contain multiple contents
-there will be no brush overlap after csg phase
-
-
-
-
-each side has a count of the other sides it splits
-
-the best split will be the one that minimizes the total split counts
-of all remaining sides
-
-precalc side on plane table
-
-evaluate split side
-{
-cost = 0
-for all sides
-	for all sides
-		get 
-		if side splits side and splitside is on same child
-			cost++;
-}
-
-
-  */
-
-void SplitBrush2 (bspbrush_t *brush, int planenum,
-	bspbrush_t **front, bspbrush_t **back)
-{
-	SplitBrush (brush, planenum, front, back);
-#if 0
-	if (*front && (*front)->sides[(*front)->numsides-1].texinfo == -1)
-		(*front)->sides[(*front)->numsides-1].texinfo = (*front)->sides[0].texinfo;	// not -1
-	if (*back && (*back)->sides[(*back)->numsides-1].texinfo == -1)
-		(*back)->sides[(*back)->numsides-1].texinfo = (*back)->sides[0].texinfo;	// not -1
-#endif
-}
-
-/*
-===============
-SubtractBrush
-
-Returns a list of brushes that remain after B is subtracted from A.
-May by empty if A is contained inside B.
-
-The originals are undisturbed.
-===============
-*/
-bspbrush_t *SubtractBrush (bspbrush_t *a, bspbrush_t *b)
-{	// a - b = out (list)
-	int		i;
-	bspbrush_t	*front, *back;
-	bspbrush_t	*out, *in;
-
-	in = a;
-	out = NULL;
-	for (i=0 ; i<b->numsides && in ; i++)
-	{
-		SplitBrush2 (in, b->sides[i].planenum, &front, &back);
-		if (in != a)
-			FreeBrush (in);
-		if (front)
-		{	// add to list
-			front->next = out;
-			out = front;
-		}
-		in = back;
-	}
-	if (in)
-		FreeBrush (in);
-	else
-	{	// didn't really intersect
-		FreeBrushList (out);
-		return a;
-	}
-	return out;
-}
-
-/*
-===============
-IntersectBrush
-
-Returns a single brush made up by the intersection of the
-two provided brushes, or NULL if they are disjoint.
-
-The originals are undisturbed.
-===============
-*/
-bspbrush_t *IntersectBrush (bspbrush_t *a, bspbrush_t *b)
-{
-	int		i;
-	bspbrush_t	*front, *back;
-	bspbrush_t	*in;
-
-	in = a;
-	for (i=0 ; i<b->numsides && in ; i++)
-	{
-		SplitBrush2 (in, b->sides[i].planenum, &front, &back);
-		if (in != a)
-			FreeBrush (in);
-		if (front)
-			FreeBrush (front);
-		in = back;
-	}
-
-	if (in == a)
-		return NULL;
-
-	in->next = NULL;
-	return in;
-}
-
-
-/*
-===============
-BrushesDisjoint
-
-Returns true if the two brushes definately do not intersect.
-There will be false negatives for some non-axial combinations.
-===============
-*/
-qboolean BrushesDisjoint (bspbrush_t *a, bspbrush_t *b)
-{
-	int		i, j;
-
-	// check bounding boxes
-	for (i=0 ; i<3 ; i++)
-		if (a->mins[i] >= b->maxs[i]
-		|| a->maxs[i] <= b->mins[i])
-			return true;	// bounding boxes don't overlap
-
-	// check for opposing planes
-	for (i=0 ; i<a->numsides ; i++)
-	{
-		for (j=0 ; j<b->numsides ; j++)
-		{
-			if (a->sides[i].planenum ==
-			(b->sides[j].planenum^1) )
-				return true;	// opposite planes, so not touching
-		}
-	}
-
-	return false;	// might intersect
-}
-
-/*
-===============
-IntersectionContents
-
-Returns a content word for the intersection of two brushes.
-Some combinations will generate a combination (water + clip),
-but most will be the stronger of the two contents.
-===============
-*/
-int	IntersectionContents (int c1, int c2)
-{
-	int		out;
-
-	out = c1 | c2;
-
-	if (out & CONTENTS_SOLID)
-		out = CONTENTS_SOLID;
-
-	return out;
-}
-
-
-int		minplanenums[3];
-int		maxplanenums[3];
-
-/*
-===============
-ClipBrushToBox
-
-Any planes shared with the box edge will be set to no texinfo
-===============
-*/
-bspbrush_t	*ClipBrushToBox (bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs)
-{
-	int		i, j;
-	bspbrush_t	*front,	*back;
-	int		p;
-
-	for (j=0 ; j<2 ; j++)
-	{
-		if (brush->maxs[j] > clipmaxs[j])
-		{
-			SplitBrush (brush, maxplanenums[j], &front, &back);
-			if (front)
-				FreeBrush (front);
-			brush = back;
-			if (!brush)
-				return NULL;
-		}
-		if (brush->mins[j] < clipmins[j])
-		{
-			SplitBrush (brush, minplanenums[j], &front, &back);
-			if (back)
-				FreeBrush (back);
-			brush = front;
-			if (!brush)
-				return NULL;
-		}
-	}
-
-	// remove any colinear faces
-
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		p = brush->sides[i].planenum & ~1;
-		if (p == maxplanenums[0] || p == maxplanenums[1] 
-			|| p == minplanenums[0] || p == minplanenums[1])
-		{
-			brush->sides[i].texinfo = TEXINFO_NODE;
-			brush->sides[i].visible = false;
-		}
-	}
-	return brush;
-}
-
-/*
-===============
-MakeBspBrushList 
-===============
-*/
-bspbrush_t *MakeBspBrushList (int startbrush, int endbrush,
-		vec3_t clipmins, vec3_t clipmaxs)
-{
-	mapbrush_t	*mb;
-	bspbrush_t	*brushlist, *newbrush;
-	int			i, j;
-	int			c_faces;
-	int			c_brushes;
-	int			numsides;
-	int			vis;
-	vec3_t		normal;
-	float		dist;
-
-	for (i=0 ; i<2 ; i++)
-	{
-		VectorClear (normal);
-		normal[i] = 1;
-		dist = clipmaxs[i];
-		maxplanenums[i] = FindFloatPlane (normal, dist);
-		dist = clipmins[i];
-		minplanenums[i] = FindFloatPlane (normal, dist);
-	}
-
-	brushlist = NULL;
-	c_faces = 0;
-	c_brushes = 0;
-
-	for (i=startbrush ; i<endbrush ; i++)
-	{
-		mb = &mapbrushes[i];
-
-		numsides = mb->numsides;
-		if (!numsides)
-			continue;
-		// make sure the brush has at least one face showing
-		vis = 0;
-		for (j=0 ; j<numsides ; j++)
-			if (mb->original_sides[j].visible && mb->original_sides[j].winding)
-				vis++;
-#if 0
-		if (!vis)
-			continue;	// no faces at all
-#endif
-		// if the brush is outside the clip area, skip it
-		for (j=0 ; j<3 ; j++)
-			if (mb->mins[j] >= clipmaxs[j]
-			|| mb->maxs[j] <= clipmins[j])
-			break;
-		if (j != 3)
-			continue;
-
-		//
-		// make a copy of the brush
-		//
-		newbrush = AllocBrush (mb->numsides);
-		newbrush->original = mb;
-		newbrush->numsides = mb->numsides;
-		memcpy (newbrush->sides, mb->original_sides, numsides*sizeof(side_t));
-		for (j=0 ; j<numsides ; j++)
-		{
-			if (newbrush->sides[j].winding)
-				newbrush->sides[j].winding = CopyWinding (newbrush->sides[j].winding);
-			if (newbrush->sides[j].surf & SURF_HINT)
-				newbrush->sides[j].visible = true;	// hints are always visible
-		}
-		VectorCopy (mb->mins, newbrush->mins);
-		VectorCopy (mb->maxs, newbrush->maxs);
-
-		//
-		// carve off anything outside the clip box
-		//
-		newbrush = ClipBrushToBox (newbrush, clipmins, clipmaxs);
-		if (!newbrush)
-			continue;
-
-		c_faces += vis;
-		c_brushes++;
-
-		newbrush->next = brushlist;
-		brushlist = newbrush;
-	}
-
-	return brushlist;
-}
-
-/*
-===============
-AddBspBrushListToTail
-===============
-*/
-bspbrush_t *AddBrushListToTail (bspbrush_t *list, bspbrush_t *tail)
-{
-	bspbrush_t	*walk, *next;
-
-	for (walk=list ; walk ; walk=next)
-	{	// add to end of list
-		next = walk->next;
-		walk->next = NULL;
-		tail->next = walk;
-		tail = walk;
-	}
-
-	return tail;
-}
-
-/*
-===========
-CullList
-
-Builds a new list that doesn't hold the given brush
-===========
-*/
-bspbrush_t *CullList (bspbrush_t *list, bspbrush_t *skip1)
-{
-	bspbrush_t	*newlist;
-	bspbrush_t	*next;
-
-	newlist = NULL;
-
-	for ( ; list ; list = next)
-	{
-		next = list->next;
-		if (list == skip1)
-		{
-			FreeBrush (list);
-			continue;
-		}
-		list->next = newlist;
-		newlist = list;
-	}
-	return newlist;
-}
-
-
-/*
-==================
-WriteBrushMap
-==================
-*/
-void WriteBrushMap (char *name, bspbrush_t *list)
-{
-	FILE	*f;
-	side_t	*s;
-	int		i;
-	winding_t	*w;
-
-	Sys_Printf ("writing %s\n", name);
-	f = fopen (name, "wb");
-	if (!f)
-		Error ("Can't write %s\b", name);
-
-	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
-
-	for ( ; list ; list=list->next )
-	{
-		fprintf (f, "{\n");
-		for (i=0,s=list->sides ; i<list->numsides ; i++,s++)
-		{
-			w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist);
-
-			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
-			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
-			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
-
-			fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
-			FreeWinding (w);
-		}
-		fprintf (f, "}\n");
-	}
-	fprintf (f, "}\n");
-
-	fclose (f);
-
-}
-
-/*
-==================
-BrushGE
-
-Returns true if b1 is allowed to bite b2
-==================
-*/
-qboolean BrushGE (bspbrush_t *b1, bspbrush_t *b2)
-{
-	// detail brushes never bite structural brushes
-	if ( (b1->original->contents & CONTENTS_DETAIL) 
-		&& !(b2->original->contents & CONTENTS_DETAIL) )
-		return false;
-	if (b1->original->contents & CONTENTS_SOLID)
-		return true;
-	return false;
-}
-
-/*
-=================
-ChopBrushes
-
-Carves any intersecting solid brushes into the minimum number
-of non-intersecting brushes. 
-=================
-*/
-bspbrush_t *ChopBrushes (bspbrush_t *head)
-{
-	bspbrush_t	*b1, *b2, *next;
-	bspbrush_t	*tail;
-	bspbrush_t	*keep;
-	bspbrush_t	*sub, *sub2;
-	int			c1, c2;
-
-	Sys_FPrintf( SYS_VRB, "---- ChopBrushes ----\n");
-	Sys_FPrintf( SYS_VRB, "original brushes: %i\n", CountBrushList (head));
-
-#if 0
-	if (startbrush == 0)
-		WriteBrushList ("before.gl", head, false);
-#endif
-	keep = NULL;
-
-newlist:
-	// find tail
-	if (!head)
-		return NULL;
-	for (tail=head ; tail->next ; tail=tail->next)
-	;
-
-	for (b1=head ; b1 ; b1=next)
-	{
-		next = b1->next;
-		for (b2=b1->next ; b2 ; b2 = b2->next)
-		{
-			if (BrushesDisjoint (b1, b2))
-				continue;
-
-			sub = NULL;
-			sub2 = NULL;
-			c1 = 999999;
-			c2 = 999999;
-
-			if ( BrushGE (b2, b1) )
-			{
-				sub = SubtractBrush (b1, b2);
-				if (sub == b1)
-					continue;		// didn't really intersect
-				if (!sub)
-				{	// b1 is swallowed by b2
-					head = CullList (b1, b1);
-					goto newlist;
-				}
-				c1 = CountBrushList (sub);
-			}
-
-			if ( BrushGE (b1, b2) )
-			{
-				sub2 = SubtractBrush (b2, b1);
-				if (sub2 == b2)
-					continue;		// didn't really intersect
-				if (!sub2)
-				{	// b2 is swallowed by b1
-					FreeBrushList (sub);
-					head = CullList (b1, b2);
-					goto newlist;
-				}
-				c2 = CountBrushList (sub2);
-			}
-
-			if (!sub && !sub2)
-				continue;		// neither one can bite
-
-			// only accept if it didn't fragment
-			// (commening this out allows full fragmentation)
-			if (c1 > 1 && c2 > 1)
-			{
-				if (sub2)
-					FreeBrushList (sub2);
-				if (sub)
-					FreeBrushList (sub);
-				continue;
-			}
-
-			if (c1 < c2)
-			{
-				if (sub2)
-					FreeBrushList (sub2);
-				tail = AddBrushListToTail (sub, tail);
-				head = CullList (b1, b1);
-				goto newlist;
-			}
-			else
-			{
-				if (sub)
-					FreeBrushList (sub);
-				tail = AddBrushListToTail (sub2, tail);
-				head = CullList (b1, b2);
-				goto newlist;
-			}
-		}
-
-		if (!b2)
-		{	// b1 is no longer intersecting anything, so keep it
-			b1->next = keep;
-			keep = b1;
-		}
-	}
-
-	Sys_FPrintf( SYS_VRB, "output brushes: %i\n", CountBrushList (keep));
-#if 0
-	{
-		WriteBrushList ("after.gl", keep, false);
-		WriteBrushMap ("after.map", keep);
-	}
-#endif
-	return keep;
-}
-
-
-/*
-=================
-InitialBrushList
-=================
-*/
-bspbrush_t *InitialBrushList (bspbrush_t *list)
-{
-	bspbrush_t *b;
-	bspbrush_t	*out, *newb;
-	int			i;
-
-	// only return brushes that have visible faces
-	out = NULL;
-	for (b=list ; b ; b=b->next)
-	{
-#if 0
-		for (i=0 ; i<b->numsides ; i++)
-			if (b->sides[i].visible)
-				break;
-		if (i == b->numsides)
-			continue;
-#endif
-		newb = CopyBrush (b);
-		newb->next = out;
-		out = newb;
-
-		// clear visible, so it must be set by MarkVisibleFaces_r
-		// to be used in the optimized list
-		for (i=0 ; i<b->numsides ; i++)
-		{
-			newb->sides[i].original = &b->sides[i];
-//			newb->sides[i].visible = true;
-			b->sides[i].visible = false;
-		}
-	}
-
-	return out;
-}
-
-/*
-=================
-OptimizedBrushList
-=================
-*/
-bspbrush_t *OptimizedBrushList (bspbrush_t *list)
-{
-	bspbrush_t *b;
-	bspbrush_t	*out, *newb;
-	int			i;
-
-	// only return brushes that have visible faces
-	out = NULL;
-	for (b=list ; b ; b=b->next)
-	{
-		for (i=0 ; i<b->numsides ; i++)
-			if (b->sides[i].visible)
-				break;
-		if (i == b->numsides)
-			continue;
-		newb = CopyBrush (b);
-		newb->next = out;
-		out = newb;
-	}
-
-//	WriteBrushList ("vis.gl", out, true);
-
-	return out;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+/*
+
+tag all brushes with original contents
+brushes may contain multiple contents
+there will be no brush overlap after csg phase
+
+
+
+
+each side has a count of the other sides it splits
+
+the best split will be the one that minimizes the total split counts
+of all remaining sides
+
+precalc side on plane table
+
+evaluate split side
+{
+cost = 0
+for all sides
+	for all sides
+		get 
+		if side splits side and splitside is on same child
+			cost++;
+}
+
+
+  */
+
+void SplitBrush2 (bspbrush_t *brush, int planenum,
+	bspbrush_t **front, bspbrush_t **back)
+{
+	SplitBrush (brush, planenum, front, back);
+#if 0
+	if (*front && (*front)->sides[(*front)->numsides-1].texinfo == -1)
+		(*front)->sides[(*front)->numsides-1].texinfo = (*front)->sides[0].texinfo;	// not -1
+	if (*back && (*back)->sides[(*back)->numsides-1].texinfo == -1)
+		(*back)->sides[(*back)->numsides-1].texinfo = (*back)->sides[0].texinfo;	// not -1
+#endif
+}
+
+/*
+===============
+SubtractBrush
+
+Returns a list of brushes that remain after B is subtracted from A.
+May by empty if A is contained inside B.
+
+The originals are undisturbed.
+===============
+*/
+bspbrush_t *SubtractBrush (bspbrush_t *a, bspbrush_t *b)
+{	// a - b = out (list)
+	int		i;
+	bspbrush_t	*front, *back;
+	bspbrush_t	*out, *in;
+
+	in = a;
+	out = NULL;
+	for (i=0 ; i<b->numsides && in ; i++)
+	{
+		SplitBrush2 (in, b->sides[i].planenum, &front, &back);
+		if (in != a)
+			FreeBrush (in);
+		if (front)
+		{	// add to list
+			front->next = out;
+			out = front;
+		}
+		in = back;
+	}
+	if (in)
+		FreeBrush (in);
+	else
+	{	// didn't really intersect
+		FreeBrushList (out);
+		return a;
+	}
+	return out;
+}
+
+/*
+===============
+IntersectBrush
+
+Returns a single brush made up by the intersection of the
+two provided brushes, or NULL if they are disjoint.
+
+The originals are undisturbed.
+===============
+*/
+bspbrush_t *IntersectBrush (bspbrush_t *a, bspbrush_t *b)
+{
+	int		i;
+	bspbrush_t	*front, *back;
+	bspbrush_t	*in;
+
+	in = a;
+	for (i=0 ; i<b->numsides && in ; i++)
+	{
+		SplitBrush2 (in, b->sides[i].planenum, &front, &back);
+		if (in != a)
+			FreeBrush (in);
+		if (front)
+			FreeBrush (front);
+		in = back;
+	}
+
+	if (in == a)
+		return NULL;
+
+	in->next = NULL;
+	return in;
+}
+
+
+/*
+===============
+BrushesDisjoint
+
+Returns true if the two brushes definately do not intersect.
+There will be false negatives for some non-axial combinations.
+===============
+*/
+qboolean BrushesDisjoint (bspbrush_t *a, bspbrush_t *b)
+{
+	int		i, j;
+
+	// check bounding boxes
+	for (i=0 ; i<3 ; i++)
+		if (a->mins[i] >= b->maxs[i]
+		|| a->maxs[i] <= b->mins[i])
+			return true;	// bounding boxes don't overlap
+
+	// check for opposing planes
+	for (i=0 ; i<a->numsides ; i++)
+	{
+		for (j=0 ; j<b->numsides ; j++)
+		{
+			if (a->sides[i].planenum ==
+			(b->sides[j].planenum^1) )
+				return true;	// opposite planes, so not touching
+		}
+	}
+
+	return false;	// might intersect
+}
+
+/*
+===============
+IntersectionContents
+
+Returns a content word for the intersection of two brushes.
+Some combinations will generate a combination (water + clip),
+but most will be the stronger of the two contents.
+===============
+*/
+int	IntersectionContents (int c1, int c2)
+{
+	int		out;
+
+	out = c1 | c2;
+
+	if (out & CONTENTS_SOLID)
+		out = CONTENTS_SOLID;
+
+	return out;
+}
+
+
+int		minplanenums[3];
+int		maxplanenums[3];
+
+/*
+===============
+ClipBrushToBox
+
+Any planes shared with the box edge will be set to no texinfo
+===============
+*/
+bspbrush_t	*ClipBrushToBox (bspbrush_t *brush, vec3_t clipmins, vec3_t clipmaxs)
+{
+	int		i, j;
+	bspbrush_t	*front,	*back;
+	int		p;
+
+	for (j=0 ; j<2 ; j++)
+	{
+		if (brush->maxs[j] > clipmaxs[j])
+		{
+			SplitBrush (brush, maxplanenums[j], &front, &back);
+			if (front)
+				FreeBrush (front);
+			brush = back;
+			if (!brush)
+				return NULL;
+		}
+		if (brush->mins[j] < clipmins[j])
+		{
+			SplitBrush (brush, minplanenums[j], &front, &back);
+			if (back)
+				FreeBrush (back);
+			brush = front;
+			if (!brush)
+				return NULL;
+		}
+	}
+
+	// remove any colinear faces
+
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		p = brush->sides[i].planenum & ~1;
+		if (p == maxplanenums[0] || p == maxplanenums[1] 
+			|| p == minplanenums[0] || p == minplanenums[1])
+		{
+			brush->sides[i].texinfo = TEXINFO_NODE;
+			brush->sides[i].visible = false;
+		}
+	}
+	return brush;
+}
+
+/*
+===============
+MakeBspBrushList 
+===============
+*/
+bspbrush_t *MakeBspBrushList (int startbrush, int endbrush,
+		vec3_t clipmins, vec3_t clipmaxs)
+{
+	mapbrush_t	*mb;
+	bspbrush_t	*brushlist, *newbrush;
+	int			i, j;
+	int			c_faces;
+	int			c_brushes;
+	int			numsides;
+	int			vis;
+	vec3_t		normal;
+	float		dist;
+
+	for (i=0 ; i<2 ; i++)
+	{
+		VectorClear (normal);
+		normal[i] = 1;
+		dist = clipmaxs[i];
+		maxplanenums[i] = FindFloatPlane (normal, dist);
+		dist = clipmins[i];
+		minplanenums[i] = FindFloatPlane (normal, dist);
+	}
+
+	brushlist = NULL;
+	c_faces = 0;
+	c_brushes = 0;
+
+	for (i=startbrush ; i<endbrush ; i++)
+	{
+		mb = &mapbrushes[i];
+
+		numsides = mb->numsides;
+		if (!numsides)
+			continue;
+		// make sure the brush has at least one face showing
+		vis = 0;
+		for (j=0 ; j<numsides ; j++)
+			if (mb->original_sides[j].visible && mb->original_sides[j].winding)
+				vis++;
+#if 0
+		if (!vis)
+			continue;	// no faces at all
+#endif
+		// if the brush is outside the clip area, skip it
+		for (j=0 ; j<3 ; j++)
+			if (mb->mins[j] >= clipmaxs[j]
+			|| mb->maxs[j] <= clipmins[j])
+			break;
+		if (j != 3)
+			continue;
+
+		//
+		// make a copy of the brush
+		//
+		newbrush = AllocBrush (mb->numsides);
+		newbrush->original = mb;
+		newbrush->numsides = mb->numsides;
+		memcpy (newbrush->sides, mb->original_sides, numsides*sizeof(side_t));
+		for (j=0 ; j<numsides ; j++)
+		{
+			if (newbrush->sides[j].winding)
+				newbrush->sides[j].winding = CopyWinding (newbrush->sides[j].winding);
+			if (newbrush->sides[j].surf & SURF_HINT)
+				newbrush->sides[j].visible = true;	// hints are always visible
+		}
+		VectorCopy (mb->mins, newbrush->mins);
+		VectorCopy (mb->maxs, newbrush->maxs);
+
+		//
+		// carve off anything outside the clip box
+		//
+		newbrush = ClipBrushToBox (newbrush, clipmins, clipmaxs);
+		if (!newbrush)
+			continue;
+
+		c_faces += vis;
+		c_brushes++;
+
+		newbrush->next = brushlist;
+		brushlist = newbrush;
+	}
+
+	return brushlist;
+}
+
+/*
+===============
+AddBspBrushListToTail
+===============
+*/
+bspbrush_t *AddBrushListToTail (bspbrush_t *list, bspbrush_t *tail)
+{
+	bspbrush_t	*walk, *next;
+
+	for (walk=list ; walk ; walk=next)
+	{	// add to end of list
+		next = walk->next;
+		walk->next = NULL;
+		tail->next = walk;
+		tail = walk;
+	}
+
+	return tail;
+}
+
+/*
+===========
+CullList
+
+Builds a new list that doesn't hold the given brush
+===========
+*/
+bspbrush_t *CullList (bspbrush_t *list, bspbrush_t *skip1)
+{
+	bspbrush_t	*newlist;
+	bspbrush_t	*next;
+
+	newlist = NULL;
+
+	for ( ; list ; list = next)
+	{
+		next = list->next;
+		if (list == skip1)
+		{
+			FreeBrush (list);
+			continue;
+		}
+		list->next = newlist;
+		newlist = list;
+	}
+	return newlist;
+}
+
+
+/*
+==================
+WriteBrushMap
+==================
+*/
+void WriteBrushMap (char *name, bspbrush_t *list)
+{
+	FILE	*f;
+	side_t	*s;
+	int		i;
+	winding_t	*w;
+
+	Sys_Printf ("writing %s\n", name);
+	f = fopen (name, "wb");
+	if (!f)
+		Error ("Can't write %s\b", name);
+
+	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
+
+	for ( ; list ; list=list->next )
+	{
+		fprintf (f, "{\n");
+		for (i=0,s=list->sides ; i<list->numsides ; i++,s++)
+		{
+			w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist);
+
+			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
+			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
+			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
+
+			fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
+			FreeWinding (w);
+		}
+		fprintf (f, "}\n");
+	}
+	fprintf (f, "}\n");
+
+	fclose (f);
+
+}
+
+/*
+==================
+BrushGE
+
+Returns true if b1 is allowed to bite b2
+==================
+*/
+qboolean BrushGE (bspbrush_t *b1, bspbrush_t *b2)
+{
+	// detail brushes never bite structural brushes
+	if ( (b1->original->contents & CONTENTS_DETAIL) 
+		&& !(b2->original->contents & CONTENTS_DETAIL) )
+		return false;
+	if (b1->original->contents & CONTENTS_SOLID)
+		return true;
+	return false;
+}
+
+/*
+=================
+ChopBrushes
+
+Carves any intersecting solid brushes into the minimum number
+of non-intersecting brushes. 
+=================
+*/
+bspbrush_t *ChopBrushes (bspbrush_t *head)
+{
+	bspbrush_t	*b1, *b2, *next;
+	bspbrush_t	*tail;
+	bspbrush_t	*keep;
+	bspbrush_t	*sub, *sub2;
+	int			c1, c2;
+
+	Sys_FPrintf( SYS_VRB, "---- ChopBrushes ----\n");
+	Sys_FPrintf( SYS_VRB, "original brushes: %i\n", CountBrushList (head));
+
+#if 0
+	if (startbrush == 0)
+		WriteBrushList ("before.gl", head, false);
+#endif
+	keep = NULL;
+
+newlist:
+	// find tail
+	if (!head)
+		return NULL;
+	for (tail=head ; tail->next ; tail=tail->next)
+	;
+
+	for (b1=head ; b1 ; b1=next)
+	{
+		next = b1->next;
+		for (b2=b1->next ; b2 ; b2 = b2->next)
+		{
+			if (BrushesDisjoint (b1, b2))
+				continue;
+
+			sub = NULL;
+			sub2 = NULL;
+			c1 = 999999;
+			c2 = 999999;
+
+			if ( BrushGE (b2, b1) )
+			{
+				sub = SubtractBrush (b1, b2);
+				if (sub == b1)
+					continue;		// didn't really intersect
+				if (!sub)
+				{	// b1 is swallowed by b2
+					head = CullList (b1, b1);
+					goto newlist;
+				}
+				c1 = CountBrushList (sub);
+			}
+
+			if ( BrushGE (b1, b2) )
+			{
+				sub2 = SubtractBrush (b2, b1);
+				if (sub2 == b2)
+					continue;		// didn't really intersect
+				if (!sub2)
+				{	// b2 is swallowed by b1
+					FreeBrushList (sub);
+					head = CullList (b1, b2);
+					goto newlist;
+				}
+				c2 = CountBrushList (sub2);
+			}
+
+			if (!sub && !sub2)
+				continue;		// neither one can bite
+
+			// only accept if it didn't fragment
+			// (commening this out allows full fragmentation)
+			if (c1 > 1 && c2 > 1)
+			{
+				if (sub2)
+					FreeBrushList (sub2);
+				if (sub)
+					FreeBrushList (sub);
+				continue;
+			}
+
+			if (c1 < c2)
+			{
+				if (sub2)
+					FreeBrushList (sub2);
+				tail = AddBrushListToTail (sub, tail);
+				head = CullList (b1, b1);
+				goto newlist;
+			}
+			else
+			{
+				if (sub)
+					FreeBrushList (sub);
+				tail = AddBrushListToTail (sub2, tail);
+				head = CullList (b1, b2);
+				goto newlist;
+			}
+		}
+
+		if (!b2)
+		{	// b1 is no longer intersecting anything, so keep it
+			b1->next = keep;
+			keep = b1;
+		}
+	}
+
+	Sys_FPrintf( SYS_VRB, "output brushes: %i\n", CountBrushList (keep));
+#if 0
+	{
+		WriteBrushList ("after.gl", keep, false);
+		WriteBrushMap ("after.map", keep);
+	}
+#endif
+	return keep;
+}
+
+
+/*
+=================
+InitialBrushList
+=================
+*/
+bspbrush_t *InitialBrushList (bspbrush_t *list)
+{
+	bspbrush_t *b;
+	bspbrush_t	*out, *newb;
+	int			i;
+
+	// only return brushes that have visible faces
+	out = NULL;
+	for (b=list ; b ; b=b->next)
+	{
+#if 0
+		for (i=0 ; i<b->numsides ; i++)
+			if (b->sides[i].visible)
+				break;
+		if (i == b->numsides)
+			continue;
+#endif
+		newb = CopyBrush (b);
+		newb->next = out;
+		out = newb;
+
+		// clear visible, so it must be set by MarkVisibleFaces_r
+		// to be used in the optimized list
+		for (i=0 ; i<b->numsides ; i++)
+		{
+			newb->sides[i].original = &b->sides[i];
+//			newb->sides[i].visible = true;
+			b->sides[i].visible = false;
+		}
+	}
+
+	return out;
+}
+
+/*
+=================
+OptimizedBrushList
+=================
+*/
+bspbrush_t *OptimizedBrushList (bspbrush_t *list)
+{
+	bspbrush_t *b;
+	bspbrush_t	*out, *newb;
+	int			i;
+
+	// only return brushes that have visible faces
+	out = NULL;
+	for (b=list ; b ; b=b->next)
+	{
+		for (i=0 ; i<b->numsides ; i++)
+			if (b->sides[i].visible)
+				break;
+		if (i == b->numsides)
+			continue;
+		newb = CopyBrush (b);
+		newb->next = out;
+		out = newb;
+	}
+
+//	WriteBrushList ("vis.gl", out, true);
+
+	return out;
+}
diff --git a/tools/quake2/q2map/faces.c b/tools/quake2/q2map/faces.c
index 0b7ba80f..4839f9c0 100644
--- a/tools/quake2/q2map/faces.c
+++ b/tools/quake2/q2map/faces.c
@@ -1,1076 +1,1076 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// faces.c
-
-#include "qbsp.h"
-
-/*
-
-  some faces will be removed before saving, but still form nodes:
-
-  the insides of sky volumes
-  meeting planes of different water current volumes
-
-*/
-
-// undefine for dumb linear searches
-#define	USE_HASHING
-
-#define	INTEGRAL_EPSILON	0.01
-#define	POINT_EPSILON		0.5
-#define	OFF_EPSILON			0.5
-
-int	c_merge;
-int	c_subdivide;
-
-int	c_totalverts;
-int	c_uniqueverts;
-int	c_degenerate;
-int	c_tjunctions;
-int	c_faceoverflows;
-int	c_facecollapse;
-int	c_badstartverts;
-
-#define	MAX_SUPERVERTS	512
-int	superverts[MAX_SUPERVERTS];
-int	numsuperverts;
-
-face_t		*edgefaces[MAX_MAP_EDGES][2];
-int		firstmodeledge = 1;
-int		firstmodelface;
-
-int	c_tryedges;
-
-vec3_t	edge_dir;
-vec3_t	edge_start;
-vec_t	edge_len;
-
-int		num_edge_verts;
-int		edge_verts[MAX_MAP_VERTS];
-
-
-float	subdivide_size = 240;
-
-
-face_t *NewFaceFromFace (face_t *f);
-
-//===========================================================================
-
-typedef struct hashvert_s
-{
-	struct hashvert_s	*next;
-	int		num;
-} hashvert_t;
-
-
-#define	HASH_SIZE	64
-
-
-int	vertexchain[MAX_MAP_VERTS];		// the next vertex in a hash chain
-int	hashverts[HASH_SIZE*HASH_SIZE];	// a vertex number, or 0 for no verts
-
-face_t		*edgefaces[MAX_MAP_EDGES][2];
-
-//============================================================================
-
-
-unsigned HashVec (vec3_t vec)
-{
-	int			x, y;
-
-	x = (4096 + (int)(vec[0]+0.5)) >> 7;
-	y = (4096 + (int)(vec[1]+0.5)) >> 7;
-
-	if ( x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE )
-		Error ("HashVec: point outside valid range");
-	
-	return y*HASH_SIZE + x;
-}
-
-#ifdef USE_HASHING
-/*
-=============
-GetVertex
-
-Uses hashing
-=============
-*/
-int	GetVertexnum (vec3_t in)
-{
-	int			h;
-	int			i;
-	float		*p;
-	vec3_t		vert;
-	int			vnum;
-
-	c_totalverts++;
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if ( fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
-			vert[i] = Q_rint(in[i]);
-		else
-			vert[i] = in[i];
-	}
-	
-	h = HashVec (vert);
-	
-	for (vnum=hashverts[h] ; vnum ; vnum=vertexchain[vnum])
-	{
-		p = dvertexes[vnum].point;
-		if ( fabs(p[0]-vert[0])<POINT_EPSILON
-		&& fabs(p[1]-vert[1])<POINT_EPSILON
-		&& fabs(p[2]-vert[2])<POINT_EPSILON )
-			return vnum;
-	}
-	
-// emit a vertex
-	if (numvertexes == MAX_MAP_VERTS)
-		Error ("numvertexes == MAX_MAP_VERTS");
-
-	dvertexes[numvertexes].point[0] = vert[0];
-	dvertexes[numvertexes].point[1] = vert[1];
-	dvertexes[numvertexes].point[2] = vert[2];
-
-	vertexchain[numvertexes] = hashverts[h];
-	hashverts[h] = numvertexes;
-
-	c_uniqueverts++;
-
-	numvertexes++;
-		
-	return numvertexes-1;
-}
-#else
-/*
-==================
-GetVertexnum
-
-Dumb linear search
-==================
-*/
-int	GetVertexnum (vec3_t v)
-{
-	int			i, j;
-	dvertex_t	*dv;
-	vec_t		d;
-
-	c_totalverts++;
-
-	// make really close values exactly integral
-	for (i=0 ; i<3 ; i++)
-	{
-		if ( fabs(v[i] - (int)(v[i]+0.5)) < INTEGRAL_EPSILON )
-			v[i] = (int)(v[i]+0.5);
-		if (v[i] < -4096 || v[i] > 4096)
-			Error ("GetVertexnum: outside +/- 4096");
-	}
-
-	// search for an existing vertex match
-	for (i=0, dv=dvertexes ; i<numvertexes ; i++, dv++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			d = v[j] - dv->point[j];
-			if ( d > POINT_EPSILON || d < -POINT_EPSILON)
-				break;
-		}
-		if (j == 3)
-			return i;		// a match
-	}
-
-	// new point
-	if (numvertexes == MAX_MAP_VERTS)
-		Error ("MAX_MAP_VERTS");
-	VectorCopy (v, dv->point);
-	numvertexes++;
-	c_uniqueverts++;
-
-	return numvertexes-1;
-}
-#endif
-
-
-/*
-==================
-FaceFromSuperverts
-
-The faces vertexes have beeb added to the superverts[] array,
-and there may be more there than can be held in a face (MAXEDGES).
-
-If less, the faces vertexnums[] will be filled in, otherwise
-face will reference a tree of split[] faces until all of the
-vertexnums can be added.
-
-superverts[base] will become face->vertexnums[0], and the others
-will be circularly filled in.
-==================
-*/
-void FaceFromSuperverts (node_t *node, face_t *f, int base)
-{
-	face_t	*newf;
-	int		remaining;
-	int		i;
-
-	remaining = numsuperverts;
-	while (remaining > MAXEDGES)
-	{	// must split into two faces, because of vertex overload
-		c_faceoverflows++;
-
-		newf = f->split[0] = NewFaceFromFace (f);
-		newf = f->split[0];
-		newf->next = node->faces;
-		node->faces = newf;
-
-		newf->numpoints = MAXEDGES;
-		for (i=0 ; i<MAXEDGES ; i++)
-			newf->vertexnums[i] = superverts[(i+base)%numsuperverts];
-
-		f->split[1] = NewFaceFromFace (f);
-		f = f->split[1];
-		f->next = node->faces;
-		node->faces = f;
-
-		remaining -= (MAXEDGES-2);
-		base = (base+MAXEDGES-1)%numsuperverts;
-	}
-
-	// copy the vertexes back to the face
-	f->numpoints = remaining;
-	for (i=0 ; i<remaining ; i++)
-		f->vertexnums[i] = superverts[(i+base)%numsuperverts];
-}
-
-
-/*
-==================
-EmitFaceVertexes
-==================
-*/
-void EmitFaceVertexes (node_t *node, face_t *f)
-{
-	winding_t	*w;
-	int			i;
-
-	if (f->merged || f->split[0] || f->split[1])
-		return;
-
-	w = f->w;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		if (noweld)
-		{	// make every point unique
-			if (numvertexes == MAX_MAP_VERTS)
-				Error ("MAX_MAP_VERTS");
-			superverts[i] = numvertexes;
-			VectorCopy (w->p[i], dvertexes[numvertexes].point);
-			numvertexes++;
-			c_uniqueverts++;
-			c_totalverts++;
-		}
-		else
-			superverts[i] = GetVertexnum (w->p[i]);
-	}
-	numsuperverts = w->numpoints;
-
-	// this may fragment the face if > MAXEDGES
-	FaceFromSuperverts (node, f, 0);
-}
-
-/*
-==================
-EmitVertexes_r
-==================
-*/
-void EmitVertexes_r (node_t *node)
-{
-	int		i;
-	face_t	*f;
-
-	if (node->planenum == PLANENUM_LEAF)
-		return;
-
-	for (f=node->faces ; f ; f=f->next)
-	{
-		EmitFaceVertexes (node, f);
-	}
-
-	for (i=0 ; i<2 ; i++)
-		EmitVertexes_r (node->children[i]);
-}
-
-
-#ifdef USE_HASHING
-/*
-==========
-FindEdgeVerts
-
-Uses the hash tables to cut down to a small number
-==========
-*/
-void FindEdgeVerts (vec3_t v1, vec3_t v2)
-{
-	int		x1, x2, y1, y2, t;
-	int		x, y;
-	int		vnum;
-
-#if 0
-{
-	int		i;
-	num_edge_verts = numvertexes-1;
-	for (i=0 ; i<numvertexes-1 ; i++)
-		edge_verts[i] = i+1;
-}
-#endif
-
-	x1 = (4096 + (int)(v1[0]+0.5)) >> 7;
-	y1 = (4096 + (int)(v1[1]+0.5)) >> 7;
-	x2 = (4096 + (int)(v2[0]+0.5)) >> 7;
-	y2 = (4096 + (int)(v2[1]+0.5)) >> 7;
-
-	if (x1 > x2)
-	{
-		t = x1;
-		x1 = x2;
-		x2 = t;
-	}
-	if (y1 > y2)
-	{
-		t = y1;
-		y1 = y2;
-		y2 = t;
-	}
-#if 0
-	x1--;
-	x2++;
-	y1--;
-	y2++;
-	if (x1 < 0)
-		x1 = 0;
-	if (x2 >= HASH_SIZE)
-		x2 = HASH_SIZE;
-	if (y1 < 0)
-		y1 = 0;
-	if (y2 >= HASH_SIZE)
-		y2 = HASH_SIZE;
-#endif
-	num_edge_verts = 0;
-	for (x=x1 ; x <= x2 ; x++)
-	{
-		for (y=y1 ; y <= y2 ; y++)
-		{
-			for (vnum=hashverts[y*HASH_SIZE+x] ; vnum ; vnum=vertexchain[vnum])
-			{
-				edge_verts[num_edge_verts++] = vnum;
-			}
-		}
-	}
-}
-
-#else
-/*
-==========
-FindEdgeVerts
-
-Forced a dumb check of everything
-==========
-*/
-void FindEdgeVerts (vec3_t v1, vec3_t v2)
-{
-	int		i;
-
-	num_edge_verts = numvertexes-1;
-	for (i=0 ; i<num_edge_verts ; i++)
-		edge_verts[i] = i+1;
-}
-#endif
-
-/*
-==========
-TestEdge
-
-Can be recursively reentered
-==========
-*/
-void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
-{
-	int		j, k;
-	vec_t	dist;
-	vec3_t	delta;
-	vec3_t	exact;
-	vec3_t	off;
-	vec_t	error;
-	vec3_t	p;
-
-	if (p1 == p2)
-	{
-		c_degenerate++;
-		return;		// degenerate edge
-	}
-
-	for (k=startvert ; k<num_edge_verts ; k++)
-	{
-		j = edge_verts[k];
-		if (j==p1 || j == p2)
-			continue;
-
-		VectorCopy (dvertexes[j].point, p);
-
-		VectorSubtract (p, edge_start, delta);
-		dist = DotProduct (delta, edge_dir);
-		if (dist <=start || dist >= end)
-			continue;		// off an end
-		VectorMA (edge_start, dist, edge_dir, exact);
-		VectorSubtract (p, exact, off);
-		error = VectorLength (off);
-
-		if (fabs(error) > OFF_EPSILON)
-			continue;		// not on the edge
-
-		// break the edge
-		c_tjunctions++;
-		TestEdge (start, dist, p1, j, k+1);
-		TestEdge (dist, end, j, p2, k+1);
-		return;
-	}
-
-	// the edge p1 to p2 is now free of tjunctions
-	if (numsuperverts >= MAX_SUPERVERTS)
-		Error ("MAX_SUPERVERTS");
-	superverts[numsuperverts] = p1;
-	numsuperverts++;
-}
-
-/*
-==================
-FixFaceEdges
-
-==================
-*/
-void FixFaceEdges (node_t *node, face_t *f)
-{
-	int		p1, p2;
-	int		i;
-	vec3_t	e2;
-	vec_t	len;
-	int		count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
-	int		base;
-
-	if (f->merged || f->split[0] || f->split[1])
-		return;
-
-	numsuperverts = 0;
-
-	for (i=0 ; i<f->numpoints ; i++)
-	{
-		p1 = f->vertexnums[i];
-		p2 = f->vertexnums[(i+1)%f->numpoints];
-
-		VectorCopy (dvertexes[p1].point, edge_start);
-		VectorCopy (dvertexes[p2].point, e2);
-
-		FindEdgeVerts (edge_start, e2);
-
-		VectorSubtract (e2, edge_start, edge_dir);
-		len = VectorNormalize (edge_dir, edge_dir);
-
-		start[i] = numsuperverts;
-		TestEdge (0, len, p1, p2, 0);
-
-		count[i] = numsuperverts - start[i];
-	}
-
-	if (numsuperverts < 3)
-	{	// entire face collapsed
-		f->numpoints = 0;
-		c_facecollapse++;
-		return;
-	}
-
-	// we want to pick a vertex that doesn't have tjunctions
-	// on either side, which can cause artifacts on trifans,
-	// especially underwater
-	for (i=0 ; i<f->numpoints ; i++)
-	{
-		if (count[i] == 1 && count[(i+f->numpoints-1)%f->numpoints] == 1)
-			break;
-	}
-	if (i == f->numpoints)
-	{
-		f->badstartvert = true;
-		c_badstartverts++;
-		base = 0;
-	}
-	else
-	{	// rotate the vertex order
-		base = start[i];
-	}
-
-	// this may fragment the face if > MAXEDGES
-	FaceFromSuperverts (node, f, base);
-}
-
-/*
-==================
-FixEdges_r
-==================
-*/
-void FixEdges_r (node_t *node)
-{
-	int		i;
-	face_t	*f;
-
-	if (node->planenum == PLANENUM_LEAF)
-		return;
-
-	for (f=node->faces ; f ; f=f->next)
-		FixFaceEdges (node, f);
-
-	for (i=0 ; i<2 ; i++)
-		FixEdges_r (node->children[i]);
-}
-
-/*
-===========
-FixTjuncs
-
-===========
-*/
-void FixTjuncs (node_t *headnode)
-{
-	// snap and merge all vertexes
-	Sys_FPrintf( SYS_VRB, "---- snap verts ----\n");
-	memset (hashverts, 0, sizeof(hashverts));
-	c_totalverts = 0;
-	c_uniqueverts = 0;
-	c_faceoverflows = 0;
-	EmitVertexes_r (headnode);
-	Sys_FPrintf( SYS_VRB, "%i unique from %i\n", c_uniqueverts, c_totalverts);
-
-	// break edges on tjunctions
-	Sys_FPrintf( SYS_VRB, "---- tjunc ----\n");
-	c_tryedges = 0;
-	c_degenerate = 0;
-	c_facecollapse = 0;
-	c_tjunctions = 0;
-	if (!notjunc)
-		FixEdges_r (headnode);
-	Sys_FPrintf( SYS_VRB, "%5i edges degenerated\n", c_degenerate);
-	Sys_FPrintf( SYS_VRB, "%5i faces degenerated\n", c_facecollapse);
-	Sys_FPrintf( SYS_VRB, "%5i edges added by tjunctions\n", c_tjunctions);
-	Sys_FPrintf( SYS_VRB, "%5i faces added by tjunctions\n", c_faceoverflows);
-	Sys_FPrintf( SYS_VRB, "%5i bad start verts\n", c_badstartverts);
-}
-
-
-//========================================================
-
-int		c_faces;
-
-face_t	*AllocFace (void)
-{
-	face_t	*f;
-
-	f = malloc(sizeof(*f));
-	memset (f, 0, sizeof(*f));
-	c_faces++;
-
-	return f;
-}
-
-face_t *NewFaceFromFace (face_t *f)
-{
-	face_t	*newf;
-
-	newf = AllocFace ();
-	*newf = *f;
-	newf->merged = NULL;
-	newf->split[0] = newf->split[1] = NULL;
-	newf->w = NULL;
-	return newf;
-}
-
-void FreeFace (face_t *f)
-{
-	if (f->w)
-		FreeWinding (f->w);
-	free (f);
-	c_faces--;
-}
-
-//========================================================
-
-/*
-==================
-GetEdge
-
-Called by writebsp.
-Don't allow four way edges
-==================
-*/
-int GetEdge2 (int v1, int v2,  face_t *f)
-{
-	dedge_t	*edge;
-	int		i;
-
-	c_tryedges++;
-
-	if (!noshare)
-	{
-		for (i=firstmodeledge ; i < numedges ; i++)
-		{
-			edge = &dedges[i];
-			if (v1 == edge->v[1] && v2 == edge->v[0]
-			&& edgefaces[i][0]->contents == f->contents)
-			{
-				if (edgefaces[i][1])
-	//				Sys_Printf ("WARNING: multiple backward edge\n");
-					continue;
-				edgefaces[i][1] = f;
-				return -i;
-			}
-	#if 0
-			if (v1 == edge->v[0] && v2 == edge->v[1])
-			{
-				Sys_Printf ("WARNING: multiple forward edge\n");
-				return i;
-			}
-	#endif
-		}
-	}
-
-// emit an edge
-	if (numedges >= MAX_MAP_EDGES)
-		Error ("numedges == MAX_MAP_EDGES");
-	edge = &dedges[numedges];
-	numedges++;
-	edge->v[0] = v1;
-	edge->v[1] = v2;
-	edgefaces[numedges-1][0] = f;
-	
-	return numedges-1;
-}
-
-/*
-===========================================================================
-
-FACE MERGING
-
-===========================================================================
-*/
-
-#define	CONTINUOUS_EPSILON	0.001
-
-/*
-=============
-TryMergeWinding
-
-If two polygons share a common edge and the edges that meet at the
-common points are both inside the other polygons, merge them
-
-Returns NULL if the faces couldn't be merged, or the new face.
-The originals will NOT be freed.
-=============
-*/
-winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal)
-{
-	vec_t		*p1, *p2, *p3, *p4, *back;
-	winding_t	*newf;
-	int			i, j, k, l;
-	vec3_t		normal, delta;
-	vec_t		dot;
-	qboolean	keep1, keep2;
-	
-
-	//
-	// find a common edge
-	//	
-	p1 = p2 = NULL;	// stop compiler warning
-	j = 0;			// 
-	
-	for (i=0 ; i<f1->numpoints ; i++)
-	{
-		p1 = f1->p[i];
-		p2 = f1->p[(i+1)%f1->numpoints];
-		for (j=0 ; j<f2->numpoints ; j++)
-		{
-			p3 = f2->p[j];
-			p4 = f2->p[(j+1)%f2->numpoints];
-			for (k=0 ; k<3 ; k++)
-			{
-				if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
-					break;
-				if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
-					break;
-			}
-			if (k==3)
-				break;
-		}
-		if (j < f2->numpoints)
-			break;
-	}
-	
-	if (i == f1->numpoints)
-		return NULL;			// no matching edges
-
-	//
-	// check slope of connected lines
-	// if the slopes are colinear, the point can be removed
-	//
-	back = f1->p[(i+f1->numpoints-1)%f1->numpoints];
-	VectorSubtract (p1, back, delta);
-	CrossProduct (planenormal, delta, normal);
-	VectorNormalize (normal, normal);
-	
-	back = f2->p[(j+2)%f2->numpoints];
-	VectorSubtract (back, p1, delta);
-	dot = DotProduct (delta, normal);
-	if (dot > CONTINUOUS_EPSILON)
-		return NULL;			// not a convex polygon
-	keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
-	
-	back = f1->p[(i+2)%f1->numpoints];
-	VectorSubtract (back, p2, delta);
-	CrossProduct (planenormal, delta, normal);
-	VectorNormalize (normal, normal);
-
-	back = f2->p[(j+f2->numpoints-1)%f2->numpoints];
-	VectorSubtract (back, p2, delta);
-	dot = DotProduct (delta, normal);
-	if (dot > CONTINUOUS_EPSILON)
-		return NULL;			// not a convex polygon
-	keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
-
-	//
-	// build the new polygon
-	//
-	newf = AllocWinding (f1->numpoints + f2->numpoints);
-	
-	// copy first polygon
-	for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
-	{
-		if (k==(i+1)%f1->numpoints && !keep2)
-			continue;
-		
-		VectorCopy (f1->p[k], newf->p[newf->numpoints]);
-		newf->numpoints++;
-	}
-	
-	// copy second polygon
-	for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
-	{
-		if (l==(j+1)%f2->numpoints && !keep1)
-			continue;
-		VectorCopy (f2->p[l], newf->p[newf->numpoints]);
-		newf->numpoints++;
-	}
-
-	return newf;
-}
-
-/*
-=============
-TryMerge
-
-If two polygons share a common edge and the edges that meet at the
-common points are both inside the other polygons, merge them
-
-Returns NULL if the faces couldn't be merged, or the new face.
-The originals will NOT be freed.
-=============
-*/
-face_t *TryMerge (face_t *f1, face_t *f2, vec3_t planenormal)
-{
-	face_t		*newf;
-	winding_t	*nw;
-
-	if (!f1->w || !f2->w)
-		return NULL;
-	if (f1->texinfo != f2->texinfo)
-		return NULL;
-	if (f1->planenum != f2->planenum)	// on front and back sides
-		return NULL;
-	if (f1->contents != f2->contents)
-		return NULL;
-		
-
-	nw = TryMergeWinding (f1->w, f2->w, planenormal);
-	if (!nw)
-		return NULL;
-
-	c_merge++;
-	newf = NewFaceFromFace (f1);
-	newf->w = nw;
-
-	f1->merged = newf;
-	f2->merged = newf;
-
-	return newf;
-}
-
-/*
-===============
-MergeNodeFaces
-===============
-*/
-void MergeNodeFaces (node_t *node)
-{
-	face_t	*f1, *f2, *end;
-	face_t	*merged;
-	plane_t	*plane;
-
-	plane = &mapplanes[node->planenum];
-	merged = NULL;
-	
-	for (f1 = node->faces ; f1 ; f1 = f1->next)
-	{
-		if (f1->merged || f1->split[0] || f1->split[1])
-			continue;
-		for (f2 = node->faces ; f2 != f1 ; f2=f2->next)
-		{
-			if (f2->merged || f2->split[0] || f2->split[1])
-				continue;
-			merged = TryMerge (f1, f2, plane->normal);
-			if (!merged)
-				continue;
-
-			// add merged to the end of the node face list 
-			// so it will be checked against all the faces again
-			for (end = node->faces ; end->next ; end = end->next)
-			;
-			merged->next = NULL;
-			end->next = merged;
-			break;
-		}
-	}
-}
-
-//=====================================================================
-
-/*
-===============
-SubdivideFace
-
-Chop up faces that are larger than we want in the surface cache
-===============
-*/
-void SubdivideFace (node_t *node, face_t *f)
-{
-	float		mins, maxs;
-	vec_t		v;
-	int			axis, i;
-	texinfo_t	*tex;
-	vec3_t		temp;
-	vec_t		dist;
-	winding_t	*w, *frontw, *backw;
-
-	if (f->merged)
-		return;
-
-// special (non-surface cached) faces don't need subdivision
-	tex = &texinfo[f->texinfo];
-
-	if ( tex->flags & (SURF_WARP|SURF_SKY) )
-	{
-		return;
-	}
-
-	for (axis = 0 ; axis < 2 ; axis++)
-	{
-		while (1)
-		{
-			mins = 999999;
-			maxs = -999999;
-			
-			VectorCopy (tex->vecs[axis], temp);
-			w = f->w;
-			for (i=0 ; i<w->numpoints ; i++)
-			{
-				v = DotProduct (w->p[i], temp);
-				if (v < mins)
-					mins = v;
-				if (v > maxs)
-					maxs = v;
-			}
-#if 0
-			if (maxs - mins <= 0)
-				Error ("zero extents");
-#endif
-			if (axis == 2)
-			{	// allow double high walls
-				if (maxs - mins <= subdivide_size/* *2 */)
-					break;
-			}
-			else if (maxs - mins <= subdivide_size)
-				break;
-			
-		// split it
-			c_subdivide++;
-			
-			v = VectorNormalize (temp, temp);	
-
-			dist = (mins + subdivide_size - 16)/v;
-
-			ClipWindingEpsilon (w, temp, dist, ON_EPSILON, &frontw, &backw);
-			if (!frontw || !backw)
-				Error ("SubdivideFace: didn't split the polygon");
-
-			f->split[0] = NewFaceFromFace (f);
-			f->split[0]->w = frontw;
-			f->split[0]->next = node->faces;
-			node->faces = f->split[0];
-
-			f->split[1] = NewFaceFromFace (f);
-			f->split[1]->w = backw;
-			f->split[1]->next = node->faces;
-			node->faces = f->split[1];
-
-			SubdivideFace (node, f->split[0]);
-			SubdivideFace (node, f->split[1]);
-			return;
-		}
-	}
-}
-
-void SubdivideNodeFaces (node_t *node)
-{
-	face_t	*f;
-
-	for (f = node->faces ; f ; f=f->next)
-	{
-		SubdivideFace (node, f);
-	}
-}
-
-//===========================================================================
-
-int	c_nodefaces;
-
-
-/*
-============
-FaceFromPortal
-
-============
-*/
-face_t *FaceFromPortal (portal_t *p, int pside)
-{
-	face_t	*f;
-	side_t	*side;
-
-	side = p->side;
-	if (!side)
-		return NULL;	// portal does not bridge different visible contents
-
-	f = AllocFace ();
-
-	f->texinfo = side->texinfo;
-	f->planenum = (side->planenum & ~1) | pside;
-	f->portal = p;
-
-	if ( (p->nodes[pside]->contents & CONTENTS_WINDOW)
-		&& VisibleContents(p->nodes[!pside]->contents^p->nodes[pside]->contents) == CONTENTS_WINDOW )
-		return NULL;	// don't show insides of windows
-
-	if (pside)
-	{
-		f->w = ReverseWinding(p->winding);
-		f->contents = p->nodes[1]->contents;
-	}
-	else
-	{
-		f->w = CopyWinding(p->winding);
-		f->contents = p->nodes[0]->contents;
-	}
-	return f;
-}
-
-
-/*
-===============
-MakeFaces_r
-
-If a portal will make a visible face,
-mark the side that originally created it
-
-  solid / empty : solid
-  solid / water : solid
-  water / empty : water
-  water / water : none
-===============
-*/
-void MakeFaces_r (node_t *node)
-{
-	portal_t	*p;
-	int			s;
-
-	// recurse down to leafs
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		MakeFaces_r (node->children[0]);
-		MakeFaces_r (node->children[1]);
-
-		// merge together all visible faces on the node
-		if (!nomerge)
-			MergeNodeFaces (node);
-		if (!nosubdiv)
-			SubdivideNodeFaces (node);
-
-		return;
-	}
-
-	// solid leafs never have visible faces
-	if (node->contents & CONTENTS_SOLID)
-		return;
-
-	// see which portals are valid
-	for (p=node->portals ; p ; p = p->next[s])
-	{
-		s = (p->nodes[1] == node);
-
-		p->face[s] = FaceFromPortal (p, s);
-		if (p->face[s])
-		{
-			c_nodefaces++;
-			p->face[s]->next = p->onnode->faces;
-			p->onnode->faces = p->face[s];
-		}
-	}
-}
-
-/*
-============
-MakeFaces
-============
-*/
-void MakeFaces (node_t *node)
-{
-	Sys_FPrintf( SYS_VRB, "--- MakeFaces ---\n");
-	c_merge = 0;
-	c_subdivide = 0;
-	c_nodefaces = 0;
-
-	MakeFaces_r (node);
-
-	Sys_FPrintf( SYS_VRB, "%5i makefaces\n", c_nodefaces);
-	Sys_FPrintf( SYS_VRB, "%5i merged\n", c_merge);
-	Sys_FPrintf( SYS_VRB, "%5i subdivided\n", c_subdivide);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// faces.c
+
+#include "qbsp.h"
+
+/*
+
+  some faces will be removed before saving, but still form nodes:
+
+  the insides of sky volumes
+  meeting planes of different water current volumes
+
+*/
+
+// undefine for dumb linear searches
+#define	USE_HASHING
+
+#define	INTEGRAL_EPSILON	0.01
+#define	POINT_EPSILON		0.5
+#define	OFF_EPSILON			0.5
+
+int	c_merge;
+int	c_subdivide;
+
+int	c_totalverts;
+int	c_uniqueverts;
+int	c_degenerate;
+int	c_tjunctions;
+int	c_faceoverflows;
+int	c_facecollapse;
+int	c_badstartverts;
+
+#define	MAX_SUPERVERTS	512
+int	superverts[MAX_SUPERVERTS];
+int	numsuperverts;
+
+face_t		*edgefaces[MAX_MAP_EDGES][2];
+int		firstmodeledge = 1;
+int		firstmodelface;
+
+int	c_tryedges;
+
+vec3_t	edge_dir;
+vec3_t	edge_start;
+vec_t	edge_len;
+
+int		num_edge_verts;
+int		edge_verts[MAX_MAP_VERTS];
+
+
+float	subdivide_size = 240;
+
+
+face_t *NewFaceFromFace (face_t *f);
+
+//===========================================================================
+
+typedef struct hashvert_s
+{
+	struct hashvert_s	*next;
+	int		num;
+} hashvert_t;
+
+
+#define	HASH_SIZE	64
+
+
+int	vertexchain[MAX_MAP_VERTS];		// the next vertex in a hash chain
+int	hashverts[HASH_SIZE*HASH_SIZE];	// a vertex number, or 0 for no verts
+
+face_t		*edgefaces[MAX_MAP_EDGES][2];
+
+//============================================================================
+
+
+unsigned HashVec (vec3_t vec)
+{
+	int			x, y;
+
+	x = (4096 + (int)(vec[0]+0.5)) >> 7;
+	y = (4096 + (int)(vec[1]+0.5)) >> 7;
+
+	if ( x < 0 || x >= HASH_SIZE || y < 0 || y >= HASH_SIZE )
+		Error ("HashVec: point outside valid range");
+	
+	return y*HASH_SIZE + x;
+}
+
+#ifdef USE_HASHING
+/*
+=============
+GetVertex
+
+Uses hashing
+=============
+*/
+int	GetVertexnum (vec3_t in)
+{
+	int			h;
+	int			i;
+	float		*p;
+	vec3_t		vert;
+	int			vnum;
+
+	c_totalverts++;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if ( fabs(in[i] - Q_rint(in[i])) < INTEGRAL_EPSILON)
+			vert[i] = Q_rint(in[i]);
+		else
+			vert[i] = in[i];
+	}
+	
+	h = HashVec (vert);
+	
+	for (vnum=hashverts[h] ; vnum ; vnum=vertexchain[vnum])
+	{
+		p = dvertexes[vnum].point;
+		if ( fabs(p[0]-vert[0])<POINT_EPSILON
+		&& fabs(p[1]-vert[1])<POINT_EPSILON
+		&& fabs(p[2]-vert[2])<POINT_EPSILON )
+			return vnum;
+	}
+	
+// emit a vertex
+	if (numvertexes == MAX_MAP_VERTS)
+		Error ("numvertexes == MAX_MAP_VERTS");
+
+	dvertexes[numvertexes].point[0] = vert[0];
+	dvertexes[numvertexes].point[1] = vert[1];
+	dvertexes[numvertexes].point[2] = vert[2];
+
+	vertexchain[numvertexes] = hashverts[h];
+	hashverts[h] = numvertexes;
+
+	c_uniqueverts++;
+
+	numvertexes++;
+		
+	return numvertexes-1;
+}
+#else
+/*
+==================
+GetVertexnum
+
+Dumb linear search
+==================
+*/
+int	GetVertexnum (vec3_t v)
+{
+	int			i, j;
+	dvertex_t	*dv;
+	vec_t		d;
+
+	c_totalverts++;
+
+	// make really close values exactly integral
+	for (i=0 ; i<3 ; i++)
+	{
+		if ( fabs(v[i] - (int)(v[i]+0.5)) < INTEGRAL_EPSILON )
+			v[i] = (int)(v[i]+0.5);
+		if (v[i] < -4096 || v[i] > 4096)
+			Error ("GetVertexnum: outside +/- 4096");
+	}
+
+	// search for an existing vertex match
+	for (i=0, dv=dvertexes ; i<numvertexes ; i++, dv++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			d = v[j] - dv->point[j];
+			if ( d > POINT_EPSILON || d < -POINT_EPSILON)
+				break;
+		}
+		if (j == 3)
+			return i;		// a match
+	}
+
+	// new point
+	if (numvertexes == MAX_MAP_VERTS)
+		Error ("MAX_MAP_VERTS");
+	VectorCopy (v, dv->point);
+	numvertexes++;
+	c_uniqueverts++;
+
+	return numvertexes-1;
+}
+#endif
+
+
+/*
+==================
+FaceFromSuperverts
+
+The faces vertexes have beeb added to the superverts[] array,
+and there may be more there than can be held in a face (MAXEDGES).
+
+If less, the faces vertexnums[] will be filled in, otherwise
+face will reference a tree of split[] faces until all of the
+vertexnums can be added.
+
+superverts[base] will become face->vertexnums[0], and the others
+will be circularly filled in.
+==================
+*/
+void FaceFromSuperverts (node_t *node, face_t *f, int base)
+{
+	face_t	*newf;
+	int		remaining;
+	int		i;
+
+	remaining = numsuperverts;
+	while (remaining > MAXEDGES)
+	{	// must split into two faces, because of vertex overload
+		c_faceoverflows++;
+
+		newf = f->split[0] = NewFaceFromFace (f);
+		newf = f->split[0];
+		newf->next = node->faces;
+		node->faces = newf;
+
+		newf->numpoints = MAXEDGES;
+		for (i=0 ; i<MAXEDGES ; i++)
+			newf->vertexnums[i] = superverts[(i+base)%numsuperverts];
+
+		f->split[1] = NewFaceFromFace (f);
+		f = f->split[1];
+		f->next = node->faces;
+		node->faces = f;
+
+		remaining -= (MAXEDGES-2);
+		base = (base+MAXEDGES-1)%numsuperverts;
+	}
+
+	// copy the vertexes back to the face
+	f->numpoints = remaining;
+	for (i=0 ; i<remaining ; i++)
+		f->vertexnums[i] = superverts[(i+base)%numsuperverts];
+}
+
+
+/*
+==================
+EmitFaceVertexes
+==================
+*/
+void EmitFaceVertexes (node_t *node, face_t *f)
+{
+	winding_t	*w;
+	int			i;
+
+	if (f->merged || f->split[0] || f->split[1])
+		return;
+
+	w = f->w;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		if (noweld)
+		{	// make every point unique
+			if (numvertexes == MAX_MAP_VERTS)
+				Error ("MAX_MAP_VERTS");
+			superverts[i] = numvertexes;
+			VectorCopy (w->p[i], dvertexes[numvertexes].point);
+			numvertexes++;
+			c_uniqueverts++;
+			c_totalverts++;
+		}
+		else
+			superverts[i] = GetVertexnum (w->p[i]);
+	}
+	numsuperverts = w->numpoints;
+
+	// this may fragment the face if > MAXEDGES
+	FaceFromSuperverts (node, f, 0);
+}
+
+/*
+==================
+EmitVertexes_r
+==================
+*/
+void EmitVertexes_r (node_t *node)
+{
+	int		i;
+	face_t	*f;
+
+	if (node->planenum == PLANENUM_LEAF)
+		return;
+
+	for (f=node->faces ; f ; f=f->next)
+	{
+		EmitFaceVertexes (node, f);
+	}
+
+	for (i=0 ; i<2 ; i++)
+		EmitVertexes_r (node->children[i]);
+}
+
+
+#ifdef USE_HASHING
+/*
+==========
+FindEdgeVerts
+
+Uses the hash tables to cut down to a small number
+==========
+*/
+void FindEdgeVerts (vec3_t v1, vec3_t v2)
+{
+	int		x1, x2, y1, y2, t;
+	int		x, y;
+	int		vnum;
+
+#if 0
+{
+	int		i;
+	num_edge_verts = numvertexes-1;
+	for (i=0 ; i<numvertexes-1 ; i++)
+		edge_verts[i] = i+1;
+}
+#endif
+
+	x1 = (4096 + (int)(v1[0]+0.5)) >> 7;
+	y1 = (4096 + (int)(v1[1]+0.5)) >> 7;
+	x2 = (4096 + (int)(v2[0]+0.5)) >> 7;
+	y2 = (4096 + (int)(v2[1]+0.5)) >> 7;
+
+	if (x1 > x2)
+	{
+		t = x1;
+		x1 = x2;
+		x2 = t;
+	}
+	if (y1 > y2)
+	{
+		t = y1;
+		y1 = y2;
+		y2 = t;
+	}
+#if 0
+	x1--;
+	x2++;
+	y1--;
+	y2++;
+	if (x1 < 0)
+		x1 = 0;
+	if (x2 >= HASH_SIZE)
+		x2 = HASH_SIZE;
+	if (y1 < 0)
+		y1 = 0;
+	if (y2 >= HASH_SIZE)
+		y2 = HASH_SIZE;
+#endif
+	num_edge_verts = 0;
+	for (x=x1 ; x <= x2 ; x++)
+	{
+		for (y=y1 ; y <= y2 ; y++)
+		{
+			for (vnum=hashverts[y*HASH_SIZE+x] ; vnum ; vnum=vertexchain[vnum])
+			{
+				edge_verts[num_edge_verts++] = vnum;
+			}
+		}
+	}
+}
+
+#else
+/*
+==========
+FindEdgeVerts
+
+Forced a dumb check of everything
+==========
+*/
+void FindEdgeVerts (vec3_t v1, vec3_t v2)
+{
+	int		i;
+
+	num_edge_verts = numvertexes-1;
+	for (i=0 ; i<num_edge_verts ; i++)
+		edge_verts[i] = i+1;
+}
+#endif
+
+/*
+==========
+TestEdge
+
+Can be recursively reentered
+==========
+*/
+void TestEdge (vec_t start, vec_t end, int p1, int p2, int startvert)
+{
+	int		j, k;
+	vec_t	dist;
+	vec3_t	delta;
+	vec3_t	exact;
+	vec3_t	off;
+	vec_t	error;
+	vec3_t	p;
+
+	if (p1 == p2)
+	{
+		c_degenerate++;
+		return;		// degenerate edge
+	}
+
+	for (k=startvert ; k<num_edge_verts ; k++)
+	{
+		j = edge_verts[k];
+		if (j==p1 || j == p2)
+			continue;
+
+		VectorCopy (dvertexes[j].point, p);
+
+		VectorSubtract (p, edge_start, delta);
+		dist = DotProduct (delta, edge_dir);
+		if (dist <=start || dist >= end)
+			continue;		// off an end
+		VectorMA (edge_start, dist, edge_dir, exact);
+		VectorSubtract (p, exact, off);
+		error = VectorLength (off);
+
+		if (fabs(error) > OFF_EPSILON)
+			continue;		// not on the edge
+
+		// break the edge
+		c_tjunctions++;
+		TestEdge (start, dist, p1, j, k+1);
+		TestEdge (dist, end, j, p2, k+1);
+		return;
+	}
+
+	// the edge p1 to p2 is now free of tjunctions
+	if (numsuperverts >= MAX_SUPERVERTS)
+		Error ("MAX_SUPERVERTS");
+	superverts[numsuperverts] = p1;
+	numsuperverts++;
+}
+
+/*
+==================
+FixFaceEdges
+
+==================
+*/
+void FixFaceEdges (node_t *node, face_t *f)
+{
+	int		p1, p2;
+	int		i;
+	vec3_t	e2;
+	vec_t	len;
+	int		count[MAX_SUPERVERTS], start[MAX_SUPERVERTS];
+	int		base;
+
+	if (f->merged || f->split[0] || f->split[1])
+		return;
+
+	numsuperverts = 0;
+
+	for (i=0 ; i<f->numpoints ; i++)
+	{
+		p1 = f->vertexnums[i];
+		p2 = f->vertexnums[(i+1)%f->numpoints];
+
+		VectorCopy (dvertexes[p1].point, edge_start);
+		VectorCopy (dvertexes[p2].point, e2);
+
+		FindEdgeVerts (edge_start, e2);
+
+		VectorSubtract (e2, edge_start, edge_dir);
+		len = VectorNormalize (edge_dir, edge_dir);
+
+		start[i] = numsuperverts;
+		TestEdge (0, len, p1, p2, 0);
+
+		count[i] = numsuperverts - start[i];
+	}
+
+	if (numsuperverts < 3)
+	{	// entire face collapsed
+		f->numpoints = 0;
+		c_facecollapse++;
+		return;
+	}
+
+	// we want to pick a vertex that doesn't have tjunctions
+	// on either side, which can cause artifacts on trifans,
+	// especially underwater
+	for (i=0 ; i<f->numpoints ; i++)
+	{
+		if (count[i] == 1 && count[(i+f->numpoints-1)%f->numpoints] == 1)
+			break;
+	}
+	if (i == f->numpoints)
+	{
+		f->badstartvert = true;
+		c_badstartverts++;
+		base = 0;
+	}
+	else
+	{	// rotate the vertex order
+		base = start[i];
+	}
+
+	// this may fragment the face if > MAXEDGES
+	FaceFromSuperverts (node, f, base);
+}
+
+/*
+==================
+FixEdges_r
+==================
+*/
+void FixEdges_r (node_t *node)
+{
+	int		i;
+	face_t	*f;
+
+	if (node->planenum == PLANENUM_LEAF)
+		return;
+
+	for (f=node->faces ; f ; f=f->next)
+		FixFaceEdges (node, f);
+
+	for (i=0 ; i<2 ; i++)
+		FixEdges_r (node->children[i]);
+}
+
+/*
+===========
+FixTjuncs
+
+===========
+*/
+void FixTjuncs (node_t *headnode)
+{
+	// snap and merge all vertexes
+	Sys_FPrintf( SYS_VRB, "---- snap verts ----\n");
+	memset (hashverts, 0, sizeof(hashverts));
+	c_totalverts = 0;
+	c_uniqueverts = 0;
+	c_faceoverflows = 0;
+	EmitVertexes_r (headnode);
+	Sys_FPrintf( SYS_VRB, "%i unique from %i\n", c_uniqueverts, c_totalverts);
+
+	// break edges on tjunctions
+	Sys_FPrintf( SYS_VRB, "---- tjunc ----\n");
+	c_tryedges = 0;
+	c_degenerate = 0;
+	c_facecollapse = 0;
+	c_tjunctions = 0;
+	if (!notjunc)
+		FixEdges_r (headnode);
+	Sys_FPrintf( SYS_VRB, "%5i edges degenerated\n", c_degenerate);
+	Sys_FPrintf( SYS_VRB, "%5i faces degenerated\n", c_facecollapse);
+	Sys_FPrintf( SYS_VRB, "%5i edges added by tjunctions\n", c_tjunctions);
+	Sys_FPrintf( SYS_VRB, "%5i faces added by tjunctions\n", c_faceoverflows);
+	Sys_FPrintf( SYS_VRB, "%5i bad start verts\n", c_badstartverts);
+}
+
+
+//========================================================
+
+int		c_faces;
+
+face_t	*AllocFace (void)
+{
+	face_t	*f;
+
+	f = malloc(sizeof(*f));
+	memset (f, 0, sizeof(*f));
+	c_faces++;
+
+	return f;
+}
+
+face_t *NewFaceFromFace (face_t *f)
+{
+	face_t	*newf;
+
+	newf = AllocFace ();
+	*newf = *f;
+	newf->merged = NULL;
+	newf->split[0] = newf->split[1] = NULL;
+	newf->w = NULL;
+	return newf;
+}
+
+void FreeFace (face_t *f)
+{
+	if (f->w)
+		FreeWinding (f->w);
+	free (f);
+	c_faces--;
+}
+
+//========================================================
+
+/*
+==================
+GetEdge
+
+Called by writebsp.
+Don't allow four way edges
+==================
+*/
+int GetEdge2 (int v1, int v2,  face_t *f)
+{
+	dedge_t	*edge;
+	int		i;
+
+	c_tryedges++;
+
+	if (!noshare)
+	{
+		for (i=firstmodeledge ; i < numedges ; i++)
+		{
+			edge = &dedges[i];
+			if (v1 == edge->v[1] && v2 == edge->v[0]
+			&& edgefaces[i][0]->contents == f->contents)
+			{
+				if (edgefaces[i][1])
+	//				Sys_Printf ("WARNING: multiple backward edge\n");
+					continue;
+				edgefaces[i][1] = f;
+				return -i;
+			}
+	#if 0
+			if (v1 == edge->v[0] && v2 == edge->v[1])
+			{
+				Sys_Printf ("WARNING: multiple forward edge\n");
+				return i;
+			}
+	#endif
+		}
+	}
+
+// emit an edge
+	if (numedges >= MAX_MAP_EDGES)
+		Error ("numedges == MAX_MAP_EDGES");
+	edge = &dedges[numedges];
+	numedges++;
+	edge->v[0] = v1;
+	edge->v[1] = v2;
+	edgefaces[numedges-1][0] = f;
+	
+	return numedges-1;
+}
+
+/*
+===========================================================================
+
+FACE MERGING
+
+===========================================================================
+*/
+
+#define	CONTINUOUS_EPSILON	0.001
+
+/*
+=============
+TryMergeWinding
+
+If two polygons share a common edge and the edges that meet at the
+common points are both inside the other polygons, merge them
+
+Returns NULL if the faces couldn't be merged, or the new face.
+The originals will NOT be freed.
+=============
+*/
+winding_t *TryMergeWinding (winding_t *f1, winding_t *f2, vec3_t planenormal)
+{
+	vec_t		*p1, *p2, *p3, *p4, *back;
+	winding_t	*newf;
+	int			i, j, k, l;
+	vec3_t		normal, delta;
+	vec_t		dot;
+	qboolean	keep1, keep2;
+	
+
+	//
+	// find a common edge
+	//	
+	p1 = p2 = NULL;	// stop compiler warning
+	j = 0;			// 
+	
+	for (i=0 ; i<f1->numpoints ; i++)
+	{
+		p1 = f1->p[i];
+		p2 = f1->p[(i+1)%f1->numpoints];
+		for (j=0 ; j<f2->numpoints ; j++)
+		{
+			p3 = f2->p[j];
+			p4 = f2->p[(j+1)%f2->numpoints];
+			for (k=0 ; k<3 ; k++)
+			{
+				if (fabs(p1[k] - p4[k]) > EQUAL_EPSILON)
+					break;
+				if (fabs(p2[k] - p3[k]) > EQUAL_EPSILON)
+					break;
+			}
+			if (k==3)
+				break;
+		}
+		if (j < f2->numpoints)
+			break;
+	}
+	
+	if (i == f1->numpoints)
+		return NULL;			// no matching edges
+
+	//
+	// check slope of connected lines
+	// if the slopes are colinear, the point can be removed
+	//
+	back = f1->p[(i+f1->numpoints-1)%f1->numpoints];
+	VectorSubtract (p1, back, delta);
+	CrossProduct (planenormal, delta, normal);
+	VectorNormalize (normal, normal);
+	
+	back = f2->p[(j+2)%f2->numpoints];
+	VectorSubtract (back, p1, delta);
+	dot = DotProduct (delta, normal);
+	if (dot > CONTINUOUS_EPSILON)
+		return NULL;			// not a convex polygon
+	keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
+	
+	back = f1->p[(i+2)%f1->numpoints];
+	VectorSubtract (back, p2, delta);
+	CrossProduct (planenormal, delta, normal);
+	VectorNormalize (normal, normal);
+
+	back = f2->p[(j+f2->numpoints-1)%f2->numpoints];
+	VectorSubtract (back, p2, delta);
+	dot = DotProduct (delta, normal);
+	if (dot > CONTINUOUS_EPSILON)
+		return NULL;			// not a convex polygon
+	keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
+
+	//
+	// build the new polygon
+	//
+	newf = AllocWinding (f1->numpoints + f2->numpoints);
+	
+	// copy first polygon
+	for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
+	{
+		if (k==(i+1)%f1->numpoints && !keep2)
+			continue;
+		
+		VectorCopy (f1->p[k], newf->p[newf->numpoints]);
+		newf->numpoints++;
+	}
+	
+	// copy second polygon
+	for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
+	{
+		if (l==(j+1)%f2->numpoints && !keep1)
+			continue;
+		VectorCopy (f2->p[l], newf->p[newf->numpoints]);
+		newf->numpoints++;
+	}
+
+	return newf;
+}
+
+/*
+=============
+TryMerge
+
+If two polygons share a common edge and the edges that meet at the
+common points are both inside the other polygons, merge them
+
+Returns NULL if the faces couldn't be merged, or the new face.
+The originals will NOT be freed.
+=============
+*/
+face_t *TryMerge (face_t *f1, face_t *f2, vec3_t planenormal)
+{
+	face_t		*newf;
+	winding_t	*nw;
+
+	if (!f1->w || !f2->w)
+		return NULL;
+	if (f1->texinfo != f2->texinfo)
+		return NULL;
+	if (f1->planenum != f2->planenum)	// on front and back sides
+		return NULL;
+	if (f1->contents != f2->contents)
+		return NULL;
+		
+
+	nw = TryMergeWinding (f1->w, f2->w, planenormal);
+	if (!nw)
+		return NULL;
+
+	c_merge++;
+	newf = NewFaceFromFace (f1);
+	newf->w = nw;
+
+	f1->merged = newf;
+	f2->merged = newf;
+
+	return newf;
+}
+
+/*
+===============
+MergeNodeFaces
+===============
+*/
+void MergeNodeFaces (node_t *node)
+{
+	face_t	*f1, *f2, *end;
+	face_t	*merged;
+	plane_t	*plane;
+
+	plane = &mapplanes[node->planenum];
+	merged = NULL;
+	
+	for (f1 = node->faces ; f1 ; f1 = f1->next)
+	{
+		if (f1->merged || f1->split[0] || f1->split[1])
+			continue;
+		for (f2 = node->faces ; f2 != f1 ; f2=f2->next)
+		{
+			if (f2->merged || f2->split[0] || f2->split[1])
+				continue;
+			merged = TryMerge (f1, f2, plane->normal);
+			if (!merged)
+				continue;
+
+			// add merged to the end of the node face list 
+			// so it will be checked against all the faces again
+			for (end = node->faces ; end->next ; end = end->next)
+			;
+			merged->next = NULL;
+			end->next = merged;
+			break;
+		}
+	}
+}
+
+//=====================================================================
+
+/*
+===============
+SubdivideFace
+
+Chop up faces that are larger than we want in the surface cache
+===============
+*/
+void SubdivideFace (node_t *node, face_t *f)
+{
+	float		mins, maxs;
+	vec_t		v;
+	int			axis, i;
+	texinfo_t	*tex;
+	vec3_t		temp;
+	vec_t		dist;
+	winding_t	*w, *frontw, *backw;
+
+	if (f->merged)
+		return;
+
+// special (non-surface cached) faces don't need subdivision
+	tex = &texinfo[f->texinfo];
+
+	if ( tex->flags & (SURF_WARP|SURF_SKY) )
+	{
+		return;
+	}
+
+	for (axis = 0 ; axis < 2 ; axis++)
+	{
+		while (1)
+		{
+			mins = 999999;
+			maxs = -999999;
+			
+			VectorCopy (tex->vecs[axis], temp);
+			w = f->w;
+			for (i=0 ; i<w->numpoints ; i++)
+			{
+				v = DotProduct (w->p[i], temp);
+				if (v < mins)
+					mins = v;
+				if (v > maxs)
+					maxs = v;
+			}
+#if 0
+			if (maxs - mins <= 0)
+				Error ("zero extents");
+#endif
+			if (axis == 2)
+			{	// allow double high walls
+				if (maxs - mins <= subdivide_size/* *2 */)
+					break;
+			}
+			else if (maxs - mins <= subdivide_size)
+				break;
+			
+		// split it
+			c_subdivide++;
+			
+			v = VectorNormalize (temp, temp);	
+
+			dist = (mins + subdivide_size - 16)/v;
+
+			ClipWindingEpsilon (w, temp, dist, ON_EPSILON, &frontw, &backw);
+			if (!frontw || !backw)
+				Error ("SubdivideFace: didn't split the polygon");
+
+			f->split[0] = NewFaceFromFace (f);
+			f->split[0]->w = frontw;
+			f->split[0]->next = node->faces;
+			node->faces = f->split[0];
+
+			f->split[1] = NewFaceFromFace (f);
+			f->split[1]->w = backw;
+			f->split[1]->next = node->faces;
+			node->faces = f->split[1];
+
+			SubdivideFace (node, f->split[0]);
+			SubdivideFace (node, f->split[1]);
+			return;
+		}
+	}
+}
+
+void SubdivideNodeFaces (node_t *node)
+{
+	face_t	*f;
+
+	for (f = node->faces ; f ; f=f->next)
+	{
+		SubdivideFace (node, f);
+	}
+}
+
+//===========================================================================
+
+int	c_nodefaces;
+
+
+/*
+============
+FaceFromPortal
+
+============
+*/
+face_t *FaceFromPortal (portal_t *p, int pside)
+{
+	face_t	*f;
+	side_t	*side;
+
+	side = p->side;
+	if (!side)
+		return NULL;	// portal does not bridge different visible contents
+
+	f = AllocFace ();
+
+	f->texinfo = side->texinfo;
+	f->planenum = (side->planenum & ~1) | pside;
+	f->portal = p;
+
+	if ( (p->nodes[pside]->contents & CONTENTS_WINDOW)
+		&& VisibleContents(p->nodes[!pside]->contents^p->nodes[pside]->contents) == CONTENTS_WINDOW )
+		return NULL;	// don't show insides of windows
+
+	if (pside)
+	{
+		f->w = ReverseWinding(p->winding);
+		f->contents = p->nodes[1]->contents;
+	}
+	else
+	{
+		f->w = CopyWinding(p->winding);
+		f->contents = p->nodes[0]->contents;
+	}
+	return f;
+}
+
+
+/*
+===============
+MakeFaces_r
+
+If a portal will make a visible face,
+mark the side that originally created it
+
+  solid / empty : solid
+  solid / water : solid
+  water / empty : water
+  water / water : none
+===============
+*/
+void MakeFaces_r (node_t *node)
+{
+	portal_t	*p;
+	int			s;
+
+	// recurse down to leafs
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		MakeFaces_r (node->children[0]);
+		MakeFaces_r (node->children[1]);
+
+		// merge together all visible faces on the node
+		if (!nomerge)
+			MergeNodeFaces (node);
+		if (!nosubdiv)
+			SubdivideNodeFaces (node);
+
+		return;
+	}
+
+	// solid leafs never have visible faces
+	if (node->contents & CONTENTS_SOLID)
+		return;
+
+	// see which portals are valid
+	for (p=node->portals ; p ; p = p->next[s])
+	{
+		s = (p->nodes[1] == node);
+
+		p->face[s] = FaceFromPortal (p, s);
+		if (p->face[s])
+		{
+			c_nodefaces++;
+			p->face[s]->next = p->onnode->faces;
+			p->onnode->faces = p->face[s];
+		}
+	}
+}
+
+/*
+============
+MakeFaces
+============
+*/
+void MakeFaces (node_t *node)
+{
+	Sys_FPrintf( SYS_VRB, "--- MakeFaces ---\n");
+	c_merge = 0;
+	c_subdivide = 0;
+	c_nodefaces = 0;
+
+	MakeFaces_r (node);
+
+	Sys_FPrintf( SYS_VRB, "%5i makefaces\n", c_nodefaces);
+	Sys_FPrintf( SYS_VRB, "%5i merged\n", c_merge);
+	Sys_FPrintf( SYS_VRB, "%5i subdivided\n", c_subdivide);
+}
diff --git a/tools/quake2/q2map/flow.c b/tools/quake2/q2map/flow.c
index 9a34f6f9..d831fbf0 100644
--- a/tools/quake2/q2map/flow.c
+++ b/tools/quake2/q2map/flow.c
@@ -1,787 +1,787 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "qvis.h"
-
-/*
-
-  each portal will have a list of all possible to see from first portal
-
-  if (!thread->portalmightsee[portalnum])
-
-  portal mightsee
-
-  for p2 = all other portals in leaf
-	get sperating planes
-	for all portals that might be seen by p2
-		mark as unseen if not present in seperating plane
-	flood fill a new mightsee
-	save as passagemightsee
-
-
-  void CalcMightSee (leaf_t *leaf, 
-*/
-
-int CountBits (byte *bits, int numbits)
-{
-	int		i;
-	int		c;
-
-	c = 0;
-	for (i=0 ; i<numbits ; i++)
-		if (bits[i>>3] & (1<<(i&7)) )
-			c++;
-
-	return c;
-}
-
-int		c_fullskip;
-int		c_portalskip, c_leafskip;
-int		c_vistest, c_mighttest;
-
-int		c_chop, c_nochop;
-
-int		active;
-
-void CheckStack (leaf_t *leaf, threaddata_t *thread)
-{
-	pstack_t	*p, *p2;
-
-	for (p=thread->pstack_head.next ; p ; p=p->next)
-	{
-//		printf ("=");
-		if (p->leaf == leaf)
-			Error ("CheckStack: leaf recursion");
-		for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
-			if (p2->leaf == p->leaf)
-				Error ("CheckStack: late leaf recursion");
-	}
-//	printf ("\n");
-}
-
-
-winding_t *AllocStackWinding (pstack_t *stack)
-{
-	int		i;
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if (stack->freewindings[i])
-		{
-			stack->freewindings[i] = 0;
-			return &stack->windings[i];
-		}
-	}
-
-	Error ("AllocStackWinding: failed");
-
-	return NULL;
-}
-
-void FreeStackWinding (winding_t *w, pstack_t *stack)
-{
-	int		i;
-
-	i = w - stack->windings;
-
-	if (i<0 || i>2)
-		return;		// not from local
-
-	if (stack->freewindings[i])
-		Error ("FreeStackWinding: allready free");
-	stack->freewindings[i] = 1;
-}
-
-/*
-==============
-Vis_ChopWinding
-
-==============
-*/
-winding_t	*Vis_ChopWinding (winding_t *in, pstack_t *stack, plane_t *split)
-{
-	vec_t	dists[128];
-	int		sides[128];
-	int		counts[3];
-	vec_t	dot;
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	winding_t	*neww;
-
-	counts[0] = counts[1] = counts[2] = 0;
-
-// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->points[i], split->normal);
-		dot -= split->dist;
-		dists[i] = dot;
-		if (dot > ON_EPSILON)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -ON_EPSILON)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-
-	if (!counts[1])
-		return in;		// completely on front side
-	
-	if (!counts[0])
-	{
-		FreeStackWinding (in, stack);
-		return NULL;
-	}
-
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	neww = AllocStackWinding (stack);
-
-	neww->numpoints = 0;
-
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->points[i];
-
-		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
-		{
-			FreeStackWinding (neww, stack);
-			return in;		// can't chop -- fall back to original
-		}
-
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, neww->points[neww->numpoints]);
-			neww->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, neww->points[neww->numpoints]);
-			neww->numpoints++;
-		}
-		
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
-		{
-			FreeStackWinding (neww, stack);
-			return in;		// can't chop -- fall back to original
-		}
-
-	// generate a split point
-		p2 = in->points[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (split->normal[j] == 1)
-				mid[j] = split->dist;
-			else if (split->normal[j] == -1)
-				mid[j] = -split->dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, neww->points[neww->numpoints]);
-		neww->numpoints++;
-	}
-	
-// free the original winding
-	FreeStackWinding (in, stack);
-	
-	return neww;
-}
-
-
-/*
-==============
-ClipToSeperators
-
-Source, pass, and target are an ordering of portals.
-
-Generates seperating planes canidates by taking two points from source and one
-point from pass, and clips target by them.
-
-If target is totally clipped away, that portal can not be seen through.
-
-Normal clip keeps target on the same side as pass, which is correct if the
-order goes source, pass, target.  If the order goes pass, source, target then
-flipclip should be set.
-==============
-*/
-winding_t	*ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack)
-{
-	int			i, j, k, l;
-	plane_t		plane;
-	vec3_t		v1, v2;
-	float		d;
-	vec_t		length;
-	int			counts[3];
-	qboolean		fliptest;
-
-// check all combinations	
-	for (i=0 ; i<source->numpoints ; i++)
-	{
-		l = (i+1)%source->numpoints;
-		VectorSubtract (source->points[l] , source->points[i], v1);
-
-	// fing a vertex of pass that makes a plane that puts all of the
-	// vertexes of pass on the front side and all of the vertexes of
-	// source on the back side
-		for (j=0 ; j<pass->numpoints ; j++)
-		{
-			VectorSubtract (pass->points[j], source->points[i], v2);
-
-			plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
-			plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
-			plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
-			
-		// if points don't make a valid plane, skip it
-
-			length = plane.normal[0] * plane.normal[0]
-			+ plane.normal[1] * plane.normal[1]
-			+ plane.normal[2] * plane.normal[2];
-			
-			if (length < ON_EPSILON)
-				continue;
-
-			length = 1/sqrt(length);
-			
-			plane.normal[0] *= length;
-			plane.normal[1] *= length;
-			plane.normal[2] *= length;
-
-			plane.dist = DotProduct (pass->points[j], plane.normal);
-
-		//
-		// find out which side of the generated seperating plane has the
-		// source portal
-		//
-#if 1
-			fliptest = false;
-			for (k=0 ; k<source->numpoints ; k++)
-			{
-				if (k == i || k == l)
-					continue;
-				d = DotProduct (source->points[k], plane.normal) - plane.dist;
-				if (d < -ON_EPSILON)
-				{	// source is on the negative side, so we want all
-					// pass and target on the positive side
-					fliptest = false;
-					break;
-				}
-				else if (d > ON_EPSILON)
-				{	// source is on the positive side, so we want all
-					// pass and target on the negative side
-					fliptest = true;
-					break;
-				}
-			}
-			if (k == source->numpoints)
-				continue;		// planar with source portal
-#else
-			fliptest = flipclip;
-#endif
-		//
-		// flip the normal if the source portal is backwards
-		//
-			if (fliptest)
-			{
-				VectorSubtract (vec3_origin, plane.normal, plane.normal);
-				plane.dist = -plane.dist;
-			}
-#if 1
-		//
-		// if all of the pass portal points are now on the positive side,
-		// this is the seperating plane
-		//
-			counts[0] = counts[1] = counts[2] = 0;
-			for (k=0 ; k<pass->numpoints ; k++)
-			{
-				if (k==j)
-					continue;
-				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-				if (d < -ON_EPSILON)
-					break;
-				else if (d > ON_EPSILON)
-					counts[0]++;
-				else
-					counts[2]++;
-			}
-			if (k != pass->numpoints)
-				continue;	// points on negative side, not a seperating plane
-				
-			if (!counts[0])
-				continue;	// planar with seperating plane
-#else
-			k = (j+1)%pass->numpoints;
-			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-			if (d < -ON_EPSILON)
-				continue;
-			k = (j+pass->numpoints-1)%pass->numpoints;
-			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-			if (d < -ON_EPSILON)
-				continue;			
-#endif
-		//
-		// flip the normal if we want the back side
-		//
-			if (flipclip)
-			{
-				VectorSubtract (vec3_origin, plane.normal, plane.normal);
-				plane.dist = -plane.dist;
-			}
-			
-		//
-		// clip target by the seperating plane
-		//
-			target = Vis_ChopWinding (target, stack, &plane);
-			if (!target)
-				return NULL;		// target is not visible
-		}
-	}
-	
-	return target;
-}
-
-
-
-/*
-==================
-RecursiveLeafFlow
-
-Flood fill through the leafs
-If src_portal is NULL, this is the originating leaf
-==================
-*/
-void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
-{
-	pstack_t	stack;
-	portal_t	*p;
-	plane_t		backplane;
-	leaf_t 		*leaf;
-	int			i, j;
-	long		*test, *might, *vis, more;
-	int			pnum;
-
-	thread->c_chains++;
-
-	leaf = &leafs[leafnum];
-//	CheckStack (leaf, thread);
-
-	prevstack->next = &stack;
-
-	stack.next = NULL;
-	stack.leaf = leaf;
-	stack.portal = NULL;
-
-	might = (long *)stack.mightsee;
-	vis = (long *)thread->base->portalvis;
-	
-// check all portals for flowing into other leafs	
-	for (i=0 ; i<leaf->numportals ; i++)
-	{
-		p = leaf->portals[i];
-		pnum = p - portals;
-
-		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
-		{
-			continue;	// can't possibly see it
-		}
-
-	// if the portal can't see anything we haven't allready seen, skip it
-		if (p->status == stat_done)
-		{
-			test = (long *)p->portalvis;
-		}
-		else
-		{
-			test = (long *)p->portalflood;
-		}
-
-		more = 0;
-		for (j=0 ; j<portallongs ; j++)
-		{
-			might[j] = ((long *)prevstack->mightsee)[j] & test[j];
-			more |= (might[j] & ~vis[j]);
-		}
-		
-		if (!more && 
-			(thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
-		{	// can't see anything new
-			continue;
-		}
-
-		// get plane of portal, point normal into the neighbor leaf
-		stack.portalplane = p->plane;
-		VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
-		backplane.dist = -p->plane.dist;
-		
-//		c_portalcheck++;
-		
-		stack.portal = p;
-		stack.next = NULL;
-		stack.freewindings[0] = 1;
-		stack.freewindings[1] = 1;
-		stack.freewindings[2] = 1;
-		
-#if 1
-{
-float d;
-
-	d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
-	d -= thread->pstack_head.portalplane.dist;
-	if (d < -p->radius)
-	{
-		continue;
-	}
-	else if (d > p->radius)
-	{
-		stack.pass = p->winding;
-	}
-	else	
-	{
-		stack.pass = Vis_ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
-		if (!stack.pass)
-			continue;
-	}
-}
-#else
-		stack.pass = Vis_ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
-		if (!stack.pass)
-			continue;
-#endif
-
-	
-#if 1
-{
-float d;
-
-	d = DotProduct (thread->base->origin, p->plane.normal);
-	d -= p->plane.dist;
-	if (d > p->radius)
-	{
-		continue;
-	}
-	else if (d < -p->radius)
-	{
-		stack.source = prevstack->source;
-	}
-	else	
-	{
-		stack.source = Vis_ChopWinding (prevstack->source, &stack, &backplane);
-		if (!stack.source)
-			continue;
-	}
-}
-#else
-		stack.source = Vis_ChopWinding (prevstack->source, &stack, &backplane);
-		if (!stack.source)
-			continue;
-#endif
-
-		if (!prevstack->pass)
-		{	// the second leaf can only be blocked if coplanar
-
-			// mark the portal as visible
-			thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
-
-			RecursiveLeafFlow (p->leaf, thread, &stack);
-			continue;
-		}
-
-		stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, false, &stack);
-		if (!stack.pass)
-			continue;
-		
-		stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, true, &stack);
-		if (!stack.pass)
-			continue;
-
-		// mark the portal as visible
-		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
-
-		// flow through it for real
-		RecursiveLeafFlow (p->leaf, thread, &stack);
-	}	
-}
-
-
-/*
-===============
-PortalFlow
-
-generates the portalvis bit vector
-===============
-*/
-void PortalFlow (int portalnum)
-{
-	threaddata_t	data;
-	int				i;
-	portal_t		*p;
-	int				c_might, c_can;
-
-	p = sorted_portals[portalnum];
-	p->status = stat_working;
-
-	c_might = CountBits (p->portalflood, numportals*2);
-
-	memset (&data, 0, sizeof(data));
-	data.base = p;
-	
-	data.pstack_head.portal = p;
-	data.pstack_head.source = p->winding;
-	data.pstack_head.portalplane = p->plane;
-	for (i=0 ; i<portallongs ; i++)
-		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
-	RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
-
-	p->status = stat_done;
-
-	c_can = CountBits (p->portalvis, numportals*2);
-
-	Sys_FPrintf ( SYS_VRB, "portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
-		(int)(p - portals),	c_might, c_can, data.c_chains);
-}
-
-
-/*
-===============================================================================
-
-This is a rough first-order aproximation that is used to trivially reject some
-of the final calculations.
-
-
-Calculates portalfront and portalflood bit vectors
-
-thinking about:
-
-typedef struct passage_s
-{
-	struct passage_s	*next;
-	struct portal_s		*to;
-	stryct sep_s		*seperators;
-	byte				*mightsee;
-} passage_t;
-
-typedef struct portal_s
-{
-	struct passage_s	*passages;
-	int					leaf;		// leaf portal faces into
-} portal_s;
-
-leaf = portal->leaf
-clear 
-for all portals
-
-
-calc portal visibility
-	clear bit vector
-	for all passages
-		passage visibility
-
-
-for a portal to be visible to a passage, it must be on the front of
-all seperating planes, and both portals must be behind the mew portal
-
-===============================================================================
-*/
-
-int		c_flood, c_vis;
-
-
-/*
-==================
-SimpleFlood
-
-==================
-*/
-void SimpleFlood (portal_t *srcportal, int leafnum)
-{
-	int		i;
-	leaf_t	*leaf;
-	portal_t	*p;
-	int		pnum;
-
-	leaf = &leafs[leafnum];
-	
-	for (i=0 ; i<leaf->numportals ; i++)
-	{
-		p = leaf->portals[i];
-		pnum = p - portals;
-		if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) )
-			continue;
-
-		if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) )
-			continue;
-
-		srcportal->portalflood[pnum>>3] |= (1<<(pnum&7));
-		
-		SimpleFlood (srcportal, p->leaf);
-	}
-}
-
-/*
-==============
-BasePortalVis
-==============
-*/
-void BasePortalVis (int portalnum)
-{
-	int			j, k;
-	portal_t	*tp, *p;
-	float		d;
-	winding_t	*w;
-
-	p = portals+portalnum;
-
-	p->portalfront = malloc (portalbytes);
-	memset (p->portalfront, 0, portalbytes);
-
-	p->portalflood = malloc (portalbytes);
-	memset (p->portalflood, 0, portalbytes);
-	
-	p->portalvis = malloc (portalbytes);
-	memset (p->portalvis, 0, portalbytes);
-	
-	for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
-	{
-		if (j == portalnum)
-			continue;
-		w = tp->winding;
-		for (k=0 ; k<w->numpoints ; k++)
-		{
-			d = DotProduct (w->points[k], p->plane.normal)
-				- p->plane.dist;
-			if (d > ON_EPSILON)
-				break;
-		}
-		if (k == w->numpoints)
-			continue;	// no points on front
-
-		w = p->winding;
-		for (k=0 ; k<w->numpoints ; k++)
-		{
-			d = DotProduct (w->points[k], tp->plane.normal)
-				- tp->plane.dist;
-			if (d < -ON_EPSILON)
-				break;
-		}
-		if (k == w->numpoints)
-			continue;	// no points on front
-
-		p->portalfront[j>>3] |= (1<<(j&7));
-	}
-	
-	SimpleFlood (p, p->leaf);
-
-	p->nummightsee = CountBits (p->portalflood, numportals*2);
-//	printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
-	c_flood += p->nummightsee;
-}
-
-
-
-
-
-/*
-===============================================================================
-
-This is a second order aproximation 
-
-Calculates portalvis bit vector
-
-WAAAAAAY too slow.
-
-===============================================================================
-*/
-
-/*
-==================
-RecursiveLeafBitFlow
-
-==================
-*/
-void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
-{
-	portal_t	*p;
-	leaf_t 		*leaf;
-	int			i, j;
-	long		more;
-	int			pnum;
-	byte		newmight[MAX_PORTALS/8];
-
-	leaf = &leafs[leafnum];
-	
-// check all portals for flowing into other leafs	
-	for (i=0 ; i<leaf->numportals ; i++)
-	{
-		p = leaf->portals[i];
-		pnum = p - portals;
-
-		// if some previous portal can't see it, skip
-		if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) )
-			continue;
-
-		// if this portal can see some portals we mightsee, recurse
-		more = 0;
-		for (j=0 ; j<portallongs ; j++)
-		{
-			((long *)newmight)[j] = ((long *)mightsee)[j] 
-				& ((long *)p->portalflood)[j];
-			more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
-		}
-
-		if (!more)
-			continue;	// can't see anything new
-
-		cansee[pnum>>3] |= (1<<(pnum&7));
-
-		RecursiveLeafBitFlow (p->leaf, newmight, cansee);
-	}	
-}
-
-/*
-==============
-BetterPortalVis
-==============
-*/
-void BetterPortalVis (int portalnum)
-{
-	portal_t	*p;
-
-	p = portals+portalnum;
-
-	RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
-
-	// build leaf vis information
-	p->nummightsee = CountBits (p->portalvis, numportals*2);
-	c_vis += p->nummightsee;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "qvis.h"
+
+/*
+
+  each portal will have a list of all possible to see from first portal
+
+  if (!thread->portalmightsee[portalnum])
+
+  portal mightsee
+
+  for p2 = all other portals in leaf
+	get sperating planes
+	for all portals that might be seen by p2
+		mark as unseen if not present in seperating plane
+	flood fill a new mightsee
+	save as passagemightsee
+
+
+  void CalcMightSee (leaf_t *leaf, 
+*/
+
+int CountBits (byte *bits, int numbits)
+{
+	int		i;
+	int		c;
+
+	c = 0;
+	for (i=0 ; i<numbits ; i++)
+		if (bits[i>>3] & (1<<(i&7)) )
+			c++;
+
+	return c;
+}
+
+int		c_fullskip;
+int		c_portalskip, c_leafskip;
+int		c_vistest, c_mighttest;
+
+int		c_chop, c_nochop;
+
+int		active;
+
+void CheckStack (leaf_t *leaf, threaddata_t *thread)
+{
+	pstack_t	*p, *p2;
+
+	for (p=thread->pstack_head.next ; p ; p=p->next)
+	{
+//		printf ("=");
+		if (p->leaf == leaf)
+			Error ("CheckStack: leaf recursion");
+		for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
+			if (p2->leaf == p->leaf)
+				Error ("CheckStack: late leaf recursion");
+	}
+//	printf ("\n");
+}
+
+
+winding_t *AllocStackWinding (pstack_t *stack)
+{
+	int		i;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (stack->freewindings[i])
+		{
+			stack->freewindings[i] = 0;
+			return &stack->windings[i];
+		}
+	}
+
+	Error ("AllocStackWinding: failed");
+
+	return NULL;
+}
+
+void FreeStackWinding (winding_t *w, pstack_t *stack)
+{
+	int		i;
+
+	i = w - stack->windings;
+
+	if (i<0 || i>2)
+		return;		// not from local
+
+	if (stack->freewindings[i])
+		Error ("FreeStackWinding: allready free");
+	stack->freewindings[i] = 1;
+}
+
+/*
+==============
+Vis_ChopWinding
+
+==============
+*/
+winding_t	*Vis_ChopWinding (winding_t *in, pstack_t *stack, plane_t *split)
+{
+	vec_t	dists[128];
+	int		sides[128];
+	int		counts[3];
+	vec_t	dot;
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	winding_t	*neww;
+
+	counts[0] = counts[1] = counts[2] = 0;
+
+// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->points[i], split->normal);
+		dot -= split->dist;
+		dists[i] = dot;
+		if (dot > ON_EPSILON)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -ON_EPSILON)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+
+	if (!counts[1])
+		return in;		// completely on front side
+	
+	if (!counts[0])
+	{
+		FreeStackWinding (in, stack);
+		return NULL;
+	}
+
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	neww = AllocStackWinding (stack);
+
+	neww->numpoints = 0;
+
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->points[i];
+
+		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
+		{
+			FreeStackWinding (neww, stack);
+			return in;		// can't chop -- fall back to original
+		}
+
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, neww->points[neww->numpoints]);
+			neww->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, neww->points[neww->numpoints]);
+			neww->numpoints++;
+		}
+		
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
+		{
+			FreeStackWinding (neww, stack);
+			return in;		// can't chop -- fall back to original
+		}
+
+	// generate a split point
+		p2 = in->points[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (split->normal[j] == 1)
+				mid[j] = split->dist;
+			else if (split->normal[j] == -1)
+				mid[j] = -split->dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, neww->points[neww->numpoints]);
+		neww->numpoints++;
+	}
+	
+// free the original winding
+	FreeStackWinding (in, stack);
+	
+	return neww;
+}
+
+
+/*
+==============
+ClipToSeperators
+
+Source, pass, and target are an ordering of portals.
+
+Generates seperating planes canidates by taking two points from source and one
+point from pass, and clips target by them.
+
+If target is totally clipped away, that portal can not be seen through.
+
+Normal clip keeps target on the same side as pass, which is correct if the
+order goes source, pass, target.  If the order goes pass, source, target then
+flipclip should be set.
+==============
+*/
+winding_t	*ClipToSeperators (winding_t *source, winding_t *pass, winding_t *target, qboolean flipclip, pstack_t *stack)
+{
+	int			i, j, k, l;
+	plane_t		plane;
+	vec3_t		v1, v2;
+	float		d;
+	vec_t		length;
+	int			counts[3];
+	qboolean		fliptest;
+
+// check all combinations	
+	for (i=0 ; i<source->numpoints ; i++)
+	{
+		l = (i+1)%source->numpoints;
+		VectorSubtract (source->points[l] , source->points[i], v1);
+
+	// fing a vertex of pass that makes a plane that puts all of the
+	// vertexes of pass on the front side and all of the vertexes of
+	// source on the back side
+		for (j=0 ; j<pass->numpoints ; j++)
+		{
+			VectorSubtract (pass->points[j], source->points[i], v2);
+
+			plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
+			plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
+			plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
+			
+		// if points don't make a valid plane, skip it
+
+			length = plane.normal[0] * plane.normal[0]
+			+ plane.normal[1] * plane.normal[1]
+			+ plane.normal[2] * plane.normal[2];
+			
+			if (length < ON_EPSILON)
+				continue;
+
+			length = 1/sqrt(length);
+			
+			plane.normal[0] *= length;
+			plane.normal[1] *= length;
+			plane.normal[2] *= length;
+
+			plane.dist = DotProduct (pass->points[j], plane.normal);
+
+		//
+		// find out which side of the generated seperating plane has the
+		// source portal
+		//
+#if 1
+			fliptest = false;
+			for (k=0 ; k<source->numpoints ; k++)
+			{
+				if (k == i || k == l)
+					continue;
+				d = DotProduct (source->points[k], plane.normal) - plane.dist;
+				if (d < -ON_EPSILON)
+				{	// source is on the negative side, so we want all
+					// pass and target on the positive side
+					fliptest = false;
+					break;
+				}
+				else if (d > ON_EPSILON)
+				{	// source is on the positive side, so we want all
+					// pass and target on the negative side
+					fliptest = true;
+					break;
+				}
+			}
+			if (k == source->numpoints)
+				continue;		// planar with source portal
+#else
+			fliptest = flipclip;
+#endif
+		//
+		// flip the normal if the source portal is backwards
+		//
+			if (fliptest)
+			{
+				VectorSubtract (vec3_origin, plane.normal, plane.normal);
+				plane.dist = -plane.dist;
+			}
+#if 1
+		//
+		// if all of the pass portal points are now on the positive side,
+		// this is the seperating plane
+		//
+			counts[0] = counts[1] = counts[2] = 0;
+			for (k=0 ; k<pass->numpoints ; k++)
+			{
+				if (k==j)
+					continue;
+				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+				if (d < -ON_EPSILON)
+					break;
+				else if (d > ON_EPSILON)
+					counts[0]++;
+				else
+					counts[2]++;
+			}
+			if (k != pass->numpoints)
+				continue;	// points on negative side, not a seperating plane
+				
+			if (!counts[0])
+				continue;	// planar with seperating plane
+#else
+			k = (j+1)%pass->numpoints;
+			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+			if (d < -ON_EPSILON)
+				continue;
+			k = (j+pass->numpoints-1)%pass->numpoints;
+			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+			if (d < -ON_EPSILON)
+				continue;			
+#endif
+		//
+		// flip the normal if we want the back side
+		//
+			if (flipclip)
+			{
+				VectorSubtract (vec3_origin, plane.normal, plane.normal);
+				plane.dist = -plane.dist;
+			}
+			
+		//
+		// clip target by the seperating plane
+		//
+			target = Vis_ChopWinding (target, stack, &plane);
+			if (!target)
+				return NULL;		// target is not visible
+		}
+	}
+	
+	return target;
+}
+
+
+
+/*
+==================
+RecursiveLeafFlow
+
+Flood fill through the leafs
+If src_portal is NULL, this is the originating leaf
+==================
+*/
+void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
+{
+	pstack_t	stack;
+	portal_t	*p;
+	plane_t		backplane;
+	leaf_t 		*leaf;
+	int			i, j;
+	long		*test, *might, *vis, more;
+	int			pnum;
+
+	thread->c_chains++;
+
+	leaf = &leafs[leafnum];
+//	CheckStack (leaf, thread);
+
+	prevstack->next = &stack;
+
+	stack.next = NULL;
+	stack.leaf = leaf;
+	stack.portal = NULL;
+
+	might = (long *)stack.mightsee;
+	vis = (long *)thread->base->portalvis;
+	
+// check all portals for flowing into other leafs	
+	for (i=0 ; i<leaf->numportals ; i++)
+	{
+		p = leaf->portals[i];
+		pnum = p - portals;
+
+		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
+		{
+			continue;	// can't possibly see it
+		}
+
+	// if the portal can't see anything we haven't allready seen, skip it
+		if (p->status == stat_done)
+		{
+			test = (long *)p->portalvis;
+		}
+		else
+		{
+			test = (long *)p->portalflood;
+		}
+
+		more = 0;
+		for (j=0 ; j<portallongs ; j++)
+		{
+			might[j] = ((long *)prevstack->mightsee)[j] & test[j];
+			more |= (might[j] & ~vis[j]);
+		}
+		
+		if (!more && 
+			(thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
+		{	// can't see anything new
+			continue;
+		}
+
+		// get plane of portal, point normal into the neighbor leaf
+		stack.portalplane = p->plane;
+		VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
+		backplane.dist = -p->plane.dist;
+		
+//		c_portalcheck++;
+		
+		stack.portal = p;
+		stack.next = NULL;
+		stack.freewindings[0] = 1;
+		stack.freewindings[1] = 1;
+		stack.freewindings[2] = 1;
+		
+#if 1
+{
+float d;
+
+	d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
+	d -= thread->pstack_head.portalplane.dist;
+	if (d < -p->radius)
+	{
+		continue;
+	}
+	else if (d > p->radius)
+	{
+		stack.pass = p->winding;
+	}
+	else	
+	{
+		stack.pass = Vis_ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
+		if (!stack.pass)
+			continue;
+	}
+}
+#else
+		stack.pass = Vis_ChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
+		if (!stack.pass)
+			continue;
+#endif
+
+	
+#if 1
+{
+float d;
+
+	d = DotProduct (thread->base->origin, p->plane.normal);
+	d -= p->plane.dist;
+	if (d > p->radius)
+	{
+		continue;
+	}
+	else if (d < -p->radius)
+	{
+		stack.source = prevstack->source;
+	}
+	else	
+	{
+		stack.source = Vis_ChopWinding (prevstack->source, &stack, &backplane);
+		if (!stack.source)
+			continue;
+	}
+}
+#else
+		stack.source = Vis_ChopWinding (prevstack->source, &stack, &backplane);
+		if (!stack.source)
+			continue;
+#endif
+
+		if (!prevstack->pass)
+		{	// the second leaf can only be blocked if coplanar
+
+			// mark the portal as visible
+			thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
+
+			RecursiveLeafFlow (p->leaf, thread, &stack);
+			continue;
+		}
+
+		stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, false, &stack);
+		if (!stack.pass)
+			continue;
+		
+		stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, true, &stack);
+		if (!stack.pass)
+			continue;
+
+		// mark the portal as visible
+		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
+
+		// flow through it for real
+		RecursiveLeafFlow (p->leaf, thread, &stack);
+	}	
+}
+
+
+/*
+===============
+PortalFlow
+
+generates the portalvis bit vector
+===============
+*/
+void PortalFlow (int portalnum)
+{
+	threaddata_t	data;
+	int				i;
+	portal_t		*p;
+	int				c_might, c_can;
+
+	p = sorted_portals[portalnum];
+	p->status = stat_working;
+
+	c_might = CountBits (p->portalflood, numportals*2);
+
+	memset (&data, 0, sizeof(data));
+	data.base = p;
+	
+	data.pstack_head.portal = p;
+	data.pstack_head.source = p->winding;
+	data.pstack_head.portalplane = p->plane;
+	for (i=0 ; i<portallongs ; i++)
+		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
+	RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
+
+	p->status = stat_done;
+
+	c_can = CountBits (p->portalvis, numportals*2);
+
+	Sys_FPrintf ( SYS_VRB, "portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
+		(int)(p - portals),	c_might, c_can, data.c_chains);
+}
+
+
+/*
+===============================================================================
+
+This is a rough first-order aproximation that is used to trivially reject some
+of the final calculations.
+
+
+Calculates portalfront and portalflood bit vectors
+
+thinking about:
+
+typedef struct passage_s
+{
+	struct passage_s	*next;
+	struct portal_s		*to;
+	stryct sep_s		*seperators;
+	byte				*mightsee;
+} passage_t;
+
+typedef struct portal_s
+{
+	struct passage_s	*passages;
+	int					leaf;		// leaf portal faces into
+} portal_s;
+
+leaf = portal->leaf
+clear 
+for all portals
+
+
+calc portal visibility
+	clear bit vector
+	for all passages
+		passage visibility
+
+
+for a portal to be visible to a passage, it must be on the front of
+all seperating planes, and both portals must be behind the mew portal
+
+===============================================================================
+*/
+
+int		c_flood, c_vis;
+
+
+/*
+==================
+SimpleFlood
+
+==================
+*/
+void SimpleFlood (portal_t *srcportal, int leafnum)
+{
+	int		i;
+	leaf_t	*leaf;
+	portal_t	*p;
+	int		pnum;
+
+	leaf = &leafs[leafnum];
+	
+	for (i=0 ; i<leaf->numportals ; i++)
+	{
+		p = leaf->portals[i];
+		pnum = p - portals;
+		if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) )
+			continue;
+
+		if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) )
+			continue;
+
+		srcportal->portalflood[pnum>>3] |= (1<<(pnum&7));
+		
+		SimpleFlood (srcportal, p->leaf);
+	}
+}
+
+/*
+==============
+BasePortalVis
+==============
+*/
+void BasePortalVis (int portalnum)
+{
+	int			j, k;
+	portal_t	*tp, *p;
+	float		d;
+	winding_t	*w;
+
+	p = portals+portalnum;
+
+	p->portalfront = malloc (portalbytes);
+	memset (p->portalfront, 0, portalbytes);
+
+	p->portalflood = malloc (portalbytes);
+	memset (p->portalflood, 0, portalbytes);
+	
+	p->portalvis = malloc (portalbytes);
+	memset (p->portalvis, 0, portalbytes);
+	
+	for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
+	{
+		if (j == portalnum)
+			continue;
+		w = tp->winding;
+		for (k=0 ; k<w->numpoints ; k++)
+		{
+			d = DotProduct (w->points[k], p->plane.normal)
+				- p->plane.dist;
+			if (d > ON_EPSILON)
+				break;
+		}
+		if (k == w->numpoints)
+			continue;	// no points on front
+
+		w = p->winding;
+		for (k=0 ; k<w->numpoints ; k++)
+		{
+			d = DotProduct (w->points[k], tp->plane.normal)
+				- tp->plane.dist;
+			if (d < -ON_EPSILON)
+				break;
+		}
+		if (k == w->numpoints)
+			continue;	// no points on front
+
+		p->portalfront[j>>3] |= (1<<(j&7));
+	}
+	
+	SimpleFlood (p, p->leaf);
+
+	p->nummightsee = CountBits (p->portalflood, numportals*2);
+//	printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
+	c_flood += p->nummightsee;
+}
+
+
+
+
+
+/*
+===============================================================================
+
+This is a second order aproximation 
+
+Calculates portalvis bit vector
+
+WAAAAAAY too slow.
+
+===============================================================================
+*/
+
+/*
+==================
+RecursiveLeafBitFlow
+
+==================
+*/
+void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
+{
+	portal_t	*p;
+	leaf_t 		*leaf;
+	int			i, j;
+	long		more;
+	int			pnum;
+	byte		newmight[MAX_PORTALS/8];
+
+	leaf = &leafs[leafnum];
+	
+// check all portals for flowing into other leafs	
+	for (i=0 ; i<leaf->numportals ; i++)
+	{
+		p = leaf->portals[i];
+		pnum = p - portals;
+
+		// if some previous portal can't see it, skip
+		if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) )
+			continue;
+
+		// if this portal can see some portals we mightsee, recurse
+		more = 0;
+		for (j=0 ; j<portallongs ; j++)
+		{
+			((long *)newmight)[j] = ((long *)mightsee)[j] 
+				& ((long *)p->portalflood)[j];
+			more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
+		}
+
+		if (!more)
+			continue;	// can't see anything new
+
+		cansee[pnum>>3] |= (1<<(pnum&7));
+
+		RecursiveLeafBitFlow (p->leaf, newmight, cansee);
+	}	
+}
+
+/*
+==============
+BetterPortalVis
+==============
+*/
+void BetterPortalVis (int portalnum)
+{
+	portal_t	*p;
+
+	p = portals+portalnum;
+
+	RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
+
+	// build leaf vis information
+	p->nummightsee = CountBits (p->portalvis, numportals*2);
+	c_vis += p->nummightsee;
+}
+
+
diff --git a/tools/quake2/q2map/gldraw.c b/tools/quake2/q2map/gldraw.c
index d3f78f53..d36355f8 100644
--- a/tools/quake2/q2map/gldraw.c
+++ b/tools/quake2/q2map/gldraw.c
@@ -1,231 +1,231 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <windows.h>
-#include <GL/gl.h>
-#include <GL/glu.h>
-#include <GL/glaux.h>
-
-#include "qbsp.h"
-
-// can't use the glvertex3fv functions, because the vec3_t fields
-// could be either floats or doubles, depending on DOUBLEVEC_T
-
-qboolean	drawflag;
-vec3_t	draw_mins, draw_maxs;
-
-
-#define	WIN_SIZE	512
-
-void InitWindow (void)
-{
-    auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
-    auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE);
-    auxInitWindow ("qcsg");
-}
-
-void Draw_ClearWindow (void)
-{
-	static int	init;
-	int		w, h, g;
-	vec_t	mx, my;
-
-	if (!drawflag)
-		return;
-
-	if (!init)
-	{
-		init = true;
-		InitWindow ();
-	}
-
-	glClearColor (1,0.8,0.8,0);
-	glClear (GL_COLOR_BUFFER_BIT);
-
-	w = (draw_maxs[0] - draw_mins[0]);
-	h = (draw_maxs[1] - draw_mins[1]);
-
-	mx = draw_mins[0] + w/2;
-	my = draw_mins[1] + h/2;
-
-	g = w > h ? w : h;
-
-	glLoadIdentity ();
-    gluPerspective (90,  1,  2,  16384);
-	gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0);
-
-	glColor3f (0,0,0);
-//	glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
-	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
-	glDisable (GL_DEPTH_TEST);
-	glEnable (GL_BLEND);
-	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-#if 0
-	glColor4f (1,0,0,0.5);
-	glBegin (GL_POLYGON);
-
-	glVertex3f (0, 500, 0);
-	glVertex3f (0, 900, 0);
-	glVertex3f (0, 900, 100);
-	glVertex3f (0, 500, 100);
-
-	glEnd ();
-#endif
-
-	glFlush ();
-
-}
-
-void Draw_SetRed (void)
-{
-	if (!drawflag)
-		return;
-
-	glColor3f (1,0,0);
-}
-
-void Draw_SetGrey (void)
-{
-	if (!drawflag)
-		return;
-
-	glColor3f (0.5,0.5,0.5);
-}
-
-void Draw_SetBlack (void)
-{
-	if (!drawflag)
-		return;
-
-	glColor3f (0,0,0);
-}
-
-void DrawWinding (winding_t *w)
-{
-	int		i;
-
-	if (!drawflag)
-		return;
-
-	glColor4f (0,0,0,0.5);
-	glBegin (GL_LINE_LOOP);
-	for (i=0 ; i<w->numpoints ; i++)
-		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
-	glEnd ();
-
-	glColor4f (0,1,0,0.3);
-	glBegin (GL_POLYGON);
-	for (i=0 ; i<w->numpoints ; i++)
-		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
-	glEnd ();
-
-	glFlush ();
-}
-
-void DrawAuxWinding (winding_t *w)
-{
-	int		i;
-
-	if (!drawflag)
-		return;
-
-	glColor4f (0,0,0,0.5);
-	glBegin (GL_LINE_LOOP);
-	for (i=0 ; i<w->numpoints ; i++)
-		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
-	glEnd ();
-
-	glColor4f (1,0,0,0.3);
-	glBegin (GL_POLYGON);
-	for (i=0 ; i<w->numpoints ; i++)
-		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
-	glEnd ();
-
-	glFlush ();
-}
-
-//============================================================
-
-#define	GLSERV_PORT	25001
-
-qboolean	wins_init;
-int			draw_socket;
-
-void GLS_BeginScene (void)
-{
-	WSADATA	winsockdata;
-	WORD	wVersionRequested; 
-	struct sockaddr_in	address;
-	int		r;
-
-	if (!wins_init)
-	{
-		wins_init = true;
-
-		wVersionRequested = MAKEWORD(1, 1); 
-
-		r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
-
-		if (r)
-			Error ("Winsock initialization failed.");
-
-	}
-
-	// connect a socket to the server
-
-	draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
-	if (draw_socket == -1)
-		Error ("draw_socket failed");
-
-	address.sin_family = AF_INET;
-	address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
-	address.sin_port = GLSERV_PORT;
-	r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address));
-	if (r == -1)
-	{
-		closesocket (draw_socket);
-		draw_socket = 0;
-	}
-}
-
-void GLS_Winding (winding_t *w, int code)
-{
-	byte	buf[1024];
-	int		i, j;
-
-	if (!draw_socket)
-		return;
-
-	((int *)buf)[0] = w->numpoints;
-	((int *)buf)[1] = code;
-	for (i=0 ; i<w->numpoints ; i++)
-		for (j=0 ; j<3 ; j++)
-			((float *)buf)[2+i*3+j] = w->p[i][j];
-
-	send (draw_socket, buf, w->numpoints*12+8, 0);
-}
-
-void GLS_EndScene (void)
-{
-	closesocket (draw_socket);
-	draw_socket = 0;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <windows.h>
+#include <GL/gl.h>
+#include <GL/glu.h>
+#include <GL/glaux.h>
+
+#include "qbsp.h"
+
+// can't use the glvertex3fv functions, because the vec3_t fields
+// could be either floats or doubles, depending on DOUBLEVEC_T
+
+qboolean	drawflag;
+vec3_t	draw_mins, draw_maxs;
+
+
+#define	WIN_SIZE	512
+
+void InitWindow (void)
+{
+    auxInitDisplayMode (AUX_SINGLE | AUX_RGB);
+    auxInitPosition (0, 0, WIN_SIZE, WIN_SIZE);
+    auxInitWindow ("qcsg");
+}
+
+void Draw_ClearWindow (void)
+{
+	static int	init;
+	int		w, h, g;
+	vec_t	mx, my;
+
+	if (!drawflag)
+		return;
+
+	if (!init)
+	{
+		init = true;
+		InitWindow ();
+	}
+
+	glClearColor (1,0.8,0.8,0);
+	glClear (GL_COLOR_BUFFER_BIT);
+
+	w = (draw_maxs[0] - draw_mins[0]);
+	h = (draw_maxs[1] - draw_mins[1]);
+
+	mx = draw_mins[0] + w/2;
+	my = draw_mins[1] + h/2;
+
+	g = w > h ? w : h;
+
+	glLoadIdentity ();
+    gluPerspective (90,  1,  2,  16384);
+	gluLookAt (mx, my, draw_maxs[2] + g/2, mx , my, draw_maxs[2], 0, 1, 0);
+
+	glColor3f (0,0,0);
+//	glPolygonMode (GL_FRONT_AND_BACK, GL_LINE);
+	glPolygonMode (GL_FRONT_AND_BACK, GL_FILL);
+	glDisable (GL_DEPTH_TEST);
+	glEnable (GL_BLEND);
+	glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+
+#if 0
+	glColor4f (1,0,0,0.5);
+	glBegin (GL_POLYGON);
+
+	glVertex3f (0, 500, 0);
+	glVertex3f (0, 900, 0);
+	glVertex3f (0, 900, 100);
+	glVertex3f (0, 500, 100);
+
+	glEnd ();
+#endif
+
+	glFlush ();
+
+}
+
+void Draw_SetRed (void)
+{
+	if (!drawflag)
+		return;
+
+	glColor3f (1,0,0);
+}
+
+void Draw_SetGrey (void)
+{
+	if (!drawflag)
+		return;
+
+	glColor3f (0.5,0.5,0.5);
+}
+
+void Draw_SetBlack (void)
+{
+	if (!drawflag)
+		return;
+
+	glColor3f (0,0,0);
+}
+
+void DrawWinding (winding_t *w)
+{
+	int		i;
+
+	if (!drawflag)
+		return;
+
+	glColor4f (0,0,0,0.5);
+	glBegin (GL_LINE_LOOP);
+	for (i=0 ; i<w->numpoints ; i++)
+		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
+	glEnd ();
+
+	glColor4f (0,1,0,0.3);
+	glBegin (GL_POLYGON);
+	for (i=0 ; i<w->numpoints ; i++)
+		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
+	glEnd ();
+
+	glFlush ();
+}
+
+void DrawAuxWinding (winding_t *w)
+{
+	int		i;
+
+	if (!drawflag)
+		return;
+
+	glColor4f (0,0,0,0.5);
+	glBegin (GL_LINE_LOOP);
+	for (i=0 ; i<w->numpoints ; i++)
+		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
+	glEnd ();
+
+	glColor4f (1,0,0,0.3);
+	glBegin (GL_POLYGON);
+	for (i=0 ; i<w->numpoints ; i++)
+		glVertex3f (w->p[i][0],w->p[i][1],w->p[i][2] );
+	glEnd ();
+
+	glFlush ();
+}
+
+//============================================================
+
+#define	GLSERV_PORT	25001
+
+qboolean	wins_init;
+int			draw_socket;
+
+void GLS_BeginScene (void)
+{
+	WSADATA	winsockdata;
+	WORD	wVersionRequested; 
+	struct sockaddr_in	address;
+	int		r;
+
+	if (!wins_init)
+	{
+		wins_init = true;
+
+		wVersionRequested = MAKEWORD(1, 1); 
+
+		r = WSAStartup (MAKEWORD(1, 1), &winsockdata);
+
+		if (r)
+			Error ("Winsock initialization failed.");
+
+	}
+
+	// connect a socket to the server
+
+	draw_socket = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP);
+	if (draw_socket == -1)
+		Error ("draw_socket failed");
+
+	address.sin_family = AF_INET;
+	address.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+	address.sin_port = GLSERV_PORT;
+	r = connect (draw_socket, (struct sockaddr *)&address, sizeof(address));
+	if (r == -1)
+	{
+		closesocket (draw_socket);
+		draw_socket = 0;
+	}
+}
+
+void GLS_Winding (winding_t *w, int code)
+{
+	byte	buf[1024];
+	int		i, j;
+
+	if (!draw_socket)
+		return;
+
+	((int *)buf)[0] = w->numpoints;
+	((int *)buf)[1] = code;
+	for (i=0 ; i<w->numpoints ; i++)
+		for (j=0 ; j<3 ; j++)
+			((float *)buf)[2+i*3+j] = w->p[i][j];
+
+	send (draw_socket, buf, w->numpoints*12+8, 0);
+}
+
+void GLS_EndScene (void)
+{
+	closesocket (draw_socket);
+	draw_socket = 0;
+}
diff --git a/tools/quake2/q2map/glfile.c b/tools/quake2/q2map/glfile.c
index a5c0e30b..b08053bd 100644
--- a/tools/quake2/q2map/glfile.c
+++ b/tools/quake2/q2map/glfile.c
@@ -1,148 +1,148 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-int		c_glfaces;
-
-int PortalVisibleSides (portal_t *p)
-{
-	int		fcon, bcon;
-
-	if (!p->onnode)
-		return 0;		// outside
-
-	fcon = p->nodes[0]->contents;
-	bcon = p->nodes[1]->contents;
-
-	// same contents never create a face
-	if (fcon == bcon)
-		return 0;
-
-	// FIXME: is this correct now?
-	if (!fcon)
-		return 1;
-	if (!bcon)
-		return 2;
-	return 0;
-}
-
-void OutputWinding (winding_t *w, FILE *glview)
-{
-	static	int	level = 128;
-	vec_t		light;
-	int			i;
-
-	fprintf (glview, "%i\n", w->numpoints);
-	level+=28;
-	light = (level&255)/255.0;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		fprintf (glview, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n",
-			w->p[i][0],
-			w->p[i][1],
-			w->p[i][2],
-			light,
-			light,
-			light);
-	}
-	fprintf (glview, "\n");
-}
-
-/*
-=============
-OutputPortal
-=============
-*/
-void OutputPortal (portal_t *p, FILE *glview)
-{
-	winding_t	*w;
-	int		sides;
-
-	sides = PortalVisibleSides (p);
-	if (!sides)
-		return;
-
-	c_glfaces++;
-
-	w = p->winding;
-
-	if (sides == 2)		// back side
-		w = ReverseWinding (w);
-
-	OutputWinding (w, glview);
-
-	if (sides == 2)
-		FreeWinding(w);
-}
-
-/*
-=============
-WriteGLView_r
-=============
-*/
-void WriteGLView_r (node_t *node, FILE *glview)
-{
-	portal_t	*p, *nextp;
-
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		WriteGLView_r (node->children[0], glview);
-		WriteGLView_r (node->children[1], glview);
-		return;
-	}
-
-	// write all the portals
-	for (p=node->portals ; p ; p=nextp)
-	{
-		if (p->nodes[0] == node)
-		{
-			OutputPortal (p, glview);
-			nextp = p->next[0];
-		}
-		else
-			nextp = p->next[1];
-	}
-}
-
-/*
-=============
-WriteGLView
-=============
-*/
-void WriteGLView (tree_t *tree, char *source)
-{
-	char	name[1024];
-	FILE	*glview;
-
-	c_glfaces = 0;
-	sprintf (name, "%s%s.gl",outbase, source);
-	Sys_Printf ("Writing %s\n", name);
-
-	glview = fopen (name, "w");
-	if (!glview)
-		Error ("Couldn't open %s", name);
-	WriteGLView_r (tree->headnode, glview);
-	fclose (glview);
-
-	Sys_Printf ("%5i c_glfaces\n", c_glfaces);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+int		c_glfaces;
+
+int PortalVisibleSides (portal_t *p)
+{
+	int		fcon, bcon;
+
+	if (!p->onnode)
+		return 0;		// outside
+
+	fcon = p->nodes[0]->contents;
+	bcon = p->nodes[1]->contents;
+
+	// same contents never create a face
+	if (fcon == bcon)
+		return 0;
+
+	// FIXME: is this correct now?
+	if (!fcon)
+		return 1;
+	if (!bcon)
+		return 2;
+	return 0;
+}
+
+void OutputWinding (winding_t *w, FILE *glview)
+{
+	static	int	level = 128;
+	vec_t		light;
+	int			i;
+
+	fprintf (glview, "%i\n", w->numpoints);
+	level+=28;
+	light = (level&255)/255.0;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		fprintf (glview, "%6.3f %6.3f %6.3f %6.3f %6.3f %6.3f\n",
+			w->p[i][0],
+			w->p[i][1],
+			w->p[i][2],
+			light,
+			light,
+			light);
+	}
+	fprintf (glview, "\n");
+}
+
+/*
+=============
+OutputPortal
+=============
+*/
+void OutputPortal (portal_t *p, FILE *glview)
+{
+	winding_t	*w;
+	int		sides;
+
+	sides = PortalVisibleSides (p);
+	if (!sides)
+		return;
+
+	c_glfaces++;
+
+	w = p->winding;
+
+	if (sides == 2)		// back side
+		w = ReverseWinding (w);
+
+	OutputWinding (w, glview);
+
+	if (sides == 2)
+		FreeWinding(w);
+}
+
+/*
+=============
+WriteGLView_r
+=============
+*/
+void WriteGLView_r (node_t *node, FILE *glview)
+{
+	portal_t	*p, *nextp;
+
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		WriteGLView_r (node->children[0], glview);
+		WriteGLView_r (node->children[1], glview);
+		return;
+	}
+
+	// write all the portals
+	for (p=node->portals ; p ; p=nextp)
+	{
+		if (p->nodes[0] == node)
+		{
+			OutputPortal (p, glview);
+			nextp = p->next[0];
+		}
+		else
+			nextp = p->next[1];
+	}
+}
+
+/*
+=============
+WriteGLView
+=============
+*/
+void WriteGLView (tree_t *tree, char *source)
+{
+	char	name[1024];
+	FILE	*glview;
+
+	c_glfaces = 0;
+	sprintf (name, "%s%s.gl",outbase, source);
+	Sys_Printf ("Writing %s\n", name);
+
+	glview = fopen (name, "w");
+	if (!glview)
+		Error ("Couldn't open %s", name);
+	WriteGLView_r (tree->headnode, glview);
+	fclose (glview);
+
+	Sys_Printf ("%5i c_glfaces\n", c_glfaces);
+}
+
diff --git a/tools/quake2/q2map/leakfile.c b/tools/quake2/q2map/leakfile.c
index 32d57b9c..6c814b20 100644
--- a/tools/quake2/q2map/leakfile.c
+++ b/tools/quake2/q2map/leakfile.c
@@ -1,180 +1,180 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-/*
-==============================================================================
-
-LEAF FILE GENERATION
-
-Save out name.line for qe3 to read
-==============================================================================
-*/
-
-
-/*
-=============
-LeakFile
-
-Finds the shortest possible chain of portals
-that leads from the outside leaf to a specifically
-occupied leaf
-=============
-*/
-
-/*
-void LeakFile (tree_t *tree)
-{
-	vec3_t	mid;
-	FILE	*linefile;
-	char	filename[1024];
-	node_t	*node;
-	int		count;
-
-	if (!tree->outside_node.occupied)
-		return;
-
-	Sys_Printf ("--- LeakFile ---\n");
-
-	//
-	// write the points to the file
-	//
-	sprintf (filename, "%s.lin", source);
-	linefile = fopen (filename, "w");
-	if (!linefile)
-		Error ("Couldn't open %s\n", filename);
-
-	count = 0;
-	node = &tree->outside_node;
-	while (node->occupied > 1)
-	{
-		int			next;
-		portal_t	*p, *nextportal;
-		node_t		*nextnode;
-		int			s;
-
-		// find the best portal exit
-		next = node->occupied;
-		for (p=node->portals ; p ; p = p->next[!s])
-		{
-			s = (p->nodes[0] == node);
-			if (p->nodes[s]->occupied
-				&& p->nodes[s]->occupied < next)
-			{
-				nextportal = p;
-				nextnode = p->nodes[s];
-				next = nextnode->occupied;
-			}
-		}
-		node = nextnode;
-		WindingCenter (nextportal->winding, mid);
-		fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
-		count++;
-	}
-	// add the occupant center
-	GetVectorForKey (node->occupant, "origin", mid);
-
-	fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
-	Sys_Printf ("%5i point linefile\n", count+1);
-
-	fclose (linefile);
-}
-*/
-
-/*
-=============
-LeakFile
-
-Finds the shortest possible chain of portals
-that leads from the outside leaf to a specifically
-occupied leaf
-
-TTimo: builds a polyline xml node
-=============
-*/
-xmlNodePtr LeakFile (tree_t *tree)
-{
-	vec3_t	mid;
-	FILE	*linefile;
-	char	filename[1024];
-	node_t	*node;
-	int		count;
-	xmlNodePtr xml_node, point;
-
-	if (!tree->outside_node.occupied)
-		return NULL;
-
-	Sys_FPrintf (SYS_VRB,"--- LeakFile ---\n");
-
-	//
-	// write the points to the file
-	//
-	sprintf (filename, "%s.lin", source);
-	linefile = fopen (filename, "w");
-	if (!linefile)
-		Error ("Couldn't open %s\n", filename);
-
-	xml_node = xmlNewNode (NULL, "polyline");
-
-	count = 0;
-	node = &tree->outside_node;
-	while (node->occupied > 1)
-	{
-		int			next;
-		portal_t	*p, *nextportal;
-		node_t		*nextnode;
-		int			s;
-
-		// find the best portal exit
-		next = node->occupied;
-		for (p=node->portals ; p ; p = p->next[!s])
-		{
-			s = (p->nodes[0] == node);
-			if (p->nodes[s]->occupied
-				&& p->nodes[s]->occupied < next)
-			{
-				nextportal = p;
-				nextnode = p->nodes[s];
-				next = nextnode->occupied;
-			}
-		}
-		node = nextnode;
-		WindingCenter (nextportal->winding, mid);
-		fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
-		point = xml_NodeForVec(mid);
-		xmlAddChild(xml_node, point);
-		count++;
-	}
-	// add the occupant center
-	GetVectorForKey (node->occupant, "origin", mid);
-
-	fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
-	point = xml_NodeForVec(mid);
-	xmlAddChild(xml_node, point);
-	Sys_FPrintf( SYS_VRB, "%9d point linefile\n", count+1);
-
-	fclose (linefile);
-	
-	return xml_node;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+/*
+==============================================================================
+
+LEAF FILE GENERATION
+
+Save out name.line for qe3 to read
+==============================================================================
+*/
+
+
+/*
+=============
+LeakFile
+
+Finds the shortest possible chain of portals
+that leads from the outside leaf to a specifically
+occupied leaf
+=============
+*/
+
+/*
+void LeakFile (tree_t *tree)
+{
+	vec3_t	mid;
+	FILE	*linefile;
+	char	filename[1024];
+	node_t	*node;
+	int		count;
+
+	if (!tree->outside_node.occupied)
+		return;
+
+	Sys_Printf ("--- LeakFile ---\n");
+
+	//
+	// write the points to the file
+	//
+	sprintf (filename, "%s.lin", source);
+	linefile = fopen (filename, "w");
+	if (!linefile)
+		Error ("Couldn't open %s\n", filename);
+
+	count = 0;
+	node = &tree->outside_node;
+	while (node->occupied > 1)
+	{
+		int			next;
+		portal_t	*p, *nextportal;
+		node_t		*nextnode;
+		int			s;
+
+		// find the best portal exit
+		next = node->occupied;
+		for (p=node->portals ; p ; p = p->next[!s])
+		{
+			s = (p->nodes[0] == node);
+			if (p->nodes[s]->occupied
+				&& p->nodes[s]->occupied < next)
+			{
+				nextportal = p;
+				nextnode = p->nodes[s];
+				next = nextnode->occupied;
+			}
+		}
+		node = nextnode;
+		WindingCenter (nextportal->winding, mid);
+		fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
+		count++;
+	}
+	// add the occupant center
+	GetVectorForKey (node->occupant, "origin", mid);
+
+	fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
+	Sys_Printf ("%5i point linefile\n", count+1);
+
+	fclose (linefile);
+}
+*/
+
+/*
+=============
+LeakFile
+
+Finds the shortest possible chain of portals
+that leads from the outside leaf to a specifically
+occupied leaf
+
+TTimo: builds a polyline xml node
+=============
+*/
+xmlNodePtr LeakFile (tree_t *tree)
+{
+	vec3_t	mid;
+	FILE	*linefile;
+	char	filename[1024];
+	node_t	*node;
+	int		count;
+	xmlNodePtr xml_node, point;
+
+	if (!tree->outside_node.occupied)
+		return NULL;
+
+	Sys_FPrintf (SYS_VRB,"--- LeakFile ---\n");
+
+	//
+	// write the points to the file
+	//
+	sprintf (filename, "%s.lin", source);
+	linefile = fopen (filename, "w");
+	if (!linefile)
+		Error ("Couldn't open %s\n", filename);
+
+	xml_node = xmlNewNode (NULL, "polyline");
+
+	count = 0;
+	node = &tree->outside_node;
+	while (node->occupied > 1)
+	{
+		int			next;
+		portal_t	*p, *nextportal;
+		node_t		*nextnode;
+		int			s;
+
+		// find the best portal exit
+		next = node->occupied;
+		for (p=node->portals ; p ; p = p->next[!s])
+		{
+			s = (p->nodes[0] == node);
+			if (p->nodes[s]->occupied
+				&& p->nodes[s]->occupied < next)
+			{
+				nextportal = p;
+				nextnode = p->nodes[s];
+				next = nextnode->occupied;
+			}
+		}
+		node = nextnode;
+		WindingCenter (nextportal->winding, mid);
+		fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
+		point = xml_NodeForVec(mid);
+		xmlAddChild(xml_node, point);
+		count++;
+	}
+	// add the occupant center
+	GetVectorForKey (node->occupant, "origin", mid);
+
+	fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
+	point = xml_NodeForVec(mid);
+	xmlAddChild(xml_node, point);
+	Sys_FPrintf( SYS_VRB, "%9d point linefile\n", count+1);
+
+	fclose (linefile);
+	
+	return xml_node;
+}
+
+
diff --git a/tools/quake2/q2map/lightmap.c b/tools/quake2/q2map/lightmap.c
index 62a61ebd..cc5da84d 100644
--- a/tools/quake2/q2map/lightmap.c
+++ b/tools/quake2/q2map/lightmap.c
@@ -1,1315 +1,1315 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "qrad.h"
-
-#define	MAX_LSTYLES	256
-
-typedef struct
-{
-	dface_t		*faces[2];
-	qboolean	coplanar;
-} edgeshare_t;
-
-edgeshare_t	edgeshare[MAX_MAP_EDGES];
-
-int			facelinks[MAX_MAP_FACES];
-int			planelinks[2][MAX_MAP_PLANES];
-
-/*
-============
-LinkPlaneFaces
-============
-*/
-void LinkPlaneFaces (void)
-{
-	int		i;
-	dface_t	*f;
-
-	f = dfaces;
-	for (i=0 ; i<numfaces ; i++, f++)
-	{
-		facelinks[i] = planelinks[f->side][f->planenum];
-		planelinks[f->side][f->planenum] = i;
-	}
-}
-
-/*
-============
-PairEdges
-============
-*/
-void PairEdges (void)
-{
-	int		i, j, k;
-	dface_t	*f;
-	edgeshare_t	*e;
-
-	f = dfaces;
-	for (i=0 ; i<numfaces ; i++, f++)
-	{
-		for (j=0 ; j<f->numedges ; j++)
-		{
-			k = dsurfedges[f->firstedge + j];
-			if (k < 0)
-			{
-				e = &edgeshare[-k];
-				e->faces[1] = f;
-			}
-			else
-			{
-				e = &edgeshare[k];
-				e->faces[0] = f;
-			}
-
-			if (e->faces[0] && e->faces[1])
-			{
-				// determine if coplanar
-				if (e->faces[0]->planenum == e->faces[1]->planenum)
-					e->coplanar = true;
-			}
-		}
-	}
-}
-
-/*
-=================================================================
-
-  POINT TRIANGULATION
-
-=================================================================
-*/
-
-typedef struct triedge_s
-{
-	int			p0, p1;
-	vec3_t		normal;
-	vec_t		dist;
-	struct triangle_s	*tri;
-} triedge_t;
-
-typedef struct triangle_s
-{
-	triedge_t	*edges[3];
-} triangle_t;
-
-#define	MAX_TRI_POINTS		1024
-#define	MAX_TRI_EDGES		(MAX_TRI_POINTS*6)
-#define	MAX_TRI_TRIS		(MAX_TRI_POINTS*2)
-
-typedef struct
-{
-	int			numpoints;
-	int			numedges;
-	int			numtris;
-	dplane_t	*plane;
-	triedge_t	*edgematrix[MAX_TRI_POINTS][MAX_TRI_POINTS];
-	patch_t		*points[MAX_TRI_POINTS];
-	triedge_t	edges[MAX_TRI_EDGES];
-	triangle_t	tris[MAX_TRI_TRIS];
-} triangulation_t;
-
-/*
-===============
-AllocTriangulation
-===============
-*/
-triangulation_t	*AllocTriangulation (dplane_t *plane)
-{
-	triangulation_t	*t;
-
-	t = malloc(sizeof(triangulation_t));
-	t->numpoints = 0;
-	t->numedges = 0;
-	t->numtris = 0;
-
-	t->plane = plane;
-
-//	memset (t->edgematrix, 0, sizeof(t->edgematrix));
-
-	return t;
-}
-
-/*
-===============
-FreeTriangulation
-===============
-*/
-void FreeTriangulation (triangulation_t *tr)
-{
-	free (tr);
-}
-
-
-triedge_t	*FindEdge (triangulation_t *trian, int p0, int p1)
-{
-	triedge_t	*e, *be;
-	vec3_t		v1;
-	vec3_t		normal;
-	vec_t		dist;
-
-	if (trian->edgematrix[p0][p1])
-		return trian->edgematrix[p0][p1];
-
-	if (trian->numedges > MAX_TRI_EDGES-2)
-		Error ("trian->numedges > MAX_TRI_EDGES-2");
-
-	VectorSubtract (trian->points[p1]->origin, trian->points[p0]->origin, v1);
-	VectorNormalize (v1, v1);
-	CrossProduct (v1, trian->plane->normal, normal);
-	dist = DotProduct (trian->points[p0]->origin, normal);
-
-	e = &trian->edges[trian->numedges];
-	e->p0 = p0;
-	e->p1 = p1;
-	e->tri = NULL;
-	VectorCopy (normal, e->normal);
-	e->dist = dist;
-	trian->numedges++;
-	trian->edgematrix[p0][p1] = e;
-
-	be = &trian->edges[trian->numedges];
-	be->p0 = p1;
-	be->p1 = p0;
-	be->tri = NULL;
-	VectorSubtract (vec3_origin, normal, be->normal);
-	be->dist = -dist;
-	trian->numedges++;
-	trian->edgematrix[p1][p0] = be;
-
-	return e;
-}
-
-triangle_t	*AllocTriangle (triangulation_t *trian)
-{
-	triangle_t	*t;
-
-	if (trian->numtris >= MAX_TRI_TRIS)
-		Error ("trian->numtris >= MAX_TRI_TRIS");
-
-	t = &trian->tris[trian->numtris];
-	trian->numtris++;
-
-	return t;
-}
-
-/*
-============
-TriEdge_r
-============
-*/
-void TriEdge_r (triangulation_t *trian, triedge_t *e)
-{
-	int		i, bestp;
-	vec3_t	v1, v2;
-	vec_t	*p0, *p1, *p;
-	vec_t	best, ang;
-	triangle_t	*nt;
-
-	if (e->tri)
-		return;		// allready connected by someone
-
-	// find the point with the best angle
-	p0 = trian->points[e->p0]->origin;
-	p1 = trian->points[e->p1]->origin;
-	best = 1.1;
-	for (i=0 ; i< trian->numpoints ; i++)
-	{
-		p = trian->points[i]->origin;
-		// a 0 dist will form a degenerate triangle
-		if (DotProduct(p, e->normal) - e->dist < 0)
-			continue;	// behind edge
-		VectorSubtract (p0, p, v1);
-		VectorSubtract (p1, p, v2);
-		if (!VectorNormalize (v1,v1))
-			continue;
-		if (!VectorNormalize (v2,v2))
-			continue;
-		ang = DotProduct (v1, v2);
-		if (ang < best)
-		{
-			best = ang;
-			bestp = i;
-		}
-	}
-	if (best >= 1)
-		return;		// edge doesn't match anything
-
-	// make a new triangle
-	nt = AllocTriangle (trian);
-	nt->edges[0] = e;
-	nt->edges[1] = FindEdge (trian, e->p1, bestp);
-	nt->edges[2] = FindEdge (trian, bestp, e->p0);
-	for (i=0 ; i<3 ; i++)
-		nt->edges[i]->tri = nt;
-	TriEdge_r (trian, FindEdge (trian, bestp, e->p1));
-	TriEdge_r (trian, FindEdge (trian, e->p0, bestp));
-}
-
-/*
-============
-TriangulatePoints
-============
-*/
-void TriangulatePoints (triangulation_t *trian)
-{
-	vec_t	d, bestd;
-	vec3_t	v1;
-	int		bp1, bp2, i, j;
-	vec_t	*p1, *p2;
-	triedge_t	*e, *e2;
-
-	if (trian->numpoints < 2)
-		return;
-
-	// find the two closest points
-	bestd = 9999;
-	for (i=0 ; i<trian->numpoints ; i++)
-	{
-		p1 = trian->points[i]->origin;
-		for (j=i+1 ; j<trian->numpoints ; j++)
-		{
-			p2 = trian->points[j]->origin;
-			VectorSubtract (p2, p1, v1);
-			d = VectorLength (v1);
-			if (d < bestd)
-			{
-				bestd = d;
-				bp1 = i;
-				bp2 = j;
-			}
-		}
-	}
-
-	e = FindEdge (trian, bp1, bp2);
-	e2 = FindEdge (trian, bp2, bp1);
-	TriEdge_r (trian, e);
-	TriEdge_r (trian, e2);
-}
-
-/*
-===============
-AddPointToTriangulation
-===============
-*/
-void AddPointToTriangulation (patch_t *patch, triangulation_t *trian)
-{
-	int			pnum;
-
-	pnum = trian->numpoints;
-	if (pnum == MAX_TRI_POINTS)
-		Error ("trian->numpoints == MAX_TRI_POINTS");
-	trian->points[pnum] = patch;
-	trian->numpoints++;
-}
-
-/*
-===============
-LerpTriangle
-===============
-*/
-void	LerpTriangle (triangulation_t *trian, triangle_t *t, vec3_t point, vec3_t color)
-{
-	patch_t		*p1, *p2, *p3;
-	vec3_t		base, d1, d2;
-	float		x, y, x1, y1, x2, y2;
-
-	p1 = trian->points[t->edges[0]->p0];
-	p2 = trian->points[t->edges[1]->p0];
-	p3 = trian->points[t->edges[2]->p0];
-
-	VectorCopy (p1->totallight, base);
-	VectorSubtract (p2->totallight, base, d1);
-	VectorSubtract (p3->totallight, base, d2);
-
-	x = DotProduct (point, t->edges[0]->normal) - t->edges[0]->dist;
-	y = DotProduct (point, t->edges[2]->normal) - t->edges[2]->dist;
-
-	x1 = 0;
-	y1 = DotProduct (p2->origin, t->edges[2]->normal) - t->edges[2]->dist;
-
-	x2 = DotProduct (p3->origin, t->edges[0]->normal) - t->edges[0]->dist;
-	y2 = 0;
-
-	if (fabs(y1)<ON_EPSILON || fabs(x2)<ON_EPSILON)
-	{
-		VectorCopy (base, color);
-		return;
-	}
-
-	VectorMA (base, x/x2, d2, color);
-	VectorMA (color, y/y1, d1, color);
-}
-
-qboolean PointInTriangle (vec3_t point, triangle_t *t)
-{
-	int		i;
-	triedge_t	*e;
-	vec_t	d;
-
-	for (i=0 ; i<3 ; i++)
-	{
-		e = t->edges[i];
-		d = DotProduct (e->normal, point) - e->dist;
-		if (d < 0)
-			return false;	// not inside
-	}
-
-	return true;
-}
-
-/*
-===============
-SampleTriangulation
-===============
-*/
-void SampleTriangulation (vec3_t point, triangulation_t *trian, vec3_t color)
-{
-	triangle_t	*t;
-	triedge_t	*e;
-	vec_t		d, best;
-	patch_t		*p0, *p1;
-	vec3_t		v1, v2;
-	int			i, j;
-
-	if (trian->numpoints == 0)
-	{
-		VectorClear (color);
-		return;
-	}
-	if (trian->numpoints == 1)
-	{
-		VectorCopy (trian->points[0]->totallight, color);
-		return;
-	}
-
-	// search for triangles
-	for (t = trian->tris, j=0 ; j < trian->numtris ; t++, j++)
-	{
-		if (!PointInTriangle (point, t))
-			continue;
-
-		// this is it
-		LerpTriangle (trian, t, point, color);
-		return;
-	}
-	
-	// search for exterior edge
-	for (e=trian->edges, j=0 ; j< trian->numedges ; e++, j++)
-	{
-		if (e->tri)
-			continue;		// not an exterior edge
-
-		d = DotProduct (point, e->normal) - e->dist;
-		if (d < 0)
-			continue;	// not in front of edge
-
-		p0 = trian->points[e->p0];
-		p1 = trian->points[e->p1];
-	
-		VectorSubtract (p1->origin, p0->origin, v1);
-		VectorNormalize (v1, v1);
-		VectorSubtract (point, p0->origin, v2);
-		d = DotProduct (v2, v1);
-		if (d < 0)
-			continue;
-		if (d > 1)
-			continue;
-		for (i=0 ; i<3 ; i++)
-			color[i] = p0->totallight[i] + d * (p1->totallight[i] - p0->totallight[i]);
-		return;
-	}
-
-	// search for nearest point
-	best = 99999;
-	p1 = NULL;
-	for (j=0 ; j<trian->numpoints ; j++)
-	{
-		p0 = trian->points[j];
-		VectorSubtract (point, p0->origin, v1);
-		d = VectorLength (v1);
-		if (d < best)
-		{
-			best = d;
-			p1 = p0;
-		}
-	}
-
-	if (!p1)
-		Error ("SampleTriangulation: no points");
-
-	VectorCopy (p1->totallight, color);
-}
-
-/*
-=================================================================
-
-  LIGHTMAP SAMPLE GENERATION
-
-=================================================================
-*/
-
-
-#define	SINGLEMAP	(64*64*4)
-
-typedef struct
-{
-	vec_t	facedist;
-	vec3_t	facenormal;
-
-	int		numsurfpt;
-	vec3_t	surfpt[SINGLEMAP];
-
-	vec3_t	modelorg;		// for origined bmodels
-
-	vec3_t	texorg;
-	vec3_t	worldtotex[2];	// s = (world - texorg) . worldtotex[0]
-	vec3_t	textoworld[2];	// world = texorg + s * textoworld[0]
-
-	vec_t	exactmins[2], exactmaxs[2];
-	
-	int		texmins[2], texsize[2];
-	int		surfnum;
-	dface_t	*face;
-} lightinfo_t;
-
-
-/*
-================
-CalcFaceExtents
-
-Fills in s->texmins[] and s->texsize[]
-also sets exactmins[] and exactmaxs[]
-================
-*/
-void CalcFaceExtents (lightinfo_t *l)
-{
-	dface_t *s;
-	vec_t	mins[2], maxs[2], val;
-	int		i,j, e;
-	dvertex_t	*v;
-	texinfo_t	*tex;
-	vec3_t		vt;
-
-	s = l->face;
-
-	mins[0] = mins[1] = 999999;
-	maxs[0] = maxs[1] = -99999;
-
-	tex = &texinfo[s->texinfo];
-	
-	for (i=0 ; i<s->numedges ; i++)
-	{
-		e = dsurfedges[s->firstedge+i];
-		if (e >= 0)
-			v = dvertexes + dedges[e].v[0];
-		else
-			v = dvertexes + dedges[-e].v[1];
-		
-//		VectorAdd (v->point, l->modelorg, vt);
-		VectorCopy (v->point, vt);
-
-		for (j=0 ; j<2 ; j++)
-		{
-			val = DotProduct (vt, tex->vecs[j]) + tex->vecs[j][3];
-			if (val < mins[j])
-				mins[j] = val;
-			if (val > maxs[j])
-				maxs[j] = val;
-		}
-	}
-
-	for (i=0 ; i<2 ; i++)
-	{	
-		l->exactmins[i] = mins[i];
-		l->exactmaxs[i] = maxs[i];
-		
-		mins[i] = floor(mins[i]/16);
-		maxs[i] = ceil(maxs[i]/16);
-
-		l->texmins[i] = mins[i];
-		l->texsize[i] = maxs[i] - mins[i];
-		if (l->texsize[0] * l->texsize[1] > SINGLEMAP/4)	// div 4 for extrasamples
-			Error ("Surface to large to map");
-	}
-}
-
-/*
-================
-CalcFaceVectors
-
-Fills in texorg, worldtotex. and textoworld
-================
-*/
-void CalcFaceVectors (lightinfo_t *l)
-{
-	texinfo_t	*tex;
-	int			i, j;
-	vec3_t	texnormal;
-	vec_t	distscale;
-	vec_t	dist, len;
-	int			w, h;
-
-	tex = &texinfo[l->face->texinfo];
-	
-// convert from float to double
-	for (i=0 ; i<2 ; i++)
-		for (j=0 ; j<3 ; j++)
-			l->worldtotex[i][j] = tex->vecs[i][j];
-
-// calculate a normal to the texture axis.  points can be moved along this
-// without changing their S/T
-	texnormal[0] = tex->vecs[1][1]*tex->vecs[0][2]
-		- tex->vecs[1][2]*tex->vecs[0][1];
-	texnormal[1] = tex->vecs[1][2]*tex->vecs[0][0]
-		- tex->vecs[1][0]*tex->vecs[0][2];
-	texnormal[2] = tex->vecs[1][0]*tex->vecs[0][1]
-		- tex->vecs[1][1]*tex->vecs[0][0];
-	VectorNormalize (texnormal, texnormal);
-
-// flip it towards plane normal
-	distscale = DotProduct (texnormal, l->facenormal);
-	if (!distscale)
-	{
-		Sys_FPrintf( SYS_VRB, "WARNING: Texture axis perpendicular to face\n");
-		distscale = 1;
-	}
-	if (distscale < 0)
-	{
-		distscale = -distscale;
-		VectorSubtract (vec3_origin, texnormal, texnormal);
-	}	
-
-// distscale is the ratio of the distance along the texture normal to
-// the distance along the plane normal
-	distscale = 1/distscale;
-
-	for (i=0 ; i<2 ; i++)
-	{
-		len = VectorLength (l->worldtotex[i]);
-		dist = DotProduct (l->worldtotex[i], l->facenormal);
-		dist *= distscale;
-		VectorMA (l->worldtotex[i], -dist, texnormal, l->textoworld[i]);
-		VectorScale (l->textoworld[i], (1/len)*(1/len), l->textoworld[i]);
-	}
-
-
-// calculate texorg on the texture plane
-	for (i=0 ; i<3 ; i++)
-		l->texorg[i] = -tex->vecs[0][3]* l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i];
-
-// project back to the face plane
-	dist = DotProduct (l->texorg, l->facenormal) - l->facedist - 1;
-	dist *= distscale;
-	VectorMA (l->texorg, -dist, texnormal, l->texorg);
-
-	// compensate for org'd bmodels
-	VectorAdd (l->texorg, l->modelorg, l->texorg);
-
-	// total sample count
-	h = l->texsize[1]+1;
-	w = l->texsize[0]+1;
-	l->numsurfpt = w * h;
-}
-
-/*
-=================
-CalcPoints
-
-For each texture aligned grid point, back project onto the plane
-to get the world xyz value of the sample point
-=================
-*/
-void CalcPoints (lightinfo_t *l, float sofs, float tofs)
-{
-	int		i;
-	int		s, t, j;
-	int		w, h, step;
-	vec_t	starts, startt, us, ut;
-	vec_t	*surf;
-	vec_t	mids, midt;
-	vec3_t	facemid;
-	dleaf_t	*leaf;
-
-	surf = l->surfpt[0];
-	mids = (l->exactmaxs[0] + l->exactmins[0])/2;
-	midt = (l->exactmaxs[1] + l->exactmins[1])/2;
-
-	for (j=0 ; j<3 ; j++)
-		facemid[j] = l->texorg[j] + l->textoworld[0][j]*mids + l->textoworld[1][j]*midt;
-
-	h = l->texsize[1]+1;
-	w = l->texsize[0]+1;
-	l->numsurfpt = w * h;
-
-	starts = l->texmins[0]*16;
-	startt = l->texmins[1]*16;
-	step = 16;
-
-
-	for (t=0 ; t<h ; t++)
-	{
-		for (s=0 ; s<w ; s++, surf+=3)
-		{
-			us = starts + (s+sofs)*step;
-			ut = startt + (t+tofs)*step;
-
-
-		// if a line can be traced from surf to facemid, the point is good
-			for (i=0 ; i<6 ; i++)
-			{
-			// calculate texture point
-				for (j=0 ; j<3 ; j++)
-					surf[j] = l->texorg[j] + l->textoworld[0][j]*us
-					+ l->textoworld[1][j]*ut;
-
-				leaf = Rad_PointInLeaf (surf);
-				if (leaf->contents != CONTENTS_SOLID)
-				{
-					if (!TestLine_r (0, facemid, surf))
-						break;	// got it
-				}
-
-				// nudge it
-				if (i & 1)
-				{
-					if (us > mids)
-					{
-						us -= 8;
-						if (us < mids)
-							us = mids;
-					}
-					else
-					{
-						us += 8;
-						if (us > mids)
-							us = mids;
-					}
-				}
-				else
-				{
-					if (ut > midt)
-					{
-						ut -= 8;
-						if (ut < midt)
-							ut = midt;
-					}
-					else
-					{
-						ut += 8;
-						if (ut > midt)
-							ut = midt;
-					}
-				}
-			}
-		}
-	}
-	
-}
-
-
-//==============================================================
-
-
-
-#define	MAX_STYLES	32
-typedef struct
-{
-	int			numsamples;
-	float		*origins;
-	int			numstyles;
-	int			stylenums[MAX_STYLES];
-	float		*samples[MAX_STYLES];
-} facelight_t;
-
-directlight_t	*directlights[MAX_MAP_LEAFS];
-facelight_t		facelight[MAX_MAP_FACES];
-int				numdlights;
-
-/*
-==================
-FindTargetEntity
-==================
-*/
-entity_t *FindTargetEntity (char *target)
-{
-	int		i;
-	char	*n;
-
-	for (i=0 ; i<num_entities ; i++)
-	{
-		n = ValueForKey (&entities[i], "targetname");
-		if (!strcmp (n, target))
-			return &entities[i];
-	}
-
-	return NULL;
-}
-
-//#define	DIRECT_LIGHT	3000
-#define	DIRECT_LIGHT	3
-
-/*
-=============
-CreateDirectLights
-=============
-*/
-void CreateDirectLights (void)
-{
-	int		i;
-	patch_t	*p;
-	directlight_t	*dl;
-	dleaf_t	*leaf;
-	int		cluster;
-	entity_t	*e, *e2;
-	char	*name;
-	char	*target;
-	float	angle;
-	vec3_t	dest;
-	char	*_color;
-	float	intensity;
-
-	//
-	// surfaces
-	//
-	for (i=0, p=patches ; i< (int) num_patches ; i++, p++)
-	{
-		if (p->totallight[0] < DIRECT_LIGHT
-			&& p->totallight[1] < DIRECT_LIGHT
-			&& p->totallight[2] < DIRECT_LIGHT)
-			continue;
-
-		numdlights++;
-		dl = malloc(sizeof(directlight_t));
-		memset (dl, 0, sizeof(*dl));
-
-		VectorCopy (p->origin, dl->origin);
-
-		leaf = Rad_PointInLeaf (dl->origin);
-		cluster = leaf->cluster;
-		dl->next = directlights[cluster];
-		directlights[cluster] = dl;
-
-		dl->type = emit_surface;
-		VectorCopy (p->plane->normal, dl->normal);
-
-		dl->intensity = ColorNormalize (p->totallight, dl->color);
-		dl->intensity *= p->area * direct_scale;
-		VectorClear (p->totallight);	// all sent now
-	}
-
-	//
-	// entities
-	//
-	for (i=0 ; i<num_entities ; i++)
-	{
-		e = &entities[i];
-		name = ValueForKey (e, "classname");
-		if (strncmp (name, "light", 5))
-			continue;
-
-		numdlights++;
-		dl = malloc(sizeof(directlight_t));
-		memset (dl, 0, sizeof(*dl));
-
-		GetVectorForKey (e, "origin", dl->origin);
-		dl->style = FloatForKey (e, "_style");
-		if (!dl->style)
-			dl->style = FloatForKey (e, "style");
-		if (dl->style < 0 || dl->style >= MAX_LSTYLES)
-			dl->style = 0;
-
-		leaf = Rad_PointInLeaf (dl->origin);
-		cluster = leaf->cluster;
-
-		dl->next = directlights[cluster];
-		directlights[cluster] = dl;
-
-		intensity = FloatForKey (e, "light");
-		if (!intensity)
-			intensity = FloatForKey (e, "_light");
-		if (!intensity)
-			intensity = 300;
-		_color = ValueForKey (e, "_color");
-		if (_color && _color[0])
-		{
-			sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]);
-			ColorNormalize (dl->color, dl->color);
-		}
-		else
-			dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
-		dl->intensity = intensity*entity_scale;
-		dl->type = emit_point;
-
-		target = ValueForKey (e, "target");
-
-		if (!strcmp (name, "light_spot") || target[0])
-		{
-			dl->type = emit_spotlight;
-			dl->stopdot = FloatForKey (e, "_cone");
-			if (!dl->stopdot)
-				dl->stopdot = 10;
-			dl->stopdot = cos(dl->stopdot/180*3.14159);
-			if (target[0])
-			{	// point towards target
-				e2 = FindTargetEntity (target);
-				if (!e2)
-					Sys_Printf ("WARNING: light at (%i %i %i) has missing target\n",
-					(int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
-				else
-				{
-					GetVectorForKey (e2, "origin", dest);
-					VectorSubtract (dest, dl->origin, dl->normal);
-					VectorNormalize (dl->normal, dl->normal);
-				}
-			}
-			else
-			{	// point down angle
-				angle = FloatForKey (e, "angle");
-				if (angle == ANGLE_UP)
-				{
-					dl->normal[0] = dl->normal[1] = 0;
-					dl->normal[2] = 1;
-				}
-				else if (angle == ANGLE_DOWN)
-				{
-					dl->normal[0] = dl->normal[1] = 0;
-					dl->normal[2] = -1;
-				}
-				else
-				{
-					dl->normal[2] = 0;
-					dl->normal[0] = cos (angle/180*3.14159);
-					dl->normal[1] = sin (angle/180*3.14159);
-				}
-			}
-		}
-	}
-
-	Sys_FPrintf( SYS_VRB, "%i direct lights\n", numdlights);
-}
-
-/*
-=============
-GatherSampleLight
-
-Lightscale is the normalizer for multisampling
-=============
-*/
-void GatherSampleLight (vec3_t pos, vec3_t normal,
-			float **styletable, int offset, int mapsize, float lightscale)
-{
-	int				i;
-	directlight_t	*l;
-	byte			pvs[(MAX_MAP_LEAFS+7)/8];
-	vec3_t			delta;
-	float			dot, dot2;
-	float			dist;
-	float			scale;
-	float			*dest;
-
-	// get the PVS for the pos to limit the number of checks
-	if (!PvsForOrigin (pos, pvs))
-	{
-		return;
-	}
-
-	for (i = 0 ; i<dvis->numclusters ; i++)
-	{
-		if ( ! (pvs[ i>>3] & (1<<(i&7))) )
-			continue;
-
-		for (l=directlights[i] ; l ; l=l->next)
-		{
-			VectorSubtract (l->origin, pos, delta);
-			dist = VectorNormalize (delta, delta);
-			dot = DotProduct (delta, normal);
-			if (dot <= 0.001)
-				continue;	// behind sample surface
-
-			switch (l->type)
-			{
-			case emit_point:
-				// linear falloff
-				scale = (l->intensity - dist) * dot;
-				break;
-
-			case emit_surface:
-				dot2 = -DotProduct (delta, l->normal);
-				if (dot2 <= 0.001)
-					goto skipadd;	// behind light surface
-				scale = (l->intensity / (dist*dist) ) * dot * dot2;
-				break;
-
-			case emit_spotlight:
-				// linear falloff
-				dot2 = -DotProduct (delta, l->normal);
-				if (dot2 <= l->stopdot)
-					goto skipadd;	// outside light cone
-				scale = (l->intensity - dist) * dot;
-				break;
-			default:
-				Error ("Bad l->type");
-			}
-
-			if (TestLine_r (0, pos, l->origin))
-				continue;	// occluded
-
-			if (scale <= 0)
-				continue;
-
-			// if this style doesn't have a table yet, allocate one
-			if (!styletable[l->style])
-			{
-				styletable[l->style] = malloc (mapsize);
-				memset (styletable[l->style], 0, mapsize);
-			}
-
-			dest = styletable[l->style] + offset;			
-			// add some light to it
-			VectorMA (dest, scale*lightscale, l->color, dest);
-
-skipadd: ;
-		}
-	}
-
-}
-
-/*
-=============
-AddSampleToPatch
-
-Take the sample's collected light and
-add it back into the apropriate patch
-for the radiosity pass.
-
-The sample is added to all patches that might include
-any part of it.  They are counted and averaged, so it
-doesn't generate extra light.
-=============
-*/
-void AddSampleToPatch (vec3_t pos, vec3_t color, int facenum)
-{
-	patch_t	*patch;
-	vec3_t	mins, maxs;
-	int		i;
-
-	if (numbounce == 0)
-		return;
-	if (color[0] + color[1] + color[2] < 3)
-		return;
-
-	for (patch = face_patches[facenum] ; patch ; patch=patch->next)
-	{
-		// see if the point is in this patch (roughly)
-		WindingBounds (patch->winding, mins, maxs);
-		for (i=0 ; i<3 ; i++)
-		{
-			if (mins[i] > pos[i] + 16)
-				goto nextpatch;
-			if (maxs[i] < pos[i] - 16)
-				goto nextpatch;
-		}
-
-		// add the sample to the patch
-		patch->samples++;
-		VectorAdd (patch->samplelight, color, patch->samplelight);
-nextpatch:;
-	}
-
-}
-
-
-/*
-=============
-BuildFacelights
-=============
-*/
-float	sampleofs[5][2] = 
-{  {0,0}, {-0.25, -0.25}, {0.25, -0.25}, {0.25, 0.25}, {-0.25, 0.25} };
-
-
-void BuildFacelights (int facenum)
-{
-	dface_t	*f;
-	lightinfo_t	l[5];
-	float		*styletable[MAX_LSTYLES];
-	int			i, j;
-	float		*spot;
-	patch_t		*patch;
-	int			numsamples;
-	int			tablesize;
-	facelight_t		*fl;
-	
-	f = &dfaces[facenum];
-
-	if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) )
-		return;		// non-lit texture
-
-	memset (styletable,0, sizeof(styletable));
-
-	if (extrasamples)
-		numsamples = 5;
-	else
-		numsamples = 1;
-	for (i=0 ; i<numsamples ; i++)
-	{
-		memset (&l[i], 0, sizeof(l[i]));
-		l[i].surfnum = facenum;
-		l[i].face = f;
-		VectorCopy (dplanes[f->planenum].normal, l[i].facenormal);
-		l[i].facedist = dplanes[f->planenum].dist;
-		if (f->side)
-		{
-			VectorSubtract (vec3_origin, l[i].facenormal, l[i].facenormal);
-			l[i].facedist = -l[i].facedist;
-		}
-
-		// get the origin offset for rotating bmodels
-		VectorCopy (face_offset[facenum], l[i].modelorg);
-
-		CalcFaceVectors (&l[i]);
-		CalcFaceExtents (&l[i]);
-		CalcPoints (&l[i], sampleofs[i][0], sampleofs[i][1]);
-	}
-
-	tablesize = l[0].numsurfpt * sizeof(vec3_t);
-	styletable[0] = malloc(tablesize);
-	memset (styletable[0], 0, tablesize);
-
-	fl = &facelight[facenum];
-	fl->numsamples = l[0].numsurfpt;
-	fl->origins = malloc (tablesize);
-	memcpy (fl->origins, l[0].surfpt, tablesize);
-
-	for (i=0 ; i<l[0].numsurfpt ; i++)
-	{
-		for (j=0 ; j<numsamples ; j++)
-		{
-			GatherSampleLight (l[j].surfpt[i], l[0].facenormal, styletable,
-				i*3, tablesize, 1.0/numsamples);
-		}
-
-		// contribute the sample to one or more patches
-		AddSampleToPatch (l[0].surfpt[i], styletable[0]+i*3, facenum);
-	}
-
-	// average up the direct light on each patch for radiosity
-	for (patch = face_patches[facenum] ; patch ; patch=patch->next)
-	{
-		if (patch->samples)
-		{
-			VectorScale (patch->samplelight, 1.0/patch->samples, patch->samplelight);
-		}
-		else
-		{
-//			printf ("patch with no samples\n");
-		}
-	}
-
-	for (i=0 ; i<MAX_LSTYLES ; i++)
-	{
-		if (!styletable[i])
-			continue;
-		if (fl->numstyles == MAX_STYLES)
-			break;
-		fl->samples[fl->numstyles] = styletable[i];
-		fl->stylenums[fl->numstyles] = i;
-		fl->numstyles++;
-	}
-
-	// the light from DIRECT_LIGHTS is sent out, but the
-	// texture itself should still be full bright
-
-	if (face_patches[facenum]->baselight[0] >= DIRECT_LIGHT ||
-		face_patches[facenum]->baselight[1] >= DIRECT_LIGHT ||
-		face_patches[facenum]->baselight[2] >= DIRECT_LIGHT
-		)
-	{
-		spot = fl->samples[0];
-		for (i=0 ; i<l[0].numsurfpt ; i++, spot+=3)
-		{
-			VectorAdd (spot, face_patches[facenum]->baselight, spot);
-		}
-	}
-}
-
-
-/*
-=============
-FinalLightFace
-
-Add the indirect lighting on top of the direct
-lighting and save into final map format
-=============
-*/
-void FinalLightFace (int facenum)
-{
-	dface_t		*f;
-	int			i, j, k, st;
-	vec3_t		lb;
-	patch_t		*patch;
-	triangulation_t	*trian;
-	facelight_t	*fl;
-	float		minlight;
-	float		max, newmax;
-	byte		*dest;
-	int			pfacenum;
-	vec3_t		facemins, facemaxs;
-
-	f = &dfaces[facenum];
-	fl = &facelight[facenum];
-
-	if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) )
-		return;		// non-lit texture
-
-	ThreadLock ();
-	f->lightofs = lightdatasize;
-	lightdatasize += fl->numstyles*(fl->numsamples*3);
-
-// add green sentinals between lightmaps
-#if 0
-lightdatasize += 64*3;
-for (i=0 ; i<64 ; i++)
-dlightdata[lightdatasize-(i+1)*3 + 1] = 255;
-#endif
-
-	if (lightdatasize > MAX_MAP_LIGHTING)
-		Error ("MAX_MAP_LIGHTING");
-	ThreadUnlock ();
-
-	f->styles[0] = 0;
-	f->styles[1] = f->styles[2] = f->styles[3] = 0xff;
-
-	//
-	// set up the triangulation
-	//
-	if (numbounce > 0)
-	{
-		ClearBounds (facemins, facemaxs);
-		for (i=0 ; i<f->numedges ; i++)
-		{
-			int		ednum;
-
-			ednum = dsurfedges[f->firstedge+i];
-			if (ednum >= 0)
-				AddPointToBounds (dvertexes[dedges[ednum].v[0]].point,
-				facemins, facemaxs);
-			else
-				AddPointToBounds (dvertexes[dedges[-ednum].v[1]].point,
-				facemins, facemaxs);
-		}
-
-		trian = AllocTriangulation (&dplanes[f->planenum]);
-
-		// for all faces on the plane, add the nearby patches
-		// to the triangulation
-		for (pfacenum = planelinks[f->side][f->planenum]
-			; pfacenum ; pfacenum = facelinks[pfacenum])
-		{
-			for (patch = face_patches[pfacenum] ; patch ; patch=patch->next)
-			{
-				for (i=0 ; i < 3 ; i++)
-				{
-					if (facemins[i] - patch->origin[i] > subdiv*2)
-						break;
-					if (patch->origin[i] - facemaxs[i] > subdiv*2)
-						break;
-				}
-				if (i != 3)
-					continue;	// not needed for this face
-				AddPointToTriangulation (patch, trian);
-			}
-		}
-		for (i=0 ; i<trian->numpoints ; i++)
-			memset (trian->edgematrix[i], 0, trian->numpoints*sizeof(trian->edgematrix[0][0]) );
-		TriangulatePoints (trian);
-	}
-	
-	//
-	// sample the triangulation
-	//
-
-	// _minlight allows models that have faces that would not be
-	// illuminated to receive a mottled light pattern instead of
-	// black
-	minlight = FloatForKey (face_entity[facenum], "_minlight") * 128;
-
-	dest = &dlightdata[f->lightofs];
-
-	if (fl->numstyles > MAXLIGHTMAPS)
-	{
-		fl->numstyles = MAXLIGHTMAPS;
-		Sys_Printf ("face with too many lightstyles: (%f %f %f)\n",
-			face_patches[facenum]->origin[0],
-			face_patches[facenum]->origin[1],
-			face_patches[facenum]->origin[2]
-			);
-	}
-
-	for (st=0 ; st<fl->numstyles ; st++)
-	{
-		f->styles[st] = fl->stylenums[st];
-		for (j=0 ; j<fl->numsamples ; j++)
-		{
-			VectorCopy ( (fl->samples[st]+j*3), lb);
-			if (numbounce > 0 && st == 0)
-			{
-				vec3_t	add;
-
-				SampleTriangulation (fl->origins + j*3, trian, add);
-				VectorAdd (lb, add, lb);
-			}
-			// add an ambient term if desired
-			lb[0] += ambient; 
-			lb[1] += ambient; 
-			lb[2] += ambient; 
-
-			VectorScale (lb, lightscale, lb);
-
-			// we need to clamp without allowing hue to change
-			for (k=0 ; k<3 ; k++)
-				if (lb[k] < 1)
-					lb[k] = 1;
-			max = lb[0];
-			if (lb[1] > max)
-				max = lb[1];
-			if (lb[2] > max)
-				max = lb[2];
-			newmax = max;
-			if (newmax < 0)
-				newmax = 0;		// roundoff problems
-			if (newmax < minlight)
-			{
-				newmax = minlight + (rand()%48);
-			}
-			if (newmax > maxlight)
-				newmax = maxlight;
-
-			for (k=0 ; k<3 ; k++)
-			{
-				*dest++ = lb[k]*newmax/max;
-			}
-		}
-	}
-
-	if (numbounce > 0)
-		FreeTriangulation (trian);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "qrad.h"
+
+#define	MAX_LSTYLES	256
+
+typedef struct
+{
+	dface_t		*faces[2];
+	qboolean	coplanar;
+} edgeshare_t;
+
+edgeshare_t	edgeshare[MAX_MAP_EDGES];
+
+int			facelinks[MAX_MAP_FACES];
+int			planelinks[2][MAX_MAP_PLANES];
+
+/*
+============
+LinkPlaneFaces
+============
+*/
+void LinkPlaneFaces (void)
+{
+	int		i;
+	dface_t	*f;
+
+	f = dfaces;
+	for (i=0 ; i<numfaces ; i++, f++)
+	{
+		facelinks[i] = planelinks[f->side][f->planenum];
+		planelinks[f->side][f->planenum] = i;
+	}
+}
+
+/*
+============
+PairEdges
+============
+*/
+void PairEdges (void)
+{
+	int		i, j, k;
+	dface_t	*f;
+	edgeshare_t	*e;
+
+	f = dfaces;
+	for (i=0 ; i<numfaces ; i++, f++)
+	{
+		for (j=0 ; j<f->numedges ; j++)
+		{
+			k = dsurfedges[f->firstedge + j];
+			if (k < 0)
+			{
+				e = &edgeshare[-k];
+				e->faces[1] = f;
+			}
+			else
+			{
+				e = &edgeshare[k];
+				e->faces[0] = f;
+			}
+
+			if (e->faces[0] && e->faces[1])
+			{
+				// determine if coplanar
+				if (e->faces[0]->planenum == e->faces[1]->planenum)
+					e->coplanar = true;
+			}
+		}
+	}
+}
+
+/*
+=================================================================
+
+  POINT TRIANGULATION
+
+=================================================================
+*/
+
+typedef struct triedge_s
+{
+	int			p0, p1;
+	vec3_t		normal;
+	vec_t		dist;
+	struct triangle_s	*tri;
+} triedge_t;
+
+typedef struct triangle_s
+{
+	triedge_t	*edges[3];
+} triangle_t;
+
+#define	MAX_TRI_POINTS		1024
+#define	MAX_TRI_EDGES		(MAX_TRI_POINTS*6)
+#define	MAX_TRI_TRIS		(MAX_TRI_POINTS*2)
+
+typedef struct
+{
+	int			numpoints;
+	int			numedges;
+	int			numtris;
+	dplane_t	*plane;
+	triedge_t	*edgematrix[MAX_TRI_POINTS][MAX_TRI_POINTS];
+	patch_t		*points[MAX_TRI_POINTS];
+	triedge_t	edges[MAX_TRI_EDGES];
+	triangle_t	tris[MAX_TRI_TRIS];
+} triangulation_t;
+
+/*
+===============
+AllocTriangulation
+===============
+*/
+triangulation_t	*AllocTriangulation (dplane_t *plane)
+{
+	triangulation_t	*t;
+
+	t = malloc(sizeof(triangulation_t));
+	t->numpoints = 0;
+	t->numedges = 0;
+	t->numtris = 0;
+
+	t->plane = plane;
+
+//	memset (t->edgematrix, 0, sizeof(t->edgematrix));
+
+	return t;
+}
+
+/*
+===============
+FreeTriangulation
+===============
+*/
+void FreeTriangulation (triangulation_t *tr)
+{
+	free (tr);
+}
+
+
+triedge_t	*FindEdge (triangulation_t *trian, int p0, int p1)
+{
+	triedge_t	*e, *be;
+	vec3_t		v1;
+	vec3_t		normal;
+	vec_t		dist;
+
+	if (trian->edgematrix[p0][p1])
+		return trian->edgematrix[p0][p1];
+
+	if (trian->numedges > MAX_TRI_EDGES-2)
+		Error ("trian->numedges > MAX_TRI_EDGES-2");
+
+	VectorSubtract (trian->points[p1]->origin, trian->points[p0]->origin, v1);
+	VectorNormalize (v1, v1);
+	CrossProduct (v1, trian->plane->normal, normal);
+	dist = DotProduct (trian->points[p0]->origin, normal);
+
+	e = &trian->edges[trian->numedges];
+	e->p0 = p0;
+	e->p1 = p1;
+	e->tri = NULL;
+	VectorCopy (normal, e->normal);
+	e->dist = dist;
+	trian->numedges++;
+	trian->edgematrix[p0][p1] = e;
+
+	be = &trian->edges[trian->numedges];
+	be->p0 = p1;
+	be->p1 = p0;
+	be->tri = NULL;
+	VectorSubtract (vec3_origin, normal, be->normal);
+	be->dist = -dist;
+	trian->numedges++;
+	trian->edgematrix[p1][p0] = be;
+
+	return e;
+}
+
+triangle_t	*AllocTriangle (triangulation_t *trian)
+{
+	triangle_t	*t;
+
+	if (trian->numtris >= MAX_TRI_TRIS)
+		Error ("trian->numtris >= MAX_TRI_TRIS");
+
+	t = &trian->tris[trian->numtris];
+	trian->numtris++;
+
+	return t;
+}
+
+/*
+============
+TriEdge_r
+============
+*/
+void TriEdge_r (triangulation_t *trian, triedge_t *e)
+{
+	int		i, bestp;
+	vec3_t	v1, v2;
+	vec_t	*p0, *p1, *p;
+	vec_t	best, ang;
+	triangle_t	*nt;
+
+	if (e->tri)
+		return;		// allready connected by someone
+
+	// find the point with the best angle
+	p0 = trian->points[e->p0]->origin;
+	p1 = trian->points[e->p1]->origin;
+	best = 1.1;
+	for (i=0 ; i< trian->numpoints ; i++)
+	{
+		p = trian->points[i]->origin;
+		// a 0 dist will form a degenerate triangle
+		if (DotProduct(p, e->normal) - e->dist < 0)
+			continue;	// behind edge
+		VectorSubtract (p0, p, v1);
+		VectorSubtract (p1, p, v2);
+		if (!VectorNormalize (v1,v1))
+			continue;
+		if (!VectorNormalize (v2,v2))
+			continue;
+		ang = DotProduct (v1, v2);
+		if (ang < best)
+		{
+			best = ang;
+			bestp = i;
+		}
+	}
+	if (best >= 1)
+		return;		// edge doesn't match anything
+
+	// make a new triangle
+	nt = AllocTriangle (trian);
+	nt->edges[0] = e;
+	nt->edges[1] = FindEdge (trian, e->p1, bestp);
+	nt->edges[2] = FindEdge (trian, bestp, e->p0);
+	for (i=0 ; i<3 ; i++)
+		nt->edges[i]->tri = nt;
+	TriEdge_r (trian, FindEdge (trian, bestp, e->p1));
+	TriEdge_r (trian, FindEdge (trian, e->p0, bestp));
+}
+
+/*
+============
+TriangulatePoints
+============
+*/
+void TriangulatePoints (triangulation_t *trian)
+{
+	vec_t	d, bestd;
+	vec3_t	v1;
+	int		bp1, bp2, i, j;
+	vec_t	*p1, *p2;
+	triedge_t	*e, *e2;
+
+	if (trian->numpoints < 2)
+		return;
+
+	// find the two closest points
+	bestd = 9999;
+	for (i=0 ; i<trian->numpoints ; i++)
+	{
+		p1 = trian->points[i]->origin;
+		for (j=i+1 ; j<trian->numpoints ; j++)
+		{
+			p2 = trian->points[j]->origin;
+			VectorSubtract (p2, p1, v1);
+			d = VectorLength (v1);
+			if (d < bestd)
+			{
+				bestd = d;
+				bp1 = i;
+				bp2 = j;
+			}
+		}
+	}
+
+	e = FindEdge (trian, bp1, bp2);
+	e2 = FindEdge (trian, bp2, bp1);
+	TriEdge_r (trian, e);
+	TriEdge_r (trian, e2);
+}
+
+/*
+===============
+AddPointToTriangulation
+===============
+*/
+void AddPointToTriangulation (patch_t *patch, triangulation_t *trian)
+{
+	int			pnum;
+
+	pnum = trian->numpoints;
+	if (pnum == MAX_TRI_POINTS)
+		Error ("trian->numpoints == MAX_TRI_POINTS");
+	trian->points[pnum] = patch;
+	trian->numpoints++;
+}
+
+/*
+===============
+LerpTriangle
+===============
+*/
+void	LerpTriangle (triangulation_t *trian, triangle_t *t, vec3_t point, vec3_t color)
+{
+	patch_t		*p1, *p2, *p3;
+	vec3_t		base, d1, d2;
+	float		x, y, x1, y1, x2, y2;
+
+	p1 = trian->points[t->edges[0]->p0];
+	p2 = trian->points[t->edges[1]->p0];
+	p3 = trian->points[t->edges[2]->p0];
+
+	VectorCopy (p1->totallight, base);
+	VectorSubtract (p2->totallight, base, d1);
+	VectorSubtract (p3->totallight, base, d2);
+
+	x = DotProduct (point, t->edges[0]->normal) - t->edges[0]->dist;
+	y = DotProduct (point, t->edges[2]->normal) - t->edges[2]->dist;
+
+	x1 = 0;
+	y1 = DotProduct (p2->origin, t->edges[2]->normal) - t->edges[2]->dist;
+
+	x2 = DotProduct (p3->origin, t->edges[0]->normal) - t->edges[0]->dist;
+	y2 = 0;
+
+	if (fabs(y1)<ON_EPSILON || fabs(x2)<ON_EPSILON)
+	{
+		VectorCopy (base, color);
+		return;
+	}
+
+	VectorMA (base, x/x2, d2, color);
+	VectorMA (color, y/y1, d1, color);
+}
+
+qboolean PointInTriangle (vec3_t point, triangle_t *t)
+{
+	int		i;
+	triedge_t	*e;
+	vec_t	d;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		e = t->edges[i];
+		d = DotProduct (e->normal, point) - e->dist;
+		if (d < 0)
+			return false;	// not inside
+	}
+
+	return true;
+}
+
+/*
+===============
+SampleTriangulation
+===============
+*/
+void SampleTriangulation (vec3_t point, triangulation_t *trian, vec3_t color)
+{
+	triangle_t	*t;
+	triedge_t	*e;
+	vec_t		d, best;
+	patch_t		*p0, *p1;
+	vec3_t		v1, v2;
+	int			i, j;
+
+	if (trian->numpoints == 0)
+	{
+		VectorClear (color);
+		return;
+	}
+	if (trian->numpoints == 1)
+	{
+		VectorCopy (trian->points[0]->totallight, color);
+		return;
+	}
+
+	// search for triangles
+	for (t = trian->tris, j=0 ; j < trian->numtris ; t++, j++)
+	{
+		if (!PointInTriangle (point, t))
+			continue;
+
+		// this is it
+		LerpTriangle (trian, t, point, color);
+		return;
+	}
+	
+	// search for exterior edge
+	for (e=trian->edges, j=0 ; j< trian->numedges ; e++, j++)
+	{
+		if (e->tri)
+			continue;		// not an exterior edge
+
+		d = DotProduct (point, e->normal) - e->dist;
+		if (d < 0)
+			continue;	// not in front of edge
+
+		p0 = trian->points[e->p0];
+		p1 = trian->points[e->p1];
+	
+		VectorSubtract (p1->origin, p0->origin, v1);
+		VectorNormalize (v1, v1);
+		VectorSubtract (point, p0->origin, v2);
+		d = DotProduct (v2, v1);
+		if (d < 0)
+			continue;
+		if (d > 1)
+			continue;
+		for (i=0 ; i<3 ; i++)
+			color[i] = p0->totallight[i] + d * (p1->totallight[i] - p0->totallight[i]);
+		return;
+	}
+
+	// search for nearest point
+	best = 99999;
+	p1 = NULL;
+	for (j=0 ; j<trian->numpoints ; j++)
+	{
+		p0 = trian->points[j];
+		VectorSubtract (point, p0->origin, v1);
+		d = VectorLength (v1);
+		if (d < best)
+		{
+			best = d;
+			p1 = p0;
+		}
+	}
+
+	if (!p1)
+		Error ("SampleTriangulation: no points");
+
+	VectorCopy (p1->totallight, color);
+}
+
+/*
+=================================================================
+
+  LIGHTMAP SAMPLE GENERATION
+
+=================================================================
+*/
+
+
+#define	SINGLEMAP	(64*64*4)
+
+typedef struct
+{
+	vec_t	facedist;
+	vec3_t	facenormal;
+
+	int		numsurfpt;
+	vec3_t	surfpt[SINGLEMAP];
+
+	vec3_t	modelorg;		// for origined bmodels
+
+	vec3_t	texorg;
+	vec3_t	worldtotex[2];	// s = (world - texorg) . worldtotex[0]
+	vec3_t	textoworld[2];	// world = texorg + s * textoworld[0]
+
+	vec_t	exactmins[2], exactmaxs[2];
+	
+	int		texmins[2], texsize[2];
+	int		surfnum;
+	dface_t	*face;
+} lightinfo_t;
+
+
+/*
+================
+CalcFaceExtents
+
+Fills in s->texmins[] and s->texsize[]
+also sets exactmins[] and exactmaxs[]
+================
+*/
+void CalcFaceExtents (lightinfo_t *l)
+{
+	dface_t *s;
+	vec_t	mins[2], maxs[2], val;
+	int		i,j, e;
+	dvertex_t	*v;
+	texinfo_t	*tex;
+	vec3_t		vt;
+
+	s = l->face;
+
+	mins[0] = mins[1] = 999999;
+	maxs[0] = maxs[1] = -99999;
+
+	tex = &texinfo[s->texinfo];
+	
+	for (i=0 ; i<s->numedges ; i++)
+	{
+		e = dsurfedges[s->firstedge+i];
+		if (e >= 0)
+			v = dvertexes + dedges[e].v[0];
+		else
+			v = dvertexes + dedges[-e].v[1];
+		
+//		VectorAdd (v->point, l->modelorg, vt);
+		VectorCopy (v->point, vt);
+
+		for (j=0 ; j<2 ; j++)
+		{
+			val = DotProduct (vt, tex->vecs[j]) + tex->vecs[j][3];
+			if (val < mins[j])
+				mins[j] = val;
+			if (val > maxs[j])
+				maxs[j] = val;
+		}
+	}
+
+	for (i=0 ; i<2 ; i++)
+	{	
+		l->exactmins[i] = mins[i];
+		l->exactmaxs[i] = maxs[i];
+		
+		mins[i] = floor(mins[i]/16);
+		maxs[i] = ceil(maxs[i]/16);
+
+		l->texmins[i] = mins[i];
+		l->texsize[i] = maxs[i] - mins[i];
+		if (l->texsize[0] * l->texsize[1] > SINGLEMAP/4)	// div 4 for extrasamples
+			Error ("Surface to large to map");
+	}
+}
+
+/*
+================
+CalcFaceVectors
+
+Fills in texorg, worldtotex. and textoworld
+================
+*/
+void CalcFaceVectors (lightinfo_t *l)
+{
+	texinfo_t	*tex;
+	int			i, j;
+	vec3_t	texnormal;
+	vec_t	distscale;
+	vec_t	dist, len;
+	int			w, h;
+
+	tex = &texinfo[l->face->texinfo];
+	
+// convert from float to double
+	for (i=0 ; i<2 ; i++)
+		for (j=0 ; j<3 ; j++)
+			l->worldtotex[i][j] = tex->vecs[i][j];
+
+// calculate a normal to the texture axis.  points can be moved along this
+// without changing their S/T
+	texnormal[0] = tex->vecs[1][1]*tex->vecs[0][2]
+		- tex->vecs[1][2]*tex->vecs[0][1];
+	texnormal[1] = tex->vecs[1][2]*tex->vecs[0][0]
+		- tex->vecs[1][0]*tex->vecs[0][2];
+	texnormal[2] = tex->vecs[1][0]*tex->vecs[0][1]
+		- tex->vecs[1][1]*tex->vecs[0][0];
+	VectorNormalize (texnormal, texnormal);
+
+// flip it towards plane normal
+	distscale = DotProduct (texnormal, l->facenormal);
+	if (!distscale)
+	{
+		Sys_FPrintf( SYS_VRB, "WARNING: Texture axis perpendicular to face\n");
+		distscale = 1;
+	}
+	if (distscale < 0)
+	{
+		distscale = -distscale;
+		VectorSubtract (vec3_origin, texnormal, texnormal);
+	}	
+
+// distscale is the ratio of the distance along the texture normal to
+// the distance along the plane normal
+	distscale = 1/distscale;
+
+	for (i=0 ; i<2 ; i++)
+	{
+		len = VectorLength (l->worldtotex[i]);
+		dist = DotProduct (l->worldtotex[i], l->facenormal);
+		dist *= distscale;
+		VectorMA (l->worldtotex[i], -dist, texnormal, l->textoworld[i]);
+		VectorScale (l->textoworld[i], (1/len)*(1/len), l->textoworld[i]);
+	}
+
+
+// calculate texorg on the texture plane
+	for (i=0 ; i<3 ; i++)
+		l->texorg[i] = -tex->vecs[0][3]* l->textoworld[0][i] - tex->vecs[1][3] * l->textoworld[1][i];
+
+// project back to the face plane
+	dist = DotProduct (l->texorg, l->facenormal) - l->facedist - 1;
+	dist *= distscale;
+	VectorMA (l->texorg, -dist, texnormal, l->texorg);
+
+	// compensate for org'd bmodels
+	VectorAdd (l->texorg, l->modelorg, l->texorg);
+
+	// total sample count
+	h = l->texsize[1]+1;
+	w = l->texsize[0]+1;
+	l->numsurfpt = w * h;
+}
+
+/*
+=================
+CalcPoints
+
+For each texture aligned grid point, back project onto the plane
+to get the world xyz value of the sample point
+=================
+*/
+void CalcPoints (lightinfo_t *l, float sofs, float tofs)
+{
+	int		i;
+	int		s, t, j;
+	int		w, h, step;
+	vec_t	starts, startt, us, ut;
+	vec_t	*surf;
+	vec_t	mids, midt;
+	vec3_t	facemid;
+	dleaf_t	*leaf;
+
+	surf = l->surfpt[0];
+	mids = (l->exactmaxs[0] + l->exactmins[0])/2;
+	midt = (l->exactmaxs[1] + l->exactmins[1])/2;
+
+	for (j=0 ; j<3 ; j++)
+		facemid[j] = l->texorg[j] + l->textoworld[0][j]*mids + l->textoworld[1][j]*midt;
+
+	h = l->texsize[1]+1;
+	w = l->texsize[0]+1;
+	l->numsurfpt = w * h;
+
+	starts = l->texmins[0]*16;
+	startt = l->texmins[1]*16;
+	step = 16;
+
+
+	for (t=0 ; t<h ; t++)
+	{
+		for (s=0 ; s<w ; s++, surf+=3)
+		{
+			us = starts + (s+sofs)*step;
+			ut = startt + (t+tofs)*step;
+
+
+		// if a line can be traced from surf to facemid, the point is good
+			for (i=0 ; i<6 ; i++)
+			{
+			// calculate texture point
+				for (j=0 ; j<3 ; j++)
+					surf[j] = l->texorg[j] + l->textoworld[0][j]*us
+					+ l->textoworld[1][j]*ut;
+
+				leaf = Rad_PointInLeaf (surf);
+				if (leaf->contents != CONTENTS_SOLID)
+				{
+					if (!TestLine_r (0, facemid, surf))
+						break;	// got it
+				}
+
+				// nudge it
+				if (i & 1)
+				{
+					if (us > mids)
+					{
+						us -= 8;
+						if (us < mids)
+							us = mids;
+					}
+					else
+					{
+						us += 8;
+						if (us > mids)
+							us = mids;
+					}
+				}
+				else
+				{
+					if (ut > midt)
+					{
+						ut -= 8;
+						if (ut < midt)
+							ut = midt;
+					}
+					else
+					{
+						ut += 8;
+						if (ut > midt)
+							ut = midt;
+					}
+				}
+			}
+		}
+	}
+	
+}
+
+
+//==============================================================
+
+
+
+#define	MAX_STYLES	32
+typedef struct
+{
+	int			numsamples;
+	float		*origins;
+	int			numstyles;
+	int			stylenums[MAX_STYLES];
+	float		*samples[MAX_STYLES];
+} facelight_t;
+
+directlight_t	*directlights[MAX_MAP_LEAFS];
+facelight_t		facelight[MAX_MAP_FACES];
+int				numdlights;
+
+/*
+==================
+FindTargetEntity
+==================
+*/
+entity_t *FindTargetEntity (char *target)
+{
+	int		i;
+	char	*n;
+
+	for (i=0 ; i<num_entities ; i++)
+	{
+		n = ValueForKey (&entities[i], "targetname");
+		if (!strcmp (n, target))
+			return &entities[i];
+	}
+
+	return NULL;
+}
+
+//#define	DIRECT_LIGHT	3000
+#define	DIRECT_LIGHT	3
+
+/*
+=============
+CreateDirectLights
+=============
+*/
+void CreateDirectLights (void)
+{
+	int		i;
+	patch_t	*p;
+	directlight_t	*dl;
+	dleaf_t	*leaf;
+	int		cluster;
+	entity_t	*e, *e2;
+	char	*name;
+	char	*target;
+	float	angle;
+	vec3_t	dest;
+	char	*_color;
+	float	intensity;
+
+	//
+	// surfaces
+	//
+	for (i=0, p=patches ; i< (int) num_patches ; i++, p++)
+	{
+		if (p->totallight[0] < DIRECT_LIGHT
+			&& p->totallight[1] < DIRECT_LIGHT
+			&& p->totallight[2] < DIRECT_LIGHT)
+			continue;
+
+		numdlights++;
+		dl = malloc(sizeof(directlight_t));
+		memset (dl, 0, sizeof(*dl));
+
+		VectorCopy (p->origin, dl->origin);
+
+		leaf = Rad_PointInLeaf (dl->origin);
+		cluster = leaf->cluster;
+		dl->next = directlights[cluster];
+		directlights[cluster] = dl;
+
+		dl->type = emit_surface;
+		VectorCopy (p->plane->normal, dl->normal);
+
+		dl->intensity = ColorNormalize (p->totallight, dl->color);
+		dl->intensity *= p->area * direct_scale;
+		VectorClear (p->totallight);	// all sent now
+	}
+
+	//
+	// entities
+	//
+	for (i=0 ; i<num_entities ; i++)
+	{
+		e = &entities[i];
+		name = ValueForKey (e, "classname");
+		if (strncmp (name, "light", 5))
+			continue;
+
+		numdlights++;
+		dl = malloc(sizeof(directlight_t));
+		memset (dl, 0, sizeof(*dl));
+
+		GetVectorForKey (e, "origin", dl->origin);
+		dl->style = FloatForKey (e, "_style");
+		if (!dl->style)
+			dl->style = FloatForKey (e, "style");
+		if (dl->style < 0 || dl->style >= MAX_LSTYLES)
+			dl->style = 0;
+
+		leaf = Rad_PointInLeaf (dl->origin);
+		cluster = leaf->cluster;
+
+		dl->next = directlights[cluster];
+		directlights[cluster] = dl;
+
+		intensity = FloatForKey (e, "light");
+		if (!intensity)
+			intensity = FloatForKey (e, "_light");
+		if (!intensity)
+			intensity = 300;
+		_color = ValueForKey (e, "_color");
+		if (_color && _color[0])
+		{
+			sscanf (_color, "%f %f %f", &dl->color[0],&dl->color[1],&dl->color[2]);
+			ColorNormalize (dl->color, dl->color);
+		}
+		else
+			dl->color[0] = dl->color[1] = dl->color[2] = 1.0;
+		dl->intensity = intensity*entity_scale;
+		dl->type = emit_point;
+
+		target = ValueForKey (e, "target");
+
+		if (!strcmp (name, "light_spot") || target[0])
+		{
+			dl->type = emit_spotlight;
+			dl->stopdot = FloatForKey (e, "_cone");
+			if (!dl->stopdot)
+				dl->stopdot = 10;
+			dl->stopdot = cos(dl->stopdot/180*3.14159);
+			if (target[0])
+			{	// point towards target
+				e2 = FindTargetEntity (target);
+				if (!e2)
+					Sys_Printf ("WARNING: light at (%i %i %i) has missing target\n",
+					(int)dl->origin[0], (int)dl->origin[1], (int)dl->origin[2]);
+				else
+				{
+					GetVectorForKey (e2, "origin", dest);
+					VectorSubtract (dest, dl->origin, dl->normal);
+					VectorNormalize (dl->normal, dl->normal);
+				}
+			}
+			else
+			{	// point down angle
+				angle = FloatForKey (e, "angle");
+				if (angle == ANGLE_UP)
+				{
+					dl->normal[0] = dl->normal[1] = 0;
+					dl->normal[2] = 1;
+				}
+				else if (angle == ANGLE_DOWN)
+				{
+					dl->normal[0] = dl->normal[1] = 0;
+					dl->normal[2] = -1;
+				}
+				else
+				{
+					dl->normal[2] = 0;
+					dl->normal[0] = cos (angle/180*3.14159);
+					dl->normal[1] = sin (angle/180*3.14159);
+				}
+			}
+		}
+	}
+
+	Sys_FPrintf( SYS_VRB, "%i direct lights\n", numdlights);
+}
+
+/*
+=============
+GatherSampleLight
+
+Lightscale is the normalizer for multisampling
+=============
+*/
+void GatherSampleLight (vec3_t pos, vec3_t normal,
+			float **styletable, int offset, int mapsize, float lightscale)
+{
+	int				i;
+	directlight_t	*l;
+	byte			pvs[(MAX_MAP_LEAFS+7)/8];
+	vec3_t			delta;
+	float			dot, dot2;
+	float			dist;
+	float			scale;
+	float			*dest;
+
+	// get the PVS for the pos to limit the number of checks
+	if (!PvsForOrigin (pos, pvs))
+	{
+		return;
+	}
+
+	for (i = 0 ; i<dvis->numclusters ; i++)
+	{
+		if ( ! (pvs[ i>>3] & (1<<(i&7))) )
+			continue;
+
+		for (l=directlights[i] ; l ; l=l->next)
+		{
+			VectorSubtract (l->origin, pos, delta);
+			dist = VectorNormalize (delta, delta);
+			dot = DotProduct (delta, normal);
+			if (dot <= 0.001)
+				continue;	// behind sample surface
+
+			switch (l->type)
+			{
+			case emit_point:
+				// linear falloff
+				scale = (l->intensity - dist) * dot;
+				break;
+
+			case emit_surface:
+				dot2 = -DotProduct (delta, l->normal);
+				if (dot2 <= 0.001)
+					goto skipadd;	// behind light surface
+				scale = (l->intensity / (dist*dist) ) * dot * dot2;
+				break;
+
+			case emit_spotlight:
+				// linear falloff
+				dot2 = -DotProduct (delta, l->normal);
+				if (dot2 <= l->stopdot)
+					goto skipadd;	// outside light cone
+				scale = (l->intensity - dist) * dot;
+				break;
+			default:
+				Error ("Bad l->type");
+			}
+
+			if (TestLine_r (0, pos, l->origin))
+				continue;	// occluded
+
+			if (scale <= 0)
+				continue;
+
+			// if this style doesn't have a table yet, allocate one
+			if (!styletable[l->style])
+			{
+				styletable[l->style] = malloc (mapsize);
+				memset (styletable[l->style], 0, mapsize);
+			}
+
+			dest = styletable[l->style] + offset;			
+			// add some light to it
+			VectorMA (dest, scale*lightscale, l->color, dest);
+
+skipadd: ;
+		}
+	}
+
+}
+
+/*
+=============
+AddSampleToPatch
+
+Take the sample's collected light and
+add it back into the apropriate patch
+for the radiosity pass.
+
+The sample is added to all patches that might include
+any part of it.  They are counted and averaged, so it
+doesn't generate extra light.
+=============
+*/
+void AddSampleToPatch (vec3_t pos, vec3_t color, int facenum)
+{
+	patch_t	*patch;
+	vec3_t	mins, maxs;
+	int		i;
+
+	if (numbounce == 0)
+		return;
+	if (color[0] + color[1] + color[2] < 3)
+		return;
+
+	for (patch = face_patches[facenum] ; patch ; patch=patch->next)
+	{
+		// see if the point is in this patch (roughly)
+		WindingBounds (patch->winding, mins, maxs);
+		for (i=0 ; i<3 ; i++)
+		{
+			if (mins[i] > pos[i] + 16)
+				goto nextpatch;
+			if (maxs[i] < pos[i] - 16)
+				goto nextpatch;
+		}
+
+		// add the sample to the patch
+		patch->samples++;
+		VectorAdd (patch->samplelight, color, patch->samplelight);
+nextpatch:;
+	}
+
+}
+
+
+/*
+=============
+BuildFacelights
+=============
+*/
+float	sampleofs[5][2] = 
+{  {0,0}, {-0.25, -0.25}, {0.25, -0.25}, {0.25, 0.25}, {-0.25, 0.25} };
+
+
+void BuildFacelights (int facenum)
+{
+	dface_t	*f;
+	lightinfo_t	l[5];
+	float		*styletable[MAX_LSTYLES];
+	int			i, j;
+	float		*spot;
+	patch_t		*patch;
+	int			numsamples;
+	int			tablesize;
+	facelight_t		*fl;
+	
+	f = &dfaces[facenum];
+
+	if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) )
+		return;		// non-lit texture
+
+	memset (styletable,0, sizeof(styletable));
+
+	if (extrasamples)
+		numsamples = 5;
+	else
+		numsamples = 1;
+	for (i=0 ; i<numsamples ; i++)
+	{
+		memset (&l[i], 0, sizeof(l[i]));
+		l[i].surfnum = facenum;
+		l[i].face = f;
+		VectorCopy (dplanes[f->planenum].normal, l[i].facenormal);
+		l[i].facedist = dplanes[f->planenum].dist;
+		if (f->side)
+		{
+			VectorSubtract (vec3_origin, l[i].facenormal, l[i].facenormal);
+			l[i].facedist = -l[i].facedist;
+		}
+
+		// get the origin offset for rotating bmodels
+		VectorCopy (face_offset[facenum], l[i].modelorg);
+
+		CalcFaceVectors (&l[i]);
+		CalcFaceExtents (&l[i]);
+		CalcPoints (&l[i], sampleofs[i][0], sampleofs[i][1]);
+	}
+
+	tablesize = l[0].numsurfpt * sizeof(vec3_t);
+	styletable[0] = malloc(tablesize);
+	memset (styletable[0], 0, tablesize);
+
+	fl = &facelight[facenum];
+	fl->numsamples = l[0].numsurfpt;
+	fl->origins = malloc (tablesize);
+	memcpy (fl->origins, l[0].surfpt, tablesize);
+
+	for (i=0 ; i<l[0].numsurfpt ; i++)
+	{
+		for (j=0 ; j<numsamples ; j++)
+		{
+			GatherSampleLight (l[j].surfpt[i], l[0].facenormal, styletable,
+				i*3, tablesize, 1.0/numsamples);
+		}
+
+		// contribute the sample to one or more patches
+		AddSampleToPatch (l[0].surfpt[i], styletable[0]+i*3, facenum);
+	}
+
+	// average up the direct light on each patch for radiosity
+	for (patch = face_patches[facenum] ; patch ; patch=patch->next)
+	{
+		if (patch->samples)
+		{
+			VectorScale (patch->samplelight, 1.0/patch->samples, patch->samplelight);
+		}
+		else
+		{
+//			printf ("patch with no samples\n");
+		}
+	}
+
+	for (i=0 ; i<MAX_LSTYLES ; i++)
+	{
+		if (!styletable[i])
+			continue;
+		if (fl->numstyles == MAX_STYLES)
+			break;
+		fl->samples[fl->numstyles] = styletable[i];
+		fl->stylenums[fl->numstyles] = i;
+		fl->numstyles++;
+	}
+
+	// the light from DIRECT_LIGHTS is sent out, but the
+	// texture itself should still be full bright
+
+	if (face_patches[facenum]->baselight[0] >= DIRECT_LIGHT ||
+		face_patches[facenum]->baselight[1] >= DIRECT_LIGHT ||
+		face_patches[facenum]->baselight[2] >= DIRECT_LIGHT
+		)
+	{
+		spot = fl->samples[0];
+		for (i=0 ; i<l[0].numsurfpt ; i++, spot+=3)
+		{
+			VectorAdd (spot, face_patches[facenum]->baselight, spot);
+		}
+	}
+}
+
+
+/*
+=============
+FinalLightFace
+
+Add the indirect lighting on top of the direct
+lighting and save into final map format
+=============
+*/
+void FinalLightFace (int facenum)
+{
+	dface_t		*f;
+	int			i, j, k, st;
+	vec3_t		lb;
+	patch_t		*patch;
+	triangulation_t	*trian;
+	facelight_t	*fl;
+	float		minlight;
+	float		max, newmax;
+	byte		*dest;
+	int			pfacenum;
+	vec3_t		facemins, facemaxs;
+
+	f = &dfaces[facenum];
+	fl = &facelight[facenum];
+
+	if ( texinfo[f->texinfo].flags & (SURF_WARP|SURF_SKY) )
+		return;		// non-lit texture
+
+	ThreadLock ();
+	f->lightofs = lightdatasize;
+	lightdatasize += fl->numstyles*(fl->numsamples*3);
+
+// add green sentinals between lightmaps
+#if 0
+lightdatasize += 64*3;
+for (i=0 ; i<64 ; i++)
+dlightdata[lightdatasize-(i+1)*3 + 1] = 255;
+#endif
+
+	if (lightdatasize > MAX_MAP_LIGHTING)
+		Error ("MAX_MAP_LIGHTING");
+	ThreadUnlock ();
+
+	f->styles[0] = 0;
+	f->styles[1] = f->styles[2] = f->styles[3] = 0xff;
+
+	//
+	// set up the triangulation
+	//
+	if (numbounce > 0)
+	{
+		ClearBounds (facemins, facemaxs);
+		for (i=0 ; i<f->numedges ; i++)
+		{
+			int		ednum;
+
+			ednum = dsurfedges[f->firstedge+i];
+			if (ednum >= 0)
+				AddPointToBounds (dvertexes[dedges[ednum].v[0]].point,
+				facemins, facemaxs);
+			else
+				AddPointToBounds (dvertexes[dedges[-ednum].v[1]].point,
+				facemins, facemaxs);
+		}
+
+		trian = AllocTriangulation (&dplanes[f->planenum]);
+
+		// for all faces on the plane, add the nearby patches
+		// to the triangulation
+		for (pfacenum = planelinks[f->side][f->planenum]
+			; pfacenum ; pfacenum = facelinks[pfacenum])
+		{
+			for (patch = face_patches[pfacenum] ; patch ; patch=patch->next)
+			{
+				for (i=0 ; i < 3 ; i++)
+				{
+					if (facemins[i] - patch->origin[i] > subdiv*2)
+						break;
+					if (patch->origin[i] - facemaxs[i] > subdiv*2)
+						break;
+				}
+				if (i != 3)
+					continue;	// not needed for this face
+				AddPointToTriangulation (patch, trian);
+			}
+		}
+		for (i=0 ; i<trian->numpoints ; i++)
+			memset (trian->edgematrix[i], 0, trian->numpoints*sizeof(trian->edgematrix[0][0]) );
+		TriangulatePoints (trian);
+	}
+	
+	//
+	// sample the triangulation
+	//
+
+	// _minlight allows models that have faces that would not be
+	// illuminated to receive a mottled light pattern instead of
+	// black
+	minlight = FloatForKey (face_entity[facenum], "_minlight") * 128;
+
+	dest = &dlightdata[f->lightofs];
+
+	if (fl->numstyles > MAXLIGHTMAPS)
+	{
+		fl->numstyles = MAXLIGHTMAPS;
+		Sys_Printf ("face with too many lightstyles: (%f %f %f)\n",
+			face_patches[facenum]->origin[0],
+			face_patches[facenum]->origin[1],
+			face_patches[facenum]->origin[2]
+			);
+	}
+
+	for (st=0 ; st<fl->numstyles ; st++)
+	{
+		f->styles[st] = fl->stylenums[st];
+		for (j=0 ; j<fl->numsamples ; j++)
+		{
+			VectorCopy ( (fl->samples[st]+j*3), lb);
+			if (numbounce > 0 && st == 0)
+			{
+				vec3_t	add;
+
+				SampleTriangulation (fl->origins + j*3, trian, add);
+				VectorAdd (lb, add, lb);
+			}
+			// add an ambient term if desired
+			lb[0] += ambient; 
+			lb[1] += ambient; 
+			lb[2] += ambient; 
+
+			VectorScale (lb, lightscale, lb);
+
+			// we need to clamp without allowing hue to change
+			for (k=0 ; k<3 ; k++)
+				if (lb[k] < 1)
+					lb[k] = 1;
+			max = lb[0];
+			if (lb[1] > max)
+				max = lb[1];
+			if (lb[2] > max)
+				max = lb[2];
+			newmax = max;
+			if (newmax < 0)
+				newmax = 0;		// roundoff problems
+			if (newmax < minlight)
+			{
+				newmax = minlight + (rand()%48);
+			}
+			if (newmax > maxlight)
+				newmax = maxlight;
+
+			for (k=0 ; k<3 ; k++)
+			{
+				*dest++ = lb[k]*newmax/max;
+			}
+		}
+	}
+
+	if (numbounce > 0)
+		FreeTriangulation (trian);
+}
diff --git a/tools/quake2/q2map/main.c b/tools/quake2/q2map/main.c
index 6edcc21c..810205a5 100644
--- a/tools/quake2/q2map/main.c
+++ b/tools/quake2/q2map/main.c
@@ -1,721 +1,721 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-/* marker */
-#define MAIN_C
-
-
-
-/* dependencies */
-#include "q2map.h"
-
-#define qtrue true
-#define qfalse false
-
-char	*mapname;
-char	game[64];
-extern	qboolean	verbose;
-
-/// BSP 
-extern	qboolean	drawflag;
-extern	qboolean	noprune;
-extern	qboolean	glview;
-extern	qboolean	nodetail;
-extern	qboolean	fulldetail;
-extern	qboolean	onlyents;
-extern	qboolean	nomerge;
-extern	qboolean	nowater;
-extern	qboolean	nofill;
-extern	qboolean	nocsg;
-extern	qboolean	noweld;
-extern	qboolean	noshare;
-extern	qboolean	nosubdiv;
-extern	qboolean	notjunc;
-extern	qboolean	noopt;
-extern	qboolean	leaktest;
-extern	qboolean	verboseentities;
-extern	char		outbase[32];
-extern	int		block_xl, block_xh, block_yl, block_yh;
-extern	vec_t		microvolume;
-extern	float		subdivide_size;
-
-// VIS
-extern	char		inbase[32];
-extern	qboolean	fastvis;
-extern	qboolean	nosort;
-extern	int		testlevel;
-
-// RAD
-extern	qboolean	dumppatches;
-extern	int		numbounce;
-extern	qboolean	extrasamples;
-extern	float		subdiv;
-extern	float		lightscale;
-extern	float		direct_scale;
-extern	float		entity_scale;
-extern	qboolean	nopvs;
-extern	float		ambient;
-extern	float		maxlight;
-
-
-void InitPaths( int *argc, char **argv );
-
-/*
-Random()
-returns a pseudorandom number between 0 and 1
-*/
-/*
-vec_t Random( void )
-{
-	return (vec_t) rand() / RAND_MAX;
-}
-*/
-
-
-/*
-ExitQ2Map()
-cleanup routine
-*/
-/*
-static void ExitQ2Map( void )
-{
-	BSPFilesCleanup();
-	if( mapDrawSurfs != NULL )
-		free( mapDrawSurfs );
-}
-*/
-
-
-/*
-BSPInfo()
-emits statistics about the bsp file
-*/
-
-int BSPInfo()
-{
-	char		source[ 1024 ], ext[ 64 ];
-	int			size;
-	FILE		*f;
-	
-	Sys_Printf ("\n----- INFO ----\n\n");
-	
-	/* dummy check */
-	if( mapname == NULL )
-	{
-		Sys_Printf( "No files to dump info for.\n");
-		return -1;
-	}
-	
-	/* enable info mode */
-	//infoMode = qtrue;
-	
-	
-	/* mangle filename and get size */
-	strcpy( source, mapname );
-	ExtractFileExtension( source, ext );
-	if( !Q_stricmp( ext, "map" ) )
-		StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	f = fopen( source, "rb" );
-	if( f )
-	{
-		size = Q_filelength (f);
-		fclose( f );
-	}
-	else
-		size = 0;
-	
-	/* load the bsp file and print lump sizes */
-	Sys_Printf( "Map: %s\n\n", source );
-	
-	Sys_Printf( "-----------------------------------------------------\n" );
-	
-	LoadBSPFile( source );		
-	PrintBSPFileSizes();
-	
-	Sys_Printf( "-----------------------------------------------------\n" );
-	
-	/* print sizes */
-	Sys_Printf( "Total:  %d B = %.3f kB = %.3f MB\n", size, size / 1024.0, size / (1024.0 * 1024.0) );
-	
-	Sys_Printf( "-----------------------------------------------------\n" );
-	
-	/* return count */
-	return 0;
-}
-
-
-
-/*
-ScaleBSPMain()
-amaze and confuse your enemies with wierd scaled maps!
-*/
-/*
-int ScaleBSPMain( int argc, char **argv )
-{
-	int			i;
-	float		f, scale;
-	vec3_t		vec;
-	char		str[ 1024 ];
-	
-	
-	// arg checking 
-	if( argc < 2 )
-	{
-		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
-		return 0;
-	}
-	
-	// get scale 
-	scale = atof( argv[ argc - 2 ] );
-	if( scale == 0.0f )
-	{
-		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
-		Sys_Printf( "Non-zero scale value required.\n" );
-		return 0;
-	}
-	
-	// do some path mangling 
-	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
-	StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	
-	// load the bsp 
-	Sys_Printf( "Loading %s\n", source );
-	LoadBSPFile( source );
-	ParseEntities();
-	
-	// note it 
-	Sys_Printf( "--- ScaleBSP ---\n" );
-	Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
-	
-	// scale entity keys 
-	for( i = 0; i < numBSPEntities && i < numEntities; i++ )
-	{
-		// scale origin 
-		GetVectorForKey( &entities[ i ], "origin", vec );
-		if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )
-		{
-			VectorScale( vec, scale, vec );
-			sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
-			SetKeyValue( &entities[ i ], "origin", str );
-		}
-		
-		// scale door lip 
-		f = FloatForKey( &entities[ i ], "lip" );
-		if( f )
-		{
-			f *= scale;
-			sprintf( str, "%f", f );
-			SetKeyValue( &entities[ i ], "lip", str );
-		}
-	}
-	
-	// scale models 
-	for( i = 0; i < numBSPModels; i++ )
-	{
-		VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
-		VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
-	}
-	
-	// scale nodes 
-	for( i = 0; i < numBSPNodes; i++ )
-	{
-		VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
-		VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
-	}
-	
-	// scale leafs 
-	for( i = 0; i < numBSPLeafs; i++ )
-	{
-		VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
-		VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
-	}
-	
-	// scale drawverts 
-	for( i = 0; i < numBSPDrawVerts; i++ )
-		VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
-	
-	// scale planes 
-	for( i = 0; i < numBSPPlanes; i++ )
-		bspPlanes[ i ].dist *= scale;
-	
-	// scale gridsize 
-	GetVectorForKey( &entities[ 0 ], "gridsize", vec );
-	if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )
-		VectorCopy( gridSize, vec );
-	VectorScale( vec, scale, vec );
-	sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
-	SetKeyValue( &entities[ 0 ], "gridsize", str );
-	
-	// write the bsp 
-	UnparseEntities();
-	StripExtension( source );
-	DefaultExtension( source, "_s.bsp" );
-	Sys_Printf( "Writing %s\n", source );
-	WriteBSPFile( source );
-	
-	// return to sender 
-	return 0;
-}
-*/
-
-
-/*
-ConvertBSPMain()
-main argument processing function for bsp conversion
-*/
-/*
-int ConvertBSPMain( int argc, char **argv )
-{
-	int		i;
-	int		(*convertFunc)( char * );
-	
-	
-	// set default 
-	convertFunc = ConvertBSPToASE;
-	
-	// arg checking 
-	if( argc < 1 )
-	{
-		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
-		return 0;
-	}
-	
-	// process arguments 
-	for( i = 1; i < (argc - 1); i++ )
-	{
-		// -format map|ase|... 
-		if( !strcmp( argv[ i ],  "-format" ) )
- 		{
-			i++;
-			if( !Q_stricmp( argv[ i ], "ase" ) )
-				convertFunc = ConvertBSPToASE;
-			else if( !Q_stricmp( argv[ i ], "map" ) )
-				convertFunc = ConvertBSPToMap;
-			else
-				Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
- 		}
-	}
-	
-	// clean up map name 
-	strcpy( source, ExpandArg( argv[ i ] ) );
-	StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	
-	LoadShaderInfo();
-	
-	Sys_Printf( "Loading %s\n", source );
-	
-	// ydnar: load surface file 
-	//%	LoadSurfaceExtraFile( source );
-	
-	LoadBSPFile( source );
-	
-	// parse bsp entities 
-	ParseEntities();
-	
-	// convert 
-	return convertFunc( source );
-}
-*/
-
-int Check_BSP_Options( int argc, char **argv )
-{
-	int i;
-	
-	for (i=1 ; i<argc ; i++)
-	{
-		if (!strcmp(argv[i],"-glview"))
-		{
-			glview = true;
-		}
-		else if (!strcmp(argv[i], "-draw"))
-		{
-			Sys_Printf ("drawflag = true\n");
-			drawflag = true;
-		}
-		else if (!strcmp(argv[i], "-noweld"))
-		{
-			Sys_Printf ("noweld = true\n");
-			noweld = true;
-		}
-		else if (!strcmp(argv[i], "-nocsg"))
-		{
-			Sys_Printf ("nocsg = true\n");
-			nocsg = true;
-		}
-		else if (!strcmp(argv[i], "-noshare"))
-		{
-			Sys_Printf ("noshare = true\n");
-			noshare = true;
-		}
-		else if (!strcmp(argv[i], "-notjunc"))
-		{
-			Sys_Printf ("notjunc = true\n");
-			notjunc = true;
-		}
-		else if (!strcmp(argv[i], "-nowater"))
-		{
-			Sys_Printf ("nowater = true\n");
-			nowater = true;
-		}
-		else if (!strcmp(argv[i], "-noopt"))
-		{
-			Sys_Printf ("noopt = true\n");
-			noopt = true;
-		}
-		else if (!strcmp(argv[i], "-noprune"))
-		{
-			Sys_Printf ("noprune = true\n");
-			noprune = true;
-		}
-		else if (!strcmp(argv[i], "-nofill"))
-		{
-			Sys_Printf ("nofill = true\n");
-			nofill = true;
-		}
-		else if (!strcmp(argv[i], "-nomerge"))
-		{
-			Sys_Printf ("nomerge = true\n");
-			nomerge = true;
-		}
-		else if (!strcmp(argv[i], "-nosubdiv"))
-		{
-			Sys_Printf ("nosubdiv = true\n");
-			nosubdiv = true;
-		}
-		else if (!strcmp(argv[i], "-nodetail"))
-		{
-			Sys_Printf ("nodetail = true\n");
-			nodetail = true;
-		}
-		else if (!strcmp(argv[i], "-fulldetail"))
-		{
-			Sys_Printf ("fulldetail = true\n");
-			fulldetail = true;
-		}
-		else if (!strcmp(argv[i], "-onlyents"))
-		{
-			Sys_Printf ("onlyents = true\n");
-			onlyents = true;
-		}
-		else if (!strcmp(argv[i], "-micro"))
-		{
-			microvolume = atof(argv[i+1]);
-			Sys_Printf ("microvolume = %f\n", microvolume);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-leaktest"))
-		{
-			Sys_Printf ("leaktest = true\n");
-			leaktest = true;
-		}
-		else if (!strcmp(argv[i], "-verboseentities"))
-		{
-			Sys_Printf ("verboseentities = true\n");
-			verboseentities = true;
-		}
-		else if (!strcmp(argv[i], "-chop"))
-		{
-			subdivide_size = atof(argv[i+1]);
-			Sys_Printf ("subdivide_size = %f\n", subdivide_size);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-block"))
-		{
-			block_xl = block_xh = atoi(argv[i+1]);
-			block_yl = block_yh = atoi(argv[i+2]);
-			Sys_Printf ("block: %i,%i\n", block_xl, block_yl);
-			i+=2;
-		}
-		else if (!strcmp(argv[i], "-blocks"))
-		{
-			block_xl = atoi(argv[i+1]);
-			block_yl = atoi(argv[i+2]);
-			block_xh = atoi(argv[i+3]);
-			block_yh = atoi(argv[i+4]);
-			Sys_Printf ("blocks: %i,%i to %i,%i\n", 
-				block_xl, block_yl, block_xh, block_yh);
-			i+=4;
-		}
-		else if (!strcmp (argv[i],"-tmpout"))
-		{
-			strcpy (outbase, "/tmp");
-		}
-		else
-			break;
-	}
-
-
-	return 0;
-}
-
-int Check_VIS_Options( int argc, char **argv )
-{
-	int i;
-	
-	for (i=1 ; i<argc ; i++)
-	{
-		if (!strcmp(argv[i], "-fast"))
-		{
-			Sys_Printf ("fastvis = true\n");
-			fastvis = true;
-		}
-		else if (!strcmp(argv[i], "-level"))
-		{
-			testlevel = atoi(argv[i+1]);
-			Sys_Printf ("testlevel = %i\n", testlevel);
-			i++;
-		}
-		else if (!strcmp (argv[i],"-nosort"))
-		{
-			Sys_Printf ("nosort = true\n");
-			nosort = true;
-		}
-		else if (!strcmp (argv[i],"-tmpin"))
-			strcpy (inbase, "/tmp");
-		else if (!strcmp (argv[i],"-tmpout"))
-			strcpy (outbase, "/tmp");
-		else
-			break;
-	}
-
-	return 0;
-}
-
-int Check_RAD_Options( int argc, char **argv )
-{
-	int i;
-	
-	for (i=1 ; i<argc ; i++)
-	{
-		if (!strcmp(argv[i],"-dump"))
-			dumppatches = true;
-		else if (!strcmp(argv[i],"-bounce"))
-		{
-			numbounce = atoi (argv[i+1]);
-			i++;
-		}
-		else if (!strcmp(argv[i],"-extra"))
-		{
-			extrasamples = true;
-			Sys_Printf ("extrasamples = true\n");
-		}
-		else if (!strcmp(argv[i],"-chop"))
-		{
-			subdiv = atoi (argv[i+1]);
-			i++;
-		}
-		else if (!strcmp(argv[i],"-scale"))
-		{
-			lightscale = atof (argv[i+1]);
-			i++;
-		}
-		else if (!strcmp(argv[i],"-direct"))
-		{
-			direct_scale *= atof(argv[i+1]);
-			Sys_Printf ("direct light scaling at %f\n", direct_scale);
-			i++;
-		}
-		else if (!strcmp(argv[i],"-entity"))
-		{
-			entity_scale *= atof(argv[i+1]);
-			Sys_Printf ("entity light scaling at %f\n", entity_scale);
-			i++;
-		}
-		else if (!strcmp(argv[i],"-glview"))
-		{
-			glview = true;
-			Sys_Printf ("glview = true\n");
-		}
-		else if (!strcmp(argv[i],"-nopvs"))
-		{
-			nopvs = true;
-			Sys_Printf ("nopvs = true\n");
-		}
-		else if (!strcmp(argv[i],"-ambient"))
-		{
-			ambient = atof (argv[i+1]) * 128;
-			i++;
-		}
-		else if (!strcmp(argv[i],"-maxlight"))
-		{
-			maxlight = atof (argv[i+1]) * 128;
-			i++;
-		}
-		else if (!strcmp (argv[i],"-tmpin"))
-			strcpy (inbase, "/tmp");
-		else if (!strcmp (argv[i],"-tmpout"))
-			strcpy (outbase, "/tmp");
-		else
-			break;
-	}
-
-	return 0;
-}
-
-/*
-main()
-*/
-
-int main( int argc, char **argv )
-{
-	int	i;
-	int	r=0;
-	int	total_time;
-	double	start, end;
-	int	alt_argc;
-	char**	alt_argv;
-	qboolean	do_info=qfalse;
-	qboolean	do_bsp=qfalse;
-	qboolean	do_vis=qfalse;
-	qboolean	do_rad=qfalse;
-	
-	
-	/* we want consistent 'randomness' */
-	srand( 0 );
-	
-	/* start timer */
-	start = I_FloatTime();
-
-	Sys_Printf( "\nQ2Map - Ver. 1.0\n" );
-
-	/* set exit call */
-	//atexit( ExitQ3Map );
-	
-	game[0] = 0;
-	
-	if ( argc < 2 )
-	{
-		Sys_Printf(" %s: -game [quake2,heretic2] -fs_basepath basepath -info -bsp -vis -rad mapname\n",argv[0]);
-		return -1;
-	}
-	/* read general options first */
-	for( i = 1; i < argc; i++ )
-	{
-		/* -connect */
-		if( !strcmp( argv[ i ], "-connect" ) )
-		{
-			i++;
-			Broadcast_Setup( argv[ i ] );
-		}
-		
-		/* verbose */
-		else if( !strcmp( argv[ i ], "-v" ) )
-		{
-			verbose = qtrue;
-		}
-		
-		/* threads */
-		 else if( !strcmp( argv[ i ], "-threads" ) )
-		{
-			i++;
-			numthreads = atoi( argv[ i ] );
-		}
-		else if( !strcmp( argv[ i ], "-game" ) )
-		{
-			i++;
-			strncpy (game, argv[ i ] , 64);
-			strlower(game);
-		} 
-	}
-	
-	/* set number of threads */
-	ThreadSetDefault();
-	
-	/* ydnar: new path initialization */
-	InitPaths( &argc, argv );
-	
-	/* read compiling options */
-	for( i = 1; i < argc; i++ )
-	{
-		/* info */
-		if( !strcmp( argv[ i ], "-info" ) )
-		{
-			do_info=qtrue;
-		}
-
-		/* bsp */
-		if( !strcmp( argv[ i ], "-bsp" ) )
-		{
-			do_bsp=qtrue;
-			alt_argc=argc - i;
-			alt_argv= (char **) ( argv + i );
-			Check_BSP_Options( alt_argc, alt_argv );
-		}
-
-		/* vis */
-		if( !strcmp( argv[ i ], "-vis" ) )
-		{
-			do_vis=qtrue;
-			alt_argc=argc - i;
-			alt_argv= (char **) ( argv + i );
-			Check_VIS_Options( alt_argc, alt_argv );
-		}
-
-		/* rad */
-		if( !strcmp( argv[ i ], "-rad" ) )
-		{
-			do_rad=qtrue;
-			alt_argc=argc - i;
-			alt_argv= (char **) ( argv + i );
-			Check_RAD_Options( alt_argc, alt_argv );
-		}
-	}
-	
-	if (game[0] == 0)
-		strncpy( game, "quake2", 7);
-		
-	Sys_Printf("Game: %s\n", game);
-	
-	if ( !do_info && !do_bsp && !do_vis && !do_rad)
-		Sys_Printf("ERROR: -bsp, -vis, -light, nor -info specified.\nWhat to you want me to do?\n\n");
-	else
-	{
-		mapname=argv[argc-1];
-		
-		if (do_bsp)
-			BSP_Main();
-		if (do_vis)
-			VIS_Main();
-		if (do_rad)
-			RAD_Main();
-		if (do_info)
-			BSPInfo();
-		
-	}
-	
-	/* emit time */
-	end = I_FloatTime();
-	total_time = (int) (end-start);
-	Sys_Printf("\nTotal Time: ");
-	if ( total_time > 59 )
-		Sys_Printf("%d Minutes ", total_time/60 );
-	Sys_Printf( "%d Seconds\n", total_time%60 );
-	
-	/* shut down connection */
-	Broadcast_Shutdown();
-	
-	/* return any error code */
-	return r;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+/* marker */
+#define MAIN_C
+
+
+
+/* dependencies */
+#include "q2map.h"
+
+#define qtrue true
+#define qfalse false
+
+char	*mapname;
+char	game[64];
+extern	qboolean	verbose;
+
+/// BSP 
+extern	qboolean	drawflag;
+extern	qboolean	noprune;
+extern	qboolean	glview;
+extern	qboolean	nodetail;
+extern	qboolean	fulldetail;
+extern	qboolean	onlyents;
+extern	qboolean	nomerge;
+extern	qboolean	nowater;
+extern	qboolean	nofill;
+extern	qboolean	nocsg;
+extern	qboolean	noweld;
+extern	qboolean	noshare;
+extern	qboolean	nosubdiv;
+extern	qboolean	notjunc;
+extern	qboolean	noopt;
+extern	qboolean	leaktest;
+extern	qboolean	verboseentities;
+extern	char		outbase[32];
+extern	int		block_xl, block_xh, block_yl, block_yh;
+extern	vec_t		microvolume;
+extern	float		subdivide_size;
+
+// VIS
+extern	char		inbase[32];
+extern	qboolean	fastvis;
+extern	qboolean	nosort;
+extern	int		testlevel;
+
+// RAD
+extern	qboolean	dumppatches;
+extern	int		numbounce;
+extern	qboolean	extrasamples;
+extern	float		subdiv;
+extern	float		lightscale;
+extern	float		direct_scale;
+extern	float		entity_scale;
+extern	qboolean	nopvs;
+extern	float		ambient;
+extern	float		maxlight;
+
+
+void InitPaths( int *argc, char **argv );
+
+/*
+Random()
+returns a pseudorandom number between 0 and 1
+*/
+/*
+vec_t Random( void )
+{
+	return (vec_t) rand() / RAND_MAX;
+}
+*/
+
+
+/*
+ExitQ2Map()
+cleanup routine
+*/
+/*
+static void ExitQ2Map( void )
+{
+	BSPFilesCleanup();
+	if( mapDrawSurfs != NULL )
+		free( mapDrawSurfs );
+}
+*/
+
+
+/*
+BSPInfo()
+emits statistics about the bsp file
+*/
+
+int BSPInfo()
+{
+	char		source[ 1024 ], ext[ 64 ];
+	int			size;
+	FILE		*f;
+	
+	Sys_Printf ("\n----- INFO ----\n\n");
+	
+	/* dummy check */
+	if( mapname == NULL )
+	{
+		Sys_Printf( "No files to dump info for.\n");
+		return -1;
+	}
+	
+	/* enable info mode */
+	//infoMode = qtrue;
+	
+	
+	/* mangle filename and get size */
+	strcpy( source, mapname );
+	ExtractFileExtension( source, ext );
+	if( !Q_stricmp( ext, "map" ) )
+		StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	f = fopen( source, "rb" );
+	if( f )
+	{
+		size = Q_filelength (f);
+		fclose( f );
+	}
+	else
+		size = 0;
+	
+	/* load the bsp file and print lump sizes */
+	Sys_Printf( "Map: %s\n\n", source );
+	
+	Sys_Printf( "-----------------------------------------------------\n" );
+	
+	LoadBSPFile( source );		
+	PrintBSPFileSizes();
+	
+	Sys_Printf( "-----------------------------------------------------\n" );
+	
+	/* print sizes */
+	Sys_Printf( "Total:  %d B = %.3f kB = %.3f MB\n", size, size / 1024.0, size / (1024.0 * 1024.0) );
+	
+	Sys_Printf( "-----------------------------------------------------\n" );
+	
+	/* return count */
+	return 0;
+}
+
+
+
+/*
+ScaleBSPMain()
+amaze and confuse your enemies with wierd scaled maps!
+*/
+/*
+int ScaleBSPMain( int argc, char **argv )
+{
+	int			i;
+	float		f, scale;
+	vec3_t		vec;
+	char		str[ 1024 ];
+	
+	
+	// arg checking 
+	if( argc < 2 )
+	{
+		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+		return 0;
+	}
+	
+	// get scale 
+	scale = atof( argv[ argc - 2 ] );
+	if( scale == 0.0f )
+	{
+		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+		Sys_Printf( "Non-zero scale value required.\n" );
+		return 0;
+	}
+	
+	// do some path mangling 
+	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
+	StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	
+	// load the bsp 
+	Sys_Printf( "Loading %s\n", source );
+	LoadBSPFile( source );
+	ParseEntities();
+	
+	// note it 
+	Sys_Printf( "--- ScaleBSP ---\n" );
+	Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
+	
+	// scale entity keys 
+	for( i = 0; i < numBSPEntities && i < numEntities; i++ )
+	{
+		// scale origin 
+		GetVectorForKey( &entities[ i ], "origin", vec );
+		if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )
+		{
+			VectorScale( vec, scale, vec );
+			sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
+			SetKeyValue( &entities[ i ], "origin", str );
+		}
+		
+		// scale door lip 
+		f = FloatForKey( &entities[ i ], "lip" );
+		if( f )
+		{
+			f *= scale;
+			sprintf( str, "%f", f );
+			SetKeyValue( &entities[ i ], "lip", str );
+		}
+	}
+	
+	// scale models 
+	for( i = 0; i < numBSPModels; i++ )
+	{
+		VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
+		VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
+	}
+	
+	// scale nodes 
+	for( i = 0; i < numBSPNodes; i++ )
+	{
+		VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
+		VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
+	}
+	
+	// scale leafs 
+	for( i = 0; i < numBSPLeafs; i++ )
+	{
+		VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
+		VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
+	}
+	
+	// scale drawverts 
+	for( i = 0; i < numBSPDrawVerts; i++ )
+		VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
+	
+	// scale planes 
+	for( i = 0; i < numBSPPlanes; i++ )
+		bspPlanes[ i ].dist *= scale;
+	
+	// scale gridsize 
+	GetVectorForKey( &entities[ 0 ], "gridsize", vec );
+	if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )
+		VectorCopy( gridSize, vec );
+	VectorScale( vec, scale, vec );
+	sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
+	SetKeyValue( &entities[ 0 ], "gridsize", str );
+	
+	// write the bsp 
+	UnparseEntities();
+	StripExtension( source );
+	DefaultExtension( source, "_s.bsp" );
+	Sys_Printf( "Writing %s\n", source );
+	WriteBSPFile( source );
+	
+	// return to sender 
+	return 0;
+}
+*/
+
+
+/*
+ConvertBSPMain()
+main argument processing function for bsp conversion
+*/
+/*
+int ConvertBSPMain( int argc, char **argv )
+{
+	int		i;
+	int		(*convertFunc)( char * );
+	
+	
+	// set default 
+	convertFunc = ConvertBSPToASE;
+	
+	// arg checking 
+	if( argc < 1 )
+	{
+		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+		return 0;
+	}
+	
+	// process arguments 
+	for( i = 1; i < (argc - 1); i++ )
+	{
+		// -format map|ase|... 
+		if( !strcmp( argv[ i ],  "-format" ) )
+ 		{
+			i++;
+			if( !Q_stricmp( argv[ i ], "ase" ) )
+				convertFunc = ConvertBSPToASE;
+			else if( !Q_stricmp( argv[ i ], "map" ) )
+				convertFunc = ConvertBSPToMap;
+			else
+				Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
+ 		}
+	}
+	
+	// clean up map name 
+	strcpy( source, ExpandArg( argv[ i ] ) );
+	StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	
+	LoadShaderInfo();
+	
+	Sys_Printf( "Loading %s\n", source );
+	
+	// ydnar: load surface file 
+	//%	LoadSurfaceExtraFile( source );
+	
+	LoadBSPFile( source );
+	
+	// parse bsp entities 
+	ParseEntities();
+	
+	// convert 
+	return convertFunc( source );
+}
+*/
+
+int Check_BSP_Options( int argc, char **argv )
+{
+	int i;
+	
+	for (i=1 ; i<argc ; i++)
+	{
+		if (!strcmp(argv[i],"-glview"))
+		{
+			glview = true;
+		}
+		else if (!strcmp(argv[i], "-draw"))
+		{
+			Sys_Printf ("drawflag = true\n");
+			drawflag = true;
+		}
+		else if (!strcmp(argv[i], "-noweld"))
+		{
+			Sys_Printf ("noweld = true\n");
+			noweld = true;
+		}
+		else if (!strcmp(argv[i], "-nocsg"))
+		{
+			Sys_Printf ("nocsg = true\n");
+			nocsg = true;
+		}
+		else if (!strcmp(argv[i], "-noshare"))
+		{
+			Sys_Printf ("noshare = true\n");
+			noshare = true;
+		}
+		else if (!strcmp(argv[i], "-notjunc"))
+		{
+			Sys_Printf ("notjunc = true\n");
+			notjunc = true;
+		}
+		else if (!strcmp(argv[i], "-nowater"))
+		{
+			Sys_Printf ("nowater = true\n");
+			nowater = true;
+		}
+		else if (!strcmp(argv[i], "-noopt"))
+		{
+			Sys_Printf ("noopt = true\n");
+			noopt = true;
+		}
+		else if (!strcmp(argv[i], "-noprune"))
+		{
+			Sys_Printf ("noprune = true\n");
+			noprune = true;
+		}
+		else if (!strcmp(argv[i], "-nofill"))
+		{
+			Sys_Printf ("nofill = true\n");
+			nofill = true;
+		}
+		else if (!strcmp(argv[i], "-nomerge"))
+		{
+			Sys_Printf ("nomerge = true\n");
+			nomerge = true;
+		}
+		else if (!strcmp(argv[i], "-nosubdiv"))
+		{
+			Sys_Printf ("nosubdiv = true\n");
+			nosubdiv = true;
+		}
+		else if (!strcmp(argv[i], "-nodetail"))
+		{
+			Sys_Printf ("nodetail = true\n");
+			nodetail = true;
+		}
+		else if (!strcmp(argv[i], "-fulldetail"))
+		{
+			Sys_Printf ("fulldetail = true\n");
+			fulldetail = true;
+		}
+		else if (!strcmp(argv[i], "-onlyents"))
+		{
+			Sys_Printf ("onlyents = true\n");
+			onlyents = true;
+		}
+		else if (!strcmp(argv[i], "-micro"))
+		{
+			microvolume = atof(argv[i+1]);
+			Sys_Printf ("microvolume = %f\n", microvolume);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-leaktest"))
+		{
+			Sys_Printf ("leaktest = true\n");
+			leaktest = true;
+		}
+		else if (!strcmp(argv[i], "-verboseentities"))
+		{
+			Sys_Printf ("verboseentities = true\n");
+			verboseentities = true;
+		}
+		else if (!strcmp(argv[i], "-chop"))
+		{
+			subdivide_size = atof(argv[i+1]);
+			Sys_Printf ("subdivide_size = %f\n", subdivide_size);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-block"))
+		{
+			block_xl = block_xh = atoi(argv[i+1]);
+			block_yl = block_yh = atoi(argv[i+2]);
+			Sys_Printf ("block: %i,%i\n", block_xl, block_yl);
+			i+=2;
+		}
+		else if (!strcmp(argv[i], "-blocks"))
+		{
+			block_xl = atoi(argv[i+1]);
+			block_yl = atoi(argv[i+2]);
+			block_xh = atoi(argv[i+3]);
+			block_yh = atoi(argv[i+4]);
+			Sys_Printf ("blocks: %i,%i to %i,%i\n", 
+				block_xl, block_yl, block_xh, block_yh);
+			i+=4;
+		}
+		else if (!strcmp (argv[i],"-tmpout"))
+		{
+			strcpy (outbase, "/tmp");
+		}
+		else
+			break;
+	}
+
+
+	return 0;
+}
+
+int Check_VIS_Options( int argc, char **argv )
+{
+	int i;
+	
+	for (i=1 ; i<argc ; i++)
+	{
+		if (!strcmp(argv[i], "-fast"))
+		{
+			Sys_Printf ("fastvis = true\n");
+			fastvis = true;
+		}
+		else if (!strcmp(argv[i], "-level"))
+		{
+			testlevel = atoi(argv[i+1]);
+			Sys_Printf ("testlevel = %i\n", testlevel);
+			i++;
+		}
+		else if (!strcmp (argv[i],"-nosort"))
+		{
+			Sys_Printf ("nosort = true\n");
+			nosort = true;
+		}
+		else if (!strcmp (argv[i],"-tmpin"))
+			strcpy (inbase, "/tmp");
+		else if (!strcmp (argv[i],"-tmpout"))
+			strcpy (outbase, "/tmp");
+		else
+			break;
+	}
+
+	return 0;
+}
+
+int Check_RAD_Options( int argc, char **argv )
+{
+	int i;
+	
+	for (i=1 ; i<argc ; i++)
+	{
+		if (!strcmp(argv[i],"-dump"))
+			dumppatches = true;
+		else if (!strcmp(argv[i],"-bounce"))
+		{
+			numbounce = atoi (argv[i+1]);
+			i++;
+		}
+		else if (!strcmp(argv[i],"-extra"))
+		{
+			extrasamples = true;
+			Sys_Printf ("extrasamples = true\n");
+		}
+		else if (!strcmp(argv[i],"-chop"))
+		{
+			subdiv = atoi (argv[i+1]);
+			i++;
+		}
+		else if (!strcmp(argv[i],"-scale"))
+		{
+			lightscale = atof (argv[i+1]);
+			i++;
+		}
+		else if (!strcmp(argv[i],"-direct"))
+		{
+			direct_scale *= atof(argv[i+1]);
+			Sys_Printf ("direct light scaling at %f\n", direct_scale);
+			i++;
+		}
+		else if (!strcmp(argv[i],"-entity"))
+		{
+			entity_scale *= atof(argv[i+1]);
+			Sys_Printf ("entity light scaling at %f\n", entity_scale);
+			i++;
+		}
+		else if (!strcmp(argv[i],"-glview"))
+		{
+			glview = true;
+			Sys_Printf ("glview = true\n");
+		}
+		else if (!strcmp(argv[i],"-nopvs"))
+		{
+			nopvs = true;
+			Sys_Printf ("nopvs = true\n");
+		}
+		else if (!strcmp(argv[i],"-ambient"))
+		{
+			ambient = atof (argv[i+1]) * 128;
+			i++;
+		}
+		else if (!strcmp(argv[i],"-maxlight"))
+		{
+			maxlight = atof (argv[i+1]) * 128;
+			i++;
+		}
+		else if (!strcmp (argv[i],"-tmpin"))
+			strcpy (inbase, "/tmp");
+		else if (!strcmp (argv[i],"-tmpout"))
+			strcpy (outbase, "/tmp");
+		else
+			break;
+	}
+
+	return 0;
+}
+
+/*
+main()
+*/
+
+int main( int argc, char **argv )
+{
+	int	i;
+	int	r=0;
+	int	total_time;
+	double	start, end;
+	int	alt_argc;
+	char**	alt_argv;
+	qboolean	do_info=qfalse;
+	qboolean	do_bsp=qfalse;
+	qboolean	do_vis=qfalse;
+	qboolean	do_rad=qfalse;
+	
+	
+	/* we want consistent 'randomness' */
+	srand( 0 );
+	
+	/* start timer */
+	start = I_FloatTime();
+
+	Sys_Printf( "\nQ2Map - Ver. 1.0\n" );
+
+	/* set exit call */
+	//atexit( ExitQ3Map );
+	
+	game[0] = 0;
+	
+	if ( argc < 2 )
+	{
+		Sys_Printf(" %s: -game [quake2,heretic2] -fs_basepath basepath -info -bsp -vis -rad mapname\n",argv[0]);
+		return -1;
+	}
+	/* read general options first */
+	for( i = 1; i < argc; i++ )
+	{
+		/* -connect */
+		if( !strcmp( argv[ i ], "-connect" ) )
+		{
+			i++;
+			Broadcast_Setup( argv[ i ] );
+		}
+		
+		/* verbose */
+		else if( !strcmp( argv[ i ], "-v" ) )
+		{
+			verbose = qtrue;
+		}
+		
+		/* threads */
+		 else if( !strcmp( argv[ i ], "-threads" ) )
+		{
+			i++;
+			numthreads = atoi( argv[ i ] );
+		}
+		else if( !strcmp( argv[ i ], "-game" ) )
+		{
+			i++;
+			strncpy (game, argv[ i ] , 64);
+			strlower(game);
+		} 
+	}
+	
+	/* set number of threads */
+	ThreadSetDefault();
+	
+	/* ydnar: new path initialization */
+	InitPaths( &argc, argv );
+	
+	/* read compiling options */
+	for( i = 1; i < argc; i++ )
+	{
+		/* info */
+		if( !strcmp( argv[ i ], "-info" ) )
+		{
+			do_info=qtrue;
+		}
+
+		/* bsp */
+		if( !strcmp( argv[ i ], "-bsp" ) )
+		{
+			do_bsp=qtrue;
+			alt_argc=argc - i;
+			alt_argv= (char **) ( argv + i );
+			Check_BSP_Options( alt_argc, alt_argv );
+		}
+
+		/* vis */
+		if( !strcmp( argv[ i ], "-vis" ) )
+		{
+			do_vis=qtrue;
+			alt_argc=argc - i;
+			alt_argv= (char **) ( argv + i );
+			Check_VIS_Options( alt_argc, alt_argv );
+		}
+
+		/* rad */
+		if( !strcmp( argv[ i ], "-rad" ) )
+		{
+			do_rad=qtrue;
+			alt_argc=argc - i;
+			alt_argv= (char **) ( argv + i );
+			Check_RAD_Options( alt_argc, alt_argv );
+		}
+	}
+	
+	if (game[0] == 0)
+		strncpy( game, "quake2", 7);
+		
+	Sys_Printf("Game: %s\n", game);
+	
+	if ( !do_info && !do_bsp && !do_vis && !do_rad)
+		Sys_Printf("ERROR: -bsp, -vis, -light, nor -info specified.\nWhat to you want me to do?\n\n");
+	else
+	{
+		mapname=argv[argc-1];
+		
+		if (do_bsp)
+			BSP_Main();
+		if (do_vis)
+			VIS_Main();
+		if (do_rad)
+			RAD_Main();
+		if (do_info)
+			BSPInfo();
+		
+	}
+	
+	/* emit time */
+	end = I_FloatTime();
+	total_time = (int) (end-start);
+	Sys_Printf("\nTotal Time: ");
+	if ( total_time > 59 )
+		Sys_Printf("%d Minutes ", total_time/60 );
+	Sys_Printf( "%d Seconds\n", total_time%60 );
+	
+	/* shut down connection */
+	Broadcast_Shutdown();
+	
+	/* return any error code */
+	return r;
+}
diff --git a/tools/quake2/q2map/map.c b/tools/quake2/q2map/map.c
index ac3be9d8..05e9df36 100644
--- a/tools/quake2/q2map/map.c
+++ b/tools/quake2/q2map/map.c
@@ -1,1017 +1,1017 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// map.c
-
-#include "qbsp.h"
-
-extern qboolean onlyents;
-
-int			nummapbrushes;
-mapbrush_t	mapbrushes[MAX_MAP_BRUSHES];
-
-int			nummapbrushsides;
-side_t		brushsides[MAX_MAP_SIDES];
-brush_texture_t	side_brushtextures[MAX_MAP_SIDES];
-
-int			nummapplanes;
-plane_t		mapplanes[MAX_MAP_PLANES];
-
-#define	PLANE_HASHES	1024
-plane_t		*planehash[PLANE_HASHES];
-
-vec3_t		map_mins, map_maxs;
-
-// undefine to make plane finding use linear sort
-#define	USE_HASHING
-
-void TestExpandBrushes (void);
-
-int		c_boxbevels;
-int		c_edgebevels;
-
-int		c_areaportals;
-
-int		c_clipbrushes;
-
-/*
-=============================================================================
-
-PLANE FINDING
-
-=============================================================================
-*/
-
-
-/*
-=================
-PlaneTypeForNormal
-=================
-*/
-int	PlaneTypeForNormal (vec3_t normal)
-{
-	vec_t	ax, ay, az;
-	
-// NOTE: should these have an epsilon around 1.0?		
-	if (normal[0] == 1.0 || normal[0] == -1.0)
-		return PLANE_X;
-	if (normal[1] == 1.0 || normal[1] == -1.0)
-		return PLANE_Y;
-	if (normal[2] == 1.0 || normal[2] == -1.0)
-		return PLANE_Z;
-		
-	ax = fabs(normal[0]);
-	ay = fabs(normal[1]);
-	az = fabs(normal[2]);
-	
-	if (ax >= ay && ax >= az)
-		return PLANE_ANYX;
-	if (ay >= ax && ay >= az)
-		return PLANE_ANYY;
-	return PLANE_ANYZ;
-}
-
-/*
-================
-PlaneEqual
-================
-*/
-#define	NORMAL_EPSILON	0.00001
-#define	DIST_EPSILON	0.01
-qboolean	PlaneEqual (plane_t *p, vec3_t normal, vec_t dist)
-{
-#if 1
-	if (
-	   fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON
-	&& fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON
-	&& fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON
-	&& fabs(p->dist - dist) < DIST_EPSILON )
-		return true;
-#else
-	if (p->normal[0] == normal[0]
-		&& p->normal[1] == normal[1]
-		&& p->normal[2] == normal[2]
-		&& p->dist == dist)
-		return true;
-#endif
-	return false;
-}
-
-/*
-================
-AddPlaneToHash
-================
-*/
-void	AddPlaneToHash (plane_t *p)
-{
-	int		hash;
-
-	hash = (int)fabs(p->dist) / 8;
-	hash &= (PLANE_HASHES-1);
-
-	p->hash_chain = planehash[hash];
-	planehash[hash] = p;
-}
-
-/*
-================
-CreateNewFloatPlane
-================
-*/
-int CreateNewFloatPlane (vec3_t normal, vec_t dist)
-{
-	plane_t	*p, temp;
-
-	if (VectorLength(normal) < 0.5)
-		Error ("FloatPlane: bad normal");
-	// create a new plane
-	if (nummapplanes+2 > MAX_MAP_PLANES)
-		Error ("MAX_MAP_PLANES");
-
-	p = &mapplanes[nummapplanes];
-	VectorCopy (normal, p->normal);
-	p->dist = dist;
-	p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
-
-	VectorSubtract (vec3_origin, normal, (p+1)->normal);
-	(p+1)->dist = -dist;
-
-	nummapplanes += 2;
-
-	// allways put axial planes facing positive first
-	if (p->type < 3)
-	{
-		if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
-		{
-			// flip order
-			temp = *p;
-			*p = *(p+1);
-			*(p+1) = temp;
-
-			AddPlaneToHash (p);
-			AddPlaneToHash (p+1);
-			return nummapplanes - 1;
-		}
-	}
-
-	AddPlaneToHash (p);
-	AddPlaneToHash (p+1);
-	return nummapplanes - 2;
-}
-
-/*
-==============
-SnapVector
-==============
-*/
-void	SnapVector (vec3_t normal)
-{
-	int		i;
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
-		{
-			VectorClear (normal);
-			normal[i] = 1;
-			break;
-		}
-		if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
-		{
-			VectorClear (normal);
-			normal[i] = -1;
-			break;
-		}
-	}
-}
-
-/*
-==============
-SnapPlane
-==============
-*/
-void	SnapPlane (vec3_t normal, vec_t *dist)
-{
-	SnapVector (normal);
-
-	if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON)
-		*dist = Q_rint(*dist);
-}
-
-/*
-=============
-FindFloatPlane
-
-=============
-*/
-#ifndef USE_HASHING
-int		FindFloatPlane (vec3_t normal, vec_t dist)
-{
-	int		i;
-	plane_t	*p;
-
-	SnapPlane (normal, &dist);
-	for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++)
-	{
-		if (PlaneEqual (p, normal, dist))
-			return i;
-	}
-
-	return CreateNewFloatPlane (normal, dist);
-}
-#else
-int		FindFloatPlane (vec3_t normal, vec_t dist)
-{
-	int		i;
-	plane_t	*p;
-	int		hash, h;
-
-	SnapPlane (normal, &dist);
-	hash = (int)fabs(dist) / 8;
-	hash &= (PLANE_HASHES-1);
-
-	// search the border bins as well
-	for (i=-1 ; i<=1 ; i++)
-	{
-		h = (hash+i)&(PLANE_HASHES-1);
-		for (p = planehash[h] ; p ; p=p->hash_chain)
-		{
-			if (PlaneEqual (p, normal, dist))
-				return p-mapplanes;
-		}
-	}
-
-	return CreateNewFloatPlane (normal, dist);
-}
-#endif
-
-/*
-================
-PlaneFromPoints
-================
-*/
-int PlaneFromPoints (int *p0, int *p1, int *p2)
-{
-	vec3_t	t1, t2, normal;
-	vec_t	dist;
-
-	VectorSubtract (p0, p1, t1);
-	VectorSubtract (p2, p1, t2);
-	CrossProduct (t1, t2, normal);
-	VectorNormalize (normal, normal);
-
-	dist = DotProduct (p0, normal);
-
-	return FindFloatPlane (normal, dist);
-}
-
-
-//====================================================================
-
-
-/*
-===========
-BrushContents
-===========
-*/
-int	BrushContents (mapbrush_t *b)
-{
-	int			contents;
-	side_t		*s;
-	int			i;
-	int			trans;
-
-	s = &b->original_sides[0];
-	contents = s->contents;
-	trans = texinfo[s->texinfo].flags;
-	for (i=1 ; i<b->numsides ; i++, s++)
-	{
-		s = &b->original_sides[i];
-		trans |= texinfo[s->texinfo].flags;
-		if (s->contents != contents)
-		{
-			Sys_Printf ("Entity %i, Brush %i: mixed face contents\n"
-				, b->entitynum, b->brushnum);
-			break;
-		}
-	}
-
-	// if any side is translucent, mark the contents
-	// and change solid to window
-	if ( trans & (SURF_TRANS33|SURF_TRANS66) )
-	{
-		contents |= CONTENTS_TRANSLUCENT;
-		if (contents & CONTENTS_SOLID)
-		{
-			contents &= ~CONTENTS_SOLID;
-			contents |= CONTENTS_WINDOW;
-		}
-	}
-
-	return contents;
-}
-
-
-//============================================================================
-
-/*
-=================
-AddBrushBevels
-
-Adds any additional planes necessary to allow the brush to be expanded
-against axial bounding boxes
-=================
-*/
-void AddBrushBevels (mapbrush_t *b)
-{
-	int		axis, dir;
-	int		i, j, k, l, order;
-	side_t	sidetemp;
-	brush_texture_t	tdtemp;
-	side_t	*s, *s2;
-	vec3_t	normal;
-	float	dist;
-	winding_t	*w, *w2;
-	vec3_t	vec, vec2;
-	float	d;
-
-	//
-	// add the axial planes
-	//
-	order = 0;
-	for (axis=0 ; axis <3 ; axis++)
-	{
-		for (dir=-1 ; dir <= 1 ; dir+=2, order++)
-		{
-			// see if the plane is allready present
-			for (i=0, s=b->original_sides ; i<b->numsides ; i++,s++)
-			{
-				if (mapplanes[s->planenum].normal[axis] == dir)
-					break;
-			}
-
-			if (i == b->numsides)
-			{	// add a new side
-				if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
-					Error ("MAX_MAP_BRUSHSIDES");
-				nummapbrushsides++;
-				b->numsides++;
-				VectorClear (normal);
-				normal[axis] = dir;
-				if (dir == 1)
-					dist = b->maxs[axis];
-				else
-					dist = -b->mins[axis];
-				s->planenum = FindFloatPlane (normal, dist);
-				s->texinfo = b->original_sides[0].texinfo;
-				s->contents = b->original_sides[0].contents;
-				s->bevel = true;
-				c_boxbevels++;
-			}
-
-			// if the plane is not in it canonical order, swap it
-			if (i != order)
-			{
-				sidetemp = b->original_sides[order];
-				b->original_sides[order] = b->original_sides[i];
-				b->original_sides[i] = sidetemp;
-
-				j = b->original_sides - brushsides;
-				tdtemp = side_brushtextures[j+order];
-				side_brushtextures[j+order] = side_brushtextures[j+i];
-				side_brushtextures[j+i] = tdtemp;
-			}
-		}
-	}
-
-	//
-	// add the edge bevels
-	//
-	if (b->numsides == 6)
-		return;		// pure axial
-
-	// test the non-axial plane edges
-	for (i=6 ; i<b->numsides ; i++)
-	{
-		s = b->original_sides + i;
-		w = s->winding;
-		if (!w)
-			continue;
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			k = (j+1)%w->numpoints;
-			VectorSubtract (w->p[j], w->p[k], vec);
-			if (VectorNormalize (vec, vec) < 0.5)
-				continue;
-			SnapVector (vec);
-			for (k=0 ; k<3 ; k++)
-				if ( vec[k] == -1 || vec[k] == 1)
-					break;	// axial
-			if (k != 3)
-				continue;	// only test non-axial edges
-
-			// try the six possible slanted axials from this edge
-			for (axis=0 ; axis <3 ; axis++)
-			{
-				for (dir=-1 ; dir <= 1 ; dir+=2)
-				{
-					// construct a plane
-					VectorClear (vec2);
-					vec2[axis] = dir;
-					CrossProduct (vec, vec2, normal);
-					if (VectorNormalize (normal, normal) < 0.5)
-						continue;
-					dist = DotProduct (w->p[j], normal);
-
-					// if all the points on all the sides are
-					// behind this plane, it is a proper edge bevel
-					for (k=0 ; k<b->numsides ; k++)
-					{
-						// if this plane has allready been used, skip it
-						if (PlaneEqual (&mapplanes[b->original_sides[k].planenum]
-							, normal, dist) )
-							break;
-
-						w2 = b->original_sides[k].winding;
-						if (!w2)
-							continue;
-						for (l=0 ; l<w2->numpoints ; l++)
-						{
-							d = DotProduct (w2->p[l], normal) - dist;
-							if (d > 0.1)
-								break;	// point in front
-						}
-						if (l != w2->numpoints)
-							break;
-					}
-
-					if (k != b->numsides)
-						continue;	// wasn't part of the outer hull
-					// add this plane
-					if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
-						Error ("MAX_MAP_BRUSHSIDES");
-					nummapbrushsides++;
-					s2 = &b->original_sides[b->numsides];
-					s2->planenum = FindFloatPlane (normal, dist);
-					s2->texinfo = b->original_sides[0].texinfo;
-					s2->contents = b->original_sides[0].contents;
-					s2->bevel = true;
-					c_edgebevels++;
-					b->numsides++;
-				}
-			}
-		}
-	}
-}
-
-
-/*
-================
-MakeBrushWindings
-
-makes basewindigs for sides and mins / maxs for the brush
-================
-*/
-qboolean MakeBrushWindings (mapbrush_t *ob)
-{
-	int			i, j;
-	winding_t	*w;
-	side_t		*side;
-	plane_t		*plane;
-
-	ClearBounds (ob->mins, ob->maxs);
-
-	for (i=0 ; i<ob->numsides ; i++)
-	{
-		plane = &mapplanes[ob->original_sides[i].planenum];
-		w = BaseWindingForPlane (plane->normal, plane->dist);
-		for (j=0 ; j<ob->numsides && w; j++)
-		{
-			if (i == j)
-				continue;
-			if (ob->original_sides[j].bevel)
-				continue;
-			plane = &mapplanes[ob->original_sides[j].planenum^1];
-			ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
-		}
-
-		side = &ob->original_sides[i];
-		side->winding = w;
-		if (w)
-		{
-			side->visible = true;
-			for (j=0 ; j<w->numpoints ; j++)
-				AddPointToBounds (w->p[j], ob->mins, ob->maxs);
-		}
-	}
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if (ob->mins[0] < -4096 || ob->maxs[0] > 4096)
-			Sys_Printf ("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
-		if (ob->mins[0] > 4096 || ob->maxs[0] < -4096)
-			Sys_Printf ("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
-	}
-
-	return true;
-}
-
-
-/*
-=================
-ParseBrush
-=================
-*/
-void ParseBrush (entity_t *mapent)
-{
-	mapbrush_t		*b;
-	int			i,j, k;
-	int			mt;
-	side_t		*side, *s2;
-	int			planenum;
-	brush_texture_t	td;
-	int			planepts[3][3];
-
-	if (nummapbrushes == MAX_MAP_BRUSHES)
-		Error ("nummapbrushes == MAX_MAP_BRUSHES");
-
-	b = &mapbrushes[nummapbrushes];
-	b->original_sides = &brushsides[nummapbrushsides];
-	b->entitynum = num_entities-1;
-	b->brushnum = nummapbrushes - mapent->firstbrush;
-
-	do
-	{
-		if (!GetToken (true))
-			break;
-		if (!strcmp (token, "}") )
-			break;
-
-		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
-			Error ("MAX_MAP_BRUSHSIDES");
-		side = &brushsides[nummapbrushsides];
-
-		// read the three point plane definition
-		for (i=0 ; i<3 ; i++)
-		{
-			if (i != 0)
-				GetToken (true);
-			if (strcmp (token, "(") )
-				Error ("parsing brush");
-			
-			for (j=0 ; j<3 ; j++)
-			{
-				GetToken (false);
-				planepts[i][j] = atoi(token);
-			}
-			
-			GetToken (false);
-			if (strcmp (token, ")") )
-				Error ("parsing brush");
-				
-		}
-
-
-		//
-		// read the texturedef
-		//
-		GetToken (false);
-		strcpy (td.name, token);
-
-		GetToken (false);
-		td.shift[0] = atoi(token);
-		GetToken (false);
-		td.shift[1] = atoi(token);
-		GetToken (false);
-		td.rotate = atoi(token);	
-		GetToken (false);
-		td.scale[0] = atof(token);
-		GetToken (false);
-		td.scale[1] = atof(token);
-
-		// find default flags and values
-		mt = FindMiptex (td.name);
-		td.flags = textureref[mt].flags;
-		td.value = textureref[mt].value;
-		side->contents = textureref[mt].contents;
-		side->surf = td.flags = textureref[mt].flags;
-
-		if (TokenAvailable())
-		{
-			GetToken (false);
-			side->contents = atoi(token);
-			GetToken (false);
-			side->surf = td.flags = atoi(token);
-			GetToken (false);
-			td.value = atoi(token);
-		}
-
-		// translucent objects are automatically classified as detail
-		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
-			side->contents |= CONTENTS_DETAIL;
-		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
-			side->contents |= CONTENTS_DETAIL;
-		if (fulldetail)
-			side->contents &= ~CONTENTS_DETAIL;
-		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
-			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
-			side->contents |= CONTENTS_SOLID;
-
-		// hints and skips are never detail, and have no content
-		if (side->surf & (SURF_HINT|SURF_SKIP) )
-		{
-			side->contents = 0;
-			side->surf &= ~CONTENTS_DETAIL;
-		}
-
-
-		//
-		// find the plane number
-		//
-		planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
-		if (planenum == -1)
-		{
-			Sys_Printf ("Entity %i, Brush %i: plane with no normal\n"
-				, b->entitynum, b->brushnum);
-			continue;
-		}
-
-		//
-		// see if the plane has been used already
-		//
-		for (k=0 ; k<b->numsides ; k++)
-		{
-			s2 = b->original_sides + k;
-			if (s2->planenum == planenum)
-			{
-				Sys_Printf ("Entity %i, Brush %i: duplicate plane\n"
-					, b->entitynum, b->brushnum);
-				break;
-			}
-			if ( s2->planenum == (planenum^1) )
-			{
-				Sys_Printf ("Entity %i, Brush %i: mirrored plane\n"
-					, b->entitynum, b->brushnum);
-				break;
-			}
-		}
-		if (k != b->numsides)
-			continue;		// duplicated
-
-		//
-		// keep this side
-		//
-
-		side = b->original_sides + b->numsides;
-		side->planenum = planenum;
-		side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
-			&td, vec3_origin);
-
-		// save the td off in case there is an origin brush and we
-		// have to recalculate the texinfo
-		side_brushtextures[nummapbrushsides] = td;
-
-		nummapbrushsides++;
-		b->numsides++;
-	} while (1);
-
-	// get the content for the entire brush
-	b->contents = BrushContents (b);
-
-	// allow detail brushes to be removed 
-	if (nodetail && (b->contents & CONTENTS_DETAIL) )
-	{
-		b->numsides = 0;
-		return;
-	}
-
-	// allow water brushes to be removed
-	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
-	{
-		b->numsides = 0;
-		return;
-	}
-
-	// create windings for sides and bounds for brush
-	MakeBrushWindings (b);
-
-	// brushes that will not be visible at all will never be
-	// used as bsp splitters
-	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
-	{
-		c_clipbrushes++;
-		for (i=0 ; i<b->numsides ; i++)
-			b->original_sides[i].texinfo = TEXINFO_NODE;
-	}
-
-	//
-	// origin brushes are removed, but they set
-	// the rotation origin for the rest of the brushes
-	// in the entity.  After the entire entity is parsed,
-	// the planenums and texinfos will be adjusted for
-	// the origin brush
-	//
-	if (b->contents & CONTENTS_ORIGIN)
-	{
-		char	string[32];
-		vec3_t	origin;
-
-		if (num_entities == 1)
-		{
-			Error ("Entity %i, Brush %i: origin brushes not allowed in world"
-				, b->entitynum, b->brushnum);
-			return;
-		}
-
-		VectorAdd (b->mins, b->maxs, origin);
-		VectorScale (origin, 0.5, origin);
-
-		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
-		SetKeyValue (&entities[b->entitynum], "origin", string);
-
-		VectorCopy (origin, entities[b->entitynum].origin);
-
-		// don't keep this brush
-		b->numsides = 0;
-
-		return;
-	}
-
-	AddBrushBevels (b);
-
-	nummapbrushes++;
-	mapent->numbrushes++;		
-}
-
-/*
-================
-MoveBrushesToWorld
-
-Takes all of the brushes from the current entity and
-adds them to the world's brush list.
-
-Used by func_group and func_areaportal
-================
-*/
-void MoveBrushesToWorld (entity_t *mapent)
-{
-	int			newbrushes;
-	int			worldbrushes;
-	mapbrush_t	*temp;
-	int			i;
-
-	// this is pretty gross, because the brushes are expected to be
-	// in linear order for each entity
-
-	newbrushes = mapent->numbrushes;
-	worldbrushes = entities[0].numbrushes;
-
-	temp = malloc(newbrushes*sizeof(mapbrush_t));
-	memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
-
-#if	0		// let them keep their original brush numbers
-	for (i=0 ; i<newbrushes ; i++)
-		temp[i].entitynum = 0;
-#endif
-
-	// make space to move the brushes (overlapped copy)
-	memmove (mapbrushes + worldbrushes + newbrushes,
-		mapbrushes + worldbrushes,
-		sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
-
-	// copy the new brushes down
-	memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
-
-	// fix up indexes
-	entities[0].numbrushes += newbrushes;
-	for (i=1 ; i<num_entities ; i++)
-		entities[i].firstbrush += newbrushes;
-	free (temp);
-
-	mapent->numbrushes = 0;
-}
-
-/*
-================
-ParseMapEntity
-================
-*/
-qboolean	ParseMapEntity (void)
-{
-	entity_t	*mapent;
-	epair_t		*e;
-	side_t		*s;
-	int			i, j;
-	int			startbrush, startsides;
-	vec_t		newdist;
-	mapbrush_t	*b;
-
-	if (!GetToken (true))
-		return false;
-
-	if (strcmp (token, "{") )
-		Error ("ParseEntity: { not found");
-	
-	if (num_entities == MAX_MAP_ENTITIES)
-		Error ("num_entities == MAX_MAP_ENTITIES");
-
-	startbrush = nummapbrushes;
-	startsides = nummapbrushsides;
-
-	mapent = &entities[num_entities];
-	num_entities++;
-	memset (mapent, 0, sizeof(*mapent));
-	mapent->firstbrush = nummapbrushes;
-	mapent->numbrushes = 0;
-//	mapent->portalareas[0] = -1;
-//	mapent->portalareas[1] = -1;
-
-	do
-	{
-		if (!GetToken (true))
-			Error ("ParseEntity: EOF without closing brace");
-		if (!strcmp (token, "}") )
-			break;
-		if (!strcmp (token, "{") )
-			ParseBrush (mapent);
-		else
-		{
-			e = ParseEpair ();
-			e->next = mapent->epairs;
-			mapent->epairs = e;
-		}
-	} while (1);
-
-	GetVectorForKey (mapent, "origin", mapent->origin);
-
-	//
-	// if there was an origin brush, offset all of the planes and texinfo
-	//
-	if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
-	{
-		for (i=0 ; i<mapent->numbrushes ; i++)
-		{
-			b = &mapbrushes[mapent->firstbrush + i];
-			for (j=0 ; j<b->numsides ; j++)
-			{
-				s = &b->original_sides[j];
-				newdist = mapplanes[s->planenum].dist -
-					DotProduct (mapplanes[s->planenum].normal, mapent->origin);
-				s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
-				s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
-					&side_brushtextures[s-brushsides], mapent->origin);
-			}
-			MakeBrushWindings (b);
-		}
-	}
-
-	// group entities are just for editor convenience
-	// toss all brushes into the world entity
-	if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
-	{
-		MoveBrushesToWorld (mapent);
-		mapent->numbrushes = 0;
-		return true;
-	}
-
-	// areaportal entities move their brushes, but don't eliminate
-	// the entity
-	if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
-	{
-		char	str[128];
-
-		if (mapent->numbrushes != 1)
-			Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
-
-		b = &mapbrushes[nummapbrushes-1];
-		b->contents = CONTENTS_AREAPORTAL;
-		c_areaportals++;
-		mapent->areaportalnum = c_areaportals;
-		// set the portal number as "style"
-		sprintf (str, "%i", c_areaportals);
-		SetKeyValue (mapent, "style", str);
-		MoveBrushesToWorld (mapent);
-		return true;
-	}
-
-	return true;
-}
-
-//===================================================================
-
-/*
-================
-LoadMapFile
-================
-*/
-void LoadMapFile (char *filename)
-{		
-	int		i;
-
-	Sys_FPrintf( SYS_VRB, "--- LoadMapFile ---\n");
-
-	LoadScriptFile (filename);
-
-	nummapbrushsides = 0;
-	num_entities = 0;
-	
-	while (ParseMapEntity ())
-	{
-	}
-
-	ClearBounds (map_mins, map_maxs);
-	for (i=0 ; i<entities[0].numbrushes ; i++)
-	{
-		if (mapbrushes[i].mins[0] > 4096)
-			continue;	// no valid points
-		AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
-		AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
-	}
-
-	Sys_FPrintf( SYS_VRB, "%5i brushes\n", nummapbrushes);
-	Sys_FPrintf( SYS_VRB, "%5i clipbrushes\n", c_clipbrushes);
-	Sys_FPrintf( SYS_VRB, "%5i total sides\n", nummapbrushsides);
-	Sys_FPrintf( SYS_VRB, "%5i boxbevels\n", c_boxbevels);
-	Sys_FPrintf( SYS_VRB, "%5i edgebevels\n", c_edgebevels);
-	Sys_FPrintf( SYS_VRB, "%5i entities\n", num_entities);
-	Sys_FPrintf( SYS_VRB, "%5i planes\n", nummapplanes);
-	Sys_FPrintf( SYS_VRB, "%5i areaportals\n", c_areaportals);
-	Sys_FPrintf( SYS_VRB, "size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2],
-		map_maxs[0],map_maxs[1],map_maxs[2]);
-
-//	TestExpandBrushes ();
-}
-
-
-//====================================================================
-
-
-/*
-================
-TestExpandBrushes
-
-Expands all the brush planes and saves a new map out
-================
-*/
-void TestExpandBrushes (void)
-{
-	FILE	*f;
-	side_t	*s;
-	int		i, j, bn;
-	winding_t	*w;
-	char	*name = "expanded.map";
-	mapbrush_t	*brush;
-	vec_t	dist;
-
-	Sys_Printf ("writing %s\n", name);
-	f = fopen (name, "wb");
-	if (!f)
-		Error ("Can't write %s\b", name);
-
-	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
-
-	for (bn=0 ; bn<nummapbrushes ; bn++)
-	{
-		brush = &mapbrushes[bn];
-		fprintf (f, "{\n");
-		for (i=0 ; i<brush->numsides ; i++)
-		{
-			s = brush->original_sides + i;
-			dist = mapplanes[s->planenum].dist;
-			for (j=0 ; j<3 ; j++)
-				dist += fabs( 16 * mapplanes[s->planenum].normal[j] );
-
-			w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist);
-
-			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
-			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
-			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
-
-			fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
-			FreeWinding (w);
-		}
-		fprintf (f, "}\n");
-	}
-	fprintf (f, "}\n");
-
-	fclose (f);
-
-	Error ("can't proceed after expanding brushes");
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// map.c
+
+#include "qbsp.h"
+
+extern qboolean onlyents;
+
+int			nummapbrushes;
+mapbrush_t	mapbrushes[MAX_MAP_BRUSHES];
+
+int			nummapbrushsides;
+side_t		brushsides[MAX_MAP_SIDES];
+brush_texture_t	side_brushtextures[MAX_MAP_SIDES];
+
+int			nummapplanes;
+plane_t		mapplanes[MAX_MAP_PLANES];
+
+#define	PLANE_HASHES	1024
+plane_t		*planehash[PLANE_HASHES];
+
+vec3_t		map_mins, map_maxs;
+
+// undefine to make plane finding use linear sort
+#define	USE_HASHING
+
+void TestExpandBrushes (void);
+
+int		c_boxbevels;
+int		c_edgebevels;
+
+int		c_areaportals;
+
+int		c_clipbrushes;
+
+/*
+=============================================================================
+
+PLANE FINDING
+
+=============================================================================
+*/
+
+
+/*
+=================
+PlaneTypeForNormal
+=================
+*/
+int	PlaneTypeForNormal (vec3_t normal)
+{
+	vec_t	ax, ay, az;
+	
+// NOTE: should these have an epsilon around 1.0?		
+	if (normal[0] == 1.0 || normal[0] == -1.0)
+		return PLANE_X;
+	if (normal[1] == 1.0 || normal[1] == -1.0)
+		return PLANE_Y;
+	if (normal[2] == 1.0 || normal[2] == -1.0)
+		return PLANE_Z;
+		
+	ax = fabs(normal[0]);
+	ay = fabs(normal[1]);
+	az = fabs(normal[2]);
+	
+	if (ax >= ay && ax >= az)
+		return PLANE_ANYX;
+	if (ay >= ax && ay >= az)
+		return PLANE_ANYY;
+	return PLANE_ANYZ;
+}
+
+/*
+================
+PlaneEqual
+================
+*/
+#define	NORMAL_EPSILON	0.00001
+#define	DIST_EPSILON	0.01
+qboolean	PlaneEqual (plane_t *p, vec3_t normal, vec_t dist)
+{
+#if 1
+	if (
+	   fabs(p->normal[0] - normal[0]) < NORMAL_EPSILON
+	&& fabs(p->normal[1] - normal[1]) < NORMAL_EPSILON
+	&& fabs(p->normal[2] - normal[2]) < NORMAL_EPSILON
+	&& fabs(p->dist - dist) < DIST_EPSILON )
+		return true;
+#else
+	if (p->normal[0] == normal[0]
+		&& p->normal[1] == normal[1]
+		&& p->normal[2] == normal[2]
+		&& p->dist == dist)
+		return true;
+#endif
+	return false;
+}
+
+/*
+================
+AddPlaneToHash
+================
+*/
+void	AddPlaneToHash (plane_t *p)
+{
+	int		hash;
+
+	hash = (int)fabs(p->dist) / 8;
+	hash &= (PLANE_HASHES-1);
+
+	p->hash_chain = planehash[hash];
+	planehash[hash] = p;
+}
+
+/*
+================
+CreateNewFloatPlane
+================
+*/
+int CreateNewFloatPlane (vec3_t normal, vec_t dist)
+{
+	plane_t	*p, temp;
+
+	if (VectorLength(normal) < 0.5)
+		Error ("FloatPlane: bad normal");
+	// create a new plane
+	if (nummapplanes+2 > MAX_MAP_PLANES)
+		Error ("MAX_MAP_PLANES");
+
+	p = &mapplanes[nummapplanes];
+	VectorCopy (normal, p->normal);
+	p->dist = dist;
+	p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
+
+	VectorSubtract (vec3_origin, normal, (p+1)->normal);
+	(p+1)->dist = -dist;
+
+	nummapplanes += 2;
+
+	// allways put axial planes facing positive first
+	if (p->type < 3)
+	{
+		if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
+		{
+			// flip order
+			temp = *p;
+			*p = *(p+1);
+			*(p+1) = temp;
+
+			AddPlaneToHash (p);
+			AddPlaneToHash (p+1);
+			return nummapplanes - 1;
+		}
+	}
+
+	AddPlaneToHash (p);
+	AddPlaneToHash (p+1);
+	return nummapplanes - 2;
+}
+
+/*
+==============
+SnapVector
+==============
+*/
+void	SnapVector (vec3_t normal)
+{
+	int		i;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if ( fabs(normal[i] - 1) < NORMAL_EPSILON )
+		{
+			VectorClear (normal);
+			normal[i] = 1;
+			break;
+		}
+		if ( fabs(normal[i] - -1) < NORMAL_EPSILON )
+		{
+			VectorClear (normal);
+			normal[i] = -1;
+			break;
+		}
+	}
+}
+
+/*
+==============
+SnapPlane
+==============
+*/
+void	SnapPlane (vec3_t normal, vec_t *dist)
+{
+	SnapVector (normal);
+
+	if (fabs(*dist-Q_rint(*dist)) < DIST_EPSILON)
+		*dist = Q_rint(*dist);
+}
+
+/*
+=============
+FindFloatPlane
+
+=============
+*/
+#ifndef USE_HASHING
+int		FindFloatPlane (vec3_t normal, vec_t dist)
+{
+	int		i;
+	plane_t	*p;
+
+	SnapPlane (normal, &dist);
+	for (i=0, p=mapplanes ; i<nummapplanes ; i++, p++)
+	{
+		if (PlaneEqual (p, normal, dist))
+			return i;
+	}
+
+	return CreateNewFloatPlane (normal, dist);
+}
+#else
+int		FindFloatPlane (vec3_t normal, vec_t dist)
+{
+	int		i;
+	plane_t	*p;
+	int		hash, h;
+
+	SnapPlane (normal, &dist);
+	hash = (int)fabs(dist) / 8;
+	hash &= (PLANE_HASHES-1);
+
+	// search the border bins as well
+	for (i=-1 ; i<=1 ; i++)
+	{
+		h = (hash+i)&(PLANE_HASHES-1);
+		for (p = planehash[h] ; p ; p=p->hash_chain)
+		{
+			if (PlaneEqual (p, normal, dist))
+				return p-mapplanes;
+		}
+	}
+
+	return CreateNewFloatPlane (normal, dist);
+}
+#endif
+
+/*
+================
+PlaneFromPoints
+================
+*/
+int PlaneFromPoints (int *p0, int *p1, int *p2)
+{
+	vec3_t	t1, t2, normal;
+	vec_t	dist;
+
+	VectorSubtract (p0, p1, t1);
+	VectorSubtract (p2, p1, t2);
+	CrossProduct (t1, t2, normal);
+	VectorNormalize (normal, normal);
+
+	dist = DotProduct (p0, normal);
+
+	return FindFloatPlane (normal, dist);
+}
+
+
+//====================================================================
+
+
+/*
+===========
+BrushContents
+===========
+*/
+int	BrushContents (mapbrush_t *b)
+{
+	int			contents;
+	side_t		*s;
+	int			i;
+	int			trans;
+
+	s = &b->original_sides[0];
+	contents = s->contents;
+	trans = texinfo[s->texinfo].flags;
+	for (i=1 ; i<b->numsides ; i++, s++)
+	{
+		s = &b->original_sides[i];
+		trans |= texinfo[s->texinfo].flags;
+		if (s->contents != contents)
+		{
+			Sys_Printf ("Entity %i, Brush %i: mixed face contents\n"
+				, b->entitynum, b->brushnum);
+			break;
+		}
+	}
+
+	// if any side is translucent, mark the contents
+	// and change solid to window
+	if ( trans & (SURF_TRANS33|SURF_TRANS66) )
+	{
+		contents |= CONTENTS_TRANSLUCENT;
+		if (contents & CONTENTS_SOLID)
+		{
+			contents &= ~CONTENTS_SOLID;
+			contents |= CONTENTS_WINDOW;
+		}
+	}
+
+	return contents;
+}
+
+
+//============================================================================
+
+/*
+=================
+AddBrushBevels
+
+Adds any additional planes necessary to allow the brush to be expanded
+against axial bounding boxes
+=================
+*/
+void AddBrushBevels (mapbrush_t *b)
+{
+	int		axis, dir;
+	int		i, j, k, l, order;
+	side_t	sidetemp;
+	brush_texture_t	tdtemp;
+	side_t	*s, *s2;
+	vec3_t	normal;
+	float	dist;
+	winding_t	*w, *w2;
+	vec3_t	vec, vec2;
+	float	d;
+
+	//
+	// add the axial planes
+	//
+	order = 0;
+	for (axis=0 ; axis <3 ; axis++)
+	{
+		for (dir=-1 ; dir <= 1 ; dir+=2, order++)
+		{
+			// see if the plane is allready present
+			for (i=0, s=b->original_sides ; i<b->numsides ; i++,s++)
+			{
+				if (mapplanes[s->planenum].normal[axis] == dir)
+					break;
+			}
+
+			if (i == b->numsides)
+			{	// add a new side
+				if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
+					Error ("MAX_MAP_BRUSHSIDES");
+				nummapbrushsides++;
+				b->numsides++;
+				VectorClear (normal);
+				normal[axis] = dir;
+				if (dir == 1)
+					dist = b->maxs[axis];
+				else
+					dist = -b->mins[axis];
+				s->planenum = FindFloatPlane (normal, dist);
+				s->texinfo = b->original_sides[0].texinfo;
+				s->contents = b->original_sides[0].contents;
+				s->bevel = true;
+				c_boxbevels++;
+			}
+
+			// if the plane is not in it canonical order, swap it
+			if (i != order)
+			{
+				sidetemp = b->original_sides[order];
+				b->original_sides[order] = b->original_sides[i];
+				b->original_sides[i] = sidetemp;
+
+				j = b->original_sides - brushsides;
+				tdtemp = side_brushtextures[j+order];
+				side_brushtextures[j+order] = side_brushtextures[j+i];
+				side_brushtextures[j+i] = tdtemp;
+			}
+		}
+	}
+
+	//
+	// add the edge bevels
+	//
+	if (b->numsides == 6)
+		return;		// pure axial
+
+	// test the non-axial plane edges
+	for (i=6 ; i<b->numsides ; i++)
+	{
+		s = b->original_sides + i;
+		w = s->winding;
+		if (!w)
+			continue;
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			k = (j+1)%w->numpoints;
+			VectorSubtract (w->p[j], w->p[k], vec);
+			if (VectorNormalize (vec, vec) < 0.5)
+				continue;
+			SnapVector (vec);
+			for (k=0 ; k<3 ; k++)
+				if ( vec[k] == -1 || vec[k] == 1)
+					break;	// axial
+			if (k != 3)
+				continue;	// only test non-axial edges
+
+			// try the six possible slanted axials from this edge
+			for (axis=0 ; axis <3 ; axis++)
+			{
+				for (dir=-1 ; dir <= 1 ; dir+=2)
+				{
+					// construct a plane
+					VectorClear (vec2);
+					vec2[axis] = dir;
+					CrossProduct (vec, vec2, normal);
+					if (VectorNormalize (normal, normal) < 0.5)
+						continue;
+					dist = DotProduct (w->p[j], normal);
+
+					// if all the points on all the sides are
+					// behind this plane, it is a proper edge bevel
+					for (k=0 ; k<b->numsides ; k++)
+					{
+						// if this plane has allready been used, skip it
+						if (PlaneEqual (&mapplanes[b->original_sides[k].planenum]
+							, normal, dist) )
+							break;
+
+						w2 = b->original_sides[k].winding;
+						if (!w2)
+							continue;
+						for (l=0 ; l<w2->numpoints ; l++)
+						{
+							d = DotProduct (w2->p[l], normal) - dist;
+							if (d > 0.1)
+								break;	// point in front
+						}
+						if (l != w2->numpoints)
+							break;
+					}
+
+					if (k != b->numsides)
+						continue;	// wasn't part of the outer hull
+					// add this plane
+					if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
+						Error ("MAX_MAP_BRUSHSIDES");
+					nummapbrushsides++;
+					s2 = &b->original_sides[b->numsides];
+					s2->planenum = FindFloatPlane (normal, dist);
+					s2->texinfo = b->original_sides[0].texinfo;
+					s2->contents = b->original_sides[0].contents;
+					s2->bevel = true;
+					c_edgebevels++;
+					b->numsides++;
+				}
+			}
+		}
+	}
+}
+
+
+/*
+================
+MakeBrushWindings
+
+makes basewindigs for sides and mins / maxs for the brush
+================
+*/
+qboolean MakeBrushWindings (mapbrush_t *ob)
+{
+	int			i, j;
+	winding_t	*w;
+	side_t		*side;
+	plane_t		*plane;
+
+	ClearBounds (ob->mins, ob->maxs);
+
+	for (i=0 ; i<ob->numsides ; i++)
+	{
+		plane = &mapplanes[ob->original_sides[i].planenum];
+		w = BaseWindingForPlane (plane->normal, plane->dist);
+		for (j=0 ; j<ob->numsides && w; j++)
+		{
+			if (i == j)
+				continue;
+			if (ob->original_sides[j].bevel)
+				continue;
+			plane = &mapplanes[ob->original_sides[j].planenum^1];
+			ChopWindingInPlace (&w, plane->normal, plane->dist, 0); //CLIP_EPSILON);
+		}
+
+		side = &ob->original_sides[i];
+		side->winding = w;
+		if (w)
+		{
+			side->visible = true;
+			for (j=0 ; j<w->numpoints ; j++)
+				AddPointToBounds (w->p[j], ob->mins, ob->maxs);
+		}
+	}
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (ob->mins[0] < -4096 || ob->maxs[0] > 4096)
+			Sys_Printf ("entity %i, brush %i: bounds out of range\n", ob->entitynum, ob->brushnum);
+		if (ob->mins[0] > 4096 || ob->maxs[0] < -4096)
+			Sys_Printf ("entity %i, brush %i: no visible sides on brush\n", ob->entitynum, ob->brushnum);
+	}
+
+	return true;
+}
+
+
+/*
+=================
+ParseBrush
+=================
+*/
+void ParseBrush (entity_t *mapent)
+{
+	mapbrush_t		*b;
+	int			i,j, k;
+	int			mt;
+	side_t		*side, *s2;
+	int			planenum;
+	brush_texture_t	td;
+	int			planepts[3][3];
+
+	if (nummapbrushes == MAX_MAP_BRUSHES)
+		Error ("nummapbrushes == MAX_MAP_BRUSHES");
+
+	b = &mapbrushes[nummapbrushes];
+	b->original_sides = &brushsides[nummapbrushsides];
+	b->entitynum = num_entities-1;
+	b->brushnum = nummapbrushes - mapent->firstbrush;
+
+	do
+	{
+		if (!GetToken (true))
+			break;
+		if (!strcmp (token, "}") )
+			break;
+
+		if (nummapbrushsides == MAX_MAP_BRUSHSIDES)
+			Error ("MAX_MAP_BRUSHSIDES");
+		side = &brushsides[nummapbrushsides];
+
+		// read the three point plane definition
+		for (i=0 ; i<3 ; i++)
+		{
+			if (i != 0)
+				GetToken (true);
+			if (strcmp (token, "(") )
+				Error ("parsing brush");
+			
+			for (j=0 ; j<3 ; j++)
+			{
+				GetToken (false);
+				planepts[i][j] = atoi(token);
+			}
+			
+			GetToken (false);
+			if (strcmp (token, ")") )
+				Error ("parsing brush");
+				
+		}
+
+
+		//
+		// read the texturedef
+		//
+		GetToken (false);
+		strcpy (td.name, token);
+
+		GetToken (false);
+		td.shift[0] = atoi(token);
+		GetToken (false);
+		td.shift[1] = atoi(token);
+		GetToken (false);
+		td.rotate = atoi(token);	
+		GetToken (false);
+		td.scale[0] = atof(token);
+		GetToken (false);
+		td.scale[1] = atof(token);
+
+		// find default flags and values
+		mt = FindMiptex (td.name);
+		td.flags = textureref[mt].flags;
+		td.value = textureref[mt].value;
+		side->contents = textureref[mt].contents;
+		side->surf = td.flags = textureref[mt].flags;
+
+		if (TokenAvailable())
+		{
+			GetToken (false);
+			side->contents = atoi(token);
+			GetToken (false);
+			side->surf = td.flags = atoi(token);
+			GetToken (false);
+			td.value = atoi(token);
+		}
+
+		// translucent objects are automatically classified as detail
+		if (side->surf & (SURF_TRANS33|SURF_TRANS66) )
+			side->contents |= CONTENTS_DETAIL;
+		if (side->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
+			side->contents |= CONTENTS_DETAIL;
+		if (fulldetail)
+			side->contents &= ~CONTENTS_DETAIL;
+		if (!(side->contents & ((LAST_VISIBLE_CONTENTS-1) 
+			| CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP|CONTENTS_MIST)  ) )
+			side->contents |= CONTENTS_SOLID;
+
+		// hints and skips are never detail, and have no content
+		if (side->surf & (SURF_HINT|SURF_SKIP) )
+		{
+			side->contents = 0;
+			side->surf &= ~CONTENTS_DETAIL;
+		}
+
+
+		//
+		// find the plane number
+		//
+		planenum = PlaneFromPoints (planepts[0], planepts[1], planepts[2]);
+		if (planenum == -1)
+		{
+			Sys_Printf ("Entity %i, Brush %i: plane with no normal\n"
+				, b->entitynum, b->brushnum);
+			continue;
+		}
+
+		//
+		// see if the plane has been used already
+		//
+		for (k=0 ; k<b->numsides ; k++)
+		{
+			s2 = b->original_sides + k;
+			if (s2->planenum == planenum)
+			{
+				Sys_Printf ("Entity %i, Brush %i: duplicate plane\n"
+					, b->entitynum, b->brushnum);
+				break;
+			}
+			if ( s2->planenum == (planenum^1) )
+			{
+				Sys_Printf ("Entity %i, Brush %i: mirrored plane\n"
+					, b->entitynum, b->brushnum);
+				break;
+			}
+		}
+		if (k != b->numsides)
+			continue;		// duplicated
+
+		//
+		// keep this side
+		//
+
+		side = b->original_sides + b->numsides;
+		side->planenum = planenum;
+		side->texinfo = TexinfoForBrushTexture (&mapplanes[planenum],
+			&td, vec3_origin);
+
+		// save the td off in case there is an origin brush and we
+		// have to recalculate the texinfo
+		side_brushtextures[nummapbrushsides] = td;
+
+		nummapbrushsides++;
+		b->numsides++;
+	} while (1);
+
+	// get the content for the entire brush
+	b->contents = BrushContents (b);
+
+	// allow detail brushes to be removed 
+	if (nodetail && (b->contents & CONTENTS_DETAIL) )
+	{
+		b->numsides = 0;
+		return;
+	}
+
+	// allow water brushes to be removed
+	if (nowater && (b->contents & (CONTENTS_LAVA | CONTENTS_SLIME | CONTENTS_WATER)) )
+	{
+		b->numsides = 0;
+		return;
+	}
+
+	// create windings for sides and bounds for brush
+	MakeBrushWindings (b);
+
+	// brushes that will not be visible at all will never be
+	// used as bsp splitters
+	if (b->contents & (CONTENTS_PLAYERCLIP|CONTENTS_MONSTERCLIP) )
+	{
+		c_clipbrushes++;
+		for (i=0 ; i<b->numsides ; i++)
+			b->original_sides[i].texinfo = TEXINFO_NODE;
+	}
+
+	//
+	// origin brushes are removed, but they set
+	// the rotation origin for the rest of the brushes
+	// in the entity.  After the entire entity is parsed,
+	// the planenums and texinfos will be adjusted for
+	// the origin brush
+	//
+	if (b->contents & CONTENTS_ORIGIN)
+	{
+		char	string[32];
+		vec3_t	origin;
+
+		if (num_entities == 1)
+		{
+			Error ("Entity %i, Brush %i: origin brushes not allowed in world"
+				, b->entitynum, b->brushnum);
+			return;
+		}
+
+		VectorAdd (b->mins, b->maxs, origin);
+		VectorScale (origin, 0.5, origin);
+
+		sprintf (string, "%i %i %i", (int)origin[0], (int)origin[1], (int)origin[2]);
+		SetKeyValue (&entities[b->entitynum], "origin", string);
+
+		VectorCopy (origin, entities[b->entitynum].origin);
+
+		// don't keep this brush
+		b->numsides = 0;
+
+		return;
+	}
+
+	AddBrushBevels (b);
+
+	nummapbrushes++;
+	mapent->numbrushes++;		
+}
+
+/*
+================
+MoveBrushesToWorld
+
+Takes all of the brushes from the current entity and
+adds them to the world's brush list.
+
+Used by func_group and func_areaportal
+================
+*/
+void MoveBrushesToWorld (entity_t *mapent)
+{
+	int			newbrushes;
+	int			worldbrushes;
+	mapbrush_t	*temp;
+	int			i;
+
+	// this is pretty gross, because the brushes are expected to be
+	// in linear order for each entity
+
+	newbrushes = mapent->numbrushes;
+	worldbrushes = entities[0].numbrushes;
+
+	temp = malloc(newbrushes*sizeof(mapbrush_t));
+	memcpy (temp, mapbrushes + mapent->firstbrush, newbrushes*sizeof(mapbrush_t));
+
+#if	0		// let them keep their original brush numbers
+	for (i=0 ; i<newbrushes ; i++)
+		temp[i].entitynum = 0;
+#endif
+
+	// make space to move the brushes (overlapped copy)
+	memmove (mapbrushes + worldbrushes + newbrushes,
+		mapbrushes + worldbrushes,
+		sizeof(mapbrush_t) * (nummapbrushes - worldbrushes - newbrushes) );
+
+	// copy the new brushes down
+	memcpy (mapbrushes + worldbrushes, temp, sizeof(mapbrush_t) * newbrushes);
+
+	// fix up indexes
+	entities[0].numbrushes += newbrushes;
+	for (i=1 ; i<num_entities ; i++)
+		entities[i].firstbrush += newbrushes;
+	free (temp);
+
+	mapent->numbrushes = 0;
+}
+
+/*
+================
+ParseMapEntity
+================
+*/
+qboolean	ParseMapEntity (void)
+{
+	entity_t	*mapent;
+	epair_t		*e;
+	side_t		*s;
+	int			i, j;
+	int			startbrush, startsides;
+	vec_t		newdist;
+	mapbrush_t	*b;
+
+	if (!GetToken (true))
+		return false;
+
+	if (strcmp (token, "{") )
+		Error ("ParseEntity: { not found");
+	
+	if (num_entities == MAX_MAP_ENTITIES)
+		Error ("num_entities == MAX_MAP_ENTITIES");
+
+	startbrush = nummapbrushes;
+	startsides = nummapbrushsides;
+
+	mapent = &entities[num_entities];
+	num_entities++;
+	memset (mapent, 0, sizeof(*mapent));
+	mapent->firstbrush = nummapbrushes;
+	mapent->numbrushes = 0;
+//	mapent->portalareas[0] = -1;
+//	mapent->portalareas[1] = -1;
+
+	do
+	{
+		if (!GetToken (true))
+			Error ("ParseEntity: EOF without closing brace");
+		if (!strcmp (token, "}") )
+			break;
+		if (!strcmp (token, "{") )
+			ParseBrush (mapent);
+		else
+		{
+			e = ParseEpair ();
+			e->next = mapent->epairs;
+			mapent->epairs = e;
+		}
+	} while (1);
+
+	GetVectorForKey (mapent, "origin", mapent->origin);
+
+	//
+	// if there was an origin brush, offset all of the planes and texinfo
+	//
+	if (mapent->origin[0] || mapent->origin[1] || mapent->origin[2])
+	{
+		for (i=0 ; i<mapent->numbrushes ; i++)
+		{
+			b = &mapbrushes[mapent->firstbrush + i];
+			for (j=0 ; j<b->numsides ; j++)
+			{
+				s = &b->original_sides[j];
+				newdist = mapplanes[s->planenum].dist -
+					DotProduct (mapplanes[s->planenum].normal, mapent->origin);
+				s->planenum = FindFloatPlane (mapplanes[s->planenum].normal, newdist);
+				s->texinfo = TexinfoForBrushTexture (&mapplanes[s->planenum],
+					&side_brushtextures[s-brushsides], mapent->origin);
+			}
+			MakeBrushWindings (b);
+		}
+	}
+
+	// group entities are just for editor convenience
+	// toss all brushes into the world entity
+	if (!strcmp ("func_group", ValueForKey (mapent, "classname")))
+	{
+		MoveBrushesToWorld (mapent);
+		mapent->numbrushes = 0;
+		return true;
+	}
+
+	// areaportal entities move their brushes, but don't eliminate
+	// the entity
+	if (!strcmp ("func_areaportal", ValueForKey (mapent, "classname")))
+	{
+		char	str[128];
+
+		if (mapent->numbrushes != 1)
+			Error ("Entity %i: func_areaportal can only be a single brush", num_entities-1);
+
+		b = &mapbrushes[nummapbrushes-1];
+		b->contents = CONTENTS_AREAPORTAL;
+		c_areaportals++;
+		mapent->areaportalnum = c_areaportals;
+		// set the portal number as "style"
+		sprintf (str, "%i", c_areaportals);
+		SetKeyValue (mapent, "style", str);
+		MoveBrushesToWorld (mapent);
+		return true;
+	}
+
+	return true;
+}
+
+//===================================================================
+
+/*
+================
+LoadMapFile
+================
+*/
+void LoadMapFile (char *filename)
+{		
+	int		i;
+
+	Sys_FPrintf( SYS_VRB, "--- LoadMapFile ---\n");
+
+	LoadScriptFile (filename);
+
+	nummapbrushsides = 0;
+	num_entities = 0;
+	
+	while (ParseMapEntity ())
+	{
+	}
+
+	ClearBounds (map_mins, map_maxs);
+	for (i=0 ; i<entities[0].numbrushes ; i++)
+	{
+		if (mapbrushes[i].mins[0] > 4096)
+			continue;	// no valid points
+		AddPointToBounds (mapbrushes[i].mins, map_mins, map_maxs);
+		AddPointToBounds (mapbrushes[i].maxs, map_mins, map_maxs);
+	}
+
+	Sys_FPrintf( SYS_VRB, "%5i brushes\n", nummapbrushes);
+	Sys_FPrintf( SYS_VRB, "%5i clipbrushes\n", c_clipbrushes);
+	Sys_FPrintf( SYS_VRB, "%5i total sides\n", nummapbrushsides);
+	Sys_FPrintf( SYS_VRB, "%5i boxbevels\n", c_boxbevels);
+	Sys_FPrintf( SYS_VRB, "%5i edgebevels\n", c_edgebevels);
+	Sys_FPrintf( SYS_VRB, "%5i entities\n", num_entities);
+	Sys_FPrintf( SYS_VRB, "%5i planes\n", nummapplanes);
+	Sys_FPrintf( SYS_VRB, "%5i areaportals\n", c_areaportals);
+	Sys_FPrintf( SYS_VRB, "size: %5.0f,%5.0f,%5.0f to %5.0f,%5.0f,%5.0f\n", map_mins[0],map_mins[1],map_mins[2],
+		map_maxs[0],map_maxs[1],map_maxs[2]);
+
+//	TestExpandBrushes ();
+}
+
+
+//====================================================================
+
+
+/*
+================
+TestExpandBrushes
+
+Expands all the brush planes and saves a new map out
+================
+*/
+void TestExpandBrushes (void)
+{
+	FILE	*f;
+	side_t	*s;
+	int		i, j, bn;
+	winding_t	*w;
+	char	*name = "expanded.map";
+	mapbrush_t	*brush;
+	vec_t	dist;
+
+	Sys_Printf ("writing %s\n", name);
+	f = fopen (name, "wb");
+	if (!f)
+		Error ("Can't write %s\b", name);
+
+	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
+
+	for (bn=0 ; bn<nummapbrushes ; bn++)
+	{
+		brush = &mapbrushes[bn];
+		fprintf (f, "{\n");
+		for (i=0 ; i<brush->numsides ; i++)
+		{
+			s = brush->original_sides + i;
+			dist = mapplanes[s->planenum].dist;
+			for (j=0 ; j<3 ; j++)
+				dist += fabs( 16 * mapplanes[s->planenum].normal[j] );
+
+			w = BaseWindingForPlane (mapplanes[s->planenum].normal, dist);
+
+			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
+			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
+			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
+
+			fprintf (f, "%s 0 0 0 1 1\n", texinfo[s->texinfo].texture);
+			FreeWinding (w);
+		}
+		fprintf (f, "}\n");
+	}
+	fprintf (f, "}\n");
+
+	fclose (f);
+
+	Error ("can't proceed after expanding brushes");
+}
diff --git a/tools/quake2/q2map/nodraw.c b/tools/quake2/q2map/nodraw.c
index e3f3680b..e473fb34 100644
--- a/tools/quake2/q2map/nodraw.c
+++ b/tools/quake2/q2map/nodraw.c
@@ -1,46 +1,46 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-vec3_t draw_mins, draw_maxs;
-qboolean	drawflag;
-
-void Draw_ClearWindow (void)
-{
-}
-
-//============================================================
-
-#define	GLSERV_PORT	25001
-
-
-void GLS_BeginScene (void)
-{
-}
-
-void GLS_Winding (winding_t *w, int code)
-{
-}
-
-void GLS_EndScene (void)
-{
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+vec3_t draw_mins, draw_maxs;
+qboolean	drawflag;
+
+void Draw_ClearWindow (void)
+{
+}
+
+//============================================================
+
+#define	GLSERV_PORT	25001
+
+
+void GLS_BeginScene (void)
+{
+}
+
+void GLS_Winding (winding_t *w, int code)
+{
+}
+
+void GLS_EndScene (void)
+{
+}
diff --git a/tools/quake2/q2map/patches.c b/tools/quake2/q2map/patches.c
index eb76bc39..8b9b75fb 100644
--- a/tools/quake2/q2map/patches.c
+++ b/tools/quake2/q2map/patches.c
@@ -1,603 +1,603 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qrad.h"
-
-vec3_t	texture_reflectivity[MAX_MAP_TEXINFO];
-
-/*
-===================================================================
-
-  TEXTURE LIGHT VALUES
-
-===================================================================
-*/
-
-/*
-======================
-CalcTextureReflectivity_Quake2
-======================
-*/
-void CalcTextureReflectivity_Quake2 (void)
-{
-	int				i;
-	int				j, k, texels;
-	int				color[3];
-	int				texel;
-	byte			*palette;
-	char			path[1024];
-	float			r, scale;
-	miptex_t		*mt;
-
-	sprintf (path, "%spics/colormap.pcx", gamedir);
-
-	// get the game palette
-	Load256Image (path, NULL, &palette, NULL, NULL);
-
-	// allways set index 0 even if no textures
-	texture_reflectivity[0][0] = 0.5;
-	texture_reflectivity[0][1] = 0.5;
-	texture_reflectivity[0][2] = 0.5;
-
-	for (i=0 ; i<numtexinfo ; i++)
-	{
-		// see if an earlier texinfo allready got the value
-		for (j=0 ; j<i ; j++)
-		{
-			if (!strcmp (texinfo[i].texture, texinfo[j].texture))
-			{
-				VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
-				break;
-			}
-		}
-		if (j != i)
-			continue;
-
-		// load the wal file
-		sprintf (path, "%stextures/%s.wal", gamedir, texinfo[i].texture);
-		if (TryLoadFile (path, (void **)&mt) == -1)
-		{
-			Sys_Printf ("Couldn't load %s\n", path);
-			texture_reflectivity[i][0] = 0.5;
-			texture_reflectivity[i][1] = 0.5;
-			texture_reflectivity[i][2] = 0.5;
-			continue;
-		}
-		texels = LittleLong(mt->width)*LittleLong(mt->height);
-		color[0] = color[1] = color[2] = 0;
-
-		for (j=0 ; j<texels ; j++)
-		{
-			texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
-			for (k=0 ; k<3 ; k++)
-				color[k] += palette[texel*3+k];
-		}
-
-		for (j=0 ; j<3 ; j++)
-		{
-			r = color[j]/texels/255.0;
-			texture_reflectivity[i][j] = r;
-		}
-		// scale the reflectivity up, because the textures are
-		// so dim
-		scale = ColorNormalize (texture_reflectivity[i],
-			texture_reflectivity[i]);
-		if (scale < 0.5)
-		{
-			scale *= 2;
-			VectorScale (texture_reflectivity[i], scale, texture_reflectivity[i]);
-		}
-#if 0
-texture_reflectivity[i][0] = 0.5;
-texture_reflectivity[i][1] = 0.5;
-texture_reflectivity[i][2] = 0.5;
-#endif
-	}
-}
-
-/*
-======================
-CalcTextureReflectivity_Heretic2
-======================
-*/
-void CalcTextureReflectivity_Heretic2 (void)
-{
-	int				i;
-	int				j, texels;
-	int				color[3];
-	int				texel;
-	char			path[1024];
-	float			r;
-	miptex_m8_t		*mt;
-	miptex_m32_t		*mt32;
-	byte			*pos;
-
-
-	// allways set index 0 even if no textures
-	texture_reflectivity[0][0] = 0.5;
-	texture_reflectivity[0][1] = 0.5;
-	texture_reflectivity[0][2] = 0.5;
-
-	for (i=0 ; i<numtexinfo ; i++)
-	{
-		// see if an earlier texinfo allready got the value
-		for (j=0 ; j<i ; j++)
-		{
-			if (!strcmp (texinfo[i].texture, texinfo[j].texture))
-			{
-				VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
-				break;
-			}
-		}
-		if (j != i)
-			continue;
-
-		// load the wal file
-
-		sprintf (path, "%stextures/%s.m32", gamedir, texinfo[i].texture);
-		if (TryLoadFile (path, (void **)&mt32) == -1)
-		{
-			sprintf (path, "%stextures/%s.m8", gamedir, texinfo[i].texture);
-			if (TryLoadFile (path, (void **)&mt) == -1)
-			{
-				Sys_Printf ("Couldn't load %s\n", path);
-				texture_reflectivity[i][0] = 0.5;
-				texture_reflectivity[i][1] = 0.5;
-				texture_reflectivity[i][2] = 0.5;
-				continue;
-			}
-			texels = LittleLong(mt->width[0])*LittleLong(mt->height[0]);
-			color[0] = color[1] = color[2] = 0;
-
-			for (j=0 ; j<texels ; j++)
-			{
-				texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
-				color[0] += mt->palette[texel].r;
-				color[1] += mt->palette[texel].g;
-				color[2] += mt->palette[texel].b;
-			}
-
-			free(mt);
-		}
-		else
-		{
-			texels = LittleLong(mt32->width[0])*LittleLong(mt32->height[0]);
-			color[0] = color[1] = color[2] = 0;
-
-			for (j=0 ; j<texels ; j++)
-			{
-				pos = (byte *)mt32 + mt32->offsets[0] + (j<<2);
-				color[0] += *pos++;	// r
-				color[1] += *pos++;	// g
-				color[2] += *pos++;	// b
-			}
-
-			free(mt32);
-		}
-
-
-		for (j=0 ; j<3 ; j++)
-		{
-			r = color[j]/((float) texels*255.0);
-			texture_reflectivity[i][j] = r;
-		}
-	}
-}
-
-/*
-=======================================================================
-
-MAKE FACES
-
-=======================================================================
-*/
-
-/*
-=============
-WindingFromFace
-=============
-*/
-winding_t	*WindingFromFace (dface_t *f)
-{
-	int			i;
-	int			se;
-	dvertex_t	*dv;
-	int			v;
-	winding_t	*w;
-
-	w = AllocWinding (f->numedges);
-	w->numpoints = f->numedges;
-
-	for (i=0 ; i<f->numedges ; i++)
-	{
-		se = dsurfedges[f->firstedge + i];
-		if (se < 0)
-			v = dedges[-se].v[1];
-		else
-			v = dedges[se].v[0];
-
-		dv = &dvertexes[v];
-		VectorCopy (dv->point, w->p[i]);
-	}
-
-	RemoveColinearPoints (w);
-
-	return w;
-}
-
-/*
-=============
-BaseLightForFace
-=============
-*/
-void BaseLightForFace (dface_t *f, vec3_t color)
-{
-	texinfo_t	*tx;
-
-	//
-	// check for light emited by texture
-	//
-	tx = &texinfo[f->texinfo];
-	if (!(tx->flags & SURF_LIGHT) || tx->value == 0)
-	{
-		VectorClear (color);
-		return;
-	}
-
-	VectorScale (texture_reflectivity[f->texinfo], tx->value, color);
-}
-
-qboolean IsSky (dface_t *f)
-{
-	texinfo_t	*tx;
-
-	tx = &texinfo[f->texinfo];
-	if (tx->flags & SURF_SKY)
-		return true;
-	return false;
-}
-
-/*
-=============
-MakePatchForFace
-=============
-*/
-float	totalarea;
-void MakePatchForFace (int fn, winding_t *w)
-{
-	dface_t *f;
-	float	area;
-	patch_t		*patch;
-	dplane_t	*pl;
-	int			i;
-	vec3_t		color;
-	dleaf_t		*leaf;
-
-	f = &dfaces[fn];
-
-	area = WindingArea (w);
-	totalarea += area;
-
-	patch = &patches[num_patches];
-	if (num_patches == MAX_PATCHES)
-		Error ("num_patches == MAX_PATCHES");
-	patch->next = face_patches[fn];
-	face_patches[fn] = patch;
-
-	patch->winding = w;
-
-	if (f->side)
-		patch->plane = &backplanes[f->planenum];
-	else
-		patch->plane = &dplanes[f->planenum];
-	if (face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] )
-	{	// origin offset faces must create new planes
-		if (numplanes + fakeplanes >= MAX_MAP_PLANES)
-			Error ("numplanes + fakeplanes >= MAX_MAP_PLANES");
-		pl = &dplanes[numplanes + fakeplanes];
-		fakeplanes++;
-
-		*pl = *(patch->plane);
-		pl->dist += DotProduct (face_offset[fn], pl->normal);
-		patch->plane = pl;
-	}
-
-	WindingCenter (w, patch->origin);
-	VectorAdd (patch->origin, patch->plane->normal, patch->origin);
-	leaf = Rad_PointInLeaf(patch->origin);
-	patch->cluster = leaf->cluster;
-	if (patch->cluster == -1)
-		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
-
-	patch->area = area;
-	if (patch->area <= 1)
-		patch->area = 1;
-	patch->sky = IsSky (f);
-
-	VectorCopy (texture_reflectivity[f->texinfo], patch->reflectivity);
-
-	// non-bmodel patches can emit light
-	if (fn < dmodels[0].numfaces)
-	{
-		BaseLightForFace (f, patch->baselight);
-
-		ColorNormalize (patch->reflectivity, color);
-
-		for (i=0 ; i<3 ; i++)
-			patch->baselight[i] *= color[i];
-
-		VectorCopy (patch->baselight, patch->totallight);
-	}
-	num_patches++;
-}
-
-
-entity_t *EntityForModel (int modnum)
-{
-	int		i;
-	char	*s;
-	char	name[16];
-
-	sprintf (name, "*%i", modnum);
-	// search the entities for one using modnum
-	for (i=0 ; i<num_entities ; i++)
-	{
-		s = ValueForKey (&entities[i], "model");
-		if (!strcmp (s, name))
-			return &entities[i];
-	}
-
-	return &entities[0];
-}
-
-/*
-=============
-MakePatches
-=============
-*/
-void MakePatches (void)
-{
-	int		i, j, k;
-	dface_t	*f;
-	int		fn;
-	winding_t	*w;
-	dmodel_t	*mod;
-	vec3_t		origin;
-	entity_t	*ent;
-
-	Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces);
-
-	for (i=0 ; i<nummodels ; i++)
-	{
-		mod = &dmodels[i];
-		ent = EntityForModel (i);
-		// bmodels with origin brushes need to be offset into their
-		// in-use position
-		GetVectorForKey (ent, "origin", origin);
-//VectorCopy (vec3_origin, origin);
-
-		for (j=0 ; j<mod->numfaces ; j++)
-		{
-			fn = mod->firstface + j;
-			face_entity[fn] = ent;
-			VectorCopy (origin, face_offset[fn]);
-			f = &dfaces[fn];
-			w = WindingFromFace (f);
-			for (k=0 ; k<w->numpoints ; k++)
-			{
-				VectorAdd (w->p[k], origin, w->p[k]);
-			}
-			MakePatchForFace (fn, w);
-		}
-	}
-
-	Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)(totalarea/64));
-}
-
-/*
-=======================================================================
-
-SUBDIVIDE
-
-=======================================================================
-*/
-
-void FinishSplit (patch_t *patch, patch_t *newp)
-{
-	dleaf_t		*leaf;
-
-	VectorCopy (patch->baselight, newp->baselight);
-	VectorCopy (patch->totallight, newp->totallight);
-	VectorCopy (patch->reflectivity, newp->reflectivity);
-	newp->plane = patch->plane;
-	newp->sky = patch->sky;
-
-	patch->area = WindingArea (patch->winding);
-	newp->area = WindingArea (newp->winding);
-
-	if (patch->area <= 1)
-		patch->area = 1;
-	if (newp->area <= 1)
-		newp->area = 1;
-
-	WindingCenter (patch->winding, patch->origin);
-	VectorAdd (patch->origin, patch->plane->normal, patch->origin);
-	leaf = Rad_PointInLeaf(patch->origin);
-	patch->cluster = leaf->cluster;
-	if (patch->cluster == -1)
-		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
-
-	WindingCenter (newp->winding, newp->origin);
-	VectorAdd (newp->origin, newp->plane->normal, newp->origin);
-	leaf = Rad_PointInLeaf(newp->origin);
-	newp->cluster = leaf->cluster;
-	if (newp->cluster == -1)
-		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
-}
-
-/*
-=============
-SubdividePatch
-
-Chops the patch only if its local bounds exceed the max size
-=============
-*/
-void	SubdividePatch (patch_t *patch)
-{
-	winding_t *w, *o1, *o2;
-	vec3_t	mins, maxs, total;
-	vec3_t	split;
-	vec_t	dist;
-	int		i, j;
-	vec_t	v;
-	patch_t	*newp;
-
-	w = patch->winding;
-	mins[0] = mins[1] = mins[2] = 99999;
-	maxs[0] = maxs[1] = maxs[2] = -99999;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			v = w->p[i][j];
-			if (v < mins[j])
-				mins[j] = v;
-			if (v > maxs[j])
-				maxs[j] = v;
-		}
-	}
-	VectorSubtract (maxs, mins, total);
-	for (i=0 ; i<3 ; i++)
-		if (total[i] > (subdiv+1) )
-			break;
-	if (i == 3)
-	{
-		// no splitting needed
-		return;		
-	}
-
-	//
-	// split the winding
-	//
-	VectorCopy (vec3_origin, split);
-	split[i] = 1;
-	dist = (mins[i] + maxs[i])*0.5;
-	ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
-
-	//
-	// create a new patch
-	//
-	if (num_patches == MAX_PATCHES)
-		Error ("MAX_PATCHES");
-	newp = &patches[num_patches];
-	num_patches++;
-
-	newp->next = patch->next;
-	patch->next = newp;
-
-	patch->winding = o1;
-	newp->winding = o2;
-
-	FinishSplit (patch, newp);
-
-	SubdividePatch (patch);
-	SubdividePatch (newp);
-}
-
-
-/*
-=============
-DicePatch
-
-Chops the patch by a global grid
-=============
-*/
-void	DicePatch (patch_t *patch)
-{
-	winding_t *w, *o1, *o2;
-	vec3_t	mins, maxs;
-	vec3_t	split;
-	vec_t	dist;
-	int		i;
-	patch_t	*newp;
-
-	w = patch->winding;
-	WindingBounds (w, mins, maxs);
-	for (i=0 ; i<3 ; i++)
-		if (floor((mins[i]+1)/subdiv) < floor((maxs[i]-1)/subdiv))
-			break;
-	if (i == 3)
-	{
-		// no splitting needed
-		return;		
-	}
-
-	//
-	// split the winding
-	//
-	VectorCopy (vec3_origin, split);
-	split[i] = 1;
-	dist = subdiv*(1+floor((mins[i]+1)/subdiv));
-	ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
-
-	//
-	// create a new patch
-	//
-	if (num_patches == MAX_PATCHES)
-		Error ("MAX_PATCHES");
-	newp = &patches[num_patches];
-	num_patches++;
-
-	newp->next = patch->next;
-	patch->next = newp;
-
-	patch->winding = o1;
-	newp->winding = o2;
-
-	FinishSplit (patch, newp);
-
-	DicePatch (patch);
-	DicePatch (newp);
-}
-
-
-/*
-=============
-SubdividePatches
-=============
-*/
-void SubdividePatches (void)
-{
-	int		i, num;
-
-	if (subdiv < 1)
-		return;
-
-	num = num_patches;	// because the list will grow
-	for (i=0 ; i<num ; i++)
-	{
-//		SubdividePatch (&patches[i]);
-		DicePatch (&patches[i]);
-	}
-	Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches);
-}
-
-//=====================================================================
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qrad.h"
+
+vec3_t	texture_reflectivity[MAX_MAP_TEXINFO];
+
+/*
+===================================================================
+
+  TEXTURE LIGHT VALUES
+
+===================================================================
+*/
+
+/*
+======================
+CalcTextureReflectivity_Quake2
+======================
+*/
+void CalcTextureReflectivity_Quake2 (void)
+{
+	int				i;
+	int				j, k, texels;
+	int				color[3];
+	int				texel;
+	byte			*palette;
+	char			path[1024];
+	float			r, scale;
+	miptex_t		*mt;
+
+	sprintf (path, "%spics/colormap.pcx", gamedir);
+
+	// get the game palette
+	Load256Image (path, NULL, &palette, NULL, NULL);
+
+	// allways set index 0 even if no textures
+	texture_reflectivity[0][0] = 0.5;
+	texture_reflectivity[0][1] = 0.5;
+	texture_reflectivity[0][2] = 0.5;
+
+	for (i=0 ; i<numtexinfo ; i++)
+	{
+		// see if an earlier texinfo allready got the value
+		for (j=0 ; j<i ; j++)
+		{
+			if (!strcmp (texinfo[i].texture, texinfo[j].texture))
+			{
+				VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
+				break;
+			}
+		}
+		if (j != i)
+			continue;
+
+		// load the wal file
+		sprintf (path, "%stextures/%s.wal", gamedir, texinfo[i].texture);
+		if (TryLoadFile (path, (void **)&mt) == -1)
+		{
+			Sys_Printf ("Couldn't load %s\n", path);
+			texture_reflectivity[i][0] = 0.5;
+			texture_reflectivity[i][1] = 0.5;
+			texture_reflectivity[i][2] = 0.5;
+			continue;
+		}
+		texels = LittleLong(mt->width)*LittleLong(mt->height);
+		color[0] = color[1] = color[2] = 0;
+
+		for (j=0 ; j<texels ; j++)
+		{
+			texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
+			for (k=0 ; k<3 ; k++)
+				color[k] += palette[texel*3+k];
+		}
+
+		for (j=0 ; j<3 ; j++)
+		{
+			r = color[j]/texels/255.0;
+			texture_reflectivity[i][j] = r;
+		}
+		// scale the reflectivity up, because the textures are
+		// so dim
+		scale = ColorNormalize (texture_reflectivity[i],
+			texture_reflectivity[i]);
+		if (scale < 0.5)
+		{
+			scale *= 2;
+			VectorScale (texture_reflectivity[i], scale, texture_reflectivity[i]);
+		}
+#if 0
+texture_reflectivity[i][0] = 0.5;
+texture_reflectivity[i][1] = 0.5;
+texture_reflectivity[i][2] = 0.5;
+#endif
+	}
+}
+
+/*
+======================
+CalcTextureReflectivity_Heretic2
+======================
+*/
+void CalcTextureReflectivity_Heretic2 (void)
+{
+	int				i;
+	int				j, texels;
+	int				color[3];
+	int				texel;
+	char			path[1024];
+	float			r;
+	miptex_m8_t		*mt;
+	miptex_m32_t		*mt32;
+	byte			*pos;
+
+
+	// allways set index 0 even if no textures
+	texture_reflectivity[0][0] = 0.5;
+	texture_reflectivity[0][1] = 0.5;
+	texture_reflectivity[0][2] = 0.5;
+
+	for (i=0 ; i<numtexinfo ; i++)
+	{
+		// see if an earlier texinfo allready got the value
+		for (j=0 ; j<i ; j++)
+		{
+			if (!strcmp (texinfo[i].texture, texinfo[j].texture))
+			{
+				VectorCopy (texture_reflectivity[j], texture_reflectivity[i]);
+				break;
+			}
+		}
+		if (j != i)
+			continue;
+
+		// load the wal file
+
+		sprintf (path, "%stextures/%s.m32", gamedir, texinfo[i].texture);
+		if (TryLoadFile (path, (void **)&mt32) == -1)
+		{
+			sprintf (path, "%stextures/%s.m8", gamedir, texinfo[i].texture);
+			if (TryLoadFile (path, (void **)&mt) == -1)
+			{
+				Sys_Printf ("Couldn't load %s\n", path);
+				texture_reflectivity[i][0] = 0.5;
+				texture_reflectivity[i][1] = 0.5;
+				texture_reflectivity[i][2] = 0.5;
+				continue;
+			}
+			texels = LittleLong(mt->width[0])*LittleLong(mt->height[0]);
+			color[0] = color[1] = color[2] = 0;
+
+			for (j=0 ; j<texels ; j++)
+			{
+				texel = ((byte *)mt)[LittleLong(mt->offsets[0]) + j];
+				color[0] += mt->palette[texel].r;
+				color[1] += mt->palette[texel].g;
+				color[2] += mt->palette[texel].b;
+			}
+
+			free(mt);
+		}
+		else
+		{
+			texels = LittleLong(mt32->width[0])*LittleLong(mt32->height[0]);
+			color[0] = color[1] = color[2] = 0;
+
+			for (j=0 ; j<texels ; j++)
+			{
+				pos = (byte *)mt32 + mt32->offsets[0] + (j<<2);
+				color[0] += *pos++;	// r
+				color[1] += *pos++;	// g
+				color[2] += *pos++;	// b
+			}
+
+			free(mt32);
+		}
+
+
+		for (j=0 ; j<3 ; j++)
+		{
+			r = color[j]/((float) texels*255.0);
+			texture_reflectivity[i][j] = r;
+		}
+	}
+}
+
+/*
+=======================================================================
+
+MAKE FACES
+
+=======================================================================
+*/
+
+/*
+=============
+WindingFromFace
+=============
+*/
+winding_t	*WindingFromFace (dface_t *f)
+{
+	int			i;
+	int			se;
+	dvertex_t	*dv;
+	int			v;
+	winding_t	*w;
+
+	w = AllocWinding (f->numedges);
+	w->numpoints = f->numedges;
+
+	for (i=0 ; i<f->numedges ; i++)
+	{
+		se = dsurfedges[f->firstedge + i];
+		if (se < 0)
+			v = dedges[-se].v[1];
+		else
+			v = dedges[se].v[0];
+
+		dv = &dvertexes[v];
+		VectorCopy (dv->point, w->p[i]);
+	}
+
+	RemoveColinearPoints (w);
+
+	return w;
+}
+
+/*
+=============
+BaseLightForFace
+=============
+*/
+void BaseLightForFace (dface_t *f, vec3_t color)
+{
+	texinfo_t	*tx;
+
+	//
+	// check for light emited by texture
+	//
+	tx = &texinfo[f->texinfo];
+	if (!(tx->flags & SURF_LIGHT) || tx->value == 0)
+	{
+		VectorClear (color);
+		return;
+	}
+
+	VectorScale (texture_reflectivity[f->texinfo], tx->value, color);
+}
+
+qboolean IsSky (dface_t *f)
+{
+	texinfo_t	*tx;
+
+	tx = &texinfo[f->texinfo];
+	if (tx->flags & SURF_SKY)
+		return true;
+	return false;
+}
+
+/*
+=============
+MakePatchForFace
+=============
+*/
+float	totalarea;
+void MakePatchForFace (int fn, winding_t *w)
+{
+	dface_t *f;
+	float	area;
+	patch_t		*patch;
+	dplane_t	*pl;
+	int			i;
+	vec3_t		color;
+	dleaf_t		*leaf;
+
+	f = &dfaces[fn];
+
+	area = WindingArea (w);
+	totalarea += area;
+
+	patch = &patches[num_patches];
+	if (num_patches == MAX_PATCHES)
+		Error ("num_patches == MAX_PATCHES");
+	patch->next = face_patches[fn];
+	face_patches[fn] = patch;
+
+	patch->winding = w;
+
+	if (f->side)
+		patch->plane = &backplanes[f->planenum];
+	else
+		patch->plane = &dplanes[f->planenum];
+	if (face_offset[fn][0] || face_offset[fn][1] || face_offset[fn][2] )
+	{	// origin offset faces must create new planes
+		if (numplanes + fakeplanes >= MAX_MAP_PLANES)
+			Error ("numplanes + fakeplanes >= MAX_MAP_PLANES");
+		pl = &dplanes[numplanes + fakeplanes];
+		fakeplanes++;
+
+		*pl = *(patch->plane);
+		pl->dist += DotProduct (face_offset[fn], pl->normal);
+		patch->plane = pl;
+	}
+
+	WindingCenter (w, patch->origin);
+	VectorAdd (patch->origin, patch->plane->normal, patch->origin);
+	leaf = Rad_PointInLeaf(patch->origin);
+	patch->cluster = leaf->cluster;
+	if (patch->cluster == -1)
+		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
+
+	patch->area = area;
+	if (patch->area <= 1)
+		patch->area = 1;
+	patch->sky = IsSky (f);
+
+	VectorCopy (texture_reflectivity[f->texinfo], patch->reflectivity);
+
+	// non-bmodel patches can emit light
+	if (fn < dmodels[0].numfaces)
+	{
+		BaseLightForFace (f, patch->baselight);
+
+		ColorNormalize (patch->reflectivity, color);
+
+		for (i=0 ; i<3 ; i++)
+			patch->baselight[i] *= color[i];
+
+		VectorCopy (patch->baselight, patch->totallight);
+	}
+	num_patches++;
+}
+
+
+entity_t *EntityForModel (int modnum)
+{
+	int		i;
+	char	*s;
+	char	name[16];
+
+	sprintf (name, "*%i", modnum);
+	// search the entities for one using modnum
+	for (i=0 ; i<num_entities ; i++)
+	{
+		s = ValueForKey (&entities[i], "model");
+		if (!strcmp (s, name))
+			return &entities[i];
+	}
+
+	return &entities[0];
+}
+
+/*
+=============
+MakePatches
+=============
+*/
+void MakePatches (void)
+{
+	int		i, j, k;
+	dface_t	*f;
+	int		fn;
+	winding_t	*w;
+	dmodel_t	*mod;
+	vec3_t		origin;
+	entity_t	*ent;
+
+	Sys_FPrintf( SYS_VRB, "%i faces\n", numfaces);
+
+	for (i=0 ; i<nummodels ; i++)
+	{
+		mod = &dmodels[i];
+		ent = EntityForModel (i);
+		// bmodels with origin brushes need to be offset into their
+		// in-use position
+		GetVectorForKey (ent, "origin", origin);
+//VectorCopy (vec3_origin, origin);
+
+		for (j=0 ; j<mod->numfaces ; j++)
+		{
+			fn = mod->firstface + j;
+			face_entity[fn] = ent;
+			VectorCopy (origin, face_offset[fn]);
+			f = &dfaces[fn];
+			w = WindingFromFace (f);
+			for (k=0 ; k<w->numpoints ; k++)
+			{
+				VectorAdd (w->p[k], origin, w->p[k]);
+			}
+			MakePatchForFace (fn, w);
+		}
+	}
+
+	Sys_FPrintf( SYS_VRB, "%i sqaure feet\n", (int)(totalarea/64));
+}
+
+/*
+=======================================================================
+
+SUBDIVIDE
+
+=======================================================================
+*/
+
+void FinishSplit (patch_t *patch, patch_t *newp)
+{
+	dleaf_t		*leaf;
+
+	VectorCopy (patch->baselight, newp->baselight);
+	VectorCopy (patch->totallight, newp->totallight);
+	VectorCopy (patch->reflectivity, newp->reflectivity);
+	newp->plane = patch->plane;
+	newp->sky = patch->sky;
+
+	patch->area = WindingArea (patch->winding);
+	newp->area = WindingArea (newp->winding);
+
+	if (patch->area <= 1)
+		patch->area = 1;
+	if (newp->area <= 1)
+		newp->area = 1;
+
+	WindingCenter (patch->winding, patch->origin);
+	VectorAdd (patch->origin, patch->plane->normal, patch->origin);
+	leaf = Rad_PointInLeaf(patch->origin);
+	patch->cluster = leaf->cluster;
+	if (patch->cluster == -1)
+		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
+
+	WindingCenter (newp->winding, newp->origin);
+	VectorAdd (newp->origin, newp->plane->normal, newp->origin);
+	leaf = Rad_PointInLeaf(newp->origin);
+	newp->cluster = leaf->cluster;
+	if (newp->cluster == -1)
+		Sys_FPrintf( SYS_VRB, "patch->cluster == -1\n");
+}
+
+/*
+=============
+SubdividePatch
+
+Chops the patch only if its local bounds exceed the max size
+=============
+*/
+void	SubdividePatch (patch_t *patch)
+{
+	winding_t *w, *o1, *o2;
+	vec3_t	mins, maxs, total;
+	vec3_t	split;
+	vec_t	dist;
+	int		i, j;
+	vec_t	v;
+	patch_t	*newp;
+
+	w = patch->winding;
+	mins[0] = mins[1] = mins[2] = 99999;
+	maxs[0] = maxs[1] = maxs[2] = -99999;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			v = w->p[i][j];
+			if (v < mins[j])
+				mins[j] = v;
+			if (v > maxs[j])
+				maxs[j] = v;
+		}
+	}
+	VectorSubtract (maxs, mins, total);
+	for (i=0 ; i<3 ; i++)
+		if (total[i] > (subdiv+1) )
+			break;
+	if (i == 3)
+	{
+		// no splitting needed
+		return;		
+	}
+
+	//
+	// split the winding
+	//
+	VectorCopy (vec3_origin, split);
+	split[i] = 1;
+	dist = (mins[i] + maxs[i])*0.5;
+	ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
+
+	//
+	// create a new patch
+	//
+	if (num_patches == MAX_PATCHES)
+		Error ("MAX_PATCHES");
+	newp = &patches[num_patches];
+	num_patches++;
+
+	newp->next = patch->next;
+	patch->next = newp;
+
+	patch->winding = o1;
+	newp->winding = o2;
+
+	FinishSplit (patch, newp);
+
+	SubdividePatch (patch);
+	SubdividePatch (newp);
+}
+
+
+/*
+=============
+DicePatch
+
+Chops the patch by a global grid
+=============
+*/
+void	DicePatch (patch_t *patch)
+{
+	winding_t *w, *o1, *o2;
+	vec3_t	mins, maxs;
+	vec3_t	split;
+	vec_t	dist;
+	int		i;
+	patch_t	*newp;
+
+	w = patch->winding;
+	WindingBounds (w, mins, maxs);
+	for (i=0 ; i<3 ; i++)
+		if (floor((mins[i]+1)/subdiv) < floor((maxs[i]-1)/subdiv))
+			break;
+	if (i == 3)
+	{
+		// no splitting needed
+		return;		
+	}
+
+	//
+	// split the winding
+	//
+	VectorCopy (vec3_origin, split);
+	split[i] = 1;
+	dist = subdiv*(1+floor((mins[i]+1)/subdiv));
+	ClipWindingEpsilon (w, split, dist, ON_EPSILON, &o1, &o2);
+
+	//
+	// create a new patch
+	//
+	if (num_patches == MAX_PATCHES)
+		Error ("MAX_PATCHES");
+	newp = &patches[num_patches];
+	num_patches++;
+
+	newp->next = patch->next;
+	patch->next = newp;
+
+	patch->winding = o1;
+	newp->winding = o2;
+
+	FinishSplit (patch, newp);
+
+	DicePatch (patch);
+	DicePatch (newp);
+}
+
+
+/*
+=============
+SubdividePatches
+=============
+*/
+void SubdividePatches (void)
+{
+	int		i, num;
+
+	if (subdiv < 1)
+		return;
+
+	num = num_patches;	// because the list will grow
+	for (i=0 ; i<num ; i++)
+	{
+//		SubdividePatch (&patches[i]);
+		DicePatch (&patches[i]);
+	}
+	Sys_FPrintf( SYS_VRB, "%i patches after subdivision\n", num_patches);
+}
+
+//=====================================================================
diff --git a/tools/quake2/q2map/portals.c b/tools/quake2/q2map/portals.c
index a65b66b2..9857a3ba 100644
--- a/tools/quake2/q2map/portals.c
+++ b/tools/quake2/q2map/portals.c
@@ -1,1110 +1,1110 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-
-int		c_active_portals;
-int		c_peak_portals;
-int		c_boundary;
-int		c_boundary_sides;
-
-/*
-===========
-AllocPortal
-===========
-*/
-portal_t *AllocPortal (void)
-{
-	portal_t	*p;
-	
-	if (numthreads == 1)
-		c_active_portals++;
-	if (c_active_portals > c_peak_portals)
-		c_peak_portals = c_active_portals;
-	
-	p = malloc (sizeof(portal_t));
-	memset (p, 0, sizeof(portal_t));
-	
-	return p;
-}
-
-void FreePortal (portal_t *p)
-{
-	if (p->winding)
-		FreeWinding (p->winding);
-	if (numthreads == 1)
-		c_active_portals--;
-	free (p);
-}
-
-//==============================================================
-
-/*
-==============
-VisibleContents
-
-Returns the single content bit of the
-strongest visible content present
-==============
-*/
-int VisibleContents (int contents)
-{
-	int		i;
-
-	for (i=1 ; i<=LAST_VISIBLE_CONTENTS ; i<<=1)
-		if (contents & i )
-			return i;
-
-	return 0;
-}
-
-
-/*
-===============
-ClusterContents
-===============
-*/
-int ClusterContents (node_t *node)
-{
-	int		c1, c2, c;
-
-	if (node->planenum == PLANENUM_LEAF)
-		return node->contents;
-
-	c1 = ClusterContents(node->children[0]);
-	c2 = ClusterContents(node->children[1]);
-	c = c1|c2;
-
-	// a cluster may include some solid detail areas, but
-	// still be seen into
-	if ( ! (c1&CONTENTS_SOLID) || ! (c2&CONTENTS_SOLID) )
-		c &= ~CONTENTS_SOLID;
-	return c;
-}
-
-/*
-=============
-Portal_VisFlood
-
-Returns true if the portal is empty or translucent, allowing
-the PVS calculation to see through it.
-The nodes on either side of the portal may actually be clusters,
-not leafs, so all contents should be ored together
-=============
-*/
-qboolean Portal_VisFlood (portal_t *p)
-{
-	int		c1, c2;
-
-	if (!p->onnode)
-		return false;	// to global outsideleaf
-
-	c1 = ClusterContents(p->nodes[0]);
-	c2 = ClusterContents(p->nodes[1]);
-
-	if (!VisibleContents (c1^c2))
-		return true;
-
-	if (c1 & (CONTENTS_TRANSLUCENT|CONTENTS_DETAIL))
-		c1 = 0;
-	if (c2 & (CONTENTS_TRANSLUCENT|CONTENTS_DETAIL))
-		c2 = 0;
-
-	if ( (c1|c2) & CONTENTS_SOLID )
-		return false;		// can't see through solid
-
-	if (! (c1 ^ c2))
-		return true;		// identical on both sides
-
-	if (!VisibleContents (c1^c2))
-		return true;
-	return false;
-}
-
-
-/*
-===============
-Portal_EntityFlood
-
-The entity flood determines which areas are
-"outside" on the map, which are then filled in.
-Flowing from side s to side !s
-===============
-*/
-qboolean Portal_EntityFlood (portal_t *p, int s)
-{
-	if (p->nodes[0]->planenum != PLANENUM_LEAF
-		|| p->nodes[1]->planenum != PLANENUM_LEAF)
-		Error ("Portal_EntityFlood: not a leaf");
-
-	// can never cross to a solid 
-	if ( (p->nodes[0]->contents & CONTENTS_SOLID)
-	|| (p->nodes[1]->contents & CONTENTS_SOLID) )
-		return false;
-
-	// can flood through everything else
-	return true;
-}
-
-
-//=============================================================================
-
-int		c_tinyportals;
-
-/*
-=============
-AddPortalToNodes
-=============
-*/
-void AddPortalToNodes (portal_t *p, node_t *front, node_t *back)
-{
-	if (p->nodes[0] || p->nodes[1])
-		Error ("AddPortalToNode: allready included");
-
-	p->nodes[0] = front;
-	p->next[0] = front->portals;
-	front->portals = p;
-	
-	p->nodes[1] = back;
-	p->next[1] = back->portals;
-	back->portals = p;
-}
-
-
-/*
-=============
-RemovePortalFromNode
-=============
-*/
-void RemovePortalFromNode (portal_t *portal, node_t *l)
-{
-	portal_t	**pp, *t;
-	
-// remove reference to the current portal
-	pp = &l->portals;
-	while (1)
-	{
-		t = *pp;
-		if (!t)
-			Error ("RemovePortalFromNode: portal not in leaf");	
-
-		if ( t == portal )
-			break;
-
-		if (t->nodes[0] == l)
-			pp = &t->next[0];
-		else if (t->nodes[1] == l)
-			pp = &t->next[1];
-		else
-			Error ("RemovePortalFromNode: portal not bounding leaf");
-	}
-	
-	if (portal->nodes[0] == l)
-	{
-		*pp = portal->next[0];
-		portal->nodes[0] = NULL;
-	}
-	else if (portal->nodes[1] == l)
-	{
-		*pp = portal->next[1];	
-		portal->nodes[1] = NULL;
-	}
-}
-
-//============================================================================
-
-void PrintPortal (portal_t *p)
-{
-	int			i;
-	winding_t	*w;
-	
-	w = p->winding;
-	for (i=0 ; i<w->numpoints ; i++)
-		Sys_Printf ("(%5.0f,%5.0f,%5.0f)\n",w->p[i][0]
-		, w->p[i][1], w->p[i][2]);
-}
-
-/*
-================
-MakeHeadnodePortals
-
-The created portals will face the global outside_node
-================
-*/
-#define	SIDESPACE	8
-void MakeHeadnodePortals (tree_t *tree)
-{
-	vec3_t		bounds[2];
-	int			i, j, n;
-	portal_t	*p, *portals[6];
-	plane_t		bplanes[6], *pl;
-	node_t *node;
-
-	node = tree->headnode;
-
-// pad with some space so there will never be null volume leafs
-	for (i=0 ; i<3 ; i++)
-	{
-		bounds[0][i] = tree->mins[i] - SIDESPACE;
-		bounds[1][i] = tree->maxs[i] + SIDESPACE;
-	}
-	
-	tree->outside_node.planenum = PLANENUM_LEAF;
-	tree->outside_node.brushlist = NULL;
-	tree->outside_node.portals = NULL;
-	tree->outside_node.contents = 0;
-
-	for (i=0 ; i<3 ; i++)
-		for (j=0 ; j<2 ; j++)
-		{
-			n = j*3 + i;
-
-			p = AllocPortal ();
-			portals[n] = p;
-			
-			pl = &bplanes[n];
-			memset (pl, 0, sizeof(*pl));
-			if (j)
-			{
-				pl->normal[i] = -1;
-				pl->dist = -bounds[j][i];
-			}
-			else
-			{
-				pl->normal[i] = 1;
-				pl->dist = bounds[j][i];
-			}
-			p->plane = *pl;
-			p->winding = BaseWindingForPlane (pl->normal, pl->dist);
-			AddPortalToNodes (p, node, &tree->outside_node);
-		}
-		
-// clip the basewindings by all the other planes
-	for (i=0 ; i<6 ; i++)
-	{
-		for (j=0 ; j<6 ; j++)
-		{
-			if (j == i)
-				continue;
-			ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON);
-		}
-	}
-}
-
-//===================================================
-
-
-/*
-================
-BaseWindingForNode
-================
-*/
-#define	BASE_WINDING_EPSILON	0.001
-#define	SPLIT_WINDING_EPSILON	0.001
-
-winding_t	*BaseWindingForNode (node_t *node)
-{
-	winding_t	*w;
-	node_t		*n;
-	plane_t		*plane;
-	vec3_t		normal;
-	vec_t		dist;
-
-	w = BaseWindingForPlane (mapplanes[node->planenum].normal
-		, mapplanes[node->planenum].dist);
-
-	// clip by all the parents
-	for (n=node->parent ; n && w ; )
-	{
-		plane = &mapplanes[n->planenum];
-
-		if (n->children[0] == node)
-		{	// take front
-			ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON);
-		}
-		else
-		{	// take back
-			VectorSubtract (vec3_origin, plane->normal, normal);
-			dist = -plane->dist;
-			ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON);
-		}
-		node = n;
-		n = n->parent;
-	}
-
-	return w;
-}
-
-//============================================================
-
-qboolean WindingIsTiny (winding_t *w);
-
-/*
-==================
-MakeNodePortal
-
-create the new portal by taking the full plane winding for the cutting plane
-and clipping it by all of parents of this node
-==================
-*/
-void MakeNodePortal (node_t *node)
-{
-	portal_t	*new_portal, *p;
-	winding_t	*w;
-	vec3_t		normal;
-	float		dist;
-	int			side;
-
-	w = BaseWindingForNode (node);
-
-	// clip the portal by all the other portals in the node
-	for (p = node->portals ; p && w; p = p->next[side])	
-	{
-		if (p->nodes[0] == node)
-		{
-			side = 0;
-			VectorCopy (p->plane.normal, normal);
-			dist = p->plane.dist;
-		}
-		else if (p->nodes[1] == node)
-		{
-			side = 1;
-			VectorSubtract (vec3_origin, p->plane.normal, normal);
-			dist = -p->plane.dist;
-		}
-		else
-			Error ("CutNodePortals_r: mislinked portal");
-
-		ChopWindingInPlace (&w, normal, dist, 0.1);
-	}
-
-	if (!w)
-	{
-		return;
-	}
-
-	if (WindingIsTiny (w))
-	{
-		c_tinyportals++;
-		FreeWinding (w);
-		return;
-	}
-
-
-	new_portal = AllocPortal ();
-	new_portal->plane = mapplanes[node->planenum];
-	new_portal->onnode = node;
-	new_portal->winding = w;	
-	AddPortalToNodes (new_portal, node->children[0], node->children[1]);
-}
-
-
-/*
-==============
-SplitNodePortals
-
-Move or split the portals that bound node so that the node's
-children have portals instead of node.
-==============
-*/
-void SplitNodePortals (node_t *node)
-{
-	portal_t	*p, *next_portal, *new_portal;
-	node_t		*f, *b, *other_node;
-	int			side;
-	plane_t		*plane;
-	winding_t	*frontwinding, *backwinding;
-
-	plane = &mapplanes[node->planenum];
-	f = node->children[0];
-	b = node->children[1];
-
-	for (p = node->portals ; p ; p = next_portal)	
-	{
-		if (p->nodes[0] == node)
-			side = 0;
-		else if (p->nodes[1] == node)
-			side = 1;
-		else
-			Error ("CutNodePortals_r: mislinked portal");
-		next_portal = p->next[side];
-
-		other_node = p->nodes[!side];
-		RemovePortalFromNode (p, p->nodes[0]);
-		RemovePortalFromNode (p, p->nodes[1]);
-
-//
-// cut the portal into two portals, one on each side of the cut plane
-//
-		ClipWindingEpsilon (p->winding, plane->normal, plane->dist,
-			SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);
-
-		if (frontwinding && WindingIsTiny(frontwinding))
-		{
-			FreeWinding (frontwinding);
-			frontwinding = NULL;
-			c_tinyportals++;
-		}
-
-		if (backwinding && WindingIsTiny(backwinding))
-		{
-			FreeWinding (backwinding);
-			backwinding = NULL;
-			c_tinyportals++;
-		}
-
-		if (!frontwinding && !backwinding)
-		{	// tiny windings on both sides
-			continue;
-		}
-
-		if (!frontwinding)
-		{
-			FreeWinding (backwinding);
-			if (side == 0)
-				AddPortalToNodes (p, b, other_node);
-			else
-				AddPortalToNodes (p, other_node, b);
-			continue;
-		}
-		if (!backwinding)
-		{
-			FreeWinding (frontwinding);
-			if (side == 0)
-				AddPortalToNodes (p, f, other_node);
-			else
-				AddPortalToNodes (p, other_node, f);
-			continue;
-		}
-		
-	// the winding is split
-		new_portal = AllocPortal ();
-		*new_portal = *p;
-		new_portal->winding = backwinding;
-		FreeWinding (p->winding);
-		p->winding = frontwinding;
-
-		if (side == 0)
-		{
-			AddPortalToNodes (p, f, other_node);
-			AddPortalToNodes (new_portal, b, other_node);
-		}
-		else
-		{
-			AddPortalToNodes (p, other_node, f);
-			AddPortalToNodes (new_portal, other_node, b);
-		}
-	}
-
-	node->portals = NULL;
-}
-
-
-/*
-================
-CalcNodeBounds
-================
-*/
-void CalcNodeBounds (node_t *node)
-{
-	portal_t	*p;
-	int			s;
-	int			i;
-
-	// calc mins/maxs for both leafs and nodes
-	ClearBounds (node->mins, node->maxs);
-	for (p = node->portals ; p ; p = p->next[s])	
-	{
-		s = (p->nodes[1] == node);
-		for (i=0 ; i<p->winding->numpoints ; i++)
-			AddPointToBounds (p->winding->p[i], node->mins, node->maxs);
-	}
-}
-
-
-/*
-==================
-MakeTreePortals_r
-==================
-*/
-void MakeTreePortals_r (node_t *node)
-{
-	int		i;
-
-	CalcNodeBounds (node);
-	if (node->mins[0] >= node->maxs[0])
-	{
-		Sys_Printf ("WARNING: node without a volume\n");
-	}
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if (node->mins[i] < -8000 || node->maxs[i] > 8000)
-		{
-			Sys_Printf ("WARNING: node with unbounded volume\n");
-			break;
-		}
-	}
-	if (node->planenum == PLANENUM_LEAF)
-		return;
-
-	MakeNodePortal (node);
-	SplitNodePortals (node);
-
-	MakeTreePortals_r (node->children[0]);
-	MakeTreePortals_r (node->children[1]);
-}
-
-/*
-==================
-MakeTreePortals
-==================
-*/
-void MakeTreePortals (tree_t *tree)
-{
-	MakeHeadnodePortals (tree);
-	MakeTreePortals_r (tree->headnode);
-}
-
-/*
-=========================================================
-
-FLOOD ENTITIES
-
-=========================================================
-*/
-
-/*
-=============
-FloodPortals_r
-=============
-*/
-void FloodPortals_r (node_t *node, int dist)
-{
-	portal_t	*p;
-	int			s;
-
-	node->occupied = dist;
-
-	for (p=node->portals ; p ; p = p->next[s])
-	{
-		s = (p->nodes[1] == node);
-
-		if (p->nodes[!s]->occupied)
-			continue;
-
-		if (!Portal_EntityFlood (p, s))
-			continue;
-
-		FloodPortals_r (p->nodes[!s], dist+1);
-	}
-}
-
-/*
-=============
-PlaceOccupant
-=============
-*/
-qboolean PlaceOccupant (node_t *headnode, vec3_t origin, entity_t *occupant)
-{
-	node_t	*node;
-	vec_t	d;
-	plane_t	*plane;
-
-	// find the leaf to start in
-	node = headnode;
-	while (node->planenum != PLANENUM_LEAF)
-	{
-		plane = &mapplanes[node->planenum];
-		d = DotProduct (origin, plane->normal) - plane->dist;
-		if (d >= 0)
-			node = node->children[0];
-		else
-			node = node->children[1];
-	}
-
-	if (node->contents == CONTENTS_SOLID)
-		return false;
-	node->occupant = occupant;
-
-	FloodPortals_r (node, 1);
-
-	return true;
-}
-
-/*
-=============
-FloodEntities
-
-Marks all nodes that can be reached by entites
-=============
-*/
-qboolean FloodEntities (tree_t *tree)
-{
-	int		i;
-	vec3_t	origin;
-	char	*cl;
-	qboolean	inside;
-	node_t *headnode;
-
-	headnode = tree->headnode;
-	Sys_FPrintf( SYS_VRB, "--- FloodEntities ---\n");
-	inside = false;
-	tree->outside_node.occupied = 0;
-
-	for (i=1 ; i<num_entities ; i++)
-	{
-		GetVectorForKey (&entities[i], "origin", origin);
-		if (VectorCompare(origin, vec3_origin))
-			continue;
-
-		cl = ValueForKey (&entities[i], "classname");
-		origin[2] += 1;	// so objects on floor are ok
-
-		// nudge playerstart around if needed so clipping hulls allways
-		// have a vlaid point
-		if (!strcmp (cl, "info_player_start"))
-		{
-			int	x, y;
-
-			for (x=-16 ; x<=16 ; x += 16)
-			{
-				for (y=-16 ; y<=16 ; y += 16)
-				{
-					origin[0] += x;
-					origin[1] += y;
-					if (PlaceOccupant (headnode, origin, &entities[i]))
-					{
-						inside = true;
-						goto gotit;
-					}
-					origin[0] -= x;
-					origin[1] -= y;
-				}
-			}
-gotit: ;
-		}
-		else
-		{
-			if (PlaceOccupant (headnode, origin, &entities[i]))
-				inside = true;
-		}
-	}
-
-	if (!inside)
-	{
-		Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n");
-	}
-	else if (tree->outside_node.occupied)
-	{
-		Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n");
-	}
-
-	return (qboolean)(inside && !tree->outside_node.occupied);
-}
-
-/*
-=========================================================
-
-FLOOD AREAS
-
-=========================================================
-*/
-
-int		c_areas;
-
-/*
-=============
-FloodAreas_r
-=============
-*/
-void FloodAreas_r (node_t *node)
-{
-	portal_t	*p;
-	int			s;
-	bspbrush_t	*b;
-	entity_t	*e;
-
-	if (node->contents == CONTENTS_AREAPORTAL)
-	{
-		// this node is part of an area portal
-		b = node->brushlist;
-		e = &entities[b->original->entitynum];
-
-		// if the current area has allready touched this
-		// portal, we are done
-		if (e->portalareas[0] == c_areas || e->portalareas[1] == c_areas)
-			return;
-
-		// note the current area as bounding the portal
-		if (e->portalareas[1])
-		{
-			Sys_Printf ("WARNING: areaportal entity %i touches > 2 areas\n", b->original->entitynum);
-			return;
-		}
-		if (e->portalareas[0])
-			e->portalareas[1] = c_areas;
-		else
-			e->portalareas[0] = c_areas;
-
-		return;
-	}
-
-	if (node->area)
-		return;		// allready got it
-	node->area = c_areas;
-
-	for (p=node->portals ; p ; p = p->next[s])
-	{
-		s = (p->nodes[1] == node);
-#if 0
-		if (p->nodes[!s]->occupied)
-			continue;
-#endif
-		if (!Portal_EntityFlood (p, s))
-			continue;
-
-		FloodAreas_r (p->nodes[!s]);
-	}
-}
-
-/*
-=============
-FindAreas_r
-
-Just decend the tree, and for each node that hasn't had an
-area set, flood fill out from there
-=============
-*/
-void FindAreas_r (node_t *node)
-{
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		FindAreas_r (node->children[0]);
-		FindAreas_r (node->children[1]);
-		return;
-	}
-
-	if (node->area)
-		return;		// allready got it
-
-	if (node->contents & CONTENTS_SOLID)
-		return;
-
-	if (!node->occupied)
-		return;			// not reachable by entities
-
-	// area portals are allways only flooded into, never
-	// out of
-	if (node->contents == CONTENTS_AREAPORTAL)
-		return;
-
-	c_areas++;
-	FloodAreas_r (node);
-}
-
-/*
-=============
-SetAreaPortalAreas_r
-
-Just decend the tree, and for each node that hasn't had an
-area set, flood fill out from there
-=============
-*/
-void SetAreaPortalAreas_r (node_t *node)
-{
-	bspbrush_t	*b;
-	entity_t	*e;
-
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		SetAreaPortalAreas_r (node->children[0]);
-		SetAreaPortalAreas_r (node->children[1]);
-		return;
-	}
-
-	if (node->contents == CONTENTS_AREAPORTAL)
-	{
-		if (node->area)
-			return;		// allready set
-
-		b = node->brushlist;
-		e = &entities[b->original->entitynum];
-		node->area = e->portalareas[0];
-		if (!e->portalareas[1])
-		{
-			Sys_Printf ("WARNING: areaportal entity %i doesn't touch two areas\n", b->original->entitynum);
-			return;
-		}
-	}
-}
-
-/*
-=============
-EmitAreaPortals
-
-=============
-*/
-void EmitAreaPortals (node_t *headnode)
-{
-	int				i, j;
-	entity_t		*e;
-	dareaportal_t	*dp;
-
-	if (c_areas > MAX_MAP_AREAS)
-		Error ("MAX_MAP_AREAS");
-	numareas = c_areas+1;
-	numareaportals = 1;		// leave 0 as an error
-
-	for (i=1 ; i<=c_areas ; i++)
-	{
-		dareas[i].firstareaportal = numareaportals;
-		for (j=0 ; j<num_entities ; j++)
-		{
-			e = &entities[j];
-			if (!e->areaportalnum)
-				continue;
-			dp = &dareaportals[numareaportals];
-			if (e->portalareas[0] == i)
-			{
-				dp->portalnum = e->areaportalnum;
-				dp->otherarea = e->portalareas[1];
-				numareaportals++;
-			}
-			else if (e->portalareas[1] == i)
-			{
-				dp->portalnum = e->areaportalnum;
-				dp->otherarea = e->portalareas[0];
-				numareaportals++;
-			}
-		}
-		dareas[i].numareaportals = numareaportals - dareas[i].firstareaportal;
-	}
-
-	Sys_FPrintf( SYS_VRB, "%5i numareas\n", numareas);
-	Sys_FPrintf( SYS_VRB, "%5i numareaportals\n", numareaportals);
-}
-
-/*
-=============
-FloodAreas
-
-Mark each leaf with an area, bounded by CONTENTS_AREAPORTAL
-=============
-*/
-void FloodAreas (tree_t *tree)
-{
-	Sys_FPrintf( SYS_VRB, "--- FloodAreas ---\n");
-	FindAreas_r (tree->headnode);
-	SetAreaPortalAreas_r (tree->headnode);
-	Sys_FPrintf( SYS_VRB, "%5i areas\n", c_areas);
-}
-
-//======================================================
-
-int		c_outside;
-int		c_inside;
-int		c_solid;
-
-void FillOutside_r (node_t *node)
-{
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		FillOutside_r (node->children[0]);
-		FillOutside_r (node->children[1]);
-		return;
-	}
-
-	// anything not reachable by an entity
-	// can be filled away
-	if (!node->occupied)
-	{
-		if (node->contents != CONTENTS_SOLID)
-		{
-			c_outside++;
-			node->contents = CONTENTS_SOLID;
-		}
-		else
-			c_solid++;
-	}
-	else
-		c_inside++;
-
-}
-
-/*
-=============
-FillOutside
-
-Fill all nodes that can't be reached by entities
-=============
-*/
-void FillOutside (node_t *headnode)
-{
-	c_outside = 0;
-	c_inside = 0;
-	c_solid = 0;
-	Sys_FPrintf( SYS_VRB, "--- FillOutside ---\n");
-	FillOutside_r (headnode);
-	Sys_FPrintf( SYS_VRB, "%5i solid leafs\n", c_solid);
-	Sys_FPrintf( SYS_VRB, "%5i leafs filled\n", c_outside);
-	Sys_FPrintf( SYS_VRB, "%5i inside leafs\n", c_inside);
-}
-
-
-//==============================================================
-
-/*
-============
-FindPortalSide
-
-Finds a brush side to use for texturing the given portal
-============
-*/
-void FindPortalSide (portal_t *p)
-{
-	int			viscontents;
-	bspbrush_t	*bb;
-	mapbrush_t	*brush;
-	node_t		*n;
-	int			i,j;
-	int			planenum;
-	side_t		*side, *bestside;
-	float		dot, bestdot;
-	plane_t		*p1, *p2;
-
-	// decide which content change is strongest
-	// solid > lava > water, etc
-	viscontents = VisibleContents (p->nodes[0]->contents ^ p->nodes[1]->contents);
-	if (!viscontents)
-		return;
-
-	planenum = p->onnode->planenum;
-	bestside = NULL;
-	bestdot = 0;
-
-	for (j=0 ; j<2 ; j++)
-	{
-		n = p->nodes[j];
-		p1 = &mapplanes[p->onnode->planenum];
-		for (bb=n->brushlist ; bb ; bb=bb->next)
-		{
-			brush = bb->original;
-			if ( !(brush->contents & viscontents) )
-				continue;
-			for (i=0 ; i<brush->numsides ; i++)
-			{
-				side = &brush->original_sides[i];
-				if (side->bevel)
-					continue;
-				if (side->texinfo == TEXINFO_NODE)
-					continue;		// non-visible
-				if ((side->planenum&~1) == planenum)
-				{	// exact match
-					bestside = &brush->original_sides[i];
-					goto gotit;
-				}
-				// see how close the match is
-				p2 = &mapplanes[side->planenum&~1];
-				dot = DotProduct (p1->normal, p2->normal);
-				if (dot > bestdot)
-				{
-					bestdot = dot;
-					bestside = side;
-				}
-			}
-		}
-	}
-
-gotit:
-	if (!bestside)
-		Sys_FPrintf( SYS_VRB, "WARNING: side not found for portal\n");
-
-	p->sidefound = true;
-	p->side = bestside;
-}
-
-
-/*
-===============
-MarkVisibleSides_r
-
-===============
-*/
-void MarkVisibleSides_r (node_t *node)
-{
-	portal_t	*p;
-	int			s;
-
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		MarkVisibleSides_r (node->children[0]);
-		MarkVisibleSides_r (node->children[1]);
-		return;
-	}
-
-	// empty leafs are never boundary leafs
-	if (!node->contents)
-		return;
-
-	// see if there is a visible face
-	for (p=node->portals ; p ; p = p->next[!s])
-	{
-		s = (p->nodes[0] == node);
-		if (!p->onnode)
-			continue;		// edge of world
-		if (!p->sidefound)
-			FindPortalSide (p);
-		if (p->side)
-			p->side->visible = true;
-	}
-
-}
-
-/*
-=============
-MarkVisibleSides
-
-=============
-*/
-void MarkVisibleSides (tree_t *tree, int startbrush, int endbrush)
-{
-	int		i, j;
-	mapbrush_t	*mb;
-	int		numsides;
-
-	Sys_FPrintf( SYS_VRB, "--- MarkVisibleSides ---\n");
-
-	// clear all the visible flags
-	for (i=startbrush ; i<endbrush ; i++)
-	{
-		mb = &mapbrushes[i];
-
-		numsides = mb->numsides;
-		for (j=0 ; j<numsides ; j++)
-			mb->original_sides[j].visible = false;
-	}
-
-	// set visible flags on the sides that are used by portals
-	MarkVisibleSides_r (tree->headnode);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+
+int		c_active_portals;
+int		c_peak_portals;
+int		c_boundary;
+int		c_boundary_sides;
+
+/*
+===========
+AllocPortal
+===========
+*/
+portal_t *AllocPortal (void)
+{
+	portal_t	*p;
+	
+	if (numthreads == 1)
+		c_active_portals++;
+	if (c_active_portals > c_peak_portals)
+		c_peak_portals = c_active_portals;
+	
+	p = malloc (sizeof(portal_t));
+	memset (p, 0, sizeof(portal_t));
+	
+	return p;
+}
+
+void FreePortal (portal_t *p)
+{
+	if (p->winding)
+		FreeWinding (p->winding);
+	if (numthreads == 1)
+		c_active_portals--;
+	free (p);
+}
+
+//==============================================================
+
+/*
+==============
+VisibleContents
+
+Returns the single content bit of the
+strongest visible content present
+==============
+*/
+int VisibleContents (int contents)
+{
+	int		i;
+
+	for (i=1 ; i<=LAST_VISIBLE_CONTENTS ; i<<=1)
+		if (contents & i )
+			return i;
+
+	return 0;
+}
+
+
+/*
+===============
+ClusterContents
+===============
+*/
+int ClusterContents (node_t *node)
+{
+	int		c1, c2, c;
+
+	if (node->planenum == PLANENUM_LEAF)
+		return node->contents;
+
+	c1 = ClusterContents(node->children[0]);
+	c2 = ClusterContents(node->children[1]);
+	c = c1|c2;
+
+	// a cluster may include some solid detail areas, but
+	// still be seen into
+	if ( ! (c1&CONTENTS_SOLID) || ! (c2&CONTENTS_SOLID) )
+		c &= ~CONTENTS_SOLID;
+	return c;
+}
+
+/*
+=============
+Portal_VisFlood
+
+Returns true if the portal is empty or translucent, allowing
+the PVS calculation to see through it.
+The nodes on either side of the portal may actually be clusters,
+not leafs, so all contents should be ored together
+=============
+*/
+qboolean Portal_VisFlood (portal_t *p)
+{
+	int		c1, c2;
+
+	if (!p->onnode)
+		return false;	// to global outsideleaf
+
+	c1 = ClusterContents(p->nodes[0]);
+	c2 = ClusterContents(p->nodes[1]);
+
+	if (!VisibleContents (c1^c2))
+		return true;
+
+	if (c1 & (CONTENTS_TRANSLUCENT|CONTENTS_DETAIL))
+		c1 = 0;
+	if (c2 & (CONTENTS_TRANSLUCENT|CONTENTS_DETAIL))
+		c2 = 0;
+
+	if ( (c1|c2) & CONTENTS_SOLID )
+		return false;		// can't see through solid
+
+	if (! (c1 ^ c2))
+		return true;		// identical on both sides
+
+	if (!VisibleContents (c1^c2))
+		return true;
+	return false;
+}
+
+
+/*
+===============
+Portal_EntityFlood
+
+The entity flood determines which areas are
+"outside" on the map, which are then filled in.
+Flowing from side s to side !s
+===============
+*/
+qboolean Portal_EntityFlood (portal_t *p, int s)
+{
+	if (p->nodes[0]->planenum != PLANENUM_LEAF
+		|| p->nodes[1]->planenum != PLANENUM_LEAF)
+		Error ("Portal_EntityFlood: not a leaf");
+
+	// can never cross to a solid 
+	if ( (p->nodes[0]->contents & CONTENTS_SOLID)
+	|| (p->nodes[1]->contents & CONTENTS_SOLID) )
+		return false;
+
+	// can flood through everything else
+	return true;
+}
+
+
+//=============================================================================
+
+int		c_tinyportals;
+
+/*
+=============
+AddPortalToNodes
+=============
+*/
+void AddPortalToNodes (portal_t *p, node_t *front, node_t *back)
+{
+	if (p->nodes[0] || p->nodes[1])
+		Error ("AddPortalToNode: allready included");
+
+	p->nodes[0] = front;
+	p->next[0] = front->portals;
+	front->portals = p;
+	
+	p->nodes[1] = back;
+	p->next[1] = back->portals;
+	back->portals = p;
+}
+
+
+/*
+=============
+RemovePortalFromNode
+=============
+*/
+void RemovePortalFromNode (portal_t *portal, node_t *l)
+{
+	portal_t	**pp, *t;
+	
+// remove reference to the current portal
+	pp = &l->portals;
+	while (1)
+	{
+		t = *pp;
+		if (!t)
+			Error ("RemovePortalFromNode: portal not in leaf");	
+
+		if ( t == portal )
+			break;
+
+		if (t->nodes[0] == l)
+			pp = &t->next[0];
+		else if (t->nodes[1] == l)
+			pp = &t->next[1];
+		else
+			Error ("RemovePortalFromNode: portal not bounding leaf");
+	}
+	
+	if (portal->nodes[0] == l)
+	{
+		*pp = portal->next[0];
+		portal->nodes[0] = NULL;
+	}
+	else if (portal->nodes[1] == l)
+	{
+		*pp = portal->next[1];	
+		portal->nodes[1] = NULL;
+	}
+}
+
+//============================================================================
+
+void PrintPortal (portal_t *p)
+{
+	int			i;
+	winding_t	*w;
+	
+	w = p->winding;
+	for (i=0 ; i<w->numpoints ; i++)
+		Sys_Printf ("(%5.0f,%5.0f,%5.0f)\n",w->p[i][0]
+		, w->p[i][1], w->p[i][2]);
+}
+
+/*
+================
+MakeHeadnodePortals
+
+The created portals will face the global outside_node
+================
+*/
+#define	SIDESPACE	8
+void MakeHeadnodePortals (tree_t *tree)
+{
+	vec3_t		bounds[2];
+	int			i, j, n;
+	portal_t	*p, *portals[6];
+	plane_t		bplanes[6], *pl;
+	node_t *node;
+
+	node = tree->headnode;
+
+// pad with some space so there will never be null volume leafs
+	for (i=0 ; i<3 ; i++)
+	{
+		bounds[0][i] = tree->mins[i] - SIDESPACE;
+		bounds[1][i] = tree->maxs[i] + SIDESPACE;
+	}
+	
+	tree->outside_node.planenum = PLANENUM_LEAF;
+	tree->outside_node.brushlist = NULL;
+	tree->outside_node.portals = NULL;
+	tree->outside_node.contents = 0;
+
+	for (i=0 ; i<3 ; i++)
+		for (j=0 ; j<2 ; j++)
+		{
+			n = j*3 + i;
+
+			p = AllocPortal ();
+			portals[n] = p;
+			
+			pl = &bplanes[n];
+			memset (pl, 0, sizeof(*pl));
+			if (j)
+			{
+				pl->normal[i] = -1;
+				pl->dist = -bounds[j][i];
+			}
+			else
+			{
+				pl->normal[i] = 1;
+				pl->dist = bounds[j][i];
+			}
+			p->plane = *pl;
+			p->winding = BaseWindingForPlane (pl->normal, pl->dist);
+			AddPortalToNodes (p, node, &tree->outside_node);
+		}
+		
+// clip the basewindings by all the other planes
+	for (i=0 ; i<6 ; i++)
+	{
+		for (j=0 ; j<6 ; j++)
+		{
+			if (j == i)
+				continue;
+			ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON);
+		}
+	}
+}
+
+//===================================================
+
+
+/*
+================
+BaseWindingForNode
+================
+*/
+#define	BASE_WINDING_EPSILON	0.001
+#define	SPLIT_WINDING_EPSILON	0.001
+
+winding_t	*BaseWindingForNode (node_t *node)
+{
+	winding_t	*w;
+	node_t		*n;
+	plane_t		*plane;
+	vec3_t		normal;
+	vec_t		dist;
+
+	w = BaseWindingForPlane (mapplanes[node->planenum].normal
+		, mapplanes[node->planenum].dist);
+
+	// clip by all the parents
+	for (n=node->parent ; n && w ; )
+	{
+		plane = &mapplanes[n->planenum];
+
+		if (n->children[0] == node)
+		{	// take front
+			ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON);
+		}
+		else
+		{	// take back
+			VectorSubtract (vec3_origin, plane->normal, normal);
+			dist = -plane->dist;
+			ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON);
+		}
+		node = n;
+		n = n->parent;
+	}
+
+	return w;
+}
+
+//============================================================
+
+qboolean WindingIsTiny (winding_t *w);
+
+/*
+==================
+MakeNodePortal
+
+create the new portal by taking the full plane winding for the cutting plane
+and clipping it by all of parents of this node
+==================
+*/
+void MakeNodePortal (node_t *node)
+{
+	portal_t	*new_portal, *p;
+	winding_t	*w;
+	vec3_t		normal;
+	float		dist;
+	int			side;
+
+	w = BaseWindingForNode (node);
+
+	// clip the portal by all the other portals in the node
+	for (p = node->portals ; p && w; p = p->next[side])	
+	{
+		if (p->nodes[0] == node)
+		{
+			side = 0;
+			VectorCopy (p->plane.normal, normal);
+			dist = p->plane.dist;
+		}
+		else if (p->nodes[1] == node)
+		{
+			side = 1;
+			VectorSubtract (vec3_origin, p->plane.normal, normal);
+			dist = -p->plane.dist;
+		}
+		else
+			Error ("CutNodePortals_r: mislinked portal");
+
+		ChopWindingInPlace (&w, normal, dist, 0.1);
+	}
+
+	if (!w)
+	{
+		return;
+	}
+
+	if (WindingIsTiny (w))
+	{
+		c_tinyportals++;
+		FreeWinding (w);
+		return;
+	}
+
+
+	new_portal = AllocPortal ();
+	new_portal->plane = mapplanes[node->planenum];
+	new_portal->onnode = node;
+	new_portal->winding = w;	
+	AddPortalToNodes (new_portal, node->children[0], node->children[1]);
+}
+
+
+/*
+==============
+SplitNodePortals
+
+Move or split the portals that bound node so that the node's
+children have portals instead of node.
+==============
+*/
+void SplitNodePortals (node_t *node)
+{
+	portal_t	*p, *next_portal, *new_portal;
+	node_t		*f, *b, *other_node;
+	int			side;
+	plane_t		*plane;
+	winding_t	*frontwinding, *backwinding;
+
+	plane = &mapplanes[node->planenum];
+	f = node->children[0];
+	b = node->children[1];
+
+	for (p = node->portals ; p ; p = next_portal)	
+	{
+		if (p->nodes[0] == node)
+			side = 0;
+		else if (p->nodes[1] == node)
+			side = 1;
+		else
+			Error ("CutNodePortals_r: mislinked portal");
+		next_portal = p->next[side];
+
+		other_node = p->nodes[!side];
+		RemovePortalFromNode (p, p->nodes[0]);
+		RemovePortalFromNode (p, p->nodes[1]);
+
+//
+// cut the portal into two portals, one on each side of the cut plane
+//
+		ClipWindingEpsilon (p->winding, plane->normal, plane->dist,
+			SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);
+
+		if (frontwinding && WindingIsTiny(frontwinding))
+		{
+			FreeWinding (frontwinding);
+			frontwinding = NULL;
+			c_tinyportals++;
+		}
+
+		if (backwinding && WindingIsTiny(backwinding))
+		{
+			FreeWinding (backwinding);
+			backwinding = NULL;
+			c_tinyportals++;
+		}
+
+		if (!frontwinding && !backwinding)
+		{	// tiny windings on both sides
+			continue;
+		}
+
+		if (!frontwinding)
+		{
+			FreeWinding (backwinding);
+			if (side == 0)
+				AddPortalToNodes (p, b, other_node);
+			else
+				AddPortalToNodes (p, other_node, b);
+			continue;
+		}
+		if (!backwinding)
+		{
+			FreeWinding (frontwinding);
+			if (side == 0)
+				AddPortalToNodes (p, f, other_node);
+			else
+				AddPortalToNodes (p, other_node, f);
+			continue;
+		}
+		
+	// the winding is split
+		new_portal = AllocPortal ();
+		*new_portal = *p;
+		new_portal->winding = backwinding;
+		FreeWinding (p->winding);
+		p->winding = frontwinding;
+
+		if (side == 0)
+		{
+			AddPortalToNodes (p, f, other_node);
+			AddPortalToNodes (new_portal, b, other_node);
+		}
+		else
+		{
+			AddPortalToNodes (p, other_node, f);
+			AddPortalToNodes (new_portal, other_node, b);
+		}
+	}
+
+	node->portals = NULL;
+}
+
+
+/*
+================
+CalcNodeBounds
+================
+*/
+void CalcNodeBounds (node_t *node)
+{
+	portal_t	*p;
+	int			s;
+	int			i;
+
+	// calc mins/maxs for both leafs and nodes
+	ClearBounds (node->mins, node->maxs);
+	for (p = node->portals ; p ; p = p->next[s])	
+	{
+		s = (p->nodes[1] == node);
+		for (i=0 ; i<p->winding->numpoints ; i++)
+			AddPointToBounds (p->winding->p[i], node->mins, node->maxs);
+	}
+}
+
+
+/*
+==================
+MakeTreePortals_r
+==================
+*/
+void MakeTreePortals_r (node_t *node)
+{
+	int		i;
+
+	CalcNodeBounds (node);
+	if (node->mins[0] >= node->maxs[0])
+	{
+		Sys_Printf ("WARNING: node without a volume\n");
+	}
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (node->mins[i] < -8000 || node->maxs[i] > 8000)
+		{
+			Sys_Printf ("WARNING: node with unbounded volume\n");
+			break;
+		}
+	}
+	if (node->planenum == PLANENUM_LEAF)
+		return;
+
+	MakeNodePortal (node);
+	SplitNodePortals (node);
+
+	MakeTreePortals_r (node->children[0]);
+	MakeTreePortals_r (node->children[1]);
+}
+
+/*
+==================
+MakeTreePortals
+==================
+*/
+void MakeTreePortals (tree_t *tree)
+{
+	MakeHeadnodePortals (tree);
+	MakeTreePortals_r (tree->headnode);
+}
+
+/*
+=========================================================
+
+FLOOD ENTITIES
+
+=========================================================
+*/
+
+/*
+=============
+FloodPortals_r
+=============
+*/
+void FloodPortals_r (node_t *node, int dist)
+{
+	portal_t	*p;
+	int			s;
+
+	node->occupied = dist;
+
+	for (p=node->portals ; p ; p = p->next[s])
+	{
+		s = (p->nodes[1] == node);
+
+		if (p->nodes[!s]->occupied)
+			continue;
+
+		if (!Portal_EntityFlood (p, s))
+			continue;
+
+		FloodPortals_r (p->nodes[!s], dist+1);
+	}
+}
+
+/*
+=============
+PlaceOccupant
+=============
+*/
+qboolean PlaceOccupant (node_t *headnode, vec3_t origin, entity_t *occupant)
+{
+	node_t	*node;
+	vec_t	d;
+	plane_t	*plane;
+
+	// find the leaf to start in
+	node = headnode;
+	while (node->planenum != PLANENUM_LEAF)
+	{
+		plane = &mapplanes[node->planenum];
+		d = DotProduct (origin, plane->normal) - plane->dist;
+		if (d >= 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+
+	if (node->contents == CONTENTS_SOLID)
+		return false;
+	node->occupant = occupant;
+
+	FloodPortals_r (node, 1);
+
+	return true;
+}
+
+/*
+=============
+FloodEntities
+
+Marks all nodes that can be reached by entites
+=============
+*/
+qboolean FloodEntities (tree_t *tree)
+{
+	int		i;
+	vec3_t	origin;
+	char	*cl;
+	qboolean	inside;
+	node_t *headnode;
+
+	headnode = tree->headnode;
+	Sys_FPrintf( SYS_VRB, "--- FloodEntities ---\n");
+	inside = false;
+	tree->outside_node.occupied = 0;
+
+	for (i=1 ; i<num_entities ; i++)
+	{
+		GetVectorForKey (&entities[i], "origin", origin);
+		if (VectorCompare(origin, vec3_origin))
+			continue;
+
+		cl = ValueForKey (&entities[i], "classname");
+		origin[2] += 1;	// so objects on floor are ok
+
+		// nudge playerstart around if needed so clipping hulls allways
+		// have a vlaid point
+		if (!strcmp (cl, "info_player_start"))
+		{
+			int	x, y;
+
+			for (x=-16 ; x<=16 ; x += 16)
+			{
+				for (y=-16 ; y<=16 ; y += 16)
+				{
+					origin[0] += x;
+					origin[1] += y;
+					if (PlaceOccupant (headnode, origin, &entities[i]))
+					{
+						inside = true;
+						goto gotit;
+					}
+					origin[0] -= x;
+					origin[1] -= y;
+				}
+			}
+gotit: ;
+		}
+		else
+		{
+			if (PlaceOccupant (headnode, origin, &entities[i]))
+				inside = true;
+		}
+	}
+
+	if (!inside)
+	{
+		Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n");
+	}
+	else if (tree->outside_node.occupied)
+	{
+		Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n");
+	}
+
+	return (qboolean)(inside && !tree->outside_node.occupied);
+}
+
+/*
+=========================================================
+
+FLOOD AREAS
+
+=========================================================
+*/
+
+int		c_areas;
+
+/*
+=============
+FloodAreas_r
+=============
+*/
+void FloodAreas_r (node_t *node)
+{
+	portal_t	*p;
+	int			s;
+	bspbrush_t	*b;
+	entity_t	*e;
+
+	if (node->contents == CONTENTS_AREAPORTAL)
+	{
+		// this node is part of an area portal
+		b = node->brushlist;
+		e = &entities[b->original->entitynum];
+
+		// if the current area has allready touched this
+		// portal, we are done
+		if (e->portalareas[0] == c_areas || e->portalareas[1] == c_areas)
+			return;
+
+		// note the current area as bounding the portal
+		if (e->portalareas[1])
+		{
+			Sys_Printf ("WARNING: areaportal entity %i touches > 2 areas\n", b->original->entitynum);
+			return;
+		}
+		if (e->portalareas[0])
+			e->portalareas[1] = c_areas;
+		else
+			e->portalareas[0] = c_areas;
+
+		return;
+	}
+
+	if (node->area)
+		return;		// allready got it
+	node->area = c_areas;
+
+	for (p=node->portals ; p ; p = p->next[s])
+	{
+		s = (p->nodes[1] == node);
+#if 0
+		if (p->nodes[!s]->occupied)
+			continue;
+#endif
+		if (!Portal_EntityFlood (p, s))
+			continue;
+
+		FloodAreas_r (p->nodes[!s]);
+	}
+}
+
+/*
+=============
+FindAreas_r
+
+Just decend the tree, and for each node that hasn't had an
+area set, flood fill out from there
+=============
+*/
+void FindAreas_r (node_t *node)
+{
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		FindAreas_r (node->children[0]);
+		FindAreas_r (node->children[1]);
+		return;
+	}
+
+	if (node->area)
+		return;		// allready got it
+
+	if (node->contents & CONTENTS_SOLID)
+		return;
+
+	if (!node->occupied)
+		return;			// not reachable by entities
+
+	// area portals are allways only flooded into, never
+	// out of
+	if (node->contents == CONTENTS_AREAPORTAL)
+		return;
+
+	c_areas++;
+	FloodAreas_r (node);
+}
+
+/*
+=============
+SetAreaPortalAreas_r
+
+Just decend the tree, and for each node that hasn't had an
+area set, flood fill out from there
+=============
+*/
+void SetAreaPortalAreas_r (node_t *node)
+{
+	bspbrush_t	*b;
+	entity_t	*e;
+
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		SetAreaPortalAreas_r (node->children[0]);
+		SetAreaPortalAreas_r (node->children[1]);
+		return;
+	}
+
+	if (node->contents == CONTENTS_AREAPORTAL)
+	{
+		if (node->area)
+			return;		// allready set
+
+		b = node->brushlist;
+		e = &entities[b->original->entitynum];
+		node->area = e->portalareas[0];
+		if (!e->portalareas[1])
+		{
+			Sys_Printf ("WARNING: areaportal entity %i doesn't touch two areas\n", b->original->entitynum);
+			return;
+		}
+	}
+}
+
+/*
+=============
+EmitAreaPortals
+
+=============
+*/
+void EmitAreaPortals (node_t *headnode)
+{
+	int				i, j;
+	entity_t		*e;
+	dareaportal_t	*dp;
+
+	if (c_areas > MAX_MAP_AREAS)
+		Error ("MAX_MAP_AREAS");
+	numareas = c_areas+1;
+	numareaportals = 1;		// leave 0 as an error
+
+	for (i=1 ; i<=c_areas ; i++)
+	{
+		dareas[i].firstareaportal = numareaportals;
+		for (j=0 ; j<num_entities ; j++)
+		{
+			e = &entities[j];
+			if (!e->areaportalnum)
+				continue;
+			dp = &dareaportals[numareaportals];
+			if (e->portalareas[0] == i)
+			{
+				dp->portalnum = e->areaportalnum;
+				dp->otherarea = e->portalareas[1];
+				numareaportals++;
+			}
+			else if (e->portalareas[1] == i)
+			{
+				dp->portalnum = e->areaportalnum;
+				dp->otherarea = e->portalareas[0];
+				numareaportals++;
+			}
+		}
+		dareas[i].numareaportals = numareaportals - dareas[i].firstareaportal;
+	}
+
+	Sys_FPrintf( SYS_VRB, "%5i numareas\n", numareas);
+	Sys_FPrintf( SYS_VRB, "%5i numareaportals\n", numareaportals);
+}
+
+/*
+=============
+FloodAreas
+
+Mark each leaf with an area, bounded by CONTENTS_AREAPORTAL
+=============
+*/
+void FloodAreas (tree_t *tree)
+{
+	Sys_FPrintf( SYS_VRB, "--- FloodAreas ---\n");
+	FindAreas_r (tree->headnode);
+	SetAreaPortalAreas_r (tree->headnode);
+	Sys_FPrintf( SYS_VRB, "%5i areas\n", c_areas);
+}
+
+//======================================================
+
+int		c_outside;
+int		c_inside;
+int		c_solid;
+
+void FillOutside_r (node_t *node)
+{
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		FillOutside_r (node->children[0]);
+		FillOutside_r (node->children[1]);
+		return;
+	}
+
+	// anything not reachable by an entity
+	// can be filled away
+	if (!node->occupied)
+	{
+		if (node->contents != CONTENTS_SOLID)
+		{
+			c_outside++;
+			node->contents = CONTENTS_SOLID;
+		}
+		else
+			c_solid++;
+	}
+	else
+		c_inside++;
+
+}
+
+/*
+=============
+FillOutside
+
+Fill all nodes that can't be reached by entities
+=============
+*/
+void FillOutside (node_t *headnode)
+{
+	c_outside = 0;
+	c_inside = 0;
+	c_solid = 0;
+	Sys_FPrintf( SYS_VRB, "--- FillOutside ---\n");
+	FillOutside_r (headnode);
+	Sys_FPrintf( SYS_VRB, "%5i solid leafs\n", c_solid);
+	Sys_FPrintf( SYS_VRB, "%5i leafs filled\n", c_outside);
+	Sys_FPrintf( SYS_VRB, "%5i inside leafs\n", c_inside);
+}
+
+
+//==============================================================
+
+/*
+============
+FindPortalSide
+
+Finds a brush side to use for texturing the given portal
+============
+*/
+void FindPortalSide (portal_t *p)
+{
+	int			viscontents;
+	bspbrush_t	*bb;
+	mapbrush_t	*brush;
+	node_t		*n;
+	int			i,j;
+	int			planenum;
+	side_t		*side, *bestside;
+	float		dot, bestdot;
+	plane_t		*p1, *p2;
+
+	// decide which content change is strongest
+	// solid > lava > water, etc
+	viscontents = VisibleContents (p->nodes[0]->contents ^ p->nodes[1]->contents);
+	if (!viscontents)
+		return;
+
+	planenum = p->onnode->planenum;
+	bestside = NULL;
+	bestdot = 0;
+
+	for (j=0 ; j<2 ; j++)
+	{
+		n = p->nodes[j];
+		p1 = &mapplanes[p->onnode->planenum];
+		for (bb=n->brushlist ; bb ; bb=bb->next)
+		{
+			brush = bb->original;
+			if ( !(brush->contents & viscontents) )
+				continue;
+			for (i=0 ; i<brush->numsides ; i++)
+			{
+				side = &brush->original_sides[i];
+				if (side->bevel)
+					continue;
+				if (side->texinfo == TEXINFO_NODE)
+					continue;		// non-visible
+				if ((side->planenum&~1) == planenum)
+				{	// exact match
+					bestside = &brush->original_sides[i];
+					goto gotit;
+				}
+				// see how close the match is
+				p2 = &mapplanes[side->planenum&~1];
+				dot = DotProduct (p1->normal, p2->normal);
+				if (dot > bestdot)
+				{
+					bestdot = dot;
+					bestside = side;
+				}
+			}
+		}
+	}
+
+gotit:
+	if (!bestside)
+		Sys_FPrintf( SYS_VRB, "WARNING: side not found for portal\n");
+
+	p->sidefound = true;
+	p->side = bestside;
+}
+
+
+/*
+===============
+MarkVisibleSides_r
+
+===============
+*/
+void MarkVisibleSides_r (node_t *node)
+{
+	portal_t	*p;
+	int			s;
+
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		MarkVisibleSides_r (node->children[0]);
+		MarkVisibleSides_r (node->children[1]);
+		return;
+	}
+
+	// empty leafs are never boundary leafs
+	if (!node->contents)
+		return;
+
+	// see if there is a visible face
+	for (p=node->portals ; p ; p = p->next[!s])
+	{
+		s = (p->nodes[0] == node);
+		if (!p->onnode)
+			continue;		// edge of world
+		if (!p->sidefound)
+			FindPortalSide (p);
+		if (p->side)
+			p->side->visible = true;
+	}
+
+}
+
+/*
+=============
+MarkVisibleSides
+
+=============
+*/
+void MarkVisibleSides (tree_t *tree, int startbrush, int endbrush)
+{
+	int		i, j;
+	mapbrush_t	*mb;
+	int		numsides;
+
+	Sys_FPrintf( SYS_VRB, "--- MarkVisibleSides ---\n");
+
+	// clear all the visible flags
+	for (i=startbrush ; i<endbrush ; i++)
+	{
+		mb = &mapbrushes[i];
+
+		numsides = mb->numsides;
+		for (j=0 ; j<numsides ; j++)
+			mb->original_sides[j].visible = false;
+	}
+
+	// set visible flags on the sides that are used by portals
+	MarkVisibleSides_r (tree->headnode);
+}
+
diff --git a/tools/quake2/q2map/prtfile.c b/tools/quake2/q2map/prtfile.c
index c88e039c..bfac302c 100644
--- a/tools/quake2/q2map/prtfile.c
+++ b/tools/quake2/q2map/prtfile.c
@@ -1,286 +1,286 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-/*
-==============================================================================
-
-PORTAL FILE GENERATION
-
-Save out name.prt for qvis to read
-==============================================================================
-*/
-
-
-#define	PORTALFILE	"PRT1"
-
-FILE	*pf;
-int		num_visclusters;				// clusters the player can be in
-int		num_visportals;
-
-void WriteFloat (FILE *f, vec_t v)
-{
-	if ( fabs(v - Q_rint(v)) < 0.001 )
-		fprintf (f,"%i ",(int)Q_rint(v));
-	else
-		fprintf (f,"%f ",v);
-}
-
-/*
-=================
-WritePortalFile_r
-=================
-*/
-void WritePortalFile_r (node_t *node)
-{
-	int			i, s;	
-	portal_t	*p;
-	winding_t	*w;
-	vec3_t		normal;
-	vec_t		dist;
-
-	// decision node
-	if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
-	{
-		WritePortalFile_r (node->children[0]);
-		WritePortalFile_r (node->children[1]);
-		return;
-	}
-	
-	if (node->contents & CONTENTS_SOLID)
-		return;
-
-	for (p = node->portals ; p ; p=p->next[s])
-	{
-		w = p->winding;
-		s = (p->nodes[1] == node);
-		if (w && p->nodes[0] == node)
-		{
-			if (!Portal_VisFlood (p))
-				continue;
-		// write out to the file
-		
-		// sometimes planes get turned around when they are very near
-		// the changeover point between different axis.  interpret the
-		// plane the same way vis will, and flip the side orders if needed
-			// FIXME: is this still relevent?
-			WindingPlane (w, normal, &dist);
-			if ( DotProduct (p->plane.normal, normal) < 0.99 )
-			{	// backwards...
-				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
-			}
-			else
-				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
-			for (i=0 ; i<w->numpoints ; i++)
-			{
-				fprintf (pf,"(");
-				WriteFloat (pf, w->p[i][0]);
-				WriteFloat (pf, w->p[i][1]);
-				WriteFloat (pf, w->p[i][2]);
-				fprintf (pf,") ");
-			}
-			fprintf (pf,"\n");
-		}
-	}
-
-}
-
-/*
-================
-FillLeafNumbers_r
-
-All of the leafs under node will have the same cluster
-================
-*/
-void FillLeafNumbers_r (node_t *node, int num)
-{
-	if (node->planenum == PLANENUM_LEAF)
-	{
-		if (node->contents & CONTENTS_SOLID)
-			node->cluster = -1;
-		else
-			node->cluster = num;
-		return;
-	}
-	node->cluster = num;
-	FillLeafNumbers_r (node->children[0], num);
-	FillLeafNumbers_r (node->children[1], num);
-}
-
-/*
-================
-NumberLeafs_r
-================
-*/
-void NumberLeafs_r (node_t *node)
-{
-	portal_t	*p;
-
-	if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
-	{	// decision node
-		node->cluster = -99;
-		NumberLeafs_r (node->children[0]);
-		NumberLeafs_r (node->children[1]);
-		return;
-	}
-	
-	// either a leaf or a detail cluster
-
-	if ( node->contents & CONTENTS_SOLID )
-	{	// solid block, viewpoint never inside
-		node->cluster = -1;
-		return;
-	}
-
-	FillLeafNumbers_r (node, num_visclusters);
-	num_visclusters++;
-
-	// count the portals
-	for (p = node->portals ; p ; )
-	{
-		if (p->nodes[0] == node)		// only write out from first leaf
-		{
-			if (Portal_VisFlood (p))
-				num_visportals++;
-			p = p->next[0];
-		}
-		else
-			p = p->next[1];		
-	}
-
-}
-
-
-/*
-================
-CreateVisPortals_r
-================
-*/
-void CreateVisPortals_r (node_t *node)
-{
-	// stop as soon as we get to a detail_seperator, which
-	// means that everything below is in a single cluster
-	if (node->planenum == PLANENUM_LEAF || node->detail_seperator )
-		return;
-
-	MakeNodePortal (node);
-	SplitNodePortals (node);
-
-	CreateVisPortals_r (node->children[0]);
-	CreateVisPortals_r (node->children[1]);
-}
-
-/*
-================
-FinishVisPortals_r
-================
-*/
-void FinishVisPortals2_r (node_t *node)
-{
-	if (node->planenum == PLANENUM_LEAF)
-		return;
-
-	MakeNodePortal (node);
-	SplitNodePortals (node);
-
-	FinishVisPortals2_r (node->children[0]);
-	FinishVisPortals2_r (node->children[1]);
-}
-
-void FinishVisPortals_r (node_t *node)
-{
-	if (node->planenum == PLANENUM_LEAF)
-		return;
-
-	if (node->detail_seperator)
-	{
-		FinishVisPortals2_r (node);
-		return;
-	}
-
-	FinishVisPortals_r (node->children[0]);
-	FinishVisPortals_r (node->children[1]);
-}
-
-
-int		clusterleaf;
-void SaveClusters_r (node_t *node)
-{
-	if (node->planenum == PLANENUM_LEAF)
-	{
-		dleafs[clusterleaf++].cluster = node->cluster;
-		return;
-	}
-	SaveClusters_r (node->children[0]);
-	SaveClusters_r (node->children[1]);
-}
-
-/*
-================
-WritePortalFile
-================
-*/
-void WritePortalFile (tree_t *tree)
-{
-	char	filename[1024];
-	node_t *headnode;
-
-	Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n");
-
-	headnode = tree->headnode;
-	num_visclusters = 0;
-	num_visportals = 0;
-
-	FreeTreePortals_r (headnode);
-
-	MakeHeadnodePortals (tree);
-
-	CreateVisPortals_r (headnode);
-
-// set the cluster field in every leaf and count the total number of portals
-
-	NumberLeafs_r (headnode);
-	
-// write the file
-	sprintf (filename, "%s.prt", source);
-	Sys_Printf ("writing %s\n", filename);
-	pf = fopen (filename, "w");
-	if (!pf)
-		Error ("Error opening %s", filename);
-		
-	fprintf (pf, "%s\n", PORTALFILE);
-	fprintf (pf, "%i\n", num_visclusters);
-	fprintf (pf, "%i\n", num_visportals);
-
-	Sys_FPrintf( SYS_VRB, "%5i visclusters\n", num_visclusters);
-	Sys_FPrintf( SYS_VRB, "%5i visportals\n", num_visportals);
-
-	WritePortalFile_r (headnode);
-
-	fclose (pf);
-
-	// we need to store the clusters out now because ordering
-	// issues made us do this after writebsp...
-	clusterleaf = 1;
-	SaveClusters_r (headnode);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+/*
+==============================================================================
+
+PORTAL FILE GENERATION
+
+Save out name.prt for qvis to read
+==============================================================================
+*/
+
+
+#define	PORTALFILE	"PRT1"
+
+FILE	*pf;
+int		num_visclusters;				// clusters the player can be in
+int		num_visportals;
+
+void WriteFloat (FILE *f, vec_t v)
+{
+	if ( fabs(v - Q_rint(v)) < 0.001 )
+		fprintf (f,"%i ",(int)Q_rint(v));
+	else
+		fprintf (f,"%f ",v);
+}
+
+/*
+=================
+WritePortalFile_r
+=================
+*/
+void WritePortalFile_r (node_t *node)
+{
+	int			i, s;	
+	portal_t	*p;
+	winding_t	*w;
+	vec3_t		normal;
+	vec_t		dist;
+
+	// decision node
+	if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
+	{
+		WritePortalFile_r (node->children[0]);
+		WritePortalFile_r (node->children[1]);
+		return;
+	}
+	
+	if (node->contents & CONTENTS_SOLID)
+		return;
+
+	for (p = node->portals ; p ; p=p->next[s])
+	{
+		w = p->winding;
+		s = (p->nodes[1] == node);
+		if (w && p->nodes[0] == node)
+		{
+			if (!Portal_VisFlood (p))
+				continue;
+		// write out to the file
+		
+		// sometimes planes get turned around when they are very near
+		// the changeover point between different axis.  interpret the
+		// plane the same way vis will, and flip the side orders if needed
+			// FIXME: is this still relevent?
+			WindingPlane (w, normal, &dist);
+			if ( DotProduct (p->plane.normal, normal) < 0.99 )
+			{	// backwards...
+				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
+			}
+			else
+				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
+			for (i=0 ; i<w->numpoints ; i++)
+			{
+				fprintf (pf,"(");
+				WriteFloat (pf, w->p[i][0]);
+				WriteFloat (pf, w->p[i][1]);
+				WriteFloat (pf, w->p[i][2]);
+				fprintf (pf,") ");
+			}
+			fprintf (pf,"\n");
+		}
+	}
+
+}
+
+/*
+================
+FillLeafNumbers_r
+
+All of the leafs under node will have the same cluster
+================
+*/
+void FillLeafNumbers_r (node_t *node, int num)
+{
+	if (node->planenum == PLANENUM_LEAF)
+	{
+		if (node->contents & CONTENTS_SOLID)
+			node->cluster = -1;
+		else
+			node->cluster = num;
+		return;
+	}
+	node->cluster = num;
+	FillLeafNumbers_r (node->children[0], num);
+	FillLeafNumbers_r (node->children[1], num);
+}
+
+/*
+================
+NumberLeafs_r
+================
+*/
+void NumberLeafs_r (node_t *node)
+{
+	portal_t	*p;
+
+	if (node->planenum != PLANENUM_LEAF && !node->detail_seperator)
+	{	// decision node
+		node->cluster = -99;
+		NumberLeafs_r (node->children[0]);
+		NumberLeafs_r (node->children[1]);
+		return;
+	}
+	
+	// either a leaf or a detail cluster
+
+	if ( node->contents & CONTENTS_SOLID )
+	{	// solid block, viewpoint never inside
+		node->cluster = -1;
+		return;
+	}
+
+	FillLeafNumbers_r (node, num_visclusters);
+	num_visclusters++;
+
+	// count the portals
+	for (p = node->portals ; p ; )
+	{
+		if (p->nodes[0] == node)		// only write out from first leaf
+		{
+			if (Portal_VisFlood (p))
+				num_visportals++;
+			p = p->next[0];
+		}
+		else
+			p = p->next[1];		
+	}
+
+}
+
+
+/*
+================
+CreateVisPortals_r
+================
+*/
+void CreateVisPortals_r (node_t *node)
+{
+	// stop as soon as we get to a detail_seperator, which
+	// means that everything below is in a single cluster
+	if (node->planenum == PLANENUM_LEAF || node->detail_seperator )
+		return;
+
+	MakeNodePortal (node);
+	SplitNodePortals (node);
+
+	CreateVisPortals_r (node->children[0]);
+	CreateVisPortals_r (node->children[1]);
+}
+
+/*
+================
+FinishVisPortals_r
+================
+*/
+void FinishVisPortals2_r (node_t *node)
+{
+	if (node->planenum == PLANENUM_LEAF)
+		return;
+
+	MakeNodePortal (node);
+	SplitNodePortals (node);
+
+	FinishVisPortals2_r (node->children[0]);
+	FinishVisPortals2_r (node->children[1]);
+}
+
+void FinishVisPortals_r (node_t *node)
+{
+	if (node->planenum == PLANENUM_LEAF)
+		return;
+
+	if (node->detail_seperator)
+	{
+		FinishVisPortals2_r (node);
+		return;
+	}
+
+	FinishVisPortals_r (node->children[0]);
+	FinishVisPortals_r (node->children[1]);
+}
+
+
+int		clusterleaf;
+void SaveClusters_r (node_t *node)
+{
+	if (node->planenum == PLANENUM_LEAF)
+	{
+		dleafs[clusterleaf++].cluster = node->cluster;
+		return;
+	}
+	SaveClusters_r (node->children[0]);
+	SaveClusters_r (node->children[1]);
+}
+
+/*
+================
+WritePortalFile
+================
+*/
+void WritePortalFile (tree_t *tree)
+{
+	char	filename[1024];
+	node_t *headnode;
+
+	Sys_FPrintf( SYS_VRB, "--- WritePortalFile ---\n");
+
+	headnode = tree->headnode;
+	num_visclusters = 0;
+	num_visportals = 0;
+
+	FreeTreePortals_r (headnode);
+
+	MakeHeadnodePortals (tree);
+
+	CreateVisPortals_r (headnode);
+
+// set the cluster field in every leaf and count the total number of portals
+
+	NumberLeafs_r (headnode);
+	
+// write the file
+	sprintf (filename, "%s.prt", source);
+	Sys_Printf ("writing %s\n", filename);
+	pf = fopen (filename, "w");
+	if (!pf)
+		Error ("Error opening %s", filename);
+		
+	fprintf (pf, "%s\n", PORTALFILE);
+	fprintf (pf, "%i\n", num_visclusters);
+	fprintf (pf, "%i\n", num_visportals);
+
+	Sys_FPrintf( SYS_VRB, "%5i visclusters\n", num_visclusters);
+	Sys_FPrintf( SYS_VRB, "%5i visportals\n", num_visportals);
+
+	WritePortalFile_r (headnode);
+
+	fclose (pf);
+
+	// we need to store the clusters out now because ordering
+	// issues made us do this after writebsp...
+	clusterleaf = 1;
+	SaveClusters_r (headnode);
+}
+
diff --git a/tools/quake2/q2map/q2map.h b/tools/quake2/q2map/q2map.h
index 159232d8..7303263c 100644
--- a/tools/quake2/q2map/q2map.h
+++ b/tools/quake2/q2map/q2map.h
@@ -1,50 +1,50 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// q2map.h
-
-/* platform-specific */
-#if defined( __linux__ ) || defined( __APPLE__ )
-	#define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
-	#include <unistd.h>
-	#include <pwd.h>
-	#include <limits.h>
-#endif
-
-#ifdef _WIN32
-	#include <windows.h>
-#endif
-
-#include <stdlib.h>
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "scriplib.h"
-#include "polylib.h"
-#include "q2_threads.h"
-#include "bspfile.h"
-#include "inout.h"
-
-int BSP_Main ();
-int VIS_Main ();
-int RAD_Main ();
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// q2map.h
+
+/* platform-specific */
+#if defined( __linux__ ) || defined( __APPLE__ )
+	#define Q_UNIX
+#endif
+
+#ifdef Q_UNIX
+	#include <unistd.h>
+	#include <pwd.h>
+	#include <limits.h>
+#endif
+
+#ifdef _WIN32
+	#include <windows.h>
+#endif
+
+#include <stdlib.h>
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "scriplib.h"
+#include "polylib.h"
+#include "q2_threads.h"
+#include "bspfile.h"
+#include "inout.h"
+
+int BSP_Main ();
+int VIS_Main ();
+int RAD_Main ();
diff --git a/tools/quake2/q2map/qbsp.c b/tools/quake2/q2map/qbsp.c
index 84e4570c..4f1180da 100644
--- a/tools/quake2/q2map/qbsp.c
+++ b/tools/quake2/q2map/qbsp.c
@@ -1,426 +1,426 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// csg4.c
-
-#include "qbsp.h"
-
-extern	float subdivide_size;
-
-char		source[1024];
-char		name[1024];
-
-vec_t		microvolume = 1.0;
-qboolean	noprune;
-qboolean	glview;
-qboolean	nodetail;
-qboolean	fulldetail;
-qboolean	onlyents;
-qboolean	nomerge;
-qboolean	nowater;
-qboolean	nofill;
-qboolean	nocsg;
-qboolean	noweld;
-qboolean	noshare;
-qboolean	nosubdiv;
-qboolean	notjunc;
-qboolean	noopt;
-qboolean	leaktest;
-qboolean	verboseentities;
-
-char		outbase[32];
-
-int			block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
-
-int			entity_num;
-
-
-node_t		*block_nodes[10][10];
-
-
-/*
-============
-BlockTree
-
-============
-*/
-node_t	*BlockTree (int xl, int yl, int xh, int yh)
-{
-	node_t	*node;
-	vec3_t	normal;
-	float	dist;
-	int		mid;
-
-	if (xl == xh && yl == yh)
-	{
-		node = block_nodes[xl+5][yl+5];
-		if (!node)
-		{	// return an empty leaf
-			node = AllocNode ();
-			node->planenum = PLANENUM_LEAF;
-			node->contents = 0; //CONTENTS_SOLID;
-			return node;
-		}
-		return node;
-	}
-
-	// create a seperator along the largest axis
-	node = AllocNode ();
-
-	if (xh - xl > yh - yl)
-	{	// split x axis
-		mid = xl + (xh-xl)/2 + 1;
-		normal[0] = 1;
-		normal[1] = 0;
-		normal[2] = 0;
-		dist = mid*1024;
-		node->planenum = FindFloatPlane (normal, dist);
-		node->children[0] = BlockTree ( mid, yl, xh, yh);
-		node->children[1] = BlockTree ( xl, yl, mid-1, yh);
-	}
-	else
-	{
-		mid = yl + (yh-yl)/2 + 1;
-		normal[0] = 0;
-		normal[1] = 1;
-		normal[2] = 0;
-		dist = mid*1024;
-		node->planenum = FindFloatPlane (normal, dist);
-		node->children[0] = BlockTree ( xl, mid, xh, yh);
-		node->children[1] = BlockTree ( xl, yl, xh, mid-1);
-	}
-
-	return node;
-}
-
-/*
-============
-ProcessBlock_Thread
-
-============
-*/
-int			brush_start, brush_end;
-void ProcessBlock_Thread (int blocknum)
-{
-	int		xblock, yblock;
-	vec3_t		mins, maxs;
-	bspbrush_t	*brushes;
-	tree_t		*tree;
-	node_t		*node;
-
-	yblock = block_yl + blocknum / (block_xh-block_xl+1);
-	xblock = block_xl + blocknum % (block_xh-block_xl+1);
-
-	Sys_FPrintf( SYS_VRB, "############### block %2i,%2i ###############\n", xblock, yblock);
-
-	mins[0] = xblock*1024;
-	mins[1] = yblock*1024;
-	mins[2] = -4096;
-	maxs[0] = (xblock+1)*1024;
-	maxs[1] = (yblock+1)*1024;
-	maxs[2] = 4096;
-
-	// the makelist and chopbrushes could be cached between the passes...
-	brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs);
-	if (!brushes)
-	{
-		node = AllocNode ();
-		node->planenum = PLANENUM_LEAF;
-		node->contents = CONTENTS_SOLID;
-		block_nodes[xblock+5][yblock+5] = node;
-		return;
-	}
-
-	if (!nocsg)
-		brushes = ChopBrushes (brushes);
-
-	tree = BrushBSP (brushes, mins, maxs);
-
-	block_nodes[xblock+5][yblock+5] = tree->headnode;
-}
-
-/*
-============
-ProcessWorldModel
-
-============
-*/
-void ProcessWorldModel (void)
-{
-	entity_t	*e;
-	tree_t		*tree;
-	qboolean	leaked;
-	qboolean	optimize;
- 	xmlNodePtr	polyline, leaknode;
-  char		level[ 2 ];
-
-	e = &entities[entity_num];
-
-	brush_start = e->firstbrush;
-	brush_end = brush_start + e->numbrushes;
-	leaked = false;
-
-	//
-	// perform per-block operations
-	//
-	if (block_xh * 1024 > map_maxs[0])
-		block_xh = floor(map_maxs[0]/1024.0);
-	if ( (block_xl+1) * 1024 < map_mins[0])
-		block_xl = floor(map_mins[0]/1024.0);
-	if (block_yh * 1024 > map_maxs[1])
-		block_yh = floor(map_maxs[1]/1024.0);
-	if ( (block_yl+1) * 1024 < map_mins[1])
-		block_yl = floor(map_mins[1]/1024.0);
-
-	if (block_xl <-4)
-		block_xl = -4;
-	if (block_yl <-4)
-		block_yl = -4;
-	if (block_xh > 3)
-		block_xh = 3;
-	if (block_yh > 3)
-		block_yh = 3;
-
-	for (optimize = false ; optimize <= true ; optimize++)
-	{
-		Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
-
-		RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1),
-			!verbose, ProcessBlock_Thread);
-
-		//
-		// build the division tree
-		// oversizing the blocks guarantees that all the boundaries
-		// will also get nodes.
-		//
-
-		Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
-
-		tree = AllocTree ();
-		tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1);
-
-		tree->mins[0] = (block_xl)*1024;
-		tree->mins[1] = (block_yl)*1024;
-		tree->mins[2] = map_mins[2] - 8;
-
-		tree->maxs[0] = (block_xh+1)*1024;
-		tree->maxs[1] = (block_yh+1)*1024;
-		tree->maxs[2] = map_maxs[2] + 8;
-
-		//
-		// perform the global operations
-		//
-		MakeTreePortals (tree);
-
-		if (FloodEntities (tree))
-			FillOutside (tree->headnode);
-		else
-		{
-
-      Sys_FPrintf( SYS_NOXML, "**********************\n" );
-		Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
-		Sys_FPrintf( SYS_NOXML, "**********************\n" );
-		polyline = LeakFile( tree );
-		leaknode = xmlNewNode( NULL, "message" );
-		xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
-		xmlAddChild( leaknode, polyline );
-		level[0] = (int) '0' + SYS_ERR;
-		level[1] = 0;
-		xmlSetProp( leaknode, "level", (char*) &level );
-		xml_SendNode( leaknode );
-		if( leaktest )
-		{
-			Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
-			exit( 0 );
-		}
-		leaked = true;
-/*
-			Sys_Printf ("**** leaked ****\n");
-			leaked = true;
-			LeakFile (tree);
-			if (leaktest)
-			{
-				Sys_Printf ("--- MAP LEAKED ---\n");
-				exit (0);
-			} */
-		}
-
-		MarkVisibleSides (tree, brush_start, brush_end);
-		if (noopt || leaked)
-			break;
-		if (!optimize)
-		{
-			FreeTree (tree);
-		}
-	}
-
-	FloodAreas (tree);
-	if (glview)
-		WriteGLView (tree, source);
-	MakeFaces (tree->headnode);
-	FixTjuncs (tree->headnode);
-
-	if (!noprune)
-		PruneNodes (tree->headnode);
-
-	WriteBSP (tree->headnode);
-
-	if (!leaked)
-		WritePortalFile (tree);
-
-	FreeTree (tree);
-}
-
-/*
-============
-ProcessSubModel
-
-============
-*/
-void ProcessSubModel (void)
-{
-	entity_t	*e;
-	int			start, end;
-	tree_t		*tree;
-	bspbrush_t	*list;
-	vec3_t		mins, maxs;
-
-	e = &entities[entity_num];
-
-	start = e->firstbrush;
-	end = start + e->numbrushes;
-
-	mins[0] = mins[1] = mins[2] = -4096;
-	maxs[0] = maxs[1] = maxs[2] = 4096;
-	list = MakeBspBrushList (start, end, mins, maxs);
-	if (!nocsg)
-		list = ChopBrushes (list);
-	tree = BrushBSP (list, mins, maxs);
-	MakeTreePortals (tree);
-	MarkVisibleSides (tree, start, end);
-	MakeFaces (tree->headnode);
-	FixTjuncs (tree->headnode);
-	WriteBSP (tree->headnode);
-	FreeTree (tree);
-}
-
-/*
-============
-ProcessModels
-============
-*/
-void ProcessModels (void)
-{
-	BeginBSPFile ();
-
-	for (entity_num=0 ; entity_num< num_entities ; entity_num++)
-	{
-		if (!entities[entity_num].numbrushes)
-			continue;
-
-		Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", nummodels);
-		BeginModel ();
-		if (entity_num == 0)
-			ProcessWorldModel ();
-		else
-			ProcessSubModel ();
-		EndModel ();
-
-		//if (!verboseentities)
-		//	verbose = false;	// don't bother printing submodels
-	}
-
-	EndBSPFile ();
-}
-
-
-/*
-============
-main
-============
-*/
-int BSP_Main ()
-{
-	double		start, end;
-	char		path[1024];
-	int		total_bsp_time;
-
-	Sys_Printf ("\n----- BSP ----\n\n");
-
-	
-	start = I_FloatTime ();
-
-	ThreadSetDefault ();
-	SetQdirFromPath (mapname);
-
-	strcpy (source, ExpandArg (mapname));
-	StripExtension (source);
-
-	// delete portal and line files
-	sprintf (path, "%s.prt", source);
-	remove (path);
-	sprintf (path, "%s.lin", source);
-	remove (path);
-
-	strcpy (name, ExpandArg (mapname));	
-	DefaultExtension (name, ".map");	// might be .reg
-
-	//
-	// if onlyents, just grab the entites and resave
-	//
-	if (onlyents)
-	{
-		char out[1024];
-
-		sprintf (out, "%s.bsp", source);
-		LoadBSPFile (out);
-		num_entities = 0;
-
-		LoadMapFile (name);
-		SetModelNumbers ();
-		SetLightStyles ();
-
-		UnparseEntities ();
-
-		WriteBSPFile (out);
-	}
-	else
-	{
-		//
-		// start from scratch
-		//
-		LoadMapFile (name);
-		SetModelNumbers ();
-		SetLightStyles ();
-
-		ProcessModels ();
-	}
-
-	end = I_FloatTime ();
-	total_bsp_time = (int) (end-start);
-	Sys_Printf("\nBSP Time: ");
-	if ( total_bsp_time > 59 )
-		Sys_Printf("%d Minutes ", total_bsp_time/60 );
-	Sys_Printf( "%d Seconds\n", total_bsp_time%60 );
-
-
-	return 0;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// csg4.c
+
+#include "qbsp.h"
+
+extern	float subdivide_size;
+
+char		source[1024];
+char		name[1024];
+
+vec_t		microvolume = 1.0;
+qboolean	noprune;
+qboolean	glview;
+qboolean	nodetail;
+qboolean	fulldetail;
+qboolean	onlyents;
+qboolean	nomerge;
+qboolean	nowater;
+qboolean	nofill;
+qboolean	nocsg;
+qboolean	noweld;
+qboolean	noshare;
+qboolean	nosubdiv;
+qboolean	notjunc;
+qboolean	noopt;
+qboolean	leaktest;
+qboolean	verboseentities;
+
+char		outbase[32];
+
+int			block_xl = -8, block_xh = 7, block_yl = -8, block_yh = 7;
+
+int			entity_num;
+
+
+node_t		*block_nodes[10][10];
+
+
+/*
+============
+BlockTree
+
+============
+*/
+node_t	*BlockTree (int xl, int yl, int xh, int yh)
+{
+	node_t	*node;
+	vec3_t	normal;
+	float	dist;
+	int		mid;
+
+	if (xl == xh && yl == yh)
+	{
+		node = block_nodes[xl+5][yl+5];
+		if (!node)
+		{	// return an empty leaf
+			node = AllocNode ();
+			node->planenum = PLANENUM_LEAF;
+			node->contents = 0; //CONTENTS_SOLID;
+			return node;
+		}
+		return node;
+	}
+
+	// create a seperator along the largest axis
+	node = AllocNode ();
+
+	if (xh - xl > yh - yl)
+	{	// split x axis
+		mid = xl + (xh-xl)/2 + 1;
+		normal[0] = 1;
+		normal[1] = 0;
+		normal[2] = 0;
+		dist = mid*1024;
+		node->planenum = FindFloatPlane (normal, dist);
+		node->children[0] = BlockTree ( mid, yl, xh, yh);
+		node->children[1] = BlockTree ( xl, yl, mid-1, yh);
+	}
+	else
+	{
+		mid = yl + (yh-yl)/2 + 1;
+		normal[0] = 0;
+		normal[1] = 1;
+		normal[2] = 0;
+		dist = mid*1024;
+		node->planenum = FindFloatPlane (normal, dist);
+		node->children[0] = BlockTree ( xl, mid, xh, yh);
+		node->children[1] = BlockTree ( xl, yl, xh, mid-1);
+	}
+
+	return node;
+}
+
+/*
+============
+ProcessBlock_Thread
+
+============
+*/
+int			brush_start, brush_end;
+void ProcessBlock_Thread (int blocknum)
+{
+	int		xblock, yblock;
+	vec3_t		mins, maxs;
+	bspbrush_t	*brushes;
+	tree_t		*tree;
+	node_t		*node;
+
+	yblock = block_yl + blocknum / (block_xh-block_xl+1);
+	xblock = block_xl + blocknum % (block_xh-block_xl+1);
+
+	Sys_FPrintf( SYS_VRB, "############### block %2i,%2i ###############\n", xblock, yblock);
+
+	mins[0] = xblock*1024;
+	mins[1] = yblock*1024;
+	mins[2] = -4096;
+	maxs[0] = (xblock+1)*1024;
+	maxs[1] = (yblock+1)*1024;
+	maxs[2] = 4096;
+
+	// the makelist and chopbrushes could be cached between the passes...
+	brushes = MakeBspBrushList (brush_start, brush_end, mins, maxs);
+	if (!brushes)
+	{
+		node = AllocNode ();
+		node->planenum = PLANENUM_LEAF;
+		node->contents = CONTENTS_SOLID;
+		block_nodes[xblock+5][yblock+5] = node;
+		return;
+	}
+
+	if (!nocsg)
+		brushes = ChopBrushes (brushes);
+
+	tree = BrushBSP (brushes, mins, maxs);
+
+	block_nodes[xblock+5][yblock+5] = tree->headnode;
+}
+
+/*
+============
+ProcessWorldModel
+
+============
+*/
+void ProcessWorldModel (void)
+{
+	entity_t	*e;
+	tree_t		*tree;
+	qboolean	leaked;
+	qboolean	optimize;
+ 	xmlNodePtr	polyline, leaknode;
+  char		level[ 2 ];
+
+	e = &entities[entity_num];
+
+	brush_start = e->firstbrush;
+	brush_end = brush_start + e->numbrushes;
+	leaked = false;
+
+	//
+	// perform per-block operations
+	//
+	if (block_xh * 1024 > map_maxs[0])
+		block_xh = floor(map_maxs[0]/1024.0);
+	if ( (block_xl+1) * 1024 < map_mins[0])
+		block_xl = floor(map_mins[0]/1024.0);
+	if (block_yh * 1024 > map_maxs[1])
+		block_yh = floor(map_maxs[1]/1024.0);
+	if ( (block_yl+1) * 1024 < map_mins[1])
+		block_yl = floor(map_mins[1]/1024.0);
+
+	if (block_xl <-4)
+		block_xl = -4;
+	if (block_yl <-4)
+		block_yl = -4;
+	if (block_xh > 3)
+		block_xh = 3;
+	if (block_yh > 3)
+		block_yh = 3;
+
+	for (optimize = false ; optimize <= true ; optimize++)
+	{
+		Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
+
+		RunThreadsOnIndividual ((block_xh-block_xl+1)*(block_yh-block_yl+1),
+			!verbose, ProcessBlock_Thread);
+
+		//
+		// build the division tree
+		// oversizing the blocks guarantees that all the boundaries
+		// will also get nodes.
+		//
+
+		Sys_FPrintf( SYS_VRB, "--------------------------------------------\n");
+
+		tree = AllocTree ();
+		tree->headnode = BlockTree (block_xl-1, block_yl-1, block_xh+1, block_yh+1);
+
+		tree->mins[0] = (block_xl)*1024;
+		tree->mins[1] = (block_yl)*1024;
+		tree->mins[2] = map_mins[2] - 8;
+
+		tree->maxs[0] = (block_xh+1)*1024;
+		tree->maxs[1] = (block_yh+1)*1024;
+		tree->maxs[2] = map_maxs[2] + 8;
+
+		//
+		// perform the global operations
+		//
+		MakeTreePortals (tree);
+
+		if (FloodEntities (tree))
+			FillOutside (tree->headnode);
+		else
+		{
+
+      Sys_FPrintf( SYS_NOXML, "**********************\n" );
+		Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
+		Sys_FPrintf( SYS_NOXML, "**********************\n" );
+		polyline = LeakFile( tree );
+		leaknode = xmlNewNode( NULL, "message" );
+		xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
+		xmlAddChild( leaknode, polyline );
+		level[0] = (int) '0' + SYS_ERR;
+		level[1] = 0;
+		xmlSetProp( leaknode, "level", (char*) &level );
+		xml_SendNode( leaknode );
+		if( leaktest )
+		{
+			Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
+			exit( 0 );
+		}
+		leaked = true;
+/*
+			Sys_Printf ("**** leaked ****\n");
+			leaked = true;
+			LeakFile (tree);
+			if (leaktest)
+			{
+				Sys_Printf ("--- MAP LEAKED ---\n");
+				exit (0);
+			} */
+		}
+
+		MarkVisibleSides (tree, brush_start, brush_end);
+		if (noopt || leaked)
+			break;
+		if (!optimize)
+		{
+			FreeTree (tree);
+		}
+	}
+
+	FloodAreas (tree);
+	if (glview)
+		WriteGLView (tree, source);
+	MakeFaces (tree->headnode);
+	FixTjuncs (tree->headnode);
+
+	if (!noprune)
+		PruneNodes (tree->headnode);
+
+	WriteBSP (tree->headnode);
+
+	if (!leaked)
+		WritePortalFile (tree);
+
+	FreeTree (tree);
+}
+
+/*
+============
+ProcessSubModel
+
+============
+*/
+void ProcessSubModel (void)
+{
+	entity_t	*e;
+	int			start, end;
+	tree_t		*tree;
+	bspbrush_t	*list;
+	vec3_t		mins, maxs;
+
+	e = &entities[entity_num];
+
+	start = e->firstbrush;
+	end = start + e->numbrushes;
+
+	mins[0] = mins[1] = mins[2] = -4096;
+	maxs[0] = maxs[1] = maxs[2] = 4096;
+	list = MakeBspBrushList (start, end, mins, maxs);
+	if (!nocsg)
+		list = ChopBrushes (list);
+	tree = BrushBSP (list, mins, maxs);
+	MakeTreePortals (tree);
+	MarkVisibleSides (tree, start, end);
+	MakeFaces (tree->headnode);
+	FixTjuncs (tree->headnode);
+	WriteBSP (tree->headnode);
+	FreeTree (tree);
+}
+
+/*
+============
+ProcessModels
+============
+*/
+void ProcessModels (void)
+{
+	BeginBSPFile ();
+
+	for (entity_num=0 ; entity_num< num_entities ; entity_num++)
+	{
+		if (!entities[entity_num].numbrushes)
+			continue;
+
+		Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", nummodels);
+		BeginModel ();
+		if (entity_num == 0)
+			ProcessWorldModel ();
+		else
+			ProcessSubModel ();
+		EndModel ();
+
+		//if (!verboseentities)
+		//	verbose = false;	// don't bother printing submodels
+	}
+
+	EndBSPFile ();
+}
+
+
+/*
+============
+main
+============
+*/
+int BSP_Main ()
+{
+	double		start, end;
+	char		path[1024];
+	int		total_bsp_time;
+
+	Sys_Printf ("\n----- BSP ----\n\n");
+
+	
+	start = I_FloatTime ();
+
+	ThreadSetDefault ();
+	SetQdirFromPath (mapname);
+
+	strcpy (source, ExpandArg (mapname));
+	StripExtension (source);
+
+	// delete portal and line files
+	sprintf (path, "%s.prt", source);
+	remove (path);
+	sprintf (path, "%s.lin", source);
+	remove (path);
+
+	strcpy (name, ExpandArg (mapname));	
+	DefaultExtension (name, ".map");	// might be .reg
+
+	//
+	// if onlyents, just grab the entites and resave
+	//
+	if (onlyents)
+	{
+		char out[1024];
+
+		sprintf (out, "%s.bsp", source);
+		LoadBSPFile (out);
+		num_entities = 0;
+
+		LoadMapFile (name);
+		SetModelNumbers ();
+		SetLightStyles ();
+
+		UnparseEntities ();
+
+		WriteBSPFile (out);
+	}
+	else
+	{
+		//
+		// start from scratch
+		//
+		LoadMapFile (name);
+		SetModelNumbers ();
+		SetLightStyles ();
+
+		ProcessModels ();
+	}
+
+	end = I_FloatTime ();
+	total_bsp_time = (int) (end-start);
+	Sys_Printf("\nBSP Time: ");
+	if ( total_bsp_time > 59 )
+		Sys_Printf("%d Minutes ", total_bsp_time/60 );
+	Sys_Printf( "%d Seconds\n", total_bsp_time%60 );
+
+
+	return 0;
+}
+
diff --git a/tools/quake2/q2map/qbsp.h b/tools/quake2/q2map/qbsp.h
index ecfaa7ca..47d8d4b5 100644
--- a/tools/quake2/q2map/qbsp.h
+++ b/tools/quake2/q2map/qbsp.h
@@ -1,390 +1,390 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/* Files:
-
-brushbsp.c
-csg.c
-faces.c
-gldraw.c
-glfile.c
-leakfile.c
-map.c
-nodraw.c
-portals.c
-prtfile.c
-qbsp3.c
-textures.c
-tree.c
-writebsp.c
-
-*/
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "scriplib.h"
-#include "polylib.h"
-#include "q2_threads.h"
-#include "bspfile.h"
-#include "inout.h"
-
-#ifdef _WIN32
-	#ifdef NDEBUG							// Don't show in a Release build
-		#pragma warning(disable : 4305)     // truncate from double to float
-		#pragma warning(disable : 4244)     // conversion from double to float
-		#pragma warning(disable : 4018)     // signed/unsigned mismatch
-	#endif
-#endif
-
-#define	MAX_BRUSH_SIDES	128
-#define	CLIP_EPSILON	0.1
-
-#define	BOGUS_RANGE	8192
-
-#define	TEXINFO_NODE		-1		// side is allready on a node
-
-typedef struct plane_s
-{
-	vec3_t	normal;
-	vec_t	dist;
-	int		type;
-	struct plane_s	*hash_chain;
-} plane_t;
-
-typedef struct
-{
-	vec_t	shift[2];
-	vec_t	rotate;
-	vec_t	scale[2];
-	char	name[32];
-	int		flags;
-	int		value;
-} brush_texture_t;
-
-typedef struct side_s
-{
-	int			planenum;
-	int			texinfo;
-	winding_t	*winding;
-	struct side_s	*original;	// bspbrush_t sides will reference the mapbrush_t sides
-	int			contents;		// from miptex
-	int			surf;			// from miptex
-	qboolean	visible;		// choose visble planes first
-	qboolean	tested;			// this plane allready checked as a split
-	qboolean	bevel;			// don't ever use for bsp splitting
-} side_t;
-
-typedef struct brush_s
-{
-	int		entitynum;
-	int		brushnum;
-
-	int		contents;
-
-	vec3_t	mins, maxs;
-
-	int		numsides;
-	side_t	*original_sides;
-} mapbrush_t;
-
-#define	PLANENUM_LEAF			-1
-
-#define	MAXEDGES		20
-
-typedef struct face_s
-{
-	struct face_s	*next;		// on node
-
-	// the chain of faces off of a node can be merged or split,
-	// but each face_t along the way will remain in the chain
-	// until the entire tree is freed
-	struct face_s	*merged;	// if set, this face isn't valid anymore
-	struct face_s	*split[2];	// if set, this face isn't valid anymore
-
-	struct portal_s	*portal;
-	int				texinfo;
-	int				planenum;
-	int				contents;	// faces in different contents can't merge
-	int				outputnumber;
-	winding_t		*w;
-	int				numpoints;
-	qboolean		badstartvert;	// tjunctions cannot be fixed without a midpoint vertex
-	int				vertexnums[MAXEDGES];
-} face_t;
-
-
-
-typedef struct bspbrush_s
-{
-	struct bspbrush_s	*next;
-	vec3_t	mins, maxs;
-	int		side, testside;		// side of node during construction
-	mapbrush_t	*original;
-	int		numsides;
-	side_t	sides[6];			// variably sized
-} bspbrush_t;
-
-
-
-#define	MAX_NODE_BRUSHES	8
-typedef struct node_s
-{
-	// both leafs and nodes
-	int				planenum;	// -1 = leaf node
-	struct node_s	*parent;
-	vec3_t			mins, maxs;	// valid after portalization
-	bspbrush_t		*volume;	// one for each leaf/node
-
-	// nodes only
-	qboolean		detail_seperator;	// a detail brush caused the split
-	side_t			*side;		// the side that created the node
-	struct node_s	*children[2];
-	face_t			*faces;
-
-	// leafs only
-	bspbrush_t		*brushlist;	// fragments of all brushes in this leaf
-	int				contents;	// OR of all brush contents
-	int				occupied;	// 1 or greater can reach entity
-	entity_t		*occupant;	// for leak file testing
-	int				cluster;	// for portalfile writing
-	int				area;		// for areaportals
-	struct portal_s	*portals;	// also on nodes during construction
-} node_t;
-
-typedef struct portal_s
-{
-	plane_t		plane;
-	node_t		*onnode;		// NULL = outside box
-	node_t		*nodes[2];		// [0] = front side of plane
-	struct portal_s	*next[2];
-	winding_t	*winding;
-
-	qboolean	sidefound;		// false if ->side hasn't been checked
-	side_t		*side;			// NULL = non-visible
-	face_t		*face[2];		// output face in bsp file
-} portal_t;
-
-typedef struct
-{
-	node_t		*headnode;
-	node_t		outside_node;
-	vec3_t		mins, maxs;
-} tree_t;
-
-extern	int			entity_num;
-
-extern	plane_t		mapplanes[MAX_MAP_PLANES];
-extern	int			nummapplanes;
-
-extern	int			nummapbrushes;
-extern	mapbrush_t	mapbrushes[MAX_MAP_BRUSHES];
-
-extern	vec3_t		map_mins, map_maxs;
-
-#define	MAX_MAP_SIDES		(MAX_MAP_BRUSHES*6)
-
-extern	int			nummapbrushsides;
-extern	side_t		brushsides[MAX_MAP_SIDES];
-
-extern	qboolean	noprune;
-extern	qboolean	nodetail;
-extern	qboolean	fulldetail;
-extern	qboolean	nomerge;
-extern	qboolean	nosubdiv;
-extern	qboolean	nowater;
-extern	qboolean	noweld;
-extern	qboolean	noshare;
-extern	qboolean	notjunc;
-
-extern	vec_t		microvolume;
-
-extern	char		outbase[32];
-
-extern	char	source[1024];
-
-void 	LoadMapFile (char *filename);
-int		FindFloatPlane (vec3_t normal, vec_t dist);
-
-//=============================================================================
-
-// textures.c
-
-typedef struct
-{
-	char	name[64];
-	int		flags;
-	int		value;
-	int		contents;
-	char	animname[64];
-} textureref_t;
-
-#define	MAX_MAP_TEXTURES	1024
-
-extern	textureref_t	textureref[MAX_MAP_TEXTURES];
-
-int	FindMiptex (char *name);
-
-int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin);
-
-//=============================================================================
-
-void FindGCD (int *v);
-
-mapbrush_t *Brush_LoadEntity (entity_t *ent);
-int	PlaneTypeForNormal (vec3_t normal);
-qboolean MakeBrushPlanes (mapbrush_t *b);
-int		FindIntPlane (int *inormal, int *iorigin);
-void	CreateBrush (int brushnum);
-
-
-//=============================================================================
-
-// draw.c
-
-extern vec3_t	draw_mins, draw_maxs;
-extern	qboolean	drawflag;
-
-void Draw_ClearWindow (void);
-void DrawWinding (winding_t *w);
-
-void GLS_BeginScene (void);
-void GLS_Winding (winding_t *w, int code);
-void GLS_EndScene (void);
-
-//=============================================================================
-
-// csg
-
-bspbrush_t *MakeBspBrushList (int startbrush, int endbrush,
-		vec3_t clipmins, vec3_t clipmaxs);
-bspbrush_t *ChopBrushes (bspbrush_t *head);
-bspbrush_t *InitialBrushList (bspbrush_t *list);
-bspbrush_t *OptimizedBrushList (bspbrush_t *list);
-
-void WriteBrushMap (char *name, bspbrush_t *list);
-
-//=============================================================================
-
-// brushbsp
-
-void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis);
-
-bspbrush_t *CopyBrush (bspbrush_t *brush);
-
-void SplitBrush (bspbrush_t *brush, int planenum,
-	bspbrush_t **front, bspbrush_t **back);
-
-tree_t *AllocTree (void);
-node_t *AllocNode (void);
-bspbrush_t *AllocBrush (int numsides);
-int	CountBrushList (bspbrush_t *brushes);
-void FreeBrush (bspbrush_t *brushes);
-vec_t BrushVolume (bspbrush_t *brush);
-
-void BoundBrush (bspbrush_t *brush);
-void FreeBrushList (bspbrush_t *brushes);
-
-tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs);
-
-//=============================================================================
-
-// portals.c
-
-int VisibleContents (int contents);
-
-void MakeHeadnodePortals (tree_t *tree);
-void MakeNodePortal (node_t *node);
-void SplitNodePortals (node_t *node);
-
-qboolean	Portal_VisFlood (portal_t *p);
-
-qboolean FloodEntities (tree_t *tree);
-void FillOutside (node_t *headnode);
-void FloodAreas (tree_t *tree);
-void MarkVisibleSides (tree_t *tree, int start, int end);
-void FreePortal (portal_t *p);
-void EmitAreaPortals (node_t *headnode);
-
-void MakeTreePortals (tree_t *tree);
-
-//=============================================================================
-
-// glfile.c
-
-void OutputWinding (winding_t *w, FILE *glview);
-void WriteGLView (tree_t *tree, char *source);
-
-//=============================================================================
-
-// leakfile.c
-
-//void LeakFile (tree_t *tree);
-xmlNodePtr LeakFile (tree_t *tree);
-
-//=============================================================================
-
-// prtfile.c
-
-void WritePortalFile (tree_t *tree);
-
-//=============================================================================
-
-// writebsp.c
-
-void SetModelNumbers (void);
-void SetLightStyles (void);
-
-void BeginBSPFile (void);
-void WriteBSP (node_t *headnode);
-void EndBSPFile (void);
-void BeginModel (void);
-void EndModel (void);
-
-//=============================================================================
-
-// faces.c
-
-void MakeFaces (node_t *headnode);
-void FixTjuncs (node_t *headnode);
-int GetEdge2 (int v1, int v2,  face_t *f);
-
-face_t	*AllocFace (void);
-void FreeFace (face_t *f);
-
-void MergeNodeFaces (node_t *node);
-
-//=============================================================================
-
-// tree.c
-
-void FreeTree (tree_t *tree);
-void FreeTree_r (node_t *node);
-void PrintTree_r (node_t *node, int depth);
-void FreeTreePortals_r (node_t *node);
-void PruneNodes_r (node_t *node);
-void PruneNodes (node_t *node);
-
-//=============================================================================
-
-// externs
-
-extern char	*mapname;
-extern char	game[64];
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* Files:
+
+brushbsp.c
+csg.c
+faces.c
+gldraw.c
+glfile.c
+leakfile.c
+map.c
+nodraw.c
+portals.c
+prtfile.c
+qbsp3.c
+textures.c
+tree.c
+writebsp.c
+
+*/
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "scriplib.h"
+#include "polylib.h"
+#include "q2_threads.h"
+#include "bspfile.h"
+#include "inout.h"
+
+#ifdef _WIN32
+	#ifdef NDEBUG							// Don't show in a Release build
+		#pragma warning(disable : 4305)     // truncate from double to float
+		#pragma warning(disable : 4244)     // conversion from double to float
+		#pragma warning(disable : 4018)     // signed/unsigned mismatch
+	#endif
+#endif
+
+#define	MAX_BRUSH_SIDES	128
+#define	CLIP_EPSILON	0.1
+
+#define	BOGUS_RANGE	8192
+
+#define	TEXINFO_NODE		-1		// side is allready on a node
+
+typedef struct plane_s
+{
+	vec3_t	normal;
+	vec_t	dist;
+	int		type;
+	struct plane_s	*hash_chain;
+} plane_t;
+
+typedef struct
+{
+	vec_t	shift[2];
+	vec_t	rotate;
+	vec_t	scale[2];
+	char	name[32];
+	int		flags;
+	int		value;
+} brush_texture_t;
+
+typedef struct side_s
+{
+	int			planenum;
+	int			texinfo;
+	winding_t	*winding;
+	struct side_s	*original;	// bspbrush_t sides will reference the mapbrush_t sides
+	int			contents;		// from miptex
+	int			surf;			// from miptex
+	qboolean	visible;		// choose visble planes first
+	qboolean	tested;			// this plane allready checked as a split
+	qboolean	bevel;			// don't ever use for bsp splitting
+} side_t;
+
+typedef struct brush_s
+{
+	int		entitynum;
+	int		brushnum;
+
+	int		contents;
+
+	vec3_t	mins, maxs;
+
+	int		numsides;
+	side_t	*original_sides;
+} mapbrush_t;
+
+#define	PLANENUM_LEAF			-1
+
+#define	MAXEDGES		20
+
+typedef struct face_s
+{
+	struct face_s	*next;		// on node
+
+	// the chain of faces off of a node can be merged or split,
+	// but each face_t along the way will remain in the chain
+	// until the entire tree is freed
+	struct face_s	*merged;	// if set, this face isn't valid anymore
+	struct face_s	*split[2];	// if set, this face isn't valid anymore
+
+	struct portal_s	*portal;
+	int				texinfo;
+	int				planenum;
+	int				contents;	// faces in different contents can't merge
+	int				outputnumber;
+	winding_t		*w;
+	int				numpoints;
+	qboolean		badstartvert;	// tjunctions cannot be fixed without a midpoint vertex
+	int				vertexnums[MAXEDGES];
+} face_t;
+
+
+
+typedef struct bspbrush_s
+{
+	struct bspbrush_s	*next;
+	vec3_t	mins, maxs;
+	int		side, testside;		// side of node during construction
+	mapbrush_t	*original;
+	int		numsides;
+	side_t	sides[6];			// variably sized
+} bspbrush_t;
+
+
+
+#define	MAX_NODE_BRUSHES	8
+typedef struct node_s
+{
+	// both leafs and nodes
+	int				planenum;	// -1 = leaf node
+	struct node_s	*parent;
+	vec3_t			mins, maxs;	// valid after portalization
+	bspbrush_t		*volume;	// one for each leaf/node
+
+	// nodes only
+	qboolean		detail_seperator;	// a detail brush caused the split
+	side_t			*side;		// the side that created the node
+	struct node_s	*children[2];
+	face_t			*faces;
+
+	// leafs only
+	bspbrush_t		*brushlist;	// fragments of all brushes in this leaf
+	int				contents;	// OR of all brush contents
+	int				occupied;	// 1 or greater can reach entity
+	entity_t		*occupant;	// for leak file testing
+	int				cluster;	// for portalfile writing
+	int				area;		// for areaportals
+	struct portal_s	*portals;	// also on nodes during construction
+} node_t;
+
+typedef struct portal_s
+{
+	plane_t		plane;
+	node_t		*onnode;		// NULL = outside box
+	node_t		*nodes[2];		// [0] = front side of plane
+	struct portal_s	*next[2];
+	winding_t	*winding;
+
+	qboolean	sidefound;		// false if ->side hasn't been checked
+	side_t		*side;			// NULL = non-visible
+	face_t		*face[2];		// output face in bsp file
+} portal_t;
+
+typedef struct
+{
+	node_t		*headnode;
+	node_t		outside_node;
+	vec3_t		mins, maxs;
+} tree_t;
+
+extern	int			entity_num;
+
+extern	plane_t		mapplanes[MAX_MAP_PLANES];
+extern	int			nummapplanes;
+
+extern	int			nummapbrushes;
+extern	mapbrush_t	mapbrushes[MAX_MAP_BRUSHES];
+
+extern	vec3_t		map_mins, map_maxs;
+
+#define	MAX_MAP_SIDES		(MAX_MAP_BRUSHES*6)
+
+extern	int			nummapbrushsides;
+extern	side_t		brushsides[MAX_MAP_SIDES];
+
+extern	qboolean	noprune;
+extern	qboolean	nodetail;
+extern	qboolean	fulldetail;
+extern	qboolean	nomerge;
+extern	qboolean	nosubdiv;
+extern	qboolean	nowater;
+extern	qboolean	noweld;
+extern	qboolean	noshare;
+extern	qboolean	notjunc;
+
+extern	vec_t		microvolume;
+
+extern	char		outbase[32];
+
+extern	char	source[1024];
+
+void 	LoadMapFile (char *filename);
+int		FindFloatPlane (vec3_t normal, vec_t dist);
+
+//=============================================================================
+
+// textures.c
+
+typedef struct
+{
+	char	name[64];
+	int		flags;
+	int		value;
+	int		contents;
+	char	animname[64];
+} textureref_t;
+
+#define	MAX_MAP_TEXTURES	1024
+
+extern	textureref_t	textureref[MAX_MAP_TEXTURES];
+
+int	FindMiptex (char *name);
+
+int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin);
+
+//=============================================================================
+
+void FindGCD (int *v);
+
+mapbrush_t *Brush_LoadEntity (entity_t *ent);
+int	PlaneTypeForNormal (vec3_t normal);
+qboolean MakeBrushPlanes (mapbrush_t *b);
+int		FindIntPlane (int *inormal, int *iorigin);
+void	CreateBrush (int brushnum);
+
+
+//=============================================================================
+
+// draw.c
+
+extern vec3_t	draw_mins, draw_maxs;
+extern	qboolean	drawflag;
+
+void Draw_ClearWindow (void);
+void DrawWinding (winding_t *w);
+
+void GLS_BeginScene (void);
+void GLS_Winding (winding_t *w, int code);
+void GLS_EndScene (void);
+
+//=============================================================================
+
+// csg
+
+bspbrush_t *MakeBspBrushList (int startbrush, int endbrush,
+		vec3_t clipmins, vec3_t clipmaxs);
+bspbrush_t *ChopBrushes (bspbrush_t *head);
+bspbrush_t *InitialBrushList (bspbrush_t *list);
+bspbrush_t *OptimizedBrushList (bspbrush_t *list);
+
+void WriteBrushMap (char *name, bspbrush_t *list);
+
+//=============================================================================
+
+// brushbsp
+
+void WriteBrushList (char *name, bspbrush_t *brush, qboolean onlyvis);
+
+bspbrush_t *CopyBrush (bspbrush_t *brush);
+
+void SplitBrush (bspbrush_t *brush, int planenum,
+	bspbrush_t **front, bspbrush_t **back);
+
+tree_t *AllocTree (void);
+node_t *AllocNode (void);
+bspbrush_t *AllocBrush (int numsides);
+int	CountBrushList (bspbrush_t *brushes);
+void FreeBrush (bspbrush_t *brushes);
+vec_t BrushVolume (bspbrush_t *brush);
+
+void BoundBrush (bspbrush_t *brush);
+void FreeBrushList (bspbrush_t *brushes);
+
+tree_t *BrushBSP (bspbrush_t *brushlist, vec3_t mins, vec3_t maxs);
+
+//=============================================================================
+
+// portals.c
+
+int VisibleContents (int contents);
+
+void MakeHeadnodePortals (tree_t *tree);
+void MakeNodePortal (node_t *node);
+void SplitNodePortals (node_t *node);
+
+qboolean	Portal_VisFlood (portal_t *p);
+
+qboolean FloodEntities (tree_t *tree);
+void FillOutside (node_t *headnode);
+void FloodAreas (tree_t *tree);
+void MarkVisibleSides (tree_t *tree, int start, int end);
+void FreePortal (portal_t *p);
+void EmitAreaPortals (node_t *headnode);
+
+void MakeTreePortals (tree_t *tree);
+
+//=============================================================================
+
+// glfile.c
+
+void OutputWinding (winding_t *w, FILE *glview);
+void WriteGLView (tree_t *tree, char *source);
+
+//=============================================================================
+
+// leakfile.c
+
+//void LeakFile (tree_t *tree);
+xmlNodePtr LeakFile (tree_t *tree);
+
+//=============================================================================
+
+// prtfile.c
+
+void WritePortalFile (tree_t *tree);
+
+//=============================================================================
+
+// writebsp.c
+
+void SetModelNumbers (void);
+void SetLightStyles (void);
+
+void BeginBSPFile (void);
+void WriteBSP (node_t *headnode);
+void EndBSPFile (void);
+void BeginModel (void);
+void EndModel (void);
+
+//=============================================================================
+
+// faces.c
+
+void MakeFaces (node_t *headnode);
+void FixTjuncs (node_t *headnode);
+int GetEdge2 (int v1, int v2,  face_t *f);
+
+face_t	*AllocFace (void);
+void FreeFace (face_t *f);
+
+void MergeNodeFaces (node_t *node);
+
+//=============================================================================
+
+// tree.c
+
+void FreeTree (tree_t *tree);
+void FreeTree_r (node_t *node);
+void PrintTree_r (node_t *node, int depth);
+void FreeTreePortals_r (node_t *node);
+void PruneNodes_r (node_t *node);
+void PruneNodes (node_t *node);
+
+//=============================================================================
+
+// externs
+
+extern char	*mapname;
+extern char	game[64];
diff --git a/tools/quake2/q2map/qrad.c b/tools/quake2/q2map/qrad.c
index e324c574..c204b56f 100644
--- a/tools/quake2/q2map/qrad.c
+++ b/tools/quake2/q2map/qrad.c
@@ -1,647 +1,647 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// qrad.c
-
-#include "qrad.h"
-
-
-
-/*
-
-NOTES
------
-
-every surface must be divided into at least two patches each axis
-
-*/
-
-patch_t		*face_patches[MAX_MAP_FACES];
-entity_t	*face_entity[MAX_MAP_FACES];
-patch_t		patches[MAX_PATCHES];
-unsigned	num_patches;
-
-vec3_t		radiosity[MAX_PATCHES];		// light leaving a patch
-vec3_t		illumination[MAX_PATCHES];	// light arriving at a patch
-
-vec3_t		face_offset[MAX_MAP_FACES];		// for rotating bmodels
-dplane_t	backplanes[MAX_MAP_PLANES];
-
-char		inbase[32], outbase[32];
-
-int			fakeplanes;					// created planes for origin offset 
-
-int		numbounce = 8;
-qboolean	extrasamples;
-
-float	subdiv = 64;
-qboolean	dumppatches;
-
-void BuildLightmaps (void);
-int TestLine (vec3_t start, vec3_t stop);
-
-int		junk;
-
-float	ambient = 0;
-float	maxlight = 196;
-
-float	lightscale = 1.0;
-
-qboolean	glview;
-
-qboolean	nopvs;
-
-char		source[1024];
-
-float	direct_scale =	0.4;
-float	entity_scale =	1.0;
-
-/*
-===================================================================
-
-MISC
-
-===================================================================
-*/
-
-
-/*
-=============
-MakeBackplanes
-=============
-*/
-void MakeBackplanes (void)
-{
-	int		i;
-
-	for (i=0 ; i<numplanes ; i++)
-	{
-		backplanes[i].dist = -dplanes[i].dist;
-		VectorSubtract (vec3_origin, dplanes[i].normal, backplanes[i].normal);
-	}
-}
-
-int		leafparents[MAX_MAP_LEAFS];
-int		nodeparents[MAX_MAP_NODES];
-
-/*
-=============
-MakeParents
-=============
-*/
-void MakeParents (int nodenum, int parent)
-{
-	int		i, j;
-	dnode_t	*node;
-
-	nodeparents[nodenum] = parent;
-	node = &dnodes[nodenum];
-
-	for (i=0 ; i<2 ; i++)
-	{
-		j = node->children[i];
-		if (j < 0)
-			leafparents[-j - 1] = nodenum;
-		else
-			MakeParents (j, nodenum);
-	}
-}
-
-
-/*
-===================================================================
-
-TRANSFER SCALES
-
-===================================================================
-*/
-
-int	PointInLeafnum (vec3_t point)
-{
-	int		nodenum;
-	vec_t	dist;
-	dnode_t	*node;
-	dplane_t	*plane;
-
-	nodenum = 0;
-	while (nodenum >= 0)
-	{
-		node = &dnodes[nodenum];
-		plane = &dplanes[node->planenum];
-		dist = DotProduct (point, plane->normal) - plane->dist;
-		if (dist > 0)
-			nodenum = node->children[0];
-		else
-			nodenum = node->children[1];
-	}
-
-	return -nodenum - 1;
-}
-
-
-dleaf_t		*Rad_PointInLeaf (vec3_t point)
-{
-	int		num;
-
-	num = PointInLeafnum (point);
-	return &dleafs[num];
-}
-
-
-qboolean PvsForOrigin (vec3_t org, byte *pvs)
-{
-	dleaf_t	*leaf;
-
-	if (!visdatasize)
-	{
-		memset (pvs, 255, (numleafs+7)/8 );
-		return true;
-	}
-
-	leaf = Rad_PointInLeaf (org);
-	if (leaf->cluster == -1)
-		return false;		// in solid leaf
-
-	DecompressVis (dvisdata + dvis->bitofs[leaf->cluster][DVIS_PVS], pvs);
-	return true;
-}
-
-
-/*
-=============
-MakeTransfers
-
-=============
-*/
-int	total_transfer;
-
-void MakeTransfers (int i)
-{
-	int			j;
-	vec3_t		delta;
-	vec_t		dist, scale;
-	float		trans;
-	int			itrans;
-	patch_t		*patch, *patch2;
-	float		total;
-	dplane_t	plane;
-	vec3_t		origin;
-	float		transfers[MAX_PATCHES], *all_transfers;
-	int			s;
-	int			itotal;
-	byte		pvs[(MAX_MAP_LEAFS+7)/8];
-	int			cluster;
-
-	patch = patches + i;
-	total = 0;
-
-	VectorCopy (patch->origin, origin);
-	plane = *patch->plane;
-
-	if (!PvsForOrigin (patch->origin, pvs))
-		return;
-
-	// find out which patch2s will collect light
-	// from patch
-
-	all_transfers = transfers;
-	patch->numtransfers = 0;
-	for (j=0, patch2 = patches ; j<num_patches ; j++, patch2++)
-	{
-		transfers[j] = 0;
-
-		if (j == i)
-			continue;
-
-		// check pvs bit
-		if (!nopvs)
-		{
-			cluster = patch2->cluster;
-			if (cluster == -1)
-				continue;
-			if ( ! ( pvs[cluster>>3] & (1<<(cluster&7)) ) )
-				continue;		// not in pvs
-		}
-
-		// calculate vector
-		VectorSubtract (patch2->origin, origin, delta);
-		dist = VectorNormalize (delta, delta);
-		if (!dist)
-			continue;	// should never happen
-
-		// reletive angles
-		scale = DotProduct (delta, plane.normal);
-		scale *= -DotProduct (delta, patch2->plane->normal);
-		if (scale <= 0)
-			continue;
-
-		// check exact tramsfer
-		if (TestLine_r (0, patch->origin, patch2->origin) )
-			continue;
-
-		trans = scale * patch2->area / (dist*dist);
-
-		if (trans < 0)
-			trans = 0;		// rounding errors...
-
-		transfers[j] = trans;
-		if (trans > 0)
-		{
-			total += trans;
-			patch->numtransfers++;
-		}
-	}
-
-	// copy the transfers out and normalize
-	// total should be somewhere near PI if everything went right
-	// because partial occlusion isn't accounted for, and nearby
-	// patches have underestimated form factors, it will usually
-	// be higher than PI
-	if (patch->numtransfers)
-	{
-		transfer_t	*t;
-		
-		if (patch->numtransfers < 0 || patch->numtransfers > MAX_PATCHES)
-			Error ("Weird numtransfers");
-		s = patch->numtransfers * sizeof(transfer_t);
-		patch->transfers = malloc (s);
-		if (!patch->transfers)
-			Error ("Memory allocation failure");
-
-		//
-		// normalize all transfers so all of the light
-		// is transfered to the surroundings
-		//
-		t = patch->transfers;
-		itotal = 0;
-		for (j=0 ; j<num_patches ; j++)
-		{
-			if (transfers[j] <= 0)
-				continue;
-			itrans = transfers[j]*0x10000 / total;
-			itotal += itrans;
-			t->transfer = itrans;
-			t->patch = j;
-			t++;
-		}
-	}
-
-	// don't bother locking around this.  not that important.
-	total_transfer += patch->numtransfers;
-}
-
-
-/*
-=============
-FreeTransfers
-=============
-*/
-void FreeTransfers (void)
-{
-	int		i;
-
-	for (i=0 ; i<num_patches ; i++)
-	{
-		free (patches[i].transfers);
-		patches[i].transfers = NULL;
-	}
-}
-
-
-//===================================================================
-
-/*
-=============
-WriteWorld
-=============
-*/
-void WriteWorld (char *name)
-{
-	int		i, j;
-	FILE		*out;
-	patch_t		*patch;
-	winding_t	*w;
-
-	out = fopen (name, "w");
-	if (!out)
-		Error ("Couldn't open %s", name);
-
-	for (j=0, patch=patches ; j<num_patches ; j++, patch++)
-	{
-		w = patch->winding;
-		fprintf (out, "%i\n", w->numpoints);
-		for (i=0 ; i<w->numpoints ; i++)
-		{
-			fprintf (out, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
-				w->p[i][0],
-				w->p[i][1],
-				w->p[i][2],
-				patch->totallight[0],
-				patch->totallight[1],
-				patch->totallight[2]);
-		}
-		fprintf (out, "\n");
-	}
-
-	fclose (out);
-}
-
-/*
-=============
-WriteGlView
-=============
-*/
-void WriteGlView (void)
-{
-	char	name[1024];
-	FILE	*f;
-	int		i, j;
-	patch_t	*p;
-	winding_t	*w;
-
-	strcpy (name, source);
-	StripExtension (name);
-	strcat (name, ".glr");
-
-	f = fopen (name, "w");
-	if (!f)
-		Error ("Couldn't open %s", f);
-
-	for (j=0 ; j<num_patches ; j++)
-	{
-		p = &patches[j];
-		w = p->winding;
-		fprintf (f, "%i\n", w->numpoints);
-		for (i=0 ; i<w->numpoints ; i++)
-		{
-			fprintf (f, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
-				w->p[i][0],
-				w->p[i][1],
-				w->p[i][2],
-				p->totallight[0]/128,
-				p->totallight[1]/128,
-				p->totallight[2]/128);
-		}
-		fprintf (f, "\n");
-	}
-
-	fclose (f);
-}
-
-
-//==============================================================
-
-/*
-=============
-CollectLight
-=============
-*/
-float CollectLight (void)
-{
-	int		i, j;
-	patch_t	*patch;
-	vec_t	total;
-
-	total = 0;
-
-	for (i=0, patch=patches ; i<num_patches ; i++, patch++)
-	{
-		// skys never collect light, it is just dropped
-		if (patch->sky)
-		{
-			VectorClear (radiosity[i]);
-			VectorClear (illumination[i]);
-			continue;
-		}
-
-		for (j=0 ; j<3 ; j++)
-		{
-			patch->totallight[j] += illumination[i][j] / patch->area;
-			radiosity[i][j] = illumination[i][j] * patch->reflectivity[j];
-		}
-
-		total += radiosity[i][0] + radiosity[i][1] + radiosity[i][2];
-		VectorClear (illumination[i]);
-	}
-
-	return total;
-}
-
-
-/*
-=============
-ShootLight
-
-Send light out to other patches
-  Run multi-threaded
-=============
-*/
-void ShootLight (int patchnum)
-{
-	int			k, l;
-	transfer_t	*trans;
-	int			num;
-	patch_t		*patch;
-	vec3_t		send;
-
-	// this is the amount of light we are distributing
-	// prescale it so that multiplying by the 16 bit
-	// transfer values gives a proper output value
-	for (k=0 ; k<3 ; k++)
-		send[k] = radiosity[patchnum][k] / 0x10000;
-	patch = &patches[patchnum];
-
-	trans = patch->transfers;
-	num = patch->numtransfers;
-
-	for (k=0 ; k<num ; k++, trans++)
-	{
-		for (l=0 ; l<3 ; l++)
-			illumination[trans->patch][l] += send[l]*trans->transfer;
-	}
-}
-
-/*
-=============
-BounceLight
-=============
-*/
-void BounceLight (void)
-{
-	int		i, j;
-	float	added;
-	char	name[64];
-	patch_t	*p;
-
-	for (i=0 ; i<num_patches ; i++)
-	{
-		p = &patches[i];
-		for (j=0 ; j<3 ; j++)
-		{
-//			p->totallight[j] = p->samplelight[j];
-			radiosity[i][j] = p->samplelight[j] * p->reflectivity[j] * p->area;
-		}
-	}
-
-	for (i=0 ; i<numbounce ; i++)
-	{
-		RunThreadsOnIndividual (num_patches, false, ShootLight);
-		added = CollectLight ();
-
-		Sys_FPrintf( SYS_VRB, "bounce:%i added:%f\n", i, added);
-		if ( dumppatches && (i==0 || i == numbounce-1) )
-		{
-			sprintf (name, "bounce%i.txt", i);
-			WriteWorld (name);
-		}
-	}
-}
-
-
-
-//==============================================================
-
-void CheckPatches (void)
-{
-	int		i;
-	patch_t	*patch;
-
-	for (i=0 ; i<num_patches ; i++)
-	{
-		patch = &patches[i];
-		if (patch->totallight[0] < 0 || patch->totallight[1] < 0 || patch->totallight[2] < 0)
-			Error ("negative patch totallight\n");
-	}
-}
-
-/*
-=============
-RadWorld
-=============
-*/
-void RadWorld (void)
-{
-	if (numnodes == 0 || numfaces == 0)
-		Error ("Empty map");
-	MakeBackplanes ();
-	MakeParents (0, -1);
-	MakeTnodes (&dmodels[0]);
-
-	// turn each face into a single patch
-	MakePatches ();
-
-	// subdivide patches to a maximum dimension
-	SubdividePatches ();
-
-	// create directlights out of patches and lights
-	CreateDirectLights ();
-
-	// build initial facelights
-	RunThreadsOnIndividual (numfaces, true, BuildFacelights);
-
-	if (numbounce > 0)
-	{
-		// build transfer lists
-		RunThreadsOnIndividual (num_patches, true, MakeTransfers);
-		Sys_FPrintf( SYS_VRB, "transfer lists: %5.1f megs\n"
-		, (float)total_transfer * sizeof(transfer_t) / (1024*1024));
-
-		// spread light around
-		BounceLight ();
-		
-		FreeTransfers ();
-
-		CheckPatches ();
-	}
-
-	if (glview)
-		WriteGlView ();
-
-	// blend bounced light into direct light and save
-	PairEdges ();
-	LinkPlaneFaces ();
-
-	lightdatasize = 0;
-	RunThreadsOnIndividual (numfaces, true, FinalLightFace);
-}
-
-
-/*
-========
-main
-
-light modelfile
-========
-*/
-int RAD_Main ()
-{
-	double		start, end;
-	char		name[1024];
-	int		total_rad_time;
-
-	Sys_Printf ("\n----- RAD ----\n\n");
-
-	if (maxlight > 255)
-		maxlight = 255;
-
-	start = I_FloatTime ();
-
-	if ( !strcmp( game, "heretic2" ) )
-		CalcTextureReflectivity = &CalcTextureReflectivity_Heretic2;
-	else
-		CalcTextureReflectivity = &CalcTextureReflectivity_Quake2;
-		
-	SetQdirFromPath (mapname);	
-	strcpy (source, ExpandArg(mapname));
-	StripExtension (source);
-	DefaultExtension (source, ".bsp");
-
-//	ReadLightFile ();
-
-	sprintf (name, "%s%s", inbase, source);
-	Sys_Printf ("reading %s\n", name);
-	LoadBSPFile (name);
-	ParseEntities ();
-	(*CalcTextureReflectivity) ();
-
-	if (!visdatasize)
-	{
-		Sys_Printf ("No vis information, direct lighting only.\n");
-		numbounce = 0;
-		ambient = 0.1;
-	}
-
-	RadWorld ();
-
-	sprintf (name, "%s%s", outbase, source);
-	Sys_Printf ("writing %s\n", name);
-	WriteBSPFile (name);
-
-	end = I_FloatTime ();
-	total_rad_time = (int) (end-start);
-	Sys_Printf("\nRAD Time: ");
-	if ( total_rad_time > 59 )
-		Sys_Printf("%d Minutes ", total_rad_time/60 );
-	Sys_Printf( "%d Seconds\n", total_rad_time%60 );
-	
-	
-	return 0;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// qrad.c
+
+#include "qrad.h"
+
+
+
+/*
+
+NOTES
+-----
+
+every surface must be divided into at least two patches each axis
+
+*/
+
+patch_t		*face_patches[MAX_MAP_FACES];
+entity_t	*face_entity[MAX_MAP_FACES];
+patch_t		patches[MAX_PATCHES];
+unsigned	num_patches;
+
+vec3_t		radiosity[MAX_PATCHES];		// light leaving a patch
+vec3_t		illumination[MAX_PATCHES];	// light arriving at a patch
+
+vec3_t		face_offset[MAX_MAP_FACES];		// for rotating bmodels
+dplane_t	backplanes[MAX_MAP_PLANES];
+
+char		inbase[32], outbase[32];
+
+int			fakeplanes;					// created planes for origin offset 
+
+int		numbounce = 8;
+qboolean	extrasamples;
+
+float	subdiv = 64;
+qboolean	dumppatches;
+
+void BuildLightmaps (void);
+int TestLine (vec3_t start, vec3_t stop);
+
+int		junk;
+
+float	ambient = 0;
+float	maxlight = 196;
+
+float	lightscale = 1.0;
+
+qboolean	glview;
+
+qboolean	nopvs;
+
+char		source[1024];
+
+float	direct_scale =	0.4;
+float	entity_scale =	1.0;
+
+/*
+===================================================================
+
+MISC
+
+===================================================================
+*/
+
+
+/*
+=============
+MakeBackplanes
+=============
+*/
+void MakeBackplanes (void)
+{
+	int		i;
+
+	for (i=0 ; i<numplanes ; i++)
+	{
+		backplanes[i].dist = -dplanes[i].dist;
+		VectorSubtract (vec3_origin, dplanes[i].normal, backplanes[i].normal);
+	}
+}
+
+int		leafparents[MAX_MAP_LEAFS];
+int		nodeparents[MAX_MAP_NODES];
+
+/*
+=============
+MakeParents
+=============
+*/
+void MakeParents (int nodenum, int parent)
+{
+	int		i, j;
+	dnode_t	*node;
+
+	nodeparents[nodenum] = parent;
+	node = &dnodes[nodenum];
+
+	for (i=0 ; i<2 ; i++)
+	{
+		j = node->children[i];
+		if (j < 0)
+			leafparents[-j - 1] = nodenum;
+		else
+			MakeParents (j, nodenum);
+	}
+}
+
+
+/*
+===================================================================
+
+TRANSFER SCALES
+
+===================================================================
+*/
+
+int	PointInLeafnum (vec3_t point)
+{
+	int		nodenum;
+	vec_t	dist;
+	dnode_t	*node;
+	dplane_t	*plane;
+
+	nodenum = 0;
+	while (nodenum >= 0)
+	{
+		node = &dnodes[nodenum];
+		plane = &dplanes[node->planenum];
+		dist = DotProduct (point, plane->normal) - plane->dist;
+		if (dist > 0)
+			nodenum = node->children[0];
+		else
+			nodenum = node->children[1];
+	}
+
+	return -nodenum - 1;
+}
+
+
+dleaf_t		*Rad_PointInLeaf (vec3_t point)
+{
+	int		num;
+
+	num = PointInLeafnum (point);
+	return &dleafs[num];
+}
+
+
+qboolean PvsForOrigin (vec3_t org, byte *pvs)
+{
+	dleaf_t	*leaf;
+
+	if (!visdatasize)
+	{
+		memset (pvs, 255, (numleafs+7)/8 );
+		return true;
+	}
+
+	leaf = Rad_PointInLeaf (org);
+	if (leaf->cluster == -1)
+		return false;		// in solid leaf
+
+	DecompressVis (dvisdata + dvis->bitofs[leaf->cluster][DVIS_PVS], pvs);
+	return true;
+}
+
+
+/*
+=============
+MakeTransfers
+
+=============
+*/
+int	total_transfer;
+
+void MakeTransfers (int i)
+{
+	int			j;
+	vec3_t		delta;
+	vec_t		dist, scale;
+	float		trans;
+	int			itrans;
+	patch_t		*patch, *patch2;
+	float		total;
+	dplane_t	plane;
+	vec3_t		origin;
+	float		transfers[MAX_PATCHES], *all_transfers;
+	int			s;
+	int			itotal;
+	byte		pvs[(MAX_MAP_LEAFS+7)/8];
+	int			cluster;
+
+	patch = patches + i;
+	total = 0;
+
+	VectorCopy (patch->origin, origin);
+	plane = *patch->plane;
+
+	if (!PvsForOrigin (patch->origin, pvs))
+		return;
+
+	// find out which patch2s will collect light
+	// from patch
+
+	all_transfers = transfers;
+	patch->numtransfers = 0;
+	for (j=0, patch2 = patches ; j<num_patches ; j++, patch2++)
+	{
+		transfers[j] = 0;
+
+		if (j == i)
+			continue;
+
+		// check pvs bit
+		if (!nopvs)
+		{
+			cluster = patch2->cluster;
+			if (cluster == -1)
+				continue;
+			if ( ! ( pvs[cluster>>3] & (1<<(cluster&7)) ) )
+				continue;		// not in pvs
+		}
+
+		// calculate vector
+		VectorSubtract (patch2->origin, origin, delta);
+		dist = VectorNormalize (delta, delta);
+		if (!dist)
+			continue;	// should never happen
+
+		// reletive angles
+		scale = DotProduct (delta, plane.normal);
+		scale *= -DotProduct (delta, patch2->plane->normal);
+		if (scale <= 0)
+			continue;
+
+		// check exact tramsfer
+		if (TestLine_r (0, patch->origin, patch2->origin) )
+			continue;
+
+		trans = scale * patch2->area / (dist*dist);
+
+		if (trans < 0)
+			trans = 0;		// rounding errors...
+
+		transfers[j] = trans;
+		if (trans > 0)
+		{
+			total += trans;
+			patch->numtransfers++;
+		}
+	}
+
+	// copy the transfers out and normalize
+	// total should be somewhere near PI if everything went right
+	// because partial occlusion isn't accounted for, and nearby
+	// patches have underestimated form factors, it will usually
+	// be higher than PI
+	if (patch->numtransfers)
+	{
+		transfer_t	*t;
+		
+		if (patch->numtransfers < 0 || patch->numtransfers > MAX_PATCHES)
+			Error ("Weird numtransfers");
+		s = patch->numtransfers * sizeof(transfer_t);
+		patch->transfers = malloc (s);
+		if (!patch->transfers)
+			Error ("Memory allocation failure");
+
+		//
+		// normalize all transfers so all of the light
+		// is transfered to the surroundings
+		//
+		t = patch->transfers;
+		itotal = 0;
+		for (j=0 ; j<num_patches ; j++)
+		{
+			if (transfers[j] <= 0)
+				continue;
+			itrans = transfers[j]*0x10000 / total;
+			itotal += itrans;
+			t->transfer = itrans;
+			t->patch = j;
+			t++;
+		}
+	}
+
+	// don't bother locking around this.  not that important.
+	total_transfer += patch->numtransfers;
+}
+
+
+/*
+=============
+FreeTransfers
+=============
+*/
+void FreeTransfers (void)
+{
+	int		i;
+
+	for (i=0 ; i<num_patches ; i++)
+	{
+		free (patches[i].transfers);
+		patches[i].transfers = NULL;
+	}
+}
+
+
+//===================================================================
+
+/*
+=============
+WriteWorld
+=============
+*/
+void WriteWorld (char *name)
+{
+	int		i, j;
+	FILE		*out;
+	patch_t		*patch;
+	winding_t	*w;
+
+	out = fopen (name, "w");
+	if (!out)
+		Error ("Couldn't open %s", name);
+
+	for (j=0, patch=patches ; j<num_patches ; j++, patch++)
+	{
+		w = patch->winding;
+		fprintf (out, "%i\n", w->numpoints);
+		for (i=0 ; i<w->numpoints ; i++)
+		{
+			fprintf (out, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
+				w->p[i][0],
+				w->p[i][1],
+				w->p[i][2],
+				patch->totallight[0],
+				patch->totallight[1],
+				patch->totallight[2]);
+		}
+		fprintf (out, "\n");
+	}
+
+	fclose (out);
+}
+
+/*
+=============
+WriteGlView
+=============
+*/
+void WriteGlView (void)
+{
+	char	name[1024];
+	FILE	*f;
+	int		i, j;
+	patch_t	*p;
+	winding_t	*w;
+
+	strcpy (name, source);
+	StripExtension (name);
+	strcat (name, ".glr");
+
+	f = fopen (name, "w");
+	if (!f)
+		Error ("Couldn't open %s", f);
+
+	for (j=0 ; j<num_patches ; j++)
+	{
+		p = &patches[j];
+		w = p->winding;
+		fprintf (f, "%i\n", w->numpoints);
+		for (i=0 ; i<w->numpoints ; i++)
+		{
+			fprintf (f, "%5.2f %5.2f %5.2f %5.3f %5.3f %5.3f\n",
+				w->p[i][0],
+				w->p[i][1],
+				w->p[i][2],
+				p->totallight[0]/128,
+				p->totallight[1]/128,
+				p->totallight[2]/128);
+		}
+		fprintf (f, "\n");
+	}
+
+	fclose (f);
+}
+
+
+//==============================================================
+
+/*
+=============
+CollectLight
+=============
+*/
+float CollectLight (void)
+{
+	int		i, j;
+	patch_t	*patch;
+	vec_t	total;
+
+	total = 0;
+
+	for (i=0, patch=patches ; i<num_patches ; i++, patch++)
+	{
+		// skys never collect light, it is just dropped
+		if (patch->sky)
+		{
+			VectorClear (radiosity[i]);
+			VectorClear (illumination[i]);
+			continue;
+		}
+
+		for (j=0 ; j<3 ; j++)
+		{
+			patch->totallight[j] += illumination[i][j] / patch->area;
+			radiosity[i][j] = illumination[i][j] * patch->reflectivity[j];
+		}
+
+		total += radiosity[i][0] + radiosity[i][1] + radiosity[i][2];
+		VectorClear (illumination[i]);
+	}
+
+	return total;
+}
+
+
+/*
+=============
+ShootLight
+
+Send light out to other patches
+  Run multi-threaded
+=============
+*/
+void ShootLight (int patchnum)
+{
+	int			k, l;
+	transfer_t	*trans;
+	int			num;
+	patch_t		*patch;
+	vec3_t		send;
+
+	// this is the amount of light we are distributing
+	// prescale it so that multiplying by the 16 bit
+	// transfer values gives a proper output value
+	for (k=0 ; k<3 ; k++)
+		send[k] = radiosity[patchnum][k] / 0x10000;
+	patch = &patches[patchnum];
+
+	trans = patch->transfers;
+	num = patch->numtransfers;
+
+	for (k=0 ; k<num ; k++, trans++)
+	{
+		for (l=0 ; l<3 ; l++)
+			illumination[trans->patch][l] += send[l]*trans->transfer;
+	}
+}
+
+/*
+=============
+BounceLight
+=============
+*/
+void BounceLight (void)
+{
+	int		i, j;
+	float	added;
+	char	name[64];
+	patch_t	*p;
+
+	for (i=0 ; i<num_patches ; i++)
+	{
+		p = &patches[i];
+		for (j=0 ; j<3 ; j++)
+		{
+//			p->totallight[j] = p->samplelight[j];
+			radiosity[i][j] = p->samplelight[j] * p->reflectivity[j] * p->area;
+		}
+	}
+
+	for (i=0 ; i<numbounce ; i++)
+	{
+		RunThreadsOnIndividual (num_patches, false, ShootLight);
+		added = CollectLight ();
+
+		Sys_FPrintf( SYS_VRB, "bounce:%i added:%f\n", i, added);
+		if ( dumppatches && (i==0 || i == numbounce-1) )
+		{
+			sprintf (name, "bounce%i.txt", i);
+			WriteWorld (name);
+		}
+	}
+}
+
+
+
+//==============================================================
+
+void CheckPatches (void)
+{
+	int		i;
+	patch_t	*patch;
+
+	for (i=0 ; i<num_patches ; i++)
+	{
+		patch = &patches[i];
+		if (patch->totallight[0] < 0 || patch->totallight[1] < 0 || patch->totallight[2] < 0)
+			Error ("negative patch totallight\n");
+	}
+}
+
+/*
+=============
+RadWorld
+=============
+*/
+void RadWorld (void)
+{
+	if (numnodes == 0 || numfaces == 0)
+		Error ("Empty map");
+	MakeBackplanes ();
+	MakeParents (0, -1);
+	MakeTnodes (&dmodels[0]);
+
+	// turn each face into a single patch
+	MakePatches ();
+
+	// subdivide patches to a maximum dimension
+	SubdividePatches ();
+
+	// create directlights out of patches and lights
+	CreateDirectLights ();
+
+	// build initial facelights
+	RunThreadsOnIndividual (numfaces, true, BuildFacelights);
+
+	if (numbounce > 0)
+	{
+		// build transfer lists
+		RunThreadsOnIndividual (num_patches, true, MakeTransfers);
+		Sys_FPrintf( SYS_VRB, "transfer lists: %5.1f megs\n"
+		, (float)total_transfer * sizeof(transfer_t) / (1024*1024));
+
+		// spread light around
+		BounceLight ();
+		
+		FreeTransfers ();
+
+		CheckPatches ();
+	}
+
+	if (glview)
+		WriteGlView ();
+
+	// blend bounced light into direct light and save
+	PairEdges ();
+	LinkPlaneFaces ();
+
+	lightdatasize = 0;
+	RunThreadsOnIndividual (numfaces, true, FinalLightFace);
+}
+
+
+/*
+========
+main
+
+light modelfile
+========
+*/
+int RAD_Main ()
+{
+	double		start, end;
+	char		name[1024];
+	int		total_rad_time;
+
+	Sys_Printf ("\n----- RAD ----\n\n");
+
+	if (maxlight > 255)
+		maxlight = 255;
+
+	start = I_FloatTime ();
+
+	if ( !strcmp( game, "heretic2" ) )
+		CalcTextureReflectivity = &CalcTextureReflectivity_Heretic2;
+	else
+		CalcTextureReflectivity = &CalcTextureReflectivity_Quake2;
+		
+	SetQdirFromPath (mapname);	
+	strcpy (source, ExpandArg(mapname));
+	StripExtension (source);
+	DefaultExtension (source, ".bsp");
+
+//	ReadLightFile ();
+
+	sprintf (name, "%s%s", inbase, source);
+	Sys_Printf ("reading %s\n", name);
+	LoadBSPFile (name);
+	ParseEntities ();
+	(*CalcTextureReflectivity) ();
+
+	if (!visdatasize)
+	{
+		Sys_Printf ("No vis information, direct lighting only.\n");
+		numbounce = 0;
+		ambient = 0.1;
+	}
+
+	RadWorld ();
+
+	sprintf (name, "%s%s", outbase, source);
+	Sys_Printf ("writing %s\n", name);
+	WriteBSPFile (name);
+
+	end = I_FloatTime ();
+	total_rad_time = (int) (end-start);
+	Sys_Printf("\nRAD Time: ");
+	if ( total_rad_time > 59 )
+		Sys_Printf("%d Minutes ", total_rad_time/60 );
+	Sys_Printf( "%d Seconds\n", total_rad_time%60 );
+	
+	
+	return 0;
+}
+
diff --git a/tools/quake2/q2map/qrad.h b/tools/quake2/q2map/qrad.h
index 3bfc3854..2eef8bc4 100644
--- a/tools/quake2/q2map/qrad.h
+++ b/tools/quake2/q2map/qrad.h
@@ -1,184 +1,184 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-/* Files:
-
-lightmap.c
-patches.c
-qrad.c
-trace.c
-
-*/
-
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "bspfile.h"
-#include "polylib.h"
-#include "q2_threads.h"
-#include "lbmlib.h"
-#include "inout.h"
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#ifdef _WIN32
-	#ifdef NDEBUG							// Don't show in a Release build
-		#pragma warning(disable : 4305)     // truncate from double to float
-		#pragma warning(disable : 4244)     // conversion from double to float
-		#pragma warning(disable : 4018)     // signed/unsigned mismatch
-	#endif
-#endif
-
-typedef enum
-{
-	emit_surface,
-	emit_point,
-	emit_spotlight
-} emittype_t;
-
-
-
-typedef struct directlight_s
-{
-	struct directlight_s *next;
-	emittype_t	type;
-
-	float		intensity;
-	int			style;
-	vec3_t		origin;
-	vec3_t		color;
-	vec3_t		normal;		// for surfaces and spotlights
-	float		stopdot;		// for spotlights
-} directlight_t;
-
-
-// the sum of all tranfer->transfer values for a given patch
-// should equal exactly 0x10000, showing that all radiance
-// reaches other patches
-typedef struct
-{
-	unsigned short	patch;
-	unsigned short	transfer;
-} transfer_t;
-
-
-#define	MAX_PATCHES	65000			// larger will cause 32 bit overflows
-
-typedef struct patch_s
-{
-	winding_t	*winding;
-	struct patch_s		*next;		// next in face
-	int			numtransfers;
-	transfer_t	*transfers;
-
-	int			cluster;			// for pvs checking
-	vec3_t		origin;
-	dplane_t	*plane;
-
-	qboolean	sky;
-
-	vec3_t		totallight;			// accumulated by radiosity
-									// does NOT include light
-									// accounted for by direct lighting
-	float		area;
-
-	// illuminance * reflectivity = radiosity
-	vec3_t		reflectivity;
-	vec3_t		baselight;			// emissivity only
-
-	// each style 0 lightmap sample in the patch will be
-	// added up to get the average illuminance of the entire patch
-	vec3_t		samplelight;
-	int			samples;		// for averaging direct light
-} patch_t;
-
-extern	patch_t		*face_patches[MAX_MAP_FACES];
-extern	entity_t	*face_entity[MAX_MAP_FACES];
-extern	vec3_t		face_offset[MAX_MAP_FACES];		// for rotating bmodels
-extern	patch_t		patches[MAX_PATCHES];
-extern	unsigned	num_patches;
-
-extern	int		leafparents[MAX_MAP_LEAFS];
-extern	int		nodeparents[MAX_MAP_NODES];
-
-extern	float	lightscale;
-
-
-void MakeShadowSplits (void);
-
-//==============================================
-
-
-void BuildVisMatrix (void);
-qboolean CheckVisBit (unsigned p1, unsigned p2);
-
-//==============================================
-
-extern	float ambient, maxlight;
-
-void LinkPlaneFaces (void);
-
-extern	qboolean	extrasamples;
-extern int numbounce;
-
-extern	directlight_t	*directlights[MAX_MAP_LEAFS];
-
-extern	byte	nodehit[MAX_MAP_NODES];
-
-void BuildLightmaps (void);
-
-void BuildFacelights (int facenum);
-
-void FinalLightFace (int facenum);
-
-qboolean PvsForOrigin (vec3_t org, byte *pvs);
-
-int TestLine_r (int node, vec3_t start, vec3_t stop);
-
-void CreateDirectLights (void);
-
-dleaf_t		*Rad_PointInLeaf (vec3_t point);
-
-
-extern	dplane_t	backplanes[MAX_MAP_PLANES];
-extern	int			fakeplanes;					// created planes for origin offset 
-
-extern	float	subdiv;
-
-extern	float	direct_scale;
-extern	float	entity_scale;
-
-int	PointInLeafnum (vec3_t point);
-void MakeTnodes (dmodel_t *bm);
-void MakePatches (void);
-void SubdividePatches (void);
-void PairEdges (void);
-void (*CalcTextureReflectivity) (void);
-void CalcTextureReflectivity_Quake2(void);
-void CalcTextureReflectivity_Heretic2(void);
-
-//=============================================================================
-
-// externs
-
-extern char	*mapname;
-extern char	game[64];
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+/* Files:
+
+lightmap.c
+patches.c
+qrad.c
+trace.c
+
+*/
+
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "bspfile.h"
+#include "polylib.h"
+#include "q2_threads.h"
+#include "lbmlib.h"
+#include "inout.h"
+
+#ifdef _WIN32
+#include <windows.h>
+#endif
+
+#ifdef _WIN32
+	#ifdef NDEBUG							// Don't show in a Release build
+		#pragma warning(disable : 4305)     // truncate from double to float
+		#pragma warning(disable : 4244)     // conversion from double to float
+		#pragma warning(disable : 4018)     // signed/unsigned mismatch
+	#endif
+#endif
+
+typedef enum
+{
+	emit_surface,
+	emit_point,
+	emit_spotlight
+} emittype_t;
+
+
+
+typedef struct directlight_s
+{
+	struct directlight_s *next;
+	emittype_t	type;
+
+	float		intensity;
+	int			style;
+	vec3_t		origin;
+	vec3_t		color;
+	vec3_t		normal;		// for surfaces and spotlights
+	float		stopdot;		// for spotlights
+} directlight_t;
+
+
+// the sum of all tranfer->transfer values for a given patch
+// should equal exactly 0x10000, showing that all radiance
+// reaches other patches
+typedef struct
+{
+	unsigned short	patch;
+	unsigned short	transfer;
+} transfer_t;
+
+
+#define	MAX_PATCHES	65000			// larger will cause 32 bit overflows
+
+typedef struct patch_s
+{
+	winding_t	*winding;
+	struct patch_s		*next;		// next in face
+	int			numtransfers;
+	transfer_t	*transfers;
+
+	int			cluster;			// for pvs checking
+	vec3_t		origin;
+	dplane_t	*plane;
+
+	qboolean	sky;
+
+	vec3_t		totallight;			// accumulated by radiosity
+									// does NOT include light
+									// accounted for by direct lighting
+	float		area;
+
+	// illuminance * reflectivity = radiosity
+	vec3_t		reflectivity;
+	vec3_t		baselight;			// emissivity only
+
+	// each style 0 lightmap sample in the patch will be
+	// added up to get the average illuminance of the entire patch
+	vec3_t		samplelight;
+	int			samples;		// for averaging direct light
+} patch_t;
+
+extern	patch_t		*face_patches[MAX_MAP_FACES];
+extern	entity_t	*face_entity[MAX_MAP_FACES];
+extern	vec3_t		face_offset[MAX_MAP_FACES];		// for rotating bmodels
+extern	patch_t		patches[MAX_PATCHES];
+extern	unsigned	num_patches;
+
+extern	int		leafparents[MAX_MAP_LEAFS];
+extern	int		nodeparents[MAX_MAP_NODES];
+
+extern	float	lightscale;
+
+
+void MakeShadowSplits (void);
+
+//==============================================
+
+
+void BuildVisMatrix (void);
+qboolean CheckVisBit (unsigned p1, unsigned p2);
+
+//==============================================
+
+extern	float ambient, maxlight;
+
+void LinkPlaneFaces (void);
+
+extern	qboolean	extrasamples;
+extern int numbounce;
+
+extern	directlight_t	*directlights[MAX_MAP_LEAFS];
+
+extern	byte	nodehit[MAX_MAP_NODES];
+
+void BuildLightmaps (void);
+
+void BuildFacelights (int facenum);
+
+void FinalLightFace (int facenum);
+
+qboolean PvsForOrigin (vec3_t org, byte *pvs);
+
+int TestLine_r (int node, vec3_t start, vec3_t stop);
+
+void CreateDirectLights (void);
+
+dleaf_t		*Rad_PointInLeaf (vec3_t point);
+
+
+extern	dplane_t	backplanes[MAX_MAP_PLANES];
+extern	int			fakeplanes;					// created planes for origin offset 
+
+extern	float	subdiv;
+
+extern	float	direct_scale;
+extern	float	entity_scale;
+
+int	PointInLeafnum (vec3_t point);
+void MakeTnodes (dmodel_t *bm);
+void MakePatches (void);
+void SubdividePatches (void);
+void PairEdges (void);
+void (*CalcTextureReflectivity) (void);
+void CalcTextureReflectivity_Quake2(void);
+void CalcTextureReflectivity_Heretic2(void);
+
+//=============================================================================
+
+// externs
+
+extern char	*mapname;
+extern char	game[64];
diff --git a/tools/quake2/q2map/qvis.c b/tools/quake2/q2map/qvis.c
index 30979914..bf7d3244 100644
--- a/tools/quake2/q2map/qvis.c
+++ b/tools/quake2/q2map/qvis.c
@@ -1,581 +1,581 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// qvis.c
-
-#include "qvis.h"
-#include "q2_threads.h"
-#include "stdlib.h"
-
-int			numportals;
-int			portalclusters;
-
-char		inbase[32];
-char		outbase[32];
-
-portal_t	*portals;
-leaf_t		*leafs;
-
-int			c_portaltest, c_portalpass, c_portalcheck;
-
-byte		*uncompressedvis;
-
-byte	*vismap, *vismap_p, *vismap_end;	// past visfile
-int		originalvismapsize;
-
-int		leafbytes;				// (portalclusters+63)>>3
-int		leaflongs;
-
-int		portalbytes, portallongs;
-
-qboolean		fastvis;
-qboolean		nosort;
-
-int			testlevel = 2;
-
-int		totalvis;
-
-portal_t	*sorted_portals[MAX_MAP_PORTALS*2];
-
-
-//=============================================================================
-
-void PlaneFromWinding (winding_t *w, plane_t *plane)
-{
-	vec3_t		v1, v2;
-
-// calc plane
-	VectorSubtract (w->points[2], w->points[1], v1);
-	VectorSubtract (w->points[0], w->points[1], v2);
-	CrossProduct (v2, v1, plane->normal);
-	VectorNormalize (plane->normal, plane->normal);
-	plane->dist = DotProduct (w->points[0], plane->normal);
-}
-
-
-/*
-==================
-NewWinding
-==================
-*/
-winding_t *NewWinding (int points)
-{
-	winding_t	*w;
-	int			size;
-	
-	if (points > MAX_POINTS_ON_WINDING)
-		Error ("NewWinding: %i points", points);
-	
-	size = (int)((winding_t *)0)->points[points];
-	w = malloc (size);
-	memset (w, 0, size);
-	
-	return w;
-}
-
-
-/*
-void pw(winding_t *w)
-{
-	int		i;
-	for (i=0 ; i<w->numpoints ; i++)
-		Sys_Printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
-}
-*/
-void prl(leaf_t *l)
-{
-	int			i;
-	portal_t	*p;
-	plane_t		pl;
-	
-	for (i=0 ; i<l->numportals ; i++)
-	{
-		p = l->portals[i];
-		pl = p->plane;
-		Sys_Printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
-	}
-}
-
-
-//=============================================================================
-
-/*
-=============
-SortPortals
-
-Sorts the portals from the least complex, so the later ones can reuse
-the earlier information.
-=============
-*/
-int PComp (const void *a, const void *b)
-{
-	if ( (*(portal_t **)a)->nummightsee == (*(portal_t **)b)->nummightsee)
-		return 0;
-	if ( (*(portal_t **)a)->nummightsee < (*(portal_t **)b)->nummightsee)
-		return -1;
-	return 1;
-}
-void SortPortals (void)
-{
-	int		i;
-	
-	for (i=0 ; i<numportals*2 ; i++)
-		sorted_portals[i] = &portals[i];
-
-	if (nosort)
-		return;
-	qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
-}
-
-
-/*
-==============
-LeafVectorFromPortalVector
-==============
-*/
-int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
-{
-	int			i;
-	portal_t	*p;
-	int			c_leafs;
-
-
-	memset (leafbits, 0, leafbytes);
-
-	for (i=0 ; i<numportals*2 ; i++)
-	{
-		if (portalbits[i>>3] & (1<<(i&7)) )
-		{
-			p = portals+i;
-			leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
-		}
-	}
-
-	c_leafs = CountBits (leafbits, portalclusters);
-
-	return c_leafs;
-}
-
-
-/*
-===============
-ClusterMerge
-
-Merges the portal visibility for a leaf
-===============
-*/
-void ClusterMerge (int leafnum)
-{
-	leaf_t		*leaf;
-	byte		portalvector[MAX_PORTALS/8];
-	byte		uncompressed[MAX_MAP_LEAFS/8];
-	byte		compressed[MAX_MAP_LEAFS/8];
-	int			i, j;
-	int			numvis;
-	byte		*dest;
-	portal_t	*p;
-	int			pnum;
-
-	// OR together all the portalvis bits
-
-	memset (portalvector, 0, portalbytes);
-	leaf = &leafs[leafnum];
-	for (i=0 ; i<leaf->numportals ; i++)
-	{
-		p = leaf->portals[i];
-		if (p->status != stat_done)
-			Error ("portal not done");
-		for (j=0 ; j<portallongs ; j++)
-			((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
-		pnum = p - portals;
-		portalvector[pnum>>3] |= 1<<(pnum&7);
-	}
-
-	// convert portal bits to leaf bits
-	numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
-
-	if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
-		Sys_Printf ("WARNING: Leaf portals saw into leaf\n");
-		
-	uncompressed[leafnum>>3] |= (1<<(leafnum&7));
-	numvis++;		// count the leaf itself
-
-	// save uncompressed for PHS calculation
-	memcpy (uncompressedvis + leafnum*leafbytes, uncompressed, leafbytes);
-
-//
-// compress the bit string
-//
-	Sys_FPrintf( SYS_VRB, "cluster %4i : %4i visible\n", leafnum, numvis);
-	totalvis += numvis;
-
-	i = CompressVis (uncompressed, compressed);
-
-	dest = vismap_p;
-	vismap_p += i;
-	
-	if (vismap_p > vismap_end)
-		Error ("Vismap expansion overflow");
-
-	dvis->bitofs[leafnum][DVIS_PVS] = dest-vismap;
-
-	memcpy (dest, compressed, i);	
-}
-
-
-/*
-==================
-CalcPortalVis
-==================
-*/
-void CalcPortalVis (void)
-{
-	int		i;
-
-// fastvis just uses mightsee for a very loose bound
-	if (fastvis)
-	{
-		for (i=0 ; i<numportals*2 ; i++)
-		{
-			portals[i].portalvis = portals[i].portalflood;
-			portals[i].status = stat_done;
-		}
-		return;
-	}
-	
-	RunThreadsOnIndividual (numportals*2, true, PortalFlow);
-
-}
-
-
-/*
-==================
-CalcVis
-==================
-*/
-void CalcVis (void)
-{
-	int		i;
-
-	RunThreadsOnIndividual (numportals*2, true, BasePortalVis);
-
-//	RunThreadsOnIndividual (numportals*2, true, BetterPortalVis);
-
-	SortPortals ();
-	
-	CalcPortalVis ();
-
-//
-// assemble the leaf vis lists by oring and compressing the portal lists
-//
-	for (i=0 ; i<portalclusters ; i++)
-		ClusterMerge (i);
-		
-	Sys_Printf ("Average clusters visible: %i\n", totalvis / portalclusters);
-}
-
-
-void SetPortalSphere (portal_t *p)
-{
-	int		i;
-	vec3_t	total, dist;
-	winding_t	*w;
-	float	r, bestr;
-
-	w = p->winding;
-	VectorCopy (vec3_origin, total);
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		VectorAdd (total, w->points[i], total);
-	}
-	
-	for (i=0 ; i<3 ; i++)
-		total[i] /= w->numpoints;
-
-	bestr = 0;		
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		VectorSubtract (w->points[i], total, dist);
-		r = VectorLength (dist);
-		if (r > bestr)
-			bestr = r;
-	}
-	VectorCopy (total, p->origin);
-	p->radius = bestr;
-}
-
-/*
-============
-LoadPortals
-============
-*/
-void LoadPortals (char *name)
-{
-	int			i, j;
-	portal_t	*p;
-	leaf_t		*l;
-	char		magic[80];
-	FILE		*f;
-	int			numpoints;
-	winding_t	*w;
-	int			leafnums[2];
-	plane_t		plane;
-	
-	if (!strcmp(name,"-"))
-		f = stdin;
-	else
-	{
-		f = fopen(name, "r");
-		if (!f)
-			Error ("LoadPortals: couldn't read %s\n",name);
-	}
-
-	if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals) != 3)
-		Error ("LoadPortals: failed to read header");
-	if (strcmp(magic,PORTALFILE))
-		Error ("LoadPortals: not a portal file");
-
-	Sys_Printf ("%4i portalclusters\n", portalclusters);
-	Sys_Printf ("%4i numportals\n", numportals);
-
-	// these counts should take advantage of 64 bit systems automatically
-	leafbytes = ((portalclusters+63)&~63)>>3;
-	leaflongs = leafbytes/sizeof(long);
-	
-	portalbytes = ((numportals*2+63)&~63)>>3;
-	portallongs = portalbytes/sizeof(long);
-
-// each file portal is split into two memory portals
-	portals = malloc(2*numportals*sizeof(portal_t));
-	memset (portals, 0, 2*numportals*sizeof(portal_t));
-	
-	leafs = malloc(portalclusters*sizeof(leaf_t));
-	memset (leafs, 0, portalclusters*sizeof(leaf_t));
-
-	originalvismapsize = portalclusters*leafbytes;
-	uncompressedvis = malloc(originalvismapsize);
-
-	vismap = vismap_p = dvisdata;
-	dvis->numclusters = portalclusters;
-	vismap_p = (byte *)&dvis->bitofs[portalclusters];
-
-	vismap_end = vismap + MAX_MAP_VISIBILITY;
-		
-	for (i=0, p=portals ; i<numportals ; i++)
-	{
-		if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
-			!= 3)
-			Error ("LoadPortals: reading portal %i", i);
-		if (numpoints > MAX_POINTS_ON_WINDING)
-			Error ("LoadPortals: portal %i has too many points", i);
-		if ( (unsigned)leafnums[0] > portalclusters
-		|| (unsigned)leafnums[1] > portalclusters)
-			Error ("LoadPortals: reading portal %i", i);
-		
-		w = p->winding = NewWinding (numpoints);
-		w->original = true;
-		w->numpoints = numpoints;
-		
-		for (j=0 ; j<numpoints ; j++)
-		{
-			double	v[3];
-			int		k;
-
-			// scanf into double, then assign to vec_t
-			// so we don't care what size vec_t is
-			if (fscanf (f, "(%lf %lf %lf ) "
-			, &v[0], &v[1], &v[2]) != 3)
-				Error ("LoadPortals: reading portal %i", i);
-			for (k=0 ; k<3 ; k++)
-				w->points[j][k] = v[k];
-		}
-		fscanf (f, "\n");
-		
-	// calc plane
-		PlaneFromWinding (w, &plane);
-
-	// create forward portal
-		l = &leafs[leafnums[0]];
-		if (l->numportals == MAX_PORTALS_ON_LEAF)
-			Error ("Leaf with too many portals");
-		l->portals[l->numportals] = p;
-		l->numportals++;
-		
-		p->winding = w;
-		VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
-		p->plane.dist = -plane.dist;
-		p->leaf = leafnums[1];
-		SetPortalSphere (p);
-		p++;
-		
-	// create backwards portal
-		l = &leafs[leafnums[1]];
-		if (l->numportals == MAX_PORTALS_ON_LEAF)
-			Error ("Leaf with too many portals");
-		l->portals[l->numportals] = p;
-		l->numportals++;
-		
-		p->winding = NewWinding(w->numpoints);
-		p->winding->numpoints = w->numpoints;
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
-		}
-
-		p->plane = plane;
-		p->leaf = leafnums[0];
-		SetPortalSphere (p);
-		p++;
-
-	}
-	
-	fclose (f);
-}
-
-
-/*
-================
-CalcPHS
-
-Calculate the PHS (Potentially Hearable Set)
-by ORing together all the PVS visible from a leaf
-================
-*/
-void CalcPHS (void)
-{
-	int		i, j, k, l, index;
-	int		bitbyte;
-	long	*dest, *src;
-	byte	*scan;
-	int		count;
-	byte	uncompressed[MAX_MAP_LEAFS/8];
-	byte	compressed[MAX_MAP_LEAFS/8];
-
-	Sys_Printf ("Building PHS...\n");
-
-	count = 0;
-	for (i=0 ; i<portalclusters ; i++)
-	{
-		scan = uncompressedvis + i*leafbytes;
-		memcpy (uncompressed, scan, leafbytes);
-		for (j=0 ; j<leafbytes ; j++)
-		{
-			bitbyte = scan[j];
-			if (!bitbyte)
-				continue;
-			for (k=0 ; k<8 ; k++)
-			{
-				if (! (bitbyte & (1<<k)) )
-					continue;
-				// OR this pvs row into the phs
-				index = ((j<<3)+k);
-				if (index >= portalclusters)
-					Error ("Bad bit in PVS");	// pad bits should be 0
-				src = (long *)(uncompressedvis + index*leafbytes);
-				dest = (long *)uncompressed;
-				for (l=0 ; l<leaflongs ; l++)
-					((long *)uncompressed)[l] |= src[l];
-			}
-		}
-		for (j=0 ; j<portalclusters ; j++)
-			if (uncompressed[j>>3] & (1<<(j&7)) )
-				count++;
-
-	//
-	// compress the bit string
-	//
-		j = CompressVis (uncompressed, compressed);
-
-		dest = (long *)vismap_p;
-		vismap_p += j;
-		
-		if (vismap_p > vismap_end)
-			Error ("Vismap expansion overflow");
-
-		dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap;
-
-		memcpy (dest, compressed, j);	
-	}
-
-	Sys_Printf ("Average clusters hearable: %i\n", count/portalclusters);
-}
-
-/*
-===========
-main
-===========
-*/
-int VIS_Main ()
-{
-	char	portalfile[1024];
-	char		source[1024];
-	char		name[1024];
-	double		start, end;
-	int		total_vis_time;
-		
-	Sys_Printf ("\n----- VIS ----\n\n");
-
-	//if (i != argc - 1)
-	//	Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
-
-	start = I_FloatTime ();
-	
-	ThreadSetDefault ();
-
-	SetQdirFromPath (mapname);	
-	strcpy (source, ExpandArg(mapname));
-	StripExtension (source);
-	DefaultExtension (source, ".bsp");
-
-	sprintf (name, "%s%s", inbase, source);
-	Sys_Printf ("reading %s\n", name);
-	LoadBSPFile (name);
-	if (numnodes == 0 || numfaces == 0)
-		Error ("Empty map");
-
-	sprintf (portalfile, "%s%s", inbase, ExpandArg(mapname));
-	StripExtension (portalfile);
-	strcat (portalfile, ".prt");
-	
-	Sys_Printf ("reading %s\n", portalfile);
-	LoadPortals (portalfile);
-	
-	CalcVis ();
-
-	CalcPHS ();
-
-	visdatasize = vismap_p - dvisdata;	
-	Sys_Printf ("visdatasize:%i  compressed from %i\n", visdatasize, originalvismapsize*2);
-
-	sprintf (name, "%s%s", outbase, source);
-	Sys_Printf ("writing %s\n", name);
-	WriteBSPFile (name);	
-	
-	end = I_FloatTime ();
-	total_vis_time = (int) (end-start);
-	Sys_Printf("\nVIS Time: ");
-	if ( total_vis_time > 59 )
-		Sys_Printf("%d Minutes ", total_vis_time/60 );
-	Sys_Printf( "%d Seconds\n", total_vis_time%60 );
-
-
-	return 0;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// qvis.c
+
+#include "qvis.h"
+#include "q2_threads.h"
+#include "stdlib.h"
+
+int			numportals;
+int			portalclusters;
+
+char		inbase[32];
+char		outbase[32];
+
+portal_t	*portals;
+leaf_t		*leafs;
+
+int			c_portaltest, c_portalpass, c_portalcheck;
+
+byte		*uncompressedvis;
+
+byte	*vismap, *vismap_p, *vismap_end;	// past visfile
+int		originalvismapsize;
+
+int		leafbytes;				// (portalclusters+63)>>3
+int		leaflongs;
+
+int		portalbytes, portallongs;
+
+qboolean		fastvis;
+qboolean		nosort;
+
+int			testlevel = 2;
+
+int		totalvis;
+
+portal_t	*sorted_portals[MAX_MAP_PORTALS*2];
+
+
+//=============================================================================
+
+void PlaneFromWinding (winding_t *w, plane_t *plane)
+{
+	vec3_t		v1, v2;
+
+// calc plane
+	VectorSubtract (w->points[2], w->points[1], v1);
+	VectorSubtract (w->points[0], w->points[1], v2);
+	CrossProduct (v2, v1, plane->normal);
+	VectorNormalize (plane->normal, plane->normal);
+	plane->dist = DotProduct (w->points[0], plane->normal);
+}
+
+
+/*
+==================
+NewWinding
+==================
+*/
+winding_t *NewWinding (int points)
+{
+	winding_t	*w;
+	int			size;
+	
+	if (points > MAX_POINTS_ON_WINDING)
+		Error ("NewWinding: %i points", points);
+	
+	size = (int)((winding_t *)0)->points[points];
+	w = malloc (size);
+	memset (w, 0, size);
+	
+	return w;
+}
+
+
+/*
+void pw(winding_t *w)
+{
+	int		i;
+	for (i=0 ; i<w->numpoints ; i++)
+		Sys_Printf ("(%5.1f, %5.1f, %5.1f)\n",w->points[i][0], w->points[i][1],w->points[i][2]);
+}
+*/
+void prl(leaf_t *l)
+{
+	int			i;
+	portal_t	*p;
+	plane_t		pl;
+	
+	for (i=0 ; i<l->numportals ; i++)
+	{
+		p = l->portals[i];
+		pl = p->plane;
+		Sys_Printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
+	}
+}
+
+
+//=============================================================================
+
+/*
+=============
+SortPortals
+
+Sorts the portals from the least complex, so the later ones can reuse
+the earlier information.
+=============
+*/
+int PComp (const void *a, const void *b)
+{
+	if ( (*(portal_t **)a)->nummightsee == (*(portal_t **)b)->nummightsee)
+		return 0;
+	if ( (*(portal_t **)a)->nummightsee < (*(portal_t **)b)->nummightsee)
+		return -1;
+	return 1;
+}
+void SortPortals (void)
+{
+	int		i;
+	
+	for (i=0 ; i<numportals*2 ; i++)
+		sorted_portals[i] = &portals[i];
+
+	if (nosort)
+		return;
+	qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
+}
+
+
+/*
+==============
+LeafVectorFromPortalVector
+==============
+*/
+int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
+{
+	int			i;
+	portal_t	*p;
+	int			c_leafs;
+
+
+	memset (leafbits, 0, leafbytes);
+
+	for (i=0 ; i<numportals*2 ; i++)
+	{
+		if (portalbits[i>>3] & (1<<(i&7)) )
+		{
+			p = portals+i;
+			leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
+		}
+	}
+
+	c_leafs = CountBits (leafbits, portalclusters);
+
+	return c_leafs;
+}
+
+
+/*
+===============
+ClusterMerge
+
+Merges the portal visibility for a leaf
+===============
+*/
+void ClusterMerge (int leafnum)
+{
+	leaf_t		*leaf;
+	byte		portalvector[MAX_PORTALS/8];
+	byte		uncompressed[MAX_MAP_LEAFS/8];
+	byte		compressed[MAX_MAP_LEAFS/8];
+	int			i, j;
+	int			numvis;
+	byte		*dest;
+	portal_t	*p;
+	int			pnum;
+
+	// OR together all the portalvis bits
+
+	memset (portalvector, 0, portalbytes);
+	leaf = &leafs[leafnum];
+	for (i=0 ; i<leaf->numportals ; i++)
+	{
+		p = leaf->portals[i];
+		if (p->status != stat_done)
+			Error ("portal not done");
+		for (j=0 ; j<portallongs ; j++)
+			((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
+		pnum = p - portals;
+		portalvector[pnum>>3] |= 1<<(pnum&7);
+	}
+
+	// convert portal bits to leaf bits
+	numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
+
+	if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
+		Sys_Printf ("WARNING: Leaf portals saw into leaf\n");
+		
+	uncompressed[leafnum>>3] |= (1<<(leafnum&7));
+	numvis++;		// count the leaf itself
+
+	// save uncompressed for PHS calculation
+	memcpy (uncompressedvis + leafnum*leafbytes, uncompressed, leafbytes);
+
+//
+// compress the bit string
+//
+	Sys_FPrintf( SYS_VRB, "cluster %4i : %4i visible\n", leafnum, numvis);
+	totalvis += numvis;
+
+	i = CompressVis (uncompressed, compressed);
+
+	dest = vismap_p;
+	vismap_p += i;
+	
+	if (vismap_p > vismap_end)
+		Error ("Vismap expansion overflow");
+
+	dvis->bitofs[leafnum][DVIS_PVS] = dest-vismap;
+
+	memcpy (dest, compressed, i);	
+}
+
+
+/*
+==================
+CalcPortalVis
+==================
+*/
+void CalcPortalVis (void)
+{
+	int		i;
+
+// fastvis just uses mightsee for a very loose bound
+	if (fastvis)
+	{
+		for (i=0 ; i<numportals*2 ; i++)
+		{
+			portals[i].portalvis = portals[i].portalflood;
+			portals[i].status = stat_done;
+		}
+		return;
+	}
+	
+	RunThreadsOnIndividual (numportals*2, true, PortalFlow);
+
+}
+
+
+/*
+==================
+CalcVis
+==================
+*/
+void CalcVis (void)
+{
+	int		i;
+
+	RunThreadsOnIndividual (numportals*2, true, BasePortalVis);
+
+//	RunThreadsOnIndividual (numportals*2, true, BetterPortalVis);
+
+	SortPortals ();
+	
+	CalcPortalVis ();
+
+//
+// assemble the leaf vis lists by oring and compressing the portal lists
+//
+	for (i=0 ; i<portalclusters ; i++)
+		ClusterMerge (i);
+		
+	Sys_Printf ("Average clusters visible: %i\n", totalvis / portalclusters);
+}
+
+
+void SetPortalSphere (portal_t *p)
+{
+	int		i;
+	vec3_t	total, dist;
+	winding_t	*w;
+	float	r, bestr;
+
+	w = p->winding;
+	VectorCopy (vec3_origin, total);
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		VectorAdd (total, w->points[i], total);
+	}
+	
+	for (i=0 ; i<3 ; i++)
+		total[i] /= w->numpoints;
+
+	bestr = 0;		
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		VectorSubtract (w->points[i], total, dist);
+		r = VectorLength (dist);
+		if (r > bestr)
+			bestr = r;
+	}
+	VectorCopy (total, p->origin);
+	p->radius = bestr;
+}
+
+/*
+============
+LoadPortals
+============
+*/
+void LoadPortals (char *name)
+{
+	int			i, j;
+	portal_t	*p;
+	leaf_t		*l;
+	char		magic[80];
+	FILE		*f;
+	int			numpoints;
+	winding_t	*w;
+	int			leafnums[2];
+	plane_t		plane;
+	
+	if (!strcmp(name,"-"))
+		f = stdin;
+	else
+	{
+		f = fopen(name, "r");
+		if (!f)
+			Error ("LoadPortals: couldn't read %s\n",name);
+	}
+
+	if (fscanf (f,"%79s\n%i\n%i\n",magic, &portalclusters, &numportals) != 3)
+		Error ("LoadPortals: failed to read header");
+	if (strcmp(magic,PORTALFILE))
+		Error ("LoadPortals: not a portal file");
+
+	Sys_Printf ("%4i portalclusters\n", portalclusters);
+	Sys_Printf ("%4i numportals\n", numportals);
+
+	// these counts should take advantage of 64 bit systems automatically
+	leafbytes = ((portalclusters+63)&~63)>>3;
+	leaflongs = leafbytes/sizeof(long);
+	
+	portalbytes = ((numportals*2+63)&~63)>>3;
+	portallongs = portalbytes/sizeof(long);
+
+// each file portal is split into two memory portals
+	portals = malloc(2*numportals*sizeof(portal_t));
+	memset (portals, 0, 2*numportals*sizeof(portal_t));
+	
+	leafs = malloc(portalclusters*sizeof(leaf_t));
+	memset (leafs, 0, portalclusters*sizeof(leaf_t));
+
+	originalvismapsize = portalclusters*leafbytes;
+	uncompressedvis = malloc(originalvismapsize);
+
+	vismap = vismap_p = dvisdata;
+	dvis->numclusters = portalclusters;
+	vismap_p = (byte *)&dvis->bitofs[portalclusters];
+
+	vismap_end = vismap + MAX_MAP_VISIBILITY;
+		
+	for (i=0, p=portals ; i<numportals ; i++)
+	{
+		if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1])
+			!= 3)
+			Error ("LoadPortals: reading portal %i", i);
+		if (numpoints > MAX_POINTS_ON_WINDING)
+			Error ("LoadPortals: portal %i has too many points", i);
+		if ( (unsigned)leafnums[0] > portalclusters
+		|| (unsigned)leafnums[1] > portalclusters)
+			Error ("LoadPortals: reading portal %i", i);
+		
+		w = p->winding = NewWinding (numpoints);
+		w->original = true;
+		w->numpoints = numpoints;
+		
+		for (j=0 ; j<numpoints ; j++)
+		{
+			double	v[3];
+			int		k;
+
+			// scanf into double, then assign to vec_t
+			// so we don't care what size vec_t is
+			if (fscanf (f, "(%lf %lf %lf ) "
+			, &v[0], &v[1], &v[2]) != 3)
+				Error ("LoadPortals: reading portal %i", i);
+			for (k=0 ; k<3 ; k++)
+				w->points[j][k] = v[k];
+		}
+		fscanf (f, "\n");
+		
+	// calc plane
+		PlaneFromWinding (w, &plane);
+
+	// create forward portal
+		l = &leafs[leafnums[0]];
+		if (l->numportals == MAX_PORTALS_ON_LEAF)
+			Error ("Leaf with too many portals");
+		l->portals[l->numportals] = p;
+		l->numportals++;
+		
+		p->winding = w;
+		VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
+		p->plane.dist = -plane.dist;
+		p->leaf = leafnums[1];
+		SetPortalSphere (p);
+		p++;
+		
+	// create backwards portal
+		l = &leafs[leafnums[1]];
+		if (l->numportals == MAX_PORTALS_ON_LEAF)
+			Error ("Leaf with too many portals");
+		l->portals[l->numportals] = p;
+		l->numportals++;
+		
+		p->winding = NewWinding(w->numpoints);
+		p->winding->numpoints = w->numpoints;
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
+		}
+
+		p->plane = plane;
+		p->leaf = leafnums[0];
+		SetPortalSphere (p);
+		p++;
+
+	}
+	
+	fclose (f);
+}
+
+
+/*
+================
+CalcPHS
+
+Calculate the PHS (Potentially Hearable Set)
+by ORing together all the PVS visible from a leaf
+================
+*/
+void CalcPHS (void)
+{
+	int		i, j, k, l, index;
+	int		bitbyte;
+	long	*dest, *src;
+	byte	*scan;
+	int		count;
+	byte	uncompressed[MAX_MAP_LEAFS/8];
+	byte	compressed[MAX_MAP_LEAFS/8];
+
+	Sys_Printf ("Building PHS...\n");
+
+	count = 0;
+	for (i=0 ; i<portalclusters ; i++)
+	{
+		scan = uncompressedvis + i*leafbytes;
+		memcpy (uncompressed, scan, leafbytes);
+		for (j=0 ; j<leafbytes ; j++)
+		{
+			bitbyte = scan[j];
+			if (!bitbyte)
+				continue;
+			for (k=0 ; k<8 ; k++)
+			{
+				if (! (bitbyte & (1<<k)) )
+					continue;
+				// OR this pvs row into the phs
+				index = ((j<<3)+k);
+				if (index >= portalclusters)
+					Error ("Bad bit in PVS");	// pad bits should be 0
+				src = (long *)(uncompressedvis + index*leafbytes);
+				dest = (long *)uncompressed;
+				for (l=0 ; l<leaflongs ; l++)
+					((long *)uncompressed)[l] |= src[l];
+			}
+		}
+		for (j=0 ; j<portalclusters ; j++)
+			if (uncompressed[j>>3] & (1<<(j&7)) )
+				count++;
+
+	//
+	// compress the bit string
+	//
+		j = CompressVis (uncompressed, compressed);
+
+		dest = (long *)vismap_p;
+		vismap_p += j;
+		
+		if (vismap_p > vismap_end)
+			Error ("Vismap expansion overflow");
+
+		dvis->bitofs[i][DVIS_PHS] = (byte *)dest-vismap;
+
+		memcpy (dest, compressed, j);	
+	}
+
+	Sys_Printf ("Average clusters hearable: %i\n", count/portalclusters);
+}
+
+/*
+===========
+main
+===========
+*/
+int VIS_Main ()
+{
+	char	portalfile[1024];
+	char		source[1024];
+	char		name[1024];
+	double		start, end;
+	int		total_vis_time;
+		
+	Sys_Printf ("\n----- VIS ----\n\n");
+
+	//if (i != argc - 1)
+	//	Error ("usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile");
+
+	start = I_FloatTime ();
+	
+	ThreadSetDefault ();
+
+	SetQdirFromPath (mapname);	
+	strcpy (source, ExpandArg(mapname));
+	StripExtension (source);
+	DefaultExtension (source, ".bsp");
+
+	sprintf (name, "%s%s", inbase, source);
+	Sys_Printf ("reading %s\n", name);
+	LoadBSPFile (name);
+	if (numnodes == 0 || numfaces == 0)
+		Error ("Empty map");
+
+	sprintf (portalfile, "%s%s", inbase, ExpandArg(mapname));
+	StripExtension (portalfile);
+	strcat (portalfile, ".prt");
+	
+	Sys_Printf ("reading %s\n", portalfile);
+	LoadPortals (portalfile);
+	
+	CalcVis ();
+
+	CalcPHS ();
+
+	visdatasize = vismap_p - dvisdata;	
+	Sys_Printf ("visdatasize:%i  compressed from %i\n", visdatasize, originalvismapsize*2);
+
+	sprintf (name, "%s%s", outbase, source);
+	Sys_Printf ("writing %s\n", name);
+	WriteBSPFile (name);	
+	
+	end = I_FloatTime ();
+	total_vis_time = (int) (end-start);
+	Sys_Printf("\nVIS Time: ");
+	if ( total_vis_time > 59 )
+		Sys_Printf("%d Minutes ", total_vis_time/60 );
+	Sys_Printf( "%d Seconds\n", total_vis_time%60 );
+
+
+	return 0;
+}
+
diff --git a/tools/quake2/q2map/qvis.h b/tools/quake2/q2map/qvis.h
index 9128907c..44c84516 100644
--- a/tools/quake2/q2map/qvis.h
+++ b/tools/quake2/q2map/qvis.h
@@ -1,169 +1,169 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-/* Files:
-
-flow.c
-qvis3.c
-
-*/
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "bspfile.h"
-#include "inout.h"
-
-#ifdef _WIN32
-	#ifdef NDEBUG							// Don't show in a Release build
-		#pragma warning(disable : 4305)     // truncate from double to float
-		#pragma warning(disable : 4244)     // conversion from double to float
-		#pragma warning(disable : 4018)     // signed/unsigned mismatch
-	#endif
-#endif
-
-#define	MAX_PORTALS	32768
-
-#define	PORTALFILE	"PRT1"
-
-#define	ON_EPSILON	0.1
-
-typedef struct
-{
-	vec3_t		normal;
-	float		dist;
-} plane_t;
-
-#define MAX_POINTS_ON_WINDING	64
-#define	MAX_POINTS_ON_FIXED_WINDING	12
-
-typedef struct
-{
-	qboolean	original;			// don't free, it's part of the portal
-	int		numpoints;
-	vec3_t	points[MAX_POINTS_ON_FIXED_WINDING];			// variable sized
-} winding_t;
-
-winding_t	*NewWinding (int points);
-void		FreeWinding (winding_t *w);
-winding_t	*CopyWinding (winding_t *w);
-
-
-typedef enum {stat_none, stat_working, stat_done} vstatus_t;
-typedef struct
-{
-	plane_t		plane;	// normal pointing into neighbor
-	int			leaf;	// neighbor
-	
-	vec3_t		origin;	// for fast clip testing
-	float		radius;
-
-	winding_t	*winding;
-	vstatus_t	status;
-	byte		*portalfront;	// [portals], preliminary
-	byte		*portalflood;	// [portals], intermediate
-	byte		*portalvis;		// [portals], final
-
-	int			nummightsee;	// bit count on portalflood for sort
-} portal_t;
-
-typedef struct seperating_plane_s
-{
-	struct seperating_plane_s *next;
-	plane_t		plane;		// from portal is on positive side
-} sep_t;
-
-
-typedef struct passage_s
-{
-	struct passage_s	*next;
-	int			from, to;		// leaf numbers
-	sep_t				*planes;
-} passage_t;
-
-#define	MAX_PORTALS_ON_LEAF		128
-typedef struct leaf_s
-{
-	int			numportals;
-	passage_t	*passages;
-	portal_t	*portals[MAX_PORTALS_ON_LEAF];
-} leaf_t;
-
-	
-typedef struct pstack_s
-{
-	byte		mightsee[MAX_PORTALS/8];		// bit string
-	struct pstack_s	*next;
-	leaf_t		*leaf;
-	portal_t	*portal;	// portal exiting
-	winding_t	*source;
-	winding_t	*pass;
-
-	winding_t	windings[3];	// source, pass, temp in any order
-	int			freewindings[3];
-
-	plane_t		portalplane;
-} pstack_t;
-
-typedef struct
-{
-	portal_t	*base;
-	int			c_chains;
-	pstack_t	pstack_head;
-} threaddata_t;
-
-
-
-extern	int			numportals;
-extern	int			portalclusters;
-
-extern	portal_t	*portals;
-extern	leaf_t		*leafs;
-
-extern	int			c_portaltest, c_portalpass, c_portalcheck;
-extern	int			c_portalskip, c_leafskip;
-extern	int			c_vistest, c_mighttest;
-extern	int			c_chains;
-
-extern	byte	*vismap, *vismap_p, *vismap_end;	// past visfile
-
-extern	int			testlevel;
-
-extern	byte		*uncompressed;
-
-extern	int		leafbytes, leaflongs;
-extern	int		portalbytes, portallongs;
-
-
-void LeafFlow (int leafnum);
-
-
-void BasePortalVis (int portalnum);
-void BetterPortalVis (int portalnum);
-void PortalFlow (int portalnum);
-
-extern	portal_t	*sorted_portals[MAX_MAP_PORTALS*2];
-
-int CountBits (byte *bits, int numbits);
-
-//=============================================================================
-
-// externs
-
-extern char	*mapname;
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+/* Files:
+
+flow.c
+qvis3.c
+
+*/
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "bspfile.h"
+#include "inout.h"
+
+#ifdef _WIN32
+	#ifdef NDEBUG							// Don't show in a Release build
+		#pragma warning(disable : 4305)     // truncate from double to float
+		#pragma warning(disable : 4244)     // conversion from double to float
+		#pragma warning(disable : 4018)     // signed/unsigned mismatch
+	#endif
+#endif
+
+#define	MAX_PORTALS	32768
+
+#define	PORTALFILE	"PRT1"
+
+#define	ON_EPSILON	0.1
+
+typedef struct
+{
+	vec3_t		normal;
+	float		dist;
+} plane_t;
+
+#define MAX_POINTS_ON_WINDING	64
+#define	MAX_POINTS_ON_FIXED_WINDING	12
+
+typedef struct
+{
+	qboolean	original;			// don't free, it's part of the portal
+	int		numpoints;
+	vec3_t	points[MAX_POINTS_ON_FIXED_WINDING];			// variable sized
+} winding_t;
+
+winding_t	*NewWinding (int points);
+void		FreeWinding (winding_t *w);
+winding_t	*CopyWinding (winding_t *w);
+
+
+typedef enum {stat_none, stat_working, stat_done} vstatus_t;
+typedef struct
+{
+	plane_t		plane;	// normal pointing into neighbor
+	int			leaf;	// neighbor
+	
+	vec3_t		origin;	// for fast clip testing
+	float		radius;
+
+	winding_t	*winding;
+	vstatus_t	status;
+	byte		*portalfront;	// [portals], preliminary
+	byte		*portalflood;	// [portals], intermediate
+	byte		*portalvis;		// [portals], final
+
+	int			nummightsee;	// bit count on portalflood for sort
+} portal_t;
+
+typedef struct seperating_plane_s
+{
+	struct seperating_plane_s *next;
+	plane_t		plane;		// from portal is on positive side
+} sep_t;
+
+
+typedef struct passage_s
+{
+	struct passage_s	*next;
+	int			from, to;		// leaf numbers
+	sep_t				*planes;
+} passage_t;
+
+#define	MAX_PORTALS_ON_LEAF		128
+typedef struct leaf_s
+{
+	int			numportals;
+	passage_t	*passages;
+	portal_t	*portals[MAX_PORTALS_ON_LEAF];
+} leaf_t;
+
+	
+typedef struct pstack_s
+{
+	byte		mightsee[MAX_PORTALS/8];		// bit string
+	struct pstack_s	*next;
+	leaf_t		*leaf;
+	portal_t	*portal;	// portal exiting
+	winding_t	*source;
+	winding_t	*pass;
+
+	winding_t	windings[3];	// source, pass, temp in any order
+	int			freewindings[3];
+
+	plane_t		portalplane;
+} pstack_t;
+
+typedef struct
+{
+	portal_t	*base;
+	int			c_chains;
+	pstack_t	pstack_head;
+} threaddata_t;
+
+
+
+extern	int			numportals;
+extern	int			portalclusters;
+
+extern	portal_t	*portals;
+extern	leaf_t		*leafs;
+
+extern	int			c_portaltest, c_portalpass, c_portalcheck;
+extern	int			c_portalskip, c_leafskip;
+extern	int			c_vistest, c_mighttest;
+extern	int			c_chains;
+
+extern	byte	*vismap, *vismap_p, *vismap_end;	// past visfile
+
+extern	int			testlevel;
+
+extern	byte		*uncompressed;
+
+extern	int		leafbytes, leaflongs;
+extern	int		portalbytes, portallongs;
+
+
+void LeafFlow (int leafnum);
+
+
+void BasePortalVis (int portalnum);
+void BetterPortalVis (int portalnum);
+void PortalFlow (int portalnum);
+
+extern	portal_t	*sorted_portals[MAX_MAP_PORTALS*2];
+
+int CountBits (byte *bits, int numbits);
+
+//=============================================================================
+
+// externs
+
+extern char	*mapname;
diff --git a/tools/quake2/q2map/textures.c b/tools/quake2/q2map/textures.c
index bbf6b29a..c0589de0 100644
--- a/tools/quake2/q2map/textures.c
+++ b/tools/quake2/q2map/textures.c
@@ -1,249 +1,249 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-int		nummiptex;
-textureref_t	textureref[MAX_MAP_TEXTURES];
-
-//==========================================================================
-
-
-int	FindMiptex (char *name)
-{
-	int		i;
-	char	path[1024];
-	miptex_t	*mt;
-	miptex_m8_t	*mt_m8;
-	miptex_m32_t	*mt_m32;
-
-	for (i=0 ; i<nummiptex ; i++)
-		if (!strcmp (name, textureref[i].name))
-		{
-			return i;
-		}
-	if (nummiptex == MAX_MAP_TEXTURES)
-		Error ("MAX_MAP_TEXTURES");
-	strcpy (textureref[i].name, name);
-
-	// load the miptex to get the flags and values
-	if ( !strcmp( game, "heretic2" ) )
-	{
-		sprintf (path, "%stextures/%s.m32", gamedir, name);
-		if (TryLoadFile (path, (void **)&mt_m32) != -1)
-		{
-			textureref[i].value = LittleLong (mt_m32->value);
-			textureref[i].flags = LittleLong (mt_m32->flags);
-			textureref[i].contents = LittleLong (mt_m32->contents);
-			strcpy (textureref[i].animname, mt_m32->animname);
-			free (mt_m32);
-		}
-		else
-			sprintf (path, "%stextures/%s.m8", gamedir, name);
-		
-		if (TryLoadFile (path, (void **)&mt_m8) != -1)
-		{
-			textureref[i].value = LittleLong (mt_m8->value);
-			textureref[i].flags = LittleLong (mt_m8->flags);
-			textureref[i].contents = LittleLong (mt_m8->contents);
-			strcpy (textureref[i].animname, mt_m8->animname);
-			free (mt_m8);
-		}
-	}
-	else
-	{
-	sprintf (path, "%stextures/%s.wal", gamedir, name);
-		if (TryLoadFile (path, (void **)&mt) != -1)
-		{
-			textureref[i].value = LittleLong (mt->value);
-			textureref[i].flags = LittleLong (mt->flags);
-			textureref[i].contents = LittleLong (mt->contents);
-			strcpy (textureref[i].animname, mt->animname);
-			free (mt);
-		}
-	}
-	
-	nummiptex++;
-
-	if (textureref[i].animname[0])
-		FindMiptex (textureref[i].animname);
-
-	return i;
-}
-
-
-/*
-==================
-textureAxisFromPlane
-==================
-*/
-vec3_t	baseaxis[18] =
-{
-{0,0,1}, {1,0,0}, {0,-1,0},			// floor
-{0,0,-1}, {1,0,0}, {0,-1,0},		// ceiling
-{1,0,0}, {0,1,0}, {0,0,-1},			// west wall
-{-1,0,0}, {0,1,0}, {0,0,-1},		// east wall
-{0,1,0}, {1,0,0}, {0,0,-1},			// south wall
-{0,-1,0}, {1,0,0}, {0,0,-1}			// north wall
-};
-
-void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
-{
-	int		bestaxis;
-	vec_t	dot,best;
-	int		i;
-	
-	best = 0;
-	bestaxis = 0;
-	
-	for (i=0 ; i<6 ; i++)
-	{
-		dot = DotProduct (pln->normal, baseaxis[i*3]);
-		if (dot > best)
-		{
-			best = dot;
-			bestaxis = i;
-		}
-	}
-	
-	VectorCopy (baseaxis[bestaxis*3+1], xv);
-	VectorCopy (baseaxis[bestaxis*3+2], yv);
-}
-
-
-
-
-int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin)
-{
-	vec3_t	vecs[2];
-	int		sv, tv;
-	vec_t	ang, sinv, cosv;
-	vec_t	ns, nt;
-	texinfo_t	tx, *tc;
-	int		i, j, k;
-	float	shift[2];
-	brush_texture_t		anim;
-	int				mt;
-
-	if (!bt->name[0])
-		return 0;
-
-	memset (&tx, 0, sizeof(tx));
-	strcpy (tx.texture, bt->name);
-
-	TextureAxisFromPlane(plane, vecs[0], vecs[1]);
-
-	shift[0] = DotProduct (origin, vecs[0]);
-	shift[1] = DotProduct (origin, vecs[1]);
-
-	if (!bt->scale[0])
-		bt->scale[0] = 1;
-	if (!bt->scale[1])
-		bt->scale[1] = 1;
-
-
-// rotate axis
-	if (bt->rotate == 0)
-		{ sinv = 0 ; cosv = 1; }
-	else if (bt->rotate == 90)
-		{ sinv = 1 ; cosv = 0; }
-	else if (bt->rotate == 180)
-		{ sinv = 0 ; cosv = -1; }
-	else if (bt->rotate == 270)
-		{ sinv = -1 ; cosv = 0; }
-	else
-	{	
-		ang = bt->rotate / 180 * Q_PI;
-		sinv = sin(ang);
-		cosv = cos(ang);
-	}
-
-	if (vecs[0][0])
-		sv = 0;
-	else if (vecs[0][1])
-		sv = 1;
-	else
-		sv = 2;
-				
-	if (vecs[1][0])
-		tv = 0;
-	else if (vecs[1][1])
-		tv = 1;
-	else
-		tv = 2;
-					
-	for (i=0 ; i<2 ; i++)
-	{
-		ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
-		nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
-		vecs[i][sv] = ns;
-		vecs[i][tv] = nt;
-	}
-
-	for (i=0 ; i<2 ; i++)
-		for (j=0 ; j<3 ; j++)
-			tx.vecs[i][j] = vecs[i][j] / bt->scale[i];
-
-	tx.vecs[0][3] = bt->shift[0] + shift[0];
-	tx.vecs[1][3] = bt->shift[1] + shift[1];
-	tx.flags = bt->flags;
-	tx.value = bt->value;
-
-	//
-	// find the texinfo
-	//
-	tc = texinfo;
-	for (i=0 ; i<numtexinfo ; i++, tc++)
-	{
-		if (tc->flags != tx.flags)
-			continue;
-		if (tc->value != tx.value)
-			continue;
-		for (j=0 ; j<2 ; j++)
-		{
-			if (strcmp (tc->texture, tx.texture))
-				goto skip;
-			for (k=0 ; k<4 ; k++)
-			{
-				if (tc->vecs[j][k] != tx.vecs[j][k])
-					goto skip;
-			}
-		}
-		return i;
-skip:;
-	}
-	*tc = tx;
-	numtexinfo++;
-
-	// load the next animation
-	mt = FindMiptex (bt->name);
-	if (textureref[mt].animname[0])
-	{
-		anim = *bt;
-		strcpy (anim.name, textureref[mt].animname);
-		tc->nexttexinfo = TexinfoForBrushTexture (plane, &anim, origin);
-	}
-	else
-		tc->nexttexinfo = -1;
-
-
-	return i;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+int		nummiptex;
+textureref_t	textureref[MAX_MAP_TEXTURES];
+
+//==========================================================================
+
+
+int	FindMiptex (char *name)
+{
+	int		i;
+	char	path[1024];
+	miptex_t	*mt;
+	miptex_m8_t	*mt_m8;
+	miptex_m32_t	*mt_m32;
+
+	for (i=0 ; i<nummiptex ; i++)
+		if (!strcmp (name, textureref[i].name))
+		{
+			return i;
+		}
+	if (nummiptex == MAX_MAP_TEXTURES)
+		Error ("MAX_MAP_TEXTURES");
+	strcpy (textureref[i].name, name);
+
+	// load the miptex to get the flags and values
+	if ( !strcmp( game, "heretic2" ) )
+	{
+		sprintf (path, "%stextures/%s.m32", gamedir, name);
+		if (TryLoadFile (path, (void **)&mt_m32) != -1)
+		{
+			textureref[i].value = LittleLong (mt_m32->value);
+			textureref[i].flags = LittleLong (mt_m32->flags);
+			textureref[i].contents = LittleLong (mt_m32->contents);
+			strcpy (textureref[i].animname, mt_m32->animname);
+			free (mt_m32);
+		}
+		else
+			sprintf (path, "%stextures/%s.m8", gamedir, name);
+		
+		if (TryLoadFile (path, (void **)&mt_m8) != -1)
+		{
+			textureref[i].value = LittleLong (mt_m8->value);
+			textureref[i].flags = LittleLong (mt_m8->flags);
+			textureref[i].contents = LittleLong (mt_m8->contents);
+			strcpy (textureref[i].animname, mt_m8->animname);
+			free (mt_m8);
+		}
+	}
+	else
+	{
+	sprintf (path, "%stextures/%s.wal", gamedir, name);
+		if (TryLoadFile (path, (void **)&mt) != -1)
+		{
+			textureref[i].value = LittleLong (mt->value);
+			textureref[i].flags = LittleLong (mt->flags);
+			textureref[i].contents = LittleLong (mt->contents);
+			strcpy (textureref[i].animname, mt->animname);
+			free (mt);
+		}
+	}
+	
+	nummiptex++;
+
+	if (textureref[i].animname[0])
+		FindMiptex (textureref[i].animname);
+
+	return i;
+}
+
+
+/*
+==================
+textureAxisFromPlane
+==================
+*/
+vec3_t	baseaxis[18] =
+{
+{0,0,1}, {1,0,0}, {0,-1,0},			// floor
+{0,0,-1}, {1,0,0}, {0,-1,0},		// ceiling
+{1,0,0}, {0,1,0}, {0,0,-1},			// west wall
+{-1,0,0}, {0,1,0}, {0,0,-1},		// east wall
+{0,1,0}, {1,0,0}, {0,0,-1},			// south wall
+{0,-1,0}, {1,0,0}, {0,0,-1}			// north wall
+};
+
+void TextureAxisFromPlane(plane_t *pln, vec3_t xv, vec3_t yv)
+{
+	int		bestaxis;
+	vec_t	dot,best;
+	int		i;
+	
+	best = 0;
+	bestaxis = 0;
+	
+	for (i=0 ; i<6 ; i++)
+	{
+		dot = DotProduct (pln->normal, baseaxis[i*3]);
+		if (dot > best)
+		{
+			best = dot;
+			bestaxis = i;
+		}
+	}
+	
+	VectorCopy (baseaxis[bestaxis*3+1], xv);
+	VectorCopy (baseaxis[bestaxis*3+2], yv);
+}
+
+
+
+
+int TexinfoForBrushTexture (plane_t *plane, brush_texture_t *bt, vec3_t origin)
+{
+	vec3_t	vecs[2];
+	int		sv, tv;
+	vec_t	ang, sinv, cosv;
+	vec_t	ns, nt;
+	texinfo_t	tx, *tc;
+	int		i, j, k;
+	float	shift[2];
+	brush_texture_t		anim;
+	int				mt;
+
+	if (!bt->name[0])
+		return 0;
+
+	memset (&tx, 0, sizeof(tx));
+	strcpy (tx.texture, bt->name);
+
+	TextureAxisFromPlane(plane, vecs[0], vecs[1]);
+
+	shift[0] = DotProduct (origin, vecs[0]);
+	shift[1] = DotProduct (origin, vecs[1]);
+
+	if (!bt->scale[0])
+		bt->scale[0] = 1;
+	if (!bt->scale[1])
+		bt->scale[1] = 1;
+
+
+// rotate axis
+	if (bt->rotate == 0)
+		{ sinv = 0 ; cosv = 1; }
+	else if (bt->rotate == 90)
+		{ sinv = 1 ; cosv = 0; }
+	else if (bt->rotate == 180)
+		{ sinv = 0 ; cosv = -1; }
+	else if (bt->rotate == 270)
+		{ sinv = -1 ; cosv = 0; }
+	else
+	{	
+		ang = bt->rotate / 180 * Q_PI;
+		sinv = sin(ang);
+		cosv = cos(ang);
+	}
+
+	if (vecs[0][0])
+		sv = 0;
+	else if (vecs[0][1])
+		sv = 1;
+	else
+		sv = 2;
+				
+	if (vecs[1][0])
+		tv = 0;
+	else if (vecs[1][1])
+		tv = 1;
+	else
+		tv = 2;
+					
+	for (i=0 ; i<2 ; i++)
+	{
+		ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
+		nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
+		vecs[i][sv] = ns;
+		vecs[i][tv] = nt;
+	}
+
+	for (i=0 ; i<2 ; i++)
+		for (j=0 ; j<3 ; j++)
+			tx.vecs[i][j] = vecs[i][j] / bt->scale[i];
+
+	tx.vecs[0][3] = bt->shift[0] + shift[0];
+	tx.vecs[1][3] = bt->shift[1] + shift[1];
+	tx.flags = bt->flags;
+	tx.value = bt->value;
+
+	//
+	// find the texinfo
+	//
+	tc = texinfo;
+	for (i=0 ; i<numtexinfo ; i++, tc++)
+	{
+		if (tc->flags != tx.flags)
+			continue;
+		if (tc->value != tx.value)
+			continue;
+		for (j=0 ; j<2 ; j++)
+		{
+			if (strcmp (tc->texture, tx.texture))
+				goto skip;
+			for (k=0 ; k<4 ; k++)
+			{
+				if (tc->vecs[j][k] != tx.vecs[j][k])
+					goto skip;
+			}
+		}
+		return i;
+skip:;
+	}
+	*tc = tx;
+	numtexinfo++;
+
+	// load the next animation
+	mt = FindMiptex (bt->name);
+	if (textureref[mt].animname[0])
+	{
+		anim = *bt;
+		strcpy (anim.name, textureref[mt].animname);
+		tc->nexttexinfo = TexinfoForBrushTexture (plane, &anim, origin);
+	}
+	else
+		tc->nexttexinfo = -1;
+
+
+	return i;
+}
diff --git a/tools/quake2/q2map/trace.c b/tools/quake2/q2map/trace.c
index 66d0e837..35902baf 100644
--- a/tools/quake2/q2map/trace.c
+++ b/tools/quake2/q2map/trace.c
@@ -1,298 +1,298 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-// trace.c
-/*
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "bspfile.h"
-*/
-
-#include "qrad.h"
-
-#define	ON_EPSILON	0.1
-
-typedef struct tnode_s
-{
-	int		type;
-	vec3_t	normal;
-	float	dist;
-	int		children[2];
-	int		pad;
-} tnode_t;
-
-tnode_t		*tnodes, *tnode_p;
-
-/*
-==============
-MakeTnode
-
-Converts the disk node structure into the efficient tracing structure
-==============
-*/
-void MakeTnode (int nodenum)
-{
-	tnode_t			*t;
-	dplane_t		*plane;
-	int				i;
-	dnode_t 		*node;
-	
-	t = tnode_p++;
-
-	node = dnodes + nodenum;
-	plane = dplanes + node->planenum;
-
-	t->type = plane->type;
-	VectorCopy (plane->normal, t->normal);
-	t->dist = plane->dist;
-	
-	for (i=0 ; i<2 ; i++)
-	{
-		if (node->children[i] < 0)
-			t->children[i] = (dleafs[-node->children[i] - 1].contents & CONTENTS_SOLID) | (1<<31);
-		else
-		{
-			t->children[i] = tnode_p - tnodes;
-			MakeTnode (node->children[i]);
-		}
-	}
-			
-}
-
-
-/*
-=============
-MakeTnodes
-
-Loads the node structure out of a .bsp file to be used for light occlusion
-=============
-*/
-void MakeTnodes (dmodel_t *bm)
-{
-	// 32 byte align the structs
-	tnodes = malloc( (numnodes+1) * sizeof(tnode_t));
-	tnodes = (tnode_t *)(((int)tnodes + 31)&~31);
-	tnode_p = tnodes;
-
-	MakeTnode (0);
-}
-
-
-//==========================================================
-
-
-int TestLine_r (int node, vec3_t start, vec3_t stop)
-{
-	tnode_t	*tnode;
-	float	front, back;
-	vec3_t	mid;
-	float	frac;
-	int		side;
-	int		r;
-
-	if (node & (1<<31))
-		return node & ~(1<<31);	// leaf node
-
-	tnode = &tnodes[node];
-	switch (tnode->type)
-	{
-	case PLANE_X:
-		front = start[0] - tnode->dist;
-		back = stop[0] - tnode->dist;
-		break;
-	case PLANE_Y:
-		front = start[1] - tnode->dist;
-		back = stop[1] - tnode->dist;
-		break;
-	case PLANE_Z:
-		front = start[2] - tnode->dist;
-		back = stop[2] - tnode->dist;
-		break;
-	default:
-		front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
-		back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist;
-		break;
-	}
-
-	if (front >= -ON_EPSILON && back >= -ON_EPSILON)
-		return TestLine_r (tnode->children[0], start, stop);
-	
-	if (front < ON_EPSILON && back < ON_EPSILON)
-		return TestLine_r (tnode->children[1], start, stop);
-
-	side = front < 0;
-	
-	frac = front / (front-back);
-
-	mid[0] = start[0] + (stop[0] - start[0])*frac;
-	mid[1] = start[1] + (stop[1] - start[1])*frac;
-	mid[2] = start[2] + (stop[2] - start[2])*frac;
-
-	r = TestLine_r (tnode->children[side], start, mid);
-	if (r)
-		return r;
-	return TestLine_r (tnode->children[!side], mid, stop);
-}
-
-int TestLine (vec3_t start, vec3_t stop)
-{
-	return TestLine_r (0, start, stop);
-}
-
-/*
-==============================================================================
-
-LINE TRACING
-
-The major lighting operation is a point to point visibility test, performed
-by recursive subdivision of the line by the BSP tree.
-
-==============================================================================
-*/
-
-typedef struct
-{
-	vec3_t	backpt;
-	int		side;
-	int		node;
-} tracestack_t;
-
-
-/*
-==============
-TestLine
-==============
-*/
-qboolean _TestLine (vec3_t start, vec3_t stop)
-{
-	int				node;
-	float			front, back;
-	tracestack_t	*tstack_p;
-	int				side;
-	float 			frontx,fronty, frontz, backx, backy, backz;
-	tracestack_t	tracestack[64];
-	tnode_t			*tnode;
-	
-	frontx = start[0];
-	fronty = start[1];
-	frontz = start[2];
-	backx = stop[0];
-	backy = stop[1];
-	backz = stop[2];
-	
-	tstack_p = tracestack;
-	node = 0;
-	
-	while (1)
-	{
-		if (node == CONTENTS_SOLID)
-		{
-#if 0
-			float	d1, d2, d3;
-
-			d1 = backx - frontx;
-			d2 = backy - fronty;
-			d3 = backz - frontz;
-
-			if (d1*d1 + d2*d2 + d3*d3 > 1)
-#endif
-				return false;	// DONE!
-		}
-		
-		while (node < 0)
-		{
-		// pop up the stack for a back side
-			tstack_p--;
-			if (tstack_p < tracestack)
-				return true;
-			node = tstack_p->node;
-			
-		// set the hit point for this plane
-			
-			frontx = backx;
-			fronty = backy;
-			frontz = backz;
-			
-		// go down the back side
-
-			backx = tstack_p->backpt[0];
-			backy = tstack_p->backpt[1];
-			backz = tstack_p->backpt[2];
-			
-			node = tnodes[tstack_p->node].children[!tstack_p->side];
-		}
-
-		tnode = &tnodes[node];
-		
-		switch (tnode->type)
-		{
-		case PLANE_X:
-			front = frontx - tnode->dist;
-			back = backx - tnode->dist;
-			break;
-		case PLANE_Y:
-			front = fronty - tnode->dist;
-			back = backy - tnode->dist;
-			break;
-		case PLANE_Z:
-			front = frontz - tnode->dist;
-			back = backz - tnode->dist;
-			break;
-		default:
-			front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist;
-			back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist;
-			break;
-		}
-
-		if (front > -ON_EPSILON && back > -ON_EPSILON)
-//		if (front > 0 && back > 0)
-		{
-			node = tnode->children[0];
-			continue;
-		}
-		
-		if (front < ON_EPSILON && back < ON_EPSILON)
-//		if (front <= 0 && back <= 0)
-		{
-			node = tnode->children[1];
-			continue;
-		}
-
-		side = front < 0;
-		
-		front = front / (front-back);
-	
-		tstack_p->node = node;
-		tstack_p->side = side;
-		tstack_p->backpt[0] = backx;
-		tstack_p->backpt[1] = backy;
-		tstack_p->backpt[2] = backz;
-		
-		tstack_p++;
-		
-		backx = frontx + front*(backx-frontx);
-		backy = fronty + front*(backy-fronty);
-		backz = frontz + front*(backz-frontz);
-		
-		node = tnode->children[side];		
-	}	
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+// trace.c
+/*
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "bspfile.h"
+*/
+
+#include "qrad.h"
+
+#define	ON_EPSILON	0.1
+
+typedef struct tnode_s
+{
+	int		type;
+	vec3_t	normal;
+	float	dist;
+	int		children[2];
+	int		pad;
+} tnode_t;
+
+tnode_t		*tnodes, *tnode_p;
+
+/*
+==============
+MakeTnode
+
+Converts the disk node structure into the efficient tracing structure
+==============
+*/
+void MakeTnode (int nodenum)
+{
+	tnode_t			*t;
+	dplane_t		*plane;
+	int				i;
+	dnode_t 		*node;
+	
+	t = tnode_p++;
+
+	node = dnodes + nodenum;
+	plane = dplanes + node->planenum;
+
+	t->type = plane->type;
+	VectorCopy (plane->normal, t->normal);
+	t->dist = plane->dist;
+	
+	for (i=0 ; i<2 ; i++)
+	{
+		if (node->children[i] < 0)
+			t->children[i] = (dleafs[-node->children[i] - 1].contents & CONTENTS_SOLID) | (1<<31);
+		else
+		{
+			t->children[i] = tnode_p - tnodes;
+			MakeTnode (node->children[i]);
+		}
+	}
+			
+}
+
+
+/*
+=============
+MakeTnodes
+
+Loads the node structure out of a .bsp file to be used for light occlusion
+=============
+*/
+void MakeTnodes (dmodel_t *bm)
+{
+	// 32 byte align the structs
+	tnodes = malloc( (numnodes+1) * sizeof(tnode_t));
+	tnodes = (tnode_t *)(((int)tnodes + 31)&~31);
+	tnode_p = tnodes;
+
+	MakeTnode (0);
+}
+
+
+//==========================================================
+
+
+int TestLine_r (int node, vec3_t start, vec3_t stop)
+{
+	tnode_t	*tnode;
+	float	front, back;
+	vec3_t	mid;
+	float	frac;
+	int		side;
+	int		r;
+
+	if (node & (1<<31))
+		return node & ~(1<<31);	// leaf node
+
+	tnode = &tnodes[node];
+	switch (tnode->type)
+	{
+	case PLANE_X:
+		front = start[0] - tnode->dist;
+		back = stop[0] - tnode->dist;
+		break;
+	case PLANE_Y:
+		front = start[1] - tnode->dist;
+		back = stop[1] - tnode->dist;
+		break;
+	case PLANE_Z:
+		front = start[2] - tnode->dist;
+		back = stop[2] - tnode->dist;
+		break;
+	default:
+		front = (start[0]*tnode->normal[0] + start[1]*tnode->normal[1] + start[2]*tnode->normal[2]) - tnode->dist;
+		back = (stop[0]*tnode->normal[0] + stop[1]*tnode->normal[1] + stop[2]*tnode->normal[2]) - tnode->dist;
+		break;
+	}
+
+	if (front >= -ON_EPSILON && back >= -ON_EPSILON)
+		return TestLine_r (tnode->children[0], start, stop);
+	
+	if (front < ON_EPSILON && back < ON_EPSILON)
+		return TestLine_r (tnode->children[1], start, stop);
+
+	side = front < 0;
+	
+	frac = front / (front-back);
+
+	mid[0] = start[0] + (stop[0] - start[0])*frac;
+	mid[1] = start[1] + (stop[1] - start[1])*frac;
+	mid[2] = start[2] + (stop[2] - start[2])*frac;
+
+	r = TestLine_r (tnode->children[side], start, mid);
+	if (r)
+		return r;
+	return TestLine_r (tnode->children[!side], mid, stop);
+}
+
+int TestLine (vec3_t start, vec3_t stop)
+{
+	return TestLine_r (0, start, stop);
+}
+
+/*
+==============================================================================
+
+LINE TRACING
+
+The major lighting operation is a point to point visibility test, performed
+by recursive subdivision of the line by the BSP tree.
+
+==============================================================================
+*/
+
+typedef struct
+{
+	vec3_t	backpt;
+	int		side;
+	int		node;
+} tracestack_t;
+
+
+/*
+==============
+TestLine
+==============
+*/
+qboolean _TestLine (vec3_t start, vec3_t stop)
+{
+	int				node;
+	float			front, back;
+	tracestack_t	*tstack_p;
+	int				side;
+	float 			frontx,fronty, frontz, backx, backy, backz;
+	tracestack_t	tracestack[64];
+	tnode_t			*tnode;
+	
+	frontx = start[0];
+	fronty = start[1];
+	frontz = start[2];
+	backx = stop[0];
+	backy = stop[1];
+	backz = stop[2];
+	
+	tstack_p = tracestack;
+	node = 0;
+	
+	while (1)
+	{
+		if (node == CONTENTS_SOLID)
+		{
+#if 0
+			float	d1, d2, d3;
+
+			d1 = backx - frontx;
+			d2 = backy - fronty;
+			d3 = backz - frontz;
+
+			if (d1*d1 + d2*d2 + d3*d3 > 1)
+#endif
+				return false;	// DONE!
+		}
+		
+		while (node < 0)
+		{
+		// pop up the stack for a back side
+			tstack_p--;
+			if (tstack_p < tracestack)
+				return true;
+			node = tstack_p->node;
+			
+		// set the hit point for this plane
+			
+			frontx = backx;
+			fronty = backy;
+			frontz = backz;
+			
+		// go down the back side
+
+			backx = tstack_p->backpt[0];
+			backy = tstack_p->backpt[1];
+			backz = tstack_p->backpt[2];
+			
+			node = tnodes[tstack_p->node].children[!tstack_p->side];
+		}
+
+		tnode = &tnodes[node];
+		
+		switch (tnode->type)
+		{
+		case PLANE_X:
+			front = frontx - tnode->dist;
+			back = backx - tnode->dist;
+			break;
+		case PLANE_Y:
+			front = fronty - tnode->dist;
+			back = backy - tnode->dist;
+			break;
+		case PLANE_Z:
+			front = frontz - tnode->dist;
+			back = backz - tnode->dist;
+			break;
+		default:
+			front = (frontx*tnode->normal[0] + fronty*tnode->normal[1] + frontz*tnode->normal[2]) - tnode->dist;
+			back = (backx*tnode->normal[0] + backy*tnode->normal[1] + backz*tnode->normal[2]) - tnode->dist;
+			break;
+		}
+
+		if (front > -ON_EPSILON && back > -ON_EPSILON)
+//		if (front > 0 && back > 0)
+		{
+			node = tnode->children[0];
+			continue;
+		}
+		
+		if (front < ON_EPSILON && back < ON_EPSILON)
+//		if (front <= 0 && back <= 0)
+		{
+			node = tnode->children[1];
+			continue;
+		}
+
+		side = front < 0;
+		
+		front = front / (front-back);
+	
+		tstack_p->node = node;
+		tstack_p->side = side;
+		tstack_p->backpt[0] = backx;
+		tstack_p->backpt[1] = backy;
+		tstack_p->backpt[2] = backz;
+		
+		tstack_p++;
+		
+		backx = frontx + front*(backx-frontx);
+		backy = fronty + front*(backy-fronty);
+		backz = frontz + front*(backz-frontz);
+		
+		node = tnode->children[side];		
+	}	
+}
+
+
diff --git a/tools/quake2/q2map/tree.c b/tools/quake2/q2map/tree.c
index ec5b5b7c..6ca4aa16 100644
--- a/tools/quake2/q2map/tree.c
+++ b/tools/quake2/q2map/tree.c
@@ -1,218 +1,218 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "qbsp.h"
-
-extern	int	c_nodes;
-
-void RemovePortalFromNode (portal_t *portal, node_t *l);
-
-node_t *NodeForPoint (node_t *node, vec3_t origin)
-{
-	plane_t	*plane;
-	vec_t	d;
-
-	while (node->planenum != PLANENUM_LEAF)
-	{
-		plane = &mapplanes[node->planenum];
-		d = DotProduct (origin, plane->normal) - plane->dist;
-		if (d >= 0)
-			node = node->children[0];
-		else
-			node = node->children[1];
-	}
-
-	return node;
-}
-
-
-
-/*
-=============
-FreeTreePortals_r
-=============
-*/
-void FreeTreePortals_r (node_t *node)
-{
-	portal_t	*p, *nextp;
-	int			s;
-
-	// free children
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		FreeTreePortals_r (node->children[0]);
-		FreeTreePortals_r (node->children[1]);
-	}
-
-	// free portals
-	for (p=node->portals ; p ; p=nextp)
-	{
-		s = (p->nodes[1] == node);
-		nextp = p->next[s];
-
-		RemovePortalFromNode (p, p->nodes[!s]);
-		FreePortal (p);
-	}
-	node->portals = NULL;
-}
-
-/*
-=============
-FreeTree_r
-=============
-*/
-void FreeTree_r (node_t *node)
-{
-	face_t		*f, *nextf;
-
-	// free children
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		FreeTree_r (node->children[0]);
-		FreeTree_r (node->children[1]);
-	}
-
-	// free bspbrushes
-	FreeBrushList (node->brushlist);
-
-	// free faces
-	for (f=node->faces ; f ; f=nextf)
-	{
-		nextf = f->next;
-		FreeFace (f);
-	}
-
-	// free the node
-	if (node->volume)
-		FreeBrush (node->volume);
-
-	if (numthreads == 1)
-		c_nodes--;
-	free (node);
-}
-
-
-/*
-=============
-FreeTree
-=============
-*/
-void FreeTree (tree_t *tree)
-{
-	FreeTreePortals_r (tree->headnode);
-	FreeTree_r (tree->headnode);
-	free (tree);
-}
-
-//===============================================================
-
-void PrintTree_r (node_t *node, int depth)
-{
-	int		i;
-	plane_t	*plane;
-	bspbrush_t	*bb;
-
-	for (i=0 ; i<depth ; i++)
-		Sys_Printf ("  ");
-	if (node->planenum == PLANENUM_LEAF)
-	{
-		if (!node->brushlist)
-			Sys_Printf ("NULL\n");
-		else
-		{
-			for (bb=node->brushlist ; bb ; bb=bb->next)
-				Sys_Printf ("%i ", bb->original->brushnum);
-			Sys_Printf ("\n");
-		}
-		return;
-	}
-
-	plane = &mapplanes[node->planenum];
-	Sys_Printf ("#%i (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum,
-		plane->normal[0], plane->normal[1], plane->normal[2],
-		plane->dist);
-	PrintTree_r (node->children[0], depth+1);
-	PrintTree_r (node->children[1], depth+1);
-}
-
-/*
-=========================================================
-
-NODES THAT DON'T SEPERATE DIFFERENT CONTENTS CAN BE PRUNED
-
-=========================================================
-*/
-
-int	c_pruned;
-
-/*
-============
-PruneNodes_r
-============
-*/
-void PruneNodes_r (node_t *node)
-{
-	bspbrush_t		*b, *next;
-
-	if (node->planenum == PLANENUM_LEAF)
-		return;
-	PruneNodes_r (node->children[0]);
-	PruneNodes_r (node->children[1]);
-
-	if ( (node->children[0]->contents & CONTENTS_SOLID)
-	&& (node->children[1]->contents & CONTENTS_SOLID) )
-	{
-		if (node->faces)
-			Error ("node->faces seperating CONTENTS_SOLID");
-		if (node->children[0]->faces || node->children[1]->faces)
-			Error ("!node->faces with children");
-
-		// FIXME: free stuff
-		node->planenum = PLANENUM_LEAF;
-		node->contents = CONTENTS_SOLID;
-		node->detail_seperator = false;
-
-		if (node->brushlist)
-			Error ("PruneNodes: node->brushlist");
-
-		// combine brush lists
-		node->brushlist = node->children[1]->brushlist;
-
-		for (b=node->children[0]->brushlist ; b ; b=next)
-		{
-			next = b->next;
-			b->next = node->brushlist;
-			node->brushlist = b;
-		}
-
-		c_pruned++;
-	}
-}
-
-
-void PruneNodes (node_t *node)
-{
-	Sys_FPrintf( SYS_VRB, "--- PruneNodes ---\n");
-	c_pruned = 0;
-	PruneNodes_r (node);
-	Sys_FPrintf( SYS_VRB, "%5i pruned nodes\n", c_pruned);
-}
-
-//===========================================================
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "qbsp.h"
+
+extern	int	c_nodes;
+
+void RemovePortalFromNode (portal_t *portal, node_t *l);
+
+node_t *NodeForPoint (node_t *node, vec3_t origin)
+{
+	plane_t	*plane;
+	vec_t	d;
+
+	while (node->planenum != PLANENUM_LEAF)
+	{
+		plane = &mapplanes[node->planenum];
+		d = DotProduct (origin, plane->normal) - plane->dist;
+		if (d >= 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+
+	return node;
+}
+
+
+
+/*
+=============
+FreeTreePortals_r
+=============
+*/
+void FreeTreePortals_r (node_t *node)
+{
+	portal_t	*p, *nextp;
+	int			s;
+
+	// free children
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		FreeTreePortals_r (node->children[0]);
+		FreeTreePortals_r (node->children[1]);
+	}
+
+	// free portals
+	for (p=node->portals ; p ; p=nextp)
+	{
+		s = (p->nodes[1] == node);
+		nextp = p->next[s];
+
+		RemovePortalFromNode (p, p->nodes[!s]);
+		FreePortal (p);
+	}
+	node->portals = NULL;
+}
+
+/*
+=============
+FreeTree_r
+=============
+*/
+void FreeTree_r (node_t *node)
+{
+	face_t		*f, *nextf;
+
+	// free children
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		FreeTree_r (node->children[0]);
+		FreeTree_r (node->children[1]);
+	}
+
+	// free bspbrushes
+	FreeBrushList (node->brushlist);
+
+	// free faces
+	for (f=node->faces ; f ; f=nextf)
+	{
+		nextf = f->next;
+		FreeFace (f);
+	}
+
+	// free the node
+	if (node->volume)
+		FreeBrush (node->volume);
+
+	if (numthreads == 1)
+		c_nodes--;
+	free (node);
+}
+
+
+/*
+=============
+FreeTree
+=============
+*/
+void FreeTree (tree_t *tree)
+{
+	FreeTreePortals_r (tree->headnode);
+	FreeTree_r (tree->headnode);
+	free (tree);
+}
+
+//===============================================================
+
+void PrintTree_r (node_t *node, int depth)
+{
+	int		i;
+	plane_t	*plane;
+	bspbrush_t	*bb;
+
+	for (i=0 ; i<depth ; i++)
+		Sys_Printf ("  ");
+	if (node->planenum == PLANENUM_LEAF)
+	{
+		if (!node->brushlist)
+			Sys_Printf ("NULL\n");
+		else
+		{
+			for (bb=node->brushlist ; bb ; bb=bb->next)
+				Sys_Printf ("%i ", bb->original->brushnum);
+			Sys_Printf ("\n");
+		}
+		return;
+	}
+
+	plane = &mapplanes[node->planenum];
+	Sys_Printf ("#%i (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum,
+		plane->normal[0], plane->normal[1], plane->normal[2],
+		plane->dist);
+	PrintTree_r (node->children[0], depth+1);
+	PrintTree_r (node->children[1], depth+1);
+}
+
+/*
+=========================================================
+
+NODES THAT DON'T SEPERATE DIFFERENT CONTENTS CAN BE PRUNED
+
+=========================================================
+*/
+
+int	c_pruned;
+
+/*
+============
+PruneNodes_r
+============
+*/
+void PruneNodes_r (node_t *node)
+{
+	bspbrush_t		*b, *next;
+
+	if (node->planenum == PLANENUM_LEAF)
+		return;
+	PruneNodes_r (node->children[0]);
+	PruneNodes_r (node->children[1]);
+
+	if ( (node->children[0]->contents & CONTENTS_SOLID)
+	&& (node->children[1]->contents & CONTENTS_SOLID) )
+	{
+		if (node->faces)
+			Error ("node->faces seperating CONTENTS_SOLID");
+		if (node->children[0]->faces || node->children[1]->faces)
+			Error ("!node->faces with children");
+
+		// FIXME: free stuff
+		node->planenum = PLANENUM_LEAF;
+		node->contents = CONTENTS_SOLID;
+		node->detail_seperator = false;
+
+		if (node->brushlist)
+			Error ("PruneNodes: node->brushlist");
+
+		// combine brush lists
+		node->brushlist = node->children[1]->brushlist;
+
+		for (b=node->children[0]->brushlist ; b ; b=next)
+		{
+			next = b->next;
+			b->next = node->brushlist;
+			node->brushlist = b;
+		}
+
+		c_pruned++;
+	}
+}
+
+
+void PruneNodes (node_t *node)
+{
+	Sys_FPrintf( SYS_VRB, "--- PruneNodes ---\n");
+	c_pruned = 0;
+	PruneNodes_r (node);
+	Sys_FPrintf( SYS_VRB, "%5i pruned nodes\n", c_pruned);
+}
+
+//===========================================================
diff --git a/tools/quake2/q2map/writebsp.c b/tools/quake2/q2map/writebsp.c
index 083f0ea7..8c45d530 100644
--- a/tools/quake2/q2map/writebsp.c
+++ b/tools/quake2/q2map/writebsp.c
@@ -1,591 +1,591 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#include "qbsp.h"
-
-int		c_nofaces;
-int		c_facenodes;
-
-
-/*
-=========================================================
-
-ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES
-
-=========================================================
-*/
-
-int		planeused[MAX_MAP_PLANES];
-
-/*
-============
-EmitPlanes
-
-There is no oportunity to discard planes, because all of the original
-brushes will be saved in the map.
-============
-*/
-void EmitPlanes (void)
-{
-	int			i;
-	dplane_t	*dp;
-	plane_t		*mp;
-	int		planetranslate[MAX_MAP_PLANES];
-
-	mp = mapplanes;
-	for (i=0 ; i<nummapplanes ; i++, mp++)
-	{
-		dp = &dplanes[numplanes];
-		planetranslate[i] = numplanes;
-		VectorCopy ( mp->normal, dp->normal);
-		dp->dist = mp->dist;
-		dp->type = mp->type;
-		numplanes++;
-	}
-}
-
-
-//========================================================
-
-void EmitMarkFace (dleaf_t *leaf_p, face_t *f)
-{
-	int			i;
-	int			facenum;
-
-	while (f->merged)
-		f = f->merged;
-
-	if (f->split[0])
-	{
-		EmitMarkFace (leaf_p, f->split[0]);
-		EmitMarkFace (leaf_p, f->split[1]);
-		return;
-	}
-
-	facenum = f->outputnumber;
-	if (facenum == -1)
-		return;	// degenerate face
-
-	if (facenum < 0 || facenum >= numfaces)
-		Error ("Bad leafface");
-	for (i=leaf_p->firstleafface ; i<numleaffaces ; i++)
-		if (dleaffaces[i] == facenum)
-			break;		// merged out face
-	if (i == numleaffaces)
-	{
-		if (numleaffaces >= MAX_MAP_LEAFFACES)
-			Error ("MAX_MAP_LEAFFACES");
-
-		dleaffaces[numleaffaces] =  facenum;
-		numleaffaces++;
-	}
-
-}
-
-
-/*
-==================
-EmitLeaf
-==================
-*/
-void EmitLeaf (node_t *node)
-{
-	dleaf_t		*leaf_p;
-	portal_t	*p;
-	int			s;
-	face_t		*f;
-	bspbrush_t	*b;
-	int			i;
-	int			brushnum;
-
-	// emit a leaf
-	if (numleafs >= MAX_MAP_LEAFS)
-		Error ("MAX_MAP_LEAFS");
-
-	leaf_p = &dleafs[numleafs];
-	numleafs++;
-
-	leaf_p->contents = node->contents;
-	leaf_p->cluster = node->cluster;
-	leaf_p->area = node->area;
-
-	//
-	// write bounding box info
-	//	
-	VectorCopy ((short) node->mins, leaf_p->mins);
-	VectorCopy ((short) node->maxs, leaf_p->maxs);
-	
-	//
-	// write the leafbrushes
-	//
-	leaf_p->firstleafbrush = numleafbrushes;
-	for (b=node->brushlist ; b ; b=b->next)
-	{
-		if (numleafbrushes >= MAX_MAP_LEAFBRUSHES)
-			Error ("MAX_MAP_LEAFBRUSHES");
-
-		brushnum = b->original - mapbrushes;
-		for (i=leaf_p->firstleafbrush ; i<numleafbrushes ; i++)
-			if (dleafbrushes[i] == brushnum)
-				break;
-		if (i == numleafbrushes)
-		{
-			dleafbrushes[numleafbrushes] = brushnum;
-			numleafbrushes++;
-		}
-	}
-	leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
-
-	//
-	// write the leaffaces
-	//
-	if (leaf_p->contents & CONTENTS_SOLID)
-		return;		// no leaffaces in solids
-
-	leaf_p->firstleafface = numleaffaces;
-
-	for (p = node->portals ; p ; p = p->next[s])	
-	{
-		s = (p->nodes[1] == node);
-		f = p->face[s];
-		if (!f)
-			continue;	// not a visible portal
-
-		EmitMarkFace (leaf_p, f);
-	}
-	
-	leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
-}
-
-
-/*
-==================
-EmitFace
-==================
-*/
-void EmitFace (face_t *f)
-{
-	dface_t	*df;
-	int		i;
-	int		e;
-
-	f->outputnumber = -1;
-
-	if (f->numpoints < 3)
-	{
-		return;		// degenerated
-	}
-	if (f->merged || f->split[0] || f->split[1])
-	{
-		return;		// not a final face
-	}
-
-	// save output number so leaffaces can use
-	f->outputnumber = numfaces;
-
-	if (numfaces >= MAX_MAP_FACES)
-		Error ("numfaces == MAX_MAP_FACES");
-	df = &dfaces[numfaces];
-	numfaces++;
-
-	// planenum is used by qlight, but not quake
-	df->planenum = f->planenum & (~1);
-	df->side = f->planenum & 1;
-
-	df->firstedge = numsurfedges;
-	df->numedges = f->numpoints;
-	df->texinfo = f->texinfo;
-	for (i=0 ; i<f->numpoints ; i++)
-	{
-//		e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);
-		e = GetEdge2 (f->vertexnums[i], f->vertexnums[(i+1)%f->numpoints], f);
-		if (numsurfedges >= MAX_MAP_SURFEDGES)
-			Error ("numsurfedges == MAX_MAP_SURFEDGES");
-		dsurfedges[numsurfedges] = e;
-		numsurfedges++;
-	}
-}
-
-/*
-============
-EmitDrawingNode_r
-============
-*/
-int EmitDrawNode_r (node_t *node)
-{
-	dnode_t	*n;
-	face_t	*f;
-	int		i;
-
-	if (node->planenum == PLANENUM_LEAF)
-	{
-		EmitLeaf (node);
-		return -numleafs;
-	}
-
-	// emit a node	
-	if (numnodes == MAX_MAP_NODES)
-		Error ("MAX_MAP_NODES");
-	n = &dnodes[numnodes];
-	numnodes++;
-
-	VectorCopy ((short) node->mins, n->mins);
-	VectorCopy ((short) node->maxs, n->maxs);
-
-	planeused[node->planenum]++;
-	planeused[node->planenum^1]++;
-
-	if (node->planenum & 1)
-		Error ("WriteDrawNodes_r: odd planenum");
-	n->planenum = node->planenum;
-	n->firstface = numfaces;
-
-	if (!node->faces)
-		c_nofaces++;
-	else
-		c_facenodes++;
-
-	for (f=node->faces ; f ; f=f->next)
-		EmitFace (f);
-
-	n->numfaces = numfaces - n->firstface;
-
-
-	//
-	// recursively output the other nodes
-	//	
-	for (i=0 ; i<2 ; i++)
-	{
-		if (node->children[i]->planenum == PLANENUM_LEAF)
-		{
-			n->children[i] = -(numleafs + 1);
-			EmitLeaf (node->children[i]);
-		}
-		else
-		{
-			n->children[i] = numnodes;	
-			EmitDrawNode_r (node->children[i]);
-		}
-	}
-
-	return n - dnodes;
-}
-
-//=========================================================
-
-
-/*
-============
-WriteBSP
-============
-*/
-void WriteBSP (node_t *headnode)
-{
-	int		oldfaces;
-
-	c_nofaces = 0;
-	c_facenodes = 0;
-
-	Sys_FPrintf( SYS_VRB, "--- WriteBSP ---\n");
-
-	oldfaces = numfaces;
-	dmodels[nummodels].headnode = EmitDrawNode_r (headnode);
-	EmitAreaPortals (headnode);
-
-	Sys_FPrintf( SYS_VRB, "%5i nodes with faces\n", c_facenodes);
-	Sys_FPrintf( SYS_VRB, "%5i nodes without faces\n", c_nofaces);
-	Sys_FPrintf( SYS_VRB, "%5i faces\n", numfaces-oldfaces);
-}
-
-//===========================================================
-
-/*
-============
-SetModelNumbers
-============
-*/
-void SetModelNumbers (void)
-{
-	int		i;
-	int		models;
-	char	value[10];
-
-	models = 1;
-	for (i=1 ; i<num_entities ; i++)
-	{
-		if (entities[i].numbrushes)
-		{
-			sprintf (value, "*%i", models);
-			models++;
-			SetKeyValue (&entities[i], "model", value);
-		}
-	}
-
-}
-
-/*
-============
-SetLightStyles
-============
-*/
-#define	MAX_SWITCHED_LIGHTS	32
-void SetLightStyles (void)
-{
-	int		stylenum;
-	char	*t;
-	entity_t	*e;
-	int		i, j;
-	char	value[10];
-	char	lighttargets[MAX_SWITCHED_LIGHTS][64];
-
-
-	// any light that is controlled (has a targetname)
-	// must have a unique style number generated for it
-
-	stylenum = 0;
-	for (i=1 ; i<num_entities ; i++)
-	{
-		e = &entities[i];
-
-		t = ValueForKey (e, "classname");
-		if (Q_strncasecmp (t, "light", 5))
-			continue;
-		t = ValueForKey (e, "targetname");
-		if (!t[0])
-			continue;
-		
-		// find this targetname
-		for (j=0 ; j<stylenum ; j++)
-			if (!strcmp (lighttargets[j], t))
-				break;
-		if (j == stylenum)
-		{
-			if (stylenum == MAX_SWITCHED_LIGHTS)
-				Error ("stylenum == MAX_SWITCHED_LIGHTS");
-			strcpy (lighttargets[j], t);
-			stylenum++;
-		}
-		sprintf (value, "%i", 32 + j);
-		SetKeyValue (e, "style", value);
-	}
-
-}
-
-//===========================================================
-
-/*
-============
-EmitBrushes
-============
-*/
-void EmitBrushes (void)
-{
-	int			i, j, bnum, s, x;
-	dbrush_t	*db;
-	mapbrush_t		*b;
-	dbrushside_t	*cp;
-	vec3_t		normal;
-	vec_t		dist;
-	int			planenum;
-
-	numbrushsides = 0;
-	numbrushes = nummapbrushes;
-
-	for (bnum=0 ; bnum<nummapbrushes ; bnum++)
-	{
-		b = &mapbrushes[bnum];
-		db = &dbrushes[bnum];
-
-		db->contents = b->contents;
-		db->firstside = numbrushsides;
-		db->numsides = b->numsides;
-		for (j=0 ; j<b->numsides ; j++)
-		{
-			if (numbrushsides == MAX_MAP_BRUSHSIDES)
-				Error ("MAX_MAP_BRUSHSIDES");
-			cp = &dbrushsides[numbrushsides];
-			numbrushsides++;
-			cp->planenum = b->original_sides[j].planenum;
-			cp->texinfo = b->original_sides[j].texinfo;
-		}
-
-		// add any axis planes not contained in the brush to bevel off corners
-		for (x=0 ; x<3 ; x++)
-			for (s=-1 ; s<=1 ; s+=2)
-			{
-			// add the plane
-				VectorCopy (vec3_origin, normal);
-				normal[x] = (float) s;
-				if (s == -1)
-					dist = -b->mins[x];
-				else
-					dist = b->maxs[x];
-				planenum = FindFloatPlane (normal, dist);
-				for (i=0 ; i<b->numsides ; i++)
-					if (b->original_sides[i].planenum == planenum)
-						break;
-				if (i == b->numsides)
-				{
-					if (numbrushsides >= MAX_MAP_BRUSHSIDES)
-						Error ("MAX_MAP_BRUSHSIDES");
-
-					dbrushsides[numbrushsides].planenum = planenum;
-					dbrushsides[numbrushsides].texinfo =
-						dbrushsides[numbrushsides-1].texinfo;
-					numbrushsides++;
-					db->numsides++;
-				}
-			}
-
-	}
-
-}
-
-//===========================================================
-
-/*
-==================
-BeginBSPFile
-==================
-*/
-void BeginBSPFile (void)
-{
-	// these values may actually be initialized
-	// if the file existed when loaded, so clear them explicitly
-	nummodels = 0;
-	numfaces = 0;
-	numnodes = 0;
-	numbrushsides = 0;
-	numvertexes = 0;
-	numleaffaces = 0;
-	numleafbrushes = 0;
-	numsurfedges = 0;
-
-	// edge 0 is not used, because 0 can't be negated
-	numedges = 1;
-
-	// leave vertex 0 as an error
-	numvertexes = 1;
-
-	// leave leaf 0 as an error
-	numleafs = 1;
-	dleafs[0].contents = CONTENTS_SOLID;
-}
-
-
-/*
-============
-EndBSPFile
-============
-*/
-void EndBSPFile (void)
-{
-	char	path[1024];
-
-#if 0
-	int		len;
-	byte	*buf;
-#endif
-
-	EmitBrushes ();
-	EmitPlanes ();
-	UnparseEntities ();
-
-	// load the pop
-#if 0
-	sprintf (path, "%s/pics/pop.lmp", gamedir);
-	len = LoadFile (path, &buf);
-	memcpy (dpop, buf, sizeof(dpop));
-	free (buf);
-#endif
-
-	// write the map
-	sprintf (path, "%s.bsp", source);
-	Sys_Printf ("Writing %s\n", path);
-	WriteBSPFile (path);
-}
-
-
-/*
-==================
-BeginModel
-==================
-*/
-int	firstmodleaf;
-extern	int firstmodeledge;
-extern	int	firstmodelface;
-void BeginModel (void)
-{
-	dmodel_t	*mod;
-	int			start, end;
-	mapbrush_t	*b;
-	int			j;
-	entity_t	*e;
-	vec3_t		mins, maxs;
-
-	if (nummodels == MAX_MAP_MODELS)
-		Error ("MAX_MAP_MODELS");
-	mod = &dmodels[nummodels];
-
-	mod->firstface = numfaces;
-
-	firstmodleaf = numleafs;
-	firstmodeledge = numedges;
-	firstmodelface = numfaces;
-
-	//
-	// bound the brushes
-	//
-	e = &entities[entity_num];
-
-	start = e->firstbrush;
-	end = start + e->numbrushes;
-	ClearBounds (mins, maxs);
-
-	for (j=start ; j<end ; j++)
-	{
-		b = &mapbrushes[j];
-		if (!b->numsides)
-			continue;	// not a real brush (origin brush)
-		AddPointToBounds (b->mins, mins, maxs);
-		AddPointToBounds (b->maxs, mins, maxs);
-	}
-
-	VectorCopy (mins, mod->mins);
-	VectorCopy (maxs, mod->maxs);
-}
-
-
-/*
-==================
-EndModel
-==================
-*/
-void EndModel (void)
-{
-	dmodel_t	*mod;
-
-	mod = &dmodels[nummodels];
-
-	mod->numfaces = numfaces - mod->firstface;
-
-	nummodels++;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#include "qbsp.h"
+
+int		c_nofaces;
+int		c_facenodes;
+
+
+/*
+=========================================================
+
+ONLY SAVE OUT PLANES THAT ARE ACTUALLY USED AS NODES
+
+=========================================================
+*/
+
+int		planeused[MAX_MAP_PLANES];
+
+/*
+============
+EmitPlanes
+
+There is no oportunity to discard planes, because all of the original
+brushes will be saved in the map.
+============
+*/
+void EmitPlanes (void)
+{
+	int			i;
+	dplane_t	*dp;
+	plane_t		*mp;
+	int		planetranslate[MAX_MAP_PLANES];
+
+	mp = mapplanes;
+	for (i=0 ; i<nummapplanes ; i++, mp++)
+	{
+		dp = &dplanes[numplanes];
+		planetranslate[i] = numplanes;
+		VectorCopy ( mp->normal, dp->normal);
+		dp->dist = mp->dist;
+		dp->type = mp->type;
+		numplanes++;
+	}
+}
+
+
+//========================================================
+
+void EmitMarkFace (dleaf_t *leaf_p, face_t *f)
+{
+	int			i;
+	int			facenum;
+
+	while (f->merged)
+		f = f->merged;
+
+	if (f->split[0])
+	{
+		EmitMarkFace (leaf_p, f->split[0]);
+		EmitMarkFace (leaf_p, f->split[1]);
+		return;
+	}
+
+	facenum = f->outputnumber;
+	if (facenum == -1)
+		return;	// degenerate face
+
+	if (facenum < 0 || facenum >= numfaces)
+		Error ("Bad leafface");
+	for (i=leaf_p->firstleafface ; i<numleaffaces ; i++)
+		if (dleaffaces[i] == facenum)
+			break;		// merged out face
+	if (i == numleaffaces)
+	{
+		if (numleaffaces >= MAX_MAP_LEAFFACES)
+			Error ("MAX_MAP_LEAFFACES");
+
+		dleaffaces[numleaffaces] =  facenum;
+		numleaffaces++;
+	}
+
+}
+
+
+/*
+==================
+EmitLeaf
+==================
+*/
+void EmitLeaf (node_t *node)
+{
+	dleaf_t		*leaf_p;
+	portal_t	*p;
+	int			s;
+	face_t		*f;
+	bspbrush_t	*b;
+	int			i;
+	int			brushnum;
+
+	// emit a leaf
+	if (numleafs >= MAX_MAP_LEAFS)
+		Error ("MAX_MAP_LEAFS");
+
+	leaf_p = &dleafs[numleafs];
+	numleafs++;
+
+	leaf_p->contents = node->contents;
+	leaf_p->cluster = node->cluster;
+	leaf_p->area = node->area;
+
+	//
+	// write bounding box info
+	//	
+	VectorCopy ((short) node->mins, leaf_p->mins);
+	VectorCopy ((short) node->maxs, leaf_p->maxs);
+	
+	//
+	// write the leafbrushes
+	//
+	leaf_p->firstleafbrush = numleafbrushes;
+	for (b=node->brushlist ; b ; b=b->next)
+	{
+		if (numleafbrushes >= MAX_MAP_LEAFBRUSHES)
+			Error ("MAX_MAP_LEAFBRUSHES");
+
+		brushnum = b->original - mapbrushes;
+		for (i=leaf_p->firstleafbrush ; i<numleafbrushes ; i++)
+			if (dleafbrushes[i] == brushnum)
+				break;
+		if (i == numleafbrushes)
+		{
+			dleafbrushes[numleafbrushes] = brushnum;
+			numleafbrushes++;
+		}
+	}
+	leaf_p->numleafbrushes = numleafbrushes - leaf_p->firstleafbrush;
+
+	//
+	// write the leaffaces
+	//
+	if (leaf_p->contents & CONTENTS_SOLID)
+		return;		// no leaffaces in solids
+
+	leaf_p->firstleafface = numleaffaces;
+
+	for (p = node->portals ; p ; p = p->next[s])	
+	{
+		s = (p->nodes[1] == node);
+		f = p->face[s];
+		if (!f)
+			continue;	// not a visible portal
+
+		EmitMarkFace (leaf_p, f);
+	}
+	
+	leaf_p->numleaffaces = numleaffaces - leaf_p->firstleafface;
+}
+
+
+/*
+==================
+EmitFace
+==================
+*/
+void EmitFace (face_t *f)
+{
+	dface_t	*df;
+	int		i;
+	int		e;
+
+	f->outputnumber = -1;
+
+	if (f->numpoints < 3)
+	{
+		return;		// degenerated
+	}
+	if (f->merged || f->split[0] || f->split[1])
+	{
+		return;		// not a final face
+	}
+
+	// save output number so leaffaces can use
+	f->outputnumber = numfaces;
+
+	if (numfaces >= MAX_MAP_FACES)
+		Error ("numfaces == MAX_MAP_FACES");
+	df = &dfaces[numfaces];
+	numfaces++;
+
+	// planenum is used by qlight, but not quake
+	df->planenum = f->planenum & (~1);
+	df->side = f->planenum & 1;
+
+	df->firstedge = numsurfedges;
+	df->numedges = f->numpoints;
+	df->texinfo = f->texinfo;
+	for (i=0 ; i<f->numpoints ; i++)
+	{
+//		e = GetEdge (f->pts[i], f->pts[(i+1)%f->numpoints], f);
+		e = GetEdge2 (f->vertexnums[i], f->vertexnums[(i+1)%f->numpoints], f);
+		if (numsurfedges >= MAX_MAP_SURFEDGES)
+			Error ("numsurfedges == MAX_MAP_SURFEDGES");
+		dsurfedges[numsurfedges] = e;
+		numsurfedges++;
+	}
+}
+
+/*
+============
+EmitDrawingNode_r
+============
+*/
+int EmitDrawNode_r (node_t *node)
+{
+	dnode_t	*n;
+	face_t	*f;
+	int		i;
+
+	if (node->planenum == PLANENUM_LEAF)
+	{
+		EmitLeaf (node);
+		return -numleafs;
+	}
+
+	// emit a node	
+	if (numnodes == MAX_MAP_NODES)
+		Error ("MAX_MAP_NODES");
+	n = &dnodes[numnodes];
+	numnodes++;
+
+	VectorCopy ((short) node->mins, n->mins);
+	VectorCopy ((short) node->maxs, n->maxs);
+
+	planeused[node->planenum]++;
+	planeused[node->planenum^1]++;
+
+	if (node->planenum & 1)
+		Error ("WriteDrawNodes_r: odd planenum");
+	n->planenum = node->planenum;
+	n->firstface = numfaces;
+
+	if (!node->faces)
+		c_nofaces++;
+	else
+		c_facenodes++;
+
+	for (f=node->faces ; f ; f=f->next)
+		EmitFace (f);
+
+	n->numfaces = numfaces - n->firstface;
+
+
+	//
+	// recursively output the other nodes
+	//	
+	for (i=0 ; i<2 ; i++)
+	{
+		if (node->children[i]->planenum == PLANENUM_LEAF)
+		{
+			n->children[i] = -(numleafs + 1);
+			EmitLeaf (node->children[i]);
+		}
+		else
+		{
+			n->children[i] = numnodes;	
+			EmitDrawNode_r (node->children[i]);
+		}
+	}
+
+	return n - dnodes;
+}
+
+//=========================================================
+
+
+/*
+============
+WriteBSP
+============
+*/
+void WriteBSP (node_t *headnode)
+{
+	int		oldfaces;
+
+	c_nofaces = 0;
+	c_facenodes = 0;
+
+	Sys_FPrintf( SYS_VRB, "--- WriteBSP ---\n");
+
+	oldfaces = numfaces;
+	dmodels[nummodels].headnode = EmitDrawNode_r (headnode);
+	EmitAreaPortals (headnode);
+
+	Sys_FPrintf( SYS_VRB, "%5i nodes with faces\n", c_facenodes);
+	Sys_FPrintf( SYS_VRB, "%5i nodes without faces\n", c_nofaces);
+	Sys_FPrintf( SYS_VRB, "%5i faces\n", numfaces-oldfaces);
+}
+
+//===========================================================
+
+/*
+============
+SetModelNumbers
+============
+*/
+void SetModelNumbers (void)
+{
+	int		i;
+	int		models;
+	char	value[10];
+
+	models = 1;
+	for (i=1 ; i<num_entities ; i++)
+	{
+		if (entities[i].numbrushes)
+		{
+			sprintf (value, "*%i", models);
+			models++;
+			SetKeyValue (&entities[i], "model", value);
+		}
+	}
+
+}
+
+/*
+============
+SetLightStyles
+============
+*/
+#define	MAX_SWITCHED_LIGHTS	32
+void SetLightStyles (void)
+{
+	int		stylenum;
+	char	*t;
+	entity_t	*e;
+	int		i, j;
+	char	value[10];
+	char	lighttargets[MAX_SWITCHED_LIGHTS][64];
+
+
+	// any light that is controlled (has a targetname)
+	// must have a unique style number generated for it
+
+	stylenum = 0;
+	for (i=1 ; i<num_entities ; i++)
+	{
+		e = &entities[i];
+
+		t = ValueForKey (e, "classname");
+		if (Q_strncasecmp (t, "light", 5))
+			continue;
+		t = ValueForKey (e, "targetname");
+		if (!t[0])
+			continue;
+		
+		// find this targetname
+		for (j=0 ; j<stylenum ; j++)
+			if (!strcmp (lighttargets[j], t))
+				break;
+		if (j == stylenum)
+		{
+			if (stylenum == MAX_SWITCHED_LIGHTS)
+				Error ("stylenum == MAX_SWITCHED_LIGHTS");
+			strcpy (lighttargets[j], t);
+			stylenum++;
+		}
+		sprintf (value, "%i", 32 + j);
+		SetKeyValue (e, "style", value);
+	}
+
+}
+
+//===========================================================
+
+/*
+============
+EmitBrushes
+============
+*/
+void EmitBrushes (void)
+{
+	int			i, j, bnum, s, x;
+	dbrush_t	*db;
+	mapbrush_t		*b;
+	dbrushside_t	*cp;
+	vec3_t		normal;
+	vec_t		dist;
+	int			planenum;
+
+	numbrushsides = 0;
+	numbrushes = nummapbrushes;
+
+	for (bnum=0 ; bnum<nummapbrushes ; bnum++)
+	{
+		b = &mapbrushes[bnum];
+		db = &dbrushes[bnum];
+
+		db->contents = b->contents;
+		db->firstside = numbrushsides;
+		db->numsides = b->numsides;
+		for (j=0 ; j<b->numsides ; j++)
+		{
+			if (numbrushsides == MAX_MAP_BRUSHSIDES)
+				Error ("MAX_MAP_BRUSHSIDES");
+			cp = &dbrushsides[numbrushsides];
+			numbrushsides++;
+			cp->planenum = b->original_sides[j].planenum;
+			cp->texinfo = b->original_sides[j].texinfo;
+		}
+
+		// add any axis planes not contained in the brush to bevel off corners
+		for (x=0 ; x<3 ; x++)
+			for (s=-1 ; s<=1 ; s+=2)
+			{
+			// add the plane
+				VectorCopy (vec3_origin, normal);
+				normal[x] = (float) s;
+				if (s == -1)
+					dist = -b->mins[x];
+				else
+					dist = b->maxs[x];
+				planenum = FindFloatPlane (normal, dist);
+				for (i=0 ; i<b->numsides ; i++)
+					if (b->original_sides[i].planenum == planenum)
+						break;
+				if (i == b->numsides)
+				{
+					if (numbrushsides >= MAX_MAP_BRUSHSIDES)
+						Error ("MAX_MAP_BRUSHSIDES");
+
+					dbrushsides[numbrushsides].planenum = planenum;
+					dbrushsides[numbrushsides].texinfo =
+						dbrushsides[numbrushsides-1].texinfo;
+					numbrushsides++;
+					db->numsides++;
+				}
+			}
+
+	}
+
+}
+
+//===========================================================
+
+/*
+==================
+BeginBSPFile
+==================
+*/
+void BeginBSPFile (void)
+{
+	// these values may actually be initialized
+	// if the file existed when loaded, so clear them explicitly
+	nummodels = 0;
+	numfaces = 0;
+	numnodes = 0;
+	numbrushsides = 0;
+	numvertexes = 0;
+	numleaffaces = 0;
+	numleafbrushes = 0;
+	numsurfedges = 0;
+
+	// edge 0 is not used, because 0 can't be negated
+	numedges = 1;
+
+	// leave vertex 0 as an error
+	numvertexes = 1;
+
+	// leave leaf 0 as an error
+	numleafs = 1;
+	dleafs[0].contents = CONTENTS_SOLID;
+}
+
+
+/*
+============
+EndBSPFile
+============
+*/
+void EndBSPFile (void)
+{
+	char	path[1024];
+
+#if 0
+	int		len;
+	byte	*buf;
+#endif
+
+	EmitBrushes ();
+	EmitPlanes ();
+	UnparseEntities ();
+
+	// load the pop
+#if 0
+	sprintf (path, "%s/pics/pop.lmp", gamedir);
+	len = LoadFile (path, &buf);
+	memcpy (dpop, buf, sizeof(dpop));
+	free (buf);
+#endif
+
+	// write the map
+	sprintf (path, "%s.bsp", source);
+	Sys_Printf ("Writing %s\n", path);
+	WriteBSPFile (path);
+}
+
+
+/*
+==================
+BeginModel
+==================
+*/
+int	firstmodleaf;
+extern	int firstmodeledge;
+extern	int	firstmodelface;
+void BeginModel (void)
+{
+	dmodel_t	*mod;
+	int			start, end;
+	mapbrush_t	*b;
+	int			j;
+	entity_t	*e;
+	vec3_t		mins, maxs;
+
+	if (nummodels == MAX_MAP_MODELS)
+		Error ("MAX_MAP_MODELS");
+	mod = &dmodels[nummodels];
+
+	mod->firstface = numfaces;
+
+	firstmodleaf = numleafs;
+	firstmodeledge = numedges;
+	firstmodelface = numfaces;
+
+	//
+	// bound the brushes
+	//
+	e = &entities[entity_num];
+
+	start = e->firstbrush;
+	end = start + e->numbrushes;
+	ClearBounds (mins, maxs);
+
+	for (j=start ; j<end ; j++)
+	{
+		b = &mapbrushes[j];
+		if (!b->numsides)
+			continue;	// not a real brush (origin brush)
+		AddPointToBounds (b->mins, mins, maxs);
+		AddPointToBounds (b->maxs, mins, maxs);
+	}
+
+	VectorCopy (mins, mod->mins);
+	VectorCopy (maxs, mod->maxs);
+}
+
+
+/*
+==================
+EndModel
+==================
+*/
+void EndModel (void)
+{
+	dmodel_t	*mod;
+
+	mod = &dmodels[nummodels];
+
+	mod->numfaces = numfaces - mod->firstface;
+
+	nummodels++;
+}
+
diff --git a/tools/quake2/qdata/anorms.h b/tools/quake2/qdata/anorms.h
index caddaa0c..65170ad9 100644
--- a/tools/quake2/qdata/anorms.h
+++ b/tools/quake2/qdata/anorms.h
@@ -1,162 +1,162 @@
-	{ -0.525731f, 0.000000f, 0.850651f },
-	{ -0.442863f, 0.238856f, 0.864188f }, 
-	{ -0.295242f, 0.000000f, 0.955423f }, 
-	{ -0.309017f, 0.500000f, 0.809017f }, 
-	{ -0.162460f, 0.262866f, 0.951056f }, 
-	{ 0.000000f, 0.000000f, 1.000000f },
-	{ 0.000000f, 0.850651f, 0.525731f },
-	{ -0.147621f, 0.716567f, 0.681718f },
-	{ 0.147621f, 0.716567f, 0.681718f }, 
-	{ 0.000000f, 0.525731f, 0.850651f }, 
-	{ 0.309017f, 0.500000f, 0.809017f }, 
-	{ 0.525731f, 0.000000f, 0.850651f }, 
-	{ 0.295242f, 0.000000f, 0.955423f }, 
-	{ 0.442863f, 0.238856f, 0.864188f }, 
-	{ 0.162460f, 0.262866f, 0.951056f }, 
-	{ -0.681718f, 0.147621f, 0.716567f }, 
-	{ -0.809017f, 0.309017f, 0.500000f }, 
-	{ -0.587785f, 0.425325f, 0.688191f }, 
-	{ -0.850651f, 0.525731f, 0.000000f }, 
-	{ -0.864188f, 0.442863f, 0.238856f }, 
-	{ -0.716567f, 0.681718f, 0.147621f }, 
-	{ -0.688191f, 0.587785f, 0.425325f }, 
-	{ -0.500000f, 0.809017f, 0.309017f }, 
-	{ -0.238856f, 0.864188f, 0.442863f }, 
-	{ -0.425325f, 0.688191f, 0.587785f }, 
-	{ -0.716567f, 0.681718f, -0.147621f }, 
-	{ -0.500000f, 0.809017f, -0.309017f }, 
-	{ -0.525731f, 0.850651f, 0.000000f }, 
-	{ 0.000000f, 0.850651f, -0.525731f }, 
-	{ -0.238856f, 0.864188f, -0.442863f }, 
-	{ 0.000000f, 0.955423f, -0.295242f }, 
-	{ -0.262866f, 0.951056f, -0.162460f }, 
-	{ 0.000000f, 1.000000f, 0.000000f }, 
-	{ 0.000000f, 0.955423f, 0.295242f }, 
-	{ -0.262866f, 0.951056f, 0.162460f }, 
-	{ 0.238856f, 0.864188f, 0.442863f }, 
-	{ 0.262866f, 0.951056f, 0.162460f }, 
-	{ 0.500000f, 0.809017f, 0.309017f }, 
-	{ 0.238856f, 0.864188f, -0.442863f }, 
-	{ 0.262866f, 0.951056f, -0.162460f }, 
-	{ 0.500000f, 0.809017f, -0.309017f }, 
-	{ 0.850651f, 0.525731f, 0.000000f }, 
-	{ 0.716567f, 0.681718f, 0.147621f }, 
-	{ 0.716567f, 0.681718f, -0.147621f }, 
-	{ 0.525731f, 0.850651f, 0.000000f }, 
-	{ 0.425325f, 0.688191f, 0.587785f }, 
-	{ 0.864188f, 0.442863f, 0.238856f }, 
-	{ 0.688191f, 0.587785f, 0.425325f }, 
-	{ 0.809017f, 0.309017f, 0.500000f }, 
-	{ 0.681718f, 0.147621f, 0.716567f }, 
-	{ 0.587785f, 0.425325f, 0.688191f }, 
-	{ 0.955423f, 0.295242f, 0.000000f }, 
-	{ 1.000000f, 0.000000f, 0.000000f }, 
-	{ 0.951056f, 0.162460f, 0.262866f }, 
-	{ 0.850651f, -0.525731f, 0.000000f }, 
-	{ 0.955423f, -0.295242f, 0.000000f }, 
-	{ 0.864188f, -0.442863f, 0.238856f }, 
-	{ 0.951056f, -0.162460f, 0.262866f }, 
-	{ 0.809017f, -0.309017f, 0.500000f }, 
-	{ 0.681718f, -0.147621f, 0.716567f }, 
-	{ 0.850651f, 0.000000f, 0.525731f }, 
-	{ 0.864188f, 0.442863f, -0.238856f }, 
-	{ 0.809017f, 0.309017f, -0.500000f }, 
-	{ 0.951056f, 0.162460f, -0.262866f }, 
-	{ 0.525731f, 0.000000f, -0.850651f }, 
-	{ 0.681718f, 0.147621f, -0.716567f }, 
-	{ 0.681718f, -0.147621f, -0.716567f }, 
-	{ 0.850651f, 0.000000f, -0.525731f }, 
-	{ 0.809017f, -0.309017f, -0.500000f }, 
-	{ 0.864188f, -0.442863f, -0.238856f }, 
-	{ 0.951056f, -0.162460f, -0.262866f }, 
-	{ 0.147621f, 0.716567f, -0.681718f }, 
-	{ 0.309017f, 0.500000f, -0.809017f }, 
-	{ 0.425325f, 0.688191f, -0.587785f }, 
-	{ 0.442863f, 0.238856f, -0.864188f }, 
-	{ 0.587785f, 0.425325f, -0.688191f }, 
-	{ 0.688191f, 0.587785f, -0.425325f }, 
-	{ -0.147621f, 0.716567f, -0.681718f }, 
-	{ -0.309017f, 0.500000f, -0.809017f }, 
-	{ 0.000000f, 0.525731f, -0.850651f }, 
-	{ -0.525731f, 0.000000f, -0.850651f }, 
-	{ -0.442863f, 0.238856f, -0.864188f }, 
-	{ -0.295242f, 0.000000f, -0.955423f }, 
-	{ -0.162460f, 0.262866f, -0.951056f }, 
-	{ 0.000000f, 0.000000f, -1.000000f }, 
-	{ 0.295242f, 0.000000f, -0.955423f }, 
-	{ 0.162460f, 0.262866f, -0.951056f }, 
-	{ -0.442863f, -0.238856f, -0.864188f }, 
-	{ -0.309017f, -0.500000f, -0.809017f }, 
-	{ -0.162460f, -0.262866f, -0.951056f }, 
-	{ 0.000000f, -0.850651f, -0.525731f }, 
-	{ -0.147621f, -0.716567f, -0.681718f }, 
-	{ 0.147621f, -0.716567f, -0.681718f }, 
-	{ 0.000000f, -0.525731f, -0.850651f }, 
-	{ 0.309017f, -0.500000f, -0.809017f }, 
-	{ 0.442863f, -0.238856f, -0.864188f }, 
-	{ 0.162460f, -0.262866f, -0.951056f }, 
-	{ 0.238856f, -0.864188f, -0.442863f }, 
-	{ 0.500000f, -0.809017f, -0.309017f }, 
-	{ 0.425325f, -0.688191f, -0.587785f }, 
-	{ 0.716567f, -0.681718f, -0.147621f }, 
-	{ 0.688191f, -0.587785f, -0.425325f }, 
-	{ 0.587785f, -0.425325f, -0.688191f }, 
-	{ 0.000000f, -0.955423f, -0.295242f }, 
-	{ 0.000000f, -1.000000f, 0.000000f }, 
-	{ 0.262866f, -0.951056f, -0.162460f }, 
-	{ 0.000000f, -0.850651f, 0.525731f }, 
-	{ 0.000000f, -0.955423f, 0.295242f }, 
-	{ 0.238856f, -0.864188f, 0.442863f }, 
-	{ 0.262866f, -0.951056f, 0.162460f }, 
-	{ 0.500000f, -0.809017f, 0.309017f }, 
-	{ 0.716567f, -0.681718f, 0.147621f }, 
-	{ 0.525731f, -0.850651f, 0.000000f }, 
-	{ -0.238856f, -0.864188f, -0.442863f }, 
-	{ -0.500000f, -0.809017f, -0.309017f }, 
-	{ -0.262866f, -0.951056f, -0.162460f }, 
-	{ -0.850651f, -0.525731f, 0.000000f }, 
-	{ -0.716567f, -0.681718f, -0.147621f }, 
-	{ -0.716567f, -0.681718f, 0.147621f }, 
-	{ -0.525731f, -0.850651f, 0.000000f }, 
-	{ -0.500000f, -0.809017f, 0.309017f }, 
-	{ -0.238856f, -0.864188f, 0.442863f }, 
-	{ -0.262866f, -0.951056f, 0.162460f }, 
-	{ -0.864188f, -0.442863f, 0.238856f }, 
-	{ -0.809017f, -0.309017f, 0.500000f }, 
-	{ -0.688191f, -0.587785f, 0.425325f }, 
-	{ -0.681718f, -0.147621f, 0.716567f }, 
-	{ -0.442863f, -0.238856f, 0.864188f }, 
-	{ -0.587785f, -0.425325f, 0.688191f }, 
-	{ -0.309017f, -0.500000f, 0.809017f }, 
-	{ -0.147621f, -0.716567f, 0.681718f }, 
-	{ -0.425325f, -0.688191f, 0.587785f }, 
-	{ -0.162460f, -0.262866f, 0.951056f }, 
-	{ 0.442863f, -0.238856f, 0.864188f }, 
-	{ 0.162460f, -0.262866f, 0.951056f }, 
-	{ 0.309017f, -0.500000f, 0.809017f }, 
-	{ 0.147621f, -0.716567f, 0.681718f }, 
-	{ 0.000000f, -0.525731f, 0.850651f }, 
-	{ 0.425325f, -0.688191f, 0.587785f }, 
-	{ 0.587785f, -0.425325f, 0.688191f }, 
-	{ 0.688191f, -0.587785f, 0.425325f }, 
-	{ -0.955423f, 0.295242f, 0.000000f }, 
-	{ -0.951056f, 0.162460f, 0.262866f }, 
-	{ -1.000000f, 0.000000f, 0.000000f }, 
-	{ -0.850651f, 0.000000f, 0.525731f }, 
-	{ -0.955423f, -0.295242f, 0.000000f }, 
-	{ -0.951056f, -0.162460f, 0.262866f }, 
-	{ -0.864188f, 0.442863f, -0.238856f }, 
-	{ -0.951056f, 0.162460f, -0.262866f }, 
-	{ -0.809017f, 0.309017f, -0.500000f }, 
-	{ -0.864188f, -0.442863f, -0.238856f },
-	{ -0.951056f, -0.162460f, -0.262866f }, 
-	{ -0.809017f, -0.309017f, -0.500000f }, 
-	{ -0.681718f, 0.147621f, -0.716567f }, 
-	{ -0.681718f, -0.147621f, -0.716567f }, 
-	{ -0.850651f, 0.000000f, -0.525731f }, 
-	{ -0.688191f, 0.587785f, -0.425325f }, 
-	{ -0.587785f, 0.425325f, -0.688191f }, 
-	{ -0.425325f, 0.688191f, -0.587785f }, 
-	{ -0.425325f, -0.688191f, -0.587785f }, 
-	{ -0.587785f, -0.425325f, -0.688191f }, 
-	{ -0.688191f, -0.587785f, -0.425325f }, 
+	{ -0.525731f, 0.000000f, 0.850651f },
+	{ -0.442863f, 0.238856f, 0.864188f }, 
+	{ -0.295242f, 0.000000f, 0.955423f }, 
+	{ -0.309017f, 0.500000f, 0.809017f }, 
+	{ -0.162460f, 0.262866f, 0.951056f }, 
+	{ 0.000000f, 0.000000f, 1.000000f },
+	{ 0.000000f, 0.850651f, 0.525731f },
+	{ -0.147621f, 0.716567f, 0.681718f },
+	{ 0.147621f, 0.716567f, 0.681718f }, 
+	{ 0.000000f, 0.525731f, 0.850651f }, 
+	{ 0.309017f, 0.500000f, 0.809017f }, 
+	{ 0.525731f, 0.000000f, 0.850651f }, 
+	{ 0.295242f, 0.000000f, 0.955423f }, 
+	{ 0.442863f, 0.238856f, 0.864188f }, 
+	{ 0.162460f, 0.262866f, 0.951056f }, 
+	{ -0.681718f, 0.147621f, 0.716567f }, 
+	{ -0.809017f, 0.309017f, 0.500000f }, 
+	{ -0.587785f, 0.425325f, 0.688191f }, 
+	{ -0.850651f, 0.525731f, 0.000000f }, 
+	{ -0.864188f, 0.442863f, 0.238856f }, 
+	{ -0.716567f, 0.681718f, 0.147621f }, 
+	{ -0.688191f, 0.587785f, 0.425325f }, 
+	{ -0.500000f, 0.809017f, 0.309017f }, 
+	{ -0.238856f, 0.864188f, 0.442863f }, 
+	{ -0.425325f, 0.688191f, 0.587785f }, 
+	{ -0.716567f, 0.681718f, -0.147621f }, 
+	{ -0.500000f, 0.809017f, -0.309017f }, 
+	{ -0.525731f, 0.850651f, 0.000000f }, 
+	{ 0.000000f, 0.850651f, -0.525731f }, 
+	{ -0.238856f, 0.864188f, -0.442863f }, 
+	{ 0.000000f, 0.955423f, -0.295242f }, 
+	{ -0.262866f, 0.951056f, -0.162460f }, 
+	{ 0.000000f, 1.000000f, 0.000000f }, 
+	{ 0.000000f, 0.955423f, 0.295242f }, 
+	{ -0.262866f, 0.951056f, 0.162460f }, 
+	{ 0.238856f, 0.864188f, 0.442863f }, 
+	{ 0.262866f, 0.951056f, 0.162460f }, 
+	{ 0.500000f, 0.809017f, 0.309017f }, 
+	{ 0.238856f, 0.864188f, -0.442863f }, 
+	{ 0.262866f, 0.951056f, -0.162460f }, 
+	{ 0.500000f, 0.809017f, -0.309017f }, 
+	{ 0.850651f, 0.525731f, 0.000000f }, 
+	{ 0.716567f, 0.681718f, 0.147621f }, 
+	{ 0.716567f, 0.681718f, -0.147621f }, 
+	{ 0.525731f, 0.850651f, 0.000000f }, 
+	{ 0.425325f, 0.688191f, 0.587785f }, 
+	{ 0.864188f, 0.442863f, 0.238856f }, 
+	{ 0.688191f, 0.587785f, 0.425325f }, 
+	{ 0.809017f, 0.309017f, 0.500000f }, 
+	{ 0.681718f, 0.147621f, 0.716567f }, 
+	{ 0.587785f, 0.425325f, 0.688191f }, 
+	{ 0.955423f, 0.295242f, 0.000000f }, 
+	{ 1.000000f, 0.000000f, 0.000000f }, 
+	{ 0.951056f, 0.162460f, 0.262866f }, 
+	{ 0.850651f, -0.525731f, 0.000000f }, 
+	{ 0.955423f, -0.295242f, 0.000000f }, 
+	{ 0.864188f, -0.442863f, 0.238856f }, 
+	{ 0.951056f, -0.162460f, 0.262866f }, 
+	{ 0.809017f, -0.309017f, 0.500000f }, 
+	{ 0.681718f, -0.147621f, 0.716567f }, 
+	{ 0.850651f, 0.000000f, 0.525731f }, 
+	{ 0.864188f, 0.442863f, -0.238856f }, 
+	{ 0.809017f, 0.309017f, -0.500000f }, 
+	{ 0.951056f, 0.162460f, -0.262866f }, 
+	{ 0.525731f, 0.000000f, -0.850651f }, 
+	{ 0.681718f, 0.147621f, -0.716567f }, 
+	{ 0.681718f, -0.147621f, -0.716567f }, 
+	{ 0.850651f, 0.000000f, -0.525731f }, 
+	{ 0.809017f, -0.309017f, -0.500000f }, 
+	{ 0.864188f, -0.442863f, -0.238856f }, 
+	{ 0.951056f, -0.162460f, -0.262866f }, 
+	{ 0.147621f, 0.716567f, -0.681718f }, 
+	{ 0.309017f, 0.500000f, -0.809017f }, 
+	{ 0.425325f, 0.688191f, -0.587785f }, 
+	{ 0.442863f, 0.238856f, -0.864188f }, 
+	{ 0.587785f, 0.425325f, -0.688191f }, 
+	{ 0.688191f, 0.587785f, -0.425325f }, 
+	{ -0.147621f, 0.716567f, -0.681718f }, 
+	{ -0.309017f, 0.500000f, -0.809017f }, 
+	{ 0.000000f, 0.525731f, -0.850651f }, 
+	{ -0.525731f, 0.000000f, -0.850651f }, 
+	{ -0.442863f, 0.238856f, -0.864188f }, 
+	{ -0.295242f, 0.000000f, -0.955423f }, 
+	{ -0.162460f, 0.262866f, -0.951056f }, 
+	{ 0.000000f, 0.000000f, -1.000000f }, 
+	{ 0.295242f, 0.000000f, -0.955423f }, 
+	{ 0.162460f, 0.262866f, -0.951056f }, 
+	{ -0.442863f, -0.238856f, -0.864188f }, 
+	{ -0.309017f, -0.500000f, -0.809017f }, 
+	{ -0.162460f, -0.262866f, -0.951056f }, 
+	{ 0.000000f, -0.850651f, -0.525731f }, 
+	{ -0.147621f, -0.716567f, -0.681718f }, 
+	{ 0.147621f, -0.716567f, -0.681718f }, 
+	{ 0.000000f, -0.525731f, -0.850651f }, 
+	{ 0.309017f, -0.500000f, -0.809017f }, 
+	{ 0.442863f, -0.238856f, -0.864188f }, 
+	{ 0.162460f, -0.262866f, -0.951056f }, 
+	{ 0.238856f, -0.864188f, -0.442863f }, 
+	{ 0.500000f, -0.809017f, -0.309017f }, 
+	{ 0.425325f, -0.688191f, -0.587785f }, 
+	{ 0.716567f, -0.681718f, -0.147621f }, 
+	{ 0.688191f, -0.587785f, -0.425325f }, 
+	{ 0.587785f, -0.425325f, -0.688191f }, 
+	{ 0.000000f, -0.955423f, -0.295242f }, 
+	{ 0.000000f, -1.000000f, 0.000000f }, 
+	{ 0.262866f, -0.951056f, -0.162460f }, 
+	{ 0.000000f, -0.850651f, 0.525731f }, 
+	{ 0.000000f, -0.955423f, 0.295242f }, 
+	{ 0.238856f, -0.864188f, 0.442863f }, 
+	{ 0.262866f, -0.951056f, 0.162460f }, 
+	{ 0.500000f, -0.809017f, 0.309017f }, 
+	{ 0.716567f, -0.681718f, 0.147621f }, 
+	{ 0.525731f, -0.850651f, 0.000000f }, 
+	{ -0.238856f, -0.864188f, -0.442863f }, 
+	{ -0.500000f, -0.809017f, -0.309017f }, 
+	{ -0.262866f, -0.951056f, -0.162460f }, 
+	{ -0.850651f, -0.525731f, 0.000000f }, 
+	{ -0.716567f, -0.681718f, -0.147621f }, 
+	{ -0.716567f, -0.681718f, 0.147621f }, 
+	{ -0.525731f, -0.850651f, 0.000000f }, 
+	{ -0.500000f, -0.809017f, 0.309017f }, 
+	{ -0.238856f, -0.864188f, 0.442863f }, 
+	{ -0.262866f, -0.951056f, 0.162460f }, 
+	{ -0.864188f, -0.442863f, 0.238856f }, 
+	{ -0.809017f, -0.309017f, 0.500000f }, 
+	{ -0.688191f, -0.587785f, 0.425325f }, 
+	{ -0.681718f, -0.147621f, 0.716567f }, 
+	{ -0.442863f, -0.238856f, 0.864188f }, 
+	{ -0.587785f, -0.425325f, 0.688191f }, 
+	{ -0.309017f, -0.500000f, 0.809017f }, 
+	{ -0.147621f, -0.716567f, 0.681718f }, 
+	{ -0.425325f, -0.688191f, 0.587785f }, 
+	{ -0.162460f, -0.262866f, 0.951056f }, 
+	{ 0.442863f, -0.238856f, 0.864188f }, 
+	{ 0.162460f, -0.262866f, 0.951056f }, 
+	{ 0.309017f, -0.500000f, 0.809017f }, 
+	{ 0.147621f, -0.716567f, 0.681718f }, 
+	{ 0.000000f, -0.525731f, 0.850651f }, 
+	{ 0.425325f, -0.688191f, 0.587785f }, 
+	{ 0.587785f, -0.425325f, 0.688191f }, 
+	{ 0.688191f, -0.587785f, 0.425325f }, 
+	{ -0.955423f, 0.295242f, 0.000000f }, 
+	{ -0.951056f, 0.162460f, 0.262866f }, 
+	{ -1.000000f, 0.000000f, 0.000000f }, 
+	{ -0.850651f, 0.000000f, 0.525731f }, 
+	{ -0.955423f, -0.295242f, 0.000000f }, 
+	{ -0.951056f, -0.162460f, 0.262866f }, 
+	{ -0.864188f, 0.442863f, -0.238856f }, 
+	{ -0.951056f, 0.162460f, -0.262866f }, 
+	{ -0.809017f, 0.309017f, -0.500000f }, 
+	{ -0.864188f, -0.442863f, -0.238856f },
+	{ -0.951056f, -0.162460f, -0.262866f }, 
+	{ -0.809017f, -0.309017f, -0.500000f }, 
+	{ -0.681718f, 0.147621f, -0.716567f }, 
+	{ -0.681718f, -0.147621f, -0.716567f }, 
+	{ -0.850651f, 0.000000f, -0.525731f }, 
+	{ -0.688191f, 0.587785f, -0.425325f }, 
+	{ -0.587785f, 0.425325f, -0.688191f }, 
+	{ -0.425325f, 0.688191f, -0.587785f }, 
+	{ -0.425325f, -0.688191f, -0.587785f }, 
+	{ -0.587785f, -0.425325f, -0.688191f }, 
+	{ -0.688191f, -0.587785f, -0.425325f }, 
diff --git a/tools/quake2/qdata/images.c b/tools/quake2/qdata/images.c
index e3b8fc1b..37a2fc19 100644
--- a/tools/quake2/qdata/images.c
+++ b/tools/quake2/qdata/images.c
@@ -1,742 +1,742 @@
-#include "qdata.h"
-#include "inout.h"
-
-char		mip_prefix[1024];		// directory to dump the textures in
-
-qboolean	colormap_issued;
-byte		colormap_palette[768];
-
-/*
-==============
-RemapZero
-
-Replaces all 0 bytes in an image with the closest palette entry.
-This is because NT won't let us change index 0, so any palette
-animation leaves those pixels untouched.
-==============
-*/
-void RemapZero (byte *pixels, byte *palette, int width, int height)
-{
-	int		i, c;
-	int		alt_zero;
-	int		value, best;
-
-	alt_zero = 0;
-	best = 9999999;
-	for (i=1 ; i<255 ; i++)
-	{
-		value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
-		if (value < best)
-		{
-			best = value;
-			alt_zero = i;
-		}
-	}
-
-	c = width*height;
-	for (i=0 ; i<c ; i++)
-		if (pixels[i] == 0)
-			pixels[i] = alt_zero;
-}
-
-/*
-==============
-Cmd_Grab
-
-$grab filename x y width height
-==============
-*/
-void Cmd_Grab (void)
-{
-	int             xl,yl,w,h,y;
-	byte			*cropped;
-	char			savename[1024];
-	char			dest[1024];
-
-	GetToken (false);
-
-	if (token[0] == '/' || token[0] == '\\')
-		sprintf (savename, "%s%s.pcx", gamedir, token+1);
-	else
-		sprintf (savename, "%spics/%s.pcx", gamedir, token);
-
-	if (g_release)
-	{
-		if (token[0] == '/' || token[0] == '\\')
-			sprintf (dest, "%s.pcx", token+1);
-		else
-			sprintf (dest, "pics/%s.pcx", token);
-
-		ReleaseFile (dest);
-		return;
-	}
-
-	GetToken (false);
-	xl = atoi (token);
-	GetToken (false);
-	yl = atoi (token);
-	GetToken (false);
-	w = atoi (token);
-	GetToken (false);
-	h = atoi (token);
-
-	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
-		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
-
-	// crop it to the proper size
-	cropped = malloc (w*h);
-	for (y=0 ; y<h ; y++)
-	{
-		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, w,	h, lbmpalette);
-
-	free (cropped);
-}
-
-/*
-==============
-Cmd_Raw
-
-$grab filename x y width height
-==============
-*/
-void Cmd_Raw (void)
-{
-	int             xl,yl,w,h,y;
-	byte			*cropped;
-	char			savename[1024];
-	char			dest[1024];
-
-	GetToken (false);
-
-	sprintf (savename, "%s%s.lmp", gamedir, token);
-
-	if (g_release)
-	{
-		sprintf (dest, "%s.lmp", token);
-		ReleaseFile (dest);
-		return;
-	}
-
-	GetToken (false);
-	xl = atoi (token);
-	GetToken (false);
-	yl = atoi (token);
-	GetToken (false);
-	w = atoi (token);
-	GetToken (false);
-	h = atoi (token);
-
-	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
-		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
-
-	// crop it to the proper size
-	cropped = malloc (w*h);
-	for (y=0 ; y<h ; y++)
-	{
-		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-
-	SaveFile (savename, cropped, w*h);
-
-	free (cropped);
-}
-
-/*
-=============================================================================
-
-COLORMAP GRABBING
-
-=============================================================================
-*/
-
-/*
-===============
-BestColor
-===============
-*/
-byte BestColor (int r, int g, int b, int start, int stop)
-{
-	int	i;
-	int	dr, dg, db;
-	int	bestdistortion, distortion;
-	int	bestcolor;
-	byte	*pal;
-
-//
-// let any color go to 0 as a last resort
-//
-	bestdistortion = 256*256*4;
-	bestcolor = 0;
-
-	pal = colormap_palette + start*3;
-	for (i=start ; i<= stop ; i++)
-	{
-		dr = r - (int)pal[0];
-		dg = g - (int)pal[1];
-		db = b - (int)pal[2];
-		pal += 3;
-		distortion = dr*dr + dg*dg + db*db;
-		if (distortion < bestdistortion)
-		{
-			if (!distortion)
-				return i;		// perfect match
-
-			bestdistortion = distortion;
-			bestcolor = i;
-		}
-	}
-
-	return bestcolor;
-}
-
-
-/*
-==============
-Cmd_Colormap
-
-$colormap filename
-
-  the brightes colormap is first in the table (FIXME: reverse this now?)
-
-  64 rows of 256 : lightmaps
-  256 rows of 256 : translucency table
-==============
-*/
-void Cmd_Colormap (void)
-{
-	int		levels, brights;
-	int		l, c;
-	float	frac, red, green, blue;
-	float	range;
-	byte	*cropped, *lump_p;
-	char	savename[1024];
-	char	dest[1024];
-
-	colormap_issued = true;
-	if (!g_release)
-		memcpy (colormap_palette, lbmpalette, 768);
-
-	if (!TokenAvailable ())
-	{	// just setting colormap_issued
-		return;
-	}
-
-	GetToken (false);
-	sprintf (savename, "%spics/%s.pcx", gamedir, token);
-
-	if (g_release)
-	{
-		sprintf (dest, "pics/%s.pcx", token);
-		ReleaseFile (dest);
-		return;
-	}
-
-	range = 2;
-	levels = 64;
-	brights = 1;	// ignore 255 (transparent)
-
-	cropped = malloc((levels+256)*256);
-	lump_p = cropped;
-
-// shaded levels
-	for (l=0;l<levels;l++)
-	{
-		frac = range - range*(float)l/(levels-1);
-		for (c=0 ; c<256-brights ; c++)
-		{
-			red = lbmpalette[c*3];
-			green = lbmpalette[c*3+1];
-			blue = lbmpalette[c*3+2];
-
-			red = (int)(red*frac+0.5);
-			green = (int)(green*frac+0.5);
-			blue = (int)(blue*frac+0.5);
-			
-//
-// note: 254 instead of 255 because 255 is the transparent color, and we
-// don't want anything remapping to that
-// don't use color 0, because NT can't remap that (or 255)
-//
-			*lump_p++ = BestColor(red,green,blue, 1, 254);
-		}
-
-		// fullbrights allways stay the same
-		for ( ; c<256 ; c++)
-			*lump_p++ = c;
-	}
-	
-// 66% transparancy table
-	for (l=0;l<255;l++)
-	{
-		for (c=0 ; c<255 ; c++)
-		{
-			red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
-			green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
-			blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
-
-			*lump_p++ = BestColor(red,green,blue, 1, 254);
-		}
-		*lump_p++ = 255;
-	}
-	for (c=0 ; c<256 ; c++)
-		*lump_p++ = 255;
-	
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
-
-	free (cropped);
-}
-
-/*
-=============================================================================
-
-MIPTEX GRABBING
-
-=============================================================================
-*/
-
-byte	pixdata[256];
-
-int		d_red, d_green, d_blue;
-
-byte	palmap[32][32][32];
-qboolean	palmap_built;
-
-/*
-=============
-FindColor
-=============
-*/
-int FindColor (int r, int g, int b)
-{
-	int		bestcolor;
-
-	if (r > 255)
-		r = 255;
-	if (r < 0)
-		r = 0;
-	if (g > 255)
-		g = 255;
-	if (g < 0)
-		g = 0;
-	if (b > 255)
-		b = 255;
-	if (b < 0)
-		b = 0;
-#ifndef TABLECOLORS
-	bestcolor = BestColor (r, g, b, 0, 254);
-#else
-	bestcolor = palmap[r>>3][g>>3][b>>3];
-#endif
-
-	return bestcolor;
-}
-
-
-void BuildPalmap (void)
-{
-#ifdef TABLECOLORS
-	int		r, g, b;
-	int		bestcolor;
-
-	if (palmap_built)
-		return;
-	palmap_built = true;
-
-	for (r=4 ; r<256 ; r+=8)
-	{
-		for (g=4 ; g<256 ; g+=8)
-		{
-			for (b=4 ; b<256 ; b+=8)
-			{
-				bestcolor = BestColor (r, g, b, 1, 254);
-				palmap[r>>3][g>>3][b>>3] = bestcolor;
-			}
-		}
-	}
-#endif
-
-	if (!colormap_issued)
-		Error ("You must issue a $colormap command first");
-
-}
-
-/*
-=============
-AveragePixels
-=============
-*/
-byte AveragePixels (int count)
-{
-	int		r,g,b;
-	int		i;
-	int		vis;
-	int		pix;
-	int		bestcolor;
-	byte	*pal;
-	int		fullbright;
-	
-	vis = 0;
-	r = g = b = 0;
-	fullbright = 0;
-	for (i=0 ; i<count ; i++)
-	{
-		pix = pixdata[i];
-		
-		r += lbmpalette[pix*3];
-		g += lbmpalette[pix*3+1];
-		b += lbmpalette[pix*3+2];
-		vis++;
-	}
-		
-	r /= vis;
-	g /= vis;
-	b /= vis;
-
-	// error diffusion
-	r += d_red;
-	g += d_green;
-	b += d_blue;
-	
-//
-// find the best color
-//
-	bestcolor = FindColor (r, g, b);
-
-	// error diffusion
-	pal = colormap_palette + bestcolor*3;
-	d_red = r - (int)pal[0];
-	d_green = g - (int)pal[1];
-	d_blue = b - (int)pal[2];
-
-	return bestcolor;
-}
-
-
-typedef enum
-{
-	pt_contents,
-	pt_flags,
-	pt_animvalue,
-	pt_flagvalue
-} parmtype_t;
-
-typedef struct
-{
-	char	*name;
-	int		flags;
-	parmtype_t	type;
-} mipparm_t;
-
-mipparm_t	mipparms[] =
-{
-	// utility content attributes
-	{"water",	CONTENTS_WATER, pt_contents},
-	{"slime",	CONTENTS_SLIME, pt_contents},		// mildly damaging
-	{"lava",	CONTENTS_LAVA, pt_contents},		// very damaging
-	{"window",	CONTENTS_WINDOW, pt_contents},	// solid, but doesn't eat internal textures
-	{"mist",	CONTENTS_MIST, pt_contents},	// non-solid window
-	{"origin",	CONTENTS_ORIGIN, pt_contents},	// center of rotating brushes
-	{"playerclip",	CONTENTS_PLAYERCLIP, pt_contents},
-	{"monsterclip",	CONTENTS_MONSTERCLIP, pt_contents},
-
-	// utility surface attributes
-	{"hint",	SURF_HINT, pt_flags},
-	{"skip",	SURF_SKIP, pt_flags},
-	{"light",	SURF_LIGHT, pt_flagvalue},		// value is the light quantity
-
-	// texture chaining
-	{"anim",	0,			pt_animvalue},		// value is the next animation
-
-	// server attributes
-	{"slick",	SURF_SLICK, pt_flags},
-
-	// drawing attributes
-	{"sky",		SURF_SKY, pt_flags},
-	{"warping",	SURF_WARP, pt_flags},		// only valid with 64x64 textures
-	{"trans33",	SURF_TRANS33, pt_flags},	// translucent should allso set fullbright
-	{"trans66",	SURF_TRANS66, pt_flags},
-	{"flowing",	SURF_FLOWING, pt_flags},	// flow direction towards angle 0
-	{"nodraw",	SURF_NODRAW, pt_flags},	// for clip textures and trigger textures
-
-	{NULL, 0, pt_contents}
-};
-
-
-
-/*
-==============
-Cmd_Mip
-
-$mip filename x y width height <OPTIONS>
-must be multiples of sixteen
-SURF_WINDOW
-==============
-*/
-void Cmd_Mip (void)
-{
-	int             x,y,xl,yl,xh,yh,w,h;
-	byte            *screen_p, *source;
-	int             linedelta;
-	miptex_t		*qtex;
-	int				miplevel, mipstep;
-	int				xx, yy, pix;
-	int				count;
-	int				flags, value, contents;
-	mipparm_t		*mp;
-	char			lumpname[64];
-	byte			*lump_p;
-	char			filename[1024];
-	char			animname[64];
-
-	GetToken (false);
-	strcpy (lumpname, token);
-	
-	GetToken (false);
-	xl = atoi (token);
-	GetToken (false);
-	yl = atoi (token);
-	GetToken (false);
-	w = atoi (token);
-	GetToken (false);
-	h = atoi (token);
-
-	if ( (w & 15) || (h & 15) )
-		Error ("line %i: miptex sizes must be multiples of 16", scriptline);
-
-	flags = 0;
-	contents = 0;
-	value = 0;
-
-	animname[0] = 0;
-
-	// get optional flags and values
-	while (TokenAvailable ())
-	{
-		GetToken (false);
-	
-		for (mp=mipparms ; mp->name ; mp++)
-		{
-			if (!strcmp(mp->name, token))
-			{
-				switch (mp->type)
-				{
-				case pt_animvalue:
-					GetToken (false);	// specify the next animation frame
-					strcpy (animname, token);
-					break;
-				case pt_flags:
-					flags |= mp->flags;
-					break;
-				case pt_contents:
-					contents |= mp->flags;
-					break;
-				case pt_flagvalue:
-					flags |= mp->flags;
-					GetToken (false);	// specify the light value
-					value = atoi(token);
-					break;
-				}
-				break;
-			}
-		}
-		if (!mp->name)
-			Error ("line %i: unknown parm %s", scriptline, token);
-	}
-
-	sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname);
-	if (g_release)
-		return;	// textures are only released by $maps
-
-	xh = xl+w;
-	yh = yl+h;
-
-	qtex = malloc (sizeof(miptex_t) + w*h*2);
-	memset (qtex, 0, sizeof(miptex_t));
-
-	qtex->width = LittleLong(w);
-	qtex->height = LittleLong(h);
-	qtex->flags = LittleLong(flags);
-	qtex->contents = LittleLong(contents);
-	qtex->value = LittleLong(value);
-	sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
-	if (animname[0])
-		sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
-	
-	lump_p = (byte *)(&qtex->value+1);
-	
-	screen_p = byteimage + yl*byteimagewidth + xl;
-	linedelta = byteimagewidth - w;
-
-	source = lump_p;
-	qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);
-
-	for (y=yl ; y<yh ; y++)
-	{
-		for (x=xl ; x<xh ; x++)
-		{
-			pix = *screen_p++;
-			if (pix == 255)
-				pix = 1;		// should never happen
-			*lump_p++ = pix;
-		}
-		screen_p += linedelta;
-	}
-	
-//
-// subsample for greater mip levels
-//
-	d_red = d_green = d_blue = 0;	// no distortion yet
-
-	for (miplevel = 1 ; miplevel<4 ; miplevel++)
-	{
-		qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);
-		
-		mipstep = 1<<miplevel;
-		for (y=0 ; y<h ; y+=mipstep)
-		{
-
-			for (x = 0 ; x<w ; x+= mipstep)
-			{
-				count = 0;
-				for (yy=0 ; yy<mipstep ; yy++)
-					for (xx=0 ; xx<mipstep ; xx++)
-					{
-						pixdata[count] = source[ (y+yy)*w + x + xx ];
-						count++;
-					}
-				*lump_p++ = AveragePixels (count);
-			}	
-		}
-	}
-
-//
-// dword align the size
-//
-	while ((int)lump_p&3)
-		*lump_p++ = 0;
-
-//
-// write it out
-//
-	printf ("writing %s\n", filename);
-	SaveFile (filename, (byte *)qtex, lump_p - (byte *)qtex);
-
-	free (qtex);
-}
-
-/*
-===============
-Cmd_Mippal
-===============
-*/
-void Cmd_Mippal (void)
-{
-	colormap_issued = true;
-	if (g_release)
-		return;
-
-	memcpy (colormap_palette, lbmpalette, 768);
-
-	BuildPalmap();
-}
-
-
-/*
-===============
-Cmd_Mipdir
-===============
-*/
-void Cmd_Mipdir (void)
-{
-	char	filename[1024];
-
-	GetToken (false);
-	strcpy (mip_prefix, token);
-	// create the directory if needed
-	sprintf (filename, "%stextures", gamedir, mip_prefix);
-	Q_mkdir (filename); 
-	sprintf (filename, "%stextures/%s", gamedir, mip_prefix);
-	Q_mkdir (filename); 
-}
-
-
-/*
-=============================================================================
-
-ENVIRONMENT MAP GRABBING
-
-Creates six pcx files from tga files without any palette edge seams
-also copies the tga files for GL rendering.
-=============================================================================
-*/
-
-// 3dstudio environment map suffixes
-char	*suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
-
-/*
-=================
-Cmd_Environment
-=================
-*/
-void Cmd_Environment (void)
-{
-	char	name[1024];
-	int		i, x, y;
-	byte	image[256*256];
-	byte	*tga;
-
-	GetToken (false);
-
-	if (g_release)
-	{
-		for (i=0 ; i<6 ; i++)
-		{
-			sprintf (name, "env/%s%s.pcx", token, suf[i]);
-			ReleaseFile (name);
-			sprintf (name, "env/%s%s.tga", token, suf[i]);
-			ReleaseFile (name);
-		}
-		return;
-	}
-	// get the palette
-	BuildPalmap ();
-
-	sprintf (name, "%senv/", gamedir);
-	CreatePath (name);
-
-	// convert the images
-	for (i=0 ; i<6 ; i++)
-	{
-		sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
-		printf ("loading %s...\n", name);
-		LoadTGA (name, &tga, NULL, NULL);
-
-		for (y=0 ; y<256 ; y++)
-		{
-			for (x=0 ; x<256 ; x++)
-			{
-				image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
-			}
-		}
-		free (tga);
-		sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
-		if (FileTime (name) != -1)
-			printf ("%s already exists, not overwriting.\n", name);
-		else
-			WritePCXfile (name, image, 256, 256, colormap_palette);
-	}
-}
-
+#include "qdata.h"
+#include "inout.h"
+
+char		mip_prefix[1024];		// directory to dump the textures in
+
+qboolean	colormap_issued;
+byte		colormap_palette[768];
+
+/*
+==============
+RemapZero
+
+Replaces all 0 bytes in an image with the closest palette entry.
+This is because NT won't let us change index 0, so any palette
+animation leaves those pixels untouched.
+==============
+*/
+void RemapZero (byte *pixels, byte *palette, int width, int height)
+{
+	int		i, c;
+	int		alt_zero;
+	int		value, best;
+
+	alt_zero = 0;
+	best = 9999999;
+	for (i=1 ; i<255 ; i++)
+	{
+		value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
+		if (value < best)
+		{
+			best = value;
+			alt_zero = i;
+		}
+	}
+
+	c = width*height;
+	for (i=0 ; i<c ; i++)
+		if (pixels[i] == 0)
+			pixels[i] = alt_zero;
+}
+
+/*
+==============
+Cmd_Grab
+
+$grab filename x y width height
+==============
+*/
+void Cmd_Grab (void)
+{
+	int             xl,yl,w,h,y;
+	byte			*cropped;
+	char			savename[1024];
+	char			dest[1024];
+
+	GetToken (false);
+
+	if (token[0] == '/' || token[0] == '\\')
+		sprintf (savename, "%s%s.pcx", gamedir, token+1);
+	else
+		sprintf (savename, "%spics/%s.pcx", gamedir, token);
+
+	if (g_release)
+	{
+		if (token[0] == '/' || token[0] == '\\')
+			sprintf (dest, "%s.pcx", token+1);
+		else
+			sprintf (dest, "pics/%s.pcx", token);
+
+		ReleaseFile (dest);
+		return;
+	}
+
+	GetToken (false);
+	xl = atoi (token);
+	GetToken (false);
+	yl = atoi (token);
+	GetToken (false);
+	w = atoi (token);
+	GetToken (false);
+	h = atoi (token);
+
+	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
+		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
+
+	// crop it to the proper size
+	cropped = malloc (w*h);
+	for (y=0 ; y<h ; y++)
+	{
+		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, w,	h, lbmpalette);
+
+	free (cropped);
+}
+
+/*
+==============
+Cmd_Raw
+
+$grab filename x y width height
+==============
+*/
+void Cmd_Raw (void)
+{
+	int             xl,yl,w,h,y;
+	byte			*cropped;
+	char			savename[1024];
+	char			dest[1024];
+
+	GetToken (false);
+
+	sprintf (savename, "%s%s.lmp", gamedir, token);
+
+	if (g_release)
+	{
+		sprintf (dest, "%s.lmp", token);
+		ReleaseFile (dest);
+		return;
+	}
+
+	GetToken (false);
+	xl = atoi (token);
+	GetToken (false);
+	yl = atoi (token);
+	GetToken (false);
+	w = atoi (token);
+	GetToken (false);
+	h = atoi (token);
+
+	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
+		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
+
+	// crop it to the proper size
+	cropped = malloc (w*h);
+	for (y=0 ; y<h ; y++)
+	{
+		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+
+	SaveFile (savename, cropped, w*h);
+
+	free (cropped);
+}
+
+/*
+=============================================================================
+
+COLORMAP GRABBING
+
+=============================================================================
+*/
+
+/*
+===============
+BestColor
+===============
+*/
+byte BestColor (int r, int g, int b, int start, int stop)
+{
+	int	i;
+	int	dr, dg, db;
+	int	bestdistortion, distortion;
+	int	bestcolor;
+	byte	*pal;
+
+//
+// let any color go to 0 as a last resort
+//
+	bestdistortion = 256*256*4;
+	bestcolor = 0;
+
+	pal = colormap_palette + start*3;
+	for (i=start ; i<= stop ; i++)
+	{
+		dr = r - (int)pal[0];
+		dg = g - (int)pal[1];
+		db = b - (int)pal[2];
+		pal += 3;
+		distortion = dr*dr + dg*dg + db*db;
+		if (distortion < bestdistortion)
+		{
+			if (!distortion)
+				return i;		// perfect match
+
+			bestdistortion = distortion;
+			bestcolor = i;
+		}
+	}
+
+	return bestcolor;
+}
+
+
+/*
+==============
+Cmd_Colormap
+
+$colormap filename
+
+  the brightes colormap is first in the table (FIXME: reverse this now?)
+
+  64 rows of 256 : lightmaps
+  256 rows of 256 : translucency table
+==============
+*/
+void Cmd_Colormap (void)
+{
+	int		levels, brights;
+	int		l, c;
+	float	frac, red, green, blue;
+	float	range;
+	byte	*cropped, *lump_p;
+	char	savename[1024];
+	char	dest[1024];
+
+	colormap_issued = true;
+	if (!g_release)
+		memcpy (colormap_palette, lbmpalette, 768);
+
+	if (!TokenAvailable ())
+	{	// just setting colormap_issued
+		return;
+	}
+
+	GetToken (false);
+	sprintf (savename, "%spics/%s.pcx", gamedir, token);
+
+	if (g_release)
+	{
+		sprintf (dest, "pics/%s.pcx", token);
+		ReleaseFile (dest);
+		return;
+	}
+
+	range = 2;
+	levels = 64;
+	brights = 1;	// ignore 255 (transparent)
+
+	cropped = malloc((levels+256)*256);
+	lump_p = cropped;
+
+// shaded levels
+	for (l=0;l<levels;l++)
+	{
+		frac = range - range*(float)l/(levels-1);
+		for (c=0 ; c<256-brights ; c++)
+		{
+			red = lbmpalette[c*3];
+			green = lbmpalette[c*3+1];
+			blue = lbmpalette[c*3+2];
+
+			red = (int)(red*frac+0.5);
+			green = (int)(green*frac+0.5);
+			blue = (int)(blue*frac+0.5);
+			
+//
+// note: 254 instead of 255 because 255 is the transparent color, and we
+// don't want anything remapping to that
+// don't use color 0, because NT can't remap that (or 255)
+//
+			*lump_p++ = BestColor(red,green,blue, 1, 254);
+		}
+
+		// fullbrights allways stay the same
+		for ( ; c<256 ; c++)
+			*lump_p++ = c;
+	}
+	
+// 66% transparancy table
+	for (l=0;l<255;l++)
+	{
+		for (c=0 ; c<255 ; c++)
+		{
+			red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
+			green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
+			blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
+
+			*lump_p++ = BestColor(red,green,blue, 1, 254);
+		}
+		*lump_p++ = 255;
+	}
+	for (c=0 ; c<256 ; c++)
+		*lump_p++ = 255;
+	
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
+
+	free (cropped);
+}
+
+/*
+=============================================================================
+
+MIPTEX GRABBING
+
+=============================================================================
+*/
+
+byte	pixdata[256];
+
+int		d_red, d_green, d_blue;
+
+byte	palmap[32][32][32];
+qboolean	palmap_built;
+
+/*
+=============
+FindColor
+=============
+*/
+int FindColor (int r, int g, int b)
+{
+	int		bestcolor;
+
+	if (r > 255)
+		r = 255;
+	if (r < 0)
+		r = 0;
+	if (g > 255)
+		g = 255;
+	if (g < 0)
+		g = 0;
+	if (b > 255)
+		b = 255;
+	if (b < 0)
+		b = 0;
+#ifndef TABLECOLORS
+	bestcolor = BestColor (r, g, b, 0, 254);
+#else
+	bestcolor = palmap[r>>3][g>>3][b>>3];
+#endif
+
+	return bestcolor;
+}
+
+
+void BuildPalmap (void)
+{
+#ifdef TABLECOLORS
+	int		r, g, b;
+	int		bestcolor;
+
+	if (palmap_built)
+		return;
+	palmap_built = true;
+
+	for (r=4 ; r<256 ; r+=8)
+	{
+		for (g=4 ; g<256 ; g+=8)
+		{
+			for (b=4 ; b<256 ; b+=8)
+			{
+				bestcolor = BestColor (r, g, b, 1, 254);
+				palmap[r>>3][g>>3][b>>3] = bestcolor;
+			}
+		}
+	}
+#endif
+
+	if (!colormap_issued)
+		Error ("You must issue a $colormap command first");
+
+}
+
+/*
+=============
+AveragePixels
+=============
+*/
+byte AveragePixels (int count)
+{
+	int		r,g,b;
+	int		i;
+	int		vis;
+	int		pix;
+	int		bestcolor;
+	byte	*pal;
+	int		fullbright;
+	
+	vis = 0;
+	r = g = b = 0;
+	fullbright = 0;
+	for (i=0 ; i<count ; i++)
+	{
+		pix = pixdata[i];
+		
+		r += lbmpalette[pix*3];
+		g += lbmpalette[pix*3+1];
+		b += lbmpalette[pix*3+2];
+		vis++;
+	}
+		
+	r /= vis;
+	g /= vis;
+	b /= vis;
+
+	// error diffusion
+	r += d_red;
+	g += d_green;
+	b += d_blue;
+	
+//
+// find the best color
+//
+	bestcolor = FindColor (r, g, b);
+
+	// error diffusion
+	pal = colormap_palette + bestcolor*3;
+	d_red = r - (int)pal[0];
+	d_green = g - (int)pal[1];
+	d_blue = b - (int)pal[2];
+
+	return bestcolor;
+}
+
+
+typedef enum
+{
+	pt_contents,
+	pt_flags,
+	pt_animvalue,
+	pt_flagvalue
+} parmtype_t;
+
+typedef struct
+{
+	char	*name;
+	int		flags;
+	parmtype_t	type;
+} mipparm_t;
+
+mipparm_t	mipparms[] =
+{
+	// utility content attributes
+	{"water",	CONTENTS_WATER, pt_contents},
+	{"slime",	CONTENTS_SLIME, pt_contents},		// mildly damaging
+	{"lava",	CONTENTS_LAVA, pt_contents},		// very damaging
+	{"window",	CONTENTS_WINDOW, pt_contents},	// solid, but doesn't eat internal textures
+	{"mist",	CONTENTS_MIST, pt_contents},	// non-solid window
+	{"origin",	CONTENTS_ORIGIN, pt_contents},	// center of rotating brushes
+	{"playerclip",	CONTENTS_PLAYERCLIP, pt_contents},
+	{"monsterclip",	CONTENTS_MONSTERCLIP, pt_contents},
+
+	// utility surface attributes
+	{"hint",	SURF_HINT, pt_flags},
+	{"skip",	SURF_SKIP, pt_flags},
+	{"light",	SURF_LIGHT, pt_flagvalue},		// value is the light quantity
+
+	// texture chaining
+	{"anim",	0,			pt_animvalue},		// value is the next animation
+
+	// server attributes
+	{"slick",	SURF_SLICK, pt_flags},
+
+	// drawing attributes
+	{"sky",		SURF_SKY, pt_flags},
+	{"warping",	SURF_WARP, pt_flags},		// only valid with 64x64 textures
+	{"trans33",	SURF_TRANS33, pt_flags},	// translucent should allso set fullbright
+	{"trans66",	SURF_TRANS66, pt_flags},
+	{"flowing",	SURF_FLOWING, pt_flags},	// flow direction towards angle 0
+	{"nodraw",	SURF_NODRAW, pt_flags},	// for clip textures and trigger textures
+
+	{NULL, 0, pt_contents}
+};
+
+
+
+/*
+==============
+Cmd_Mip
+
+$mip filename x y width height <OPTIONS>
+must be multiples of sixteen
+SURF_WINDOW
+==============
+*/
+void Cmd_Mip (void)
+{
+	int             x,y,xl,yl,xh,yh,w,h;
+	byte            *screen_p, *source;
+	int             linedelta;
+	miptex_t		*qtex;
+	int				miplevel, mipstep;
+	int				xx, yy, pix;
+	int				count;
+	int				flags, value, contents;
+	mipparm_t		*mp;
+	char			lumpname[64];
+	byte			*lump_p;
+	char			filename[1024];
+	char			animname[64];
+
+	GetToken (false);
+	strcpy (lumpname, token);
+	
+	GetToken (false);
+	xl = atoi (token);
+	GetToken (false);
+	yl = atoi (token);
+	GetToken (false);
+	w = atoi (token);
+	GetToken (false);
+	h = atoi (token);
+
+	if ( (w & 15) || (h & 15) )
+		Error ("line %i: miptex sizes must be multiples of 16", scriptline);
+
+	flags = 0;
+	contents = 0;
+	value = 0;
+
+	animname[0] = 0;
+
+	// get optional flags and values
+	while (TokenAvailable ())
+	{
+		GetToken (false);
+	
+		for (mp=mipparms ; mp->name ; mp++)
+		{
+			if (!strcmp(mp->name, token))
+			{
+				switch (mp->type)
+				{
+				case pt_animvalue:
+					GetToken (false);	// specify the next animation frame
+					strcpy (animname, token);
+					break;
+				case pt_flags:
+					flags |= mp->flags;
+					break;
+				case pt_contents:
+					contents |= mp->flags;
+					break;
+				case pt_flagvalue:
+					flags |= mp->flags;
+					GetToken (false);	// specify the light value
+					value = atoi(token);
+					break;
+				}
+				break;
+			}
+		}
+		if (!mp->name)
+			Error ("line %i: unknown parm %s", scriptline, token);
+	}
+
+	sprintf (filename, "%stextures/%s/%s.wal", gamedir, mip_prefix, lumpname);
+	if (g_release)
+		return;	// textures are only released by $maps
+
+	xh = xl+w;
+	yh = yl+h;
+
+	qtex = malloc (sizeof(miptex_t) + w*h*2);
+	memset (qtex, 0, sizeof(miptex_t));
+
+	qtex->width = LittleLong(w);
+	qtex->height = LittleLong(h);
+	qtex->flags = LittleLong(flags);
+	qtex->contents = LittleLong(contents);
+	qtex->value = LittleLong(value);
+	sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
+	if (animname[0])
+		sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
+	
+	lump_p = (byte *)(&qtex->value+1);
+	
+	screen_p = byteimage + yl*byteimagewidth + xl;
+	linedelta = byteimagewidth - w;
+
+	source = lump_p;
+	qtex->offsets[0] = LittleLong(lump_p - (byte *)qtex);
+
+	for (y=yl ; y<yh ; y++)
+	{
+		for (x=xl ; x<xh ; x++)
+		{
+			pix = *screen_p++;
+			if (pix == 255)
+				pix = 1;		// should never happen
+			*lump_p++ = pix;
+		}
+		screen_p += linedelta;
+	}
+	
+//
+// subsample for greater mip levels
+//
+	d_red = d_green = d_blue = 0;	// no distortion yet
+
+	for (miplevel = 1 ; miplevel<4 ; miplevel++)
+	{
+		qtex->offsets[miplevel] = LittleLong(lump_p - (byte *)qtex);
+		
+		mipstep = 1<<miplevel;
+		for (y=0 ; y<h ; y+=mipstep)
+		{
+
+			for (x = 0 ; x<w ; x+= mipstep)
+			{
+				count = 0;
+				for (yy=0 ; yy<mipstep ; yy++)
+					for (xx=0 ; xx<mipstep ; xx++)
+					{
+						pixdata[count] = source[ (y+yy)*w + x + xx ];
+						count++;
+					}
+				*lump_p++ = AveragePixels (count);
+			}	
+		}
+	}
+
+//
+// dword align the size
+//
+	while ((int)lump_p&3)
+		*lump_p++ = 0;
+
+//
+// write it out
+//
+	printf ("writing %s\n", filename);
+	SaveFile (filename, (byte *)qtex, lump_p - (byte *)qtex);
+
+	free (qtex);
+}
+
+/*
+===============
+Cmd_Mippal
+===============
+*/
+void Cmd_Mippal (void)
+{
+	colormap_issued = true;
+	if (g_release)
+		return;
+
+	memcpy (colormap_palette, lbmpalette, 768);
+
+	BuildPalmap();
+}
+
+
+/*
+===============
+Cmd_Mipdir
+===============
+*/
+void Cmd_Mipdir (void)
+{
+	char	filename[1024];
+
+	GetToken (false);
+	strcpy (mip_prefix, token);
+	// create the directory if needed
+	sprintf (filename, "%stextures", gamedir, mip_prefix);
+	Q_mkdir (filename); 
+	sprintf (filename, "%stextures/%s", gamedir, mip_prefix);
+	Q_mkdir (filename); 
+}
+
+
+/*
+=============================================================================
+
+ENVIRONMENT MAP GRABBING
+
+Creates six pcx files from tga files without any palette edge seams
+also copies the tga files for GL rendering.
+=============================================================================
+*/
+
+// 3dstudio environment map suffixes
+char	*suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
+
+/*
+=================
+Cmd_Environment
+=================
+*/
+void Cmd_Environment (void)
+{
+	char	name[1024];
+	int		i, x, y;
+	byte	image[256*256];
+	byte	*tga;
+
+	GetToken (false);
+
+	if (g_release)
+	{
+		for (i=0 ; i<6 ; i++)
+		{
+			sprintf (name, "env/%s%s.pcx", token, suf[i]);
+			ReleaseFile (name);
+			sprintf (name, "env/%s%s.tga", token, suf[i]);
+			ReleaseFile (name);
+		}
+		return;
+	}
+	// get the palette
+	BuildPalmap ();
+
+	sprintf (name, "%senv/", gamedir);
+	CreatePath (name);
+
+	// convert the images
+	for (i=0 ; i<6 ; i++)
+	{
+		sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
+		printf ("loading %s...\n", name);
+		LoadTGA (name, &tga, NULL, NULL);
+
+		for (y=0 ; y<256 ; y++)
+		{
+			for (x=0 ; x<256 ; x++)
+			{
+				image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
+			}
+		}
+		free (tga);
+		sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
+		if (FileTime (name) != -1)
+			printf ("%s already exists, not overwriting.\n", name);
+		else
+			WritePCXfile (name, image, 256, 256, colormap_palette);
+	}
+}
+
diff --git a/tools/quake2/qdata/models.c b/tools/quake2/qdata/models.c
index 58fdc0ff..76713a5b 100644
--- a/tools/quake2/qdata/models.c
+++ b/tools/quake2/qdata/models.c
@@ -1,1132 +1,1132 @@
-
-#include "qdata.h"
-#include "inout.h"
-
-//=================================================================
-
-typedef struct 
-{
-	int		numnormals;
-	vec3_t	normalsum;
-} vertexnormals_t;
-
-typedef struct
-{
-	vec3_t		v;
-	int			lightnormalindex;
-} trivert_t;
-
-typedef struct
-{
-	vec3_t		mins, maxs;
-	char		name[16];
-	trivert_t	v[MAX_VERTS];
-} frame_t;
-
-//================================================================
-
-frame_t		g_frames[MAX_FRAMES];
-
-dmdl_t		model;
-
-
-float		scale_up;			// set by $scale
-vec3_t		adjust;				// set by $origin
-int			g_fixedwidth, g_fixedheight;	// set by $skinsize
-
-
-//
-// base frame info
-//
-vec3_t		base_xyz[MAX_VERTS];
-dstvert_t	base_st[MAX_VERTS];
-dtriangle_t	triangles[MAX_TRIANGLES];
-
-int			triangle_st[MAX_TRIANGLES][3][2];
-
-// the command list holds counts, s/t values, and xyz indexes
-// that are valid for every frame
-int			commands[16384];
-int			numcommands;
-int			numglverts;
-int			used[MAX_TRIANGLES];
-
-char		g_skins[MAX_MD2SKINS][64];
-
-char		cdarchive[1024];
-char		cdpartial[1024];
-char		cddir[1024];
-
-char		modelname[64];	// empty unless $modelname issued (players)
-
-#define NUMVERTEXNORMALS	162
-
-float	avertexnormals[NUMVERTEXNORMALS][3] = {
-#include "anorms.h"
-};
-
-FILE	*headerouthandle = NULL;
-
-//==============================================================
-
-/*
-===============
-ClearModel
-===============
-*/
-void ClearModel (void)
-{
-	memset (&model, 0, sizeof(model));
-
-	modelname[0] = 0;
-	scale_up = 1.0;	
-	VectorCopy (vec3_origin, adjust);
-	g_fixedwidth = g_fixedheight = 0;
-	g_skipmodel = false;
-}
-
-
-void H_printf(char *fmt, ...)
-{
-	va_list argptr;
-	char	name[1024];
-
-	if (!headerouthandle)
-	{
-		sprintf (name, "%s/tris.h", cddir);
-		headerouthandle = SafeOpenWrite (name);
-		fprintf(headerouthandle, "// %s\n\n", cddir);
-		fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n");
-	}
-
-	va_start (argptr, fmt);
-	vfprintf (headerouthandle, fmt, argptr);
-	va_end (argptr);
-}
-
-
-/*
-============
-WriteModelFile
-============
-*/
-void WriteModelFile (FILE *modelouthandle)
-{
-	int				i;
-	dmdl_t			modeltemp;
-	int				j, k;
-	frame_t			*in;
-	daliasframe_t	*out;
-	byte			buffer[MAX_VERTS*4+128];
-	float			v;
-	int				c_on, c_off;
-
-	model.ident = IDALIASHEADER;
-	model.version = ALIAS_VERSION;
-	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
-	model.num_glcmds = numcommands;
-	model.ofs_skins = sizeof(dmdl_t);
-	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
-	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
-	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
-	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
-	model.ofs_end = model.ofs_glcmds + model.num_glcmds*4;
-
-	//
-	// write out the model header
-	//
-	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
-		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
-
-	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
-
-	//
-	// write out the skin names
-	//
-	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
-
-	//
-	// write out the texture coordinates
-	//
-	c_on = c_off = 0;
-	for (i=0 ; i<model.num_st ; i++)
-	{
-		base_st[i].s = LittleShort (base_st[i].s);
-		base_st[i].t = LittleShort (base_st[i].t);
-	}
-
-	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
-
-	//
-	// write out the triangles
-	//
-	for (i=0 ; i<model.num_tris ; i++)
-	{
-		int			j;
-		dtriangle_t	tri;
-
-		for (j=0 ; j<3 ; j++)
-		{
-			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
-			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
-		}
-
-		SafeWrite (modelouthandle, &tri, sizeof(tri));
-	}
-
-	//
-	// write out the frames
-	//
-	for (i=0 ; i<model.num_frames ; i++)
-	{
-		in = &g_frames[i];
-		out = (daliasframe_t *)buffer;
-
-		strcpy (out->name, in->name);
-		for (j=0 ; j<3 ; j++)
-		{
-			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
-			out->translate[j] = in->mins[j];
-		}
-
-		for (j=0 ; j<model.num_xyz ; j++)
-		{
-		// all of these are byte values, so no need to deal with endianness
-			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
-
-			for (k=0 ; k<3 ; k++)
-			{
-			// scale to byte values & min/max check
-				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
-
-			// clamp, so rounding doesn't wrap from 255.6 to 0
-				if (v > 255.0)
-					v = 255.0;
-				if (v < 0)
-					v = 0;
-				out->verts[j].v[k] = v;
-			}
-		}
-
-		for (j=0 ; j<3 ; j++)
-		{
-			out->scale[j] = LittleFloat (out->scale[j]);
-			out->translate[j] = LittleFloat (out->translate[j]);
-		}
-
-		SafeWrite (modelouthandle, out, model.framesize);
-	}
-
-	//
-	// write out glcmds
-	//
-	SafeWrite (modelouthandle, commands, numcommands*4);
-}
-
-
-/*
-===============
-FinishModel
-===============
-*/
-void FinishModel (void)
-{
-	FILE		*modelouthandle;
-	int			i;
-	char		name[1024];
-	
-	if (!model.num_frames)
-		return;
-	
-//
-// copy to release directory tree if doing a release build
-//
-	if (g_release)
-	{
-		if (modelname[0])
-			sprintf (name, "%s", modelname);
-		else
-			sprintf (name, "%s/tris.md2", cdpartial);
-		ReleaseFile (name);
-
-		for (i=0 ; i<model.num_skins ; i++)
-		{
-			ReleaseFile (g_skins[i]);
-		}
-		model.num_frames = 0;
-		return;
-	}
-	
-//
-// write the model output file
-//
-	if (modelname[0])
-		sprintf (name, "%s%s", gamedir, modelname);
-	else
-		sprintf (name, "%s/tris.md2", cddir);
-	printf ("saving to %s\n", name);
-	CreatePath (name);
-	modelouthandle = SafeOpenWrite (name);
-
-	WriteModelFile (modelouthandle);
-	
-	printf ("%3dx%3d skin\n", model.skinwidth, model.skinheight);
-	printf ("%4d vertexes\n", model.num_xyz);
-	printf ("%4d triangles\n", model.num_tris);
-	printf ("%4d frame\n", model.num_frames);
-	printf ("%4d glverts\n", numglverts);
-	printf ("%4d glcmd\n", model.num_glcmds);
-	printf ("%4d skins\n", model.num_skins);
-	printf ("file size: %d\n", (int)ftell (modelouthandle) );
-	printf ("---------------------\n");
-	
-	fclose (modelouthandle);
-
-	// finish writing header file
-	H_printf("\n");
-
-	// scale_up is usefull to allow step distances to be adjusted
-	H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
-
-	fclose (headerouthandle);
-	headerouthandle = NULL;
-}
-
-
-/*
-=================================================================
-
-ALIAS MODEL DISPLAY LIST GENERATION
-
-=================================================================
-*/
-
-int		strip_xyz[128];
-int		strip_st[128];
-int		strip_tris[128];
-int		stripcount;
-
-/*
-================
-StripLength
-================
-*/
-int	StripLength (int starttri, int startv)
-{
-	int			m1, m2;
-	int			st1, st2;
-	int			j;
-	dtriangle_t	*last, *check;
-	int			k;
-
-	used[starttri] = 2;
-
-	last = &triangles[starttri];
-
-	strip_xyz[0] = last->index_xyz[(startv)%3];
-	strip_xyz[1] = last->index_xyz[(startv+1)%3];
-	strip_xyz[2] = last->index_xyz[(startv+2)%3];
-	strip_st[0] = last->index_st[(startv)%3];
-	strip_st[1] = last->index_st[(startv+1)%3];
-	strip_st[2] = last->index_st[(startv+2)%3];
-
-	strip_tris[0] = starttri;
-	stripcount = 1;
-
-	m1 = last->index_xyz[(startv+2)%3];
-	st1 = last->index_st[(startv+2)%3];
-	m2 = last->index_xyz[(startv+1)%3];
-	st2 = last->index_st[(startv+1)%3];
-
-	// look for a matching triangle
-nexttri:
-	for (j=starttri+1, check=&triangles[starttri+1]
-		; j<model.num_tris ; j++, check++)
-	{
-		for (k=0 ; k<3 ; k++)
-		{
-			if (check->index_xyz[k] != m1)
-				continue;
-			if (check->index_st[k] != st1)
-				continue;
-			if (check->index_xyz[ (k+1)%3 ] != m2)
-				continue;
-			if (check->index_st[ (k+1)%3 ] != st2)
-				continue;
-
-			// this is the next part of the fan
-
-			// if we can't use this triangle, this tristrip is done
-			if (used[j])
-				goto done;
-
-			// the new edge
-			if (stripcount & 1)
-			{
-				m2 = check->index_xyz[ (k+2)%3 ];
-				st2 = check->index_st[ (k+2)%3 ];
-			}
-			else
-			{
-				m1 = check->index_xyz[ (k+2)%3 ];
-				st1 = check->index_st[ (k+2)%3 ];
-			}
-
-			strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
-			strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
-			strip_tris[stripcount] = j;
-			stripcount++;
-
-			used[j] = 2;
-			goto nexttri;
-		}
-	}
-done:
-
-	// clear the temp used flags
-	for (j=starttri+1 ; j<model.num_tris ; j++)
-		if (used[j] == 2)
-			used[j] = 0;
-
-	return stripcount;
-}
-
-
-/*
-===========
-FanLength
-===========
-*/
-int	FanLength (int starttri, int startv)
-{
-	int		m1, m2;
-	int		st1, st2;
-	int		j;
-	dtriangle_t	*last, *check;
-	int		k;
-
-	used[starttri] = 2;
-
-	last = &triangles[starttri];
-
-	strip_xyz[0] = last->index_xyz[(startv)%3];
-	strip_xyz[1] = last->index_xyz[(startv+1)%3];
-	strip_xyz[2] = last->index_xyz[(startv+2)%3];
-	strip_st[0] = last->index_st[(startv)%3];
-	strip_st[1] = last->index_st[(startv+1)%3];
-	strip_st[2] = last->index_st[(startv+2)%3];
-
-	strip_tris[0] = starttri;
-	stripcount = 1;
-
-	m1 = last->index_xyz[(startv+0)%3];
-	st1 = last->index_st[(startv+0)%3];
-	m2 = last->index_xyz[(startv+2)%3];
-	st2 = last->index_st[(startv+2)%3];
-
-
-	// look for a matching triangle
-nexttri:
-	for (j=starttri+1, check=&triangles[starttri+1] 
-		; j<model.num_tris ; j++, check++)
-	{
-		for (k=0 ; k<3 ; k++)
-		{
-			if (check->index_xyz[k] != m1)
-				continue;
-			if (check->index_st[k] != st1)
-				continue;
-			if (check->index_xyz[ (k+1)%3 ] != m2)
-				continue;
-			if (check->index_st[ (k+1)%3 ] != st2)
-				continue;
-
-			// this is the next part of the fan
-
-			// if we can't use this triangle, this tristrip is done
-			if (used[j])
-				goto done;
-
-			// the new edge
-			m2 = check->index_xyz[ (k+2)%3 ];
-			st2 = check->index_st[ (k+2)%3 ];
-
-			strip_xyz[stripcount+2] = m2;
-			strip_st[stripcount+2] = st2;
-			strip_tris[stripcount] = j;
-			stripcount++;
-
-			used[j] = 2;
-			goto nexttri;
-		}
-	}
-done:
-
-	// clear the temp used flags
-	for (j=starttri+1 ; j<model.num_tris ; j++)
-		if (used[j] == 2)
-			used[j] = 0;
-
-	return stripcount;
-}
-
-
-
-/*
-================
-BuildGlCmds
-
-Generate a list of trifans or strips
-for the model, which holds for all frames
-================
-*/
-void BuildGlCmds (void)
-{
-	int		i, j, k;
-	int		startv;
-	float	s, t;
-	int		len, bestlen, besttype;
-	int		best_xyz[1024];
-	int		best_st[1024];
-	int		best_tris[1024];
-	int		type;
-
-	//
-	// build tristrips
-	//
-	numcommands = 0;
-	numglverts = 0;
-	memset (used, 0, sizeof(used));
-	for (i=0 ; i<model.num_tris ; i++)
-	{
-		// pick an unused triangle and start the trifan
-		if (used[i])
-			continue;
-
-		bestlen = 0;
-		for (type = 0 ; type < 2 ; type++)
-//	type = 1;
-		{
-			for (startv =0 ; startv < 3 ; startv++)
-			{
-				if (type == 1)
-					len = StripLength (i, startv);
-				else
-					len = FanLength (i, startv);
-				if (len > bestlen)
-				{
-					besttype = type;
-					bestlen = len;
-					for (j=0 ; j<bestlen+2 ; j++)
-					{
-						best_st[j] = strip_st[j];
-						best_xyz[j] = strip_xyz[j];
-					}
-					for (j=0 ; j<bestlen ; j++)
-						best_tris[j] = strip_tris[j];
-				}
-			}
-		}
-
-		// mark the tris on the best strip/fan as used
-		for (j=0 ; j<bestlen ; j++)
-			used[best_tris[j]] = 1;
-
-		if (besttype == 1)
-			commands[numcommands++] = (bestlen+2);
-		else
-			commands[numcommands++] = -(bestlen+2);
-
-		numglverts += bestlen+2;
-
-		for (j=0 ; j<bestlen+2 ; j++)
-		{
-			// emit a vertex into the reorder buffer
-			k = best_st[j];
-
-			// emit s/t coords into the commands stream
-			s = base_st[k].s;
-			t = base_st[k].t;
-
-			s = (s + 0.5) / model.skinwidth;
-			t = (t + 0.5) / model.skinheight;
-
-			*(float *)&commands[numcommands++] = s;
-			*(float *)&commands[numcommands++] = t;
-			*(int *)&commands[numcommands++] = best_xyz[j];
-		}
-	}
-
-	commands[numcommands++] = 0;		// end of list marker
-}
-
-
-/*
-===============================================================
-
-BASE FRAME SETUP
-
-===============================================================
-*/
-
-/*
-============
-BuildST
-
-Builds the triangle_st array for the base frame and
-model.skinwidth / model.skinheight
-
-  FIXME: allow this to be loaded from a file for
-  arbitrary mappings
-============
-*/
-void BuildST (triangle_t *ptri, int numtri)
-{
-	int			i, j;
-	int			width, height, iwidth, iheight, swidth;
-	float		basex, basey;
-	float		s_scale, t_scale;
-	float		scale;
-	vec3_t		mins, maxs;
-	float		*pbasevert;
-	vec3_t		vtemp1, vtemp2, normal;
-
-	//
-	// find bounds of all the verts on the base frame
-	//
-	ClearBounds (mins, maxs);
-	
-	for (i=0 ; i<numtri ; i++)
-		for (j=0 ; j<3 ; j++)
-			AddPointToBounds (ptri[i].verts[j], mins, maxs);
-	
-	for (i=0 ; i<3 ; i++)
-	{
-		mins[i] = floor(mins[i]);
-		maxs[i] = ceil(maxs[i]);
-	}
-	
-	width = maxs[0] - mins[0];
-	height = maxs[2] - mins[2];
-
-	if (!g_fixedwidth)
-	{	// old style
-		scale = 8;
-		if (width*scale >= 150)
-			scale = 150.0 / width;	
-		if (height*scale >= 190)
-			scale = 190.0 / height;
-
-		s_scale = t_scale = scale;
-
-		iwidth = ceil(width*s_scale);
-		iheight = ceil(height*t_scale);
-
-		iwidth += 4;
-		iheight += 4;
-	}
-	else
-	{	// new style
-		iwidth = g_fixedwidth / 2;
-		iheight = g_fixedheight;
-
-		s_scale = (float)(iwidth-4) / width;
-		t_scale = (float)(iheight-4) / height;
-	}
-
-//
-// determine which side of each triangle to map the texture to
-//
-	for (i=0 ; i<numtri ; i++)
-	{
-		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-		CrossProduct (vtemp1, vtemp2, normal);
-
-		if (normal[1] > 0)
-		{
-			basex = iwidth + 2;
-		}
-		else
-		{
-			basex = 2;
-		}
-		basey = 2;
-		
-		for (j=0 ; j<3 ; j++)
-		{
-			pbasevert = ptri[i].verts[j];
-
-			triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
-			triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
-		}
-	}
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-	swidth = iwidth*2;
-	model.skinwidth = (swidth + 3) & ~3;
-	model.skinheight = iheight;
-}
-
-
-/*
-=================
-Cmd_Base
-=================
-*/
-void Cmd_Base (void)
-{
-	triangle_t	*ptri;
-	int			i, j, k;
-	int		time1;
-	char	file1[1024];
-
-	GetToken (false);
-
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	printf ("---------------------\n");
-	sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
-	printf ("%s\n", file1);
-
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s.%s", cddir, token, trifileext);
-
-	time1 = FileTime (file1);
-	if (time1 == -1)
-		Error ("%s doesn't exist", file1);
-
-//
-// load the base triangles
-//
-	if (do3ds)
-		Load3DSTriangleList (file1, &ptri, &model.num_tris);
-	else
-		LoadTriangleList (file1, &ptri, &model.num_tris);
-
-//
-// get the ST values
-//
-	BuildST (ptri, model.num_tris);
-
-//
-// run through all the base triangles, storing each unique vertex in the
-// base vertex list and setting the indirect triangles to point to the base
-// vertices
-//
-	for (i=0 ; i<model.num_tris ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			// get the xyz index
-			for (k=0 ; k<model.num_xyz ; k++)
-				if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
-					break;	// this vertex is already in the base vertex list
-
-			if (k == model.num_xyz)
-			{ // new index
-				VectorCopy (ptri[i].verts[j], base_xyz[model.num_xyz]);
-				model.num_xyz++;
-			}
-
-			triangles[i].index_xyz[j] = k;
-
-			// get the st index
-			for (k=0 ; k<model.num_st ; k++)
-				if (triangle_st[i][j][0] == base_st[k].s
-				&& triangle_st[i][j][1] == base_st[k].t)
-					break;	// this vertex is already in the base vertex list
-
-			if (k == model.num_st)
-			{ // new index
-				base_st[model.num_st].s = triangle_st[i][j][0];
-				base_st[model.num_st].t = triangle_st[i][j][1];
-				model.num_st++;
-			}
-
-			triangles[i].index_st[j] = k;
-		}
-	}
-
-	// build triangle strips / fans
-	BuildGlCmds ();
-}
-
-//===============================================================
-
-char	*FindFrameFile (char *frame)
-{
-	int			time1;
-	char	file1[1024];
-	static char	retname[1024];
-	char	base[32];
-	char	suffix[32];
-	char	*s;
-
-	if (strstr (frame, "."))
-		return frame;		// allready in dot format
-
-	// split 'run1' into 'run' and '1'
-	s = frame + strlen(frame)-1;
-
-	while (s != frame && *s >= '0' && *s <= '9')
-		s--;
-
-	strcpy (suffix, s+1);
-	strcpy (base, frame);
-	base[s-frame+1] = 0;
-
-	// check for 'run1.tri'
-	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, trifileext);
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s%s.%s", base, suffix, trifileext);
-		return retname;
-	}
-
-	// check for 'run.1'
-	sprintf (file1, "%s/%s.%s",cddir, base, suffix);
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s.%s", base, suffix);
-		return retname;
-	}
-
-	Error ("frame %s could not be found",frame);
-	return NULL;
-}
-
-/*
-===============
-GrabFrame
-===============
-*/
-void GrabFrame (char *frame)
-{
-	triangle_t	*ptri;
-	int			i, j;
-	trivert_t	*ptrivert;
-	int			num_tris;
-	char		file1[1024];
-	frame_t		*fr;
-	vertexnormals_t	vnorms[MAX_VERTS];
-	int		index_xyz;
-	char	*framefile;
-
-	// the frame 'run1' will be looked for as either
-	// run.1 or run1.tri, so the new alias sequence save
-	// feature an be used
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-	printf ("grabbing %s\n", file1);
-
-	if (model.num_frames >= MAX_FRAMES)
-		Error ("model.num_frames >= MAX_FRAMES");
-	fr = &g_frames[model.num_frames];
-	model.num_frames++;
-
-	strcpy (fr->name, frame);
-
-//
-// load the frame
-//
-	if (do3ds)
-		Load3DSTriangleList (file1, &ptri, &num_tris);
-	else
-		LoadTriangleList (file1, &ptri, &num_tris);
-
-	if (num_tris != model.num_tris)
-		Error ("%s: number of triangles doesn't match base frame\n", file1);
-
-//
-// allocate storage for the frame's vertices
-//
-	ptrivert = fr->v;
-
-	for (i=0 ; i<model.num_xyz ; i++)
-	{
-		vnorms[i].numnormals = 0;
-		VectorClear (vnorms[i].normalsum);
-	}
-	ClearBounds (fr->mins, fr->maxs);
-
-//
-// store the frame's vertices in the same order as the base. This assumes the
-// triangles and vertices in this frame are in exactly the same order as in the
-// base
-//
-	for (i=0 ; i<num_tris ; i++)
-	{
-		vec3_t	vtemp1, vtemp2, normal;
-		float	ftemp;
-
-		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-		CrossProduct (vtemp1, vtemp2, normal);
-
-		VectorNormalize (normal, normal);
-
-	// rotate the normal so the model faces down the positive x axis
-		ftemp = normal[0];
-		normal[0] = -normal[1];
-		normal[1] = ftemp;
-
-		for (j=0 ; j<3 ; j++)
-		{
-			index_xyz = triangles[i].index_xyz[j];
-
-		// rotate the vertices so the model faces down the positive x axis
-		// also adjust the vertices to the desired origin
-			ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
-										adjust[0];
-			ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
-										adjust[1];
-			ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
-										adjust[2];
-
-			AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
-
-			VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum);
-			vnorms[index_xyz].numnormals++;
-		}
-	}
-
-//
-// calculate the vertex normals, match them to the template list, and store the
-// index of the best match
-//
-	for (i=0 ; i<model.num_xyz ; i++)
-	{
-		int		j;
-		vec3_t	v;
-		float	maxdot;
-		int		maxdotindex;
-		int		c;
-
-		c = vnorms[i].numnormals;
-		if (!c)
-			Error ("Vertex with no triangles attached");
-
-		VectorScale (vnorms[i].normalsum, 1.0/c, v);
-		VectorNormalize (v, v);
-
-		maxdot = -999999.0;
-		maxdotindex = -1;
-
-		for (j=0 ; j<NUMVERTEXNORMALS ; j++)
-		{
-			float	dot;
-
-			dot = DotProduct (v, avertexnormals[j]);
-			if (dot > maxdot)
-			{
-				maxdot = dot;
-				maxdotindex = j;
-			}
-		}
-
-		ptrivert[i].lightnormalindex = maxdotindex;
-	}
-
-	free (ptri);
-}
-
-/*
-===============
-Cmd_Frame	
-===============
-*/
-void Cmd_Frame (void)
-{
-	while (TokenAvailable())
-	{
-		GetToken (false);
-		if (g_skipmodel)
-			continue;
-		if (g_release || g_archive)
-		{
-			model.num_frames = 1;	// don't skip the writeout
-			continue;
-		}
-
-		H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames);
-
-		GrabFrame (token);
-	}
-}
-
-
-/*
-===============
-Cmd_Skin
-
-Skins aren't actually stored in the file, only a reference
-is saved out to the header file.
-===============
-*/
-void Cmd_Skin (void)
-{
-	byte	*palette;
-	byte	*pixels;
-	int		width, height;
-	byte	*cropped;
-	int		y;
-	char	name[1024], savename[1024];
-
-	GetToken (false);
-
-	if (model.num_skins == MAX_MD2SKINS)
-		Error ("model.num_skins == MAX_MD2SKINS");
-
-	if (g_skipmodel)
-		return;
-
-	sprintf (name, "%s/%s.lbm", cdarchive, token);
-	strcpy (name, ExpandPathAndArchive( name ) );
-//	sprintf (name, "%s/%s.lbm", cddir, token);
-
-	if (TokenAvailable())
-	{
-		GetToken (false);
-		sprintf (g_skins[model.num_skins], "%s.pcx", token);
-		sprintf (savename, "%s%s.pcx", gamedir, g_skins[model.num_skins]);
-	}
-	else
-	{
-		sprintf (savename, "%s/%s.pcx", cddir, token);
-		sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token);
-	}
-
-	model.num_skins++;
-
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	// load the image
-	printf ("loading %s\n", name);
-	Load256Image (name, &pixels, &palette, &width, &height);
-	RemapZero (pixels, palette, width, height);
-
-	// crop it to the proper size
-	cropped = malloc (model.skinwidth*model.skinheight);
-	for (y=0 ; y<model.skinheight ; y++)
-	{
-		memcpy (cropped+y*model.skinwidth,
-			pixels+y*width, model.skinwidth);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, model.skinwidth,
-		model.skinheight, palette);
-
-	free (pixels);
-	free (palette);
-	free (cropped);
-}
-
-
-/*
-=================
-Cmd_Origin
-=================
-*/
-void Cmd_Origin (void)
-{
-	// rotate points into frame of reference so model points down the
-	// positive x axis
-	GetToken (false);
-	adjust[1] = -atof (token);
-
-	GetToken (false);
-	adjust[0] = atof (token);
-
-	GetToken (false);
-	adjust[2] = -atof (token);
-}
-
-
-/*
-=================
-Cmd_ScaleUp
-=================
-*/
-void Cmd_ScaleUp (void)
-{
-	GetToken (false);
-	scale_up = atof (token);
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	printf ("Scale up: %f\n", scale_up);
-}
-
-
-/*
-=================
-Cmd_Skinsize
-
-Set a skin size other than the default
-=================
-*/
-void Cmd_Skinsize (void)
-{
-	GetToken (false);
-	g_fixedwidth = atoi(token);
-	GetToken (false);
-	g_fixedheight = atoi(token);
-}
-
-/*
-=================
-Cmd_Modelname
-
-Gives a different name/location for the file, instead of the cddir
-=================
-*/
-void Cmd_Modelname (void)
-{
-	GetToken (false);
-	strcpy (modelname, token);
-}
-
-/*
-===============
-Cmd_Cd
-===============
-*/
-void Cmd_Cd (void)
-{
-	FinishModel ();
-	ClearModel ();
-
-	GetToken (false);
-
-	// this is a silly mess...
-	sprintf (cdpartial, "models/%s", token); 
-	sprintf (cdarchive, "%smodels/%s", gamedir+strlen(qdir), token); 
-	sprintf (cddir, "%s%s", gamedir, cdpartial);
-
-	// if -only was specified and this cd doesn't match,
-	// skip the model (you only need to match leading chars,
-	// so you could regrab all monsters with -only monsters)
-	if (!g_only[0])
-		return;
-	if (strncmp(token, g_only, strlen(g_only)))
-	{
-		g_skipmodel = true;
-		printf ("skipping %s\n", cdpartial);
-	}
-}
-
+
+#include "qdata.h"
+#include "inout.h"
+
+//=================================================================
+
+typedef struct 
+{
+	int		numnormals;
+	vec3_t	normalsum;
+} vertexnormals_t;
+
+typedef struct
+{
+	vec3_t		v;
+	int			lightnormalindex;
+} trivert_t;
+
+typedef struct
+{
+	vec3_t		mins, maxs;
+	char		name[16];
+	trivert_t	v[MAX_VERTS];
+} frame_t;
+
+//================================================================
+
+frame_t		g_frames[MAX_FRAMES];
+
+dmdl_t		model;
+
+
+float		scale_up;			// set by $scale
+vec3_t		adjust;				// set by $origin
+int			g_fixedwidth, g_fixedheight;	// set by $skinsize
+
+
+//
+// base frame info
+//
+vec3_t		base_xyz[MAX_VERTS];
+dstvert_t	base_st[MAX_VERTS];
+dtriangle_t	triangles[MAX_TRIANGLES];
+
+int			triangle_st[MAX_TRIANGLES][3][2];
+
+// the command list holds counts, s/t values, and xyz indexes
+// that are valid for every frame
+int			commands[16384];
+int			numcommands;
+int			numglverts;
+int			used[MAX_TRIANGLES];
+
+char		g_skins[MAX_MD2SKINS][64];
+
+char		cdarchive[1024];
+char		cdpartial[1024];
+char		cddir[1024];
+
+char		modelname[64];	// empty unless $modelname issued (players)
+
+#define NUMVERTEXNORMALS	162
+
+float	avertexnormals[NUMVERTEXNORMALS][3] = {
+#include "anorms.h"
+};
+
+FILE	*headerouthandle = NULL;
+
+//==============================================================
+
+/*
+===============
+ClearModel
+===============
+*/
+void ClearModel (void)
+{
+	memset (&model, 0, sizeof(model));
+
+	modelname[0] = 0;
+	scale_up = 1.0;	
+	VectorCopy (vec3_origin, adjust);
+	g_fixedwidth = g_fixedheight = 0;
+	g_skipmodel = false;
+}
+
+
+void H_printf(char *fmt, ...)
+{
+	va_list argptr;
+	char	name[1024];
+
+	if (!headerouthandle)
+	{
+		sprintf (name, "%s/tris.h", cddir);
+		headerouthandle = SafeOpenWrite (name);
+		fprintf(headerouthandle, "// %s\n\n", cddir);
+		fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n");
+	}
+
+	va_start (argptr, fmt);
+	vfprintf (headerouthandle, fmt, argptr);
+	va_end (argptr);
+}
+
+
+/*
+============
+WriteModelFile
+============
+*/
+void WriteModelFile (FILE *modelouthandle)
+{
+	int				i;
+	dmdl_t			modeltemp;
+	int				j, k;
+	frame_t			*in;
+	daliasframe_t	*out;
+	byte			buffer[MAX_VERTS*4+128];
+	float			v;
+	int				c_on, c_off;
+
+	model.ident = IDALIASHEADER;
+	model.version = ALIAS_VERSION;
+	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
+	model.num_glcmds = numcommands;
+	model.ofs_skins = sizeof(dmdl_t);
+	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
+	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
+	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
+	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
+	model.ofs_end = model.ofs_glcmds + model.num_glcmds*4;
+
+	//
+	// write out the model header
+	//
+	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
+		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
+
+	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
+
+	//
+	// write out the skin names
+	//
+	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
+
+	//
+	// write out the texture coordinates
+	//
+	c_on = c_off = 0;
+	for (i=0 ; i<model.num_st ; i++)
+	{
+		base_st[i].s = LittleShort (base_st[i].s);
+		base_st[i].t = LittleShort (base_st[i].t);
+	}
+
+	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
+
+	//
+	// write out the triangles
+	//
+	for (i=0 ; i<model.num_tris ; i++)
+	{
+		int			j;
+		dtriangle_t	tri;
+
+		for (j=0 ; j<3 ; j++)
+		{
+			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
+			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
+		}
+
+		SafeWrite (modelouthandle, &tri, sizeof(tri));
+	}
+
+	//
+	// write out the frames
+	//
+	for (i=0 ; i<model.num_frames ; i++)
+	{
+		in = &g_frames[i];
+		out = (daliasframe_t *)buffer;
+
+		strcpy (out->name, in->name);
+		for (j=0 ; j<3 ; j++)
+		{
+			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
+			out->translate[j] = in->mins[j];
+		}
+
+		for (j=0 ; j<model.num_xyz ; j++)
+		{
+		// all of these are byte values, so no need to deal with endianness
+			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
+
+			for (k=0 ; k<3 ; k++)
+			{
+			// scale to byte values & min/max check
+				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
+
+			// clamp, so rounding doesn't wrap from 255.6 to 0
+				if (v > 255.0)
+					v = 255.0;
+				if (v < 0)
+					v = 0;
+				out->verts[j].v[k] = v;
+			}
+		}
+
+		for (j=0 ; j<3 ; j++)
+		{
+			out->scale[j] = LittleFloat (out->scale[j]);
+			out->translate[j] = LittleFloat (out->translate[j]);
+		}
+
+		SafeWrite (modelouthandle, out, model.framesize);
+	}
+
+	//
+	// write out glcmds
+	//
+	SafeWrite (modelouthandle, commands, numcommands*4);
+}
+
+
+/*
+===============
+FinishModel
+===============
+*/
+void FinishModel (void)
+{
+	FILE		*modelouthandle;
+	int			i;
+	char		name[1024];
+	
+	if (!model.num_frames)
+		return;
+	
+//
+// copy to release directory tree if doing a release build
+//
+	if (g_release)
+	{
+		if (modelname[0])
+			sprintf (name, "%s", modelname);
+		else
+			sprintf (name, "%s/tris.md2", cdpartial);
+		ReleaseFile (name);
+
+		for (i=0 ; i<model.num_skins ; i++)
+		{
+			ReleaseFile (g_skins[i]);
+		}
+		model.num_frames = 0;
+		return;
+	}
+	
+//
+// write the model output file
+//
+	if (modelname[0])
+		sprintf (name, "%s%s", gamedir, modelname);
+	else
+		sprintf (name, "%s/tris.md2", cddir);
+	printf ("saving to %s\n", name);
+	CreatePath (name);
+	modelouthandle = SafeOpenWrite (name);
+
+	WriteModelFile (modelouthandle);
+	
+	printf ("%3dx%3d skin\n", model.skinwidth, model.skinheight);
+	printf ("%4d vertexes\n", model.num_xyz);
+	printf ("%4d triangles\n", model.num_tris);
+	printf ("%4d frame\n", model.num_frames);
+	printf ("%4d glverts\n", numglverts);
+	printf ("%4d glcmd\n", model.num_glcmds);
+	printf ("%4d skins\n", model.num_skins);
+	printf ("file size: %d\n", (int)ftell (modelouthandle) );
+	printf ("---------------------\n");
+	
+	fclose (modelouthandle);
+
+	// finish writing header file
+	H_printf("\n");
+
+	// scale_up is usefull to allow step distances to be adjusted
+	H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
+
+	fclose (headerouthandle);
+	headerouthandle = NULL;
+}
+
+
+/*
+=================================================================
+
+ALIAS MODEL DISPLAY LIST GENERATION
+
+=================================================================
+*/
+
+int		strip_xyz[128];
+int		strip_st[128];
+int		strip_tris[128];
+int		stripcount;
+
+/*
+================
+StripLength
+================
+*/
+int	StripLength (int starttri, int startv)
+{
+	int			m1, m2;
+	int			st1, st2;
+	int			j;
+	dtriangle_t	*last, *check;
+	int			k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	strip_xyz[0] = last->index_xyz[(startv)%3];
+	strip_xyz[1] = last->index_xyz[(startv+1)%3];
+	strip_xyz[2] = last->index_xyz[(startv+2)%3];
+	strip_st[0] = last->index_st[(startv)%3];
+	strip_st[1] = last->index_st[(startv+1)%3];
+	strip_st[2] = last->index_st[(startv+2)%3];
+
+	strip_tris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->index_xyz[(startv+2)%3];
+	st1 = last->index_st[(startv+2)%3];
+	m2 = last->index_xyz[(startv+1)%3];
+	st2 = last->index_st[(startv+1)%3];
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1]
+		; j<model.num_tris ; j++, check++)
+	{
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->index_xyz[k] != m1)
+				continue;
+			if (check->index_st[k] != st1)
+				continue;
+			if (check->index_xyz[ (k+1)%3 ] != m2)
+				continue;
+			if (check->index_st[ (k+1)%3 ] != st2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			if (stripcount & 1)
+			{
+				m2 = check->index_xyz[ (k+2)%3 ];
+				st2 = check->index_st[ (k+2)%3 ];
+			}
+			else
+			{
+				m1 = check->index_xyz[ (k+2)%3 ];
+				st1 = check->index_st[ (k+2)%3 ];
+			}
+
+			strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
+			strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
+			strip_tris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<model.num_tris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+/*
+===========
+FanLength
+===========
+*/
+int	FanLength (int starttri, int startv)
+{
+	int		m1, m2;
+	int		st1, st2;
+	int		j;
+	dtriangle_t	*last, *check;
+	int		k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	strip_xyz[0] = last->index_xyz[(startv)%3];
+	strip_xyz[1] = last->index_xyz[(startv+1)%3];
+	strip_xyz[2] = last->index_xyz[(startv+2)%3];
+	strip_st[0] = last->index_st[(startv)%3];
+	strip_st[1] = last->index_st[(startv+1)%3];
+	strip_st[2] = last->index_st[(startv+2)%3];
+
+	strip_tris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->index_xyz[(startv+0)%3];
+	st1 = last->index_st[(startv+0)%3];
+	m2 = last->index_xyz[(startv+2)%3];
+	st2 = last->index_st[(startv+2)%3];
+
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1] 
+		; j<model.num_tris ; j++, check++)
+	{
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->index_xyz[k] != m1)
+				continue;
+			if (check->index_st[k] != st1)
+				continue;
+			if (check->index_xyz[ (k+1)%3 ] != m2)
+				continue;
+			if (check->index_st[ (k+1)%3 ] != st2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			m2 = check->index_xyz[ (k+2)%3 ];
+			st2 = check->index_st[ (k+2)%3 ];
+
+			strip_xyz[stripcount+2] = m2;
+			strip_st[stripcount+2] = st2;
+			strip_tris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<model.num_tris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+
+/*
+================
+BuildGlCmds
+
+Generate a list of trifans or strips
+for the model, which holds for all frames
+================
+*/
+void BuildGlCmds (void)
+{
+	int		i, j, k;
+	int		startv;
+	float	s, t;
+	int		len, bestlen, besttype;
+	int		best_xyz[1024];
+	int		best_st[1024];
+	int		best_tris[1024];
+	int		type;
+
+	//
+	// build tristrips
+	//
+	numcommands = 0;
+	numglverts = 0;
+	memset (used, 0, sizeof(used));
+	for (i=0 ; i<model.num_tris ; i++)
+	{
+		// pick an unused triangle and start the trifan
+		if (used[i])
+			continue;
+
+		bestlen = 0;
+		for (type = 0 ; type < 2 ; type++)
+//	type = 1;
+		{
+			for (startv =0 ; startv < 3 ; startv++)
+			{
+				if (type == 1)
+					len = StripLength (i, startv);
+				else
+					len = FanLength (i, startv);
+				if (len > bestlen)
+				{
+					besttype = type;
+					bestlen = len;
+					for (j=0 ; j<bestlen+2 ; j++)
+					{
+						best_st[j] = strip_st[j];
+						best_xyz[j] = strip_xyz[j];
+					}
+					for (j=0 ; j<bestlen ; j++)
+						best_tris[j] = strip_tris[j];
+				}
+			}
+		}
+
+		// mark the tris on the best strip/fan as used
+		for (j=0 ; j<bestlen ; j++)
+			used[best_tris[j]] = 1;
+
+		if (besttype == 1)
+			commands[numcommands++] = (bestlen+2);
+		else
+			commands[numcommands++] = -(bestlen+2);
+
+		numglverts += bestlen+2;
+
+		for (j=0 ; j<bestlen+2 ; j++)
+		{
+			// emit a vertex into the reorder buffer
+			k = best_st[j];
+
+			// emit s/t coords into the commands stream
+			s = base_st[k].s;
+			t = base_st[k].t;
+
+			s = (s + 0.5) / model.skinwidth;
+			t = (t + 0.5) / model.skinheight;
+
+			*(float *)&commands[numcommands++] = s;
+			*(float *)&commands[numcommands++] = t;
+			*(int *)&commands[numcommands++] = best_xyz[j];
+		}
+	}
+
+	commands[numcommands++] = 0;		// end of list marker
+}
+
+
+/*
+===============================================================
+
+BASE FRAME SETUP
+
+===============================================================
+*/
+
+/*
+============
+BuildST
+
+Builds the triangle_st array for the base frame and
+model.skinwidth / model.skinheight
+
+  FIXME: allow this to be loaded from a file for
+  arbitrary mappings
+============
+*/
+void BuildST (triangle_t *ptri, int numtri)
+{
+	int			i, j;
+	int			width, height, iwidth, iheight, swidth;
+	float		basex, basey;
+	float		s_scale, t_scale;
+	float		scale;
+	vec3_t		mins, maxs;
+	float		*pbasevert;
+	vec3_t		vtemp1, vtemp2, normal;
+
+	//
+	// find bounds of all the verts on the base frame
+	//
+	ClearBounds (mins, maxs);
+	
+	for (i=0 ; i<numtri ; i++)
+		for (j=0 ; j<3 ; j++)
+			AddPointToBounds (ptri[i].verts[j], mins, maxs);
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		mins[i] = floor(mins[i]);
+		maxs[i] = ceil(maxs[i]);
+	}
+	
+	width = maxs[0] - mins[0];
+	height = maxs[2] - mins[2];
+
+	if (!g_fixedwidth)
+	{	// old style
+		scale = 8;
+		if (width*scale >= 150)
+			scale = 150.0 / width;	
+		if (height*scale >= 190)
+			scale = 190.0 / height;
+
+		s_scale = t_scale = scale;
+
+		iwidth = ceil(width*s_scale);
+		iheight = ceil(height*t_scale);
+
+		iwidth += 4;
+		iheight += 4;
+	}
+	else
+	{	// new style
+		iwidth = g_fixedwidth / 2;
+		iheight = g_fixedheight;
+
+		s_scale = (float)(iwidth-4) / width;
+		t_scale = (float)(iheight-4) / height;
+	}
+
+//
+// determine which side of each triangle to map the texture to
+//
+	for (i=0 ; i<numtri ; i++)
+	{
+		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+		CrossProduct (vtemp1, vtemp2, normal);
+
+		if (normal[1] > 0)
+		{
+			basex = iwidth + 2;
+		}
+		else
+		{
+			basex = 2;
+		}
+		basey = 2;
+		
+		for (j=0 ; j<3 ; j++)
+		{
+			pbasevert = ptri[i].verts[j];
+
+			triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
+			triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
+		}
+	}
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+	swidth = iwidth*2;
+	model.skinwidth = (swidth + 3) & ~3;
+	model.skinheight = iheight;
+}
+
+
+/*
+=================
+Cmd_Base
+=================
+*/
+void Cmd_Base (void)
+{
+	triangle_t	*ptri;
+	int			i, j, k;
+	int		time1;
+	char	file1[1024];
+
+	GetToken (false);
+
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	printf ("---------------------\n");
+	sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
+	printf ("%s\n", file1);
+
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s.%s", cddir, token, trifileext);
+
+	time1 = FileTime (file1);
+	if (time1 == -1)
+		Error ("%s doesn't exist", file1);
+
+//
+// load the base triangles
+//
+	if (do3ds)
+		Load3DSTriangleList (file1, &ptri, &model.num_tris);
+	else
+		LoadTriangleList (file1, &ptri, &model.num_tris);
+
+//
+// get the ST values
+//
+	BuildST (ptri, model.num_tris);
+
+//
+// run through all the base triangles, storing each unique vertex in the
+// base vertex list and setting the indirect triangles to point to the base
+// vertices
+//
+	for (i=0 ; i<model.num_tris ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			// get the xyz index
+			for (k=0 ; k<model.num_xyz ; k++)
+				if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
+					break;	// this vertex is already in the base vertex list
+
+			if (k == model.num_xyz)
+			{ // new index
+				VectorCopy (ptri[i].verts[j], base_xyz[model.num_xyz]);
+				model.num_xyz++;
+			}
+
+			triangles[i].index_xyz[j] = k;
+
+			// get the st index
+			for (k=0 ; k<model.num_st ; k++)
+				if (triangle_st[i][j][0] == base_st[k].s
+				&& triangle_st[i][j][1] == base_st[k].t)
+					break;	// this vertex is already in the base vertex list
+
+			if (k == model.num_st)
+			{ // new index
+				base_st[model.num_st].s = triangle_st[i][j][0];
+				base_st[model.num_st].t = triangle_st[i][j][1];
+				model.num_st++;
+			}
+
+			triangles[i].index_st[j] = k;
+		}
+	}
+
+	// build triangle strips / fans
+	BuildGlCmds ();
+}
+
+//===============================================================
+
+char	*FindFrameFile (char *frame)
+{
+	int			time1;
+	char	file1[1024];
+	static char	retname[1024];
+	char	base[32];
+	char	suffix[32];
+	char	*s;
+
+	if (strstr (frame, "."))
+		return frame;		// allready in dot format
+
+	// split 'run1' into 'run' and '1'
+	s = frame + strlen(frame)-1;
+
+	while (s != frame && *s >= '0' && *s <= '9')
+		s--;
+
+	strcpy (suffix, s+1);
+	strcpy (base, frame);
+	base[s-frame+1] = 0;
+
+	// check for 'run1.tri'
+	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, trifileext);
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s%s.%s", base, suffix, trifileext);
+		return retname;
+	}
+
+	// check for 'run.1'
+	sprintf (file1, "%s/%s.%s",cddir, base, suffix);
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s.%s", base, suffix);
+		return retname;
+	}
+
+	Error ("frame %s could not be found",frame);
+	return NULL;
+}
+
+/*
+===============
+GrabFrame
+===============
+*/
+void GrabFrame (char *frame)
+{
+	triangle_t	*ptri;
+	int			i, j;
+	trivert_t	*ptrivert;
+	int			num_tris;
+	char		file1[1024];
+	frame_t		*fr;
+	vertexnormals_t	vnorms[MAX_VERTS];
+	int		index_xyz;
+	char	*framefile;
+
+	// the frame 'run1' will be looked for as either
+	// run.1 or run1.tri, so the new alias sequence save
+	// feature an be used
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+	printf ("grabbing %s\n", file1);
+
+	if (model.num_frames >= MAX_FRAMES)
+		Error ("model.num_frames >= MAX_FRAMES");
+	fr = &g_frames[model.num_frames];
+	model.num_frames++;
+
+	strcpy (fr->name, frame);
+
+//
+// load the frame
+//
+	if (do3ds)
+		Load3DSTriangleList (file1, &ptri, &num_tris);
+	else
+		LoadTriangleList (file1, &ptri, &num_tris);
+
+	if (num_tris != model.num_tris)
+		Error ("%s: number of triangles doesn't match base frame\n", file1);
+
+//
+// allocate storage for the frame's vertices
+//
+	ptrivert = fr->v;
+
+	for (i=0 ; i<model.num_xyz ; i++)
+	{
+		vnorms[i].numnormals = 0;
+		VectorClear (vnorms[i].normalsum);
+	}
+	ClearBounds (fr->mins, fr->maxs);
+
+//
+// store the frame's vertices in the same order as the base. This assumes the
+// triangles and vertices in this frame are in exactly the same order as in the
+// base
+//
+	for (i=0 ; i<num_tris ; i++)
+	{
+		vec3_t	vtemp1, vtemp2, normal;
+		float	ftemp;
+
+		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+		CrossProduct (vtemp1, vtemp2, normal);
+
+		VectorNormalize (normal, normal);
+
+	// rotate the normal so the model faces down the positive x axis
+		ftemp = normal[0];
+		normal[0] = -normal[1];
+		normal[1] = ftemp;
+
+		for (j=0 ; j<3 ; j++)
+		{
+			index_xyz = triangles[i].index_xyz[j];
+
+		// rotate the vertices so the model faces down the positive x axis
+		// also adjust the vertices to the desired origin
+			ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
+										adjust[0];
+			ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
+										adjust[1];
+			ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
+										adjust[2];
+
+			AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
+
+			VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum);
+			vnorms[index_xyz].numnormals++;
+		}
+	}
+
+//
+// calculate the vertex normals, match them to the template list, and store the
+// index of the best match
+//
+	for (i=0 ; i<model.num_xyz ; i++)
+	{
+		int		j;
+		vec3_t	v;
+		float	maxdot;
+		int		maxdotindex;
+		int		c;
+
+		c = vnorms[i].numnormals;
+		if (!c)
+			Error ("Vertex with no triangles attached");
+
+		VectorScale (vnorms[i].normalsum, 1.0/c, v);
+		VectorNormalize (v, v);
+
+		maxdot = -999999.0;
+		maxdotindex = -1;
+
+		for (j=0 ; j<NUMVERTEXNORMALS ; j++)
+		{
+			float	dot;
+
+			dot = DotProduct (v, avertexnormals[j]);
+			if (dot > maxdot)
+			{
+				maxdot = dot;
+				maxdotindex = j;
+			}
+		}
+
+		ptrivert[i].lightnormalindex = maxdotindex;
+	}
+
+	free (ptri);
+}
+
+/*
+===============
+Cmd_Frame	
+===============
+*/
+void Cmd_Frame (void)
+{
+	while (TokenAvailable())
+	{
+		GetToken (false);
+		if (g_skipmodel)
+			continue;
+		if (g_release || g_archive)
+		{
+			model.num_frames = 1;	// don't skip the writeout
+			continue;
+		}
+
+		H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames);
+
+		GrabFrame (token);
+	}
+}
+
+
+/*
+===============
+Cmd_Skin
+
+Skins aren't actually stored in the file, only a reference
+is saved out to the header file.
+===============
+*/
+void Cmd_Skin (void)
+{
+	byte	*palette;
+	byte	*pixels;
+	int		width, height;
+	byte	*cropped;
+	int		y;
+	char	name[1024], savename[1024];
+
+	GetToken (false);
+
+	if (model.num_skins == MAX_MD2SKINS)
+		Error ("model.num_skins == MAX_MD2SKINS");
+
+	if (g_skipmodel)
+		return;
+
+	sprintf (name, "%s/%s.lbm", cdarchive, token);
+	strcpy (name, ExpandPathAndArchive( name ) );
+//	sprintf (name, "%s/%s.lbm", cddir, token);
+
+	if (TokenAvailable())
+	{
+		GetToken (false);
+		sprintf (g_skins[model.num_skins], "%s.pcx", token);
+		sprintf (savename, "%s%s.pcx", gamedir, g_skins[model.num_skins]);
+	}
+	else
+	{
+		sprintf (savename, "%s/%s.pcx", cddir, token);
+		sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token);
+	}
+
+	model.num_skins++;
+
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	// load the image
+	printf ("loading %s\n", name);
+	Load256Image (name, &pixels, &palette, &width, &height);
+	RemapZero (pixels, palette, width, height);
+
+	// crop it to the proper size
+	cropped = malloc (model.skinwidth*model.skinheight);
+	for (y=0 ; y<model.skinheight ; y++)
+	{
+		memcpy (cropped+y*model.skinwidth,
+			pixels+y*width, model.skinwidth);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, model.skinwidth,
+		model.skinheight, palette);
+
+	free (pixels);
+	free (palette);
+	free (cropped);
+}
+
+
+/*
+=================
+Cmd_Origin
+=================
+*/
+void Cmd_Origin (void)
+{
+	// rotate points into frame of reference so model points down the
+	// positive x axis
+	GetToken (false);
+	adjust[1] = -atof (token);
+
+	GetToken (false);
+	adjust[0] = atof (token);
+
+	GetToken (false);
+	adjust[2] = -atof (token);
+}
+
+
+/*
+=================
+Cmd_ScaleUp
+=================
+*/
+void Cmd_ScaleUp (void)
+{
+	GetToken (false);
+	scale_up = atof (token);
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	printf ("Scale up: %f\n", scale_up);
+}
+
+
+/*
+=================
+Cmd_Skinsize
+
+Set a skin size other than the default
+=================
+*/
+void Cmd_Skinsize (void)
+{
+	GetToken (false);
+	g_fixedwidth = atoi(token);
+	GetToken (false);
+	g_fixedheight = atoi(token);
+}
+
+/*
+=================
+Cmd_Modelname
+
+Gives a different name/location for the file, instead of the cddir
+=================
+*/
+void Cmd_Modelname (void)
+{
+	GetToken (false);
+	strcpy (modelname, token);
+}
+
+/*
+===============
+Cmd_Cd
+===============
+*/
+void Cmd_Cd (void)
+{
+	FinishModel ();
+	ClearModel ();
+
+	GetToken (false);
+
+	// this is a silly mess...
+	sprintf (cdpartial, "models/%s", token); 
+	sprintf (cdarchive, "%smodels/%s", gamedir+strlen(qdir), token); 
+	sprintf (cddir, "%s%s", gamedir, cdpartial);
+
+	// if -only was specified and this cd doesn't match,
+	// skip the model (you only need to match leading chars,
+	// so you could regrab all monsters with -only monsters)
+	if (!g_only[0])
+		return;
+	if (strncmp(token, g_only, strlen(g_only)))
+	{
+		g_skipmodel = true;
+		printf ("skipping %s\n", cdpartial);
+	}
+}
+
diff --git a/tools/quake2/qdata/qdata.c b/tools/quake2/qdata/qdata.c
index 1ba332b0..0502ec89 100644
--- a/tools/quake2/qdata/qdata.c
+++ b/tools/quake2/qdata/qdata.c
@@ -1,526 +1,526 @@
-#include "qdata.h"
-#include "inout.h"
-
-qboolean	g_compress_pak;
-qboolean	g_release;			// don't grab, copy output data to new tree
-qboolean	g_pak;				// if true, copy to pak instead of release
-char		g_releasedir[1024];	// c:\quake2\baseq2, etc
-qboolean	g_archive;			// don't grab, copy source data to new tree
-qboolean	do3ds;
-char		g_only[256];		// if set, only grab this cd
-qboolean	g_skipmodel;		// set true when a cd is not g_only
-
-char		*ext_3ds = "3ds";
-char		*ext_tri= "tri";
-char		*trifileext;
-
-char		game[64] = "quake2";
-
-void InitPaths( int *argc, char **argv );
-
-/*
-=======================================================
-
-  PAK FILES
-
-=======================================================
-*/
-
-typedef struct
-{
-	char	name[56];
-	int		filepos, filelen;
-} packfile_t;
-
-typedef struct
-{
-	char	id[4];
-	int		dirofs;
-	int		dirlen;
-} packheader_t;
-
-packfile_t		pfiles[16384];
-FILE			*pakfile;
-packfile_t		*pf;
-packheader_t	pakheader;
-
-
-
-/*
-==============
-BeginPak
-==============
-*/
-void BeginPak (char *outname)
-{
-	if (!g_pak)
-		return;
-
-	pakfile = SafeOpenWrite (outname);
-
-	// leave space for header
-	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
-	
-	pf = pfiles;
-}
-
-
-/*
-==============
-ReleaseFile
-
-Filename should be gamedir reletive.
-Either copies the file to the release dir, or adds it to
-the pak file.
-==============
-*/
-void ReleaseFile (char *filename)
-{
-	int		len;
-	byte	*buf;
-	char	source[1024];
-	char	dest[1024];
-
-	if (!g_release)
-		return;
-
-	sprintf (source, "%s%s", gamedir, filename);
-
-	if (!g_pak)
-	{	// copy it
-		sprintf (dest, "%s/%s", g_releasedir, filename);
-		printf ("copying to %s\n", dest);
-		QCopyFile (source, dest);
-		return;
-	}
-
-	// pak it
-	printf ("paking %s\n", filename);
-	if (strlen(filename) >= sizeof(pf->name))
-		Error ("Filename too long for pak: %s", filename);
-
-	len = LoadFile (source, (void **)&buf);
-
-	if (g_compress_pak && len < 4096*1024 )
-	{
-		cblock_t	in, out;
-		cblock_t Huffman (cblock_t in);
-
-		in.count = len;
-		in.data = buf;
-
-		out = Huffman (in);
-
-		if (out.count < in.count)
-		{
-			printf ("   compressed from %i to %i\n", in.count, out.count);
-			free (in.data);
-			buf = out.data;
-			len = out.count;
-		}
-		else
-			free (out.data);
-	}
-
-	strcpy (pf->name, filename);
-	pf->filepos = LittleLong(ftell(pakfile));
-	pf->filelen = LittleLong(len);
-	pf++;
-
-	SafeWrite (pakfile, buf, len);
-
-	free (buf);
-}
-
-
-/*
-==============
-FinishPak
-==============
-*/
-void FinishPak (void)
-{
-	int		dirlen;
-	int		d;
-	int		i;
-
-	if (!g_pak)
-		return;
-
-	pakheader.id[0] = 'P';
-	pakheader.id[1] = 'A';
-	pakheader.id[2] = 'C';
-	pakheader.id[3] = 'K';
-	dirlen = (byte *)pf - (byte *)pfiles;
-	pakheader.dirofs = LittleLong(ftell(pakfile));
-	pakheader.dirlen = LittleLong(dirlen);
-	
-	SafeWrite (pakfile, pfiles, dirlen);
-
-	i = ftell (pakfile);
-	 
-	fseek (pakfile, 0, SEEK_SET);
-	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
-	fclose (pakfile);	
-	
-	d = pf - pfiles;
-	printf ("%i files packed in %i bytes\n",d, i);
-}
-
-
-/*
-===============
-Cmd_File
-
-This is only used to cause a file to be copied during a release
-build (default.cfg, maps, etc)
-===============
-*/
-void Cmd_File (void)
-{
-	GetToken (false);
-	ReleaseFile (token);
-}
-
-/*
-===============
-PackDirectory_r
-
-===============
-*/
-#ifdef _WIN32
-#include "io.h"
-void PackDirectory_r (char *dir)
-{
-	struct _finddata_t fileinfo;
-	int		handle;
-	char	dirstring[1024];
-	char	filename[1024];
-
-	sprintf (dirstring, "%s%s/*.*", gamedir, dir);
-
-	handle = _findfirst (dirstring, &fileinfo);
-	if (handle == -1)
-		return;
-
-	do
-	{
-		sprintf (filename, "%s/%s", dir, fileinfo.name);
-		if (fileinfo.attrib & _A_SUBDIR)
-		{	// directory
-			if (fileinfo.name[0] != '.')	// don't pak . and ..
-				PackDirectory_r (filename);
-			continue;
-		}
-		// copy or pack the file
-		ReleaseFile (filename);		
-	} while (_findnext( handle, &fileinfo ) != -1);
-
-	_findclose (handle);
-}
-#else
-
-#include <sys/types.h>
-#include <sys/dir.h>
-
-void PackDirectory_r (char *dir)
-{
-#ifdef NeXT
-	struct direct **namelist, *ent;
-#else
-	struct dirent **namelist, *ent;
-#endif
-	int		count;
-	struct stat st;
-	int			i;
-	int			len;
-	char		fullname[1024];
-	char		dirstring[1024];
-	char		*name;
-	
-	sprintf (dirstring, "%s%s", gamedir, dir);
-	count = scandir(dirstring, &namelist, NULL, NULL);
-	
-	for (i=0 ; i<count ; i++)
-	{
-		ent = namelist[i];	
-		name = ent->d_name;
-
-		if (name[0] == '.')
-			continue;
-	
-		sprintf (fullname, "%s/%s", dir, name);
-		sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
-		
-		if (stat (dirstring, &st) == -1)
-			Error ("fstating %s", pf->name);
-		if (st.st_mode & S_IFDIR)
-		{	// directory
-			PackDirectory_r (fullname);
-			continue;
-		}
-
-		// copy or pack the file
-		ReleaseFile (fullname);		
-	}
-}
-#endif
-
-
-/*
-===============
-Cmd_Dir
-
-This is only used to cause a directory to be copied during a
-release build (sounds, etc)
-===============
-*/
-void Cmd_Dir (void)
-{
-	GetToken (false);
-	PackDirectory_r (token);	
-}
-
-//========================================================================
-
-#define	MAX_RTEX	16384
-int		numrtex;
-char	rtex[MAX_RTEX][64];
-
-void ReleaseTexture (char *name)
-{
-	int		i;
-	char	path[1024];
-
-	for (i=0 ; i<numrtex ; i++)
-		if (!Q_strncasecmp(name, rtex[i], strlen(name)))
-			return;
-
-	if (numrtex == MAX_RTEX)
-		Error ("numrtex == MAX_RTEX");
-
-	strcpy (rtex[i], name);
-	numrtex++;
-
-	sprintf (path, "textures/%s.wal", name);
-	ReleaseFile (path);
-}
-
-/*
-===============
-Cmd_Maps
-
-Only relevent for release and pak files.
-Releases the .bsp files for the maps, and scans all of the files to
-build a list of all textures used, which are then released.
-===============
-*/
-void Cmd_Maps (void)
-{
-	char	map[1024];
-	int		i;
-
-	while (TokenAvailable ())
-	{
-		GetToken (false);
-		sprintf (map, "maps/%s.bsp", token);
-		ReleaseFile (map);
-
-		if (!g_release)
-			continue;
-
-		// get all the texture references
-		sprintf (map, "%smaps/%s.bsp", gamedir, token);
-		LoadBSPFileTexinfo (map);
-		for (i=0 ; i<numtexinfo ; i++)
-			ReleaseTexture (texinfo[i].texture);
-	}
-}
-
-
-//==============================================================
-
-/*
-===============
-ParseScript
-===============
-*/
-void ParseScript (void)
-{
-	while (1)
-	{
-		do
-		{	// look for a line starting with a $ command
-			GetToken (true);
-			if (endofscript)
-				return;
-			if (token[0] == '$')
-				break;				
-			while (TokenAvailable())
-				GetToken (false);
-		} while (1);
-	
-		//
-		// model commands
-		//
-		if (!strcmp (token, "$modelname"))
-			Cmd_Modelname ();
-		else if (!strcmp (token, "$base"))
-			Cmd_Base ();
-		else if (!strcmp (token, "$cd"))
-			Cmd_Cd ();
-		else if (!strcmp (token, "$origin"))
-			Cmd_Origin ();
-		else if (!strcmp (token, "$scale"))
-			Cmd_ScaleUp ();
-		else if (!strcmp (token, "$frame"))
-			Cmd_Frame ();
-		else if (!strcmp (token, "$skin"))
-			Cmd_Skin ();
-		else if (!strcmp (token, "$skinsize"))
-			Cmd_Skinsize ();
-		//
-		// sprite commands
-		//
-		else if (!strcmp (token, "$spritename"))
-			Cmd_SpriteName ();
-		else if (!strcmp (token, "$load"))
-			Cmd_Load ();
-		else if (!strcmp (token, "$spriteframe"))
-			Cmd_SpriteFrame ();
-		//
-		// image commands
-		//
-		else if (!strcmp (token, "$grab"))
-			Cmd_Grab ();
-		else if (!strcmp (token, "$raw"))
-			Cmd_Raw ();
-		else if (!strcmp (token, "$colormap"))
-			Cmd_Colormap ();
-		else if (!strcmp (token, "$mippal"))
-			Cmd_Mippal ();
-		else if (!strcmp (token, "$mipdir"))
-			Cmd_Mipdir ();
-		else if (!strcmp (token, "$mip"))
-			Cmd_Mip ();
-		else if (!strcmp (token, "$environment"))
-			Cmd_Environment ();
-		//
-		// video
-		//
-		else if (!strcmp (token, "$video"))
-			Cmd_Video ();
-		//
-		// misc
-		//
-		else if (!strcmp (token, "$file"))
-			Cmd_File ();
-		else if (!strcmp (token, "$dir"))
-			Cmd_Dir ();
-		else if (!strcmp (token, "$maps"))
-			Cmd_Maps ();
-		else if (!strcmp (token, "$alphalight"))
-			Cmd_Alphalight ();
-		else if (!strcmp (token, "$inverse16table" ))
-			Cmd_Inverse16Table();
-		else
-			Error ("bad command %s\n", token);
-	}
-}
-
-//=======================================================
-
-/*
-==============
-main
-==============
-*/
-int main (int argc, char **argv)
-{
-	static	int		i;		// VC4.2 compiler bug if auto...
-	char	path[1024];
-
-	ExpandWildcards (&argc, &argv);
-
-  InitPaths( &argc, argv );
-
-	for (i=1 ; i<argc ; i++)
-	{
-		if (!strcmp(argv[i], "-archive"))
-		{
-			// -archive f:/quake2/release/dump_11_30
-			archive = true;
-			strcpy (archivedir, argv[i+1]);
-			printf ("Archiving source to: %s\n", archivedir);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-release"))
-		{
-			g_release = true;
-			strcpy (g_releasedir, argv[i+1]);
-			printf ("Copy output to: %s\n", g_releasedir);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-compress"))
-		{
-			g_compress_pak = true;
-			printf ("Compressing pakfile\n");
-		}
-		else if (!strcmp(argv[i], "-pak"))
-		{
-			g_release = true;
-			g_pak = true;
-			printf ("Building pakfile: %s\n", argv[i+1]);
-			BeginPak (argv[i+1]);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-only"))
-		{
-			strcpy (g_only, argv[i+1]);
-			printf ("Only grabbing %s\n", g_only);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-3ds"))
-		{
-			do3ds = true;
-			printf ("loading .3ds files\n");
-		}
-		else if (argv[i][0] == '-')
-			Error ("Unknown option \"%s\"", argv[i]);
-		else
-			break;
-	}
-
-	if (i >= argc)
-		Error ("usage: %s [-archive <directory>] [-release <directory>] [-only <model>] [-3ds] file.qgr", argv[ 0 ] );
-
-	if (do3ds)
-		trifileext = ext_3ds;
-	else
-		trifileext = ext_tri;
-
-	for ( ; i<argc ; i++)
-	{
-		printf ("--------------- %s ---------------\n", argv[i]);
-		// load the script
-		strcpy (path, argv[i]);
-		DefaultExtension (path, ".qdt");
-		SetQdirFromPath (path);
-		LoadScriptFile (ExpandArg(path));
-		
-		//
-		// parse it
-		//
-		ParseScript ();
-
-		// write out the last model
-		FinishModel ();
-		FinishSprite ();
-	}
-
-	if (g_pak)
-		FinishPak ();
-
-	return 0;
-}
-
+#include "qdata.h"
+#include "inout.h"
+
+qboolean	g_compress_pak;
+qboolean	g_release;			// don't grab, copy output data to new tree
+qboolean	g_pak;				// if true, copy to pak instead of release
+char		g_releasedir[1024];	// c:\quake2\baseq2, etc
+qboolean	g_archive;			// don't grab, copy source data to new tree
+qboolean	do3ds;
+char		g_only[256];		// if set, only grab this cd
+qboolean	g_skipmodel;		// set true when a cd is not g_only
+
+char		*ext_3ds = "3ds";
+char		*ext_tri= "tri";
+char		*trifileext;
+
+char		game[64] = "quake2";
+
+void InitPaths( int *argc, char **argv );
+
+/*
+=======================================================
+
+  PAK FILES
+
+=======================================================
+*/
+
+typedef struct
+{
+	char	name[56];
+	int		filepos, filelen;
+} packfile_t;
+
+typedef struct
+{
+	char	id[4];
+	int		dirofs;
+	int		dirlen;
+} packheader_t;
+
+packfile_t		pfiles[16384];
+FILE			*pakfile;
+packfile_t		*pf;
+packheader_t	pakheader;
+
+
+
+/*
+==============
+BeginPak
+==============
+*/
+void BeginPak (char *outname)
+{
+	if (!g_pak)
+		return;
+
+	pakfile = SafeOpenWrite (outname);
+
+	// leave space for header
+	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
+	
+	pf = pfiles;
+}
+
+
+/*
+==============
+ReleaseFile
+
+Filename should be gamedir reletive.
+Either copies the file to the release dir, or adds it to
+the pak file.
+==============
+*/
+void ReleaseFile (char *filename)
+{
+	int		len;
+	byte	*buf;
+	char	source[1024];
+	char	dest[1024];
+
+	if (!g_release)
+		return;
+
+	sprintf (source, "%s%s", gamedir, filename);
+
+	if (!g_pak)
+	{	// copy it
+		sprintf (dest, "%s/%s", g_releasedir, filename);
+		printf ("copying to %s\n", dest);
+		QCopyFile (source, dest);
+		return;
+	}
+
+	// pak it
+	printf ("paking %s\n", filename);
+	if (strlen(filename) >= sizeof(pf->name))
+		Error ("Filename too long for pak: %s", filename);
+
+	len = LoadFile (source, (void **)&buf);
+
+	if (g_compress_pak && len < 4096*1024 )
+	{
+		cblock_t	in, out;
+		cblock_t Huffman (cblock_t in);
+
+		in.count = len;
+		in.data = buf;
+
+		out = Huffman (in);
+
+		if (out.count < in.count)
+		{
+			printf ("   compressed from %i to %i\n", in.count, out.count);
+			free (in.data);
+			buf = out.data;
+			len = out.count;
+		}
+		else
+			free (out.data);
+	}
+
+	strcpy (pf->name, filename);
+	pf->filepos = LittleLong(ftell(pakfile));
+	pf->filelen = LittleLong(len);
+	pf++;
+
+	SafeWrite (pakfile, buf, len);
+
+	free (buf);
+}
+
+
+/*
+==============
+FinishPak
+==============
+*/
+void FinishPak (void)
+{
+	int		dirlen;
+	int		d;
+	int		i;
+
+	if (!g_pak)
+		return;
+
+	pakheader.id[0] = 'P';
+	pakheader.id[1] = 'A';
+	pakheader.id[2] = 'C';
+	pakheader.id[3] = 'K';
+	dirlen = (byte *)pf - (byte *)pfiles;
+	pakheader.dirofs = LittleLong(ftell(pakfile));
+	pakheader.dirlen = LittleLong(dirlen);
+	
+	SafeWrite (pakfile, pfiles, dirlen);
+
+	i = ftell (pakfile);
+	 
+	fseek (pakfile, 0, SEEK_SET);
+	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
+	fclose (pakfile);	
+	
+	d = pf - pfiles;
+	printf ("%i files packed in %i bytes\n",d, i);
+}
+
+
+/*
+===============
+Cmd_File
+
+This is only used to cause a file to be copied during a release
+build (default.cfg, maps, etc)
+===============
+*/
+void Cmd_File (void)
+{
+	GetToken (false);
+	ReleaseFile (token);
+}
+
+/*
+===============
+PackDirectory_r
+
+===============
+*/
+#ifdef _WIN32
+#include "io.h"
+void PackDirectory_r (char *dir)
+{
+	struct _finddata_t fileinfo;
+	int		handle;
+	char	dirstring[1024];
+	char	filename[1024];
+
+	sprintf (dirstring, "%s%s/*.*", gamedir, dir);
+
+	handle = _findfirst (dirstring, &fileinfo);
+	if (handle == -1)
+		return;
+
+	do
+	{
+		sprintf (filename, "%s/%s", dir, fileinfo.name);
+		if (fileinfo.attrib & _A_SUBDIR)
+		{	// directory
+			if (fileinfo.name[0] != '.')	// don't pak . and ..
+				PackDirectory_r (filename);
+			continue;
+		}
+		// copy or pack the file
+		ReleaseFile (filename);		
+	} while (_findnext( handle, &fileinfo ) != -1);
+
+	_findclose (handle);
+}
+#else
+
+#include <sys/types.h>
+#include <sys/dir.h>
+
+void PackDirectory_r (char *dir)
+{
+#ifdef NeXT
+	struct direct **namelist, *ent;
+#else
+	struct dirent **namelist, *ent;
+#endif
+	int		count;
+	struct stat st;
+	int			i;
+	int			len;
+	char		fullname[1024];
+	char		dirstring[1024];
+	char		*name;
+	
+	sprintf (dirstring, "%s%s", gamedir, dir);
+	count = scandir(dirstring, &namelist, NULL, NULL);
+	
+	for (i=0 ; i<count ; i++)
+	{
+		ent = namelist[i];	
+		name = ent->d_name;
+
+		if (name[0] == '.')
+			continue;
+	
+		sprintf (fullname, "%s/%s", dir, name);
+		sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
+		
+		if (stat (dirstring, &st) == -1)
+			Error ("fstating %s", pf->name);
+		if (st.st_mode & S_IFDIR)
+		{	// directory
+			PackDirectory_r (fullname);
+			continue;
+		}
+
+		// copy or pack the file
+		ReleaseFile (fullname);		
+	}
+}
+#endif
+
+
+/*
+===============
+Cmd_Dir
+
+This is only used to cause a directory to be copied during a
+release build (sounds, etc)
+===============
+*/
+void Cmd_Dir (void)
+{
+	GetToken (false);
+	PackDirectory_r (token);	
+}
+
+//========================================================================
+
+#define	MAX_RTEX	16384
+int		numrtex;
+char	rtex[MAX_RTEX][64];
+
+void ReleaseTexture (char *name)
+{
+	int		i;
+	char	path[1024];
+
+	for (i=0 ; i<numrtex ; i++)
+		if (!Q_strncasecmp(name, rtex[i], strlen(name)))
+			return;
+
+	if (numrtex == MAX_RTEX)
+		Error ("numrtex == MAX_RTEX");
+
+	strcpy (rtex[i], name);
+	numrtex++;
+
+	sprintf (path, "textures/%s.wal", name);
+	ReleaseFile (path);
+}
+
+/*
+===============
+Cmd_Maps
+
+Only relevent for release and pak files.
+Releases the .bsp files for the maps, and scans all of the files to
+build a list of all textures used, which are then released.
+===============
+*/
+void Cmd_Maps (void)
+{
+	char	map[1024];
+	int		i;
+
+	while (TokenAvailable ())
+	{
+		GetToken (false);
+		sprintf (map, "maps/%s.bsp", token);
+		ReleaseFile (map);
+
+		if (!g_release)
+			continue;
+
+		// get all the texture references
+		sprintf (map, "%smaps/%s.bsp", gamedir, token);
+		LoadBSPFileTexinfo (map);
+		for (i=0 ; i<numtexinfo ; i++)
+			ReleaseTexture (texinfo[i].texture);
+	}
+}
+
+
+//==============================================================
+
+/*
+===============
+ParseScript
+===============
+*/
+void ParseScript (void)
+{
+	while (1)
+	{
+		do
+		{	// look for a line starting with a $ command
+			GetToken (true);
+			if (endofscript)
+				return;
+			if (token[0] == '$')
+				break;				
+			while (TokenAvailable())
+				GetToken (false);
+		} while (1);
+	
+		//
+		// model commands
+		//
+		if (!strcmp (token, "$modelname"))
+			Cmd_Modelname ();
+		else if (!strcmp (token, "$base"))
+			Cmd_Base ();
+		else if (!strcmp (token, "$cd"))
+			Cmd_Cd ();
+		else if (!strcmp (token, "$origin"))
+			Cmd_Origin ();
+		else if (!strcmp (token, "$scale"))
+			Cmd_ScaleUp ();
+		else if (!strcmp (token, "$frame"))
+			Cmd_Frame ();
+		else if (!strcmp (token, "$skin"))
+			Cmd_Skin ();
+		else if (!strcmp (token, "$skinsize"))
+			Cmd_Skinsize ();
+		//
+		// sprite commands
+		//
+		else if (!strcmp (token, "$spritename"))
+			Cmd_SpriteName ();
+		else if (!strcmp (token, "$load"))
+			Cmd_Load ();
+		else if (!strcmp (token, "$spriteframe"))
+			Cmd_SpriteFrame ();
+		//
+		// image commands
+		//
+		else if (!strcmp (token, "$grab"))
+			Cmd_Grab ();
+		else if (!strcmp (token, "$raw"))
+			Cmd_Raw ();
+		else if (!strcmp (token, "$colormap"))
+			Cmd_Colormap ();
+		else if (!strcmp (token, "$mippal"))
+			Cmd_Mippal ();
+		else if (!strcmp (token, "$mipdir"))
+			Cmd_Mipdir ();
+		else if (!strcmp (token, "$mip"))
+			Cmd_Mip ();
+		else if (!strcmp (token, "$environment"))
+			Cmd_Environment ();
+		//
+		// video
+		//
+		else if (!strcmp (token, "$video"))
+			Cmd_Video ();
+		//
+		// misc
+		//
+		else if (!strcmp (token, "$file"))
+			Cmd_File ();
+		else if (!strcmp (token, "$dir"))
+			Cmd_Dir ();
+		else if (!strcmp (token, "$maps"))
+			Cmd_Maps ();
+		else if (!strcmp (token, "$alphalight"))
+			Cmd_Alphalight ();
+		else if (!strcmp (token, "$inverse16table" ))
+			Cmd_Inverse16Table();
+		else
+			Error ("bad command %s\n", token);
+	}
+}
+
+//=======================================================
+
+/*
+==============
+main
+==============
+*/
+int main (int argc, char **argv)
+{
+	static	int		i;		// VC4.2 compiler bug if auto...
+	char	path[1024];
+
+	ExpandWildcards (&argc, &argv);
+
+  InitPaths( &argc, argv );
+
+	for (i=1 ; i<argc ; i++)
+	{
+		if (!strcmp(argv[i], "-archive"))
+		{
+			// -archive f:/quake2/release/dump_11_30
+			archive = true;
+			strcpy (archivedir, argv[i+1]);
+			printf ("Archiving source to: %s\n", archivedir);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-release"))
+		{
+			g_release = true;
+			strcpy (g_releasedir, argv[i+1]);
+			printf ("Copy output to: %s\n", g_releasedir);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-compress"))
+		{
+			g_compress_pak = true;
+			printf ("Compressing pakfile\n");
+		}
+		else if (!strcmp(argv[i], "-pak"))
+		{
+			g_release = true;
+			g_pak = true;
+			printf ("Building pakfile: %s\n", argv[i+1]);
+			BeginPak (argv[i+1]);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-only"))
+		{
+			strcpy (g_only, argv[i+1]);
+			printf ("Only grabbing %s\n", g_only);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-3ds"))
+		{
+			do3ds = true;
+			printf ("loading .3ds files\n");
+		}
+		else if (argv[i][0] == '-')
+			Error ("Unknown option \"%s\"", argv[i]);
+		else
+			break;
+	}
+
+	if (i >= argc)
+		Error ("usage: %s [-archive <directory>] [-release <directory>] [-only <model>] [-3ds] file.qgr", argv[ 0 ] );
+
+	if (do3ds)
+		trifileext = ext_3ds;
+	else
+		trifileext = ext_tri;
+
+	for ( ; i<argc ; i++)
+	{
+		printf ("--------------- %s ---------------\n", argv[i]);
+		// load the script
+		strcpy (path, argv[i]);
+		DefaultExtension (path, ".qdt");
+		SetQdirFromPath (path);
+		LoadScriptFile (ExpandArg(path));
+		
+		//
+		// parse it
+		//
+		ParseScript ();
+
+		// write out the last model
+		FinishModel ();
+		FinishSprite ();
+	}
+
+	if (g_pak)
+		FinishPak ();
+
+	return 0;
+}
+
diff --git a/tools/quake2/qdata/qdata.h b/tools/quake2/qdata/qdata.h
index f742bbec..2a1da9cb 100644
--- a/tools/quake2/qdata/qdata.h
+++ b/tools/quake2/qdata/qdata.h
@@ -1,75 +1,75 @@
-// qdata.h
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "cmdlib.h"
-#include "scriplib.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "lbmlib.h"
-#include "q2_threads.h"
-#include "l3dslib.h"
-#include "bspfile.h"
-
-#ifdef _WIN32
-	#ifdef NDEBUG							// Don't show in a Release build
-		#pragma warning(disable : 4305)     // truncate from double to float
-		#pragma warning(disable : 4244)     // conversion from double to float
-		#pragma warning(disable : 4018)     // signed/unsigned mismatch
-	#endif
-#endif
-
-void Cmd_Modelname (void);
-void Cmd_Base (void);
-void Cmd_Cd (void);
-void Cmd_Origin (void);
-void Cmd_ScaleUp (void);
-void Cmd_Frame (void);
-void Cmd_Modelname (void);
-void Cmd_Skin (void);
-void Cmd_Skinsize (void);
-void FinishModel (void);
-
-void Cmd_Inverse16Table( void );
-
-void Cmd_SpriteName (void);
-void Cmd_Load (void);
-void Cmd_SpriteFrame (void);
-void FinishSprite (void);
-
-void Cmd_Grab (void);
-void Cmd_Raw (void);
-void Cmd_Mip (void);
-void Cmd_Environment (void);
-void Cmd_Colormap (void);
-
-void Cmd_File (void);
-void Cmd_Dir (void);
-void Cmd_StartWad (void);
-void Cmd_EndWad (void);
-void Cmd_Mippal (void);
-void Cmd_Mipdir (void);
-void Cmd_Alphalight (void);
-
-void Cmd_Video (void);
-
-void RemapZero (byte *pixels, byte *palette, int width, int height);
-
-void ReleaseFile (char *filename);
-
-extern	byte		*byteimage, *lbmpalette;
-extern	int			byteimagewidth, byteimageheight;
-
-extern	qboolean	g_release;			// don't grab, copy output data to new tree
-extern	char		g_releasedir[1024];	// c:\quake2\baseq2, etc
-extern	qboolean	g_archive;			// don't grab, copy source data to new tree
-extern	qboolean	do3ds;
-extern	char		g_only[256];		// if set, only grab this cd
-extern	qboolean	g_skipmodel;		// set true when a cd is not g_only
-
-extern	char		*trifileext;
+// qdata.h
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "cmdlib.h"
+#include "scriplib.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "lbmlib.h"
+#include "q2_threads.h"
+#include "l3dslib.h"
+#include "bspfile.h"
+
+#ifdef _WIN32
+	#ifdef NDEBUG							// Don't show in a Release build
+		#pragma warning(disable : 4305)     // truncate from double to float
+		#pragma warning(disable : 4244)     // conversion from double to float
+		#pragma warning(disable : 4018)     // signed/unsigned mismatch
+	#endif
+#endif
+
+void Cmd_Modelname (void);
+void Cmd_Base (void);
+void Cmd_Cd (void);
+void Cmd_Origin (void);
+void Cmd_ScaleUp (void);
+void Cmd_Frame (void);
+void Cmd_Modelname (void);
+void Cmd_Skin (void);
+void Cmd_Skinsize (void);
+void FinishModel (void);
+
+void Cmd_Inverse16Table( void );
+
+void Cmd_SpriteName (void);
+void Cmd_Load (void);
+void Cmd_SpriteFrame (void);
+void FinishSprite (void);
+
+void Cmd_Grab (void);
+void Cmd_Raw (void);
+void Cmd_Mip (void);
+void Cmd_Environment (void);
+void Cmd_Colormap (void);
+
+void Cmd_File (void);
+void Cmd_Dir (void);
+void Cmd_StartWad (void);
+void Cmd_EndWad (void);
+void Cmd_Mippal (void);
+void Cmd_Mipdir (void);
+void Cmd_Alphalight (void);
+
+void Cmd_Video (void);
+
+void RemapZero (byte *pixels, byte *palette, int width, int height);
+
+void ReleaseFile (char *filename);
+
+extern	byte		*byteimage, *lbmpalette;
+extern	int			byteimagewidth, byteimageheight;
+
+extern	qboolean	g_release;			// don't grab, copy output data to new tree
+extern	char		g_releasedir[1024];	// c:\quake2\baseq2, etc
+extern	qboolean	g_archive;			// don't grab, copy source data to new tree
+extern	qboolean	do3ds;
+extern	char		g_only[256];		// if set, only grab this cd
+extern	qboolean	g_skipmodel;		// set true when a cd is not g_only
+
+extern	char		*trifileext;
diff --git a/tools/quake2/qdata/sprites.c b/tools/quake2/qdata/sprites.c
index 0f3f2f3e..db812751 100644
--- a/tools/quake2/qdata/sprites.c
+++ b/tools/quake2/qdata/sprites.c
@@ -1,208 +1,208 @@
-
-#include "qdata.h"
-#include "inout.h"
-
-#define MAX_SPRFRAMES			MAX_MD2SKINS
-
-dsprite_t		sprite;
-dsprframe_t		frames[MAX_SPRFRAMES];
-
-byte			*byteimage, *lbmpalette;
-int				byteimagewidth, byteimageheight;
-
-char			spritename[1024];
-
-
-void FinishSprite (void);
-void Cmd_Spritename (void);
-
-
-
-/*
-==============
-FinishSprite	
-==============
-*/
-void FinishSprite (void)
-{
-	FILE	*spriteouthandle;
-	int			i, curframe;
-	dsprite_t	spritetemp;
-	char		savename[1024];
-
-	if (sprite.numframes == 0)
-		return;
-
-	if (!strlen(spritename))
-		Error ("Didn't name sprite file");
-		
-	sprintf (savename, "%s%s.sp2", gamedir, spritename);
-
-	if (g_release)
-	{
-		char	name[1024];
-
-		sprintf (name, "%s.sp2", spritename);
-		ReleaseFile (name);
-		spritename[0] = 0;		// clear for a new sprite
-		sprite.numframes = 0;
-		return;
-	}
-
-
-	printf ("saving in %s\n", savename);
-	CreatePath (savename);
-	spriteouthandle = SafeOpenWrite (savename);
-
-
-//
-// write out the sprite header
-//
-	spritetemp.ident = LittleLong (IDSPRITEHEADER);
-	spritetemp.version = LittleLong (SPRITE_VERSION);
-	spritetemp.numframes = LittleLong (sprite.numframes);
-
-	SafeWrite (spriteouthandle, &spritetemp, 12);
-
-//
-// write out the frames
-//
-	curframe = 0;
-
-	for (i=0 ; i<sprite.numframes ; i++)
-	{
-		frames[i].width = LittleLong(frames[i].width);
-		frames[i].height = LittleLong(frames[i].height);
-		frames[i].origin_x = LittleLong(frames[i].origin_x);
-		frames[i].origin_y = LittleLong(frames[i].origin_y);
-	}
-	SafeWrite (spriteouthandle, frames, sizeof(frames[0])*sprite.numframes);
-
-	fclose (spriteouthandle);
-	
-	spritename[0] = 0;		// clear for a new sprite
-	sprite.numframes = 0;
-}
-
-
-/*
-===============
-Cmd_Load
-===============
-*/
-void Cmd_Load (void)
-{
-	char	*name;
-
-	GetToken (false);
-
-	if (g_release)
-		return;
-
-	name = ExpandPathAndArchive(token);
-
-	// load the image
-	printf ("loading %s\n", name);
-	Load256Image (name, &byteimage, &lbmpalette, 
-		&byteimagewidth, &byteimageheight);
-	RemapZero (byteimage, lbmpalette, 
-		byteimagewidth, byteimageheight);
-}
-
-
-/*
-===============
-Cmd_SpriteFrame
-===============
-*/
-void Cmd_SpriteFrame (void)
-{
-	int             y,xl,yl,xh,yh,w,h;
-	dsprframe_t		*pframe;
-	int				ox, oy;
-	byte			*cropped;
-	char			savename[1024];
-
-	GetToken (false);
-	xl = atoi (token);
-	GetToken (false);
-	yl = atoi (token);
-	GetToken (false);
-	w = atoi (token);
-	GetToken (false);
-	h = atoi (token);
-
-	// origin offset is optional
-	if (TokenAvailable ())
-	{
-		GetToken (false);
-		ox = atoi (token);
-		GetToken (false);
-		oy = atoi (token);		
-	}
-	else
-	{
-		ox = w/2;
-		oy = h/2;
-	}
-
-	if ((xl & 0x07) || (yl & 0x07) || (w & 0x07) || (h & 0x07))
-		Error ("Sprite dimensions not multiples of 8\n");
-
-	if ((w > 256) || (h > 256))
-		Error ("Sprite has a dimension longer than 256");
-
-	xh = xl+w;
-	yh = yl+h;
-
-	if (sprite.numframes >= MAX_SPRFRAMES)
-		Error ("Too many frames; increase MAX_SPRFRAMES\n");
-
-	pframe = &frames[sprite.numframes];
-	pframe->width = w;
-	pframe->height = h;
-	pframe->origin_x = ox;
-	pframe->origin_y = oy;
-	sprintf (pframe->name, "%s_%i.pcx", spritename, sprite.numframes);
-	sprintf (savename, "%s%s_%i.pcx", gamedir, spritename, sprite.numframes);
-	sprite.numframes++;
-
-	if (g_release)
-	{
-		ReleaseFile (pframe->name);
-		return;
-	}
-
-	// crop it to the proper size
-	cropped = malloc (w*h);
-	for (y=0 ; y<h ; y++)
-	{
-		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, w,	h, lbmpalette);
-
-	free (cropped);
-}
-
-
-
-/*
-==============
-Cmd_SpriteName
-==============
-*/
-void Cmd_SpriteName (void)
-{
-	if (sprite.numframes)
-		FinishSprite ();
-
-	GetToken (false);
-	strcpy (spritename, token);
-	memset (&sprite, 0, sizeof(sprite));
-	memset (&frames, 0, sizeof(frames));
-}
-
+
+#include "qdata.h"
+#include "inout.h"
+
+#define MAX_SPRFRAMES			MAX_MD2SKINS
+
+dsprite_t		sprite;
+dsprframe_t		frames[MAX_SPRFRAMES];
+
+byte			*byteimage, *lbmpalette;
+int				byteimagewidth, byteimageheight;
+
+char			spritename[1024];
+
+
+void FinishSprite (void);
+void Cmd_Spritename (void);
+
+
+
+/*
+==============
+FinishSprite	
+==============
+*/
+void FinishSprite (void)
+{
+	FILE	*spriteouthandle;
+	int			i, curframe;
+	dsprite_t	spritetemp;
+	char		savename[1024];
+
+	if (sprite.numframes == 0)
+		return;
+
+	if (!strlen(spritename))
+		Error ("Didn't name sprite file");
+		
+	sprintf (savename, "%s%s.sp2", gamedir, spritename);
+
+	if (g_release)
+	{
+		char	name[1024];
+
+		sprintf (name, "%s.sp2", spritename);
+		ReleaseFile (name);
+		spritename[0] = 0;		// clear for a new sprite
+		sprite.numframes = 0;
+		return;
+	}
+
+
+	printf ("saving in %s\n", savename);
+	CreatePath (savename);
+	spriteouthandle = SafeOpenWrite (savename);
+
+
+//
+// write out the sprite header
+//
+	spritetemp.ident = LittleLong (IDSPRITEHEADER);
+	spritetemp.version = LittleLong (SPRITE_VERSION);
+	spritetemp.numframes = LittleLong (sprite.numframes);
+
+	SafeWrite (spriteouthandle, &spritetemp, 12);
+
+//
+// write out the frames
+//
+	curframe = 0;
+
+	for (i=0 ; i<sprite.numframes ; i++)
+	{
+		frames[i].width = LittleLong(frames[i].width);
+		frames[i].height = LittleLong(frames[i].height);
+		frames[i].origin_x = LittleLong(frames[i].origin_x);
+		frames[i].origin_y = LittleLong(frames[i].origin_y);
+	}
+	SafeWrite (spriteouthandle, frames, sizeof(frames[0])*sprite.numframes);
+
+	fclose (spriteouthandle);
+	
+	spritename[0] = 0;		// clear for a new sprite
+	sprite.numframes = 0;
+}
+
+
+/*
+===============
+Cmd_Load
+===============
+*/
+void Cmd_Load (void)
+{
+	char	*name;
+
+	GetToken (false);
+
+	if (g_release)
+		return;
+
+	name = ExpandPathAndArchive(token);
+
+	// load the image
+	printf ("loading %s\n", name);
+	Load256Image (name, &byteimage, &lbmpalette, 
+		&byteimagewidth, &byteimageheight);
+	RemapZero (byteimage, lbmpalette, 
+		byteimagewidth, byteimageheight);
+}
+
+
+/*
+===============
+Cmd_SpriteFrame
+===============
+*/
+void Cmd_SpriteFrame (void)
+{
+	int             y,xl,yl,xh,yh,w,h;
+	dsprframe_t		*pframe;
+	int				ox, oy;
+	byte			*cropped;
+	char			savename[1024];
+
+	GetToken (false);
+	xl = atoi (token);
+	GetToken (false);
+	yl = atoi (token);
+	GetToken (false);
+	w = atoi (token);
+	GetToken (false);
+	h = atoi (token);
+
+	// origin offset is optional
+	if (TokenAvailable ())
+	{
+		GetToken (false);
+		ox = atoi (token);
+		GetToken (false);
+		oy = atoi (token);		
+	}
+	else
+	{
+		ox = w/2;
+		oy = h/2;
+	}
+
+	if ((xl & 0x07) || (yl & 0x07) || (w & 0x07) || (h & 0x07))
+		Error ("Sprite dimensions not multiples of 8\n");
+
+	if ((w > 256) || (h > 256))
+		Error ("Sprite has a dimension longer than 256");
+
+	xh = xl+w;
+	yh = yl+h;
+
+	if (sprite.numframes >= MAX_SPRFRAMES)
+		Error ("Too many frames; increase MAX_SPRFRAMES\n");
+
+	pframe = &frames[sprite.numframes];
+	pframe->width = w;
+	pframe->height = h;
+	pframe->origin_x = ox;
+	pframe->origin_y = oy;
+	sprintf (pframe->name, "%s_%i.pcx", spritename, sprite.numframes);
+	sprintf (savename, "%s%s_%i.pcx", gamedir, spritename, sprite.numframes);
+	sprite.numframes++;
+
+	if (g_release)
+	{
+		ReleaseFile (pframe->name);
+		return;
+	}
+
+	// crop it to the proper size
+	cropped = malloc (w*h);
+	for (y=0 ; y<h ; y++)
+	{
+		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, w,	h, lbmpalette);
+
+	free (cropped);
+}
+
+
+
+/*
+==============
+Cmd_SpriteName
+==============
+*/
+void Cmd_SpriteName (void)
+{
+	if (sprite.numframes)
+		FinishSprite ();
+
+	GetToken (false);
+	strcpy (spritename, token);
+	memset (&sprite, 0, sizeof(sprite));
+	memset (&frames, 0, sizeof(frames));
+}
+
diff --git a/tools/quake2/qdata/tables.c b/tools/quake2/qdata/tables.c
index 58f81c26..6aee6126 100644
--- a/tools/quake2/qdata/tables.c
+++ b/tools/quake2/qdata/tables.c
@@ -1,150 +1,150 @@
-#include "qdata.h"
-
-/*
-=============================================================================
-
-ALPHALIGHT GENERATION
-
-Find alphamap values that best match modulated lightmap values
-
-This isn't used anymore, but I'm keeping it around...
-=============================================================================
-*/
-
-unsigned short	alphamap[32*32*32];
-unsigned char	inverse16to8table[65536];
-
-/*
-static int FindNearestColor( unsigned int color )
-{
-	int i;
-	int closest_so_far = 0;
-	float closest_distance_so_far = 100000000;
-	float d;
-	float r[2], g[2], b[2];
-
-	// incoming color is assumed to be in 0xRRGGBB format
-	r[0] = ( color & 31 ) << 3;
-	g[0] = ( ( color >> 5 ) & 63 ) << 2;
-	b[0] = ( ( color >> 11 ) & 31 ) << 3;
-
-	for ( i = 0; i < 256; i++ )
-	{
-		r[1] = ( d_8to24table[i] >> 0 ) & 0xFF;
-		g[1] = ( d_8to24table[i] >> 8 ) & 0xFF;
-		b[1] = ( d_8to24table[i] >> 16 ) & 0xFF;
-
-		d = ( r[1] - r[0] ) * ( r[1] - r[0] ) +
-			( g[1] - g[0] ) * ( g[1] - g[0] ) +
-			( b[1] - b[0] ) * ( b[1] - b[0] );
-
-		if ( d < closest_distance_so_far )
-		{
-			closest_distance_so_far = d;
-			closest_so_far = i;
-		}
-	}
-
-	return closest_so_far;
-}
-*/
-
-extern byte BestColor( int, int, int, int, int );
-
-void Inverse16_BuildTable( void )
-{
-	int i;
-
-	/*
-	** create the 16-to-8 table
-	*/
-	for ( i = 0; i < 65536; i++ )
-	{
-		int r = i & 31;
-		int g = ( i >> 5 ) & 63;
-		int b = ( i >> 11 ) & 31;
-
-		r <<= 3;
-		g <<= 2;
-		b <<= 3;
-
-		inverse16to8table[i] = BestColor( r, g, b, 0, 255 );
-	}
-}
-
-void Alphalight_Thread (int i)
-{
-	int		j;
-	float	r, g, b;
-	float	mr, mg, mb, ma;
-	float	distortion, bestdistortion;
-	float	v;
-
-	r = (i>>10) * (1.0/16);
-	g = ((i>>5)&31)  * (1.0/16);
-	b = (i&31) * (1.0/16);
-
-	bestdistortion = 999999;
-	for (j=0 ; j<16*16*16*16 ; j++)
-	{
-		mr = (j>>12) * (1.0/16);
-		mg = ((j>>8)&15) * (1.0/16);
-		mb = ((j>>4)&15) * (1.0/16);
-		ma = (j&15) * (1.0/16);
-
-		v = r * 0.5 - (mr*ma + 0.5*(1.0-ma));
-		distortion = v*v;
-		v = g * 0.5 - (mg*ma + 0.5*(1.0-ma));
-		distortion += v*v;
-		v = b * 0.5 - (mb*ma + 0.5*(1.0-ma));
-		distortion += v*v;
-
-		distortion *= 1.0 + ma*4;
-
-		if (distortion < bestdistortion)
-		{
-			bestdistortion = distortion;
-			alphamap[i] = j;
-		}
-	}
-}
-
-void Cmd_Alphalight (void)
-{
-	char	savename[1024];
-
-	GetToken (false);
-
-	if (g_release)
-	{
-		ReleaseFile (token);
-		return;
-	}
-
-	sprintf (savename, "%s%s", gamedir, token);
-	printf ("Building alphalight table...\n");
-
-	RunThreadsOnIndividual (32*32*32, true, Alphalight_Thread);
-
-	SaveFile (savename, (byte *)alphamap, sizeof(alphamap));
-}
-
-
-void Cmd_Inverse16Table( void )
-{
-	char savename[1024];
-
-	if ( g_release )
-	{
-		sprintf (savename, "pics/16to8.dat");
-		ReleaseFile( savename );
-		return;
-	}
-
-	sprintf (savename, "%spics/16to8.dat", gamedir);
-	printf ("Building inverse 16-to-8 table...\n");
-
-	Inverse16_BuildTable();
-
-	SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) );
-}
+#include "qdata.h"
+
+/*
+=============================================================================
+
+ALPHALIGHT GENERATION
+
+Find alphamap values that best match modulated lightmap values
+
+This isn't used anymore, but I'm keeping it around...
+=============================================================================
+*/
+
+unsigned short	alphamap[32*32*32];
+unsigned char	inverse16to8table[65536];
+
+/*
+static int FindNearestColor( unsigned int color )
+{
+	int i;
+	int closest_so_far = 0;
+	float closest_distance_so_far = 100000000;
+	float d;
+	float r[2], g[2], b[2];
+
+	// incoming color is assumed to be in 0xRRGGBB format
+	r[0] = ( color & 31 ) << 3;
+	g[0] = ( ( color >> 5 ) & 63 ) << 2;
+	b[0] = ( ( color >> 11 ) & 31 ) << 3;
+
+	for ( i = 0; i < 256; i++ )
+	{
+		r[1] = ( d_8to24table[i] >> 0 ) & 0xFF;
+		g[1] = ( d_8to24table[i] >> 8 ) & 0xFF;
+		b[1] = ( d_8to24table[i] >> 16 ) & 0xFF;
+
+		d = ( r[1] - r[0] ) * ( r[1] - r[0] ) +
+			( g[1] - g[0] ) * ( g[1] - g[0] ) +
+			( b[1] - b[0] ) * ( b[1] - b[0] );
+
+		if ( d < closest_distance_so_far )
+		{
+			closest_distance_so_far = d;
+			closest_so_far = i;
+		}
+	}
+
+	return closest_so_far;
+}
+*/
+
+extern byte BestColor( int, int, int, int, int );
+
+void Inverse16_BuildTable( void )
+{
+	int i;
+
+	/*
+	** create the 16-to-8 table
+	*/
+	for ( i = 0; i < 65536; i++ )
+	{
+		int r = i & 31;
+		int g = ( i >> 5 ) & 63;
+		int b = ( i >> 11 ) & 31;
+
+		r <<= 3;
+		g <<= 2;
+		b <<= 3;
+
+		inverse16to8table[i] = BestColor( r, g, b, 0, 255 );
+	}
+}
+
+void Alphalight_Thread (int i)
+{
+	int		j;
+	float	r, g, b;
+	float	mr, mg, mb, ma;
+	float	distortion, bestdistortion;
+	float	v;
+
+	r = (i>>10) * (1.0/16);
+	g = ((i>>5)&31)  * (1.0/16);
+	b = (i&31) * (1.0/16);
+
+	bestdistortion = 999999;
+	for (j=0 ; j<16*16*16*16 ; j++)
+	{
+		mr = (j>>12) * (1.0/16);
+		mg = ((j>>8)&15) * (1.0/16);
+		mb = ((j>>4)&15) * (1.0/16);
+		ma = (j&15) * (1.0/16);
+
+		v = r * 0.5 - (mr*ma + 0.5*(1.0-ma));
+		distortion = v*v;
+		v = g * 0.5 - (mg*ma + 0.5*(1.0-ma));
+		distortion += v*v;
+		v = b * 0.5 - (mb*ma + 0.5*(1.0-ma));
+		distortion += v*v;
+
+		distortion *= 1.0 + ma*4;
+
+		if (distortion < bestdistortion)
+		{
+			bestdistortion = distortion;
+			alphamap[i] = j;
+		}
+	}
+}
+
+void Cmd_Alphalight (void)
+{
+	char	savename[1024];
+
+	GetToken (false);
+
+	if (g_release)
+	{
+		ReleaseFile (token);
+		return;
+	}
+
+	sprintf (savename, "%s%s", gamedir, token);
+	printf ("Building alphalight table...\n");
+
+	RunThreadsOnIndividual (32*32*32, true, Alphalight_Thread);
+
+	SaveFile (savename, (byte *)alphamap, sizeof(alphamap));
+}
+
+
+void Cmd_Inverse16Table( void )
+{
+	char savename[1024];
+
+	if ( g_release )
+	{
+		sprintf (savename, "pics/16to8.dat");
+		ReleaseFile( savename );
+		return;
+	}
+
+	sprintf (savename, "%spics/16to8.dat", gamedir);
+	printf ("Building inverse 16-to-8 table...\n");
+
+	Inverse16_BuildTable();
+
+	SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) );
+}
diff --git a/tools/quake2/qdata/video.c b/tools/quake2/qdata/video.c
index 1ed1b96c..370f5e95 100644
--- a/tools/quake2/qdata/video.c
+++ b/tools/quake2/qdata/video.c
@@ -1,1238 +1,1238 @@
-#include "qdata.h"
-#include "inout.h"
-
-byte	*soundtrack;
-char	base[32];
-
-/*
-===============================================================================
-
-WAV loading
-
-===============================================================================
-*/
-
-typedef struct
-{
-	int			rate;
-	int			width;
-	int			channels;
-	int			loopstart;
-	int			samples;
-	int			dataofs;		// chunk starts this many bytes from file start
-} wavinfo_t;
-
-
-byte	*data_p;
-byte 	*iff_end;
-byte 	*last_chunk;
-byte 	*iff_data;
-int 	iff_chunk_len;
-
-
-int		samplecounts[0x10000];
-
-wavinfo_t	wavinfo;
-
-short GetLittleShort(void)
-{
-	short val = 0;
-	val = *data_p;
-	val = val + (*(data_p+1)<<8);
-	data_p += 2;
-	return val;
-}
-
-int GetLittleLong(void)
-{
-	int val = 0;
-	val = *data_p;
-	val = val + (*(data_p+1)<<8);
-	val = val + (*(data_p+2)<<16);
-	val = val + (*(data_p+3)<<24);
-	data_p += 4;
-	return val;
-}
-
-void FindNextChunk(char *name)
-{
-	while (1)
-	{
-		data_p=last_chunk;
-
-		if (data_p >= iff_end)
-		{	// didn't find the chunk
-			data_p = NULL;
-			return;
-		}
-		
-		data_p += 4;
-		iff_chunk_len = GetLittleLong();
-		if (iff_chunk_len < 0)
-		{
-			data_p = NULL;
-			return;
-		}
-//		if (iff_chunk_len > 1024*1024)
-//			Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
-		data_p -= 8;
-		last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
-		if (!strncmp(data_p, name, 4))
-			return;
-	}
-}
-
-void FindChunk(char *name)
-{
-	last_chunk = iff_data;
-	FindNextChunk (name);
-}
-
-
-void DumpChunks(void)
-{
-	char	str[5];
-	
-	str[4] = 0;
-	data_p=iff_data;
-	do
-	{
-		memcpy (str, data_p, 4);
-		data_p += 4;
-		iff_chunk_len = GetLittleLong();
-		printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
-		data_p += (iff_chunk_len + 1) & ~1;
-	} while (data_p < iff_end);
-}
-
-/*
-============
-GetWavinfo
-============
-*/
-wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
-{
-	wavinfo_t	info;
-	int     i;
-	int     format;
-	int		samples;
-
-	memset (&info, 0, sizeof(info));
-
-	if (!wav)
-		return info;
-		
-	iff_data = wav;
-	iff_end = wav + wavlength;
-
-// find "RIFF" chunk
-	FindChunk("RIFF");
-	if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
-	{
-		printf("Missing RIFF/WAVE chunks\n");
-		return info;
-	}
-
-// get "fmt " chunk
-	iff_data = data_p + 12;
-// DumpChunks ();
-
-	FindChunk("fmt ");
-	if (!data_p)
-	{
-		printf("Missing fmt chunk\n");
-		return info;
-	}
-	data_p += 8;
-	format = GetLittleShort();
-	if (format != 1)
-	{
-		printf("Microsoft PCM format only\n");
-		return info;
-	}
-
-	info.channels = GetLittleShort();
-	info.rate = GetLittleLong();
-	data_p += 4+2;
-	info.width = GetLittleShort() / 8;
-
-// get cue chunk
-	FindChunk("cue ");
-	if (data_p)
-	{
-		data_p += 32;
-		info.loopstart = GetLittleLong();
-//		Com_Printf("loopstart=%d\n", sfx->loopstart);
-
-	// if the next chunk is a LIST chunk, look for a cue length marker
-		FindNextChunk ("LIST");
-		if (data_p)
-		{
-			if (!strncmp (data_p + 28, "mark", 4))
-			{	// this is not a proper parse, but it works with cooledit...
-				data_p += 24;
-				i = GetLittleLong ();	// samples in loop
-				info.samples = info.loopstart + i;
-			}
-		}
-	}
-	else
-		info.loopstart = -1;
-
-// find data chunk
-	FindChunk("data");
-	if (!data_p)
-	{
-		printf("Missing data chunk\n");
-		return info;
-	}
-
-	data_p += 4;
-	samples = GetLittleLong ();
-
-	if (info.samples)
-	{
-		if (samples < info.samples)
-			Error ("Sound %s has a bad loop length", name);
-	}
-	else
-		info.samples = samples;
-
-	info.dataofs = data_p - wav;
-
-	return info;
-}
-
-//=====================================================================
-
-/*
-==============
-LoadSoundtrack
-==============
-*/
-void LoadSoundtrack (void)
-{
-	char	name[1024];
-	FILE	*f;
-	int		len;
-	int     i, val, j;
-
-	soundtrack = NULL;
-	sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
-	printf ("%s\n", name);
-	f = fopen (name, "rb");
-	if (!f)
-	{
-		printf ("no soundtrack for %s\n", base);
-		return;
-	}
-	len = Q_filelength(f);
-	soundtrack = malloc(len);
-	fread (soundtrack, 1, len, f);
-	fclose (f);
-
-	wavinfo = GetWavinfo (name, soundtrack, len);
-
-	// count samples for compression
-	memset (samplecounts, 0, sizeof(samplecounts));
-
-	j = wavinfo.samples/2;
-	for (i=0 ; i<j ; i++)
-	{
-		val = ((unsigned short *)( soundtrack + wavinfo.dataofs))[i];
-		samplecounts[val]++;
-	}
-	val = 0;
-	for (i=0 ; i<0x10000 ; i++)
-		if (samplecounts[i])
-			val++;
-
-	printf ("%i unique sample values\n", val);
-}
-
-/*
-==================
-WriteSound
-==================
-*/
-void WriteSound (FILE *output, int frame)
-{
-	int		start, end;
-	int		count;
-	int		empty = 0;
-	int		i;
-	int		sample;
-	int		width;
-
-	width = wavinfo.width * wavinfo.channels;
-
-	start = frame*wavinfo.rate/14;
-	end = (frame+1)*wavinfo.rate/14;
-	count = end - start;
-
-	for (i=0 ; i<count ; i++)
-	{
-		sample = start+i;
-		if (sample > wavinfo.samples || !soundtrack)
-			fwrite (&empty, 1, width, output);
-		else
-			fwrite (soundtrack + wavinfo.dataofs + sample*width, 1, width,output);
-	}
-}
-
-//==========================================================================
-
-/*
-==================
-MTF
-==================
-*/
-cblock_t MTF (cblock_t in)
-{
-	int			i, j, b, code;
-	byte		*out_p;
-	int			index[256];
-	cblock_t	out;
-
-	out_p = out.data = malloc(in.count + 4);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	for (i=0 ; i<256 ; i++)
-		index[i] = i;
-
-	for (i=0 ; i<in.count ; i++)
-	{
-		b = in.data[i];
-		code = index[b];
-		*out_p++ = code;
-		
-		// shuffle b indexes to 0
-		for (j=0 ; j<256 ; j++)
-			if (index[j] < code)
-				index[j]++;
-		index[b] = 0;
-	}
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-
-//==========================================================================
-
-int		bwt_size;
-byte	*bwt_data;
-
-int bwtCompare (const void *elem1, const void *elem2)
-{
-	int		i;
-	int		i1, i2;
-	int		b1, b2;
-
-	i1 = *(int *)elem1;
-	i2 = *(int *)elem2;
-
-	for (i=0 ; i<bwt_size ; i++)
-	{
-		b1 = bwt_data[i1];
-		b2 = bwt_data[i2];
-		if (b1 < b2)
-			return -1;
-		if (b1 > b2)
-			return 1;
-		if (++i1 == bwt_size)
-			i1 = 0;
-		if (++i2 == bwt_size)
-			i2 = 0;
-	}
-
-	return 0;
-}
-
-/*
-==================
-BWT
-==================
-*/
-cblock_t BWT (cblock_t in)
-{
-	int		*sorted;
-	int		i;
-	byte	*out_p;
-	cblock_t	out;
-
-	bwt_size = in.count;
-	bwt_data = in.data;
-
-	sorted = malloc(in.count*sizeof(*sorted));
-	for (i=0 ; i<in.count ; i++)
-		sorted[i] = i;
-	qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
-
-	out_p = out.data = malloc(in.count + 8);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	// write head index
-	for (i=0 ; i<in.count ; i++)
-		if (sorted[i] == 0)
-			break;
-	*out_p++ = i&255;
-	*out_p++ = (i>>8)&255;
-	*out_p++ = (i>>16)&255;
-	*out_p++ = (i>>24)&255;
-
-	// write the L column
-	for (i=0 ; i<in.count ; i++)
-		*out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
-
-	free (sorted);
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-//==========================================================================
-
-typedef struct hnode_s
-{
-	int			count;
-	qboolean	used;
-	int			children[2];
-} hnode_t;
-
-int			numhnodes;
-hnode_t		hnodes[512];
-unsigned	charbits[256];
-int			charbitscount[256];
-
-int	SmallestNode (void)
-{
-	int		i;
-	int		best, bestnode;
-
-	best = 99999999;
-	bestnode = -1;
-	for (i=0 ; i<numhnodes ; i++)
-	{
-		if (hnodes[i].used)
-			continue;
-		if (!hnodes[i].count)
-			continue;
-		if (hnodes[i].count < best)
-		{
-			best = hnodes[i].count;
-			bestnode = i;
-		}
-	}
-
-	if (bestnode == -1)
-		return -1;
-
-	hnodes[bestnode].used = true;
-	return bestnode;
-}
-
-void BuildChars (int nodenum, unsigned bits, int bitcount)
-{
-	hnode_t	*node;
-
-	if (nodenum < 256)
-	{
-		if (bitcount > 32)
-			Error ("bitcount > 32");
-		charbits[nodenum] = bits;
-		charbitscount[nodenum] = bitcount;
-		return;
-	}
-
-	node = &hnodes[nodenum];
-	bits <<= 1;
-	BuildChars (node->children[0], bits, bitcount+1);
-	bits |= 1;
-	BuildChars (node->children[1], bits, bitcount+1);
-}
-
-
-/*
-==================
-Huffman
-==================
-*/
-cblock_t Huffman (cblock_t in)
-{
-	int			i;
-	hnode_t		*node;
-	int			outbits, c;
-	unsigned	bits;
-	byte		*out_p;
-	cblock_t	out;
-	int			max, maxchar;
-
-	// count
-	memset (hnodes, 0, sizeof(hnodes));
-	for (i=0 ; i<in.count ; i++)
-		hnodes[in.data[i]].count++;
-
-	// normalize counts
-	max = 0;
-	maxchar = 0;
-	for (i=0 ; i<256 ; i++)
-	{
-		if (hnodes[i].count > max)
-		{
-			max = hnodes[i].count;
-			maxchar = i;
-		}
-	}
-	if (max == 0)
-		Error ("Huffman: max == 0");
-
-	for (i=0 ; i<256 ; i++)
-	{
-		hnodes[i].count = (hnodes[i].count*255+max-1) / max;
-	}
-
-	// build the nodes
-	numhnodes = 256;
-	while (numhnodes != 511)
-	{
-		node = &hnodes[numhnodes];
-
-		// pick two lowest counts
-		node->children[0] = SmallestNode ();
-		if (node->children[0] == -1)
-			break;	// no more
-
-		node->children[1] = SmallestNode ();
-		if (node->children[1] == -1)
-		{
-			if (node->children[0] != numhnodes-1)
-				Error ("Bad smallestnode");
-			break;
-		}
-		node->count = hnodes[node->children[0]].count + 
-			hnodes[node->children[1]].count;
-		numhnodes++;
-	}
-
-	BuildChars (numhnodes-1, 0, 0);
-
-	out_p = out.data = malloc(in.count*2 + 1024);
-	memset (out_p, 0, in.count*2+1024);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	// save out the 256 normalized counts so the tree can be recreated
-	for (i=0 ; i<256 ; i++)
-		*out_p++ = hnodes[i].count;
-
-	// write bits
-	outbits = 0;
-	for (i=0 ; i<in.count ; i++)
-	{
-		c = charbitscount[in.data[i]];
-		bits = charbits[in.data[i]];
-		while (c)
-		{
-			c--;
-			if (bits & (1<<c))
-				out_p[outbits>>3] |= 1<<(outbits&7);
-			outbits++;
-		}
-	}
-
-	out_p += (outbits+7)>>3;
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-//==========================================================================
-
-/*
-==================
-RLE
-==================
-*/
-#define	RLE_CODE	0xe8
-#define	RLE_TRIPPLE	0xe9
-
-int	rle_counts[256];
-int	rle_bytes[256];
-
-cblock_t RLE (cblock_t in)
-{
-	int		i;
-	byte	*out_p;
-	int		val;
-	int		repeat;
-	cblock_t	out;
-
-	out_p = out.data = malloc (in.count*2);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	for (i=0 ; i<in.count ; )
-	{
-		val = in.data[i];
-		rle_bytes[val]++;
-		repeat = 1;
-		i++;
-		while (i<in.count && repeat < 255 && in.data[i] == val)
-		{
-			repeat++;
-			i++;
-		}
-if (repeat < 256)
-rle_counts[repeat]++;
-		if (repeat > 3 || val == RLE_CODE)
-		{
-			*out_p++ = RLE_CODE;
-			*out_p++ = val;
-			*out_p++ = repeat;
-		}
-		else
-		{
-			while (repeat--)
-				*out_p++ = val;
-		}
-	}
-
-	out.count = out_p - out.data;
-	return out;
-}
-
-//==========================================================================
-
-unsigned	lzss_head[256];
-unsigned	lzss_next[0x20000];
-
-/*
-==================
-LZSS
-==================
-*/
-#define	BACK_WINDOW		0x10000
-#define	BACK_BITS		16
-#define	FRONT_WINDOW	16
-#define	FRONT_BITS		4
-cblock_t LZSS (cblock_t in)
-{
-	int		i;
-	byte	*out_p;
-	cblock_t	out;
-	int		val;
-	int		j, start, max;
-	int		bestlength, beststart;
-	int		outbits;
-
-if (in.count >= sizeof(lzss_next)/4)
-Error ("LZSS: too big");
-
-	memset (lzss_head, -1, sizeof(lzss_head));
-
-	out_p = out.data = malloc (in.count*2);
-	memset (out.data, 0, in.count*2);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	outbits = 0;
-	for (i=0 ; i<in.count ; )
-	{
-		val = in.data[i];
-#if 1
-// chained search
-		bestlength = 0;
-		beststart = 0;
-
-		max = FRONT_WINDOW;
-		if (i + max > in.count)
-			max = in.count - i;
-
-		start = lzss_head[val];
-		while (start != -1 && start >= i-BACK_WINDOW)
-		{			
-			// count match length
-			for (j=0 ; j<max ; j++)
-				if (in.data[start+j] != in.data[i+j])
-					break;
-			if (j > bestlength)
-			{
-				bestlength = j;
-				beststart = start;
-			}
-			start = lzss_next[start];
-		}
-
-#else
-// slow simple search
-		// search for a match
-		max = FRONT_WINDOW;
-		if (i + max > in.count)
-			max = in.count - i;
-
-		start = i - BACK_WINDOW;
-		if (start < 0)
-			start = 0;
-		bestlength = 0;
-		beststart = 0;
-		for ( ; start < i ; start++)
-		{
-			if (in.data[start] != val)
-				continue;
-			// count match length
-			for (j=0 ; j<max ; j++)
-				if (in.data[start+j] != in.data[i+j])
-					break;
-			if (j > bestlength)
-			{
-				bestlength = j;
-				beststart = start;
-			}
-		}
-#endif
-		beststart = BACK_WINDOW - (i-beststart);
-
-		if (bestlength < 3)
-		{	// output a single char
-			bestlength = 1;
-
-			out_p[outbits>>3] |= 1<<(outbits&7);	// set bit to mark char
-			outbits++;
-			for (j=0 ; j<8 ; j++, outbits++)
-				if (val & (1<<j) )
-					out_p[outbits>>3] |= 1<<(outbits&7);
-		}
-		else
-		{	// output a phrase
-			outbits++;	// leave a 0 bit to mark phrase
-			for (j=0 ; j<BACK_BITS ; j++, outbits++)
-				if (beststart & (1<<j) )
-					out_p[outbits>>3] |= 1<<(outbits&7);
-			for (j=0 ; j<FRONT_BITS ; j++, outbits++)
-				if (bestlength & (1<<j) )
-					out_p[outbits>>3] |= 1<<(outbits&7);
-		}
-
-		while (bestlength--)
-		{
-			val = in.data[i];
-			lzss_next[i] = lzss_head[val];
-			lzss_head[val] = i;
-			i++;
-		}
-	}
-
-	out_p += (outbits+7)>>3;
-	out.count = out_p - out.data;
-	return out;
-}
-
-//==========================================================================
-
-#define	MIN_REPT	15
-#define	MAX_REPT	0
-#define	HUF_TOKENS	(256+MAX_REPT)
-
-unsigned	charbits1[256][HUF_TOKENS];
-int			charbitscount1[256][HUF_TOKENS];
-
-hnode_t		hnodes1[256][HUF_TOKENS*2];
-int			numhnodes1[256];
-
-int			order0counts[256];
-
-/*
-==================
-SmallestNode1
-==================
-*/
-int	SmallestNode1 (hnode_t *hnodes, int numhnodes)
-{
-	int		i;
-	int		best, bestnode;
-
-	best = 99999999;
-	bestnode = -1;
-	for (i=0 ; i<numhnodes ; i++)
-	{
-		if (hnodes[i].used)
-			continue;
-		if (!hnodes[i].count)
-			continue;
-		if (hnodes[i].count < best)
-		{
-			best = hnodes[i].count;
-			bestnode = i;
-		}
-	}
-
-	if (bestnode == -1)
-		return -1;
-
-	hnodes[bestnode].used = true;
-	return bestnode;
-}
-
-
-/*
-==================
-BuildChars1
-==================
-*/
-void BuildChars1 (int prev, int nodenum, unsigned bits, int bitcount)
-{
-	hnode_t	*node;
-
-	if (nodenum < HUF_TOKENS)
-	{
-		if (bitcount > 32)
-			Error ("bitcount > 32");
-		charbits1[prev][nodenum] = bits;
-		charbitscount1[prev][nodenum] = bitcount;
-		return;
-	}
-
-	node = &hnodes1[prev][nodenum];
-	bits <<= 1;
-	BuildChars1 (prev, node->children[0], bits, bitcount+1);
-	bits |= 1;
-	BuildChars1 (prev, node->children[1], bits, bitcount+1);
-}
-
-
-/*
-==================
-BuildTree1
-==================
-*/
-void BuildTree1 (int prev)
-{
-	hnode_t		*node, *nodebase;
-	int			numhnodes;
-
-	// build the nodes
-	numhnodes = HUF_TOKENS;
-	nodebase = hnodes1[prev];
-	while (1)
-	{
-		node = &nodebase[numhnodes];
-
-		// pick two lowest counts
-		node->children[0] = SmallestNode1 (nodebase, numhnodes);
-		if (node->children[0] == -1)
-			break;	// no more
-
-		node->children[1] = SmallestNode1 (nodebase, numhnodes);
-		if (node->children[1] == -1)
-			break;
-
-		node->count = nodebase[node->children[0]].count + 
-			nodebase[node->children[1]].count;
-		numhnodes++;
-	}
-	numhnodes1[prev] = numhnodes-1;
-	BuildChars1 (prev, numhnodes-1, 0, 0);
-}
-
-
-/*
-==================
-Huffman1_Count
-==================
-*/
-void Huffman1_Count (cblock_t in)
-{
-	int		i;
-	int		prev;
-	int		v;
-	int		rept;
-
-	prev = 0;
-	for (i=0 ; i<in.count ; i++)
-	{
-		v = in.data[i];
-		order0counts[v]++;
-		hnodes1[prev][v].count++;
-		prev = v;
-#if 1
-		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
-			if (in.data[i+rept] != v)
-				break;
-		if (rept > MIN_REPT)
-		{
-			hnodes1[prev][255+rept].count++;
-			i += rept-1;
-		}
-#endif
-	}
-}
-
-
-/*
-==================
-Huffman1_Build
-==================
-*/
-byte	scaled[256][HUF_TOKENS];
-void Huffman1_Build (FILE *f)
-{
-	int		i, j, v;
-	int		max;
-	int		total;
-
-	for (i=0 ; i<256 ; i++)
-	{
-		// normalize and save the counts
-		max = 0;
-		for (j=0 ; j<HUF_TOKENS ; j++)
-		{
-			if (hnodes1[i][j].count > max)
-				max = hnodes1[i][j].count;
-		}
-		if (max == 0)
-			max = 1;
-		total = 0;
-		for (j=0 ; j<HUF_TOKENS ; j++)
-		{	// easy to overflow 32 bits here!
-			v = (hnodes1[i][j].count*(double)255+max-1)/max;
-			if (v > 255)
-				Error ("v > 255");
-			scaled[i][j] = hnodes1[i][j].count = v;
-			if (v)
-				total++;
-		}
-		if (total == 1)
-		{	// must have two tokens
-			if (!scaled[i][0])
-				scaled[i][0] = hnodes1[i][0].count = 1;
-			else
-				scaled[i][1] = hnodes1[i][1].count = 1;
-		}
-
-		BuildTree1 (i);
-	}
-
-#if 0
-	// count up the total bits
-	total = 0;
-	for (i=0 ; i<256 ; i++)
-		for (j=0 ; j<256 ; j++)
-			total += charbitscount1[i][j] * hnodes1[i][j].count;
-
-	total = (total+7)/8;
-	printf ("%i bytes huffman1 compressed\n", total);
-#endif
-
-	fwrite (scaled, 1, sizeof(scaled), f);
-}
-
-/*
-==================
-Huffman1
-
-Order 1 compression with pre-built table
-==================
-*/
-cblock_t Huffman1 (cblock_t in)
-{
-	int			i;
-	int			outbits, c;
-	unsigned	bits;
-	byte		*out_p;
-	cblock_t	out;
-	int			prev;
-	int			v;
-	int			rept;
-
-	out_p = out.data = malloc(in.count*2 + 1024);
-	memset (out_p, 0, in.count*2+1024);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	// write bits
-	outbits = 0;
-	prev = 0;
-	for (i=0 ; i<in.count ; i++)
-	{
-		v = in.data[i];
-
-		c = charbitscount1[prev][v];
-		bits = charbits1[prev][v];
-		if (!c)
-			Error ("!bits");
-		while (c)
-		{
-			c--;
-			if (bits & (1<<c))
-				out_p[outbits>>3] |= 1<<(outbits&7);
-			outbits++;
-		}
-
-		prev = v;
-#if 1
-		// check for repeat encodes
-		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
-			if (in.data[i+rept] != v)
-				break;
-		if (rept > MIN_REPT)
-		{
-			c = charbitscount1[prev][255+rept];
-			bits = charbits1[prev][255+rept];
-			if (!c)
-				Error ("!bits");
-			while (c)
-			{
-				c--;
-				if (bits & (1<<c))
-					out_p[outbits>>3] |= 1<<(outbits&7);
-				outbits++;
-			}
-			i += rept-1;
-		}
-#endif
-	}
-
-	out_p += (outbits+7)>>3;
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-//==========================================================================
-
-
-/*
-===================
-LoadFrame
-===================
-*/
-cblock_t LoadFrame (char *base, int frame, int digits, byte **palette)
-{
-	int			ten3, ten2, ten1, ten0;
-	cblock_t	in;
-	int			width, height;
-	char		name[1024];
-	FILE		*f;
-
-	in.data = NULL;
-	in.count = -1;
-
-	ten3 = frame/1000;
-	ten2 = (frame-ten3*1000)/100;
-	ten1 = (frame-ten3*1000-ten2*100)/10;
-	ten0 = frame%10;
-
-	if (digits == 4)
-		sprintf (name, "%svideo/%s/%s%i%i%i%i.pcx", gamedir, base, base, ten3, ten2, ten1, ten0);
-	else
-		sprintf (name, "%svideo/%s/%s%i%i%i.pcx", gamedir, base, base, ten2, ten1, ten0);
-
-	f = fopen(name, "rb");
-	if (!f)
-	{
-		in.data = NULL;
-		return in;
-	}
-	fclose (f);
-
-	printf ("%s\n", name);
-	Load256Image (name, &in.data, palette, &width, &height);
-	in.count = width*height;
-// FIXME: map 0 and 255!
-
-#if 0
-	// rle compress
-	rle = RLE(in);
-	free (in.data);
-
-	return rle;
-#endif
-
-	return in;
-}
-
-/*
-===============
-Cmd_Video
-
-video <directory> <framedigits>
-===============
-*/
-void Cmd_Video (void)
-{
-	char	savename[1024];
-	char	name[1024];
-	FILE	*output;
-	int		startframe, frame;
-	byte	*palette;
-	int		width, height;
-	byte	current_palette[768];
-	int		command;
-	int		i;
-	int		digits;
-	cblock_t	in, huffman;
-	int		swap;
-
-
-	GetToken (false);
-	strcpy (base, token);
-	if (g_release)
-	{
-//		sprintf (savename, "video/%s.cin", token);
-//		ReleaseFile (savename);
-		return;
-	}
-
-	GetToken (false);
-	digits = atoi(token);
-
-	// optionally skip frames
-	if (TokenAvailable ())
-	{
-		GetToken (false);
-		startframe = atoi(token);
-	}
-	else
-		startframe=0;
-
-	sprintf (savename, "%svideo/%s.cin", gamedir, base);
-
-
-	// clear stuff
-	memset (charbits1, 0, sizeof(charbits1));
-	memset (charbitscount1, 0, sizeof(charbitscount1));
-	memset (hnodes1, 0, sizeof(hnodes1));
-	memset (numhnodes1, 0, sizeof(numhnodes1));
-	memset (order0counts, 0, sizeof(order0counts));
-
-
-	// load the entire sound wav file if present
-	LoadSoundtrack ();
-
-	if (digits == 4)
-		sprintf (name, "%svideo/%s/%s0000.pcx", gamedir, base, base);
-	else
-		sprintf (name, "%svideo/%s/%s000.pcx", gamedir, base, base);
-
-	printf ("%s\n", name);
-	Load256Image (name, NULL, &palette, &width, &height);
-
-	output = fopen (savename, "wb");
-	if (!output)
-		Error ("Can't open %s", savename);
-
-	// write header info
-	i = LittleLong (width);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (height);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (wavinfo.rate);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (wavinfo.width);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (wavinfo.channels);
-	fwrite (&i, 4, 1, output);
-
-	// build the dictionary
-	for ( frame=startframe ;  ; frame++)
-	{
-		printf ("counting ", frame);
-		in = LoadFrame (base, frame, digits, &palette);
-		if (!in.data)
-			break;
-		Huffman1_Count (in);
-		free (in.data);
-	}
-	printf ("\n");
-
-	// build nodes and write counts
-	Huffman1_Build (output);
-
-
-	memset (current_palette, 0, sizeof(current_palette));
-
-	// compress it with the dictionary
-	for (frame=startframe ;  ; frame++)
-	{
-		printf ("packing ", frame);
-		in = LoadFrame (base, frame, digits, &palette);
-		if (!in.data)
-			break;
-
-		// see if the palette has changed
-		for (i=0 ; i<768 ; i++)
-			if (palette[i] != current_palette[i])
-			{
-				// write a palette change
-				memcpy (current_palette, palette, sizeof(current_palette));
-				command = LittleLong(1);
-				fwrite (&command, 1, 4, output);
-				fwrite (current_palette, 1, sizeof(current_palette), output);
-				break;
-			}
-		if (i == 768)
-		{
-			command = 0;	// no palette change
-			fwrite (&command, 1, 4, output);
-		}
-
-		// save the image
-		huffman = Huffman1 (in);
-		printf ("%5i bytes after huffman1\n", huffman.count);
-
-		swap = LittleLong (huffman.count);
-		fwrite (&swap, 1, sizeof(swap), output);
-
-		fwrite (huffman.data, 1, huffman.count, output);
-
-		// save some sound samples
-		WriteSound (output, frame);
-
-		free (palette);
-		free (in.data);
-		free (huffman.data);
-	}
-	printf ("\n");
-
-	// write end-of-file command
-	command = 2;
-	fwrite (&command, 1, 4, output);
-
-	printf ("Total size: %i\n", ftell (output));
-
-	fclose (output);
-
-	if (soundtrack)
-		free (soundtrack);
-}
+#include "qdata.h"
+#include "inout.h"
+
+byte	*soundtrack;
+char	base[32];
+
+/*
+===============================================================================
+
+WAV loading
+
+===============================================================================
+*/
+
+typedef struct
+{
+	int			rate;
+	int			width;
+	int			channels;
+	int			loopstart;
+	int			samples;
+	int			dataofs;		// chunk starts this many bytes from file start
+} wavinfo_t;
+
+
+byte	*data_p;
+byte 	*iff_end;
+byte 	*last_chunk;
+byte 	*iff_data;
+int 	iff_chunk_len;
+
+
+int		samplecounts[0x10000];
+
+wavinfo_t	wavinfo;
+
+short GetLittleShort(void)
+{
+	short val = 0;
+	val = *data_p;
+	val = val + (*(data_p+1)<<8);
+	data_p += 2;
+	return val;
+}
+
+int GetLittleLong(void)
+{
+	int val = 0;
+	val = *data_p;
+	val = val + (*(data_p+1)<<8);
+	val = val + (*(data_p+2)<<16);
+	val = val + (*(data_p+3)<<24);
+	data_p += 4;
+	return val;
+}
+
+void FindNextChunk(char *name)
+{
+	while (1)
+	{
+		data_p=last_chunk;
+
+		if (data_p >= iff_end)
+		{	// didn't find the chunk
+			data_p = NULL;
+			return;
+		}
+		
+		data_p += 4;
+		iff_chunk_len = GetLittleLong();
+		if (iff_chunk_len < 0)
+		{
+			data_p = NULL;
+			return;
+		}
+//		if (iff_chunk_len > 1024*1024)
+//			Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
+		data_p -= 8;
+		last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
+		if (!strncmp(data_p, name, 4))
+			return;
+	}
+}
+
+void FindChunk(char *name)
+{
+	last_chunk = iff_data;
+	FindNextChunk (name);
+}
+
+
+void DumpChunks(void)
+{
+	char	str[5];
+	
+	str[4] = 0;
+	data_p=iff_data;
+	do
+	{
+		memcpy (str, data_p, 4);
+		data_p += 4;
+		iff_chunk_len = GetLittleLong();
+		printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
+		data_p += (iff_chunk_len + 1) & ~1;
+	} while (data_p < iff_end);
+}
+
+/*
+============
+GetWavinfo
+============
+*/
+wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
+{
+	wavinfo_t	info;
+	int     i;
+	int     format;
+	int		samples;
+
+	memset (&info, 0, sizeof(info));
+
+	if (!wav)
+		return info;
+		
+	iff_data = wav;
+	iff_end = wav + wavlength;
+
+// find "RIFF" chunk
+	FindChunk("RIFF");
+	if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
+	{
+		printf("Missing RIFF/WAVE chunks\n");
+		return info;
+	}
+
+// get "fmt " chunk
+	iff_data = data_p + 12;
+// DumpChunks ();
+
+	FindChunk("fmt ");
+	if (!data_p)
+	{
+		printf("Missing fmt chunk\n");
+		return info;
+	}
+	data_p += 8;
+	format = GetLittleShort();
+	if (format != 1)
+	{
+		printf("Microsoft PCM format only\n");
+		return info;
+	}
+
+	info.channels = GetLittleShort();
+	info.rate = GetLittleLong();
+	data_p += 4+2;
+	info.width = GetLittleShort() / 8;
+
+// get cue chunk
+	FindChunk("cue ");
+	if (data_p)
+	{
+		data_p += 32;
+		info.loopstart = GetLittleLong();
+//		Com_Printf("loopstart=%d\n", sfx->loopstart);
+
+	// if the next chunk is a LIST chunk, look for a cue length marker
+		FindNextChunk ("LIST");
+		if (data_p)
+		{
+			if (!strncmp (data_p + 28, "mark", 4))
+			{	// this is not a proper parse, but it works with cooledit...
+				data_p += 24;
+				i = GetLittleLong ();	// samples in loop
+				info.samples = info.loopstart + i;
+			}
+		}
+	}
+	else
+		info.loopstart = -1;
+
+// find data chunk
+	FindChunk("data");
+	if (!data_p)
+	{
+		printf("Missing data chunk\n");
+		return info;
+	}
+
+	data_p += 4;
+	samples = GetLittleLong ();
+
+	if (info.samples)
+	{
+		if (samples < info.samples)
+			Error ("Sound %s has a bad loop length", name);
+	}
+	else
+		info.samples = samples;
+
+	info.dataofs = data_p - wav;
+
+	return info;
+}
+
+//=====================================================================
+
+/*
+==============
+LoadSoundtrack
+==============
+*/
+void LoadSoundtrack (void)
+{
+	char	name[1024];
+	FILE	*f;
+	int		len;
+	int     i, val, j;
+
+	soundtrack = NULL;
+	sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
+	printf ("%s\n", name);
+	f = fopen (name, "rb");
+	if (!f)
+	{
+		printf ("no soundtrack for %s\n", base);
+		return;
+	}
+	len = Q_filelength(f);
+	soundtrack = malloc(len);
+	fread (soundtrack, 1, len, f);
+	fclose (f);
+
+	wavinfo = GetWavinfo (name, soundtrack, len);
+
+	// count samples for compression
+	memset (samplecounts, 0, sizeof(samplecounts));
+
+	j = wavinfo.samples/2;
+	for (i=0 ; i<j ; i++)
+	{
+		val = ((unsigned short *)( soundtrack + wavinfo.dataofs))[i];
+		samplecounts[val]++;
+	}
+	val = 0;
+	for (i=0 ; i<0x10000 ; i++)
+		if (samplecounts[i])
+			val++;
+
+	printf ("%i unique sample values\n", val);
+}
+
+/*
+==================
+WriteSound
+==================
+*/
+void WriteSound (FILE *output, int frame)
+{
+	int		start, end;
+	int		count;
+	int		empty = 0;
+	int		i;
+	int		sample;
+	int		width;
+
+	width = wavinfo.width * wavinfo.channels;
+
+	start = frame*wavinfo.rate/14;
+	end = (frame+1)*wavinfo.rate/14;
+	count = end - start;
+
+	for (i=0 ; i<count ; i++)
+	{
+		sample = start+i;
+		if (sample > wavinfo.samples || !soundtrack)
+			fwrite (&empty, 1, width, output);
+		else
+			fwrite (soundtrack + wavinfo.dataofs + sample*width, 1, width,output);
+	}
+}
+
+//==========================================================================
+
+/*
+==================
+MTF
+==================
+*/
+cblock_t MTF (cblock_t in)
+{
+	int			i, j, b, code;
+	byte		*out_p;
+	int			index[256];
+	cblock_t	out;
+
+	out_p = out.data = malloc(in.count + 4);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	for (i=0 ; i<256 ; i++)
+		index[i] = i;
+
+	for (i=0 ; i<in.count ; i++)
+	{
+		b = in.data[i];
+		code = index[b];
+		*out_p++ = code;
+		
+		// shuffle b indexes to 0
+		for (j=0 ; j<256 ; j++)
+			if (index[j] < code)
+				index[j]++;
+		index[b] = 0;
+	}
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+
+//==========================================================================
+
+int		bwt_size;
+byte	*bwt_data;
+
+int bwtCompare (const void *elem1, const void *elem2)
+{
+	int		i;
+	int		i1, i2;
+	int		b1, b2;
+
+	i1 = *(int *)elem1;
+	i2 = *(int *)elem2;
+
+	for (i=0 ; i<bwt_size ; i++)
+	{
+		b1 = bwt_data[i1];
+		b2 = bwt_data[i2];
+		if (b1 < b2)
+			return -1;
+		if (b1 > b2)
+			return 1;
+		if (++i1 == bwt_size)
+			i1 = 0;
+		if (++i2 == bwt_size)
+			i2 = 0;
+	}
+
+	return 0;
+}
+
+/*
+==================
+BWT
+==================
+*/
+cblock_t BWT (cblock_t in)
+{
+	int		*sorted;
+	int		i;
+	byte	*out_p;
+	cblock_t	out;
+
+	bwt_size = in.count;
+	bwt_data = in.data;
+
+	sorted = malloc(in.count*sizeof(*sorted));
+	for (i=0 ; i<in.count ; i++)
+		sorted[i] = i;
+	qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
+
+	out_p = out.data = malloc(in.count + 8);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	// write head index
+	for (i=0 ; i<in.count ; i++)
+		if (sorted[i] == 0)
+			break;
+	*out_p++ = i&255;
+	*out_p++ = (i>>8)&255;
+	*out_p++ = (i>>16)&255;
+	*out_p++ = (i>>24)&255;
+
+	// write the L column
+	for (i=0 ; i<in.count ; i++)
+		*out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
+
+	free (sorted);
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+//==========================================================================
+
+typedef struct hnode_s
+{
+	int			count;
+	qboolean	used;
+	int			children[2];
+} hnode_t;
+
+int			numhnodes;
+hnode_t		hnodes[512];
+unsigned	charbits[256];
+int			charbitscount[256];
+
+int	SmallestNode (void)
+{
+	int		i;
+	int		best, bestnode;
+
+	best = 99999999;
+	bestnode = -1;
+	for (i=0 ; i<numhnodes ; i++)
+	{
+		if (hnodes[i].used)
+			continue;
+		if (!hnodes[i].count)
+			continue;
+		if (hnodes[i].count < best)
+		{
+			best = hnodes[i].count;
+			bestnode = i;
+		}
+	}
+
+	if (bestnode == -1)
+		return -1;
+
+	hnodes[bestnode].used = true;
+	return bestnode;
+}
+
+void BuildChars (int nodenum, unsigned bits, int bitcount)
+{
+	hnode_t	*node;
+
+	if (nodenum < 256)
+	{
+		if (bitcount > 32)
+			Error ("bitcount > 32");
+		charbits[nodenum] = bits;
+		charbitscount[nodenum] = bitcount;
+		return;
+	}
+
+	node = &hnodes[nodenum];
+	bits <<= 1;
+	BuildChars (node->children[0], bits, bitcount+1);
+	bits |= 1;
+	BuildChars (node->children[1], bits, bitcount+1);
+}
+
+
+/*
+==================
+Huffman
+==================
+*/
+cblock_t Huffman (cblock_t in)
+{
+	int			i;
+	hnode_t		*node;
+	int			outbits, c;
+	unsigned	bits;
+	byte		*out_p;
+	cblock_t	out;
+	int			max, maxchar;
+
+	// count
+	memset (hnodes, 0, sizeof(hnodes));
+	for (i=0 ; i<in.count ; i++)
+		hnodes[in.data[i]].count++;
+
+	// normalize counts
+	max = 0;
+	maxchar = 0;
+	for (i=0 ; i<256 ; i++)
+	{
+		if (hnodes[i].count > max)
+		{
+			max = hnodes[i].count;
+			maxchar = i;
+		}
+	}
+	if (max == 0)
+		Error ("Huffman: max == 0");
+
+	for (i=0 ; i<256 ; i++)
+	{
+		hnodes[i].count = (hnodes[i].count*255+max-1) / max;
+	}
+
+	// build the nodes
+	numhnodes = 256;
+	while (numhnodes != 511)
+	{
+		node = &hnodes[numhnodes];
+
+		// pick two lowest counts
+		node->children[0] = SmallestNode ();
+		if (node->children[0] == -1)
+			break;	// no more
+
+		node->children[1] = SmallestNode ();
+		if (node->children[1] == -1)
+		{
+			if (node->children[0] != numhnodes-1)
+				Error ("Bad smallestnode");
+			break;
+		}
+		node->count = hnodes[node->children[0]].count + 
+			hnodes[node->children[1]].count;
+		numhnodes++;
+	}
+
+	BuildChars (numhnodes-1, 0, 0);
+
+	out_p = out.data = malloc(in.count*2 + 1024);
+	memset (out_p, 0, in.count*2+1024);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	// save out the 256 normalized counts so the tree can be recreated
+	for (i=0 ; i<256 ; i++)
+		*out_p++ = hnodes[i].count;
+
+	// write bits
+	outbits = 0;
+	for (i=0 ; i<in.count ; i++)
+	{
+		c = charbitscount[in.data[i]];
+		bits = charbits[in.data[i]];
+		while (c)
+		{
+			c--;
+			if (bits & (1<<c))
+				out_p[outbits>>3] |= 1<<(outbits&7);
+			outbits++;
+		}
+	}
+
+	out_p += (outbits+7)>>3;
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+//==========================================================================
+
+/*
+==================
+RLE
+==================
+*/
+#define	RLE_CODE	0xe8
+#define	RLE_TRIPPLE	0xe9
+
+int	rle_counts[256];
+int	rle_bytes[256];
+
+cblock_t RLE (cblock_t in)
+{
+	int		i;
+	byte	*out_p;
+	int		val;
+	int		repeat;
+	cblock_t	out;
+
+	out_p = out.data = malloc (in.count*2);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	for (i=0 ; i<in.count ; )
+	{
+		val = in.data[i];
+		rle_bytes[val]++;
+		repeat = 1;
+		i++;
+		while (i<in.count && repeat < 255 && in.data[i] == val)
+		{
+			repeat++;
+			i++;
+		}
+if (repeat < 256)
+rle_counts[repeat]++;
+		if (repeat > 3 || val == RLE_CODE)
+		{
+			*out_p++ = RLE_CODE;
+			*out_p++ = val;
+			*out_p++ = repeat;
+		}
+		else
+		{
+			while (repeat--)
+				*out_p++ = val;
+		}
+	}
+
+	out.count = out_p - out.data;
+	return out;
+}
+
+//==========================================================================
+
+unsigned	lzss_head[256];
+unsigned	lzss_next[0x20000];
+
+/*
+==================
+LZSS
+==================
+*/
+#define	BACK_WINDOW		0x10000
+#define	BACK_BITS		16
+#define	FRONT_WINDOW	16
+#define	FRONT_BITS		4
+cblock_t LZSS (cblock_t in)
+{
+	int		i;
+	byte	*out_p;
+	cblock_t	out;
+	int		val;
+	int		j, start, max;
+	int		bestlength, beststart;
+	int		outbits;
+
+if (in.count >= sizeof(lzss_next)/4)
+Error ("LZSS: too big");
+
+	memset (lzss_head, -1, sizeof(lzss_head));
+
+	out_p = out.data = malloc (in.count*2);
+	memset (out.data, 0, in.count*2);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	outbits = 0;
+	for (i=0 ; i<in.count ; )
+	{
+		val = in.data[i];
+#if 1
+// chained search
+		bestlength = 0;
+		beststart = 0;
+
+		max = FRONT_WINDOW;
+		if (i + max > in.count)
+			max = in.count - i;
+
+		start = lzss_head[val];
+		while (start != -1 && start >= i-BACK_WINDOW)
+		{			
+			// count match length
+			for (j=0 ; j<max ; j++)
+				if (in.data[start+j] != in.data[i+j])
+					break;
+			if (j > bestlength)
+			{
+				bestlength = j;
+				beststart = start;
+			}
+			start = lzss_next[start];
+		}
+
+#else
+// slow simple search
+		// search for a match
+		max = FRONT_WINDOW;
+		if (i + max > in.count)
+			max = in.count - i;
+
+		start = i - BACK_WINDOW;
+		if (start < 0)
+			start = 0;
+		bestlength = 0;
+		beststart = 0;
+		for ( ; start < i ; start++)
+		{
+			if (in.data[start] != val)
+				continue;
+			// count match length
+			for (j=0 ; j<max ; j++)
+				if (in.data[start+j] != in.data[i+j])
+					break;
+			if (j > bestlength)
+			{
+				bestlength = j;
+				beststart = start;
+			}
+		}
+#endif
+		beststart = BACK_WINDOW - (i-beststart);
+
+		if (bestlength < 3)
+		{	// output a single char
+			bestlength = 1;
+
+			out_p[outbits>>3] |= 1<<(outbits&7);	// set bit to mark char
+			outbits++;
+			for (j=0 ; j<8 ; j++, outbits++)
+				if (val & (1<<j) )
+					out_p[outbits>>3] |= 1<<(outbits&7);
+		}
+		else
+		{	// output a phrase
+			outbits++;	// leave a 0 bit to mark phrase
+			for (j=0 ; j<BACK_BITS ; j++, outbits++)
+				if (beststart & (1<<j) )
+					out_p[outbits>>3] |= 1<<(outbits&7);
+			for (j=0 ; j<FRONT_BITS ; j++, outbits++)
+				if (bestlength & (1<<j) )
+					out_p[outbits>>3] |= 1<<(outbits&7);
+		}
+
+		while (bestlength--)
+		{
+			val = in.data[i];
+			lzss_next[i] = lzss_head[val];
+			lzss_head[val] = i;
+			i++;
+		}
+	}
+
+	out_p += (outbits+7)>>3;
+	out.count = out_p - out.data;
+	return out;
+}
+
+//==========================================================================
+
+#define	MIN_REPT	15
+#define	MAX_REPT	0
+#define	HUF_TOKENS	(256+MAX_REPT)
+
+unsigned	charbits1[256][HUF_TOKENS];
+int			charbitscount1[256][HUF_TOKENS];
+
+hnode_t		hnodes1[256][HUF_TOKENS*2];
+int			numhnodes1[256];
+
+int			order0counts[256];
+
+/*
+==================
+SmallestNode1
+==================
+*/
+int	SmallestNode1 (hnode_t *hnodes, int numhnodes)
+{
+	int		i;
+	int		best, bestnode;
+
+	best = 99999999;
+	bestnode = -1;
+	for (i=0 ; i<numhnodes ; i++)
+	{
+		if (hnodes[i].used)
+			continue;
+		if (!hnodes[i].count)
+			continue;
+		if (hnodes[i].count < best)
+		{
+			best = hnodes[i].count;
+			bestnode = i;
+		}
+	}
+
+	if (bestnode == -1)
+		return -1;
+
+	hnodes[bestnode].used = true;
+	return bestnode;
+}
+
+
+/*
+==================
+BuildChars1
+==================
+*/
+void BuildChars1 (int prev, int nodenum, unsigned bits, int bitcount)
+{
+	hnode_t	*node;
+
+	if (nodenum < HUF_TOKENS)
+	{
+		if (bitcount > 32)
+			Error ("bitcount > 32");
+		charbits1[prev][nodenum] = bits;
+		charbitscount1[prev][nodenum] = bitcount;
+		return;
+	}
+
+	node = &hnodes1[prev][nodenum];
+	bits <<= 1;
+	BuildChars1 (prev, node->children[0], bits, bitcount+1);
+	bits |= 1;
+	BuildChars1 (prev, node->children[1], bits, bitcount+1);
+}
+
+
+/*
+==================
+BuildTree1
+==================
+*/
+void BuildTree1 (int prev)
+{
+	hnode_t		*node, *nodebase;
+	int			numhnodes;
+
+	// build the nodes
+	numhnodes = HUF_TOKENS;
+	nodebase = hnodes1[prev];
+	while (1)
+	{
+		node = &nodebase[numhnodes];
+
+		// pick two lowest counts
+		node->children[0] = SmallestNode1 (nodebase, numhnodes);
+		if (node->children[0] == -1)
+			break;	// no more
+
+		node->children[1] = SmallestNode1 (nodebase, numhnodes);
+		if (node->children[1] == -1)
+			break;
+
+		node->count = nodebase[node->children[0]].count + 
+			nodebase[node->children[1]].count;
+		numhnodes++;
+	}
+	numhnodes1[prev] = numhnodes-1;
+	BuildChars1 (prev, numhnodes-1, 0, 0);
+}
+
+
+/*
+==================
+Huffman1_Count
+==================
+*/
+void Huffman1_Count (cblock_t in)
+{
+	int		i;
+	int		prev;
+	int		v;
+	int		rept;
+
+	prev = 0;
+	for (i=0 ; i<in.count ; i++)
+	{
+		v = in.data[i];
+		order0counts[v]++;
+		hnodes1[prev][v].count++;
+		prev = v;
+#if 1
+		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
+			if (in.data[i+rept] != v)
+				break;
+		if (rept > MIN_REPT)
+		{
+			hnodes1[prev][255+rept].count++;
+			i += rept-1;
+		}
+#endif
+	}
+}
+
+
+/*
+==================
+Huffman1_Build
+==================
+*/
+byte	scaled[256][HUF_TOKENS];
+void Huffman1_Build (FILE *f)
+{
+	int		i, j, v;
+	int		max;
+	int		total;
+
+	for (i=0 ; i<256 ; i++)
+	{
+		// normalize and save the counts
+		max = 0;
+		for (j=0 ; j<HUF_TOKENS ; j++)
+		{
+			if (hnodes1[i][j].count > max)
+				max = hnodes1[i][j].count;
+		}
+		if (max == 0)
+			max = 1;
+		total = 0;
+		for (j=0 ; j<HUF_TOKENS ; j++)
+		{	// easy to overflow 32 bits here!
+			v = (hnodes1[i][j].count*(double)255+max-1)/max;
+			if (v > 255)
+				Error ("v > 255");
+			scaled[i][j] = hnodes1[i][j].count = v;
+			if (v)
+				total++;
+		}
+		if (total == 1)
+		{	// must have two tokens
+			if (!scaled[i][0])
+				scaled[i][0] = hnodes1[i][0].count = 1;
+			else
+				scaled[i][1] = hnodes1[i][1].count = 1;
+		}
+
+		BuildTree1 (i);
+	}
+
+#if 0
+	// count up the total bits
+	total = 0;
+	for (i=0 ; i<256 ; i++)
+		for (j=0 ; j<256 ; j++)
+			total += charbitscount1[i][j] * hnodes1[i][j].count;
+
+	total = (total+7)/8;
+	printf ("%i bytes huffman1 compressed\n", total);
+#endif
+
+	fwrite (scaled, 1, sizeof(scaled), f);
+}
+
+/*
+==================
+Huffman1
+
+Order 1 compression with pre-built table
+==================
+*/
+cblock_t Huffman1 (cblock_t in)
+{
+	int			i;
+	int			outbits, c;
+	unsigned	bits;
+	byte		*out_p;
+	cblock_t	out;
+	int			prev;
+	int			v;
+	int			rept;
+
+	out_p = out.data = malloc(in.count*2 + 1024);
+	memset (out_p, 0, in.count*2+1024);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	// write bits
+	outbits = 0;
+	prev = 0;
+	for (i=0 ; i<in.count ; i++)
+	{
+		v = in.data[i];
+
+		c = charbitscount1[prev][v];
+		bits = charbits1[prev][v];
+		if (!c)
+			Error ("!bits");
+		while (c)
+		{
+			c--;
+			if (bits & (1<<c))
+				out_p[outbits>>3] |= 1<<(outbits&7);
+			outbits++;
+		}
+
+		prev = v;
+#if 1
+		// check for repeat encodes
+		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
+			if (in.data[i+rept] != v)
+				break;
+		if (rept > MIN_REPT)
+		{
+			c = charbitscount1[prev][255+rept];
+			bits = charbits1[prev][255+rept];
+			if (!c)
+				Error ("!bits");
+			while (c)
+			{
+				c--;
+				if (bits & (1<<c))
+					out_p[outbits>>3] |= 1<<(outbits&7);
+				outbits++;
+			}
+			i += rept-1;
+		}
+#endif
+	}
+
+	out_p += (outbits+7)>>3;
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+//==========================================================================
+
+
+/*
+===================
+LoadFrame
+===================
+*/
+cblock_t LoadFrame (char *base, int frame, int digits, byte **palette)
+{
+	int			ten3, ten2, ten1, ten0;
+	cblock_t	in;
+	int			width, height;
+	char		name[1024];
+	FILE		*f;
+
+	in.data = NULL;
+	in.count = -1;
+
+	ten3 = frame/1000;
+	ten2 = (frame-ten3*1000)/100;
+	ten1 = (frame-ten3*1000-ten2*100)/10;
+	ten0 = frame%10;
+
+	if (digits == 4)
+		sprintf (name, "%svideo/%s/%s%i%i%i%i.pcx", gamedir, base, base, ten3, ten2, ten1, ten0);
+	else
+		sprintf (name, "%svideo/%s/%s%i%i%i.pcx", gamedir, base, base, ten2, ten1, ten0);
+
+	f = fopen(name, "rb");
+	if (!f)
+	{
+		in.data = NULL;
+		return in;
+	}
+	fclose (f);
+
+	printf ("%s\n", name);
+	Load256Image (name, &in.data, palette, &width, &height);
+	in.count = width*height;
+// FIXME: map 0 and 255!
+
+#if 0
+	// rle compress
+	rle = RLE(in);
+	free (in.data);
+
+	return rle;
+#endif
+
+	return in;
+}
+
+/*
+===============
+Cmd_Video
+
+video <directory> <framedigits>
+===============
+*/
+void Cmd_Video (void)
+{
+	char	savename[1024];
+	char	name[1024];
+	FILE	*output;
+	int		startframe, frame;
+	byte	*palette;
+	int		width, height;
+	byte	current_palette[768];
+	int		command;
+	int		i;
+	int		digits;
+	cblock_t	in, huffman;
+	int		swap;
+
+
+	GetToken (false);
+	strcpy (base, token);
+	if (g_release)
+	{
+//		sprintf (savename, "video/%s.cin", token);
+//		ReleaseFile (savename);
+		return;
+	}
+
+	GetToken (false);
+	digits = atoi(token);
+
+	// optionally skip frames
+	if (TokenAvailable ())
+	{
+		GetToken (false);
+		startframe = atoi(token);
+	}
+	else
+		startframe=0;
+
+	sprintf (savename, "%svideo/%s.cin", gamedir, base);
+
+
+	// clear stuff
+	memset (charbits1, 0, sizeof(charbits1));
+	memset (charbitscount1, 0, sizeof(charbitscount1));
+	memset (hnodes1, 0, sizeof(hnodes1));
+	memset (numhnodes1, 0, sizeof(numhnodes1));
+	memset (order0counts, 0, sizeof(order0counts));
+
+
+	// load the entire sound wav file if present
+	LoadSoundtrack ();
+
+	if (digits == 4)
+		sprintf (name, "%svideo/%s/%s0000.pcx", gamedir, base, base);
+	else
+		sprintf (name, "%svideo/%s/%s000.pcx", gamedir, base, base);
+
+	printf ("%s\n", name);
+	Load256Image (name, NULL, &palette, &width, &height);
+
+	output = fopen (savename, "wb");
+	if (!output)
+		Error ("Can't open %s", savename);
+
+	// write header info
+	i = LittleLong (width);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (height);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (wavinfo.rate);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (wavinfo.width);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (wavinfo.channels);
+	fwrite (&i, 4, 1, output);
+
+	// build the dictionary
+	for ( frame=startframe ;  ; frame++)
+	{
+		printf ("counting ", frame);
+		in = LoadFrame (base, frame, digits, &palette);
+		if (!in.data)
+			break;
+		Huffman1_Count (in);
+		free (in.data);
+	}
+	printf ("\n");
+
+	// build nodes and write counts
+	Huffman1_Build (output);
+
+
+	memset (current_palette, 0, sizeof(current_palette));
+
+	// compress it with the dictionary
+	for (frame=startframe ;  ; frame++)
+	{
+		printf ("packing ", frame);
+		in = LoadFrame (base, frame, digits, &palette);
+		if (!in.data)
+			break;
+
+		// see if the palette has changed
+		for (i=0 ; i<768 ; i++)
+			if (palette[i] != current_palette[i])
+			{
+				// write a palette change
+				memcpy (current_palette, palette, sizeof(current_palette));
+				command = LittleLong(1);
+				fwrite (&command, 1, 4, output);
+				fwrite (current_palette, 1, sizeof(current_palette), output);
+				break;
+			}
+		if (i == 768)
+		{
+			command = 0;	// no palette change
+			fwrite (&command, 1, 4, output);
+		}
+
+		// save the image
+		huffman = Huffman1 (in);
+		printf ("%5i bytes after huffman1\n", huffman.count);
+
+		swap = LittleLong (huffman.count);
+		fwrite (&swap, 1, sizeof(swap), output);
+
+		fwrite (huffman.data, 1, huffman.count, output);
+
+		// save some sound samples
+		WriteSound (output, frame);
+
+		free (palette);
+		free (in.data);
+		free (huffman.data);
+	}
+	printf ("\n");
+
+	// write end-of-file command
+	command = 2;
+	fwrite (&command, 1, 4, output);
+
+	printf ("Total size: %i\n", ftell (output));
+
+	fclose (output);
+
+	if (soundtrack)
+		free (soundtrack);
+}
diff --git a/tools/quake2/qdata_heretic2/adpcm.h b/tools/quake2/qdata_heretic2/adpcm.h
index e4e8b5dc..3698da9a 100644
--- a/tools/quake2/qdata_heretic2/adpcm.h
+++ b/tools/quake2/qdata_heretic2/adpcm.h
@@ -1,49 +1,49 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-** adpcm.h - include file for adpcm coder.
-**
-** Version 1.0, 7-Jul-92.
-** 
-** Modded 10/3/98
-** John Scott
-*/
-
-typedef struct adpcm_state_s
-{
-    short	in_valprev;			// Previous output value
-    short	in_index;	 		// Index into stepsize table
-    short	out_valprev; 		// Previous output value
-    short	out_index;			// Index into stepsize table
-	int		count;				// Number of sample counts
-}	adpcm_state_t;
-
-typedef struct adpcm_s
-{
-	adpcm_state_t	state;
-	char			adpcm[0x10000];			
-}	adpcm_t;
-
-void adpcm_coder(short [], adpcm_t *);
-void adpcm_decoder(adpcm_t *, short []);
-
-// end
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+** adpcm.h - include file for adpcm coder.
+**
+** Version 1.0, 7-Jul-92.
+** 
+** Modded 10/3/98
+** John Scott
+*/
+
+typedef struct adpcm_state_s
+{
+    short	in_valprev;			// Previous output value
+    short	in_index;	 		// Index into stepsize table
+    short	out_valprev; 		// Previous output value
+    short	out_index;			// Index into stepsize table
+	int		count;				// Number of sample counts
+}	adpcm_state_t;
+
+typedef struct adpcm_s
+{
+	adpcm_state_t	state;
+	char			adpcm[0x10000];			
+}	adpcm_t;
+
+void adpcm_coder(short [], adpcm_t *);
+void adpcm_decoder(adpcm_t *, short []);
+
+// end
diff --git a/tools/quake2/qdata_heretic2/animcomp.c b/tools/quake2/qdata_heretic2/animcomp.c
index 7e0c96d1..c32b7bf6 100644
--- a/tools/quake2/qdata_heretic2/animcomp.c
+++ b/tools/quake2/qdata_heretic2/animcomp.c
@@ -1,351 +1,351 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <memory.h>
-#include "animcomp.h"
-
-
-void	*SafeMalloc(size_t n, char *desc);
-
-
-
-float *matrix;
-float *delta;
-float *best;
-float *comp;
-float *tcomp;
-float *bestcomp;
-float *frames;
-float *base;
-
-int MatWidth;
-int MatHeight;
-int CFrameSize;
-int nFrames;
-
-
-void AnimCompressInit(int nframes,int nVerts,int CompressedFrameSize)
-{
-	nFrames=nframes;
-	MatWidth=nVerts*3;
-	MatHeight=CompressedFrameSize;
-	CFrameSize=CompressedFrameSize;
-	matrix=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
-	best=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
-	delta=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
-	comp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
-	tcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
-	bestcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
-	base=(float *)SafeMalloc(MatWidth*sizeof(float), "AnimCompressInit");
-	frames=(float *)SafeMalloc(MatWidth*nFrames*sizeof(float), "AnimCompressInit");
-}
-
-void AnimSetFrame(int frame,int index,float x,float y,float z)
-{
-	frames[frame*MatWidth+index*3]=x;
-	frames[frame*MatWidth+index*3+1]=y;
-	frames[frame*MatWidth+index*3+2]=z;
-}
-
-typedef struct 
-{
-	int index;
-	float val;
-} SORTP;
-
-
-#define F_RANDOM (((float)rand())/(float)RAND_MAX)
-
-extern void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize);
-
-void AnimCompressDoit()
-{
-	float compression;
-	float *rescale;
-	float *ans;
-	float maxdev;
-	float avedev;
-	float tmp;
-	int j,k,l,numave;
-
-	for (k=0;k<MatWidth;k++)
-		base[k]=0.0f;
-	for (j=0;j<nFrames;j++)
-		for (k=0;k<MatWidth;k++)
-			base[k]+=frames[j*MatWidth+k];
-	tmp=1.0f/(float)nFrames;
-	for (k=0;k<MatWidth;k++)
-		base[k]*=tmp;
-	for (j=0;j<nFrames;j++)
-		for (k=0;k<MatWidth;k++)
-			frames[j*MatWidth+k]-=base[k];
-
-	ans=(float *)SafeMalloc(sizeof(float)*MatWidth, "AnimCompressDoit");
-	rescale=(float *)SafeMalloc(sizeof(float)*CFrameSize, "AnimCompressDoit");
-	DOsvd(frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight);
-	avedev=0.0;
-	for (l=0;l<CFrameSize;l++)
-		avedev+=rescale[l];
-	for (l=0;l<CFrameSize;l++)
-		printf("%3.1f ",100.0f*rescale[l]/avedev);
-	printf("\n");
-	for (j=0;j<nFrames;j++)
-	{
-		for (l=0;l<CFrameSize;l++)
-		{
-			bestcomp[j*CFrameSize+l]=0.0;
-			for (k=0;k<MatWidth;k++)
-				bestcomp[j*CFrameSize+l]+=best[l*MatWidth+k]*frames[j*MatWidth+k];
-		}
-	}
-	numave=0;
-	avedev=0.0;
-	maxdev=0.0;
-	for (j=0;j<nFrames;j++)
-	{
-		for (k=0;k<MatWidth;k++)
-		{
-			ans[k]=0.0;
-			for (l=0;l<CFrameSize;l++)
-				ans[k]+=best[l*MatWidth+k]*bestcomp[j*CFrameSize+l];
-			ans[k]-=frames[j*MatWidth+k];
-			tmp=(float)fabs(ans[k]);
-			if (tmp>maxdev)
-				maxdev=tmp;
-			avedev+=tmp;
-			numave++;
-		}
-	}
-	avedev/=(float)numave;
-printf("%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev);
-printf("%d bytes original size\n",MatWidth*nFrames);
-printf("%d bytes of overhead\n",MatWidth*MatHeight);
-printf("%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize*nFrames);
-	compression=(float)(MatWidth*MatHeight+CFrameSize*nFrames+MatWidth);
-	compression/=(float)(MatWidth*nFrames);
-printf("Overall compression = %f %%\n",100.0f-100.0f*compression);
-	compression=(float)(CFrameSize);
-	compression/=(float)(MatWidth);
-printf("frame size compression = %f %%\n",100.0f-100.0f*compression);
-	free(rescale);
-	free(ans);
-}
-
-void AnimCompressToBytes(float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax)
-{
-	int k,l,nv,j;
-	float maxdev;
-	float avedev;
-	float tmp;
-	int numave;
-	float t,mx;
-	float *ans;
-
-
-	nv=MatWidth/3;
-
-	trans[0]=1E30f;
-	scale[0]=-1E30f;
-	trans[1]=1E30f;
-	scale[1]=-1E30f;
-	trans[2]=1E30f;
-	scale[2]=-1E30f;
-	for (k=0;k<MatWidth;k+=3)
-	{
-		if (base[k]>scale[0])
-			scale[0]=base[k];
-		if (base[k]<trans[0])
-			trans[0]=base[k];
-
-		if (base[k+1]>scale[1])
-			scale[1]=base[k+1];
-		if (base[k+1]<trans[1])
-			trans[1]=base[k+1];
-
-		if (base[k+2]>scale[2])
-			scale[2]=base[k+2];
-		if (base[k+2]<trans[2])
-			trans[2]=base[k+2];
-	}
-
-	scale[0]-=trans[0];
-	scale[1]-=trans[1];
-	scale[2]-=trans[2];
-	scale[0]/=255.0f;
-	scale[1]/=255.0f;
-	scale[2]/=255.0f;
-	for (k=0;k<MatWidth;k+=3)
-	{
-		t=(base[k]-trans[0])/scale[0];
-		if (t<0.0f)
-			t=0.0f;
-		if (t>255.0f)
-			t=255.0f;
-		cbase[k]=(unsigned char)t;
-
-		t=(base[k+1]-trans[1])/scale[1];
-		if (t<0.0f)
-			t=0.0f;
-		if (t>255.0f)
-			t=255.0f;
-		cbase[k+1]=(unsigned char)t;
-
-		t=(base[k+2]-trans[2])/scale[2];
-		if (t<0.0f)
-			t=0.0f;
-		if (t>255.0f)
-			t=255.0f;
-		cbase[k+2]=(unsigned char)t;
-	}
-	for (l=0;l<MatHeight;l++)
-	{
-		mx=0.0;
-		for (k=0;k<MatWidth;k++)
-		{
-			if (fabs(best[l*MatWidth+k])>mx)
-				mx=(float)fabs(best[l*MatWidth+k]);
-		}
-		if (mx>1E-8)
-		{
-			mx/=127.0f;
-			coffset[l]=1E30f;
-			cscale[l]=-1E30f;
-			for (j=0;j<nFrames;j++)
-			{
-				bestcomp[j*MatHeight+l]*=mx;
-				if (bestcomp[j*MatHeight+l]>cscale[l])
-					cscale[l]=bestcomp[j*MatHeight+l];
-				if (bestcomp[j*MatHeight+l]<coffset[l])
-					coffset[l]=bestcomp[j*MatHeight+l];
-			}
-			cscale[l]-=coffset[l];
-			if (cscale[l]>1E-10)
-			{
-				for (j=0;j<nFrames;j++)
-				{
-					tmp=254.0f*(bestcomp[j*MatHeight+l]-coffset[l])/cscale[l]-127.0f;
-					if (tmp>127.0f)
-						tmp=127.0f;
-					if (tmp<-127.0f)
-						tmp=-127.0f;
-					ccomp[j*MatHeight+l]=(char)floor(tmp+0.5);
-				}
-				coffset[l]+=cscale[l]*127.0f/254.0f;
-				cscale[l]/=254.0f;
-			}
-			else
-			{
-				cscale[l]=1.0f;
-				coffset[l]=0.0f;
-				for (j=0;j<nFrames;j++)
-					ccomp[j*MatHeight+l]=0;
-			}
-			mx=1.0f/mx;
-			for (k=0;k<MatWidth;k++)
-			{
-				tmp=best[l*MatWidth+k]*mx;
-				if (tmp>127.0f)
-					tmp=127.0f;
-				if (tmp<-127.0f)
-					tmp=-127.0f;
-				mat[k*MatHeight+l]=(char)floor(tmp+0.5);
-			}
-		}
-		else
-		{
-			cscale[l]=1.0f;
-			coffset[l]=0.0f;
-			for (j=0;j<nFrames;j++)
-				ccomp[j*MatHeight+l]=0;
-			for (k=0;k<MatWidth;k++)
-				mat[k*MatHeight+l]=0;
-		}
-	}
-	bmin[0]=1E30f;
-	bmin[1]=1E30f;
-	bmin[2]=1E30f;
-	bmax[0]=-1E30f;
-	bmax[1]=-1E30f;
-	bmax[2]=-1E30f;
-	numave=0;
-	avedev=0.0;
-	maxdev=0.0;
-	ans=(float *)SafeMalloc(sizeof(float)*MatWidth, "AnimCompressToBytes");
-	for (j=0;j<nFrames;j++)
-	{
-		for (k=0;k<MatWidth;k++)
-		{
-			ans[k]=0.0;
-			for (l=0;l<CFrameSize;l++)
-				ans[k]+=(float)(mat[l+k*MatHeight])*((float)(ccomp[j*CFrameSize+l])*cscale[l]+coffset[l]);
-			ans[k]+=(float)(cbase[k])*scale[k%3]+trans[k%3];
-			tmp=(float)fabs(ans[k]-frames[j*MatWidth+k]-base[k]);
-			if (tmp>maxdev)
-				maxdev=tmp;
-			avedev+=tmp;
-			numave++;
-
-			if (bmin[k%3]>ans[k])
-				bmin[k%3]=ans[k];
-			if (bmax[k%3]<ans[k])
-				bmax[k%3]=ans[k];
-		}
-	}
-	avedev/=(float)numave;
-printf("%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev);
-	free(ans);
-}
-
-void AnimCompressGetMatrix(float *mat)
-{
-	int k,l;
-	for (k=0;k<MatWidth;k++)
-		for (l=0;l<MatHeight;l++)
-			mat[k*MatHeight+l]=best[l*MatWidth+k];
-}
-
-void AnimCompressGetFrames(float *mat)
-{
-	memcpy(mat,bestcomp,CFrameSize*nFrames*sizeof(float));
-}
-
-void AnimCompressGetBase(int i,float *x,float *y,float *z)
-{
-	*x=base[i*3];
-	*y=base[i*3+1];
-	*z=base[i*3+2];
-}
-
-void AnimCompressEnd()
-{
-	free(matrix);
-	free(best);
-	free(delta);
-	free(comp);
-	free(tcomp);
-	free(bestcomp);
-	free(base);
-	free(frames);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <memory.h>
+#include "animcomp.h"
+
+
+void	*SafeMalloc(size_t n, char *desc);
+
+
+
+float *matrix;
+float *delta;
+float *best;
+float *comp;
+float *tcomp;
+float *bestcomp;
+float *frames;
+float *base;
+
+int MatWidth;
+int MatHeight;
+int CFrameSize;
+int nFrames;
+
+
+void AnimCompressInit(int nframes,int nVerts,int CompressedFrameSize)
+{
+	nFrames=nframes;
+	MatWidth=nVerts*3;
+	MatHeight=CompressedFrameSize;
+	CFrameSize=CompressedFrameSize;
+	matrix=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
+	best=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
+	delta=(float *)SafeMalloc(MatWidth*MatHeight*sizeof(float), "AnimCompressInit");
+	comp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
+	tcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
+	bestcomp=(float *)SafeMalloc(CFrameSize*nFrames*sizeof(float), "AnimCompressInit");
+	base=(float *)SafeMalloc(MatWidth*sizeof(float), "AnimCompressInit");
+	frames=(float *)SafeMalloc(MatWidth*nFrames*sizeof(float), "AnimCompressInit");
+}
+
+void AnimSetFrame(int frame,int index,float x,float y,float z)
+{
+	frames[frame*MatWidth+index*3]=x;
+	frames[frame*MatWidth+index*3+1]=y;
+	frames[frame*MatWidth+index*3+2]=z;
+}
+
+typedef struct 
+{
+	int index;
+	float val;
+} SORTP;
+
+
+#define F_RANDOM (((float)rand())/(float)RAND_MAX)
+
+extern void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize);
+
+void AnimCompressDoit()
+{
+	float compression;
+	float *rescale;
+	float *ans;
+	float maxdev;
+	float avedev;
+	float tmp;
+	int j,k,l,numave;
+
+	for (k=0;k<MatWidth;k++)
+		base[k]=0.0f;
+	for (j=0;j<nFrames;j++)
+		for (k=0;k<MatWidth;k++)
+			base[k]+=frames[j*MatWidth+k];
+	tmp=1.0f/(float)nFrames;
+	for (k=0;k<MatWidth;k++)
+		base[k]*=tmp;
+	for (j=0;j<nFrames;j++)
+		for (k=0;k<MatWidth;k++)
+			frames[j*MatWidth+k]-=base[k];
+
+	ans=(float *)SafeMalloc(sizeof(float)*MatWidth, "AnimCompressDoit");
+	rescale=(float *)SafeMalloc(sizeof(float)*CFrameSize, "AnimCompressDoit");
+	DOsvd(frames,best,bestcomp,rescale,nFrames,MatWidth,MatHeight);
+	avedev=0.0;
+	for (l=0;l<CFrameSize;l++)
+		avedev+=rescale[l];
+	for (l=0;l<CFrameSize;l++)
+		printf("%3.1f ",100.0f*rescale[l]/avedev);
+	printf("\n");
+	for (j=0;j<nFrames;j++)
+	{
+		for (l=0;l<CFrameSize;l++)
+		{
+			bestcomp[j*CFrameSize+l]=0.0;
+			for (k=0;k<MatWidth;k++)
+				bestcomp[j*CFrameSize+l]+=best[l*MatWidth+k]*frames[j*MatWidth+k];
+		}
+	}
+	numave=0;
+	avedev=0.0;
+	maxdev=0.0;
+	for (j=0;j<nFrames;j++)
+	{
+		for (k=0;k<MatWidth;k++)
+		{
+			ans[k]=0.0;
+			for (l=0;l<CFrameSize;l++)
+				ans[k]+=best[l*MatWidth+k]*bestcomp[j*CFrameSize+l];
+			ans[k]-=frames[j*MatWidth+k];
+			tmp=(float)fabs(ans[k]);
+			if (tmp>maxdev)
+				maxdev=tmp;
+			avedev+=tmp;
+			numave++;
+		}
+	}
+	avedev/=(float)numave;
+printf("%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev);
+printf("%d bytes original size\n",MatWidth*nFrames);
+printf("%d bytes of overhead\n",MatWidth*MatHeight);
+printf("%d bytes/frame * %d frames = %d bytes\n",CFrameSize,nFrames,CFrameSize*nFrames);
+	compression=(float)(MatWidth*MatHeight+CFrameSize*nFrames+MatWidth);
+	compression/=(float)(MatWidth*nFrames);
+printf("Overall compression = %f %%\n",100.0f-100.0f*compression);
+	compression=(float)(CFrameSize);
+	compression/=(float)(MatWidth);
+printf("frame size compression = %f %%\n",100.0f-100.0f*compression);
+	free(rescale);
+	free(ans);
+}
+
+void AnimCompressToBytes(float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax)
+{
+	int k,l,nv,j;
+	float maxdev;
+	float avedev;
+	float tmp;
+	int numave;
+	float t,mx;
+	float *ans;
+
+
+	nv=MatWidth/3;
+
+	trans[0]=1E30f;
+	scale[0]=-1E30f;
+	trans[1]=1E30f;
+	scale[1]=-1E30f;
+	trans[2]=1E30f;
+	scale[2]=-1E30f;
+	for (k=0;k<MatWidth;k+=3)
+	{
+		if (base[k]>scale[0])
+			scale[0]=base[k];
+		if (base[k]<trans[0])
+			trans[0]=base[k];
+
+		if (base[k+1]>scale[1])
+			scale[1]=base[k+1];
+		if (base[k+1]<trans[1])
+			trans[1]=base[k+1];
+
+		if (base[k+2]>scale[2])
+			scale[2]=base[k+2];
+		if (base[k+2]<trans[2])
+			trans[2]=base[k+2];
+	}
+
+	scale[0]-=trans[0];
+	scale[1]-=trans[1];
+	scale[2]-=trans[2];
+	scale[0]/=255.0f;
+	scale[1]/=255.0f;
+	scale[2]/=255.0f;
+	for (k=0;k<MatWidth;k+=3)
+	{
+		t=(base[k]-trans[0])/scale[0];
+		if (t<0.0f)
+			t=0.0f;
+		if (t>255.0f)
+			t=255.0f;
+		cbase[k]=(unsigned char)t;
+
+		t=(base[k+1]-trans[1])/scale[1];
+		if (t<0.0f)
+			t=0.0f;
+		if (t>255.0f)
+			t=255.0f;
+		cbase[k+1]=(unsigned char)t;
+
+		t=(base[k+2]-trans[2])/scale[2];
+		if (t<0.0f)
+			t=0.0f;
+		if (t>255.0f)
+			t=255.0f;
+		cbase[k+2]=(unsigned char)t;
+	}
+	for (l=0;l<MatHeight;l++)
+	{
+		mx=0.0;
+		for (k=0;k<MatWidth;k++)
+		{
+			if (fabs(best[l*MatWidth+k])>mx)
+				mx=(float)fabs(best[l*MatWidth+k]);
+		}
+		if (mx>1E-8)
+		{
+			mx/=127.0f;
+			coffset[l]=1E30f;
+			cscale[l]=-1E30f;
+			for (j=0;j<nFrames;j++)
+			{
+				bestcomp[j*MatHeight+l]*=mx;
+				if (bestcomp[j*MatHeight+l]>cscale[l])
+					cscale[l]=bestcomp[j*MatHeight+l];
+				if (bestcomp[j*MatHeight+l]<coffset[l])
+					coffset[l]=bestcomp[j*MatHeight+l];
+			}
+			cscale[l]-=coffset[l];
+			if (cscale[l]>1E-10)
+			{
+				for (j=0;j<nFrames;j++)
+				{
+					tmp=254.0f*(bestcomp[j*MatHeight+l]-coffset[l])/cscale[l]-127.0f;
+					if (tmp>127.0f)
+						tmp=127.0f;
+					if (tmp<-127.0f)
+						tmp=-127.0f;
+					ccomp[j*MatHeight+l]=(char)floor(tmp+0.5);
+				}
+				coffset[l]+=cscale[l]*127.0f/254.0f;
+				cscale[l]/=254.0f;
+			}
+			else
+			{
+				cscale[l]=1.0f;
+				coffset[l]=0.0f;
+				for (j=0;j<nFrames;j++)
+					ccomp[j*MatHeight+l]=0;
+			}
+			mx=1.0f/mx;
+			for (k=0;k<MatWidth;k++)
+			{
+				tmp=best[l*MatWidth+k]*mx;
+				if (tmp>127.0f)
+					tmp=127.0f;
+				if (tmp<-127.0f)
+					tmp=-127.0f;
+				mat[k*MatHeight+l]=(char)floor(tmp+0.5);
+			}
+		}
+		else
+		{
+			cscale[l]=1.0f;
+			coffset[l]=0.0f;
+			for (j=0;j<nFrames;j++)
+				ccomp[j*MatHeight+l]=0;
+			for (k=0;k<MatWidth;k++)
+				mat[k*MatHeight+l]=0;
+		}
+	}
+	bmin[0]=1E30f;
+	bmin[1]=1E30f;
+	bmin[2]=1E30f;
+	bmax[0]=-1E30f;
+	bmax[1]=-1E30f;
+	bmax[2]=-1E30f;
+	numave=0;
+	avedev=0.0;
+	maxdev=0.0;
+	ans=(float *)SafeMalloc(sizeof(float)*MatWidth, "AnimCompressToBytes");
+	for (j=0;j<nFrames;j++)
+	{
+		for (k=0;k<MatWidth;k++)
+		{
+			ans[k]=0.0;
+			for (l=0;l<CFrameSize;l++)
+				ans[k]+=(float)(mat[l+k*MatHeight])*((float)(ccomp[j*CFrameSize+l])*cscale[l]+coffset[l]);
+			ans[k]+=(float)(cbase[k])*scale[k%3]+trans[k%3];
+			tmp=(float)fabs(ans[k]-frames[j*MatWidth+k]-base[k]);
+			if (tmp>maxdev)
+				maxdev=tmp;
+			avedev+=tmp;
+			numave++;
+
+			if (bmin[k%3]>ans[k])
+				bmin[k%3]=ans[k];
+			if (bmax[k%3]<ans[k])
+				bmax[k%3]=ans[k];
+		}
+	}
+	avedev/=(float)numave;
+printf("%f Max Deviation (inches)  %f Ave Dev. (inches)\n",maxdev,avedev);
+	free(ans);
+}
+
+void AnimCompressGetMatrix(float *mat)
+{
+	int k,l;
+	for (k=0;k<MatWidth;k++)
+		for (l=0;l<MatHeight;l++)
+			mat[k*MatHeight+l]=best[l*MatWidth+k];
+}
+
+void AnimCompressGetFrames(float *mat)
+{
+	memcpy(mat,bestcomp,CFrameSize*nFrames*sizeof(float));
+}
+
+void AnimCompressGetBase(int i,float *x,float *y,float *z)
+{
+	*x=base[i*3];
+	*y=base[i*3+1];
+	*z=base[i*3+2];
+}
+
+void AnimCompressEnd()
+{
+	free(matrix);
+	free(best);
+	free(delta);
+	free(comp);
+	free(tcomp);
+	free(bestcomp);
+	free(base);
+	free(frames);
+}
diff --git a/tools/quake2/qdata_heretic2/animcomp.h b/tools/quake2/qdata_heretic2/animcomp.h
index 7378b502..15d0dc5b 100644
--- a/tools/quake2/qdata_heretic2/animcomp.h
+++ b/tools/quake2/qdata_heretic2/animcomp.h
@@ -1,43 +1,43 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#if !defined(ANIMCOMP_INC)
-#define ANIMCOMP_INC
-
-#ifdef  __cplusplus
-extern "C" 
-{
-#endif
-void AnimCompressInit(int nFrames,int nVerts,int CompressedFrameSize);
-void AnimSetFrame(int frame,int index,float x,float y,float z);
-void AnimCompressDoit();
-void AnimCompressToBytes(float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax);
-void AnimCompressGetMatrix(float *mat);
-void AnimCompressGetFrames(float *mat);
-void AnimCompressGetBase(int i,float *x,float *y,float *z);
-void AnimCompressEnd();
-void DOsvdPlane(float *pnts,int npnts,float *n,float *base);
-#ifdef  __cplusplus
-}
-#endif
-
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#if !defined(ANIMCOMP_INC)
+#define ANIMCOMP_INC
+
+#ifdef  __cplusplus
+extern "C" 
+{
+#endif
+void AnimCompressInit(int nFrames,int nVerts,int CompressedFrameSize);
+void AnimSetFrame(int frame,int index,float x,float y,float z);
+void AnimCompressDoit();
+void AnimCompressToBytes(float *trans,float *scale,char *mat,char *ccomp,unsigned char *cbase,float *cscale,float *coffset,float *bmin,float *bmax);
+void AnimCompressGetMatrix(float *mat);
+void AnimCompressGetFrames(float *mat);
+void AnimCompressGetBase(int i,float *x,float *y,float *z);
+void AnimCompressEnd();
+void DOsvdPlane(float *pnts,int npnts,float *n,float *base);
+#ifdef  __cplusplus
+}
+#endif
+
+#endif
+
diff --git a/tools/quake2/qdata_heretic2/anorms.h b/tools/quake2/qdata_heretic2/anorms.h
index f66b084a..f240902b 100644
--- a/tools/quake2/qdata_heretic2/anorms.h
+++ b/tools/quake2/qdata_heretic2/anorms.h
@@ -1,183 +1,183 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-  {-0.525731f, 0.000000f, 0.850651f},
-  {-0.442863f, 0.238856f, 0.864188f},
-  {-0.295242f, 0.000000f, 0.955423f},
-  {-0.309017f, 0.500000f, 0.809017f},
-  {-0.162460f, 0.262866f, 0.951056f},
-  {0.000000f, 0.000000f, 1.000000f},
-  {0.000000f, 0.850651f, 0.525731f},
-  {-0.147621f, 0.716567f, 0.681718f},
-  {0.147621f, 0.716567f, 0.681718f},
-  {0.000000f, 0.525731f, 0.850651f},
-  {0.309017f, 0.500000f, 0.809017f},
-  {0.525731f, 0.000000f, 0.850651f},
-  {0.295242f, 0.000000f, 0.955423f},
-  {0.442863f, 0.238856f, 0.864188f},
-  {0.162460f, 0.262866f, 0.951056f},
-  {-0.681718f, 0.147621f, 0.716567f},
-  {-0.809017f, 0.309017f, 0.500000f},
-  {-0.587785f, 0.425325f, 0.688191f},
-  {-0.850651f, 0.525731f, 0.000000f},
-  {-0.864188f, 0.442863f, 0.238856f},
-  {-0.716567f, 0.681718f, 0.147621f},
-  {-0.688191f, 0.587785f, 0.425325f},
-  {-0.500000f, 0.809017f, 0.309017f},
-  {-0.238856f, 0.864188f, 0.442863f},
-  {-0.425325f, 0.688191f, 0.587785f},
-  {-0.716567f, 0.681718f, -0.147621f},
-  {-0.500000f, 0.809017f, -0.309017f},
-  {-0.525731f, 0.850651f, 0.000000f},
-  {0.000000f, 0.850651f, -0.525731f},
-  {-0.238856f, 0.864188f, -0.442863f},
-  {0.000000f, 0.955423f, -0.295242f},
-  {-0.262866f, 0.951056f, -0.162460f},
-  {0.000000f, 1.000000f, 0.000000f},
-  {0.000000f, 0.955423f, 0.295242f},
-  {-0.262866f, 0.951056f, 0.162460f},
-  {0.238856f, 0.864188f, 0.442863f},
-  {0.262866f, 0.951056f, 0.162460f},
-  {0.500000f, 0.809017f, 0.309017f},
-  {0.238856f, 0.864188f, -0.442863f},
-  {0.262866f, 0.951056f, -0.162460f},
-  {0.500000f, 0.809017f, -0.309017f},
-  {0.850651f, 0.525731f, 0.000000f},
-  {0.716567f, 0.681718f, 0.147621f},
-  {0.716567f, 0.681718f, -0.147621f},
-  {0.525731f, 0.850651f, 0.000000f}, 
-  {0.425325f, 0.688191f, 0.587785f},
-  {0.864188f, 0.442863f, 0.238856f}, 
-  {0.688191f, 0.587785f, 0.425325f},
-  {0.809017f, 0.309017f, 0.500000f},
-  {0.681718f, 0.147621f, 0.716567f},
-  {0.587785f, 0.425325f, 0.688191f},
-  {0.955423f, 0.295242f, 0.000000f},
-  {1.000000f, 0.000000f, 0.000000f},
-  {0.951056f, 0.162460f, 0.262866f},
-  {0.850651f, -0.525731f, 0.000000f}, 
-  {0.955423f, -0.295242f, 0.000000f},
-  {0.864188f, -0.442863f, 0.238856f},
-  {0.951056f, -0.162460f, 0.262866f},
-  {0.809017f, -0.309017f, 0.500000f},
-  {0.681718f, -0.147621f, 0.716567f},
-  {0.850651f, 0.000000f, 0.525731f},
-  {0.864188f, 0.442863f, -0.238856f}, 
-  {0.809017f, 0.309017f, -0.500000f},
-  {0.951056f, 0.162460f, -0.262866f}, 
-  {0.525731f, 0.000000f, -0.850651f},
-  {0.681718f, 0.147621f, -0.716567f},
-  {0.681718f, -0.147621f, -0.716567f},
-  {0.850651f, 0.000000f, -0.525731f},
-  {0.809017f, -0.309017f, -0.500000f},
-  {0.864188f, -0.442863f, -0.238856f},
-  {0.951056f, -0.162460f, -0.262866f},
-  {0.147621f, 0.716567f, -0.681718f},
-  {0.309017f, 0.500000f, -0.809017f},
-  {0.425325f, 0.688191f, -0.587785f},
-  {0.442863f, 0.238856f, -0.864188f},
-  {0.587785f, 0.425325f, -0.688191f},
-  {0.688191f, 0.587785f, -0.425325f},
-  {-0.147621f, 0.716567f, -0.681718f},
-  {-0.309017f, 0.500000f, -0.809017f},
-  {0.000000f, 0.525731f, -0.850651f},
-  {-0.525731f, 0.000000f, -0.850651f},
-  {-0.442863f, 0.238856f, -0.864188f},
-  {-0.295242f, 0.000000f, -0.955423f},
-  {-0.162460f, 0.262866f, -0.951056f},
-  {0.000000f, 0.000000f, -1.000000f},
-  {0.295242f, 0.000000f, -0.955423f},
-  {0.162460f, 0.262866f, -0.951056f},
-  {-0.442863f, -0.238856f, -0.864188f},
-  {-0.309017f, -0.500000f, -0.809017f},
-  {-0.162460f, -0.262866f, -0.951056f},
-  {0.000000f, -0.850651f, -0.525731f},
-  {-0.147621f, -0.716567f, -0.681718f},
-  {0.147621f, -0.716567f, -0.681718f},
-  {0.000000f, -0.525731f, -0.850651f},
-  {0.309017f, -0.500000f, -0.809017f},
-  {0.442863f, -0.238856f, -0.864188f},
-  {0.162460f, -0.262866f, -0.951056f},
-  {0.238856f, -0.864188f, -0.442863f},
-  {0.500000f, -0.809017f, -0.309017f},
-  {0.425325f, -0.688191f, -0.587785f},
-  {0.716567f, -0.681718f, -0.147621f},
-  {0.688191f, -0.587785f, -0.425325f},
-  {0.587785f, -0.425325f, -0.688191f},
-  {0.000000f, -0.955423f, -0.295242f},
-  {0.000000f, -1.000000f, 0.000000f},
-  {0.262866f, -0.951056f, -0.162460f},
-  {0.000000f, -0.850651f, 0.525731f},
-  {0.000000f, -0.955423f, 0.295242f},
-  {0.238856f, -0.864188f, 0.442863f},
-  {0.262866f, -0.951056f, 0.162460f},
-  {0.500000f, -0.809017f, 0.309017f},
-  {0.716567f, -0.681718f, 0.147621f},
-  {0.525731f, -0.850651f, 0.000000f},
-  {-0.238856f, -0.864188f, -0.442863f},
-  {-0.500000f, -0.809017f, -0.309017f},
-  {-0.262866f, -0.951056f, -0.162460f},
-  {-0.850651f, -0.525731f, 0.000000f},
-  {-0.716567f, -0.681718f, -0.147621f},
-  {-0.716567f, -0.681718f, 0.147621f},
-  {-0.525731f, -0.850651f, 0.000000f},
-  {-0.500000f, -0.809017f, 0.309017f},
-  {-0.238856f, -0.864188f, 0.442863f},
-  {-0.262866f, -0.951056f, 0.162460f},
-  {-0.864188f, -0.442863f, 0.238856f},
-  {-0.809017f, -0.309017f, 0.500000f},
-  {-0.688191f, -0.587785f, 0.425325f},
-  {-0.681718f, -0.147621f, 0.716567f},
-  {-0.442863f, -0.238856f, 0.864188f},
-  {-0.587785f, -0.425325f, 0.688191f},
-  {-0.309017f, -0.500000f, 0.809017f},
-  {-0.147621f, -0.716567f, 0.681718f},
-  {-0.425325f, -0.688191f, 0.587785f},
-  {-0.162460f, -0.262866f, 0.951056f},
-  {0.442863f, -0.238856f, 0.864188f},
-  {0.162460f, -0.262866f, 0.951056f},
-  {0.309017f, -0.500000f, 0.809017f},
-  {0.147621f, -0.716567f, 0.681718f},
-  {0.000000f, -0.525731f, 0.850651f},
-  {0.425325f, -0.688191f, 0.587785f},
-  {0.587785f, -0.425325f, 0.688191f},
-  {0.688191f, -0.587785f, 0.425325f},
-  {-0.955423f, 0.295242f, 0.000000f},
-  {-0.951056f, 0.162460f, 0.262866f},
-  {-1.000000f, 0.000000f, 0.000000f},
-  {-0.850651f, 0.000000f, 0.525731f},
-  {-0.955423f, -0.295242f, 0.000000f},
-  {-0.951056f, -0.162460f, 0.262866f},
-  {-0.864188f, 0.442863f, -0.238856f},
-  {-0.951056f, 0.162460f, -0.262866f},
-  {-0.809017f, 0.309017f, -0.500000f},
-  {-0.864188f, -0.442863f, -0.238856f},
-  {-0.951056f, -0.162460f, -0.262866f},
-  {-0.809017f, -0.309017f, -0.500000f},
-  {-0.681718f, 0.147621f, -0.716567f},
-  {-0.681718f, -0.147621f, -0.716567f},
-  {-0.850651f, 0.000000f, -0.525731f},
-  {-0.688191f, 0.587785f, -0.425325f},
-  {-0.587785f, 0.425325f, -0.688191f},
-  {-0.425325f, 0.688191f, -0.587785f},
-  {-0.425325f, -0.688191f, -0.587785f},
-  {-0.587785f, -0.425325f, -0.688191f},
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+  {-0.525731f, 0.000000f, 0.850651f},
+  {-0.442863f, 0.238856f, 0.864188f},
+  {-0.295242f, 0.000000f, 0.955423f},
+  {-0.309017f, 0.500000f, 0.809017f},
+  {-0.162460f, 0.262866f, 0.951056f},
+  {0.000000f, 0.000000f, 1.000000f},
+  {0.000000f, 0.850651f, 0.525731f},
+  {-0.147621f, 0.716567f, 0.681718f},
+  {0.147621f, 0.716567f, 0.681718f},
+  {0.000000f, 0.525731f, 0.850651f},
+  {0.309017f, 0.500000f, 0.809017f},
+  {0.525731f, 0.000000f, 0.850651f},
+  {0.295242f, 0.000000f, 0.955423f},
+  {0.442863f, 0.238856f, 0.864188f},
+  {0.162460f, 0.262866f, 0.951056f},
+  {-0.681718f, 0.147621f, 0.716567f},
+  {-0.809017f, 0.309017f, 0.500000f},
+  {-0.587785f, 0.425325f, 0.688191f},
+  {-0.850651f, 0.525731f, 0.000000f},
+  {-0.864188f, 0.442863f, 0.238856f},
+  {-0.716567f, 0.681718f, 0.147621f},
+  {-0.688191f, 0.587785f, 0.425325f},
+  {-0.500000f, 0.809017f, 0.309017f},
+  {-0.238856f, 0.864188f, 0.442863f},
+  {-0.425325f, 0.688191f, 0.587785f},
+  {-0.716567f, 0.681718f, -0.147621f},
+  {-0.500000f, 0.809017f, -0.309017f},
+  {-0.525731f, 0.850651f, 0.000000f},
+  {0.000000f, 0.850651f, -0.525731f},
+  {-0.238856f, 0.864188f, -0.442863f},
+  {0.000000f, 0.955423f, -0.295242f},
+  {-0.262866f, 0.951056f, -0.162460f},
+  {0.000000f, 1.000000f, 0.000000f},
+  {0.000000f, 0.955423f, 0.295242f},
+  {-0.262866f, 0.951056f, 0.162460f},
+  {0.238856f, 0.864188f, 0.442863f},
+  {0.262866f, 0.951056f, 0.162460f},
+  {0.500000f, 0.809017f, 0.309017f},
+  {0.238856f, 0.864188f, -0.442863f},
+  {0.262866f, 0.951056f, -0.162460f},
+  {0.500000f, 0.809017f, -0.309017f},
+  {0.850651f, 0.525731f, 0.000000f},
+  {0.716567f, 0.681718f, 0.147621f},
+  {0.716567f, 0.681718f, -0.147621f},
+  {0.525731f, 0.850651f, 0.000000f}, 
+  {0.425325f, 0.688191f, 0.587785f},
+  {0.864188f, 0.442863f, 0.238856f}, 
+  {0.688191f, 0.587785f, 0.425325f},
+  {0.809017f, 0.309017f, 0.500000f},
+  {0.681718f, 0.147621f, 0.716567f},
+  {0.587785f, 0.425325f, 0.688191f},
+  {0.955423f, 0.295242f, 0.000000f},
+  {1.000000f, 0.000000f, 0.000000f},
+  {0.951056f, 0.162460f, 0.262866f},
+  {0.850651f, -0.525731f, 0.000000f}, 
+  {0.955423f, -0.295242f, 0.000000f},
+  {0.864188f, -0.442863f, 0.238856f},
+  {0.951056f, -0.162460f, 0.262866f},
+  {0.809017f, -0.309017f, 0.500000f},
+  {0.681718f, -0.147621f, 0.716567f},
+  {0.850651f, 0.000000f, 0.525731f},
+  {0.864188f, 0.442863f, -0.238856f}, 
+  {0.809017f, 0.309017f, -0.500000f},
+  {0.951056f, 0.162460f, -0.262866f}, 
+  {0.525731f, 0.000000f, -0.850651f},
+  {0.681718f, 0.147621f, -0.716567f},
+  {0.681718f, -0.147621f, -0.716567f},
+  {0.850651f, 0.000000f, -0.525731f},
+  {0.809017f, -0.309017f, -0.500000f},
+  {0.864188f, -0.442863f, -0.238856f},
+  {0.951056f, -0.162460f, -0.262866f},
+  {0.147621f, 0.716567f, -0.681718f},
+  {0.309017f, 0.500000f, -0.809017f},
+  {0.425325f, 0.688191f, -0.587785f},
+  {0.442863f, 0.238856f, -0.864188f},
+  {0.587785f, 0.425325f, -0.688191f},
+  {0.688191f, 0.587785f, -0.425325f},
+  {-0.147621f, 0.716567f, -0.681718f},
+  {-0.309017f, 0.500000f, -0.809017f},
+  {0.000000f, 0.525731f, -0.850651f},
+  {-0.525731f, 0.000000f, -0.850651f},
+  {-0.442863f, 0.238856f, -0.864188f},
+  {-0.295242f, 0.000000f, -0.955423f},
+  {-0.162460f, 0.262866f, -0.951056f},
+  {0.000000f, 0.000000f, -1.000000f},
+  {0.295242f, 0.000000f, -0.955423f},
+  {0.162460f, 0.262866f, -0.951056f},
+  {-0.442863f, -0.238856f, -0.864188f},
+  {-0.309017f, -0.500000f, -0.809017f},
+  {-0.162460f, -0.262866f, -0.951056f},
+  {0.000000f, -0.850651f, -0.525731f},
+  {-0.147621f, -0.716567f, -0.681718f},
+  {0.147621f, -0.716567f, -0.681718f},
+  {0.000000f, -0.525731f, -0.850651f},
+  {0.309017f, -0.500000f, -0.809017f},
+  {0.442863f, -0.238856f, -0.864188f},
+  {0.162460f, -0.262866f, -0.951056f},
+  {0.238856f, -0.864188f, -0.442863f},
+  {0.500000f, -0.809017f, -0.309017f},
+  {0.425325f, -0.688191f, -0.587785f},
+  {0.716567f, -0.681718f, -0.147621f},
+  {0.688191f, -0.587785f, -0.425325f},
+  {0.587785f, -0.425325f, -0.688191f},
+  {0.000000f, -0.955423f, -0.295242f},
+  {0.000000f, -1.000000f, 0.000000f},
+  {0.262866f, -0.951056f, -0.162460f},
+  {0.000000f, -0.850651f, 0.525731f},
+  {0.000000f, -0.955423f, 0.295242f},
+  {0.238856f, -0.864188f, 0.442863f},
+  {0.262866f, -0.951056f, 0.162460f},
+  {0.500000f, -0.809017f, 0.309017f},
+  {0.716567f, -0.681718f, 0.147621f},
+  {0.525731f, -0.850651f, 0.000000f},
+  {-0.238856f, -0.864188f, -0.442863f},
+  {-0.500000f, -0.809017f, -0.309017f},
+  {-0.262866f, -0.951056f, -0.162460f},
+  {-0.850651f, -0.525731f, 0.000000f},
+  {-0.716567f, -0.681718f, -0.147621f},
+  {-0.716567f, -0.681718f, 0.147621f},
+  {-0.525731f, -0.850651f, 0.000000f},
+  {-0.500000f, -0.809017f, 0.309017f},
+  {-0.238856f, -0.864188f, 0.442863f},
+  {-0.262866f, -0.951056f, 0.162460f},
+  {-0.864188f, -0.442863f, 0.238856f},
+  {-0.809017f, -0.309017f, 0.500000f},
+  {-0.688191f, -0.587785f, 0.425325f},
+  {-0.681718f, -0.147621f, 0.716567f},
+  {-0.442863f, -0.238856f, 0.864188f},
+  {-0.587785f, -0.425325f, 0.688191f},
+  {-0.309017f, -0.500000f, 0.809017f},
+  {-0.147621f, -0.716567f, 0.681718f},
+  {-0.425325f, -0.688191f, 0.587785f},
+  {-0.162460f, -0.262866f, 0.951056f},
+  {0.442863f, -0.238856f, 0.864188f},
+  {0.162460f, -0.262866f, 0.951056f},
+  {0.309017f, -0.500000f, 0.809017f},
+  {0.147621f, -0.716567f, 0.681718f},
+  {0.000000f, -0.525731f, 0.850651f},
+  {0.425325f, -0.688191f, 0.587785f},
+  {0.587785f, -0.425325f, 0.688191f},
+  {0.688191f, -0.587785f, 0.425325f},
+  {-0.955423f, 0.295242f, 0.000000f},
+  {-0.951056f, 0.162460f, 0.262866f},
+  {-1.000000f, 0.000000f, 0.000000f},
+  {-0.850651f, 0.000000f, 0.525731f},
+  {-0.955423f, -0.295242f, 0.000000f},
+  {-0.951056f, -0.162460f, 0.262866f},
+  {-0.864188f, 0.442863f, -0.238856f},
+  {-0.951056f, 0.162460f, -0.262866f},
+  {-0.809017f, 0.309017f, -0.500000f},
+  {-0.864188f, -0.442863f, -0.238856f},
+  {-0.951056f, -0.162460f, -0.262866f},
+  {-0.809017f, -0.309017f, -0.500000f},
+  {-0.681718f, 0.147621f, -0.716567f},
+  {-0.681718f, -0.147621f, -0.716567f},
+  {-0.850651f, 0.000000f, -0.525731f},
+  {-0.688191f, 0.587785f, -0.425325f},
+  {-0.587785f, 0.425325f, -0.688191f},
+  {-0.425325f, 0.688191f, -0.587785f},
+  {-0.425325f, -0.688191f, -0.587785f},
+  {-0.587785f, -0.425325f, -0.688191f},
   {-0.688191f, -0.587785f, -0.425325f},
\ No newline at end of file
diff --git a/tools/quake2/qdata_heretic2/book.c b/tools/quake2/qdata_heretic2/book.c
index a65174a6..fd8072cb 100644
--- a/tools/quake2/qdata_heretic2/book.c
+++ b/tools/quake2/qdata_heretic2/book.c
@@ -1,372 +1,372 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "qdata.h"
-
-byte			*byteimage, *lbmpalette;
-int				byteimagewidth, byteimageheight;
-
-qboolean		TrueColorImage;
-int				longimagewidth, longimageheight;
-
-char			book_prefix[1024];
-byte			buffer[640 * 480];
-unsigned long	bufferl[640 * 480];
-
-miptex_t *CreateBook8(byte *buffer, int w, int h, byte *palette, int *FinalSize)
-{
-	miptex_t	*mp;
-	int			i, j;
-	byte		*pos;
-	int			size;
-
-	size = sizeof(*mp) + (w * h);
-	mp = (miptex_t *)SafeMalloc(size, "CreateBook8");
-	memset(mp, 0, size);
-
-	mp->version = MIP_VERSION;
-
-	for(i=j=0;i<256;i++,j+=3)
-	{
-		mp->palette[i].r = palette[j];
-		mp->palette[i].g = palette[j+1];
-		mp->palette[i].b = palette[j+2];
-	}
-	pos = (byte *)(mp + 1);
-
-	mp->width[0] = w;
-	mp->height[0] = h;
-	mp->offsets[0] = sizeof(*mp);
-	memcpy(pos, buffer, w * h);
-
-	*FinalSize = size;
-	return(mp);
-}
-
-miptex32_t *CreateBook32(long *buffer, int w, int h, int *FinalSize)
-{
-	miptex32_t	*mp;
-	byte		*pos;
-	int			size;
-
-	size = sizeof(*mp) + (w * h * 4);
-	mp = (miptex32_t *)SafeMalloc(size, "CreateBook32");
-	memset(mp, 0, size);
-
-	mp->version = MIP32_VERSION;
-
-	pos = (byte *)(mp + 1);
-
-	mp->width[0] = w;
-	mp->height[0] = h;
-	mp->offsets[0] = sizeof(*mp);
-	memcpy(pos, buffer, w * h * 4);
-
-	*FinalSize = size;
-	return(mp);
-}
-
-
-// Routines to chop a random sized image into gl texture friendly chunks
-
-typedef struct rect_s 
-{
-	int		x, y;
-	int		w, h;
-	char	name[4];
-} rect_t;
-
-int GetCoords(int x, int store[MAX_MD2SKINS])
-{
-	int		index, start, delta;
-
-	index = 0;
-	start = 0;
-	delta = 256;
-
-	store[index++] = start;
-	while(x)
-	{
-		if(x >= delta)
-		{
-			start += delta;
-			store[index++] = start;
-			x -= delta;
-		}
-		else
-		{
-			delta >>= 1;
-		}
-	}
-	return(index);
-}
-
-int ChopImage(int w, int h, rect_t coords[MAX_MD2SKINS])
-{
-	int		xs[MAX_MD2SKINS], ys[MAX_MD2SKINS];
-	int		xcount, ycount, x, y, index;
-
-	index = 0;
-	xcount = GetCoords(w, xs) - 1;
-	ycount = GetCoords(h, ys) - 1;
-
-	for(y = 0; y < ycount; y++)
-	{
-		for(x = 0; x < xcount; x++, index++)
-		{
-			coords[index].x = xs[x];
-			coords[index].y = ys[y];
-			coords[index].w = xs[x + 1] - xs[x];
-			coords[index].h = ys[y + 1] - ys[y];
-			coords[index].name[0] = x + '0';
-			coords[index].name[1] = y + '0';
-			coords[index].name[2] = 0;
-		}
-	}
-	return(index);
-}
-
-/*
-===============
-Cmd_Pic
-===============
-*/
-
-void Cmd_Book()
-{
-	int             xl,yl,xh,yh,w,h;
-	byte            *dest, *source;
-	int				flags, value, contents;
-	char			lumpname[64];
-	char			filename[1024];
-	unsigned long	*destl, *sourcel;
-	int             linedelta, x, y;
-	int				size;
-	miptex_t		*qtex;
-	miptex32_t		*qtex32;
-	float			scale_x, scale_y;
-	int				numrects, i;
-	rect_t			coords[MAX_MD2SKINS];
-	bookframe_t		bframes[MAX_MD2SKINS];
-	bookframe_t		*bf;
-	book_t			book;
-
-	GetScriptToken (false);
-	strcpy (lumpname, token);
-	
-	GetScriptToken (false);
-	xl = atoi (token);
-	GetScriptToken (false);
-	yl = atoi (token);
-	GetScriptToken (false);
-	w = atoi (token);
-	GetScriptToken (false);
-	h = atoi (token);
-
-	total_x += w;
-	total_y += h;
-	total_textures++;
-
-	if ( (w & 7) || (h & 7) )
-		Error ("line %i: miptex sizes must be multiples of 8", scriptline);
-
-	flags = 0;
-	contents = 0;
-	value = 0;
-
-	scale_x = scale_y = 0.5;
-
-	if (g_release)
-		return;
-
-	if(TrueColorImage)
-	{
-		xh = xl + w;
-		yh = yl + h;
-
-		if (xl >= longimagewidth || xh > longimagewidth ||
-			yl >= longimageheight || yh > longimageheight)
-		{
-			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
-		}
-
-		sourcel = (unsigned long *) longimage + (yl * longimagewidth) + xl;
-		destl = (unsigned long *) longimage;
-		linedelta = (longimagewidth - w);
-
-		for(y = yl; y < yh; y++)
-		{
-			for(x = xl; x < xh; x++)
-			{
-				*destl++ = *sourcel++;	// RGBA
-			}
-			sourcel += linedelta;
-		}
-
-		// Get rectangles to chop into
-		numrects = ChopImage(w, h, coords);
-
-		bf = bframes;
-		for(i = 0; i < numrects; i++, bf++)
-		{
-			// Copy section of image to buffer
-			sourcel = (unsigned long *) longimage + (coords[i].y * w) + coords[i].x;
-			destl = bufferl;
-			linedelta = w - coords[i].w;
-
-			for(y = 0; y < coords[i].h; y++)
-			{
-				for(x = 0; x < coords[i].w; x++)
-				{
-					*destl++ = *sourcel++;
-				}
-				sourcel += linedelta;
-			}
-
-			qtex32 = CreateBook32(bufferl, coords[i].w, coords[i].h, &size);
-
-			qtex32->flags = flags;
-			qtex32->contents = contents;
-			qtex32->value = value;
-			qtex32->scale_x = scale_x;
-			qtex32->scale_y = scale_y;
-
-			sprintf (filename, "%sbook/%s/%s_%s.m32", gamedir, book_prefix, lumpname, coords[i].name);
-			sprintf (qtex32->name, "%s/%s_%s.m32", book_prefix, lumpname, coords[i].name);
-
-			strcpy(bf->name, qtex32->name);
-			bf->x = coords[i].x;
-			bf->y = coords[i].y;
-			bf->w = coords[i].w;
-			bf->h = coords[i].h;
- 		//
-		// write it out
-		//
-			printf ("writing %s\n", filename);
-			SaveFile (filename, (byte *)qtex32, size);
-
-			free (qtex32);
-		}
-	}
-	else
-	{
-		xh = xl + w;
-		yh = yl + h;
-
-		if (xl >= byteimagewidth || xh > byteimagewidth ||
-			yl >= byteimageheight || yh > byteimageheight)
-		{
-			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
-		}
-
-		// Copy image to top left
-		source = byteimage + yl*byteimagewidth + xl;
-		dest = byteimage;
-		linedelta = byteimagewidth - w;
-
-		for(y = yl; y < yh; y++)
-		{
-			for(x = xl; x < xh; x++)
-			{
-				*dest++ = *source++;
-			}
-			source += linedelta;
-		}
-
-		// Get rectangles to chop into
-		numrects = ChopImage(w, h, coords);
-
-		bf = bframes;
-		for(i = 0; i < numrects; i++, bf++)
-		{
-			// Copy section of image to buffer
-			source = byteimage + (coords[i].y * w) + coords[i].x;
-			dest = buffer;
-			linedelta = w - coords[i].w;
-
-			for(y = 0; y < coords[i].h; y++)
-			{
-				for(x = 0; x < coords[i].w; x++)
-				{
-					*dest++ = *source++;
-				}
-				source += linedelta;
-			}
-
-			qtex = CreateBook8(buffer, coords[i].w, coords[i].h, lbmpalette, &size);
-
-			qtex->flags = flags;
-			qtex->contents = contents;
-			qtex->value = value;
-
-			sprintf (filename, "%sbook/%s/%s_%s.m8", gamedir, book_prefix, lumpname, coords[i].name);
-			sprintf (qtex->name, "%s/%s_%s.m8", book_prefix, lumpname, coords[i].name);
-
-			strcpy(bf->name, qtex->name);
-			bf->x = coords[i].x;
-			bf->y = coords[i].y;
-			bf->w = coords[i].w;
-			bf->h = coords[i].h;
- 		//
-		// write it out
-		//
-			printf ("writing %s\n", filename);
-			SaveFile (filename, (byte *)qtex, size);
-
-			free (qtex);
-		}
-	}
-	// Set up descriptor
-	size = sizeof(bookframe_t) * numrects;
-
-	book.bheader.ident = IDBOOKHEADER;
-	book.bheader.version = BOOK_VERSION;
-	book.bheader.num_segments = numrects;
-	book.bheader.total_w = w;
-	book.bheader.total_h = h;
-	memcpy(book.bframes, bframes, size);
-
-	// Save out segment descriptor
-	sprintf (filename, "%sBook/%s/%s.bk", gamedir, book_prefix, lumpname);
-	printf ("writing %s\n", filename);
-	SaveFile (filename, (byte *)&book, size + sizeof(bookheader_t));
-}
-
-/*
-===============
-Cmd_picdir
-===============
-*/
-void Cmd_Bookdir (void)
-{
-	char	filename[1024];
-
-	GetScriptToken (false);
-	strcpy (book_prefix, token);
-	// create the directory if needed
-	sprintf (filename, "%sBook", gamedir);
-	Q_mkdir (filename); 
-	sprintf (filename, "%sBook/%s", gamedir, book_prefix);
-	Q_mkdir (filename); 
-}
-
-// end
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "qdata.h"
+
+byte			*byteimage, *lbmpalette;
+int				byteimagewidth, byteimageheight;
+
+qboolean		TrueColorImage;
+int				longimagewidth, longimageheight;
+
+char			book_prefix[1024];
+byte			buffer[640 * 480];
+unsigned long	bufferl[640 * 480];
+
+miptex_t *CreateBook8(byte *buffer, int w, int h, byte *palette, int *FinalSize)
+{
+	miptex_t	*mp;
+	int			i, j;
+	byte		*pos;
+	int			size;
+
+	size = sizeof(*mp) + (w * h);
+	mp = (miptex_t *)SafeMalloc(size, "CreateBook8");
+	memset(mp, 0, size);
+
+	mp->version = MIP_VERSION;
+
+	for(i=j=0;i<256;i++,j+=3)
+	{
+		mp->palette[i].r = palette[j];
+		mp->palette[i].g = palette[j+1];
+		mp->palette[i].b = palette[j+2];
+	}
+	pos = (byte *)(mp + 1);
+
+	mp->width[0] = w;
+	mp->height[0] = h;
+	mp->offsets[0] = sizeof(*mp);
+	memcpy(pos, buffer, w * h);
+
+	*FinalSize = size;
+	return(mp);
+}
+
+miptex32_t *CreateBook32(long *buffer, int w, int h, int *FinalSize)
+{
+	miptex32_t	*mp;
+	byte		*pos;
+	int			size;
+
+	size = sizeof(*mp) + (w * h * 4);
+	mp = (miptex32_t *)SafeMalloc(size, "CreateBook32");
+	memset(mp, 0, size);
+
+	mp->version = MIP32_VERSION;
+
+	pos = (byte *)(mp + 1);
+
+	mp->width[0] = w;
+	mp->height[0] = h;
+	mp->offsets[0] = sizeof(*mp);
+	memcpy(pos, buffer, w * h * 4);
+
+	*FinalSize = size;
+	return(mp);
+}
+
+
+// Routines to chop a random sized image into gl texture friendly chunks
+
+typedef struct rect_s 
+{
+	int		x, y;
+	int		w, h;
+	char	name[4];
+} rect_t;
+
+int GetCoords(int x, int store[MAX_MD2SKINS])
+{
+	int		index, start, delta;
+
+	index = 0;
+	start = 0;
+	delta = 256;
+
+	store[index++] = start;
+	while(x)
+	{
+		if(x >= delta)
+		{
+			start += delta;
+			store[index++] = start;
+			x -= delta;
+		}
+		else
+		{
+			delta >>= 1;
+		}
+	}
+	return(index);
+}
+
+int ChopImage(int w, int h, rect_t coords[MAX_MD2SKINS])
+{
+	int		xs[MAX_MD2SKINS], ys[MAX_MD2SKINS];
+	int		xcount, ycount, x, y, index;
+
+	index = 0;
+	xcount = GetCoords(w, xs) - 1;
+	ycount = GetCoords(h, ys) - 1;
+
+	for(y = 0; y < ycount; y++)
+	{
+		for(x = 0; x < xcount; x++, index++)
+		{
+			coords[index].x = xs[x];
+			coords[index].y = ys[y];
+			coords[index].w = xs[x + 1] - xs[x];
+			coords[index].h = ys[y + 1] - ys[y];
+			coords[index].name[0] = x + '0';
+			coords[index].name[1] = y + '0';
+			coords[index].name[2] = 0;
+		}
+	}
+	return(index);
+}
+
+/*
+===============
+Cmd_Pic
+===============
+*/
+
+void Cmd_Book()
+{
+	int             xl,yl,xh,yh,w,h;
+	byte            *dest, *source;
+	int				flags, value, contents;
+	char			lumpname[64];
+	char			filename[1024];
+	unsigned long	*destl, *sourcel;
+	int             linedelta, x, y;
+	int				size;
+	miptex_t		*qtex;
+	miptex32_t		*qtex32;
+	float			scale_x, scale_y;
+	int				numrects, i;
+	rect_t			coords[MAX_MD2SKINS];
+	bookframe_t		bframes[MAX_MD2SKINS];
+	bookframe_t		*bf;
+	book_t			book;
+
+	GetScriptToken (false);
+	strcpy (lumpname, token);
+	
+	GetScriptToken (false);
+	xl = atoi (token);
+	GetScriptToken (false);
+	yl = atoi (token);
+	GetScriptToken (false);
+	w = atoi (token);
+	GetScriptToken (false);
+	h = atoi (token);
+
+	total_x += w;
+	total_y += h;
+	total_textures++;
+
+	if ( (w & 7) || (h & 7) )
+		Error ("line %i: miptex sizes must be multiples of 8", scriptline);
+
+	flags = 0;
+	contents = 0;
+	value = 0;
+
+	scale_x = scale_y = 0.5;
+
+	if (g_release)
+		return;
+
+	if(TrueColorImage)
+	{
+		xh = xl + w;
+		yh = yl + h;
+
+		if (xl >= longimagewidth || xh > longimagewidth ||
+			yl >= longimageheight || yh > longimageheight)
+		{
+			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
+		}
+
+		sourcel = (unsigned long *) longimage + (yl * longimagewidth) + xl;
+		destl = (unsigned long *) longimage;
+		linedelta = (longimagewidth - w);
+
+		for(y = yl; y < yh; y++)
+		{
+			for(x = xl; x < xh; x++)
+			{
+				*destl++ = *sourcel++;	// RGBA
+			}
+			sourcel += linedelta;
+		}
+
+		// Get rectangles to chop into
+		numrects = ChopImage(w, h, coords);
+
+		bf = bframes;
+		for(i = 0; i < numrects; i++, bf++)
+		{
+			// Copy section of image to buffer
+			sourcel = (unsigned long *) longimage + (coords[i].y * w) + coords[i].x;
+			destl = bufferl;
+			linedelta = w - coords[i].w;
+
+			for(y = 0; y < coords[i].h; y++)
+			{
+				for(x = 0; x < coords[i].w; x++)
+				{
+					*destl++ = *sourcel++;
+				}
+				sourcel += linedelta;
+			}
+
+			qtex32 = CreateBook32(bufferl, coords[i].w, coords[i].h, &size);
+
+			qtex32->flags = flags;
+			qtex32->contents = contents;
+			qtex32->value = value;
+			qtex32->scale_x = scale_x;
+			qtex32->scale_y = scale_y;
+
+			sprintf (filename, "%sbook/%s/%s_%s.m32", gamedir, book_prefix, lumpname, coords[i].name);
+			sprintf (qtex32->name, "%s/%s_%s.m32", book_prefix, lumpname, coords[i].name);
+
+			strcpy(bf->name, qtex32->name);
+			bf->x = coords[i].x;
+			bf->y = coords[i].y;
+			bf->w = coords[i].w;
+			bf->h = coords[i].h;
+ 		//
+		// write it out
+		//
+			printf ("writing %s\n", filename);
+			SaveFile (filename, (byte *)qtex32, size);
+
+			free (qtex32);
+		}
+	}
+	else
+	{
+		xh = xl + w;
+		yh = yl + h;
+
+		if (xl >= byteimagewidth || xh > byteimagewidth ||
+			yl >= byteimageheight || yh > byteimageheight)
+		{
+			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
+		}
+
+		// Copy image to top left
+		source = byteimage + yl*byteimagewidth + xl;
+		dest = byteimage;
+		linedelta = byteimagewidth - w;
+
+		for(y = yl; y < yh; y++)
+		{
+			for(x = xl; x < xh; x++)
+			{
+				*dest++ = *source++;
+			}
+			source += linedelta;
+		}
+
+		// Get rectangles to chop into
+		numrects = ChopImage(w, h, coords);
+
+		bf = bframes;
+		for(i = 0; i < numrects; i++, bf++)
+		{
+			// Copy section of image to buffer
+			source = byteimage + (coords[i].y * w) + coords[i].x;
+			dest = buffer;
+			linedelta = w - coords[i].w;
+
+			for(y = 0; y < coords[i].h; y++)
+			{
+				for(x = 0; x < coords[i].w; x++)
+				{
+					*dest++ = *source++;
+				}
+				source += linedelta;
+			}
+
+			qtex = CreateBook8(buffer, coords[i].w, coords[i].h, lbmpalette, &size);
+
+			qtex->flags = flags;
+			qtex->contents = contents;
+			qtex->value = value;
+
+			sprintf (filename, "%sbook/%s/%s_%s.m8", gamedir, book_prefix, lumpname, coords[i].name);
+			sprintf (qtex->name, "%s/%s_%s.m8", book_prefix, lumpname, coords[i].name);
+
+			strcpy(bf->name, qtex->name);
+			bf->x = coords[i].x;
+			bf->y = coords[i].y;
+			bf->w = coords[i].w;
+			bf->h = coords[i].h;
+ 		//
+		// write it out
+		//
+			printf ("writing %s\n", filename);
+			SaveFile (filename, (byte *)qtex, size);
+
+			free (qtex);
+		}
+	}
+	// Set up descriptor
+	size = sizeof(bookframe_t) * numrects;
+
+	book.bheader.ident = IDBOOKHEADER;
+	book.bheader.version = BOOK_VERSION;
+	book.bheader.num_segments = numrects;
+	book.bheader.total_w = w;
+	book.bheader.total_h = h;
+	memcpy(book.bframes, bframes, size);
+
+	// Save out segment descriptor
+	sprintf (filename, "%sBook/%s/%s.bk", gamedir, book_prefix, lumpname);
+	printf ("writing %s\n", filename);
+	SaveFile (filename, (byte *)&book, size + sizeof(bookheader_t));
+}
+
+/*
+===============
+Cmd_picdir
+===============
+*/
+void Cmd_Bookdir (void)
+{
+	char	filename[1024];
+
+	GetScriptToken (false);
+	strcpy (book_prefix, token);
+	// create the directory if needed
+	sprintf (filename, "%sBook", gamedir);
+	Q_mkdir (filename); 
+	sprintf (filename, "%sBook/%s", gamedir, book_prefix);
+	Q_mkdir (filename); 
+}
+
+// end
diff --git a/tools/quake2/qdata_heretic2/common/bspfile.c b/tools/quake2/qdata_heretic2/common/bspfile.c
index db7c0add..d029a335 100644
--- a/tools/quake2/qdata_heretic2/common/bspfile.c
+++ b/tools/quake2/qdata_heretic2/common/bspfile.c
@@ -1,793 +1,793 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "bspfile.h"
-#include "scriplib.h"
-
-void GetLeafNums (void);
-
-//=============================================================================
-
-int			nummodels;
-dmodel_t	dmodels[MAX_MAP_MODELS];
-
-int			visdatasize;
-byte		dvisdata[MAX_MAP_VISIBILITY];
-dvis_t		*dvis = (dvis_t *)dvisdata;
-
-int			lightdatasize;
-byte		dlightdata[MAX_MAP_LIGHTING];
-
-int			entdatasize;
-char		dentdata[MAX_MAP_ENTSTRING];
-
-int			numleafs;
-dleaf_t		dleafs[MAX_MAP_LEAFS];
-
-int			numplanes;
-dplane_t	dplanes[MAX_MAP_PLANES];
-
-int			numvertexes;
-dvertex_t	dvertexes[MAX_MAP_VERTS];
-
-int			numnodes;
-dnode_t		dnodes[MAX_MAP_NODES];
-
-int			numtexinfo;
-texinfo_t	texinfo[MAX_MAP_TEXINFO];
-
-int			numfaces;
-dface_t		dfaces[MAX_MAP_FACES];
-
-int			numedges;
-dedge_t		dedges[MAX_MAP_EDGES];
-
-int			numleaffaces;
-unsigned short		dleaffaces[MAX_MAP_LEAFFACES];
-
-int			numleafbrushes;
-unsigned short		dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-int			numsurfedges;
-int			dsurfedges[MAX_MAP_SURFEDGES];
-
-int			numbrushes;
-dbrush_t	dbrushes[MAX_MAP_BRUSHES];
-
-int			numbrushsides;
-dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
-
-int			numareas;
-darea_t		dareas[MAX_MAP_AREAS];
-
-int			numareaportals;
-dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
-
-byte		dpop[256];
-
-/*
-===============
-CompressVis
-
-===============
-*/
-int CompressVis (byte *vis, byte *dest)
-{
-	int		j;
-	int		rep;
-	int		visrow;
-	byte	*dest_p;
-	
-	dest_p = dest;
-//	visrow = (r_numvisleafs + 7)>>3;
-	visrow = (dvis->numclusters + 7)>>3;
-	
-	for (j=0 ; j<visrow ; j++)
-	{
-		*dest_p++ = vis[j];
-		if (vis[j])
-			continue;
-
-		rep = 1;
-		for ( j++; j<visrow ; j++)
-			if (vis[j] || rep == 255)
-				break;
-			else
-				rep++;
-		*dest_p++ = rep;
-		j--;
-	}
-	
-	return dest_p - dest;
-}
-
-
-/*
-===================
-DecompressVis
-===================
-*/
-void DecompressVis (byte *in, byte *decompressed)
-{
-	int		c;
-	byte	*out;
-	int		row;
-
-//	row = (r_numvisleafs+7)>>3;	
-	row = (dvis->numclusters+7)>>3;	
-	out = decompressed;
-
-	do
-	{
-		if (*in)
-		{
-			*out++ = *in++;
-			continue;
-		}
-	
-		c = in[1];
-		if (!c)
-			Error ("DecompressVis: 0 repeat");
-		in += 2;
-		while (c)
-		{
-			*out++ = 0;
-			c--;
-		}
-	} while (out - decompressed < row);
-}
-
-//=============================================================================
-
-/*
-=============
-SwapBSPFile
-
-Byte swaps all data in a bsp file.
-=============
-*/
-void SwapBSPFile (qboolean todisk)
-{
-	int				i, j;
-	dmodel_t		*d;
-
-	
-// models	
-	for (i=0 ; i<nummodels ; i++)
-	{
-		d = &dmodels[i];
-
-		d->firstface = LittleLong (d->firstface);
-		d->numfaces = LittleLong (d->numfaces);
-		d->headnode = LittleLong (d->headnode);
-		
-		for (j=0 ; j<3 ; j++)
-		{
-			d->mins[j] = LittleFloat(d->mins[j]);
-			d->maxs[j] = LittleFloat(d->maxs[j]);
-			d->origin[j] = LittleFloat(d->origin[j]);
-		}
-	}
-
-//
-// vertexes
-//
-	for (i=0 ; i<numvertexes ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-			dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
-	}
-		
-//
-// planes
-//	
-	for (i=0 ; i<numplanes ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-			dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
-		dplanes[i].dist = LittleFloat (dplanes[i].dist);
-		dplanes[i].type = LittleLong (dplanes[i].type);
-	}
-	
-//
-// texinfos
-//	
-	for (i=0 ; i<numtexinfo ; i++)
-	{
-		for (j=0 ; j<8 ; j++)
-			texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
-		texinfo[i].flags = LittleLong (texinfo[i].flags);
-		texinfo[i].value = LittleLong (texinfo[i].value);
-		texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
-	}
-	
-//
-// faces
-//
-	for (i=0 ; i<numfaces ; i++)
-	{
-		dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
-		dfaces[i].planenum = LittleShort (dfaces[i].planenum);
-		dfaces[i].side = LittleShort (dfaces[i].side);
-		dfaces[i].lighting.c = LittleLong (dfaces[i].lighting.c);
-		dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
-		dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
-		dfaces[i].numedges = LittleShort (dfaces[i].numedges);
-	}
-
-//
-// nodes
-//
-	for (i=0 ; i<numnodes ; i++)
-	{
-		dnodes[i].planenum = LittleLong (dnodes[i].planenum);
-		for (j=0 ; j<3 ; j++)
-		{
-			dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
-			dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
-		}
-		dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
-		dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
-		dnodes[i].firstface = LittleShort (dnodes[i].firstface);
-		dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
-	}
-
-//
-// leafs
-//
-	for (i=0 ; i<numleafs ; i++)
-	{
-		dleafs[i].contents = LittleLong (dleafs[i].contents);
-		dleafs[i].cluster = LittleShort (dleafs[i].cluster);
-		dleafs[i].area = LittleShort (dleafs[i].area);
-		for (j=0 ; j<3 ; j++)
-		{
-			dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
-			dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
-		}
-
-		dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
-		dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
-		dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
-		dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
-	}
-
-//
-// leaffaces
-//
-	for (i=0 ; i<numleaffaces ; i++)
-		dleaffaces[i] = LittleShort (dleaffaces[i]);
-
-//
-// leafbrushes
-//
-	for (i=0 ; i<numleafbrushes ; i++)
-		dleafbrushes[i] = LittleShort (dleafbrushes[i]);
-
-//
-// surfedges
-//
-	for (i=0 ; i<numsurfedges ; i++)
-		dsurfedges[i] = LittleLong (dsurfedges[i]);
-
-//
-// edges
-//
-	for (i=0 ; i<numedges ; i++)
-	{
-		dedges[i].v[0] = LittleShort (dedges[i].v[0]);
-		dedges[i].v[1] = LittleShort (dedges[i].v[1]);
-	}
-
-//
-// brushes
-//
-	for (i=0 ; i<numbrushes ; i++)
-	{
-		dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
-		dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
-		dbrushes[i].contents = LittleLong (dbrushes[i].contents);
-	}
-
-//
-// areas
-//
-	for (i=0 ; i<numareas ; i++)
-	{
-		dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
-		dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
-	}
-
-//
-// areasportals
-//
-	for (i=0 ; i<numareaportals ; i++)
-	{
-		dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
-		dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
-	}
-
-//
-// brushsides
-//
-	for (i=0 ; i<numbrushsides ; i++)
-	{
-		dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
-		dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
-	}
-
-//
-// visibility
-//
-	if (todisk)
-		j = dvis->numclusters;
-	else
-		j = LittleLong(dvis->numclusters);
-	dvis->numclusters = LittleLong (dvis->numclusters);
-	for (i=0 ; i<j ; i++)
-	{
-		dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
-		dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
-	}
-}
-
-
-dheader_t	*header;
-
-int CopyLump (int lump, void *dest, int size)
-{
-	int		length, ofs;
-
-	length = header->lumps[lump].filelen;
-	ofs = header->lumps[lump].fileofs;
-	
-	if (length % size)
-		Error ("LoadBSPFile: odd lump size");
-	
-	memcpy (dest, (byte *)header + ofs, length);
-
-	return length / size;
-}
-
-/*
-=============
-LoadBSPFile
-=============
-*/
-void	LoadBSPFile (char *filename)
-{
-	int			i;
-	
-//
-// load the file header
-//
-	LoadFile (filename, (void **)&header);
-
-// swap the header
-	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
-		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
-
-	if (header->ident != IDBSPHEADER)
-		Error ("%s is not a IBSP file", filename);
-	if (header->version != BSPVERSION)
-		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
-
-	nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
-	numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
-	numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
-	numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
-	numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
-	numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
-	numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
-	numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]));
-	numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]));
-	numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
-	numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
-	numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t));
-	numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t));
-	numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t));
-	numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t));
-
-	visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
-	lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
-	entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
-
-	CopyLump (LUMP_POP, dpop, 1);
-
-	free (header);		// everything has been copied out
-		
-//
-// swap everything
-//	
-	SwapBSPFile (false);
-}
-
-
-/*
-=============
-LoadBSPFileTexinfo
-
-Only loads the texinfo lump, so qdata can scan for textures
-=============
-*/
-void	LoadBSPFileTexinfo (char *filename)
-{
-	int			i;
-	FILE		*f;
-	int		length, ofs;
-
-	header = malloc(sizeof(dheader_t));
-
-	f = fopen (filename, "rb");
-	fread (header, sizeof(dheader_t), 1, f);
-
-// swap the header
-	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
-		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
-
-	if (header->ident != IDBSPHEADER)
-		Error ("%s is not a IBSP file", filename);
-	if (header->version != BSPVERSION)
-		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
-
-
-	length = header->lumps[LUMP_TEXINFO].filelen;
-	ofs = header->lumps[LUMP_TEXINFO].fileofs;
-
-	fseek (f, ofs, SEEK_SET);
-	fread (texinfo, length, 1, f);
-	fclose (f);
-
-	numtexinfo = length / sizeof(texinfo_t);
-
-	free (header);		// everything has been copied out
-		
-	SwapBSPFile (false);
-}
-
-
-//============================================================================
-
-FILE		*wadfile;
-dheader_t	outheader;
-
-void AddLump (int lumpnum, void *data, int len)
-{
-	lump_t *lump;
-
-	lump = &header->lumps[lumpnum];
-	
-	lump->fileofs = LittleLong( ftell(wadfile) );
-	lump->filelen = LittleLong(len);
-	SafeWrite (wadfile, data, (len+3)&~3);
-}
-
-/*
-=============
-WriteBSPFile
-
-Swaps the bsp file in place, so it should not be referenced again
-=============
-*/
-void	WriteBSPFile (char *filename)
-{		
-	header = &outheader;
-	memset (header, 0, sizeof(dheader_t));
-	
-	SwapBSPFile (true);
-
-	header->ident = LittleLong (IDBSPHEADER);
-	header->version = LittleLong (BSPVERSION);
-	
-	wadfile = SafeOpenWrite (filename);
-	SafeWrite (wadfile, header, sizeof(dheader_t));	// overwritten later
-
-	AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
-	AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
-	AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
-	AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
-	AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
-	AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
-	AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
-	AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
-	AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
-	AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
-	AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
-	AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
-	AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
-	AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
-	AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
-
-	AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
-	AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
-	AddLump (LUMP_ENTITIES, dentdata, entdatasize);
-	AddLump (LUMP_POP, dpop, sizeof(dpop));
-	
-	fseek (wadfile, 0, SEEK_SET);
-	SafeWrite (wadfile, header, sizeof(dheader_t));
-	fclose (wadfile);	
-}
-
-//============================================================================
-
-/*
-=============
-PrintBSPFileSizes
-
-Dumps info about current file
-=============
-*/
-void PrintBSPFileSizes (void)
-{
-	if (!num_entities)
-		ParseEntities ();
-
-	printf ("%5i models       %7i\n"
-		,nummodels, (int)(nummodels*sizeof(dmodel_t)));
-	printf ("%5i brushes      %7i\n"
-		,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
-	printf ("%5i brushsides   %7i\n"
-		,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
-	printf ("%5i planes       %7i\n"
-		,numplanes, (int)(numplanes*sizeof(dplane_t)));
-	printf ("%5i texinfo      %7i\n"
-		,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
-	printf ("%5i entdata      %7i\n", num_entities, entdatasize);
-
-	printf ("\n");
-
-	printf ("%5i vertexes     %7i\n"
-		,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
-	printf ("%5i nodes        %7i\n"
-		,numnodes, (int)(numnodes*sizeof(dnode_t)));
-	printf ("%5i faces        %7i\n"
-		,numfaces, (int)(numfaces*sizeof(dface_t)));
-	printf ("%5i leafs        %7i\n"
-		,numleafs, (int)(numleafs*sizeof(dleaf_t)));
-	printf ("%5i leaffaces    %7i\n"
-		,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
-	printf ("%5i leafbrushes  %7i\n"
-		,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
-	printf ("%5i surfedges    %7i\n"
-		,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
-	printf ("%5i edges        %7i\n"
-		,numedges, (int)(numedges*sizeof(dedge_t)));
-	printf ("      lightdata    %7i\n", lightdatasize);
-	printf ("      visdata      %7i\n", visdatasize);
-}
-
-
-//============================================
-
-int			num_entities;
-entity_t	entities[MAX_MAP_ENTITIES];
-
-void StripTrailing (char *e)
-{
-	char	*s;
-
-	s = e + strlen(e)-1;
-	while (s >= e && *s <= 32)
-	{
-		*s = 0;
-		s--;
-	}
-}
-
-/*
-=================
-ParseEpair
-=================
-*/
-epair_t *ParseEpair (void)
-{
-	epair_t	*e;
-
-	e = malloc (sizeof(epair_t));
-	memset (e, 0, sizeof(epair_t));
-	
-	if (strlen(token) >= MAX_KEY-1)
-		Error ("ParseEpar: token too long");
-	e->key = copystring(token);
-	GetScriptToken (false);
-	if (strlen(token) >= MAX_VALUE-1)
-		Error ("ParseEpar: token too long");
-	e->value = copystring(token);
-
-	// strip trailing spaces
-	StripTrailing (e->key);
-	StripTrailing (e->value);
-
-	return e;
-}
-
-
-/*
-================
-ParseEntity
-================
-*/
-qboolean	ParseEntity (void)
-{
-	epair_t		*e;
-	entity_t	*mapent;
-
-	if (!GetScriptToken (true))
-		return false;
-
-	if (strcmp (token, "{") )
-		Error ("ParseEntity: { not found");
-	
-	if (num_entities == MAX_MAP_ENTITIES)
-		Error ("num_entities == MAX_MAP_ENTITIES");
-
-	mapent = &entities[num_entities];
-	num_entities++;
-
-	do
-	{
-		if (!GetScriptToken (true))
-			Error ("ParseEntity: EOF without closing brace");
-		if (!strcmp (token, "}") )
-			break;
-		e = ParseEpair ();
-		e->next = mapent->epairs;
-		mapent->epairs = e;
-	} while (1);
-	
-	return true;
-}
-
-/*
-================
-ParseEntities
-
-Parses the dentdata string into entities
-================
-*/
-void ParseEntities (void)
-{
-	num_entities = 0;
-	ParseFromMemory (dentdata, entdatasize);
-
-	while (ParseEntity ())
-	{
-	}	
-}
-
-
-/*
-================
-UnparseEntities
-
-Generates the dentdata string from all the entities
-================
-*/
-void UnparseEntities (void)
-{
-	char	*buf, *end;
-	epair_t	*ep;
-	char	line[2048];
-	int		i;
-	char	key[1024], value[1024];
-
-	buf = dentdata;
-	end = buf;
-	*end = 0;
-	
-	for (i=0 ; i<num_entities ; i++)
-	{
-		ep = entities[i].epairs;
-		if (!ep)
-			continue;	// ent got removed
-		
-		strcat (end,"{\n");
-		end += 2;
-				
-		for (ep = entities[i].epairs ; ep ; ep=ep->next)
-		{
-			strcpy (key, ep->key);
-			StripTrailing (key);
-			strcpy (value, ep->value);
-			StripTrailing (value);
-				
-			sprintf (line, "\"%s\" \"%s\"\n", key, value);
-			strcat (end, line);
-			end += strlen(line);
-		}
-		strcat (end,"}\n");
-		end += 2;
-
-		if (end > buf + MAX_MAP_ENTSTRING)
-			Error ("Entity text too long");
-	}
-	entdatasize = end - buf + 1;
-}
-
-void PrintEntity (entity_t *ent)
-{
-	epair_t	*ep;
-	
-	printf ("------- entity %p -------\n", ent);
-	for (ep=ent->epairs ; ep ; ep=ep->next)
-	{
-		printf ("%s = %s\n", ep->key, ep->value);
-	}
-
-}
-
-void 	SetKeyValue (entity_t *ent, char *key, char *value)
-{
-	epair_t	*ep;
-	
-	for (ep=ent->epairs ; ep ; ep=ep->next)
-		if (!strcmp (ep->key, key) )
-		{
-			free (ep->value);
-			ep->value = copystring(value);
-			return;
-		}
-	ep = malloc (sizeof(*ep));
-	if (!ep)
-		Error("SetKeyValue MALLOC failed!  Could not allocate %s bytes.", sizeof(*ep));
-	ep->next = ent->epairs;
-	ent->epairs = ep;
-	ep->key = copystring(key);
-	ep->value = copystring(value);
-}
-
-char 	*ValueForKey (entity_t *ent, char *key)
-{
-	epair_t	*ep;
-	
-	for (ep=ent->epairs ; ep ; ep=ep->next)
-		if (!strcmp (ep->key, key) )
-			return ep->value;
-	return "";
-}
-
-vec_t	FloatForKey (entity_t *ent, char *key)
-{
-	char	*k;
-	
-	k = ValueForKey (ent, key);
-	return atof(k);
-}
-
-void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
-{
-	char	*k;
-	double	v1, v2, v3;
-
-	k = ValueForKey (ent, key);
-// scanf into doubles, then assign, so it is vec_t size independent
-	v1 = v2 = v3 = 0;
-	sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
-	vec[0] = v1;
-	vec[1] = v2;
-	vec[2] = v3;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "bspfile.h"
+#include "scriplib.h"
+
+void GetLeafNums (void);
+
+//=============================================================================
+
+int			nummodels;
+dmodel_t	dmodels[MAX_MAP_MODELS];
+
+int			visdatasize;
+byte		dvisdata[MAX_MAP_VISIBILITY];
+dvis_t		*dvis = (dvis_t *)dvisdata;
+
+int			lightdatasize;
+byte		dlightdata[MAX_MAP_LIGHTING];
+
+int			entdatasize;
+char		dentdata[MAX_MAP_ENTSTRING];
+
+int			numleafs;
+dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+int			numplanes;
+dplane_t	dplanes[MAX_MAP_PLANES];
+
+int			numvertexes;
+dvertex_t	dvertexes[MAX_MAP_VERTS];
+
+int			numnodes;
+dnode_t		dnodes[MAX_MAP_NODES];
+
+int			numtexinfo;
+texinfo_t	texinfo[MAX_MAP_TEXINFO];
+
+int			numfaces;
+dface_t		dfaces[MAX_MAP_FACES];
+
+int			numedges;
+dedge_t		dedges[MAX_MAP_EDGES];
+
+int			numleaffaces;
+unsigned short		dleaffaces[MAX_MAP_LEAFFACES];
+
+int			numleafbrushes;
+unsigned short		dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+int			numsurfedges;
+int			dsurfedges[MAX_MAP_SURFEDGES];
+
+int			numbrushes;
+dbrush_t	dbrushes[MAX_MAP_BRUSHES];
+
+int			numbrushsides;
+dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
+
+int			numareas;
+darea_t		dareas[MAX_MAP_AREAS];
+
+int			numareaportals;
+dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
+
+byte		dpop[256];
+
+/*
+===============
+CompressVis
+
+===============
+*/
+int CompressVis (byte *vis, byte *dest)
+{
+	int		j;
+	int		rep;
+	int		visrow;
+	byte	*dest_p;
+	
+	dest_p = dest;
+//	visrow = (r_numvisleafs + 7)>>3;
+	visrow = (dvis->numclusters + 7)>>3;
+	
+	for (j=0 ; j<visrow ; j++)
+	{
+		*dest_p++ = vis[j];
+		if (vis[j])
+			continue;
+
+		rep = 1;
+		for ( j++; j<visrow ; j++)
+			if (vis[j] || rep == 255)
+				break;
+			else
+				rep++;
+		*dest_p++ = rep;
+		j--;
+	}
+	
+	return dest_p - dest;
+}
+
+
+/*
+===================
+DecompressVis
+===================
+*/
+void DecompressVis (byte *in, byte *decompressed)
+{
+	int		c;
+	byte	*out;
+	int		row;
+
+//	row = (r_numvisleafs+7)>>3;	
+	row = (dvis->numclusters+7)>>3;	
+	out = decompressed;
+
+	do
+	{
+		if (*in)
+		{
+			*out++ = *in++;
+			continue;
+		}
+	
+		c = in[1];
+		if (!c)
+			Error ("DecompressVis: 0 repeat");
+		in += 2;
+		while (c)
+		{
+			*out++ = 0;
+			c--;
+		}
+	} while (out - decompressed < row);
+}
+
+//=============================================================================
+
+/*
+=============
+SwapBSPFile
+
+Byte swaps all data in a bsp file.
+=============
+*/
+void SwapBSPFile (qboolean todisk)
+{
+	int				i, j;
+	dmodel_t		*d;
+
+	
+// models	
+	for (i=0 ; i<nummodels ; i++)
+	{
+		d = &dmodels[i];
+
+		d->firstface = LittleLong (d->firstface);
+		d->numfaces = LittleLong (d->numfaces);
+		d->headnode = LittleLong (d->headnode);
+		
+		for (j=0 ; j<3 ; j++)
+		{
+			d->mins[j] = LittleFloat(d->mins[j]);
+			d->maxs[j] = LittleFloat(d->maxs[j]);
+			d->origin[j] = LittleFloat(d->origin[j]);
+		}
+	}
+
+//
+// vertexes
+//
+	for (i=0 ; i<numvertexes ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+			dvertexes[i].point[j] = LittleFloat (dvertexes[i].point[j]);
+	}
+		
+//
+// planes
+//	
+	for (i=0 ; i<numplanes ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+			dplanes[i].normal[j] = LittleFloat (dplanes[i].normal[j]);
+		dplanes[i].dist = LittleFloat (dplanes[i].dist);
+		dplanes[i].type = LittleLong (dplanes[i].type);
+	}
+	
+//
+// texinfos
+//	
+	for (i=0 ; i<numtexinfo ; i++)
+	{
+		for (j=0 ; j<8 ; j++)
+			texinfo[i].vecs[0][j] = LittleFloat (texinfo[i].vecs[0][j]);
+		texinfo[i].flags = LittleLong (texinfo[i].flags);
+		texinfo[i].value = LittleLong (texinfo[i].value);
+		texinfo[i].nexttexinfo = LittleLong (texinfo[i].nexttexinfo);
+	}
+	
+//
+// faces
+//
+	for (i=0 ; i<numfaces ; i++)
+	{
+		dfaces[i].texinfo = LittleShort (dfaces[i].texinfo);
+		dfaces[i].planenum = LittleShort (dfaces[i].planenum);
+		dfaces[i].side = LittleShort (dfaces[i].side);
+		dfaces[i].lighting.c = LittleLong (dfaces[i].lighting.c);
+		dfaces[i].lightofs = LittleLong (dfaces[i].lightofs);
+		dfaces[i].firstedge = LittleLong (dfaces[i].firstedge);
+		dfaces[i].numedges = LittleShort (dfaces[i].numedges);
+	}
+
+//
+// nodes
+//
+	for (i=0 ; i<numnodes ; i++)
+	{
+		dnodes[i].planenum = LittleLong (dnodes[i].planenum);
+		for (j=0 ; j<3 ; j++)
+		{
+			dnodes[i].mins[j] = LittleShort (dnodes[i].mins[j]);
+			dnodes[i].maxs[j] = LittleShort (dnodes[i].maxs[j]);
+		}
+		dnodes[i].children[0] = LittleLong (dnodes[i].children[0]);
+		dnodes[i].children[1] = LittleLong (dnodes[i].children[1]);
+		dnodes[i].firstface = LittleShort (dnodes[i].firstface);
+		dnodes[i].numfaces = LittleShort (dnodes[i].numfaces);
+	}
+
+//
+// leafs
+//
+	for (i=0 ; i<numleafs ; i++)
+	{
+		dleafs[i].contents = LittleLong (dleafs[i].contents);
+		dleafs[i].cluster = LittleShort (dleafs[i].cluster);
+		dleafs[i].area = LittleShort (dleafs[i].area);
+		for (j=0 ; j<3 ; j++)
+		{
+			dleafs[i].mins[j] = LittleShort (dleafs[i].mins[j]);
+			dleafs[i].maxs[j] = LittleShort (dleafs[i].maxs[j]);
+		}
+
+		dleafs[i].firstleafface = LittleShort (dleafs[i].firstleafface);
+		dleafs[i].numleaffaces = LittleShort (dleafs[i].numleaffaces);
+		dleafs[i].firstleafbrush = LittleShort (dleafs[i].firstleafbrush);
+		dleafs[i].numleafbrushes = LittleShort (dleafs[i].numleafbrushes);
+	}
+
+//
+// leaffaces
+//
+	for (i=0 ; i<numleaffaces ; i++)
+		dleaffaces[i] = LittleShort (dleaffaces[i]);
+
+//
+// leafbrushes
+//
+	for (i=0 ; i<numleafbrushes ; i++)
+		dleafbrushes[i] = LittleShort (dleafbrushes[i]);
+
+//
+// surfedges
+//
+	for (i=0 ; i<numsurfedges ; i++)
+		dsurfedges[i] = LittleLong (dsurfedges[i]);
+
+//
+// edges
+//
+	for (i=0 ; i<numedges ; i++)
+	{
+		dedges[i].v[0] = LittleShort (dedges[i].v[0]);
+		dedges[i].v[1] = LittleShort (dedges[i].v[1]);
+	}
+
+//
+// brushes
+//
+	for (i=0 ; i<numbrushes ; i++)
+	{
+		dbrushes[i].firstside = LittleLong (dbrushes[i].firstside);
+		dbrushes[i].numsides = LittleLong (dbrushes[i].numsides);
+		dbrushes[i].contents = LittleLong (dbrushes[i].contents);
+	}
+
+//
+// areas
+//
+	for (i=0 ; i<numareas ; i++)
+	{
+		dareas[i].numareaportals = LittleLong (dareas[i].numareaportals);
+		dareas[i].firstareaportal = LittleLong (dareas[i].firstareaportal);
+	}
+
+//
+// areasportals
+//
+	for (i=0 ; i<numareaportals ; i++)
+	{
+		dareaportals[i].portalnum = LittleLong (dareaportals[i].portalnum);
+		dareaportals[i].otherarea = LittleLong (dareaportals[i].otherarea);
+	}
+
+//
+// brushsides
+//
+	for (i=0 ; i<numbrushsides ; i++)
+	{
+		dbrushsides[i].planenum = LittleShort (dbrushsides[i].planenum);
+		dbrushsides[i].texinfo = LittleShort (dbrushsides[i].texinfo);
+	}
+
+//
+// visibility
+//
+	if (todisk)
+		j = dvis->numclusters;
+	else
+		j = LittleLong(dvis->numclusters);
+	dvis->numclusters = LittleLong (dvis->numclusters);
+	for (i=0 ; i<j ; i++)
+	{
+		dvis->bitofs[i][0] = LittleLong (dvis->bitofs[i][0]);
+		dvis->bitofs[i][1] = LittleLong (dvis->bitofs[i][1]);
+	}
+}
+
+
+dheader_t	*header;
+
+int CopyLump (int lump, void *dest, int size)
+{
+	int		length, ofs;
+
+	length = header->lumps[lump].filelen;
+	ofs = header->lumps[lump].fileofs;
+	
+	if (length % size)
+		Error ("LoadBSPFile: odd lump size");
+	
+	memcpy (dest, (byte *)header + ofs, length);
+
+	return length / size;
+}
+
+/*
+=============
+LoadBSPFile
+=============
+*/
+void	LoadBSPFile (char *filename)
+{
+	int			i;
+	
+//
+// load the file header
+//
+	LoadFile (filename, (void **)&header);
+
+// swap the header
+	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+	if (header->ident != IDBSPHEADER)
+		Error ("%s is not a IBSP file", filename);
+	if (header->version != BSPVERSION)
+		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
+
+	nummodels = CopyLump (LUMP_MODELS, dmodels, sizeof(dmodel_t));
+	numvertexes = CopyLump (LUMP_VERTEXES, dvertexes, sizeof(dvertex_t));
+	numplanes = CopyLump (LUMP_PLANES, dplanes, sizeof(dplane_t));
+	numleafs = CopyLump (LUMP_LEAFS, dleafs, sizeof(dleaf_t));
+	numnodes = CopyLump (LUMP_NODES, dnodes, sizeof(dnode_t));
+	numtexinfo = CopyLump (LUMP_TEXINFO, texinfo, sizeof(texinfo_t));
+	numfaces = CopyLump (LUMP_FACES, dfaces, sizeof(dface_t));
+	numleaffaces = CopyLump (LUMP_LEAFFACES, dleaffaces, sizeof(dleaffaces[0]));
+	numleafbrushes = CopyLump (LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]));
+	numsurfedges = CopyLump (LUMP_SURFEDGES, dsurfedges, sizeof(dsurfedges[0]));
+	numedges = CopyLump (LUMP_EDGES, dedges, sizeof(dedge_t));
+	numbrushes = CopyLump (LUMP_BRUSHES, dbrushes, sizeof(dbrush_t));
+	numbrushsides = CopyLump (LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t));
+	numareas = CopyLump (LUMP_AREAS, dareas, sizeof(darea_t));
+	numareaportals = CopyLump (LUMP_AREAPORTALS, dareaportals, sizeof(dareaportal_t));
+
+	visdatasize = CopyLump (LUMP_VISIBILITY, dvisdata, 1);
+	lightdatasize = CopyLump (LUMP_LIGHTING, dlightdata, 1);
+	entdatasize = CopyLump (LUMP_ENTITIES, dentdata, 1);
+
+	CopyLump (LUMP_POP, dpop, 1);
+
+	free (header);		// everything has been copied out
+		
+//
+// swap everything
+//	
+	SwapBSPFile (false);
+}
+
+
+/*
+=============
+LoadBSPFileTexinfo
+
+Only loads the texinfo lump, so qdata can scan for textures
+=============
+*/
+void	LoadBSPFileTexinfo (char *filename)
+{
+	int			i;
+	FILE		*f;
+	int		length, ofs;
+
+	header = malloc(sizeof(dheader_t));
+
+	f = fopen (filename, "rb");
+	fread (header, sizeof(dheader_t), 1, f);
+
+// swap the header
+	for (i=0 ; i< sizeof(dheader_t)/4 ; i++)
+		((int *)header)[i] = LittleLong ( ((int *)header)[i]);
+
+	if (header->ident != IDBSPHEADER)
+		Error ("%s is not a IBSP file", filename);
+	if (header->version != BSPVERSION)
+		Error ("%s is version %i, not %i", filename, header->version, BSPVERSION);
+
+
+	length = header->lumps[LUMP_TEXINFO].filelen;
+	ofs = header->lumps[LUMP_TEXINFO].fileofs;
+
+	fseek (f, ofs, SEEK_SET);
+	fread (texinfo, length, 1, f);
+	fclose (f);
+
+	numtexinfo = length / sizeof(texinfo_t);
+
+	free (header);		// everything has been copied out
+		
+	SwapBSPFile (false);
+}
+
+
+//============================================================================
+
+FILE		*wadfile;
+dheader_t	outheader;
+
+void AddLump (int lumpnum, void *data, int len)
+{
+	lump_t *lump;
+
+	lump = &header->lumps[lumpnum];
+	
+	lump->fileofs = LittleLong( ftell(wadfile) );
+	lump->filelen = LittleLong(len);
+	SafeWrite (wadfile, data, (len+3)&~3);
+}
+
+/*
+=============
+WriteBSPFile
+
+Swaps the bsp file in place, so it should not be referenced again
+=============
+*/
+void	WriteBSPFile (char *filename)
+{		
+	header = &outheader;
+	memset (header, 0, sizeof(dheader_t));
+	
+	SwapBSPFile (true);
+
+	header->ident = LittleLong (IDBSPHEADER);
+	header->version = LittleLong (BSPVERSION);
+	
+	wadfile = SafeOpenWrite (filename);
+	SafeWrite (wadfile, header, sizeof(dheader_t));	// overwritten later
+
+	AddLump (LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t));
+	AddLump (LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t));
+	AddLump (LUMP_VERTEXES, dvertexes, numvertexes*sizeof(dvertex_t));
+	AddLump (LUMP_NODES, dnodes, numnodes*sizeof(dnode_t));
+	AddLump (LUMP_TEXINFO, texinfo, numtexinfo*sizeof(texinfo_t));
+	AddLump (LUMP_FACES, dfaces, numfaces*sizeof(dface_t));
+	AddLump (LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t));
+	AddLump (LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t));
+	AddLump (LUMP_LEAFFACES, dleaffaces, numleaffaces*sizeof(dleaffaces[0]));
+	AddLump (LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]));
+	AddLump (LUMP_SURFEDGES, dsurfedges, numsurfedges*sizeof(dsurfedges[0]));
+	AddLump (LUMP_EDGES, dedges, numedges*sizeof(dedge_t));
+	AddLump (LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t));
+	AddLump (LUMP_AREAS, dareas, numareas*sizeof(darea_t));
+	AddLump (LUMP_AREAPORTALS, dareaportals, numareaportals*sizeof(dareaportal_t));
+
+	AddLump (LUMP_LIGHTING, dlightdata, lightdatasize);
+	AddLump (LUMP_VISIBILITY, dvisdata, visdatasize);
+	AddLump (LUMP_ENTITIES, dentdata, entdatasize);
+	AddLump (LUMP_POP, dpop, sizeof(dpop));
+	
+	fseek (wadfile, 0, SEEK_SET);
+	SafeWrite (wadfile, header, sizeof(dheader_t));
+	fclose (wadfile);	
+}
+
+//============================================================================
+
+/*
+=============
+PrintBSPFileSizes
+
+Dumps info about current file
+=============
+*/
+void PrintBSPFileSizes (void)
+{
+	if (!num_entities)
+		ParseEntities ();
+
+	printf ("%5i models       %7i\n"
+		,nummodels, (int)(nummodels*sizeof(dmodel_t)));
+	printf ("%5i brushes      %7i\n"
+		,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
+	printf ("%5i brushsides   %7i\n"
+		,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
+	printf ("%5i planes       %7i\n"
+		,numplanes, (int)(numplanes*sizeof(dplane_t)));
+	printf ("%5i texinfo      %7i\n"
+		,numtexinfo, (int)(numtexinfo*sizeof(texinfo_t)));
+	printf ("%5i entdata      %7i\n", num_entities, entdatasize);
+
+	printf ("\n");
+
+	printf ("%5i vertexes     %7i\n"
+		,numvertexes, (int)(numvertexes*sizeof(dvertex_t)));
+	printf ("%5i nodes        %7i\n"
+		,numnodes, (int)(numnodes*sizeof(dnode_t)));
+	printf ("%5i faces        %7i\n"
+		,numfaces, (int)(numfaces*sizeof(dface_t)));
+	printf ("%5i leafs        %7i\n"
+		,numleafs, (int)(numleafs*sizeof(dleaf_t)));
+	printf ("%5i leaffaces    %7i\n"
+		,numleaffaces, (int)(numleaffaces*sizeof(dleaffaces[0])));
+	printf ("%5i leafbrushes  %7i\n"
+		,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
+	printf ("%5i surfedges    %7i\n"
+		,numsurfedges, (int)(numsurfedges*sizeof(dsurfedges[0])));
+	printf ("%5i edges        %7i\n"
+		,numedges, (int)(numedges*sizeof(dedge_t)));
+	printf ("      lightdata    %7i\n", lightdatasize);
+	printf ("      visdata      %7i\n", visdatasize);
+}
+
+
+//============================================
+
+int			num_entities;
+entity_t	entities[MAX_MAP_ENTITIES];
+
+void StripTrailing (char *e)
+{
+	char	*s;
+
+	s = e + strlen(e)-1;
+	while (s >= e && *s <= 32)
+	{
+		*s = 0;
+		s--;
+	}
+}
+
+/*
+=================
+ParseEpair
+=================
+*/
+epair_t *ParseEpair (void)
+{
+	epair_t	*e;
+
+	e = malloc (sizeof(epair_t));
+	memset (e, 0, sizeof(epair_t));
+	
+	if (strlen(token) >= MAX_KEY-1)
+		Error ("ParseEpar: token too long");
+	e->key = copystring(token);
+	GetScriptToken (false);
+	if (strlen(token) >= MAX_VALUE-1)
+		Error ("ParseEpar: token too long");
+	e->value = copystring(token);
+
+	// strip trailing spaces
+	StripTrailing (e->key);
+	StripTrailing (e->value);
+
+	return e;
+}
+
+
+/*
+================
+ParseEntity
+================
+*/
+qboolean	ParseEntity (void)
+{
+	epair_t		*e;
+	entity_t	*mapent;
+
+	if (!GetScriptToken (true))
+		return false;
+
+	if (strcmp (token, "{") )
+		Error ("ParseEntity: { not found");
+	
+	if (num_entities == MAX_MAP_ENTITIES)
+		Error ("num_entities == MAX_MAP_ENTITIES");
+
+	mapent = &entities[num_entities];
+	num_entities++;
+
+	do
+	{
+		if (!GetScriptToken (true))
+			Error ("ParseEntity: EOF without closing brace");
+		if (!strcmp (token, "}") )
+			break;
+		e = ParseEpair ();
+		e->next = mapent->epairs;
+		mapent->epairs = e;
+	} while (1);
+	
+	return true;
+}
+
+/*
+================
+ParseEntities
+
+Parses the dentdata string into entities
+================
+*/
+void ParseEntities (void)
+{
+	num_entities = 0;
+	ParseFromMemory (dentdata, entdatasize);
+
+	while (ParseEntity ())
+	{
+	}	
+}
+
+
+/*
+================
+UnparseEntities
+
+Generates the dentdata string from all the entities
+================
+*/
+void UnparseEntities (void)
+{
+	char	*buf, *end;
+	epair_t	*ep;
+	char	line[2048];
+	int		i;
+	char	key[1024], value[1024];
+
+	buf = dentdata;
+	end = buf;
+	*end = 0;
+	
+	for (i=0 ; i<num_entities ; i++)
+	{
+		ep = entities[i].epairs;
+		if (!ep)
+			continue;	// ent got removed
+		
+		strcat (end,"{\n");
+		end += 2;
+				
+		for (ep = entities[i].epairs ; ep ; ep=ep->next)
+		{
+			strcpy (key, ep->key);
+			StripTrailing (key);
+			strcpy (value, ep->value);
+			StripTrailing (value);
+				
+			sprintf (line, "\"%s\" \"%s\"\n", key, value);
+			strcat (end, line);
+			end += strlen(line);
+		}
+		strcat (end,"}\n");
+		end += 2;
+
+		if (end > buf + MAX_MAP_ENTSTRING)
+			Error ("Entity text too long");
+	}
+	entdatasize = end - buf + 1;
+}
+
+void PrintEntity (entity_t *ent)
+{
+	epair_t	*ep;
+	
+	printf ("------- entity %p -------\n", ent);
+	for (ep=ent->epairs ; ep ; ep=ep->next)
+	{
+		printf ("%s = %s\n", ep->key, ep->value);
+	}
+
+}
+
+void 	SetKeyValue (entity_t *ent, char *key, char *value)
+{
+	epair_t	*ep;
+	
+	for (ep=ent->epairs ; ep ; ep=ep->next)
+		if (!strcmp (ep->key, key) )
+		{
+			free (ep->value);
+			ep->value = copystring(value);
+			return;
+		}
+	ep = malloc (sizeof(*ep));
+	if (!ep)
+		Error("SetKeyValue MALLOC failed!  Could not allocate %s bytes.", sizeof(*ep));
+	ep->next = ent->epairs;
+	ent->epairs = ep;
+	ep->key = copystring(key);
+	ep->value = copystring(value);
+}
+
+char 	*ValueForKey (entity_t *ent, char *key)
+{
+	epair_t	*ep;
+	
+	for (ep=ent->epairs ; ep ; ep=ep->next)
+		if (!strcmp (ep->key, key) )
+			return ep->value;
+	return "";
+}
+
+vec_t	FloatForKey (entity_t *ent, char *key)
+{
+	char	*k;
+	
+	k = ValueForKey (ent, key);
+	return atof(k);
+}
+
+void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec)
+{
+	char	*k;
+	double	v1, v2, v3;
+
+	k = ValueForKey (ent, key);
+// scanf into doubles, then assign, so it is vec_t size independent
+	v1 = v2 = v3 = 0;
+	sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
+	vec[0] = v1;
+	vec[1] = v2;
+	vec[2] = v3;
+}
+
+
diff --git a/tools/quake2/qdata_heretic2/common/bspfile.h b/tools/quake2/qdata_heretic2/common/bspfile.h
index c08cf6c9..4e5453bb 100644
--- a/tools/quake2/qdata_heretic2/common/bspfile.h
+++ b/tools/quake2/qdata_heretic2/common/bspfile.h
@@ -1,133 +1,133 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _QBSP3_H
-#define _QBSP3_H
-
-
-#include "qfiles.h"
-
-
-extern	int			nummodels;
-extern	dmodel_t	dmodels[MAX_MAP_MODELS];
-
-extern	int			visdatasize;
-extern	byte		dvisdata[MAX_MAP_VISIBILITY];
-extern	dvis_t		*dvis;
-
-extern	int			lightdatasize;
-extern	byte		dlightdata[MAX_MAP_LIGHTING];
-
-extern	int			entdatasize;
-extern	char		dentdata[MAX_MAP_ENTSTRING];
-
-extern	int			numleafs;
-extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
-
-extern	int			numplanes;
-extern	dplane_t	dplanes[MAX_MAP_PLANES];
-
-extern	int			numvertexes;
-extern	dvertex_t	dvertexes[MAX_MAP_VERTS];
-
-extern	int			numnodes;
-extern	dnode_t		dnodes[MAX_MAP_NODES];
-
-extern	int			numtexinfo;
-extern	texinfo_t	texinfo[MAX_MAP_TEXINFO];
-
-extern	int			numfaces;
-extern	dface_t		dfaces[MAX_MAP_FACES];
-
-extern	int			numedges;
-extern	dedge_t		dedges[MAX_MAP_EDGES];
-
-extern	int			numleaffaces;
-extern	unsigned short	dleaffaces[MAX_MAP_LEAFFACES];
-
-extern	int			numleafbrushes;
-extern	unsigned short	dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-extern	int			numsurfedges;
-extern	int			dsurfedges[MAX_MAP_SURFEDGES];
-
-extern	int			numareas;
-extern	darea_t		dareas[MAX_MAP_AREAS];
-
-extern	int			numareaportals;
-extern	dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
-
-extern	int			numbrushes;
-extern	dbrush_t	dbrushes[MAX_MAP_BRUSHES];
-
-extern	int			numbrushsides;
-extern	dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
-
-extern	byte		dpop[256];
-
-void DecompressVis (byte *in, byte *decompressed);
-int CompressVis (byte *vis, byte *dest);
-
-void	LoadBSPFile (char *filename);
-void	LoadBSPFileTexinfo (char *filename);	// just for qdata
-void	WriteBSPFile (char *filename);
-void	PrintBSPFileSizes (void);
-
-//===============
-
-
-typedef struct epair_s
-{
-	struct epair_s	*next;
-	char	*key;
-	char	*value;
-} epair_t;
-
-typedef struct
-{
-	vec3_t		origin;
-	int			firstbrush;
-	int			numbrushes;
-	epair_t		*epairs;
-
-// only valid for func_areaportals
-	int			areaportalnum;
-	int			portalareas[2];
-} entity_t;
-
-extern	int			num_entities;
-extern	entity_t	entities[MAX_MAP_ENTITIES];
-
-void	ParseEntities (void);
-void	UnparseEntities (void);
-
-void 	SetKeyValue (entity_t *ent, char *key, char *value);
-char 	*ValueForKey (entity_t *ent, char *key);
-// will return "" if not present
-
-vec_t	FloatForKey (entity_t *ent, char *key);
-void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
-
-epair_t *ParseEpair (void);
-
-void PrintEntity (entity_t *ent);
-
-#endif //_QBSP3_H
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _QBSP3_H
+#define _QBSP3_H
+
+
+#include "qfiles.h"
+
+
+extern	int			nummodels;
+extern	dmodel_t	dmodels[MAX_MAP_MODELS];
+
+extern	int			visdatasize;
+extern	byte		dvisdata[MAX_MAP_VISIBILITY];
+extern	dvis_t		*dvis;
+
+extern	int			lightdatasize;
+extern	byte		dlightdata[MAX_MAP_LIGHTING];
+
+extern	int			entdatasize;
+extern	char		dentdata[MAX_MAP_ENTSTRING];
+
+extern	int			numleafs;
+extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+extern	int			numplanes;
+extern	dplane_t	dplanes[MAX_MAP_PLANES];
+
+extern	int			numvertexes;
+extern	dvertex_t	dvertexes[MAX_MAP_VERTS];
+
+extern	int			numnodes;
+extern	dnode_t		dnodes[MAX_MAP_NODES];
+
+extern	int			numtexinfo;
+extern	texinfo_t	texinfo[MAX_MAP_TEXINFO];
+
+extern	int			numfaces;
+extern	dface_t		dfaces[MAX_MAP_FACES];
+
+extern	int			numedges;
+extern	dedge_t		dedges[MAX_MAP_EDGES];
+
+extern	int			numleaffaces;
+extern	unsigned short	dleaffaces[MAX_MAP_LEAFFACES];
+
+extern	int			numleafbrushes;
+extern	unsigned short	dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+extern	int			numsurfedges;
+extern	int			dsurfedges[MAX_MAP_SURFEDGES];
+
+extern	int			numareas;
+extern	darea_t		dareas[MAX_MAP_AREAS];
+
+extern	int			numareaportals;
+extern	dareaportal_t	dareaportals[MAX_MAP_AREAPORTALS];
+
+extern	int			numbrushes;
+extern	dbrush_t	dbrushes[MAX_MAP_BRUSHES];
+
+extern	int			numbrushsides;
+extern	dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
+
+extern	byte		dpop[256];
+
+void DecompressVis (byte *in, byte *decompressed);
+int CompressVis (byte *vis, byte *dest);
+
+void	LoadBSPFile (char *filename);
+void	LoadBSPFileTexinfo (char *filename);	// just for qdata
+void	WriteBSPFile (char *filename);
+void	PrintBSPFileSizes (void);
+
+//===============
+
+
+typedef struct epair_s
+{
+	struct epair_s	*next;
+	char	*key;
+	char	*value;
+} epair_t;
+
+typedef struct
+{
+	vec3_t		origin;
+	int			firstbrush;
+	int			numbrushes;
+	epair_t		*epairs;
+
+// only valid for func_areaportals
+	int			areaportalnum;
+	int			portalareas[2];
+} entity_t;
+
+extern	int			num_entities;
+extern	entity_t	entities[MAX_MAP_ENTITIES];
+
+void	ParseEntities (void);
+void	UnparseEntities (void);
+
+void 	SetKeyValue (entity_t *ent, char *key, char *value);
+char 	*ValueForKey (entity_t *ent, char *key);
+// will return "" if not present
+
+vec_t	FloatForKey (entity_t *ent, char *key);
+void 	GetVectorForKey (entity_t *ent, char *key, vec3_t vec);
+
+epair_t *ParseEpair (void);
+
+void PrintEntity (entity_t *ent);
+
+#endif //_QBSP3_H
diff --git a/tools/quake2/qdata_heretic2/common/cmdlib.c b/tools/quake2/qdata_heretic2/common/cmdlib.c
index 1eeb3c49..c5f5c3a6 100644
--- a/tools/quake2/qdata_heretic2/common/cmdlib.c
+++ b/tools/quake2/qdata_heretic2/common/cmdlib.c
@@ -1,1238 +1,1238 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// Nurail: Swiped from quake3/common
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <windows.h>
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-#include <unistd.h>
-#endif
-
-#ifdef NeXT
-#include <libc.h>
-#endif
-
-#define	BASEDIRNAME	"h"		
-#define PATHSEPERATOR   '/'
-
-extern qboolean verbose;
-
-qboolean	g_dokeypress = false;
-
-qboolean	g_nomkdir = false;
-
-
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size )
-{
-  void *p;
-
-  p = malloc(size);
-  if(!p)
-    Error ("safe_malloc failed on allocation of %i bytes", size);
-
-  return p;
-}
-
-void *safe_malloc_info( size_t size, char* info )
-{
-  void *p;
-
-  p = malloc(size);
-  if(!p)
-    Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
-
-  return p;
-}
-#endif
-
-void *SafeMalloc(size_t n, char *desc)
-{
-	void *p;
-
-	if((p = malloc(n)) == NULL)
-	{
-		Error("Failed to allocate %d bytes for '%s'.\n", n, desc);
-	}
-	memset(p, 0, n);
-	return p;
-}
-
-#if defined (__linux__) || defined (__APPLE__)
-void strlwr(char *conv_str)
-{
-	int i;
-
-	for(i=0; i<strlen(conv_str); i++)
-		conv_str[i]=tolower(conv_str[i]);
-}
-#endif
-
-
-// set these before calling CheckParm
-int myargc;
-char **myargv;
-
-char		com_token[1024];
-qboolean	com_eof;
-
-qboolean		archive;
-char			archivedir[1024];
-
-
-/*
-===================
-ExpandWildcards
-
-Mimic unix command line expansion
-===================
-*/
-#define	MAX_EX_ARGC	1024
-int		ex_argc;
-char	*ex_argv[MAX_EX_ARGC];
-#ifdef _WIN32
-#include "io.h"
-void ExpandWildcards( int *argc, char ***argv )
-{
-	struct _finddata_t fileinfo;
-	int		handle;
-	int		i;
-	char	filename[1024];
-	char	filebase[1024];
-	char	*path;
-
-	ex_argc = 0;
-	for (i=0 ; i<*argc ; i++)
-	{
-		path = (*argv)[i];
-		if ( path[0] == '-'
-			|| ( !strstr(path, "*") && !strstr(path, "?") ) )
-		{
-			ex_argv[ex_argc++] = path;
-			continue;
-		}
-
-		handle = _findfirst (path, &fileinfo);
-		if (handle == -1)
-			return;
-
-		ExtractFilePath (path, filebase);
-
-		do
-		{
-			sprintf (filename, "%s%s", filebase, fileinfo.name);
-			ex_argv[ex_argc++] = copystring (filename);
-		} while (_findnext( handle, &fileinfo ) != -1);
-
-		_findclose (handle);
-	}
-
-	*argc = ex_argc;
-	*argv = ex_argv;
-}
-#else
-void ExpandWildcards (int *argc, char ***argv)
-{
-}
-#endif
-
-/*
-
-qdir will hold the path up to the quake directory, including the slash
-
-  f:\quake\
-  /raid/quake/
-
-gamedir will hold qdir + the game directory (id1, id2, etc)
-
-*/
-
-char		qdir[1024];
-char		gamedir[1024];
-char		writedir[1024];
-
-void SetQdirFromPath( const char *path )
-{
-	char	temp[1024];
-	const char	*c;
-  const char *sep;
-	int		len, count;
-
-	if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
-	{	// path is partial
-		Q_getwd (temp);
-		strcat (temp, path);
-		path = temp;
-	}
-
-	// search for "quake2" in path
-
-	len = strlen(BASEDIRNAME);
-	for (c=path+strlen(path)-1 ; c != path ; c--)
-	{
-		int i;
-
-		if (!Q_strncasecmp (c, BASEDIRNAME, len))
-		{
-      //
-			//strncpy (qdir, path, c+len+2-path);
-      // the +2 assumes a 2 or 3 following quake which is not the
-      // case with a retail install
-      // so we need to add up how much to the next separator
-      sep = c + len;
-      count = 1;
-      while (*sep && *sep != '/' && *sep != '\\')
-      {
-        sep++;
-        count++;
-      }
-			strncpy (qdir, path, c+len+count-path);
-			Sys_Printf ("qdir: %s\n", qdir);
-			for ( i = 0; i < strlen( qdir ); i++ )
-			{
-				if ( qdir[i] == '\\' ) 
-					qdir[i] = '/';
-			}
-
-			c += len+count;
-			while (*c)
-			{
-				if (*c == '/' || *c == '\\')
-				{
-					strncpy (gamedir, path, c+1-path);
-
-					for ( i = 0; i < strlen( gamedir ); i++ )
-					{
-						if ( gamedir[i] == '\\' ) 
-							gamedir[i] = '/';
-					}
-
-					Sys_Printf ("gamedir: %s\n", gamedir);
-
-					if ( !writedir[0] )
-						strcpy( writedir, gamedir );
-					else if ( writedir[strlen( writedir )-1] != '/' )
-					{
-						writedir[strlen( writedir )] = '/';
-						writedir[strlen( writedir )+1] = 0;
-					}
-
-					return;
-				}
-				c++;
-			}
-			Error ("No gamedir in %s", path);
-			return;
-		}
-	}
-	Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
-}
-
-char *ExpandArg (const char *path)
-{
-	static char full[1024];
-
-	if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
-	{
-		Q_getwd (full);
-		strcat (full, path);
-	}
-	else
-		strcpy (full, path);
-	return full;
-}
-
-char *ExpandPath (const char *path)
-{
-	static char full[1024];
-	if (!qdir)
-		Error ("ExpandPath called without qdir set");
-	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
-		strcpy( full, path );
-		return full;
-	}
-	sprintf (full, "%s%s", qdir, path);
-	return full;
-}
-
-char *ExpandGamePath (const char *path)
-{
-	static char full[1024];
-	if (!qdir)
-		Error ("ExpandGamePath called without qdir set");
-	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
-		strcpy( full, path );
-		return full;
-	}
-	sprintf (full, "%s%s", gamedir, path);
-	return full;
-}
-
-char *ExpandPathAndArchive (const char *path)
-{
-	char	*expanded;
-	char	archivename[1024];
-
-	expanded = ExpandPath (path);
-
-	if (archive)
-	{
-		sprintf (archivename, "%s/%s", archivedir, path);
-		QCopyFile (expanded, archivename);
-	}
-	return expanded;
-}
-
-
-char *copystring(const char *s)
-{
-	char	*b;
-	b = safe_malloc(strlen(s)+1);
-	strcpy (b, s);
-	return b;
-}
-
-
-
-/*
-================
-I_FloatTime
-================
-*/
-double I_FloatTime (void)
-{
-	time_t	t;
-	
-	time (&t);
-	
-	return t;
-#if 0
-// more precise, less portable
-	struct timeval tp;
-	struct timezone tzp;
-	static int		secbase;
-
-	gettimeofday(&tp, &tzp);
-	
-	if (!secbase)
-	{
-		secbase = tp.tv_sec;
-		return tp.tv_usec/1000000.0;
-	}
-	
-	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
-#endif
-}
-
-void Q_getwd (char *out)
-{
-	int i = 0;
-
-#ifdef _WIN32
-   _getcwd (out, 256);
-   strcat (out, "\\");
-#else
-   // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
-   getcwd (out, 256);
-   strcat (out, "/");
-#endif
-   while ( out[i] != 0 )
-   {
-	   if ( out[i] == '\\' )
-		   out[i] = '/';
-	   i++;
-   }
-}
-
-
-void Q_mkdir (const char *path)
-{
-#ifdef _WIN32
-	if (_mkdir (path) != -1)
-		return;
-#else
-	if (mkdir (path, 0777) != -1)
-		return;
-#endif
-	if (errno != EEXIST)
-		Error ("mkdir %s: %s",path, strerror(errno));
-}
-
-/*
-============
-FileTime
-
-returns -1 if not present
-============
-*/
-int	FileTime (const char *path)
-{
-	struct	stat	buf;
-	
-	if (stat (path,&buf) == -1)
-		return -1;
-	
-	return buf.st_mtime;
-}
-
-
-
-/*
-==============
-COM_Parse
-
-Parse a token out of a string
-==============
-*/
-char *COM_Parse (char *data)
-{
-	int		c;
-	int		len;
-	
-	len = 0;
-	com_token[0] = 0;
-	
-	if (!data)
-		return NULL;
-		
-// skip whitespace
-skipwhite:
-	while ( (c = *data) <= ' ')
-	{
-		if (c == 0)
-		{
-			com_eof = true;
-			return NULL;			// end of file;
-		}
-		data++;
-	}
-	
-// skip // comments
-	if (c=='/' && data[1] == '/')
-	{
-		while (*data && *data != '\n')
-			data++;
-		goto skipwhite;
-	}
-	
-
-// handle quoted strings specially
-	if (c == '\"')
-	{
-		data++;
-		do
-		{
-			c = *data++;
-			if (c=='\"')
-			{
-				com_token[len] = 0;
-				return data;
-			}
-			com_token[len] = c;
-			len++;
-		} while (1);
-	}
-
-// parse single characters
-	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
-	{
-		com_token[len] = c;
-		len++;
-		com_token[len] = 0;
-		return data+1;
-	}
-
-// parse a regular word
-	do
-	{
-		com_token[len] = c;
-		data++;
-		len++;
-		c = *data;
-	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
-			break;
-	} while (c>32);
-	
-	com_token[len] = 0;
-	return data;
-}
-
-int Q_strncasecmp (const char *s1, const char *s2, int n)
-{
-	int		c1, c2;
-	
-	do
-	{
-		c1 = *s1++;
-		c2 = *s2++;
-
-		if (!n--)
-			return 0;		// strings are equal until end point
-		
-		if (c1 != c2)
-		{
-			if (c1 >= 'a' && c1 <= 'z')
-				c1 -= ('a' - 'A');
-			if (c2 >= 'a' && c2 <= 'z')
-				c2 -= ('a' - 'A');
-			if (c1 != c2)
-				return -1;		// strings not equal
-		}
-	} while (c1);
-	
-	return 0;		// strings are equal
-}
-
-int Q_stricmp (const char *s1, const char *s2)
-{
-	return Q_strncasecmp (s1, s2, 99999);
-}
-
-int Q_strcasecmp (const char *s1, const char *s2)
-{
-	return Q_strncasecmp (s1, s2, 99999);
-}
-
-// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
-//   started getting warnings about that function, prolly a duplicate with the runtime function
-//   maybe we still need to have it in linux builds
-/*
-char *strupr (char *start)
-{
-	char	*in;
-	in = start;
-	while (*in)
-	{
-		*in = toupper(*in);
-		in++;
-	}
-	return start;
-}
-*/
-
-char *strlower (char *start)
-{
-	char	*in;
-	in = start;
-	while (*in)
-	{
-		*in = tolower(*in); 
-		in++;
-	}
-	return start;
-}
-
-
-/*
-=============================================================================
-
-						MISC FUNCTIONS
-
-=============================================================================
-*/
-
-
-/*
-=================
-CheckParm
-
-Checks for the given parameter in the program's command line arguments
-Returns the argument number (1 to argc-1) or 0 if not present
-=================
-*/
-int CheckParm (const char *check)
-{
-	int             i;
-
-	for (i = 1;i<myargc;i++)
-	{
-		if ( !Q_stricmp(check, myargv[i]) )
-			return i;
-	}
-
-	return 0;
-}
-
-
-
-/*
-================
-Q_filelength
-================
-*/
-int Q_filelength (FILE *f)
-{
-	int		pos;
-	int		end;
-
-	pos = ftell (f);
-	fseek (f, 0, SEEK_END);
-	end = ftell (f);
-	fseek (f, pos, SEEK_SET);
-
-	return end;
-}
-
-
-FILE *SafeOpenWrite (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen(filename, "wb");
-
-	if (!f)
-		Error ("Error opening %s: %s",filename,strerror(errno));
-
-	return f;
-}
-
-FILE *SafeOpenRead (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen(filename, "rb");
-
-	if (!f)
-		Error ("Error opening %s: %s",filename,strerror(errno));
-
-	return f;
-}
-
-
-void SafeRead (FILE *f, void *buffer, int count)
-{
-	if ( fread (buffer, 1, count, f) != (size_t)count)
-		Error ("File read failure");
-}
-
-
-void SafeWrite (FILE *f, const void *buffer, int count)
-{
-	if (fwrite (buffer, 1, count, f) != (size_t)count)
-		Error ("File write failure");
-}
-
-
-/*
-==============
-FileExists
-==============
-*/
-qboolean	FileExists (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen (filename, "r");
-	if (!f)
-		return false;
-	fclose (f);
-	return true;
-}
-
-/*
-==============
-LoadFile
-==============
-*/
-int    LoadFile( const char *filename, void **bufferptr )
-{
-	FILE	*f;
-	int    length;
-	void    *buffer;
-
-	f = SafeOpenRead (filename);
-	length = Q_filelength (f);
-	buffer = safe_malloc (length+1);
-	((char *)buffer)[length] = 0;
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-LoadFileBlock
--
-rounds up memory allocation to 4K boundry
--
-==============
-*/
-int    LoadFileBlock( const char *filename, void **bufferptr )
-{
-	FILE	*f;
-	int    length, nBlock, nAllocSize;
-	void    *buffer;
-
-	f = SafeOpenRead (filename);
-	length = Q_filelength (f);
-  nAllocSize = length;
-  nBlock = nAllocSize % MEM_BLOCKSIZE;
-  if ( nBlock > 0) {
-    nAllocSize += MEM_BLOCKSIZE - nBlock;
-  }
-	buffer = safe_malloc (nAllocSize+1);
-  memset(buffer, 0, nAllocSize+1);
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-TryLoadFile
-
-Allows failure
-==============
-*/
-int    TryLoadFile (const char *filename, void **bufferptr)
-{
-	FILE	*f;
-	int    length;
-	void    *buffer;
-
-	*bufferptr = NULL;
-
-	f = fopen (filename, "rb");
-	if (!f)
-		return -1;
-	length = Q_filelength (f);
-	buffer = safe_malloc (length+1);
-	((char *)buffer)[length] = 0;
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-SaveFile
-==============
-*/
-void    SaveFile (const char *filename, const void *buffer, int count)
-{
-	FILE	*f;
-
-	f = SafeOpenWrite (filename);
-	SafeWrite (f, buffer, count);
-	fclose (f);
-}
-
-
-
-void DefaultExtension (char *path, const char *extension)
-{
-	char    *src;
-//
-// if path doesnt have a .EXT, append extension
-// (extension should include the .)
-//
-	src = path + strlen(path) - 1;
-
-	while (*src != '/' && *src != '\\' && src != path)
-	{
-		if (*src == '.')
-			return;                 // it has an extension
-		src--;
-	}
-
-	strcat (path, extension);
-}
-
-
-void DefaultPath (char *path, const char *basepath)
-{
-	char    temp[128];
-
-	if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
-		return;                   // absolute path location
-	strcpy (temp,path);
-	strcpy (path,basepath);
-	strcat (path,temp);
-}
-
-
-void    StripFilename (char *path)
-{
-	int             length;
-
-	length = strlen(path)-1;
-	while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
-		length--;
-	path[length] = 0;
-}
-
-void    StripExtension (char *path)
-{
-	int             length;
-
-	length = strlen(path)-1;
-	while (length > 0 && path[length] != '.')
-	{
-		length--;
-		if (path[length] == '/' || path[ length ] == '\\' )
-			return;		// no extension
-	}
-	if (length)
-		path[length] = 0;
-}
-
-
-/*
-====================
-Extract file parts
-====================
-*/
-// FIXME: should include the slash, otherwise
-// backing to an empty path will be wrong when appending a slash
-void ExtractFilePath (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
-	while (src != path && *(src-1) != '\\' && *(src-1) != '/')
-		src--;
-
-	memcpy (dest, path, src-path);
-	dest[src-path] = 0;
-}
-
-void ExtractFileBase (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
-	while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
-		src--;
-
-	while (*src && *src != '.')
-	{
-		*dest++ = *src++;
-	}
-	*dest = 0;
-}
-
-void ExtractFileExtension (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a . or the start
-//
-	while (src != path && *(src-1) != '.')
-		src--;
-	if (src == path)
-	{
-		*dest = 0;	// no extension
-		return;
-	}
-
-	strcpy (dest,src);
-}
-
-
-/*
-==============
-ParseNum / ParseHex
-==============
-*/
-int ParseHex (const char *hex)
-{
-	const char    *str;
-	int    num;
-
-	num = 0;
-	str = hex;
-
-	while (*str)
-	{
-		num <<= 4;
-		if (*str >= '0' && *str <= '9')
-			num += *str-'0';
-		else if (*str >= 'a' && *str <= 'f')
-			num += 10 + *str-'a';
-		else if (*str >= 'A' && *str <= 'F')
-			num += 10 + *str-'A';
-		else
-			Error ("Bad hex number: %s",hex);
-		str++;
-	}
-
-	return num;
-}
-
-
-int ParseNum (const char *str)
-{
-	if (str[0] == '$')
-		return ParseHex (str+1);
-	if (str[0] == '0' && str[1] == 'x')
-		return ParseHex (str+2);
-	return atol (str);
-}
-/*
-// all output ends up through here
-void FPrintf (int flag, char *buf)
-{
-  printf(buf);
-
-}
-
-void Sys_FPrintf (int flag, const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-
-  if ((flag == SYS_VRB) && (verbose == false))
-    return;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-
-  FPrintf (flag, out_buffer);
-}
-
-void Sys_Printf (const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-
-  FPrintf (SYS_STD, out_buffer);
-}
-
-//=================
-//Error
-//
-//For abnormal program terminations
-//=================
-
-void Error( const char *error, ...)
-{
-  char out_buffer[4096];
-  char tmp[4096];
-	va_list argptr;
-
-	va_start (argptr,error);
-	vsprintf (tmp, error, argptr);
-	va_end (argptr);
-
-  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
-
-  FPrintf( SYS_ERR, out_buffer );
-
-	exit (1);
-}
-
-*/
-
-/*
-============================================================================
-
-					BYTE ORDER FUNCTIONS
-
-============================================================================
-*/
-
-#ifdef _SGI_SOURCE
-#define	__BIG_ENDIAN__
-#endif
-
-#ifdef __BIG_ENDIAN__
-
-short   LittleShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   BigShort (short l)
-{
-	return l;
-}
-
-
-int    LittleLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    BigLong (int l)
-{
-	return l;
-}
-
-
-float	LittleFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	BigFloat (float l)
-{
-	return l;
-}
-
-
-#else
-
-
-short   BigShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   LittleShort (short l)
-{
-	return l;
-}
-
-
-int    BigLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    LittleLong (int l)
-{
-	return l;
-}
-
-float	BigFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	LittleFloat (float l)
-{
-	return l;
-}
-
-
-#endif
-
-
-//=======================================================
-
-
-// FIXME: byte swap?
-
-// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
-// and the initial and final xor values shown below...  in other words, the
-// CCITT standard CRC used by XMODEM
-
-#define CRC_INIT_VALUE	0xffff
-#define CRC_XOR_VALUE	0x0000
-
-static unsigned short crctable[256] =
-{
-	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
-	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
-	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
-	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
-	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
-	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
-	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
-	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
-	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
-	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
-	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
-	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
-	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
-	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
-	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
-	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
-	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
-	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
-	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
-	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
-	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
-	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
-	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
-	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
-	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
-	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
-	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
-	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
-	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
-	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
-	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
-	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
-};
-
-void CRC_Init(unsigned short *crcvalue)
-{
-	*crcvalue = CRC_INIT_VALUE;
-}
-
-void CRC_ProcessByte(unsigned short *crcvalue, byte data)
-{
-	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
-}
-
-unsigned short CRC_Value(unsigned short crcvalue)
-{
-	return crcvalue ^ CRC_XOR_VALUE;
-}
-//=============================================================================
-
-/*
-============
-CreatePath
-============
-*/
-void	CreatePath (const char *path)
-{
-	const char	*ofs;
-	char		c;
-	char		dir[1024];
-
-#ifdef _WIN32
-	int		olddrive = -1;
-
-	if ( path[1] == ':' )
-	{
-		olddrive = _getdrive();
-		_chdrive( toupper( path[0] ) - 'A' + 1 );
-	}
-#endif
-
-	if (path[1] == ':')
-		path += 2;
-
-	for (ofs = path+1 ; *ofs ; ofs++)
-	{
-		c = *ofs;
-		if (c == '/' || c == '\\')
-		{	// create the directory
-			memcpy( dir, path, ofs - path );
-			dir[ ofs - path ] = 0;
-			Q_mkdir( dir );
-		}
-	}
-
-#ifdef _WIN32
-	if ( olddrive != -1 )
-	{
-		_chdrive( olddrive );
-	}
-#endif
-}
-
-
-/*
-============
-QCopyFile
-
-  Used to archive source files
-============
-*/
-void QCopyFile (const char *from, const char *to)
-{
-	void	*buffer;
-	int		length;
-
-	length = LoadFile (from, &buffer);
-	CreatePath (to);
-	SaveFile (to, buffer, length);
-	free (buffer);
-}
-
-void Sys_Sleep(int n)
-{
-#ifdef _WIN32
-  Sleep (n);
-#endif
-#if defined (__linux__) || defined (__APPLE__)
-  usleep (n * 1000);
-#endif
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Nurail: Swiped from quake3/common
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+#include <unistd.h>
+#endif
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+
+#define	BASEDIRNAME	"h"		
+#define PATHSEPERATOR   '/'
+
+extern qboolean verbose;
+
+qboolean	g_dokeypress = false;
+
+qboolean	g_nomkdir = false;
+
+
+#ifdef SAFE_MALLOC
+void *safe_malloc( size_t size )
+{
+  void *p;
+
+  p = malloc(size);
+  if(!p)
+    Error ("safe_malloc failed on allocation of %i bytes", size);
+
+  return p;
+}
+
+void *safe_malloc_info( size_t size, char* info )
+{
+  void *p;
+
+  p = malloc(size);
+  if(!p)
+    Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
+
+  return p;
+}
+#endif
+
+void *SafeMalloc(size_t n, char *desc)
+{
+	void *p;
+
+	if((p = malloc(n)) == NULL)
+	{
+		Error("Failed to allocate %d bytes for '%s'.\n", n, desc);
+	}
+	memset(p, 0, n);
+	return p;
+}
+
+#if defined (__linux__) || defined (__APPLE__)
+void strlwr(char *conv_str)
+{
+	int i;
+
+	for(i=0; i<strlen(conv_str); i++)
+		conv_str[i]=tolower(conv_str[i]);
+}
+#endif
+
+
+// set these before calling CheckParm
+int myargc;
+char **myargv;
+
+char		com_token[1024];
+qboolean	com_eof;
+
+qboolean		archive;
+char			archivedir[1024];
+
+
+/*
+===================
+ExpandWildcards
+
+Mimic unix command line expansion
+===================
+*/
+#define	MAX_EX_ARGC	1024
+int		ex_argc;
+char	*ex_argv[MAX_EX_ARGC];
+#ifdef _WIN32
+#include "io.h"
+void ExpandWildcards( int *argc, char ***argv )
+{
+	struct _finddata_t fileinfo;
+	int		handle;
+	int		i;
+	char	filename[1024];
+	char	filebase[1024];
+	char	*path;
+
+	ex_argc = 0;
+	for (i=0 ; i<*argc ; i++)
+	{
+		path = (*argv)[i];
+		if ( path[0] == '-'
+			|| ( !strstr(path, "*") && !strstr(path, "?") ) )
+		{
+			ex_argv[ex_argc++] = path;
+			continue;
+		}
+
+		handle = _findfirst (path, &fileinfo);
+		if (handle == -1)
+			return;
+
+		ExtractFilePath (path, filebase);
+
+		do
+		{
+			sprintf (filename, "%s%s", filebase, fileinfo.name);
+			ex_argv[ex_argc++] = copystring (filename);
+		} while (_findnext( handle, &fileinfo ) != -1);
+
+		_findclose (handle);
+	}
+
+	*argc = ex_argc;
+	*argv = ex_argv;
+}
+#else
+void ExpandWildcards (int *argc, char ***argv)
+{
+}
+#endif
+
+/*
+
+qdir will hold the path up to the quake directory, including the slash
+
+  f:\quake\
+  /raid/quake/
+
+gamedir will hold qdir + the game directory (id1, id2, etc)
+
+*/
+
+char		qdir[1024];
+char		gamedir[1024];
+char		writedir[1024];
+
+void SetQdirFromPath( const char *path )
+{
+	char	temp[1024];
+	const char	*c;
+  const char *sep;
+	int		len, count;
+
+	if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
+	{	// path is partial
+		Q_getwd (temp);
+		strcat (temp, path);
+		path = temp;
+	}
+
+	// search for "quake2" in path
+
+	len = strlen(BASEDIRNAME);
+	for (c=path+strlen(path)-1 ; c != path ; c--)
+	{
+		int i;
+
+		if (!Q_strncasecmp (c, BASEDIRNAME, len))
+		{
+      //
+			//strncpy (qdir, path, c+len+2-path);
+      // the +2 assumes a 2 or 3 following quake which is not the
+      // case with a retail install
+      // so we need to add up how much to the next separator
+      sep = c + len;
+      count = 1;
+      while (*sep && *sep != '/' && *sep != '\\')
+      {
+        sep++;
+        count++;
+      }
+			strncpy (qdir, path, c+len+count-path);
+			Sys_Printf ("qdir: %s\n", qdir);
+			for ( i = 0; i < strlen( qdir ); i++ )
+			{
+				if ( qdir[i] == '\\' ) 
+					qdir[i] = '/';
+			}
+
+			c += len+count;
+			while (*c)
+			{
+				if (*c == '/' || *c == '\\')
+				{
+					strncpy (gamedir, path, c+1-path);
+
+					for ( i = 0; i < strlen( gamedir ); i++ )
+					{
+						if ( gamedir[i] == '\\' ) 
+							gamedir[i] = '/';
+					}
+
+					Sys_Printf ("gamedir: %s\n", gamedir);
+
+					if ( !writedir[0] )
+						strcpy( writedir, gamedir );
+					else if ( writedir[strlen( writedir )-1] != '/' )
+					{
+						writedir[strlen( writedir )] = '/';
+						writedir[strlen( writedir )+1] = 0;
+					}
+
+					return;
+				}
+				c++;
+			}
+			Error ("No gamedir in %s", path);
+			return;
+		}
+	}
+	Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
+}
+
+char *ExpandArg (const char *path)
+{
+	static char full[1024];
+
+	if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
+	{
+		Q_getwd (full);
+		strcat (full, path);
+	}
+	else
+		strcpy (full, path);
+	return full;
+}
+
+char *ExpandPath (const char *path)
+{
+	static char full[1024];
+	if (!qdir)
+		Error ("ExpandPath called without qdir set");
+	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+		strcpy( full, path );
+		return full;
+	}
+	sprintf (full, "%s%s", qdir, path);
+	return full;
+}
+
+char *ExpandGamePath (const char *path)
+{
+	static char full[1024];
+	if (!qdir)
+		Error ("ExpandGamePath called without qdir set");
+	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+		strcpy( full, path );
+		return full;
+	}
+	sprintf (full, "%s%s", gamedir, path);
+	return full;
+}
+
+char *ExpandPathAndArchive (const char *path)
+{
+	char	*expanded;
+	char	archivename[1024];
+
+	expanded = ExpandPath (path);
+
+	if (archive)
+	{
+		sprintf (archivename, "%s/%s", archivedir, path);
+		QCopyFile (expanded, archivename);
+	}
+	return expanded;
+}
+
+
+char *copystring(const char *s)
+{
+	char	*b;
+	b = safe_malloc(strlen(s)+1);
+	strcpy (b, s);
+	return b;
+}
+
+
+
+/*
+================
+I_FloatTime
+================
+*/
+double I_FloatTime (void)
+{
+	time_t	t;
+	
+	time (&t);
+	
+	return t;
+#if 0
+// more precise, less portable
+	struct timeval tp;
+	struct timezone tzp;
+	static int		secbase;
+
+	gettimeofday(&tp, &tzp);
+	
+	if (!secbase)
+	{
+		secbase = tp.tv_sec;
+		return tp.tv_usec/1000000.0;
+	}
+	
+	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
+#endif
+}
+
+void Q_getwd (char *out)
+{
+	int i = 0;
+
+#ifdef _WIN32
+   _getcwd (out, 256);
+   strcat (out, "\\");
+#else
+   // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
+   getcwd (out, 256);
+   strcat (out, "/");
+#endif
+   while ( out[i] != 0 )
+   {
+	   if ( out[i] == '\\' )
+		   out[i] = '/';
+	   i++;
+   }
+}
+
+
+void Q_mkdir (const char *path)
+{
+#ifdef _WIN32
+	if (_mkdir (path) != -1)
+		return;
+#else
+	if (mkdir (path, 0777) != -1)
+		return;
+#endif
+	if (errno != EEXIST)
+		Error ("mkdir %s: %s",path, strerror(errno));
+}
+
+/*
+============
+FileTime
+
+returns -1 if not present
+============
+*/
+int	FileTime (const char *path)
+{
+	struct	stat	buf;
+	
+	if (stat (path,&buf) == -1)
+		return -1;
+	
+	return buf.st_mtime;
+}
+
+
+
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+	int		c;
+	int		len;
+	
+	len = 0;
+	com_token[0] = 0;
+	
+	if (!data)
+		return NULL;
+		
+// skip whitespace
+skipwhite:
+	while ( (c = *data) <= ' ')
+	{
+		if (c == 0)
+		{
+			com_eof = true;
+			return NULL;			// end of file;
+		}
+		data++;
+	}
+	
+// skip // comments
+	if (c=='/' && data[1] == '/')
+	{
+		while (*data && *data != '\n')
+			data++;
+		goto skipwhite;
+	}
+	
+
+// handle quoted strings specially
+	if (c == '\"')
+	{
+		data++;
+		do
+		{
+			c = *data++;
+			if (c=='\"')
+			{
+				com_token[len] = 0;
+				return data;
+			}
+			com_token[len] = c;
+			len++;
+		} while (1);
+	}
+
+// parse single characters
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+	{
+		com_token[len] = c;
+		len++;
+		com_token[len] = 0;
+		return data+1;
+	}
+
+// parse a regular word
+	do
+	{
+		com_token[len] = c;
+		data++;
+		len++;
+		c = *data;
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+			break;
+	} while (c>32);
+	
+	com_token[len] = 0;
+	return data;
+}
+
+int Q_strncasecmp (const char *s1, const char *s2, int n)
+{
+	int		c1, c2;
+	
+	do
+	{
+		c1 = *s1++;
+		c2 = *s2++;
+
+		if (!n--)
+			return 0;		// strings are equal until end point
+		
+		if (c1 != c2)
+		{
+			if (c1 >= 'a' && c1 <= 'z')
+				c1 -= ('a' - 'A');
+			if (c2 >= 'a' && c2 <= 'z')
+				c2 -= ('a' - 'A');
+			if (c1 != c2)
+				return -1;		// strings not equal
+		}
+	} while (c1);
+	
+	return 0;		// strings are equal
+}
+
+int Q_stricmp (const char *s1, const char *s2)
+{
+	return Q_strncasecmp (s1, s2, 99999);
+}
+
+int Q_strcasecmp (const char *s1, const char *s2)
+{
+	return Q_strncasecmp (s1, s2, 99999);
+}
+
+// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
+//   started getting warnings about that function, prolly a duplicate with the runtime function
+//   maybe we still need to have it in linux builds
+/*
+char *strupr (char *start)
+{
+	char	*in;
+	in = start;
+	while (*in)
+	{
+		*in = toupper(*in);
+		in++;
+	}
+	return start;
+}
+*/
+
+char *strlower (char *start)
+{
+	char	*in;
+	in = start;
+	while (*in)
+	{
+		*in = tolower(*in); 
+		in++;
+	}
+	return start;
+}
+
+
+/*
+=============================================================================
+
+						MISC FUNCTIONS
+
+=============================================================================
+*/
+
+
+/*
+=================
+CheckParm
+
+Checks for the given parameter in the program's command line arguments
+Returns the argument number (1 to argc-1) or 0 if not present
+=================
+*/
+int CheckParm (const char *check)
+{
+	int             i;
+
+	for (i = 1;i<myargc;i++)
+	{
+		if ( !Q_stricmp(check, myargv[i]) )
+			return i;
+	}
+
+	return 0;
+}
+
+
+
+/*
+================
+Q_filelength
+================
+*/
+int Q_filelength (FILE *f)
+{
+	int		pos;
+	int		end;
+
+	pos = ftell (f);
+	fseek (f, 0, SEEK_END);
+	end = ftell (f);
+	fseek (f, pos, SEEK_SET);
+
+	return end;
+}
+
+
+FILE *SafeOpenWrite (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen(filename, "wb");
+
+	if (!f)
+		Error ("Error opening %s: %s",filename,strerror(errno));
+
+	return f;
+}
+
+FILE *SafeOpenRead (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen(filename, "rb");
+
+	if (!f)
+		Error ("Error opening %s: %s",filename,strerror(errno));
+
+	return f;
+}
+
+
+void SafeRead (FILE *f, void *buffer, int count)
+{
+	if ( fread (buffer, 1, count, f) != (size_t)count)
+		Error ("File read failure");
+}
+
+
+void SafeWrite (FILE *f, const void *buffer, int count)
+{
+	if (fwrite (buffer, 1, count, f) != (size_t)count)
+		Error ("File write failure");
+}
+
+
+/*
+==============
+FileExists
+==============
+*/
+qboolean	FileExists (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen (filename, "r");
+	if (!f)
+		return false;
+	fclose (f);
+	return true;
+}
+
+/*
+==============
+LoadFile
+==============
+*/
+int    LoadFile( const char *filename, void **bufferptr )
+{
+	FILE	*f;
+	int    length;
+	void    *buffer;
+
+	f = SafeOpenRead (filename);
+	length = Q_filelength (f);
+	buffer = safe_malloc (length+1);
+	((char *)buffer)[length] = 0;
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+LoadFileBlock
+-
+rounds up memory allocation to 4K boundry
+-
+==============
+*/
+int    LoadFileBlock( const char *filename, void **bufferptr )
+{
+	FILE	*f;
+	int    length, nBlock, nAllocSize;
+	void    *buffer;
+
+	f = SafeOpenRead (filename);
+	length = Q_filelength (f);
+  nAllocSize = length;
+  nBlock = nAllocSize % MEM_BLOCKSIZE;
+  if ( nBlock > 0) {
+    nAllocSize += MEM_BLOCKSIZE - nBlock;
+  }
+	buffer = safe_malloc (nAllocSize+1);
+  memset(buffer, 0, nAllocSize+1);
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+TryLoadFile
+
+Allows failure
+==============
+*/
+int    TryLoadFile (const char *filename, void **bufferptr)
+{
+	FILE	*f;
+	int    length;
+	void    *buffer;
+
+	*bufferptr = NULL;
+
+	f = fopen (filename, "rb");
+	if (!f)
+		return -1;
+	length = Q_filelength (f);
+	buffer = safe_malloc (length+1);
+	((char *)buffer)[length] = 0;
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+SaveFile
+==============
+*/
+void    SaveFile (const char *filename, const void *buffer, int count)
+{
+	FILE	*f;
+
+	f = SafeOpenWrite (filename);
+	SafeWrite (f, buffer, count);
+	fclose (f);
+}
+
+
+
+void DefaultExtension (char *path, const char *extension)
+{
+	char    *src;
+//
+// if path doesnt have a .EXT, append extension
+// (extension should include the .)
+//
+	src = path + strlen(path) - 1;
+
+	while (*src != '/' && *src != '\\' && src != path)
+	{
+		if (*src == '.')
+			return;                 // it has an extension
+		src--;
+	}
+
+	strcat (path, extension);
+}
+
+
+void DefaultPath (char *path, const char *basepath)
+{
+	char    temp[128];
+
+	if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
+		return;                   // absolute path location
+	strcpy (temp,path);
+	strcpy (path,basepath);
+	strcat (path,temp);
+}
+
+
+void    StripFilename (char *path)
+{
+	int             length;
+
+	length = strlen(path)-1;
+	while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
+		length--;
+	path[length] = 0;
+}
+
+void    StripExtension (char *path)
+{
+	int             length;
+
+	length = strlen(path)-1;
+	while (length > 0 && path[length] != '.')
+	{
+		length--;
+		if (path[length] == '/' || path[ length ] == '\\' )
+			return;		// no extension
+	}
+	if (length)
+		path[length] = 0;
+}
+
+
+/*
+====================
+Extract file parts
+====================
+*/
+// FIXME: should include the slash, otherwise
+// backing to an empty path will be wrong when appending a slash
+void ExtractFilePath (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+	while (src != path && *(src-1) != '\\' && *(src-1) != '/')
+		src--;
+
+	memcpy (dest, path, src-path);
+	dest[src-path] = 0;
+}
+
+void ExtractFileBase (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+	while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
+		src--;
+
+	while (*src && *src != '.')
+	{
+		*dest++ = *src++;
+	}
+	*dest = 0;
+}
+
+void ExtractFileExtension (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a . or the start
+//
+	while (src != path && *(src-1) != '.')
+		src--;
+	if (src == path)
+	{
+		*dest = 0;	// no extension
+		return;
+	}
+
+	strcpy (dest,src);
+}
+
+
+/*
+==============
+ParseNum / ParseHex
+==============
+*/
+int ParseHex (const char *hex)
+{
+	const char    *str;
+	int    num;
+
+	num = 0;
+	str = hex;
+
+	while (*str)
+	{
+		num <<= 4;
+		if (*str >= '0' && *str <= '9')
+			num += *str-'0';
+		else if (*str >= 'a' && *str <= 'f')
+			num += 10 + *str-'a';
+		else if (*str >= 'A' && *str <= 'F')
+			num += 10 + *str-'A';
+		else
+			Error ("Bad hex number: %s",hex);
+		str++;
+	}
+
+	return num;
+}
+
+
+int ParseNum (const char *str)
+{
+	if (str[0] == '$')
+		return ParseHex (str+1);
+	if (str[0] == '0' && str[1] == 'x')
+		return ParseHex (str+2);
+	return atol (str);
+}
+/*
+// all output ends up through here
+void FPrintf (int flag, char *buf)
+{
+  printf(buf);
+
+}
+
+void Sys_FPrintf (int flag, const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+
+  if ((flag == SYS_VRB) && (verbose == false))
+    return;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+
+  FPrintf (flag, out_buffer);
+}
+
+void Sys_Printf (const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+
+  FPrintf (SYS_STD, out_buffer);
+}
+
+//=================
+//Error
+//
+//For abnormal program terminations
+//=================
+
+void Error( const char *error, ...)
+{
+  char out_buffer[4096];
+  char tmp[4096];
+	va_list argptr;
+
+	va_start (argptr,error);
+	vsprintf (tmp, error, argptr);
+	va_end (argptr);
+
+  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
+
+  FPrintf( SYS_ERR, out_buffer );
+
+	exit (1);
+}
+
+*/
+
+/*
+============================================================================
+
+					BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+#ifdef _SGI_SOURCE
+#define	__BIG_ENDIAN__
+#endif
+
+#ifdef __BIG_ENDIAN__
+
+short   LittleShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   BigShort (short l)
+{
+	return l;
+}
+
+
+int    LittleLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    BigLong (int l)
+{
+	return l;
+}
+
+
+float	LittleFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	BigFloat (float l)
+{
+	return l;
+}
+
+
+#else
+
+
+short   BigShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   LittleShort (short l)
+{
+	return l;
+}
+
+
+int    BigLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    LittleLong (int l)
+{
+	return l;
+}
+
+float	BigFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	LittleFloat (float l)
+{
+	return l;
+}
+
+
+#endif
+
+
+//=======================================================
+
+
+// FIXME: byte swap?
+
+// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
+// and the initial and final xor values shown below...  in other words, the
+// CCITT standard CRC used by XMODEM
+
+#define CRC_INIT_VALUE	0xffff
+#define CRC_XOR_VALUE	0x0000
+
+static unsigned short crctable[256] =
+{
+	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
+	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
+	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
+	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
+	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
+	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
+	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
+	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
+	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
+	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
+	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
+	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
+	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
+	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
+	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
+	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
+	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
+	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
+	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
+	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
+	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
+	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
+	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
+	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
+	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
+	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
+	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
+	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
+	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
+	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
+	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
+	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
+};
+
+void CRC_Init(unsigned short *crcvalue)
+{
+	*crcvalue = CRC_INIT_VALUE;
+}
+
+void CRC_ProcessByte(unsigned short *crcvalue, byte data)
+{
+	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
+}
+
+unsigned short CRC_Value(unsigned short crcvalue)
+{
+	return crcvalue ^ CRC_XOR_VALUE;
+}
+//=============================================================================
+
+/*
+============
+CreatePath
+============
+*/
+void	CreatePath (const char *path)
+{
+	const char	*ofs;
+	char		c;
+	char		dir[1024];
+
+#ifdef _WIN32
+	int		olddrive = -1;
+
+	if ( path[1] == ':' )
+	{
+		olddrive = _getdrive();
+		_chdrive( toupper( path[0] ) - 'A' + 1 );
+	}
+#endif
+
+	if (path[1] == ':')
+		path += 2;
+
+	for (ofs = path+1 ; *ofs ; ofs++)
+	{
+		c = *ofs;
+		if (c == '/' || c == '\\')
+		{	// create the directory
+			memcpy( dir, path, ofs - path );
+			dir[ ofs - path ] = 0;
+			Q_mkdir( dir );
+		}
+	}
+
+#ifdef _WIN32
+	if ( olddrive != -1 )
+	{
+		_chdrive( olddrive );
+	}
+#endif
+}
+
+
+/*
+============
+QCopyFile
+
+  Used to archive source files
+============
+*/
+void QCopyFile (const char *from, const char *to)
+{
+	void	*buffer;
+	int		length;
+
+	length = LoadFile (from, &buffer);
+	CreatePath (to);
+	SaveFile (to, buffer, length);
+	free (buffer);
+}
+
+void Sys_Sleep(int n)
+{
+#ifdef _WIN32
+  Sleep (n);
+#endif
+#if defined (__linux__) || defined (__APPLE__)
+  usleep (n * 1000);
+#endif
+}
diff --git a/tools/quake2/qdata_heretic2/common/cmdlib.h b/tools/quake2/qdata_heretic2/common/cmdlib.h
index ba7bacde..edc29d5c 100644
--- a/tools/quake2/qdata_heretic2/common/cmdlib.h
+++ b/tools/quake2/qdata_heretic2/common/cmdlib.h
@@ -1,177 +1,177 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// cmdlib.h
-
-#ifndef __CMDLIB__
-#define __CMDLIB__
-
-#ifdef _WIN32
-#pragma warning(disable : 4244)     // MIPS
-#pragma warning(disable : 4136)     // X86
-#pragma warning(disable : 4051)     // ALPHA
-
-#pragma warning(disable : 4018)     // signed/unsigned mismatch
-#pragma warning(disable : 4305)     // truncate from double to float
-
-#pragma check_stack(off)
-
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-
-#ifdef _WIN32
-
-#pragma intrinsic( memset, memcpy )
-
-#endif
-
-#ifndef __BYTEBOOL__
-  #define __BYTEBOOL__
-  //typedef enum {false, true} qboolean;
-  //typedef unsigned char byte;
-  #include "q_typedef.h"
-#endif
-
-#define	MAX_OS_PATH		1024
-#define MEM_BLOCKSIZE 4096
-/*
-extern	qboolean verbose;
-#define SYS_VRB 0 // verbose support (on/off)
-#define SYS_STD 1 // standard print level
-#define SYS_WRN 2 // warnings
-#define SYS_ERR 3 // error
-*/
-// the dec offsetof macro doesnt work very well...
-#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
-
-#define SAFE_MALLOC
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size );
-void *safe_malloc_info( size_t size, char* info );
-#else
-#define safe_malloc(a) malloc(a)
-#endif /* SAFE_MALLOC */
-
-// set these before calling CheckParm
-extern int myargc;
-extern char **myargv;
-
-char *strlower (char *in);
-int Q_strncasecmp( const char *s1, const char *s2, int n );
-int Q_stricmp( const char *s1, const char *s2 );
-int Q_strcasecmp( const char *s1, const char *s2 );
-void Q_getwd( char *out );
-
-int Q_filelength (FILE *f);
-int	FileTime( const char *path );
-
-void	Q_mkdir( const char *path );
-
-extern	char		qdir[1024];
-extern	char		gamedir[1024];
-extern  char		writedir[1024];
-extern  char    *moddirparam;
-void SetQdirFromPath( const char *path);
-char *ExpandArg( const char *path );	// from cmd line
-char *ExpandPath( const char *path );	// from scripts
-char *ExpandGamePath (const char *path);
-char *ExpandPathAndArchive( const char *path );
-void ExpandWildcards( int *argc, char ***argv );
-
-
-double I_FloatTime( void );
-
-int		CheckParm( const char *check );
-
-void	*SafeMalloc(size_t n, char *desc);
-FILE	*SafeOpenWrite( const char *filename );
-FILE	*SafeOpenRead( const char *filename );
-void	SafeRead (FILE *f, void *buffer, int count);
-void	SafeWrite (FILE *f, const void *buffer, int count);
-
-int		LoadFile( const char *filename, void **bufferptr );
-int   LoadFileBlock( const char *filename, void **bufferptr );
-int		TryLoadFile( const char *filename, void **bufferptr );
-void	SaveFile( const char *filename, const void *buffer, int count );
-qboolean	FileExists( const char *filename );
-
-void 	DefaultExtension( char *path, const char *extension );
-void 	DefaultPath( char *path, const char *basepath );
-void 	StripFilename( char *path );
-void 	StripExtension( char *path );
-
-void 	ExtractFilePath( const char *path, char *dest );
-void 	ExtractFileBase( const char *path, char *dest );
-void	ExtractFileExtension( const char *path, char *dest );
-
-int 	ParseNum (const char *str);
-/*
-void Sys_Printf (const char *text, ...);
-void Sys_FPrintf (int flag, const char *text, ...);
-void	Error( const char *error, ... );
-*/
-short	BigShort (short l);
-short	LittleShort (short l);
-int		BigLong (int l);
-int		LittleLong (int l);
-float	BigFloat (float l);
-float	LittleFloat (float l);
-
-
-char *COM_Parse (char *data);
-
-extern	char		com_token[1024];
-extern	qboolean	com_eof;
-
-char *copystring(const char *s);
-
-
-void CRC_Init(unsigned short *crcvalue);
-void CRC_ProcessByte(unsigned short *crcvalue, byte data);
-unsigned short CRC_Value(unsigned short crcvalue);
-
-void	CreatePath( const char *path );
-void	QCopyFile( const char *from, const char *to );
-
-extern	qboolean		archive;
-extern	char			archivedir[1024];
-
-extern  qboolean	g_dokeypress;
-
-// sleep for the given amount of milliseconds
-void Sys_Sleep(int n);
-
-// for compression routines
-typedef struct
-{
-	byte	*data;
-	int		count;
-} cblock_t;
-
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// cmdlib.h
+
+#ifndef __CMDLIB__
+#define __CMDLIB__
+
+#ifdef _WIN32
+#pragma warning(disable : 4244)     // MIPS
+#pragma warning(disable : 4136)     // X86
+#pragma warning(disable : 4051)     // ALPHA
+
+#pragma warning(disable : 4018)     // signed/unsigned mismatch
+#pragma warning(disable : 4305)     // truncate from double to float
+
+#pragma check_stack(off)
+
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+
+#pragma intrinsic( memset, memcpy )
+
+#endif
+
+#ifndef __BYTEBOOL__
+  #define __BYTEBOOL__
+  //typedef enum {false, true} qboolean;
+  //typedef unsigned char byte;
+  #include "q_typedef.h"
+#endif
+
+#define	MAX_OS_PATH		1024
+#define MEM_BLOCKSIZE 4096
+/*
+extern	qboolean verbose;
+#define SYS_VRB 0 // verbose support (on/off)
+#define SYS_STD 1 // standard print level
+#define SYS_WRN 2 // warnings
+#define SYS_ERR 3 // error
+*/
+// the dec offsetof macro doesnt work very well...
+#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
+
+#define SAFE_MALLOC
+#ifdef SAFE_MALLOC
+void *safe_malloc( size_t size );
+void *safe_malloc_info( size_t size, char* info );
+#else
+#define safe_malloc(a) malloc(a)
+#endif /* SAFE_MALLOC */
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+char *strlower (char *in);
+int Q_strncasecmp( const char *s1, const char *s2, int n );
+int Q_stricmp( const char *s1, const char *s2 );
+int Q_strcasecmp( const char *s1, const char *s2 );
+void Q_getwd( char *out );
+
+int Q_filelength (FILE *f);
+int	FileTime( const char *path );
+
+void	Q_mkdir( const char *path );
+
+extern	char		qdir[1024];
+extern	char		gamedir[1024];
+extern  char		writedir[1024];
+extern  char    *moddirparam;
+void SetQdirFromPath( const char *path);
+char *ExpandArg( const char *path );	// from cmd line
+char *ExpandPath( const char *path );	// from scripts
+char *ExpandGamePath (const char *path);
+char *ExpandPathAndArchive( const char *path );
+void ExpandWildcards( int *argc, char ***argv );
+
+
+double I_FloatTime( void );
+
+int		CheckParm( const char *check );
+
+void	*SafeMalloc(size_t n, char *desc);
+FILE	*SafeOpenWrite( const char *filename );
+FILE	*SafeOpenRead( const char *filename );
+void	SafeRead (FILE *f, void *buffer, int count);
+void	SafeWrite (FILE *f, const void *buffer, int count);
+
+int		LoadFile( const char *filename, void **bufferptr );
+int   LoadFileBlock( const char *filename, void **bufferptr );
+int		TryLoadFile( const char *filename, void **bufferptr );
+void	SaveFile( const char *filename, const void *buffer, int count );
+qboolean	FileExists( const char *filename );
+
+void 	DefaultExtension( char *path, const char *extension );
+void 	DefaultPath( char *path, const char *basepath );
+void 	StripFilename( char *path );
+void 	StripExtension( char *path );
+
+void 	ExtractFilePath( const char *path, char *dest );
+void 	ExtractFileBase( const char *path, char *dest );
+void	ExtractFileExtension( const char *path, char *dest );
+
+int 	ParseNum (const char *str);
+/*
+void Sys_Printf (const char *text, ...);
+void Sys_FPrintf (int flag, const char *text, ...);
+void	Error( const char *error, ... );
+*/
+short	BigShort (short l);
+short	LittleShort (short l);
+int		BigLong (int l);
+int		LittleLong (int l);
+float	BigFloat (float l);
+float	LittleFloat (float l);
+
+
+char *COM_Parse (char *data);
+
+extern	char		com_token[1024];
+extern	qboolean	com_eof;
+
+char *copystring(const char *s);
+
+
+void CRC_Init(unsigned short *crcvalue);
+void CRC_ProcessByte(unsigned short *crcvalue, byte data);
+unsigned short CRC_Value(unsigned short crcvalue);
+
+void	CreatePath( const char *path );
+void	QCopyFile( const char *from, const char *to );
+
+extern	qboolean		archive;
+extern	char			archivedir[1024];
+
+extern  qboolean	g_dokeypress;
+
+// sleep for the given amount of milliseconds
+void Sys_Sleep(int n);
+
+// for compression routines
+typedef struct
+{
+	byte	*data;
+	int		count;
+} cblock_t;
+
+
+#endif
diff --git a/tools/quake2/qdata_heretic2/common/her2_threads.h b/tools/quake2/qdata_heretic2/common/her2_threads.h
index 1ef28c0f..77e7414d 100644
--- a/tools/quake2/qdata_heretic2/common/her2_threads.h
+++ b/tools/quake2/qdata_heretic2/common/her2_threads.h
@@ -1,35 +1,35 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-#ifndef _THREADS_H
-
-#define _THREADS_H
-
-
-extern	int		numthreads;
-
-void ThreadSetDefault (void);
-int	GetThreadWork (void);
-void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
-void ThreadLock (void);
-void ThreadUnlock (void);
-
-#endif //_THREADS_H
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+#ifndef _THREADS_H
+
+#define _THREADS_H
+
+
+extern	int		numthreads;
+
+void ThreadSetDefault (void);
+int	GetThreadWork (void);
+void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
+void ThreadLock (void);
+void ThreadUnlock (void);
+
+#endif //_THREADS_H
diff --git a/tools/quake2/qdata_heretic2/common/inout.c b/tools/quake2/qdata_heretic2/common/inout.c
index ef21edea..33eac651 100644
--- a/tools/quake2/qdata_heretic2/common/inout.c
+++ b/tools/quake2/qdata_heretic2/common/inout.c
@@ -1,367 +1,367 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-//
-// DESCRIPTION:
-// deal with in/out tasks, for either stdin/stdout or network/XML stream
-// 
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "polylib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <windows.h>
-#endif
-
-// network broadcasting
-#include "l_net/l_net.h"
-#include "libxml/tree.h"
-
-#ifdef _WIN32
-HWND hwndOut = NULL;
-qboolean lookedForServer = false;
-UINT wm_BroadcastCommand = -1;
-#endif
-
-socket_t *brdcst_socket;
-netmessage_t msg;
-
-qboolean verbose = false;
-
-// our main document
-// is streamed through the network to Radiant
-// possibly written to disk at the end of the run
-//++timo FIXME: need to be global, required when creating nodes?
-xmlDocPtr doc;
-xmlNodePtr tree;
-
-// some useful stuff
-xmlNodePtr xml_NodeForVec( vec3_t v )
-{
-  xmlNodePtr ret;
-  char buf[1024];
-  
-  sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
-  ret = xmlNewNode (NULL, "point");
-  xmlNodeSetContent (ret, buf);
-  return ret;
-}
-
-// send a node down the stream, add it to the document
-void xml_SendNode (xmlNodePtr node)
-{
-  xmlBufferPtr xml_buf;
-  char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
-  // this index loops through the node buffer
-  int pos = 0;
-  int size;
-
-  xmlAddChild( doc->children, node );
-
-  if (brdcst_socket)
-  {
-    xml_buf = xmlBufferCreate();
-    xmlNodeDump( xml_buf, doc, node, 0, 0 );
-
-    // the XML node might be too big to fit in a single network message
-    // l_net library defines an upper limit of MAX_NETMESSAGE
-    // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
-    // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
-    while (pos < xml_buf->use)
-    {
-      // what size are we gonna send now?
-      (xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
-      //++timo just a debug thing
-      if (size == MAX_NETMESSAGE - 10)
-        Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
-      memcpy( xmlbuf, xml_buf->content+pos, size);
-      xmlbuf[size] = '\0';
-      NMSG_Clear( &msg );
-      NMSG_WriteString (&msg, xmlbuf );
-      Net_Send(brdcst_socket, &msg );
-      // now that the thing is sent prepare to loop again
-      pos += size;
-    }
-
-#if 0
-    // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
-    // we will need to split into chunks
-    // (we could also go lower level, in the end it's using send and receiv which are not size limited)
-    //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
-    //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
-
-    //++timo we need to handle the case of a buffer too big to fit in a single message
-    // try without checks for now
-    if (xml_buf->use > MAX_NETMESSAGE-10 )
-    {
-      // if we send that we are probably gonna break the stream at the other end..
-      // and Error will call right there
-      //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
-      Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
-      xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
-      Sys_FPrintf (SYS_NOXML, xml_buf->content);
-
-    }
-
-    size = xml_buf->use;
-    memcpy( xmlbuf, xml_buf->content, size );
-    xmlbuf[size] = '\0';
-    NMSG_Clear( &msg );
-    NMSG_WriteString (&msg, xmlbuf );
-    Net_Send(brdcst_socket, &msg );
-#endif
-
-    xmlBufferFree( xml_buf );
-  }  
-}
-
-void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
-{
-  xmlNodePtr node, select;
-  char buf[1024];
-  char level[2];
-
-  // now build a proper "select" XML node
-  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
-  node = xmlNewNode (NULL, "select");
-  xmlNodeSetContent (node, buf);
-  level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN)  ;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'select' information
-  sprintf (buf, "%i %i", entitynum, brushnum);
-  select = xmlNewNode (NULL, "brush");
-  xmlNodeSetContent (select, buf);
-  xmlAddChild (node, select);
-  xml_SendNode (node);
-
-  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
-  if (bError)
-    Error(buf);
-  else
-    Sys_FPrintf (SYS_NOXML, "%s\n", buf);
-
-}
-
-void xml_Point (char *msg, vec3_t pt)
-{
-  xmlNodePtr node, point;
-  char buf[1024];
-  char level[2];
-
-  node = xmlNewNode (NULL, "pointmsg");
-  xmlNodeSetContent (node, msg);
-  level[0] = (int)'0' + SYS_ERR;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'point' node
-  sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
-  point = xmlNewNode (NULL, "point");
-  xmlNodeSetContent (point, buf);
-  xmlAddChild (node, point);
-  xml_SendNode (node);
-
-  sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
-  Error (buf);
-}
-
-#define WINDING_BUFSIZE 2048
-void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
-{
-  xmlNodePtr node, winding;
-  char buf[WINDING_BUFSIZE];
-  char smlbuf[128];
-  char level[2];
-  int i;
-
-  node = xmlNewNode (NULL, "windingmsg");
-  xmlNodeSetContent (node, msg);
-  level[0] = (int)'0' + SYS_ERR;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'winding' node
-  sprintf( buf, "%i ", numpoints);
-  for(i = 0; i < numpoints; i++)
-  {
-	  sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
-    // don't overflow
-    if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
-      break;
-	  strcat( buf, smlbuf);
-  }
-
-  winding = xmlNewNode (NULL, "winding");
-  xmlNodeSetContent (winding, buf);
-  xmlAddChild (node, winding);
-  xml_SendNode (node);
-
-  if(die)
-    Error (msg);
-  else
-  {
-    Sys_Printf(msg);
-    Sys_Printf("\n");
-  }
-}
-
-// in include
-#include "stream_version.h"
-
-void Broadcast_Setup( const char *dest )
-{
-	address_t address;
-  char sMsg[1024];
-
-	Net_Setup();
-	Net_StringToAddress((char *)dest, &address);
-  brdcst_socket = Net_Connect(&address, 0);
-  if (brdcst_socket)
-  {
-    // send in a header
-    sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
-    NMSG_Clear( &msg );
-    NMSG_WriteString(&msg, sMsg );
-    Net_Send(brdcst_socket, &msg );
-  }
-}
-
-void Broadcast_Shutdown()
-{
-  if (brdcst_socket)
-  {    
-    Sys_Printf("Disconnecting\n");
-    Net_Disconnect(brdcst_socket);
-    brdcst_socket = NULL;
-  }
-}
-
-// all output ends up through here
-void FPrintf (int flag, char *buf)
-{
-  xmlNodePtr node;
-  static qboolean bGotXML = false;
-  char level[2];
-
-  printf(buf);
-
-  // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
-  if (flag == SYS_NOXML)
-    return;
-
-  // ouput an XML file of the run
-  // use the DOM interface to build a tree
-  /*
-  <message level='flag'>
-    message string
-    .. various nodes to describe corresponding geometry ..
-  </message>
-  */
-  if (!bGotXML)
-  {
-    // initialize
-    doc = xmlNewDoc("1.0");
-    doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
-    bGotXML = true;
-  }
-  node = xmlNewNode (NULL, "message");
-  xmlNodeSetContent (node, buf);
-  level[0] = (int)'0' + flag;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level );
-  
-  xml_SendNode (node);
-}
-
-#ifdef DBG_XML
-void DumpXML()
-{
-  xmlSaveFile( "XMLDump.xml", doc );
-}
-#endif
-
-void Sys_FPrintf (int flag, const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-  
-  if ((flag == SYS_VRB) && (verbose == false))
-    return;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-
-  FPrintf (flag, out_buffer);
-}
-
-void Sys_Printf (const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-  
-  FPrintf (SYS_STD, out_buffer);
-}
-
-/*
-=================
-Error
-
-For abnormal program terminations
-=================
-*/
-void Error( const char *error, ...)
-{
-  char out_buffer[4096];
-  char tmp[4096];
-	va_list argptr;
-
-	va_start (argptr,error);
-	vsprintf (tmp, error, argptr);
-	va_end (argptr);
-
-  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
-
-  FPrintf( SYS_ERR, out_buffer );
-
-#ifdef DBG_XML  
-  DumpXML();
-#endif
-
-  //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
-  // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
-  Sys_Sleep( 1000 );
-  
-  Broadcast_Shutdown();
-
-	exit (1);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+//
+// DESCRIPTION:
+// deal with in/out tasks, for either stdin/stdout or network/XML stream
+// 
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "polylib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#endif
+
+// network broadcasting
+#include "l_net/l_net.h"
+#include "libxml/tree.h"
+
+#ifdef _WIN32
+HWND hwndOut = NULL;
+qboolean lookedForServer = false;
+UINT wm_BroadcastCommand = -1;
+#endif
+
+socket_t *brdcst_socket;
+netmessage_t msg;
+
+qboolean verbose = false;
+
+// our main document
+// is streamed through the network to Radiant
+// possibly written to disk at the end of the run
+//++timo FIXME: need to be global, required when creating nodes?
+xmlDocPtr doc;
+xmlNodePtr tree;
+
+// some useful stuff
+xmlNodePtr xml_NodeForVec( vec3_t v )
+{
+  xmlNodePtr ret;
+  char buf[1024];
+  
+  sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
+  ret = xmlNewNode (NULL, "point");
+  xmlNodeSetContent (ret, buf);
+  return ret;
+}
+
+// send a node down the stream, add it to the document
+void xml_SendNode (xmlNodePtr node)
+{
+  xmlBufferPtr xml_buf;
+  char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
+  // this index loops through the node buffer
+  int pos = 0;
+  int size;
+
+  xmlAddChild( doc->children, node );
+
+  if (brdcst_socket)
+  {
+    xml_buf = xmlBufferCreate();
+    xmlNodeDump( xml_buf, doc, node, 0, 0 );
+
+    // the XML node might be too big to fit in a single network message
+    // l_net library defines an upper limit of MAX_NETMESSAGE
+    // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
+    // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
+    while (pos < xml_buf->use)
+    {
+      // what size are we gonna send now?
+      (xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
+      //++timo just a debug thing
+      if (size == MAX_NETMESSAGE - 10)
+        Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
+      memcpy( xmlbuf, xml_buf->content+pos, size);
+      xmlbuf[size] = '\0';
+      NMSG_Clear( &msg );
+      NMSG_WriteString (&msg, xmlbuf );
+      Net_Send(brdcst_socket, &msg );
+      // now that the thing is sent prepare to loop again
+      pos += size;
+    }
+
+#if 0
+    // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
+    // we will need to split into chunks
+    // (we could also go lower level, in the end it's using send and receiv which are not size limited)
+    //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
+    //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
+
+    //++timo we need to handle the case of a buffer too big to fit in a single message
+    // try without checks for now
+    if (xml_buf->use > MAX_NETMESSAGE-10 )
+    {
+      // if we send that we are probably gonna break the stream at the other end..
+      // and Error will call right there
+      //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
+      Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
+      xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
+      Sys_FPrintf (SYS_NOXML, xml_buf->content);
+
+    }
+
+    size = xml_buf->use;
+    memcpy( xmlbuf, xml_buf->content, size );
+    xmlbuf[size] = '\0';
+    NMSG_Clear( &msg );
+    NMSG_WriteString (&msg, xmlbuf );
+    Net_Send(brdcst_socket, &msg );
+#endif
+
+    xmlBufferFree( xml_buf );
+  }  
+}
+
+void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
+{
+  xmlNodePtr node, select;
+  char buf[1024];
+  char level[2];
+
+  // now build a proper "select" XML node
+  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
+  node = xmlNewNode (NULL, "select");
+  xmlNodeSetContent (node, buf);
+  level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN)  ;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'select' information
+  sprintf (buf, "%i %i", entitynum, brushnum);
+  select = xmlNewNode (NULL, "brush");
+  xmlNodeSetContent (select, buf);
+  xmlAddChild (node, select);
+  xml_SendNode (node);
+
+  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
+  if (bError)
+    Error(buf);
+  else
+    Sys_FPrintf (SYS_NOXML, "%s\n", buf);
+
+}
+
+void xml_Point (char *msg, vec3_t pt)
+{
+  xmlNodePtr node, point;
+  char buf[1024];
+  char level[2];
+
+  node = xmlNewNode (NULL, "pointmsg");
+  xmlNodeSetContent (node, msg);
+  level[0] = (int)'0' + SYS_ERR;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'point' node
+  sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
+  point = xmlNewNode (NULL, "point");
+  xmlNodeSetContent (point, buf);
+  xmlAddChild (node, point);
+  xml_SendNode (node);
+
+  sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
+  Error (buf);
+}
+
+#define WINDING_BUFSIZE 2048
+void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
+{
+  xmlNodePtr node, winding;
+  char buf[WINDING_BUFSIZE];
+  char smlbuf[128];
+  char level[2];
+  int i;
+
+  node = xmlNewNode (NULL, "windingmsg");
+  xmlNodeSetContent (node, msg);
+  level[0] = (int)'0' + SYS_ERR;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'winding' node
+  sprintf( buf, "%i ", numpoints);
+  for(i = 0; i < numpoints; i++)
+  {
+	  sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
+    // don't overflow
+    if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
+      break;
+	  strcat( buf, smlbuf);
+  }
+
+  winding = xmlNewNode (NULL, "winding");
+  xmlNodeSetContent (winding, buf);
+  xmlAddChild (node, winding);
+  xml_SendNode (node);
+
+  if(die)
+    Error (msg);
+  else
+  {
+    Sys_Printf(msg);
+    Sys_Printf("\n");
+  }
+}
+
+// in include
+#include "stream_version.h"
+
+void Broadcast_Setup( const char *dest )
+{
+	address_t address;
+  char sMsg[1024];
+
+	Net_Setup();
+	Net_StringToAddress((char *)dest, &address);
+  brdcst_socket = Net_Connect(&address, 0);
+  if (brdcst_socket)
+  {
+    // send in a header
+    sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
+    NMSG_Clear( &msg );
+    NMSG_WriteString(&msg, sMsg );
+    Net_Send(brdcst_socket, &msg );
+  }
+}
+
+void Broadcast_Shutdown()
+{
+  if (brdcst_socket)
+  {    
+    Sys_Printf("Disconnecting\n");
+    Net_Disconnect(brdcst_socket);
+    brdcst_socket = NULL;
+  }
+}
+
+// all output ends up through here
+void FPrintf (int flag, char *buf)
+{
+  xmlNodePtr node;
+  static qboolean bGotXML = false;
+  char level[2];
+
+  printf(buf);
+
+  // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
+  if (flag == SYS_NOXML)
+    return;
+
+  // ouput an XML file of the run
+  // use the DOM interface to build a tree
+  /*
+  <message level='flag'>
+    message string
+    .. various nodes to describe corresponding geometry ..
+  </message>
+  */
+  if (!bGotXML)
+  {
+    // initialize
+    doc = xmlNewDoc("1.0");
+    doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
+    bGotXML = true;
+  }
+  node = xmlNewNode (NULL, "message");
+  xmlNodeSetContent (node, buf);
+  level[0] = (int)'0' + flag;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level );
+  
+  xml_SendNode (node);
+}
+
+#ifdef DBG_XML
+void DumpXML()
+{
+  xmlSaveFile( "XMLDump.xml", doc );
+}
+#endif
+
+void Sys_FPrintf (int flag, const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+  
+  if ((flag == SYS_VRB) && (verbose == false))
+    return;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+
+  FPrintf (flag, out_buffer);
+}
+
+void Sys_Printf (const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+  
+  FPrintf (SYS_STD, out_buffer);
+}
+
+/*
+=================
+Error
+
+For abnormal program terminations
+=================
+*/
+void Error( const char *error, ...)
+{
+  char out_buffer[4096];
+  char tmp[4096];
+	va_list argptr;
+
+	va_start (argptr,error);
+	vsprintf (tmp, error, argptr);
+	va_end (argptr);
+
+  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
+
+  FPrintf( SYS_ERR, out_buffer );
+
+#ifdef DBG_XML  
+  DumpXML();
+#endif
+
+  //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
+  // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
+  Sys_Sleep( 1000 );
+  
+  Broadcast_Shutdown();
+
+	exit (1);
+}
+
diff --git a/tools/quake2/qdata_heretic2/common/inout.h b/tools/quake2/qdata_heretic2/common/inout.h
index 4843a7b6..05b56a09 100644
--- a/tools/quake2/qdata_heretic2/common/inout.h
+++ b/tools/quake2/qdata_heretic2/common/inout.h
@@ -1,63 +1,63 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __INOUT__
-#define __INOUT__
-
-// inout is the only stuff relying on xml, include the headers there
-#include "libxml/tree.h"
-#include "mathlib.h"
-
-// some useful xml routines
-xmlNodePtr xml_NodeForVec( vec3_t v );
-void xml_SendNode (xmlNodePtr node);
-// print a message in q3map output and send the corresponding select information down the xml stream
-// bError: do we end with an error on this one or do we go ahead?
-void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
-// end q3map with an error message and send a point information in the xml stream
-// note: we might want to add a boolean to use this as a warning or an error thing..
-void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
-void xml_Point (char *msg, vec3_t pt);
-
-extern qboolean bNetworkBroadcast;
-void Broadcast_Setup( const char *dest );
-void Broadcast_Shutdown();
-
-#define SYS_VRB 0 // verbose support (on/off)
-#define SYS_STD 1 // standard print level
-#define SYS_WRN 2 // warnings
-#define SYS_ERR 3 // error
-#define SYS_NOXML 4 // don't send that down the XML stream
-
-extern	qboolean verbose;
-void Sys_Printf (const char *text, ...);
-void Sys_FPrintf (int flag, const char *text, ...);
-void Error( const char *error, ...);
-
-#ifdef _DEBUG
-#define DBG_XML 1
-#endif
-
-#ifdef DBG_XML
-void DumpXML();
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __INOUT__
+#define __INOUT__
+
+// inout is the only stuff relying on xml, include the headers there
+#include "libxml/tree.h"
+#include "mathlib.h"
+
+// some useful xml routines
+xmlNodePtr xml_NodeForVec( vec3_t v );
+void xml_SendNode (xmlNodePtr node);
+// print a message in q3map output and send the corresponding select information down the xml stream
+// bError: do we end with an error on this one or do we go ahead?
+void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
+// end q3map with an error message and send a point information in the xml stream
+// note: we might want to add a boolean to use this as a warning or an error thing..
+void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
+void xml_Point (char *msg, vec3_t pt);
+
+extern qboolean bNetworkBroadcast;
+void Broadcast_Setup( const char *dest );
+void Broadcast_Shutdown();
+
+#define SYS_VRB 0 // verbose support (on/off)
+#define SYS_STD 1 // standard print level
+#define SYS_WRN 2 // warnings
+#define SYS_ERR 3 // error
+#define SYS_NOXML 4 // don't send that down the XML stream
+
+extern	qboolean verbose;
+void Sys_Printf (const char *text, ...);
+void Sys_FPrintf (int flag, const char *text, ...);
+void Error( const char *error, ...);
+
+#ifdef _DEBUG
+#define DBG_XML 1
+#endif
+
+#ifdef DBG_XML
+void DumpXML();
+#endif
+
+#endif
diff --git a/tools/quake2/qdata_heretic2/common/l3dslib.c b/tools/quake2/qdata_heretic2/common/l3dslib.c
index 686c0191..12cdd193 100644
--- a/tools/quake2/qdata_heretic2/common/l3dslib.c
+++ b/tools/quake2/qdata_heretic2/common/l3dslib.c
@@ -1,476 +1,476 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// l3dslib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "l3dslib.h"
-#include "token.h"
-#include "fmodel.h"
-#include "bspfile.h"
-
-#define MAIN3DS       0x4D4D
-#define EDIT3DS       0x3D3D  // this is the start of the editor config
-#define EDIT_OBJECT   0x4000
-#define OBJ_TRIMESH   0x4100
-#define TRI_VERTEXL   0x4110
-#define TRI_FACEL1    0x4120
-
-#define MAXVERTS	2000
-
-typedef struct {
-	int	v[4];
-} tri;
-
-float	fverts[MAXVERTS][3];
-tri		tris[MAXTRIANGLES];
-
-int	bytesread, level, numtris, totaltris;
-int	vertsfound, trisfound;
-
-triangle_t	*ptri;
-
-
-
-void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles)
-{
-	int pos, bit, i;
-
-	if (nodesList)
-	{
-		*num_mesh_nodes = 1;
-		memset(&(*nodesList)[0], 0, sizeof(mesh_node_t));
-		strcpy((*nodesList)[0].name, "default");
-
-		// set all of the tris to be used for the top node
-		for(i = 0; i < (*numtriangles); i++)
-		{
-			pos = (i) >> 3;
-			bit = 1 << ((i) & 7 );
-
-			(*nodesList)[0].tris[pos] |= bit;
-		}
-	}
-}
-
-
-// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
-// start out with a vertex pool and vertex indices for triangles, we have to convert
-// to raw, explicit triangles
-void StoreAliasTriangles (void)
-{
-	int		i, j, k;
-
-	if ((totaltris + numtris) > MAXTRIANGLES)
-		Error ("Error: Too many triangles");
-
-	for (i=0; i<numtris ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			for (k=0 ; k<3 ; k++)
-			{
-				ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
-			}
-		}
-	}
-	
-	totaltris += numtris;
-	numtris = 0;
-	vertsfound = 0;
-	trisfound = 0;
-}
-
-
-int ParseVertexL (FILE *input)
-{
-	int				i, j, startbytesread, numverts;
-	unsigned short	tshort;
-
-	if (vertsfound)
-		Error ("Error: Multiple vertex chunks");
-
-	vertsfound = 1;
-	startbytesread = bytesread;
-
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&tshort, sizeof(tshort), 1, input);
-	bytesread += sizeof(tshort);
-	numverts = (int)tshort;
-
-	if (numverts > MAXVERTS)
-		Error ("Error: Too many vertices");
-
-	for (i=0 ; i<numverts ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread(&fverts[i][j], sizeof(float), 1, input);
-			bytesread += sizeof(float);
-		}
-	}
-
-	if (vertsfound && trisfound)
-		StoreAliasTriangles ();
-
-	return bytesread - startbytesread;
-}
-
-
-int ParseFaceL1 (FILE *input)
-{
-
-	int				i, j, startbytesread;
-	unsigned short	tshort;
-
-	if (trisfound)
-		Error ("Error: Multiple face chunks");
-
-	trisfound = 1;
-	startbytesread = bytesread;
-
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&tshort, sizeof(tshort), 1, input);
-	bytesread += sizeof(tshort);
-	numtris = (int)tshort;
-
-	if (numtris > MAXTRIANGLES)
-		Error ("Error: Too many triangles");
-
-	for (i=0 ; i<numtris ; i++)
-	{
-		for (j=0 ; j<4 ; j++)
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread(&tshort, sizeof(tshort), 1, input);
-			bytesread += sizeof(tshort);
-			tris[i].v[j] = (int)tshort;
-		}
-	}
-
-	if (vertsfound && trisfound)
-		StoreAliasTriangles ();
-
-	return bytesread - startbytesread;
-}
-
-
-int ParseChunk (FILE *input)
-{
-#define BLOCK_SIZE	4096
-	char			temp[BLOCK_SIZE];
-	unsigned short	type;
-	int				i, length, w, t, retval;
-
-	level++;
-	retval = 0;
-
-// chunk type
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&type, sizeof(type), 1, input);
-	bytesread += sizeof(type);
-
-// chunk length
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread (&length, sizeof(length), 1, input);
-	bytesread += sizeof(length);
-	w = length - 6;
-
-// process chunk if we care about it, otherwise skip it
-	switch (type)
-	{
-	case TRI_VERTEXL:
-		w -= ParseVertexL (input);
-		goto ParseSubchunk;
-
-	case TRI_FACEL1:
-		w -= ParseFaceL1 (input);
-		goto ParseSubchunk;
-
-	case EDIT_OBJECT:
-	// read the name
-		i = 0;
-
-		do
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread (&temp[i], 1, 1, input);
-			i++;
-			w--;
-			bytesread++;
-		} while (temp[i-1]);
-
-	case MAIN3DS:
-	case OBJ_TRIMESH:
-	case EDIT3DS:
-	// parse through subchunks
-ParseSubchunk:
-		while (w > 0)
-		{
-			w -= ParseChunk (input);
-		}
-
-		retval = length;
-		goto Done;
-
-	default:
-	// skip other chunks
-		while (w > 0)
-		{
-			t = w;
-
-			if (t > BLOCK_SIZE)
-				t = BLOCK_SIZE;
-
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread (&temp, t, 1, input);
-			bytesread += t;
-
-			w -= t;
-		}
-
-		retval = length;
-		goto Done;
-	}
-
-Done:
-	level--;
-	return retval;
-}
-
-
-void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes)
-{
-	FILE        *input;
-	short int	tshort;
-
-	if (nodesList)
-	{
-		*num_mesh_nodes = 0;
-		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-	}
-
-	bytesread = 0;
-	level = 0;
-	numtris = 0;
-	totaltris = 0;
-	vertsfound = 0;
-	trisfound = 0;
-
-	if ((input = fopen(filename, "rb")) == 0) {
-		fprintf(stderr,"reader: could not open file '%s'\n", filename);
-		exit(0);
-	}
-
-	fread(&tshort, sizeof(tshort), 1, input);
-
-// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
-// no MAIN3DS
-	if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
-		fprintf(stderr,"File is not a 3DS file.\n");
-		exit(0);
-	}
-
-// back to top of file so we can parse the first chunk descriptor
-	fseek(input, 0, SEEK_SET);
-
-	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
-
-	*pptri = ptri;
-
-// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
-// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
-	ParseChunk (input);
-
-	if (vertsfound || trisfound)
-		Error ("Incomplete triangle set");
-
-	*numtriangles = totaltris;
-
-	fclose (input);
-
-	DefaultNodesList(nodesList,num_mesh_nodes,numtriangles);
-}
-
-//==========================================================================
-//
-// LoadASC
-//
-//==========================================================================
-
-void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
-{
-	int			i, j;
-	int			vertexCount;
-	struct
-	{
-		float v[3];
-	}			*vList;
-	int			triCount;
-	triangle_t	*tList;
-	float		x, y, z;
-//	float		x2, y2, z2;
-//	float		rx, ry, rz;
-	qboolean	goodObject;
-
-	if (nodesList)
-	{
-		*num_mesh_nodes = 0;
-		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-	}
-
-	TK_OpenSource(fileName);
-
-	goodObject = false;
-	while(goodObject == false)
-	{
-		TK_Beyond(TK_C_NAMED);
-		TK_Beyond(TK_OBJECT);
-		TK_Beyond(TK_C_TRI);
-		TK_Beyond(TK_MESH);
-		TK_BeyondRequire(TK_C_VERTICES, TK_COLON);
-		TK_FetchRequire(TK_INTNUMBER);
-		vertexCount = tk_IntNumber;
-		if(vertexCount > 0)
-		{
-			goodObject = true;
-		}
-	}
-	TK_BeyondRequire(TK_C_FACES, TK_COLON);
-	TK_FetchRequire(TK_INTNUMBER);
-	triCount = tk_IntNumber;
-	if(triCount >= MAXTRIANGLES)
-	{
-		Error("Too many triangles in file %s\n", fileName);
-	}
-	*triangleCount = triCount;
-	tList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
-	*triList = tList;
-
-	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
-	TK_BeyondRequire(TK_C_VERTEX, TK_LIST);
-
-/*	rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
-	//rx = (rotation[0]/360.0)*2.0*M_PI;
-	ry = (rotation[1]/360.0)*2.0*M_PI;
-	rz = (rotation[2]/360.0)*2.0*M_PI;
-*/
-	vList = (void *) SafeMalloc(vertexCount*sizeof vList[0], "Vertex list");
-	for(i = 0; i < vertexCount; i++)
-	{
-		TK_BeyondRequire(TK_C_VERTEX, TK_INTNUMBER);
-		if(tk_IntNumber != i)
-		{
-			Error("File '%s', line %d:\nVertex index mismatch.\n",
-				tk_SourceName, tk_Line);
-		}
-		TK_FetchRequireFetch(TK_COLON);
-
-		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
-		x = tk_FloatNumber;
-		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
-		y = tk_FloatNumber;
-		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
-		z = tk_FloatNumber;
-
-/*		x2 = x*cos(rz)+y*sin(rz);
-		y2 = -x*sin(rz)+y*cos(rz);
-		x = x2;
-		y = y2;
-		y2 = y*cos(rx)+z*sin(rx);
-		z2 = -y*sin(rx)+z*cos(rx);
-		y = y2;
-		z = z2;
-		x2 = x*cos(ry)-z*sin(ry);
-		z2 = x*sin(ry)+z*cos(ry);
-		x = x2;
-		z = z2;
-*/
-		vList[i].v[0] = x;
-		vList[i].v[1] = y;
-		vList[i].v[2] = z;
-	}
-	TK_BeyondRequire(TK_C_FACE, TK_LIST);
-	for(i = 0; i < triCount; i++)
-	{
-		TK_BeyondRequire(TK_C_FACE, TK_INTNUMBER);
-		if(tk_IntNumber != i)
-		{
-			Error("File '%s', line %d:\nTriangle index mismatch.\n",
-				tk_SourceName, tk_Line);
-		}
-		for(j = 0; j < 3; j++)
-		{
-			TK_BeyondRequire(TK_IDENTIFIER, TK_COLON);
-			TK_FetchRequire(TK_INTNUMBER);
-			if(tk_IntNumber >= vertexCount)
-			{
-				Error("File '%s', line %d:\nVertex number"
-					" > vertexCount: %d\n", tk_SourceName, tk_Line,
-					tk_IntNumber);
-			}
-			tList[i].verts[2-j][0] = vList[tk_IntNumber].v[0];
-			tList[i].verts[2-j][1] = vList[tk_IntNumber].v[1];
-			tList[i].verts[2-j][2] = vList[tk_IntNumber].v[2];
-#ifdef _QDATA
-			tList[i].indicies[2-j] = tk_IntNumber;
-#endif
-		}
-
-/*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-			"  v2: %f, %f, %f\n", i,
-			tList[i].verts[0][0],
-			tList[i].verts[0][1],
-			tList[i].verts[0][2],
-			tList[i].verts[1][0],
-			tList[i].verts[1][1],
-			tList[i].verts[1][2],
-			tList[i].verts[2][0],
-			tList[i].verts[2][1],
-			tList[i].verts[2][2]);
-*/
-	}
-
-	DefaultNodesList(nodesList,num_mesh_nodes,triangleCount);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// l3dslib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "l3dslib.h"
+#include "token.h"
+#include "fmodel.h"
+#include "bspfile.h"
+
+#define MAIN3DS       0x4D4D
+#define EDIT3DS       0x3D3D  // this is the start of the editor config
+#define EDIT_OBJECT   0x4000
+#define OBJ_TRIMESH   0x4100
+#define TRI_VERTEXL   0x4110
+#define TRI_FACEL1    0x4120
+
+#define MAXVERTS	2000
+
+typedef struct {
+	int	v[4];
+} tri;
+
+float	fverts[MAXVERTS][3];
+tri		tris[MAXTRIANGLES];
+
+int	bytesread, level, numtris, totaltris;
+int	vertsfound, trisfound;
+
+triangle_t	*ptri;
+
+
+
+void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles)
+{
+	int pos, bit, i;
+
+	if (nodesList)
+	{
+		*num_mesh_nodes = 1;
+		memset(&(*nodesList)[0], 0, sizeof(mesh_node_t));
+		strcpy((*nodesList)[0].name, "default");
+
+		// set all of the tris to be used for the top node
+		for(i = 0; i < (*numtriangles); i++)
+		{
+			pos = (i) >> 3;
+			bit = 1 << ((i) & 7 );
+
+			(*nodesList)[0].tris[pos] |= bit;
+		}
+	}
+}
+
+
+// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
+// start out with a vertex pool and vertex indices for triangles, we have to convert
+// to raw, explicit triangles
+void StoreAliasTriangles (void)
+{
+	int		i, j, k;
+
+	if ((totaltris + numtris) > MAXTRIANGLES)
+		Error ("Error: Too many triangles");
+
+	for (i=0; i<numtris ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			for (k=0 ; k<3 ; k++)
+			{
+				ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
+			}
+		}
+	}
+	
+	totaltris += numtris;
+	numtris = 0;
+	vertsfound = 0;
+	trisfound = 0;
+}
+
+
+int ParseVertexL (FILE *input)
+{
+	int				i, j, startbytesread, numverts;
+	unsigned short	tshort;
+
+	if (vertsfound)
+		Error ("Error: Multiple vertex chunks");
+
+	vertsfound = 1;
+	startbytesread = bytesread;
+
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&tshort, sizeof(tshort), 1, input);
+	bytesread += sizeof(tshort);
+	numverts = (int)tshort;
+
+	if (numverts > MAXVERTS)
+		Error ("Error: Too many vertices");
+
+	for (i=0 ; i<numverts ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread(&fverts[i][j], sizeof(float), 1, input);
+			bytesread += sizeof(float);
+		}
+	}
+
+	if (vertsfound && trisfound)
+		StoreAliasTriangles ();
+
+	return bytesread - startbytesread;
+}
+
+
+int ParseFaceL1 (FILE *input)
+{
+
+	int				i, j, startbytesread;
+	unsigned short	tshort;
+
+	if (trisfound)
+		Error ("Error: Multiple face chunks");
+
+	trisfound = 1;
+	startbytesread = bytesread;
+
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&tshort, sizeof(tshort), 1, input);
+	bytesread += sizeof(tshort);
+	numtris = (int)tshort;
+
+	if (numtris > MAXTRIANGLES)
+		Error ("Error: Too many triangles");
+
+	for (i=0 ; i<numtris ; i++)
+	{
+		for (j=0 ; j<4 ; j++)
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread(&tshort, sizeof(tshort), 1, input);
+			bytesread += sizeof(tshort);
+			tris[i].v[j] = (int)tshort;
+		}
+	}
+
+	if (vertsfound && trisfound)
+		StoreAliasTriangles ();
+
+	return bytesread - startbytesread;
+}
+
+
+int ParseChunk (FILE *input)
+{
+#define BLOCK_SIZE	4096
+	char			temp[BLOCK_SIZE];
+	unsigned short	type;
+	int				i, length, w, t, retval;
+
+	level++;
+	retval = 0;
+
+// chunk type
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&type, sizeof(type), 1, input);
+	bytesread += sizeof(type);
+
+// chunk length
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread (&length, sizeof(length), 1, input);
+	bytesread += sizeof(length);
+	w = length - 6;
+
+// process chunk if we care about it, otherwise skip it
+	switch (type)
+	{
+	case TRI_VERTEXL:
+		w -= ParseVertexL (input);
+		goto ParseSubchunk;
+
+	case TRI_FACEL1:
+		w -= ParseFaceL1 (input);
+		goto ParseSubchunk;
+
+	case EDIT_OBJECT:
+	// read the name
+		i = 0;
+
+		do
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread (&temp[i], 1, 1, input);
+			i++;
+			w--;
+			bytesread++;
+		} while (temp[i-1]);
+
+	case MAIN3DS:
+	case OBJ_TRIMESH:
+	case EDIT3DS:
+	// parse through subchunks
+ParseSubchunk:
+		while (w > 0)
+		{
+			w -= ParseChunk (input);
+		}
+
+		retval = length;
+		goto Done;
+
+	default:
+	// skip other chunks
+		while (w > 0)
+		{
+			t = w;
+
+			if (t > BLOCK_SIZE)
+				t = BLOCK_SIZE;
+
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread (&temp, t, 1, input);
+			bytesread += t;
+
+			w -= t;
+		}
+
+		retval = length;
+		goto Done;
+	}
+
+Done:
+	level--;
+	return retval;
+}
+
+
+void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes)
+{
+	FILE        *input;
+	short int	tshort;
+
+	if (nodesList)
+	{
+		*num_mesh_nodes = 0;
+		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+	}
+
+	bytesread = 0;
+	level = 0;
+	numtris = 0;
+	totaltris = 0;
+	vertsfound = 0;
+	trisfound = 0;
+
+	if ((input = fopen(filename, "rb")) == 0) {
+		fprintf(stderr,"reader: could not open file '%s'\n", filename);
+		exit(0);
+	}
+
+	fread(&tshort, sizeof(tshort), 1, input);
+
+// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
+// no MAIN3DS
+	if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
+		fprintf(stderr,"File is not a 3DS file.\n");
+		exit(0);
+	}
+
+// back to top of file so we can parse the first chunk descriptor
+	fseek(input, 0, SEEK_SET);
+
+	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
+
+	*pptri = ptri;
+
+// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
+// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
+	ParseChunk (input);
+
+	if (vertsfound || trisfound)
+		Error ("Incomplete triangle set");
+
+	*numtriangles = totaltris;
+
+	fclose (input);
+
+	DefaultNodesList(nodesList,num_mesh_nodes,numtriangles);
+}
+
+//==========================================================================
+//
+// LoadASC
+//
+//==========================================================================
+
+void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
+{
+	int			i, j;
+	int			vertexCount;
+	struct
+	{
+		float v[3];
+	}			*vList;
+	int			triCount;
+	triangle_t	*tList;
+	float		x, y, z;
+//	float		x2, y2, z2;
+//	float		rx, ry, rz;
+	qboolean	goodObject;
+
+	if (nodesList)
+	{
+		*num_mesh_nodes = 0;
+		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+	}
+
+	TK_OpenSource(fileName);
+
+	goodObject = false;
+	while(goodObject == false)
+	{
+		TK_Beyond(TK_C_NAMED);
+		TK_Beyond(TK_OBJECT);
+		TK_Beyond(TK_C_TRI);
+		TK_Beyond(TK_MESH);
+		TK_BeyondRequire(TK_C_VERTICES, TK_COLON);
+		TK_FetchRequire(TK_INTNUMBER);
+		vertexCount = tk_IntNumber;
+		if(vertexCount > 0)
+		{
+			goodObject = true;
+		}
+	}
+	TK_BeyondRequire(TK_C_FACES, TK_COLON);
+	TK_FetchRequire(TK_INTNUMBER);
+	triCount = tk_IntNumber;
+	if(triCount >= MAXTRIANGLES)
+	{
+		Error("Too many triangles in file %s\n", fileName);
+	}
+	*triangleCount = triCount;
+	tList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
+	*triList = tList;
+
+	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
+	TK_BeyondRequire(TK_C_VERTEX, TK_LIST);
+
+/*	rx = ((rotation[0]+90.0)/360.0)*2.0*M_PI;
+	//rx = (rotation[0]/360.0)*2.0*M_PI;
+	ry = (rotation[1]/360.0)*2.0*M_PI;
+	rz = (rotation[2]/360.0)*2.0*M_PI;
+*/
+	vList = (void *) SafeMalloc(vertexCount*sizeof vList[0], "Vertex list");
+	for(i = 0; i < vertexCount; i++)
+	{
+		TK_BeyondRequire(TK_C_VERTEX, TK_INTNUMBER);
+		if(tk_IntNumber != i)
+		{
+			Error("File '%s', line %d:\nVertex index mismatch.\n",
+				tk_SourceName, tk_Line);
+		}
+		TK_FetchRequireFetch(TK_COLON);
+
+		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
+		x = tk_FloatNumber;
+		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
+		y = tk_FloatNumber;
+		TK_BeyondRequire(TK_COLON, TK_FLOATNUMBER);
+		z = tk_FloatNumber;
+
+/*		x2 = x*cos(rz)+y*sin(rz);
+		y2 = -x*sin(rz)+y*cos(rz);
+		x = x2;
+		y = y2;
+		y2 = y*cos(rx)+z*sin(rx);
+		z2 = -y*sin(rx)+z*cos(rx);
+		y = y2;
+		z = z2;
+		x2 = x*cos(ry)-z*sin(ry);
+		z2 = x*sin(ry)+z*cos(ry);
+		x = x2;
+		z = z2;
+*/
+		vList[i].v[0] = x;
+		vList[i].v[1] = y;
+		vList[i].v[2] = z;
+	}
+	TK_BeyondRequire(TK_C_FACE, TK_LIST);
+	for(i = 0; i < triCount; i++)
+	{
+		TK_BeyondRequire(TK_C_FACE, TK_INTNUMBER);
+		if(tk_IntNumber != i)
+		{
+			Error("File '%s', line %d:\nTriangle index mismatch.\n",
+				tk_SourceName, tk_Line);
+		}
+		for(j = 0; j < 3; j++)
+		{
+			TK_BeyondRequire(TK_IDENTIFIER, TK_COLON);
+			TK_FetchRequire(TK_INTNUMBER);
+			if(tk_IntNumber >= vertexCount)
+			{
+				Error("File '%s', line %d:\nVertex number"
+					" > vertexCount: %d\n", tk_SourceName, tk_Line,
+					tk_IntNumber);
+			}
+			tList[i].verts[2-j][0] = vList[tk_IntNumber].v[0];
+			tList[i].verts[2-j][1] = vList[tk_IntNumber].v[1];
+			tList[i].verts[2-j][2] = vList[tk_IntNumber].v[2];
+#ifdef _QDATA
+			tList[i].indicies[2-j] = tk_IntNumber;
+#endif
+		}
+
+/*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+			"  v2: %f, %f, %f\n", i,
+			tList[i].verts[0][0],
+			tList[i].verts[0][1],
+			tList[i].verts[0][2],
+			tList[i].verts[1][0],
+			tList[i].verts[1][1],
+			tList[i].verts[1][2],
+			tList[i].verts[2][0],
+			tList[i].verts[2][1],
+			tList[i].verts[2][2]);
+*/
+	}
+
+	DefaultNodesList(nodesList,num_mesh_nodes,triangleCount);
+}
diff --git a/tools/quake2/qdata_heretic2/common/l3dslib.h b/tools/quake2/qdata_heretic2/common/l3dslib.h
index 899b9fe6..7a26ade9 100644
--- a/tools/quake2/qdata_heretic2/common/l3dslib.h
+++ b/tools/quake2/qdata_heretic2/common/l3dslib.h
@@ -1,28 +1,28 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// l3dslib.h: header file for loading triangles from a 3DS triangle file
-//
-void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles);
-
-void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes);
-void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// l3dslib.h: header file for loading triangles from a 3DS triangle file
+//
+void DefaultNodesList(mesh_node_t **nodesList, int *num_mesh_nodes, int *numtriangles);
+
+void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes);
+void LoadASC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes);
diff --git a/tools/quake2/qdata_heretic2/common/lbmlib.c b/tools/quake2/qdata_heretic2/common/lbmlib.c
index 7e3611ac..7c1f714f 100644
--- a/tools/quake2/qdata_heretic2/common/lbmlib.c
+++ b/tools/quake2/qdata_heretic2/common/lbmlib.c
@@ -1,1052 +1,1052 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// lbmlib.c
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "lbmlib.h"
-
-// Ups the palette values so no pixels except 0 appear transparent
-// Need a value of 8 to cater for 16bit renderers
-
-typedef struct
-{
-	byte	r;
-	byte	g;
-	byte	b;
-} paletteRGB_t;
-
-
-void CorrectPalette(byte *pal)
-{
-	paletteRGB_t	*p;
-
-	p = (paletteRGB_t *)pal;
-	// Color 0 always transparent
-	p->r = 0;
-	p->g = 0;
-	p->b = 0;
-}
-
-/*
-============================================================================
-
-						LBM STUFF
-
-============================================================================
-*/
-
-
-typedef unsigned char	UBYTE;
-//conflicts with windows typedef short			WORD;
-typedef unsigned short	UWORD;
-typedef long			LONG;
-
-typedef enum
-{
-	ms_none,
-	ms_mask,
-	ms_transcolor,
-	ms_lasso
-} mask_t;
-
-typedef enum
-{
-	cm_none,
-	cm_rle1
-} compress_t;
-
-typedef struct
-{
-	UWORD		w,h;
-	short		x,y;
-	UBYTE		nPlanes;
-	UBYTE		masking;
-	UBYTE		compression;
-	UBYTE		pad1;
-	UWORD		transparentColor;
-	UBYTE		xAspect,yAspect;
-	short		pageWidth,pageHeight;
-} bmhd_t;
-
-extern	bmhd_t	bmhd;						// will be in native byte order
-
-
-
-#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
-#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
-#define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
-#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
-#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
-#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
-
-
-bmhd_t  bmhd;
-
-int    Align (int l)
-{
-	if (l&1)
-		return l+1;
-	return l;
-}
-
-
-
-/*
-================
-LBMRLEdecompress
-
-Source must be evenly aligned!
-================
-*/
-byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
-{
-	int     count;
-	byte    b,rept;
-
-	count = 0;
-
-	do
-	{
-		rept = *source++;
-
-		if (rept > 0x80)
-		{
-			rept = (rept^0xff)+2;
-			b = *source++;
-			memset(unpacked,b,rept);
-			unpacked += rept;
-		}
-		else if (rept < 0x80)
-		{
-			rept++;
-			memcpy(unpacked,source,rept);
-			unpacked += rept;
-			source += rept;
-		}
-		else
-			rept = 0;               // rept of 0x80 is NOP
-
-		count += rept;
-
-	} while (count<bpwidth);
-
-	if (count>bpwidth)
-		Error ("Decompression exceeded width!\n");
-
-
-	return source;
-}
-
-
-/*
-=================
-LoadLBM
-=================
-*/
-void LoadLBM (char *filename, byte **picture, byte **palette)
-{
-	byte    *LBMbuffer, *picbuffer, *cmapbuffer;
-	int             y;
-	byte    *LBM_P, *LBMEND_P;
-	byte    *pic_p;
-	byte    *body_p;
-
-	int    formtype,formlength;
-	int    chunktype,chunklength;
-
-// qiet compiler warnings
-	picbuffer = NULL;
-	cmapbuffer = NULL;
-
-//
-// load the LBM
-//
-	LoadFile (filename, (void **)&LBMbuffer);
-
-//
-// parse the LBM header
-//
-	LBM_P = LBMbuffer;
-	if ( *(int *)LBMbuffer != LittleLong(FORMID) )
-	   Error ("No FORM ID at start of file!\n");
-
-	LBM_P += 4;
-	formlength = BigLong( *(int *)LBM_P );
-	LBM_P += 4;
-	LBMEND_P = LBM_P + Align(formlength);
-
-	formtype = LittleLong(*(int *)LBM_P);
-
-	if (formtype != ILBMID && formtype != PBMID)
-		Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
-		,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
-
-	LBM_P += 4;
-
-//
-// parse chunks
-//
-
-	while (LBM_P < LBMEND_P)
-	{
-		chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
-		LBM_P += 4;
-		chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
-		LBM_P += 4;
-
-		switch ( chunktype )
-		{
-		case BMHDID:
-			memcpy (&bmhd,LBM_P,sizeof(bmhd));
-			bmhd.w = BigShort(bmhd.w);
-			bmhd.h = BigShort(bmhd.h);
-			bmhd.x = BigShort(bmhd.x);
-			bmhd.y = BigShort(bmhd.y);
-			bmhd.pageWidth = BigShort(bmhd.pageWidth);
-			bmhd.pageHeight = BigShort(bmhd.pageHeight);
-			break;
-
-		case CMAPID:
-			cmapbuffer = malloc (768);
-			memset (cmapbuffer, 0, 768);
-			memcpy (cmapbuffer, LBM_P, chunklength);
-			CorrectPalette(cmapbuffer);
-			break;
-
-		case BODYID:
-			body_p = LBM_P;
-
-			pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
-			if (formtype == PBMID)
-			{
-			//
-			// unpack PBM
-			//
-				for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
-				{
-					if (bmhd.compression == cm_rle1)
-						body_p = LBMRLEDecompress ((byte *)body_p
-						, pic_p , bmhd.w);
-					else if (bmhd.compression == cm_none)
-					{
-						memcpy (pic_p,body_p,bmhd.w);
-						body_p += Align(bmhd.w);
-					}
-				}
-
-			}
-			else
-			{
-			//
-			// unpack ILBM
-			//
-				Error ("%s is an interlaced LBM, not packed", filename);
-			}
-			break;
-		}
-
-		LBM_P += Align(chunklength);
-	}
-
-	free (LBMbuffer);
-
-	*picture = picbuffer;
-
-	if (palette)
-		*palette = cmapbuffer;
-}
-
-
-/*
-============================================================================
-
-							WRITE LBM
-
-============================================================================
-*/
-
-/*
-==============
-WriteLBMfile
-==============
-*/
-void WriteLBMfile (char *filename, byte *data,
-				   int width, int height, byte *palette)
-{
-	byte    *lbm, *lbmptr;
-	int    *formlength, *bmhdlength, *cmaplength, *bodylength;
-	int    length;
-	bmhd_t  basebmhd;
-
-	lbm = lbmptr = malloc (width*height+1000);
-
-//
-// start FORM
-//
-	*lbmptr++ = 'F';
-	*lbmptr++ = 'O';
-	*lbmptr++ = 'R';
-	*lbmptr++ = 'M';
-
-	formlength = (int*)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	*lbmptr++ = 'P';
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'M';
-	*lbmptr++ = ' ';
-
-//
-// write BMHD
-//
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'M';
-	*lbmptr++ = 'H';
-	*lbmptr++ = 'D';
-
-	bmhdlength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memset (&basebmhd,0,sizeof(basebmhd));
-	basebmhd.w = BigShort((short)width);
-	basebmhd.h = BigShort((short)height);
-	basebmhd.nPlanes = BigShort(8);
-	basebmhd.xAspect = BigShort(5);
-	basebmhd.yAspect = BigShort(6);
-	basebmhd.pageWidth = BigShort((short)width);
-	basebmhd.pageHeight = BigShort((short)height);
-
-	memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
-	lbmptr += sizeof(basebmhd);
-
-	length = lbmptr-(byte *)bmhdlength-4;
-	*bmhdlength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write CMAP
-//
-	*lbmptr++ = 'C';
-	*lbmptr++ = 'M';
-	*lbmptr++ = 'A';
-	*lbmptr++ = 'P';
-
-	cmaplength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memcpy (lbmptr,palette,768);
-	lbmptr += 768;
-
-	length = lbmptr-(byte *)cmaplength-4;
-	*cmaplength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write BODY
-//
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'O';
-	*lbmptr++ = 'D';
-	*lbmptr++ = 'Y';
-
-	bodylength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memcpy (lbmptr,data,width*height);
-	lbmptr += width*height;
-
-	length = lbmptr-(byte *)bodylength-4;
-	*bodylength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// done
-//
-	length = lbmptr-(byte *)formlength-4;
-	*formlength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write output file
-//
-	SaveFile (filename, lbm, lbmptr-lbm);
-	free (lbm);
-}
-
-
-/*
-============================================================================
-
-LOAD PCX
-
-============================================================================
-*/
-
-typedef struct
-{
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
-
-/*
-==============
-LoadPCX
-==============
-*/
-void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
-{
-	byte	*raw;
-	pcx_t	*pcx;
-	int		x, y;
-	int		len;
-	int		dataByte, runLength;
-	byte	*out, *pix;
-
-	//
-	// load the file
-	//
-	len = LoadFile (filename, (void **)&raw);
-
-	//
-	// parse the PCX file
-	//
-	pcx = (pcx_t *)raw;
-	raw = &pcx->data;
-
-	pcx->xmin = LittleShort(pcx->xmin);
-	pcx->ymin = LittleShort(pcx->ymin);
-	pcx->xmax = LittleShort(pcx->xmax);
-	pcx->ymax = LittleShort(pcx->ymax);
-	pcx->hres = LittleShort(pcx->hres);
-	pcx->vres = LittleShort(pcx->vres);
-	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
-	pcx->palette_type = LittleShort(pcx->palette_type);
-
-	if (pcx->manufacturer != 0x0a
-		|| pcx->version != 5
-		|| pcx->encoding != 1
-		|| pcx->bits_per_pixel != 8
-		|| pcx->xmax >= 640
-		|| pcx->ymax >= 480)
-		Error ("Bad pcx file %s", filename);
-	
-	if (palette)
-	{
-		*palette = malloc(768);
-		memcpy (*palette, (byte *)pcx + len - 768, 768);
-		CorrectPalette(*palette);
-	}
-
-	if (width)
-		*width = pcx->xmax+1;
-	if (height)
-		*height = pcx->ymax+1;
-
-	if (!pic)
-		return;
-
-	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
-	if (!out)
-		Error ("Skin_Cache: couldn't allocate");
-
-	*pic = out;
-
-	pix = out;
-
-	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
-	{
-		for (x=0 ; x<=pcx->xmax ; )
-		{
-			dataByte = *raw++;
-
-			if((dataByte & 0xC0) == 0xC0)
-			{
-				runLength = dataByte & 0x3F;
-				dataByte = *raw++;
-			}
-			else
-				runLength = 1;
-
-			while(runLength-- > 0)
-				pix[x++] = dataByte;
-		}
-
-	}
-
-	if ( raw - (byte *)pcx > len)
-		Error ("PCX file %s was malformed", filename);
-
-	free (pcx);
-}
-
-/* 
-============== 
-WritePCXfile 
-============== 
-*/ 
-
-void StuffPackedByte(int curRepCount, byte curByte, byte** packPtr)
-{
-	byte* pack;
-	
-	pack = *packPtr;
-
-	while(curRepCount > 0)
-	{
-		if (curRepCount == 1)
-		{
-			if ((curByte & 0xc0) != 0xc0)
-			{
-				*pack++ = curByte;
-			}
-			else
-			{
-				*pack++ = 0xc1;
-				*pack++ = curByte;
-			}
-			break;
-		}
-		if (curRepCount < 0x0040)
-		{
-			*pack++ = (0x00c0 | curRepCount);
-			curRepCount = 0;
-		}
-		else
-		{
-			*pack++ = 0xff;
-			curRepCount -= 0x003f;
-		}
-		*pack++ = curByte;
-	}
-	*packPtr = pack;
-}
-
-void WritePCXfile (char *filename, byte *data, 
-				   int width, int height, byte *palette) 
-{
-	int		i, j, length;
-	pcx_t		*pcx;
-	byte		*pack;
-	byte		curByte;
-	int			curRepCount;
-	  
-	pcx = malloc (width*height*2+1000);
-	memset (pcx, 0, sizeof(*pcx));
-
-	pcx->manufacturer = 0x0a;	// PCX id
-	pcx->version = 5;			// 256 color
- 	pcx->encoding = 1;		// RLE
-	pcx->bits_per_pixel = 8;		// 256 color
-	pcx->xmin = 0;
-	pcx->ymin = 0;
-	pcx->xmax = LittleShort((short)(width-1));
-	pcx->ymax = LittleShort((short)(height-1));
-	pcx->hres = LittleShort((short)width);
-	pcx->vres = LittleShort((short)height);
-	pcx->color_planes = 1;		// chunky image
-	pcx->bytes_per_line = LittleShort((short)width);
-	pcx->palette_type = LittleShort(1);		// not a grey scale
-
-	// pack the image
-	pack = &pcx->data;
-	
-/*	for (i=0 ; i<height ; i++)
-	{
-		for (j=0 ; j<width ; j++)
-		{
-			if ( (*data & 0xc0) != 0xc0)
-				*pack++ = *data++;
-			else
-			{
-				*pack++ = 0xc1;
-				*pack++ = *data++;
-			}
-		}
-	}
-*/	
-	for (i=0 ; i<height ; i++)
-	{
-		curByte = *data;
-		curRepCount = 0;
-		for (j=0 ; j<width ; j++)
-		{
-			if (*data == curByte)
-			{
-				curRepCount++;
-				data++;
-				continue;
-			}
-			StuffPackedByte(curRepCount, curByte, &pack);
-			curByte = *data++;
-			curRepCount = 1;
-		}
-		StuffPackedByte(curRepCount, curByte, &pack);
-	}
-	// write the palette
-	*pack++ = 0x0c;	// palette ID byte
-	for (i=0 ; i<768 ; i++)
-		*pack++ = *palette++;
-		
-// write output file 
-	length = pack - (byte *)pcx;
-	SaveFile (filename, pcx, length);
-
-	free (pcx);
-} 
- 
-
-/*
-============================================================================
-
-LOAD IMAGE
-
-============================================================================
-*/
-
-/*
-==============
-Load256Image
-
-Will load either an lbm or pcx, depending on extension.
-Any of the return pointers can be NULL if you don't want them.
-==============
-*/
-void Load256Image (char *name, byte **pixels, byte **palette,
-				   int *width, int *height)
-{
-	char	ext[128];
-
-	ExtractFileExtension (name, ext);
-	if (!Q_strcasecmp (ext, "lbm"))
-	{
-		LoadLBM (name, pixels, palette);
-		if (width)
-			*width = bmhd.w;
-		if (height)
-			*height = bmhd.h;
-	}
-	else if (!Q_strcasecmp (ext, "pcx"))
-	{
-		LoadPCX (name, pixels, palette, width, height);
-	}
-	else
-		Error ("%s doesn't have a known image extension", name);
-}
-
-
-/*
-==============
-Save256Image
-
-Will save either an lbm or pcx, depending on extension.
-==============
-*/
-void Save256Image (char *name, byte *pixels, byte *palette,
-				   int width, int height)
-{
-	char	ext[128];
-
-	ExtractFileExtension (name, ext);
-	if (!Q_strcasecmp (ext, "lbm"))
-	{
-		WriteLBMfile (name, pixels, width, height, palette);
-	}
-	else if (!Q_strcasecmp (ext, "pcx"))
-	{
-		WritePCXfile (name, pixels, width, height, palette);
-	}
-	else
-		Error ("%s doesn't have a known image extension", name);
-}
-
-
-
-
-/*
-============================================================================
-
-TARGA IMAGE
-
-============================================================================
-*/
-
-typedef struct _TargaHeader
-{
-	unsigned char 	id_length, colormap_type, image_type;
-	unsigned short	colormap_index, colormap_length;
-	unsigned char	colormap_size;
-	unsigned short	x_origin, y_origin, width, height;
-	unsigned char	pixel_size, attributes;
-} TargaHeader;
-
-int fgetLittleShort (FILE *f)
-{
-	byte	b1, b2;
-
-	b1 = fgetc(f);
-	b2 = fgetc(f);
-
-	return((short)(b1 + (b2 << 8)));
-}
-
-int fgetLittleLong (FILE *f)
-{
-	byte	b1, b2, b3, b4;
-
-	b1 = fgetc(f);
-	b2 = fgetc(f);
-	b3 = fgetc(f);
-	b4 = fgetc(f);
-
-	return(b1 + (b2 << 8) + (b3 << 16) + (b4 << 24));
-}
-
-
-/*
-=============
-LoadTGA
-=============
-*/
-void LoadTGA(char *name, byte **pixels, int *width, int *height)
-{
-	int				columns, rows, numPixels;
-	byte			*pixbuf;
-	byte			*rowBuf;
-	int				row, column;
-	FILE			*fin;
-	byte			*targa_rgba;
-	TargaHeader		targa_header;
-	unsigned char	red, green, blue, alphabyte;
-	unsigned char	packetHeader, packetSize, j;
-	int				flip;
-	int				mirror;
-	int				rowOffset;
-	int				pixDirection;
-
-	fin = fopen(name, "rb");
-	if (!fin)
-		Error ("Couldn't read %s", name);
-
-	targa_header.id_length = fgetc(fin);
-	targa_header.colormap_type = fgetc(fin);
-	targa_header.image_type = fgetc(fin);
-	
-	targa_header.colormap_index = fgetLittleShort(fin);
-	targa_header.colormap_length = fgetLittleShort(fin);
-	targa_header.colormap_size = fgetc(fin);
-	targa_header.x_origin = fgetLittleShort(fin);
-	targa_header.y_origin = fgetLittleShort(fin);
-	targa_header.width = fgetLittleShort(fin);
-	targa_header.height = fgetLittleShort(fin);
-	targa_header.pixel_size = fgetc(fin);
-	targa_header.attributes = fgetc(fin);
-	flip = (targa_header.attributes & 0x020) == 0;
-	mirror = (targa_header.attributes & 0x010) != 0;
-
-	if ((targa_header.image_type != 2) && (targa_header.image_type != 10)) 
-		Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
-
-	if (targa_header.colormap_type || ((targa_header.pixel_size != 32) && (targa_header.pixel_size != 24)))
-		Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
-
-	columns = targa_header.width;
-	rows = targa_header.height;
-	numPixels = columns * rows;
-
-	if (width)
-		*width = columns;
-	if (height)
-		*height = rows;
-
-	if(!pixels)
-		return;
-
-	targa_rgba = malloc(numPixels * 4);
-	*pixels = targa_rgba;
-
-	if (flip)
-	{
-		pixbuf = targa_rgba + ((rows - 1) * columns * 4);
-		rowOffset = -columns * 4;
-	}
-	else
-	{
-		pixbuf = targa_rgba;
-		rowOffset = columns * 4;
-	}
-	if (mirror)
-	{
-		pixDirection = -4;
-		pixbuf += ((columns - 1) * 4);
-	}
-	else
-	{
-		pixDirection = 4;
-	}
-
-	if (targa_header.id_length)
-		fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
-	
-	if (targa_header.image_type == 2)
-	{													// Uncompressed, RGB images
-		for(row = 0; row < rows; row++)
-		{
-			rowBuf = pixbuf;
-			for(column = 0; column < columns; column++)
-			{
-				switch (targa_header.pixel_size)
-				{
-					case 24:
-						blue = getc(fin);
-						green = getc(fin);
-						red = getc(fin);
-						rowBuf[0] = red;
-						rowBuf[1] = green;
-						rowBuf[2] = blue;
-						rowBuf[3] = 255;
-						rowBuf += pixDirection;
-					break;
-					case 32:
-						blue = getc(fin);
-						green = getc(fin);
-						red = getc(fin);
-						alphabyte = getc(fin);
-						rowBuf[0] = red;
-						rowBuf[1] = green;
-						rowBuf[2] = blue;
-						rowBuf[3] = alphabyte;
-						rowBuf += pixDirection;
-					break;
-				}
-			}
-			pixbuf += rowOffset;
-		}
-	}
-	else if(targa_header.image_type == 10)
-	{												// Runlength encoded RGB images
-		for(row = 0; row < rows; row++)
-		{
-			rowBuf = pixbuf;
-			for(column = 0; column < columns; )
-			{
-				packetHeader = getc(fin);
-				packetSize = 1 + (packetHeader & 0x7f);
-				if (packetHeader & 0x80)
-				{									// run-length packet
-					switch (targa_header.pixel_size)
-					{
-						case 24:
-					 		blue = getc(fin);
-					 		green = getc(fin);
-					 		red = getc(fin);
-					 		alphabyte = 255;
-					 	break;
-						case 32:
-					 		blue = getc(fin);
-					 		green = getc(fin);
-					 		red = getc(fin);
-					 		alphabyte = getc(fin);
-					 	break;
-					}
-	
-					for(j = 0; j < packetSize; j++)
-					{
-						rowBuf[0] = red;
-						rowBuf[1] = green;
-						rowBuf[2] = blue;
-						rowBuf[3] = alphabyte;
-						rowBuf += pixDirection;
-						column++;
-						if(column == columns)
-						{									// run spans across rows
-							column = 0;
-							row++;
-							if (row >= rows)
-								goto breakOut;
-							pixbuf += rowOffset;
-							rowBuf = pixbuf;
-						}
-					}
-				}
-				else
-				{			                            // non run-length packet
-					for(j = 0; j < packetSize; j++)
-					{
-						switch (targa_header.pixel_size)
-						{
-							case 24:
-								blue = getc(fin);
-								green = getc(fin);
-								red = getc(fin);
-								rowBuf[0] = red;
-								rowBuf[1] = green;
-								rowBuf[2] = blue;
-								rowBuf[3] = 255;
-								rowBuf += pixDirection;
-							break;
-							case 32:
-								blue = getc(fin);
-								green = getc(fin);
-								red = getc(fin);
-								alphabyte = getc(fin);
-								rowBuf[0] = red;
-								rowBuf[1] = green;
-								rowBuf[2] = blue;
-								rowBuf[3] = alphabyte;
-								rowBuf += pixDirection;
-							break;
-						}
-						column++;
-						if (column == columns)
-						{							// pixel packet run spans across rows
-							column = 0;
-							row++;
-							if (row >= rows)
-								goto breakOut;
-							pixbuf += rowOffset;
-							rowBuf = pixbuf;
-						}						
-					}
-				}
-			}
-			breakOut:;
-			pixbuf += rowOffset;
-		}
-	}
-	fclose(fin);
-}
-
-void MergeAlpha(byte *pix, byte *alpha, byte *pal, byte **out, int width, int height)
-{
-	int		size, i;
-	byte	*data, *src, *srca;
-
-	size = width * height;
-	data = malloc(size * 4);
-	if(!data)
-		Error("Could not allocate memory for true color image");
-
-	*out = data;
-	src = pix;
-	srca = alpha;
-
-	for(i = 0; i < size; i++, src++, srca++)
-	{
-		*data++ = pal[*src * 3 + 0];	  // r
-		*data++ = pal[*src * 3 + 1];	  // g
-		*data++ = pal[*src * 3 + 2];	  // b
-		*data++ = *srca;				  // a
-	}
-	free(pix);
-	free(alpha);
-	free(pal);
-}
-
-/*
-==============
-LoadAnyImage
-
-Return Value:
-	false: paletted texture
-	true:  true color RGBA image (no palette)
-==============
-*/
-qboolean LoadAnyImage (char *name, byte **pixels, byte **palette, int *width, int *height)
-{
-	char	ext[128];
-	int		len;
-	int		alpha_width, alpha_height;
-	char	alpha_name[128];
-	byte	*alpha_pixels;
-
-	ExtractFileExtension (name, ext);
-
-	if(palette)
-	{
-		*palette = NULL;
-	}
-
-	if (!Q_strcasecmp (ext, "lbm"))
-	{
-		LoadLBM (name, pixels, palette);
-		if (width)
-			*width = bmhd.w;
-		if (height)
-			*height = bmhd.h;
-		return false;
-	}
-	else if (!Q_strcasecmp (ext, "pcx"))
-	{
-		len = strlen(name);
-		strcpy(alpha_name, name);
-		strcpy(&alpha_name[len - 4], "_a.pcx");					// Alpha map name (may not exist)
-
-		if(FileExists(alpha_name))
-		{
-			LoadPCX (name, pixels, palette, width, height);							// Load in image
-			LoadPCX (alpha_name, &alpha_pixels, NULL, &alpha_width, &alpha_height);	// Load in alpha map	
-			if((*width != alpha_width) || (*height != alpha_height))
-			{
-				Error("Alpha image dimensions not equal to graphic image dimensions");
-			}
-			MergeAlpha(*pixels, alpha_pixels, *palette, pixels, *width, *height);
-			*palette = NULL;//Merge Frees pal
-			return true;
-		}
-		else
-		{
-			LoadPCX (name, pixels, palette, width, height);			// Load in image
-			return false;
-		}
-	}
-	else if (!Q_strcasecmp (ext, "tga"))
-	{
-		LoadTGA(name, pixels, width, height);
-		if (palette)
-		{
-			*palette = NULL;
-		}
-
-		return true;
-	}
-	else
-		Error ("%s doesn't have a known image extension", name);
-
-	return false;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// lbmlib.c
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "lbmlib.h"
+
+// Ups the palette values so no pixels except 0 appear transparent
+// Need a value of 8 to cater for 16bit renderers
+
+typedef struct
+{
+	byte	r;
+	byte	g;
+	byte	b;
+} paletteRGB_t;
+
+
+void CorrectPalette(byte *pal)
+{
+	paletteRGB_t	*p;
+
+	p = (paletteRGB_t *)pal;
+	// Color 0 always transparent
+	p->r = 0;
+	p->g = 0;
+	p->b = 0;
+}
+
+/*
+============================================================================
+
+						LBM STUFF
+
+============================================================================
+*/
+
+
+typedef unsigned char	UBYTE;
+//conflicts with windows typedef short			WORD;
+typedef unsigned short	UWORD;
+typedef long			LONG;
+
+typedef enum
+{
+	ms_none,
+	ms_mask,
+	ms_transcolor,
+	ms_lasso
+} mask_t;
+
+typedef enum
+{
+	cm_none,
+	cm_rle1
+} compress_t;
+
+typedef struct
+{
+	UWORD		w,h;
+	short		x,y;
+	UBYTE		nPlanes;
+	UBYTE		masking;
+	UBYTE		compression;
+	UBYTE		pad1;
+	UWORD		transparentColor;
+	UBYTE		xAspect,yAspect;
+	short		pageWidth,pageHeight;
+} bmhd_t;
+
+extern	bmhd_t	bmhd;						// will be in native byte order
+
+
+
+#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
+#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
+#define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
+#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
+#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
+#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
+
+
+bmhd_t  bmhd;
+
+int    Align (int l)
+{
+	if (l&1)
+		return l+1;
+	return l;
+}
+
+
+
+/*
+================
+LBMRLEdecompress
+
+Source must be evenly aligned!
+================
+*/
+byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
+{
+	int     count;
+	byte    b,rept;
+
+	count = 0;
+
+	do
+	{
+		rept = *source++;
+
+		if (rept > 0x80)
+		{
+			rept = (rept^0xff)+2;
+			b = *source++;
+			memset(unpacked,b,rept);
+			unpacked += rept;
+		}
+		else if (rept < 0x80)
+		{
+			rept++;
+			memcpy(unpacked,source,rept);
+			unpacked += rept;
+			source += rept;
+		}
+		else
+			rept = 0;               // rept of 0x80 is NOP
+
+		count += rept;
+
+	} while (count<bpwidth);
+
+	if (count>bpwidth)
+		Error ("Decompression exceeded width!\n");
+
+
+	return source;
+}
+
+
+/*
+=================
+LoadLBM
+=================
+*/
+void LoadLBM (char *filename, byte **picture, byte **palette)
+{
+	byte    *LBMbuffer, *picbuffer, *cmapbuffer;
+	int             y;
+	byte    *LBM_P, *LBMEND_P;
+	byte    *pic_p;
+	byte    *body_p;
+
+	int    formtype,formlength;
+	int    chunktype,chunklength;
+
+// qiet compiler warnings
+	picbuffer = NULL;
+	cmapbuffer = NULL;
+
+//
+// load the LBM
+//
+	LoadFile (filename, (void **)&LBMbuffer);
+
+//
+// parse the LBM header
+//
+	LBM_P = LBMbuffer;
+	if ( *(int *)LBMbuffer != LittleLong(FORMID) )
+	   Error ("No FORM ID at start of file!\n");
+
+	LBM_P += 4;
+	formlength = BigLong( *(int *)LBM_P );
+	LBM_P += 4;
+	LBMEND_P = LBM_P + Align(formlength);
+
+	formtype = LittleLong(*(int *)LBM_P);
+
+	if (formtype != ILBMID && formtype != PBMID)
+		Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
+		,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
+
+	LBM_P += 4;
+
+//
+// parse chunks
+//
+
+	while (LBM_P < LBMEND_P)
+	{
+		chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
+		LBM_P += 4;
+		chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
+		LBM_P += 4;
+
+		switch ( chunktype )
+		{
+		case BMHDID:
+			memcpy (&bmhd,LBM_P,sizeof(bmhd));
+			bmhd.w = BigShort(bmhd.w);
+			bmhd.h = BigShort(bmhd.h);
+			bmhd.x = BigShort(bmhd.x);
+			bmhd.y = BigShort(bmhd.y);
+			bmhd.pageWidth = BigShort(bmhd.pageWidth);
+			bmhd.pageHeight = BigShort(bmhd.pageHeight);
+			break;
+
+		case CMAPID:
+			cmapbuffer = malloc (768);
+			memset (cmapbuffer, 0, 768);
+			memcpy (cmapbuffer, LBM_P, chunklength);
+			CorrectPalette(cmapbuffer);
+			break;
+
+		case BODYID:
+			body_p = LBM_P;
+
+			pic_p = picbuffer = malloc (bmhd.w*bmhd.h);
+			if (formtype == PBMID)
+			{
+			//
+			// unpack PBM
+			//
+				for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
+				{
+					if (bmhd.compression == cm_rle1)
+						body_p = LBMRLEDecompress ((byte *)body_p
+						, pic_p , bmhd.w);
+					else if (bmhd.compression == cm_none)
+					{
+						memcpy (pic_p,body_p,bmhd.w);
+						body_p += Align(bmhd.w);
+					}
+				}
+
+			}
+			else
+			{
+			//
+			// unpack ILBM
+			//
+				Error ("%s is an interlaced LBM, not packed", filename);
+			}
+			break;
+		}
+
+		LBM_P += Align(chunklength);
+	}
+
+	free (LBMbuffer);
+
+	*picture = picbuffer;
+
+	if (palette)
+		*palette = cmapbuffer;
+}
+
+
+/*
+============================================================================
+
+							WRITE LBM
+
+============================================================================
+*/
+
+/*
+==============
+WriteLBMfile
+==============
+*/
+void WriteLBMfile (char *filename, byte *data,
+				   int width, int height, byte *palette)
+{
+	byte    *lbm, *lbmptr;
+	int    *formlength, *bmhdlength, *cmaplength, *bodylength;
+	int    length;
+	bmhd_t  basebmhd;
+
+	lbm = lbmptr = malloc (width*height+1000);
+
+//
+// start FORM
+//
+	*lbmptr++ = 'F';
+	*lbmptr++ = 'O';
+	*lbmptr++ = 'R';
+	*lbmptr++ = 'M';
+
+	formlength = (int*)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	*lbmptr++ = 'P';
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'M';
+	*lbmptr++ = ' ';
+
+//
+// write BMHD
+//
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'M';
+	*lbmptr++ = 'H';
+	*lbmptr++ = 'D';
+
+	bmhdlength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memset (&basebmhd,0,sizeof(basebmhd));
+	basebmhd.w = BigShort((short)width);
+	basebmhd.h = BigShort((short)height);
+	basebmhd.nPlanes = BigShort(8);
+	basebmhd.xAspect = BigShort(5);
+	basebmhd.yAspect = BigShort(6);
+	basebmhd.pageWidth = BigShort((short)width);
+	basebmhd.pageHeight = BigShort((short)height);
+
+	memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
+	lbmptr += sizeof(basebmhd);
+
+	length = lbmptr-(byte *)bmhdlength-4;
+	*bmhdlength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write CMAP
+//
+	*lbmptr++ = 'C';
+	*lbmptr++ = 'M';
+	*lbmptr++ = 'A';
+	*lbmptr++ = 'P';
+
+	cmaplength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memcpy (lbmptr,palette,768);
+	lbmptr += 768;
+
+	length = lbmptr-(byte *)cmaplength-4;
+	*cmaplength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write BODY
+//
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'O';
+	*lbmptr++ = 'D';
+	*lbmptr++ = 'Y';
+
+	bodylength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memcpy (lbmptr,data,width*height);
+	lbmptr += width*height;
+
+	length = lbmptr-(byte *)bodylength-4;
+	*bodylength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// done
+//
+	length = lbmptr-(byte *)formlength-4;
+	*formlength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write output file
+//
+	SaveFile (filename, lbm, lbmptr-lbm);
+	free (lbm);
+}
+
+
+/*
+============================================================================
+
+LOAD PCX
+
+============================================================================
+*/
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+/*
+==============
+LoadPCX
+==============
+*/
+void LoadPCX (char *filename, byte **pic, byte **palette, int *width, int *height)
+{
+	byte	*raw;
+	pcx_t	*pcx;
+	int		x, y;
+	int		len;
+	int		dataByte, runLength;
+	byte	*out, *pix;
+
+	//
+	// load the file
+	//
+	len = LoadFile (filename, (void **)&raw);
+
+	//
+	// parse the PCX file
+	//
+	pcx = (pcx_t *)raw;
+	raw = &pcx->data;
+
+	pcx->xmin = LittleShort(pcx->xmin);
+	pcx->ymin = LittleShort(pcx->ymin);
+	pcx->xmax = LittleShort(pcx->xmax);
+	pcx->ymax = LittleShort(pcx->ymax);
+	pcx->hres = LittleShort(pcx->hres);
+	pcx->vres = LittleShort(pcx->vres);
+	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
+	pcx->palette_type = LittleShort(pcx->palette_type);
+
+	if (pcx->manufacturer != 0x0a
+		|| pcx->version != 5
+		|| pcx->encoding != 1
+		|| pcx->bits_per_pixel != 8
+		|| pcx->xmax >= 640
+		|| pcx->ymax >= 480)
+		Error ("Bad pcx file %s", filename);
+	
+	if (palette)
+	{
+		*palette = malloc(768);
+		memcpy (*palette, (byte *)pcx + len - 768, 768);
+		CorrectPalette(*palette);
+	}
+
+	if (width)
+		*width = pcx->xmax+1;
+	if (height)
+		*height = pcx->ymax+1;
+
+	if (!pic)
+		return;
+
+	out = malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
+	if (!out)
+		Error ("Skin_Cache: couldn't allocate");
+
+	*pic = out;
+
+	pix = out;
+
+	for (y=0 ; y<=pcx->ymax ; y++, pix += pcx->xmax+1)
+	{
+		for (x=0 ; x<=pcx->xmax ; )
+		{
+			dataByte = *raw++;
+
+			if((dataByte & 0xC0) == 0xC0)
+			{
+				runLength = dataByte & 0x3F;
+				dataByte = *raw++;
+			}
+			else
+				runLength = 1;
+
+			while(runLength-- > 0)
+				pix[x++] = dataByte;
+		}
+
+	}
+
+	if ( raw - (byte *)pcx > len)
+		Error ("PCX file %s was malformed", filename);
+
+	free (pcx);
+}
+
+/* 
+============== 
+WritePCXfile 
+============== 
+*/ 
+
+void StuffPackedByte(int curRepCount, byte curByte, byte** packPtr)
+{
+	byte* pack;
+	
+	pack = *packPtr;
+
+	while(curRepCount > 0)
+	{
+		if (curRepCount == 1)
+		{
+			if ((curByte & 0xc0) != 0xc0)
+			{
+				*pack++ = curByte;
+			}
+			else
+			{
+				*pack++ = 0xc1;
+				*pack++ = curByte;
+			}
+			break;
+		}
+		if (curRepCount < 0x0040)
+		{
+			*pack++ = (0x00c0 | curRepCount);
+			curRepCount = 0;
+		}
+		else
+		{
+			*pack++ = 0xff;
+			curRepCount -= 0x003f;
+		}
+		*pack++ = curByte;
+	}
+	*packPtr = pack;
+}
+
+void WritePCXfile (char *filename, byte *data, 
+				   int width, int height, byte *palette) 
+{
+	int		i, j, length;
+	pcx_t		*pcx;
+	byte		*pack;
+	byte		curByte;
+	int			curRepCount;
+	  
+	pcx = malloc (width*height*2+1000);
+	memset (pcx, 0, sizeof(*pcx));
+
+	pcx->manufacturer = 0x0a;	// PCX id
+	pcx->version = 5;			// 256 color
+ 	pcx->encoding = 1;		// RLE
+	pcx->bits_per_pixel = 8;		// 256 color
+	pcx->xmin = 0;
+	pcx->ymin = 0;
+	pcx->xmax = LittleShort((short)(width-1));
+	pcx->ymax = LittleShort((short)(height-1));
+	pcx->hres = LittleShort((short)width);
+	pcx->vres = LittleShort((short)height);
+	pcx->color_planes = 1;		// chunky image
+	pcx->bytes_per_line = LittleShort((short)width);
+	pcx->palette_type = LittleShort(1);		// not a grey scale
+
+	// pack the image
+	pack = &pcx->data;
+	
+/*	for (i=0 ; i<height ; i++)
+	{
+		for (j=0 ; j<width ; j++)
+		{
+			if ( (*data & 0xc0) != 0xc0)
+				*pack++ = *data++;
+			else
+			{
+				*pack++ = 0xc1;
+				*pack++ = *data++;
+			}
+		}
+	}
+*/	
+	for (i=0 ; i<height ; i++)
+	{
+		curByte = *data;
+		curRepCount = 0;
+		for (j=0 ; j<width ; j++)
+		{
+			if (*data == curByte)
+			{
+				curRepCount++;
+				data++;
+				continue;
+			}
+			StuffPackedByte(curRepCount, curByte, &pack);
+			curByte = *data++;
+			curRepCount = 1;
+		}
+		StuffPackedByte(curRepCount, curByte, &pack);
+	}
+	// write the palette
+	*pack++ = 0x0c;	// palette ID byte
+	for (i=0 ; i<768 ; i++)
+		*pack++ = *palette++;
+		
+// write output file 
+	length = pack - (byte *)pcx;
+	SaveFile (filename, pcx, length);
+
+	free (pcx);
+} 
+ 
+
+/*
+============================================================================
+
+LOAD IMAGE
+
+============================================================================
+*/
+
+/*
+==============
+Load256Image
+
+Will load either an lbm or pcx, depending on extension.
+Any of the return pointers can be NULL if you don't want them.
+==============
+*/
+void Load256Image (char *name, byte **pixels, byte **palette,
+				   int *width, int *height)
+{
+	char	ext[128];
+
+	ExtractFileExtension (name, ext);
+	if (!Q_strcasecmp (ext, "lbm"))
+	{
+		LoadLBM (name, pixels, palette);
+		if (width)
+			*width = bmhd.w;
+		if (height)
+			*height = bmhd.h;
+	}
+	else if (!Q_strcasecmp (ext, "pcx"))
+	{
+		LoadPCX (name, pixels, palette, width, height);
+	}
+	else
+		Error ("%s doesn't have a known image extension", name);
+}
+
+
+/*
+==============
+Save256Image
+
+Will save either an lbm or pcx, depending on extension.
+==============
+*/
+void Save256Image (char *name, byte *pixels, byte *palette,
+				   int width, int height)
+{
+	char	ext[128];
+
+	ExtractFileExtension (name, ext);
+	if (!Q_strcasecmp (ext, "lbm"))
+	{
+		WriteLBMfile (name, pixels, width, height, palette);
+	}
+	else if (!Q_strcasecmp (ext, "pcx"))
+	{
+		WritePCXfile (name, pixels, width, height, palette);
+	}
+	else
+		Error ("%s doesn't have a known image extension", name);
+}
+
+
+
+
+/*
+============================================================================
+
+TARGA IMAGE
+
+============================================================================
+*/
+
+typedef struct _TargaHeader
+{
+	unsigned char 	id_length, colormap_type, image_type;
+	unsigned short	colormap_index, colormap_length;
+	unsigned char	colormap_size;
+	unsigned short	x_origin, y_origin, width, height;
+	unsigned char	pixel_size, attributes;
+} TargaHeader;
+
+int fgetLittleShort (FILE *f)
+{
+	byte	b1, b2;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+
+	return((short)(b1 + (b2 << 8)));
+}
+
+int fgetLittleLong (FILE *f)
+{
+	byte	b1, b2, b3, b4;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+	b3 = fgetc(f);
+	b4 = fgetc(f);
+
+	return(b1 + (b2 << 8) + (b3 << 16) + (b4 << 24));
+}
+
+
+/*
+=============
+LoadTGA
+=============
+*/
+void LoadTGA(char *name, byte **pixels, int *width, int *height)
+{
+	int				columns, rows, numPixels;
+	byte			*pixbuf;
+	byte			*rowBuf;
+	int				row, column;
+	FILE			*fin;
+	byte			*targa_rgba;
+	TargaHeader		targa_header;
+	unsigned char	red, green, blue, alphabyte;
+	unsigned char	packetHeader, packetSize, j;
+	int				flip;
+	int				mirror;
+	int				rowOffset;
+	int				pixDirection;
+
+	fin = fopen(name, "rb");
+	if (!fin)
+		Error ("Couldn't read %s", name);
+
+	targa_header.id_length = fgetc(fin);
+	targa_header.colormap_type = fgetc(fin);
+	targa_header.image_type = fgetc(fin);
+	
+	targa_header.colormap_index = fgetLittleShort(fin);
+	targa_header.colormap_length = fgetLittleShort(fin);
+	targa_header.colormap_size = fgetc(fin);
+	targa_header.x_origin = fgetLittleShort(fin);
+	targa_header.y_origin = fgetLittleShort(fin);
+	targa_header.width = fgetLittleShort(fin);
+	targa_header.height = fgetLittleShort(fin);
+	targa_header.pixel_size = fgetc(fin);
+	targa_header.attributes = fgetc(fin);
+	flip = (targa_header.attributes & 0x020) == 0;
+	mirror = (targa_header.attributes & 0x010) != 0;
+
+	if ((targa_header.image_type != 2) && (targa_header.image_type != 10)) 
+		Error ("LoadTGA: Only type 2 and 10 targa RGB images supported\n");
+
+	if (targa_header.colormap_type || ((targa_header.pixel_size != 32) && (targa_header.pixel_size != 24)))
+		Error ("Texture_LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+
+	columns = targa_header.width;
+	rows = targa_header.height;
+	numPixels = columns * rows;
+
+	if (width)
+		*width = columns;
+	if (height)
+		*height = rows;
+
+	if(!pixels)
+		return;
+
+	targa_rgba = malloc(numPixels * 4);
+	*pixels = targa_rgba;
+
+	if (flip)
+	{
+		pixbuf = targa_rgba + ((rows - 1) * columns * 4);
+		rowOffset = -columns * 4;
+	}
+	else
+	{
+		pixbuf = targa_rgba;
+		rowOffset = columns * 4;
+	}
+	if (mirror)
+	{
+		pixDirection = -4;
+		pixbuf += ((columns - 1) * 4);
+	}
+	else
+	{
+		pixDirection = 4;
+	}
+
+	if (targa_header.id_length)
+		fseek(fin, targa_header.id_length, SEEK_CUR);  // skip TARGA image comment
+	
+	if (targa_header.image_type == 2)
+	{													// Uncompressed, RGB images
+		for(row = 0; row < rows; row++)
+		{
+			rowBuf = pixbuf;
+			for(column = 0; column < columns; column++)
+			{
+				switch (targa_header.pixel_size)
+				{
+					case 24:
+						blue = getc(fin);
+						green = getc(fin);
+						red = getc(fin);
+						rowBuf[0] = red;
+						rowBuf[1] = green;
+						rowBuf[2] = blue;
+						rowBuf[3] = 255;
+						rowBuf += pixDirection;
+					break;
+					case 32:
+						blue = getc(fin);
+						green = getc(fin);
+						red = getc(fin);
+						alphabyte = getc(fin);
+						rowBuf[0] = red;
+						rowBuf[1] = green;
+						rowBuf[2] = blue;
+						rowBuf[3] = alphabyte;
+						rowBuf += pixDirection;
+					break;
+				}
+			}
+			pixbuf += rowOffset;
+		}
+	}
+	else if(targa_header.image_type == 10)
+	{												// Runlength encoded RGB images
+		for(row = 0; row < rows; row++)
+		{
+			rowBuf = pixbuf;
+			for(column = 0; column < columns; )
+			{
+				packetHeader = getc(fin);
+				packetSize = 1 + (packetHeader & 0x7f);
+				if (packetHeader & 0x80)
+				{									// run-length packet
+					switch (targa_header.pixel_size)
+					{
+						case 24:
+					 		blue = getc(fin);
+					 		green = getc(fin);
+					 		red = getc(fin);
+					 		alphabyte = 255;
+					 	break;
+						case 32:
+					 		blue = getc(fin);
+					 		green = getc(fin);
+					 		red = getc(fin);
+					 		alphabyte = getc(fin);
+					 	break;
+					}
+	
+					for(j = 0; j < packetSize; j++)
+					{
+						rowBuf[0] = red;
+						rowBuf[1] = green;
+						rowBuf[2] = blue;
+						rowBuf[3] = alphabyte;
+						rowBuf += pixDirection;
+						column++;
+						if(column == columns)
+						{									// run spans across rows
+							column = 0;
+							row++;
+							if (row >= rows)
+								goto breakOut;
+							pixbuf += rowOffset;
+							rowBuf = pixbuf;
+						}
+					}
+				}
+				else
+				{			                            // non run-length packet
+					for(j = 0; j < packetSize; j++)
+					{
+						switch (targa_header.pixel_size)
+						{
+							case 24:
+								blue = getc(fin);
+								green = getc(fin);
+								red = getc(fin);
+								rowBuf[0] = red;
+								rowBuf[1] = green;
+								rowBuf[2] = blue;
+								rowBuf[3] = 255;
+								rowBuf += pixDirection;
+							break;
+							case 32:
+								blue = getc(fin);
+								green = getc(fin);
+								red = getc(fin);
+								alphabyte = getc(fin);
+								rowBuf[0] = red;
+								rowBuf[1] = green;
+								rowBuf[2] = blue;
+								rowBuf[3] = alphabyte;
+								rowBuf += pixDirection;
+							break;
+						}
+						column++;
+						if (column == columns)
+						{							// pixel packet run spans across rows
+							column = 0;
+							row++;
+							if (row >= rows)
+								goto breakOut;
+							pixbuf += rowOffset;
+							rowBuf = pixbuf;
+						}						
+					}
+				}
+			}
+			breakOut:;
+			pixbuf += rowOffset;
+		}
+	}
+	fclose(fin);
+}
+
+void MergeAlpha(byte *pix, byte *alpha, byte *pal, byte **out, int width, int height)
+{
+	int		size, i;
+	byte	*data, *src, *srca;
+
+	size = width * height;
+	data = malloc(size * 4);
+	if(!data)
+		Error("Could not allocate memory for true color image");
+
+	*out = data;
+	src = pix;
+	srca = alpha;
+
+	for(i = 0; i < size; i++, src++, srca++)
+	{
+		*data++ = pal[*src * 3 + 0];	  // r
+		*data++ = pal[*src * 3 + 1];	  // g
+		*data++ = pal[*src * 3 + 2];	  // b
+		*data++ = *srca;				  // a
+	}
+	free(pix);
+	free(alpha);
+	free(pal);
+}
+
+/*
+==============
+LoadAnyImage
+
+Return Value:
+	false: paletted texture
+	true:  true color RGBA image (no palette)
+==============
+*/
+qboolean LoadAnyImage (char *name, byte **pixels, byte **palette, int *width, int *height)
+{
+	char	ext[128];
+	int		len;
+	int		alpha_width, alpha_height;
+	char	alpha_name[128];
+	byte	*alpha_pixels;
+
+	ExtractFileExtension (name, ext);
+
+	if(palette)
+	{
+		*palette = NULL;
+	}
+
+	if (!Q_strcasecmp (ext, "lbm"))
+	{
+		LoadLBM (name, pixels, palette);
+		if (width)
+			*width = bmhd.w;
+		if (height)
+			*height = bmhd.h;
+		return false;
+	}
+	else if (!Q_strcasecmp (ext, "pcx"))
+	{
+		len = strlen(name);
+		strcpy(alpha_name, name);
+		strcpy(&alpha_name[len - 4], "_a.pcx");					// Alpha map name (may not exist)
+
+		if(FileExists(alpha_name))
+		{
+			LoadPCX (name, pixels, palette, width, height);							// Load in image
+			LoadPCX (alpha_name, &alpha_pixels, NULL, &alpha_width, &alpha_height);	// Load in alpha map	
+			if((*width != alpha_width) || (*height != alpha_height))
+			{
+				Error("Alpha image dimensions not equal to graphic image dimensions");
+			}
+			MergeAlpha(*pixels, alpha_pixels, *palette, pixels, *width, *height);
+			*palette = NULL;//Merge Frees pal
+			return true;
+		}
+		else
+		{
+			LoadPCX (name, pixels, palette, width, height);			// Load in image
+			return false;
+		}
+	}
+	else if (!Q_strcasecmp (ext, "tga"))
+	{
+		LoadTGA(name, pixels, width, height);
+		if (palette)
+		{
+			*palette = NULL;
+		}
+
+		return true;
+	}
+	else
+		Error ("%s doesn't have a known image extension", name);
+
+	return false;
+}
+
diff --git a/tools/quake2/qdata_heretic2/common/lbmlib.h b/tools/quake2/qdata_heretic2/common/lbmlib.h
index ec0e8e2a..e050efa6 100644
--- a/tools/quake2/qdata_heretic2/common/lbmlib.h
+++ b/tools/quake2/qdata_heretic2/common/lbmlib.h
@@ -1,41 +1,41 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// piclib.h
-
-
-void LoadLBM (char *filename, byte **picture, byte **palette);
-void WriteLBMfile (char *filename, byte *data, int width, int height
-	, byte *palette);
-void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
-void WritePCXfile (char *filename, byte *data, int width, int height
-	, byte *palette);
-
-// loads / saves either lbm or pcx, depending on extension
-void Load256Image (char *name, byte **pixels, byte **palette,
-				   int *width, int *height);
-void Save256Image (char *name, byte *pixels, byte *palette,
-				   int width, int height);
-
-
-void LoadTGA (char *filename, byte **pixels, int *width, int *height);
-
-qboolean LoadAnyImage (char *name, byte **pixels, byte **palette, int *width, int *height);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// piclib.h
+
+
+void LoadLBM (char *filename, byte **picture, byte **palette);
+void WriteLBMfile (char *filename, byte *data, int width, int height
+	, byte *palette);
+void LoadPCX (char *filename, byte **picture, byte **palette, int *width, int *height);
+void WritePCXfile (char *filename, byte *data, int width, int height
+	, byte *palette);
+
+// loads / saves either lbm or pcx, depending on extension
+void Load256Image (char *name, byte **pixels, byte **palette,
+				   int *width, int *height);
+void Save256Image (char *name, byte *pixels, byte *palette,
+				   int width, int height);
+
+
+void LoadTGA (char *filename, byte **pixels, int *width, int *height);
+
+qboolean LoadAnyImage (char *name, byte **pixels, byte **palette, int *width, int *height);
diff --git a/tools/quake2/qdata_heretic2/common/mathlib.c b/tools/quake2/qdata_heretic2/common/mathlib.c
index 0fd9ac23..a1c0733c 100644
--- a/tools/quake2/qdata_heretic2/common/mathlib.c
+++ b/tools/quake2/qdata_heretic2/common/mathlib.c
@@ -1,176 +1,176 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// mathlib.c -- math primitives
-
-#include "cmdlib.h"
-#include "mathlib.h"
-
-vec3_t vec3_origin = {0,0,0};
-
-
-double VectorLength(vec3_t v)
-{
-	int		i;
-	double	length;
-	
-	length = 0;
-	for (i=0 ; i< 3 ; i++)
-		length += v[i]*v[i];
-	length = sqrt (length);		// FIXME
-
-	return length;
-}
-
-qboolean VectorCompare (vec3_t v1, vec3_t v2)
-{
-	int		i;
-	
-	for (i=0 ; i<3 ; i++)
-		if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
-			return false;
-			
-	return true;
-}
-
-vec_t Q_rint (vec_t in)
-{
-	return floor (in + 0.5);
-}
-
-void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc)
-{
-	vc[0] = va[0] + scale*vb[0];
-	vc[1] = va[1] + scale*vb[1];
-	vc[2] = va[2] + scale*vb[2];
-}
-
-void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
-{
-	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
-	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
-	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
-}
-
-vec_t _DotProduct (vec3_t v1, vec3_t v2)
-{
-	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
-}
-
-void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
-{
-	out[0] = va[0]-vb[0];
-	out[1] = va[1]-vb[1];
-	out[2] = va[2]-vb[2];
-}
-
-void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
-{
-	out[0] = va[0]+vb[0];
-	out[1] = va[1]+vb[1];
-	out[2] = va[2]+vb[2];
-}
-
-void _VectorCopy (vec3_t in, vec3_t out)
-{
-	out[0] = in[0];
-	out[1] = in[1];
-	out[2] = in[2];
-}
-
-void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
-{
-	out[0] = v[0] * scale;
-	out[1] = v[1] * scale;
-	out[2] = v[2] * scale;
-}
-
-#pragma optimize("g", off)	// went back to turning optimization off,
-							// the bug_fix thing stopped working
-
-vec_t VectorNormalize (vec3_t in, vec3_t out)
-{
-	vec_t	length, ilength;
-
-	length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
-	if (length == 0)
-	{
-		VectorClear (out);
-		return 0;
-	}
-
-	ilength = 1.0/length;
-	out[0] = in[0]*ilength;
-	out[1] = in[1]*ilength;
-	out[2] = in[2]*ilength;
-
-	return length;
-}
-
-vec_t ColorNormalize (vec3_t in, vec3_t out)
-{
-	float	max, scale;
-
-	max = in[0];
-	if (in[1] > max)
-		max = in[1];
-	if (in[2] > max)
-		max = in[2];
-
-	if (max == 0)
-		return 0;
-
-	scale = 1.0 / max;
-
-	VectorScale (in, scale, out);
-
-	return max;
-}
-
-#pragma optimize("", on)
-
-void VectorInverse (vec3_t v)
-{
-	v[0] = -v[0];
-	v[1] = -v[1];
-	v[2] = -v[2];
-}
-
-void ClearBounds (vec3_t mins, vec3_t maxs)
-{
-	mins[0] = mins[1] = mins[2] = 99999;
-	maxs[0] = maxs[1] = maxs[2] = -99999;
-}
-
-void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
-{
-	int		i;
-	vec_t	val;
-
-	for (i=0 ; i<3 ; i++)
-	{
-		val = v[i];
-		if (val < mins[i])
-			mins[i] = val;
-		if (val > maxs[i])
-			maxs[i] = val;
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// mathlib.c -- math primitives
+
+#include "cmdlib.h"
+#include "mathlib.h"
+
+vec3_t vec3_origin = {0,0,0};
+
+
+double VectorLength(vec3_t v)
+{
+	int		i;
+	double	length;
+	
+	length = 0;
+	for (i=0 ; i< 3 ; i++)
+		length += v[i]*v[i];
+	length = sqrt (length);		// FIXME
+
+	return length;
+}
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2)
+{
+	int		i;
+	
+	for (i=0 ; i<3 ; i++)
+		if (fabs(v1[i]-v2[i]) > EQUAL_EPSILON)
+			return false;
+			
+	return true;
+}
+
+vec_t Q_rint (vec_t in)
+{
+	return floor (in + 0.5);
+}
+
+void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc)
+{
+	vc[0] = va[0] + scale*vb[0];
+	vc[1] = va[1] + scale*vb[1];
+	vc[2] = va[2] + scale*vb[2];
+}
+
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross)
+{
+	cross[0] = v1[1]*v2[2] - v1[2]*v2[1];
+	cross[1] = v1[2]*v2[0] - v1[0]*v2[2];
+	cross[2] = v1[0]*v2[1] - v1[1]*v2[0];
+}
+
+vec_t _DotProduct (vec3_t v1, vec3_t v2)
+{
+	return v1[0]*v2[0] + v1[1]*v2[1] + v1[2]*v2[2];
+}
+
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out)
+{
+	out[0] = va[0]-vb[0];
+	out[1] = va[1]-vb[1];
+	out[2] = va[2]-vb[2];
+}
+
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out)
+{
+	out[0] = va[0]+vb[0];
+	out[1] = va[1]+vb[1];
+	out[2] = va[2]+vb[2];
+}
+
+void _VectorCopy (vec3_t in, vec3_t out)
+{
+	out[0] = in[0];
+	out[1] = in[1];
+	out[2] = in[2];
+}
+
+void _VectorScale (vec3_t v, vec_t scale, vec3_t out)
+{
+	out[0] = v[0] * scale;
+	out[1] = v[1] * scale;
+	out[2] = v[2] * scale;
+}
+
+#pragma optimize("g", off)	// went back to turning optimization off,
+							// the bug_fix thing stopped working
+
+vec_t VectorNormalize (vec3_t in, vec3_t out)
+{
+	vec_t	length, ilength;
+
+	length = sqrt (in[0]*in[0] + in[1]*in[1] + in[2]*in[2]);
+	if (length == 0)
+	{
+		VectorClear (out);
+		return 0;
+	}
+
+	ilength = 1.0/length;
+	out[0] = in[0]*ilength;
+	out[1] = in[1]*ilength;
+	out[2] = in[2]*ilength;
+
+	return length;
+}
+
+vec_t ColorNormalize (vec3_t in, vec3_t out)
+{
+	float	max, scale;
+
+	max = in[0];
+	if (in[1] > max)
+		max = in[1];
+	if (in[2] > max)
+		max = in[2];
+
+	if (max == 0)
+		return 0;
+
+	scale = 1.0 / max;
+
+	VectorScale (in, scale, out);
+
+	return max;
+}
+
+#pragma optimize("", on)
+
+void VectorInverse (vec3_t v)
+{
+	v[0] = -v[0];
+	v[1] = -v[1];
+	v[2] = -v[2];
+}
+
+void ClearBounds (vec3_t mins, vec3_t maxs)
+{
+	mins[0] = mins[1] = mins[2] = 99999;
+	maxs[0] = maxs[1] = maxs[2] = -99999;
+}
+
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs)
+{
+	int		i;
+	vec_t	val;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		val = v[i];
+		if (val < mins[i])
+			mins[i] = val;
+		if (val > maxs[i])
+			maxs[i] = val;
+	}
+}
diff --git a/tools/quake2/qdata_heretic2/common/mathlib.h b/tools/quake2/qdata_heretic2/common/mathlib.h
index b4cbf05f..03e5325b 100644
--- a/tools/quake2/qdata_heretic2/common/mathlib.h
+++ b/tools/quake2/qdata_heretic2/common/mathlib.h
@@ -1,76 +1,76 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __MATHLIB__
-#define __MATHLIB__
-
-// mathlib.h
-
-#include <math.h>
-/*
-#ifdef DOUBLEVEC_T
-typedef double vec_t;
-#else
-typedef float vec_t;
-#endif
-typedef vec_t vec3_t[3];
-*/
-#define	SIDE_FRONT		0
-#define	SIDE_ON			2
-#define	SIDE_BACK		1
-#define	SIDE_CROSS		-2
-
-#define	Q_PI	3.14159265358979323846
-
-extern vec3_t vec3_origin;
-
-#define	EQUAL_EPSILON	0.001
-
-qboolean VectorCompare (vec3_t v1, vec3_t v2);
-
-#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
-#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
-#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
-#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
-#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
-#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
-#define	VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
-
-vec_t Q_rint (vec_t in);
-vec_t _DotProduct (vec3_t v1, vec3_t v2);
-void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
-void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
-void _VectorCopy (vec3_t in, vec3_t out);
-void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
-
-double VectorLength(vec3_t v);
-
-void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc);
-
-void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
-vec_t VectorNormalize (vec3_t in, vec3_t out);
-vec_t ColorNormalize (vec3_t in, vec3_t out);
-void VectorInverse (vec3_t v);
-
-void ClearBounds (vec3_t mins, vec3_t maxs);
-void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __MATHLIB__
+#define __MATHLIB__
+
+// mathlib.h
+
+#include <math.h>
+/*
+#ifdef DOUBLEVEC_T
+typedef double vec_t;
+#else
+typedef float vec_t;
+#endif
+typedef vec_t vec3_t[3];
+*/
+#define	SIDE_FRONT		0
+#define	SIDE_ON			2
+#define	SIDE_BACK		1
+#define	SIDE_CROSS		-2
+
+#define	Q_PI	3.14159265358979323846
+
+extern vec3_t vec3_origin;
+
+#define	EQUAL_EPSILON	0.001
+
+qboolean VectorCompare (vec3_t v1, vec3_t v2);
+
+#define DotProduct(x,y) (x[0]*y[0]+x[1]*y[1]+x[2]*y[2])
+#define VectorSubtract(a,b,c) {c[0]=a[0]-b[0];c[1]=a[1]-b[1];c[2]=a[2]-b[2];}
+#define VectorAdd(a,b,c) {c[0]=a[0]+b[0];c[1]=a[1]+b[1];c[2]=a[2]+b[2];}
+#define VectorCopy(a,b) {b[0]=a[0];b[1]=a[1];b[2]=a[2];}
+#define VectorScale(a,b,c) {c[0]=b*a[0];c[1]=b*a[1];c[2]=b*a[2];}
+#define VectorClear(x) {x[0] = x[1] = x[2] = 0;}
+#define	VectorNegate(x) {x[0]=-x[0];x[1]=-x[1];x[2]=-x[2];}
+
+vec_t Q_rint (vec_t in);
+vec_t _DotProduct (vec3_t v1, vec3_t v2);
+void _VectorSubtract (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorAdd (vec3_t va, vec3_t vb, vec3_t out);
+void _VectorCopy (vec3_t in, vec3_t out);
+void _VectorScale (vec3_t v, vec_t scale, vec3_t out);
+
+double VectorLength(vec3_t v);
+
+void VectorMA (vec3_t va, double scale, vec3_t vb, vec3_t vc);
+
+void CrossProduct (vec3_t v1, vec3_t v2, vec3_t cross);
+vec_t VectorNormalize (vec3_t in, vec3_t out);
+vec_t ColorNormalize (vec3_t in, vec3_t out);
+void VectorInverse (vec3_t v);
+
+void ClearBounds (vec3_t mins, vec3_t maxs);
+void AddPointToBounds (vec3_t v, vec3_t mins, vec3_t maxs);
+
+#endif
diff --git a/tools/quake2/qdata_heretic2/common/path_init.c b/tools/quake2/qdata_heretic2/common/path_init.c
index 0a630a10..644908ea 100644
--- a/tools/quake2/qdata_heretic2/common/path_init.c
+++ b/tools/quake2/qdata_heretic2/common/path_init.c
@@ -1,404 +1,404 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*
-Nurail: Swiped from Q3Map2
-*/
-
-
-
-/* marker */
-#define PATH_INIT_C
-
-#if defined( __linux__ ) || defined( __APPLE__ )
-	#define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
-	#include <unistd.h>
-	#include <pwd.h>
-	#include <limits.h>
-#endif
-
-
-/* dependencies */
-#include "cmdlib.h"
-#include "inout.h"
-
-
-
-/* path support */
-#define MAX_BASE_PATHS	10
-#define MAX_GAME_PATHS	10
-
-char					*homePath;
-char					installPath[ MAX_OS_PATH ];
-
-int						numBasePaths;
-char					*basePaths[ MAX_BASE_PATHS ];
-int						numGamePaths;
-char					*gamePaths[ MAX_GAME_PATHS ];
-
-/*
-some of this code is based off the original q3map port from loki
-and finds various paths. moved here from bsp.c for clarity.
-*/
-
-/*
-PathLokiGetHomeDir()
-gets the user's home dir (for ~/.q3a)
-*/
-
-char *LokiGetHomeDir( void )
-{
-	#ifndef Q_UNIX
-		return NULL;
-	#else
-		char			*home;
-		uid_t			id;
-		struct passwd	*pwd;
-		
-		
-		/* get the home environment variable */
-		home = getenv( "HOME" );
-		if( home == NULL )
-		{
-			/* do some more digging */
-			id = getuid();
-			setpwent();
-			while( (pwd = getpwent()) != NULL )
-			{
-				if( pwd->pw_uid == id )
-				{
-					home = pwd->pw_dir;
-					break;
-				}
-			}
-			endpwent();
-		}
-		
-		/* return it */
-		return home;
-	#endif
-}
-
-
-
-/*
-PathLokiInitPaths()
-initializes some paths on linux/os x
-*/
-
-void LokiInitPaths( char *argv0 )
-{
-	#ifndef Q_UNIX
-		/* this is kinda crap, but hey */
-		strcpy( installPath, "../" );
-	#else
-		char		temp[ MAX_OS_PATH ];
-		char		*home;
-		char		*path;
-		char		*last;
-		qboolean	found;
-		
-		
-		/* get home dir */
-		home = LokiGetHomeDir();
-		if( home == NULL )
-			home = ".";
-		
-		/* do some path divining */
-		strcpy( temp, argv0 );
-		if( strrchr( temp, '/' ) )
-			argv0 = strrchr( argv0, '/' ) + 1;
-		else
-		{
-			/* get path environment variable */
-			path = getenv( "PATH" );
-			
-			/* minor setup */
-			last[ 0 ] = path[ 0 ];
-			last[ 1 ] = '\0';
-			found = false;
-			
-			/* go through each : segment of path */
-			while( last[ 0 ] != '\0' && found == false )
-			{
-				/* null out temp */
-				temp[ 0 ] = '\0';
-				
-				/* find next chunk */
-				last = strchr( path, ':' );
-				if( last == NULL )
-					last = path + strlen( path );
-				
-				/* found home dir candidate */
-				if( *path == '~' )
-				{
-					strcpy( temp, home );
-					path++;
-				}
-				
-				/* concatenate */
-				if( last > (path + 1) )
-				{
-					strncat( temp, path, (last - path) );
-					strcat( temp, "/" );
-				}
-				strcat( temp, "./" );
-				strcat( temp, argv0 );
-				
-				/* verify the path */
-				if( access( temp, X_OK ) == 0 )
-					found++;
-				path = last + 1;
-			}
-		}
-		
-		/* flake */
-		if( realpath( temp, installPath ) )
-		{
-			/* q3map is in "tools/" */
-			*(strrchr( installPath, '/' )) = '\0';
-			*(strrchr( installPath, '/' ) + 1) = '\0';
-		}
-		
-		/* set home path */
-		homePath = home;
-	#endif
-}
-
-
-
-/*
-CleanPath() - ydnar
-cleans a dos path \ -> /
-*/
-
-void CleanPath( char *path )
-{
-	while( *path )
-	{
-		if( *path == '\\' )
-			*path = '/';
-		path++;
-	}
-}
-
-/*
-AddBasePath() - ydnar
-adds a base path to the list
-*/
-
-void AddBasePath( char *path )
-{
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
-		return;
-	
-	/* add it to the list */
-	basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
-	strcpy( basePaths[ numBasePaths ], path );
-	CleanPath( basePaths[ numBasePaths ] );
-	numBasePaths++;
-}
-
-
-
-/*
-AddHomeBasePath() - ydnar
-adds a base path to the beginning of the list, prefixed by ~/
-*/
-
-void AddHomeBasePath( char *path )
-{
-	#ifdef Q_UNIX
-		int		i;
-		char	temp[ MAX_OS_PATH ];
-
-
-		/* dummy check */
-		if( path == NULL || path[ 0 ] == '\0' )
-			return;
-
-		/* make a hole */
-		for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
-			basePaths[ i + 1 ] = basePaths[ i ];
-		
-		/* concatenate home dir and path */
-		sprintf( temp, "%s/%s", homePath, path );
-		
-		/* add it to the list */
-		basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
-		strcpy( basePaths[ 0 ], temp );
-		CleanPath( basePaths[ 0 ] );
-		numBasePaths++;
-	#endif
-}
-
-
-
-/*
-AddGamePath() - ydnar
-adds a game path to the list
-*/
-
-void AddGamePath( char *path )
-{
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
-		return;
-	
-	/* add it to the list */
-	gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
-	strcpy( gamePaths[ numGamePaths ], path );
-	CleanPath( gamePaths[ numGamePaths ] );
-	numGamePaths++;
-}
-
-
-
-
-/*
-InitPaths() - ydnar
-cleaned up some of the path initialization code from bsp.c
-will remove any arguments it uses
-*/
-
-void InitPaths( int *argc, char **argv )
-{
-	int		i, j, k, len, len2;
-	char	temp[ MAX_OS_PATH ];
-  char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
-
-  strcpy(gamePath, "base");
-  strcpy(game_magic, "h");
-  strcpy(homeBasePath, ".heretic2");
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
-	
-	/* get the install path for backup */
-	LokiInitPaths( argv[ 0 ] );
-
-	/* set game to default (q3a) */
-	numBasePaths = 0;
-	numGamePaths = 0;
-
-	/* parse through the arguments and extract those relevant to paths */
-	for( i = 0; i < *argc; i++ )
-	{
-		/* check for null */
-		if( argv[ i ] == NULL )
-			continue;
-
-		/* -fs_basepath */
-		if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
-		{
-			if( ++i >= *argc )
-				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
-			argv[ i - 1 ] = NULL;
-			AddBasePath( argv[ i ] );
-			argv[ i ] = NULL;
-		}
-
-	}
-
-	/* remove processed arguments */
-	for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
-	{
-		for( j; j < *argc && argv[ j ] == NULL; j++ );
-		argv[ i ] = argv[ j ];
-		if( argv[ i ] != NULL )
-			k++;
-	}
-	*argc = k;
-
-	/* add standard game path */
-  AddGamePath( gamePath );
-
-	/* if there is no base path set, figure it out */
-	if( numBasePaths == 0 )
-	{
-		/* this is another crappy replacement for SetQdirFromPath() */
-    len2 = strlen( game_magic );
-		for( i = 0; i < *argc && numBasePaths == 0; i++ )
-		{
-			/* extract the arg */
-			strcpy( temp, argv[ i ] );
-			CleanPath( temp );
-			len = strlen( temp );
-			Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
-
-			/* this is slow, but only done once */
-			for( j = 0; j < (len - len2); j++ )
-			{
-				/* check for the game's magic word */
-				if( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 )
-				{
-					/* now find the next slash and nuke everything after it */
-					while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
-					temp[ j ] = '\0';
-
-					/* add this as a base path */
-					AddBasePath( temp );
-					break;
-				}
-			}
-		}
-
-		/* add install path */
-		if( numBasePaths == 0 )
-			AddBasePath( installPath );
-
-		/* check again */
-		if( numBasePaths == 0 )
-			Error( "Failed to find a valid base path." );
-	}
-
-	/* this only affects unix */
-	AddHomeBasePath( homeBasePath );
-
-	/* initialize vfs paths */
-	if( numBasePaths > MAX_BASE_PATHS )
-		numBasePaths = MAX_BASE_PATHS;
-	if( numGamePaths > MAX_GAME_PATHS )
-		numGamePaths = MAX_GAME_PATHS;
-	
-	/* walk the list of game paths */
-	//for( j = 0; j < numGamePaths; j++ )
-	//{
-		/* walk the list of base paths */
-	//	for( i = 0; i < numBasePaths; i++ )
-	//	{
-			/* create a full path and initialize it */
-	//		sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
-	//		vfsInitDirectory( temp );
-	//	}
-	//}
-	
-	/* done */
-	Sys_Printf( "\n" );
-}
-
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*
+Nurail: Swiped from Q3Map2
+*/
+
+
+
+/* marker */
+#define PATH_INIT_C
+
+#if defined( __linux__ ) || defined( __APPLE__ )
+	#define Q_UNIX
+#endif
+
+#ifdef Q_UNIX
+	#include <unistd.h>
+	#include <pwd.h>
+	#include <limits.h>
+#endif
+
+
+/* dependencies */
+#include "cmdlib.h"
+#include "inout.h"
+
+
+
+/* path support */
+#define MAX_BASE_PATHS	10
+#define MAX_GAME_PATHS	10
+
+char					*homePath;
+char					installPath[ MAX_OS_PATH ];
+
+int						numBasePaths;
+char					*basePaths[ MAX_BASE_PATHS ];
+int						numGamePaths;
+char					*gamePaths[ MAX_GAME_PATHS ];
+
+/*
+some of this code is based off the original q3map port from loki
+and finds various paths. moved here from bsp.c for clarity.
+*/
+
+/*
+PathLokiGetHomeDir()
+gets the user's home dir (for ~/.q3a)
+*/
+
+char *LokiGetHomeDir( void )
+{
+	#ifndef Q_UNIX
+		return NULL;
+	#else
+		char			*home;
+		uid_t			id;
+		struct passwd	*pwd;
+		
+		
+		/* get the home environment variable */
+		home = getenv( "HOME" );
+		if( home == NULL )
+		{
+			/* do some more digging */
+			id = getuid();
+			setpwent();
+			while( (pwd = getpwent()) != NULL )
+			{
+				if( pwd->pw_uid == id )
+				{
+					home = pwd->pw_dir;
+					break;
+				}
+			}
+			endpwent();
+		}
+		
+		/* return it */
+		return home;
+	#endif
+}
+
+
+
+/*
+PathLokiInitPaths()
+initializes some paths on linux/os x
+*/
+
+void LokiInitPaths( char *argv0 )
+{
+	#ifndef Q_UNIX
+		/* this is kinda crap, but hey */
+		strcpy( installPath, "../" );
+	#else
+		char		temp[ MAX_OS_PATH ];
+		char		*home;
+		char		*path;
+		char		*last;
+		qboolean	found;
+		
+		
+		/* get home dir */
+		home = LokiGetHomeDir();
+		if( home == NULL )
+			home = ".";
+		
+		/* do some path divining */
+		strcpy( temp, argv0 );
+		if( strrchr( temp, '/' ) )
+			argv0 = strrchr( argv0, '/' ) + 1;
+		else
+		{
+			/* get path environment variable */
+			path = getenv( "PATH" );
+			
+			/* minor setup */
+			last[ 0 ] = path[ 0 ];
+			last[ 1 ] = '\0';
+			found = false;
+			
+			/* go through each : segment of path */
+			while( last[ 0 ] != '\0' && found == false )
+			{
+				/* null out temp */
+				temp[ 0 ] = '\0';
+				
+				/* find next chunk */
+				last = strchr( path, ':' );
+				if( last == NULL )
+					last = path + strlen( path );
+				
+				/* found home dir candidate */
+				if( *path == '~' )
+				{
+					strcpy( temp, home );
+					path++;
+				}
+				
+				/* concatenate */
+				if( last > (path + 1) )
+				{
+					strncat( temp, path, (last - path) );
+					strcat( temp, "/" );
+				}
+				strcat( temp, "./" );
+				strcat( temp, argv0 );
+				
+				/* verify the path */
+				if( access( temp, X_OK ) == 0 )
+					found++;
+				path = last + 1;
+			}
+		}
+		
+		/* flake */
+		if( realpath( temp, installPath ) )
+		{
+			/* q3map is in "tools/" */
+			*(strrchr( installPath, '/' )) = '\0';
+			*(strrchr( installPath, '/' ) + 1) = '\0';
+		}
+		
+		/* set home path */
+		homePath = home;
+	#endif
+}
+
+
+
+/*
+CleanPath() - ydnar
+cleans a dos path \ -> /
+*/
+
+void CleanPath( char *path )
+{
+	while( *path )
+	{
+		if( *path == '\\' )
+			*path = '/';
+		path++;
+	}
+}
+
+/*
+AddBasePath() - ydnar
+adds a base path to the list
+*/
+
+void AddBasePath( char *path )
+{
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
+		return;
+	
+	/* add it to the list */
+	basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
+	strcpy( basePaths[ numBasePaths ], path );
+	CleanPath( basePaths[ numBasePaths ] );
+	numBasePaths++;
+}
+
+
+
+/*
+AddHomeBasePath() - ydnar
+adds a base path to the beginning of the list, prefixed by ~/
+*/
+
+void AddHomeBasePath( char *path )
+{
+	#ifdef Q_UNIX
+		int		i;
+		char	temp[ MAX_OS_PATH ];
+
+
+		/* dummy check */
+		if( path == NULL || path[ 0 ] == '\0' )
+			return;
+
+		/* make a hole */
+		for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
+			basePaths[ i + 1 ] = basePaths[ i ];
+		
+		/* concatenate home dir and path */
+		sprintf( temp, "%s/%s", homePath, path );
+		
+		/* add it to the list */
+		basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
+		strcpy( basePaths[ 0 ], temp );
+		CleanPath( basePaths[ 0 ] );
+		numBasePaths++;
+	#endif
+}
+
+
+
+/*
+AddGamePath() - ydnar
+adds a game path to the list
+*/
+
+void AddGamePath( char *path )
+{
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
+		return;
+	
+	/* add it to the list */
+	gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
+	strcpy( gamePaths[ numGamePaths ], path );
+	CleanPath( gamePaths[ numGamePaths ] );
+	numGamePaths++;
+}
+
+
+
+
+/*
+InitPaths() - ydnar
+cleaned up some of the path initialization code from bsp.c
+will remove any arguments it uses
+*/
+
+void InitPaths( int *argc, char **argv )
+{
+	int		i, j, k, len, len2;
+	char	temp[ MAX_OS_PATH ];
+  char gamePath[MAX_OS_PATH], homeBasePath[MAX_OS_PATH], game_magic[10];
+
+  strcpy(gamePath, "base");
+  strcpy(game_magic, "h");
+  strcpy(homeBasePath, ".heretic2");
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
+	
+	/* get the install path for backup */
+	LokiInitPaths( argv[ 0 ] );
+
+	/* set game to default (q3a) */
+	numBasePaths = 0;
+	numGamePaths = 0;
+
+	/* parse through the arguments and extract those relevant to paths */
+	for( i = 0; i < *argc; i++ )
+	{
+		/* check for null */
+		if( argv[ i ] == NULL )
+			continue;
+
+		/* -fs_basepath */
+		if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
+		{
+			if( ++i >= *argc )
+				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+			argv[ i - 1 ] = NULL;
+			AddBasePath( argv[ i ] );
+			argv[ i ] = NULL;
+		}
+
+	}
+
+	/* remove processed arguments */
+	for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
+	{
+		for( j; j < *argc && argv[ j ] == NULL; j++ );
+		argv[ i ] = argv[ j ];
+		if( argv[ i ] != NULL )
+			k++;
+	}
+	*argc = k;
+
+	/* add standard game path */
+  AddGamePath( gamePath );
+
+	/* if there is no base path set, figure it out */
+	if( numBasePaths == 0 )
+	{
+		/* this is another crappy replacement for SetQdirFromPath() */
+    len2 = strlen( game_magic );
+		for( i = 0; i < *argc && numBasePaths == 0; i++ )
+		{
+			/* extract the arg */
+			strcpy( temp, argv[ i ] );
+			CleanPath( temp );
+			len = strlen( temp );
+			Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game_magic, temp, i );
+
+			/* this is slow, but only done once */
+			for( j = 0; j < (len - len2); j++ )
+			{
+				/* check for the game's magic word */
+				if( Q_strncasecmp( &temp[ j ], game_magic, len2 ) == 0 )
+				{
+					/* now find the next slash and nuke everything after it */
+					while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
+					temp[ j ] = '\0';
+
+					/* add this as a base path */
+					AddBasePath( temp );
+					break;
+				}
+			}
+		}
+
+		/* add install path */
+		if( numBasePaths == 0 )
+			AddBasePath( installPath );
+
+		/* check again */
+		if( numBasePaths == 0 )
+			Error( "Failed to find a valid base path." );
+	}
+
+	/* this only affects unix */
+	AddHomeBasePath( homeBasePath );
+
+	/* initialize vfs paths */
+	if( numBasePaths > MAX_BASE_PATHS )
+		numBasePaths = MAX_BASE_PATHS;
+	if( numGamePaths > MAX_GAME_PATHS )
+		numGamePaths = MAX_GAME_PATHS;
+	
+	/* walk the list of game paths */
+	//for( j = 0; j < numGamePaths; j++ )
+	//{
+		/* walk the list of base paths */
+	//	for( i = 0; i < numBasePaths; i++ )
+	//	{
+			/* create a full path and initialize it */
+	//		sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
+	//		vfsInitDirectory( temp );
+	//	}
+	//}
+	
+	/* done */
+	Sys_Printf( "\n" );
+}
+
+
+
+
diff --git a/tools/quake2/qdata_heretic2/common/polylib.c b/tools/quake2/qdata_heretic2/common/polylib.c
index 34dfc2ef..b4b69ac1 100644
--- a/tools/quake2/qdata_heretic2/common/polylib.c
+++ b/tools/quake2/qdata_heretic2/common/polylib.c
@@ -1,656 +1,656 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "polylib.h"
-
-
-extern int numthreads;
-
-// counters are only bumped when running single threaded,
-// because they are an awefull coherence problem
-int	c_active_windings;
-int	c_peak_windings;
-int	c_winding_allocs;
-int	c_winding_points;
-
-#define	BOGUS_RANGE	8192
-
-void pw(winding_t *w)
-{
-	int		i;
-	for (i=0 ; i<w->numpoints ; i++)
-		printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
-}
-
-
-/*
-=============
-AllocWinding
-=============
-*/
-winding_t	*AllocWinding (int points)
-{
-	winding_t	*w;
-	int			s;
-
-	if (numthreads == 1)
-	{
-		c_winding_allocs++;
-		c_winding_points += points;
-		c_active_windings++;
-		if (c_active_windings > c_peak_windings)
-			c_peak_windings = c_active_windings;
-	}
-	s = sizeof(vec_t)*3*points + sizeof(int);
-	w = malloc (s);
-	if (!w)
-		Error("AllocWinding MALLOC failed!  Could not allocate %s bytes.", s);
-	memset (w, 0, s); 
-	return w;
-}
-
-void FreeWinding (winding_t *w)
-{
-	if (*(unsigned *)w == 0xdeaddead)
-		Error ("FreeWinding: freed a freed winding");
-	*(unsigned *)w = 0xdeaddead;
-
-	if (numthreads == 1)
-		c_active_windings--;
-	free (w);
-}
-
-/*
-============
-RemoveColinearPoints
-============
-*/
-int	c_removed;
-
-void	RemoveColinearPoints (winding_t *w)
-{
-	int		i, j, k;
-	vec3_t	v1, v2;
-	int		nump;
-	vec3_t	p[MAX_POINTS_ON_WINDING];
-
-	nump = 0;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		j = (i+1)%w->numpoints;
-		k = (i+w->numpoints-1)%w->numpoints;
-		VectorSubtract (w->p[j], w->p[i], v1);
-		VectorSubtract (w->p[i], w->p[k], v2);
-		VectorNormalize(v1,v1);
-		VectorNormalize(v2,v2);
-		if (DotProduct(v1, v2) < 0.999)
-		{
-			VectorCopy (w->p[i], p[nump]);
-			nump++;
-		}
-	}
-
-	if (nump == w->numpoints)
-		return;
-
-	if (numthreads == 1)
-		c_removed += w->numpoints - nump;
-	w->numpoints = nump;
-	memcpy (w->p, p, nump*sizeof(p[0]));
-}
-
-/*
-============
-WindingPlane
-============
-*/
-void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
-{
-	vec3_t	v1, v2;
-
-	VectorSubtract (w->p[1], w->p[0], v1);
-	VectorSubtract (w->p[2], w->p[0], v2);
-	CrossProduct (v2, v1, normal);
-	VectorNormalize (normal, normal);
-	*dist = DotProduct (w->p[0], normal);
-
-}
-
-/*
-=============
-WindingArea
-=============
-*/
-vec_t	WindingArea (winding_t *w)
-{
-	int		i;
-	vec3_t	d1, d2, cross;
-	vec_t	total;
-
-	total = 0;
-	for (i=2 ; i<w->numpoints ; i++)
-	{
-		VectorSubtract (w->p[i-1], w->p[0], d1);
-		VectorSubtract (w->p[i], w->p[0], d2);
-		CrossProduct (d1, d2, cross);
-		total += 0.5 * VectorLength ( cross );
-	}
-	return total;
-}
-
-void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
-{
-	vec_t	v;
-	int		i,j;
-
-	mins[0] = mins[1] = mins[2] = 99999;
-	maxs[0] = maxs[1] = maxs[2] = -99999;
-
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			v = w->p[i][j];
-			if (v < mins[j])
-				mins[j] = v;
-			if (v > maxs[j])
-				maxs[j] = v;
-		}
-	}
-}
-
-/*
-=============
-WindingCenter
-=============
-*/
-void	WindingCenter (winding_t *w, vec3_t center)
-{
-	int		i;
-	float	scale;
-
-	VectorCopy (vec3_origin, center);
-	for (i=0 ; i<w->numpoints ; i++)
-		VectorAdd (w->p[i], center, center);
-
-	scale = 1.0/w->numpoints;
-	VectorScale (center, scale, center);
-}
-
-/*
-=================
-BaseWindingForPlane
-=================
-*/
-winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
-{
-	int		i, x;
-	vec_t	max, v;
-	vec3_t	org, vright, vup;
-	winding_t	*w;
-	
-// find the major axis
-
-	max = -BOGUS_RANGE;
-	x = -1;
-	for (i=0 ; i<3; i++)
-	{
-		v = fabs(normal[i]);
-		if (v > max)
-		{
-			x = i;
-			max = v;
-		}
-	}
-	if (x==-1)
-		Error ("BaseWindingForPlane: no axis found");
-		
-	VectorCopy (vec3_origin, vup);	
-	switch (x)
-	{
-	case 0:
-	case 1:
-		vup[2] = 1;
-		break;		
-	case 2:
-		vup[0] = 1;
-		break;		
-	}
-
-	v = DotProduct (vup, normal);
-	VectorMA (vup, -v, normal, vup);
-	VectorNormalize (vup, vup);
-		
-	VectorScale (normal, dist, org);
-	
-	CrossProduct (vup, normal, vright);
-	
-	VectorScale (vup, 8192, vup);
-	VectorScale (vright, 8192, vright);
-
-// project a really big	axis aligned box onto the plane
-	w = AllocWinding (4);
-	
-	VectorSubtract (org, vright, w->p[0]);
-	VectorAdd (w->p[0], vup, w->p[0]);
-	
-	VectorAdd (org, vright, w->p[1]);
-	VectorAdd (w->p[1], vup, w->p[1]);
-	
-	VectorAdd (org, vright, w->p[2]);
-	VectorSubtract (w->p[2], vup, w->p[2]);
-	
-	VectorSubtract (org, vright, w->p[3]);
-	VectorSubtract (w->p[3], vup, w->p[3]);
-	
-	w->numpoints = 4;
-	
-	return w;	
-}
-
-/*
-==================
-CopyWinding
-==================
-*/
-winding_t	*CopyWinding (winding_t *w)
-{
-	int			size;
-	winding_t	*c;
-
-	c = AllocWinding (w->numpoints);
-	size = (int)((winding_t *)0)->p[w->numpoints];
-	memcpy (c, w, size);
-	return c;
-}
-
-/*
-==================
-ReverseWinding
-==================
-*/
-winding_t	*ReverseWinding (winding_t *w)
-{
-	int			i;
-	winding_t	*c;
-
-	c = AllocWinding (w->numpoints);
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
-	}
-	c->numpoints = w->numpoints;
-	return c;
-}
-
-
-/*
-=============
-ClipWindingEpsilon
-=============
-*/
-void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
-				vec_t epsilon, winding_t **front, winding_t **back)
-{
-	vec_t	dists[MAX_POINTS_ON_WINDING+4];
-	int		sides[MAX_POINTS_ON_WINDING+4];
-	int		counts[3];
-	vec_t	dot;		// VC 4.2 optimizer bug if not static
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	winding_t	*f, *b;
-	int		maxpts;
-	
-	if (in->numpoints >= MAX_POINTS_ON_WINDING-4)
-		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
-
-	counts[0] = counts[1] = counts[2] = 0;
-
-// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->p[i], normal);
-		dot -= dist;
-		dists[i] = dot;
-		if (dot > epsilon)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -epsilon)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	*front = *back = NULL;
-
-	if (!counts[0])
-	{
-		*back = CopyWinding (in);
-		return;
-	}
-	if (!counts[1])
-	{
-		*front = CopyWinding (in);
-		return;
-	}
-
-	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
-								// of fp grouping errors
-
-	*front = f = AllocWinding (maxpts);
-	*back = b = AllocWinding (maxpts);
-		
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->p[i];
-		
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-			VectorCopy (p1, b->p[b->numpoints]);
-			b->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-		}
-		if (sides[i] == SIDE_BACK)
-		{
-			VectorCopy (p1, b->p[b->numpoints]);
-			b->numpoints++;
-		}
-
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-	// generate a split point
-		p2 = in->p[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (normal[j] == 1)
-				mid[j] = dist;
-			else if (normal[j] == -1)
-				mid[j] = -dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, f->p[f->numpoints]);
-		f->numpoints++;
-		VectorCopy (mid, b->p[b->numpoints]);
-		b->numpoints++;
-	}
-	
-	if (f->numpoints > maxpts || b->numpoints > maxpts)
-		Error ("ClipWinding: points exceeded estimate");
-	if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
-		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
-}
-
-
-/*
-=============
-ChopWindingInPlace
-=============
-*/
-void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
-{
-	winding_t	*in;
-	vec_t	dists[MAX_POINTS_ON_WINDING+4];
-	int		sides[MAX_POINTS_ON_WINDING+4];
-	int		counts[3];
-	vec_t	dot;		// VC 4.2 optimizer bug if not static
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	winding_t	*f;
-	int		maxpts;
-
-	in = *inout;
-	counts[0] = counts[1] = counts[2] = 0;
-
-	if (!in)
-	{
-		printf ("Warning: NULL passed to ChopWindingInPlace\n");
-		return;
-	}
-	if (in->numpoints >= MAX_POINTS_ON_WINDING-4)
-		Error ("ChopWinding: MAX_POINTS_ON_WINDING");
-
-// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->p[i], normal);
-		dot -= dist;
-		dists[i] = dot;
-		if (dot > epsilon)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -epsilon)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	if (!counts[0])
-	{
-		FreeWinding (in);
-		*inout = NULL;
-		return;
-	}
-	if (!counts[1])
-		return;		// inout stays the same
-
-	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
-								// of fp grouping errors
-
-	f = AllocWinding (maxpts);
-		
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->p[i];
-		
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-		}
-
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-	// generate a split point
-		p2 = in->p[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (normal[j] == 1)
-				mid[j] = dist;
-			else if (normal[j] == -1)
-				mid[j] = -dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, f->p[f->numpoints]);
-		f->numpoints++;
-	}
-	
-	if (f->numpoints > maxpts)
-		Error ("ClipWinding: points exceeded estimate");
-	if (f->numpoints > MAX_POINTS_ON_WINDING)
-		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
-
-	FreeWinding (in);
-	*inout = f;
-}
-
-
-/*
-=================
-ChopWinding
-
-Returns the fragment of in that is on the front side
-of the cliping plane.  The original is freed.
-=================
-*/
-winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
-{
-	winding_t	*f, *b;
-
-	ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
-	FreeWinding (in);
-	if (b)
-		FreeWinding (b);
-	return f;
-}
-
-
-/*
-=================
-CheckWinding
-
-=================
-*/
-void CheckWinding (winding_t *w)
-{
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec_t	d, edgedist;
-	vec3_t	dir, edgenormal, facenormal;
-	vec_t	area;
-	vec_t	facedist;
-
-	if (w->numpoints < 3)
-		Error ("CheckWinding: %i points",w->numpoints);
-	
-	area = WindingArea(w);
-	if (area < 1)
-		Error ("CheckWinding: %f area", area);
-
-	WindingPlane (w, facenormal, &facedist);
-	
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		p1 = w->p[i];
-
-		for (j=0 ; j<3 ; j++)
-			if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
-				Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
-
-		j = i+1 == w->numpoints ? 0 : i+1;
-		
-	// check the point is on the face plane
-		d = DotProduct (p1, facenormal) - facedist;
-		if (d < -ON_EPSILON || d > ON_EPSILON)
-			Error ("CheckWinding: point off plane");
-	
-	// check the edge isnt degenerate
-		p2 = w->p[j];
-		VectorSubtract (p2, p1, dir);
-		
-		if (VectorLength (dir) < ON_EPSILON)
-			Error ("CheckWinding: degenerate edge");
-			
-		CrossProduct (facenormal, dir, edgenormal);
-		VectorNormalize (edgenormal, edgenormal);
-		edgedist = DotProduct (p1, edgenormal);
-		edgedist += ON_EPSILON;
-		
-	// all other points must be on front side
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			if (j == i)
-				continue;
-			d = DotProduct (w->p[j], edgenormal);
-			if (d > edgedist)
-				Error ("CheckWinding: non-convex");
-		}
-	}
-}
-
-
-/*
-============
-WindingOnPlaneSide
-============
-*/
-int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
-{
-	qboolean	front, back;
-	int			i;
-	vec_t		d;
-
-	front = false;
-	back = false;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		d = DotProduct (w->p[i], normal) - dist;
-		if (d < -ON_EPSILON)
-		{
-			if (front)
-				return SIDE_CROSS;
-			back = true;
-			continue;
-		}
-		if (d > ON_EPSILON)
-		{
-			if (back)
-				return SIDE_CROSS;
-			front = true;
-			continue;
-		}
-	}
-
-	if (back)
-		return SIDE_BACK;
-	if (front)
-		return SIDE_FRONT;
-	return SIDE_ON;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "polylib.h"
+
+
+extern int numthreads;
+
+// counters are only bumped when running single threaded,
+// because they are an awefull coherence problem
+int	c_active_windings;
+int	c_peak_windings;
+int	c_winding_allocs;
+int	c_winding_points;
+
+#define	BOGUS_RANGE	8192
+
+void pw(winding_t *w)
+{
+	int		i;
+	for (i=0 ; i<w->numpoints ; i++)
+		printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
+}
+
+
+/*
+=============
+AllocWinding
+=============
+*/
+winding_t	*AllocWinding (int points)
+{
+	winding_t	*w;
+	int			s;
+
+	if (numthreads == 1)
+	{
+		c_winding_allocs++;
+		c_winding_points += points;
+		c_active_windings++;
+		if (c_active_windings > c_peak_windings)
+			c_peak_windings = c_active_windings;
+	}
+	s = sizeof(vec_t)*3*points + sizeof(int);
+	w = malloc (s);
+	if (!w)
+		Error("AllocWinding MALLOC failed!  Could not allocate %s bytes.", s);
+	memset (w, 0, s); 
+	return w;
+}
+
+void FreeWinding (winding_t *w)
+{
+	if (*(unsigned *)w == 0xdeaddead)
+		Error ("FreeWinding: freed a freed winding");
+	*(unsigned *)w = 0xdeaddead;
+
+	if (numthreads == 1)
+		c_active_windings--;
+	free (w);
+}
+
+/*
+============
+RemoveColinearPoints
+============
+*/
+int	c_removed;
+
+void	RemoveColinearPoints (winding_t *w)
+{
+	int		i, j, k;
+	vec3_t	v1, v2;
+	int		nump;
+	vec3_t	p[MAX_POINTS_ON_WINDING];
+
+	nump = 0;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		j = (i+1)%w->numpoints;
+		k = (i+w->numpoints-1)%w->numpoints;
+		VectorSubtract (w->p[j], w->p[i], v1);
+		VectorSubtract (w->p[i], w->p[k], v2);
+		VectorNormalize(v1,v1);
+		VectorNormalize(v2,v2);
+		if (DotProduct(v1, v2) < 0.999)
+		{
+			VectorCopy (w->p[i], p[nump]);
+			nump++;
+		}
+	}
+
+	if (nump == w->numpoints)
+		return;
+
+	if (numthreads == 1)
+		c_removed += w->numpoints - nump;
+	w->numpoints = nump;
+	memcpy (w->p, p, nump*sizeof(p[0]));
+}
+
+/*
+============
+WindingPlane
+============
+*/
+void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
+{
+	vec3_t	v1, v2;
+
+	VectorSubtract (w->p[1], w->p[0], v1);
+	VectorSubtract (w->p[2], w->p[0], v2);
+	CrossProduct (v2, v1, normal);
+	VectorNormalize (normal, normal);
+	*dist = DotProduct (w->p[0], normal);
+
+}
+
+/*
+=============
+WindingArea
+=============
+*/
+vec_t	WindingArea (winding_t *w)
+{
+	int		i;
+	vec3_t	d1, d2, cross;
+	vec_t	total;
+
+	total = 0;
+	for (i=2 ; i<w->numpoints ; i++)
+	{
+		VectorSubtract (w->p[i-1], w->p[0], d1);
+		VectorSubtract (w->p[i], w->p[0], d2);
+		CrossProduct (d1, d2, cross);
+		total += 0.5 * VectorLength ( cross );
+	}
+	return total;
+}
+
+void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
+{
+	vec_t	v;
+	int		i,j;
+
+	mins[0] = mins[1] = mins[2] = 99999;
+	maxs[0] = maxs[1] = maxs[2] = -99999;
+
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			v = w->p[i][j];
+			if (v < mins[j])
+				mins[j] = v;
+			if (v > maxs[j])
+				maxs[j] = v;
+		}
+	}
+}
+
+/*
+=============
+WindingCenter
+=============
+*/
+void	WindingCenter (winding_t *w, vec3_t center)
+{
+	int		i;
+	float	scale;
+
+	VectorCopy (vec3_origin, center);
+	for (i=0 ; i<w->numpoints ; i++)
+		VectorAdd (w->p[i], center, center);
+
+	scale = 1.0/w->numpoints;
+	VectorScale (center, scale, center);
+}
+
+/*
+=================
+BaseWindingForPlane
+=================
+*/
+winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
+{
+	int		i, x;
+	vec_t	max, v;
+	vec3_t	org, vright, vup;
+	winding_t	*w;
+	
+// find the major axis
+
+	max = -BOGUS_RANGE;
+	x = -1;
+	for (i=0 ; i<3; i++)
+	{
+		v = fabs(normal[i]);
+		if (v > max)
+		{
+			x = i;
+			max = v;
+		}
+	}
+	if (x==-1)
+		Error ("BaseWindingForPlane: no axis found");
+		
+	VectorCopy (vec3_origin, vup);	
+	switch (x)
+	{
+	case 0:
+	case 1:
+		vup[2] = 1;
+		break;		
+	case 2:
+		vup[0] = 1;
+		break;		
+	}
+
+	v = DotProduct (vup, normal);
+	VectorMA (vup, -v, normal, vup);
+	VectorNormalize (vup, vup);
+		
+	VectorScale (normal, dist, org);
+	
+	CrossProduct (vup, normal, vright);
+	
+	VectorScale (vup, 8192, vup);
+	VectorScale (vright, 8192, vright);
+
+// project a really big	axis aligned box onto the plane
+	w = AllocWinding (4);
+	
+	VectorSubtract (org, vright, w->p[0]);
+	VectorAdd (w->p[0], vup, w->p[0]);
+	
+	VectorAdd (org, vright, w->p[1]);
+	VectorAdd (w->p[1], vup, w->p[1]);
+	
+	VectorAdd (org, vright, w->p[2]);
+	VectorSubtract (w->p[2], vup, w->p[2]);
+	
+	VectorSubtract (org, vright, w->p[3]);
+	VectorSubtract (w->p[3], vup, w->p[3]);
+	
+	w->numpoints = 4;
+	
+	return w;	
+}
+
+/*
+==================
+CopyWinding
+==================
+*/
+winding_t	*CopyWinding (winding_t *w)
+{
+	int			size;
+	winding_t	*c;
+
+	c = AllocWinding (w->numpoints);
+	size = (int)((winding_t *)0)->p[w->numpoints];
+	memcpy (c, w, size);
+	return c;
+}
+
+/*
+==================
+ReverseWinding
+==================
+*/
+winding_t	*ReverseWinding (winding_t *w)
+{
+	int			i;
+	winding_t	*c;
+
+	c = AllocWinding (w->numpoints);
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
+	}
+	c->numpoints = w->numpoints;
+	return c;
+}
+
+
+/*
+=============
+ClipWindingEpsilon
+=============
+*/
+void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
+				vec_t epsilon, winding_t **front, winding_t **back)
+{
+	vec_t	dists[MAX_POINTS_ON_WINDING+4];
+	int		sides[MAX_POINTS_ON_WINDING+4];
+	int		counts[3];
+	vec_t	dot;		// VC 4.2 optimizer bug if not static
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	winding_t	*f, *b;
+	int		maxpts;
+	
+	if (in->numpoints >= MAX_POINTS_ON_WINDING-4)
+		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
+
+	counts[0] = counts[1] = counts[2] = 0;
+
+// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->p[i], normal);
+		dot -= dist;
+		dists[i] = dot;
+		if (dot > epsilon)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -epsilon)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	*front = *back = NULL;
+
+	if (!counts[0])
+	{
+		*back = CopyWinding (in);
+		return;
+	}
+	if (!counts[1])
+	{
+		*front = CopyWinding (in);
+		return;
+	}
+
+	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
+								// of fp grouping errors
+
+	*front = f = AllocWinding (maxpts);
+	*back = b = AllocWinding (maxpts);
+		
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->p[i];
+		
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+			VectorCopy (p1, b->p[b->numpoints]);
+			b->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+		}
+		if (sides[i] == SIDE_BACK)
+		{
+			VectorCopy (p1, b->p[b->numpoints]);
+			b->numpoints++;
+		}
+
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+	// generate a split point
+		p2 = in->p[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (normal[j] == 1)
+				mid[j] = dist;
+			else if (normal[j] == -1)
+				mid[j] = -dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, f->p[f->numpoints]);
+		f->numpoints++;
+		VectorCopy (mid, b->p[b->numpoints]);
+		b->numpoints++;
+	}
+	
+	if (f->numpoints > maxpts || b->numpoints > maxpts)
+		Error ("ClipWinding: points exceeded estimate");
+	if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
+		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
+}
+
+
+/*
+=============
+ChopWindingInPlace
+=============
+*/
+void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
+{
+	winding_t	*in;
+	vec_t	dists[MAX_POINTS_ON_WINDING+4];
+	int		sides[MAX_POINTS_ON_WINDING+4];
+	int		counts[3];
+	vec_t	dot;		// VC 4.2 optimizer bug if not static
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	winding_t	*f;
+	int		maxpts;
+
+	in = *inout;
+	counts[0] = counts[1] = counts[2] = 0;
+
+	if (!in)
+	{
+		printf ("Warning: NULL passed to ChopWindingInPlace\n");
+		return;
+	}
+	if (in->numpoints >= MAX_POINTS_ON_WINDING-4)
+		Error ("ChopWinding: MAX_POINTS_ON_WINDING");
+
+// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->p[i], normal);
+		dot -= dist;
+		dists[i] = dot;
+		if (dot > epsilon)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -epsilon)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	if (!counts[0])
+	{
+		FreeWinding (in);
+		*inout = NULL;
+		return;
+	}
+	if (!counts[1])
+		return;		// inout stays the same
+
+	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
+								// of fp grouping errors
+
+	f = AllocWinding (maxpts);
+		
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->p[i];
+		
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+		}
+
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+	// generate a split point
+		p2 = in->p[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (normal[j] == 1)
+				mid[j] = dist;
+			else if (normal[j] == -1)
+				mid[j] = -dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, f->p[f->numpoints]);
+		f->numpoints++;
+	}
+	
+	if (f->numpoints > maxpts)
+		Error ("ClipWinding: points exceeded estimate");
+	if (f->numpoints > MAX_POINTS_ON_WINDING)
+		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
+
+	FreeWinding (in);
+	*inout = f;
+}
+
+
+/*
+=================
+ChopWinding
+
+Returns the fragment of in that is on the front side
+of the cliping plane.  The original is freed.
+=================
+*/
+winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
+{
+	winding_t	*f, *b;
+
+	ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
+	FreeWinding (in);
+	if (b)
+		FreeWinding (b);
+	return f;
+}
+
+
+/*
+=================
+CheckWinding
+
+=================
+*/
+void CheckWinding (winding_t *w)
+{
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec_t	d, edgedist;
+	vec3_t	dir, edgenormal, facenormal;
+	vec_t	area;
+	vec_t	facedist;
+
+	if (w->numpoints < 3)
+		Error ("CheckWinding: %i points",w->numpoints);
+	
+	area = WindingArea(w);
+	if (area < 1)
+		Error ("CheckWinding: %f area", area);
+
+	WindingPlane (w, facenormal, &facedist);
+	
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		p1 = w->p[i];
+
+		for (j=0 ; j<3 ; j++)
+			if (p1[j] > BOGUS_RANGE || p1[j] < -BOGUS_RANGE)
+				Error ("CheckFace: BUGUS_RANGE: %f",p1[j]);
+
+		j = i+1 == w->numpoints ? 0 : i+1;
+		
+	// check the point is on the face plane
+		d = DotProduct (p1, facenormal) - facedist;
+		if (d < -ON_EPSILON || d > ON_EPSILON)
+			Error ("CheckWinding: point off plane");
+	
+	// check the edge isnt degenerate
+		p2 = w->p[j];
+		VectorSubtract (p2, p1, dir);
+		
+		if (VectorLength (dir) < ON_EPSILON)
+			Error ("CheckWinding: degenerate edge");
+			
+		CrossProduct (facenormal, dir, edgenormal);
+		VectorNormalize (edgenormal, edgenormal);
+		edgedist = DotProduct (p1, edgenormal);
+		edgedist += ON_EPSILON;
+		
+	// all other points must be on front side
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			if (j == i)
+				continue;
+			d = DotProduct (w->p[j], edgenormal);
+			if (d > edgedist)
+				Error ("CheckWinding: non-convex");
+		}
+	}
+}
+
+
+/*
+============
+WindingOnPlaneSide
+============
+*/
+int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
+{
+	qboolean	front, back;
+	int			i;
+	vec_t		d;
+
+	front = false;
+	back = false;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		d = DotProduct (w->p[i], normal) - dist;
+		if (d < -ON_EPSILON)
+		{
+			if (front)
+				return SIDE_CROSS;
+			back = true;
+			continue;
+		}
+		if (d > ON_EPSILON)
+		{
+			if (back)
+				return SIDE_CROSS;
+			front = true;
+			continue;
+		}
+	}
+
+	if (back)
+		return SIDE_BACK;
+	if (front)
+		return SIDE_FRONT;
+	return SIDE_ON;
+}
+
diff --git a/tools/quake2/qdata_heretic2/common/polylib.h b/tools/quake2/qdata_heretic2/common/polylib.h
index e19fb2bd..68660e27 100644
--- a/tools/quake2/qdata_heretic2/common/polylib.h
+++ b/tools/quake2/qdata_heretic2/common/polylib.h
@@ -1,55 +1,55 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-typedef struct
-{
-	int		numpoints;
-	vec3_t	p[4];		// variable sized
-} winding_t;
-
-#define	MAX_POINTS_ON_WINDING	64
-
-// you can define on_epsilon in the makefile as tighter
-#ifndef	ON_EPSILON
-#define	ON_EPSILON	0.1
-#endif
-
-winding_t	*AllocWinding (int points);
-vec_t	WindingArea (winding_t *w);
-void	WindingCenter (winding_t *w, vec3_t center);
-void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
-				vec_t epsilon, winding_t **front, winding_t **back);
-winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
-winding_t	*CopyWinding (winding_t *w);
-winding_t	*ReverseWinding (winding_t *w);
-winding_t	*BaseWindingForPlane (vec3_t normal, vec_t dist);
-void	CheckWinding (winding_t *w);
-void	WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
-void	RemoveColinearPoints (winding_t *w);
-int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
-void	FreeWinding (winding_t *w);
-void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
-
-void	ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
-// frees the original if clipped
-
-void pw(winding_t *w);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+typedef struct
+{
+	int		numpoints;
+	vec3_t	p[4];		// variable sized
+} winding_t;
+
+#define	MAX_POINTS_ON_WINDING	64
+
+// you can define on_epsilon in the makefile as tighter
+#ifndef	ON_EPSILON
+#define	ON_EPSILON	0.1
+#endif
+
+winding_t	*AllocWinding (int points);
+vec_t	WindingArea (winding_t *w);
+void	WindingCenter (winding_t *w, vec3_t center);
+void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
+				vec_t epsilon, winding_t **front, winding_t **back);
+winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
+winding_t	*CopyWinding (winding_t *w);
+winding_t	*ReverseWinding (winding_t *w);
+winding_t	*BaseWindingForPlane (vec3_t normal, vec_t dist);
+void	CheckWinding (winding_t *w);
+void	WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
+void	RemoveColinearPoints (winding_t *w);
+int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
+void	FreeWinding (winding_t *w);
+void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
+
+void	ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
+// frees the original if clipped
+
+void pw(winding_t *w);
diff --git a/tools/quake2/qdata_heretic2/common/qfiles.c b/tools/quake2/qdata_heretic2/common/qfiles.c
index 58fcda00..7e9414f3 100644
--- a/tools/quake2/qdata_heretic2/common/qfiles.c
+++ b/tools/quake2/qdata_heretic2/common/qfiles.c
@@ -1,82 +1,82 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qfiles.h"
-#include "scriplib.h"
-//#include <windows.h>
-
-materialtype_t	defaultmaterialtypes[] =
-{
-	{"gravel",	MATERIAL_GRAVEL},
-	{"metal",	MATERIAL_METAL},
-	{"stone",	MATERIAL_STONE},
-	{"wood",	MATERIAL_WOOD},
-	{NULL,		0}
-};
-
-materialtype_t	*materialtypes;
-
-void QFile_ReadMaterialTypes(char* filename)
-{
-	int		i;
-	FILE	*f;
-
-	f = fopen (filename, "rb");
-	if (!f)
-	{
-		materialtypes = defaultmaterialtypes;
-		return;
-	}
-	fclose (f);
-
-	free(materialtypes);
-	materialtypes = (materialtype_t*)malloc(256 * sizeof(materialtype_t));
-
-	LoadScriptFile(filename);
-	i = 0;
-	
-	while (i < 255)
-	{
-		GetScriptToken (true);
-		if (endofscript)
-		{
-			break;
-		}
-		if (strcmp(token, "material") != 0)
-		{
-			while (ScriptTokenAvailable())
-			{
-				GetScriptToken(false);
-			}
-		}
-		else
-		{
-			GetScriptToken(false);
-			materialtypes[i].name = (char*)malloc(strlen(token) + 1);
-			strcpy(materialtypes[i].name, token);
-			GetScriptToken (false);
-			materialtypes[i].value = atoi(token);
-		}
-		i++;
-	}
-	materialtypes[i].name = NULL;
-	materialtypes[i].value = 0;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qfiles.h"
+#include "scriplib.h"
+//#include <windows.h>
+
+materialtype_t	defaultmaterialtypes[] =
+{
+	{"gravel",	MATERIAL_GRAVEL},
+	{"metal",	MATERIAL_METAL},
+	{"stone",	MATERIAL_STONE},
+	{"wood",	MATERIAL_WOOD},
+	{NULL,		0}
+};
+
+materialtype_t	*materialtypes;
+
+void QFile_ReadMaterialTypes(char* filename)
+{
+	int		i;
+	FILE	*f;
+
+	f = fopen (filename, "rb");
+	if (!f)
+	{
+		materialtypes = defaultmaterialtypes;
+		return;
+	}
+	fclose (f);
+
+	free(materialtypes);
+	materialtypes = (materialtype_t*)malloc(256 * sizeof(materialtype_t));
+
+	LoadScriptFile(filename);
+	i = 0;
+	
+	while (i < 255)
+	{
+		GetScriptToken (true);
+		if (endofscript)
+		{
+			break;
+		}
+		if (strcmp(token, "material") != 0)
+		{
+			while (ScriptTokenAvailable())
+			{
+				GetScriptToken(false);
+			}
+		}
+		else
+		{
+			GetScriptToken(false);
+			materialtypes[i].name = (char*)malloc(strlen(token) + 1);
+			strcpy(materialtypes[i].name, token);
+			GetScriptToken (false);
+			materialtypes[i].value = atoi(token);
+		}
+		i++;
+	}
+	materialtypes[i].name = NULL;
+	materialtypes[i].value = 0;
+}
diff --git a/tools/quake2/qdata_heretic2/common/qfiles.h b/tools/quake2/qdata_heretic2/common/qfiles.h
index 1af6d078..1aa61983 100644
--- a/tools/quake2/qdata_heretic2/common/qfiles.h
+++ b/tools/quake2/qdata_heretic2/common/qfiles.h
@@ -1,619 +1,619 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _QFILES_H
-#define _QFILES_H
-
-#include "q_typedef.h"
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-/*
-========================================================================
-
-The .pak files are just a linear collapse of a directory tree
-
-========================================================================
-*/
-
-#define IDPAKHEADER		(('K'<<24)+('C'<<16)+('A'<<8)+'P')
-
-typedef struct
-{
-	char	name[56];
-	int		filepos, filelen;
-} dpackfile_t;
-
-typedef struct
-{
-	int		ident;		// == IDPAKHEADER
-	int		dirofs;
-	int		dirlen;
-} dpackheader_t;
-
-#define	MAX_FILES_IN_PACK	4096
-
-
-/*
-========================================================================
-
-PCX files are used for as many images as possible
-
-========================================================================
-*/
-
-typedef struct
-{
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
-
-
-/*
-========================================================================
-
-.MD2 compressed triangle model file format
-
-========================================================================
-*/
-#define IDJOINTEDALIASHEADER	(('2'<<24)+('J'<<16)+('D'<<8)+'I')
-
-/*
-========================================================================
-
-.MD2 triangle model file format
-
-========================================================================
-*/
-
-#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
-#define ALIAS_VERSION	8
-
-#define	MAX_TRIANGLES	2048
-#define MAX_VERTS		2048
-#define MAX_FRAMES		512
-#define MAX_MD2SKINS	64
-#define	MAX_SKINNAME	64
-
-typedef struct
-{
-	short	s;
-	short	t;
-} dstvert_t;
-
-typedef struct 
-{
-	short	index_xyz[3];
-	short	index_st[3];
-} dtriangle_t;
-
-typedef struct
-{
-	byte	v[3];			// scaled byte to fit in frame mins/maxs
-	byte	lightnormalindex;
-} dtrivertx_t;
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-typedef struct
-{
-	float		scale[3];	// multiply byte verts by this
-	float		translate[3];	// then add this
-	char		name[16];	// frame name from grabbing
-	dtrivertx_t	verts[1];	// variable sized
-} daliasframe_t;
-
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-typedef struct
-{
-	int			ident;
-	int			version;
-
-	int			skinwidth;
-	int			skinheight;
-	int			framesize;		// byte size of each frame
-
-	int			num_skins;
-	int			num_xyz;
-	int			num_st;			// greater than num_xyz for seams
-	int			num_tris;
-	int			num_glcmds;		// dwords in strip/fan command list
-	int			num_frames;
-
-	int			ofs_skins;		// each skin is a MAX_SKINNAME string
-	int			ofs_st;			// byte offset from start for stverts
-	int			ofs_tris;		// offset for dtriangles
-	int			ofs_frames;		// offset for first frame
-	int			ofs_glcmds;	
-	int			ofs_end;		// end of file
-
-} dmdl_t;
-
-/*
-========================================================================
-
-.BK file format
-
-========================================================================
-*/
-
-#define IDBOOKHEADER	(('K'<<24)+('O'<<16)+('O'<<8)+'B')
-#define BOOK_VERSION	2
-
-typedef struct bookframe_s
-{
-	int			x;
-	int			y;
-	int			w;
-	int			h;
-	char		name[MAX_SKINNAME];		// name of gfx file
-} bookframe_t;
-
-typedef struct bookheader_s
-{
-	unsigned int	ident;
-	unsigned int	version;
-	int				num_segments;
-	int				total_w;
-	int				total_h;
-} bookheader_t;
-
-typedef struct book_s
-{
-	bookheader_t bheader;
-	bookframe_t	bframes[MAX_MD2SKINS];
-} book_t;
-
-/*
-========================================================================
-
-.SP2 sprite file format
-
-========================================================================
-*/
-
-#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
-		// little-endian "IDS2"
-#define SPRITE_VERSION	2
-
-typedef struct
-{
-	int		width, height;
-	int		origin_x, origin_y;		// raster coordinates inside pic
-	char	name[MAX_SKINNAME];		// name of pcx file
-} dsprframe_t;
-
-typedef struct {
-	int			ident;
-	int			version;
-	int			numframes;
-	dsprframe_t	frames[1];			// variable sized
-} dsprite_t;
-
-/*
-==============================================================================
-
-  .M8 texture file format
-
-==============================================================================
-*/
-
-typedef struct palette_s
-{
-	union
-	{
-		struct
-		{
-			byte r,g,b;
-		};
-	};
-} palette_t;
-
-#define MIP_VERSION		2
-#define PAL_SIZE		256
-#define	MIPLEVELS		16
-
-typedef struct miptex_s
-{
-	int			version;
-	char		name[32];
-	unsigned	width[MIPLEVELS], height[MIPLEVELS];
-	unsigned	offsets[MIPLEVELS];		// four mip maps stored
-	char		animname[32];			// next frame in animation chain
-	palette_t	palette[PAL_SIZE];
-	int			flags;
-	int			contents;
-	int			value;
-} miptex_t;
-
-
-#define MIP32_VERSION	4
-
-#define MIP32_NOMIP_FLAG2			0x00000001
-#define MIP32_DETAILER_FLAG2		0x00000002
-
-typedef struct miptex32_s
-{
-	int			version;
-	char		name[128];
-	char		altname[128];			// texture substitution
-	char		animname[128];			// next frame in animation chain
-	char		damagename[128];		// image that should be shown when damaged
-	unsigned	width[MIPLEVELS], height[MIPLEVELS];
-	unsigned	offsets[MIPLEVELS];		
-	int			flags;
-	int			contents;
-	int			value;
-	float		scale_x, scale_y;
-	int			mip_scale;
-
-	// detail texturing info
-	char		dt_name[128];		// detailed texture name
-	float		dt_scale_x, dt_scale_y;
-	float		dt_u, dt_v;
-	float		dt_alpha;
-	int			dt_src_blend_mode, dt_dst_blend_mode;
-
-	int			flags2;
-	int			unused[19];				// future expansion to maintain compatibility with h2
-} miptex32_t;
-
-
-
-/*
-==============================================================================
-
-  .BSP file format
-
-==============================================================================
-*/
-
-#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
-		// little-endian "IBSP"
-
-#define BSPVERSION	38
-
-
-// upper design bounds
-// leaffaces, leafbrushes, planes, and verts are still bounded by
-// 16 bit short limits
-#define	MAX_MAP_MODELS		1024
-#define	MAX_MAP_BRUSHES		8192
-#define	MAX_MAP_ENTITIES	2048
-#define	MAX_MAP_ENTSTRING	0x40000
-#define	MAX_MAP_TEXINFO		8192
-
-#define	MAX_MAP_AREAS		256
-#define	MAX_MAP_AREAPORTALS	1024
-#define	MAX_MAP_PLANES		65536
-#define	MAX_MAP_NODES		65536
-#define	MAX_MAP_BRUSHSIDES	65536
-#define	MAX_MAP_LEAFS		65536
-#define	MAX_MAP_VERTS		65536
-#define	MAX_MAP_FACES		65536
-#define	MAX_MAP_LEAFFACES	65536
-#define	MAX_MAP_LEAFBRUSHES 65536
-#define	MAX_MAP_PORTALS		65536
-#define	MAX_MAP_EDGES		128000
-#define	MAX_MAP_SURFEDGES	256000
-#define	MAX_MAP_LIGHTING	0x200000
-#define	MAX_MAP_VISIBILITY	0x180000
-
-// key / value pair sizes
-
-#define	MAX_KEY		32
-#define	MAX_VALUE	1024
-
-//=============================================================================
-
-typedef struct
-{
-	int		fileofs, filelen;
-} lump_t;
-
-#define	LUMP_ENTITIES		0
-#define	LUMP_PLANES			1
-#define	LUMP_VERTEXES		2
-#define	LUMP_VISIBILITY		3
-#define	LUMP_NODES			4
-#define	LUMP_TEXINFO		5
-#define	LUMP_FACES			6
-#define	LUMP_LIGHTING		7
-#define	LUMP_LEAFS			8
-#define	LUMP_LEAFFACES		9
-#define	LUMP_LEAFBRUSHES	10
-#define	LUMP_EDGES			11
-#define	LUMP_SURFEDGES		12
-#define	LUMP_MODELS			13
-#define	LUMP_BRUSHES		14
-#define	LUMP_BRUSHSIDES		15
-#define	LUMP_POP			16
-#define	LUMP_AREAS			17
-#define	LUMP_AREAPORTALS	18
-#define	HEADER_LUMPS		19
-
-typedef struct
-{
-	int			ident;
-	int			version;	
-	lump_t		lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct
-{
-	float		mins[3], maxs[3];
-	float		origin[3];		// for sounds or lights
-	int			headnode;
-	int			firstface, numfaces;	// submodels just draw faces
-										// without walking the bsp tree
-} dmodel_t;
-
-
-typedef struct
-{
-	float	point[3];
-} dvertex_t;
-
-
-// 0-2 are axial planes
-#define	PLANE_X			0
-#define	PLANE_Y			1
-#define	PLANE_Z			2
-
-// 3-5 are non-axial planes snapped to the nearest
-#define	PLANE_ANYX		3
-#define	PLANE_ANYY		4
-#define	PLANE_ANYZ		5
-
-// planes (x&~1) and (x&~1)+1 are allways opposites
-
-typedef struct
-{
-	float	normal[3];
-	float	dist;
-	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
-} dplane_t;
-
-
-// contents flags are seperate bits
-// a given brush can contribute multiple content bits
-// multiple brushes can be in a single leaf
-
-// these definitions also need to be in q_shared.h!
-
-// lower bits are stronger, and will eat weaker brushes completely
-#define	CONTENTS_SOLID			0x00000001		// an eye is never valid in a solid
-#define	CONTENTS_WINDOW			0x00000002		// translucent, but not watery
-#define	CONTENTS_PUSHPULL		0x00000004
-#define	CONTENTS_LAVA			0x00000008
-#define	CONTENTS_SLIME			0x00000010
-#define	CONTENTS_WATER			0x00000020
-#define	CONTENTS_MIST			0x00000040		// 64
-#define	LAST_VISIBLE_CONTENTS	64				// this one worries me a bit JKH
-
-// remaining contents are non-visible, and don't eat brushes
-
-#define	CONTENTS_AREAPORTAL		0x00008000
-
-#define	CONTENTS_PLAYERCLIP		0x00010000
-#define	CONTENTS_MONSTERCLIP	0x00020000
-
-// currents can be added to any other contents, and may be mixed
-#define	CONTENTS_CURRENT_0		0x00040000
-#define	CONTENTS_CURRENT_90		0x00080000
-#define	CONTENTS_CURRENT_180	0x00100000
-#define	CONTENTS_CURRENT_270	0x00200000
-#define	CONTENTS_CURRENT_UP		0x00400000
-#define	CONTENTS_CURRENT_DOWN	0x00800000
-
-#define	CONTENTS_ORIGIN			0x01000000	// removed before bsping an entity
-
-#define	CONTENTS_MONSTER		0x02000000	// should never be on a brush, only in game
-#define	CONTENTS_DEADMONSTER	0x04000000
-#define	CONTENTS_DETAIL			0x08000000	// brushes to be added after vis leafs
-#define	CONTENTS_TRANSLUCENT	0x10000000	// auto set if any surface has trans
-#define	CONTENTS_LADDER			0x20000000
-
-
-
-#define	SURF_LIGHT				0x00000001		// value will hold the light strength
-
-#define	SURF_SLICK				0x00000002		// effects game physics
-
-#define	SURF_SKY				0x00000004		// don't draw, but add to skybox
-#define	SURF_WARP				0x00000008		// turbulent water warp
-#define	SURF_TRANS33			0x00000010
-#define	SURF_TRANS66			0x00000020
-#define	SURF_FLOWING			0x00000040	// scroll towards angle
-#define	SURF_NODRAW				0x00000080	// don't bother referencing the texture
-
-#define	SURF_HINT				0x00000100	// make a primary bsp splitter
-#define	SURF_SKIP				0x00000200	// completely ignore, allowing non-closed brushes
-#define	SURF_TALL_WALL			0x00000400	// face doesn't get broken up as normal
-
-#define	SURF_ALPHA_TEXTURE		0x00000800	// texture has alpha in it, and should show through in bsp process
-#define	SURF_ANIMSPEED			0x00001000		// value will hold the anim speed in fps
-
-#define SURF_UNDULATE			0x00002000	// rock surface up and down...
-#define SURF_SKYREFLECT			0x00004000	// liquid will somewhat reflect the sky - not quite finished....
-
-#define SURF_TYPE_GRAVEL		0x00000000
-#define SURF_TYPE_METAL			0x01000000
-#define SURF_TYPE_STONE			0x02000000
-#define SURF_TYPE_WOOD			0x03000000
-#define	SURF_MATERIAL			0xFF000000
-
-
-
-typedef struct
-{
-	int			planenum;
-	int			children[2];	// negative numbers are -(leafs+1), not nodes
-	short		mins[3];		// for frustom culling
-	short		maxs[3];
-	unsigned short	firstface;
-	unsigned short	numfaces;	// counting both sides
-} dnode_t;
-
-
-typedef struct texinfo_s
-{
-	float		vecs[2][4];		// [s/t][xyz offset]
-	int			flags;			// miptex flags + overrides
-	int			value;			// light emission, etc
-	char		texture[32];	// texture name (textures/*.wal)
-	int			nexttexinfo;	// for animations, -1 = end of chain
-} texinfo_t;
-
-
-// note that edge 0 is never used, because negative edge nums are used for
-// counterclockwise use of the edge in a face
-typedef struct
-{
-	unsigned short	v[2];		// vertex numbers
-} dedge_t;
-
-#define	MAXLIGHTMAPS	4
-typedef struct
-{
-	unsigned short	planenum;
-	short		side;
-
-	int			firstedge;		// we must support > 64k edges
-	short		numedges;	
-	short		texinfo;
-
-// lighting info
-	union {
-	byte		styles[MAXLIGHTMAPS];
-	paletteRGBA_t	lighting;
-	};
-	int			lightofs;		// start of [numstyles*surfsize] samples
-} dface_t;
-
-typedef struct
-{
-	int				contents;			// OR of all brushes (not needed?)
-
-	short			cluster;
-	short			area;
-
-	short			mins[3];			// for frustum culling
-	short			maxs[3];
-
-	unsigned short	firstleafface;
-	unsigned short	numleaffaces;
-
-	unsigned short	firstleafbrush;
-	unsigned short	numleafbrushes;
-} dleaf_t;
-
-typedef struct
-{
-	unsigned short	planenum;		// facing out of the leaf
-	short	texinfo;
-} dbrushside_t;
-
-typedef struct
-{
-	int			firstside;
-	int			numsides;
-	int			contents;
-} dbrush_t;
-
-#define	ANGLE_UP	-1
-#define	ANGLE_DOWN	-2
-
-
-// the visibility lump consists of a header with a count, then
-// byte offsets for the PVS and PHS of each cluster, then the raw
-// compressed bit vectors
-#define	DVIS_PVS	0
-#define	DVIS_PHS	1
-typedef struct
-{
-	int			numclusters;
-	int			bitofs[8][2];	// bitofs[numclusters][2]
-} dvis_t;
-
-// each area has a list of portals that lead into other areas
-// when portals are closed, other areas may not be visible or
-// hearable even if the vis info says that it should be
-typedef struct
-{
-	int		portalnum;
-	int		otherarea;
-} dareaportal_t;
-
-
-typedef struct
-{
-	int		numareaportals;
-	int		firstareaportal;
-} darea_t;
-
-typedef struct
-{
-	char	*name;
-	int		value;
-} materialtype_t;
-
-enum
-{
-	MATERIAL_GRAVEL,
-	MATERIAL_METAL,
-	MATERIAL_STONE,
-	MATERIAL_WOOD,
-};
-
-materialtype_t	*materialtypes;
-
-void QFile_ReadMaterialTypes(char* filename);
-
-
-#endif //_QFILES_H
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _QFILES_H
+#define _QFILES_H
+
+#include "q_typedef.h"
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+/*
+========================================================================
+
+The .pak files are just a linear collapse of a directory tree
+
+========================================================================
+*/
+
+#define IDPAKHEADER		(('K'<<24)+('C'<<16)+('A'<<8)+'P')
+
+typedef struct
+{
+	char	name[56];
+	int		filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+	int		ident;		// == IDPAKHEADER
+	int		dirofs;
+	int		dirlen;
+} dpackheader_t;
+
+#define	MAX_FILES_IN_PACK	4096
+
+
+/*
+========================================================================
+
+PCX files are used for as many images as possible
+
+========================================================================
+*/
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+
+/*
+========================================================================
+
+.MD2 compressed triangle model file format
+
+========================================================================
+*/
+#define IDJOINTEDALIASHEADER	(('2'<<24)+('J'<<16)+('D'<<8)+'I')
+
+/*
+========================================================================
+
+.MD2 triangle model file format
+
+========================================================================
+*/
+
+#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
+#define ALIAS_VERSION	8
+
+#define	MAX_TRIANGLES	2048
+#define MAX_VERTS		2048
+#define MAX_FRAMES		512
+#define MAX_MD2SKINS	64
+#define	MAX_SKINNAME	64
+
+typedef struct
+{
+	short	s;
+	short	t;
+} dstvert_t;
+
+typedef struct 
+{
+	short	index_xyz[3];
+	short	index_st[3];
+} dtriangle_t;
+
+typedef struct
+{
+	byte	v[3];			// scaled byte to fit in frame mins/maxs
+	byte	lightnormalindex;
+} dtrivertx_t;
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+typedef struct
+{
+	float		scale[3];	// multiply byte verts by this
+	float		translate[3];	// then add this
+	char		name[16];	// frame name from grabbing
+	dtrivertx_t	verts[1];	// variable sized
+} daliasframe_t;
+
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+typedef struct
+{
+	int			ident;
+	int			version;
+
+	int			skinwidth;
+	int			skinheight;
+	int			framesize;		// byte size of each frame
+
+	int			num_skins;
+	int			num_xyz;
+	int			num_st;			// greater than num_xyz for seams
+	int			num_tris;
+	int			num_glcmds;		// dwords in strip/fan command list
+	int			num_frames;
+
+	int			ofs_skins;		// each skin is a MAX_SKINNAME string
+	int			ofs_st;			// byte offset from start for stverts
+	int			ofs_tris;		// offset for dtriangles
+	int			ofs_frames;		// offset for first frame
+	int			ofs_glcmds;	
+	int			ofs_end;		// end of file
+
+} dmdl_t;
+
+/*
+========================================================================
+
+.BK file format
+
+========================================================================
+*/
+
+#define IDBOOKHEADER	(('K'<<24)+('O'<<16)+('O'<<8)+'B')
+#define BOOK_VERSION	2
+
+typedef struct bookframe_s
+{
+	int			x;
+	int			y;
+	int			w;
+	int			h;
+	char		name[MAX_SKINNAME];		// name of gfx file
+} bookframe_t;
+
+typedef struct bookheader_s
+{
+	unsigned int	ident;
+	unsigned int	version;
+	int				num_segments;
+	int				total_w;
+	int				total_h;
+} bookheader_t;
+
+typedef struct book_s
+{
+	bookheader_t bheader;
+	bookframe_t	bframes[MAX_MD2SKINS];
+} book_t;
+
+/*
+========================================================================
+
+.SP2 sprite file format
+
+========================================================================
+*/
+
+#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
+		// little-endian "IDS2"
+#define SPRITE_VERSION	2
+
+typedef struct
+{
+	int		width, height;
+	int		origin_x, origin_y;		// raster coordinates inside pic
+	char	name[MAX_SKINNAME];		// name of pcx file
+} dsprframe_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+	int			numframes;
+	dsprframe_t	frames[1];			// variable sized
+} dsprite_t;
+
+/*
+==============================================================================
+
+  .M8 texture file format
+
+==============================================================================
+*/
+
+typedef struct palette_s
+{
+	union
+	{
+		struct
+		{
+			byte r,g,b;
+		};
+	};
+} palette_t;
+
+#define MIP_VERSION		2
+#define PAL_SIZE		256
+#define	MIPLEVELS		16
+
+typedef struct miptex_s
+{
+	int			version;
+	char		name[32];
+	unsigned	width[MIPLEVELS], height[MIPLEVELS];
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+	char		animname[32];			// next frame in animation chain
+	palette_t	palette[PAL_SIZE];
+	int			flags;
+	int			contents;
+	int			value;
+} miptex_t;
+
+
+#define MIP32_VERSION	4
+
+#define MIP32_NOMIP_FLAG2			0x00000001
+#define MIP32_DETAILER_FLAG2		0x00000002
+
+typedef struct miptex32_s
+{
+	int			version;
+	char		name[128];
+	char		altname[128];			// texture substitution
+	char		animname[128];			// next frame in animation chain
+	char		damagename[128];		// image that should be shown when damaged
+	unsigned	width[MIPLEVELS], height[MIPLEVELS];
+	unsigned	offsets[MIPLEVELS];		
+	int			flags;
+	int			contents;
+	int			value;
+	float		scale_x, scale_y;
+	int			mip_scale;
+
+	// detail texturing info
+	char		dt_name[128];		// detailed texture name
+	float		dt_scale_x, dt_scale_y;
+	float		dt_u, dt_v;
+	float		dt_alpha;
+	int			dt_src_blend_mode, dt_dst_blend_mode;
+
+	int			flags2;
+	int			unused[19];				// future expansion to maintain compatibility with h2
+} miptex32_t;
+
+
+
+/*
+==============================================================================
+
+  .BSP file format
+
+==============================================================================
+*/
+
+#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
+		// little-endian "IBSP"
+
+#define BSPVERSION	38
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define	MAX_MAP_MODELS		1024
+#define	MAX_MAP_BRUSHES		8192
+#define	MAX_MAP_ENTITIES	2048
+#define	MAX_MAP_ENTSTRING	0x40000
+#define	MAX_MAP_TEXINFO		8192
+
+#define	MAX_MAP_AREAS		256
+#define	MAX_MAP_AREAPORTALS	1024
+#define	MAX_MAP_PLANES		65536
+#define	MAX_MAP_NODES		65536
+#define	MAX_MAP_BRUSHSIDES	65536
+#define	MAX_MAP_LEAFS		65536
+#define	MAX_MAP_VERTS		65536
+#define	MAX_MAP_FACES		65536
+#define	MAX_MAP_LEAFFACES	65536
+#define	MAX_MAP_LEAFBRUSHES 65536
+#define	MAX_MAP_PORTALS		65536
+#define	MAX_MAP_EDGES		128000
+#define	MAX_MAP_SURFEDGES	256000
+#define	MAX_MAP_LIGHTING	0x200000
+#define	MAX_MAP_VISIBILITY	0x180000
+
+// key / value pair sizes
+
+#define	MAX_KEY		32
+#define	MAX_VALUE	1024
+
+//=============================================================================
+
+typedef struct
+{
+	int		fileofs, filelen;
+} lump_t;
+
+#define	LUMP_ENTITIES		0
+#define	LUMP_PLANES			1
+#define	LUMP_VERTEXES		2
+#define	LUMP_VISIBILITY		3
+#define	LUMP_NODES			4
+#define	LUMP_TEXINFO		5
+#define	LUMP_FACES			6
+#define	LUMP_LIGHTING		7
+#define	LUMP_LEAFS			8
+#define	LUMP_LEAFFACES		9
+#define	LUMP_LEAFBRUSHES	10
+#define	LUMP_EDGES			11
+#define	LUMP_SURFEDGES		12
+#define	LUMP_MODELS			13
+#define	LUMP_BRUSHES		14
+#define	LUMP_BRUSHSIDES		15
+#define	LUMP_POP			16
+#define	LUMP_AREAS			17
+#define	LUMP_AREAPORTALS	18
+#define	HEADER_LUMPS		19
+
+typedef struct
+{
+	int			ident;
+	int			version;	
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+	float		mins[3], maxs[3];
+	float		origin[3];		// for sounds or lights
+	int			headnode;
+	int			firstface, numfaces;	// submodels just draw faces
+										// without walking the bsp tree
+} dmodel_t;
+
+
+typedef struct
+{
+	float	point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define	PLANE_X			0
+#define	PLANE_Y			1
+#define	PLANE_Z			2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define	PLANE_ANYX		3
+#define	PLANE_ANYY		4
+#define	PLANE_ANYZ		5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+	float	normal[3];
+	float	dist;
+	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// these definitions also need to be in q_shared.h!
+
+// lower bits are stronger, and will eat weaker brushes completely
+#define	CONTENTS_SOLID			0x00000001		// an eye is never valid in a solid
+#define	CONTENTS_WINDOW			0x00000002		// translucent, but not watery
+#define	CONTENTS_PUSHPULL		0x00000004
+#define	CONTENTS_LAVA			0x00000008
+#define	CONTENTS_SLIME			0x00000010
+#define	CONTENTS_WATER			0x00000020
+#define	CONTENTS_MIST			0x00000040		// 64
+#define	LAST_VISIBLE_CONTENTS	64				// this one worries me a bit JKH
+
+// remaining contents are non-visible, and don't eat brushes
+
+#define	CONTENTS_AREAPORTAL		0x00008000
+
+#define	CONTENTS_PLAYERCLIP		0x00010000
+#define	CONTENTS_MONSTERCLIP	0x00020000
+
+// currents can be added to any other contents, and may be mixed
+#define	CONTENTS_CURRENT_0		0x00040000
+#define	CONTENTS_CURRENT_90		0x00080000
+#define	CONTENTS_CURRENT_180	0x00100000
+#define	CONTENTS_CURRENT_270	0x00200000
+#define	CONTENTS_CURRENT_UP		0x00400000
+#define	CONTENTS_CURRENT_DOWN	0x00800000
+
+#define	CONTENTS_ORIGIN			0x01000000	// removed before bsping an entity
+
+#define	CONTENTS_MONSTER		0x02000000	// should never be on a brush, only in game
+#define	CONTENTS_DEADMONSTER	0x04000000
+#define	CONTENTS_DETAIL			0x08000000	// brushes to be added after vis leafs
+#define	CONTENTS_TRANSLUCENT	0x10000000	// auto set if any surface has trans
+#define	CONTENTS_LADDER			0x20000000
+
+
+
+#define	SURF_LIGHT				0x00000001		// value will hold the light strength
+
+#define	SURF_SLICK				0x00000002		// effects game physics
+
+#define	SURF_SKY				0x00000004		// don't draw, but add to skybox
+#define	SURF_WARP				0x00000008		// turbulent water warp
+#define	SURF_TRANS33			0x00000010
+#define	SURF_TRANS66			0x00000020
+#define	SURF_FLOWING			0x00000040	// scroll towards angle
+#define	SURF_NODRAW				0x00000080	// don't bother referencing the texture
+
+#define	SURF_HINT				0x00000100	// make a primary bsp splitter
+#define	SURF_SKIP				0x00000200	// completely ignore, allowing non-closed brushes
+#define	SURF_TALL_WALL			0x00000400	// face doesn't get broken up as normal
+
+#define	SURF_ALPHA_TEXTURE		0x00000800	// texture has alpha in it, and should show through in bsp process
+#define	SURF_ANIMSPEED			0x00001000		// value will hold the anim speed in fps
+
+#define SURF_UNDULATE			0x00002000	// rock surface up and down...
+#define SURF_SKYREFLECT			0x00004000	// liquid will somewhat reflect the sky - not quite finished....
+
+#define SURF_TYPE_GRAVEL		0x00000000
+#define SURF_TYPE_METAL			0x01000000
+#define SURF_TYPE_STONE			0x02000000
+#define SURF_TYPE_WOOD			0x03000000
+#define	SURF_MATERIAL			0xFF000000
+
+
+
+typedef struct
+{
+	int			planenum;
+	int			children[2];	// negative numbers are -(leafs+1), not nodes
+	short		mins[3];		// for frustom culling
+	short		maxs[3];
+	unsigned short	firstface;
+	unsigned short	numfaces;	// counting both sides
+} dnode_t;
+
+
+typedef struct texinfo_s
+{
+	float		vecs[2][4];		// [s/t][xyz offset]
+	int			flags;			// miptex flags + overrides
+	int			value;			// light emission, etc
+	char		texture[32];	// texture name (textures/*.wal)
+	int			nexttexinfo;	// for animations, -1 = end of chain
+} texinfo_t;
+
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+	unsigned short	v[2];		// vertex numbers
+} dedge_t;
+
+#define	MAXLIGHTMAPS	4
+typedef struct
+{
+	unsigned short	planenum;
+	short		side;
+
+	int			firstedge;		// we must support > 64k edges
+	short		numedges;	
+	short		texinfo;
+
+// lighting info
+	union {
+	byte		styles[MAXLIGHTMAPS];
+	paletteRGBA_t	lighting;
+	};
+	int			lightofs;		// start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+	int				contents;			// OR of all brushes (not needed?)
+
+	short			cluster;
+	short			area;
+
+	short			mins[3];			// for frustum culling
+	short			maxs[3];
+
+	unsigned short	firstleafface;
+	unsigned short	numleaffaces;
+
+	unsigned short	firstleafbrush;
+	unsigned short	numleafbrushes;
+} dleaf_t;
+
+typedef struct
+{
+	unsigned short	planenum;		// facing out of the leaf
+	short	texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+	int			firstside;
+	int			numsides;
+	int			contents;
+} dbrush_t;
+
+#define	ANGLE_UP	-1
+#define	ANGLE_DOWN	-2
+
+
+// the visibility lump consists of a header with a count, then
+// byte offsets for the PVS and PHS of each cluster, then the raw
+// compressed bit vectors
+#define	DVIS_PVS	0
+#define	DVIS_PHS	1
+typedef struct
+{
+	int			numclusters;
+	int			bitofs[8][2];	// bitofs[numclusters][2]
+} dvis_t;
+
+// each area has a list of portals that lead into other areas
+// when portals are closed, other areas may not be visible or
+// hearable even if the vis info says that it should be
+typedef struct
+{
+	int		portalnum;
+	int		otherarea;
+} dareaportal_t;
+
+
+typedef struct
+{
+	int		numareaportals;
+	int		firstareaportal;
+} darea_t;
+
+typedef struct
+{
+	char	*name;
+	int		value;
+} materialtype_t;
+
+enum
+{
+	MATERIAL_GRAVEL,
+	MATERIAL_METAL,
+	MATERIAL_STONE,
+	MATERIAL_WOOD,
+};
+
+materialtype_t	*materialtypes;
+
+void QFile_ReadMaterialTypes(char* filename);
+
+
+#endif //_QFILES_H
diff --git a/tools/quake2/qdata_heretic2/common/scriplib.c b/tools/quake2/qdata_heretic2/common/scriplib.c
index 25fc66d1..15042d5d 100644
--- a/tools/quake2/qdata_heretic2/common/scriplib.c
+++ b/tools/quake2/qdata_heretic2/common/scriplib.c
@@ -1,297 +1,297 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// scriplib.c
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "scriplib.h"
-
-/*
-=============================================================================
-
-						PARSING STUFF
-
-=============================================================================
-*/
-
-typedef struct
-{
-	char	filename[1024];
-	char    *buffer,*script_p,*end_p;
-	int     line;
-} script_t;
-
-#define	MAX_INCLUDES	8
-script_t	scriptstack[MAX_INCLUDES];
-script_t	*script;
-int			scriptline;
-
-char    token[MAXTOKEN];
-qboolean endofscript;
-qboolean tokenready;                     // only true if UnGetScriptToken was just called
-
-/*
-==============
-AddScriptToStack
-==============
-*/
-void AddScriptToStack (char *filename)
-{
-	int            size;
-
-	script++;
-	if (script == &scriptstack[MAX_INCLUDES])
-		Error ("script file exceeded MAX_INCLUDES");
-	strcpy (script->filename, ExpandPath (filename) );
-
-	size = LoadFile (script->filename, (void **)&script->buffer);
-
-	printf ("entering %s\n", script->filename);
-
-	script->line = 1;
-
-	script->script_p = script->buffer;
-	script->end_p = script->buffer + size;
-}
-
-
-/*
-==============
-LoadScriptFile
-==============
-*/
-void LoadScriptFile (char *filename)
-{
-	script = scriptstack;
-	AddScriptToStack (filename);
-
-	endofscript = false;
-	tokenready = false;
-}
-
-
-/*
-==============
-ParseFromMemory
-==============
-*/
-void ParseFromMemory (char *buffer, int size)
-{
-	script = scriptstack;
-	script++;
-	if (script == &scriptstack[MAX_INCLUDES])
-		Error ("script file exceeded MAX_INCLUDES");
-	strcpy (script->filename, "memory buffer" );
-
-	script->buffer = buffer;
-	script->line = 1;
-	script->script_p = script->buffer;
-	script->end_p = script->buffer + size;
-
-	endofscript = false;
-	tokenready = false;
-}
-
-
-/*
-==============
-UnGetScriptToken
-
-Signals that the current token was not used, and should be reported
-for the next GetScriptToken.  Note that
-
-GetScriptToken (true);
-UnGetScriptToken ();
-GetScriptToken (false);
-
-could cross a line boundary.
-==============
-*/
-void UnGetScriptToken (void)
-{
-	tokenready = true;
-}
-
-
-qboolean EndOfScript (qboolean crossline)
-{
-	if (!crossline)
-		Error ("Line %i is incomplete\n",scriptline);
-
-	if (!strcmp (script->filename, "memory buffer"))
-	{
-		endofscript = true;
-		return false;
-	}
-
-	free (script->buffer);
-	if (script == scriptstack+1)
-	{
-		endofscript = true;
-		return false;
-	}
-	script--;
-	scriptline = script->line;
-	printf ("returning to %s\n", script->filename);
-	return GetScriptToken (crossline);
-}
-
-/*
-==============
-GetScriptToken
-==============
-*/
-qboolean GetScriptToken (qboolean crossline)
-{
-	char    *token_p;
-
-	if (tokenready)                         // is a token allready waiting?
-	{
-		tokenready = false;
-		return true;
-	}
-
-	if (script->script_p >= script->end_p)
-		return EndOfScript (crossline);
-
-//
-// skip space
-//
-skipspace:
-	while (*script->script_p <= 32)
-	{
-		if (script->script_p >= script->end_p)
-			return EndOfScript (crossline);
-		if (*script->script_p++ == '\n')
-		{
-			if (!crossline)
-				Error ("Line %i is incomplete\n",scriptline);
-			scriptline = script->line++;
-		}
-	}
-
-	if (script->script_p >= script->end_p)
-		return EndOfScript (crossline);
-
-	// ; # // comments
-	if (*script->script_p == ';' || *script->script_p == '#'
-		|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
-	{
-		if (!crossline)
-			Error ("Line %i is incomplete\n",scriptline);
-		while (*script->script_p++ != '\n')
-			if (script->script_p >= script->end_p)
-				return EndOfScript (crossline);
-		goto skipspace;
-	}
-
-	// /* */ comments
-	if (script->script_p[0] == '/' && script->script_p[1] == '*')
-	{
-		if (!crossline)
-			Error ("Line %i is incomplete\n",scriptline);
-		script->script_p+=2;
-		while (script->script_p[0] != '*' && script->script_p[1] != '/')
-		{
-			script->script_p++;
-			if (script->script_p >= script->end_p)
-				return EndOfScript (crossline);
-		}
-		script->script_p += 2;
-		goto skipspace;
-	}
-
-//
-// copy token
-//
-	token_p = token;
-
-	if (*script->script_p == '"')
-	{
-		// quoted token
-		script->script_p++;
-		while (*script->script_p != '"')
-		{
-			*token_p++ = *script->script_p++;
-			if (script->script_p == script->end_p)
-				break;
-			if (token_p == &token[MAXTOKEN])
-				Error ("Token too large on line %i\n",scriptline);
-		}
-		script->script_p++;
-	}
-	else	// regular token
-	while ( *script->script_p > 32 && *script->script_p != ';')
-	{
-		*token_p++ = *script->script_p++;
-		if (script->script_p == script->end_p)
-			break;
-		if (token_p == &token[MAXTOKEN])
-			Error ("Token too large on line %i\n",scriptline);
-	}
-
-	*token_p = 0;
-
-	if (!strcmp (token, "$include"))
-	{
-		GetScriptToken (false);
-		AddScriptToStack (token);
-		return GetScriptToken (crossline);
-	}
-
-	return true;
-}
-
-
-/*
-==============
-ScriptTokenAvailable
-
-Returns true if there is another token on the line
-==============
-*/
-qboolean ScriptTokenAvailable (void)
-{
-	char    *search_p;
-
-	search_p = script->script_p;
-
-	if (search_p >= script->end_p)
-		return false;
-
-	while ( *search_p <= 32)
-	{
-		if (*search_p == '\n')
-			return false;
-		search_p++;
-		if (search_p == script->end_p)
-			return false;
-
-	}
-
-	if (*search_p == ';')
-		return false;
-
-	return true;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// scriplib.c
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "scriplib.h"
+
+/*
+=============================================================================
+
+						PARSING STUFF
+
+=============================================================================
+*/
+
+typedef struct
+{
+	char	filename[1024];
+	char    *buffer,*script_p,*end_p;
+	int     line;
+} script_t;
+
+#define	MAX_INCLUDES	8
+script_t	scriptstack[MAX_INCLUDES];
+script_t	*script;
+int			scriptline;
+
+char    token[MAXTOKEN];
+qboolean endofscript;
+qboolean tokenready;                     // only true if UnGetScriptToken was just called
+
+/*
+==============
+AddScriptToStack
+==============
+*/
+void AddScriptToStack (char *filename)
+{
+	int            size;
+
+	script++;
+	if (script == &scriptstack[MAX_INCLUDES])
+		Error ("script file exceeded MAX_INCLUDES");
+	strcpy (script->filename, ExpandPath (filename) );
+
+	size = LoadFile (script->filename, (void **)&script->buffer);
+
+	printf ("entering %s\n", script->filename);
+
+	script->line = 1;
+
+	script->script_p = script->buffer;
+	script->end_p = script->buffer + size;
+}
+
+
+/*
+==============
+LoadScriptFile
+==============
+*/
+void LoadScriptFile (char *filename)
+{
+	script = scriptstack;
+	AddScriptToStack (filename);
+
+	endofscript = false;
+	tokenready = false;
+}
+
+
+/*
+==============
+ParseFromMemory
+==============
+*/
+void ParseFromMemory (char *buffer, int size)
+{
+	script = scriptstack;
+	script++;
+	if (script == &scriptstack[MAX_INCLUDES])
+		Error ("script file exceeded MAX_INCLUDES");
+	strcpy (script->filename, "memory buffer" );
+
+	script->buffer = buffer;
+	script->line = 1;
+	script->script_p = script->buffer;
+	script->end_p = script->buffer + size;
+
+	endofscript = false;
+	tokenready = false;
+}
+
+
+/*
+==============
+UnGetScriptToken
+
+Signals that the current token was not used, and should be reported
+for the next GetScriptToken.  Note that
+
+GetScriptToken (true);
+UnGetScriptToken ();
+GetScriptToken (false);
+
+could cross a line boundary.
+==============
+*/
+void UnGetScriptToken (void)
+{
+	tokenready = true;
+}
+
+
+qboolean EndOfScript (qboolean crossline)
+{
+	if (!crossline)
+		Error ("Line %i is incomplete\n",scriptline);
+
+	if (!strcmp (script->filename, "memory buffer"))
+	{
+		endofscript = true;
+		return false;
+	}
+
+	free (script->buffer);
+	if (script == scriptstack+1)
+	{
+		endofscript = true;
+		return false;
+	}
+	script--;
+	scriptline = script->line;
+	printf ("returning to %s\n", script->filename);
+	return GetScriptToken (crossline);
+}
+
+/*
+==============
+GetScriptToken
+==============
+*/
+qboolean GetScriptToken (qboolean crossline)
+{
+	char    *token_p;
+
+	if (tokenready)                         // is a token allready waiting?
+	{
+		tokenready = false;
+		return true;
+	}
+
+	if (script->script_p >= script->end_p)
+		return EndOfScript (crossline);
+
+//
+// skip space
+//
+skipspace:
+	while (*script->script_p <= 32)
+	{
+		if (script->script_p >= script->end_p)
+			return EndOfScript (crossline);
+		if (*script->script_p++ == '\n')
+		{
+			if (!crossline)
+				Error ("Line %i is incomplete\n",scriptline);
+			scriptline = script->line++;
+		}
+	}
+
+	if (script->script_p >= script->end_p)
+		return EndOfScript (crossline);
+
+	// ; # // comments
+	if (*script->script_p == ';' || *script->script_p == '#'
+		|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
+	{
+		if (!crossline)
+			Error ("Line %i is incomplete\n",scriptline);
+		while (*script->script_p++ != '\n')
+			if (script->script_p >= script->end_p)
+				return EndOfScript (crossline);
+		goto skipspace;
+	}
+
+	// /* */ comments
+	if (script->script_p[0] == '/' && script->script_p[1] == '*')
+	{
+		if (!crossline)
+			Error ("Line %i is incomplete\n",scriptline);
+		script->script_p+=2;
+		while (script->script_p[0] != '*' && script->script_p[1] != '/')
+		{
+			script->script_p++;
+			if (script->script_p >= script->end_p)
+				return EndOfScript (crossline);
+		}
+		script->script_p += 2;
+		goto skipspace;
+	}
+
+//
+// copy token
+//
+	token_p = token;
+
+	if (*script->script_p == '"')
+	{
+		// quoted token
+		script->script_p++;
+		while (*script->script_p != '"')
+		{
+			*token_p++ = *script->script_p++;
+			if (script->script_p == script->end_p)
+				break;
+			if (token_p == &token[MAXTOKEN])
+				Error ("Token too large on line %i\n",scriptline);
+		}
+		script->script_p++;
+	}
+	else	// regular token
+	while ( *script->script_p > 32 && *script->script_p != ';')
+	{
+		*token_p++ = *script->script_p++;
+		if (script->script_p == script->end_p)
+			break;
+		if (token_p == &token[MAXTOKEN])
+			Error ("Token too large on line %i\n",scriptline);
+	}
+
+	*token_p = 0;
+
+	if (!strcmp (token, "$include"))
+	{
+		GetScriptToken (false);
+		AddScriptToStack (token);
+		return GetScriptToken (crossline);
+	}
+
+	return true;
+}
+
+
+/*
+==============
+ScriptTokenAvailable
+
+Returns true if there is another token on the line
+==============
+*/
+qboolean ScriptTokenAvailable (void)
+{
+	char    *search_p;
+
+	search_p = script->script_p;
+
+	if (search_p >= script->end_p)
+		return false;
+
+	while ( *search_p <= 32)
+	{
+		if (*search_p == '\n')
+			return false;
+		search_p++;
+		if (search_p == script->end_p)
+			return false;
+
+	}
+
+	if (*search_p == ';')
+		return false;
+
+	return true;
+}
+
+
diff --git a/tools/quake2/qdata_heretic2/common/scriplib.h b/tools/quake2/qdata_heretic2/common/scriplib.h
index bee8d0aa..80ece66f 100644
--- a/tools/quake2/qdata_heretic2/common/scriplib.h
+++ b/tools/quake2/qdata_heretic2/common/scriplib.h
@@ -1,44 +1,44 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// scriplib.h
-
-#ifndef __CMDLIB__
-#include "cmdlib.h"
-#endif
-
-#define	MAXTOKEN	1024
-
-extern	char	token[MAXTOKEN];
-extern	char	*scriptbuffer,*script_p,*scriptend_p;
-extern	int		grabbed;
-extern	int		scriptline;
-extern	qboolean	endofscript;
-
-
-void LoadScriptFile (char *filename);
-void ParseFromMemory (char *buffer, int size);
-
-qboolean GetScriptToken (qboolean crossline);
-void UnGetScriptToken (void);
-qboolean ScriptTokenAvailable (void);
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// scriplib.h
+
+#ifndef __CMDLIB__
+#include "cmdlib.h"
+#endif
+
+#define	MAXTOKEN	1024
+
+extern	char	token[MAXTOKEN];
+extern	char	*scriptbuffer,*script_p,*scriptend_p;
+extern	int		grabbed;
+extern	int		scriptline;
+extern	qboolean	endofscript;
+
+
+void LoadScriptFile (char *filename);
+void ParseFromMemory (char *buffer, int size);
+
+qboolean GetScriptToken (qboolean crossline);
+void UnGetScriptToken (void);
+qboolean ScriptTokenAvailable (void);
+
+
diff --git a/tools/quake2/qdata_heretic2/common/threads.c b/tools/quake2/qdata_heretic2/common/threads.c
index 2a2b9787..ce51fb32 100644
--- a/tools/quake2/qdata_heretic2/common/threads.c
+++ b/tools/quake2/qdata_heretic2/common/threads.c
@@ -1,620 +1,620 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef WIN32
-// The below define is necessary to use
-// pthreads extensions like pthread_mutexattr_settype
-#define _GNU_SOURCE
-#include <pthread.h>
-#endif
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include "her2_threads.h"
-
-#define	MAX_THREADS	64
-
-int		dispatch;
-int		workcount;
-int		oldf;
-qboolean		pacifier;
-
-qboolean	threaded;
-
-/*
-=============
-GetThreadWork
-
-=============
-*/
-int	GetThreadWork (void)
-{
-	int	r;
-	int	f;
-
-	ThreadLock ();
-
-	if (dispatch == workcount)
-	{
-		ThreadUnlock ();
-		return -1;
-	}
-
-	f = 10*dispatch / workcount;
-	if (f != oldf)
-	{
-		oldf = f;
-		if (pacifier)
-		{
-			Sys_Printf ("%i...", f);
-			fflush( stdout );	/* ydnar */
-		}
-	}
-
-	r = dispatch;
-	dispatch++;
-	ThreadUnlock ();
-
-	return r;
-}
-
-
-void (*workfunction) (int);
-
-void ThreadWorkerFunction (int threadnum)
-{
-	int		work;
-
-	while (1)
-	{
-		work = GetThreadWork ();
-		if (work == -1)
-			break;
-//Sys_Printf ("thread %i, work %i\n", threadnum, work);
-		workfunction(work);
-	}
-}
-
-void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	if (numthreads == -1)
-		ThreadSetDefault ();
-	workfunction = func;
-  RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
-}
-
-
-/*
-===================================================================
-
-WIN32
-
-===================================================================
-*/
-#ifdef _WIN32
-
-#define	USED
-
-#include <windows.h>
-
-int		numthreads = -1;
-CRITICAL_SECTION		crit;
-static int enter;
-
-void ThreadSetDefault (void)
-{
-	SYSTEM_INFO info;
-
-	if (numthreads == -1)	// not set manually
-	{
-		GetSystemInfo (&info);
-		numthreads = info.dwNumberOfProcessors;
-		if (numthreads < 1 || numthreads > 32)
-			numthreads = 1;
-	}
-
-	Sys_Printf ("%i threads\n", numthreads);
-}
-
-
-void ThreadLock (void)
-{
-	if (!threaded)
-		return;
-	EnterCriticalSection (&crit);
-	if (enter)
-		Error ("Recursive ThreadLock\n");
-	enter = 1;
-}
-
-void ThreadUnlock (void)
-{
-	if (!threaded)
-		return;
-	if (!enter)
-		Error ("ThreadUnlock without lock\n");
-	enter = 0;
-	LeaveCriticalSection (&crit);
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		threadid[MAX_THREADS];
-	HANDLE	threadhandle[MAX_THREADS];
-	int		i;
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = true;
-
-	//
-	// run threads in parallel
-	//
-	InitializeCriticalSection (&crit);
-
-	if (numthreads == 1)
-	{	// use same thread
-		func (0);
-	}
-	else
-	{
-		for (i=0 ; i<numthreads ; i++)
-		{
-			threadhandle[i] = CreateThread(
-			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
-			   //0,		// DWORD cbStack,
-
-				/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
-				(4096 * 1024),
-
-			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
-			   (LPVOID)i,	// LPVOID lpvThreadParm,
-			   0,			//   DWORD fdwCreate,
-			   &threadid[i]);
-		}
-
-		for (i=0 ; i<numthreads ; i++)
-			WaitForSingleObject (threadhandle[i], INFINITE);
-	}
-	DeleteCriticalSection (&crit);
-
-	threaded = false;
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-/*
-===================================================================
-
-OSF1
-
-===================================================================
-*/
-
-#ifdef __osf__
-#define	USED
-
-int		numthreads = 4;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)	// not set manually
-	{
-		numthreads = 4;
-	}
-}
-
-
-#include <pthread.h>
-
-pthread_mutex_t	*my_mutex;
-
-void ThreadLock (void)
-{
-	if (my_mutex)
-		pthread_mutex_lock (my_mutex);
-}
-
-void ThreadUnlock (void)
-{
-	if (my_mutex)
-		pthread_mutex_unlock (my_mutex);
-}
-
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	pthread_t	work_threads[MAX_THREADS];
-	pthread_addr_t	status;
-	pthread_attr_t	attrib;
-	pthread_mutexattr_t	mattrib;
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = true;
-
-	if (pacifier)
-		setbuf (stdout, NULL);
-
-	if (!my_mutex)
-	{
-		my_mutex = safe_malloc (sizeof(*my_mutex));
-		if (pthread_mutexattr_create (&mattrib) == -1)
-			Error ("pthread_mutex_attr_create failed");
-		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
-			Error ("pthread_mutexattr_setkind_np failed");
-		if (pthread_mutex_init (my_mutex, mattrib) == -1)
-			Error ("pthread_mutex_init failed");
-	}
-
-	if (pthread_attr_create (&attrib) == -1)
-		Error ("pthread_attr_create failed");
-	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
-		Error ("pthread_attr_setstacksize failed");
-	
-	for (i=0 ; i<numthreads ; i++)
-	{
-  		if (pthread_create(&work_threads[i], attrib
-		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
-			Error ("pthread_create failed");
-	}
-		
-	for (i=0 ; i<numthreads ; i++)
-	{
-		if (pthread_join (work_threads[i], &status) == -1)
-			Error ("pthread_join failed");
-	}
-
-	threaded = false;
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-/*
-===================================================================
-
-IRIX
-
-===================================================================
-*/
-
-#ifdef _MIPS_ISA 
-#define	USED
-
-#include <task.h>
-#include <abi_mutex.h>
-#include <sys/types.h>
-#include <sys/prctl.h>
-
-
-int		numthreads = -1;
-abilock_t		lck;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)
-		numthreads = prctl(PR_MAXPPROCS);
-	Sys_Printf ("%i threads\n", numthreads);
-	usconfig (CONF_INITUSERS, numthreads);
-}
-
-
-void ThreadLock (void)
-{
-	spin_lock (&lck);
-}
-
-void ThreadUnlock (void)
-{
-	release_lock (&lck);
-}
-
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	int		pid[MAX_THREADS];
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = true;
-
-	if (pacifier)
-		setbuf (stdout, NULL);
-
-	init_lock (&lck);
-
-	for (i=0 ; i<numthreads-1 ; i++)
-	{
-		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
-			, NULL, 0x200000);		// 2 meg stacks
-		if (pid[i] == -1)
-		{
-			perror ("sproc");
-			Error ("sproc failed");
-		}
-	}
-		
-	func(i);
-			
-	for (i=0 ; i<numthreads-1 ; i++)
-		wait (NULL);
-
-	threaded = false;
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-
-/*
-=======================================================================
-
-  Linux pthreads
-
-=======================================================================
-*/
-
-#ifdef __linux__
-#define USED
-
-int numthreads = 4;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)	// not set manually
-	{
-    /* default to one thread, only multi-thread when specifically told to */
-		numthreads = 1;
-	}
-  if(numthreads > 1)
-    Sys_Printf("threads: %d\n", numthreads);
-}
-
-#include <pthread.h>
-
-typedef struct pt_mutex_s
-{
-  pthread_t       *owner;
-  pthread_mutex_t a_mutex;
-  pthread_cond_t  cond;
-  unsigned int    lock;
-} pt_mutex_t;
-
-pt_mutex_t global_lock;
-
-void ThreadLock(void)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-
-  if(!threaded)
-    return;
-
-  pthread_mutex_lock(&pt_mutex->a_mutex);
-  if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner)) 
-    pt_mutex->lock++;
-  else
-  {
-    if((!pt_mutex->owner) && (pt_mutex->lock == 0))
-    {
-      pt_mutex->owner = (pthread_t *)pthread_self();
-      pt_mutex->lock  = 1;
-    }
-    else
-    {
-      while(1)
-      {
-        pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
-        if((!pt_mutex->owner) && (pt_mutex->lock == 0))
-        {
-          pt_mutex->owner = (pthread_t *)pthread_self();
-          pt_mutex->lock  = 1;
-          break;
-        }
-      }
-    }
-  }
-  pthread_mutex_unlock(&pt_mutex->a_mutex);
-}
-
-void ThreadUnlock(void)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-  
-  if(!threaded)
-    return;
-
-  pthread_mutex_lock(&pt_mutex->a_mutex);
-  pt_mutex->lock--;
-  
-  if(pt_mutex->lock == 0)
-  {
-    pt_mutex->owner = NULL;
-    pthread_cond_signal(&pt_mutex->cond);
-  }
-  
-  pthread_mutex_unlock(&pt_mutex->a_mutex);
-}
-
-void recursive_mutex_init(pthread_mutexattr_t attribs)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-  
-  pt_mutex->owner = NULL;
-  if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
-    Error("pthread_mutex_init failed\n");
-  if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
-    Error("pthread_cond_init failed\n");
-  
-  pt_mutex->lock = 0;
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-  pthread_mutexattr_t         mattrib;
-  pthread_t work_threads[MAX_THREADS];
-  
-  int	  start, end;
-  int   i=0, status=0;
-  
-  start     = I_FloatTime ();
-  pacifier  = showpacifier;
-  
-  dispatch  = 0;
-  oldf      = -1;
-  workcount = workcnt;
-  
-  if(numthreads == 1)
-    func(0);
-  else
-  {    
-    threaded  = true;
-      
-    if(pacifier)
-      setbuf(stdout, NULL);
-
-    if(pthread_mutexattr_init(&mattrib) != 0)
-      Error("pthread_mutexattr_init failed");
-#if __GLIBC_MINOR__ == 1
-    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
-#else
-    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
-#endif
-      Error ("pthread_mutexattr_settype failed");
-    recursive_mutex_init(mattrib);
-
-    for (i=0 ; i<numthreads ; i++)
-    {
-      /* Default pthread attributes: joinable & non-realtime scheduling */
-      if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
-        Error("pthread_create failed");
-    }
-    for (i=0 ; i<numthreads ; i++)
-    {
-      if(pthread_join(work_threads[i], (void **)&status) != 0)
-        Error("pthread_join failed");
-    }
-    pthread_mutexattr_destroy(&mattrib);
-    threaded = false;
-  }
-  
-  end = I_FloatTime ();
-  if (pacifier)
-    Sys_Printf (" (%i)\n", end-start);
-}
-#endif // ifdef __linux__
-
-
-/*
-=======================================================================
-
-  SINGLE THREAD
-
-=======================================================================
-*/
-
-#ifndef USED
-
-int		numthreads = 1;
-
-void ThreadSetDefault (void)
-{
-	numthreads = 1;
-}
-
-void ThreadLock (void)
-{
-}
-
-void ThreadUnlock (void)
-{
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	int		start, end;
-
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	start = I_FloatTime (); 
-	func(0);
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef WIN32
+// The below define is necessary to use
+// pthreads extensions like pthread_mutexattr_settype
+#define _GNU_SOURCE
+#include <pthread.h>
+#endif
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include "her2_threads.h"
+
+#define	MAX_THREADS	64
+
+int		dispatch;
+int		workcount;
+int		oldf;
+qboolean		pacifier;
+
+qboolean	threaded;
+
+/*
+=============
+GetThreadWork
+
+=============
+*/
+int	GetThreadWork (void)
+{
+	int	r;
+	int	f;
+
+	ThreadLock ();
+
+	if (dispatch == workcount)
+	{
+		ThreadUnlock ();
+		return -1;
+	}
+
+	f = 10*dispatch / workcount;
+	if (f != oldf)
+	{
+		oldf = f;
+		if (pacifier)
+		{
+			Sys_Printf ("%i...", f);
+			fflush( stdout );	/* ydnar */
+		}
+	}
+
+	r = dispatch;
+	dispatch++;
+	ThreadUnlock ();
+
+	return r;
+}
+
+
+void (*workfunction) (int);
+
+void ThreadWorkerFunction (int threadnum)
+{
+	int		work;
+
+	while (1)
+	{
+		work = GetThreadWork ();
+		if (work == -1)
+			break;
+//Sys_Printf ("thread %i, work %i\n", threadnum, work);
+		workfunction(work);
+	}
+}
+
+void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	if (numthreads == -1)
+		ThreadSetDefault ();
+	workfunction = func;
+  RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
+}
+
+
+/*
+===================================================================
+
+WIN32
+
+===================================================================
+*/
+#ifdef _WIN32
+
+#define	USED
+
+#include <windows.h>
+
+int		numthreads = -1;
+CRITICAL_SECTION		crit;
+static int enter;
+
+void ThreadSetDefault (void)
+{
+	SYSTEM_INFO info;
+
+	if (numthreads == -1)	// not set manually
+	{
+		GetSystemInfo (&info);
+		numthreads = info.dwNumberOfProcessors;
+		if (numthreads < 1 || numthreads > 32)
+			numthreads = 1;
+	}
+
+	Sys_Printf ("%i threads\n", numthreads);
+}
+
+
+void ThreadLock (void)
+{
+	if (!threaded)
+		return;
+	EnterCriticalSection (&crit);
+	if (enter)
+		Error ("Recursive ThreadLock\n");
+	enter = 1;
+}
+
+void ThreadUnlock (void)
+{
+	if (!threaded)
+		return;
+	if (!enter)
+		Error ("ThreadUnlock without lock\n");
+	enter = 0;
+	LeaveCriticalSection (&crit);
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		threadid[MAX_THREADS];
+	HANDLE	threadhandle[MAX_THREADS];
+	int		i;
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = true;
+
+	//
+	// run threads in parallel
+	//
+	InitializeCriticalSection (&crit);
+
+	if (numthreads == 1)
+	{	// use same thread
+		func (0);
+	}
+	else
+	{
+		for (i=0 ; i<numthreads ; i++)
+		{
+			threadhandle[i] = CreateThread(
+			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
+			   //0,		// DWORD cbStack,
+
+				/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
+				(4096 * 1024),
+
+			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
+			   (LPVOID)i,	// LPVOID lpvThreadParm,
+			   0,			//   DWORD fdwCreate,
+			   &threadid[i]);
+		}
+
+		for (i=0 ; i<numthreads ; i++)
+			WaitForSingleObject (threadhandle[i], INFINITE);
+	}
+	DeleteCriticalSection (&crit);
+
+	threaded = false;
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+/*
+===================================================================
+
+OSF1
+
+===================================================================
+*/
+
+#ifdef __osf__
+#define	USED
+
+int		numthreads = 4;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)	// not set manually
+	{
+		numthreads = 4;
+	}
+}
+
+
+#include <pthread.h>
+
+pthread_mutex_t	*my_mutex;
+
+void ThreadLock (void)
+{
+	if (my_mutex)
+		pthread_mutex_lock (my_mutex);
+}
+
+void ThreadUnlock (void)
+{
+	if (my_mutex)
+		pthread_mutex_unlock (my_mutex);
+}
+
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	pthread_t	work_threads[MAX_THREADS];
+	pthread_addr_t	status;
+	pthread_attr_t	attrib;
+	pthread_mutexattr_t	mattrib;
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = true;
+
+	if (pacifier)
+		setbuf (stdout, NULL);
+
+	if (!my_mutex)
+	{
+		my_mutex = safe_malloc (sizeof(*my_mutex));
+		if (pthread_mutexattr_create (&mattrib) == -1)
+			Error ("pthread_mutex_attr_create failed");
+		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
+			Error ("pthread_mutexattr_setkind_np failed");
+		if (pthread_mutex_init (my_mutex, mattrib) == -1)
+			Error ("pthread_mutex_init failed");
+	}
+
+	if (pthread_attr_create (&attrib) == -1)
+		Error ("pthread_attr_create failed");
+	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
+		Error ("pthread_attr_setstacksize failed");
+	
+	for (i=0 ; i<numthreads ; i++)
+	{
+  		if (pthread_create(&work_threads[i], attrib
+		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
+			Error ("pthread_create failed");
+	}
+		
+	for (i=0 ; i<numthreads ; i++)
+	{
+		if (pthread_join (work_threads[i], &status) == -1)
+			Error ("pthread_join failed");
+	}
+
+	threaded = false;
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+/*
+===================================================================
+
+IRIX
+
+===================================================================
+*/
+
+#ifdef _MIPS_ISA 
+#define	USED
+
+#include <task.h>
+#include <abi_mutex.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+
+
+int		numthreads = -1;
+abilock_t		lck;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)
+		numthreads = prctl(PR_MAXPPROCS);
+	Sys_Printf ("%i threads\n", numthreads);
+	usconfig (CONF_INITUSERS, numthreads);
+}
+
+
+void ThreadLock (void)
+{
+	spin_lock (&lck);
+}
+
+void ThreadUnlock (void)
+{
+	release_lock (&lck);
+}
+
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	int		pid[MAX_THREADS];
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = true;
+
+	if (pacifier)
+		setbuf (stdout, NULL);
+
+	init_lock (&lck);
+
+	for (i=0 ; i<numthreads-1 ; i++)
+	{
+		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
+			, NULL, 0x200000);		// 2 meg stacks
+		if (pid[i] == -1)
+		{
+			perror ("sproc");
+			Error ("sproc failed");
+		}
+	}
+		
+	func(i);
+			
+	for (i=0 ; i<numthreads-1 ; i++)
+		wait (NULL);
+
+	threaded = false;
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+
+/*
+=======================================================================
+
+  Linux pthreads
+
+=======================================================================
+*/
+
+#ifdef __linux__
+#define USED
+
+int numthreads = 4;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)	// not set manually
+	{
+    /* default to one thread, only multi-thread when specifically told to */
+		numthreads = 1;
+	}
+  if(numthreads > 1)
+    Sys_Printf("threads: %d\n", numthreads);
+}
+
+#include <pthread.h>
+
+typedef struct pt_mutex_s
+{
+  pthread_t       *owner;
+  pthread_mutex_t a_mutex;
+  pthread_cond_t  cond;
+  unsigned int    lock;
+} pt_mutex_t;
+
+pt_mutex_t global_lock;
+
+void ThreadLock(void)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+
+  if(!threaded)
+    return;
+
+  pthread_mutex_lock(&pt_mutex->a_mutex);
+  if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner)) 
+    pt_mutex->lock++;
+  else
+  {
+    if((!pt_mutex->owner) && (pt_mutex->lock == 0))
+    {
+      pt_mutex->owner = (pthread_t *)pthread_self();
+      pt_mutex->lock  = 1;
+    }
+    else
+    {
+      while(1)
+      {
+        pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
+        if((!pt_mutex->owner) && (pt_mutex->lock == 0))
+        {
+          pt_mutex->owner = (pthread_t *)pthread_self();
+          pt_mutex->lock  = 1;
+          break;
+        }
+      }
+    }
+  }
+  pthread_mutex_unlock(&pt_mutex->a_mutex);
+}
+
+void ThreadUnlock(void)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+  
+  if(!threaded)
+    return;
+
+  pthread_mutex_lock(&pt_mutex->a_mutex);
+  pt_mutex->lock--;
+  
+  if(pt_mutex->lock == 0)
+  {
+    pt_mutex->owner = NULL;
+    pthread_cond_signal(&pt_mutex->cond);
+  }
+  
+  pthread_mutex_unlock(&pt_mutex->a_mutex);
+}
+
+void recursive_mutex_init(pthread_mutexattr_t attribs)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+  
+  pt_mutex->owner = NULL;
+  if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
+    Error("pthread_mutex_init failed\n");
+  if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
+    Error("pthread_cond_init failed\n");
+  
+  pt_mutex->lock = 0;
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+  pthread_mutexattr_t         mattrib;
+  pthread_t work_threads[MAX_THREADS];
+  
+  int	  start, end;
+  int   i=0, status=0;
+  
+  start     = I_FloatTime ();
+  pacifier  = showpacifier;
+  
+  dispatch  = 0;
+  oldf      = -1;
+  workcount = workcnt;
+  
+  if(numthreads == 1)
+    func(0);
+  else
+  {    
+    threaded  = true;
+      
+    if(pacifier)
+      setbuf(stdout, NULL);
+
+    if(pthread_mutexattr_init(&mattrib) != 0)
+      Error("pthread_mutexattr_init failed");
+#if __GLIBC_MINOR__ == 1
+    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
+#else
+    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
+#endif
+      Error ("pthread_mutexattr_settype failed");
+    recursive_mutex_init(mattrib);
+
+    for (i=0 ; i<numthreads ; i++)
+    {
+      /* Default pthread attributes: joinable & non-realtime scheduling */
+      if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
+        Error("pthread_create failed");
+    }
+    for (i=0 ; i<numthreads ; i++)
+    {
+      if(pthread_join(work_threads[i], (void **)&status) != 0)
+        Error("pthread_join failed");
+    }
+    pthread_mutexattr_destroy(&mattrib);
+    threaded = false;
+  }
+  
+  end = I_FloatTime ();
+  if (pacifier)
+    Sys_Printf (" (%i)\n", end-start);
+}
+#endif // ifdef __linux__
+
+
+/*
+=======================================================================
+
+  SINGLE THREAD
+
+=======================================================================
+*/
+
+#ifndef USED
+
+int		numthreads = 1;
+
+void ThreadSetDefault (void)
+{
+	numthreads = 1;
+}
+
+void ThreadLock (void)
+{
+}
+
+void ThreadUnlock (void)
+{
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	int		start, end;
+
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	start = I_FloatTime (); 
+	func(0);
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+#endif
diff --git a/tools/quake2/qdata_heretic2/common/token.c b/tools/quake2/qdata_heretic2/common/token.c
index 7fe8871f..911607cf 100644
--- a/tools/quake2/qdata_heretic2/common/token.c
+++ b/tools/quake2/qdata_heretic2/common/token.c
@@ -1,550 +1,550 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-//**************************************************************************
-//**
-//** token.c
-//**
-//**************************************************************************
-
-// HEADER FILES ------------------------------------------------------------
-
-#include "token.h"
-#include "inout.h"
-
-// MACROS ------------------------------------------------------------------
-
-// TYPES -------------------------------------------------------------------
-
-typedef enum
-{
-	CHR_EOF,
-	CHR_LETTER,
-	CHR_NUMBER,
-	CHR_QUOTE,
-	CHR_SPECIAL
-} chr_t;
-
-// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
-
-// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
-
-// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
-
-static void ProcessLetterToken(void);
-static void ProcessNumberToken(void);
-static void ProcessQuoteToken(void);
-static void ProcessSpecialToken(void);
-static qboolean CheckForKeyword(void);
-static void NextChr(void);
-
-// EXTERNAL DATA DECLARATIONS ----------------------------------------------
-
-// PUBLIC DATA DEFINITIONS -------------------------------------------------
-
-tokenType_t tk_Token;
-int tk_Line;
-int tk_IntNumber;
-float tk_FloatNumber;
-char *tk_String;
-char tk_SourceName[MAX_FILE_NAME_LENGTH];
-
-// PRIVATE DATA DEFINITIONS ------------------------------------------------
-
-static char Chr;
-static char *FileStart;
-static char *FilePtr;
-static char *FileEnd;
-static qboolean SourceOpen;
-static char ASCIIToChrCode[256];
-static char TokenStringBuffer[MAX_QUOTED_LENGTH];
-static qboolean IncLineNumber;
-static char TempBuffer[2048];
-
-static struct
-{
-	char *name;
-	tokenType_t token;
-} Keywords[] =
-{
-	"model",			TK_MODEL,
-	"mesh",				TK_MESH,
-	"vertices",			TK_VERTICES,
-	"edges",			TK_EDGES,
-	"position",			TK_POSITION,
-	"polygons",			TK_POLYGONS,
-	"nodes",			TK_NODES,
-	"rotation",			TK_ROTATION,
-	"scaling",			TK_SCALING,
-	"translation",		TK_TRANSLATION,
-	"vertex",			TK_VERTEX,
-	"HRCH",				TK_HRCH,
-	"Softimage",		TK_SOFTIMAGE,
-	"material",			TK_MATERIAL,
-	"spline",			TK_SPLINE,
-
-	"Named",			TK_C_NAMED,
-	"object",			TK_OBJECT,
-	"Tri",				TK_C_TRI,
-	"Vertices",			TK_C_VERTICES,
-	"Faces",			TK_C_FACES,
-	"Vertex",			TK_C_VERTEX,
-	"list",				TK_LIST,
-	"Face",				TK_C_FACE,
-
-	"Hexen",			TK_C_HEXEN,
-	"Triangles",		TK_C_TRIANGLES,
-	"Version",			TK_C_VERSION,
-	"faces",			TK_FACES,
-	"face",				TK_FACE,
-	"origin",			TK_ORIGIN,
-
-	"DK_clusters",		TK_CLUSTERS,
-	"DK_cluster_ncvs",	TK_NUM_CLUSTER_VERTICES,
-	"name",				TK_NAME,
-	"DK_cluster_name",	TK_CLUSTER_NAME,
-	"DK_cluster_state",	TK_CLUSTER_STATE,
-
-	"actor_data",		TK_ACTOR_DATA,
-	"uvTexture",		TK_UVTEXTURE,
-
-	NULL,				-1
-};
-
-static char *TokenNames[] =
-{
-	"<nothing>",
-	"<unknown_char>",
-	"<EOF>",
-	"<identifier>",
-	"<string>",
-	"<int_number>",
-	"<float_number>",
-	"(",
-	")",
-	"{",
-	"}",
-	"[",
-	"]",
-	":",
-	"mesh",
-	"model",
-	"nodes",
-	"rotation",
-	"scaling",
-	"translation",
-	"polygons",
-	"position",
-	"vertex",
-	"vertices",
-	"HRCH",
-	"Softimage"
-};
-
-// CODE --------------------------------------------------------------------
-
-//==========================================================================
-//
-// TK_Init
-//
-//==========================================================================
-
-void TK_Init(void)
-{
-	int i;
-
-	for(i = 0; i < 256; i++)
-	{
-		ASCIIToChrCode[i] = CHR_SPECIAL;
-	}
-	for(i = '0'; i <= '9'; i++)
-	{
-		ASCIIToChrCode[i] = CHR_NUMBER;
-	}
-	for(i = 'A'; i <= 'Z'; i++)
-	{
-		ASCIIToChrCode[i] = CHR_LETTER;
-	}
-	for(i = 'a'; i <= 'z'; i++)
-	{
-		ASCIIToChrCode[i] = CHR_LETTER;
-	}
-	ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
-	ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
-	ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
-	tk_String = TokenStringBuffer;
-	IncLineNumber = FALSE;
-	SourceOpen = FALSE;
-}
-
-//==========================================================================
-//
-// TK_OpenSource
-//
-//==========================================================================
-
-void TK_OpenSource(char *fileName)
-{
-	int size;
-
-	TK_CloseSource();
-	size = LoadFile(fileName, (void **)&FileStart);
-	strcpy(tk_SourceName, fileName);
-	SourceOpen = TRUE;
-	FileEnd = FileStart+size;
-	FilePtr = FileStart;
-	tk_Line = 1;
-	tk_Token = TK_NONE;
-	NextChr();
-}
-
-//==========================================================================
-//
-// TK_CloseSource
-//
-//==========================================================================
-
-void TK_CloseSource(void)
-{
-	if(SourceOpen)
-	{
-		free(FileStart);
-		SourceOpen = FALSE;
-	}
-}
-
-//==========================================================================
-//
-// TK_Fetch
-//
-//==========================================================================
-
-tokenType_t TK_Fetch(void)
-{
-	while(Chr == ASCII_SPACE)
-	{
-		NextChr();
-	}
-	if(Chr == '-')
-	{
-		ProcessNumberToken();
-	}
-	else switch(ASCIIToChrCode[(byte)Chr])
-	{
-		case CHR_EOF:
-			tk_Token = TK_EOF;
-			break;
-		case CHR_LETTER:
-			ProcessLetterToken();
-			break;
-		case CHR_NUMBER:
-			ProcessNumberToken();
-			break;
-		case CHR_QUOTE:
-			ProcessQuoteToken();
-			break;
-		default:
-			ProcessSpecialToken();
-			break;
-	}
-	return tk_Token;
-}
-
-//==========================================================================
-//
-// TK_Require
-//
-//==========================================================================
-
-void TK_Require(tokenType_t tokType)
-{
-	if(tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER)
-	{
-		tk_FloatNumber = (float)tk_IntNumber;
-		tk_Token = TK_FLOATNUMBER;
-		return;
-	}
-	if(tk_Token != tokType)
-	{
-		Error("File '%s', line %d:\nExpected '%s', found '%s'.\n",
-			tk_SourceName, tk_Line, TokenNames[tokType],
-			TokenNames[tk_Token]);
-	}
-}
-
-void TK_FetchRequire(tokenType_t tokType)
-{
-	TK_Fetch();
-	TK_Require(tokType);
-}
-
-tokenType_t TK_RequireFetch(tokenType_t tokType)
-{
-	TK_Require(tokType);
-	return TK_Fetch();
-}
-
-tokenType_t TK_FetchRequireFetch(tokenType_t tokType)
-{
-	TK_Fetch();
-	TK_Require(tokType);
-	return TK_Fetch();
-}
-
-tokenType_t TK_Beyond(tokenType_t tokType)
-{
-	while(tk_Token != tokType)
-	{
-		if(TK_Fetch() == TK_EOF)
-		{
-			Error("File '%s':\nCould not find token '%s'.\n",		// FIXME: TokenNames table not big enuff 
-				tk_SourceName, TokenNames[tokType]);
-		}
-	}
-	return TK_Fetch();
-}
-
-void TK_BeyondRequire(tokenType_t bTok, tokenType_t rTok)
-{
-	TK_Beyond(bTok);
-	TK_Require(rTok);
-}
-
-tokenType_t TK_Search(tokenType_t tokType)
-{
-	while(tk_Token != tokType)
-	{
-		if(TK_Fetch() == TK_EOF)
-		{
-			return TK_EOF;
-		}
-	}
-	return TK_Fetch();
-}
-
-tokenType_t TK_Get(tokenType_t tokType)
-{
-	while(tk_Token != tokType)
-	{
-		if(TK_Fetch() == TK_EOF)
-		{
-			Error("File '%s':\nCould not find token '%s'.\n",
-				tk_SourceName, TokenNames[tokType]);
-		}
-	}
-	return tk_Token;
-}
-
-//==========================================================================
-//
-// ProcessLetterToken
-//
-//==========================================================================
-
-static void ProcessLetterToken(void)
-{
-	int i;
-	char *text;
-
-	i = 0;
-	text = TokenStringBuffer;
-	while(ASCIIToChrCode[(byte)Chr] == CHR_LETTER
-		|| ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
-	{
-		if(++i == MAX_IDENTIFIER_LENGTH)
-		{
-			Error("File '%s', line %d:\nIdentifier too long.\n",
-				tk_SourceName, tk_Line);
-		}
-		*text++ = Chr;
-		NextChr();
-	}
-	*text = 0;
-	if(CheckForKeyword() == FALSE)
-	{
-		tk_Token = TK_IDENTIFIER;
-	}
-}
-
-//==========================================================================
-//
-// CheckForKeyword
-//
-//==========================================================================
-
-static qboolean CheckForKeyword(void)
-{
-	int i;
-
-	for(i = 0; Keywords[i].name != NULL; i++)
-	{
-		if(strcmp(tk_String, Keywords[i].name) == 0)
-		{
-			tk_Token = Keywords[i].token;
-			return TRUE;
-		}
-	}
-	return FALSE;
-}
-
-//==========================================================================
-//
-// ProcessNumberToken
-//
-//==========================================================================
-
-static void ProcessNumberToken(void)
-{
-	char *buffer;
-
-	buffer = TempBuffer;
-	*buffer++ = Chr;
-	NextChr();
-	while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
-	{
-		*buffer++ = Chr;
-		NextChr();
-	}
-	if(Chr == '.')
-	{ // Float
-		*buffer++ = Chr;
-		NextChr(); // Skip period
-		while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
-		{
-			*buffer++ = Chr;
-			NextChr();
-		}
-		*buffer = 0;
-		tk_FloatNumber = (float)atof(TempBuffer);
-		tk_Token = TK_FLOATNUMBER;
-		return;
-	}
-
-	// Integer
-	*buffer = 0;
-	tk_IntNumber = atoi(TempBuffer);
-	tk_Token = TK_INTNUMBER;
-}
-
-//==========================================================================
-//
-// ProcessQuoteToken
-//
-//==========================================================================
-
-static void ProcessQuoteToken(void)
-{
-	int i;
-	char *text;
-
-	i = 0;
-	text = TokenStringBuffer;
-	NextChr();
-	while(Chr != ASCII_QUOTE)
-	{
-		if(Chr == EOF_CHARACTER)
-		{
-			Error("File '%s', line %d:\n<EOF> inside string.\n",
-				tk_SourceName, tk_Line);
-		}
-		if(++i > MAX_QUOTED_LENGTH-1)
-		{
-			Error("File '%s', line %d:\nString literal too long.\n",
-				tk_SourceName, tk_Line);
-		}
-		*text++ = Chr;
-		NextChr();
-	}
-	*text = 0;
-	NextChr();
-	tk_Token = TK_STRING;
-}
-
-//==========================================================================
-//
-// ProcessSpecialToken
-//
-//==========================================================================
-
-static void ProcessSpecialToken(void)
-{
-	char c;
-
-	c = Chr;
-	NextChr();
-	switch(c)
-	{
-		case '(':
-			tk_Token = TK_LPAREN;
-			break;
-		case ')':
-			tk_Token = TK_RPAREN;
-			break;
-		case '{':
-			tk_Token = TK_LBRACE;
-			break;
-		case '}':
-			tk_Token = TK_RBRACE;
-			break;
-		case '[':
-			tk_Token = TK_LBRACKET;
-			break;
-		case ']':
-			tk_Token = TK_RBRACKET;
-			break;
-		case ':':
-			tk_Token = TK_COLON;
-			break;
-		default:
-			tk_Token = TK_UNKNOWNCHAR;
-			break;
-	}
-}
-
-//==========================================================================
-//
-// NextChr
-//
-//==========================================================================
-
-static void NextChr(void)
-{
-	if(FilePtr >= FileEnd)
-	{
-		Chr = EOF_CHARACTER;
-		return;
-	}
-	if(IncLineNumber == TRUE)
-	{
-		tk_Line++;
-		IncLineNumber = FALSE;
-	}
-	Chr = *FilePtr++;
-	if(Chr < ASCII_SPACE)
-	{
-		if(Chr == '\n')
-		{
-			IncLineNumber = TRUE;
-		}
-		Chr = ASCII_SPACE;
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+//**************************************************************************
+//**
+//** token.c
+//**
+//**************************************************************************
+
+// HEADER FILES ------------------------------------------------------------
+
+#include "token.h"
+#include "inout.h"
+
+// MACROS ------------------------------------------------------------------
+
+// TYPES -------------------------------------------------------------------
+
+typedef enum
+{
+	CHR_EOF,
+	CHR_LETTER,
+	CHR_NUMBER,
+	CHR_QUOTE,
+	CHR_SPECIAL
+} chr_t;
+
+// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
+
+// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
+
+// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
+
+static void ProcessLetterToken(void);
+static void ProcessNumberToken(void);
+static void ProcessQuoteToken(void);
+static void ProcessSpecialToken(void);
+static qboolean CheckForKeyword(void);
+static void NextChr(void);
+
+// EXTERNAL DATA DECLARATIONS ----------------------------------------------
+
+// PUBLIC DATA DEFINITIONS -------------------------------------------------
+
+tokenType_t tk_Token;
+int tk_Line;
+int tk_IntNumber;
+float tk_FloatNumber;
+char *tk_String;
+char tk_SourceName[MAX_FILE_NAME_LENGTH];
+
+// PRIVATE DATA DEFINITIONS ------------------------------------------------
+
+static char Chr;
+static char *FileStart;
+static char *FilePtr;
+static char *FileEnd;
+static qboolean SourceOpen;
+static char ASCIIToChrCode[256];
+static char TokenStringBuffer[MAX_QUOTED_LENGTH];
+static qboolean IncLineNumber;
+static char TempBuffer[2048];
+
+static struct
+{
+	char *name;
+	tokenType_t token;
+} Keywords[] =
+{
+	"model",			TK_MODEL,
+	"mesh",				TK_MESH,
+	"vertices",			TK_VERTICES,
+	"edges",			TK_EDGES,
+	"position",			TK_POSITION,
+	"polygons",			TK_POLYGONS,
+	"nodes",			TK_NODES,
+	"rotation",			TK_ROTATION,
+	"scaling",			TK_SCALING,
+	"translation",		TK_TRANSLATION,
+	"vertex",			TK_VERTEX,
+	"HRCH",				TK_HRCH,
+	"Softimage",		TK_SOFTIMAGE,
+	"material",			TK_MATERIAL,
+	"spline",			TK_SPLINE,
+
+	"Named",			TK_C_NAMED,
+	"object",			TK_OBJECT,
+	"Tri",				TK_C_TRI,
+	"Vertices",			TK_C_VERTICES,
+	"Faces",			TK_C_FACES,
+	"Vertex",			TK_C_VERTEX,
+	"list",				TK_LIST,
+	"Face",				TK_C_FACE,
+
+	"Hexen",			TK_C_HEXEN,
+	"Triangles",		TK_C_TRIANGLES,
+	"Version",			TK_C_VERSION,
+	"faces",			TK_FACES,
+	"face",				TK_FACE,
+	"origin",			TK_ORIGIN,
+
+	"DK_clusters",		TK_CLUSTERS,
+	"DK_cluster_ncvs",	TK_NUM_CLUSTER_VERTICES,
+	"name",				TK_NAME,
+	"DK_cluster_name",	TK_CLUSTER_NAME,
+	"DK_cluster_state",	TK_CLUSTER_STATE,
+
+	"actor_data",		TK_ACTOR_DATA,
+	"uvTexture",		TK_UVTEXTURE,
+
+	NULL,				-1
+};
+
+static char *TokenNames[] =
+{
+	"<nothing>",
+	"<unknown_char>",
+	"<EOF>",
+	"<identifier>",
+	"<string>",
+	"<int_number>",
+	"<float_number>",
+	"(",
+	")",
+	"{",
+	"}",
+	"[",
+	"]",
+	":",
+	"mesh",
+	"model",
+	"nodes",
+	"rotation",
+	"scaling",
+	"translation",
+	"polygons",
+	"position",
+	"vertex",
+	"vertices",
+	"HRCH",
+	"Softimage"
+};
+
+// CODE --------------------------------------------------------------------
+
+//==========================================================================
+//
+// TK_Init
+//
+//==========================================================================
+
+void TK_Init(void)
+{
+	int i;
+
+	for(i = 0; i < 256; i++)
+	{
+		ASCIIToChrCode[i] = CHR_SPECIAL;
+	}
+	for(i = '0'; i <= '9'; i++)
+	{
+		ASCIIToChrCode[i] = CHR_NUMBER;
+	}
+	for(i = 'A'; i <= 'Z'; i++)
+	{
+		ASCIIToChrCode[i] = CHR_LETTER;
+	}
+	for(i = 'a'; i <= 'z'; i++)
+	{
+		ASCIIToChrCode[i] = CHR_LETTER;
+	}
+	ASCIIToChrCode[ASCII_QUOTE] = CHR_QUOTE;
+	ASCIIToChrCode[ASCII_UNDERSCORE] = CHR_LETTER;
+	ASCIIToChrCode[EOF_CHARACTER] = CHR_EOF;
+	tk_String = TokenStringBuffer;
+	IncLineNumber = FALSE;
+	SourceOpen = FALSE;
+}
+
+//==========================================================================
+//
+// TK_OpenSource
+//
+//==========================================================================
+
+void TK_OpenSource(char *fileName)
+{
+	int size;
+
+	TK_CloseSource();
+	size = LoadFile(fileName, (void **)&FileStart);
+	strcpy(tk_SourceName, fileName);
+	SourceOpen = TRUE;
+	FileEnd = FileStart+size;
+	FilePtr = FileStart;
+	tk_Line = 1;
+	tk_Token = TK_NONE;
+	NextChr();
+}
+
+//==========================================================================
+//
+// TK_CloseSource
+//
+//==========================================================================
+
+void TK_CloseSource(void)
+{
+	if(SourceOpen)
+	{
+		free(FileStart);
+		SourceOpen = FALSE;
+	}
+}
+
+//==========================================================================
+//
+// TK_Fetch
+//
+//==========================================================================
+
+tokenType_t TK_Fetch(void)
+{
+	while(Chr == ASCII_SPACE)
+	{
+		NextChr();
+	}
+	if(Chr == '-')
+	{
+		ProcessNumberToken();
+	}
+	else switch(ASCIIToChrCode[(byte)Chr])
+	{
+		case CHR_EOF:
+			tk_Token = TK_EOF;
+			break;
+		case CHR_LETTER:
+			ProcessLetterToken();
+			break;
+		case CHR_NUMBER:
+			ProcessNumberToken();
+			break;
+		case CHR_QUOTE:
+			ProcessQuoteToken();
+			break;
+		default:
+			ProcessSpecialToken();
+			break;
+	}
+	return tk_Token;
+}
+
+//==========================================================================
+//
+// TK_Require
+//
+//==========================================================================
+
+void TK_Require(tokenType_t tokType)
+{
+	if(tokType == TK_FLOATNUMBER && tk_Token == TK_INTNUMBER)
+	{
+		tk_FloatNumber = (float)tk_IntNumber;
+		tk_Token = TK_FLOATNUMBER;
+		return;
+	}
+	if(tk_Token != tokType)
+	{
+		Error("File '%s', line %d:\nExpected '%s', found '%s'.\n",
+			tk_SourceName, tk_Line, TokenNames[tokType],
+			TokenNames[tk_Token]);
+	}
+}
+
+void TK_FetchRequire(tokenType_t tokType)
+{
+	TK_Fetch();
+	TK_Require(tokType);
+}
+
+tokenType_t TK_RequireFetch(tokenType_t tokType)
+{
+	TK_Require(tokType);
+	return TK_Fetch();
+}
+
+tokenType_t TK_FetchRequireFetch(tokenType_t tokType)
+{
+	TK_Fetch();
+	TK_Require(tokType);
+	return TK_Fetch();
+}
+
+tokenType_t TK_Beyond(tokenType_t tokType)
+{
+	while(tk_Token != tokType)
+	{
+		if(TK_Fetch() == TK_EOF)
+		{
+			Error("File '%s':\nCould not find token '%s'.\n",		// FIXME: TokenNames table not big enuff 
+				tk_SourceName, TokenNames[tokType]);
+		}
+	}
+	return TK_Fetch();
+}
+
+void TK_BeyondRequire(tokenType_t bTok, tokenType_t rTok)
+{
+	TK_Beyond(bTok);
+	TK_Require(rTok);
+}
+
+tokenType_t TK_Search(tokenType_t tokType)
+{
+	while(tk_Token != tokType)
+	{
+		if(TK_Fetch() == TK_EOF)
+		{
+			return TK_EOF;
+		}
+	}
+	return TK_Fetch();
+}
+
+tokenType_t TK_Get(tokenType_t tokType)
+{
+	while(tk_Token != tokType)
+	{
+		if(TK_Fetch() == TK_EOF)
+		{
+			Error("File '%s':\nCould not find token '%s'.\n",
+				tk_SourceName, TokenNames[tokType]);
+		}
+	}
+	return tk_Token;
+}
+
+//==========================================================================
+//
+// ProcessLetterToken
+//
+//==========================================================================
+
+static void ProcessLetterToken(void)
+{
+	int i;
+	char *text;
+
+	i = 0;
+	text = TokenStringBuffer;
+	while(ASCIIToChrCode[(byte)Chr] == CHR_LETTER
+		|| ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
+	{
+		if(++i == MAX_IDENTIFIER_LENGTH)
+		{
+			Error("File '%s', line %d:\nIdentifier too long.\n",
+				tk_SourceName, tk_Line);
+		}
+		*text++ = Chr;
+		NextChr();
+	}
+	*text = 0;
+	if(CheckForKeyword() == FALSE)
+	{
+		tk_Token = TK_IDENTIFIER;
+	}
+}
+
+//==========================================================================
+//
+// CheckForKeyword
+//
+//==========================================================================
+
+static qboolean CheckForKeyword(void)
+{
+	int i;
+
+	for(i = 0; Keywords[i].name != NULL; i++)
+	{
+		if(strcmp(tk_String, Keywords[i].name) == 0)
+		{
+			tk_Token = Keywords[i].token;
+			return TRUE;
+		}
+	}
+	return FALSE;
+}
+
+//==========================================================================
+//
+// ProcessNumberToken
+//
+//==========================================================================
+
+static void ProcessNumberToken(void)
+{
+	char *buffer;
+
+	buffer = TempBuffer;
+	*buffer++ = Chr;
+	NextChr();
+	while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
+	{
+		*buffer++ = Chr;
+		NextChr();
+	}
+	if(Chr == '.')
+	{ // Float
+		*buffer++ = Chr;
+		NextChr(); // Skip period
+		while(ASCIIToChrCode[(byte)Chr] == CHR_NUMBER)
+		{
+			*buffer++ = Chr;
+			NextChr();
+		}
+		*buffer = 0;
+		tk_FloatNumber = (float)atof(TempBuffer);
+		tk_Token = TK_FLOATNUMBER;
+		return;
+	}
+
+	// Integer
+	*buffer = 0;
+	tk_IntNumber = atoi(TempBuffer);
+	tk_Token = TK_INTNUMBER;
+}
+
+//==========================================================================
+//
+// ProcessQuoteToken
+//
+//==========================================================================
+
+static void ProcessQuoteToken(void)
+{
+	int i;
+	char *text;
+
+	i = 0;
+	text = TokenStringBuffer;
+	NextChr();
+	while(Chr != ASCII_QUOTE)
+	{
+		if(Chr == EOF_CHARACTER)
+		{
+			Error("File '%s', line %d:\n<EOF> inside string.\n",
+				tk_SourceName, tk_Line);
+		}
+		if(++i > MAX_QUOTED_LENGTH-1)
+		{
+			Error("File '%s', line %d:\nString literal too long.\n",
+				tk_SourceName, tk_Line);
+		}
+		*text++ = Chr;
+		NextChr();
+	}
+	*text = 0;
+	NextChr();
+	tk_Token = TK_STRING;
+}
+
+//==========================================================================
+//
+// ProcessSpecialToken
+//
+//==========================================================================
+
+static void ProcessSpecialToken(void)
+{
+	char c;
+
+	c = Chr;
+	NextChr();
+	switch(c)
+	{
+		case '(':
+			tk_Token = TK_LPAREN;
+			break;
+		case ')':
+			tk_Token = TK_RPAREN;
+			break;
+		case '{':
+			tk_Token = TK_LBRACE;
+			break;
+		case '}':
+			tk_Token = TK_RBRACE;
+			break;
+		case '[':
+			tk_Token = TK_LBRACKET;
+			break;
+		case ']':
+			tk_Token = TK_RBRACKET;
+			break;
+		case ':':
+			tk_Token = TK_COLON;
+			break;
+		default:
+			tk_Token = TK_UNKNOWNCHAR;
+			break;
+	}
+}
+
+//==========================================================================
+//
+// NextChr
+//
+//==========================================================================
+
+static void NextChr(void)
+{
+	if(FilePtr >= FileEnd)
+	{
+		Chr = EOF_CHARACTER;
+		return;
+	}
+	if(IncLineNumber == TRUE)
+	{
+		tk_Line++;
+		IncLineNumber = FALSE;
+	}
+	Chr = *FilePtr++;
+	if(Chr < ASCII_SPACE)
+	{
+		if(Chr == '\n')
+		{
+			IncLineNumber = TRUE;
+		}
+		Chr = ASCII_SPACE;
+	}
+}
diff --git a/tools/quake2/qdata_heretic2/common/token.h b/tools/quake2/qdata_heretic2/common/token.h
index e6aab853..ab0e0de5 100644
--- a/tools/quake2/qdata_heretic2/common/token.h
+++ b/tools/quake2/qdata_heretic2/common/token.h
@@ -1,132 +1,132 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-//**************************************************************************
-//**
-//** token.h
-//**
-//**************************************************************************
-
-#ifndef __TOKEN_H__
-#define __TOKEN_H__
-
-#include "cmdlib.h"
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-#ifndef FALSE
-#define FALSE 0
-#endif
-#ifndef YES
-#define YES 1
-#endif
-#ifndef NO
-#define NO 0
-#endif
-#define ASCII_SPACE 32
-#define ASCII_QUOTE 34
-#define ASCII_UNDERSCORE 95
-#define EOF_CHARACTER 127
-#define MAX_IDENTIFIER_LENGTH 64
-#define MAX_QUOTED_LENGTH 1024
-#define MAX_FILE_NAME_LENGTH 1024
-
-typedef enum
-{
-	TK_NONE,
-	TK_UNKNOWNCHAR,
-	TK_EOF,
-	TK_IDENTIFIER,			// VALUE: (char *) tk_String
-	TK_STRING,				// VALUE: (char *) tk_String
-	TK_INTNUMBER,			// VALUE: (int) tk_IntNumber
-	TK_FLOATNUMBER,			// VALUE: (float) tk_FloatNumber
-	TK_LPAREN,
-	TK_RPAREN,
-	TK_LBRACE,
-	TK_RBRACE,				// 10
-	TK_LBRACKET,			
-	TK_RBRACKET,
-	TK_COLON,
-	TK_MESH,
-	TK_MODEL,				// 15
-	TK_NODES,
-	TK_ROTATION,
-	TK_SCALING,
-	TK_TRANSLATION,
-	TK_POLYGONS,			// 20
-	TK_POSITION,
-	TK_VERTEX,
-	TK_VERTICES,
-	TK_EDGES,
-	TK_HRCH,				// 25
-	TK_SOFTIMAGE,
-	TK_MATERIAL,
-	TK_SPLINE,				// 28
-
-	TK_C_NAMED,
-	TK_OBJECT,				// 30
-	TK_C_TRI,				
-	TK_C_VERTICES,
-	TK_C_FACES,
-	TK_C_VERTEX,
-	TK_LIST,				// 35
-	TK_C_FACE,				
-
-	TK_C_HEXEN,
-	TK_C_TRIANGLES,
-	TK_C_VERSION,
-	TK_FACES,				// 40
-	TK_FACE,				
-	TK_ORIGIN,
-
-	TK_CLUSTERS,
-	TK_NUM_CLUSTER_VERTICES,
-	TK_NAME,				// 45
-	TK_CLUSTER_NAME,		
-	TK_CLUSTER_STATE,
-
-	TK_ACTOR_DATA,
-	TK_UVTEXTURE,
-} tokenType_t;
-
-void TK_Init(void);
-void TK_OpenSource(char *fileName);
-void TK_CloseSource(void);
-tokenType_t TK_Fetch(void);
-void TK_Require(tokenType_t tokType);
-void TK_FetchRequire(tokenType_t tokType);
-tokenType_t TK_RequireFetch(tokenType_t tokType);
-tokenType_t TK_FetchRequireFetch(tokenType_t tokType);
-tokenType_t TK_Beyond(tokenType_t tokType);
-void TK_BeyondRequire(tokenType_t bTok, tokenType_t rTok);
-tokenType_t TK_Search(tokenType_t tokType);
-tokenType_t TK_Get(tokenType_t tokType);
-
-extern tokenType_t tk_Token;
-extern int tk_Line;
-extern int tk_IntNumber;
-extern float tk_FloatNumber;
-extern char *tk_String;
-extern char tk_SourceName[MAX_FILE_NAME_LENGTH];
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+//**************************************************************************
+//**
+//** token.h
+//**
+//**************************************************************************
+
+#ifndef __TOKEN_H__
+#define __TOKEN_H__
+
+#include "cmdlib.h"
+
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef YES
+#define YES 1
+#endif
+#ifndef NO
+#define NO 0
+#endif
+#define ASCII_SPACE 32
+#define ASCII_QUOTE 34
+#define ASCII_UNDERSCORE 95
+#define EOF_CHARACTER 127
+#define MAX_IDENTIFIER_LENGTH 64
+#define MAX_QUOTED_LENGTH 1024
+#define MAX_FILE_NAME_LENGTH 1024
+
+typedef enum
+{
+	TK_NONE,
+	TK_UNKNOWNCHAR,
+	TK_EOF,
+	TK_IDENTIFIER,			// VALUE: (char *) tk_String
+	TK_STRING,				// VALUE: (char *) tk_String
+	TK_INTNUMBER,			// VALUE: (int) tk_IntNumber
+	TK_FLOATNUMBER,			// VALUE: (float) tk_FloatNumber
+	TK_LPAREN,
+	TK_RPAREN,
+	TK_LBRACE,
+	TK_RBRACE,				// 10
+	TK_LBRACKET,			
+	TK_RBRACKET,
+	TK_COLON,
+	TK_MESH,
+	TK_MODEL,				// 15
+	TK_NODES,
+	TK_ROTATION,
+	TK_SCALING,
+	TK_TRANSLATION,
+	TK_POLYGONS,			// 20
+	TK_POSITION,
+	TK_VERTEX,
+	TK_VERTICES,
+	TK_EDGES,
+	TK_HRCH,				// 25
+	TK_SOFTIMAGE,
+	TK_MATERIAL,
+	TK_SPLINE,				// 28
+
+	TK_C_NAMED,
+	TK_OBJECT,				// 30
+	TK_C_TRI,				
+	TK_C_VERTICES,
+	TK_C_FACES,
+	TK_C_VERTEX,
+	TK_LIST,				// 35
+	TK_C_FACE,				
+
+	TK_C_HEXEN,
+	TK_C_TRIANGLES,
+	TK_C_VERSION,
+	TK_FACES,				// 40
+	TK_FACE,				
+	TK_ORIGIN,
+
+	TK_CLUSTERS,
+	TK_NUM_CLUSTER_VERTICES,
+	TK_NAME,				// 45
+	TK_CLUSTER_NAME,		
+	TK_CLUSTER_STATE,
+
+	TK_ACTOR_DATA,
+	TK_UVTEXTURE,
+} tokenType_t;
+
+void TK_Init(void);
+void TK_OpenSource(char *fileName);
+void TK_CloseSource(void);
+tokenType_t TK_Fetch(void);
+void TK_Require(tokenType_t tokType);
+void TK_FetchRequire(tokenType_t tokType);
+tokenType_t TK_RequireFetch(tokenType_t tokType);
+tokenType_t TK_FetchRequireFetch(tokenType_t tokType);
+tokenType_t TK_Beyond(tokenType_t tokType);
+void TK_BeyondRequire(tokenType_t bTok, tokenType_t rTok);
+tokenType_t TK_Search(tokenType_t tokType);
+tokenType_t TK_Get(tokenType_t tokType);
+
+extern tokenType_t tk_Token;
+extern int tk_Line;
+extern int tk_IntNumber;
+extern float tk_FloatNumber;
+extern char *tk_String;
+extern char tk_SourceName[MAX_FILE_NAME_LENGTH];
+
+#endif
diff --git a/tools/quake2/qdata_heretic2/common/trilib.c b/tools/quake2/qdata_heretic2/common/trilib.c
index 4ed79051..7a0f412f 100644
--- a/tools/quake2/qdata_heretic2/common/trilib.c
+++ b/tools/quake2/qdata_heretic2/common/trilib.c
@@ -1,1077 +1,1077 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// trilib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "inout.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "token.h"
-#include "l3dslib.h"
-#include "fmodel.h"
-#if 1
-#include "qd_skeletons.h"
-#endif
-
-// on disk representation of a face
-#define	FLOAT_START	99999.0
-#define	FLOAT_END	-FLOAT_START
-#define MAGIC       123322
-#ifndef M_PI
-  #define M_PI		3.14159265
-#endif
-
-float FixHTRRotateX = 0.0;
-float FixHTRRotateY = 0.0;
-float FixHTRRotateZ = 0.0;
-float FixHTRTranslateX = 0.0;
-float FixHTRTranslateY = 0.0;
-float FixHTRTranslateZ = 0.0;
-
-//#define NOISY 1
-
-typedef struct {
-	float v[3];
-} vector;
-
-typedef struct
-{
-	vector n;    /* normal */
-	vector p;    /* point */
-	vector c;    /* color */
-	float  u;    /* u */
-	float  v;    /* v */
-} aliaspoint_t;
-
-typedef struct {
-	aliaspoint_t	pt[3];
-} tf_triangle;
-
-
-void ByteSwapTri (tf_triangle *tri)
-{
-	int		i;
-	
-	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
-	{
-		((int *)tri)[i] = BigLong (((int *)tri)[i]);
-	}
-}
-
-void LoadTRI (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes)
-{
-	FILE        *input;
-	float       start;
-	char        name[256], tex[256];
-	int         i, count, magic;
-	tf_triangle	tri;
-	triangle_t	*ptri;
-	int			iLevel;
-	int			exitpattern;
-	float		t;
-
-	if (nodesList)
-	{
-		*num_mesh_nodes = 0;
-		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-	}
-
-	t = -FLOAT_START;
-	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
-	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
-	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
-	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
-
-	if ((input = fopen(filename, "rb")) == 0)
-		Error ("reader: could not open file '%s'", filename);
-
-	iLevel = 0;
-
-	fread(&magic, sizeof(int), 1, input);
-	if (BigLong(magic) != MAGIC)
-		Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
-
-	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
-
-	*pptri = ptri;
-
-	while (feof(input) == 0) {
-		if (fread(&start,  sizeof(float), 1, input) < 1)
-			break;
-		*(int *)&start = BigLong(*(int *)&start);
-		if (*(int *)&start != exitpattern)
-		{
-			if (start == FLOAT_START) {
-				/* Start of an object or group of objects. */
-				i = -1;
-				do {
-					/* There are probably better ways to read a string from */
-					/* a file, but this does allow you to do error checking */
-					/* (which I'm not doing) on a per character basis.      */
-					++i;
-					fread( &(name[i]), sizeof( char ), 1, input);
-				} while( name[i] != '\0' );
-	
-//				indent();
-//				fprintf(stdout,"OBJECT START: %s\n",name);
-				fread( &count, sizeof(int), 1, input);
-				count = BigLong(count);
-				++iLevel;
-				if (count != 0) {
-//					indent();
-//					fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
-	
-					i = -1;
-					do {
-						++i;
-						fread( &(tex[i]), sizeof( char ), 1, input);
-					} while( tex[i] != '\0' );
-	
-//					indent();
-//					fprintf(stdout,"  Object texture name: '%s'\n",tex);
-				}
-	
-				/* Else (count == 0) this is the start of a group, and */
-				/* no texture name is present. */
-			}
-			else if (start == FLOAT_END) {
-				/* End of an object or group. Yes, the name should be */
-				/* obvious from context, but it is in here just to be */
-				/* safe and to provide a little extra information for */
-				/* those who do not wish to write a recursive reader. */
-				/* Mia culpa. */
-				--iLevel;
-				i = -1;
-				do {
-					++i;
-					fread( &(name[i]), sizeof( char ), 1, input);
-				} while( name[i] != '\0' );
-	
-//				indent();
-//				fprintf(stdout,"OBJECT END: %s\n",name);
-				continue;
-			}
-		}
-
-//
-// read the triangles
-//		
-		for (i = 0; i < count; ++i) {
-			int		j;
-
-			fread( &tri, sizeof(tf_triangle), 1, input );
-			ByteSwapTri (&tri);
-			for (j=0 ; j<3 ; j++)
-			{
-				int		k;
-
-				for (k=0 ; k<3 ; k++)
-				{
-					ptri->verts[j][k] = tri.pt[j].p.v[k];
-				}
-			}
-
-			ptri++;
-
-			if ((ptri - *pptri) >= MAXTRIANGLES)
-				Error ("Error: too many triangles; increase MAXTRIANGLES\n");
-		}
-	}
-
-	*numtriangles = ptri - *pptri;
-
-	fclose (input);
-
-	DefaultNodesList(nodesList,num_mesh_nodes,numtriangles);
-}
-
-
-//==========================================================================
-//
-// LoadHRC
-//
-//==========================================================================
-
-float	scaling[3];
-float	rotation[3];
-float	translation[3];
-static char		*hrc_name;
-
-struct
-{
-	float v[3];
-} vList[8192];
-
-void HandleHRCModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
-						   int ActiveNode, int Depth, int numVerts)
-{
-	void ReadHRCClusterList(mesh_node_t *meshNode, int baseIndex);
-
-	int			i, j;
-	int			vertexCount;
-	int			triCount;
-	triangle_t	*tList;
-	mesh_node_t *meshNode;
-	float		x, y, z;
-	float		x2, y2, z2;
-	float		rx, ry, rz;
-	tokenType_t nextToken;
-	float		orig_scaling[3];
-	float		orig_rotation[3];
-	float		orig_translation[3];
-	int			start_tri;
-	int			pos,bit;
-	int			vertIndexBase;
-
-	// Update Node Info
-	if (nodesList)
-	{
-		TK_BeyondRequire(TK_NAME, TK_STRING);
-
-		if (Depth == 0 || tk_String[0] == '_')
-		{	// Root
-			ActiveNode = *num_mesh_nodes;
-			(*num_mesh_nodes)++;
-			if ((*num_mesh_nodes) > MAX_FM_MESH_NODES)
-			{
-				Error("Too many mesh nodes in file %s\n", hrc_name);
-			}
-			meshNode = &(*nodesList)[ActiveNode];
-
-//			memset(meshNode, 0, sizeof(mesh_node_t));
-			strcpy(meshNode->name, tk_String);
-
-			memset(meshNode->tris, 0, sizeof(meshNode->tris));
-			memset(meshNode->verts, 0, sizeof(meshNode->verts));
-
-			meshNode->start_glcmds = 0;
-			meshNode->num_glcmds = 0;
-			vertIndexBase = 0;
-		}
-		else
-		{	// Childs under the children
-			meshNode = &(*nodesList)[ActiveNode];
-			vertIndexBase = numVerts;
-		}
-	}
-	else 
-	{
-		meshNode = NULL;
-	}
-
-
-	// Get the scaling, rotation, and translation values
-	TK_Beyond(TK_SCALING);
-	for(i = 0; i < 3; i++)
-	{
-		orig_scaling[i] = scaling[i];
-
-		TK_Require(TK_FLOATNUMBER);
-		scaling[i] *= tk_FloatNumber;
-
-		TK_Fetch();
-	}
-	TK_Beyond(TK_ROTATION);
-	for(i = 0; i < 3; i++)
-	{
-		orig_rotation[i] = rotation[i];
-
-		TK_Require(TK_FLOATNUMBER);
-		rotation[i] = tk_FloatNumber;
-
-		TK_Fetch();
-	}
-	TK_Beyond(TK_TRANSLATION);
-	for(i = 0; i < 3; i++)
-	{
-		orig_translation[i] = translation[i];
-
-		TK_Require(TK_FLOATNUMBER);
-		translation[i] += tk_FloatNumber;
-
-		TK_Fetch();
-	}
-
-	rx = ((rotation[0]-90.0)/360.0)*2.0*M_PI;
-	ry = (rotation[2]/360.0)*2.0*M_PI;
-	rz = (rotation[1]/360.0)*2.0*M_PI;
-
-	// rjr - might not work if there an item doesn't have a mesh
-	nextToken = tk_Token;
-	if (nextToken == TK_ACTOR_DATA)
-	{
-		while (nextToken != TK_MODEL && nextToken != TK_RBRACE)
-		{
-			nextToken = TK_Fetch();
-		}
-	}
-
-	while (nextToken == TK_SPLINE)
-	{	// spline node has two right braces
-		nextToken = TK_Beyond(TK_RBRACE);
-		nextToken = TK_Beyond(TK_RBRACE);
-	}
-
-	while (nextToken == TK_MATERIAL)
-	{
-		nextToken = TK_Beyond(TK_RBRACE);
-	}
-
-	while(nextToken == TK_MODEL)
-	{
-		HandleHRCModel(triList,triangleCount,nodesList,num_mesh_nodes,ActiveNode, Depth+1, 0);
-
-		nextToken = TK_Fetch();
-	}
-
-	if (nextToken == TK_MESH)
-	{
-		// Get all the tri and vertex info
-		TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
-		vertexCount = tk_IntNumber;
-		for(i = 0; i < vertexCount; i++)
-		{
-			TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
-			if(tk_IntNumber != i)
-			{
-				Error("File '%s', line %d:\nVertex index mismatch.\n",
-					tk_SourceName, tk_Line);
-			}
-			TK_Beyond(TK_POSITION);
-			// Apply the scaling, rotation, and translation in the order
-			// specified in the HRC file.  This could be wrong.
-			TK_Require(TK_FLOATNUMBER);
-			x = tk_FloatNumber*scaling[0];
-			TK_FetchRequire(TK_FLOATNUMBER);
-			y = tk_FloatNumber*scaling[1];
-			TK_FetchRequire(TK_FLOATNUMBER);
-			z = tk_FloatNumber*scaling[2];
-
-			y2 = y*cos(rx)+z*sin(rx);
-			z2 = -y*sin(rx)+z*cos(rx);
-			y = y2;
-			z = z2;
-
-			x2 = x*cos(ry)-z*sin(ry);
-			z2 = x*sin(ry)+z*cos(ry);
-			x = x2;
-			z = z2;
-
-			x2 = x*cos(rz)+y*sin(rz);
-			y2 = -x*sin(rz)+y*cos(rz);
-			x = x2;
-			y = y2;
-
-			vList[i].v[0] = x+translation[0];
-			vList[i].v[1] = y-translation[2];
-			vList[i].v[2] = z+translation[1];
-		}
-		TK_BeyondRequire(TK_POLYGONS, TK_INTNUMBER);
-		triCount = tk_IntNumber;
-		if(triCount >= MAXTRIANGLES)
-		{
-			Error("Too many triangles in file %s\n", hrc_name);
-		}
-
-		start_tri = *triangleCount;
-		*triangleCount += triCount;
-
-		tList = *triList;
-
-		for(i = 0; i < triCount; i++)
-		{
-			if (meshNode)
-			{	// Update the node
-				pos = (i + start_tri) >> 3;
-				bit = 1 << ((i + start_tri) & 7 );
-				meshNode->tris[pos] |= bit;
-			}
-
-			TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
-			if(tk_IntNumber != i)
-			{
-				Error("File '%s', line %d:\nTriangle index mismatch.\n",
-					tk_SourceName, tk_Line);
-			}
-			TK_BeyondRequire(TK_NODES, TK_INTNUMBER);
-			if(tk_IntNumber != 3)
-			{
-				Error("File '%s', line %d:\nBad polygon vertex count: %d.",
-					tk_SourceName, tk_Line, tk_IntNumber);
-			}
-			tList[i+start_tri].HasUV = true;
-			for(j = 0; j < 3; j++)
-			{
-				TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
-				if(tk_IntNumber != j)
-				{
-					Error("File '%s', line %d:\nTriangle vertex index"
-						" mismatch.  %d should be %d\n", tk_SourceName, tk_Line,
-						tk_IntNumber, j);
-				}
-				TK_BeyondRequire(TK_VERTEX, TK_INTNUMBER);
-
-				tList[i+start_tri].verts[2-j][0] = vList[tk_IntNumber].v[0];
-				tList[i+start_tri].verts[2-j][1] = vList[tk_IntNumber].v[1];
-				tList[i+start_tri].verts[2-j][2] = vList[tk_IntNumber].v[2];
-#if 1
-				tList[i+start_tri].indicies[2-j] = tk_IntNumber+vertIndexBase;
-#endif
-				TK_BeyondRequire(TK_UVTEXTURE, TK_FLOATNUMBER);
-				tList[i+start_tri].uv[2-j][0] = tk_FloatNumber;
-				TK_Fetch();
-				TK_Require(TK_FLOATNUMBER);
-				tList[i+start_tri].uv[2-j][1] = tk_FloatNumber;
-			}
-
-	/*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-				"  v2: %f, %f, %f\n", i,
-				tList[i].verts[0][0],
-				tList[i].verts[0][1],
-				tList[i].verts[0][2],
-				tList[i].verts[1][0],
-				tList[i].verts[1][1],
-				tList[i].verts[1][2],
-				tList[i].verts[2][0],
-				tList[i].verts[2][1],
-				tList[i].verts[2][2]);
-	*/
-		}
-
-		TK_Beyond(TK_RBRACE);
-		TK_Beyond(TK_RBRACE);
-
-		if (tk_Token == TK_EDGES)
-		{
-		//	TK_Beyond(TK_EDGES);
-			TK_Beyond(TK_RBRACE);
-		}
-
-		scaling[0] = scaling[1] = scaling[2] = 1.0;
-	//	rotation[0] = rotation[1] = rotation[2] = 0.0;
-	//	translation[0] = translation[1] = translation[2] = 0.0;
-
-		// See if there are any other models belonging to this node
-
-#if 1
-		TK_Fetch();
-
-		nextToken = tk_Token;
-		if(nextToken == TK_CLUSTERS)
-		{
-			if(g_skelModel.clustered == -1)
-			{
-				ReadHRCClusterList(meshNode, vertIndexBase);
-			}
-			else
-			{
-				nextToken = TK_Get(TK_CLUSTER_NAME);
-
-				while (nextToken == TK_CLUSTER_NAME)
-				{
-					TK_BeyondRequire(TK_CLUSTER_STATE, TK_INTNUMBER);
-					nextToken = TK_Fetch();
-				}
-			}
-
-			// one right brace follow the list of clusters
-			nextToken = TK_Beyond(TK_RBRACE);
-		}
-		else
-		{
-			if(g_skelModel.clustered == -1 && !vertIndexBase)
-			{
-				meshNode->clustered = false;
-			}
-		}
-#endif
-
-		nextToken = tk_Token;
-		if(nextToken == TK_SPLINE)
-		{
-			while (nextToken == TK_SPLINE)
-			{	// spline node has two right braces
-				nextToken = TK_Beyond(TK_RBRACE);
-				nextToken = TK_Beyond(TK_RBRACE);
-			}
-
-			nextToken = TK_Beyond(TK_RBRACE);
-		}
-
-		while (nextToken == TK_MATERIAL)
-		{
-			nextToken = TK_Beyond(TK_RBRACE);
-		}
-
-		while(nextToken == TK_MODEL)
-		{
-			HandleHRCModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase);
-
-			nextToken = TK_Fetch();
-		}
-	}
-
-	for(i=0;i<3;i++)
-	{
-		scaling[i] = orig_scaling[i];
-		rotation[i] = orig_rotation[i];
-		translation[i] = orig_translation[i];
-	}
-}
-
-static void LoadHRC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
-{
-	if (nodesList)
-	{
-		*num_mesh_nodes = 0;
-
-		if(!*nodesList)
-		{
-			*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-		}
-	}
-
-	hrc_name = fileName;
-
-	scaling[0] = scaling[1] = scaling[2] = 1.0;
-	rotation[0] = rotation[1] = rotation[2] = 0.0;
-	translation[0] = translation[1] = translation[2] = 0.0;
-
-	*triangleCount = 0;
-	*triList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
-	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-
-	// prime it
-	TK_Beyond(TK_MODEL);
-
-	HandleHRCModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0);
-	TK_CloseSource();
-}
-
-//==========================================================================
-//
-// LoadHTR
-//
-//==========================================================================
-/*
-static int Version2;
-
-void HandleHTRModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
-						   int ActiveNode, int Depth, int numVerts)
-{
-	int			i, j;
-	int			vertexCount;
-	int			vertexNum;
-	int			triCount;
-	float		origin[3];
-	triangle_t	*tList;
-	float		x, y, z;
-	float		x2, y2, z2;
-	float		rx, ry, rz;
-	mesh_node_t *meshNode;
-	int			pos,bit;
-	int			vertIndexBase;
-	int			start_tri;
-
-	if (nodesList)
-	{
-		TK_BeyondRequire(TK_NAME, TK_STRING);
-
-		if (Depth == 0 || tk_String[0] == '_')
-		{	// Root
-			ActiveNode = *num_mesh_nodes;
-			(*num_mesh_nodes)++;
-			if ((*num_mesh_nodes) > MAX_FM_MESH_NODES)
-			{
-				Error("Too many mesh nodes in file %s\n", hrc_name);
-			}
-			meshNode = &(*nodesList)[ActiveNode];
-
-//			memset(meshNode, 0, sizeof(mesh_node_t));
-			strcpy(meshNode->name, tk_String);
-
-			memset(meshNode->tris, 0, sizeof(meshNode->tris));
-			memset(meshNode->verts, 0, sizeof(meshNode->verts));
-
-			meshNode->start_glcmds = 0;
-			meshNode->num_glcmds = 0;
-			vertIndexBase = 0;
-		}
-		else
-		{	// Childs under the children
-			meshNode = &(*nodesList)[ActiveNode];
-			vertIndexBase = numVerts;
-		}
-	}
-	else 
-	{
-		meshNode = NULL;
-	}
-
-	// Get vertex count
-	TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
-	vertexCount = tk_IntNumber;
-	
-	// Get triangle count
-	TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
-	triCount = tk_IntNumber;
-	if(triCount >= MAXTRIANGLES)
-	{
-		Error("Too many triangles in file %s\n", hrc_name);
-	}
-
-	// Get origin
-	TK_Beyond(TK_ORIGIN);
-	TK_Require(TK_FLOATNUMBER);
-	origin[0] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	origin[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	origin[2] = tk_FloatNumber;
-
-	//rx = 90.0/360.0*2.0*M_PI;
-	rx = FixHTRRotateX/360.0*2.0*M_PI;
-	ry = FixHTRRotateY/360.0*2.0*M_PI;
-	rz = FixHTRRotateZ/360.0*2.0*M_PI;
-
-	// Get vertex list
-	for(i = 0; i < vertexCount; i++)
-	{
-		TK_FetchRequire(TK_VERTEX);
-		TK_FetchRequire(TK_FLOATNUMBER);
-		x = tk_FloatNumber-origin[0];
-		TK_FetchRequire(TK_FLOATNUMBER);
-		y = tk_FloatNumber-origin[1];
-		TK_FetchRequire(TK_FLOATNUMBER);
-		z = tk_FloatNumber-origin[2];
-
-		x += FixHTRTranslateX;
-		y += FixHTRTranslateY;
-		z += FixHTRTranslateZ;
-
-		y2 = y*cos(rx)-z*sin(rx);
-		z2 = y*sin(rx)+z*cos(rx);
-		y = y2;
-		z = z2;
-		x2 = x*cos(ry)+z*sin(ry);
-		z2 = -x*sin(ry)+z*cos(ry);
-		x = x2;
-		z = z2;
-		x2 = x*cos(rz)-y*sin(rz);
-		y2 = x*sin(rz)+y*cos(rz);
-		x = x2;
-		y = y2;
-
-		vList[i].v[0] = x;
-		vList[i].v[1] = y;
-		vList[i].v[2] = z;
-	}
-
-	start_tri = *triangleCount;
-	*triangleCount += triCount;
-
-	tList = *triList;
-
-	// Get face list
-	for(i = 0; i < triCount; i++)
-	{
-		if (meshNode)
-		{	// Update the node
-			pos = (i + start_tri) >> 3;
-			bit = 1 << ((i + start_tri) & 7 );
-			meshNode->tris[pos] |= bit;
-		}
-
-		TK_FetchRequire(TK_FACE);
-		TK_FetchRequire(TK_LPAREN);
-		for(j = 0; j < 3; j++)
-		{
-			TK_FetchRequire(TK_INTNUMBER);
-			vertexNum = tk_IntNumber-1;
-			if(vertexNum >= vertexCount)
-			{
-				Error("File '%s', line %d:\nVertex number"
-					" >= vertexCount: %d\n", tk_SourceName, tk_Line,
-					tk_IntNumber);
-			}
-			tList[i+start_tri].verts[2-j][0] = vList[vertexNum].v[0];
-			tList[i+start_tri].verts[2-j][1] = vList[vertexNum].v[1];
-			tList[i+start_tri].verts[2-j][2] = vList[vertexNum].v[2];
-		}
-		TK_FetchRequire(TK_RPAREN);
-#ifdef _QDATA
-		if (Version2)
-		{
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i+start_tri].uv[0][0]=tk_FloatNumber;
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i+start_tri].uv[0][1]=tk_FloatNumber;
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i+start_tri].uv[1][0]=tk_FloatNumber;
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i+start_tri].uv[1][1]=tk_FloatNumber;
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i+start_tri].uv[2][0]=tk_FloatNumber;
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i+start_tri].uv[2][1]=tk_FloatNumber;
-			tList[i+start_tri].HasUV=1;
-		}
-		else
-			tList[i+start_tri].HasUV=0;
-#endif
-//		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-//			"  v2: %f, %f, %f\n", i,
-//			tList[i].verts[0][0],
-//			tList[i].verts[0][1],
-//			tList[i].verts[0][2],
-//			tList[i].verts[1][0],
-//			tList[i].verts[1][1],
-//			tList[i].verts[1][2],
-//			tList[i].verts[2][0],
-//			tList[i].verts[2][1],
-//			tList[i].verts[2][2]);
-
-	}
-
-	TK_Fetch();
-
-	if (tk_Token == TK_VERTICES) 
-	{
-		HandleHTRModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase);
-	}
-}
-
-static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
-{
-	if (nodesList)
-	{
-		*num_mesh_nodes = 0;
-
-		if(!*nodesList)
-		{
-			*nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-		}
-	}
-
-	hrc_name = fileName;
-
-	scaling[0] = scaling[1] = scaling[2] = 1.0;
-	rotation[0] = rotation[1] = rotation[2] = 0.0;
-	translation[0] = translation[1] = translation[2] = 0.0;
-
-	*triangleCount = 0;
-	*triList = SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
-	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
-
-	TK_OpenSource(fileName);
-
-	TK_Beyond(TK_C_HEXEN);
-	TK_Beyond(TK_C_TRIANGLES);
-	TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
-	if(tk_IntNumber != 1&&tk_IntNumber != 2)
-	{
-		Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
-			fileName);
-	}
-	Version2=(tk_IntNumber==2);
-
-
-	HandleHTRModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0);
-}
-
-*/
-
-static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
-{
-	int Version2=0;
-	int			i, j;
-	int			vertexCount;
-	int			vertexNum;
-	struct
-	{
-		float v[3];
-	}			*vList;
-	int			triCount;
-	float		origin[3];
-	triangle_t	*tList;
-	float		x, y, z;
-	float		x2, y2, z2;
-	float		rx, ry, rz;
-
-	if (nodesList)
-	{
-		*num_mesh_nodes = 0;
-		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-	}
-
-	TK_OpenSource(fileName);
-
-	TK_Beyond(TK_C_HEXEN);
-	TK_Beyond(TK_C_TRIANGLES);
-	TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
-	if(tk_IntNumber != 1&&tk_IntNumber != 2)
-	{
-		Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
-			fileName);
-	}
-	Version2=(tk_IntNumber==2);
-
-
-	// Get vertex count
-	TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
-	vertexCount = tk_IntNumber;
-	vList = (void *) SafeMalloc(vertexCount*sizeof vList[0], "Vertex list");
-	
-	// Get triangle count
-	TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
-	triCount = tk_IntNumber;
-	if(triCount >= MAXTRIANGLES)
-	{
-		Error("Too many triangles in file %s\n", fileName);
-	}
-	*triangleCount = triCount;
-	tList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
-	*triList = tList;
-	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
-
-	// Get origin
-	TK_Beyond(TK_ORIGIN);
-	TK_Require(TK_FLOATNUMBER);
-	origin[0] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	origin[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	origin[2] = tk_FloatNumber;
-
-	//rx = 90.0/360.0*2.0*M_PI;
-	rx = FixHTRRotateX/360.0*2.0*M_PI;
-	ry = FixHTRRotateY/360.0*2.0*M_PI;
-	rz = FixHTRRotateZ/360.0*2.0*M_PI;
-
-	// Get vertex list
-	for(i = 0; i < vertexCount; i++)
-	{
-		TK_FetchRequire(TK_VERTEX);
-		TK_FetchRequire(TK_FLOATNUMBER);
-		x = tk_FloatNumber-origin[0];
-		TK_FetchRequire(TK_FLOATNUMBER);
-		y = tk_FloatNumber-origin[1];
-		TK_FetchRequire(TK_FLOATNUMBER);
-		z = tk_FloatNumber-origin[2];
-
-		x += FixHTRTranslateX;
-		y += FixHTRTranslateY;
-		z += FixHTRTranslateZ;
-
-		y2 = y*cos(rx)-z*sin(rx);
-		z2 = y*sin(rx)+z*cos(rx);
-		y = y2;
-		z = z2;
-		x2 = x*cos(ry)+z*sin(ry);
-		z2 = -x*sin(ry)+z*cos(ry);
-		x = x2;
-		z = z2;
-		x2 = x*cos(rz)-y*sin(rz);
-		y2 = x*sin(rz)+y*cos(rz);
-		x = x2;
-		y = y2;
-
-		vList[i].v[0] = x;
-		vList[i].v[1] = y;
-		vList[i].v[2] = z;
-	}
-
-	// Get face list
-	for(i = 0; i < triCount; i++)
-	{
-		TK_FetchRequire(TK_FACE);
-		TK_FetchRequire(TK_LPAREN);
-		for(j = 0; j < 3; j++)
-		{
-			TK_FetchRequire(TK_INTNUMBER);
-			vertexNum = tk_IntNumber-1;
-			if(vertexNum >= vertexCount)
-			{
-				Error("File '%s', line %d:\nVertex number"
-					" >= vertexCount: %d\n", tk_SourceName, tk_Line,
-					tk_IntNumber);
-			}
-			tList[i].verts[2-j][0] = vList[vertexNum].v[0];
-			tList[i].verts[2-j][1] = vList[vertexNum].v[1];
-			tList[i].verts[2-j][2] = vList[vertexNum].v[2];
-		}
-		TK_FetchRequire(TK_RPAREN);
-#if 1
-		if (Version2)
-		{
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i].uv[2][0]= fmod(1000+tk_FloatNumber,1);
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i].uv[2][1]=fmod(1000+tk_FloatNumber,1);
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i].uv[1][0]=fmod(1000+tk_FloatNumber,1);
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i].uv[1][1]=fmod(1000+tk_FloatNumber,1);
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i].uv[0][0]=fmod(1000+tk_FloatNumber,1);
-			TK_FetchRequire(TK_FLOATNUMBER);
-			tList[i].uv[0][1]=fmod(1000+tk_FloatNumber,1);
-			tList[i].HasUV=1;
-		}
-		else
-			tList[i].HasUV=0;
-#endif
-/*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
-			"  v2: %f, %f, %f\n", i,
-			tList[i].verts[0][0],
-			tList[i].verts[0][1],
-			tList[i].verts[0][2],
-			tList[i].verts[1][0],
-			tList[i].verts[1][1],
-			tList[i].verts[1][2],
-			tList[i].verts[2][0],
-			tList[i].verts[2][1],
-			tList[i].verts[2][2]);
-*/
-	}
-
-	free(vList);
-	TK_CloseSource();
-	DefaultNodesList(nodesList,num_mesh_nodes,triangleCount);
-}
-
-//==========================================================================
-//
-// LoadTriangleList
-//
-//==========================================================================
-
-void LoadTriangleList(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes)
-{
-	FILE	*file1;
-    int		dot = '.';
-	char	*dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-			LoadHRC(InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".asc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-			LoadASC(InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			printf(" - assuming .ASC\n");
-			return;
-		}
-
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".tri");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{			
-			fclose(file1);
-			LoadTRI(InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			printf(" - assuming .TRI\n");
-			return;
-		}
-
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".3ds");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{			
-			fclose(file1);
-			Load3DSTriangleList (InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			printf(" - assuming .3DS\n");
-			return;
-		}
-
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".htr");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{			
-			fclose(file1);
-			LoadHTR (InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			printf(" - assuming .HTR\n");
-			return;
-		}
-		Error("\n Could not open file '%s':\n"
-			"No HRC, ASC, 3DS, HTR, or TRI match.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRC(fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			}
-			else if (strcmp(dotstart,".asc") == 0 || strcmp(dotstart,".ASC") == 0)
-			{
-				LoadASC(fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			}
-			else if (strcmp(dotstart,".tri") == 0 || strcmp(dotstart,".TRI") == 0)
-			{
-				LoadTRI(fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			}
-			else if (strcmp(dotstart,".3ds") == 0 || strcmp(dotstart,".3DS") == 0)
-			{
-				Load3DSTriangleList (fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			}
-			else if (strcmp(dotstart,".htr") == 0 || strcmp(dotstart,".HTR") == 0)
-			{
-				LoadHTR (fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
-			}
-			else
-			{
-				Error("Could not open file '%s':\n",fileName);
-				return;
-			}
-		}
-		else	//failed to load file
-		{
-				Error("Could not open file '%s':\n",fileName);
-		}
-
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// trilib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "inout.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "token.h"
+#include "l3dslib.h"
+#include "fmodel.h"
+#if 1
+#include "qd_skeletons.h"
+#endif
+
+// on disk representation of a face
+#define	FLOAT_START	99999.0
+#define	FLOAT_END	-FLOAT_START
+#define MAGIC       123322
+#ifndef M_PI
+  #define M_PI		3.14159265
+#endif
+
+float FixHTRRotateX = 0.0;
+float FixHTRRotateY = 0.0;
+float FixHTRRotateZ = 0.0;
+float FixHTRTranslateX = 0.0;
+float FixHTRTranslateY = 0.0;
+float FixHTRTranslateZ = 0.0;
+
+//#define NOISY 1
+
+typedef struct {
+	float v[3];
+} vector;
+
+typedef struct
+{
+	vector n;    /* normal */
+	vector p;    /* point */
+	vector c;    /* color */
+	float  u;    /* u */
+	float  v;    /* v */
+} aliaspoint_t;
+
+typedef struct {
+	aliaspoint_t	pt[3];
+} tf_triangle;
+
+
+void ByteSwapTri (tf_triangle *tri)
+{
+	int		i;
+	
+	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
+	{
+		((int *)tri)[i] = BigLong (((int *)tri)[i]);
+	}
+}
+
+void LoadTRI (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **nodesList, int *num_mesh_nodes)
+{
+	FILE        *input;
+	float       start;
+	char        name[256], tex[256];
+	int         i, count, magic;
+	tf_triangle	tri;
+	triangle_t	*ptri;
+	int			iLevel;
+	int			exitpattern;
+	float		t;
+
+	if (nodesList)
+	{
+		*num_mesh_nodes = 0;
+		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+	}
+
+	t = -FLOAT_START;
+	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
+	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
+	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
+	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
+
+	if ((input = fopen(filename, "rb")) == 0)
+		Error ("reader: could not open file '%s'", filename);
+
+	iLevel = 0;
+
+	fread(&magic, sizeof(int), 1, input);
+	if (BigLong(magic) != MAGIC)
+		Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
+
+	ptri = malloc (MAXTRIANGLES * sizeof(triangle_t));
+
+	*pptri = ptri;
+
+	while (feof(input) == 0) {
+		if (fread(&start,  sizeof(float), 1, input) < 1)
+			break;
+		*(int *)&start = BigLong(*(int *)&start);
+		if (*(int *)&start != exitpattern)
+		{
+			if (start == FLOAT_START) {
+				/* Start of an object or group of objects. */
+				i = -1;
+				do {
+					/* There are probably better ways to read a string from */
+					/* a file, but this does allow you to do error checking */
+					/* (which I'm not doing) on a per character basis.      */
+					++i;
+					fread( &(name[i]), sizeof( char ), 1, input);
+				} while( name[i] != '\0' );
+	
+//				indent();
+//				fprintf(stdout,"OBJECT START: %s\n",name);
+				fread( &count, sizeof(int), 1, input);
+				count = BigLong(count);
+				++iLevel;
+				if (count != 0) {
+//					indent();
+//					fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
+	
+					i = -1;
+					do {
+						++i;
+						fread( &(tex[i]), sizeof( char ), 1, input);
+					} while( tex[i] != '\0' );
+	
+//					indent();
+//					fprintf(stdout,"  Object texture name: '%s'\n",tex);
+				}
+	
+				/* Else (count == 0) this is the start of a group, and */
+				/* no texture name is present. */
+			}
+			else if (start == FLOAT_END) {
+				/* End of an object or group. Yes, the name should be */
+				/* obvious from context, but it is in here just to be */
+				/* safe and to provide a little extra information for */
+				/* those who do not wish to write a recursive reader. */
+				/* Mia culpa. */
+				--iLevel;
+				i = -1;
+				do {
+					++i;
+					fread( &(name[i]), sizeof( char ), 1, input);
+				} while( name[i] != '\0' );
+	
+//				indent();
+//				fprintf(stdout,"OBJECT END: %s\n",name);
+				continue;
+			}
+		}
+
+//
+// read the triangles
+//		
+		for (i = 0; i < count; ++i) {
+			int		j;
+
+			fread( &tri, sizeof(tf_triangle), 1, input );
+			ByteSwapTri (&tri);
+			for (j=0 ; j<3 ; j++)
+			{
+				int		k;
+
+				for (k=0 ; k<3 ; k++)
+				{
+					ptri->verts[j][k] = tri.pt[j].p.v[k];
+				}
+			}
+
+			ptri++;
+
+			if ((ptri - *pptri) >= MAXTRIANGLES)
+				Error ("Error: too many triangles; increase MAXTRIANGLES\n");
+		}
+	}
+
+	*numtriangles = ptri - *pptri;
+
+	fclose (input);
+
+	DefaultNodesList(nodesList,num_mesh_nodes,numtriangles);
+}
+
+
+//==========================================================================
+//
+// LoadHRC
+//
+//==========================================================================
+
+float	scaling[3];
+float	rotation[3];
+float	translation[3];
+static char		*hrc_name;
+
+struct
+{
+	float v[3];
+} vList[8192];
+
+void HandleHRCModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
+						   int ActiveNode, int Depth, int numVerts)
+{
+	void ReadHRCClusterList(mesh_node_t *meshNode, int baseIndex);
+
+	int			i, j;
+	int			vertexCount;
+	int			triCount;
+	triangle_t	*tList;
+	mesh_node_t *meshNode;
+	float		x, y, z;
+	float		x2, y2, z2;
+	float		rx, ry, rz;
+	tokenType_t nextToken;
+	float		orig_scaling[3];
+	float		orig_rotation[3];
+	float		orig_translation[3];
+	int			start_tri;
+	int			pos,bit;
+	int			vertIndexBase;
+
+	// Update Node Info
+	if (nodesList)
+	{
+		TK_BeyondRequire(TK_NAME, TK_STRING);
+
+		if (Depth == 0 || tk_String[0] == '_')
+		{	// Root
+			ActiveNode = *num_mesh_nodes;
+			(*num_mesh_nodes)++;
+			if ((*num_mesh_nodes) > MAX_FM_MESH_NODES)
+			{
+				Error("Too many mesh nodes in file %s\n", hrc_name);
+			}
+			meshNode = &(*nodesList)[ActiveNode];
+
+//			memset(meshNode, 0, sizeof(mesh_node_t));
+			strcpy(meshNode->name, tk_String);
+
+			memset(meshNode->tris, 0, sizeof(meshNode->tris));
+			memset(meshNode->verts, 0, sizeof(meshNode->verts));
+
+			meshNode->start_glcmds = 0;
+			meshNode->num_glcmds = 0;
+			vertIndexBase = 0;
+		}
+		else
+		{	// Childs under the children
+			meshNode = &(*nodesList)[ActiveNode];
+			vertIndexBase = numVerts;
+		}
+	}
+	else 
+	{
+		meshNode = NULL;
+	}
+
+
+	// Get the scaling, rotation, and translation values
+	TK_Beyond(TK_SCALING);
+	for(i = 0; i < 3; i++)
+	{
+		orig_scaling[i] = scaling[i];
+
+		TK_Require(TK_FLOATNUMBER);
+		scaling[i] *= tk_FloatNumber;
+
+		TK_Fetch();
+	}
+	TK_Beyond(TK_ROTATION);
+	for(i = 0; i < 3; i++)
+	{
+		orig_rotation[i] = rotation[i];
+
+		TK_Require(TK_FLOATNUMBER);
+		rotation[i] = tk_FloatNumber;
+
+		TK_Fetch();
+	}
+	TK_Beyond(TK_TRANSLATION);
+	for(i = 0; i < 3; i++)
+	{
+		orig_translation[i] = translation[i];
+
+		TK_Require(TK_FLOATNUMBER);
+		translation[i] += tk_FloatNumber;
+
+		TK_Fetch();
+	}
+
+	rx = ((rotation[0]-90.0)/360.0)*2.0*M_PI;
+	ry = (rotation[2]/360.0)*2.0*M_PI;
+	rz = (rotation[1]/360.0)*2.0*M_PI;
+
+	// rjr - might not work if there an item doesn't have a mesh
+	nextToken = tk_Token;
+	if (nextToken == TK_ACTOR_DATA)
+	{
+		while (nextToken != TK_MODEL && nextToken != TK_RBRACE)
+		{
+			nextToken = TK_Fetch();
+		}
+	}
+
+	while (nextToken == TK_SPLINE)
+	{	// spline node has two right braces
+		nextToken = TK_Beyond(TK_RBRACE);
+		nextToken = TK_Beyond(TK_RBRACE);
+	}
+
+	while (nextToken == TK_MATERIAL)
+	{
+		nextToken = TK_Beyond(TK_RBRACE);
+	}
+
+	while(nextToken == TK_MODEL)
+	{
+		HandleHRCModel(triList,triangleCount,nodesList,num_mesh_nodes,ActiveNode, Depth+1, 0);
+
+		nextToken = TK_Fetch();
+	}
+
+	if (nextToken == TK_MESH)
+	{
+		// Get all the tri and vertex info
+		TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
+		vertexCount = tk_IntNumber;
+		for(i = 0; i < vertexCount; i++)
+		{
+			TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
+			if(tk_IntNumber != i)
+			{
+				Error("File '%s', line %d:\nVertex index mismatch.\n",
+					tk_SourceName, tk_Line);
+			}
+			TK_Beyond(TK_POSITION);
+			// Apply the scaling, rotation, and translation in the order
+			// specified in the HRC file.  This could be wrong.
+			TK_Require(TK_FLOATNUMBER);
+			x = tk_FloatNumber*scaling[0];
+			TK_FetchRequire(TK_FLOATNUMBER);
+			y = tk_FloatNumber*scaling[1];
+			TK_FetchRequire(TK_FLOATNUMBER);
+			z = tk_FloatNumber*scaling[2];
+
+			y2 = y*cos(rx)+z*sin(rx);
+			z2 = -y*sin(rx)+z*cos(rx);
+			y = y2;
+			z = z2;
+
+			x2 = x*cos(ry)-z*sin(ry);
+			z2 = x*sin(ry)+z*cos(ry);
+			x = x2;
+			z = z2;
+
+			x2 = x*cos(rz)+y*sin(rz);
+			y2 = -x*sin(rz)+y*cos(rz);
+			x = x2;
+			y = y2;
+
+			vList[i].v[0] = x+translation[0];
+			vList[i].v[1] = y-translation[2];
+			vList[i].v[2] = z+translation[1];
+		}
+		TK_BeyondRequire(TK_POLYGONS, TK_INTNUMBER);
+		triCount = tk_IntNumber;
+		if(triCount >= MAXTRIANGLES)
+		{
+			Error("Too many triangles in file %s\n", hrc_name);
+		}
+
+		start_tri = *triangleCount;
+		*triangleCount += triCount;
+
+		tList = *triList;
+
+		for(i = 0; i < triCount; i++)
+		{
+			if (meshNode)
+			{	// Update the node
+				pos = (i + start_tri) >> 3;
+				bit = 1 << ((i + start_tri) & 7 );
+				meshNode->tris[pos] |= bit;
+			}
+
+			TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
+			if(tk_IntNumber != i)
+			{
+				Error("File '%s', line %d:\nTriangle index mismatch.\n",
+					tk_SourceName, tk_Line);
+			}
+			TK_BeyondRequire(TK_NODES, TK_INTNUMBER);
+			if(tk_IntNumber != 3)
+			{
+				Error("File '%s', line %d:\nBad polygon vertex count: %d.",
+					tk_SourceName, tk_Line, tk_IntNumber);
+			}
+			tList[i+start_tri].HasUV = true;
+			for(j = 0; j < 3; j++)
+			{
+				TK_BeyondRequire(TK_LBRACKET, TK_INTNUMBER);
+				if(tk_IntNumber != j)
+				{
+					Error("File '%s', line %d:\nTriangle vertex index"
+						" mismatch.  %d should be %d\n", tk_SourceName, tk_Line,
+						tk_IntNumber, j);
+				}
+				TK_BeyondRequire(TK_VERTEX, TK_INTNUMBER);
+
+				tList[i+start_tri].verts[2-j][0] = vList[tk_IntNumber].v[0];
+				tList[i+start_tri].verts[2-j][1] = vList[tk_IntNumber].v[1];
+				tList[i+start_tri].verts[2-j][2] = vList[tk_IntNumber].v[2];
+#if 1
+				tList[i+start_tri].indicies[2-j] = tk_IntNumber+vertIndexBase;
+#endif
+				TK_BeyondRequire(TK_UVTEXTURE, TK_FLOATNUMBER);
+				tList[i+start_tri].uv[2-j][0] = tk_FloatNumber;
+				TK_Fetch();
+				TK_Require(TK_FLOATNUMBER);
+				tList[i+start_tri].uv[2-j][1] = tk_FloatNumber;
+			}
+
+	/*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+				"  v2: %f, %f, %f\n", i,
+				tList[i].verts[0][0],
+				tList[i].verts[0][1],
+				tList[i].verts[0][2],
+				tList[i].verts[1][0],
+				tList[i].verts[1][1],
+				tList[i].verts[1][2],
+				tList[i].verts[2][0],
+				tList[i].verts[2][1],
+				tList[i].verts[2][2]);
+	*/
+		}
+
+		TK_Beyond(TK_RBRACE);
+		TK_Beyond(TK_RBRACE);
+
+		if (tk_Token == TK_EDGES)
+		{
+		//	TK_Beyond(TK_EDGES);
+			TK_Beyond(TK_RBRACE);
+		}
+
+		scaling[0] = scaling[1] = scaling[2] = 1.0;
+	//	rotation[0] = rotation[1] = rotation[2] = 0.0;
+	//	translation[0] = translation[1] = translation[2] = 0.0;
+
+		// See if there are any other models belonging to this node
+
+#if 1
+		TK_Fetch();
+
+		nextToken = tk_Token;
+		if(nextToken == TK_CLUSTERS)
+		{
+			if(g_skelModel.clustered == -1)
+			{
+				ReadHRCClusterList(meshNode, vertIndexBase);
+			}
+			else
+			{
+				nextToken = TK_Get(TK_CLUSTER_NAME);
+
+				while (nextToken == TK_CLUSTER_NAME)
+				{
+					TK_BeyondRequire(TK_CLUSTER_STATE, TK_INTNUMBER);
+					nextToken = TK_Fetch();
+				}
+			}
+
+			// one right brace follow the list of clusters
+			nextToken = TK_Beyond(TK_RBRACE);
+		}
+		else
+		{
+			if(g_skelModel.clustered == -1 && !vertIndexBase)
+			{
+				meshNode->clustered = false;
+			}
+		}
+#endif
+
+		nextToken = tk_Token;
+		if(nextToken == TK_SPLINE)
+		{
+			while (nextToken == TK_SPLINE)
+			{	// spline node has two right braces
+				nextToken = TK_Beyond(TK_RBRACE);
+				nextToken = TK_Beyond(TK_RBRACE);
+			}
+
+			nextToken = TK_Beyond(TK_RBRACE);
+		}
+
+		while (nextToken == TK_MATERIAL)
+		{
+			nextToken = TK_Beyond(TK_RBRACE);
+		}
+
+		while(nextToken == TK_MODEL)
+		{
+			HandleHRCModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase);
+
+			nextToken = TK_Fetch();
+		}
+	}
+
+	for(i=0;i<3;i++)
+	{
+		scaling[i] = orig_scaling[i];
+		rotation[i] = orig_rotation[i];
+		translation[i] = orig_translation[i];
+	}
+}
+
+static void LoadHRC(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
+{
+	if (nodesList)
+	{
+		*num_mesh_nodes = 0;
+
+		if(!*nodesList)
+		{
+			*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+		}
+	}
+
+	hrc_name = fileName;
+
+	scaling[0] = scaling[1] = scaling[2] = 1.0;
+	rotation[0] = rotation[1] = rotation[2] = 0.0;
+	translation[0] = translation[1] = translation[2] = 0.0;
+
+	*triangleCount = 0;
+	*triList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
+	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+
+	// prime it
+	TK_Beyond(TK_MODEL);
+
+	HandleHRCModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0);
+	TK_CloseSource();
+}
+
+//==========================================================================
+//
+// LoadHTR
+//
+//==========================================================================
+/*
+static int Version2;
+
+void HandleHTRModel(triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes,
+						   int ActiveNode, int Depth, int numVerts)
+{
+	int			i, j;
+	int			vertexCount;
+	int			vertexNum;
+	int			triCount;
+	float		origin[3];
+	triangle_t	*tList;
+	float		x, y, z;
+	float		x2, y2, z2;
+	float		rx, ry, rz;
+	mesh_node_t *meshNode;
+	int			pos,bit;
+	int			vertIndexBase;
+	int			start_tri;
+
+	if (nodesList)
+	{
+		TK_BeyondRequire(TK_NAME, TK_STRING);
+
+		if (Depth == 0 || tk_String[0] == '_')
+		{	// Root
+			ActiveNode = *num_mesh_nodes;
+			(*num_mesh_nodes)++;
+			if ((*num_mesh_nodes) > MAX_FM_MESH_NODES)
+			{
+				Error("Too many mesh nodes in file %s\n", hrc_name);
+			}
+			meshNode = &(*nodesList)[ActiveNode];
+
+//			memset(meshNode, 0, sizeof(mesh_node_t));
+			strcpy(meshNode->name, tk_String);
+
+			memset(meshNode->tris, 0, sizeof(meshNode->tris));
+			memset(meshNode->verts, 0, sizeof(meshNode->verts));
+
+			meshNode->start_glcmds = 0;
+			meshNode->num_glcmds = 0;
+			vertIndexBase = 0;
+		}
+		else
+		{	// Childs under the children
+			meshNode = &(*nodesList)[ActiveNode];
+			vertIndexBase = numVerts;
+		}
+	}
+	else 
+	{
+		meshNode = NULL;
+	}
+
+	// Get vertex count
+	TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
+	vertexCount = tk_IntNumber;
+	
+	// Get triangle count
+	TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
+	triCount = tk_IntNumber;
+	if(triCount >= MAXTRIANGLES)
+	{
+		Error("Too many triangles in file %s\n", hrc_name);
+	}
+
+	// Get origin
+	TK_Beyond(TK_ORIGIN);
+	TK_Require(TK_FLOATNUMBER);
+	origin[0] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	origin[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	origin[2] = tk_FloatNumber;
+
+	//rx = 90.0/360.0*2.0*M_PI;
+	rx = FixHTRRotateX/360.0*2.0*M_PI;
+	ry = FixHTRRotateY/360.0*2.0*M_PI;
+	rz = FixHTRRotateZ/360.0*2.0*M_PI;
+
+	// Get vertex list
+	for(i = 0; i < vertexCount; i++)
+	{
+		TK_FetchRequire(TK_VERTEX);
+		TK_FetchRequire(TK_FLOATNUMBER);
+		x = tk_FloatNumber-origin[0];
+		TK_FetchRequire(TK_FLOATNUMBER);
+		y = tk_FloatNumber-origin[1];
+		TK_FetchRequire(TK_FLOATNUMBER);
+		z = tk_FloatNumber-origin[2];
+
+		x += FixHTRTranslateX;
+		y += FixHTRTranslateY;
+		z += FixHTRTranslateZ;
+
+		y2 = y*cos(rx)-z*sin(rx);
+		z2 = y*sin(rx)+z*cos(rx);
+		y = y2;
+		z = z2;
+		x2 = x*cos(ry)+z*sin(ry);
+		z2 = -x*sin(ry)+z*cos(ry);
+		x = x2;
+		z = z2;
+		x2 = x*cos(rz)-y*sin(rz);
+		y2 = x*sin(rz)+y*cos(rz);
+		x = x2;
+		y = y2;
+
+		vList[i].v[0] = x;
+		vList[i].v[1] = y;
+		vList[i].v[2] = z;
+	}
+
+	start_tri = *triangleCount;
+	*triangleCount += triCount;
+
+	tList = *triList;
+
+	// Get face list
+	for(i = 0; i < triCount; i++)
+	{
+		if (meshNode)
+		{	// Update the node
+			pos = (i + start_tri) >> 3;
+			bit = 1 << ((i + start_tri) & 7 );
+			meshNode->tris[pos] |= bit;
+		}
+
+		TK_FetchRequire(TK_FACE);
+		TK_FetchRequire(TK_LPAREN);
+		for(j = 0; j < 3; j++)
+		{
+			TK_FetchRequire(TK_INTNUMBER);
+			vertexNum = tk_IntNumber-1;
+			if(vertexNum >= vertexCount)
+			{
+				Error("File '%s', line %d:\nVertex number"
+					" >= vertexCount: %d\n", tk_SourceName, tk_Line,
+					tk_IntNumber);
+			}
+			tList[i+start_tri].verts[2-j][0] = vList[vertexNum].v[0];
+			tList[i+start_tri].verts[2-j][1] = vList[vertexNum].v[1];
+			tList[i+start_tri].verts[2-j][2] = vList[vertexNum].v[2];
+		}
+		TK_FetchRequire(TK_RPAREN);
+#ifdef _QDATA
+		if (Version2)
+		{
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i+start_tri].uv[0][0]=tk_FloatNumber;
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i+start_tri].uv[0][1]=tk_FloatNumber;
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i+start_tri].uv[1][0]=tk_FloatNumber;
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i+start_tri].uv[1][1]=tk_FloatNumber;
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i+start_tri].uv[2][0]=tk_FloatNumber;
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i+start_tri].uv[2][1]=tk_FloatNumber;
+			tList[i+start_tri].HasUV=1;
+		}
+		else
+			tList[i+start_tri].HasUV=0;
+#endif
+//		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+//			"  v2: %f, %f, %f\n", i,
+//			tList[i].verts[0][0],
+//			tList[i].verts[0][1],
+//			tList[i].verts[0][2],
+//			tList[i].verts[1][0],
+//			tList[i].verts[1][1],
+//			tList[i].verts[1][2],
+//			tList[i].verts[2][0],
+//			tList[i].verts[2][1],
+//			tList[i].verts[2][2]);
+
+	}
+
+	TK_Fetch();
+
+	if (tk_Token == TK_VERTICES) 
+	{
+		HandleHTRModel(triList,triangleCount,nodesList, num_mesh_nodes, ActiveNode, Depth+1, vertexCount+vertIndexBase);
+	}
+}
+
+static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
+{
+	if (nodesList)
+	{
+		*num_mesh_nodes = 0;
+
+		if(!*nodesList)
+		{
+			*nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+		}
+	}
+
+	hrc_name = fileName;
+
+	scaling[0] = scaling[1] = scaling[2] = 1.0;
+	rotation[0] = rotation[1] = rotation[2] = 0.0;
+	translation[0] = translation[1] = translation[2] = 0.0;
+
+	*triangleCount = 0;
+	*triList = SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
+	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
+
+	TK_OpenSource(fileName);
+
+	TK_Beyond(TK_C_HEXEN);
+	TK_Beyond(TK_C_TRIANGLES);
+	TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
+	if(tk_IntNumber != 1&&tk_IntNumber != 2)
+	{
+		Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
+			fileName);
+	}
+	Version2=(tk_IntNumber==2);
+
+
+	HandleHTRModel(triList, triangleCount, nodesList, num_mesh_nodes, 0, 0, 0);
+}
+
+*/
+
+static void LoadHTR(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **nodesList, int *num_mesh_nodes)
+{
+	int Version2=0;
+	int			i, j;
+	int			vertexCount;
+	int			vertexNum;
+	struct
+	{
+		float v[3];
+	}			*vList;
+	int			triCount;
+	float		origin[3];
+	triangle_t	*tList;
+	float		x, y, z;
+	float		x2, y2, z2;
+	float		rx, ry, rz;
+
+	if (nodesList)
+	{
+		*num_mesh_nodes = 0;
+		*nodesList = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+	}
+
+	TK_OpenSource(fileName);
+
+	TK_Beyond(TK_C_HEXEN);
+	TK_Beyond(TK_C_TRIANGLES);
+	TK_BeyondRequire(TK_C_VERSION, TK_INTNUMBER);
+	if(tk_IntNumber != 1&&tk_IntNumber != 2)
+	{
+		Error("Unsupported version (%d) in file %s\n", tk_IntNumber,
+			fileName);
+	}
+	Version2=(tk_IntNumber==2);
+
+
+	// Get vertex count
+	TK_BeyondRequire(TK_VERTICES, TK_INTNUMBER);
+	vertexCount = tk_IntNumber;
+	vList = (void *) SafeMalloc(vertexCount*sizeof vList[0], "Vertex list");
+	
+	// Get triangle count
+	TK_BeyondRequire(TK_FACES, TK_INTNUMBER);
+	triCount = tk_IntNumber;
+	if(triCount >= MAXTRIANGLES)
+	{
+		Error("Too many triangles in file %s\n", fileName);
+	}
+	*triangleCount = triCount;
+	tList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
+	*triList = tList;
+	memset(*triList,0,MAXTRIANGLES*sizeof(triangle_t));
+
+	// Get origin
+	TK_Beyond(TK_ORIGIN);
+	TK_Require(TK_FLOATNUMBER);
+	origin[0] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	origin[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	origin[2] = tk_FloatNumber;
+
+	//rx = 90.0/360.0*2.0*M_PI;
+	rx = FixHTRRotateX/360.0*2.0*M_PI;
+	ry = FixHTRRotateY/360.0*2.0*M_PI;
+	rz = FixHTRRotateZ/360.0*2.0*M_PI;
+
+	// Get vertex list
+	for(i = 0; i < vertexCount; i++)
+	{
+		TK_FetchRequire(TK_VERTEX);
+		TK_FetchRequire(TK_FLOATNUMBER);
+		x = tk_FloatNumber-origin[0];
+		TK_FetchRequire(TK_FLOATNUMBER);
+		y = tk_FloatNumber-origin[1];
+		TK_FetchRequire(TK_FLOATNUMBER);
+		z = tk_FloatNumber-origin[2];
+
+		x += FixHTRTranslateX;
+		y += FixHTRTranslateY;
+		z += FixHTRTranslateZ;
+
+		y2 = y*cos(rx)-z*sin(rx);
+		z2 = y*sin(rx)+z*cos(rx);
+		y = y2;
+		z = z2;
+		x2 = x*cos(ry)+z*sin(ry);
+		z2 = -x*sin(ry)+z*cos(ry);
+		x = x2;
+		z = z2;
+		x2 = x*cos(rz)-y*sin(rz);
+		y2 = x*sin(rz)+y*cos(rz);
+		x = x2;
+		y = y2;
+
+		vList[i].v[0] = x;
+		vList[i].v[1] = y;
+		vList[i].v[2] = z;
+	}
+
+	// Get face list
+	for(i = 0; i < triCount; i++)
+	{
+		TK_FetchRequire(TK_FACE);
+		TK_FetchRequire(TK_LPAREN);
+		for(j = 0; j < 3; j++)
+		{
+			TK_FetchRequire(TK_INTNUMBER);
+			vertexNum = tk_IntNumber-1;
+			if(vertexNum >= vertexCount)
+			{
+				Error("File '%s', line %d:\nVertex number"
+					" >= vertexCount: %d\n", tk_SourceName, tk_Line,
+					tk_IntNumber);
+			}
+			tList[i].verts[2-j][0] = vList[vertexNum].v[0];
+			tList[i].verts[2-j][1] = vList[vertexNum].v[1];
+			tList[i].verts[2-j][2] = vList[vertexNum].v[2];
+		}
+		TK_FetchRequire(TK_RPAREN);
+#if 1
+		if (Version2)
+		{
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i].uv[2][0]= fmod(1000+tk_FloatNumber,1);
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i].uv[2][1]=fmod(1000+tk_FloatNumber,1);
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i].uv[1][0]=fmod(1000+tk_FloatNumber,1);
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i].uv[1][1]=fmod(1000+tk_FloatNumber,1);
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i].uv[0][0]=fmod(1000+tk_FloatNumber,1);
+			TK_FetchRequire(TK_FLOATNUMBER);
+			tList[i].uv[0][1]=fmod(1000+tk_FloatNumber,1);
+			tList[i].HasUV=1;
+		}
+		else
+			tList[i].HasUV=0;
+#endif
+/*		printf("Face %i:\n  v0: %f, %f, %f\n  v1: %f, %f, %f\n"
+			"  v2: %f, %f, %f\n", i,
+			tList[i].verts[0][0],
+			tList[i].verts[0][1],
+			tList[i].verts[0][2],
+			tList[i].verts[1][0],
+			tList[i].verts[1][1],
+			tList[i].verts[1][2],
+			tList[i].verts[2][0],
+			tList[i].verts[2][1],
+			tList[i].verts[2][2]);
+*/
+	}
+
+	free(vList);
+	TK_CloseSource();
+	DefaultNodesList(nodesList,num_mesh_nodes,triangleCount);
+}
+
+//==========================================================================
+//
+// LoadTriangleList
+//
+//==========================================================================
+
+void LoadTriangleList(char *fileName, triangle_t **triList, int *triangleCount, mesh_node_t **ppmnodes, int *num_mesh_nodes)
+{
+	FILE	*file1;
+    int		dot = '.';
+	char	*dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+			LoadHRC(InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".asc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+			LoadASC(InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			printf(" - assuming .ASC\n");
+			return;
+		}
+
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".tri");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{			
+			fclose(file1);
+			LoadTRI(InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			printf(" - assuming .TRI\n");
+			return;
+		}
+
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".3ds");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{			
+			fclose(file1);
+			Load3DSTriangleList (InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			printf(" - assuming .3DS\n");
+			return;
+		}
+
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".htr");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{			
+			fclose(file1);
+			LoadHTR (InputFileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			printf(" - assuming .HTR\n");
+			return;
+		}
+		Error("\n Could not open file '%s':\n"
+			"No HRC, ASC, 3DS, HTR, or TRI match.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRC(fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			}
+			else if (strcmp(dotstart,".asc") == 0 || strcmp(dotstart,".ASC") == 0)
+			{
+				LoadASC(fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			}
+			else if (strcmp(dotstart,".tri") == 0 || strcmp(dotstart,".TRI") == 0)
+			{
+				LoadTRI(fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			}
+			else if (strcmp(dotstart,".3ds") == 0 || strcmp(dotstart,".3DS") == 0)
+			{
+				Load3DSTriangleList (fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			}
+			else if (strcmp(dotstart,".htr") == 0 || strcmp(dotstart,".HTR") == 0)
+			{
+				LoadHTR (fileName, triList, triangleCount, ppmnodes, num_mesh_nodes);
+			}
+			else
+			{
+				Error("Could not open file '%s':\n",fileName);
+				return;
+			}
+		}
+		else	//failed to load file
+		{
+				Error("Could not open file '%s':\n",fileName);
+		}
+
+	}
+}
diff --git a/tools/quake2/qdata_heretic2/common/trilib.h b/tools/quake2/qdata_heretic2/common/trilib.h
index 2afdf559..5bceadde 100644
--- a/tools/quake2/qdata_heretic2/common/trilib.h
+++ b/tools/quake2/qdata_heretic2/common/trilib.h
@@ -1,56 +1,56 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// trilib.h: header file for loading triangles from an Alias triangle file
-//
-
-#include "fmodel.h"
-
-#define MAXTRIANGLES	MAX_FM_TRIANGLES
-
-typedef struct 
-{
-	vec3_t		verts[3];
-#if 1
-	int			indicies[3];
-	float		uv[3][2];
-	qboolean	HasUV;
-#endif
-} triangle_t;
-
-#define NUM_CLUSTERS 8
-
-typedef struct
-{
-	char	name[64];
-	byte	tris[MAXTRIANGLES>>3];
-	byte	verts[MAX_FM_VERTS>>3];
-	int		start_glcmds, num_glcmds;
-
-	int *clusters[NUM_CLUSTERS];
-	struct IntListNode_s *vertLists[NUM_CLUSTERS];
-	int num_verts[NUM_CLUSTERS + 1];
-	int new_num_verts[NUM_CLUSTERS + 1];
-	qboolean clustered;
-} mesh_node_t;
-
-void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// trilib.h: header file for loading triangles from an Alias triangle file
+//
+
+#include "fmodel.h"
+
+#define MAXTRIANGLES	MAX_FM_TRIANGLES
+
+typedef struct 
+{
+	vec3_t		verts[3];
+#if 1
+	int			indicies[3];
+	float		uv[3][2];
+	qboolean	HasUV;
+#endif
+} triangle_t;
+
+#define NUM_CLUSTERS 8
+
+typedef struct
+{
+	char	name[64];
+	byte	tris[MAXTRIANGLES>>3];
+	byte	verts[MAX_FM_VERTS>>3];
+	int		start_glcmds, num_glcmds;
+
+	int *clusters[NUM_CLUSTERS];
+	struct IntListNode_s *vertLists[NUM_CLUSTERS];
+	int num_verts[NUM_CLUSTERS + 1];
+	int new_num_verts[NUM_CLUSTERS + 1];
+	qboolean clustered;
+} mesh_node_t;
+
+void LoadTriangleList (char *filename, triangle_t **pptri, int *numtriangles, mesh_node_t **ppmnodes, int *num_mesh_nodes);
diff --git a/tools/quake2/qdata_heretic2/fmodels.c b/tools/quake2/qdata_heretic2/fmodels.c
index 6dd16355..273a482d 100644
--- a/tools/quake2/qdata_heretic2/fmodels.c
+++ b/tools/quake2/qdata_heretic2/fmodels.c
@@ -1,3404 +1,3404 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qd_fmodel.h"
-#include "animcomp.h"
-#include "qd_skeletons.h"
-#include "skeletons.h"
-#include "qdata.h"
-#include "flex.h"
-#include "reference.h"
-
-#include <assert.h>
-
-/*
-========================================================================
-
-.FM triangle flexible model file format
-
-========================================================================
-*/
-
-//=================================================================
-
-#define NUMVERTEXNORMALS	162
-
-extern float	avertexnormals[NUMVERTEXNORMALS][3];
-
-#define MAX_GROUPS	128
-
-typedef struct
-{
-	triangle_t	triangle;
-	int		group;
-} trigroup_t;
-
-#define TRIVERT_DIST	.1
-
-typedef struct
-{
-	int			start_frame;
-	int		num_frames;
-	int			degrees;
-	char *mat;
-	char *ccomp;
-	char *cbase;
-	float *cscale;
-	float *coffset;
-	float trans[3];
-	float scale[3];
-	float bmin[3];
-	float bmax[3];
-} fmgroup_t;
-
-//================================================================
-
-// Initial
-fmheader_t	fmheader;
-
-// Skin
-extern char			g_skins[MAX_FM_SKINS][64];
-
-// ST Coord
-extern fmstvert_t	base_st[MAX_FM_VERTS];
-
-// Triangles
-extern fmtriangle_t	triangles[MAX_FM_TRIANGLES];
-
-// Frames
-fmframe_t	g_frames[MAX_FM_FRAMES];
-//fmframe_t	*g_FMframes;
-
-// GL Commands
-extern int			commands[16384];
-extern int			numcommands;
-
-
-//
-// varibles set by commands
-//
-extern float		scale_up;						// set by $scale
-extern vec3_t		adjust;							// set by $origin
-extern int			g_fixedwidth, g_fixedheight;	// set by $skinsize
-extern char			modelname[64];					// set by $modelname
-
-
-extern 	char		*g_outputDir;
-
-
-// Mesh Nodes
-mesh_node_t	*pmnodes = NULL;
-fmmeshnode_t	mesh_nodes[MAX_FM_MESH_NODES]; 
-
-fmgroup_t	groups[MAX_GROUPS];
-int			num_groups;
-int	frame_to_group[MAX_FM_FRAMES];
-
-//
-// variables set by command line arguments
-//
-qboolean	g_no_opimizations = false;
-
-
-//
-// base frame info
-//
-static int			triangle_st[MAX_FM_TRIANGLES][3][2];
-
-
-// number of gl vertices
-extern int			numglverts;
-// indicates if a triangle has already been used in a glcmd
-extern int			used[MAX_FM_TRIANGLES];
-// indicates if a triangle has translucency in it or not
-static qboolean		translucent[MAX_FM_TRIANGLES];
-
-// main output file handle
-extern FILE			*headerouthandle;
-// output sizes of buildst()
-static int			skin_width, skin_height;
-
-
-// statistics
-static int			total_skin_pixels;
-static int			skin_pixels_used;
-
-int ShareVertex( trigroup_t trione, trigroup_t tritwo);
-float DistBetween(vec3_t point1, vec3_t point2);
-int GetNumTris( trigroup_t *tris, int group);
-void GetOneGroup(trigroup_t *tris, int grp, triangle_t* triangles);
-void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts);
-void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height);
-
-#ifndef _WIN32
-
-void strupr(char *string)
-{
-	int i;
-
-	for (i=0 ; i<strlen(string); i++)
-		toupper(string[i]);
-
-	return;
-}
-
-#endif
-//==============================================================
-
-/*
-===============
-ClearModel
-===============
-*/
-static void ClearModel (void)
-{
-	memset (&fmheader, 0, sizeof(fmheader));
-
-	modelname[0] = 0;
-	scale_up = 1.0;	
-	VectorCopy (vec3_origin, adjust);
-	g_fixedwidth = g_fixedheight = 0;
-	g_skipmodel = false;
-	num_groups = 0;
-
-	if (pmnodes)
-	{
-		free(pmnodes);
-		pmnodes = NULL;
-	}
-
-	ClearSkeletalModel();
-}
-
-
-extern void H_printf(char *fmt, ...);
-
-
-void WriteHeader(FILE *FH, char *Ident, int Version, int Size, void *Data)
-{
-	header_t	header;
-	static long	pos = -1;
-	long		CurrentPos;
-
-	if (Size == 0)
-	{	// Don't write out empty packets
-		return;
-	}
-
-	if (pos != -1)
-	{
-		CurrentPos = ftell(FH);
-		Size = CurrentPos - pos + sizeof(header_t);
-		fseek(FH, pos, SEEK_SET);
-		pos = -2;
-	}
-	else if (Size == -1)
-	{
-		pos = ftell(FH);
-	}
-
-	memset(&header,0,sizeof(header));
-	strcpy(header.ident,Ident);
-	header.version = Version;
-	header.size = Size;
-
-	SafeWrite (FH, &header, sizeof(header));
-
-	if (Data)
-	{
-		SafeWrite (FH, Data, Size);
-	}
-
-	if (pos == -2)
-	{
-		pos = -1;
-		fseek(FH, 0, SEEK_END);
-	}
-}
-
-/*
-============
-WriteModelFile
-============
-*/
-static void WriteModelFile (FILE *modelouthandle)
-{
-	int				i;
-	int				j, k;
-	fmframe_t		*in;
-	fmaliasframe_t	*out;
-	byte			buffer[MAX_FM_VERTS*4+128];
-	float			v;
-	int				c_on, c_off;
-	IntListNode_t	*current, *toFree;
-	qboolean framesWritten = false;
-	size_t temp ,size = 0;
-
-	// probably should do this dynamically one of these days
-	struct
-	{
-		float		scale[3];	// multiply byte verts by this
-		float		translate[3];	// then add this
-	} outFrames[MAX_FM_FRAMES];
-
-#define DATA_SIZE 0x60000		// 384K had better be enough, particularly for the reference points
-	byte data[DATA_SIZE];
-	byte data2[DATA_SIZE];
-
-	fmheader.num_glcmds = numcommands;
-	fmheader.framesize = (int)&((fmaliasframe_t *)0)->verts[fmheader.num_xyz];
-
-	WriteHeader(modelouthandle, FM_HEADER_NAME, FM_HEADER_VER, sizeof(fmheader), &fmheader);
-
-	//
-	// write out the skin names
-	//
-
- 	WriteHeader(modelouthandle, FM_SKIN_NAME, FM_SKIN_VER, fmheader.num_skins * MAX_FM_SKINNAME, g_skins);
-
-	//
-	// write out the texture coordinates
-	//
-	c_on = c_off = 0;
-	for (i=0 ; i<fmheader.num_st ; i++)
-	{
-		base_st[i].s = LittleShort (base_st[i].s);
-		base_st[i].t = LittleShort (base_st[i].t);
-	}
-
-	WriteHeader(modelouthandle, FM_ST_NAME, FM_ST_VER, fmheader.num_st * sizeof(base_st[0]), base_st);
-
-	//
-	// write out the triangles
-	//
-	WriteHeader(modelouthandle, FM_TRI_NAME, FM_TRI_VER, fmheader.num_tris * sizeof(fmtriangle_t), NULL);
-
-	for (i=0 ; i<fmheader.num_tris ; i++)
-	{
-		int				j;
-		fmtriangle_t	tri;
-
-		for (j=0 ; j<3 ; j++)
-		{
-			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
-			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
-		}
-
-		SafeWrite (modelouthandle, &tri, sizeof(tri));
-	}
-
-	if (!num_groups)
-	{
-		//
-		// write out the frames
-		//
-		WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, fmheader.num_frames * fmheader.framesize, NULL);
-	//	WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
-
-		for (i=0 ; i<fmheader.num_frames ; i++)
-		{
-			in = &g_frames[i];
-			out = (fmaliasframe_t *)buffer;
-
-			strcpy (out->name, in->name);
-			for (j=0 ; j<3 ; j++)
-			{
-				out->scale[j] = (in->maxs[j] - in->mins[j])/255;
-				out->translate[j] = in->mins[j];
-
-				outFrames[i].scale[j] = out->scale[j];
-				outFrames[i].translate[j] = out->translate[j];
-			}
-
-			for (j=0 ; j<fmheader.num_xyz ; j++)
-			{
-			// all of these are byte values, so no need to deal with endianness
-				out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
-
-				for (k=0 ; k<3 ; k++)
-				{
-				// scale to byte values & min/max check
-					v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
-
-				// clamp, so rounding doesn't wrap from 255.6 to 0
-					if (v > 255.0)
-						v = 255.0;
-					if (v < 0)
-						v = 0;
-					out->verts[j].v[k] = v;
-				}
-			}
-
-			for (j=0 ; j<3 ; j++)
-			{
-				out->scale[j] = LittleFloat (out->scale[j]);
-				out->translate[j] = LittleFloat (out->translate[j]);
-			}
-
-			SafeWrite (modelouthandle, out, fmheader.framesize);
-		}
-
-		// Go back and finish the header
-	//	WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
-	}
-	else
-	{
-		WriteHeader(modelouthandle, FM_SHORT_FRAME_NAME, FM_SHORT_FRAME_VER,FRAME_NAME_LEN*fmheader.num_frames, NULL);
-		for (i=0 ; i<fmheader.num_frames ; i++)
-		{
-			in = &g_frames[i];
-			SafeWrite (modelouthandle,in->name,FRAME_NAME_LEN);
-		}
-		WriteHeader(modelouthandle, FM_NORMAL_NAME, FM_NORMAL_VER,fmheader.num_xyz, NULL);
-		in = &g_frames[0];
-		for (j=0 ; j<fmheader.num_xyz ; j++)
-			SafeWrite (modelouthandle,&in->v[j].lightnormalindex,1);
-	}
-
-	//
-	// write out glcmds
-	//
-	WriteHeader(modelouthandle, FM_GLCMDS_NAME, FM_GLCMDS_VER, numcommands*4, commands);
-
-	//
-	// write out mesh nodes
-	//
-	for(i=0;i<fmheader.num_mesh_nodes;i++)
-	{
-		memcpy(mesh_nodes[i].tris, pmnodes[i].tris, sizeof(mesh_nodes[i].tris));
-		memcpy(mesh_nodes[i].verts, pmnodes[i].verts, sizeof(mesh_nodes[i].verts));
-		mesh_nodes[i].start_glcmds = LittleShort((short)pmnodes[i].start_glcmds);
-		mesh_nodes[i].num_glcmds = LittleShort((short)pmnodes[i].num_glcmds);
-	}
-
-	WriteHeader(modelouthandle, FM_MESH_NAME, FM_MESH_VER, sizeof(fmmeshnode_t) * fmheader.num_mesh_nodes, mesh_nodes);
-
-	if (num_groups)
-	{
-
-/*
-typedef struct
-{
-	int			start_frame;
-	int			num_frames;
-	int			degrees;
-	char *mat; fmheader.num_xyz*3*g->degrees*sizeof(char)
-	char *ccomp; g->num_frames*g->degrees*sizeof(char)
-	char *cbase; fmheader.num_xyz*3*sizeof(unsigned char)
-	float *cscale; g->degrees*sizeof(float)
-	float *coffset; g->degrees*sizeof(float)
-	float trans[3]; 3*sizeof(float)
-	float scale[3]; 3*sizeof(float)
-} fmgroup_t;
-*/
-		int tmp,k;
-		fmgroup_t *g;
-		size=sizeof(int)+fmheader.num_frames*sizeof(int);
-		for (k=0;k<num_groups;k++)
-		{
-			g=&groups[k];
-			size+=sizeof(int)*3;
-			size+=fmheader.num_xyz*3*g->degrees*sizeof(char);
-			size+=g->num_frames*g->degrees*sizeof(char);
-			size+=fmheader.num_xyz*3*sizeof(unsigned char);
-			size+=g->degrees*sizeof(float);
-			size+=g->degrees*sizeof(float);
-			size+=12*sizeof(float);
-		}
-		WriteHeader(modelouthandle, FM_COMP_NAME, FM_COMP_VER,size, NULL);
-		SafeWrite (modelouthandle,&num_groups,sizeof(int));
-		SafeWrite (modelouthandle,frame_to_group,sizeof(int)*fmheader.num_frames);
-
-		for (k=0;k<num_groups;k++)
-		{
-			g=&groups[k];
-			tmp=LittleLong(g->start_frame);
-			SafeWrite (modelouthandle,&tmp,sizeof(int));
-			tmp=LittleLong(g->num_frames);
-			SafeWrite (modelouthandle,&tmp,sizeof(int));
-			tmp=LittleLong(g->degrees);
-			SafeWrite (modelouthandle,&tmp,sizeof(int));
-
-			SafeWrite (modelouthandle,g->mat,fmheader.num_xyz*3*g->degrees*sizeof(char));
-			SafeWrite (modelouthandle,g->ccomp,g->num_frames*g->degrees*sizeof(char));
-			SafeWrite (modelouthandle,g->cbase,fmheader.num_xyz*3*sizeof(unsigned char));
-			SafeWrite (modelouthandle,g->cscale,g->degrees*sizeof(float));
-			SafeWrite (modelouthandle,g->coffset,g->degrees*sizeof(float));
-			SafeWrite (modelouthandle,g->trans,3*sizeof(float));
-			SafeWrite (modelouthandle,g->scale,3*sizeof(float));
-			SafeWrite (modelouthandle,g->bmin,3*sizeof(float));
-			SafeWrite (modelouthandle,g->bmax,3*sizeof(float));
-			free(g->mat);
-			free(g->ccomp);
-			free(g->cbase);
-			free(g->cscale);
-			free(g->coffset);
-		}
-	}
-
-	// write the skeletal info
-	if(g_skelModel.type != SKEL_NULL)
-	{
-		size = 0;
-
-		temp = sizeof(int);		// change this to a byte
-		memcpy(data + size, &g_skelModel.type, temp);
-		size += temp;
-
-		// number of joints
-		temp = sizeof(int);		// change this to a byte
-		memcpy(data + size, &numJointsInSkeleton[g_skelModel.type], temp);
-		size += temp;
-
-		// number of verts in each joint cluster
-		temp = sizeof(int)*numJointsInSkeleton[g_skelModel.type]; // change this to shorts
-		memcpy(data + size, &g_skelModel.new_num_verts[1], temp);
-		size += temp;
-
-		// cluster verts
-		for(i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)
-		{
-			current = g_skelModel.vertLists[i];
-			while(current)
-			{
-				temp = sizeof(int);	// change this to a short
-				memcpy(data + size, &current->data, temp);
-				size += temp;
-				toFree = current;
-				current = current->next;
-				free(toFree);  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
-			}
-		}
-
-		if(!num_groups) // joints are stored with regular verts for compressed models
-		{
-			framesWritten = true;
-
-			temp = sizeof(int);	// change this to a byte
-			memcpy(data + size, &framesWritten, temp);
-			size += temp;
-
-			for (i = 0; i < fmheader.num_frames; ++i)
-			{
-				in = &g_frames[i];
-
-				for (j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j)
-				{
-					for (k=0 ; k<3 ; k++)
-					{
-						// scale to byte values & min/max check
-						v = Q_rint ( (in->joints[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-						// write out origin as a float since they arn't clamped
-						temp = sizeof(float);	// change this to a short
-						assert(size+temp < DATA_SIZE);
-						memcpy(data + size, &v, temp);
-						size += temp;
-					}
-
-					for (k=0 ; k<3 ; k++)
-					{
-						v = Q_rint ( (in->joints[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-						// write out origin as a float since they arn't clamped
-						temp = sizeof(float);	// change this to a short
-						assert(size+temp < DATA_SIZE);
-						memcpy(data + size, &v, temp);
-						size += temp;
-					}
-
-					for (k=0 ; k<3 ; k++)
-					{
-						v = Q_rint ( (in->joints[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-						// write out origin as a float since they arn't clamped
-						temp = sizeof(float);	// change this to a short
-						assert(size+temp < DATA_SIZE);
-						memcpy(data + size, &v, temp);
-						size += temp;
-					}
-				}
-			}
-
-		}
-		else
-		{
-			temp = sizeof(int);	// change this to a byte
-			memcpy(data + size, &framesWritten, temp);
-			size += temp;
-		}
-
-		WriteHeader(modelouthandle, FM_SKELETON_NAME, FM_SKELETON_VER, size, data);
-	}
-
-	if(g_skelModel.references != REF_NULL)
-	{
-		int refnum;
-
-		size = 0;
-		if (RefPointNum <= 0)
-		{	// Hard-coded labels
-			refnum = numReferences[g_skelModel.references];
-		}
-		else
-		{	// Labels indicated in QDT
-			refnum = RefPointNum;
-		}
-
-		temp = sizeof(int);	// change this to a byte
-		memcpy(data2 + size, &g_skelModel.references, temp);
-		size += temp;
-
-		if(!num_groups)
-		{
-			framesWritten = true;
-
-			temp = sizeof(int);	// change this to a byte
-			memcpy(data2 + size, &framesWritten, temp);
-			size += temp;
-
-			for (i = 0; i < fmheader.num_frames; ++i)
-			{
-				in = &g_frames[i];
-
-				for (j = 0 ; j < refnum; ++j)
-				{
-					for (k=0 ; k<3 ; k++)
-					{
-						// scale to byte values & min/max check
-						v = Q_rint ( (in->references[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-						// write out origin as a float since they arn't clamped
-						temp = sizeof(float);	// change this to a short
-						assert(size+temp < DATA_SIZE);
-						memcpy(data2 + size, &v, temp);
-						size += temp;
-					}
-
-					for (k=0 ; k<3 ; k++)
-					{
-						v = Q_rint ( (in->references[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-						// write out origin as a float since they arn't clamped
-						temp = sizeof(float);	// change this to a short
-						assert(size+temp < DATA_SIZE);
-						memcpy(data2 + size, &v, temp);
-						size += temp;
-					}
-
-					for (k=0 ; k<3 ; k++)
-					{
-						v = Q_rint ( (in->references[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-						// write out origin as a float since they arn't clamped
-						temp = sizeof(float);	// change this to a short
-						assert(size+temp < DATA_SIZE);
-						memcpy(data2 + size, &v, temp);
-						size += temp;
-					}
-				}
-			}
-		}
-		else	// FINISH ME: references need to be stored with regular verts for compressed models
-		{
-			framesWritten = false;
-
-			temp = sizeof(int);	// change this to a byte
-			memcpy(data2 + size, &framesWritten, temp);
-			size += temp;
-		}
-
-		WriteHeader(modelouthandle, FM_REFERENCES_NAME, FM_REFERENCES_VER, size, data2);
-	}
-}
-
-static void CompressFrames()
-{
-	fmgroup_t *g;
-	int i,j,k;
-	fmframe_t	*in;
-
-	j=0;
-	for (i=0;i<fmheader.num_frames;i++)
-	{
-		while (i>=groups[j].start_frame+groups[j].num_frames&&j<num_groups-1)
-			j++;
-		frame_to_group[i]=j;
-	}
-
-	for (k=0;k<num_groups;k++)
-	{
-		g=&groups[k];
-
-		printf("\nCompressing Frames for group %i...\n", k);
-		AnimCompressInit(g->num_frames,fmheader.num_xyz,g->degrees);
-		for (i=0;i<g->num_frames;i++)
-		{
-			in = &g_frames[i+g->start_frame];
-			for (j=0;j<fmheader.num_xyz;j++)
-				AnimSetFrame(i,j,in->v[j].v[0],in->v[j].v[1],in->v[j].v[2]);
-		}
-		AnimCompressDoit();
-		g->mat= (char *) SafeMalloc(fmheader.num_xyz*3*g->degrees*sizeof(char), "CompressFrames");
-		g->ccomp=(char *) SafeMalloc(g->num_frames*g->degrees*sizeof(char), "CompressFrames");
-		g->cbase=(char *) SafeMalloc(fmheader.num_xyz*3*sizeof(unsigned char), "CompressFrames");
-		g->cscale=(float *) SafeMalloc(g->degrees*sizeof(float), "CompressFrames");
-		g->coffset=(float *) SafeMalloc(g->degrees*sizeof(float), "CompressFrames");
-		AnimCompressToBytes(g->trans,g->scale,g->mat,g->ccomp,g->cbase,g->cscale,g->coffset,g->bmin,g->bmax);
-		AnimCompressEnd();
-	}
-}
-
-static void OptimizeVertices(void)
-{
-	qboolean	vert_used[MAX_FM_VERTS];
-	short		vert_replacement[MAX_FM_VERTS];
-	int			i,j,k,l,pos,bit,set_pos,set_bit;
-	fmframe_t	*in;
-	qboolean	Found;
-	int			num_unique;
-	static IntListNode_t *newVertLists[NUM_CLUSTERS];
-	static int newNum_verts[NUM_CLUSTERS];
-	IntListNode_t *current, *next;
-
-	printf("Optimizing vertices...");
-
-	memset(vert_used, 0, sizeof(vert_used));
-
-	if(g_skelModel.clustered == true)
-	{
-		memset(newNum_verts, 0, sizeof(newNum_verts));
-		memset(newVertLists, 0, sizeof(newVertLists));
-	}
-
-	num_unique = 0;
-
-	// search for common points among all the frames
-	for (i=0 ; i<fmheader.num_frames ; i++)
-	{
-		in = &g_frames[i];
-
-		for(j=0;j<fmheader.num_xyz;j++)
-		{
-			for(k=0,Found=false;k<j;k++)
-			{	// starting from the beginning always ensures vert_replacement points to the first point in the array
-				if (in->v[j].v[0] == in->v[k].v[0] &&
-					in->v[j].v[1] == in->v[k].v[1] &&
-					in->v[j].v[2] == in->v[k].v[2])
-				{
-					Found = true;
-					vert_replacement[j] = k;
-					break;
-				}
-
-			}
-
-			if (!Found)
-			{
-				if (!vert_used[j])
-				{
-					num_unique++;
-				}
-				vert_used[j] = true;
-			}
-		}
-	}
-
-	// recompute the light normals
-	for (i=0 ; i<fmheader.num_frames ; i++)
-	{
-		in = &g_frames[i];
-
-		for(j=0;j<fmheader.num_xyz;j++)
-		{
-			if (!vert_used[j])
-			{
-				k = vert_replacement[j];
-
-				VectorAdd (in->v[j].vnorm.normalsum, in->v[k].vnorm.normalsum, in->v[k].vnorm.normalsum);
-				in->v[k].vnorm.numnormals += in->v[j].vnorm.numnormals++;
-			}
-		}
-
-		for (j=0 ; j<fmheader.num_xyz ; j++)
-		{
-			vec3_t	v;
-			float	maxdot;
-			int		maxdotindex;
-			int		c;
-
-			c = in->v[j].vnorm.numnormals;
-			if (!c)
-				Error ("Vertex with no triangles attached");
-
-			VectorScale (in->v[j].vnorm.normalsum, 1.0/c, v);
-			VectorNormalize (v, v);
-
-			maxdot = -999999.0;
-			maxdotindex = -1;
-
-			for (k=0 ; k<NUMVERTEXNORMALS ; k++)
-			{
-				float	dot;
-
-				dot = DotProduct (v, avertexnormals[k]);
-				if (dot > maxdot)
-				{
-					maxdot = dot;
-					maxdotindex = k;
-				}
-			}
-
-			in->v[j].lightnormalindex = maxdotindex;
-		}
-	}
-
-	// create substitution list
-	num_unique = 0;
-	for(i=0;i<fmheader.num_xyz;i++)
-	{
-		if (vert_used[i])
-		{
-			vert_replacement[i] = num_unique;
-			num_unique++;
-		}
-		else
-		{
-			vert_replacement[i] = vert_replacement[vert_replacement[i]];
-		}
-
-		// vert_replacement[i] is the new index, i is the old index
-		// need to add the new index to the cluster list if old index was in it
-		if(g_skelModel.clustered == true)
-		{
-			for(k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k)
-			{
-				for(l = 0, current = g_skelModel.vertLists[k]; 
-					l < g_skelModel.new_num_verts[k+1]; ++l, current = current->next)
-				{
-					if(current->data == i)
-					{
-						IntListNode_t *current2;
-						int m;
-						qboolean added = false;
-
-						for(m = 0, current2 = newVertLists[k]; m < newNum_verts[k+1];
-							++m, current2 = current2->next)
-						{
-							if(current2->data == vert_replacement[i])
-							{
-								added = true;
-								break;
-							}
-						}
-
-						if(!added)
-						{
-							++newNum_verts[k+1];
-
-							next = newVertLists[k];
-
-							newVertLists[k] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "OptimizeVertices");
-							// freed after model write out
-
-							newVertLists[k]->data = vert_replacement[i];
-							newVertLists[k]->next = next;
-						}
-						break;
-					}
-				}
-			}
-		}
-	}
-
-	// substitute
-	for (i=0 ; i<fmheader.num_frames ; i++)
-	{
-		in = &g_frames[i];
-
-		for(j=0;j<fmheader.num_xyz;j++)
-		{
-			in->v[vert_replacement[j]] = in->v[j];
-		}
-
-	}
-
-	for(i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)
-	{
-		IntListNode_t *toFree;
-		current = g_skelModel.vertLists[i];
-
-		while(current)
-		{
-			toFree = current;
-			current = current->next;
-			free(toFree);  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
-		}
-
-		g_skelModel.vertLists[i] = newVertLists[i];
-		g_skelModel.new_num_verts[i+1] = newNum_verts[i+1];
-	}
-
-#ifndef NDEBUG
-	for(k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k)
-	{
-		for(l = 0, current = g_skelModel.vertLists[k]; 
-			l < g_skelModel.new_num_verts[k+1]; ++l, current = current->next)
-		{
-			IntListNode_t *current2;
-			int m;
-
-			for(m = l+1, current2 = current->next; m < newNum_verts[k+1];
-				++m, current2 = current2->next)
-			{
-				if(current->data == current2->data)
-				{
-					printf("Warning duplicate vertex:  %d\n", current->data);
-					break;
-				}
-			}
-		}
-	}
-#endif
-
-	for(i=0;i<fmheader.num_mesh_nodes;i++)
-	{	// reset the vert bits
-		memset(pmnodes[i].verts,0,sizeof(pmnodes[i].verts));
-	}
-
-	// repleace the master triangle list vertex indexes and update the vert bits for each mesh node
-	for (i=0 ; i<fmheader.num_tris ; i++)
-	{
-		pos = i >> 3;
-		bit = 1 << (i & 7 );
-
-		for (j=0 ; j<3 ; j++)
-		{	
-			set_bit = set_pos = triangles[i].index_xyz[j] = vert_replacement[triangles[i].index_xyz[j]];
-
-			set_pos >>= 3;
-			set_bit = 1 << (set_bit & 7);
-
-			for(k=0;k<fmheader.num_mesh_nodes;k++)
-			{
-				if (!(pmnodes[k].tris[pos] & bit))
-				{
-					continue;
-				}
-				pmnodes[k].verts[set_pos] |= set_bit;
-			}
-		}
-	}
-
-	for (i=0;i<numcommands;i++)
-	{
-		j = commands[i];
-		if (!j) continue;
-
-		j = abs(j);
-		for(i++;j;j--,i+=3)
-		{
-			commands[i+2] = vert_replacement[commands[i+2]];
-		}
-		i--;
-	}
-
-	printf("Reduced by %d\n",fmheader.num_xyz - num_unique);
-	
-	fmheader.num_xyz = num_unique;
-	if (num_groups)
-	{
-		// tack on the reference verts to the regular verts
-		if(g_skelModel.references != REF_NULL)
-		{
-			fmframe_t	*in;
-			int index;
-			int refnum;
-
-			if (RefPointNum <= 0)
-			{	// Hard-coded labels
-				refnum = numReferences[g_skelModel.references];
-			}
-			else
-			{	// Labels indicated in QDT
-				refnum = RefPointNum;
-			}
-
-
-			for (i = 0; i < fmheader.num_frames; ++i)
-			{
-				in = &g_frames[i];
-				index = fmheader.num_xyz;
-
-				for (j = 0 ; j < refnum; ++j)
-				{
-					VectorCopy(in->references[j].placement.origin, in->v[index].v);
-					index++;
-
-					VectorCopy(in->references[j].placement.direction, in->v[index].v);
-					index++;
-
-					VectorCopy(in->references[j].placement.up, in->v[index].v);
-					index++;
-				}
-			}
-
-			fmheader.num_xyz += refnum*3;
-		}
-
-		// tack on the skeletal joint verts to the regular verts
-		if(g_skelModel.type != SKEL_NULL)
-		{
-			fmframe_t	*in;
-			int index;
-
-			for (i = 0; i < fmheader.num_frames; ++i)
-			{
-				in = &g_frames[i];
-				index = fmheader.num_xyz;
-
-				for (j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j)
-				{
-					VectorCopy(in->joints[j].placement.origin, in->v[index].v);
-					index++;
-
-					VectorCopy(in->joints[j].placement.direction, in->v[index].v);
-					index++;
-
-					VectorCopy(in->joints[j].placement.up, in->v[index].v);
-					index++;
-				}
-			}
-
-			fmheader.num_xyz += numJointsInSkeleton[g_skelModel.type]*3;
-		}
-
-		CompressFrames();
-	}
-}
-
-
-/*
-===============
-FinishModel
-===============
-*/
-void FMFinishModel (void)
-{
-	FILE		*modelouthandle;
-	int			i,j,length,tris,verts,bit,pos,total_tris,total_verts;
-	char		name[1024];
-	int			trans_count;
-	
-	if (!fmheader.num_frames)
-		return;
-	
-//
-// copy to release directory tree if doing a release build
-//
-	if (g_release)
-	{
-		if (modelname[0])
-			sprintf (name, "%s", modelname);
-		else
-			sprintf (name, "%s/tris.fm", cdpartial);
-		ReleaseFile (name);
-
-		for (i=0 ; i<fmheader.num_skins ; i++)
-		{
-			ReleaseFile (g_skins[i]);
-		}
-		fmheader.num_frames = 0;
-		return;
-	}
-
-	printf("\n");
-
-	trans_count = 0;
-	for(i=0;i<fmheader.num_tris;i++)
-		if (translucent[i])
-			trans_count++;
-
-	if (!g_no_opimizations)
-	{
-		OptimizeVertices();
-	}
-
-//
-// write the model output file
-//
-	if (modelname[0])
-		sprintf (name, "%s%s", g_outputDir, modelname);
-	else
-		sprintf (name, "%s/tris.fm", g_outputDir);
-	printf ("saving to %s\n", name);
-	CreatePath (name);
-	modelouthandle = SafeOpenWrite (name);
-
-	WriteModelFile (modelouthandle);
-	
-	printf ("%3dx%3d skin\n", fmheader.skinwidth, fmheader.skinheight);
-	printf ("First frame boundaries:\n");
-	printf ("	minimum x: %3f\n", g_frames[0].mins[0]);
-	printf ("	maximum x: %3f\n", g_frames[0].maxs[0]);
-	printf ("	minimum y: %3f\n", g_frames[0].mins[1]);
-	printf ("	maximum y: %3f\n", g_frames[0].maxs[1]);
-	printf ("	minimum z: %3f\n", g_frames[0].mins[2]);
-	printf ("	maximum z: %3f\n", g_frames[0].maxs[2]);
-	printf ("%4d vertices\n", fmheader.num_xyz);
-	printf ("%4d triangles, %4d of them translucent\n", fmheader.num_tris, trans_count);
-	printf ("%4d frame\n", fmheader.num_frames);
-	printf ("%4d glverts\n", numglverts);
-	printf ("%4d glcmd\n", fmheader.num_glcmds);
-	printf ("%4d skins\n", fmheader.num_skins);
-	printf ("%4d mesh nodes\n", fmheader.num_mesh_nodes);
-	printf ("wasted pixels: %d / %d (%5.2f Percent)\n",total_skin_pixels - skin_pixels_used, 
-		total_skin_pixels, (double)(total_skin_pixels - skin_pixels_used) / (double)total_skin_pixels * 100.0);
-
-	printf ("file size: %d\n", (int)ftell (modelouthandle) );
-	printf ("---------------------\n");
-	
-	if (g_verbose)
-	{
-		if (fmheader.num_mesh_nodes)
-		{
-			total_tris = total_verts = 0;
-			printf("Node Name                         Tris Verts\n");
-			printf("--------------------------------- ---- -----\n");
-			for(i=0;i<fmheader.num_mesh_nodes;i++)
-			{
-				tris = 0;
-				verts = 0;
-				for(j=0;j<MAXTRIANGLES;j++)
-				{
-					pos = (j) >> 3;
-					bit = 1 << ((j) & 7 );
-					if (pmnodes[i].tris[pos] & bit)
-					{
-						tris++;
-					}
-				}
-				for(j=0;j<MAX_FM_VERTS;j++)
-				{
-					pos = (j) >> 3;
-					bit = 1 << ((j) & 7 );
-					if (pmnodes[i].verts[pos] & bit)
-					{
-						verts++;
-					}
-				}
-
-				printf("%-33s %4d %5d\n",pmnodes[i].name,tris,verts);
-
-				total_tris += tris;
-				total_verts += verts;
-			}
-			printf("--------------------------------- ---- -----\n");
-			printf("%-33s %4d %5d\n","TOTALS",total_tris,total_verts);
-		}
-	}
-	fclose (modelouthandle);
-
-	// finish writing header file
-	H_printf("\n");
-
-	// scale_up is usefull to allow step distances to be adjusted
-	H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
-
-	// mesh nodes
-	if (fmheader.num_mesh_nodes)
-	{
-		H_printf("\n");
-		H_printf("#define NUM_MESH_NODES\t\t%d\n\n",fmheader.num_mesh_nodes);
-		for(i=0;i<fmheader.num_mesh_nodes;i++)
-		{
-			strcpy(name, pmnodes[i].name);
-			strupr(name);
-			length = strlen(name);
-			for(j=0;j<length;j++)
-			{
-				if (name[j] == ' ')
-				{
-					name[j] = '_';
-				}
-			}
-			H_printf("#define MESH_%s\t\t%d\n", name, i);
-		}
-	}
-
-	fclose (headerouthandle);
-	headerouthandle = NULL;
-	free (pmnodes);
-}
-
-
-/*
-=================================================================
-
-ALIAS MODEL DISPLAY LIST GENERATION
-
-=================================================================
-*/
-
-extern int		strip_xyz[128];
-extern int		strip_st[128];
-extern int		strip_tris[128];
-extern int		stripcount;
-
-/*
-================
-StripLength
-================
-*/
-static int	StripLength (int starttri, int startv, int num_tris, int node)
-{
-	int				m1, m2;
-	int				st1, st2;
-	int				j;
-	fmtriangle_t	*last, *check;
-	int				k;
-	int				pos, bit;
-
-	used[starttri] = 2;
-
-	last = &triangles[starttri];
-
-	strip_xyz[0] = last->index_xyz[(startv)%3];
-	strip_xyz[1] = last->index_xyz[(startv+1)%3];
-	strip_xyz[2] = last->index_xyz[(startv+2)%3];
-	strip_st[0] = last->index_st[(startv)%3];
-	strip_st[1] = last->index_st[(startv+1)%3];
-	strip_st[2] = last->index_st[(startv+2)%3];
-
-	strip_tris[0] = starttri;
-	stripcount = 1;
-
-	m1 = last->index_xyz[(startv+2)%3];
-	st1 = last->index_st[(startv+2)%3];
-	m2 = last->index_xyz[(startv+1)%3];
-	st2 = last->index_st[(startv+1)%3];
-
-	// look for a matching triangle
-nexttri:
-	for (j=starttri+1, check=&triangles[starttri+1]
-		; j<num_tris ; j++, check++)
-	{
-		pos = j >> 3;
-		bit = 1 << (j & 7 );
-		if (!(pmnodes[node].tris[pos] & bit))
-		{
-			continue;
-		}
-		for (k=0 ; k<3 ; k++)
-		{
-			if (check->index_xyz[k] != m1)
-				continue;
-			if (check->index_st[k] != st1)
-				continue;
-			if (check->index_xyz[ (k+1)%3 ] != m2)
-				continue;
-			if (check->index_st[ (k+1)%3 ] != st2)
-				continue;
-
-			// this is the next part of the fan
-
-			// if we can't use this triangle, this tristrip is done
-			if (used[j] || translucent[j] != translucent[starttri])
-				goto done;
-
-			// the new edge
-			if (stripcount & 1)
-			{
-				m2 = check->index_xyz[ (k+2)%3 ];
-				st2 = check->index_st[ (k+2)%3 ];
-			}
-			else
-			{
-				m1 = check->index_xyz[ (k+2)%3 ];
-				st1 = check->index_st[ (k+2)%3 ];
-			}
-
-			strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
-			strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
-			strip_tris[stripcount] = j;
-			stripcount++;
-
-			used[j] = 2;
-			goto nexttri;
-		}
-	}
-done:
-
-	// clear the temp used flags
-	for (j=starttri+1 ; j<num_tris ; j++)
-		if (used[j] == 2)
-			used[j] = 0;
-
-	return stripcount;
-}
-
-
-/*
-===========
-FanLength
-===========
-*/
-static int	FanLength (int starttri, int startv, int num_tris, int node)
-{
-	int				m1, m2;
-	int				st1, st2;
-	int				j;
-	fmtriangle_t	*last, *check;
-	int				k;
-	int				pos, bit;
-
-	used[starttri] = 2;
-
-	last = &triangles[starttri];
-
-	strip_xyz[0] = last->index_xyz[(startv)%3];
-	strip_xyz[1] = last->index_xyz[(startv+1)%3];
-	strip_xyz[2] = last->index_xyz[(startv+2)%3];
-	strip_st[0] = last->index_st[(startv)%3];
-	strip_st[1] = last->index_st[(startv+1)%3];
-	strip_st[2] = last->index_st[(startv+2)%3];
-
-	strip_tris[0] = starttri;
-	stripcount = 1;
-
-	m1 = last->index_xyz[(startv+0)%3];
-	st1 = last->index_st[(startv+0)%3];
-	m2 = last->index_xyz[(startv+2)%3];
-	st2 = last->index_st[(startv+2)%3];
-
-
-	// look for a matching triangle
-nexttri:
-	for (j=starttri+1, check=&triangles[starttri+1] 
-		; j<num_tris ; j++, check++)
-	{
-		pos = j >> 3;
-		bit = 1 << (j & 7 );
-		if (!(pmnodes[node].tris[pos] & bit))
-		{
-			continue;
-		}
-		for (k=0 ; k<3 ; k++)
-		{
-			if (check->index_xyz[k] != m1)
-				continue;
-			if (check->index_st[k] != st1)
-				continue;
-			if (check->index_xyz[ (k+1)%3 ] != m2)
-				continue;
-			if (check->index_st[ (k+1)%3 ] != st2)
-				continue;
-
-			// this is the next part of the fan
-
-			// if we can't use this triangle, this tristrip is done
-			if (used[j] || translucent[j] != translucent[starttri])
-				goto done;
-
-			// the new edge
-			m2 = check->index_xyz[ (k+2)%3 ];
-			st2 = check->index_st[ (k+2)%3 ];
-
-			strip_xyz[stripcount+2] = m2;
-			strip_st[stripcount+2] = st2;
-			strip_tris[stripcount] = j;
-			stripcount++;
-
-			used[j] = 2;
-			goto nexttri;
-		}
-	}
-done:
-
-	// clear the temp used flags
-	for (j=starttri+1 ; j<num_tris ; j++)
-		if (used[j] == 2)
-			used[j] = 0;
-
-	return stripcount;
-}
-
-
-
-/*
-================
-BuildGlCmds
-
-Generate a list of trifans or strips
-for the model, which holds for all frames
-================
-*/
-static void BuildGlCmds (void)
-{
-	int		i, j, k, l;
-	int		startv;
-	float	s, t;
-	int		len, bestlen, besttype;
-	int		best_xyz[1024];
-	int		best_st[1024];
-	int		best_tris[1024];
-	int		type;
-	int		trans_check;
-	int		bit,pos;
-
-	//
-	// build tristrips
-	//
-	numcommands = 0;
-	numglverts = 0;
-
-
-	for(l=0;l<fmheader.num_mesh_nodes;l++)
-	{
-		memset (used, 0, sizeof(used));
-
-		pmnodes[l].start_glcmds = numcommands;
-
-		for(trans_check = 0; trans_check<2; trans_check++)
-		{
-			for (i=0 ; i < fmheader.num_tris ; i++)
-			{
-				pos = i >> 3;
-				bit = 1 << (i & 7 );
-				if (!(pmnodes[l].tris[pos] & bit))
-				{
-					continue;
-				}
-
-				// pick an unused triangle and start the trifan
-				if (used[i] || trans_check != translucent[i])
-				{
-					continue;
-				}
-
-				bestlen = 0;
-				for (type = 0 ; type < 2 ; type++)
-		//	type = 1;
-				{
-					for (startv =0 ; startv < 3 ; startv++)
-					{
-						if (type == 1)
-							len = StripLength (i, startv, fmheader.num_tris, l);
-						else
-							len = FanLength (i, startv, fmheader.num_tris, l);
-						if (len > bestlen)
-						{
-							besttype = type;
-							bestlen = len;
-							for (j=0 ; j<bestlen+2 ; j++)
-							{
-								best_st[j] = strip_st[j];
-								best_xyz[j] = strip_xyz[j];
-							}
-							for (j=0 ; j<bestlen ; j++)
-								best_tris[j] = strip_tris[j];
-						}
-					}
-				}
-
-				// mark the tris on the best strip/fan as used
-				for (j=0 ; j<bestlen ; j++)
-					used[best_tris[j]] = 1;
-
-				if (besttype == 1)
-					commands[numcommands++] = (bestlen+2);
-				else
-					commands[numcommands++] = -(bestlen+2);
-
-				numglverts += bestlen+2;
-
-				for (j=0 ; j<bestlen+2 ; j++)
-				{
-					// emit a vertex into the reorder buffer
-					k = best_st[j];
-
-					// emit s/t coords into the commands stream
-					s = base_st[k].s;
-					t = base_st[k].t;
-
-					s = (s  ) / fmheader.skinwidth;
-					t = (t  ) / fmheader.skinheight;
-
-					*(float *)&commands[numcommands++] = s;
-					*(float *)&commands[numcommands++] = t;
-					*(int *)&commands[numcommands++] = best_xyz[j];
-				}
-			}
-		}
-		commands[numcommands++] = 0;		// end of list marker
-		pmnodes[l].num_glcmds = numcommands - pmnodes[l].start_glcmds;
-	}
-}
-
-
-/*
-===============================================================
-
-BASE FRAME SETUP
-
-===============================================================
-*/
-
-
-#define LINE_NORMAL 1
-#define LINE_FAT 2
-#define LINE_DOTTED 3
-
-
-#define ASCII_SPACE 32
-
-int LineType = LINE_NORMAL;
-extern unsigned char pic[SKINPAGE_HEIGHT*SKINPAGE_WIDTH], pic_palette[768];
-unsigned char LineColor = 255;
-int ScaleWidth, ScaleHeight;
-
-
-static char *CharDefs[] =
-{
-	"-------------------------",
-	"-------------------------", // !
-	"-------------------------", // "
-	"-------------------------", // #
-	"-------------------------", // $
-	"-------------------------", // %
-	"-------------------------", // &
-	"--*----*-----------------", // '
-	"-*---*----*----*-----*---", // (
-	"*-----*----*----*---*----", // )
-	"-----*--*--**---**--*--*-", // *
-	"-------------------------", // +
-	"----------------**--**---", // ,
-	"-------------------------", // -
-	"----------------**---**--", // .
-	"-------------------------", // /
-	" *** *  *** * ***  * *** ", // 0
-	"   *   **    *    *    * ",
-	"****     * *** *    *****",
-	"****     * ***     ***** ",
-	"  **  * * *  * *****   * ",
-	"**** *    ****     ***** ",
-	" *** *    **** *   * *** ",
-	"*****    *   *   *    *  ",
-	" *** *   * *** *   * *** ",
-	" *** *   * ****    * *** ", // 9
-	"-**---**--------**---**--", // :
-	"-------------------------", // ;
-	"-------------------------", // <
-	"-------------------------", // =
-	"-------------------------", // >
-	"-------------------------", // ?
-	"-------------------------", // @
-	"-***-*---*******---**---*", // A
-	"****-*---*****-*---*****-",
-	"-*****----*----*-----****",
-	"****-*---**---**---*****-",
-	"******----****-*----*****",
-	"******----****-*----*----",
-	"-*****----*--***---*-****",
-	"*---**---*******---**---*",
-	"-***---*----*----*---***-",
-	"----*----*----**---*-***-",
-	"-*--*-*-*--**---*-*--*--*",
-	"-*----*----*----*----****",
-	"*---***-***-*-**---**---*",
-	"*---***--**-*-**--***---*",
-	"-***-*---**---**---*-***-",
-	"****-*---*****-*----*----",
-	"-***-*---**---*-***----**",
-	"****-*---*****-*-*--*--**",
-	"-*****-----***-----*****-",
-	"*****--*----*----*----*--",
-	"*---**---**---**---******",
-	"*---**---**---*-*-*---*--",
-	"*---**---**-*-***-***---*",
-	"*---*-*-*---*---*-*-*---*",
-	"*---**---*-*-*---*----*--",
-	"*****---*---*---*---*****" // Z
-};
-
-void DrawLine(int x1, int y1, int x2, int y2)
-{
-	int dx, dy;
-	int adx, ady;
-	int count;
-	float xfrac, yfrac, xstep, ystep;
-	unsigned sx, sy;
-	float u, v;
-
-	dx = x2 - x1;
-	dy = y2 - y1;
-	adx = abs(dx);
-	ady = abs(dy);
-
-	count = adx > ady ? adx : ady;
-	count++;
-
-	if(count > 300)
-	{
-		printf("Bad count\n");
-		return; // don't ever hang up on bad data
-	}
-		
-	xfrac = x1;
-	yfrac = y1;
-	
-	xstep = (float)dx/count;
-	ystep = (float)dy/count;
-
-	switch(LineType)
-	{
-		case LINE_NORMAL:
-			do
-			{
-				if(xfrac < SKINPAGE_WIDTH && yfrac < SKINPAGE_HEIGHT)
-				{
-					pic[(int)yfrac*SKINPAGE_WIDTH+(int)xfrac] = LineColor;
-				}
-				xfrac += xstep;
-				yfrac += ystep;
-				count--;
-			} while (count > 0);
-			break;
-		case LINE_FAT:
-			do
-			{
-				for (u=-0.1 ; u<=0.9 ; u+=0.999)
-				{
-					for (v=-0.1 ; v<=0.9 ; v+=0.999)
-					{
-						sx = xfrac+u;
-						sy = yfrac+v;
-						if(sx < SKINPAGE_WIDTH && sy < SKINPAGE_HEIGHT)
-						{
-							pic[sy*SKINPAGE_WIDTH+sx] = LineColor;
-						}
-					}
-				}
-				xfrac += xstep;
-				yfrac += ystep;
-				count--;
-			} while (count > 0);
-			break;
-		case LINE_DOTTED:
-			do
-			{
-				if(count&1 && xfrac < SKINPAGE_WIDTH &&
-					yfrac < SKINPAGE_HEIGHT)
-				{
-					pic[(int)yfrac*SKINPAGE_WIDTH+(int)xfrac] = LineColor;
-				}
-				xfrac += xstep;
-				yfrac += ystep;
-				count--;
-			} while (count > 0);
-			break;
-		default:
-			Error("Unknown <linetype> %d.\n", LineType);
-	}
-}
-
-//==========================================================================
-//
-// DrawCharacter
-//
-//==========================================================================
-
-static void DrawCharacter(int x, int y, int character)
-{
-	int r, c;
-	char *def;
-
-	character = toupper(character);
-	if(character < ASCII_SPACE || character > 'Z')
-	{
-		character = ASCII_SPACE;
-	}
-	character -= ASCII_SPACE;
-	for(def = CharDefs[character], r = 0; r < 5; r++)
-	{
-		for(c = 0; c < 5; c++)
-		{
-			pic[(y+r)*SKINPAGE_WIDTH+x+c] = *def++ == '*' ? 255 : 0;
-		}
-	}
-}
-
-//==========================================================================
-//
-// DrawTextChar
-//
-//==========================================================================
-
-void DrawTextChar(int x, int y, char *text)
-{
-	int c;
-
-	while((c = *text++) != '\0')
-	{
-		DrawCharacter(x, y, c);
-		x += 6;
-	}
-}
-
-
-extern void DrawScreen(float s_scale, float t_scale, float iwidth, float iheight);
-
-//==========================================================================
-// ExtractDigit
-
-static int ExtractDigit(byte *pic, int x, int y)
-{
-	int		i;
-	int		r, c;
-	char	digString[32];
-	char	*buffer;
-	byte	backColor;
-	char	**DigitDefs;
-
-	backColor = pic[(SKINPAGE_HEIGHT - 1) * SKINPAGE_WIDTH];
-	DigitDefs = &CharDefs['0' - ASCII_SPACE];
-
-	buffer = digString;
-	for(r = 0; r < 5; r++)
-	{
-		for(c = 0; c < 5; c++)
-		{
-			*buffer++ = (pic[(y + r) * SKINPAGE_WIDTH + x + c] == backColor) ? ' ' : '*';
-		}
-	}
-	*buffer = '\0';
-	for(i = 0; i < 10; i++)
-	{
-		if(strcmp(DigitDefs[i], digString) == 0)
-		{
-			return i;
-		}
-	}
-
-	Error("Unable to extract scaling info from skin PCX.");
-	return 0;
-}
-
-//==========================================================================
-// ExtractNumber
-
-int ExtractNumber(byte *pic, int x, int y)
-{
-	return ExtractDigit(pic, x, y) * 100 + ExtractDigit(pic, x + 6, y) * 10 + ExtractDigit(pic, x + 12, y);
-}
-
-
-
-
-
-/*
-============
-BuildST
-
-Builds the triangle_st array for the base frame and
-fmheader.skinwidth / fmheader.skinheight
-
-  FIXME: allow this to be loaded from a file for
-  arbitrary mappings
-============
-*/
-static void BuildST (triangle_t *ptri, int numtri, qboolean DrawSkin)
-{
-	int			backface_flag;
-	int			i, j;
-	int			width, height, iwidth, iheight, swidth;
-	float		basex, basey;
-	float		scale;
-	vec3_t		mins, maxs;
-	float		*pbasevert;
-	vec3_t		vtemp1, vtemp2, normal;
-	float		s_scale, t_scale;
-	float		scWidth;
-	float		scHeight;
-	int skinwidth;
-	int skinheight;
-
-	//
-	// find bounds of all the verts on the base frame
-	//
-	ClearBounds (mins, maxs);
-	backface_flag = false;
-	
-	if (ptri[0].HasUV)	// if we have the uv already, we don't want to double up or scale
-	{
-		iwidth = ScaleWidth;
-		iheight = ScaleHeight;
-		
-		t_scale = s_scale = 1.0;
-	}
-	else
-	{
-		for (i=0 ; i<numtri ; i++)
-			for (j=0 ; j<3 ; j++)
-				AddPointToBounds (ptri[i].verts[j], mins, maxs);
-			
-			for (i=0 ; i<3 ; i++)
-			{
-				mins[i] = floor(mins[i]);
-				maxs[i] = ceil(maxs[i]);
-			}
-			
-			width = maxs[0] - mins[0];
-			height = maxs[2] - mins[2];
-			
-			for (i=0 ; i<numtri ; i++)
-			{
-				VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-				VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-				CrossProduct (vtemp1, vtemp2, normal);
-				
-				if (normal[1] > 0)
-				{
-					backface_flag = true;
-					break;
-				}
-			}
-			scWidth = ScaleWidth*SCALE_ADJUST_FACTOR;
-			if (backface_flag)	//we are doubling
-				scWidth /= 2;
-			
-			scHeight = ScaleHeight*SCALE_ADJUST_FACTOR;
-			
-			scale = scWidth/width;
-			
-			if(height*scale >= scHeight)
-			{
-				scale = scHeight/height;
-			}
-			
-			iwidth = ceil(width*scale)+4;
-			iheight = ceil(height*scale)+4;
-			
-			s_scale = (float)(iwidth-4) / width;
-			t_scale = (float)(iheight-4) / height;
-			t_scale = s_scale;
-	}
-	if (DrawSkin)
-	{
-		if(backface_flag)
-			DrawScreen(s_scale, t_scale, iwidth*2, iheight);
-		else
-			DrawScreen(s_scale, t_scale, iwidth, iheight);
-	}
-	if (backface_flag)
-		skinwidth=iwidth*2;
-	else
-		skinwidth=iwidth;
-	skinheight=iheight;
-
-
-/*	if (!g_fixedwidth)
-	{	// old style
-		scale = 8;
-		if (width*scale >= 150)
-			scale = 150.0 / width;	
-		if (height*scale >= 190)
-			scale = 190.0 / height;
-
-		s_scale = t_scale = scale;
-
-		iwidth = ceil(width*s_scale);
-		iheight = ceil(height*t_scale);
-
-		iwidth += 4;
-		iheight += 4;
-	}
-	else
-	{	// new style
-		iwidth = g_fixedwidth / 2;
-		iheight = g_fixedheight;
-
-		s_scale = (float)(iwidth-4) / width;
-		t_scale = (float)(iheight-4) / height;
-	}*/
-
-//
-// determine which side of each triangle to map the texture to
-//
-	basey = 2;
-	for (i=0 ; i<numtri ; i++)
-	{
-		if (ptri[i].HasUV)
-		{
-			for (j=0 ; j<3 ; j++)
-			{
-				triangle_st[i][j][0] = Q_rint(ptri[i].uv[j][0]*skinwidth);
-				triangle_st[i][j][1] = Q_rint((1.0f-ptri[i].uv[j][1])*skinheight);
-			}
-		}
-		else
-		{
-			VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-			VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-			CrossProduct (vtemp1, vtemp2, normal);
-
-			if (normal[1] > 0)
-			{
-				basex = iwidth + 2;
-			}
-			else
-			{
-				basex = 2;
-			}
-			
-			for (j=0 ; j<3 ; j++)
-			{
-				pbasevert = ptri[i].verts[j];
-
-				triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
-				triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
-			}
-		}
-
-		if (DrawSkin)
-		{
-			DrawLine(triangle_st[i][0][0], triangle_st[i][0][1],
-				triangle_st[i][1][0], triangle_st[i][1][1]);
-			DrawLine(triangle_st[i][1][0], triangle_st[i][1][1],
-				triangle_st[i][2][0], triangle_st[i][2][1]);
-			DrawLine(triangle_st[i][2][0], triangle_st[i][2][1],
-				triangle_st[i][0][0], triangle_st[i][0][1]);
-		}
-	}
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-
-	swidth = iwidth;
-	if(backface_flag)
-		swidth *= 2;
-	fmheader.skinwidth = (swidth + 3) & ~3;
-	fmheader.skinheight = iheight;
-
-	skin_width = iwidth;
-	skin_height = iheight;
-}
-
-
-static void BuildNewST (triangle_t *ptri, int numtri, qboolean DrawSkin)
-{
-	int			i, j;
-
-	for (i=0 ; i<numtri ; i++)
-	{
-		if (ptri[i].HasUV)
-		{
-			for (j=0 ; j<3 ; j++)
-			{
-				triangle_st[i][j][0] = Q_rint(ptri[i].uv[j][0]*(ScaleWidth-1));
-				triangle_st[i][j][1] = Q_rint((1.0f-ptri[i].uv[j][1])*(ScaleHeight-1));
-			}
-		}
-
-		if (DrawSkin)
-		{
-			DrawLine(triangle_st[i][0][0], triangle_st[i][0][1],
-				triangle_st[i][1][0], triangle_st[i][1][1]);
-			DrawLine(triangle_st[i][1][0], triangle_st[i][1][1],
-				triangle_st[i][2][0], triangle_st[i][2][1]);
-			DrawLine(triangle_st[i][2][0], triangle_st[i][2][1],
-				triangle_st[i][0][0], triangle_st[i][0][1]);
-		}
-	}
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-
-	fmheader.skinwidth = (ScaleWidth + 3) & ~3;
-	fmheader.skinheight = ScaleHeight;
-
-	skin_width = ScaleWidth;
-	skin_height = ScaleHeight;
-}
-
-
-
-
-byte			*BasePalette;
-byte			*BasePixels,*TransPixels;
-int				BaseWidth, BaseHeight, TransWidth, TransHeight;
-qboolean		BaseTrueColor;
-static qboolean SetPixel = false;
-
-int CheckTransRecursiveTri (int *lp1, int *lp2, int *lp3)
-{
-	int		*temp;
-	int		d;
-	int		new[2];
-
-	d = lp2[0] - lp1[0];
-	if (d < -1 || d > 1)
-		goto split;
-	d = lp2[1] - lp1[1];
-	if (d < -1 || d > 1)
-		goto split;
-
-	d = lp3[0] - lp2[0];
-	if (d < -1 || d > 1)
-		goto split2;
-	d = lp3[1] - lp2[1];
-	if (d < -1 || d > 1)
-		goto split2;
-
-	d = lp1[0] - lp3[0];
-	if (d < -1 || d > 1)
-		goto split3;
-	d = lp1[1] - lp3[1];
-	if (d < -1 || d > 1)
-	{
-split3:
-		temp = lp1;
-		lp1 = lp3;
-		lp3 = lp2;
-		lp2 = temp;
-
-		goto split;
-	}
-
-	return 0;			// entire tri is filled
-
-split2:
-	temp = lp1;
-	lp1 = lp2;
-	lp2 = lp3;
-	lp3 = temp;
-
-split:
-// split this edge
-	new[0] = (lp1[0] + lp2[0]) >> 1;
-	new[1] = (lp1[1] + lp2[1]) >> 1;
-
-// draw the point if splitting a leading edge
-	if (lp2[1] > lp1[1])
-		goto nodraw;
-	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
-		goto nodraw;
-
-	if (SetPixel)
-	{
-		assert ((new[1]*BaseWidth) + new[0] < BaseWidth*BaseHeight);
-
-		if (BaseTrueColor)
-		{
-			BasePixels[((new[1]*BaseWidth) + new[0]) * 4] = 1;
-		}
-		else
-		{
-			BasePixels[(new[1]*BaseWidth) + new[0]] = 1;
-		}
-	}
-	else
-	{
-		if (TransPixels)
-		{
-			if (TransPixels[(new[1]*TransWidth) + new[0]] != 255)
-				return 1;
-		}
-		else if (BaseTrueColor)
-		{
-			if (BasePixels[(((new[1]*BaseWidth) + new[0]) * 4) + 3] != 255)
-				return 1;
-		}
-		else
-		{
-//			pixel = BasePixels[(new[1]*BaseWidth) + new[0]];
-		}
-	}
-
-nodraw:
-// recursively continue
-	if (CheckTransRecursiveTri(lp3, lp1, new)) 
-		return 1;
-
-	return CheckTransRecursiveTri(lp3, new, lp2);
-}
-
-static void ReplaceClusterIndex(int newIndex, int oldindex, int **clusters, 
-	IntListNode_t **vertLists, int *num_verts, int *new_num_verts)
-{
-	int i, j;
-	IntListNode_t *next;
-
-	for(j = 0; j < numJointsInSkeleton[g_skelModel.type]; ++j)
-	{
-		if(!clusters[j])
-		{
-			continue;
-		}
-
-		for(i = 0; i < num_verts[j+1]; ++i)
-		{
-			if(clusters[j][i] == oldindex)
-			{
-				++new_num_verts[j+1];
-
-				next = vertLists[j];
-
-				vertLists[j] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "ReplaceClusterIndex");
-				// Currently freed in WriteJointedModelFile only
-
-				vertLists[j]->data = newIndex;
-				vertLists[j]->next = next;
-			}
-		}
-	}
-}
-
-#define	FUDGE_EPSILON	0.002
-
-qboolean VectorFudgeCompare (vec3_t v1, vec3_t v2)
-{
-	int		i;
-	
-	for (i=0 ; i<3 ; i++)
-		if (fabs(v1[i]-v2[i]) > FUDGE_EPSILON)
-			return false;
-			
-	return true;
-}
-
-/*
-=================
-Cmd_Base
-=================
-*/
-void Cmd_FMBase (qboolean GetST)
-{
-	triangle_t	*ptri, *st_tri;
-	int			num_st_tris;
-	int			i, j, k, l;
-	int			x,y,z;
-//	int			time1;
-	char		file1[1024],file2[1024],trans_file[1024], stfile[1024], extension[256];
-	vec3_t		base_xyz[MAX_FM_VERTS];
-	FILE		*FH;
-	int			pos,bit;
-	qboolean	NewSkin;
-
-	GetScriptToken (false);
-
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	printf ("---------------------\n");
-	sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
-	printf ("%s ", file1);
-
-	ExpandPathAndArchive (file1);
-
-	// Use the input filepath for this one.
-	sprintf (file1, "%s/%s", cddir, token);
-
-//	time1 = FileTime (file1);
-//	if (time1 == -1)
-//		Error ("%s doesn't exist", file1);
-
-//
-// load the base triangles
-//
-	if (do3ds)
-		Load3DSTriangleList (file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
-	else
-		LoadTriangleList (file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
-
-	if (g_ignoreTriUV)
-	{
-		for (i=0;i<fmheader.num_tris;i++)
-		{
-			ptri[i].HasUV=0;
-		}
-	}
-
-	GetScriptToken (false);
-	sprintf (file2, "%s/%s", cddir, token);
-	sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
-
-	ExtractFileExtension (file2, extension);
-	if (extension[0] == 0)
-	{
-		strcat(file2, ".pcx");
-	}
-	printf ("skin: %s\n", file2);
-
-	BaseTrueColor = LoadAnyImage (file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight);
-
-	NewSkin = false;
-	if (BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT)
-	{
-		if (g_allow_newskin)
-		{
-			ScaleWidth = BaseWidth;
-			ScaleHeight = BaseHeight;
-			NewSkin = true;
-		}
-		else
-		{
-			Error("Invalid skin page size: (%d,%d) should be (%d,%d)",
-				BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT);
-		}
-	}
-	else if (!BaseTrueColor)
-	{
-		ScaleWidth = (float)ExtractNumber(BasePixels, ENCODED_WIDTH_X,
-			ENCODED_WIDTH_Y);
-		ScaleHeight = (float)ExtractNumber(BasePixels, ENCODED_HEIGHT_X,
-			ENCODED_HEIGHT_Y);
-	}
-	else
-	{
-		Error("Texture coordinates not supported on true color image");
-	}
-
-	if (GetST)
-	{
-		GetScriptToken (false);
-
-		sprintf (stfile, "%s/%s.%s", cdarchive, token, trifileext);
-		printf ("ST: %s ", stfile);
-
-		sprintf (stfile, "%s/%s", cddir, token);
-
-		if (do3ds)
-			Load3DSTriangleList (stfile, &st_tri, &num_st_tris, NULL, NULL);
-		else
-			LoadTriangleList (stfile, &st_tri, &num_st_tris, NULL, NULL);
-
-		if (num_st_tris != fmheader.num_tris)
-		{
-			Error ("num st tris mismatch: st %d / base %d", num_st_tris, fmheader.num_tris);
-		}
-
-		printf("   matching triangles...\n");
-		for(i=0;i<fmheader.num_tris;i++)
-		{
-			k = -1;
-			for(j=0;j<num_st_tris;j++)
-			{
-				for(x=0;x<3;x++)
-				{
-					for(y=0;y<3;y++)
-					{
-						if (x == y)
-						{
-							continue;
-						}
-						for(z=0;z<3;z++)
-						{
-							if (z == x || z == y) 
-							{
-								continue;
-							}
-
-							if (VectorFudgeCompare (ptri[i].verts[0], st_tri[j].verts[x]) &&
-							    VectorFudgeCompare (ptri[i].verts[1], st_tri[j].verts[y]) &&
-								VectorFudgeCompare (ptri[i].verts[2], st_tri[j].verts[z]))
-							{
-								if (k == -1)
-								{
-									k = j;
-									ptri[i].HasUV = st_tri[k].HasUV;
-									ptri[i].uv[0][0] = st_tri[k].uv[x][0];
-									ptri[i].uv[0][1] = st_tri[k].uv[x][1];
-									ptri[i].uv[1][0] = st_tri[k].uv[y][0];
-									ptri[i].uv[1][1] = st_tri[k].uv[y][1];
-									ptri[i].uv[2][0] = st_tri[k].uv[z][0];
-									ptri[i].uv[2][1] = st_tri[k].uv[z][1];
-									x = y = z = 999;
-								}
-								else if (k != j)
-								{
-									printf("Duplicate triangle %d found in st file: %d and %d\n",i,k,j);
-									printf("   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
-										ptri[i].verts[0][0],ptri[i].verts[0][1],ptri[i].verts[0][2],
-										ptri[i].verts[1][0],ptri[i].verts[1][1],ptri[i].verts[1][2],
-										ptri[i].verts[2][0],ptri[i].verts[2][1],ptri[i].verts[2][2]);
-									printf("   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
-										st_tri[k].verts[0][0],st_tri[k].verts[0][1],st_tri[k].verts[0][2],
-										st_tri[k].verts[1][0],st_tri[k].verts[1][1],st_tri[k].verts[1][2],
-										st_tri[k].verts[2][0],st_tri[k].verts[2][1],st_tri[k].verts[2][2]);
-									printf("   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
-										st_tri[j].verts[0][0],st_tri[j].verts[0][1],st_tri[j].verts[0][2],
-										st_tri[j].verts[1][0],st_tri[j].verts[1][1],st_tri[j].verts[1][2],
-										st_tri[j].verts[2][0],st_tri[j].verts[2][1],st_tri[j].verts[2][2]);
-								}
-							}
-						}
-					}
-				}
-			}
-			if (k == -1)
-			{
-				printf("No matching triangle %d\n",i);
-			}
-		}
-		free (st_tri);
-	}
-
-//
-// get the ST values
-//
-	if (ptri && ptri[0].HasUV)
-	{
-		if (!NewSkin)
-		{
-			Error("Base has UVs with old style skin page\nMaybe you want to use -ignoreUV");
-		}
-		else
-		{
-			BuildNewST (ptri, fmheader.num_tris, false);
-		}
-	}
-	else
-	{
-		if (NewSkin)
-		{
-			Error("Base has new style skin without UVs");
-		}
-		else
-		{
-			BuildST (ptri, fmheader.num_tris, false);
-		}
-	}
-
-	TransPixels = NULL;
-	if (!BaseTrueColor)
-	{
-		FH = fopen(trans_file,"rb");
-		if (FH)
-		{
-			fclose(FH);
-			Load256Image (trans_file, &TransPixels, NULL, &TransWidth, &TransHeight);
-			if (TransWidth != fmheader.skinwidth || TransHeight != fmheader.skinheight)
-			{
-				Error ("source image %s dimensions (%d,%d) are not the same as alpha image (%d,%d)\n",file2,fmheader.skinwidth,fmheader.skinheight,TransWidth,TransHeight);
-			}
-		}
-	}
-
-//
-// run through all the base triangles, storing each unique vertex in the
-// base vertex list and setting the indirect triangles to point to the base
-// vertices
-//
-	for(l=0;l<fmheader.num_mesh_nodes;l++)
-	{
-		for (i=0 ; i < fmheader.num_tris ; i++)
-		{
-			pos = i >> 3;
-			bit = 1 << (i & 7 );
-			if (!(pmnodes[l].tris[pos] & bit))
-			{
-				continue;
-			}
-
-			for (j=0 ; j<3 ; j++)
-			{
-				// get the xyz index
-				for (k=0 ; k<fmheader.num_xyz ; k++)
-				{
-					if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
-					{
-						break;	// this vertex is already in the base vertex list
-					}
-				}
-
-				if (k == fmheader.num_xyz)
-				{ // new index
-					VectorCopy (ptri[i].verts[j], base_xyz[fmheader.num_xyz]);
-
-					if(pmnodes[l].clustered == true)
-					{
-						ReplaceClusterIndex(k, ptri[i].indicies[j], (int **)&pmnodes[l].clusters, (IntListNode_t **)&g_skelModel.vertLists, (int *)&pmnodes[l].num_verts, (int *)&g_skelModel.new_num_verts);
-					}
-
-					fmheader.num_xyz++;
-				}
-
-				pos = k >> 3;
-				bit = 1 << (k & 7);
-				pmnodes[l].verts[pos] |= bit;
-
-				triangles[i].index_xyz[j] = k;
-
-				// get the st index
-				for (k=0 ; k<fmheader.num_st ; k++)
-				{
-					if (triangle_st[i][j][0] == base_st[k].s
-					&& triangle_st[i][j][1] == base_st[k].t)
-					{
-						break;	// this vertex is already in the base vertex list
-					}
-				}
-
-				if (k == fmheader.num_st)
-				{ // new index
-					base_st[fmheader.num_st].s = triangle_st[i][j][0];
-					base_st[fmheader.num_st].t = triangle_st[i][j][1];
-					fmheader.num_st++;
-				}
-
-				triangles[i].index_st[j] = k;
-			}
-
-			if (TransPixels || BaseTrueColor)
-			{
-				translucent[i] = CheckTransRecursiveTri(triangle_st[i][0], triangle_st[i][1], triangle_st[i][2]);
-			}
-			else
-			{
-				translucent[i] = false;
-			}
-		}
-	}
-
-	if (!BaseTrueColor)
-	{
-		SetPixel = true;
-		memset(BasePixels,0,BaseWidth*BaseHeight);
-		for (i=0 ; i < fmheader.num_tris ; i++)
-		{
-			CheckTransRecursiveTri(triangle_st[i][0], triangle_st[i][1], triangle_st[i][2]);
-		}
-		SetPixel = false;
-
-		skin_pixels_used = 0;
-		for(i=0;i<fmheader.skinheight;i++)
-		{
-			for(j=0;j<fmheader.skinwidth;j++)
-			{
-				skin_pixels_used += BasePixels[(i*BaseWidth) + j];
-			}
-		}
-		total_skin_pixels = fmheader.skinheight*fmheader.skinwidth;
-	}
-	else
-	{
-		SetPixel = true;
-		memset(BasePixels,0,BaseWidth*BaseHeight*4);
-		for (i=0 ; i < fmheader.num_tris ; i++)
-		{
-			CheckTransRecursiveTri(triangle_st[i][0], triangle_st[i][1], triangle_st[i][2]);
-		}
-		SetPixel = false;
-
-		skin_pixels_used = 0;
-		for(i=0;i<fmheader.skinheight;i++)
-		{
-			for(j=0;j<fmheader.skinwidth;j++)
-			{
-				skin_pixels_used += BasePixels[((i*BaseWidth) + j)*4];
-			}
-		}
-		total_skin_pixels = fmheader.skinheight*fmheader.skinwidth;
-	}
-
-	// build triangle strips / fans
-	BuildGlCmds ();
-
-	if (TransPixels)
-	{
-		free(TransPixels);
-	}
-	free (BasePixels);
-	if (BasePalette)
-	{
-		free (BasePalette);
-	}
-	free(ptri);
-}
-
-void Cmd_FMNodeOrder(void)
-{
-	mesh_node_t	*newnodes, *pos;
-	int			i,j;
-
-	if (!pmnodes)
-	{
-		Error ("Base has not been established yet");
-	}
-
-	pos = newnodes = malloc(sizeof(mesh_node_t) * fmheader.num_mesh_nodes);
-
-	for(i=0;i<fmheader.num_mesh_nodes;i++)
-	{
-		GetScriptToken (false);
-
-		for(j=0;j<fmheader.num_mesh_nodes;j++)
-		{
-			if (strcmpi(pmnodes[j].name, token) == 0)
-			{
-				*pos = pmnodes[j];
-				pos++;
-				break;
-			}
-		}
-		if (j >= fmheader.num_mesh_nodes)
-		{
-			Error("Node '%s' not in base list!\n", token);
-		}
-	}
-
-	free(pmnodes);
-	pmnodes = newnodes;
-}
-
-//===============================================================
-
-extern char	*FindFrameFile (char *frame);
-
-
-/*
-===============
-GrabFrame
-===============
-*/
-void GrabFrame (char *frame)
-{
-	triangle_t		*ptri;
-	int				i, j;
-	fmtrivert_t		*ptrivert;
-	int				num_tris;
-	char			file1[1024];
-	fmframe_t		*fr;
-	int				index_xyz;
-	char			*framefile;
-
-	// the frame 'run1' will be looked for as either
-	// run.1 or run1.tri, so the new alias sequence save
-	// feature an be used
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-	printf ("grabbing %s  ", file1);
-
-	if (fmheader.num_frames >= MAX_FM_FRAMES)
-		Error ("fmheader.num_frames >= MAX_FM_FRAMES");
-	fr = &g_frames[fmheader.num_frames];
-	fmheader.num_frames++;
-
-	strcpy (fr->name, frame);
-
-//
-// load the frame
-//
-	if (do3ds)
-		Load3DSTriangleList (file1, &ptri, &num_tris, NULL, NULL);
-	else
-		LoadTriangleList (file1, &ptri, &num_tris, NULL, NULL);
-
-	if (num_tris != fmheader.num_tris)
-		Error ("%s: number of triangles (%d) doesn't match base frame (%d)\n", file1, num_tris, fmheader.num_tris);
-
-//
-// allocate storage for the frame's vertices
-//
-	ptrivert = fr->v;
-
-	for (i=0 ; i<fmheader.num_xyz ; i++)
-	{
-		ptrivert[i].vnorm.numnormals = 0;
-		VectorClear (ptrivert[i].vnorm.normalsum);
-	}
-	ClearBounds (fr->mins, fr->maxs);
-
-//
-// store the frame's vertices in the same order as the base. This assumes the
-// triangles and vertices in this frame are in exactly the same order as in the
-// base
-//
-	for (i=0 ; i<num_tris ; i++)
-	{
-		vec3_t	vtemp1, vtemp2, normal;
-		float	ftemp;
-
-		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-		CrossProduct (vtemp1, vtemp2, normal);
-
-		VectorNormalize (normal, normal);
-
-	// rotate the normal so the model faces down the positive x axis
-		ftemp = normal[0];
-		normal[0] = -normal[1];
-		normal[1] = ftemp;
-
-		for (j=0 ; j<3 ; j++)
-		{
-			index_xyz = triangles[i].index_xyz[j];
-
-		// rotate the vertices so the model faces down the positive x axis
-		// also adjust the vertices to the desired origin
-			ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
-										adjust[0];
-			ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
-										adjust[1];
-			ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
-										adjust[2];
-
-			AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
-
-			VectorAdd (ptrivert[index_xyz].vnorm.normalsum, normal, ptrivert[index_xyz].vnorm.normalsum);
-			ptrivert[index_xyz].vnorm.numnormals++;
-		}
-	}
-
-//
-// calculate the vertex normals, match them to the template list, and store the
-// index of the best match
-//
-	for (i=0 ; i<fmheader.num_xyz ; i++)
-	{
-		int		j;
-		vec3_t	v;
-		float	maxdot;
-		int		maxdotindex;
-		int		c;
-
-		c = ptrivert[i].vnorm.numnormals;
-		if (!c)
-			Error ("Vertex with no triangles attached");
-
-		VectorScale (ptrivert[i].vnorm.normalsum, 1.0/c, v);
-		VectorNormalize (v, v);
-
-		maxdot = -999999.0;
-		maxdotindex = -1;
-
-		for (j=0 ; j<NUMVERTEXNORMALS ; j++)
-		{
-			float	dot;
-
-			dot = DotProduct (v, avertexnormals[j]);
-			if (dot > maxdot)
-			{
-				maxdot = dot;
-				maxdotindex = j;
-			}
-		}
-
-		ptrivert[i].lightnormalindex = maxdotindex;
-	}
-
-	free (ptri);
-}
-
-/*
-===============
-Cmd_Frame	
-===============
-*/
-void Cmd_FMFrame (void)
-{
-	while (ScriptTokenAvailable())
-	{
-		GetScriptToken (false);
-		if (g_skipmodel)
-			continue;
-		if (g_release || g_archive)
-		{
-			fmheader.num_frames = 1;	// don't skip the writeout
-			continue;
-		}
-
-		H_printf("#define FRAME_%-16s\t%i\n", token, fmheader.num_frames);
-
-		if((g_skelModel.type != SKEL_NULL) || (g_skelModel.references != REF_NULL))
-		{
-			GrabModelTransform(token);
-		}
-
-		GrabFrame (token);
-
-		if(g_skelModel.type != SKEL_NULL)
-		{
-			GrabSkeletalFrame(token);
-		}
-
-		if(g_skelModel.references != REF_NULL)
-		{
-			GrabReferencedFrame(token);
-		}
-
-		// need to add the up and dir points to the frame bounds here
-		// using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
-		// then remove fudge in determining scale on frame write out
-	}
-}
-
-/*
-===============
-Cmd_Skin
-
-Skins aren't actually stored in the file, only a reference
-is saved out to the header file.
-===============
-*/
-void Cmd_FMSkin (void)
-{
-	byte		*palette;
-	byte		*pixels;
-	int			width, height;
-	byte		*cropped;
-	int			y;
-	char		name[1024], savename[1024], transname[1024], extension[256];
-	miptex32_t	*qtex32;
-	int			size;
-	FILE		*FH;
-	qboolean	TrueColor;
-
-	GetScriptToken (false);
-
-	if (fmheader.num_skins == MAX_FM_SKINS)
-		Error ("fmheader.num_skins == MAX_FM_SKINS");
-
-	if (g_skipmodel)
-		return;
-
-	sprintf (name, "%s/%s", cdarchive, token);
-	strcpy (name, ExpandPathAndArchive( name ) );
-//	sprintf (name, "%s/%s.lbm", cddir, token);
-
-	if (ScriptTokenAvailable())
-	{
-		GetScriptToken (false);
-		sprintf (g_skins[fmheader.num_skins], "!%s", token);
-		sprintf (savename, "%s!%s", g_outputDir, token);
-		sprintf (transname, "%s!%s_a.pcx", gamedir, token);
-	}
-	else
-	{
-		sprintf (g_skins[fmheader.num_skins], "%s/!%s", cdpartial, token);
-		sprintf (savename, "%s/!%s", g_outputDir, token);
-		sprintf (transname, "%s/!%s_a.pcx", cddir, token);
-	}
-
-	fmheader.num_skins++;
-
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	// load the image
-	printf ("loading %s\n", name);
-	ExtractFileExtension (name, extension);
-	if (extension[0] == 0)
-	{
-		strcat(name, ".pcx");
-	}
-
-
-	TrueColor = LoadAnyImage (name, &pixels, &palette, &width, &height);
-//	RemapZero (pixels, palette, width, height);
-
-	// crop it to the proper size
-
-	if (!TrueColor)
-	{
-		cropped = (byte *) SafeMalloc (fmheader.skinwidth*fmheader.skinheight, "Cmd_FMSkin");
-		for (y=0 ; y<fmheader.skinheight ; y++)
-		{
-			memcpy (cropped+y*fmheader.skinwidth,
-				pixels+y*width, fmheader.skinwidth);
-		}
-
-		TransPixels = NULL;
-		FH = fopen(transname,"rb");
-		if (FH)
-		{
-			fclose(FH);
-
-			strcat(g_skins[fmheader.num_skins-1],".pcx");
-			strcat(savename,".pcx");
-
-			// save off the new image
-			printf ("saving %s\n", savename);
-			CreatePath (savename);
-			WritePCXfile (savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette);
-		}
-		else
-		{
-	#if 1
-		miptex_t	*qtex;
-			qtex = CreateMip(cropped, fmheader.skinwidth, fmheader.skinheight, palette, &size, true);
-
-			strcat(g_skins[fmheader.num_skins-1],".m8");
-			strcat(savename,".m8");
-
-			printf ("saving %s\n", savename);
-			CreatePath (savename);
-			SaveFile (savename, (byte *)qtex, size);
-			free(qtex);
-	#else
-			strcat(g_skins[fmheader.num_skins-1],".pcx");
-			strcat(savename,".pcx");
-
-			// save off the new image
-			printf ("saving %s\n", savename);
-			CreatePath (savename);
-			WritePCXfile (savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette);
-	#endif
-		}
-	}
-	else
-	{
-		cropped = (byte *) SafeMalloc (fmheader.skinwidth*fmheader.skinheight*4, "Cmd_FMSkin");
-		for (y=0 ; y<fmheader.skinheight ; y++)
-		{
-			memcpy (cropped+((y*fmheader.skinwidth)*4), pixels+(y*width*4), fmheader.skinwidth*4);
-		}
-
-		qtex32 = CreateMip32((unsigned *)cropped, fmheader.skinwidth, fmheader.skinheight, &size, true);
-
-	    StripExtension(g_skins[fmheader.num_skins-1]);
-		strcat(g_skins[fmheader.num_skins-1],".m32");
-	    StripExtension(savename);
-		strcat(savename,".m32");
-
-		printf ("saving %s\n", savename);
-		CreatePath (savename);
-		SaveFile (savename, (byte *)qtex32, size);
-	}
-
-	free (pixels);
-	if (palette)
-	{
-		free (palette);
-	}
-	free (cropped);
-}
-
-
-/*
-===============
-Cmd_Cd
-===============
-*/
-void Cmd_FMCd (void)
-{
-	char temp[256];
-
-	FinishModel ();
-	ClearModel ();
-
-	GetScriptToken (false);
-
-	// this is a silly mess...
-	sprintf(cdpartial, "models/%s", token); 
-	sprintf(cdarchive, "%smodels/%s", gamedir+strlen(qdir), token); 
-	sprintf(cddir, "%s%s", gamedir, cdpartial);
-
-	// Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
-	sprintf(temp, "%s%s", g_outputDir, cdpartial);
-	strcpy(g_outputDir, temp);
-
-	// if -only was specified and this cd doesn't match,
-	// skip the model (you only need to match leading chars,
-	// so you could regrab all monsters with -only monsters)
-	if (!g_only[0])
-		return;
-	if (strncmp(token, g_only, strlen(g_only)))
-	{
-		g_skipmodel = true;
-		printf ("skipping %s\n", cdpartial);
-	}
-}
-
-
-/*
-
-//=======================
-//		NEW GEN
-//=======================
-
-void NewGen (char *ModelFile, char *OutputName, int width, int height)
-{
-	trigroup_t  *triangles;
-	triangle_t	*ptri;
-	triangle_t	*grouptris;
-	mesh_node_t	*pmnodes;
-
-	vec3_t		*vertices;
-	vec3_t		*uvs;
-	vec3_t		aveNorm, crossvect;
-	vec3_t		diffvect1, diffvect2;
-	vec3_t		v0, v1, v2;
-	vec3_t		n, u, v;
-	vec3_t		base, zaxis, yaxis;
-	vec3_t		uvwMin, uvwMax;
-	vec3_t		groupMin, groupMax;
-	vec3_t		uvw;
-	
-	float		*uFinal, *vFinal;
-	unsigned char	*newpic;
-
-	int			finalstart = 0, finalcount = 0;
-	int			xbase = 0, xwidth = 0, ywidth = 0;
-	int			*todo, *done, finished;
-	int			i, j, k, l; //counters
-	int			groupnum, numtris, numverts, num;
-	int			count;
-	FILE		*grpfile;
-	long		datasize;
-
-	for ( i = 0; i<3; i++)
-	{
-		aveNorm[i] = 0;
-		uvwMin[i] = 1e30f;
-		uvwMax[i] = -1e30f;
-	}
-
-	pmnodes = NULL;
-	ptri = NULL;
-	triangles = NULL;
-	
-	zaxis[0] = 0;
-	zaxis[1] = 0;
-	zaxis[2] = 1;
-
-	yaxis[0] = 0;
-	yaxis[1] = 1;
-	yaxis[2] = 0;
-
-	LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
-
-	todo = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
-	done = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
-	triangles = (trigroup_t*)SafeMalloc(fmheader.num_tris*sizeof(trigroup_t), "NewGen");
-	
-	for ( i=0; i < fmheader.num_tris; i++)
-	{
-		todo[i] = false;
-		done[i] = false;
-		triangles[i].triangle = ptri[i];
-		triangles[i].group = 0;
-	}
-
-	groupnum = 0;
-
-//  transitive closure algorithm follows
-//  put all triangles who transitively share vertices into separate groups
-
-	while (1)
-	{
-		for ( i = 0; i < fmheader.num_tris; i++)
-		{
-			if (!done[i])
-			{
-				break;
-			}
-		}
-		if ( i == fmheader.num_tris)
-		{
-			break;
-		}
-		finished = false;
-		todo[i] = true;
-		while (!finished)
-		{
-			finished = true;
-			for ( i = 0; i < fmheader.num_tris; i++)
-			{
-				if (todo[i])
-				{
-					done[i] = true;
-					triangles[i].group = groupnum;
-					todo[i] = false;
-					for ( j = 0; j < fmheader.num_tris; j++)
-					{
-						if ((!done[j]) && (ShareVertex(triangles[i],triangles[j])))
-						{
-							todo[j] = true;
-							finished = false;
-						}
-					}
-				}
-			}
-		}
-		groupnum++;
-	}
-		uFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
-		vFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
-
-	grpfile = fopen("grpdebug.txt","w");
-
-	
-	for (i = 0; i < groupnum; i++)
-	{
-
-		fprintf(grpfile,"Group Number: %d\n", i);
-		
-		numtris = GetNumTris(triangles, i); // number of triangles in group i
-		numverts = numtris * 3;
-
-		fprintf(grpfile,"%d triangles.\n", numtris);
-
-		vertices = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
-		uvs = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
-		grouptris = (triangle_t*)SafeMalloc(numtris*sizeof(triangle_t), "NewGen");
-		
-		for (count = 0; count < fmheader.num_tris; count++)
-		{
-			if (triangles[count].group == i)
-			{
-				fprintf(grpfile,"Triangle %d\n", count);
-			}
-		}
-		fprintf(grpfile,"\n");
-
-		
-		
-		
-		GetOneGroup(triangles, i, grouptris);		
-		
-		num = 0;
-		for (j = 0; j < numtris; j++)
-		{
-			VectorCopy(grouptris[j].verts[0], v0);
-			VectorCopy(grouptris[j].verts[1], v1);
-			VectorCopy(grouptris[j].verts[2], v2);
-			VectorSubtract(v1, v0, diffvect1);
-			VectorSubtract(v2, v1, diffvect2);
-			CrossProduct( diffvect1, diffvect2, crossvect);
-			VectorAdd(aveNorm, crossvect, aveNorm);	
-			VectorCopy(v0,vertices[num]);
-			num++;					//  FIXME
-			VectorCopy(v1,vertices[num]);
-			num++;					//  add routine to add only verts that
-			VectorCopy(v2,vertices[num]);
-			num++;					// have not already been added
-		}
-
-		assert (num >= 3);
-// figure out the best plane projections
-		DOsvdPlane ((float*)vertices, num, (float *)&n, (float *)&base);
-		
-		if (DotProduct(aveNorm,n) < 0.0f)
-		{
-			VectorScale(n, -1.0f, n);
-		}
-		VectorNormalize(n,n);
-		if (fabs(n[2]) < .57)
-		{
-			CrossProduct( zaxis, n, crossvect);
-			VectorCopy(crossvect, u);
-		}
-		else
-		{
-			CrossProduct( yaxis, n, crossvect);
-			VectorCopy(crossvect, u);
-		}
-		VectorNormalize(u,u);
-		CrossProduct( n, u, crossvect);
-		VectorCopy(crossvect, v);
-		VectorNormalize(v,v);
-
-		num = 0;
-
-		for ( j = 0; j < 3; j++)
-		{
-			groupMin[j] = 1e30f;
-			groupMax[j] = -1e30f;
-		}
-		
-		for ( j = 0; j < numtris; j++)
-		{
-			for ( k = 0; k < 3; k++)
-			{
-				VectorCopy(grouptris[j].verts[k],v0);
-				VectorSubtract(v0, base, v0);
-				uvw[0] = DotProduct(v0, u);
-				uvw[1] = DotProduct(v0, v);
-				uvw[2] = DotProduct(v0, n);
-				VectorCopy(uvw,uvs[num]);
-				num++;
-				for ( l = 0; l < 3; l++)
-				{
-					if (uvw[l] < groupMin[l])
-					{
-						groupMin[l] = uvw[l];
-					}
-					if (uvw[l] > groupMax[l])
-					{
-						groupMax[l] = uvw[l];
-					}
-				}
-			}
-		}
-		
-		xwidth = ceil(0 - groupMin[0]) + 2; // move right of origin and avoid overlap
-		ywidth = ceil(0 - groupMin[1]) + 2; // move "above" origin
-		
-		for ( j=0; j < numverts; j++)
-		{
-			uFinal[finalcount] = uvs[j][0] + xwidth + xbase;			
-			vFinal[finalcount] = uvs[j][1] + ywidth;
-			if (uFinal[finalcount] < uvwMin[0])
-			{
-				uvwMin[0] = uFinal[finalcount];
-			}
-			if (uFinal[finalcount] > uvwMax[0])
-			{
-				uvwMax[0] = uFinal[finalcount];
-			}
-			if (vFinal[finalcount] < uvwMin[1])
-			{
-				uvwMin[1] = vFinal[finalcount];
-			}
-			if (vFinal[finalcount] > uvwMax[1])
-			{
-				uvwMax[1] = vFinal[finalcount];
-			}
-			finalcount++;
-		}
-
-		fprintf(grpfile,"svdPlaned Group min: ( %f , %f )\n",groupMin[0] + xwidth + xbase, groupMin[1] + ywidth);
-		fprintf(grpfile,"svdPlaned Group max: ( %f , %f )\n",groupMax[0] + xwidth + xbase, groupMax[1] + ywidth);
-		
-		finalcount = finalstart;
-
-		for ( count = 0; count < numverts; count++)
-		{
-			fprintf(grpfile,"Vertex %d: ( %f , %f , %f )\n",count,vertices[count][0],vertices[count][1],vertices[count][2]);
-			fprintf(grpfile,"svdPlaned: ( %f , %f )\n",uFinal[finalcount],vFinal[finalcount++]);
-		}
-		
-		finalstart = finalcount;
-
-		fprintf(grpfile,"\n");
-		
-		free(vertices);
-		free(uvs);
-		free(grouptris);
-
-		xbase += ceil(groupMax[0] - groupMin[0]) + 2; 		
-
-	}	
-
-	fprintf(grpfile,"Global Min ( %f , %f )\n",uvwMin[0],uvwMin[1]);
-	fprintf(grpfile,"Global Max ( %f , %f )\n",uvwMax[0],uvwMax[1]);
-
-
-	ScaleTris(uvwMin, uvwMax, width, height, uFinal, vFinal, finalcount);
-
-	for (k = 0; k < finalcount; k++)
-	{
-		fprintf(grpfile, "scaled vertex %d: ( %f , %f )\n",k,uFinal[k],vFinal[k]);
-	}
-	
-	//  i've got the array of vertices in uFinal and vFinal.  Now I need to write them and draw lines
-
-	datasize = width * height*sizeof(unsigned char);
-	newpic = (unsigned char*)SafeMalloc(datasize, "NewGen");
-	memset(newpic,0,datasize);
-	memset(pic_palette,0,sizeof(pic_palette));
-	pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
-
-	k = 0;
-	while (k < finalcount)
-	{
-		NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
-		k++;
-		NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
-		k++;
-		NewDrawLine(uFinal[k], vFinal[k], uFinal[k-2], vFinal[k-2], newpic, width, height);
-		k++;
-		fprintf(grpfile, "output tri with verts %d, %d, %d", k-2, k-1, k);
-	}
-
-	WritePCXfile (OutputName, newpic, width, height, pic_palette);
-
-	fclose(grpfile);
-
-	free(todo);
-	free(done);
-	free(triangles);
-	free(newpic);	
-	return;
-}
-void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height)
-{
-	long dx, dy;
-	long adx, ady;
-	long count;
-	float xfrac, yfrac, xstep, ystep;
-	unsigned long sx, sy;
-	float u, v;
-
-	dx = x2 - x1;
-	dy = y2 - y1;
-	adx = abs(dx);
-	ady = abs(dy);
-
-	count = adx > ady ? adx : ady;
-	count++;
-
-	if(count > 300)
-	{
-		printf("Bad count\n");
-		return; // don't ever hang up on bad data
-	}
-		
-	xfrac = x1;
-	yfrac = y1;
-	
-	xstep = (float)dx/count;
-	ystep = (float)dy/count;
-
-	switch(LineType)
-	{
-		case LINE_NORMAL:
-			do
-			{
-				if(xfrac < width && yfrac < height)
-				{
-					picture[(long)yfrac*width+(long)xfrac] = LineColor;
-				}
-				xfrac += xstep;
-				yfrac += ystep;
-				count--;
-			} while (count > 0);
-			break;
-		case LINE_FAT:
-			do
-			{
-				for (u=-0.1 ; u<=0.9 ; u+=0.999)
-				{
-					for (v=-0.1 ; v<=0.9 ; v+=0.999)
-					{
-						sx = xfrac+u;
-						sy = yfrac+v;
-						if(sx < width && sy < height)
-						{
-							picture[sy*width+sx] = LineColor;
-						}
-					}
-				}
-				xfrac += xstep;
-				yfrac += ystep;
-				count--;
-			} while (count > 0);
-			break;
-		case LINE_DOTTED:
-			do
-			{
-				if(count&1 && xfrac < width &&
-					yfrac < height)
-				{
-					picture[(long)yfrac*width+(long)xfrac] = LineColor;
-				}
-				xfrac += xstep;
-				yfrac += ystep;
-				count--;
-			} while (count > 0);
-			break;
-		default:
-			Error("Unknown <linetype> %d.\n", LineType);
-	}
-}
-*/
-void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts)
-{
-
-	int		i;
-	float	hscale, vscale;
-	float	scale;
-
-	hscale = max[0];
-	vscale = max[1];
-
-	hscale = (Width-2) / max[0];
-	vscale = (Height-2) / max[1];
-
-	scale = hscale;
-	if (scale > vscale)
-	{
-		scale = vscale;
-	}
-	for ( i = 0; i<verts; i++)
-	{
-		u[i] *= scale;
-		v[i] *= scale;
-	}
-	return;
-}
-
-
-void GetOneGroup(trigroup_t *tris, int grp, triangle_t* triangles)
-{
-	int	i;
-	int j;
-
-	j = 0;
-	for (i = 0; i < fmheader.num_tris; i++)
-	{
-		if (tris[i].group == grp)
-		{
-			triangles[j++] = tris[i].triangle;
-		}
-	}
-	return;
-}
-
-
-int GetNumTris( trigroup_t *tris, int grp)
-{
-	int i;
-	int verts;
-
-	verts = 0;
-	for (i = 0; i < fmheader.num_tris; i++)
-	{
-		if (tris[i].group == grp)
-		{
-			verts++;
-		}
-	}
-	return verts;
-}
-
-
-int ShareVertex( trigroup_t trione, trigroup_t tritwo)
-{
-	int	i;
-	int	j;
-
-	i = 1;
-	j = 1;
-	for ( i = 0; i < 3; i++)
-	{
-		for ( j = 0; j < 3; j++)
-		{
-			if (DistBetween(trione.triangle.verts[i],tritwo.triangle.verts[j]) < TRIVERT_DIST)
-			{
-				return true; 
-			}
-		}
-	}
-	return false;
-}
-
-
-float DistBetween(vec3_t point1, vec3_t point2)
-{
-	float	dist;
-
-	dist = (point1[0] - point2[0]);
-	dist *= dist;
-	dist += (point1[1] - point2[1])*(point1[1]-point2[1]);
-	dist += (point1[2] - point2[2])*(point1[2]-point2[2]);
-	dist = sqrt(dist);
-	return dist;
-}
-
-
-void GenSkin(char *ModelFile, char *OutputName, int Width, int Height)
-{
-	triangle_t	*ptri;
-	mesh_node_t *pmnodes;
-	int			i;
-
-	pmnodes = NULL;
-	ptri = NULL;
-
-	LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
-	if (g_ignoreTriUV)
-	{
-		for (i=0;i<fmheader.num_tris;i++)
-		{
-			ptri[i].HasUV=0;
-		}
-	}
-
-	memset(pic,0,sizeof(pic));
-	memset(pic_palette,0,sizeof(pic_palette));
-	pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
-
-	ScaleWidth = Width;
-	ScaleHeight = Height;
-
-	BuildST (ptri, fmheader.num_tris, true);
-
-	WritePCXfile (OutputName, pic, SKINPAGE_WIDTH, SKINPAGE_HEIGHT, pic_palette);
-
-	printf("Gen Skin Stats:\n");
-	printf("   Input Base: %s\n",ModelFile);
-	printf("   Input Dimensions: %d,%d\n",Width,Height);
-	printf("\n");
-	printf("   Output File: %s\n",OutputName);
-	printf("   Output Dimensions: %d,%d\n",ScaleWidth,ScaleHeight);
-
-	if (fmheader.num_mesh_nodes)
-	{
-		printf("\nNodes:\n");
-		for(i=0;i<fmheader.num_mesh_nodes;i++)
-		{
-			printf("   %s\n",pmnodes[i].name);
-		}
-	}
-
-	free(ptri);
-	free(pmnodes);
-}
-
-
-void Cmd_FMBeginGroup (void)
-{
-	GetScriptToken (false);
-
-	g_no_opimizations = false;
-
-	groups[num_groups].start_frame = fmheader.num_frames;
-	groups[num_groups].num_frames = 0;
-
-	groups[num_groups].degrees = atol(token);
-	if (groups[num_groups].degrees < 1 || groups[num_groups].degrees > 32)
-	{
-		Error ("Degrees of freedom out of range: %d",groups[num_groups].degrees);
-	}
-}
-
-void Cmd_FMEndGroup (void)
-{
-	groups[num_groups].num_frames = fmheader.num_frames - groups[num_groups].start_frame;
-
-	if(num_groups < MAX_GROUPS - 1)
-	{
-		num_groups++;
-	}
-	else
-	{
-		Error("Number of compression groups exceded: %i\n", MAX_GROUPS);
-	}
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qd_fmodel.h"
+#include "animcomp.h"
+#include "qd_skeletons.h"
+#include "skeletons.h"
+#include "qdata.h"
+#include "flex.h"
+#include "reference.h"
+
+#include <assert.h>
+
+/*
+========================================================================
+
+.FM triangle flexible model file format
+
+========================================================================
+*/
+
+//=================================================================
+
+#define NUMVERTEXNORMALS	162
+
+extern float	avertexnormals[NUMVERTEXNORMALS][3];
+
+#define MAX_GROUPS	128
+
+typedef struct
+{
+	triangle_t	triangle;
+	int		group;
+} trigroup_t;
+
+#define TRIVERT_DIST	.1
+
+typedef struct
+{
+	int			start_frame;
+	int		num_frames;
+	int			degrees;
+	char *mat;
+	char *ccomp;
+	char *cbase;
+	float *cscale;
+	float *coffset;
+	float trans[3];
+	float scale[3];
+	float bmin[3];
+	float bmax[3];
+} fmgroup_t;
+
+//================================================================
+
+// Initial
+fmheader_t	fmheader;
+
+// Skin
+extern char			g_skins[MAX_FM_SKINS][64];
+
+// ST Coord
+extern fmstvert_t	base_st[MAX_FM_VERTS];
+
+// Triangles
+extern fmtriangle_t	triangles[MAX_FM_TRIANGLES];
+
+// Frames
+fmframe_t	g_frames[MAX_FM_FRAMES];
+//fmframe_t	*g_FMframes;
+
+// GL Commands
+extern int			commands[16384];
+extern int			numcommands;
+
+
+//
+// varibles set by commands
+//
+extern float		scale_up;						// set by $scale
+extern vec3_t		adjust;							// set by $origin
+extern int			g_fixedwidth, g_fixedheight;	// set by $skinsize
+extern char			modelname[64];					// set by $modelname
+
+
+extern 	char		*g_outputDir;
+
+
+// Mesh Nodes
+mesh_node_t	*pmnodes = NULL;
+fmmeshnode_t	mesh_nodes[MAX_FM_MESH_NODES]; 
+
+fmgroup_t	groups[MAX_GROUPS];
+int			num_groups;
+int	frame_to_group[MAX_FM_FRAMES];
+
+//
+// variables set by command line arguments
+//
+qboolean	g_no_opimizations = false;
+
+
+//
+// base frame info
+//
+static int			triangle_st[MAX_FM_TRIANGLES][3][2];
+
+
+// number of gl vertices
+extern int			numglverts;
+// indicates if a triangle has already been used in a glcmd
+extern int			used[MAX_FM_TRIANGLES];
+// indicates if a triangle has translucency in it or not
+static qboolean		translucent[MAX_FM_TRIANGLES];
+
+// main output file handle
+extern FILE			*headerouthandle;
+// output sizes of buildst()
+static int			skin_width, skin_height;
+
+
+// statistics
+static int			total_skin_pixels;
+static int			skin_pixels_used;
+
+int ShareVertex( trigroup_t trione, trigroup_t tritwo);
+float DistBetween(vec3_t point1, vec3_t point2);
+int GetNumTris( trigroup_t *tris, int group);
+void GetOneGroup(trigroup_t *tris, int grp, triangle_t* triangles);
+void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts);
+void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height);
+
+#ifndef _WIN32
+
+void strupr(char *string)
+{
+	int i;
+
+	for (i=0 ; i<strlen(string); i++)
+		toupper(string[i]);
+
+	return;
+}
+
+#endif
+//==============================================================
+
+/*
+===============
+ClearModel
+===============
+*/
+static void ClearModel (void)
+{
+	memset (&fmheader, 0, sizeof(fmheader));
+
+	modelname[0] = 0;
+	scale_up = 1.0;	
+	VectorCopy (vec3_origin, adjust);
+	g_fixedwidth = g_fixedheight = 0;
+	g_skipmodel = false;
+	num_groups = 0;
+
+	if (pmnodes)
+	{
+		free(pmnodes);
+		pmnodes = NULL;
+	}
+
+	ClearSkeletalModel();
+}
+
+
+extern void H_printf(char *fmt, ...);
+
+
+void WriteHeader(FILE *FH, char *Ident, int Version, int Size, void *Data)
+{
+	header_t	header;
+	static long	pos = -1;
+	long		CurrentPos;
+
+	if (Size == 0)
+	{	// Don't write out empty packets
+		return;
+	}
+
+	if (pos != -1)
+	{
+		CurrentPos = ftell(FH);
+		Size = CurrentPos - pos + sizeof(header_t);
+		fseek(FH, pos, SEEK_SET);
+		pos = -2;
+	}
+	else if (Size == -1)
+	{
+		pos = ftell(FH);
+	}
+
+	memset(&header,0,sizeof(header));
+	strcpy(header.ident,Ident);
+	header.version = Version;
+	header.size = Size;
+
+	SafeWrite (FH, &header, sizeof(header));
+
+	if (Data)
+	{
+		SafeWrite (FH, Data, Size);
+	}
+
+	if (pos == -2)
+	{
+		pos = -1;
+		fseek(FH, 0, SEEK_END);
+	}
+}
+
+/*
+============
+WriteModelFile
+============
+*/
+static void WriteModelFile (FILE *modelouthandle)
+{
+	int				i;
+	int				j, k;
+	fmframe_t		*in;
+	fmaliasframe_t	*out;
+	byte			buffer[MAX_FM_VERTS*4+128];
+	float			v;
+	int				c_on, c_off;
+	IntListNode_t	*current, *toFree;
+	qboolean framesWritten = false;
+	size_t temp ,size = 0;
+
+	// probably should do this dynamically one of these days
+	struct
+	{
+		float		scale[3];	// multiply byte verts by this
+		float		translate[3];	// then add this
+	} outFrames[MAX_FM_FRAMES];
+
+#define DATA_SIZE 0x60000		// 384K had better be enough, particularly for the reference points
+	byte data[DATA_SIZE];
+	byte data2[DATA_SIZE];
+
+	fmheader.num_glcmds = numcommands;
+	fmheader.framesize = (int)&((fmaliasframe_t *)0)->verts[fmheader.num_xyz];
+
+	WriteHeader(modelouthandle, FM_HEADER_NAME, FM_HEADER_VER, sizeof(fmheader), &fmheader);
+
+	//
+	// write out the skin names
+	//
+
+ 	WriteHeader(modelouthandle, FM_SKIN_NAME, FM_SKIN_VER, fmheader.num_skins * MAX_FM_SKINNAME, g_skins);
+
+	//
+	// write out the texture coordinates
+	//
+	c_on = c_off = 0;
+	for (i=0 ; i<fmheader.num_st ; i++)
+	{
+		base_st[i].s = LittleShort (base_st[i].s);
+		base_st[i].t = LittleShort (base_st[i].t);
+	}
+
+	WriteHeader(modelouthandle, FM_ST_NAME, FM_ST_VER, fmheader.num_st * sizeof(base_st[0]), base_st);
+
+	//
+	// write out the triangles
+	//
+	WriteHeader(modelouthandle, FM_TRI_NAME, FM_TRI_VER, fmheader.num_tris * sizeof(fmtriangle_t), NULL);
+
+	for (i=0 ; i<fmheader.num_tris ; i++)
+	{
+		int				j;
+		fmtriangle_t	tri;
+
+		for (j=0 ; j<3 ; j++)
+		{
+			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
+			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
+		}
+
+		SafeWrite (modelouthandle, &tri, sizeof(tri));
+	}
+
+	if (!num_groups)
+	{
+		//
+		// write out the frames
+		//
+		WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, fmheader.num_frames * fmheader.framesize, NULL);
+	//	WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
+
+		for (i=0 ; i<fmheader.num_frames ; i++)
+		{
+			in = &g_frames[i];
+			out = (fmaliasframe_t *)buffer;
+
+			strcpy (out->name, in->name);
+			for (j=0 ; j<3 ; j++)
+			{
+				out->scale[j] = (in->maxs[j] - in->mins[j])/255;
+				out->translate[j] = in->mins[j];
+
+				outFrames[i].scale[j] = out->scale[j];
+				outFrames[i].translate[j] = out->translate[j];
+			}
+
+			for (j=0 ; j<fmheader.num_xyz ; j++)
+			{
+			// all of these are byte values, so no need to deal with endianness
+				out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
+
+				for (k=0 ; k<3 ; k++)
+				{
+				// scale to byte values & min/max check
+					v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
+
+				// clamp, so rounding doesn't wrap from 255.6 to 0
+					if (v > 255.0)
+						v = 255.0;
+					if (v < 0)
+						v = 0;
+					out->verts[j].v[k] = v;
+				}
+			}
+
+			for (j=0 ; j<3 ; j++)
+			{
+				out->scale[j] = LittleFloat (out->scale[j]);
+				out->translate[j] = LittleFloat (out->translate[j]);
+			}
+
+			SafeWrite (modelouthandle, out, fmheader.framesize);
+		}
+
+		// Go back and finish the header
+	//	WriteHeader(modelouthandle, FM_FRAME_NAME, FM_FRAME_VER, -1, NULL);
+	}
+	else
+	{
+		WriteHeader(modelouthandle, FM_SHORT_FRAME_NAME, FM_SHORT_FRAME_VER,FRAME_NAME_LEN*fmheader.num_frames, NULL);
+		for (i=0 ; i<fmheader.num_frames ; i++)
+		{
+			in = &g_frames[i];
+			SafeWrite (modelouthandle,in->name,FRAME_NAME_LEN);
+		}
+		WriteHeader(modelouthandle, FM_NORMAL_NAME, FM_NORMAL_VER,fmheader.num_xyz, NULL);
+		in = &g_frames[0];
+		for (j=0 ; j<fmheader.num_xyz ; j++)
+			SafeWrite (modelouthandle,&in->v[j].lightnormalindex,1);
+	}
+
+	//
+	// write out glcmds
+	//
+	WriteHeader(modelouthandle, FM_GLCMDS_NAME, FM_GLCMDS_VER, numcommands*4, commands);
+
+	//
+	// write out mesh nodes
+	//
+	for(i=0;i<fmheader.num_mesh_nodes;i++)
+	{
+		memcpy(mesh_nodes[i].tris, pmnodes[i].tris, sizeof(mesh_nodes[i].tris));
+		memcpy(mesh_nodes[i].verts, pmnodes[i].verts, sizeof(mesh_nodes[i].verts));
+		mesh_nodes[i].start_glcmds = LittleShort((short)pmnodes[i].start_glcmds);
+		mesh_nodes[i].num_glcmds = LittleShort((short)pmnodes[i].num_glcmds);
+	}
+
+	WriteHeader(modelouthandle, FM_MESH_NAME, FM_MESH_VER, sizeof(fmmeshnode_t) * fmheader.num_mesh_nodes, mesh_nodes);
+
+	if (num_groups)
+	{
+
+/*
+typedef struct
+{
+	int			start_frame;
+	int			num_frames;
+	int			degrees;
+	char *mat; fmheader.num_xyz*3*g->degrees*sizeof(char)
+	char *ccomp; g->num_frames*g->degrees*sizeof(char)
+	char *cbase; fmheader.num_xyz*3*sizeof(unsigned char)
+	float *cscale; g->degrees*sizeof(float)
+	float *coffset; g->degrees*sizeof(float)
+	float trans[3]; 3*sizeof(float)
+	float scale[3]; 3*sizeof(float)
+} fmgroup_t;
+*/
+		int tmp,k;
+		fmgroup_t *g;
+		size=sizeof(int)+fmheader.num_frames*sizeof(int);
+		for (k=0;k<num_groups;k++)
+		{
+			g=&groups[k];
+			size+=sizeof(int)*3;
+			size+=fmheader.num_xyz*3*g->degrees*sizeof(char);
+			size+=g->num_frames*g->degrees*sizeof(char);
+			size+=fmheader.num_xyz*3*sizeof(unsigned char);
+			size+=g->degrees*sizeof(float);
+			size+=g->degrees*sizeof(float);
+			size+=12*sizeof(float);
+		}
+		WriteHeader(modelouthandle, FM_COMP_NAME, FM_COMP_VER,size, NULL);
+		SafeWrite (modelouthandle,&num_groups,sizeof(int));
+		SafeWrite (modelouthandle,frame_to_group,sizeof(int)*fmheader.num_frames);
+
+		for (k=0;k<num_groups;k++)
+		{
+			g=&groups[k];
+			tmp=LittleLong(g->start_frame);
+			SafeWrite (modelouthandle,&tmp,sizeof(int));
+			tmp=LittleLong(g->num_frames);
+			SafeWrite (modelouthandle,&tmp,sizeof(int));
+			tmp=LittleLong(g->degrees);
+			SafeWrite (modelouthandle,&tmp,sizeof(int));
+
+			SafeWrite (modelouthandle,g->mat,fmheader.num_xyz*3*g->degrees*sizeof(char));
+			SafeWrite (modelouthandle,g->ccomp,g->num_frames*g->degrees*sizeof(char));
+			SafeWrite (modelouthandle,g->cbase,fmheader.num_xyz*3*sizeof(unsigned char));
+			SafeWrite (modelouthandle,g->cscale,g->degrees*sizeof(float));
+			SafeWrite (modelouthandle,g->coffset,g->degrees*sizeof(float));
+			SafeWrite (modelouthandle,g->trans,3*sizeof(float));
+			SafeWrite (modelouthandle,g->scale,3*sizeof(float));
+			SafeWrite (modelouthandle,g->bmin,3*sizeof(float));
+			SafeWrite (modelouthandle,g->bmax,3*sizeof(float));
+			free(g->mat);
+			free(g->ccomp);
+			free(g->cbase);
+			free(g->cscale);
+			free(g->coffset);
+		}
+	}
+
+	// write the skeletal info
+	if(g_skelModel.type != SKEL_NULL)
+	{
+		size = 0;
+
+		temp = sizeof(int);		// change this to a byte
+		memcpy(data + size, &g_skelModel.type, temp);
+		size += temp;
+
+		// number of joints
+		temp = sizeof(int);		// change this to a byte
+		memcpy(data + size, &numJointsInSkeleton[g_skelModel.type], temp);
+		size += temp;
+
+		// number of verts in each joint cluster
+		temp = sizeof(int)*numJointsInSkeleton[g_skelModel.type]; // change this to shorts
+		memcpy(data + size, &g_skelModel.new_num_verts[1], temp);
+		size += temp;
+
+		// cluster verts
+		for(i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)
+		{
+			current = g_skelModel.vertLists[i];
+			while(current)
+			{
+				temp = sizeof(int);	// change this to a short
+				memcpy(data + size, &current->data, temp);
+				size += temp;
+				toFree = current;
+				current = current->next;
+				free(toFree);  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
+			}
+		}
+
+		if(!num_groups) // joints are stored with regular verts for compressed models
+		{
+			framesWritten = true;
+
+			temp = sizeof(int);	// change this to a byte
+			memcpy(data + size, &framesWritten, temp);
+			size += temp;
+
+			for (i = 0; i < fmheader.num_frames; ++i)
+			{
+				in = &g_frames[i];
+
+				for (j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j)
+				{
+					for (k=0 ; k<3 ; k++)
+					{
+						// scale to byte values & min/max check
+						v = Q_rint ( (in->joints[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+						// write out origin as a float since they arn't clamped
+						temp = sizeof(float);	// change this to a short
+						assert(size+temp < DATA_SIZE);
+						memcpy(data + size, &v, temp);
+						size += temp;
+					}
+
+					for (k=0 ; k<3 ; k++)
+					{
+						v = Q_rint ( (in->joints[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+						// write out origin as a float since they arn't clamped
+						temp = sizeof(float);	// change this to a short
+						assert(size+temp < DATA_SIZE);
+						memcpy(data + size, &v, temp);
+						size += temp;
+					}
+
+					for (k=0 ; k<3 ; k++)
+					{
+						v = Q_rint ( (in->joints[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+						// write out origin as a float since they arn't clamped
+						temp = sizeof(float);	// change this to a short
+						assert(size+temp < DATA_SIZE);
+						memcpy(data + size, &v, temp);
+						size += temp;
+					}
+				}
+			}
+
+		}
+		else
+		{
+			temp = sizeof(int);	// change this to a byte
+			memcpy(data + size, &framesWritten, temp);
+			size += temp;
+		}
+
+		WriteHeader(modelouthandle, FM_SKELETON_NAME, FM_SKELETON_VER, size, data);
+	}
+
+	if(g_skelModel.references != REF_NULL)
+	{
+		int refnum;
+
+		size = 0;
+		if (RefPointNum <= 0)
+		{	// Hard-coded labels
+			refnum = numReferences[g_skelModel.references];
+		}
+		else
+		{	// Labels indicated in QDT
+			refnum = RefPointNum;
+		}
+
+		temp = sizeof(int);	// change this to a byte
+		memcpy(data2 + size, &g_skelModel.references, temp);
+		size += temp;
+
+		if(!num_groups)
+		{
+			framesWritten = true;
+
+			temp = sizeof(int);	// change this to a byte
+			memcpy(data2 + size, &framesWritten, temp);
+			size += temp;
+
+			for (i = 0; i < fmheader.num_frames; ++i)
+			{
+				in = &g_frames[i];
+
+				for (j = 0 ; j < refnum; ++j)
+				{
+					for (k=0 ; k<3 ; k++)
+					{
+						// scale to byte values & min/max check
+						v = Q_rint ( (in->references[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+						// write out origin as a float since they arn't clamped
+						temp = sizeof(float);	// change this to a short
+						assert(size+temp < DATA_SIZE);
+						memcpy(data2 + size, &v, temp);
+						size += temp;
+					}
+
+					for (k=0 ; k<3 ; k++)
+					{
+						v = Q_rint ( (in->references[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+						// write out origin as a float since they arn't clamped
+						temp = sizeof(float);	// change this to a short
+						assert(size+temp < DATA_SIZE);
+						memcpy(data2 + size, &v, temp);
+						size += temp;
+					}
+
+					for (k=0 ; k<3 ; k++)
+					{
+						v = Q_rint ( (in->references[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+						// write out origin as a float since they arn't clamped
+						temp = sizeof(float);	// change this to a short
+						assert(size+temp < DATA_SIZE);
+						memcpy(data2 + size, &v, temp);
+						size += temp;
+					}
+				}
+			}
+		}
+		else	// FINISH ME: references need to be stored with regular verts for compressed models
+		{
+			framesWritten = false;
+
+			temp = sizeof(int);	// change this to a byte
+			memcpy(data2 + size, &framesWritten, temp);
+			size += temp;
+		}
+
+		WriteHeader(modelouthandle, FM_REFERENCES_NAME, FM_REFERENCES_VER, size, data2);
+	}
+}
+
+static void CompressFrames()
+{
+	fmgroup_t *g;
+	int i,j,k;
+	fmframe_t	*in;
+
+	j=0;
+	for (i=0;i<fmheader.num_frames;i++)
+	{
+		while (i>=groups[j].start_frame+groups[j].num_frames&&j<num_groups-1)
+			j++;
+		frame_to_group[i]=j;
+	}
+
+	for (k=0;k<num_groups;k++)
+	{
+		g=&groups[k];
+
+		printf("\nCompressing Frames for group %i...\n", k);
+		AnimCompressInit(g->num_frames,fmheader.num_xyz,g->degrees);
+		for (i=0;i<g->num_frames;i++)
+		{
+			in = &g_frames[i+g->start_frame];
+			for (j=0;j<fmheader.num_xyz;j++)
+				AnimSetFrame(i,j,in->v[j].v[0],in->v[j].v[1],in->v[j].v[2]);
+		}
+		AnimCompressDoit();
+		g->mat= (char *) SafeMalloc(fmheader.num_xyz*3*g->degrees*sizeof(char), "CompressFrames");
+		g->ccomp=(char *) SafeMalloc(g->num_frames*g->degrees*sizeof(char), "CompressFrames");
+		g->cbase=(char *) SafeMalloc(fmheader.num_xyz*3*sizeof(unsigned char), "CompressFrames");
+		g->cscale=(float *) SafeMalloc(g->degrees*sizeof(float), "CompressFrames");
+		g->coffset=(float *) SafeMalloc(g->degrees*sizeof(float), "CompressFrames");
+		AnimCompressToBytes(g->trans,g->scale,g->mat,g->ccomp,g->cbase,g->cscale,g->coffset,g->bmin,g->bmax);
+		AnimCompressEnd();
+	}
+}
+
+static void OptimizeVertices(void)
+{
+	qboolean	vert_used[MAX_FM_VERTS];
+	short		vert_replacement[MAX_FM_VERTS];
+	int			i,j,k,l,pos,bit,set_pos,set_bit;
+	fmframe_t	*in;
+	qboolean	Found;
+	int			num_unique;
+	static IntListNode_t *newVertLists[NUM_CLUSTERS];
+	static int newNum_verts[NUM_CLUSTERS];
+	IntListNode_t *current, *next;
+
+	printf("Optimizing vertices...");
+
+	memset(vert_used, 0, sizeof(vert_used));
+
+	if(g_skelModel.clustered == true)
+	{
+		memset(newNum_verts, 0, sizeof(newNum_verts));
+		memset(newVertLists, 0, sizeof(newVertLists));
+	}
+
+	num_unique = 0;
+
+	// search for common points among all the frames
+	for (i=0 ; i<fmheader.num_frames ; i++)
+	{
+		in = &g_frames[i];
+
+		for(j=0;j<fmheader.num_xyz;j++)
+		{
+			for(k=0,Found=false;k<j;k++)
+			{	// starting from the beginning always ensures vert_replacement points to the first point in the array
+				if (in->v[j].v[0] == in->v[k].v[0] &&
+					in->v[j].v[1] == in->v[k].v[1] &&
+					in->v[j].v[2] == in->v[k].v[2])
+				{
+					Found = true;
+					vert_replacement[j] = k;
+					break;
+				}
+
+			}
+
+			if (!Found)
+			{
+				if (!vert_used[j])
+				{
+					num_unique++;
+				}
+				vert_used[j] = true;
+			}
+		}
+	}
+
+	// recompute the light normals
+	for (i=0 ; i<fmheader.num_frames ; i++)
+	{
+		in = &g_frames[i];
+
+		for(j=0;j<fmheader.num_xyz;j++)
+		{
+			if (!vert_used[j])
+			{
+				k = vert_replacement[j];
+
+				VectorAdd (in->v[j].vnorm.normalsum, in->v[k].vnorm.normalsum, in->v[k].vnorm.normalsum);
+				in->v[k].vnorm.numnormals += in->v[j].vnorm.numnormals++;
+			}
+		}
+
+		for (j=0 ; j<fmheader.num_xyz ; j++)
+		{
+			vec3_t	v;
+			float	maxdot;
+			int		maxdotindex;
+			int		c;
+
+			c = in->v[j].vnorm.numnormals;
+			if (!c)
+				Error ("Vertex with no triangles attached");
+
+			VectorScale (in->v[j].vnorm.normalsum, 1.0/c, v);
+			VectorNormalize (v, v);
+
+			maxdot = -999999.0;
+			maxdotindex = -1;
+
+			for (k=0 ; k<NUMVERTEXNORMALS ; k++)
+			{
+				float	dot;
+
+				dot = DotProduct (v, avertexnormals[k]);
+				if (dot > maxdot)
+				{
+					maxdot = dot;
+					maxdotindex = k;
+				}
+			}
+
+			in->v[j].lightnormalindex = maxdotindex;
+		}
+	}
+
+	// create substitution list
+	num_unique = 0;
+	for(i=0;i<fmheader.num_xyz;i++)
+	{
+		if (vert_used[i])
+		{
+			vert_replacement[i] = num_unique;
+			num_unique++;
+		}
+		else
+		{
+			vert_replacement[i] = vert_replacement[vert_replacement[i]];
+		}
+
+		// vert_replacement[i] is the new index, i is the old index
+		// need to add the new index to the cluster list if old index was in it
+		if(g_skelModel.clustered == true)
+		{
+			for(k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k)
+			{
+				for(l = 0, current = g_skelModel.vertLists[k]; 
+					l < g_skelModel.new_num_verts[k+1]; ++l, current = current->next)
+				{
+					if(current->data == i)
+					{
+						IntListNode_t *current2;
+						int m;
+						qboolean added = false;
+
+						for(m = 0, current2 = newVertLists[k]; m < newNum_verts[k+1];
+							++m, current2 = current2->next)
+						{
+							if(current2->data == vert_replacement[i])
+							{
+								added = true;
+								break;
+							}
+						}
+
+						if(!added)
+						{
+							++newNum_verts[k+1];
+
+							next = newVertLists[k];
+
+							newVertLists[k] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "OptimizeVertices");
+							// freed after model write out
+
+							newVertLists[k]->data = vert_replacement[i];
+							newVertLists[k]->next = next;
+						}
+						break;
+					}
+				}
+			}
+		}
+	}
+
+	// substitute
+	for (i=0 ; i<fmheader.num_frames ; i++)
+	{
+		in = &g_frames[i];
+
+		for(j=0;j<fmheader.num_xyz;j++)
+		{
+			in->v[vert_replacement[j]] = in->v[j];
+		}
+
+	}
+
+	for(i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)
+	{
+		IntListNode_t *toFree;
+		current = g_skelModel.vertLists[i];
+
+		while(current)
+		{
+			toFree = current;
+			current = current->next;
+			free(toFree);  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
+		}
+
+		g_skelModel.vertLists[i] = newVertLists[i];
+		g_skelModel.new_num_verts[i+1] = newNum_verts[i+1];
+	}
+
+#ifndef NDEBUG
+	for(k = 0; k < numJointsInSkeleton[g_skelModel.type]; ++k)
+	{
+		for(l = 0, current = g_skelModel.vertLists[k]; 
+			l < g_skelModel.new_num_verts[k+1]; ++l, current = current->next)
+		{
+			IntListNode_t *current2;
+			int m;
+
+			for(m = l+1, current2 = current->next; m < newNum_verts[k+1];
+				++m, current2 = current2->next)
+			{
+				if(current->data == current2->data)
+				{
+					printf("Warning duplicate vertex:  %d\n", current->data);
+					break;
+				}
+			}
+		}
+	}
+#endif
+
+	for(i=0;i<fmheader.num_mesh_nodes;i++)
+	{	// reset the vert bits
+		memset(pmnodes[i].verts,0,sizeof(pmnodes[i].verts));
+	}
+
+	// repleace the master triangle list vertex indexes and update the vert bits for each mesh node
+	for (i=0 ; i<fmheader.num_tris ; i++)
+	{
+		pos = i >> 3;
+		bit = 1 << (i & 7 );
+
+		for (j=0 ; j<3 ; j++)
+		{	
+			set_bit = set_pos = triangles[i].index_xyz[j] = vert_replacement[triangles[i].index_xyz[j]];
+
+			set_pos >>= 3;
+			set_bit = 1 << (set_bit & 7);
+
+			for(k=0;k<fmheader.num_mesh_nodes;k++)
+			{
+				if (!(pmnodes[k].tris[pos] & bit))
+				{
+					continue;
+				}
+				pmnodes[k].verts[set_pos] |= set_bit;
+			}
+		}
+	}
+
+	for (i=0;i<numcommands;i++)
+	{
+		j = commands[i];
+		if (!j) continue;
+
+		j = abs(j);
+		for(i++;j;j--,i+=3)
+		{
+			commands[i+2] = vert_replacement[commands[i+2]];
+		}
+		i--;
+	}
+
+	printf("Reduced by %d\n",fmheader.num_xyz - num_unique);
+	
+	fmheader.num_xyz = num_unique;
+	if (num_groups)
+	{
+		// tack on the reference verts to the regular verts
+		if(g_skelModel.references != REF_NULL)
+		{
+			fmframe_t	*in;
+			int index;
+			int refnum;
+
+			if (RefPointNum <= 0)
+			{	// Hard-coded labels
+				refnum = numReferences[g_skelModel.references];
+			}
+			else
+			{	// Labels indicated in QDT
+				refnum = RefPointNum;
+			}
+
+
+			for (i = 0; i < fmheader.num_frames; ++i)
+			{
+				in = &g_frames[i];
+				index = fmheader.num_xyz;
+
+				for (j = 0 ; j < refnum; ++j)
+				{
+					VectorCopy(in->references[j].placement.origin, in->v[index].v);
+					index++;
+
+					VectorCopy(in->references[j].placement.direction, in->v[index].v);
+					index++;
+
+					VectorCopy(in->references[j].placement.up, in->v[index].v);
+					index++;
+				}
+			}
+
+			fmheader.num_xyz += refnum*3;
+		}
+
+		// tack on the skeletal joint verts to the regular verts
+		if(g_skelModel.type != SKEL_NULL)
+		{
+			fmframe_t	*in;
+			int index;
+
+			for (i = 0; i < fmheader.num_frames; ++i)
+			{
+				in = &g_frames[i];
+				index = fmheader.num_xyz;
+
+				for (j = 0 ; j < numJointsInSkeleton[g_skelModel.type]; ++j)
+				{
+					VectorCopy(in->joints[j].placement.origin, in->v[index].v);
+					index++;
+
+					VectorCopy(in->joints[j].placement.direction, in->v[index].v);
+					index++;
+
+					VectorCopy(in->joints[j].placement.up, in->v[index].v);
+					index++;
+				}
+			}
+
+			fmheader.num_xyz += numJointsInSkeleton[g_skelModel.type]*3;
+		}
+
+		CompressFrames();
+	}
+}
+
+
+/*
+===============
+FinishModel
+===============
+*/
+void FMFinishModel (void)
+{
+	FILE		*modelouthandle;
+	int			i,j,length,tris,verts,bit,pos,total_tris,total_verts;
+	char		name[1024];
+	int			trans_count;
+	
+	if (!fmheader.num_frames)
+		return;
+	
+//
+// copy to release directory tree if doing a release build
+//
+	if (g_release)
+	{
+		if (modelname[0])
+			sprintf (name, "%s", modelname);
+		else
+			sprintf (name, "%s/tris.fm", cdpartial);
+		ReleaseFile (name);
+
+		for (i=0 ; i<fmheader.num_skins ; i++)
+		{
+			ReleaseFile (g_skins[i]);
+		}
+		fmheader.num_frames = 0;
+		return;
+	}
+
+	printf("\n");
+
+	trans_count = 0;
+	for(i=0;i<fmheader.num_tris;i++)
+		if (translucent[i])
+			trans_count++;
+
+	if (!g_no_opimizations)
+	{
+		OptimizeVertices();
+	}
+
+//
+// write the model output file
+//
+	if (modelname[0])
+		sprintf (name, "%s%s", g_outputDir, modelname);
+	else
+		sprintf (name, "%s/tris.fm", g_outputDir);
+	printf ("saving to %s\n", name);
+	CreatePath (name);
+	modelouthandle = SafeOpenWrite (name);
+
+	WriteModelFile (modelouthandle);
+	
+	printf ("%3dx%3d skin\n", fmheader.skinwidth, fmheader.skinheight);
+	printf ("First frame boundaries:\n");
+	printf ("	minimum x: %3f\n", g_frames[0].mins[0]);
+	printf ("	maximum x: %3f\n", g_frames[0].maxs[0]);
+	printf ("	minimum y: %3f\n", g_frames[0].mins[1]);
+	printf ("	maximum y: %3f\n", g_frames[0].maxs[1]);
+	printf ("	minimum z: %3f\n", g_frames[0].mins[2]);
+	printf ("	maximum z: %3f\n", g_frames[0].maxs[2]);
+	printf ("%4d vertices\n", fmheader.num_xyz);
+	printf ("%4d triangles, %4d of them translucent\n", fmheader.num_tris, trans_count);
+	printf ("%4d frame\n", fmheader.num_frames);
+	printf ("%4d glverts\n", numglverts);
+	printf ("%4d glcmd\n", fmheader.num_glcmds);
+	printf ("%4d skins\n", fmheader.num_skins);
+	printf ("%4d mesh nodes\n", fmheader.num_mesh_nodes);
+	printf ("wasted pixels: %d / %d (%5.2f Percent)\n",total_skin_pixels - skin_pixels_used, 
+		total_skin_pixels, (double)(total_skin_pixels - skin_pixels_used) / (double)total_skin_pixels * 100.0);
+
+	printf ("file size: %d\n", (int)ftell (modelouthandle) );
+	printf ("---------------------\n");
+	
+	if (g_verbose)
+	{
+		if (fmheader.num_mesh_nodes)
+		{
+			total_tris = total_verts = 0;
+			printf("Node Name                         Tris Verts\n");
+			printf("--------------------------------- ---- -----\n");
+			for(i=0;i<fmheader.num_mesh_nodes;i++)
+			{
+				tris = 0;
+				verts = 0;
+				for(j=0;j<MAXTRIANGLES;j++)
+				{
+					pos = (j) >> 3;
+					bit = 1 << ((j) & 7 );
+					if (pmnodes[i].tris[pos] & bit)
+					{
+						tris++;
+					}
+				}
+				for(j=0;j<MAX_FM_VERTS;j++)
+				{
+					pos = (j) >> 3;
+					bit = 1 << ((j) & 7 );
+					if (pmnodes[i].verts[pos] & bit)
+					{
+						verts++;
+					}
+				}
+
+				printf("%-33s %4d %5d\n",pmnodes[i].name,tris,verts);
+
+				total_tris += tris;
+				total_verts += verts;
+			}
+			printf("--------------------------------- ---- -----\n");
+			printf("%-33s %4d %5d\n","TOTALS",total_tris,total_verts);
+		}
+	}
+	fclose (modelouthandle);
+
+	// finish writing header file
+	H_printf("\n");
+
+	// scale_up is usefull to allow step distances to be adjusted
+	H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
+
+	// mesh nodes
+	if (fmheader.num_mesh_nodes)
+	{
+		H_printf("\n");
+		H_printf("#define NUM_MESH_NODES\t\t%d\n\n",fmheader.num_mesh_nodes);
+		for(i=0;i<fmheader.num_mesh_nodes;i++)
+		{
+			strcpy(name, pmnodes[i].name);
+			strupr(name);
+			length = strlen(name);
+			for(j=0;j<length;j++)
+			{
+				if (name[j] == ' ')
+				{
+					name[j] = '_';
+				}
+			}
+			H_printf("#define MESH_%s\t\t%d\n", name, i);
+		}
+	}
+
+	fclose (headerouthandle);
+	headerouthandle = NULL;
+	free (pmnodes);
+}
+
+
+/*
+=================================================================
+
+ALIAS MODEL DISPLAY LIST GENERATION
+
+=================================================================
+*/
+
+extern int		strip_xyz[128];
+extern int		strip_st[128];
+extern int		strip_tris[128];
+extern int		stripcount;
+
+/*
+================
+StripLength
+================
+*/
+static int	StripLength (int starttri, int startv, int num_tris, int node)
+{
+	int				m1, m2;
+	int				st1, st2;
+	int				j;
+	fmtriangle_t	*last, *check;
+	int				k;
+	int				pos, bit;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	strip_xyz[0] = last->index_xyz[(startv)%3];
+	strip_xyz[1] = last->index_xyz[(startv+1)%3];
+	strip_xyz[2] = last->index_xyz[(startv+2)%3];
+	strip_st[0] = last->index_st[(startv)%3];
+	strip_st[1] = last->index_st[(startv+1)%3];
+	strip_st[2] = last->index_st[(startv+2)%3];
+
+	strip_tris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->index_xyz[(startv+2)%3];
+	st1 = last->index_st[(startv+2)%3];
+	m2 = last->index_xyz[(startv+1)%3];
+	st2 = last->index_st[(startv+1)%3];
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1]
+		; j<num_tris ; j++, check++)
+	{
+		pos = j >> 3;
+		bit = 1 << (j & 7 );
+		if (!(pmnodes[node].tris[pos] & bit))
+		{
+			continue;
+		}
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->index_xyz[k] != m1)
+				continue;
+			if (check->index_st[k] != st1)
+				continue;
+			if (check->index_xyz[ (k+1)%3 ] != m2)
+				continue;
+			if (check->index_st[ (k+1)%3 ] != st2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j] || translucent[j] != translucent[starttri])
+				goto done;
+
+			// the new edge
+			if (stripcount & 1)
+			{
+				m2 = check->index_xyz[ (k+2)%3 ];
+				st2 = check->index_st[ (k+2)%3 ];
+			}
+			else
+			{
+				m1 = check->index_xyz[ (k+2)%3 ];
+				st1 = check->index_st[ (k+2)%3 ];
+			}
+
+			strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
+			strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
+			strip_tris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<num_tris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+/*
+===========
+FanLength
+===========
+*/
+static int	FanLength (int starttri, int startv, int num_tris, int node)
+{
+	int				m1, m2;
+	int				st1, st2;
+	int				j;
+	fmtriangle_t	*last, *check;
+	int				k;
+	int				pos, bit;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	strip_xyz[0] = last->index_xyz[(startv)%3];
+	strip_xyz[1] = last->index_xyz[(startv+1)%3];
+	strip_xyz[2] = last->index_xyz[(startv+2)%3];
+	strip_st[0] = last->index_st[(startv)%3];
+	strip_st[1] = last->index_st[(startv+1)%3];
+	strip_st[2] = last->index_st[(startv+2)%3];
+
+	strip_tris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->index_xyz[(startv+0)%3];
+	st1 = last->index_st[(startv+0)%3];
+	m2 = last->index_xyz[(startv+2)%3];
+	st2 = last->index_st[(startv+2)%3];
+
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1] 
+		; j<num_tris ; j++, check++)
+	{
+		pos = j >> 3;
+		bit = 1 << (j & 7 );
+		if (!(pmnodes[node].tris[pos] & bit))
+		{
+			continue;
+		}
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->index_xyz[k] != m1)
+				continue;
+			if (check->index_st[k] != st1)
+				continue;
+			if (check->index_xyz[ (k+1)%3 ] != m2)
+				continue;
+			if (check->index_st[ (k+1)%3 ] != st2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j] || translucent[j] != translucent[starttri])
+				goto done;
+
+			// the new edge
+			m2 = check->index_xyz[ (k+2)%3 ];
+			st2 = check->index_st[ (k+2)%3 ];
+
+			strip_xyz[stripcount+2] = m2;
+			strip_st[stripcount+2] = st2;
+			strip_tris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<num_tris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+
+/*
+================
+BuildGlCmds
+
+Generate a list of trifans or strips
+for the model, which holds for all frames
+================
+*/
+static void BuildGlCmds (void)
+{
+	int		i, j, k, l;
+	int		startv;
+	float	s, t;
+	int		len, bestlen, besttype;
+	int		best_xyz[1024];
+	int		best_st[1024];
+	int		best_tris[1024];
+	int		type;
+	int		trans_check;
+	int		bit,pos;
+
+	//
+	// build tristrips
+	//
+	numcommands = 0;
+	numglverts = 0;
+
+
+	for(l=0;l<fmheader.num_mesh_nodes;l++)
+	{
+		memset (used, 0, sizeof(used));
+
+		pmnodes[l].start_glcmds = numcommands;
+
+		for(trans_check = 0; trans_check<2; trans_check++)
+		{
+			for (i=0 ; i < fmheader.num_tris ; i++)
+			{
+				pos = i >> 3;
+				bit = 1 << (i & 7 );
+				if (!(pmnodes[l].tris[pos] & bit))
+				{
+					continue;
+				}
+
+				// pick an unused triangle and start the trifan
+				if (used[i] || trans_check != translucent[i])
+				{
+					continue;
+				}
+
+				bestlen = 0;
+				for (type = 0 ; type < 2 ; type++)
+		//	type = 1;
+				{
+					for (startv =0 ; startv < 3 ; startv++)
+					{
+						if (type == 1)
+							len = StripLength (i, startv, fmheader.num_tris, l);
+						else
+							len = FanLength (i, startv, fmheader.num_tris, l);
+						if (len > bestlen)
+						{
+							besttype = type;
+							bestlen = len;
+							for (j=0 ; j<bestlen+2 ; j++)
+							{
+								best_st[j] = strip_st[j];
+								best_xyz[j] = strip_xyz[j];
+							}
+							for (j=0 ; j<bestlen ; j++)
+								best_tris[j] = strip_tris[j];
+						}
+					}
+				}
+
+				// mark the tris on the best strip/fan as used
+				for (j=0 ; j<bestlen ; j++)
+					used[best_tris[j]] = 1;
+
+				if (besttype == 1)
+					commands[numcommands++] = (bestlen+2);
+				else
+					commands[numcommands++] = -(bestlen+2);
+
+				numglverts += bestlen+2;
+
+				for (j=0 ; j<bestlen+2 ; j++)
+				{
+					// emit a vertex into the reorder buffer
+					k = best_st[j];
+
+					// emit s/t coords into the commands stream
+					s = base_st[k].s;
+					t = base_st[k].t;
+
+					s = (s  ) / fmheader.skinwidth;
+					t = (t  ) / fmheader.skinheight;
+
+					*(float *)&commands[numcommands++] = s;
+					*(float *)&commands[numcommands++] = t;
+					*(int *)&commands[numcommands++] = best_xyz[j];
+				}
+			}
+		}
+		commands[numcommands++] = 0;		// end of list marker
+		pmnodes[l].num_glcmds = numcommands - pmnodes[l].start_glcmds;
+	}
+}
+
+
+/*
+===============================================================
+
+BASE FRAME SETUP
+
+===============================================================
+*/
+
+
+#define LINE_NORMAL 1
+#define LINE_FAT 2
+#define LINE_DOTTED 3
+
+
+#define ASCII_SPACE 32
+
+int LineType = LINE_NORMAL;
+extern unsigned char pic[SKINPAGE_HEIGHT*SKINPAGE_WIDTH], pic_palette[768];
+unsigned char LineColor = 255;
+int ScaleWidth, ScaleHeight;
+
+
+static char *CharDefs[] =
+{
+	"-------------------------",
+	"-------------------------", // !
+	"-------------------------", // "
+	"-------------------------", // #
+	"-------------------------", // $
+	"-------------------------", // %
+	"-------------------------", // &
+	"--*----*-----------------", // '
+	"-*---*----*----*-----*---", // (
+	"*-----*----*----*---*----", // )
+	"-----*--*--**---**--*--*-", // *
+	"-------------------------", // +
+	"----------------**--**---", // ,
+	"-------------------------", // -
+	"----------------**---**--", // .
+	"-------------------------", // /
+	" *** *  *** * ***  * *** ", // 0
+	"   *   **    *    *    * ",
+	"****     * *** *    *****",
+	"****     * ***     ***** ",
+	"  **  * * *  * *****   * ",
+	"**** *    ****     ***** ",
+	" *** *    **** *   * *** ",
+	"*****    *   *   *    *  ",
+	" *** *   * *** *   * *** ",
+	" *** *   * ****    * *** ", // 9
+	"-**---**--------**---**--", // :
+	"-------------------------", // ;
+	"-------------------------", // <
+	"-------------------------", // =
+	"-------------------------", // >
+	"-------------------------", // ?
+	"-------------------------", // @
+	"-***-*---*******---**---*", // A
+	"****-*---*****-*---*****-",
+	"-*****----*----*-----****",
+	"****-*---**---**---*****-",
+	"******----****-*----*****",
+	"******----****-*----*----",
+	"-*****----*--***---*-****",
+	"*---**---*******---**---*",
+	"-***---*----*----*---***-",
+	"----*----*----**---*-***-",
+	"-*--*-*-*--**---*-*--*--*",
+	"-*----*----*----*----****",
+	"*---***-***-*-**---**---*",
+	"*---***--**-*-**--***---*",
+	"-***-*---**---**---*-***-",
+	"****-*---*****-*----*----",
+	"-***-*---**---*-***----**",
+	"****-*---*****-*-*--*--**",
+	"-*****-----***-----*****-",
+	"*****--*----*----*----*--",
+	"*---**---**---**---******",
+	"*---**---**---*-*-*---*--",
+	"*---**---**-*-***-***---*",
+	"*---*-*-*---*---*-*-*---*",
+	"*---**---*-*-*---*----*--",
+	"*****---*---*---*---*****" // Z
+};
+
+void DrawLine(int x1, int y1, int x2, int y2)
+{
+	int dx, dy;
+	int adx, ady;
+	int count;
+	float xfrac, yfrac, xstep, ystep;
+	unsigned sx, sy;
+	float u, v;
+
+	dx = x2 - x1;
+	dy = y2 - y1;
+	adx = abs(dx);
+	ady = abs(dy);
+
+	count = adx > ady ? adx : ady;
+	count++;
+
+	if(count > 300)
+	{
+		printf("Bad count\n");
+		return; // don't ever hang up on bad data
+	}
+		
+	xfrac = x1;
+	yfrac = y1;
+	
+	xstep = (float)dx/count;
+	ystep = (float)dy/count;
+
+	switch(LineType)
+	{
+		case LINE_NORMAL:
+			do
+			{
+				if(xfrac < SKINPAGE_WIDTH && yfrac < SKINPAGE_HEIGHT)
+				{
+					pic[(int)yfrac*SKINPAGE_WIDTH+(int)xfrac] = LineColor;
+				}
+				xfrac += xstep;
+				yfrac += ystep;
+				count--;
+			} while (count > 0);
+			break;
+		case LINE_FAT:
+			do
+			{
+				for (u=-0.1 ; u<=0.9 ; u+=0.999)
+				{
+					for (v=-0.1 ; v<=0.9 ; v+=0.999)
+					{
+						sx = xfrac+u;
+						sy = yfrac+v;
+						if(sx < SKINPAGE_WIDTH && sy < SKINPAGE_HEIGHT)
+						{
+							pic[sy*SKINPAGE_WIDTH+sx] = LineColor;
+						}
+					}
+				}
+				xfrac += xstep;
+				yfrac += ystep;
+				count--;
+			} while (count > 0);
+			break;
+		case LINE_DOTTED:
+			do
+			{
+				if(count&1 && xfrac < SKINPAGE_WIDTH &&
+					yfrac < SKINPAGE_HEIGHT)
+				{
+					pic[(int)yfrac*SKINPAGE_WIDTH+(int)xfrac] = LineColor;
+				}
+				xfrac += xstep;
+				yfrac += ystep;
+				count--;
+			} while (count > 0);
+			break;
+		default:
+			Error("Unknown <linetype> %d.\n", LineType);
+	}
+}
+
+//==========================================================================
+//
+// DrawCharacter
+//
+//==========================================================================
+
+static void DrawCharacter(int x, int y, int character)
+{
+	int r, c;
+	char *def;
+
+	character = toupper(character);
+	if(character < ASCII_SPACE || character > 'Z')
+	{
+		character = ASCII_SPACE;
+	}
+	character -= ASCII_SPACE;
+	for(def = CharDefs[character], r = 0; r < 5; r++)
+	{
+		for(c = 0; c < 5; c++)
+		{
+			pic[(y+r)*SKINPAGE_WIDTH+x+c] = *def++ == '*' ? 255 : 0;
+		}
+	}
+}
+
+//==========================================================================
+//
+// DrawTextChar
+//
+//==========================================================================
+
+void DrawTextChar(int x, int y, char *text)
+{
+	int c;
+
+	while((c = *text++) != '\0')
+	{
+		DrawCharacter(x, y, c);
+		x += 6;
+	}
+}
+
+
+extern void DrawScreen(float s_scale, float t_scale, float iwidth, float iheight);
+
+//==========================================================================
+// ExtractDigit
+
+static int ExtractDigit(byte *pic, int x, int y)
+{
+	int		i;
+	int		r, c;
+	char	digString[32];
+	char	*buffer;
+	byte	backColor;
+	char	**DigitDefs;
+
+	backColor = pic[(SKINPAGE_HEIGHT - 1) * SKINPAGE_WIDTH];
+	DigitDefs = &CharDefs['0' - ASCII_SPACE];
+
+	buffer = digString;
+	for(r = 0; r < 5; r++)
+	{
+		for(c = 0; c < 5; c++)
+		{
+			*buffer++ = (pic[(y + r) * SKINPAGE_WIDTH + x + c] == backColor) ? ' ' : '*';
+		}
+	}
+	*buffer = '\0';
+	for(i = 0; i < 10; i++)
+	{
+		if(strcmp(DigitDefs[i], digString) == 0)
+		{
+			return i;
+		}
+	}
+
+	Error("Unable to extract scaling info from skin PCX.");
+	return 0;
+}
+
+//==========================================================================
+// ExtractNumber
+
+int ExtractNumber(byte *pic, int x, int y)
+{
+	return ExtractDigit(pic, x, y) * 100 + ExtractDigit(pic, x + 6, y) * 10 + ExtractDigit(pic, x + 12, y);
+}
+
+
+
+
+
+/*
+============
+BuildST
+
+Builds the triangle_st array for the base frame and
+fmheader.skinwidth / fmheader.skinheight
+
+  FIXME: allow this to be loaded from a file for
+  arbitrary mappings
+============
+*/
+static void BuildST (triangle_t *ptri, int numtri, qboolean DrawSkin)
+{
+	int			backface_flag;
+	int			i, j;
+	int			width, height, iwidth, iheight, swidth;
+	float		basex, basey;
+	float		scale;
+	vec3_t		mins, maxs;
+	float		*pbasevert;
+	vec3_t		vtemp1, vtemp2, normal;
+	float		s_scale, t_scale;
+	float		scWidth;
+	float		scHeight;
+	int skinwidth;
+	int skinheight;
+
+	//
+	// find bounds of all the verts on the base frame
+	//
+	ClearBounds (mins, maxs);
+	backface_flag = false;
+	
+	if (ptri[0].HasUV)	// if we have the uv already, we don't want to double up or scale
+	{
+		iwidth = ScaleWidth;
+		iheight = ScaleHeight;
+		
+		t_scale = s_scale = 1.0;
+	}
+	else
+	{
+		for (i=0 ; i<numtri ; i++)
+			for (j=0 ; j<3 ; j++)
+				AddPointToBounds (ptri[i].verts[j], mins, maxs);
+			
+			for (i=0 ; i<3 ; i++)
+			{
+				mins[i] = floor(mins[i]);
+				maxs[i] = ceil(maxs[i]);
+			}
+			
+			width = maxs[0] - mins[0];
+			height = maxs[2] - mins[2];
+			
+			for (i=0 ; i<numtri ; i++)
+			{
+				VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+				VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+				CrossProduct (vtemp1, vtemp2, normal);
+				
+				if (normal[1] > 0)
+				{
+					backface_flag = true;
+					break;
+				}
+			}
+			scWidth = ScaleWidth*SCALE_ADJUST_FACTOR;
+			if (backface_flag)	//we are doubling
+				scWidth /= 2;
+			
+			scHeight = ScaleHeight*SCALE_ADJUST_FACTOR;
+			
+			scale = scWidth/width;
+			
+			if(height*scale >= scHeight)
+			{
+				scale = scHeight/height;
+			}
+			
+			iwidth = ceil(width*scale)+4;
+			iheight = ceil(height*scale)+4;
+			
+			s_scale = (float)(iwidth-4) / width;
+			t_scale = (float)(iheight-4) / height;
+			t_scale = s_scale;
+	}
+	if (DrawSkin)
+	{
+		if(backface_flag)
+			DrawScreen(s_scale, t_scale, iwidth*2, iheight);
+		else
+			DrawScreen(s_scale, t_scale, iwidth, iheight);
+	}
+	if (backface_flag)
+		skinwidth=iwidth*2;
+	else
+		skinwidth=iwidth;
+	skinheight=iheight;
+
+
+/*	if (!g_fixedwidth)
+	{	// old style
+		scale = 8;
+		if (width*scale >= 150)
+			scale = 150.0 / width;	
+		if (height*scale >= 190)
+			scale = 190.0 / height;
+
+		s_scale = t_scale = scale;
+
+		iwidth = ceil(width*s_scale);
+		iheight = ceil(height*t_scale);
+
+		iwidth += 4;
+		iheight += 4;
+	}
+	else
+	{	// new style
+		iwidth = g_fixedwidth / 2;
+		iheight = g_fixedheight;
+
+		s_scale = (float)(iwidth-4) / width;
+		t_scale = (float)(iheight-4) / height;
+	}*/
+
+//
+// determine which side of each triangle to map the texture to
+//
+	basey = 2;
+	for (i=0 ; i<numtri ; i++)
+	{
+		if (ptri[i].HasUV)
+		{
+			for (j=0 ; j<3 ; j++)
+			{
+				triangle_st[i][j][0] = Q_rint(ptri[i].uv[j][0]*skinwidth);
+				triangle_st[i][j][1] = Q_rint((1.0f-ptri[i].uv[j][1])*skinheight);
+			}
+		}
+		else
+		{
+			VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+			VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+			CrossProduct (vtemp1, vtemp2, normal);
+
+			if (normal[1] > 0)
+			{
+				basex = iwidth + 2;
+			}
+			else
+			{
+				basex = 2;
+			}
+			
+			for (j=0 ; j<3 ; j++)
+			{
+				pbasevert = ptri[i].verts[j];
+
+				triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
+				triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
+			}
+		}
+
+		if (DrawSkin)
+		{
+			DrawLine(triangle_st[i][0][0], triangle_st[i][0][1],
+				triangle_st[i][1][0], triangle_st[i][1][1]);
+			DrawLine(triangle_st[i][1][0], triangle_st[i][1][1],
+				triangle_st[i][2][0], triangle_st[i][2][1]);
+			DrawLine(triangle_st[i][2][0], triangle_st[i][2][1],
+				triangle_st[i][0][0], triangle_st[i][0][1]);
+		}
+	}
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+
+	swidth = iwidth;
+	if(backface_flag)
+		swidth *= 2;
+	fmheader.skinwidth = (swidth + 3) & ~3;
+	fmheader.skinheight = iheight;
+
+	skin_width = iwidth;
+	skin_height = iheight;
+}
+
+
+static void BuildNewST (triangle_t *ptri, int numtri, qboolean DrawSkin)
+{
+	int			i, j;
+
+	for (i=0 ; i<numtri ; i++)
+	{
+		if (ptri[i].HasUV)
+		{
+			for (j=0 ; j<3 ; j++)
+			{
+				triangle_st[i][j][0] = Q_rint(ptri[i].uv[j][0]*(ScaleWidth-1));
+				triangle_st[i][j][1] = Q_rint((1.0f-ptri[i].uv[j][1])*(ScaleHeight-1));
+			}
+		}
+
+		if (DrawSkin)
+		{
+			DrawLine(triangle_st[i][0][0], triangle_st[i][0][1],
+				triangle_st[i][1][0], triangle_st[i][1][1]);
+			DrawLine(triangle_st[i][1][0], triangle_st[i][1][1],
+				triangle_st[i][2][0], triangle_st[i][2][1]);
+			DrawLine(triangle_st[i][2][0], triangle_st[i][2][1],
+				triangle_st[i][0][0], triangle_st[i][0][1]);
+		}
+	}
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+
+	fmheader.skinwidth = (ScaleWidth + 3) & ~3;
+	fmheader.skinheight = ScaleHeight;
+
+	skin_width = ScaleWidth;
+	skin_height = ScaleHeight;
+}
+
+
+
+
+byte			*BasePalette;
+byte			*BasePixels,*TransPixels;
+int				BaseWidth, BaseHeight, TransWidth, TransHeight;
+qboolean		BaseTrueColor;
+static qboolean SetPixel = false;
+
+int CheckTransRecursiveTri (int *lp1, int *lp2, int *lp3)
+{
+	int		*temp;
+	int		d;
+	int		new[2];
+
+	d = lp2[0] - lp1[0];
+	if (d < -1 || d > 1)
+		goto split;
+	d = lp2[1] - lp1[1];
+	if (d < -1 || d > 1)
+		goto split;
+
+	d = lp3[0] - lp2[0];
+	if (d < -1 || d > 1)
+		goto split2;
+	d = lp3[1] - lp2[1];
+	if (d < -1 || d > 1)
+		goto split2;
+
+	d = lp1[0] - lp3[0];
+	if (d < -1 || d > 1)
+		goto split3;
+	d = lp1[1] - lp3[1];
+	if (d < -1 || d > 1)
+	{
+split3:
+		temp = lp1;
+		lp1 = lp3;
+		lp3 = lp2;
+		lp2 = temp;
+
+		goto split;
+	}
+
+	return 0;			// entire tri is filled
+
+split2:
+	temp = lp1;
+	lp1 = lp2;
+	lp2 = lp3;
+	lp3 = temp;
+
+split:
+// split this edge
+	new[0] = (lp1[0] + lp2[0]) >> 1;
+	new[1] = (lp1[1] + lp2[1]) >> 1;
+
+// draw the point if splitting a leading edge
+	if (lp2[1] > lp1[1])
+		goto nodraw;
+	if ((lp2[1] == lp1[1]) && (lp2[0] < lp1[0]))
+		goto nodraw;
+
+	if (SetPixel)
+	{
+		assert ((new[1]*BaseWidth) + new[0] < BaseWidth*BaseHeight);
+
+		if (BaseTrueColor)
+		{
+			BasePixels[((new[1]*BaseWidth) + new[0]) * 4] = 1;
+		}
+		else
+		{
+			BasePixels[(new[1]*BaseWidth) + new[0]] = 1;
+		}
+	}
+	else
+	{
+		if (TransPixels)
+		{
+			if (TransPixels[(new[1]*TransWidth) + new[0]] != 255)
+				return 1;
+		}
+		else if (BaseTrueColor)
+		{
+			if (BasePixels[(((new[1]*BaseWidth) + new[0]) * 4) + 3] != 255)
+				return 1;
+		}
+		else
+		{
+//			pixel = BasePixels[(new[1]*BaseWidth) + new[0]];
+		}
+	}
+
+nodraw:
+// recursively continue
+	if (CheckTransRecursiveTri(lp3, lp1, new)) 
+		return 1;
+
+	return CheckTransRecursiveTri(lp3, new, lp2);
+}
+
+static void ReplaceClusterIndex(int newIndex, int oldindex, int **clusters, 
+	IntListNode_t **vertLists, int *num_verts, int *new_num_verts)
+{
+	int i, j;
+	IntListNode_t *next;
+
+	for(j = 0; j < numJointsInSkeleton[g_skelModel.type]; ++j)
+	{
+		if(!clusters[j])
+		{
+			continue;
+		}
+
+		for(i = 0; i < num_verts[j+1]; ++i)
+		{
+			if(clusters[j][i] == oldindex)
+			{
+				++new_num_verts[j+1];
+
+				next = vertLists[j];
+
+				vertLists[j] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "ReplaceClusterIndex");
+				// Currently freed in WriteJointedModelFile only
+
+				vertLists[j]->data = newIndex;
+				vertLists[j]->next = next;
+			}
+		}
+	}
+}
+
+#define	FUDGE_EPSILON	0.002
+
+qboolean VectorFudgeCompare (vec3_t v1, vec3_t v2)
+{
+	int		i;
+	
+	for (i=0 ; i<3 ; i++)
+		if (fabs(v1[i]-v2[i]) > FUDGE_EPSILON)
+			return false;
+			
+	return true;
+}
+
+/*
+=================
+Cmd_Base
+=================
+*/
+void Cmd_FMBase (qboolean GetST)
+{
+	triangle_t	*ptri, *st_tri;
+	int			num_st_tris;
+	int			i, j, k, l;
+	int			x,y,z;
+//	int			time1;
+	char		file1[1024],file2[1024],trans_file[1024], stfile[1024], extension[256];
+	vec3_t		base_xyz[MAX_FM_VERTS];
+	FILE		*FH;
+	int			pos,bit;
+	qboolean	NewSkin;
+
+	GetScriptToken (false);
+
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	printf ("---------------------\n");
+	sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
+	printf ("%s ", file1);
+
+	ExpandPathAndArchive (file1);
+
+	// Use the input filepath for this one.
+	sprintf (file1, "%s/%s", cddir, token);
+
+//	time1 = FileTime (file1);
+//	if (time1 == -1)
+//		Error ("%s doesn't exist", file1);
+
+//
+// load the base triangles
+//
+	if (do3ds)
+		Load3DSTriangleList (file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
+	else
+		LoadTriangleList (file1, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
+
+	if (g_ignoreTriUV)
+	{
+		for (i=0;i<fmheader.num_tris;i++)
+		{
+			ptri[i].HasUV=0;
+		}
+	}
+
+	GetScriptToken (false);
+	sprintf (file2, "%s/%s", cddir, token);
+	sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
+
+	ExtractFileExtension (file2, extension);
+	if (extension[0] == 0)
+	{
+		strcat(file2, ".pcx");
+	}
+	printf ("skin: %s\n", file2);
+
+	BaseTrueColor = LoadAnyImage (file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight);
+
+	NewSkin = false;
+	if (BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT)
+	{
+		if (g_allow_newskin)
+		{
+			ScaleWidth = BaseWidth;
+			ScaleHeight = BaseHeight;
+			NewSkin = true;
+		}
+		else
+		{
+			Error("Invalid skin page size: (%d,%d) should be (%d,%d)",
+				BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT);
+		}
+	}
+	else if (!BaseTrueColor)
+	{
+		ScaleWidth = (float)ExtractNumber(BasePixels, ENCODED_WIDTH_X,
+			ENCODED_WIDTH_Y);
+		ScaleHeight = (float)ExtractNumber(BasePixels, ENCODED_HEIGHT_X,
+			ENCODED_HEIGHT_Y);
+	}
+	else
+	{
+		Error("Texture coordinates not supported on true color image");
+	}
+
+	if (GetST)
+	{
+		GetScriptToken (false);
+
+		sprintf (stfile, "%s/%s.%s", cdarchive, token, trifileext);
+		printf ("ST: %s ", stfile);
+
+		sprintf (stfile, "%s/%s", cddir, token);
+
+		if (do3ds)
+			Load3DSTriangleList (stfile, &st_tri, &num_st_tris, NULL, NULL);
+		else
+			LoadTriangleList (stfile, &st_tri, &num_st_tris, NULL, NULL);
+
+		if (num_st_tris != fmheader.num_tris)
+		{
+			Error ("num st tris mismatch: st %d / base %d", num_st_tris, fmheader.num_tris);
+		}
+
+		printf("   matching triangles...\n");
+		for(i=0;i<fmheader.num_tris;i++)
+		{
+			k = -1;
+			for(j=0;j<num_st_tris;j++)
+			{
+				for(x=0;x<3;x++)
+				{
+					for(y=0;y<3;y++)
+					{
+						if (x == y)
+						{
+							continue;
+						}
+						for(z=0;z<3;z++)
+						{
+							if (z == x || z == y) 
+							{
+								continue;
+							}
+
+							if (VectorFudgeCompare (ptri[i].verts[0], st_tri[j].verts[x]) &&
+							    VectorFudgeCompare (ptri[i].verts[1], st_tri[j].verts[y]) &&
+								VectorFudgeCompare (ptri[i].verts[2], st_tri[j].verts[z]))
+							{
+								if (k == -1)
+								{
+									k = j;
+									ptri[i].HasUV = st_tri[k].HasUV;
+									ptri[i].uv[0][0] = st_tri[k].uv[x][0];
+									ptri[i].uv[0][1] = st_tri[k].uv[x][1];
+									ptri[i].uv[1][0] = st_tri[k].uv[y][0];
+									ptri[i].uv[1][1] = st_tri[k].uv[y][1];
+									ptri[i].uv[2][0] = st_tri[k].uv[z][0];
+									ptri[i].uv[2][1] = st_tri[k].uv[z][1];
+									x = y = z = 999;
+								}
+								else if (k != j)
+								{
+									printf("Duplicate triangle %d found in st file: %d and %d\n",i,k,j);
+									printf("   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
+										ptri[i].verts[0][0],ptri[i].verts[0][1],ptri[i].verts[0][2],
+										ptri[i].verts[1][0],ptri[i].verts[1][1],ptri[i].verts[1][2],
+										ptri[i].verts[2][0],ptri[i].verts[2][1],ptri[i].verts[2][2]);
+									printf("   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
+										st_tri[k].verts[0][0],st_tri[k].verts[0][1],st_tri[k].verts[0][2],
+										st_tri[k].verts[1][0],st_tri[k].verts[1][1],st_tri[k].verts[1][2],
+										st_tri[k].verts[2][0],st_tri[k].verts[2][1],st_tri[k].verts[2][2]);
+									printf("   (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f) (%0.3f %0.3f %0.3f)\n",
+										st_tri[j].verts[0][0],st_tri[j].verts[0][1],st_tri[j].verts[0][2],
+										st_tri[j].verts[1][0],st_tri[j].verts[1][1],st_tri[j].verts[1][2],
+										st_tri[j].verts[2][0],st_tri[j].verts[2][1],st_tri[j].verts[2][2]);
+								}
+							}
+						}
+					}
+				}
+			}
+			if (k == -1)
+			{
+				printf("No matching triangle %d\n",i);
+			}
+		}
+		free (st_tri);
+	}
+
+//
+// get the ST values
+//
+	if (ptri && ptri[0].HasUV)
+	{
+		if (!NewSkin)
+		{
+			Error("Base has UVs with old style skin page\nMaybe you want to use -ignoreUV");
+		}
+		else
+		{
+			BuildNewST (ptri, fmheader.num_tris, false);
+		}
+	}
+	else
+	{
+		if (NewSkin)
+		{
+			Error("Base has new style skin without UVs");
+		}
+		else
+		{
+			BuildST (ptri, fmheader.num_tris, false);
+		}
+	}
+
+	TransPixels = NULL;
+	if (!BaseTrueColor)
+	{
+		FH = fopen(trans_file,"rb");
+		if (FH)
+		{
+			fclose(FH);
+			Load256Image (trans_file, &TransPixels, NULL, &TransWidth, &TransHeight);
+			if (TransWidth != fmheader.skinwidth || TransHeight != fmheader.skinheight)
+			{
+				Error ("source image %s dimensions (%d,%d) are not the same as alpha image (%d,%d)\n",file2,fmheader.skinwidth,fmheader.skinheight,TransWidth,TransHeight);
+			}
+		}
+	}
+
+//
+// run through all the base triangles, storing each unique vertex in the
+// base vertex list and setting the indirect triangles to point to the base
+// vertices
+//
+	for(l=0;l<fmheader.num_mesh_nodes;l++)
+	{
+		for (i=0 ; i < fmheader.num_tris ; i++)
+		{
+			pos = i >> 3;
+			bit = 1 << (i & 7 );
+			if (!(pmnodes[l].tris[pos] & bit))
+			{
+				continue;
+			}
+
+			for (j=0 ; j<3 ; j++)
+			{
+				// get the xyz index
+				for (k=0 ; k<fmheader.num_xyz ; k++)
+				{
+					if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
+					{
+						break;	// this vertex is already in the base vertex list
+					}
+				}
+
+				if (k == fmheader.num_xyz)
+				{ // new index
+					VectorCopy (ptri[i].verts[j], base_xyz[fmheader.num_xyz]);
+
+					if(pmnodes[l].clustered == true)
+					{
+						ReplaceClusterIndex(k, ptri[i].indicies[j], (int **)&pmnodes[l].clusters, (IntListNode_t **)&g_skelModel.vertLists, (int *)&pmnodes[l].num_verts, (int *)&g_skelModel.new_num_verts);
+					}
+
+					fmheader.num_xyz++;
+				}
+
+				pos = k >> 3;
+				bit = 1 << (k & 7);
+				pmnodes[l].verts[pos] |= bit;
+
+				triangles[i].index_xyz[j] = k;
+
+				// get the st index
+				for (k=0 ; k<fmheader.num_st ; k++)
+				{
+					if (triangle_st[i][j][0] == base_st[k].s
+					&& triangle_st[i][j][1] == base_st[k].t)
+					{
+						break;	// this vertex is already in the base vertex list
+					}
+				}
+
+				if (k == fmheader.num_st)
+				{ // new index
+					base_st[fmheader.num_st].s = triangle_st[i][j][0];
+					base_st[fmheader.num_st].t = triangle_st[i][j][1];
+					fmheader.num_st++;
+				}
+
+				triangles[i].index_st[j] = k;
+			}
+
+			if (TransPixels || BaseTrueColor)
+			{
+				translucent[i] = CheckTransRecursiveTri(triangle_st[i][0], triangle_st[i][1], triangle_st[i][2]);
+			}
+			else
+			{
+				translucent[i] = false;
+			}
+		}
+	}
+
+	if (!BaseTrueColor)
+	{
+		SetPixel = true;
+		memset(BasePixels,0,BaseWidth*BaseHeight);
+		for (i=0 ; i < fmheader.num_tris ; i++)
+		{
+			CheckTransRecursiveTri(triangle_st[i][0], triangle_st[i][1], triangle_st[i][2]);
+		}
+		SetPixel = false;
+
+		skin_pixels_used = 0;
+		for(i=0;i<fmheader.skinheight;i++)
+		{
+			for(j=0;j<fmheader.skinwidth;j++)
+			{
+				skin_pixels_used += BasePixels[(i*BaseWidth) + j];
+			}
+		}
+		total_skin_pixels = fmheader.skinheight*fmheader.skinwidth;
+	}
+	else
+	{
+		SetPixel = true;
+		memset(BasePixels,0,BaseWidth*BaseHeight*4);
+		for (i=0 ; i < fmheader.num_tris ; i++)
+		{
+			CheckTransRecursiveTri(triangle_st[i][0], triangle_st[i][1], triangle_st[i][2]);
+		}
+		SetPixel = false;
+
+		skin_pixels_used = 0;
+		for(i=0;i<fmheader.skinheight;i++)
+		{
+			for(j=0;j<fmheader.skinwidth;j++)
+			{
+				skin_pixels_used += BasePixels[((i*BaseWidth) + j)*4];
+			}
+		}
+		total_skin_pixels = fmheader.skinheight*fmheader.skinwidth;
+	}
+
+	// build triangle strips / fans
+	BuildGlCmds ();
+
+	if (TransPixels)
+	{
+		free(TransPixels);
+	}
+	free (BasePixels);
+	if (BasePalette)
+	{
+		free (BasePalette);
+	}
+	free(ptri);
+}
+
+void Cmd_FMNodeOrder(void)
+{
+	mesh_node_t	*newnodes, *pos;
+	int			i,j;
+
+	if (!pmnodes)
+	{
+		Error ("Base has not been established yet");
+	}
+
+	pos = newnodes = malloc(sizeof(mesh_node_t) * fmheader.num_mesh_nodes);
+
+	for(i=0;i<fmheader.num_mesh_nodes;i++)
+	{
+		GetScriptToken (false);
+
+		for(j=0;j<fmheader.num_mesh_nodes;j++)
+		{
+			if (strcmpi(pmnodes[j].name, token) == 0)
+			{
+				*pos = pmnodes[j];
+				pos++;
+				break;
+			}
+		}
+		if (j >= fmheader.num_mesh_nodes)
+		{
+			Error("Node '%s' not in base list!\n", token);
+		}
+	}
+
+	free(pmnodes);
+	pmnodes = newnodes;
+}
+
+//===============================================================
+
+extern char	*FindFrameFile (char *frame);
+
+
+/*
+===============
+GrabFrame
+===============
+*/
+void GrabFrame (char *frame)
+{
+	triangle_t		*ptri;
+	int				i, j;
+	fmtrivert_t		*ptrivert;
+	int				num_tris;
+	char			file1[1024];
+	fmframe_t		*fr;
+	int				index_xyz;
+	char			*framefile;
+
+	// the frame 'run1' will be looked for as either
+	// run.1 or run1.tri, so the new alias sequence save
+	// feature an be used
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+	printf ("grabbing %s  ", file1);
+
+	if (fmheader.num_frames >= MAX_FM_FRAMES)
+		Error ("fmheader.num_frames >= MAX_FM_FRAMES");
+	fr = &g_frames[fmheader.num_frames];
+	fmheader.num_frames++;
+
+	strcpy (fr->name, frame);
+
+//
+// load the frame
+//
+	if (do3ds)
+		Load3DSTriangleList (file1, &ptri, &num_tris, NULL, NULL);
+	else
+		LoadTriangleList (file1, &ptri, &num_tris, NULL, NULL);
+
+	if (num_tris != fmheader.num_tris)
+		Error ("%s: number of triangles (%d) doesn't match base frame (%d)\n", file1, num_tris, fmheader.num_tris);
+
+//
+// allocate storage for the frame's vertices
+//
+	ptrivert = fr->v;
+
+	for (i=0 ; i<fmheader.num_xyz ; i++)
+	{
+		ptrivert[i].vnorm.numnormals = 0;
+		VectorClear (ptrivert[i].vnorm.normalsum);
+	}
+	ClearBounds (fr->mins, fr->maxs);
+
+//
+// store the frame's vertices in the same order as the base. This assumes the
+// triangles and vertices in this frame are in exactly the same order as in the
+// base
+//
+	for (i=0 ; i<num_tris ; i++)
+	{
+		vec3_t	vtemp1, vtemp2, normal;
+		float	ftemp;
+
+		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+		CrossProduct (vtemp1, vtemp2, normal);
+
+		VectorNormalize (normal, normal);
+
+	// rotate the normal so the model faces down the positive x axis
+		ftemp = normal[0];
+		normal[0] = -normal[1];
+		normal[1] = ftemp;
+
+		for (j=0 ; j<3 ; j++)
+		{
+			index_xyz = triangles[i].index_xyz[j];
+
+		// rotate the vertices so the model faces down the positive x axis
+		// also adjust the vertices to the desired origin
+			ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
+										adjust[0];
+			ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
+										adjust[1];
+			ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
+										adjust[2];
+
+			AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
+
+			VectorAdd (ptrivert[index_xyz].vnorm.normalsum, normal, ptrivert[index_xyz].vnorm.normalsum);
+			ptrivert[index_xyz].vnorm.numnormals++;
+		}
+	}
+
+//
+// calculate the vertex normals, match them to the template list, and store the
+// index of the best match
+//
+	for (i=0 ; i<fmheader.num_xyz ; i++)
+	{
+		int		j;
+		vec3_t	v;
+		float	maxdot;
+		int		maxdotindex;
+		int		c;
+
+		c = ptrivert[i].vnorm.numnormals;
+		if (!c)
+			Error ("Vertex with no triangles attached");
+
+		VectorScale (ptrivert[i].vnorm.normalsum, 1.0/c, v);
+		VectorNormalize (v, v);
+
+		maxdot = -999999.0;
+		maxdotindex = -1;
+
+		for (j=0 ; j<NUMVERTEXNORMALS ; j++)
+		{
+			float	dot;
+
+			dot = DotProduct (v, avertexnormals[j]);
+			if (dot > maxdot)
+			{
+				maxdot = dot;
+				maxdotindex = j;
+			}
+		}
+
+		ptrivert[i].lightnormalindex = maxdotindex;
+	}
+
+	free (ptri);
+}
+
+/*
+===============
+Cmd_Frame	
+===============
+*/
+void Cmd_FMFrame (void)
+{
+	while (ScriptTokenAvailable())
+	{
+		GetScriptToken (false);
+		if (g_skipmodel)
+			continue;
+		if (g_release || g_archive)
+		{
+			fmheader.num_frames = 1;	// don't skip the writeout
+			continue;
+		}
+
+		H_printf("#define FRAME_%-16s\t%i\n", token, fmheader.num_frames);
+
+		if((g_skelModel.type != SKEL_NULL) || (g_skelModel.references != REF_NULL))
+		{
+			GrabModelTransform(token);
+		}
+
+		GrabFrame (token);
+
+		if(g_skelModel.type != SKEL_NULL)
+		{
+			GrabSkeletalFrame(token);
+		}
+
+		if(g_skelModel.references != REF_NULL)
+		{
+			GrabReferencedFrame(token);
+		}
+
+		// need to add the up and dir points to the frame bounds here
+		// using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
+		// then remove fudge in determining scale on frame write out
+	}
+}
+
+/*
+===============
+Cmd_Skin
+
+Skins aren't actually stored in the file, only a reference
+is saved out to the header file.
+===============
+*/
+void Cmd_FMSkin (void)
+{
+	byte		*palette;
+	byte		*pixels;
+	int			width, height;
+	byte		*cropped;
+	int			y;
+	char		name[1024], savename[1024], transname[1024], extension[256];
+	miptex32_t	*qtex32;
+	int			size;
+	FILE		*FH;
+	qboolean	TrueColor;
+
+	GetScriptToken (false);
+
+	if (fmheader.num_skins == MAX_FM_SKINS)
+		Error ("fmheader.num_skins == MAX_FM_SKINS");
+
+	if (g_skipmodel)
+		return;
+
+	sprintf (name, "%s/%s", cdarchive, token);
+	strcpy (name, ExpandPathAndArchive( name ) );
+//	sprintf (name, "%s/%s.lbm", cddir, token);
+
+	if (ScriptTokenAvailable())
+	{
+		GetScriptToken (false);
+		sprintf (g_skins[fmheader.num_skins], "!%s", token);
+		sprintf (savename, "%s!%s", g_outputDir, token);
+		sprintf (transname, "%s!%s_a.pcx", gamedir, token);
+	}
+	else
+	{
+		sprintf (g_skins[fmheader.num_skins], "%s/!%s", cdpartial, token);
+		sprintf (savename, "%s/!%s", g_outputDir, token);
+		sprintf (transname, "%s/!%s_a.pcx", cddir, token);
+	}
+
+	fmheader.num_skins++;
+
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	// load the image
+	printf ("loading %s\n", name);
+	ExtractFileExtension (name, extension);
+	if (extension[0] == 0)
+	{
+		strcat(name, ".pcx");
+	}
+
+
+	TrueColor = LoadAnyImage (name, &pixels, &palette, &width, &height);
+//	RemapZero (pixels, palette, width, height);
+
+	// crop it to the proper size
+
+	if (!TrueColor)
+	{
+		cropped = (byte *) SafeMalloc (fmheader.skinwidth*fmheader.skinheight, "Cmd_FMSkin");
+		for (y=0 ; y<fmheader.skinheight ; y++)
+		{
+			memcpy (cropped+y*fmheader.skinwidth,
+				pixels+y*width, fmheader.skinwidth);
+		}
+
+		TransPixels = NULL;
+		FH = fopen(transname,"rb");
+		if (FH)
+		{
+			fclose(FH);
+
+			strcat(g_skins[fmheader.num_skins-1],".pcx");
+			strcat(savename,".pcx");
+
+			// save off the new image
+			printf ("saving %s\n", savename);
+			CreatePath (savename);
+			WritePCXfile (savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette);
+		}
+		else
+		{
+	#if 1
+		miptex_t	*qtex;
+			qtex = CreateMip(cropped, fmheader.skinwidth, fmheader.skinheight, palette, &size, true);
+
+			strcat(g_skins[fmheader.num_skins-1],".m8");
+			strcat(savename,".m8");
+
+			printf ("saving %s\n", savename);
+			CreatePath (savename);
+			SaveFile (savename, (byte *)qtex, size);
+			free(qtex);
+	#else
+			strcat(g_skins[fmheader.num_skins-1],".pcx");
+			strcat(savename,".pcx");
+
+			// save off the new image
+			printf ("saving %s\n", savename);
+			CreatePath (savename);
+			WritePCXfile (savename, cropped, fmheader.skinwidth, fmheader.skinheight, palette);
+	#endif
+		}
+	}
+	else
+	{
+		cropped = (byte *) SafeMalloc (fmheader.skinwidth*fmheader.skinheight*4, "Cmd_FMSkin");
+		for (y=0 ; y<fmheader.skinheight ; y++)
+		{
+			memcpy (cropped+((y*fmheader.skinwidth)*4), pixels+(y*width*4), fmheader.skinwidth*4);
+		}
+
+		qtex32 = CreateMip32((unsigned *)cropped, fmheader.skinwidth, fmheader.skinheight, &size, true);
+
+	    StripExtension(g_skins[fmheader.num_skins-1]);
+		strcat(g_skins[fmheader.num_skins-1],".m32");
+	    StripExtension(savename);
+		strcat(savename,".m32");
+
+		printf ("saving %s\n", savename);
+		CreatePath (savename);
+		SaveFile (savename, (byte *)qtex32, size);
+	}
+
+	free (pixels);
+	if (palette)
+	{
+		free (palette);
+	}
+	free (cropped);
+}
+
+
+/*
+===============
+Cmd_Cd
+===============
+*/
+void Cmd_FMCd (void)
+{
+	char temp[256];
+
+	FinishModel ();
+	ClearModel ();
+
+	GetScriptToken (false);
+
+	// this is a silly mess...
+	sprintf(cdpartial, "models/%s", token); 
+	sprintf(cdarchive, "%smodels/%s", gamedir+strlen(qdir), token); 
+	sprintf(cddir, "%s%s", gamedir, cdpartial);
+
+	// Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
+	sprintf(temp, "%s%s", g_outputDir, cdpartial);
+	strcpy(g_outputDir, temp);
+
+	// if -only was specified and this cd doesn't match,
+	// skip the model (you only need to match leading chars,
+	// so you could regrab all monsters with -only monsters)
+	if (!g_only[0])
+		return;
+	if (strncmp(token, g_only, strlen(g_only)))
+	{
+		g_skipmodel = true;
+		printf ("skipping %s\n", cdpartial);
+	}
+}
+
+
+/*
+
+//=======================
+//		NEW GEN
+//=======================
+
+void NewGen (char *ModelFile, char *OutputName, int width, int height)
+{
+	trigroup_t  *triangles;
+	triangle_t	*ptri;
+	triangle_t	*grouptris;
+	mesh_node_t	*pmnodes;
+
+	vec3_t		*vertices;
+	vec3_t		*uvs;
+	vec3_t		aveNorm, crossvect;
+	vec3_t		diffvect1, diffvect2;
+	vec3_t		v0, v1, v2;
+	vec3_t		n, u, v;
+	vec3_t		base, zaxis, yaxis;
+	vec3_t		uvwMin, uvwMax;
+	vec3_t		groupMin, groupMax;
+	vec3_t		uvw;
+	
+	float		*uFinal, *vFinal;
+	unsigned char	*newpic;
+
+	int			finalstart = 0, finalcount = 0;
+	int			xbase = 0, xwidth = 0, ywidth = 0;
+	int			*todo, *done, finished;
+	int			i, j, k, l; //counters
+	int			groupnum, numtris, numverts, num;
+	int			count;
+	FILE		*grpfile;
+	long		datasize;
+
+	for ( i = 0; i<3; i++)
+	{
+		aveNorm[i] = 0;
+		uvwMin[i] = 1e30f;
+		uvwMax[i] = -1e30f;
+	}
+
+	pmnodes = NULL;
+	ptri = NULL;
+	triangles = NULL;
+	
+	zaxis[0] = 0;
+	zaxis[1] = 0;
+	zaxis[2] = 1;
+
+	yaxis[0] = 0;
+	yaxis[1] = 1;
+	yaxis[2] = 0;
+
+	LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
+
+	todo = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
+	done = (int*)SafeMalloc(fmheader.num_tris*sizeof(int), "NewGen");
+	triangles = (trigroup_t*)SafeMalloc(fmheader.num_tris*sizeof(trigroup_t), "NewGen");
+	
+	for ( i=0; i < fmheader.num_tris; i++)
+	{
+		todo[i] = false;
+		done[i] = false;
+		triangles[i].triangle = ptri[i];
+		triangles[i].group = 0;
+	}
+
+	groupnum = 0;
+
+//  transitive closure algorithm follows
+//  put all triangles who transitively share vertices into separate groups
+
+	while (1)
+	{
+		for ( i = 0; i < fmheader.num_tris; i++)
+		{
+			if (!done[i])
+			{
+				break;
+			}
+		}
+		if ( i == fmheader.num_tris)
+		{
+			break;
+		}
+		finished = false;
+		todo[i] = true;
+		while (!finished)
+		{
+			finished = true;
+			for ( i = 0; i < fmheader.num_tris; i++)
+			{
+				if (todo[i])
+				{
+					done[i] = true;
+					triangles[i].group = groupnum;
+					todo[i] = false;
+					for ( j = 0; j < fmheader.num_tris; j++)
+					{
+						if ((!done[j]) && (ShareVertex(triangles[i],triangles[j])))
+						{
+							todo[j] = true;
+							finished = false;
+						}
+					}
+				}
+			}
+		}
+		groupnum++;
+	}
+		uFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
+		vFinal = (float*)SafeMalloc(3*fmheader.num_tris*sizeof(float), "NewGen");
+
+	grpfile = fopen("grpdebug.txt","w");
+
+	
+	for (i = 0; i < groupnum; i++)
+	{
+
+		fprintf(grpfile,"Group Number: %d\n", i);
+		
+		numtris = GetNumTris(triangles, i); // number of triangles in group i
+		numverts = numtris * 3;
+
+		fprintf(grpfile,"%d triangles.\n", numtris);
+
+		vertices = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
+		uvs = (vec3_t*)SafeMalloc(numverts*sizeof(vec3_t), "NewGen");
+		grouptris = (triangle_t*)SafeMalloc(numtris*sizeof(triangle_t), "NewGen");
+		
+		for (count = 0; count < fmheader.num_tris; count++)
+		{
+			if (triangles[count].group == i)
+			{
+				fprintf(grpfile,"Triangle %d\n", count);
+			}
+		}
+		fprintf(grpfile,"\n");
+
+		
+		
+		
+		GetOneGroup(triangles, i, grouptris);		
+		
+		num = 0;
+		for (j = 0; j < numtris; j++)
+		{
+			VectorCopy(grouptris[j].verts[0], v0);
+			VectorCopy(grouptris[j].verts[1], v1);
+			VectorCopy(grouptris[j].verts[2], v2);
+			VectorSubtract(v1, v0, diffvect1);
+			VectorSubtract(v2, v1, diffvect2);
+			CrossProduct( diffvect1, diffvect2, crossvect);
+			VectorAdd(aveNorm, crossvect, aveNorm);	
+			VectorCopy(v0,vertices[num]);
+			num++;					//  FIXME
+			VectorCopy(v1,vertices[num]);
+			num++;					//  add routine to add only verts that
+			VectorCopy(v2,vertices[num]);
+			num++;					// have not already been added
+		}
+
+		assert (num >= 3);
+// figure out the best plane projections
+		DOsvdPlane ((float*)vertices, num, (float *)&n, (float *)&base);
+		
+		if (DotProduct(aveNorm,n) < 0.0f)
+		{
+			VectorScale(n, -1.0f, n);
+		}
+		VectorNormalize(n,n);
+		if (fabs(n[2]) < .57)
+		{
+			CrossProduct( zaxis, n, crossvect);
+			VectorCopy(crossvect, u);
+		}
+		else
+		{
+			CrossProduct( yaxis, n, crossvect);
+			VectorCopy(crossvect, u);
+		}
+		VectorNormalize(u,u);
+		CrossProduct( n, u, crossvect);
+		VectorCopy(crossvect, v);
+		VectorNormalize(v,v);
+
+		num = 0;
+
+		for ( j = 0; j < 3; j++)
+		{
+			groupMin[j] = 1e30f;
+			groupMax[j] = -1e30f;
+		}
+		
+		for ( j = 0; j < numtris; j++)
+		{
+			for ( k = 0; k < 3; k++)
+			{
+				VectorCopy(grouptris[j].verts[k],v0);
+				VectorSubtract(v0, base, v0);
+				uvw[0] = DotProduct(v0, u);
+				uvw[1] = DotProduct(v0, v);
+				uvw[2] = DotProduct(v0, n);
+				VectorCopy(uvw,uvs[num]);
+				num++;
+				for ( l = 0; l < 3; l++)
+				{
+					if (uvw[l] < groupMin[l])
+					{
+						groupMin[l] = uvw[l];
+					}
+					if (uvw[l] > groupMax[l])
+					{
+						groupMax[l] = uvw[l];
+					}
+				}
+			}
+		}
+		
+		xwidth = ceil(0 - groupMin[0]) + 2; // move right of origin and avoid overlap
+		ywidth = ceil(0 - groupMin[1]) + 2; // move "above" origin
+		
+		for ( j=0; j < numverts; j++)
+		{
+			uFinal[finalcount] = uvs[j][0] + xwidth + xbase;			
+			vFinal[finalcount] = uvs[j][1] + ywidth;
+			if (uFinal[finalcount] < uvwMin[0])
+			{
+				uvwMin[0] = uFinal[finalcount];
+			}
+			if (uFinal[finalcount] > uvwMax[0])
+			{
+				uvwMax[0] = uFinal[finalcount];
+			}
+			if (vFinal[finalcount] < uvwMin[1])
+			{
+				uvwMin[1] = vFinal[finalcount];
+			}
+			if (vFinal[finalcount] > uvwMax[1])
+			{
+				uvwMax[1] = vFinal[finalcount];
+			}
+			finalcount++;
+		}
+
+		fprintf(grpfile,"svdPlaned Group min: ( %f , %f )\n",groupMin[0] + xwidth + xbase, groupMin[1] + ywidth);
+		fprintf(grpfile,"svdPlaned Group max: ( %f , %f )\n",groupMax[0] + xwidth + xbase, groupMax[1] + ywidth);
+		
+		finalcount = finalstart;
+
+		for ( count = 0; count < numverts; count++)
+		{
+			fprintf(grpfile,"Vertex %d: ( %f , %f , %f )\n",count,vertices[count][0],vertices[count][1],vertices[count][2]);
+			fprintf(grpfile,"svdPlaned: ( %f , %f )\n",uFinal[finalcount],vFinal[finalcount++]);
+		}
+		
+		finalstart = finalcount;
+
+		fprintf(grpfile,"\n");
+		
+		free(vertices);
+		free(uvs);
+		free(grouptris);
+
+		xbase += ceil(groupMax[0] - groupMin[0]) + 2; 		
+
+	}	
+
+	fprintf(grpfile,"Global Min ( %f , %f )\n",uvwMin[0],uvwMin[1]);
+	fprintf(grpfile,"Global Max ( %f , %f )\n",uvwMax[0],uvwMax[1]);
+
+
+	ScaleTris(uvwMin, uvwMax, width, height, uFinal, vFinal, finalcount);
+
+	for (k = 0; k < finalcount; k++)
+	{
+		fprintf(grpfile, "scaled vertex %d: ( %f , %f )\n",k,uFinal[k],vFinal[k]);
+	}
+	
+	//  i've got the array of vertices in uFinal and vFinal.  Now I need to write them and draw lines
+
+	datasize = width * height*sizeof(unsigned char);
+	newpic = (unsigned char*)SafeMalloc(datasize, "NewGen");
+	memset(newpic,0,datasize);
+	memset(pic_palette,0,sizeof(pic_palette));
+	pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
+
+	k = 0;
+	while (k < finalcount)
+	{
+		NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
+		k++;
+		NewDrawLine(uFinal[k], vFinal[k], uFinal[k+1], vFinal[k+1], newpic, width, height);
+		k++;
+		NewDrawLine(uFinal[k], vFinal[k], uFinal[k-2], vFinal[k-2], newpic, width, height);
+		k++;
+		fprintf(grpfile, "output tri with verts %d, %d, %d", k-2, k-1, k);
+	}
+
+	WritePCXfile (OutputName, newpic, width, height, pic_palette);
+
+	fclose(grpfile);
+
+	free(todo);
+	free(done);
+	free(triangles);
+	free(newpic);	
+	return;
+}
+void NewDrawLine(int x1, int y1, int x2, int y2, unsigned char* picture, int width, int height)
+{
+	long dx, dy;
+	long adx, ady;
+	long count;
+	float xfrac, yfrac, xstep, ystep;
+	unsigned long sx, sy;
+	float u, v;
+
+	dx = x2 - x1;
+	dy = y2 - y1;
+	adx = abs(dx);
+	ady = abs(dy);
+
+	count = adx > ady ? adx : ady;
+	count++;
+
+	if(count > 300)
+	{
+		printf("Bad count\n");
+		return; // don't ever hang up on bad data
+	}
+		
+	xfrac = x1;
+	yfrac = y1;
+	
+	xstep = (float)dx/count;
+	ystep = (float)dy/count;
+
+	switch(LineType)
+	{
+		case LINE_NORMAL:
+			do
+			{
+				if(xfrac < width && yfrac < height)
+				{
+					picture[(long)yfrac*width+(long)xfrac] = LineColor;
+				}
+				xfrac += xstep;
+				yfrac += ystep;
+				count--;
+			} while (count > 0);
+			break;
+		case LINE_FAT:
+			do
+			{
+				for (u=-0.1 ; u<=0.9 ; u+=0.999)
+				{
+					for (v=-0.1 ; v<=0.9 ; v+=0.999)
+					{
+						sx = xfrac+u;
+						sy = yfrac+v;
+						if(sx < width && sy < height)
+						{
+							picture[sy*width+sx] = LineColor;
+						}
+					}
+				}
+				xfrac += xstep;
+				yfrac += ystep;
+				count--;
+			} while (count > 0);
+			break;
+		case LINE_DOTTED:
+			do
+			{
+				if(count&1 && xfrac < width &&
+					yfrac < height)
+				{
+					picture[(long)yfrac*width+(long)xfrac] = LineColor;
+				}
+				xfrac += xstep;
+				yfrac += ystep;
+				count--;
+			} while (count > 0);
+			break;
+		default:
+			Error("Unknown <linetype> %d.\n", LineType);
+	}
+}
+*/
+void ScaleTris( vec3_t min, vec3_t max, int Width, int Height, float* u, float* v, int verts)
+{
+
+	int		i;
+	float	hscale, vscale;
+	float	scale;
+
+	hscale = max[0];
+	vscale = max[1];
+
+	hscale = (Width-2) / max[0];
+	vscale = (Height-2) / max[1];
+
+	scale = hscale;
+	if (scale > vscale)
+	{
+		scale = vscale;
+	}
+	for ( i = 0; i<verts; i++)
+	{
+		u[i] *= scale;
+		v[i] *= scale;
+	}
+	return;
+}
+
+
+void GetOneGroup(trigroup_t *tris, int grp, triangle_t* triangles)
+{
+	int	i;
+	int j;
+
+	j = 0;
+	for (i = 0; i < fmheader.num_tris; i++)
+	{
+		if (tris[i].group == grp)
+		{
+			triangles[j++] = tris[i].triangle;
+		}
+	}
+	return;
+}
+
+
+int GetNumTris( trigroup_t *tris, int grp)
+{
+	int i;
+	int verts;
+
+	verts = 0;
+	for (i = 0; i < fmheader.num_tris; i++)
+	{
+		if (tris[i].group == grp)
+		{
+			verts++;
+		}
+	}
+	return verts;
+}
+
+
+int ShareVertex( trigroup_t trione, trigroup_t tritwo)
+{
+	int	i;
+	int	j;
+
+	i = 1;
+	j = 1;
+	for ( i = 0; i < 3; i++)
+	{
+		for ( j = 0; j < 3; j++)
+		{
+			if (DistBetween(trione.triangle.verts[i],tritwo.triangle.verts[j]) < TRIVERT_DIST)
+			{
+				return true; 
+			}
+		}
+	}
+	return false;
+}
+
+
+float DistBetween(vec3_t point1, vec3_t point2)
+{
+	float	dist;
+
+	dist = (point1[0] - point2[0]);
+	dist *= dist;
+	dist += (point1[1] - point2[1])*(point1[1]-point2[1]);
+	dist += (point1[2] - point2[2])*(point1[2]-point2[2]);
+	dist = sqrt(dist);
+	return dist;
+}
+
+
+void GenSkin(char *ModelFile, char *OutputName, int Width, int Height)
+{
+	triangle_t	*ptri;
+	mesh_node_t *pmnodes;
+	int			i;
+
+	pmnodes = NULL;
+	ptri = NULL;
+
+	LoadTriangleList (ModelFile, &ptri, &fmheader.num_tris, &pmnodes, &fmheader.num_mesh_nodes);
+	if (g_ignoreTriUV)
+	{
+		for (i=0;i<fmheader.num_tris;i++)
+		{
+			ptri[i].HasUV=0;
+		}
+	}
+
+	memset(pic,0,sizeof(pic));
+	memset(pic_palette,0,sizeof(pic_palette));
+	pic_palette[767] = pic_palette[766] = pic_palette[765] = 255;
+
+	ScaleWidth = Width;
+	ScaleHeight = Height;
+
+	BuildST (ptri, fmheader.num_tris, true);
+
+	WritePCXfile (OutputName, pic, SKINPAGE_WIDTH, SKINPAGE_HEIGHT, pic_palette);
+
+	printf("Gen Skin Stats:\n");
+	printf("   Input Base: %s\n",ModelFile);
+	printf("   Input Dimensions: %d,%d\n",Width,Height);
+	printf("\n");
+	printf("   Output File: %s\n",OutputName);
+	printf("   Output Dimensions: %d,%d\n",ScaleWidth,ScaleHeight);
+
+	if (fmheader.num_mesh_nodes)
+	{
+		printf("\nNodes:\n");
+		for(i=0;i<fmheader.num_mesh_nodes;i++)
+		{
+			printf("   %s\n",pmnodes[i].name);
+		}
+	}
+
+	free(ptri);
+	free(pmnodes);
+}
+
+
+void Cmd_FMBeginGroup (void)
+{
+	GetScriptToken (false);
+
+	g_no_opimizations = false;
+
+	groups[num_groups].start_frame = fmheader.num_frames;
+	groups[num_groups].num_frames = 0;
+
+	groups[num_groups].degrees = atol(token);
+	if (groups[num_groups].degrees < 1 || groups[num_groups].degrees > 32)
+	{
+		Error ("Degrees of freedom out of range: %d",groups[num_groups].degrees);
+	}
+}
+
+void Cmd_FMEndGroup (void)
+{
+	groups[num_groups].num_frames = fmheader.num_frames - groups[num_groups].start_frame;
+
+	if(num_groups < MAX_GROUPS - 1)
+	{
+		num_groups++;
+	}
+	else
+	{
+		Error("Number of compression groups exceded: %i\n", MAX_GROUPS);
+	}
+}
+
diff --git a/tools/quake2/qdata_heretic2/images.c b/tools/quake2/qdata_heretic2/images.c
index bdc8ba50..c2dc29fb 100644
--- a/tools/quake2/qdata_heretic2/images.c
+++ b/tools/quake2/qdata_heretic2/images.c
@@ -1,1397 +1,1397 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qdata.h"
-
-#ifdef _WIN32
- #include <windows.h>
-#endif
-
-#include <GL/gl.h>
-
-#if 1
-	extern char		*g_outputDir;
-#endif // _QDATA
-
-char		mip_prefix[1024];		// directory to dump the textures in
-
-qboolean	colormap_issued;
-byte		colormap_palette[768];
-
-unsigned total_x = 0;
-unsigned total_y = 0;
-unsigned total_textures = 0;
-
-#define MAX_IMAGE_SIZE 512
-
-#if	0
-/*
-==============
-RemapZero
-
-Replaces all 0 bytes in an image with the closest palette entry.
-This is because NT won't let us change index 0, so any palette
-animation leaves those pixels untouched.
-==============
-*/
-void RemapZero (byte *pixels, byte *palette, int width, int height)
-{
-	int		i, c;
-	int		alt_zero;
-	int		value, best;
-
-	alt_zero = 0;
-	best = 9999999;
-	for (i=1 ; i<255 ; i++)
-	{
-		value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
-		if (value < best)
-		{
-			best = value;
-			alt_zero = i;
-		}
-	}
-
-	c = width*height;
-	for (i=0 ; i<c ; i++)
-		if (pixels[i] == 0)
-			pixels[i] = alt_zero;
-}
-
-#endif
-
-
-// ********************************************************************
-// **  Mip Map Pre-Processing Routines
-// ********************************************************************
-
-#define intensity_value 1
-
-static unsigned image_pal[256];
-
-#define MAX_LAST 25
-
-long palette_r[256], palette_g[256], palette_b[256];
-long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
-
-long cached;
-
-void PrepareConvert(unsigned *palette)
-{
-	int i;
-
-	for(i=0;i<256;i++)
-	{
-		palette_r[i] = (palette[i] & 0x00ff0000) >> 16;
-		palette_g[i] = (palette[i] & 0x0000ff00) >> 8;
-		palette_b[i] = (palette[i] & 0x000000ff);
-	}
-
-	for(i=0;i<MAX_LAST;i++)
-		last_r[i] = -1;
-
-	last_place = -1;
-}
-
-int ConvertTrueColorToPal(unsigned r, unsigned g, unsigned b)
-{
-	int i;
-	long min_dist;
-	int min_index;
-	long dist;
-	long dr, dg, db, biggest_delta;
-
-	for(i=0;i<MAX_LAST;i++)
-		if (r == last_r[i] && g == last_g[i] && b == last_b[i])
-		{
-			cached++;
-			return last_i[i];
-		}
-
-	min_dist = 256 * 256 + 256 * 256 + 256 * 256;
-	biggest_delta = 256*256;
-	min_index = 0;
-
-	for (i=0;i<256;i++)
-	{
-		dr = abs(palette_r[i] - r);
-		if (dr > biggest_delta)
-			continue;
-		dg = abs(palette_g[i] - g);
-		if (dg > biggest_delta)
-			continue;
-		db = abs(palette_b[i] - b);
-		if (db > biggest_delta)
-			continue;
-
-		dist = dr * dr + dg * dg + db * db;
-		if (dist < min_dist)
-		{
-			min_dist = dist;
-			min_index = i;
-			if (min_dist == 0) break;
-
-			dist = dr;
-			if (dg > dist) dist = dg;
-			if (db > dist) dist = db;
-			if (dist < biggest_delta)
-				biggest_delta = dist;
-		}
-	}
-
-	last_place++;
-	if (last_place >= MAX_LAST)
-		last_place = 0;
-
-	last_r[last_place] = r;
-	last_g[last_place] = g;
-	last_b[last_place] = b;
-	last_i[last_place] = min_index;
-
-	return min_index;
-}
-
-
-void GL_ResampleTexture8P (byte *in, int inwidth, int inheight, byte *out,  
-						   int outwidth, int outheight, palette_t *palette)
-{
-	int		i, j;
-	byte	*inrow, *inrow2;
-	unsigned	frac, fracstep;
-	unsigned	p1[1024], p2[1024], *p1p, *p2p;
-	palette_t	*c1,*c2,*c3,*c4;
-	unsigned	r,g,b;
-	
-	fracstep = inwidth*0x10000/outwidth;
-
-	frac = fracstep>>2;
-	for (i=0 ; i<outwidth ; i++)
-	{
-		p1[i] = frac>>16;
-		frac += fracstep;
-	}
-	frac = 3*(fracstep>>2);
-	for (i=0 ; i<outwidth ; i++)
-	{
-		p2[i] = frac>>16;
-		frac += fracstep;
-	}
-
-	cached = 0;
-	
-	for (i=0 ; i<outheight ; i++)//, out += outwidth)
-	{
-		inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
-		inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
-
-		p1p = p1;
-		p2p = p2;
-		for (j=0 ; j<outwidth ; j++)
-		{
-			c1 = &palette[*((byte *)inrow + (*p1p))];
-			c2 = &palette[*((byte *)inrow + (*p2p))];
-			c3 = &palette[*((byte *)inrow2 + (*p1p++))];
-			c4 = &palette[*((byte *)inrow2 + (*p2p++))];
-
-			r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r)>>2;
-			g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g)>>2;
-			b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b)>>2;
-
-			*out++ = ConvertTrueColorToPal(r,g,b);
-		}
-	}
-}
-
-void GL_MipMap8P(byte *out, byte *in, int width, int height, palette_t *palette)
-{
-	int			i, j;
-	palette_t	*c1,*c2,*c3,*c4;
-	unsigned	r,g,b;
-
-	cached = 0;
-	memset(out, 0, 256 * 256);
-	width <<= 1;
-	height <<= 1;
-
-	for (i = 0; i < height; i += 2, in += width)
-	{
-		for (j = 0; j < width; j += 2)
-		{
-			c1 = &palette[in[0]];
-			c3 = &palette[in[width]];
-			in++;
-			c2 = &palette[in[0]];
-			c4 = &palette[in[width]];
-			in++;
-
-			r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r) >> 2;
-			g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g) >> 2;
-			b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b) >> 2;
-
-			*out++ = ConvertTrueColorToPal(r, g, b);
-		}
-	}
-}
-
-
-miptex_t *CreateMip(byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip)
-{
-	int			scaled_width, scaled_height;
-	int			i,j,r,g,b;
-	byte		intensitytable[256];
-	byte		scaled[256*256];
-	byte		out[256*256];
-	int			miplevel;
-	miptex_t	*mp;
-	byte		*pos;
-	int			size;
-
-	for (i=0 ; i<256 ; i++)
-	{
-		j = i * intensity_value;
-		if (j > 255)
-			j = 255;
-		intensitytable[i] = j;
-	}
-
-	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
-		;
-	if (1 && scaled_width > width && 1)
-		scaled_width >>= 1;
-	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
-		;
-	if (1 && scaled_height > height && 1)
-		scaled_height >>= 1;
-
-	// don't ever bother with >256 textures
-	if (scaled_width > 256)
-		scaled_width = 256;
-	if (scaled_height > 256)
-		scaled_height = 256;
-
-	if (scaled_width < 1)
-		scaled_width = 1;
-	if (scaled_height < 1)
-		scaled_height = 1;
-
-	size = sizeof(*mp) + (scaled_width*scaled_height*3);
-	mp = (miptex_t *)SafeMalloc(size, "CreateMip");
-	memset(mp,0,size);
-
-	mp->version = MIP_VERSION;
-
-	for(i=j=0;i<256;i++,j+=3)
-	{
-		mp->palette[i].r = r = intensitytable[palette[j]];
-		mp->palette[i].g = g = intensitytable[palette[j+1]];
-		mp->palette[i].b = b = intensitytable[palette[j+2]];
-		image_pal[i] = 0xff000000 | (r<<16) | (g<<8) | (b);
-	}
-
-	PrepareConvert(image_pal);
-
-	if (scaled_width == width && scaled_height == height)
-	{
-		memcpy (scaled, data, width*height);
-	}
-	else
-		GL_ResampleTexture8P (data, width, height, scaled, scaled_width, scaled_height, mp->palette);
-
-	pos = (byte *)(mp + 1);
-	miplevel = 0;
-
-	while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))
-	{
-		if (scaled_width < 1)
-			scaled_width = 1;
-		if (scaled_height < 1)
-			scaled_height = 1;
-
-		if(miplevel > 0)
-			GL_MipMap8P(out, (byte *)scaled, scaled_width, scaled_height, mp->palette);
-		else
-			memcpy(out, scaled, 256 * 256);
-
-		mp->width[miplevel] = scaled_width;
-		mp->height[miplevel] = scaled_height;
-		mp->offsets[miplevel] = pos - ((byte *)(mp));
-		memcpy(pos, out, scaled_width * scaled_height);
-		memcpy(scaled, out, 256 * 256);
-		pos += scaled_width * scaled_height;
-
-		scaled_width >>= 1;
-		scaled_height >>= 1;
-
-		miplevel++;
-	}
-
-	*FinalSize = pos - ((byte *)(mp));
-
-	return mp;
-}
-
-
-void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
-{
-	int		i, j;
-	unsigned	*inrow, *inrow2;
-	unsigned	frac, fracstep;
-	unsigned	p1[1024], p2[1024];
-	byte		*pix1, *pix2, *pix3, *pix4;
-
-	fracstep = inwidth*0x10000/outwidth;
-
-	frac = fracstep>>2;
-	for (i=0 ; i<outwidth ; i++)
-	{
-		p1[i] = 4*(frac>>16);
-		frac += fracstep;
-	}
-	frac = 3*(fracstep>>2);
-	for (i=0 ; i<outwidth ; i++)
-	{
-		p2[i] = 4*(frac>>16);
-		frac += fracstep;
-	}
-
-	for (i=0 ; i<outheight ; i++, out += outwidth)
-	{
-		inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
-		inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
-		frac = fracstep >> 1;
-		for (j=0 ; j<outwidth ; j++)
-		{
-			pix1 = (byte *)inrow + p1[j];
-			pix2 = (byte *)inrow + p2[j];
-			pix3 = (byte *)inrow2 + p1[j];
-			pix4 = (byte *)inrow2 + p2[j];
-			((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
-			((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
-			((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
-			((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
-		}
-	}
-}
-
-void GL_MipMap (byte *out, byte *in, int width, int height)
-{
-	int		i, j;
-
-	width <<=3;
-	height <<= 1;
-	for (i=0 ; i<height ; i++, in+=width)
-	{
-		for (j=0 ; j<width ; j+=8, out+=4, in+=8)
-		{
-			out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
-			out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
-			out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
-			out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
-		}
-	}
-}
-
-miptex32_t *CreateMip32(unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip)
-{
-	int				scaled_width, scaled_height;
-	unsigned		scaled[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
-	unsigned		out[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
-	int				miplevel;
-	miptex32_t		*mp;
-	byte			*pos;
-	int				size;
-	paletteRGBA_t	*test;
-
-	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
-		;
-	if (1 && scaled_width > width && 1)
-		scaled_width >>= 1;
-	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
-		;
-	if (1 && scaled_height > height && 1)
-		scaled_height >>= 1;
-
-	// don't ever bother with >256 textures
-	if (scaled_width > MAX_IMAGE_SIZE)
-		scaled_width = MAX_IMAGE_SIZE;
-	if (scaled_height > MAX_IMAGE_SIZE)
-		scaled_height = MAX_IMAGE_SIZE;
-
-	if (scaled_width < 1)
-		scaled_width = 1;
-	if (scaled_height < 1)
-		scaled_height = 1;
-
-	size = sizeof(*mp) + (scaled_width*scaled_height*3*4);
-	mp = (miptex32_t *)SafeMalloc(size, "CreateMip");
-	memset(mp,0,size);
-
-	mp->version = MIP32_VERSION;
-
-	size = width*height;
-	test = (paletteRGBA_t *)data;
-	while(size)
-	{
-		if (test->a != 255)
-		{
-			mp->flags |= LittleLong(SURF_ALPHA_TEXTURE);
-			break;
-		}
-
-		size--;
-		test++;
-	}
-
-	if (scaled_width == width && scaled_height == height)
-	{
-		memcpy (scaled, data, width*height*4);
-	}
-	else
-		GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
-
-	pos = (byte *)(mp + 1);
-	miplevel = 0;
-
-	while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))
-	{
-		if (scaled_width < 1)
-			scaled_width = 1;
-		if (scaled_height < 1)
-			scaled_height = 1;
-
-		if (miplevel > 0)
-		{
-			GL_MipMap((byte *)out, (byte *)scaled, scaled_width, scaled_height);
-		}
-		else
-		{
-			memcpy(out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);
-		}
-
-		mp->width[miplevel] = scaled_width;
-		mp->height[miplevel] = scaled_height;
-		mp->offsets[miplevel] = pos - ((byte *)(mp));
-		memcpy(pos, out, scaled_width * scaled_height * 4);
-		memcpy(scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);
-		pos += scaled_width * scaled_height * 4;
-
-		scaled_width >>= 1;
-		scaled_height >>= 1;
-
-		miplevel++;
-	}
-
-	*FinalSize = pos - ((byte *)(mp));
-
-	return mp;
-}
-
-/*
-==============
-Cmd_Grab
-
-$grab filename x y width height
-==============
-*/
-void Cmd_Grab (void)
-{
-	int             xl,yl,w,h,y;
-	byte			*cropped;
-	char			savename[1024];
-	char			dest[1024];
-
-	GetScriptToken (false);
-
-	if (token[0] == '/' || token[0] == '\\')
-		sprintf (savename, "%s%s.pcx", gamedir, token+1);
-	else
-		sprintf (savename, "%spics/%s.pcx", gamedir, token);
-
-	if (g_release)
-	{
-		if (token[0] == '/' || token[0] == '\\')
-			sprintf (dest, "%s.pcx", token+1);
-		else
-			sprintf (dest, "pics/%s.pcx", token);
-
-		ReleaseFile (dest);
-		return;
-	}
-
-	GetScriptToken (false);
-	xl = atoi (token);
-	GetScriptToken (false);
-	yl = atoi (token);
-	GetScriptToken (false);
-	w = atoi (token);
-	GetScriptToken (false);
-	h = atoi (token);
-
-	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
-		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
-
-	// crop it to the proper size
-	cropped = (byte *) SafeMalloc (w*h, "Cmd_Grab");
-	for (y=0 ; y<h ; y++)
-	{
-		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, w,	h, lbmpalette);
-
-	free (cropped);
-}
-
-/*
-==============
-Cmd_Raw
-
-$grab filename x y width height
-==============
-*/
-void Cmd_Raw (void)
-{
-	int             xl,yl,w,h,y;
-	byte			*cropped;
-	char			savename[1024];
-	char			dest[1024];
-
-	GetScriptToken (false);
-
-	sprintf (savename, "%s%s.lmp", gamedir, token);
-
-	if (g_release)
-	{
-		sprintf (dest, "%s.lmp", token);
-		ReleaseFile (dest);
-		return;
-	}
-
-	GetScriptToken (false);
-	xl = atoi (token);
-	GetScriptToken (false);
-	yl = atoi (token);
-	GetScriptToken (false);
-	w = atoi (token);
-	GetScriptToken (false);
-	h = atoi (token);
-
-	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
-		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
-
-	// crop it to the proper size
-	cropped = (byte *) SafeMalloc (w*h, "Cmd_Raw");
-	for (y=0 ; y<h ; y++)
-	{
-		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-
-	SaveFile (savename, cropped, w*h);
-
-	free (cropped);
-}
-
-/*
-=============================================================================
-
-COLORMAP GRABBING
-
-=============================================================================
-*/
-
-/*
-===============
-BestColor
-===============
-*/
-byte BestColor (int r, int g, int b, int start, int stop)
-{
-	int	i;
-	int	dr, dg, db;
-	int	bestdistortion, distortion;
-	int	bestcolor;
-	byte	*pal;
-
-//
-// let any color go to 0 as a last resort
-//
-	bestdistortion = 256*256*4;
-	bestcolor = 0;
-
-	pal = colormap_palette + start*3;
-	for (i=start ; i<= stop ; i++)
-	{
-		dr = r - (int)pal[0];
-		dg = g - (int)pal[1];
-		db = b - (int)pal[2];
-		pal += 3;
-		distortion = dr*dr + dg*dg + db*db;
-		if (distortion < bestdistortion)
-		{
-			if (!distortion)
-				return i;		// perfect match
-
-			bestdistortion = distortion;
-			bestcolor = i;
-		}
-	}
-
-	return bestcolor;
-}
-
-
-/*
-==============
-Cmd_Colormap
-
-$colormap filename
-
-  the brightes colormap is first in the table (FIXME: reverse this now?)
-
-  64 rows of 256 : lightmaps
-  256 rows of 256 : translucency table
-==============
-*/
-void Cmd_Colormap (void)
-{
-	int		levels, brights;
-	int		l, c;
-	float	frac, red, green, blue;
-	float	range;
-	byte	*cropped, *lump_p;
-	char	savename[1024];
-	char	dest[1024];
-
-	colormap_issued = true;
-	if (!g_release)
-		memcpy (colormap_palette, lbmpalette, 768);
-
-	if (!ScriptTokenAvailable ())
-	{	// just setting colormap_issued
-		return;
-	}
-
-	GetScriptToken (false);
-	sprintf (savename, "%spics/%s.pcx", gamedir, token);
-
-	if (g_release)
-	{
-		sprintf (dest, "pics/%s.pcx", token);
-		ReleaseFile (dest);
-		return;
-	}
-
-	range = 2;
-	levels = 64;
-	brights = 1;	// ignore 255 (transparent)
-
-	cropped = (byte *) SafeMalloc((levels+256)*256, "Cmd_ColorMap");
-	lump_p = cropped;
-
-// shaded levels
-	for (l=0;l<levels;l++)
-	{
-		frac = range - range*(float)l/(levels-1);
-		for (c=0 ; c<256-brights ; c++)
-		{
-			red = lbmpalette[c*3];
-			green = lbmpalette[c*3+1];
-			blue = lbmpalette[c*3+2];
-
-			red = (int)(red*frac+0.5);
-			green = (int)(green*frac+0.5);
-			blue = (int)(blue*frac+0.5);
-			
-//
-// note: 254 instead of 255 because 255 is the transparent color, and we
-// don't want anything remapping to that
-// don't use color 0, because NT can't remap that (or 255)
-//
-			*lump_p++ = BestColor(red,green,blue, 1, 254);
-		}
-
-		// fullbrights allways stay the same
-		for ( ; c<256 ; c++)
-			*lump_p++ = c;
-	}
-	
-// 66% transparancy table
-	for (l=0;l<255;l++)
-	{
-		for (c=0 ; c<255 ; c++)
-		{
-			red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
-			green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
-			blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
-
-			*lump_p++ = BestColor(red,green,blue, 1, 254);
-		}
-		*lump_p++ = 255;
-	}
-	for (c=0 ; c<256 ; c++)
-		*lump_p++ = 255;
-	
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
-
-	free (cropped);
-}
-
-/*
-=============================================================================
-
-MIPTEX GRABBING
-
-=============================================================================
-*/
-
-byte	pixdata[256];
-
-int		d_red, d_green, d_blue;
-
-byte	palmap[32][32][32];
-qboolean	palmap_built;
-
-/*
-=============
-FindColor
-=============
-*/
-int FindColor (int r, int g, int b)
-{
-	int		bestcolor;
-
-	if (r > 255)
-		r = 255;
-	if (r < 0)
-		r = 0;
-	if (g > 255)
-		g = 255;
-	if (g < 0)
-		g = 0;
-	if (b > 255)
-		b = 255;
-	if (b < 0)
-		b = 0;
-#ifndef TABLECOLORS
-	bestcolor = BestColor (r, g, b, 0, 254);
-#else
-	bestcolor = palmap[r>>3][g>>3][b>>3];
-#endif
-
-	return bestcolor;
-}
-
-
-void BuildPalmap (void)
-{
-#ifdef TABLECOLORS
-	int		r, g, b;
-	int		bestcolor;
-
-	if (palmap_built)
-		return;
-	palmap_built = true;
-
-	for (r=4 ; r<256 ; r+=8)
-	{
-		for (g=4 ; g<256 ; g+=8)
-		{
-			for (b=4 ; b<256 ; b+=8)
-			{
-				bestcolor = BestColor (r, g, b, 1, 254);
-				palmap[r>>3][g>>3][b>>3] = bestcolor;
-			}
-		}
-	}
-#endif
-
-	if (!colormap_issued)
-		Error ("You must issue a $colormap command first");
-
-}
-
-/*
-=============
-AveragePixels
-=============
-*/
-byte AveragePixels (int count)
-{
-	int		r,g,b;
-	int		i;
-	int		vis;
-	int		pix;
-	int		bestcolor;
-	byte	*pal;
-	int		fullbright;
-	
-	vis = 0;
-	r = g = b = 0;
-	fullbright = 0;
-	for (i=0 ; i<count ; i++)
-	{
-		pix = pixdata[i];
-		
-		r += lbmpalette[pix*3];
-		g += lbmpalette[pix*3+1];
-		b += lbmpalette[pix*3+2];
-		vis++;
-	}
-		
-	r /= vis;
-	g /= vis;
-	b /= vis;
-
-	// error diffusion
-	r += d_red;
-	g += d_green;
-	b += d_blue;
-	
-//
-// find the best color
-//
-	bestcolor = FindColor (r, g, b);
-
-	// error diffusion
-	pal = colormap_palette + bestcolor*3;
-	d_red = r - (int)pal[0];
-	d_green = g - (int)pal[1];
-	d_blue = b - (int)pal[2];
-
-	return bestcolor;
-}
-
-
-typedef enum
-{
-	pt_contents,
-	pt_flags,
-	pt_animvalue,
-	pt_altnamevalue,
-	pt_damagenamevalue,
-	pt_flagvalue,
-	pt_materialvalue,
-	pt_scale,
-	pt_mip,
-	pt_detail,
-	pt_gl,
-	pt_nomip,
-	pt_detailer,
-} parmtype_t;
-
-typedef struct
-{
-	char	*name;
-	int		flags;
-	parmtype_t	type;
-} mipparm_t;
-
-mipparm_t	mipparms[] =
-{
-	// utility content attributes
-	{"pushpull",CONTENTS_PUSHPULL, pt_contents},
-	{"water",	CONTENTS_WATER, pt_contents},
-	{"slime",	CONTENTS_SLIME, pt_contents},		// mildly damaging
-	{"lava",	CONTENTS_LAVA, pt_contents},		// very damaging
-	{"window",	CONTENTS_WINDOW, pt_contents},	// solid, but doesn't eat internal textures
-	{"mist",	CONTENTS_MIST, pt_contents},	// non-solid window
-	{"origin",	CONTENTS_ORIGIN, pt_contents},	// center of rotating brushes
-	{"playerclip",	CONTENTS_PLAYERCLIP, pt_contents},
-	{"monsterclip",	CONTENTS_MONSTERCLIP, pt_contents},
-
-	// utility surface attributes
-	{"hint",	SURF_HINT, pt_flags},
-	{"skip",	SURF_SKIP, pt_flags},
-	{"light",	SURF_LIGHT, pt_flagvalue},		// value is the light quantity
-
-	{"animspeed",SURF_ANIMSPEED, pt_flagvalue},		// value will hold the anim speed in fps
-
-	// texture chaining
-	{"anim",	0,			pt_animvalue},		// animname is the next animation
-	{"alt",		0,			pt_altnamevalue},	// altname is the alternate texture
-	{"damage",	0,			pt_damagenamevalue},	// damagename is the damage texture
-	{"scale",	0,			pt_scale},		// next two values are for scale
-	{"mip",		0,			pt_mip},		
-	{"detail",	0,			pt_detail},		
-
-	{"GL_ZERO",					GL_ZERO,				pt_gl},
-	{"GL_ONE",					GL_ONE,					pt_gl},
-	{"GL_SRC_COLOR",			GL_SRC_COLOR,			pt_gl},
-	{"GL_ONE_MINUS_SRC_COLOR",	GL_ONE_MINUS_SRC_COLOR,	pt_gl},
-	{"GL_DST_COLOR",			GL_DST_COLOR,			pt_gl},
-	{"GL_ONE_MINUS_DST_COLOR",	GL_ONE_MINUS_DST_COLOR,	pt_gl},
-	{"GL_SRC_ALPHA",			GL_SRC_ALPHA,			pt_gl},
-	{"GL_ONE_MINUS_SRC_ALPHA",	GL_ONE_MINUS_SRC_ALPHA,	pt_gl},
-	{"GL_DST_ALPHA",			GL_DST_ALPHA,			pt_gl},
-	{"GL_ONE_MINUS_DST_ALPHA",	GL_ONE_MINUS_DST_ALPHA,	pt_gl},
-	{"GL_SRC_ALPHA_SATURATE",	GL_SRC_ALPHA_SATURATE,	pt_gl},
-
-	// server attributes
-	{"slick",	SURF_SLICK, pt_flags},
-
-	// drawing attributes
-	{"sky",		SURF_SKY, pt_flags},
-	{"warping",	SURF_WARP, pt_flags},		// only valid with 64x64 textures
-	{"trans33",	SURF_TRANS33, pt_flags},	// translucent should allso set fullbright
-	{"trans66",	SURF_TRANS66, pt_flags},
-	{"flowing",	SURF_FLOWING, pt_flags},	// flow direction towards angle 0
-	{"nodraw",	SURF_NODRAW, pt_flags},	// for clip textures and trigger textures
-	{"alpha",	SURF_ALPHA_TEXTURE, pt_flags},
-	{"undulate",	SURF_UNDULATE, pt_flags},		// rock surface up and down...
-	{"skyreflect",	SURF_SKYREFLECT, pt_flags},		// liquid will somewhat reflect the sky - not quite finished....
-
-	{"material", SURF_MATERIAL, pt_materialvalue},
-	{"metal",	SURF_TYPE_METAL, pt_flags},
-	{"stone",	SURF_TYPE_STONE, pt_flags},
-	{"wood",	SURF_TYPE_WOOD, pt_flags},
-
-	{"m_nomip", 0, pt_nomip},
-	{"m_detail", 0, pt_detailer},
-
-	{NULL, 0, pt_contents}
-};
-
-/*
-==============
-Cmd_Mip
-
-$mip filename x y width height <OPTIONS>
-must be multiples of sixteen
-SURF_WINDOW
-==============
-*/
-
-void Cmd_Mip (void)
-{
-	int             xl,yl,xh,yh,w,h;
-	byte            *dest, *source;
-	int				flags, value, contents;
-	mipparm_t		*mp;
-	char			lumpname[128];
-	char			altname[128];
-	char			animname[128];
-	char			damagename[128];
-	byte			buffer[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
-	unsigned		bufferl[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
-	materialtype_t	*mat;
-	char			filename[1024];
-	unsigned        *destl, *sourcel;
-	int             linedelta, x, y;
-	int				size;
-	miptex_t		*qtex;
-	miptex32_t		*qtex32;
-	float			scale_x, scale_y;
-	int				mip_scale;
-	// detail texturing
-	char			dt_name[128];
-	float			dt_scale_x, dt_scale_y;
-	float			dt_u, dt_v;
-	float			dt_alpha;
-	int				dt_src_blend_mode, dt_dst_blend_mode;
-	int				flags2;
-
-
-	GetScriptToken (false);
-	strcpy (lumpname, token);
-	
-	GetScriptToken (false);
-	xl = atoi (token);
-	GetScriptToken (false);
-	yl = atoi (token);
-	GetScriptToken (false);
-	w = atoi (token);
-	GetScriptToken (false);
-	h = atoi (token);
-
-	total_x += w;
-	total_y += h;
-	total_textures++;
-
-	if ( (w & 15) || (h & 15) )
-		Error ("line %i: miptex sizes must be multiples of 16", scriptline);
-
-	flags = 0;
-	flags2 = 0;
-	contents = 0;
-	value = 0;
-	mip_scale = 0;
-
-	altname[0] = animname[0] = damagename[0] = 0;
-
-	scale_x = scale_y = 0.5;
-
-	// detail texturing
-	dt_name[0] = 0;
-	dt_scale_x = dt_scale_y = 0.0;
-	dt_u = dt_v = 0.0;
-	dt_alpha = 0.0;
-	dt_src_blend_mode = dt_dst_blend_mode = 0;
-
-	// get optional flags and values
-	while (ScriptTokenAvailable ())
-	{
-		GetScriptToken (false);
-	
-		for (mp=mipparms ; mp->name ; mp++)
-		{
-			if (!strcmp(mp->name, token))
-			{
-				switch (mp->type)
-				{
-					case pt_animvalue:
-						GetScriptToken (false);	// specify the next animation frame
-						strcpy (animname, token);
-						break;
-					case pt_altnamevalue:
-						GetScriptToken (false);	// specify the alternate texture
-						strcpy (altname, token);
-						break;
-					case pt_damagenamevalue:
-						GetScriptToken (false);	// specify the damage texture
-						strcpy (damagename, token);
-						break;
-					case pt_flags:
-						flags |= mp->flags;
-						break;
-					case pt_contents:
-						contents |= mp->flags;
-						break;
-					case pt_flagvalue:
-						flags |= mp->flags;
-						GetScriptToken (false);	// specify the light value
-						value = atoi(token);
-						break;
-					case pt_materialvalue:
-						GetScriptToken(false);
-						for (mat=materialtypes ; mat->name ; mat++)
-						{
-							if (!strcmp(mat->name, token))
-							{
-								// assumes SURF_MATERIAL is in top 8 bits
-								flags = (flags & 0x0FFFFFF) | (mat->value << 24);
-								break;
-							}
-						}
-						break;
-					case pt_scale:
-						GetScriptToken (false);	// specify the x scale
-						scale_x = atof(token);
-						GetScriptToken (false);	// specify the y scale
-						scale_y = atof(token);
-						break;
-
-					case pt_mip:
-						mip_scale = 1;
-						break;
-
-					case pt_detailer:
-						flags2 |= MIP32_DETAILER_FLAG2;
-						break;
-
-					case pt_nomip:
-						flags2 |= MIP32_NOMIP_FLAG2;
-						break;
-
-					case pt_detail:
-						GetScriptToken(false);
-						strcpy(dt_name, token);
-						GetScriptToken(false);
-						dt_scale_x = atof(token);
-						GetScriptToken(false);
-						dt_scale_y = atof(token);
-						GetScriptToken(false);
-						dt_u = atof(token);
-						GetScriptToken(false);
-						dt_v = atof(token);
-						GetScriptToken(false);
-						dt_alpha = atof(token);
-						GetScriptToken(false);
-						for (mp=mipparms ; mp->name ; mp++)
-						{
-							if (!strcmp(mp->name, token))
-							{
-								if (mp->type == pt_gl)
-								{
-									dt_src_blend_mode = mp->flags;
-									break;
-								}
-							}
-						}
-						if (!mp->name)
-						{
-							Error ("line %i: invalid gl blend mode %s", scriptline, token);
-						}
-						GetScriptToken (false);
-						for (mp=mipparms ; mp->name ; mp++)
-						{
-							if (!strcmp(mp->name, token))
-							{
-								if (mp->type == pt_gl)
-								{
-									dt_dst_blend_mode = mp->flags;
-									break;
-								}
-							}
-						}
-						if (!mp->name)
-						{
-							Error ("line %i: invalid gl blend mode %s", scriptline, token);
-						}
-						break;
-				}
-				break;
-			}
-		}
-		if (!mp->name)
-			Error ("line %i: unknown parm %s", scriptline, token);
-	}
-
-	if (g_release)
-		return;	// textures are only released by $maps
-
-	xh = xl+w;
-	yh = yl+h;
-	if (xh*yh > MAX_IMAGE_SIZE*MAX_IMAGE_SIZE)
-	{
-		Error("line %i image %s: image is too big!", scriptline, lumpname);
-	}
-		
-	if (TrueColorImage)
-	{
-		if (xl >= longimagewidth || xh > longimagewidth ||
-			yl >= longimageheight || yh > longimageheight)
-		{
-			Error ("line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight);
-		}
-
-		sourcel = longimage + (yl*longimagewidth) + xl;
-		destl = bufferl;
-		linedelta = (longimagewidth - w);
-
-		for (y=yl ; y<yh ; y++)
-		{
-			for (x=xl ; x<xh ; x++)
-			{
-				*destl++ = *sourcel++;	// RGBA
-			}
-			sourcel += linedelta;
-		}
-
-		qtex32 = CreateMip32(bufferl, w, h, &size, true);
-
-		qtex32->flags |= LittleLong(flags);
-		qtex32->flags2 |= LittleLong(flags2);
-		qtex32->contents = LittleLong(contents);
-		qtex32->value = LittleLong(value);
-		qtex32->scale_x = scale_x;
-		qtex32->scale_y = scale_y;
-		qtex32->mip_scale = mip_scale;
-		sprintf (qtex32->name, "%s/%s", mip_prefix, lumpname);
-		if (animname[0])
-		{
-			sprintf (qtex32->animname, "%s/%s", mip_prefix, animname);
-		}
-		if (altname[0])
-		{
-			sprintf (qtex32->altname, "%s/%s", mip_prefix, altname);
-		}
-		if (damagename[0])
-		{
-			sprintf (qtex32->damagename, "%s/%s", mip_prefix, damagename);
-		}
-		if (dt_name[0] & ((flags2 & MIP32_DETAILER_FLAG2) == 0)) 
-		{
-			sprintf (qtex32->dt_name, "%s/%s", mip_prefix, dt_name);
-			qtex32->dt_scale_x = dt_scale_x;
-			qtex32->dt_scale_y = dt_scale_y;
-			qtex32->dt_u = dt_u;
-			qtex32->dt_v = dt_v;
-			qtex32->dt_alpha = dt_alpha;
-			qtex32->dt_src_blend_mode = dt_src_blend_mode;
-			qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
-		}
-		
-	//
-	// write it out
-	//
-		sprintf (filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname);
-		if(qtex32->flags & (SURF_ALPHA_TEXTURE))
-			printf ("writing %s with ALPHA\n", filename);
-		else
-			printf ("writing %s\n", filename);
-		SaveFile (filename, (byte *)qtex32, size);
-
-		free (qtex32);
-	}
-	else
-	{
-		if (xl >= byteimagewidth || xh > byteimagewidth ||
-			yl >= byteimageheight || yh > byteimageheight)
-		{
-			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
-		}
-
-		source = byteimage + yl*byteimagewidth + xl;
-		dest = buffer;
-		linedelta = byteimagewidth - w;
-
-		for (y=yl ; y<yh ; y++)
-		{
-			for (x=xl ; x<xh ; x++)
-			{
-				*dest++ = *source++;
-			}
-			source += linedelta;
-		}
-
-		qtex = CreateMip(buffer, w, h, lbmpalette, &size, true);
-
-		qtex->flags = LittleLong(flags);
-		qtex->contents = LittleLong(contents);
-		qtex->value = LittleLong(value);
-		sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
-		if (animname[0])
-			sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
-		
-	//
-	// write it out
-	//
-		sprintf (filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname);
-		printf ("writing %s\n", filename);
-		SaveFile (filename, (byte *)qtex, size);
-
-		free (qtex);
-	}
-}
-
-/*
-===============
-Cmd_Mippal
-===============
-*/
-void Cmd_Mippal (void)
-{
-	colormap_issued = true;
-	if (g_release)
-		return;
-
-	memcpy (colormap_palette, lbmpalette, 768);
-
-	BuildPalmap();
-}
-
-
-/*
-===============
-Cmd_Mipdir
-===============
-*/
-void Cmd_Mipdir (void)
-{
-	char	filename[1024];
-
-	GetScriptToken (false);
-	strcpy (mip_prefix, token);
-	// create the directory if needed
-	sprintf (filename, "%stextures", g_outputDir);
-	Q_mkdir (filename); 
-	sprintf (filename, "%stextures/%s", g_outputDir, mip_prefix);
-	Q_mkdir (filename); 
-}
-
-
-/*
-=============================================================================
-
-ENVIRONMENT MAP GRABBING
-
-Creates six pcx files from tga files without any palette edge seams
-also copies the tga files for GL rendering.
-=============================================================================
-*/
-
-// 3dstudio environment map suffixes
-char	*suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
-
-/*
-=================
-Cmd_Environment
-=================
-*/
-void Cmd_Environment (void)
-{
-	char	name[1024];
-	int		i, x, y;
-	byte	image[256*256];
-	byte	*tga;
-
-	GetScriptToken (false);
-
-	if (g_release)
-	{
-		for (i=0 ; i<6 ; i++)
-		{
-			sprintf (name, "env/%s%s.pcx", token, suf[i]);
-			ReleaseFile (name);
-			sprintf (name, "env/%s%s.tga", token, suf[i]);
-			ReleaseFile (name);
-		}
-		return;
-	}
-	// get the palette
-	BuildPalmap ();
-
-	sprintf (name, "%senv/", gamedir);
-	CreatePath (name);
-
-	// convert the images
-	for (i=0 ; i<6 ; i++)
-	{
-		sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
-		printf ("loading %s...\n", name);
-		LoadTGA (name, &tga, NULL, NULL);
-
-		for (y=0 ; y<256 ; y++)
-		{
-			for (x=0 ; x<256 ; x++)
-			{
-				image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
-			}
-		}
-		free (tga);
-		sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
-		if (FileTime (name) != -1)
-			printf ("%s already exists, not overwriting.\n", name);
-		else
-			WritePCXfile (name, image, 256, 256, colormap_palette);
-	}
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qdata.h"
+
+#ifdef _WIN32
+ #include <windows.h>
+#endif
+
+#include <GL/gl.h>
+
+#if 1
+	extern char		*g_outputDir;
+#endif // _QDATA
+
+char		mip_prefix[1024];		// directory to dump the textures in
+
+qboolean	colormap_issued;
+byte		colormap_palette[768];
+
+unsigned total_x = 0;
+unsigned total_y = 0;
+unsigned total_textures = 0;
+
+#define MAX_IMAGE_SIZE 512
+
+#if	0
+/*
+==============
+RemapZero
+
+Replaces all 0 bytes in an image with the closest palette entry.
+This is because NT won't let us change index 0, so any palette
+animation leaves those pixels untouched.
+==============
+*/
+void RemapZero (byte *pixels, byte *palette, int width, int height)
+{
+	int		i, c;
+	int		alt_zero;
+	int		value, best;
+
+	alt_zero = 0;
+	best = 9999999;
+	for (i=1 ; i<255 ; i++)
+	{
+		value = palette[i*3+0]+palette[i*3+1]+palette[i*3+2];
+		if (value < best)
+		{
+			best = value;
+			alt_zero = i;
+		}
+	}
+
+	c = width*height;
+	for (i=0 ; i<c ; i++)
+		if (pixels[i] == 0)
+			pixels[i] = alt_zero;
+}
+
+#endif
+
+
+// ********************************************************************
+// **  Mip Map Pre-Processing Routines
+// ********************************************************************
+
+#define intensity_value 1
+
+static unsigned image_pal[256];
+
+#define MAX_LAST 25
+
+long palette_r[256], palette_g[256], palette_b[256];
+long last_r[MAX_LAST],last_g[MAX_LAST],last_b[MAX_LAST], last_i[MAX_LAST], last_place;
+
+long cached;
+
+void PrepareConvert(unsigned *palette)
+{
+	int i;
+
+	for(i=0;i<256;i++)
+	{
+		palette_r[i] = (palette[i] & 0x00ff0000) >> 16;
+		palette_g[i] = (palette[i] & 0x0000ff00) >> 8;
+		palette_b[i] = (palette[i] & 0x000000ff);
+	}
+
+	for(i=0;i<MAX_LAST;i++)
+		last_r[i] = -1;
+
+	last_place = -1;
+}
+
+int ConvertTrueColorToPal(unsigned r, unsigned g, unsigned b)
+{
+	int i;
+	long min_dist;
+	int min_index;
+	long dist;
+	long dr, dg, db, biggest_delta;
+
+	for(i=0;i<MAX_LAST;i++)
+		if (r == last_r[i] && g == last_g[i] && b == last_b[i])
+		{
+			cached++;
+			return last_i[i];
+		}
+
+	min_dist = 256 * 256 + 256 * 256 + 256 * 256;
+	biggest_delta = 256*256;
+	min_index = 0;
+
+	for (i=0;i<256;i++)
+	{
+		dr = abs(palette_r[i] - r);
+		if (dr > biggest_delta)
+			continue;
+		dg = abs(palette_g[i] - g);
+		if (dg > biggest_delta)
+			continue;
+		db = abs(palette_b[i] - b);
+		if (db > biggest_delta)
+			continue;
+
+		dist = dr * dr + dg * dg + db * db;
+		if (dist < min_dist)
+		{
+			min_dist = dist;
+			min_index = i;
+			if (min_dist == 0) break;
+
+			dist = dr;
+			if (dg > dist) dist = dg;
+			if (db > dist) dist = db;
+			if (dist < biggest_delta)
+				biggest_delta = dist;
+		}
+	}
+
+	last_place++;
+	if (last_place >= MAX_LAST)
+		last_place = 0;
+
+	last_r[last_place] = r;
+	last_g[last_place] = g;
+	last_b[last_place] = b;
+	last_i[last_place] = min_index;
+
+	return min_index;
+}
+
+
+void GL_ResampleTexture8P (byte *in, int inwidth, int inheight, byte *out,  
+						   int outwidth, int outheight, palette_t *palette)
+{
+	int		i, j;
+	byte	*inrow, *inrow2;
+	unsigned	frac, fracstep;
+	unsigned	p1[1024], p2[1024], *p1p, *p2p;
+	palette_t	*c1,*c2,*c3,*c4;
+	unsigned	r,g,b;
+	
+	fracstep = inwidth*0x10000/outwidth;
+
+	frac = fracstep>>2;
+	for (i=0 ; i<outwidth ; i++)
+	{
+		p1[i] = frac>>16;
+		frac += fracstep;
+	}
+	frac = 3*(fracstep>>2);
+	for (i=0 ; i<outwidth ; i++)
+	{
+		p2[i] = frac>>16;
+		frac += fracstep;
+	}
+
+	cached = 0;
+	
+	for (i=0 ; i<outheight ; i++)//, out += outwidth)
+	{
+		inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
+		inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
+
+		p1p = p1;
+		p2p = p2;
+		for (j=0 ; j<outwidth ; j++)
+		{
+			c1 = &palette[*((byte *)inrow + (*p1p))];
+			c2 = &palette[*((byte *)inrow + (*p2p))];
+			c3 = &palette[*((byte *)inrow2 + (*p1p++))];
+			c4 = &palette[*((byte *)inrow2 + (*p2p++))];
+
+			r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r)>>2;
+			g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g)>>2;
+			b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b)>>2;
+
+			*out++ = ConvertTrueColorToPal(r,g,b);
+		}
+	}
+}
+
+void GL_MipMap8P(byte *out, byte *in, int width, int height, palette_t *palette)
+{
+	int			i, j;
+	palette_t	*c1,*c2,*c3,*c4;
+	unsigned	r,g,b;
+
+	cached = 0;
+	memset(out, 0, 256 * 256);
+	width <<= 1;
+	height <<= 1;
+
+	for (i = 0; i < height; i += 2, in += width)
+	{
+		for (j = 0; j < width; j += 2)
+		{
+			c1 = &palette[in[0]];
+			c3 = &palette[in[width]];
+			in++;
+			c2 = &palette[in[0]];
+			c4 = &palette[in[width]];
+			in++;
+
+			r = ((unsigned)c1->r + (unsigned)c2->r + (unsigned)c3->r + (unsigned)c4->r) >> 2;
+			g = ((unsigned)c1->g + (unsigned)c2->g + (unsigned)c3->g + (unsigned)c4->g) >> 2;
+			b = ((unsigned)c1->b + (unsigned)c2->b + (unsigned)c3->b + (unsigned)c4->b) >> 2;
+
+			*out++ = ConvertTrueColorToPal(r, g, b);
+		}
+	}
+}
+
+
+miptex_t *CreateMip(byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip)
+{
+	int			scaled_width, scaled_height;
+	int			i,j,r,g,b;
+	byte		intensitytable[256];
+	byte		scaled[256*256];
+	byte		out[256*256];
+	int			miplevel;
+	miptex_t	*mp;
+	byte		*pos;
+	int			size;
+
+	for (i=0 ; i<256 ; i++)
+	{
+		j = i * intensity_value;
+		if (j > 255)
+			j = 255;
+		intensitytable[i] = j;
+	}
+
+	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+		;
+	if (1 && scaled_width > width && 1)
+		scaled_width >>= 1;
+	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+		;
+	if (1 && scaled_height > height && 1)
+		scaled_height >>= 1;
+
+	// don't ever bother with >256 textures
+	if (scaled_width > 256)
+		scaled_width = 256;
+	if (scaled_height > 256)
+		scaled_height = 256;
+
+	if (scaled_width < 1)
+		scaled_width = 1;
+	if (scaled_height < 1)
+		scaled_height = 1;
+
+	size = sizeof(*mp) + (scaled_width*scaled_height*3);
+	mp = (miptex_t *)SafeMalloc(size, "CreateMip");
+	memset(mp,0,size);
+
+	mp->version = MIP_VERSION;
+
+	for(i=j=0;i<256;i++,j+=3)
+	{
+		mp->palette[i].r = r = intensitytable[palette[j]];
+		mp->palette[i].g = g = intensitytable[palette[j+1]];
+		mp->palette[i].b = b = intensitytable[palette[j+2]];
+		image_pal[i] = 0xff000000 | (r<<16) | (g<<8) | (b);
+	}
+
+	PrepareConvert(image_pal);
+
+	if (scaled_width == width && scaled_height == height)
+	{
+		memcpy (scaled, data, width*height);
+	}
+	else
+		GL_ResampleTexture8P (data, width, height, scaled, scaled_width, scaled_height, mp->palette);
+
+	pos = (byte *)(mp + 1);
+	miplevel = 0;
+
+	while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))
+	{
+		if (scaled_width < 1)
+			scaled_width = 1;
+		if (scaled_height < 1)
+			scaled_height = 1;
+
+		if(miplevel > 0)
+			GL_MipMap8P(out, (byte *)scaled, scaled_width, scaled_height, mp->palette);
+		else
+			memcpy(out, scaled, 256 * 256);
+
+		mp->width[miplevel] = scaled_width;
+		mp->height[miplevel] = scaled_height;
+		mp->offsets[miplevel] = pos - ((byte *)(mp));
+		memcpy(pos, out, scaled_width * scaled_height);
+		memcpy(scaled, out, 256 * 256);
+		pos += scaled_width * scaled_height;
+
+		scaled_width >>= 1;
+		scaled_height >>= 1;
+
+		miplevel++;
+	}
+
+	*FinalSize = pos - ((byte *)(mp));
+
+	return mp;
+}
+
+
+void GL_ResampleTexture (unsigned *in, int inwidth, int inheight, unsigned *out,  int outwidth, int outheight)
+{
+	int		i, j;
+	unsigned	*inrow, *inrow2;
+	unsigned	frac, fracstep;
+	unsigned	p1[1024], p2[1024];
+	byte		*pix1, *pix2, *pix3, *pix4;
+
+	fracstep = inwidth*0x10000/outwidth;
+
+	frac = fracstep>>2;
+	for (i=0 ; i<outwidth ; i++)
+	{
+		p1[i] = 4*(frac>>16);
+		frac += fracstep;
+	}
+	frac = 3*(fracstep>>2);
+	for (i=0 ; i<outwidth ; i++)
+	{
+		p2[i] = 4*(frac>>16);
+		frac += fracstep;
+	}
+
+	for (i=0 ; i<outheight ; i++, out += outwidth)
+	{
+		inrow = in + inwidth*(int)((i+0.25)*inheight/outheight);
+		inrow2 = in + inwidth*(int)((i+0.75)*inheight/outheight);
+		frac = fracstep >> 1;
+		for (j=0 ; j<outwidth ; j++)
+		{
+			pix1 = (byte *)inrow + p1[j];
+			pix2 = (byte *)inrow + p2[j];
+			pix3 = (byte *)inrow2 + p1[j];
+			pix4 = (byte *)inrow2 + p2[j];
+			((byte *)(out+j))[0] = (pix1[0] + pix2[0] + pix3[0] + pix4[0])>>2;
+			((byte *)(out+j))[1] = (pix1[1] + pix2[1] + pix3[1] + pix4[1])>>2;
+			((byte *)(out+j))[2] = (pix1[2] + pix2[2] + pix3[2] + pix4[2])>>2;
+			((byte *)(out+j))[3] = (pix1[3] + pix2[3] + pix3[3] + pix4[3])>>2;
+		}
+	}
+}
+
+void GL_MipMap (byte *out, byte *in, int width, int height)
+{
+	int		i, j;
+
+	width <<=3;
+	height <<= 1;
+	for (i=0 ; i<height ; i++, in+=width)
+	{
+		for (j=0 ; j<width ; j+=8, out+=4, in+=8)
+		{
+			out[0] = (in[0] + in[4] + in[width+0] + in[width+4])>>2;
+			out[1] = (in[1] + in[5] + in[width+1] + in[width+5])>>2;
+			out[2] = (in[2] + in[6] + in[width+2] + in[width+6])>>2;
+			out[3] = (in[3] + in[7] + in[width+3] + in[width+7])>>2;
+		}
+	}
+}
+
+miptex32_t *CreateMip32(unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip)
+{
+	int				scaled_width, scaled_height;
+	unsigned		scaled[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
+	unsigned		out[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
+	int				miplevel;
+	miptex32_t		*mp;
+	byte			*pos;
+	int				size;
+	paletteRGBA_t	*test;
+
+	for (scaled_width = 1 ; scaled_width < width ; scaled_width<<=1)
+		;
+	if (1 && scaled_width > width && 1)
+		scaled_width >>= 1;
+	for (scaled_height = 1 ; scaled_height < height ; scaled_height<<=1)
+		;
+	if (1 && scaled_height > height && 1)
+		scaled_height >>= 1;
+
+	// don't ever bother with >256 textures
+	if (scaled_width > MAX_IMAGE_SIZE)
+		scaled_width = MAX_IMAGE_SIZE;
+	if (scaled_height > MAX_IMAGE_SIZE)
+		scaled_height = MAX_IMAGE_SIZE;
+
+	if (scaled_width < 1)
+		scaled_width = 1;
+	if (scaled_height < 1)
+		scaled_height = 1;
+
+	size = sizeof(*mp) + (scaled_width*scaled_height*3*4);
+	mp = (miptex32_t *)SafeMalloc(size, "CreateMip");
+	memset(mp,0,size);
+
+	mp->version = MIP32_VERSION;
+
+	size = width*height;
+	test = (paletteRGBA_t *)data;
+	while(size)
+	{
+		if (test->a != 255)
+		{
+			mp->flags |= LittleLong(SURF_ALPHA_TEXTURE);
+			break;
+		}
+
+		size--;
+		test++;
+	}
+
+	if (scaled_width == width && scaled_height == height)
+	{
+		memcpy (scaled, data, width*height*4);
+	}
+	else
+		GL_ResampleTexture (data, width, height, scaled, scaled_width, scaled_height);
+
+	pos = (byte *)(mp + 1);
+	miplevel = 0;
+
+	while ((scaled_width >= 1 || scaled_height >= 1) && (miplevel <= MIPLEVELS-1) && (!miplevel || mip))
+	{
+		if (scaled_width < 1)
+			scaled_width = 1;
+		if (scaled_height < 1)
+			scaled_height = 1;
+
+		if (miplevel > 0)
+		{
+			GL_MipMap((byte *)out, (byte *)scaled, scaled_width, scaled_height);
+		}
+		else
+		{
+			memcpy(out, scaled, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);
+		}
+
+		mp->width[miplevel] = scaled_width;
+		mp->height[miplevel] = scaled_height;
+		mp->offsets[miplevel] = pos - ((byte *)(mp));
+		memcpy(pos, out, scaled_width * scaled_height * 4);
+		memcpy(scaled, out, MAX_IMAGE_SIZE * MAX_IMAGE_SIZE * 4);
+		pos += scaled_width * scaled_height * 4;
+
+		scaled_width >>= 1;
+		scaled_height >>= 1;
+
+		miplevel++;
+	}
+
+	*FinalSize = pos - ((byte *)(mp));
+
+	return mp;
+}
+
+/*
+==============
+Cmd_Grab
+
+$grab filename x y width height
+==============
+*/
+void Cmd_Grab (void)
+{
+	int             xl,yl,w,h,y;
+	byte			*cropped;
+	char			savename[1024];
+	char			dest[1024];
+
+	GetScriptToken (false);
+
+	if (token[0] == '/' || token[0] == '\\')
+		sprintf (savename, "%s%s.pcx", gamedir, token+1);
+	else
+		sprintf (savename, "%spics/%s.pcx", gamedir, token);
+
+	if (g_release)
+	{
+		if (token[0] == '/' || token[0] == '\\')
+			sprintf (dest, "%s.pcx", token+1);
+		else
+			sprintf (dest, "pics/%s.pcx", token);
+
+		ReleaseFile (dest);
+		return;
+	}
+
+	GetScriptToken (false);
+	xl = atoi (token);
+	GetScriptToken (false);
+	yl = atoi (token);
+	GetScriptToken (false);
+	w = atoi (token);
+	GetScriptToken (false);
+	h = atoi (token);
+
+	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
+		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
+
+	// crop it to the proper size
+	cropped = (byte *) SafeMalloc (w*h, "Cmd_Grab");
+	for (y=0 ; y<h ; y++)
+	{
+		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, w,	h, lbmpalette);
+
+	free (cropped);
+}
+
+/*
+==============
+Cmd_Raw
+
+$grab filename x y width height
+==============
+*/
+void Cmd_Raw (void)
+{
+	int             xl,yl,w,h,y;
+	byte			*cropped;
+	char			savename[1024];
+	char			dest[1024];
+
+	GetScriptToken (false);
+
+	sprintf (savename, "%s%s.lmp", gamedir, token);
+
+	if (g_release)
+	{
+		sprintf (dest, "%s.lmp", token);
+		ReleaseFile (dest);
+		return;
+	}
+
+	GetScriptToken (false);
+	xl = atoi (token);
+	GetScriptToken (false);
+	yl = atoi (token);
+	GetScriptToken (false);
+	w = atoi (token);
+	GetScriptToken (false);
+	h = atoi (token);
+
+	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
+		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
+
+	// crop it to the proper size
+	cropped = (byte *) SafeMalloc (w*h, "Cmd_Raw");
+	for (y=0 ; y<h ; y++)
+	{
+		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+
+	SaveFile (savename, cropped, w*h);
+
+	free (cropped);
+}
+
+/*
+=============================================================================
+
+COLORMAP GRABBING
+
+=============================================================================
+*/
+
+/*
+===============
+BestColor
+===============
+*/
+byte BestColor (int r, int g, int b, int start, int stop)
+{
+	int	i;
+	int	dr, dg, db;
+	int	bestdistortion, distortion;
+	int	bestcolor;
+	byte	*pal;
+
+//
+// let any color go to 0 as a last resort
+//
+	bestdistortion = 256*256*4;
+	bestcolor = 0;
+
+	pal = colormap_palette + start*3;
+	for (i=start ; i<= stop ; i++)
+	{
+		dr = r - (int)pal[0];
+		dg = g - (int)pal[1];
+		db = b - (int)pal[2];
+		pal += 3;
+		distortion = dr*dr + dg*dg + db*db;
+		if (distortion < bestdistortion)
+		{
+			if (!distortion)
+				return i;		// perfect match
+
+			bestdistortion = distortion;
+			bestcolor = i;
+		}
+	}
+
+	return bestcolor;
+}
+
+
+/*
+==============
+Cmd_Colormap
+
+$colormap filename
+
+  the brightes colormap is first in the table (FIXME: reverse this now?)
+
+  64 rows of 256 : lightmaps
+  256 rows of 256 : translucency table
+==============
+*/
+void Cmd_Colormap (void)
+{
+	int		levels, brights;
+	int		l, c;
+	float	frac, red, green, blue;
+	float	range;
+	byte	*cropped, *lump_p;
+	char	savename[1024];
+	char	dest[1024];
+
+	colormap_issued = true;
+	if (!g_release)
+		memcpy (colormap_palette, lbmpalette, 768);
+
+	if (!ScriptTokenAvailable ())
+	{	// just setting colormap_issued
+		return;
+	}
+
+	GetScriptToken (false);
+	sprintf (savename, "%spics/%s.pcx", gamedir, token);
+
+	if (g_release)
+	{
+		sprintf (dest, "pics/%s.pcx", token);
+		ReleaseFile (dest);
+		return;
+	}
+
+	range = 2;
+	levels = 64;
+	brights = 1;	// ignore 255 (transparent)
+
+	cropped = (byte *) SafeMalloc((levels+256)*256, "Cmd_ColorMap");
+	lump_p = cropped;
+
+// shaded levels
+	for (l=0;l<levels;l++)
+	{
+		frac = range - range*(float)l/(levels-1);
+		for (c=0 ; c<256-brights ; c++)
+		{
+			red = lbmpalette[c*3];
+			green = lbmpalette[c*3+1];
+			blue = lbmpalette[c*3+2];
+
+			red = (int)(red*frac+0.5);
+			green = (int)(green*frac+0.5);
+			blue = (int)(blue*frac+0.5);
+			
+//
+// note: 254 instead of 255 because 255 is the transparent color, and we
+// don't want anything remapping to that
+// don't use color 0, because NT can't remap that (or 255)
+//
+			*lump_p++ = BestColor(red,green,blue, 1, 254);
+		}
+
+		// fullbrights allways stay the same
+		for ( ; c<256 ; c++)
+			*lump_p++ = c;
+	}
+	
+// 66% transparancy table
+	for (l=0;l<255;l++)
+	{
+		for (c=0 ; c<255 ; c++)
+		{
+			red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
+			green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
+			blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
+
+			*lump_p++ = BestColor(red,green,blue, 1, 254);
+		}
+		*lump_p++ = 255;
+	}
+	for (c=0 ; c<256 ; c++)
+		*lump_p++ = 255;
+	
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
+
+	free (cropped);
+}
+
+/*
+=============================================================================
+
+MIPTEX GRABBING
+
+=============================================================================
+*/
+
+byte	pixdata[256];
+
+int		d_red, d_green, d_blue;
+
+byte	palmap[32][32][32];
+qboolean	palmap_built;
+
+/*
+=============
+FindColor
+=============
+*/
+int FindColor (int r, int g, int b)
+{
+	int		bestcolor;
+
+	if (r > 255)
+		r = 255;
+	if (r < 0)
+		r = 0;
+	if (g > 255)
+		g = 255;
+	if (g < 0)
+		g = 0;
+	if (b > 255)
+		b = 255;
+	if (b < 0)
+		b = 0;
+#ifndef TABLECOLORS
+	bestcolor = BestColor (r, g, b, 0, 254);
+#else
+	bestcolor = palmap[r>>3][g>>3][b>>3];
+#endif
+
+	return bestcolor;
+}
+
+
+void BuildPalmap (void)
+{
+#ifdef TABLECOLORS
+	int		r, g, b;
+	int		bestcolor;
+
+	if (palmap_built)
+		return;
+	palmap_built = true;
+
+	for (r=4 ; r<256 ; r+=8)
+	{
+		for (g=4 ; g<256 ; g+=8)
+		{
+			for (b=4 ; b<256 ; b+=8)
+			{
+				bestcolor = BestColor (r, g, b, 1, 254);
+				palmap[r>>3][g>>3][b>>3] = bestcolor;
+			}
+		}
+	}
+#endif
+
+	if (!colormap_issued)
+		Error ("You must issue a $colormap command first");
+
+}
+
+/*
+=============
+AveragePixels
+=============
+*/
+byte AveragePixels (int count)
+{
+	int		r,g,b;
+	int		i;
+	int		vis;
+	int		pix;
+	int		bestcolor;
+	byte	*pal;
+	int		fullbright;
+	
+	vis = 0;
+	r = g = b = 0;
+	fullbright = 0;
+	for (i=0 ; i<count ; i++)
+	{
+		pix = pixdata[i];
+		
+		r += lbmpalette[pix*3];
+		g += lbmpalette[pix*3+1];
+		b += lbmpalette[pix*3+2];
+		vis++;
+	}
+		
+	r /= vis;
+	g /= vis;
+	b /= vis;
+
+	// error diffusion
+	r += d_red;
+	g += d_green;
+	b += d_blue;
+	
+//
+// find the best color
+//
+	bestcolor = FindColor (r, g, b);
+
+	// error diffusion
+	pal = colormap_palette + bestcolor*3;
+	d_red = r - (int)pal[0];
+	d_green = g - (int)pal[1];
+	d_blue = b - (int)pal[2];
+
+	return bestcolor;
+}
+
+
+typedef enum
+{
+	pt_contents,
+	pt_flags,
+	pt_animvalue,
+	pt_altnamevalue,
+	pt_damagenamevalue,
+	pt_flagvalue,
+	pt_materialvalue,
+	pt_scale,
+	pt_mip,
+	pt_detail,
+	pt_gl,
+	pt_nomip,
+	pt_detailer,
+} parmtype_t;
+
+typedef struct
+{
+	char	*name;
+	int		flags;
+	parmtype_t	type;
+} mipparm_t;
+
+mipparm_t	mipparms[] =
+{
+	// utility content attributes
+	{"pushpull",CONTENTS_PUSHPULL, pt_contents},
+	{"water",	CONTENTS_WATER, pt_contents},
+	{"slime",	CONTENTS_SLIME, pt_contents},		// mildly damaging
+	{"lava",	CONTENTS_LAVA, pt_contents},		// very damaging
+	{"window",	CONTENTS_WINDOW, pt_contents},	// solid, but doesn't eat internal textures
+	{"mist",	CONTENTS_MIST, pt_contents},	// non-solid window
+	{"origin",	CONTENTS_ORIGIN, pt_contents},	// center of rotating brushes
+	{"playerclip",	CONTENTS_PLAYERCLIP, pt_contents},
+	{"monsterclip",	CONTENTS_MONSTERCLIP, pt_contents},
+
+	// utility surface attributes
+	{"hint",	SURF_HINT, pt_flags},
+	{"skip",	SURF_SKIP, pt_flags},
+	{"light",	SURF_LIGHT, pt_flagvalue},		// value is the light quantity
+
+	{"animspeed",SURF_ANIMSPEED, pt_flagvalue},		// value will hold the anim speed in fps
+
+	// texture chaining
+	{"anim",	0,			pt_animvalue},		// animname is the next animation
+	{"alt",		0,			pt_altnamevalue},	// altname is the alternate texture
+	{"damage",	0,			pt_damagenamevalue},	// damagename is the damage texture
+	{"scale",	0,			pt_scale},		// next two values are for scale
+	{"mip",		0,			pt_mip},		
+	{"detail",	0,			pt_detail},		
+
+	{"GL_ZERO",					GL_ZERO,				pt_gl},
+	{"GL_ONE",					GL_ONE,					pt_gl},
+	{"GL_SRC_COLOR",			GL_SRC_COLOR,			pt_gl},
+	{"GL_ONE_MINUS_SRC_COLOR",	GL_ONE_MINUS_SRC_COLOR,	pt_gl},
+	{"GL_DST_COLOR",			GL_DST_COLOR,			pt_gl},
+	{"GL_ONE_MINUS_DST_COLOR",	GL_ONE_MINUS_DST_COLOR,	pt_gl},
+	{"GL_SRC_ALPHA",			GL_SRC_ALPHA,			pt_gl},
+	{"GL_ONE_MINUS_SRC_ALPHA",	GL_ONE_MINUS_SRC_ALPHA,	pt_gl},
+	{"GL_DST_ALPHA",			GL_DST_ALPHA,			pt_gl},
+	{"GL_ONE_MINUS_DST_ALPHA",	GL_ONE_MINUS_DST_ALPHA,	pt_gl},
+	{"GL_SRC_ALPHA_SATURATE",	GL_SRC_ALPHA_SATURATE,	pt_gl},
+
+	// server attributes
+	{"slick",	SURF_SLICK, pt_flags},
+
+	// drawing attributes
+	{"sky",		SURF_SKY, pt_flags},
+	{"warping",	SURF_WARP, pt_flags},		// only valid with 64x64 textures
+	{"trans33",	SURF_TRANS33, pt_flags},	// translucent should allso set fullbright
+	{"trans66",	SURF_TRANS66, pt_flags},
+	{"flowing",	SURF_FLOWING, pt_flags},	// flow direction towards angle 0
+	{"nodraw",	SURF_NODRAW, pt_flags},	// for clip textures and trigger textures
+	{"alpha",	SURF_ALPHA_TEXTURE, pt_flags},
+	{"undulate",	SURF_UNDULATE, pt_flags},		// rock surface up and down...
+	{"skyreflect",	SURF_SKYREFLECT, pt_flags},		// liquid will somewhat reflect the sky - not quite finished....
+
+	{"material", SURF_MATERIAL, pt_materialvalue},
+	{"metal",	SURF_TYPE_METAL, pt_flags},
+	{"stone",	SURF_TYPE_STONE, pt_flags},
+	{"wood",	SURF_TYPE_WOOD, pt_flags},
+
+	{"m_nomip", 0, pt_nomip},
+	{"m_detail", 0, pt_detailer},
+
+	{NULL, 0, pt_contents}
+};
+
+/*
+==============
+Cmd_Mip
+
+$mip filename x y width height <OPTIONS>
+must be multiples of sixteen
+SURF_WINDOW
+==============
+*/
+
+void Cmd_Mip (void)
+{
+	int             xl,yl,xh,yh,w,h;
+	byte            *dest, *source;
+	int				flags, value, contents;
+	mipparm_t		*mp;
+	char			lumpname[128];
+	char			altname[128];
+	char			animname[128];
+	char			damagename[128];
+	byte			buffer[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
+	unsigned		bufferl[MAX_IMAGE_SIZE*MAX_IMAGE_SIZE];
+	materialtype_t	*mat;
+	char			filename[1024];
+	unsigned        *destl, *sourcel;
+	int             linedelta, x, y;
+	int				size;
+	miptex_t		*qtex;
+	miptex32_t		*qtex32;
+	float			scale_x, scale_y;
+	int				mip_scale;
+	// detail texturing
+	char			dt_name[128];
+	float			dt_scale_x, dt_scale_y;
+	float			dt_u, dt_v;
+	float			dt_alpha;
+	int				dt_src_blend_mode, dt_dst_blend_mode;
+	int				flags2;
+
+
+	GetScriptToken (false);
+	strcpy (lumpname, token);
+	
+	GetScriptToken (false);
+	xl = atoi (token);
+	GetScriptToken (false);
+	yl = atoi (token);
+	GetScriptToken (false);
+	w = atoi (token);
+	GetScriptToken (false);
+	h = atoi (token);
+
+	total_x += w;
+	total_y += h;
+	total_textures++;
+
+	if ( (w & 15) || (h & 15) )
+		Error ("line %i: miptex sizes must be multiples of 16", scriptline);
+
+	flags = 0;
+	flags2 = 0;
+	contents = 0;
+	value = 0;
+	mip_scale = 0;
+
+	altname[0] = animname[0] = damagename[0] = 0;
+
+	scale_x = scale_y = 0.5;
+
+	// detail texturing
+	dt_name[0] = 0;
+	dt_scale_x = dt_scale_y = 0.0;
+	dt_u = dt_v = 0.0;
+	dt_alpha = 0.0;
+	dt_src_blend_mode = dt_dst_blend_mode = 0;
+
+	// get optional flags and values
+	while (ScriptTokenAvailable ())
+	{
+		GetScriptToken (false);
+	
+		for (mp=mipparms ; mp->name ; mp++)
+		{
+			if (!strcmp(mp->name, token))
+			{
+				switch (mp->type)
+				{
+					case pt_animvalue:
+						GetScriptToken (false);	// specify the next animation frame
+						strcpy (animname, token);
+						break;
+					case pt_altnamevalue:
+						GetScriptToken (false);	// specify the alternate texture
+						strcpy (altname, token);
+						break;
+					case pt_damagenamevalue:
+						GetScriptToken (false);	// specify the damage texture
+						strcpy (damagename, token);
+						break;
+					case pt_flags:
+						flags |= mp->flags;
+						break;
+					case pt_contents:
+						contents |= mp->flags;
+						break;
+					case pt_flagvalue:
+						flags |= mp->flags;
+						GetScriptToken (false);	// specify the light value
+						value = atoi(token);
+						break;
+					case pt_materialvalue:
+						GetScriptToken(false);
+						for (mat=materialtypes ; mat->name ; mat++)
+						{
+							if (!strcmp(mat->name, token))
+							{
+								// assumes SURF_MATERIAL is in top 8 bits
+								flags = (flags & 0x0FFFFFF) | (mat->value << 24);
+								break;
+							}
+						}
+						break;
+					case pt_scale:
+						GetScriptToken (false);	// specify the x scale
+						scale_x = atof(token);
+						GetScriptToken (false);	// specify the y scale
+						scale_y = atof(token);
+						break;
+
+					case pt_mip:
+						mip_scale = 1;
+						break;
+
+					case pt_detailer:
+						flags2 |= MIP32_DETAILER_FLAG2;
+						break;
+
+					case pt_nomip:
+						flags2 |= MIP32_NOMIP_FLAG2;
+						break;
+
+					case pt_detail:
+						GetScriptToken(false);
+						strcpy(dt_name, token);
+						GetScriptToken(false);
+						dt_scale_x = atof(token);
+						GetScriptToken(false);
+						dt_scale_y = atof(token);
+						GetScriptToken(false);
+						dt_u = atof(token);
+						GetScriptToken(false);
+						dt_v = atof(token);
+						GetScriptToken(false);
+						dt_alpha = atof(token);
+						GetScriptToken(false);
+						for (mp=mipparms ; mp->name ; mp++)
+						{
+							if (!strcmp(mp->name, token))
+							{
+								if (mp->type == pt_gl)
+								{
+									dt_src_blend_mode = mp->flags;
+									break;
+								}
+							}
+						}
+						if (!mp->name)
+						{
+							Error ("line %i: invalid gl blend mode %s", scriptline, token);
+						}
+						GetScriptToken (false);
+						for (mp=mipparms ; mp->name ; mp++)
+						{
+							if (!strcmp(mp->name, token))
+							{
+								if (mp->type == pt_gl)
+								{
+									dt_dst_blend_mode = mp->flags;
+									break;
+								}
+							}
+						}
+						if (!mp->name)
+						{
+							Error ("line %i: invalid gl blend mode %s", scriptline, token);
+						}
+						break;
+				}
+				break;
+			}
+		}
+		if (!mp->name)
+			Error ("line %i: unknown parm %s", scriptline, token);
+	}
+
+	if (g_release)
+		return;	// textures are only released by $maps
+
+	xh = xl+w;
+	yh = yl+h;
+	if (xh*yh > MAX_IMAGE_SIZE*MAX_IMAGE_SIZE)
+	{
+		Error("line %i image %s: image is too big!", scriptline, lumpname);
+	}
+		
+	if (TrueColorImage)
+	{
+		if (xl >= longimagewidth || xh > longimagewidth ||
+			yl >= longimageheight || yh > longimageheight)
+		{
+			Error ("line %i image %s: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, lumpname, xl,yl,w,h,longimagewidth,longimageheight);
+		}
+
+		sourcel = longimage + (yl*longimagewidth) + xl;
+		destl = bufferl;
+		linedelta = (longimagewidth - w);
+
+		for (y=yl ; y<yh ; y++)
+		{
+			for (x=xl ; x<xh ; x++)
+			{
+				*destl++ = *sourcel++;	// RGBA
+			}
+			sourcel += linedelta;
+		}
+
+		qtex32 = CreateMip32(bufferl, w, h, &size, true);
+
+		qtex32->flags |= LittleLong(flags);
+		qtex32->flags2 |= LittleLong(flags2);
+		qtex32->contents = LittleLong(contents);
+		qtex32->value = LittleLong(value);
+		qtex32->scale_x = scale_x;
+		qtex32->scale_y = scale_y;
+		qtex32->mip_scale = mip_scale;
+		sprintf (qtex32->name, "%s/%s", mip_prefix, lumpname);
+		if (animname[0])
+		{
+			sprintf (qtex32->animname, "%s/%s", mip_prefix, animname);
+		}
+		if (altname[0])
+		{
+			sprintf (qtex32->altname, "%s/%s", mip_prefix, altname);
+		}
+		if (damagename[0])
+		{
+			sprintf (qtex32->damagename, "%s/%s", mip_prefix, damagename);
+		}
+		if (dt_name[0] & ((flags2 & MIP32_DETAILER_FLAG2) == 0)) 
+		{
+			sprintf (qtex32->dt_name, "%s/%s", mip_prefix, dt_name);
+			qtex32->dt_scale_x = dt_scale_x;
+			qtex32->dt_scale_y = dt_scale_y;
+			qtex32->dt_u = dt_u;
+			qtex32->dt_v = dt_v;
+			qtex32->dt_alpha = dt_alpha;
+			qtex32->dt_src_blend_mode = dt_src_blend_mode;
+			qtex32->dt_dst_blend_mode = dt_dst_blend_mode;
+		}
+		
+	//
+	// write it out
+	//
+		sprintf (filename, "%stextures/%s/%s.m32", g_outputDir, mip_prefix, lumpname);
+		if(qtex32->flags & (SURF_ALPHA_TEXTURE))
+			printf ("writing %s with ALPHA\n", filename);
+		else
+			printf ("writing %s\n", filename);
+		SaveFile (filename, (byte *)qtex32, size);
+
+		free (qtex32);
+	}
+	else
+	{
+		if (xl >= byteimagewidth || xh > byteimagewidth ||
+			yl >= byteimageheight || yh > byteimageheight)
+		{
+			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
+		}
+
+		source = byteimage + yl*byteimagewidth + xl;
+		dest = buffer;
+		linedelta = byteimagewidth - w;
+
+		for (y=yl ; y<yh ; y++)
+		{
+			for (x=xl ; x<xh ; x++)
+			{
+				*dest++ = *source++;
+			}
+			source += linedelta;
+		}
+
+		qtex = CreateMip(buffer, w, h, lbmpalette, &size, true);
+
+		qtex->flags = LittleLong(flags);
+		qtex->contents = LittleLong(contents);
+		qtex->value = LittleLong(value);
+		sprintf (qtex->name, "%s/%s", mip_prefix, lumpname);
+		if (animname[0])
+			sprintf (qtex->animname, "%s/%s", mip_prefix, animname);
+		
+	//
+	// write it out
+	//
+		sprintf (filename, "%stextures/%s/%s.m8", g_outputDir, mip_prefix, lumpname);
+		printf ("writing %s\n", filename);
+		SaveFile (filename, (byte *)qtex, size);
+
+		free (qtex);
+	}
+}
+
+/*
+===============
+Cmd_Mippal
+===============
+*/
+void Cmd_Mippal (void)
+{
+	colormap_issued = true;
+	if (g_release)
+		return;
+
+	memcpy (colormap_palette, lbmpalette, 768);
+
+	BuildPalmap();
+}
+
+
+/*
+===============
+Cmd_Mipdir
+===============
+*/
+void Cmd_Mipdir (void)
+{
+	char	filename[1024];
+
+	GetScriptToken (false);
+	strcpy (mip_prefix, token);
+	// create the directory if needed
+	sprintf (filename, "%stextures", g_outputDir);
+	Q_mkdir (filename); 
+	sprintf (filename, "%stextures/%s", g_outputDir, mip_prefix);
+	Q_mkdir (filename); 
+}
+
+
+/*
+=============================================================================
+
+ENVIRONMENT MAP GRABBING
+
+Creates six pcx files from tga files without any palette edge seams
+also copies the tga files for GL rendering.
+=============================================================================
+*/
+
+// 3dstudio environment map suffixes
+char	*suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
+
+/*
+=================
+Cmd_Environment
+=================
+*/
+void Cmd_Environment (void)
+{
+	char	name[1024];
+	int		i, x, y;
+	byte	image[256*256];
+	byte	*tga;
+
+	GetScriptToken (false);
+
+	if (g_release)
+	{
+		for (i=0 ; i<6 ; i++)
+		{
+			sprintf (name, "env/%s%s.pcx", token, suf[i]);
+			ReleaseFile (name);
+			sprintf (name, "env/%s%s.tga", token, suf[i]);
+			ReleaseFile (name);
+		}
+		return;
+	}
+	// get the palette
+	BuildPalmap ();
+
+	sprintf (name, "%senv/", gamedir);
+	CreatePath (name);
+
+	// convert the images
+	for (i=0 ; i<6 ; i++)
+	{
+		sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
+		printf ("loading %s...\n", name);
+		LoadTGA (name, &tga, NULL, NULL);
+
+		for (y=0 ; y<256 ; y++)
+		{
+			for (x=0 ; x<256 ; x++)
+			{
+				image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
+			}
+		}
+		free (tga);
+		sprintf (name, "%senv/%s%s.pcx", gamedir, token, suf[i]);
+		if (FileTime (name) != -1)
+			printf ("%s already exists, not overwriting.\n", name);
+		else
+			WritePCXfile (name, image, 256, 256, colormap_palette);
+	}
+}
+
diff --git a/tools/quake2/qdata_heretic2/jointed.c b/tools/quake2/qdata_heretic2/jointed.c
index 09b963f6..af458ba2 100644
--- a/tools/quake2/qdata_heretic2/jointed.c
+++ b/tools/quake2/qdata_heretic2/jointed.c
@@ -1,572 +1,572 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <assert.h>
-#include <math.h>
-#include "token.h"
-#include "joints.h"
-#include "angles.h"
-#include "inout.h"
-
-char *SKEL_ROOT_NAMES[] =
-{
-	"RAVEN_SPINE"
-};
-
-char *SKEL_NAMES[] =
-{
-	"RAVEN_WAIST1",
-	"RAVEN_WAIST2",
-	"RAVEN_NECK"
-};
-
-int NAME_OFFSETS[] =
-{
-	0
-};
-
-int numJointsForSkeleton[] = 
-{
-	NUM_JOINTS_RAVEN,
-	NUM_JOINTS_BOX
-};
-
-float g_scaling[3];
-float g_rotation[3];
-float g_translation[3];
-
-//==========================================================================
-//
-// LoadHRCClustered
-//
-//==========================================================================
-
-static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)
-{
-	int i, j;
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-
-	TK_Beyond(TK_CLUSTERS);
-
-	while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)
-	{
-		TK_Require(TK_STRING);
-
-		for( i = 0; i < numJointsForSkeleton[skelType]; ++i)
-		{
-			if(stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
-			{
-				i = -i + numJointsForSkeleton[skelType] - 1;
-
-				TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
-
-				num_verts[i+1] = tk_IntNumber;
-
-				clusterList[i] = (int *) SafeMalloc(num_verts[i+1]*sizeof(int), "LoadHRCClustered");
-				assert(clusterList[i]);
-				// currently this function is only called by LoadTriangleListClustered, which in turn is only
-				// called by Cmd_Base in qdata.  This is where the only call to free for this memory is being made.
-
-				TK_Beyond(TK_LBRACE);
-
-				for(j = 0; j < num_verts[i+1]; ++j)
-				{
-					TK_Require(TK_INTNUMBER);
-					clusterList[i][j] = tk_IntNumber;
-					TK_Fetch();
-				}
-
-				break;
-			}
-		}
-	}
-
-	num_verts[0] = numJointsForSkeleton[skelType];
-}
-
-static void LoadHRCGlobals(char *fileName)
-{
-	int i;
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-	TK_Beyond(TK_MODEL);
-
-	TK_Beyond(TK_SCALING);
-	for(i = 0; i < 3; i++)
-	{
-		TK_Require(TK_FLOATNUMBER);
-		g_scaling[i] = tk_FloatNumber;
-		TK_Fetch();
-	}
-
-	TK_Beyond(TK_ROTATION);
-	for(i = 0; i < 3; i++)
-	{
-		TK_Require(TK_FLOATNUMBER);
-		g_rotation[i] = tk_FloatNumber;
-		TK_Fetch();
-	}
-
-	TK_Beyond(TK_TRANSLATION);
-	for(i = 0; i < 3; i++)
-	{
-		TK_Require(TK_FLOATNUMBER);
-		g_translation[i] = tk_FloatNumber;
-		TK_Fetch();
-	}
-}
-
-static void ParseVec3(vec3_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void ParseRotation3(vec3_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = -tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void ParseTranslation3(vec3_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void LoadHRCJointList(char *fileName, QDataJoint_t *jointList, int skelType)
-{
-#define MAX_STACK 64
-	int i, j;
-	vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
-	int curCorrespondingJoint[MAX_STACK];
-	int currentStack = 0, stackSize;
-	int baseJoint;
-	float cx, sx, cy, sy, cz, sz;
-	float rx, ry, rz;
-	float x2, y2, z2;
-
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-
-	TK_Beyond(TK_MODEL);
-	TK_Beyond(TK_MODEL);
-
-/*	while(1)
-	{
-		TK_Beyond(TK_MODEL);
-		TK_BeyondRequire(TK_NAME, TK_STRING);
-
-		if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
-			break;
-	}*/
-
-	TK_Beyond(TK_SCALING);
-
-	ParseVec3(curScale[currentStack]);
-
-	TK_Beyond(TK_ROTATION);
-
-	ParseRotation3(curRotation[currentStack]);
-
-	TK_Beyond(TK_TRANSLATION);
-
-	ParseVec3(curTranslation[currentStack]);
-
-	// account for global model translation
-	curTranslation[currentStack][1] += g_translation[0];
-	curTranslation[currentStack][2] += g_translation[1];
-	curTranslation[currentStack][0] += g_translation[2];
-
-	++currentStack;
-
-	for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
-	{
-		while(1)
-		{
-			TK_Beyond(TK_MODEL);
-
-//			TK_BeyondRequire(TK_NAME, TK_STRING);
-
-//			if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
-				break;
-
-			TK_Beyond(TK_SCALING);
-
-			ParseVec3(curScale[currentStack]);
-
-			TK_Beyond(TK_ROTATION);
-
-			ParseRotation3(curRotation[currentStack]);
-
-			TK_Beyond(TK_TRANSLATION);
-
-			ParseVec3(curTranslation[currentStack]);
-
-			curCorrespondingJoint[currentStack] = -1;
-
-			++currentStack;
-		}
-
-		TK_Beyond(TK_SCALING);
-
-		ParseVec3(curScale[currentStack]);
-
-		TK_Beyond(TK_ROTATION);
-
-		ParseRotation3(curRotation[currentStack]);
-
-		jointList[i].rotation[1] = curRotation[currentStack][1];
-		jointList[i].rotation[2] = curRotation[currentStack][2];
-		jointList[i].rotation[0] = curRotation[currentStack][0];
-
-		TK_Beyond(TK_TRANSLATION);
-
-		ParseVec3(curTranslation[currentStack]);
-
-		jointList[i].placement.origin[1] = curTranslation[currentStack][1];
-		jointList[i].placement.origin[2] = curTranslation[currentStack][2];
-		jointList[i].placement.origin[0] = curTranslation[currentStack][0];
-
-		jointList[i].placement.direction[1] = 7.5;
-		jointList[i].placement.direction[2] = 0.0;
-		jointList[i].placement.direction[0] = 0.0;
-
-		jointList[i].placement.up[1] = 0.0;
-		jointList[i].placement.up[2] = 7.5;
-		jointList[i].placement.up[0] = 0.0;
-
-		curCorrespondingJoint[currentStack] = i;
-
-		++currentStack;
-	}
-
-	stackSize = currentStack;
-
-	for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
-	{
-		rx = jointList[i].rotation[0]*ANGLE_TO_RAD;
-		ry = jointList[i].rotation[1]*ANGLE_TO_RAD;
-		rz = jointList[i].rotation[2]*ANGLE_TO_RAD;
-
-		cx = cos(rx);
-		sx = sin(rx);
-
-		cy = cos(ry);
-		sy = sin(ry);
-
-		cz = cos(rz);
-		sz = sin(rz);
-
-		// y-axis rotation for direction
-		x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;
-		z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;
-		jointList[i].placement.direction[0] = x2;
-		jointList[i].placement.direction[2] = z2;
-
-		// y-axis rotation for up
-		x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;
-		z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;
-		jointList[i].placement.up[0] = x2;
-		jointList[i].placement.up[2] = z2;
-
-		// z-axis rotation for direction
-		x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;
-		y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;
-		jointList[i].placement.direction[0] = x2;
-		jointList[i].placement.direction[1] = y2;
-
-		// z-axis rotation for up
-		x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;
-		y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;
-		jointList[i].placement.up[0] = x2;
-		jointList[i].placement.up[1] = y2;
-
-		// x-axis rotation for direction vector
-		y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;
-		z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;
-		jointList[i].placement.direction[1] = y2;
-		jointList[i].placement.direction[2] = z2;
-
-		// x-axis rotation for up vector
-		y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;
-		z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;
-		jointList[i].placement.up[1] = y2;
-		jointList[i].placement.up[2] = z2;
-
-		// translate to position in model
-		jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
-		jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
-		jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
-
-		// translate to position in model
-		jointList[i].placement.up[0] += jointList[i].placement.origin[0];
-		jointList[i].placement.up[1] += jointList[i].placement.origin[1];
-		jointList[i].placement.up[2] += jointList[i].placement.origin[2];
-	}
-
-	baseJoint = NUM_JOINTS_RAVEN;
-
-	for(i = stackSize/*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i)
-	{
-
-		rx = curRotation[i-1][0]*ANGLE_TO_RAD;
-		ry = curRotation[i-1][1]*ANGLE_TO_RAD;
-		rz = curRotation[i-1][2]*ANGLE_TO_RAD;
-
-		cx = cos(rx);
-		sx = sin(rx);
-
-		cy = cos(ry);
-		sy = sin(ry);
-
-		cz = cos(rz);
-		sz = sin(rz);
-
-		for(j = i-1; j < stackSize-1; ++j)
-		{
-			// y-axis rotation for origin
-			x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;
-			z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;
-			jointList[j].placement.origin[0] = x2;
-			jointList[j].placement.origin[2] = z2;
-
-			// y-axis rotation for direction
-			x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;
-			z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;
-			jointList[j].placement.direction[0] = x2;
-			jointList[j].placement.direction[2] = z2;
-
-			// y-axis rotation for up
-			x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;
-			z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;
-			jointList[j].placement.up[0] = x2;
-			jointList[j].placement.up[2] = z2;
-
-			// z-axis rotation for origin
-			x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;
-			y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;
-			jointList[j].placement.origin[0] = x2;
-			jointList[j].placement.origin[1] = y2;
-
-			// z-axis rotation for direction
-			x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;
-			y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;
-			jointList[j].placement.direction[0] = x2;
-			jointList[j].placement.direction[1] = y2;
-
-			// z-axis rotation for up
-			x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;
-			y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;
-			jointList[j].placement.up[0] = x2;
-			jointList[j].placement.up[1] = y2;
-
-			// x-axis rotation for origin
-			y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;
-			z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;
-			jointList[j].placement.origin[1] = y2;
-			jointList[j].placement.origin[2] = z2;
-
-			// x-axis rotation for direction vector
-			y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;
-			z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;
-			jointList[j].placement.direction[1] = y2;
-			jointList[j].placement.direction[2] = z2;
-
-			// x-axis rotation for up vector
-			y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;
-			z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;
-			jointList[j].placement.up[1] = y2;
-			jointList[j].placement.up[2] = z2;
-
-			if(curCorrespondingJoint[j+1] != -1)
-			{
-				// translate origin
-				jointList[j].placement.origin[0] += curTranslation[i-1][0];
-				jointList[j].placement.origin[1] += curTranslation[i-1][1];
-				jointList[j].placement.origin[2] += curTranslation[i-1][2];
-
-				// translate back to local coord
-				jointList[j].placement.direction[0] += curTranslation[i-1][0];
-				jointList[j].placement.direction[1] += curTranslation[i-1][1];
-				jointList[j].placement.direction[2] += curTranslation[i-1][2];
-
-				// translate back to local coord
-				jointList[j].placement.up[0] += curTranslation[i-1][0];
-				jointList[j].placement.up[1] += curTranslation[i-1][1];
-				jointList[j].placement.up[2] += curTranslation[i-1][2];
-			}
-		}
-	}
-}
-
-void LoadGlobals(char *fileName)
-{
-	FILE *file1;
-    int dot = '.';
-	char *dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-
-			LoadHRCGlobals(InputFileName);
-
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		Error("\n Could not open file '%s':\n"
-			"No HRC match.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRCGlobals(fileName);
-				return;
-			}
-		}
-
-		Error("Could not open file '%s':\n",fileName);
-	}
-}
-
-void LoadClusters(char *fileName, int **clusterList, int *num_verts, int skelType)
-{
-	FILE *file1;
-    int dot = '.';
-	char *dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-
-			LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);
-
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		Error("\n Could not open file '%s':\n"
-			"No HRC match.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRCClustered(fileName, clusterList, num_verts, skelType);
-				return;
-			}
-		}
-
-		Error("Could not open file '%s':\n",fileName);
-	}
-}
-
-void LoadJointList(char *fileName, QDataJoint_t *jointList, int skelType)
-{
-	FILE *file1;
-    int dot = '.';
-	char *dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-
-			LoadHRCJointList(InputFileName, jointList, skelType);
-
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		Error("\n Could not open file '%s':\n"
-			"No HRC.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRCJointList(fileName, jointList, skelType);
-
-				return;
-			}
-		}
-
-		Error("Could not open file '%s':\n",fileName);
-	}
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <assert.h>
+#include <math.h>
+#include "token.h"
+#include "joints.h"
+#include "angles.h"
+#include "inout.h"
+
+char *SKEL_ROOT_NAMES[] =
+{
+	"RAVEN_SPINE"
+};
+
+char *SKEL_NAMES[] =
+{
+	"RAVEN_WAIST1",
+	"RAVEN_WAIST2",
+	"RAVEN_NECK"
+};
+
+int NAME_OFFSETS[] =
+{
+	0
+};
+
+int numJointsForSkeleton[] = 
+{
+	NUM_JOINTS_RAVEN,
+	NUM_JOINTS_BOX
+};
+
+float g_scaling[3];
+float g_rotation[3];
+float g_translation[3];
+
+//==========================================================================
+//
+// LoadHRCClustered
+//
+//==========================================================================
+
+static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)
+{
+	int i, j;
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+
+	TK_Beyond(TK_CLUSTERS);
+
+	while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)
+	{
+		TK_Require(TK_STRING);
+
+		for( i = 0; i < numJointsForSkeleton[skelType]; ++i)
+		{
+			if(stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
+			{
+				i = -i + numJointsForSkeleton[skelType] - 1;
+
+				TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
+
+				num_verts[i+1] = tk_IntNumber;
+
+				clusterList[i] = (int *) SafeMalloc(num_verts[i+1]*sizeof(int), "LoadHRCClustered");
+				assert(clusterList[i]);
+				// currently this function is only called by LoadTriangleListClustered, which in turn is only
+				// called by Cmd_Base in qdata.  This is where the only call to free for this memory is being made.
+
+				TK_Beyond(TK_LBRACE);
+
+				for(j = 0; j < num_verts[i+1]; ++j)
+				{
+					TK_Require(TK_INTNUMBER);
+					clusterList[i][j] = tk_IntNumber;
+					TK_Fetch();
+				}
+
+				break;
+			}
+		}
+	}
+
+	num_verts[0] = numJointsForSkeleton[skelType];
+}
+
+static void LoadHRCGlobals(char *fileName)
+{
+	int i;
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+	TK_Beyond(TK_MODEL);
+
+	TK_Beyond(TK_SCALING);
+	for(i = 0; i < 3; i++)
+	{
+		TK_Require(TK_FLOATNUMBER);
+		g_scaling[i] = tk_FloatNumber;
+		TK_Fetch();
+	}
+
+	TK_Beyond(TK_ROTATION);
+	for(i = 0; i < 3; i++)
+	{
+		TK_Require(TK_FLOATNUMBER);
+		g_rotation[i] = tk_FloatNumber;
+		TK_Fetch();
+	}
+
+	TK_Beyond(TK_TRANSLATION);
+	for(i = 0; i < 3; i++)
+	{
+		TK_Require(TK_FLOATNUMBER);
+		g_translation[i] = tk_FloatNumber;
+		TK_Fetch();
+	}
+}
+
+static void ParseVec3(vec3_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void ParseRotation3(vec3_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = -tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void ParseTranslation3(vec3_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void LoadHRCJointList(char *fileName, QDataJoint_t *jointList, int skelType)
+{
+#define MAX_STACK 64
+	int i, j;
+	vec3_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
+	int curCorrespondingJoint[MAX_STACK];
+	int currentStack = 0, stackSize;
+	int baseJoint;
+	float cx, sx, cy, sy, cz, sz;
+	float rx, ry, rz;
+	float x2, y2, z2;
+
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+
+	TK_Beyond(TK_MODEL);
+	TK_Beyond(TK_MODEL);
+
+/*	while(1)
+	{
+		TK_Beyond(TK_MODEL);
+		TK_BeyondRequire(TK_NAME, TK_STRING);
+
+		if(_stricmp(tk_String, SKEL_ROOT_NAMES[skelType]) == 0)
+			break;
+	}*/
+
+	TK_Beyond(TK_SCALING);
+
+	ParseVec3(curScale[currentStack]);
+
+	TK_Beyond(TK_ROTATION);
+
+	ParseRotation3(curRotation[currentStack]);
+
+	TK_Beyond(TK_TRANSLATION);
+
+	ParseVec3(curTranslation[currentStack]);
+
+	// account for global model translation
+	curTranslation[currentStack][1] += g_translation[0];
+	curTranslation[currentStack][2] += g_translation[1];
+	curTranslation[currentStack][0] += g_translation[2];
+
+	++currentStack;
+
+	for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
+	{
+		while(1)
+		{
+			TK_Beyond(TK_MODEL);
+
+//			TK_BeyondRequire(TK_NAME, TK_STRING);
+
+//			if(_stricmp(tk_String, SKEL_NAMES[NAME_OFFSETS[skelType]+i]) == 0)
+				break;
+
+			TK_Beyond(TK_SCALING);
+
+			ParseVec3(curScale[currentStack]);
+
+			TK_Beyond(TK_ROTATION);
+
+			ParseRotation3(curRotation[currentStack]);
+
+			TK_Beyond(TK_TRANSLATION);
+
+			ParseVec3(curTranslation[currentStack]);
+
+			curCorrespondingJoint[currentStack] = -1;
+
+			++currentStack;
+		}
+
+		TK_Beyond(TK_SCALING);
+
+		ParseVec3(curScale[currentStack]);
+
+		TK_Beyond(TK_ROTATION);
+
+		ParseRotation3(curRotation[currentStack]);
+
+		jointList[i].rotation[1] = curRotation[currentStack][1];
+		jointList[i].rotation[2] = curRotation[currentStack][2];
+		jointList[i].rotation[0] = curRotation[currentStack][0];
+
+		TK_Beyond(TK_TRANSLATION);
+
+		ParseVec3(curTranslation[currentStack]);
+
+		jointList[i].placement.origin[1] = curTranslation[currentStack][1];
+		jointList[i].placement.origin[2] = curTranslation[currentStack][2];
+		jointList[i].placement.origin[0] = curTranslation[currentStack][0];
+
+		jointList[i].placement.direction[1] = 7.5;
+		jointList[i].placement.direction[2] = 0.0;
+		jointList[i].placement.direction[0] = 0.0;
+
+		jointList[i].placement.up[1] = 0.0;
+		jointList[i].placement.up[2] = 7.5;
+		jointList[i].placement.up[0] = 0.0;
+
+		curCorrespondingJoint[currentStack] = i;
+
+		++currentStack;
+	}
+
+	stackSize = currentStack;
+
+	for(i = 0; i < NUM_JOINTS_RAVEN; ++i)
+	{
+		rx = jointList[i].rotation[0]*ANGLE_TO_RAD;
+		ry = jointList[i].rotation[1]*ANGLE_TO_RAD;
+		rz = jointList[i].rotation[2]*ANGLE_TO_RAD;
+
+		cx = cos(rx);
+		sx = sin(rx);
+
+		cy = cos(ry);
+		sy = sin(ry);
+
+		cz = cos(rz);
+		sz = sin(rz);
+
+		// y-axis rotation for direction
+		x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;
+		z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;
+		jointList[i].placement.direction[0] = x2;
+		jointList[i].placement.direction[2] = z2;
+
+		// y-axis rotation for up
+		x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;
+		z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;
+		jointList[i].placement.up[0] = x2;
+		jointList[i].placement.up[2] = z2;
+
+		// z-axis rotation for direction
+		x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;
+		y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;
+		jointList[i].placement.direction[0] = x2;
+		jointList[i].placement.direction[1] = y2;
+
+		// z-axis rotation for up
+		x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;
+		y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;
+		jointList[i].placement.up[0] = x2;
+		jointList[i].placement.up[1] = y2;
+
+		// x-axis rotation for direction vector
+		y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;
+		z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;
+		jointList[i].placement.direction[1] = y2;
+		jointList[i].placement.direction[2] = z2;
+
+		// x-axis rotation for up vector
+		y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;
+		z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;
+		jointList[i].placement.up[1] = y2;
+		jointList[i].placement.up[2] = z2;
+
+		// translate to position in model
+		jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
+		jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
+		jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
+
+		// translate to position in model
+		jointList[i].placement.up[0] += jointList[i].placement.origin[0];
+		jointList[i].placement.up[1] += jointList[i].placement.origin[1];
+		jointList[i].placement.up[2] += jointList[i].placement.origin[2];
+	}
+
+	baseJoint = NUM_JOINTS_RAVEN;
+
+	for(i = stackSize/*NUM_JOINTS_RAVEN*/ - 1; i > 0; --i)
+	{
+
+		rx = curRotation[i-1][0]*ANGLE_TO_RAD;
+		ry = curRotation[i-1][1]*ANGLE_TO_RAD;
+		rz = curRotation[i-1][2]*ANGLE_TO_RAD;
+
+		cx = cos(rx);
+		sx = sin(rx);
+
+		cy = cos(ry);
+		sy = sin(ry);
+
+		cz = cos(rz);
+		sz = sin(rz);
+
+		for(j = i-1; j < stackSize-1; ++j)
+		{
+			// y-axis rotation for origin
+			x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;
+			z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;
+			jointList[j].placement.origin[0] = x2;
+			jointList[j].placement.origin[2] = z2;
+
+			// y-axis rotation for direction
+			x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;
+			z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;
+			jointList[j].placement.direction[0] = x2;
+			jointList[j].placement.direction[2] = z2;
+
+			// y-axis rotation for up
+			x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;
+			z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;
+			jointList[j].placement.up[0] = x2;
+			jointList[j].placement.up[2] = z2;
+
+			// z-axis rotation for origin
+			x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;
+			y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;
+			jointList[j].placement.origin[0] = x2;
+			jointList[j].placement.origin[1] = y2;
+
+			// z-axis rotation for direction
+			x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;
+			y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;
+			jointList[j].placement.direction[0] = x2;
+			jointList[j].placement.direction[1] = y2;
+
+			// z-axis rotation for up
+			x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;
+			y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;
+			jointList[j].placement.up[0] = x2;
+			jointList[j].placement.up[1] = y2;
+
+			// x-axis rotation for origin
+			y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;
+			z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;
+			jointList[j].placement.origin[1] = y2;
+			jointList[j].placement.origin[2] = z2;
+
+			// x-axis rotation for direction vector
+			y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;
+			z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;
+			jointList[j].placement.direction[1] = y2;
+			jointList[j].placement.direction[2] = z2;
+
+			// x-axis rotation for up vector
+			y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;
+			z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;
+			jointList[j].placement.up[1] = y2;
+			jointList[j].placement.up[2] = z2;
+
+			if(curCorrespondingJoint[j+1] != -1)
+			{
+				// translate origin
+				jointList[j].placement.origin[0] += curTranslation[i-1][0];
+				jointList[j].placement.origin[1] += curTranslation[i-1][1];
+				jointList[j].placement.origin[2] += curTranslation[i-1][2];
+
+				// translate back to local coord
+				jointList[j].placement.direction[0] += curTranslation[i-1][0];
+				jointList[j].placement.direction[1] += curTranslation[i-1][1];
+				jointList[j].placement.direction[2] += curTranslation[i-1][2];
+
+				// translate back to local coord
+				jointList[j].placement.up[0] += curTranslation[i-1][0];
+				jointList[j].placement.up[1] += curTranslation[i-1][1];
+				jointList[j].placement.up[2] += curTranslation[i-1][2];
+			}
+		}
+	}
+}
+
+void LoadGlobals(char *fileName)
+{
+	FILE *file1;
+    int dot = '.';
+	char *dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+
+			LoadHRCGlobals(InputFileName);
+
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		Error("\n Could not open file '%s':\n"
+			"No HRC match.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRCGlobals(fileName);
+				return;
+			}
+		}
+
+		Error("Could not open file '%s':\n",fileName);
+	}
+}
+
+void LoadClusters(char *fileName, int **clusterList, int *num_verts, int skelType)
+{
+	FILE *file1;
+    int dot = '.';
+	char *dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+
+			LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);
+
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		Error("\n Could not open file '%s':\n"
+			"No HRC match.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRCClustered(fileName, clusterList, num_verts, skelType);
+				return;
+			}
+		}
+
+		Error("Could not open file '%s':\n",fileName);
+	}
+}
+
+void LoadJointList(char *fileName, QDataJoint_t *jointList, int skelType)
+{
+	FILE *file1;
+    int dot = '.';
+	char *dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+
+			LoadHRCJointList(InputFileName, jointList, skelType);
+
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		Error("\n Could not open file '%s':\n"
+			"No HRC.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRCJointList(fileName, jointList, skelType);
+
+				return;
+			}
+		}
+
+		Error("Could not open file '%s':\n",fileName);
+	}
+}
+
diff --git a/tools/quake2/qdata_heretic2/jointed.h b/tools/quake2/qdata_heretic2/jointed.h
index 6907a2d8..ffd82631 100644
--- a/tools/quake2/qdata_heretic2/jointed.h
+++ b/tools/quake2/qdata_heretic2/jointed.h
@@ -1,35 +1,35 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _JOINTED_H
-#define _JOINTED_H
-
-#include "joints.h"
-
-void LoadGlobals(char *fileName);
-void LoadClusters(char *fileName, int **clusterList, int *num_verts, int skel_type);
-void LoadJointList(char *fileName, struct QDataJoint_s *jointList, int num_verts);
-
-#define NUM_CLUSTERS 8
-
-#define NOT_JOINTED -1
-
-#endif //_JOINTED_H
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _JOINTED_H
+#define _JOINTED_H
+
+#include "joints.h"
+
+void LoadGlobals(char *fileName);
+void LoadClusters(char *fileName, int **clusterList, int *num_verts, int skel_type);
+void LoadJointList(char *fileName, struct QDataJoint_s *jointList, int num_verts);
+
+#define NUM_CLUSTERS 8
+
+#define NOT_JOINTED -1
+
+#endif //_JOINTED_H
diff --git a/tools/quake2/qdata_heretic2/joints.h b/tools/quake2/qdata_heretic2/joints.h
index e489114e..046bebdf 100644
--- a/tools/quake2/qdata_heretic2/joints.h
+++ b/tools/quake2/qdata_heretic2/joints.h
@@ -1,144 +1,144 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef JOINTS_H
-#define JOINTS_H
-
-#ifdef _HERETIC2_
-#include "angles.h"
-#endif
-
-//typedef float vec3_t[3];
-//typedef unsigned char byte;
-
-#ifndef _WIN32
-#define stricmp strcasecmp
-#define strcmpi strcasecmp
-#endif
-
-typedef struct Placement_s
-{
-	vec3_t origin;
-	vec3_t direction;
-	vec3_t up;
-} Placement_t;
-
-#if 1
-typedef struct QDataJoint_s
-{
-	Placement_t placement;
-	vec3_t		rotation;
-} QDataJoint_t;
-#endif
-
-typedef struct ArrayedListNode_s
-{
-	int data;
-	int next;
-	int inUse;
-} ArrayedListNode_t;
-
-#define ARRAYEDLISTNODE_NULL -1
-
-typedef struct JointAngles_s
-{
-	float angles[3];
-	int children;
-	int created;
-} JointAngles_t;
-
-typedef struct JointAngles2_s
-{
-	float angles[3];
-	int children;
-	int changed[3];
-	int inUse;
-} JointAngles2_t;
-
-#define MAX_MODELJOINTS			256
-#define MAX_MODELJOINTNODES		255
-
-extern JointAngles_t jointAngles[MAX_MODELJOINTS];
-extern JointAngles2_t jointAngles2[MAX_MODELJOINTS];
-
-extern ArrayedListNode_t jointAngleNodes[MAX_MODELJOINTNODES];
-
-// Skeletal structures enums
-enum {
-	SKEL_RAVEN = 0,
-	SKEL_BOX,
-	NUM_SKELETONS
-};
-
-// Raven Skeletal structures enums
-enum {
-	RAVEN_WAIST1 = 0,
-	RAVEN_WAIST2 = 1,
-	RAVEN_HEAD = 2,
-	NUM_JOINTS_RAVEN
-};
-
-// Box Skeletal structures enums
-enum {
-	BOX_CENTER = 0,
-	NUM_JOINTS_BOX
-};
-
-extern int numJointsForSkeleton[];
-extern char *RAVEN_SKEL_NAMES[];
-
-#define J_NEW_SKELETON		0x00001000
-#define J_YAW_CHANGED		0x00002000
-#define J_PITCH_CHANGED		0x00004000
-#define J_ROLL_CHANGED		0x00008000
-#define MAX_JOINTS			0x00000fff
-/*
-inline int GetFreeNode(ArrayedListNode_t *nodeArray, int max)
-{	// yeah, I know this is a sucky, inefficient way to do this, but I didn't feel like taking the time to write a real resource manager in C
-	int i;
-
-	for(i = 0; i < max; ++i)
-	{
-		if(!nodeArray[i].inUse)
-		{
-			nodeArray[i].inUse = 1;
-			return i;
-		}
-	}
-
-	assert(0);
-	return -1;
-}
-
-inline void FreeNode(ArrayedListNode_t *nodeArray, int index)
-{
-	nodeArray[index].inUse = 0;
-}
-*/
-int CreateSkeleton(int structure);
-void CreateSkeletonAtIndex(int structure, int index);
-void FreeSkeleton(int structure, int index);
-void SetJointAngle(int jointIndex, int angleIndex, float angle);
-float ModifyJointAngle(int jointIndex, int angleIndex, float deltaAngle);
-int ZeroJointAngle(int jointIndex, int angleIndex, float angVel);
-int ApplyAngVelToJoint(int jointIndex, int angleIndex, float angVel, float destAng);
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef JOINTS_H
+#define JOINTS_H
+
+#ifdef _HERETIC2_
+#include "angles.h"
+#endif
+
+//typedef float vec3_t[3];
+//typedef unsigned char byte;
+
+#ifndef _WIN32
+#define stricmp strcasecmp
+#define strcmpi strcasecmp
+#endif
+
+typedef struct Placement_s
+{
+	vec3_t origin;
+	vec3_t direction;
+	vec3_t up;
+} Placement_t;
+
+#if 1
+typedef struct QDataJoint_s
+{
+	Placement_t placement;
+	vec3_t		rotation;
+} QDataJoint_t;
+#endif
+
+typedef struct ArrayedListNode_s
+{
+	int data;
+	int next;
+	int inUse;
+} ArrayedListNode_t;
+
+#define ARRAYEDLISTNODE_NULL -1
+
+typedef struct JointAngles_s
+{
+	float angles[3];
+	int children;
+	int created;
+} JointAngles_t;
+
+typedef struct JointAngles2_s
+{
+	float angles[3];
+	int children;
+	int changed[3];
+	int inUse;
+} JointAngles2_t;
+
+#define MAX_MODELJOINTS			256
+#define MAX_MODELJOINTNODES		255
+
+extern JointAngles_t jointAngles[MAX_MODELJOINTS];
+extern JointAngles2_t jointAngles2[MAX_MODELJOINTS];
+
+extern ArrayedListNode_t jointAngleNodes[MAX_MODELJOINTNODES];
+
+// Skeletal structures enums
+enum {
+	SKEL_RAVEN = 0,
+	SKEL_BOX,
+	NUM_SKELETONS
+};
+
+// Raven Skeletal structures enums
+enum {
+	RAVEN_WAIST1 = 0,
+	RAVEN_WAIST2 = 1,
+	RAVEN_HEAD = 2,
+	NUM_JOINTS_RAVEN
+};
+
+// Box Skeletal structures enums
+enum {
+	BOX_CENTER = 0,
+	NUM_JOINTS_BOX
+};
+
+extern int numJointsForSkeleton[];
+extern char *RAVEN_SKEL_NAMES[];
+
+#define J_NEW_SKELETON		0x00001000
+#define J_YAW_CHANGED		0x00002000
+#define J_PITCH_CHANGED		0x00004000
+#define J_ROLL_CHANGED		0x00008000
+#define MAX_JOINTS			0x00000fff
+/*
+inline int GetFreeNode(ArrayedListNode_t *nodeArray, int max)
+{	// yeah, I know this is a sucky, inefficient way to do this, but I didn't feel like taking the time to write a real resource manager in C
+	int i;
+
+	for(i = 0; i < max; ++i)
+	{
+		if(!nodeArray[i].inUse)
+		{
+			nodeArray[i].inUse = 1;
+			return i;
+		}
+	}
+
+	assert(0);
+	return -1;
+}
+
+inline void FreeNode(ArrayedListNode_t *nodeArray, int index)
+{
+	nodeArray[index].inUse = 0;
+}
+*/
+int CreateSkeleton(int structure);
+void CreateSkeletonAtIndex(int structure, int index);
+void FreeSkeleton(int structure, int index);
+void SetJointAngle(int jointIndex, int angleIndex, float angle);
+float ModifyJointAngle(int jointIndex, int angleIndex, float deltaAngle);
+int ZeroJointAngle(int jointIndex, int angleIndex, float angVel);
+int ApplyAngVelToJoint(int jointIndex, int angleIndex, float angVel, float destAng);
+
+#endif
diff --git a/tools/quake2/qdata_heretic2/models.c b/tools/quake2/qdata_heretic2/models.c
index d594cafe..5ae30a15 100644
--- a/tools/quake2/qdata_heretic2/models.c
+++ b/tools/quake2/qdata_heretic2/models.c
@@ -1,2050 +1,2050 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "qdata.h"
-#include <assert.h>
-#include "jointed.h"
-#include "fmodel.h"
-
-//=================================================================
-
-typedef struct 
-{
-	int		numnormals;
-	vec3_t	normalsum;
-} vertexnormals_t;
-
-typedef struct
-{
-	vec3_t		v;
-	int			lightnormalindex;
-} trivert_t;
-
-typedef struct
-{
-	vec3_t		mins, maxs;
-	char		name[16];
-	trivert_t	v[MAX_VERTS];
-	QDataJoint_t	joints[NUM_CLUSTERS]; // ,this
-} frame_t;
-
-// ,and all of this should get out of here, need to use new stuff in fmodels instead
-
-typedef struct IntListNode_s
-{
-	int data;
-	struct IntListNode_s *next;
-} IntListNode_t;  // gaak
-
-typedef struct
-{
-	float		scale[3];	// multiply byte verts by this
-	float		translate[3];	// then add this
-} PartialAliasFrame_t;
-
-int jointed;
-int clustered;
-
-int *clusters[NUM_CLUSTERS];
-IntListNode_t *vertLists[NUM_CLUSTERS];
-int		num_verts[NUM_CLUSTERS + 1];
-int		new_num_verts[NUM_CLUSTERS + 1];
-
-// end that
-
-//================================================================
-
-frame_t		g_frames[MAX_FRAMES];
-//frame_t		*g_frames;
-
-static dmdl_t		model;
-
-
-float		scale_up;			// set by $scale
-vec3_t		adjust;				// set by $origin
-int			g_fixedwidth, g_fixedheight;	// set by $skinsize
-
-
-//
-// base frame info
-//
-dstvert_t	base_st[MAX_VERTS];
-dtriangle_t	triangles[MAX_TRIANGLES];
-
-static int			triangle_st[MAX_TRIANGLES][3][2];
-
-// the command list holds counts, s/t values, and xyz indexes
-// that are valid for every frame
-int			commands[16384];
-int			numcommands;
-int			numglverts;
-int			used[MAX_TRIANGLES];
-
-char		g_skins[MAX_MD2SKINS][64];
-
-char		cdarchive[1024];
-char		cdpartial[1024];
-char		cddir[1024];
-
-char		modelname[64];	// empty unless $modelname issued (players)
-
-extern 	char		*g_outputDir;
-
-#define NUMVERTEXNORMALS	162
-
-float	avertexnormals[NUMVERTEXNORMALS][3] = 
-{
-	#include "anorms.h"
-};
-
-unsigned char pic[SKINPAGE_HEIGHT*SKINPAGE_WIDTH], pic_palette[768];
-
-FILE	*headerouthandle = NULL;
-
-//==============================================================
-
-/*
-===============
-ClearModel
-===============
-*/
-static void ClearModel (void)
-{
-	memset (&model, 0, sizeof(model));
-
-	modelname[0] = 0;
-	jointed = NOT_JOINTED;
-	clustered = 0;
-	scale_up = 1.0;	
-	VectorCopy (vec3_origin, adjust);
-	g_fixedwidth = g_fixedheight = 0;
-	g_skipmodel = false;
-}
-
-
-void H_printf(char *fmt, ...)
-{
-	va_list argptr;
-	char	name[1024];
-
-	if (!headerouthandle)
-	{
-		sprintf (name, "%s/tris.h", cddir);
-		headerouthandle = SafeOpenWrite (name);
-		fprintf(headerouthandle, "// %s\n\n", cddir);
-		fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n");
-	}
-
-	va_start (argptr, fmt);
-	vfprintf (headerouthandle, fmt, argptr);
-	va_end (argptr);
-}
-
-#if 1
-/*
-============
-WriteModelFile
-============
-*/
-void WriteCommonModelFile (FILE *modelouthandle, PartialAliasFrame_t *outFrames)
-{
-	int				i;
-	dmdl_t			modeltemp;
-	int				j, k;
-	frame_t			*in;
-	daliasframe_t	*out;
-	byte			buffer[MAX_VERTS*4+128];
-	float			v;
-	int				c_on, c_off;
-
-	model.version = ALIAS_VERSION;
-	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
-	model.num_glcmds = numcommands;
-	model.ofs_skins = sizeof(dmdl_t);
-	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
-	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
-	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
-	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
-	model.ofs_end = model.ofs_glcmds + model.num_glcmds*sizeof(int);
-	//
-	// write out the model header
-	//
-	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
-		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
-
-	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
-
-	//
-	// write out the skin names
-	//
-	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
-
-	//
-	// write out the texture coordinates
-	//
-	c_on = c_off = 0;
-	for (i=0 ; i<model.num_st ; i++)
-	{
-		base_st[i].s = LittleShort (base_st[i].s);
-		base_st[i].t = LittleShort (base_st[i].t);
-	}
-
-	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
-
-	//
-	// write out the triangles
-	//
-	for (i=0 ; i<model.num_tris ; i++)
-	{
-		int			j;
-		dtriangle_t	tri;
-
-		for (j=0 ; j<3 ; j++)
-		{
-			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
-			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
-		}
-
-		SafeWrite (modelouthandle, &tri, sizeof(tri));
-	}
-
-	//
-	// write out the frames
-	//
-	for (i=0 ; i<model.num_frames ; i++)
-	{
-		in = &g_frames[i];
-		out = (daliasframe_t *)buffer;
-
-		strcpy (out->name, in->name);
-		for (j=0 ; j<3 ; j++)
-		{
-			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
-			out->translate[j] = in->mins[j];
-
-			if(outFrames)
-			{
-				outFrames[i].scale[j] = out->scale[j];
-				outFrames[i].translate[j] = out->translate[j];
-			}
-		}
-
-		for (j=0 ; j<model.num_xyz ; j++)
-		{
-		// all of these are byte values, so no need to deal with endianness
-			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
-
-			for (k=0 ; k<3 ; k++)
-			{
-			// scale to byte values & min/max check
-				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
-
-			// clamp, so rounding doesn't wrap from 255.6 to 0
-				if (v > 255.0)
-					v = 255.0;
-				if (v < 0)
-					v = 0;
-				out->verts[j].v[k] = v;
-			}
-		}
-
-		for (j=0 ; j<3 ; j++)
-		{
-			out->scale[j] = LittleFloat (out->scale[j]);
-			out->translate[j] = LittleFloat (out->translate[j]);
-		}
-
-		SafeWrite (modelouthandle, out, model.framesize);
-	}
-
-	//
-	// write out glcmds
-	//
-	SafeWrite (modelouthandle, commands, numcommands*4);
-}
-
-/*
-============
-WriteModelFile
-============
-*/
-void WriteModelFile (FILE *modelouthandle)
-{
-	model.ident = IDALIASHEADER;
-
-	WriteCommonModelFile(modelouthandle, NULL);
-}
-
-/*
-============
-WriteJointedModelFile
-============
-*/
-void WriteJointedModelFile (FILE *modelouthandle)
-{
-	int				i;
-	int				j, k;
-	frame_t			*in;
-	float			v;
-	IntListNode_t	*current, *toFree;
-	PartialAliasFrame_t outFrames[MAX_FRAMES];
-
-	model.ident = IDJOINTEDALIASHEADER;
-	
-	WriteCommonModelFile(modelouthandle, outFrames);
-
-	// Skeletal Type
-	SafeWrite(modelouthandle, &jointed, sizeof(int));
-
-	// number of joints
-	SafeWrite(modelouthandle, &numJointsForSkeleton[jointed], sizeof(int));
-
-	// number of verts in each cluster
-	SafeWrite(modelouthandle, &new_num_verts[1], sizeof(int)*numJointsForSkeleton[jointed]);
-
-	// cluster verts
-	for(i = 0; i < new_num_verts[0]; ++i)
-	{
-		current = vertLists[i];
-		while(current)
-		{
-			SafeWrite (modelouthandle, &current->data, sizeof(int));
-			toFree = current;
-			current = current->next;
-			free(toFree);  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
-		}
-	}
-
-	for (i=0 ; i<model.num_frames ; i++)
-	{
-		in = &g_frames[i];
-
-		for (j = 0 ; j < new_num_verts[0]; ++j)
-		{
-			for (k=0 ; k<3 ; k++)
-			{
-				// scale to byte values & min/max check
-				v = Q_rint ( (in->joints[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-				// clamp, so rounding doesn't wrap from 255.6 to 0
-				if (v > 255.0)
-				{
-					v = 255.0;
-				}
-
-				if (v < 0)
-				{
-					v = 0;
-				}
-
-				// write out origin as a float (there's only a few per model, so it's not really 
-				// a size issue)
-				SafeWrite (modelouthandle, &v, sizeof(float));
-			}
-
-			for (k=0 ; k<3 ; k++)
-			{
-				v = Q_rint ( (in->joints[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-				// clamp, so rounding doesn't wrap from 255.6 to 0
-				if (v > 255.0)
-				{
-					v = 255.0;
-				}
-
-				if (v < 0)
-				{
-					v = 0;
-				}
-
-				// write out origin as a float (there's only a few per model, so it's not really 
-				// a size issue)
-				SafeWrite (modelouthandle, &v, sizeof(float));
-			}
-
-			for (k=0 ; k<3 ; k++)
-			{
-				v = Q_rint ( (in->joints[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
-
-				// clamp, so rounding doesn't wrap from 255.6 to 0
-				if (v > 255.0)
-				{
-					v = 255.0;
-				}
-
-				if (v < 0)
-				{
-					v = 0;
-				}
-
-				// write out origin as a float (there's only a few per model, so it's not really 
-				// a size issue)
-				SafeWrite (modelouthandle, &v, sizeof(float));
-			}
-		}
-	}
-}
-#else
-/*
-============
-WriteModelFile
-============
-*/
-static void WriteModelFile (FILE *modelouthandle)
-{
-	int				i;
-	dmdl_t			modeltemp;
-	int				j, k;
-	frame_t			*in;
-	daliasframe_t	*out;
-	byte			buffer[MAX_VERTS*4+128];
-	float			v;
-	int				c_on, c_off;
-
-	model.ident = IDALIASHEADER;
-	model.version = ALIAS_VERSION;
-	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
-	model.num_glcmds = numcommands;
-	model.ofs_skins = sizeof(dmdl_t);
-	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
-	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
-	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
-	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
-	model.ofs_end = model.ofs_glcmds + model.num_glcmds*4;
-
-	//
-	// write out the model header
-	//
-	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
-		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
-
-	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
-
-	//
-	// write out the skin names
-	//
-	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
-
-	//
-	// write out the texture coordinates
-	//
-	c_on = c_off = 0;
-	for (i=0 ; i<model.num_st ; i++)
-	{
-		base_st[i].s = LittleShort (base_st[i].s);
-		base_st[i].t = LittleShort (base_st[i].t);
-	}
-
-	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
-
-	//
-	// write out the triangles
-	//
-	for (i=0 ; i<model.num_tris ; i++)
-	{
-		int			j;
-		dtriangle_t	tri;
-
-		for (j=0 ; j<3 ; j++)
-		{
-			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
-			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
-		}
-
-		SafeWrite (modelouthandle, &tri, sizeof(tri));
-	}
-
-	//
-	// write out the frames
-	//
-	for (i=0 ; i<model.num_frames ; i++)
-	{
-		in = &g_frames[i];
-		out = (daliasframe_t *)buffer;
-
-		strcpy (out->name, in->name);
-		for (j=0 ; j<3 ; j++)
-		{
-			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
-			out->translate[j] = in->mins[j];
-		}
-
-		for (j=0 ; j<model.num_xyz ; j++)
-		{
-		// all of these are byte values, so no need to deal with endianness
-			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
-
-			for (k=0 ; k<3 ; k++)
-			{
-			// scale to byte values & min/max check
-				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
-
-			// clamp, so rounding doesn't wrap from 255.6 to 0
-				if (v > 255.0)
-					v = 255.0;
-				if (v < 0)
-					v = 0;
-				out->verts[j].v[k] = v;
-			}
-		}
-
-		for (j=0 ; j<3 ; j++)
-		{
-			out->scale[j] = LittleFloat (out->scale[j]);
-			out->translate[j] = LittleFloat (out->translate[j]);
-		}
-
-		SafeWrite (modelouthandle, out, model.framesize);
-	}
-
-	//
-	// write out glcmds
-	//
-	SafeWrite (modelouthandle, commands, numcommands*4);
-}
-#endif
-
-/*
-===============
-FinishModel
-===============
-*/
-void FinishModel (void)
-{
-	FILE		*modelouthandle;
-	int			i;
-	char		name[1024];
-	
-	if (!model.num_frames)
-		return;
-	
-//
-// copy to release directory tree if doing a release build
-//
-	if (g_release)
-	{
-		if (modelname[0])
-			sprintf (name, "%s", modelname);
-		else
-			sprintf (name, "%s/tris.md2", cdpartial);
-		ReleaseFile (name);
-
-		for (i=0 ; i<model.num_skins ; i++)
-		{
-			ReleaseFile (g_skins[i]);
-		}
-		model.num_frames = 0;
-		return;
-	}
-	
-//
-// write the model output file
-//
-	if (modelname[0])
-		sprintf (name, "%s%s", g_outputDir, modelname);
-	else
-		sprintf (name, "%s/tris.md2", g_outputDir);
-	printf ("saving to %s\n", name);
-	CreatePath (name);
-	modelouthandle = SafeOpenWrite (name);
-
-#if 1
-	if(jointed != NOT_JOINTED)
-		WriteJointedModelFile(modelouthandle);
-	else
-#endif
-		WriteModelFile(modelouthandle);
-	
-	printf ("%3dx%3d skin\n", model.skinwidth, model.skinheight);
-	printf ("First frame boundaries:\n");
-	printf ("	minimum x: %3f\n", g_frames[0].mins[0]);
-	printf ("	maximum x: %3f\n", g_frames[0].maxs[0]);
-	printf ("	minimum y: %3f\n", g_frames[0].mins[1]);
-	printf ("	maximum y: %3f\n", g_frames[0].maxs[1]);
-	printf ("	minimum z: %3f\n", g_frames[0].mins[2]);
-	printf ("	maximum z: %3f\n", g_frames[0].maxs[2]);
-	printf ("%4d vertices\n", model.num_xyz);
-	printf ("%4d triangles\n", model.num_tris);
-	printf ("%4d frame\n", model.num_frames);
-	printf ("%4d glverts\n", numglverts);
-	printf ("%4d glcmd\n", model.num_glcmds);
-	printf ("%4d skins\n", model.num_skins);
-	printf ("file size: %d\n", (int)ftell (modelouthandle) );
-	printf ("---------------------\n");
-	
-	fclose (modelouthandle);
-
-	// finish writing header file
-	H_printf("\n");
-
-	// scale_up is usefull to allow step distances to be adjusted
-	H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
-
-	fclose (headerouthandle);
-	headerouthandle = NULL;
-}
-
-
-/*
-=================================================================
-
-ALIAS MODEL DISPLAY LIST GENERATION
-
-=================================================================
-*/
-
-int		strip_xyz[128];
-int		strip_st[128];
-int		strip_tris[128];
-int		stripcount;
-
-/*
-================
-StripLength
-================
-*/
-static int	StripLength (int starttri, int startv)
-{
-	int			m1, m2;
-	int			st1, st2;
-	int			j;
-	dtriangle_t	*last, *check;
-	int			k;
-
-	used[starttri] = 2;
-
-	last = &triangles[starttri];
-
-	strip_xyz[0] = last->index_xyz[(startv)%3];
-	strip_xyz[1] = last->index_xyz[(startv+1)%3];
-	strip_xyz[2] = last->index_xyz[(startv+2)%3];
-	strip_st[0] = last->index_st[(startv)%3];
-	strip_st[1] = last->index_st[(startv+1)%3];
-	strip_st[2] = last->index_st[(startv+2)%3];
-
-	strip_tris[0] = starttri;
-	stripcount = 1;
-
-	m1 = last->index_xyz[(startv+2)%3];
-	st1 = last->index_st[(startv+2)%3];
-	m2 = last->index_xyz[(startv+1)%3];
-	st2 = last->index_st[(startv+1)%3];
-
-	// look for a matching triangle
-nexttri:
-	for (j=starttri+1, check=&triangles[starttri+1]
-		; j<model.num_tris ; j++, check++)
-	{
-		for (k=0 ; k<3 ; k++)
-		{
-			if (check->index_xyz[k] != m1)
-				continue;
-			if (check->index_st[k] != st1)
-				continue;
-			if (check->index_xyz[ (k+1)%3 ] != m2)
-				continue;
-			if (check->index_st[ (k+1)%3 ] != st2)
-				continue;
-
-			// this is the next part of the fan
-
-			// if we can't use this triangle, this tristrip is done
-			if (used[j])
-				goto done;
-
-			// the new edge
-			if (stripcount & 1)
-			{
-				m2 = check->index_xyz[ (k+2)%3 ];
-				st2 = check->index_st[ (k+2)%3 ];
-			}
-			else
-			{
-				m1 = check->index_xyz[ (k+2)%3 ];
-				st1 = check->index_st[ (k+2)%3 ];
-			}
-
-			strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
-			strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
-			strip_tris[stripcount] = j;
-			stripcount++;
-
-			used[j] = 2;
-			goto nexttri;
-		}
-	}
-done:
-
-	// clear the temp used flags
-	for (j=starttri+1 ; j<model.num_tris ; j++)
-		if (used[j] == 2)
-			used[j] = 0;
-
-	return stripcount;
-}
-
-
-/*
-===========
-FanLength
-===========
-*/
-static int	FanLength (int starttri, int startv)
-{
-	int		m1, m2;
-	int		st1, st2;
-	int		j;
-	dtriangle_t	*last, *check;
-	int		k;
-
-	used[starttri] = 2;
-
-	last = &triangles[starttri];
-
-	strip_xyz[0] = last->index_xyz[(startv)%3];
-	strip_xyz[1] = last->index_xyz[(startv+1)%3];
-	strip_xyz[2] = last->index_xyz[(startv+2)%3];
-	strip_st[0] = last->index_st[(startv)%3];
-	strip_st[1] = last->index_st[(startv+1)%3];
-	strip_st[2] = last->index_st[(startv+2)%3];
-
-	strip_tris[0] = starttri;
-	stripcount = 1;
-
-	m1 = last->index_xyz[(startv+0)%3];
-	st1 = last->index_st[(startv+0)%3];
-	m2 = last->index_xyz[(startv+2)%3];
-	st2 = last->index_st[(startv+2)%3];
-
-
-	// look for a matching triangle
-nexttri:
-	for (j=starttri+1, check=&triangles[starttri+1] 
-		; j<model.num_tris ; j++, check++)
-	{
-		for (k=0 ; k<3 ; k++)
-		{
-			if (check->index_xyz[k] != m1)
-				continue;
-			if (check->index_st[k] != st1)
-				continue;
-			if (check->index_xyz[ (k+1)%3 ] != m2)
-				continue;
-			if (check->index_st[ (k+1)%3 ] != st2)
-				continue;
-
-			// this is the next part of the fan
-
-			// if we can't use this triangle, this tristrip is done
-			if (used[j])
-				goto done;
-
-			// the new edge
-			m2 = check->index_xyz[ (k+2)%3 ];
-			st2 = check->index_st[ (k+2)%3 ];
-
-			strip_xyz[stripcount+2] = m2;
-			strip_st[stripcount+2] = st2;
-			strip_tris[stripcount] = j;
-			stripcount++;
-
-			used[j] = 2;
-			goto nexttri;
-		}
-	}
-done:
-
-	// clear the temp used flags
-	for (j=starttri+1 ; j<model.num_tris ; j++)
-		if (used[j] == 2)
-			used[j] = 0;
-
-	return stripcount;
-}
-
-
-
-/*
-================
-BuildGlCmds
-
-Generate a list of trifans or strips
-for the model, which holds for all frames
-================
-*/
-static void BuildGlCmds (void)
-{
-	int		i, j, k;
-	int		startv;
-	float	s, t;
-	int		len, bestlen, besttype;
-	int		best_xyz[1024];
-	int		best_st[1024];
-	int		best_tris[1024];
-	int		type;
-
-	//
-	// build tristrips
-	//
-	numcommands = 0;
-	numglverts = 0;
-	memset (used, 0, sizeof(used));
-	for (i=0 ; i<model.num_tris ; i++)
-	{
-		// pick an unused triangle and start the trifan
-		if (used[i])
-			continue;
-
-		bestlen = 0;
-		for (type = 0 ; type < 2 ; type++)
-//	type = 1;
-		{
-			for (startv =0 ; startv < 3 ; startv++)
-			{
-				if (type == 1)
-					len = StripLength (i, startv);
-				else
-					len = FanLength (i, startv);
-				if (len > bestlen)
-				{
-					besttype = type;
-					bestlen = len;
-					for (j=0 ; j<bestlen+2 ; j++)
-					{
-						best_st[j] = strip_st[j];
-						best_xyz[j] = strip_xyz[j];
-					}
-					for (j=0 ; j<bestlen ; j++)
-						best_tris[j] = strip_tris[j];
-				}
-			}
-		}
-
-		// mark the tris on the best strip/fan as used
-		for (j=0 ; j<bestlen ; j++)
-			used[best_tris[j]] = 1;
-
-		if (besttype == 1)
-			commands[numcommands++] = (bestlen+2);
-		else
-			commands[numcommands++] = -(bestlen+2);
-
-		numglverts += bestlen+2;
-
-		for (j=0 ; j<bestlen+2 ; j++)
-		{
-			// emit a vertex into the reorder buffer
-			k = best_st[j];
-
-			// emit s/t coords into the commands stream
-			s = base_st[k].s;
-			t = base_st[k].t;
-
-			s = (s + 0.5) / model.skinwidth;
-			t = (t + 0.5) / model.skinheight;
-
-			*(float *)&commands[numcommands++] = s;
-			*(float *)&commands[numcommands++] = t;
-			*(int *)&commands[numcommands++] = best_xyz[j];
-		}
-	}
-
-	commands[numcommands++] = 0;		// end of list marker
-}
-
-
-/*
-===============================================================
-
-BASE FRAME SETUP
-
-===============================================================
-*/
-
-/*
-============
-BuildST
-
-Builds the triangle_st array for the base frame and
-model.skinwidth / model.skinheight
-
-  FIXME: allow this to be loaded from a file for
-  arbitrary mappings
-============
-*/
-#if 0
-static void OldBuildST (triangle_t *ptri, int numtri)
-{
-	int			i, j;
-	int			width, height, iwidth, iheight, swidth;
-	float		basex, basey;
-	float		s_scale, t_scale;
-	float		scale;
-	vec3_t		mins, maxs;
-	float		*pbasevert;
-	vec3_t		vtemp1, vtemp2, normal;
-
-	//
-	// find bounds of all the verts on the base frame
-	//
-	ClearBounds (mins, maxs);
-	
-	for (i=0 ; i<numtri ; i++)
-		for (j=0 ; j<3 ; j++)
-			AddPointToBounds (ptri[i].verts[j], mins, maxs);
-	
-	for (i=0 ; i<3 ; i++)
-	{
-		mins[i] = floor(mins[i]);
-		maxs[i] = ceil(maxs[i]);
-	}
-	
-	width = maxs[0] - mins[0];
-	height = maxs[2] - mins[2];
-
-	if (!g_fixedwidth)
-	{	// old style
-		scale = 8;
-		if (width*scale >= 150)
-			scale = 150.0 / width;	
-		if (height*scale >= 190)
-			scale = 190.0 / height;
-
-		s_scale = t_scale = scale;
-
-		iwidth = ceil(width*s_scale);
-		iheight = ceil(height*t_scale);
-
-		iwidth += 4;
-		iheight += 4;
-	}
-	else
-	{	// new style
-		iwidth = g_fixedwidth / 2;
-		iheight = g_fixedheight;
-
-		s_scale = (float)(iwidth-4) / width;
-		t_scale = (float)(iheight-4) / height;
-	}
-
-//
-// determine which side of each triangle to map the texture to
-//
-	for (i=0 ; i<numtri ; i++)
-	{
-		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-		CrossProduct (vtemp1, vtemp2, normal);
-
-		if (normal[1] > 0)
-		{
-			basex = iwidth + 2;
-		}
-		else
-		{
-			basex = 2;
-		}
-		basey = 2;
-		
-		for (j=0 ; j<3 ; j++)
-		{
-			pbasevert = ptri[i].verts[j];
-
-			triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
-			triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
-		}
-	}
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-	swidth = iwidth*2;
-	model.skinwidth = (swidth + 3) & ~3;
-	model.skinheight = iheight;
-}
-#endif
-
-//==========================================================================
-//
-// DrawScreen
-//
-//==========================================================================
-
-void DrawScreen(float s_scale, float t_scale, float iwidth, float iheight)
-{
-	int i;
-	byte *scrpos;
-	char buffer[256];
-
-	// Divider
-	scrpos = &pic[(INFO_Y-2)*SKINPAGE_WIDTH];
-	for(i = 0; i < SKINPAGE_WIDTH; i++)
-	{
-		*scrpos++ = 255;
-	}
-
-	sprintf(buffer, "GENSKIN:  ");
-	DrawTextChar(16, INFO_Y, buffer);
-	
-	sprintf(buffer, "( %03d * %03d )   SCALE %f %f, SKINWIDTH %d,"
-		" SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth*2, (int)iheight);
-	DrawTextChar(80, INFO_Y, buffer);
-}
-
-/*
-============
-BuildST
-
-Builds the triangle_st array for the base frame and
-model.skinwidth / model.skinheight
-
-  FIXME: allow this to be loaded from a file for
-  arbitrary mappings
-============
-*/
-void BuildST (triangle_t *ptri, int numtri, qboolean DrawSkin)
-{
-	int			i, j;
-	int			width, height, iwidth, iheight, swidth;
-	float		basex, basey;
-	float		scale;
-	vec3_t		mins, maxs;
-	float		*pbasevert;
-	vec3_t		vtemp1, vtemp2, normal;
-	float		s_scale, t_scale;
-	float		scWidth;
-	float		scHeight;
-
-	//
-	// find bounds of all the verts on the base frame
-	//
-	ClearBounds (mins, maxs);
-	
-	for (i=0 ; i<numtri ; i++)
-		for (j=0 ; j<3 ; j++)
-			AddPointToBounds (ptri[i].verts[j], mins, maxs);
-	
-	for (i=0 ; i<3 ; i++)
-	{
-		mins[i] = floor(mins[i]);
-		maxs[i] = ceil(maxs[i]);
-	}
-	
-	width = maxs[0] - mins[0];
-	height = maxs[2] - mins[2];
-
-
-	scWidth = (ScaleWidth/2)*SCALE_ADJUST_FACTOR;
-	scHeight = ScaleHeight*SCALE_ADJUST_FACTOR;
-
-	scale = scWidth/width;
-
-	if(height*scale >= scHeight)
-	{
-		scale = scHeight/height;
-	}
-
-	iwidth = ceil(width*scale)+4;
-	iheight = ceil(height*scale)+4;
-
-	s_scale = (float)(iwidth-4) / width;
-	t_scale = (float)(iheight-4) / height;
-	t_scale = s_scale;
-
-	if (DrawSkin)
-		DrawScreen(s_scale, t_scale, iwidth, iheight);
-
-
-/*	if (!g_fixedwidth)
-	{	// old style
-		scale = 8;
-		if (width*scale >= 150)
-			scale = 150.0 / width;	
-		if (height*scale >= 190)
-			scale = 190.0 / height;
-
-		s_scale = t_scale = scale;
-
-		iwidth = ceil(width*s_scale);
-		iheight = ceil(height*t_scale);
-
-		iwidth += 4;
-		iheight += 4;
-	}
-	else
-	{	// new style
-		iwidth = g_fixedwidth / 2;
-		iheight = g_fixedheight;
-
-		s_scale = (float)(iwidth-4) / width;
-		t_scale = (float)(iheight-4) / height;
-	}*/
-
-//
-// determine which side of each triangle to map the texture to
-//
-	for (i=0 ; i<numtri ; i++)
-	{
-		if (ptri[i].HasUV)
-		{
-			for (j=0 ; j<3 ; j++)
-			{
-				triangle_st[i][j][0] = Q_rint(ptri[i].uv[j][0]*iwidth);
-				triangle_st[i][j][1] = Q_rint((1.0f-ptri[i].uv[j][1])*iheight);
-			}
-		}
-		else
-		{
-			VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-			VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-			CrossProduct (vtemp1, vtemp2, normal);
-
-			if (normal[1] > 0)
-			{
-				basex = iwidth + 2;
-			}
-			else
-			{
-				basex = 2;
-			}
-			basey = 2;
-			
-			for (j=0 ; j<3 ; j++)
-			{
-				pbasevert = ptri[i].verts[j];
-
-				triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
-				triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
-			}
-		}
-
-		DrawLine(triangle_st[i][0][0], triangle_st[i][0][1],
-			triangle_st[i][1][0], triangle_st[i][1][1]);
-		DrawLine(triangle_st[i][1][0], triangle_st[i][1][1],
-			triangle_st[i][2][0], triangle_st[i][2][1]);
-		DrawLine(triangle_st[i][2][0], triangle_st[i][2][1],
-			triangle_st[i][0][0], triangle_st[i][0][1]); 
-	}
-
-// make the width a multiple of 4; some hardware requires this, and it ensures
-// dword alignment for each scan
-
-	swidth = iwidth*2;
-	model.skinwidth = (swidth + 3) & ~3;
-	model.skinheight = iheight;
-}
-
-
-static void ReplaceClusterIndex(int newIndex, int oldindex, int **clusters, 
-	IntListNode_t **vertLists, int *num_verts, int *new_num_verts)
-{
-	int i, j;
-	IntListNode_t *next;
-
-	for(j = 0; j < num_verts[0]; ++j)
-	{
-		for(i = 0; i < num_verts[j+1]; ++i)
-		{
-			if(clusters[j][i] == oldindex)
-			{
-				++new_num_verts[j+1];
-
-				next = vertLists[j];
-
-				vertLists[j] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "ReplaceClusterIndex");
-				// Currently freed in WriteJointedModelFile only
-
-				vertLists[j]->data = newIndex;
-				vertLists[j]->next = next;
-			}
-		}
-	}
-}
-
-/*
-=================
-Cmd_Base
-=================
-*/
-void Cmd_Base (void)
-{
-	vec3_t		base_xyz[MAX_VERTS];
-	triangle_t	*ptri;
-	int			i, j, k;
-#if 1
-#else
-	int		time1;
-#endif
-	char	file1[1024];
-	char	file2[1024];
-
-	GetScriptToken (false);
-
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	printf ("---------------------\n");
-#if 1
-	sprintf (file1, "%s/%s", cdpartial, token);
-	printf ("%s  ", file1);
-
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s", cddir, token);
-#else
-	sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
-	printf ("%s\n", file1);
-
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s.%s", cddir, token, trifileext);
-
-	time1 = FileTime (file1);
-	if (time1 == -1)
-		Error ("%s doesn't exist", file1);
-#endif
-//
-// load the base triangles
-//
-	if (do3ds)
-		Load3DSTriangleList (file1, &ptri, &model.num_tris, NULL, NULL);
-	else
-		LoadTriangleList (file1, &ptri, &model.num_tris, NULL, NULL);
-
-
-	GetScriptToken (false);
-	sprintf (file2, "%s/%s.pcx", cddir, token);
-//	sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
-
-	printf ("skin: %s\n", file2);
- 	Load256Image (file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight);
-
-	if (BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT)
-	{
-		if (g_allow_newskin)
-		{
-			ScaleWidth = BaseWidth;
-			ScaleHeight = BaseHeight;
-		}
-		else
-		{
-			Error("Invalid skin page size: (%d,%d) should be (%d,%d)",
-				BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT);
-		}
-	}
-	else
-	{
-		ScaleWidth = (float)ExtractNumber(BasePixels, ENCODED_WIDTH_X,
-			ENCODED_WIDTH_Y);
-		ScaleHeight = (float)ExtractNumber(BasePixels, ENCODED_HEIGHT_X,
-			ENCODED_HEIGHT_Y);
-	}
-
-//
-// get the ST values
-//
-	BuildST (ptri, model.num_tris,false);
-
-//
-// run through all the base triangles, storing each unique vertex in the
-// base vertex list and setting the indirect triangles to point to the base
-// vertices
-//
-	for (i=0 ; i<model.num_tris ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			// get the xyz index
-			for (k=0 ; k<model.num_xyz ; k++)
-				if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
-					break;	// this vertex is already in the base vertex list
-
-			if (k == model.num_xyz)
-			{ // new index
-				VectorCopy (ptri[i].verts[j], base_xyz[model.num_xyz]);
-
-				if(clustered)
-					ReplaceClusterIndex(k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts);
-
-				model.num_xyz++;
-			}
-
-			triangles[i].index_xyz[j] = k;
-
-			// get the st index
-			for (k=0 ; k<model.num_st ; k++)
-				if (triangle_st[i][j][0] == base_st[k].s
-				&& triangle_st[i][j][1] == base_st[k].t)
-					break;	// this vertex is already in the base vertex list
-
-			if (k == model.num_st)
-			{ // new index
-				base_st[model.num_st].s = triangle_st[i][j][0];
-				base_st[model.num_st].t = triangle_st[i][j][1];
-				model.num_st++;
-			}
-
-			triangles[i].index_st[j] = k;
-		}
-	}
-
-	// build triangle strips / fans
-	BuildGlCmds ();
-}
-
-//===============================================================
-
-char	*FindFrameFile (char *frame)
-{
-	int				time1;
-	char			file1[1024];
-	static char		retname[1024];
-	char			base[32];
-	char			suffix[32];
-	char			*s;
-
-	if (strstr (frame, "."))
-		return frame;		// allready in dot format
-
-	// split 'run1' into 'run' and '1'
-	s = frame + strlen(frame)-1;
-
-	while (s != frame && *s >= '0' && *s <= '9')
-		s--;
-
-	strcpy (suffix, s+1);
-	strcpy (base, frame);
-	base[s-frame+1] = 0;
-
-	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "hrc");
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s%s.%s", base, suffix, "hrc");
-		return retname;
-	}
-
-	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "asc");
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s%s.%s", base, suffix, "asc");
-		return retname;
-	}
-
-	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "tri");
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s%s.%s", base, suffix, "tri");
-		return retname;
-	}
-
-	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "3ds");
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s%s.%s", base, suffix, "3ds");
-		return retname;
-	}
-
-	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "htr");
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s%s.%s", base, suffix, "htr");
-		return retname;
-	}
-
-	// check for 'run.1'
-	sprintf (file1, "%s/%s.%s",cddir, base, suffix);
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s.%s", base, suffix);
-		return retname;
-	}
-
-	Error ("frame %s could not be found",frame);
-	return NULL;
-}
-
-/*
-===============
-GrabFrame
-===============
-*/
-static void GrabFrame (char *frame)
-{
-	triangle_t		*ptri;
-	int				i, j;
-	trivert_t		*ptrivert;
-	int				num_tris;
-	char			file1[1024];
-	frame_t			*fr;
-	vertexnormals_t	vnorms[MAX_VERTS];
-	int				index_xyz;
-	char			*framefile;
-
-	// the frame 'run1' will be looked for as either
-	// run.1 or run1.tri, so the new alias sequence save
-	// feature an be used
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-	printf ("grabbing %s  ", file1);
-
-	if (model.num_frames >= MAX_FRAMES)
-		Error ("model.num_frames >= MAX_FRAMES");
-	fr = &g_frames[model.num_frames];
-	model.num_frames++;
-
-	strcpy (fr->name, frame);
-
-//
-// load the frame
-//
-	if (do3ds)
-		Load3DSTriangleList (file1, &ptri, &num_tris, NULL, NULL);
-	else
-		LoadTriangleList (file1, &ptri, &num_tris, NULL, NULL);
-
-	if (num_tris != model.num_tris)
-		Error ("%s: number of triangles doesn't match base frame\n", file1);
-
-//
-// allocate storage for the frame's vertices
-//
-	ptrivert = fr->v;
-
-	for (i=0 ; i<model.num_xyz ; i++)
-	{
-		vnorms[i].numnormals = 0;
-		VectorClear (vnorms[i].normalsum);
-	}
-	ClearBounds (fr->mins, fr->maxs);
-
-//
-// store the frame's vertices in the same order as the base. This assumes the
-// triangles and vertices in this frame are in exactly the same order as in the
-// base
-//
-	for (i=0 ; i<num_tris ; i++)
-	{
-		vec3_t	vtemp1, vtemp2, normal;
-		float	ftemp;
-
-		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
-		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
-		CrossProduct (vtemp1, vtemp2, normal);
-
-		VectorNormalize (normal, normal);
-
-	// rotate the normal so the model faces down the positive x axis
-		ftemp = normal[0];
-		normal[0] = -normal[1];
-		normal[1] = ftemp;
-
-		for (j=0 ; j<3 ; j++)
-		{
-			index_xyz = triangles[i].index_xyz[j];
-
-		// rotate the vertices so the model faces down the positive x axis
-		// also adjust the vertices to the desired origin
-			ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
-										adjust[0];
-			ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
-										adjust[1];
-			ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
-										adjust[2];
-
-			AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
-
-			VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum);
-			vnorms[index_xyz].numnormals++;
-		}
-	}
-
-//
-// calculate the vertex normals, match them to the template list, and store the
-// index of the best match
-//
-	for (i=0 ; i<model.num_xyz ; i++)
-	{
-		int		j;
-		vec3_t	v;
-		float	maxdot;
-		int		maxdotindex;
-		int		c;
-
-		c = vnorms[i].numnormals;
-		if (!c)
-			Error ("Vertex with no triangles attached");
-
-		VectorScale (vnorms[i].normalsum, 1.0/c, v);
-		VectorNormalize (v, v);
-
-		maxdot = -999999.0;
-		maxdotindex = -1;
-
-		for (j=0 ; j<NUMVERTEXNORMALS ; j++)
-		{
-			float	dot;
-
-			dot = DotProduct (v, avertexnormals[j]);
-			if (dot > maxdot)
-			{
-				maxdot = dot;
-				maxdotindex = j;
-			}
-		}
-
-		ptrivert[i].lightnormalindex = maxdotindex;
-	}
-
-	free (ptri);
-}
-
-/*
-===============
-GrabJointedFrame
-===============
-*/
-void GrabJointedFrame(char *frame)
-{
-	char	file1[1024];
-	char	*framefile;
-	frame_t		*fr;
-
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-	printf ("grabbing %s\n", file1);
-
-	fr = &g_frames[model.num_frames - 1]; // last frame read in
-
-	LoadJointList(file1, fr->joints, jointed);
-}
-
-/*
-===============
-GrabGlobals
-===============
-*/
-void GrabGlobals(char *frame)
-{
-	char	file1[1024];
-	char	*framefile;
-	frame_t		*fr;
-
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-	printf ("grabbing %s\n", file1);
-
-	fr = &g_frames[model.num_frames - 1]; // last frame read in
-
-	LoadGlobals(file1);
-}
-
-/*
-===============
-Cmd_Frame	
-===============
-*/
-void Cmd_Frame (void)
-{
-	while (ScriptTokenAvailable())
-	{
-		GetScriptToken (false);
-		if (g_skipmodel)
-			continue;
-		if (g_release || g_archive)
-		{
-			model.num_frames = 1;	// don't skip the writeout
-			continue;
-		}
-
-		H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames);
-
-		GrabFrame (token);
-	}
-}
-
-/*
-===============
-Cmd_Skin
-
-Skins aren't actually stored in the file, only a reference
-is saved out to the header file.
-===============
-*/
-void Cmd_Skin (void)
-{
-	byte	*palette;
-	byte	*pixels;
-	int		width, height;
-	byte	*cropped;
-	int		y;
-	char	name[1024], savename[1024];
-
-	GetScriptToken (false);
-
-	if (model.num_skins == MAX_MD2SKINS)
-		Error ("model.num_skins == MAX_MD2SKINS");
-
-	if (g_skipmodel)
-		return;
-
-#if 1
-	sprintf (name, "%s/%s.pcx", cddir, token);
-	sprintf (savename, "%s/!%s.pcx", g_outputDir, token);
-	sprintf (g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token);
-#else
-	sprintf (name, "%s/%s.lbm", cdarchive, token);
-	strcpy (name, ExpandPathAndArchive( name ) );
-//	sprintf (name, "%s/%s.lbm", cddir, token);
-
-	if (ScriptTokenAvailable())
-	{
-		GetScriptToken (false);
-		sprintf (g_skins[model.num_skins], "%s.pcx", token);
-		sprintf (savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins]);
-	}
-	else
-	{
-		sprintf (savename, "%s/%s.pcx", g_outputDir, token);
-		sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token);
-	}
-#endif
-
-	model.num_skins++;
-
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	// load the image
-	printf ("loading %s\n", name);
-	Load256Image (name, &pixels, &palette, &width, &height);
-//	RemapZero (pixels, palette, width, height);
-
-	// crop it to the proper size
-	cropped = (byte *) SafeMalloc (model.skinwidth*model.skinheight, "Cmd_Skin");
-	for (y=0 ; y<model.skinheight ; y++)
-	{
-		memcpy (cropped+y*model.skinwidth,
-			pixels+y*width, model.skinwidth);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, model.skinwidth,
-		model.skinheight, palette);
-
-	free (pixels);
-	free (palette);
-	free (cropped);
-}
-
-
-/*
-=================
-Cmd_Origin
-=================
-*/
-void Cmd_Origin (void)
-{
-	// rotate points into frame of reference so model points down the
-	// positive x axis
-	GetScriptToken (false);
-	adjust[1] = -atof (token);
-
-	GetScriptToken (false);
-	adjust[0] = atof (token);
-
-	GetScriptToken (false);
-	adjust[2] = -atof (token);
-}
-
-
-/*
-=================
-Cmd_ScaleUp
-=================
-*/
-void Cmd_ScaleUp (void)
-{
-	GetScriptToken (false);
-	scale_up = atof (token);
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	printf ("Scale up: %f\n", scale_up);
-}
-
-
-/*
-=================
-Cmd_Skinsize
-
-Set a skin size other than the default
-=================
-*/
-void Cmd_Skinsize (void)
-{
-	GetScriptToken (false);
-	g_fixedwidth = atoi(token);
-	GetScriptToken (false);
-	g_fixedheight = atoi(token);
-}
-
-/*
-=================
-Cmd_Modelname
-
-Gives a different name/location for the file, instead of the cddir
-=================
-*/
-void Cmd_Modelname (void)
-{
-	GetScriptToken (false);
-	strcpy (modelname, token);
-}
-
-/*
-===============
-Cmd_Cd
-===============
-*/
-void Cmd_Cd (void)
-{
-	char temp[256];
-
-	FinishModel ();
-	ClearModel ();
-
-	GetScriptToken (false);
-
-	// this is a silly mess...
-	sprintf (cdpartial, "models/%s", token); 
-	sprintf (cdarchive, "%smodels/%s", gamedir+strlen(qdir), token); 
-	sprintf (cddir, "%s%s", gamedir, cdpartial);
-
-	// Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
-	sprintf(temp, "%s%s", g_outputDir, cdpartial);
-	strcpy(g_outputDir, temp);
-
-	// if -only was specified and this cd doesn't match,
-	// skip the model (you only need to match leading chars,
-	// so you could regrab all monsters with -only monsters)
-	if (!g_only[0])
-		return;
-	if (strncmp(token, g_only, strlen(g_only)))
-	{
-		g_skipmodel = true;
-		printf ("skipping %s\n", cdpartial);
-	}
-}
-
-/*
-=================
-Cmd_Cluster
-=================
-*/
-void Cmd_Cluster()
-{
-	char file1[1024];
-
-	GetScriptToken (false);
-
-	printf ("---------------------\n");
-	sprintf (file1, "%s/%s", cdpartial, token);
-	printf ("%s\n", file1);
-
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s", cddir, token);
-
-	LoadClusters(file1, (int **)&clusters, (int *)&num_verts, jointed);
-
-	new_num_verts[0] = num_verts[0];
-
-	clustered = 1;
-}
-
-// Model construction cover functions.
-void MODELCMD_Modelname (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	Cmd_Modelname ();
-/*
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Modelname ();		
-		break;
-	case MODEL_FM:
-		Cmd_FMModelname ();
-		break;
-	}
-*/
-}
-
-void MODELCMD_Cd (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Cd ();
-		break;
-	case MODEL_FM:
-		Cmd_FMCd ();
-		break;
-	}
-}
-
-void MODELCMD_Origin (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	Cmd_Origin ();
-/*	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Origin ();
-		break;
-	case MODEL_FM:
-		Cmd_FMOrigin ();
-		break;
-	}
-*/
-}
-
-void MODELCMD_Cluster (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Cluster ();
-		break;
-	case MODEL_FM:
-		Cmd_FMCluster ();
-		break;
-	}
-}
-
-void MODELCMD_Base (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Base ();
-		break;
-	case MODEL_FM:
-		Cmd_FMBase (false);
-		break;
-	}
-}
-
-void MODELCMD_BaseST (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Base ();
-		break;
-	case MODEL_FM:
-		Cmd_FMBase (true);
-		break;
-	}
-}
-
-void MODELCMD_ScaleUp (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	Cmd_ScaleUp ();
-/*	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_ScaleUp ();
-		break;
-	case MODEL_FM:
-		Cmd_FMScaleUp ();
-		break;
-	}
-*/
-}
-
-void MODELCMD_Frame (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Frame ();
-		break;
-	case MODEL_FM:
-		Cmd_FMFrame ();
-		break;
-	}
-}
-
-void MODELCMD_Skin (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Skin ();
-		break;
-	case MODEL_FM:
-		Cmd_FMSkin ();
-		break;
-	}
-}
-
-void MODELCMD_Skinsize (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	Cmd_Skinsize ();
-/*
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		Cmd_Skinsize ();
-		break;
-	case MODEL_FM:
-		Cmd_FMSkinsize ();
-		break;
-	}
-*/
-}
-
-void MODELCMD_Skeleton (int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		break;
-	case MODEL_FM:
-		Cmd_FMSkeleton ();
-		break;
-	}
-}
-
-void MODELCMD_BeginGroup(int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		break;
-	case MODEL_FM:
-		Cmd_FMBeginGroup();
-		break;
-	}
-}
-
-void MODELCMD_EndGroup(int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		break;
-	case MODEL_FM:
-		Cmd_FMEndGroup();
-		break;
-	}
-}
-
-void MODELCMD_Referenced(int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		break;
-	case MODEL_FM:
-		Cmd_FMReferenced();
-		break;
-	}
-}
-
-void MODELCMD_NodeOrder(int modeltype)
-{
-	if (g_forcemodel)
-		modeltype = g_forcemodel;
-
-	switch(modeltype)
-	{
-	case MODEL_MD2:
-		break;
-	case MODEL_FM:
-		Cmd_FMNodeOrder();
-		break;
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "qdata.h"
+#include <assert.h>
+#include "jointed.h"
+#include "fmodel.h"
+
+//=================================================================
+
+typedef struct 
+{
+	int		numnormals;
+	vec3_t	normalsum;
+} vertexnormals_t;
+
+typedef struct
+{
+	vec3_t		v;
+	int			lightnormalindex;
+} trivert_t;
+
+typedef struct
+{
+	vec3_t		mins, maxs;
+	char		name[16];
+	trivert_t	v[MAX_VERTS];
+	QDataJoint_t	joints[NUM_CLUSTERS]; // ,this
+} frame_t;
+
+// ,and all of this should get out of here, need to use new stuff in fmodels instead
+
+typedef struct IntListNode_s
+{
+	int data;
+	struct IntListNode_s *next;
+} IntListNode_t;  // gaak
+
+typedef struct
+{
+	float		scale[3];	// multiply byte verts by this
+	float		translate[3];	// then add this
+} PartialAliasFrame_t;
+
+int jointed;
+int clustered;
+
+int *clusters[NUM_CLUSTERS];
+IntListNode_t *vertLists[NUM_CLUSTERS];
+int		num_verts[NUM_CLUSTERS + 1];
+int		new_num_verts[NUM_CLUSTERS + 1];
+
+// end that
+
+//================================================================
+
+frame_t		g_frames[MAX_FRAMES];
+//frame_t		*g_frames;
+
+static dmdl_t		model;
+
+
+float		scale_up;			// set by $scale
+vec3_t		adjust;				// set by $origin
+int			g_fixedwidth, g_fixedheight;	// set by $skinsize
+
+
+//
+// base frame info
+//
+dstvert_t	base_st[MAX_VERTS];
+dtriangle_t	triangles[MAX_TRIANGLES];
+
+static int			triangle_st[MAX_TRIANGLES][3][2];
+
+// the command list holds counts, s/t values, and xyz indexes
+// that are valid for every frame
+int			commands[16384];
+int			numcommands;
+int			numglverts;
+int			used[MAX_TRIANGLES];
+
+char		g_skins[MAX_MD2SKINS][64];
+
+char		cdarchive[1024];
+char		cdpartial[1024];
+char		cddir[1024];
+
+char		modelname[64];	// empty unless $modelname issued (players)
+
+extern 	char		*g_outputDir;
+
+#define NUMVERTEXNORMALS	162
+
+float	avertexnormals[NUMVERTEXNORMALS][3] = 
+{
+	#include "anorms.h"
+};
+
+unsigned char pic[SKINPAGE_HEIGHT*SKINPAGE_WIDTH], pic_palette[768];
+
+FILE	*headerouthandle = NULL;
+
+//==============================================================
+
+/*
+===============
+ClearModel
+===============
+*/
+static void ClearModel (void)
+{
+	memset (&model, 0, sizeof(model));
+
+	modelname[0] = 0;
+	jointed = NOT_JOINTED;
+	clustered = 0;
+	scale_up = 1.0;	
+	VectorCopy (vec3_origin, adjust);
+	g_fixedwidth = g_fixedheight = 0;
+	g_skipmodel = false;
+}
+
+
+void H_printf(char *fmt, ...)
+{
+	va_list argptr;
+	char	name[1024];
+
+	if (!headerouthandle)
+	{
+		sprintf (name, "%s/tris.h", cddir);
+		headerouthandle = SafeOpenWrite (name);
+		fprintf(headerouthandle, "// %s\n\n", cddir);
+		fprintf(headerouthandle, "// This file generated by qdata - Do NOT Modify\n\n");
+	}
+
+	va_start (argptr, fmt);
+	vfprintf (headerouthandle, fmt, argptr);
+	va_end (argptr);
+}
+
+#if 1
+/*
+============
+WriteModelFile
+============
+*/
+void WriteCommonModelFile (FILE *modelouthandle, PartialAliasFrame_t *outFrames)
+{
+	int				i;
+	dmdl_t			modeltemp;
+	int				j, k;
+	frame_t			*in;
+	daliasframe_t	*out;
+	byte			buffer[MAX_VERTS*4+128];
+	float			v;
+	int				c_on, c_off;
+
+	model.version = ALIAS_VERSION;
+	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
+	model.num_glcmds = numcommands;
+	model.ofs_skins = sizeof(dmdl_t);
+	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
+	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
+	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
+	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
+	model.ofs_end = model.ofs_glcmds + model.num_glcmds*sizeof(int);
+	//
+	// write out the model header
+	//
+	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
+		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
+
+	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
+
+	//
+	// write out the skin names
+	//
+	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
+
+	//
+	// write out the texture coordinates
+	//
+	c_on = c_off = 0;
+	for (i=0 ; i<model.num_st ; i++)
+	{
+		base_st[i].s = LittleShort (base_st[i].s);
+		base_st[i].t = LittleShort (base_st[i].t);
+	}
+
+	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
+
+	//
+	// write out the triangles
+	//
+	for (i=0 ; i<model.num_tris ; i++)
+	{
+		int			j;
+		dtriangle_t	tri;
+
+		for (j=0 ; j<3 ; j++)
+		{
+			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
+			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
+		}
+
+		SafeWrite (modelouthandle, &tri, sizeof(tri));
+	}
+
+	//
+	// write out the frames
+	//
+	for (i=0 ; i<model.num_frames ; i++)
+	{
+		in = &g_frames[i];
+		out = (daliasframe_t *)buffer;
+
+		strcpy (out->name, in->name);
+		for (j=0 ; j<3 ; j++)
+		{
+			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
+			out->translate[j] = in->mins[j];
+
+			if(outFrames)
+			{
+				outFrames[i].scale[j] = out->scale[j];
+				outFrames[i].translate[j] = out->translate[j];
+			}
+		}
+
+		for (j=0 ; j<model.num_xyz ; j++)
+		{
+		// all of these are byte values, so no need to deal with endianness
+			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
+
+			for (k=0 ; k<3 ; k++)
+			{
+			// scale to byte values & min/max check
+				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
+
+			// clamp, so rounding doesn't wrap from 255.6 to 0
+				if (v > 255.0)
+					v = 255.0;
+				if (v < 0)
+					v = 0;
+				out->verts[j].v[k] = v;
+			}
+		}
+
+		for (j=0 ; j<3 ; j++)
+		{
+			out->scale[j] = LittleFloat (out->scale[j]);
+			out->translate[j] = LittleFloat (out->translate[j]);
+		}
+
+		SafeWrite (modelouthandle, out, model.framesize);
+	}
+
+	//
+	// write out glcmds
+	//
+	SafeWrite (modelouthandle, commands, numcommands*4);
+}
+
+/*
+============
+WriteModelFile
+============
+*/
+void WriteModelFile (FILE *modelouthandle)
+{
+	model.ident = IDALIASHEADER;
+
+	WriteCommonModelFile(modelouthandle, NULL);
+}
+
+/*
+============
+WriteJointedModelFile
+============
+*/
+void WriteJointedModelFile (FILE *modelouthandle)
+{
+	int				i;
+	int				j, k;
+	frame_t			*in;
+	float			v;
+	IntListNode_t	*current, *toFree;
+	PartialAliasFrame_t outFrames[MAX_FRAMES];
+
+	model.ident = IDJOINTEDALIASHEADER;
+	
+	WriteCommonModelFile(modelouthandle, outFrames);
+
+	// Skeletal Type
+	SafeWrite(modelouthandle, &jointed, sizeof(int));
+
+	// number of joints
+	SafeWrite(modelouthandle, &numJointsForSkeleton[jointed], sizeof(int));
+
+	// number of verts in each cluster
+	SafeWrite(modelouthandle, &new_num_verts[1], sizeof(int)*numJointsForSkeleton[jointed]);
+
+	// cluster verts
+	for(i = 0; i < new_num_verts[0]; ++i)
+	{
+		current = vertLists[i];
+		while(current)
+		{
+			SafeWrite (modelouthandle, &current->data, sizeof(int));
+			toFree = current;
+			current = current->next;
+			free(toFree);  // freeing of memory allocated in ReplaceClusterIndex called in Cmd_Base
+		}
+	}
+
+	for (i=0 ; i<model.num_frames ; i++)
+	{
+		in = &g_frames[i];
+
+		for (j = 0 ; j < new_num_verts[0]; ++j)
+		{
+			for (k=0 ; k<3 ; k++)
+			{
+				// scale to byte values & min/max check
+				v = Q_rint ( (in->joints[j].placement.origin[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+				// clamp, so rounding doesn't wrap from 255.6 to 0
+				if (v > 255.0)
+				{
+					v = 255.0;
+				}
+
+				if (v < 0)
+				{
+					v = 0;
+				}
+
+				// write out origin as a float (there's only a few per model, so it's not really 
+				// a size issue)
+				SafeWrite (modelouthandle, &v, sizeof(float));
+			}
+
+			for (k=0 ; k<3 ; k++)
+			{
+				v = Q_rint ( (in->joints[j].placement.direction[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+				// clamp, so rounding doesn't wrap from 255.6 to 0
+				if (v > 255.0)
+				{
+					v = 255.0;
+				}
+
+				if (v < 0)
+				{
+					v = 0;
+				}
+
+				// write out origin as a float (there's only a few per model, so it's not really 
+				// a size issue)
+				SafeWrite (modelouthandle, &v, sizeof(float));
+			}
+
+			for (k=0 ; k<3 ; k++)
+			{
+				v = Q_rint ( (in->joints[j].placement.up[k] - outFrames[i].translate[k]) / outFrames[i].scale[k] );
+
+				// clamp, so rounding doesn't wrap from 255.6 to 0
+				if (v > 255.0)
+				{
+					v = 255.0;
+				}
+
+				if (v < 0)
+				{
+					v = 0;
+				}
+
+				// write out origin as a float (there's only a few per model, so it's not really 
+				// a size issue)
+				SafeWrite (modelouthandle, &v, sizeof(float));
+			}
+		}
+	}
+}
+#else
+/*
+============
+WriteModelFile
+============
+*/
+static void WriteModelFile (FILE *modelouthandle)
+{
+	int				i;
+	dmdl_t			modeltemp;
+	int				j, k;
+	frame_t			*in;
+	daliasframe_t	*out;
+	byte			buffer[MAX_VERTS*4+128];
+	float			v;
+	int				c_on, c_off;
+
+	model.ident = IDALIASHEADER;
+	model.version = ALIAS_VERSION;
+	model.framesize = (int)&((daliasframe_t *)0)->verts[model.num_xyz];
+	model.num_glcmds = numcommands;
+	model.ofs_skins = sizeof(dmdl_t);
+	model.ofs_st = model.ofs_skins + model.num_skins * MAX_SKINNAME;
+	model.ofs_tris = model.ofs_st + model.num_st*sizeof(dstvert_t);
+	model.ofs_frames = model.ofs_tris + model.num_tris*sizeof(dtriangle_t);
+	model.ofs_glcmds = model.ofs_frames + model.num_frames*model.framesize;
+	model.ofs_end = model.ofs_glcmds + model.num_glcmds*4;
+
+	//
+	// write out the model header
+	//
+	for (i=0 ; i<sizeof(dmdl_t)/4 ; i++)
+		((int *)&modeltemp)[i] = LittleLong (((int *)&model)[i]);
+
+	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
+
+	//
+	// write out the skin names
+	//
+	SafeWrite (modelouthandle, g_skins, model.num_skins * MAX_SKINNAME);
+
+	//
+	// write out the texture coordinates
+	//
+	c_on = c_off = 0;
+	for (i=0 ; i<model.num_st ; i++)
+	{
+		base_st[i].s = LittleShort (base_st[i].s);
+		base_st[i].t = LittleShort (base_st[i].t);
+	}
+
+	SafeWrite (modelouthandle, base_st, model.num_st * sizeof(base_st[0]));
+
+	//
+	// write out the triangles
+	//
+	for (i=0 ; i<model.num_tris ; i++)
+	{
+		int			j;
+		dtriangle_t	tri;
+
+		for (j=0 ; j<3 ; j++)
+		{
+			tri.index_xyz[j] = LittleShort (triangles[i].index_xyz[j]);
+			tri.index_st[j] = LittleShort (triangles[i].index_st[j]);
+		}
+
+		SafeWrite (modelouthandle, &tri, sizeof(tri));
+	}
+
+	//
+	// write out the frames
+	//
+	for (i=0 ; i<model.num_frames ; i++)
+	{
+		in = &g_frames[i];
+		out = (daliasframe_t *)buffer;
+
+		strcpy (out->name, in->name);
+		for (j=0 ; j<3 ; j++)
+		{
+			out->scale[j] = (in->maxs[j] - in->mins[j])/255;
+			out->translate[j] = in->mins[j];
+		}
+
+		for (j=0 ; j<model.num_xyz ; j++)
+		{
+		// all of these are byte values, so no need to deal with endianness
+			out->verts[j].lightnormalindex = in->v[j].lightnormalindex;
+
+			for (k=0 ; k<3 ; k++)
+			{
+			// scale to byte values & min/max check
+				v = Q_rint ( (in->v[j].v[k] - out->translate[k]) / out->scale[k] );
+
+			// clamp, so rounding doesn't wrap from 255.6 to 0
+				if (v > 255.0)
+					v = 255.0;
+				if (v < 0)
+					v = 0;
+				out->verts[j].v[k] = v;
+			}
+		}
+
+		for (j=0 ; j<3 ; j++)
+		{
+			out->scale[j] = LittleFloat (out->scale[j]);
+			out->translate[j] = LittleFloat (out->translate[j]);
+		}
+
+		SafeWrite (modelouthandle, out, model.framesize);
+	}
+
+	//
+	// write out glcmds
+	//
+	SafeWrite (modelouthandle, commands, numcommands*4);
+}
+#endif
+
+/*
+===============
+FinishModel
+===============
+*/
+void FinishModel (void)
+{
+	FILE		*modelouthandle;
+	int			i;
+	char		name[1024];
+	
+	if (!model.num_frames)
+		return;
+	
+//
+// copy to release directory tree if doing a release build
+//
+	if (g_release)
+	{
+		if (modelname[0])
+			sprintf (name, "%s", modelname);
+		else
+			sprintf (name, "%s/tris.md2", cdpartial);
+		ReleaseFile (name);
+
+		for (i=0 ; i<model.num_skins ; i++)
+		{
+			ReleaseFile (g_skins[i]);
+		}
+		model.num_frames = 0;
+		return;
+	}
+	
+//
+// write the model output file
+//
+	if (modelname[0])
+		sprintf (name, "%s%s", g_outputDir, modelname);
+	else
+		sprintf (name, "%s/tris.md2", g_outputDir);
+	printf ("saving to %s\n", name);
+	CreatePath (name);
+	modelouthandle = SafeOpenWrite (name);
+
+#if 1
+	if(jointed != NOT_JOINTED)
+		WriteJointedModelFile(modelouthandle);
+	else
+#endif
+		WriteModelFile(modelouthandle);
+	
+	printf ("%3dx%3d skin\n", model.skinwidth, model.skinheight);
+	printf ("First frame boundaries:\n");
+	printf ("	minimum x: %3f\n", g_frames[0].mins[0]);
+	printf ("	maximum x: %3f\n", g_frames[0].maxs[0]);
+	printf ("	minimum y: %3f\n", g_frames[0].mins[1]);
+	printf ("	maximum y: %3f\n", g_frames[0].maxs[1]);
+	printf ("	minimum z: %3f\n", g_frames[0].mins[2]);
+	printf ("	maximum z: %3f\n", g_frames[0].maxs[2]);
+	printf ("%4d vertices\n", model.num_xyz);
+	printf ("%4d triangles\n", model.num_tris);
+	printf ("%4d frame\n", model.num_frames);
+	printf ("%4d glverts\n", numglverts);
+	printf ("%4d glcmd\n", model.num_glcmds);
+	printf ("%4d skins\n", model.num_skins);
+	printf ("file size: %d\n", (int)ftell (modelouthandle) );
+	printf ("---------------------\n");
+	
+	fclose (modelouthandle);
+
+	// finish writing header file
+	H_printf("\n");
+
+	// scale_up is usefull to allow step distances to be adjusted
+	H_printf("#define MODEL_SCALE\t\t%f\n", scale_up);
+
+	fclose (headerouthandle);
+	headerouthandle = NULL;
+}
+
+
+/*
+=================================================================
+
+ALIAS MODEL DISPLAY LIST GENERATION
+
+=================================================================
+*/
+
+int		strip_xyz[128];
+int		strip_st[128];
+int		strip_tris[128];
+int		stripcount;
+
+/*
+================
+StripLength
+================
+*/
+static int	StripLength (int starttri, int startv)
+{
+	int			m1, m2;
+	int			st1, st2;
+	int			j;
+	dtriangle_t	*last, *check;
+	int			k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	strip_xyz[0] = last->index_xyz[(startv)%3];
+	strip_xyz[1] = last->index_xyz[(startv+1)%3];
+	strip_xyz[2] = last->index_xyz[(startv+2)%3];
+	strip_st[0] = last->index_st[(startv)%3];
+	strip_st[1] = last->index_st[(startv+1)%3];
+	strip_st[2] = last->index_st[(startv+2)%3];
+
+	strip_tris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->index_xyz[(startv+2)%3];
+	st1 = last->index_st[(startv+2)%3];
+	m2 = last->index_xyz[(startv+1)%3];
+	st2 = last->index_st[(startv+1)%3];
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1]
+		; j<model.num_tris ; j++, check++)
+	{
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->index_xyz[k] != m1)
+				continue;
+			if (check->index_st[k] != st1)
+				continue;
+			if (check->index_xyz[ (k+1)%3 ] != m2)
+				continue;
+			if (check->index_st[ (k+1)%3 ] != st2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			if (stripcount & 1)
+			{
+				m2 = check->index_xyz[ (k+2)%3 ];
+				st2 = check->index_st[ (k+2)%3 ];
+			}
+			else
+			{
+				m1 = check->index_xyz[ (k+2)%3 ];
+				st1 = check->index_st[ (k+2)%3 ];
+			}
+
+			strip_xyz[stripcount+2] = check->index_xyz[ (k+2)%3 ];
+			strip_st[stripcount+2] = check->index_st[ (k+2)%3 ];
+			strip_tris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<model.num_tris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+/*
+===========
+FanLength
+===========
+*/
+static int	FanLength (int starttri, int startv)
+{
+	int		m1, m2;
+	int		st1, st2;
+	int		j;
+	dtriangle_t	*last, *check;
+	int		k;
+
+	used[starttri] = 2;
+
+	last = &triangles[starttri];
+
+	strip_xyz[0] = last->index_xyz[(startv)%3];
+	strip_xyz[1] = last->index_xyz[(startv+1)%3];
+	strip_xyz[2] = last->index_xyz[(startv+2)%3];
+	strip_st[0] = last->index_st[(startv)%3];
+	strip_st[1] = last->index_st[(startv+1)%3];
+	strip_st[2] = last->index_st[(startv+2)%3];
+
+	strip_tris[0] = starttri;
+	stripcount = 1;
+
+	m1 = last->index_xyz[(startv+0)%3];
+	st1 = last->index_st[(startv+0)%3];
+	m2 = last->index_xyz[(startv+2)%3];
+	st2 = last->index_st[(startv+2)%3];
+
+
+	// look for a matching triangle
+nexttri:
+	for (j=starttri+1, check=&triangles[starttri+1] 
+		; j<model.num_tris ; j++, check++)
+	{
+		for (k=0 ; k<3 ; k++)
+		{
+			if (check->index_xyz[k] != m1)
+				continue;
+			if (check->index_st[k] != st1)
+				continue;
+			if (check->index_xyz[ (k+1)%3 ] != m2)
+				continue;
+			if (check->index_st[ (k+1)%3 ] != st2)
+				continue;
+
+			// this is the next part of the fan
+
+			// if we can't use this triangle, this tristrip is done
+			if (used[j])
+				goto done;
+
+			// the new edge
+			m2 = check->index_xyz[ (k+2)%3 ];
+			st2 = check->index_st[ (k+2)%3 ];
+
+			strip_xyz[stripcount+2] = m2;
+			strip_st[stripcount+2] = st2;
+			strip_tris[stripcount] = j;
+			stripcount++;
+
+			used[j] = 2;
+			goto nexttri;
+		}
+	}
+done:
+
+	// clear the temp used flags
+	for (j=starttri+1 ; j<model.num_tris ; j++)
+		if (used[j] == 2)
+			used[j] = 0;
+
+	return stripcount;
+}
+
+
+
+/*
+================
+BuildGlCmds
+
+Generate a list of trifans or strips
+for the model, which holds for all frames
+================
+*/
+static void BuildGlCmds (void)
+{
+	int		i, j, k;
+	int		startv;
+	float	s, t;
+	int		len, bestlen, besttype;
+	int		best_xyz[1024];
+	int		best_st[1024];
+	int		best_tris[1024];
+	int		type;
+
+	//
+	// build tristrips
+	//
+	numcommands = 0;
+	numglverts = 0;
+	memset (used, 0, sizeof(used));
+	for (i=0 ; i<model.num_tris ; i++)
+	{
+		// pick an unused triangle and start the trifan
+		if (used[i])
+			continue;
+
+		bestlen = 0;
+		for (type = 0 ; type < 2 ; type++)
+//	type = 1;
+		{
+			for (startv =0 ; startv < 3 ; startv++)
+			{
+				if (type == 1)
+					len = StripLength (i, startv);
+				else
+					len = FanLength (i, startv);
+				if (len > bestlen)
+				{
+					besttype = type;
+					bestlen = len;
+					for (j=0 ; j<bestlen+2 ; j++)
+					{
+						best_st[j] = strip_st[j];
+						best_xyz[j] = strip_xyz[j];
+					}
+					for (j=0 ; j<bestlen ; j++)
+						best_tris[j] = strip_tris[j];
+				}
+			}
+		}
+
+		// mark the tris on the best strip/fan as used
+		for (j=0 ; j<bestlen ; j++)
+			used[best_tris[j]] = 1;
+
+		if (besttype == 1)
+			commands[numcommands++] = (bestlen+2);
+		else
+			commands[numcommands++] = -(bestlen+2);
+
+		numglverts += bestlen+2;
+
+		for (j=0 ; j<bestlen+2 ; j++)
+		{
+			// emit a vertex into the reorder buffer
+			k = best_st[j];
+
+			// emit s/t coords into the commands stream
+			s = base_st[k].s;
+			t = base_st[k].t;
+
+			s = (s + 0.5) / model.skinwidth;
+			t = (t + 0.5) / model.skinheight;
+
+			*(float *)&commands[numcommands++] = s;
+			*(float *)&commands[numcommands++] = t;
+			*(int *)&commands[numcommands++] = best_xyz[j];
+		}
+	}
+
+	commands[numcommands++] = 0;		// end of list marker
+}
+
+
+/*
+===============================================================
+
+BASE FRAME SETUP
+
+===============================================================
+*/
+
+/*
+============
+BuildST
+
+Builds the triangle_st array for the base frame and
+model.skinwidth / model.skinheight
+
+  FIXME: allow this to be loaded from a file for
+  arbitrary mappings
+============
+*/
+#if 0
+static void OldBuildST (triangle_t *ptri, int numtri)
+{
+	int			i, j;
+	int			width, height, iwidth, iheight, swidth;
+	float		basex, basey;
+	float		s_scale, t_scale;
+	float		scale;
+	vec3_t		mins, maxs;
+	float		*pbasevert;
+	vec3_t		vtemp1, vtemp2, normal;
+
+	//
+	// find bounds of all the verts on the base frame
+	//
+	ClearBounds (mins, maxs);
+	
+	for (i=0 ; i<numtri ; i++)
+		for (j=0 ; j<3 ; j++)
+			AddPointToBounds (ptri[i].verts[j], mins, maxs);
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		mins[i] = floor(mins[i]);
+		maxs[i] = ceil(maxs[i]);
+	}
+	
+	width = maxs[0] - mins[0];
+	height = maxs[2] - mins[2];
+
+	if (!g_fixedwidth)
+	{	// old style
+		scale = 8;
+		if (width*scale >= 150)
+			scale = 150.0 / width;	
+		if (height*scale >= 190)
+			scale = 190.0 / height;
+
+		s_scale = t_scale = scale;
+
+		iwidth = ceil(width*s_scale);
+		iheight = ceil(height*t_scale);
+
+		iwidth += 4;
+		iheight += 4;
+	}
+	else
+	{	// new style
+		iwidth = g_fixedwidth / 2;
+		iheight = g_fixedheight;
+
+		s_scale = (float)(iwidth-4) / width;
+		t_scale = (float)(iheight-4) / height;
+	}
+
+//
+// determine which side of each triangle to map the texture to
+//
+	for (i=0 ; i<numtri ; i++)
+	{
+		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+		CrossProduct (vtemp1, vtemp2, normal);
+
+		if (normal[1] > 0)
+		{
+			basex = iwidth + 2;
+		}
+		else
+		{
+			basex = 2;
+		}
+		basey = 2;
+		
+		for (j=0 ; j<3 ; j++)
+		{
+			pbasevert = ptri[i].verts[j];
+
+			triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
+			triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
+		}
+	}
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+	swidth = iwidth*2;
+	model.skinwidth = (swidth + 3) & ~3;
+	model.skinheight = iheight;
+}
+#endif
+
+//==========================================================================
+//
+// DrawScreen
+//
+//==========================================================================
+
+void DrawScreen(float s_scale, float t_scale, float iwidth, float iheight)
+{
+	int i;
+	byte *scrpos;
+	char buffer[256];
+
+	// Divider
+	scrpos = &pic[(INFO_Y-2)*SKINPAGE_WIDTH];
+	for(i = 0; i < SKINPAGE_WIDTH; i++)
+	{
+		*scrpos++ = 255;
+	}
+
+	sprintf(buffer, "GENSKIN:  ");
+	DrawTextChar(16, INFO_Y, buffer);
+	
+	sprintf(buffer, "( %03d * %03d )   SCALE %f %f, SKINWIDTH %d,"
+		" SKINHEIGHT %d", (int)ScaleWidth, (int)ScaleHeight, s_scale, t_scale, (int)iwidth*2, (int)iheight);
+	DrawTextChar(80, INFO_Y, buffer);
+}
+
+/*
+============
+BuildST
+
+Builds the triangle_st array for the base frame and
+model.skinwidth / model.skinheight
+
+  FIXME: allow this to be loaded from a file for
+  arbitrary mappings
+============
+*/
+void BuildST (triangle_t *ptri, int numtri, qboolean DrawSkin)
+{
+	int			i, j;
+	int			width, height, iwidth, iheight, swidth;
+	float		basex, basey;
+	float		scale;
+	vec3_t		mins, maxs;
+	float		*pbasevert;
+	vec3_t		vtemp1, vtemp2, normal;
+	float		s_scale, t_scale;
+	float		scWidth;
+	float		scHeight;
+
+	//
+	// find bounds of all the verts on the base frame
+	//
+	ClearBounds (mins, maxs);
+	
+	for (i=0 ; i<numtri ; i++)
+		for (j=0 ; j<3 ; j++)
+			AddPointToBounds (ptri[i].verts[j], mins, maxs);
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		mins[i] = floor(mins[i]);
+		maxs[i] = ceil(maxs[i]);
+	}
+	
+	width = maxs[0] - mins[0];
+	height = maxs[2] - mins[2];
+
+
+	scWidth = (ScaleWidth/2)*SCALE_ADJUST_FACTOR;
+	scHeight = ScaleHeight*SCALE_ADJUST_FACTOR;
+
+	scale = scWidth/width;
+
+	if(height*scale >= scHeight)
+	{
+		scale = scHeight/height;
+	}
+
+	iwidth = ceil(width*scale)+4;
+	iheight = ceil(height*scale)+4;
+
+	s_scale = (float)(iwidth-4) / width;
+	t_scale = (float)(iheight-4) / height;
+	t_scale = s_scale;
+
+	if (DrawSkin)
+		DrawScreen(s_scale, t_scale, iwidth, iheight);
+
+
+/*	if (!g_fixedwidth)
+	{	// old style
+		scale = 8;
+		if (width*scale >= 150)
+			scale = 150.0 / width;	
+		if (height*scale >= 190)
+			scale = 190.0 / height;
+
+		s_scale = t_scale = scale;
+
+		iwidth = ceil(width*s_scale);
+		iheight = ceil(height*t_scale);
+
+		iwidth += 4;
+		iheight += 4;
+	}
+	else
+	{	// new style
+		iwidth = g_fixedwidth / 2;
+		iheight = g_fixedheight;
+
+		s_scale = (float)(iwidth-4) / width;
+		t_scale = (float)(iheight-4) / height;
+	}*/
+
+//
+// determine which side of each triangle to map the texture to
+//
+	for (i=0 ; i<numtri ; i++)
+	{
+		if (ptri[i].HasUV)
+		{
+			for (j=0 ; j<3 ; j++)
+			{
+				triangle_st[i][j][0] = Q_rint(ptri[i].uv[j][0]*iwidth);
+				triangle_st[i][j][1] = Q_rint((1.0f-ptri[i].uv[j][1])*iheight);
+			}
+		}
+		else
+		{
+			VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+			VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+			CrossProduct (vtemp1, vtemp2, normal);
+
+			if (normal[1] > 0)
+			{
+				basex = iwidth + 2;
+			}
+			else
+			{
+				basex = 2;
+			}
+			basey = 2;
+			
+			for (j=0 ; j<3 ; j++)
+			{
+				pbasevert = ptri[i].verts[j];
+
+				triangle_st[i][j][0] = Q_rint((pbasevert[0] - mins[0]) * s_scale + basex);
+				triangle_st[i][j][1] = Q_rint((maxs[2] - pbasevert[2]) * t_scale + basey);
+			}
+		}
+
+		DrawLine(triangle_st[i][0][0], triangle_st[i][0][1],
+			triangle_st[i][1][0], triangle_st[i][1][1]);
+		DrawLine(triangle_st[i][1][0], triangle_st[i][1][1],
+			triangle_st[i][2][0], triangle_st[i][2][1]);
+		DrawLine(triangle_st[i][2][0], triangle_st[i][2][1],
+			triangle_st[i][0][0], triangle_st[i][0][1]); 
+	}
+
+// make the width a multiple of 4; some hardware requires this, and it ensures
+// dword alignment for each scan
+
+	swidth = iwidth*2;
+	model.skinwidth = (swidth + 3) & ~3;
+	model.skinheight = iheight;
+}
+
+
+static void ReplaceClusterIndex(int newIndex, int oldindex, int **clusters, 
+	IntListNode_t **vertLists, int *num_verts, int *new_num_verts)
+{
+	int i, j;
+	IntListNode_t *next;
+
+	for(j = 0; j < num_verts[0]; ++j)
+	{
+		for(i = 0; i < num_verts[j+1]; ++i)
+		{
+			if(clusters[j][i] == oldindex)
+			{
+				++new_num_verts[j+1];
+
+				next = vertLists[j];
+
+				vertLists[j] = (IntListNode_t *) SafeMalloc(sizeof(IntListNode_t), "ReplaceClusterIndex");
+				// Currently freed in WriteJointedModelFile only
+
+				vertLists[j]->data = newIndex;
+				vertLists[j]->next = next;
+			}
+		}
+	}
+}
+
+/*
+=================
+Cmd_Base
+=================
+*/
+void Cmd_Base (void)
+{
+	vec3_t		base_xyz[MAX_VERTS];
+	triangle_t	*ptri;
+	int			i, j, k;
+#if 1
+#else
+	int		time1;
+#endif
+	char	file1[1024];
+	char	file2[1024];
+
+	GetScriptToken (false);
+
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	printf ("---------------------\n");
+#if 1
+	sprintf (file1, "%s/%s", cdpartial, token);
+	printf ("%s  ", file1);
+
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s", cddir, token);
+#else
+	sprintf (file1, "%s/%s.%s", cdarchive, token, trifileext);
+	printf ("%s\n", file1);
+
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s.%s", cddir, token, trifileext);
+
+	time1 = FileTime (file1);
+	if (time1 == -1)
+		Error ("%s doesn't exist", file1);
+#endif
+//
+// load the base triangles
+//
+	if (do3ds)
+		Load3DSTriangleList (file1, &ptri, &model.num_tris, NULL, NULL);
+	else
+		LoadTriangleList (file1, &ptri, &model.num_tris, NULL, NULL);
+
+
+	GetScriptToken (false);
+	sprintf (file2, "%s/%s.pcx", cddir, token);
+//	sprintf (trans_file, "%s/!%s_a.pcx", cddir, token);
+
+	printf ("skin: %s\n", file2);
+ 	Load256Image (file2, &BasePixels, &BasePalette, &BaseWidth, &BaseHeight);
+
+	if (BaseWidth != SKINPAGE_WIDTH || BaseHeight != SKINPAGE_HEIGHT)
+	{
+		if (g_allow_newskin)
+		{
+			ScaleWidth = BaseWidth;
+			ScaleHeight = BaseHeight;
+		}
+		else
+		{
+			Error("Invalid skin page size: (%d,%d) should be (%d,%d)",
+				BaseWidth,BaseHeight,SKINPAGE_WIDTH,SKINPAGE_HEIGHT);
+		}
+	}
+	else
+	{
+		ScaleWidth = (float)ExtractNumber(BasePixels, ENCODED_WIDTH_X,
+			ENCODED_WIDTH_Y);
+		ScaleHeight = (float)ExtractNumber(BasePixels, ENCODED_HEIGHT_X,
+			ENCODED_HEIGHT_Y);
+	}
+
+//
+// get the ST values
+//
+	BuildST (ptri, model.num_tris,false);
+
+//
+// run through all the base triangles, storing each unique vertex in the
+// base vertex list and setting the indirect triangles to point to the base
+// vertices
+//
+	for (i=0 ; i<model.num_tris ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			// get the xyz index
+			for (k=0 ; k<model.num_xyz ; k++)
+				if (VectorCompare (ptri[i].verts[j], base_xyz[k]))
+					break;	// this vertex is already in the base vertex list
+
+			if (k == model.num_xyz)
+			{ // new index
+				VectorCopy (ptri[i].verts[j], base_xyz[model.num_xyz]);
+
+				if(clustered)
+					ReplaceClusterIndex(k, ptri[i].indicies[j], (int **)&clusters, (IntListNode_t **)&vertLists, (int *)&num_verts, (int *)&new_num_verts);
+
+				model.num_xyz++;
+			}
+
+			triangles[i].index_xyz[j] = k;
+
+			// get the st index
+			for (k=0 ; k<model.num_st ; k++)
+				if (triangle_st[i][j][0] == base_st[k].s
+				&& triangle_st[i][j][1] == base_st[k].t)
+					break;	// this vertex is already in the base vertex list
+
+			if (k == model.num_st)
+			{ // new index
+				base_st[model.num_st].s = triangle_st[i][j][0];
+				base_st[model.num_st].t = triangle_st[i][j][1];
+				model.num_st++;
+			}
+
+			triangles[i].index_st[j] = k;
+		}
+	}
+
+	// build triangle strips / fans
+	BuildGlCmds ();
+}
+
+//===============================================================
+
+char	*FindFrameFile (char *frame)
+{
+	int				time1;
+	char			file1[1024];
+	static char		retname[1024];
+	char			base[32];
+	char			suffix[32];
+	char			*s;
+
+	if (strstr (frame, "."))
+		return frame;		// allready in dot format
+
+	// split 'run1' into 'run' and '1'
+	s = frame + strlen(frame)-1;
+
+	while (s != frame && *s >= '0' && *s <= '9')
+		s--;
+
+	strcpy (suffix, s+1);
+	strcpy (base, frame);
+	base[s-frame+1] = 0;
+
+	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "hrc");
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s%s.%s", base, suffix, "hrc");
+		return retname;
+	}
+
+	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "asc");
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s%s.%s", base, suffix, "asc");
+		return retname;
+	}
+
+	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "tri");
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s%s.%s", base, suffix, "tri");
+		return retname;
+	}
+
+	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "3ds");
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s%s.%s", base, suffix, "3ds");
+		return retname;
+	}
+
+	sprintf (file1, "%s/%s%s.%s",cddir, base, suffix, "htr");
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s%s.%s", base, suffix, "htr");
+		return retname;
+	}
+
+	// check for 'run.1'
+	sprintf (file1, "%s/%s.%s",cddir, base, suffix);
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s.%s", base, suffix);
+		return retname;
+	}
+
+	Error ("frame %s could not be found",frame);
+	return NULL;
+}
+
+/*
+===============
+GrabFrame
+===============
+*/
+static void GrabFrame (char *frame)
+{
+	triangle_t		*ptri;
+	int				i, j;
+	trivert_t		*ptrivert;
+	int				num_tris;
+	char			file1[1024];
+	frame_t			*fr;
+	vertexnormals_t	vnorms[MAX_VERTS];
+	int				index_xyz;
+	char			*framefile;
+
+	// the frame 'run1' will be looked for as either
+	// run.1 or run1.tri, so the new alias sequence save
+	// feature an be used
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+	printf ("grabbing %s  ", file1);
+
+	if (model.num_frames >= MAX_FRAMES)
+		Error ("model.num_frames >= MAX_FRAMES");
+	fr = &g_frames[model.num_frames];
+	model.num_frames++;
+
+	strcpy (fr->name, frame);
+
+//
+// load the frame
+//
+	if (do3ds)
+		Load3DSTriangleList (file1, &ptri, &num_tris, NULL, NULL);
+	else
+		LoadTriangleList (file1, &ptri, &num_tris, NULL, NULL);
+
+	if (num_tris != model.num_tris)
+		Error ("%s: number of triangles doesn't match base frame\n", file1);
+
+//
+// allocate storage for the frame's vertices
+//
+	ptrivert = fr->v;
+
+	for (i=0 ; i<model.num_xyz ; i++)
+	{
+		vnorms[i].numnormals = 0;
+		VectorClear (vnorms[i].normalsum);
+	}
+	ClearBounds (fr->mins, fr->maxs);
+
+//
+// store the frame's vertices in the same order as the base. This assumes the
+// triangles and vertices in this frame are in exactly the same order as in the
+// base
+//
+	for (i=0 ; i<num_tris ; i++)
+	{
+		vec3_t	vtemp1, vtemp2, normal;
+		float	ftemp;
+
+		VectorSubtract (ptri[i].verts[0], ptri[i].verts[1], vtemp1);
+		VectorSubtract (ptri[i].verts[2], ptri[i].verts[1], vtemp2);
+		CrossProduct (vtemp1, vtemp2, normal);
+
+		VectorNormalize (normal, normal);
+
+	// rotate the normal so the model faces down the positive x axis
+		ftemp = normal[0];
+		normal[0] = -normal[1];
+		normal[1] = ftemp;
+
+		for (j=0 ; j<3 ; j++)
+		{
+			index_xyz = triangles[i].index_xyz[j];
+
+		// rotate the vertices so the model faces down the positive x axis
+		// also adjust the vertices to the desired origin
+			ptrivert[index_xyz].v[0] = ((-ptri[i].verts[j][1]) * scale_up) +
+										adjust[0];
+			ptrivert[index_xyz].v[1] = (ptri[i].verts[j][0] * scale_up) +
+										adjust[1];
+			ptrivert[index_xyz].v[2] = (ptri[i].verts[j][2] * scale_up) +
+										adjust[2];
+
+			AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
+
+			VectorAdd (vnorms[index_xyz].normalsum, normal, vnorms[index_xyz].normalsum);
+			vnorms[index_xyz].numnormals++;
+		}
+	}
+
+//
+// calculate the vertex normals, match them to the template list, and store the
+// index of the best match
+//
+	for (i=0 ; i<model.num_xyz ; i++)
+	{
+		int		j;
+		vec3_t	v;
+		float	maxdot;
+		int		maxdotindex;
+		int		c;
+
+		c = vnorms[i].numnormals;
+		if (!c)
+			Error ("Vertex with no triangles attached");
+
+		VectorScale (vnorms[i].normalsum, 1.0/c, v);
+		VectorNormalize (v, v);
+
+		maxdot = -999999.0;
+		maxdotindex = -1;
+
+		for (j=0 ; j<NUMVERTEXNORMALS ; j++)
+		{
+			float	dot;
+
+			dot = DotProduct (v, avertexnormals[j]);
+			if (dot > maxdot)
+			{
+				maxdot = dot;
+				maxdotindex = j;
+			}
+		}
+
+		ptrivert[i].lightnormalindex = maxdotindex;
+	}
+
+	free (ptri);
+}
+
+/*
+===============
+GrabJointedFrame
+===============
+*/
+void GrabJointedFrame(char *frame)
+{
+	char	file1[1024];
+	char	*framefile;
+	frame_t		*fr;
+
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+	printf ("grabbing %s\n", file1);
+
+	fr = &g_frames[model.num_frames - 1]; // last frame read in
+
+	LoadJointList(file1, fr->joints, jointed);
+}
+
+/*
+===============
+GrabGlobals
+===============
+*/
+void GrabGlobals(char *frame)
+{
+	char	file1[1024];
+	char	*framefile;
+	frame_t		*fr;
+
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+	printf ("grabbing %s\n", file1);
+
+	fr = &g_frames[model.num_frames - 1]; // last frame read in
+
+	LoadGlobals(file1);
+}
+
+/*
+===============
+Cmd_Frame	
+===============
+*/
+void Cmd_Frame (void)
+{
+	while (ScriptTokenAvailable())
+	{
+		GetScriptToken (false);
+		if (g_skipmodel)
+			continue;
+		if (g_release || g_archive)
+		{
+			model.num_frames = 1;	// don't skip the writeout
+			continue;
+		}
+
+		H_printf("#define FRAME_%-16s\t%i\n", token, model.num_frames);
+
+		GrabFrame (token);
+	}
+}
+
+/*
+===============
+Cmd_Skin
+
+Skins aren't actually stored in the file, only a reference
+is saved out to the header file.
+===============
+*/
+void Cmd_Skin (void)
+{
+	byte	*palette;
+	byte	*pixels;
+	int		width, height;
+	byte	*cropped;
+	int		y;
+	char	name[1024], savename[1024];
+
+	GetScriptToken (false);
+
+	if (model.num_skins == MAX_MD2SKINS)
+		Error ("model.num_skins == MAX_MD2SKINS");
+
+	if (g_skipmodel)
+		return;
+
+#if 1
+	sprintf (name, "%s/%s.pcx", cddir, token);
+	sprintf (savename, "%s/!%s.pcx", g_outputDir, token);
+	sprintf (g_skins[model.num_skins], "%s/!%s.pcx", cdpartial, token);
+#else
+	sprintf (name, "%s/%s.lbm", cdarchive, token);
+	strcpy (name, ExpandPathAndArchive( name ) );
+//	sprintf (name, "%s/%s.lbm", cddir, token);
+
+	if (ScriptTokenAvailable())
+	{
+		GetScriptToken (false);
+		sprintf (g_skins[model.num_skins], "%s.pcx", token);
+		sprintf (savename, "%s%s.pcx", g_outputDir, g_skins[model.num_skins]);
+	}
+	else
+	{
+		sprintf (savename, "%s/%s.pcx", g_outputDir, token);
+		sprintf (g_skins[model.num_skins], "%s/%s.pcx", cdpartial, token);
+	}
+#endif
+
+	model.num_skins++;
+
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	// load the image
+	printf ("loading %s\n", name);
+	Load256Image (name, &pixels, &palette, &width, &height);
+//	RemapZero (pixels, palette, width, height);
+
+	// crop it to the proper size
+	cropped = (byte *) SafeMalloc (model.skinwidth*model.skinheight, "Cmd_Skin");
+	for (y=0 ; y<model.skinheight ; y++)
+	{
+		memcpy (cropped+y*model.skinwidth,
+			pixels+y*width, model.skinwidth);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, model.skinwidth,
+		model.skinheight, palette);
+
+	free (pixels);
+	free (palette);
+	free (cropped);
+}
+
+
+/*
+=================
+Cmd_Origin
+=================
+*/
+void Cmd_Origin (void)
+{
+	// rotate points into frame of reference so model points down the
+	// positive x axis
+	GetScriptToken (false);
+	adjust[1] = -atof (token);
+
+	GetScriptToken (false);
+	adjust[0] = atof (token);
+
+	GetScriptToken (false);
+	adjust[2] = -atof (token);
+}
+
+
+/*
+=================
+Cmd_ScaleUp
+=================
+*/
+void Cmd_ScaleUp (void)
+{
+	GetScriptToken (false);
+	scale_up = atof (token);
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	printf ("Scale up: %f\n", scale_up);
+}
+
+
+/*
+=================
+Cmd_Skinsize
+
+Set a skin size other than the default
+=================
+*/
+void Cmd_Skinsize (void)
+{
+	GetScriptToken (false);
+	g_fixedwidth = atoi(token);
+	GetScriptToken (false);
+	g_fixedheight = atoi(token);
+}
+
+/*
+=================
+Cmd_Modelname
+
+Gives a different name/location for the file, instead of the cddir
+=================
+*/
+void Cmd_Modelname (void)
+{
+	GetScriptToken (false);
+	strcpy (modelname, token);
+}
+
+/*
+===============
+Cmd_Cd
+===============
+*/
+void Cmd_Cd (void)
+{
+	char temp[256];
+
+	FinishModel ();
+	ClearModel ();
+
+	GetScriptToken (false);
+
+	// this is a silly mess...
+	sprintf (cdpartial, "models/%s", token); 
+	sprintf (cdarchive, "%smodels/%s", gamedir+strlen(qdir), token); 
+	sprintf (cddir, "%s%s", gamedir, cdpartial);
+
+	// Since we also changed directories on the output side (for mirror) make sure the outputdir is set properly too.
+	sprintf(temp, "%s%s", g_outputDir, cdpartial);
+	strcpy(g_outputDir, temp);
+
+	// if -only was specified and this cd doesn't match,
+	// skip the model (you only need to match leading chars,
+	// so you could regrab all monsters with -only monsters)
+	if (!g_only[0])
+		return;
+	if (strncmp(token, g_only, strlen(g_only)))
+	{
+		g_skipmodel = true;
+		printf ("skipping %s\n", cdpartial);
+	}
+}
+
+/*
+=================
+Cmd_Cluster
+=================
+*/
+void Cmd_Cluster()
+{
+	char file1[1024];
+
+	GetScriptToken (false);
+
+	printf ("---------------------\n");
+	sprintf (file1, "%s/%s", cdpartial, token);
+	printf ("%s\n", file1);
+
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s", cddir, token);
+
+	LoadClusters(file1, (int **)&clusters, (int *)&num_verts, jointed);
+
+	new_num_verts[0] = num_verts[0];
+
+	clustered = 1;
+}
+
+// Model construction cover functions.
+void MODELCMD_Modelname (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	Cmd_Modelname ();
+/*
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Modelname ();		
+		break;
+	case MODEL_FM:
+		Cmd_FMModelname ();
+		break;
+	}
+*/
+}
+
+void MODELCMD_Cd (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Cd ();
+		break;
+	case MODEL_FM:
+		Cmd_FMCd ();
+		break;
+	}
+}
+
+void MODELCMD_Origin (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	Cmd_Origin ();
+/*	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Origin ();
+		break;
+	case MODEL_FM:
+		Cmd_FMOrigin ();
+		break;
+	}
+*/
+}
+
+void MODELCMD_Cluster (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Cluster ();
+		break;
+	case MODEL_FM:
+		Cmd_FMCluster ();
+		break;
+	}
+}
+
+void MODELCMD_Base (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Base ();
+		break;
+	case MODEL_FM:
+		Cmd_FMBase (false);
+		break;
+	}
+}
+
+void MODELCMD_BaseST (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Base ();
+		break;
+	case MODEL_FM:
+		Cmd_FMBase (true);
+		break;
+	}
+}
+
+void MODELCMD_ScaleUp (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	Cmd_ScaleUp ();
+/*	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_ScaleUp ();
+		break;
+	case MODEL_FM:
+		Cmd_FMScaleUp ();
+		break;
+	}
+*/
+}
+
+void MODELCMD_Frame (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Frame ();
+		break;
+	case MODEL_FM:
+		Cmd_FMFrame ();
+		break;
+	}
+}
+
+void MODELCMD_Skin (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Skin ();
+		break;
+	case MODEL_FM:
+		Cmd_FMSkin ();
+		break;
+	}
+}
+
+void MODELCMD_Skinsize (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	Cmd_Skinsize ();
+/*
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		Cmd_Skinsize ();
+		break;
+	case MODEL_FM:
+		Cmd_FMSkinsize ();
+		break;
+	}
+*/
+}
+
+void MODELCMD_Skeleton (int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		break;
+	case MODEL_FM:
+		Cmd_FMSkeleton ();
+		break;
+	}
+}
+
+void MODELCMD_BeginGroup(int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		break;
+	case MODEL_FM:
+		Cmd_FMBeginGroup();
+		break;
+	}
+}
+
+void MODELCMD_EndGroup(int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		break;
+	case MODEL_FM:
+		Cmd_FMEndGroup();
+		break;
+	}
+}
+
+void MODELCMD_Referenced(int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		break;
+	case MODEL_FM:
+		Cmd_FMReferenced();
+		break;
+	}
+}
+
+void MODELCMD_NodeOrder(int modeltype)
+{
+	if (g_forcemodel)
+		modeltype = g_forcemodel;
+
+	switch(modeltype)
+	{
+	case MODEL_MD2:
+		break;
+	case MODEL_FM:
+		Cmd_FMNodeOrder();
+		break;
+	}
+}
diff --git a/tools/quake2/qdata_heretic2/pics.c b/tools/quake2/qdata_heretic2/pics.c
index d227f264..70ff7d52 100644
--- a/tools/quake2/qdata_heretic2/pics.c
+++ b/tools/quake2/qdata_heretic2/pics.c
@@ -1,198 +1,198 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "qdata.h"
-
-byte			*byteimage, *lbmpalette;
-int				byteimagewidth, byteimageheight;
-
-qboolean		TrueColorImage;
-unsigned		*longimage;
-int				longimagewidth, longimageheight;
-
-char			pic_prefix[1024];
-extern 	char		*g_outputDir;
-
-/*
-===============
-Cmd_Pic
-===============
-*/
-
-void Cmd_Pic (void)
-{
-	int             xl,yl,xh,yh,w,h;
-	byte            *dest, *source;
-	int				flags, value, contents;
-	char			lumpname[128];
-	char			animname[128];
-	byte			buffer[256*256];
-	unsigned		bufferl[256*256];
-	char			filename[1024];
-	unsigned        *destl, *sourcel;
-	int             linedelta, x, y;
-	int				size;
-	miptex_t		*qtex;
-	miptex32_t		*qtex32;
-	float			scale_x, scale_y;
-
-	GetScriptToken (false);
-	strcpy (lumpname, token);
-	
-	GetScriptToken (false);
-	xl = atoi (token);
-	GetScriptToken (false);
-	yl = atoi (token);
-	GetScriptToken (false);
-	w = atoi (token);
-	GetScriptToken (false);
-	h = atoi (token);
-
-	total_x += w;
-	total_y += h;
-	total_textures++;
-
-	if ( (w & 7) || (h & 7) )
-		Error ("line %i: miptex sizes must be multiples of 8", scriptline);
-
-	flags = 0;
-	contents = 0;
-	value = 0;
-
-	animname[0] = 0;
-
-	scale_x = scale_y = 0.5;
-
-	if (TrueColorImage)
-	{
-		sprintf (filename, "%spics/%s/%s.m32", g_outputDir, pic_prefix, lumpname);
-		if (g_release)
-			return;	// textures are only released by $maps
-
-		xh = xl+w;
-		yh = yl+h;
-
-		if (xl >= longimagewidth || xh > longimagewidth ||
-			yl >= longimageheight || yh > longimageheight)
-		{
-			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
-		}
-
-		sourcel = longimage + (yl*longimagewidth) + xl;
-		destl = bufferl;
-		linedelta = (longimagewidth - w);
-
-		for (y=yl ; y<yh ; y++)
-		{
-			for (x=xl ; x<xh ; x++)
-			{
-				*destl++ = *sourcel++;	// RGBA
-			}
-			sourcel += linedelta;
-		}
-
-		qtex32 = CreateMip32(bufferl, w, h, &size, false);
-
-		qtex32->flags |= LittleLong(flags);
-		qtex32->contents = contents;
-		qtex32->value = value;
-		qtex32->scale_x = scale_x;
-		qtex32->scale_y = scale_y;
-		sprintf (qtex32->name, "%s/%s", pic_prefix, lumpname);
-		if (animname[0])
-			sprintf (qtex32->animname, "%s/%s", pic_prefix, animname);
-		
-	//
-	// write it out
-	//
-		printf ("writing %s\n", filename);
-		SaveFile (filename, (byte *)qtex32, size);
-
-		free (qtex32);
-	}
-	else
-	{
-		sprintf (filename, "%spics/%s/%s.m8", g_outputDir, pic_prefix, lumpname);
-		if (g_release)
-			return;	// textures are only released by $maps
-
-		xh = xl+w;
-		yh = yl+h;
-
-		if (xl >= byteimagewidth || xh > byteimagewidth ||
-			yl >= byteimageheight || yh > byteimageheight)
-		{
-			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
-		}
-
-		source = byteimage + yl*byteimagewidth + xl;
-		dest = buffer;
-		linedelta = byteimagewidth - w;
-
-		for (y=yl ; y<yh ; y++)
-		{
-			for (x=xl ; x<xh ; x++)
-			{
-				*dest++ = *source++;
-			}
-			source += linedelta;
-		}
-
-		qtex = CreateMip(buffer, w, h, lbmpalette, &size, false);
-
-		qtex->flags = flags;
-		qtex->contents = contents;
-		qtex->value = value;
-		sprintf (qtex->name, "%s/%s", pic_prefix, lumpname);
-		if (animname[0])
-			sprintf (qtex->animname, "%s/%s", pic_prefix, animname);
-		
-	//
-	// write it out
-	//
-		printf ("writing %s\n", filename);
-		SaveFile (filename, (byte *)qtex, size);
-
-		free (qtex);
-	}
-}
-
-
-/*
-===============
-Cmd_picdir
-===============
-*/
-void Cmd_Picdir (void)
-{
-	char	filename[1024];
-
-	GetScriptToken (false);
-	strcpy (pic_prefix, token);
-	// create the directory if needed
-	sprintf (filename, "%sPics", g_outputDir);
-	Q_mkdir (filename); 
-	sprintf (filename, "%sPics/%s", g_outputDir, pic_prefix);
-	Q_mkdir (filename); 
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "qdata.h"
+
+byte			*byteimage, *lbmpalette;
+int				byteimagewidth, byteimageheight;
+
+qboolean		TrueColorImage;
+unsigned		*longimage;
+int				longimagewidth, longimageheight;
+
+char			pic_prefix[1024];
+extern 	char		*g_outputDir;
+
+/*
+===============
+Cmd_Pic
+===============
+*/
+
+void Cmd_Pic (void)
+{
+	int             xl,yl,xh,yh,w,h;
+	byte            *dest, *source;
+	int				flags, value, contents;
+	char			lumpname[128];
+	char			animname[128];
+	byte			buffer[256*256];
+	unsigned		bufferl[256*256];
+	char			filename[1024];
+	unsigned        *destl, *sourcel;
+	int             linedelta, x, y;
+	int				size;
+	miptex_t		*qtex;
+	miptex32_t		*qtex32;
+	float			scale_x, scale_y;
+
+	GetScriptToken (false);
+	strcpy (lumpname, token);
+	
+	GetScriptToken (false);
+	xl = atoi (token);
+	GetScriptToken (false);
+	yl = atoi (token);
+	GetScriptToken (false);
+	w = atoi (token);
+	GetScriptToken (false);
+	h = atoi (token);
+
+	total_x += w;
+	total_y += h;
+	total_textures++;
+
+	if ( (w & 7) || (h & 7) )
+		Error ("line %i: miptex sizes must be multiples of 8", scriptline);
+
+	flags = 0;
+	contents = 0;
+	value = 0;
+
+	animname[0] = 0;
+
+	scale_x = scale_y = 0.5;
+
+	if (TrueColorImage)
+	{
+		sprintf (filename, "%spics/%s/%s.m32", g_outputDir, pic_prefix, lumpname);
+		if (g_release)
+			return;	// textures are only released by $maps
+
+		xh = xl+w;
+		yh = yl+h;
+
+		if (xl >= longimagewidth || xh > longimagewidth ||
+			yl >= longimageheight || yh > longimageheight)
+		{
+			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
+		}
+
+		sourcel = longimage + (yl*longimagewidth) + xl;
+		destl = bufferl;
+		linedelta = (longimagewidth - w);
+
+		for (y=yl ; y<yh ; y++)
+		{
+			for (x=xl ; x<xh ; x++)
+			{
+				*destl++ = *sourcel++;	// RGBA
+			}
+			sourcel += linedelta;
+		}
+
+		qtex32 = CreateMip32(bufferl, w, h, &size, false);
+
+		qtex32->flags |= LittleLong(flags);
+		qtex32->contents = contents;
+		qtex32->value = value;
+		qtex32->scale_x = scale_x;
+		qtex32->scale_y = scale_y;
+		sprintf (qtex32->name, "%s/%s", pic_prefix, lumpname);
+		if (animname[0])
+			sprintf (qtex32->animname, "%s/%s", pic_prefix, animname);
+		
+	//
+	// write it out
+	//
+		printf ("writing %s\n", filename);
+		SaveFile (filename, (byte *)qtex32, size);
+
+		free (qtex32);
+	}
+	else
+	{
+		sprintf (filename, "%spics/%s/%s.m8", g_outputDir, pic_prefix, lumpname);
+		if (g_release)
+			return;	// textures are only released by $maps
+
+		xh = xl+w;
+		yh = yl+h;
+
+		if (xl >= byteimagewidth || xh > byteimagewidth ||
+			yl >= byteimageheight || yh > byteimageheight)
+		{
+			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
+		}
+
+		source = byteimage + yl*byteimagewidth + xl;
+		dest = buffer;
+		linedelta = byteimagewidth - w;
+
+		for (y=yl ; y<yh ; y++)
+		{
+			for (x=xl ; x<xh ; x++)
+			{
+				*dest++ = *source++;
+			}
+			source += linedelta;
+		}
+
+		qtex = CreateMip(buffer, w, h, lbmpalette, &size, false);
+
+		qtex->flags = flags;
+		qtex->contents = contents;
+		qtex->value = value;
+		sprintf (qtex->name, "%s/%s", pic_prefix, lumpname);
+		if (animname[0])
+			sprintf (qtex->animname, "%s/%s", pic_prefix, animname);
+		
+	//
+	// write it out
+	//
+		printf ("writing %s\n", filename);
+		SaveFile (filename, (byte *)qtex, size);
+
+		free (qtex);
+	}
+}
+
+
+/*
+===============
+Cmd_picdir
+===============
+*/
+void Cmd_Picdir (void)
+{
+	char	filename[1024];
+
+	GetScriptToken (false);
+	strcpy (pic_prefix, token);
+	// create the directory if needed
+	sprintf (filename, "%sPics", g_outputDir);
+	Q_mkdir (filename); 
+	sprintf (filename, "%sPics/%s", g_outputDir, pic_prefix);
+	Q_mkdir (filename); 
+}
+
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/angles.h b/tools/quake2/qdata_heretic2/qcommon/angles.h
index b264f96a..e51d2e29 100644
--- a/tools/quake2/qdata_heretic2/qcommon/angles.h
+++ b/tools/quake2/qdata_heretic2/qcommon/angles.h
@@ -1,76 +1,76 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// Angles in radians
-
-#define ANGLE_0			0.0F
-#define ANGLE_1			0.017453292F
-#define ANGLE_5			0.087266462F
-#define ANGLE_10		0.174532925F
-#define ANGLE_15		0.261799387F
-#define ANGLE_20		0.392699081F
-#define ANGLE_30		0.523598775F
-#define ANGLE_45		0.785398163F
-#define ANGLE_60		1.047197551F
-#define ANGLE_72		1.256637061F
-#define ANGLE_90		1.570796327F
-#define ANGLE_120		2.094395102F
-#define ANGLE_135		2.35619449F
-#define ANGLE_144		2.513274123F
-#define ANGLE_180		3.141592653F
-#define	ANGLE_225		3.926990817F
-#define ANGLE_270		4.71238898F
-#define	ANGLE_315		5.497787144F
-#define ANGLE_360		6.283185307F
-
-// Angles in degrees
-
-#define DEGREE_0		0.0F
-#define DEGREE_180		180.0F
-#define DEGREE_45		(DEGREE_180 / 4.0F)
-#define DEGREE_90		(DEGREE_180 / 2.0F)
-#define DEGREE_135		(DEGREE_90 + DEGREE_45)
-#define DEGREE_270		(DEGREE_180 + DEGREE_90)
-#define DEGREE_360		(DEGREE_180 * 2.0F)
-
-#define	DEGREE_225		(DEGREE_180 + DEGREE_45)
-#define	DEGREE_315		(DEGREE_270 + DEGREE_45)
-
-#define DEGREE_30		(DEGREE_180 / 6.0F)
-#define DEGREE_60		(DEGREE_180 / 3.0F)
-#define DEGREE_120		(DEGREE_360 / 3.0F)
-
-#define DEGREE_1		(DEGREE_180 / 180.0F)
-#define DEGREE_5		(DEGREE_180 / 36.0F)
-#define DEGREE_10		(DEGREE_180 / 18.0F)
-#define DEGREE_15		(DEGREE_180 / 12.0F)
-#define DEGREE_20		(DEGREE_180 / 8.0F)
-
-// Conversion routines
-
-#define ANGLE_TO_RAD	ANGLE_1
-#define RAD_TO_ANGLE	(180.0F / ANGLE_180)
-
-#define	SHORT_TO_ANGLE	(360.0/65536)
-
-
-#pragma warning(disable : 4305)		// 'initializing' : truncation from 'const double ' to 'float '
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Angles in radians
+
+#define ANGLE_0			0.0F
+#define ANGLE_1			0.017453292F
+#define ANGLE_5			0.087266462F
+#define ANGLE_10		0.174532925F
+#define ANGLE_15		0.261799387F
+#define ANGLE_20		0.392699081F
+#define ANGLE_30		0.523598775F
+#define ANGLE_45		0.785398163F
+#define ANGLE_60		1.047197551F
+#define ANGLE_72		1.256637061F
+#define ANGLE_90		1.570796327F
+#define ANGLE_120		2.094395102F
+#define ANGLE_135		2.35619449F
+#define ANGLE_144		2.513274123F
+#define ANGLE_180		3.141592653F
+#define	ANGLE_225		3.926990817F
+#define ANGLE_270		4.71238898F
+#define	ANGLE_315		5.497787144F
+#define ANGLE_360		6.283185307F
+
+// Angles in degrees
+
+#define DEGREE_0		0.0F
+#define DEGREE_180		180.0F
+#define DEGREE_45		(DEGREE_180 / 4.0F)
+#define DEGREE_90		(DEGREE_180 / 2.0F)
+#define DEGREE_135		(DEGREE_90 + DEGREE_45)
+#define DEGREE_270		(DEGREE_180 + DEGREE_90)
+#define DEGREE_360		(DEGREE_180 * 2.0F)
+
+#define	DEGREE_225		(DEGREE_180 + DEGREE_45)
+#define	DEGREE_315		(DEGREE_270 + DEGREE_45)
+
+#define DEGREE_30		(DEGREE_180 / 6.0F)
+#define DEGREE_60		(DEGREE_180 / 3.0F)
+#define DEGREE_120		(DEGREE_360 / 3.0F)
+
+#define DEGREE_1		(DEGREE_180 / 180.0F)
+#define DEGREE_5		(DEGREE_180 / 36.0F)
+#define DEGREE_10		(DEGREE_180 / 18.0F)
+#define DEGREE_15		(DEGREE_180 / 12.0F)
+#define DEGREE_20		(DEGREE_180 / 8.0F)
+
+// Conversion routines
+
+#define ANGLE_TO_RAD	ANGLE_1
+#define RAD_TO_ANGLE	(180.0F / ANGLE_180)
+
+#define	SHORT_TO_ANGLE	(360.0/65536)
+
+
+#pragma warning(disable : 4305)		// 'initializing' : truncation from 'const double ' to 'float '
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h b/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h
index d329d1a6..831f37cf 100644
--- a/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h
+++ b/tools/quake2/qdata_heretic2/qcommon/arrayedlist.h
@@ -1,71 +1,71 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _ARRAYEDLIST_H
-#define _ARRAYEDLIST_H
-
-#include <assert.h>
-
-typedef struct ArrayedListNode_s
-{
-	int data;
-	int next;
-	int inUse;
-} ArrayedListNode_t;
-
-#define ARRAYEDLISTNODE_NULL -1
-
-static 
-#ifdef _WIN32
-  _inline
-#else
-  inline
-#endif  
-  int GetFreeNode(ArrayedListNode_t *nodeArray, int max)
-{
-	int i;
-
-	for(i = 0; i < max; ++i)
-	{
-		if(!nodeArray[i].inUse)
-		{
-			nodeArray[i].inUse = 1;
-			return i;
-		}
-	}
-
-	assert(0);
-	return -1;
-}
-
-static 
-#ifdef _WIN32
-  _inline
-#else
-  inline
-#endif
-void FreeNode(ArrayedListNode_t *nodeArray, int index)
-{
-	nodeArray[index].inUse = 0;
-}
-
-#endif //_ARRAYEDLIST_H
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _ARRAYEDLIST_H
+#define _ARRAYEDLIST_H
+
+#include <assert.h>
+
+typedef struct ArrayedListNode_s
+{
+	int data;
+	int next;
+	int inUse;
+} ArrayedListNode_t;
+
+#define ARRAYEDLISTNODE_NULL -1
+
+static 
+#ifdef _WIN32
+  _inline
+#else
+  inline
+#endif  
+  int GetFreeNode(ArrayedListNode_t *nodeArray, int max)
+{
+	int i;
+
+	for(i = 0; i < max; ++i)
+	{
+		if(!nodeArray[i].inUse)
+		{
+			nodeArray[i].inUse = 1;
+			return i;
+		}
+	}
+
+	assert(0);
+	return -1;
+}
+
+static 
+#ifdef _WIN32
+  _inline
+#else
+  inline
+#endif
+void FreeNode(ArrayedListNode_t *nodeArray, int index)
+{
+	nodeArray[index].inUse = 0;
+}
+
+#endif //_ARRAYEDLIST_H
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/flex.h b/tools/quake2/qdata_heretic2/qcommon/flex.h
index c3cf6076..db86ac67 100644
--- a/tools/quake2/qdata_heretic2/qcommon/flex.h
+++ b/tools/quake2/qdata_heretic2/qcommon/flex.h
@@ -1,33 +1,33 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// Generic flexible format 
-
-typedef struct
-{
-	char	ident[32];
-	int		version;
-	int		size;
-} header_t;
-
-void WriteHeader(FILE *, char *, int, int, void *);
-
-// end
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// Generic flexible format 
+
+typedef struct
+{
+	char	ident[32];
+	int		version;
+	int		size;
+} header_t;
+
+void WriteHeader(FILE *, char *, int, int, void *);
+
+// end
diff --git a/tools/quake2/qdata_heretic2/qcommon/fmodel.h b/tools/quake2/qdata_heretic2/qcommon/fmodel.h
index f33efa47..f52d922c 100644
--- a/tools/quake2/qdata_heretic2/qcommon/fmodel.h
+++ b/tools/quake2/qdata_heretic2/qcommon/fmodel.h
@@ -1,202 +1,202 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-/*
-========================================================================
-
-.FM triangle flexible model file format
-
-========================================================================
-*/
-
-#ifndef __FMODEL_HEADER
-#define __FMODEL_HEADER
-
-#include "bspfile.h"
-
-//typedef unsigned char 		byte;
-//typedef int	qboolean;
-//typedef float vec3_t[3];
-
-#define	MAX_FM_TRIANGLES	2048
-#define MAX_FM_VERTS		2048
-#define MAX_FM_FRAMES		2048
-#define MAX_FM_SKINS		64
-#define	MAX_FM_SKINNAME		64
-#define MAX_FM_MESH_NODES	16		// also defined in game/qshared.h
-
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-#define SKINPAGE_WIDTH 640
-#define SKINPAGE_HEIGHT 480
-
-#define ENCODED_WIDTH_X 92
-#define ENCODED_WIDTH_Y 475
-#define ENCODED_HEIGHT_X 128
-#define ENCODED_HEIGHT_Y 475
-
-#define SCALE_ADJUST_FACTOR 0.96
-
-#define INFO_HEIGHT 5
-#define INFO_Y (SKINPAGE_HEIGHT-INFO_HEIGHT)
-
-extern byte		*BasePalette;
-extern byte		*BasePixels,*TransPixels;
-extern int		BaseWidth, BaseHeight, TransWidth, TransHeight;
-extern int ScaleWidth, ScaleHeight;
-
-int ExtractNumber(byte *pic, int x, int y);
-void DrawTextChar(int x, int y, char *text);
-void DrawLine(int x1, int y1, int x2, int y2);
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-// Initial Header
-#define FM_HEADER_NAME	"header"
-#define FM_HEADER_VER	2
-
-typedef struct
-{
-	int			skinwidth;
-	int			skinheight;
-	int			framesize;		// byte size of each frame
-
-	int			num_skins;
-	int			num_xyz;
-	int			num_st;			// greater than num_xyz for seams
-	int			num_tris;
-	int			num_glcmds;		// dwords in strip/fan command list
-	int			num_frames;
-	int			num_mesh_nodes;
-} fmheader_t;
-
-
-// Skin Header
-#define FM_SKIN_NAME	"skin"
-#define FM_SKIN_VER		1
-
-
-// ST Coord Header
-#define FM_ST_NAME		"st coord"
-#define FM_ST_VER		1
-
-typedef struct
-{
-	short	s;
-	short	t;
-} fmstvert_t;
-
-
-// Tri Header
-#define FM_TRI_NAME		"tris"
-#define FM_TRI_VER		1
-
-typedef struct 
-{
-	short	index_xyz[3];
-	short	index_st[3];
-} fmtriangle_t;
-
-
-// Frame Header
-#define FM_FRAME_NAME	"frames"
-#define FM_FRAME_VER	1
-
-// Frame for compression, just the names
-#define FM_SHORT_FRAME_NAME	"short frames"
-#define FM_SHORT_FRAME_VER	1
-
-// Normals for compressed frames
-#define FM_NORMAL_NAME	"normals"
-#define FM_NORMAL_VER	1
-
-// Compressed Frame Data
-#define FM_COMP_NAME	"comp data"
-#define FM_COMP_VER	1
-
-// GL Cmds Header
-#define FM_GLCMDS_NAME	"glcmds"
-#define FM_GLCMDS_VER	1
-
-
-// Mesh Nodes Header
-#define FM_MESH_NAME	"mesh nodes"
-#define FM_MESH_VER		3
-
-// Skeleton Header
-#define FM_SKELETON_NAME "skeleton"
-#define FM_SKELETON_VER	1
-
-// References Header
-#define FM_REFERENCES_NAME "references"
-#define FM_REFERENCES_VER	1
-
-typedef struct
-{
-
-	union
-	{
-
-	byte	tris[MAX_FM_TRIANGLES>>3];
-
-	struct {
-	short	*triIndicies;
-	int		num_tris;
-	};
-
-	};
-
-	byte	verts[MAX_FM_VERTS>>3];
-	short	start_glcmds, num_glcmds;
-} fmmeshnode_t;
-
-//=================================================================
-
-// Frame info
-typedef struct
-{
-	byte	v[3];			// scaled byte to fit in frame mins/maxs
-	byte	lightnormalindex;
-} fmtrivertx_t;
-
-typedef struct
-{
-	float			scale[3];		// multiply byte verts by this
-	float			translate[3];	// then add this
-	char			name[16];		// frame name from grabbing
-	fmtrivertx_t	verts[1];		// variable sized
-} fmaliasframe_t;
-
-
-#endif // #define __FMODEL_HEADER
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+/*
+========================================================================
+
+.FM triangle flexible model file format
+
+========================================================================
+*/
+
+#ifndef __FMODEL_HEADER
+#define __FMODEL_HEADER
+
+#include "bspfile.h"
+
+//typedef unsigned char 		byte;
+//typedef int	qboolean;
+//typedef float vec3_t[3];
+
+#define	MAX_FM_TRIANGLES	2048
+#define MAX_FM_VERTS		2048
+#define MAX_FM_FRAMES		2048
+#define MAX_FM_SKINS		64
+#define	MAX_FM_SKINNAME		64
+#define MAX_FM_MESH_NODES	16		// also defined in game/qshared.h
+
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+#define SKINPAGE_WIDTH 640
+#define SKINPAGE_HEIGHT 480
+
+#define ENCODED_WIDTH_X 92
+#define ENCODED_WIDTH_Y 475
+#define ENCODED_HEIGHT_X 128
+#define ENCODED_HEIGHT_Y 475
+
+#define SCALE_ADJUST_FACTOR 0.96
+
+#define INFO_HEIGHT 5
+#define INFO_Y (SKINPAGE_HEIGHT-INFO_HEIGHT)
+
+extern byte		*BasePalette;
+extern byte		*BasePixels,*TransPixels;
+extern int		BaseWidth, BaseHeight, TransWidth, TransHeight;
+extern int ScaleWidth, ScaleHeight;
+
+int ExtractNumber(byte *pic, int x, int y);
+void DrawTextChar(int x, int y, char *text);
+void DrawLine(int x1, int y1, int x2, int y2);
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+// Initial Header
+#define FM_HEADER_NAME	"header"
+#define FM_HEADER_VER	2
+
+typedef struct
+{
+	int			skinwidth;
+	int			skinheight;
+	int			framesize;		// byte size of each frame
+
+	int			num_skins;
+	int			num_xyz;
+	int			num_st;			// greater than num_xyz for seams
+	int			num_tris;
+	int			num_glcmds;		// dwords in strip/fan command list
+	int			num_frames;
+	int			num_mesh_nodes;
+} fmheader_t;
+
+
+// Skin Header
+#define FM_SKIN_NAME	"skin"
+#define FM_SKIN_VER		1
+
+
+// ST Coord Header
+#define FM_ST_NAME		"st coord"
+#define FM_ST_VER		1
+
+typedef struct
+{
+	short	s;
+	short	t;
+} fmstvert_t;
+
+
+// Tri Header
+#define FM_TRI_NAME		"tris"
+#define FM_TRI_VER		1
+
+typedef struct 
+{
+	short	index_xyz[3];
+	short	index_st[3];
+} fmtriangle_t;
+
+
+// Frame Header
+#define FM_FRAME_NAME	"frames"
+#define FM_FRAME_VER	1
+
+// Frame for compression, just the names
+#define FM_SHORT_FRAME_NAME	"short frames"
+#define FM_SHORT_FRAME_VER	1
+
+// Normals for compressed frames
+#define FM_NORMAL_NAME	"normals"
+#define FM_NORMAL_VER	1
+
+// Compressed Frame Data
+#define FM_COMP_NAME	"comp data"
+#define FM_COMP_VER	1
+
+// GL Cmds Header
+#define FM_GLCMDS_NAME	"glcmds"
+#define FM_GLCMDS_VER	1
+
+
+// Mesh Nodes Header
+#define FM_MESH_NAME	"mesh nodes"
+#define FM_MESH_VER		3
+
+// Skeleton Header
+#define FM_SKELETON_NAME "skeleton"
+#define FM_SKELETON_VER	1
+
+// References Header
+#define FM_REFERENCES_NAME "references"
+#define FM_REFERENCES_VER	1
+
+typedef struct
+{
+
+	union
+	{
+
+	byte	tris[MAX_FM_TRIANGLES>>3];
+
+	struct {
+	short	*triIndicies;
+	int		num_tris;
+	};
+
+	};
+
+	byte	verts[MAX_FM_VERTS>>3];
+	short	start_glcmds, num_glcmds;
+} fmmeshnode_t;
+
+//=================================================================
+
+// Frame info
+typedef struct
+{
+	byte	v[3];			// scaled byte to fit in frame mins/maxs
+	byte	lightnormalindex;
+} fmtrivertx_t;
+
+typedef struct
+{
+	float			scale[3];		// multiply byte verts by this
+	float			translate[3];	// then add this
+	char			name[16];		// frame name from grabbing
+	fmtrivertx_t	verts[1];		// variable sized
+} fmaliasframe_t;
+
+
+#endif // #define __FMODEL_HEADER
diff --git a/tools/quake2/qdata_heretic2/qcommon/h2common.h b/tools/quake2/qdata_heretic2/qcommon/h2common.h
index a2778f0b..aecfee64 100644
--- a/tools/quake2/qdata_heretic2/qcommon/h2common.h
+++ b/tools/quake2/qdata_heretic2/qcommon/h2common.h
@@ -1,26 +1,26 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef H2COMMON_H
-#define H2COMMON_H
-  #define H2COMMON_API
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef H2COMMON_H
+#define H2COMMON_H
+  #define H2COMMON_API
+#endif
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/placement.h b/tools/quake2/qdata_heretic2/qcommon/placement.h
index df98896f..7194bf3c 100644
--- a/tools/quake2/qdata_heretic2/qcommon/placement.h
+++ b/tools/quake2/qdata_heretic2/qcommon/placement.h
@@ -1,38 +1,38 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef PLACEMENT_H
-#define PLACEMENT_H
-
-#include "q_typedef.h"
-
-//typedef float vec3_t[3];
-
-typedef struct Placement_s
-{
-	vec3_t origin;
-	vec3_t direction;
-	vec3_t up;
-} Placement_t;
-
-#endif
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef PLACEMENT_H
+#define PLACEMENT_H
+
+#include "q_typedef.h"
+
+//typedef float vec3_t[3];
+
+typedef struct Placement_s
+{
+	vec3_t origin;
+	vec3_t direction;
+	vec3_t up;
+} Placement_t;
+
+#endif
+
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/q_typedef.h b/tools/quake2/qdata_heretic2/qcommon/q_typedef.h
index 14206cb0..63507f72 100644
--- a/tools/quake2/qdata_heretic2/qcommon/q_typedef.h
+++ b/tools/quake2/qdata_heretic2/qcommon/q_typedef.h
@@ -1,63 +1,63 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef Q_TYPEDEF_H
-#define Q_TYPEDEF_H
-
-typedef float vec_t;
-typedef vec_t vec2_t[2];
-typedef vec_t vec3_t[3];
-typedef double vec3d_t[3];
-typedef vec_t vec5_t[5];
-
-typedef float matrix3_t[3][3];
-typedef float matrix3d_t[3][3];
-
-typedef	int	fixed4_t;
-typedef	int	fixed8_t;
-typedef	int	fixed16_t;
-
-typedef unsigned char 		byte;
-
-#ifndef __cplusplus
-typedef enum {false, true}	qboolean;
-#else
-typedef int qboolean;
-#endif
-
-typedef struct edict_s edict_t;
-
-typedef struct paletteRGBA_s
-{
-	union
-	{
-		struct
-		{
-			byte r,g,b,a;
-		};
-		unsigned c;
-		byte c_array[4];
-	};
-} paletteRGBA_t;
-
-#endif
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef Q_TYPEDEF_H
+#define Q_TYPEDEF_H
+
+typedef float vec_t;
+typedef vec_t vec2_t[2];
+typedef vec_t vec3_t[3];
+typedef double vec3d_t[3];
+typedef vec_t vec5_t[5];
+
+typedef float matrix3_t[3][3];
+typedef float matrix3d_t[3][3];
+
+typedef	int	fixed4_t;
+typedef	int	fixed8_t;
+typedef	int	fixed16_t;
+
+typedef unsigned char 		byte;
+
+#ifndef __cplusplus
+typedef enum {false, true}	qboolean;
+#else
+typedef int qboolean;
+#endif
+
+typedef struct edict_s edict_t;
+
+typedef struct paletteRGBA_s
+{
+	union
+	{
+		struct
+		{
+			byte r,g,b,a;
+		};
+		unsigned c;
+		byte c_array[4];
+	};
+} paletteRGBA_t;
+
+#endif
+
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/qfiles.h b/tools/quake2/qdata_heretic2/qcommon/qfiles.h
index cb0a4b53..9466b796 100644
--- a/tools/quake2/qdata_heretic2/qcommon/qfiles.h
+++ b/tools/quake2/qdata_heretic2/qcommon/qfiles.h
@@ -1,604 +1,604 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-/*
-========================================================================
-
-The .pak files are just a linear collapse of a directory tree
-
-========================================================================
-*/
-
-#define IDPAKHEADER		(('K'<<24)+('C'<<16)+('A'<<8)+'P')
-
-typedef struct
-{
-	char	name[56];
-	int		filepos, filelen;
-} dpackfile_t;
-
-typedef struct
-{
-	int		ident;		// == IDPAKHEADER
-	int		dirofs;
-	int		dirlen;
-} dpackheader_t;
-
-#define	MAX_FILES_IN_PACK	6144
-
-
-/*
-========================================================================
-
-PCX files are used for as many images as possible
-
-========================================================================
-*/
-
-typedef struct
-{
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
-
-/*
-========================================================================
-
-.MD2 compressed triangle model file format
-
-========================================================================
-*/
-#define IDCOMPRESSEDALIASHEADER	(('2'<<24)+('C'<<16)+('D'<<8)+'I')
-
-/*
-========================================================================
-
-.MD2 compressed triangle model file format
-
-========================================================================
-*/
-#define IDJOINTEDALIASHEADER	(('2'<<24)+('J'<<16)+('D'<<8)+'I')
-
-/*
-========================================================================
-
-.MD2 triangle model file format
-
-========================================================================
-*/
-
-#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
-#define ALIAS_VERSION	8
-
-#define	MAX_TRIANGLES	4096
-#define MAX_VERTS		2048
-#define MAX_FRAMES		512
-#define MAX_MD2SKINS	64
-#define	MAX_SKINNAME	64
-
-typedef struct
-{
-	short	s;
-	short	t;
-} dstvert_t;
-
-typedef struct 
-{
-	short	index_xyz[3];
-	short	index_st[3];
-} dtriangle_t;
-
-typedef struct
-{
-	union
-	{
-		struct
-		{
-		byte	v[3];			// scaled byte to fit in frame mins/maxs
-		byte	lightnormalindex;
-		};
-
-		int vert;
-	};
-} dtrivertx_t;
-
-#define DTRIVERTX_V0   0
-#define DTRIVERTX_V1   1
-#define DTRIVERTX_V2   2
-#define DTRIVERTX_LNI  3
-#define DTRIVERTX_SIZE 4
-
-typedef struct
-{
-	float		scale[3];	// multiply byte verts by this
-	float		translate[3];	// then add this
-	char		name[16];	// frame name from grabbing
-	dtrivertx_t	verts[1];	// variable sized
-} daliasframe_t;
-
-
-// the glcmd format:
-// a positive integer starts a tristrip command, followed by that many
-// vertex structures.
-// a negative integer starts a trifan command, followed by -x vertexes
-// a zero indicates the end of the command list.
-// a vertex consists of a floating point s, a floating point t,
-// and an integer vertex index.
-
-
-typedef struct
-{
-	int			ident;
-	int			version;
-
-	int			skinwidth;
-	int			skinheight;
-	int			framesize;		// byte size of each frame
-
-	int			num_skins;
-	int			num_xyz;
-	int			num_st;			// greater than num_xyz for seams
-	int			num_tris;
-	int			num_glcmds;		// dwords in strip/fan command list
-	int			num_frames;
-
-	int			ofs_skins;		// each skin is a MAX_SKINNAME string
-	int			ofs_st;			// byte offset from start for stverts
-	int			ofs_tris;		// offset for dtriangles
-	int			ofs_frames;		// offset for first frame
-	int			ofs_glcmds;	
-	int			ofs_end;		// end of file
-
-} dmdl_t;
-
-// compressed model
-typedef struct dcompmdl_s
-{
-	dmdl_t header;
-	short CompressedFrameSize;
-	short UniqueVerts;
-	short *remap;
-	float *translate;	// then add this
-	float *scale;	// multiply byte verts by this
-	char *mat;
-	char *frames;
-	char *base;
-	float *ctranslate;	
-	float *cscale;	
-	char data[1];
-} dcompmdl_t;
-
-typedef struct 
-{
-	dcompmdl_t compModInfo;
-	int rootCluster;
-	int skeletalType;
-	struct ModelSkeleton_s *skeletons;
-} JointedModel_t;
-
-/*
-========================================================================
-
-.BK file format
-
-========================================================================
-*/
-
-#define IDBOOKHEADER	(('K'<<24)+('O'<<16)+('O'<<8)+'B')
-#define BOOK_VERSION	2
-
-typedef struct bookframe_s
-{
-	int			x;
-	int			y;
-	int			w;
-	int			h;
-	char		name[MAX_SKINNAME];		// name of gfx file
-} bookframe_t;
-
-typedef struct bookheader_s
-{
-	unsigned int	ident;
-	unsigned int	version;
-	int				num_segments;
-	int				total_w;
-	int				total_h;
-} bookheader_t;
-
-typedef struct book_s
-{
-	bookheader_t bheader;
-	bookframe_t	bframes[MAX_MD2SKINS];
-} book_t;
-
-/*
-========================================================================
-
-.SP2 sprite file format
-
-========================================================================
-*/
-
-#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
-		// little-endian "IDS2"
-#define SPRITE_VERSION	2
-
-typedef struct
-{
-	int		width, height;
-	int		origin_x, origin_y;		// raster coordinates inside pic
-	char	name[MAX_SKINNAME];		// name of pcx file
-} dsprframe_t;
-
-typedef struct {
-	int			ident;
-	int			version;
-	int			numframes;
-	dsprframe_t	frames[1];			// variable sized
-} dsprite_t;
-
-/*
-==============================================================================
-
-  .M8 texture file format
-
-==============================================================================
-*/
-
-typedef struct palette_s
-{
-	union
-	{
-		struct
-		{
-			byte r,g,b;
-		};
-	};
-} palette_t;
-
-#define MIP_VERSION		2
-#define PAL_SIZE		256
-#define	MIPLEVELS		16
-
-typedef struct miptex_s
-{
-	int			version;
-	char		name[32];
-	unsigned	width[MIPLEVELS], height[MIPLEVELS];
-	unsigned	offsets[MIPLEVELS];		// four mip maps stored
-	char		animname[32];			// next frame in animation chain
-	palette_t	palette[PAL_SIZE];
-	int			flags;
-	int			contents;
-	int			value;
-} miptex_t;
-
-
-
-#define MIP32_VERSION	4
-
-typedef struct miptex32_s
-{
-	int			version;
-	char		name[128];
-	char		altname[128];			// texture substitution
-	char		animname[128];			// next frame in animation chain
-	char		damagename[128];		// image that should be shown when damaged
-	unsigned	width[MIPLEVELS], height[MIPLEVELS];
-	unsigned	offsets[MIPLEVELS];		
-	int			flags;
-	int			contents;
-	int			value;
-	float		scale_x, scale_y;
-	int			mip_scale;
-
-	// detail texturing info
-	char		dt_name[128];		// detailed texture name
-	float		dt_scale_x, dt_scale_y;
-	float		dt_u, dt_v;
-	float		dt_alpha;
-	int			dt_src_blend_mode, dt_dst_blend_mode;
-
-	int			unused[20];				// future expansion to maintain compatibility with h2
-} miptex32_t;
-
-
-/*
-==============================================================================
-
-  .BSP file format
-
-==============================================================================
-*/
-
-#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
-		// little-endian "IBSP"
-
-#define BSPVERSION	38
-
-
-// upper design bounds
-// leaffaces, leafbrushes, planes, and verts are still bounded by
-// 16 bit short limits
-#define	MAX_MAP_MODELS		1024
-//#define	MAX_MAP_BRUSHES		8192	// Quake 2 original
-#define	MAX_MAP_BRUSHES		10240
-#define	MAX_MAP_ENTITIES	2048
-#define	MAX_MAP_ENTSTRING	0x40000
-#define	MAX_MAP_TEXINFO		8192
-
-#define	MAX_MAP_AREAS		256
-#define	MAX_MAP_AREAPORTALS	1024
-#define	MAX_MAP_PLANES		65536
-#define	MAX_MAP_NODES		65536
-#define	MAX_MAP_BRUSHSIDES	65536
-#define	MAX_MAP_LEAFS		65536
-#define	MAX_MAP_VERTS		65536
-#define	MAX_MAP_FACES		65536
-#define	MAX_MAP_LEAFFACES	65536
-#define	MAX_MAP_LEAFBRUSHES 65536
-#define	MAX_MAP_PORTALS		65536
-#define	MAX_MAP_EDGES		128000
-#define	MAX_MAP_SURFEDGES	256000
-#define	MAX_MAP_LIGHTING	0x200000
-#define	MAX_MAP_VISIBILITY	0x180000
-
-// key / value pair sizes
-
-#define	MAX_KEY		32
-#define	MAX_VALUE	1024
-
-//=============================================================================
-
-typedef struct
-{
-	int		fileofs, filelen;
-} lump_t;
-
-#define	LUMP_ENTITIES		0
-#define	LUMP_PLANES			1
-#define	LUMP_VERTEXES		2
-#define	LUMP_VISIBILITY		3
-#define	LUMP_NODES			4
-#define	LUMP_TEXINFO		5
-#define	LUMP_FACES			6
-#define	LUMP_LIGHTING		7
-#define	LUMP_LEAFS			8
-#define	LUMP_LEAFFACES		9
-#define	LUMP_LEAFBRUSHES	10
-#define	LUMP_EDGES			11
-#define	LUMP_SURFEDGES		12
-#define	LUMP_MODELS			13
-#define	LUMP_BRUSHES		14
-#define	LUMP_BRUSHSIDES		15
-#define	LUMP_POP			16
-#define	LUMP_AREAS			17
-#define	LUMP_AREAPORTALS	18
-#define	HEADER_LUMPS		19
-
-typedef struct
-{
-	int			ident;
-	int			version;	
-	lump_t		lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct
-{
-	float		mins[3], maxs[3];
-	float		origin[3];		// for sounds or lights
-	int			headnode;
-	int			firstface, numfaces;	// submodels just draw faces
-										// without walking the bsp tree
-} dmodel_t;
-
-
-typedef struct
-{
-	float	point[3];
-} dvertex_t;
-
-
-// 0-2 are axial planes
-#define	PLANE_X			0
-#define	PLANE_Y			1
-#define	PLANE_Z			2
-
-// 3-5 are non-axial planes snapped to the nearest
-#define	PLANE_ANYX		3
-#define	PLANE_ANYY		4
-#define	PLANE_ANYZ		5
-
-// planes (x&~1) and (x&~1)+1 are allways opposites
-
-typedef struct
-{
- 	float	normal[3];
-	float	dist;
-	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
-} dplane_t;
-
-
-// contents flags are seperate bits
-// a given brush can contribute multiple content bits
-// multiple brushes can be in a single leaf
-
-// These definitions also need to be in q_shared.h!
-
-// ************************************************************************************************
-// CONTENTS_XXX
-// ------------
-// Contents flags.
-// ************************************************************************************************
-
-// Lower bits are stronger, and will eat weaker brushes completely.
-
-#define	CONTENTS_SOLID			0x00000001	// An eye is never valid in a solid.
-#define	CONTENTS_WINDOW			0x00000002	// Translucent, but not watery.
-#define	CONTENTS_AUX			0x00000004
-#define	CONTENTS_LAVA			0x00000008
-#define	CONTENTS_SLIME			0x00000010
-#define	CONTENTS_WATER			0x00000020
-#define	CONTENTS_MIST			0x00000040
-#define	LAST_VISIBLE_CONTENTS	CONTENTS_MIST
-
-// Remaining contents are non-visible, and don't eat brushes.
-
-#define	CONTENTS_AREAPORTAL		0x00008000
-#define	CONTENTS_PLAYERCLIP		0x00010000
-#define	CONTENTS_MONSTERCLIP	0x00020000
-
-// Currents can be added to any other contents, and may be mixed.
-
-#define	CONTENTS_CURRENT_0		0x00040000
-#define	CONTENTS_CURRENT_90		0x00080000
-#define	CONTENTS_CURRENT_180	0x00100000
-#define	CONTENTS_CURRENT_270	0x00200000
-#define	CONTENTS_CURRENT_UP		0x00400000
-#define	CONTENTS_CURRENT_DOWN	0x00800000
-#define	CONTENTS_ORIGIN			0x01000000	// Removed before bsping an entity.
-#define	CONTENTS_MONSTER		0x02000000	// Should never be on a brush, only in game.
-#define	CONTENTS_DEADMONSTER	0x04000000
-#define	CONTENTS_DETAIL			0x08000000	// Brushes to be added after vis leaves.
-#define	CONTENTS_TRANSLUCENT	0x10000000	// Auto set if any surface has transparency.
-#define	CONTENTS_LADDER			0x20000000
-#define	CONTENTS_CAMERANOBLOCK	0x40000000	// Camera LOS ignores any brushes with this flag.
-
-typedef struct
-{
-	int			planenum;
-	int			children[2];	// negative numbers are -(leafs+1), not nodes
-	short		mins[3];		// for frustom culling
-	short		maxs[3];
-	unsigned short	firstface;
-	unsigned short	numfaces;	// counting both sides
-} dnode_t;
-
-
-typedef struct texinfo_s
-{
-	float		vecs[2][4];		// [s/t][xyz offset]
-	int			flags;			// miptex flags + overrides
-	int			value;			// light emission, etc
-	char		texture[32];	// texture name (textures/*.wal)
-	int			nexttexinfo;	// for animations, -1 = end of chain
-} texinfo_t;
-
-
-// note that edge 0 is never used, because negative edge nums are used for
-// counterclockwise use of the edge in a face
-typedef struct
-{
-	unsigned short	v[2];		// vertex numbers
-} dedge_t;
-
-#define	MAXLIGHTMAPS	4
-typedef struct
-{
-	unsigned short	planenum;
-	short		side;
-
-	int			firstedge;		// we must support > 64k edges
-	short		numedges;	
-	short		texinfo;
-
-// lighting info
-	byte		styles[MAXLIGHTMAPS];
-	int			lightofs;		// start of [numstyles*surfsize] samples
-} dface_t;
-
-typedef struct
-{
-	int				contents;			// OR of all brushes (not needed?)
-
-	short			cluster;
-	short			area;
-
-	short			mins[3];			// for frustum culling
-	short			maxs[3];
-
-	unsigned short	firstleafface;
-	unsigned short	numleaffaces;
-
-	unsigned short	firstleafbrush;
-	unsigned short	numleafbrushes;
-} dleaf_t;
-
-typedef struct
-{
-	unsigned short	planenum;		// facing out of the leaf
-	short	texinfo;
-} dbrushside_t;
-
-typedef struct
-{
-	int			firstside;
-	int			numsides;
-	int			contents;
-} dbrush_t;
-
-#define	ANGLE_UP	-1
-#define	ANGLE_DOWN	-2
-
-
-// the visibility lump consists of a header with a count, then
-// byte offsets for the PVS and PHS of each cluster, then the raw
-// compressed bit vectors
-#define	DVIS_PVS	0
-#define	DVIS_PHS	1
-typedef struct
-{
-	int			numclusters;
-	int			bitofs[8][2];	// bitofs[numclusters][2]
-} dvis_t;
-
-// each area has a list of portals that lead into other areas
-// when portals are closed, other areas may not be visible or
-// hearable even if the vis info says that it should be
-typedef struct
-{
-	int		portalnum;
-	int		otherarea;
-} dareaportal_t;
-
-typedef struct
-{
-	int		numareaportals;
-	int		firstareaportal;
-} darea_t;
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+/*
+========================================================================
+
+The .pak files are just a linear collapse of a directory tree
+
+========================================================================
+*/
+
+#define IDPAKHEADER		(('K'<<24)+('C'<<16)+('A'<<8)+'P')
+
+typedef struct
+{
+	char	name[56];
+	int		filepos, filelen;
+} dpackfile_t;
+
+typedef struct
+{
+	int		ident;		// == IDPAKHEADER
+	int		dirofs;
+	int		dirlen;
+} dpackheader_t;
+
+#define	MAX_FILES_IN_PACK	6144
+
+
+/*
+========================================================================
+
+PCX files are used for as many images as possible
+
+========================================================================
+*/
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+/*
+========================================================================
+
+.MD2 compressed triangle model file format
+
+========================================================================
+*/
+#define IDCOMPRESSEDALIASHEADER	(('2'<<24)+('C'<<16)+('D'<<8)+'I')
+
+/*
+========================================================================
+
+.MD2 compressed triangle model file format
+
+========================================================================
+*/
+#define IDJOINTEDALIASHEADER	(('2'<<24)+('J'<<16)+('D'<<8)+'I')
+
+/*
+========================================================================
+
+.MD2 triangle model file format
+
+========================================================================
+*/
+
+#define IDALIASHEADER		(('2'<<24)+('P'<<16)+('D'<<8)+'I')
+#define ALIAS_VERSION	8
+
+#define	MAX_TRIANGLES	4096
+#define MAX_VERTS		2048
+#define MAX_FRAMES		512
+#define MAX_MD2SKINS	64
+#define	MAX_SKINNAME	64
+
+typedef struct
+{
+	short	s;
+	short	t;
+} dstvert_t;
+
+typedef struct 
+{
+	short	index_xyz[3];
+	short	index_st[3];
+} dtriangle_t;
+
+typedef struct
+{
+	union
+	{
+		struct
+		{
+		byte	v[3];			// scaled byte to fit in frame mins/maxs
+		byte	lightnormalindex;
+		};
+
+		int vert;
+	};
+} dtrivertx_t;
+
+#define DTRIVERTX_V0   0
+#define DTRIVERTX_V1   1
+#define DTRIVERTX_V2   2
+#define DTRIVERTX_LNI  3
+#define DTRIVERTX_SIZE 4
+
+typedef struct
+{
+	float		scale[3];	// multiply byte verts by this
+	float		translate[3];	// then add this
+	char		name[16];	// frame name from grabbing
+	dtrivertx_t	verts[1];	// variable sized
+} daliasframe_t;
+
+
+// the glcmd format:
+// a positive integer starts a tristrip command, followed by that many
+// vertex structures.
+// a negative integer starts a trifan command, followed by -x vertexes
+// a zero indicates the end of the command list.
+// a vertex consists of a floating point s, a floating point t,
+// and an integer vertex index.
+
+
+typedef struct
+{
+	int			ident;
+	int			version;
+
+	int			skinwidth;
+	int			skinheight;
+	int			framesize;		// byte size of each frame
+
+	int			num_skins;
+	int			num_xyz;
+	int			num_st;			// greater than num_xyz for seams
+	int			num_tris;
+	int			num_glcmds;		// dwords in strip/fan command list
+	int			num_frames;
+
+	int			ofs_skins;		// each skin is a MAX_SKINNAME string
+	int			ofs_st;			// byte offset from start for stverts
+	int			ofs_tris;		// offset for dtriangles
+	int			ofs_frames;		// offset for first frame
+	int			ofs_glcmds;	
+	int			ofs_end;		// end of file
+
+} dmdl_t;
+
+// compressed model
+typedef struct dcompmdl_s
+{
+	dmdl_t header;
+	short CompressedFrameSize;
+	short UniqueVerts;
+	short *remap;
+	float *translate;	// then add this
+	float *scale;	// multiply byte verts by this
+	char *mat;
+	char *frames;
+	char *base;
+	float *ctranslate;	
+	float *cscale;	
+	char data[1];
+} dcompmdl_t;
+
+typedef struct 
+{
+	dcompmdl_t compModInfo;
+	int rootCluster;
+	int skeletalType;
+	struct ModelSkeleton_s *skeletons;
+} JointedModel_t;
+
+/*
+========================================================================
+
+.BK file format
+
+========================================================================
+*/
+
+#define IDBOOKHEADER	(('K'<<24)+('O'<<16)+('O'<<8)+'B')
+#define BOOK_VERSION	2
+
+typedef struct bookframe_s
+{
+	int			x;
+	int			y;
+	int			w;
+	int			h;
+	char		name[MAX_SKINNAME];		// name of gfx file
+} bookframe_t;
+
+typedef struct bookheader_s
+{
+	unsigned int	ident;
+	unsigned int	version;
+	int				num_segments;
+	int				total_w;
+	int				total_h;
+} bookheader_t;
+
+typedef struct book_s
+{
+	bookheader_t bheader;
+	bookframe_t	bframes[MAX_MD2SKINS];
+} book_t;
+
+/*
+========================================================================
+
+.SP2 sprite file format
+
+========================================================================
+*/
+
+#define IDSPRITEHEADER	(('2'<<24)+('S'<<16)+('D'<<8)+'I')
+		// little-endian "IDS2"
+#define SPRITE_VERSION	2
+
+typedef struct
+{
+	int		width, height;
+	int		origin_x, origin_y;		// raster coordinates inside pic
+	char	name[MAX_SKINNAME];		// name of pcx file
+} dsprframe_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+	int			numframes;
+	dsprframe_t	frames[1];			// variable sized
+} dsprite_t;
+
+/*
+==============================================================================
+
+  .M8 texture file format
+
+==============================================================================
+*/
+
+typedef struct palette_s
+{
+	union
+	{
+		struct
+		{
+			byte r,g,b;
+		};
+	};
+} palette_t;
+
+#define MIP_VERSION		2
+#define PAL_SIZE		256
+#define	MIPLEVELS		16
+
+typedef struct miptex_s
+{
+	int			version;
+	char		name[32];
+	unsigned	width[MIPLEVELS], height[MIPLEVELS];
+	unsigned	offsets[MIPLEVELS];		// four mip maps stored
+	char		animname[32];			// next frame in animation chain
+	palette_t	palette[PAL_SIZE];
+	int			flags;
+	int			contents;
+	int			value;
+} miptex_t;
+
+
+
+#define MIP32_VERSION	4
+
+typedef struct miptex32_s
+{
+	int			version;
+	char		name[128];
+	char		altname[128];			// texture substitution
+	char		animname[128];			// next frame in animation chain
+	char		damagename[128];		// image that should be shown when damaged
+	unsigned	width[MIPLEVELS], height[MIPLEVELS];
+	unsigned	offsets[MIPLEVELS];		
+	int			flags;
+	int			contents;
+	int			value;
+	float		scale_x, scale_y;
+	int			mip_scale;
+
+	// detail texturing info
+	char		dt_name[128];		// detailed texture name
+	float		dt_scale_x, dt_scale_y;
+	float		dt_u, dt_v;
+	float		dt_alpha;
+	int			dt_src_blend_mode, dt_dst_blend_mode;
+
+	int			unused[20];				// future expansion to maintain compatibility with h2
+} miptex32_t;
+
+
+/*
+==============================================================================
+
+  .BSP file format
+
+==============================================================================
+*/
+
+#define IDBSPHEADER	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
+		// little-endian "IBSP"
+
+#define BSPVERSION	38
+
+
+// upper design bounds
+// leaffaces, leafbrushes, planes, and verts are still bounded by
+// 16 bit short limits
+#define	MAX_MAP_MODELS		1024
+//#define	MAX_MAP_BRUSHES		8192	// Quake 2 original
+#define	MAX_MAP_BRUSHES		10240
+#define	MAX_MAP_ENTITIES	2048
+#define	MAX_MAP_ENTSTRING	0x40000
+#define	MAX_MAP_TEXINFO		8192
+
+#define	MAX_MAP_AREAS		256
+#define	MAX_MAP_AREAPORTALS	1024
+#define	MAX_MAP_PLANES		65536
+#define	MAX_MAP_NODES		65536
+#define	MAX_MAP_BRUSHSIDES	65536
+#define	MAX_MAP_LEAFS		65536
+#define	MAX_MAP_VERTS		65536
+#define	MAX_MAP_FACES		65536
+#define	MAX_MAP_LEAFFACES	65536
+#define	MAX_MAP_LEAFBRUSHES 65536
+#define	MAX_MAP_PORTALS		65536
+#define	MAX_MAP_EDGES		128000
+#define	MAX_MAP_SURFEDGES	256000
+#define	MAX_MAP_LIGHTING	0x200000
+#define	MAX_MAP_VISIBILITY	0x180000
+
+// key / value pair sizes
+
+#define	MAX_KEY		32
+#define	MAX_VALUE	1024
+
+//=============================================================================
+
+typedef struct
+{
+	int		fileofs, filelen;
+} lump_t;
+
+#define	LUMP_ENTITIES		0
+#define	LUMP_PLANES			1
+#define	LUMP_VERTEXES		2
+#define	LUMP_VISIBILITY		3
+#define	LUMP_NODES			4
+#define	LUMP_TEXINFO		5
+#define	LUMP_FACES			6
+#define	LUMP_LIGHTING		7
+#define	LUMP_LEAFS			8
+#define	LUMP_LEAFFACES		9
+#define	LUMP_LEAFBRUSHES	10
+#define	LUMP_EDGES			11
+#define	LUMP_SURFEDGES		12
+#define	LUMP_MODELS			13
+#define	LUMP_BRUSHES		14
+#define	LUMP_BRUSHSIDES		15
+#define	LUMP_POP			16
+#define	LUMP_AREAS			17
+#define	LUMP_AREAPORTALS	18
+#define	HEADER_LUMPS		19
+
+typedef struct
+{
+	int			ident;
+	int			version;	
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct
+{
+	float		mins[3], maxs[3];
+	float		origin[3];		// for sounds or lights
+	int			headnode;
+	int			firstface, numfaces;	// submodels just draw faces
+										// without walking the bsp tree
+} dmodel_t;
+
+
+typedef struct
+{
+	float	point[3];
+} dvertex_t;
+
+
+// 0-2 are axial planes
+#define	PLANE_X			0
+#define	PLANE_Y			1
+#define	PLANE_Z			2
+
+// 3-5 are non-axial planes snapped to the nearest
+#define	PLANE_ANYX		3
+#define	PLANE_ANYY		4
+#define	PLANE_ANYZ		5
+
+// planes (x&~1) and (x&~1)+1 are allways opposites
+
+typedef struct
+{
+ 	float	normal[3];
+	float	dist;
+	int		type;		// PLANE_X - PLANE_ANYZ ?remove? trivial to regenerate
+} dplane_t;
+
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+// multiple brushes can be in a single leaf
+
+// These definitions also need to be in q_shared.h!
+
+// ************************************************************************************************
+// CONTENTS_XXX
+// ------------
+// Contents flags.
+// ************************************************************************************************
+
+// Lower bits are stronger, and will eat weaker brushes completely.
+
+#define	CONTENTS_SOLID			0x00000001	// An eye is never valid in a solid.
+#define	CONTENTS_WINDOW			0x00000002	// Translucent, but not watery.
+#define	CONTENTS_AUX			0x00000004
+#define	CONTENTS_LAVA			0x00000008
+#define	CONTENTS_SLIME			0x00000010
+#define	CONTENTS_WATER			0x00000020
+#define	CONTENTS_MIST			0x00000040
+#define	LAST_VISIBLE_CONTENTS	CONTENTS_MIST
+
+// Remaining contents are non-visible, and don't eat brushes.
+
+#define	CONTENTS_AREAPORTAL		0x00008000
+#define	CONTENTS_PLAYERCLIP		0x00010000
+#define	CONTENTS_MONSTERCLIP	0x00020000
+
+// Currents can be added to any other contents, and may be mixed.
+
+#define	CONTENTS_CURRENT_0		0x00040000
+#define	CONTENTS_CURRENT_90		0x00080000
+#define	CONTENTS_CURRENT_180	0x00100000
+#define	CONTENTS_CURRENT_270	0x00200000
+#define	CONTENTS_CURRENT_UP		0x00400000
+#define	CONTENTS_CURRENT_DOWN	0x00800000
+#define	CONTENTS_ORIGIN			0x01000000	// Removed before bsping an entity.
+#define	CONTENTS_MONSTER		0x02000000	// Should never be on a brush, only in game.
+#define	CONTENTS_DEADMONSTER	0x04000000
+#define	CONTENTS_DETAIL			0x08000000	// Brushes to be added after vis leaves.
+#define	CONTENTS_TRANSLUCENT	0x10000000	// Auto set if any surface has transparency.
+#define	CONTENTS_LADDER			0x20000000
+#define	CONTENTS_CAMERANOBLOCK	0x40000000	// Camera LOS ignores any brushes with this flag.
+
+typedef struct
+{
+	int			planenum;
+	int			children[2];	// negative numbers are -(leafs+1), not nodes
+	short		mins[3];		// for frustom culling
+	short		maxs[3];
+	unsigned short	firstface;
+	unsigned short	numfaces;	// counting both sides
+} dnode_t;
+
+
+typedef struct texinfo_s
+{
+	float		vecs[2][4];		// [s/t][xyz offset]
+	int			flags;			// miptex flags + overrides
+	int			value;			// light emission, etc
+	char		texture[32];	// texture name (textures/*.wal)
+	int			nexttexinfo;	// for animations, -1 = end of chain
+} texinfo_t;
+
+
+// note that edge 0 is never used, because negative edge nums are used for
+// counterclockwise use of the edge in a face
+typedef struct
+{
+	unsigned short	v[2];		// vertex numbers
+} dedge_t;
+
+#define	MAXLIGHTMAPS	4
+typedef struct
+{
+	unsigned short	planenum;
+	short		side;
+
+	int			firstedge;		// we must support > 64k edges
+	short		numedges;	
+	short		texinfo;
+
+// lighting info
+	byte		styles[MAXLIGHTMAPS];
+	int			lightofs;		// start of [numstyles*surfsize] samples
+} dface_t;
+
+typedef struct
+{
+	int				contents;			// OR of all brushes (not needed?)
+
+	short			cluster;
+	short			area;
+
+	short			mins[3];			// for frustum culling
+	short			maxs[3];
+
+	unsigned short	firstleafface;
+	unsigned short	numleaffaces;
+
+	unsigned short	firstleafbrush;
+	unsigned short	numleafbrushes;
+} dleaf_t;
+
+typedef struct
+{
+	unsigned short	planenum;		// facing out of the leaf
+	short	texinfo;
+} dbrushside_t;
+
+typedef struct
+{
+	int			firstside;
+	int			numsides;
+	int			contents;
+} dbrush_t;
+
+#define	ANGLE_UP	-1
+#define	ANGLE_DOWN	-2
+
+
+// the visibility lump consists of a header with a count, then
+// byte offsets for the PVS and PHS of each cluster, then the raw
+// compressed bit vectors
+#define	DVIS_PVS	0
+#define	DVIS_PHS	1
+typedef struct
+{
+	int			numclusters;
+	int			bitofs[8][2];	// bitofs[numclusters][2]
+} dvis_t;
+
+// each area has a list of portals that lead into other areas
+// when portals are closed, other areas may not be visible or
+// hearable even if the vis info says that it should be
+typedef struct
+{
+	int		portalnum;
+	int		otherarea;
+} dareaportal_t;
+
+typedef struct
+{
+	int		numareaportals;
+	int		firstareaportal;
+} darea_t;
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/reference.c b/tools/quake2/qdata_heretic2/qcommon/reference.c
index c26b1ae9..3145c052 100644
--- a/tools/quake2/qdata_heretic2/qcommon/reference.c
+++ b/tools/quake2/qdata_heretic2/qcommon/reference.c
@@ -1,124 +1,124 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <string.h>
-#include "reference.h"
-#include "arrayedlist.h"
-#include "resourcemanager.h"
-#include "skeletons.h"
-
-char *referenceRootNames[] =
-{
-	"elf_Lhandroot",//0
-	"elf_Rhandroot",
-	"elf_Rfootroot",
-	"elf_Lfootroot",
-	"elf_Bstaffroot",
-	"elf_bladeroot",
-	"elf_hellroot",
-	"StaffBone",//7
-	"SwordBone",
-	"SpearBone",
-	"RFootBone",
-	"LFootBone",
-	"hp_backroot",//12
-	"hp_staffroot",
-	"hp_lhandroot",
-	"hp_rhandroot",
-	"hp_rfootroot",
-	"hp_lfootroot",
-	"staffroot",//18
-	"rfootroot",
-	"lfootroot",
-	"rhandroot",
-	"lhandroot",
-	"leyeroot",
-	"reyeroot"
-};
-
-int referenceRootNameOffsets[NUM_REFERENCED] =
-{
-	0,	// CORVUS
-	7,	// INSECT
-	12, // HIGH PRIESTESS
-	18,	// MORCALAVIN
-};
-
-int numReferences[NUM_REFERENCED] = 
-{
-	NUM_REFERENCES_CORVUS,
-	NUM_REFERENCES_INSECT,
-	NUM_REFERENCES_PRIESTESS,
-	NUM_REFERENCES_MORK,
-};
-
-int corvusJointIDs[NUM_REFERENCES_CORVUS] =
-{
-	CORVUS_UPPERBACK,
-	CORVUS_UPPERBACK,
-	-1,
-	-1,
-	CORVUS_UPPERBACK,
-	CORVUS_UPPERBACK,
-	CORVUS_UPPERBACK,
-};
-
-int *jointIDs[NUM_REFERENCED] =
-{
-	corvusJointIDs,
-};
-
-static ResourceManager_t ReferenceMngr;
-
-void InitReferenceMngr()
-{
-#define	REFERENCE_BLOCK_SIZE 8
-	char *dummystr = NULL;
-	
-	ResMngr_Con(&ReferenceMngr, sizeof(LERPedReferences_t), REFERENCE_BLOCK_SIZE, dummystr);
-}
-
-void ReleaseReferenceMngr()
-{
-	ResMngr_Des(&ReferenceMngr);
-}
-
-LERPedReferences_t *LERPedReferences_new(int init_refType)
-{
-	LERPedReferences_t	*newRefs;
-
-	newRefs = ResMngr_AllocateResource(&ReferenceMngr, sizeof(*newRefs));
-	newRefs->refType = init_refType;
-	newRefs->jointIDs = jointIDs[init_refType];
-	newRefs->lastUpdate = -(REF_MINCULLTIME*2.0);
-
-	memset(newRefs->references, 0, MAX_REFPOINTS*sizeof(Reference_t));
-	memset(newRefs->oldReferences, 0, MAX_REFPOINTS*sizeof(Reference_t));
-
-	return newRefs;
-}
-
-void LERPedReferences_delete(LERPedReferences_t *toDelete)
-{
-	ResMngr_DeallocateResource(&ReferenceMngr, toDelete, sizeof(*toDelete));
-}
-
-// end
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <string.h>
+#include "reference.h"
+#include "arrayedlist.h"
+#include "resourcemanager.h"
+#include "skeletons.h"
+
+char *referenceRootNames[] =
+{
+	"elf_Lhandroot",//0
+	"elf_Rhandroot",
+	"elf_Rfootroot",
+	"elf_Lfootroot",
+	"elf_Bstaffroot",
+	"elf_bladeroot",
+	"elf_hellroot",
+	"StaffBone",//7
+	"SwordBone",
+	"SpearBone",
+	"RFootBone",
+	"LFootBone",
+	"hp_backroot",//12
+	"hp_staffroot",
+	"hp_lhandroot",
+	"hp_rhandroot",
+	"hp_rfootroot",
+	"hp_lfootroot",
+	"staffroot",//18
+	"rfootroot",
+	"lfootroot",
+	"rhandroot",
+	"lhandroot",
+	"leyeroot",
+	"reyeroot"
+};
+
+int referenceRootNameOffsets[NUM_REFERENCED] =
+{
+	0,	// CORVUS
+	7,	// INSECT
+	12, // HIGH PRIESTESS
+	18,	// MORCALAVIN
+};
+
+int numReferences[NUM_REFERENCED] = 
+{
+	NUM_REFERENCES_CORVUS,
+	NUM_REFERENCES_INSECT,
+	NUM_REFERENCES_PRIESTESS,
+	NUM_REFERENCES_MORK,
+};
+
+int corvusJointIDs[NUM_REFERENCES_CORVUS] =
+{
+	CORVUS_UPPERBACK,
+	CORVUS_UPPERBACK,
+	-1,
+	-1,
+	CORVUS_UPPERBACK,
+	CORVUS_UPPERBACK,
+	CORVUS_UPPERBACK,
+};
+
+int *jointIDs[NUM_REFERENCED] =
+{
+	corvusJointIDs,
+};
+
+static ResourceManager_t ReferenceMngr;
+
+void InitReferenceMngr()
+{
+#define	REFERENCE_BLOCK_SIZE 8
+	char *dummystr = NULL;
+	
+	ResMngr_Con(&ReferenceMngr, sizeof(LERPedReferences_t), REFERENCE_BLOCK_SIZE, dummystr);
+}
+
+void ReleaseReferenceMngr()
+{
+	ResMngr_Des(&ReferenceMngr);
+}
+
+LERPedReferences_t *LERPedReferences_new(int init_refType)
+{
+	LERPedReferences_t	*newRefs;
+
+	newRefs = ResMngr_AllocateResource(&ReferenceMngr, sizeof(*newRefs));
+	newRefs->refType = init_refType;
+	newRefs->jointIDs = jointIDs[init_refType];
+	newRefs->lastUpdate = -(REF_MINCULLTIME*2.0);
+
+	memset(newRefs->references, 0, MAX_REFPOINTS*sizeof(Reference_t));
+	memset(newRefs->oldReferences, 0, MAX_REFPOINTS*sizeof(Reference_t));
+
+	return newRefs;
+}
+
+void LERPedReferences_delete(LERPedReferences_t *toDelete)
+{
+	ResMngr_DeallocateResource(&ReferenceMngr, toDelete, sizeof(*toDelete));
+}
+
+// end
diff --git a/tools/quake2/qdata_heretic2/qcommon/reference.h b/tools/quake2/qdata_heretic2/qcommon/reference.h
index 9acdc56b..c61a1cec 100644
--- a/tools/quake2/qdata_heretic2/qcommon/reference.h
+++ b/tools/quake2/qdata_heretic2/qcommon/reference.h
@@ -1,126 +1,126 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef REFERENCE_H
-#define REFERENCE_H
-
-#include "placement.h"
-
-#define MAX_REFPOINTS		16
-#define REF_MINCULLTIME		1.0
-
-typedef struct Reference_s
-{
-	int activecount;
-	Placement_t placement;
-} Reference_t;
-
-typedef struct LERPedReferences_s
-{
-	int			refType;
-	int			*jointIDs;
-	float		lastUpdate;
-	Reference_t references[MAX_REFPOINTS];
-	Reference_t oldReferences[MAX_REFPOINTS];
-} LERPedReferences_t;
-
-// Reference Types
-enum {
-	REF_NULL = -1,
-	REF_CORVUS,//0
-	REF_INSECT,//1
-	REF_PRIESTESS,//2
-	REF_MORK,//3
-	NUM_REFERENCED//4
-};
-
-// Corvus Reference Points
-enum {
-	CORVUS_LEFTHAND,//0
-	CORVUS_RIGHTHAND,
-	CORVUS_LEFTFOOT,
-	CORVUS_RIGHTFOOT,
-	CORVUS_STAFF,
-	CORVUS_BLADE,
-	CORVUS_HELL_HEAD,
-	NUM_REFERENCES_CORVUS//7
-};
-
-// Tchekrik Reference Points
-enum {
-	INSECT_STAFF,//0
-	INSECT_SWORD,
-	INSECT_SPEAR,
-	INSECT_RIGHTFOOT,
-	INSECT_LEFTFOOT,
-	NUM_REFERENCES_INSECT//5
-};
-
-// High Priestess Reference Points
-enum {
-	PRIESTESS_BACK,//0
-	PRIESTESS_STAFF,
-	PRIESTESS_LHAND,
-	PRIESTESS_RHAND,
-	PRIESTESS_RFOOT,
-	PRIESTESS_LFOOT,
-	NUM_REFERENCES_PRIESTESS//6
-};
-
-// Morcalavin Reference Points
-enum 
-{
-	MORK_STAFFREF,//0
-	MORK_RFOOTREF,//1
-	MORK_LFOOTREF,//2
-	MORK_RHANDREF,//3
-	MORK_LHANDREF,//4
-	MORK_LEYEREF,//5
-	MORK_REYEREF,//6
-	NUM_REFERENCES_MORK//7
-};
-
-#define CORVUS_LIMBS_MASK	((1 << CORVUS_LEFTHAND) | (1 << CORVUS_RIGHTHAND) | (1 << CORVUS_LEFTFOOT) | (1 << CORVUS_RIGHTFOOT))
-#define CORVUS_WEAPON_MASK	((1 << CORVUS_STAFF) | (1 << CORVUS_BLADE) | (1 << CORVUS_HELL_HEAD))
-#define CORVUS_MASK			(CORVUS_LIMBS_MASK | CORVUS_WEAPON_MASK)
-
-#define INSECT_MASK			((1 << INSECT_STAFF) | (1 << INSECT_SWORD) | (1 << INSECT_SPEAR) | (1 << INSECT_RIGHTFOOT) | (1 << INSECT_LEFTFOOT))
-
-#define PRIESTESS_MASK		((1 << PRIESTESS_BACK) | (1 << PRIESTESS_STAFF) | (1 << PRIESTESS_LHAND) | (1 << PRIESTESS_RHAND) | (1 << PRIESTESS_RFOOT) | (1 << PRIESTESS_LFOOT))
-
-#define MORK_MASK			((1 << MORK_STAFFREF) | (1 << MORK_RFOOTREF) | (1 << MORK_LFOOTREF) | (1 << MORK_RHANDREF) | (1 << MORK_LHANDREF) | (1 << MORK_LEYEREF) | (1 << MORK_REYEREF))
-
-extern char *referenceRootNames[];
-extern int referenceRootNameOffsets[];
-extern int numReferences[];
-
-void EnableRefPoints(LERPedReferences_t *refInfo, int mask);
-void DisableRefPoints(LERPedReferences_t *refInfo, int mask);
-
-void InitReferenceMngr();
-void ReleaseReferenceMngr();
-
-LERPedReferences_t *LERPedReferences_new(int init_refType);
-void LERPedReferences_delete(LERPedReferences_t *toDelete);
-
-#endif
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef REFERENCE_H
+#define REFERENCE_H
+
+#include "placement.h"
+
+#define MAX_REFPOINTS		16
+#define REF_MINCULLTIME		1.0
+
+typedef struct Reference_s
+{
+	int activecount;
+	Placement_t placement;
+} Reference_t;
+
+typedef struct LERPedReferences_s
+{
+	int			refType;
+	int			*jointIDs;
+	float		lastUpdate;
+	Reference_t references[MAX_REFPOINTS];
+	Reference_t oldReferences[MAX_REFPOINTS];
+} LERPedReferences_t;
+
+// Reference Types
+enum {
+	REF_NULL = -1,
+	REF_CORVUS,//0
+	REF_INSECT,//1
+	REF_PRIESTESS,//2
+	REF_MORK,//3
+	NUM_REFERENCED//4
+};
+
+// Corvus Reference Points
+enum {
+	CORVUS_LEFTHAND,//0
+	CORVUS_RIGHTHAND,
+	CORVUS_LEFTFOOT,
+	CORVUS_RIGHTFOOT,
+	CORVUS_STAFF,
+	CORVUS_BLADE,
+	CORVUS_HELL_HEAD,
+	NUM_REFERENCES_CORVUS//7
+};
+
+// Tchekrik Reference Points
+enum {
+	INSECT_STAFF,//0
+	INSECT_SWORD,
+	INSECT_SPEAR,
+	INSECT_RIGHTFOOT,
+	INSECT_LEFTFOOT,
+	NUM_REFERENCES_INSECT//5
+};
+
+// High Priestess Reference Points
+enum {
+	PRIESTESS_BACK,//0
+	PRIESTESS_STAFF,
+	PRIESTESS_LHAND,
+	PRIESTESS_RHAND,
+	PRIESTESS_RFOOT,
+	PRIESTESS_LFOOT,
+	NUM_REFERENCES_PRIESTESS//6
+};
+
+// Morcalavin Reference Points
+enum 
+{
+	MORK_STAFFREF,//0
+	MORK_RFOOTREF,//1
+	MORK_LFOOTREF,//2
+	MORK_RHANDREF,//3
+	MORK_LHANDREF,//4
+	MORK_LEYEREF,//5
+	MORK_REYEREF,//6
+	NUM_REFERENCES_MORK//7
+};
+
+#define CORVUS_LIMBS_MASK	((1 << CORVUS_LEFTHAND) | (1 << CORVUS_RIGHTHAND) | (1 << CORVUS_LEFTFOOT) | (1 << CORVUS_RIGHTFOOT))
+#define CORVUS_WEAPON_MASK	((1 << CORVUS_STAFF) | (1 << CORVUS_BLADE) | (1 << CORVUS_HELL_HEAD))
+#define CORVUS_MASK			(CORVUS_LIMBS_MASK | CORVUS_WEAPON_MASK)
+
+#define INSECT_MASK			((1 << INSECT_STAFF) | (1 << INSECT_SWORD) | (1 << INSECT_SPEAR) | (1 << INSECT_RIGHTFOOT) | (1 << INSECT_LEFTFOOT))
+
+#define PRIESTESS_MASK		((1 << PRIESTESS_BACK) | (1 << PRIESTESS_STAFF) | (1 << PRIESTESS_LHAND) | (1 << PRIESTESS_RHAND) | (1 << PRIESTESS_RFOOT) | (1 << PRIESTESS_LFOOT))
+
+#define MORK_MASK			((1 << MORK_STAFFREF) | (1 << MORK_RFOOTREF) | (1 << MORK_LFOOTREF) | (1 << MORK_RHANDREF) | (1 << MORK_LHANDREF) | (1 << MORK_LEYEREF) | (1 << MORK_REYEREF))
+
+extern char *referenceRootNames[];
+extern int referenceRootNameOffsets[];
+extern int numReferences[];
+
+void EnableRefPoints(LERPedReferences_t *refInfo, int mask);
+void DisableRefPoints(LERPedReferences_t *refInfo, int mask);
+
+void InitReferenceMngr();
+void ReleaseReferenceMngr();
+
+LERPedReferences_t *LERPedReferences_new(int init_refType);
+void LERPedReferences_delete(LERPedReferences_t *toDelete);
+
+#endif
+
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c
index cc5293c5..a48f372d 100644
--- a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c
+++ b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.c
@@ -1,159 +1,159 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-//
-// ResourceManager.c
-//
-
-#include <stdio.h>
-#include "resourcemanager.h"
-#include <assert.h>
-
-typedef struct ResMngr_Block_s
-{
-	char *start;
-	unsigned int size;
-	struct ResMngr_Block_s *next;
-} ResMngr_Block_t;
-
-static void ResMngr_CreateBlock(ResourceManager_t *resource)
-{
-	unsigned int _blockSize;
-	char *block;
-	char **current;
-	ResMngr_Block_t *temp;
-	unsigned int i;
-
-	_blockSize = resource->nodeSize * resource->resPerBlock;
-
-	block = malloc(_blockSize);
-
-	assert(block);
-
-	temp = malloc(sizeof(*temp));
-
-	temp->start = block;
-	temp->size = _blockSize;
-	temp->next = resource->blockList;
-
-	resource->blockList = temp; 
-
-	resource->free = (char **)(block);
-
-	current = resource->free;
-
-	for(i = 1; i < resource->resPerBlock; ++i)
-	{
-		// set current->next to point to next node
-		*current = (char *)(current) + resource->nodeSize;
-
-		// set current node to current->next
-		current = (char **)(*current);
-	}
-
-	*current = NULL;
-}
-
-H2COMMON_API void ResMngr_Con(ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name)
-{
-	resource->resSize = init_resSize;
-
-	resource->resPerBlock = init_resPerBlock;
-
-	resource->nodeSize = resource->resSize + sizeof(*resource->free);
-
-	resource->blockList = NULL;
-
-	resource->numResourcesAllocated = 0;
-
-	ResMngr_CreateBlock(resource);
-}
-
-H2COMMON_API void ResMngr_Des(ResourceManager_t *resource)
-{
-	ResMngr_Block_t *toDelete;
-
-#if 0
-	if (resource->numResourcesAllocated)
-	{
-		char mess[100];
-		sprintf(mess,"Potential memory leak %d bytes unfreed\n",resource->resSize*resource->numResourcesAllocated);
-		OutputDebugString(mess);
-	}
-#endif
-
-	while(resource->blockList)
-	{
-		toDelete = resource->blockList;
-		resource->blockList = resource->blockList->next;
-		free(toDelete->start);
-		free(toDelete);
-	}
-}
-
-H2COMMON_API void *ResMngr_AllocateResource(ResourceManager_t *resource, size_t size)
-{
-	char **toPop;
-
-	assert(size == resource->resSize);
-
-	++resource->numResourcesAllocated;
-
-	assert(resource->free);	// constructor not called; possibly due to a static object
-								// containing a static ResourceManagerFastLarge member being
-								// constructed before its own static members
-
-	toPop = resource->free;
-
-	// set unallocated to the next node and check for NULL (end of list)
-	if(!(resource->free = (char **)(*resource->free)))
-	{	// if at end create new block
-		ResMngr_CreateBlock(resource);
-	}
-
-	// set next to NULL
-	*toPop = NULL;
-
-	// return the resource for the node
-	return (void *)(toPop + 1);
-}
-
-H2COMMON_API void ResMngr_DeallocateResource(ResourceManager_t *resource, void *toDeallocate, size_t size)
-{
-	char **toPush;
-
-	assert(size == resource->resSize);
-
-	--resource->numResourcesAllocated;
-
-	toPush = (char **)(toDeallocate) - 1;
-
-	assert(resource->free);	// see same assert at top of AllocateResource
-
-	// set toPop->next to current unallocated front
-	*toPush = (char *)(resource->free);
-
-	// set unallocated to the node removed from allocated
-	resource->free = toPush;
-}
-
-// end
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+//
+// ResourceManager.c
+//
+
+#include <stdio.h>
+#include "resourcemanager.h"
+#include <assert.h>
+
+typedef struct ResMngr_Block_s
+{
+	char *start;
+	unsigned int size;
+	struct ResMngr_Block_s *next;
+} ResMngr_Block_t;
+
+static void ResMngr_CreateBlock(ResourceManager_t *resource)
+{
+	unsigned int _blockSize;
+	char *block;
+	char **current;
+	ResMngr_Block_t *temp;
+	unsigned int i;
+
+	_blockSize = resource->nodeSize * resource->resPerBlock;
+
+	block = malloc(_blockSize);
+
+	assert(block);
+
+	temp = malloc(sizeof(*temp));
+
+	temp->start = block;
+	temp->size = _blockSize;
+	temp->next = resource->blockList;
+
+	resource->blockList = temp; 
+
+	resource->free = (char **)(block);
+
+	current = resource->free;
+
+	for(i = 1; i < resource->resPerBlock; ++i)
+	{
+		// set current->next to point to next node
+		*current = (char *)(current) + resource->nodeSize;
+
+		// set current node to current->next
+		current = (char **)(*current);
+	}
+
+	*current = NULL;
+}
+
+H2COMMON_API void ResMngr_Con(ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name)
+{
+	resource->resSize = init_resSize;
+
+	resource->resPerBlock = init_resPerBlock;
+
+	resource->nodeSize = resource->resSize + sizeof(*resource->free);
+
+	resource->blockList = NULL;
+
+	resource->numResourcesAllocated = 0;
+
+	ResMngr_CreateBlock(resource);
+}
+
+H2COMMON_API void ResMngr_Des(ResourceManager_t *resource)
+{
+	ResMngr_Block_t *toDelete;
+
+#if 0
+	if (resource->numResourcesAllocated)
+	{
+		char mess[100];
+		sprintf(mess,"Potential memory leak %d bytes unfreed\n",resource->resSize*resource->numResourcesAllocated);
+		OutputDebugString(mess);
+	}
+#endif
+
+	while(resource->blockList)
+	{
+		toDelete = resource->blockList;
+		resource->blockList = resource->blockList->next;
+		free(toDelete->start);
+		free(toDelete);
+	}
+}
+
+H2COMMON_API void *ResMngr_AllocateResource(ResourceManager_t *resource, size_t size)
+{
+	char **toPop;
+
+	assert(size == resource->resSize);
+
+	++resource->numResourcesAllocated;
+
+	assert(resource->free);	// constructor not called; possibly due to a static object
+								// containing a static ResourceManagerFastLarge member being
+								// constructed before its own static members
+
+	toPop = resource->free;
+
+	// set unallocated to the next node and check for NULL (end of list)
+	if(!(resource->free = (char **)(*resource->free)))
+	{	// if at end create new block
+		ResMngr_CreateBlock(resource);
+	}
+
+	// set next to NULL
+	*toPop = NULL;
+
+	// return the resource for the node
+	return (void *)(toPop + 1);
+}
+
+H2COMMON_API void ResMngr_DeallocateResource(ResourceManager_t *resource, void *toDeallocate, size_t size)
+{
+	char **toPush;
+
+	assert(size == resource->resSize);
+
+	--resource->numResourcesAllocated;
+
+	toPush = (char **)(toDeallocate) - 1;
+
+	assert(resource->free);	// see same assert at top of AllocateResource
+
+	// set toPop->next to current unallocated front
+	*toPush = (char *)(resource->free);
+
+	// set unallocated to the node removed from allocated
+	resource->free = toPush;
+}
+
+// end
diff --git a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h
index b8f1eb89..1891d49a 100644
--- a/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h
+++ b/tools/quake2/qdata_heretic2/qcommon/resourcemanager.h
@@ -1,47 +1,47 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// ResourceManager.h
-//
-
-#include "h2common.h"
-#include <stdlib.h>		// needed here for size_t
-
-typedef struct ResourceManager_s
-{
-	size_t resSize;
-	unsigned int resPerBlock;
-	unsigned int nodeSize;
-	struct ResMngr_Block_s *blockList;
-	char **free;
-	char *ResMan_Name;
-
-	unsigned numResourcesAllocated;
-
-} ResourceManager_t;
-
-extern H2COMMON_API void ResMngr_Con(ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name);
-extern H2COMMON_API void ResMngr_Des(ResourceManager_t *resource);
-extern H2COMMON_API void *ResMngr_AllocateResource(ResourceManager_t *resource, size_t size);
-extern H2COMMON_API void ResMngr_DeallocateResource(ResourceManager_t *resource, void *toDeallocate, size_t size);
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// ResourceManager.h
+//
+
+#include "h2common.h"
+#include <stdlib.h>		// needed here for size_t
+
+typedef struct ResourceManager_s
+{
+	size_t resSize;
+	unsigned int resPerBlock;
+	unsigned int nodeSize;
+	struct ResMngr_Block_s *blockList;
+	char **free;
+	char *ResMan_Name;
+
+	unsigned numResourcesAllocated;
+
+} ResourceManager_t;
+
+extern H2COMMON_API void ResMngr_Con(ResourceManager_t *resource, size_t init_resSize, unsigned int init_resPerBlock, char *resman_name);
+extern H2COMMON_API void ResMngr_Des(ResourceManager_t *resource);
+extern H2COMMON_API void *ResMngr_AllocateResource(ResourceManager_t *resource, size_t size);
+extern H2COMMON_API void ResMngr_DeallocateResource(ResourceManager_t *resource, void *toDeallocate, size_t size);
+
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/skeletons.c b/tools/quake2/qdata_heretic2/qcommon/skeletons.c
index c1db9608..8e2f685d 100644
--- a/tools/quake2/qdata_heretic2/qcommon/skeletons.c
+++ b/tools/quake2/qdata_heretic2/qcommon/skeletons.c
@@ -1,232 +1,232 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// Skeletons.c
-//
-
-#include "skeletons.h"
-
-char *skeletonRootNames[] =
-{
-	"RAVEN_ROOT",
-	"BOX_ROOT",
-	"BEETLE_ROOT",
-	"ELFLORD_ROOT",
-	"PLAGUELF_ROOT",
-	"ELF_BACKROOT",
-};
-
-int skeletonRNameOffsets[] =
-{
-	0,	// RAVEN
-	1,	// BOX
-	2,	// BEETLE
-	3,	// ELFLORD
-	4,	// PLAGUE ELF
-	5,	// CORVUS
-};
-
-char *skeletonJointNames[] =
-{
-	"RAVEN_LOWERBACK",	// 0
-	"RAVEN_UPPERBACK",
-	"RAVEN_NECK",
-	"BOX_CENTER",		// 3
-	"BEETLE_NECK",		// 4
-	"BEETLE_HEAD",
-	"PLAGUELF_BACKB",	// 6
-	"PLAGUELF_BACKC",
-	"PLAGUELF_NECK",
-	"ELF_BACKB",		// 9
-	"ELF_BACKC",
-	"ELF_NECKB",
-};
-
-int skeletonNameOffsets[] =
-{
-	0,	// RAVEN
-	3,	// BOX
-	4,	// BEETLE
-	-1,	// ELFLORD
-	6,	// PLAGUE ELF
-	9,	// CORVUS
-};
-
-char *skeletonEffectorNames[] =
-{
-	"BEETLE_EYES",		// 0
-	"CORVUS_EYES",		// 1
-};
-
-int skeletonENameOffsets[] =
-{
-	-1,	// RAVEN
-	-1,	// BOX
-	0,	// BEETLE
-	-1,	// ELFLORD
-	1,	// PLAGUE ELF
-};
-
-int numJointsInSkeleton[] = 
-{
-	NUM_JOINTS_RAVEN,
-	NUM_JOINTS_BOX,
-	NUM_JOINTS_BEETLE,
-	NUM_JOINTS_ELFLORD,
-	NUM_JOINTS_PLAGUE_ELF,
-	NUM_JOINTS_CORVUS,
-};
-
-int numNodesInSkeleton[] =
-{
-	2,	// RAVEN
-	0,	// BOX
-	1,	// BEETLE
-	-1,	// ELFLORD
-	2,	// PLAGUE ELF
-	2,	// CORVUS
-};
-
-void CreateRavenSkel(void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root);
-void CreateBoxSkel(void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root);
-void CreateBeetleSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex);
-void CreateElfLordSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex);
-void CreatePlagueElfSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex);
-
-CreateSkeleton_t SkeletonCreators[NUM_SKELETONS] =
-{
-	CreateRavenSkel,
-	CreateBoxSkel,
-	CreateBeetleSkel,
-	CreateElfLordSkel,
-	CreatePlagueElfSkel,
-	CreatePlagueElfSkel,	// Corvus has the same structure as the Plague Elf
-};
-
-void CreateRavenSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
-{
-	char *root;
-	int *children;
-	int nodeIndex;
-
-	root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-	children = (int *)(root + RAVEN_HEAD * jointSize);
-	*children = ARRAYEDLISTNODE_NULL;
-
-	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
-
-	children = (int *)(root + RAVEN_UPPERBACK * jointSize);
-	*children = nodeIndex;
-
-	g_jointNodes[nodeIndex].data = rootIndex + RAVEN_HEAD;
-	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-
-	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
-
-	children = (int *)(root + RAVEN_LOWERBACK * jointSize);
-	*children = nodeIndex;
-
-	g_jointNodes[nodeIndex].data = rootIndex + RAVEN_UPPERBACK;
-	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
-
-void CreateBoxSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
-{
-	char *root;
-	int *children;
-
-	root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-	children = (int *)(root + RAVEN_HEAD * jointSize);
-	*children = ARRAYEDLISTNODE_NULL;
-}
-
-void CreateBeetleSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
-{
-	char *root;
-	int *children;
-	int nodeIndex;
-
-	root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-	children = (int *)(root + BEETLE_HEAD * jointSize);
-	*children = ARRAYEDLISTNODE_NULL;
-
-	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
-
-	children = (int *)(root + BEETLE_NECK * jointSize);
-	*children = nodeIndex;
-
-	g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
-	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
-
-void CreateElfLordSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
-{
-	char *root;
-	int *children;
-	int nodeIndex;
-
-	root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-	children = (int *)(root + BEETLE_HEAD * jointSize);
-	*children = ARRAYEDLISTNODE_NULL;
-
-	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
-
-	children = (int *)(root + BEETLE_NECK * jointSize);
-	*children = nodeIndex;
-
-	g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
-	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
-
-void CreatePlagueElfSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
-{
-	char *root;
-	int *children;
-	int nodeIndex;
-
-	root = (char *)g_skeletalJoints + rootIndex * jointSize;
-
-	children = (int *)(root + PLAGUE_ELF_HEAD * jointSize);
-	*children = ARRAYEDLISTNODE_NULL;
-
-	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
-
-	children = (int *)(root + PLAGUE_ELF_UPPERBACK * jointSize);
-	*children = nodeIndex;
-
-	g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_HEAD;
-	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-
-	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
-
-	children = (int *)(root + PLAGUE_ELF_LOWERBACK * jointSize);
-	*children = nodeIndex;
-
-	g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_UPPERBACK;
-	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// Skeletons.c
+//
+
+#include "skeletons.h"
+
+char *skeletonRootNames[] =
+{
+	"RAVEN_ROOT",
+	"BOX_ROOT",
+	"BEETLE_ROOT",
+	"ELFLORD_ROOT",
+	"PLAGUELF_ROOT",
+	"ELF_BACKROOT",
+};
+
+int skeletonRNameOffsets[] =
+{
+	0,	// RAVEN
+	1,	// BOX
+	2,	// BEETLE
+	3,	// ELFLORD
+	4,	// PLAGUE ELF
+	5,	// CORVUS
+};
+
+char *skeletonJointNames[] =
+{
+	"RAVEN_LOWERBACK",	// 0
+	"RAVEN_UPPERBACK",
+	"RAVEN_NECK",
+	"BOX_CENTER",		// 3
+	"BEETLE_NECK",		// 4
+	"BEETLE_HEAD",
+	"PLAGUELF_BACKB",	// 6
+	"PLAGUELF_BACKC",
+	"PLAGUELF_NECK",
+	"ELF_BACKB",		// 9
+	"ELF_BACKC",
+	"ELF_NECKB",
+};
+
+int skeletonNameOffsets[] =
+{
+	0,	// RAVEN
+	3,	// BOX
+	4,	// BEETLE
+	-1,	// ELFLORD
+	6,	// PLAGUE ELF
+	9,	// CORVUS
+};
+
+char *skeletonEffectorNames[] =
+{
+	"BEETLE_EYES",		// 0
+	"CORVUS_EYES",		// 1
+};
+
+int skeletonENameOffsets[] =
+{
+	-1,	// RAVEN
+	-1,	// BOX
+	0,	// BEETLE
+	-1,	// ELFLORD
+	1,	// PLAGUE ELF
+};
+
+int numJointsInSkeleton[] = 
+{
+	NUM_JOINTS_RAVEN,
+	NUM_JOINTS_BOX,
+	NUM_JOINTS_BEETLE,
+	NUM_JOINTS_ELFLORD,
+	NUM_JOINTS_PLAGUE_ELF,
+	NUM_JOINTS_CORVUS,
+};
+
+int numNodesInSkeleton[] =
+{
+	2,	// RAVEN
+	0,	// BOX
+	1,	// BEETLE
+	-1,	// ELFLORD
+	2,	// PLAGUE ELF
+	2,	// CORVUS
+};
+
+void CreateRavenSkel(void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root);
+void CreateBoxSkel(void *g_skeletalJoints, size_t jointSize, struct ArrayedListNode_s *g_jointNodes, int root);
+void CreateBeetleSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex);
+void CreateElfLordSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex);
+void CreatePlagueElfSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex);
+
+CreateSkeleton_t SkeletonCreators[NUM_SKELETONS] =
+{
+	CreateRavenSkel,
+	CreateBoxSkel,
+	CreateBeetleSkel,
+	CreateElfLordSkel,
+	CreatePlagueElfSkel,
+	CreatePlagueElfSkel,	// Corvus has the same structure as the Plague Elf
+};
+
+void CreateRavenSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
+{
+	char *root;
+	int *children;
+	int nodeIndex;
+
+	root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+	children = (int *)(root + RAVEN_HEAD * jointSize);
+	*children = ARRAYEDLISTNODE_NULL;
+
+	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
+
+	children = (int *)(root + RAVEN_UPPERBACK * jointSize);
+	*children = nodeIndex;
+
+	g_jointNodes[nodeIndex].data = rootIndex + RAVEN_HEAD;
+	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+
+	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
+
+	children = (int *)(root + RAVEN_LOWERBACK * jointSize);
+	*children = nodeIndex;
+
+	g_jointNodes[nodeIndex].data = rootIndex + RAVEN_UPPERBACK;
+	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
+
+void CreateBoxSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
+{
+	char *root;
+	int *children;
+
+	root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+	children = (int *)(root + RAVEN_HEAD * jointSize);
+	*children = ARRAYEDLISTNODE_NULL;
+}
+
+void CreateBeetleSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
+{
+	char *root;
+	int *children;
+	int nodeIndex;
+
+	root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+	children = (int *)(root + BEETLE_HEAD * jointSize);
+	*children = ARRAYEDLISTNODE_NULL;
+
+	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
+
+	children = (int *)(root + BEETLE_NECK * jointSize);
+	*children = nodeIndex;
+
+	g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
+	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
+
+void CreateElfLordSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
+{
+	char *root;
+	int *children;
+	int nodeIndex;
+
+	root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+	children = (int *)(root + BEETLE_HEAD * jointSize);
+	*children = ARRAYEDLISTNODE_NULL;
+
+	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
+
+	children = (int *)(root + BEETLE_NECK * jointSize);
+	*children = nodeIndex;
+
+	g_jointNodes[nodeIndex].data = rootIndex + BEETLE_HEAD;
+	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
+
+void CreatePlagueElfSkel(void *g_skeletalJoints, size_t jointSize, ArrayedListNode_t *g_jointNodes, int rootIndex)
+{
+	char *root;
+	int *children;
+	int nodeIndex;
+
+	root = (char *)g_skeletalJoints + rootIndex * jointSize;
+
+	children = (int *)(root + PLAGUE_ELF_HEAD * jointSize);
+	*children = ARRAYEDLISTNODE_NULL;
+
+	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
+
+	children = (int *)(root + PLAGUE_ELF_UPPERBACK * jointSize);
+	*children = nodeIndex;
+
+	g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_HEAD;
+	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+
+	nodeIndex = GetFreeNode(g_jointNodes, MAX_ARRAYED_JOINT_NODES);
+
+	children = (int *)(root + PLAGUE_ELF_LOWERBACK * jointSize);
+	*children = nodeIndex;
+
+	g_jointNodes[nodeIndex].data = rootIndex + PLAGUE_ELF_UPPERBACK;
+	g_jointNodes[nodeIndex].next = ARRAYEDLISTNODE_NULL;
+}
+
+
diff --git a/tools/quake2/qdata_heretic2/qcommon/skeletons.h b/tools/quake2/qdata_heretic2/qcommon/skeletons.h
index 83793592..6f340941 100644
--- a/tools/quake2/qdata_heretic2/qcommon/skeletons.h
+++ b/tools/quake2/qdata_heretic2/qcommon/skeletons.h
@@ -1,107 +1,107 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <stdlib.h> // for size_t
-#include "arrayedlist.h"
-
-#define JN_YAW_CHANGED		0x00000001
-#define JN_PITCH_CHANGED	0x00000002
-#define JN_ROLL_CHANGED		0x00000004
-
-// Skeleton types
-enum {
-	SKEL_NULL = -1,
-	SKEL_RAVEN = 0,
-	SKEL_BOX,
-	SKEL_BEETLE,
-	SKEL_ELFLORD,
-	SKEL_PLAGUE_ELF,
-	SKEL_CORVUS,
-	NUM_SKELETONS
-};
-
-// Raven Skeletal joints
-enum {
-	RAVEN_LOWERBACK = 0,
-	RAVEN_UPPERBACK,
-	RAVEN_HEAD,
-	NUM_JOINTS_RAVEN
-};
-
-// Box Skeletal joints
-enum {
-	BOX_CENTER = 0,
-	NUM_JOINTS_BOX
-};
-
-// Beetle Skeletal joints
-enum {
-	BEETLE_NECK = 0,
-	BEETLE_HEAD,
-	NUM_JOINTS_BEETLE
-};
-
-// Elflord Skeletal joints
-enum {
-	ELFLORD_,
-	ELFLORD__,
-	NUM_JOINTS_ELFLORD
-};
-
-// Plague Elf Skeletal joints
-enum {
-	PLAGUE_ELF_LOWERBACK,
-	PLAGUE_ELF_UPPERBACK,
-	PLAGUE_ELF_HEAD,
-	NUM_JOINTS_PLAGUE_ELF
-};
-
-// Corvus Skeletal joints
-enum {
-	CORVUS_LOWERBACK,
-	CORVUS_UPPERBACK,
-	CORVUS_HEAD,
-	NUM_JOINTS_CORVUS
-};
-
-#define NO_SWAP_FRAME -1
-#define NULL_ROOT_JOINT -1
-
-#define MAX_ARRAYED_SKELETAL_JOINTS 255	// has max of 65,535 (if this remains at 255, net code can be changed to reflect)
-#define MAX_ARRAYED_JOINT_NODES	(MAX_ARRAYED_SKELETAL_JOINTS - 1)
-
-#define MAX_JOINTS_PER_SKELETON	8	// arbitrary small number
-#define MAX_JOINT_NODES_PER_SKELETON (MAX_JOINTS_PER_SKELETON - 1)
-
-extern char *skeletonRootNames[];
-extern int skeletonRNameOffsets[];
-extern char *skeletonJointNames[];
-extern int skeletonNameOffsets[];
-extern int numJointsInSkeleton[];
-extern char *skeletonEffectorNames[];
-extern int skeletonENameOffsets[];
-extern int numNodesInSkeleton[];
-
-typedef void (*CreateSkeleton_t)(void *skeletalJoints, size_t jointSize, struct ArrayedListNode_s *jointNodes, int rootIndex);
-
-extern CreateSkeleton_t SkeletonCreators[NUM_SKELETONS];
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdlib.h> // for size_t
+#include "arrayedlist.h"
+
+#define JN_YAW_CHANGED		0x00000001
+#define JN_PITCH_CHANGED	0x00000002
+#define JN_ROLL_CHANGED		0x00000004
+
+// Skeleton types
+enum {
+	SKEL_NULL = -1,
+	SKEL_RAVEN = 0,
+	SKEL_BOX,
+	SKEL_BEETLE,
+	SKEL_ELFLORD,
+	SKEL_PLAGUE_ELF,
+	SKEL_CORVUS,
+	NUM_SKELETONS
+};
+
+// Raven Skeletal joints
+enum {
+	RAVEN_LOWERBACK = 0,
+	RAVEN_UPPERBACK,
+	RAVEN_HEAD,
+	NUM_JOINTS_RAVEN
+};
+
+// Box Skeletal joints
+enum {
+	BOX_CENTER = 0,
+	NUM_JOINTS_BOX
+};
+
+// Beetle Skeletal joints
+enum {
+	BEETLE_NECK = 0,
+	BEETLE_HEAD,
+	NUM_JOINTS_BEETLE
+};
+
+// Elflord Skeletal joints
+enum {
+	ELFLORD_,
+	ELFLORD__,
+	NUM_JOINTS_ELFLORD
+};
+
+// Plague Elf Skeletal joints
+enum {
+	PLAGUE_ELF_LOWERBACK,
+	PLAGUE_ELF_UPPERBACK,
+	PLAGUE_ELF_HEAD,
+	NUM_JOINTS_PLAGUE_ELF
+};
+
+// Corvus Skeletal joints
+enum {
+	CORVUS_LOWERBACK,
+	CORVUS_UPPERBACK,
+	CORVUS_HEAD,
+	NUM_JOINTS_CORVUS
+};
+
+#define NO_SWAP_FRAME -1
+#define NULL_ROOT_JOINT -1
+
+#define MAX_ARRAYED_SKELETAL_JOINTS 255	// has max of 65,535 (if this remains at 255, net code can be changed to reflect)
+#define MAX_ARRAYED_JOINT_NODES	(MAX_ARRAYED_SKELETAL_JOINTS - 1)
+
+#define MAX_JOINTS_PER_SKELETON	8	// arbitrary small number
+#define MAX_JOINT_NODES_PER_SKELETON (MAX_JOINTS_PER_SKELETON - 1)
+
+extern char *skeletonRootNames[];
+extern int skeletonRNameOffsets[];
+extern char *skeletonJointNames[];
+extern int skeletonNameOffsets[];
+extern int numJointsInSkeleton[];
+extern char *skeletonEffectorNames[];
+extern int skeletonENameOffsets[];
+extern int numNodesInSkeleton[];
+
+typedef void (*CreateSkeleton_t)(void *skeletalJoints, size_t jointSize, struct ArrayedListNode_s *jointNodes, int rootIndex);
+
+extern CreateSkeleton_t SkeletonCreators[NUM_SKELETONS];
+
+
diff --git a/tools/quake2/qdata_heretic2/qd_fmodel.h b/tools/quake2/qdata_heretic2/qd_fmodel.h
index 830325f1..c1db5da6 100644
--- a/tools/quake2/qdata_heretic2/qd_fmodel.h
+++ b/tools/quake2/qdata_heretic2/qd_fmodel.h
@@ -1,61 +1,61 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef FMODEL_H
-#define FMODEL_H
-#include "fmodel.h"
-#endif
-#include "qd_skeletons.h"
-
-typedef struct
-{
-	int		numnormals;
-	vec3_t	normalsum;
-} fmvertexnormals_t;
-
-typedef struct
-{
-	vec3_t				v;
-	int					lightnormalindex;
-	fmvertexnormals_t	vnorm;
-} fmtrivert_t;
-
-#define FRAME_NAME_LEN (16)
-
-typedef struct
-{
-	vec3_t		mins, maxs;
-	char		name[FRAME_NAME_LEN];
-	fmtrivert_t	v[MAX_FM_VERTS];
-	struct QD_SkeletalJoint_s joints[NUM_CLUSTERS];
-	struct QD_SkeletalJoint_s references[NUM_REFERENCES];
-} fmframe_t;
-
-extern fmframe_t	g_frames[MAX_FM_FRAMES];
-
-extern fmheader_t	fmheader;
-extern char			cdarchive[1024];				// set by $fmcd
-extern char			cdpartial[1024];				// set by $fmcd
-extern char			cddir[1024];					// set by $fmcd
-
-void GrabFrame (char *frame);
-void H_printf(char *fmt, ...);
-char *FindFrameFile (char *frame);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef FMODEL_H
+#define FMODEL_H
+#include "fmodel.h"
+#endif
+#include "qd_skeletons.h"
+
+typedef struct
+{
+	int		numnormals;
+	vec3_t	normalsum;
+} fmvertexnormals_t;
+
+typedef struct
+{
+	vec3_t				v;
+	int					lightnormalindex;
+	fmvertexnormals_t	vnorm;
+} fmtrivert_t;
+
+#define FRAME_NAME_LEN (16)
+
+typedef struct
+{
+	vec3_t		mins, maxs;
+	char		name[FRAME_NAME_LEN];
+	fmtrivert_t	v[MAX_FM_VERTS];
+	struct QD_SkeletalJoint_s joints[NUM_CLUSTERS];
+	struct QD_SkeletalJoint_s references[NUM_REFERENCES];
+} fmframe_t;
+
+extern fmframe_t	g_frames[MAX_FM_FRAMES];
+
+extern fmheader_t	fmheader;
+extern char			cdarchive[1024];				// set by $fmcd
+extern char			cdpartial[1024];				// set by $fmcd
+extern char			cddir[1024];					// set by $fmcd
+
+void GrabFrame (char *frame);
+void H_printf(char *fmt, ...);
+char *FindFrameFile (char *frame);
diff --git a/tools/quake2/qdata_heretic2/qd_skeletons.c b/tools/quake2/qdata_heretic2/qd_skeletons.c
index 18868f1e..f36fb1df 100644
--- a/tools/quake2/qdata_heretic2/qd_skeletons.c
+++ b/tools/quake2/qdata_heretic2/qd_skeletons.c
@@ -1,1291 +1,1291 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qd_skeletons.h"
-#include "skeletons.h"
-#include "qd_fmodel.h"
-#include "angles.h"
-#include "token.h"
-#include "qdata.h"
-#include "reference.h"
-
-#include <assert.h>
-#include <math.h>
-#include <memory.h>
-
-
-// We're assuming no more than 16 reference points, with no more than 32 characters in the name
-char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
-int	 RefPointNum = 0;
-
-Skeletalfmheader_t g_skelModel;
-
-void ClearSkeletalModel()
-{
-	g_skelModel.type = SKEL_NULL;
-	g_skelModel.clustered = false;
-	g_skelModel.references = REF_NULL;
-}
-
-//==========================================================================
-//
-// LoadHRCClustered
-//
-//==========================================================================
-
-// Places the null terminated src string into the dest string less any trailing digits or underscores
-void StripTrailingDigits(char *src, char *dest)
-{
-#ifndef NDEBUG
-	int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files
-#endif
-	int i = 0;
-
-	while(src[i] != '\0')
-	{
-		++i;
-#ifndef NDEBUG
-		assert(i < max);
-#endif
-	}
-
-	while((src[--i] >= '0' && src[i] <= '9') || src[i] == '_')
-	{
-
-	}
-
-	memcpy(dest, src, ++i);
-
-	dest[i] = '\0';
-}
-
-static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)
-{
-	extern void HandleHRCModel(triangle_t **triList, int *triangleCount, 
-		mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth);
-
-	extern mesh_node_t	*pmnodes;
-
-	triangle_t *triList;
-//    	mesh_node_t *nodesList;
-	int num_mesh_nodes = 0, triangleCount = 0;
-
-#if 0
-	int i;
-	int j, numVerts;
-	char stripped[SKELETAL_NAME_MAX];
-
-	for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
-	{
-		num_verts[i] = 0;
-	}
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-
-	TK_Beyond(TK_CLUSTERS);
-
-	while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)
-	{
-		TK_Require(TK_STRING);
-
-		StripTrailingDigits(tk_String, stripped);
-
-		for( i = 0; i < numJointsInSkeleton[skelType]; ++i)
-		{
-			if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)
-			{
-				i = -i + numJointsInSkeleton[skelType] - 1;
-
-				TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
-
-				numVerts = tk_IntNumber;
-
-				if(!num_verts[i+1])	// first set of verts for cluster
-				{
-					clusterList[i] = SafeMalloc(numVerts*sizeof(int), "LoadHRCClustered");
-					assert(clusterList[i]);
-				}
-				else				// any later sets of verts need to copy current
-				{
-					int *temp;
-
-					temp = SafeMalloc((num_verts[i+1]+numVerts)*sizeof(int), "LoadHRCClustered");
-					assert(temp);
-
-					memcpy(temp + numVerts, clusterList[i], num_verts[i+1]*sizeof(int));
-
-					free(clusterList[i]);
-
-					clusterList[i] = temp;
-				}
-
-				// currently this function is only called by LoadModelClusters.
-				// Apparently the matching free has disappeared, 
-				// should probably be free at the end of FMCmd_Base
-
-				TK_Beyond(TK_LBRACE);
-
-				for(j = 0; j < numVerts; ++j)
-				{
-					TK_Require(TK_INTNUMBER);
-					clusterList[i][j] = tk_IntNumber;
-					TK_Fetch();
-				}
-
-				num_verts[i+1] += numVerts;
-
-				break;
-			}
-		}
-	}
-
-	num_verts[0] = numJointsInSkeleton[skelType];
-#endif
-
-#if 1	// get the index number localized to the root
-//	for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
-//	{
-//		g_skelModel.num_verts[i] = 0;
-//	}
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-
-	// prime it
-	TK_Beyond(TK_MODEL);
-
-	triList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
-	memset(triList,0,MAXTRIANGLES*sizeof(triangle_t));
-//	nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-	pmnodes = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
-
-	memset(pmnodes, 0, MAX_FM_MESH_NODES * sizeof(mesh_node_t));
-
-	// this should eventually use a stripped down version of this
-	HandleHRCModel(&triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0);
-
-//	free(nodesList);
-	free(triList);
-
-	num_verts[0] = numJointsInSkeleton[skelType];
-#endif
-}
-
-void ReadHRCClusterList(mesh_node_t *meshNode, int baseIndex)
-{
-	int i, j, numVerts;
-	tokenType_t nextToken;
-	char stripped[SKELETAL_NAME_MAX];
-
-	meshNode->clustered = true;
-
-	nextToken = TK_Get(TK_CLUSTER_NAME);
-
-	while (nextToken == TK_CLUSTER_NAME)
-	{
-		TK_FetchRequire(TK_STRING);
-
-		StripTrailingDigits(tk_String, stripped);
-
-		for( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)
-		{
-			if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type]+i]) == 0)
-			{
-				i = -i + numJointsInSkeleton[g_skelModel.type] - 1;
-
-				TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
-
-				numVerts = tk_IntNumber;
-
-				if(!baseIndex)
-				{
-					meshNode->clusters[i] = (int *) SafeMalloc(numVerts*sizeof(int), "ReadHRCClusterList");
-					assert(meshNode->clusters[i]);
-				}
-				else
-				{
-					int *temp; 
-
-					temp = meshNode->clusters[i];
-					meshNode->clusters[i] = (int *) SafeMalloc((meshNode->num_verts[i+1]+numVerts)*sizeof(int), "ReadHRCClusterList");
-					assert(meshNode->clusters[i]);
-
-					memcpy(meshNode->clusters[i], temp, meshNode->num_verts[i+1]*sizeof(int));
-					free(temp);
-				}
-
-				// currently this function is only called by LoadModelClusters.
-				// Apparently the matching free has disappeared, 
-				// should probably be free at the end of FMCmd_Base
-
-				TK_Beyond(TK_LBRACE);
-
-				for(j = 0; j < numVerts; ++j)
-				{
-					TK_Require(TK_INTNUMBER);
-					meshNode->clusters[i][baseIndex+j] = tk_IntNumber+baseIndex;
-					TK_Fetch();
-				}
-
-				if(baseIndex)
-				{
-					meshNode->num_verts[i+1] += numVerts;
-				}
-				else
-				{
-					meshNode->num_verts[i+1] = numVerts;
-				}
-
-				break;
-			}
-		}
-
-		TK_BeyondRequire(TK_CLUSTER_STATE, TK_INTNUMBER);
-		nextToken = TK_Fetch();
-	}
-}
-
-static void LoadHRCGlobals(char *fileName)
-{
-	int i;
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-	TK_Beyond(TK_MODEL);
-
-	TK_Beyond(TK_SCALING);
-	for(i = 0; i < 3; i++)
-	{
-		TK_Require(TK_FLOATNUMBER);
-		g_skelModel.scaling[i] = tk_FloatNumber;
-		TK_Fetch();
-	}
-
-	TK_Beyond(TK_ROTATION);
-	for(i = 0; i < 3; i++)
-	{
-		TK_Require(TK_FLOATNUMBER);
-		g_skelModel.rotation[i] = tk_FloatNumber;
-		TK_Fetch();
-	}
-
-	TK_Beyond(TK_TRANSLATION);
-	for(i = 0; i < 3; i++)
-	{
-		TK_Require(TK_FLOATNUMBER);
-		g_skelModel.translation[i] = tk_FloatNumber;
-		TK_Fetch();
-	}
-}
-
-static void ParseVec3(vec3_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void ParseVec3d(vec3d_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void ParseRotation3(vec3_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void ParseRotation3d(vec3d_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void ParseTranslation3(vec3_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void ParseTranslation3d(vec3d_t in)
-{
-	TK_Require(TK_FLOATNUMBER);
-	in[1] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[2] = tk_FloatNumber;
-	TK_FetchRequire(TK_FLOATNUMBER);
-	in[0] = tk_FloatNumber;
-}
-
-static void LoadHRCJointList(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)
-{
-#define MAX_STACK 64
-	int i, j;
-	vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
-	int curCorrespondingJoint[MAX_STACK];
-	int currentStack = 0, stackSize;
-	double cx, sx, cy, sy, cz, sz;
-	double rx, ry, rz;
-	double x2, y2, z2;
-	char stripped[SKELETAL_NAME_MAX];
-	Placement_d_t *placement;
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-
-	TK_Beyond(TK_MODEL);
-
-	while(TK_Search(TK_NAME) != TK_EOF)
-	{
-		TK_Require(TK_STRING);
-
-		StripTrailingDigits(tk_String, stripped);
-
-		if(stricmp(stripped, skeletonRootNames[skeletonRNameOffsets[skelType]]) == 0)
-		{
-			break;
-		}
-	}
-
-	if(tk_Token == TK_EOF)
-	{
-		Error("Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]]);
-		return;
-	}
-
-	TK_Beyond(TK_SCALING);
-
-	ParseVec3d(curScale[currentStack]);
-
-	TK_Beyond(TK_ROTATION);
-
-	ParseRotation3d(curRotation[currentStack]);
-
-	TK_Beyond(TK_TRANSLATION);
-
-	ParseVec3d(curTranslation[currentStack]);
-
-	// account for global model translation
-	curTranslation[currentStack][1] += g_skelModel.translation[0];
-	curTranslation[currentStack][2] += g_skelModel.translation[1];
-	curTranslation[currentStack][0] += g_skelModel.translation[2];
-
-	curCorrespondingJoint[currentStack] = -1;
-
-	++currentStack;
-
-	for(i = 0; i < numJointsInSkeleton[skelType]; ++i)
-	{
-		while(1)
-		{
-			TK_Beyond(TK_MODEL);
-
-			TK_BeyondRequire(TK_NAME, TK_STRING);
-
-			StripTrailingDigits(tk_String, stripped);
-
-			if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)
-				break;
-
-			TK_Beyond(TK_SCALING);
-
-			ParseVec3d(curScale[currentStack]);
-
-			TK_Beyond(TK_ROTATION);
-
-			ParseRotation3d(curRotation[currentStack]);
-
-			TK_Beyond(TK_TRANSLATION);
-
-			ParseVec3d(curTranslation[currentStack]);
-
-			curCorrespondingJoint[currentStack] = -1;
-
-			++currentStack;
-		}
-
-		TK_Beyond(TK_SCALING);
-
-		ParseVec3d(curScale[currentStack]);
-
-		TK_Beyond(TK_ROTATION);
-
-		ParseRotation3d(curRotation[currentStack]);
-
-		jointList[i].rotation[1] = curRotation[currentStack][1];
-		jointList[i].rotation[2] = curRotation[currentStack][2];
-		jointList[i].rotation[0] = curRotation[currentStack][0];
-
-		TK_Beyond(TK_TRANSLATION);
-
-		ParseVec3d(curTranslation[currentStack]);
-
-//		jointList[i].placement.origin[1] = curTranslation[currentStack][1];
-//		jointList[i].placement.origin[2] = curTranslation[currentStack][2];
-//		jointList[i].placement.origin[0] = curTranslation[currentStack][0];
-
-		jointList[i].placement.origin[1] = 0.0;
-		jointList[i].placement.origin[2] = 0.0;
-		jointList[i].placement.origin[0] = 0.0;
-
-		jointList[i].placement.direction[1] = 20.0;
-		jointList[i].placement.direction[2] = 0.0;
-		jointList[i].placement.direction[0] = 0.0;
-
-		jointList[i].placement.up[1] = 0.0;
-		jointList[i].placement.up[2] = 20.0;
-		jointList[i].placement.up[0] = 0.0;
-
-		curCorrespondingJoint[currentStack] = i;
-
-		++currentStack;
-	}
-
-	stackSize = currentStack;
-
-#if 0
-	// rotate the direction and up vectors to correspond to the rotation
-	for(i = 0; i < numJointsInSkeleton[skelType]; ++i)
-	{
-		rx = jointList[i].rotation[0]*ANGLE_TO_RAD;
-		ry = jointList[i].rotation[1]*ANGLE_TO_RAD;
-		rz = jointList[i].rotation[2]*ANGLE_TO_RAD;
-
-		cx = cos(rx);
-		sx = sin(rx);
-
-		cy = cos(ry);
-		sy = sin(ry);
-
-		cz = cos(rz);
-		sz = sin(rz);
-
-		// y-axis rotation for direction
-		x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;
-		z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;
-		jointList[i].placement.direction[0] = x2;
-		jointList[i].placement.direction[2] = z2;
-
-		// y-axis rotation for up
-		x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;
-		z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;
-		jointList[i].placement.up[0] = x2;
-		jointList[i].placement.up[2] = z2;
-
-		// z-axis rotation for direction
-		x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;
-		y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;
-		jointList[i].placement.direction[0] = x2;
-		jointList[i].placement.direction[1] = y2;
-
-		// z-axis rotation for up
-		x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;
-		y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;
-		jointList[i].placement.up[0] = x2;
-		jointList[i].placement.up[1] = y2;
-
-		// x-axis rotation for direction vector
-		y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;
-		z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;
-		jointList[i].placement.direction[1] = y2;
-		jointList[i].placement.direction[2] = z2;
-
-		// x-axis rotation for up vector
-		y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;
-		z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;
-		jointList[i].placement.up[1] = y2;
-		jointList[i].placement.up[2] = z2;
-
-		// translate direction to a point in the model
-		jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
-		jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
-		jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
-
-		// translate up to a point in the model
-		jointList[i].placement.up[0] += jointList[i].placement.origin[0];
-		jointList[i].placement.up[1] += jointList[i].placement.origin[1];
-		jointList[i].placement.up[2] += jointList[i].placement.origin[2];
-	}
-#endif
-
-	for(i = stackSize - 1; i >= 0; --i)
-	{
-		rx = curRotation[i][0]*ANGLE_TO_RAD;
-		ry = curRotation[i][1]*ANGLE_TO_RAD;
-		rz = curRotation[i][2]*ANGLE_TO_RAD;
-
-		cx = cos(rx);
-		sx = sin(rx);
-
-		cy = cos(ry);
-		sy = sin(ry);
-
-		cz = cos(rz);
-		sz = sin(rz);
-
-#if 1
-		for(j = i; j < stackSize; ++j)
-		{
-			if(curCorrespondingJoint[j] != -1)
-			{
-				placement = &jointList[curCorrespondingJoint[j]].placement;
-
-				// y-axis rotation for origin
-				x2 = placement->origin[0]*cy+placement->origin[2]*sy;
-				z2 = -placement->origin[0]*sy+placement->origin[2]*cy;
-				placement->origin[0] = x2;
-				placement->origin[2] = z2;
-
-				// y-axis rotation for direction
-				x2 = placement->direction[0]*cy+placement->direction[2]*sy;
-				z2 = -placement->direction[0]*sy+placement->direction[2]*cy;
-				placement->direction[0] = x2;
-				placement->direction[2] = z2;
-
-				// y-axis rotation for up
-				x2 = placement->up[0]*cy+placement->up[2]*sy;
-				z2 = -placement->up[0]*sy+placement->up[2]*cy;
-				placement->up[0] = x2;
-				placement->up[2] = z2;
-
-				// z-axis rotation for origin
-				x2 = placement->origin[0]*cz-placement->origin[1]*sz;
-				y2 = placement->origin[0]*sz+placement->origin[1]*cz;
-				placement->origin[0] = x2;
-				placement->origin[1] = y2;
-
-				// z-axis rotation for direction
-				x2 = placement->direction[0]*cz-placement->direction[1]*sz;
-				y2 = placement->direction[0]*sz+placement->direction[1]*cz;
-				placement->direction[0] = x2;
-				placement->direction[1] = y2;
-
-				// z-axis rotation for up
-				x2 = placement->up[0]*cz-placement->up[1]*sz;
-				y2 = placement->up[0]*sz+placement->up[1]*cz;
-				placement->up[0] = x2;
-				placement->up[1] = y2;
-
-				// x-axis rotation for origin
-				y2 = placement->origin[1]*cx-placement->origin[2]*sx;
-				z2 = placement->origin[1]*sx+placement->origin[2]*cx;
-				placement->origin[1] = y2;
-				placement->origin[2] = z2;
-
-				// x-axis rotation for direction vector
-				y2 = placement->direction[1]*cx-placement->direction[2]*sx;
-				z2 = placement->direction[1]*sx+placement->direction[2]*cx;
-				placement->direction[1] = y2;
-				placement->direction[2] = z2;
-
-				// x-axis rotation for up vector
-				y2 = placement->up[1]*cx-placement->up[2]*sx;
-				z2 = placement->up[1]*sx+placement->up[2]*cx;
-				placement->up[1] = y2;
-				placement->up[2] = z2;
-
-				// translate origin
-				placement->origin[0] += curTranslation[i][0];
-				placement->origin[1] += curTranslation[i][1];
-				placement->origin[2] += curTranslation[i][2];
-
-				// translate back to local coord
-				placement->direction[0] += curTranslation[i][0];
-				placement->direction[1] += curTranslation[i][1];
-				placement->direction[2] += curTranslation[i][2];
-
-				// translate back to local coord
-				placement->up[0] += curTranslation[i][0];
-				placement->up[1] += curTranslation[i][1];
-				placement->up[2] += curTranslation[i][2];
-			}
-		}
-#else
-		// This screwed up and needs to be sorted out!!!
-		// The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton
-		for(j = i-1; j < stackSize-1; ++j)
-		{
-			// y-axis rotation for origin
-			x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;
-			z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;
-			jointList[j].placement.origin[0] = x2;
-			jointList[j].placement.origin[2] = z2;
-
-			// y-axis rotation for direction
-			x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;
-			z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;
-			jointList[j].placement.direction[0] = x2;
-			jointList[j].placement.direction[2] = z2;
-
-			// y-axis rotation for up
-			x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;
-			z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;
-			jointList[j].placement.up[0] = x2;
-			jointList[j].placement.up[2] = z2;
-
-			// z-axis rotation for origin
-			x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;
-			y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;
-			jointList[j].placement.origin[0] = x2;
-			jointList[j].placement.origin[1] = y2;
-
-			// z-axis rotation for direction
-			x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;
-			y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;
-			jointList[j].placement.direction[0] = x2;
-			jointList[j].placement.direction[1] = y2;
-
-			// z-axis rotation for up
-			x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;
-			y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;
-			jointList[j].placement.up[0] = x2;
-			jointList[j].placement.up[1] = y2;
-
-			// x-axis rotation for origin
-			y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;
-			z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;
-			jointList[j].placement.origin[1] = y2;
-			jointList[j].placement.origin[2] = z2;
-
-			// x-axis rotation for direction vector
-			y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;
-			z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;
-			jointList[j].placement.direction[1] = y2;
-			jointList[j].placement.direction[2] = z2;
-
-			// x-axis rotation for up vector
-			y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;
-			z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;
-			jointList[j].placement.up[1] = y2;
-			jointList[j].placement.up[2] = z2;
-
-			if(curCorrespondingJoint[j+1] != -1)
-			{
-				// translate origin
-				jointList[j].placement.origin[0] += curTranslation[i-1][0];
-				jointList[j].placement.origin[1] += curTranslation[i-1][1];
-				jointList[j].placement.origin[2] += curTranslation[i-1][2];
-
-				// translate back to local coord
-				jointList[j].placement.direction[0] += curTranslation[i-1][0];
-				jointList[j].placement.direction[1] += curTranslation[i-1][1];
-				jointList[j].placement.direction[2] += curTranslation[i-1][2];
-
-				// translate back to local coord
-				jointList[j].placement.up[0] += curTranslation[i-1][0];
-				jointList[j].placement.up[1] += curTranslation[i-1][1];
-				jointList[j].placement.up[2] += curTranslation[i-1][2];
-			}
-		}
-#endif
-	}
-}
-
-void LoadModelTransform(char *fileName)
-{
-	FILE *file1;
-    int dot = '.';
-	char *dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-
-			LoadHRCGlobals(InputFileName);
-
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		Error("\n Could not open file '%s':\n"
-			"No HRC match.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-//			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRCGlobals(fileName);
-				return;
-			}
-		}
-
-		Error("Could not open file '%s':\n",fileName);
-	}
-}
-
-void LoadModelClusters(char *fileName, int **clusterList, int *num_verts, int skelType)
-{
-	FILE *file1;
-    int dot = '.';
-	char *dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-
-			LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);
-
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		Error("\n Could not open file '%s':\n"
-			"No HRC match.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-//			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRCClustered(fileName, clusterList, num_verts, skelType);
-				return;
-			}
-		}
-
-		Error("Could not open file '%s':\n",fileName);
-	}
-}
-
-void LoadSkeleton(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)
-{
-	FILE *file1;
-    int dot = '.';
-	char *dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-
-			LoadHRCJointList(InputFileName, jointList, skelType);
-
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		Error("\n Could not open file '%s':\n"
-			"No HRC.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-//			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRCJointList(fileName, jointList, skelType);
-
-				return;
-			}
-		}
-
-		Error("Could not open file '%s':\n",fileName);
-	}
-}
-
-/*
-===============
-GrabSkeletalFrame
-===============
-*/
-void GrabSkeletalFrame(char *frame)
-{
-	char	file1[1024];
-	char	*framefile;
-	fmframe_t	*fr;
-
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-	printf ("Grabbing Skeletal Frame %s\n", file1);
-
-	fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
-
-	LoadSkeleton(file1, fr->joints, g_skelModel.type);
-}
-
-/*
-===============
-GrabModelTransform
-===============
-*/
-void GrabModelTransform(char *frame)
-{
-	char	file1[1024];
-	char	*framefile;
-	fmframe_t	*fr;
-
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-//	printf ("grabbing %s\n", file1);
-
-	fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
-
-	LoadModelTransform(file1);
-}
-
-void Cmd_FMCluster()
-{
-	char file1[1024];
-
-	GetScriptToken (false);
-
-	printf ("---------------------\n");
-	sprintf (file1, "%s/%s", cdpartial, token);
-	printf ("%s\n", file1);
-
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s", cddir, token);
-
-	g_skelModel.clustered = -1;
-
-	LoadModelClusters(file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type);
-
-	g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];
-
-	g_skelModel.clustered = true;
-}
-
-void Cmd_FMSkeleton()
-{
-	GetScriptToken (false);
-	g_skelModel.type = atoi(token);
-}
-
-void Cmd_FMSkeletalFrame()
-{
-	while (ScriptTokenAvailable())
-	{
-		GetScriptToken (false);
-		if (g_skipmodel)
-		{
-			GetScriptToken (false);
-			continue;
-		}
-		if (g_release || g_archive)
-		{
-			fmheader.num_frames = 1;	// don't skip the writeout
-			GetScriptToken (false);
-			continue;
-		}
-
-		H_printf("#define FRAME_%-16s\t%i\n", token, fmheader.num_frames);
-
-		GrabModelTransform (token);
-		GrabFrame (token);
-		GrabSkeletalFrame (token);
-
-		// need to add the up and dir points to the frame bounds here
-		// using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
-		// then remove fudge in determining scale on frame write out
-	}
-}
-
-static void LoadHRCReferences(char *fileName, fmframe_t *fr)
-{
-#define MAX_STACK 64
-	int i, j, k;
-	vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];
-	int curCorrespondingJoint[MAX_STACK];
-	int currentStack, stackSize;
-	double cx, sx, cy, sy, cz, sz;
-	double rx, ry, rz;
-	double x2, y2, z2;
-	char stripped[SKELETAL_NAME_MAX];
-	Placement_d_t *placement;
-	int refnum;
-
-	TK_OpenSource(fileName);
-	TK_FetchRequire(TK_HRCH);
-	TK_FetchRequire(TK_COLON);
-	TK_FetchRequire(TK_SOFTIMAGE);
-
-	if (RefPointNum <= 0)
-	{	// There were no labels indicated in the QDT, so use the hard-coded stuff.
-		refnum = numReferences[g_skelModel.references];
-	}
-	else
-	{
-		refnum = RefPointNum;
-	}
-
-	for(k = 0; k < refnum; ++k)
-	{
-		currentStack = 0;
-
-		// Load the root to get translation and initial rotation
-//		TK_Beyond(TK_MODEL);
-
-		while(TK_Search(TK_NAME) != TK_EOF)
-		{
-			TK_Require(TK_STRING);
-
-			StripTrailingDigits(tk_String, stripped);
-
-			if (RefPointNum == 0)
-			{	// Hard coded refpoint labels
-				if(stricmp(stripped, 
-					referenceRootNames[referenceRootNameOffsets[g_skelModel.references]+k]) == 0)
-				{
-					break;
-				}
-			}
-			else
-			{	// labels indicated by the QDT
-				if(stricmp(stripped, RefPointNameList[k]) == 0)
-				{
-					break;
-				}
-			}
-		}
-
-		if(tk_Token == TK_EOF)
-		{
-			if (RefPointNum == 0)
-			{	// Hard coded refpoint labels
-				Error("Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]]);
-			}
-			else
-			{	// labels indicated by the QDT
-				Error("Bone Chain Root: %s not found\n", RefPointNameList[k]);
-			}
-			return;
-		}
-
-//		TK_Beyond(TK_SCALING);
-
-//		ParseVec3d(curScale[currentStack]);
-
-		TK_Beyond(TK_ROTATION);
-
-		ParseRotation3d(curRotation[currentStack]);
-
-		TK_Beyond(TK_TRANSLATION);
-
-		ParseVec3d(curTranslation[currentStack]);
-
-		// account for global model translation
-		curTranslation[currentStack][1] += g_skelModel.translation[0];
-		curTranslation[currentStack][2] += g_skelModel.translation[1];
-		curTranslation[currentStack][0] += g_skelModel.translation[2];
-
-		curCorrespondingJoint[currentStack] = -1;
-
-//		rjr - this one not needed, as there is also a stack increment 20 lines below???
-//		++currentStack;
-
-		// Load the joint to get orientation
-		TK_Beyond(TK_MODEL);
-
-//		TK_Beyond(TK_SCALING);
-
-//		ParseVec3d(curScale[currentStack]);
-
-		TK_Beyond(TK_ROTATION);
-
-		ParseRotation3d(curRotation[currentStack]);
-
-//		TK_Beyond(TK_TRANSLATION);
-
-//		ParseVec3d(curTranslation[currentStack]);
-
-		fr->references[k].placement.origin[1] = 0.0;
-		fr->references[k].placement.origin[2] = 0.0;
-		fr->references[k].placement.origin[0] = 0.0;
-
-		fr->references[k].placement.direction[1] = 20.0;
-		fr->references[k].placement.direction[2] = 0.0;
-		fr->references[k].placement.direction[0] = 0.0;
-
-		fr->references[k].placement.up[1] = 0.0;
-		fr->references[k].placement.up[2] = 20.0;
-		fr->references[k].placement.up[0] = 0.0;
-
-		curCorrespondingJoint[currentStack] = k;
-
-		++currentStack;
-
-		stackSize = currentStack;
-
-		for(i = stackSize - 1; i >= 0; --i)
-		{
-			rx = curRotation[i][0]*ANGLE_TO_RAD;
-			ry = curRotation[i][1]*ANGLE_TO_RAD;
-			rz = curRotation[i][2]*ANGLE_TO_RAD;
-
-			cx = cos(rx);
-			sx = sin(rx);
-
-			cy = cos(ry);
-			sy = sin(ry);
-
-			cz = cos(rz);
-			sz = sin(rz);
-
-			for(j = i; j < stackSize; ++j)
-			{
-				if(curCorrespondingJoint[j] != -1)
-				{
-					placement = &fr->references[curCorrespondingJoint[j]].placement;
-
-					// y-axis rotation for origin
-					x2 = placement->origin[0]*cy+placement->origin[2]*sy;
-					z2 = -placement->origin[0]*sy+placement->origin[2]*cy;
-					placement->origin[0] = x2;
-					placement->origin[2] = z2;
-
-					// y-axis rotation for direction
-					x2 = placement->direction[0]*cy+placement->direction[2]*sy;
-					z2 = -placement->direction[0]*sy+placement->direction[2]*cy;
-					placement->direction[0] = x2;
-					placement->direction[2] = z2;
-
-					// y-axis rotation for up
-					x2 = placement->up[0]*cy+placement->up[2]*sy;
-					z2 = -placement->up[0]*sy+placement->up[2]*cy;
-					placement->up[0] = x2;
-					placement->up[2] = z2;
-
-					// z-axis rotation for origin
-					x2 = placement->origin[0]*cz-placement->origin[1]*sz;
-					y2 = placement->origin[0]*sz+placement->origin[1]*cz;
-					placement->origin[0] = x2;
-					placement->origin[1] = y2;
-
-					// z-axis rotation for direction
-					x2 = placement->direction[0]*cz-placement->direction[1]*sz;
-					y2 = placement->direction[0]*sz+placement->direction[1]*cz;
-					placement->direction[0] = x2;
-					placement->direction[1] = y2;
-
-					// z-axis rotation for up
-					x2 = placement->up[0]*cz-placement->up[1]*sz;
-					y2 = placement->up[0]*sz+placement->up[1]*cz;
-					placement->up[0] = x2;
-					placement->up[1] = y2;
-
-					// x-axis rotation for origin
-					y2 = placement->origin[1]*cx-placement->origin[2]*sx;
-					z2 = placement->origin[1]*sx+placement->origin[2]*cx;
-					placement->origin[1] = y2;
-					placement->origin[2] = z2;
-
-					// x-axis rotation for direction vector
-					y2 = placement->direction[1]*cx-placement->direction[2]*sx;
-					z2 = placement->direction[1]*sx+placement->direction[2]*cx;
-					placement->direction[1] = y2;
-					placement->direction[2] = z2;
-
-					// x-axis rotation for up vector
-					y2 = placement->up[1]*cx-placement->up[2]*sx;
-					z2 = placement->up[1]*sx+placement->up[2]*cx;
-					placement->up[1] = y2;
-					placement->up[2] = z2;
-
-					// translate origin
-					placement->origin[0] += curTranslation[i][0];
-					placement->origin[1] += curTranslation[i][1];
-					placement->origin[2] += curTranslation[i][2];
-
-					// translate back to local coord
-					placement->direction[0] += curTranslation[i][0];
-					placement->direction[1] += curTranslation[i][1];
-					placement->direction[2] += curTranslation[i][2];
-
-					// translate back to local coord
-					placement->up[0] += curTranslation[i][0];
-					placement->up[1] += curTranslation[i][1];
-					placement->up[2] += curTranslation[i][2];
-
-				}
-			}
-		}
-		printf("%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2]);
-	}
-	printf("\n");
-}
-
-void Cmd_FMReferenced()
-{
-	int i;
-
-	GetScriptToken (false);
-	g_skelModel.references = atoi(token);
-
-	// Guess what?  Now, we now want a list of strings to look for here instead of a hard-coded list
-	for (i=0; i<REF_MAX_POINTS; i++)
-	{
-		if (ScriptTokenAvailable())
-		{	// There is yet another reference point waiting.
-			GetScriptToken(false);
-			strcpy(RefPointNameList[i], token);
-		}
-		else
-		{
-			break;
-		}
-	}
-
-	RefPointNum = i;
-
-	if (RefPointNum > 0)
-	{
-		printf("Searching for %d different reference points.\n", RefPointNum);
-	}
-	else
-	{
-		printf("Using built-in reference points.\n");
-	}
-
-}
-
-void LoadReferences(char *fileName, fmframe_t *fr)
-{
-	FILE *file1;
-    int dot = '.';
-	char *dotstart;
-	char	InputFileName[256];
-
-	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
-
-	if (!dotstart)
-	{
-		strcpy(InputFileName, fileName);
-		strcat(InputFileName, ".hrc");
-		if((file1 = fopen(InputFileName, "rb")) != NULL)
-		{
-			fclose(file1);
-
-			LoadHRCReferences(InputFileName, fr);
-
-			printf(" - assuming .HRC\n");
-			return;
-		}
-
-		Error("\n Could not open file '%s':\n"
-			"No HRC.\n", fileName);
-	}
-	else
-	{
-		if((file1 = fopen(fileName, "rb")) != NULL)
-		{
-			printf("\n");
-			fclose(file1);
-			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
-			{
-				LoadHRCReferences(fileName, fr);
-
-				return;
-			}
-		}
-
-		Error("Could not open file '%s':\n",fileName);
-	}
-}
-
-void GrabReferencedFrame(char *frame)
-{
-	char	file1[1024];
-	char	*framefile;
-	fmframe_t	*fr;
-
-	framefile = FindFrameFile (frame);
-
-	sprintf (file1, "%s/%s", cdarchive, framefile);
-	ExpandPathAndArchive (file1);
-
-	sprintf (file1, "%s/%s",cddir, framefile);
-
-	printf ("Grabbing Referenced %s\n", file1);
-
-	fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
-
-	LoadReferences(file1, fr);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qd_skeletons.h"
+#include "skeletons.h"
+#include "qd_fmodel.h"
+#include "angles.h"
+#include "token.h"
+#include "qdata.h"
+#include "reference.h"
+
+#include <assert.h>
+#include <math.h>
+#include <memory.h>
+
+
+// We're assuming no more than 16 reference points, with no more than 32 characters in the name
+char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
+int	 RefPointNum = 0;
+
+Skeletalfmheader_t g_skelModel;
+
+void ClearSkeletalModel()
+{
+	g_skelModel.type = SKEL_NULL;
+	g_skelModel.clustered = false;
+	g_skelModel.references = REF_NULL;
+}
+
+//==========================================================================
+//
+// LoadHRCClustered
+//
+//==========================================================================
+
+// Places the null terminated src string into the dest string less any trailing digits or underscores
+void StripTrailingDigits(char *src, char *dest)
+{
+#ifndef NDEBUG
+	int max = SKELETAL_NAME_MAX; // should be sufficient for inteded use on names from hrc files
+#endif
+	int i = 0;
+
+	while(src[i] != '\0')
+	{
+		++i;
+#ifndef NDEBUG
+		assert(i < max);
+#endif
+	}
+
+	while((src[--i] >= '0' && src[i] <= '9') || src[i] == '_')
+	{
+
+	}
+
+	memcpy(dest, src, ++i);
+
+	dest[i] = '\0';
+}
+
+static void LoadHRCClustered(char *fileName, int **clusterList, int *num_verts, int skelType)
+{
+	extern void HandleHRCModel(triangle_t **triList, int *triangleCount, 
+		mesh_node_t **nodesList, int *num_mesh_nodes, int ActiveNode, int Depth);
+
+	extern mesh_node_t	*pmnodes;
+
+	triangle_t *triList;
+//    	mesh_node_t *nodesList;
+	int num_mesh_nodes = 0, triangleCount = 0;
+
+#if 0
+	int i;
+	int j, numVerts;
+	char stripped[SKELETAL_NAME_MAX];
+
+	for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
+	{
+		num_verts[i] = 0;
+	}
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+
+	TK_Beyond(TK_CLUSTERS);
+
+	while(TK_Search(TK_CLUSTER_NAME) != TK_EOF)
+	{
+		TK_Require(TK_STRING);
+
+		StripTrailingDigits(tk_String, stripped);
+
+		for( i = 0; i < numJointsInSkeleton[skelType]; ++i)
+		{
+			if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)
+			{
+				i = -i + numJointsInSkeleton[skelType] - 1;
+
+				TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
+
+				numVerts = tk_IntNumber;
+
+				if(!num_verts[i+1])	// first set of verts for cluster
+				{
+					clusterList[i] = SafeMalloc(numVerts*sizeof(int), "LoadHRCClustered");
+					assert(clusterList[i]);
+				}
+				else				// any later sets of verts need to copy current
+				{
+					int *temp;
+
+					temp = SafeMalloc((num_verts[i+1]+numVerts)*sizeof(int), "LoadHRCClustered");
+					assert(temp);
+
+					memcpy(temp + numVerts, clusterList[i], num_verts[i+1]*sizeof(int));
+
+					free(clusterList[i]);
+
+					clusterList[i] = temp;
+				}
+
+				// currently this function is only called by LoadModelClusters.
+				// Apparently the matching free has disappeared, 
+				// should probably be free at the end of FMCmd_Base
+
+				TK_Beyond(TK_LBRACE);
+
+				for(j = 0; j < numVerts; ++j)
+				{
+					TK_Require(TK_INTNUMBER);
+					clusterList[i][j] = tk_IntNumber;
+					TK_Fetch();
+				}
+
+				num_verts[i+1] += numVerts;
+
+				break;
+			}
+		}
+	}
+
+	num_verts[0] = numJointsInSkeleton[skelType];
+#endif
+
+#if 1	// get the index number localized to the root
+//	for( i = 1; i < numJointsInSkeleton[skelType] + 1; ++i)
+//	{
+//		g_skelModel.num_verts[i] = 0;
+//	}
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+
+	// prime it
+	TK_Beyond(TK_MODEL);
+
+	triList = (triangle_t *) SafeMalloc(MAXTRIANGLES*sizeof(triangle_t), "Triangle list");
+	memset(triList,0,MAXTRIANGLES*sizeof(triangle_t));
+//	nodesList = SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+	pmnodes = (mesh_node_t *) SafeMalloc(MAX_FM_MESH_NODES * sizeof(mesh_node_t), "Mesh Node List");
+
+	memset(pmnodes, 0, MAX_FM_MESH_NODES * sizeof(mesh_node_t));
+
+	// this should eventually use a stripped down version of this
+	HandleHRCModel(&triList, &triangleCount, &pmnodes, &num_mesh_nodes, 0, 0);
+
+//	free(nodesList);
+	free(triList);
+
+	num_verts[0] = numJointsInSkeleton[skelType];
+#endif
+}
+
+void ReadHRCClusterList(mesh_node_t *meshNode, int baseIndex)
+{
+	int i, j, numVerts;
+	tokenType_t nextToken;
+	char stripped[SKELETAL_NAME_MAX];
+
+	meshNode->clustered = true;
+
+	nextToken = TK_Get(TK_CLUSTER_NAME);
+
+	while (nextToken == TK_CLUSTER_NAME)
+	{
+		TK_FetchRequire(TK_STRING);
+
+		StripTrailingDigits(tk_String, stripped);
+
+		for( i = 0; i < numJointsInSkeleton[g_skelModel.type]; ++i)
+		{
+			if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[g_skelModel.type]+i]) == 0)
+			{
+				i = -i + numJointsInSkeleton[g_skelModel.type] - 1;
+
+				TK_BeyondRequire(TK_NUM_CLUSTER_VERTICES, TK_INTNUMBER);
+
+				numVerts = tk_IntNumber;
+
+				if(!baseIndex)
+				{
+					meshNode->clusters[i] = (int *) SafeMalloc(numVerts*sizeof(int), "ReadHRCClusterList");
+					assert(meshNode->clusters[i]);
+				}
+				else
+				{
+					int *temp; 
+
+					temp = meshNode->clusters[i];
+					meshNode->clusters[i] = (int *) SafeMalloc((meshNode->num_verts[i+1]+numVerts)*sizeof(int), "ReadHRCClusterList");
+					assert(meshNode->clusters[i]);
+
+					memcpy(meshNode->clusters[i], temp, meshNode->num_verts[i+1]*sizeof(int));
+					free(temp);
+				}
+
+				// currently this function is only called by LoadModelClusters.
+				// Apparently the matching free has disappeared, 
+				// should probably be free at the end of FMCmd_Base
+
+				TK_Beyond(TK_LBRACE);
+
+				for(j = 0; j < numVerts; ++j)
+				{
+					TK_Require(TK_INTNUMBER);
+					meshNode->clusters[i][baseIndex+j] = tk_IntNumber+baseIndex;
+					TK_Fetch();
+				}
+
+				if(baseIndex)
+				{
+					meshNode->num_verts[i+1] += numVerts;
+				}
+				else
+				{
+					meshNode->num_verts[i+1] = numVerts;
+				}
+
+				break;
+			}
+		}
+
+		TK_BeyondRequire(TK_CLUSTER_STATE, TK_INTNUMBER);
+		nextToken = TK_Fetch();
+	}
+}
+
+static void LoadHRCGlobals(char *fileName)
+{
+	int i;
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+	TK_Beyond(TK_MODEL);
+
+	TK_Beyond(TK_SCALING);
+	for(i = 0; i < 3; i++)
+	{
+		TK_Require(TK_FLOATNUMBER);
+		g_skelModel.scaling[i] = tk_FloatNumber;
+		TK_Fetch();
+	}
+
+	TK_Beyond(TK_ROTATION);
+	for(i = 0; i < 3; i++)
+	{
+		TK_Require(TK_FLOATNUMBER);
+		g_skelModel.rotation[i] = tk_FloatNumber;
+		TK_Fetch();
+	}
+
+	TK_Beyond(TK_TRANSLATION);
+	for(i = 0; i < 3; i++)
+	{
+		TK_Require(TK_FLOATNUMBER);
+		g_skelModel.translation[i] = tk_FloatNumber;
+		TK_Fetch();
+	}
+}
+
+static void ParseVec3(vec3_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void ParseVec3d(vec3d_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void ParseRotation3(vec3_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void ParseRotation3d(vec3d_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void ParseTranslation3(vec3_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void ParseTranslation3d(vec3d_t in)
+{
+	TK_Require(TK_FLOATNUMBER);
+	in[1] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[2] = tk_FloatNumber;
+	TK_FetchRequire(TK_FLOATNUMBER);
+	in[0] = tk_FloatNumber;
+}
+
+static void LoadHRCJointList(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)
+{
+#define MAX_STACK 64
+	int i, j;
+	vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK], curScale[MAX_STACK];
+	int curCorrespondingJoint[MAX_STACK];
+	int currentStack = 0, stackSize;
+	double cx, sx, cy, sy, cz, sz;
+	double rx, ry, rz;
+	double x2, y2, z2;
+	char stripped[SKELETAL_NAME_MAX];
+	Placement_d_t *placement;
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+
+	TK_Beyond(TK_MODEL);
+
+	while(TK_Search(TK_NAME) != TK_EOF)
+	{
+		TK_Require(TK_STRING);
+
+		StripTrailingDigits(tk_String, stripped);
+
+		if(stricmp(stripped, skeletonRootNames[skeletonRNameOffsets[skelType]]) == 0)
+		{
+			break;
+		}
+	}
+
+	if(tk_Token == TK_EOF)
+	{
+		Error("Bone Chain Root: %s not found\n", skeletonRootNames[skeletonRNameOffsets[skelType]]);
+		return;
+	}
+
+	TK_Beyond(TK_SCALING);
+
+	ParseVec3d(curScale[currentStack]);
+
+	TK_Beyond(TK_ROTATION);
+
+	ParseRotation3d(curRotation[currentStack]);
+
+	TK_Beyond(TK_TRANSLATION);
+
+	ParseVec3d(curTranslation[currentStack]);
+
+	// account for global model translation
+	curTranslation[currentStack][1] += g_skelModel.translation[0];
+	curTranslation[currentStack][2] += g_skelModel.translation[1];
+	curTranslation[currentStack][0] += g_skelModel.translation[2];
+
+	curCorrespondingJoint[currentStack] = -1;
+
+	++currentStack;
+
+	for(i = 0; i < numJointsInSkeleton[skelType]; ++i)
+	{
+		while(1)
+		{
+			TK_Beyond(TK_MODEL);
+
+			TK_BeyondRequire(TK_NAME, TK_STRING);
+
+			StripTrailingDigits(tk_String, stripped);
+
+			if(stricmp(stripped, skeletonJointNames[skeletonNameOffsets[skelType]+i]) == 0)
+				break;
+
+			TK_Beyond(TK_SCALING);
+
+			ParseVec3d(curScale[currentStack]);
+
+			TK_Beyond(TK_ROTATION);
+
+			ParseRotation3d(curRotation[currentStack]);
+
+			TK_Beyond(TK_TRANSLATION);
+
+			ParseVec3d(curTranslation[currentStack]);
+
+			curCorrespondingJoint[currentStack] = -1;
+
+			++currentStack;
+		}
+
+		TK_Beyond(TK_SCALING);
+
+		ParseVec3d(curScale[currentStack]);
+
+		TK_Beyond(TK_ROTATION);
+
+		ParseRotation3d(curRotation[currentStack]);
+
+		jointList[i].rotation[1] = curRotation[currentStack][1];
+		jointList[i].rotation[2] = curRotation[currentStack][2];
+		jointList[i].rotation[0] = curRotation[currentStack][0];
+
+		TK_Beyond(TK_TRANSLATION);
+
+		ParseVec3d(curTranslation[currentStack]);
+
+//		jointList[i].placement.origin[1] = curTranslation[currentStack][1];
+//		jointList[i].placement.origin[2] = curTranslation[currentStack][2];
+//		jointList[i].placement.origin[0] = curTranslation[currentStack][0];
+
+		jointList[i].placement.origin[1] = 0.0;
+		jointList[i].placement.origin[2] = 0.0;
+		jointList[i].placement.origin[0] = 0.0;
+
+		jointList[i].placement.direction[1] = 20.0;
+		jointList[i].placement.direction[2] = 0.0;
+		jointList[i].placement.direction[0] = 0.0;
+
+		jointList[i].placement.up[1] = 0.0;
+		jointList[i].placement.up[2] = 20.0;
+		jointList[i].placement.up[0] = 0.0;
+
+		curCorrespondingJoint[currentStack] = i;
+
+		++currentStack;
+	}
+
+	stackSize = currentStack;
+
+#if 0
+	// rotate the direction and up vectors to correspond to the rotation
+	for(i = 0; i < numJointsInSkeleton[skelType]; ++i)
+	{
+		rx = jointList[i].rotation[0]*ANGLE_TO_RAD;
+		ry = jointList[i].rotation[1]*ANGLE_TO_RAD;
+		rz = jointList[i].rotation[2]*ANGLE_TO_RAD;
+
+		cx = cos(rx);
+		sx = sin(rx);
+
+		cy = cos(ry);
+		sy = sin(ry);
+
+		cz = cos(rz);
+		sz = sin(rz);
+
+		// y-axis rotation for direction
+		x2 = jointList[i].placement.direction[0]*cy+jointList[i].placement.direction[2]*sy;
+		z2 = -jointList[i].placement.direction[0]*sy+jointList[i].placement.direction[2]*cy;
+		jointList[i].placement.direction[0] = x2;
+		jointList[i].placement.direction[2] = z2;
+
+		// y-axis rotation for up
+		x2 = jointList[i].placement.up[0]*cy+jointList[i].placement.up[2]*sy;
+		z2 = -jointList[i].placement.up[0]*sy+jointList[i].placement.up[2]*cy;
+		jointList[i].placement.up[0] = x2;
+		jointList[i].placement.up[2] = z2;
+
+		// z-axis rotation for direction
+		x2 = jointList[i].placement.direction[0]*cz-jointList[i].placement.direction[1]*sz;
+		y2 = jointList[i].placement.direction[0]*sz+jointList[i].placement.direction[1]*cz;
+		jointList[i].placement.direction[0] = x2;
+		jointList[i].placement.direction[1] = y2;
+
+		// z-axis rotation for up
+		x2 = jointList[i].placement.up[0]*cz-jointList[i].placement.up[1]*sz;
+		y2 = jointList[i].placement.up[0]*sz+jointList[i].placement.up[1]*cz;
+		jointList[i].placement.up[0] = x2;
+		jointList[i].placement.up[1] = y2;
+
+		// x-axis rotation for direction vector
+		y2 = jointList[i].placement.direction[1]*cx-jointList[i].placement.direction[2]*sx;
+		z2 = jointList[i].placement.direction[1]*sx+jointList[i].placement.direction[2]*cx;
+		jointList[i].placement.direction[1] = y2;
+		jointList[i].placement.direction[2] = z2;
+
+		// x-axis rotation for up vector
+		y2 = jointList[i].placement.up[1]*cx-jointList[i].placement.up[2]*sx;
+		z2 = jointList[i].placement.up[1]*sx+jointList[i].placement.up[2]*cx;
+		jointList[i].placement.up[1] = y2;
+		jointList[i].placement.up[2] = z2;
+
+		// translate direction to a point in the model
+		jointList[i].placement.direction[0] += jointList[i].placement.origin[0];
+		jointList[i].placement.direction[1] += jointList[i].placement.origin[1];
+		jointList[i].placement.direction[2] += jointList[i].placement.origin[2];
+
+		// translate up to a point in the model
+		jointList[i].placement.up[0] += jointList[i].placement.origin[0];
+		jointList[i].placement.up[1] += jointList[i].placement.origin[1];
+		jointList[i].placement.up[2] += jointList[i].placement.origin[2];
+	}
+#endif
+
+	for(i = stackSize - 1; i >= 0; --i)
+	{
+		rx = curRotation[i][0]*ANGLE_TO_RAD;
+		ry = curRotation[i][1]*ANGLE_TO_RAD;
+		rz = curRotation[i][2]*ANGLE_TO_RAD;
+
+		cx = cos(rx);
+		sx = sin(rx);
+
+		cy = cos(ry);
+		sy = sin(ry);
+
+		cz = cos(rz);
+		sz = sin(rz);
+
+#if 1
+		for(j = i; j < stackSize; ++j)
+		{
+			if(curCorrespondingJoint[j] != -1)
+			{
+				placement = &jointList[curCorrespondingJoint[j]].placement;
+
+				// y-axis rotation for origin
+				x2 = placement->origin[0]*cy+placement->origin[2]*sy;
+				z2 = -placement->origin[0]*sy+placement->origin[2]*cy;
+				placement->origin[0] = x2;
+				placement->origin[2] = z2;
+
+				// y-axis rotation for direction
+				x2 = placement->direction[0]*cy+placement->direction[2]*sy;
+				z2 = -placement->direction[0]*sy+placement->direction[2]*cy;
+				placement->direction[0] = x2;
+				placement->direction[2] = z2;
+
+				// y-axis rotation for up
+				x2 = placement->up[0]*cy+placement->up[2]*sy;
+				z2 = -placement->up[0]*sy+placement->up[2]*cy;
+				placement->up[0] = x2;
+				placement->up[2] = z2;
+
+				// z-axis rotation for origin
+				x2 = placement->origin[0]*cz-placement->origin[1]*sz;
+				y2 = placement->origin[0]*sz+placement->origin[1]*cz;
+				placement->origin[0] = x2;
+				placement->origin[1] = y2;
+
+				// z-axis rotation for direction
+				x2 = placement->direction[0]*cz-placement->direction[1]*sz;
+				y2 = placement->direction[0]*sz+placement->direction[1]*cz;
+				placement->direction[0] = x2;
+				placement->direction[1] = y2;
+
+				// z-axis rotation for up
+				x2 = placement->up[0]*cz-placement->up[1]*sz;
+				y2 = placement->up[0]*sz+placement->up[1]*cz;
+				placement->up[0] = x2;
+				placement->up[1] = y2;
+
+				// x-axis rotation for origin
+				y2 = placement->origin[1]*cx-placement->origin[2]*sx;
+				z2 = placement->origin[1]*sx+placement->origin[2]*cx;
+				placement->origin[1] = y2;
+				placement->origin[2] = z2;
+
+				// x-axis rotation for direction vector
+				y2 = placement->direction[1]*cx-placement->direction[2]*sx;
+				z2 = placement->direction[1]*sx+placement->direction[2]*cx;
+				placement->direction[1] = y2;
+				placement->direction[2] = z2;
+
+				// x-axis rotation for up vector
+				y2 = placement->up[1]*cx-placement->up[2]*sx;
+				z2 = placement->up[1]*sx+placement->up[2]*cx;
+				placement->up[1] = y2;
+				placement->up[2] = z2;
+
+				// translate origin
+				placement->origin[0] += curTranslation[i][0];
+				placement->origin[1] += curTranslation[i][1];
+				placement->origin[2] += curTranslation[i][2];
+
+				// translate back to local coord
+				placement->direction[0] += curTranslation[i][0];
+				placement->direction[1] += curTranslation[i][1];
+				placement->direction[2] += curTranslation[i][2];
+
+				// translate back to local coord
+				placement->up[0] += curTranslation[i][0];
+				placement->up[1] += curTranslation[i][1];
+				placement->up[2] += curTranslation[i][2];
+			}
+		}
+#else
+		// This screwed up and needs to be sorted out!!!
+		// The stack info needs to be written too instead of the jointList for j > numJoints for Skeleton
+		for(j = i-1; j < stackSize-1; ++j)
+		{
+			// y-axis rotation for origin
+			x2 = jointList[j].placement.origin[0]*cy+jointList[j].placement.origin[2]*sy;
+			z2 = -jointList[j].placement.origin[0]*sy+jointList[j].placement.origin[2]*cy;
+			jointList[j].placement.origin[0] = x2;
+			jointList[j].placement.origin[2] = z2;
+
+			// y-axis rotation for direction
+			x2 = jointList[j].placement.direction[0]*cy+jointList[j].placement.direction[2]*sy;
+			z2 = -jointList[j].placement.direction[0]*sy+jointList[j].placement.direction[2]*cy;
+			jointList[j].placement.direction[0] = x2;
+			jointList[j].placement.direction[2] = z2;
+
+			// y-axis rotation for up
+			x2 = jointList[j].placement.up[0]*cy+jointList[j].placement.up[2]*sy;
+			z2 = -jointList[j].placement.up[0]*sy+jointList[j].placement.up[2]*cy;
+			jointList[j].placement.up[0] = x2;
+			jointList[j].placement.up[2] = z2;
+
+			// z-axis rotation for origin
+			x2 = jointList[j].placement.origin[0]*cz-jointList[j].placement.origin[1]*sz;
+			y2 = jointList[j].placement.origin[0]*sz+jointList[j].placement.origin[1]*cz;
+			jointList[j].placement.origin[0] = x2;
+			jointList[j].placement.origin[1] = y2;
+
+			// z-axis rotation for direction
+			x2 = jointList[j].placement.direction[0]*cz-jointList[j].placement.direction[1]*sz;
+			y2 = jointList[j].placement.direction[0]*sz+jointList[j].placement.direction[1]*cz;
+			jointList[j].placement.direction[0] = x2;
+			jointList[j].placement.direction[1] = y2;
+
+			// z-axis rotation for up
+			x2 = jointList[j].placement.up[0]*cz-jointList[j].placement.up[1]*sz;
+			y2 = jointList[j].placement.up[0]*sz+jointList[j].placement.up[1]*cz;
+			jointList[j].placement.up[0] = x2;
+			jointList[j].placement.up[1] = y2;
+
+			// x-axis rotation for origin
+			y2 = jointList[j].placement.origin[1]*cx-jointList[j].placement.origin[2]*sx;
+			z2 = jointList[j].placement.origin[1]*sx+jointList[j].placement.origin[2]*cx;
+			jointList[j].placement.origin[1] = y2;
+			jointList[j].placement.origin[2] = z2;
+
+			// x-axis rotation for direction vector
+			y2 = jointList[j].placement.direction[1]*cx-jointList[j].placement.direction[2]*sx;
+			z2 = jointList[j].placement.direction[1]*sx+jointList[j].placement.direction[2]*cx;
+			jointList[j].placement.direction[1] = y2;
+			jointList[j].placement.direction[2] = z2;
+
+			// x-axis rotation for up vector
+			y2 = jointList[j].placement.up[1]*cx-jointList[j].placement.up[2]*sx;
+			z2 = jointList[j].placement.up[1]*sx+jointList[j].placement.up[2]*cx;
+			jointList[j].placement.up[1] = y2;
+			jointList[j].placement.up[2] = z2;
+
+			if(curCorrespondingJoint[j+1] != -1)
+			{
+				// translate origin
+				jointList[j].placement.origin[0] += curTranslation[i-1][0];
+				jointList[j].placement.origin[1] += curTranslation[i-1][1];
+				jointList[j].placement.origin[2] += curTranslation[i-1][2];
+
+				// translate back to local coord
+				jointList[j].placement.direction[0] += curTranslation[i-1][0];
+				jointList[j].placement.direction[1] += curTranslation[i-1][1];
+				jointList[j].placement.direction[2] += curTranslation[i-1][2];
+
+				// translate back to local coord
+				jointList[j].placement.up[0] += curTranslation[i-1][0];
+				jointList[j].placement.up[1] += curTranslation[i-1][1];
+				jointList[j].placement.up[2] += curTranslation[i-1][2];
+			}
+		}
+#endif
+	}
+}
+
+void LoadModelTransform(char *fileName)
+{
+	FILE *file1;
+    int dot = '.';
+	char *dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+
+			LoadHRCGlobals(InputFileName);
+
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		Error("\n Could not open file '%s':\n"
+			"No HRC match.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+//			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRCGlobals(fileName);
+				return;
+			}
+		}
+
+		Error("Could not open file '%s':\n",fileName);
+	}
+}
+
+void LoadModelClusters(char *fileName, int **clusterList, int *num_verts, int skelType)
+{
+	FILE *file1;
+    int dot = '.';
+	char *dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+
+			LoadHRCClustered(InputFileName, clusterList, num_verts, skelType);
+
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		Error("\n Could not open file '%s':\n"
+			"No HRC match.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+//			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRCClustered(fileName, clusterList, num_verts, skelType);
+				return;
+			}
+		}
+
+		Error("Could not open file '%s':\n",fileName);
+	}
+}
+
+void LoadSkeleton(char *fileName, QD_SkeletalJoint_t *jointList, int skelType)
+{
+	FILE *file1;
+    int dot = '.';
+	char *dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+
+			LoadHRCJointList(InputFileName, jointList, skelType);
+
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		Error("\n Could not open file '%s':\n"
+			"No HRC.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+//			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRCJointList(fileName, jointList, skelType);
+
+				return;
+			}
+		}
+
+		Error("Could not open file '%s':\n",fileName);
+	}
+}
+
+/*
+===============
+GrabSkeletalFrame
+===============
+*/
+void GrabSkeletalFrame(char *frame)
+{
+	char	file1[1024];
+	char	*framefile;
+	fmframe_t	*fr;
+
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+	printf ("Grabbing Skeletal Frame %s\n", file1);
+
+	fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
+
+	LoadSkeleton(file1, fr->joints, g_skelModel.type);
+}
+
+/*
+===============
+GrabModelTransform
+===============
+*/
+void GrabModelTransform(char *frame)
+{
+	char	file1[1024];
+	char	*framefile;
+	fmframe_t	*fr;
+
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+//	printf ("grabbing %s\n", file1);
+
+	fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
+
+	LoadModelTransform(file1);
+}
+
+void Cmd_FMCluster()
+{
+	char file1[1024];
+
+	GetScriptToken (false);
+
+	printf ("---------------------\n");
+	sprintf (file1, "%s/%s", cdpartial, token);
+	printf ("%s\n", file1);
+
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s", cddir, token);
+
+	g_skelModel.clustered = -1;
+
+	LoadModelClusters(file1, (int **)&g_skelModel.clusters, (int *)&g_skelModel.num_verts, g_skelModel.type);
+
+	g_skelModel.new_num_verts[0] = g_skelModel.num_verts[0];
+
+	g_skelModel.clustered = true;
+}
+
+void Cmd_FMSkeleton()
+{
+	GetScriptToken (false);
+	g_skelModel.type = atoi(token);
+}
+
+void Cmd_FMSkeletalFrame()
+{
+	while (ScriptTokenAvailable())
+	{
+		GetScriptToken (false);
+		if (g_skipmodel)
+		{
+			GetScriptToken (false);
+			continue;
+		}
+		if (g_release || g_archive)
+		{
+			fmheader.num_frames = 1;	// don't skip the writeout
+			GetScriptToken (false);
+			continue;
+		}
+
+		H_printf("#define FRAME_%-16s\t%i\n", token, fmheader.num_frames);
+
+		GrabModelTransform (token);
+		GrabFrame (token);
+		GrabSkeletalFrame (token);
+
+		// need to add the up and dir points to the frame bounds here
+		// using AddPointToBounds (ptrivert[index_xyz].v, fr->mins, fr->maxs);
+		// then remove fudge in determining scale on frame write out
+	}
+}
+
+static void LoadHRCReferences(char *fileName, fmframe_t *fr)
+{
+#define MAX_STACK 64
+	int i, j, k;
+	vec3d_t curTranslation[MAX_STACK], curRotation[MAX_STACK];
+	int curCorrespondingJoint[MAX_STACK];
+	int currentStack, stackSize;
+	double cx, sx, cy, sy, cz, sz;
+	double rx, ry, rz;
+	double x2, y2, z2;
+	char stripped[SKELETAL_NAME_MAX];
+	Placement_d_t *placement;
+	int refnum;
+
+	TK_OpenSource(fileName);
+	TK_FetchRequire(TK_HRCH);
+	TK_FetchRequire(TK_COLON);
+	TK_FetchRequire(TK_SOFTIMAGE);
+
+	if (RefPointNum <= 0)
+	{	// There were no labels indicated in the QDT, so use the hard-coded stuff.
+		refnum = numReferences[g_skelModel.references];
+	}
+	else
+	{
+		refnum = RefPointNum;
+	}
+
+	for(k = 0; k < refnum; ++k)
+	{
+		currentStack = 0;
+
+		// Load the root to get translation and initial rotation
+//		TK_Beyond(TK_MODEL);
+
+		while(TK_Search(TK_NAME) != TK_EOF)
+		{
+			TK_Require(TK_STRING);
+
+			StripTrailingDigits(tk_String, stripped);
+
+			if (RefPointNum == 0)
+			{	// Hard coded refpoint labels
+				if(stricmp(stripped, 
+					referenceRootNames[referenceRootNameOffsets[g_skelModel.references]+k]) == 0)
+				{
+					break;
+				}
+			}
+			else
+			{	// labels indicated by the QDT
+				if(stricmp(stripped, RefPointNameList[k]) == 0)
+				{
+					break;
+				}
+			}
+		}
+
+		if(tk_Token == TK_EOF)
+		{
+			if (RefPointNum == 0)
+			{	// Hard coded refpoint labels
+				Error("Bone Chain Root: %s not found\n", referenceRootNames[referenceRootNameOffsets[g_skelModel.references]]);
+			}
+			else
+			{	// labels indicated by the QDT
+				Error("Bone Chain Root: %s not found\n", RefPointNameList[k]);
+			}
+			return;
+		}
+
+//		TK_Beyond(TK_SCALING);
+
+//		ParseVec3d(curScale[currentStack]);
+
+		TK_Beyond(TK_ROTATION);
+
+		ParseRotation3d(curRotation[currentStack]);
+
+		TK_Beyond(TK_TRANSLATION);
+
+		ParseVec3d(curTranslation[currentStack]);
+
+		// account for global model translation
+		curTranslation[currentStack][1] += g_skelModel.translation[0];
+		curTranslation[currentStack][2] += g_skelModel.translation[1];
+		curTranslation[currentStack][0] += g_skelModel.translation[2];
+
+		curCorrespondingJoint[currentStack] = -1;
+
+//		rjr - this one not needed, as there is also a stack increment 20 lines below???
+//		++currentStack;
+
+		// Load the joint to get orientation
+		TK_Beyond(TK_MODEL);
+
+//		TK_Beyond(TK_SCALING);
+
+//		ParseVec3d(curScale[currentStack]);
+
+		TK_Beyond(TK_ROTATION);
+
+		ParseRotation3d(curRotation[currentStack]);
+
+//		TK_Beyond(TK_TRANSLATION);
+
+//		ParseVec3d(curTranslation[currentStack]);
+
+		fr->references[k].placement.origin[1] = 0.0;
+		fr->references[k].placement.origin[2] = 0.0;
+		fr->references[k].placement.origin[0] = 0.0;
+
+		fr->references[k].placement.direction[1] = 20.0;
+		fr->references[k].placement.direction[2] = 0.0;
+		fr->references[k].placement.direction[0] = 0.0;
+
+		fr->references[k].placement.up[1] = 0.0;
+		fr->references[k].placement.up[2] = 20.0;
+		fr->references[k].placement.up[0] = 0.0;
+
+		curCorrespondingJoint[currentStack] = k;
+
+		++currentStack;
+
+		stackSize = currentStack;
+
+		for(i = stackSize - 1; i >= 0; --i)
+		{
+			rx = curRotation[i][0]*ANGLE_TO_RAD;
+			ry = curRotation[i][1]*ANGLE_TO_RAD;
+			rz = curRotation[i][2]*ANGLE_TO_RAD;
+
+			cx = cos(rx);
+			sx = sin(rx);
+
+			cy = cos(ry);
+			sy = sin(ry);
+
+			cz = cos(rz);
+			sz = sin(rz);
+
+			for(j = i; j < stackSize; ++j)
+			{
+				if(curCorrespondingJoint[j] != -1)
+				{
+					placement = &fr->references[curCorrespondingJoint[j]].placement;
+
+					// y-axis rotation for origin
+					x2 = placement->origin[0]*cy+placement->origin[2]*sy;
+					z2 = -placement->origin[0]*sy+placement->origin[2]*cy;
+					placement->origin[0] = x2;
+					placement->origin[2] = z2;
+
+					// y-axis rotation for direction
+					x2 = placement->direction[0]*cy+placement->direction[2]*sy;
+					z2 = -placement->direction[0]*sy+placement->direction[2]*cy;
+					placement->direction[0] = x2;
+					placement->direction[2] = z2;
+
+					// y-axis rotation for up
+					x2 = placement->up[0]*cy+placement->up[2]*sy;
+					z2 = -placement->up[0]*sy+placement->up[2]*cy;
+					placement->up[0] = x2;
+					placement->up[2] = z2;
+
+					// z-axis rotation for origin
+					x2 = placement->origin[0]*cz-placement->origin[1]*sz;
+					y2 = placement->origin[0]*sz+placement->origin[1]*cz;
+					placement->origin[0] = x2;
+					placement->origin[1] = y2;
+
+					// z-axis rotation for direction
+					x2 = placement->direction[0]*cz-placement->direction[1]*sz;
+					y2 = placement->direction[0]*sz+placement->direction[1]*cz;
+					placement->direction[0] = x2;
+					placement->direction[1] = y2;
+
+					// z-axis rotation for up
+					x2 = placement->up[0]*cz-placement->up[1]*sz;
+					y2 = placement->up[0]*sz+placement->up[1]*cz;
+					placement->up[0] = x2;
+					placement->up[1] = y2;
+
+					// x-axis rotation for origin
+					y2 = placement->origin[1]*cx-placement->origin[2]*sx;
+					z2 = placement->origin[1]*sx+placement->origin[2]*cx;
+					placement->origin[1] = y2;
+					placement->origin[2] = z2;
+
+					// x-axis rotation for direction vector
+					y2 = placement->direction[1]*cx-placement->direction[2]*sx;
+					z2 = placement->direction[1]*sx+placement->direction[2]*cx;
+					placement->direction[1] = y2;
+					placement->direction[2] = z2;
+
+					// x-axis rotation for up vector
+					y2 = placement->up[1]*cx-placement->up[2]*sx;
+					z2 = placement->up[1]*sx+placement->up[2]*cx;
+					placement->up[1] = y2;
+					placement->up[2] = z2;
+
+					// translate origin
+					placement->origin[0] += curTranslation[i][0];
+					placement->origin[1] += curTranslation[i][1];
+					placement->origin[2] += curTranslation[i][2];
+
+					// translate back to local coord
+					placement->direction[0] += curTranslation[i][0];
+					placement->direction[1] += curTranslation[i][1];
+					placement->direction[2] += curTranslation[i][2];
+
+					// translate back to local coord
+					placement->up[0] += curTranslation[i][0];
+					placement->up[1] += curTranslation[i][1];
+					placement->up[2] += curTranslation[i][2];
+
+				}
+			}
+		}
+		printf("%f, %f, %f\n", placement->origin[0], placement->origin[1], placement->origin[2]);
+	}
+	printf("\n");
+}
+
+void Cmd_FMReferenced()
+{
+	int i;
+
+	GetScriptToken (false);
+	g_skelModel.references = atoi(token);
+
+	// Guess what?  Now, we now want a list of strings to look for here instead of a hard-coded list
+	for (i=0; i<REF_MAX_POINTS; i++)
+	{
+		if (ScriptTokenAvailable())
+		{	// There is yet another reference point waiting.
+			GetScriptToken(false);
+			strcpy(RefPointNameList[i], token);
+		}
+		else
+		{
+			break;
+		}
+	}
+
+	RefPointNum = i;
+
+	if (RefPointNum > 0)
+	{
+		printf("Searching for %d different reference points.\n", RefPointNum);
+	}
+	else
+	{
+		printf("Using built-in reference points.\n");
+	}
+
+}
+
+void LoadReferences(char *fileName, fmframe_t *fr)
+{
+	FILE *file1;
+    int dot = '.';
+	char *dotstart;
+	char	InputFileName[256];
+
+	dotstart = strrchr(fileName,dot); // Does it already have an extension on the file name?
+
+	if (!dotstart)
+	{
+		strcpy(InputFileName, fileName);
+		strcat(InputFileName, ".hrc");
+		if((file1 = fopen(InputFileName, "rb")) != NULL)
+		{
+			fclose(file1);
+
+			LoadHRCReferences(InputFileName, fr);
+
+			printf(" - assuming .HRC\n");
+			return;
+		}
+
+		Error("\n Could not open file '%s':\n"
+			"No HRC.\n", fileName);
+	}
+	else
+	{
+		if((file1 = fopen(fileName, "rb")) != NULL)
+		{
+			printf("\n");
+			fclose(file1);
+			if (strcmp(dotstart,".hrc") == 0 || strcmp(dotstart,".HRC") == 0)
+			{
+				LoadHRCReferences(fileName, fr);
+
+				return;
+			}
+		}
+
+		Error("Could not open file '%s':\n",fileName);
+	}
+}
+
+void GrabReferencedFrame(char *frame)
+{
+	char	file1[1024];
+	char	*framefile;
+	fmframe_t	*fr;
+
+	framefile = FindFrameFile (frame);
+
+	sprintf (file1, "%s/%s", cdarchive, framefile);
+	ExpandPathAndArchive (file1);
+
+	sprintf (file1, "%s/%s",cddir, framefile);
+
+	printf ("Grabbing Referenced %s\n", file1);
+
+	fr = &g_frames[fmheader.num_frames - 1]; // last frame read in
+
+	LoadReferences(file1, fr);
+}
+
diff --git a/tools/quake2/qdata_heretic2/qd_skeletons.h b/tools/quake2/qdata_heretic2/qd_skeletons.h
index 867e9602..59261432 100644
--- a/tools/quake2/qdata_heretic2/qd_skeletons.h
+++ b/tools/quake2/qdata_heretic2/qd_skeletons.h
@@ -1,84 +1,84 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef QD_SKELETONS_H
-#define QD_SKELETONS_H
-
-#include "placement.h"
-
-
-typedef struct Placement_d_s
-{
-	vec3d_t origin;
-	vec3d_t direction;
-	vec3d_t up;
-} Placement_d_t;
-
-typedef struct QD_SkeletalJoint_s
-{
-	Placement_d_t placement;
-	vec3d_t		rotation;
-} QD_SkeletalJoint_t;
-
-#define NUM_CLUSTERS 8
-
-typedef struct IntListNode_s
-{
-	int data;
-	struct IntListNode_s *next;
-} IntListNode_t;  // gaak
-
-typedef struct Skeletalfmheader_s
-{
-	int type;
-	int clustered;
-	int references;
-
-	int *clusters[NUM_CLUSTERS];
-	IntListNode_t *vertLists[NUM_CLUSTERS];
-	int num_verts[NUM_CLUSTERS + 1];
-	int new_num_verts[NUM_CLUSTERS + 1];
-
-	float scaling[3];
-	float rotation[3];
-	float translation[3];
-} Skeletalfmheader_t;
-
-#define SKELETAL_NAME_MAX 32
-
-extern Skeletalfmheader_t g_skelModel;
-
-void ClearSkeletalModel();
-void GrabModelTransform(char *frame);
-void GrabSkeletalFrame(char *frame);
-void GrabReferencedFrame(char *frame);
-
-// Reference Stuff
-#define NUM_REFERENCES 8
-
-#define REF_MAX_POINTS	16
-#define REF_MAX_STRLEN	32
-
-// We're assuming no more than 16 reference points, with no more than 32 characters in the name
-extern char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
-extern int	RefPointNum;
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef QD_SKELETONS_H
+#define QD_SKELETONS_H
+
+#include "placement.h"
+
+
+typedef struct Placement_d_s
+{
+	vec3d_t origin;
+	vec3d_t direction;
+	vec3d_t up;
+} Placement_d_t;
+
+typedef struct QD_SkeletalJoint_s
+{
+	Placement_d_t placement;
+	vec3d_t		rotation;
+} QD_SkeletalJoint_t;
+
+#define NUM_CLUSTERS 8
+
+typedef struct IntListNode_s
+{
+	int data;
+	struct IntListNode_s *next;
+} IntListNode_t;  // gaak
+
+typedef struct Skeletalfmheader_s
+{
+	int type;
+	int clustered;
+	int references;
+
+	int *clusters[NUM_CLUSTERS];
+	IntListNode_t *vertLists[NUM_CLUSTERS];
+	int num_verts[NUM_CLUSTERS + 1];
+	int new_num_verts[NUM_CLUSTERS + 1];
+
+	float scaling[3];
+	float rotation[3];
+	float translation[3];
+} Skeletalfmheader_t;
+
+#define SKELETAL_NAME_MAX 32
+
+extern Skeletalfmheader_t g_skelModel;
+
+void ClearSkeletalModel();
+void GrabModelTransform(char *frame);
+void GrabSkeletalFrame(char *frame);
+void GrabReferencedFrame(char *frame);
+
+// Reference Stuff
+#define NUM_REFERENCES 8
+
+#define REF_MAX_POINTS	16
+#define REF_MAX_STRLEN	32
+
+// We're assuming no more than 16 reference points, with no more than 32 characters in the name
+extern char RefPointNameList[REF_MAX_POINTS][REF_MAX_STRLEN];
+extern int	RefPointNum;
+
+#endif
diff --git a/tools/quake2/qdata_heretic2/qdata.c b/tools/quake2/qdata_heretic2/qdata.c
index d8488f69..64edf0a3 100644
--- a/tools/quake2/qdata_heretic2/qdata.c
+++ b/tools/quake2/qdata_heretic2/qdata.c
@@ -1,730 +1,730 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qdata.h"
-
-void TK_Init();
-
-qboolean	g_compress_pak;
-qboolean	g_release;			// don't grab, copy output data to new tree
-qboolean	g_pak;				// if true, copy to pak instead of release
-char		g_releasedir[1024];	// c:\quake2\baseq2, etc
-qboolean	g_archive;			// don't grab, copy source data to new tree
-qboolean	do3ds;
-char		g_only[256];		// if set, only grab this cd
-qboolean	g_skipmodel;		// set true when a cd is not g_only
-int			g_forcemodel = MODEL_AUTO;
-qboolean	g_verbose = false;
-qboolean	g_allow_newskin = true;
-qboolean	g_ignoreTriUV = false;
-qboolean	g_publishOutput = false;
-
-char		*ext_3ds = "3ds";
-char		*ext_tri= "tri";
-char		*trifileext;
-
-char		g_materialFile[256] = "none";	// default for Heretic2
-char		*g_outputDir;
-extern char *g_publishDir;
-
-extern qboolean	g_nomkdir;
-
-/*
-=======================================================
-
-  PAK FILES
-
-=======================================================
-*/
-
-typedef struct
-{
-	char	name[56];
-	int		filepos, filelen;
-} packfile_t;
-
-typedef struct
-{
-	char	id[4];
-	int		dirofs;
-	int		dirlen;
-} packheader_t;
-
-packfile_t		pfiles[16384];
-FILE			*pakfile;
-packfile_t		*pf;
-packheader_t	pakheader;
-
-
-
-/*
-==============
-BeginPak
-==============
-*/
-void BeginPak (char *outname)
-{
-	if (!g_pak)
-		return;
-
-	pakfile = SafeOpenWrite (outname);
-
-	// leave space for header
-	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
-	
-	pf = pfiles;
-}
-
-
-/*
-==============
-ReleaseFile
-
-Filename should be gamedir reletive.
-Either copies the file to the release dir, or adds it to
-the pak file.
-==============
-*/
-void ReleaseFile (char *filename)
-{
-	int		len;
-	byte	*buf;
-	char	source[1024];
-	char	dest[1024];
-
-	if (!g_release)
-		return;
-
-	sprintf (source, "%s%s", gamedir, filename);
-
-	if (!g_pak)
-	{	// copy it
-		sprintf (dest, "%s/%s", g_releasedir, filename);
-		printf ("copying to %s\n", dest);
-		QCopyFile (source, dest);
-		return;
-	}
-
-	// pak it
-	printf ("paking %s\n", filename);
-	if (strlen(filename) >= sizeof(pf->name))
-		Error ("Filename too long for pak: %s", filename);
-
-	len = LoadFile (source, (void **)&buf);
-
-	// segment moved to old.c
-
-	strcpy (pf->name, filename);
-	pf->filepos = LittleLong(ftell(pakfile));
-	pf->filelen = LittleLong(len);
-	pf++;
-
-	SafeWrite (pakfile, buf, len);
-
-	free (buf);
-}
-
-
-/*
-==============
-FinishPak
-==============
-*/
-void FinishPak (void)
-{
-	int		dirlen;
-	int		d;
-	int		i;
-
-	if (!g_pak)
-		return;
-
-	pakheader.id[0] = 'P';
-	pakheader.id[1] = 'A';
-	pakheader.id[2] = 'C';
-	pakheader.id[3] = 'K';
-	dirlen = (byte *)pf - (byte *)pfiles;
-	pakheader.dirofs = LittleLong(ftell(pakfile));
-	pakheader.dirlen = LittleLong(dirlen);
-	
-	SafeWrite (pakfile, pfiles, dirlen);
-
-	i = ftell (pakfile);
-	 
-	fseek (pakfile, 0, SEEK_SET);
-	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
-	fclose (pakfile);	
-	
-	d = pf - pfiles;
-	printf ("%i files packed in %i bytes\n",d, i);
-}
-
-
-/*
-===============
-Cmd_File
-
-This is only used to cause a file to be copied during a release
-build (default.cfg, maps, etc)
-===============
-*/
-void Cmd_File (void)
-{
-	GetScriptToken (false);
-	ReleaseFile (token);
-}
-
-/*
-===============
-PackDirectory_r
-
-===============
-*/
-#ifdef _WIN32
-#include "io.h"
-void PackDirectory_r (char *dir)
-{
-	struct _finddata_t fileinfo;
-	int		handle;
-	char	dirstring[1024];
-	char	filename[1024];
-
-	sprintf (dirstring, "%s%s/*.*", gamedir, dir);
-
-	handle = _findfirst (dirstring, &fileinfo);
-	if (handle == -1)
-		return;
-
-	do
-	{
-		sprintf (filename, "%s/%s", dir, fileinfo.name);
-		if (fileinfo.attrib & _A_SUBDIR)
-		{	// directory
-			if (fileinfo.name[0] != '.')	// don't pak . and ..
-				PackDirectory_r (filename);
-			continue;
-		}
-		// copy or pack the file
-		ReleaseFile (filename);		
-	} while (_findnext( handle, &fileinfo ) != -1);
-
-	_findclose (handle);
-}
-#else
-
-#include <sys/types.h>
-#ifdef NeXT
-#include <sys/dir.h>
-#else
-#include <dirent.h>
-#endif
-
-void PackDirectory_r (char *dir)
-{
-#ifdef NeXT
-	struct direct **namelist, *ent;
-#else
-	struct dirent **namelist, *ent;
-#endif
-	int		count;
-	struct stat st;
-	int			i;
-	int			len;
-	char		fullname[1024];
-	char		dirstring[1024];
-	char		*name;
-	
-	sprintf (dirstring, "%s%s", gamedir, dir);
-	count = scandir(dirstring, &namelist, NULL, NULL);
-	
-	for (i=0 ; i<count ; i++)
-	{
-		ent = namelist[i];	
-		name = ent->d_name;
-
-		if (name[0] == '.')
-			continue;
-	
-		sprintf (fullname, "%s/%s", dir, name);
-		sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
-		
-		if (stat (dirstring, &st) == -1)
-			Error ("fstating %s", pf->name);
-		if (st.st_mode & S_IFDIR)
-		{	// directory
-			PackDirectory_r (fullname);
-			continue;
-		}
-
-		// copy or pack the file
-		ReleaseFile (fullname);		
-	}
-}
-#endif
-
-
-/*
-===============
-Cmd_Dir
-
-This is only used to cause a directory to be copied during a
-release build (sounds, etc)
-===============
-*/
-void Cmd_Dir (void)
-{
-	GetScriptToken (false);
-	PackDirectory_r (token);	
-}
-
-//========================================================================
-
-#define	MAX_RTEX	16384
-int		numrtex;
-char	rtex[MAX_RTEX][64];
-
-void ReleaseTexture (char *name)
-{
-	int		i;
-	char	path[1024];
-
-	for (i=0 ; i<numrtex ; i++)
-		if (!Q_strcasecmp(name, rtex[i]))
-			return;
-
-	if (numrtex == MAX_RTEX)
-		Error ("numrtex == MAX_RTEX");
-
-	strcpy (rtex[i], name);
-	numrtex++;
-
-	sprintf (path, "textures/%s.wal", name);
-	ReleaseFile (path);
-}
-
-/*
-===============
-Cmd_Maps
-
-Only relevent for release and pak files.
-Releases the .bsp files for the maps, and scans all of the files to
-build a list of all textures used, which are then released.
-===============
-*/
-void Cmd_Maps (void)
-{
-	char	map[1024];
-	int		i;
-
-	while (ScriptTokenAvailable ())
-	{
-		GetScriptToken (false);
-		sprintf (map, "maps/%s.bsp", token);
-		ReleaseFile (map);
-
-		if (!g_release)
-			continue;
-
-		// get all the texture references
-		sprintf (map, "%smaps/%s.bsp", gamedir, token);
-		LoadBSPFileTexinfo (map);
-		for (i=0 ; i<numtexinfo ; i++)
-			ReleaseTexture (texinfo[i].texture);
-	}
-}
-
-
-//==============================================================
-
-/*
-===============
-ParseScript
-===============
-*/
-void ParseScript (void)
-{
-	while (1)
-	{
-		do
-		{	// look for a line starting with a $ command
-			GetScriptToken (true);
-			if (endofscript)
-				return;
-			if (token[0] == '$')
-				break;				
-			while (ScriptTokenAvailable())
-				GetScriptToken (false);
-		} while (1);
-		
-		//
-		// model commands
-		//
-		if (!strcmp (token, "$modelname"))
-			MODELCMD_Modelname (MODEL_MD2);
-		else if (!strcmp (token, "$cd"))
-			MODELCMD_Cd (MODEL_MD2);
-		else if (!strcmp (token, "$origin"))
-			MODELCMD_Origin (MODEL_MD2);
-		else if (!strcmp (token, "$cluster"))
-			MODELCMD_Cluster (MODEL_MD2);
-		else if (!strcmp (token, "$base"))
-			MODELCMD_Base (MODEL_MD2);
-		else if (!strcmp (token, "$scale"))
-			MODELCMD_ScaleUp (MODEL_MD2);
-		else if (!strcmp (token, "$frame"))
-			MODELCMD_Frame (MODEL_MD2);
-		else if (!strcmp (token, "$skin"))
-			MODELCMD_Skin (MODEL_MD2);
-		else if (!strcmp (token, "$skinsize"))
-			MODELCMD_Skinsize (MODEL_MD2);
-		//
-		// flexible model commands
-		//
-		else if (!strcmp (token, "$fm_modelname"))
-			MODELCMD_Modelname (MODEL_FM);
-		else if (!strcmp (token, "$fm_base"))
-			MODELCMD_Base (MODEL_FM);
-		else if (!strcmp (token, "$fm_basest"))
-			MODELCMD_BaseST (MODEL_FM);
-		else if (!strcmp (token, "$fm_cd"))
-			MODELCMD_Cd (MODEL_FM);
-		else if (!strcmp (token, "$fm_origin"))
-			MODELCMD_Origin (MODEL_FM);
-		else if (!strcmp (token, "$fm_cluster"))
-			MODELCMD_Cluster (MODEL_FM);
-		else if (!strcmp (token, "$fm_skeleton"))
-			MODELCMD_Skeleton (MODEL_FM);
-		else if (!strcmp (token, "$fm_scale"))
-			MODELCMD_ScaleUp (MODEL_FM);
-		else if (!strcmp (token, "$fm_frame"))
-			MODELCMD_Frame (MODEL_FM);
-		else if (!strcmp (token, "$fm_skeletal_frame"))	// left in for compadibility with qdt already using fm_skeletal_frame
-			MODELCMD_Frame (MODEL_FM);
-		else if (!strcmp (token, "$fm_skin"))
-			MODELCMD_Skin (MODEL_FM);
-		else if (!strcmp (token, "$fm_skinsize"))
-			MODELCMD_Skinsize (MODEL_FM);
-		else if (!strcmp (token, "$fm_begin_group"))
-			MODELCMD_BeginGroup(MODEL_FM);
-		else if (!strcmp (token, "$fm_end_group"))
-			MODELCMD_EndGroup(MODEL_FM);
-		else if (!strcmp (token, "$fm_referenced"))
-			MODELCMD_Referenced(MODEL_FM);
-		else if (!strcmp (token, "$fm_node_order"))
-			MODELCMD_NodeOrder(MODEL_FM);
-		
-		//
-		// sprite commands
-		//
-		else if (!strcmp (token, "$spritename"))
-			Cmd_SpriteName ();
-		else if (!strcmp (token, "$sprdir"))
-			Cmd_Sprdir ();
-		else if (!strcmp (token, "$load"))
-			Cmd_Load ();
-		else if (!strcmp (token, "$spriteframe"))
-			Cmd_SpriteFrame ();
-		//
-		// image commands
-		//
-		else if (!strcmpi (token, "$grab"))
-			Cmd_Grab ();
-		else if (!strcmpi (token, "$raw"))
-			Cmd_Raw ();
-		else if (!strcmpi (token, "$colormap"))
-			Cmd_Colormap ();
-		else if (!strcmpi (token, "$mippal"))
-			Cmd_Mippal ();
-		else if (!strcmpi (token, "$mipdir"))
-			Cmd_Mipdir ();
-		else if (!strcmpi (token, "$mip"))
-			Cmd_Mip ();
-		else if (!strcmp (token, "$environment"))
-			Cmd_Environment ();
-		//
-		// pics
-		//
-		else if (!strcmp (token, "$picdir"))
-			Cmd_Picdir ();
-		else if (!strcmp (token, "$pic"))
-			Cmd_Pic ();
-		//
-		// book
-		//
-		else if (!strcmp (token, "$bookdir"))
-			Cmd_Bookdir ();
-		else if (!strcmp (token, "$book"))
-			Cmd_Book ();
-		//
-		// tmix
-		//
-		else if (!strcmp (token, "$texturemix"))
-			Cmd_TextureMix ();
-		//
-		// video
-		//
-		else if (!strcmp (token, "$video"))
-			Cmd_Video ();
-		//
-		// misc
-		//
-		else if (!strcmp (token, "$file"))
-			Cmd_File ();
-		else if (!strcmp (token, "$dir"))
-			Cmd_Dir ();
-		else if (!strcmp (token, "$maps"))
-			Cmd_Maps ();
-		else if (!strcmp (token, "$alphalight"))
-			Cmd_Alphalight ();
-		else if (!strcmp (token, "$inverse16table" ))
-			Cmd_Inverse16Table();
-		else
-			Error ("bad command %s\n", token);
-	}
-}
-
-//=======================================================
-
-/*
-==============
-main
-==============
-*/
-int main (int argc, char **argv)
-{
-	int			i;
-	char		path[1024];
-	char		*basedir;
-	double		starttime, endtime;
-
-	printf ("Qdata Plus : "__TIME__" "__DATE__"\n");
-
-	starttime = I_FloatTime();
-	basedir = NULL;
-
-	TK_Init();
-	ExpandWildcards (&argc, &argv);
-
-	for (i=1 ; i<argc ; i++)
-	{
-		if (!strcmp(argv[i], "-archive"))
-		{
-			// -archive f:/quake2/release/dump_11_30
-			archive = true;
-			strcpy (archivedir, argv[i+1]);
-			printf ("Archiving source to: %s\n", archivedir);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-release"))
-		{
-			g_release = true;
-			strcpy (g_releasedir, argv[i+1]);
-			printf ("Copy output to: %s\n", g_releasedir);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-base"))
-		{
-			i++;
-			basedir = argv[i];
-		}
-		else if (!strcmp(argv[i], "-compress"))
-		{
-			g_compress_pak = true;
-			printf ("Compressing pakfile\n");
-		}
-		else if (!strcmp(argv[i], "-pak"))
-		{
-			g_release = true;
-			g_pak = true;
-			printf ("Building pakfile: %s\n", argv[i+1]);
-			BeginPak (argv[i+1]);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-only"))
-		{
-			strcpy (g_only, argv[i+1]);
-			printf ("Only grabbing %s\n", g_only);
-			i++;
-		}
-		else if (!strcmpi(argv[i], "-keypress"))
-		{
-			g_dokeypress = true;
-		}
-		else if (!strcmp(argv[i], "-3ds"))
-		{
-			do3ds = true;
-			printf ("loading .3ds files\n");
-		}
-		else if (!strcmp(argv[i], "-materialfile"))
-		{
-			strcpy(g_materialFile, argv[i+1]);
-			printf("Setting material file to %s\n", g_materialFile);
-			i++;
-		}
-/*		else if (!strcmpi(argv[i], "-newgen"))
-		{
-			if (i < argc-4)
-			{
-				printf("run new triangle grouping routine here\n");
-				NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
-			}
-			else
-			{
-				printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");
-			}
-			return 0;
-		}
-*/		else if (!strcmpi(argv[i], "-genskin"))
-		{
-			i++;
-			if (i < argc-3)
-			{
-				GenSkin(argv[i],argv[i+1],atol(argv[i+2]),atol(argv[i+3]));
-			}
-			else
-			{
-				printf("qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n");
-			}
-			return 0;
-			
-		}
-		else if (!strcmpi(argv[i], "-noopts"))
-		{
-			g_no_opimizations = true;
-			printf("not performing optimizations\n");
-		}
-		else if (!strcmpi(argv[i], "-md2"))
-		{
-			g_forcemodel = MODEL_MD2;
-		}
-		else if (!strcmpi(argv[i], "-fm"))
-		{
-			g_forcemodel = MODEL_FM;
-		}
-		else if (!strcmpi(argv[i], "-verbose"))
-		{
-			g_verbose = true;
-		}
-		else if (!strcmpi(argv[i], "-oldskin"))
-		{
-			g_allow_newskin = false;
-		}
-		else if (!strcmpi(argv[i], "-ignoreUV"))
-		{
-			g_ignoreTriUV = true;
-		}
-		else if (!strcmpi(argv[i], "-publish"))
-		{
-			g_publishOutput = true;
-		}
-		else if (!strcmpi(argv[i], "-nomkdir"))
-		{
-			g_nomkdir = true;
-		}
-		else if (argv[i][0] == '-')
-			Error ("Unknown option \"%s\"", argv[i]);
-		else
-			break;
-	}
-
-	if (i >= argc)
-	{
-		Error ("usage: qdata [-archive <directory>]\n"
-			"             [-release <directory>]\n"
-			"             [-base <directory>]\n"
-			"             [-compress]\n"
-			"             [-pak <file>]\n"
-			"             [-only <model>]\n"
-			"             [-keypress]\n"
-			"             [-3ds]\n"
-			"             [-materialfile <file>]\n"
-			"             [-noopts]\n"
-			"             [-md2]\n"
-			"             [-fm]\n"
-			"             [-verbose]\n"
-			"             [-ignoreUV]\n"
-			"             [-oldskin]\n"
-			"             [-publish]\n"
-			"             [-nomkdir]\n"
-			"             file.qdt\n"
-			"or\n"
-			"       qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>");
-	}
-
-	if (do3ds)
-		trifileext = ext_3ds;
-	else
-		trifileext = ext_tri;
-
-	for ( ; i<argc ; i++)
-	{
-		printf ("--------------- %s ---------------\n", argv[i]);
-		// load the script
-		strcpy (path, argv[i]);
-		DefaultExtension (path, ".qdt");
-		DefaultExtension(g_materialFile, ".mat");
-		SetQdirFromPath (path);
-
-		printf("workingdir='%s'\n", gamedir);
-		if (basedir)
-		{
-			qdir[0] = 0;
-			g_outputDir = basedir;
-		}
-
-		printf("outputdir='%s'\n", g_outputDir);
-
-		QFile_ReadMaterialTypes(g_materialFile);
-		LoadScriptFile (ExpandArg(path));
-		
-		//
-		// parse it
-		//
-		ParseScript ();
-
-		// write out the last model
-		FinishModel ();
-		FMFinishModel ();
-		FinishSprite ();
-	}
-
-	if (total_textures)
-	{
-		printf("\n");
-		printf("Total textures processed: %d\n",total_textures);
-		printf("Average size: %d x %d\n",total_x / total_textures, total_y / total_textures);
-	}
-
-	if (g_pak)
-		FinishPak ();
-
-	endtime = I_FloatTime();
-	printf("Time elapsed:  %f\n", endtime-starttime);
-	
-	if (g_dokeypress)
-	{
-		printf("Success! ... Hit a key: ");
-		getchar();
-	}
-
-	return 0;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qdata.h"
+
+void TK_Init();
+
+qboolean	g_compress_pak;
+qboolean	g_release;			// don't grab, copy output data to new tree
+qboolean	g_pak;				// if true, copy to pak instead of release
+char		g_releasedir[1024];	// c:\quake2\baseq2, etc
+qboolean	g_archive;			// don't grab, copy source data to new tree
+qboolean	do3ds;
+char		g_only[256];		// if set, only grab this cd
+qboolean	g_skipmodel;		// set true when a cd is not g_only
+int			g_forcemodel = MODEL_AUTO;
+qboolean	g_verbose = false;
+qboolean	g_allow_newskin = true;
+qboolean	g_ignoreTriUV = false;
+qboolean	g_publishOutput = false;
+
+char		*ext_3ds = "3ds";
+char		*ext_tri= "tri";
+char		*trifileext;
+
+char		g_materialFile[256] = "none";	// default for Heretic2
+char		*g_outputDir;
+extern char *g_publishDir;
+
+extern qboolean	g_nomkdir;
+
+/*
+=======================================================
+
+  PAK FILES
+
+=======================================================
+*/
+
+typedef struct
+{
+	char	name[56];
+	int		filepos, filelen;
+} packfile_t;
+
+typedef struct
+{
+	char	id[4];
+	int		dirofs;
+	int		dirlen;
+} packheader_t;
+
+packfile_t		pfiles[16384];
+FILE			*pakfile;
+packfile_t		*pf;
+packheader_t	pakheader;
+
+
+
+/*
+==============
+BeginPak
+==============
+*/
+void BeginPak (char *outname)
+{
+	if (!g_pak)
+		return;
+
+	pakfile = SafeOpenWrite (outname);
+
+	// leave space for header
+	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
+	
+	pf = pfiles;
+}
+
+
+/*
+==============
+ReleaseFile
+
+Filename should be gamedir reletive.
+Either copies the file to the release dir, or adds it to
+the pak file.
+==============
+*/
+void ReleaseFile (char *filename)
+{
+	int		len;
+	byte	*buf;
+	char	source[1024];
+	char	dest[1024];
+
+	if (!g_release)
+		return;
+
+	sprintf (source, "%s%s", gamedir, filename);
+
+	if (!g_pak)
+	{	// copy it
+		sprintf (dest, "%s/%s", g_releasedir, filename);
+		printf ("copying to %s\n", dest);
+		QCopyFile (source, dest);
+		return;
+	}
+
+	// pak it
+	printf ("paking %s\n", filename);
+	if (strlen(filename) >= sizeof(pf->name))
+		Error ("Filename too long for pak: %s", filename);
+
+	len = LoadFile (source, (void **)&buf);
+
+	// segment moved to old.c
+
+	strcpy (pf->name, filename);
+	pf->filepos = LittleLong(ftell(pakfile));
+	pf->filelen = LittleLong(len);
+	pf++;
+
+	SafeWrite (pakfile, buf, len);
+
+	free (buf);
+}
+
+
+/*
+==============
+FinishPak
+==============
+*/
+void FinishPak (void)
+{
+	int		dirlen;
+	int		d;
+	int		i;
+
+	if (!g_pak)
+		return;
+
+	pakheader.id[0] = 'P';
+	pakheader.id[1] = 'A';
+	pakheader.id[2] = 'C';
+	pakheader.id[3] = 'K';
+	dirlen = (byte *)pf - (byte *)pfiles;
+	pakheader.dirofs = LittleLong(ftell(pakfile));
+	pakheader.dirlen = LittleLong(dirlen);
+	
+	SafeWrite (pakfile, pfiles, dirlen);
+
+	i = ftell (pakfile);
+	 
+	fseek (pakfile, 0, SEEK_SET);
+	SafeWrite (pakfile, &pakheader, sizeof(pakheader));
+	fclose (pakfile);	
+	
+	d = pf - pfiles;
+	printf ("%i files packed in %i bytes\n",d, i);
+}
+
+
+/*
+===============
+Cmd_File
+
+This is only used to cause a file to be copied during a release
+build (default.cfg, maps, etc)
+===============
+*/
+void Cmd_File (void)
+{
+	GetScriptToken (false);
+	ReleaseFile (token);
+}
+
+/*
+===============
+PackDirectory_r
+
+===============
+*/
+#ifdef _WIN32
+#include "io.h"
+void PackDirectory_r (char *dir)
+{
+	struct _finddata_t fileinfo;
+	int		handle;
+	char	dirstring[1024];
+	char	filename[1024];
+
+	sprintf (dirstring, "%s%s/*.*", gamedir, dir);
+
+	handle = _findfirst (dirstring, &fileinfo);
+	if (handle == -1)
+		return;
+
+	do
+	{
+		sprintf (filename, "%s/%s", dir, fileinfo.name);
+		if (fileinfo.attrib & _A_SUBDIR)
+		{	// directory
+			if (fileinfo.name[0] != '.')	// don't pak . and ..
+				PackDirectory_r (filename);
+			continue;
+		}
+		// copy or pack the file
+		ReleaseFile (filename);		
+	} while (_findnext( handle, &fileinfo ) != -1);
+
+	_findclose (handle);
+}
+#else
+
+#include <sys/types.h>
+#ifdef NeXT
+#include <sys/dir.h>
+#else
+#include <dirent.h>
+#endif
+
+void PackDirectory_r (char *dir)
+{
+#ifdef NeXT
+	struct direct **namelist, *ent;
+#else
+	struct dirent **namelist, *ent;
+#endif
+	int		count;
+	struct stat st;
+	int			i;
+	int			len;
+	char		fullname[1024];
+	char		dirstring[1024];
+	char		*name;
+	
+	sprintf (dirstring, "%s%s", gamedir, dir);
+	count = scandir(dirstring, &namelist, NULL, NULL);
+	
+	for (i=0 ; i<count ; i++)
+	{
+		ent = namelist[i];	
+		name = ent->d_name;
+
+		if (name[0] == '.')
+			continue;
+	
+		sprintf (fullname, "%s/%s", dir, name);
+		sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
+		
+		if (stat (dirstring, &st) == -1)
+			Error ("fstating %s", pf->name);
+		if (st.st_mode & S_IFDIR)
+		{	// directory
+			PackDirectory_r (fullname);
+			continue;
+		}
+
+		// copy or pack the file
+		ReleaseFile (fullname);		
+	}
+}
+#endif
+
+
+/*
+===============
+Cmd_Dir
+
+This is only used to cause a directory to be copied during a
+release build (sounds, etc)
+===============
+*/
+void Cmd_Dir (void)
+{
+	GetScriptToken (false);
+	PackDirectory_r (token);	
+}
+
+//========================================================================
+
+#define	MAX_RTEX	16384
+int		numrtex;
+char	rtex[MAX_RTEX][64];
+
+void ReleaseTexture (char *name)
+{
+	int		i;
+	char	path[1024];
+
+	for (i=0 ; i<numrtex ; i++)
+		if (!Q_strcasecmp(name, rtex[i]))
+			return;
+
+	if (numrtex == MAX_RTEX)
+		Error ("numrtex == MAX_RTEX");
+
+	strcpy (rtex[i], name);
+	numrtex++;
+
+	sprintf (path, "textures/%s.wal", name);
+	ReleaseFile (path);
+}
+
+/*
+===============
+Cmd_Maps
+
+Only relevent for release and pak files.
+Releases the .bsp files for the maps, and scans all of the files to
+build a list of all textures used, which are then released.
+===============
+*/
+void Cmd_Maps (void)
+{
+	char	map[1024];
+	int		i;
+
+	while (ScriptTokenAvailable ())
+	{
+		GetScriptToken (false);
+		sprintf (map, "maps/%s.bsp", token);
+		ReleaseFile (map);
+
+		if (!g_release)
+			continue;
+
+		// get all the texture references
+		sprintf (map, "%smaps/%s.bsp", gamedir, token);
+		LoadBSPFileTexinfo (map);
+		for (i=0 ; i<numtexinfo ; i++)
+			ReleaseTexture (texinfo[i].texture);
+	}
+}
+
+
+//==============================================================
+
+/*
+===============
+ParseScript
+===============
+*/
+void ParseScript (void)
+{
+	while (1)
+	{
+		do
+		{	// look for a line starting with a $ command
+			GetScriptToken (true);
+			if (endofscript)
+				return;
+			if (token[0] == '$')
+				break;				
+			while (ScriptTokenAvailable())
+				GetScriptToken (false);
+		} while (1);
+		
+		//
+		// model commands
+		//
+		if (!strcmp (token, "$modelname"))
+			MODELCMD_Modelname (MODEL_MD2);
+		else if (!strcmp (token, "$cd"))
+			MODELCMD_Cd (MODEL_MD2);
+		else if (!strcmp (token, "$origin"))
+			MODELCMD_Origin (MODEL_MD2);
+		else if (!strcmp (token, "$cluster"))
+			MODELCMD_Cluster (MODEL_MD2);
+		else if (!strcmp (token, "$base"))
+			MODELCMD_Base (MODEL_MD2);
+		else if (!strcmp (token, "$scale"))
+			MODELCMD_ScaleUp (MODEL_MD2);
+		else if (!strcmp (token, "$frame"))
+			MODELCMD_Frame (MODEL_MD2);
+		else if (!strcmp (token, "$skin"))
+			MODELCMD_Skin (MODEL_MD2);
+		else if (!strcmp (token, "$skinsize"))
+			MODELCMD_Skinsize (MODEL_MD2);
+		//
+		// flexible model commands
+		//
+		else if (!strcmp (token, "$fm_modelname"))
+			MODELCMD_Modelname (MODEL_FM);
+		else if (!strcmp (token, "$fm_base"))
+			MODELCMD_Base (MODEL_FM);
+		else if (!strcmp (token, "$fm_basest"))
+			MODELCMD_BaseST (MODEL_FM);
+		else if (!strcmp (token, "$fm_cd"))
+			MODELCMD_Cd (MODEL_FM);
+		else if (!strcmp (token, "$fm_origin"))
+			MODELCMD_Origin (MODEL_FM);
+		else if (!strcmp (token, "$fm_cluster"))
+			MODELCMD_Cluster (MODEL_FM);
+		else if (!strcmp (token, "$fm_skeleton"))
+			MODELCMD_Skeleton (MODEL_FM);
+		else if (!strcmp (token, "$fm_scale"))
+			MODELCMD_ScaleUp (MODEL_FM);
+		else if (!strcmp (token, "$fm_frame"))
+			MODELCMD_Frame (MODEL_FM);
+		else if (!strcmp (token, "$fm_skeletal_frame"))	// left in for compadibility with qdt already using fm_skeletal_frame
+			MODELCMD_Frame (MODEL_FM);
+		else if (!strcmp (token, "$fm_skin"))
+			MODELCMD_Skin (MODEL_FM);
+		else if (!strcmp (token, "$fm_skinsize"))
+			MODELCMD_Skinsize (MODEL_FM);
+		else if (!strcmp (token, "$fm_begin_group"))
+			MODELCMD_BeginGroup(MODEL_FM);
+		else if (!strcmp (token, "$fm_end_group"))
+			MODELCMD_EndGroup(MODEL_FM);
+		else if (!strcmp (token, "$fm_referenced"))
+			MODELCMD_Referenced(MODEL_FM);
+		else if (!strcmp (token, "$fm_node_order"))
+			MODELCMD_NodeOrder(MODEL_FM);
+		
+		//
+		// sprite commands
+		//
+		else if (!strcmp (token, "$spritename"))
+			Cmd_SpriteName ();
+		else if (!strcmp (token, "$sprdir"))
+			Cmd_Sprdir ();
+		else if (!strcmp (token, "$load"))
+			Cmd_Load ();
+		else if (!strcmp (token, "$spriteframe"))
+			Cmd_SpriteFrame ();
+		//
+		// image commands
+		//
+		else if (!strcmpi (token, "$grab"))
+			Cmd_Grab ();
+		else if (!strcmpi (token, "$raw"))
+			Cmd_Raw ();
+		else if (!strcmpi (token, "$colormap"))
+			Cmd_Colormap ();
+		else if (!strcmpi (token, "$mippal"))
+			Cmd_Mippal ();
+		else if (!strcmpi (token, "$mipdir"))
+			Cmd_Mipdir ();
+		else if (!strcmpi (token, "$mip"))
+			Cmd_Mip ();
+		else if (!strcmp (token, "$environment"))
+			Cmd_Environment ();
+		//
+		// pics
+		//
+		else if (!strcmp (token, "$picdir"))
+			Cmd_Picdir ();
+		else if (!strcmp (token, "$pic"))
+			Cmd_Pic ();
+		//
+		// book
+		//
+		else if (!strcmp (token, "$bookdir"))
+			Cmd_Bookdir ();
+		else if (!strcmp (token, "$book"))
+			Cmd_Book ();
+		//
+		// tmix
+		//
+		else if (!strcmp (token, "$texturemix"))
+			Cmd_TextureMix ();
+		//
+		// video
+		//
+		else if (!strcmp (token, "$video"))
+			Cmd_Video ();
+		//
+		// misc
+		//
+		else if (!strcmp (token, "$file"))
+			Cmd_File ();
+		else if (!strcmp (token, "$dir"))
+			Cmd_Dir ();
+		else if (!strcmp (token, "$maps"))
+			Cmd_Maps ();
+		else if (!strcmp (token, "$alphalight"))
+			Cmd_Alphalight ();
+		else if (!strcmp (token, "$inverse16table" ))
+			Cmd_Inverse16Table();
+		else
+			Error ("bad command %s\n", token);
+	}
+}
+
+//=======================================================
+
+/*
+==============
+main
+==============
+*/
+int main (int argc, char **argv)
+{
+	int			i;
+	char		path[1024];
+	char		*basedir;
+	double		starttime, endtime;
+
+	printf ("Qdata Plus : "__TIME__" "__DATE__"\n");
+
+	starttime = I_FloatTime();
+	basedir = NULL;
+
+	TK_Init();
+	ExpandWildcards (&argc, &argv);
+
+	for (i=1 ; i<argc ; i++)
+	{
+		if (!strcmp(argv[i], "-archive"))
+		{
+			// -archive f:/quake2/release/dump_11_30
+			archive = true;
+			strcpy (archivedir, argv[i+1]);
+			printf ("Archiving source to: %s\n", archivedir);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-release"))
+		{
+			g_release = true;
+			strcpy (g_releasedir, argv[i+1]);
+			printf ("Copy output to: %s\n", g_releasedir);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-base"))
+		{
+			i++;
+			basedir = argv[i];
+		}
+		else if (!strcmp(argv[i], "-compress"))
+		{
+			g_compress_pak = true;
+			printf ("Compressing pakfile\n");
+		}
+		else if (!strcmp(argv[i], "-pak"))
+		{
+			g_release = true;
+			g_pak = true;
+			printf ("Building pakfile: %s\n", argv[i+1]);
+			BeginPak (argv[i+1]);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-only"))
+		{
+			strcpy (g_only, argv[i+1]);
+			printf ("Only grabbing %s\n", g_only);
+			i++;
+		}
+		else if (!strcmpi(argv[i], "-keypress"))
+		{
+			g_dokeypress = true;
+		}
+		else if (!strcmp(argv[i], "-3ds"))
+		{
+			do3ds = true;
+			printf ("loading .3ds files\n");
+		}
+		else if (!strcmp(argv[i], "-materialfile"))
+		{
+			strcpy(g_materialFile, argv[i+1]);
+			printf("Setting material file to %s\n", g_materialFile);
+			i++;
+		}
+/*		else if (!strcmpi(argv[i], "-newgen"))
+		{
+			if (i < argc-4)
+			{
+				printf("run new triangle grouping routine here\n");
+				NewGen(argv[i+1],argv[i+2],atoi(argv[i+3]),atoi(argv[i+4]));
+			}
+			else
+			{
+				printf("qdata -newskin <base.hrc> <skin.pcx> width height\n");
+			}
+			return 0;
+		}
+*/		else if (!strcmpi(argv[i], "-genskin"))
+		{
+			i++;
+			if (i < argc-3)
+			{
+				GenSkin(argv[i],argv[i+1],atol(argv[i+2]),atol(argv[i+3]));
+			}
+			else
+			{
+				printf("qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>\n");
+			}
+			return 0;
+			
+		}
+		else if (!strcmpi(argv[i], "-noopts"))
+		{
+			g_no_opimizations = true;
+			printf("not performing optimizations\n");
+		}
+		else if (!strcmpi(argv[i], "-md2"))
+		{
+			g_forcemodel = MODEL_MD2;
+		}
+		else if (!strcmpi(argv[i], "-fm"))
+		{
+			g_forcemodel = MODEL_FM;
+		}
+		else if (!strcmpi(argv[i], "-verbose"))
+		{
+			g_verbose = true;
+		}
+		else if (!strcmpi(argv[i], "-oldskin"))
+		{
+			g_allow_newskin = false;
+		}
+		else if (!strcmpi(argv[i], "-ignoreUV"))
+		{
+			g_ignoreTriUV = true;
+		}
+		else if (!strcmpi(argv[i], "-publish"))
+		{
+			g_publishOutput = true;
+		}
+		else if (!strcmpi(argv[i], "-nomkdir"))
+		{
+			g_nomkdir = true;
+		}
+		else if (argv[i][0] == '-')
+			Error ("Unknown option \"%s\"", argv[i]);
+		else
+			break;
+	}
+
+	if (i >= argc)
+	{
+		Error ("usage: qdata [-archive <directory>]\n"
+			"             [-release <directory>]\n"
+			"             [-base <directory>]\n"
+			"             [-compress]\n"
+			"             [-pak <file>]\n"
+			"             [-only <model>]\n"
+			"             [-keypress]\n"
+			"             [-3ds]\n"
+			"             [-materialfile <file>]\n"
+			"             [-noopts]\n"
+			"             [-md2]\n"
+			"             [-fm]\n"
+			"             [-verbose]\n"
+			"             [-ignoreUV]\n"
+			"             [-oldskin]\n"
+			"             [-publish]\n"
+			"             [-nomkdir]\n"
+			"             file.qdt\n"
+			"or\n"
+			"       qdata -genskin <base.hrc> <skin.pcx> <desired width> <desired height>");
+	}
+
+	if (do3ds)
+		trifileext = ext_3ds;
+	else
+		trifileext = ext_tri;
+
+	for ( ; i<argc ; i++)
+	{
+		printf ("--------------- %s ---------------\n", argv[i]);
+		// load the script
+		strcpy (path, argv[i]);
+		DefaultExtension (path, ".qdt");
+		DefaultExtension(g_materialFile, ".mat");
+		SetQdirFromPath (path);
+
+		printf("workingdir='%s'\n", gamedir);
+		if (basedir)
+		{
+			qdir[0] = 0;
+			g_outputDir = basedir;
+		}
+
+		printf("outputdir='%s'\n", g_outputDir);
+
+		QFile_ReadMaterialTypes(g_materialFile);
+		LoadScriptFile (ExpandArg(path));
+		
+		//
+		// parse it
+		//
+		ParseScript ();
+
+		// write out the last model
+		FinishModel ();
+		FMFinishModel ();
+		FinishSprite ();
+	}
+
+	if (total_textures)
+	{
+		printf("\n");
+		printf("Total textures processed: %d\n",total_textures);
+		printf("Average size: %d x %d\n",total_x / total_textures, total_y / total_textures);
+	}
+
+	if (g_pak)
+		FinishPak ();
+
+	endtime = I_FloatTime();
+	printf("Time elapsed:  %f\n", endtime-starttime);
+	
+	if (g_dokeypress)
+	{
+		printf("Success! ... Hit a key: ");
+		getchar();
+	}
+
+	return 0;
+}
+
diff --git a/tools/quake2/qdata_heretic2/qdata.h b/tools/quake2/qdata_heretic2/qdata.h
index 57f6f896..bbe9c6b3 100644
--- a/tools/quake2/qdata_heretic2/qdata.h
+++ b/tools/quake2/qdata_heretic2/qdata.h
@@ -1,166 +1,166 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// qdata.h
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "cmdlib.h"
-#include "inout.h"
-#include "scriplib.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "lbmlib.h"
-#include "her2_threads.h"
-#include "l3dslib.h"
-#include "bspfile.h"
-
-#ifndef _WIN32
-#define stricmp strcasecmp
-#define strcmpi strcasecmp
-#endif
-
-
-#define MODEL_AUTO	0
-#define	MODEL_MD2	1
-#define MODEL_FM	2
-
-// Model cover functions (to allow the forcing of a model type)
-void MODELCMD_Modelname (int modeltype);
-void MODELCMD_Cd (int modeltype);
-void MODELCMD_Origin (int modeltype);
-void MODELCMD_Jointed (int modeltype);
-void MODELCMD_Cluster (int modeltype);
-void MODELCMD_Base (int modeltype);
-void MODELCMD_BaseST (int modeltype);
-void MODELCMD_ScaleUp (int modeltype);
-void MODELCMD_Frame (int modeltype);
-void MODELCMD_Skin (int modeltype);
-void MODELCMD_Skinsize (int modeltype);
-void MODELCMD_Skeleton (int modeltype);
-void MODELCMD_SkeletalFrame (int modeltype);
-void MODELCMD_BeginGroup(int modeltype);
-void MODELCMD_EndGroup(int modeltype);
-void MODELCMD_Referenced(int modeltype);
-void MODELCMD_NodeOrder(int modeltype);
-
-void Cmd_Modelname (void);
-void Cmd_Base (void);
-void Cmd_Cd (void);
-void Cmd_Origin (void);
-void Cmd_ScaleUp (void);
-void Cmd_Frame (void);
-void Cmd_Skin (void);
-void Cmd_Skinsize (void);
-void FinishModel (void);
-void Cmd_Cluster (void);
-
-// Flexible Models
-//void Cmd_FMModelname (void);
-void Cmd_FMBase (qboolean GetST);
-void Cmd_FMCd (void);
-//void Cmd_FMOrigin (void);
-void Cmd_FMCluster();
-void Cmd_FMSkeleton();
-//void Cmd_FMScaleUp (void);
-void Cmd_FMFrame (void);
-void Cmd_FMSkeletalFrame();
-void Cmd_FMSkin (void);
-//void Cmd_FMSkinsize (void);
-void Cmd_FMBeginGroup(void);
-void Cmd_FMEndGroup(void);
-void Cmd_FMReferenced();
-void Cmd_FMNodeOrder(void);
-void FMFinishModel (void);
-void GenSkin(char *ModelFile, char *OutputName, int Width, int Height);
-void NewGen (char *ModelFile, char *OutputName, int width, int height);
-
-
-void Cmd_Inverse16Table( void );
-
-void Cmd_SpriteName (void);
-void Cmd_Load (void);
-void Cmd_SpriteFrame (void);
-void Cmd_Sprdir (void);
-void FinishSprite (void);
-
-void Cmd_Grab (void);
-void Cmd_Raw (void);
-void Cmd_Mip (void);
-void Cmd_Environment (void);
-void Cmd_Colormap (void);
-
-void Cmd_File (void);
-void Cmd_Dir (void);
-void Cmd_StartWad (void);
-void Cmd_EndWad (void);
-void Cmd_Mippal (void);
-void Cmd_Mipdir (void);
-void Cmd_Alphalight (void);
-
-void Cmd_Picdir (void);
-void Cmd_Pic (void);
-
-void Cmd_Bookdir (void);
-void Cmd_Book (void);
-
-void Cmd_TextureMix (void);
-
-void Cmd_Video (void);
-
-//void RemapZero (byte *pixels, byte *palette, int width, int height);
-
-void ReleaseFile (char *filename);
-
-extern	byte		*byteimage, *lbmpalette;
-extern	int			byteimagewidth, byteimageheight;
-extern	qboolean	TrueColorImage;
-extern	unsigned	*longimage;
-extern	int			longimagewidth, longimageheight;
-
-extern	qboolean	g_release;			// don't grab, copy output data to new tree
-extern	char		g_releasedir[1024];	// c:\quake2\baseq2, etc
-extern	qboolean	g_archive;			// don't grab, copy source data to new tree
-extern	qboolean	do3ds;
-extern	char		g_only[256];		// if set, only grab this cd
-extern	qboolean	g_skipmodel;		// set true when a cd is not g_only
-extern	qboolean	g_no_opimizations;
-extern	int			g_forcemodel;
-extern	qboolean	g_verbose;
-extern	qboolean	g_allow_newskin;
-extern	qboolean	g_ignoreTriUV;	//from qdata.c
-extern qboolean	g_dokeypress;
-
-extern	char		*trifileext;
-
-extern	char		g_materialFile[256];
-
-extern	unsigned	total_x;
-extern	unsigned	total_y;
-extern	unsigned	total_textures;
-
-miptex_t *CreateMip(byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip);
-miptex32_t *CreateMip32(unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// qdata.h
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "cmdlib.h"
+#include "inout.h"
+#include "scriplib.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "lbmlib.h"
+#include "her2_threads.h"
+#include "l3dslib.h"
+#include "bspfile.h"
+
+#ifndef _WIN32
+#define stricmp strcasecmp
+#define strcmpi strcasecmp
+#endif
+
+
+#define MODEL_AUTO	0
+#define	MODEL_MD2	1
+#define MODEL_FM	2
+
+// Model cover functions (to allow the forcing of a model type)
+void MODELCMD_Modelname (int modeltype);
+void MODELCMD_Cd (int modeltype);
+void MODELCMD_Origin (int modeltype);
+void MODELCMD_Jointed (int modeltype);
+void MODELCMD_Cluster (int modeltype);
+void MODELCMD_Base (int modeltype);
+void MODELCMD_BaseST (int modeltype);
+void MODELCMD_ScaleUp (int modeltype);
+void MODELCMD_Frame (int modeltype);
+void MODELCMD_Skin (int modeltype);
+void MODELCMD_Skinsize (int modeltype);
+void MODELCMD_Skeleton (int modeltype);
+void MODELCMD_SkeletalFrame (int modeltype);
+void MODELCMD_BeginGroup(int modeltype);
+void MODELCMD_EndGroup(int modeltype);
+void MODELCMD_Referenced(int modeltype);
+void MODELCMD_NodeOrder(int modeltype);
+
+void Cmd_Modelname (void);
+void Cmd_Base (void);
+void Cmd_Cd (void);
+void Cmd_Origin (void);
+void Cmd_ScaleUp (void);
+void Cmd_Frame (void);
+void Cmd_Skin (void);
+void Cmd_Skinsize (void);
+void FinishModel (void);
+void Cmd_Cluster (void);
+
+// Flexible Models
+//void Cmd_FMModelname (void);
+void Cmd_FMBase (qboolean GetST);
+void Cmd_FMCd (void);
+//void Cmd_FMOrigin (void);
+void Cmd_FMCluster();
+void Cmd_FMSkeleton();
+//void Cmd_FMScaleUp (void);
+void Cmd_FMFrame (void);
+void Cmd_FMSkeletalFrame();
+void Cmd_FMSkin (void);
+//void Cmd_FMSkinsize (void);
+void Cmd_FMBeginGroup(void);
+void Cmd_FMEndGroup(void);
+void Cmd_FMReferenced();
+void Cmd_FMNodeOrder(void);
+void FMFinishModel (void);
+void GenSkin(char *ModelFile, char *OutputName, int Width, int Height);
+void NewGen (char *ModelFile, char *OutputName, int width, int height);
+
+
+void Cmd_Inverse16Table( void );
+
+void Cmd_SpriteName (void);
+void Cmd_Load (void);
+void Cmd_SpriteFrame (void);
+void Cmd_Sprdir (void);
+void FinishSprite (void);
+
+void Cmd_Grab (void);
+void Cmd_Raw (void);
+void Cmd_Mip (void);
+void Cmd_Environment (void);
+void Cmd_Colormap (void);
+
+void Cmd_File (void);
+void Cmd_Dir (void);
+void Cmd_StartWad (void);
+void Cmd_EndWad (void);
+void Cmd_Mippal (void);
+void Cmd_Mipdir (void);
+void Cmd_Alphalight (void);
+
+void Cmd_Picdir (void);
+void Cmd_Pic (void);
+
+void Cmd_Bookdir (void);
+void Cmd_Book (void);
+
+void Cmd_TextureMix (void);
+
+void Cmd_Video (void);
+
+//void RemapZero (byte *pixels, byte *palette, int width, int height);
+
+void ReleaseFile (char *filename);
+
+extern	byte		*byteimage, *lbmpalette;
+extern	int			byteimagewidth, byteimageheight;
+extern	qboolean	TrueColorImage;
+extern	unsigned	*longimage;
+extern	int			longimagewidth, longimageheight;
+
+extern	qboolean	g_release;			// don't grab, copy output data to new tree
+extern	char		g_releasedir[1024];	// c:\quake2\baseq2, etc
+extern	qboolean	g_archive;			// don't grab, copy source data to new tree
+extern	qboolean	do3ds;
+extern	char		g_only[256];		// if set, only grab this cd
+extern	qboolean	g_skipmodel;		// set true when a cd is not g_only
+extern	qboolean	g_no_opimizations;
+extern	int			g_forcemodel;
+extern	qboolean	g_verbose;
+extern	qboolean	g_allow_newskin;
+extern	qboolean	g_ignoreTriUV;	//from qdata.c
+extern qboolean	g_dokeypress;
+
+extern	char		*trifileext;
+
+extern	char		g_materialFile[256];
+
+extern	unsigned	total_x;
+extern	unsigned	total_y;
+extern	unsigned	total_textures;
+
+miptex_t *CreateMip(byte *data, unsigned width, unsigned height, byte *palette, int *FinalSize, qboolean mip);
+miptex32_t *CreateMip32(unsigned *data, unsigned width, unsigned height, int *FinalSize, qboolean mip);
diff --git a/tools/quake2/qdata_heretic2/resource.h b/tools/quake2/qdata_heretic2/resource.h
index b71bb50e..14e2fb5b 100644
--- a/tools/quake2/qdata_heretic2/resource.h
+++ b/tools/quake2/qdata_heretic2/resource.h
@@ -1,18 +1,18 @@
-//{{NO_DEPENDENCIES}}
-// Microsoft Developer Studio generated include file.
-// Used by Script1.rc
-//
-#define IDI_ICON1                       101
-
-// Next default values for new objects
-// 
-#ifdef APSTUDIO_INVOKED
-#ifndef APSTUDIO_READONLY_SYMBOLS
-#define _APS_NO_MFC                     1
-#define _APS_3D_CONTROLS                     1
-#define _APS_NEXT_RESOURCE_VALUE        102
-#define _APS_NEXT_COMMAND_VALUE         40001
-#define _APS_NEXT_CONTROL_VALUE         1000
-#define _APS_NEXT_SYMED_VALUE           101
-#endif
-#endif
+//{{NO_DEPENDENCIES}}
+// Microsoft Developer Studio generated include file.
+// Used by Script1.rc
+//
+#define IDI_ICON1                       101
+
+// Next default values for new objects
+// 
+#ifdef APSTUDIO_INVOKED
+#ifndef APSTUDIO_READONLY_SYMBOLS
+#define _APS_NO_MFC                     1
+#define _APS_3D_CONTROLS                     1
+#define _APS_NEXT_RESOURCE_VALUE        102
+#define _APS_NEXT_COMMAND_VALUE         40001
+#define _APS_NEXT_CONTROL_VALUE         1000
+#define _APS_NEXT_SYMED_VALUE           101
+#endif
+#endif
diff --git a/tools/quake2/qdata_heretic2/sprites.c b/tools/quake2/qdata_heretic2/sprites.c
index 68514c20..86854063 100644
--- a/tools/quake2/qdata_heretic2/sprites.c
+++ b/tools/quake2/qdata_heretic2/sprites.c
@@ -1,349 +1,349 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "qdata.h"
-
-#define MAX_SPRFRAMES			MAX_MD2SKINS
-
-dsprite_t		sprite;
-dsprframe_t		frames[MAX_SPRFRAMES];
-
-byte			*byteimage, *lbmpalette;
-int				byteimagewidth, byteimageheight;
-
-qboolean		TrueColorImage;
-unsigned		*longimage;
-int				longimagewidth, longimageheight;
-
-char			spritename[1024];
-
-
-void FinishSprite (void);
-void Cmd_Spritename (void);
-
-char spr_prefix[1024];
-char pic_prefix[1024];
-
-extern 	char		*g_outputDir;
-
-
-/*
-==============
-FinishSprite	
-==============
-*/
-void FinishSprite (void)
-{
-	FILE	*spriteouthandle;
-	int			i, curframe;
-	dsprite_t	spritetemp;
-	char		savename[1024];
-
-	if (sprite.numframes == 0)
-		return;
-
-	if (!strlen(spritename))
-		Error ("Didn't name sprite file");
-		
-	sprintf (savename, "%sSprites/%s/%s.sp2", g_outputDir, spr_prefix, spritename);
-
-	if (g_release)
-	{
-		char	name[1024];
-
-		sprintf (name, "%s.sp2", spritename);
-		ReleaseFile (name);
-		spritename[0] = 0;		// clear for a new sprite
-		sprite.numframes = 0;
-		return;
-	}
-
-
-	printf ("saving in %s\n", savename);
-	CreatePath (savename);
-	spriteouthandle = SafeOpenWrite (savename);
-
-
-//
-// write out the sprite header
-//
-	spritetemp.ident = LittleLong (IDSPRITEHEADER);
-	spritetemp.version = LittleLong (SPRITE_VERSION);
-	spritetemp.numframes = LittleLong (sprite.numframes);
-
-	SafeWrite (spriteouthandle, &spritetemp, 12);
-
-//
-// write out the frames
-//
-	curframe = 0;
-
-	for (i=0 ; i<sprite.numframes ; i++)
-	{
-		frames[i].width = LittleLong(frames[i].width);
-		frames[i].height = LittleLong(frames[i].height);
-		frames[i].origin_x = LittleLong(frames[i].origin_x);
-		frames[i].origin_y = LittleLong(frames[i].origin_y);
-	}
-	SafeWrite (spriteouthandle, frames, sizeof(frames[0])*sprite.numframes);
-
-	fclose (spriteouthandle);
-	
-	spritename[0] = 0;		// clear for a new sprite
-	sprite.numframes = 0;
-}
-
-
-/*
-===============
-Cmd_Load
-===============
-*/
-void Cmd_Load (void)
-{
-	char	*name;
-
-	GetScriptToken (false);
-
-	if (g_release)
-		return;
-
-	name = ExpandPathAndArchive(token);
-
-	// load the image
-	printf ("loading %s\n", name);
-	TrueColorImage = LoadAnyImage (name, &byteimage, &lbmpalette, &byteimagewidth, &byteimageheight);
-
-	if (!TrueColorImage)
-	{
-//		RemapZero (byteimage, lbmpalette, byteimagewidth, byteimageheight);
-	}
-	else
-	{
-		if (longimage)
-			free(longimage);
-		longimage = (unsigned *)byteimage;
-		longimagewidth = byteimagewidth;
-		longimageheight = byteimageheight;
-
-		byteimage = NULL;
-		byteimagewidth = 0;
-		byteimageheight = 0;
-	}
-}
-
-
-/*
-===============
-Cmd_SpriteFrame
-===============
-*/
-
-void Cmd_SpriteFrame (void)
-{
-	int             x,y,xl,yl,xh,yh,w,h;
-	dsprframe_t		*pframe;
-	int				ox, oy, linedelta, size;
-//	byte			*cropped;
-	char			filename[1024];
-	miptex_t		*qtex;
-	miptex32_t		*qtex32;
-	unsigned        *destl, *sourcel;
-	unsigned		bufferl[256*256];
-	byte            *dest, *source;
-	byte			buffer[256*256];
-
-	GetScriptToken (false);
-	xl = atoi (token);
-	GetScriptToken (false);
-	yl = atoi (token);
-	GetScriptToken (false);
-	w = atoi (token);
-	GetScriptToken (false);
-	h = atoi (token);
-
-	// origin offset is optional
-	if (ScriptTokenAvailable ())
-	{
-		GetScriptToken (false);
-		ox = atoi (token);
-		GetScriptToken (false);
-		oy = atoi (token);		
-	}
-	else
-	{
-		ox = w/2;
-		oy = h/2;
-	}
-
-	if ((xl & 0x0f) || (yl & 0x0f) || (w & 0x0f) || (h & 0x0f))
-		Error ("Sprite dimensions not multiples of 16\n");
-
-	if ((w > 256) || (h > 256))
-		Error ("Sprite has a dimension longer than 256");
-
-	xh = xl+w;
-	yh = yl+h;
-
-	if (sprite.numframes >= MAX_SPRFRAMES)
-		Error ("Too many frames; increase MAX_SPRFRAMES\n");
-
-	pframe = &frames[sprite.numframes];
-	pframe->width = w;
-	pframe->height = h;
-	pframe->origin_x = ox;
-	pframe->origin_y = oy;
-
-	if (g_release)
-	{
-		ReleaseFile (pframe->name);
-		return;
-	}
-
-	if (TrueColorImage)
-	{
-		sprintf (filename, "%ssprites/%s/%s_%i.m32", g_outputDir, spr_prefix, spritename, sprite.numframes);
-		sprintf (pframe->name, "%s/%s_%i.m32", spr_prefix, spritename, sprite.numframes);
-
-		if (g_release)
-			return;	// textures are only released by $maps
-
-		xh = xl+w;
-		yh = yl+h;
-
-		if (xl >= longimagewidth || xh > longimagewidth ||
-			yl >= longimageheight || yh > longimageheight)
-		{
-			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
-		}
-
-		sourcel = longimage + (yl*longimagewidth) + xl;
-		destl = bufferl;
-		linedelta = (longimagewidth - w);
-
-		for (y=yl ; y<yh ; y++)
-		{
-			for (x=xl ; x<xh ; x++)
-			{
-				*destl++ = *sourcel++;	// RGBA
-			}
-			sourcel += linedelta;
-		}
-
-		qtex32 = CreateMip32(bufferl, w, h, &size, true);
-
-		qtex32->contents = 0;
-		qtex32->value = 0;
-		strcpy(qtex32->name, pframe->name);
-	//
-	// write it out
-	//
-		printf ("writing %s\n", filename);
-		SaveFile (filename, (byte *)qtex32, size);
-
-		free (qtex32);
-	}
-	else
-	{
-		sprintf (filename, "%ssprites/%s/%s_%i.m8", g_outputDir, spr_prefix, spritename, sprite.numframes);
-		sprintf (pframe->name, "%s/%s_%i.m8", spr_prefix, spritename, sprite.numframes);
-
-		if (g_release)
-			return;	// textures are only released by $maps
-
-		xh = xl+w;
-		yh = yl+h;
-
-		if (xl >= byteimagewidth || xh > byteimagewidth ||
-			yl >= byteimageheight || yh > byteimageheight)
-		{
-			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
-		}
-
-		source = byteimage + yl*byteimagewidth + xl;
-		dest = buffer;
-		linedelta = byteimagewidth - w;
-
-		for (y=yl ; y<yh ; y++)
-		{
-			for (x=xl ; x<xh ; x++)
-			{
-				*dest++ = *source++;
-			}
-			source += linedelta;
-		}
-
-		qtex = CreateMip(buffer, w, h, lbmpalette, &size, true);
-
-		qtex->flags = 0;
-		qtex->contents = 0;
-		qtex->value = 0;
-		strcpy(qtex->name, pframe->name);
-	//
-	// write it out
-	//
-		printf ("writing %s\n", filename);
-		SaveFile (filename, (byte *)qtex, size);
-
-		free (qtex);
-	}
-
-	sprite.numframes++;
-}
-
-
-/*
-==============
-Cmd_SpriteName
-==============
-*/
-void Cmd_SpriteName (void)
-{
-	if (sprite.numframes)
-		FinishSprite ();
-
-	GetScriptToken (false);
-	strcpy (spritename, token);
-	memset (&sprite, 0, sizeof(sprite));
-	memset (&frames, 0, sizeof(frames));
-}
-
-
-/*
-===============
-Cmd_Sprdir
-===============
-*/
-void Cmd_Sprdir (void)
-{
-	char	filename[1024];
-
-	GetScriptToken (false);
-	strcpy (spr_prefix, token);
-	// create the directory if needed
-	sprintf (filename, "%sSprites", g_outputDir);
-	Q_mkdir (filename); 
-	sprintf (filename, "%sSprites/%s", g_outputDir, spr_prefix);
-	Q_mkdir (filename); 
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "qdata.h"
+
+#define MAX_SPRFRAMES			MAX_MD2SKINS
+
+dsprite_t		sprite;
+dsprframe_t		frames[MAX_SPRFRAMES];
+
+byte			*byteimage, *lbmpalette;
+int				byteimagewidth, byteimageheight;
+
+qboolean		TrueColorImage;
+unsigned		*longimage;
+int				longimagewidth, longimageheight;
+
+char			spritename[1024];
+
+
+void FinishSprite (void);
+void Cmd_Spritename (void);
+
+char spr_prefix[1024];
+char pic_prefix[1024];
+
+extern 	char		*g_outputDir;
+
+
+/*
+==============
+FinishSprite	
+==============
+*/
+void FinishSprite (void)
+{
+	FILE	*spriteouthandle;
+	int			i, curframe;
+	dsprite_t	spritetemp;
+	char		savename[1024];
+
+	if (sprite.numframes == 0)
+		return;
+
+	if (!strlen(spritename))
+		Error ("Didn't name sprite file");
+		
+	sprintf (savename, "%sSprites/%s/%s.sp2", g_outputDir, spr_prefix, spritename);
+
+	if (g_release)
+	{
+		char	name[1024];
+
+		sprintf (name, "%s.sp2", spritename);
+		ReleaseFile (name);
+		spritename[0] = 0;		// clear for a new sprite
+		sprite.numframes = 0;
+		return;
+	}
+
+
+	printf ("saving in %s\n", savename);
+	CreatePath (savename);
+	spriteouthandle = SafeOpenWrite (savename);
+
+
+//
+// write out the sprite header
+//
+	spritetemp.ident = LittleLong (IDSPRITEHEADER);
+	spritetemp.version = LittleLong (SPRITE_VERSION);
+	spritetemp.numframes = LittleLong (sprite.numframes);
+
+	SafeWrite (spriteouthandle, &spritetemp, 12);
+
+//
+// write out the frames
+//
+	curframe = 0;
+
+	for (i=0 ; i<sprite.numframes ; i++)
+	{
+		frames[i].width = LittleLong(frames[i].width);
+		frames[i].height = LittleLong(frames[i].height);
+		frames[i].origin_x = LittleLong(frames[i].origin_x);
+		frames[i].origin_y = LittleLong(frames[i].origin_y);
+	}
+	SafeWrite (spriteouthandle, frames, sizeof(frames[0])*sprite.numframes);
+
+	fclose (spriteouthandle);
+	
+	spritename[0] = 0;		// clear for a new sprite
+	sprite.numframes = 0;
+}
+
+
+/*
+===============
+Cmd_Load
+===============
+*/
+void Cmd_Load (void)
+{
+	char	*name;
+
+	GetScriptToken (false);
+
+	if (g_release)
+		return;
+
+	name = ExpandPathAndArchive(token);
+
+	// load the image
+	printf ("loading %s\n", name);
+	TrueColorImage = LoadAnyImage (name, &byteimage, &lbmpalette, &byteimagewidth, &byteimageheight);
+
+	if (!TrueColorImage)
+	{
+//		RemapZero (byteimage, lbmpalette, byteimagewidth, byteimageheight);
+	}
+	else
+	{
+		if (longimage)
+			free(longimage);
+		longimage = (unsigned *)byteimage;
+		longimagewidth = byteimagewidth;
+		longimageheight = byteimageheight;
+
+		byteimage = NULL;
+		byteimagewidth = 0;
+		byteimageheight = 0;
+	}
+}
+
+
+/*
+===============
+Cmd_SpriteFrame
+===============
+*/
+
+void Cmd_SpriteFrame (void)
+{
+	int             x,y,xl,yl,xh,yh,w,h;
+	dsprframe_t		*pframe;
+	int				ox, oy, linedelta, size;
+//	byte			*cropped;
+	char			filename[1024];
+	miptex_t		*qtex;
+	miptex32_t		*qtex32;
+	unsigned        *destl, *sourcel;
+	unsigned		bufferl[256*256];
+	byte            *dest, *source;
+	byte			buffer[256*256];
+
+	GetScriptToken (false);
+	xl = atoi (token);
+	GetScriptToken (false);
+	yl = atoi (token);
+	GetScriptToken (false);
+	w = atoi (token);
+	GetScriptToken (false);
+	h = atoi (token);
+
+	// origin offset is optional
+	if (ScriptTokenAvailable ())
+	{
+		GetScriptToken (false);
+		ox = atoi (token);
+		GetScriptToken (false);
+		oy = atoi (token);		
+	}
+	else
+	{
+		ox = w/2;
+		oy = h/2;
+	}
+
+	if ((xl & 0x0f) || (yl & 0x0f) || (w & 0x0f) || (h & 0x0f))
+		Error ("Sprite dimensions not multiples of 16\n");
+
+	if ((w > 256) || (h > 256))
+		Error ("Sprite has a dimension longer than 256");
+
+	xh = xl+w;
+	yh = yl+h;
+
+	if (sprite.numframes >= MAX_SPRFRAMES)
+		Error ("Too many frames; increase MAX_SPRFRAMES\n");
+
+	pframe = &frames[sprite.numframes];
+	pframe->width = w;
+	pframe->height = h;
+	pframe->origin_x = ox;
+	pframe->origin_y = oy;
+
+	if (g_release)
+	{
+		ReleaseFile (pframe->name);
+		return;
+	}
+
+	if (TrueColorImage)
+	{
+		sprintf (filename, "%ssprites/%s/%s_%i.m32", g_outputDir, spr_prefix, spritename, sprite.numframes);
+		sprintf (pframe->name, "%s/%s_%i.m32", spr_prefix, spritename, sprite.numframes);
+
+		if (g_release)
+			return;	// textures are only released by $maps
+
+		xh = xl+w;
+		yh = yl+h;
+
+		if (xl >= longimagewidth || xh > longimagewidth ||
+			yl >= longimageheight || yh > longimageheight)
+		{
+			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,longimagewidth,longimageheight);
+		}
+
+		sourcel = longimage + (yl*longimagewidth) + xl;
+		destl = bufferl;
+		linedelta = (longimagewidth - w);
+
+		for (y=yl ; y<yh ; y++)
+		{
+			for (x=xl ; x<xh ; x++)
+			{
+				*destl++ = *sourcel++;	// RGBA
+			}
+			sourcel += linedelta;
+		}
+
+		qtex32 = CreateMip32(bufferl, w, h, &size, true);
+
+		qtex32->contents = 0;
+		qtex32->value = 0;
+		strcpy(qtex32->name, pframe->name);
+	//
+	// write it out
+	//
+		printf ("writing %s\n", filename);
+		SaveFile (filename, (byte *)qtex32, size);
+
+		free (qtex32);
+	}
+	else
+	{
+		sprintf (filename, "%ssprites/%s/%s_%i.m8", g_outputDir, spr_prefix, spritename, sprite.numframes);
+		sprintf (pframe->name, "%s/%s_%i.m8", spr_prefix, spritename, sprite.numframes);
+
+		if (g_release)
+			return;	// textures are only released by $maps
+
+		xh = xl+w;
+		yh = yl+h;
+
+		if (xl >= byteimagewidth || xh > byteimagewidth ||
+			yl >= byteimageheight || yh > byteimageheight)
+		{
+			Error ("line %i: bad clip dimmensions (%d,%d) (%d,%d) > image (%d,%d)", scriptline, xl,yl,w,h,byteimagewidth,byteimageheight);
+		}
+
+		source = byteimage + yl*byteimagewidth + xl;
+		dest = buffer;
+		linedelta = byteimagewidth - w;
+
+		for (y=yl ; y<yh ; y++)
+		{
+			for (x=xl ; x<xh ; x++)
+			{
+				*dest++ = *source++;
+			}
+			source += linedelta;
+		}
+
+		qtex = CreateMip(buffer, w, h, lbmpalette, &size, true);
+
+		qtex->flags = 0;
+		qtex->contents = 0;
+		qtex->value = 0;
+		strcpy(qtex->name, pframe->name);
+	//
+	// write it out
+	//
+		printf ("writing %s\n", filename);
+		SaveFile (filename, (byte *)qtex, size);
+
+		free (qtex);
+	}
+
+	sprite.numframes++;
+}
+
+
+/*
+==============
+Cmd_SpriteName
+==============
+*/
+void Cmd_SpriteName (void)
+{
+	if (sprite.numframes)
+		FinishSprite ();
+
+	GetScriptToken (false);
+	strcpy (spritename, token);
+	memset (&sprite, 0, sizeof(sprite));
+	memset (&frames, 0, sizeof(frames));
+}
+
+
+/*
+===============
+Cmd_Sprdir
+===============
+*/
+void Cmd_Sprdir (void)
+{
+	char	filename[1024];
+
+	GetScriptToken (false);
+	strcpy (spr_prefix, token);
+	// create the directory if needed
+	sprintf (filename, "%sSprites", g_outputDir);
+	Q_mkdir (filename); 
+	sprintf (filename, "%sSprites/%s", g_outputDir, spr_prefix);
+	Q_mkdir (filename); 
+}
+
+
diff --git a/tools/quake2/qdata_heretic2/svdcmp.c b/tools/quake2/qdata_heretic2/svdcmp.c
index 8e02f8e4..e4496a19 100644
--- a/tools/quake2/qdata_heretic2/svdcmp.c
+++ b/tools/quake2/qdata_heretic2/svdcmp.c
@@ -1,490 +1,490 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <assert.h>
-#include <string.h>
-#include <math.h>
-
-static double at,bt,ct;
-#define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
-		     (ct=bt/at,at*sqrt(1.0+ct*ct)) : (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
-
-  static double maxarg1,maxarg2;
-#define MAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
-		  (maxarg1) : (maxarg2))
-#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
-
-void ntrerror(char *s)
-{
-  printf("%s\n",s);
-  exit(1);
-}
-
-double *allocVect(int sz)
-{
-	double *ret;
-	
-	ret = calloc(sizeof(double), (size_t)sz);
-	return ret;
-}
-
-void freeVect(double *ret)
-{
-	free(ret);
-}
-
-double **allocMatrix(int r,int c)
-{
-	double **ret;
-		
-	ret = calloc(sizeof(double), (size_t)(r*c));
-	return ret;
-}
-
-void freeMatrix(double **ret,int r)
-{
-	free(ret);
-}
-
-void svdcmp(double** a, int m, int n, double* w, double** v)
-{
-  int flag,i,its,j,jj,k,l,nm;
-  double c,f,h,s,x,y,z;
-  double anorm=0.0,g=0.0,scale=0.0;
-  double *rv1;
-  void nrerror();
-
-  if (m < n) ntrerror("SVDCMP: You must augment A with extra zero rows");
-  rv1=allocVect(n);
-  for (i=1;i<=n;i++) {
-    l=i+1;
-    rv1[i]=scale*g;
-    g=s=scale=0.0;
-    if (i <= m) {
-      for (k=i;k<=m;k++) scale += fabs(a[k][i]);
-      if (scale) {
-	for (k=i;k<=m;k++) {
-	  a[k][i] /= scale;
-	  s += a[k][i]*a[k][i];
-	}
-	f=a[i][i];
-	g = -SIGN(sqrt(s),f);
-	h=f*g-s;
-	a[i][i]=f-g;
-	if (i != n) {
-	  for (j=l;j<=n;j++) {
-	    for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
-	    f=s/h;
-	    for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
-	  }
-	}
-	for (k=i;k<=m;k++) a[k][i] *= scale;
-      }
-    }
-    w[i]=scale*g;
-    g=s=scale=0.0;
-    if (i <= m && i != n) {
-      for (k=l;k<=n;k++) scale += fabs(a[i][k]);
-      if (scale) {
-	for (k=l;k<=n;k++) {
-	  a[i][k] /= scale;
-	  s += a[i][k]*a[i][k];
-	}
-	f=a[i][l];
-	g = -SIGN(sqrt(s),f);
-	h=f*g-s;
-	a[i][l]=f-g;
-	for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
-	if (i != m) {
-	  for (j=l;j<=m;j++) {
-	    for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
-	    for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
-	  }
-	}
-	for (k=l;k<=n;k++) a[i][k] *= scale;
-      }
-    }
-    anorm=MAX(anorm,(fabs(w[i])+fabs(rv1[i])));
-  }
-  for (i=n;i>=1;i--) {
-    if (i < n) {
-      if (g) {
-	for (j=l;j<=n;j++)
-	  v[j][i]=(a[i][j]/a[i][l])/g;
-	for (j=l;j<=n;j++) {
-	  for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
-	  for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
-	}
-      }
-      for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
-    }
-    v[i][i]=1.0;
-    g=rv1[i];
-    l=i;
-  }
-  for (i=n;i>=1;i--) {
-    l=i+1;
-    g=w[i];
-    if (i < n)
-      for (j=l;j<=n;j++) a[i][j]=0.0;
-    if (g) {
-      g=1.0/g;
-      if (i != n) {
-	for (j=l;j<=n;j++) {
-	  for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
-	  f=(s/a[i][i])*g;
-	  for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
-	}
-      }
-      for (j=i;j<=m;j++) a[j][i] *= g;
-    } else {
-      for (j=i;j<=m;j++) a[j][i]=0.0;
-    }
-    ++a[i][i];
-  }
-  for (k=n;k>=1;k--) {
-    for (its=1;its<=30;its++) {
-      flag=1;
-      for (l=k;l>=1;l--) {
-	nm=l-1;
-	if (fabs(rv1[l])+anorm == anorm) {
-	  flag=0;
-	  break;
-	}
-	if (fabs(w[nm])+anorm == anorm) break;
-      }
-      if (flag) {
-	c=0.0;
-	s=1.0;
-	for (i=l;i<=k;i++) {
-	  f=s*rv1[i];
-	  if (fabs(f)+anorm != anorm) {
-	    g=w[i];
-	    h=PYTHAG(f,g);
-	    w[i]=h;
-	    h=1.0/h;
-	    c=g*h;
-	    s=(-f*h);
-	    for (j=1;j<=m;j++) {
-	      y=a[j][nm];
-	      z=a[j][i];
-	      a[j][nm]=y*c+z*s;
-	      a[j][i]=z*c-y*s;
-	    }
-	  }
-	}
-      }
-      z=w[k];
-      if (l == k) {
-	if (z < 0.0) {
-	  w[k] = -z;
-	  for (j=1;j<=n;j++) v[j][k]=(-v[j][k]);
-	}
-	break;
-      }
-      if (its == 30) ntrerror("No convergence in 30 SVDCMP iterations");
-      x=w[l];
-      nm=k-1;
-      y=w[nm];
-      g=rv1[nm];
-      h=rv1[k];
-      f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
-      g=PYTHAG(f,1.0);
-      f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
-      c=s=1.0;
-      for (j=l;j<=nm;j++) {
-	i=j+1;
-	g=rv1[i];
-	y=w[i];
-	h=s*g;
-	g=c*g;
-	z=PYTHAG(f,h);
-	rv1[j]=z;
-	c=f/z;
-	s=h/z;
-	f=x*c+g*s;
-	g=g*c-x*s;
-	h=y*s;
-	y=y*c;
-	for (jj=1;jj<=n;jj++) {
-	  x=v[jj][j];
-	  z=v[jj][i];
-	  v[jj][j]=x*c+z*s;
-	  v[jj][i]=z*c-x*s;
-	}
-	z=PYTHAG(f,h);
-	w[j]=z;
-	if (z) {
-	  z=1.0/z;
-	  c=f*z;
-	  s=h*z;
-	}
-	f=(c*g)+(s*y);
-	x=(c*y)-(s*g);
-	for (jj=1;jj<=m;jj++) {
-	  y=a[jj][j];
-	  z=a[jj][i];
-	  a[jj][j]=y*c+z*s;
-	  a[jj][i]=z*c-y*s;
-	}
-      }
-      rv1[l]=0.0;
-      rv1[k]=f;
-      w[k]=x;
-    }
-  }
-  freeVect(rv1);
-}
-
-
-
-void svbksb(double** u, double* w, double** v,int m, int n, double* b, double* x)
-{  
-	int jj,j,i; 
-	double s,*tmp;
-	tmp=allocVect(n);
-	for (j=1;j<=n;j++) 
-	{    
-		s=0.0;    
-		if (w[j]) 
-		{
-			for (i=1;i<=m;i++) 
-				s += u[i][j]*b[i];   
-			s /= w[j];   
-		}   
-		tmp[j]=s; 
-	}
-	for (j=1;j<=n;j++) 
-	{   
-		s=0.0;  
-		for (jj=1;jj<=n;jj++) 
-			s += v[j][jj]*tmp[jj];
-		x[j]=s;
-	} 
-	freeVect(tmp);
-}
-
-#undef SIGN
-#undef MAX
-#undef PYTHAG
-
-
-#if 1
-void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize)
-{
-	int usedfs;
-	int *remap;
-	int i,j;
-	double **da;
-	double **v;
-	double *w;
-	int DOFerr;
-	float mx;
-	int bestat;
-
-	if (nframes>framesize)
-		usedfs=nframes;
-	else
-		usedfs=framesize;
-
-	da=allocMatrix(usedfs,nframes);
-	v=allocMatrix(nframes,nframes);
-	w=allocVect(nframes);
-
-	DOFerr = 0; //false
-	for (i=0;i<nframes;i++)
-	{
-		for (j=0;j<framesize;j++)
-			da[j+1][i+1]=a[i*framesize+j];
-		for (;j<usedfs;j++)
-			da[j+1][i+1]=0.0;
-	}
-
-	svdcmp(da,usedfs,nframes,w,v);
-
-	remap = calloc(sizeof(int), (size_t)nframes);
-
-
-	for (i=0;i<nframes;i++)
-		remap[i]=-1;
-	for (j=0;j<compressedsize;j++)
-	{
-		mx=-1.0f;
-		for (i=0;i<nframes;i++)
-		{
-			if (remap[i]<0&&fabs(w[i+1])>mx)
-			{
-				mx=(float) fabs(w[i+1]);
-				bestat=i;
-			}
-		}
-
-		if(mx>0)
-		{
-			remap[bestat]=j;
-		}
-		else
-		{
-			DOFerr = 1; //true
-		}
-	}
-
-	if(DOFerr)
-	{
-		printf("Warning:  To many degrees of freedom!  File size may increase\n");
-
-		for (i=0;i<compressedsize;i++)
-		{
-			values[i]=0;
-			for (j=0;j<framesize;j++)
-				res[i*framesize+j]=0;
-		}
-	}
-
-	for (i=0;i<nframes;i++)
-	{
-		if (remap[i]<0)
-			w[i+1]=0.0;
-		else
-		{
-			values[remap[i]]=(float) w[i+1];
-			for (j=0;j<framesize;j++)
-				res[remap[i]*framesize+j]=(float) da[j+1][i+1];
-		}
-	}
-	freeVect(w);
-	freeMatrix(v,nframes);
-	freeMatrix(da,framesize);
-	free(remap);
-}
-
-#else
-
-void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize)
-{
-	int *remap;
-	int i,j;
-	int nrows;
-	nrows=nframes;
-	if (nrows<framesize)
-		nrows=framesize;
-	double **da=allocMatrix(nrows,framesize);
-	double **v=allocMatrix(framesize,framesize);
-	double *w=allocVect(framesize);
-	float mx;
-	int bestat;
-
-	for (j=0;j<framesize;j++)
-	{
-		for (i=0;i<nframes;i++)
-			da[j+1][i+1]=a[i*framesize+j];
-		for (;i<nrows;i++)
-			da[j+1][i+1]=0.0;
-	}
-
-	svdcmp(da,nrows,framesize,w,v);
-
-	remap=new int[framesize];
-
-
-	for (i=0;i<framesize;i++)
-		remap[i]=-1;
-	for (j=0;j<compressedsize;j++)
-	{
-		mx=-1.0f;
-		for (i=0;i<framesize;i++)
-		{
-			if (remap[i]<0&&fabs(w[i+1])>mx)
-			{
-				mx=fabs(w[i+1]);
-				bestat=i;
-			}
-		}
-		assert(mx>-.5f);
-		remap[bestat]=j;
-	}
-	// josh **DO NOT** put your dof>nframes mod here
-	for (i=0;i<framesize;i++)
-	{
-		if (remap[i]<0)
-			w[i+1]=0.0;
-		else
-		{
-			values[remap[i]]=w[i+1];
-			for (j=0;j<framesize;j++)
-				res[remap[i]*framesize+j]=v[j+1][i+1];
-		}
-	}
-	freeVect(w);
-	freeMatrix(v,framesize);
-	freeMatrix(da,nrows);
-	delete[] remap;
-}
-
-#endif
-
-void DOsvdPlane(float *pnts,int npnts,float *n,float *base)
-{
-	int i,j;
-	double **da=allocMatrix(npnts,3);
-	double **v=allocMatrix(3,3);
-	double *w=allocVect(3);
-	float mn=1E30f;
-	int bestat;
-
-
-	assert(npnts>=3);
-	base[0]=pnts[0];
-	base[1]=pnts[1];
-	base[2]=pnts[2];
-	for (i=1;i<npnts;i++)
-	{
-		for (j=0;j<3;j++)
-			base[j]+=pnts[i*3+j];
-	}
-	base[0]/=(float)(npnts);
-	base[1]/=(float)(npnts);
-	base[2]/=(float)(npnts);
-
-	for (i=0;i<3;i++)
-	{
-		for (j=0;j<npnts;j++)
-			da[j+1][i+1]=pnts[j*3+i]-base[i];
-	}
-
-	svdcmp(da,npnts,3,w,v);
-	for (i=0;i<3;i++)
-	{
-		if (fabs(w[i+1])<mn)
-		{
-			mn=(float) fabs(w[i+1]);
-			bestat=i;
-		}
-	}
-	n[0]=(float) v[1][bestat+1];
-	n[1]=(float) v[2][bestat+1];
-	n[2]=(float) v[3][bestat+1];
-	freeVect(w);
-	freeMatrix(v,3);
-	freeMatrix(da,npnts);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <assert.h>
+#include <string.h>
+#include <math.h>
+
+static double at,bt,ct;
+#define PYTHAG(a,b) ((at=fabs(a)) > (bt=fabs(b)) ? \
+		     (ct=bt/at,at*sqrt(1.0+ct*ct)) : (bt ? (ct=at/bt,bt*sqrt(1.0+ct*ct)): 0.0))
+
+  static double maxarg1,maxarg2;
+#define MAX(a,b) (maxarg1=(a),maxarg2=(b),(maxarg1) > (maxarg2) ?\
+		  (maxarg1) : (maxarg2))
+#define SIGN(a,b) ((b) >= 0.0 ? fabs(a) : -fabs(a))
+
+void ntrerror(char *s)
+{
+  printf("%s\n",s);
+  exit(1);
+}
+
+double *allocVect(int sz)
+{
+	double *ret;
+	
+	ret = calloc(sizeof(double), (size_t)sz);
+	return ret;
+}
+
+void freeVect(double *ret)
+{
+	free(ret);
+}
+
+double **allocMatrix(int r,int c)
+{
+	double **ret;
+		
+	ret = calloc(sizeof(double), (size_t)(r*c));
+	return ret;
+}
+
+void freeMatrix(double **ret,int r)
+{
+	free(ret);
+}
+
+void svdcmp(double** a, int m, int n, double* w, double** v)
+{
+  int flag,i,its,j,jj,k,l,nm;
+  double c,f,h,s,x,y,z;
+  double anorm=0.0,g=0.0,scale=0.0;
+  double *rv1;
+  void nrerror();
+
+  if (m < n) ntrerror("SVDCMP: You must augment A with extra zero rows");
+  rv1=allocVect(n);
+  for (i=1;i<=n;i++) {
+    l=i+1;
+    rv1[i]=scale*g;
+    g=s=scale=0.0;
+    if (i <= m) {
+      for (k=i;k<=m;k++) scale += fabs(a[k][i]);
+      if (scale) {
+	for (k=i;k<=m;k++) {
+	  a[k][i] /= scale;
+	  s += a[k][i]*a[k][i];
+	}
+	f=a[i][i];
+	g = -SIGN(sqrt(s),f);
+	h=f*g-s;
+	a[i][i]=f-g;
+	if (i != n) {
+	  for (j=l;j<=n;j++) {
+	    for (s=0.0,k=i;k<=m;k++) s += a[k][i]*a[k][j];
+	    f=s/h;
+	    for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
+	  }
+	}
+	for (k=i;k<=m;k++) a[k][i] *= scale;
+      }
+    }
+    w[i]=scale*g;
+    g=s=scale=0.0;
+    if (i <= m && i != n) {
+      for (k=l;k<=n;k++) scale += fabs(a[i][k]);
+      if (scale) {
+	for (k=l;k<=n;k++) {
+	  a[i][k] /= scale;
+	  s += a[i][k]*a[i][k];
+	}
+	f=a[i][l];
+	g = -SIGN(sqrt(s),f);
+	h=f*g-s;
+	a[i][l]=f-g;
+	for (k=l;k<=n;k++) rv1[k]=a[i][k]/h;
+	if (i != m) {
+	  for (j=l;j<=m;j++) {
+	    for (s=0.0,k=l;k<=n;k++) s += a[j][k]*a[i][k];
+	    for (k=l;k<=n;k++) a[j][k] += s*rv1[k];
+	  }
+	}
+	for (k=l;k<=n;k++) a[i][k] *= scale;
+      }
+    }
+    anorm=MAX(anorm,(fabs(w[i])+fabs(rv1[i])));
+  }
+  for (i=n;i>=1;i--) {
+    if (i < n) {
+      if (g) {
+	for (j=l;j<=n;j++)
+	  v[j][i]=(a[i][j]/a[i][l])/g;
+	for (j=l;j<=n;j++) {
+	  for (s=0.0,k=l;k<=n;k++) s += a[i][k]*v[k][j];
+	  for (k=l;k<=n;k++) v[k][j] += s*v[k][i];
+	}
+      }
+      for (j=l;j<=n;j++) v[i][j]=v[j][i]=0.0;
+    }
+    v[i][i]=1.0;
+    g=rv1[i];
+    l=i;
+  }
+  for (i=n;i>=1;i--) {
+    l=i+1;
+    g=w[i];
+    if (i < n)
+      for (j=l;j<=n;j++) a[i][j]=0.0;
+    if (g) {
+      g=1.0/g;
+      if (i != n) {
+	for (j=l;j<=n;j++) {
+	  for (s=0.0,k=l;k<=m;k++) s += a[k][i]*a[k][j];
+	  f=(s/a[i][i])*g;
+	  for (k=i;k<=m;k++) a[k][j] += f*a[k][i];
+	}
+      }
+      for (j=i;j<=m;j++) a[j][i] *= g;
+    } else {
+      for (j=i;j<=m;j++) a[j][i]=0.0;
+    }
+    ++a[i][i];
+  }
+  for (k=n;k>=1;k--) {
+    for (its=1;its<=30;its++) {
+      flag=1;
+      for (l=k;l>=1;l--) {
+	nm=l-1;
+	if (fabs(rv1[l])+anorm == anorm) {
+	  flag=0;
+	  break;
+	}
+	if (fabs(w[nm])+anorm == anorm) break;
+      }
+      if (flag) {
+	c=0.0;
+	s=1.0;
+	for (i=l;i<=k;i++) {
+	  f=s*rv1[i];
+	  if (fabs(f)+anorm != anorm) {
+	    g=w[i];
+	    h=PYTHAG(f,g);
+	    w[i]=h;
+	    h=1.0/h;
+	    c=g*h;
+	    s=(-f*h);
+	    for (j=1;j<=m;j++) {
+	      y=a[j][nm];
+	      z=a[j][i];
+	      a[j][nm]=y*c+z*s;
+	      a[j][i]=z*c-y*s;
+	    }
+	  }
+	}
+      }
+      z=w[k];
+      if (l == k) {
+	if (z < 0.0) {
+	  w[k] = -z;
+	  for (j=1;j<=n;j++) v[j][k]=(-v[j][k]);
+	}
+	break;
+      }
+      if (its == 30) ntrerror("No convergence in 30 SVDCMP iterations");
+      x=w[l];
+      nm=k-1;
+      y=w[nm];
+      g=rv1[nm];
+      h=rv1[k];
+      f=((y-z)*(y+z)+(g-h)*(g+h))/(2.0*h*y);
+      g=PYTHAG(f,1.0);
+      f=((x-z)*(x+z)+h*((y/(f+SIGN(g,f)))-h))/x;
+      c=s=1.0;
+      for (j=l;j<=nm;j++) {
+	i=j+1;
+	g=rv1[i];
+	y=w[i];
+	h=s*g;
+	g=c*g;
+	z=PYTHAG(f,h);
+	rv1[j]=z;
+	c=f/z;
+	s=h/z;
+	f=x*c+g*s;
+	g=g*c-x*s;
+	h=y*s;
+	y=y*c;
+	for (jj=1;jj<=n;jj++) {
+	  x=v[jj][j];
+	  z=v[jj][i];
+	  v[jj][j]=x*c+z*s;
+	  v[jj][i]=z*c-x*s;
+	}
+	z=PYTHAG(f,h);
+	w[j]=z;
+	if (z) {
+	  z=1.0/z;
+	  c=f*z;
+	  s=h*z;
+	}
+	f=(c*g)+(s*y);
+	x=(c*y)-(s*g);
+	for (jj=1;jj<=m;jj++) {
+	  y=a[jj][j];
+	  z=a[jj][i];
+	  a[jj][j]=y*c+z*s;
+	  a[jj][i]=z*c-y*s;
+	}
+      }
+      rv1[l]=0.0;
+      rv1[k]=f;
+      w[k]=x;
+    }
+  }
+  freeVect(rv1);
+}
+
+
+
+void svbksb(double** u, double* w, double** v,int m, int n, double* b, double* x)
+{  
+	int jj,j,i; 
+	double s,*tmp;
+	tmp=allocVect(n);
+	for (j=1;j<=n;j++) 
+	{    
+		s=0.0;    
+		if (w[j]) 
+		{
+			for (i=1;i<=m;i++) 
+				s += u[i][j]*b[i];   
+			s /= w[j];   
+		}   
+		tmp[j]=s; 
+	}
+	for (j=1;j<=n;j++) 
+	{   
+		s=0.0;  
+		for (jj=1;jj<=n;jj++) 
+			s += v[j][jj]*tmp[jj];
+		x[j]=s;
+	} 
+	freeVect(tmp);
+}
+
+#undef SIGN
+#undef MAX
+#undef PYTHAG
+
+
+#if 1
+void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize)
+{
+	int usedfs;
+	int *remap;
+	int i,j;
+	double **da;
+	double **v;
+	double *w;
+	int DOFerr;
+	float mx;
+	int bestat;
+
+	if (nframes>framesize)
+		usedfs=nframes;
+	else
+		usedfs=framesize;
+
+	da=allocMatrix(usedfs,nframes);
+	v=allocMatrix(nframes,nframes);
+	w=allocVect(nframes);
+
+	DOFerr = 0; //false
+	for (i=0;i<nframes;i++)
+	{
+		for (j=0;j<framesize;j++)
+			da[j+1][i+1]=a[i*framesize+j];
+		for (;j<usedfs;j++)
+			da[j+1][i+1]=0.0;
+	}
+
+	svdcmp(da,usedfs,nframes,w,v);
+
+	remap = calloc(sizeof(int), (size_t)nframes);
+
+
+	for (i=0;i<nframes;i++)
+		remap[i]=-1;
+	for (j=0;j<compressedsize;j++)
+	{
+		mx=-1.0f;
+		for (i=0;i<nframes;i++)
+		{
+			if (remap[i]<0&&fabs(w[i+1])>mx)
+			{
+				mx=(float) fabs(w[i+1]);
+				bestat=i;
+			}
+		}
+
+		if(mx>0)
+		{
+			remap[bestat]=j;
+		}
+		else
+		{
+			DOFerr = 1; //true
+		}
+	}
+
+	if(DOFerr)
+	{
+		printf("Warning:  To many degrees of freedom!  File size may increase\n");
+
+		for (i=0;i<compressedsize;i++)
+		{
+			values[i]=0;
+			for (j=0;j<framesize;j++)
+				res[i*framesize+j]=0;
+		}
+	}
+
+	for (i=0;i<nframes;i++)
+	{
+		if (remap[i]<0)
+			w[i+1]=0.0;
+		else
+		{
+			values[remap[i]]=(float) w[i+1];
+			for (j=0;j<framesize;j++)
+				res[remap[i]*framesize+j]=(float) da[j+1][i+1];
+		}
+	}
+	freeVect(w);
+	freeMatrix(v,nframes);
+	freeMatrix(da,framesize);
+	free(remap);
+}
+
+#else
+
+void DOsvd(float *a,float *res,float *comp,float *values,int nframes,int framesize,int compressedsize)
+{
+	int *remap;
+	int i,j;
+	int nrows;
+	nrows=nframes;
+	if (nrows<framesize)
+		nrows=framesize;
+	double **da=allocMatrix(nrows,framesize);
+	double **v=allocMatrix(framesize,framesize);
+	double *w=allocVect(framesize);
+	float mx;
+	int bestat;
+
+	for (j=0;j<framesize;j++)
+	{
+		for (i=0;i<nframes;i++)
+			da[j+1][i+1]=a[i*framesize+j];
+		for (;i<nrows;i++)
+			da[j+1][i+1]=0.0;
+	}
+
+	svdcmp(da,nrows,framesize,w,v);
+
+	remap=new int[framesize];
+
+
+	for (i=0;i<framesize;i++)
+		remap[i]=-1;
+	for (j=0;j<compressedsize;j++)
+	{
+		mx=-1.0f;
+		for (i=0;i<framesize;i++)
+		{
+			if (remap[i]<0&&fabs(w[i+1])>mx)
+			{
+				mx=fabs(w[i+1]);
+				bestat=i;
+			}
+		}
+		assert(mx>-.5f);
+		remap[bestat]=j;
+	}
+	// josh **DO NOT** put your dof>nframes mod here
+	for (i=0;i<framesize;i++)
+	{
+		if (remap[i]<0)
+			w[i+1]=0.0;
+		else
+		{
+			values[remap[i]]=w[i+1];
+			for (j=0;j<framesize;j++)
+				res[remap[i]*framesize+j]=v[j+1][i+1];
+		}
+	}
+	freeVect(w);
+	freeMatrix(v,framesize);
+	freeMatrix(da,nrows);
+	delete[] remap;
+}
+
+#endif
+
+void DOsvdPlane(float *pnts,int npnts,float *n,float *base)
+{
+	int i,j;
+	double **da=allocMatrix(npnts,3);
+	double **v=allocMatrix(3,3);
+	double *w=allocVect(3);
+	float mn=1E30f;
+	int bestat;
+
+
+	assert(npnts>=3);
+	base[0]=pnts[0];
+	base[1]=pnts[1];
+	base[2]=pnts[2];
+	for (i=1;i<npnts;i++)
+	{
+		for (j=0;j<3;j++)
+			base[j]+=pnts[i*3+j];
+	}
+	base[0]/=(float)(npnts);
+	base[1]/=(float)(npnts);
+	base[2]/=(float)(npnts);
+
+	for (i=0;i<3;i++)
+	{
+		for (j=0;j<npnts;j++)
+			da[j+1][i+1]=pnts[j*3+i]-base[i];
+	}
+
+	svdcmp(da,npnts,3,w,v);
+	for (i=0;i<3;i++)
+	{
+		if (fabs(w[i+1])<mn)
+		{
+			mn=(float) fabs(w[i+1]);
+			bestat=i;
+		}
+	}
+	n[0]=(float) v[1][bestat+1];
+	n[1]=(float) v[2][bestat+1];
+	n[2]=(float) v[3][bestat+1];
+	freeVect(w);
+	freeMatrix(v,3);
+	freeMatrix(da,npnts);
+}
diff --git a/tools/quake2/qdata_heretic2/tables.c b/tools/quake2/qdata_heretic2/tables.c
index e7bb8ff5..cc78ae9f 100644
--- a/tools/quake2/qdata_heretic2/tables.c
+++ b/tools/quake2/qdata_heretic2/tables.c
@@ -1,171 +1,171 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qdata.h"
-
-/*
-=============================================================================
-
-ALPHALIGHT GENERATION
-
-Find alphamap values that best match modulated lightmap values
-
-This isn't used anymore, but I'm keeping it around...
-=============================================================================
-*/
-
-unsigned short	alphamap[32*32*32];
-unsigned char	inverse16to8table[65536];
-
-/*
-static int FindNearestColor( unsigned int color )
-{
-	int i;
-	int closest_so_far = 0;
-	float closest_distance_so_far = 100000000;
-	float d;
-	float r[2], g[2], b[2];
-
-	// incoming color is assumed to be in 0xRRGGBB format
-	r[0] = ( color & 31 ) << 3;
-	g[0] = ( ( color >> 5 ) & 63 ) << 2;
-	b[0] = ( ( color >> 11 ) & 31 ) << 3;
-
-	for ( i = 0; i < 256; i++ )
-	{
-		r[1] = ( d_8to24table[i] >> 0 ) & 0xFF;
-		g[1] = ( d_8to24table[i] >> 8 ) & 0xFF;
-		b[1] = ( d_8to24table[i] >> 16 ) & 0xFF;
-
-		d = ( r[1] - r[0] ) * ( r[1] - r[0] ) +
-			( g[1] - g[0] ) * ( g[1] - g[0] ) +
-			( b[1] - b[0] ) * ( b[1] - b[0] );
-
-		if ( d < closest_distance_so_far )
-		{
-			closest_distance_so_far = d;
-			closest_so_far = i;
-		}
-	}
-
-	return closest_so_far;
-}
-*/
-
-extern byte BestColor( int, int, int, int, int );
-
-void Inverse16_BuildTable( void )
-{
-	int i;
-
-	/*
-	** create the 16-to-8 table
-	*/
-	for ( i = 0; i < 65536; i++ )
-	{
-		int r = i & 31;
-		int g = ( i >> 5 ) & 63;
-		int b = ( i >> 11 ) & 31;
-
-		r <<= 3;
-		g <<= 2;
-		b <<= 3;
-
-		inverse16to8table[i] = BestColor( r, g, b, 0, 255 );
-	}
-}
-
-void Alphalight_Thread (int i)
-{
-	int		j;
-	float	r, g, b;
-	float	mr, mg, mb, ma;
-	float	distortion, bestdistortion;
-	float	v;
-
-	r = (i>>10) * (1.0/16);
-	g = ((i>>5)&31)  * (1.0/16);
-	b = (i&31) * (1.0/16);
-
-	bestdistortion = 999999;
-	for (j=0 ; j<16*16*16*16 ; j++)
-	{
-		mr = (j>>12) * (1.0/16);
-		mg = ((j>>8)&15) * (1.0/16);
-		mb = ((j>>4)&15) * (1.0/16);
-		ma = (j&15) * (1.0/16);
-
-		v = r * 0.5 - (mr*ma + 0.5*(1.0-ma));
-		distortion = v*v;
-		v = g * 0.5 - (mg*ma + 0.5*(1.0-ma));
-		distortion += v*v;
-		v = b * 0.5 - (mb*ma + 0.5*(1.0-ma));
-		distortion += v*v;
-
-		distortion *= 1.0 + ma*4;
-
-		if (distortion < bestdistortion)
-		{
-			bestdistortion = distortion;
-			alphamap[i] = j;
-		}
-	}
-}
-
-void Cmd_Alphalight (void)
-{
-	char	savename[1024];
-
-	GetScriptToken (false);
-
-	if (g_release)
-	{
-		ReleaseFile (token);
-		return;
-	}
-
-	sprintf (savename, "%s%s", gamedir, token);
-	printf ("Building alphalight table...\n");
-
-	RunThreadsOnIndividual (32*32*32, true, Alphalight_Thread);
-
-	SaveFile (savename, (byte *)alphamap, sizeof(alphamap));
-}
-
-
-void Cmd_Inverse16Table( void )
-{
-	char savename[1024];
-
-	if ( g_release )
-	{
-		sprintf (savename, "pics/16to8.dat");
-		ReleaseFile( savename );
-		return;
-	}
-
-	sprintf (savename, "%spics/16to8.dat", gamedir);
-	printf ("Building inverse 16-to-8 table...\n");
-
-	Inverse16_BuildTable();
-
-	SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) );
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qdata.h"
+
+/*
+=============================================================================
+
+ALPHALIGHT GENERATION
+
+Find alphamap values that best match modulated lightmap values
+
+This isn't used anymore, but I'm keeping it around...
+=============================================================================
+*/
+
+unsigned short	alphamap[32*32*32];
+unsigned char	inverse16to8table[65536];
+
+/*
+static int FindNearestColor( unsigned int color )
+{
+	int i;
+	int closest_so_far = 0;
+	float closest_distance_so_far = 100000000;
+	float d;
+	float r[2], g[2], b[2];
+
+	// incoming color is assumed to be in 0xRRGGBB format
+	r[0] = ( color & 31 ) << 3;
+	g[0] = ( ( color >> 5 ) & 63 ) << 2;
+	b[0] = ( ( color >> 11 ) & 31 ) << 3;
+
+	for ( i = 0; i < 256; i++ )
+	{
+		r[1] = ( d_8to24table[i] >> 0 ) & 0xFF;
+		g[1] = ( d_8to24table[i] >> 8 ) & 0xFF;
+		b[1] = ( d_8to24table[i] >> 16 ) & 0xFF;
+
+		d = ( r[1] - r[0] ) * ( r[1] - r[0] ) +
+			( g[1] - g[0] ) * ( g[1] - g[0] ) +
+			( b[1] - b[0] ) * ( b[1] - b[0] );
+
+		if ( d < closest_distance_so_far )
+		{
+			closest_distance_so_far = d;
+			closest_so_far = i;
+		}
+	}
+
+	return closest_so_far;
+}
+*/
+
+extern byte BestColor( int, int, int, int, int );
+
+void Inverse16_BuildTable( void )
+{
+	int i;
+
+	/*
+	** create the 16-to-8 table
+	*/
+	for ( i = 0; i < 65536; i++ )
+	{
+		int r = i & 31;
+		int g = ( i >> 5 ) & 63;
+		int b = ( i >> 11 ) & 31;
+
+		r <<= 3;
+		g <<= 2;
+		b <<= 3;
+
+		inverse16to8table[i] = BestColor( r, g, b, 0, 255 );
+	}
+}
+
+void Alphalight_Thread (int i)
+{
+	int		j;
+	float	r, g, b;
+	float	mr, mg, mb, ma;
+	float	distortion, bestdistortion;
+	float	v;
+
+	r = (i>>10) * (1.0/16);
+	g = ((i>>5)&31)  * (1.0/16);
+	b = (i&31) * (1.0/16);
+
+	bestdistortion = 999999;
+	for (j=0 ; j<16*16*16*16 ; j++)
+	{
+		mr = (j>>12) * (1.0/16);
+		mg = ((j>>8)&15) * (1.0/16);
+		mb = ((j>>4)&15) * (1.0/16);
+		ma = (j&15) * (1.0/16);
+
+		v = r * 0.5 - (mr*ma + 0.5*(1.0-ma));
+		distortion = v*v;
+		v = g * 0.5 - (mg*ma + 0.5*(1.0-ma));
+		distortion += v*v;
+		v = b * 0.5 - (mb*ma + 0.5*(1.0-ma));
+		distortion += v*v;
+
+		distortion *= 1.0 + ma*4;
+
+		if (distortion < bestdistortion)
+		{
+			bestdistortion = distortion;
+			alphamap[i] = j;
+		}
+	}
+}
+
+void Cmd_Alphalight (void)
+{
+	char	savename[1024];
+
+	GetScriptToken (false);
+
+	if (g_release)
+	{
+		ReleaseFile (token);
+		return;
+	}
+
+	sprintf (savename, "%s%s", gamedir, token);
+	printf ("Building alphalight table...\n");
+
+	RunThreadsOnIndividual (32*32*32, true, Alphalight_Thread);
+
+	SaveFile (savename, (byte *)alphamap, sizeof(alphamap));
+}
+
+
+void Cmd_Inverse16Table( void )
+{
+	char savename[1024];
+
+	if ( g_release )
+	{
+		sprintf (savename, "pics/16to8.dat");
+		ReleaseFile( savename );
+		return;
+	}
+
+	sprintf (savename, "%spics/16to8.dat", gamedir);
+	printf ("Building inverse 16-to-8 table...\n");
+
+	Inverse16_BuildTable();
+
+	SaveFile( savename, (byte *) inverse16to8table, sizeof( inverse16to8table ) );
+}
diff --git a/tools/quake2/qdata_heretic2/tmix.c b/tools/quake2/qdata_heretic2/tmix.c
index ad1d1902..5bccddf8 100644
--- a/tools/quake2/qdata_heretic2/tmix.c
+++ b/tools/quake2/qdata_heretic2/tmix.c
@@ -1,698 +1,698 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qdata.h"
-#include "flex.h"
-
-#define		MAXFILES	2048
-
-typedef	struct
-{
-	int			x;
-	int			y;
-	int			w;
-	int			h;
-	int			cw;
-	int			ch;
-	int			rw;
-	int			index;
-	int			depth;
-	int			col;
-	int			baseline;
-	char		name[128];
-} Coords;
-
-int				filenum;
-int				valid;
-Coords 			in[MAXFILES];
-Coords			out;
-char		  	outscript[256];
-char		  	sourcedir[256];
-char		  	outusage[256];
-char		  	root[32];
-
-int				destsize = 0;
-byte		  	*pixels = NULL;				// Buffer to load image
-long		  	*outpixels = NULL;			// Buffer to store combined textures
-long		  	*usagemap = NULL;			// Buffer of usage map
-void		  	*bmptemp = NULL;			// Buffer of usage map
-byte		  	*map = NULL;
-
-int				xcharsize;
-int				ycharsize;
-int				dosort = 0;
-int				missed = 0;
-int				overlap = 0;
-int				nobaseline = 0;
-int				percent;
-
-//////////////////////////////////////////////////
-// Setting the char based usage map				//
-//////////////////////////////////////////////////
-
-byte	TryPlace(Coords *coord)
-{
-	int		x, y;
-	byte	entry = 0;
-	byte	*mapitem;
-	
-	mapitem = map + (coord->x / xcharsize) + ((coord->y / ycharsize) * out.cw);
-
-	for (y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw)
-	{
-		for (x = 0; x < coord->cw; x++)
-		{
-			if (entry |= *mapitem++ & 8)
-			{
-				return(entry);
-			}
-		}
-	}
-	return(entry);
-}
-
-void	SetMap(Coords *coord)
-{
-	int		x, y;
-	byte	*mapitem;
-
-	mapitem = map + (coord->x / xcharsize) + ((coord->y / ycharsize) * out.cw);
-
-	for (y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw)
-		for (x = 0; x < coord->cw; x++)
-			*mapitem++ |= 8;
-}
-
-//////////////////////////////////////////////////
-// Setting the pixel based usage map			//
-//////////////////////////////////////////////////
-
-void	CheckOverlap(Coords *coord)
-{
-	int			x;
-	int			y;
-	long		*dest;
-
-	x = coord->x;
-	y = coord->y;
-
-	dest = (long *)(usagemap + x + (y * out.w));
-
-	for (y = 0; y < coord->h; y++, dest += out.w - coord->w)
-	{
-		for (x = 0; x < coord->w; x++)
-		{
-			if (*dest++)
-			{
-				overlap++;
-				return;
-			}
-		}
-	}
-}
-
-void	SetUsageMap(Coords *coord)
-{
-	int			x;
-	int			y;
-	long		*dest;
-
-	x = coord->x;
-	y = coord->y;
-
-	dest = (long *)(usagemap + x + (y * out.w));
-
-	for (y = 0; y < coord->h; y++, dest += out.w - coord->w)
-	{
-		for (x = 0; x < coord->w; x++)
-		{
-			*dest++ = coord->col;
-		}
-	}
-}
-
-//////////////////////////////////////////////////
-// Flips the BMP image to the correct way up	//
-//////////////////////////////////////////////////
-
-void	CopyLine(byte *dest, byte *src, int size)
-{
-	int		x;
-	
-	for (x = 0; x < size; x++)
-		*dest++ = *src++;
-}
-
-/****************************************************/
-/* Printing headers etc								*/
-/****************************************************/
-
-void RemoveLeading(char *name)
-{
-	int		i;
-	char	temp[128];
-
-	for(i = strlen(name) - 1; i > 0; i--)
-	{
-		if((name[i] == '\\') || (name[i] == '/'))
-		{
-			strcpy(temp, name + i + 1);
-			strcpy(name, temp);
-			return;
-		}
-	}
-}
-
-void RemoveExt(char *name)
-{
-	while ((*name != '.') && *name)
-		name++;
-	*name = 0;
-}
-
-/****************************************************/
-/* Misc calcualtions								*/
-/****************************************************/
-
-int	TotalArea()
-{
-	int		i;
-	int		total = 0;
-
-	for (i = 0; i < (filenum + 2); i++)
-		total += in[i].w * in[i].h;
-
-	return(total);
-}
-
-/****************************************************/
-/* Setup and checking of all info					*/
-/****************************************************/
-
-void	InitVars()
-{
-	filenum = 0;
-	valid = 0;
-   	dosort = 0;
-   	missed = 0;
-   	overlap = 0;
-   	nobaseline = 0;
-	
-	memset(outscript, 0, sizeof(outscript));
-	memset(outscript, 0, sizeof(sourcedir));
-	memset(outscript, 0, sizeof(outusage));
-	memset(outscript, 0, sizeof(root));
-
-	memset(in, 0, sizeof(in));
-	memset(&out, 0, sizeof(out));
-}
-void Cleanup()
-{
-	if (pixels)
-		free(pixels);
-	if (usagemap)
-		free(usagemap);
-	if (outpixels)
-		free(outpixels);
-	if (bmptemp)
-		free(bmptemp);
-	if (map)
-		free(map);
-}
-
-typedef struct glxy_s
-{
-	float	xl, yt, xr, yb;
-	int		w, h, baseline;
-} glxy_t;
-
-int	SaveScript(char *name)
-{
-	FILE		*fp;
-	int			i, j;
-	glxy_t		buff;
-	
-	if(fp = fopen(name, "wb"))
-	{
-		for (j = 0; j < filenum; j++)
-		{
-			for (i = 0; i < filenum; i++)
-			{
-				if (in[i].index == j)
-				{
-					if (in[i].depth)
-					{
-						buff.xl = (float)in[i].x / (float)out.w;
-						buff.yt = (float)in[i].y / (float)out.h;
-						buff.xr = ((float)in[i].w + (float)in[i].x) / (float)out.w;
-						buff.yb = ((float)in[i].h + (float)in[i].y) / (float)out.h;
-						buff.w = in[i].w;
-						buff.h = in[i].h;
-						buff.baseline = in[i].baseline;
-					}
-					else
-					{
-						memset(&buff, 0, sizeof(glxy_t));
-					}
-					fwrite(&buff, 1, sizeof(glxy_t), fp);
-					i = filenum;
-				}
-			}
-		}
-		fclose(fp);
-		return(true);
-	}
-	else
-		return(false);
-}
-
-int		GetScriptInfo(char *name)
-{
-	FILE		*fp;
-	char		buffer[256];
-	char		tempbuff[256];
-	char		delims[] = {" \t,\n"};
-
-	printf("Opening script file %s.\n", name);
-
-	if (fp = fopen(name, "r"))
-	{
-		while(fgets(buffer, 256, fp))
-		{
-			if (strncmp(buffer, "//", 2) && strncmp(buffer, "\n", 1))
-			{
-				strupr(buffer);
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "OUTPUT") == 0)
-				{
-					strcpy(out.name, strtok(NULL, delims));
-					strlwr(out.name);
-				}
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "SOURCEDIR") == 0)
-				{
-					strcpy(tempbuff, strtok(NULL, delims));
-					strcpy(sourcedir, ExpandPathAndArchive(tempbuff));
-				}
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "DOSORT") == 0)
-					dosort = 1;
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "XCHARSIZE") == 0)
-					xcharsize = strtol(strtok(NULL, delims), NULL, 0);
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "YCHARSIZE") == 0)
-					ycharsize = strtol(strtok(NULL, delims), NULL, 0);
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "OUTSCRIPT") == 0)
-				{
-					strcpy(outscript, strtok(NULL, delims));
-					strlwr(outscript);
-				}
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "OUTUSAGE") == 0)
-					strcpy(outusage, strtok(NULL, delims));
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "POS") == 0)
-				{
-					out.w = strtol(strtok(NULL, delims), NULL, 0);
-			 		out.h = strtol(strtok(NULL, delims), NULL, 0);
-				}
-
-				strcpy(tempbuff, buffer);
-				if (strcmp(strtok(tempbuff, delims), "FILE") == 0)
-				{
-					strcpy(in[filenum].name, strtok(NULL, delims));
-					in[filenum].x = strtol(strtok(NULL, delims), NULL, 0);
-					in[filenum].y = strtol(strtok(NULL, delims), NULL, 0);
-					in[filenum].col = strtol(strtok(NULL, delims), NULL, 0);
-					filenum++;
-				}
-			}
-		}
-		fclose(fp);
-		return(true);
-	}
-	else
-	{
-		printf("ERROR : Could not open script file.\n");
-		return(false);
-	}
-}
-
-int	CheckVars()
-{
-	int		i;
-
-	 if (out.name[0] == 0)
-	 {
-	 	printf("ERROR : No output name specified.\n");
-		return(false);
-	}
-	if ((out.w <= 0) || (out.h <= 0))
-	{
-		printf("ERROR : Invalid VRAM coordinates.\n");
-		return(false);
-	}
-	if (filenum == 0)
-	{
-		printf("ERROR : No input files specified.\n");
-		return(false);
-	}
-	for (i = 0; i < filenum; i++)
-		if (in[i].name[0] == 0)
-		{
-			printf("ERROR : Input filename invalid.\n");
-			return(false);
-		}
-	return(true);
-}
-
-// Makes sure texture is totally within the output area
-
-int	CheckCoords(Coords *coord)
-{
-	if ((coord->x + coord->w) > out.w)
-		return(false);
-	if ((coord->y + coord->h) > out.h)
-		return(false);
-
-	return(true);
-}
-// Gets the width, height, palette width and palette height of each BMP file
-
-int		GetFileDimensions()
-{
-	int			i;
-	int			width, height;
-	char		name[128];
-
-	for (i = 0; i < filenum; i++)
-	{
-		in[i].index = i;
-
-		strcpy(name, sourcedir);
-		strcat(name, in[i].name);
-		printf("Getting file dimensions, file : %s        \r", in[i].name);
-		if(FileExists(name))
-		{
-			LoadAnyImage(name, NULL, NULL, &width, &height);
-			in[i].depth = 32;
-			in[i].rw = width;
-			in[i].w = width;					 	// makes it width in 
-			in[i].h = height;
-			in[i].cw = (in[i].w + (xcharsize - 1)) / xcharsize;
-			in[i].ch = (in[i].h + (ycharsize - 1)) / ycharsize;
-
-			if (!CheckCoords(&in[i]) && (in[i].x >= 0))
-			{
-			 	printf("Error : texture %s out of bounds.\n", in[i].name);
-				return(false);
-			}
-			valid++;
-		}
-		else
-		{
-			in[i].depth = 0;
-			in[i].x = -1;
-			in[i].y = -1;
-			in[i].w = 0;
-			in[i].h = 0;
-		}
-	}
-	printf("\n\n");
-	return(true);
-}
-
-// Sorts files into order for optimal space finding
-// Fixed position ones first, followed by the others in descending size
-// The theory being that it is easier to find space for smaller textures.
-// size = (width + height)
-// For space finding it is easier to place a 32x32 than a 128x2
-
-#define	WEIGHT	0x8000
-
-void	Swap(Coords *a, Coords *b)
-{
-	Coords		c;
-
-	c = *a;
-	*a = *b;
-	*b = c;
-}
-
-void	SortInNames()
-{
-	int		i, j;
-	int		largest, largcount;
-	int		size;
-
-	printf("Sorting filenames by size.\n\n");
-
-	for (j = 0; j < filenum; j++)
-	{
-		largest = -1;
-		largcount = -1;
-
-		for (i = j; i < filenum; i++)
-		{
-			if (in[i].depth)
-			{
-				size = in[i].w + in[i].h;
-		
-				if ((in[i].x < 0) && (size > largest))
-				{
-					largcount = i;
-					largest = size;
-				}
-			}
-		}
-		if ((largcount >= 0) && (largcount != j))
-			Swap(&in[j], &in[largcount]);
-	}
-}
-
-int	SetVars(char *name)
-{
-	if (!GetScriptInfo(name))
-		return(false);
-
-	if (!CheckVars())
-		return(false);
-
-	destsize = out.w * out.h;
-
-	out.cw = out.w / xcharsize;
-	out.ch = out.h / ycharsize;
-
-	if ((usagemap = (long *)SafeMalloc(destsize * 4, "")) == NULL)
-		return(false);
-	if ((outpixels = (long *)SafeMalloc(destsize * 4, "")) == NULL)
-		return(false); 
-	if ((bmptemp = (void *)SafeMalloc(destsize * 4, "")) == NULL)
-		return(false);
-	if ((map = (byte *)SafeMalloc(destsize / (xcharsize * ycharsize), "")) == NULL)
-		return(false);
-
-	if (GetFileDimensions() == false)
-		return(false);
-
-	if (dosort)
-		SortInNames();
-
-	return(true);
-}
-/****************************************************/
-/* Actual copying routines							*/
-/****************************************************/
-
-int FindCoords(Coords *coord)
-{
-	int		tx, ty;
-
-	if (coord->x >= 0)
-	{	
-		SetMap(coord);
-		return(true);
-	}
-	else
-	{
-		for (ty = 0; ty < out.ch; ty++)
-		{
-			for (tx = 0; tx < out.cw; tx++)
-			{
-				coord->x = (tx * xcharsize);
-				coord->y = (ty * ycharsize);
-	
-				if (CheckCoords(coord) && !TryPlace(coord))
-				{
-					SetMap(coord);
-					return(true);
-				}
-			}
-		}
-	}
-	coord->x = -1;
-	coord->y = -1;
-
-	return(false);
-}
-
-void CheckBaseline(int i)
-{
-	int		y;
-	long	*pix;
-
-	in[i].baseline = -1;
-	pix = (long *)pixels;
-
-	for(y = 0; y < in[i].h; y++, pix += in[i].w)
-	{
-		if((*pix & 0x00ffffff) == 0x00ff00ff)
-		{
-			in[i].baseline = y;
-			break;
-		}
-	}
-	pix = (long *)pixels;
-	for(y = 0; y < in[i].w * in[i].h; y++, pix++)
-	{
-		if((*pix & 0x00ffffff) == 0x00ff00ff)
-		{
-			*pix = 0;
-		}
-	}
-
-	if(in[i].baseline == -1)
-	{
-		printf("\nERROR : %s has no baseline\n", in[i].name);
-		nobaseline++;
-	}
-}
-
-void	CopyToMain32(Coords *coord)
-{
-	int			x;
-	int			y;
-	long		*source;
-	long		*dest;
-
-	x = coord->x;
-	y = coord->y;
-
-	source = (long *)pixels;
-	dest = (long *)(outpixels + x + (y * out.w));
-
-	for (y = 0; y < coord->h; y++, dest += out.w - coord->w)
-	{
-		for (x = 0; x < coord->w; x++)
-		{
-			*dest++ = *source++;
-		}
-	}
-}
-
-void CreateMain()
-{
-	int			i, count;
-	int			width, height;
-	char		name[128];
-	
-	for (i = 0, count = 0; i < filenum; i++)
-	{
-		if (in[i].depth)
-		{
-			printf("\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline);
-			count++;
-			if (!FindCoords(&in[i]))
-				missed++;
-			else
-			{
-				strcpy(name, sourcedir);
-				strcat(name, in[i].name);
-				LoadAnyImage(name, &pixels, NULL, &width, &height);
-				CheckBaseline(i);
-				CheckOverlap(&in[i]);
-				CopyToMain32(&in[i]);
-				SetUsageMap(&in[i]);
-			}
-		}
-	}
-}
-
-void Cmd_TextureMix()
-{
-	miptex32_t		*qtex32;
-	char			filename[1024];
-	int				size;
-
-	InitVars();
-
-	GetScriptToken (false);
-
-	strcpy(root, token);
-	RemoveExt(root);
-	RemoveLeading(root);
-
-	strcpy(filename, ExpandPathAndArchive(token));
-	if (SetVars(filename))
-	{
-		// Create combined texture
-		percent = ((TotalArea() * 100) / (out.w * out.h));
-		printf("Total area consumed : %d%%\n", percent);
-		printf("Texture resolution  : %dx%d pixels.\n", xcharsize, ycharsize);
-		CreateMain();
-
-		// Save image as m32
-		sprintf (filename, "%spics/misc/%s.m32", gamedir, out.name);
-		qtex32 = CreateMip32((unsigned *)outpixels, out.w, out.h, &size, false);
-
-		qtex32->contents = 0;
-		qtex32->value = 0;
-		qtex32->scale_x = 1.0;
-		qtex32->scale_y = 1.0;
-		sprintf (qtex32->name, "misc/%s", out.name);
-
-		printf ("\n\nwriting %s\n", filename);
-		SaveFile (filename, (byte *)qtex32, size);
-		free (qtex32);
-
-		// Save out script file
-		sprintf (filename, "%spics/misc/%s.fnt", gamedir, outscript);
-		printf("Writing %s as script file\n", filename);
-		if (!SaveScript(filename))
-		{
-			printf("Unable to save output script.\n");
-		}
-	}
-	printf("Everythings groovy.\n");
-	Cleanup();
-}
-
-// end
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qdata.h"
+#include "flex.h"
+
+#define		MAXFILES	2048
+
+typedef	struct
+{
+	int			x;
+	int			y;
+	int			w;
+	int			h;
+	int			cw;
+	int			ch;
+	int			rw;
+	int			index;
+	int			depth;
+	int			col;
+	int			baseline;
+	char		name[128];
+} Coords;
+
+int				filenum;
+int				valid;
+Coords 			in[MAXFILES];
+Coords			out;
+char		  	outscript[256];
+char		  	sourcedir[256];
+char		  	outusage[256];
+char		  	root[32];
+
+int				destsize = 0;
+byte		  	*pixels = NULL;				// Buffer to load image
+long		  	*outpixels = NULL;			// Buffer to store combined textures
+long		  	*usagemap = NULL;			// Buffer of usage map
+void		  	*bmptemp = NULL;			// Buffer of usage map
+byte		  	*map = NULL;
+
+int				xcharsize;
+int				ycharsize;
+int				dosort = 0;
+int				missed = 0;
+int				overlap = 0;
+int				nobaseline = 0;
+int				percent;
+
+//////////////////////////////////////////////////
+// Setting the char based usage map				//
+//////////////////////////////////////////////////
+
+byte	TryPlace(Coords *coord)
+{
+	int		x, y;
+	byte	entry = 0;
+	byte	*mapitem;
+	
+	mapitem = map + (coord->x / xcharsize) + ((coord->y / ycharsize) * out.cw);
+
+	for (y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw)
+	{
+		for (x = 0; x < coord->cw; x++)
+		{
+			if (entry |= *mapitem++ & 8)
+			{
+				return(entry);
+			}
+		}
+	}
+	return(entry);
+}
+
+void	SetMap(Coords *coord)
+{
+	int		x, y;
+	byte	*mapitem;
+
+	mapitem = map + (coord->x / xcharsize) + ((coord->y / ycharsize) * out.cw);
+
+	for (y = 0; y < coord->ch; y++, mapitem += out.cw - coord->cw)
+		for (x = 0; x < coord->cw; x++)
+			*mapitem++ |= 8;
+}
+
+//////////////////////////////////////////////////
+// Setting the pixel based usage map			//
+//////////////////////////////////////////////////
+
+void	CheckOverlap(Coords *coord)
+{
+	int			x;
+	int			y;
+	long		*dest;
+
+	x = coord->x;
+	y = coord->y;
+
+	dest = (long *)(usagemap + x + (y * out.w));
+
+	for (y = 0; y < coord->h; y++, dest += out.w - coord->w)
+	{
+		for (x = 0; x < coord->w; x++)
+		{
+			if (*dest++)
+			{
+				overlap++;
+				return;
+			}
+		}
+	}
+}
+
+void	SetUsageMap(Coords *coord)
+{
+	int			x;
+	int			y;
+	long		*dest;
+
+	x = coord->x;
+	y = coord->y;
+
+	dest = (long *)(usagemap + x + (y * out.w));
+
+	for (y = 0; y < coord->h; y++, dest += out.w - coord->w)
+	{
+		for (x = 0; x < coord->w; x++)
+		{
+			*dest++ = coord->col;
+		}
+	}
+}
+
+//////////////////////////////////////////////////
+// Flips the BMP image to the correct way up	//
+//////////////////////////////////////////////////
+
+void	CopyLine(byte *dest, byte *src, int size)
+{
+	int		x;
+	
+	for (x = 0; x < size; x++)
+		*dest++ = *src++;
+}
+
+/****************************************************/
+/* Printing headers etc								*/
+/****************************************************/
+
+void RemoveLeading(char *name)
+{
+	int		i;
+	char	temp[128];
+
+	for(i = strlen(name) - 1; i > 0; i--)
+	{
+		if((name[i] == '\\') || (name[i] == '/'))
+		{
+			strcpy(temp, name + i + 1);
+			strcpy(name, temp);
+			return;
+		}
+	}
+}
+
+void RemoveExt(char *name)
+{
+	while ((*name != '.') && *name)
+		name++;
+	*name = 0;
+}
+
+/****************************************************/
+/* Misc calcualtions								*/
+/****************************************************/
+
+int	TotalArea()
+{
+	int		i;
+	int		total = 0;
+
+	for (i = 0; i < (filenum + 2); i++)
+		total += in[i].w * in[i].h;
+
+	return(total);
+}
+
+/****************************************************/
+/* Setup and checking of all info					*/
+/****************************************************/
+
+void	InitVars()
+{
+	filenum = 0;
+	valid = 0;
+   	dosort = 0;
+   	missed = 0;
+   	overlap = 0;
+   	nobaseline = 0;
+	
+	memset(outscript, 0, sizeof(outscript));
+	memset(outscript, 0, sizeof(sourcedir));
+	memset(outscript, 0, sizeof(outusage));
+	memset(outscript, 0, sizeof(root));
+
+	memset(in, 0, sizeof(in));
+	memset(&out, 0, sizeof(out));
+}
+void Cleanup()
+{
+	if (pixels)
+		free(pixels);
+	if (usagemap)
+		free(usagemap);
+	if (outpixels)
+		free(outpixels);
+	if (bmptemp)
+		free(bmptemp);
+	if (map)
+		free(map);
+}
+
+typedef struct glxy_s
+{
+	float	xl, yt, xr, yb;
+	int		w, h, baseline;
+} glxy_t;
+
+int	SaveScript(char *name)
+{
+	FILE		*fp;
+	int			i, j;
+	glxy_t		buff;
+	
+	if(fp = fopen(name, "wb"))
+	{
+		for (j = 0; j < filenum; j++)
+		{
+			for (i = 0; i < filenum; i++)
+			{
+				if (in[i].index == j)
+				{
+					if (in[i].depth)
+					{
+						buff.xl = (float)in[i].x / (float)out.w;
+						buff.yt = (float)in[i].y / (float)out.h;
+						buff.xr = ((float)in[i].w + (float)in[i].x) / (float)out.w;
+						buff.yb = ((float)in[i].h + (float)in[i].y) / (float)out.h;
+						buff.w = in[i].w;
+						buff.h = in[i].h;
+						buff.baseline = in[i].baseline;
+					}
+					else
+					{
+						memset(&buff, 0, sizeof(glxy_t));
+					}
+					fwrite(&buff, 1, sizeof(glxy_t), fp);
+					i = filenum;
+				}
+			}
+		}
+		fclose(fp);
+		return(true);
+	}
+	else
+		return(false);
+}
+
+int		GetScriptInfo(char *name)
+{
+	FILE		*fp;
+	char		buffer[256];
+	char		tempbuff[256];
+	char		delims[] = {" \t,\n"};
+
+	printf("Opening script file %s.\n", name);
+
+	if (fp = fopen(name, "r"))
+	{
+		while(fgets(buffer, 256, fp))
+		{
+			if (strncmp(buffer, "//", 2) && strncmp(buffer, "\n", 1))
+			{
+				strupr(buffer);
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "OUTPUT") == 0)
+				{
+					strcpy(out.name, strtok(NULL, delims));
+					strlwr(out.name);
+				}
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "SOURCEDIR") == 0)
+				{
+					strcpy(tempbuff, strtok(NULL, delims));
+					strcpy(sourcedir, ExpandPathAndArchive(tempbuff));
+				}
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "DOSORT") == 0)
+					dosort = 1;
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "XCHARSIZE") == 0)
+					xcharsize = strtol(strtok(NULL, delims), NULL, 0);
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "YCHARSIZE") == 0)
+					ycharsize = strtol(strtok(NULL, delims), NULL, 0);
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "OUTSCRIPT") == 0)
+				{
+					strcpy(outscript, strtok(NULL, delims));
+					strlwr(outscript);
+				}
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "OUTUSAGE") == 0)
+					strcpy(outusage, strtok(NULL, delims));
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "POS") == 0)
+				{
+					out.w = strtol(strtok(NULL, delims), NULL, 0);
+			 		out.h = strtol(strtok(NULL, delims), NULL, 0);
+				}
+
+				strcpy(tempbuff, buffer);
+				if (strcmp(strtok(tempbuff, delims), "FILE") == 0)
+				{
+					strcpy(in[filenum].name, strtok(NULL, delims));
+					in[filenum].x = strtol(strtok(NULL, delims), NULL, 0);
+					in[filenum].y = strtol(strtok(NULL, delims), NULL, 0);
+					in[filenum].col = strtol(strtok(NULL, delims), NULL, 0);
+					filenum++;
+				}
+			}
+		}
+		fclose(fp);
+		return(true);
+	}
+	else
+	{
+		printf("ERROR : Could not open script file.\n");
+		return(false);
+	}
+}
+
+int	CheckVars()
+{
+	int		i;
+
+	 if (out.name[0] == 0)
+	 {
+	 	printf("ERROR : No output name specified.\n");
+		return(false);
+	}
+	if ((out.w <= 0) || (out.h <= 0))
+	{
+		printf("ERROR : Invalid VRAM coordinates.\n");
+		return(false);
+	}
+	if (filenum == 0)
+	{
+		printf("ERROR : No input files specified.\n");
+		return(false);
+	}
+	for (i = 0; i < filenum; i++)
+		if (in[i].name[0] == 0)
+		{
+			printf("ERROR : Input filename invalid.\n");
+			return(false);
+		}
+	return(true);
+}
+
+// Makes sure texture is totally within the output area
+
+int	CheckCoords(Coords *coord)
+{
+	if ((coord->x + coord->w) > out.w)
+		return(false);
+	if ((coord->y + coord->h) > out.h)
+		return(false);
+
+	return(true);
+}
+// Gets the width, height, palette width and palette height of each BMP file
+
+int		GetFileDimensions()
+{
+	int			i;
+	int			width, height;
+	char		name[128];
+
+	for (i = 0; i < filenum; i++)
+	{
+		in[i].index = i;
+
+		strcpy(name, sourcedir);
+		strcat(name, in[i].name);
+		printf("Getting file dimensions, file : %s        \r", in[i].name);
+		if(FileExists(name))
+		{
+			LoadAnyImage(name, NULL, NULL, &width, &height);
+			in[i].depth = 32;
+			in[i].rw = width;
+			in[i].w = width;					 	// makes it width in 
+			in[i].h = height;
+			in[i].cw = (in[i].w + (xcharsize - 1)) / xcharsize;
+			in[i].ch = (in[i].h + (ycharsize - 1)) / ycharsize;
+
+			if (!CheckCoords(&in[i]) && (in[i].x >= 0))
+			{
+			 	printf("Error : texture %s out of bounds.\n", in[i].name);
+				return(false);
+			}
+			valid++;
+		}
+		else
+		{
+			in[i].depth = 0;
+			in[i].x = -1;
+			in[i].y = -1;
+			in[i].w = 0;
+			in[i].h = 0;
+		}
+	}
+	printf("\n\n");
+	return(true);
+}
+
+// Sorts files into order for optimal space finding
+// Fixed position ones first, followed by the others in descending size
+// The theory being that it is easier to find space for smaller textures.
+// size = (width + height)
+// For space finding it is easier to place a 32x32 than a 128x2
+
+#define	WEIGHT	0x8000
+
+void	Swap(Coords *a, Coords *b)
+{
+	Coords		c;
+
+	c = *a;
+	*a = *b;
+	*b = c;
+}
+
+void	SortInNames()
+{
+	int		i, j;
+	int		largest, largcount;
+	int		size;
+
+	printf("Sorting filenames by size.\n\n");
+
+	for (j = 0; j < filenum; j++)
+	{
+		largest = -1;
+		largcount = -1;
+
+		for (i = j; i < filenum; i++)
+		{
+			if (in[i].depth)
+			{
+				size = in[i].w + in[i].h;
+		
+				if ((in[i].x < 0) && (size > largest))
+				{
+					largcount = i;
+					largest = size;
+				}
+			}
+		}
+		if ((largcount >= 0) && (largcount != j))
+			Swap(&in[j], &in[largcount]);
+	}
+}
+
+int	SetVars(char *name)
+{
+	if (!GetScriptInfo(name))
+		return(false);
+
+	if (!CheckVars())
+		return(false);
+
+	destsize = out.w * out.h;
+
+	out.cw = out.w / xcharsize;
+	out.ch = out.h / ycharsize;
+
+	if ((usagemap = (long *)SafeMalloc(destsize * 4, "")) == NULL)
+		return(false);
+	if ((outpixels = (long *)SafeMalloc(destsize * 4, "")) == NULL)
+		return(false); 
+	if ((bmptemp = (void *)SafeMalloc(destsize * 4, "")) == NULL)
+		return(false);
+	if ((map = (byte *)SafeMalloc(destsize / (xcharsize * ycharsize), "")) == NULL)
+		return(false);
+
+	if (GetFileDimensions() == false)
+		return(false);
+
+	if (dosort)
+		SortInNames();
+
+	return(true);
+}
+/****************************************************/
+/* Actual copying routines							*/
+/****************************************************/
+
+int FindCoords(Coords *coord)
+{
+	int		tx, ty;
+
+	if (coord->x >= 0)
+	{	
+		SetMap(coord);
+		return(true);
+	}
+	else
+	{
+		for (ty = 0; ty < out.ch; ty++)
+		{
+			for (tx = 0; tx < out.cw; tx++)
+			{
+				coord->x = (tx * xcharsize);
+				coord->y = (ty * ycharsize);
+	
+				if (CheckCoords(coord) && !TryPlace(coord))
+				{
+					SetMap(coord);
+					return(true);
+				}
+			}
+		}
+	}
+	coord->x = -1;
+	coord->y = -1;
+
+	return(false);
+}
+
+void CheckBaseline(int i)
+{
+	int		y;
+	long	*pix;
+
+	in[i].baseline = -1;
+	pix = (long *)pixels;
+
+	for(y = 0; y < in[i].h; y++, pix += in[i].w)
+	{
+		if((*pix & 0x00ffffff) == 0x00ff00ff)
+		{
+			in[i].baseline = y;
+			break;
+		}
+	}
+	pix = (long *)pixels;
+	for(y = 0; y < in[i].w * in[i].h; y++, pix++)
+	{
+		if((*pix & 0x00ffffff) == 0x00ff00ff)
+		{
+			*pix = 0;
+		}
+	}
+
+	if(in[i].baseline == -1)
+	{
+		printf("\nERROR : %s has no baseline\n", in[i].name);
+		nobaseline++;
+	}
+}
+
+void	CopyToMain32(Coords *coord)
+{
+	int			x;
+	int			y;
+	long		*source;
+	long		*dest;
+
+	x = coord->x;
+	y = coord->y;
+
+	source = (long *)pixels;
+	dest = (long *)(outpixels + x + (y * out.w));
+
+	for (y = 0; y < coord->h; y++, dest += out.w - coord->w)
+	{
+		for (x = 0; x < coord->w; x++)
+		{
+			*dest++ = *source++;
+		}
+	}
+}
+
+void CreateMain()
+{
+	int			i, count;
+	int			width, height;
+	char		name[128];
+	
+	for (i = 0, count = 0; i < filenum; i++)
+	{
+		if (in[i].depth)
+		{
+			printf("\rProcessing %d of %d (%d missed, %d overlapping, %d nobase)\r", count + 1, valid, missed, overlap, nobaseline);
+			count++;
+			if (!FindCoords(&in[i]))
+				missed++;
+			else
+			{
+				strcpy(name, sourcedir);
+				strcat(name, in[i].name);
+				LoadAnyImage(name, &pixels, NULL, &width, &height);
+				CheckBaseline(i);
+				CheckOverlap(&in[i]);
+				CopyToMain32(&in[i]);
+				SetUsageMap(&in[i]);
+			}
+		}
+	}
+}
+
+void Cmd_TextureMix()
+{
+	miptex32_t		*qtex32;
+	char			filename[1024];
+	int				size;
+
+	InitVars();
+
+	GetScriptToken (false);
+
+	strcpy(root, token);
+	RemoveExt(root);
+	RemoveLeading(root);
+
+	strcpy(filename, ExpandPathAndArchive(token));
+	if (SetVars(filename))
+	{
+		// Create combined texture
+		percent = ((TotalArea() * 100) / (out.w * out.h));
+		printf("Total area consumed : %d%%\n", percent);
+		printf("Texture resolution  : %dx%d pixels.\n", xcharsize, ycharsize);
+		CreateMain();
+
+		// Save image as m32
+		sprintf (filename, "%spics/misc/%s.m32", gamedir, out.name);
+		qtex32 = CreateMip32((unsigned *)outpixels, out.w, out.h, &size, false);
+
+		qtex32->contents = 0;
+		qtex32->value = 0;
+		qtex32->scale_x = 1.0;
+		qtex32->scale_y = 1.0;
+		sprintf (qtex32->name, "misc/%s", out.name);
+
+		printf ("\n\nwriting %s\n", filename);
+		SaveFile (filename, (byte *)qtex32, size);
+		free (qtex32);
+
+		// Save out script file
+		sprintf (filename, "%spics/misc/%s.fnt", gamedir, outscript);
+		printf("Writing %s as script file\n", filename);
+		if (!SaveScript(filename))
+		{
+			printf("Unable to save output script.\n");
+		}
+	}
+	printf("Everythings groovy.\n");
+	Cleanup();
+}
+
+// end
+
diff --git a/tools/quake2/qdata_heretic2/video.c b/tools/quake2/qdata_heretic2/video.c
index b41c6598..b4ed1a6f 100644
--- a/tools/quake2/qdata_heretic2/video.c
+++ b/tools/quake2/qdata_heretic2/video.c
@@ -1,1149 +1,1149 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// To do
-
-// Sound error handling (when sound too short)
-// rle b4 huffing
-// adpcm encoding of sound
-
-#if	0
-#include "qdata.h"
-#include "flex.h"
-#include "fc.h"
-#include "adpcm.h"
-
-#define	MIN_REPT	15
-#define	MAX_REPT	0
-#define	HUF_TOKENS	(256 + MAX_REPT)
-
-#define BLOCKSIZE	8
-
-#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
-#define SQRT2		1.414213562
-
-typedef struct hnode_s
-{
-	int			count;
-	qboolean	used;
-	int			children[2];
-} hnode_t;
-
-typedef struct
-{
-	int			rate;
-	int			width;
-	int			channels;
-	int			loopstart;
-	int			samples;
-	int			dataofs;		// chunk starts this many bytes from file start
-} wavinfo_t;
-
-// These weren`t picked out my ass....
-// They were defined at http://www.rahul.net/jfm/dct.html
-// However, I think he plucked them out of his ass.....
-
-float Quantise[BLOCKSIZE * BLOCKSIZE];
-
-float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] =
-{
-	16.0F/16.0F, 11.0F/16.0F, 10.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 51.0F/16.0F, 61.0F/16.0F,
-	12.0F/16.0F, 13.0F/16.0F, 14.0F/16.0F, 19.0F/16.0F, 26.0F/16.0F, 58.0F/16.0F, 60.0F/16.0F, 55.0F/16.0F,
-	14.0F/16.0F, 13.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 57.0F/16.0F, 69.0F/16.0F, 56.0F/16.0F,
-	14.0F/16.0F, 17.0F/16.0F, 22.0F/16.0F, 29.0F/16.0F, 51.0F/16.0F, 87.0F/16.0F, 80.0F/16.0F, 62.0F/16.0F,
-	18.0F/16.0F, 22.0F/16.0F, 37.0F/16.0F, 56.0F/16.0F, 68.0F/16.0F,109.0F/16.0F,103.0F/16.0F, 77.0F/16.0F,
-	24.0F/16.0F, 35.0F/16.0F, 55.0F/16.0F, 64.0F/16.0F, 81.0F/16.0F,104.0F/16.0F,113.0F/16.0F, 92.0F/16.0F,
-	49.0F/16.0F, 64.0F/16.0F, 78.0F/16.0F, 87.0F/16.0F,103.0F/16.0F,121.0F/16.0F,120.0F/16.0F,101.0F/16.0F,
-	72.0F/16.0F, 92.0F/16.0F, 95.0F/16.0F, 98.0F/16.0F,112.0F/16.0F,100.0F/16.0F,103.0F/16.0F, 99.0F/16.0F
-};
-
-int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] =
-{
-	 0,
-	 1,  8, 
-	16,  9,  2,
-	 3, 10, 17, 24,
-	32, 25, 18, 11,  4,
-	 5, 12, 19, 26, 33, 40,
-	48, 41, 34, 27, 20, 13, 6,
-	 7, 14, 21, 28, 35, 42, 49, 56,
-	57, 50, 43, 36, 29, 22, 15,
-	23, 30, 37, 44, 51, 58,
-	59, 52, 45, 38, 31, 
-	39, 46, 53, 60,
-	61, 54, 47,
-	55, 62, 
-	63
-};
-
-char			base[32];
-
-byte			*soundtrack;
-
-byte			scaled[256][HUF_TOKENS];
-unsigned int	charbits1[256][HUF_TOKENS];
-int				charbitscount1[256][HUF_TOKENS];
-hnode_t			hnodes1[256][HUF_TOKENS * 2];
-int				numhnodes1[256];
-int				order0counts[256];
-int				numhnodes;
-hnode_t			hnodes[512];
-unsigned		charbits[256];
-int				charbitscount[256];
-
-CineHead_t		cinehead;
-
-byte			*data_p;
-byte			*iff_end;
-byte			*last_chunk;
-byte			*iff_data;
-int				iff_chunk_len;
-
-float			dctbase[BLOCKSIZE][BLOCKSIZE];
-float			red[BLOCKSIZE * BLOCKSIZE];
-float			green[BLOCKSIZE * BLOCKSIZE];
-float			blue[BLOCKSIZE * BLOCKSIZE];
-float			temp[BLOCKSIZE * BLOCKSIZE];
-
-wavinfo_t		wavinfo;
-adpcm_t			adpcm;
-
-/*
-===============================================================================
-
-WAV loading
-
-===============================================================================
-*/
-
-/* Intel ADPCM step variation table */
-static int indexTable[16] = 
-{
-	-1, -1, -1, -1, 2, 4, 6, 8,
-	-1, -1, -1, -1, 2, 4, 6, 8,
-};
-
-static int stepsizeTable[89] = 
-{
-	7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
-	19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
-	50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
-	130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
-	337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
-	876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
-	2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
-	5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
-	15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
-};
-
-#if	0
-static void adpcm_decoder(char *indata, short *outdata, int len, adpcm_state_t *state)
-{
-	signed char *inp;		/* Input buffer pointer */
-	short *outp;		/* output buffer pointer */
-	int sign;			/* Current adpcm sign bit */
-	int delta;			/* Current adpcm output value */
-	int step;			/* Stepsize */
-	int valpred;		/* Predicted value */
-	int vpdiff; 		/* Current change to valpred */
-	int index;			/* Current step change index */
-	int inputbuffer;		/* place to keep next 4-bit value */
-	int bufferstep; 	/* toggle between inputbuffer/input */
-
-	outp = outdata;
-	inp = (signed char *)indata;
-
-	valpred = state->valprev;
-	index = state->index;
-	step = stepsizeTable[index];
-
-	bufferstep = 0;
-	
-	for(; len > 0; len--)
-	{
-		/* Step 1 - get the delta value */
-		if (bufferstep)
-			delta = inputbuffer & 0xf;
-		else
-		{
-			inputbuffer = *inp++;
-			delta = (inputbuffer >> 4) & 0xf;
-		}
-		bufferstep = !bufferstep;
-
-		/* Step 2 - Find new index value (for later) */
-		index += indexTable[delta];
-		if(index < 0)
-			index = 0;
-		if(index > 88)
-			index = 88;
-
-		/* Step 3 - Separate sign and magnitude */
-		sign = delta & 8;
-		delta = delta & 7;
-
-		/* Step 4 - Compute difference and new predicted value */
-		/*
-		** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
-		** in adpcm_coder.
-		*/
-		vpdiff = step >> 3;
-		if(delta & 4)
-			vpdiff += step;
-		if(delta & 2)
-			vpdiff += step>>1;
-		if(delta & 1)
-			vpdiff += step>>2;
-
-		if (sign)
-		  valpred -= vpdiff;
-		else
-		  valpred += vpdiff;
-
-		/* Step 5 - clamp output value */
-		if (valpred > 32767)
-		  valpred = 32767;
-		else if (valpred < -32768)
-		  valpred = -32768;
-
-		/* Step 6 - Update step value */
-		step = stepsizeTable[index];
-
-		/* Step 7 - Output value */
-		*outp++ = valpred;
-	}
-
-	state->valprev = valpred;
-	state->index = index;
-}
-#endif
-
-void adpcm_coder(short *inp, adpcm_t *adpcm)
-{
-	int				val;			/* Current input sample value */
-	int				sign;			/* Current adpcm sign bit */
-	int				delta;			/* Current adpcm output value */
-	int				diff;			/* Difference between val and valprev */
-	int				step;			/* Stepsize */
-	int				valpred;		/* Predicted output value */
-	int				vpdiff; 		/* Current change to valpred */
-	int				index;			/* Current step change index */
-	int				outputbuffer;  	/* place to keep previous 4-bit value */
-	int				bufferstep; 	/* toggle between outputbuffer/output */
-	adpcm_state_t	*state;
-	char			*outp;
-	int				len;
-
-	state = &adpcm->state;
-	len = state->count;
-	outp = adpcm->adpcm;
-
-	valpred = state->in_valprev;
-	index = state->in_index;
-	step = stepsizeTable[index];
-	
-	bufferstep = 1;
-	while(len--)
-	{
-		val = *inp++;
-
-		/* Step 1 - compute difference with previous value */
-		diff = val - valpred;
-		sign = (diff < 0) ? 8 : 0;
-		if (sign)
-			diff = -diff;
-
-		/* Step 2 - Divide and clamp */
-		/* Note:
-		** This code *approximately* computes:
-		**	  delta = diff*4/step;
-		**	  vpdiff = (delta+0.5)*step/4;
-		** but in shift step bits are dropped. The net result of this is
-		** that even if you have fast mul/div hardware you cannot put it to
-		** good use since the fixup would be too expensive.
-		*/
-		delta = 0;
-		vpdiff = (step >> 3);
-		
-		if (diff >= step)
-		{
-			delta = 4;
-			diff -= step;
-			vpdiff += step;
-		}
-		step >>= 1;
-		if (diff >= step)
-		{
-			delta |= 2;
-			diff -= step;
-			vpdiff += step;
-		}
-		step >>= 1;
-		if (diff >= step)
-		{
-			delta |= 1;
-			vpdiff += step;
-		}
-
-		/* Step 3 - Update previous value */
-		if (sign)
-		  valpred -= vpdiff;
-		else
-		  valpred += vpdiff;
-
-		/* Step 4 - Clamp previous value to 16 bits */
-		if (valpred > 32767)
-		  valpred = 32767;
-		else if (valpred < -32768)
-		  valpred = -32768;
-
-		/* Step 5 - Assemble value, update index and step values */
-		delta |= sign;
-		
-		index += indexTable[delta];
-		if (index < 0)
-			index = 0;
-		if (index > 88)
-			index = 88;
-		step = stepsizeTable[index];
-
-		/* Step 6 - Output value */
-		if (bufferstep)
-			outputbuffer = (delta << 4) & 0xf0;
-		else
-			*outp++ = (delta & 0x0f) | outputbuffer;
-
-		bufferstep = !bufferstep;
-	}
-
-	/* Output last step, if needed */
-	if(!bufferstep)
-	  *outp++ = outputbuffer;
-	
-	state->out_valprev = valpred;
-	state->out_index = index;
-}
-
-void FindNextChunk(char *name)
-{
-	while(1)
-	{
-		data_p = last_chunk;
-
-		if(data_p >= iff_end)
-		{								// didn't find the chunk
-			data_p = NULL;
-			return;
-		}
-		
-		data_p += 4;
-		iff_chunk_len = *(long *)data_p;
-		data_p += 4;
-		if(iff_chunk_len < 0)
-		{
-			data_p = NULL;
-			return;
-		}
-
-		data_p -= 8;
-		last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1);
-		if (!strncmp(data_p, name, 4))
-			return;
-	}
-}
-
-void FindChunk(char *name)
-{
-	last_chunk = iff_data;
-	FindNextChunk (name);
-}
-
-void DumpChunks(void)
-{
-	char	str[5];
-	
-	str[4] = 0;
-	data_p = iff_data;
-	do
-	{
-		memcpy (str, data_p, 4);
-		data_p += 4;
-		iff_chunk_len = *(long *)data_p;
-		data_p += 4;
-		printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
-		data_p += (iff_chunk_len + 1) & ~1;
-	}
-	while(data_p < iff_end);
-}
-
-/*
-============
-GetWavinfo
-============
-*/
-wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
-{
-	wavinfo_t	info;
-	int			i;
-	int			format;
-	int			samples;
-
-	memset(&info, 0, sizeof(info));
-
-	if (!wav)
-		return(info);
-		
-	iff_data = wav;
-	iff_end = wav + wavlength;
-
-// find "RIFF" chunk
-	FindChunk("RIFF");
-	if (!(data_p && !strncmp(data_p + 8, "WAVE", 4)))
-	{
-		printf("Missing RIFF/WAVE chunks\n");
-		return(info);
-	}
-
-// get "fmt " chunk
-	iff_data = data_p + 12;
-
-	FindChunk("fmt ");
-	if(!data_p)
-	{
-		printf("Missing fmt chunk\n");
-		return(info);
-	}
-	data_p += 8;
-	format = *(short *)data_p;
-	data_p += 2;
-	if (format != 1)
-	{
-		printf("Microsoft PCM format only\n");
-		return(info);
-	}
-
-	info.channels = *(short *)data_p;
-	data_p += 2;
-	info.rate = *(long *)data_p;
-	data_p += 4;
-	data_p += 6;
-	info.width = *(short *)data_p / 8;
-	data_p += 2;
-
-// get cue chunk
-	FindChunk("cue ");
-	if(data_p)
-	{
-		data_p += 32;
-		info.loopstart = *(long *)data_p;
-		data_p += 4;
-
-// if the next chunk is a LIST chunk, look for a cue length marker
-		FindNextChunk ("LIST");
-		if(data_p)
-		{
-// this is not a proper parse, but it works with cooledit...
-			if (!strncmp (data_p + 28, "mark", 4))
-			{
-				data_p += 24;
-				i = *(long *)data_p;					// samples in loop
-				data_p += 4;
-				info.samples = info.loopstart + i;
-			}
-		}
-	}
-	else
-		info.loopstart = -1;
-
-// find data chunk
-	FindChunk("data");
-	if (!data_p)
-	{
-		printf("Missing data chunk\n");
-		return(info);
-	}
-
-	data_p += 4;
-	samples = *(long *)data_p;
-	data_p += 4;
-
-	if (info.samples)
-	{
-		if(samples < info.samples)
-			Error ("Sound %s has a bad loop length", name);
-	}
-	else
-		info.samples = samples;
-
-	info.dataofs = data_p - wav;
-	return(info);
-}
-
-// ==============
-// LoadSoundtrack
-// ==============
-
-void LoadSoundtrack()
-{
-	char	name[1024];
-	FILE	*f;
-	int		len;
-
-	soundtrack = NULL;
-	sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
-	printf ("\nLoading sound    : %s\n", name);
-	f = fopen (name, "rb");
-	if (!f)
-	{
-		printf ("\nNo soundtrack for %s\n", base);
-		return;
-	}
-	len = Q_filelength(f);
-	soundtrack = SafeMalloc(len, "LoadSoundtrack");
-	fread(soundtrack, 1, len, f);
-	fclose(f);
-
-	wavinfo = GetWavinfo(name, soundtrack, len);
-	adpcm.state.out_valprev = 0;
-	adpcm.state.out_index = 0;
-}
-
-// ==================
-// WriteSound
-// ==================
-
-int WriteSound(FILE *output, int frame, int numframes)
-{
-	int		start, end;
-	int		count;
-	int		empty = 0;
-	int		width;
-	char	*work;
-
-	width = wavinfo.width * wavinfo.channels;
-	start = ((frame * wavinfo.rate / 14) + 31) & 0xffffffe0;				// start sample
-	end = (((frame + numframes) * wavinfo.rate / 14) + 31) & 0xffffffe0;	// end sample
-	count = end - start;
-
-	work = soundtrack + wavinfo.dataofs + (start * width);
-	adpcm.state.count = count * wavinfo.channels;			// Number of samples
-	adpcm.state.in_valprev = adpcm.state.out_valprev;
-	adpcm.state.in_index = adpcm.state.out_index;
-	adpcm_coder((short *)work, &adpcm);
-	WriteHeader(output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, (adpcm.state.count / 2) + sizeof(adpcm_state_t), (char *)&adpcm);
-	return(count / 2);
-}
-// ==============================
-// Basic run length encoder
-// ==============================
-
-char *RLEZZ(char *in, char *out)
-{
-	int		srun;
-	char	count;
-	int		idx = 0;
-
-	while(idx < 64)
-	{
-		srun = idx;								// Start of run
-
-		while(idx < 63)
-		{
-			if(in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]])
-				break;
-			idx++;
-		}
-		count = (char)(idx - srun);				// count of repeated bytes
-
-		if(!count)
-		{
-			while(idx < 63)
-			{
-				if(in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]])
-					break;
-				idx++;
-			}
-			if(idx == 63)
-				idx++;
-
-			count = (char)(idx - srun);			// count of unique bytes
-			*out++ = count;
-			while(count--)
-				*out++ = in[LUT_ZZ[srun++]];
-		}
-		else
-		{
-			*out++ = -(count + 1);
-			*out++ = in[LUT_ZZ[idx]];
-			idx++;
-		}
-	}
-	return(out);
-}
-
-// ==============================
-// Discrete Cosine Transformation
-// ==============================
-
-void init_base(float quant)
-{
-	int			y, x;
-
-	for(y = 0; y < BLOCKSIZE; y++)
-		for(x = 0; x < BLOCKSIZE; x++)
-		{
-			if(y == 0)
-				dctbase[y][x] = 1;
-			else
-				dctbase[y][x] = SQRT2 * cos(((x * 2 + 1) * y * M_PI) / (BLOCKSIZE * 2));
-		}
-
-	for(y = 0; y < BLOCKSIZE * BLOCKSIZE; y++)
-		Quantise[y] = LUT_Quantise[y] / quant;
-}
-
-void SplitComponents(byte *src, int width, int height)
-{
-	int		i, j;
-	float	*tr = red;
-	float	*tg = green;
-	float	*tb = blue;
-
-	for(i = 0; i < BLOCKSIZE; i++, src += (width - BLOCKSIZE) * 4)
-		for(j = 0; j < BLOCKSIZE; j++)
-		{
-			*tr++ = ((float)*src++) - 128.0F;
-			*tg++ = ((float)*src++) - 128.0F;
-			*tb++ = ((float)*src++) - 128.0F;
-			src++;
-		}
-}
-
-void transferH(float *src, float *dst)
-{
-	int		y, dx, dy;
-	float	sum;
-	float	*work;
-
-	for(y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE)
-	{
-		for(dy = 0; dy < BLOCKSIZE; dy++)
-		{
-			sum = 0;
-			work = src;
-			for(dx = 0; dx < BLOCKSIZE; dx++, work++)
-				sum += dctbase[dy][dx] * *work;
-
-			*dst++ = sum / BLOCKSIZE;
-		}
-	}
-}
-
-void transferV(float *src, float *dst)
-{
-	int		x, dy, fy;
-	float	sum;
-	float	*work;
-
-	for(x = 0; x < BLOCKSIZE; x++, src++, dst++)
-	{
-		for(fy = 0; fy < BLOCKSIZE; fy++)
-		{
-			sum = 0;
-			work = src;
-			for(dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE)
-				sum += dctbase[fy][dy] * *work;
-
-			dst[fy * BLOCKSIZE] = sum / BLOCKSIZE;
-		}
-	}
-}
-
-char *Combine(byte *dst, float *p, float *q)
-{
-	int		i, j;
-	byte	rlesrc[BLOCKSIZE * BLOCKSIZE];
- 	int		c;
-	byte	*work;
-
-	work = rlesrc;
-	for(j = 0; j < BLOCKSIZE; j++)
-		for(i = 0; i < BLOCKSIZE; i++)
-		{
-			c = (int)((*p++ / *q++) + 128.5F);
-			c -= 128;
-
-			if(c < -128)
-				c = -128;
-			if(c > 127)
-				c = 127;
-
-			*work++ = (char)c;
-		}
-
-	dst = RLEZZ(rlesrc, dst);
-	return(dst);
-}
-
-char *CombineComponents(char *dst, int width, int height)
-{
-	dst = Combine(dst, red, Quantise);
-	dst = Combine(dst, green, Quantise);
-	dst = Combine(dst, blue, Quantise);
-	return(dst);
-}
-
-void DCT(cblock_t *out, cblock_t in, int width, int height)
-{
-	int		x, y;
-	char	*cursrc;
-	char	*curdst;
-
-	curdst = out->data;
-	for(y = 0; y < height; y += BLOCKSIZE)
-		for(x = 0; x < width; x += BLOCKSIZE)
-		{
-			cursrc = in.data + ((y * width) + x) * 4;
-			SplitComponents(cursrc, width, height);
-			transferH(red, temp);
-			transferV(temp, red);
-			transferH(green, temp);
-			transferV(temp, green);
-			transferH(blue, temp);
-			transferV(temp, blue);
-			curdst = CombineComponents(curdst, width, height);
-		}
-	out->count = curdst - out->data;
-}
-
-// ==================
-// BuildChars1
-// ==================
-
-void BuildChars1(int prev, int nodenum, unsigned bits, int bitcount)
-{
-	hnode_t		*node;
-
-	if(nodenum < HUF_TOKENS)
-	{
-		if (bitcount > 32)
-			Error("bitcount > 32");
-		charbits1[prev][nodenum] = bits;
-		charbitscount1[prev][nodenum] = bitcount;
-		return;
-	}
-
-	node = &hnodes1[prev][nodenum];
-	bits <<= 1;
-	BuildChars1(prev, node->children[0], bits, bitcount+1);
-	bits |= 1;
-	BuildChars1(prev, node->children[1], bits, bitcount+1);
-}
-
-// ==================
-// SmallestNode1
-// ==================
-
-int	SmallestNode1(hnode_t *hnodes, int numhnodes)
-{
-	int		i;
-	int		best, bestnode;
-
-	best = 99999999;
-	bestnode = -1;
-	for(i = 0; i < numhnodes; i++)
-	{
-		if(hnodes[i].used)
-			continue;
-		if(!hnodes[i].count)
-			continue;
-		if(hnodes[i].count < best)
-		{
-			best = hnodes[i].count;
-			bestnode = i;
-		}
-	}
-
-	if (bestnode == -1)
-		return(-1);
-
-	hnodes[bestnode].used = true;
-	return(bestnode);
-}
-
-// ==================
-// BuildTree1
-// ==================
-
-void BuildTree1(int prev)
-{
-	hnode_t		*node, *nodebase;
-	int			numhnodes;
-
-	// build the nodes
-	numhnodes = HUF_TOKENS;
-	nodebase = hnodes1[prev];
-	while(1)
-	{
-		node = &nodebase[numhnodes];
-
-		// pick two lowest counts
-		node->children[0] = SmallestNode1 (nodebase, numhnodes);
-		if (node->children[0] == -1)
-			break;	// no more
-
-		node->children[1] = SmallestNode1 (nodebase, numhnodes);
-		if (node->children[1] == -1)
-			break;
-
-		node->count = nodebase[node->children[0]].count + 
-			nodebase[node->children[1]].count;
-		numhnodes++;
-	}
-	numhnodes1[prev] = numhnodes-1;
-	BuildChars1 (prev, numhnodes-1, 0, 0);
-}
-
-// ==================
-// Huffman1_Count
-// ==================
-
-void Huffman1_Count(cblock_t in)
-{
-	int		i;
-	int		prev;
-	int		v;
-	int		rept;
-
-	prev = 0;
-	for(i = 0; i < in.count; i++)
-	{
-		v = in.data[i];
-		order0counts[v]++;
-		hnodes1[prev][v].count++;
-		prev = v;
-
-		for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
-			if(in.data[i+rept] != v)
-				break;
-		if(rept > MIN_REPT)
-		{
-			hnodes1[prev][255 + rept].count++;
-			i += rept - 1;
-		}
-	}
-}
-
-// ==================
-// Huffman1_Build
-// ==================
-
-void Huffman1_Build()
-{
-	int		i, j, v;
-	int		max;
-	int		total;
-
-	for(i = 0; i < 256; i++)
-	{
-// normalize and save the counts
-		max = 0;
-		for (j = 0; j < HUF_TOKENS; j++)
-		{
-			if (hnodes1[i][j].count > max)
-				max = hnodes1[i][j].count;
-		}
-		if (max == 0)
-			max = 1;
-		total = 0;
-// easy to overflow 32 bits here!
-		for(j = 0; j < HUF_TOKENS; j++)
-		{
-			v = (hnodes1[i][j].count * (double) 255 + max - 1) / max;
-			if (v > 255)
-				Error ("v > 255");
-			scaled[i][j] = hnodes1[i][j].count = v;
-			if (v)
-				total++;
-		}
-		if (total == 1)
-		{	// must have two tokens
-			if (!scaled[i][0])
-				scaled[i][0] = hnodes1[i][0].count = 1;
-			else
-				scaled[i][1] = hnodes1[i][1].count = 1;
-		}
-		BuildTree1 (i);
-	}
-}
-
-// ==================
-// Huffman1
-// Order 1 compression with pre-built table
-// ==================
-
-cblock_t Huffman1(cblock_t in)
-{
-	int			i;
-	int			outbits, c;
-	unsigned	bits;
-	byte		*out_p;
-	cblock_t	out;
-	int			prev;
-	int			v;
-	int			rept;
-
-	out_p = out.data = SafeMalloc((in.count * 2) + 1024 + 4, "Huffman");
-	memset(out_p, 0, (in.count * 2) + 1024 + 4);
-
-	// leave space for compressed count
-	out_p += 4;
-	// write count
-	*(long *)out_p = in.count;
-	out_p += 4;
-
-	// write bits
-	outbits = 0;
-	prev = 0;
-	for(i = 0; i < in.count; i++)
-	{
-		v = in.data[i];
-
-		c = charbitscount1[prev][v];
-		bits = charbits1[prev][v];
-		if (!c)
-			Error ("!bits");
-		while (c)
-		{
-			c--;
-			if (bits & (1 << c))
-				out_p[outbits>>3] |= 1 << (outbits & 7);
-			outbits++;
-		}
-
-		prev = v;
-		// check for repeat encodes
-		for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
-			if(in.data[i + rept] != v)
-				break;
-		if (rept > MIN_REPT)
-		{
-			c = charbitscount1[prev][255 + rept];
-			bits = charbits1[prev][255 + rept];
-			if (!c)
-				Error ("!bits");
-			while (c)
-			{
-				c--;
-				if(bits & (1 << c))
-					out_p[outbits >> 3] |= 1 << (outbits & 7);
-				outbits++;
-			}
-			i += rept - 1;
-		}
-	}
-	out_p += (outbits + 7) >> 3;
-	out.count = out_p - out.data;
-
-	out_p = out.data;
-	*(long *)out_p = out.count;
-	return(out);
-}
-// ===================
-// LoadFrame
-// ===================
-
-void LoadFrame(cblock_t *out, char *base, int frame)
-{
-	cblock_t	in;
-	int			width, height;
-	char		name[1024];
-	FILE		*f;
-
-	in.data = NULL;
-	in.count = -1;
-	sprintf (name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame);
-
-	f = fopen(name, "rb");
-	if (!f)
-	{
-		out->data = NULL;
-		return;
-	}
-	fclose (f);
-
-	LoadTGA(name, &in.data, &width, &height);
-	if((width != cinehead.Width) || (height != cinehead.Height))
-	{
-		free(in.data);
-		printf("Invalid picture size\n");
-		out->data = NULL;
-		return;
-	}
-	out->data = SafeMalloc(width * height * 3, "LoadFrame");		// rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression)
-	DCT(out, in, width, height);
-	free(in.data);
-}
-
-// ==================================
-// Cmd_Video
-// 
-// video <directory> <framedigits>
-// ==================================
-
-void Cmd_Video()
-{
-	char		savename[256];
-	char		name[256];
-	FILE		*output;
-	int			frame;
-	int			width, height;
-	cblock_t	in, huffman;
-	int			size;
-	float		dctconst;
-	int			maxsize, ssize;
-	int			min_rle_size, warnings;
-	int			ave_image, ave_sound;
-
-	GetScriptToken(false);
-	strcpy(base, token);
-	if (g_release)
-		return;
-
-	GetScriptToken(false);
-	dctconst = atof(token);
-	GetScriptToken(false);
-	maxsize = atoi(token);
-
-	sprintf (savename, "%svideo/%s.cin", gamedir, base);
-
-	// clear stuff
-	memset(charbits1, 0, sizeof(charbits1));
-	memset(charbitscount1, 0, sizeof(charbitscount1));
-	memset(hnodes1, 0, sizeof(hnodes1));
-	memset(numhnodes1, 0, sizeof(numhnodes1));
-	memset(order0counts, 0, sizeof(order0counts));
-
-	// load the entire sound wav file if present
-	LoadSoundtrack();
-
-	cinehead.SndRate = wavinfo.rate;
-	cinehead.SndWidth = wavinfo.width;
-	cinehead.SndChannels = wavinfo.channels;
-
-	sprintf(name, "%svideo/%s/%s0000.tga", gamedir, base, base);
-	printf("Loading sequence : %s\n", name);
-	printf("DCT constant     : %f\n", dctconst);
-
-	LoadTGA (name, NULL, &width, &height);
-
-	output = fopen (savename, "wb");
-	if (!output)
-		Error ("Can't open %s", savename);
-
-	if((width % BLOCKSIZE) || (height % BLOCKSIZE))
-		Error("Width and height must be a multiple of %d", BLOCKSIZE);
-
-	cinehead.Width = width;
-	cinehead.Height = height;
-	init_base(dctconst);
-
-	// build the dictionary
-	printf("Counting         : ");
-	min_rle_size = 0;
-	for (frame = 0;  ; frame++)
-	{
-		printf(".");
-		LoadFrame(&in, base, frame);
-		if(!in.data)
-			break;
-		Huffman1_Count(in);
-		if(in.count > min_rle_size)
-			min_rle_size = in.count;
-		free(in.data);
-	}
-	printf ("\n");
-	cinehead.NumFrames = frame;
-	printf("Num Frames       : %d\n", frame);
-	cinehead.MaxRleSize = (min_rle_size + 0x1f) & 0xfffffe0;
-	cinehead.MaxSndSize = ((4 * wavinfo.rate * wavinfo.channels / 14) + 0x1f) & 0xffffffe0;
-
-	WriteHeader(output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof(CineHead_t), &cinehead);
-
-	// build nodes and write counts
-	Huffman1_Build();
-	WriteHeader(output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof(scaled), scaled);
-	WriteHeader(output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof(Quantise), Quantise);
-
-	ave_image = 0;
-	ave_sound = 0;
-	warnings = 0;
-	// compress it with the dictionary
-	if(soundtrack)
-	{
-		ssize = WriteSound(output, frame, 4);
-		ave_sound += ssize;
-	}
-
-	for (frame = 0; frame < cinehead.NumFrames; frame++)
-	{
-		// save some sound samples
-		printf ("Packing          : ", frame);
-		LoadFrame(&in, base, frame);
-
-		// save the image
-		huffman = Huffman1(in);
-		printf ("%d bytes rle, %d bytes huffman", in.count, huffman.count);
-		size = (huffman.count + 3) & 0xfffffffc;					// round up to longwords
-		if(size > maxsize)
-		{
-			printf(" ** WARNING **");
-			warnings++;
-		}
-		printf("\n");
-		ave_image += huffman.count;
-
-		WriteHeader(output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data);
-		if(soundtrack)
-		{
-			ssize = WriteSound(output, frame + 4, 1);
-			ave_sound += ssize;
-		}
-
-		free (in.data);
-		free (huffman.data);
-	}
-	printf("\nTotal size: %d (headers + %d image + %d sound)\n", ftell(output), ave_image, ave_sound);
-	printf("Data rate : %d bytes per sec (image and sound)\n", (ave_image + ave_sound) / cinehead.NumFrames);
-	printf("Cin created ok with %d warnings.\n", warnings);
-	fclose (output);
-
-	if (soundtrack)
-		free (soundtrack);
-}
-#endif
-
-void Cmd_Video()
-{
-}
-
-// end
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// To do
+
+// Sound error handling (when sound too short)
+// rle b4 huffing
+// adpcm encoding of sound
+
+#if	0
+#include "qdata.h"
+#include "flex.h"
+#include "fc.h"
+#include "adpcm.h"
+
+#define	MIN_REPT	15
+#define	MAX_REPT	0
+#define	HUF_TOKENS	(256 + MAX_REPT)
+
+#define BLOCKSIZE	8
+
+#define M_PI		3.14159265358979323846	// matches value in gcc v2 math.h
+#define SQRT2		1.414213562
+
+typedef struct hnode_s
+{
+	int			count;
+	qboolean	used;
+	int			children[2];
+} hnode_t;
+
+typedef struct
+{
+	int			rate;
+	int			width;
+	int			channels;
+	int			loopstart;
+	int			samples;
+	int			dataofs;		// chunk starts this many bytes from file start
+} wavinfo_t;
+
+// These weren`t picked out my ass....
+// They were defined at http://www.rahul.net/jfm/dct.html
+// However, I think he plucked them out of his ass.....
+
+float Quantise[BLOCKSIZE * BLOCKSIZE];
+
+float LUT_Quantise[BLOCKSIZE * BLOCKSIZE] =
+{
+	16.0F/16.0F, 11.0F/16.0F, 10.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 51.0F/16.0F, 61.0F/16.0F,
+	12.0F/16.0F, 13.0F/16.0F, 14.0F/16.0F, 19.0F/16.0F, 26.0F/16.0F, 58.0F/16.0F, 60.0F/16.0F, 55.0F/16.0F,
+	14.0F/16.0F, 13.0F/16.0F, 16.0F/16.0F, 24.0F/16.0F, 40.0F/16.0F, 57.0F/16.0F, 69.0F/16.0F, 56.0F/16.0F,
+	14.0F/16.0F, 17.0F/16.0F, 22.0F/16.0F, 29.0F/16.0F, 51.0F/16.0F, 87.0F/16.0F, 80.0F/16.0F, 62.0F/16.0F,
+	18.0F/16.0F, 22.0F/16.0F, 37.0F/16.0F, 56.0F/16.0F, 68.0F/16.0F,109.0F/16.0F,103.0F/16.0F, 77.0F/16.0F,
+	24.0F/16.0F, 35.0F/16.0F, 55.0F/16.0F, 64.0F/16.0F, 81.0F/16.0F,104.0F/16.0F,113.0F/16.0F, 92.0F/16.0F,
+	49.0F/16.0F, 64.0F/16.0F, 78.0F/16.0F, 87.0F/16.0F,103.0F/16.0F,121.0F/16.0F,120.0F/16.0F,101.0F/16.0F,
+	72.0F/16.0F, 92.0F/16.0F, 95.0F/16.0F, 98.0F/16.0F,112.0F/16.0F,100.0F/16.0F,103.0F/16.0F, 99.0F/16.0F
+};
+
+int LUT_ZZ[BLOCKSIZE * BLOCKSIZE] =
+{
+	 0,
+	 1,  8, 
+	16,  9,  2,
+	 3, 10, 17, 24,
+	32, 25, 18, 11,  4,
+	 5, 12, 19, 26, 33, 40,
+	48, 41, 34, 27, 20, 13, 6,
+	 7, 14, 21, 28, 35, 42, 49, 56,
+	57, 50, 43, 36, 29, 22, 15,
+	23, 30, 37, 44, 51, 58,
+	59, 52, 45, 38, 31, 
+	39, 46, 53, 60,
+	61, 54, 47,
+	55, 62, 
+	63
+};
+
+char			base[32];
+
+byte			*soundtrack;
+
+byte			scaled[256][HUF_TOKENS];
+unsigned int	charbits1[256][HUF_TOKENS];
+int				charbitscount1[256][HUF_TOKENS];
+hnode_t			hnodes1[256][HUF_TOKENS * 2];
+int				numhnodes1[256];
+int				order0counts[256];
+int				numhnodes;
+hnode_t			hnodes[512];
+unsigned		charbits[256];
+int				charbitscount[256];
+
+CineHead_t		cinehead;
+
+byte			*data_p;
+byte			*iff_end;
+byte			*last_chunk;
+byte			*iff_data;
+int				iff_chunk_len;
+
+float			dctbase[BLOCKSIZE][BLOCKSIZE];
+float			red[BLOCKSIZE * BLOCKSIZE];
+float			green[BLOCKSIZE * BLOCKSIZE];
+float			blue[BLOCKSIZE * BLOCKSIZE];
+float			temp[BLOCKSIZE * BLOCKSIZE];
+
+wavinfo_t		wavinfo;
+adpcm_t			adpcm;
+
+/*
+===============================================================================
+
+WAV loading
+
+===============================================================================
+*/
+
+/* Intel ADPCM step variation table */
+static int indexTable[16] = 
+{
+	-1, -1, -1, -1, 2, 4, 6, 8,
+	-1, -1, -1, -1, 2, 4, 6, 8,
+};
+
+static int stepsizeTable[89] = 
+{
+	7, 8, 9, 10, 11, 12, 13, 14, 16, 17,
+	19, 21, 23, 25, 28, 31, 34, 37, 41, 45,
+	50, 55, 60, 66, 73, 80, 88, 97, 107, 118,
+	130, 143, 157, 173, 190, 209, 230, 253, 279, 307,
+	337, 371, 408, 449, 494, 544, 598, 658, 724, 796,
+	876, 963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066,
+	2272, 2499, 2749, 3024, 3327, 3660, 4026, 4428, 4871, 5358,
+	5894, 6484, 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
+	15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, 32767
+};
+
+#if	0
+static void adpcm_decoder(char *indata, short *outdata, int len, adpcm_state_t *state)
+{
+	signed char *inp;		/* Input buffer pointer */
+	short *outp;		/* output buffer pointer */
+	int sign;			/* Current adpcm sign bit */
+	int delta;			/* Current adpcm output value */
+	int step;			/* Stepsize */
+	int valpred;		/* Predicted value */
+	int vpdiff; 		/* Current change to valpred */
+	int index;			/* Current step change index */
+	int inputbuffer;		/* place to keep next 4-bit value */
+	int bufferstep; 	/* toggle between inputbuffer/input */
+
+	outp = outdata;
+	inp = (signed char *)indata;
+
+	valpred = state->valprev;
+	index = state->index;
+	step = stepsizeTable[index];
+
+	bufferstep = 0;
+	
+	for(; len > 0; len--)
+	{
+		/* Step 1 - get the delta value */
+		if (bufferstep)
+			delta = inputbuffer & 0xf;
+		else
+		{
+			inputbuffer = *inp++;
+			delta = (inputbuffer >> 4) & 0xf;
+		}
+		bufferstep = !bufferstep;
+
+		/* Step 2 - Find new index value (for later) */
+		index += indexTable[delta];
+		if(index < 0)
+			index = 0;
+		if(index > 88)
+			index = 88;
+
+		/* Step 3 - Separate sign and magnitude */
+		sign = delta & 8;
+		delta = delta & 7;
+
+		/* Step 4 - Compute difference and new predicted value */
+		/*
+		** Computes 'vpdiff = (delta+0.5)*step/4', but see comment
+		** in adpcm_coder.
+		*/
+		vpdiff = step >> 3;
+		if(delta & 4)
+			vpdiff += step;
+		if(delta & 2)
+			vpdiff += step>>1;
+		if(delta & 1)
+			vpdiff += step>>2;
+
+		if (sign)
+		  valpred -= vpdiff;
+		else
+		  valpred += vpdiff;
+
+		/* Step 5 - clamp output value */
+		if (valpred > 32767)
+		  valpred = 32767;
+		else if (valpred < -32768)
+		  valpred = -32768;
+
+		/* Step 6 - Update step value */
+		step = stepsizeTable[index];
+
+		/* Step 7 - Output value */
+		*outp++ = valpred;
+	}
+
+	state->valprev = valpred;
+	state->index = index;
+}
+#endif
+
+void adpcm_coder(short *inp, adpcm_t *adpcm)
+{
+	int				val;			/* Current input sample value */
+	int				sign;			/* Current adpcm sign bit */
+	int				delta;			/* Current adpcm output value */
+	int				diff;			/* Difference between val and valprev */
+	int				step;			/* Stepsize */
+	int				valpred;		/* Predicted output value */
+	int				vpdiff; 		/* Current change to valpred */
+	int				index;			/* Current step change index */
+	int				outputbuffer;  	/* place to keep previous 4-bit value */
+	int				bufferstep; 	/* toggle between outputbuffer/output */
+	adpcm_state_t	*state;
+	char			*outp;
+	int				len;
+
+	state = &adpcm->state;
+	len = state->count;
+	outp = adpcm->adpcm;
+
+	valpred = state->in_valprev;
+	index = state->in_index;
+	step = stepsizeTable[index];
+	
+	bufferstep = 1;
+	while(len--)
+	{
+		val = *inp++;
+
+		/* Step 1 - compute difference with previous value */
+		diff = val - valpred;
+		sign = (diff < 0) ? 8 : 0;
+		if (sign)
+			diff = -diff;
+
+		/* Step 2 - Divide and clamp */
+		/* Note:
+		** This code *approximately* computes:
+		**	  delta = diff*4/step;
+		**	  vpdiff = (delta+0.5)*step/4;
+		** but in shift step bits are dropped. The net result of this is
+		** that even if you have fast mul/div hardware you cannot put it to
+		** good use since the fixup would be too expensive.
+		*/
+		delta = 0;
+		vpdiff = (step >> 3);
+		
+		if (diff >= step)
+		{
+			delta = 4;
+			diff -= step;
+			vpdiff += step;
+		}
+		step >>= 1;
+		if (diff >= step)
+		{
+			delta |= 2;
+			diff -= step;
+			vpdiff += step;
+		}
+		step >>= 1;
+		if (diff >= step)
+		{
+			delta |= 1;
+			vpdiff += step;
+		}
+
+		/* Step 3 - Update previous value */
+		if (sign)
+		  valpred -= vpdiff;
+		else
+		  valpred += vpdiff;
+
+		/* Step 4 - Clamp previous value to 16 bits */
+		if (valpred > 32767)
+		  valpred = 32767;
+		else if (valpred < -32768)
+		  valpred = -32768;
+
+		/* Step 5 - Assemble value, update index and step values */
+		delta |= sign;
+		
+		index += indexTable[delta];
+		if (index < 0)
+			index = 0;
+		if (index > 88)
+			index = 88;
+		step = stepsizeTable[index];
+
+		/* Step 6 - Output value */
+		if (bufferstep)
+			outputbuffer = (delta << 4) & 0xf0;
+		else
+			*outp++ = (delta & 0x0f) | outputbuffer;
+
+		bufferstep = !bufferstep;
+	}
+
+	/* Output last step, if needed */
+	if(!bufferstep)
+	  *outp++ = outputbuffer;
+	
+	state->out_valprev = valpred;
+	state->out_index = index;
+}
+
+void FindNextChunk(char *name)
+{
+	while(1)
+	{
+		data_p = last_chunk;
+
+		if(data_p >= iff_end)
+		{								// didn't find the chunk
+			data_p = NULL;
+			return;
+		}
+		
+		data_p += 4;
+		iff_chunk_len = *(long *)data_p;
+		data_p += 4;
+		if(iff_chunk_len < 0)
+		{
+			data_p = NULL;
+			return;
+		}
+
+		data_p -= 8;
+		last_chunk = data_p + 8 + ((iff_chunk_len + 1) & ~1);
+		if (!strncmp(data_p, name, 4))
+			return;
+	}
+}
+
+void FindChunk(char *name)
+{
+	last_chunk = iff_data;
+	FindNextChunk (name);
+}
+
+void DumpChunks(void)
+{
+	char	str[5];
+	
+	str[4] = 0;
+	data_p = iff_data;
+	do
+	{
+		memcpy (str, data_p, 4);
+		data_p += 4;
+		iff_chunk_len = *(long *)data_p;
+		data_p += 4;
+		printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
+		data_p += (iff_chunk_len + 1) & ~1;
+	}
+	while(data_p < iff_end);
+}
+
+/*
+============
+GetWavinfo
+============
+*/
+wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
+{
+	wavinfo_t	info;
+	int			i;
+	int			format;
+	int			samples;
+
+	memset(&info, 0, sizeof(info));
+
+	if (!wav)
+		return(info);
+		
+	iff_data = wav;
+	iff_end = wav + wavlength;
+
+// find "RIFF" chunk
+	FindChunk("RIFF");
+	if (!(data_p && !strncmp(data_p + 8, "WAVE", 4)))
+	{
+		printf("Missing RIFF/WAVE chunks\n");
+		return(info);
+	}
+
+// get "fmt " chunk
+	iff_data = data_p + 12;
+
+	FindChunk("fmt ");
+	if(!data_p)
+	{
+		printf("Missing fmt chunk\n");
+		return(info);
+	}
+	data_p += 8;
+	format = *(short *)data_p;
+	data_p += 2;
+	if (format != 1)
+	{
+		printf("Microsoft PCM format only\n");
+		return(info);
+	}
+
+	info.channels = *(short *)data_p;
+	data_p += 2;
+	info.rate = *(long *)data_p;
+	data_p += 4;
+	data_p += 6;
+	info.width = *(short *)data_p / 8;
+	data_p += 2;
+
+// get cue chunk
+	FindChunk("cue ");
+	if(data_p)
+	{
+		data_p += 32;
+		info.loopstart = *(long *)data_p;
+		data_p += 4;
+
+// if the next chunk is a LIST chunk, look for a cue length marker
+		FindNextChunk ("LIST");
+		if(data_p)
+		{
+// this is not a proper parse, but it works with cooledit...
+			if (!strncmp (data_p + 28, "mark", 4))
+			{
+				data_p += 24;
+				i = *(long *)data_p;					// samples in loop
+				data_p += 4;
+				info.samples = info.loopstart + i;
+			}
+		}
+	}
+	else
+		info.loopstart = -1;
+
+// find data chunk
+	FindChunk("data");
+	if (!data_p)
+	{
+		printf("Missing data chunk\n");
+		return(info);
+	}
+
+	data_p += 4;
+	samples = *(long *)data_p;
+	data_p += 4;
+
+	if (info.samples)
+	{
+		if(samples < info.samples)
+			Error ("Sound %s has a bad loop length", name);
+	}
+	else
+		info.samples = samples;
+
+	info.dataofs = data_p - wav;
+	return(info);
+}
+
+// ==============
+// LoadSoundtrack
+// ==============
+
+void LoadSoundtrack()
+{
+	char	name[1024];
+	FILE	*f;
+	int		len;
+
+	soundtrack = NULL;
+	sprintf (name, "%svideo/%s/%s.wav", gamedir, base, base);
+	printf ("\nLoading sound    : %s\n", name);
+	f = fopen (name, "rb");
+	if (!f)
+	{
+		printf ("\nNo soundtrack for %s\n", base);
+		return;
+	}
+	len = Q_filelength(f);
+	soundtrack = SafeMalloc(len, "LoadSoundtrack");
+	fread(soundtrack, 1, len, f);
+	fclose(f);
+
+	wavinfo = GetWavinfo(name, soundtrack, len);
+	adpcm.state.out_valprev = 0;
+	adpcm.state.out_index = 0;
+}
+
+// ==================
+// WriteSound
+// ==================
+
+int WriteSound(FILE *output, int frame, int numframes)
+{
+	int		start, end;
+	int		count;
+	int		empty = 0;
+	int		width;
+	char	*work;
+
+	width = wavinfo.width * wavinfo.channels;
+	start = ((frame * wavinfo.rate / 14) + 31) & 0xffffffe0;				// start sample
+	end = (((frame + numframes) * wavinfo.rate / 14) + 31) & 0xffffffe0;	// end sample
+	count = end - start;
+
+	work = soundtrack + wavinfo.dataofs + (start * width);
+	adpcm.state.count = count * wavinfo.channels;			// Number of samples
+	adpcm.state.in_valprev = adpcm.state.out_valprev;
+	adpcm.state.in_index = adpcm.state.out_index;
+	adpcm_coder((short *)work, &adpcm);
+	WriteHeader(output, FC_SOUND_22KMADPCM, FC_ADPCM_VERSION, (adpcm.state.count / 2) + sizeof(adpcm_state_t), (char *)&adpcm);
+	return(count / 2);
+}
+// ==============================
+// Basic run length encoder
+// ==============================
+
+char *RLEZZ(char *in, char *out)
+{
+	int		srun;
+	char	count;
+	int		idx = 0;
+
+	while(idx < 64)
+	{
+		srun = idx;								// Start of run
+
+		while(idx < 63)
+		{
+			if(in[LUT_ZZ[idx]] != in[LUT_ZZ[idx + 1]])
+				break;
+			idx++;
+		}
+		count = (char)(idx - srun);				// count of repeated bytes
+
+		if(!count)
+		{
+			while(idx < 63)
+			{
+				if(in[LUT_ZZ[idx]] == in[LUT_ZZ[idx + 1]])
+					break;
+				idx++;
+			}
+			if(idx == 63)
+				idx++;
+
+			count = (char)(idx - srun);			// count of unique bytes
+			*out++ = count;
+			while(count--)
+				*out++ = in[LUT_ZZ[srun++]];
+		}
+		else
+		{
+			*out++ = -(count + 1);
+			*out++ = in[LUT_ZZ[idx]];
+			idx++;
+		}
+	}
+	return(out);
+}
+
+// ==============================
+// Discrete Cosine Transformation
+// ==============================
+
+void init_base(float quant)
+{
+	int			y, x;
+
+	for(y = 0; y < BLOCKSIZE; y++)
+		for(x = 0; x < BLOCKSIZE; x++)
+		{
+			if(y == 0)
+				dctbase[y][x] = 1;
+			else
+				dctbase[y][x] = SQRT2 * cos(((x * 2 + 1) * y * M_PI) / (BLOCKSIZE * 2));
+		}
+
+	for(y = 0; y < BLOCKSIZE * BLOCKSIZE; y++)
+		Quantise[y] = LUT_Quantise[y] / quant;
+}
+
+void SplitComponents(byte *src, int width, int height)
+{
+	int		i, j;
+	float	*tr = red;
+	float	*tg = green;
+	float	*tb = blue;
+
+	for(i = 0; i < BLOCKSIZE; i++, src += (width - BLOCKSIZE) * 4)
+		for(j = 0; j < BLOCKSIZE; j++)
+		{
+			*tr++ = ((float)*src++) - 128.0F;
+			*tg++ = ((float)*src++) - 128.0F;
+			*tb++ = ((float)*src++) - 128.0F;
+			src++;
+		}
+}
+
+void transferH(float *src, float *dst)
+{
+	int		y, dx, dy;
+	float	sum;
+	float	*work;
+
+	for(y = 0; y < BLOCKSIZE; y++, src += BLOCKSIZE)
+	{
+		for(dy = 0; dy < BLOCKSIZE; dy++)
+		{
+			sum = 0;
+			work = src;
+			for(dx = 0; dx < BLOCKSIZE; dx++, work++)
+				sum += dctbase[dy][dx] * *work;
+
+			*dst++ = sum / BLOCKSIZE;
+		}
+	}
+}
+
+void transferV(float *src, float *dst)
+{
+	int		x, dy, fy;
+	float	sum;
+	float	*work;
+
+	for(x = 0; x < BLOCKSIZE; x++, src++, dst++)
+	{
+		for(fy = 0; fy < BLOCKSIZE; fy++)
+		{
+			sum = 0;
+			work = src;
+			for(dy = 0; dy < BLOCKSIZE; dy++, work += BLOCKSIZE)
+				sum += dctbase[fy][dy] * *work;
+
+			dst[fy * BLOCKSIZE] = sum / BLOCKSIZE;
+		}
+	}
+}
+
+char *Combine(byte *dst, float *p, float *q)
+{
+	int		i, j;
+	byte	rlesrc[BLOCKSIZE * BLOCKSIZE];
+ 	int		c;
+	byte	*work;
+
+	work = rlesrc;
+	for(j = 0; j < BLOCKSIZE; j++)
+		for(i = 0; i < BLOCKSIZE; i++)
+		{
+			c = (int)((*p++ / *q++) + 128.5F);
+			c -= 128;
+
+			if(c < -128)
+				c = -128;
+			if(c > 127)
+				c = 127;
+
+			*work++ = (char)c;
+		}
+
+	dst = RLEZZ(rlesrc, dst);
+	return(dst);
+}
+
+char *CombineComponents(char *dst, int width, int height)
+{
+	dst = Combine(dst, red, Quantise);
+	dst = Combine(dst, green, Quantise);
+	dst = Combine(dst, blue, Quantise);
+	return(dst);
+}
+
+void DCT(cblock_t *out, cblock_t in, int width, int height)
+{
+	int		x, y;
+	char	*cursrc;
+	char	*curdst;
+
+	curdst = out->data;
+	for(y = 0; y < height; y += BLOCKSIZE)
+		for(x = 0; x < width; x += BLOCKSIZE)
+		{
+			cursrc = in.data + ((y * width) + x) * 4;
+			SplitComponents(cursrc, width, height);
+			transferH(red, temp);
+			transferV(temp, red);
+			transferH(green, temp);
+			transferV(temp, green);
+			transferH(blue, temp);
+			transferV(temp, blue);
+			curdst = CombineComponents(curdst, width, height);
+		}
+	out->count = curdst - out->data;
+}
+
+// ==================
+// BuildChars1
+// ==================
+
+void BuildChars1(int prev, int nodenum, unsigned bits, int bitcount)
+{
+	hnode_t		*node;
+
+	if(nodenum < HUF_TOKENS)
+	{
+		if (bitcount > 32)
+			Error("bitcount > 32");
+		charbits1[prev][nodenum] = bits;
+		charbitscount1[prev][nodenum] = bitcount;
+		return;
+	}
+
+	node = &hnodes1[prev][nodenum];
+	bits <<= 1;
+	BuildChars1(prev, node->children[0], bits, bitcount+1);
+	bits |= 1;
+	BuildChars1(prev, node->children[1], bits, bitcount+1);
+}
+
+// ==================
+// SmallestNode1
+// ==================
+
+int	SmallestNode1(hnode_t *hnodes, int numhnodes)
+{
+	int		i;
+	int		best, bestnode;
+
+	best = 99999999;
+	bestnode = -1;
+	for(i = 0; i < numhnodes; i++)
+	{
+		if(hnodes[i].used)
+			continue;
+		if(!hnodes[i].count)
+			continue;
+		if(hnodes[i].count < best)
+		{
+			best = hnodes[i].count;
+			bestnode = i;
+		}
+	}
+
+	if (bestnode == -1)
+		return(-1);
+
+	hnodes[bestnode].used = true;
+	return(bestnode);
+}
+
+// ==================
+// BuildTree1
+// ==================
+
+void BuildTree1(int prev)
+{
+	hnode_t		*node, *nodebase;
+	int			numhnodes;
+
+	// build the nodes
+	numhnodes = HUF_TOKENS;
+	nodebase = hnodes1[prev];
+	while(1)
+	{
+		node = &nodebase[numhnodes];
+
+		// pick two lowest counts
+		node->children[0] = SmallestNode1 (nodebase, numhnodes);
+		if (node->children[0] == -1)
+			break;	// no more
+
+		node->children[1] = SmallestNode1 (nodebase, numhnodes);
+		if (node->children[1] == -1)
+			break;
+
+		node->count = nodebase[node->children[0]].count + 
+			nodebase[node->children[1]].count;
+		numhnodes++;
+	}
+	numhnodes1[prev] = numhnodes-1;
+	BuildChars1 (prev, numhnodes-1, 0, 0);
+}
+
+// ==================
+// Huffman1_Count
+// ==================
+
+void Huffman1_Count(cblock_t in)
+{
+	int		i;
+	int		prev;
+	int		v;
+	int		rept;
+
+	prev = 0;
+	for(i = 0; i < in.count; i++)
+	{
+		v = in.data[i];
+		order0counts[v]++;
+		hnodes1[prev][v].count++;
+		prev = v;
+
+		for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
+			if(in.data[i+rept] != v)
+				break;
+		if(rept > MIN_REPT)
+		{
+			hnodes1[prev][255 + rept].count++;
+			i += rept - 1;
+		}
+	}
+}
+
+// ==================
+// Huffman1_Build
+// ==================
+
+void Huffman1_Build()
+{
+	int		i, j, v;
+	int		max;
+	int		total;
+
+	for(i = 0; i < 256; i++)
+	{
+// normalize and save the counts
+		max = 0;
+		for (j = 0; j < HUF_TOKENS; j++)
+		{
+			if (hnodes1[i][j].count > max)
+				max = hnodes1[i][j].count;
+		}
+		if (max == 0)
+			max = 1;
+		total = 0;
+// easy to overflow 32 bits here!
+		for(j = 0; j < HUF_TOKENS; j++)
+		{
+			v = (hnodes1[i][j].count * (double) 255 + max - 1) / max;
+			if (v > 255)
+				Error ("v > 255");
+			scaled[i][j] = hnodes1[i][j].count = v;
+			if (v)
+				total++;
+		}
+		if (total == 1)
+		{	// must have two tokens
+			if (!scaled[i][0])
+				scaled[i][0] = hnodes1[i][0].count = 1;
+			else
+				scaled[i][1] = hnodes1[i][1].count = 1;
+		}
+		BuildTree1 (i);
+	}
+}
+
+// ==================
+// Huffman1
+// Order 1 compression with pre-built table
+// ==================
+
+cblock_t Huffman1(cblock_t in)
+{
+	int			i;
+	int			outbits, c;
+	unsigned	bits;
+	byte		*out_p;
+	cblock_t	out;
+	int			prev;
+	int			v;
+	int			rept;
+
+	out_p = out.data = SafeMalloc((in.count * 2) + 1024 + 4, "Huffman");
+	memset(out_p, 0, (in.count * 2) + 1024 + 4);
+
+	// leave space for compressed count
+	out_p += 4;
+	// write count
+	*(long *)out_p = in.count;
+	out_p += 4;
+
+	// write bits
+	outbits = 0;
+	prev = 0;
+	for(i = 0; i < in.count; i++)
+	{
+		v = in.data[i];
+
+		c = charbitscount1[prev][v];
+		bits = charbits1[prev][v];
+		if (!c)
+			Error ("!bits");
+		while (c)
+		{
+			c--;
+			if (bits & (1 << c))
+				out_p[outbits>>3] |= 1 << (outbits & 7);
+			outbits++;
+		}
+
+		prev = v;
+		// check for repeat encodes
+		for(rept = 1; (i + rept < in.count) && (rept < MAX_REPT); rept++)
+			if(in.data[i + rept] != v)
+				break;
+		if (rept > MIN_REPT)
+		{
+			c = charbitscount1[prev][255 + rept];
+			bits = charbits1[prev][255 + rept];
+			if (!c)
+				Error ("!bits");
+			while (c)
+			{
+				c--;
+				if(bits & (1 << c))
+					out_p[outbits >> 3] |= 1 << (outbits & 7);
+				outbits++;
+			}
+			i += rept - 1;
+		}
+	}
+	out_p += (outbits + 7) >> 3;
+	out.count = out_p - out.data;
+
+	out_p = out.data;
+	*(long *)out_p = out.count;
+	return(out);
+}
+// ===================
+// LoadFrame
+// ===================
+
+void LoadFrame(cblock_t *out, char *base, int frame)
+{
+	cblock_t	in;
+	int			width, height;
+	char		name[1024];
+	FILE		*f;
+
+	in.data = NULL;
+	in.count = -1;
+	sprintf (name, "%svideo/%s/%s%04i.tga", gamedir, base, base, frame);
+
+	f = fopen(name, "rb");
+	if (!f)
+	{
+		out->data = NULL;
+		return;
+	}
+	fclose (f);
+
+	LoadTGA(name, &in.data, &width, &height);
+	if((width != cinehead.Width) || (height != cinehead.Height))
+	{
+		free(in.data);
+		printf("Invalid picture size\n");
+		out->data = NULL;
+		return;
+	}
+	out->data = SafeMalloc(width * height * 3, "LoadFrame");		// rle could possibly expand file so this not 100% safe (however DCT should force a lot of compression)
+	DCT(out, in, width, height);
+	free(in.data);
+}
+
+// ==================================
+// Cmd_Video
+// 
+// video <directory> <framedigits>
+// ==================================
+
+void Cmd_Video()
+{
+	char		savename[256];
+	char		name[256];
+	FILE		*output;
+	int			frame;
+	int			width, height;
+	cblock_t	in, huffman;
+	int			size;
+	float		dctconst;
+	int			maxsize, ssize;
+	int			min_rle_size, warnings;
+	int			ave_image, ave_sound;
+
+	GetScriptToken(false);
+	strcpy(base, token);
+	if (g_release)
+		return;
+
+	GetScriptToken(false);
+	dctconst = atof(token);
+	GetScriptToken(false);
+	maxsize = atoi(token);
+
+	sprintf (savename, "%svideo/%s.cin", gamedir, base);
+
+	// clear stuff
+	memset(charbits1, 0, sizeof(charbits1));
+	memset(charbitscount1, 0, sizeof(charbitscount1));
+	memset(hnodes1, 0, sizeof(hnodes1));
+	memset(numhnodes1, 0, sizeof(numhnodes1));
+	memset(order0counts, 0, sizeof(order0counts));
+
+	// load the entire sound wav file if present
+	LoadSoundtrack();
+
+	cinehead.SndRate = wavinfo.rate;
+	cinehead.SndWidth = wavinfo.width;
+	cinehead.SndChannels = wavinfo.channels;
+
+	sprintf(name, "%svideo/%s/%s0000.tga", gamedir, base, base);
+	printf("Loading sequence : %s\n", name);
+	printf("DCT constant     : %f\n", dctconst);
+
+	LoadTGA (name, NULL, &width, &height);
+
+	output = fopen (savename, "wb");
+	if (!output)
+		Error ("Can't open %s", savename);
+
+	if((width % BLOCKSIZE) || (height % BLOCKSIZE))
+		Error("Width and height must be a multiple of %d", BLOCKSIZE);
+
+	cinehead.Width = width;
+	cinehead.Height = height;
+	init_base(dctconst);
+
+	// build the dictionary
+	printf("Counting         : ");
+	min_rle_size = 0;
+	for (frame = 0;  ; frame++)
+	{
+		printf(".");
+		LoadFrame(&in, base, frame);
+		if(!in.data)
+			break;
+		Huffman1_Count(in);
+		if(in.count > min_rle_size)
+			min_rle_size = in.count;
+		free(in.data);
+	}
+	printf ("\n");
+	cinehead.NumFrames = frame;
+	printf("Num Frames       : %d\n", frame);
+	cinehead.MaxRleSize = (min_rle_size + 0x1f) & 0xfffffe0;
+	cinehead.MaxSndSize = ((4 * wavinfo.rate * wavinfo.channels / 14) + 0x1f) & 0xffffffe0;
+
+	WriteHeader(output, FC_HEADER_NAME, FC_HEADER_VERSION, sizeof(CineHead_t), &cinehead);
+
+	// build nodes and write counts
+	Huffman1_Build();
+	WriteHeader(output, FC_HUFFBITS_NAME, FC_HUFFBITS_VERSION, sizeof(scaled), scaled);
+	WriteHeader(output, FC_QUANT_NAME, FC_QUANT_VERSION, sizeof(Quantise), Quantise);
+
+	ave_image = 0;
+	ave_sound = 0;
+	warnings = 0;
+	// compress it with the dictionary
+	if(soundtrack)
+	{
+		ssize = WriteSound(output, frame, 4);
+		ave_sound += ssize;
+	}
+
+	for (frame = 0; frame < cinehead.NumFrames; frame++)
+	{
+		// save some sound samples
+		printf ("Packing          : ", frame);
+		LoadFrame(&in, base, frame);
+
+		// save the image
+		huffman = Huffman1(in);
+		printf ("%d bytes rle, %d bytes huffman", in.count, huffman.count);
+		size = (huffman.count + 3) & 0xfffffffc;					// round up to longwords
+		if(size > maxsize)
+		{
+			printf(" ** WARNING **");
+			warnings++;
+		}
+		printf("\n");
+		ave_image += huffman.count;
+
+		WriteHeader(output, FC_IMAGE_NAME, FC_IMAGE_VERSION, size, huffman.data);
+		if(soundtrack)
+		{
+			ssize = WriteSound(output, frame + 4, 1);
+			ave_sound += ssize;
+		}
+
+		free (in.data);
+		free (huffman.data);
+	}
+	printf("\nTotal size: %d (headers + %d image + %d sound)\n", ftell(output), ave_image, ave_sound);
+	printf("Data rate : %d bytes per sec (image and sound)\n", (ave_image + ave_sound) / cinehead.NumFrames);
+	printf("Cin created ok with %d warnings.\n", warnings);
+	fclose (output);
+
+	if (soundtrack)
+		free (soundtrack);
+}
+#endif
+
+void Cmd_Video()
+{
+}
+
+// end
+
diff --git a/tools/quake3/common/aselib.c b/tools/quake3/common/aselib.c
index 58307f85..94491f7f 100644
--- a/tools/quake3/common/aselib.c
+++ b/tools/quake3/common/aselib.c
@@ -1,965 +1,965 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "aselib.h"
-#include "inout.h"
-
-#include <assert.h>
-#include <stdio.h>
-#include <stdlib.h>
-
-#define MAX_ASE_MATERIALS			32
-#define MAX_ASE_OBJECTS				64
-#define MAX_ASE_ANIMATIONS			32
-#define MAX_ASE_ANIMATION_FRAMES	512
-
-#define VERBOSE( x ) { if ( ase.verbose ) { Sys_Printf x ; } }
-
-typedef struct
-{
-	float x, y, z;
-	float nx, ny, nz;
-	float s, t;
-} aseVertex_t;
-
-typedef struct
-{
-	float s, t;
-} aseTVertex_t;
-
-typedef int aseFace_t[3];
-
-typedef struct
-{
-	int numFaces;
-	int numVertexes;
-	int numTVertexes;
-
-	int timeValue;
-
-	aseVertex_t		*vertexes;
-	aseTVertex_t	*tvertexes;
-	aseFace_t		*faces, *tfaces;
-
-	int currentFace, currentVertex;
-} aseMesh_t;
-
-typedef struct
-{
-	int			numFrames;
-	aseMesh_t	frames[MAX_ASE_ANIMATION_FRAMES];
-
-	int		   currentFrame;
-} aseMeshAnimation_t;
-
-typedef struct
-{
-	char name[128];
-} aseMaterial_t;
-
-/*
-** contains the animate sequence of a single surface
-** using a single material
-*/
-typedef struct
-{
-	char name[128];
-
-	int materialRef;
-	int numAnimations;
-
-	aseMeshAnimation_t	anim;
-
-} aseGeomObject_t;
-
-typedef struct
-{
-	int				numMaterials;
-	aseMaterial_t	materials[MAX_ASE_MATERIALS];
-	aseGeomObject_t objects[MAX_ASE_OBJECTS];
-
-	char	*buffer;
-	char	*curpos;
-	int		 len;
-
-	int			currentObject;
-	qboolean	verbose;
-	qboolean	grabAnims;
-
-} ase_t;
-
-static char s_token[1024];
-static ase_t ase;
-static char gl_filename[1024];
-
-static void ASE_Process( void );
-static void ASE_FreeGeomObject( int ndx );
-
-#if defined (__linux__) || defined (__APPLE__)
-
-static char* strlwr (char* string)
-{
-  char *cp;
-  for (cp = string; *cp; ++cp)
-  {
-    if ('A' <= *cp && *cp <= 'Z')
-      *cp += 'a' - 'A';
-  }
- 
-  return string;
-}
-
-#endif
-
-/*
-** ASE_Load
-*/
-void ASE_Load( const char *filename, qboolean verbose, qboolean grabAnims )
-{
-	FILE *fp = fopen( filename, "rb" );
-
-	if ( !fp )
-		Error( "File not found '%s'", filename );
-
-	memset( &ase, 0, sizeof( ase ) );
-
-	ase.verbose = verbose;
-	ase.grabAnims = grabAnims;
-	ase.len = Q_filelength( fp );
-
-	ase.curpos = ase.buffer = safe_malloc( ase.len );
-
-	Sys_Printf( "Processing '%s'\n", filename );
-
-	if ( fread( ase.buffer, ase.len, 1, fp ) != 1 )
-	{
-		fclose( fp );
-		Error( "fread() != -1 for '%s'", filename );
-	}
-
-	fclose( fp );
-
-        strcpy(gl_filename, filename);
-        
-	ASE_Process();
-}
-
-/*
-** ASE_Free
-*/
-void ASE_Free( void )
-{
-	int i;
-
-	for ( i = 0; i < ase.currentObject; i++ )
-	{
-		ASE_FreeGeomObject( i );
-	}
-}
-
-/*
-** ASE_GetNumSurfaces
-*/
-int ASE_GetNumSurfaces( void )
-{
-	return ase.currentObject;
-}
-
-/*
-** ASE_GetSurfaceName
-*/
-const char *ASE_GetSurfaceName( int which )
-{
-	aseGeomObject_t *pObject = &ase.objects[which];
-
-	if ( !pObject->anim.numFrames )
-		return 0;
-
-	return pObject->name;
-}
-
-/*
-** ASE_GetSurfaceAnimation
-**
-** Returns an animation (sequence of polysets)
-*/
-polyset_t *ASE_GetSurfaceAnimation( int which, int *pNumFrames, int skipFrameStart, int skipFrameEnd, int maxFrames )
-{
-	aseGeomObject_t *pObject = &ase.objects[which];
-	polyset_t *psets;
-	int numFramesInAnimation;
-	int numFramesToKeep;
-	int i, f;
-
-	if ( !pObject->anim.numFrames )
-		return 0;
-
-	if ( pObject->anim.numFrames > maxFrames && maxFrames != -1 )
-	{
-		numFramesInAnimation = maxFrames;
-	}
-	else 
-	{
-		numFramesInAnimation = pObject->anim.numFrames;
-		if ( maxFrames != -1 )
-			Sys_Printf( "WARNING: ASE_GetSurfaceAnimation maxFrames > numFramesInAnimation\n" );
-	}
-
-	if ( skipFrameEnd != -1 )
-		numFramesToKeep = numFramesInAnimation - ( skipFrameEnd - skipFrameStart + 1 );
-	else
-		numFramesToKeep = numFramesInAnimation;
-
-	*pNumFrames = numFramesToKeep;
-
-	psets = calloc( sizeof( polyset_t ) * numFramesToKeep, 1 );
-
-	for ( f = 0, i = 0; i < numFramesInAnimation; i++ )
-	{
-		int t;
-		aseMesh_t *pMesh = &pObject->anim.frames[i];
-
-		if ( skipFrameStart != -1 )
-		{
-			if ( i >= skipFrameStart && i <= skipFrameEnd )
-				continue;
-		}
-
-		strcpy( psets[f].name, pObject->name );
-		strcpy( psets[f].materialname, ase.materials[pObject->materialRef].name );
-
-		psets[f].triangles = calloc( sizeof( triangle_t ) * pObject->anim.frames[i].numFaces, 1 );
-		psets[f].numtriangles = pObject->anim.frames[i].numFaces;
-
-		for ( t = 0; t < pObject->anim.frames[i].numFaces; t++ )
-		{
-			int k;
-
-			for ( k = 0; k < 3; k++ )
-			{
-				psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x;
-				psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y;
-				psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z;
-
-				if ( pMesh->tvertexes && pMesh->tfaces )
-				{
-					psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s;
-					psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t;
-				}
-
-			}
-		}
-
-		f++;
-	}
-
-	return psets;
-}
-
-static void ASE_FreeGeomObject( int ndx )
-{
-	aseGeomObject_t *pObject;
-	int i;
-
-	pObject = &ase.objects[ndx];
-
-	for ( i = 0; i < pObject->anim.numFrames; i++ )
-	{
-		if ( pObject->anim.frames[i].vertexes )
-		{
-			free( pObject->anim.frames[i].vertexes );
-		}
-		if ( pObject->anim.frames[i].tvertexes )
-		{
-			free( pObject->anim.frames[i].tvertexes );
-		}
-		if ( pObject->anim.frames[i].faces )
-		{
-			free( pObject->anim.frames[i].faces );
-		}
-		if ( pObject->anim.frames[i].tfaces )
-		{
-			free( pObject->anim.frames[i].tfaces );
-		}
-	}
-
-	memset( pObject, 0, sizeof( *pObject ) );
-}
-
-static aseMesh_t *ASE_GetCurrentMesh( void )
-{
-	aseGeomObject_t *pObject;
-
-	if ( ase.currentObject >= MAX_ASE_OBJECTS )
-	{
-		Error( "Too many GEOMOBJECTs" );
-		return 0; // never called
-	}
-
-	pObject = &ase.objects[ase.currentObject];
-
-	if ( pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES )
-	{
-		Error( "Too many MESHes" );
-		return 0;
-	}
-
-	return &pObject->anim.frames[pObject->anim.currentFrame];
-}
-
-static int CharIsTokenDelimiter( int ch )
-{
-	if ( ch <= 32 )
-		return 1;
-	return 0;
-}
-
-static int ASE_GetToken( qboolean restOfLine )
-{
-	int i = 0;
-
-	if ( ase.buffer == 0 )
-		return 0;
-
-	if ( ( ase.curpos - ase.buffer ) == ase.len )
-		return 0;
-
-	// skip over crap
-	while ( ( ( ase.curpos - ase.buffer ) < ase.len ) &&
-		    ( *ase.curpos <= 32 ) )
-	{
-		ase.curpos++;
-	}
-
-	while ( ( ase.curpos - ase.buffer ) < ase.len )
-	{
-		s_token[i] = *ase.curpos;
-
-		ase.curpos++;
-		i++;
-
-		if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
-			 ( ( s_token[i-1] == '\n' ) || ( s_token[i-1] == '\r' ) ) )
-		{
-			s_token[i-1] = 0;
-			break;
-		}
-	}
-
-	s_token[i] = 0;
-
-	return 1;
-}
-
-static void ASE_ParseBracedBlock( void (*parser)( const char *token ) )
-{
-	int indent = 0;
-
-	while ( ASE_GetToken( qfalse ) )
-	{
-		if ( !strcmp( s_token, "{" ) )
-		{
-			indent++;
-		}
-		else if ( !strcmp( s_token, "}" ) )
-		{
-			--indent;
-			if ( indent == 0 )
-				break;
-			else if ( indent < 0 )
-				Error( "Unexpected '}'" );
-		}
-		else
-		{
-			if ( parser )
-				parser( s_token );
-		}
-	}
-}
-
-static void ASE_SkipEnclosingBraces( void )
-{
-	int indent = 0;
-
-	while ( ASE_GetToken( qfalse ) )
-	{
-		if ( !strcmp( s_token, "{" ) )
-		{
-			indent++;
-		}
-		else if ( !strcmp( s_token, "}" ) )
-		{
-			indent--;
-			if ( indent == 0 )
-				break;
-			else if ( indent < 0 )
-				Error( "Unexpected '}'" );
-		}
-	}
-}
-
-static void ASE_SkipRestOfLine( void )
-{
-	ASE_GetToken( qtrue );
-}
-
-static void ASE_KeyMAP_DIFFUSE( const char *token )
-{
-	char fullpath[1024], bitmap[1024], modeldir[1024];
-	char filename[1024];
-	int i = 0, count;
-
-	strcpy(filename, gl_filename);
-
-	if ( !strcmp( token, "*BITMAP" ) )
-	{
-		ASE_GetToken( qfalse );
-
-		// the purpose of this whole chunk of code below is to extract the relative path
-		// from a full path in the ASE
-			
-		strcpy( bitmap, s_token + 1 );
-		if ( strchr( bitmap, '"' ) )
-			*strchr( bitmap, '"' ) = 0;
-
-		/* convert backslash to slash */
-		while ( bitmap[i] )
-		{
-			if ( bitmap[i] == '\\' )
-				bitmap[i] = '/';
-			i++;
-		}
-
-		/* remove filename from path */
-		for( i=strlen(filename); i>0; i--)
-		{
-			if(filename[i] == '/')
-			{
-				filename[i] = '\0';
-				break;
-			}
-		}
-
-		/* replaces a relative path with a full path */
-		if(bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/')
-		{
-			while(bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/')
-			{
-				/* remove last item from path */
-				for( i=strlen(filename); i>0; i--)
-				{
-					if(filename[i] == '/')
-					{
-						filename[i] = '\0';
-						break;
-					}
-				}
-				strcpy(bitmap, &bitmap[3]);
-			}
-			strcat(filename, "/");
-			strcat(filename, bitmap);
-			strcpy(bitmap, filename);
-		}
-
-		if ( strstr( bitmap, gamedir ) )
-		{
-			strcpy( ase.materials[ase.numMaterials].name, strstr( bitmap, gamedir ) + strlen( gamedir ) );
-			Sys_Printf("material name: \'%s\'\n", strstr( bitmap, gamedir ) + strlen( gamedir ) );
-		}
-		else
-		{
-			sprintf( ase.materials[ase.numMaterials].name, "(not converted: '%s')", bitmap );
-			Sys_Printf( "WARNING: illegal material name '%s'\n", bitmap );
-		}
-	}
-	else
-	{
-	}
-}
-
-static void ASE_KeyMATERIAL( const char *token )
-{
-	if ( !strcmp( token, "*MAP_DIFFUSE" ) )
-	{
-		ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE );
-	}
-	else
-	{
-	}
-}
-
-static void ASE_KeyMATERIAL_LIST( const char *token )
-{
-	if ( !strcmp( token, "*MATERIAL_COUNT" ) )
-	{
-		ASE_GetToken( qfalse );
-		VERBOSE( ( "..num materials: %s\n", s_token ) );
-		if ( atoi( s_token ) > MAX_ASE_MATERIALS )
-		{
-			Error( "Too many materials!" );
-		}
-		ase.numMaterials = 0;
-	}
-	else if ( !strcmp( token, "*MATERIAL" ) )
-	{
-		VERBOSE( ( "..material %d ", ase.numMaterials ) );
-		ASE_ParseBracedBlock( ASE_KeyMATERIAL );
-		ase.numMaterials++;
-	}
-}
-
-static void ASE_KeyMESH_VERTEX_LIST( const char *token )
-{
-	aseMesh_t *pMesh = ASE_GetCurrentMesh();
-
-	if ( !strcmp( token, "*MESH_VERTEX" ) )
-	{
-		ASE_GetToken( qfalse );		// skip number
-
-		ASE_GetToken( qfalse );
-		pMesh->vertexes[pMesh->currentVertex].y = atof( s_token );
-
-		ASE_GetToken( qfalse );
-		pMesh->vertexes[pMesh->currentVertex].x = -atof( s_token );
-
-		ASE_GetToken( qfalse );
-		pMesh->vertexes[pMesh->currentVertex].z = atof( s_token );
-
-		pMesh->currentVertex++;
-
-		if ( pMesh->currentVertex > pMesh->numVertexes )
-		{
-			Error( "pMesh->currentVertex >= pMesh->numVertexes" );
-		}
-	}
-	else
-	{
-		Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token );
-	}
-}
-
-static void ASE_KeyMESH_FACE_LIST( const char *token )
-{
-	aseMesh_t *pMesh = ASE_GetCurrentMesh();
-
-	if ( !strcmp( token, "*MESH_FACE" ) )
-	{
-		ASE_GetToken( qfalse );	// skip face number
-
-		ASE_GetToken( qfalse );	// skip label
-		ASE_GetToken( qfalse );	// first vertex
-		pMesh->faces[pMesh->currentFace][0] = atoi( s_token );
-
-		ASE_GetToken( qfalse );	// skip label
-		ASE_GetToken( qfalse );	// second vertex
-		pMesh->faces[pMesh->currentFace][2] = atoi( s_token );
-
-		ASE_GetToken( qfalse );	// skip label
-		ASE_GetToken( qfalse );	// third vertex
-		pMesh->faces[pMesh->currentFace][1] = atoi( s_token );
-
-		ASE_GetToken( qtrue );
-
-/*
-		if ( ( p = strstr( s_token, "*MESH_MTLID" ) ) != 0 )
-		{
-			p += strlen( "*MESH_MTLID" ) + 1;
-			mtlID = atoi( p );
-		}
-		else
-		{
-			Error( "No *MESH_MTLID found for face!" );
-		}
-*/
-
-		pMesh->currentFace++;
-	}
-	else
-	{
-		Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token );
-	}
-}
-
-static void ASE_KeyTFACE_LIST( const char *token )
-{
-	aseMesh_t *pMesh = ASE_GetCurrentMesh();
-
-	if ( !strcmp( token, "*MESH_TFACE" ) )
-	{
-		int a, b, c;
-
-		ASE_GetToken( qfalse );
-
-		ASE_GetToken( qfalse );
-		a = atoi( s_token );
-		ASE_GetToken( qfalse );
-		c = atoi( s_token );
-		ASE_GetToken( qfalse );
-		b = atoi( s_token );
-
-		pMesh->tfaces[pMesh->currentFace][0] = a;
-		pMesh->tfaces[pMesh->currentFace][1] = b;
-		pMesh->tfaces[pMesh->currentFace][2] = c;
-
-		pMesh->currentFace++;
-	}
-	else
-	{
-		Error( "Unknown token '%s' in MESH_TFACE", token );
-	}
-}
-
-static void ASE_KeyMESH_TVERTLIST( const char *token )
-{
-	aseMesh_t *pMesh = ASE_GetCurrentMesh();
-
-	if ( !strcmp( token, "*MESH_TVERT" ) )
-	{
-		char u[80], v[80], w[80];
-
-		ASE_GetToken( qfalse );
-
-		ASE_GetToken( qfalse );
-		strcpy( u, s_token );
-
-		ASE_GetToken( qfalse );
-		strcpy( v, s_token );
-
-		ASE_GetToken( qfalse );
-		strcpy( w, s_token );
-
-		pMesh->tvertexes[pMesh->currentVertex].s = atof( u );
-		pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof( v );
-
-		pMesh->currentVertex++;
-
-		if ( pMesh->currentVertex > pMesh->numTVertexes )
-		{
-			Error( "pMesh->currentVertex > pMesh->numTVertexes" );
-		}
-	}
-	else
-	{
-		Error( "Unknown token '%s' while parsing MESH_TVERTLIST" );
-	}
-}
-
-static void ASE_KeyMESH( const char *token )
-{
-	aseMesh_t *pMesh = ASE_GetCurrentMesh();
-
-	if ( !strcmp( token, "*TIMEVALUE" ) )
-	{
-		ASE_GetToken( qfalse );
-
-		pMesh->timeValue = atoi( s_token );
-		VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) );
-	}
-	else if ( !strcmp( token, "*MESH_NUMVERTEX" ) )
-	{
-		ASE_GetToken( qfalse );
-
-		pMesh->numVertexes = atoi( s_token );
-		VERBOSE( ( ".....TIMEVALUE: %d\n", pMesh->timeValue ) );
-		VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) );
-	}
-	else if ( !strcmp( token, "*MESH_NUMFACES" ) )
-	{
-		ASE_GetToken( qfalse );
-
-		pMesh->numFaces = atoi( s_token );
-		VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) );
-	}
-	else if ( !strcmp( token, "*MESH_NUMTVFACES" ) )
-	{
-		ASE_GetToken( qfalse );
-
-		if ( atoi( s_token ) != pMesh->numFaces )
-		{
-			Error( "MESH_NUMTVFACES != MESH_NUMFACES" );
-		}
-	}
-	else if ( !strcmp( token, "*MESH_NUMTVERTEX" ) )
-	{
-		ASE_GetToken( qfalse );
-
-		pMesh->numTVertexes = atoi( s_token );
-		VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) );
-	}
-	else if ( !strcmp( token, "*MESH_VERTEX_LIST" ) )
-	{
-		pMesh->vertexes = calloc( sizeof( aseVertex_t ) * pMesh->numVertexes, 1 );
-		pMesh->currentVertex = 0;
-		VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) );
-		ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST );
-	}
-	else if ( !strcmp( token, "*MESH_TVERTLIST" ) )
-	{
-		pMesh->currentVertex = 0;
-		pMesh->tvertexes = calloc( sizeof( aseTVertex_t ) * pMesh->numTVertexes, 1 );
-		VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) );
-		ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST );
-	}
-	else if ( !strcmp( token, "*MESH_FACE_LIST" ) )
-	{
-		pMesh->faces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
-		pMesh->currentFace = 0;
-		VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) );
-		ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST );
-	}
-	else if ( !strcmp( token, "*MESH_TFACELIST" ) )
-	{
-		pMesh->tfaces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
-		pMesh->currentFace = 0;
-		VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) );
-		ASE_ParseBracedBlock( ASE_KeyTFACE_LIST );
-	}
-	else if ( !strcmp( token, "*MESH_NORMALS" ) )
-	{
-		ASE_ParseBracedBlock( 0 );
-	}
-}
-
-static void ASE_KeyMESH_ANIMATION( const char *token )
-{
-	aseMesh_t *pMesh = ASE_GetCurrentMesh();
-
-	// loads a single animation frame
-	if ( !strcmp( token, "*MESH" ) )
-	{
-		VERBOSE( ( "...found MESH\n" ) );
-		assert( pMesh->faces == 0 );
-		assert( pMesh->vertexes == 0 );
-		assert( pMesh->tvertexes == 0 );
-		memset( pMesh, 0, sizeof( *pMesh ) );
-
-		ASE_ParseBracedBlock( ASE_KeyMESH );
-
-		if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES )
-		{
-			Error( "Too many animation frames" );
-		}
-	}
-	else
-	{
-		Error( "Unknown token '%s' while parsing MESH_ANIMATION", token );
-	}
-}
-
-static void ASE_KeyGEOMOBJECT( const char *token )
-{
-	if ( !strcmp( token, "*NODE_NAME" ) )
-	{
-		char *name = ase.objects[ase.currentObject].name;
-
-		ASE_GetToken( qtrue );
-		VERBOSE( ( " %s\n", s_token ) );
-		strcpy( ase.objects[ase.currentObject].name, s_token + 1 );
-		if ( strchr( ase.objects[ase.currentObject].name, '"' ) )
-			*strchr( ase.objects[ase.currentObject].name, '"' ) = 0;
-
-		if ( strstr( name, "tag" ) == name )
-		{
-			while ( strchr( name, '_' ) != strrchr( name, '_' ) )
-			{
-				*strrchr( name, '_' ) = 0;
-			}
-			while ( strrchr( name, ' ' ) )
-			{
-				*strrchr( name, ' ' ) = 0;
-			}
-		}
-	}
-	else if ( !strcmp( token, "*NODE_PARENT" ) )
-	{
-		ASE_SkipRestOfLine();
-	}
-	// ignore unused data blocks
-	else if ( !strcmp( token, "*NODE_TM" ) ||
-		      !strcmp( token, "*TM_ANIMATION" ) )
-	{
-		ASE_ParseBracedBlock( 0 );
-	}
-	// ignore regular meshes that aren't part of animation
-	else if ( !strcmp( token, "*MESH" ) && !ase.grabAnims )
-	{
-/*
-		if ( strstr( ase.objects[ase.currentObject].name, "tag_" ) == ase.objects[ase.currentObject].name ) 
-		{
-			s_forceStaticMesh = true;
-			ASE_ParseBracedBlock( ASE_KeyMESH );
-			s_forceStaticMesh = false;
-		}
-*/
-		ASE_ParseBracedBlock( ASE_KeyMESH );
-		if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES )
-		{
-			Error( "Too many animation frames" );
-		}
-		ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
-		ase.objects[ase.currentObject].numAnimations++;
-/*
-		// ignore meshes that aren't part of animations if this object isn't a 
-		// a tag
-		else
-		{
-			ASE_ParseBracedBlock( 0 );
-		}
-*/
-	}
-	// according to spec these are obsolete
-	else if ( !strcmp( token, "*MATERIAL_REF" ) )
-	{
-		ASE_GetToken( qfalse );
-
-		ase.objects[ase.currentObject].materialRef = atoi( s_token );
-	}
-	// loads a sequence of animation frames
-	else if ( !strcmp( token, "*MESH_ANIMATION" ) )
-	{
-		if ( ase.grabAnims )
-		{
-			VERBOSE( ( "..found MESH_ANIMATION\n" ) );
-
-			if ( ase.objects[ase.currentObject].numAnimations )
-			{
-				Error( "Multiple MESH_ANIMATIONS within a single GEOM_OBJECT" );
-			}
-			ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION );
-			ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
-			ase.objects[ase.currentObject].numAnimations++;
-		}
-		else
-		{
-			ASE_SkipEnclosingBraces();
-		}
-	}
-	// skip unused info
-	else if ( !strcmp( token, "*PROP_MOTIONBLUR" ) ||
-		      !strcmp( token, "*PROP_CASTSHADOW" ) ||
-			  !strcmp( token, "*PROP_RECVSHADOW" ) )
-	{
-		ASE_SkipRestOfLine();
-	}
-}
-
-static void ConcatenateObjects( aseGeomObject_t *pObjA, aseGeomObject_t *pObjB )
-{
-}
-
-static void CollapseObjects( void )
-{
-	int i;
-	int numObjects = ase.currentObject;
-
-	for ( i = 0; i < numObjects; i++ )
-	{
-		int j;
-
-		// skip tags
-		if ( strstr( ase.objects[i].name, "tag" ) == ase.objects[i].name )
-		{
-			continue;
-		}
-
-		if ( !ase.objects[i].numAnimations )
-		{
-			continue;
-		}
-
-		for ( j = i + 1; j < numObjects; j++ )
-		{
-			if ( strstr( ase.objects[j].name, "tag" ) == ase.objects[j].name )
-			{
-				continue;
-			}
-			if ( ase.objects[i].materialRef == ase.objects[j].materialRef )
-			{
-				if ( ase.objects[j].numAnimations )
-				{
-					ConcatenateObjects( &ase.objects[i], &ase.objects[j] );
-				}
-			}
-		}
-	}
-}
-
-/*
-** ASE_Process
-*/
-static void ASE_Process( void )
-{
-	while ( ASE_GetToken( qfalse ) )
-	{
-		if ( !strcmp( s_token, "*3DSMAX_ASCIIEXPORT" ) ||
-			 !strcmp( s_token, "*COMMENT" ) )
-		{
-			ASE_SkipRestOfLine();
-		}
-		else if ( !strcmp( s_token, "*SCENE" ) )
-			ASE_SkipEnclosingBraces();
-		else if ( !strcmp( s_token, "*MATERIAL_LIST" ) )
-		{
-			VERBOSE( ("MATERIAL_LIST\n") );
-
-			ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST );
-		}
-		else if ( !strcmp( s_token, "*GEOMOBJECT" ) )
-		{
-			VERBOSE( ("GEOMOBJECT" ) );
-
-			ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT );
-
-			if ( strstr( ase.objects[ase.currentObject].name, "Bip" ) ||
-				 strstr( ase.objects[ase.currentObject].name, "ignore_" ) )
-			{
-				ASE_FreeGeomObject( ase.currentObject );
-				VERBOSE( ( "(discarding BIP/ignore object)\n" ) );
-			}
-			else if ( ( strstr( ase.objects[ase.currentObject].name, "h_" ) != ase.objects[ase.currentObject].name ) &&
-				      ( strstr( ase.objects[ase.currentObject].name, "l_" ) != ase.objects[ase.currentObject].name ) &&
-					  ( strstr( ase.objects[ase.currentObject].name, "u_" ) != ase.objects[ase.currentObject].name ) &&
-					  ( strstr( ase.objects[ase.currentObject].name, "tag" ) != ase.objects[ase.currentObject].name ) &&
-					  ase.grabAnims )
-			{
-				VERBOSE( ( "(ignoring improperly labeled object '%s')\n", ase.objects[ase.currentObject].name ) );
-				ASE_FreeGeomObject( ase.currentObject );
-			}
-			else
-			{
-				if ( ++ase.currentObject == MAX_ASE_OBJECTS )
-				{
-					Error( "Too many GEOMOBJECTs" );
-				}
-			}
-		}
-		else if ( s_token[0] )
-		{
-			Sys_Printf( "Unknown token '%s'\n", s_token );
-		}
-	}
-
-	if ( !ase.currentObject )
-		Error( "No animation data!" );
-
-	CollapseObjects();
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "aselib.h"
+#include "inout.h"
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#define MAX_ASE_MATERIALS			32
+#define MAX_ASE_OBJECTS				64
+#define MAX_ASE_ANIMATIONS			32
+#define MAX_ASE_ANIMATION_FRAMES	512
+
+#define VERBOSE( x ) { if ( ase.verbose ) { Sys_Printf x ; } }
+
+typedef struct
+{
+	float x, y, z;
+	float nx, ny, nz;
+	float s, t;
+} aseVertex_t;
+
+typedef struct
+{
+	float s, t;
+} aseTVertex_t;
+
+typedef int aseFace_t[3];
+
+typedef struct
+{
+	int numFaces;
+	int numVertexes;
+	int numTVertexes;
+
+	int timeValue;
+
+	aseVertex_t		*vertexes;
+	aseTVertex_t	*tvertexes;
+	aseFace_t		*faces, *tfaces;
+
+	int currentFace, currentVertex;
+} aseMesh_t;
+
+typedef struct
+{
+	int			numFrames;
+	aseMesh_t	frames[MAX_ASE_ANIMATION_FRAMES];
+
+	int		   currentFrame;
+} aseMeshAnimation_t;
+
+typedef struct
+{
+	char name[128];
+} aseMaterial_t;
+
+/*
+** contains the animate sequence of a single surface
+** using a single material
+*/
+typedef struct
+{
+	char name[128];
+
+	int materialRef;
+	int numAnimations;
+
+	aseMeshAnimation_t	anim;
+
+} aseGeomObject_t;
+
+typedef struct
+{
+	int				numMaterials;
+	aseMaterial_t	materials[MAX_ASE_MATERIALS];
+	aseGeomObject_t objects[MAX_ASE_OBJECTS];
+
+	char	*buffer;
+	char	*curpos;
+	int		 len;
+
+	int			currentObject;
+	qboolean	verbose;
+	qboolean	grabAnims;
+
+} ase_t;
+
+static char s_token[1024];
+static ase_t ase;
+static char gl_filename[1024];
+
+static void ASE_Process( void );
+static void ASE_FreeGeomObject( int ndx );
+
+#if defined (__linux__) || defined (__APPLE__)
+
+static char* strlwr (char* string)
+{
+  char *cp;
+  for (cp = string; *cp; ++cp)
+  {
+    if ('A' <= *cp && *cp <= 'Z')
+      *cp += 'a' - 'A';
+  }
+ 
+  return string;
+}
+
+#endif
+
+/*
+** ASE_Load
+*/
+void ASE_Load( const char *filename, qboolean verbose, qboolean grabAnims )
+{
+	FILE *fp = fopen( filename, "rb" );
+
+	if ( !fp )
+		Error( "File not found '%s'", filename );
+
+	memset( &ase, 0, sizeof( ase ) );
+
+	ase.verbose = verbose;
+	ase.grabAnims = grabAnims;
+	ase.len = Q_filelength( fp );
+
+	ase.curpos = ase.buffer = safe_malloc( ase.len );
+
+	Sys_Printf( "Processing '%s'\n", filename );
+
+	if ( fread( ase.buffer, ase.len, 1, fp ) != 1 )
+	{
+		fclose( fp );
+		Error( "fread() != -1 for '%s'", filename );
+	}
+
+	fclose( fp );
+
+        strcpy(gl_filename, filename);
+        
+	ASE_Process();
+}
+
+/*
+** ASE_Free
+*/
+void ASE_Free( void )
+{
+	int i;
+
+	for ( i = 0; i < ase.currentObject; i++ )
+	{
+		ASE_FreeGeomObject( i );
+	}
+}
+
+/*
+** ASE_GetNumSurfaces
+*/
+int ASE_GetNumSurfaces( void )
+{
+	return ase.currentObject;
+}
+
+/*
+** ASE_GetSurfaceName
+*/
+const char *ASE_GetSurfaceName( int which )
+{
+	aseGeomObject_t *pObject = &ase.objects[which];
+
+	if ( !pObject->anim.numFrames )
+		return 0;
+
+	return pObject->name;
+}
+
+/*
+** ASE_GetSurfaceAnimation
+**
+** Returns an animation (sequence of polysets)
+*/
+polyset_t *ASE_GetSurfaceAnimation( int which, int *pNumFrames, int skipFrameStart, int skipFrameEnd, int maxFrames )
+{
+	aseGeomObject_t *pObject = &ase.objects[which];
+	polyset_t *psets;
+	int numFramesInAnimation;
+	int numFramesToKeep;
+	int i, f;
+
+	if ( !pObject->anim.numFrames )
+		return 0;
+
+	if ( pObject->anim.numFrames > maxFrames && maxFrames != -1 )
+	{
+		numFramesInAnimation = maxFrames;
+	}
+	else 
+	{
+		numFramesInAnimation = pObject->anim.numFrames;
+		if ( maxFrames != -1 )
+			Sys_Printf( "WARNING: ASE_GetSurfaceAnimation maxFrames > numFramesInAnimation\n" );
+	}
+
+	if ( skipFrameEnd != -1 )
+		numFramesToKeep = numFramesInAnimation - ( skipFrameEnd - skipFrameStart + 1 );
+	else
+		numFramesToKeep = numFramesInAnimation;
+
+	*pNumFrames = numFramesToKeep;
+
+	psets = calloc( sizeof( polyset_t ) * numFramesToKeep, 1 );
+
+	for ( f = 0, i = 0; i < numFramesInAnimation; i++ )
+	{
+		int t;
+		aseMesh_t *pMesh = &pObject->anim.frames[i];
+
+		if ( skipFrameStart != -1 )
+		{
+			if ( i >= skipFrameStart && i <= skipFrameEnd )
+				continue;
+		}
+
+		strcpy( psets[f].name, pObject->name );
+		strcpy( psets[f].materialname, ase.materials[pObject->materialRef].name );
+
+		psets[f].triangles = calloc( sizeof( triangle_t ) * pObject->anim.frames[i].numFaces, 1 );
+		psets[f].numtriangles = pObject->anim.frames[i].numFaces;
+
+		for ( t = 0; t < pObject->anim.frames[i].numFaces; t++ )
+		{
+			int k;
+
+			for ( k = 0; k < 3; k++ )
+			{
+				psets[f].triangles[t].verts[k][0] = pMesh->vertexes[pMesh->faces[t][k]].x;
+				psets[f].triangles[t].verts[k][1] = pMesh->vertexes[pMesh->faces[t][k]].y;
+				psets[f].triangles[t].verts[k][2] = pMesh->vertexes[pMesh->faces[t][k]].z;
+
+				if ( pMesh->tvertexes && pMesh->tfaces )
+				{
+					psets[f].triangles[t].texcoords[k][0] = pMesh->tvertexes[pMesh->tfaces[t][k]].s;
+					psets[f].triangles[t].texcoords[k][1] = pMesh->tvertexes[pMesh->tfaces[t][k]].t;
+				}
+
+			}
+		}
+
+		f++;
+	}
+
+	return psets;
+}
+
+static void ASE_FreeGeomObject( int ndx )
+{
+	aseGeomObject_t *pObject;
+	int i;
+
+	pObject = &ase.objects[ndx];
+
+	for ( i = 0; i < pObject->anim.numFrames; i++ )
+	{
+		if ( pObject->anim.frames[i].vertexes )
+		{
+			free( pObject->anim.frames[i].vertexes );
+		}
+		if ( pObject->anim.frames[i].tvertexes )
+		{
+			free( pObject->anim.frames[i].tvertexes );
+		}
+		if ( pObject->anim.frames[i].faces )
+		{
+			free( pObject->anim.frames[i].faces );
+		}
+		if ( pObject->anim.frames[i].tfaces )
+		{
+			free( pObject->anim.frames[i].tfaces );
+		}
+	}
+
+	memset( pObject, 0, sizeof( *pObject ) );
+}
+
+static aseMesh_t *ASE_GetCurrentMesh( void )
+{
+	aseGeomObject_t *pObject;
+
+	if ( ase.currentObject >= MAX_ASE_OBJECTS )
+	{
+		Error( "Too many GEOMOBJECTs" );
+		return 0; // never called
+	}
+
+	pObject = &ase.objects[ase.currentObject];
+
+	if ( pObject->anim.currentFrame >= MAX_ASE_ANIMATION_FRAMES )
+	{
+		Error( "Too many MESHes" );
+		return 0;
+	}
+
+	return &pObject->anim.frames[pObject->anim.currentFrame];
+}
+
+static int CharIsTokenDelimiter( int ch )
+{
+	if ( ch <= 32 )
+		return 1;
+	return 0;
+}
+
+static int ASE_GetToken( qboolean restOfLine )
+{
+	int i = 0;
+
+	if ( ase.buffer == 0 )
+		return 0;
+
+	if ( ( ase.curpos - ase.buffer ) == ase.len )
+		return 0;
+
+	// skip over crap
+	while ( ( ( ase.curpos - ase.buffer ) < ase.len ) &&
+		    ( *ase.curpos <= 32 ) )
+	{
+		ase.curpos++;
+	}
+
+	while ( ( ase.curpos - ase.buffer ) < ase.len )
+	{
+		s_token[i] = *ase.curpos;
+
+		ase.curpos++;
+		i++;
+
+		if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
+			 ( ( s_token[i-1] == '\n' ) || ( s_token[i-1] == '\r' ) ) )
+		{
+			s_token[i-1] = 0;
+			break;
+		}
+	}
+
+	s_token[i] = 0;
+
+	return 1;
+}
+
+static void ASE_ParseBracedBlock( void (*parser)( const char *token ) )
+{
+	int indent = 0;
+
+	while ( ASE_GetToken( qfalse ) )
+	{
+		if ( !strcmp( s_token, "{" ) )
+		{
+			indent++;
+		}
+		else if ( !strcmp( s_token, "}" ) )
+		{
+			--indent;
+			if ( indent == 0 )
+				break;
+			else if ( indent < 0 )
+				Error( "Unexpected '}'" );
+		}
+		else
+		{
+			if ( parser )
+				parser( s_token );
+		}
+	}
+}
+
+static void ASE_SkipEnclosingBraces( void )
+{
+	int indent = 0;
+
+	while ( ASE_GetToken( qfalse ) )
+	{
+		if ( !strcmp( s_token, "{" ) )
+		{
+			indent++;
+		}
+		else if ( !strcmp( s_token, "}" ) )
+		{
+			indent--;
+			if ( indent == 0 )
+				break;
+			else if ( indent < 0 )
+				Error( "Unexpected '}'" );
+		}
+	}
+}
+
+static void ASE_SkipRestOfLine( void )
+{
+	ASE_GetToken( qtrue );
+}
+
+static void ASE_KeyMAP_DIFFUSE( const char *token )
+{
+	char fullpath[1024], bitmap[1024], modeldir[1024];
+	char filename[1024];
+	int i = 0, count;
+
+	strcpy(filename, gl_filename);
+
+	if ( !strcmp( token, "*BITMAP" ) )
+	{
+		ASE_GetToken( qfalse );
+
+		// the purpose of this whole chunk of code below is to extract the relative path
+		// from a full path in the ASE
+			
+		strcpy( bitmap, s_token + 1 );
+		if ( strchr( bitmap, '"' ) )
+			*strchr( bitmap, '"' ) = 0;
+
+		/* convert backslash to slash */
+		while ( bitmap[i] )
+		{
+			if ( bitmap[i] == '\\' )
+				bitmap[i] = '/';
+			i++;
+		}
+
+		/* remove filename from path */
+		for( i=strlen(filename); i>0; i--)
+		{
+			if(filename[i] == '/')
+			{
+				filename[i] = '\0';
+				break;
+			}
+		}
+
+		/* replaces a relative path with a full path */
+		if(bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/')
+		{
+			while(bitmap[0] == '.' && bitmap[1] == '.' && bitmap[2] == '/')
+			{
+				/* remove last item from path */
+				for( i=strlen(filename); i>0; i--)
+				{
+					if(filename[i] == '/')
+					{
+						filename[i] = '\0';
+						break;
+					}
+				}
+				strcpy(bitmap, &bitmap[3]);
+			}
+			strcat(filename, "/");
+			strcat(filename, bitmap);
+			strcpy(bitmap, filename);
+		}
+
+		if ( strstr( bitmap, gamedir ) )
+		{
+			strcpy( ase.materials[ase.numMaterials].name, strstr( bitmap, gamedir ) + strlen( gamedir ) );
+			Sys_Printf("material name: \'%s\'\n", strstr( bitmap, gamedir ) + strlen( gamedir ) );
+		}
+		else
+		{
+			sprintf( ase.materials[ase.numMaterials].name, "(not converted: '%s')", bitmap );
+			Sys_Printf( "WARNING: illegal material name '%s'\n", bitmap );
+		}
+	}
+	else
+	{
+	}
+}
+
+static void ASE_KeyMATERIAL( const char *token )
+{
+	if ( !strcmp( token, "*MAP_DIFFUSE" ) )
+	{
+		ASE_ParseBracedBlock( ASE_KeyMAP_DIFFUSE );
+	}
+	else
+	{
+	}
+}
+
+static void ASE_KeyMATERIAL_LIST( const char *token )
+{
+	if ( !strcmp( token, "*MATERIAL_COUNT" ) )
+	{
+		ASE_GetToken( qfalse );
+		VERBOSE( ( "..num materials: %s\n", s_token ) );
+		if ( atoi( s_token ) > MAX_ASE_MATERIALS )
+		{
+			Error( "Too many materials!" );
+		}
+		ase.numMaterials = 0;
+	}
+	else if ( !strcmp( token, "*MATERIAL" ) )
+	{
+		VERBOSE( ( "..material %d ", ase.numMaterials ) );
+		ASE_ParseBracedBlock( ASE_KeyMATERIAL );
+		ase.numMaterials++;
+	}
+}
+
+static void ASE_KeyMESH_VERTEX_LIST( const char *token )
+{
+	aseMesh_t *pMesh = ASE_GetCurrentMesh();
+
+	if ( !strcmp( token, "*MESH_VERTEX" ) )
+	{
+		ASE_GetToken( qfalse );		// skip number
+
+		ASE_GetToken( qfalse );
+		pMesh->vertexes[pMesh->currentVertex].y = atof( s_token );
+
+		ASE_GetToken( qfalse );
+		pMesh->vertexes[pMesh->currentVertex].x = -atof( s_token );
+
+		ASE_GetToken( qfalse );
+		pMesh->vertexes[pMesh->currentVertex].z = atof( s_token );
+
+		pMesh->currentVertex++;
+
+		if ( pMesh->currentVertex > pMesh->numVertexes )
+		{
+			Error( "pMesh->currentVertex >= pMesh->numVertexes" );
+		}
+	}
+	else
+	{
+		Error( "Unknown token '%s' while parsing MESH_VERTEX_LIST", token );
+	}
+}
+
+static void ASE_KeyMESH_FACE_LIST( const char *token )
+{
+	aseMesh_t *pMesh = ASE_GetCurrentMesh();
+
+	if ( !strcmp( token, "*MESH_FACE" ) )
+	{
+		ASE_GetToken( qfalse );	// skip face number
+
+		ASE_GetToken( qfalse );	// skip label
+		ASE_GetToken( qfalse );	// first vertex
+		pMesh->faces[pMesh->currentFace][0] = atoi( s_token );
+
+		ASE_GetToken( qfalse );	// skip label
+		ASE_GetToken( qfalse );	// second vertex
+		pMesh->faces[pMesh->currentFace][2] = atoi( s_token );
+
+		ASE_GetToken( qfalse );	// skip label
+		ASE_GetToken( qfalse );	// third vertex
+		pMesh->faces[pMesh->currentFace][1] = atoi( s_token );
+
+		ASE_GetToken( qtrue );
+
+/*
+		if ( ( p = strstr( s_token, "*MESH_MTLID" ) ) != 0 )
+		{
+			p += strlen( "*MESH_MTLID" ) + 1;
+			mtlID = atoi( p );
+		}
+		else
+		{
+			Error( "No *MESH_MTLID found for face!" );
+		}
+*/
+
+		pMesh->currentFace++;
+	}
+	else
+	{
+		Error( "Unknown token '%s' while parsing MESH_FACE_LIST", token );
+	}
+}
+
+static void ASE_KeyTFACE_LIST( const char *token )
+{
+	aseMesh_t *pMesh = ASE_GetCurrentMesh();
+
+	if ( !strcmp( token, "*MESH_TFACE" ) )
+	{
+		int a, b, c;
+
+		ASE_GetToken( qfalse );
+
+		ASE_GetToken( qfalse );
+		a = atoi( s_token );
+		ASE_GetToken( qfalse );
+		c = atoi( s_token );
+		ASE_GetToken( qfalse );
+		b = atoi( s_token );
+
+		pMesh->tfaces[pMesh->currentFace][0] = a;
+		pMesh->tfaces[pMesh->currentFace][1] = b;
+		pMesh->tfaces[pMesh->currentFace][2] = c;
+
+		pMesh->currentFace++;
+	}
+	else
+	{
+		Error( "Unknown token '%s' in MESH_TFACE", token );
+	}
+}
+
+static void ASE_KeyMESH_TVERTLIST( const char *token )
+{
+	aseMesh_t *pMesh = ASE_GetCurrentMesh();
+
+	if ( !strcmp( token, "*MESH_TVERT" ) )
+	{
+		char u[80], v[80], w[80];
+
+		ASE_GetToken( qfalse );
+
+		ASE_GetToken( qfalse );
+		strcpy( u, s_token );
+
+		ASE_GetToken( qfalse );
+		strcpy( v, s_token );
+
+		ASE_GetToken( qfalse );
+		strcpy( w, s_token );
+
+		pMesh->tvertexes[pMesh->currentVertex].s = atof( u );
+		pMesh->tvertexes[pMesh->currentVertex].t = 1.0f - atof( v );
+
+		pMesh->currentVertex++;
+
+		if ( pMesh->currentVertex > pMesh->numTVertexes )
+		{
+			Error( "pMesh->currentVertex > pMesh->numTVertexes" );
+		}
+	}
+	else
+	{
+		Error( "Unknown token '%s' while parsing MESH_TVERTLIST" );
+	}
+}
+
+static void ASE_KeyMESH( const char *token )
+{
+	aseMesh_t *pMesh = ASE_GetCurrentMesh();
+
+	if ( !strcmp( token, "*TIMEVALUE" ) )
+	{
+		ASE_GetToken( qfalse );
+
+		pMesh->timeValue = atoi( s_token );
+		VERBOSE( ( ".....timevalue: %d\n", pMesh->timeValue ) );
+	}
+	else if ( !strcmp( token, "*MESH_NUMVERTEX" ) )
+	{
+		ASE_GetToken( qfalse );
+
+		pMesh->numVertexes = atoi( s_token );
+		VERBOSE( ( ".....TIMEVALUE: %d\n", pMesh->timeValue ) );
+		VERBOSE( ( ".....num vertexes: %d\n", pMesh->numVertexes ) );
+	}
+	else if ( !strcmp( token, "*MESH_NUMFACES" ) )
+	{
+		ASE_GetToken( qfalse );
+
+		pMesh->numFaces = atoi( s_token );
+		VERBOSE( ( ".....num faces: %d\n", pMesh->numFaces ) );
+	}
+	else if ( !strcmp( token, "*MESH_NUMTVFACES" ) )
+	{
+		ASE_GetToken( qfalse );
+
+		if ( atoi( s_token ) != pMesh->numFaces )
+		{
+			Error( "MESH_NUMTVFACES != MESH_NUMFACES" );
+		}
+	}
+	else if ( !strcmp( token, "*MESH_NUMTVERTEX" ) )
+	{
+		ASE_GetToken( qfalse );
+
+		pMesh->numTVertexes = atoi( s_token );
+		VERBOSE( ( ".....num tvertexes: %d\n", pMesh->numTVertexes ) );
+	}
+	else if ( !strcmp( token, "*MESH_VERTEX_LIST" ) )
+	{
+		pMesh->vertexes = calloc( sizeof( aseVertex_t ) * pMesh->numVertexes, 1 );
+		pMesh->currentVertex = 0;
+		VERBOSE( ( ".....parsing MESH_VERTEX_LIST\n" ) );
+		ASE_ParseBracedBlock( ASE_KeyMESH_VERTEX_LIST );
+	}
+	else if ( !strcmp( token, "*MESH_TVERTLIST" ) )
+	{
+		pMesh->currentVertex = 0;
+		pMesh->tvertexes = calloc( sizeof( aseTVertex_t ) * pMesh->numTVertexes, 1 );
+		VERBOSE( ( ".....parsing MESH_TVERTLIST\n" ) );
+		ASE_ParseBracedBlock( ASE_KeyMESH_TVERTLIST );
+	}
+	else if ( !strcmp( token, "*MESH_FACE_LIST" ) )
+	{
+		pMesh->faces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
+		pMesh->currentFace = 0;
+		VERBOSE( ( ".....parsing MESH_FACE_LIST\n" ) );
+		ASE_ParseBracedBlock( ASE_KeyMESH_FACE_LIST );
+	}
+	else if ( !strcmp( token, "*MESH_TFACELIST" ) )
+	{
+		pMesh->tfaces = calloc( sizeof( aseFace_t ) * pMesh->numFaces, 1 );
+		pMesh->currentFace = 0;
+		VERBOSE( ( ".....parsing MESH_TFACE_LIST\n" ) );
+		ASE_ParseBracedBlock( ASE_KeyTFACE_LIST );
+	}
+	else if ( !strcmp( token, "*MESH_NORMALS" ) )
+	{
+		ASE_ParseBracedBlock( 0 );
+	}
+}
+
+static void ASE_KeyMESH_ANIMATION( const char *token )
+{
+	aseMesh_t *pMesh = ASE_GetCurrentMesh();
+
+	// loads a single animation frame
+	if ( !strcmp( token, "*MESH" ) )
+	{
+		VERBOSE( ( "...found MESH\n" ) );
+		assert( pMesh->faces == 0 );
+		assert( pMesh->vertexes == 0 );
+		assert( pMesh->tvertexes == 0 );
+		memset( pMesh, 0, sizeof( *pMesh ) );
+
+		ASE_ParseBracedBlock( ASE_KeyMESH );
+
+		if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES )
+		{
+			Error( "Too many animation frames" );
+		}
+	}
+	else
+	{
+		Error( "Unknown token '%s' while parsing MESH_ANIMATION", token );
+	}
+}
+
+static void ASE_KeyGEOMOBJECT( const char *token )
+{
+	if ( !strcmp( token, "*NODE_NAME" ) )
+	{
+		char *name = ase.objects[ase.currentObject].name;
+
+		ASE_GetToken( qtrue );
+		VERBOSE( ( " %s\n", s_token ) );
+		strcpy( ase.objects[ase.currentObject].name, s_token + 1 );
+		if ( strchr( ase.objects[ase.currentObject].name, '"' ) )
+			*strchr( ase.objects[ase.currentObject].name, '"' ) = 0;
+
+		if ( strstr( name, "tag" ) == name )
+		{
+			while ( strchr( name, '_' ) != strrchr( name, '_' ) )
+			{
+				*strrchr( name, '_' ) = 0;
+			}
+			while ( strrchr( name, ' ' ) )
+			{
+				*strrchr( name, ' ' ) = 0;
+			}
+		}
+	}
+	else if ( !strcmp( token, "*NODE_PARENT" ) )
+	{
+		ASE_SkipRestOfLine();
+	}
+	// ignore unused data blocks
+	else if ( !strcmp( token, "*NODE_TM" ) ||
+		      !strcmp( token, "*TM_ANIMATION" ) )
+	{
+		ASE_ParseBracedBlock( 0 );
+	}
+	// ignore regular meshes that aren't part of animation
+	else if ( !strcmp( token, "*MESH" ) && !ase.grabAnims )
+	{
+/*
+		if ( strstr( ase.objects[ase.currentObject].name, "tag_" ) == ase.objects[ase.currentObject].name ) 
+		{
+			s_forceStaticMesh = true;
+			ASE_ParseBracedBlock( ASE_KeyMESH );
+			s_forceStaticMesh = false;
+		}
+*/
+		ASE_ParseBracedBlock( ASE_KeyMESH );
+		if ( ++ase.objects[ase.currentObject].anim.currentFrame == MAX_ASE_ANIMATION_FRAMES )
+		{
+			Error( "Too many animation frames" );
+		}
+		ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
+		ase.objects[ase.currentObject].numAnimations++;
+/*
+		// ignore meshes that aren't part of animations if this object isn't a 
+		// a tag
+		else
+		{
+			ASE_ParseBracedBlock( 0 );
+		}
+*/
+	}
+	// according to spec these are obsolete
+	else if ( !strcmp( token, "*MATERIAL_REF" ) )
+	{
+		ASE_GetToken( qfalse );
+
+		ase.objects[ase.currentObject].materialRef = atoi( s_token );
+	}
+	// loads a sequence of animation frames
+	else if ( !strcmp( token, "*MESH_ANIMATION" ) )
+	{
+		if ( ase.grabAnims )
+		{
+			VERBOSE( ( "..found MESH_ANIMATION\n" ) );
+
+			if ( ase.objects[ase.currentObject].numAnimations )
+			{
+				Error( "Multiple MESH_ANIMATIONS within a single GEOM_OBJECT" );
+			}
+			ASE_ParseBracedBlock( ASE_KeyMESH_ANIMATION );
+			ase.objects[ase.currentObject].anim.numFrames = ase.objects[ase.currentObject].anim.currentFrame;
+			ase.objects[ase.currentObject].numAnimations++;
+		}
+		else
+		{
+			ASE_SkipEnclosingBraces();
+		}
+	}
+	// skip unused info
+	else if ( !strcmp( token, "*PROP_MOTIONBLUR" ) ||
+		      !strcmp( token, "*PROP_CASTSHADOW" ) ||
+			  !strcmp( token, "*PROP_RECVSHADOW" ) )
+	{
+		ASE_SkipRestOfLine();
+	}
+}
+
+static void ConcatenateObjects( aseGeomObject_t *pObjA, aseGeomObject_t *pObjB )
+{
+}
+
+static void CollapseObjects( void )
+{
+	int i;
+	int numObjects = ase.currentObject;
+
+	for ( i = 0; i < numObjects; i++ )
+	{
+		int j;
+
+		// skip tags
+		if ( strstr( ase.objects[i].name, "tag" ) == ase.objects[i].name )
+		{
+			continue;
+		}
+
+		if ( !ase.objects[i].numAnimations )
+		{
+			continue;
+		}
+
+		for ( j = i + 1; j < numObjects; j++ )
+		{
+			if ( strstr( ase.objects[j].name, "tag" ) == ase.objects[j].name )
+			{
+				continue;
+			}
+			if ( ase.objects[i].materialRef == ase.objects[j].materialRef )
+			{
+				if ( ase.objects[j].numAnimations )
+				{
+					ConcatenateObjects( &ase.objects[i], &ase.objects[j] );
+				}
+			}
+		}
+	}
+}
+
+/*
+** ASE_Process
+*/
+static void ASE_Process( void )
+{
+	while ( ASE_GetToken( qfalse ) )
+	{
+		if ( !strcmp( s_token, "*3DSMAX_ASCIIEXPORT" ) ||
+			 !strcmp( s_token, "*COMMENT" ) )
+		{
+			ASE_SkipRestOfLine();
+		}
+		else if ( !strcmp( s_token, "*SCENE" ) )
+			ASE_SkipEnclosingBraces();
+		else if ( !strcmp( s_token, "*MATERIAL_LIST" ) )
+		{
+			VERBOSE( ("MATERIAL_LIST\n") );
+
+			ASE_ParseBracedBlock( ASE_KeyMATERIAL_LIST );
+		}
+		else if ( !strcmp( s_token, "*GEOMOBJECT" ) )
+		{
+			VERBOSE( ("GEOMOBJECT" ) );
+
+			ASE_ParseBracedBlock( ASE_KeyGEOMOBJECT );
+
+			if ( strstr( ase.objects[ase.currentObject].name, "Bip" ) ||
+				 strstr( ase.objects[ase.currentObject].name, "ignore_" ) )
+			{
+				ASE_FreeGeomObject( ase.currentObject );
+				VERBOSE( ( "(discarding BIP/ignore object)\n" ) );
+			}
+			else if ( ( strstr( ase.objects[ase.currentObject].name, "h_" ) != ase.objects[ase.currentObject].name ) &&
+				      ( strstr( ase.objects[ase.currentObject].name, "l_" ) != ase.objects[ase.currentObject].name ) &&
+					  ( strstr( ase.objects[ase.currentObject].name, "u_" ) != ase.objects[ase.currentObject].name ) &&
+					  ( strstr( ase.objects[ase.currentObject].name, "tag" ) != ase.objects[ase.currentObject].name ) &&
+					  ase.grabAnims )
+			{
+				VERBOSE( ( "(ignoring improperly labeled object '%s')\n", ase.objects[ase.currentObject].name ) );
+				ASE_FreeGeomObject( ase.currentObject );
+			}
+			else
+			{
+				if ( ++ase.currentObject == MAX_ASE_OBJECTS )
+				{
+					Error( "Too many GEOMOBJECTs" );
+				}
+			}
+		}
+		else if ( s_token[0] )
+		{
+			Sys_Printf( "Unknown token '%s'\n", s_token );
+		}
+	}
+
+	if ( !ase.currentObject )
+		Error( "No animation data!" );
+
+	CollapseObjects();
+}
diff --git a/tools/quake3/common/aselib.h b/tools/quake3/common/aselib.h
index 4ff9b234..e3e62adb 100644
--- a/tools/quake3/common/aselib.h
+++ b/tools/quake3/common/aselib.h
@@ -1,31 +1,31 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "../common/cmdlib.h"
-#include "mathlib.h"
-#include "polyset.h"
-
-void		ASE_Load( const char *filename, qboolean verbose, qboolean meshanims );
-int			ASE_GetNumSurfaces( void );
-polyset_t	*ASE_GetSurfaceAnimation( int ndx, int *numFrames, int skipFrameStart, int skipFrameEnd, int maxFrames );
-const char  *ASE_GetSurfaceName( int ndx );
-void		ASE_Free( void );
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "../common/cmdlib.h"
+#include "mathlib.h"
+#include "polyset.h"
+
+void		ASE_Load( const char *filename, qboolean verbose, qboolean meshanims );
+int			ASE_GetNumSurfaces( void );
+polyset_t	*ASE_GetSurfaceAnimation( int ndx, int *numFrames, int skipFrameStart, int skipFrameEnd, int maxFrames );
+const char  *ASE_GetSurfaceName( int ndx );
+void		ASE_Free( void );
diff --git a/tools/quake3/common/bspfile.c b/tools/quake3/common/bspfile.c
index edc3cd65..3ce497a7 100644
--- a/tools/quake3/common/bspfile.c
+++ b/tools/quake3/common/bspfile.c
@@ -1,706 +1,706 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include "bspfile.h"
-#include "scriplib.h"
-
-void GetLeafNums (void);
-
-//=============================================================================
-
-int     bsp_version = Q3_BSP_VERSION;
-
-int			nummodels;
-dmodel_t	dmodels[MAX_MAP_MODELS];
-
-int			numShaders;
-dshader_t	dshaders[MAX_MAP_SHADERS];
-
-int			entdatasize;
-char		dentdata[MAX_MAP_ENTSTRING];
-
-int			numleafs;
-dleaf_t		dleafs[MAX_MAP_LEAFS];
-
-int			numplanes;
-dplane_t	dplanes[MAX_MAP_PLANES];
-
-int			numnodes;
-dnode_t		dnodes[MAX_MAP_NODES];
-
-int			numleafsurfaces;
-int			dleafsurfaces[MAX_MAP_LEAFFACES];
-
-int			numleafbrushes;
-int			dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-int			numbrushes;
-dbrush_t	dbrushes[MAX_MAP_BRUSHES];
-
-int			numbrushsides;
-dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
-
-int			numLightBytes;
-byte		*lightBytes;
-
-int			numGridPoints;
-byte		*gridData;
-
-int			numVisBytes;
-byte		visBytes[MAX_MAP_VISIBILITY];
-
-int			numDrawVerts = 0;
-int         numDrawVertsBuffer = 0;
-drawVert_t	*drawVerts = NULL;
-
-int			numDrawIndexes;
-int			drawIndexes[MAX_MAP_DRAW_INDEXES];
-
-int			numDrawSurfaces;
-int         numDrawSurfacesBuffer = 0;
-dsurface_t	*drawSurfaces = NULL;
-
-int			numFogs;
-dfog_t		dfogs[MAX_MAP_FOGS];
-
-void SetLightBytes(int n)
-{
-	if(lightBytes != 0)
-		free(lightBytes);
-
-	numLightBytes = n;
-
-	if(n == 0)
-		return;
-
-	lightBytes = safe_malloc_info(numLightBytes, "SetLightBytes");
-
-	memset(lightBytes, 0, numLightBytes);
-}
-
-void SetGridPoints(int n)
-{
-	if(gridData != 0)
-		free(gridData);
-
-	numGridPoints = n;
-
-	if(n == 0)
-		return;
-
-  gridData = safe_malloc_info(numGridPoints * 8, "SetGridPoints");
-
-	memset(gridData, 0, numGridPoints * 8);
-}
-
-void IncDrawVerts()
-{
-	numDrawVerts++;
-
-	if(drawVerts == 0)
-	{
-		numDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
-		
-		drawVerts = safe_malloc_info(sizeof(drawVert_t) * numDrawVertsBuffer, "IncDrawVerts");
-
-	}
-	else if(numDrawVerts > numDrawVertsBuffer)
-	{
-		numDrawVertsBuffer *= 3; // multiply by 1.5
-		numDrawVertsBuffer /= 2;
-
-		if(numDrawVertsBuffer > MAX_MAP_DRAW_VERTS)
-			numDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
-
-		drawVerts = realloc(drawVerts, sizeof(drawVert_t) * numDrawVertsBuffer);
-
-		if(!drawVerts)
-			Error( "realloc() failed (IncDrawVerts)");
-	}
-
-	memset(drawVerts + (numDrawVerts - 1), 0, sizeof(drawVert_t));
-}
-
-void SetDrawVerts(int n)
-{
-	if(drawVerts != 0)
-		free(drawVerts);
-
-	numDrawVerts = n;
-	numDrawVertsBuffer = numDrawVerts;
-
-	drawVerts = safe_malloc_info(sizeof(drawVert_t) * numDrawVertsBuffer, "IncDrawVerts");
-
-	memset(drawVerts, 0, n * sizeof(drawVert_t));
-}
-
-void SetDrawSurfacesBuffer()
-{
-	if(drawSurfaces != 0)
-		free(drawSurfaces);
-
-	numDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
-
-	drawSurfaces = safe_malloc_info(sizeof(dsurface_t) * numDrawSurfacesBuffer, "IncDrawSurfaces");
-
-	memset(drawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof(drawVert_t));
-}
-
-void SetDrawSurfaces(int n)
-{
-	if(drawSurfaces != 0)
-		free(drawSurfaces);
-
-	numDrawSurfaces = n;
-	numDrawSurfacesBuffer = numDrawSurfaces;
-
-	drawSurfaces = safe_malloc_info(sizeof(dsurface_t) * numDrawSurfacesBuffer, "IncDrawSurfaces");
-
-	memset(drawSurfaces, 0, n * sizeof(drawVert_t));
-}
-
-void BspFilesCleanup()
-{
-	if(drawVerts != 0)
-		free(drawVerts);
-	if(drawSurfaces != 0)
-		free(drawSurfaces);
-	if(lightBytes != 0)
-		free(lightBytes);
-	if(gridData != 0)
-		free(gridData);
-}
-
-//=============================================================================
-
-/*
-=============
-SwapBlock
-
-If all values are 32 bits, this can be used to swap everything
-=============
-*/
-void SwapBlock( int *block, int sizeOfBlock ) {
-	int		i;
-
-	sizeOfBlock >>= 2;
-	for ( i = 0 ; i < sizeOfBlock ; i++ ) {
-		block[i] = LittleLong( block[i] );
-	}
-}
-
-/*
-=============
-SwapBSPFile
-
-Byte swaps all data in a bsp file.
-=============
-*/
-void SwapBSPFile( void ) {
-	int				i;
-	
-	// models	
-	SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) );
-
-	// shaders (don't swap the name)
-	for ( i = 0 ; i < numShaders ; i++ ) {
-		dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags );
-		dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags );
-	}
-
-	// planes
-	SwapBlock( (int *)dplanes, numplanes * sizeof( dplanes[0] ) );
-	
-	// nodes
-	SwapBlock( (int *)dnodes, numnodes * sizeof( dnodes[0] ) );
-
-	// leafs
-	SwapBlock( (int *)dleafs, numleafs * sizeof( dleafs[0] ) );
-
-	// leaffaces
-	SwapBlock( (int *)dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
-
-	// leafbrushes
-	SwapBlock( (int *)dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
-
-	// brushes
-	SwapBlock( (int *)dbrushes, numbrushes * sizeof( dbrushes[0] ) );
-
-	// brushsides
-	SwapBlock( (int *)dbrushsides, numbrushsides * sizeof( dbrushsides[0] ) );
-
-	// vis
-	((int *)&visBytes)[0] = LittleLong( ((int *)&visBytes)[0] );
-	((int *)&visBytes)[1] = LittleLong( ((int *)&visBytes)[1] );
-
-	// drawverts (don't swap colors )
-	for ( i = 0 ; i < numDrawVerts ; i++ ) {
-		drawVerts[i].lightmap[0] = LittleFloat( drawVerts[i].lightmap[0] );
-		drawVerts[i].lightmap[1] = LittleFloat( drawVerts[i].lightmap[1] );
-		drawVerts[i].st[0] = LittleFloat( drawVerts[i].st[0] );
-		drawVerts[i].st[1] = LittleFloat( drawVerts[i].st[1] );
-		drawVerts[i].xyz[0] = LittleFloat( drawVerts[i].xyz[0] );
-		drawVerts[i].xyz[1] = LittleFloat( drawVerts[i].xyz[1] );
-		drawVerts[i].xyz[2] = LittleFloat( drawVerts[i].xyz[2] );
-		drawVerts[i].normal[0] = LittleFloat( drawVerts[i].normal[0] );
-		drawVerts[i].normal[1] = LittleFloat( drawVerts[i].normal[1] );
-		drawVerts[i].normal[2] = LittleFloat( drawVerts[i].normal[2] );
-	}
-
-	// drawindexes
-	SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
-
-	// drawsurfs
-	SwapBlock( (int *)drawSurfaces, numDrawSurfaces * sizeof( drawSurfaces[0] ) );
-
-	// fogs
-	for ( i = 0 ; i < numFogs ; i++ ) {
-		dfogs[i].brushNum = LittleLong( dfogs[i].brushNum );
-		dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide );
-	}
-}
-
-
-
-/*
-=============
-GetLumpElements
-=============
-*/
-int GetLumpElements( dheader_t	*header, int lump, int size ) {
-	int		length, ofs;
-
-	length = header->lumps[lump].filelen;
-	ofs = header->lumps[lump].fileofs;
-	
-	if ( length % size ) {
-		Error ("LoadBSPFile: odd lump size");
-	}
-
-	return length / size;
-}
-
-/*
-=============
-CopyLump
-=============
-*/
-int CopyLump( dheader_t	*header, int lump, void *dest, int size ) {
-	int		length, ofs;
-
-	length = header->lumps[lump].filelen;
-	ofs = header->lumps[lump].fileofs;
-	
-	if(length == 0)
-		return 0;
-	
-	if ( length % size ) {
-		Error ("LoadBSPFile: odd lump size");
-	}
-
-	memcpy( dest, (byte *)header + ofs, length );
-
-	return length / size;
-}
-
-/*
-=============
-LoadBSPFile
-=============
-*/
-void	LoadBSPFile( const char *filename ) {
-	dheader_t	*header;
-
-	// load the file header
-	LoadFile (filename, (void **)&header);
-
-	// swap the header
-	SwapBlock( (int *)header, sizeof(*header) );
-
-	if ( header->ident != BSP_IDENT ) {
-		Error( "%s is not a IBSP file", filename );
-	}
-	if ( header->version != bsp_version ) {
-		Error( "%s is version %i, not %i", filename, header->version, bsp_version );
-	}
-
-	numShaders = CopyLump( header, LUMP_SHADERS, dshaders, sizeof(dshader_t) );
-	nummodels = CopyLump( header, LUMP_MODELS, dmodels, sizeof(dmodel_t) );
-	numplanes = CopyLump( header, LUMP_PLANES, dplanes, sizeof(dplane_t) );
-	numleafs = CopyLump( header, LUMP_LEAFS, dleafs, sizeof(dleaf_t) );
-	numnodes = CopyLump( header, LUMP_NODES, dnodes, sizeof(dnode_t) );
-	numleafsurfaces = CopyLump( header, LUMP_LEAFSURFACES, dleafsurfaces, sizeof(dleafsurfaces[0]) );
-	numleafbrushes = CopyLump( header, LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]) );
-	numbrushes = CopyLump( header, LUMP_BRUSHES, dbrushes, sizeof(dbrush_t) );
-	numbrushsides = CopyLump( header, LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t) );
-	numDrawVerts = GetLumpElements( header, LUMP_DRAWVERTS, sizeof(drawVert_t) );
-		SetDrawVerts(numDrawVerts);
-		CopyLump( header, LUMP_DRAWVERTS, drawVerts, sizeof(drawVert_t) );
-	numDrawSurfaces = GetLumpElements( header, LUMP_SURFACES, sizeof(dsurface_t) );
-		SetDrawSurfaces(numDrawSurfaces);
-		numDrawSurfaces = CopyLump( header, LUMP_SURFACES, drawSurfaces, sizeof(dsurface_t) );
-	numFogs = CopyLump( header, LUMP_FOGS, dfogs, sizeof(dfog_t) );
-	numDrawIndexes = CopyLump( header, LUMP_DRAWINDEXES, drawIndexes, sizeof(drawIndexes[0]) );
-
-	numVisBytes = CopyLump( header, LUMP_VISIBILITY, visBytes, 1 );
-	numLightBytes = GetLumpElements( header, LUMP_LIGHTMAPS, 1 );
-		SetLightBytes(numLightBytes);
-		CopyLump( header, LUMP_LIGHTMAPS, lightBytes, 1 );
-	entdatasize = CopyLump( header, LUMP_ENTITIES, dentdata, 1);
-
-	numGridPoints = GetLumpElements( header, LUMP_LIGHTGRID, 8 );
-		SetGridPoints(numGridPoints);
-		CopyLump( header, LUMP_LIGHTGRID, gridData, 8 );
-
-
-	free( header );		// everything has been copied out
-		
-	// swap everything
-	SwapBSPFile();
-}
-
-
-//============================================================================
-
-/*
-=============
-AddLump
-=============
-*/
-void AddLump( FILE *bspfile, dheader_t *header, int lumpnum, const void *data, int len ) {
-	lump_t *lump;
-
-	lump = &header->lumps[lumpnum];
-	
-	lump->fileofs = LittleLong( ftell(bspfile) );
-	lump->filelen = LittleLong( len );
-	SafeWrite( bspfile, data, (len+3)&~3 );
-}
-
-/*
-=============
-WriteBSPFile
-
-Swaps the bsp file in place, so it should not be referenced again
-=============
-*/
-void	WriteBSPFile( const char *filename ) {		
-	dheader_t	outheader, *header;
-	FILE		*bspfile;
-
-	header = &outheader;
-	memset( header, 0, sizeof(dheader_t) );
-	
-	SwapBSPFile();
-
-	header->ident = LittleLong( BSP_IDENT );
-	header->version = LittleLong( bsp_version );
-	
-	bspfile = SafeOpenWrite( filename );
-	SafeWrite( bspfile, header, sizeof(dheader_t) );	// overwritten later
-
-	AddLump( bspfile, header, LUMP_SHADERS, dshaders, numShaders*sizeof(dshader_t) );
-	AddLump( bspfile, header, LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t) );
-	AddLump( bspfile, header, LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t) );
-	AddLump( bspfile, header, LUMP_NODES, dnodes, numnodes*sizeof(dnode_t) );
-	AddLump( bspfile, header, LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t) );
-	AddLump( bspfile, header, LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t) );
-	AddLump( bspfile, header, LUMP_LEAFSURFACES, dleafsurfaces, numleafsurfaces*sizeof(dleafsurfaces[0]) );
-	AddLump( bspfile, header, LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]) );
-	AddLump( bspfile, header, LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t) );
-	AddLump( bspfile, header, LUMP_DRAWVERTS, drawVerts, numDrawVerts*sizeof(drawVert_t) );
-	AddLump( bspfile, header, LUMP_SURFACES, drawSurfaces, numDrawSurfaces*sizeof(dsurface_t) );
-	AddLump( bspfile, header, LUMP_VISIBILITY, visBytes, numVisBytes );
-	AddLump( bspfile, header, LUMP_LIGHTMAPS, lightBytes, numLightBytes );
-	AddLump( bspfile, header, LUMP_LIGHTGRID, gridData, 8 * numGridPoints );
-	AddLump( bspfile, header, LUMP_ENTITIES, dentdata, entdatasize );
-	AddLump( bspfile, header, LUMP_FOGS, dfogs, numFogs * sizeof(dfog_t) );
-	AddLump( bspfile, header, LUMP_DRAWINDEXES, drawIndexes, numDrawIndexes * sizeof(drawIndexes[0]) );
-	
-	fseek (bspfile, 0, SEEK_SET);
-	SafeWrite (bspfile, header, sizeof(dheader_t));
-	fclose (bspfile);	
-}
-
-//============================================================================
-
-/*
-=============
-PrintBSPFileSizes
-
-Dumps info about current file
-=============
-*/
-void PrintBSPFileSizes( void ) {
-	if ( !num_entities ) {
-		ParseEntities();
-	}
-
-	Sys_Printf ("%6i models       %7i\n"
-		,nummodels, (int)(nummodels*sizeof(dmodel_t)));
-	Sys_Printf ("%6i shaders      %7i\n"
-		,numShaders, (int)(numShaders*sizeof(dshader_t)));
-	Sys_Printf ("%6i brushes      %7i\n"
-		,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
-	Sys_Printf ("%6i brushsides   %7i\n"
-		,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
-	Sys_Printf ("%6i fogs         %7i\n"
-		,numFogs, (int)(numFogs*sizeof(dfog_t)));
-	Sys_Printf ("%6i planes       %7i\n"
-		,numplanes, (int)(numplanes*sizeof(dplane_t)));
-	Sys_Printf ("%6i entdata      %7i\n", num_entities, entdatasize);
-
-	Sys_Printf ("\n");
-
-	Sys_Printf ("%6i nodes        %7i\n"
-		,numnodes, (int)(numnodes*sizeof(dnode_t)));
-	Sys_Printf ("%6i leafs        %7i\n"
-		,numleafs, (int)(numleafs*sizeof(dleaf_t)));
-	Sys_Printf ("%6i leafsurfaces %7i\n"
-		,numleafsurfaces, (int)(numleafsurfaces*sizeof(dleafsurfaces[0])));
-	Sys_Printf ("%6i leafbrushes  %7i\n"
-		,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
-	Sys_Printf ("%6i drawverts    %7i\n"
-		,numDrawVerts, (int)(numDrawVerts*sizeof(drawVerts[0])));
-	Sys_Printf ("%6i drawindexes  %7i\n"
-		,numDrawIndexes, (int)(numDrawIndexes*sizeof(drawIndexes[0])));
-	Sys_Printf ("%6i drawsurfaces %7i\n"
-		,numDrawSurfaces, (int)(numDrawSurfaces*sizeof(drawSurfaces[0])));
-
-	Sys_Printf ("%6i lightmaps    %7i\n"
-		,numLightBytes / (LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*3), numLightBytes );
-	Sys_Printf ("       visibility   %7i\n"
-		, numVisBytes );
-}
-
-
-//============================================
-
-int			num_entities;
-entity_t	entities[MAX_MAP_ENTITIES];
-
-void StripTrailing( char *e ) {
-	char	*s;
-
-	s = e + strlen(e)-1;
-	while (s >= e && *s <= 32)
-	{
-		*s = 0;
-		s--;
-	}
-}
-
-/*
-=================
-ParseEpair
-=================
-*/
-epair_t *ParseEpair( void ) {
-	epair_t	*e;
-
-	e = safe_malloc( sizeof(epair_t) );
-	memset( e, 0, sizeof(epair_t) );
-	
-	if ( strlen(token) >= MAX_KEY-1 ) {
-		Error ("ParseEpar: token too long");
-	}
-	e->key = copystring( token );
-	GetToken( qfalse );
-	if ( strlen(token) >= MAX_VALUE-1 ) {
-		Error ("ParseEpar: token too long");
-	}
-	e->value = copystring( token );
-
-	// strip trailing spaces that sometimes get accidentally
-	// added in the editor
-	StripTrailing( e->key );
-	StripTrailing( e->value );
-
-	return e;
-}
-
-
-/*
-================
-ParseEntity
-================
-*/
-qboolean	ParseEntity( void ) {
-	epair_t		*e;
-	entity_t	*mapent;
-
-	if ( !GetToken (qtrue) ) {
-		return qfalse;
-	}
-
-	if ( strcmp (token, "{") ) {
-		Error ("ParseEntity: { not found");
-	}
-	if ( num_entities == MAX_MAP_ENTITIES ) {
-		Error ("num_entities == MAX_MAP_ENTITIES");
-	}
-	mapent = &entities[num_entities];
-	num_entities++;
-
-	do {
-		if ( !GetToken (qtrue) ) {
-			Error ("ParseEntity: EOF without closing brace");
-		}
-		if ( !strcmp (token, "}") ) {
-			break;
-		}
-		e = ParseEpair ();
-		e->next = mapent->epairs;
-		mapent->epairs = e;
-	} while (1);
-	
-	return qtrue;
-}
-
-/*
-================
-ParseEntities
-
-Parses the dentdata string into entities
-================
-*/
-void ParseEntities( void ) {
-	num_entities = 0;
-	ParseFromMemory( dentdata, entdatasize );
-
-	while ( ParseEntity () ) {
-	}	
-}
-
-
-/*
-================
-UnparseEntities
-
-Generates the dentdata string from all the entities
-This allows the utilities to add or remove key/value pairs
-to the data created by the map editor.
-================
-*/
-void UnparseEntities( void ) {
-	char	*buf, *end;
-	epair_t	*ep;
-	char	line[2048];
-	int		i;
-	char	key[1024], value[1024];
-
-	buf = dentdata;
-	end = buf;
-	*end = 0;
-	
-	for (i=0 ; i<num_entities ; i++) {
-		ep = entities[i].epairs;
-		if ( !ep ) {
-			continue;	// ent got removed
-		}
-		
-		strcat (end,"{\n");
-		end += 2;
-				
-		for ( ep = entities[i].epairs ; ep ; ep=ep->next ) {
-			strcpy (key, ep->key);
-			StripTrailing (key);
-			strcpy (value, ep->value);
-			StripTrailing (value);
-				
-			sprintf (line, "\"%s\" \"%s\"\n", key, value);
-			strcat (end, line);
-			end += strlen(line);
-		}
-		strcat (end,"}\n");
-		end += 2;
-
-		if (end > buf + MAX_MAP_ENTSTRING) {
-			Error ("Entity text too long");
-		}
-	}
-	entdatasize = end - buf + 1;
-}
-
-void PrintEntity( const entity_t *ent ) {
-	epair_t	*ep;
-	
-	Sys_Printf ("------- entity %p -------\n", ent);
-	for (ep=ent->epairs ; ep ; ep=ep->next) {
-		Sys_Printf( "%s = %s\n", ep->key, ep->value );
-	}
-
-}
-
-void 	SetKeyValue( entity_t *ent, const char *key, const char *value ) {
-	epair_t	*ep;
-	
-	for ( ep=ent->epairs ; ep ; ep=ep->next ) {
-		if ( !strcmp (ep->key, key) ) {
-			free (ep->value);
-			ep->value = copystring(value);
-			return;
-		}
-	}
-	ep = safe_malloc (sizeof(*ep));
-	ep->next = ent->epairs;
-	ent->epairs = ep;
-	ep->key = copystring(key);
-	ep->value = copystring(value);
-}
-
-const char 	*ValueForKey( const entity_t *ent, const char *key ) {
-	epair_t	*ep;
-	
-	for (ep=ent->epairs ; ep ; ep=ep->next) {
-		if (!strcmp (ep->key, key) ) {
-			return ep->value;
-		}
-	}
-	return "";
-}
-
-vec_t	FloatForKey( const entity_t *ent, const char *key ) {
-	const char	*k;
-	
-	k = ValueForKey( ent, key );
-	return atof(k);
-}
-
-void 	GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec ) {
-	const char	*k;
-	double	v1, v2, v3;
-
-	k = ValueForKey (ent, key);
-
-	// scanf into doubles, then assign, so it is vec_t size independent
-	v1 = v2 = v3 = 0;
-	sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
-	vec[0] = v1;
-	vec[1] = v2;
-	vec[2] = v3;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include "bspfile.h"
+#include "scriplib.h"
+
+void GetLeafNums (void);
+
+//=============================================================================
+
+int     bsp_version = Q3_BSP_VERSION;
+
+int			nummodels;
+dmodel_t	dmodels[MAX_MAP_MODELS];
+
+int			numShaders;
+dshader_t	dshaders[MAX_MAP_SHADERS];
+
+int			entdatasize;
+char		dentdata[MAX_MAP_ENTSTRING];
+
+int			numleafs;
+dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+int			numplanes;
+dplane_t	dplanes[MAX_MAP_PLANES];
+
+int			numnodes;
+dnode_t		dnodes[MAX_MAP_NODES];
+
+int			numleafsurfaces;
+int			dleafsurfaces[MAX_MAP_LEAFFACES];
+
+int			numleafbrushes;
+int			dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+int			numbrushes;
+dbrush_t	dbrushes[MAX_MAP_BRUSHES];
+
+int			numbrushsides;
+dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
+
+int			numLightBytes;
+byte		*lightBytes;
+
+int			numGridPoints;
+byte		*gridData;
+
+int			numVisBytes;
+byte		visBytes[MAX_MAP_VISIBILITY];
+
+int			numDrawVerts = 0;
+int         numDrawVertsBuffer = 0;
+drawVert_t	*drawVerts = NULL;
+
+int			numDrawIndexes;
+int			drawIndexes[MAX_MAP_DRAW_INDEXES];
+
+int			numDrawSurfaces;
+int         numDrawSurfacesBuffer = 0;
+dsurface_t	*drawSurfaces = NULL;
+
+int			numFogs;
+dfog_t		dfogs[MAX_MAP_FOGS];
+
+void SetLightBytes(int n)
+{
+	if(lightBytes != 0)
+		free(lightBytes);
+
+	numLightBytes = n;
+
+	if(n == 0)
+		return;
+
+	lightBytes = safe_malloc_info(numLightBytes, "SetLightBytes");
+
+	memset(lightBytes, 0, numLightBytes);
+}
+
+void SetGridPoints(int n)
+{
+	if(gridData != 0)
+		free(gridData);
+
+	numGridPoints = n;
+
+	if(n == 0)
+		return;
+
+  gridData = safe_malloc_info(numGridPoints * 8, "SetGridPoints");
+
+	memset(gridData, 0, numGridPoints * 8);
+}
+
+void IncDrawVerts()
+{
+	numDrawVerts++;
+
+	if(drawVerts == 0)
+	{
+		numDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
+		
+		drawVerts = safe_malloc_info(sizeof(drawVert_t) * numDrawVertsBuffer, "IncDrawVerts");
+
+	}
+	else if(numDrawVerts > numDrawVertsBuffer)
+	{
+		numDrawVertsBuffer *= 3; // multiply by 1.5
+		numDrawVertsBuffer /= 2;
+
+		if(numDrawVertsBuffer > MAX_MAP_DRAW_VERTS)
+			numDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
+
+		drawVerts = realloc(drawVerts, sizeof(drawVert_t) * numDrawVertsBuffer);
+
+		if(!drawVerts)
+			Error( "realloc() failed (IncDrawVerts)");
+	}
+
+	memset(drawVerts + (numDrawVerts - 1), 0, sizeof(drawVert_t));
+}
+
+void SetDrawVerts(int n)
+{
+	if(drawVerts != 0)
+		free(drawVerts);
+
+	numDrawVerts = n;
+	numDrawVertsBuffer = numDrawVerts;
+
+	drawVerts = safe_malloc_info(sizeof(drawVert_t) * numDrawVertsBuffer, "IncDrawVerts");
+
+	memset(drawVerts, 0, n * sizeof(drawVert_t));
+}
+
+void SetDrawSurfacesBuffer()
+{
+	if(drawSurfaces != 0)
+		free(drawSurfaces);
+
+	numDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
+
+	drawSurfaces = safe_malloc_info(sizeof(dsurface_t) * numDrawSurfacesBuffer, "IncDrawSurfaces");
+
+	memset(drawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof(drawVert_t));
+}
+
+void SetDrawSurfaces(int n)
+{
+	if(drawSurfaces != 0)
+		free(drawSurfaces);
+
+	numDrawSurfaces = n;
+	numDrawSurfacesBuffer = numDrawSurfaces;
+
+	drawSurfaces = safe_malloc_info(sizeof(dsurface_t) * numDrawSurfacesBuffer, "IncDrawSurfaces");
+
+	memset(drawSurfaces, 0, n * sizeof(drawVert_t));
+}
+
+void BspFilesCleanup()
+{
+	if(drawVerts != 0)
+		free(drawVerts);
+	if(drawSurfaces != 0)
+		free(drawSurfaces);
+	if(lightBytes != 0)
+		free(lightBytes);
+	if(gridData != 0)
+		free(gridData);
+}
+
+//=============================================================================
+
+/*
+=============
+SwapBlock
+
+If all values are 32 bits, this can be used to swap everything
+=============
+*/
+void SwapBlock( int *block, int sizeOfBlock ) {
+	int		i;
+
+	sizeOfBlock >>= 2;
+	for ( i = 0 ; i < sizeOfBlock ; i++ ) {
+		block[i] = LittleLong( block[i] );
+	}
+}
+
+/*
+=============
+SwapBSPFile
+
+Byte swaps all data in a bsp file.
+=============
+*/
+void SwapBSPFile( void ) {
+	int				i;
+	
+	// models	
+	SwapBlock( (int *)dmodels, nummodels * sizeof( dmodels[0] ) );
+
+	// shaders (don't swap the name)
+	for ( i = 0 ; i < numShaders ; i++ ) {
+		dshaders[i].contentFlags = LittleLong( dshaders[i].contentFlags );
+		dshaders[i].surfaceFlags = LittleLong( dshaders[i].surfaceFlags );
+	}
+
+	// planes
+	SwapBlock( (int *)dplanes, numplanes * sizeof( dplanes[0] ) );
+	
+	// nodes
+	SwapBlock( (int *)dnodes, numnodes * sizeof( dnodes[0] ) );
+
+	// leafs
+	SwapBlock( (int *)dleafs, numleafs * sizeof( dleafs[0] ) );
+
+	// leaffaces
+	SwapBlock( (int *)dleafsurfaces, numleafsurfaces * sizeof( dleafsurfaces[0] ) );
+
+	// leafbrushes
+	SwapBlock( (int *)dleafbrushes, numleafbrushes * sizeof( dleafbrushes[0] ) );
+
+	// brushes
+	SwapBlock( (int *)dbrushes, numbrushes * sizeof( dbrushes[0] ) );
+
+	// brushsides
+	SwapBlock( (int *)dbrushsides, numbrushsides * sizeof( dbrushsides[0] ) );
+
+	// vis
+	((int *)&visBytes)[0] = LittleLong( ((int *)&visBytes)[0] );
+	((int *)&visBytes)[1] = LittleLong( ((int *)&visBytes)[1] );
+
+	// drawverts (don't swap colors )
+	for ( i = 0 ; i < numDrawVerts ; i++ ) {
+		drawVerts[i].lightmap[0] = LittleFloat( drawVerts[i].lightmap[0] );
+		drawVerts[i].lightmap[1] = LittleFloat( drawVerts[i].lightmap[1] );
+		drawVerts[i].st[0] = LittleFloat( drawVerts[i].st[0] );
+		drawVerts[i].st[1] = LittleFloat( drawVerts[i].st[1] );
+		drawVerts[i].xyz[0] = LittleFloat( drawVerts[i].xyz[0] );
+		drawVerts[i].xyz[1] = LittleFloat( drawVerts[i].xyz[1] );
+		drawVerts[i].xyz[2] = LittleFloat( drawVerts[i].xyz[2] );
+		drawVerts[i].normal[0] = LittleFloat( drawVerts[i].normal[0] );
+		drawVerts[i].normal[1] = LittleFloat( drawVerts[i].normal[1] );
+		drawVerts[i].normal[2] = LittleFloat( drawVerts[i].normal[2] );
+	}
+
+	// drawindexes
+	SwapBlock( (int *)drawIndexes, numDrawIndexes * sizeof( drawIndexes[0] ) );
+
+	// drawsurfs
+	SwapBlock( (int *)drawSurfaces, numDrawSurfaces * sizeof( drawSurfaces[0] ) );
+
+	// fogs
+	for ( i = 0 ; i < numFogs ; i++ ) {
+		dfogs[i].brushNum = LittleLong( dfogs[i].brushNum );
+		dfogs[i].visibleSide = LittleLong( dfogs[i].visibleSide );
+	}
+}
+
+
+
+/*
+=============
+GetLumpElements
+=============
+*/
+int GetLumpElements( dheader_t	*header, int lump, int size ) {
+	int		length, ofs;
+
+	length = header->lumps[lump].filelen;
+	ofs = header->lumps[lump].fileofs;
+	
+	if ( length % size ) {
+		Error ("LoadBSPFile: odd lump size");
+	}
+
+	return length / size;
+}
+
+/*
+=============
+CopyLump
+=============
+*/
+int CopyLump( dheader_t	*header, int lump, void *dest, int size ) {
+	int		length, ofs;
+
+	length = header->lumps[lump].filelen;
+	ofs = header->lumps[lump].fileofs;
+	
+	if(length == 0)
+		return 0;
+	
+	if ( length % size ) {
+		Error ("LoadBSPFile: odd lump size");
+	}
+
+	memcpy( dest, (byte *)header + ofs, length );
+
+	return length / size;
+}
+
+/*
+=============
+LoadBSPFile
+=============
+*/
+void	LoadBSPFile( const char *filename ) {
+	dheader_t	*header;
+
+	// load the file header
+	LoadFile (filename, (void **)&header);
+
+	// swap the header
+	SwapBlock( (int *)header, sizeof(*header) );
+
+	if ( header->ident != BSP_IDENT ) {
+		Error( "%s is not a IBSP file", filename );
+	}
+	if ( header->version != bsp_version ) {
+		Error( "%s is version %i, not %i", filename, header->version, bsp_version );
+	}
+
+	numShaders = CopyLump( header, LUMP_SHADERS, dshaders, sizeof(dshader_t) );
+	nummodels = CopyLump( header, LUMP_MODELS, dmodels, sizeof(dmodel_t) );
+	numplanes = CopyLump( header, LUMP_PLANES, dplanes, sizeof(dplane_t) );
+	numleafs = CopyLump( header, LUMP_LEAFS, dleafs, sizeof(dleaf_t) );
+	numnodes = CopyLump( header, LUMP_NODES, dnodes, sizeof(dnode_t) );
+	numleafsurfaces = CopyLump( header, LUMP_LEAFSURFACES, dleafsurfaces, sizeof(dleafsurfaces[0]) );
+	numleafbrushes = CopyLump( header, LUMP_LEAFBRUSHES, dleafbrushes, sizeof(dleafbrushes[0]) );
+	numbrushes = CopyLump( header, LUMP_BRUSHES, dbrushes, sizeof(dbrush_t) );
+	numbrushsides = CopyLump( header, LUMP_BRUSHSIDES, dbrushsides, sizeof(dbrushside_t) );
+	numDrawVerts = GetLumpElements( header, LUMP_DRAWVERTS, sizeof(drawVert_t) );
+		SetDrawVerts(numDrawVerts);
+		CopyLump( header, LUMP_DRAWVERTS, drawVerts, sizeof(drawVert_t) );
+	numDrawSurfaces = GetLumpElements( header, LUMP_SURFACES, sizeof(dsurface_t) );
+		SetDrawSurfaces(numDrawSurfaces);
+		numDrawSurfaces = CopyLump( header, LUMP_SURFACES, drawSurfaces, sizeof(dsurface_t) );
+	numFogs = CopyLump( header, LUMP_FOGS, dfogs, sizeof(dfog_t) );
+	numDrawIndexes = CopyLump( header, LUMP_DRAWINDEXES, drawIndexes, sizeof(drawIndexes[0]) );
+
+	numVisBytes = CopyLump( header, LUMP_VISIBILITY, visBytes, 1 );
+	numLightBytes = GetLumpElements( header, LUMP_LIGHTMAPS, 1 );
+		SetLightBytes(numLightBytes);
+		CopyLump( header, LUMP_LIGHTMAPS, lightBytes, 1 );
+	entdatasize = CopyLump( header, LUMP_ENTITIES, dentdata, 1);
+
+	numGridPoints = GetLumpElements( header, LUMP_LIGHTGRID, 8 );
+		SetGridPoints(numGridPoints);
+		CopyLump( header, LUMP_LIGHTGRID, gridData, 8 );
+
+
+	free( header );		// everything has been copied out
+		
+	// swap everything
+	SwapBSPFile();
+}
+
+
+//============================================================================
+
+/*
+=============
+AddLump
+=============
+*/
+void AddLump( FILE *bspfile, dheader_t *header, int lumpnum, const void *data, int len ) {
+	lump_t *lump;
+
+	lump = &header->lumps[lumpnum];
+	
+	lump->fileofs = LittleLong( ftell(bspfile) );
+	lump->filelen = LittleLong( len );
+	SafeWrite( bspfile, data, (len+3)&~3 );
+}
+
+/*
+=============
+WriteBSPFile
+
+Swaps the bsp file in place, so it should not be referenced again
+=============
+*/
+void	WriteBSPFile( const char *filename ) {		
+	dheader_t	outheader, *header;
+	FILE		*bspfile;
+
+	header = &outheader;
+	memset( header, 0, sizeof(dheader_t) );
+	
+	SwapBSPFile();
+
+	header->ident = LittleLong( BSP_IDENT );
+	header->version = LittleLong( bsp_version );
+	
+	bspfile = SafeOpenWrite( filename );
+	SafeWrite( bspfile, header, sizeof(dheader_t) );	// overwritten later
+
+	AddLump( bspfile, header, LUMP_SHADERS, dshaders, numShaders*sizeof(dshader_t) );
+	AddLump( bspfile, header, LUMP_PLANES, dplanes, numplanes*sizeof(dplane_t) );
+	AddLump( bspfile, header, LUMP_LEAFS, dleafs, numleafs*sizeof(dleaf_t) );
+	AddLump( bspfile, header, LUMP_NODES, dnodes, numnodes*sizeof(dnode_t) );
+	AddLump( bspfile, header, LUMP_BRUSHES, dbrushes, numbrushes*sizeof(dbrush_t) );
+	AddLump( bspfile, header, LUMP_BRUSHSIDES, dbrushsides, numbrushsides*sizeof(dbrushside_t) );
+	AddLump( bspfile, header, LUMP_LEAFSURFACES, dleafsurfaces, numleafsurfaces*sizeof(dleafsurfaces[0]) );
+	AddLump( bspfile, header, LUMP_LEAFBRUSHES, dleafbrushes, numleafbrushes*sizeof(dleafbrushes[0]) );
+	AddLump( bspfile, header, LUMP_MODELS, dmodels, nummodels*sizeof(dmodel_t) );
+	AddLump( bspfile, header, LUMP_DRAWVERTS, drawVerts, numDrawVerts*sizeof(drawVert_t) );
+	AddLump( bspfile, header, LUMP_SURFACES, drawSurfaces, numDrawSurfaces*sizeof(dsurface_t) );
+	AddLump( bspfile, header, LUMP_VISIBILITY, visBytes, numVisBytes );
+	AddLump( bspfile, header, LUMP_LIGHTMAPS, lightBytes, numLightBytes );
+	AddLump( bspfile, header, LUMP_LIGHTGRID, gridData, 8 * numGridPoints );
+	AddLump( bspfile, header, LUMP_ENTITIES, dentdata, entdatasize );
+	AddLump( bspfile, header, LUMP_FOGS, dfogs, numFogs * sizeof(dfog_t) );
+	AddLump( bspfile, header, LUMP_DRAWINDEXES, drawIndexes, numDrawIndexes * sizeof(drawIndexes[0]) );
+	
+	fseek (bspfile, 0, SEEK_SET);
+	SafeWrite (bspfile, header, sizeof(dheader_t));
+	fclose (bspfile);	
+}
+
+//============================================================================
+
+/*
+=============
+PrintBSPFileSizes
+
+Dumps info about current file
+=============
+*/
+void PrintBSPFileSizes( void ) {
+	if ( !num_entities ) {
+		ParseEntities();
+	}
+
+	Sys_Printf ("%6i models       %7i\n"
+		,nummodels, (int)(nummodels*sizeof(dmodel_t)));
+	Sys_Printf ("%6i shaders      %7i\n"
+		,numShaders, (int)(numShaders*sizeof(dshader_t)));
+	Sys_Printf ("%6i brushes      %7i\n"
+		,numbrushes, (int)(numbrushes*sizeof(dbrush_t)));
+	Sys_Printf ("%6i brushsides   %7i\n"
+		,numbrushsides, (int)(numbrushsides*sizeof(dbrushside_t)));
+	Sys_Printf ("%6i fogs         %7i\n"
+		,numFogs, (int)(numFogs*sizeof(dfog_t)));
+	Sys_Printf ("%6i planes       %7i\n"
+		,numplanes, (int)(numplanes*sizeof(dplane_t)));
+	Sys_Printf ("%6i entdata      %7i\n", num_entities, entdatasize);
+
+	Sys_Printf ("\n");
+
+	Sys_Printf ("%6i nodes        %7i\n"
+		,numnodes, (int)(numnodes*sizeof(dnode_t)));
+	Sys_Printf ("%6i leafs        %7i\n"
+		,numleafs, (int)(numleafs*sizeof(dleaf_t)));
+	Sys_Printf ("%6i leafsurfaces %7i\n"
+		,numleafsurfaces, (int)(numleafsurfaces*sizeof(dleafsurfaces[0])));
+	Sys_Printf ("%6i leafbrushes  %7i\n"
+		,numleafbrushes, (int)(numleafbrushes*sizeof(dleafbrushes[0])));
+	Sys_Printf ("%6i drawverts    %7i\n"
+		,numDrawVerts, (int)(numDrawVerts*sizeof(drawVerts[0])));
+	Sys_Printf ("%6i drawindexes  %7i\n"
+		,numDrawIndexes, (int)(numDrawIndexes*sizeof(drawIndexes[0])));
+	Sys_Printf ("%6i drawsurfaces %7i\n"
+		,numDrawSurfaces, (int)(numDrawSurfaces*sizeof(drawSurfaces[0])));
+
+	Sys_Printf ("%6i lightmaps    %7i\n"
+		,numLightBytes / (LIGHTMAP_WIDTH*LIGHTMAP_HEIGHT*3), numLightBytes );
+	Sys_Printf ("       visibility   %7i\n"
+		, numVisBytes );
+}
+
+
+//============================================
+
+int			num_entities;
+entity_t	entities[MAX_MAP_ENTITIES];
+
+void StripTrailing( char *e ) {
+	char	*s;
+
+	s = e + strlen(e)-1;
+	while (s >= e && *s <= 32)
+	{
+		*s = 0;
+		s--;
+	}
+}
+
+/*
+=================
+ParseEpair
+=================
+*/
+epair_t *ParseEpair( void ) {
+	epair_t	*e;
+
+	e = safe_malloc( sizeof(epair_t) );
+	memset( e, 0, sizeof(epair_t) );
+	
+	if ( strlen(token) >= MAX_KEY-1 ) {
+		Error ("ParseEpar: token too long");
+	}
+	e->key = copystring( token );
+	GetToken( qfalse );
+	if ( strlen(token) >= MAX_VALUE-1 ) {
+		Error ("ParseEpar: token too long");
+	}
+	e->value = copystring( token );
+
+	// strip trailing spaces that sometimes get accidentally
+	// added in the editor
+	StripTrailing( e->key );
+	StripTrailing( e->value );
+
+	return e;
+}
+
+
+/*
+================
+ParseEntity
+================
+*/
+qboolean	ParseEntity( void ) {
+	epair_t		*e;
+	entity_t	*mapent;
+
+	if ( !GetToken (qtrue) ) {
+		return qfalse;
+	}
+
+	if ( strcmp (token, "{") ) {
+		Error ("ParseEntity: { not found");
+	}
+	if ( num_entities == MAX_MAP_ENTITIES ) {
+		Error ("num_entities == MAX_MAP_ENTITIES");
+	}
+	mapent = &entities[num_entities];
+	num_entities++;
+
+	do {
+		if ( !GetToken (qtrue) ) {
+			Error ("ParseEntity: EOF without closing brace");
+		}
+		if ( !strcmp (token, "}") ) {
+			break;
+		}
+		e = ParseEpair ();
+		e->next = mapent->epairs;
+		mapent->epairs = e;
+	} while (1);
+	
+	return qtrue;
+}
+
+/*
+================
+ParseEntities
+
+Parses the dentdata string into entities
+================
+*/
+void ParseEntities( void ) {
+	num_entities = 0;
+	ParseFromMemory( dentdata, entdatasize );
+
+	while ( ParseEntity () ) {
+	}	
+}
+
+
+/*
+================
+UnparseEntities
+
+Generates the dentdata string from all the entities
+This allows the utilities to add or remove key/value pairs
+to the data created by the map editor.
+================
+*/
+void UnparseEntities( void ) {
+	char	*buf, *end;
+	epair_t	*ep;
+	char	line[2048];
+	int		i;
+	char	key[1024], value[1024];
+
+	buf = dentdata;
+	end = buf;
+	*end = 0;
+	
+	for (i=0 ; i<num_entities ; i++) {
+		ep = entities[i].epairs;
+		if ( !ep ) {
+			continue;	// ent got removed
+		}
+		
+		strcat (end,"{\n");
+		end += 2;
+				
+		for ( ep = entities[i].epairs ; ep ; ep=ep->next ) {
+			strcpy (key, ep->key);
+			StripTrailing (key);
+			strcpy (value, ep->value);
+			StripTrailing (value);
+				
+			sprintf (line, "\"%s\" \"%s\"\n", key, value);
+			strcat (end, line);
+			end += strlen(line);
+		}
+		strcat (end,"}\n");
+		end += 2;
+
+		if (end > buf + MAX_MAP_ENTSTRING) {
+			Error ("Entity text too long");
+		}
+	}
+	entdatasize = end - buf + 1;
+}
+
+void PrintEntity( const entity_t *ent ) {
+	epair_t	*ep;
+	
+	Sys_Printf ("------- entity %p -------\n", ent);
+	for (ep=ent->epairs ; ep ; ep=ep->next) {
+		Sys_Printf( "%s = %s\n", ep->key, ep->value );
+	}
+
+}
+
+void 	SetKeyValue( entity_t *ent, const char *key, const char *value ) {
+	epair_t	*ep;
+	
+	for ( ep=ent->epairs ; ep ; ep=ep->next ) {
+		if ( !strcmp (ep->key, key) ) {
+			free (ep->value);
+			ep->value = copystring(value);
+			return;
+		}
+	}
+	ep = safe_malloc (sizeof(*ep));
+	ep->next = ent->epairs;
+	ent->epairs = ep;
+	ep->key = copystring(key);
+	ep->value = copystring(value);
+}
+
+const char 	*ValueForKey( const entity_t *ent, const char *key ) {
+	epair_t	*ep;
+	
+	for (ep=ent->epairs ; ep ; ep=ep->next) {
+		if (!strcmp (ep->key, key) ) {
+			return ep->value;
+		}
+	}
+	return "";
+}
+
+vec_t	FloatForKey( const entity_t *ent, const char *key ) {
+	const char	*k;
+	
+	k = ValueForKey( ent, key );
+	return atof(k);
+}
+
+void 	GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec ) {
+	const char	*k;
+	double	v1, v2, v3;
+
+	k = ValueForKey (ent, key);
+
+	// scanf into doubles, then assign, so it is vec_t size independent
+	v1 = v2 = v3 = 0;
+	sscanf (k, "%lf %lf %lf", &v1, &v2, &v3);
+	vec[0] = v1;
+	vec[1] = v2;
+	vec[2] = v3;
+}
+
+
diff --git a/tools/quake3/common/bspfile.h b/tools/quake3/common/bspfile.h
index b44285f0..c12daca8 100644
--- a/tools/quake3/common/bspfile.h
+++ b/tools/quake3/common/bspfile.h
@@ -1,121 +1,121 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qfiles.h"
-#include "surfaceflags.h"
-
-extern  int     bsp_version;
-
-extern	int			nummodels;
-extern	dmodel_t	dmodels[MAX_MAP_MODELS];
-
-extern	int			numShaders;
-extern	dshader_t	dshaders[MAX_MAP_MODELS];
-
-extern	int			entdatasize;
-extern	char		dentdata[MAX_MAP_ENTSTRING];
-
-extern	int			numleafs;
-extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
-
-extern	int			numplanes;
-extern	dplane_t	dplanes[MAX_MAP_PLANES];
-
-extern	int			numnodes;
-extern	dnode_t		dnodes[MAX_MAP_NODES];
-
-extern	int			numleafsurfaces;
-extern	int			dleafsurfaces[MAX_MAP_LEAFFACES];
-
-extern	int			numleafbrushes;
-extern	int			dleafbrushes[MAX_MAP_LEAFBRUSHES];
-
-extern	int			numbrushes;
-extern	dbrush_t	dbrushes[MAX_MAP_BRUSHES];
-
-extern	int			numbrushsides;
-extern	dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
-
-void SetLightBytes(int n);
-extern	int			numLightBytes;
-extern	byte		*lightBytes;
-
-void SetGridPoints(int n);
-extern	int			numGridPoints;
-extern	byte		*gridData;
-
-extern	int			numVisBytes;
-extern	byte		visBytes[MAX_MAP_VISIBILITY];
-
-void SetDrawVerts(int n);
-void IncDrawVerts();
-extern	int			numDrawVerts;
-extern	drawVert_t	*drawVerts;
-
-extern	int			numDrawIndexes;
-extern	int			drawIndexes[MAX_MAP_DRAW_INDEXES];
-
-void SetDrawSurfaces(int n);
-void SetDrawSurfacesBuffer();
-extern	int			numDrawSurfaces;
-extern	dsurface_t	*drawSurfaces;
-
-extern	int			numFogs;
-extern	dfog_t		dfogs[MAX_MAP_FOGS];
-
-void	LoadBSPFile( const char *filename );
-void	WriteBSPFile( const char *filename );
-void	PrintBSPFileSizes( void );
-
-//===============
-
-
-typedef struct epair_s {
-	struct epair_s	*next;
-	char	*key;
-	char	*value;
-} epair_t;
-
-typedef struct {
-	vec3_t		origin;
-	struct bspbrush_s	*brushes;
-	struct parseMesh_s	*patches;
-	int			firstDrawSurf;
-	epair_t		*epairs;
-} entity_t;
-
-extern	int			num_entities;
-extern	entity_t	entities[MAX_MAP_ENTITIES];
-
-void	ParseEntities( void );
-void	UnparseEntities( void );
-
-void 	SetKeyValue( entity_t *ent, const char *key, const char *value );
-const char 	*ValueForKey( const entity_t *ent, const char *key );
-// will return "" if not present
-
-vec_t	FloatForKey( const entity_t *ent, const char *key );
-void 	GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec );
-
-epair_t *ParseEpair( void );
-
-void	PrintEntity( const entity_t *ent );
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qfiles.h"
+#include "surfaceflags.h"
+
+extern  int     bsp_version;
+
+extern	int			nummodels;
+extern	dmodel_t	dmodels[MAX_MAP_MODELS];
+
+extern	int			numShaders;
+extern	dshader_t	dshaders[MAX_MAP_MODELS];
+
+extern	int			entdatasize;
+extern	char		dentdata[MAX_MAP_ENTSTRING];
+
+extern	int			numleafs;
+extern	dleaf_t		dleafs[MAX_MAP_LEAFS];
+
+extern	int			numplanes;
+extern	dplane_t	dplanes[MAX_MAP_PLANES];
+
+extern	int			numnodes;
+extern	dnode_t		dnodes[MAX_MAP_NODES];
+
+extern	int			numleafsurfaces;
+extern	int			dleafsurfaces[MAX_MAP_LEAFFACES];
+
+extern	int			numleafbrushes;
+extern	int			dleafbrushes[MAX_MAP_LEAFBRUSHES];
+
+extern	int			numbrushes;
+extern	dbrush_t	dbrushes[MAX_MAP_BRUSHES];
+
+extern	int			numbrushsides;
+extern	dbrushside_t	dbrushsides[MAX_MAP_BRUSHSIDES];
+
+void SetLightBytes(int n);
+extern	int			numLightBytes;
+extern	byte		*lightBytes;
+
+void SetGridPoints(int n);
+extern	int			numGridPoints;
+extern	byte		*gridData;
+
+extern	int			numVisBytes;
+extern	byte		visBytes[MAX_MAP_VISIBILITY];
+
+void SetDrawVerts(int n);
+void IncDrawVerts();
+extern	int			numDrawVerts;
+extern	drawVert_t	*drawVerts;
+
+extern	int			numDrawIndexes;
+extern	int			drawIndexes[MAX_MAP_DRAW_INDEXES];
+
+void SetDrawSurfaces(int n);
+void SetDrawSurfacesBuffer();
+extern	int			numDrawSurfaces;
+extern	dsurface_t	*drawSurfaces;
+
+extern	int			numFogs;
+extern	dfog_t		dfogs[MAX_MAP_FOGS];
+
+void	LoadBSPFile( const char *filename );
+void	WriteBSPFile( const char *filename );
+void	PrintBSPFileSizes( void );
+
+//===============
+
+
+typedef struct epair_s {
+	struct epair_s	*next;
+	char	*key;
+	char	*value;
+} epair_t;
+
+typedef struct {
+	vec3_t		origin;
+	struct bspbrush_s	*brushes;
+	struct parseMesh_s	*patches;
+	int			firstDrawSurf;
+	epair_t		*epairs;
+} entity_t;
+
+extern	int			num_entities;
+extern	entity_t	entities[MAX_MAP_ENTITIES];
+
+void	ParseEntities( void );
+void	UnparseEntities( void );
+
+void 	SetKeyValue( entity_t *ent, const char *key, const char *value );
+const char 	*ValueForKey( const entity_t *ent, const char *key );
+// will return "" if not present
+
+vec_t	FloatForKey( const entity_t *ent, const char *key );
+void 	GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec );
+
+epair_t *ParseEpair( void );
+
+void	PrintEntity( const entity_t *ent );
+
diff --git a/tools/quake3/common/cmdlib.c b/tools/quake3/common/cmdlib.c
index 17e41032..e2ea8f0a 100644
--- a/tools/quake3/common/cmdlib.c
+++ b/tools/quake3/common/cmdlib.c
@@ -1,1153 +1,1153 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// cmdlib.c
-// TTimo 09/30/2000
-// from an intial copy of common/cmdlib.c
-// stripped out the Sys_Printf Sys_Printf stuff
-
-// SPoG 05/27/2001
-// merging alpha branch into trunk
-// replaced qprintf with Sys_Printf 
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <windows.h>
-#endif
-
-#if defined (__linux__) || defined (__APPLE__)
-#include <unistd.h>
-#endif
-
-#ifdef NeXT
-#include <libc.h>
-#endif
-
-#define	BASEDIRNAME	"quake"		// assumed to have a 2 or 3 following
-#define PATHSEPERATOR   '/'
-
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size )
-{
-  void *p;
-
-  p = malloc(size);
-  if(!p)
-    Error ("safe_malloc failed on allocation of %i bytes", size);
-
-  return p;
-}
-
-void *safe_malloc_info( size_t size, char* info )
-{
-  void *p;
-
-  p = malloc(size);
-  if(!p)
-    Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
-
-  return p;
-}
-#endif
-
-// set these before calling CheckParm
-int myargc;
-char **myargv;
-
-char		com_token[1024];
-qboolean	com_eof;
-
-qboolean		archive;
-char			archivedir[1024];
-
-
-/*
-===================
-ExpandWildcards
-
-Mimic unix command line expansion
-===================
-*/
-#define	MAX_EX_ARGC	1024
-int		ex_argc;
-char	*ex_argv[MAX_EX_ARGC];
-#ifdef _WIN32
-#include "io.h"
-void ExpandWildcards( int *argc, char ***argv )
-{
-	struct _finddata_t fileinfo;
-	int		handle;
-	int		i;
-	char	filename[1024];
-	char	filebase[1024];
-	char	*path;
-
-	ex_argc = 0;
-	for (i=0 ; i<*argc ; i++)
-	{
-		path = (*argv)[i];
-		if ( path[0] == '-'
-			|| ( !strstr(path, "*") && !strstr(path, "?") ) )
-		{
-			ex_argv[ex_argc++] = path;
-			continue;
-		}
-
-		handle = _findfirst (path, &fileinfo);
-		if (handle == -1)
-			return;
-
-		ExtractFilePath (path, filebase);
-
-		do
-		{
-			sprintf (filename, "%s%s", filebase, fileinfo.name);
-			ex_argv[ex_argc++] = copystring (filename);
-		} while (_findnext( handle, &fileinfo ) != -1);
-
-		_findclose (handle);
-	}
-
-	*argc = ex_argc;
-	*argv = ex_argv;
-}
-#else
-void ExpandWildcards (int *argc, char ***argv)
-{
-}
-#endif
-
-/*
-
-qdir will hold the path up to the quake directory, including the slash
-
-  f:\quake\
-  /raid/quake/
-
-gamedir will hold qdir + the game directory (id1, id2, etc)
-
-*/
-
-char		qdir[1024];
-char		gamedir[1024];
-char		writedir[1024];
-
-void SetQdirFromPath( const char *path )
-{
-	char	temp[1024];
-	const char	*c;
-  const char *sep;
-	int		len, count;
-
-	if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
-	{	// path is partial
-		Q_getwd (temp);
-		strcat (temp, path);
-		path = temp;
-	}
-
-	// search for "quake2" in path
-
-	len = strlen(BASEDIRNAME);
-	for (c=path+strlen(path)-1 ; c != path ; c--)
-	{
-		int i;
-
-		if (!Q_strncasecmp (c, BASEDIRNAME, len))
-		{
-      //
-			//strncpy (qdir, path, c+len+2-path);
-      // the +2 assumes a 2 or 3 following quake which is not the
-      // case with a retail install
-      // so we need to add up how much to the next separator
-      sep = c + len;
-      count = 1;
-      while (*sep && *sep != '/' && *sep != '\\')
-      {
-        sep++;
-        count++;
-      }
-			strncpy (qdir, path, c+len+count-path);
-			Sys_Printf ("qdir: %s\n", qdir);
-			for ( i = 0; i < strlen( qdir ); i++ )
-			{
-				if ( qdir[i] == '\\' ) 
-					qdir[i] = '/';
-			}
-
-			c += len+count;
-			while (*c)
-			{
-				if (*c == '/' || *c == '\\')
-				{
-					strncpy (gamedir, path, c+1-path);
-
-					for ( i = 0; i < strlen( gamedir ); i++ )
-					{
-						if ( gamedir[i] == '\\' ) 
-							gamedir[i] = '/';
-					}
-
-					Sys_Printf ("gamedir: %s\n", gamedir);
-
-					if ( !writedir[0] )
-						strcpy( writedir, gamedir );
-					else if ( writedir[strlen( writedir )-1] != '/' )
-					{
-						writedir[strlen( writedir )] = '/';
-						writedir[strlen( writedir )+1] = 0;
-					}
-
-					return;
-				}
-				c++;
-			}
-			Error ("No gamedir in %s", path);
-			return;
-		}
-	}
-	Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
-}
-
-char *ExpandArg (const char *path)
-{
-	static char full[1024];
-
-	if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
-	{
-		Q_getwd (full);
-		strcat (full, path);
-	}
-	else
-		strcpy (full, path);
-	return full;
-}
-
-char *ExpandPath (const char *path)
-{
-	static char full[1024];
-	if (!qdir)
-		Error ("ExpandPath called without qdir set");
-	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
-		strcpy( full, path );
-		return full;
-	}
-	sprintf (full, "%s%s", qdir, path);
-	return full;
-}
-
-char *ExpandGamePath (const char *path)
-{
-	static char full[1024];
-	if (!qdir)
-		Error ("ExpandGamePath called without qdir set");
-	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
-		strcpy( full, path );
-		return full;
-	}
-	sprintf (full, "%s%s", gamedir, path);
-	return full;
-}
-
-char *ExpandPathAndArchive (const char *path)
-{
-	char	*expanded;
-	char	archivename[1024];
-
-	expanded = ExpandPath (path);
-
-	if (archive)
-	{
-		sprintf (archivename, "%s/%s", archivedir, path);
-		QCopyFile (expanded, archivename);
-	}
-	return expanded;
-}
-
-
-char *copystring(const char *s)
-{
-	char	*b;
-	b = safe_malloc(strlen(s)+1);
-	strcpy (b, s);
-	return b;
-}
-
-
-
-/*
-================
-I_FloatTime
-================
-*/
-double I_FloatTime (void)
-{
-	time_t	t;
-	
-	time (&t);
-	
-	return t;
-#if 0
-// more precise, less portable
-	struct timeval tp;
-	struct timezone tzp;
-	static int		secbase;
-
-	gettimeofday(&tp, &tzp);
-	
-	if (!secbase)
-	{
-		secbase = tp.tv_sec;
-		return tp.tv_usec/1000000.0;
-	}
-	
-	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
-#endif
-}
-
-void Q_getwd (char *out)
-{
-	int i = 0;
-
-#ifdef _WIN32
-   _getcwd (out, 256);
-   strcat (out, "\\");
-#else
-   // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
-   getcwd (out, 256);
-   strcat (out, "/");
-#endif
-   while ( out[i] != 0 )
-   {
-	   if ( out[i] == '\\' )
-		   out[i] = '/';
-	   i++;
-   }
-}
-
-
-void Q_mkdir (const char *path)
-{
-#ifdef _WIN32
-	if (_mkdir (path) != -1)
-		return;
-#else
-	if (mkdir (path, 0777) != -1)
-		return;
-#endif
-	if (errno != EEXIST)
-		Error ("mkdir %s: %s",path, strerror(errno));
-}
-
-/*
-============
-FileTime
-
-returns -1 if not present
-============
-*/
-int	FileTime (const char *path)
-{
-	struct	stat	buf;
-	
-	if (stat (path,&buf) == -1)
-		return -1;
-	
-	return buf.st_mtime;
-}
-
-
-
-/*
-==============
-COM_Parse
-
-Parse a token out of a string
-==============
-*/
-char *COM_Parse (char *data)
-{
-	int		c;
-	int		len;
-	
-	len = 0;
-	com_token[0] = 0;
-	
-	if (!data)
-		return NULL;
-		
-// skip whitespace
-skipwhite:
-	while ( (c = *data) <= ' ')
-	{
-		if (c == 0)
-		{
-			com_eof = qtrue;
-			return NULL;			// end of file;
-		}
-		data++;
-	}
-	
-// skip // comments
-	if (c=='/' && data[1] == '/')
-	{
-		while (*data && *data != '\n')
-			data++;
-		goto skipwhite;
-	}
-	
-
-// handle quoted strings specially
-	if (c == '\"')
-	{
-		data++;
-		do
-		{
-			c = *data++;
-			if (c=='\"')
-			{
-				com_token[len] = 0;
-				return data;
-			}
-			com_token[len] = c;
-			len++;
-		} while (1);
-	}
-
-// parse single characters
-	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
-	{
-		com_token[len] = c;
-		len++;
-		com_token[len] = 0;
-		return data+1;
-	}
-
-// parse a regular word
-	do
-	{
-		com_token[len] = c;
-		data++;
-		len++;
-		c = *data;
-	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
-			break;
-	} while (c>32);
-	
-	com_token[len] = 0;
-	return data;
-}
-
-int Q_strncasecmp (const char *s1, const char *s2, int n)
-{
-	int		c1, c2;
-	
-	do
-	{
-		c1 = *s1++;
-		c2 = *s2++;
-
-		if (!n--)
-			return 0;		// strings are equal until end point
-		
-		if (c1 != c2)
-		{
-			if (c1 >= 'a' && c1 <= 'z')
-				c1 -= ('a' - 'A');
-			if (c2 >= 'a' && c2 <= 'z')
-				c2 -= ('a' - 'A');
-			if (c1 != c2)
-				return -1;		// strings not equal
-		}
-	} while (c1);
-	
-	return 0;		// strings are equal
-}
-
-int Q_stricmp (const char *s1, const char *s2)
-{
-	return Q_strncasecmp (s1, s2, 99999);
-}
-
-// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
-//   started getting warnings about that function, prolly a duplicate with the runtime function
-//   maybe we still need to have it in linux builds
-/*
-char *strupr (char *start)
-{
-	char	*in;
-	in = start;
-	while (*in)
-	{
-		*in = toupper(*in);
-		in++;
-	}
-	return start;
-}
-*/
-
-char *strlower (char *start)
-{
-	char	*in;
-	in = start;
-	while (*in)
-	{
-		*in = tolower(*in); 
-		in++;
-	}
-	return start;
-}
-
-
-/*
-=============================================================================
-
-						MISC FUNCTIONS
-
-=============================================================================
-*/
-
-
-/*
-=================
-CheckParm
-
-Checks for the given parameter in the program's command line arguments
-Returns the argument number (1 to argc-1) or 0 if not present
-=================
-*/
-int CheckParm (const char *check)
-{
-	int             i;
-
-	for (i = 1;i<myargc;i++)
-	{
-		if ( !Q_stricmp(check, myargv[i]) )
-			return i;
-	}
-
-	return 0;
-}
-
-
-
-/*
-================
-Q_filelength
-================
-*/
-int Q_filelength (FILE *f)
-{
-	int		pos;
-	int		end;
-
-	pos = ftell (f);
-	fseek (f, 0, SEEK_END);
-	end = ftell (f);
-	fseek (f, pos, SEEK_SET);
-
-	return end;
-}
-
-
-FILE *SafeOpenWrite (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen(filename, "wb");
-
-	if (!f)
-		Error ("Error opening %s: %s",filename,strerror(errno));
-
-	return f;
-}
-
-FILE *SafeOpenRead (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen(filename, "rb");
-
-	if (!f)
-		Error ("Error opening %s: %s",filename,strerror(errno));
-
-	return f;
-}
-
-
-void SafeRead (FILE *f, void *buffer, int count)
-{
-	if ( fread (buffer, 1, count, f) != (size_t)count)
-		Error ("File read failure");
-}
-
-
-void SafeWrite (FILE *f, const void *buffer, int count)
-{
-	if (fwrite (buffer, 1, count, f) != (size_t)count)
-		Error ("File write failure");
-}
-
-
-/*
-==============
-FileExists
-==============
-*/
-qboolean	FileExists (const char *filename)
-{
-	FILE	*f;
-
-	f = fopen (filename, "r");
-	if (!f)
-		return qfalse;
-	fclose (f);
-	return qtrue;
-}
-
-/*
-==============
-LoadFile
-==============
-*/
-int    LoadFile( const char *filename, void **bufferptr )
-{
-	FILE	*f;
-	int    length;
-	void    *buffer;
-
-	f = SafeOpenRead (filename);
-	length = Q_filelength (f);
-	buffer = safe_malloc (length+1);
-	((char *)buffer)[length] = 0;
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-LoadFileBlock
--
-rounds up memory allocation to 4K boundry
--
-==============
-*/
-int    LoadFileBlock( const char *filename, void **bufferptr )
-{
-	FILE	*f;
-	int    length, nBlock, nAllocSize;
-	void    *buffer;
-
-	f = SafeOpenRead (filename);
-	length = Q_filelength (f);
-  nAllocSize = length;
-  nBlock = nAllocSize % MEM_BLOCKSIZE;
-  if ( nBlock > 0) {
-    nAllocSize += MEM_BLOCKSIZE - nBlock;
-  }
-	buffer = safe_malloc (nAllocSize+1);
-  memset(buffer, 0, nAllocSize+1);
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-TryLoadFile
-
-Allows failure
-==============
-*/
-int    TryLoadFile (const char *filename, void **bufferptr)
-{
-	FILE	*f;
-	int    length;
-	void    *buffer;
-
-	*bufferptr = NULL;
-
-	f = fopen (filename, "rb");
-	if (!f)
-		return -1;
-	length = Q_filelength (f);
-	buffer = safe_malloc (length+1);
-	((char *)buffer)[length] = 0;
-	SafeRead (f, buffer, length);
-	fclose (f);
-
-	*bufferptr = buffer;
-	return length;
-}
-
-
-/*
-==============
-SaveFile
-==============
-*/
-void    SaveFile (const char *filename, const void *buffer, int count)
-{
-	FILE	*f;
-
-	f = SafeOpenWrite (filename);
-	SafeWrite (f, buffer, count);
-	fclose (f);
-}
-
-
-
-void DefaultExtension (char *path, const char *extension)
-{
-	char    *src;
-//
-// if path doesnt have a .EXT, append extension
-// (extension should include the .)
-//
-	src = path + strlen(path) - 1;
-
-	while (*src != '/' && *src != '\\' && src != path)
-	{
-		if (*src == '.')
-			return;                 // it has an extension
-		src--;
-	}
-
-	strcat (path, extension);
-}
-
-
-void DefaultPath (char *path, const char *basepath)
-{
-	char    temp[128];
-
-	if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
-		return;                   // absolute path location
-	strcpy (temp,path);
-	strcpy (path,basepath);
-	strcat (path,temp);
-}
-
-
-void    StripFilename (char *path)
-{
-	int             length;
-
-	length = strlen(path)-1;
-	while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
-		length--;
-	path[length] = 0;
-}
-
-void    StripExtension (char *path)
-{
-	int             length;
-
-	length = strlen(path)-1;
-	while (length > 0 && path[length] != '.')
-	{
-		length--;
-		if (path[length] == '/' || path[ length ] == '\\' )
-			return;		// no extension
-	}
-	if (length)
-		path[length] = 0;
-}
-
-
-/*
-====================
-Extract file parts
-====================
-*/
-// FIXME: should include the slash, otherwise
-// backing to an empty path will be wrong when appending a slash
-void ExtractFilePath (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
-	while (src != path && *(src-1) != '\\' && *(src-1) != '/')
-		src--;
-
-	memcpy (dest, path, src-path);
-	dest[src-path] = 0;
-}
-
-void ExtractFileBase (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a \ or the start
-//
-	while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
-		src--;
-
-	while (*src && *src != '.')
-	{
-		*dest++ = *src++;
-	}
-	*dest = 0;
-}
-
-void ExtractFileExtension (const char *path, char *dest)
-{
-	const char    *src;
-
-	src = path + strlen(path) - 1;
-
-//
-// back up until a . or the start
-//
-	while (src != path && *(src-1) != '.')
-		src--;
-	if (src == path)
-	{
-		*dest = 0;	// no extension
-		return;
-	}
-
-	strcpy (dest,src);
-}
-
-
-/*
-==============
-ParseNum / ParseHex
-==============
-*/
-int ParseHex (const char *hex)
-{
-	const char    *str;
-	int    num;
-
-	num = 0;
-	str = hex;
-
-	while (*str)
-	{
-		num <<= 4;
-		if (*str >= '0' && *str <= '9')
-			num += *str-'0';
-		else if (*str >= 'a' && *str <= 'f')
-			num += 10 + *str-'a';
-		else if (*str >= 'A' && *str <= 'F')
-			num += 10 + *str-'A';
-		else
-			Error ("Bad hex number: %s",hex);
-		str++;
-	}
-
-	return num;
-}
-
-
-int ParseNum (const char *str)
-{
-	if (str[0] == '$')
-		return ParseHex (str+1);
-	if (str[0] == '0' && str[1] == 'x')
-		return ParseHex (str+2);
-	return atol (str);
-}
-
-
-
-/*
-============================================================================
-
-					BYTE ORDER FUNCTIONS
-
-============================================================================
-*/
-
-#ifdef _SGI_SOURCE
-#define	__BIG_ENDIAN__
-#endif
-
-#ifdef __BIG_ENDIAN__
-
-short   LittleShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   BigShort (short l)
-{
-	return l;
-}
-
-
-int    LittleLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    BigLong (int l)
-{
-	return l;
-}
-
-
-float	LittleFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	BigFloat (float l)
-{
-	return l;
-}
-
-
-#else
-
-
-short   BigShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   LittleShort (short l)
-{
-	return l;
-}
-
-
-int    BigLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    LittleLong (int l)
-{
-	return l;
-}
-
-float	BigFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	LittleFloat (float l)
-{
-	return l;
-}
-
-
-#endif
-
-
-//=======================================================
-
-
-// FIXME: byte swap?
-
-// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
-// and the initial and final xor values shown below...  in other words, the
-// CCITT standard CRC used by XMODEM
-
-#define CRC_INIT_VALUE	0xffff
-#define CRC_XOR_VALUE	0x0000
-
-static unsigned short crctable[256] =
-{
-	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
-	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
-	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
-	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
-	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
-	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
-	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
-	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
-	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
-	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
-	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
-	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
-	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
-	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
-	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
-	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
-	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
-	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
-	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
-	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
-	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
-	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
-	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
-	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
-	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
-	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
-	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
-	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
-	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
-	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
-	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
-	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
-};
-
-void CRC_Init(unsigned short *crcvalue)
-{
-	*crcvalue = CRC_INIT_VALUE;
-}
-
-void CRC_ProcessByte(unsigned short *crcvalue, byte data)
-{
-	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
-}
-
-unsigned short CRC_Value(unsigned short crcvalue)
-{
-	return crcvalue ^ CRC_XOR_VALUE;
-}
-//=============================================================================
-
-/*
-============
-CreatePath
-============
-*/
-void	CreatePath (const char *path)
-{
-	const char	*ofs;
-	char		c;
-	char		dir[1024];
-
-#ifdef _WIN32
-	int		olddrive = -1;
-
-	if ( path[1] == ':' )
-	{
-		olddrive = _getdrive();
-		_chdrive( toupper( path[0] ) - 'A' + 1 );
-	}
-#endif
-
-	if (path[1] == ':')
-		path += 2;
-
-	for (ofs = path+1 ; *ofs ; ofs++)
-	{
-		c = *ofs;
-		if (c == '/' || c == '\\')
-		{	// create the directory
-			memcpy( dir, path, ofs - path );
-			dir[ ofs - path ] = 0;
-			Q_mkdir( dir );
-		}
-	}
-
-#ifdef _WIN32
-	if ( olddrive != -1 )
-	{
-		_chdrive( olddrive );
-	}
-#endif
-}
-
-
-/*
-============
-QCopyFile
-
-  Used to archive source files
-============
-*/
-void QCopyFile (const char *from, const char *to)
-{
-	void	*buffer;
-	int		length;
-
-	length = LoadFile (from, &buffer);
-	CreatePath (to);
-	SaveFile (to, buffer, length);
-	free (buffer);
-}
-
-void Sys_Sleep(int n)
-{
-#ifdef _WIN32
-  Sleep (n);
-#endif
-#if defined (__linux__) || defined (__APPLE__)
-  usleep (n * 1000);
-#endif
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// cmdlib.c
+// TTimo 09/30/2000
+// from an intial copy of common/cmdlib.c
+// stripped out the Sys_Printf Sys_Printf stuff
+
+// SPoG 05/27/2001
+// merging alpha branch into trunk
+// replaced qprintf with Sys_Printf 
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#endif
+
+#if defined (__linux__) || defined (__APPLE__)
+#include <unistd.h>
+#endif
+
+#ifdef NeXT
+#include <libc.h>
+#endif
+
+#define	BASEDIRNAME	"quake"		// assumed to have a 2 or 3 following
+#define PATHSEPERATOR   '/'
+
+#ifdef SAFE_MALLOC
+void *safe_malloc( size_t size )
+{
+  void *p;
+
+  p = malloc(size);
+  if(!p)
+    Error ("safe_malloc failed on allocation of %i bytes", size);
+
+  return p;
+}
+
+void *safe_malloc_info( size_t size, char* info )
+{
+  void *p;
+
+  p = malloc(size);
+  if(!p)
+    Error ("%s: safe_malloc failed on allocation of %i bytes", info, size);
+
+  return p;
+}
+#endif
+
+// set these before calling CheckParm
+int myargc;
+char **myargv;
+
+char		com_token[1024];
+qboolean	com_eof;
+
+qboolean		archive;
+char			archivedir[1024];
+
+
+/*
+===================
+ExpandWildcards
+
+Mimic unix command line expansion
+===================
+*/
+#define	MAX_EX_ARGC	1024
+int		ex_argc;
+char	*ex_argv[MAX_EX_ARGC];
+#ifdef _WIN32
+#include "io.h"
+void ExpandWildcards( int *argc, char ***argv )
+{
+	struct _finddata_t fileinfo;
+	int		handle;
+	int		i;
+	char	filename[1024];
+	char	filebase[1024];
+	char	*path;
+
+	ex_argc = 0;
+	for (i=0 ; i<*argc ; i++)
+	{
+		path = (*argv)[i];
+		if ( path[0] == '-'
+			|| ( !strstr(path, "*") && !strstr(path, "?") ) )
+		{
+			ex_argv[ex_argc++] = path;
+			continue;
+		}
+
+		handle = _findfirst (path, &fileinfo);
+		if (handle == -1)
+			return;
+
+		ExtractFilePath (path, filebase);
+
+		do
+		{
+			sprintf (filename, "%s%s", filebase, fileinfo.name);
+			ex_argv[ex_argc++] = copystring (filename);
+		} while (_findnext( handle, &fileinfo ) != -1);
+
+		_findclose (handle);
+	}
+
+	*argc = ex_argc;
+	*argv = ex_argv;
+}
+#else
+void ExpandWildcards (int *argc, char ***argv)
+{
+}
+#endif
+
+/*
+
+qdir will hold the path up to the quake directory, including the slash
+
+  f:\quake\
+  /raid/quake/
+
+gamedir will hold qdir + the game directory (id1, id2, etc)
+
+*/
+
+char		qdir[1024];
+char		gamedir[1024];
+char		writedir[1024];
+
+void SetQdirFromPath( const char *path )
+{
+	char	temp[1024];
+	const char	*c;
+  const char *sep;
+	int		len, count;
+
+	if (!(path[0] == '/' || path[0] == '\\' || path[1] == ':'))
+	{	// path is partial
+		Q_getwd (temp);
+		strcat (temp, path);
+		path = temp;
+	}
+
+	// search for "quake2" in path
+
+	len = strlen(BASEDIRNAME);
+	for (c=path+strlen(path)-1 ; c != path ; c--)
+	{
+		int i;
+
+		if (!Q_strncasecmp (c, BASEDIRNAME, len))
+		{
+      //
+			//strncpy (qdir, path, c+len+2-path);
+      // the +2 assumes a 2 or 3 following quake which is not the
+      // case with a retail install
+      // so we need to add up how much to the next separator
+      sep = c + len;
+      count = 1;
+      while (*sep && *sep != '/' && *sep != '\\')
+      {
+        sep++;
+        count++;
+      }
+			strncpy (qdir, path, c+len+count-path);
+			Sys_Printf ("qdir: %s\n", qdir);
+			for ( i = 0; i < strlen( qdir ); i++ )
+			{
+				if ( qdir[i] == '\\' ) 
+					qdir[i] = '/';
+			}
+
+			c += len+count;
+			while (*c)
+			{
+				if (*c == '/' || *c == '\\')
+				{
+					strncpy (gamedir, path, c+1-path);
+
+					for ( i = 0; i < strlen( gamedir ); i++ )
+					{
+						if ( gamedir[i] == '\\' ) 
+							gamedir[i] = '/';
+					}
+
+					Sys_Printf ("gamedir: %s\n", gamedir);
+
+					if ( !writedir[0] )
+						strcpy( writedir, gamedir );
+					else if ( writedir[strlen( writedir )-1] != '/' )
+					{
+						writedir[strlen( writedir )] = '/';
+						writedir[strlen( writedir )+1] = 0;
+					}
+
+					return;
+				}
+				c++;
+			}
+			Error ("No gamedir in %s", path);
+			return;
+		}
+	}
+	Error ("SetQdirFromPath: no '%s' in %s", BASEDIRNAME, path);
+}
+
+char *ExpandArg (const char *path)
+{
+	static char full[1024];
+
+	if (path[0] != '/' && path[0] != '\\' && path[1] != ':')
+	{
+		Q_getwd (full);
+		strcat (full, path);
+	}
+	else
+		strcpy (full, path);
+	return full;
+}
+
+char *ExpandPath (const char *path)
+{
+	static char full[1024];
+	if (!qdir)
+		Error ("ExpandPath called without qdir set");
+	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+		strcpy( full, path );
+		return full;
+	}
+	sprintf (full, "%s%s", qdir, path);
+	return full;
+}
+
+char *ExpandGamePath (const char *path)
+{
+	static char full[1024];
+	if (!qdir)
+		Error ("ExpandGamePath called without qdir set");
+	if (path[0] == '/' || path[0] == '\\' || path[1] == ':') {
+		strcpy( full, path );
+		return full;
+	}
+	sprintf (full, "%s%s", gamedir, path);
+	return full;
+}
+
+char *ExpandPathAndArchive (const char *path)
+{
+	char	*expanded;
+	char	archivename[1024];
+
+	expanded = ExpandPath (path);
+
+	if (archive)
+	{
+		sprintf (archivename, "%s/%s", archivedir, path);
+		QCopyFile (expanded, archivename);
+	}
+	return expanded;
+}
+
+
+char *copystring(const char *s)
+{
+	char	*b;
+	b = safe_malloc(strlen(s)+1);
+	strcpy (b, s);
+	return b;
+}
+
+
+
+/*
+================
+I_FloatTime
+================
+*/
+double I_FloatTime (void)
+{
+	time_t	t;
+	
+	time (&t);
+	
+	return t;
+#if 0
+// more precise, less portable
+	struct timeval tp;
+	struct timezone tzp;
+	static int		secbase;
+
+	gettimeofday(&tp, &tzp);
+	
+	if (!secbase)
+	{
+		secbase = tp.tv_sec;
+		return tp.tv_usec/1000000.0;
+	}
+	
+	return (tp.tv_sec - secbase) + tp.tv_usec/1000000.0;
+#endif
+}
+
+void Q_getwd (char *out)
+{
+	int i = 0;
+
+#ifdef _WIN32
+   _getcwd (out, 256);
+   strcat (out, "\\");
+#else
+   // Gef: Changed from getwd() to getcwd() to avoid potential buffer overflow
+   getcwd (out, 256);
+   strcat (out, "/");
+#endif
+   while ( out[i] != 0 )
+   {
+	   if ( out[i] == '\\' )
+		   out[i] = '/';
+	   i++;
+   }
+}
+
+
+void Q_mkdir (const char *path)
+{
+#ifdef _WIN32
+	if (_mkdir (path) != -1)
+		return;
+#else
+	if (mkdir (path, 0777) != -1)
+		return;
+#endif
+	if (errno != EEXIST)
+		Error ("mkdir %s: %s",path, strerror(errno));
+}
+
+/*
+============
+FileTime
+
+returns -1 if not present
+============
+*/
+int	FileTime (const char *path)
+{
+	struct	stat	buf;
+	
+	if (stat (path,&buf) == -1)
+		return -1;
+	
+	return buf.st_mtime;
+}
+
+
+
+/*
+==============
+COM_Parse
+
+Parse a token out of a string
+==============
+*/
+char *COM_Parse (char *data)
+{
+	int		c;
+	int		len;
+	
+	len = 0;
+	com_token[0] = 0;
+	
+	if (!data)
+		return NULL;
+		
+// skip whitespace
+skipwhite:
+	while ( (c = *data) <= ' ')
+	{
+		if (c == 0)
+		{
+			com_eof = qtrue;
+			return NULL;			// end of file;
+		}
+		data++;
+	}
+	
+// skip // comments
+	if (c=='/' && data[1] == '/')
+	{
+		while (*data && *data != '\n')
+			data++;
+		goto skipwhite;
+	}
+	
+
+// handle quoted strings specially
+	if (c == '\"')
+	{
+		data++;
+		do
+		{
+			c = *data++;
+			if (c=='\"')
+			{
+				com_token[len] = 0;
+				return data;
+			}
+			com_token[len] = c;
+			len++;
+		} while (1);
+	}
+
+// parse single characters
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+	{
+		com_token[len] = c;
+		len++;
+		com_token[len] = 0;
+		return data+1;
+	}
+
+// parse a regular word
+	do
+	{
+		com_token[len] = c;
+		data++;
+		len++;
+		c = *data;
+	if (c=='{' || c=='}'|| c==')'|| c=='(' || c=='\'' || c==':')
+			break;
+	} while (c>32);
+	
+	com_token[len] = 0;
+	return data;
+}
+
+int Q_strncasecmp (const char *s1, const char *s2, int n)
+{
+	int		c1, c2;
+	
+	do
+	{
+		c1 = *s1++;
+		c2 = *s2++;
+
+		if (!n--)
+			return 0;		// strings are equal until end point
+		
+		if (c1 != c2)
+		{
+			if (c1 >= 'a' && c1 <= 'z')
+				c1 -= ('a' - 'A');
+			if (c2 >= 'a' && c2 <= 'z')
+				c2 -= ('a' - 'A');
+			if (c1 != c2)
+				return -1;		// strings not equal
+		}
+	} while (c1);
+	
+	return 0;		// strings are equal
+}
+
+int Q_stricmp (const char *s1, const char *s2)
+{
+	return Q_strncasecmp (s1, s2, 99999);
+}
+
+// NOTE TTimo when switching to Multithread DLL (Release/Debug) in the config
+//   started getting warnings about that function, prolly a duplicate with the runtime function
+//   maybe we still need to have it in linux builds
+/*
+char *strupr (char *start)
+{
+	char	*in;
+	in = start;
+	while (*in)
+	{
+		*in = toupper(*in);
+		in++;
+	}
+	return start;
+}
+*/
+
+char *strlower (char *start)
+{
+	char	*in;
+	in = start;
+	while (*in)
+	{
+		*in = tolower(*in); 
+		in++;
+	}
+	return start;
+}
+
+
+/*
+=============================================================================
+
+						MISC FUNCTIONS
+
+=============================================================================
+*/
+
+
+/*
+=================
+CheckParm
+
+Checks for the given parameter in the program's command line arguments
+Returns the argument number (1 to argc-1) or 0 if not present
+=================
+*/
+int CheckParm (const char *check)
+{
+	int             i;
+
+	for (i = 1;i<myargc;i++)
+	{
+		if ( !Q_stricmp(check, myargv[i]) )
+			return i;
+	}
+
+	return 0;
+}
+
+
+
+/*
+================
+Q_filelength
+================
+*/
+int Q_filelength (FILE *f)
+{
+	int		pos;
+	int		end;
+
+	pos = ftell (f);
+	fseek (f, 0, SEEK_END);
+	end = ftell (f);
+	fseek (f, pos, SEEK_SET);
+
+	return end;
+}
+
+
+FILE *SafeOpenWrite (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen(filename, "wb");
+
+	if (!f)
+		Error ("Error opening %s: %s",filename,strerror(errno));
+
+	return f;
+}
+
+FILE *SafeOpenRead (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen(filename, "rb");
+
+	if (!f)
+		Error ("Error opening %s: %s",filename,strerror(errno));
+
+	return f;
+}
+
+
+void SafeRead (FILE *f, void *buffer, int count)
+{
+	if ( fread (buffer, 1, count, f) != (size_t)count)
+		Error ("File read failure");
+}
+
+
+void SafeWrite (FILE *f, const void *buffer, int count)
+{
+	if (fwrite (buffer, 1, count, f) != (size_t)count)
+		Error ("File write failure");
+}
+
+
+/*
+==============
+FileExists
+==============
+*/
+qboolean	FileExists (const char *filename)
+{
+	FILE	*f;
+
+	f = fopen (filename, "r");
+	if (!f)
+		return qfalse;
+	fclose (f);
+	return qtrue;
+}
+
+/*
+==============
+LoadFile
+==============
+*/
+int    LoadFile( const char *filename, void **bufferptr )
+{
+	FILE	*f;
+	int    length;
+	void    *buffer;
+
+	f = SafeOpenRead (filename);
+	length = Q_filelength (f);
+	buffer = safe_malloc (length+1);
+	((char *)buffer)[length] = 0;
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+LoadFileBlock
+-
+rounds up memory allocation to 4K boundry
+-
+==============
+*/
+int    LoadFileBlock( const char *filename, void **bufferptr )
+{
+	FILE	*f;
+	int    length, nBlock, nAllocSize;
+	void    *buffer;
+
+	f = SafeOpenRead (filename);
+	length = Q_filelength (f);
+  nAllocSize = length;
+  nBlock = nAllocSize % MEM_BLOCKSIZE;
+  if ( nBlock > 0) {
+    nAllocSize += MEM_BLOCKSIZE - nBlock;
+  }
+	buffer = safe_malloc (nAllocSize+1);
+  memset(buffer, 0, nAllocSize+1);
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+TryLoadFile
+
+Allows failure
+==============
+*/
+int    TryLoadFile (const char *filename, void **bufferptr)
+{
+	FILE	*f;
+	int    length;
+	void    *buffer;
+
+	*bufferptr = NULL;
+
+	f = fopen (filename, "rb");
+	if (!f)
+		return -1;
+	length = Q_filelength (f);
+	buffer = safe_malloc (length+1);
+	((char *)buffer)[length] = 0;
+	SafeRead (f, buffer, length);
+	fclose (f);
+
+	*bufferptr = buffer;
+	return length;
+}
+
+
+/*
+==============
+SaveFile
+==============
+*/
+void    SaveFile (const char *filename, const void *buffer, int count)
+{
+	FILE	*f;
+
+	f = SafeOpenWrite (filename);
+	SafeWrite (f, buffer, count);
+	fclose (f);
+}
+
+
+
+void DefaultExtension (char *path, const char *extension)
+{
+	char    *src;
+//
+// if path doesnt have a .EXT, append extension
+// (extension should include the .)
+//
+	src = path + strlen(path) - 1;
+
+	while (*src != '/' && *src != '\\' && src != path)
+	{
+		if (*src == '.')
+			return;                 // it has an extension
+		src--;
+	}
+
+	strcat (path, extension);
+}
+
+
+void DefaultPath (char *path, const char *basepath)
+{
+	char    temp[128];
+
+	if( path[ 0 ] == '/' || path[ 0 ] == '\\' )
+		return;                   // absolute path location
+	strcpy (temp,path);
+	strcpy (path,basepath);
+	strcat (path,temp);
+}
+
+
+void    StripFilename (char *path)
+{
+	int             length;
+
+	length = strlen(path)-1;
+	while (length > 0 && path[length] != '/' && path[ length ] != '\\' )
+		length--;
+	path[length] = 0;
+}
+
+void    StripExtension (char *path)
+{
+	int             length;
+
+	length = strlen(path)-1;
+	while (length > 0 && path[length] != '.')
+	{
+		length--;
+		if (path[length] == '/' || path[ length ] == '\\' )
+			return;		// no extension
+	}
+	if (length)
+		path[length] = 0;
+}
+
+
+/*
+====================
+Extract file parts
+====================
+*/
+// FIXME: should include the slash, otherwise
+// backing to an empty path will be wrong when appending a slash
+void ExtractFilePath (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+	while (src != path && *(src-1) != '\\' && *(src-1) != '/')
+		src--;
+
+	memcpy (dest, path, src-path);
+	dest[src-path] = 0;
+}
+
+void ExtractFileBase (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a \ or the start
+//
+	while (src != path && *(src-1) != '/' && *(src-1) != '\\' )
+		src--;
+
+	while (*src && *src != '.')
+	{
+		*dest++ = *src++;
+	}
+	*dest = 0;
+}
+
+void ExtractFileExtension (const char *path, char *dest)
+{
+	const char    *src;
+
+	src = path + strlen(path) - 1;
+
+//
+// back up until a . or the start
+//
+	while (src != path && *(src-1) != '.')
+		src--;
+	if (src == path)
+	{
+		*dest = 0;	// no extension
+		return;
+	}
+
+	strcpy (dest,src);
+}
+
+
+/*
+==============
+ParseNum / ParseHex
+==============
+*/
+int ParseHex (const char *hex)
+{
+	const char    *str;
+	int    num;
+
+	num = 0;
+	str = hex;
+
+	while (*str)
+	{
+		num <<= 4;
+		if (*str >= '0' && *str <= '9')
+			num += *str-'0';
+		else if (*str >= 'a' && *str <= 'f')
+			num += 10 + *str-'a';
+		else if (*str >= 'A' && *str <= 'F')
+			num += 10 + *str-'A';
+		else
+			Error ("Bad hex number: %s",hex);
+		str++;
+	}
+
+	return num;
+}
+
+
+int ParseNum (const char *str)
+{
+	if (str[0] == '$')
+		return ParseHex (str+1);
+	if (str[0] == '0' && str[1] == 'x')
+		return ParseHex (str+2);
+	return atol (str);
+}
+
+
+
+/*
+============================================================================
+
+					BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+#ifdef _SGI_SOURCE
+#define	__BIG_ENDIAN__
+#endif
+
+#ifdef __BIG_ENDIAN__
+
+short   LittleShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   BigShort (short l)
+{
+	return l;
+}
+
+
+int    LittleLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    BigLong (int l)
+{
+	return l;
+}
+
+
+float	LittleFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	BigFloat (float l)
+{
+	return l;
+}
+
+
+#else
+
+
+short   BigShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   LittleShort (short l)
+{
+	return l;
+}
+
+
+int    BigLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    LittleLong (int l)
+{
+	return l;
+}
+
+float	BigFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	LittleFloat (float l)
+{
+	return l;
+}
+
+
+#endif
+
+
+//=======================================================
+
+
+// FIXME: byte swap?
+
+// this is a 16 bit, non-reflected CRC using the polynomial 0x1021
+// and the initial and final xor values shown below...  in other words, the
+// CCITT standard CRC used by XMODEM
+
+#define CRC_INIT_VALUE	0xffff
+#define CRC_XOR_VALUE	0x0000
+
+static unsigned short crctable[256] =
+{
+	0x0000,	0x1021,	0x2042,	0x3063,	0x4084,	0x50a5,	0x60c6,	0x70e7,
+	0x8108,	0x9129,	0xa14a,	0xb16b,	0xc18c,	0xd1ad,	0xe1ce,	0xf1ef,
+	0x1231,	0x0210,	0x3273,	0x2252,	0x52b5,	0x4294,	0x72f7,	0x62d6,
+	0x9339,	0x8318,	0xb37b,	0xa35a,	0xd3bd,	0xc39c,	0xf3ff,	0xe3de,
+	0x2462,	0x3443,	0x0420,	0x1401,	0x64e6,	0x74c7,	0x44a4,	0x5485,
+	0xa56a,	0xb54b,	0x8528,	0x9509,	0xe5ee,	0xf5cf,	0xc5ac,	0xd58d,
+	0x3653,	0x2672,	0x1611,	0x0630,	0x76d7,	0x66f6,	0x5695,	0x46b4,
+	0xb75b,	0xa77a,	0x9719,	0x8738,	0xf7df,	0xe7fe,	0xd79d,	0xc7bc,
+	0x48c4,	0x58e5,	0x6886,	0x78a7,	0x0840,	0x1861,	0x2802,	0x3823,
+	0xc9cc,	0xd9ed,	0xe98e,	0xf9af,	0x8948,	0x9969,	0xa90a,	0xb92b,
+	0x5af5,	0x4ad4,	0x7ab7,	0x6a96,	0x1a71,	0x0a50,	0x3a33,	0x2a12,
+	0xdbfd,	0xcbdc,	0xfbbf,	0xeb9e,	0x9b79,	0x8b58,	0xbb3b,	0xab1a,
+	0x6ca6,	0x7c87,	0x4ce4,	0x5cc5,	0x2c22,	0x3c03,	0x0c60,	0x1c41,
+	0xedae,	0xfd8f,	0xcdec,	0xddcd,	0xad2a,	0xbd0b,	0x8d68,	0x9d49,
+	0x7e97,	0x6eb6,	0x5ed5,	0x4ef4,	0x3e13,	0x2e32,	0x1e51,	0x0e70,
+	0xff9f,	0xefbe,	0xdfdd,	0xcffc,	0xbf1b,	0xaf3a,	0x9f59,	0x8f78,
+	0x9188,	0x81a9,	0xb1ca,	0xa1eb,	0xd10c,	0xc12d,	0xf14e,	0xe16f,
+	0x1080,	0x00a1,	0x30c2,	0x20e3,	0x5004,	0x4025,	0x7046,	0x6067,
+	0x83b9,	0x9398,	0xa3fb,	0xb3da,	0xc33d,	0xd31c,	0xe37f,	0xf35e,
+	0x02b1,	0x1290,	0x22f3,	0x32d2,	0x4235,	0x5214,	0x6277,	0x7256,
+	0xb5ea,	0xa5cb,	0x95a8,	0x8589,	0xf56e,	0xe54f,	0xd52c,	0xc50d,
+	0x34e2,	0x24c3,	0x14a0,	0x0481,	0x7466,	0x6447,	0x5424,	0x4405,
+	0xa7db,	0xb7fa,	0x8799,	0x97b8,	0xe75f,	0xf77e,	0xc71d,	0xd73c,
+	0x26d3,	0x36f2,	0x0691,	0x16b0,	0x6657,	0x7676,	0x4615,	0x5634,
+	0xd94c,	0xc96d,	0xf90e,	0xe92f,	0x99c8,	0x89e9,	0xb98a,	0xa9ab,
+	0x5844,	0x4865,	0x7806,	0x6827,	0x18c0,	0x08e1,	0x3882,	0x28a3,
+	0xcb7d,	0xdb5c,	0xeb3f,	0xfb1e,	0x8bf9,	0x9bd8,	0xabbb,	0xbb9a,
+	0x4a75,	0x5a54,	0x6a37,	0x7a16,	0x0af1,	0x1ad0,	0x2ab3,	0x3a92,
+	0xfd2e,	0xed0f,	0xdd6c,	0xcd4d,	0xbdaa,	0xad8b,	0x9de8,	0x8dc9,
+	0x7c26,	0x6c07,	0x5c64,	0x4c45,	0x3ca2,	0x2c83,	0x1ce0,	0x0cc1,
+	0xef1f,	0xff3e,	0xcf5d,	0xdf7c,	0xaf9b,	0xbfba,	0x8fd9,	0x9ff8,
+	0x6e17,	0x7e36,	0x4e55,	0x5e74,	0x2e93,	0x3eb2,	0x0ed1,	0x1ef0
+};
+
+void CRC_Init(unsigned short *crcvalue)
+{
+	*crcvalue = CRC_INIT_VALUE;
+}
+
+void CRC_ProcessByte(unsigned short *crcvalue, byte data)
+{
+	*crcvalue = (*crcvalue << 8) ^ crctable[(*crcvalue >> 8) ^ data];
+}
+
+unsigned short CRC_Value(unsigned short crcvalue)
+{
+	return crcvalue ^ CRC_XOR_VALUE;
+}
+//=============================================================================
+
+/*
+============
+CreatePath
+============
+*/
+void	CreatePath (const char *path)
+{
+	const char	*ofs;
+	char		c;
+	char		dir[1024];
+
+#ifdef _WIN32
+	int		olddrive = -1;
+
+	if ( path[1] == ':' )
+	{
+		olddrive = _getdrive();
+		_chdrive( toupper( path[0] ) - 'A' + 1 );
+	}
+#endif
+
+	if (path[1] == ':')
+		path += 2;
+
+	for (ofs = path+1 ; *ofs ; ofs++)
+	{
+		c = *ofs;
+		if (c == '/' || c == '\\')
+		{	// create the directory
+			memcpy( dir, path, ofs - path );
+			dir[ ofs - path ] = 0;
+			Q_mkdir( dir );
+		}
+	}
+
+#ifdef _WIN32
+	if ( olddrive != -1 )
+	{
+		_chdrive( olddrive );
+	}
+#endif
+}
+
+
+/*
+============
+QCopyFile
+
+  Used to archive source files
+============
+*/
+void QCopyFile (const char *from, const char *to)
+{
+	void	*buffer;
+	int		length;
+
+	length = LoadFile (from, &buffer);
+	CreatePath (to);
+	SaveFile (to, buffer, length);
+	free (buffer);
+}
+
+void Sys_Sleep(int n)
+{
+#ifdef _WIN32
+  Sleep (n);
+#endif
+#if defined (__linux__) || defined (__APPLE__)
+  usleep (n * 1000);
+#endif
+}
diff --git a/tools/quake3/common/cmdlib.h b/tools/quake3/common/cmdlib.h
index 8c27ab85..7eee55ed 100644
--- a/tools/quake3/common/cmdlib.h
+++ b/tools/quake3/common/cmdlib.h
@@ -1,160 +1,160 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// cmdlib.h
-
-#ifndef __CMDLIB__
-#define __CMDLIB__
-
-#include "bytebool.h"
-
-#ifdef _WIN32
-#pragma warning(disable : 4244)     // MIPS
-#pragma warning(disable : 4136)     // X86
-#pragma warning(disable : 4051)     // ALPHA
-
-#pragma warning(disable : 4018)     // signed/unsigned mismatch
-#pragma warning(disable : 4305)     // truncate from double to float
-
-#pragma check_stack(off)
-
-#endif
-
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <ctype.h>
-#include <time.h>
-#include <stdarg.h>
-
-#ifdef _WIN32
-
-#pragma intrinsic( memset, memcpy )
-
-#endif
-
-
-#define	MAX_OS_PATH		1024
-#define MEM_BLOCKSIZE 4096
-
-// the dec offsetof macro doesnt work very well...
-#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
-
-#define SAFE_MALLOC
-#ifdef SAFE_MALLOC
-void *safe_malloc( size_t size );
-void *safe_malloc_info( size_t size, char* info );
-#else
-#define safe_malloc(a) malloc(a)
-#endif /* SAFE_MALLOC */
-
-// set these before calling CheckParm
-extern int myargc;
-extern char **myargv;
-
-char *strlower (char *in);
-int Q_strncasecmp( const char *s1, const char *s2, int n );
-int Q_stricmp( const char *s1, const char *s2 );
-void Q_getwd( char *out );
-
-int Q_filelength (FILE *f);
-int	FileTime( const char *path );
-
-void	Q_mkdir( const char *path );
-
-extern	char		qdir[1024];
-extern	char		gamedir[1024];
-extern  char		writedir[1024];
-extern  char    *moddirparam;
-void SetQdirFromPath( const char *path);
-char *ExpandArg( const char *path );	// from cmd line
-char *ExpandPath( const char *path );	// from scripts
-char *ExpandGamePath (const char *path);
-char *ExpandPathAndArchive( const char *path );
-void ExpandWildcards( int *argc, char ***argv );
-
-
-double I_FloatTime( void );
-
-void	Error( const char *error, ... );
-int		CheckParm( const char *check );
-
-FILE	*SafeOpenWrite( const char *filename );
-FILE	*SafeOpenRead( const char *filename );
-void	SafeRead (FILE *f, void *buffer, int count);
-void	SafeWrite (FILE *f, const void *buffer, int count);
-
-int		LoadFile( const char *filename, void **bufferptr );
-int   LoadFileBlock( const char *filename, void **bufferptr );
-int		TryLoadFile( const char *filename, void **bufferptr );
-void	SaveFile( const char *filename, const void *buffer, int count );
-qboolean	FileExists( const char *filename );
-
-void 	DefaultExtension( char *path, const char *extension );
-void 	DefaultPath( char *path, const char *basepath );
-void 	StripFilename( char *path );
-void 	StripExtension( char *path );
-
-void 	ExtractFilePath( const char *path, char *dest );
-void 	ExtractFileBase( const char *path, char *dest );
-void	ExtractFileExtension( const char *path, char *dest );
-
-int 	ParseNum (const char *str);
-
-short	BigShort (short l);
-short	LittleShort (short l);
-int		BigLong (int l);
-int		LittleLong (int l);
-float	BigFloat (float l);
-float	LittleFloat (float l);
-
-
-char *COM_Parse (char *data);
-
-extern	char		com_token[1024];
-extern	qboolean	com_eof;
-
-char *copystring(const char *s);
-
-
-void CRC_Init(unsigned short *crcvalue);
-void CRC_ProcessByte(unsigned short *crcvalue, byte data);
-unsigned short CRC_Value(unsigned short crcvalue);
-
-void	CreatePath( const char *path );
-void	QCopyFile( const char *from, const char *to );
-
-extern	qboolean		archive;
-extern	char			archivedir[1024];
-
-// sleep for the given amount of milliseconds
-void Sys_Sleep(int n);
-
-// for compression routines
-typedef struct
-{
-	void	*data;
-	int		count, width, height;
-} cblock_t;
-
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// cmdlib.h
+
+#ifndef __CMDLIB__
+#define __CMDLIB__
+
+#include "bytebool.h"
+
+#ifdef _WIN32
+#pragma warning(disable : 4244)     // MIPS
+#pragma warning(disable : 4136)     // X86
+#pragma warning(disable : 4051)     // ALPHA
+
+#pragma warning(disable : 4018)     // signed/unsigned mismatch
+#pragma warning(disable : 4305)     // truncate from double to float
+
+#pragma check_stack(off)
+
+#endif
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <time.h>
+#include <stdarg.h>
+
+#ifdef _WIN32
+
+#pragma intrinsic( memset, memcpy )
+
+#endif
+
+
+#define	MAX_OS_PATH		1024
+#define MEM_BLOCKSIZE 4096
+
+// the dec offsetof macro doesnt work very well...
+#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier)
+
+#define SAFE_MALLOC
+#ifdef SAFE_MALLOC
+void *safe_malloc( size_t size );
+void *safe_malloc_info( size_t size, char* info );
+#else
+#define safe_malloc(a) malloc(a)
+#endif /* SAFE_MALLOC */
+
+// set these before calling CheckParm
+extern int myargc;
+extern char **myargv;
+
+char *strlower (char *in);
+int Q_strncasecmp( const char *s1, const char *s2, int n );
+int Q_stricmp( const char *s1, const char *s2 );
+void Q_getwd( char *out );
+
+int Q_filelength (FILE *f);
+int	FileTime( const char *path );
+
+void	Q_mkdir( const char *path );
+
+extern	char		qdir[1024];
+extern	char		gamedir[1024];
+extern  char		writedir[1024];
+extern  char    *moddirparam;
+void SetQdirFromPath( const char *path);
+char *ExpandArg( const char *path );	// from cmd line
+char *ExpandPath( const char *path );	// from scripts
+char *ExpandGamePath (const char *path);
+char *ExpandPathAndArchive( const char *path );
+void ExpandWildcards( int *argc, char ***argv );
+
+
+double I_FloatTime( void );
+
+void	Error( const char *error, ... );
+int		CheckParm( const char *check );
+
+FILE	*SafeOpenWrite( const char *filename );
+FILE	*SafeOpenRead( const char *filename );
+void	SafeRead (FILE *f, void *buffer, int count);
+void	SafeWrite (FILE *f, const void *buffer, int count);
+
+int		LoadFile( const char *filename, void **bufferptr );
+int   LoadFileBlock( const char *filename, void **bufferptr );
+int		TryLoadFile( const char *filename, void **bufferptr );
+void	SaveFile( const char *filename, const void *buffer, int count );
+qboolean	FileExists( const char *filename );
+
+void 	DefaultExtension( char *path, const char *extension );
+void 	DefaultPath( char *path, const char *basepath );
+void 	StripFilename( char *path );
+void 	StripExtension( char *path );
+
+void 	ExtractFilePath( const char *path, char *dest );
+void 	ExtractFileBase( const char *path, char *dest );
+void	ExtractFileExtension( const char *path, char *dest );
+
+int 	ParseNum (const char *str);
+
+short	BigShort (short l);
+short	LittleShort (short l);
+int		BigLong (int l);
+int		LittleLong (int l);
+float	BigFloat (float l);
+float	LittleFloat (float l);
+
+
+char *COM_Parse (char *data);
+
+extern	char		com_token[1024];
+extern	qboolean	com_eof;
+
+char *copystring(const char *s);
+
+
+void CRC_Init(unsigned short *crcvalue);
+void CRC_ProcessByte(unsigned short *crcvalue, byte data);
+unsigned short CRC_Value(unsigned short crcvalue);
+
+void	CreatePath( const char *path );
+void	QCopyFile( const char *from, const char *to );
+
+extern	qboolean		archive;
+extern	char			archivedir[1024];
+
+// sleep for the given amount of milliseconds
+void Sys_Sleep(int n);
+
+// for compression routines
+typedef struct
+{
+	void	*data;
+	int		count, width, height;
+} cblock_t;
+
+
+#endif
diff --git a/tools/quake3/common/imagelib.c b/tools/quake3/common/imagelib.c
index 8955d35a..7a0d22cf 100644
--- a/tools/quake3/common/imagelib.c
+++ b/tools/quake3/common/imagelib.c
@@ -1,1220 +1,1220 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// imagelib.c
-
-#include "cmdlib.h"
-#include "imagelib.h"
-#include "vfs.h"
-
-int fgetLittleShort (FILE *f)
-{
-	byte	b1, b2;
-
-	b1 = fgetc(f);
-	b2 = fgetc(f);
-
-	return (short)(b1 + b2*256);
-}
-
-int fgetLittleLong (FILE *f)
-{
-	byte	b1, b2, b3, b4;
-
-	b1 = fgetc(f);
-	b2 = fgetc(f);
-	b3 = fgetc(f);
-	b4 = fgetc(f);
-
-	return b1 + (b2<<8) + (b3<<16) + (b4<<24);
-}
-
-int bufLittleShort (byte *buf, int len, int *pos)
-{
-  byte	b1, b2;
-
-  if ((len - *pos) < 2)
-    Error ("Unexpected buffer end");
-
-  b1 = buf[*pos]; *pos += 1;
-  b2 = buf[*pos]; *pos += 1;
-
-  return (short)(b1 + b2*256);
-}
-
-int bufLittleLong (byte *buf, int len, int *pos)
-{
-  byte b1, b2, b3, b4;
-
-  if ((len - *pos) < 4)
-    Error ("Unexpected buffer end");
-
-  b1 = buf[*pos]; *pos += 1;
-  b2 = buf[*pos]; *pos += 1;
-  b3 = buf[*pos]; *pos += 1;
-  b4 = buf[*pos]; *pos += 1;
-
-  return b1 + (b2<<8) + (b3<<16) + (b4<<24);
-}
-
-
-/*
-============================================================================
-
-						LBM STUFF
-
-============================================================================
-*/
-
-
-typedef unsigned char	UBYTE;
-//conflicts with windows typedef short			WORD;
-typedef unsigned short	UWORD;
-typedef long			LONG;
-
-typedef enum
-{
-	ms_none,
-	ms_mask,
-	ms_transcolor,
-	ms_lasso
-} mask_t;
-
-typedef enum
-{
-	cm_none,
-	cm_rle1
-} compress_t;
-
-typedef struct
-{
-	UWORD		w,h;
-	short		x,y;
-	UBYTE		nPlanes;
-	UBYTE		masking;
-	UBYTE		compression;
-	UBYTE		pad1;
-	UWORD		transparentColor;
-	UBYTE		xAspect,yAspect;
-	short		pageWidth,pageHeight;
-} bmhd_t;
-
-extern	bmhd_t	bmhd;						// will be in native byte order
-
-
-
-#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
-#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
-#define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
-#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
-#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
-#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
-
-
-bmhd_t  bmhd;
-
-int    Align (int l)
-{
-	if (l&1)
-		return l+1;
-	return l;
-}
-
-
-
-/*
-================
-LBMRLEdecompress
-
-Source must be evenly aligned!
-================
-*/
-byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
-{
-	int     count;
-	byte    b,rept;
-
-	count = 0;
-
-	do
-	{
-		rept = *source++;
-
-		if (rept > 0x80)
-		{
-			rept = (rept^0xff)+2;
-			b = *source++;
-			memset(unpacked,b,rept);
-			unpacked += rept;
-		}
-		else if (rept < 0x80)
-		{
-			rept++;
-			memcpy(unpacked,source,rept);
-			unpacked += rept;
-			source += rept;
-		}
-		else
-			rept = 0;               // rept of 0x80 is NOP
-
-		count += rept;
-
-	} while (count<bpwidth);
-
-	if (count>bpwidth)
-		Error ("Decompression exceeded width!\n");
-
-
-	return source;
-}
-
-
-/*
-=================
-LoadLBM
-=================
-*/
-void LoadLBM (const char *filename, byte **picture, byte **palette)
-{
-	byte    *LBMbuffer, *picbuffer, *cmapbuffer;
-	int             y;
-	byte    *LBM_P, *LBMEND_P;
-	byte    *pic_p;
-	byte    *body_p;
-
-	int    formtype,formlength;
-	int    chunktype,chunklength;
-
-// qiet compiler warnings
-	picbuffer = NULL;
-	cmapbuffer = NULL;
-
-//
-// load the LBM
-//
-	LoadFile (filename, (void **)&LBMbuffer);
-
-//
-// parse the LBM header
-//
-	LBM_P = LBMbuffer;
-	if ( *(int *)LBMbuffer != LittleLong(FORMID) )
-	   Error ("No FORM ID at start of file!\n");
-
-	LBM_P += 4;
-	formlength = BigLong( *(int *)LBM_P );
-	LBM_P += 4;
-	LBMEND_P = LBM_P + Align(formlength);
-
-	formtype = LittleLong(*(int *)LBM_P);
-
-	if (formtype != ILBMID && formtype != PBMID)
-		Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
-		,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
-
-	LBM_P += 4;
-
-//
-// parse chunks
-//
-
-	while (LBM_P < LBMEND_P)
-	{
-		chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
-		LBM_P += 4;
-		chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
-		LBM_P += 4;
-
-		switch ( chunktype )
-		{
-		case BMHDID:
-			memcpy (&bmhd,LBM_P,sizeof(bmhd));
-			bmhd.w = BigShort(bmhd.w);
-			bmhd.h = BigShort(bmhd.h);
-			bmhd.x = BigShort(bmhd.x);
-			bmhd.y = BigShort(bmhd.y);
-			bmhd.pageWidth = BigShort(bmhd.pageWidth);
-			bmhd.pageHeight = BigShort(bmhd.pageHeight);
-			break;
-
-		case CMAPID:
-			cmapbuffer = safe_malloc (768);
-			memset (cmapbuffer, 0, 768);
-			memcpy (cmapbuffer, LBM_P, chunklength);
-			break;
-
-		case BODYID:
-			body_p = LBM_P;
-
-			pic_p = picbuffer = safe_malloc (bmhd.w*bmhd.h);
-			if (formtype == PBMID)
-			{
-			//
-			// unpack PBM
-			//
-				for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
-				{
-					if (bmhd.compression == cm_rle1)
-						body_p = LBMRLEDecompress ((byte *)body_p
-						, pic_p , bmhd.w);
-					else if (bmhd.compression == cm_none)
-					{
-						memcpy (pic_p,body_p,bmhd.w);
-						body_p += Align(bmhd.w);
-					}
-				}
-
-			}
-			else
-			{
-			//
-			// unpack ILBM
-			//
-				Error ("%s is an interlaced LBM, not packed", filename);
-			}
-			break;
-		}
-
-		LBM_P += Align(chunklength);
-	}
-
-	free (LBMbuffer);
-
-	*picture = picbuffer;
-
-	if (palette)
-		*palette = cmapbuffer;
-}
-
-
-/*
-============================================================================
-
-							WRITE LBM
-
-============================================================================
-*/
-
-/*
-==============
-WriteLBMfile
-==============
-*/
-void WriteLBMfile (const char *filename, byte *data,
-				   int width, int height, byte *palette)
-{
-	byte    *lbm, *lbmptr;
-	int    *formlength, *bmhdlength, *cmaplength, *bodylength;
-	int    length;
-	bmhd_t  basebmhd;
-
-	lbm = lbmptr = safe_malloc (width*height+1000);
-
-//
-// start FORM
-//
-	*lbmptr++ = 'F';
-	*lbmptr++ = 'O';
-	*lbmptr++ = 'R';
-	*lbmptr++ = 'M';
-
-	formlength = (int*)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	*lbmptr++ = 'P';
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'M';
-	*lbmptr++ = ' ';
-
-//
-// write BMHD
-//
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'M';
-	*lbmptr++ = 'H';
-	*lbmptr++ = 'D';
-
-	bmhdlength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memset (&basebmhd,0,sizeof(basebmhd));
-	basebmhd.w = BigShort((short)width);
-	basebmhd.h = BigShort((short)height);
-	basebmhd.nPlanes = BigShort(8);
-	basebmhd.xAspect = BigShort(5);
-	basebmhd.yAspect = BigShort(6);
-	basebmhd.pageWidth = BigShort((short)width);
-	basebmhd.pageHeight = BigShort((short)height);
-
-	memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
-	lbmptr += sizeof(basebmhd);
-
-	length = lbmptr-(byte *)bmhdlength-4;
-	*bmhdlength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write CMAP
-//
-	*lbmptr++ = 'C';
-	*lbmptr++ = 'M';
-	*lbmptr++ = 'A';
-	*lbmptr++ = 'P';
-
-	cmaplength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memcpy (lbmptr,palette,768);
-	lbmptr += 768;
-
-	length = lbmptr-(byte *)cmaplength-4;
-	*cmaplength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write BODY
-//
-	*lbmptr++ = 'B';
-	*lbmptr++ = 'O';
-	*lbmptr++ = 'D';
-	*lbmptr++ = 'Y';
-
-	bodylength = (int *)lbmptr;
-	lbmptr+=4;                      // leave space for length
-
-	memcpy (lbmptr,data,width*height);
-	lbmptr += width*height;
-
-	length = lbmptr-(byte *)bodylength-4;
-	*bodylength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// done
-//
-	length = lbmptr-(byte *)formlength-4;
-	*formlength = BigLong(length);
-	if (length&1)
-		*lbmptr++ = 0;          // pad chunk to even offset
-
-//
-// write output file
-//
-	SaveFile (filename, lbm, lbmptr-lbm);
-	free (lbm);
-}
-
-
-/*
-============================================================================
-
-LOAD PCX
-
-============================================================================
-*/
-
-typedef struct
-{
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
-
-
-/*
-==============
-LoadPCX
-==============
-*/
-
-/* RR2DO2 */
-#define DECODEPCX( b, d, r ) d=*b++;if((d&0xC0)==0xC0){r=d&0x3F;d=*b++;}else{r=1;}
-
-void LoadPCX( const char *filename, byte **pic, byte **palette, int *width, int *height )
-{
-	byte	*raw;
-	pcx_t	*pcx;
-	int		x, y, lsize;
-	int		len;
-	int		dataByte, runLength;
-	byte	*out, *pix;
-	
-
-	/* load the file */
-	len = vfsLoadFile (filename, (void **)&raw, 0);
-    if( len == -1 ) 
-		Error( "LoadPCX: Couldn't read %s", filename );
-
-	
-	/* parse the PCX file */
-	pcx = (pcx_t *)raw;
-	raw = &pcx->data;
-
-	pcx->xmin = LittleShort(pcx->xmin);
-	pcx->ymin = LittleShort(pcx->ymin);
-	pcx->xmax = LittleShort(pcx->xmax);
-	pcx->ymax = LittleShort(pcx->ymax);
-	pcx->hres = LittleShort(pcx->hres);
-	pcx->vres = LittleShort(pcx->vres);
-	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
-	pcx->palette_type = LittleShort(pcx->palette_type);
-
-	if (pcx->manufacturer != 0x0a
-		|| pcx->version != 5
-		|| pcx->encoding != 1
-		|| pcx->bits_per_pixel != 8
-		|| pcx->xmax >= 640
-		|| pcx->ymax >= 480)
-		Error ("Bad pcx file %s", filename);
-	
-	if (palette)
-	{
-		*palette = safe_malloc(768);
-		memcpy (*palette, (byte *)pcx + len - 768, 768);
-	}
-
-	if (width)
-		*width = pcx->xmax+1;
-	if (height)
-		*height = pcx->ymax+1;
-
-	if (!pic)
-		return;
-
-	out = safe_malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
-	if (!out)
-		Error( "LoadPCX: couldn't allocate");
-
-	*pic = out;
-	pix = out;
-	
-	/* RR2DO2: pcx fix  */
-	lsize = pcx->color_planes * pcx->bytes_per_line;
-	
-	/* go scanline by scanline */
-	for( y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1 )
-	{
-		/* do a scanline */
-		for( x=0; x <= pcx->xmax; )
-		{
-			/* RR2DO2 */
-			DECODEPCX( raw, dataByte, runLength );
-			while( runLength-- > 0 )
-				pix[ x++ ] = dataByte;
-		}
-
-		/* RR2DO2: discard any other data */
-		while( x < lsize )
-		{
-			DECODEPCX( raw, dataByte, runLength );
-			x++;
-		}
-		while( runLength-- > 0 )
-			x++;
-	}
-	
-	/* validity check */
-	if( raw - (byte *) pcx > len)
-		Error( "PCX file %s was malformed", filename );
-	free( pcx );
-}
-
-
-
-/* 
-============== 
-WritePCXfile 
-============== 
-*/ 
-void WritePCXfile (const char *filename, byte *data, 
-				   int width, int height, byte *palette) 
-{
-	int		i, j, length;
-	pcx_t	*pcx;
-	byte		*pack;
-	  
-	pcx = safe_malloc (width*height*2+1000);
-	memset (pcx, 0, sizeof(*pcx));
-
-	pcx->manufacturer = 0x0a;	// PCX id
-	pcx->version = 5;			// 256 color
- 	pcx->encoding = 1;		// uncompressed
-	pcx->bits_per_pixel = 8;		// 256 color
-	pcx->xmin = 0;
-	pcx->ymin = 0;
-	pcx->xmax = LittleShort((short)(width-1));
-	pcx->ymax = LittleShort((short)(height-1));
-	pcx->hres = LittleShort((short)width);
-	pcx->vres = LittleShort((short)height);
-	pcx->color_planes = 1;		// chunky image
-	pcx->bytes_per_line = LittleShort((short)width);
-	pcx->palette_type = LittleShort(1);		// not a grey scale
-
-	// pack the image
-	pack = &pcx->data;
-	
-	for (i=0 ; i<height ; i++)
-	{
-		for (j=0 ; j<width ; j++)
-		{
-			if ( (*data & 0xc0) != 0xc0)
-				*pack++ = *data++;
-			else
-			{
-				*pack++ = 0xc1;
-				*pack++ = *data++;
-			}
-		}
-	}
-			
-	// write the palette
-	*pack++ = 0x0c;	// palette ID byte
-	for (i=0 ; i<768 ; i++)
-		*pack++ = *palette++;
-		
-// write output file 
-	length = pack - (byte *)pcx;
-	SaveFile (filename, pcx, length);
-
-	free (pcx);
-} 
- 
-/*
-============================================================================
-
-LOAD BMP
-
-============================================================================
-*/
-
-
-/*
-
-// we can't just use these structures, because
-// compiler structure alignment will not be portable
-// on this unaligned stuff
-
-typedef struct tagBITMAPFILEHEADER { // bmfh 
-        WORD    bfType;				// BM
-        DWORD   bfSize; 
-        WORD    bfReserved1; 
-        WORD    bfReserved2; 
-        DWORD   bfOffBits; 
-} BITMAPFILEHEADER; 
- 
-typedef struct tagBITMAPINFOHEADER{ // bmih 
-   DWORD  biSize; 
-   LONG   biWidth; 
-   LONG   biHeight; 
-   WORD   biPlanes; 
-   WORD   biBitCount 
-   DWORD  biCompression; 
-   DWORD  biSizeImage; 
-   LONG   biXPelsPerMeter; 
-   LONG   biYPelsPerMeter; 
-   DWORD  biClrUsed; 
-   DWORD  biClrImportant; 
-} BITMAPINFOHEADER; 
- 
-typedef struct tagBITMAPINFO { // bmi 
-   BITMAPINFOHEADER bmiHeader; 
-   RGBQUAD          bmiColors[1]; 
-} BITMAPINFO; 
-
-typedef struct tagBITMAPCOREHEADER { // bmch 
-        DWORD   bcSize; 
-        WORD    bcWidth; 
-        WORD    bcHeight; 
-        WORD    bcPlanes; 
-        WORD    bcBitCount; 
-} BITMAPCOREHEADER; 
- 
-typedef struct _BITMAPCOREINFO {    // bmci 
-        BITMAPCOREHEADER  bmciHeader; 
-        RGBTRIPLE         bmciColors[1]; 
-} BITMAPCOREINFO; 
- 
-*/
-
-/*
-==============
-LoadBMP
-==============
-*/
-void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height)
-{
-  byte	*out;
-  int		i;
-  int		bfSize; 
-  int		bfOffBits; 
-  int		structSize;
-  int		bcWidth; 
-  int     bcHeight; 
-  int	    bcPlanes; 
-  int		bcBitCount; 
-  byte	bcPalette[1024];
-  qboolean	flipped;
-  byte *in;
-  int len, pos = 0;
-
-  len = vfsLoadFile (filename, (void **)&in, 0);
-  if (len == -1) 
-  {
-    Error ("Couldn't read %s", filename);
-  }
-
-  i = bufLittleShort (in, len, &pos);
-  if (i != 'B' + ('M'<<8) ) {
-    Error ("%s is not a bmp file", filename);
-  }
-
-  bfSize = bufLittleLong (in, len, &pos);
-  bufLittleShort(in, len, &pos);
-  bufLittleShort(in, len, &pos);
-  bfOffBits = bufLittleLong (in, len, &pos);
-
-  // the size will tell us if it is a
-  // bitmapinfo or a bitmapcore
-  structSize = bufLittleLong (in, len, &pos);
-  if (structSize == 40)
-  {
-    // bitmapinfo
-    bcWidth = bufLittleLong(in, len, &pos); 
-    bcHeight= bufLittleLong(in, len, &pos); 
-    bcPlanes = bufLittleShort(in, len, &pos); 
-    bcBitCount = bufLittleShort(in, len, &pos); 
-
-    pos += 24;
-
-    if (palette)
-    {
-      memcpy (bcPalette, in+pos, 1024);
-      pos += 1024;
-      *palette = safe_malloc(768);
-
-      for (i = 0 ; i < 256 ; i++)
-      {
-        (*palette)[i * 3 + 0] = bcPalette[i * 4 + 2];
-        (*palette)[i * 3 + 1] = bcPalette[i * 4 + 1];
-        (*palette)[i * 3 + 2] = bcPalette[i * 4 + 0];
-      }
-    }
-  }
-  else if (structSize == 12)
-  {
-    // bitmapcore
-    bcWidth = bufLittleShort(in, len, &pos); 
-    bcHeight= bufLittleShort(in, len, &pos); 
-    bcPlanes = bufLittleShort(in, len, &pos); 
-    bcBitCount = bufLittleShort(in, len, &pos); 
-
-    if (palette)
-    {
-      memcpy (bcPalette, in+pos, 768);
-      pos += 768;
-      *palette = safe_malloc(768);
-
-      for (i = 0 ; i < 256 ; i++) {
-        (*palette)[i * 3 + 0] = bcPalette[i * 3 + 2];
-        (*palette)[i * 3 + 1] = bcPalette[i * 3 + 1];
-        (*palette)[i * 3 + 2] = bcPalette[i * 3 + 0];
-      }
-    }
-  } else {
-    Error ("%s had strange struct size", filename);
-  }
-
-  if (bcPlanes != 1) {
-    Error ("%s was not a single plane image", filename);
-  }
-
-  if (bcBitCount != 8) {
-    Error ("%s was not an 8 bit image", filename);
-  }
-
-  if (bcHeight < 0) {
-    bcHeight = -bcHeight;
-    flipped = qtrue;
-  } else {
-    flipped = qfalse;
-  }
-
-  if (width)
-    *width = bcWidth;
-  if (height)
-    *height = bcHeight;
-
-  if (!pic) {
-    free (in);
-    return;
-  }
-
-  out = safe_malloc ( bcWidth * bcHeight );
-  *pic = out;
-  pos = bfOffBits;
-
-  if (flipped) {
-    for (i = 0 ; i < bcHeight ; i++) {
-      memcpy (out + bcWidth * (bcHeight - 1 - i), in+pos, bcWidth);
-      pos += bcWidth;
-    }
-  } else {
-    memcpy (out, in+pos, bcWidth*bcHeight);
-    pos += bcWidth*bcHeight;
-  }
-
-  free (in);
-}
-
-
-/*
-============================================================================
-
-LOAD IMAGE
-
-============================================================================
-*/
-
-/*
-==============
-Load256Image
-
-Will load either an lbm or pcx, depending on extension.
-Any of the return pointers can be NULL if you don't want them.
-==============
-*/
-void Load256Image (const char *name, byte **pixels, byte **palette, int *width, int *height)
-{
-  char ext[128];
-
-  ExtractFileExtension (name, ext);
-  if (!Q_stricmp (ext, "lbm"))
-  {
-    LoadLBM (name, pixels, palette);
-    if (width)
-      *width = bmhd.w;
-    if (height)
-      *height = bmhd.h;
-  }
-  else if (!Q_stricmp (ext, "pcx"))
-  {
-    LoadPCX (name, pixels, palette, width, height);
-  }
-  else if (!Q_stricmp (ext, "bmp"))
-  {
-    LoadBMP (name, pixels, palette, width, height);
-  }
-  else
-    Error ("%s doesn't have a known image extension", name);
-}
-
-
-/*
-==============
-Save256Image
-
-Will save either an lbm or pcx, depending on extension.
-==============
-*/
-void Save256Image (const char *name, byte *pixels, byte *palette,
-				   int width, int height)
-{
-	char	ext[128];
-
-	ExtractFileExtension (name, ext);
-	if (!Q_stricmp (ext, "lbm"))
-	{
-		WriteLBMfile (name, pixels, width, height, palette);
-	}
-	else if (!Q_stricmp (ext, "pcx"))
-	{
-		WritePCXfile (name, pixels, width, height, palette);
-	}
-	else
-		Error ("%s doesn't have a known image extension", name);
-}
-
-
-
-
-/*
-============================================================================
-
-TARGA IMAGE
-
-============================================================================
-*/
-
-typedef struct _TargaHeader {
-	unsigned char 	id_length, colormap_type, image_type;
-	unsigned short	colormap_index, colormap_length;
-	unsigned char	colormap_size;
-	unsigned short	x_origin, y_origin, width, height;
-	unsigned char	pixel_size, attributes;
-} TargaHeader;
-
-/*
-=============
-LoadTGABuffer
-=============
-*/
-void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height)
-{
-	int		columns, rows, numPixels;
-	byte	*pixbuf;
-	int		row, column;
-	byte	*buf_p;
-	TargaHeader	targa_header;
-	byte		*targa_rgba;
-
-	*pic = NULL;
-
-	buf_p = buffer;
-
-	targa_header.id_length = *buf_p++;
-	targa_header.colormap_type = *buf_p++;
-	targa_header.image_type = *buf_p++;
-	
-	targa_header.colormap_index = LittleShort ( *(short *)buf_p );
-	buf_p += 2;
-	targa_header.colormap_length = LittleShort ( *(short *)buf_p );
-	buf_p += 2;
-	targa_header.colormap_size = *buf_p++;
-	targa_header.x_origin = LittleShort ( *(short *)buf_p );
-	buf_p += 2;
-	targa_header.y_origin = LittleShort ( *(short *)buf_p );
-	buf_p += 2;
-	targa_header.width = LittleShort ( *(short *)buf_p );
-	buf_p += 2;
-	targa_header.height = LittleShort ( *(short *)buf_p );
-	buf_p += 2;
-	targa_header.pixel_size = *buf_p++;
-	targa_header.attributes = *buf_p++;
-
-	if (targa_header.image_type!=2 
-		&& targa_header.image_type!=10
-		&& targa_header.image_type != 3 ) 
-	{
-		Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
-	}
-
-	if ( targa_header.colormap_type != 0 )
-	{
-		Error("LoadTGA: colormaps not supported\n" );
-	}
-
-	if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
-	{
-		Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
-	}
-
-	columns = targa_header.width;
-	rows = targa_header.height;
-	numPixels = columns * rows;
-
-	if (width)
-		*width = columns;
-	if (height)
-		*height = rows;
-
-	targa_rgba = safe_malloc (numPixels*4);
-	*pic = targa_rgba;
-
-	if (targa_header.id_length != 0)
-		buf_p += targa_header.id_length;  // skip TARGA image comment
-	
-	if ( targa_header.image_type==2 || targa_header.image_type == 3 )
-	{ 
-		// Uncompressed RGB or gray scale image
-		for(row=rows-1; row>=0; row--) 
-		{
-			pixbuf = targa_rgba + row*columns*4;
-			for(column=0; column<columns; column++) 
-			{
-				unsigned char red,green,blue,alphabyte;
-				switch (targa_header.pixel_size) 
-				{
-					
-				case 8:
-					blue = *buf_p++;
-					green = blue;
-					red = blue;
-					*pixbuf++ = red;
-					*pixbuf++ = green;
-					*pixbuf++ = blue;
-					*pixbuf++ = 255;
-					break;
-
-				case 24:
-					blue = *buf_p++;
-					green = *buf_p++;
-					red = *buf_p++;
-					*pixbuf++ = red;
-					*pixbuf++ = green;
-					*pixbuf++ = blue;
-					*pixbuf++ = 255;
-					break;
-				case 32:
-					blue = *buf_p++;
-					green = *buf_p++;
-					red = *buf_p++;
-					alphabyte = *buf_p++;
-					*pixbuf++ = red;
-					*pixbuf++ = green;
-					*pixbuf++ = blue;
-					*pixbuf++ = alphabyte;
-					break;
-				default:
-					//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
-					break;
-				}
-			}
-		}
-	}
-	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
-		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
-
-		red = 0;
-		green = 0;
-		blue = 0;
-		alphabyte = 0xff;
-
-		for(row=rows-1; row>=0; row--) {
-			pixbuf = targa_rgba + row*columns*4;
-			for(column=0; column<columns; ) {
-				packetHeader= *buf_p++;
-				packetSize = 1 + (packetHeader & 0x7f);
-				if (packetHeader & 0x80) {        // run-length packet
-					switch (targa_header.pixel_size) {
-						case 24:
-								blue = *buf_p++;
-								green = *buf_p++;
-								red = *buf_p++;
-								alphabyte = 255;
-								break;
-						case 32:
-								blue = *buf_p++;
-								green = *buf_p++;
-								red = *buf_p++;
-								alphabyte = *buf_p++;
-								break;
-						default:
-							//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
-							break;
-					}
-	
-					for(j=0;j<packetSize;j++) {
-						*pixbuf++=red;
-						*pixbuf++=green;
-						*pixbuf++=blue;
-						*pixbuf++=alphabyte;
-						column++;
-						if (column==columns) { // run spans across rows
-							column=0;
-							if (row>0)
-								row--;
-							else
-								goto breakOut;
-							pixbuf = targa_rgba + row*columns*4;
-						}
-					}
-				}
-				else {                            // non run-length packet
-					for(j=0;j<packetSize;j++) {
-						switch (targa_header.pixel_size) {
-							case 24:
-									blue = *buf_p++;
-									green = *buf_p++;
-									red = *buf_p++;
-									*pixbuf++ = red;
-									*pixbuf++ = green;
-									*pixbuf++ = blue;
-									*pixbuf++ = 255;
-									break;
-							case 32:
-									blue = *buf_p++;
-									green = *buf_p++;
-									red = *buf_p++;
-									alphabyte = *buf_p++;
-									*pixbuf++ = red;
-									*pixbuf++ = green;
-									*pixbuf++ = blue;
-									*pixbuf++ = alphabyte;
-									break;
-							default:
-								//Sysprintf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
-								break;
-						}
-						column++;
-						if (column==columns) { // pixel packet run spans across rows
-							column=0;
-							if (row>0)
-								row--;
-							else
-								goto breakOut;
-							pixbuf = targa_rgba + row*columns*4;
-						}						
-					}
-				}
-			}
-			breakOut:;
-		}
-	}
-
-	// vertically flipped
-	if ( (targa_header.attributes & (1<<5)) ) {
-		int flip;
-		for (row = 0; row < .5f * rows; row++)
-		{
-			for (column = 0; column < columns; column++)
-			{
-				flip = *( (int*)targa_rgba + row * columns + column);
-				*( (int*)targa_rgba + row * columns + column) = *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column );
-				*( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column ) = flip;
-			}
-		}
-	}
-
-	//free(buffer);
-}
-
-
-
-/*
-=============
-LoadTGA
-=============
-*/
-void LoadTGA (const char *name, byte **pixels, int *width, int *height)
-{
-	byte			*buffer;
-  int nLen;
-	//
-	// load the file
-	//
-	nLen = vfsLoadFile ( ( char * ) name, (void **)&buffer, 0);
-	if (nLen == -1) 
-  {
-		Error ("Couldn't read %s", name);
-  }
-
-  LoadTGABuffer(buffer, pixels, width, height);
-
-}
-
-
-/*
-================
-WriteTGA
-================
-*/
-void WriteTGA (const char *filename, byte *data, int width, int height) {
-	byte	*buffer;
-	int		i;
-	int		c;
-	FILE	*f;
-
-	buffer = safe_malloc(width*height*4 + 18);
-	memset (buffer, 0, 18);
-	buffer[2] = 2;		// uncompressed type
-	buffer[12] = width&255;
-	buffer[13] = width>>8;
-	buffer[14] = height&255;
-	buffer[15] = height>>8;
-	buffer[16] = 32;	// pixel size
-
-	// swap rgb to bgr
-	c = 18 + width * height * 4;
-	for (i=18 ; i<c ; i+=4)
-	{
-		buffer[i] = data[i-18+2];		// blue
-		buffer[i+1] = data[i-18+1];		// green
-		buffer[i+2] = data[i-18+0];		// red
-		buffer[i+3] = data[i-18+3];		// alpha
-	}
-
-	f = fopen (filename, "wb");
-	fwrite (buffer, 1, c, f);
-	fclose (f);
-
-	free (buffer);
-}
-
-/*
-============================================================================
-
-LOAD32BITIMAGE
-
-============================================================================
-*/
-
-/*
-==============
-Load32BitImage
-
-Any of the return pointers can be NULL if you don't want them.
-==============
-*/
-void Load32BitImage (const char *name, unsigned **pixels,  int *width, int *height)
-{
-	char	ext[128];
-	byte	*palette;
-	byte	*pixels8;
-	byte	*pixels32;
-	int		size;
-	int		i;
-	int		v;
-
-	ExtractFileExtension (name, ext);
-	if (!Q_stricmp (ext, "tga")) {
-		LoadTGA (name, (byte **)pixels, width, height);
-	} else {
-		Load256Image (name, &pixels8, &palette, width, height);
-		if (!pixels) {
-			return;
-		}
-		size = *width * *height;
-		pixels32 = safe_malloc(size * 4);
-		*pixels = (unsigned *)pixels32;
-		for (i = 0 ; i < size ; i++) {
-			v = pixels8[i];
-			pixels32[i*4 + 0] = palette[ v * 3 + 0 ];
-			pixels32[i*4 + 1] = palette[ v * 3 + 1 ];
-			pixels32[i*4 + 2] = palette[ v * 3 + 2 ];
-			pixels32[i*4 + 3] = 0xff;
-		}
-	}
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// imagelib.c
+
+#include "cmdlib.h"
+#include "imagelib.h"
+#include "vfs.h"
+
+int fgetLittleShort (FILE *f)
+{
+	byte	b1, b2;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+
+	return (short)(b1 + b2*256);
+}
+
+int fgetLittleLong (FILE *f)
+{
+	byte	b1, b2, b3, b4;
+
+	b1 = fgetc(f);
+	b2 = fgetc(f);
+	b3 = fgetc(f);
+	b4 = fgetc(f);
+
+	return b1 + (b2<<8) + (b3<<16) + (b4<<24);
+}
+
+int bufLittleShort (byte *buf, int len, int *pos)
+{
+  byte	b1, b2;
+
+  if ((len - *pos) < 2)
+    Error ("Unexpected buffer end");
+
+  b1 = buf[*pos]; *pos += 1;
+  b2 = buf[*pos]; *pos += 1;
+
+  return (short)(b1 + b2*256);
+}
+
+int bufLittleLong (byte *buf, int len, int *pos)
+{
+  byte b1, b2, b3, b4;
+
+  if ((len - *pos) < 4)
+    Error ("Unexpected buffer end");
+
+  b1 = buf[*pos]; *pos += 1;
+  b2 = buf[*pos]; *pos += 1;
+  b3 = buf[*pos]; *pos += 1;
+  b4 = buf[*pos]; *pos += 1;
+
+  return b1 + (b2<<8) + (b3<<16) + (b4<<24);
+}
+
+
+/*
+============================================================================
+
+						LBM STUFF
+
+============================================================================
+*/
+
+
+typedef unsigned char	UBYTE;
+//conflicts with windows typedef short			WORD;
+typedef unsigned short	UWORD;
+typedef long			LONG;
+
+typedef enum
+{
+	ms_none,
+	ms_mask,
+	ms_transcolor,
+	ms_lasso
+} mask_t;
+
+typedef enum
+{
+	cm_none,
+	cm_rle1
+} compress_t;
+
+typedef struct
+{
+	UWORD		w,h;
+	short		x,y;
+	UBYTE		nPlanes;
+	UBYTE		masking;
+	UBYTE		compression;
+	UBYTE		pad1;
+	UWORD		transparentColor;
+	UBYTE		xAspect,yAspect;
+	short		pageWidth,pageHeight;
+} bmhd_t;
+
+extern	bmhd_t	bmhd;						// will be in native byte order
+
+
+
+#define FORMID ('F'+('O'<<8)+((int)'R'<<16)+((int)'M'<<24))
+#define ILBMID ('I'+('L'<<8)+((int)'B'<<16)+((int)'M'<<24))
+#define PBMID  ('P'+('B'<<8)+((int)'M'<<16)+((int)' '<<24))
+#define BMHDID ('B'+('M'<<8)+((int)'H'<<16)+((int)'D'<<24))
+#define BODYID ('B'+('O'<<8)+((int)'D'<<16)+((int)'Y'<<24))
+#define CMAPID ('C'+('M'<<8)+((int)'A'<<16)+((int)'P'<<24))
+
+
+bmhd_t  bmhd;
+
+int    Align (int l)
+{
+	if (l&1)
+		return l+1;
+	return l;
+}
+
+
+
+/*
+================
+LBMRLEdecompress
+
+Source must be evenly aligned!
+================
+*/
+byte  *LBMRLEDecompress (byte *source,byte *unpacked, int bpwidth)
+{
+	int     count;
+	byte    b,rept;
+
+	count = 0;
+
+	do
+	{
+		rept = *source++;
+
+		if (rept > 0x80)
+		{
+			rept = (rept^0xff)+2;
+			b = *source++;
+			memset(unpacked,b,rept);
+			unpacked += rept;
+		}
+		else if (rept < 0x80)
+		{
+			rept++;
+			memcpy(unpacked,source,rept);
+			unpacked += rept;
+			source += rept;
+		}
+		else
+			rept = 0;               // rept of 0x80 is NOP
+
+		count += rept;
+
+	} while (count<bpwidth);
+
+	if (count>bpwidth)
+		Error ("Decompression exceeded width!\n");
+
+
+	return source;
+}
+
+
+/*
+=================
+LoadLBM
+=================
+*/
+void LoadLBM (const char *filename, byte **picture, byte **palette)
+{
+	byte    *LBMbuffer, *picbuffer, *cmapbuffer;
+	int             y;
+	byte    *LBM_P, *LBMEND_P;
+	byte    *pic_p;
+	byte    *body_p;
+
+	int    formtype,formlength;
+	int    chunktype,chunklength;
+
+// qiet compiler warnings
+	picbuffer = NULL;
+	cmapbuffer = NULL;
+
+//
+// load the LBM
+//
+	LoadFile (filename, (void **)&LBMbuffer);
+
+//
+// parse the LBM header
+//
+	LBM_P = LBMbuffer;
+	if ( *(int *)LBMbuffer != LittleLong(FORMID) )
+	   Error ("No FORM ID at start of file!\n");
+
+	LBM_P += 4;
+	formlength = BigLong( *(int *)LBM_P );
+	LBM_P += 4;
+	LBMEND_P = LBM_P + Align(formlength);
+
+	formtype = LittleLong(*(int *)LBM_P);
+
+	if (formtype != ILBMID && formtype != PBMID)
+		Error ("Unrecognized form type: %c%c%c%c\n", formtype&0xff
+		,(formtype>>8)&0xff,(formtype>>16)&0xff,(formtype>>24)&0xff);
+
+	LBM_P += 4;
+
+//
+// parse chunks
+//
+
+	while (LBM_P < LBMEND_P)
+	{
+		chunktype = LBM_P[0] + (LBM_P[1]<<8) + (LBM_P[2]<<16) + (LBM_P[3]<<24);
+		LBM_P += 4;
+		chunklength = LBM_P[3] + (LBM_P[2]<<8) + (LBM_P[1]<<16) + (LBM_P[0]<<24);
+		LBM_P += 4;
+
+		switch ( chunktype )
+		{
+		case BMHDID:
+			memcpy (&bmhd,LBM_P,sizeof(bmhd));
+			bmhd.w = BigShort(bmhd.w);
+			bmhd.h = BigShort(bmhd.h);
+			bmhd.x = BigShort(bmhd.x);
+			bmhd.y = BigShort(bmhd.y);
+			bmhd.pageWidth = BigShort(bmhd.pageWidth);
+			bmhd.pageHeight = BigShort(bmhd.pageHeight);
+			break;
+
+		case CMAPID:
+			cmapbuffer = safe_malloc (768);
+			memset (cmapbuffer, 0, 768);
+			memcpy (cmapbuffer, LBM_P, chunklength);
+			break;
+
+		case BODYID:
+			body_p = LBM_P;
+
+			pic_p = picbuffer = safe_malloc (bmhd.w*bmhd.h);
+			if (formtype == PBMID)
+			{
+			//
+			// unpack PBM
+			//
+				for (y=0 ; y<bmhd.h ; y++, pic_p += bmhd.w)
+				{
+					if (bmhd.compression == cm_rle1)
+						body_p = LBMRLEDecompress ((byte *)body_p
+						, pic_p , bmhd.w);
+					else if (bmhd.compression == cm_none)
+					{
+						memcpy (pic_p,body_p,bmhd.w);
+						body_p += Align(bmhd.w);
+					}
+				}
+
+			}
+			else
+			{
+			//
+			// unpack ILBM
+			//
+				Error ("%s is an interlaced LBM, not packed", filename);
+			}
+			break;
+		}
+
+		LBM_P += Align(chunklength);
+	}
+
+	free (LBMbuffer);
+
+	*picture = picbuffer;
+
+	if (palette)
+		*palette = cmapbuffer;
+}
+
+
+/*
+============================================================================
+
+							WRITE LBM
+
+============================================================================
+*/
+
+/*
+==============
+WriteLBMfile
+==============
+*/
+void WriteLBMfile (const char *filename, byte *data,
+				   int width, int height, byte *palette)
+{
+	byte    *lbm, *lbmptr;
+	int    *formlength, *bmhdlength, *cmaplength, *bodylength;
+	int    length;
+	bmhd_t  basebmhd;
+
+	lbm = lbmptr = safe_malloc (width*height+1000);
+
+//
+// start FORM
+//
+	*lbmptr++ = 'F';
+	*lbmptr++ = 'O';
+	*lbmptr++ = 'R';
+	*lbmptr++ = 'M';
+
+	formlength = (int*)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	*lbmptr++ = 'P';
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'M';
+	*lbmptr++ = ' ';
+
+//
+// write BMHD
+//
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'M';
+	*lbmptr++ = 'H';
+	*lbmptr++ = 'D';
+
+	bmhdlength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memset (&basebmhd,0,sizeof(basebmhd));
+	basebmhd.w = BigShort((short)width);
+	basebmhd.h = BigShort((short)height);
+	basebmhd.nPlanes = BigShort(8);
+	basebmhd.xAspect = BigShort(5);
+	basebmhd.yAspect = BigShort(6);
+	basebmhd.pageWidth = BigShort((short)width);
+	basebmhd.pageHeight = BigShort((short)height);
+
+	memcpy (lbmptr,&basebmhd,sizeof(basebmhd));
+	lbmptr += sizeof(basebmhd);
+
+	length = lbmptr-(byte *)bmhdlength-4;
+	*bmhdlength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write CMAP
+//
+	*lbmptr++ = 'C';
+	*lbmptr++ = 'M';
+	*lbmptr++ = 'A';
+	*lbmptr++ = 'P';
+
+	cmaplength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memcpy (lbmptr,palette,768);
+	lbmptr += 768;
+
+	length = lbmptr-(byte *)cmaplength-4;
+	*cmaplength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write BODY
+//
+	*lbmptr++ = 'B';
+	*lbmptr++ = 'O';
+	*lbmptr++ = 'D';
+	*lbmptr++ = 'Y';
+
+	bodylength = (int *)lbmptr;
+	lbmptr+=4;                      // leave space for length
+
+	memcpy (lbmptr,data,width*height);
+	lbmptr += width*height;
+
+	length = lbmptr-(byte *)bodylength-4;
+	*bodylength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// done
+//
+	length = lbmptr-(byte *)formlength-4;
+	*formlength = BigLong(length);
+	if (length&1)
+		*lbmptr++ = 0;          // pad chunk to even offset
+
+//
+// write output file
+//
+	SaveFile (filename, lbm, lbmptr-lbm);
+	free (lbm);
+}
+
+
+/*
+============================================================================
+
+LOAD PCX
+
+============================================================================
+*/
+
+typedef struct
+{
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+
+/*
+==============
+LoadPCX
+==============
+*/
+
+/* RR2DO2 */
+#define DECODEPCX( b, d, r ) d=*b++;if((d&0xC0)==0xC0){r=d&0x3F;d=*b++;}else{r=1;}
+
+void LoadPCX( const char *filename, byte **pic, byte **palette, int *width, int *height )
+{
+	byte	*raw;
+	pcx_t	*pcx;
+	int		x, y, lsize;
+	int		len;
+	int		dataByte, runLength;
+	byte	*out, *pix;
+	
+
+	/* load the file */
+	len = vfsLoadFile (filename, (void **)&raw, 0);
+    if( len == -1 ) 
+		Error( "LoadPCX: Couldn't read %s", filename );
+
+	
+	/* parse the PCX file */
+	pcx = (pcx_t *)raw;
+	raw = &pcx->data;
+
+	pcx->xmin = LittleShort(pcx->xmin);
+	pcx->ymin = LittleShort(pcx->ymin);
+	pcx->xmax = LittleShort(pcx->xmax);
+	pcx->ymax = LittleShort(pcx->ymax);
+	pcx->hres = LittleShort(pcx->hres);
+	pcx->vres = LittleShort(pcx->vres);
+	pcx->bytes_per_line = LittleShort(pcx->bytes_per_line);
+	pcx->palette_type = LittleShort(pcx->palette_type);
+
+	if (pcx->manufacturer != 0x0a
+		|| pcx->version != 5
+		|| pcx->encoding != 1
+		|| pcx->bits_per_pixel != 8
+		|| pcx->xmax >= 640
+		|| pcx->ymax >= 480)
+		Error ("Bad pcx file %s", filename);
+	
+	if (palette)
+	{
+		*palette = safe_malloc(768);
+		memcpy (*palette, (byte *)pcx + len - 768, 768);
+	}
+
+	if (width)
+		*width = pcx->xmax+1;
+	if (height)
+		*height = pcx->ymax+1;
+
+	if (!pic)
+		return;
+
+	out = safe_malloc ( (pcx->ymax+1) * (pcx->xmax+1) );
+	if (!out)
+		Error( "LoadPCX: couldn't allocate");
+
+	*pic = out;
+	pix = out;
+	
+	/* RR2DO2: pcx fix  */
+	lsize = pcx->color_planes * pcx->bytes_per_line;
+	
+	/* go scanline by scanline */
+	for( y = 0; y <= pcx->ymax; y++, pix += pcx->xmax + 1 )
+	{
+		/* do a scanline */
+		for( x=0; x <= pcx->xmax; )
+		{
+			/* RR2DO2 */
+			DECODEPCX( raw, dataByte, runLength );
+			while( runLength-- > 0 )
+				pix[ x++ ] = dataByte;
+		}
+
+		/* RR2DO2: discard any other data */
+		while( x < lsize )
+		{
+			DECODEPCX( raw, dataByte, runLength );
+			x++;
+		}
+		while( runLength-- > 0 )
+			x++;
+	}
+	
+	/* validity check */
+	if( raw - (byte *) pcx > len)
+		Error( "PCX file %s was malformed", filename );
+	free( pcx );
+}
+
+
+
+/* 
+============== 
+WritePCXfile 
+============== 
+*/ 
+void WritePCXfile (const char *filename, byte *data, 
+				   int width, int height, byte *palette) 
+{
+	int		i, j, length;
+	pcx_t	*pcx;
+	byte		*pack;
+	  
+	pcx = safe_malloc (width*height*2+1000);
+	memset (pcx, 0, sizeof(*pcx));
+
+	pcx->manufacturer = 0x0a;	// PCX id
+	pcx->version = 5;			// 256 color
+ 	pcx->encoding = 1;		// uncompressed
+	pcx->bits_per_pixel = 8;		// 256 color
+	pcx->xmin = 0;
+	pcx->ymin = 0;
+	pcx->xmax = LittleShort((short)(width-1));
+	pcx->ymax = LittleShort((short)(height-1));
+	pcx->hres = LittleShort((short)width);
+	pcx->vres = LittleShort((short)height);
+	pcx->color_planes = 1;		// chunky image
+	pcx->bytes_per_line = LittleShort((short)width);
+	pcx->palette_type = LittleShort(1);		// not a grey scale
+
+	// pack the image
+	pack = &pcx->data;
+	
+	for (i=0 ; i<height ; i++)
+	{
+		for (j=0 ; j<width ; j++)
+		{
+			if ( (*data & 0xc0) != 0xc0)
+				*pack++ = *data++;
+			else
+			{
+				*pack++ = 0xc1;
+				*pack++ = *data++;
+			}
+		}
+	}
+			
+	// write the palette
+	*pack++ = 0x0c;	// palette ID byte
+	for (i=0 ; i<768 ; i++)
+		*pack++ = *palette++;
+		
+// write output file 
+	length = pack - (byte *)pcx;
+	SaveFile (filename, pcx, length);
+
+	free (pcx);
+} 
+ 
+/*
+============================================================================
+
+LOAD BMP
+
+============================================================================
+*/
+
+
+/*
+
+// we can't just use these structures, because
+// compiler structure alignment will not be portable
+// on this unaligned stuff
+
+typedef struct tagBITMAPFILEHEADER { // bmfh 
+        WORD    bfType;				// BM
+        DWORD   bfSize; 
+        WORD    bfReserved1; 
+        WORD    bfReserved2; 
+        DWORD   bfOffBits; 
+} BITMAPFILEHEADER; 
+ 
+typedef struct tagBITMAPINFOHEADER{ // bmih 
+   DWORD  biSize; 
+   LONG   biWidth; 
+   LONG   biHeight; 
+   WORD   biPlanes; 
+   WORD   biBitCount 
+   DWORD  biCompression; 
+   DWORD  biSizeImage; 
+   LONG   biXPelsPerMeter; 
+   LONG   biYPelsPerMeter; 
+   DWORD  biClrUsed; 
+   DWORD  biClrImportant; 
+} BITMAPINFOHEADER; 
+ 
+typedef struct tagBITMAPINFO { // bmi 
+   BITMAPINFOHEADER bmiHeader; 
+   RGBQUAD          bmiColors[1]; 
+} BITMAPINFO; 
+
+typedef struct tagBITMAPCOREHEADER { // bmch 
+        DWORD   bcSize; 
+        WORD    bcWidth; 
+        WORD    bcHeight; 
+        WORD    bcPlanes; 
+        WORD    bcBitCount; 
+} BITMAPCOREHEADER; 
+ 
+typedef struct _BITMAPCOREINFO {    // bmci 
+        BITMAPCOREHEADER  bmciHeader; 
+        RGBTRIPLE         bmciColors[1]; 
+} BITMAPCOREINFO; 
+ 
+*/
+
+/*
+==============
+LoadBMP
+==============
+*/
+void LoadBMP (const char *filename, byte **pic, byte **palette, int *width, int *height)
+{
+  byte	*out;
+  int		i;
+  int		bfSize; 
+  int		bfOffBits; 
+  int		structSize;
+  int		bcWidth; 
+  int     bcHeight; 
+  int	    bcPlanes; 
+  int		bcBitCount; 
+  byte	bcPalette[1024];
+  qboolean	flipped;
+  byte *in;
+  int len, pos = 0;
+
+  len = vfsLoadFile (filename, (void **)&in, 0);
+  if (len == -1) 
+  {
+    Error ("Couldn't read %s", filename);
+  }
+
+  i = bufLittleShort (in, len, &pos);
+  if (i != 'B' + ('M'<<8) ) {
+    Error ("%s is not a bmp file", filename);
+  }
+
+  bfSize = bufLittleLong (in, len, &pos);
+  bufLittleShort(in, len, &pos);
+  bufLittleShort(in, len, &pos);
+  bfOffBits = bufLittleLong (in, len, &pos);
+
+  // the size will tell us if it is a
+  // bitmapinfo or a bitmapcore
+  structSize = bufLittleLong (in, len, &pos);
+  if (structSize == 40)
+  {
+    // bitmapinfo
+    bcWidth = bufLittleLong(in, len, &pos); 
+    bcHeight= bufLittleLong(in, len, &pos); 
+    bcPlanes = bufLittleShort(in, len, &pos); 
+    bcBitCount = bufLittleShort(in, len, &pos); 
+
+    pos += 24;
+
+    if (palette)
+    {
+      memcpy (bcPalette, in+pos, 1024);
+      pos += 1024;
+      *palette = safe_malloc(768);
+
+      for (i = 0 ; i < 256 ; i++)
+      {
+        (*palette)[i * 3 + 0] = bcPalette[i * 4 + 2];
+        (*palette)[i * 3 + 1] = bcPalette[i * 4 + 1];
+        (*palette)[i * 3 + 2] = bcPalette[i * 4 + 0];
+      }
+    }
+  }
+  else if (structSize == 12)
+  {
+    // bitmapcore
+    bcWidth = bufLittleShort(in, len, &pos); 
+    bcHeight= bufLittleShort(in, len, &pos); 
+    bcPlanes = bufLittleShort(in, len, &pos); 
+    bcBitCount = bufLittleShort(in, len, &pos); 
+
+    if (palette)
+    {
+      memcpy (bcPalette, in+pos, 768);
+      pos += 768;
+      *palette = safe_malloc(768);
+
+      for (i = 0 ; i < 256 ; i++) {
+        (*palette)[i * 3 + 0] = bcPalette[i * 3 + 2];
+        (*palette)[i * 3 + 1] = bcPalette[i * 3 + 1];
+        (*palette)[i * 3 + 2] = bcPalette[i * 3 + 0];
+      }
+    }
+  } else {
+    Error ("%s had strange struct size", filename);
+  }
+
+  if (bcPlanes != 1) {
+    Error ("%s was not a single plane image", filename);
+  }
+
+  if (bcBitCount != 8) {
+    Error ("%s was not an 8 bit image", filename);
+  }
+
+  if (bcHeight < 0) {
+    bcHeight = -bcHeight;
+    flipped = qtrue;
+  } else {
+    flipped = qfalse;
+  }
+
+  if (width)
+    *width = bcWidth;
+  if (height)
+    *height = bcHeight;
+
+  if (!pic) {
+    free (in);
+    return;
+  }
+
+  out = safe_malloc ( bcWidth * bcHeight );
+  *pic = out;
+  pos = bfOffBits;
+
+  if (flipped) {
+    for (i = 0 ; i < bcHeight ; i++) {
+      memcpy (out + bcWidth * (bcHeight - 1 - i), in+pos, bcWidth);
+      pos += bcWidth;
+    }
+  } else {
+    memcpy (out, in+pos, bcWidth*bcHeight);
+    pos += bcWidth*bcHeight;
+  }
+
+  free (in);
+}
+
+
+/*
+============================================================================
+
+LOAD IMAGE
+
+============================================================================
+*/
+
+/*
+==============
+Load256Image
+
+Will load either an lbm or pcx, depending on extension.
+Any of the return pointers can be NULL if you don't want them.
+==============
+*/
+void Load256Image (const char *name, byte **pixels, byte **palette, int *width, int *height)
+{
+  char ext[128];
+
+  ExtractFileExtension (name, ext);
+  if (!Q_stricmp (ext, "lbm"))
+  {
+    LoadLBM (name, pixels, palette);
+    if (width)
+      *width = bmhd.w;
+    if (height)
+      *height = bmhd.h;
+  }
+  else if (!Q_stricmp (ext, "pcx"))
+  {
+    LoadPCX (name, pixels, palette, width, height);
+  }
+  else if (!Q_stricmp (ext, "bmp"))
+  {
+    LoadBMP (name, pixels, palette, width, height);
+  }
+  else
+    Error ("%s doesn't have a known image extension", name);
+}
+
+
+/*
+==============
+Save256Image
+
+Will save either an lbm or pcx, depending on extension.
+==============
+*/
+void Save256Image (const char *name, byte *pixels, byte *palette,
+				   int width, int height)
+{
+	char	ext[128];
+
+	ExtractFileExtension (name, ext);
+	if (!Q_stricmp (ext, "lbm"))
+	{
+		WriteLBMfile (name, pixels, width, height, palette);
+	}
+	else if (!Q_stricmp (ext, "pcx"))
+	{
+		WritePCXfile (name, pixels, width, height, palette);
+	}
+	else
+		Error ("%s doesn't have a known image extension", name);
+}
+
+
+
+
+/*
+============================================================================
+
+TARGA IMAGE
+
+============================================================================
+*/
+
+typedef struct _TargaHeader {
+	unsigned char 	id_length, colormap_type, image_type;
+	unsigned short	colormap_index, colormap_length;
+	unsigned char	colormap_size;
+	unsigned short	x_origin, y_origin, width, height;
+	unsigned char	pixel_size, attributes;
+} TargaHeader;
+
+/*
+=============
+LoadTGABuffer
+=============
+*/
+void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height)
+{
+	int		columns, rows, numPixels;
+	byte	*pixbuf;
+	int		row, column;
+	byte	*buf_p;
+	TargaHeader	targa_header;
+	byte		*targa_rgba;
+
+	*pic = NULL;
+
+	buf_p = buffer;
+
+	targa_header.id_length = *buf_p++;
+	targa_header.colormap_type = *buf_p++;
+	targa_header.image_type = *buf_p++;
+	
+	targa_header.colormap_index = LittleShort ( *(short *)buf_p );
+	buf_p += 2;
+	targa_header.colormap_length = LittleShort ( *(short *)buf_p );
+	buf_p += 2;
+	targa_header.colormap_size = *buf_p++;
+	targa_header.x_origin = LittleShort ( *(short *)buf_p );
+	buf_p += 2;
+	targa_header.y_origin = LittleShort ( *(short *)buf_p );
+	buf_p += 2;
+	targa_header.width = LittleShort ( *(short *)buf_p );
+	buf_p += 2;
+	targa_header.height = LittleShort ( *(short *)buf_p );
+	buf_p += 2;
+	targa_header.pixel_size = *buf_p++;
+	targa_header.attributes = *buf_p++;
+
+	if (targa_header.image_type!=2 
+		&& targa_header.image_type!=10
+		&& targa_header.image_type != 3 ) 
+	{
+		Error("LoadTGA: Only type 2 (RGB), 3 (gray), and 10 (RGB) TGA images supported\n");
+	}
+
+	if ( targa_header.colormap_type != 0 )
+	{
+		Error("LoadTGA: colormaps not supported\n" );
+	}
+
+	if ( ( targa_header.pixel_size != 32 && targa_header.pixel_size != 24 ) && targa_header.image_type != 3 )
+	{
+		Error("LoadTGA: Only 32 or 24 bit images supported (no colormaps)\n");
+	}
+
+	columns = targa_header.width;
+	rows = targa_header.height;
+	numPixels = columns * rows;
+
+	if (width)
+		*width = columns;
+	if (height)
+		*height = rows;
+
+	targa_rgba = safe_malloc (numPixels*4);
+	*pic = targa_rgba;
+
+	if (targa_header.id_length != 0)
+		buf_p += targa_header.id_length;  // skip TARGA image comment
+	
+	if ( targa_header.image_type==2 || targa_header.image_type == 3 )
+	{ 
+		// Uncompressed RGB or gray scale image
+		for(row=rows-1; row>=0; row--) 
+		{
+			pixbuf = targa_rgba + row*columns*4;
+			for(column=0; column<columns; column++) 
+			{
+				unsigned char red,green,blue,alphabyte;
+				switch (targa_header.pixel_size) 
+				{
+					
+				case 8:
+					blue = *buf_p++;
+					green = blue;
+					red = blue;
+					*pixbuf++ = red;
+					*pixbuf++ = green;
+					*pixbuf++ = blue;
+					*pixbuf++ = 255;
+					break;
+
+				case 24:
+					blue = *buf_p++;
+					green = *buf_p++;
+					red = *buf_p++;
+					*pixbuf++ = red;
+					*pixbuf++ = green;
+					*pixbuf++ = blue;
+					*pixbuf++ = 255;
+					break;
+				case 32:
+					blue = *buf_p++;
+					green = *buf_p++;
+					red = *buf_p++;
+					alphabyte = *buf_p++;
+					*pixbuf++ = red;
+					*pixbuf++ = green;
+					*pixbuf++ = blue;
+					*pixbuf++ = alphabyte;
+					break;
+				default:
+					//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
+					break;
+				}
+			}
+		}
+	}
+	else if (targa_header.image_type==10) {   // Runlength encoded RGB images
+		unsigned char red,green,blue,alphabyte,packetHeader,packetSize,j;
+
+		red = 0;
+		green = 0;
+		blue = 0;
+		alphabyte = 0xff;
+
+		for(row=rows-1; row>=0; row--) {
+			pixbuf = targa_rgba + row*columns*4;
+			for(column=0; column<columns; ) {
+				packetHeader= *buf_p++;
+				packetSize = 1 + (packetHeader & 0x7f);
+				if (packetHeader & 0x80) {        // run-length packet
+					switch (targa_header.pixel_size) {
+						case 24:
+								blue = *buf_p++;
+								green = *buf_p++;
+								red = *buf_p++;
+								alphabyte = 255;
+								break;
+						case 32:
+								blue = *buf_p++;
+								green = *buf_p++;
+								red = *buf_p++;
+								alphabyte = *buf_p++;
+								break;
+						default:
+							//Error("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
+							break;
+					}
+	
+					for(j=0;j<packetSize;j++) {
+						*pixbuf++=red;
+						*pixbuf++=green;
+						*pixbuf++=blue;
+						*pixbuf++=alphabyte;
+						column++;
+						if (column==columns) { // run spans across rows
+							column=0;
+							if (row>0)
+								row--;
+							else
+								goto breakOut;
+							pixbuf = targa_rgba + row*columns*4;
+						}
+					}
+				}
+				else {                            // non run-length packet
+					for(j=0;j<packetSize;j++) {
+						switch (targa_header.pixel_size) {
+							case 24:
+									blue = *buf_p++;
+									green = *buf_p++;
+									red = *buf_p++;
+									*pixbuf++ = red;
+									*pixbuf++ = green;
+									*pixbuf++ = blue;
+									*pixbuf++ = 255;
+									break;
+							case 32:
+									blue = *buf_p++;
+									green = *buf_p++;
+									red = *buf_p++;
+									alphabyte = *buf_p++;
+									*pixbuf++ = red;
+									*pixbuf++ = green;
+									*pixbuf++ = blue;
+									*pixbuf++ = alphabyte;
+									break;
+							default:
+								//Sysprintf("LoadTGA: illegal pixel_size '%d' in file '%s'\n", targa_header.pixel_size, name );
+								break;
+						}
+						column++;
+						if (column==columns) { // pixel packet run spans across rows
+							column=0;
+							if (row>0)
+								row--;
+							else
+								goto breakOut;
+							pixbuf = targa_rgba + row*columns*4;
+						}						
+					}
+				}
+			}
+			breakOut:;
+		}
+	}
+
+	// vertically flipped
+	if ( (targa_header.attributes & (1<<5)) ) {
+		int flip;
+		for (row = 0; row < .5f * rows; row++)
+		{
+			for (column = 0; column < columns; column++)
+			{
+				flip = *( (int*)targa_rgba + row * columns + column);
+				*( (int*)targa_rgba + row * columns + column) = *( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column );
+				*( (int*)targa_rgba + ( ( rows - 1 ) - row ) * columns + column ) = flip;
+			}
+		}
+	}
+
+	//free(buffer);
+}
+
+
+
+/*
+=============
+LoadTGA
+=============
+*/
+void LoadTGA (const char *name, byte **pixels, int *width, int *height)
+{
+	byte			*buffer;
+  int nLen;
+	//
+	// load the file
+	//
+	nLen = vfsLoadFile ( ( char * ) name, (void **)&buffer, 0);
+	if (nLen == -1) 
+  {
+		Error ("Couldn't read %s", name);
+  }
+
+  LoadTGABuffer(buffer, pixels, width, height);
+
+}
+
+
+/*
+================
+WriteTGA
+================
+*/
+void WriteTGA (const char *filename, byte *data, int width, int height) {
+	byte	*buffer;
+	int		i;
+	int		c;
+	FILE	*f;
+
+	buffer = safe_malloc(width*height*4 + 18);
+	memset (buffer, 0, 18);
+	buffer[2] = 2;		// uncompressed type
+	buffer[12] = width&255;
+	buffer[13] = width>>8;
+	buffer[14] = height&255;
+	buffer[15] = height>>8;
+	buffer[16] = 32;	// pixel size
+
+	// swap rgb to bgr
+	c = 18 + width * height * 4;
+	for (i=18 ; i<c ; i+=4)
+	{
+		buffer[i] = data[i-18+2];		// blue
+		buffer[i+1] = data[i-18+1];		// green
+		buffer[i+2] = data[i-18+0];		// red
+		buffer[i+3] = data[i-18+3];		// alpha
+	}
+
+	f = fopen (filename, "wb");
+	fwrite (buffer, 1, c, f);
+	fclose (f);
+
+	free (buffer);
+}
+
+/*
+============================================================================
+
+LOAD32BITIMAGE
+
+============================================================================
+*/
+
+/*
+==============
+Load32BitImage
+
+Any of the return pointers can be NULL if you don't want them.
+==============
+*/
+void Load32BitImage (const char *name, unsigned **pixels,  int *width, int *height)
+{
+	char	ext[128];
+	byte	*palette;
+	byte	*pixels8;
+	byte	*pixels32;
+	int		size;
+	int		i;
+	int		v;
+
+	ExtractFileExtension (name, ext);
+	if (!Q_stricmp (ext, "tga")) {
+		LoadTGA (name, (byte **)pixels, width, height);
+	} else {
+		Load256Image (name, &pixels8, &palette, width, height);
+		if (!pixels) {
+			return;
+		}
+		size = *width * *height;
+		pixels32 = safe_malloc(size * 4);
+		*pixels = (unsigned *)pixels32;
+		for (i = 0 ; i < size ; i++) {
+			v = pixels8[i];
+			pixels32[i*4 + 0] = palette[ v * 3 + 0 ];
+			pixels32[i*4 + 1] = palette[ v * 3 + 1 ];
+			pixels32[i*4 + 2] = palette[ v * 3 + 2 ];
+			pixels32[i*4 + 3] = 0xff;
+		}
+	}
+}
+
+
diff --git a/tools/quake3/common/imagelib.h b/tools/quake3/common/imagelib.h
index 46b4ae3a..e3d64e96 100644
--- a/tools/quake3/common/imagelib.h
+++ b/tools/quake3/common/imagelib.h
@@ -1,44 +1,44 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// piclib.h
-
-
-void LoadLBM (const char *filename, byte **picture, byte **palette);
-void WriteLBMfile (const char *filename, byte *data, int width, int height
-	, byte *palette);
-void LoadPCX (const char *filename, byte **picture, byte **palette, int *width, int *height);
-void WritePCXfile (const char *filename, byte *data, int width, int height
-	, byte *palette);
-
-// loads / saves either lbm or pcx, depending on extension
-void Load256Image (const char *name, byte **pixels, byte **palette,
-				   int *width, int *height);
-void Save256Image (const char *name, byte *pixels, byte *palette,
-				   int width, int height);
-
-
-void LoadTGA (const char *filename, byte **pixels, int *width, int *height);
-void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height);
-void WriteTGA (const char *filename, byte *data, int width, int height);
-
-void Load32BitImage (const char *name, unsigned **pixels, int *width, int *height);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// piclib.h
+
+
+void LoadLBM (const char *filename, byte **picture, byte **palette);
+void WriteLBMfile (const char *filename, byte *data, int width, int height
+	, byte *palette);
+void LoadPCX (const char *filename, byte **picture, byte **palette, int *width, int *height);
+void WritePCXfile (const char *filename, byte *data, int width, int height
+	, byte *palette);
+
+// loads / saves either lbm or pcx, depending on extension
+void Load256Image (const char *name, byte **pixels, byte **palette,
+				   int *width, int *height);
+void Save256Image (const char *name, byte *pixels, byte *palette,
+				   int width, int height);
+
+
+void LoadTGA (const char *filename, byte **pixels, int *width, int *height);
+void LoadTGABuffer ( byte *buffer, byte **pic, int *width, int *height);
+void WriteTGA (const char *filename, byte *data, int width, int height);
+
+void Load32BitImage (const char *name, unsigned **pixels, int *width, int *height);
+
diff --git a/tools/quake3/common/inout.c b/tools/quake3/common/inout.c
index ede88891..dcdd0893 100644
--- a/tools/quake3/common/inout.c
+++ b/tools/quake3/common/inout.c
@@ -1,367 +1,367 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//-----------------------------------------------------------------------------
-//
-//
-// DESCRIPTION:
-// deal with in/out tasks, for either stdin/stdout or network/XML stream
-// 
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "polylib.h"
-#include "inout.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifdef _WIN32
-#include <direct.h>
-#include <windows.h>
-#endif
-
-// network broadcasting
-#include "l_net/l_net.h"
-#include "libxml/tree.h"
-
-#ifdef _WIN32
-HWND hwndOut = NULL;
-qboolean lookedForServer = qfalse;
-UINT wm_BroadcastCommand = -1;
-#endif
-
-socket_t *brdcst_socket;
-netmessage_t msg;
-
-qboolean verbose = qfalse;
-
-// our main document
-// is streamed through the network to Radiant
-// possibly written to disk at the end of the run
-//++timo FIXME: need to be global, required when creating nodes?
-xmlDocPtr doc;
-xmlNodePtr tree;
-
-// some useful stuff
-xmlNodePtr xml_NodeForVec( vec3_t v )
-{
-  xmlNodePtr ret;
-  char buf[1024];
-  
-  sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
-  ret = xmlNewNode (NULL, "point");
-  xmlNodeSetContent (ret, buf);
-  return ret;
-}
-
-// send a node down the stream, add it to the document
-void xml_SendNode (xmlNodePtr node)
-{
-  xmlBufferPtr xml_buf;
-  char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
-  // this index loops through the node buffer
-  int pos = 0;
-  int size;
-
-  xmlAddChild( doc->children, node );
-
-  if (brdcst_socket)
-  {
-    xml_buf = xmlBufferCreate();
-    xmlNodeDump( xml_buf, doc, node, 0, 0 );
-
-    // the XML node might be too big to fit in a single network message
-    // l_net library defines an upper limit of MAX_NETMESSAGE
-    // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
-    // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
-    while (pos < xml_buf->use)
-    {
-      // what size are we gonna send now?
-      (xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
-      //++timo just a debug thing
-      if (size == MAX_NETMESSAGE - 10)
-        Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
-      memcpy( xmlbuf, xml_buf->content+pos, size);
-      xmlbuf[size] = '\0';
-      NMSG_Clear( &msg );
-      NMSG_WriteString (&msg, xmlbuf );
-      Net_Send(brdcst_socket, &msg );
-      // now that the thing is sent prepare to loop again
-      pos += size;
-    }
-
-#if 0
-    // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
-    // we will need to split into chunks
-    // (we could also go lower level, in the end it's using send and receiv which are not size limited)
-    //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
-    //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
-
-    //++timo we need to handle the case of a buffer too big to fit in a single message
-    // try without checks for now
-    if (xml_buf->use > MAX_NETMESSAGE-10 )
-    {
-      // if we send that we are probably gonna break the stream at the other end..
-      // and Error will call right there
-      //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
-      Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
-      xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
-      Sys_FPrintf (SYS_NOXML, xml_buf->content);
-
-    }
-
-    size = xml_buf->use;
-    memcpy( xmlbuf, xml_buf->content, size );
-    xmlbuf[size] = '\0';
-    NMSG_Clear( &msg );
-    NMSG_WriteString (&msg, xmlbuf );
-    Net_Send(brdcst_socket, &msg );
-#endif
-
-    xmlBufferFree( xml_buf );
-  }  
-}
-
-void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
-{
-  xmlNodePtr node, select;
-  char buf[1024];
-  char level[2];
-
-  // now build a proper "select" XML node
-  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
-  node = xmlNewNode (NULL, "select");
-  xmlNodeSetContent (node, buf);
-  level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN)  ;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'select' information
-  sprintf (buf, "%i %i", entitynum, brushnum);
-  select = xmlNewNode (NULL, "brush");
-  xmlNodeSetContent (select, buf);
-  xmlAddChild (node, select);
-  xml_SendNode (node);
-
-  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
-  if (bError)
-    Error(buf);
-  else
-    Sys_FPrintf (SYS_NOXML, "%s\n", buf);
-
-}
-
-void xml_Point (char *msg, vec3_t pt)
-{
-  xmlNodePtr node, point;
-  char buf[1024];
-  char level[2];
-
-  node = xmlNewNode (NULL, "pointmsg");
-  xmlNodeSetContent (node, msg);
-  level[0] = (int)'0' + SYS_ERR;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'point' node
-  sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
-  point = xmlNewNode (NULL, "point");
-  xmlNodeSetContent (point, buf);
-  xmlAddChild (node, point);
-  xml_SendNode (node);
-
-  sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
-  Error (buf);
-}
-
-#define WINDING_BUFSIZE 2048
-void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
-{
-  xmlNodePtr node, winding;
-  char buf[WINDING_BUFSIZE];
-  char smlbuf[128];
-  char level[2];
-  int i;
-
-  node = xmlNewNode (NULL, "windingmsg");
-  xmlNodeSetContent (node, msg);
-  level[0] = (int)'0' + SYS_ERR;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level);
-  // a 'winding' node
-  sprintf( buf, "%i ", numpoints);
-  for(i = 0; i < numpoints; i++)
-  {
-	  sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
-    // don't overflow
-    if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
-      break;
-	  strcat( buf, smlbuf);
-  }
-
-  winding = xmlNewNode (NULL, "winding");
-  xmlNodeSetContent (winding, buf);
-  xmlAddChild (node, winding);
-  xml_SendNode (node);
-
-  if(die)
-    Error (msg);
-  else
-  {
-    Sys_Printf(msg);
-    Sys_Printf("\n");
-  }
-}
-
-// in include
-#include "stream_version.h"
-
-void Broadcast_Setup( const char *dest )
-{
-	address_t address;
-  char sMsg[1024];
-
-	Net_Setup();
-	Net_StringToAddress((char *)dest, &address);
-  brdcst_socket = Net_Connect(&address, 0);
-  if (brdcst_socket)
-  {
-    // send in a header
-    sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
-    NMSG_Clear( &msg );
-    NMSG_WriteString(&msg, sMsg );
-    Net_Send(brdcst_socket, &msg );
-  }
-}
-
-void Broadcast_Shutdown()
-{
-  if (brdcst_socket)
-  {    
-    Sys_Printf("Disconnecting\n");
-    Net_Disconnect(brdcst_socket);
-    brdcst_socket = NULL;
-  }
-}
-
-// all output ends up through here
-void FPrintf (int flag, char *buf)
-{
-  xmlNodePtr node;
-  static qboolean bGotXML = qfalse;
-  char level[2];
-
-  printf(buf);
-
-  // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
-  if (flag == SYS_NOXML)
-    return;
-
-  // ouput an XML file of the run
-  // use the DOM interface to build a tree
-  /*
-  <message level='flag'>
-    message string
-    .. various nodes to describe corresponding geometry ..
-  </message>
-  */
-  if (!bGotXML)
-  {
-    // initialize
-    doc = xmlNewDoc("1.0");
-    doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
-    bGotXML = qtrue;
-  }
-  node = xmlNewNode (NULL, "message");
-  xmlNodeSetContent (node, buf);
-  level[0] = (int)'0' + flag;
-  level[1] = 0;
-  xmlSetProp (node, "level", (char *)&level );
-  
-  xml_SendNode (node);
-}
-
-#ifdef DBG_XML
-void DumpXML()
-{
-  xmlSaveFile( "XMLDump.xml", doc );
-}
-#endif
-
-void Sys_FPrintf (int flag, const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-  
-  if ((flag == SYS_VRB) && (verbose == qfalse))
-    return;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-
-  FPrintf (flag, out_buffer);
-}
-
-void Sys_Printf (const char *format, ...)
-{
-  char out_buffer[4096];
-	va_list argptr;
-
-  va_start (argptr, format);
-	vsprintf (out_buffer, format, argptr);
-	va_end (argptr);
-  
-  FPrintf (SYS_STD, out_buffer);
-}
-
-/*
-=================
-Error
-
-For abnormal program terminations
-=================
-*/
-void Error( const char *error, ...)
-{
-  char out_buffer[4096];
-  char tmp[4096];
-	va_list argptr;
-
-	va_start (argptr,error);
-	vsprintf (tmp, error, argptr);
-	va_end (argptr);
-
-  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
-
-  FPrintf( SYS_ERR, out_buffer );
-
-#ifdef DBG_XML  
-  DumpXML();
-#endif
-
-  //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
-  // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
-  Sys_Sleep( 1000 );
-  
-  Broadcast_Shutdown();
-
-	exit (1);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//-----------------------------------------------------------------------------
+//
+//
+// DESCRIPTION:
+// deal with in/out tasks, for either stdin/stdout or network/XML stream
+// 
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "polylib.h"
+#include "inout.h"
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#ifdef _WIN32
+#include <direct.h>
+#include <windows.h>
+#endif
+
+// network broadcasting
+#include "l_net/l_net.h"
+#include "libxml/tree.h"
+
+#ifdef _WIN32
+HWND hwndOut = NULL;
+qboolean lookedForServer = qfalse;
+UINT wm_BroadcastCommand = -1;
+#endif
+
+socket_t *brdcst_socket;
+netmessage_t msg;
+
+qboolean verbose = qfalse;
+
+// our main document
+// is streamed through the network to Radiant
+// possibly written to disk at the end of the run
+//++timo FIXME: need to be global, required when creating nodes?
+xmlDocPtr doc;
+xmlNodePtr tree;
+
+// some useful stuff
+xmlNodePtr xml_NodeForVec( vec3_t v )
+{
+  xmlNodePtr ret;
+  char buf[1024];
+  
+  sprintf (buf, "%f %f %f", v[0], v[1], v[2]);
+  ret = xmlNewNode (NULL, "point");
+  xmlNodeSetContent (ret, buf);
+  return ret;
+}
+
+// send a node down the stream, add it to the document
+void xml_SendNode (xmlNodePtr node)
+{
+  xmlBufferPtr xml_buf;
+  char xmlbuf[MAX_NETMESSAGE]; // we have to copy content from the xmlBufferPtr into an aux buffer .. that sucks ..
+  // this index loops through the node buffer
+  int pos = 0;
+  int size;
+
+  xmlAddChild( doc->children, node );
+
+  if (brdcst_socket)
+  {
+    xml_buf = xmlBufferCreate();
+    xmlNodeDump( xml_buf, doc, node, 0, 0 );
+
+    // the XML node might be too big to fit in a single network message
+    // l_net library defines an upper limit of MAX_NETMESSAGE
+    // there are some size check errors, so we use MAX_NETMESSAGE-10 to be safe
+    // if the size of the buffer exceeds MAX_NETMESSAGE-10 we'll send in several network messages
+    while (pos < xml_buf->use)
+    {
+      // what size are we gonna send now?
+      (xml_buf->use - pos < MAX_NETMESSAGE - 10) ? (size = xml_buf->use - pos) : (size = MAX_NETMESSAGE - 10);
+      //++timo just a debug thing
+      if (size == MAX_NETMESSAGE - 10)
+        Sys_FPrintf (SYS_NOXML, "Got to split the buffer\n");
+      memcpy( xmlbuf, xml_buf->content+pos, size);
+      xmlbuf[size] = '\0';
+      NMSG_Clear( &msg );
+      NMSG_WriteString (&msg, xmlbuf );
+      Net_Send(brdcst_socket, &msg );
+      // now that the thing is sent prepare to loop again
+      pos += size;
+    }
+
+#if 0
+    // NOTE: the NMSG_WriteString is limited to MAX_NETMESSAGE
+    // we will need to split into chunks
+    // (we could also go lower level, in the end it's using send and receiv which are not size limited)
+    //++timo FIXME: MAX_NETMESSAGE is not exactly the max size we can stick in the message
+    //  there's some tweaking to do in l_net for that .. so let's give us a margin for now
+
+    //++timo we need to handle the case of a buffer too big to fit in a single message
+    // try without checks for now
+    if (xml_buf->use > MAX_NETMESSAGE-10 )
+    {
+      // if we send that we are probably gonna break the stream at the other end..
+      // and Error will call right there
+      //Error( "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
+      Sys_FPrintf (SYS_NOXML, "MAX_NETMESSAGE exceeded for XML feedback stream in FPrintf (%d)\n", xml_buf->use);
+      xml_buf->content[xml_buf->use]='\0'; //++timo this corrupts the buffer but we don't care it's for printing
+      Sys_FPrintf (SYS_NOXML, xml_buf->content);
+
+    }
+
+    size = xml_buf->use;
+    memcpy( xmlbuf, xml_buf->content, size );
+    xmlbuf[size] = '\0';
+    NMSG_Clear( &msg );
+    NMSG_WriteString (&msg, xmlbuf );
+    Net_Send(brdcst_socket, &msg );
+#endif
+
+    xmlBufferFree( xml_buf );
+  }  
+}
+
+void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError)
+{
+  xmlNodePtr node, select;
+  char buf[1024];
+  char level[2];
+
+  // now build a proper "select" XML node
+  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
+  node = xmlNewNode (NULL, "select");
+  xmlNodeSetContent (node, buf);
+  level[0] = (int)'0' + (bError ? SYS_ERR : SYS_WRN)  ;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'select' information
+  sprintf (buf, "%i %i", entitynum, brushnum);
+  select = xmlNewNode (NULL, "brush");
+  xmlNodeSetContent (select, buf);
+  xmlAddChild (node, select);
+  xml_SendNode (node);
+
+  sprintf (buf, "Entity %i, Brush %i: %s", entitynum, brushnum, msg);
+  if (bError)
+    Error(buf);
+  else
+    Sys_FPrintf (SYS_NOXML, "%s\n", buf);
+
+}
+
+void xml_Point (char *msg, vec3_t pt)
+{
+  xmlNodePtr node, point;
+  char buf[1024];
+  char level[2];
+
+  node = xmlNewNode (NULL, "pointmsg");
+  xmlNodeSetContent (node, msg);
+  level[0] = (int)'0' + SYS_ERR;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'point' node
+  sprintf (buf, "%g %g %g", pt[0], pt[1], pt[2]);
+  point = xmlNewNode (NULL, "point");
+  xmlNodeSetContent (point, buf);
+  xmlAddChild (node, point);
+  xml_SendNode (node);
+
+  sprintf (buf, "%s (%g %g %g)", msg, pt[0], pt[1], pt[2]);
+  Error (buf);
+}
+
+#define WINDING_BUFSIZE 2048
+void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die)
+{
+  xmlNodePtr node, winding;
+  char buf[WINDING_BUFSIZE];
+  char smlbuf[128];
+  char level[2];
+  int i;
+
+  node = xmlNewNode (NULL, "windingmsg");
+  xmlNodeSetContent (node, msg);
+  level[0] = (int)'0' + SYS_ERR;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level);
+  // a 'winding' node
+  sprintf( buf, "%i ", numpoints);
+  for(i = 0; i < numpoints; i++)
+  {
+	  sprintf (smlbuf, "(%g %g %g)", p[i][0], p[i][1], p[i][2]);
+    // don't overflow
+    if (strlen(buf)+strlen(smlbuf)>WINDING_BUFSIZE)
+      break;
+	  strcat( buf, smlbuf);
+  }
+
+  winding = xmlNewNode (NULL, "winding");
+  xmlNodeSetContent (winding, buf);
+  xmlAddChild (node, winding);
+  xml_SendNode (node);
+
+  if(die)
+    Error (msg);
+  else
+  {
+    Sys_Printf(msg);
+    Sys_Printf("\n");
+  }
+}
+
+// in include
+#include "stream_version.h"
+
+void Broadcast_Setup( const char *dest )
+{
+	address_t address;
+  char sMsg[1024];
+
+	Net_Setup();
+	Net_StringToAddress((char *)dest, &address);
+  brdcst_socket = Net_Connect(&address, 0);
+  if (brdcst_socket)
+  {
+    // send in a header
+    sprintf (sMsg, "<?xml version=\"1.0\"?><q3map_feedback version=\"" Q3MAP_STREAM_VERSION "\">");
+    NMSG_Clear( &msg );
+    NMSG_WriteString(&msg, sMsg );
+    Net_Send(brdcst_socket, &msg );
+  }
+}
+
+void Broadcast_Shutdown()
+{
+  if (brdcst_socket)
+  {    
+    Sys_Printf("Disconnecting\n");
+    Net_Disconnect(brdcst_socket);
+    brdcst_socket = NULL;
+  }
+}
+
+// all output ends up through here
+void FPrintf (int flag, char *buf)
+{
+  xmlNodePtr node;
+  static qboolean bGotXML = qfalse;
+  char level[2];
+
+  printf(buf);
+
+  // the following part is XML stuff only.. but maybe we don't want that message to go down the XML pipe?
+  if (flag == SYS_NOXML)
+    return;
+
+  // ouput an XML file of the run
+  // use the DOM interface to build a tree
+  /*
+  <message level='flag'>
+    message string
+    .. various nodes to describe corresponding geometry ..
+  </message>
+  */
+  if (!bGotXML)
+  {
+    // initialize
+    doc = xmlNewDoc("1.0");
+    doc->children = xmlNewDocRawNode(doc, NULL, "q3map_feedback", NULL);
+    bGotXML = qtrue;
+  }
+  node = xmlNewNode (NULL, "message");
+  xmlNodeSetContent (node, buf);
+  level[0] = (int)'0' + flag;
+  level[1] = 0;
+  xmlSetProp (node, "level", (char *)&level );
+  
+  xml_SendNode (node);
+}
+
+#ifdef DBG_XML
+void DumpXML()
+{
+  xmlSaveFile( "XMLDump.xml", doc );
+}
+#endif
+
+void Sys_FPrintf (int flag, const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+  
+  if ((flag == SYS_VRB) && (verbose == qfalse))
+    return;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+
+  FPrintf (flag, out_buffer);
+}
+
+void Sys_Printf (const char *format, ...)
+{
+  char out_buffer[4096];
+	va_list argptr;
+
+  va_start (argptr, format);
+	vsprintf (out_buffer, format, argptr);
+	va_end (argptr);
+  
+  FPrintf (SYS_STD, out_buffer);
+}
+
+/*
+=================
+Error
+
+For abnormal program terminations
+=================
+*/
+void Error( const char *error, ...)
+{
+  char out_buffer[4096];
+  char tmp[4096];
+	va_list argptr;
+
+	va_start (argptr,error);
+	vsprintf (tmp, error, argptr);
+	va_end (argptr);
+
+  sprintf( out_buffer, "************ ERROR ************\n%s\n", tmp );
+
+  FPrintf( SYS_ERR, out_buffer );
+
+#ifdef DBG_XML  
+  DumpXML();
+#endif
+
+  //++timo HACK ALERT .. if we shut down too fast the xml stream won't reach the listener.
+  // a clean solution is to send a sync request node in the stream and wait for an answer before exiting
+  Sys_Sleep( 1000 );
+  
+  Broadcast_Shutdown();
+
+	exit (1);
+}
+
diff --git a/tools/quake3/common/inout.h b/tools/quake3/common/inout.h
index b7f13270..d417a583 100644
--- a/tools/quake3/common/inout.h
+++ b/tools/quake3/common/inout.h
@@ -1,61 +1,61 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __INOUT__
-#define __INOUT__
-
-// inout is the only stuff relying on xml, include the headers there
-#include "libxml/tree.h"
-
-// some useful xml routines
-xmlNodePtr xml_NodeForVec( vec3_t v );
-void xml_SendNode (xmlNodePtr node);
-// print a message in q3map output and send the corresponding select information down the xml stream
-// bError: do we end with an error on this one or do we go ahead?
-void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
-// end q3map with an error message and send a point information in the xml stream
-// note: we might want to add a boolean to use this as a warning or an error thing..
-void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
-void xml_Point (char *msg, vec3_t pt);
-
-extern qboolean bNetworkBroadcast;
-void Broadcast_Setup( const char *dest );
-void Broadcast_Shutdown();
-
-#define SYS_VRB 0 // verbose support (on/off)
-#define SYS_STD 1 // standard print level
-#define SYS_WRN 2 // warnings
-#define SYS_ERR 3 // error
-#define SYS_NOXML 4 // don't send that down the XML stream
-
-extern	qboolean verbose;
-void Sys_Printf (const char *text, ...);
-void Sys_FPrintf (int flag, const char *text, ...);
-
-#ifdef _DEBUG
-#define DBG_XML 1
-#endif
-
-#ifdef DBG_XML
-void DumpXML();
-#endif
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __INOUT__
+#define __INOUT__
+
+// inout is the only stuff relying on xml, include the headers there
+#include "libxml/tree.h"
+
+// some useful xml routines
+xmlNodePtr xml_NodeForVec( vec3_t v );
+void xml_SendNode (xmlNodePtr node);
+// print a message in q3map output and send the corresponding select information down the xml stream
+// bError: do we end with an error on this one or do we go ahead?
+void xml_Select (char *msg, int entitynum, int brushnum, qboolean bError);
+// end q3map with an error message and send a point information in the xml stream
+// note: we might want to add a boolean to use this as a warning or an error thing..
+void xml_Winding (char *msg, vec3_t p[], int numpoints, qboolean die);
+void xml_Point (char *msg, vec3_t pt);
+
+extern qboolean bNetworkBroadcast;
+void Broadcast_Setup( const char *dest );
+void Broadcast_Shutdown();
+
+#define SYS_VRB 0 // verbose support (on/off)
+#define SYS_STD 1 // standard print level
+#define SYS_WRN 2 // warnings
+#define SYS_ERR 3 // error
+#define SYS_NOXML 4 // don't send that down the XML stream
+
+extern	qboolean verbose;
+void Sys_Printf (const char *text, ...);
+void Sys_FPrintf (int flag, const char *text, ...);
+
+#ifdef _DEBUG
+#define DBG_XML 1
+#endif
+
+#ifdef DBG_XML
+void DumpXML();
+#endif
+
+#endif
diff --git a/tools/quake3/common/l3dslib.c b/tools/quake3/common/l3dslib.c
index eb67e065..0620f9b4 100644
--- a/tools/quake3/common/l3dslib.c
+++ b/tools/quake3/common/l3dslib.c
@@ -1,301 +1,301 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// l3dslib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "trilib.h"
-#include "l3dslib.h"
-
-#define MAIN3DS       0x4D4D
-#define EDIT3DS       0x3D3D  // this is the start of the editor config
-#define EDIT_OBJECT   0x4000
-#define OBJ_TRIMESH   0x4100
-#define TRI_VERTEXL   0x4110
-#define TRI_FACEL1    0x4120
-
-#define MAXVERTS	2000
-#define MAXTRIANGLES	750
-
-typedef struct {
-	int	v[4];
-} tri;
-
-float	fverts[MAXVERTS][3];
-tri		tris[MAXTRIANGLES];
-
-int	bytesread, level, numtris, totaltris;
-int	vertsfound, trisfound;
-
-triangle_t	*ptri;
-
-
-// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
-// start out with a vertex pool and vertex indices for triangles, we have to convert
-// to raw, explicit triangles
-void StoreAliasTriangles (void)
-{
-	int		i, j, k;
-
-	if ((totaltris + numtris) > MAXTRIANGLES)
-		Error ("Error: Too many triangles");
-
-	for (i=0; i<numtris ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			for (k=0 ; k<3 ; k++)
-			{
-				ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
-			}
-		}
-	}
-	
-	totaltris += numtris;
-	numtris = 0;
-	vertsfound = 0;
-	trisfound = 0;
-}
-
-
-int ParseVertexL (FILE *input)
-{
-	int				i, j, startbytesread, numverts;
-	unsigned short	tshort;
-
-	if (vertsfound)
-		Error ("Error: Multiple vertex chunks");
-
-	vertsfound = 1;
-	startbytesread = bytesread;
-
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&tshort, sizeof(tshort), 1, input);
-	bytesread += sizeof(tshort);
-	numverts = (int)tshort;
-
-	if (numverts > MAXVERTS)
-		Error ("Error: Too many vertices");
-
-	for (i=0 ; i<numverts ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread(&fverts[i][j], sizeof(float), 1, input);
-			bytesread += sizeof(float);
-		}
-	}
-
-	if (vertsfound && trisfound)
-		StoreAliasTriangles ();
-
-	return bytesread - startbytesread;
-}
-
-
-int ParseFaceL1 (FILE *input)
-{
-
-	int				i, j, startbytesread;
-	unsigned short	tshort;
-
-	if (trisfound)
-		Error ("Error: Multiple face chunks");
-
-	trisfound = 1;
-	startbytesread = bytesread;
-
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&tshort, sizeof(tshort), 1, input);
-	bytesread += sizeof(tshort);
-	numtris = (int)tshort;
-
-	if (numtris > MAXTRIANGLES)
-		Error ("Error: Too many triangles");
-
-	for (i=0 ; i<numtris ; i++)
-	{
-		for (j=0 ; j<4 ; j++)
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread(&tshort, sizeof(tshort), 1, input);
-			bytesread += sizeof(tshort);
-			tris[i].v[j] = (int)tshort;
-		}
-	}
-
-	if (vertsfound && trisfound)
-		StoreAliasTriangles ();
-
-	return bytesread - startbytesread;
-}
-
-
-int ParseChunk (FILE *input)
-{
-#define BLOCK_SIZE	4096
-	char			temp[BLOCK_SIZE];
-	unsigned short	type;
-	int				i, length, w, t, retval;
-
-	level++;
-	retval = 0;
-
-// chunk type
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread(&type, sizeof(type), 1, input);
-	bytesread += sizeof(type);
-
-// chunk length
-	if (feof(input))
-		Error ("Error: unexpected end of file");
-
-	fread (&length, sizeof(length), 1, input);
-	bytesread += sizeof(length);
-	w = length - 6;
-
-// process chunk if we care about it, otherwise skip it
-	switch (type)
-	{
-	case TRI_VERTEXL:
-		w -= ParseVertexL (input);
-		goto ParseSubchunk;
-
-	case TRI_FACEL1:
-		w -= ParseFaceL1 (input);
-		goto ParseSubchunk;
-
-	case EDIT_OBJECT:
-	// read the name
-		i = 0;
-
-		do
-		{
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread (&temp[i], 1, 1, input);
-			i++;
-			w--;
-			bytesread++;
-		} while (temp[i-1]);
-
-	case MAIN3DS:
-	case OBJ_TRIMESH:
-	case EDIT3DS:
-	// parse through subchunks
-ParseSubchunk:
-		while (w > 0)
-		{
-			w -= ParseChunk (input);
-		}
-
-		retval = length;
-		goto Done;
-
-	default:
-	// skip other chunks
-		while (w > 0)
-		{
-			t = w;
-
-			if (t > BLOCK_SIZE)
-				t = BLOCK_SIZE;
-
-			if (feof(input))
-				Error ("Error: unexpected end of file");
-
-			fread (&temp, t, 1, input);
-			bytesread += t;
-
-			w -= t;
-		}
-
-		retval = length;
-		goto Done;
-	}
-
-Done:
-	level--;
-	return retval;
-}
-
-
-void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
-{
-	FILE        *input;
-	short int	tshort;
-
-	bytesread = 0;
-	level = 0;
-	numtris = 0;
-	totaltris = 0;
-	vertsfound = 0;
-	trisfound = 0;
-
-	if ((input = fopen(filename, "rb")) == 0) {
-		fprintf(stderr,"reader: could not open file '%s'\n", filename);
-		exit(0);
-	}
-
-	fread(&tshort, sizeof(tshort), 1, input);
-
-// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
-// no MAIN3DS
-	if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
-		fprintf(stderr,"File is not a 3DS file.\n");
-		exit(0);
-	}
-
-// back to top of file so we can parse the first chunk descriptor
-	fseek(input, 0, SEEK_SET);
-
-	ptri = safe_malloc (MAXTRIANGLES * sizeof(triangle_t));
-
-	*pptri = ptri;
-
-// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
-// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
-	ParseChunk (input);
-
-	if (vertsfound || trisfound)
-		Error ("Incomplete triangle set");
-
-	*numtriangles = totaltris;
-
-	fclose (input);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// l3dslib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "trilib.h"
+#include "l3dslib.h"
+
+#define MAIN3DS       0x4D4D
+#define EDIT3DS       0x3D3D  // this is the start of the editor config
+#define EDIT_OBJECT   0x4000
+#define OBJ_TRIMESH   0x4100
+#define TRI_VERTEXL   0x4110
+#define TRI_FACEL1    0x4120
+
+#define MAXVERTS	2000
+#define MAXTRIANGLES	750
+
+typedef struct {
+	int	v[4];
+} tri;
+
+float	fverts[MAXVERTS][3];
+tri		tris[MAXTRIANGLES];
+
+int	bytesread, level, numtris, totaltris;
+int	vertsfound, trisfound;
+
+triangle_t	*ptri;
+
+
+// Alias stores triangles as 3 explicit vertices in .tri files, so even though we
+// start out with a vertex pool and vertex indices for triangles, we have to convert
+// to raw, explicit triangles
+void StoreAliasTriangles (void)
+{
+	int		i, j, k;
+
+	if ((totaltris + numtris) > MAXTRIANGLES)
+		Error ("Error: Too many triangles");
+
+	for (i=0; i<numtris ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			for (k=0 ; k<3 ; k++)
+			{
+				ptri[i+totaltris].verts[j][k] = fverts[tris[i].v[j]][k];
+			}
+		}
+	}
+	
+	totaltris += numtris;
+	numtris = 0;
+	vertsfound = 0;
+	trisfound = 0;
+}
+
+
+int ParseVertexL (FILE *input)
+{
+	int				i, j, startbytesread, numverts;
+	unsigned short	tshort;
+
+	if (vertsfound)
+		Error ("Error: Multiple vertex chunks");
+
+	vertsfound = 1;
+	startbytesread = bytesread;
+
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&tshort, sizeof(tshort), 1, input);
+	bytesread += sizeof(tshort);
+	numverts = (int)tshort;
+
+	if (numverts > MAXVERTS)
+		Error ("Error: Too many vertices");
+
+	for (i=0 ; i<numverts ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread(&fverts[i][j], sizeof(float), 1, input);
+			bytesread += sizeof(float);
+		}
+	}
+
+	if (vertsfound && trisfound)
+		StoreAliasTriangles ();
+
+	return bytesread - startbytesread;
+}
+
+
+int ParseFaceL1 (FILE *input)
+{
+
+	int				i, j, startbytesread;
+	unsigned short	tshort;
+
+	if (trisfound)
+		Error ("Error: Multiple face chunks");
+
+	trisfound = 1;
+	startbytesread = bytesread;
+
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&tshort, sizeof(tshort), 1, input);
+	bytesread += sizeof(tshort);
+	numtris = (int)tshort;
+
+	if (numtris > MAXTRIANGLES)
+		Error ("Error: Too many triangles");
+
+	for (i=0 ; i<numtris ; i++)
+	{
+		for (j=0 ; j<4 ; j++)
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread(&tshort, sizeof(tshort), 1, input);
+			bytesread += sizeof(tshort);
+			tris[i].v[j] = (int)tshort;
+		}
+	}
+
+	if (vertsfound && trisfound)
+		StoreAliasTriangles ();
+
+	return bytesread - startbytesread;
+}
+
+
+int ParseChunk (FILE *input)
+{
+#define BLOCK_SIZE	4096
+	char			temp[BLOCK_SIZE];
+	unsigned short	type;
+	int				i, length, w, t, retval;
+
+	level++;
+	retval = 0;
+
+// chunk type
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread(&type, sizeof(type), 1, input);
+	bytesread += sizeof(type);
+
+// chunk length
+	if (feof(input))
+		Error ("Error: unexpected end of file");
+
+	fread (&length, sizeof(length), 1, input);
+	bytesread += sizeof(length);
+	w = length - 6;
+
+// process chunk if we care about it, otherwise skip it
+	switch (type)
+	{
+	case TRI_VERTEXL:
+		w -= ParseVertexL (input);
+		goto ParseSubchunk;
+
+	case TRI_FACEL1:
+		w -= ParseFaceL1 (input);
+		goto ParseSubchunk;
+
+	case EDIT_OBJECT:
+	// read the name
+		i = 0;
+
+		do
+		{
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread (&temp[i], 1, 1, input);
+			i++;
+			w--;
+			bytesread++;
+		} while (temp[i-1]);
+
+	case MAIN3DS:
+	case OBJ_TRIMESH:
+	case EDIT3DS:
+	// parse through subchunks
+ParseSubchunk:
+		while (w > 0)
+		{
+			w -= ParseChunk (input);
+		}
+
+		retval = length;
+		goto Done;
+
+	default:
+	// skip other chunks
+		while (w > 0)
+		{
+			t = w;
+
+			if (t > BLOCK_SIZE)
+				t = BLOCK_SIZE;
+
+			if (feof(input))
+				Error ("Error: unexpected end of file");
+
+			fread (&temp, t, 1, input);
+			bytesread += t;
+
+			w -= t;
+		}
+
+		retval = length;
+		goto Done;
+	}
+
+Done:
+	level--;
+	return retval;
+}
+
+
+void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles)
+{
+	FILE        *input;
+	short int	tshort;
+
+	bytesread = 0;
+	level = 0;
+	numtris = 0;
+	totaltris = 0;
+	vertsfound = 0;
+	trisfound = 0;
+
+	if ((input = fopen(filename, "rb")) == 0) {
+		fprintf(stderr,"reader: could not open file '%s'\n", filename);
+		exit(0);
+	}
+
+	fread(&tshort, sizeof(tshort), 1, input);
+
+// should only be MAIN3DS, but some files seem to start with EDIT3DS, with
+// no MAIN3DS
+	if ((tshort != MAIN3DS) && (tshort != EDIT3DS)) {
+		fprintf(stderr,"File is not a 3DS file.\n");
+		exit(0);
+	}
+
+// back to top of file so we can parse the first chunk descriptor
+	fseek(input, 0, SEEK_SET);
+
+	ptri = safe_malloc (MAXTRIANGLES * sizeof(triangle_t));
+
+	*pptri = ptri;
+
+// parse through looking for the relevant chunk tree (MAIN3DS | EDIT3DS | EDIT_OBJECT |
+// OBJ_TRIMESH | {TRI_VERTEXL, TRI_FACEL1}) and skipping other chunks
+	ParseChunk (input);
+
+	if (vertsfound || trisfound)
+		Error ("Incomplete triangle set");
+
+	*numtriangles = totaltris;
+
+	fclose (input);
+}
+
diff --git a/tools/quake3/common/l3dslib.h b/tools/quake3/common/l3dslib.h
index a22d9c87..ae835963 100644
--- a/tools/quake3/common/l3dslib.h
+++ b/tools/quake3/common/l3dslib.h
@@ -1,26 +1,26 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// l3dslib.h: header file for loading triangles from a 3DS triangle file
-//
-void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// l3dslib.h: header file for loading triangles from a 3DS triangle file
+//
+void Load3DSTriangleList (char *filename, triangle_t **pptri, int *numtriangles);
+
diff --git a/tools/quake3/common/mutex.c b/tools/quake3/common/mutex.c
index bd699bf9..f7be7f5f 100644
--- a/tools/quake3/common/mutex.c
+++ b/tools/quake3/common/mutex.c
@@ -1,197 +1,197 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "cmdlib.h"
-#include "qthreads.h"
-#include "mutex.h"
-
-/*
-===================================================================
-
-WIN32
-
-===================================================================
-*/
-#ifdef _WIN32
-
-#define	USED
-
-#include <windows.h>
-
-void MutexLock (mutex_t *m)
-{
-	CRITICAL_SECTION *crit;
-
-	if (!m)
-		return;
-	crit = (CRITICAL_SECTION *) m;
-	EnterCriticalSection (crit);
-}
-
-void MutexUnlock (mutex_t *m)
-{
-	CRITICAL_SECTION *crit;
-
-	if (!m)
-		return;
-	crit = (CRITICAL_SECTION *) m;
-	LeaveCriticalSection (crit);
-}
-
-mutex_t *MutexAlloc(void)
-{
-	CRITICAL_SECTION *crit;
-
-	if (numthreads == 1)
-		return NULL;
-	crit = (CRITICAL_SECTION *) safe_malloc(sizeof(CRITICAL_SECTION));
-	InitializeCriticalSection (crit);
-	return (void *) crit;
-}
-
-#endif
-
-/*
-===================================================================
-
-OSF1
-
-===================================================================
-*/
-
-#ifdef __osf__
-#define	USED
-
-#include <pthread.h>
-
-void MutexLock (mutex_t *m)
-{
-	pthread_mutex_t	*my_mutex;
-
-	if (!m)
-		return;
-	my_mutex = (pthread_mutex_t *) m;
-	pthread_mutex_lock (my_mutex);
-}
-
-void MutexUnlock (mutex_t *m)
-{
-	pthread_mutex_t	*my_mutex;
-
-	if (!m)
-		return;
-	my_mutex = (pthread_mutex_t *) m;
-	pthread_mutex_unlock (my_mutex);
-}
-
-mutex_t *MutexAlloc(void)
-{
-	pthread_mutex_t	*my_mutex;
-	pthread_mutexattr_t	mattrib;
-
-	if (numthreads == 1)
-		return NULL;
-	my_mutex = safe_malloc (sizeof(*my_mutex));
-	if (pthread_mutexattr_create (&mattrib) == -1)
-		Error ("pthread_mutex_attr_create failed");
-	if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
-		Error ("pthread_mutexattr_setkind_np failed");
-	if (pthread_mutex_init (my_mutex, mattrib) == -1)
-		Error ("pthread_mutex_init failed");
-	return (void *) my_mutex;
-}
-
-#endif
-
-/*
-===================================================================
-
-IRIX
-
-===================================================================
-*/
-
-#ifdef _MIPS_ISA 
-#define	USED
-
-#include <task.h>
-#include <abi_mutex.h>
-#include <sys/types.h>
-#include <sys/prctl.h>
-
-void MutexLock (mutex_t *m)
-{
-	abilock_t *lck;
-
-	if (!m)
-		return;
-	lck = (abilock_t *) m;
-	spin_lock (lck);
-}
-
-void MutexUnlock (mutex_t *m)
-{
-	abilock_t *lck;
-
-	if (!m)
-		return;
-	lck = (abilock_t *) m;
-	release_lock (lck);
-}
-
-mutex_t *MutexAlloc(void)
-{
-	abilock_t *lck;
-
-	if (numthreads == 1)
-		return NULL;
-	lck = (abilock_t *) safe_malloc(sizeof(abilock_t));
-	init_lock (lck);
-	return (void *) lck;
-}
-
-#endif
-
-/*
-=======================================================================
-
-  SINGLE THREAD
-
-=======================================================================
-*/
-
-#ifndef USED
-
-void MutexLock (mutex_t *m)
-{
-}
-
-void MutexUnlock (mutex_t *m)
-{
-}
-
-mutex_t *MutexAlloc(void)
-{
-	return NULL;
-}
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "cmdlib.h"
+#include "qthreads.h"
+#include "mutex.h"
+
+/*
+===================================================================
+
+WIN32
+
+===================================================================
+*/
+#ifdef _WIN32
+
+#define	USED
+
+#include <windows.h>
+
+void MutexLock (mutex_t *m)
+{
+	CRITICAL_SECTION *crit;
+
+	if (!m)
+		return;
+	crit = (CRITICAL_SECTION *) m;
+	EnterCriticalSection (crit);
+}
+
+void MutexUnlock (mutex_t *m)
+{
+	CRITICAL_SECTION *crit;
+
+	if (!m)
+		return;
+	crit = (CRITICAL_SECTION *) m;
+	LeaveCriticalSection (crit);
+}
+
+mutex_t *MutexAlloc(void)
+{
+	CRITICAL_SECTION *crit;
+
+	if (numthreads == 1)
+		return NULL;
+	crit = (CRITICAL_SECTION *) safe_malloc(sizeof(CRITICAL_SECTION));
+	InitializeCriticalSection (crit);
+	return (void *) crit;
+}
+
+#endif
+
+/*
+===================================================================
+
+OSF1
+
+===================================================================
+*/
+
+#ifdef __osf__
+#define	USED
+
+#include <pthread.h>
+
+void MutexLock (mutex_t *m)
+{
+	pthread_mutex_t	*my_mutex;
+
+	if (!m)
+		return;
+	my_mutex = (pthread_mutex_t *) m;
+	pthread_mutex_lock (my_mutex);
+}
+
+void MutexUnlock (mutex_t *m)
+{
+	pthread_mutex_t	*my_mutex;
+
+	if (!m)
+		return;
+	my_mutex = (pthread_mutex_t *) m;
+	pthread_mutex_unlock (my_mutex);
+}
+
+mutex_t *MutexAlloc(void)
+{
+	pthread_mutex_t	*my_mutex;
+	pthread_mutexattr_t	mattrib;
+
+	if (numthreads == 1)
+		return NULL;
+	my_mutex = safe_malloc (sizeof(*my_mutex));
+	if (pthread_mutexattr_create (&mattrib) == -1)
+		Error ("pthread_mutex_attr_create failed");
+	if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
+		Error ("pthread_mutexattr_setkind_np failed");
+	if (pthread_mutex_init (my_mutex, mattrib) == -1)
+		Error ("pthread_mutex_init failed");
+	return (void *) my_mutex;
+}
+
+#endif
+
+/*
+===================================================================
+
+IRIX
+
+===================================================================
+*/
+
+#ifdef _MIPS_ISA 
+#define	USED
+
+#include <task.h>
+#include <abi_mutex.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+
+void MutexLock (mutex_t *m)
+{
+	abilock_t *lck;
+
+	if (!m)
+		return;
+	lck = (abilock_t *) m;
+	spin_lock (lck);
+}
+
+void MutexUnlock (mutex_t *m)
+{
+	abilock_t *lck;
+
+	if (!m)
+		return;
+	lck = (abilock_t *) m;
+	release_lock (lck);
+}
+
+mutex_t *MutexAlloc(void)
+{
+	abilock_t *lck;
+
+	if (numthreads == 1)
+		return NULL;
+	lck = (abilock_t *) safe_malloc(sizeof(abilock_t));
+	init_lock (lck);
+	return (void *) lck;
+}
+
+#endif
+
+/*
+=======================================================================
+
+  SINGLE THREAD
+
+=======================================================================
+*/
+
+#ifndef USED
+
+void MutexLock (mutex_t *m)
+{
+}
+
+void MutexUnlock (mutex_t *m)
+{
+}
+
+mutex_t *MutexAlloc(void)
+{
+	return NULL;
+}
+
+#endif
diff --git a/tools/quake3/common/mutex.h b/tools/quake3/common/mutex.h
index ce6dab00..1bd34dc6 100644
--- a/tools/quake3/common/mutex.h
+++ b/tools/quake3/common/mutex.h
@@ -1,28 +1,28 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-
-typedef void *mutex_t;
-
-void MutexLock (mutex_t *m);
-void MutexUnlock (mutex_t *m);
-mutex_t *MutexAlloc(void);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+
+typedef void *mutex_t;
+
+void MutexLock (mutex_t *m);
+void MutexUnlock (mutex_t *m);
+mutex_t *MutexAlloc(void);
diff --git a/tools/quake3/common/polylib.c b/tools/quake3/common/polylib.c
index 9f5a1d49..187b1e70 100644
--- a/tools/quake3/common/polylib.c
+++ b/tools/quake3/common/polylib.c
@@ -1,745 +1,745 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include "polylib.h"
-#include "qfiles.h"
-
-
-extern int numthreads;
-
-// counters are only bumped when running single threaded,
-// because they are an awefull coherence problem
-int	c_active_windings;
-int	c_peak_windings;
-int	c_winding_allocs;
-int	c_winding_points;
-
-#define	BOGUS_RANGE	WORLD_SIZE
-
-void pw(winding_t *w)
-{
-	int		i;
-	for (i=0 ; i<w->numpoints ; i++)
-		Sys_Printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
-}
-
-
-/*
-=============
-AllocWinding
-=============
-*/
-winding_t	*AllocWinding (int points)
-{
-	winding_t	*w;
-	int			s;
-
-  if (points >= MAX_POINTS_ON_WINDING)
-    Error ("AllocWinding failed: MAX_POINTS_ON_WINDING exceeded");
-
-	if (numthreads == 1)
-	{
-		c_winding_allocs++;
-		c_winding_points += points;
-		c_active_windings++;
-		if (c_active_windings > c_peak_windings)
-			c_peak_windings = c_active_windings;
-	}
-	s = sizeof(vec_t)*3*points + sizeof(int);
-	w = safe_malloc (s);
-	memset (w, 0, s); 
-	return w;
-}
-
-void FreeWinding (winding_t *w)
-{
-	if (*(unsigned *)w == 0xdeaddead)
-		Error ("FreeWinding: freed a freed winding");
-	*(unsigned *)w = 0xdeaddead;
-
-	if (numthreads == 1)
-		c_active_windings--;
-	free (w);
-}
-
-/*
-============
-RemoveColinearPoints
-============
-*/
-int	c_removed;
-
-void	RemoveColinearPoints (winding_t *w)
-{
-	int		i, j, k;
-	vec3_t	v1, v2;
-	int		nump;
-	vec3_t	p[MAX_POINTS_ON_WINDING];
-
-	nump = 0;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		j = (i+1)%w->numpoints;
-		k = (i+w->numpoints-1)%w->numpoints;
-		VectorSubtract (w->p[j], w->p[i], v1);
-		VectorSubtract (w->p[i], w->p[k], v2);
-		VectorNormalize(v1,v1);
-		VectorNormalize(v2,v2);
-		if (DotProduct(v1, v2) < 0.999)
-		{
-			VectorCopy (w->p[i], p[nump]);
-			nump++;
-		}
-	}
-
-	if (nump == w->numpoints)
-		return;
-
-	if (numthreads == 1)
-		c_removed += w->numpoints - nump;
-	w->numpoints = nump;
-	memcpy (w->p, p, nump*sizeof(p[0]));
-}
-
-/*
-============
-WindingPlane
-============
-*/
-void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
-{
-	vec3_t	v1, v2;
-
-	VectorSubtract (w->p[1], w->p[0], v1);
-	VectorSubtract (w->p[2], w->p[0], v2);
-	CrossProduct (v2, v1, normal);
-	VectorNormalize (normal, normal);
-	*dist = DotProduct (w->p[0], normal);
-
-}
-
-/*
-=============
-WindingArea
-=============
-*/
-vec_t	WindingArea (winding_t *w)
-{
-	int		i;
-	vec3_t	d1, d2, cross;
-	vec_t	total;
-
-	total = 0;
-	for (i=2 ; i<w->numpoints ; i++)
-	{
-		VectorSubtract (w->p[i-1], w->p[0], d1);
-		VectorSubtract (w->p[i], w->p[0], d2);
-		CrossProduct (d1, d2, cross);
-		total += 0.5 * VectorLength ( cross );
-	}
-	return total;
-}
-
-void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
-{
-	vec_t	v;
-	int		i,j;
-
-	mins[0] = mins[1] = mins[2] = 99999;
-	maxs[0] = maxs[1] = maxs[2] = -99999;
-
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-		{
-			v = w->p[i][j];
-			if (v < mins[j])
-				mins[j] = v;
-			if (v > maxs[j])
-				maxs[j] = v;
-		}
-	}
-}
-
-/*
-=============
-WindingCenter
-=============
-*/
-void	WindingCenter (winding_t *w, vec3_t center)
-{
-	int		i;
-	float	scale;
-
-	VectorCopy (vec3_origin, center);
-	for (i=0 ; i<w->numpoints ; i++)
-		VectorAdd (w->p[i], center, center);
-
-	scale = 1.0/w->numpoints;
-	VectorScale (center, scale, center);
-}
-
-/*
-=================
-BaseWindingForPlane
-=================
-*/
-winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
-{
-	int		i, x;
-	vec_t	max, v;
-	vec3_t	org, vright, vup;
-	winding_t	*w;
-	
-// find the major axis
-
-	max = -BOGUS_RANGE;
-	x = -1;
-	for (i=0 ; i<3; i++)
-	{
-		v = fabs(normal[i]);
-		if (v > max)
-		{
-			x = i;
-			max = v;
-		}
-	}
-	if (x==-1)
-		Error ("BaseWindingForPlane: no axis found");
-		
-	VectorCopy (vec3_origin, vup);	
-	switch (x)
-	{
-	case 0:
-	case 1:
-		vup[2] = 1;
-		break;		
-	case 2:
-		vup[0] = 1;
-		break;		
-	}
-
-	v = DotProduct (vup, normal);
-	VectorMA (vup, -v, normal, vup);
-	VectorNormalize (vup, vup);
-		
-	VectorScale (normal, dist, org);
-	
-	CrossProduct (vup, normal, vright);
-	
-	VectorScale (vup, MAX_WORLD_COORD, vup);
-	VectorScale (vright, MAX_WORLD_COORD, vright);
-
-  // project a really big	axis aligned box onto the plane
-	w = AllocWinding (4);
-	
-	VectorSubtract (org, vright, w->p[0]);
-	VectorAdd (w->p[0], vup, w->p[0]);
-	
-	VectorAdd (org, vright, w->p[1]);
-	VectorAdd (w->p[1], vup, w->p[1]);
-	
-	VectorAdd (org, vright, w->p[2]);
-	VectorSubtract (w->p[2], vup, w->p[2]);
-	
-	VectorSubtract (org, vright, w->p[3]);
-	VectorSubtract (w->p[3], vup, w->p[3]);
-	
-	w->numpoints = 4;
-	
-	return w;	
-}
-
-/*
-==================
-CopyWinding
-==================
-*/
-winding_t	*CopyWinding (winding_t *w)
-{
-	int			size;
-	winding_t	*c;
-
-	c = AllocWinding (w->numpoints);
-	size = (int)((winding_t *)0)->p[w->numpoints];
-	memcpy (c, w, size);
-	return c;
-}
-
-/*
-==================
-ReverseWinding
-==================
-*/
-winding_t	*ReverseWinding (winding_t *w)
-{
-	int			i;
-	winding_t	*c;
-
-	c = AllocWinding (w->numpoints);
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
-	}
-	c->numpoints = w->numpoints;
-	return c;
-}
-
-
-/*
-=============
-ClipWindingEpsilon
-=============
-*/
-void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
-				vec_t epsilon, winding_t **front, winding_t **back)
-{
-	vec_t	dists[MAX_POINTS_ON_WINDING+4];
-	int		sides[MAX_POINTS_ON_WINDING+4];
-	int		counts[3];
-	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	winding_t	*f, *b;
-	int		maxpts;
-	
-	counts[0] = counts[1] = counts[2] = 0;
-
-// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-  {
-
-		dot = DotProduct (in->p[i], normal);
-		dot -= dist;
-		dists[i] = dot;
-		if (dot > epsilon)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -epsilon)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	*front = *back = NULL;
-
-	if (!counts[0])
-	{
-		*back = CopyWinding (in);
-		return;
-	}
-	if (!counts[1])
-	{
-		*front = CopyWinding (in);
-		return;
-	}
-
-	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
-								// of fp grouping errors
-
-	*front = f = AllocWinding (maxpts);
-	*back = b = AllocWinding (maxpts);
-		
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->p[i];
-		
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-			VectorCopy (p1, b->p[b->numpoints]);
-			b->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-		}
-		if (sides[i] == SIDE_BACK)
-		{
-			VectorCopy (p1, b->p[b->numpoints]);
-			b->numpoints++;
-		}
-
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-	// generate a split point
-		p2 = in->p[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (normal[j] == 1)
-				mid[j] = dist;
-			else if (normal[j] == -1)
-				mid[j] = -dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, f->p[f->numpoints]);
-		f->numpoints++;
-		VectorCopy (mid, b->p[b->numpoints]);
-		b->numpoints++;
-	}
-	
-	if (f->numpoints > maxpts || b->numpoints > maxpts)
-		Error ("ClipWinding: points exceeded estimate");
-	if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
-		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
-}
-
-
-/*
-=============
-ChopWindingInPlace
-=============
-*/
-void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
-{
-	winding_t	*in;
-	vec_t	dists[MAX_POINTS_ON_WINDING+4];
-	int		sides[MAX_POINTS_ON_WINDING+4];
-	int		counts[3];
-	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	winding_t	*f;
-	int		maxpts;
-
-	in = *inout;
-	counts[0] = counts[1] = counts[2] = 0;
-
-// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->p[i], normal);
-		dot -= dist;
-		dists[i] = dot;
-		if (dot > epsilon)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -epsilon)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	if (!counts[0])
-	{
-		FreeWinding (in);
-		*inout = NULL;
-		return;
-	}
-	if (!counts[1])
-		return;		// inout stays the same
-
-	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
-								// of fp grouping errors
-
-	f = AllocWinding (maxpts);
-		
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->p[i];
-		
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, f->p[f->numpoints]);
-			f->numpoints++;
-		}
-
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-	// generate a split point
-		p2 = in->p[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (normal[j] == 1)
-				mid[j] = dist;
-			else if (normal[j] == -1)
-				mid[j] = -dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, f->p[f->numpoints]);
-		f->numpoints++;
-	}
-	
-	if (f->numpoints > maxpts)
-		Error ("ClipWinding: points exceeded estimate");
-	if (f->numpoints > MAX_POINTS_ON_WINDING)
-		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
-
-	FreeWinding (in);
-	*inout = f;
-}
-
-
-/*
-=================
-ChopWinding
-
-Returns the fragment of in that is on the front side
-of the cliping plane.  The original is freed.
-=================
-*/
-winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
-{
-	winding_t	*f, *b;
-
-	ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
-	FreeWinding (in);
-	if (b)
-		FreeWinding (b);
-	return f;
-}
-
-
-/*
-=================
-CheckWinding
-
-=================
-*/
-void CheckWinding (winding_t *w)
-{
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec_t	d, edgedist;
-	vec3_t	dir, edgenormal, facenormal;
-	vec_t	area;
-	vec_t	facedist;
-
-	if (w->numpoints < 3)
-		Error ("CheckWinding: %i points",w->numpoints);
-	
-	area = WindingArea(w);
-	if (area < 1)
-		Error ("CheckWinding: %f area", area);
-
-	WindingPlane (w, facenormal, &facedist);
-	
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		p1 = w->p[i];
-
-		for (j=0 ; j<3 ; j++)
-			if (p1[j] > MAX_WORLD_COORD || p1[j] < MIN_WORLD_COORD)
-				Error ("CheckFace: MAX_WORLD_COORD exceeded: %f",p1[j]);
-
-		j = i+1 == w->numpoints ? 0 : i+1;
-		
-	// check the point is on the face plane
-		d = DotProduct (p1, facenormal) - facedist;
-		if (d < -ON_EPSILON || d > ON_EPSILON)
-			Error ("CheckWinding: point off plane");
-	
-	// check the edge isnt degenerate
-		p2 = w->p[j];
-		VectorSubtract (p2, p1, dir);
-		
-		if (VectorLength (dir) < ON_EPSILON)
-			Error ("CheckWinding: degenerate edge");
-			
-		CrossProduct (facenormal, dir, edgenormal);
-		VectorNormalize (edgenormal, edgenormal);
-		edgedist = DotProduct (p1, edgenormal);
-		edgedist += ON_EPSILON;
-		
-	// all other points must be on front side
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			if (j == i)
-				continue;
-			d = DotProduct (w->p[j], edgenormal);
-			if (d > edgedist)
-				Error ("CheckWinding: non-convex");
-		}
-	}
-}
-
-
-/*
-============
-WindingOnPlaneSide
-============
-*/
-int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
-{
-	qboolean	front, back;
-	int			i;
-	vec_t		d;
-
-	front = qfalse;
-	back = qfalse;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		d = DotProduct (w->p[i], normal) - dist;
-		if (d < -ON_EPSILON)
-		{
-			if (front)
-				return SIDE_CROSS;
-			back = qtrue;
-			continue;
-		}
-		if (d > ON_EPSILON)
-		{
-			if (back)
-				return SIDE_CROSS;
-			front = qtrue;
-			continue;
-		}
-	}
-
-	if (back)
-		return SIDE_BACK;
-	if (front)
-		return SIDE_FRONT;
-	return SIDE_ON;
-}
-
-
-/*
-=================
-AddWindingToConvexHull
-
-Both w and *hull are on the same plane
-=================
-*/
-#define	MAX_HULL_POINTS		128
-void	AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal ) {
-	int			i, j, k;
-	float		*p, *copy;
-	vec3_t		dir;
-	float		d;
-	int			numHullPoints, numNew;
-	vec3_t		hullPoints[MAX_HULL_POINTS];
-	vec3_t		newHullPoints[MAX_HULL_POINTS];
-	vec3_t		hullDirs[MAX_HULL_POINTS];
-	qboolean	hullSide[MAX_HULL_POINTS];
-	qboolean	outside;
-
-	if ( !*hull ) {
-		*hull = CopyWinding( w );
-		return;
-	}
-
-	numHullPoints = (*hull)->numpoints;
-	memcpy( hullPoints, (*hull)->p, numHullPoints * sizeof(vec3_t) );
-
-	for ( i = 0 ; i < w->numpoints ; i++ ) {
-		p = w->p[i];
-
-		// calculate hull side vectors
-		for ( j = 0 ; j < numHullPoints ; j++ ) {
-			k = ( j + 1 ) % numHullPoints;
-
-			VectorSubtract( hullPoints[k], hullPoints[j], dir );
-			VectorNormalize( dir, dir );
-			CrossProduct( normal, dir, hullDirs[j] );
-		}
-
-		outside = qfalse;
-		for ( j = 0 ; j < numHullPoints ; j++ ) {
-			VectorSubtract( p, hullPoints[j], dir );
-			d = DotProduct( dir, hullDirs[j] );
-			if ( d >= ON_EPSILON ) {
-				outside = qtrue;
-			}
-			if ( d >= -ON_EPSILON ) {
-				hullSide[j] = qtrue;
-			} else {
-				hullSide[j] = qfalse;
-			}
-		}
-
-		// if the point is effectively inside, do nothing
-		if ( !outside ) {
-			continue;
-		}
-
-		// find the back side to front side transition
-		for ( j = 0 ; j < numHullPoints ; j++ ) {
-			if ( !hullSide[ j % numHullPoints ] && hullSide[ (j + 1) % numHullPoints ] ) {
-				break;
-			}
-		}
-		if ( j == numHullPoints ) {
-			continue;
-		}
-
-		// insert the point here
-		VectorCopy( p, newHullPoints[0] );
-		numNew = 1;
-
-		// copy over all points that aren't double fronts
-		j = (j+1)%numHullPoints;
-		for ( k = 0 ; k < numHullPoints ; k++ ) {
-			if ( hullSide[ (j+k) % numHullPoints ] && hullSide[ (j+k+1) % numHullPoints ] ) {
-				continue;
-			}
-			copy = hullPoints[ (j+k+1) % numHullPoints ];
-			VectorCopy( copy, newHullPoints[numNew] );
-			numNew++;
-		}
-
-		numHullPoints = numNew;
-		memcpy( hullPoints, newHullPoints, numHullPoints * sizeof(vec3_t) );
-	}
-
-	FreeWinding( *hull );
-	w = AllocWinding( numHullPoints );
-	w->numpoints = numHullPoints;
-	*hull = w;
-	memcpy( w->p, hullPoints, numHullPoints * sizeof(vec3_t) );
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include "polylib.h"
+#include "qfiles.h"
+
+
+extern int numthreads;
+
+// counters are only bumped when running single threaded,
+// because they are an awefull coherence problem
+int	c_active_windings;
+int	c_peak_windings;
+int	c_winding_allocs;
+int	c_winding_points;
+
+#define	BOGUS_RANGE	WORLD_SIZE
+
+void pw(winding_t *w)
+{
+	int		i;
+	for (i=0 ; i<w->numpoints ; i++)
+		Sys_Printf ("(%5.1f, %5.1f, %5.1f)\n",w->p[i][0], w->p[i][1],w->p[i][2]);
+}
+
+
+/*
+=============
+AllocWinding
+=============
+*/
+winding_t	*AllocWinding (int points)
+{
+	winding_t	*w;
+	int			s;
+
+  if (points >= MAX_POINTS_ON_WINDING)
+    Error ("AllocWinding failed: MAX_POINTS_ON_WINDING exceeded");
+
+	if (numthreads == 1)
+	{
+		c_winding_allocs++;
+		c_winding_points += points;
+		c_active_windings++;
+		if (c_active_windings > c_peak_windings)
+			c_peak_windings = c_active_windings;
+	}
+	s = sizeof(vec_t)*3*points + sizeof(int);
+	w = safe_malloc (s);
+	memset (w, 0, s); 
+	return w;
+}
+
+void FreeWinding (winding_t *w)
+{
+	if (*(unsigned *)w == 0xdeaddead)
+		Error ("FreeWinding: freed a freed winding");
+	*(unsigned *)w = 0xdeaddead;
+
+	if (numthreads == 1)
+		c_active_windings--;
+	free (w);
+}
+
+/*
+============
+RemoveColinearPoints
+============
+*/
+int	c_removed;
+
+void	RemoveColinearPoints (winding_t *w)
+{
+	int		i, j, k;
+	vec3_t	v1, v2;
+	int		nump;
+	vec3_t	p[MAX_POINTS_ON_WINDING];
+
+	nump = 0;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		j = (i+1)%w->numpoints;
+		k = (i+w->numpoints-1)%w->numpoints;
+		VectorSubtract (w->p[j], w->p[i], v1);
+		VectorSubtract (w->p[i], w->p[k], v2);
+		VectorNormalize(v1,v1);
+		VectorNormalize(v2,v2);
+		if (DotProduct(v1, v2) < 0.999)
+		{
+			VectorCopy (w->p[i], p[nump]);
+			nump++;
+		}
+	}
+
+	if (nump == w->numpoints)
+		return;
+
+	if (numthreads == 1)
+		c_removed += w->numpoints - nump;
+	w->numpoints = nump;
+	memcpy (w->p, p, nump*sizeof(p[0]));
+}
+
+/*
+============
+WindingPlane
+============
+*/
+void WindingPlane (winding_t *w, vec3_t normal, vec_t *dist)
+{
+	vec3_t	v1, v2;
+
+	VectorSubtract (w->p[1], w->p[0], v1);
+	VectorSubtract (w->p[2], w->p[0], v2);
+	CrossProduct (v2, v1, normal);
+	VectorNormalize (normal, normal);
+	*dist = DotProduct (w->p[0], normal);
+
+}
+
+/*
+=============
+WindingArea
+=============
+*/
+vec_t	WindingArea (winding_t *w)
+{
+	int		i;
+	vec3_t	d1, d2, cross;
+	vec_t	total;
+
+	total = 0;
+	for (i=2 ; i<w->numpoints ; i++)
+	{
+		VectorSubtract (w->p[i-1], w->p[0], d1);
+		VectorSubtract (w->p[i], w->p[0], d2);
+		CrossProduct (d1, d2, cross);
+		total += 0.5 * VectorLength ( cross );
+	}
+	return total;
+}
+
+void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs)
+{
+	vec_t	v;
+	int		i,j;
+
+	mins[0] = mins[1] = mins[2] = 99999;
+	maxs[0] = maxs[1] = maxs[2] = -99999;
+
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+		{
+			v = w->p[i][j];
+			if (v < mins[j])
+				mins[j] = v;
+			if (v > maxs[j])
+				maxs[j] = v;
+		}
+	}
+}
+
+/*
+=============
+WindingCenter
+=============
+*/
+void	WindingCenter (winding_t *w, vec3_t center)
+{
+	int		i;
+	float	scale;
+
+	VectorCopy (vec3_origin, center);
+	for (i=0 ; i<w->numpoints ; i++)
+		VectorAdd (w->p[i], center, center);
+
+	scale = 1.0/w->numpoints;
+	VectorScale (center, scale, center);
+}
+
+/*
+=================
+BaseWindingForPlane
+=================
+*/
+winding_t *BaseWindingForPlane (vec3_t normal, vec_t dist)
+{
+	int		i, x;
+	vec_t	max, v;
+	vec3_t	org, vright, vup;
+	winding_t	*w;
+	
+// find the major axis
+
+	max = -BOGUS_RANGE;
+	x = -1;
+	for (i=0 ; i<3; i++)
+	{
+		v = fabs(normal[i]);
+		if (v > max)
+		{
+			x = i;
+			max = v;
+		}
+	}
+	if (x==-1)
+		Error ("BaseWindingForPlane: no axis found");
+		
+	VectorCopy (vec3_origin, vup);	
+	switch (x)
+	{
+	case 0:
+	case 1:
+		vup[2] = 1;
+		break;		
+	case 2:
+		vup[0] = 1;
+		break;		
+	}
+
+	v = DotProduct (vup, normal);
+	VectorMA (vup, -v, normal, vup);
+	VectorNormalize (vup, vup);
+		
+	VectorScale (normal, dist, org);
+	
+	CrossProduct (vup, normal, vright);
+	
+	VectorScale (vup, MAX_WORLD_COORD, vup);
+	VectorScale (vright, MAX_WORLD_COORD, vright);
+
+  // project a really big	axis aligned box onto the plane
+	w = AllocWinding (4);
+	
+	VectorSubtract (org, vright, w->p[0]);
+	VectorAdd (w->p[0], vup, w->p[0]);
+	
+	VectorAdd (org, vright, w->p[1]);
+	VectorAdd (w->p[1], vup, w->p[1]);
+	
+	VectorAdd (org, vright, w->p[2]);
+	VectorSubtract (w->p[2], vup, w->p[2]);
+	
+	VectorSubtract (org, vright, w->p[3]);
+	VectorSubtract (w->p[3], vup, w->p[3]);
+	
+	w->numpoints = 4;
+	
+	return w;	
+}
+
+/*
+==================
+CopyWinding
+==================
+*/
+winding_t	*CopyWinding (winding_t *w)
+{
+	int			size;
+	winding_t	*c;
+
+	c = AllocWinding (w->numpoints);
+	size = (int)((winding_t *)0)->p[w->numpoints];
+	memcpy (c, w, size);
+	return c;
+}
+
+/*
+==================
+ReverseWinding
+==================
+*/
+winding_t	*ReverseWinding (winding_t *w)
+{
+	int			i;
+	winding_t	*c;
+
+	c = AllocWinding (w->numpoints);
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		VectorCopy (w->p[w->numpoints-1-i], c->p[i]);
+	}
+	c->numpoints = w->numpoints;
+	return c;
+}
+
+
+/*
+=============
+ClipWindingEpsilon
+=============
+*/
+void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
+				vec_t epsilon, winding_t **front, winding_t **back)
+{
+	vec_t	dists[MAX_POINTS_ON_WINDING+4];
+	int		sides[MAX_POINTS_ON_WINDING+4];
+	int		counts[3];
+	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	winding_t	*f, *b;
+	int		maxpts;
+	
+	counts[0] = counts[1] = counts[2] = 0;
+
+// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+  {
+
+		dot = DotProduct (in->p[i], normal);
+		dot -= dist;
+		dists[i] = dot;
+		if (dot > epsilon)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -epsilon)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	*front = *back = NULL;
+
+	if (!counts[0])
+	{
+		*back = CopyWinding (in);
+		return;
+	}
+	if (!counts[1])
+	{
+		*front = CopyWinding (in);
+		return;
+	}
+
+	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
+								// of fp grouping errors
+
+	*front = f = AllocWinding (maxpts);
+	*back = b = AllocWinding (maxpts);
+		
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->p[i];
+		
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+			VectorCopy (p1, b->p[b->numpoints]);
+			b->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+		}
+		if (sides[i] == SIDE_BACK)
+		{
+			VectorCopy (p1, b->p[b->numpoints]);
+			b->numpoints++;
+		}
+
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+	// generate a split point
+		p2 = in->p[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (normal[j] == 1)
+				mid[j] = dist;
+			else if (normal[j] == -1)
+				mid[j] = -dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, f->p[f->numpoints]);
+		f->numpoints++;
+		VectorCopy (mid, b->p[b->numpoints]);
+		b->numpoints++;
+	}
+	
+	if (f->numpoints > maxpts || b->numpoints > maxpts)
+		Error ("ClipWinding: points exceeded estimate");
+	if (f->numpoints > MAX_POINTS_ON_WINDING || b->numpoints > MAX_POINTS_ON_WINDING)
+		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
+}
+
+
+/*
+=============
+ChopWindingInPlace
+=============
+*/
+void ChopWindingInPlace (winding_t **inout, vec3_t normal, vec_t dist, vec_t epsilon)
+{
+	winding_t	*in;
+	vec_t	dists[MAX_POINTS_ON_WINDING+4];
+	int		sides[MAX_POINTS_ON_WINDING+4];
+	int		counts[3];
+	static	vec_t	dot;		// VC 4.2 optimizer bug if not static
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	winding_t	*f;
+	int		maxpts;
+
+	in = *inout;
+	counts[0] = counts[1] = counts[2] = 0;
+
+// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->p[i], normal);
+		dot -= dist;
+		dists[i] = dot;
+		if (dot > epsilon)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -epsilon)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	if (!counts[0])
+	{
+		FreeWinding (in);
+		*inout = NULL;
+		return;
+	}
+	if (!counts[1])
+		return;		// inout stays the same
+
+	maxpts = in->numpoints+4;	// cant use counts[0]+2 because
+								// of fp grouping errors
+
+	f = AllocWinding (maxpts);
+		
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->p[i];
+		
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, f->p[f->numpoints]);
+			f->numpoints++;
+		}
+
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+	// generate a split point
+		p2 = in->p[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (normal[j] == 1)
+				mid[j] = dist;
+			else if (normal[j] == -1)
+				mid[j] = -dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, f->p[f->numpoints]);
+		f->numpoints++;
+	}
+	
+	if (f->numpoints > maxpts)
+		Error ("ClipWinding: points exceeded estimate");
+	if (f->numpoints > MAX_POINTS_ON_WINDING)
+		Error ("ClipWinding: MAX_POINTS_ON_WINDING");
+
+	FreeWinding (in);
+	*inout = f;
+}
+
+
+/*
+=================
+ChopWinding
+
+Returns the fragment of in that is on the front side
+of the cliping plane.  The original is freed.
+=================
+*/
+winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist)
+{
+	winding_t	*f, *b;
+
+	ClipWindingEpsilon (in, normal, dist, ON_EPSILON, &f, &b);
+	FreeWinding (in);
+	if (b)
+		FreeWinding (b);
+	return f;
+}
+
+
+/*
+=================
+CheckWinding
+
+=================
+*/
+void CheckWinding (winding_t *w)
+{
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec_t	d, edgedist;
+	vec3_t	dir, edgenormal, facenormal;
+	vec_t	area;
+	vec_t	facedist;
+
+	if (w->numpoints < 3)
+		Error ("CheckWinding: %i points",w->numpoints);
+	
+	area = WindingArea(w);
+	if (area < 1)
+		Error ("CheckWinding: %f area", area);
+
+	WindingPlane (w, facenormal, &facedist);
+	
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		p1 = w->p[i];
+
+		for (j=0 ; j<3 ; j++)
+			if (p1[j] > MAX_WORLD_COORD || p1[j] < MIN_WORLD_COORD)
+				Error ("CheckFace: MAX_WORLD_COORD exceeded: %f",p1[j]);
+
+		j = i+1 == w->numpoints ? 0 : i+1;
+		
+	// check the point is on the face plane
+		d = DotProduct (p1, facenormal) - facedist;
+		if (d < -ON_EPSILON || d > ON_EPSILON)
+			Error ("CheckWinding: point off plane");
+	
+	// check the edge isnt degenerate
+		p2 = w->p[j];
+		VectorSubtract (p2, p1, dir);
+		
+		if (VectorLength (dir) < ON_EPSILON)
+			Error ("CheckWinding: degenerate edge");
+			
+		CrossProduct (facenormal, dir, edgenormal);
+		VectorNormalize (edgenormal, edgenormal);
+		edgedist = DotProduct (p1, edgenormal);
+		edgedist += ON_EPSILON;
+		
+	// all other points must be on front side
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			if (j == i)
+				continue;
+			d = DotProduct (w->p[j], edgenormal);
+			if (d > edgedist)
+				Error ("CheckWinding: non-convex");
+		}
+	}
+}
+
+
+/*
+============
+WindingOnPlaneSide
+============
+*/
+int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist)
+{
+	qboolean	front, back;
+	int			i;
+	vec_t		d;
+
+	front = qfalse;
+	back = qfalse;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		d = DotProduct (w->p[i], normal) - dist;
+		if (d < -ON_EPSILON)
+		{
+			if (front)
+				return SIDE_CROSS;
+			back = qtrue;
+			continue;
+		}
+		if (d > ON_EPSILON)
+		{
+			if (back)
+				return SIDE_CROSS;
+			front = qtrue;
+			continue;
+		}
+	}
+
+	if (back)
+		return SIDE_BACK;
+	if (front)
+		return SIDE_FRONT;
+	return SIDE_ON;
+}
+
+
+/*
+=================
+AddWindingToConvexHull
+
+Both w and *hull are on the same plane
+=================
+*/
+#define	MAX_HULL_POINTS		128
+void	AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal ) {
+	int			i, j, k;
+	float		*p, *copy;
+	vec3_t		dir;
+	float		d;
+	int			numHullPoints, numNew;
+	vec3_t		hullPoints[MAX_HULL_POINTS];
+	vec3_t		newHullPoints[MAX_HULL_POINTS];
+	vec3_t		hullDirs[MAX_HULL_POINTS];
+	qboolean	hullSide[MAX_HULL_POINTS];
+	qboolean	outside;
+
+	if ( !*hull ) {
+		*hull = CopyWinding( w );
+		return;
+	}
+
+	numHullPoints = (*hull)->numpoints;
+	memcpy( hullPoints, (*hull)->p, numHullPoints * sizeof(vec3_t) );
+
+	for ( i = 0 ; i < w->numpoints ; i++ ) {
+		p = w->p[i];
+
+		// calculate hull side vectors
+		for ( j = 0 ; j < numHullPoints ; j++ ) {
+			k = ( j + 1 ) % numHullPoints;
+
+			VectorSubtract( hullPoints[k], hullPoints[j], dir );
+			VectorNormalize( dir, dir );
+			CrossProduct( normal, dir, hullDirs[j] );
+		}
+
+		outside = qfalse;
+		for ( j = 0 ; j < numHullPoints ; j++ ) {
+			VectorSubtract( p, hullPoints[j], dir );
+			d = DotProduct( dir, hullDirs[j] );
+			if ( d >= ON_EPSILON ) {
+				outside = qtrue;
+			}
+			if ( d >= -ON_EPSILON ) {
+				hullSide[j] = qtrue;
+			} else {
+				hullSide[j] = qfalse;
+			}
+		}
+
+		// if the point is effectively inside, do nothing
+		if ( !outside ) {
+			continue;
+		}
+
+		// find the back side to front side transition
+		for ( j = 0 ; j < numHullPoints ; j++ ) {
+			if ( !hullSide[ j % numHullPoints ] && hullSide[ (j + 1) % numHullPoints ] ) {
+				break;
+			}
+		}
+		if ( j == numHullPoints ) {
+			continue;
+		}
+
+		// insert the point here
+		VectorCopy( p, newHullPoints[0] );
+		numNew = 1;
+
+		// copy over all points that aren't double fronts
+		j = (j+1)%numHullPoints;
+		for ( k = 0 ; k < numHullPoints ; k++ ) {
+			if ( hullSide[ (j+k) % numHullPoints ] && hullSide[ (j+k+1) % numHullPoints ] ) {
+				continue;
+			}
+			copy = hullPoints[ (j+k+1) % numHullPoints ];
+			VectorCopy( copy, newHullPoints[numNew] );
+			numNew++;
+		}
+
+		numHullPoints = numNew;
+		memcpy( hullPoints, newHullPoints, numHullPoints * sizeof(vec3_t) );
+	}
+
+	FreeWinding( *hull );
+	w = AllocWinding( numHullPoints );
+	w->numpoints = numHullPoints;
+	*hull = w;
+	memcpy( w->p, hullPoints, numHullPoints * sizeof(vec3_t) );
+}
+
+
diff --git a/tools/quake3/common/polylib.h b/tools/quake3/common/polylib.h
index 0bc4a8ad..58b21d5a 100644
--- a/tools/quake3/common/polylib.h
+++ b/tools/quake3/common/polylib.h
@@ -1,57 +1,57 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-typedef struct
-{
-	int		numpoints;
-	vec3_t	p[4];		// variable sized
-} winding_t;
-
-#define	MAX_POINTS_ON_WINDING	64
-
-// you can define on_epsilon in the makefile as tighter
-#ifndef	ON_EPSILON
-#define	ON_EPSILON	0.1
-#endif
-
-winding_t	*AllocWinding (int points);
-vec_t	WindingArea (winding_t *w);
-void	WindingCenter (winding_t *w, vec3_t center);
-void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
-				vec_t epsilon, winding_t **front, winding_t **back);
-winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
-winding_t	*CopyWinding (winding_t *w);
-winding_t	*ReverseWinding (winding_t *w);
-winding_t	*BaseWindingForPlane (vec3_t normal, vec_t dist);
-void	CheckWinding (winding_t *w);
-void	WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
-void	RemoveColinearPoints (winding_t *w);
-int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
-void	FreeWinding (winding_t *w);
-void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
-
-void	AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal );
-
-void	ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
-// frees the original if clipped
-
-void pw(winding_t *w);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+typedef struct
+{
+	int		numpoints;
+	vec3_t	p[4];		// variable sized
+} winding_t;
+
+#define	MAX_POINTS_ON_WINDING	64
+
+// you can define on_epsilon in the makefile as tighter
+#ifndef	ON_EPSILON
+#define	ON_EPSILON	0.1
+#endif
+
+winding_t	*AllocWinding (int points);
+vec_t	WindingArea (winding_t *w);
+void	WindingCenter (winding_t *w, vec3_t center);
+void	ClipWindingEpsilon (winding_t *in, vec3_t normal, vec_t dist, 
+				vec_t epsilon, winding_t **front, winding_t **back);
+winding_t	*ChopWinding (winding_t *in, vec3_t normal, vec_t dist);
+winding_t	*CopyWinding (winding_t *w);
+winding_t	*ReverseWinding (winding_t *w);
+winding_t	*BaseWindingForPlane (vec3_t normal, vec_t dist);
+void	CheckWinding (winding_t *w);
+void	WindingPlane (winding_t *w, vec3_t normal, vec_t *dist);
+void	RemoveColinearPoints (winding_t *w);
+int		WindingOnPlaneSide (winding_t *w, vec3_t normal, vec_t dist);
+void	FreeWinding (winding_t *w);
+void	WindingBounds (winding_t *w, vec3_t mins, vec3_t maxs);
+
+void	AddWindingToConvexHull( winding_t *w, winding_t **hull, vec3_t normal );
+
+void	ChopWindingInPlace (winding_t **w, vec3_t normal, vec_t dist, vec_t epsilon);
+// frees the original if clipped
+
+void pw(winding_t *w);
diff --git a/tools/quake3/common/polyset.h b/tools/quake3/common/polyset.h
index 459fde12..04a4d5b7 100644
--- a/tools/quake3/common/polyset.h
+++ b/tools/quake3/common/polyset.h
@@ -1,51 +1,51 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __POLYSET_H__
-#define __POLYSET_H__
-
-#define POLYSET_MAXTRIANGLES	4096
-#define POLYSET_MAXPOLYSETS		64
-
-typedef float st_t[2];
-typedef float rgb_t[3];
-
-typedef struct {
-	vec3_t	verts[3];
-	vec3_t	normals[3];
-	st_t	texcoords[3];
-} triangle_t;
-
-typedef struct
-{
-	char name[100];
-	char materialname[100];
-	triangle_t *triangles;
-	int numtriangles;
-} polyset_t;
-
-polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet );
-polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets );
-polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris );
-void Polyset_SnapSets( polyset_t *psets, int numpolysets );
-void Polyset_ComputeNormals( polyset_t *psets, int numpolysets );
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __POLYSET_H__
+#define __POLYSET_H__
+
+#define POLYSET_MAXTRIANGLES	4096
+#define POLYSET_MAXPOLYSETS		64
+
+typedef float st_t[2];
+typedef float rgb_t[3];
+
+typedef struct {
+	vec3_t	verts[3];
+	vec3_t	normals[3];
+	st_t	texcoords[3];
+} triangle_t;
+
+typedef struct
+{
+	char name[100];
+	char materialname[100];
+	triangle_t *triangles;
+	int numtriangles;
+} polyset_t;
+
+polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet );
+polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets );
+polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris );
+void Polyset_SnapSets( polyset_t *psets, int numpolysets );
+void Polyset_ComputeNormals( polyset_t *psets, int numpolysets );
+
+#endif
diff --git a/tools/quake3/common/qfiles.h b/tools/quake3/common/qfiles.h
index 584d8e96..091640ed 100644
--- a/tools/quake3/common/qfiles.h
+++ b/tools/quake3/common/qfiles.h
@@ -1,489 +1,489 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef __QFILES_H__
-#define __QFILES_H__
-
-//
-// qfiles.h: quake file formats
-// This file must be identical in the quake and utils directories
-//
-
-// surface geometry should not exceed these limits
-#define	SHADER_MAX_VERTEXES	1000
-#define	SHADER_MAX_INDEXES	(6*SHADER_MAX_VERTEXES)
-
-
-// the maximum size of game reletive pathnames
-#define	MAX_QPATH		64
-
-/*
-========================================================================
-
-QVM files
-
-========================================================================
-*/
-
-#define	VM_MAGIC	0x12721444
-typedef struct {
-	int		vmMagic;
-
-	int		instructionCount;
-
-	int		codeOffset;
-	int		codeLength;
-
-	int		dataOffset;
-	int		dataLength;
-	int		litLength;			// ( dataLength - litLength ) should be byteswapped on load
-	int		bssLength;			// zero filled memory appended to datalength
-} vmHeader_t;
-
-
-/*
-========================================================================
-
-PCX files are used for 8 bit images
-
-========================================================================
-*/
-
-typedef struct {
-    char	manufacturer;
-    char	version;
-    char	encoding;
-    char	bits_per_pixel;
-    unsigned short	xmin,ymin,xmax,ymax;
-    unsigned short	hres,vres;
-    unsigned char	palette[48];
-    char	reserved;
-    char	color_planes;
-    unsigned short	bytes_per_line;
-    unsigned short	palette_type;
-    char	filler[58];
-    unsigned char	data;			// unbounded
-} pcx_t;
-
-
-/*
-========================================================================
-
-TGA files are used for 24/32 bit images
-
-========================================================================
-*/
-
-typedef struct _TargaHeader {
-	unsigned char 	id_length, colormap_type, image_type;
-	unsigned short	colormap_index, colormap_length;
-	unsigned char	colormap_size;
-	unsigned short	x_origin, y_origin, width, height;
-	unsigned char	pixel_size, attributes;
-} TargaHeader;
-
-
-
-/*
-========================================================================
-
-.MD3 triangle model file format
-
-========================================================================
-*/
-
-#define MD3_IDENT			(('3'<<24)+('P'<<16)+('D'<<8)+'I')
-#define MD3_VERSION			15
-
-// limits
-#define MD3_MAX_LODS		4
-#define	MD3_MAX_TRIANGLES	8192	// per surface
-#define MD3_MAX_VERTS		4096	// per surface
-#define MD3_MAX_SHADERS		256		// per surface
-#define MD3_MAX_FRAMES		1024	// per model
-#define	MD3_MAX_SURFACES	32		// per model
-#define MD3_MAX_TAGS		16		// per frame
-
-// vertex scales
-#define	MD3_XYZ_SCALE		(1.0/64)
-
-typedef struct md3Frame_s {
-	vec3_t		bounds[2];
-	vec3_t		localOrigin;
-	float		radius;
-	char		name[16];
-} md3Frame_t;
-
-typedef struct md3Tag_s {
-	char		name[MAX_QPATH];	// tag name
-	vec3_t		origin;
-	vec3_t		axis[3];
-} md3Tag_t;
-
-/*
-** md3Surface_t
-**
-** CHUNK			SIZE
-** header			sizeof( md3Surface_t )
-** shaders			sizeof( md3Shader_t ) * numShaders
-** triangles[0]		sizeof( md3Triangle_t ) * numTriangles
-** st				sizeof( md3St_t ) * numVerts
-** XyzNormals		sizeof( md3XyzNormal_t ) * numVerts * numFrames
-*/
-typedef struct {
-	int		ident;				// 
-
-	char	name[MAX_QPATH];	// polyset name
-
-	int		flags;
-	int		numFrames;			// all surfaces in a model should have the same
-
-	int		numShaders;			// all surfaces in a model should have the same
-	int		numVerts;
-
-	int		numTriangles;
-	int		ofsTriangles;
-
-	int		ofsShaders;			// offset from start of md3Surface_t
-	int		ofsSt;				// texture coords are common for all frames
-	int		ofsXyzNormals;		// numVerts * numFrames
-
-	int		ofsEnd;				// next surface follows
-} md3Surface_t;
-
-typedef struct {
-	char			name[MAX_QPATH];
-	int				shaderIndex;	// for in-game use
-} md3Shader_t;
-
-typedef struct {
-	int			indexes[3];
-} md3Triangle_t;
-
-typedef struct {
-	float		st[2];
-} md3St_t;
-
-typedef struct {
-	short		xyz[3];
-	short		normal;
-} md3XyzNormal_t;
-
-typedef struct {
-	int			ident;
-	int			version;
-
-	char		name[MAX_QPATH];	// model name
-
-	int			flags;
-
-	int			numFrames;
-	int			numTags;			
-	int			numSurfaces;
-
-	int			numSkins;
-
-	int			ofsFrames;			// offset for first frame
-	int			ofsTags;			// numFrames * numTags
-	int			ofsSurfaces;		// first surface, others follow
-
-	int			ofsEnd;				// end of file
-} md3Header_t;
-
-/*
-==============================================================================
-
-MD4 file format
-
-==============================================================================
-*/
-
-#define MD4_IDENT			(('4'<<24)+('P'<<16)+('D'<<8)+'I')
-#define MD4_VERSION			1
-#define	MD4_MAX_BONES		128
-
-typedef struct {
-	int			boneIndex;		// these are indexes into the boneReferences,
-	float		   boneWeight;		// not the global per-frame bone list
-} md4Weight_t;
-
-typedef struct {
-  vec3_t    vertex;
-	vec3_t		normal;
-	float		texCoords[2];
-	int			numWeights;
-	md4Weight_t	weights[1];		// variable sized
-} md4Vertex_t;
-
-typedef struct {
-	int			indexes[3];
-} md4Triangle_t;
-
-typedef struct {
-	int			ident;
-
-	char		name[MAX_QPATH];	// polyset name
-	char		shader[MAX_QPATH];
-	int			shaderIndex;		// for in-game use
-
-	int			ofsHeader;			// this will be a negative number
-
-	int			numVerts;
-	int			ofsVerts;
-
-	int			numTriangles;
-	int			ofsTriangles;
-
-	// Bone references are a set of ints representing all the bones
-	// present in any vertex weights for this surface.  This is
-	// needed because a model may have surfaces that need to be
-	// drawn at different sort times, and we don't want to have
-	// to re-interpolate all the bones for each surface.
-	int			numBoneReferences;
-	int			ofsBoneReferences;
-
-	int			ofsEnd;				// next surface follows
-} md4Surface_t;
-
-typedef struct {
-	float		matrix[3][4];
-} md4Bone_t;
-
-typedef struct {
-	vec3_t		bounds[2];			// bounds of all surfaces of all LOD's for this frame
-	vec3_t		localOrigin;		// midpoint of bounds, used for sphere cull
-	float		radius;				// dist from localOrigin to corner
-	char		name[16];
-	md4Bone_t	bones[1];			// [numBones]
-} md4Frame_t;
-
-typedef struct {
-	int			numSurfaces;
-	int			ofsSurfaces;		// first surface, others follow
-	int			ofsEnd;				// next lod follows
-} md4LOD_t;
-
-typedef struct {
-	int			ident;
-	int			version;
-
-	char		name[MAX_QPATH];	// model name
-
-	// frames and bones are shared by all levels of detail
-	int			numFrames;
-	int			numBones;
-	int			ofsFrames;			// md4Frame_t[numFrames]
-
-	// each level of detail has completely separate sets of surfaces
-	int			numLODs;
-	int			ofsLODs;
-
-	int			ofsEnd;				// end of file
-} md4Header_t;
-
-
-/*
-==============================================================================
-
-  .BSP file format
-
-==============================================================================
-*/
-
-
-#define BSP_IDENT	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
-		// little-endian "IBSP"
-
-//#define BSP_VERSION			46
-#define Q3_BSP_VERSION			46
-#define WOLF_BSP_VERSION		47
-
-// there shouldn't be any problem with increasing these values at the
-// expense of more memory allocation in the utilities
-#define	MAX_MAP_MODELS		0x400
-#define	MAX_MAP_BRUSHES		0x8000
-#define	MAX_MAP_ENTITIES	0x800
-#define	MAX_MAP_ENTSTRING	0x40000
-#define	MAX_MAP_SHADERS		0x400
-
-#define	MAX_MAP_AREAS		0x100	// MAX_MAP_AREA_BYTES in q_shared must match!
-#define	MAX_MAP_FOGS		0x100
-#define	MAX_MAP_PLANES		0x20000
-#define	MAX_MAP_NODES		0x20000
-#define	MAX_MAP_BRUSHSIDES	0x40000	//%	0x20000	/* ydnar */
-#define	MAX_MAP_LEAFS		0x20000
-#define	MAX_MAP_LEAFFACES	0x20000
-#define	MAX_MAP_LEAFBRUSHES 0x40000
-#define	MAX_MAP_PORTALS		0x20000
-#define	MAX_MAP_LIGHTING	0x800000
-#define	MAX_MAP_LIGHTGRID	0x800000
-#define	MAX_MAP_VISIBILITY	0x200000
-
-#define	MAX_MAP_DRAW_SURFS	0x20000
-#define	MAX_MAP_DRAW_VERTS	0x80000
-#define	MAX_MAP_DRAW_INDEXES	0x80000
-
-
-// key / value pair sizes in the entities lump
-#define	MAX_KEY				32
-#define	MAX_VALUE			1024
-
-// the editor uses these predefined yaw angles to orient entities up or down
-#define	ANGLE_UP			-1
-#define	ANGLE_DOWN			-2
-
-#define	LIGHTMAP_WIDTH		128
-#define	LIGHTMAP_HEIGHT		128
-
-#define MIN_WORLD_COORD		(-65536)
-#define	MAX_WORLD_COORD		(65536)
-#define WORLD_SIZE			(MAX_WORLD_COORD - MIN_WORLD_COORD)
-
-//=============================================================================
-
-
-typedef struct {
-	int		fileofs, filelen;
-} lump_t;
-
-#define	LUMP_ENTITIES		0
-#define	LUMP_SHADERS		1
-#define	LUMP_PLANES			2
-#define	LUMP_NODES			3
-#define	LUMP_LEAFS			4
-#define	LUMP_LEAFSURFACES	5
-#define	LUMP_LEAFBRUSHES	6
-#define	LUMP_MODELS			7
-#define	LUMP_BRUSHES		8
-#define	LUMP_BRUSHSIDES		9
-#define	LUMP_DRAWVERTS		10
-#define	LUMP_DRAWINDEXES	11
-#define	LUMP_FOGS			12
-#define	LUMP_SURFACES		13
-#define	LUMP_LIGHTMAPS		14
-#define	LUMP_LIGHTGRID		15
-#define	LUMP_VISIBILITY		16
-#define	HEADER_LUMPS		17
-
-typedef struct {
-	int			ident;
-	int			version;
-
-	lump_t		lumps[HEADER_LUMPS];
-} dheader_t;
-
-typedef struct {
-	float		mins[3], maxs[3];
-	int			firstSurface, numSurfaces;
-	int			firstBrush, numBrushes;
-} dmodel_t;
-
-typedef struct {
-	char		shader[MAX_QPATH];
-	int			surfaceFlags;
-	int			contentFlags;
-} dshader_t;
-
-// planes x^1 is allways the opposite of plane x
-
-typedef struct {
-	float		normal[3];
-	float		dist;
-} dplane_t;
-
-typedef struct {
-	int			planeNum;
-	int			children[2];	// negative numbers are -(leafs+1), not nodes
-	int			mins[3];		// for frustom culling
-	int			maxs[3];
-} dnode_t;
-
-typedef struct {
-	int			cluster;			// -1 = opaque cluster (do I still store these?)
-	int			area;
-
-	int			mins[3];			// for frustum culling
-	int			maxs[3];
-
-	int			firstLeafSurface;
-	int			numLeafSurfaces;
-
-	int			firstLeafBrush;
-	int			numLeafBrushes;
-} dleaf_t;
-
-typedef struct {
-	int			planeNum;			// positive plane side faces out of the leaf
-	int			shaderNum;
-} dbrushside_t;
-
-typedef struct {
-	int			firstSide;
-	int			numSides;
-	int			shaderNum;		// the shader that determines the contents flags
-} dbrush_t;
-
-typedef struct {
-	char		shader[MAX_QPATH];
-	int			brushNum;
-	int			visibleSide;	// the brush side that ray tests need to clip against (-1 == none)
-} dfog_t;
-
-typedef struct {
-	vec3_t		xyz;
-	float		st[2];
-	float		lightmap[2];
-	vec3_t		normal;
-	byte		color[4];
-} drawVert_t;
-
-typedef enum {
-	MST_BAD,
-	MST_PLANAR,
-	MST_PATCH,
-	MST_TRIANGLE_SOUP,
-	MST_FLARE
-} mapSurfaceType_t;
-
-typedef struct {
-	int			shaderNum;
-	int			fogNum;
-	int			surfaceType;
-
-	int			firstVert;
-	int			numVerts;
-
-	int			firstIndex;
-	int			numIndexes;
-
-	int			lightmapNum;
-	int			lightmapX, lightmapY;
-	int			lightmapWidth, lightmapHeight;
-
-	vec3_t		lightmapOrigin;
-	vec3_t		lightmapVecs[3];	// for patches, [0] and [1] are lodbounds
-
-	int			patchWidth;
-	int			patchHeight;
-} dsurface_t;
-
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef __QFILES_H__
+#define __QFILES_H__
+
+//
+// qfiles.h: quake file formats
+// This file must be identical in the quake and utils directories
+//
+
+// surface geometry should not exceed these limits
+#define	SHADER_MAX_VERTEXES	1000
+#define	SHADER_MAX_INDEXES	(6*SHADER_MAX_VERTEXES)
+
+
+// the maximum size of game reletive pathnames
+#define	MAX_QPATH		64
+
+/*
+========================================================================
+
+QVM files
+
+========================================================================
+*/
+
+#define	VM_MAGIC	0x12721444
+typedef struct {
+	int		vmMagic;
+
+	int		instructionCount;
+
+	int		codeOffset;
+	int		codeLength;
+
+	int		dataOffset;
+	int		dataLength;
+	int		litLength;			// ( dataLength - litLength ) should be byteswapped on load
+	int		bssLength;			// zero filled memory appended to datalength
+} vmHeader_t;
+
+
+/*
+========================================================================
+
+PCX files are used for 8 bit images
+
+========================================================================
+*/
+
+typedef struct {
+    char	manufacturer;
+    char	version;
+    char	encoding;
+    char	bits_per_pixel;
+    unsigned short	xmin,ymin,xmax,ymax;
+    unsigned short	hres,vres;
+    unsigned char	palette[48];
+    char	reserved;
+    char	color_planes;
+    unsigned short	bytes_per_line;
+    unsigned short	palette_type;
+    char	filler[58];
+    unsigned char	data;			// unbounded
+} pcx_t;
+
+
+/*
+========================================================================
+
+TGA files are used for 24/32 bit images
+
+========================================================================
+*/
+
+typedef struct _TargaHeader {
+	unsigned char 	id_length, colormap_type, image_type;
+	unsigned short	colormap_index, colormap_length;
+	unsigned char	colormap_size;
+	unsigned short	x_origin, y_origin, width, height;
+	unsigned char	pixel_size, attributes;
+} TargaHeader;
+
+
+
+/*
+========================================================================
+
+.MD3 triangle model file format
+
+========================================================================
+*/
+
+#define MD3_IDENT			(('3'<<24)+('P'<<16)+('D'<<8)+'I')
+#define MD3_VERSION			15
+
+// limits
+#define MD3_MAX_LODS		4
+#define	MD3_MAX_TRIANGLES	8192	// per surface
+#define MD3_MAX_VERTS		4096	// per surface
+#define MD3_MAX_SHADERS		256		// per surface
+#define MD3_MAX_FRAMES		1024	// per model
+#define	MD3_MAX_SURFACES	32		// per model
+#define MD3_MAX_TAGS		16		// per frame
+
+// vertex scales
+#define	MD3_XYZ_SCALE		(1.0/64)
+
+typedef struct md3Frame_s {
+	vec3_t		bounds[2];
+	vec3_t		localOrigin;
+	float		radius;
+	char		name[16];
+} md3Frame_t;
+
+typedef struct md3Tag_s {
+	char		name[MAX_QPATH];	// tag name
+	vec3_t		origin;
+	vec3_t		axis[3];
+} md3Tag_t;
+
+/*
+** md3Surface_t
+**
+** CHUNK			SIZE
+** header			sizeof( md3Surface_t )
+** shaders			sizeof( md3Shader_t ) * numShaders
+** triangles[0]		sizeof( md3Triangle_t ) * numTriangles
+** st				sizeof( md3St_t ) * numVerts
+** XyzNormals		sizeof( md3XyzNormal_t ) * numVerts * numFrames
+*/
+typedef struct {
+	int		ident;				// 
+
+	char	name[MAX_QPATH];	// polyset name
+
+	int		flags;
+	int		numFrames;			// all surfaces in a model should have the same
+
+	int		numShaders;			// all surfaces in a model should have the same
+	int		numVerts;
+
+	int		numTriangles;
+	int		ofsTriangles;
+
+	int		ofsShaders;			// offset from start of md3Surface_t
+	int		ofsSt;				// texture coords are common for all frames
+	int		ofsXyzNormals;		// numVerts * numFrames
+
+	int		ofsEnd;				// next surface follows
+} md3Surface_t;
+
+typedef struct {
+	char			name[MAX_QPATH];
+	int				shaderIndex;	// for in-game use
+} md3Shader_t;
+
+typedef struct {
+	int			indexes[3];
+} md3Triangle_t;
+
+typedef struct {
+	float		st[2];
+} md3St_t;
+
+typedef struct {
+	short		xyz[3];
+	short		normal;
+} md3XyzNormal_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+
+	char		name[MAX_QPATH];	// model name
+
+	int			flags;
+
+	int			numFrames;
+	int			numTags;			
+	int			numSurfaces;
+
+	int			numSkins;
+
+	int			ofsFrames;			// offset for first frame
+	int			ofsTags;			// numFrames * numTags
+	int			ofsSurfaces;		// first surface, others follow
+
+	int			ofsEnd;				// end of file
+} md3Header_t;
+
+/*
+==============================================================================
+
+MD4 file format
+
+==============================================================================
+*/
+
+#define MD4_IDENT			(('4'<<24)+('P'<<16)+('D'<<8)+'I')
+#define MD4_VERSION			1
+#define	MD4_MAX_BONES		128
+
+typedef struct {
+	int			boneIndex;		// these are indexes into the boneReferences,
+	float		   boneWeight;		// not the global per-frame bone list
+} md4Weight_t;
+
+typedef struct {
+  vec3_t    vertex;
+	vec3_t		normal;
+	float		texCoords[2];
+	int			numWeights;
+	md4Weight_t	weights[1];		// variable sized
+} md4Vertex_t;
+
+typedef struct {
+	int			indexes[3];
+} md4Triangle_t;
+
+typedef struct {
+	int			ident;
+
+	char		name[MAX_QPATH];	// polyset name
+	char		shader[MAX_QPATH];
+	int			shaderIndex;		// for in-game use
+
+	int			ofsHeader;			// this will be a negative number
+
+	int			numVerts;
+	int			ofsVerts;
+
+	int			numTriangles;
+	int			ofsTriangles;
+
+	// Bone references are a set of ints representing all the bones
+	// present in any vertex weights for this surface.  This is
+	// needed because a model may have surfaces that need to be
+	// drawn at different sort times, and we don't want to have
+	// to re-interpolate all the bones for each surface.
+	int			numBoneReferences;
+	int			ofsBoneReferences;
+
+	int			ofsEnd;				// next surface follows
+} md4Surface_t;
+
+typedef struct {
+	float		matrix[3][4];
+} md4Bone_t;
+
+typedef struct {
+	vec3_t		bounds[2];			// bounds of all surfaces of all LOD's for this frame
+	vec3_t		localOrigin;		// midpoint of bounds, used for sphere cull
+	float		radius;				// dist from localOrigin to corner
+	char		name[16];
+	md4Bone_t	bones[1];			// [numBones]
+} md4Frame_t;
+
+typedef struct {
+	int			numSurfaces;
+	int			ofsSurfaces;		// first surface, others follow
+	int			ofsEnd;				// next lod follows
+} md4LOD_t;
+
+typedef struct {
+	int			ident;
+	int			version;
+
+	char		name[MAX_QPATH];	// model name
+
+	// frames and bones are shared by all levels of detail
+	int			numFrames;
+	int			numBones;
+	int			ofsFrames;			// md4Frame_t[numFrames]
+
+	// each level of detail has completely separate sets of surfaces
+	int			numLODs;
+	int			ofsLODs;
+
+	int			ofsEnd;				// end of file
+} md4Header_t;
+
+
+/*
+==============================================================================
+
+  .BSP file format
+
+==============================================================================
+*/
+
+
+#define BSP_IDENT	(('P'<<24)+('S'<<16)+('B'<<8)+'I')
+		// little-endian "IBSP"
+
+//#define BSP_VERSION			46
+#define Q3_BSP_VERSION			46
+#define WOLF_BSP_VERSION		47
+
+// there shouldn't be any problem with increasing these values at the
+// expense of more memory allocation in the utilities
+#define	MAX_MAP_MODELS		0x400
+#define	MAX_MAP_BRUSHES		0x8000
+#define	MAX_MAP_ENTITIES	0x800
+#define	MAX_MAP_ENTSTRING	0x40000
+#define	MAX_MAP_SHADERS		0x400
+
+#define	MAX_MAP_AREAS		0x100	// MAX_MAP_AREA_BYTES in q_shared must match!
+#define	MAX_MAP_FOGS		0x100
+#define	MAX_MAP_PLANES		0x20000
+#define	MAX_MAP_NODES		0x20000
+#define	MAX_MAP_BRUSHSIDES	0x40000	//%	0x20000	/* ydnar */
+#define	MAX_MAP_LEAFS		0x20000
+#define	MAX_MAP_LEAFFACES	0x20000
+#define	MAX_MAP_LEAFBRUSHES 0x40000
+#define	MAX_MAP_PORTALS		0x20000
+#define	MAX_MAP_LIGHTING	0x800000
+#define	MAX_MAP_LIGHTGRID	0x800000
+#define	MAX_MAP_VISIBILITY	0x200000
+
+#define	MAX_MAP_DRAW_SURFS	0x20000
+#define	MAX_MAP_DRAW_VERTS	0x80000
+#define	MAX_MAP_DRAW_INDEXES	0x80000
+
+
+// key / value pair sizes in the entities lump
+#define	MAX_KEY				32
+#define	MAX_VALUE			1024
+
+// the editor uses these predefined yaw angles to orient entities up or down
+#define	ANGLE_UP			-1
+#define	ANGLE_DOWN			-2
+
+#define	LIGHTMAP_WIDTH		128
+#define	LIGHTMAP_HEIGHT		128
+
+#define MIN_WORLD_COORD		(-65536)
+#define	MAX_WORLD_COORD		(65536)
+#define WORLD_SIZE			(MAX_WORLD_COORD - MIN_WORLD_COORD)
+
+//=============================================================================
+
+
+typedef struct {
+	int		fileofs, filelen;
+} lump_t;
+
+#define	LUMP_ENTITIES		0
+#define	LUMP_SHADERS		1
+#define	LUMP_PLANES			2
+#define	LUMP_NODES			3
+#define	LUMP_LEAFS			4
+#define	LUMP_LEAFSURFACES	5
+#define	LUMP_LEAFBRUSHES	6
+#define	LUMP_MODELS			7
+#define	LUMP_BRUSHES		8
+#define	LUMP_BRUSHSIDES		9
+#define	LUMP_DRAWVERTS		10
+#define	LUMP_DRAWINDEXES	11
+#define	LUMP_FOGS			12
+#define	LUMP_SURFACES		13
+#define	LUMP_LIGHTMAPS		14
+#define	LUMP_LIGHTGRID		15
+#define	LUMP_VISIBILITY		16
+#define	HEADER_LUMPS		17
+
+typedef struct {
+	int			ident;
+	int			version;
+
+	lump_t		lumps[HEADER_LUMPS];
+} dheader_t;
+
+typedef struct {
+	float		mins[3], maxs[3];
+	int			firstSurface, numSurfaces;
+	int			firstBrush, numBrushes;
+} dmodel_t;
+
+typedef struct {
+	char		shader[MAX_QPATH];
+	int			surfaceFlags;
+	int			contentFlags;
+} dshader_t;
+
+// planes x^1 is allways the opposite of plane x
+
+typedef struct {
+	float		normal[3];
+	float		dist;
+} dplane_t;
+
+typedef struct {
+	int			planeNum;
+	int			children[2];	// negative numbers are -(leafs+1), not nodes
+	int			mins[3];		// for frustom culling
+	int			maxs[3];
+} dnode_t;
+
+typedef struct {
+	int			cluster;			// -1 = opaque cluster (do I still store these?)
+	int			area;
+
+	int			mins[3];			// for frustum culling
+	int			maxs[3];
+
+	int			firstLeafSurface;
+	int			numLeafSurfaces;
+
+	int			firstLeafBrush;
+	int			numLeafBrushes;
+} dleaf_t;
+
+typedef struct {
+	int			planeNum;			// positive plane side faces out of the leaf
+	int			shaderNum;
+} dbrushside_t;
+
+typedef struct {
+	int			firstSide;
+	int			numSides;
+	int			shaderNum;		// the shader that determines the contents flags
+} dbrush_t;
+
+typedef struct {
+	char		shader[MAX_QPATH];
+	int			brushNum;
+	int			visibleSide;	// the brush side that ray tests need to clip against (-1 == none)
+} dfog_t;
+
+typedef struct {
+	vec3_t		xyz;
+	float		st[2];
+	float		lightmap[2];
+	vec3_t		normal;
+	byte		color[4];
+} drawVert_t;
+
+typedef enum {
+	MST_BAD,
+	MST_PLANAR,
+	MST_PATCH,
+	MST_TRIANGLE_SOUP,
+	MST_FLARE
+} mapSurfaceType_t;
+
+typedef struct {
+	int			shaderNum;
+	int			fogNum;
+	int			surfaceType;
+
+	int			firstVert;
+	int			numVerts;
+
+	int			firstIndex;
+	int			numIndexes;
+
+	int			lightmapNum;
+	int			lightmapX, lightmapY;
+	int			lightmapWidth, lightmapHeight;
+
+	vec3_t		lightmapOrigin;
+	vec3_t		lightmapVecs[3];	// for patches, [0] and [1] are lodbounds
+
+	int			patchWidth;
+	int			patchHeight;
+} dsurface_t;
+
+
+#endif
diff --git a/tools/quake3/common/qthreads.h b/tools/quake3/common/qthreads.h
index eeeac14f..25bacca4 100644
--- a/tools/quake3/common/qthreads.h
+++ b/tools/quake3/common/qthreads.h
@@ -1,31 +1,31 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-extern	int		numthreads;
-
-void ThreadSetDefault (void);
-int	GetThreadWork (void);
-void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
-void ThreadLock (void);
-void ThreadUnlock (void);
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+extern	int		numthreads;
+
+void ThreadSetDefault (void);
+int	GetThreadWork (void);
+void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int));
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int));
+void ThreadLock (void);
+void ThreadUnlock (void);
+
diff --git a/tools/quake3/common/scriplib.c b/tools/quake3/common/scriplib.c
index 267078c6..a4c9bb88 100644
--- a/tools/quake3/common/scriplib.c
+++ b/tools/quake3/common/scriplib.c
@@ -1,409 +1,409 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// scriplib.c
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include "scriplib.h"
-#include "vfs.h"
-
-/*
-=============================================================================
-
-						PARSING STUFF
-
-=============================================================================
-*/
-
-typedef struct
-{
-	char	filename[1024];
-	char    *buffer,*script_p,*end_p;
-	int     line;
-} script_t;
-
-#define	MAX_INCLUDES	8
-script_t	scriptstack[MAX_INCLUDES];
-script_t	*script;
-int			scriptline;
-
-char    token[MAXTOKEN];
-qboolean endofscript;
-qboolean tokenready;                     // only qtrue if UnGetToken was just called
-
-/*
-==============
-AddScriptToStack
-==============
-*/
-void AddScriptToStack (const char *filename, int index)
-{
-  int size;
-
-  script++;
-  if (script == &scriptstack[MAX_INCLUDES])
-    Error ("script file exceeded MAX_INCLUDES");
-  strcpy (script->filename, ExpandPath (filename));
-
-  size = vfsLoadFile (script->filename, (void **)&script->buffer, index);
-
-  if (size == -1)
-    Sys_Printf ("Script file %s was not found\n", script->filename);
-  else
-  {
-    if (index > 0)
-      Sys_Printf ("entering %s (%d)\n", script->filename, index+1);
-    else
-      Sys_Printf ("entering %s\n", script->filename);
-  }
-
-  script->line = 1;
-  script->script_p = script->buffer;
-  script->end_p = script->buffer + size;
-}
-
-
-/*
-==============
-LoadScriptFile
-==============
-*/
-void LoadScriptFile (const char *filename, int index)
-{
-  script = scriptstack;
-  AddScriptToStack (filename, index);
-
-  endofscript = qfalse;
-  tokenready = qfalse;
-}
-
-
-/*
-==============
-ParseFromMemory
-==============
-*/
-void ParseFromMemory (char *buffer, int size)
-{
-	script = scriptstack;
-	script++;
-	if (script == &scriptstack[MAX_INCLUDES])
-		Error ("script file exceeded MAX_INCLUDES");
-	strcpy (script->filename, "memory buffer" );
-
-	script->buffer = buffer;
-	script->line = 1;
-	script->script_p = script->buffer;
-	script->end_p = script->buffer + size;
-
-	endofscript = qfalse;
-	tokenready = qfalse;
-}
-
-
-/*
-==============
-UnGetToken
-
-Signals that the current token was not used, and should be reported
-for the next GetToken.  Note that
-
-GetToken (qtrue);
-UnGetToken ();
-GetToken (qfalse);
-
-could cross a line boundary.
-==============
-*/
-void UnGetToken (void)
-{
-	tokenready = qtrue;
-}
-
-
-qboolean EndOfScript (qboolean crossline)
-{
-	if (!crossline)
-		Error ("Line %i is incomplete\n",scriptline);
-
-	if (!strcmp (script->filename, "memory buffer"))
-	{
-		endofscript = qtrue;
-		return qfalse;
-	}
-	
-	if( script->buffer == NULL )
-		Sys_Printf( "WARNING: Attempt to free already freed script buffer\n" );
-	else
-		free( script->buffer );
-	script->buffer = NULL;
-	if (script == scriptstack+1)
-	{
-		endofscript = qtrue;
-		return qfalse;
-	}
-	script--;
-	scriptline = script->line;
-	Sys_Printf ("returning to %s\n", script->filename);
-	return GetToken (crossline);
-}
-
-/*
-==============
-GetToken
-==============
-*/
-qboolean GetToken (qboolean crossline)
-{
-	char    *token_p;
-
-	
-	/* ydnar: dummy testing */
-	if( script == NULL || script->buffer == NULL )
-		return qfalse;
-	
-	if (tokenready)                         // is a token already waiting?
-	{
-		tokenready = qfalse;
-		return qtrue;
-	}
-
-	if ((script->script_p >= script->end_p) || (script->script_p == NULL))
-          return EndOfScript (crossline);
-
-//
-// skip space
-//
-skipspace:
-	while (*script->script_p <= 32)
-	{
-		if (script->script_p >= script->end_p)
-			return EndOfScript (crossline);
-		if (*script->script_p++ == '\n')
-		{
-			if (!crossline)
-				Error ("Line %i is incomplete\n",scriptline);
-			script->line++;
-			scriptline = script->line;
-		}
-	}
-
-	if (script->script_p >= script->end_p)
-		return EndOfScript (crossline);
-
-	// ; # // comments
-	if (*script->script_p == ';' || *script->script_p == '#'
-		|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
-	{
-		if (!crossline)
-			Error ("Line %i is incomplete\n",scriptline);
-		while (*script->script_p++ != '\n')
-			if (script->script_p >= script->end_p)
-				return EndOfScript (crossline);
-		script->line++;
-		scriptline = script->line;
-		goto skipspace;
-	}
-
-	// /* */ comments
-	if (script->script_p[0] == '/' && script->script_p[1] == '*')
-	{
-		if (!crossline)
-			Error ("Line %i is incomplete\n",scriptline);
-		script->script_p+=2;
-		while (script->script_p[0] != '*' && script->script_p[1] != '/')
-		{
-			if ( *script->script_p == '\n' )
-			{
-				script->line++;
-				scriptline = script->line;
-			}
-			script->script_p++;
-			if (script->script_p >= script->end_p)
-				return EndOfScript (crossline);
-		}
-		script->script_p += 2;
-		goto skipspace;
-	}
-
-//
-// copy token
-//
-	token_p = token;
-
-	if (*script->script_p == '"')
-	{
-		// quoted token
-		script->script_p++;
-		while (*script->script_p != '"')
-		{
-			*token_p++ = *script->script_p++;
-			if (script->script_p == script->end_p)
-				break;
-			if (token_p == &token[MAXTOKEN])
-				Error ("Token too large on line %i\n",scriptline);
-		}
-		script->script_p++;
-	}
-	else	// regular token
-	while ( *script->script_p > 32 && *script->script_p != ';')
-	{
-		*token_p++ = *script->script_p++;
-		if (script->script_p == script->end_p)
-			break;
-		if (token_p == &token[MAXTOKEN])
-			Error ("Token too large on line %i\n",scriptline);
-	}
-
-	*token_p = 0;
-
-	if (!strcmp (token, "$include"))
-	{
-		GetToken (qfalse);
-		AddScriptToStack (token, 0);
-		return GetToken (crossline);
-	}
-
-	return qtrue;
-}
-
-
-/*
-==============
-TokenAvailable
-
-Returns qtrue if there is another token on the line
-==============
-*/
-qboolean TokenAvailable (void) {
-	int		oldLine, oldScriptLine;
-	qboolean	r;
-	
-	/* save */
-	oldLine = scriptline;
-	oldScriptLine = script->line;
-	
-	/* test */
-	r = GetToken( qtrue );
-	if ( !r ) {
-		return qfalse;
-	}
-	UnGetToken();
-	if ( oldLine == scriptline ) {
-		return qtrue;
-	}
-	
-	/* restore */
-	//%	scriptline = oldLine;
-	//%	script->line = oldScriptLine;
-
-	return qfalse;
-}
-
-
-//=====================================================================
-
-
-void MatchToken( char *match ) {
-	GetToken( qtrue );
-
-	if ( strcmp( token, match ) ) {
-		Error( "MatchToken( \"%s\" ) failed at line %i in file %s", match, scriptline, script->filename);
-	}
-}
-
-
-void Parse1DMatrix (int x, vec_t *m) {
-	int		i;
-
-	MatchToken( "(" );
-
-	for (i = 0 ; i < x ; i++) {
-		GetToken( qfalse );
-		m[i] = atof(token);
-	}
-
-	MatchToken( ")" );
-}
-
-void Parse2DMatrix (int y, int x, vec_t *m) {
-	int		i;
-
-	MatchToken( "(" );
-
-	for (i = 0 ; i < y ; i++) {
-		Parse1DMatrix (x, m + i * x);
-	}
-
-	MatchToken( ")" );
-}
-
-void Parse3DMatrix (int z, int y, int x, vec_t *m) {
-	int		i;
-
-	MatchToken( "(" );
-
-	for (i = 0 ; i < z ; i++) {
-		Parse2DMatrix (y, x, m + i * x*y);
-	}
-
-	MatchToken( ")" );
-}
-
-
-void Write1DMatrix (FILE *f, int x, vec_t *m) {
-	int		i;
-
-	fprintf (f, "( ");
-	for (i = 0 ; i < x ; i++) {
-		if (m[i] == (int)m[i] ) {
-			fprintf (f, "%i ", (int)m[i]);
-		} else {
-			fprintf (f, "%f ", m[i]);
-		}
-	}
-	fprintf (f, ")");
-}
-
-void Write2DMatrix (FILE *f, int y, int x, vec_t *m) {
-	int		i;
-
-	fprintf (f, "( ");
-	for (i = 0 ; i < y ; i++) {
-		Write1DMatrix (f, x, m + i*x);
-		fprintf (f, " ");
-	}
-	fprintf (f, ")\n");
-}
-
-
-void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m) {
-	int		i;
-
-	fprintf (f, "(\n");
-	for (i = 0 ; i < z ; i++) {
-		Write2DMatrix (f, y, x, m + i*(x*y) );
-	}
-	fprintf (f, ")\n");
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// scriplib.c
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include "scriplib.h"
+#include "vfs.h"
+
+/*
+=============================================================================
+
+						PARSING STUFF
+
+=============================================================================
+*/
+
+typedef struct
+{
+	char	filename[1024];
+	char    *buffer,*script_p,*end_p;
+	int     line;
+} script_t;
+
+#define	MAX_INCLUDES	8
+script_t	scriptstack[MAX_INCLUDES];
+script_t	*script;
+int			scriptline;
+
+char    token[MAXTOKEN];
+qboolean endofscript;
+qboolean tokenready;                     // only qtrue if UnGetToken was just called
+
+/*
+==============
+AddScriptToStack
+==============
+*/
+void AddScriptToStack (const char *filename, int index)
+{
+  int size;
+
+  script++;
+  if (script == &scriptstack[MAX_INCLUDES])
+    Error ("script file exceeded MAX_INCLUDES");
+  strcpy (script->filename, ExpandPath (filename));
+
+  size = vfsLoadFile (script->filename, (void **)&script->buffer, index);
+
+  if (size == -1)
+    Sys_Printf ("Script file %s was not found\n", script->filename);
+  else
+  {
+    if (index > 0)
+      Sys_Printf ("entering %s (%d)\n", script->filename, index+1);
+    else
+      Sys_Printf ("entering %s\n", script->filename);
+  }
+
+  script->line = 1;
+  script->script_p = script->buffer;
+  script->end_p = script->buffer + size;
+}
+
+
+/*
+==============
+LoadScriptFile
+==============
+*/
+void LoadScriptFile (const char *filename, int index)
+{
+  script = scriptstack;
+  AddScriptToStack (filename, index);
+
+  endofscript = qfalse;
+  tokenready = qfalse;
+}
+
+
+/*
+==============
+ParseFromMemory
+==============
+*/
+void ParseFromMemory (char *buffer, int size)
+{
+	script = scriptstack;
+	script++;
+	if (script == &scriptstack[MAX_INCLUDES])
+		Error ("script file exceeded MAX_INCLUDES");
+	strcpy (script->filename, "memory buffer" );
+
+	script->buffer = buffer;
+	script->line = 1;
+	script->script_p = script->buffer;
+	script->end_p = script->buffer + size;
+
+	endofscript = qfalse;
+	tokenready = qfalse;
+}
+
+
+/*
+==============
+UnGetToken
+
+Signals that the current token was not used, and should be reported
+for the next GetToken.  Note that
+
+GetToken (qtrue);
+UnGetToken ();
+GetToken (qfalse);
+
+could cross a line boundary.
+==============
+*/
+void UnGetToken (void)
+{
+	tokenready = qtrue;
+}
+
+
+qboolean EndOfScript (qboolean crossline)
+{
+	if (!crossline)
+		Error ("Line %i is incomplete\n",scriptline);
+
+	if (!strcmp (script->filename, "memory buffer"))
+	{
+		endofscript = qtrue;
+		return qfalse;
+	}
+	
+	if( script->buffer == NULL )
+		Sys_Printf( "WARNING: Attempt to free already freed script buffer\n" );
+	else
+		free( script->buffer );
+	script->buffer = NULL;
+	if (script == scriptstack+1)
+	{
+		endofscript = qtrue;
+		return qfalse;
+	}
+	script--;
+	scriptline = script->line;
+	Sys_Printf ("returning to %s\n", script->filename);
+	return GetToken (crossline);
+}
+
+/*
+==============
+GetToken
+==============
+*/
+qboolean GetToken (qboolean crossline)
+{
+	char    *token_p;
+
+	
+	/* ydnar: dummy testing */
+	if( script == NULL || script->buffer == NULL )
+		return qfalse;
+	
+	if (tokenready)                         // is a token already waiting?
+	{
+		tokenready = qfalse;
+		return qtrue;
+	}
+
+	if ((script->script_p >= script->end_p) || (script->script_p == NULL))
+          return EndOfScript (crossline);
+
+//
+// skip space
+//
+skipspace:
+	while (*script->script_p <= 32)
+	{
+		if (script->script_p >= script->end_p)
+			return EndOfScript (crossline);
+		if (*script->script_p++ == '\n')
+		{
+			if (!crossline)
+				Error ("Line %i is incomplete\n",scriptline);
+			script->line++;
+			scriptline = script->line;
+		}
+	}
+
+	if (script->script_p >= script->end_p)
+		return EndOfScript (crossline);
+
+	// ; # // comments
+	if (*script->script_p == ';' || *script->script_p == '#'
+		|| ( script->script_p[0] == '/' && script->script_p[1] == '/') )
+	{
+		if (!crossline)
+			Error ("Line %i is incomplete\n",scriptline);
+		while (*script->script_p++ != '\n')
+			if (script->script_p >= script->end_p)
+				return EndOfScript (crossline);
+		script->line++;
+		scriptline = script->line;
+		goto skipspace;
+	}
+
+	// /* */ comments
+	if (script->script_p[0] == '/' && script->script_p[1] == '*')
+	{
+		if (!crossline)
+			Error ("Line %i is incomplete\n",scriptline);
+		script->script_p+=2;
+		while (script->script_p[0] != '*' && script->script_p[1] != '/')
+		{
+			if ( *script->script_p == '\n' )
+			{
+				script->line++;
+				scriptline = script->line;
+			}
+			script->script_p++;
+			if (script->script_p >= script->end_p)
+				return EndOfScript (crossline);
+		}
+		script->script_p += 2;
+		goto skipspace;
+	}
+
+//
+// copy token
+//
+	token_p = token;
+
+	if (*script->script_p == '"')
+	{
+		// quoted token
+		script->script_p++;
+		while (*script->script_p != '"')
+		{
+			*token_p++ = *script->script_p++;
+			if (script->script_p == script->end_p)
+				break;
+			if (token_p == &token[MAXTOKEN])
+				Error ("Token too large on line %i\n",scriptline);
+		}
+		script->script_p++;
+	}
+	else	// regular token
+	while ( *script->script_p > 32 && *script->script_p != ';')
+	{
+		*token_p++ = *script->script_p++;
+		if (script->script_p == script->end_p)
+			break;
+		if (token_p == &token[MAXTOKEN])
+			Error ("Token too large on line %i\n",scriptline);
+	}
+
+	*token_p = 0;
+
+	if (!strcmp (token, "$include"))
+	{
+		GetToken (qfalse);
+		AddScriptToStack (token, 0);
+		return GetToken (crossline);
+	}
+
+	return qtrue;
+}
+
+
+/*
+==============
+TokenAvailable
+
+Returns qtrue if there is another token on the line
+==============
+*/
+qboolean TokenAvailable (void) {
+	int		oldLine, oldScriptLine;
+	qboolean	r;
+	
+	/* save */
+	oldLine = scriptline;
+	oldScriptLine = script->line;
+	
+	/* test */
+	r = GetToken( qtrue );
+	if ( !r ) {
+		return qfalse;
+	}
+	UnGetToken();
+	if ( oldLine == scriptline ) {
+		return qtrue;
+	}
+	
+	/* restore */
+	//%	scriptline = oldLine;
+	//%	script->line = oldScriptLine;
+
+	return qfalse;
+}
+
+
+//=====================================================================
+
+
+void MatchToken( char *match ) {
+	GetToken( qtrue );
+
+	if ( strcmp( token, match ) ) {
+		Error( "MatchToken( \"%s\" ) failed at line %i in file %s", match, scriptline, script->filename);
+	}
+}
+
+
+void Parse1DMatrix (int x, vec_t *m) {
+	int		i;
+
+	MatchToken( "(" );
+
+	for (i = 0 ; i < x ; i++) {
+		GetToken( qfalse );
+		m[i] = atof(token);
+	}
+
+	MatchToken( ")" );
+}
+
+void Parse2DMatrix (int y, int x, vec_t *m) {
+	int		i;
+
+	MatchToken( "(" );
+
+	for (i = 0 ; i < y ; i++) {
+		Parse1DMatrix (x, m + i * x);
+	}
+
+	MatchToken( ")" );
+}
+
+void Parse3DMatrix (int z, int y, int x, vec_t *m) {
+	int		i;
+
+	MatchToken( "(" );
+
+	for (i = 0 ; i < z ; i++) {
+		Parse2DMatrix (y, x, m + i * x*y);
+	}
+
+	MatchToken( ")" );
+}
+
+
+void Write1DMatrix (FILE *f, int x, vec_t *m) {
+	int		i;
+
+	fprintf (f, "( ");
+	for (i = 0 ; i < x ; i++) {
+		if (m[i] == (int)m[i] ) {
+			fprintf (f, "%i ", (int)m[i]);
+		} else {
+			fprintf (f, "%f ", m[i]);
+		}
+	}
+	fprintf (f, ")");
+}
+
+void Write2DMatrix (FILE *f, int y, int x, vec_t *m) {
+	int		i;
+
+	fprintf (f, "( ");
+	for (i = 0 ; i < y ; i++) {
+		Write1DMatrix (f, x, m + i*x);
+		fprintf (f, " ");
+	}
+	fprintf (f, ")\n");
+}
+
+
+void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m) {
+	int		i;
+
+	fprintf (f, "(\n");
+	for (i = 0 ; i < z ; i++) {
+		Write2DMatrix (f, y, x, m + i*(x*y) );
+	}
+	fprintf (f, ")\n");
+}
+
diff --git a/tools/quake3/common/scriplib.h b/tools/quake3/common/scriplib.h
index accc5a1c..e924e974 100644
--- a/tools/quake3/common/scriplib.h
+++ b/tools/quake3/common/scriplib.h
@@ -1,55 +1,55 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// scriplib.h
-
-#ifndef __CMDLIB__
-#include "../common/cmdlib.h"
-#endif
-#ifndef __MATHLIB__
-#include "mathlib.h"
-#endif
-
-#define	MAXTOKEN	1024
-
-extern	char	token[MAXTOKEN];
-extern	char	*scriptbuffer,*script_p,*scriptend_p;
-extern	int		grabbed;
-extern	int		scriptline;
-extern	qboolean	endofscript;
-
-
-void LoadScriptFile (const char *filename, int index);
-void ParseFromMemory (char *buffer, int size);
-
-qboolean GetToken (qboolean crossline);
-void UnGetToken (void);
-qboolean TokenAvailable (void);
-
-void MatchToken( char *match );
-
-void Parse1DMatrix (int x, vec_t *m);
-void Parse2DMatrix (int y, int x, vec_t *m);
-void Parse3DMatrix (int z, int y, int x, vec_t *m);
-
-void Write1DMatrix (FILE *f, int x, vec_t *m);
-void Write2DMatrix (FILE *f, int y, int x, vec_t *m);
-void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m);
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// scriplib.h
+
+#ifndef __CMDLIB__
+#include "../common/cmdlib.h"
+#endif
+#ifndef __MATHLIB__
+#include "mathlib.h"
+#endif
+
+#define	MAXTOKEN	1024
+
+extern	char	token[MAXTOKEN];
+extern	char	*scriptbuffer,*script_p,*scriptend_p;
+extern	int		grabbed;
+extern	int		scriptline;
+extern	qboolean	endofscript;
+
+
+void LoadScriptFile (const char *filename, int index);
+void ParseFromMemory (char *buffer, int size);
+
+qboolean GetToken (qboolean crossline);
+void UnGetToken (void);
+qboolean TokenAvailable (void);
+
+void MatchToken( char *match );
+
+void Parse1DMatrix (int x, vec_t *m);
+void Parse2DMatrix (int y, int x, vec_t *m);
+void Parse3DMatrix (int z, int y, int x, vec_t *m);
+
+void Write1DMatrix (FILE *f, int x, vec_t *m);
+void Write2DMatrix (FILE *f, int y, int x, vec_t *m);
+void Write3DMatrix (FILE *f, int z, int y, int x, vec_t *m);
diff --git a/tools/quake3/common/surfaceflags.h b/tools/quake3/common/surfaceflags.h
index cb8f045c..425e4f28 100644
--- a/tools/quake3/common/surfaceflags.h
+++ b/tools/quake3/common/surfaceflags.h
@@ -1,112 +1,112 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-// This file must be identical in the quake and utils directories
-
-// contents flags are seperate bits
-// a given brush can contribute multiple content bits
-
-// these definitions also need to be in q_shared.h!
-
-#define	CONTENTS_SOLID			1		// an eye is never valid in a solid
-#define	CONTENTS_LAVA			8
-#define	CONTENTS_SLIME			16
-#define	CONTENTS_WATER			32
-#define	CONTENTS_FOG			64
-
-#define	CONTENTS_AREAPORTAL		0x8000
-
-#define	CONTENTS_PLAYERCLIP		0x10000
-#define	CONTENTS_MONSTERCLIP	0x20000
-//bot specific contents types
-#define	CONTENTS_TELEPORTER		0x40000
-#define	CONTENTS_JUMPPAD		0x80000
-#define CONTENTS_CLUSTERPORTAL	0x100000
-#define CONTENTS_DONOTENTER		0x200000
-#define CONTENTS_BOTCLIP		0x400000
-
-#define	CONTENTS_ORIGIN			0x1000000	// removed before bsping an entity
-
-#define	CONTENTS_BODY			0x2000000	// should never be on a brush, only in game
-#define	CONTENTS_CORPSE			0x4000000
-#define	CONTENTS_DETAIL			0x8000000	// brushes not used for the bsp
-#define	CONTENTS_STRUCTURAL		0x10000000	// brushes used for the bsp
-#define	CONTENTS_TRANSLUCENT	0x20000000	// don't consume surface fragments inside
-#define	CONTENTS_TRIGGER		0x40000000
-#define	CONTENTS_NODROP			0x80000000	// don't leave bodies or items (death fog, lava)
-
-#define	SURF_NODAMAGE			0x1		// never give falling damage
-#define	SURF_SLICK				0x2		// effects game physics
-#define	SURF_SKY				0x4		// lighting from environment map
-#define	SURF_LADDER				0x8
-#define	SURF_NOIMPACT			0x10	// don't make missile explosions
-#define	SURF_NOMARKS			0x20	// don't leave missile marks
-#define	SURF_FLESH				0x40	// make flesh sounds and effects
-#define	SURF_NODRAW				0x80	// don't generate a drawsurface at all
-#define	SURF_HINT				0x100	// make a primary bsp splitter
-#define	SURF_SKIP				0x200	// completely ignore, allowing non-closed brushes
-#define	SURF_NOLIGHTMAP			0x400	// surface doesn't need a lightmap
-#define	SURF_POINTLIGHT			0x800	// generate lighting info at vertexes
-#define	SURF_METALSTEPS			0x1000	// clanking footsteps
-#define	SURF_NOSTEPS			0x2000	// no footstep sounds
-#define	SURF_NONSOLID			0x4000	// don't collide against curves with this set
-#define SURF_LIGHTFILTER		0x8000	// act as a light filter during q3map -light
-#define	SURF_ALPHASHADOW		0x10000	// do per-pixel light shadow casting in q3map
-#define	SURF_NODLIGHT			0x20000	// don't dlight even if solid (solid lava, skies)
-#define SURF_DUST				0x40000 // leave a dust trail when walking on this surface
-
-
-
-
-/* ydnar flags */
-
-#define CONTENTS_OPAQUE			0x02
-#define CONTENTS_LIGHTGRID		0x04
-
-#define SURF_VERTEXLIT			(SURF_POINTLIGHT | SURF_NOLIGHTMAP)
-
-
-
-/* wolfenstein flags (collisions with valid q3a flags are noted) */
-
-#define	CONTENTS_MISSILECLIP	0x80
-#define CONTENTS_ITEM			0x100
-#define	CONTENTS_AI_NOSIGHT		0x1000
-#define	CONTENTS_CLIPSHOT		0x2000
-#define CONTENTS_DONOTENTER_LARGE	0x400000	/* CONTENTS_BOTCLIP */
-
-#define SURF_CERAMIC			0x40			/* SURF_FLESH */
-#define	SURF_METAL  			0x1000			/* SURF_METALSTEPS */
-#define	SURF_WOOD				0x40000			/* SURF_DUST */
-#define	SURF_GRASS				0x80000
-#define SURF_GRAVEL				0x100000
-#define SURF_GLASS				0x200000
-#define SURF_SNOW				0x400000
-#define SURF_ROOF				0x800000
-#define	SURF_RUBBLE				0x1000000
-#define	SURF_CARPET				0x2000000
-#define SURF_MONSTERSLICK		0x4000000
-#define SURF_MONSLICK_W			0x8000000
-#define SURF_MONSLICK_N			0x10000000
-#define SURF_MONSLICK_E			0x20000000
-#define SURF_MONSLICK_S			0x40000000
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+// This file must be identical in the quake and utils directories
+
+// contents flags are seperate bits
+// a given brush can contribute multiple content bits
+
+// these definitions also need to be in q_shared.h!
+
+#define	CONTENTS_SOLID			1		// an eye is never valid in a solid
+#define	CONTENTS_LAVA			8
+#define	CONTENTS_SLIME			16
+#define	CONTENTS_WATER			32
+#define	CONTENTS_FOG			64
+
+#define	CONTENTS_AREAPORTAL		0x8000
+
+#define	CONTENTS_PLAYERCLIP		0x10000
+#define	CONTENTS_MONSTERCLIP	0x20000
+//bot specific contents types
+#define	CONTENTS_TELEPORTER		0x40000
+#define	CONTENTS_JUMPPAD		0x80000
+#define CONTENTS_CLUSTERPORTAL	0x100000
+#define CONTENTS_DONOTENTER		0x200000
+#define CONTENTS_BOTCLIP		0x400000
+
+#define	CONTENTS_ORIGIN			0x1000000	// removed before bsping an entity
+
+#define	CONTENTS_BODY			0x2000000	// should never be on a brush, only in game
+#define	CONTENTS_CORPSE			0x4000000
+#define	CONTENTS_DETAIL			0x8000000	// brushes not used for the bsp
+#define	CONTENTS_STRUCTURAL		0x10000000	// brushes used for the bsp
+#define	CONTENTS_TRANSLUCENT	0x20000000	// don't consume surface fragments inside
+#define	CONTENTS_TRIGGER		0x40000000
+#define	CONTENTS_NODROP			0x80000000	// don't leave bodies or items (death fog, lava)
+
+#define	SURF_NODAMAGE			0x1		// never give falling damage
+#define	SURF_SLICK				0x2		// effects game physics
+#define	SURF_SKY				0x4		// lighting from environment map
+#define	SURF_LADDER				0x8
+#define	SURF_NOIMPACT			0x10	// don't make missile explosions
+#define	SURF_NOMARKS			0x20	// don't leave missile marks
+#define	SURF_FLESH				0x40	// make flesh sounds and effects
+#define	SURF_NODRAW				0x80	// don't generate a drawsurface at all
+#define	SURF_HINT				0x100	// make a primary bsp splitter
+#define	SURF_SKIP				0x200	// completely ignore, allowing non-closed brushes
+#define	SURF_NOLIGHTMAP			0x400	// surface doesn't need a lightmap
+#define	SURF_POINTLIGHT			0x800	// generate lighting info at vertexes
+#define	SURF_METALSTEPS			0x1000	// clanking footsteps
+#define	SURF_NOSTEPS			0x2000	// no footstep sounds
+#define	SURF_NONSOLID			0x4000	// don't collide against curves with this set
+#define SURF_LIGHTFILTER		0x8000	// act as a light filter during q3map -light
+#define	SURF_ALPHASHADOW		0x10000	// do per-pixel light shadow casting in q3map
+#define	SURF_NODLIGHT			0x20000	// don't dlight even if solid (solid lava, skies)
+#define SURF_DUST				0x40000 // leave a dust trail when walking on this surface
+
+
+
+
+/* ydnar flags */
+
+#define CONTENTS_OPAQUE			0x02
+#define CONTENTS_LIGHTGRID		0x04
+
+#define SURF_VERTEXLIT			(SURF_POINTLIGHT | SURF_NOLIGHTMAP)
+
+
+
+/* wolfenstein flags (collisions with valid q3a flags are noted) */
+
+#define	CONTENTS_MISSILECLIP	0x80
+#define CONTENTS_ITEM			0x100
+#define	CONTENTS_AI_NOSIGHT		0x1000
+#define	CONTENTS_CLIPSHOT		0x2000
+#define CONTENTS_DONOTENTER_LARGE	0x400000	/* CONTENTS_BOTCLIP */
+
+#define SURF_CERAMIC			0x40			/* SURF_FLESH */
+#define	SURF_METAL  			0x1000			/* SURF_METALSTEPS */
+#define	SURF_WOOD				0x40000			/* SURF_DUST */
+#define	SURF_GRASS				0x80000
+#define SURF_GRAVEL				0x100000
+#define SURF_GLASS				0x200000
+#define SURF_SNOW				0x400000
+#define SURF_ROOF				0x800000
+#define	SURF_RUBBLE				0x1000000
+#define	SURF_CARPET				0x2000000
+#define SURF_MONSTERSLICK		0x4000000
+#define SURF_MONSLICK_W			0x8000000
+#define SURF_MONSLICK_N			0x10000000
+#define SURF_MONSLICK_E			0x20000000
+#define SURF_MONSLICK_S			0x40000000
+
+
diff --git a/tools/quake3/common/threads.c b/tools/quake3/common/threads.c
index 49ded171..463d32bd 100644
--- a/tools/quake3/common/threads.c
+++ b/tools/quake3/common/threads.c
@@ -1,620 +1,620 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#ifndef _WIN32
-// The below define is necessary to use
-// pthreads extensions like pthread_mutexattr_settype
-#define _GNU_SOURCE
-#include <pthread.h>
-#endif
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "inout.h"
-#include "qthreads.h"
-
-#define	MAX_THREADS	64
-
-int		dispatch;
-int		workcount;
-int		oldf;
-qboolean		pacifier;
-
-qboolean	threaded;
-
-/*
-=============
-GetThreadWork
-
-=============
-*/
-int	GetThreadWork (void)
-{
-	int	r;
-	int	f;
-
-	ThreadLock ();
-
-	if (dispatch == workcount)
-	{
-		ThreadUnlock ();
-		return -1;
-	}
-
-	f = 10*dispatch / workcount;
-	if (f != oldf)
-	{
-		oldf = f;
-		if (pacifier)
-		{
-			Sys_Printf ("%i...", f);
-			fflush( stdout );	/* ydnar */
-		}
-	}
-
-	r = dispatch;
-	dispatch++;
-	ThreadUnlock ();
-
-	return r;
-}
-
-
-void (*workfunction) (int);
-
-void ThreadWorkerFunction (int threadnum)
-{
-	int		work;
-
-	while (1)
-	{
-		work = GetThreadWork ();
-		if (work == -1)
-			break;
-//Sys_Printf ("thread %i, work %i\n", threadnum, work);
-		workfunction(work);
-	}
-}
-
-void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	if (numthreads == -1)
-		ThreadSetDefault ();
-	workfunction = func;
-  RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
-}
-
-
-/*
-===================================================================
-
-WIN32
-
-===================================================================
-*/
-#ifdef _WIN32
-
-#define	USED
-
-#include <windows.h>
-
-int		numthreads = -1;
-CRITICAL_SECTION		crit;
-static int enter;
-
-void ThreadSetDefault (void)
-{
-	SYSTEM_INFO info;
-
-	if (numthreads == -1)	// not set manually
-	{
-		GetSystemInfo (&info);
-		numthreads = info.dwNumberOfProcessors;
-		if (numthreads < 1 || numthreads > 32)
-			numthreads = 1;
-	}
-
-	Sys_Printf ("%i threads\n", numthreads);
-}
-
-
-void ThreadLock (void)
-{
-	if (!threaded)
-		return;
-	EnterCriticalSection (&crit);
-	if (enter)
-		Error ("Recursive ThreadLock\n");
-	enter = 1;
-}
-
-void ThreadUnlock (void)
-{
-	if (!threaded)
-		return;
-	if (!enter)
-		Error ("ThreadUnlock without lock\n");
-	enter = 0;
-	LeaveCriticalSection (&crit);
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		threadid[MAX_THREADS];
-	HANDLE	threadhandle[MAX_THREADS];
-	int		i;
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = qtrue;
-
-	//
-	// run threads in parallel
-	//
-	InitializeCriticalSection (&crit);
-
-	if (numthreads == 1)
-	{	// use same thread
-		func (0);
-	}
-	else
-	{
-		for (i=0 ; i<numthreads ; i++)
-		{
-			threadhandle[i] = CreateThread(
-			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
-			   //0,		// DWORD cbStack,
-
-				/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
-				(4096 * 1024),
-
-			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
-			   (LPVOID)i,	// LPVOID lpvThreadParm,
-			   0,			//   DWORD fdwCreate,
-			   &threadid[i]);
-		}
-
-		for (i=0 ; i<numthreads ; i++)
-			WaitForSingleObject (threadhandle[i], INFINITE);
-	}
-	DeleteCriticalSection (&crit);
-
-	threaded = qfalse;
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-/*
-===================================================================
-
-OSF1
-
-===================================================================
-*/
-
-#ifdef __osf__
-#define	USED
-
-int		numthreads = 4;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)	// not set manually
-	{
-		numthreads = 4;
-	}
-}
-
-
-#include <pthread.h>
-
-pthread_mutex_t	*my_mutex;
-
-void ThreadLock (void)
-{
-	if (my_mutex)
-		pthread_mutex_lock (my_mutex);
-}
-
-void ThreadUnlock (void)
-{
-	if (my_mutex)
-		pthread_mutex_unlock (my_mutex);
-}
-
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	pthread_t	work_threads[MAX_THREADS];
-	pthread_addr_t	status;
-	pthread_attr_t	attrib;
-	pthread_mutexattr_t	mattrib;
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = qtrue;
-
-	if (pacifier)
-		setbuf (stdout, NULL);
-
-	if (!my_mutex)
-	{
-		my_mutex = safe_malloc (sizeof(*my_mutex));
-		if (pthread_mutexattr_create (&mattrib) == -1)
-			Error ("pthread_mutex_attr_create failed");
-		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
-			Error ("pthread_mutexattr_setkind_np failed");
-		if (pthread_mutex_init (my_mutex, mattrib) == -1)
-			Error ("pthread_mutex_init failed");
-	}
-
-	if (pthread_attr_create (&attrib) == -1)
-		Error ("pthread_attr_create failed");
-	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
-		Error ("pthread_attr_setstacksize failed");
-	
-	for (i=0 ; i<numthreads ; i++)
-	{
-  		if (pthread_create(&work_threads[i], attrib
-		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
-			Error ("pthread_create failed");
-	}
-		
-	for (i=0 ; i<numthreads ; i++)
-	{
-		if (pthread_join (work_threads[i], &status) == -1)
-			Error ("pthread_join failed");
-	}
-
-	threaded = qfalse;
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-/*
-===================================================================
-
-IRIX
-
-===================================================================
-*/
-
-#ifdef _MIPS_ISA 
-#define	USED
-
-#include <task.h>
-#include <abi_mutex.h>
-#include <sys/types.h>
-#include <sys/prctl.h>
-
-
-int		numthreads = -1;
-abilock_t		lck;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)
-		numthreads = prctl(PR_MAXPPROCS);
-	Sys_Printf ("%i threads\n", numthreads);
-	usconfig (CONF_INITUSERS, numthreads);
-}
-
-
-void ThreadLock (void)
-{
-	spin_lock (&lck);
-}
-
-void ThreadUnlock (void)
-{
-	release_lock (&lck);
-}
-
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	int		pid[MAX_THREADS];
-	int		start, end;
-
-	start = I_FloatTime ();
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	threaded = qtrue;
-
-	if (pacifier)
-		setbuf (stdout, NULL);
-
-	init_lock (&lck);
-
-	for (i=0 ; i<numthreads-1 ; i++)
-	{
-		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
-			, NULL, 0x200000);		// 2 meg stacks
-		if (pid[i] == -1)
-		{
-			perror ("sproc");
-			Error ("sproc failed");
-		}
-	}
-		
-	func(i);
-			
-	for (i=0 ; i<numthreads-1 ; i++)
-		wait (NULL);
-
-	threaded = qfalse;
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-
-#endif
-
-
-/*
-=======================================================================
-
-  Linux pthreads
-
-=======================================================================
-*/
-
-#ifdef __linux__
-#define USED
-
-int numthreads = 4;
-
-void ThreadSetDefault (void)
-{
-	if (numthreads == -1)	// not set manually
-	{
-    /* default to one thread, only multi-thread when specifically told to */
-		numthreads = 1;
-	}
-  if(numthreads > 1)
-    Sys_Printf("threads: %d\n", numthreads);
-}
-
-#include <pthread.h>
-
-typedef struct pt_mutex_s
-{
-  pthread_t       *owner;
-  pthread_mutex_t a_mutex;
-  pthread_cond_t  cond;
-  unsigned int    lock;
-} pt_mutex_t;
-
-pt_mutex_t global_lock;
-
-void ThreadLock(void)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-
-  if(!threaded)
-    return;
-
-  pthread_mutex_lock(&pt_mutex->a_mutex);
-  if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner)) 
-    pt_mutex->lock++;
-  else
-  {
-    if((!pt_mutex->owner) && (pt_mutex->lock == 0))
-    {
-      pt_mutex->owner = (pthread_t *)pthread_self();
-      pt_mutex->lock  = 1;
-    }
-    else
-    {
-      while(1)
-      {
-        pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
-        if((!pt_mutex->owner) && (pt_mutex->lock == 0))
-        {
-          pt_mutex->owner = (pthread_t *)pthread_self();
-          pt_mutex->lock  = 1;
-          break;
-        }
-      }
-    }
-  }
-  pthread_mutex_unlock(&pt_mutex->a_mutex);
-}
-
-void ThreadUnlock(void)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-  
-  if(!threaded)
-    return;
-
-  pthread_mutex_lock(&pt_mutex->a_mutex);
-  pt_mutex->lock--;
-  
-  if(pt_mutex->lock == 0)
-  {
-    pt_mutex->owner = NULL;
-    pthread_cond_signal(&pt_mutex->cond);
-  }
-  
-  pthread_mutex_unlock(&pt_mutex->a_mutex);
-}
-
-void recursive_mutex_init(pthread_mutexattr_t attribs)
-{
-  pt_mutex_t *pt_mutex = &global_lock;
-  
-  pt_mutex->owner = NULL;
-  if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
-    Error("pthread_mutex_init failed\n");
-  if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
-    Error("pthread_cond_init failed\n");
-  
-  pt_mutex->lock = 0;
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-  pthread_mutexattr_t         mattrib;
-  pthread_t work_threads[MAX_THREADS];
-  
-  int	  start, end;
-  int   i=0, status=0;
-  
-  start     = I_FloatTime ();
-  pacifier  = showpacifier;
-  
-  dispatch  = 0;
-  oldf      = -1;
-  workcount = workcnt;
-  
-  if(numthreads == 1)
-    func(0);
-  else
-  {    
-    threaded  = qtrue;
-      
-    if(pacifier)
-      setbuf(stdout, NULL);
-
-    if(pthread_mutexattr_init(&mattrib) != 0)
-      Error("pthread_mutexattr_init failed");
-#if __GLIBC_MINOR__ == 1
-    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
-#else
-    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
-#endif
-      Error ("pthread_mutexattr_settype failed");
-    recursive_mutex_init(mattrib);
-
-    for (i=0 ; i<numthreads ; i++)
-    {
-      /* Default pthread attributes: joinable & non-realtime scheduling */
-      if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
-        Error("pthread_create failed");
-    }
-    for (i=0 ; i<numthreads ; i++)
-    {
-      if(pthread_join(work_threads[i], (void **)&status) != 0)
-        Error("pthread_join failed");
-    }
-    pthread_mutexattr_destroy(&mattrib);
-    threaded = qfalse;
-  }
-  
-  end = I_FloatTime ();
-  if (pacifier)
-    Sys_Printf (" (%i)\n", end-start);
-}
-#endif // ifdef __linux__
-
-
-/*
-=======================================================================
-
-  SINGLE THREAD
-
-=======================================================================
-*/
-
-#ifndef USED
-
-int		numthreads = 1;
-
-void ThreadSetDefault (void)
-{
-	numthreads = 1;
-}
-
-void ThreadLock (void)
-{
-}
-
-void ThreadUnlock (void)
-{
-}
-
-/*
-=============
-RunThreadsOn
-=============
-*/
-void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
-{
-	int		i;
-	int		start, end;
-
-	dispatch = 0;
-	workcount = workcnt;
-	oldf = -1;
-	pacifier = showpacifier;
-	start = I_FloatTime (); 
-	func(0);
-
-	end = I_FloatTime ();
-	if (pacifier)
-		Sys_Printf (" (%i)\n", end-start);
-}
-
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#ifndef _WIN32
+// The below define is necessary to use
+// pthreads extensions like pthread_mutexattr_settype
+#define _GNU_SOURCE
+#include <pthread.h>
+#endif
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "inout.h"
+#include "qthreads.h"
+
+#define	MAX_THREADS	64
+
+int		dispatch;
+int		workcount;
+int		oldf;
+qboolean		pacifier;
+
+qboolean	threaded;
+
+/*
+=============
+GetThreadWork
+
+=============
+*/
+int	GetThreadWork (void)
+{
+	int	r;
+	int	f;
+
+	ThreadLock ();
+
+	if (dispatch == workcount)
+	{
+		ThreadUnlock ();
+		return -1;
+	}
+
+	f = 10*dispatch / workcount;
+	if (f != oldf)
+	{
+		oldf = f;
+		if (pacifier)
+		{
+			Sys_Printf ("%i...", f);
+			fflush( stdout );	/* ydnar */
+		}
+	}
+
+	r = dispatch;
+	dispatch++;
+	ThreadUnlock ();
+
+	return r;
+}
+
+
+void (*workfunction) (int);
+
+void ThreadWorkerFunction (int threadnum)
+{
+	int		work;
+
+	while (1)
+	{
+		work = GetThreadWork ();
+		if (work == -1)
+			break;
+//Sys_Printf ("thread %i, work %i\n", threadnum, work);
+		workfunction(work);
+	}
+}
+
+void RunThreadsOnIndividual (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	if (numthreads == -1)
+		ThreadSetDefault ();
+	workfunction = func;
+  RunThreadsOn (workcnt, showpacifier, ThreadWorkerFunction);
+}
+
+
+/*
+===================================================================
+
+WIN32
+
+===================================================================
+*/
+#ifdef _WIN32
+
+#define	USED
+
+#include <windows.h>
+
+int		numthreads = -1;
+CRITICAL_SECTION		crit;
+static int enter;
+
+void ThreadSetDefault (void)
+{
+	SYSTEM_INFO info;
+
+	if (numthreads == -1)	// not set manually
+	{
+		GetSystemInfo (&info);
+		numthreads = info.dwNumberOfProcessors;
+		if (numthreads < 1 || numthreads > 32)
+			numthreads = 1;
+	}
+
+	Sys_Printf ("%i threads\n", numthreads);
+}
+
+
+void ThreadLock (void)
+{
+	if (!threaded)
+		return;
+	EnterCriticalSection (&crit);
+	if (enter)
+		Error ("Recursive ThreadLock\n");
+	enter = 1;
+}
+
+void ThreadUnlock (void)
+{
+	if (!threaded)
+		return;
+	if (!enter)
+		Error ("ThreadUnlock without lock\n");
+	enter = 0;
+	LeaveCriticalSection (&crit);
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		threadid[MAX_THREADS];
+	HANDLE	threadhandle[MAX_THREADS];
+	int		i;
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = qtrue;
+
+	//
+	// run threads in parallel
+	//
+	InitializeCriticalSection (&crit);
+
+	if (numthreads == 1)
+	{	// use same thread
+		func (0);
+	}
+	else
+	{
+		for (i=0 ; i<numthreads ; i++)
+		{
+			threadhandle[i] = CreateThread(
+			   NULL,	// LPSECURITY_ATTRIBUTES lpsa,
+			   //0,		// DWORD cbStack,
+
+				/* ydnar: cranking stack size to eliminate radiosity crash with 1MB stack on win32 */
+				(4096 * 1024),
+
+			   (LPTHREAD_START_ROUTINE)func,	// LPTHREAD_START_ROUTINE lpStartAddr,
+			   (LPVOID)i,	// LPVOID lpvThreadParm,
+			   0,			//   DWORD fdwCreate,
+			   &threadid[i]);
+		}
+
+		for (i=0 ; i<numthreads ; i++)
+			WaitForSingleObject (threadhandle[i], INFINITE);
+	}
+	DeleteCriticalSection (&crit);
+
+	threaded = qfalse;
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+/*
+===================================================================
+
+OSF1
+
+===================================================================
+*/
+
+#ifdef __osf__
+#define	USED
+
+int		numthreads = 4;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)	// not set manually
+	{
+		numthreads = 4;
+	}
+}
+
+
+#include <pthread.h>
+
+pthread_mutex_t	*my_mutex;
+
+void ThreadLock (void)
+{
+	if (my_mutex)
+		pthread_mutex_lock (my_mutex);
+}
+
+void ThreadUnlock (void)
+{
+	if (my_mutex)
+		pthread_mutex_unlock (my_mutex);
+}
+
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	pthread_t	work_threads[MAX_THREADS];
+	pthread_addr_t	status;
+	pthread_attr_t	attrib;
+	pthread_mutexattr_t	mattrib;
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = qtrue;
+
+	if (pacifier)
+		setbuf (stdout, NULL);
+
+	if (!my_mutex)
+	{
+		my_mutex = safe_malloc (sizeof(*my_mutex));
+		if (pthread_mutexattr_create (&mattrib) == -1)
+			Error ("pthread_mutex_attr_create failed");
+		if (pthread_mutexattr_setkind_np (&mattrib, MUTEX_FAST_NP) == -1)
+			Error ("pthread_mutexattr_setkind_np failed");
+		if (pthread_mutex_init (my_mutex, mattrib) == -1)
+			Error ("pthread_mutex_init failed");
+	}
+
+	if (pthread_attr_create (&attrib) == -1)
+		Error ("pthread_attr_create failed");
+	if (pthread_attr_setstacksize (&attrib, 0x100000) == -1)
+		Error ("pthread_attr_setstacksize failed");
+	
+	for (i=0 ; i<numthreads ; i++)
+	{
+  		if (pthread_create(&work_threads[i], attrib
+		, (pthread_startroutine_t)func, (pthread_addr_t)i) == -1)
+			Error ("pthread_create failed");
+	}
+		
+	for (i=0 ; i<numthreads ; i++)
+	{
+		if (pthread_join (work_threads[i], &status) == -1)
+			Error ("pthread_join failed");
+	}
+
+	threaded = qfalse;
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+/*
+===================================================================
+
+IRIX
+
+===================================================================
+*/
+
+#ifdef _MIPS_ISA 
+#define	USED
+
+#include <task.h>
+#include <abi_mutex.h>
+#include <sys/types.h>
+#include <sys/prctl.h>
+
+
+int		numthreads = -1;
+abilock_t		lck;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)
+		numthreads = prctl(PR_MAXPPROCS);
+	Sys_Printf ("%i threads\n", numthreads);
+	usconfig (CONF_INITUSERS, numthreads);
+}
+
+
+void ThreadLock (void)
+{
+	spin_lock (&lck);
+}
+
+void ThreadUnlock (void)
+{
+	release_lock (&lck);
+}
+
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	int		pid[MAX_THREADS];
+	int		start, end;
+
+	start = I_FloatTime ();
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	threaded = qtrue;
+
+	if (pacifier)
+		setbuf (stdout, NULL);
+
+	init_lock (&lck);
+
+	for (i=0 ; i<numthreads-1 ; i++)
+	{
+		pid[i] = sprocsp ( (void (*)(void *, size_t))func, PR_SALL, (void *)i
+			, NULL, 0x200000);		// 2 meg stacks
+		if (pid[i] == -1)
+		{
+			perror ("sproc");
+			Error ("sproc failed");
+		}
+	}
+		
+	func(i);
+			
+	for (i=0 ; i<numthreads-1 ; i++)
+		wait (NULL);
+
+	threaded = qfalse;
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+
+#endif
+
+
+/*
+=======================================================================
+
+  Linux pthreads
+
+=======================================================================
+*/
+
+#ifdef __linux__
+#define USED
+
+int numthreads = 4;
+
+void ThreadSetDefault (void)
+{
+	if (numthreads == -1)	// not set manually
+	{
+    /* default to one thread, only multi-thread when specifically told to */
+		numthreads = 1;
+	}
+  if(numthreads > 1)
+    Sys_Printf("threads: %d\n", numthreads);
+}
+
+#include <pthread.h>
+
+typedef struct pt_mutex_s
+{
+  pthread_t       *owner;
+  pthread_mutex_t a_mutex;
+  pthread_cond_t  cond;
+  unsigned int    lock;
+} pt_mutex_t;
+
+pt_mutex_t global_lock;
+
+void ThreadLock(void)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+
+  if(!threaded)
+    return;
+
+  pthread_mutex_lock(&pt_mutex->a_mutex);
+  if(pthread_equal(pthread_self(), (pthread_t)&pt_mutex->owner)) 
+    pt_mutex->lock++;
+  else
+  {
+    if((!pt_mutex->owner) && (pt_mutex->lock == 0))
+    {
+      pt_mutex->owner = (pthread_t *)pthread_self();
+      pt_mutex->lock  = 1;
+    }
+    else
+    {
+      while(1)
+      {
+        pthread_cond_wait(&pt_mutex->cond, &pt_mutex->a_mutex);
+        if((!pt_mutex->owner) && (pt_mutex->lock == 0))
+        {
+          pt_mutex->owner = (pthread_t *)pthread_self();
+          pt_mutex->lock  = 1;
+          break;
+        }
+      }
+    }
+  }
+  pthread_mutex_unlock(&pt_mutex->a_mutex);
+}
+
+void ThreadUnlock(void)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+  
+  if(!threaded)
+    return;
+
+  pthread_mutex_lock(&pt_mutex->a_mutex);
+  pt_mutex->lock--;
+  
+  if(pt_mutex->lock == 0)
+  {
+    pt_mutex->owner = NULL;
+    pthread_cond_signal(&pt_mutex->cond);
+  }
+  
+  pthread_mutex_unlock(&pt_mutex->a_mutex);
+}
+
+void recursive_mutex_init(pthread_mutexattr_t attribs)
+{
+  pt_mutex_t *pt_mutex = &global_lock;
+  
+  pt_mutex->owner = NULL;
+  if(pthread_mutex_init(&pt_mutex->a_mutex, &attribs) != 0)
+    Error("pthread_mutex_init failed\n");
+  if(pthread_cond_init(&pt_mutex->cond, NULL) != 0)
+    Error("pthread_cond_init failed\n");
+  
+  pt_mutex->lock = 0;
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+  pthread_mutexattr_t         mattrib;
+  pthread_t work_threads[MAX_THREADS];
+  
+  int	  start, end;
+  int   i=0, status=0;
+  
+  start     = I_FloatTime ();
+  pacifier  = showpacifier;
+  
+  dispatch  = 0;
+  oldf      = -1;
+  workcount = workcnt;
+  
+  if(numthreads == 1)
+    func(0);
+  else
+  {    
+    threaded  = qtrue;
+      
+    if(pacifier)
+      setbuf(stdout, NULL);
+
+    if(pthread_mutexattr_init(&mattrib) != 0)
+      Error("pthread_mutexattr_init failed");
+#if __GLIBC_MINOR__ == 1
+    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_FAST_NP) != 0)
+#else
+    if (pthread_mutexattr_settype(&mattrib, PTHREAD_MUTEX_ADAPTIVE_NP) != 0)
+#endif
+      Error ("pthread_mutexattr_settype failed");
+    recursive_mutex_init(mattrib);
+
+    for (i=0 ; i<numthreads ; i++)
+    {
+      /* Default pthread attributes: joinable & non-realtime scheduling */
+      if(pthread_create(&work_threads[i], NULL, (void*)func, (void*)i) != 0)
+        Error("pthread_create failed");
+    }
+    for (i=0 ; i<numthreads ; i++)
+    {
+      if(pthread_join(work_threads[i], (void **)&status) != 0)
+        Error("pthread_join failed");
+    }
+    pthread_mutexattr_destroy(&mattrib);
+    threaded = qfalse;
+  }
+  
+  end = I_FloatTime ();
+  if (pacifier)
+    Sys_Printf (" (%i)\n", end-start);
+}
+#endif // ifdef __linux__
+
+
+/*
+=======================================================================
+
+  SINGLE THREAD
+
+=======================================================================
+*/
+
+#ifndef USED
+
+int		numthreads = 1;
+
+void ThreadSetDefault (void)
+{
+	numthreads = 1;
+}
+
+void ThreadLock (void)
+{
+}
+
+void ThreadUnlock (void)
+{
+}
+
+/*
+=============
+RunThreadsOn
+=============
+*/
+void RunThreadsOn (int workcnt, qboolean showpacifier, void(*func)(int))
+{
+	int		i;
+	int		start, end;
+
+	dispatch = 0;
+	workcount = workcnt;
+	oldf = -1;
+	pacifier = showpacifier;
+	start = I_FloatTime (); 
+	func(0);
+
+	end = I_FloatTime ();
+	if (pacifier)
+		Sys_Printf (" (%i)\n", end-start);
+}
+
+#endif
diff --git a/tools/quake3/common/trilib.c b/tools/quake3/common/trilib.c
index 89978949..9726569e 100644
--- a/tools/quake3/common/trilib.c
+++ b/tools/quake3/common/trilib.c
@@ -1,235 +1,235 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// trilib.c: library for loading triangles from an Alias triangle file
-//
-
-#include <stdio.h>
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "polyset.h"
-#include "trilib.h"
-
-// on disk representation of a face
-
-
-#define	FLOAT_START	99999.0
-#define	FLOAT_END	-FLOAT_START
-#define MAGIC       123322
-
-//#define NOISY 1
-
-#if defined (__linux__) || defined (__APPLE__)
-#define strlwr strlower
-#endif
-
-typedef struct {
-	float v[3];
-} vector;
-
-typedef struct
-{
-	vector n;    /* normal */
-	vector p;    /* point */
-	vector c;    /* color */
-	float  u;    /* u */
-	float  v;    /* v */
-} aliaspoint_t;
-
-typedef struct {
-	aliaspoint_t	pt[3];
-} tf_triangle;
-
-
-static void ByteSwapTri (tf_triangle *tri)
-{
-	int		i;
-	
-	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
-	{
-		((int *)tri)[i] = BigLong (((int *)tri)[i]);
-	}
-}
-
-static void ReadPolysetGeometry( triangle_t *tripool, FILE *input, int count, triangle_t *ptri )
-{
-	tf_triangle tri;
-	int i;
-
-	for (i = 0; i < count; ++i) {
-		int		j;
-
-		fread( &tri, sizeof(tf_triangle), 1, input );
-		ByteSwapTri (&tri);
-		for (j=0 ; j<3 ; j++)
-		{
-			int		k;
-
-			for (k=0 ; k<3 ; k++)
-			{
-				ptri->verts[j][k] = tri.pt[j].p.v[k];
-				ptri->normals[j][k] = tri.pt[j].n.v[k];
-//				ptri->colors[j][k] = tri.pt[j].c.v[k];
-			}
-
-			ptri->texcoords[j][0] = tri.pt[j].u;
-			ptri->texcoords[j][1] = tri.pt[j].v;
-		}
-
-		ptri++;
-		if ((ptri - tripool ) >= POLYSET_MAXTRIANGLES)
-			Error ("Error: too many triangles; increase POLYSET_MAXTRIANGLES\n");
-	}
-}
-
-void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets )
-{
-	FILE        *input;
-	float       start;
-	char        name[256], tex[256];
-	int         i, count, magic, pset = 0;
-	triangle_t	*ptri;
-	polyset_t	*pPSET;
-	int			iLevel;
-	int			exitpattern;
-	float		t;
-
-	t = -FLOAT_START;
-	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
-	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
-	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
-	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
-
-	if ((input = fopen(filename, "rb")) == 0)
-		Error ("reader: could not open file '%s'", filename);
-
-	iLevel = 0;
-
-	fread(&magic, sizeof(int), 1, input);
-	if (BigLong(magic) != MAGIC)
-		Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
-
-	pPSET = calloc( 1, POLYSET_MAXPOLYSETS * sizeof( polyset_t ) );
-	ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
-
-	*ppPSET = pPSET;
-
-	while (feof(input) == 0) {
-		if (fread(&start,  sizeof(float), 1, input) < 1)
-			break;
-		*(int *)&start = BigLong(*(int *)&start);
-		if (*(int *)&start != exitpattern)
-		{
-			if (start == FLOAT_START) {
-				/* Start of an object or group of objects. */
-				i = -1;
-				do {
-					/* There are probably better ways to read a string from */
-					/* a file, but this does allow you to do error checking */
-					/* (which I'm not doing) on a per character basis.      */
-					++i;
-					fread( &(name[i]), sizeof( char ), 1, input);
-				} while( name[i] != '\0' );
-	
-				if ( i != 0 )
-					strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
-				else
-					strcpy( pPSET[pset].name , "(unnamed)" );
-				strlwr( pPSET[pset].name );
-
-//				indent();
-//				fprintf(stdout,"OBJECT START: %s\n",name);
-				fread( &count, sizeof(int), 1, input);
-				count = BigLong(count);
-				++iLevel;
-				if (count != 0) {
-//					indent();
-//					fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
-	
-					i = -1;
-					do {
-						++i;
-						fread( &(tex[i]), sizeof( char ), 1, input);
-					} while( tex[i] != '\0' );
-
-/*
-					if ( i != 0 )
-						strncpy( pPSET[pset].texname, tex, sizeof( pPSET[pset].texname ) - 1 );
-					else
-						strcpy( pPSET[pset].texname, "(unnamed)" );
-					strlwr( pPSET[pset].texname );
-*/
-
-//					indent();
-//					fprintf(stdout,"  Object texture name: '%s'\n",tex);
-				}
-	
-				/* Else (count == 0) this is the start of a group, and */
-				/* no texture name is present. */
-			}
-			else if (start == FLOAT_END) {
-				/* End of an object or group. Yes, the name should be */
-				/* obvious from context, but it is in here just to be */
-				/* safe and to provide a little extra information for */
-				/* those who do not wish to write a recursive reader. */
-				/* Mea culpa. */
-				--iLevel;
-				i = -1;
-				do {
-					++i;
-					fread( &(name[i]), sizeof( char ), 1, input);
-				} while( name[i] != '\0' );
-
-				if ( i != 0 )
-					strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
-				else
-					strcpy( pPSET[pset].name , "(unnamed)" );
-
-				strlwr( pPSET[pset].name );
-	
-//				indent();
-//				fprintf(stdout,"OBJECT END: %s\n",name);
-				continue;
-			}
-		}
-
-//
-// read the triangles
-//		
-		if ( count > 0 )
-		{
-			pPSET[pset].triangles = ptri;
-			ReadPolysetGeometry( pPSET[0].triangles, input, count, ptri );
-			ptri += count;
-			pPSET[pset].numtriangles = count;
-			if ( ++pset >= POLYSET_MAXPOLYSETS )
-			{
-				Error ("Error: too many polysets; increase POLYSET_MAXPOLYSETS\n");
-			}
-		}
-	}
-
-	*numpsets = pset;
-
-	fclose (input);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// trilib.c: library for loading triangles from an Alias triangle file
+//
+
+#include <stdio.h>
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "polyset.h"
+#include "trilib.h"
+
+// on disk representation of a face
+
+
+#define	FLOAT_START	99999.0
+#define	FLOAT_END	-FLOAT_START
+#define MAGIC       123322
+
+//#define NOISY 1
+
+#if defined (__linux__) || defined (__APPLE__)
+#define strlwr strlower
+#endif
+
+typedef struct {
+	float v[3];
+} vector;
+
+typedef struct
+{
+	vector n;    /* normal */
+	vector p;    /* point */
+	vector c;    /* color */
+	float  u;    /* u */
+	float  v;    /* v */
+} aliaspoint_t;
+
+typedef struct {
+	aliaspoint_t	pt[3];
+} tf_triangle;
+
+
+static void ByteSwapTri (tf_triangle *tri)
+{
+	int		i;
+	
+	for (i=0 ; i<sizeof(tf_triangle)/4 ; i++)
+	{
+		((int *)tri)[i] = BigLong (((int *)tri)[i]);
+	}
+}
+
+static void ReadPolysetGeometry( triangle_t *tripool, FILE *input, int count, triangle_t *ptri )
+{
+	tf_triangle tri;
+	int i;
+
+	for (i = 0; i < count; ++i) {
+		int		j;
+
+		fread( &tri, sizeof(tf_triangle), 1, input );
+		ByteSwapTri (&tri);
+		for (j=0 ; j<3 ; j++)
+		{
+			int		k;
+
+			for (k=0 ; k<3 ; k++)
+			{
+				ptri->verts[j][k] = tri.pt[j].p.v[k];
+				ptri->normals[j][k] = tri.pt[j].n.v[k];
+//				ptri->colors[j][k] = tri.pt[j].c.v[k];
+			}
+
+			ptri->texcoords[j][0] = tri.pt[j].u;
+			ptri->texcoords[j][1] = tri.pt[j].v;
+		}
+
+		ptri++;
+		if ((ptri - tripool ) >= POLYSET_MAXTRIANGLES)
+			Error ("Error: too many triangles; increase POLYSET_MAXTRIANGLES\n");
+	}
+}
+
+void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets )
+{
+	FILE        *input;
+	float       start;
+	char        name[256], tex[256];
+	int         i, count, magic, pset = 0;
+	triangle_t	*ptri;
+	polyset_t	*pPSET;
+	int			iLevel;
+	int			exitpattern;
+	float		t;
+
+	t = -FLOAT_START;
+	*((unsigned char *)&exitpattern + 0) = *((unsigned char *)&t + 3);
+	*((unsigned char *)&exitpattern + 1) = *((unsigned char *)&t + 2);
+	*((unsigned char *)&exitpattern + 2) = *((unsigned char *)&t + 1);
+	*((unsigned char *)&exitpattern + 3) = *((unsigned char *)&t + 0);
+
+	if ((input = fopen(filename, "rb")) == 0)
+		Error ("reader: could not open file '%s'", filename);
+
+	iLevel = 0;
+
+	fread(&magic, sizeof(int), 1, input);
+	if (BigLong(magic) != MAGIC)
+		Error ("%s is not a Alias object separated triangle file, magic number is wrong.", filename);
+
+	pPSET = calloc( 1, POLYSET_MAXPOLYSETS * sizeof( polyset_t ) );
+	ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
+
+	*ppPSET = pPSET;
+
+	while (feof(input) == 0) {
+		if (fread(&start,  sizeof(float), 1, input) < 1)
+			break;
+		*(int *)&start = BigLong(*(int *)&start);
+		if (*(int *)&start != exitpattern)
+		{
+			if (start == FLOAT_START) {
+				/* Start of an object or group of objects. */
+				i = -1;
+				do {
+					/* There are probably better ways to read a string from */
+					/* a file, but this does allow you to do error checking */
+					/* (which I'm not doing) on a per character basis.      */
+					++i;
+					fread( &(name[i]), sizeof( char ), 1, input);
+				} while( name[i] != '\0' );
+	
+				if ( i != 0 )
+					strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
+				else
+					strcpy( pPSET[pset].name , "(unnamed)" );
+				strlwr( pPSET[pset].name );
+
+//				indent();
+//				fprintf(stdout,"OBJECT START: %s\n",name);
+				fread( &count, sizeof(int), 1, input);
+				count = BigLong(count);
+				++iLevel;
+				if (count != 0) {
+//					indent();
+//					fprintf(stdout,"NUMBER OF TRIANGLES: %d\n",count);
+	
+					i = -1;
+					do {
+						++i;
+						fread( &(tex[i]), sizeof( char ), 1, input);
+					} while( tex[i] != '\0' );
+
+/*
+					if ( i != 0 )
+						strncpy( pPSET[pset].texname, tex, sizeof( pPSET[pset].texname ) - 1 );
+					else
+						strcpy( pPSET[pset].texname, "(unnamed)" );
+					strlwr( pPSET[pset].texname );
+*/
+
+//					indent();
+//					fprintf(stdout,"  Object texture name: '%s'\n",tex);
+				}
+	
+				/* Else (count == 0) this is the start of a group, and */
+				/* no texture name is present. */
+			}
+			else if (start == FLOAT_END) {
+				/* End of an object or group. Yes, the name should be */
+				/* obvious from context, but it is in here just to be */
+				/* safe and to provide a little extra information for */
+				/* those who do not wish to write a recursive reader. */
+				/* Mea culpa. */
+				--iLevel;
+				i = -1;
+				do {
+					++i;
+					fread( &(name[i]), sizeof( char ), 1, input);
+				} while( name[i] != '\0' );
+
+				if ( i != 0 )
+					strncpy( pPSET[pset].name, name, sizeof( pPSET[pset].name ) - 1 );
+				else
+					strcpy( pPSET[pset].name , "(unnamed)" );
+
+				strlwr( pPSET[pset].name );
+	
+//				indent();
+//				fprintf(stdout,"OBJECT END: %s\n",name);
+				continue;
+			}
+		}
+
+//
+// read the triangles
+//		
+		if ( count > 0 )
+		{
+			pPSET[pset].triangles = ptri;
+			ReadPolysetGeometry( pPSET[0].triangles, input, count, ptri );
+			ptri += count;
+			pPSET[pset].numtriangles = count;
+			if ( ++pset >= POLYSET_MAXPOLYSETS )
+			{
+				Error ("Error: too many polysets; increase POLYSET_MAXPOLYSETS\n");
+			}
+		}
+	}
+
+	*numpsets = pset;
+
+	fclose (input);
+}
+
diff --git a/tools/quake3/common/trilib.h b/tools/quake3/common/trilib.h
index 0b41d3c0..30b10837 100644
--- a/tools/quake3/common/trilib.h
+++ b/tools/quake3/common/trilib.h
@@ -1,26 +1,26 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-//
-// trilib.h: header file for loading triangles from an Alias triangle file
-//
-void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets );
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+//
+// trilib.h: header file for loading triangles from an Alias triangle file
+//
+void TRI_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets );
+
diff --git a/tools/quake3/common/unzip.c b/tools/quake3/common/unzip.c
index 1732626a..1949db22 100644
--- a/tools/quake3/common/unzip.c
+++ b/tools/quake3/common/unzip.c
@@ -1,4596 +1,4596 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/*****************************************************************************
- * name:		unzip.c
- *
- * desc:		IO on .zip files using portions of zlib 
- *
- *
- *****************************************************************************/
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include "unzip.h"
-
-// TTimo added for safe_malloc wrapping
-#include "cmdlib.h"
-
-/* unzip.h -- IO for uncompress .zip files using zlib 
-   Version 0.15 beta, Mar 19th, 1998,
-
-   Copyright (C) 1998 Gilles Vollant
-
-   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
-     WinZip, InfoZip tools and compatible.
-   Encryption and multi volume ZipFile (span) are not supported.
-   Old compressions used by old PKZip 1.x are not supported
-
-   THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
-   CAN CHANGE IN FUTURE VERSION !!
-   I WAIT FEEDBACK at mail info@winimage.com
-   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
-
-   Condition of use and distribution are the same than zlib :
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-
-*/
-/* for more info about .ZIP format, see 
-      ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
-   PkWare has also a specification at :
-      ftp://ftp.pkware.com/probdesc.zip */
-
-/* zlib.h -- interface of the 'zlib' general purpose compression library
-  version 1.1.3, July 9th, 1998
-
-  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
-
-  This software is provided 'as-is', without any express or implied
-  warranty.  In no event will the authors be held liable for any damages
-  arising from the use of this software.
-
-  Permission is granted to anyone to use this software for any purpose,
-  including commercial applications, and to alter it and redistribute it
-  freely, subject to the following restrictions:
-
-  1. The origin of this software must not be misrepresented; you must not
-     claim that you wrote the original software. If you use this software
-     in a product, an acknowledgment in the product documentation would be
-     appreciated but is not required.
-  2. Altered source versions must be plainly marked as such, and must not be
-     misrepresented as being the original software.
-  3. This notice may not be removed or altered from any source distribution.
-
-  Jean-loup Gailly        Mark Adler
-  jloup@gzip.org          madler@alumni.caltech.edu
-
-
-  The data format used by the zlib library is described by RFCs (Request for
-  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
-  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
-*/
-
-/* zconf.h -- configuration of the zlib compression library
- * Copyright (C) 1995-1998 Jean-loup Gailly.
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-
-#ifndef _ZCONF_H
-#define _ZCONF_H
-
-/* Maximum value for memLevel in deflateInit2 */
-#ifndef MAX_MEM_LEVEL
-#  ifdef MAXSEG_64K
-#    define MAX_MEM_LEVEL 8
-#  else
-#    define MAX_MEM_LEVEL 9
-#  endif
-#endif
-
-/* Maximum value for windowBits in deflateInit2 and inflateInit2.
- * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
- * created by gzip. (Files created by minigzip can still be extracted by
- * gzip.)
- */
-#ifndef MAX_WBITS
-#  define MAX_WBITS   15 /* 32K LZ77 window */
-#endif
-
-/* The memory requirements for deflate are (in bytes):
-            (1 << (windowBits+2)) +  (1 << (memLevel+9))
- that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
- plus a few kilobytes for small objects. For example, if you want to reduce
- the default memory requirements from 256K to 128K, compile with
-     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
- Of course this will generally degrade compression (there's no free lunch).
-
-   The memory requirements for inflate are (in bytes) 1 << windowBits
- that is, 32K for windowBits=15 (default value) plus a few kilobytes
- for small objects.
-*/
-
-                        /* Type declarations */
-
-#ifndef OF /* function prototypes */
-#define OF(args)  args
-#endif
-
-typedef unsigned char  Byte;  /* 8 bits */
-typedef unsigned int   uInt;  /* 16 bits or more */
-typedef unsigned long  uLong; /* 32 bits or more */
-typedef Byte    *voidp;
-
-#ifndef SEEK_SET
-#  define SEEK_SET        0       /* Seek from beginning of file.  */
-#  define SEEK_CUR        1       /* Seek from current position.  */
-#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
-#endif
-
-#endif /* _ZCONF_H */
-
-#define ZLIB_VERSION "1.1.3"
-
-/* 
-     The 'zlib' compression library provides in-memory compression and
-  decompression functions, including integrity checks of the uncompressed
-  data.  This version of the library supports only one compression method
-  (deflation) but other algorithms will be added later and will have the same
-  stream interface.
-
-     Compression can be done in a single step if the buffers are large
-  enough (for example if an input file is mmap'ed), or can be done by
-  repeated calls of the compression function.  In the latter case, the
-  application must provide more input and/or consume the output
-  (providing more output space) before each call.
-
-     The library also supports reading and writing files in gzip (.gz) format
-  with an interface similar to that of stdio.
-
-     The library does not install any signal handler. The decoder checks
-  the consistency of the compressed data, so the library should never
-  crash even in case of corrupted input.
-*/
-
-/*
-   The application must update next_in and avail_in when avail_in has
-   dropped to zero. It must update next_out and avail_out when avail_out
-   has dropped to zero. The application must initialize zalloc, zfree and
-   opaque before calling the init function. All other fields are set by the
-   compression library and must not be updated by the application.
-
-   The opaque value provided by the application will be passed as the first
-   parameter for calls of zalloc and zfree. This can be useful for custom
-   memory management. The compression library attaches no meaning to the
-   opaque value.
-
-   zalloc must return Z_NULL if there is not enough memory for the object.
-   If zlib is used in a multi-threaded application, zalloc and zfree must be
-   thread safe.
-
-   On 16-bit systems, the functions zalloc and zfree must be able to allocate
-   exactly 65536 bytes, but will not be required to allocate more than this
-   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
-   pointers returned by zalloc for objects of exactly 65536 bytes *must*
-   have their offset normalized to zero. The default allocation function
-   provided by this library ensures this (see zutil.c). To reduce memory
-   requirements and avoid any allocation of 64K objects, at the expense of
-   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
-
-   The fields total_in and total_out can be used for statistics or
-   progress reports. After compression, total_in holds the total size of
-   the uncompressed data and may be saved for use in the decompressor
-   (particularly if the decompressor wants to decompress everything in
-   a single step).
-*/
-
-                        /* constants */
-
-#define Z_NO_FLUSH      0
-#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
-#define Z_SYNC_FLUSH    2
-#define Z_FULL_FLUSH    3
-#define Z_FINISH        4
-/* Allowed flush values; see deflate() below for details */
-
-#define Z_OK            0
-#define Z_STREAM_END    1
-#define Z_NEED_DICT     2
-#define Z_ERRNO        (-1)
-#define Z_STREAM_ERROR (-2)
-#define Z_DATA_ERROR   (-3)
-#define Z_MEM_ERROR    (-4)
-#define Z_BUF_ERROR    (-5)
-#define Z_VERSION_ERROR (-6)
-/* Return codes for the compression/decompression functions. Negative
- * values are errors, positive values are used for special but normal events.
- */
-
-#define Z_NO_COMPRESSION         0
-#define Z_BEST_SPEED             1
-#define Z_BEST_COMPRESSION       9
-#define Z_DEFAULT_COMPRESSION  (-1)
-/* compression levels */
-
-#define Z_FILTERED            1
-#define Z_HUFFMAN_ONLY        2
-#define Z_DEFAULT_STRATEGY    0
-/* compression strategy; see deflateInit2() below for details */
-
-#define Z_BINARY   0
-#define Z_ASCII    1
-#define Z_UNKNOWN  2
-/* Possible values of the data_type field */
-
-#define Z_DEFLATED   8
-/* The deflate compression method (the only one supported in this version) */
-
-#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
-
-#define zlib_version zlibVersion()
-/* for compatibility with versions < 1.0.2 */
-
-                        /* basic functions */
-
-const char * zlibVersion OF((void));
-/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
-   If the first character differs, the library code actually used is
-   not compatible with the zlib.h header file used by the application.
-   This check is automatically made by deflateInit and inflateInit.
- */
-
-/* 
-int deflateInit OF((z_streamp strm, int level));
-
-     Initializes the internal stream state for compression. The fields
-   zalloc, zfree and opaque must be initialized before by the caller.
-   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
-   use default allocation functions.
-
-     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
-   1 gives best speed, 9 gives best compression, 0 gives no compression at
-   all (the input data is simply copied a block at a time).
-   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
-   compression (currently equivalent to level 6).
-
-     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
-   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
-   with the version assumed by the caller (ZLIB_VERSION).
-   msg is set to null if there is no error message.  deflateInit does not
-   perform any compression: this will be done by deflate().
-*/
-
-
-int deflate OF((z_streamp strm, int flush));
-/*
-    deflate compresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may introduce some
-  output latency (reading input without producing any output) except when
-  forced to flush.
-
-    The detailed semantics are as follows. deflate performs one or both of the
-  following actions:
-
-  - Compress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in and avail_in are updated and
-    processing will resume at this point for the next call of deflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly. This action is forced if the parameter flush is non zero.
-    Forcing flush frequently degrades the compression ratio, so this parameter
-    should be set only when necessary (in interactive applications).
-    Some output may be provided even if flush is not set.
-
-  Before the call of deflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating avail_in or avail_out accordingly; avail_out
-  should never be zero before the call. The application can consume the
-  compressed output when it wants, for example when the output buffer is full
-  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
-  and with zero avail_out, it must be called again after making room in the
-  output buffer because there might be more output pending.
-
-    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
-  flushed to the output buffer and the output is aligned on a byte boundary, so
-  that the decompressor can get all input data available so far. (In particular
-  avail_in is zero after the call if enough output space has been provided
-  before the call.)  Flushing may degrade compression for some compression
-  algorithms and so it should be used only when necessary.
-
-    If flush is set to Z_FULL_FLUSH, all output is flushed as with
-  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
-  restart from this point if previous compressed data has been damaged or if
-  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
-  the compression.
-
-    If deflate returns with avail_out == 0, this function must be called again
-  with the same value of the flush parameter and more output space (updated
-  avail_out), until the flush is complete (deflate returns with non-zero
-  avail_out).
-
-    If the parameter flush is set to Z_FINISH, pending input is processed,
-  pending output is flushed and deflate returns with Z_STREAM_END if there
-  was enough output space; if deflate returns with Z_OK, this function must be
-  called again with Z_FINISH and more output space (updated avail_out) but no
-  more input data, until it returns with Z_STREAM_END or an error. After
-  deflate has returned Z_STREAM_END, the only possible operations on the
-  stream are deflateReset or deflateEnd.
-  
-    Z_FINISH can be used immediately after deflateInit if all the compression
-  is to be done in a single step. In this case, avail_out must be at least
-  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
-  Z_STREAM_END, then it must be called again as described above.
-
-    deflate() sets strm->adler to the adler32 checksum of all input read
-  so (that is, total_in bytes).
-
-    deflate() may update data_type if it can make a good guess about
-  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
-  binary. This field is only for information purposes and does not affect
-  the compression algorithm in any manner.
-
-    deflate() returns Z_OK if some progress has been made (more input
-  processed or more output produced), Z_STREAM_END if all input has been
-  consumed and all output has been produced (only when flush is set to
-  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
-  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
-  (for example avail_in or avail_out was zero).
-*/
-
-
-int deflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-
-     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
-   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
-   prematurely (some input or output was discarded). In the error case,
-   msg may be set but then points to a static string (which must not be
-   deallocated).
-*/
-
-
-/* 
-int inflateInit OF((z_streamp strm));
-
-     Initializes the internal stream state for decompression. The fields
-   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
-   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
-   value depends on the compression method), inflateInit determines the
-   compression method from the zlib header and allocates all data structures
-   accordingly; otherwise the allocation will be deferred to the first call of
-   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
-   use default allocation functions.
-
-     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
-   version assumed by the caller.  msg is set to null if there is no error
-   message. inflateInit does not perform any decompression apart from reading
-   the zlib header if present: this will be done by inflate().  (So next_in and
-   avail_in may be modified, but next_out and avail_out are unchanged.)
-*/
-
-
-int inflate OF((z_streamp strm, int flush));
-/*
-    inflate decompresses as much data as possible, and stops when the input
-  buffer becomes empty or the output buffer becomes full. It may some
-  introduce some output latency (reading input without producing any output)
-  except when forced to flush.
-
-  The detailed semantics are as follows. inflate performs one or both of the
-  following actions:
-
-  - Decompress more input starting at next_in and update next_in and avail_in
-    accordingly. If not all input can be processed (because there is not
-    enough room in the output buffer), next_in is updated and processing
-    will resume at this point for the next call of inflate().
-
-  - Provide more output starting at next_out and update next_out and avail_out
-    accordingly.  inflate() provides as much output as possible, until there
-    is no more input data or no more space in the output buffer (see below
-    about the flush parameter).
-
-  Before the call of inflate(), the application should ensure that at least
-  one of the actions is possible, by providing more input and/or consuming
-  more output, and updating the next_* and avail_* values accordingly.
-  The application can consume the uncompressed output when it wants, for
-  example when the output buffer is full (avail_out == 0), or after each
-  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
-  must be called again after making room in the output buffer because there
-  might be more output pending.
-
-    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
-  output as possible to the output buffer. The flushing behavior of inflate is
-  not specified for values of the flush parameter other than Z_SYNC_FLUSH
-  and Z_FINISH, but the current implementation actually flushes as much output
-  as possible anyway.
-
-    inflate() should normally be called until it returns Z_STREAM_END or an
-  error. However if all decompression is to be performed in a single step
-  (a single call of inflate), the parameter flush should be set to
-  Z_FINISH. In this case all pending input is processed and all pending
-  output is flushed; avail_out must be large enough to hold all the
-  uncompressed data. (The size of the uncompressed data may have been saved
-  by the compressor for this purpose.) The next operation on this stream must
-  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
-  is never required, but can be used to inform inflate that a faster routine
-  may be used for the single inflate() call.
-
-     If a preset dictionary is needed at this point (see inflateSetDictionary
-  below), inflate sets strm-adler to the adler32 checksum of the
-  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
-  it sets strm->adler to the adler32 checksum of all output produced
-  so (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
-  an error code as described below. At the end of the stream, inflate()
-  checks that its computed adler32 checksum is equal to that saved by the
-  compressor and returns Z_STREAM_END only if the checksum is correct.
-
-    inflate() returns Z_OK if some progress has been made (more input processed
-  or more output produced), Z_STREAM_END if the end of the compressed data has
-  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
-  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
-  corrupted (input stream not conforming to the zlib format or incorrect
-  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
-  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
-  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
-  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
-  case, the application may then call inflateSync to look for a good
-  compression block.
-*/
-
-
-int inflateEnd OF((z_streamp strm));
-/*
-     All dynamically allocated data structures for this stream are freed.
-   This function discards any unprocessed input and does not flush any
-   pending output.
-
-     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
-   was inconsistent. In the error case, msg may be set but then points to a
-   static string (which must not be deallocated).
-*/
-
-                        /* Advanced functions */
-
-/*
-    The following functions are needed only in some special applications.
-*/
-
-/*   
-int deflateInit2 OF((z_streamp strm,
-                                     int  level,
-                                     int  method,
-                                     int  windowBits,
-                                     int  memLevel,
-                                     int  strategy));
-
-     This is another version of deflateInit with more compression options. The
-   fields next_in, zalloc, zfree and opaque must be initialized before by
-   the caller.
-
-     The method parameter is the compression method. It must be Z_DEFLATED in
-   this version of the library.
-
-     The windowBits parameter is the base two logarithm of the window size
-   (the size of the history buffer).  It should be in the range 8..15 for this
-   version of the library. Larger values of this parameter result in better
-   compression at the expense of memory usage. The default value is 15 if
-   deflateInit is used instead.
-
-     The memLevel parameter specifies how much memory should be allocated
-   for the internal compression state. memLevel=1 uses minimum memory but
-   is slow and reduces compression ratio; memLevel=9 uses maximum memory
-   for optimal speed. The default value is 8. See zconf.h for total memory
-   usage as a function of windowBits and memLevel.
-
-     The strategy parameter is used to tune the compression algorithm. Use the
-   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
-   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
-   string match).  Filtered data consists mostly of small values with a
-   somewhat random distribution. In this case, the compression algorithm is
-   tuned to compress them better. The effect of Z_FILTERED is to force more
-   Huffman coding and less string matching; it is somewhat intermediate
-   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
-   the compression ratio but not the correctness of the compressed output even
-   if it is not set appropriately.
-
-      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
-   method). msg is set to null if there is no error message.  deflateInit2 does
-   not perform any compression: this will be done by deflate().
-*/
-                            
-int deflateSetDictionary OF((z_streamp strm,
-                                             const Byte *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the compression dictionary from the given byte sequence
-   without producing any compressed output. This function must be called
-   immediately after deflateInit, deflateInit2 or deflateReset, before any
-   call of deflate. The compressor and decompressor must use exactly the same
-   dictionary (see inflateSetDictionary).
-
-     The dictionary should consist of strings (byte sequences) that are likely
-   to be encountered later in the data to be compressed, with the most commonly
-   used strings preferably put towards the end of the dictionary. Using a
-   dictionary is most useful when the data to be compressed is short and can be
-   predicted with good accuracy; the data can then be compressed better than
-   with the default empty dictionary.
-
-     Depending on the size of the compression data structures selected by
-   deflateInit or deflateInit2, a part of the dictionary may in effect be
-   discarded, for example if the dictionary is larger than the window size in
-   deflate or deflate2. Thus the strings most likely to be useful should be
-   put at the end of the dictionary, not at the front.
-
-     Upon return of this function, strm->adler is set to the Adler32 value
-   of the dictionary; the decompressor may later use this value to determine
-   which dictionary has been used by the compressor. (The Adler32 value
-   applies to the whole dictionary even if only a subset of the dictionary is
-   actually used by the compressor.)
-
-     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
-   parameter is invalid (such as NULL dictionary) or the stream state is
-   inconsistent (for example if deflate has already been called for this stream
-   or if the compression method is bsort). deflateSetDictionary does not
-   perform any compression: this will be done by deflate().
-*/
-
-int deflateCopy OF((z_streamp dest,
-                                    z_streamp source));
-/*
-     Sets the destination stream as a complete copy of the source stream.
-
-     This function can be useful when several compression strategies will be
-   tried, for example when there are several ways of pre-processing the input
-   data with a filter. The streams that will be discarded should then be freed
-   by calling deflateEnd.  Note that deflateCopy duplicates the internal
-   compression state which can be quite large, so this strategy is slow and
-   can consume lots of memory.
-
-     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
-   (such as zalloc being NULL). msg is left unchanged in both source and
-   destination.
-*/
-
-int deflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to deflateEnd followed by deflateInit,
-   but does not free and reallocate all the internal compression state.
-   The stream will keep the same compression level and any other attributes
-   that may have been set by deflateInit2.
-
-      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-int deflateParams OF((z_streamp strm,
-				      int level,
-				      int strategy));
-/*
-     Dynamically update the compression level and compression strategy.  The
-   interpretation of level and strategy is as in deflateInit2.  This can be
-   used to switch between compression and straight copy of the input data, or
-   to switch to a different kind of input data requiring a different
-   strategy. If the compression level is changed, the input available so far
-   is compressed with the old level (and may be flushed); the new level will
-   take effect only at the next call of deflate().
-
-     Before the call of deflateParams, the stream state must be set as for
-   a call of deflate(), since the currently available input may have to
-   be compressed and flushed. In particular, strm->avail_out must be non-zero.
-
-     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
-   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
-   if strm->avail_out was zero.
-*/
-
-/*   
-int inflateInit2 OF((z_streamp strm,
-                                     int  windowBits));
-
-     This is another version of inflateInit with an extra parameter. The
-   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
-   before by the caller.
-
-     The windowBits parameter is the base two logarithm of the maximum window
-   size (the size of the history buffer).  It should be in the range 8..15 for
-   this version of the library. The default value is 15 if inflateInit is used
-   instead. If a compressed stream with a larger window size is given as
-   input, inflate() will return with the error code Z_DATA_ERROR instead of
-   trying to allocate a larger window.
-
-      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
-   memLevel). msg is set to null if there is no error message.  inflateInit2
-   does not perform any decompression apart from reading the zlib header if
-   present: this will be done by inflate(). (So next_in and avail_in may be
-   modified, but next_out and avail_out are unchanged.)
-*/
-
-int inflateSetDictionary OF((z_streamp strm,
-                                             const Byte *dictionary,
-                                             uInt  dictLength));
-/*
-     Initializes the decompression dictionary from the given uncompressed byte
-   sequence. This function must be called immediately after a call of inflate
-   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
-   can be determined from the Adler32 value returned by this call of
-   inflate. The compressor and decompressor must use exactly the same
-   dictionary (see deflateSetDictionary).
-
-     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
-   parameter is invalid (such as NULL dictionary) or the stream state is
-   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
-   expected one (incorrect Adler32 value). inflateSetDictionary does not
-   perform any decompression: this will be done by subsequent calls of
-   inflate().
-*/
-
-int inflateSync OF((z_streamp strm));
-/* 
-    Skips invalid compressed data until a full flush point (see above the
-  description of deflate with Z_FULL_FLUSH) can be found, or until all
-  available input is skipped. No output is provided.
-
-    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
-  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
-  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
-  case, the application may save the current current value of total_in which
-  indicates where valid compressed data was found. In the error case, the
-  application may repeatedly call inflateSync, providing more input each time,
-  until success or end of the input data.
-*/
-
-int inflateReset OF((z_streamp strm));
-/*
-     This function is equivalent to inflateEnd followed by inflateInit,
-   but does not free and reallocate all the internal decompression state.
-   The stream will keep attributes that may have been set by inflateInit2.
-
-      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
-   stream state was inconsistent (such as zalloc or state being NULL).
-*/
-
-
-                        /* utility functions */
-
-/*
-     The following utility functions are implemented on top of the
-   basic stream-oriented functions. To simplify the interface, some
-   default options are assumed (compression level and memory usage,
-   standard memory allocation functions). The source code of these
-   utility functions can easily be modified if you need special options.
-*/
-
-int compress OF((Byte *dest,   uLong *destLen,
-                                 const Byte *source, uLong sourceLen));
-/*
-     Compresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be at least 0.1% larger than
-   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
-   compressed buffer.
-     This function can be used to compress a whole file at once if the
-   input file is mmap'ed.
-     compress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer.
-*/
-
-int compress2 OF((Byte *dest,   uLong *destLen,
-                                  const Byte *source, uLong sourceLen,
-                                  int level));
-/*
-     Compresses the source buffer into the destination buffer. The level
-   parameter has the same meaning as in deflateInit.  sourceLen is the byte
-   length of the source buffer. Upon entry, destLen is the total size of the
-   destination buffer, which must be at least 0.1% larger than sourceLen plus
-   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
-
-     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
-   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
-   Z_STREAM_ERROR if the level parameter is invalid.
-*/
-
-int uncompress OF((Byte *dest,   uLong *destLen,
-                                   const Byte *source, uLong sourceLen));
-/*
-     Decompresses the source buffer into the destination buffer.  sourceLen is
-   the byte length of the source buffer. Upon entry, destLen is the total
-   size of the destination buffer, which must be large enough to hold the
-   entire uncompressed data. (The size of the uncompressed data must have
-   been saved previously by the compressor and transmitted to the decompressor
-   by some mechanism outside the scope of this compression library.)
-   Upon exit, destLen is the actual size of the compressed buffer.
-     This function can be used to decompress a whole file at once if the
-   input file is mmap'ed.
-
-     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
-   enough memory, Z_BUF_ERROR if there was not enough room in the output
-   buffer, or Z_DATA_ERROR if the input data was corrupted.
-*/
-
-
-typedef voidp gzFile;
-
-gzFile gzopen  OF((const char *path, const char *mode));
-/*
-     Opens a gzip (.gz) file for reading or writing. The mode parameter
-   is as in fopen ("rb" or "wb") but can also include a compression level
-   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
-   Huffman only compression as in "wb1h". (See the description
-   of deflateInit2 for more information about the strategy parameter.)
-
-     gzopen can be used to read a file which is not in gzip format; in this
-   case gzread will directly read from the file without decompression.
-
-     gzopen returns NULL if the file could not be opened or if there was
-   insufficient memory to allocate the (de)compression state; errno
-   can be checked to distinguish the two cases (if errno is zero, the
-   zlib error is Z_MEM_ERROR).  */
-
-gzFile gzdopen  OF((int fd, const char *mode));
-/*
-     gzdopen() associates a gzFile with the file descriptor fd.  File
-   descriptors are obtained from calls like open, dup, creat, pipe or
-   fileno (in the file has been previously opened with fopen).
-   The mode parameter is as in gzopen.
-     The next call of gzclose on the returned gzFile will also close the
-   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
-   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
-     gzdopen returns NULL if there was insufficient memory to allocate
-   the (de)compression state.
-*/
-
-int gzsetparams OF((gzFile file, int level, int strategy));
-/*
-     Dynamically update the compression level or strategy. See the description
-   of deflateInit2 for the meaning of these parameters.
-     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
-   opened for writing.
-*/
-
-int    gzread  OF((gzFile file, voidp buf, unsigned len));
-/*
-     Reads the given number of uncompressed bytes from the compressed file.
-   If the input file was not in gzip format, gzread copies the given number
-   of bytes into the buffer.
-     gzread returns the number of uncompressed bytes actually read (0 for
-   end of file, -1 for error). */
-
-int    gzwrite OF((gzFile file, 
-				   const voidp buf, unsigned len));
-/*
-     Writes the given number of uncompressed bytes into the compressed file.
-   gzwrite returns the number of uncompressed bytes actually written
-   (0 in case of error).
-*/
-
-int    gzprintf OF((gzFile file, const char *format, ...));
-/*
-     Converts, formats, and writes the args to the compressed file under
-   control of the format string, as in fprintf. gzprintf returns the number of
-   uncompressed bytes actually written (0 in case of error).
-*/
-
-int gzputs OF((gzFile file, const char *s));
-/*
-      Writes the given null-terminated string to the compressed file, excluding
-   the terminating null character.
-      gzputs returns the number of characters written, or -1 in case of error.
-*/
-
-char * gzgets OF((gzFile file, char *buf, int len));
-/*
-      Reads bytes from the compressed file until len-1 characters are read, or
-   a newline character is read and transferred to buf, or an end-of-file
-   condition is encountered.  The string is then terminated with a null
-   character.
-      gzgets returns buf, or Z_NULL in case of error.
-*/
-
-int    gzputc OF((gzFile file, int c));
-/*
-      Writes c, converted to an unsigned char, into the compressed file.
-   gzputc returns the value that was written, or -1 in case of error.
-*/
-
-int    gzgetc OF((gzFile file));
-/*
-      Reads one byte from the compressed file. gzgetc returns this byte
-   or -1 in case of end of file or error.
-*/
-
-int    gzflush OF((gzFile file, int flush));
-/*
-     Flushes all pending output into the compressed file. The parameter
-   flush is as in the deflate() function. The return value is the zlib
-   error number (see function gzerror below). gzflush returns Z_OK if
-   the flush parameter is Z_FINISH and all output could be flushed.
-     gzflush should be called only when strictly necessary because it can
-   degrade compression.
-*/
-
-long gzseek OF((gzFile file,
-				      long offset, int whence));
-/* 
-      Sets the starting position for the next gzread or gzwrite on the
-   given compressed file. The offset represents a number of bytes in the
-   uncompressed data stream. The whence parameter is defined as in lseek(2);
-   the value SEEK_END is not supported.
-     If the file is opened for reading, this function is emulated but can be
-   extremely slow. If the file is opened for writing, only forward seeks are
-   supported; gzseek then compresses a sequence of zeroes up to the new
-   starting position.
-
-      gzseek returns the resulting offset location as measured in bytes from
-   the beginning of the uncompressed stream, or -1 in case of error, in
-   particular if the file is opened for writing and the new starting position
-   would be before the current position.
-*/
-
-int    gzrewind OF((gzFile file));
-/*
-     Rewinds the given file. This function is supported only for reading.
-
-   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
-*/
-
-long    gztell OF((gzFile file));
-/*
-     Returns the starting position for the next gzread or gzwrite on the
-   given compressed file. This position represents a number of bytes in the
-   uncompressed data stream.
-
-   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
-*/
-
-int gzeof OF((gzFile file));
-/*
-     Returns 1 when EOF has previously been detected reading the given
-   input stream, otherwise zero.
-*/
-
-int    gzclose OF((gzFile file));
-/*
-     Flushes all pending output if necessary, closes the compressed file
-   and deallocates all the (de)compression state. The return value is the zlib
-   error number (see function gzerror below).
-*/
-
-const char * gzerror OF((gzFile file, int *errnum));
-/*
-     Returns the error message for the last error which occurred on the
-   given compressed file. errnum is set to zlib error number. If an
-   error occurred in the file system and not in the compression library,
-   errnum is set to Z_ERRNO and the application may consult errno
-   to get the exact error code.
-*/
-
-                        /* checksum functions */
-
-/*
-     These functions are not related to compression but are exported
-   anyway because they might be useful in applications using the
-   compression library.
-*/
-
-uLong adler32 OF((uLong adler, const Byte *buf, uInt len));
-
-/*
-     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
-   return the updated checksum. If buf is NULL, this function returns
-   the required initial value for the checksum.
-   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
-   much faster. Usage example:
-
-     uLong adler = adler32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       adler = adler32(adler, buffer, length);
-     }
-     if (adler != original_adler) error();
-*/
-
-uLong crc32   OF((uLong crc, const Byte *buf, uInt len));
-/*
-     Update a running crc with the bytes buf[0..len-1] and return the updated
-   crc. If buf is NULL, this function returns the required initial value
-   for the crc. Pre- and post-conditioning (one's complement) is performed
-   within this function so it shouldn't be done by the application.
-   Usage example:
-
-     uLong crc = crc32(0L, Z_NULL, 0);
-
-     while (read_buffer(buffer, length) != EOF) {
-       crc = crc32(crc, buffer, length);
-     }
-     if (crc != original_crc) error();
-*/
-
-// private stuff to not include cmdlib.h
-/*
-============================================================================
-
-					BYTE ORDER FUNCTIONS
-
-============================================================================
-*/
-
-#ifdef _SGI_SOURCE
-#define	__BIG_ENDIAN__
-#endif
-
-#ifdef __BIG_ENDIAN__
-
-short   __LittleShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   __BigShort (short l)
-{
-	return l;
-}
-
-
-int    __LittleLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    __BigLong (int l)
-{
-	return l;
-}
-
-
-float	__LittleFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	__BigFloat (float l)
-{
-	return l;
-}
-
-
-#else
-
-
-short   __BigShort (short l)
-{
-	byte    b1,b2;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-
-	return (b1<<8) + b2;
-}
-
-short   __LittleShort (short l)
-{
-	return l;
-}
-
-
-int    __BigLong (int l)
-{
-	byte    b1,b2,b3,b4;
-
-	b1 = l&255;
-	b2 = (l>>8)&255;
-	b3 = (l>>16)&255;
-	b4 = (l>>24)&255;
-
-	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
-}
-
-int    __LittleLong (int l)
-{
-	return l;
-}
-
-float	__BigFloat (float l)
-{
-	union {byte b[4]; float f;} in, out;
-	
-	in.f = l;
-	out.b[0] = in.b[3];
-	out.b[1] = in.b[2];
-	out.b[2] = in.b[1];
-	out.b[3] = in.b[0];
-	
-	return out.f;
-}
-
-float	__LittleFloat (float l)
-{
-	return l;
-}
-
-
-
-#endif
-
-
-
-
-                        /* various hacks, don't look :) */
-
-/* deflateInit and inflateInit are macros to allow checking the zlib version
- * and the compiler's view of z_stream:
- */
-int deflateInit_ OF((z_streamp strm, int level,
-                                     const char *version, int stream_size));
-int inflateInit_ OF((z_streamp strm,
-                                     const char *version, int stream_size));
-int deflateInit2_ OF((z_streamp strm, int  level, int  method,
-                                      int windowBits, int memLevel,
-                                      int strategy, const char *version,
-                                      int stream_size));
-int inflateInit2_ OF((z_streamp strm, int  windowBits,
-                                      const char *version, int stream_size));
-#define deflateInit(strm, level) \
-        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit(strm) \
-        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
-#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
-        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
-                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
-#define inflateInit2(strm, windowBits) \
-        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
-
-
-const char   * zError           OF((int err));
-int            inflateSyncPoint OF((z_streamp z));
-const uLong * get_crc_table    OF((void));
-
-typedef unsigned char  uch;
-typedef unsigned short ush;
-typedef unsigned long  ulg;
-
-extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
-/* (size given to avoid silly warnings with Visual C++) */
-
-#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
-
-#define ERR_RETURN(strm,err) \
-  return (strm->msg = (char*)ERR_MSG(err), (err))
-/* To be used only when the state is known to be valid */
-
-        /* common constants */
-
-#ifndef DEF_WBITS
-#  define DEF_WBITS MAX_WBITS
-#endif
-/* default windowBits for decompression. MAX_WBITS is for compression only */
-
-#if MAX_MEM_LEVEL >= 8
-#  define DEF_MEM_LEVEL 8
-#else
-#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
-#endif
-/* default memLevel */
-
-#define STORED_BLOCK 0
-#define STATIC_TREES 1
-#define DYN_TREES    2
-/* The three kinds of block type */
-
-#define MIN_MATCH  3
-#define MAX_MATCH  258
-/* The minimum and maximum match lengths */
-
-#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
-
-        /* target dependencies */
-
-        /* Common defaults */
-
-#ifndef OS_CODE
-#  define OS_CODE  0x03  /* assume Unix */
-#endif
-
-#ifndef F_OPEN
-#  define F_OPEN(name, mode) fopen((name), (mode))
-#endif
-
-         /* functions */
-
-#ifdef HAVE_STRERROR
-   extern char *strerror OF((int));
-#  define zstrerror(errnum) strerror(errnum)
-#else
-#  define zstrerror(errnum) ""
-#endif
-
-#define zmemcpy memcpy
-#define zmemcmp memcmp
-#define zmemzero(dest, len) memset(dest, 0, len)
-
-/* Diagnostic functions */
-#ifdef _ZIP_DEBUG_
-   int z_verbose = 0;
-#  define Assert(cond,msg) assert(cond);
-   //{if(!(cond)) Sys_Error(msg);}
-#  define Trace(x) {if (z_verbose>=0) Sys_Error x ;}
-#  define Tracev(x) {if (z_verbose>0) Sys_Error x ;}
-#  define Tracevv(x) {if (z_verbose>1) Sys_Error x ;}
-#  define Tracec(c,x) {if (z_verbose>0 && (c)) Sys_Error x ;}
-#  define Tracecv(c,x) {if (z_verbose>1 && (c)) Sys_Error x ;}
-#else
-#  define Assert(cond,msg)
-#  define Trace(x)
-#  define Tracev(x)
-#  define Tracevv(x)
-#  define Tracec(c,x)
-#  define Tracecv(c,x)
-#endif
-
-
-typedef uLong (*check_func) OF((uLong check, const Byte *buf, uInt len));
-voidp zcalloc OF((voidp opaque, unsigned items, unsigned size));
-void   zcfree  OF((voidp opaque, voidp ptr));
-
-#define ZALLOC(strm, items, size) \
-           (*((strm)->zalloc))((strm)->opaque, (items), (size))
-#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidp)(addr))
-#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
-
-
-#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
-                      !defined(CASESENSITIVITYDEFAULT_NO)
-#define CASESENSITIVITYDEFAULT_NO
-#endif
-
-
-#ifndef UNZ_BUFSIZE
-#define UNZ_BUFSIZE (65536)
-#endif
-
-#ifndef UNZ_MAXFILENAMEINZIP
-#define UNZ_MAXFILENAMEINZIP (256)
-#endif
-
-#ifndef ALLOC
-# define ALLOC(size) (safe_malloc(size))
-#endif
-#ifndef TRYFREE
-# define TRYFREE(p) {if (p) free(p);}
-#endif
-
-#define SIZECENTRALDIRITEM (0x2e)
-#define SIZEZIPLOCALHEADER (0x1e)
-
-
-
-/* ===========================================================================
-     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
-   for end of file.
-   IN assertion: the stream s has been sucessfully opened for reading.
-*/
-
-/*
-static int unzlocal_getByte(FILE *fin,int *pi)
-{
-    unsigned char c;
-	int err = fread(&c, 1, 1, fin);
-    if (err==1)
-    {
-        *pi = (int)c;
-        return UNZ_OK;
-    }
-    else
-    {
-        if (ferror(fin)) 
-            return UNZ_ERRNO;
-        else
-            return UNZ_EOF;
-    }
-}
-*/
-
-/* ===========================================================================
-   Reads a long in LSB order from the given gz_stream. Sets 
-*/
-static int unzlocal_getShort (FILE* fin, uLong *pX)
-{
-	short	v;
-
-	fread( &v, sizeof(v), 1, fin );
-
-	*pX = __LittleShort( v);
-	return UNZ_OK;
-
-/*
-    uLong x ;
-    int i;
-    int err;
-
-    err = unzlocal_getByte(fin,&i);
-    x = (uLong)i;
-    
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
-    x += ((uLong)i)<<8;
-   
-    if (err==UNZ_OK)
-        *pX = x;
-    else
-        *pX = 0;
-    return err;
-*/
-}
-
-static int unzlocal_getLong (FILE *fin, uLong *pX)
-{
-	int		v;
-
-	fread( &v, sizeof(v), 1, fin );
-
-	*pX = __LittleLong( v);
-	return UNZ_OK;
-
-/*
-    uLong x ;
-    int i;
-    int err;
-
-    err = unzlocal_getByte(fin,&i);
-    x = (uLong)i;
-    
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
-    x += ((uLong)i)<<8;
-
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
-    x += ((uLong)i)<<16;
-
-    if (err==UNZ_OK)
-        err = unzlocal_getByte(fin,&i);
-    x += ((uLong)i)<<24;
-   
-    if (err==UNZ_OK)
-        *pX = x;
-    else
-        *pX = 0;
-    return err;
-*/
-}
-
-
-/* My own strcmpi / strcasecmp */
-static int strcmpcasenosensitive_internal (const char* fileName1,const char* fileName2)
-{
-	for (;;)
-	{
-		char c1=*(fileName1++);
-		char c2=*(fileName2++);
-		if ((c1>='a') && (c1<='z'))
-			c1 -= 0x20;
-		if ((c2>='a') && (c2<='z'))
-			c2 -= 0x20;
-		if (c1=='\0')
-			return ((c2=='\0') ? 0 : -1);
-		if (c2=='\0')
-			return 1;
-		if (c1<c2)
-			return -1;
-		if (c1>c2)
-			return 1;
-	}
-}
-
-
-#ifdef  CASESENSITIVITYDEFAULT_NO
-#define CASESENSITIVITYDEFAULTVALUE 2
-#else
-#define CASESENSITIVITYDEFAULTVALUE 1
-#endif
-
-#ifndef STRCMPCASENOSENTIVEFUNCTION
-#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
-#endif
-
-/* 
-   Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-                                                                or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
-        (like 1 on Unix, 2 on Windows)
-
-*/
-extern int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity)
-{
-	if (iCaseSensitivity==0)
-		iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
-
-	if (iCaseSensitivity==1)
-		return strcmp(fileName1,fileName2);
-
-	return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
-} 
-
-#define BUFREADCOMMENT (0x400)
-
-/*
-  Locate the Central directory of a zipfile (at the end, just before
-    the global comment)
-*/
-static uLong unzlocal_SearchCentralDir(FILE *fin)
-{
-	unsigned char* buf;
-	uLong uSizeFile;
-	uLong uBackRead;
-	uLong uMaxBack=0xffff; /* maximum size of global comment */
-	uLong uPosFound=0;
-	
-	if (fseek(fin,0,SEEK_END) != 0)
-		return 0;
-
-
-	uSizeFile = ftell( fin );
-	
-	if (uMaxBack>uSizeFile)
-		uMaxBack = uSizeFile;
-
-	buf = (unsigned char*)safe_malloc(BUFREADCOMMENT+4);
-	if (buf==NULL)
-		return 0;
-
-	uBackRead = 4;
-	while (uBackRead<uMaxBack)
-	{
-		uLong uReadSize,uReadPos ;
-		int i;
-		if (uBackRead+BUFREADCOMMENT>uMaxBack) 
-			uBackRead = uMaxBack;
-		else
-			uBackRead+=BUFREADCOMMENT;
-		uReadPos = uSizeFile-uBackRead ;
-		
-		uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
-                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
-		if (fseek(fin,uReadPos,SEEK_SET)!=0)
-			break;
-
-		if (fread(buf,(uInt)uReadSize,1,fin)!=1)
-			break;
-
-                for (i=(int)uReadSize-3; (i--)>0;)
-			if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
-				((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
-			{
-				uPosFound = uReadPos+i;
-				break;
-			}
-
-		if (uPosFound!=0)
-			break;
-	}
-	free(buf);
-	return uPosFound;
-}
-
-extern unzFile unzReOpen (const char* path, unzFile file)
-{
-	unz_s *s;
-	FILE * fin;
-
-    fin=fopen(path,"rb");
-	if (fin==NULL)
-		return NULL;
-
-	s=(unz_s*)safe_malloc(sizeof(unz_s));
-	memcpy(s, (unz_s*)file, sizeof(unz_s));
-
-	s->file = fin;
-	return (unzFile)s;	
-}
-
-/*
-  Open a Zip file. path contain the full pathname (by example,
-     on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
-	 "zlib/zlib109.zip".
-	 If the zipfile cannot be opened (file don't exist or in not valid), the
-	   return value is NULL.
-     Else, the return value is a unzFile Handle, usable with other function
-	   of this unzip package.
-*/
-extern unzFile unzOpen (const char* path)
-{
-	unz_s us;
-	unz_s *s;
-	uLong central_pos,uL;
-	FILE * fin ;
-
-	uLong number_disk;          /* number of the current dist, used for 
-								   spaning ZIP, unsupported, always 0*/
-	uLong number_disk_with_CD;  /* number the the disk with central dir, used
-								   for spaning ZIP, unsupported, always 0*/
-	uLong number_entry_CD;      /* total number of entries in
-	                               the central dir 
-	                               (same than number_entry on nospan) */
-
-	int err=UNZ_OK;
-
-    fin=fopen(path,"rb");
-	if (fin==NULL)
-		return NULL;
-
-	central_pos = unzlocal_SearchCentralDir(fin);
-	if (central_pos==0)
-		err=UNZ_ERRNO;
-
-	if (fseek(fin,central_pos,SEEK_SET)!=0)
-		err=UNZ_ERRNO;
-
-	/* the signature, already checked */
-	if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	/* number of this disk */
-	if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	/* number of the disk with the start of the central directory */
-	if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	/* total number of entries in the central dir on this disk */
-	if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	/* total number of entries in the central dir */
-	if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if ((number_entry_CD!=us.gi.number_entry) ||
-		(number_disk_with_CD!=0) ||
-		(number_disk!=0))
-		err=UNZ_BADZIPFILE;
-
-	/* size of the central directory */
-	if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	/* offset of start of central directory with respect to the 
-	      starting disk number */
-	if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	/* zipfile comment length */
-	if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
-		(err==UNZ_OK))
-		err=UNZ_BADZIPFILE;
-
-	if (err!=UNZ_OK)
-	{
-		fclose(fin);
-		return NULL;
-	}
-
-	us.file=fin;
-	us.byte_before_the_zipfile = central_pos -
-		                    (us.offset_central_dir+us.size_central_dir);
-	us.central_pos = central_pos;
-    us.pfile_in_zip_read = NULL;
-	
-
-	s=(unz_s*)safe_malloc(sizeof(unz_s));
-	*s=us;
-//	unzGoToFirstFile((unzFile)s);	
-	return (unzFile)s;	
-}
-
-
-/*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
-  return UNZ_OK if there is no problem. */
-extern int unzClose (unzFile file)
-{
-	unz_s* s;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-
-    if (s->pfile_in_zip_read!=NULL)
-        unzCloseCurrentFile(file);
-
-	fclose(s->file);
-	free(s);
-	return UNZ_OK;
-}
-
-
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem. */
-extern int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info)
-{
-	unz_s* s;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	*pglobal_info=s->gi;
-	return UNZ_OK;
-}
-
-
-/*
-   Translate date/time from Dos format to tm_unz (readable more easilty)
-*/
-static void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
-{
-    uLong uDate;
-    uDate = (uLong)(ulDosDate>>16);
-    ptm->tm_mday = (uInt)(uDate&0x1f) ;
-    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
-    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
-
-    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
-    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
-    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
-}
-
-/*
-  Get Info about the current file in the zipfile, with internal only info
-*/
-static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
-                                                  unz_file_info *pfile_info,
-                                                  unz_file_info_internal 
-                                                  *pfile_info_internal,
-                                                  char *szFileName,
-												  uLong fileNameBufferSize,
-                                                  void *extraField,
-												  uLong extraFieldBufferSize,
-                                                  char *szComment,
-												  uLong commentBufferSize)
-{
-	unz_s* s;
-	unz_file_info file_info;
-	unz_file_info_internal file_info_internal;
-	int err=UNZ_OK;
-	uLong uMagic;
-	long lSeek=0;
-
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
-		err=UNZ_ERRNO;
-
-
-	/* we check the magic */
-	if (err==UNZ_OK)
-		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
-			err=UNZ_ERRNO;
-		else if (uMagic!=0x02014b50)
-			err=UNZ_BADZIPFILE;
-
-	if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
-
-	if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	lSeek+=file_info.size_filename;
-	if ((err==UNZ_OK) && (szFileName!=NULL))
-	{
-		uLong uSizeRead ;
-		if (file_info.size_filename<fileNameBufferSize)
-		{
-			*(szFileName+file_info.size_filename)='\0';
-			uSizeRead = file_info.size_filename;
-		}
-		else
-			uSizeRead = fileNameBufferSize;
-
-		if ((file_info.size_filename>0) && (fileNameBufferSize>0))
-			if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
-				err=UNZ_ERRNO;
-		lSeek -= uSizeRead;
-	}
-
-	
-	if ((err==UNZ_OK) && (extraField!=NULL))
-	{
-		uLong uSizeRead ;
-		if (file_info.size_file_extra<extraFieldBufferSize)
-			uSizeRead = file_info.size_file_extra;
-		else
-			uSizeRead = extraFieldBufferSize;
-
-		if (lSeek!=0)
-			if (fseek(s->file,lSeek,SEEK_CUR)==0)
-				lSeek=0;
-			else
-				err=UNZ_ERRNO;
-		if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
-			if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
-				err=UNZ_ERRNO;
-		lSeek += file_info.size_file_extra - uSizeRead;
-	}
-	else
-		lSeek+=file_info.size_file_extra; 
-
-	
-	if ((err==UNZ_OK) && (szComment!=NULL))
-	{
-		uLong uSizeRead ;
-		if (file_info.size_file_comment<commentBufferSize)
-		{
-			*(szComment+file_info.size_file_comment)='\0';
-			uSizeRead = file_info.size_file_comment;
-		}
-		else
-			uSizeRead = commentBufferSize;
-
-		if (lSeek!=0)
-			if (fseek(s->file,lSeek,SEEK_CUR)==0)
-				lSeek=0;
-			else
-				err=UNZ_ERRNO;
-		if ((file_info.size_file_comment>0) && (commentBufferSize>0))
-			if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
-				err=UNZ_ERRNO;
-		lSeek+=file_info.size_file_comment - uSizeRead;
-	}
-	else
-		lSeek+=file_info.size_file_comment;
-
-	if ((err==UNZ_OK) && (pfile_info!=NULL))
-		*pfile_info=file_info;
-
-	if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
-		*pfile_info_internal=file_info_internal;
-
-	return err;
-}
-
-
-
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem.
-*/
-extern int unzGetCurrentFileInfo (	unzFile file, unz_file_info *pfile_info,
-									char *szFileName, uLong fileNameBufferSize,
-									void *extraField, uLong extraFieldBufferSize,
-									char *szComment, uLong commentBufferSize)
-{
-	return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
-												szFileName,fileNameBufferSize,
-												extraField,extraFieldBufferSize,
-												szComment,commentBufferSize);
-}
-
-/*
-  Set the current file of the zipfile to the first file.
-  return UNZ_OK if there is no problem
-*/
-extern int unzGoToFirstFile (unzFile file)
-{
-	int err=UNZ_OK;
-	unz_s* s;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	s->pos_in_central_dir=s->offset_central_dir;
-	s->num_file=0;
-	err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-											 &s->cur_file_info_internal,
-											 NULL,0,NULL,0,NULL,0);
-	s->current_file_ok = (err == UNZ_OK);
-	return err;
-}
-
-
-/*
-  Set the current file of the zipfile to the next file.
-  return UNZ_OK if there is no problem
-  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
-*/
-extern int unzGoToNextFile (unzFile file)
-{
-	unz_s* s;	
-	int err;
-
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	if (!s->current_file_ok)
-		return UNZ_END_OF_LIST_OF_FILE;
-	if (s->num_file+1==s->gi.number_entry)
-		return UNZ_END_OF_LIST_OF_FILE;
-
-	s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
-			s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
-	s->num_file++;
-	err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
-											   &s->cur_file_info_internal,
-											   NULL,0,NULL,0,NULL,0);
-	s->current_file_ok = (err == UNZ_OK);
-	return err;
-}
-
-
-/*
-  Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzipStringFileNameCompare
-
-  return value :
-  UNZ_OK if the file is found. It becomes the current file.
-  UNZ_END_OF_LIST_OF_FILE if the file is not found
-*/
-extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
-{
-	unz_s* s;	
-	int err;
-
-	
-	uLong num_fileSaved;
-	uLong pos_in_central_dirSaved;
-
-
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-
-    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
-        return UNZ_PARAMERROR;
-
-	s=(unz_s*)file;
-	if (!s->current_file_ok)
-		return UNZ_END_OF_LIST_OF_FILE;
-
-	num_fileSaved = s->num_file;
-	pos_in_central_dirSaved = s->pos_in_central_dir;
-
-	err = unzGoToFirstFile(file);
-
-	while (err == UNZ_OK)
-	{
-		char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
-		unzGetCurrentFileInfo(file,NULL,
-								szCurrentFileName,sizeof(szCurrentFileName)-1,
-								NULL,0,NULL,0);
-		if (unzStringFileNameCompare(szCurrentFileName,
-										szFileName,iCaseSensitivity)==0)
-			return UNZ_OK;
-		err = unzGoToNextFile(file);
-	}
-
-	s->num_file = num_fileSaved ;
-	s->pos_in_central_dir = pos_in_central_dirSaved ;
-	return err;
-}
-
-
-/*
-  Read the static header of the current zipfile
-  Check the coherency of the static header and info in the end of central
-        directory about this file
-  store in *piSizeVar the size of extra info in static header
-        (filename and size of extra field data)
-*/
-static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
-													uLong *poffset_local_extrafield,
-													uInt *psize_local_extrafield)
-{
-	uLong uMagic,uData,uFlags;
-	uLong size_filename;
-	uLong size_extra_field;
-	int err=UNZ_OK;
-
-	*piSizeVar = 0;
-	*poffset_local_extrafield = 0;
-	*psize_local_extrafield = 0;
-
-	if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
-								s->byte_before_the_zipfile,SEEK_SET)!=0)
-		return UNZ_ERRNO;
-
-
-	if (err==UNZ_OK)
-		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
-			err=UNZ_ERRNO;
-		else if (uMagic!=0x04034b50)
-			err=UNZ_BADZIPFILE;
-
-	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
-		err=UNZ_ERRNO;
-/*
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
-		err=UNZ_BADZIPFILE;
-*/
-	if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
-		err=UNZ_BADZIPFILE;
-
-    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
-                         (s->cur_file_info.compression_method!=Z_DEFLATED))
-        err=UNZ_BADZIPFILE;
-
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
-		err=UNZ_ERRNO;
-
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
-		                      ((uFlags & 8)==0))
-		err=UNZ_BADZIPFILE;
-
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
-							  ((uFlags & 8)==0))
-		err=UNZ_BADZIPFILE;
-
-	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
-							  ((uFlags & 8)==0))
-		err=UNZ_BADZIPFILE;
-
-
-	if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
-		err=UNZ_ERRNO;
-	else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
-		err=UNZ_BADZIPFILE;
-
-	*piSizeVar += (uInt)size_filename;
-
-	if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
-		err=UNZ_ERRNO;
-	*poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
-									SIZEZIPLOCALHEADER + size_filename;
-	*psize_local_extrafield = (uInt)size_extra_field;
-
-	*piSizeVar += (uInt)size_extra_field;
-
-	return err;
-}
-												
-/*
-  Open for reading data the current file in the zipfile.
-  If there is no error and the file is opened, the return value is UNZ_OK.
-*/
-extern int unzOpenCurrentFile (unzFile file)
-{
-	int err=UNZ_OK;
-	int Store;
-	uInt iSizeVar;
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	uLong offset_local_extrafield;  /* offset of the static extra field */
-	uInt  size_local_extrafield;    /* size of the static extra field */
-
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-	if (!s->current_file_ok)
-		return UNZ_PARAMERROR;
-
-    if (s->pfile_in_zip_read != NULL)
-        unzCloseCurrentFile(file);
-
-	if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
-				&offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
-		return UNZ_BADZIPFILE;
-
-	pfile_in_zip_read_info = (file_in_zip_read_info_s*)
-									    safe_malloc(sizeof(file_in_zip_read_info_s));
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_INTERNALERROR;
-
-	pfile_in_zip_read_info->read_buffer=(char*)safe_malloc(UNZ_BUFSIZE);
-	pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
-	pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
-	pfile_in_zip_read_info->pos_local_extrafield=0;
-
-	if (pfile_in_zip_read_info->read_buffer==NULL)
-	{
-		free(pfile_in_zip_read_info);
-		return UNZ_INTERNALERROR;
-	}
-
-	pfile_in_zip_read_info->stream_initialised=0;
-	
-	if ((s->cur_file_info.compression_method!=0) &&
-        (s->cur_file_info.compression_method!=Z_DEFLATED))
-		err=UNZ_BADZIPFILE;
-	Store = s->cur_file_info.compression_method==0;
-
-	pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
-	pfile_in_zip_read_info->crc32=0;
-	pfile_in_zip_read_info->compression_method =
-            s->cur_file_info.compression_method;
-	pfile_in_zip_read_info->file=s->file;
-	pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
-
-    pfile_in_zip_read_info->stream.total_out = 0;
-
-	if (!Store)
-	{
-	  pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
-	  pfile_in_zip_read_info->stream.zfree = (free_func)0;
-	  pfile_in_zip_read_info->stream.opaque = (voidp)0; 
-      
-	  err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
-	  if (err == Z_OK)
-	    pfile_in_zip_read_info->stream_initialised=1;
-        /* windowBits is passed < 0 to tell that there is no zlib header.
-         * Note that in this case inflate *requires* an extra "dummy" byte
-         * after the compressed stream in order to complete decompression and
-         * return Z_STREAM_END. 
-         * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
-         * size of both compressed and uncompressed data
-         */
-	}
-	pfile_in_zip_read_info->rest_read_compressed = 
-            s->cur_file_info.compressed_size ;
-	pfile_in_zip_read_info->rest_read_uncompressed = 
-            s->cur_file_info.uncompressed_size ;
-
-	
-	pfile_in_zip_read_info->pos_in_zipfile = 
-            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
-			  iSizeVar;
-	
-	pfile_in_zip_read_info->stream.avail_in = (uInt)0;
-
-
-	s->pfile_in_zip_read = pfile_in_zip_read_info;
-    return UNZ_OK;
-}
-
-
-/*
-  Read bytes from the current file.
-  buf contain buffer where data must be copied
-  len the size of buf.
-
-  return the number of byte copied if somes bytes are copied
-  return 0 if the end of file was reached
-  return <0 with error code if there is an error
-    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-extern int unzReadCurrentFile  (unzFile file, void *buf, unsigned len)
-{
-	int err=UNZ_OK;
-	uInt iRead = 0;
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
-
-
-	if ((pfile_in_zip_read_info->read_buffer == NULL))
-		return UNZ_END_OF_LIST_OF_FILE;
-	if (len==0)
-		return 0;
-
-	pfile_in_zip_read_info->stream.next_out = (Byte*)buf;
-
-	pfile_in_zip_read_info->stream.avail_out = (uInt)len;
-	
-	if (len>pfile_in_zip_read_info->rest_read_uncompressed)
-		pfile_in_zip_read_info->stream.avail_out = 
-		  (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
-
-	while (pfile_in_zip_read_info->stream.avail_out>0)
-	{
-		if ((pfile_in_zip_read_info->stream.avail_in==0) &&
-            (pfile_in_zip_read_info->rest_read_compressed>0))
-		{
-			uInt uReadThis = UNZ_BUFSIZE;
-			if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
-				uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
-			if (uReadThis == 0)
-				return UNZ_EOF;
-			if (s->cur_file_info.compressed_size == pfile_in_zip_read_info->rest_read_compressed)
-				if (fseek(pfile_in_zip_read_info->file,
-						  pfile_in_zip_read_info->pos_in_zipfile + 
-							 pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
-					return UNZ_ERRNO;
-			if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
-                         pfile_in_zip_read_info->file)!=1)
-				return UNZ_ERRNO;
-			pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
-
-			pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
-			
-			pfile_in_zip_read_info->stream.next_in = 
-                (Byte*)pfile_in_zip_read_info->read_buffer;
-			pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
-		}
-
-		if (pfile_in_zip_read_info->compression_method==0)
-		{
-			uInt uDoCopy,i ;
-			if (pfile_in_zip_read_info->stream.avail_out < 
-                            pfile_in_zip_read_info->stream.avail_in)
-				uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
-			else
-				uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
-				
-			for (i=0;i<uDoCopy;i++)
-				*(pfile_in_zip_read_info->stream.next_out+i) =
-                        *(pfile_in_zip_read_info->stream.next_in+i);
-					
-			pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
-								pfile_in_zip_read_info->stream.next_out,
-								uDoCopy);
-			pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
-			pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
-			pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
-			pfile_in_zip_read_info->stream.next_out += uDoCopy;
-			pfile_in_zip_read_info->stream.next_in += uDoCopy;
-            pfile_in_zip_read_info->stream.total_out += uDoCopy;
-			iRead += uDoCopy;
-		}
-		else
-		{
-			uLong uTotalOutBefore,uTotalOutAfter;
-			const Byte *bufBefore;
-			uLong uOutThis;
-			int flush=Z_SYNC_FLUSH;
-
-			uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
-			bufBefore = pfile_in_zip_read_info->stream.next_out;
-
-			/*
-			if ((pfile_in_zip_read_info->rest_read_uncompressed ==
-			         pfile_in_zip_read_info->stream.avail_out) &&
-				(pfile_in_zip_read_info->rest_read_compressed == 0))
-				flush = Z_FINISH;
-			*/
-			err=inflate(&pfile_in_zip_read_info->stream,flush);
-
-			uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
-			uOutThis = uTotalOutAfter-uTotalOutBefore;
-			
-			pfile_in_zip_read_info->crc32 = 
-                crc32(pfile_in_zip_read_info->crc32,bufBefore,
-                        (uInt)(uOutThis));
-
-			pfile_in_zip_read_info->rest_read_uncompressed -=
-                uOutThis;
-
-			iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
-            
-			if (err==Z_STREAM_END)
-				return (iRead==0) ? UNZ_EOF : iRead;
-			if (err!=Z_OK) 
-				break;
-		}
-	}
-
-	if (err==Z_OK)
-		return iRead;
-	return err;
-}
-
-
-/*
-  Give the current position in uncompressed data
-*/
-extern long unztell (unzFile file)
-{
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
-
-	return (long)pfile_in_zip_read_info->stream.total_out;
-}
-
-
-/*
-  return 1 if the end of file was reached, 0 elsewhere 
-*/
-extern int unzeof (unzFile file)
-{
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
-	
-	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
-		return 1;
-	else
-		return 0;
-}
-
-
-
-/*
-  Read extra field from the current file (opened by unzOpenCurrentFile)
-  This is the static-header version of the extra field (sometimes, there is
-    more info in the static-header version than in the central-header)
-
-  if buf==NULL, it return the size of the static extra field that can be read
-
-  if buf!=NULL, len is the size of the buffer, the extra header is copied in
-	buf.
-  the return value is the number of bytes copied in buf, or (if <0) 
-	the error code
-*/
-extern int unzGetLocalExtrafield (unzFile file,void *buf,unsigned len)
-{
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	uInt read_now;
-	uLong size_to_read;
-
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
-
-	size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
-				pfile_in_zip_read_info->pos_local_extrafield);
-
-	if (buf==NULL)
-		return (int)size_to_read;
-	
-	if (len>size_to_read)
-		read_now = (uInt)size_to_read;
-	else
-		read_now = (uInt)len ;
-
-	if (read_now==0)
-		return 0;
-	
-	if (fseek(pfile_in_zip_read_info->file,
-              pfile_in_zip_read_info->offset_local_extrafield + 
-			  pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
-		return UNZ_ERRNO;
-
-	if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
-		return UNZ_ERRNO;
-
-	return (int)read_now;
-}
-
-/*
-  Close the file in zip opened with unzipOpenCurrentFile
-  Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-extern int unzCloseCurrentFile (unzFile file)
-{
-	int err=UNZ_OK;
-
-	unz_s* s;
-	file_in_zip_read_info_s* pfile_in_zip_read_info;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-    pfile_in_zip_read_info=s->pfile_in_zip_read;
-
-	if (pfile_in_zip_read_info==NULL)
-		return UNZ_PARAMERROR;
-
-
-	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
-	{
-		if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
-			err=UNZ_CRCERROR;
-	}
-
-
-	free(pfile_in_zip_read_info->read_buffer);
-	pfile_in_zip_read_info->read_buffer = NULL;
-	if (pfile_in_zip_read_info->stream_initialised)
-		inflateEnd(&pfile_in_zip_read_info->stream);
-
-	pfile_in_zip_read_info->stream_initialised = 0;
-	free(pfile_in_zip_read_info);
-
-    s->pfile_in_zip_read=NULL;
-
-	return err;
-}
-
-
-/*
-  Get the global comment string of the ZipFile, in the szComment buffer.
-  uSizeBuf is the size of the szComment buffer.
-  return the number of byte copied or an error code <0
-*/
-extern int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)
-{
-	unz_s* s;
-	uLong uReadThis ;
-	if (file==NULL)
-		return UNZ_PARAMERROR;
-	s=(unz_s*)file;
-
-	uReadThis = uSizeBuf;
-	if (uReadThis>s->gi.size_comment)
-		uReadThis = s->gi.size_comment;
-
-	if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
-		return UNZ_ERRNO;
-
-	if (uReadThis>0)
-    {
-      *szComment='\0';
-	  if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
-		return UNZ_ERRNO;
-    }
-
-	if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
-		*(szComment+s->gi.size_comment)='\0';
-	return (int)uReadThis;
-}
-
-/* crc32.c -- compute the CRC-32 of a data stream
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-
-#ifdef DYNAMIC_CRC_TABLE
-
-static int crc_table_empty = 1;
-static uLong crc_table[256];
-static void make_crc_table OF((void));
-
-/*
-  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
-  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
-
-  Polynomials over GF(2) are represented in binary, one bit per coefficient,
-  with the lowest powers in the most significant bit.  Then adding polynomials
-  is just exclusive-or, and multiplying a polynomial by x is a right shift by
-  one.  If we call the above polynomial p, and represent a byte as the
-  polynomial q, also with the lowest power in the most significant bit (so the
-  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
-  where a mod b means the remainder after dividing a by b.
-
-  This calculation is done using the shift-register method of multiplying and
-  taking the remainder.  The register is initialized to zero, and for each
-  incoming bit, x^32 is added mod p to the register if the bit is a one (where
-  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
-  x (which is shifting right by one and adding x^32 mod p if the bit shifted
-  out is a one).  We start with the highest power (least significant bit) of
-  q and repeat for all eight bits of q.
-
-  The table is simply the CRC of all possible eight bit values.  This is all
-  the information needed to generate CRC's on data a byte at a time for all
-  combinations of CRC register values and incoming bytes.
-*/
-static void make_crc_table()
-{
-  uLong c;
-  int n, k;
-  uLong poly;            /* polynomial exclusive-or pattern */
-  /* terms of polynomial defining this crc (except x^32): */
-  static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
-
-  /* make exclusive-or pattern from polynomial (0xedb88320L) */
-  poly = 0L;
-  for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
-    poly |= 1L << (31 - p[n]);
- 
-  for (n = 0; n < 256; n++)
-  {
-    c = (uLong)n;
-    for (k = 0; k < 8; k++)
-      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
-    crc_table[n] = c;
-  }
-  crc_table_empty = 0;
-}
-#else
-/* ========================================================================
- * Table of CRC-32's of all single-byte values (made by make_crc_table)
- */
-static const uLong crc_table[256] = {
-  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
-  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
-  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
-  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
-  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
-  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
-  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
-  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
-  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
-  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
-  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
-  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
-  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
-  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
-  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
-  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
-  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
-  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
-  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
-  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
-  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
-  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
-  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
-  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
-  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
-  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
-  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
-  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
-  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
-  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
-  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
-  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
-  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
-  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
-  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
-  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
-  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
-  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
-  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
-  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
-  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
-  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
-  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
-  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
-  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
-  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
-  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
-  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
-  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
-  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
-  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
-  0x2d02ef8dL
-};
-#endif
-
-/* =========================================================================
- * This function can be used by asm versions of crc32()
- */
-#ifndef __APPLE__
-const uLong * get_crc_table()
-{
-#ifdef DYNAMIC_CRC_TABLE
-  if (crc_table_empty) make_crc_table();
-#endif
-  return (const uLong *)crc_table;
-}
-#endif
-
-/* ========================================================================= */
-#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
-#define DO2(buf)  DO1(buf); DO1(buf);
-#define DO4(buf)  DO2(buf); DO2(buf);
-#define DO8(buf)  DO4(buf); DO4(buf);
-
-/* ========================================================================= */
-#ifndef __APPLE__
-uLong crc32(uLong crc, const Byte *buf, uInt len)
-{
-    if (buf == Z_NULL) return 0L;
-#ifdef DYNAMIC_CRC_TABLE
-    if (crc_table_empty)
-      make_crc_table();
-#endif
-    crc = crc ^ 0xffffffffL;
-    while (len >= 8)
-    {
-      DO8(buf);
-      len -= 8;
-    }
-    if (len) do {
-      DO1(buf);
-    } while (--len);
-    return crc ^ 0xffffffffL;
-}
-#endif
-
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_blocks_state;
-typedef struct inflate_blocks_state inflate_blocks_statef;
-
-extern inflate_blocks_statef * inflate_blocks_new OF((
-    z_streamp z,
-    check_func c,               /* check function */
-    uInt w));                   /* window size */
-
-extern int inflate_blocks OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    int));                      /* initial return code */
-
-extern void inflate_blocks_reset OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    uLong *));                  /* check value on output */
-
-extern int inflate_blocks_free OF((
-    inflate_blocks_statef *,
-    z_streamp));
-
-extern void inflate_set_dictionary OF((
-    inflate_blocks_statef *s,
-    const Byte *d,  /* dictionary */
-    uInt  n));       /* dictionary length */
-
-extern int inflate_blocks_sync_point OF((
-    inflate_blocks_statef *s));
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* Table for deflate from PKZIP's appnote.txt. */
-static const uInt border[] = { /* Order of the bit length code lengths */
-        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
-
-/* inftrees.h -- header to use inftrees.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-/* Huffman code lookup table entry--this entry is four bytes for machines
-   that have 16-bit pointers (e.g. PC's in the small or medium model). */
-
-typedef struct inflate_huft_s inflate_huft;
-
-struct inflate_huft_s {
-  union {
-    struct {
-      Byte Exop;        /* number of extra bits or operation */
-      Byte Bits;        /* number of bits in this code or subcode */
-    } what;
-    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
-  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
-  uInt base;            /* literal, length base, distance base,
-                           or table offset */
-};
-
-/* Maximum size of dynamic tree.  The maximum found in a long but non-
-   exhaustive search was 1004 huft structures (850 for length/literals
-   and 154 for distances, the latter actually the result of an
-   exhaustive search).  The actual maximum is not known, but the
-   value below is more than safe. */
-#define MANY 1440
-
-extern int inflate_trees_bits OF((
-    uInt *,                    /* 19 code lengths */
-    uInt *,                    /* bits tree desired/actual depth */
-    inflate_huft * *,       /* bits tree result */
-    inflate_huft *,             /* space for trees */
-    z_streamp));                /* for messages */
-
-extern int inflate_trees_dynamic OF((
-    uInt,                       /* number of literal/length codes */
-    uInt,                       /* number of distance codes */
-    uInt *,                    /* that many (total) code lengths */
-    uInt *,                    /* literal desired/actual bit depth */
-    uInt *,                    /* distance desired/actual bit depth */
-    inflate_huft * *,       /* literal/length tree result */
-    inflate_huft * *,       /* distance tree result */
-    inflate_huft *,             /* space for trees */
-    z_streamp));                /* for messages */
-
-extern int inflate_trees_fixed OF((
-    uInt *,                    /* literal desired/actual bit depth */
-    uInt *,                    /* distance desired/actual bit depth */
-    inflate_huft * *,       /* literal/length tree result */
-    inflate_huft * *,       /* distance tree result */
-    z_streamp));                /* for memory allocation */
-
-
-/* infcodes.h -- header to use infcodes.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-struct inflate_codes_state;
-typedef struct inflate_codes_state inflate_codes_statef;
-
-extern inflate_codes_statef *inflate_codes_new OF((
-    uInt, uInt,
-    inflate_huft *, inflate_huft *,
-    z_streamp ));
-
-extern int inflate_codes OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    int));
-
-extern void inflate_codes_free OF((
-    inflate_codes_statef *,
-    z_streamp ));
-
-/* infutil.h -- types and macros common to blocks and codes
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-#ifndef _INFUTIL_H
-#define _INFUTIL_H
-
-typedef enum {
-      TYPE,     /* get type bits (3, including end bit) */
-      LENS,     /* get lengths for stored */
-      STORED,   /* processing stored block */
-      TABLE,    /* get table lengths */
-      BTREE,    /* get bit lengths tree for a dynamic block */
-      DTREE,    /* get length, distance trees for a dynamic block */
-      CODES,    /* processing fixed or dynamic block */
-      DRY,      /* output remaining window bytes */
-      DONE,     /* finished last block, done */
-      BAD}      /* got a data error--stuck here */
-inflate_block_mode;
-
-/* inflate blocks semi-private state */
-struct inflate_blocks_state {
-
-  /* mode */
-  inflate_block_mode  mode;     /* current inflate_block mode */
-
-  /* mode dependent information */
-  union {
-    uInt left;          /* if STORED, bytes left to copy */
-    struct {
-      uInt table;               /* table lengths (14 bits) */
-      uInt index;               /* index into blens (or border) */
-      uInt *blens;             /* bit lengths of codes */
-      uInt bb;                  /* bit length tree depth */
-      inflate_huft *tb;         /* bit length decoding tree */
-    } trees;            /* if DTREE, decoding info for trees */
-    struct {
-      inflate_codes_statef 
-         *codes;
-    } decode;           /* if CODES, current state */
-  } sub;                /* submode */
-  uInt last;            /* true if this block is the last block */
-
-  /* mode independent information */
-  uInt bitk;            /* bits in bit buffer */
-  uLong bitb;           /* bit buffer */
-  inflate_huft *hufts;  /* single safe_malloc for tree space */
-  Byte *window;        /* sliding window */
-  Byte *end;           /* one byte after sliding window */
-  Byte *read;          /* window read pointer */
-  Byte *write;         /* window write pointer */
-  check_func checkfn;   /* check function */
-  uLong check;          /* check on output */
-
-};
-
-
-/* defines for inflate input/output */
-/*   update pointers and return */
-#define UPDBITS {s->bitb=b;s->bitk=k;}
-#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
-#define UPDOUT {s->write=q;}
-#define UPDATE {UPDBITS UPDIN UPDOUT}
-#define LEAVE {UPDATE return inflate_flush(s,z,r);}
-/*   get bytes and bits */
-#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
-#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
-#define NEXTBYTE (n--,*p++)
-#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define DUMPBITS(j) {b>>=(j);k-=(j);}
-/*   output bytes */
-#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
-#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
-#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
-#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
-#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
-#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
-/*   load static pointers */
-#define LOAD {LOADIN LOADOUT}
-
-/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
-extern uInt inflate_mask[17];
-
-/* copy as much as possible from the sliding window to the output area */
-extern int inflate_flush OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    int));
-
-#endif
-
-								
-/*
-   Notes beyond the 1.93a appnote.txt:
-
-   1. Distance pointers never point before the beginning of the output
-      stream.
-   2. Distance pointers can point back across blocks, up to 32k away.
-   3. There is an implied maximum of 7 bits for the bit length table and
-      15 bits for the actual data.
-   4. If only one code exists, then it is encoded using one bit.  (Zero
-      would be more efficient, but perhaps a little confusing.)  If two
-      codes exist, they are coded using one bit each (0 and 1).
-   5. There is no way of sending zero distance codes--a dummy must be
-      sent if there are none.  (History: a pre 2.0 version of PKZIP would
-      store blocks with no distance codes, but this was discovered to be
-      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
-      zero distance codes, which is sent as one code of zero bits in
-      length.
-   6. There are up to 286 literal/length codes.  Code 256 represents the
-      end-of-block.  Note however that the static length tree defines
-      288 codes just to fill out the Huffman codes.  Codes 286 and 287
-      cannot be used though, since there is no length base or extra bits
-      defined for them.  Similarily, there are up to 30 distance codes.
-      However, static trees define 32 codes (all 5 bits) to fill out the
-      Huffman codes, but the last two had better not show up in the data.
-   7. Unzip can check dynamic Huffman blocks for complete code sets.
-      The exception is that a single code would not be complete (see #4).
-   8. The five bits following the block type is really the number of
-      literal codes sent minus 257.
-   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
-      (1+6+6).  Therefore, to output three times the length, you output
-      three codes (1+1+1), whereas to output four times the same length,
-      you only need two codes (1+3).  Hmm.
-  10. In the tree reconstruction algorithm, Code = Code + Increment
-      only if BitLength(i) is not zero.  (Pretty obvious.)
-  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
-  12. Note: length code 284 can represent 227-258, but length code 285
-      really is 258.  The last length deserves its own, short code
-      since it gets used a lot in very redundant files.  The length
-      258 is special since 258 - 3 (the min match length) is 255.
-  13. The literal/length and distance code bit lengths are read as a
-      single stream of lengths.  It is possible (and advantageous) for
-      a repeat code (16, 17, or 18) to go across the boundary between
-      the two sets of lengths.
- */
-
-
-#ifndef __APPLE__
-void inflate_blocks_reset(inflate_blocks_statef *s, z_streamp z, uLong *c)
-{
-  if (c != Z_NULL)
-    *c = s->check;
-  if (s->mode == BTREE || s->mode == DTREE)
-    ZFREE(z, s->sub.trees.blens);
-  if (s->mode == CODES)
-    inflate_codes_free(s->sub.decode.codes, z);
-  s->mode = TYPE;
-  s->bitk = 0;
-  s->bitb = 0;
-  s->read = s->write = s->window;
-  if (s->checkfn != Z_NULL)
-    z->adler = s->check = (*s->checkfn)(0L, (const Byte *)Z_NULL, 0);
-  Tracev(("inflate:   blocks reset\n"));
-}
-#endif
-
-#ifndef __APPLE__
-inflate_blocks_statef *inflate_blocks_new(z_streamp z, check_func c, uInt w)
-{
-  inflate_blocks_statef *s;
-
-  if ((s = (inflate_blocks_statef *)ZALLOC
-       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
-    return s;
-  if ((s->hufts =
-       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
-  {
-    ZFREE(z, s);
-    return Z_NULL;
-  }
-  if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL)
-  {
-    ZFREE(z, s->hufts);
-    ZFREE(z, s);
-    return Z_NULL;
-  }
-  s->end = s->window + w;
-  s->checkfn = c;
-  s->mode = TYPE;
-  Tracev(("inflate:   blocks allocated\n"));
-  inflate_blocks_reset(s, z, Z_NULL);
-  return s;
-}
-#endif
-
-#ifndef __APPLE__
-int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r)
-{
-  uInt t;               /* temporary storage */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Byte *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Byte *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input based on current state */
-  while (1) switch (s->mode)
-  {
-    case TYPE:
-      NEEDBITS(3)
-      t = (uInt)b & 7;
-      s->last = t & 1;
-      switch (t >> 1)
-      {
-        case 0:                         /* stored */
-          Tracev(("inflate:     stored block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          t = k & 7;                    /* go to byte boundary */
-          DUMPBITS(t)
-          s->mode = LENS;               /* get length of stored block */
-          break;
-        case 1:                         /* fixed */
-          Tracev(("inflate:     fixed codes block%s\n",
-                 s->last ? " (last)" : ""));
-          {
-            uInt bl, bd;
-            inflate_huft *tl, *td;
-
-            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
-            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
-            if (s->sub.decode.codes == Z_NULL)
-            {
-              r = Z_MEM_ERROR;
-              LEAVE
-            }
-          }
-          DUMPBITS(3)
-          s->mode = CODES;
-          break;
-        case 2:                         /* dynamic */
-          Tracev(("inflate:     dynamic codes block%s\n",
-                 s->last ? " (last)" : ""));
-          DUMPBITS(3)
-          s->mode = TABLE;
-          break;
-        case 3:                         /* illegal */
-          DUMPBITS(3)
-          s->mode = BAD;
-          z->msg = (char*)"invalid block type";
-          r = Z_DATA_ERROR;
-          LEAVE
-      }
-      break;
-    case LENS:
-      NEEDBITS(32)
-      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
-      {
-        s->mode = BAD;
-        z->msg = (char*)"invalid stored block lengths";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-      s->sub.left = (uInt)b & 0xffff;
-      b = k = 0;                      /* dump bits */
-      Tracev(("inflate:       stored length %u\n", s->sub.left));
-      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
-      break;
-    case STORED:
-      if (n == 0)
-        LEAVE
-      NEEDOUT
-      t = s->sub.left;
-      if (t > n) t = n;
-      if (t > m) t = m;
-      zmemcpy(q, p, t);
-      p += t;  n -= t;
-      q += t;  m -= t;
-      if ((s->sub.left -= t) != 0)
-        break;
-      Tracev(("inflate:       stored end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      s->mode = s->last ? DRY : TYPE;
-      break;
-    case TABLE:
-      NEEDBITS(14)
-      s->sub.trees.table = t = (uInt)b & 0x3fff;
-#ifndef PKZIP_BUG_WORKAROUND
-      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
-      {
-        s->mode = BAD;
-        z->msg = (char*)"too many length or distance symbols";
-        r = Z_DATA_ERROR;
-        LEAVE
-      }
-#endif
-      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
-      if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
-      {
-        r = Z_MEM_ERROR;
-        LEAVE
-      }
-      DUMPBITS(14)
-      s->sub.trees.index = 0;
-      Tracev(("inflate:       table sizes ok\n"));
-      s->mode = BTREE;
-    case BTREE:
-      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
-      {
-        NEEDBITS(3)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
-        DUMPBITS(3)
-      }
-      while (s->sub.trees.index < 19)
-        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
-      s->sub.trees.bb = 7;
-      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
-                             &s->sub.trees.tb, s->hufts, z);
-      if (t != Z_OK)
-      {
-        ZFREE(z, s->sub.trees.blens);
-        r = t;
-        if (r == Z_DATA_ERROR)
-          s->mode = BAD;
-        LEAVE
-      }
-      s->sub.trees.index = 0;
-      Tracev(("inflate:       bits tree ok\n"));
-      s->mode = DTREE;
-    case DTREE:
-      while (t = s->sub.trees.table,
-             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
-      {
-        inflate_huft *h;
-        uInt i, j, c;
-
-        t = s->sub.trees.bb;
-        NEEDBITS(t)
-        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
-        t = h->bits;
-        c = h->base;
-        if (c < 16)
-        {
-          DUMPBITS(t)
-          s->sub.trees.blens[s->sub.trees.index++] = c;
-        }
-        else /* c == 16..18 */
-        {
-          i = c == 18 ? 7 : c - 14;
-          j = c == 18 ? 11 : 3;
-          NEEDBITS(t + i)
-          DUMPBITS(t)
-          j += (uInt)b & inflate_mask[i];
-          DUMPBITS(i)
-          i = s->sub.trees.index;
-          t = s->sub.trees.table;
-          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
-              (c == 16 && i < 1))
-          {
-            ZFREE(z, s->sub.trees.blens);
-            s->mode = BAD;
-            z->msg = (char*)"invalid bit length repeat";
-            r = Z_DATA_ERROR;
-            LEAVE
-          }
-          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
-          do {
-            s->sub.trees.blens[i++] = c;
-          } while (--j);
-          s->sub.trees.index = i;
-        }
-      }
-      s->sub.trees.tb = Z_NULL;
-      {
-        uInt bl, bd;
-        inflate_huft *tl, *td;
-        inflate_codes_statef *c;
-
-        bl = 9;         /* must be <= 9 for lookahead assumptions */
-        bd = 6;         /* must be <= 9 for lookahead assumptions */
-        t = s->sub.trees.table;
-        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
-                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
-                                  s->hufts, z);
-        ZFREE(z, s->sub.trees.blens);
-        if (t != Z_OK)
-        {
-          if (t == (uInt)Z_DATA_ERROR)
-            s->mode = BAD;
-          r = t;
-          LEAVE
-        }
-        Tracev(("inflate:       trees ok\n"));
-        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
-        {
-          r = Z_MEM_ERROR;
-          LEAVE
-        }
-        s->sub.decode.codes = c;
-      }
-      s->mode = CODES;
-    case CODES:
-      UPDATE
-      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
-        return inflate_flush(s, z, r);
-      r = Z_OK;
-      inflate_codes_free(s->sub.decode.codes, z);
-      LOAD
-      Tracev(("inflate:       codes end, %lu total out\n",
-              z->total_out + (q >= s->read ? q - s->read :
-              (s->end - s->read) + (q - s->window))));
-      if (!s->last)
-      {
-        s->mode = TYPE;
-        break;
-      }
-      s->mode = DRY;
-    case DRY:
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      s->mode = DONE;
-    case DONE:
-      r = Z_STREAM_END;
-      LEAVE
-    case BAD:
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-}
-#endif
-
-#ifndef __APPLE__
-int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z)
-{
-  inflate_blocks_reset(s, z, Z_NULL);
-  ZFREE(z, s->window);
-  ZFREE(z, s->hufts);
-  ZFREE(z, s);
-  Tracev(("inflate:   blocks freed\n"));
-  return Z_OK;
-}
-#endif
-
-#ifndef __APPLE__
-void inflate_set_dictionary(inflate_blocks_statef *s, const Byte *d, uInt n)
-{
-  zmemcpy(s->window, d, n);
-  s->read = s->write = s->window + n;
-}
-#endif
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
- * IN assertion: s != Z_NULL
- */
-#ifndef __APPLE__
-int inflate_blocks_sync_point(inflate_blocks_statef *s)
-{
-  return s->mode == LENS;
-}
-#endif
-
-/* And'ing with mask[n] masks the lower n bits */
-uInt inflate_mask[17] = {
-    0x0000,
-    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
-    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
-};
-
-/* copy as much as possible from the sliding window to the output area */
-#ifndef __APPLE__
-int inflate_flush(inflate_blocks_statef *s, z_streamp z, int r)
-{
-  uInt n;
-  Byte *p;
-  Byte *q;
-
-  /* static copies of source and destination pointers */
-  p = z->next_out;
-  q = s->read;
-
-  /* compute number of bytes to copy as as end of window */
-  n = (uInt)((q <= s->write ? s->write : s->end) - q);
-  if (n > z->avail_out) n = z->avail_out;
-  if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-  /* update counters */
-  z->avail_out -= n;
-  z->total_out += n;
-
-  /* update check information */
-  if (s->checkfn != Z_NULL)
-    z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
-  /* copy as as end of window */
-  zmemcpy(p, q, n);
-  p += n;
-  q += n;
-
-  /* see if more to copy at beginning of window */
-  if (q == s->end)
-  {
-    /* wrap pointers */
-    q = s->window;
-    if (s->write == s->end)
-      s->write = s->window;
-
-    /* compute bytes to copy */
-    n = (uInt)(s->write - q);
-    if (n > z->avail_out) n = z->avail_out;
-    if (n && r == Z_BUF_ERROR) r = Z_OK;
-
-    /* update counters */
-    z->avail_out -= n;
-    z->total_out += n;
-
-    /* update check information */
-    if (s->checkfn != Z_NULL)
-      z->adler = s->check = (*s->checkfn)(s->check, q, n);
-
-    /* copy */
-    zmemcpy(p, q, n);
-    p += n;
-    q += n;
-  }
-
-  /* update pointers */
-  z->next_out = p;
-  s->read = q;
-
-  /* done */
-  return r;
-}
-#endif
-
-/* inftrees.c -- generate Huffman trees for efficient decoding
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#ifndef __APPLE__
-const char inflate_copyright[] =
-   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
-#endif
-
-/*
-  If you use the zlib library in a product, an acknowledgment is welcome
-  in the documentation of your product. If for some reason you cannot
-  include such an acknowledgment, I would appreciate that you keep this
-  copyright string in the executable of your product.
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-
-static int huft_build OF((
-    uInt *,				/* code lengths in bits */
-    uInt,               /* number of codes */
-    uInt,               /* number of "simple" codes */
-    const uInt *,		/* list of base values for non-simple codes */
-    const uInt *,		/* list of extra bits for non-simple codes */
-    inflate_huft **,	/* result: starting table */
-    uInt *,				/* maximum lookup bits (returns actual) */
-    inflate_huft *,     /* space for trees */
-    uInt *,             /* hufts used in space */
-    uInt * ));			/* space for values */
-
-/* Tables for deflate from PKZIP's appnote.txt. */
-static const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
-        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
-        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
-        /* see note #13 above about 258 */
-static const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
-        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
-        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
-static const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
-        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
-        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
-        8193, 12289, 16385, 24577};
-static const uInt cpdext[30] = { /* Extra bits for distance codes */
-        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
-        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
-        12, 12, 13, 13};
-
-/*
-   Huffman code decoding is performed using a multi-level table lookup.
-   The fastest way to decode is to simply build a lookup table whose
-   size is determined by the longest code.  However, the time it takes
-   to build this table can also be a factor if the data being decoded
-   is not very long.  The most common codes are necessarily the
-   shortest codes, so those codes dominate the decoding time, and hence
-   the speed.  The idea is you can have a shorter table that decodes the
-   shorter, more probable codes, and then point to subsidiary tables for
-   the longer codes.  The time it costs to decode the longer codes is
-   then traded against the time it takes to make longer tables.
-
-   This results of this trade are in the variables lbits and dbits
-   below.  lbits is the number of bits the first level table for literal/
-   length codes can decode in one step, and dbits is the same thing for
-   the distance codes.  Subsequent tables are also less than or equal to
-   those sizes.  These values may be adjusted either when all of the
-   codes are shorter than that, in which case the longest code length in
-   bits is used, or when the shortest code is *longer* than the requested
-   table size, in which case the length of the shortest code in bits is
-   used.
-
-   There are two different values for the two tables, since they code a
-   different number of possibilities each.  The literal/length table
-   codes 286 possible values, or in a flat code, a little over eight
-   bits.  The distance table codes 30 possible values, or a little less
-   than five bits, flat.  The optimum values for speed end up being
-   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
-   The optimum values may differ though from machine to machine, and
-   possibly even between compilers.  Your mileage may vary.
- */
-
-
-/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
-#define BMAX 15         /* maximum bit length of any code */
-
-static int huft_build(uInt *b, uInt n, uInt s, const uInt *d, const uInt *e, inflate_huft ** t, uInt *m, inflate_huft *hp, uInt *hn, uInt *v)
-//uInt *b;               /* code lengths in bits (all assumed <= BMAX) */
-//uInt n;                 /* number of codes (assumed <= 288) */
-//uInt s;                 /* number of simple-valued codes (0..s-1) */
-//const uInt *d;         /* list of base values for non-simple codes */
-//const uInt *e;         /* list of extra bits for non-simple codes */
-//inflate_huft ** t;		/* result: starting table */
-//uInt *m;               /* maximum lookup bits, returns actual */
-//inflate_huft *hp;       /* space for trees */
-//uInt *hn;               /* hufts used in space */
-//uInt *v;               /* working area: values in order of bit length */
-/* Given a list of code lengths and a maximum table size, make a set of
-   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
-   if the given code set is incomplete (the tables are still built in this
-   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
-   lengths), or Z_MEM_ERROR if not enough memory. */
-{
-
-  uInt a;                       /* counter for codes of length k */
-  uInt c[BMAX+1];               /* bit length count table */
-  uInt f;                       /* i repeats in table every f entries */
-  int g;                        /* maximum code length */
-  int h;                        /* table level */
-  register uInt i;              /* counter, current code */
-  register uInt j;              /* counter */
-  register int k;               /* number of bits in current code */
-  int l;                        /* bits per table (returned in m) */
-  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
-  register uInt *p;            /* pointer into c[], b[], or v[] */
-  inflate_huft *q;              /* points to current table */
-  struct inflate_huft_s r;      /* table entry for structure assignment */
-  inflate_huft *u[BMAX];        /* table stack */
-  register int w;               /* bits before this table == (l * h) */
-  uInt x[BMAX+1];               /* bit offsets, then code stack */
-  uInt *xp;                    /* pointer into x */
-  int y;                        /* number of dummy codes added */
-  uInt z;                       /* number of entries in current table */
-
-
-  /* Generate counts for each bit length */
-  p = c;
-#define C0 *p++ = 0;
-#define C2 C0 C0 C0 C0
-#define C4 C2 C2 C2 C2
-  C4                            /* clear c[]--assume BMAX+1 is 16 */
-  p = b;  i = n;
-  do {
-    c[*p++]++;                  /* assume all entries <= BMAX */
-  } while (--i);
-  if (c[0] == n)                /* null input--all zero length codes */
-  {
-    *t = (inflate_huft *)Z_NULL;
-    *m = 0;
-    return Z_OK;
-  }
-
-
-  /* Find minimum and maximum length, bound *m by those */
-  l = *m;
-  for (j = 1; j <= BMAX; j++)
-    if (c[j])
-      break;
-  k = j;                        /* minimum code length */
-  if ((uInt)l < j)
-    l = j;
-  for (i = BMAX; i; i--)
-    if (c[i])
-      break;
-  g = i;                        /* maximum code length */
-  if ((uInt)l > i)
-    l = i;
-  *m = l;
-
-
-  /* Adjust last length count to fill out codes, if needed */
-  for (y = 1 << j; j < i; j++, y <<= 1)
-    if ((y -= c[j]) < 0)
-      return Z_DATA_ERROR;
-  if ((y -= c[i]) < 0)
-    return Z_DATA_ERROR;
-  c[i] += y;
-
-
-  /* Generate starting offsets into the value table for each length */
-  x[1] = j = 0;
-  p = c + 1;  xp = x + 2;
-  while (--i) {                 /* note that i == g from above */
-    *xp++ = (j += *p++);
-  }
-
-
-  /* Make a table of values in order of bit lengths */
-  p = b;  i = 0;
-  do {
-    if ((j = *p++) != 0)
-      v[x[j]++] = i;
-  } while (++i < n);
-  n = x[g];                     /* set n to length of v */
-
-
-  /* Generate the Huffman codes and for each, make the table entries */
-  x[0] = i = 0;                 /* first Huffman code is zero */
-  p = v;                        /* grab values in bit order */
-  h = -1;                       /* no tables yet--level -1 */
-  w = -l;                       /* bits decoded == (l * h) */
-  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
-  q = (inflate_huft *)Z_NULL;   /* ditto */
-  z = 0;                        /* ditto */
-
-  /* go through the bit lengths (k already is bits in shortest code) */
-  for (; k <= g; k++)
-  {
-    a = c[k];
-    while (a--)
-    {
-      /* here i is the Huffman code of length k bits for value *p */
-      /* make tables up to required level */
-      while (k > w + l)
-      {
-        h++;
-        w += l;                 /* previous table always l bits */
-
-        /* compute minimum size table less than or equal to l bits */
-        z = g - w;
-        z = z > (uInt)l ? l : z;        /* table size upper limit */
-        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
-        {                       /* too few codes for k-w bit table */
-          f -= a + 1;           /* deduct codes from patterns left */
-          xp = c + k;
-          if (j < z)
-            while (++j < z)     /* try smaller tables up to z bits */
-            {
-              if ((f <<= 1) <= *++xp)
-                break;          /* enough codes to use up j bits */
-              f -= *xp;         /* else deduct codes from patterns */
-            }
-        }
-        z = 1 << j;             /* table entries for j-bit table */
-
-        /* allocate new table */
-        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
-          return Z_MEM_ERROR;   /* not enough memory */
-        u[h] = q = hp + *hn;
-        *hn += z;
-
-        /* connect to last table, if there is one */
-        if (h)
-        {
-          x[h] = i;             /* save pattern for backing up */
-          r.bits = (Byte)l;     /* bits to dump before this table */
-          r.exop = (Byte)j;     /* bits in this table */
-          j = i >> (w - l);
-          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
-          u[h-1][j] = r;        /* connect to last table */
-        }
-        else
-          *t = q;               /* first table is returned result */
-      }
-
-      /* set up table entry in r */
-      r.bits = (Byte)(k - w);
-      if (p >= v + n)
-        r.exop = 128 + 64;      /* out of values--invalid code */
-      else if (*p < s)
-      {
-        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
-        r.base = *p++;          /* simple code is just the value */
-      }
-      else
-      {
-        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
-        r.base = d[*p++ - s];
-      }
-
-      /* fill code-like entries with r */
-      f = 1 << (k - w);
-      for (j = i >> w; j < z; j += f)
-        q[j] = r;
-
-      /* backwards increment the k-bit code i */
-      for (j = 1 << (k - 1); i & j; j >>= 1)
-        i ^= j;
-      i ^= j;
-
-      /* backup over finished tables */
-      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
-      while ((i & mask) != x[h])
-      {
-        h--;                    /* don't need to update q */
-        w -= l;
-        mask = (1 << w) - 1;
-      }
-    }
-  }
-
-
-  /* Return Z_BUF_ERROR if we were given an incomplete table */
-  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
-}
-
-
-#ifndef __APPLE__
-int inflate_trees_bits(uInt *c, uInt *bb, inflate_huft * *tb, inflate_huft *hp, z_streamp z)
-//uInt *c;               /* 19 code lengths */
-//uInt *bb;              /* bits tree desired/actual depth */
-//inflate_huft * *tb; /* bits tree result */
-//inflate_huft *hp;       /* space for trees */
-//z_streamp z;            /* for messages */
-{
-  int r;
-  uInt hn = 0;          /* hufts used in space */
-  uInt *v;             /* work area for huft_build */
-
-  if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
-    return Z_MEM_ERROR;
-  r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL,
-                 tb, bb, hp, &hn, v);
-  if (r == Z_DATA_ERROR)
-    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
-  else if (r == Z_BUF_ERROR || *bb == 0)
-  {
-    z->msg = (char*)"incomplete dynamic bit lengths tree";
-    r = Z_DATA_ERROR;
-  }
-  ZFREE(z, v);
-  return r;
-}
-#endif
-
-#ifndef __APPLE__
-int inflate_trees_dynamic(uInt nl, uInt nd, uInt *c, uInt *bl, uInt *bd, inflate_huft * *tl, inflate_huft * *td, inflate_huft *hp, z_streamp z)
-//uInt nl;                /* number of literal/length codes */
-//uInt nd;                /* number of distance codes */
-//uInt *c;               /* that many (total) code lengths */
-//uInt *bl;              /* literal desired/actual bit depth */
-//uInt *bd;              /* distance desired/actual bit depth */
-//inflate_huft * *tl; /* literal/length tree result */
-//inflate_huft * *td; /* distance tree result */
-//inflate_huft *hp;       /* space for trees */
-//z_streamp z;            /* for messages */
-{
-  int r;
-  uInt hn = 0;          /* hufts used in space */
-  uInt *v;             /* work area for huft_build */
-
-  /* allocate work area */
-  if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
-    return Z_MEM_ERROR;
-
-  /* build literal/length tree */
-  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
-  if (r != Z_OK || *bl == 0)
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = (char*)"oversubscribed literal/length tree";
-    else if (r != Z_MEM_ERROR)
-    {
-      z->msg = (char*)"incomplete literal/length tree";
-      r = Z_DATA_ERROR;
-    }
-    ZFREE(z, v);
-    return r;
-  }
-
-  /* build distance tree */
-  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
-  if (r != Z_OK || (*bd == 0 && nl > 257))
-  {
-    if (r == Z_DATA_ERROR)
-      z->msg = (char*)"oversubscribed distance tree";
-    else if (r == Z_BUF_ERROR) {
-#ifdef PKZIP_BUG_WORKAROUND
-      r = Z_OK;
-    }
-#else
-      z->msg = (char*)"incomplete distance tree";
-      r = Z_DATA_ERROR;
-    }
-    else if (r != Z_MEM_ERROR)
-    {
-      z->msg = (char*)"empty distance tree with lengths";
-      r = Z_DATA_ERROR;
-    }
-    ZFREE(z, v);
-    return r;
-#endif
-  }
-
-  /* done */
-  ZFREE(z, v);
-  return Z_OK;
-}
-#endif
-
-/* inffixed.h -- table for decoding fixed codes
- * Generated automatically by the maketree.c program
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-static uInt fixed_bl = 9;
-static uInt fixed_bd = 5;
-static inflate_huft fixed_tl[] = {
-    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
-    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
-    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
-    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
-    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
-    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
-    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
-    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
-    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
-    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
-    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
-    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
-    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
-    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
-    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
-    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
-    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
-    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
-    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
-    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
-    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
-    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
-    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
-    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
-    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
-    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
-    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
-    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
-    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
-    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
-    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
-    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
-    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
-    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
-    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
-    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
-    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
-    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
-    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
-    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
-    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
-    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
-    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
-    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
-    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
-    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
-    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
-    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
-    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
-    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
-    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
-    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
-    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
-    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
-    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
-    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
-    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
-    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
-    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
-    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
-    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
-    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
-    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
-    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
-    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
-    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
-    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
-    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
-    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
-    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
-    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
-    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
-    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
-    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
-    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
-    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
-    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
-    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
-    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
-    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
-    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
-    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
-    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
-    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
-    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
-    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
-    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
-    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
-    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
-    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
-    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
-    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
-    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
-    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
-    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
-    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
-    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
-    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
-    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
-    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
-    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
-    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
-    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
-    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
-    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
-    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
-    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
-    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
-    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
-    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
-    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
-    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
-    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
-    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
-    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
-    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
-    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
-    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
-    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
-    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
-    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
-    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
-    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
-    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
-    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
-  };
-static inflate_huft fixed_td[] = {
-    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
-    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
-    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
-    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
-    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
-    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
-    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
-    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
-  };
-
-#ifndef __APPLE__
-int inflate_trees_fixed(uInt *bl, uInt *bd, inflate_huft * *tl, inflate_huft * *td, z_streamp z)
-//uInt *bl;               /* literal desired/actual bit depth */
-//uInt *bd;               /* distance desired/actual bit depth */
-//inflate_huft * *tl;  /* literal/length tree result */
-//inflate_huft * *td;  /* distance tree result */
-//z_streamp z;             /* for memory allocation */
-{
-  *bl = fixed_bl;
-  *bd = fixed_bd;
-  *tl = fixed_tl;
-  *td = fixed_td;
-  return Z_OK;
-}
-#endif
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-/* macros for bit input with no checking and for returning unused bytes */
-#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
-#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
-
-/* Called with number of bytes left to write in window at least 258
-   (the maximum string length) and number of input bytes available
-   at least ten.  The ten bytes are six bytes for the longest length/
-   distance pair plus four bytes for overloading the bit buffer. */
-
-#ifndef __APPLE__
-int inflate_fast(uInt bl, uInt bd, inflate_huft *tl, inflate_huft *td, inflate_blocks_statef *s, z_streamp z)
-{
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Byte *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Byte *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  uInt ml;              /* mask for literal/length tree */
-  uInt md;              /* mask for distance tree */
-  uInt c;               /* bytes to copy */
-  uInt d;               /* distance back to copy from */
-  Byte *r;             /* copy source pointer */
-
-  /* load input, output, bit values */
-  LOAD
-
-  /* initialize masks */
-  ml = inflate_mask[bl];
-  md = inflate_mask[bd];
-
-  /* do until not enough input or output space for fast loop */
-  do {                          /* assume called with m >= 258 && n >= 10 */
-    /* get literal/length code */
-    GRABBITS(20)                /* max bits for literal/length code */
-    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
-    {
-      DUMPBITS(t->bits)
-      Tracevv((t->base >= 0x20 && t->base < 0x7f ?
-                "inflate:         * literal '%c'\n" :
-                "inflate:         * literal 0x%02x\n", t->base));
-      *q++ = (Byte)t->base;
-      m--;
-      continue;
-    }
-    do {
-      DUMPBITS(t->bits)
-      if (e & 16)
-      {
-        /* get extra bits for length */
-        e &= 15;
-        c = t->base + ((uInt)b & inflate_mask[e]);
-        DUMPBITS(e)
-        Tracevv(("inflate:         * length %u\n", c));
-
-        /* decode distance base of block to copy */
-        GRABBITS(15);           /* max bits for distance code */
-        e = (t = td + ((uInt)b & md))->exop;
-        do {
-          DUMPBITS(t->bits)
-          if (e & 16)
-          {
-            /* get extra bits to add to distance base */
-            e &= 15;
-            GRABBITS(e)         /* get extra bits (up to 13) */
-            d = t->base + ((uInt)b & inflate_mask[e]);
-            DUMPBITS(e)
-            Tracevv(("inflate:         * distance %u\n", d));
-
-            /* do the copy */
-            m -= c;
-            if ((uInt)(q - s->window) >= d)     /* offset before dest */
-            {                                   /*  just copy */
-              r = q - d;
-              *q++ = *r++;  c--;        /* minimum count is three, */
-              *q++ = *r++;  c--;        /*  so unroll loop a little */
-            }
-            else                        /* else offset after destination */
-            {
-              e = d - (uInt)(q - s->window); /* bytes from offset to end */
-              r = s->end - e;           /* pointer to offset */
-              if (c > e)                /* if source crosses, */
-              {
-                c -= e;                 /* copy to end of window */
-                do {
-                  *q++ = *r++;
-                } while (--e);
-                r = s->window;          /* copy rest from start of window */
-              }
-            }
-            do {                        /* copy all or what's left */
-              *q++ = *r++;
-            } while (--c);
-            break;
-          }
-          else if ((e & 64) == 0)
-          {
-            t += t->base;
-            e = (t += ((uInt)b & inflate_mask[e]))->exop;
-          }
-          else
-          {
-            z->msg = (char*)"invalid distance code";
-            UNGRAB
-            UPDATE
-            return Z_DATA_ERROR;
-          }
-        } while (1);
-        break;
-      }
-      if ((e & 64) == 0)
-      {
-        t += t->base;
-        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
-        {
-          DUMPBITS(t->bits)
-          Tracevv((t->base >= 0x20 && t->base < 0x7f ?
-                    "inflate:         * literal '%c'\n" :
-                    "inflate:         * literal 0x%02x\n", t->base));
-          *q++ = (Byte)t->base;
-          m--;
-          break;
-        }
-      }
-      else if (e & 32)
-      {
-        Tracevv(("inflate:         * end of block\n"));
-        UNGRAB
-        UPDATE
-        return Z_STREAM_END;
-      }
-      else
-      {
-        z->msg = (char*)"invalid literal/length code";
-        UNGRAB
-        UPDATE
-        return Z_DATA_ERROR;
-      }
-    } while (1);
-  } while (m >= 258 && n >= 10);
-
-  /* not enough input or output--restore pointers and return */
-  UNGRAB
-  UPDATE
-  return Z_OK;
-}
-#endif
-
-/* infcodes.c -- process literals and length/distance pairs
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* simplify the use of the inflate_huft type with some defines */
-#define exop word.what.Exop
-#define bits word.what.Bits
-
-typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-      START,    /* x: set up for LEN */
-      LEN,      /* i: get length/literal/eob next */
-      LENEXT,   /* i: getting length extra (have base) */
-      DIST,     /* i: get distance next */
-      DISTEXT,  /* i: getting distance extra */
-      COPY,     /* o: copying bytes in window, waiting for space */
-      LIT,      /* o: got literal, waiting for output space */
-      WASH,     /* o: got eob, possibly still output waiting */
-      END,      /* x: got eob and all data flushed */
-      BADCODE}  /* x: got error */
-inflate_codes_mode;
-
-/* inflate codes private state */
-struct inflate_codes_state {
-
-  /* mode */
-  inflate_codes_mode mode;      /* current inflate_codes mode */
-
-  /* mode dependent information */
-  uInt len;
-  union {
-    struct {
-      inflate_huft *tree;       /* pointer into tree */
-      uInt need;                /* bits needed */
-    } code;             /* if LEN or DIST, where in tree */
-    uInt lit;           /* if LIT, literal */
-    struct {
-      uInt get;                 /* bits to get for extra */
-      uInt dist;                /* distance back to copy from */
-    } copy;             /* if EXT or COPY, where and how much */
-  } sub;                /* submode */
-
-  /* mode independent information */
-  Byte lbits;           /* ltree bits decoded per branch */
-  Byte dbits;           /* dtree bits decoder per branch */
-  inflate_huft *ltree;          /* literal/length/eob tree */
-  inflate_huft *dtree;          /* distance tree */
-
-};
-
-#ifndef __APPLE__
-inflate_codes_statef *inflate_codes_new(uInt bl, uInt bd, inflate_huft *tl, inflate_huft *td, z_streamp z)
-{
-  inflate_codes_statef *c;
-
-  if ((c = (inflate_codes_statef *)
-       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
-  {
-    c->mode = START;
-    c->lbits = (Byte)bl;
-    c->dbits = (Byte)bd;
-    c->ltree = tl;
-    c->dtree = td;
-    Tracev(("inflate:       codes new\n"));
-  }
-  return c;
-}
-#endif
-
-#ifndef __APPLE__
-int inflate_codes(inflate_blocks_statef *s, z_streamp z, int r)
-{
-  uInt j;               /* temporary storage */
-  inflate_huft *t;      /* temporary pointer */
-  uInt e;               /* extra bits or operation */
-  uLong b;              /* bit buffer */
-  uInt k;               /* bits in bit buffer */
-  Byte *p;             /* input data pointer */
-  uInt n;               /* bytes available there */
-  Byte *q;             /* output window write pointer */
-  uInt m;               /* bytes to end of window or read pointer */
-  Byte *f;             /* pointer to copy strings from */
-  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
-
-  /* copy input/output information to locals (UPDATE macro restores) */
-  LOAD
-
-  /* process input and output based on current state */
-  while (1) switch (c->mode)
-  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
-    case START:         /* x: set up for LEN */
-#ifndef SLOW
-      if (m >= 258 && n >= 10)
-      {
-        UPDATE
-        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
-        LOAD
-        if (r != Z_OK)
-        {
-          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
-          break;
-        }
-      }
-#endif /* !SLOW */
-      c->sub.code.need = c->lbits;
-      c->sub.code.tree = c->ltree;
-      c->mode = LEN;
-    case LEN:           /* i: get length/literal/eob next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e == 0)               /* literal */
-      {
-        c->sub.lit = t->base;
-        Tracevv((t->base >= 0x20 && t->base < 0x7f ?
-                 "inflate:         literal '%c'\n" :
-                 "inflate:         literal 0x%02x\n", t->base));
-        c->mode = LIT;
-        break;
-      }
-      if (e & 16)               /* length */
-      {
-        c->sub.copy.get = e & 15;
-        c->len = t->base;
-        c->mode = LENEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t + t->base;
-        break;
-      }
-      if (e & 32)               /* end of block */
-      {
-        Tracevv(("inflate:         end of block\n"));
-        c->mode = WASH;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = (char*)"invalid literal/length code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case LENEXT:        /* i: getting length extra (have base) */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->len += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      c->sub.code.need = c->dbits;
-      c->sub.code.tree = c->dtree;
-      Tracevv(("inflate:         length %u\n", c->len));
-      c->mode = DIST;
-    case DIST:          /* i: get distance next */
-      j = c->sub.code.need;
-      NEEDBITS(j)
-      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
-      DUMPBITS(t->bits)
-      e = (uInt)(t->exop);
-      if (e & 16)               /* distance */
-      {
-        c->sub.copy.get = e & 15;
-        c->sub.copy.dist = t->base;
-        c->mode = DISTEXT;
-        break;
-      }
-      if ((e & 64) == 0)        /* next table */
-      {
-        c->sub.code.need = e;
-        c->sub.code.tree = t + t->base;
-        break;
-      }
-      c->mode = BADCODE;        /* invalid code */
-      z->msg = (char*)"invalid distance code";
-      r = Z_DATA_ERROR;
-      LEAVE
-    case DISTEXT:       /* i: getting distance extra */
-      j = c->sub.copy.get;
-      NEEDBITS(j)
-      c->sub.copy.dist += (uInt)b & inflate_mask[j];
-      DUMPBITS(j)
-      Tracevv(("inflate:         distance %u\n", c->sub.copy.dist));
-      c->mode = COPY;
-    case COPY:          /* o: copying bytes in window, waiting for space */
-#ifndef __TURBOC__ /* Turbo C bug for following expression */
-      f = (uInt)(q - s->window) < c->sub.copy.dist ?
-          s->end - (c->sub.copy.dist - (q - s->window)) :
-          q - c->sub.copy.dist;
-#else
-      f = q - c->sub.copy.dist;
-      if ((uInt)(q - s->window) < c->sub.copy.dist)
-        f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
-#endif
-      while (c->len)
-      {
-        NEEDOUT
-        OUTBYTE(*f++)
-        if (f == s->end)
-          f = s->window;
-        c->len--;
-      }
-      c->mode = START;
-      break;
-    case LIT:           /* o: got literal, waiting for output space */
-      NEEDOUT
-      OUTBYTE(c->sub.lit)
-      c->mode = START;
-      break;
-    case WASH:          /* o: got eob, possibly more output */
-      if (k > 7)        /* return unused byte, if any */
-      {
-        Assert(k < 16, "inflate_codes grabbed too many bytes")
-        k -= 8;
-        n++;
-        p--;            /* can always return one */
-      }
-      FLUSH
-      if (s->read != s->write)
-        LEAVE
-      c->mode = END;
-    case END:
-      r = Z_STREAM_END;
-      LEAVE
-    case BADCODE:       /* x: got error */
-      r = Z_DATA_ERROR;
-      LEAVE
-    default:
-      r = Z_STREAM_ERROR;
-      LEAVE
-  }
-#ifdef NEED_DUMMY_RETURN
-  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
-#endif
-}
-#endif
-
-#ifndef __APPLE__
-void inflate_codes_free(inflate_codes_statef *c, z_streamp z)
-{
-  ZFREE(z, c);
-  Tracev(("inflate:       codes free\n"));
-}
-#endif
-
-/* adler32.c -- compute the Adler-32 checksum of a data stream
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-#define BASE 65521L /* largest prime smaller than 65536 */
-#define NMAX 5552
-/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
-
-#undef DO1
-#undef DO2
-#undef DO4
-#undef DO8
-
-#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
-#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
-#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
-#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
-#define DO16(buf)   DO8(buf,0); DO8(buf,8);
-
-/* ========================================================================= */
-#ifndef __APPLE__
-uLong adler32(uLong adler, const Byte *buf, uInt len)
-{
-    unsigned long s1 = adler & 0xffff;
-    unsigned long s2 = (adler >> 16) & 0xffff;
-    int k;
-
-    if (buf == Z_NULL) return 1L;
-
-    while (len > 0) {
-        k = len < NMAX ? len : NMAX;
-        len -= k;
-        while (k >= 16) {
-            DO16(buf);
-	    buf += 16;
-            k -= 16;
-        }
-        if (k != 0) do {
-            s1 += *buf++;
-	    s2 += s1;
-        } while (--k);
-        s1 %= BASE;
-        s2 %= BASE;
-    }
-    return (s2 << 16) | s1;
-}
-#endif
-
-
-/* infblock.h -- header to use infblock.c
- * Copyright (C) 1995-1998 Mark Adler
- * For conditions of distribution and use, see copyright notice in zlib.h 
- */
-
-/* WARNING: this file should *not* be used by applications. It is
-   part of the implementation of the compression library and is
-   subject to change. Applications should only use zlib.h.
- */
-
-extern inflate_blocks_statef * inflate_blocks_new OF((
-    z_streamp z,
-    check_func c,               /* check function */
-    uInt w));                   /* window size */
-
-extern int inflate_blocks OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    int));                      /* initial return code */
-
-extern void inflate_blocks_reset OF((
-    inflate_blocks_statef *,
-    z_streamp ,
-    uLong *));                  /* check value on output */
-
-extern int inflate_blocks_free OF((
-    inflate_blocks_statef *,
-    z_streamp));
-
-extern void inflate_set_dictionary OF((
-    inflate_blocks_statef *s,
-    const Byte *d,  /* dictionary */
-    uInt  n));       /* dictionary length */
-
-extern int inflate_blocks_sync_point OF((
-    inflate_blocks_statef *s));
-
-typedef enum {
-      imMETHOD,   /* waiting for method byte */
-      imFLAG,     /* waiting for flag byte */
-      imDICT4,    /* four dictionary check bytes to go */
-      imDICT3,    /* three dictionary check bytes to go */
-      imDICT2,    /* two dictionary check bytes to go */
-      imDICT1,    /* one dictionary check byte to go */
-      imDICT0,    /* waiting for inflateSetDictionary */
-      imBLOCKS,   /* decompressing blocks */
-      imCHECK4,   /* four check bytes to go */
-      imCHECK3,   /* three check bytes to go */
-      imCHECK2,   /* two check bytes to go */
-      imCHECK1,   /* one check byte to go */
-      imDONE,     /* finished check, done */
-      imBAD}      /* got an error--stay here */
-inflate_mode;
-
-/* inflate private state */
-struct internal_state {
-
-  /* mode */
-  inflate_mode  mode;   /* current inflate mode */
-
-  /* mode dependent information */
-  union {
-    uInt method;        /* if FLAGS, method byte */
-    struct {
-      uLong was;                /* computed check value */
-      uLong need;               /* stream check value */
-    } check;            /* if CHECK, check values to compare */
-    uInt marker;        /* if BAD, inflateSync's marker bytes count */
-  } sub;        /* submode */
-
-  /* mode independent information */
-  int  nowrap;          /* flag for no wrapper */
-  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
-  inflate_blocks_statef 
-    *blocks;            /* current inflate_blocks state */
-
-};
-
-
-#ifndef __APPLE__
-int inflateReset(z_streamp z)
-{
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  z->total_in = z->total_out = 0;
-  z->msg = Z_NULL;
-  z->state->mode = z->state->nowrap ? imBLOCKS : imMETHOD;
-  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
-  Tracev(("inflate: reset\n"));
-  return Z_OK;
-}
-#endif
-
-#ifndef __APPLE__
-int inflateEnd(z_streamp z)
-{
-  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->blocks != Z_NULL)
-    inflate_blocks_free(z->state->blocks, z);
-  ZFREE(z, z->state);
-  z->state = Z_NULL;
-  Tracev(("inflate: end\n"));
-  return Z_OK;
-}
-#endif
-
-#ifndef __APPLE__
-int inflateInit2_(z_streamp z, int w, const char *version, int stream_size)
-{
-  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
-      stream_size != sizeof(z_stream))
-      return Z_VERSION_ERROR;
-
-  /* initialize state */
-  if (z == Z_NULL)
-    return Z_STREAM_ERROR;
-  z->msg = Z_NULL;
-  if (z->zalloc == Z_NULL)
-  {
-    z->zalloc = (void *(*)(void *, unsigned, unsigned))zcalloc;
-    z->opaque = (voidp)0;
-  }
-  if (z->zfree == Z_NULL) z->zfree = (void (*)(void *, void *))zcfree;
-  if ((z->state = (struct internal_state *)
-       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
-    return Z_MEM_ERROR;
-  z->state->blocks = Z_NULL;
-
-  /* handle undocumented nowrap option (no zlib header or check) */
-  z->state->nowrap = 0;
-  if (w < 0)
-  {
-    w = - w;
-    z->state->nowrap = 1;
-  }
-
-  /* set window size */
-  if (w < 8 || w > 15)
-  {
-    inflateEnd(z);
-    return Z_STREAM_ERROR;
-  }
-  z->state->wbits = (uInt)w;
-
-  /* create inflate_blocks state */
-  if ((z->state->blocks =
-      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
-      == Z_NULL)
-  {
-    inflateEnd(z);
-    return Z_MEM_ERROR;
-  }
-  Tracev(("inflate: allocated\n"));
-
-  /* reset state */
-  inflateReset(z);
-  return Z_OK;
-}
-#endif
-
-#ifndef __APPLE__
-int inflateInit_(z_streamp z, const char *version, int stream_size)
-{
-  return inflateInit2_(z, DEF_WBITS, version, stream_size);
-}
-#endif
-
-#define iNEEDBYTE {if(z->avail_in==0)return r;r=f;}
-#define iNEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
-
-#ifndef __APPLE__
-int inflate(z_streamp z, int f)
-{
-  int r;
-  uInt b;
-
-  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
-    return Z_STREAM_ERROR;
-  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
-  r = Z_BUF_ERROR;
-  while (1) switch (z->state->mode)
-  {
-    case imMETHOD:
-      iNEEDBYTE
-      if (((z->state->sub.method = iNEXTBYTE) & 0xf) != Z_DEFLATED)
-      {
-        z->state->mode = imBAD;
-        z->msg = (char*)"unknown compression method";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
-      {
-        z->state->mode = imBAD;
-        z->msg = (char*)"invalid window size";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      z->state->mode = imFLAG;
-    case imFLAG:
-      iNEEDBYTE
-      b = iNEXTBYTE;
-      if (((z->state->sub.method << 8) + b) % 31)
-      {
-        z->state->mode = imBAD;
-        z->msg = (char*)"incorrect header check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Tracev(("inflate: zlib header ok\n"));
-      if (!(b & PRESET_DICT))
-      {
-        z->state->mode = imBLOCKS;
-        break;
-      }
-      z->state->mode = imDICT4;
-    case imDICT4:
-      iNEEDBYTE
-      z->state->sub.check.need = (uLong)iNEXTBYTE << 24;
-      z->state->mode = imDICT3;
-    case imDICT3:
-      iNEEDBYTE
-      z->state->sub.check.need += (uLong)iNEXTBYTE << 16;
-      z->state->mode = imDICT2;
-    case imDICT2:
-      iNEEDBYTE
-      z->state->sub.check.need += (uLong)iNEXTBYTE << 8;
-      z->state->mode = imDICT1;
-    case imDICT1:
-      iNEEDBYTE
-      z->state->sub.check.need += (uLong)iNEXTBYTE;
-      z->adler = z->state->sub.check.need;
-      z->state->mode = imDICT0;
-      return Z_NEED_DICT;
-    case imDICT0:
-      z->state->mode = imBAD;
-      z->msg = (char*)"need dictionary";
-      z->state->sub.marker = 0;       /* can try inflateSync */
-      return Z_STREAM_ERROR;
-    case imBLOCKS:
-      r = inflate_blocks(z->state->blocks, z, r);
-      if (r == Z_DATA_ERROR)
-      {
-        z->state->mode = imBAD;
-        z->state->sub.marker = 0;       /* can try inflateSync */
-        break;
-      }
-      if (r == Z_OK)
-        r = f;
-      if (r != Z_STREAM_END)
-        return r;
-      r = f;
-      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
-      if (z->state->nowrap)
-      {
-        z->state->mode = imDONE;
-        break;
-      }
-      z->state->mode = imCHECK4;
-    case imCHECK4:
-      iNEEDBYTE
-      z->state->sub.check.need = (uLong)iNEXTBYTE << 24;
-      z->state->mode = imCHECK3;
-    case imCHECK3:
-      iNEEDBYTE
-      z->state->sub.check.need += (uLong)iNEXTBYTE << 16;
-      z->state->mode = imCHECK2;
-    case imCHECK2:
-      iNEEDBYTE
-      z->state->sub.check.need += (uLong)iNEXTBYTE << 8;
-      z->state->mode = imCHECK1;
-    case imCHECK1:
-      iNEEDBYTE
-      z->state->sub.check.need += (uLong)iNEXTBYTE;
-
-      if (z->state->sub.check.was != z->state->sub.check.need)
-      {
-        z->state->mode = imBAD;
-        z->msg = (char*)"incorrect data check";
-        z->state->sub.marker = 5;       /* can't try inflateSync */
-        break;
-      }
-      Tracev(("inflate: zlib check ok\n"));
-      z->state->mode = imDONE;
-    case imDONE:
-      return Z_STREAM_END;
-    case imBAD:
-      return Z_DATA_ERROR;
-    default:
-      return Z_STREAM_ERROR;
-  }
-#ifdef NEED_DUMMY_RETURN
-  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
-#endif
-}
-#endif
-
-#ifndef __APPLE__
-int inflateSetDictionary(z_streamp z, const Byte *dictionary, uInt dictLength)
-{
-  uInt length = dictLength;
-
-  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != imDICT0)
-    return Z_STREAM_ERROR;
-
-  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
-  z->adler = 1L;
-
-  if (length >= ((uInt)1<<z->state->wbits))
-  {
-    length = (1<<z->state->wbits)-1;
-    dictionary += dictLength - length;
-  }
-  inflate_set_dictionary(z->state->blocks, dictionary, length);
-  z->state->mode = imBLOCKS;
-  return Z_OK;
-}
-#endif
-
-#ifndef __APPLE__
-int inflateSync(z_streamp z)
-{
-  uInt n;       /* number of bytes to look at */
-  Byte *p;     /* pointer to bytes */
-  uInt m;       /* number of marker bytes found in a row */
-  uLong r, w;   /* temporaries to save total_in and total_out */
-
-  /* set up */
-  if (z == Z_NULL || z->state == Z_NULL)
-    return Z_STREAM_ERROR;
-  if (z->state->mode != imBAD)
-  {
-    z->state->mode = imBAD;
-    z->state->sub.marker = 0;
-  }
-  if ((n = z->avail_in) == 0)
-    return Z_BUF_ERROR;
-  p = z->next_in;
-  m = z->state->sub.marker;
-
-  /* search */
-  while (n && m < 4)
-  {
-    static const Byte mark[4] = {0, 0, 0xff, 0xff};
-    if (*p == mark[m])
-      m++;
-    else if (*p)
-      m = 0;
-    else
-      m = 4 - m;
-    p++, n--;
-  }
-
-  /* restore */
-  z->total_in += p - z->next_in;
-  z->next_in = p;
-  z->avail_in = n;
-  z->state->sub.marker = m;
-
-  /* return no joy or set up to restart on a new block */
-  if (m != 4)
-    return Z_DATA_ERROR;
-  r = z->total_in;  w = z->total_out;
-  inflateReset(z);
-  z->total_in = r;  z->total_out = w;
-  z->state->mode = imBLOCKS;
-  return Z_OK;
-}
-#endif
-
-/* Returns true if inflate is currently at the end of a block generated
- * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
- * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
- * but removes the length bytes of the resulting empty stored block. When
- * decompressing, PPP checks that at the end of input packet, inflate is
- * waiting for these length bytes.
- */
-#ifndef __APPLE__
-int inflateSyncPoint(z_streamp z)
-{
-  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
-    return Z_STREAM_ERROR;
-  return inflate_blocks_sync_point(z->state->blocks);
-}
-#endif
-
-#ifndef __APPLE__
-voidp zcalloc (voidp opaque, unsigned items, unsigned size)
-{
-    if (opaque) items += size - size; /* make compiler happy */
-    return (voidp)safe_malloc(items*size);
-}
-
-void  zcfree (voidp opaque, voidp ptr)
-{
-    free(ptr);
-    if (opaque) return; /* make compiler happy */
-}
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/*****************************************************************************
+ * name:		unzip.c
+ *
+ * desc:		IO on .zip files using portions of zlib 
+ *
+ *
+ *****************************************************************************/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "unzip.h"
+
+// TTimo added for safe_malloc wrapping
+#include "cmdlib.h"
+
+/* unzip.h -- IO for uncompress .zip files using zlib 
+   Version 0.15 beta, Mar 19th, 1998,
+
+   Copyright (C) 1998 Gilles Vollant
+
+   This unzip package allow extract file from .ZIP file, compatible with PKZip 2.04g
+     WinZip, InfoZip tools and compatible.
+   Encryption and multi volume ZipFile (span) are not supported.
+   Old compressions used by old PKZip 1.x are not supported
+
+   THIS IS AN ALPHA VERSION. AT THIS STAGE OF DEVELOPPEMENT, SOMES API OR STRUCTURE
+   CAN CHANGE IN FUTURE VERSION !!
+   I WAIT FEEDBACK at mail info@winimage.com
+   Visit also http://www.winimage.com/zLibDll/unzip.htm for evolution
+
+   Condition of use and distribution are the same than zlib :
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+
+*/
+/* for more info about .ZIP format, see 
+      ftp://ftp.cdrom.com/pub/infozip/doc/appnote-970311-iz.zip
+   PkWare has also a specification at :
+      ftp://ftp.pkware.com/probdesc.zip */
+
+/* zlib.h -- interface of the 'zlib' general purpose compression library
+  version 1.1.3, July 9th, 1998
+
+  Copyright (C) 1995-1998 Jean-loup Gailly and Mark Adler
+
+  This software is provided 'as-is', without any express or implied
+  warranty.  In no event will the authors be held liable for any damages
+  arising from the use of this software.
+
+  Permission is granted to anyone to use this software for any purpose,
+  including commercial applications, and to alter it and redistribute it
+  freely, subject to the following restrictions:
+
+  1. The origin of this software must not be misrepresented; you must not
+     claim that you wrote the original software. If you use this software
+     in a product, an acknowledgment in the product documentation would be
+     appreciated but is not required.
+  2. Altered source versions must be plainly marked as such, and must not be
+     misrepresented as being the original software.
+  3. This notice may not be removed or altered from any source distribution.
+
+  Jean-loup Gailly        Mark Adler
+  jloup@gzip.org          madler@alumni.caltech.edu
+
+
+  The data format used by the zlib library is described by RFCs (Request for
+  Comments) 1950 to 1952 in the files ftp://ds.internic.net/rfc/rfc1950.txt
+  (zlib format), rfc1951.txt (deflate format) and rfc1952.txt (gzip format).
+*/
+
+/* zconf.h -- configuration of the zlib compression library
+ * Copyright (C) 1995-1998 Jean-loup Gailly.
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+
+#ifndef _ZCONF_H
+#define _ZCONF_H
+
+/* Maximum value for memLevel in deflateInit2 */
+#ifndef MAX_MEM_LEVEL
+#  ifdef MAXSEG_64K
+#    define MAX_MEM_LEVEL 8
+#  else
+#    define MAX_MEM_LEVEL 9
+#  endif
+#endif
+
+/* Maximum value for windowBits in deflateInit2 and inflateInit2.
+ * WARNING: reducing MAX_WBITS makes minigzip unable to extract .gz files
+ * created by gzip. (Files created by minigzip can still be extracted by
+ * gzip.)
+ */
+#ifndef MAX_WBITS
+#  define MAX_WBITS   15 /* 32K LZ77 window */
+#endif
+
+/* The memory requirements for deflate are (in bytes):
+            (1 << (windowBits+2)) +  (1 << (memLevel+9))
+ that is: 128K for windowBits=15  +  128K for memLevel = 8  (default values)
+ plus a few kilobytes for small objects. For example, if you want to reduce
+ the default memory requirements from 256K to 128K, compile with
+     make CFLAGS="-O -DMAX_WBITS=14 -DMAX_MEM_LEVEL=7"
+ Of course this will generally degrade compression (there's no free lunch).
+
+   The memory requirements for inflate are (in bytes) 1 << windowBits
+ that is, 32K for windowBits=15 (default value) plus a few kilobytes
+ for small objects.
+*/
+
+                        /* Type declarations */
+
+#ifndef OF /* function prototypes */
+#define OF(args)  args
+#endif
+
+typedef unsigned char  Byte;  /* 8 bits */
+typedef unsigned int   uInt;  /* 16 bits or more */
+typedef unsigned long  uLong; /* 32 bits or more */
+typedef Byte    *voidp;
+
+#ifndef SEEK_SET
+#  define SEEK_SET        0       /* Seek from beginning of file.  */
+#  define SEEK_CUR        1       /* Seek from current position.  */
+#  define SEEK_END        2       /* Set file pointer to EOF plus "offset" */
+#endif
+
+#endif /* _ZCONF_H */
+
+#define ZLIB_VERSION "1.1.3"
+
+/* 
+     The 'zlib' compression library provides in-memory compression and
+  decompression functions, including integrity checks of the uncompressed
+  data.  This version of the library supports only one compression method
+  (deflation) but other algorithms will be added later and will have the same
+  stream interface.
+
+     Compression can be done in a single step if the buffers are large
+  enough (for example if an input file is mmap'ed), or can be done by
+  repeated calls of the compression function.  In the latter case, the
+  application must provide more input and/or consume the output
+  (providing more output space) before each call.
+
+     The library also supports reading and writing files in gzip (.gz) format
+  with an interface similar to that of stdio.
+
+     The library does not install any signal handler. The decoder checks
+  the consistency of the compressed data, so the library should never
+  crash even in case of corrupted input.
+*/
+
+/*
+   The application must update next_in and avail_in when avail_in has
+   dropped to zero. It must update next_out and avail_out when avail_out
+   has dropped to zero. The application must initialize zalloc, zfree and
+   opaque before calling the init function. All other fields are set by the
+   compression library and must not be updated by the application.
+
+   The opaque value provided by the application will be passed as the first
+   parameter for calls of zalloc and zfree. This can be useful for custom
+   memory management. The compression library attaches no meaning to the
+   opaque value.
+
+   zalloc must return Z_NULL if there is not enough memory for the object.
+   If zlib is used in a multi-threaded application, zalloc and zfree must be
+   thread safe.
+
+   On 16-bit systems, the functions zalloc and zfree must be able to allocate
+   exactly 65536 bytes, but will not be required to allocate more than this
+   if the symbol MAXSEG_64K is defined (see zconf.h). WARNING: On MSDOS,
+   pointers returned by zalloc for objects of exactly 65536 bytes *must*
+   have their offset normalized to zero. The default allocation function
+   provided by this library ensures this (see zutil.c). To reduce memory
+   requirements and avoid any allocation of 64K objects, at the expense of
+   compression ratio, compile the library with -DMAX_WBITS=14 (see zconf.h).
+
+   The fields total_in and total_out can be used for statistics or
+   progress reports. After compression, total_in holds the total size of
+   the uncompressed data and may be saved for use in the decompressor
+   (particularly if the decompressor wants to decompress everything in
+   a single step).
+*/
+
+                        /* constants */
+
+#define Z_NO_FLUSH      0
+#define Z_PARTIAL_FLUSH 1 /* will be removed, use Z_SYNC_FLUSH instead */
+#define Z_SYNC_FLUSH    2
+#define Z_FULL_FLUSH    3
+#define Z_FINISH        4
+/* Allowed flush values; see deflate() below for details */
+
+#define Z_OK            0
+#define Z_STREAM_END    1
+#define Z_NEED_DICT     2
+#define Z_ERRNO        (-1)
+#define Z_STREAM_ERROR (-2)
+#define Z_DATA_ERROR   (-3)
+#define Z_MEM_ERROR    (-4)
+#define Z_BUF_ERROR    (-5)
+#define Z_VERSION_ERROR (-6)
+/* Return codes for the compression/decompression functions. Negative
+ * values are errors, positive values are used for special but normal events.
+ */
+
+#define Z_NO_COMPRESSION         0
+#define Z_BEST_SPEED             1
+#define Z_BEST_COMPRESSION       9
+#define Z_DEFAULT_COMPRESSION  (-1)
+/* compression levels */
+
+#define Z_FILTERED            1
+#define Z_HUFFMAN_ONLY        2
+#define Z_DEFAULT_STRATEGY    0
+/* compression strategy; see deflateInit2() below for details */
+
+#define Z_BINARY   0
+#define Z_ASCII    1
+#define Z_UNKNOWN  2
+/* Possible values of the data_type field */
+
+#define Z_DEFLATED   8
+/* The deflate compression method (the only one supported in this version) */
+
+#define Z_NULL  0  /* for initializing zalloc, zfree, opaque */
+
+#define zlib_version zlibVersion()
+/* for compatibility with versions < 1.0.2 */
+
+                        /* basic functions */
+
+const char * zlibVersion OF((void));
+/* The application can compare zlibVersion and ZLIB_VERSION for consistency.
+   If the first character differs, the library code actually used is
+   not compatible with the zlib.h header file used by the application.
+   This check is automatically made by deflateInit and inflateInit.
+ */
+
+/* 
+int deflateInit OF((z_streamp strm, int level));
+
+     Initializes the internal stream state for compression. The fields
+   zalloc, zfree and opaque must be initialized before by the caller.
+   If zalloc and zfree are set to Z_NULL, deflateInit updates them to
+   use default allocation functions.
+
+     The compression level must be Z_DEFAULT_COMPRESSION, or between 0 and 9:
+   1 gives best speed, 9 gives best compression, 0 gives no compression at
+   all (the input data is simply copied a block at a time).
+   Z_DEFAULT_COMPRESSION requests a default compromise between speed and
+   compression (currently equivalent to level 6).
+
+     deflateInit returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if level is not a valid compression level,
+   Z_VERSION_ERROR if the zlib library version (zlib_version) is incompatible
+   with the version assumed by the caller (ZLIB_VERSION).
+   msg is set to null if there is no error message.  deflateInit does not
+   perform any compression: this will be done by deflate().
+*/
+
+
+int deflate OF((z_streamp strm, int flush));
+/*
+    deflate compresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may introduce some
+  output latency (reading input without producing any output) except when
+  forced to flush.
+
+    The detailed semantics are as follows. deflate performs one or both of the
+  following actions:
+
+  - Compress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in and avail_in are updated and
+    processing will resume at this point for the next call of deflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly. This action is forced if the parameter flush is non zero.
+    Forcing flush frequently degrades the compression ratio, so this parameter
+    should be set only when necessary (in interactive applications).
+    Some output may be provided even if flush is not set.
+
+  Before the call of deflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating avail_in or avail_out accordingly; avail_out
+  should never be zero before the call. The application can consume the
+  compressed output when it wants, for example when the output buffer is full
+  (avail_out == 0), or after each call of deflate(). If deflate returns Z_OK
+  and with zero avail_out, it must be called again after making room in the
+  output buffer because there might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, all pending output is
+  flushed to the output buffer and the output is aligned on a byte boundary, so
+  that the decompressor can get all input data available so far. (In particular
+  avail_in is zero after the call if enough output space has been provided
+  before the call.)  Flushing may degrade compression for some compression
+  algorithms and so it should be used only when necessary.
+
+    If flush is set to Z_FULL_FLUSH, all output is flushed as with
+  Z_SYNC_FLUSH, and the compression state is reset so that decompression can
+  restart from this point if previous compressed data has been damaged or if
+  random access is desired. Using Z_FULL_FLUSH too often can seriously degrade
+  the compression.
+
+    If deflate returns with avail_out == 0, this function must be called again
+  with the same value of the flush parameter and more output space (updated
+  avail_out), until the flush is complete (deflate returns with non-zero
+  avail_out).
+
+    If the parameter flush is set to Z_FINISH, pending input is processed,
+  pending output is flushed and deflate returns with Z_STREAM_END if there
+  was enough output space; if deflate returns with Z_OK, this function must be
+  called again with Z_FINISH and more output space (updated avail_out) but no
+  more input data, until it returns with Z_STREAM_END or an error. After
+  deflate has returned Z_STREAM_END, the only possible operations on the
+  stream are deflateReset or deflateEnd.
+  
+    Z_FINISH can be used immediately after deflateInit if all the compression
+  is to be done in a single step. In this case, avail_out must be at least
+  0.1% larger than avail_in plus 12 bytes.  If deflate does not return
+  Z_STREAM_END, then it must be called again as described above.
+
+    deflate() sets strm->adler to the adler32 checksum of all input read
+  so (that is, total_in bytes).
+
+    deflate() may update data_type if it can make a good guess about
+  the input data type (Z_ASCII or Z_BINARY). In doubt, the data is considered
+  binary. This field is only for information purposes and does not affect
+  the compression algorithm in any manner.
+
+    deflate() returns Z_OK if some progress has been made (more input
+  processed or more output produced), Z_STREAM_END if all input has been
+  consumed and all output has been produced (only when flush is set to
+  Z_FINISH), Z_STREAM_ERROR if the stream state was inconsistent (for example
+  if next_in or next_out was NULL), Z_BUF_ERROR if no progress is possible
+  (for example avail_in or avail_out was zero).
+*/
+
+
+int deflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     deflateEnd returns Z_OK if success, Z_STREAM_ERROR if the
+   stream state was inconsistent, Z_DATA_ERROR if the stream was freed
+   prematurely (some input or output was discarded). In the error case,
+   msg may be set but then points to a static string (which must not be
+   deallocated).
+*/
+
+
+/* 
+int inflateInit OF((z_streamp strm));
+
+     Initializes the internal stream state for decompression. The fields
+   next_in, avail_in, zalloc, zfree and opaque must be initialized before by
+   the caller. If next_in is not Z_NULL and avail_in is large enough (the exact
+   value depends on the compression method), inflateInit determines the
+   compression method from the zlib header and allocates all data structures
+   accordingly; otherwise the allocation will be deferred to the first call of
+   inflate.  If zalloc and zfree are set to Z_NULL, inflateInit updates them to
+   use default allocation functions.
+
+     inflateInit returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_VERSION_ERROR if the zlib library version is incompatible with the
+   version assumed by the caller.  msg is set to null if there is no error
+   message. inflateInit does not perform any decompression apart from reading
+   the zlib header if present: this will be done by inflate().  (So next_in and
+   avail_in may be modified, but next_out and avail_out are unchanged.)
+*/
+
+
+int inflate OF((z_streamp strm, int flush));
+/*
+    inflate decompresses as much data as possible, and stops when the input
+  buffer becomes empty or the output buffer becomes full. It may some
+  introduce some output latency (reading input without producing any output)
+  except when forced to flush.
+
+  The detailed semantics are as follows. inflate performs one or both of the
+  following actions:
+
+  - Decompress more input starting at next_in and update next_in and avail_in
+    accordingly. If not all input can be processed (because there is not
+    enough room in the output buffer), next_in is updated and processing
+    will resume at this point for the next call of inflate().
+
+  - Provide more output starting at next_out and update next_out and avail_out
+    accordingly.  inflate() provides as much output as possible, until there
+    is no more input data or no more space in the output buffer (see below
+    about the flush parameter).
+
+  Before the call of inflate(), the application should ensure that at least
+  one of the actions is possible, by providing more input and/or consuming
+  more output, and updating the next_* and avail_* values accordingly.
+  The application can consume the uncompressed output when it wants, for
+  example when the output buffer is full (avail_out == 0), or after each
+  call of inflate(). If inflate returns Z_OK and with zero avail_out, it
+  must be called again after making room in the output buffer because there
+  might be more output pending.
+
+    If the parameter flush is set to Z_SYNC_FLUSH, inflate flushes as much
+  output as possible to the output buffer. The flushing behavior of inflate is
+  not specified for values of the flush parameter other than Z_SYNC_FLUSH
+  and Z_FINISH, but the current implementation actually flushes as much output
+  as possible anyway.
+
+    inflate() should normally be called until it returns Z_STREAM_END or an
+  error. However if all decompression is to be performed in a single step
+  (a single call of inflate), the parameter flush should be set to
+  Z_FINISH. In this case all pending input is processed and all pending
+  output is flushed; avail_out must be large enough to hold all the
+  uncompressed data. (The size of the uncompressed data may have been saved
+  by the compressor for this purpose.) The next operation on this stream must
+  be inflateEnd to deallocate the decompression state. The use of Z_FINISH
+  is never required, but can be used to inform inflate that a faster routine
+  may be used for the single inflate() call.
+
+     If a preset dictionary is needed at this point (see inflateSetDictionary
+  below), inflate sets strm-adler to the adler32 checksum of the
+  dictionary chosen by the compressor and returns Z_NEED_DICT; otherwise 
+  it sets strm->adler to the adler32 checksum of all output produced
+  so (that is, total_out bytes) and returns Z_OK, Z_STREAM_END or
+  an error code as described below. At the end of the stream, inflate()
+  checks that its computed adler32 checksum is equal to that saved by the
+  compressor and returns Z_STREAM_END only if the checksum is correct.
+
+    inflate() returns Z_OK if some progress has been made (more input processed
+  or more output produced), Z_STREAM_END if the end of the compressed data has
+  been reached and all uncompressed output has been produced, Z_NEED_DICT if a
+  preset dictionary is needed at this point, Z_DATA_ERROR if the input data was
+  corrupted (input stream not conforming to the zlib format or incorrect
+  adler32 checksum), Z_STREAM_ERROR if the stream structure was inconsistent
+  (for example if next_in or next_out was NULL), Z_MEM_ERROR if there was not
+  enough memory, Z_BUF_ERROR if no progress is possible or if there was not
+  enough room in the output buffer when Z_FINISH is used. In the Z_DATA_ERROR
+  case, the application may then call inflateSync to look for a good
+  compression block.
+*/
+
+
+int inflateEnd OF((z_streamp strm));
+/*
+     All dynamically allocated data structures for this stream are freed.
+   This function discards any unprocessed input and does not flush any
+   pending output.
+
+     inflateEnd returns Z_OK if success, Z_STREAM_ERROR if the stream state
+   was inconsistent. In the error case, msg may be set but then points to a
+   static string (which must not be deallocated).
+*/
+
+                        /* Advanced functions */
+
+/*
+    The following functions are needed only in some special applications.
+*/
+
+/*   
+int deflateInit2 OF((z_streamp strm,
+                                     int  level,
+                                     int  method,
+                                     int  windowBits,
+                                     int  memLevel,
+                                     int  strategy));
+
+     This is another version of deflateInit with more compression options. The
+   fields next_in, zalloc, zfree and opaque must be initialized before by
+   the caller.
+
+     The method parameter is the compression method. It must be Z_DEFLATED in
+   this version of the library.
+
+     The windowBits parameter is the base two logarithm of the window size
+   (the size of the history buffer).  It should be in the range 8..15 for this
+   version of the library. Larger values of this parameter result in better
+   compression at the expense of memory usage. The default value is 15 if
+   deflateInit is used instead.
+
+     The memLevel parameter specifies how much memory should be allocated
+   for the internal compression state. memLevel=1 uses minimum memory but
+   is slow and reduces compression ratio; memLevel=9 uses maximum memory
+   for optimal speed. The default value is 8. See zconf.h for total memory
+   usage as a function of windowBits and memLevel.
+
+     The strategy parameter is used to tune the compression algorithm. Use the
+   value Z_DEFAULT_STRATEGY for normal data, Z_FILTERED for data produced by a
+   filter (or predictor), or Z_HUFFMAN_ONLY to force Huffman encoding only (no
+   string match).  Filtered data consists mostly of small values with a
+   somewhat random distribution. In this case, the compression algorithm is
+   tuned to compress them better. The effect of Z_FILTERED is to force more
+   Huffman coding and less string matching; it is somewhat intermediate
+   between Z_DEFAULT and Z_HUFFMAN_ONLY. The strategy parameter only affects
+   the compression ratio but not the correctness of the compressed output even
+   if it is not set appropriately.
+
+      deflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as an invalid
+   method). msg is set to null if there is no error message.  deflateInit2 does
+   not perform any compression: this will be done by deflate().
+*/
+                            
+int deflateSetDictionary OF((z_streamp strm,
+                                             const Byte *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the compression dictionary from the given byte sequence
+   without producing any compressed output. This function must be called
+   immediately after deflateInit, deflateInit2 or deflateReset, before any
+   call of deflate. The compressor and decompressor must use exactly the same
+   dictionary (see inflateSetDictionary).
+
+     The dictionary should consist of strings (byte sequences) that are likely
+   to be encountered later in the data to be compressed, with the most commonly
+   used strings preferably put towards the end of the dictionary. Using a
+   dictionary is most useful when the data to be compressed is short and can be
+   predicted with good accuracy; the data can then be compressed better than
+   with the default empty dictionary.
+
+     Depending on the size of the compression data structures selected by
+   deflateInit or deflateInit2, a part of the dictionary may in effect be
+   discarded, for example if the dictionary is larger than the window size in
+   deflate or deflate2. Thus the strings most likely to be useful should be
+   put at the end of the dictionary, not at the front.
+
+     Upon return of this function, strm->adler is set to the Adler32 value
+   of the dictionary; the decompressor may later use this value to determine
+   which dictionary has been used by the compressor. (The Adler32 value
+   applies to the whole dictionary even if only a subset of the dictionary is
+   actually used by the compressor.)
+
+     deflateSetDictionary returns Z_OK if success, or Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent (for example if deflate has already been called for this stream
+   or if the compression method is bsort). deflateSetDictionary does not
+   perform any compression: this will be done by deflate().
+*/
+
+int deflateCopy OF((z_streamp dest,
+                                    z_streamp source));
+/*
+     Sets the destination stream as a complete copy of the source stream.
+
+     This function can be useful when several compression strategies will be
+   tried, for example when there are several ways of pre-processing the input
+   data with a filter. The streams that will be discarded should then be freed
+   by calling deflateEnd.  Note that deflateCopy duplicates the internal
+   compression state which can be quite large, so this strategy is slow and
+   can consume lots of memory.
+
+     deflateCopy returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_STREAM_ERROR if the source stream state was inconsistent
+   (such as zalloc being NULL). msg is left unchanged in both source and
+   destination.
+*/
+
+int deflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to deflateEnd followed by deflateInit,
+   but does not free and reallocate all the internal compression state.
+   The stream will keep the same compression level and any other attributes
+   that may have been set by deflateInit2.
+
+      deflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+int deflateParams OF((z_streamp strm,
+				      int level,
+				      int strategy));
+/*
+     Dynamically update the compression level and compression strategy.  The
+   interpretation of level and strategy is as in deflateInit2.  This can be
+   used to switch between compression and straight copy of the input data, or
+   to switch to a different kind of input data requiring a different
+   strategy. If the compression level is changed, the input available so far
+   is compressed with the old level (and may be flushed); the new level will
+   take effect only at the next call of deflate().
+
+     Before the call of deflateParams, the stream state must be set as for
+   a call of deflate(), since the currently available input may have to
+   be compressed and flushed. In particular, strm->avail_out must be non-zero.
+
+     deflateParams returns Z_OK if success, Z_STREAM_ERROR if the source
+   stream state was inconsistent or if a parameter was invalid, Z_BUF_ERROR
+   if strm->avail_out was zero.
+*/
+
+/*   
+int inflateInit2 OF((z_streamp strm,
+                                     int  windowBits));
+
+     This is another version of inflateInit with an extra parameter. The
+   fields next_in, avail_in, zalloc, zfree and opaque must be initialized
+   before by the caller.
+
+     The windowBits parameter is the base two logarithm of the maximum window
+   size (the size of the history buffer).  It should be in the range 8..15 for
+   this version of the library. The default value is 15 if inflateInit is used
+   instead. If a compressed stream with a larger window size is given as
+   input, inflate() will return with the error code Z_DATA_ERROR instead of
+   trying to allocate a larger window.
+
+      inflateInit2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_STREAM_ERROR if a parameter is invalid (such as a negative
+   memLevel). msg is set to null if there is no error message.  inflateInit2
+   does not perform any decompression apart from reading the zlib header if
+   present: this will be done by inflate(). (So next_in and avail_in may be
+   modified, but next_out and avail_out are unchanged.)
+*/
+
+int inflateSetDictionary OF((z_streamp strm,
+                                             const Byte *dictionary,
+                                             uInt  dictLength));
+/*
+     Initializes the decompression dictionary from the given uncompressed byte
+   sequence. This function must be called immediately after a call of inflate
+   if this call returned Z_NEED_DICT. The dictionary chosen by the compressor
+   can be determined from the Adler32 value returned by this call of
+   inflate. The compressor and decompressor must use exactly the same
+   dictionary (see deflateSetDictionary).
+
+     inflateSetDictionary returns Z_OK if success, Z_STREAM_ERROR if a
+   parameter is invalid (such as NULL dictionary) or the stream state is
+   inconsistent, Z_DATA_ERROR if the given dictionary doesn't match the
+   expected one (incorrect Adler32 value). inflateSetDictionary does not
+   perform any decompression: this will be done by subsequent calls of
+   inflate().
+*/
+
+int inflateSync OF((z_streamp strm));
+/* 
+    Skips invalid compressed data until a full flush point (see above the
+  description of deflate with Z_FULL_FLUSH) can be found, or until all
+  available input is skipped. No output is provided.
+
+    inflateSync returns Z_OK if a full flush point has been found, Z_BUF_ERROR
+  if no more input was provided, Z_DATA_ERROR if no flush point has been found,
+  or Z_STREAM_ERROR if the stream structure was inconsistent. In the success
+  case, the application may save the current current value of total_in which
+  indicates where valid compressed data was found. In the error case, the
+  application may repeatedly call inflateSync, providing more input each time,
+  until success or end of the input data.
+*/
+
+int inflateReset OF((z_streamp strm));
+/*
+     This function is equivalent to inflateEnd followed by inflateInit,
+   but does not free and reallocate all the internal decompression state.
+   The stream will keep attributes that may have been set by inflateInit2.
+
+      inflateReset returns Z_OK if success, or Z_STREAM_ERROR if the source
+   stream state was inconsistent (such as zalloc or state being NULL).
+*/
+
+
+                        /* utility functions */
+
+/*
+     The following utility functions are implemented on top of the
+   basic stream-oriented functions. To simplify the interface, some
+   default options are assumed (compression level and memory usage,
+   standard memory allocation functions). The source code of these
+   utility functions can easily be modified if you need special options.
+*/
+
+int compress OF((Byte *dest,   uLong *destLen,
+                                 const Byte *source, uLong sourceLen));
+/*
+     Compresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be at least 0.1% larger than
+   sourceLen plus 12 bytes. Upon exit, destLen is the actual size of the
+   compressed buffer.
+     This function can be used to compress a whole file at once if the
+   input file is mmap'ed.
+     compress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer.
+*/
+
+int compress2 OF((Byte *dest,   uLong *destLen,
+                                  const Byte *source, uLong sourceLen,
+                                  int level));
+/*
+     Compresses the source buffer into the destination buffer. The level
+   parameter has the same meaning as in deflateInit.  sourceLen is the byte
+   length of the source buffer. Upon entry, destLen is the total size of the
+   destination buffer, which must be at least 0.1% larger than sourceLen plus
+   12 bytes. Upon exit, destLen is the actual size of the compressed buffer.
+
+     compress2 returns Z_OK if success, Z_MEM_ERROR if there was not enough
+   memory, Z_BUF_ERROR if there was not enough room in the output buffer,
+   Z_STREAM_ERROR if the level parameter is invalid.
+*/
+
+int uncompress OF((Byte *dest,   uLong *destLen,
+                                   const Byte *source, uLong sourceLen));
+/*
+     Decompresses the source buffer into the destination buffer.  sourceLen is
+   the byte length of the source buffer. Upon entry, destLen is the total
+   size of the destination buffer, which must be large enough to hold the
+   entire uncompressed data. (The size of the uncompressed data must have
+   been saved previously by the compressor and transmitted to the decompressor
+   by some mechanism outside the scope of this compression library.)
+   Upon exit, destLen is the actual size of the compressed buffer.
+     This function can be used to decompress a whole file at once if the
+   input file is mmap'ed.
+
+     uncompress returns Z_OK if success, Z_MEM_ERROR if there was not
+   enough memory, Z_BUF_ERROR if there was not enough room in the output
+   buffer, or Z_DATA_ERROR if the input data was corrupted.
+*/
+
+
+typedef voidp gzFile;
+
+gzFile gzopen  OF((const char *path, const char *mode));
+/*
+     Opens a gzip (.gz) file for reading or writing. The mode parameter
+   is as in fopen ("rb" or "wb") but can also include a compression level
+   ("wb9") or a strategy: 'f' for filtered data as in "wb6f", 'h' for
+   Huffman only compression as in "wb1h". (See the description
+   of deflateInit2 for more information about the strategy parameter.)
+
+     gzopen can be used to read a file which is not in gzip format; in this
+   case gzread will directly read from the file without decompression.
+
+     gzopen returns NULL if the file could not be opened or if there was
+   insufficient memory to allocate the (de)compression state; errno
+   can be checked to distinguish the two cases (if errno is zero, the
+   zlib error is Z_MEM_ERROR).  */
+
+gzFile gzdopen  OF((int fd, const char *mode));
+/*
+     gzdopen() associates a gzFile with the file descriptor fd.  File
+   descriptors are obtained from calls like open, dup, creat, pipe or
+   fileno (in the file has been previously opened with fopen).
+   The mode parameter is as in gzopen.
+     The next call of gzclose on the returned gzFile will also close the
+   file descriptor fd, just like fclose(fdopen(fd), mode) closes the file
+   descriptor fd. If you want to keep fd open, use gzdopen(dup(fd), mode).
+     gzdopen returns NULL if there was insufficient memory to allocate
+   the (de)compression state.
+*/
+
+int gzsetparams OF((gzFile file, int level, int strategy));
+/*
+     Dynamically update the compression level or strategy. See the description
+   of deflateInit2 for the meaning of these parameters.
+     gzsetparams returns Z_OK if success, or Z_STREAM_ERROR if the file was not
+   opened for writing.
+*/
+
+int    gzread  OF((gzFile file, voidp buf, unsigned len));
+/*
+     Reads the given number of uncompressed bytes from the compressed file.
+   If the input file was not in gzip format, gzread copies the given number
+   of bytes into the buffer.
+     gzread returns the number of uncompressed bytes actually read (0 for
+   end of file, -1 for error). */
+
+int    gzwrite OF((gzFile file, 
+				   const voidp buf, unsigned len));
+/*
+     Writes the given number of uncompressed bytes into the compressed file.
+   gzwrite returns the number of uncompressed bytes actually written
+   (0 in case of error).
+*/
+
+int    gzprintf OF((gzFile file, const char *format, ...));
+/*
+     Converts, formats, and writes the args to the compressed file under
+   control of the format string, as in fprintf. gzprintf returns the number of
+   uncompressed bytes actually written (0 in case of error).
+*/
+
+int gzputs OF((gzFile file, const char *s));
+/*
+      Writes the given null-terminated string to the compressed file, excluding
+   the terminating null character.
+      gzputs returns the number of characters written, or -1 in case of error.
+*/
+
+char * gzgets OF((gzFile file, char *buf, int len));
+/*
+      Reads bytes from the compressed file until len-1 characters are read, or
+   a newline character is read and transferred to buf, or an end-of-file
+   condition is encountered.  The string is then terminated with a null
+   character.
+      gzgets returns buf, or Z_NULL in case of error.
+*/
+
+int    gzputc OF((gzFile file, int c));
+/*
+      Writes c, converted to an unsigned char, into the compressed file.
+   gzputc returns the value that was written, or -1 in case of error.
+*/
+
+int    gzgetc OF((gzFile file));
+/*
+      Reads one byte from the compressed file. gzgetc returns this byte
+   or -1 in case of end of file or error.
+*/
+
+int    gzflush OF((gzFile file, int flush));
+/*
+     Flushes all pending output into the compressed file. The parameter
+   flush is as in the deflate() function. The return value is the zlib
+   error number (see function gzerror below). gzflush returns Z_OK if
+   the flush parameter is Z_FINISH and all output could be flushed.
+     gzflush should be called only when strictly necessary because it can
+   degrade compression.
+*/
+
+long gzseek OF((gzFile file,
+				      long offset, int whence));
+/* 
+      Sets the starting position for the next gzread or gzwrite on the
+   given compressed file. The offset represents a number of bytes in the
+   uncompressed data stream. The whence parameter is defined as in lseek(2);
+   the value SEEK_END is not supported.
+     If the file is opened for reading, this function is emulated but can be
+   extremely slow. If the file is opened for writing, only forward seeks are
+   supported; gzseek then compresses a sequence of zeroes up to the new
+   starting position.
+
+      gzseek returns the resulting offset location as measured in bytes from
+   the beginning of the uncompressed stream, or -1 in case of error, in
+   particular if the file is opened for writing and the new starting position
+   would be before the current position.
+*/
+
+int    gzrewind OF((gzFile file));
+/*
+     Rewinds the given file. This function is supported only for reading.
+
+   gzrewind(file) is equivalent to (int)gzseek(file, 0L, SEEK_SET)
+*/
+
+long    gztell OF((gzFile file));
+/*
+     Returns the starting position for the next gzread or gzwrite on the
+   given compressed file. This position represents a number of bytes in the
+   uncompressed data stream.
+
+   gztell(file) is equivalent to gzseek(file, 0L, SEEK_CUR)
+*/
+
+int gzeof OF((gzFile file));
+/*
+     Returns 1 when EOF has previously been detected reading the given
+   input stream, otherwise zero.
+*/
+
+int    gzclose OF((gzFile file));
+/*
+     Flushes all pending output if necessary, closes the compressed file
+   and deallocates all the (de)compression state. The return value is the zlib
+   error number (see function gzerror below).
+*/
+
+const char * gzerror OF((gzFile file, int *errnum));
+/*
+     Returns the error message for the last error which occurred on the
+   given compressed file. errnum is set to zlib error number. If an
+   error occurred in the file system and not in the compression library,
+   errnum is set to Z_ERRNO and the application may consult errno
+   to get the exact error code.
+*/
+
+                        /* checksum functions */
+
+/*
+     These functions are not related to compression but are exported
+   anyway because they might be useful in applications using the
+   compression library.
+*/
+
+uLong adler32 OF((uLong adler, const Byte *buf, uInt len));
+
+/*
+     Update a running Adler-32 checksum with the bytes buf[0..len-1] and
+   return the updated checksum. If buf is NULL, this function returns
+   the required initial value for the checksum.
+   An Adler-32 checksum is almost as reliable as a CRC32 but can be computed
+   much faster. Usage example:
+
+     uLong adler = adler32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       adler = adler32(adler, buffer, length);
+     }
+     if (adler != original_adler) error();
+*/
+
+uLong crc32   OF((uLong crc, const Byte *buf, uInt len));
+/*
+     Update a running crc with the bytes buf[0..len-1] and return the updated
+   crc. If buf is NULL, this function returns the required initial value
+   for the crc. Pre- and post-conditioning (one's complement) is performed
+   within this function so it shouldn't be done by the application.
+   Usage example:
+
+     uLong crc = crc32(0L, Z_NULL, 0);
+
+     while (read_buffer(buffer, length) != EOF) {
+       crc = crc32(crc, buffer, length);
+     }
+     if (crc != original_crc) error();
+*/
+
+// private stuff to not include cmdlib.h
+/*
+============================================================================
+
+					BYTE ORDER FUNCTIONS
+
+============================================================================
+*/
+
+#ifdef _SGI_SOURCE
+#define	__BIG_ENDIAN__
+#endif
+
+#ifdef __BIG_ENDIAN__
+
+short   __LittleShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   __BigShort (short l)
+{
+	return l;
+}
+
+
+int    __LittleLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    __BigLong (int l)
+{
+	return l;
+}
+
+
+float	__LittleFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	__BigFloat (float l)
+{
+	return l;
+}
+
+
+#else
+
+
+short   __BigShort (short l)
+{
+	byte    b1,b2;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+
+	return (b1<<8) + b2;
+}
+
+short   __LittleShort (short l)
+{
+	return l;
+}
+
+
+int    __BigLong (int l)
+{
+	byte    b1,b2,b3,b4;
+
+	b1 = l&255;
+	b2 = (l>>8)&255;
+	b3 = (l>>16)&255;
+	b4 = (l>>24)&255;
+
+	return ((int)b1<<24) + ((int)b2<<16) + ((int)b3<<8) + b4;
+}
+
+int    __LittleLong (int l)
+{
+	return l;
+}
+
+float	__BigFloat (float l)
+{
+	union {byte b[4]; float f;} in, out;
+	
+	in.f = l;
+	out.b[0] = in.b[3];
+	out.b[1] = in.b[2];
+	out.b[2] = in.b[1];
+	out.b[3] = in.b[0];
+	
+	return out.f;
+}
+
+float	__LittleFloat (float l)
+{
+	return l;
+}
+
+
+
+#endif
+
+
+
+
+                        /* various hacks, don't look :) */
+
+/* deflateInit and inflateInit are macros to allow checking the zlib version
+ * and the compiler's view of z_stream:
+ */
+int deflateInit_ OF((z_streamp strm, int level,
+                                     const char *version, int stream_size));
+int inflateInit_ OF((z_streamp strm,
+                                     const char *version, int stream_size));
+int deflateInit2_ OF((z_streamp strm, int  level, int  method,
+                                      int windowBits, int memLevel,
+                                      int strategy, const char *version,
+                                      int stream_size));
+int inflateInit2_ OF((z_streamp strm, int  windowBits,
+                                      const char *version, int stream_size));
+#define deflateInit(strm, level) \
+        deflateInit_((strm), (level),       ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit(strm) \
+        inflateInit_((strm),                ZLIB_VERSION, sizeof(z_stream))
+#define deflateInit2(strm, level, method, windowBits, memLevel, strategy) \
+        deflateInit2_((strm),(level),(method),(windowBits),(memLevel),\
+                      (strategy),           ZLIB_VERSION, sizeof(z_stream))
+#define inflateInit2(strm, windowBits) \
+        inflateInit2_((strm), (windowBits), ZLIB_VERSION, sizeof(z_stream))
+
+
+const char   * zError           OF((int err));
+int            inflateSyncPoint OF((z_streamp z));
+const uLong * get_crc_table    OF((void));
+
+typedef unsigned char  uch;
+typedef unsigned short ush;
+typedef unsigned long  ulg;
+
+extern const char *z_errmsg[10]; /* indexed by 2-zlib_error */
+/* (size given to avoid silly warnings with Visual C++) */
+
+#define ERR_MSG(err) z_errmsg[Z_NEED_DICT-(err)]
+
+#define ERR_RETURN(strm,err) \
+  return (strm->msg = (char*)ERR_MSG(err), (err))
+/* To be used only when the state is known to be valid */
+
+        /* common constants */
+
+#ifndef DEF_WBITS
+#  define DEF_WBITS MAX_WBITS
+#endif
+/* default windowBits for decompression. MAX_WBITS is for compression only */
+
+#if MAX_MEM_LEVEL >= 8
+#  define DEF_MEM_LEVEL 8
+#else
+#  define DEF_MEM_LEVEL  MAX_MEM_LEVEL
+#endif
+/* default memLevel */
+
+#define STORED_BLOCK 0
+#define STATIC_TREES 1
+#define DYN_TREES    2
+/* The three kinds of block type */
+
+#define MIN_MATCH  3
+#define MAX_MATCH  258
+/* The minimum and maximum match lengths */
+
+#define PRESET_DICT 0x20 /* preset dictionary flag in zlib header */
+
+        /* target dependencies */
+
+        /* Common defaults */
+
+#ifndef OS_CODE
+#  define OS_CODE  0x03  /* assume Unix */
+#endif
+
+#ifndef F_OPEN
+#  define F_OPEN(name, mode) fopen((name), (mode))
+#endif
+
+         /* functions */
+
+#ifdef HAVE_STRERROR
+   extern char *strerror OF((int));
+#  define zstrerror(errnum) strerror(errnum)
+#else
+#  define zstrerror(errnum) ""
+#endif
+
+#define zmemcpy memcpy
+#define zmemcmp memcmp
+#define zmemzero(dest, len) memset(dest, 0, len)
+
+/* Diagnostic functions */
+#ifdef _ZIP_DEBUG_
+   int z_verbose = 0;
+#  define Assert(cond,msg) assert(cond);
+   //{if(!(cond)) Sys_Error(msg);}
+#  define Trace(x) {if (z_verbose>=0) Sys_Error x ;}
+#  define Tracev(x) {if (z_verbose>0) Sys_Error x ;}
+#  define Tracevv(x) {if (z_verbose>1) Sys_Error x ;}
+#  define Tracec(c,x) {if (z_verbose>0 && (c)) Sys_Error x ;}
+#  define Tracecv(c,x) {if (z_verbose>1 && (c)) Sys_Error x ;}
+#else
+#  define Assert(cond,msg)
+#  define Trace(x)
+#  define Tracev(x)
+#  define Tracevv(x)
+#  define Tracec(c,x)
+#  define Tracecv(c,x)
+#endif
+
+
+typedef uLong (*check_func) OF((uLong check, const Byte *buf, uInt len));
+voidp zcalloc OF((voidp opaque, unsigned items, unsigned size));
+void   zcfree  OF((voidp opaque, voidp ptr));
+
+#define ZALLOC(strm, items, size) \
+           (*((strm)->zalloc))((strm)->opaque, (items), (size))
+#define ZFREE(strm, addr)  (*((strm)->zfree))((strm)->opaque, (voidp)(addr))
+#define TRY_FREE(s, p) {if (p) ZFREE(s, p);}
+
+
+#if !defined(unix) && !defined(CASESENSITIVITYDEFAULT_YES) && \
+                      !defined(CASESENSITIVITYDEFAULT_NO)
+#define CASESENSITIVITYDEFAULT_NO
+#endif
+
+
+#ifndef UNZ_BUFSIZE
+#define UNZ_BUFSIZE (65536)
+#endif
+
+#ifndef UNZ_MAXFILENAMEINZIP
+#define UNZ_MAXFILENAMEINZIP (256)
+#endif
+
+#ifndef ALLOC
+# define ALLOC(size) (safe_malloc(size))
+#endif
+#ifndef TRYFREE
+# define TRYFREE(p) {if (p) free(p);}
+#endif
+
+#define SIZECENTRALDIRITEM (0x2e)
+#define SIZEZIPLOCALHEADER (0x1e)
+
+
+
+/* ===========================================================================
+     Read a byte from a gz_stream; update next_in and avail_in. Return EOF
+   for end of file.
+   IN assertion: the stream s has been sucessfully opened for reading.
+*/
+
+/*
+static int unzlocal_getByte(FILE *fin,int *pi)
+{
+    unsigned char c;
+	int err = fread(&c, 1, 1, fin);
+    if (err==1)
+    {
+        *pi = (int)c;
+        return UNZ_OK;
+    }
+    else
+    {
+        if (ferror(fin)) 
+            return UNZ_ERRNO;
+        else
+            return UNZ_EOF;
+    }
+}
+*/
+
+/* ===========================================================================
+   Reads a long in LSB order from the given gz_stream. Sets 
+*/
+static int unzlocal_getShort (FILE* fin, uLong *pX)
+{
+	short	v;
+
+	fread( &v, sizeof(v), 1, fin );
+
+	*pX = __LittleShort( v);
+	return UNZ_OK;
+
+/*
+    uLong x ;
+    int i;
+    int err;
+
+    err = unzlocal_getByte(fin,&i);
+    x = (uLong)i;
+    
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<8;
+   
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+*/
+}
+
+static int unzlocal_getLong (FILE *fin, uLong *pX)
+{
+	int		v;
+
+	fread( &v, sizeof(v), 1, fin );
+
+	*pX = __LittleLong( v);
+	return UNZ_OK;
+
+/*
+    uLong x ;
+    int i;
+    int err;
+
+    err = unzlocal_getByte(fin,&i);
+    x = (uLong)i;
+    
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<8;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<16;
+
+    if (err==UNZ_OK)
+        err = unzlocal_getByte(fin,&i);
+    x += ((uLong)i)<<24;
+   
+    if (err==UNZ_OK)
+        *pX = x;
+    else
+        *pX = 0;
+    return err;
+*/
+}
+
+
+/* My own strcmpi / strcasecmp */
+static int strcmpcasenosensitive_internal (const char* fileName1,const char* fileName2)
+{
+	for (;;)
+	{
+		char c1=*(fileName1++);
+		char c2=*(fileName2++);
+		if ((c1>='a') && (c1<='z'))
+			c1 -= 0x20;
+		if ((c2>='a') && (c2<='z'))
+			c2 -= 0x20;
+		if (c1=='\0')
+			return ((c2=='\0') ? 0 : -1);
+		if (c2=='\0')
+			return 1;
+		if (c1<c2)
+			return -1;
+		if (c1>c2)
+			return 1;
+	}
+}
+
+
+#ifdef  CASESENSITIVITYDEFAULT_NO
+#define CASESENSITIVITYDEFAULTVALUE 2
+#else
+#define CASESENSITIVITYDEFAULTVALUE 1
+#endif
+
+#ifndef STRCMPCASENOSENTIVEFUNCTION
+#define STRCMPCASENOSENTIVEFUNCTION strcmpcasenosensitive_internal
+#endif
+
+/* 
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+                                                                or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+        (like 1 on Unix, 2 on Windows)
+
+*/
+extern int unzStringFileNameCompare (const char* fileName1,const char* fileName2,int iCaseSensitivity)
+{
+	if (iCaseSensitivity==0)
+		iCaseSensitivity=CASESENSITIVITYDEFAULTVALUE;
+
+	if (iCaseSensitivity==1)
+		return strcmp(fileName1,fileName2);
+
+	return STRCMPCASENOSENTIVEFUNCTION(fileName1,fileName2);
+} 
+
+#define BUFREADCOMMENT (0x400)
+
+/*
+  Locate the Central directory of a zipfile (at the end, just before
+    the global comment)
+*/
+static uLong unzlocal_SearchCentralDir(FILE *fin)
+{
+	unsigned char* buf;
+	uLong uSizeFile;
+	uLong uBackRead;
+	uLong uMaxBack=0xffff; /* maximum size of global comment */
+	uLong uPosFound=0;
+	
+	if (fseek(fin,0,SEEK_END) != 0)
+		return 0;
+
+
+	uSizeFile = ftell( fin );
+	
+	if (uMaxBack>uSizeFile)
+		uMaxBack = uSizeFile;
+
+	buf = (unsigned char*)safe_malloc(BUFREADCOMMENT+4);
+	if (buf==NULL)
+		return 0;
+
+	uBackRead = 4;
+	while (uBackRead<uMaxBack)
+	{
+		uLong uReadSize,uReadPos ;
+		int i;
+		if (uBackRead+BUFREADCOMMENT>uMaxBack) 
+			uBackRead = uMaxBack;
+		else
+			uBackRead+=BUFREADCOMMENT;
+		uReadPos = uSizeFile-uBackRead ;
+		
+		uReadSize = ((BUFREADCOMMENT+4) < (uSizeFile-uReadPos)) ? 
+                     (BUFREADCOMMENT+4) : (uSizeFile-uReadPos);
+		if (fseek(fin,uReadPos,SEEK_SET)!=0)
+			break;
+
+		if (fread(buf,(uInt)uReadSize,1,fin)!=1)
+			break;
+
+                for (i=(int)uReadSize-3; (i--)>0;)
+			if (((*(buf+i))==0x50) && ((*(buf+i+1))==0x4b) && 
+				((*(buf+i+2))==0x05) && ((*(buf+i+3))==0x06))
+			{
+				uPosFound = uReadPos+i;
+				break;
+			}
+
+		if (uPosFound!=0)
+			break;
+	}
+	free(buf);
+	return uPosFound;
+}
+
+extern unzFile unzReOpen (const char* path, unzFile file)
+{
+	unz_s *s;
+	FILE * fin;
+
+    fin=fopen(path,"rb");
+	if (fin==NULL)
+		return NULL;
+
+	s=(unz_s*)safe_malloc(sizeof(unz_s));
+	memcpy(s, (unz_s*)file, sizeof(unz_s));
+
+	s->file = fin;
+	return (unzFile)s;	
+}
+
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\test\\zlib109.zip" or on an Unix computer
+	 "zlib/zlib109.zip".
+	 If the zipfile cannot be opened (file don't exist or in not valid), the
+	   return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+	   of this unzip package.
+*/
+extern unzFile unzOpen (const char* path)
+{
+	unz_s us;
+	unz_s *s;
+	uLong central_pos,uL;
+	FILE * fin ;
+
+	uLong number_disk;          /* number of the current dist, used for 
+								   spaning ZIP, unsupported, always 0*/
+	uLong number_disk_with_CD;  /* number the the disk with central dir, used
+								   for spaning ZIP, unsupported, always 0*/
+	uLong number_entry_CD;      /* total number of entries in
+	                               the central dir 
+	                               (same than number_entry on nospan) */
+
+	int err=UNZ_OK;
+
+    fin=fopen(path,"rb");
+	if (fin==NULL)
+		return NULL;
+
+	central_pos = unzlocal_SearchCentralDir(fin);
+	if (central_pos==0)
+		err=UNZ_ERRNO;
+
+	if (fseek(fin,central_pos,SEEK_SET)!=0)
+		err=UNZ_ERRNO;
+
+	/* the signature, already checked */
+	if (unzlocal_getLong(fin,&uL)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	/* number of this disk */
+	if (unzlocal_getShort(fin,&number_disk)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	/* number of the disk with the start of the central directory */
+	if (unzlocal_getShort(fin,&number_disk_with_CD)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	/* total number of entries in the central dir on this disk */
+	if (unzlocal_getShort(fin,&us.gi.number_entry)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	/* total number of entries in the central dir */
+	if (unzlocal_getShort(fin,&number_entry_CD)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if ((number_entry_CD!=us.gi.number_entry) ||
+		(number_disk_with_CD!=0) ||
+		(number_disk!=0))
+		err=UNZ_BADZIPFILE;
+
+	/* size of the central directory */
+	if (unzlocal_getLong(fin,&us.size_central_dir)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	/* offset of start of central directory with respect to the 
+	      starting disk number */
+	if (unzlocal_getLong(fin,&us.offset_central_dir)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	/* zipfile comment length */
+	if (unzlocal_getShort(fin,&us.gi.size_comment)!=UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if ((central_pos<us.offset_central_dir+us.size_central_dir) && 
+		(err==UNZ_OK))
+		err=UNZ_BADZIPFILE;
+
+	if (err!=UNZ_OK)
+	{
+		fclose(fin);
+		return NULL;
+	}
+
+	us.file=fin;
+	us.byte_before_the_zipfile = central_pos -
+		                    (us.offset_central_dir+us.size_central_dir);
+	us.central_pos = central_pos;
+    us.pfile_in_zip_read = NULL;
+	
+
+	s=(unz_s*)safe_malloc(sizeof(unz_s));
+	*s=us;
+//	unzGoToFirstFile((unzFile)s);	
+	return (unzFile)s;	
+}
+
+
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzipOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+extern int unzClose (unzFile file)
+{
+	unz_s* s;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+
+    if (s->pfile_in_zip_read!=NULL)
+        unzCloseCurrentFile(file);
+
+	fclose(s->file);
+	free(s);
+	return UNZ_OK;
+}
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+extern int unzGetGlobalInfo (unzFile file,unz_global_info *pglobal_info)
+{
+	unz_s* s;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+	*pglobal_info=s->gi;
+	return UNZ_OK;
+}
+
+
+/*
+   Translate date/time from Dos format to tm_unz (readable more easilty)
+*/
+static void unzlocal_DosDateToTmuDate (uLong ulDosDate, tm_unz* ptm)
+{
+    uLong uDate;
+    uDate = (uLong)(ulDosDate>>16);
+    ptm->tm_mday = (uInt)(uDate&0x1f) ;
+    ptm->tm_mon =  (uInt)((((uDate)&0x1E0)/0x20)-1) ;
+    ptm->tm_year = (uInt)(((uDate&0x0FE00)/0x0200)+1980) ;
+
+    ptm->tm_hour = (uInt) ((ulDosDate &0xF800)/0x800);
+    ptm->tm_min =  (uInt) ((ulDosDate&0x7E0)/0x20) ;
+    ptm->tm_sec =  (uInt) (2*(ulDosDate&0x1f)) ;
+}
+
+/*
+  Get Info about the current file in the zipfile, with internal only info
+*/
+static int unzlocal_GetCurrentFileInfoInternal (unzFile file,
+                                                  unz_file_info *pfile_info,
+                                                  unz_file_info_internal 
+                                                  *pfile_info_internal,
+                                                  char *szFileName,
+												  uLong fileNameBufferSize,
+                                                  void *extraField,
+												  uLong extraFieldBufferSize,
+                                                  char *szComment,
+												  uLong commentBufferSize)
+{
+	unz_s* s;
+	unz_file_info file_info;
+	unz_file_info_internal file_info_internal;
+	int err=UNZ_OK;
+	uLong uMagic;
+	long lSeek=0;
+
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+	if (fseek(s->file,s->pos_in_central_dir+s->byte_before_the_zipfile,SEEK_SET)!=0)
+		err=UNZ_ERRNO;
+
+
+	/* we check the magic */
+	if (err==UNZ_OK)
+		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
+			err=UNZ_ERRNO;
+		else if (uMagic!=0x02014b50)
+			err=UNZ_BADZIPFILE;
+
+	if (unzlocal_getShort(s->file,&file_info.version) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.version_needed) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.flag) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.compression_method) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getLong(s->file,&file_info.dosDate) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+    unzlocal_DosDateToTmuDate(file_info.dosDate,&file_info.tmu_date);
+
+	if (unzlocal_getLong(s->file,&file_info.crc) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getLong(s->file,&file_info.compressed_size) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getLong(s->file,&file_info.uncompressed_size) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.size_filename) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.size_file_extra) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.size_file_comment) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.disk_num_start) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&file_info.internal_fa) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getLong(s->file,&file_info.external_fa) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getLong(s->file,&file_info_internal.offset_curfile) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	lSeek+=file_info.size_filename;
+	if ((err==UNZ_OK) && (szFileName!=NULL))
+	{
+		uLong uSizeRead ;
+		if (file_info.size_filename<fileNameBufferSize)
+		{
+			*(szFileName+file_info.size_filename)='\0';
+			uSizeRead = file_info.size_filename;
+		}
+		else
+			uSizeRead = fileNameBufferSize;
+
+		if ((file_info.size_filename>0) && (fileNameBufferSize>0))
+			if (fread(szFileName,(uInt)uSizeRead,1,s->file)!=1)
+				err=UNZ_ERRNO;
+		lSeek -= uSizeRead;
+	}
+
+	
+	if ((err==UNZ_OK) && (extraField!=NULL))
+	{
+		uLong uSizeRead ;
+		if (file_info.size_file_extra<extraFieldBufferSize)
+			uSizeRead = file_info.size_file_extra;
+		else
+			uSizeRead = extraFieldBufferSize;
+
+		if (lSeek!=0)
+			if (fseek(s->file,lSeek,SEEK_CUR)==0)
+				lSeek=0;
+			else
+				err=UNZ_ERRNO;
+		if ((file_info.size_file_extra>0) && (extraFieldBufferSize>0))
+			if (fread(extraField,(uInt)uSizeRead,1,s->file)!=1)
+				err=UNZ_ERRNO;
+		lSeek += file_info.size_file_extra - uSizeRead;
+	}
+	else
+		lSeek+=file_info.size_file_extra; 
+
+	
+	if ((err==UNZ_OK) && (szComment!=NULL))
+	{
+		uLong uSizeRead ;
+		if (file_info.size_file_comment<commentBufferSize)
+		{
+			*(szComment+file_info.size_file_comment)='\0';
+			uSizeRead = file_info.size_file_comment;
+		}
+		else
+			uSizeRead = commentBufferSize;
+
+		if (lSeek!=0)
+			if (fseek(s->file,lSeek,SEEK_CUR)==0)
+				lSeek=0;
+			else
+				err=UNZ_ERRNO;
+		if ((file_info.size_file_comment>0) && (commentBufferSize>0))
+			if (fread(szComment,(uInt)uSizeRead,1,s->file)!=1)
+				err=UNZ_ERRNO;
+		lSeek+=file_info.size_file_comment - uSizeRead;
+	}
+	else
+		lSeek+=file_info.size_file_comment;
+
+	if ((err==UNZ_OK) && (pfile_info!=NULL))
+		*pfile_info=file_info;
+
+	if ((err==UNZ_OK) && (pfile_info_internal!=NULL))
+		*pfile_info_internal=file_info_internal;
+
+	return err;
+}
+
+
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem.
+*/
+extern int unzGetCurrentFileInfo (	unzFile file, unz_file_info *pfile_info,
+									char *szFileName, uLong fileNameBufferSize,
+									void *extraField, uLong extraFieldBufferSize,
+									char *szComment, uLong commentBufferSize)
+{
+	return unzlocal_GetCurrentFileInfoInternal(file,pfile_info,NULL,
+												szFileName,fileNameBufferSize,
+												extraField,extraFieldBufferSize,
+												szComment,commentBufferSize);
+}
+
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+extern int unzGoToFirstFile (unzFile file)
+{
+	int err=UNZ_OK;
+	unz_s* s;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+	s->pos_in_central_dir=s->offset_central_dir;
+	s->num_file=0;
+	err=unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+											 &s->cur_file_info_internal,
+											 NULL,0,NULL,0,NULL,0);
+	s->current_file_ok = (err == UNZ_OK);
+	return err;
+}
+
+
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+extern int unzGoToNextFile (unzFile file)
+{
+	unz_s* s;	
+	int err;
+
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+	if (!s->current_file_ok)
+		return UNZ_END_OF_LIST_OF_FILE;
+	if (s->num_file+1==s->gi.number_entry)
+		return UNZ_END_OF_LIST_OF_FILE;
+
+	s->pos_in_central_dir += SIZECENTRALDIRITEM + s->cur_file_info.size_filename +
+			s->cur_file_info.size_file_extra + s->cur_file_info.size_file_comment ;
+	s->num_file++;
+	err = unzlocal_GetCurrentFileInfoInternal(file,&s->cur_file_info,
+											   &s->cur_file_info_internal,
+											   NULL,0,NULL,0,NULL,0);
+	s->current_file_ok = (err == UNZ_OK);
+	return err;
+}
+
+
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzipStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity)
+{
+	unz_s* s;	
+	int err;
+
+	
+	uLong num_fileSaved;
+	uLong pos_in_central_dirSaved;
+
+
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+
+    if (strlen(szFileName)>=UNZ_MAXFILENAMEINZIP)
+        return UNZ_PARAMERROR;
+
+	s=(unz_s*)file;
+	if (!s->current_file_ok)
+		return UNZ_END_OF_LIST_OF_FILE;
+
+	num_fileSaved = s->num_file;
+	pos_in_central_dirSaved = s->pos_in_central_dir;
+
+	err = unzGoToFirstFile(file);
+
+	while (err == UNZ_OK)
+	{
+		char szCurrentFileName[UNZ_MAXFILENAMEINZIP+1];
+		unzGetCurrentFileInfo(file,NULL,
+								szCurrentFileName,sizeof(szCurrentFileName)-1,
+								NULL,0,NULL,0);
+		if (unzStringFileNameCompare(szCurrentFileName,
+										szFileName,iCaseSensitivity)==0)
+			return UNZ_OK;
+		err = unzGoToNextFile(file);
+	}
+
+	s->num_file = num_fileSaved ;
+	s->pos_in_central_dir = pos_in_central_dirSaved ;
+	return err;
+}
+
+
+/*
+  Read the static header of the current zipfile
+  Check the coherency of the static header and info in the end of central
+        directory about this file
+  store in *piSizeVar the size of extra info in static header
+        (filename and size of extra field data)
+*/
+static int unzlocal_CheckCurrentFileCoherencyHeader (unz_s* s, uInt* piSizeVar,
+													uLong *poffset_local_extrafield,
+													uInt *psize_local_extrafield)
+{
+	uLong uMagic,uData,uFlags;
+	uLong size_filename;
+	uLong size_extra_field;
+	int err=UNZ_OK;
+
+	*piSizeVar = 0;
+	*poffset_local_extrafield = 0;
+	*psize_local_extrafield = 0;
+
+	if (fseek(s->file,s->cur_file_info_internal.offset_curfile +
+								s->byte_before_the_zipfile,SEEK_SET)!=0)
+		return UNZ_ERRNO;
+
+
+	if (err==UNZ_OK)
+		if (unzlocal_getLong(s->file,&uMagic) != UNZ_OK)
+			err=UNZ_ERRNO;
+		else if (uMagic!=0x04034b50)
+			err=UNZ_BADZIPFILE;
+
+	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
+		err=UNZ_ERRNO;
+/*
+	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.wVersion))
+		err=UNZ_BADZIPFILE;
+*/
+	if (unzlocal_getShort(s->file,&uFlags) != UNZ_OK)
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getShort(s->file,&uData) != UNZ_OK)
+		err=UNZ_ERRNO;
+	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compression_method))
+		err=UNZ_BADZIPFILE;
+
+    if ((err==UNZ_OK) && (s->cur_file_info.compression_method!=0) &&
+                         (s->cur_file_info.compression_method!=Z_DEFLATED))
+        err=UNZ_BADZIPFILE;
+
+	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* date/time */
+		err=UNZ_ERRNO;
+
+	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* crc */
+		err=UNZ_ERRNO;
+	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.crc) &&
+		                      ((uFlags & 8)==0))
+		err=UNZ_BADZIPFILE;
+
+	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size compr */
+		err=UNZ_ERRNO;
+	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.compressed_size) &&
+							  ((uFlags & 8)==0))
+		err=UNZ_BADZIPFILE;
+
+	if (unzlocal_getLong(s->file,&uData) != UNZ_OK) /* size uncompr */
+		err=UNZ_ERRNO;
+	else if ((err==UNZ_OK) && (uData!=s->cur_file_info.uncompressed_size) && 
+							  ((uFlags & 8)==0))
+		err=UNZ_BADZIPFILE;
+
+
+	if (unzlocal_getShort(s->file,&size_filename) != UNZ_OK)
+		err=UNZ_ERRNO;
+	else if ((err==UNZ_OK) && (size_filename!=s->cur_file_info.size_filename))
+		err=UNZ_BADZIPFILE;
+
+	*piSizeVar += (uInt)size_filename;
+
+	if (unzlocal_getShort(s->file,&size_extra_field) != UNZ_OK)
+		err=UNZ_ERRNO;
+	*poffset_local_extrafield= s->cur_file_info_internal.offset_curfile +
+									SIZEZIPLOCALHEADER + size_filename;
+	*psize_local_extrafield = (uInt)size_extra_field;
+
+	*piSizeVar += (uInt)size_extra_field;
+
+	return err;
+}
+												
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error and the file is opened, the return value is UNZ_OK.
+*/
+extern int unzOpenCurrentFile (unzFile file)
+{
+	int err=UNZ_OK;
+	int Store;
+	uInt iSizeVar;
+	unz_s* s;
+	file_in_zip_read_info_s* pfile_in_zip_read_info;
+	uLong offset_local_extrafield;  /* offset of the static extra field */
+	uInt  size_local_extrafield;    /* size of the static extra field */
+
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+	if (!s->current_file_ok)
+		return UNZ_PARAMERROR;
+
+    if (s->pfile_in_zip_read != NULL)
+        unzCloseCurrentFile(file);
+
+	if (unzlocal_CheckCurrentFileCoherencyHeader(s,&iSizeVar,
+				&offset_local_extrafield,&size_local_extrafield)!=UNZ_OK)
+		return UNZ_BADZIPFILE;
+
+	pfile_in_zip_read_info = (file_in_zip_read_info_s*)
+									    safe_malloc(sizeof(file_in_zip_read_info_s));
+	if (pfile_in_zip_read_info==NULL)
+		return UNZ_INTERNALERROR;
+
+	pfile_in_zip_read_info->read_buffer=(char*)safe_malloc(UNZ_BUFSIZE);
+	pfile_in_zip_read_info->offset_local_extrafield = offset_local_extrafield;
+	pfile_in_zip_read_info->size_local_extrafield = size_local_extrafield;
+	pfile_in_zip_read_info->pos_local_extrafield=0;
+
+	if (pfile_in_zip_read_info->read_buffer==NULL)
+	{
+		free(pfile_in_zip_read_info);
+		return UNZ_INTERNALERROR;
+	}
+
+	pfile_in_zip_read_info->stream_initialised=0;
+	
+	if ((s->cur_file_info.compression_method!=0) &&
+        (s->cur_file_info.compression_method!=Z_DEFLATED))
+		err=UNZ_BADZIPFILE;
+	Store = s->cur_file_info.compression_method==0;
+
+	pfile_in_zip_read_info->crc32_wait=s->cur_file_info.crc;
+	pfile_in_zip_read_info->crc32=0;
+	pfile_in_zip_read_info->compression_method =
+            s->cur_file_info.compression_method;
+	pfile_in_zip_read_info->file=s->file;
+	pfile_in_zip_read_info->byte_before_the_zipfile=s->byte_before_the_zipfile;
+
+    pfile_in_zip_read_info->stream.total_out = 0;
+
+	if (!Store)
+	{
+	  pfile_in_zip_read_info->stream.zalloc = (alloc_func)0;
+	  pfile_in_zip_read_info->stream.zfree = (free_func)0;
+	  pfile_in_zip_read_info->stream.opaque = (voidp)0; 
+      
+	  err=inflateInit2(&pfile_in_zip_read_info->stream, -MAX_WBITS);
+	  if (err == Z_OK)
+	    pfile_in_zip_read_info->stream_initialised=1;
+        /* windowBits is passed < 0 to tell that there is no zlib header.
+         * Note that in this case inflate *requires* an extra "dummy" byte
+         * after the compressed stream in order to complete decompression and
+         * return Z_STREAM_END. 
+         * In unzip, i don't wait absolutely Z_STREAM_END because I known the 
+         * size of both compressed and uncompressed data
+         */
+	}
+	pfile_in_zip_read_info->rest_read_compressed = 
+            s->cur_file_info.compressed_size ;
+	pfile_in_zip_read_info->rest_read_uncompressed = 
+            s->cur_file_info.uncompressed_size ;
+
+	
+	pfile_in_zip_read_info->pos_in_zipfile = 
+            s->cur_file_info_internal.offset_curfile + SIZEZIPLOCALHEADER + 
+			  iSizeVar;
+	
+	pfile_in_zip_read_info->stream.avail_in = (uInt)0;
+
+
+	s->pfile_in_zip_read = pfile_in_zip_read_info;
+    return UNZ_OK;
+}
+
+
+/*
+  Read bytes from the current file.
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of byte copied if somes bytes are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+extern int unzReadCurrentFile  (unzFile file, void *buf, unsigned len)
+{
+	int err=UNZ_OK;
+	uInt iRead = 0;
+	unz_s* s;
+	file_in_zip_read_info_s* pfile_in_zip_read_info;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+	if (pfile_in_zip_read_info==NULL)
+		return UNZ_PARAMERROR;
+
+
+	if ((pfile_in_zip_read_info->read_buffer == NULL))
+		return UNZ_END_OF_LIST_OF_FILE;
+	if (len==0)
+		return 0;
+
+	pfile_in_zip_read_info->stream.next_out = (Byte*)buf;
+
+	pfile_in_zip_read_info->stream.avail_out = (uInt)len;
+	
+	if (len>pfile_in_zip_read_info->rest_read_uncompressed)
+		pfile_in_zip_read_info->stream.avail_out = 
+		  (uInt)pfile_in_zip_read_info->rest_read_uncompressed;
+
+	while (pfile_in_zip_read_info->stream.avail_out>0)
+	{
+		if ((pfile_in_zip_read_info->stream.avail_in==0) &&
+            (pfile_in_zip_read_info->rest_read_compressed>0))
+		{
+			uInt uReadThis = UNZ_BUFSIZE;
+			if (pfile_in_zip_read_info->rest_read_compressed<uReadThis)
+				uReadThis = (uInt)pfile_in_zip_read_info->rest_read_compressed;
+			if (uReadThis == 0)
+				return UNZ_EOF;
+			if (s->cur_file_info.compressed_size == pfile_in_zip_read_info->rest_read_compressed)
+				if (fseek(pfile_in_zip_read_info->file,
+						  pfile_in_zip_read_info->pos_in_zipfile + 
+							 pfile_in_zip_read_info->byte_before_the_zipfile,SEEK_SET)!=0)
+					return UNZ_ERRNO;
+			if (fread(pfile_in_zip_read_info->read_buffer,uReadThis,1,
+                         pfile_in_zip_read_info->file)!=1)
+				return UNZ_ERRNO;
+			pfile_in_zip_read_info->pos_in_zipfile += uReadThis;
+
+			pfile_in_zip_read_info->rest_read_compressed-=uReadThis;
+			
+			pfile_in_zip_read_info->stream.next_in = 
+                (Byte*)pfile_in_zip_read_info->read_buffer;
+			pfile_in_zip_read_info->stream.avail_in = (uInt)uReadThis;
+		}
+
+		if (pfile_in_zip_read_info->compression_method==0)
+		{
+			uInt uDoCopy,i ;
+			if (pfile_in_zip_read_info->stream.avail_out < 
+                            pfile_in_zip_read_info->stream.avail_in)
+				uDoCopy = pfile_in_zip_read_info->stream.avail_out ;
+			else
+				uDoCopy = pfile_in_zip_read_info->stream.avail_in ;
+				
+			for (i=0;i<uDoCopy;i++)
+				*(pfile_in_zip_read_info->stream.next_out+i) =
+                        *(pfile_in_zip_read_info->stream.next_in+i);
+					
+			pfile_in_zip_read_info->crc32 = crc32(pfile_in_zip_read_info->crc32,
+								pfile_in_zip_read_info->stream.next_out,
+								uDoCopy);
+			pfile_in_zip_read_info->rest_read_uncompressed-=uDoCopy;
+			pfile_in_zip_read_info->stream.avail_in -= uDoCopy;
+			pfile_in_zip_read_info->stream.avail_out -= uDoCopy;
+			pfile_in_zip_read_info->stream.next_out += uDoCopy;
+			pfile_in_zip_read_info->stream.next_in += uDoCopy;
+            pfile_in_zip_read_info->stream.total_out += uDoCopy;
+			iRead += uDoCopy;
+		}
+		else
+		{
+			uLong uTotalOutBefore,uTotalOutAfter;
+			const Byte *bufBefore;
+			uLong uOutThis;
+			int flush=Z_SYNC_FLUSH;
+
+			uTotalOutBefore = pfile_in_zip_read_info->stream.total_out;
+			bufBefore = pfile_in_zip_read_info->stream.next_out;
+
+			/*
+			if ((pfile_in_zip_read_info->rest_read_uncompressed ==
+			         pfile_in_zip_read_info->stream.avail_out) &&
+				(pfile_in_zip_read_info->rest_read_compressed == 0))
+				flush = Z_FINISH;
+			*/
+			err=inflate(&pfile_in_zip_read_info->stream,flush);
+
+			uTotalOutAfter = pfile_in_zip_read_info->stream.total_out;
+			uOutThis = uTotalOutAfter-uTotalOutBefore;
+			
+			pfile_in_zip_read_info->crc32 = 
+                crc32(pfile_in_zip_read_info->crc32,bufBefore,
+                        (uInt)(uOutThis));
+
+			pfile_in_zip_read_info->rest_read_uncompressed -=
+                uOutThis;
+
+			iRead += (uInt)(uTotalOutAfter - uTotalOutBefore);
+            
+			if (err==Z_STREAM_END)
+				return (iRead==0) ? UNZ_EOF : iRead;
+			if (err!=Z_OK) 
+				break;
+		}
+	}
+
+	if (err==Z_OK)
+		return iRead;
+	return err;
+}
+
+
+/*
+  Give the current position in uncompressed data
+*/
+extern long unztell (unzFile file)
+{
+	unz_s* s;
+	file_in_zip_read_info_s* pfile_in_zip_read_info;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+	if (pfile_in_zip_read_info==NULL)
+		return UNZ_PARAMERROR;
+
+	return (long)pfile_in_zip_read_info->stream.total_out;
+}
+
+
+/*
+  return 1 if the end of file was reached, 0 elsewhere 
+*/
+extern int unzeof (unzFile file)
+{
+	unz_s* s;
+	file_in_zip_read_info_s* pfile_in_zip_read_info;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+	if (pfile_in_zip_read_info==NULL)
+		return UNZ_PARAMERROR;
+	
+	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+		return 1;
+	else
+		return 0;
+}
+
+
+
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the static-header version of the extra field (sometimes, there is
+    more info in the static-header version than in the central-header)
+
+  if buf==NULL, it return the size of the static extra field that can be read
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+	buf.
+  the return value is the number of bytes copied in buf, or (if <0) 
+	the error code
+*/
+extern int unzGetLocalExtrafield (unzFile file,void *buf,unsigned len)
+{
+	unz_s* s;
+	file_in_zip_read_info_s* pfile_in_zip_read_info;
+	uInt read_now;
+	uLong size_to_read;
+
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+	if (pfile_in_zip_read_info==NULL)
+		return UNZ_PARAMERROR;
+
+	size_to_read = (pfile_in_zip_read_info->size_local_extrafield - 
+				pfile_in_zip_read_info->pos_local_extrafield);
+
+	if (buf==NULL)
+		return (int)size_to_read;
+	
+	if (len>size_to_read)
+		read_now = (uInt)size_to_read;
+	else
+		read_now = (uInt)len ;
+
+	if (read_now==0)
+		return 0;
+	
+	if (fseek(pfile_in_zip_read_info->file,
+              pfile_in_zip_read_info->offset_local_extrafield + 
+			  pfile_in_zip_read_info->pos_local_extrafield,SEEK_SET)!=0)
+		return UNZ_ERRNO;
+
+	if (fread(buf,(uInt)size_to_read,1,pfile_in_zip_read_info->file)!=1)
+		return UNZ_ERRNO;
+
+	return (int)read_now;
+}
+
+/*
+  Close the file in zip opened with unzipOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+extern int unzCloseCurrentFile (unzFile file)
+{
+	int err=UNZ_OK;
+
+	unz_s* s;
+	file_in_zip_read_info_s* pfile_in_zip_read_info;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+    pfile_in_zip_read_info=s->pfile_in_zip_read;
+
+	if (pfile_in_zip_read_info==NULL)
+		return UNZ_PARAMERROR;
+
+
+	if (pfile_in_zip_read_info->rest_read_uncompressed == 0)
+	{
+		if (pfile_in_zip_read_info->crc32 != pfile_in_zip_read_info->crc32_wait)
+			err=UNZ_CRCERROR;
+	}
+
+
+	free(pfile_in_zip_read_info->read_buffer);
+	pfile_in_zip_read_info->read_buffer = NULL;
+	if (pfile_in_zip_read_info->stream_initialised)
+		inflateEnd(&pfile_in_zip_read_info->stream);
+
+	pfile_in_zip_read_info->stream_initialised = 0;
+	free(pfile_in_zip_read_info);
+
+    s->pfile_in_zip_read=NULL;
+
+	return err;
+}
+
+
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of byte copied or an error code <0
+*/
+extern int unzGetGlobalComment (unzFile file, char *szComment, uLong uSizeBuf)
+{
+	unz_s* s;
+	uLong uReadThis ;
+	if (file==NULL)
+		return UNZ_PARAMERROR;
+	s=(unz_s*)file;
+
+	uReadThis = uSizeBuf;
+	if (uReadThis>s->gi.size_comment)
+		uReadThis = s->gi.size_comment;
+
+	if (fseek(s->file,s->central_pos+22,SEEK_SET)!=0)
+		return UNZ_ERRNO;
+
+	if (uReadThis>0)
+    {
+      *szComment='\0';
+	  if (fread(szComment,(uInt)uReadThis,1,s->file)!=1)
+		return UNZ_ERRNO;
+    }
+
+	if ((szComment != NULL) && (uSizeBuf > s->gi.size_comment))
+		*(szComment+s->gi.size_comment)='\0';
+	return (int)uReadThis;
+}
+
+/* crc32.c -- compute the CRC-32 of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+
+#ifdef DYNAMIC_CRC_TABLE
+
+static int crc_table_empty = 1;
+static uLong crc_table[256];
+static void make_crc_table OF((void));
+
+/*
+  Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
+  x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1.
+
+  Polynomials over GF(2) are represented in binary, one bit per coefficient,
+  with the lowest powers in the most significant bit.  Then adding polynomials
+  is just exclusive-or, and multiplying a polynomial by x is a right shift by
+  one.  If we call the above polynomial p, and represent a byte as the
+  polynomial q, also with the lowest power in the most significant bit (so the
+  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
+  where a mod b means the remainder after dividing a by b.
+
+  This calculation is done using the shift-register method of multiplying and
+  taking the remainder.  The register is initialized to zero, and for each
+  incoming bit, x^32 is added mod p to the register if the bit is a one (where
+  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
+  x (which is shifting right by one and adding x^32 mod p if the bit shifted
+  out is a one).  We start with the highest power (least significant bit) of
+  q and repeat for all eight bits of q.
+
+  The table is simply the CRC of all possible eight bit values.  This is all
+  the information needed to generate CRC's on data a byte at a time for all
+  combinations of CRC register values and incoming bytes.
+*/
+static void make_crc_table()
+{
+  uLong c;
+  int n, k;
+  uLong poly;            /* polynomial exclusive-or pattern */
+  /* terms of polynomial defining this crc (except x^32): */
+  static const Byte p[] = {0,1,2,4,5,7,8,10,11,12,16,22,23,26};
+
+  /* make exclusive-or pattern from polynomial (0xedb88320L) */
+  poly = 0L;
+  for (n = 0; n < sizeof(p)/sizeof(Byte); n++)
+    poly |= 1L << (31 - p[n]);
+ 
+  for (n = 0; n < 256; n++)
+  {
+    c = (uLong)n;
+    for (k = 0; k < 8; k++)
+      c = c & 1 ? poly ^ (c >> 1) : c >> 1;
+    crc_table[n] = c;
+  }
+  crc_table_empty = 0;
+}
+#else
+/* ========================================================================
+ * Table of CRC-32's of all single-byte values (made by make_crc_table)
+ */
+static const uLong crc_table[256] = {
+  0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
+  0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
+  0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
+  0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
+  0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
+  0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
+  0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
+  0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
+  0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
+  0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
+  0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
+  0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
+  0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
+  0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
+  0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
+  0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
+  0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
+  0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
+  0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
+  0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
+  0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
+  0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
+  0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
+  0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
+  0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
+  0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
+  0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
+  0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
+  0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
+  0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
+  0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
+  0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
+  0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
+  0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
+  0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
+  0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
+  0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
+  0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
+  0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
+  0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
+  0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
+  0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
+  0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
+  0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
+  0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
+  0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
+  0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
+  0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
+  0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
+  0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
+  0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
+  0x2d02ef8dL
+};
+#endif
+
+/* =========================================================================
+ * This function can be used by asm versions of crc32()
+ */
+#ifndef __APPLE__
+const uLong * get_crc_table()
+{
+#ifdef DYNAMIC_CRC_TABLE
+  if (crc_table_empty) make_crc_table();
+#endif
+  return (const uLong *)crc_table;
+}
+#endif
+
+/* ========================================================================= */
+#define DO1(buf) crc = crc_table[((int)crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
+#define DO2(buf)  DO1(buf); DO1(buf);
+#define DO4(buf)  DO2(buf); DO2(buf);
+#define DO8(buf)  DO4(buf); DO4(buf);
+
+/* ========================================================================= */
+#ifndef __APPLE__
+uLong crc32(uLong crc, const Byte *buf, uInt len)
+{
+    if (buf == Z_NULL) return 0L;
+#ifdef DYNAMIC_CRC_TABLE
+    if (crc_table_empty)
+      make_crc_table();
+#endif
+    crc = crc ^ 0xffffffffL;
+    while (len >= 8)
+    {
+      DO8(buf);
+      len -= 8;
+    }
+    if (len) do {
+      DO1(buf);
+    } while (--len);
+    return crc ^ 0xffffffffL;
+}
+#endif
+
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_blocks_state;
+typedef struct inflate_blocks_state inflate_blocks_statef;
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+    z_streamp z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+extern int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));                      /* initial return code */
+
+extern void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    uLong *));                  /* check value on output */
+
+extern int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_streamp));
+
+extern void inflate_set_dictionary OF((
+    inflate_blocks_statef *s,
+    const Byte *d,  /* dictionary */
+    uInt  n));       /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+    inflate_blocks_statef *s));
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* Table for deflate from PKZIP's appnote.txt. */
+static const uInt border[] = { /* Order of the bit length code lengths */
+        16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 11, 4, 12, 3, 13, 2, 14, 1, 15};
+
+/* inftrees.h -- header to use inftrees.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+/* Huffman code lookup table entry--this entry is four bytes for machines
+   that have 16-bit pointers (e.g. PC's in the small or medium model). */
+
+typedef struct inflate_huft_s inflate_huft;
+
+struct inflate_huft_s {
+  union {
+    struct {
+      Byte Exop;        /* number of extra bits or operation */
+      Byte Bits;        /* number of bits in this code or subcode */
+    } what;
+    uInt pad;           /* pad structure to a power of 2 (4 bytes for */
+  } word;               /*  16-bit, 8 bytes for 32-bit int's) */
+  uInt base;            /* literal, length base, distance base,
+                           or table offset */
+};
+
+/* Maximum size of dynamic tree.  The maximum found in a long but non-
+   exhaustive search was 1004 huft structures (850 for length/literals
+   and 154 for distances, the latter actually the result of an
+   exhaustive search).  The actual maximum is not known, but the
+   value below is more than safe. */
+#define MANY 1440
+
+extern int inflate_trees_bits OF((
+    uInt *,                    /* 19 code lengths */
+    uInt *,                    /* bits tree desired/actual depth */
+    inflate_huft * *,       /* bits tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_dynamic OF((
+    uInt,                       /* number of literal/length codes */
+    uInt,                       /* number of distance codes */
+    uInt *,                    /* that many (total) code lengths */
+    uInt *,                    /* literal desired/actual bit depth */
+    uInt *,                    /* distance desired/actual bit depth */
+    inflate_huft * *,       /* literal/length tree result */
+    inflate_huft * *,       /* distance tree result */
+    inflate_huft *,             /* space for trees */
+    z_streamp));                /* for messages */
+
+extern int inflate_trees_fixed OF((
+    uInt *,                    /* literal desired/actual bit depth */
+    uInt *,                    /* distance desired/actual bit depth */
+    inflate_huft * *,       /* literal/length tree result */
+    inflate_huft * *,       /* distance tree result */
+    z_streamp));                /* for memory allocation */
+
+
+/* infcodes.h -- header to use infcodes.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+struct inflate_codes_state;
+typedef struct inflate_codes_state inflate_codes_statef;
+
+extern inflate_codes_statef *inflate_codes_new OF((
+    uInt, uInt,
+    inflate_huft *, inflate_huft *,
+    z_streamp ));
+
+extern int inflate_codes OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+extern void inflate_codes_free OF((
+    inflate_codes_statef *,
+    z_streamp ));
+
+/* infutil.h -- types and macros common to blocks and codes
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+#ifndef _INFUTIL_H
+#define _INFUTIL_H
+
+typedef enum {
+      TYPE,     /* get type bits (3, including end bit) */
+      LENS,     /* get lengths for stored */
+      STORED,   /* processing stored block */
+      TABLE,    /* get table lengths */
+      BTREE,    /* get bit lengths tree for a dynamic block */
+      DTREE,    /* get length, distance trees for a dynamic block */
+      CODES,    /* processing fixed or dynamic block */
+      DRY,      /* output remaining window bytes */
+      DONE,     /* finished last block, done */
+      BAD}      /* got a data error--stuck here */
+inflate_block_mode;
+
+/* inflate blocks semi-private state */
+struct inflate_blocks_state {
+
+  /* mode */
+  inflate_block_mode  mode;     /* current inflate_block mode */
+
+  /* mode dependent information */
+  union {
+    uInt left;          /* if STORED, bytes left to copy */
+    struct {
+      uInt table;               /* table lengths (14 bits) */
+      uInt index;               /* index into blens (or border) */
+      uInt *blens;             /* bit lengths of codes */
+      uInt bb;                  /* bit length tree depth */
+      inflate_huft *tb;         /* bit length decoding tree */
+    } trees;            /* if DTREE, decoding info for trees */
+    struct {
+      inflate_codes_statef 
+         *codes;
+    } decode;           /* if CODES, current state */
+  } sub;                /* submode */
+  uInt last;            /* true if this block is the last block */
+
+  /* mode independent information */
+  uInt bitk;            /* bits in bit buffer */
+  uLong bitb;           /* bit buffer */
+  inflate_huft *hufts;  /* single safe_malloc for tree space */
+  Byte *window;        /* sliding window */
+  Byte *end;           /* one byte after sliding window */
+  Byte *read;          /* window read pointer */
+  Byte *write;         /* window write pointer */
+  check_func checkfn;   /* check function */
+  uLong check;          /* check on output */
+
+};
+
+
+/* defines for inflate input/output */
+/*   update pointers and return */
+#define UPDBITS {s->bitb=b;s->bitk=k;}
+#define UPDIN {z->avail_in=n;z->total_in+=p-z->next_in;z->next_in=p;}
+#define UPDOUT {s->write=q;}
+#define UPDATE {UPDBITS UPDIN UPDOUT}
+#define LEAVE {UPDATE return inflate_flush(s,z,r);}
+/*   get bytes and bits */
+#define LOADIN {p=z->next_in;n=z->avail_in;b=s->bitb;k=s->bitk;}
+#define NEEDBYTE {if(n)r=Z_OK;else LEAVE}
+#define NEXTBYTE (n--,*p++)
+#define NEEDBITS(j) {while(k<(j)){NEEDBYTE;b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define DUMPBITS(j) {b>>=(j);k-=(j);}
+/*   output bytes */
+#define WAVAIL (uInt)(q<s->read?s->read-q-1:s->end-q)
+#define LOADOUT {q=s->write;m=(uInt)WAVAIL;}
+#define WRAP {if(q==s->end&&s->read!=s->window){q=s->window;m=(uInt)WAVAIL;}}
+#define FLUSH {UPDOUT r=inflate_flush(s,z,r); LOADOUT}
+#define NEEDOUT {if(m==0){WRAP if(m==0){FLUSH WRAP if(m==0) LEAVE}}r=Z_OK;}
+#define OUTBYTE(a) {*q++=(Byte)(a);m--;}
+/*   load static pointers */
+#define LOAD {LOADIN LOADOUT}
+
+/* masks for lower bits (size given to avoid silly warnings with Visual C++) */
+extern uInt inflate_mask[17];
+
+/* copy as much as possible from the sliding window to the output area */
+extern int inflate_flush OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));
+
+#endif
+
+								
+/*
+   Notes beyond the 1.93a appnote.txt:
+
+   1. Distance pointers never point before the beginning of the output
+      stream.
+   2. Distance pointers can point back across blocks, up to 32k away.
+   3. There is an implied maximum of 7 bits for the bit length table and
+      15 bits for the actual data.
+   4. If only one code exists, then it is encoded using one bit.  (Zero
+      would be more efficient, but perhaps a little confusing.)  If two
+      codes exist, they are coded using one bit each (0 and 1).
+   5. There is no way of sending zero distance codes--a dummy must be
+      sent if there are none.  (History: a pre 2.0 version of PKZIP would
+      store blocks with no distance codes, but this was discovered to be
+      too harsh a criterion.)  Valid only for 1.93a.  2.04c does allow
+      zero distance codes, which is sent as one code of zero bits in
+      length.
+   6. There are up to 286 literal/length codes.  Code 256 represents the
+      end-of-block.  Note however that the static length tree defines
+      288 codes just to fill out the Huffman codes.  Codes 286 and 287
+      cannot be used though, since there is no length base or extra bits
+      defined for them.  Similarily, there are up to 30 distance codes.
+      However, static trees define 32 codes (all 5 bits) to fill out the
+      Huffman codes, but the last two had better not show up in the data.
+   7. Unzip can check dynamic Huffman blocks for complete code sets.
+      The exception is that a single code would not be complete (see #4).
+   8. The five bits following the block type is really the number of
+      literal codes sent minus 257.
+   9. Length codes 8,16,16 are interpreted as 13 length codes of 8 bits
+      (1+6+6).  Therefore, to output three times the length, you output
+      three codes (1+1+1), whereas to output four times the same length,
+      you only need two codes (1+3).  Hmm.
+  10. In the tree reconstruction algorithm, Code = Code + Increment
+      only if BitLength(i) is not zero.  (Pretty obvious.)
+  11. Correction: 4 Bits: # of Bit Length codes - 4     (4 - 19)
+  12. Note: length code 284 can represent 227-258, but length code 285
+      really is 258.  The last length deserves its own, short code
+      since it gets used a lot in very redundant files.  The length
+      258 is special since 258 - 3 (the min match length) is 255.
+  13. The literal/length and distance code bit lengths are read as a
+      single stream of lengths.  It is possible (and advantageous) for
+      a repeat code (16, 17, or 18) to go across the boundary between
+      the two sets of lengths.
+ */
+
+
+#ifndef __APPLE__
+void inflate_blocks_reset(inflate_blocks_statef *s, z_streamp z, uLong *c)
+{
+  if (c != Z_NULL)
+    *c = s->check;
+  if (s->mode == BTREE || s->mode == DTREE)
+    ZFREE(z, s->sub.trees.blens);
+  if (s->mode == CODES)
+    inflate_codes_free(s->sub.decode.codes, z);
+  s->mode = TYPE;
+  s->bitk = 0;
+  s->bitb = 0;
+  s->read = s->write = s->window;
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(0L, (const Byte *)Z_NULL, 0);
+  Tracev(("inflate:   blocks reset\n"));
+}
+#endif
+
+#ifndef __APPLE__
+inflate_blocks_statef *inflate_blocks_new(z_streamp z, check_func c, uInt w)
+{
+  inflate_blocks_statef *s;
+
+  if ((s = (inflate_blocks_statef *)ZALLOC
+       (z,1,sizeof(struct inflate_blocks_state))) == Z_NULL)
+    return s;
+  if ((s->hufts =
+       (inflate_huft *)ZALLOC(z, sizeof(inflate_huft), MANY)) == Z_NULL)
+  {
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  if ((s->window = (Byte *)ZALLOC(z, 1, w)) == Z_NULL)
+  {
+    ZFREE(z, s->hufts);
+    ZFREE(z, s);
+    return Z_NULL;
+  }
+  s->end = s->window + w;
+  s->checkfn = c;
+  s->mode = TYPE;
+  Tracev(("inflate:   blocks allocated\n"));
+  inflate_blocks_reset(s, z, Z_NULL);
+  return s;
+}
+#endif
+
+#ifndef __APPLE__
+int inflate_blocks(inflate_blocks_statef *s, z_streamp z, int r)
+{
+  uInt t;               /* temporary storage */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Byte *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Byte *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input based on current state */
+  while (1) switch (s->mode)
+  {
+    case TYPE:
+      NEEDBITS(3)
+      t = (uInt)b & 7;
+      s->last = t & 1;
+      switch (t >> 1)
+      {
+        case 0:                         /* stored */
+          Tracev(("inflate:     stored block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          t = k & 7;                    /* go to byte boundary */
+          DUMPBITS(t)
+          s->mode = LENS;               /* get length of stored block */
+          break;
+        case 1:                         /* fixed */
+          Tracev(("inflate:     fixed codes block%s\n",
+                 s->last ? " (last)" : ""));
+          {
+            uInt bl, bd;
+            inflate_huft *tl, *td;
+
+            inflate_trees_fixed(&bl, &bd, &tl, &td, z);
+            s->sub.decode.codes = inflate_codes_new(bl, bd, tl, td, z);
+            if (s->sub.decode.codes == Z_NULL)
+            {
+              r = Z_MEM_ERROR;
+              LEAVE
+            }
+          }
+          DUMPBITS(3)
+          s->mode = CODES;
+          break;
+        case 2:                         /* dynamic */
+          Tracev(("inflate:     dynamic codes block%s\n",
+                 s->last ? " (last)" : ""));
+          DUMPBITS(3)
+          s->mode = TABLE;
+          break;
+        case 3:                         /* illegal */
+          DUMPBITS(3)
+          s->mode = BAD;
+          z->msg = (char*)"invalid block type";
+          r = Z_DATA_ERROR;
+          LEAVE
+      }
+      break;
+    case LENS:
+      NEEDBITS(32)
+      if ((((~b) >> 16) & 0xffff) != (b & 0xffff))
+      {
+        s->mode = BAD;
+        z->msg = (char*)"invalid stored block lengths";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+      s->sub.left = (uInt)b & 0xffff;
+      b = k = 0;                      /* dump bits */
+      Tracev(("inflate:       stored length %u\n", s->sub.left));
+      s->mode = s->sub.left ? STORED : (s->last ? DRY : TYPE);
+      break;
+    case STORED:
+      if (n == 0)
+        LEAVE
+      NEEDOUT
+      t = s->sub.left;
+      if (t > n) t = n;
+      if (t > m) t = m;
+      zmemcpy(q, p, t);
+      p += t;  n -= t;
+      q += t;  m -= t;
+      if ((s->sub.left -= t) != 0)
+        break;
+      Tracev(("inflate:       stored end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      s->mode = s->last ? DRY : TYPE;
+      break;
+    case TABLE:
+      NEEDBITS(14)
+      s->sub.trees.table = t = (uInt)b & 0x3fff;
+#ifndef PKZIP_BUG_WORKAROUND
+      if ((t & 0x1f) > 29 || ((t >> 5) & 0x1f) > 29)
+      {
+        s->mode = BAD;
+        z->msg = (char*)"too many length or distance symbols";
+        r = Z_DATA_ERROR;
+        LEAVE
+      }
+#endif
+      t = 258 + (t & 0x1f) + ((t >> 5) & 0x1f);
+      if ((s->sub.trees.blens = (uInt*)ZALLOC(z, t, sizeof(uInt))) == Z_NULL)
+      {
+        r = Z_MEM_ERROR;
+        LEAVE
+      }
+      DUMPBITS(14)
+      s->sub.trees.index = 0;
+      Tracev(("inflate:       table sizes ok\n"));
+      s->mode = BTREE;
+    case BTREE:
+      while (s->sub.trees.index < 4 + (s->sub.trees.table >> 10))
+      {
+        NEEDBITS(3)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = (uInt)b & 7;
+        DUMPBITS(3)
+      }
+      while (s->sub.trees.index < 19)
+        s->sub.trees.blens[border[s->sub.trees.index++]] = 0;
+      s->sub.trees.bb = 7;
+      t = inflate_trees_bits(s->sub.trees.blens, &s->sub.trees.bb,
+                             &s->sub.trees.tb, s->hufts, z);
+      if (t != Z_OK)
+      {
+        ZFREE(z, s->sub.trees.blens);
+        r = t;
+        if (r == Z_DATA_ERROR)
+          s->mode = BAD;
+        LEAVE
+      }
+      s->sub.trees.index = 0;
+      Tracev(("inflate:       bits tree ok\n"));
+      s->mode = DTREE;
+    case DTREE:
+      while (t = s->sub.trees.table,
+             s->sub.trees.index < 258 + (t & 0x1f) + ((t >> 5) & 0x1f))
+      {
+        inflate_huft *h;
+        uInt i, j, c;
+
+        t = s->sub.trees.bb;
+        NEEDBITS(t)
+        h = s->sub.trees.tb + ((uInt)b & inflate_mask[t]);
+        t = h->bits;
+        c = h->base;
+        if (c < 16)
+        {
+          DUMPBITS(t)
+          s->sub.trees.blens[s->sub.trees.index++] = c;
+        }
+        else /* c == 16..18 */
+        {
+          i = c == 18 ? 7 : c - 14;
+          j = c == 18 ? 11 : 3;
+          NEEDBITS(t + i)
+          DUMPBITS(t)
+          j += (uInt)b & inflate_mask[i];
+          DUMPBITS(i)
+          i = s->sub.trees.index;
+          t = s->sub.trees.table;
+          if (i + j > 258 + (t & 0x1f) + ((t >> 5) & 0x1f) ||
+              (c == 16 && i < 1))
+          {
+            ZFREE(z, s->sub.trees.blens);
+            s->mode = BAD;
+            z->msg = (char*)"invalid bit length repeat";
+            r = Z_DATA_ERROR;
+            LEAVE
+          }
+          c = c == 16 ? s->sub.trees.blens[i - 1] : 0;
+          do {
+            s->sub.trees.blens[i++] = c;
+          } while (--j);
+          s->sub.trees.index = i;
+        }
+      }
+      s->sub.trees.tb = Z_NULL;
+      {
+        uInt bl, bd;
+        inflate_huft *tl, *td;
+        inflate_codes_statef *c;
+
+        bl = 9;         /* must be <= 9 for lookahead assumptions */
+        bd = 6;         /* must be <= 9 for lookahead assumptions */
+        t = s->sub.trees.table;
+        t = inflate_trees_dynamic(257 + (t & 0x1f), 1 + ((t >> 5) & 0x1f),
+                                  s->sub.trees.blens, &bl, &bd, &tl, &td,
+                                  s->hufts, z);
+        ZFREE(z, s->sub.trees.blens);
+        if (t != Z_OK)
+        {
+          if (t == (uInt)Z_DATA_ERROR)
+            s->mode = BAD;
+          r = t;
+          LEAVE
+        }
+        Tracev(("inflate:       trees ok\n"));
+        if ((c = inflate_codes_new(bl, bd, tl, td, z)) == Z_NULL)
+        {
+          r = Z_MEM_ERROR;
+          LEAVE
+        }
+        s->sub.decode.codes = c;
+      }
+      s->mode = CODES;
+    case CODES:
+      UPDATE
+      if ((r = inflate_codes(s, z, r)) != Z_STREAM_END)
+        return inflate_flush(s, z, r);
+      r = Z_OK;
+      inflate_codes_free(s->sub.decode.codes, z);
+      LOAD
+      Tracev(("inflate:       codes end, %lu total out\n",
+              z->total_out + (q >= s->read ? q - s->read :
+              (s->end - s->read) + (q - s->window))));
+      if (!s->last)
+      {
+        s->mode = TYPE;
+        break;
+      }
+      s->mode = DRY;
+    case DRY:
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      s->mode = DONE;
+    case DONE:
+      r = Z_STREAM_END;
+      LEAVE
+    case BAD:
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+}
+#endif
+
+#ifndef __APPLE__
+int inflate_blocks_free(inflate_blocks_statef *s, z_streamp z)
+{
+  inflate_blocks_reset(s, z, Z_NULL);
+  ZFREE(z, s->window);
+  ZFREE(z, s->hufts);
+  ZFREE(z, s);
+  Tracev(("inflate:   blocks freed\n"));
+  return Z_OK;
+}
+#endif
+
+#ifndef __APPLE__
+void inflate_set_dictionary(inflate_blocks_statef *s, const Byte *d, uInt n)
+{
+  zmemcpy(s->window, d, n);
+  s->read = s->write = s->window + n;
+}
+#endif
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. 
+ * IN assertion: s != Z_NULL
+ */
+#ifndef __APPLE__
+int inflate_blocks_sync_point(inflate_blocks_statef *s)
+{
+  return s->mode == LENS;
+}
+#endif
+
+/* And'ing with mask[n] masks the lower n bits */
+uInt inflate_mask[17] = {
+    0x0000,
+    0x0001, 0x0003, 0x0007, 0x000f, 0x001f, 0x003f, 0x007f, 0x00ff,
+    0x01ff, 0x03ff, 0x07ff, 0x0fff, 0x1fff, 0x3fff, 0x7fff, 0xffff
+};
+
+/* copy as much as possible from the sliding window to the output area */
+#ifndef __APPLE__
+int inflate_flush(inflate_blocks_statef *s, z_streamp z, int r)
+{
+  uInt n;
+  Byte *p;
+  Byte *q;
+
+  /* static copies of source and destination pointers */
+  p = z->next_out;
+  q = s->read;
+
+  /* compute number of bytes to copy as as end of window */
+  n = (uInt)((q <= s->write ? s->write : s->end) - q);
+  if (n > z->avail_out) n = z->avail_out;
+  if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+  /* update counters */
+  z->avail_out -= n;
+  z->total_out += n;
+
+  /* update check information */
+  if (s->checkfn != Z_NULL)
+    z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+  /* copy as as end of window */
+  zmemcpy(p, q, n);
+  p += n;
+  q += n;
+
+  /* see if more to copy at beginning of window */
+  if (q == s->end)
+  {
+    /* wrap pointers */
+    q = s->window;
+    if (s->write == s->end)
+      s->write = s->window;
+
+    /* compute bytes to copy */
+    n = (uInt)(s->write - q);
+    if (n > z->avail_out) n = z->avail_out;
+    if (n && r == Z_BUF_ERROR) r = Z_OK;
+
+    /* update counters */
+    z->avail_out -= n;
+    z->total_out += n;
+
+    /* update check information */
+    if (s->checkfn != Z_NULL)
+      z->adler = s->check = (*s->checkfn)(s->check, q, n);
+
+    /* copy */
+    zmemcpy(p, q, n);
+    p += n;
+    q += n;
+  }
+
+  /* update pointers */
+  z->next_out = p;
+  s->read = q;
+
+  /* done */
+  return r;
+}
+#endif
+
+/* inftrees.c -- generate Huffman trees for efficient decoding
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#ifndef __APPLE__
+const char inflate_copyright[] =
+   " inflate 1.1.3 Copyright 1995-1998 Mark Adler ";
+#endif
+
+/*
+  If you use the zlib library in a product, an acknowledgment is welcome
+  in the documentation of your product. If for some reason you cannot
+  include such an acknowledgment, I would appreciate that you keep this
+  copyright string in the executable of your product.
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+
+static int huft_build OF((
+    uInt *,				/* code lengths in bits */
+    uInt,               /* number of codes */
+    uInt,               /* number of "simple" codes */
+    const uInt *,		/* list of base values for non-simple codes */
+    const uInt *,		/* list of extra bits for non-simple codes */
+    inflate_huft **,	/* result: starting table */
+    uInt *,				/* maximum lookup bits (returns actual) */
+    inflate_huft *,     /* space for trees */
+    uInt *,             /* hufts used in space */
+    uInt * ));			/* space for values */
+
+/* Tables for deflate from PKZIP's appnote.txt. */
+static const uInt cplens[31] = { /* Copy lengths for literal codes 257..285 */
+        3, 4, 5, 6, 7, 8, 9, 10, 11, 13, 15, 17, 19, 23, 27, 31,
+        35, 43, 51, 59, 67, 83, 99, 115, 131, 163, 195, 227, 258, 0, 0};
+        /* see note #13 above about 258 */
+static const uInt cplext[31] = { /* Extra bits for literal codes 257..285 */
+        0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2,
+        3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 0, 112, 112}; /* 112==invalid */
+static const uInt cpdist[30] = { /* Copy offsets for distance codes 0..29 */
+        1, 2, 3, 4, 5, 7, 9, 13, 17, 25, 33, 49, 65, 97, 129, 193,
+        257, 385, 513, 769, 1025, 1537, 2049, 3073, 4097, 6145,
+        8193, 12289, 16385, 24577};
+static const uInt cpdext[30] = { /* Extra bits for distance codes */
+        0, 0, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6,
+        7, 7, 8, 8, 9, 9, 10, 10, 11, 11,
+        12, 12, 13, 13};
+
+/*
+   Huffman code decoding is performed using a multi-level table lookup.
+   The fastest way to decode is to simply build a lookup table whose
+   size is determined by the longest code.  However, the time it takes
+   to build this table can also be a factor if the data being decoded
+   is not very long.  The most common codes are necessarily the
+   shortest codes, so those codes dominate the decoding time, and hence
+   the speed.  The idea is you can have a shorter table that decodes the
+   shorter, more probable codes, and then point to subsidiary tables for
+   the longer codes.  The time it costs to decode the longer codes is
+   then traded against the time it takes to make longer tables.
+
+   This results of this trade are in the variables lbits and dbits
+   below.  lbits is the number of bits the first level table for literal/
+   length codes can decode in one step, and dbits is the same thing for
+   the distance codes.  Subsequent tables are also less than or equal to
+   those sizes.  These values may be adjusted either when all of the
+   codes are shorter than that, in which case the longest code length in
+   bits is used, or when the shortest code is *longer* than the requested
+   table size, in which case the length of the shortest code in bits is
+   used.
+
+   There are two different values for the two tables, since they code a
+   different number of possibilities each.  The literal/length table
+   codes 286 possible values, or in a flat code, a little over eight
+   bits.  The distance table codes 30 possible values, or a little less
+   than five bits, flat.  The optimum values for speed end up being
+   about one bit more than those, so lbits is 8+1 and dbits is 5+1.
+   The optimum values may differ though from machine to machine, and
+   possibly even between compilers.  Your mileage may vary.
+ */
+
+
+/* If BMAX needs to be larger than 16, then h and x[] should be uLong. */
+#define BMAX 15         /* maximum bit length of any code */
+
+static int huft_build(uInt *b, uInt n, uInt s, const uInt *d, const uInt *e, inflate_huft ** t, uInt *m, inflate_huft *hp, uInt *hn, uInt *v)
+//uInt *b;               /* code lengths in bits (all assumed <= BMAX) */
+//uInt n;                 /* number of codes (assumed <= 288) */
+//uInt s;                 /* number of simple-valued codes (0..s-1) */
+//const uInt *d;         /* list of base values for non-simple codes */
+//const uInt *e;         /* list of extra bits for non-simple codes */
+//inflate_huft ** t;		/* result: starting table */
+//uInt *m;               /* maximum lookup bits, returns actual */
+//inflate_huft *hp;       /* space for trees */
+//uInt *hn;               /* hufts used in space */
+//uInt *v;               /* working area: values in order of bit length */
+/* Given a list of code lengths and a maximum table size, make a set of
+   tables to decode that set of codes.  Return Z_OK on success, Z_BUF_ERROR
+   if the given code set is incomplete (the tables are still built in this
+   case), Z_DATA_ERROR if the input is invalid (an over-subscribed set of
+   lengths), or Z_MEM_ERROR if not enough memory. */
+{
+
+  uInt a;                       /* counter for codes of length k */
+  uInt c[BMAX+1];               /* bit length count table */
+  uInt f;                       /* i repeats in table every f entries */
+  int g;                        /* maximum code length */
+  int h;                        /* table level */
+  register uInt i;              /* counter, current code */
+  register uInt j;              /* counter */
+  register int k;               /* number of bits in current code */
+  int l;                        /* bits per table (returned in m) */
+  uInt mask;                    /* (1 << w) - 1, to avoid cc -O bug on HP */
+  register uInt *p;            /* pointer into c[], b[], or v[] */
+  inflate_huft *q;              /* points to current table */
+  struct inflate_huft_s r;      /* table entry for structure assignment */
+  inflate_huft *u[BMAX];        /* table stack */
+  register int w;               /* bits before this table == (l * h) */
+  uInt x[BMAX+1];               /* bit offsets, then code stack */
+  uInt *xp;                    /* pointer into x */
+  int y;                        /* number of dummy codes added */
+  uInt z;                       /* number of entries in current table */
+
+
+  /* Generate counts for each bit length */
+  p = c;
+#define C0 *p++ = 0;
+#define C2 C0 C0 C0 C0
+#define C4 C2 C2 C2 C2
+  C4                            /* clear c[]--assume BMAX+1 is 16 */
+  p = b;  i = n;
+  do {
+    c[*p++]++;                  /* assume all entries <= BMAX */
+  } while (--i);
+  if (c[0] == n)                /* null input--all zero length codes */
+  {
+    *t = (inflate_huft *)Z_NULL;
+    *m = 0;
+    return Z_OK;
+  }
+
+
+  /* Find minimum and maximum length, bound *m by those */
+  l = *m;
+  for (j = 1; j <= BMAX; j++)
+    if (c[j])
+      break;
+  k = j;                        /* minimum code length */
+  if ((uInt)l < j)
+    l = j;
+  for (i = BMAX; i; i--)
+    if (c[i])
+      break;
+  g = i;                        /* maximum code length */
+  if ((uInt)l > i)
+    l = i;
+  *m = l;
+
+
+  /* Adjust last length count to fill out codes, if needed */
+  for (y = 1 << j; j < i; j++, y <<= 1)
+    if ((y -= c[j]) < 0)
+      return Z_DATA_ERROR;
+  if ((y -= c[i]) < 0)
+    return Z_DATA_ERROR;
+  c[i] += y;
+
+
+  /* Generate starting offsets into the value table for each length */
+  x[1] = j = 0;
+  p = c + 1;  xp = x + 2;
+  while (--i) {                 /* note that i == g from above */
+    *xp++ = (j += *p++);
+  }
+
+
+  /* Make a table of values in order of bit lengths */
+  p = b;  i = 0;
+  do {
+    if ((j = *p++) != 0)
+      v[x[j]++] = i;
+  } while (++i < n);
+  n = x[g];                     /* set n to length of v */
+
+
+  /* Generate the Huffman codes and for each, make the table entries */
+  x[0] = i = 0;                 /* first Huffman code is zero */
+  p = v;                        /* grab values in bit order */
+  h = -1;                       /* no tables yet--level -1 */
+  w = -l;                       /* bits decoded == (l * h) */
+  u[0] = (inflate_huft *)Z_NULL;        /* just to keep compilers happy */
+  q = (inflate_huft *)Z_NULL;   /* ditto */
+  z = 0;                        /* ditto */
+
+  /* go through the bit lengths (k already is bits in shortest code) */
+  for (; k <= g; k++)
+  {
+    a = c[k];
+    while (a--)
+    {
+      /* here i is the Huffman code of length k bits for value *p */
+      /* make tables up to required level */
+      while (k > w + l)
+      {
+        h++;
+        w += l;                 /* previous table always l bits */
+
+        /* compute minimum size table less than or equal to l bits */
+        z = g - w;
+        z = z > (uInt)l ? l : z;        /* table size upper limit */
+        if ((f = 1 << (j = k - w)) > a + 1)     /* try a k-w bit table */
+        {                       /* too few codes for k-w bit table */
+          f -= a + 1;           /* deduct codes from patterns left */
+          xp = c + k;
+          if (j < z)
+            while (++j < z)     /* try smaller tables up to z bits */
+            {
+              if ((f <<= 1) <= *++xp)
+                break;          /* enough codes to use up j bits */
+              f -= *xp;         /* else deduct codes from patterns */
+            }
+        }
+        z = 1 << j;             /* table entries for j-bit table */
+
+        /* allocate new table */
+        if (*hn + z > MANY)     /* (note: doesn't matter for fixed) */
+          return Z_MEM_ERROR;   /* not enough memory */
+        u[h] = q = hp + *hn;
+        *hn += z;
+
+        /* connect to last table, if there is one */
+        if (h)
+        {
+          x[h] = i;             /* save pattern for backing up */
+          r.bits = (Byte)l;     /* bits to dump before this table */
+          r.exop = (Byte)j;     /* bits in this table */
+          j = i >> (w - l);
+          r.base = (uInt)(q - u[h-1] - j);   /* offset to this table */
+          u[h-1][j] = r;        /* connect to last table */
+        }
+        else
+          *t = q;               /* first table is returned result */
+      }
+
+      /* set up table entry in r */
+      r.bits = (Byte)(k - w);
+      if (p >= v + n)
+        r.exop = 128 + 64;      /* out of values--invalid code */
+      else if (*p < s)
+      {
+        r.exop = (Byte)(*p < 256 ? 0 : 32 + 64);     /* 256 is end-of-block */
+        r.base = *p++;          /* simple code is just the value */
+      }
+      else
+      {
+        r.exop = (Byte)(e[*p - s] + 16 + 64);/* non-simple--look up in lists */
+        r.base = d[*p++ - s];
+      }
+
+      /* fill code-like entries with r */
+      f = 1 << (k - w);
+      for (j = i >> w; j < z; j += f)
+        q[j] = r;
+
+      /* backwards increment the k-bit code i */
+      for (j = 1 << (k - 1); i & j; j >>= 1)
+        i ^= j;
+      i ^= j;
+
+      /* backup over finished tables */
+      mask = (1 << w) - 1;      /* needed on HP, cc -O bug */
+      while ((i & mask) != x[h])
+      {
+        h--;                    /* don't need to update q */
+        w -= l;
+        mask = (1 << w) - 1;
+      }
+    }
+  }
+
+
+  /* Return Z_BUF_ERROR if we were given an incomplete table */
+  return y != 0 && g != 1 ? Z_BUF_ERROR : Z_OK;
+}
+
+
+#ifndef __APPLE__
+int inflate_trees_bits(uInt *c, uInt *bb, inflate_huft * *tb, inflate_huft *hp, z_streamp z)
+//uInt *c;               /* 19 code lengths */
+//uInt *bb;              /* bits tree desired/actual depth */
+//inflate_huft * *tb; /* bits tree result */
+//inflate_huft *hp;       /* space for trees */
+//z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uInt *v;             /* work area for huft_build */
+
+  if ((v = (uInt*)ZALLOC(z, 19, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+  r = huft_build(c, 19, 19, (uInt*)Z_NULL, (uInt*)Z_NULL,
+                 tb, bb, hp, &hn, v);
+  if (r == Z_DATA_ERROR)
+    z->msg = (char*)"oversubscribed dynamic bit lengths tree";
+  else if (r == Z_BUF_ERROR || *bb == 0)
+  {
+    z->msg = (char*)"incomplete dynamic bit lengths tree";
+    r = Z_DATA_ERROR;
+  }
+  ZFREE(z, v);
+  return r;
+}
+#endif
+
+#ifndef __APPLE__
+int inflate_trees_dynamic(uInt nl, uInt nd, uInt *c, uInt *bl, uInt *bd, inflate_huft * *tl, inflate_huft * *td, inflate_huft *hp, z_streamp z)
+//uInt nl;                /* number of literal/length codes */
+//uInt nd;                /* number of distance codes */
+//uInt *c;               /* that many (total) code lengths */
+//uInt *bl;              /* literal desired/actual bit depth */
+//uInt *bd;              /* distance desired/actual bit depth */
+//inflate_huft * *tl; /* literal/length tree result */
+//inflate_huft * *td; /* distance tree result */
+//inflate_huft *hp;       /* space for trees */
+//z_streamp z;            /* for messages */
+{
+  int r;
+  uInt hn = 0;          /* hufts used in space */
+  uInt *v;             /* work area for huft_build */
+
+  /* allocate work area */
+  if ((v = (uInt*)ZALLOC(z, 288, sizeof(uInt))) == Z_NULL)
+    return Z_MEM_ERROR;
+
+  /* build literal/length tree */
+  r = huft_build(c, nl, 257, cplens, cplext, tl, bl, hp, &hn, v);
+  if (r != Z_OK || *bl == 0)
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed literal/length tree";
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"incomplete literal/length tree";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+  }
+
+  /* build distance tree */
+  r = huft_build(c + nl, nd, 0, cpdist, cpdext, td, bd, hp, &hn, v);
+  if (r != Z_OK || (*bd == 0 && nl > 257))
+  {
+    if (r == Z_DATA_ERROR)
+      z->msg = (char*)"oversubscribed distance tree";
+    else if (r == Z_BUF_ERROR) {
+#ifdef PKZIP_BUG_WORKAROUND
+      r = Z_OK;
+    }
+#else
+      z->msg = (char*)"incomplete distance tree";
+      r = Z_DATA_ERROR;
+    }
+    else if (r != Z_MEM_ERROR)
+    {
+      z->msg = (char*)"empty distance tree with lengths";
+      r = Z_DATA_ERROR;
+    }
+    ZFREE(z, v);
+    return r;
+#endif
+  }
+
+  /* done */
+  ZFREE(z, v);
+  return Z_OK;
+}
+#endif
+
+/* inffixed.h -- table for decoding fixed codes
+ * Generated automatically by the maketree.c program
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+static uInt fixed_bl = 9;
+static uInt fixed_bd = 5;
+static inflate_huft fixed_tl[] = {
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},192},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},160},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},224},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},144},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},208},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},176},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},240},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},200},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},168},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},232},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},152},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},216},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},184},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},248},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},196},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},164},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},228},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},148},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},212},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},180},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},244},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},204},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},172},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},236},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},156},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},220},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},188},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},252},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},194},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},162},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},226},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},146},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},210},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},178},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},242},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},202},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},170},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},234},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},154},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},218},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},186},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},250},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},198},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},166},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},230},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},150},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},214},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},182},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},246},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},206},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},174},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},238},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},158},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},222},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},190},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},254},
+    {{{96,7}},256}, {{{0,8}},80}, {{{0,8}},16}, {{{84,8}},115},
+    {{{82,7}},31}, {{{0,8}},112}, {{{0,8}},48}, {{{0,9}},193},
+    {{{80,7}},10}, {{{0,8}},96}, {{{0,8}},32}, {{{0,9}},161},
+    {{{0,8}},0}, {{{0,8}},128}, {{{0,8}},64}, {{{0,9}},225},
+    {{{80,7}},6}, {{{0,8}},88}, {{{0,8}},24}, {{{0,9}},145},
+    {{{83,7}},59}, {{{0,8}},120}, {{{0,8}},56}, {{{0,9}},209},
+    {{{81,7}},17}, {{{0,8}},104}, {{{0,8}},40}, {{{0,9}},177},
+    {{{0,8}},8}, {{{0,8}},136}, {{{0,8}},72}, {{{0,9}},241},
+    {{{80,7}},4}, {{{0,8}},84}, {{{0,8}},20}, {{{85,8}},227},
+    {{{83,7}},43}, {{{0,8}},116}, {{{0,8}},52}, {{{0,9}},201},
+    {{{81,7}},13}, {{{0,8}},100}, {{{0,8}},36}, {{{0,9}},169},
+    {{{0,8}},4}, {{{0,8}},132}, {{{0,8}},68}, {{{0,9}},233},
+    {{{80,7}},8}, {{{0,8}},92}, {{{0,8}},28}, {{{0,9}},153},
+    {{{84,7}},83}, {{{0,8}},124}, {{{0,8}},60}, {{{0,9}},217},
+    {{{82,7}},23}, {{{0,8}},108}, {{{0,8}},44}, {{{0,9}},185},
+    {{{0,8}},12}, {{{0,8}},140}, {{{0,8}},76}, {{{0,9}},249},
+    {{{80,7}},3}, {{{0,8}},82}, {{{0,8}},18}, {{{85,8}},163},
+    {{{83,7}},35}, {{{0,8}},114}, {{{0,8}},50}, {{{0,9}},197},
+    {{{81,7}},11}, {{{0,8}},98}, {{{0,8}},34}, {{{0,9}},165},
+    {{{0,8}},2}, {{{0,8}},130}, {{{0,8}},66}, {{{0,9}},229},
+    {{{80,7}},7}, {{{0,8}},90}, {{{0,8}},26}, {{{0,9}},149},
+    {{{84,7}},67}, {{{0,8}},122}, {{{0,8}},58}, {{{0,9}},213},
+    {{{82,7}},19}, {{{0,8}},106}, {{{0,8}},42}, {{{0,9}},181},
+    {{{0,8}},10}, {{{0,8}},138}, {{{0,8}},74}, {{{0,9}},245},
+    {{{80,7}},5}, {{{0,8}},86}, {{{0,8}},22}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},118}, {{{0,8}},54}, {{{0,9}},205},
+    {{{81,7}},15}, {{{0,8}},102}, {{{0,8}},38}, {{{0,9}},173},
+    {{{0,8}},6}, {{{0,8}},134}, {{{0,8}},70}, {{{0,9}},237},
+    {{{80,7}},9}, {{{0,8}},94}, {{{0,8}},30}, {{{0,9}},157},
+    {{{84,7}},99}, {{{0,8}},126}, {{{0,8}},62}, {{{0,9}},221},
+    {{{82,7}},27}, {{{0,8}},110}, {{{0,8}},46}, {{{0,9}},189},
+    {{{0,8}},14}, {{{0,8}},142}, {{{0,8}},78}, {{{0,9}},253},
+    {{{96,7}},256}, {{{0,8}},81}, {{{0,8}},17}, {{{85,8}},131},
+    {{{82,7}},31}, {{{0,8}},113}, {{{0,8}},49}, {{{0,9}},195},
+    {{{80,7}},10}, {{{0,8}},97}, {{{0,8}},33}, {{{0,9}},163},
+    {{{0,8}},1}, {{{0,8}},129}, {{{0,8}},65}, {{{0,9}},227},
+    {{{80,7}},6}, {{{0,8}},89}, {{{0,8}},25}, {{{0,9}},147},
+    {{{83,7}},59}, {{{0,8}},121}, {{{0,8}},57}, {{{0,9}},211},
+    {{{81,7}},17}, {{{0,8}},105}, {{{0,8}},41}, {{{0,9}},179},
+    {{{0,8}},9}, {{{0,8}},137}, {{{0,8}},73}, {{{0,9}},243},
+    {{{80,7}},4}, {{{0,8}},85}, {{{0,8}},21}, {{{80,8}},258},
+    {{{83,7}},43}, {{{0,8}},117}, {{{0,8}},53}, {{{0,9}},203},
+    {{{81,7}},13}, {{{0,8}},101}, {{{0,8}},37}, {{{0,9}},171},
+    {{{0,8}},5}, {{{0,8}},133}, {{{0,8}},69}, {{{0,9}},235},
+    {{{80,7}},8}, {{{0,8}},93}, {{{0,8}},29}, {{{0,9}},155},
+    {{{84,7}},83}, {{{0,8}},125}, {{{0,8}},61}, {{{0,9}},219},
+    {{{82,7}},23}, {{{0,8}},109}, {{{0,8}},45}, {{{0,9}},187},
+    {{{0,8}},13}, {{{0,8}},141}, {{{0,8}},77}, {{{0,9}},251},
+    {{{80,7}},3}, {{{0,8}},83}, {{{0,8}},19}, {{{85,8}},195},
+    {{{83,7}},35}, {{{0,8}},115}, {{{0,8}},51}, {{{0,9}},199},
+    {{{81,7}},11}, {{{0,8}},99}, {{{0,8}},35}, {{{0,9}},167},
+    {{{0,8}},3}, {{{0,8}},131}, {{{0,8}},67}, {{{0,9}},231},
+    {{{80,7}},7}, {{{0,8}},91}, {{{0,8}},27}, {{{0,9}},151},
+    {{{84,7}},67}, {{{0,8}},123}, {{{0,8}},59}, {{{0,9}},215},
+    {{{82,7}},19}, {{{0,8}},107}, {{{0,8}},43}, {{{0,9}},183},
+    {{{0,8}},11}, {{{0,8}},139}, {{{0,8}},75}, {{{0,9}},247},
+    {{{80,7}},5}, {{{0,8}},87}, {{{0,8}},23}, {{{192,8}},0},
+    {{{83,7}},51}, {{{0,8}},119}, {{{0,8}},55}, {{{0,9}},207},
+    {{{81,7}},15}, {{{0,8}},103}, {{{0,8}},39}, {{{0,9}},175},
+    {{{0,8}},7}, {{{0,8}},135}, {{{0,8}},71}, {{{0,9}},239},
+    {{{80,7}},9}, {{{0,8}},95}, {{{0,8}},31}, {{{0,9}},159},
+    {{{84,7}},99}, {{{0,8}},127}, {{{0,8}},63}, {{{0,9}},223},
+    {{{82,7}},27}, {{{0,8}},111}, {{{0,8}},47}, {{{0,9}},191},
+    {{{0,8}},15}, {{{0,8}},143}, {{{0,8}},79}, {{{0,9}},255}
+  };
+static inflate_huft fixed_td[] = {
+    {{{80,5}},1}, {{{87,5}},257}, {{{83,5}},17}, {{{91,5}},4097},
+    {{{81,5}},5}, {{{89,5}},1025}, {{{85,5}},65}, {{{93,5}},16385},
+    {{{80,5}},3}, {{{88,5}},513}, {{{84,5}},33}, {{{92,5}},8193},
+    {{{82,5}},9}, {{{90,5}},2049}, {{{86,5}},129}, {{{192,5}},24577},
+    {{{80,5}},2}, {{{87,5}},385}, {{{83,5}},25}, {{{91,5}},6145},
+    {{{81,5}},7}, {{{89,5}},1537}, {{{85,5}},97}, {{{93,5}},24577},
+    {{{80,5}},4}, {{{88,5}},769}, {{{84,5}},49}, {{{92,5}},12289},
+    {{{82,5}},13}, {{{90,5}},3073}, {{{86,5}},193}, {{{192,5}},24577}
+  };
+
+#ifndef __APPLE__
+int inflate_trees_fixed(uInt *bl, uInt *bd, inflate_huft * *tl, inflate_huft * *td, z_streamp z)
+//uInt *bl;               /* literal desired/actual bit depth */
+//uInt *bd;               /* distance desired/actual bit depth */
+//inflate_huft * *tl;  /* literal/length tree result */
+//inflate_huft * *td;  /* distance tree result */
+//z_streamp z;             /* for memory allocation */
+{
+  *bl = fixed_bl;
+  *bd = fixed_bd;
+  *tl = fixed_tl;
+  *td = fixed_td;
+  return Z_OK;
+}
+#endif
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+/* macros for bit input with no checking and for returning unused bytes */
+#define GRABBITS(j) {while(k<(j)){b|=((uLong)NEXTBYTE)<<k;k+=8;}}
+#define UNGRAB {c=z->avail_in-n;c=(k>>3)<c?k>>3:c;n+=c;p-=c;k-=c<<3;}
+
+/* Called with number of bytes left to write in window at least 258
+   (the maximum string length) and number of input bytes available
+   at least ten.  The ten bytes are six bytes for the longest length/
+   distance pair plus four bytes for overloading the bit buffer. */
+
+#ifndef __APPLE__
+int inflate_fast(uInt bl, uInt bd, inflate_huft *tl, inflate_huft *td, inflate_blocks_statef *s, z_streamp z)
+{
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Byte *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Byte *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  uInt ml;              /* mask for literal/length tree */
+  uInt md;              /* mask for distance tree */
+  uInt c;               /* bytes to copy */
+  uInt d;               /* distance back to copy from */
+  Byte *r;             /* copy source pointer */
+
+  /* load input, output, bit values */
+  LOAD
+
+  /* initialize masks */
+  ml = inflate_mask[bl];
+  md = inflate_mask[bd];
+
+  /* do until not enough input or output space for fast loop */
+  do {                          /* assume called with m >= 258 && n >= 10 */
+    /* get literal/length code */
+    GRABBITS(20)                /* max bits for literal/length code */
+    if ((e = (t = tl + ((uInt)b & ml))->exop) == 0)
+    {
+      DUMPBITS(t->bits)
+      Tracevv((t->base >= 0x20 && t->base < 0x7f ?
+                "inflate:         * literal '%c'\n" :
+                "inflate:         * literal 0x%02x\n", t->base));
+      *q++ = (Byte)t->base;
+      m--;
+      continue;
+    }
+    do {
+      DUMPBITS(t->bits)
+      if (e & 16)
+      {
+        /* get extra bits for length */
+        e &= 15;
+        c = t->base + ((uInt)b & inflate_mask[e]);
+        DUMPBITS(e)
+        Tracevv(("inflate:         * length %u\n", c));
+
+        /* decode distance base of block to copy */
+        GRABBITS(15);           /* max bits for distance code */
+        e = (t = td + ((uInt)b & md))->exop;
+        do {
+          DUMPBITS(t->bits)
+          if (e & 16)
+          {
+            /* get extra bits to add to distance base */
+            e &= 15;
+            GRABBITS(e)         /* get extra bits (up to 13) */
+            d = t->base + ((uInt)b & inflate_mask[e]);
+            DUMPBITS(e)
+            Tracevv(("inflate:         * distance %u\n", d));
+
+            /* do the copy */
+            m -= c;
+            if ((uInt)(q - s->window) >= d)     /* offset before dest */
+            {                                   /*  just copy */
+              r = q - d;
+              *q++ = *r++;  c--;        /* minimum count is three, */
+              *q++ = *r++;  c--;        /*  so unroll loop a little */
+            }
+            else                        /* else offset after destination */
+            {
+              e = d - (uInt)(q - s->window); /* bytes from offset to end */
+              r = s->end - e;           /* pointer to offset */
+              if (c > e)                /* if source crosses, */
+              {
+                c -= e;                 /* copy to end of window */
+                do {
+                  *q++ = *r++;
+                } while (--e);
+                r = s->window;          /* copy rest from start of window */
+              }
+            }
+            do {                        /* copy all or what's left */
+              *q++ = *r++;
+            } while (--c);
+            break;
+          }
+          else if ((e & 64) == 0)
+          {
+            t += t->base;
+            e = (t += ((uInt)b & inflate_mask[e]))->exop;
+          }
+          else
+          {
+            z->msg = (char*)"invalid distance code";
+            UNGRAB
+            UPDATE
+            return Z_DATA_ERROR;
+          }
+        } while (1);
+        break;
+      }
+      if ((e & 64) == 0)
+      {
+        t += t->base;
+        if ((e = (t += ((uInt)b & inflate_mask[e]))->exop) == 0)
+        {
+          DUMPBITS(t->bits)
+          Tracevv((t->base >= 0x20 && t->base < 0x7f ?
+                    "inflate:         * literal '%c'\n" :
+                    "inflate:         * literal 0x%02x\n", t->base));
+          *q++ = (Byte)t->base;
+          m--;
+          break;
+        }
+      }
+      else if (e & 32)
+      {
+        Tracevv(("inflate:         * end of block\n"));
+        UNGRAB
+        UPDATE
+        return Z_STREAM_END;
+      }
+      else
+      {
+        z->msg = (char*)"invalid literal/length code";
+        UNGRAB
+        UPDATE
+        return Z_DATA_ERROR;
+      }
+    } while (1);
+  } while (m >= 258 && n >= 10);
+
+  /* not enough input or output--restore pointers and return */
+  UNGRAB
+  UPDATE
+  return Z_OK;
+}
+#endif
+
+/* infcodes.c -- process literals and length/distance pairs
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* simplify the use of the inflate_huft type with some defines */
+#define exop word.what.Exop
+#define bits word.what.Bits
+
+typedef enum {        /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+      START,    /* x: set up for LEN */
+      LEN,      /* i: get length/literal/eob next */
+      LENEXT,   /* i: getting length extra (have base) */
+      DIST,     /* i: get distance next */
+      DISTEXT,  /* i: getting distance extra */
+      COPY,     /* o: copying bytes in window, waiting for space */
+      LIT,      /* o: got literal, waiting for output space */
+      WASH,     /* o: got eob, possibly still output waiting */
+      END,      /* x: got eob and all data flushed */
+      BADCODE}  /* x: got error */
+inflate_codes_mode;
+
+/* inflate codes private state */
+struct inflate_codes_state {
+
+  /* mode */
+  inflate_codes_mode mode;      /* current inflate_codes mode */
+
+  /* mode dependent information */
+  uInt len;
+  union {
+    struct {
+      inflate_huft *tree;       /* pointer into tree */
+      uInt need;                /* bits needed */
+    } code;             /* if LEN or DIST, where in tree */
+    uInt lit;           /* if LIT, literal */
+    struct {
+      uInt get;                 /* bits to get for extra */
+      uInt dist;                /* distance back to copy from */
+    } copy;             /* if EXT or COPY, where and how much */
+  } sub;                /* submode */
+
+  /* mode independent information */
+  Byte lbits;           /* ltree bits decoded per branch */
+  Byte dbits;           /* dtree bits decoder per branch */
+  inflate_huft *ltree;          /* literal/length/eob tree */
+  inflate_huft *dtree;          /* distance tree */
+
+};
+
+#ifndef __APPLE__
+inflate_codes_statef *inflate_codes_new(uInt bl, uInt bd, inflate_huft *tl, inflate_huft *td, z_streamp z)
+{
+  inflate_codes_statef *c;
+
+  if ((c = (inflate_codes_statef *)
+       ZALLOC(z,1,sizeof(struct inflate_codes_state))) != Z_NULL)
+  {
+    c->mode = START;
+    c->lbits = (Byte)bl;
+    c->dbits = (Byte)bd;
+    c->ltree = tl;
+    c->dtree = td;
+    Tracev(("inflate:       codes new\n"));
+  }
+  return c;
+}
+#endif
+
+#ifndef __APPLE__
+int inflate_codes(inflate_blocks_statef *s, z_streamp z, int r)
+{
+  uInt j;               /* temporary storage */
+  inflate_huft *t;      /* temporary pointer */
+  uInt e;               /* extra bits or operation */
+  uLong b;              /* bit buffer */
+  uInt k;               /* bits in bit buffer */
+  Byte *p;             /* input data pointer */
+  uInt n;               /* bytes available there */
+  Byte *q;             /* output window write pointer */
+  uInt m;               /* bytes to end of window or read pointer */
+  Byte *f;             /* pointer to copy strings from */
+  inflate_codes_statef *c = s->sub.decode.codes;  /* codes state */
+
+  /* copy input/output information to locals (UPDATE macro restores) */
+  LOAD
+
+  /* process input and output based on current state */
+  while (1) switch (c->mode)
+  {             /* waiting for "i:"=input, "o:"=output, "x:"=nothing */
+    case START:         /* x: set up for LEN */
+#ifndef SLOW
+      if (m >= 258 && n >= 10)
+      {
+        UPDATE
+        r = inflate_fast(c->lbits, c->dbits, c->ltree, c->dtree, s, z);
+        LOAD
+        if (r != Z_OK)
+        {
+          c->mode = r == Z_STREAM_END ? WASH : BADCODE;
+          break;
+        }
+      }
+#endif /* !SLOW */
+      c->sub.code.need = c->lbits;
+      c->sub.code.tree = c->ltree;
+      c->mode = LEN;
+    case LEN:           /* i: get length/literal/eob next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e == 0)               /* literal */
+      {
+        c->sub.lit = t->base;
+        Tracevv((t->base >= 0x20 && t->base < 0x7f ?
+                 "inflate:         literal '%c'\n" :
+                 "inflate:         literal 0x%02x\n", t->base));
+        c->mode = LIT;
+        break;
+      }
+      if (e & 16)               /* length */
+      {
+        c->sub.copy.get = e & 15;
+        c->len = t->base;
+        c->mode = LENEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      if (e & 32)               /* end of block */
+      {
+        Tracevv(("inflate:         end of block\n"));
+        c->mode = WASH;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid literal/length code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case LENEXT:        /* i: getting length extra (have base) */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->len += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      c->sub.code.need = c->dbits;
+      c->sub.code.tree = c->dtree;
+      Tracevv(("inflate:         length %u\n", c->len));
+      c->mode = DIST;
+    case DIST:          /* i: get distance next */
+      j = c->sub.code.need;
+      NEEDBITS(j)
+      t = c->sub.code.tree + ((uInt)b & inflate_mask[j]);
+      DUMPBITS(t->bits)
+      e = (uInt)(t->exop);
+      if (e & 16)               /* distance */
+      {
+        c->sub.copy.get = e & 15;
+        c->sub.copy.dist = t->base;
+        c->mode = DISTEXT;
+        break;
+      }
+      if ((e & 64) == 0)        /* next table */
+      {
+        c->sub.code.need = e;
+        c->sub.code.tree = t + t->base;
+        break;
+      }
+      c->mode = BADCODE;        /* invalid code */
+      z->msg = (char*)"invalid distance code";
+      r = Z_DATA_ERROR;
+      LEAVE
+    case DISTEXT:       /* i: getting distance extra */
+      j = c->sub.copy.get;
+      NEEDBITS(j)
+      c->sub.copy.dist += (uInt)b & inflate_mask[j];
+      DUMPBITS(j)
+      Tracevv(("inflate:         distance %u\n", c->sub.copy.dist));
+      c->mode = COPY;
+    case COPY:          /* o: copying bytes in window, waiting for space */
+#ifndef __TURBOC__ /* Turbo C bug for following expression */
+      f = (uInt)(q - s->window) < c->sub.copy.dist ?
+          s->end - (c->sub.copy.dist - (q - s->window)) :
+          q - c->sub.copy.dist;
+#else
+      f = q - c->sub.copy.dist;
+      if ((uInt)(q - s->window) < c->sub.copy.dist)
+        f = s->end - (c->sub.copy.dist - (uInt)(q - s->window));
+#endif
+      while (c->len)
+      {
+        NEEDOUT
+        OUTBYTE(*f++)
+        if (f == s->end)
+          f = s->window;
+        c->len--;
+      }
+      c->mode = START;
+      break;
+    case LIT:           /* o: got literal, waiting for output space */
+      NEEDOUT
+      OUTBYTE(c->sub.lit)
+      c->mode = START;
+      break;
+    case WASH:          /* o: got eob, possibly more output */
+      if (k > 7)        /* return unused byte, if any */
+      {
+        Assert(k < 16, "inflate_codes grabbed too many bytes")
+        k -= 8;
+        n++;
+        p--;            /* can always return one */
+      }
+      FLUSH
+      if (s->read != s->write)
+        LEAVE
+      c->mode = END;
+    case END:
+      r = Z_STREAM_END;
+      LEAVE
+    case BADCODE:       /* x: got error */
+      r = Z_DATA_ERROR;
+      LEAVE
+    default:
+      r = Z_STREAM_ERROR;
+      LEAVE
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+#endif
+
+#ifndef __APPLE__
+void inflate_codes_free(inflate_codes_statef *c, z_streamp z)
+{
+  ZFREE(z, c);
+  Tracev(("inflate:       codes free\n"));
+}
+#endif
+
+/* adler32.c -- compute the Adler-32 checksum of a data stream
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+#define BASE 65521L /* largest prime smaller than 65536 */
+#define NMAX 5552
+/* NMAX is the largest n such that 255n(n+1)/2 + (n+1)(BASE-1) <= 2^32-1 */
+
+#undef DO1
+#undef DO2
+#undef DO4
+#undef DO8
+
+#define DO1(buf,i)  {s1 += buf[i]; s2 += s1;}
+#define DO2(buf,i)  DO1(buf,i); DO1(buf,i+1);
+#define DO4(buf,i)  DO2(buf,i); DO2(buf,i+2);
+#define DO8(buf,i)  DO4(buf,i); DO4(buf,i+4);
+#define DO16(buf)   DO8(buf,0); DO8(buf,8);
+
+/* ========================================================================= */
+#ifndef __APPLE__
+uLong adler32(uLong adler, const Byte *buf, uInt len)
+{
+    unsigned long s1 = adler & 0xffff;
+    unsigned long s2 = (adler >> 16) & 0xffff;
+    int k;
+
+    if (buf == Z_NULL) return 1L;
+
+    while (len > 0) {
+        k = len < NMAX ? len : NMAX;
+        len -= k;
+        while (k >= 16) {
+            DO16(buf);
+	    buf += 16;
+            k -= 16;
+        }
+        if (k != 0) do {
+            s1 += *buf++;
+	    s2 += s1;
+        } while (--k);
+        s1 %= BASE;
+        s2 %= BASE;
+    }
+    return (s2 << 16) | s1;
+}
+#endif
+
+
+/* infblock.h -- header to use infblock.c
+ * Copyright (C) 1995-1998 Mark Adler
+ * For conditions of distribution and use, see copyright notice in zlib.h 
+ */
+
+/* WARNING: this file should *not* be used by applications. It is
+   part of the implementation of the compression library and is
+   subject to change. Applications should only use zlib.h.
+ */
+
+extern inflate_blocks_statef * inflate_blocks_new OF((
+    z_streamp z,
+    check_func c,               /* check function */
+    uInt w));                   /* window size */
+
+extern int inflate_blocks OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    int));                      /* initial return code */
+
+extern void inflate_blocks_reset OF((
+    inflate_blocks_statef *,
+    z_streamp ,
+    uLong *));                  /* check value on output */
+
+extern int inflate_blocks_free OF((
+    inflate_blocks_statef *,
+    z_streamp));
+
+extern void inflate_set_dictionary OF((
+    inflate_blocks_statef *s,
+    const Byte *d,  /* dictionary */
+    uInt  n));       /* dictionary length */
+
+extern int inflate_blocks_sync_point OF((
+    inflate_blocks_statef *s));
+
+typedef enum {
+      imMETHOD,   /* waiting for method byte */
+      imFLAG,     /* waiting for flag byte */
+      imDICT4,    /* four dictionary check bytes to go */
+      imDICT3,    /* three dictionary check bytes to go */
+      imDICT2,    /* two dictionary check bytes to go */
+      imDICT1,    /* one dictionary check byte to go */
+      imDICT0,    /* waiting for inflateSetDictionary */
+      imBLOCKS,   /* decompressing blocks */
+      imCHECK4,   /* four check bytes to go */
+      imCHECK3,   /* three check bytes to go */
+      imCHECK2,   /* two check bytes to go */
+      imCHECK1,   /* one check byte to go */
+      imDONE,     /* finished check, done */
+      imBAD}      /* got an error--stay here */
+inflate_mode;
+
+/* inflate private state */
+struct internal_state {
+
+  /* mode */
+  inflate_mode  mode;   /* current inflate mode */
+
+  /* mode dependent information */
+  union {
+    uInt method;        /* if FLAGS, method byte */
+    struct {
+      uLong was;                /* computed check value */
+      uLong need;               /* stream check value */
+    } check;            /* if CHECK, check values to compare */
+    uInt marker;        /* if BAD, inflateSync's marker bytes count */
+  } sub;        /* submode */
+
+  /* mode independent information */
+  int  nowrap;          /* flag for no wrapper */
+  uInt wbits;           /* log2(window size)  (8..15, defaults to 15) */
+  inflate_blocks_statef 
+    *blocks;            /* current inflate_blocks state */
+
+};
+
+
+#ifndef __APPLE__
+int inflateReset(z_streamp z)
+{
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->total_in = z->total_out = 0;
+  z->msg = Z_NULL;
+  z->state->mode = z->state->nowrap ? imBLOCKS : imMETHOD;
+  inflate_blocks_reset(z->state->blocks, z, Z_NULL);
+  Tracev(("inflate: reset\n"));
+  return Z_OK;
+}
+#endif
+
+#ifndef __APPLE__
+int inflateEnd(z_streamp z)
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->zfree == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->blocks != Z_NULL)
+    inflate_blocks_free(z->state->blocks, z);
+  ZFREE(z, z->state);
+  z->state = Z_NULL;
+  Tracev(("inflate: end\n"));
+  return Z_OK;
+}
+#endif
+
+#ifndef __APPLE__
+int inflateInit2_(z_streamp z, int w, const char *version, int stream_size)
+{
+  if (version == Z_NULL || version[0] != ZLIB_VERSION[0] ||
+      stream_size != sizeof(z_stream))
+      return Z_VERSION_ERROR;
+
+  /* initialize state */
+  if (z == Z_NULL)
+    return Z_STREAM_ERROR;
+  z->msg = Z_NULL;
+  if (z->zalloc == Z_NULL)
+  {
+    z->zalloc = (void *(*)(void *, unsigned, unsigned))zcalloc;
+    z->opaque = (voidp)0;
+  }
+  if (z->zfree == Z_NULL) z->zfree = (void (*)(void *, void *))zcfree;
+  if ((z->state = (struct internal_state *)
+       ZALLOC(z,1,sizeof(struct internal_state))) == Z_NULL)
+    return Z_MEM_ERROR;
+  z->state->blocks = Z_NULL;
+
+  /* handle undocumented nowrap option (no zlib header or check) */
+  z->state->nowrap = 0;
+  if (w < 0)
+  {
+    w = - w;
+    z->state->nowrap = 1;
+  }
+
+  /* set window size */
+  if (w < 8 || w > 15)
+  {
+    inflateEnd(z);
+    return Z_STREAM_ERROR;
+  }
+  z->state->wbits = (uInt)w;
+
+  /* create inflate_blocks state */
+  if ((z->state->blocks =
+      inflate_blocks_new(z, z->state->nowrap ? Z_NULL : adler32, (uInt)1 << w))
+      == Z_NULL)
+  {
+    inflateEnd(z);
+    return Z_MEM_ERROR;
+  }
+  Tracev(("inflate: allocated\n"));
+
+  /* reset state */
+  inflateReset(z);
+  return Z_OK;
+}
+#endif
+
+#ifndef __APPLE__
+int inflateInit_(z_streamp z, const char *version, int stream_size)
+{
+  return inflateInit2_(z, DEF_WBITS, version, stream_size);
+}
+#endif
+
+#define iNEEDBYTE {if(z->avail_in==0)return r;r=f;}
+#define iNEXTBYTE (z->avail_in--,z->total_in++,*z->next_in++)
+
+#ifndef __APPLE__
+int inflate(z_streamp z, int f)
+{
+  int r;
+  uInt b;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->next_in == Z_NULL)
+    return Z_STREAM_ERROR;
+  f = f == Z_FINISH ? Z_BUF_ERROR : Z_OK;
+  r = Z_BUF_ERROR;
+  while (1) switch (z->state->mode)
+  {
+    case imMETHOD:
+      iNEEDBYTE
+      if (((z->state->sub.method = iNEXTBYTE) & 0xf) != Z_DEFLATED)
+      {
+        z->state->mode = imBAD;
+        z->msg = (char*)"unknown compression method";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      if ((z->state->sub.method >> 4) + 8 > z->state->wbits)
+      {
+        z->state->mode = imBAD;
+        z->msg = (char*)"invalid window size";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      z->state->mode = imFLAG;
+    case imFLAG:
+      iNEEDBYTE
+      b = iNEXTBYTE;
+      if (((z->state->sub.method << 8) + b) % 31)
+      {
+        z->state->mode = imBAD;
+        z->msg = (char*)"incorrect header check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev(("inflate: zlib header ok\n"));
+      if (!(b & PRESET_DICT))
+      {
+        z->state->mode = imBLOCKS;
+        break;
+      }
+      z->state->mode = imDICT4;
+    case imDICT4:
+      iNEEDBYTE
+      z->state->sub.check.need = (uLong)iNEXTBYTE << 24;
+      z->state->mode = imDICT3;
+    case imDICT3:
+      iNEEDBYTE
+      z->state->sub.check.need += (uLong)iNEXTBYTE << 16;
+      z->state->mode = imDICT2;
+    case imDICT2:
+      iNEEDBYTE
+      z->state->sub.check.need += (uLong)iNEXTBYTE << 8;
+      z->state->mode = imDICT1;
+    case imDICT1:
+      iNEEDBYTE
+      z->state->sub.check.need += (uLong)iNEXTBYTE;
+      z->adler = z->state->sub.check.need;
+      z->state->mode = imDICT0;
+      return Z_NEED_DICT;
+    case imDICT0:
+      z->state->mode = imBAD;
+      z->msg = (char*)"need dictionary";
+      z->state->sub.marker = 0;       /* can try inflateSync */
+      return Z_STREAM_ERROR;
+    case imBLOCKS:
+      r = inflate_blocks(z->state->blocks, z, r);
+      if (r == Z_DATA_ERROR)
+      {
+        z->state->mode = imBAD;
+        z->state->sub.marker = 0;       /* can try inflateSync */
+        break;
+      }
+      if (r == Z_OK)
+        r = f;
+      if (r != Z_STREAM_END)
+        return r;
+      r = f;
+      inflate_blocks_reset(z->state->blocks, z, &z->state->sub.check.was);
+      if (z->state->nowrap)
+      {
+        z->state->mode = imDONE;
+        break;
+      }
+      z->state->mode = imCHECK4;
+    case imCHECK4:
+      iNEEDBYTE
+      z->state->sub.check.need = (uLong)iNEXTBYTE << 24;
+      z->state->mode = imCHECK3;
+    case imCHECK3:
+      iNEEDBYTE
+      z->state->sub.check.need += (uLong)iNEXTBYTE << 16;
+      z->state->mode = imCHECK2;
+    case imCHECK2:
+      iNEEDBYTE
+      z->state->sub.check.need += (uLong)iNEXTBYTE << 8;
+      z->state->mode = imCHECK1;
+    case imCHECK1:
+      iNEEDBYTE
+      z->state->sub.check.need += (uLong)iNEXTBYTE;
+
+      if (z->state->sub.check.was != z->state->sub.check.need)
+      {
+        z->state->mode = imBAD;
+        z->msg = (char*)"incorrect data check";
+        z->state->sub.marker = 5;       /* can't try inflateSync */
+        break;
+      }
+      Tracev(("inflate: zlib check ok\n"));
+      z->state->mode = imDONE;
+    case imDONE:
+      return Z_STREAM_END;
+    case imBAD:
+      return Z_DATA_ERROR;
+    default:
+      return Z_STREAM_ERROR;
+  }
+#ifdef NEED_DUMMY_RETURN
+  return Z_STREAM_ERROR;  /* Some dumb compilers complain without this */
+#endif
+}
+#endif
+
+#ifndef __APPLE__
+int inflateSetDictionary(z_streamp z, const Byte *dictionary, uInt dictLength)
+{
+  uInt length = dictLength;
+
+  if (z == Z_NULL || z->state == Z_NULL || z->state->mode != imDICT0)
+    return Z_STREAM_ERROR;
+
+  if (adler32(1L, dictionary, dictLength) != z->adler) return Z_DATA_ERROR;
+  z->adler = 1L;
+
+  if (length >= ((uInt)1<<z->state->wbits))
+  {
+    length = (1<<z->state->wbits)-1;
+    dictionary += dictLength - length;
+  }
+  inflate_set_dictionary(z->state->blocks, dictionary, length);
+  z->state->mode = imBLOCKS;
+  return Z_OK;
+}
+#endif
+
+#ifndef __APPLE__
+int inflateSync(z_streamp z)
+{
+  uInt n;       /* number of bytes to look at */
+  Byte *p;     /* pointer to bytes */
+  uInt m;       /* number of marker bytes found in a row */
+  uLong r, w;   /* temporaries to save total_in and total_out */
+
+  /* set up */
+  if (z == Z_NULL || z->state == Z_NULL)
+    return Z_STREAM_ERROR;
+  if (z->state->mode != imBAD)
+  {
+    z->state->mode = imBAD;
+    z->state->sub.marker = 0;
+  }
+  if ((n = z->avail_in) == 0)
+    return Z_BUF_ERROR;
+  p = z->next_in;
+  m = z->state->sub.marker;
+
+  /* search */
+  while (n && m < 4)
+  {
+    static const Byte mark[4] = {0, 0, 0xff, 0xff};
+    if (*p == mark[m])
+      m++;
+    else if (*p)
+      m = 0;
+    else
+      m = 4 - m;
+    p++, n--;
+  }
+
+  /* restore */
+  z->total_in += p - z->next_in;
+  z->next_in = p;
+  z->avail_in = n;
+  z->state->sub.marker = m;
+
+  /* return no joy or set up to restart on a new block */
+  if (m != 4)
+    return Z_DATA_ERROR;
+  r = z->total_in;  w = z->total_out;
+  inflateReset(z);
+  z->total_in = r;  z->total_out = w;
+  z->state->mode = imBLOCKS;
+  return Z_OK;
+}
+#endif
+
+/* Returns true if inflate is currently at the end of a block generated
+ * by Z_SYNC_FLUSH or Z_FULL_FLUSH. This function is used by one PPP
+ * implementation to provide an additional safety check. PPP uses Z_SYNC_FLUSH
+ * but removes the length bytes of the resulting empty stored block. When
+ * decompressing, PPP checks that at the end of input packet, inflate is
+ * waiting for these length bytes.
+ */
+#ifndef __APPLE__
+int inflateSyncPoint(z_streamp z)
+{
+  if (z == Z_NULL || z->state == Z_NULL || z->state->blocks == Z_NULL)
+    return Z_STREAM_ERROR;
+  return inflate_blocks_sync_point(z->state->blocks);
+}
+#endif
+
+#ifndef __APPLE__
+voidp zcalloc (voidp opaque, unsigned items, unsigned size)
+{
+    if (opaque) items += size - size; /* make compiler happy */
+    return (voidp)safe_malloc(items*size);
+}
+
+void  zcfree (voidp opaque, voidp ptr)
+{
+    free(ptr);
+    if (opaque) return; /* make compiler happy */
+}
+#endif
diff --git a/tools/quake3/common/unzip.h b/tools/quake3/common/unzip.h
index ddb7820a..d2ba6532 100644
--- a/tools/quake3/common/unzip.h
+++ b/tools/quake3/common/unzip.h
@@ -1,321 +1,321 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-
-#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
-/* like the STRICT of WIN32, we define a pointer that cannot be converted
-    from (void*) without cast */
-typedef struct TagunzFile__ { int unused; } unzFile__; 
-typedef unzFile__ *unzFile;
-#else
-typedef void* unzFile;
-#endif
-
-
-/* tm_unz contain date/time info */
-typedef struct tm_unz_s 
-{
-	unsigned int tm_sec;            /* seconds after the minute - [0,59] */
-	unsigned int tm_min;            /* minutes after the hour - [0,59] */
-	unsigned int tm_hour;           /* hours since midnight - [0,23] */
-	unsigned int tm_mday;           /* day of the month - [1,31] */
-	unsigned int tm_mon;            /* months since January - [0,11] */
-	unsigned int tm_year;           /* years - [1980..2044] */
-} tm_unz;
-
-/* unz_global_info structure contain global data about the ZIPfile
-   These data comes from the end of central dir */
-typedef struct unz_global_info_s
-{
-	unsigned long number_entry;         /* total number of entries in the central dir on this disk */
-	unsigned long size_comment;         /* size of the global comment of the zipfile */
-} unz_global_info;
-
-
-/* unz_file_info contain information about a file in the zipfile */
-typedef struct unz_file_info_s
-{
-    unsigned long version;              /* version made by                 2 unsigned chars */
-    unsigned long version_needed;       /* version needed to extract       2 unsigned chars */
-    unsigned long flag;                 /* general purpose bit flag        2 unsigned chars */
-    unsigned long compression_method;   /* compression method              2 unsigned chars */
-    unsigned long dosDate;              /* last mod file date in Dos fmt   4 unsigned chars */
-    unsigned long crc;                  /* crc-32                          4 unsigned chars */
-    unsigned long compressed_size;      /* compressed size                 4 unsigned chars */ 
-    unsigned long uncompressed_size;    /* uncompressed size               4 unsigned chars */ 
-    unsigned long size_filename;        /* filename length                 2 unsigned chars */
-    unsigned long size_file_extra;      /* extra field length              2 unsigned chars */
-    unsigned long size_file_comment;    /* file comment length             2 unsigned chars */
-
-    unsigned long disk_num_start;       /* disk number start               2 unsigned chars */
-    unsigned long internal_fa;          /* internal file attributes        2 unsigned chars */
-    unsigned long external_fa;          /* external file attributes        4 unsigned chars */
-
-    tm_unz tmu_date;
-} unz_file_info;
-
-/* unz_file_info_interntal contain internal info about a file in zipfile*/
-typedef struct unz_file_info_internal_s
-{
-    unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
-} unz_file_info_internal;
-
-typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
-typedef void   (*free_func) (void* opaque, void* address);
-
-struct internal_state;
-
-typedef struct z_stream_s {
-    unsigned char    *next_in;  /* next input unsigned char */
-    unsigned int     avail_in;  /* number of unsigned chars available at next_in */
-    unsigned long    total_in;  /* total nb of input unsigned chars read so */
-
-    unsigned char    *next_out; /* next output unsigned char should be put there */
-    unsigned int     avail_out; /* remaining free space at next_out */
-    unsigned long    total_out; /* total nb of unsigned chars output so */
-
-    char     *msg;      /* last error message, NULL if no error */
-    struct internal_state *state; /* not visible by applications */
-
-    alloc_func zalloc;  /* used to allocate the internal state */
-    free_func  zfree;   /* used to free the internal state */
-    unsigned char*     opaque;  /* private data object passed to zalloc and zfree */
-
-    int     data_type;  /* best guess about the data type: ascii or binary */
-    unsigned long   adler;      /* adler32 value of the uncompressed data */
-    unsigned long   reserved;   /* reserved for future use */
-} z_stream;
-
-typedef z_stream *z_streamp;
-
-
-/* file_in_zip_read_info_s contain internal information about a file in zipfile,
-    when reading and decompress it */
-typedef struct
-{
-	char  *read_buffer;         /* internal buffer for compressed data */
-	z_stream stream;            /* zLib stream structure for inflate */
-
-	unsigned long pos_in_zipfile;       /* position in unsigned char on the zipfile, for fseek*/
-	unsigned long stream_initialised;   /* flag set if stream structure is initialised*/
-
-	unsigned long offset_local_extrafield;/* offset of the static extra field */
-	unsigned int  size_local_extrafield;/* size of the static extra field */
-	unsigned long pos_local_extrafield;   /* position in the static extra field in read*/
-
-	unsigned long crc32;                /* crc32 of all data uncompressed */
-	unsigned long crc32_wait;           /* crc32 we must obtain after decompress all */
-	unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
-	unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
-	FILE* file;                 /* io structore of the zipfile */
-	unsigned long compression_method;   /* compression method (0==store) */
-	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
-} file_in_zip_read_info_s;
-
-
-/* unz_s contain internal information about the zipfile
-*/
-typedef struct
-{
-	FILE* file;                 /* io structore of the zipfile */
-	unz_global_info gi;       /* public global information */
-	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
-	unsigned long num_file;             /* number of the current file in the zipfile*/
-	unsigned long pos_in_central_dir;   /* pos of the current file in the central dir*/
-	unsigned long current_file_ok;      /* flag about the usability of the current file*/
-	unsigned long central_pos;          /* position of the beginning of the central dir*/
-
-	unsigned long size_central_dir;     /* size of the central directory  */
-	unsigned long offset_central_dir;   /* offset of start of central directory with
-								   respect to the starting disk number */
-
-	unz_file_info cur_file_info; /* public info about the current file in zip*/
-	unz_file_info_internal cur_file_info_internal; /* private info about it*/
-    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
-	                                    file if we are decompressing it */
-} unz_s;
-
-#define UNZ_OK                                  (0)
-#define UNZ_END_OF_LIST_OF_FILE (-100)
-#define UNZ_ERRNO               (Z_ERRNO)
-#define UNZ_EOF                 (0)
-#define UNZ_PARAMERROR                  (-102)
-#define UNZ_BADZIPFILE                  (-103)
-#define UNZ_INTERNALERROR               (-104)
-#define UNZ_CRCERROR                    (-105)
-
-#define UNZ_CASESENSITIVE		1
-#define UNZ_NOTCASESENSITIVE	2
-#define UNZ_OSDEFAULTCASE		0
-
-extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
-
-/*
-   Compare two filename (fileName1,fileName2).
-   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
-   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
-								or strcasecmp)
-   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
-	(like 1 on Unix, 2 on Windows)
-*/
-
-extern unzFile unzOpen (const char *path);
-extern unzFile unzReOpen (const char* path, unzFile file);
-
-/*
-  Open a Zip file. path contain the full pathname (by example,
-     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
-	 "zlib/zlib111.zip".
-	 If the zipfile cannot be opened (file don't exist or in not valid), the
-	   return value is NULL.
-     Else, the return value is a unzFile Handle, usable with other function
-	   of this unzip package.
-*/
-
-extern int unzClose (unzFile file);
-
-/*
-  Close a ZipFile opened with unzipOpen.
-  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
-    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
-  return UNZ_OK if there is no problem. */
-
-extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
-
-/*
-  Write info about the ZipFile in the *pglobal_info structure.
-  No preparation of the structure is needed
-  return UNZ_OK if there is no problem. */
-
-
-extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
-
-/*
-  Get the global comment string of the ZipFile, in the szComment buffer.
-  uSizeBuf is the size of the szComment buffer.
-  return the number of unsigned char copied or an error code <0
-*/
-
-
-/***************************************************************************/
-/* Unzip package allow you browse the directory of the zipfile */
-
-extern int unzGoToFirstFile (unzFile file);
-
-/*
-  Set the current file of the zipfile to the first file.
-  return UNZ_OK if there is no problem
-*/
-
-extern int unzGoToNextFile (unzFile file);
-
-/*
-  Set the current file of the zipfile to the next file.
-  return UNZ_OK if there is no problem
-  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
-*/
-
-extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
-
-/*
-  Try locate the file szFileName in the zipfile.
-  For the iCaseSensitivity signification, see unzStringFileNameCompare
-
-  return value :
-  UNZ_OK if the file is found. It becomes the current file.
-  UNZ_END_OF_LIST_OF_FILE if the file is not found
-*/
-
-
-extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
-
-/*
-  Get Info about the current file
-  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
-	    the current file
-  if szFileName!=NULL, the filemane string will be copied in szFileName
-			(fileNameBufferSize is the size of the buffer)
-  if extraField!=NULL, the extra field information will be copied in extraField
-			(extraFieldBufferSize is the size of the buffer).
-			This is the Central-header version of the extra field
-  if szComment!=NULL, the comment string of the file will be copied in szComment
-			(commentBufferSize is the size of the buffer)
-*/
-
-/***************************************************************************/
-/* for reading the content of the current zipfile, you can open it, read data
-   from it, and close it (you can close it before reading all the file)
-   */
-
-extern int unzOpenCurrentFile (unzFile file);
-
-/*
-  Open for reading data the current file in the zipfile.
-  If there is no error, the return value is UNZ_OK.
-*/
-
-extern int unzCloseCurrentFile (unzFile file);
-
-/*
-  Close the file in zip opened with unzOpenCurrentFile
-  Return UNZ_CRCERROR if all the file was read but the CRC is not good
-*/
-
-												
-extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
-
-/*
-  Read unsigned chars from the current file (opened by unzOpenCurrentFile)
-  buf contain buffer where data must be copied
-  len the size of buf.
-
-  return the number of unsigned char copied if somes unsigned chars are copied
-  return 0 if the end of file was reached
-  return <0 with error code if there is an error
-    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
-*/
-
-extern long unztell(unzFile file);
-
-/*
-  Give the current position in uncompressed data
-*/
-
-extern int unzeof (unzFile file);
-
-/*
-  return 1 if the end of file was reached, 0 elsewhere 
-*/
-
-extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
-
-/*
-  Read extra field from the current file (opened by unzOpenCurrentFile)
-  This is the local-header version of the extra field (sometimes, there is
-    more info in the local-header version than in the central-header)
-
-  if buf==NULL, it return the size of the local extra field
-
-  if buf!=NULL, len is the size of the buffer, the extra header is copied in
-	buf.
-  the return value is the number of unsigned chars copied in buf, or (if <0) 
-	the error code
-*/
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+
+#if defined(STRICTUNZIP) || defined(STRICTZIPUNZIP)
+/* like the STRICT of WIN32, we define a pointer that cannot be converted
+    from (void*) without cast */
+typedef struct TagunzFile__ { int unused; } unzFile__; 
+typedef unzFile__ *unzFile;
+#else
+typedef void* unzFile;
+#endif
+
+
+/* tm_unz contain date/time info */
+typedef struct tm_unz_s 
+{
+	unsigned int tm_sec;            /* seconds after the minute - [0,59] */
+	unsigned int tm_min;            /* minutes after the hour - [0,59] */
+	unsigned int tm_hour;           /* hours since midnight - [0,23] */
+	unsigned int tm_mday;           /* day of the month - [1,31] */
+	unsigned int tm_mon;            /* months since January - [0,11] */
+	unsigned int tm_year;           /* years - [1980..2044] */
+} tm_unz;
+
+/* unz_global_info structure contain global data about the ZIPfile
+   These data comes from the end of central dir */
+typedef struct unz_global_info_s
+{
+	unsigned long number_entry;         /* total number of entries in the central dir on this disk */
+	unsigned long size_comment;         /* size of the global comment of the zipfile */
+} unz_global_info;
+
+
+/* unz_file_info contain information about a file in the zipfile */
+typedef struct unz_file_info_s
+{
+    unsigned long version;              /* version made by                 2 unsigned chars */
+    unsigned long version_needed;       /* version needed to extract       2 unsigned chars */
+    unsigned long flag;                 /* general purpose bit flag        2 unsigned chars */
+    unsigned long compression_method;   /* compression method              2 unsigned chars */
+    unsigned long dosDate;              /* last mod file date in Dos fmt   4 unsigned chars */
+    unsigned long crc;                  /* crc-32                          4 unsigned chars */
+    unsigned long compressed_size;      /* compressed size                 4 unsigned chars */ 
+    unsigned long uncompressed_size;    /* uncompressed size               4 unsigned chars */ 
+    unsigned long size_filename;        /* filename length                 2 unsigned chars */
+    unsigned long size_file_extra;      /* extra field length              2 unsigned chars */
+    unsigned long size_file_comment;    /* file comment length             2 unsigned chars */
+
+    unsigned long disk_num_start;       /* disk number start               2 unsigned chars */
+    unsigned long internal_fa;          /* internal file attributes        2 unsigned chars */
+    unsigned long external_fa;          /* external file attributes        4 unsigned chars */
+
+    tm_unz tmu_date;
+} unz_file_info;
+
+/* unz_file_info_interntal contain internal info about a file in zipfile*/
+typedef struct unz_file_info_internal_s
+{
+    unsigned long offset_curfile;/* relative offset of static header 4 unsigned chars */
+} unz_file_info_internal;
+
+typedef void* (*alloc_func) (void* opaque, unsigned int items, unsigned int size);
+typedef void   (*free_func) (void* opaque, void* address);
+
+struct internal_state;
+
+typedef struct z_stream_s {
+    unsigned char    *next_in;  /* next input unsigned char */
+    unsigned int     avail_in;  /* number of unsigned chars available at next_in */
+    unsigned long    total_in;  /* total nb of input unsigned chars read so */
+
+    unsigned char    *next_out; /* next output unsigned char should be put there */
+    unsigned int     avail_out; /* remaining free space at next_out */
+    unsigned long    total_out; /* total nb of unsigned chars output so */
+
+    char     *msg;      /* last error message, NULL if no error */
+    struct internal_state *state; /* not visible by applications */
+
+    alloc_func zalloc;  /* used to allocate the internal state */
+    free_func  zfree;   /* used to free the internal state */
+    unsigned char*     opaque;  /* private data object passed to zalloc and zfree */
+
+    int     data_type;  /* best guess about the data type: ascii or binary */
+    unsigned long   adler;      /* adler32 value of the uncompressed data */
+    unsigned long   reserved;   /* reserved for future use */
+} z_stream;
+
+typedef z_stream *z_streamp;
+
+
+/* file_in_zip_read_info_s contain internal information about a file in zipfile,
+    when reading and decompress it */
+typedef struct
+{
+	char  *read_buffer;         /* internal buffer for compressed data */
+	z_stream stream;            /* zLib stream structure for inflate */
+
+	unsigned long pos_in_zipfile;       /* position in unsigned char on the zipfile, for fseek*/
+	unsigned long stream_initialised;   /* flag set if stream structure is initialised*/
+
+	unsigned long offset_local_extrafield;/* offset of the static extra field */
+	unsigned int  size_local_extrafield;/* size of the static extra field */
+	unsigned long pos_local_extrafield;   /* position in the static extra field in read*/
+
+	unsigned long crc32;                /* crc32 of all data uncompressed */
+	unsigned long crc32_wait;           /* crc32 we must obtain after decompress all */
+	unsigned long rest_read_compressed; /* number of unsigned char to be decompressed */
+	unsigned long rest_read_uncompressed;/*number of unsigned char to be obtained after decomp*/
+	FILE* file;                 /* io structore of the zipfile */
+	unsigned long compression_method;   /* compression method (0==store) */
+	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
+} file_in_zip_read_info_s;
+
+
+/* unz_s contain internal information about the zipfile
+*/
+typedef struct
+{
+	FILE* file;                 /* io structore of the zipfile */
+	unz_global_info gi;       /* public global information */
+	unsigned long byte_before_the_zipfile;/* unsigned char before the zipfile, (>0 for sfx)*/
+	unsigned long num_file;             /* number of the current file in the zipfile*/
+	unsigned long pos_in_central_dir;   /* pos of the current file in the central dir*/
+	unsigned long current_file_ok;      /* flag about the usability of the current file*/
+	unsigned long central_pos;          /* position of the beginning of the central dir*/
+
+	unsigned long size_central_dir;     /* size of the central directory  */
+	unsigned long offset_central_dir;   /* offset of start of central directory with
+								   respect to the starting disk number */
+
+	unz_file_info cur_file_info; /* public info about the current file in zip*/
+	unz_file_info_internal cur_file_info_internal; /* private info about it*/
+    file_in_zip_read_info_s* pfile_in_zip_read; /* structure about the current
+	                                    file if we are decompressing it */
+} unz_s;
+
+#define UNZ_OK                                  (0)
+#define UNZ_END_OF_LIST_OF_FILE (-100)
+#define UNZ_ERRNO               (Z_ERRNO)
+#define UNZ_EOF                 (0)
+#define UNZ_PARAMERROR                  (-102)
+#define UNZ_BADZIPFILE                  (-103)
+#define UNZ_INTERNALERROR               (-104)
+#define UNZ_CRCERROR                    (-105)
+
+#define UNZ_CASESENSITIVE		1
+#define UNZ_NOTCASESENSITIVE	2
+#define UNZ_OSDEFAULTCASE		0
+
+extern int unzStringFileNameCompare (const char* fileName1, const char* fileName2, int iCaseSensitivity);
+
+/*
+   Compare two filename (fileName1,fileName2).
+   If iCaseSenisivity = 1, comparision is case sensitivity (like strcmp)
+   If iCaseSenisivity = 2, comparision is not case sensitivity (like strcmpi
+								or strcasecmp)
+   If iCaseSenisivity = 0, case sensitivity is defaut of your operating system
+	(like 1 on Unix, 2 on Windows)
+*/
+
+extern unzFile unzOpen (const char *path);
+extern unzFile unzReOpen (const char* path, unzFile file);
+
+/*
+  Open a Zip file. path contain the full pathname (by example,
+     on a Windows NT computer "c:\\zlib\\zlib111.zip" or on an Unix computer
+	 "zlib/zlib111.zip".
+	 If the zipfile cannot be opened (file don't exist or in not valid), the
+	   return value is NULL.
+     Else, the return value is a unzFile Handle, usable with other function
+	   of this unzip package.
+*/
+
+extern int unzClose (unzFile file);
+
+/*
+  Close a ZipFile opened with unzipOpen.
+  If there is files inside the .Zip opened with unzOpenCurrentFile (see later),
+    these files MUST be closed with unzipCloseCurrentFile before call unzipClose.
+  return UNZ_OK if there is no problem. */
+
+extern int unzGetGlobalInfo (unzFile file, unz_global_info *pglobal_info);
+
+/*
+  Write info about the ZipFile in the *pglobal_info structure.
+  No preparation of the structure is needed
+  return UNZ_OK if there is no problem. */
+
+
+extern int unzGetGlobalComment (unzFile file, char *szComment, unsigned long uSizeBuf);
+
+/*
+  Get the global comment string of the ZipFile, in the szComment buffer.
+  uSizeBuf is the size of the szComment buffer.
+  return the number of unsigned char copied or an error code <0
+*/
+
+
+/***************************************************************************/
+/* Unzip package allow you browse the directory of the zipfile */
+
+extern int unzGoToFirstFile (unzFile file);
+
+/*
+  Set the current file of the zipfile to the first file.
+  return UNZ_OK if there is no problem
+*/
+
+extern int unzGoToNextFile (unzFile file);
+
+/*
+  Set the current file of the zipfile to the next file.
+  return UNZ_OK if there is no problem
+  return UNZ_END_OF_LIST_OF_FILE if the actual file was the latest.
+*/
+
+extern int unzLocateFile (unzFile file, const char *szFileName, int iCaseSensitivity);
+
+/*
+  Try locate the file szFileName in the zipfile.
+  For the iCaseSensitivity signification, see unzStringFileNameCompare
+
+  return value :
+  UNZ_OK if the file is found. It becomes the current file.
+  UNZ_END_OF_LIST_OF_FILE if the file is not found
+*/
+
+
+extern int unzGetCurrentFileInfo (unzFile file, unz_file_info *pfile_info, char *szFileName, unsigned long fileNameBufferSize, void *extraField, unsigned long extraFieldBufferSize, char *szComment, unsigned long commentBufferSize);
+
+/*
+  Get Info about the current file
+  if pfile_info!=NULL, the *pfile_info structure will contain somes info about
+	    the current file
+  if szFileName!=NULL, the filemane string will be copied in szFileName
+			(fileNameBufferSize is the size of the buffer)
+  if extraField!=NULL, the extra field information will be copied in extraField
+			(extraFieldBufferSize is the size of the buffer).
+			This is the Central-header version of the extra field
+  if szComment!=NULL, the comment string of the file will be copied in szComment
+			(commentBufferSize is the size of the buffer)
+*/
+
+/***************************************************************************/
+/* for reading the content of the current zipfile, you can open it, read data
+   from it, and close it (you can close it before reading all the file)
+   */
+
+extern int unzOpenCurrentFile (unzFile file);
+
+/*
+  Open for reading data the current file in the zipfile.
+  If there is no error, the return value is UNZ_OK.
+*/
+
+extern int unzCloseCurrentFile (unzFile file);
+
+/*
+  Close the file in zip opened with unzOpenCurrentFile
+  Return UNZ_CRCERROR if all the file was read but the CRC is not good
+*/
+
+												
+extern int unzReadCurrentFile (unzFile file, void* buf, unsigned len);
+
+/*
+  Read unsigned chars from the current file (opened by unzOpenCurrentFile)
+  buf contain buffer where data must be copied
+  len the size of buf.
+
+  return the number of unsigned char copied if somes unsigned chars are copied
+  return 0 if the end of file was reached
+  return <0 with error code if there is an error
+    (UNZ_ERRNO for IO error, or zLib error for uncompress error)
+*/
+
+extern long unztell(unzFile file);
+
+/*
+  Give the current position in uncompressed data
+*/
+
+extern int unzeof (unzFile file);
+
+/*
+  return 1 if the end of file was reached, 0 elsewhere 
+*/
+
+extern int unzGetLocalExtrafield (unzFile file, void* buf, unsigned len);
+
+/*
+  Read extra field from the current file (opened by unzOpenCurrentFile)
+  This is the local-header version of the extra field (sometimes, there is
+    more info in the local-header version than in the central-header)
+
+  if buf==NULL, it return the size of the local extra field
+
+  if buf!=NULL, len is the size of the buffer, the extra header is copied in
+	buf.
+  the return value is the number of unsigned chars copied in buf, or (if <0) 
+	the error code
+*/
diff --git a/tools/quake3/common/vfs.c b/tools/quake3/common/vfs.c
index 2d2ab138..3afb00c6 100644
--- a/tools/quake3/common/vfs.c
+++ b/tools/quake3/common/vfs.c
@@ -1,365 +1,365 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-  
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-    
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-      
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-        
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-//
-// Rules:
-//
-// - Directories should be searched in the following order: ~/.q3a/baseq3,
-//   install dir (/usr/local/games/quake3/baseq3) and cd_path (/mnt/cdrom/baseq3).
-//
-// - Pak files are searched first inside the directories.
-// - Case insensitive.
-// - Unix-style slashes (/) (windows is backwards .. everyone knows that)
-//
-// Leonardo Zide (leo@lokigames.com)
-//
-
-#include <stdio.h>
-
-#if defined (__linux__) || defined (__APPLE__)
-#include <dirent.h>
-#include <unistd.h>
-#else
-#include <wtypes.h>
-#include <io.h>
-#define R_OK 04
-#define S_ISDIR(mode) (mode & _S_IFDIR)
-#define PATH_MAX 260
-#endif
-
-#include <string.h>
-#include <stdlib.h>
-#include <sys/stat.h>
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "glib.h"
-#include "inout.h"
-#include "vfs.h"
-#include "unzip.h"
-
-typedef struct
-{
-  char*   name;
-  unz_s   zipinfo;
-  unzFile zipfile;
-  guint32   size;
-} VFS_PAKFILE;
-
-// =============================================================================
-// Global variables
-
-static GSList*  g_unzFiles;
-static GSList*  g_pakFiles;
-static char     g_strDirs[VFS_MAXDIRS][PATH_MAX];
-static int      g_numDirs;
-static gboolean g_bUsePak = TRUE;
-
-// =============================================================================
-// Static functions
-
-static void vfsAddSlash (char *str)
-{
-  int n = strlen (str);
-  if (n > 0)
-  {
-    if (str[n-1] != '\\' && str[n-1] != '/')
-      strcat (str, "/");
-  }
-}
-
-static void vfsFixDOSName (char *src)
-{
-  if (src == NULL)
-    return;
-  
-  while (*src)
-  {
-    if (*src == '\\')
-      *src = '/';
-    src++;
-  }
-}
-
-//!\todo Define globally or use heap-allocated string.
-#define NAME_MAX 255
-
-static void vfsInitPakFile (const char *filename)
-{
-  unz_global_info gi;
-  unzFile uf;
-  guint32 i;
-  int err;
-  
-  uf = unzOpen (filename);
-  if (uf == NULL)
-    return;
-  
-  g_unzFiles = g_slist_append (g_unzFiles, uf);
-  
-  err = unzGetGlobalInfo (uf,&gi);
-  if (err != UNZ_OK)
-    return;
-  unzGoToFirstFile(uf);
-  
-  for (i = 0; i < gi.number_entry; i++)
-  {
-    char filename_inzip[NAME_MAX];
-    unz_file_info file_info;
-    VFS_PAKFILE* file;
-    
-    err = unzGetCurrentFileInfo (uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
-    if (err != UNZ_OK)
-      break;
-    
-    file = (VFS_PAKFILE*)safe_malloc (sizeof (VFS_PAKFILE));
-    g_pakFiles = g_slist_append (g_pakFiles, file);
-    
-    vfsFixDOSName (filename_inzip);
-    g_strdown (filename_inzip);
-    
-    file->name = strdup (filename_inzip);
-    file->size = file_info.uncompressed_size;
-    file->zipfile = uf;
-    memcpy (&file->zipinfo, uf, sizeof (unz_s));
-    
-    if ((i+1) < gi.number_entry)
-    {
-      err = unzGoToNextFile(uf);
-      if (err!=UNZ_OK)
-        break;
-    }
-  }
-}
-
-// =============================================================================
-// Global functions
-
-// reads all pak files from a dir
-void vfsInitDirectory (const char *path)
-{
-  char filename[PATH_MAX];
-  char *dirlist;
-  GDir *dir;
-  
-  if (g_numDirs == (VFS_MAXDIRS-1))
-    return;
-  
-  Sys_Printf ("VFS Init: %s\n", path);
-  
-  strcpy (g_strDirs[g_numDirs], path);
-  vfsFixDOSName (g_strDirs[g_numDirs]);
-  vfsAddSlash (g_strDirs[g_numDirs]);
-  g_numDirs++;
-  
-  if (g_bUsePak)
-  {
-    dir = g_dir_open (path, 0, NULL);
-
-    if (dir != NULL)
-    {
-      while (1)
-      {
-        const char* name = g_dir_read_name(dir);
-        if(name == NULL)
-          break;
-
-        dirlist = g_strdup(name);
-
-        {
-          char *ext = strrchr (dirlist, '.');
-          if ((ext == NULL) || (Q_stricmp (ext, ".pk3") != 0))
-            continue;
-        }
-        
-        sprintf (filename, "%s/%s", path, dirlist);
-        vfsInitPakFile (filename);
-
-        g_free(dirlist);
-      }
-      g_dir_close (dir);
-    }
-  }
-}
-
-// frees all memory that we allocated
-void vfsShutdown ()
-{
-  while (g_unzFiles)
-  {
-    unzClose ((unzFile)g_unzFiles->data);
-    g_unzFiles = g_slist_remove (g_unzFiles, g_unzFiles->data);
-  }
-  
-  while (g_pakFiles)
-  {
-    VFS_PAKFILE* file = (VFS_PAKFILE*)g_pakFiles->data;
-    free (file->name);
-    free (file);
-    g_pakFiles = g_slist_remove (g_pakFiles, file);
-  }
-}
-
-// return the number of files that match
-int vfsGetFileCount (const char *filename)
-{
-  int i, count = 0;
-  char fixed[NAME_MAX], tmp[NAME_MAX];
-  GSList *lst;
-  
-  strcpy (fixed, filename);
-  vfsFixDOSName (fixed);
-  g_strdown (fixed);
-  
-  for (lst = g_pakFiles; lst != NULL; lst = g_slist_next (lst))
-  {
-    VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
-    
-    if (strcmp (file->name, fixed) == 0)
-      count++;
-  }
-  
-  for (i = 0; i < g_numDirs; i++)
-  {
-    strcpy (tmp, g_strDirs[i]);
-    strcat (tmp, fixed);
-    if (access (tmp, R_OK) == 0)
-      count++;
-  }
-  
-  return count;
-}
-
-// NOTE: when loading a file, you have to allocate one extra byte and set it to \0
-int vfsLoadFile (const char *filename, void **bufferptr, int index)
-{
-  int i, count = 0;
-  char tmp[NAME_MAX], fixed[NAME_MAX];
-  GSList *lst;
-  
-  // filename is a full path
-  if (index == -1)
-  {
-    long len;
-    FILE *f;
-    
-    f = fopen (filename, "rb");
-    if (f == NULL)
-      return -1;
-    
-    fseek (f, 0, SEEK_END);
-    len = ftell (f);
-    rewind (f);
-    
-    *bufferptr = safe_malloc (len+1);
-    if (*bufferptr == NULL)
-      return -1;
-    
-    fread (*bufferptr, 1, len, f);
-    fclose (f);
-    
-    // we need to end the buffer with a 0
-    ((char*) (*bufferptr))[len] = 0;
-    
-    return len;
-  }
-  
-  *bufferptr = NULL;
-  strcpy (fixed, filename);
-  vfsFixDOSName (fixed);
-  g_strdown (fixed);
-  
-  for (i = 0; i < g_numDirs; i++)
-  {
-    strcpy (tmp, g_strDirs[i]);
-    strcat (tmp, filename);
-    if (access (tmp, R_OK) == 0)
-    {
-      if (count == index)
-      {
-        long len;
-        FILE *f;
-        
-        f = fopen (tmp, "rb");
-        if (f == NULL)
-          return -1;
-        
-        fseek (f, 0, SEEK_END);
-        len = ftell (f);
-        rewind (f);
-        
-        *bufferptr = safe_malloc (len+1);
-        if (*bufferptr == NULL)
-          return -1;
-        
-        fread (*bufferptr, 1, len, f);
-        fclose (f);
-        
-        // we need to end the buffer with a 0
-        ((char*) (*bufferptr))[len] = 0;
-        
-        return len;
-      }
-      
-      count++;
-    }
-  }
-  
-  for (lst = g_pakFiles; lst != NULL; lst = g_slist_next (lst))
-  {
-    VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
-    
-    if (strcmp (file->name, fixed) != 0)
-      continue;
-    
-    if (count == index)
-    {
-      memcpy (file->zipfile, &file->zipinfo, sizeof (unz_s));
-      
-      if (unzOpenCurrentFile (file->zipfile) != UNZ_OK)
-        return -1;
-      
-      *bufferptr = safe_malloc (file->size+1);
-      // we need to end the buffer with a 0
-      ((char*) (*bufferptr))[file->size] = 0;
-      
-      i = unzReadCurrentFile (file->zipfile , *bufferptr, file->size);
-      unzCloseCurrentFile (file->zipfile);
-      if (i < 0)
-        return -1;
-      else
-        return file->size;
-    }
-    
-    count++;
-  }
-  
-  return -1;
-}
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+  
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+    
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+      
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+        
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+//
+// Rules:
+//
+// - Directories should be searched in the following order: ~/.q3a/baseq3,
+//   install dir (/usr/local/games/quake3/baseq3) and cd_path (/mnt/cdrom/baseq3).
+//
+// - Pak files are searched first inside the directories.
+// - Case insensitive.
+// - Unix-style slashes (/) (windows is backwards .. everyone knows that)
+//
+// Leonardo Zide (leo@lokigames.com)
+//
+
+#include <stdio.h>
+
+#if defined (__linux__) || defined (__APPLE__)
+#include <dirent.h>
+#include <unistd.h>
+#else
+#include <wtypes.h>
+#include <io.h>
+#define R_OK 04
+#define S_ISDIR(mode) (mode & _S_IFDIR)
+#define PATH_MAX 260
+#endif
+
+#include <string.h>
+#include <stdlib.h>
+#include <sys/stat.h>
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "glib.h"
+#include "inout.h"
+#include "vfs.h"
+#include "unzip.h"
+
+typedef struct
+{
+  char*   name;
+  unz_s   zipinfo;
+  unzFile zipfile;
+  guint32   size;
+} VFS_PAKFILE;
+
+// =============================================================================
+// Global variables
+
+static GSList*  g_unzFiles;
+static GSList*  g_pakFiles;
+static char     g_strDirs[VFS_MAXDIRS][PATH_MAX];
+static int      g_numDirs;
+static gboolean g_bUsePak = TRUE;
+
+// =============================================================================
+// Static functions
+
+static void vfsAddSlash (char *str)
+{
+  int n = strlen (str);
+  if (n > 0)
+  {
+    if (str[n-1] != '\\' && str[n-1] != '/')
+      strcat (str, "/");
+  }
+}
+
+static void vfsFixDOSName (char *src)
+{
+  if (src == NULL)
+    return;
+  
+  while (*src)
+  {
+    if (*src == '\\')
+      *src = '/';
+    src++;
+  }
+}
+
+//!\todo Define globally or use heap-allocated string.
+#define NAME_MAX 255
+
+static void vfsInitPakFile (const char *filename)
+{
+  unz_global_info gi;
+  unzFile uf;
+  guint32 i;
+  int err;
+  
+  uf = unzOpen (filename);
+  if (uf == NULL)
+    return;
+  
+  g_unzFiles = g_slist_append (g_unzFiles, uf);
+  
+  err = unzGetGlobalInfo (uf,&gi);
+  if (err != UNZ_OK)
+    return;
+  unzGoToFirstFile(uf);
+  
+  for (i = 0; i < gi.number_entry; i++)
+  {
+    char filename_inzip[NAME_MAX];
+    unz_file_info file_info;
+    VFS_PAKFILE* file;
+    
+    err = unzGetCurrentFileInfo (uf, &file_info, filename_inzip, sizeof(filename_inzip), NULL, 0, NULL, 0);
+    if (err != UNZ_OK)
+      break;
+    
+    file = (VFS_PAKFILE*)safe_malloc (sizeof (VFS_PAKFILE));
+    g_pakFiles = g_slist_append (g_pakFiles, file);
+    
+    vfsFixDOSName (filename_inzip);
+    g_strdown (filename_inzip);
+    
+    file->name = strdup (filename_inzip);
+    file->size = file_info.uncompressed_size;
+    file->zipfile = uf;
+    memcpy (&file->zipinfo, uf, sizeof (unz_s));
+    
+    if ((i+1) < gi.number_entry)
+    {
+      err = unzGoToNextFile(uf);
+      if (err!=UNZ_OK)
+        break;
+    }
+  }
+}
+
+// =============================================================================
+// Global functions
+
+// reads all pak files from a dir
+void vfsInitDirectory (const char *path)
+{
+  char filename[PATH_MAX];
+  char *dirlist;
+  GDir *dir;
+  
+  if (g_numDirs == (VFS_MAXDIRS-1))
+    return;
+  
+  Sys_Printf ("VFS Init: %s\n", path);
+  
+  strcpy (g_strDirs[g_numDirs], path);
+  vfsFixDOSName (g_strDirs[g_numDirs]);
+  vfsAddSlash (g_strDirs[g_numDirs]);
+  g_numDirs++;
+  
+  if (g_bUsePak)
+  {
+    dir = g_dir_open (path, 0, NULL);
+
+    if (dir != NULL)
+    {
+      while (1)
+      {
+        const char* name = g_dir_read_name(dir);
+        if(name == NULL)
+          break;
+
+        dirlist = g_strdup(name);
+
+        {
+          char *ext = strrchr (dirlist, '.');
+          if ((ext == NULL) || (Q_stricmp (ext, ".pk3") != 0))
+            continue;
+        }
+        
+        sprintf (filename, "%s/%s", path, dirlist);
+        vfsInitPakFile (filename);
+
+        g_free(dirlist);
+      }
+      g_dir_close (dir);
+    }
+  }
+}
+
+// frees all memory that we allocated
+void vfsShutdown ()
+{
+  while (g_unzFiles)
+  {
+    unzClose ((unzFile)g_unzFiles->data);
+    g_unzFiles = g_slist_remove (g_unzFiles, g_unzFiles->data);
+  }
+  
+  while (g_pakFiles)
+  {
+    VFS_PAKFILE* file = (VFS_PAKFILE*)g_pakFiles->data;
+    free (file->name);
+    free (file);
+    g_pakFiles = g_slist_remove (g_pakFiles, file);
+  }
+}
+
+// return the number of files that match
+int vfsGetFileCount (const char *filename)
+{
+  int i, count = 0;
+  char fixed[NAME_MAX], tmp[NAME_MAX];
+  GSList *lst;
+  
+  strcpy (fixed, filename);
+  vfsFixDOSName (fixed);
+  g_strdown (fixed);
+  
+  for (lst = g_pakFiles; lst != NULL; lst = g_slist_next (lst))
+  {
+    VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
+    
+    if (strcmp (file->name, fixed) == 0)
+      count++;
+  }
+  
+  for (i = 0; i < g_numDirs; i++)
+  {
+    strcpy (tmp, g_strDirs[i]);
+    strcat (tmp, fixed);
+    if (access (tmp, R_OK) == 0)
+      count++;
+  }
+  
+  return count;
+}
+
+// NOTE: when loading a file, you have to allocate one extra byte and set it to \0
+int vfsLoadFile (const char *filename, void **bufferptr, int index)
+{
+  int i, count = 0;
+  char tmp[NAME_MAX], fixed[NAME_MAX];
+  GSList *lst;
+  
+  // filename is a full path
+  if (index == -1)
+  {
+    long len;
+    FILE *f;
+    
+    f = fopen (filename, "rb");
+    if (f == NULL)
+      return -1;
+    
+    fseek (f, 0, SEEK_END);
+    len = ftell (f);
+    rewind (f);
+    
+    *bufferptr = safe_malloc (len+1);
+    if (*bufferptr == NULL)
+      return -1;
+    
+    fread (*bufferptr, 1, len, f);
+    fclose (f);
+    
+    // we need to end the buffer with a 0
+    ((char*) (*bufferptr))[len] = 0;
+    
+    return len;
+  }
+  
+  *bufferptr = NULL;
+  strcpy (fixed, filename);
+  vfsFixDOSName (fixed);
+  g_strdown (fixed);
+  
+  for (i = 0; i < g_numDirs; i++)
+  {
+    strcpy (tmp, g_strDirs[i]);
+    strcat (tmp, filename);
+    if (access (tmp, R_OK) == 0)
+    {
+      if (count == index)
+      {
+        long len;
+        FILE *f;
+        
+        f = fopen (tmp, "rb");
+        if (f == NULL)
+          return -1;
+        
+        fseek (f, 0, SEEK_END);
+        len = ftell (f);
+        rewind (f);
+        
+        *bufferptr = safe_malloc (len+1);
+        if (*bufferptr == NULL)
+          return -1;
+        
+        fread (*bufferptr, 1, len, f);
+        fclose (f);
+        
+        // we need to end the buffer with a 0
+        ((char*) (*bufferptr))[len] = 0;
+        
+        return len;
+      }
+      
+      count++;
+    }
+  }
+  
+  for (lst = g_pakFiles; lst != NULL; lst = g_slist_next (lst))
+  {
+    VFS_PAKFILE* file = (VFS_PAKFILE*)lst->data;
+    
+    if (strcmp (file->name, fixed) != 0)
+      continue;
+    
+    if (count == index)
+    {
+      memcpy (file->zipfile, &file->zipinfo, sizeof (unz_s));
+      
+      if (unzOpenCurrentFile (file->zipfile) != UNZ_OK)
+        return -1;
+      
+      *bufferptr = safe_malloc (file->size+1);
+      // we need to end the buffer with a 0
+      ((char*) (*bufferptr))[file->size] = 0;
+      
+      i = unzReadCurrentFile (file->zipfile , *bufferptr, file->size);
+      unzCloseCurrentFile (file->zipfile);
+      if (i < 0)
+        return -1;
+      else
+        return file->size;
+    }
+    
+    count++;
+  }
+  
+  return -1;
+}
diff --git a/tools/quake3/common/vfs.h b/tools/quake3/common/vfs.h
index ed74161e..44b3ffad 100644
--- a/tools/quake3/common/vfs.h
+++ b/tools/quake3/common/vfs.h
@@ -1,41 +1,41 @@
-/*
-Copyright (c) 2001, Loki software, inc.
-All rights reserved.
-
-Redistribution and use in source and binary forms, with or without modification, 
-are permitted provided that the following conditions are met:
-
-Redistributions of source code must retain the above copyright notice, this list 
-of conditions and the following disclaimer.
-
-Redistributions in binary form must reproduce the above copyright notice, this
-list of conditions and the following disclaimer in the documentation and/or
-other materials provided with the distribution.
-
-Neither the name of Loki software nor the names of its contributors may be used 
-to endorse or promote products derived from this software without specific prior 
-written permission. 
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
-AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
-DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
-DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
-*/
-
-#ifndef _VFS_H_
-#define _VFS_H_
-
-#define VFS_MAXDIRS 8
-
-void vfsInitDirectory (const char *path);
-void vfsShutdown ();
-int vfsGetFileCount (const char *filename);
-int vfsLoadFile (const char *filename, void **buffer, int index);
-
-#endif // _VFS_H_
+/*
+Copyright (c) 2001, Loki software, inc.
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without modification, 
+are permitted provided that the following conditions are met:
+
+Redistributions of source code must retain the above copyright notice, this list 
+of conditions and the following disclaimer.
+
+Redistributions in binary form must reproduce the above copyright notice, this
+list of conditions and the following disclaimer in the documentation and/or
+other materials provided with the distribution.
+
+Neither the name of Loki software nor the names of its contributors may be used 
+to endorse or promote products derived from this software without specific prior 
+written permission. 
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' 
+AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 
+DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR ANY 
+DIRECT,INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 
+ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+*/
+
+#ifndef _VFS_H_
+#define _VFS_H_
+
+#define VFS_MAXDIRS 8
+
+void vfsInitDirectory (const char *path);
+void vfsShutdown ();
+int vfsGetFileCount (const char *filename);
+int vfsLoadFile (const char *filename, void **buffer, int index);
+
+#endif // _VFS_H_
diff --git a/tools/quake3/q3data/3dslib.c b/tools/quake3/q3data/3dslib.c
index d5e864fd..719a487f 100644
--- a/tools/quake3/q3data/3dslib.c
+++ b/tools/quake3/q3data/3dslib.c
@@ -1,630 +1,630 @@
-#include <assert.h>
-#include "q3data.h"
-
-static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose );
-
-static qboolean s_verbose;
-
-#define MAX_MATERIALS 100
-#define MAX_NAMED_OBJECTS 100
-#define MAX_MESH_MATERIAL_GROUPS 100
-#define MAX_TRI_OBJECTS 512
-
-static char s_buffer[1000000];
-
-static int ReadString( FILE *fp, char *buffer )
-{
-	int i = 0;
-	int bytesRead = 0;
-
-	do
-	{
-		fread( &buffer[i], 1, sizeof( char ), fp );
-		bytesRead++;
-	} while ( buffer[i++] != 0 );
-	buffer[i] = 0;
-
-	return bytesRead;
-}
-
-static int ReadChunkAndLength( FILE *fp, short *chunk, long *len )
-{
-	if ( fread( chunk, sizeof( short ), 1, fp ) != 1 )
-		return 0;
-	if ( fread( len, sizeof( long ), 1, fp ) != 1 )
-		Error( "Unexpected EOF found" );
-	return 1;
-}
-
-static void LoadMapName( FILE *fp, char *buffer, int thisChunkLen )
-{
-	unsigned short chunkID;
-	long chunkLen;
-	long bytesRead = 0;
-
-	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
-	{
-		switch ( chunkID )
-		{
-		case _3DS_CHUNK_MAT_MAPNAME:
-			fread( buffer, chunkLen - 6, 1, fp );
-			break;
-		default:
-			fread( s_buffer, chunkLen - 6, 1, fp );
-			break;
-		}
-		bytesRead += chunkLen;
-		if ( bytesRead >= thisChunkLen )
-			return;
-	}
-}
-
-static void LoadMaterialList( FILE *fp, long thisChunkLen, _3DSMaterial_t *pMat )
-{
-	long chunkLen;
-	unsigned short chunkID;
-	long bytesRead = 0;
-	_3DSMaterial_t mat;
-	char curdir[1024];
-	char buffer[2048];
-
-	memset( &mat, 0, sizeof( mat ) );
-
-	if ( s_verbose )
-		printf( "    >>> MATERIAL LIST\n" );
-
-	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
-	{
-		switch ( chunkID )
-		{
-			case _3DS_CHUNK_MAT_NAME:
-				fread( mat.name, chunkLen - 6, 1, fp );
-				if ( s_verbose )
-					printf( "        found mat name '%s'\n", mat.name );
-				break;
-			case _3DS_CHUNK_TEXMAP:
-				LoadMapName( fp, mat.texture, chunkLen - 6 );
-				if ( s_verbose )
-					printf( "        found texture '%s'\n", mat.texture );
-				break;
-			case _3DS_CHUNK_SPECMAP:
-				LoadMapName( fp, mat.specular, chunkLen - 6 );
-				if ( s_verbose )
-					printf( "        found specular map '%s'\n", mat.specular );
-				break;
-			case _3DS_CHUNK_OPACMAP:
-				LoadMapName( fp, mat.opacity, chunkLen - 6 );
-				if ( s_verbose )
-					printf( "        found opacity map '%s'\n", mat.opacity );
-				break;
-			case _3DS_CHUNK_REFLMAP:
-				LoadMapName( fp, mat.reflection, chunkLen - 6 );
-				if ( s_verbose )
-					printf( "        found reflection map '%s'\n", mat.reflection );
-				break;
-			case _3DS_CHUNK_BUMPMAP:
-				LoadMapName( fp, mat.bump, chunkLen - 6 );
-				if ( s_verbose )
-					printf( "        found bump map '%s'\n", mat.bump );
-				break;
-			default:
-				fread( s_buffer, chunkLen - 6, 1, fp );
-				break;
-		}
-
-		bytesRead += chunkLen;
-
-		if ( bytesRead >= thisChunkLen )
-			break;
-	}
-
-	Q_getwd( curdir );
-
-	if ( mat.texture[0] )
-	{
-		sprintf( buffer, "%s%s", curdir, mat.texture );
-		if ( strstr( buffer, gamedir + 1 ) )
-			strcpy( mat.texture, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
-		else
-			strcpy( mat.texture, buffer );
-	}
-
-	if ( mat.specular[0] )
-	{
-		sprintf( buffer, "%s%s", curdir, mat.specular );
-		if ( strstr( buffer, gamedir + 1 ) )
-			strcpy( mat.specular, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
-		else
-			strcpy( mat.specular, buffer );
-	}
-
-	if ( mat.bump[0] )
-	{
-		sprintf( buffer, "%s%s", curdir, mat.bump );
-		if ( strstr( buffer, gamedir + 1 ) )
-			strcpy( mat.bump, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
-		else
-			strcpy( mat.bump, buffer );
-	}
-
-	if ( mat.reflection[0] )
-	{
-		sprintf( buffer, "%s%s", curdir, mat.reflection );
-		if ( strstr( buffer, gamedir + 1 ) )
-			strcpy( mat.reflection, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
-		else
-			strcpy( mat.reflection, buffer );
-	}
-
-	if ( mat.opacity[0] )
-	{
-		sprintf( buffer, "%s%s", curdir, mat.opacity );
-		if ( strstr( buffer, gamedir + 1 ) )
-			strcpy( mat.opacity, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
-		else
-			strcpy( mat.opacity, buffer );
-	}
-
-	*pMat = mat;
-}
-
-static void LoadMeshMaterialGroup( FILE *fp, long thisChunkLen, _3DSMeshMaterialGroup_t *pMMG )
-{
-	_3DSMeshMaterialGroup_t mmg;
-
-	memset( &mmg, 0, sizeof( mmg ) );
-
-	ReadString( fp, mmg.name );
-
-	fread( &mmg.numFaces, sizeof( mmg.numFaces ), 1, fp );
-	mmg.pFaces = malloc( sizeof( mmg.pFaces[0] ) * mmg.numFaces );
-	fread( mmg.pFaces, sizeof( mmg.pFaces[0] ), mmg.numFaces, fp );
-
-	if ( s_verbose )
-	{
-		printf( "    >>> MESH MATERIAL GROUP '%s' (%d faces)\n", mmg.name, mmg.numFaces );
-
-		{
-			int i;
-
-			for ( i = 0; i < mmg.numFaces; i++ )
-			{
-				printf( "        %d\n", mmg.pFaces[i] );
-			}
-		}
-	}
-
-	*pMMG = mmg;
-}
-
-static void LoadNamedTriObject( FILE *fp, long thisChunkLen, _3DSTriObject_t *pTO )
-{
-	long chunkLen;
-	unsigned short chunkID;
-	int i = 0;
-	long bytesRead = 0;
-	_3DSTriObject_t triObj;
-	_3DSMeshMaterialGroup_t meshMaterialGroups[MAX_MESH_MATERIAL_GROUPS];
-	int numMeshMaterialGroups = 0;
-
-	memset( &triObj, 0, sizeof( triObj ) );
-
-	if ( s_verbose )
-		printf( "        >>> NAMED TRI OBJECT\n" );
-
-	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
-	{
-		switch ( chunkID )
-		{
-		case _3DS_CHUNK_MSH_MAT_GROUP:
-			LoadMeshMaterialGroup( fp, chunkLen - 6, &meshMaterialGroups[numMeshMaterialGroups] );
-			bytesRead += chunkLen;
-			numMeshMaterialGroups++;
-			break;
-		case _3DS_CHUNK_FACE_ARRAY:
-			fread( &triObj.numFaces, sizeof( triObj.numFaces ), 1, fp );
-			assert( triObj.pFaces == 0 );
-
-			triObj.pFaces = malloc( sizeof( triObj.pFaces[0] ) * triObj.numFaces );
-			fread( triObj.pFaces, sizeof( triObj.pFaces[0] ), triObj.numFaces, fp );
-			bytesRead += sizeof( triObj.numFaces ) + triObj.numFaces * sizeof( triObj.pFaces[0] ) + 6;
-
-			if ( s_verbose )
-			{
-				printf( "            found face array with %d faces\n", triObj.numFaces );
-				for ( i = 0; i < triObj.numFaces; i++ )
-				{
-					printf( "                %d: %d,%d,%d\n", i, triObj.pFaces[i].a, triObj.pFaces[i].b, triObj.pFaces[i].c );
-				}
-			}
-
-			break;
-		case _3DS_CHUNK_POINT_ARRAY:
-			fread( &triObj.numPoints, sizeof( triObj.numPoints ), 1, fp );
-			triObj.pPoints = malloc( sizeof( triObj.pPoints[0] ) * triObj.numPoints );
-			fread( triObj.pPoints, sizeof( triObj.pPoints[0] ), triObj.numPoints, fp );
-			bytesRead += sizeof( triObj.numPoints ) + triObj.numPoints * sizeof( triObj.pPoints[0] ) + 6;
-
-			// flip points around into our coordinate system
-			for ( i = 0; i < triObj.numPoints; i++ )
-			{
-				float x, y, z;
-
-				x = triObj.pPoints[i].x;
-				y = triObj.pPoints[i].y;
-				z = triObj.pPoints[i].z;
-
-				triObj.pPoints[i].x = -y;
-				triObj.pPoints[i].y = x;
-				triObj.pPoints[i].z = z;
-			}
-
-			if ( s_verbose )
-			{
-				printf( "            found point array with %d points\n", triObj.numPoints );
-				for ( i = 0; i < triObj.numPoints; i++ )
-				{
-					printf( "                %d: %f,%f,%f\n", i, triObj.pPoints[i].x, triObj.pPoints[i].y, triObj.pPoints[i].z );
-				}
-			}
-			break;
-		case _3DS_CHUNK_TEX_VERTS:
-			fread( &triObj.numTexVerts, sizeof( triObj.numTexVerts ), 1, fp );
-			triObj.pTexVerts = malloc( sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts );
-			fread( triObj.pTexVerts, sizeof( triObj.pTexVerts[0] ), triObj.numTexVerts, fp );
-			bytesRead += sizeof( triObj.numTexVerts ) + sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts + 6;
-
-			if ( s_verbose )
-			{
-				printf( "            found tex vert array with %d tex verts\n", triObj.numTexVerts );
-				for ( i = 0; i < triObj.numTexVerts; i++ )
-				{
-					printf( "                %d: %f,%f\n", i, triObj.pTexVerts[i].s, triObj.pTexVerts[i].t );
-				}
-			}
-			break;
-		default:
-			fread( s_buffer, chunkLen - 6, 1, fp );
-			bytesRead += chunkLen;
-			break;
-		}
-
-		if ( bytesRead >= thisChunkLen )
-			break;
-	}
-	*pTO = triObj;
-
-	if ( numMeshMaterialGroups == 0 )
-	{
-		numMeshMaterialGroups = 1;
-		strcpy( meshMaterialGroups[0].name, "(null)" );
-		if ( pTO->numTexVerts ) {
-			printf( "Warning: assigning (null) skin to tri object\n" );
-		}
-	}
-	else
-	{
-		assert( pTO->numFaces == meshMaterialGroups[0].numFaces );
-	}
-
-	pTO->pMeshMaterialGroups = malloc( sizeof( _3DSMeshMaterialGroup_t ) * numMeshMaterialGroups );
-	memcpy( pTO->pMeshMaterialGroups, meshMaterialGroups, numMeshMaterialGroups * sizeof( meshMaterialGroups[0] ) );
-	pTO->numMeshMaterialGroups = numMeshMaterialGroups;
-
-	//
-	// sanity checks
-	//
-	assert( numMeshMaterialGroups <= 1 );
-}
-
-static void LoadNamedObject( FILE *fp, long thisChunkLen, _3DSNamedObject_t *pNO )
-{
-	long chunkLen;
-	unsigned short chunkID;
-	int i = 0;
-	long bytesRead = 0;
-	char name[100];
-	_3DSTriObject_t triObj[MAX_TRI_OBJECTS];
-	int numTriObjects = 0;
-
-	memset( triObj, 0, sizeof( triObj ) );
-
-	bytesRead += ReadString( fp, name );
-
-	if ( s_verbose )
-		printf( "    >>> NAMED OBJECT '%s'\n", name );
-
-	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
-	{
-		switch ( chunkID )
-		{
-		case _3DS_CHUNK_NAMED_TRI_OBJECT:
-			LoadNamedTriObject( fp, chunkLen - 6, &triObj[numTriObjects] );
-			numTriObjects++;
-			break;
-		default:
-			fread( s_buffer, chunkLen - 6, 1, fp );
-			break;
-		}
-
-		bytesRead += chunkLen;
-
-		if ( bytesRead >= thisChunkLen )
-			break;
-	}
-
-	strcpy( pNO->name, name );
-	pNO->pTriObjects = malloc( sizeof( _3DSTriObject_t ) * numTriObjects );
-	memcpy( pNO->pTriObjects, triObj, sizeof( triObj[0] ) * numTriObjects );
-	pNO->numTriObjects = numTriObjects;
-
-	assert( numTriObjects <= 1 );
-}
-
-static void LoadEditChunk( FILE *fp, long thisChunkLen, _3DSEditChunk_t *pEC )
-{
-	unsigned short chunkID;
-	long chunkLen;
-	long bytesRead = 0;
-	_3DSEditChunk_t editChunk;
-
-	_3DSMaterial_t mat[MAX_MATERIALS];
-	_3DSNamedObject_t namedObjects[MAX_NAMED_OBJECTS];
-
-	int numMaterials = 0, numNamedObjects = 0;
-
-	memset( &editChunk, 0, sizeof( editChunk ) );
-
-	if ( s_verbose )
-		printf( ">>> EDIT CHUNK\n" );
-
-	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
-	{
-		switch ( chunkID )
-		{
-		case _3DS_CHUNK_MAT_LIST:
-			LoadMaterialList( fp, chunkLen - 6, &mat[numMaterials] );
-			numMaterials++;
-			break;
-		case _3DS_CHUNK_NAMED_OBJECT:
-			LoadNamedObject( fp, chunkLen - 6, &namedObjects[numNamedObjects] );
-			if ( namedObjects[numNamedObjects].numTriObjects != 0 )
-				++numNamedObjects;
-			break;
-		case _3DS_CHUNK_MESH_VERSION:
-		default:
-			fread( s_buffer, chunkLen - 6, 1, fp );
-			break;
-		}
-
-		bytesRead += chunkLen;
-
-		if ( bytesRead >= thisChunkLen )
-			break;
-	}
-
-	if ( numMaterials == 0 )
-	{
-		numMaterials = 1;
-		strcpy( mat[0].name, "(null)" );
-		printf( "Warning: no material definitions found\n" );
-	}
-
-	pEC->numNamedObjects = numNamedObjects;
-
-	pEC->pMaterials = malloc( sizeof( _3DSMaterial_t ) * numMaterials );
-	pEC->pNamedObjects = malloc( sizeof( _3DSNamedObject_t ) * numNamedObjects );
-
-	memcpy( pEC->pMaterials, mat, numMaterials * sizeof( mat[0] ) );
-	memcpy( pEC->pNamedObjects, namedObjects, numNamedObjects * sizeof( namedObjects[0] ) );
-}
-
-static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose )
-{
-	FILE *fp;
-	unsigned short chunkID;
-	long  chunkLen;
-	_3DSEditChunk_t editChunk;
-
-	s_verbose = verbose;
-
-	if ( ( fp = fopen( filename, "rb" ) ) == 0 )
-		Error( "Unable to open '%s'", filename );
-
-	// read magic number
-	if ( ( fread( &chunkID, sizeof( short ), 1, fp ) != 1 ) ||
-		 ( LittleShort( chunkID ) != _3DS_CHUNK_MAGIC ) )
-	{
-		Error( "Missing or incorrect magic number in '%s'", filename );
-	}
-	if ( fread( &chunkLen, sizeof( chunkLen ), 1, fp ) != 1 )
-		Error( "Unexpected EOF encountered in '%s'", filename );
-	// version number
-	if ( !ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
-		Error( "Missing version number in '%s'", filename );
-	if ( fread( s_buffer, chunkLen - 6, 1, fp ) != 1 )
-		Error( "Unexpected EOF encountered in '%s'", filename );
-
-	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
-	{
-		switch ( chunkID )
-		{
-			case _3DS_CHUNK_EDIT:
-				LoadEditChunk( fp, chunkLen - 6, &editChunk );
-				break;
-			case _3DS_CHUNK_KEYFRAME_DATA:
-				fread( s_buffer, chunkLen - 6, 1, fp );
-				break;
-			default:
-				fread( s_buffer, chunkLen - 6, 1, fp );
-				break;
-		}
-	}
-
-	fclose( fp );
-
-	p3DS->editChunk = editChunk;
-}
-
-static void ComputeNormals( _3DSTriObject_t *pTO, triangle_t *pTris )
-{
-	vec3_t faceNormals[POLYSET_MAXTRIANGLES];
-	vec3_t vertexNormals[POLYSET_MAXTRIANGLES*3];
-	vec3_t side0, side1, facenormal;
-	int f, v;
-
-	memset( faceNormals, 0, sizeof( faceNormals ) );
-	memset( vertexNormals, 0, sizeof( vertexNormals ) );
-
-	//
-	// compute face normals
-	//
-	for ( f = 0; f < pTO->numFaces; f++ )
-	{
-		VectorSubtract( pTris[f].verts[0], pTris[f].verts[1], side0 );
-		VectorSubtract( pTris[f].verts[2], pTris[f].verts[1], side1 );
-
-		CrossProduct( side0, side1, facenormal );
-		VectorNormalize( facenormal, faceNormals[f] );
-	}
-
-	//
-	// sum vertex normals
-	//
-	for ( v = 0; v < pTO->numPoints; v++ )
-	{
-		for ( f = 0; f < pTO->numFaces; f++ )
-		{
-			if ( ( pTO->pFaces[f].a == v ) ||
-				 ( pTO->pFaces[f].b == v ) ||
-				 ( pTO->pFaces[f].c == v ) )
-			{
-				vertexNormals[v][0] += faceNormals[f][0];
-				vertexNormals[v][1] += faceNormals[f][1];
-				vertexNormals[v][2] += faceNormals[f][2];
-			}
-		}
-
-		VectorNormalize( vertexNormals[v], vertexNormals[v] );
-	}
-
-	//
-	// copy vertex normals into triangles
-	//
-	for ( f = 0; f < pTO->numFaces; f++ )
-	{
-		int i0 = pTO->pFaces[f].c;
-		int i1 = pTO->pFaces[f].b;
-		int i2 = pTO->pFaces[f].a;
-
-		VectorCopy( vertexNormals[i0], pTris[f].normals[0] );
-		VectorCopy( vertexNormals[i1], pTris[f].normals[1] );
-		VectorCopy( vertexNormals[i2], pTris[f].normals[2] );
-	}
-}
-
-/*
-** void _3DS_LoadPolysets
-*/
-void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose )
-{
-	_3DS_t _3ds;
-	int numPolysets;
-	polyset_t *pPSET;
-	triangle_t *ptri, *triangles;
-	int i;
-
-	// load the 3DS
-	memset( &_3ds, 0, sizeof( _3ds ) );
-	Load3DS( filename, &_3ds, verbose );
-
-	// compute information
-	numPolysets = _3ds.editChunk.numNamedObjects;
-
-	// allocate memory
-	pPSET = calloc( 1, numPolysets * sizeof( polyset_t ) );
-	triangles = ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
-
-	// copy the data over
-	for ( i = 0; i < numPolysets; i++ )
-	{
-		char matnamebuf[1024];
-		int j;
-		triangle_t *tri;
-		_3DSTriObject_t *pTO = &_3ds.editChunk.pNamedObjects[i].pTriObjects[0];
-
-		pPSET[i].triangles = ptri;
-		pPSET[i].numtriangles = pTO->numFaces;
-		strcpy( pPSET[i].name, _3ds.editChunk.pNamedObjects[i].name );
-
-		strcpy( matnamebuf, filename );
-		if ( strrchr( matnamebuf, '/' ) )
-			*( strrchr( matnamebuf, '/' ) + 1 )= 0;
-		strcat( matnamebuf, pTO->pMeshMaterialGroups[0].name );
-
-		if ( strstr( matnamebuf, gamedir ) )
-			strcpy( pPSET[i].materialname, strstr( matnamebuf, gamedir ) + strlen( gamedir ) );
-		else
-			strcpy( pPSET[i].materialname, pTO->pMeshMaterialGroups[0].name );
-
-		assert( pPSET[i].numtriangles < POLYSET_MAXTRIANGLES );
-
-		for ( tri = ptri, j = 0; j < pPSET[i].numtriangles; j++ )
-		{
-			int i0 = pTO->pFaces[j].c;
-			int i1 = pTO->pFaces[j].b;
-			int i2 = pTO->pFaces[j].a;
-
-			tri->verts[0][0] = pTO->pPoints[i0].x;
-			tri->verts[0][1] = pTO->pPoints[i0].y;
-			tri->verts[0][2] = pTO->pPoints[i0].z;
-
-			tri->verts[1][0] = pTO->pPoints[i1].x;
-			tri->verts[1][1] = pTO->pPoints[i1].y;
-			tri->verts[1][2] = pTO->pPoints[i1].z;
-
-			tri->verts[2][0] = pTO->pPoints[i2].x;
-			tri->verts[2][1] = pTO->pPoints[i2].y;
-			tri->verts[2][2] = pTO->pPoints[i2].z;
-/*
-			for ( k = 0; k < 3; k++ )
-			{
-				tri->colors[0][k] = 1;
-				tri->colors[1][k] = 1;
-				tri->colors[2][k] = 1;
-			}
-*/
-
-			if ( pTO->pTexVerts )
-			{
-				tri->texcoords[0][0] = pTO->pTexVerts[i0].s;
-				tri->texcoords[0][1] = 1.0f - pTO->pTexVerts[i0].t;
-				tri->texcoords[1][0] = pTO->pTexVerts[i1].s;
-				tri->texcoords[1][1] = 1.0f - pTO->pTexVerts[i1].t;
-				tri->texcoords[2][0] = pTO->pTexVerts[i2].s;
-				tri->texcoords[2][1] = 1.0f - pTO->pTexVerts[i2].t;
-			}
-
-			tri++;
-		}
-
-		ptri += pPSET[i].numtriangles;
-		assert( ptri - triangles < POLYSET_MAXTRIANGLES );
-	}
-
-	// compute normal data
-#if 0
-	for ( i = 0; i < numPolysets; i++ )
-	{
-		// unique vertices based solely on vertex position
-		ComputeNormals( &_3ds.editChunk.pNamedObjects[i].pTriObjects[0],
-						 pPSET[i].triangles );
-	}
-#endif
-
-	free( _3ds.editChunk.pMaterials );
-	free( _3ds.editChunk.pNamedObjects );
-
-	*ppPSET = pPSET;
-	*numpsets = numPolysets;
-}
+#include <assert.h>
+#include "q3data.h"
+
+static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose );
+
+static qboolean s_verbose;
+
+#define MAX_MATERIALS 100
+#define MAX_NAMED_OBJECTS 100
+#define MAX_MESH_MATERIAL_GROUPS 100
+#define MAX_TRI_OBJECTS 512
+
+static char s_buffer[1000000];
+
+static int ReadString( FILE *fp, char *buffer )
+{
+	int i = 0;
+	int bytesRead = 0;
+
+	do
+	{
+		fread( &buffer[i], 1, sizeof( char ), fp );
+		bytesRead++;
+	} while ( buffer[i++] != 0 );
+	buffer[i] = 0;
+
+	return bytesRead;
+}
+
+static int ReadChunkAndLength( FILE *fp, short *chunk, long *len )
+{
+	if ( fread( chunk, sizeof( short ), 1, fp ) != 1 )
+		return 0;
+	if ( fread( len, sizeof( long ), 1, fp ) != 1 )
+		Error( "Unexpected EOF found" );
+	return 1;
+}
+
+static void LoadMapName( FILE *fp, char *buffer, int thisChunkLen )
+{
+	unsigned short chunkID;
+	long chunkLen;
+	long bytesRead = 0;
+
+	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
+	{
+		switch ( chunkID )
+		{
+		case _3DS_CHUNK_MAT_MAPNAME:
+			fread( buffer, chunkLen - 6, 1, fp );
+			break;
+		default:
+			fread( s_buffer, chunkLen - 6, 1, fp );
+			break;
+		}
+		bytesRead += chunkLen;
+		if ( bytesRead >= thisChunkLen )
+			return;
+	}
+}
+
+static void LoadMaterialList( FILE *fp, long thisChunkLen, _3DSMaterial_t *pMat )
+{
+	long chunkLen;
+	unsigned short chunkID;
+	long bytesRead = 0;
+	_3DSMaterial_t mat;
+	char curdir[1024];
+	char buffer[2048];
+
+	memset( &mat, 0, sizeof( mat ) );
+
+	if ( s_verbose )
+		printf( "    >>> MATERIAL LIST\n" );
+
+	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
+	{
+		switch ( chunkID )
+		{
+			case _3DS_CHUNK_MAT_NAME:
+				fread( mat.name, chunkLen - 6, 1, fp );
+				if ( s_verbose )
+					printf( "        found mat name '%s'\n", mat.name );
+				break;
+			case _3DS_CHUNK_TEXMAP:
+				LoadMapName( fp, mat.texture, chunkLen - 6 );
+				if ( s_verbose )
+					printf( "        found texture '%s'\n", mat.texture );
+				break;
+			case _3DS_CHUNK_SPECMAP:
+				LoadMapName( fp, mat.specular, chunkLen - 6 );
+				if ( s_verbose )
+					printf( "        found specular map '%s'\n", mat.specular );
+				break;
+			case _3DS_CHUNK_OPACMAP:
+				LoadMapName( fp, mat.opacity, chunkLen - 6 );
+				if ( s_verbose )
+					printf( "        found opacity map '%s'\n", mat.opacity );
+				break;
+			case _3DS_CHUNK_REFLMAP:
+				LoadMapName( fp, mat.reflection, chunkLen - 6 );
+				if ( s_verbose )
+					printf( "        found reflection map '%s'\n", mat.reflection );
+				break;
+			case _3DS_CHUNK_BUMPMAP:
+				LoadMapName( fp, mat.bump, chunkLen - 6 );
+				if ( s_verbose )
+					printf( "        found bump map '%s'\n", mat.bump );
+				break;
+			default:
+				fread( s_buffer, chunkLen - 6, 1, fp );
+				break;
+		}
+
+		bytesRead += chunkLen;
+
+		if ( bytesRead >= thisChunkLen )
+			break;
+	}
+
+	Q_getwd( curdir );
+
+	if ( mat.texture[0] )
+	{
+		sprintf( buffer, "%s%s", curdir, mat.texture );
+		if ( strstr( buffer, gamedir + 1 ) )
+			strcpy( mat.texture, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
+		else
+			strcpy( mat.texture, buffer );
+	}
+
+	if ( mat.specular[0] )
+	{
+		sprintf( buffer, "%s%s", curdir, mat.specular );
+		if ( strstr( buffer, gamedir + 1 ) )
+			strcpy( mat.specular, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
+		else
+			strcpy( mat.specular, buffer );
+	}
+
+	if ( mat.bump[0] )
+	{
+		sprintf( buffer, "%s%s", curdir, mat.bump );
+		if ( strstr( buffer, gamedir + 1 ) )
+			strcpy( mat.bump, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
+		else
+			strcpy( mat.bump, buffer );
+	}
+
+	if ( mat.reflection[0] )
+	{
+		sprintf( buffer, "%s%s", curdir, mat.reflection );
+		if ( strstr( buffer, gamedir + 1 ) )
+			strcpy( mat.reflection, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
+		else
+			strcpy( mat.reflection, buffer );
+	}
+
+	if ( mat.opacity[0] )
+	{
+		sprintf( buffer, "%s%s", curdir, mat.opacity );
+		if ( strstr( buffer, gamedir + 1 ) )
+			strcpy( mat.opacity, strstr( buffer, gamedir + 1 ) + strlen( gamedir ) - 1 );
+		else
+			strcpy( mat.opacity, buffer );
+	}
+
+	*pMat = mat;
+}
+
+static void LoadMeshMaterialGroup( FILE *fp, long thisChunkLen, _3DSMeshMaterialGroup_t *pMMG )
+{
+	_3DSMeshMaterialGroup_t mmg;
+
+	memset( &mmg, 0, sizeof( mmg ) );
+
+	ReadString( fp, mmg.name );
+
+	fread( &mmg.numFaces, sizeof( mmg.numFaces ), 1, fp );
+	mmg.pFaces = malloc( sizeof( mmg.pFaces[0] ) * mmg.numFaces );
+	fread( mmg.pFaces, sizeof( mmg.pFaces[0] ), mmg.numFaces, fp );
+
+	if ( s_verbose )
+	{
+		printf( "    >>> MESH MATERIAL GROUP '%s' (%d faces)\n", mmg.name, mmg.numFaces );
+
+		{
+			int i;
+
+			for ( i = 0; i < mmg.numFaces; i++ )
+			{
+				printf( "        %d\n", mmg.pFaces[i] );
+			}
+		}
+	}
+
+	*pMMG = mmg;
+}
+
+static void LoadNamedTriObject( FILE *fp, long thisChunkLen, _3DSTriObject_t *pTO )
+{
+	long chunkLen;
+	unsigned short chunkID;
+	int i = 0;
+	long bytesRead = 0;
+	_3DSTriObject_t triObj;
+	_3DSMeshMaterialGroup_t meshMaterialGroups[MAX_MESH_MATERIAL_GROUPS];
+	int numMeshMaterialGroups = 0;
+
+	memset( &triObj, 0, sizeof( triObj ) );
+
+	if ( s_verbose )
+		printf( "        >>> NAMED TRI OBJECT\n" );
+
+	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
+	{
+		switch ( chunkID )
+		{
+		case _3DS_CHUNK_MSH_MAT_GROUP:
+			LoadMeshMaterialGroup( fp, chunkLen - 6, &meshMaterialGroups[numMeshMaterialGroups] );
+			bytesRead += chunkLen;
+			numMeshMaterialGroups++;
+			break;
+		case _3DS_CHUNK_FACE_ARRAY:
+			fread( &triObj.numFaces, sizeof( triObj.numFaces ), 1, fp );
+			assert( triObj.pFaces == 0 );
+
+			triObj.pFaces = malloc( sizeof( triObj.pFaces[0] ) * triObj.numFaces );
+			fread( triObj.pFaces, sizeof( triObj.pFaces[0] ), triObj.numFaces, fp );
+			bytesRead += sizeof( triObj.numFaces ) + triObj.numFaces * sizeof( triObj.pFaces[0] ) + 6;
+
+			if ( s_verbose )
+			{
+				printf( "            found face array with %d faces\n", triObj.numFaces );
+				for ( i = 0; i < triObj.numFaces; i++ )
+				{
+					printf( "                %d: %d,%d,%d\n", i, triObj.pFaces[i].a, triObj.pFaces[i].b, triObj.pFaces[i].c );
+				}
+			}
+
+			break;
+		case _3DS_CHUNK_POINT_ARRAY:
+			fread( &triObj.numPoints, sizeof( triObj.numPoints ), 1, fp );
+			triObj.pPoints = malloc( sizeof( triObj.pPoints[0] ) * triObj.numPoints );
+			fread( triObj.pPoints, sizeof( triObj.pPoints[0] ), triObj.numPoints, fp );
+			bytesRead += sizeof( triObj.numPoints ) + triObj.numPoints * sizeof( triObj.pPoints[0] ) + 6;
+
+			// flip points around into our coordinate system
+			for ( i = 0; i < triObj.numPoints; i++ )
+			{
+				float x, y, z;
+
+				x = triObj.pPoints[i].x;
+				y = triObj.pPoints[i].y;
+				z = triObj.pPoints[i].z;
+
+				triObj.pPoints[i].x = -y;
+				triObj.pPoints[i].y = x;
+				triObj.pPoints[i].z = z;
+			}
+
+			if ( s_verbose )
+			{
+				printf( "            found point array with %d points\n", triObj.numPoints );
+				for ( i = 0; i < triObj.numPoints; i++ )
+				{
+					printf( "                %d: %f,%f,%f\n", i, triObj.pPoints[i].x, triObj.pPoints[i].y, triObj.pPoints[i].z );
+				}
+			}
+			break;
+		case _3DS_CHUNK_TEX_VERTS:
+			fread( &triObj.numTexVerts, sizeof( triObj.numTexVerts ), 1, fp );
+			triObj.pTexVerts = malloc( sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts );
+			fread( triObj.pTexVerts, sizeof( triObj.pTexVerts[0] ), triObj.numTexVerts, fp );
+			bytesRead += sizeof( triObj.numTexVerts ) + sizeof( triObj.pTexVerts[0] ) * triObj.numTexVerts + 6;
+
+			if ( s_verbose )
+			{
+				printf( "            found tex vert array with %d tex verts\n", triObj.numTexVerts );
+				for ( i = 0; i < triObj.numTexVerts; i++ )
+				{
+					printf( "                %d: %f,%f\n", i, triObj.pTexVerts[i].s, triObj.pTexVerts[i].t );
+				}
+			}
+			break;
+		default:
+			fread( s_buffer, chunkLen - 6, 1, fp );
+			bytesRead += chunkLen;
+			break;
+		}
+
+		if ( bytesRead >= thisChunkLen )
+			break;
+	}
+	*pTO = triObj;
+
+	if ( numMeshMaterialGroups == 0 )
+	{
+		numMeshMaterialGroups = 1;
+		strcpy( meshMaterialGroups[0].name, "(null)" );
+		if ( pTO->numTexVerts ) {
+			printf( "Warning: assigning (null) skin to tri object\n" );
+		}
+	}
+	else
+	{
+		assert( pTO->numFaces == meshMaterialGroups[0].numFaces );
+	}
+
+	pTO->pMeshMaterialGroups = malloc( sizeof( _3DSMeshMaterialGroup_t ) * numMeshMaterialGroups );
+	memcpy( pTO->pMeshMaterialGroups, meshMaterialGroups, numMeshMaterialGroups * sizeof( meshMaterialGroups[0] ) );
+	pTO->numMeshMaterialGroups = numMeshMaterialGroups;
+
+	//
+	// sanity checks
+	//
+	assert( numMeshMaterialGroups <= 1 );
+}
+
+static void LoadNamedObject( FILE *fp, long thisChunkLen, _3DSNamedObject_t *pNO )
+{
+	long chunkLen;
+	unsigned short chunkID;
+	int i = 0;
+	long bytesRead = 0;
+	char name[100];
+	_3DSTriObject_t triObj[MAX_TRI_OBJECTS];
+	int numTriObjects = 0;
+
+	memset( triObj, 0, sizeof( triObj ) );
+
+	bytesRead += ReadString( fp, name );
+
+	if ( s_verbose )
+		printf( "    >>> NAMED OBJECT '%s'\n", name );
+
+	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
+	{
+		switch ( chunkID )
+		{
+		case _3DS_CHUNK_NAMED_TRI_OBJECT:
+			LoadNamedTriObject( fp, chunkLen - 6, &triObj[numTriObjects] );
+			numTriObjects++;
+			break;
+		default:
+			fread( s_buffer, chunkLen - 6, 1, fp );
+			break;
+		}
+
+		bytesRead += chunkLen;
+
+		if ( bytesRead >= thisChunkLen )
+			break;
+	}
+
+	strcpy( pNO->name, name );
+	pNO->pTriObjects = malloc( sizeof( _3DSTriObject_t ) * numTriObjects );
+	memcpy( pNO->pTriObjects, triObj, sizeof( triObj[0] ) * numTriObjects );
+	pNO->numTriObjects = numTriObjects;
+
+	assert( numTriObjects <= 1 );
+}
+
+static void LoadEditChunk( FILE *fp, long thisChunkLen, _3DSEditChunk_t *pEC )
+{
+	unsigned short chunkID;
+	long chunkLen;
+	long bytesRead = 0;
+	_3DSEditChunk_t editChunk;
+
+	_3DSMaterial_t mat[MAX_MATERIALS];
+	_3DSNamedObject_t namedObjects[MAX_NAMED_OBJECTS];
+
+	int numMaterials = 0, numNamedObjects = 0;
+
+	memset( &editChunk, 0, sizeof( editChunk ) );
+
+	if ( s_verbose )
+		printf( ">>> EDIT CHUNK\n" );
+
+	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
+	{
+		switch ( chunkID )
+		{
+		case _3DS_CHUNK_MAT_LIST:
+			LoadMaterialList( fp, chunkLen - 6, &mat[numMaterials] );
+			numMaterials++;
+			break;
+		case _3DS_CHUNK_NAMED_OBJECT:
+			LoadNamedObject( fp, chunkLen - 6, &namedObjects[numNamedObjects] );
+			if ( namedObjects[numNamedObjects].numTriObjects != 0 )
+				++numNamedObjects;
+			break;
+		case _3DS_CHUNK_MESH_VERSION:
+		default:
+			fread( s_buffer, chunkLen - 6, 1, fp );
+			break;
+		}
+
+		bytesRead += chunkLen;
+
+		if ( bytesRead >= thisChunkLen )
+			break;
+	}
+
+	if ( numMaterials == 0 )
+	{
+		numMaterials = 1;
+		strcpy( mat[0].name, "(null)" );
+		printf( "Warning: no material definitions found\n" );
+	}
+
+	pEC->numNamedObjects = numNamedObjects;
+
+	pEC->pMaterials = malloc( sizeof( _3DSMaterial_t ) * numMaterials );
+	pEC->pNamedObjects = malloc( sizeof( _3DSNamedObject_t ) * numNamedObjects );
+
+	memcpy( pEC->pMaterials, mat, numMaterials * sizeof( mat[0] ) );
+	memcpy( pEC->pNamedObjects, namedObjects, numNamedObjects * sizeof( namedObjects[0] ) );
+}
+
+static void Load3DS( const char *filename, _3DS_t *p3DS, qboolean verbose )
+{
+	FILE *fp;
+	unsigned short chunkID;
+	long  chunkLen;
+	_3DSEditChunk_t editChunk;
+
+	s_verbose = verbose;
+
+	if ( ( fp = fopen( filename, "rb" ) ) == 0 )
+		Error( "Unable to open '%s'", filename );
+
+	// read magic number
+	if ( ( fread( &chunkID, sizeof( short ), 1, fp ) != 1 ) ||
+		 ( LittleShort( chunkID ) != _3DS_CHUNK_MAGIC ) )
+	{
+		Error( "Missing or incorrect magic number in '%s'", filename );
+	}
+	if ( fread( &chunkLen, sizeof( chunkLen ), 1, fp ) != 1 )
+		Error( "Unexpected EOF encountered in '%s'", filename );
+	// version number
+	if ( !ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
+		Error( "Missing version number in '%s'", filename );
+	if ( fread( s_buffer, chunkLen - 6, 1, fp ) != 1 )
+		Error( "Unexpected EOF encountered in '%s'", filename );
+
+	while ( ReadChunkAndLength( fp, &chunkID, &chunkLen ) )
+	{
+		switch ( chunkID )
+		{
+			case _3DS_CHUNK_EDIT:
+				LoadEditChunk( fp, chunkLen - 6, &editChunk );
+				break;
+			case _3DS_CHUNK_KEYFRAME_DATA:
+				fread( s_buffer, chunkLen - 6, 1, fp );
+				break;
+			default:
+				fread( s_buffer, chunkLen - 6, 1, fp );
+				break;
+		}
+	}
+
+	fclose( fp );
+
+	p3DS->editChunk = editChunk;
+}
+
+static void ComputeNormals( _3DSTriObject_t *pTO, triangle_t *pTris )
+{
+	vec3_t faceNormals[POLYSET_MAXTRIANGLES];
+	vec3_t vertexNormals[POLYSET_MAXTRIANGLES*3];
+	vec3_t side0, side1, facenormal;
+	int f, v;
+
+	memset( faceNormals, 0, sizeof( faceNormals ) );
+	memset( vertexNormals, 0, sizeof( vertexNormals ) );
+
+	//
+	// compute face normals
+	//
+	for ( f = 0; f < pTO->numFaces; f++ )
+	{
+		VectorSubtract( pTris[f].verts[0], pTris[f].verts[1], side0 );
+		VectorSubtract( pTris[f].verts[2], pTris[f].verts[1], side1 );
+
+		CrossProduct( side0, side1, facenormal );
+		VectorNormalize( facenormal, faceNormals[f] );
+	}
+
+	//
+	// sum vertex normals
+	//
+	for ( v = 0; v < pTO->numPoints; v++ )
+	{
+		for ( f = 0; f < pTO->numFaces; f++ )
+		{
+			if ( ( pTO->pFaces[f].a == v ) ||
+				 ( pTO->pFaces[f].b == v ) ||
+				 ( pTO->pFaces[f].c == v ) )
+			{
+				vertexNormals[v][0] += faceNormals[f][0];
+				vertexNormals[v][1] += faceNormals[f][1];
+				vertexNormals[v][2] += faceNormals[f][2];
+			}
+		}
+
+		VectorNormalize( vertexNormals[v], vertexNormals[v] );
+	}
+
+	//
+	// copy vertex normals into triangles
+	//
+	for ( f = 0; f < pTO->numFaces; f++ )
+	{
+		int i0 = pTO->pFaces[f].c;
+		int i1 = pTO->pFaces[f].b;
+		int i2 = pTO->pFaces[f].a;
+
+		VectorCopy( vertexNormals[i0], pTris[f].normals[0] );
+		VectorCopy( vertexNormals[i1], pTris[f].normals[1] );
+		VectorCopy( vertexNormals[i2], pTris[f].normals[2] );
+	}
+}
+
+/*
+** void _3DS_LoadPolysets
+*/
+void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose )
+{
+	_3DS_t _3ds;
+	int numPolysets;
+	polyset_t *pPSET;
+	triangle_t *ptri, *triangles;
+	int i;
+
+	// load the 3DS
+	memset( &_3ds, 0, sizeof( _3ds ) );
+	Load3DS( filename, &_3ds, verbose );
+
+	// compute information
+	numPolysets = _3ds.editChunk.numNamedObjects;
+
+	// allocate memory
+	pPSET = calloc( 1, numPolysets * sizeof( polyset_t ) );
+	triangles = ptri = calloc( 1, POLYSET_MAXTRIANGLES * sizeof( triangle_t ) );
+
+	// copy the data over
+	for ( i = 0; i < numPolysets; i++ )
+	{
+		char matnamebuf[1024];
+		int j;
+		triangle_t *tri;
+		_3DSTriObject_t *pTO = &_3ds.editChunk.pNamedObjects[i].pTriObjects[0];
+
+		pPSET[i].triangles = ptri;
+		pPSET[i].numtriangles = pTO->numFaces;
+		strcpy( pPSET[i].name, _3ds.editChunk.pNamedObjects[i].name );
+
+		strcpy( matnamebuf, filename );
+		if ( strrchr( matnamebuf, '/' ) )
+			*( strrchr( matnamebuf, '/' ) + 1 )= 0;
+		strcat( matnamebuf, pTO->pMeshMaterialGroups[0].name );
+
+		if ( strstr( matnamebuf, gamedir ) )
+			strcpy( pPSET[i].materialname, strstr( matnamebuf, gamedir ) + strlen( gamedir ) );
+		else
+			strcpy( pPSET[i].materialname, pTO->pMeshMaterialGroups[0].name );
+
+		assert( pPSET[i].numtriangles < POLYSET_MAXTRIANGLES );
+
+		for ( tri = ptri, j = 0; j < pPSET[i].numtriangles; j++ )
+		{
+			int i0 = pTO->pFaces[j].c;
+			int i1 = pTO->pFaces[j].b;
+			int i2 = pTO->pFaces[j].a;
+
+			tri->verts[0][0] = pTO->pPoints[i0].x;
+			tri->verts[0][1] = pTO->pPoints[i0].y;
+			tri->verts[0][2] = pTO->pPoints[i0].z;
+
+			tri->verts[1][0] = pTO->pPoints[i1].x;
+			tri->verts[1][1] = pTO->pPoints[i1].y;
+			tri->verts[1][2] = pTO->pPoints[i1].z;
+
+			tri->verts[2][0] = pTO->pPoints[i2].x;
+			tri->verts[2][1] = pTO->pPoints[i2].y;
+			tri->verts[2][2] = pTO->pPoints[i2].z;
+/*
+			for ( k = 0; k < 3; k++ )
+			{
+				tri->colors[0][k] = 1;
+				tri->colors[1][k] = 1;
+				tri->colors[2][k] = 1;
+			}
+*/
+
+			if ( pTO->pTexVerts )
+			{
+				tri->texcoords[0][0] = pTO->pTexVerts[i0].s;
+				tri->texcoords[0][1] = 1.0f - pTO->pTexVerts[i0].t;
+				tri->texcoords[1][0] = pTO->pTexVerts[i1].s;
+				tri->texcoords[1][1] = 1.0f - pTO->pTexVerts[i1].t;
+				tri->texcoords[2][0] = pTO->pTexVerts[i2].s;
+				tri->texcoords[2][1] = 1.0f - pTO->pTexVerts[i2].t;
+			}
+
+			tri++;
+		}
+
+		ptri += pPSET[i].numtriangles;
+		assert( ptri - triangles < POLYSET_MAXTRIANGLES );
+	}
+
+	// compute normal data
+#if 0
+	for ( i = 0; i < numPolysets; i++ )
+	{
+		// unique vertices based solely on vertex position
+		ComputeNormals( &_3ds.editChunk.pNamedObjects[i].pTriObjects[0],
+						 pPSET[i].triangles );
+	}
+#endif
+
+	free( _3ds.editChunk.pMaterials );
+	free( _3ds.editChunk.pNamedObjects );
+
+	*ppPSET = pPSET;
+	*numpsets = numPolysets;
+}
diff --git a/tools/quake3/q3data/3dslib.h b/tools/quake3/q3data/3dslib.h
index 96757234..cd73cb43 100644
--- a/tools/quake3/q3data/3dslib.h
+++ b/tools/quake3/q3data/3dslib.h
@@ -1,118 +1,118 @@
-typedef struct
-{
-	float x, y, z;
-} _3DSPoint_t;
-
-typedef struct
-{
-	short a, b, c;
-	short flags;
-} _3DSFace_t;
-
-typedef struct
-{
-	float s, t;
-} _3DSTexVert_t;
-
-typedef struct
-{
-	char name[100];
-	short numFaces;
-	short *pFaces;
-} _3DSMeshMaterialGroup_t;
-
-typedef struct
-{
-	char name[80];
-
-	char texture[100];
-	char specular[100];
-	char reflection[100];
-	char bump[100];
-	char opacity[100];
-} _3DSMaterial_t;
-
-typedef struct
-{
-	short numFaces, numPoints, numTexVerts;
-	int numMeshMaterialGroups;
-
-	_3DSPoint_t *pPoints;
-	_3DSFace_t	*pFaces;
-	_3DSTexVert_t *pTexVerts;
-
-	_3DSMeshMaterialGroup_t *pMeshMaterialGroups;
-} _3DSTriObject_t;
-
-typedef struct
-{
-	char name[100];
-
-	int				 numTriObjects;
-	_3DSTriObject_t *pTriObjects;
-} _3DSNamedObject_t;
-
-typedef struct
-{
-	int					numNamedObjects;
-	int					numMaterials;
-
-	_3DSNamedObject_t	*pNamedObjects;
-	_3DSMaterial_t		*pMaterials;
-
-} _3DSEditChunk_t;
-
-typedef struct
-{
-	_3DSEditChunk_t editChunk;
-} _3DS_t;
-
-#define _3DS_CHUNK_NULL						0x0000
-#define _3DS_CHUNK_UNKNOWN0					0x0001
-#define _3DS_CHUNK_M3D_VERSION				0x0002
-#define _3DS_CHUNK_M3D_KFVERSION			0x0005
-#define _3DS_CHUNK_COLOR_F					0x0010
-#define _3DS_CHUNK_COLOR_24					0x0011
-#define _3DS_CHUNK_LIN_COLOR_24				0x0012
-#define _3DS_CHUNK_LIN_COLOR_F				0x0013
-#define _3DS_CHUNK_INT_PERCENTAGE			0x0030
-#define _3DS_CHUNK_FLOAT_PERCENT			0x0031
-#define _3DS_CHUNK_MASTER_SCALE				0x0100
-#define _3DS_CHUNK_CHUNK_TYPE				0x0995
-#define _3DS_CHUNK_CHUNK_UNIQUE				0x0996
-#define _3DS_CHUNK_NOT_CHUNK				0x0997
-#define _3DS_CHUNK_CONTAINER				0x0998
-#define _3DS_CHUNK_IS_CHUNK					0x0999
-#define _3DS_CHUNK_C_SXP_SELFI_MASKDATA		0x0c3c
-
-#define _3DS_CHUNK_BITMAP					0x1100
-#define _3DS_CHUNK_USE_BITMAP				0x1101
-#define _3DS_CHUNK_SOLID_BGND				0x1200
-#define _3DS_CHUNK_USE_SOLID_BGND			0x1201
-
-#define _3DS_CHUNK_EDIT						0x3d3d
-#define _3DS_CHUNK_MESH_VERSION				0x3d3e
-
-#define _3DS_CHUNK_NAMED_OBJECT				0x4000
-#define _3DS_CHUNK_NAMED_TRI_OBJECT			0x4100
-#define _3DS_CHUNK_POINT_ARRAY				0x4110
-#define _3DS_CHUNK_POINT_FLAG_ARRAY			0x4111
-#define _3DS_CHUNK_FACE_ARRAY				0x4120
-#define _3DS_CHUNK_MSH_MAT_GROUP			0x4130
-#define _3DS_CHUNK_TEX_VERTS				0x4140
-#define _3DS_CHUNK_SMOOTH_GROUP				0x4150
-#define _3DS_CHUNK_MESH_MATRIX				0x4160
-#define _3DS_CHUNK_MAGIC					0x4d4d
-
-#define _3DS_CHUNK_MAT_NAME					0xa000
-#define _3DS_CHUNK_TEXMAP					0xa200
-#define _3DS_CHUNK_SPECMAP					0xa204
-#define _3DS_CHUNK_OPACMAP					0xa210
-#define _3DS_CHUNK_REFLMAP					0xa220
-#define _3DS_CHUNK_BUMPMAP					0xa230
-#define _3DS_CHUNK_MAT_MAPNAME				0xa300
-#define _3DS_CHUNK_MAT_LIST					0xafff
-
-#define _3DS_CHUNK_KEYFRAME_DATA			0xb000
-
-void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose );
+typedef struct
+{
+	float x, y, z;
+} _3DSPoint_t;
+
+typedef struct
+{
+	short a, b, c;
+	short flags;
+} _3DSFace_t;
+
+typedef struct
+{
+	float s, t;
+} _3DSTexVert_t;
+
+typedef struct
+{
+	char name[100];
+	short numFaces;
+	short *pFaces;
+} _3DSMeshMaterialGroup_t;
+
+typedef struct
+{
+	char name[80];
+
+	char texture[100];
+	char specular[100];
+	char reflection[100];
+	char bump[100];
+	char opacity[100];
+} _3DSMaterial_t;
+
+typedef struct
+{
+	short numFaces, numPoints, numTexVerts;
+	int numMeshMaterialGroups;
+
+	_3DSPoint_t *pPoints;
+	_3DSFace_t	*pFaces;
+	_3DSTexVert_t *pTexVerts;
+
+	_3DSMeshMaterialGroup_t *pMeshMaterialGroups;
+} _3DSTriObject_t;
+
+typedef struct
+{
+	char name[100];
+
+	int				 numTriObjects;
+	_3DSTriObject_t *pTriObjects;
+} _3DSNamedObject_t;
+
+typedef struct
+{
+	int					numNamedObjects;
+	int					numMaterials;
+
+	_3DSNamedObject_t	*pNamedObjects;
+	_3DSMaterial_t		*pMaterials;
+
+} _3DSEditChunk_t;
+
+typedef struct
+{
+	_3DSEditChunk_t editChunk;
+} _3DS_t;
+
+#define _3DS_CHUNK_NULL						0x0000
+#define _3DS_CHUNK_UNKNOWN0					0x0001
+#define _3DS_CHUNK_M3D_VERSION				0x0002
+#define _3DS_CHUNK_M3D_KFVERSION			0x0005
+#define _3DS_CHUNK_COLOR_F					0x0010
+#define _3DS_CHUNK_COLOR_24					0x0011
+#define _3DS_CHUNK_LIN_COLOR_24				0x0012
+#define _3DS_CHUNK_LIN_COLOR_F				0x0013
+#define _3DS_CHUNK_INT_PERCENTAGE			0x0030
+#define _3DS_CHUNK_FLOAT_PERCENT			0x0031
+#define _3DS_CHUNK_MASTER_SCALE				0x0100
+#define _3DS_CHUNK_CHUNK_TYPE				0x0995
+#define _3DS_CHUNK_CHUNK_UNIQUE				0x0996
+#define _3DS_CHUNK_NOT_CHUNK				0x0997
+#define _3DS_CHUNK_CONTAINER				0x0998
+#define _3DS_CHUNK_IS_CHUNK					0x0999
+#define _3DS_CHUNK_C_SXP_SELFI_MASKDATA		0x0c3c
+
+#define _3DS_CHUNK_BITMAP					0x1100
+#define _3DS_CHUNK_USE_BITMAP				0x1101
+#define _3DS_CHUNK_SOLID_BGND				0x1200
+#define _3DS_CHUNK_USE_SOLID_BGND			0x1201
+
+#define _3DS_CHUNK_EDIT						0x3d3d
+#define _3DS_CHUNK_MESH_VERSION				0x3d3e
+
+#define _3DS_CHUNK_NAMED_OBJECT				0x4000
+#define _3DS_CHUNK_NAMED_TRI_OBJECT			0x4100
+#define _3DS_CHUNK_POINT_ARRAY				0x4110
+#define _3DS_CHUNK_POINT_FLAG_ARRAY			0x4111
+#define _3DS_CHUNK_FACE_ARRAY				0x4120
+#define _3DS_CHUNK_MSH_MAT_GROUP			0x4130
+#define _3DS_CHUNK_TEX_VERTS				0x4140
+#define _3DS_CHUNK_SMOOTH_GROUP				0x4150
+#define _3DS_CHUNK_MESH_MATRIX				0x4160
+#define _3DS_CHUNK_MAGIC					0x4d4d
+
+#define _3DS_CHUNK_MAT_NAME					0xa000
+#define _3DS_CHUNK_TEXMAP					0xa200
+#define _3DS_CHUNK_SPECMAP					0xa204
+#define _3DS_CHUNK_OPACMAP					0xa210
+#define _3DS_CHUNK_REFLMAP					0xa220
+#define _3DS_CHUNK_BUMPMAP					0xa230
+#define _3DS_CHUNK_MAT_MAPNAME				0xa300
+#define _3DS_CHUNK_MAT_LIST					0xafff
+
+#define _3DS_CHUNK_KEYFRAME_DATA			0xb000
+
+void _3DS_LoadPolysets( const char *filename, polyset_t **ppPSET, int *numpsets, qboolean verbose );
diff --git a/tools/quake3/q3data/compress.c b/tools/quake3/q3data/compress.c
index ede2a95e..af9669ab 100644
--- a/tools/quake3/q3data/compress.c
+++ b/tools/quake3/q3data/compress.c
@@ -1,750 +1,750 @@
-#include "q3data.h"
-
-#if 0
-/*
-==================
-MTF
-==================
-*/
-cblock_t MTF (cblock_t in)
-{
-	int			i, j, b, code;
-	byte		*out_p;
-	int			index[256];
-	cblock_t	out;
-
-	out_p = out.data = malloc(in.count + 4);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	for (i=0 ; i<256 ; i++)
-		index[i] = i;
-
-	for (i=0 ; i<in.count ; i++)
-	{
-		b = in.data[i];
-		code = index[b];
-		*out_p++ = code;
-		
-		// shuffle b indexes to 0
-		for (j=0 ; j<256 ; j++)
-			if (index[j] < code)
-				index[j]++;
-		index[b] = 0;
-	}
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-
-//==========================================================================
-
-int		bwt_size;
-byte	*bwt_data;
-
-int bwtCompare (const void *elem1, const void *elem2)
-{
-	int		i;
-	int		i1, i2;
-	int		b1, b2;
-
-	i1 = *(int *)elem1;
-	i2 = *(int *)elem2;
-
-	for (i=0 ; i<bwt_size ; i++)
-	{
-		b1 = bwt_data[i1];
-		b2 = bwt_data[i2];
-		if (b1 < b2)
-			return -1;
-		if (b1 > b2)
-			return 1;
-		if (++i1 == bwt_size)
-			i1 = 0;
-		if (++i2 == bwt_size)
-			i2 = 0;
-	}
-
-	return 0;
-}
-
-/*
-==================
-BWT
-==================
-*/
-cblock_t BWT (cblock_t in)
-{
-	int		*sorted;
-	int		i;
-	byte	*out_p;
-	cblock_t	out;
-
-	bwt_size = in.count;
-	bwt_data = in.data;
-
-	sorted = malloc(in.count*sizeof(*sorted));
-	for (i=0 ; i<in.count ; i++)
-		sorted[i] = i;
-	qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
-
-	out_p = out.data = malloc(in.count + 8);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	// write head index
-	for (i=0 ; i<in.count ; i++)
-		if (sorted[i] == 0)
-			break;
-	*out_p++ = i&255;
-	*out_p++ = (i>>8)&255;
-	*out_p++ = (i>>16)&255;
-	*out_p++ = (i>>24)&255;
-
-	// write the L column
-	for (i=0 ; i<in.count ; i++)
-		*out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
-
-	free (sorted);
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-//==========================================================================
-
-typedef struct hnode_s
-{
-	int			count;
-	qboolean	used;
-	int			children[2];
-} hnode_t;
-
-int			numhnodes;
-hnode_t		hnodes[512];
-unsigned	charbits[256];
-int			charbitscount[256];
-
-int	SmallestNode (void)
-{
-	int		i;
-	int		best, bestnode;
-
-	best = 99999999;
-	bestnode = -1;
-	for (i=0 ; i<numhnodes ; i++)
-	{
-		if (hnodes[i].used)
-			continue;
-		if (!hnodes[i].count)
-			continue;
-		if (hnodes[i].count < best)
-		{
-			best = hnodes[i].count;
-			bestnode = i;
-		}
-	}
-
-	if (bestnode == -1)
-		return -1;
-
-	hnodes[bestnode].used = true;
-	return bestnode;
-}
-
-void BuildChars (int nodenum, unsigned bits, int bitcount)
-{
-	hnode_t	*node;
-
-	if (nodenum < 256)
-	{
-		if (bitcount > 32)
-			Error ("bitcount > 32");
-		charbits[nodenum] = bits;
-		charbitscount[nodenum] = bitcount;
-		return;
-	}
-
-	node = &hnodes[nodenum];
-	bits <<= 1;
-	BuildChars (node->children[0], bits, bitcount+1);
-	bits |= 1;
-	BuildChars (node->children[1], bits, bitcount+1);
-}
-
-/*
-==================
-Huffman
-==================
-*/
-cblock_t Huffman (cblock_t in)
-{
-	int			i;
-	hnode_t		*node;
-	int			outbits, c;
-	unsigned	bits;
-	byte		*out_p;
-	cblock_t	out;
-	int			max, maxchar;
-
-	// count
-	memset (hnodes, 0, sizeof(hnodes));
-	for (i=0 ; i<in.count ; i++)
-		hnodes[in.data[i]].count++;
-
-	// normalize counts
-	max = 0;
-	maxchar = 0;
-	for (i=0 ; i<256 ; i++)
-	{
-		if (hnodes[i].count > max)
-		{
-			max = hnodes[i].count;
-			maxchar = i;
-		}
-	}
-	if (max == 0)
-		Error ("Huffman: max == 0");
-
-	for (i=0 ; i<256 ; i++)
-	{
-		hnodes[i].count = (hnodes[i].count*255+max-1) / max;
-	}
-
-	// build the nodes
-	numhnodes = 256;
-	while (numhnodes != 511)
-	{
-		node = &hnodes[numhnodes];
-
-		// pick two lowest counts
-		node->children[0] = SmallestNode ();
-		if (node->children[0] == -1)
-			break;	// no more
-
-		node->children[1] = SmallestNode ();
-		if (node->children[1] == -1)
-		{
-			if (node->children[0] != numhnodes-1)
-				Error ("Bad smallestnode");
-			break;
-		}
-		node->count = hnodes[node->children[0]].count + 
-			hnodes[node->children[1]].count;
-		numhnodes++;
-	}
-
-	BuildChars (numhnodes-1, 0, 0);
-
-	out_p = out.data = malloc(in.count*2 + 1024);
-	memset (out_p, 0, in.count*2+1024);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	// save out the 256 normalized counts so the tree can be recreated
-	for (i=0 ; i<256 ; i++)
-		*out_p++ = hnodes[i].count;
-
-	// write bits
-	outbits = 0;
-	for (i=0 ; i<in.count ; i++)
-	{
-		c = charbitscount[in.data[i]];
-		bits = charbits[in.data[i]];
-		while (c)
-		{
-			c--;
-			if (bits & (1<<c))
-				out_p[outbits>>3] |= 1<<(outbits&7);
-			outbits++;
-		}
-	}
-
-	out_p += (outbits+7)>>3;
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-//==========================================================================
-
-/*
-==================
-RLE
-==================
-*/
-#define	RLE_CODE	0xe8
-#define	RLE_TRIPPLE	0xe9
-
-int	rle_counts[256];
-int	rle_bytes[256];
-
-cblock_t RLE (cblock_t in)
-{
-	int		i;
-	byte	*out_p;
-	int		val;
-	int		repeat;
-	cblock_t	out;
-
-	out_p = out.data = malloc (in.count*2);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	for (i=0 ; i<in.count ; )
-	{
-		val = in.data[i];
-		rle_bytes[val]++;
-		repeat = 1;
-		i++;
-		while (i<in.count && repeat < 255 && in.data[i] == val)
-		{
-			repeat++;
-			i++;
-		}
-if (repeat < 256)
-rle_counts[repeat]++;
-		if (repeat > 3 || val == RLE_CODE)
-		{
-			*out_p++ = RLE_CODE;
-			*out_p++ = val;
-			*out_p++ = repeat;
-		}
-		else
-		{
-			while (repeat--)
-				*out_p++ = val;
-		}
-	}
-
-	out.count = out_p - out.data;
-	return out;
-}
-
-//==========================================================================
-
-unsigned	lzss_head[256];
-unsigned	lzss_next[0x20000];
-
-/*
-==================
-LZSS
-==================
-*/
-#define	BACK_WINDOW		0x10000
-#define	BACK_BITS		16
-#define	FRONT_WINDOW	16
-#define	FRONT_BITS		4
-cblock_t LZSS (cblock_t in)
-{
-	int		i;
-	byte	*out_p;
-	cblock_t	out;
-	int		val;
-	int		j, start, max;
-	int		bestlength, beststart;
-	int		outbits;
-
-if (in.count >= sizeof(lzss_next)/4)
-Error ("LZSS: too big");
-
-	memset (lzss_head, -1, sizeof(lzss_head));
-
-	out_p = out.data = malloc (in.count*2);
-	memset (out.data, 0, in.count*2);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	outbits = 0;
-	for (i=0 ; i<in.count ; )
-	{
-		val = in.data[i];
-#if 1
-// chained search
-		bestlength = 0;
-		beststart = 0;
-
-		max = FRONT_WINDOW;
-		if (i + max > in.count)
-			max = in.count - i;
-
-		start = lzss_head[val];
-		while (start != -1 && start >= i-BACK_WINDOW)
-		{			
-			// count match length
-			for (j=0 ; j<max ; j++)
-				if (in.data[start+j] != in.data[i+j])
-					break;
-			if (j > bestlength)
-			{
-				bestlength = j;
-				beststart = start;
-			}
-			start = lzss_next[start];
-		}
-
-#else
-// slow simple search
-		// search for a match
-		max = FRONT_WINDOW;
-		if (i + max > in.count)
-			max = in.count - i;
-
-		start = i - BACK_WINDOW;
-		if (start < 0)
-			start = 0;
-		bestlength = 0;
-		beststart = 0;
-		for ( ; start < i ; start++)
-		{
-			if (in.data[start] != val)
-				continue;
-			// count match length
-			for (j=0 ; j<max ; j++)
-				if (in.data[start+j] != in.data[i+j])
-					break;
-			if (j > bestlength)
-			{
-				bestlength = j;
-				beststart = start;
-			}
-		}
-#endif
-		beststart = BACK_WINDOW - (i-beststart);
-
-		if (bestlength < 3)
-		{	// output a single char
-			bestlength = 1;
-
-			out_p[outbits>>3] |= 1<<(outbits&7);	// set bit to mark char
-			outbits++;
-			for (j=0 ; j<8 ; j++, outbits++)
-				if (val & (1<<j) )
-					out_p[outbits>>3] |= 1<<(outbits&7);
-		}
-		else
-		{	// output a phrase
-			outbits++;	// leave a 0 bit to mark phrase
-			for (j=0 ; j<BACK_BITS ; j++, outbits++)
-				if (beststart & (1<<j) )
-					out_p[outbits>>3] |= 1<<(outbits&7);
-			for (j=0 ; j<FRONT_BITS ; j++, outbits++)
-				if (bestlength & (1<<j) )
-					out_p[outbits>>3] |= 1<<(outbits&7);
-		}
-
-		while (bestlength--)
-		{
-			val = in.data[i];
-			lzss_next[i] = lzss_head[val];
-			lzss_head[val] = i;
-			i++;
-		}
-	}
-
-	out_p += (outbits+7)>>3;
-	out.count = out_p - out.data;
-	return out;
-}
-
-//==========================================================================
-
-#define	MIN_REPT	15
-#define	MAX_REPT	0
-#define	HUF_TOKENS	(256+MAX_REPT)
-
-unsigned	charbits1[256][HUF_TOKENS];
-int			charbitscount1[256][HUF_TOKENS];
-
-hnode_t		hnodes1[256][HUF_TOKENS*2];
-int			numhnodes1[256];
-
-int			order0counts[256];
-
-/*
-==================
-SmallestNode1
-==================
-*/
-int	SmallestNode1 (hnode_t *hnodes, int numhnodes)
-{
-	int		i;
-	int		best, bestnode;
-
-	best = 99999999;
-	bestnode = -1;
-	for (i=0 ; i<numhnodes ; i++)
-	{
-		if (hnodes[i].used)
-			continue;
-		if (!hnodes[i].count)
-			continue;
-		if (hnodes[i].count < best)
-		{
-			best = hnodes[i].count;
-			bestnode = i;
-		}
-	}
-
-	if (bestnode == -1)
-		return -1;
-
-	hnodes[bestnode].used = true;
-	return bestnode;
-}
-
-
-/*
-==================
-BuildChars1
-==================
-*/
-void BuildChars1 (int prev, int nodenum, unsigned bits, int bitcount)
-{
-	hnode_t	*node;
-
-	if (nodenum < HUF_TOKENS)
-	{
-		if (bitcount > 32)
-			Error ("bitcount > 32");
-		charbits1[prev][nodenum] = bits;
-		charbitscount1[prev][nodenum] = bitcount;
-		return;
-	}
-
-	node = &hnodes1[prev][nodenum];
-	bits <<= 1;
-	BuildChars1 (prev, node->children[0], bits, bitcount+1);
-	bits |= 1;
-	BuildChars1 (prev, node->children[1], bits, bitcount+1);
-}
-
-
-/*
-==================
-BuildTree1
-==================
-*/
-void BuildTree1 (int prev)
-{
-	hnode_t		*node, *nodebase;
-	int			numhnodes;
-
-	// build the nodes
-	numhnodes = HUF_TOKENS;
-	nodebase = hnodes1[prev];
-	while (1)
-	{
-		node = &nodebase[numhnodes];
-
-		// pick two lowest counts
-		node->children[0] = SmallestNode1 (nodebase, numhnodes);
-		if (node->children[0] == -1)
-			break;	// no more
-
-		node->children[1] = SmallestNode1 (nodebase, numhnodes);
-		if (node->children[1] == -1)
-			break;
-
-		node->count = nodebase[node->children[0]].count + 
-			nodebase[node->children[1]].count;
-		numhnodes++;
-	}
-	numhnodes1[prev] = numhnodes-1;
-	BuildChars1 (prev, numhnodes-1, 0, 0);
-}
-
-
-/*
-==================
-Huffman1_Count
-==================
-*/
-void Huffman1_Count (cblock_t in)
-{
-	int		i;
-	int		prev;
-	int		v;
-	int		rept;
-
-	prev = 0;
-	for (i=0 ; i<in.count ; i++)
-	{
-		v = in.data[i];
-		order0counts[v]++;
-		hnodes1[prev][v].count++;
-		prev = v;
-#if 1
-		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
-			if (in.data[i+rept] != v)
-				break;
-		if (rept > MIN_REPT)
-		{
-			hnodes1[prev][255+rept].count++;
-			i += rept-1;
-		}
-#endif
-	}
-}
-
-
-/*
-==================
-Huffman1_Build
-==================
-*/
-byte	scaled[256][HUF_TOKENS];
-void Huffman1_Build (FILE *f)
-{
-	int		i, j, v;
-	int		max;
-	int		total;
-
-	for (i=0 ; i<256 ; i++)
-	{
-		// normalize and save the counts
-		max = 0;
-		for (j=0 ; j<HUF_TOKENS ; j++)
-		{
-			if (hnodes1[i][j].count > max)
-				max = hnodes1[i][j].count;
-		}
-		if (max == 0)
-			max = 1;
-		total = 0;
-		for (j=0 ; j<HUF_TOKENS ; j++)
-		{	// easy to overflow 32 bits here!
-			v = (hnodes1[i][j].count*(double)255+max-1)/max;
-			if (v > 255)
-				Error ("v > 255");
-			scaled[i][j] = hnodes1[i][j].count = v;
-			if (v)
-				total++;
-		}
-		if (total == 1)
-		{	// must have two tokens
-			if (!scaled[i][0])
-				scaled[i][0] = hnodes1[i][0].count = 1;
-			else
-				scaled[i][1] = hnodes1[i][1].count = 1;
-		}
-
-		BuildTree1 (i);
-	}
-
-#if 0
-	// count up the total bits
-	total = 0;
-	for (i=0 ; i<256 ; i++)
-		for (j=0 ; j<256 ; j++)
-			total += charbitscount1[i][j] * hnodes1[i][j].count;
-
-	total = (total+7)/8;
-	printf ("%i bytes huffman1 compressed\n", total);
-#endif
-
-	fwrite (scaled, 1, sizeof(scaled), f);
-}
-
-/*
-==================
-Huffman1
-
-Order 1 compression with pre-built table
-==================
-*/
-cblock_t Huffman1 (cblock_t in)
-{
-	int			i;
-	int			outbits, c;
-	unsigned	bits;
-	byte		*out_p;
-	cblock_t	out;
-	int			prev;
-	int			v;
-	int			rept;
-
-	out_p = out.data = malloc(in.count*2 + 1024);
-	memset (out_p, 0, in.count*2+1024);
-
-	// write count
-	*out_p++ = in.count&255;
-	*out_p++ = (in.count>>8)&255;
-	*out_p++ = (in.count>>16)&255;
-	*out_p++ = (in.count>>24)&255;
-
-	// write bits
-	outbits = 0;
-	prev = 0;
-	for (i=0 ; i<in.count ; i++)
-	{
-		v = in.data[i];
-
-		c = charbitscount1[prev][v];
-		bits = charbits1[prev][v];
-		if (!c)
-			Error ("!bits");
-		while (c)
-		{
-			c--;
-			if (bits & (1<<c))
-				out_p[outbits>>3] |= 1<<(outbits&7);
-			outbits++;
-		}
-
-		prev = v;
-#if 1
-		// check for repeat encodes
-		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
-			if (in.data[i+rept] != v)
-				break;
-		if (rept > MIN_REPT)
-		{
-			c = charbitscount1[prev][255+rept];
-			bits = charbits1[prev][255+rept];
-			if (!c)
-				Error ("!bits");
-			while (c)
-			{
-				c--;
-				if (bits & (1<<c))
-					out_p[outbits>>3] |= 1<<(outbits&7);
-				outbits++;
-			}
-			i += rept-1;
-		}
-#endif
-	}
-
-	out_p += (outbits+7)>>3;
-
-	out.count = out_p - out.data;
-
-	return out;
-}
-
-#endif
+#include "q3data.h"
+
+#if 0
+/*
+==================
+MTF
+==================
+*/
+cblock_t MTF (cblock_t in)
+{
+	int			i, j, b, code;
+	byte		*out_p;
+	int			index[256];
+	cblock_t	out;
+
+	out_p = out.data = malloc(in.count + 4);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	for (i=0 ; i<256 ; i++)
+		index[i] = i;
+
+	for (i=0 ; i<in.count ; i++)
+	{
+		b = in.data[i];
+		code = index[b];
+		*out_p++ = code;
+		
+		// shuffle b indexes to 0
+		for (j=0 ; j<256 ; j++)
+			if (index[j] < code)
+				index[j]++;
+		index[b] = 0;
+	}
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+
+//==========================================================================
+
+int		bwt_size;
+byte	*bwt_data;
+
+int bwtCompare (const void *elem1, const void *elem2)
+{
+	int		i;
+	int		i1, i2;
+	int		b1, b2;
+
+	i1 = *(int *)elem1;
+	i2 = *(int *)elem2;
+
+	for (i=0 ; i<bwt_size ; i++)
+	{
+		b1 = bwt_data[i1];
+		b2 = bwt_data[i2];
+		if (b1 < b2)
+			return -1;
+		if (b1 > b2)
+			return 1;
+		if (++i1 == bwt_size)
+			i1 = 0;
+		if (++i2 == bwt_size)
+			i2 = 0;
+	}
+
+	return 0;
+}
+
+/*
+==================
+BWT
+==================
+*/
+cblock_t BWT (cblock_t in)
+{
+	int		*sorted;
+	int		i;
+	byte	*out_p;
+	cblock_t	out;
+
+	bwt_size = in.count;
+	bwt_data = in.data;
+
+	sorted = malloc(in.count*sizeof(*sorted));
+	for (i=0 ; i<in.count ; i++)
+		sorted[i] = i;
+	qsort (sorted, in.count, sizeof(*sorted), bwtCompare);
+
+	out_p = out.data = malloc(in.count + 8);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	// write head index
+	for (i=0 ; i<in.count ; i++)
+		if (sorted[i] == 0)
+			break;
+	*out_p++ = i&255;
+	*out_p++ = (i>>8)&255;
+	*out_p++ = (i>>16)&255;
+	*out_p++ = (i>>24)&255;
+
+	// write the L column
+	for (i=0 ; i<in.count ; i++)
+		*out_p++ = in.data[(sorted[i]+in.count-1)%in.count];
+
+	free (sorted);
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+//==========================================================================
+
+typedef struct hnode_s
+{
+	int			count;
+	qboolean	used;
+	int			children[2];
+} hnode_t;
+
+int			numhnodes;
+hnode_t		hnodes[512];
+unsigned	charbits[256];
+int			charbitscount[256];
+
+int	SmallestNode (void)
+{
+	int		i;
+	int		best, bestnode;
+
+	best = 99999999;
+	bestnode = -1;
+	for (i=0 ; i<numhnodes ; i++)
+	{
+		if (hnodes[i].used)
+			continue;
+		if (!hnodes[i].count)
+			continue;
+		if (hnodes[i].count < best)
+		{
+			best = hnodes[i].count;
+			bestnode = i;
+		}
+	}
+
+	if (bestnode == -1)
+		return -1;
+
+	hnodes[bestnode].used = true;
+	return bestnode;
+}
+
+void BuildChars (int nodenum, unsigned bits, int bitcount)
+{
+	hnode_t	*node;
+
+	if (nodenum < 256)
+	{
+		if (bitcount > 32)
+			Error ("bitcount > 32");
+		charbits[nodenum] = bits;
+		charbitscount[nodenum] = bitcount;
+		return;
+	}
+
+	node = &hnodes[nodenum];
+	bits <<= 1;
+	BuildChars (node->children[0], bits, bitcount+1);
+	bits |= 1;
+	BuildChars (node->children[1], bits, bitcount+1);
+}
+
+/*
+==================
+Huffman
+==================
+*/
+cblock_t Huffman (cblock_t in)
+{
+	int			i;
+	hnode_t		*node;
+	int			outbits, c;
+	unsigned	bits;
+	byte		*out_p;
+	cblock_t	out;
+	int			max, maxchar;
+
+	// count
+	memset (hnodes, 0, sizeof(hnodes));
+	for (i=0 ; i<in.count ; i++)
+		hnodes[in.data[i]].count++;
+
+	// normalize counts
+	max = 0;
+	maxchar = 0;
+	for (i=0 ; i<256 ; i++)
+	{
+		if (hnodes[i].count > max)
+		{
+			max = hnodes[i].count;
+			maxchar = i;
+		}
+	}
+	if (max == 0)
+		Error ("Huffman: max == 0");
+
+	for (i=0 ; i<256 ; i++)
+	{
+		hnodes[i].count = (hnodes[i].count*255+max-1) / max;
+	}
+
+	// build the nodes
+	numhnodes = 256;
+	while (numhnodes != 511)
+	{
+		node = &hnodes[numhnodes];
+
+		// pick two lowest counts
+		node->children[0] = SmallestNode ();
+		if (node->children[0] == -1)
+			break;	// no more
+
+		node->children[1] = SmallestNode ();
+		if (node->children[1] == -1)
+		{
+			if (node->children[0] != numhnodes-1)
+				Error ("Bad smallestnode");
+			break;
+		}
+		node->count = hnodes[node->children[0]].count + 
+			hnodes[node->children[1]].count;
+		numhnodes++;
+	}
+
+	BuildChars (numhnodes-1, 0, 0);
+
+	out_p = out.data = malloc(in.count*2 + 1024);
+	memset (out_p, 0, in.count*2+1024);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	// save out the 256 normalized counts so the tree can be recreated
+	for (i=0 ; i<256 ; i++)
+		*out_p++ = hnodes[i].count;
+
+	// write bits
+	outbits = 0;
+	for (i=0 ; i<in.count ; i++)
+	{
+		c = charbitscount[in.data[i]];
+		bits = charbits[in.data[i]];
+		while (c)
+		{
+			c--;
+			if (bits & (1<<c))
+				out_p[outbits>>3] |= 1<<(outbits&7);
+			outbits++;
+		}
+	}
+
+	out_p += (outbits+7)>>3;
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+//==========================================================================
+
+/*
+==================
+RLE
+==================
+*/
+#define	RLE_CODE	0xe8
+#define	RLE_TRIPPLE	0xe9
+
+int	rle_counts[256];
+int	rle_bytes[256];
+
+cblock_t RLE (cblock_t in)
+{
+	int		i;
+	byte	*out_p;
+	int		val;
+	int		repeat;
+	cblock_t	out;
+
+	out_p = out.data = malloc (in.count*2);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	for (i=0 ; i<in.count ; )
+	{
+		val = in.data[i];
+		rle_bytes[val]++;
+		repeat = 1;
+		i++;
+		while (i<in.count && repeat < 255 && in.data[i] == val)
+		{
+			repeat++;
+			i++;
+		}
+if (repeat < 256)
+rle_counts[repeat]++;
+		if (repeat > 3 || val == RLE_CODE)
+		{
+			*out_p++ = RLE_CODE;
+			*out_p++ = val;
+			*out_p++ = repeat;
+		}
+		else
+		{
+			while (repeat--)
+				*out_p++ = val;
+		}
+	}
+
+	out.count = out_p - out.data;
+	return out;
+}
+
+//==========================================================================
+
+unsigned	lzss_head[256];
+unsigned	lzss_next[0x20000];
+
+/*
+==================
+LZSS
+==================
+*/
+#define	BACK_WINDOW		0x10000
+#define	BACK_BITS		16
+#define	FRONT_WINDOW	16
+#define	FRONT_BITS		4
+cblock_t LZSS (cblock_t in)
+{
+	int		i;
+	byte	*out_p;
+	cblock_t	out;
+	int		val;
+	int		j, start, max;
+	int		bestlength, beststart;
+	int		outbits;
+
+if (in.count >= sizeof(lzss_next)/4)
+Error ("LZSS: too big");
+
+	memset (lzss_head, -1, sizeof(lzss_head));
+
+	out_p = out.data = malloc (in.count*2);
+	memset (out.data, 0, in.count*2);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	outbits = 0;
+	for (i=0 ; i<in.count ; )
+	{
+		val = in.data[i];
+#if 1
+// chained search
+		bestlength = 0;
+		beststart = 0;
+
+		max = FRONT_WINDOW;
+		if (i + max > in.count)
+			max = in.count - i;
+
+		start = lzss_head[val];
+		while (start != -1 && start >= i-BACK_WINDOW)
+		{			
+			// count match length
+			for (j=0 ; j<max ; j++)
+				if (in.data[start+j] != in.data[i+j])
+					break;
+			if (j > bestlength)
+			{
+				bestlength = j;
+				beststart = start;
+			}
+			start = lzss_next[start];
+		}
+
+#else
+// slow simple search
+		// search for a match
+		max = FRONT_WINDOW;
+		if (i + max > in.count)
+			max = in.count - i;
+
+		start = i - BACK_WINDOW;
+		if (start < 0)
+			start = 0;
+		bestlength = 0;
+		beststart = 0;
+		for ( ; start < i ; start++)
+		{
+			if (in.data[start] != val)
+				continue;
+			// count match length
+			for (j=0 ; j<max ; j++)
+				if (in.data[start+j] != in.data[i+j])
+					break;
+			if (j > bestlength)
+			{
+				bestlength = j;
+				beststart = start;
+			}
+		}
+#endif
+		beststart = BACK_WINDOW - (i-beststart);
+
+		if (bestlength < 3)
+		{	// output a single char
+			bestlength = 1;
+
+			out_p[outbits>>3] |= 1<<(outbits&7);	// set bit to mark char
+			outbits++;
+			for (j=0 ; j<8 ; j++, outbits++)
+				if (val & (1<<j) )
+					out_p[outbits>>3] |= 1<<(outbits&7);
+		}
+		else
+		{	// output a phrase
+			outbits++;	// leave a 0 bit to mark phrase
+			for (j=0 ; j<BACK_BITS ; j++, outbits++)
+				if (beststart & (1<<j) )
+					out_p[outbits>>3] |= 1<<(outbits&7);
+			for (j=0 ; j<FRONT_BITS ; j++, outbits++)
+				if (bestlength & (1<<j) )
+					out_p[outbits>>3] |= 1<<(outbits&7);
+		}
+
+		while (bestlength--)
+		{
+			val = in.data[i];
+			lzss_next[i] = lzss_head[val];
+			lzss_head[val] = i;
+			i++;
+		}
+	}
+
+	out_p += (outbits+7)>>3;
+	out.count = out_p - out.data;
+	return out;
+}
+
+//==========================================================================
+
+#define	MIN_REPT	15
+#define	MAX_REPT	0
+#define	HUF_TOKENS	(256+MAX_REPT)
+
+unsigned	charbits1[256][HUF_TOKENS];
+int			charbitscount1[256][HUF_TOKENS];
+
+hnode_t		hnodes1[256][HUF_TOKENS*2];
+int			numhnodes1[256];
+
+int			order0counts[256];
+
+/*
+==================
+SmallestNode1
+==================
+*/
+int	SmallestNode1 (hnode_t *hnodes, int numhnodes)
+{
+	int		i;
+	int		best, bestnode;
+
+	best = 99999999;
+	bestnode = -1;
+	for (i=0 ; i<numhnodes ; i++)
+	{
+		if (hnodes[i].used)
+			continue;
+		if (!hnodes[i].count)
+			continue;
+		if (hnodes[i].count < best)
+		{
+			best = hnodes[i].count;
+			bestnode = i;
+		}
+	}
+
+	if (bestnode == -1)
+		return -1;
+
+	hnodes[bestnode].used = true;
+	return bestnode;
+}
+
+
+/*
+==================
+BuildChars1
+==================
+*/
+void BuildChars1 (int prev, int nodenum, unsigned bits, int bitcount)
+{
+	hnode_t	*node;
+
+	if (nodenum < HUF_TOKENS)
+	{
+		if (bitcount > 32)
+			Error ("bitcount > 32");
+		charbits1[prev][nodenum] = bits;
+		charbitscount1[prev][nodenum] = bitcount;
+		return;
+	}
+
+	node = &hnodes1[prev][nodenum];
+	bits <<= 1;
+	BuildChars1 (prev, node->children[0], bits, bitcount+1);
+	bits |= 1;
+	BuildChars1 (prev, node->children[1], bits, bitcount+1);
+}
+
+
+/*
+==================
+BuildTree1
+==================
+*/
+void BuildTree1 (int prev)
+{
+	hnode_t		*node, *nodebase;
+	int			numhnodes;
+
+	// build the nodes
+	numhnodes = HUF_TOKENS;
+	nodebase = hnodes1[prev];
+	while (1)
+	{
+		node = &nodebase[numhnodes];
+
+		// pick two lowest counts
+		node->children[0] = SmallestNode1 (nodebase, numhnodes);
+		if (node->children[0] == -1)
+			break;	// no more
+
+		node->children[1] = SmallestNode1 (nodebase, numhnodes);
+		if (node->children[1] == -1)
+			break;
+
+		node->count = nodebase[node->children[0]].count + 
+			nodebase[node->children[1]].count;
+		numhnodes++;
+	}
+	numhnodes1[prev] = numhnodes-1;
+	BuildChars1 (prev, numhnodes-1, 0, 0);
+}
+
+
+/*
+==================
+Huffman1_Count
+==================
+*/
+void Huffman1_Count (cblock_t in)
+{
+	int		i;
+	int		prev;
+	int		v;
+	int		rept;
+
+	prev = 0;
+	for (i=0 ; i<in.count ; i++)
+	{
+		v = in.data[i];
+		order0counts[v]++;
+		hnodes1[prev][v].count++;
+		prev = v;
+#if 1
+		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
+			if (in.data[i+rept] != v)
+				break;
+		if (rept > MIN_REPT)
+		{
+			hnodes1[prev][255+rept].count++;
+			i += rept-1;
+		}
+#endif
+	}
+}
+
+
+/*
+==================
+Huffman1_Build
+==================
+*/
+byte	scaled[256][HUF_TOKENS];
+void Huffman1_Build (FILE *f)
+{
+	int		i, j, v;
+	int		max;
+	int		total;
+
+	for (i=0 ; i<256 ; i++)
+	{
+		// normalize and save the counts
+		max = 0;
+		for (j=0 ; j<HUF_TOKENS ; j++)
+		{
+			if (hnodes1[i][j].count > max)
+				max = hnodes1[i][j].count;
+		}
+		if (max == 0)
+			max = 1;
+		total = 0;
+		for (j=0 ; j<HUF_TOKENS ; j++)
+		{	// easy to overflow 32 bits here!
+			v = (hnodes1[i][j].count*(double)255+max-1)/max;
+			if (v > 255)
+				Error ("v > 255");
+			scaled[i][j] = hnodes1[i][j].count = v;
+			if (v)
+				total++;
+		}
+		if (total == 1)
+		{	// must have two tokens
+			if (!scaled[i][0])
+				scaled[i][0] = hnodes1[i][0].count = 1;
+			else
+				scaled[i][1] = hnodes1[i][1].count = 1;
+		}
+
+		BuildTree1 (i);
+	}
+
+#if 0
+	// count up the total bits
+	total = 0;
+	for (i=0 ; i<256 ; i++)
+		for (j=0 ; j<256 ; j++)
+			total += charbitscount1[i][j] * hnodes1[i][j].count;
+
+	total = (total+7)/8;
+	printf ("%i bytes huffman1 compressed\n", total);
+#endif
+
+	fwrite (scaled, 1, sizeof(scaled), f);
+}
+
+/*
+==================
+Huffman1
+
+Order 1 compression with pre-built table
+==================
+*/
+cblock_t Huffman1 (cblock_t in)
+{
+	int			i;
+	int			outbits, c;
+	unsigned	bits;
+	byte		*out_p;
+	cblock_t	out;
+	int			prev;
+	int			v;
+	int			rept;
+
+	out_p = out.data = malloc(in.count*2 + 1024);
+	memset (out_p, 0, in.count*2+1024);
+
+	// write count
+	*out_p++ = in.count&255;
+	*out_p++ = (in.count>>8)&255;
+	*out_p++ = (in.count>>16)&255;
+	*out_p++ = (in.count>>24)&255;
+
+	// write bits
+	outbits = 0;
+	prev = 0;
+	for (i=0 ; i<in.count ; i++)
+	{
+		v = in.data[i];
+
+		c = charbitscount1[prev][v];
+		bits = charbits1[prev][v];
+		if (!c)
+			Error ("!bits");
+		while (c)
+		{
+			c--;
+			if (bits & (1<<c))
+				out_p[outbits>>3] |= 1<<(outbits&7);
+			outbits++;
+		}
+
+		prev = v;
+#if 1
+		// check for repeat encodes
+		for (rept=1 ; i+rept < in.count && rept < MAX_REPT ; rept++)
+			if (in.data[i+rept] != v)
+				break;
+		if (rept > MIN_REPT)
+		{
+			c = charbitscount1[prev][255+rept];
+			bits = charbits1[prev][255+rept];
+			if (!c)
+				Error ("!bits");
+			while (c)
+			{
+				c--;
+				if (bits & (1<<c))
+					out_p[outbits>>3] |= 1<<(outbits&7);
+				outbits++;
+			}
+			i += rept-1;
+		}
+#endif
+	}
+
+	out_p += (outbits+7)>>3;
+
+	out.count = out_p - out.data;
+
+	return out;
+}
+
+#endif
diff --git a/tools/quake3/q3data/images.c b/tools/quake3/q3data/images.c
index ea661754..de872d2b 100644
--- a/tools/quake3/q3data/images.c
+++ b/tools/quake3/q3data/images.c
@@ -1,465 +1,465 @@
-#include "q3data.h"
-
-byte			*byteimage, *lbmpalette;
-int				byteimagewidth, byteimageheight;
-
-
-char		mip_prefix[1024];		// directory to dump the textures in
-
-qboolean	colormap_issued;
-byte		colormap_palette[768];
-
-/*
-==============
-Cmd_Grab
-
-$grab filename x y width height
-==============
-*/
-void Cmd_Grab (void)
-{
-	int             xl,yl,w,h,y;
-	byte			*cropped;
-	char			savename[1024];
-	char			dest[1024];
-
-	GetToken (qfalse);
-
-	if (token[0] == '/' || token[0] == '\\')
-		sprintf (savename, "%s%s.pcx", writedir, token+1);
-	else
-		sprintf (savename, "%spics/%s.pcx", writedir, token);
-
-	if (g_release)
-	{
-		if (token[0] == '/' || token[0] == '\\')
-			sprintf (dest, "%s.pcx", token+1);
-		else
-			sprintf (dest, "pics/%s.pcx", token);
-
-		ReleaseFile (dest);
-		return;
-	}
-
-	GetToken (qfalse);
-	xl = atoi (token);
-	GetToken (qfalse);
-	yl = atoi (token);
-	GetToken (qfalse);
-	w = atoi (token);
-	GetToken (qfalse);
-	h = atoi (token);
-
-	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
-		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
-
-	// crop it to the proper size
-	cropped = malloc (w*h);
-	for (y=0 ; y<h ; y++)
-	{
-		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, w,	h, lbmpalette);
-
-	free (cropped);
-}
-
-/*
-==============
-Cmd_Raw
-
-$grab filename x y width height
-==============
-*/
-void Cmd_Raw (void)
-{
-	int             xl,yl,w,h,y;
-	byte			*cropped;
-	char			savename[1024];
-	char			dest[1024];
-
-	GetToken (qfalse);
-
-	sprintf (savename, "%s%s.lmp", writedir, token);
-
-	if (g_release)
-	{
-		sprintf (dest, "%s.lmp", token);
-		ReleaseFile (dest);
-		return;
-	}
-
-	GetToken (qfalse);
-	xl = atoi (token);
-	GetToken (qfalse);
-	yl = atoi (token);
-	GetToken (qfalse);
-	w = atoi (token);
-	GetToken (qfalse);
-	h = atoi (token);
-
-	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
-		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
-
-	// crop it to the proper size
-	cropped = malloc (w*h);
-	for (y=0 ; y<h ; y++)
-	{
-		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
-	}
-
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-
-	SaveFile (savename, cropped, w*h);
-
-	free (cropped);
-}
-
-/*
-=============================================================================
-
-COLORMAP GRABBING
-
-=============================================================================
-*/
-
-/*
-===============
-BestColor
-===============
-*/
-byte BestColor (int r, int g, int b, int start, int stop)
-{
-	int	i;
-	int	dr, dg, db;
-	int	bestdistortion, distortion;
-	int	bestcolor;
-	byte	*pal;
-
-//
-// let any color go to 0 as a last resort
-//
-	bestdistortion = 256*256*4;
-	bestcolor = 0;
-
-	pal = colormap_palette + start*3;
-	for (i=start ; i<= stop ; i++)
-	{
-		dr = r - (int)pal[0];
-		dg = g - (int)pal[1];
-		db = b - (int)pal[2];
-		pal += 3;
-		distortion = dr*dr + dg*dg + db*db;
-		if (distortion < bestdistortion)
-		{
-			if (!distortion)
-				return i;		// perfect match
-
-			bestdistortion = distortion;
-			bestcolor = i;
-		}
-	}
-
-	return bestcolor;
-}
-
-
-/*
-==============
-Cmd_Colormap
-
-$colormap filename
-
-  the brightes colormap is first in the table (FIXME: reverse this now?)
-
-  64 rows of 256 : lightmaps
-  256 rows of 256 : translucency table
-==============
-*/
-void Cmd_Colormap (void)
-{
-	int		levels, brights;
-	int		l, c;
-	float	frac, red, green, blue;
-	float	range;
-	byte	*cropped, *lump_p;
-	char	savename[1024];
-	char	dest[1024];
-
-	colormap_issued = qtrue;
-	if (!g_release)
-		memcpy (colormap_palette, lbmpalette, 768);
-
-	if (!TokenAvailable ())
-	{	// just setting colormap_issued
-		return;
-	}
-
-	GetToken (qfalse);
-	sprintf (savename, "%spics/%s.pcx", writedir, token);
-
-	if (g_release)
-	{
-		sprintf (dest, "pics/%s.pcx", token);
-		ReleaseFile (dest);
-		return;
-	}
-
-	range = 2;
-	levels = 64;
-	brights = 1;	// ignore 255 (transparent)
-
-	cropped = malloc((levels+256)*256);
-	lump_p = cropped;
-
-// shaded levels
-	for (l=0;l<levels;l++)
-	{
-		frac = range - range*(float)l/(levels-1);
-		for (c=0 ; c<256-brights ; c++)
-		{
-			red = lbmpalette[c*3];
-			green = lbmpalette[c*3+1];
-			blue = lbmpalette[c*3+2];
-
-			red = (int)(red*frac+0.5);
-			green = (int)(green*frac+0.5);
-			blue = (int)(blue*frac+0.5);
-			
-//
-// note: 254 instead of 255 because 255 is the transparent color, and we
-// don't want anything remapping to that
-// don't use color 0, because NT can't remap that (or 255)
-//
-			*lump_p++ = BestColor(red,green,blue, 1, 254);
-		}
-
-		// fullbrights allways stay the same
-		for ( ; c<256 ; c++)
-			*lump_p++ = c;
-	}
-	
-// 66% transparancy table
-	for (l=0;l<255;l++)
-	{
-		for (c=0 ; c<255 ; c++)
-		{
-			red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
-			green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
-			blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
-
-			*lump_p++ = BestColor(red,green,blue, 1, 254);
-		}
-		*lump_p++ = 255;
-	}
-	for (c=0 ; c<256 ; c++)
-		*lump_p++ = 255;
-	
-	// save off the new image
-	printf ("saving %s\n", savename);
-	CreatePath (savename);
-	WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
-
-	free (cropped);
-}
-
-/*
-=============================================================================
-
-MIPTEX GRABBING
-
-=============================================================================
-*/
-
-byte	pixdata[256];
-
-int		d_red, d_green, d_blue;
-
-byte	palmap[32][32][32];
-qboolean	palmap_built;
-
-/*
-=============
-FindColor
-=============
-*/
-int FindColor (int r, int g, int b)
-{
-	int		bestcolor;
-
-	if (r > 255)
-		r = 255;
-	if (r < 0)
-		r = 0;
-	if (g > 255)
-		g = 255;
-	if (g < 0)
-		g = 0;
-	if (b > 255)
-		b = 255;
-	if (b < 0)
-		b = 0;
-#ifndef TABLECOLORS
-	bestcolor = BestColor (r, g, b, 0, 254);
-#else
-	bestcolor = palmap[r>>3][g>>3][b>>3];
-#endif
-
-	return bestcolor;
-}
-
-
-void BuildPalmap (void)
-{
-#ifdef TABLECOLORS
-	int		r, g, b;
-	int		bestcolor;
-
-	if (palmap_built)
-		return;
-	palmap_built = qtrue;
-
-	for (r=4 ; r<256 ; r+=8)
-	{
-		for (g=4 ; g<256 ; g+=8)
-		{
-			for (b=4 ; b<256 ; b+=8)
-			{
-				bestcolor = BestColor (r, g, b, 1, 254);
-				palmap[r>>3][g>>3][b>>3] = bestcolor;
-			}
-		}
-	}
-#endif
-
-	if (!colormap_issued)
-		Error ("You must issue a $colormap command first");
-
-}
-
-/*
-=============
-AveragePixels
-=============
-*/
-byte AveragePixels (int count)
-{
-	int		r,g,b;
-	int		i;
-	int		vis;
-	int		pix;
-	int		bestcolor;
-	byte	*pal;
-	int		fullbright;
-	
-	vis = 0;
-	r = g = b = 0;
-	fullbright = 0;
-	for (i=0 ; i<count ; i++)
-	{
-		pix = pixdata[i];
-		
-		r += lbmpalette[pix*3];
-		g += lbmpalette[pix*3+1];
-		b += lbmpalette[pix*3+2];
-		vis++;
-	}
-		
-	r /= vis;
-	g /= vis;
-	b /= vis;
-
-	// error diffusion
-	r += d_red;
-	g += d_green;
-	b += d_blue;
-	
-//
-// find the best color
-//
-	bestcolor = FindColor (r, g, b);
-
-	// error diffusion
-	pal = colormap_palette + bestcolor*3;
-	d_red = r - (int)pal[0];
-	d_green = g - (int)pal[1];
-	d_blue = b - (int)pal[2];
-
-	return bestcolor;
-}
-
-
-
-/*
-=============================================================================
-
-ENVIRONMENT MAP GRABBING
-
-Creates six pcx files from tga files without any palette edge seams
-also copies the tga files for GL rendering.
-=============================================================================
-*/
-
-// 3dstudio environment map suffixes
-char	*suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
-
-/*
-=================
-Cmd_Environment
-=================
-*/
-void Cmd_Environment (void)
-{
-	char	name[1024];
-	int		i, x, y;
-	byte	image[256*256];
-	byte	*tga;
-
-	GetToken (qfalse);
-
-	if (g_release)
-	{
-		for (i=0 ; i<6 ; i++)
-		{
-			sprintf (name, "env/%s%s.pcx", token, suf[i]);
-			ReleaseFile (name);
-			sprintf (name, "env/%s%s.tga", token, suf[i]);
-			ReleaseFile (name);
-		}
-		return;
-	}
-	// get the palette
-	BuildPalmap ();
-
-	sprintf (name, "%senv/", gamedir);
-	CreatePath (name);
-
-	// convert the images
-	for (i=0 ; i<6 ; i++)
-	{
-		sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
-		printf ("loading %s...\n", name);
-		LoadTGA (name, &tga, NULL, NULL);
-
-		for (y=0 ; y<256 ; y++)
-		{
-			for (x=0 ; x<256 ; x++)
-			{
-				image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
-			}
-		}
-		free (tga);
-		sprintf (name, "%senv/%s%s.pcx", writedir, token, suf[i]);
-		if (FileTime (name) != -1)
-			printf ("%s already exists, not overwriting.\n", name);
-		else
-			WritePCXfile (name, image, 256, 256, colormap_palette);
-	}
-}
-
+#include "q3data.h"
+
+byte			*byteimage, *lbmpalette;
+int				byteimagewidth, byteimageheight;
+
+
+char		mip_prefix[1024];		// directory to dump the textures in
+
+qboolean	colormap_issued;
+byte		colormap_palette[768];
+
+/*
+==============
+Cmd_Grab
+
+$grab filename x y width height
+==============
+*/
+void Cmd_Grab (void)
+{
+	int             xl,yl,w,h,y;
+	byte			*cropped;
+	char			savename[1024];
+	char			dest[1024];
+
+	GetToken (qfalse);
+
+	if (token[0] == '/' || token[0] == '\\')
+		sprintf (savename, "%s%s.pcx", writedir, token+1);
+	else
+		sprintf (savename, "%spics/%s.pcx", writedir, token);
+
+	if (g_release)
+	{
+		if (token[0] == '/' || token[0] == '\\')
+			sprintf (dest, "%s.pcx", token+1);
+		else
+			sprintf (dest, "pics/%s.pcx", token);
+
+		ReleaseFile (dest);
+		return;
+	}
+
+	GetToken (qfalse);
+	xl = atoi (token);
+	GetToken (qfalse);
+	yl = atoi (token);
+	GetToken (qfalse);
+	w = atoi (token);
+	GetToken (qfalse);
+	h = atoi (token);
+
+	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
+		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
+
+	// crop it to the proper size
+	cropped = malloc (w*h);
+	for (y=0 ; y<h ; y++)
+	{
+		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, w,	h, lbmpalette);
+
+	free (cropped);
+}
+
+/*
+==============
+Cmd_Raw
+
+$grab filename x y width height
+==============
+*/
+void Cmd_Raw (void)
+{
+	int             xl,yl,w,h,y;
+	byte			*cropped;
+	char			savename[1024];
+	char			dest[1024];
+
+	GetToken (qfalse);
+
+	sprintf (savename, "%s%s.lmp", writedir, token);
+
+	if (g_release)
+	{
+		sprintf (dest, "%s.lmp", token);
+		ReleaseFile (dest);
+		return;
+	}
+
+	GetToken (qfalse);
+	xl = atoi (token);
+	GetToken (qfalse);
+	yl = atoi (token);
+	GetToken (qfalse);
+	w = atoi (token);
+	GetToken (qfalse);
+	h = atoi (token);
+
+	if (xl<0 || yl<0 || w<0 || h<0 || xl+w>byteimagewidth || yl+h>byteimageheight)
+		Error ("GrabPic: Bad size: %i, %i, %i, %i",xl,yl,w,h);
+
+	// crop it to the proper size
+	cropped = malloc (w*h);
+	for (y=0 ; y<h ; y++)
+	{
+		memcpy (cropped+y*w, byteimage+(y+yl)*byteimagewidth+xl, w);
+	}
+
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+
+	SaveFile (savename, cropped, w*h);
+
+	free (cropped);
+}
+
+/*
+=============================================================================
+
+COLORMAP GRABBING
+
+=============================================================================
+*/
+
+/*
+===============
+BestColor
+===============
+*/
+byte BestColor (int r, int g, int b, int start, int stop)
+{
+	int	i;
+	int	dr, dg, db;
+	int	bestdistortion, distortion;
+	int	bestcolor;
+	byte	*pal;
+
+//
+// let any color go to 0 as a last resort
+//
+	bestdistortion = 256*256*4;
+	bestcolor = 0;
+
+	pal = colormap_palette + start*3;
+	for (i=start ; i<= stop ; i++)
+	{
+		dr = r - (int)pal[0];
+		dg = g - (int)pal[1];
+		db = b - (int)pal[2];
+		pal += 3;
+		distortion = dr*dr + dg*dg + db*db;
+		if (distortion < bestdistortion)
+		{
+			if (!distortion)
+				return i;		// perfect match
+
+			bestdistortion = distortion;
+			bestcolor = i;
+		}
+	}
+
+	return bestcolor;
+}
+
+
+/*
+==============
+Cmd_Colormap
+
+$colormap filename
+
+  the brightes colormap is first in the table (FIXME: reverse this now?)
+
+  64 rows of 256 : lightmaps
+  256 rows of 256 : translucency table
+==============
+*/
+void Cmd_Colormap (void)
+{
+	int		levels, brights;
+	int		l, c;
+	float	frac, red, green, blue;
+	float	range;
+	byte	*cropped, *lump_p;
+	char	savename[1024];
+	char	dest[1024];
+
+	colormap_issued = qtrue;
+	if (!g_release)
+		memcpy (colormap_palette, lbmpalette, 768);
+
+	if (!TokenAvailable ())
+	{	// just setting colormap_issued
+		return;
+	}
+
+	GetToken (qfalse);
+	sprintf (savename, "%spics/%s.pcx", writedir, token);
+
+	if (g_release)
+	{
+		sprintf (dest, "pics/%s.pcx", token);
+		ReleaseFile (dest);
+		return;
+	}
+
+	range = 2;
+	levels = 64;
+	brights = 1;	// ignore 255 (transparent)
+
+	cropped = malloc((levels+256)*256);
+	lump_p = cropped;
+
+// shaded levels
+	for (l=0;l<levels;l++)
+	{
+		frac = range - range*(float)l/(levels-1);
+		for (c=0 ; c<256-brights ; c++)
+		{
+			red = lbmpalette[c*3];
+			green = lbmpalette[c*3+1];
+			blue = lbmpalette[c*3+2];
+
+			red = (int)(red*frac+0.5);
+			green = (int)(green*frac+0.5);
+			blue = (int)(blue*frac+0.5);
+			
+//
+// note: 254 instead of 255 because 255 is the transparent color, and we
+// don't want anything remapping to that
+// don't use color 0, because NT can't remap that (or 255)
+//
+			*lump_p++ = BestColor(red,green,blue, 1, 254);
+		}
+
+		// fullbrights allways stay the same
+		for ( ; c<256 ; c++)
+			*lump_p++ = c;
+	}
+	
+// 66% transparancy table
+	for (l=0;l<255;l++)
+	{
+		for (c=0 ; c<255 ; c++)
+		{
+			red = lbmpalette[c*3]*0.33 + lbmpalette[l*3]*0.66;
+			green = lbmpalette[c*3+1]*0.33 + lbmpalette[l*3+1]*0.66;
+			blue = lbmpalette[c*3+2]*0.33 + lbmpalette[l*3+2]*0.66;
+
+			*lump_p++ = BestColor(red,green,blue, 1, 254);
+		}
+		*lump_p++ = 255;
+	}
+	for (c=0 ; c<256 ; c++)
+		*lump_p++ = 255;
+	
+	// save off the new image
+	printf ("saving %s\n", savename);
+	CreatePath (savename);
+	WritePCXfile (savename, cropped, 256, levels+256, lbmpalette);
+
+	free (cropped);
+}
+
+/*
+=============================================================================
+
+MIPTEX GRABBING
+
+=============================================================================
+*/
+
+byte	pixdata[256];
+
+int		d_red, d_green, d_blue;
+
+byte	palmap[32][32][32];
+qboolean	palmap_built;
+
+/*
+=============
+FindColor
+=============
+*/
+int FindColor (int r, int g, int b)
+{
+	int		bestcolor;
+
+	if (r > 255)
+		r = 255;
+	if (r < 0)
+		r = 0;
+	if (g > 255)
+		g = 255;
+	if (g < 0)
+		g = 0;
+	if (b > 255)
+		b = 255;
+	if (b < 0)
+		b = 0;
+#ifndef TABLECOLORS
+	bestcolor = BestColor (r, g, b, 0, 254);
+#else
+	bestcolor = palmap[r>>3][g>>3][b>>3];
+#endif
+
+	return bestcolor;
+}
+
+
+void BuildPalmap (void)
+{
+#ifdef TABLECOLORS
+	int		r, g, b;
+	int		bestcolor;
+
+	if (palmap_built)
+		return;
+	palmap_built = qtrue;
+
+	for (r=4 ; r<256 ; r+=8)
+	{
+		for (g=4 ; g<256 ; g+=8)
+		{
+			for (b=4 ; b<256 ; b+=8)
+			{
+				bestcolor = BestColor (r, g, b, 1, 254);
+				palmap[r>>3][g>>3][b>>3] = bestcolor;
+			}
+		}
+	}
+#endif
+
+	if (!colormap_issued)
+		Error ("You must issue a $colormap command first");
+
+}
+
+/*
+=============
+AveragePixels
+=============
+*/
+byte AveragePixels (int count)
+{
+	int		r,g,b;
+	int		i;
+	int		vis;
+	int		pix;
+	int		bestcolor;
+	byte	*pal;
+	int		fullbright;
+	
+	vis = 0;
+	r = g = b = 0;
+	fullbright = 0;
+	for (i=0 ; i<count ; i++)
+	{
+		pix = pixdata[i];
+		
+		r += lbmpalette[pix*3];
+		g += lbmpalette[pix*3+1];
+		b += lbmpalette[pix*3+2];
+		vis++;
+	}
+		
+	r /= vis;
+	g /= vis;
+	b /= vis;
+
+	// error diffusion
+	r += d_red;
+	g += d_green;
+	b += d_blue;
+	
+//
+// find the best color
+//
+	bestcolor = FindColor (r, g, b);
+
+	// error diffusion
+	pal = colormap_palette + bestcolor*3;
+	d_red = r - (int)pal[0];
+	d_green = g - (int)pal[1];
+	d_blue = b - (int)pal[2];
+
+	return bestcolor;
+}
+
+
+
+/*
+=============================================================================
+
+ENVIRONMENT MAP GRABBING
+
+Creates six pcx files from tga files without any palette edge seams
+also copies the tga files for GL rendering.
+=============================================================================
+*/
+
+// 3dstudio environment map suffixes
+char	*suf[6] = {"rt", "ft", "lf", "bk", "up", "dn"};
+
+/*
+=================
+Cmd_Environment
+=================
+*/
+void Cmd_Environment (void)
+{
+	char	name[1024];
+	int		i, x, y;
+	byte	image[256*256];
+	byte	*tga;
+
+	GetToken (qfalse);
+
+	if (g_release)
+	{
+		for (i=0 ; i<6 ; i++)
+		{
+			sprintf (name, "env/%s%s.pcx", token, suf[i]);
+			ReleaseFile (name);
+			sprintf (name, "env/%s%s.tga", token, suf[i]);
+			ReleaseFile (name);
+		}
+		return;
+	}
+	// get the palette
+	BuildPalmap ();
+
+	sprintf (name, "%senv/", gamedir);
+	CreatePath (name);
+
+	// convert the images
+	for (i=0 ; i<6 ; i++)
+	{
+		sprintf (name, "%senv/%s%s.tga", gamedir, token, suf[i]);
+		printf ("loading %s...\n", name);
+		LoadTGA (name, &tga, NULL, NULL);
+
+		for (y=0 ; y<256 ; y++)
+		{
+			for (x=0 ; x<256 ; x++)
+			{
+				image[y*256+x] = FindColor (tga[(y*256+x)*4+0],tga[(y*256+x)*4+1],tga[(y*256+x)*4+2]);
+			}
+		}
+		free (tga);
+		sprintf (name, "%senv/%s%s.pcx", writedir, token, suf[i]);
+		if (FileTime (name) != -1)
+			printf ("%s already exists, not overwriting.\n", name);
+		else
+			WritePCXfile (name, image, 256, 256, colormap_palette);
+	}
+}
+
diff --git a/tools/quake3/q3data/md3lib.c b/tools/quake3/q3data/md3lib.c
index 5bc90b10..e959a411 100644
--- a/tools/quake3/q3data/md3lib.c
+++ b/tools/quake3/q3data/md3lib.c
@@ -1,193 +1,193 @@
-#include <assert.h>
-#ifdef _WIN32
-#include <io.h>
-#endif
-#include "md3lib.h"
-
-#if defined (__linux__) || defined (__APPLE__)
-#define filelength Q_filelength
-#endif
-
-/*
-** MD3_ComputeTagFromTri
-*/
-void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float pTri[3][3] )
-{
-	float	len[3];
-	vec3_t	axes[3], sides[3];
-	int		longestSide, shortestSide, hypotSide;
-	int		origin;
-	int		j;
-	float	d;
-
-	memset( axes, 0, sizeof( axes ) );
-	memset( sides, 0, sizeof( sides ) );
-
-	//
-	// compute sides
-	//
-	for ( j = 0; j < 3; j++ )
-	{
-		sides[j][0] = pTri[(j+1)%3][0] - pTri[j][0];
-		sides[j][1] = pTri[(j+1)%3][1] - pTri[j][1];
-		sides[j][2] = pTri[(j+1)%3][2] - pTri[j][2];
-
-		len[j] = ( float ) sqrt( DotProduct( sides[j], sides[j] ) );
-	}
-
-#if 0
-	if ( len[0] > len[1] && len[0] > len[2] )
-	{
-		longestSide = 0; shortestSide = 1; origin = 2;
-	}
-	else if ( len[1] > len[0] && len[1] > len[2] )
-	{
-		longestSide = 1; shortestSide = 2; origin = 0;
-	}
-	else if ( len[2] > len[0] && len[2] > len[1] )
-	{
-		longestSide = 2; shortestSide = 0; origin = 1;
-	}
-	else
-	{
-		Error( "invalid tag triangle, must be a right triangle with unequal length sides" );
-	}
-#endif
-	if ( len[0] > len[1] && len[0] > len[2] ) {
-		hypotSide = 0;
-		origin = 2;
-	} else if ( len[1] > len[0] && len[1] > len[2] ) {
-		hypotSide = 1;
-		origin = 0;
-	} else if ( len[2] > len[0] && len[2] > len[1] ) {
-		hypotSide = 2;
-		origin = 1;
-	}
-	len[hypotSide] = -1;
-
-	if ( len[0] > len[1] && len[0] > len[2] ) {
-		longestSide = 0;
-	} else if ( len[1] > len[0] && len[1] > len[2] ) {
-		longestSide = 1;
-	} else if ( len[2] > len[0] && len[2] > len[1] ) {
-		longestSide = 2;
-	}
-	len[longestSide] = -1;
-
-	if ( len[0] > len[1] && len[0] > len[2] ) {
-		shortestSide = 0;
-	} else if ( len[1] > len[0] && len[1] > len[2] ) {
-		shortestSide = 1;
-	} else if ( len[2] > len[0] && len[2] > len[1] ) {
-		shortestSide = 2;
-	}
-	len[shortestSide] = -1;
-
-
-
-//	VectorNormalize( sides[shortestSide], axes[0] );
-//	VectorNormalize( sides[longestSide], axes[1] );
-	VectorNormalize( sides[longestSide], axes[0] );
-	VectorNormalize( sides[shortestSide], axes[1] );
-
-	// project shortest side so that it is exactly 90 degrees to the longer side
-	d = DotProduct( axes[0], axes[1] );
-	VectorMA( axes[0], -d, axes[1], axes[0] );
-	VectorNormalize( axes[0], axes[0] );
-
-	CrossProduct( sides[longestSide], sides[shortestSide], axes[2] );
-	VectorNormalize( axes[2], axes[2] );
-
-	pTag->origin[0] = pTri[origin][0];
-	pTag->origin[1] = pTri[origin][1];
-	pTag->origin[2] = pTri[origin][2];
-
-	VectorCopy( axes[0], pTag->axis[0] );
-	VectorCopy( axes[1], pTag->axis[1] );
-	VectorCopy( axes[2], pTag->axis[2] );
-}
-
-/*
-==============
-MD3_Dump
-==============
-*/
-void MD3_Dump( const char *filename )
-{
-	md3Header_t header;
-	md3Tag_t *pTag;
-	md3Surface_t *pSurface;
-	FILE *fp;
-	void *_buffer;
-	void *buffer;
-	long fileSize;
-	int i;
-
-	if ( ( fp = fopen( filename, "rb" ) ) == 0 )
-	{
-		Error( "Unable to open '%s'\n", filename );
-	}
-
-	fileSize = filelength( fileno( fp ) );
-	_buffer = malloc( filelength( fileno( fp ) ) );
-	fread( _buffer, fileSize, 1, fp );
-	fclose( fp );
-
-	buffer = ( char * ) _buffer;
-	header = *( md3Header_t * ) _buffer;
-
-	if ( header.ident != MD3_IDENT )
-	{
-		Error( "Incorrect ident for '%s'\n", filename );
-	}
-
-	printf( "Contents of '%s'\n", filename );
-	printf( "  version:        %d\n", header.version );
-	printf( "  name:           %s\n", header.name );
-	printf( "  num frames:     %d\n", header.numFrames );
-	printf( "  num tags:       %d\n", header.numTags );
-	printf( "  num surfaces:   %d\n", header.numSurfaces );
-	printf( "  num skins:      %d\n", header.numSkins );
-	printf( "  file size:      %d\n", fileSize );
-
-	printf( "--- TAGS ---\n" );
-	pTag = ( md3Tag_t * ) ( ( ( char * ) buffer ) + header.ofsTags );
-	for ( i = 0; i < header.numTags; i++, pTag++ )
-	{
-		printf( "  tag %d ('%s')\n", i, pTag->name );
-		printf( "    origin: %f,%f,%f\n", pTag->origin[0], pTag->origin[1], pTag->origin[2] );
-		printf( "        vf: %f,%f,%f\n", pTag->axis[0][0], pTag->axis[0][1], pTag->axis[0][2] );
-		printf( "        vr: %f,%f,%f\n", pTag->axis[1][0], pTag->axis[1][1], pTag->axis[1][2] );
-		printf( "        vu: %f,%f,%f\n", pTag->axis[2][0], pTag->axis[2][1], pTag->axis[2][2] );
-	}
-
-	printf( "--- SURFACES ---\n" );
-	pSurface = ( md3Surface_t * ) ( ( ( char * ) buffer ) + header.ofsSurfaces );
-
-	for ( i = 0; i < header.numSurfaces; i++ )
-	{
-		int j;
-
-		md3Shader_t *pShader = ( md3Shader_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsShaders );
-
-		printf( "\n  surface %d ('%s')\n", i, pSurface->name );
-		printf( "    num frames: %d\n", pSurface->numFrames );
-		printf( "    num shaders: %d\n", pSurface->numShaders );
-		printf( "    num tris: %d\n", pSurface->numTriangles );
-		printf( "    num verts: %d\n", pSurface->numVerts );
-
-		if ( pSurface->numShaders > 0 )
-		{
-			printf( "    --- SHADERS ---\n" );
-
-			for ( j = 0; j < pSurface->numShaders; j++, pShader++ )
-			{
-				printf( "    shader %d ('%s')\n", j, pShader->name );
-			}
-		}
-		pSurface = ( md3Surface_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsEnd );
-	}
-
-	free( _buffer );
-}
-
+#include <assert.h>
+#ifdef _WIN32
+#include <io.h>
+#endif
+#include "md3lib.h"
+
+#if defined (__linux__) || defined (__APPLE__)
+#define filelength Q_filelength
+#endif
+
+/*
+** MD3_ComputeTagFromTri
+*/
+void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float pTri[3][3] )
+{
+	float	len[3];
+	vec3_t	axes[3], sides[3];
+	int		longestSide, shortestSide, hypotSide;
+	int		origin;
+	int		j;
+	float	d;
+
+	memset( axes, 0, sizeof( axes ) );
+	memset( sides, 0, sizeof( sides ) );
+
+	//
+	// compute sides
+	//
+	for ( j = 0; j < 3; j++ )
+	{
+		sides[j][0] = pTri[(j+1)%3][0] - pTri[j][0];
+		sides[j][1] = pTri[(j+1)%3][1] - pTri[j][1];
+		sides[j][2] = pTri[(j+1)%3][2] - pTri[j][2];
+
+		len[j] = ( float ) sqrt( DotProduct( sides[j], sides[j] ) );
+	}
+
+#if 0
+	if ( len[0] > len[1] && len[0] > len[2] )
+	{
+		longestSide = 0; shortestSide = 1; origin = 2;
+	}
+	else if ( len[1] > len[0] && len[1] > len[2] )
+	{
+		longestSide = 1; shortestSide = 2; origin = 0;
+	}
+	else if ( len[2] > len[0] && len[2] > len[1] )
+	{
+		longestSide = 2; shortestSide = 0; origin = 1;
+	}
+	else
+	{
+		Error( "invalid tag triangle, must be a right triangle with unequal length sides" );
+	}
+#endif
+	if ( len[0] > len[1] && len[0] > len[2] ) {
+		hypotSide = 0;
+		origin = 2;
+	} else if ( len[1] > len[0] && len[1] > len[2] ) {
+		hypotSide = 1;
+		origin = 0;
+	} else if ( len[2] > len[0] && len[2] > len[1] ) {
+		hypotSide = 2;
+		origin = 1;
+	}
+	len[hypotSide] = -1;
+
+	if ( len[0] > len[1] && len[0] > len[2] ) {
+		longestSide = 0;
+	} else if ( len[1] > len[0] && len[1] > len[2] ) {
+		longestSide = 1;
+	} else if ( len[2] > len[0] && len[2] > len[1] ) {
+		longestSide = 2;
+	}
+	len[longestSide] = -1;
+
+	if ( len[0] > len[1] && len[0] > len[2] ) {
+		shortestSide = 0;
+	} else if ( len[1] > len[0] && len[1] > len[2] ) {
+		shortestSide = 1;
+	} else if ( len[2] > len[0] && len[2] > len[1] ) {
+		shortestSide = 2;
+	}
+	len[shortestSide] = -1;
+
+
+
+//	VectorNormalize( sides[shortestSide], axes[0] );
+//	VectorNormalize( sides[longestSide], axes[1] );
+	VectorNormalize( sides[longestSide], axes[0] );
+	VectorNormalize( sides[shortestSide], axes[1] );
+
+	// project shortest side so that it is exactly 90 degrees to the longer side
+	d = DotProduct( axes[0], axes[1] );
+	VectorMA( axes[0], -d, axes[1], axes[0] );
+	VectorNormalize( axes[0], axes[0] );
+
+	CrossProduct( sides[longestSide], sides[shortestSide], axes[2] );
+	VectorNormalize( axes[2], axes[2] );
+
+	pTag->origin[0] = pTri[origin][0];
+	pTag->origin[1] = pTri[origin][1];
+	pTag->origin[2] = pTri[origin][2];
+
+	VectorCopy( axes[0], pTag->axis[0] );
+	VectorCopy( axes[1], pTag->axis[1] );
+	VectorCopy( axes[2], pTag->axis[2] );
+}
+
+/*
+==============
+MD3_Dump
+==============
+*/
+void MD3_Dump( const char *filename )
+{
+	md3Header_t header;
+	md3Tag_t *pTag;
+	md3Surface_t *pSurface;
+	FILE *fp;
+	void *_buffer;
+	void *buffer;
+	long fileSize;
+	int i;
+
+	if ( ( fp = fopen( filename, "rb" ) ) == 0 )
+	{
+		Error( "Unable to open '%s'\n", filename );
+	}
+
+	fileSize = filelength( fileno( fp ) );
+	_buffer = malloc( filelength( fileno( fp ) ) );
+	fread( _buffer, fileSize, 1, fp );
+	fclose( fp );
+
+	buffer = ( char * ) _buffer;
+	header = *( md3Header_t * ) _buffer;
+
+	if ( header.ident != MD3_IDENT )
+	{
+		Error( "Incorrect ident for '%s'\n", filename );
+	}
+
+	printf( "Contents of '%s'\n", filename );
+	printf( "  version:        %d\n", header.version );
+	printf( "  name:           %s\n", header.name );
+	printf( "  num frames:     %d\n", header.numFrames );
+	printf( "  num tags:       %d\n", header.numTags );
+	printf( "  num surfaces:   %d\n", header.numSurfaces );
+	printf( "  num skins:      %d\n", header.numSkins );
+	printf( "  file size:      %d\n", fileSize );
+
+	printf( "--- TAGS ---\n" );
+	pTag = ( md3Tag_t * ) ( ( ( char * ) buffer ) + header.ofsTags );
+	for ( i = 0; i < header.numTags; i++, pTag++ )
+	{
+		printf( "  tag %d ('%s')\n", i, pTag->name );
+		printf( "    origin: %f,%f,%f\n", pTag->origin[0], pTag->origin[1], pTag->origin[2] );
+		printf( "        vf: %f,%f,%f\n", pTag->axis[0][0], pTag->axis[0][1], pTag->axis[0][2] );
+		printf( "        vr: %f,%f,%f\n", pTag->axis[1][0], pTag->axis[1][1], pTag->axis[1][2] );
+		printf( "        vu: %f,%f,%f\n", pTag->axis[2][0], pTag->axis[2][1], pTag->axis[2][2] );
+	}
+
+	printf( "--- SURFACES ---\n" );
+	pSurface = ( md3Surface_t * ) ( ( ( char * ) buffer ) + header.ofsSurfaces );
+
+	for ( i = 0; i < header.numSurfaces; i++ )
+	{
+		int j;
+
+		md3Shader_t *pShader = ( md3Shader_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsShaders );
+
+		printf( "\n  surface %d ('%s')\n", i, pSurface->name );
+		printf( "    num frames: %d\n", pSurface->numFrames );
+		printf( "    num shaders: %d\n", pSurface->numShaders );
+		printf( "    num tris: %d\n", pSurface->numTriangles );
+		printf( "    num verts: %d\n", pSurface->numVerts );
+
+		if ( pSurface->numShaders > 0 )
+		{
+			printf( "    --- SHADERS ---\n" );
+
+			for ( j = 0; j < pSurface->numShaders; j++, pShader++ )
+			{
+				printf( "    shader %d ('%s')\n", j, pShader->name );
+			}
+		}
+		pSurface = ( md3Surface_t * ) ( ( ( char * ) pSurface ) + pSurface->ofsEnd );
+	}
+
+	free( _buffer );
+}
+
diff --git a/tools/quake3/q3data/md3lib.h b/tools/quake3/q3data/md3lib.h
index 7132906f..bdee0bd9 100644
--- a/tools/quake3/q3data/md3lib.h
+++ b/tools/quake3/q3data/md3lib.h
@@ -1,7 +1,7 @@
-#include <stdio.h>
-#include "../common/cmdlib.h"
-#include "mathlib.h"
-#include "../common/qfiles.h"
-
-void MD3_Dump( const char *filename );
-void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float tri[3][3] );
+#include <stdio.h>
+#include "../common/cmdlib.h"
+#include "mathlib.h"
+#include "../common/qfiles.h"
+
+void MD3_Dump( const char *filename );
+void MD3_ComputeTagFromTri( md3Tag_t *pTag, const float tri[3][3] );
diff --git a/tools/quake3/q3data/models.c b/tools/quake3/q3data/models.c
index 05d65df7..1d2d6904 100644
--- a/tools/quake3/q3data/models.c
+++ b/tools/quake3/q3data/models.c
@@ -1,2134 +1,2134 @@
-#include <assert.h>
-#include "q3data.h"
-
-//=================================================================
-
-static void OrderSurfaces( void );
-static void LoadBase( const char *filename );
-static int	LoadModelFile( const char *filename, polyset_t **ppsets, int *pnumpolysets );
-
-#define MAX_SURFACE_TRIS	(SHADER_MAX_INDEXES / 3)
-#define MAX_SURFACE_VERTS	SHADER_MAX_VERTEXES
-
-#define MD3_TYPE_UNKNOWN 0
-#define MD3_TYPE_BASE3DS 1
-#define MD3_TYPE_SPRITE  2
-#define MD3_TYPE_ASE	 3
-
-#define MAX_ANIM_FRAMES		512
-#define MAX_ANIM_SURFACES	32
-
-typedef struct
-{
-	polyset_t *frames;
-	int numFrames;
-} SurfaceAnimation_t;
-
-typedef struct
-{
-	polyset_t *surfaces[MAX_ANIM_SURFACES];
-	int numSurfaces;
-} ObjectAnimationFrame_t;
-
-typedef struct {
-	vec3_t		xyz;
-	vec3_t		normal;
-	vec3_t		color;
-	float		st[2];
-	int			index;
-} baseVertex_t;
-	
-typedef struct {
-	baseVertex_t	v[3];
-} baseTriangle_t;
-
-//================================================================
-
-typedef struct
-{
-	md3Surface_t	header;
-	md3Shader_t		shaders[MD3_MAX_SHADERS];
-	// all verts (xyz_normal)
-	float	*verts[MD3_MAX_FRAMES];
-
-	baseTriangle_t	baseTriangles[MD3_MAX_TRIANGLES];
-
-	// the triangles will be sorted so that they form long generalized tristrips
-	int				orderedTriangles[MD3_MAX_TRIANGLES][3];
-	int				lodTriangles[MD3_MAX_TRIANGLES][3];
-	baseVertex_t	baseVertexes[MD3_MAX_VERTS];
-
-} md3SurfaceData_t;
-
-typedef struct
-{
-	int			skinwidth, skinheight;
-	
-	md3SurfaceData_t surfData[MD3_MAX_SURFACES];
-
-	md3Tag_t		tags[MD3_MAX_FRAMES][MD3_MAX_TAGS];
-	md3Frame_t		frames[MD3_MAX_FRAMES];
-
-	md3Header_t	model;
-	float		scale_up;			// set by $scale
-	vec3_t		adjust;				// set by $origin
-	vec3_t		aseAdjust;
-	int			fixedwidth, fixedheight;	// set by $skinsize
-
-	int			maxSurfaceTris;
-
-	int			lowerSkipFrameStart, lowerSkipFrameEnd;
-	int			maxUpperFrames;
-	int			maxHeadFrames;
-	int			currentLod;
-	float		lodBias;
-
-	int			type;		// MD3_TYPE_BASE, MD3_TYPE_OLDBASE, MD3_TYPE_ASE, or MD3_TYPE_SPRITE
-
-} q3data;
-
-q3data g_data;
-
-// the command list holds counts, the count * 3 xyz, st, normal indexes
-// that are valid for every frame
-char		g_cddir[1024];
-char		g_modelname[1024];
-
-//==============================================================
-
-/*
-===============
-ClearModel
-===============
-*/
-void ClearModel (void)
-{
-	int i;
-
-	g_data.type = MD3_TYPE_UNKNOWN;
-
-	for ( i = 0; i < MD3_MAX_SURFACES; i++ )
-	{
-		memset( &g_data.surfData[i].header, 0, sizeof( g_data.surfData[i].header ) );
-		memset( &g_data.surfData[i].shaders, 0, sizeof( g_data.surfData[i].shaders ) );
-		memset( &g_data.surfData[i].verts, 0, sizeof( g_data.surfData[i].verts ) );
-	}
-
-	memset( g_data.tags, 0, sizeof( g_data.tags ) );
-
-	for ( i = 0; i < g_data.model.numSurfaces; i++ )
-	{
-		int j;
-
-		for ( j = 0; j < g_data.surfData[i].header.numShaders; j++ )
-		{
-			memset( &g_data.surfData[i].shaders[j], 0, sizeof( g_data.surfData[i].shaders[j] ) );
-		}
-	}
-	memset (&g_data.model, 0, sizeof(g_data.model));
-	memset (g_cddir, 0, sizeof(g_cddir));
-
-	g_modelname[0] = 0;
-	g_data.scale_up = 1.0;	
-	memset( &g_data.model, 0, sizeof( g_data.model ) );
-	VectorCopy (vec3_origin, g_data.adjust);
-	g_data.fixedwidth = g_data.fixedheight = 0;
-	g_skipmodel = qfalse;
-}
-
-/*
-** void WriteModelSurface( FILE *modelouthandle, md3SurfaceData_t *pSurfData )
-**
-** This routine assumes that the file position has been adjusted
-** properly prior to entry to point at the beginning of the surface.
-**
-** Since surface header information is completely relative, we can't
-** just randomly seek to an arbitrary surface location right now.  Is
-** this something we should add?
-*/
-void WriteModelSurface( FILE *modelouthandle, md3SurfaceData_t *pSurfData )
-{
-	md3Surface_t	*pSurf = &pSurfData->header;
-	md3Shader_t		*pShader = pSurfData->shaders;
-	baseVertex_t	*pBaseVertex = pSurfData->baseVertexes;
-	float			**verts = pSurfData->verts;
-
-	short xyznormals[MD3_MAX_VERTS][4];
-
-	float base_st[MD3_MAX_VERTS][2];
-	md3Surface_t surftemp;
-
-	int f, i, j, k;
-
-	if ( strstr( pSurf->name, "tag_" ) == pSurf->name )
-		return;
-
-	//
-	// write out the header
-	//
-	surftemp = *pSurf;
-	surftemp.ident = LittleLong( MD3_IDENT );
-	surftemp.flags = LittleLong( pSurf->flags );
-	surftemp.numFrames = LittleLong( pSurf->numFrames );
-	surftemp.numShaders = LittleLong( pSurf->numShaders );
-
-	surftemp.ofsShaders = LittleLong( pSurf->ofsShaders );
-
-	surftemp.ofsTriangles = LittleLong( pSurf->ofsTriangles );
-	surftemp.numTriangles = LittleLong( pSurf->numTriangles );
-
-	surftemp.ofsSt = LittleLong( pSurf->ofsSt );
-	surftemp.ofsXyzNormals = LittleLong( pSurf->ofsXyzNormals );
-	surftemp.ofsEnd = LittleLong( pSurf->ofsEnd );
-
-	SafeWrite( modelouthandle, &surftemp, sizeof( surftemp ) );
-
-	if ( g_verbose )
-	{
-		printf( "surface '%s'\n", pSurf->name );
-		printf( "...num shaders: %d\n", pSurf->numShaders );
-	}
-
-	//
-	// write out shaders
-	//
-	for ( i = 0; i < pSurf->numShaders; i++ )
-	{
-		md3Shader_t shadertemp;
-
-		if ( g_verbose )
-			printf( "......'%s'\n", pShader[i].name );
-
-		shadertemp = pShader[i];
-		shadertemp.shaderIndex = LittleLong( shadertemp.shaderIndex );
-		SafeWrite( modelouthandle, &shadertemp, sizeof( shadertemp ) );
-	}
-
-	//
-	// write out the triangles
-	//
-	for ( i = 0 ; i < pSurf->numTriangles ; i++ ) 
-	{
-		for (j = 0 ; j < 3 ; j++) 
-		{
-			int ivalue = LittleLong( pSurfData->orderedTriangles[i][j] );
-			pSurfData->orderedTriangles[i][j] = ivalue;
-		}
-	}
-
-	SafeWrite( modelouthandle, pSurfData->orderedTriangles, pSurf->numTriangles * sizeof( g_data.surfData[0].orderedTriangles[0] ) );
-
-	if ( g_verbose )
-	{
-		printf( "\n...num verts: %d\n", pSurf->numVerts );
-		printf( "...TEX COORDINATES\n" );
-	}
-
-	//
-	// write out the texture coordinates
-	//
-	for ( i = 0; i < pSurf->numVerts ; i++) {
-		base_st[i][0] = LittleFloat( pBaseVertex[i].st[0] );
-		base_st[i][1] = LittleFloat( pBaseVertex[i].st[1] );
-		if ( g_verbose )
-			printf( "......%d: %f,%f\n", i, base_st[i][0], base_st[i][1] );
-	}
-	SafeWrite( modelouthandle, base_st, pSurf->numVerts * sizeof(base_st[0]));
-
-	//
-	// write the xyz_normal
-	//
-	if ( g_verbose )
-		printf( "...XYZNORMALS\n" );
-	for ( f = 0; f < g_data.model.numFrames; f++ )
-	{
-		for (j=0 ; j< pSurf->numVerts; j++) 
-		{
-			short value;
-
-			for (k=0 ; k < 3 ; k++) 
-			{
-				value = ( short ) ( verts[f][j*6+k] / MD3_XYZ_SCALE );
-				xyznormals[j][k] = LittleShort( value );
-			}
-			NormalToLatLong( &verts[f][j*6+3], (byte *)&xyznormals[j][3] );
-		}
-		SafeWrite( modelouthandle, xyznormals, pSurf->numVerts * sizeof( short ) * 4 );
-	}
-}
-
-/*
-** void WriteModelFile( FILE *modelouthandle )
-**
-** CHUNK			SIZE
-** header			sizeof( md3Header_t )
-** frames			sizeof( md3Frame_t ) * numFrames
-** tags				sizeof( md3Tag_t ) * numFrames * numTags
-** surfaces			surfaceSum
-*/
-void WriteModelFile( FILE *modelouthandle )
-{
-	int				f;
-	int				i, j;
-	md3Header_t		modeltemp;
-	long			surfaceSum = 0;
-	int				numRealSurfaces = 0;
-	int				numFrames = g_data.model.numFrames;
-
-	// compute offsets for all surfaces, sum their total size
-	for ( i = 0; i < g_data.model.numSurfaces; i++ )
-	{
-		if ( strstr( g_data.surfData[i].header.name, "tag_" ) != g_data.surfData[i].header.name )
-		{
-			md3Surface_t *psurf = &g_data.surfData[i].header;
-
-			if ( psurf->numTriangles == 0 || psurf->numVerts == 0 )
-				continue;
-
-			//
-			// the triangle and vertex split threshold is controlled by a parameter
-			// to $base, a la $base blah.3ds 1900, where "1900" determines the number
-			// of triangles to split on
-			//
-			else if ( psurf->numVerts > MAX_SURFACE_VERTS )
-			{
-				Error( "too many vertices\n" );
-			}
-
-			psurf->numFrames = numFrames;
-
-			psurf->ofsShaders = sizeof( md3Surface_t );
-
-			if ( psurf->numTriangles > MAX_SURFACE_TRIS  ) 
-			{
-				Error( "too many faces\n" );
-			}
-
-			psurf->ofsTriangles = psurf->ofsShaders + psurf->numShaders * sizeof( md3Shader_t );
-
-			psurf->ofsSt = psurf->ofsTriangles + psurf->numTriangles * sizeof( md3Triangle_t );
-			psurf->ofsXyzNormals = psurf->ofsSt + psurf->numVerts * sizeof( md3St_t );
-			psurf->ofsEnd = psurf->ofsXyzNormals + psurf->numFrames * psurf->numVerts * ( sizeof( short ) * 4 );
-
-			surfaceSum += psurf->ofsEnd;
-
-			numRealSurfaces++;
-		}
-	}
-
-	g_data.model.ident = MD3_IDENT;
-	g_data.model.version = MD3_VERSION;
-
-	g_data.model.ofsFrames = sizeof(md3Header_t);
-	g_data.model.ofsTags = g_data.model.ofsFrames + numFrames*sizeof(md3Frame_t);
-	g_data.model.ofsSurfaces = g_data.model.ofsTags + numFrames*g_data.model.numTags*sizeof(md3Tag_t);
-	g_data.model.ofsEnd = g_data.model.ofsSurfaces + surfaceSum;
-
-	//
-	// write out the model header
-	//
-	modeltemp = g_data.model;
-	modeltemp.ident = LittleLong( modeltemp.ident );
-	modeltemp.version = LittleLong( modeltemp.version );
-	modeltemp.numFrames = LittleLong( modeltemp.numFrames );
-	modeltemp.numTags = LittleLong( modeltemp.numTags );
-	modeltemp.numSurfaces = LittleLong( numRealSurfaces );
-	modeltemp.ofsFrames = LittleLong( modeltemp.ofsFrames );
-	modeltemp.ofsTags = LittleLong( modeltemp.ofsTags );
-	modeltemp.ofsSurfaces = LittleLong( modeltemp.ofsSurfaces );
-	modeltemp.ofsEnd = LittleLong( modeltemp.ofsEnd );
-
-	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
-
-	//
-	// write out the frames
-	//
-	for (i=0 ; i < numFrames ; i++) 
-	{
-		vec3_t tmpVec;
-		float maxRadius = 0;
-
-		//
-		// compute localOrigin and radius
-		//
-		g_data.frames[i].localOrigin[0] =
-		g_data.frames[i].localOrigin[1] =
-		g_data.frames[i].localOrigin[2] = 0;
-
-		for ( j = 0; j < 8; j++ )
-		{
-			tmpVec[0] = g_data.frames[i].bounds[(j&1)!=0][0];
-			tmpVec[1] = g_data.frames[i].bounds[(j&2)!=0][1];
-			tmpVec[2] = g_data.frames[i].bounds[(j&4)!=0][2];
-
-			if ( VectorLength( tmpVec ) > maxRadius )
-				maxRadius = VectorLength( tmpVec );
-		}
-
-		g_data.frames[i].radius = LittleFloat( maxRadius );
-
-		// swap
-		for (j=0 ; j<3 ; j++) {
-			g_data.frames[i].bounds[0][j] = LittleFloat( g_data.frames[i].bounds[0][j] );
-			g_data.frames[i].bounds[1][j] = LittleFloat( g_data.frames[i].bounds[1][j] );
-			g_data.frames[i].localOrigin[j] = LittleFloat( g_data.frames[i].localOrigin[j] );
-		}
-	}
-	fseek (modelouthandle, g_data.model.ofsFrames, SEEK_SET);
-	SafeWrite( modelouthandle, g_data.frames, numFrames * sizeof(g_data.frames[0]) );
-
-	//
-	// write out the tags
-	//
-	fseek( modelouthandle, g_data.model.ofsTags, SEEK_SET );
-	for (f=0 ; f<g_data.model.numFrames; f++) 
-	{
-		int t;
-
-		for ( t = 0; t < g_data.model.numTags; t++ )
-		{
-			g_data.tags[f][t].origin[0] = LittleFloat(g_data.tags[f][t].origin[0]);
-			g_data.tags[f][t].origin[1] = LittleFloat(g_data.tags[f][t].origin[1]);
-			g_data.tags[f][t].origin[2] = LittleFloat(g_data.tags[f][t].origin[2]);
-
-			for (j=0 ; j<3 ; j++) 
-			{
-				g_data.tags[f][t].axis[0][j] = LittleFloat(g_data.tags[f][t].axis[0][j]);
-				g_data.tags[f][t].axis[1][j] = LittleFloat(g_data.tags[f][t].axis[1][j]);
-				g_data.tags[f][t].axis[2][j] = LittleFloat(g_data.tags[f][t].axis[2][j]);
-			}
-		}
-		SafeWrite( modelouthandle, g_data.tags[f], g_data.model.numTags * sizeof(md3Tag_t) );
-	}
-
-	//
-	// write out the surfaces
-	//
-	fseek( modelouthandle, g_data.model.ofsSurfaces, SEEK_SET );
-	for ( i = 0; i < g_data.model.numSurfaces; i++ )
-	{
-		WriteModelSurface( modelouthandle, &g_data.surfData[i] );
-	}
-}
-
-
-/*
-===============
-FinishModel
-===============
-*/
-void FinishModel ( int type )
-{
-	FILE		*modelouthandle;
-	FILE		*defaultSkinHandle;
-	char		name[1024];
-	int			i;
-
-	if (!g_data.model.numFrames)
-		return;
-
-	//
-	// build generalized triangle strips
-	//
-	OrderSurfaces();
-
-	if ( type == TYPE_PLAYER )
-	{
-		sprintf( name, "%s%s", writedir, g_modelname );
-		*strrchr( name, '.' ) = 0;
-		strcat( name, "_default.skin" );
-
-		defaultSkinHandle = fopen( name, "wt" );
-		for ( i = 0; i < g_data.model.numSurfaces; i++ )
-		{
-			fprintf( defaultSkinHandle, "%s,%s\n", g_data.surfData[i].header.name, g_data.surfData[i].shaders[0].name );
-		}
-		fclose( defaultSkinHandle );
-	}
-
-	sprintf (name, "%s%s", writedir, g_modelname);
-
-	//
-	// copy the model and its shaders to release directory tree 
-	// if doing a release build
-	//
-	if ( g_release ) {
-		int			i, j;
-		md3SurfaceData_t *pSurf;
-
-		ReleaseFile( g_modelname );
-
-		for ( i = 0; i < g_data.model.numSurfaces; i++ ) {
-			pSurf = &g_data.surfData[i];
-			for ( j = 0; j < g_data.model.numSkins; j++ ) {
-				ReleaseShader( pSurf->shaders[j].name );
-			}
-		}		
-		return;
-	}
-	
-	//
-	// write the model output file
-	//
-	printf ("saving to %s\n", name);
-	CreatePath (name);
-	modelouthandle = SafeOpenWrite (name);
-
-	WriteModelFile (modelouthandle);
-	
-	printf ("%4d surfaces\n", g_data.model.numSurfaces);
-	printf ("%4d frames\n", g_data.model.numFrames);
-	printf ("%4d tags\n", g_data.model.numTags);
-	printf ("file size: %d\n", (int)ftell (modelouthandle) );
-	printf ("---------------------\n");
-	
-	fclose (modelouthandle);
-}
-
-/*
-** OrderSurfaces
-**
-** Reorders triangles in all the surfaces.
-*/
-static void OrderSurfaces( void )
-{
-	int s;
-	extern qboolean g_stripify;
-
-	// go through each surface and find best strip/fans possible
-	for ( s = 0; s < g_data.model.numSurfaces; s++ )
-	{
-		int mesh[MD3_MAX_TRIANGLES][3];
-		int i;
-
-		printf( "stripifying surface %d/%d with %d tris\n", s, g_data.model.numSurfaces, g_data.surfData[s].header.numTriangles );
-
-		for ( i = 0; i < g_data.surfData[s].header.numTriangles; i++ )
-		{
-			mesh[i][0] = g_data.surfData[s].lodTriangles[i][0];
-			mesh[i][1] = g_data.surfData[s].lodTriangles[i][1];
-			mesh[i][2] = g_data.surfData[s].lodTriangles[i][2];
-		}
-
-		if ( g_stripify )
-		{
-			OrderMesh( mesh,									// input
-					   g_data.surfData[s].orderedTriangles,		// output
-					   g_data.surfData[s].header.numTriangles );
-		}
-		else
-		{
-			memcpy( g_data.surfData[s].orderedTriangles, mesh, sizeof( int ) * 3 * g_data.surfData[s].header.numTriangles );
-		}
-	}
-}
-
-
-/*
-===============================================================
-
-BASE FRAME SETUP
-
-===============================================================
-*/
-/*
-============
-CopyTrianglesToBaseTriangles
-
-============
-*/
-static void CopyTrianglesToBaseTriangles(triangle_t *ptri, int numtri, baseTriangle_t *bTri )
-{
-	int			i;
-//	int			width, height, iwidth, iheight, swidth;
-//	float		s_scale, t_scale;
-//	float		scale;
-//	vec3_t		mins, maxs;
-	float		*pbasevert;
-
-/*
-	//
-	// find bounds of all the verts on the base frame
-	//
-	ClearBounds (mins, maxs);
-	
-	for (i=0 ; i<numtri ; i++)
-		for (j=0 ; j<3 ; j++)
-			AddPointToBounds (ptri[i].verts[j], mins, maxs);
-	
-	for (i=0 ; i<3 ; i++)
-	{
-		mins[i] = floor(mins[i]);
-		maxs[i] = ceil(maxs[i]);
-	}
-	
-	width = maxs[0] - mins[0];
-	height = maxs[2] - mins[2];
-
-	if (!g_data.fixedwidth)
-	{	// old style
-		scale = 8;
-		if (width*scale >= 150)
-			scale = 150.0 / width;	
-		if (height*scale >= 190)
-			scale = 190.0 / height;
-
-		s_scale = t_scale = scale;
-
-		iwidth = ceil(width*s_scale);
-		iheight = ceil(height*t_scale);
-
-		iwidth += 4;
-		iheight += 4;
-	}
-	else
-	{	// new style
-		iwidth = g_data.fixedwidth / 2;
-		iheight = g_data.fixedheight;
-
-		s_scale = (float)(iwidth-4) / width;
-		t_scale = (float)(iheight-4) / height;
-	}
-
-	// make the width a multiple of 4; some hardware requires this, and it ensures
-	// dword alignment for each scan
-	swidth = iwidth*2;
-	g_data.skinwidth = (swidth + 3) & ~3;
-	g_data.skinheight = iheight;
-*/
-
-	for (i=0; i<numtri ; i++, ptri++, bTri++)
-	{
-		int j;
-
-		for (j=0 ; j<3 ; j++) 
-		{
-			pbasevert = ptri->verts[j];
-
-			VectorCopy( ptri->verts[j], bTri->v[j].xyz);
-			VectorCopy( ptri->normals[j], bTri->v[j].normal );
-
-			bTri->v[j].st[0] = ptri->texcoords[j][0];
-			bTri->v[j].st[1] = ptri->texcoords[j][1];
-		}
-	}
-}
-
-static void BuildBaseFrame( const char *filename, ObjectAnimationFrame_t *pOAF )
-{
-	baseTriangle_t	*bTri;
-	baseVertex_t	*bVert;
-	int i, j;
-
-	// calculate the base triangles
-	for ( i = 0; i < g_data.model.numSurfaces; i++ )
-	{
-		CopyTrianglesToBaseTriangles( pOAF->surfaces[i]->triangles, 
-					                pOAF->surfaces[i]->numtriangles,
-									g_data.surfData[i].baseTriangles );
-
-		strcpy( g_data.surfData[i].header.name, pOAF->surfaces[i]->name );
-
-		g_data.surfData[i].header.numTriangles = pOAF->surfaces[i]->numtriangles;
-		g_data.surfData[i].header.numVerts = 0;
-
-/*
-		if ( strstr( filename, gamedir + 1 ) )
-		{
-			strcpy( shaderName, strstr( filename, gamedir + 1 ) + strlen( gamedir ) - 1 );
-		}
-		else
-		{
-			strcpy( shaderName, filename );
-		}
-
-		if ( strrchr( shaderName, '/' ) )
-			*( strrchr( shaderName, '/' ) + 1 ) = 0;
-
-
-		strcpy( shaderName, pOAF->surfaces[i]->materialname );
-*/
-		strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, pOAF->surfaces[i]->materialname );
-
-		g_data.surfData[i].header.numShaders++;
-	}
-
-	//
-	// compute unique vertices for each polyset
-	//
-	for ( i = 0; i < g_data.model.numSurfaces; i++ )
-	{
-		int t;
-
-		for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
-		{
-			bTri = &g_data.surfData[i].baseTriangles[t];
-
-			for (j=0 ; j<3 ; j++)
-			{
-				int k;
-
-				bVert = &bTri->v[j];
-
-				// get the xyz index
-				for ( k = 0; k < g_data.surfData[i].header.numVerts; k++ )
-				{
-					if ( ( g_data.surfData[i].baseVertexes[k].st[0] == bVert->st[0] ) &&
-						 ( g_data.surfData[i].baseVertexes[k].st[1] == bVert->st[1] ) &&
-						 ( VectorCompare (bVert->xyz, g_data.surfData[i].baseVertexes[k].xyz) ) &&
-						 ( VectorCompare (bVert->normal, g_data.surfData[i].baseVertexes[k].normal) ) )
-					{
-						break;	// this vertex is already in the base vertex list
-					}
-				}
-
-				if (k == g_data.surfData[i].header.numVerts)	{ // new index
-					g_data.surfData[i].baseVertexes[g_data.surfData[i].header.numVerts] = *bVert;
-					g_data.surfData[i].header.numVerts++;
-				}
-
-				bVert->index = k;
-
-				g_data.surfData[i].lodTriangles[t][j] = k;
-			}
-		}
-	}
-
-	//
-	// find tags
-	//
-	for ( i = 0; i < g_data.model.numSurfaces; i++ )
-	{
-		if ( strstr( pOAF->surfaces[i]->name, "tag_" ) == pOAF->surfaces[i]->name )
-		{
-			if ( pOAF->surfaces[i]->numtriangles != 1 )
-			{
-				Error( "tag polysets must consist of only one triangle" );
-			}
-			if ( strstr( filename, "_flash.md3" ) && !strcmp( pOAF->surfaces[i]->name, "tag_parent" ) )
-				continue;
-			printf( "found tag '%s'\n", pOAF->surfaces[i]->name );
-			g_data.model.numTags++;
-		}
-	}
-
-}
-
-static int LoadModelFile( const char *filename, polyset_t **psets, int *numpolysets )
-{
-	int			time1;
-	char		file1[1024];
-	const char			*frameFile;
-
-	printf ("---------------------\n");
-	if ( filename[1] != ':' )
-	{
-		frameFile = filename;
-		sprintf( file1, "%s/%s", g_cddir, frameFile );
-	}
-	else
-	{
-		strcpy( file1, filename );
-	}
-
-	time1 = FileTime (file1);
-	if (time1 == -1)
-		Error ("%s doesn't exist", file1);
-
-	//
-	// load the base triangles
-	//
-	*psets = Polyset_LoadSets( file1, numpolysets, g_data.maxSurfaceTris );
-
-	//
-	// snap polysets
-	//
-	Polyset_SnapSets( *psets, *numpolysets );
-
-	if ( strstr( file1, ".3ds" ) || strstr( file1, ".3DS" ) )
-		return MD3_TYPE_BASE3DS;
-
-	Error( "Unknown model file type" );
-
-	return MD3_TYPE_UNKNOWN;
-}
-
-/*
-=================
-Cmd_Base
-=================
-*/
-void Cmd_Base( void )
-{
-	char filename[1024];
-
-	GetToken( qfalse );
-	sprintf( filename, "%s/%s", g_cddir, token );
-	LoadBase( filename );
-}
-
-static void LoadBase( const char *filename )
-{
-	int numpolysets;
-	polyset_t *psets;
-	int			i;
-	ObjectAnimationFrame_t oaf;
-
-	// determine polyset splitting threshold
-	if ( TokenAvailable() )
-	{
-		GetToken( qfalse );
-		g_data.maxSurfaceTris = atoi( token );
-	}
-	else
-	{
-		g_data.maxSurfaceTris = MAX_SURFACE_TRIS - 1;
-	}
-
-	g_data.type = LoadModelFile( filename, &psets, &numpolysets );
-
-	Polyset_ComputeNormals( psets, numpolysets );
-
-	g_data.model.numSurfaces = numpolysets;
-
-	memset( &oaf, 0, sizeof( oaf ) );
-
-	for ( i = 0; i < numpolysets; i++ )
-	{
-		oaf.surfaces[i] = &psets[i];
-		oaf.numSurfaces = numpolysets;
-	}
-
-	BuildBaseFrame( filename, &oaf );
-
-	free( psets[0].triangles );
-	free( psets );
-}
-
-/*
-=================
-Cmd_SpriteBase
-
-$spritebase xorg yorg width height
-
-Generate a single square for the model
-=================
-*/
-void Cmd_SpriteBase (void)
-{
-	float		xl, yl, width, height;
-
-	g_data.type = MD3_TYPE_SPRITE;
-
-	GetToken (qfalse);
-	xl = atof(token);
-	GetToken (qfalse);
-	yl = atof(token);
-	GetToken (qfalse);
-	width = atof(token);
-	GetToken (qfalse);
-	height = atof(token);
-
-//	if (g_skipmodel || g_release || g_archive)
-//		return;
-
-	printf ("---------------------\n");
-
-	g_data.surfData[0].verts[0] = ( float * ) calloc( 1, sizeof( float ) * 6 * 4 );
-
-	g_data.surfData[0].header.numVerts = 4;
-
-	g_data.surfData[0].verts[0][0+0] = 0;
-	g_data.surfData[0].verts[0][0+1] = -xl;
-	g_data.surfData[0].verts[0][0+2] = yl + height;
-
-	g_data.surfData[0].verts[0][0+3] = -1;
-	g_data.surfData[0].verts[0][0+4] = 0;
-	g_data.surfData[0].verts[0][0+5] = 0;
-	g_data.surfData[0].baseVertexes[0].st[0] = 0;
-	g_data.surfData[0].baseVertexes[0].st[1] = 0;
-
-
-	g_data.surfData[0].verts[0][6+0] = 0;
-	g_data.surfData[0].verts[0][6+1] = -xl - width;
-	g_data.surfData[0].verts[0][6+2] = yl + height;
-	
-	g_data.surfData[0].verts[0][6+3] = -1;
-	g_data.surfData[0].verts[0][6+4] = 0;
-	g_data.surfData[0].verts[0][6+5] = 0;
-	g_data.surfData[0].baseVertexes[1].st[0] = 1;
-	g_data.surfData[0].baseVertexes[1].st[1] = 0;
-
-
-	g_data.surfData[0].verts[0][12+0] = 0;
-	g_data.surfData[0].verts[0][12+1] = -xl - width;
-	g_data.surfData[0].verts[0][12+2] = yl;
-
-	g_data.surfData[0].verts[0][12+3] = -1;
-	g_data.surfData[0].verts[0][12+4] = 0;
-	g_data.surfData[0].verts[0][12+5] = 0;
-	g_data.surfData[0].baseVertexes[2].st[0] = 1;
-	g_data.surfData[0].baseVertexes[2].st[1] = 1;
-
-
-	g_data.surfData[0].verts[0][18+0] = 0;
-	g_data.surfData[0].verts[0][18+1] = -xl;
-	g_data.surfData[0].verts[0][18+2] = yl;
-
-	g_data.surfData[0].verts[0][18+3] = -1;
-	g_data.surfData[0].verts[0][18+4] = 0;
-	g_data.surfData[0].verts[0][18+5] = 0;
-	g_data.surfData[0].baseVertexes[3].st[0] = 0;
-	g_data.surfData[0].baseVertexes[3].st[1] = 1;
-
-	g_data.surfData[0].lodTriangles[0][0] = 0;
-	g_data.surfData[0].lodTriangles[0][1] = 1;
-	g_data.surfData[0].lodTriangles[0][2] = 2;
-
-	g_data.surfData[0].lodTriangles[1][0] = 2;
-	g_data.surfData[0].lodTriangles[1][1] = 3;
-	g_data.surfData[0].lodTriangles[1][2] = 0;
-
-	g_data.model.numSurfaces = 1;
-
-	g_data.surfData[0].header.numTriangles = 2;
-	g_data.surfData[0].header.numVerts = 4;
-
-	g_data.model.numFrames = 1;
-}
-
-/*
-===========================================================================
-
-  FRAME GRABBING
-
-===========================================================================
-*/
-
-/*
-===============
-GrabFrame
-===============
-*/
-void GrabFrame (const char *frame)
-{
-	int			i, j, k;
-	char		file1[1024];
-	md3Frame_t		*fr;
-	md3Tag_t		tagParent;
-	float		*frameXyz;
-	float		*frameNormals;
-	const char	*framefile;
-	polyset_t		*psets;
-	qboolean	 parentTagExists = qfalse;
-	int			 numpolysets;
-	int			numtags = 0;
-	int			tagcount;
-
-	// the frame 'run1' will be looked for as either
-	// run.1 or run1.tri, so the new alias sequence save
-	// feature an be used
-	if ( frame[1] != ':' )
-	{
-//		framefile = FindFrameFile (frame);
-		framefile = frame;
-		sprintf (file1, "%s/%s",g_cddir, framefile);
-	}
-	else
-	{
-		strcpy( file1, frame );
-	}
-	printf ("grabbing %s\n", file1);
-
-	if (g_data.model.numFrames >= MD3_MAX_FRAMES)
-		Error ("model.numFrames >= MD3_MAX_FRAMES");
-	fr = &g_data.frames[g_data.model.numFrames];
-
-	strcpy (fr->name, frame);
-
-	psets = Polyset_LoadSets( file1, &numpolysets, g_data.maxSurfaceTris );
-
-	//
-	// snap polysets
-	//
-	Polyset_SnapSets( psets, numpolysets );
-
-	//
-	// compute vertex normals
-	//
-	Polyset_ComputeNormals( psets, numpolysets );
-
-	//
-	// flip everything to compensate for the alias coordinate system
-	// and perform global scale and adjust
-	//
-	for ( i = 0; i < g_data.model.numSurfaces; i++ )
-	{
-		triangle_t *ptri = psets[i].triangles;
-		int t;
-
-		for ( t = 0; t < psets[i].numtriangles; t++ )
-		{
-
-			for ( j = 0; j < 3; j++ )
-			{
-
-				// scale and adjust
-				for ( k = 0 ; k < 3 ; k++ ) {
-					ptri[t].verts[j][k] = ptri[t].verts[j][k] * g_data.scale_up +
-						g_data.adjust[k];
-
-					if ( ptri[t].verts[j][k] > 1023 ||
-						 ptri[t].verts[j][k] < -1023 )
-					{
-						Error( "Model extents too large" );
-					}
-				}
-			}
-		}
-	}
-
-	//
-	// find and count tags, locate parent tag
-	//
-	for ( i = 0; i < numpolysets; i++ )
-	{
-		if ( strstr( psets[i].name, "tag_" ) == psets[i].name )
-		{
-			if ( strstr( psets[i].name, "tag_parent" ) == psets[i].name )
-			{
-				if ( strstr( psets[i].name, "tag_parent" ) )
-				{
-					float tri[3][3];
-
-					if ( parentTagExists )
-						Error( "Multiple parent tags not allowed" );
-
-					memcpy( tri[0], psets[i].triangles[0].verts[0], sizeof( float ) * 3 );
-					memcpy( tri[1], psets[i].triangles[0].verts[1], sizeof( float ) * 3 );
-					memcpy( tri[2], psets[i].triangles[0].verts[2], sizeof( float ) * 3 );
-
-					MD3_ComputeTagFromTri( &tagParent, tri );
-					strcpy( tagParent.name, psets[i].name );
-					g_data.tags[g_data.model.numFrames][numtags] = tagParent;
-					parentTagExists = qtrue;
-
-				}
-			}
-			numtags++;
-		}
-
-		if ( strcmp( psets[i].name, g_data.surfData[i].header.name ) )
-		{
-			Error( "Mismatched surfaces from base('%s') to frame('%s') in model '%s'\n", g_data.surfData[i].header.name, psets[i].name, g_modelname );
-		}
-	}
-
-	if ( numtags != g_data.model.numTags )
-	{
-		Error( "mismatched number of tags in frame(%d) vs. base(%d)", numtags, g_data.model.numTags );
-	}
-
-	if ( numpolysets != g_data.model.numSurfaces )
-	{
-		Error( "mismatched number of surfaces in frame(%d) vs. base(%d)", numpolysets-numtags, g_data.model.numSurfaces );
-	}
-	
-	//
-	// prepare to accumulate bounds and normals
-	//
-	ClearBounds( fr->bounds[0], fr->bounds[1] );
-
-	//
-	// store the frame's vertices in the same order as the base. This assumes the
-	// triangles and vertices in this frame are in exactly the same order as in the
-	// base
-	//
-	for ( i = 0, tagcount = 0; i < numpolysets; i++ )
-	{
-		int t;
-		triangle_t *pTris = psets[i].triangles;
-
-		strcpy( g_data.surfData[i].header.name, psets[i].name );
-
-		//
-		// parent tag adjust
-		//
-		if ( parentTagExists ) {
-			for ( t = 0; t < psets[i].numtriangles; t++ )
-			{
-				for ( j = 0; j < 3 ; j++ )
-				{
-					vec3_t tmp;
-					
-					VectorSubtract( pTris[t].verts[j], tagParent.origin, tmp );
-
-					pTris[t].verts[j][0] = DotProduct( tmp, tagParent.axis[0] );
-					pTris[t].verts[j][1] = DotProduct( tmp, tagParent.axis[1] );
-					pTris[t].verts[j][2] = DotProduct( tmp, tagParent.axis[2] );
-
-					VectorCopy( pTris[t].normals[j], tmp );
-					pTris[t].normals[j][0] = DotProduct( tmp, tagParent.axis[0] );
-					pTris[t].normals[j][1] = DotProduct( tmp, tagParent.axis[1] );
-					pTris[t].normals[j][2] = DotProduct( tmp, tagParent.axis[2] );
-				}
-			}
-		}
-
-		//
-		// compute tag data
-		//
-		if ( strstr( psets[i].name, "tag_" ) == psets[i].name )
-		{
-			md3Tag_t *pTag = &g_data.tags[g_data.model.numFrames][tagcount];
-			float tri[3][3];
-
-			strcpy( pTag->name, psets[i].name );
-
-			memcpy( tri[0], pTris[0].verts[0], sizeof( float ) * 3 );
-			memcpy( tri[1], pTris[0].verts[1], sizeof( float ) * 3 );
-			memcpy( tri[2], pTris[0].verts[2], sizeof( float ) * 3 );
-
-			MD3_ComputeTagFromTri( pTag, tri );
-			tagcount++;
-		}
-		else
-		{
-			if ( g_data.surfData[i].verts[g_data.model.numFrames] )
-				free( g_data.surfData[i].verts[g_data.model.numFrames] );
-			frameXyz = g_data.surfData[i].verts[g_data.model.numFrames] = calloc( 1, sizeof( float ) * 6 * g_data.surfData[i].header.numVerts );
-			frameNormals = frameXyz + 3;
-
-			for ( t = 0; t < psets[i].numtriangles; t++ )
-			{
-				for ( j = 0; j < 3 ; j++ )
-				{
-					int index;
-
-					index = g_data.surfData[i].baseTriangles[t].v[j].index;
-					frameXyz[index*6+0] = pTris[t].verts[j][0];
-					frameXyz[index*6+1] = pTris[t].verts[j][1];
-					frameXyz[index*6+2] = pTris[t].verts[j][2];
-					frameNormals[index*6+0] =  pTris[t].normals[j][0];
-					frameNormals[index*6+1] =  pTris[t].normals[j][1];
-					frameNormals[index*6+2] =  pTris[t].normals[j][2];
-					AddPointToBounds (&frameXyz[index*6], fr->bounds[0], fr->bounds[1] );
-				}
-			}
-		}
-	}
-
-	g_data.model.numFrames++;
-
-	// only free the first triangle array, all of the psets in this array share the
-	// same triangle pool!!!
-//	free( psets[0].triangles );
-//	free( psets );
-}
-
-//===========================================================================
-
-
-
-/*
-===============
-Cmd_Frame	
-===============
-*/
-void Cmd_Frame (void)
-{
-	while (TokenAvailable())
-	{
-		GetToken (qfalse);
-		if (g_skipmodel)
-			continue;
-		if (g_release || g_archive)
-		{
-			g_data.model.numFrames = 1;	// don't skip the writeout
-			continue;
-		}
-
-		GrabFrame( token );
-	}
-}
-
-
-/*
-===============
-Cmd_Skin
-
-===============
-*/
-void SkinFrom3DS( const char *filename )
-{
-	polyset_t *psets;
-	char name[1024];
-	int numPolysets;
-	int i;
-
-	_3DS_LoadPolysets( filename, &psets, &numPolysets, g_verbose );
-
-	for ( i = 0; i < numPolysets; i++ )
-	{
-/*
-		if ( strstr( filename, gamedir + 1 ) )
-		{
-			strcpy( name, strstr( filename, gamedir + 1 ) + strlen( gamedir ) - 1 );
-		}
-		else
-		{
-			strcpy( name, filename );
-		}
-
-		if ( strrchr( name, '/' ) )
-			*( strrchr( name, '/' ) + 1 ) = 0;
-*/
-		strcpy( name, psets[i].materialname );
-		strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, name );
-
-		g_data.surfData[i].header.numShaders++;
-	}
-
-	free( psets[0].triangles );
-	free( psets );
-}
-
-void Cmd_Skin (void)
-{
-	char skinfile[1024];
-
-	if ( g_data.type == MD3_TYPE_BASE3DS )
-	{
-		GetToken( qfalse );
-
-		sprintf( skinfile, "%s/%s", g_cddir, token );
-
-		if ( strstr( token, ".3ds" ) || strstr( token, ".3DS" ) )
-		{
-			SkinFrom3DS( skinfile );
-		}
-		else
-		{
-			Error( "Unknown file format for $skin '%s'\n", skinfile );
-		}
-	}
-	else
-	{
-		Error( "invalid model type while processing $skin" );
-	}
-
-	g_data.model.numSkins++;
-}
-
-/*
-=================
-Cmd_SpriteShader
-=================
-
-This routine is also called for $oldskin
-
-*/
-void Cmd_SpriteShader()
-{
-	GetToken( qfalse );
-	strcpy( g_data.surfData[0].shaders[g_data.surfData[0].header.numShaders].name, token );
-	g_data.surfData[0].header.numShaders++;
-	g_data.model.numSkins++;
-}
-
-/*
-=================
-Cmd_Origin
-=================
-*/
-void Cmd_Origin (void)
-{
-	// rotate points into frame of reference so model points down the
-	// positive x axis
-	// FIXME: use alias native coordinate system
-	GetToken (qfalse);
-	g_data.adjust[1] = -atof (token);
-
-	GetToken (qfalse);
-	g_data.adjust[0] = atof (token);
-
-	GetToken (qfalse);
-	g_data.adjust[2] = -atof (token);
-}
-
-
-/*
-=================
-Cmd_ScaleUp
-=================
-*/
-void Cmd_ScaleUp (void)
-{
-	GetToken (qfalse);
-	g_data.scale_up = atof (token);
-	if (g_skipmodel || g_release || g_archive)
-		return;
-
-	printf ("Scale up: %f\n", g_data.scale_up);
-}
-
-
-/*
-=================
-Cmd_Skinsize
-
-Set a skin size other than the default
-QUAKE3: not needed
-=================
-*/
-void Cmd_Skinsize (void)
-{
-	GetToken (qfalse);
-	g_data.fixedwidth = atoi(token);
-	GetToken (qfalse);
-	g_data.fixedheight = atoi(token);
-}
-
-/*
-=================
-Cmd_Modelname
-
-Begin creating a model of the given name
-=================
-*/
-void Cmd_Modelname (void)
-{
-	FinishModel ( TYPE_UNKNOWN );
-	ClearModel ();
-
-	GetToken (qfalse);
-	strcpy (g_modelname, token);
-	StripExtension (g_modelname);
-	strcat (g_modelname, ".md3");
-	strcpy (g_data.model.name, g_modelname);
-}
-
-/*
-===============
-fCmd_Cd
-===============
-*/
-void Cmd_Cd (void)
-{
-	if ( g_cddir[0]) {
-		Error ("$cd command without a $modelname");
-	}
-
-	GetToken (qfalse);
-
-	sprintf ( g_cddir, "%s%s", gamedir, token);
-
-	// if -only was specified and this cd doesn't match,
-	// skip the model (you only need to match leading chars,
-	// so you could regrab all monsters with -only models/monsters)
-	if (!g_only[0])
-		return;
-	if (strncmp(token, g_only, strlen(g_only)))
-	{
-		g_skipmodel = qtrue;
-		printf ("skipping %s\n", token);
-	}
-}
-
-void Convert3DStoMD3( const char *file )
-{
-	LoadBase( file );
-	GrabFrame( file );
-	SkinFrom3DS( file );
-
-	strcpy( g_data.model.name, g_modelname );
-
-	FinishModel( TYPE_UNKNOWN );
-	ClearModel();
-}
-
-/*
-** Cmd_3DSConvert
-*/
-void Cmd_3DSConvert()
-{
-	char file[1024];
-
-	FinishModel( TYPE_UNKNOWN );
-	ClearModel();
-
-	GetToken( qfalse );
-
-	sprintf( file, "%s%s", gamedir, token );
-	strcpy( g_modelname, token );
-	if ( strrchr( g_modelname, '.' ) )
-		*strrchr( g_modelname, '.' ) = 0;
-	strcat( g_modelname, ".md3" );
-
-	if ( FileTime( file ) == -1 )
-		Error( "%s doesn't exist", file );
-
-	if ( TokenAvailable() )
-	{
-		GetToken( qfalse );
-		g_data.scale_up = atof( token );
-	}
-
-	Convert3DStoMD3( file );
-}
-
-static void ConvertASE( const char *filename, int type, qboolean grabAnims );
-
-/*
-** Cmd_ASEConvert
-*/
-void Cmd_ASEConvert( qboolean grabAnims )
-{
-	char filename[1024];
-	int type = TYPE_ITEM;
-
-	FinishModel( TYPE_UNKNOWN );
-	ClearModel();
-
-	GetToken( qfalse );
-	sprintf( filename, "%s%s", gamedir, token );
-
-	strcpy (g_modelname, token);
-	StripExtension (g_modelname);
-	strcat (g_modelname, ".md3");
-	strcpy (g_data.model.name, g_modelname);
-
-	if ( !strstr( filename, ".ase" ) && !strstr( filename, ".ASE" ) )
-		strcat( filename, ".ASE" );
-
-	g_data.maxSurfaceTris = MAX_SURFACE_TRIS - 1;
-
-	while ( TokenAvailable() )
-	{
-		GetToken( qfalse );
-		if ( !strcmp( token, "-origin" ) )
-		{
-			if ( !TokenAvailable() )
-				Error( "missing parameter for -origin" );
-			GetToken( qfalse );
-			g_data.aseAdjust[1] = -atof( token );
-
-			if ( !TokenAvailable() )
-				Error( "missing parameter for -origin" );
-			GetToken( qfalse );
-			g_data.aseAdjust[0] = atof (token);
-
-			if ( !TokenAvailable() )
-				Error( "missing parameter for -origin" );
-			GetToken( qfalse );
-			g_data.aseAdjust[2] = -atof (token);
-		}
-		else if ( !strcmp( token, "-lod" ) )
-		{
-			if ( !TokenAvailable() )
-				Error( "No parameter for -lod" );
-			GetToken( qfalse );
-			g_data.currentLod = atoi( token );
-			if ( g_data.currentLod > MD3_MAX_LODS - 1 )
-			{
-				Error( "-lod parameter too large! (%d)\n", g_data.currentLod );
-			}
-
-			if ( !TokenAvailable() )
-				Error( "No second parameter for -lod" );
-			GetToken( qfalse );
-			g_data.lodBias = atof( token );
-		}
-		else if ( !strcmp( token, "-maxtris" ) )
-		{
-			if ( !TokenAvailable() )
-				Error( "No parameter for -maxtris" );
-			GetToken( qfalse );
-			g_data.maxSurfaceTris = atoi( token );
-		}
-		else if ( !strcmp( token, "-playerparms" ) )
-		{
-			if ( !TokenAvailable() )
-				Error( "missing skip start parameter for -playerparms" );
-			GetToken( qfalse );
-			g_data.lowerSkipFrameStart = atoi( token );
-
-#if 0
-			if ( !TokenAvailable() )
-				Error( "missing skip end parameter for -playerparms" );
-			GetToken( qfalse );
-			g_data.lowerSkipFrameEnd = atoi( token );
-#endif
-
-			if ( !TokenAvailable() )
-				Error( "missing upper parameter for -playerparms" );
-			GetToken( qfalse );
-			g_data.maxUpperFrames = atoi( token );
-
-			g_data.lowerSkipFrameEnd = g_data.maxUpperFrames - 1;
-
-#if 0
-			if ( !TokenAvailable() )
-				Error( "missing head parameter for -playerparms" );
-			GetToken( qfalse );
-			g_data.maxHeadFrames = atoi( token );
-#endif
-			g_data.maxHeadFrames = 1;
-
-			if ( type != TYPE_ITEM )
-				Error( "invalid argument" );
-
-			type = TYPE_PLAYER;
-		}
-		else if ( !strcmp( token, "-weapon" ) )
-		{
-			if ( type != TYPE_ITEM )
-				Error( "invalid argument" );
-
-			type = TYPE_WEAPON;
-		}
-	}
-
-	g_data.type = MD3_TYPE_ASE;
-
-	if ( type == TYPE_WEAPON && grabAnims )
-	{
-		Error( "can't grab anims with weapon models" );
-	}
-	if ( type == TYPE_PLAYER && !grabAnims )
-	{
-		Error( "player models must be converted with $aseanimconvert" );
-	}
-
-	if ( type == TYPE_WEAPON )
-	{
-		ConvertASE( filename, type, qfalse );
-		ConvertASE( filename, TYPE_HAND, qtrue );
-	}
-	else
-	{
-		ConvertASE( filename, type, grabAnims );
-	}
-}
-
-static int GetSurfaceAnimations( SurfaceAnimation_t sanims[MAX_ANIM_SURFACES], 
-								  const char *part,
-								  int skipFrameStart,
-								  int skipFrameEnd,
-								  int maxFrames )
-
-{
-	int numSurfaces;
-	int numValidSurfaces;
-	int i;
-	int numFrames = -1;
-
-	if ( ( numSurfaces = ASE_GetNumSurfaces() ) > MAX_ANIM_SURFACES )
-	{
-		Error( "Too many surfaces in ASE" );
-	}
-
-	for ( numValidSurfaces = 0, i = 0; i < numSurfaces; i++ )
-	{
-		polyset_t *splitSets;
-		int numNewFrames;
-		const char *surfaceName = ASE_GetSurfaceName( i );
-
-		if ( !surfaceName )
-		{
-			continue;
-//			Error( "Missing animation frames in model" );
-		}
-
-		if ( strstr( surfaceName, "tag_" ) || 
-			 !strcmp( part, "any" ) || 
-			 ( strstr( surfaceName, part ) == surfaceName ) )
-		{
-
-			// skip this if it's an inappropriate tag
-			if ( strcmp( part, "any" ) )
-			{
-				// ignore non-"tag_head" tags if this is the head
-				if ( !strcmp( part, "h_" ) && strstr( surfaceName, "tag_" ) && strcmp( surfaceName, "tag_head" ) )
-					continue;
-				// ignore "tag_head" if this is the legs
-				if ( !strcmp( part, "l_" ) && !strcmp( surfaceName, "tag_head" ) )
-					continue;
-				// ignore "tag_weapon" if this is the legs
-				if ( !strcmp( part, "l_" ) && !strcmp( surfaceName, "tag_weapon" ) )
-					continue;
-			}
-
-			if ( ( sanims[numValidSurfaces].frames = ASE_GetSurfaceAnimation( i, &sanims[numValidSurfaces].numFrames, skipFrameStart, skipFrameEnd, maxFrames ) ) != 0 )
-			{
-				splitSets = Polyset_SplitSets( sanims[numValidSurfaces].frames, sanims[numValidSurfaces].numFrames, &numNewFrames, g_data.maxSurfaceTris );
-				
-				if ( numFrames == -1 )
-					numFrames = sanims[numValidSurfaces].numFrames;
-				else if ( numFrames != sanims[numValidSurfaces].numFrames )
-					Error( "Different number of animation frames on surfaces" );
-				
-				if ( sanims[numValidSurfaces].frames != splitSets )
-				{
-					int j;
-
-					// free old data if we split the surfaces
-					for ( j = 0; j < sanims[numValidSurfaces].numFrames; j++ )
-					{
-						free( sanims[numValidSurfaces].frames[j].triangles );
-						free( sanims[numValidSurfaces].frames );
-					}
-					
-					sanims[numValidSurfaces].frames = splitSets;
-					sanims[numValidSurfaces].numFrames = numNewFrames;
-				}
-				Polyset_SnapSets( sanims[numValidSurfaces].frames, sanims[numValidSurfaces].numFrames );
-				Polyset_ComputeNormals( sanims[numValidSurfaces].frames, sanims[numValidSurfaces].numFrames );
-
-				numValidSurfaces++;
-			}
-		}
-	}
-
-	return numValidSurfaces;
-}
-
-static int SurfaceOrderToFrameOrder( SurfaceAnimation_t sanims[], ObjectAnimationFrame_t oanims[], int numSurfaces )
-{
-	int i, s;
-	int numFrames = -1;
-
-	/*
-	** we have the data here arranged in surface order, now we need to convert it to 
-	** frame order
-	*/
-	for ( i = 0, s = 0; i < numSurfaces; i++ )
-	{
-		int j;
-		
-		if ( sanims[i].frames )
-		{
-			if ( numFrames == -1 )
-				numFrames = sanims[i].numFrames;
-			else if ( numFrames != sanims[i].numFrames )
-				Error( "numFrames != sanims[i].numFrames (%d != %d)\n", numFrames, sanims[i].numFrames );
-
-			for ( j = 0; j < sanims[i].numFrames; j++ )
-			{
-				oanims[j].surfaces[s] = &sanims[i].frames[j];
-				oanims[j].numSurfaces = numSurfaces;
-			}
-			s++;
-		}
-	}
-
-	return numFrames;
-}
-
-static void WriteMD3( const char *_filename, ObjectAnimationFrame_t oanims[], int numFrames )
-{
-	char filename[1024];
-
-	strcpy( filename, _filename );
-	if ( strchr( filename, '.' ) )
-		*strchr( filename, '.' ) = 0;
-	strcat( filename, ".md3" );
-}
-
-static void BuildAnimationFromOAFs( const char *filename, ObjectAnimationFrame_t oanims[], int numFrames, int type )
-{
-	int f, i, j, tagcount;
-	float *frameXyz;
-	float *frameNormals;
-
-	g_data.model.numSurfaces = oanims[0].numSurfaces;
-	g_data.model.numFrames = numFrames;
-	if ( g_data.model.numFrames < 0)
-		Error ("model.numFrames < 0");
-	if ( g_data.model.numFrames >= MD3_MAX_FRAMES)
-		Error ("model.numFrames >= MD3_MAX_FRAMES");
-
-	// build base frame
-	BuildBaseFrame( filename, &oanims[0] );
-	
-	// build animation frames
-	for ( f = 0; f < numFrames; f++ )
-	{
-		ObjectAnimationFrame_t *pOAF = &oanims[f];
-		qboolean	parentTagExists = qfalse;
-		md3Tag_t	tagParent;
-		int			numtags = 0;
-		md3Frame_t		*fr;
-		
-		fr = &g_data.frames[f];
-		
-		strcpy( fr->name, "(from ASE)" );
-		
-		// scale and adjust frame
-		for ( i = 0; i < pOAF->numSurfaces; i++ )
-		{
-			triangle_t *pTris = pOAF->surfaces[i]->triangles;
-			int t;
-			
-			for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
-			{
-				for ( j = 0; j < 3; j++ )
-				{
-					int k;
-					
-					// scale and adjust
-					for ( k = 0 ; k < 3 ; k++ ) {
-						pTris[t].verts[j][k] = pTris[t].verts[j][k] * g_data.scale_up +
-							g_data.aseAdjust[k];
-						
-						if ( pTris[t].verts[j][k] > 1023 ||
-							pTris[t].verts[j][k] < -1023 )
-						{
-							Error( "Model extents too large" );
-						}
-					}
-				}
-			}
-		}
-		
-		//
-		// find and count tags, locate parent tag
-		//
-		for ( i = 0; i < pOAF->numSurfaces; i++ )
-		{
-			if ( strstr( pOAF->surfaces[i]->name, "tag_" ) == pOAF->surfaces[i]->name )
-			{
-				// ignore parent tags when grabbing a weapon model and this is the flash portion
-				if ( !strcmp( pOAF->surfaces[i]->name, "tag_parent" ) && strstr( filename, "_flash.md3" ) )
-				{
-					continue;
-				}
-				else if ( !strstr( filename, "_hand.md3" ) && (
-					 ( !strcmp( pOAF->surfaces[i]->name, "tag_parent" ) && !strstr( filename, "_flash.md3" ) ) ||
-					 ( !strcmp( pOAF->surfaces[i]->name, "tag_torso" ) && ( strstr( filename, "upper_" ) || strstr( filename, "upper.md3" ) ) ) ||
-					 ( !strcmp( pOAF->surfaces[i]->name, "tag_head" ) && ( strstr( filename, "head.md3" ) || strstr( filename, "head_" ) ) ) ||
-					 ( !strcmp( pOAF->surfaces[i]->name, "tag_flash" ) && strstr( filename, "_flash.md3" ) )|| 
-					 ( !strcmp( pOAF->surfaces[i]->name, "tag_weapon" ) && type == TYPE_WEAPON ) ) )
-				{
-					float tri[3][3];
-					
-					if ( parentTagExists )
-						Error( "Multiple parent tags not allowed" );
-					
-					memcpy( tri[0], pOAF->surfaces[i]->triangles[0].verts[0], sizeof( float ) * 3 );
-					memcpy( tri[1], pOAF->surfaces[i]->triangles[0].verts[1], sizeof( float ) * 3 );
-					memcpy( tri[2], pOAF->surfaces[i]->triangles[0].verts[2], sizeof( float ) * 3 );
-					
-					MD3_ComputeTagFromTri( &tagParent, tri );
-					strcpy( tagParent.name, "tag_parent" );
-					g_data.tags[f][numtags] = tagParent;
-					parentTagExists = qtrue;
-				}
-				else
-				{
-					float tri[3][3];
-				
-					memcpy( tri[0], pOAF->surfaces[i]->triangles[0].verts[0], sizeof( float ) * 3 );
-					memcpy( tri[1], pOAF->surfaces[i]->triangles[0].verts[1], sizeof( float ) * 3 );
-					memcpy( tri[2], pOAF->surfaces[i]->triangles[0].verts[2], sizeof( float ) * 3 );
-					
-					MD3_ComputeTagFromTri( &g_data.tags[f][numtags], tri );
-					strcpy( g_data.tags[f][numtags].name, pOAF->surfaces[i]->name );
-					if ( strstr( g_data.tags[f][numtags].name, "tag_flash" ) )
-						* ( strstr( g_data.tags[f][numtags].name, "tag_flash" ) + strlen( "tag_flash" ) ) = 0;
-				}
-
-				numtags++;
-			}
-			
-			if ( strcmp( pOAF->surfaces[i]->name, g_data.surfData[i].header.name ) )
-			{
-				Error( "Mismatched surfaces from base('%s') to frame('%s') in model '%s'\n", g_data.surfData[i].header.name, pOAF->surfaces[i]->name, filename );
-			}
-		}
-		
-		if ( numtags != g_data.model.numTags )
-		{
-			Error( "mismatched number of tags in frame(%d) vs. base(%d)", numtags, g_data.model.numTags );
-		}
-		
-		//
-		// prepare to accumulate bounds and normals
-		//
-		ClearBounds( fr->bounds[0], fr->bounds[1] );
-		
-		//
-		// store the frame's vertices in the same order as the base. This assumes the
-		// triangles and vertices in this frame are in exactly the same order as in the
-		// base
-		//
-		for ( i = 0, tagcount = 0; i < pOAF->numSurfaces; i++ )
-		{
-			int t;
-			triangle_t *pTris = pOAF->surfaces[i]->triangles;
-			
-			//
-			// parent tag adjust
-			//
-			if ( parentTagExists ) 
-			{
-				for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
-				{
-					for ( j = 0; j < 3 ; j++ )
-					{
-						vec3_t tmp;
-						
-						VectorSubtract( pTris[t].verts[j], tagParent.origin, tmp );
-						
-						pTris[t].verts[j][0] = DotProduct( tmp, tagParent.axis[0] );
-						pTris[t].verts[j][1] = DotProduct( tmp, tagParent.axis[1] );
-						pTris[t].verts[j][2] = DotProduct( tmp, tagParent.axis[2] );
-						
-						VectorCopy( pTris[t].normals[j], tmp );
-						pTris[t].normals[j][0] = DotProduct( tmp, tagParent.axis[0] );
-						pTris[t].normals[j][1] = DotProduct( tmp, tagParent.axis[1] );
-						pTris[t].normals[j][2] = DotProduct( tmp, tagParent.axis[2] );
-					}
-				}
-			}
-			
-			//
-			// compute tag data
-			//
-			if ( strstr( pOAF->surfaces[i]->name, "tag_" ) == pOAF->surfaces[i]->name )
-			{
-				md3Tag_t *pTag = &g_data.tags[f][tagcount];
-				float tri[3][3];
-				
-				strcpy( pTag->name, pOAF->surfaces[i]->name );
-				
-				memcpy( tri[0], pTris[0].verts[0], sizeof( float ) * 3 );
-				memcpy( tri[1], pTris[0].verts[1], sizeof( float ) * 3 );
-				memcpy( tri[2], pTris[0].verts[2], sizeof( float ) * 3 );
-				
-				MD3_ComputeTagFromTri( pTag, tri );
-				tagcount++;
-			}
-			else
-			{
-				if ( g_data.surfData[i].verts[f] )
-					free( g_data.surfData[i].verts[f] );
-				frameXyz = g_data.surfData[i].verts[f] = calloc( 1, sizeof( float ) * 6 * g_data.surfData[i].header.numVerts );
-				frameNormals = frameXyz + 3;
-				
-				for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
-				{
-					for ( j = 0; j < 3 ; j++ )
-					{
-						int index;
-						
-						index = g_data.surfData[i].baseTriangles[t].v[j].index;
-						frameXyz[index*6+0] = pTris[t].verts[j][0];
-						frameXyz[index*6+1] = pTris[t].verts[j][1];
-						frameXyz[index*6+2] = pTris[t].verts[j][2];
-						frameNormals[index*6+0] =  pTris[t].normals[j][0];
-						frameNormals[index*6+1] =  pTris[t].normals[j][1];
-						frameNormals[index*6+2] =  pTris[t].normals[j][2];
-						AddPointToBounds (&frameXyz[index*6], fr->bounds[0], fr->bounds[1] );
-					}
-				}
-			}
-		}
-	}
-
-	if ( strstr( filename, gamedir + 1 ) )
-	{
-		strcpy( g_modelname, strstr( filename, gamedir + 1 ) + strlen( gamedir ) - 1 );
-	}
-	else
-	{
-		strcpy( g_modelname, filename );
-	}
-
-	FinishModel( type );
-	ClearModel();
-}
-
-static void ConvertASE( const char *filename, int type, qboolean grabAnims )
-{
-	int i, j;
-	int numSurfaces;
-	int numFrames = -1;
-	SurfaceAnimation_t surfaceAnimations[MAX_ANIM_SURFACES];
-	ObjectAnimationFrame_t objectAnimationFrames[MAX_ANIM_FRAMES];
-	char outfilename[1024];
-
-	/*
-	** load ASE into memory
-	*/
-	ASE_Load( filename, g_verbose, grabAnims );
-
-	/*
-	** process parts
-	*/
-	if ( type == TYPE_ITEM )
-	{
-		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "any", -1, -1, -1 );
-
-		if ( numSurfaces <= 0 )
-			Error( "numSurfaces <= 0" );
-
-		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
-
-		if ( numFrames <= 0 )
-			Error( "numFrames <= 0" );
-
-		strcpy( outfilename, filename );
-		if ( strrchr( outfilename, '.' ) )
-			*( strrchr( outfilename, '.' ) + 1 ) = 0;
-		strcat( outfilename, "md3" );
-		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
-
-		// free memory
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( surfaceAnimations[i].frames )
-			{
-				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
-				{
-					free( surfaceAnimations[i].frames[j].triangles );
-				}
-				free( surfaceAnimations[i].frames );
-				surfaceAnimations[i].frames = 0;
-			}
-		}
-	}
-	else if ( type == TYPE_PLAYER )
-	{
-		qboolean tagTorso = qfalse;
-		qboolean tagHead = qfalse;
-		qboolean tagWeapon = qfalse;
-
-		//
-		// verify that all necessary tags exist
-		//
-		numSurfaces = ASE_GetNumSurfaces();
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( !strcmp( ASE_GetSurfaceName( i ), "tag_head" ) )
-			{
-				tagHead = qtrue;
-			}
-			if ( !strcmp( ASE_GetSurfaceName( i ), "tag_torso" ) )
-			{
-				tagTorso = qtrue;
-			}
-			if ( !strcmp( ASE_GetSurfaceName( i ), "tag_weapon" ) )
-			{
-				tagWeapon = qtrue;
-			}
-		}
-
-		if ( !tagWeapon )
-		{
-			Error( "Missing tag_weapon!" );
-		}
-		if ( !tagTorso )
-		{
-			Error( "Missing tag_torso!" );
-		}
-		if ( !tagWeapon )
-		{
-			Error( "Missing tag_weapon!" );
-		}
-
-		// get all upper body surfaces
-		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "u_", -1, -1, g_data.maxUpperFrames );
-		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
-		strcpy( outfilename, filename );
-		if ( strrchr( outfilename, '/' ) )
-			*( strrchr( outfilename, '/' ) + 1 ) = 0;
-
-		if ( g_data.currentLod == 0 )
-		{
-			strcat( outfilename, "upper.md3" );
-		}
-		else
-		{
-			char temp[128];
-
-			sprintf( temp, "upper_%d.md3", g_data.currentLod );
-			strcat( outfilename, temp );
-		}
-		
-		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
-
-		// free memory
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( surfaceAnimations[i].frames )
-			{
-				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
-				{
-					free( surfaceAnimations[i].frames[j].triangles );
-				}
-				free( surfaceAnimations[i].frames );
-				surfaceAnimations[i].frames = 0;
-			}
-		}
-
-		// get lower body surfaces
-		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "l_", g_data.lowerSkipFrameStart, g_data.lowerSkipFrameEnd, -1 );
-		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
-		strcpy( outfilename, filename );
-		if ( strrchr( outfilename, '/' ) )
-			*( strrchr( outfilename, '/' ) + 1 ) = 0;
-
-		if ( g_data.currentLod == 0 )
-		{
-			strcat( outfilename, "lower.md3" );
-		}
-		else
-		{
-			char temp[128];
-
-			sprintf( temp, "lower_%d.md3", g_data.currentLod );
-			strcat( outfilename, temp );
-		}
-		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
-
-		// free memory
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( surfaceAnimations[i].frames )
-			{
-				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
-				{
-					free( surfaceAnimations[i].frames[j].triangles );
-				}
-				free( surfaceAnimations[i].frames );
-				surfaceAnimations[i].frames = 0;
-			}
-		}
-
-		// get head surfaces
-		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "h_", -1, -1, g_data.maxHeadFrames );
-		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
-		strcpy( outfilename, filename );
-		if ( strrchr( outfilename, '/' ) )
-			*( strrchr( outfilename, '/' ) + 1 ) = 0;
-
-		if ( g_data.currentLod == 0 )
-		{
-			strcat( outfilename, "head.md3" );
-		}
-		else
-		{
-			char temp[128];
-
-			sprintf( temp, "head_%d.md3", g_data.currentLod );
-			strcat( outfilename, temp );
-		}
-		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
-
-		// free memory
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( surfaceAnimations[i].frames )
-			{
-				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
-				{
-					free( surfaceAnimations[i].frames[j].triangles );
-				}
-				free( surfaceAnimations[i].frames );
-				surfaceAnimations[i].frames = 0;
-			}
-		}
-	}
-	else if ( type == TYPE_WEAPON )
-	{
-		// get the weapon surfaces
-		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "w_", -1, -1, -1 );
-		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
-
-		strcpy( outfilename, filename );
-		if ( strrchr( outfilename, '.' ) )
-			*( strrchr( outfilename, '.' ) + 1 ) = 0;
-		strcat( outfilename, "md3" );
-		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
-
-		// free memory
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( surfaceAnimations[i].frames )
-			{
-				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
-				{
-					free( surfaceAnimations[i].frames[j].triangles );
-				}
-				free( surfaceAnimations[i].frames );
-				surfaceAnimations[i].frames = 0;
-			}
-		}
-
-		// get the flash surfaces
-		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "f_", -1, -1, -1 );
-		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
-
-		strcpy( outfilename, filename );
-		if ( strrchr( outfilename, '.' ) )
-			*strrchr( outfilename, '.' ) = 0;
-		strcat( outfilename, "_flash.md3" );
-		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, TYPE_ITEM );
-
-		// free memory
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( surfaceAnimations[i].frames )
-			{
-				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
-				{
-					free( surfaceAnimations[i].frames[j].triangles );
-				}
-				free( surfaceAnimations[i].frames );
-				surfaceAnimations[i].frames = 0;
-			}
-		}
-	}
-	else if ( type == TYPE_HAND )
-	{
-		// get the hand tags
-		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "tag_", -1, -1, -1 );
-		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
-
-		strcpy( outfilename, filename );
-		if ( strrchr( outfilename, '.' ) )
-			*strrchr( outfilename, '.' ) = 0;
-		strcat( outfilename, "_hand.md3" );
-		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, TYPE_HAND );
-
-		// free memory
-		for ( i = 0; i < numSurfaces; i++ )
-		{
-			if ( surfaceAnimations[i].frames )
-			{
-				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
-				{
-					free( surfaceAnimations[i].frames[j].triangles );
-				}
-				free( surfaceAnimations[i].frames );
-				surfaceAnimations[i].frames = 0;
-			}
-		}
-	}
-	else
-	{
-		Error( "Unknown type passed to ConvertASE()" );
-	}
-
-	g_data.currentLod = 0;
-	g_data.lodBias = 0;
-	g_data.maxHeadFrames = 0;
-	g_data.maxUpperFrames = 0;
-	g_data.lowerSkipFrameStart = 0;
-	g_data.lowerSkipFrameEnd = 0;
-	VectorCopy( vec3_origin, g_data.aseAdjust );
-
-	// unload ASE from memory
-	ASE_Free();
-}
+#include <assert.h>
+#include "q3data.h"
+
+//=================================================================
+
+static void OrderSurfaces( void );
+static void LoadBase( const char *filename );
+static int	LoadModelFile( const char *filename, polyset_t **ppsets, int *pnumpolysets );
+
+#define MAX_SURFACE_TRIS	(SHADER_MAX_INDEXES / 3)
+#define MAX_SURFACE_VERTS	SHADER_MAX_VERTEXES
+
+#define MD3_TYPE_UNKNOWN 0
+#define MD3_TYPE_BASE3DS 1
+#define MD3_TYPE_SPRITE  2
+#define MD3_TYPE_ASE	 3
+
+#define MAX_ANIM_FRAMES		512
+#define MAX_ANIM_SURFACES	32
+
+typedef struct
+{
+	polyset_t *frames;
+	int numFrames;
+} SurfaceAnimation_t;
+
+typedef struct
+{
+	polyset_t *surfaces[MAX_ANIM_SURFACES];
+	int numSurfaces;
+} ObjectAnimationFrame_t;
+
+typedef struct {
+	vec3_t		xyz;
+	vec3_t		normal;
+	vec3_t		color;
+	float		st[2];
+	int			index;
+} baseVertex_t;
+	
+typedef struct {
+	baseVertex_t	v[3];
+} baseTriangle_t;
+
+//================================================================
+
+typedef struct
+{
+	md3Surface_t	header;
+	md3Shader_t		shaders[MD3_MAX_SHADERS];
+	// all verts (xyz_normal)
+	float	*verts[MD3_MAX_FRAMES];
+
+	baseTriangle_t	baseTriangles[MD3_MAX_TRIANGLES];
+
+	// the triangles will be sorted so that they form long generalized tristrips
+	int				orderedTriangles[MD3_MAX_TRIANGLES][3];
+	int				lodTriangles[MD3_MAX_TRIANGLES][3];
+	baseVertex_t	baseVertexes[MD3_MAX_VERTS];
+
+} md3SurfaceData_t;
+
+typedef struct
+{
+	int			skinwidth, skinheight;
+	
+	md3SurfaceData_t surfData[MD3_MAX_SURFACES];
+
+	md3Tag_t		tags[MD3_MAX_FRAMES][MD3_MAX_TAGS];
+	md3Frame_t		frames[MD3_MAX_FRAMES];
+
+	md3Header_t	model;
+	float		scale_up;			// set by $scale
+	vec3_t		adjust;				// set by $origin
+	vec3_t		aseAdjust;
+	int			fixedwidth, fixedheight;	// set by $skinsize
+
+	int			maxSurfaceTris;
+
+	int			lowerSkipFrameStart, lowerSkipFrameEnd;
+	int			maxUpperFrames;
+	int			maxHeadFrames;
+	int			currentLod;
+	float		lodBias;
+
+	int			type;		// MD3_TYPE_BASE, MD3_TYPE_OLDBASE, MD3_TYPE_ASE, or MD3_TYPE_SPRITE
+
+} q3data;
+
+q3data g_data;
+
+// the command list holds counts, the count * 3 xyz, st, normal indexes
+// that are valid for every frame
+char		g_cddir[1024];
+char		g_modelname[1024];
+
+//==============================================================
+
+/*
+===============
+ClearModel
+===============
+*/
+void ClearModel (void)
+{
+	int i;
+
+	g_data.type = MD3_TYPE_UNKNOWN;
+
+	for ( i = 0; i < MD3_MAX_SURFACES; i++ )
+	{
+		memset( &g_data.surfData[i].header, 0, sizeof( g_data.surfData[i].header ) );
+		memset( &g_data.surfData[i].shaders, 0, sizeof( g_data.surfData[i].shaders ) );
+		memset( &g_data.surfData[i].verts, 0, sizeof( g_data.surfData[i].verts ) );
+	}
+
+	memset( g_data.tags, 0, sizeof( g_data.tags ) );
+
+	for ( i = 0; i < g_data.model.numSurfaces; i++ )
+	{
+		int j;
+
+		for ( j = 0; j < g_data.surfData[i].header.numShaders; j++ )
+		{
+			memset( &g_data.surfData[i].shaders[j], 0, sizeof( g_data.surfData[i].shaders[j] ) );
+		}
+	}
+	memset (&g_data.model, 0, sizeof(g_data.model));
+	memset (g_cddir, 0, sizeof(g_cddir));
+
+	g_modelname[0] = 0;
+	g_data.scale_up = 1.0;	
+	memset( &g_data.model, 0, sizeof( g_data.model ) );
+	VectorCopy (vec3_origin, g_data.adjust);
+	g_data.fixedwidth = g_data.fixedheight = 0;
+	g_skipmodel = qfalse;
+}
+
+/*
+** void WriteModelSurface( FILE *modelouthandle, md3SurfaceData_t *pSurfData )
+**
+** This routine assumes that the file position has been adjusted
+** properly prior to entry to point at the beginning of the surface.
+**
+** Since surface header information is completely relative, we can't
+** just randomly seek to an arbitrary surface location right now.  Is
+** this something we should add?
+*/
+void WriteModelSurface( FILE *modelouthandle, md3SurfaceData_t *pSurfData )
+{
+	md3Surface_t	*pSurf = &pSurfData->header;
+	md3Shader_t		*pShader = pSurfData->shaders;
+	baseVertex_t	*pBaseVertex = pSurfData->baseVertexes;
+	float			**verts = pSurfData->verts;
+
+	short xyznormals[MD3_MAX_VERTS][4];
+
+	float base_st[MD3_MAX_VERTS][2];
+	md3Surface_t surftemp;
+
+	int f, i, j, k;
+
+	if ( strstr( pSurf->name, "tag_" ) == pSurf->name )
+		return;
+
+	//
+	// write out the header
+	//
+	surftemp = *pSurf;
+	surftemp.ident = LittleLong( MD3_IDENT );
+	surftemp.flags = LittleLong( pSurf->flags );
+	surftemp.numFrames = LittleLong( pSurf->numFrames );
+	surftemp.numShaders = LittleLong( pSurf->numShaders );
+
+	surftemp.ofsShaders = LittleLong( pSurf->ofsShaders );
+
+	surftemp.ofsTriangles = LittleLong( pSurf->ofsTriangles );
+	surftemp.numTriangles = LittleLong( pSurf->numTriangles );
+
+	surftemp.ofsSt = LittleLong( pSurf->ofsSt );
+	surftemp.ofsXyzNormals = LittleLong( pSurf->ofsXyzNormals );
+	surftemp.ofsEnd = LittleLong( pSurf->ofsEnd );
+
+	SafeWrite( modelouthandle, &surftemp, sizeof( surftemp ) );
+
+	if ( g_verbose )
+	{
+		printf( "surface '%s'\n", pSurf->name );
+		printf( "...num shaders: %d\n", pSurf->numShaders );
+	}
+
+	//
+	// write out shaders
+	//
+	for ( i = 0; i < pSurf->numShaders; i++ )
+	{
+		md3Shader_t shadertemp;
+
+		if ( g_verbose )
+			printf( "......'%s'\n", pShader[i].name );
+
+		shadertemp = pShader[i];
+		shadertemp.shaderIndex = LittleLong( shadertemp.shaderIndex );
+		SafeWrite( modelouthandle, &shadertemp, sizeof( shadertemp ) );
+	}
+
+	//
+	// write out the triangles
+	//
+	for ( i = 0 ; i < pSurf->numTriangles ; i++ ) 
+	{
+		for (j = 0 ; j < 3 ; j++) 
+		{
+			int ivalue = LittleLong( pSurfData->orderedTriangles[i][j] );
+			pSurfData->orderedTriangles[i][j] = ivalue;
+		}
+	}
+
+	SafeWrite( modelouthandle, pSurfData->orderedTriangles, pSurf->numTriangles * sizeof( g_data.surfData[0].orderedTriangles[0] ) );
+
+	if ( g_verbose )
+	{
+		printf( "\n...num verts: %d\n", pSurf->numVerts );
+		printf( "...TEX COORDINATES\n" );
+	}
+
+	//
+	// write out the texture coordinates
+	//
+	for ( i = 0; i < pSurf->numVerts ; i++) {
+		base_st[i][0] = LittleFloat( pBaseVertex[i].st[0] );
+		base_st[i][1] = LittleFloat( pBaseVertex[i].st[1] );
+		if ( g_verbose )
+			printf( "......%d: %f,%f\n", i, base_st[i][0], base_st[i][1] );
+	}
+	SafeWrite( modelouthandle, base_st, pSurf->numVerts * sizeof(base_st[0]));
+
+	//
+	// write the xyz_normal
+	//
+	if ( g_verbose )
+		printf( "...XYZNORMALS\n" );
+	for ( f = 0; f < g_data.model.numFrames; f++ )
+	{
+		for (j=0 ; j< pSurf->numVerts; j++) 
+		{
+			short value;
+
+			for (k=0 ; k < 3 ; k++) 
+			{
+				value = ( short ) ( verts[f][j*6+k] / MD3_XYZ_SCALE );
+				xyznormals[j][k] = LittleShort( value );
+			}
+			NormalToLatLong( &verts[f][j*6+3], (byte *)&xyznormals[j][3] );
+		}
+		SafeWrite( modelouthandle, xyznormals, pSurf->numVerts * sizeof( short ) * 4 );
+	}
+}
+
+/*
+** void WriteModelFile( FILE *modelouthandle )
+**
+** CHUNK			SIZE
+** header			sizeof( md3Header_t )
+** frames			sizeof( md3Frame_t ) * numFrames
+** tags				sizeof( md3Tag_t ) * numFrames * numTags
+** surfaces			surfaceSum
+*/
+void WriteModelFile( FILE *modelouthandle )
+{
+	int				f;
+	int				i, j;
+	md3Header_t		modeltemp;
+	long			surfaceSum = 0;
+	int				numRealSurfaces = 0;
+	int				numFrames = g_data.model.numFrames;
+
+	// compute offsets for all surfaces, sum their total size
+	for ( i = 0; i < g_data.model.numSurfaces; i++ )
+	{
+		if ( strstr( g_data.surfData[i].header.name, "tag_" ) != g_data.surfData[i].header.name )
+		{
+			md3Surface_t *psurf = &g_data.surfData[i].header;
+
+			if ( psurf->numTriangles == 0 || psurf->numVerts == 0 )
+				continue;
+
+			//
+			// the triangle and vertex split threshold is controlled by a parameter
+			// to $base, a la $base blah.3ds 1900, where "1900" determines the number
+			// of triangles to split on
+			//
+			else if ( psurf->numVerts > MAX_SURFACE_VERTS )
+			{
+				Error( "too many vertices\n" );
+			}
+
+			psurf->numFrames = numFrames;
+
+			psurf->ofsShaders = sizeof( md3Surface_t );
+
+			if ( psurf->numTriangles > MAX_SURFACE_TRIS  ) 
+			{
+				Error( "too many faces\n" );
+			}
+
+			psurf->ofsTriangles = psurf->ofsShaders + psurf->numShaders * sizeof( md3Shader_t );
+
+			psurf->ofsSt = psurf->ofsTriangles + psurf->numTriangles * sizeof( md3Triangle_t );
+			psurf->ofsXyzNormals = psurf->ofsSt + psurf->numVerts * sizeof( md3St_t );
+			psurf->ofsEnd = psurf->ofsXyzNormals + psurf->numFrames * psurf->numVerts * ( sizeof( short ) * 4 );
+
+			surfaceSum += psurf->ofsEnd;
+
+			numRealSurfaces++;
+		}
+	}
+
+	g_data.model.ident = MD3_IDENT;
+	g_data.model.version = MD3_VERSION;
+
+	g_data.model.ofsFrames = sizeof(md3Header_t);
+	g_data.model.ofsTags = g_data.model.ofsFrames + numFrames*sizeof(md3Frame_t);
+	g_data.model.ofsSurfaces = g_data.model.ofsTags + numFrames*g_data.model.numTags*sizeof(md3Tag_t);
+	g_data.model.ofsEnd = g_data.model.ofsSurfaces + surfaceSum;
+
+	//
+	// write out the model header
+	//
+	modeltemp = g_data.model;
+	modeltemp.ident = LittleLong( modeltemp.ident );
+	modeltemp.version = LittleLong( modeltemp.version );
+	modeltemp.numFrames = LittleLong( modeltemp.numFrames );
+	modeltemp.numTags = LittleLong( modeltemp.numTags );
+	modeltemp.numSurfaces = LittleLong( numRealSurfaces );
+	modeltemp.ofsFrames = LittleLong( modeltemp.ofsFrames );
+	modeltemp.ofsTags = LittleLong( modeltemp.ofsTags );
+	modeltemp.ofsSurfaces = LittleLong( modeltemp.ofsSurfaces );
+	modeltemp.ofsEnd = LittleLong( modeltemp.ofsEnd );
+
+	SafeWrite (modelouthandle, &modeltemp, sizeof(modeltemp));
+
+	//
+	// write out the frames
+	//
+	for (i=0 ; i < numFrames ; i++) 
+	{
+		vec3_t tmpVec;
+		float maxRadius = 0;
+
+		//
+		// compute localOrigin and radius
+		//
+		g_data.frames[i].localOrigin[0] =
+		g_data.frames[i].localOrigin[1] =
+		g_data.frames[i].localOrigin[2] = 0;
+
+		for ( j = 0; j < 8; j++ )
+		{
+			tmpVec[0] = g_data.frames[i].bounds[(j&1)!=0][0];
+			tmpVec[1] = g_data.frames[i].bounds[(j&2)!=0][1];
+			tmpVec[2] = g_data.frames[i].bounds[(j&4)!=0][2];
+
+			if ( VectorLength( tmpVec ) > maxRadius )
+				maxRadius = VectorLength( tmpVec );
+		}
+
+		g_data.frames[i].radius = LittleFloat( maxRadius );
+
+		// swap
+		for (j=0 ; j<3 ; j++) {
+			g_data.frames[i].bounds[0][j] = LittleFloat( g_data.frames[i].bounds[0][j] );
+			g_data.frames[i].bounds[1][j] = LittleFloat( g_data.frames[i].bounds[1][j] );
+			g_data.frames[i].localOrigin[j] = LittleFloat( g_data.frames[i].localOrigin[j] );
+		}
+	}
+	fseek (modelouthandle, g_data.model.ofsFrames, SEEK_SET);
+	SafeWrite( modelouthandle, g_data.frames, numFrames * sizeof(g_data.frames[0]) );
+
+	//
+	// write out the tags
+	//
+	fseek( modelouthandle, g_data.model.ofsTags, SEEK_SET );
+	for (f=0 ; f<g_data.model.numFrames; f++) 
+	{
+		int t;
+
+		for ( t = 0; t < g_data.model.numTags; t++ )
+		{
+			g_data.tags[f][t].origin[0] = LittleFloat(g_data.tags[f][t].origin[0]);
+			g_data.tags[f][t].origin[1] = LittleFloat(g_data.tags[f][t].origin[1]);
+			g_data.tags[f][t].origin[2] = LittleFloat(g_data.tags[f][t].origin[2]);
+
+			for (j=0 ; j<3 ; j++) 
+			{
+				g_data.tags[f][t].axis[0][j] = LittleFloat(g_data.tags[f][t].axis[0][j]);
+				g_data.tags[f][t].axis[1][j] = LittleFloat(g_data.tags[f][t].axis[1][j]);
+				g_data.tags[f][t].axis[2][j] = LittleFloat(g_data.tags[f][t].axis[2][j]);
+			}
+		}
+		SafeWrite( modelouthandle, g_data.tags[f], g_data.model.numTags * sizeof(md3Tag_t) );
+	}
+
+	//
+	// write out the surfaces
+	//
+	fseek( modelouthandle, g_data.model.ofsSurfaces, SEEK_SET );
+	for ( i = 0; i < g_data.model.numSurfaces; i++ )
+	{
+		WriteModelSurface( modelouthandle, &g_data.surfData[i] );
+	}
+}
+
+
+/*
+===============
+FinishModel
+===============
+*/
+void FinishModel ( int type )
+{
+	FILE		*modelouthandle;
+	FILE		*defaultSkinHandle;
+	char		name[1024];
+	int			i;
+
+	if (!g_data.model.numFrames)
+		return;
+
+	//
+	// build generalized triangle strips
+	//
+	OrderSurfaces();
+
+	if ( type == TYPE_PLAYER )
+	{
+		sprintf( name, "%s%s", writedir, g_modelname );
+		*strrchr( name, '.' ) = 0;
+		strcat( name, "_default.skin" );
+
+		defaultSkinHandle = fopen( name, "wt" );
+		for ( i = 0; i < g_data.model.numSurfaces; i++ )
+		{
+			fprintf( defaultSkinHandle, "%s,%s\n", g_data.surfData[i].header.name, g_data.surfData[i].shaders[0].name );
+		}
+		fclose( defaultSkinHandle );
+	}
+
+	sprintf (name, "%s%s", writedir, g_modelname);
+
+	//
+	// copy the model and its shaders to release directory tree 
+	// if doing a release build
+	//
+	if ( g_release ) {
+		int			i, j;
+		md3SurfaceData_t *pSurf;
+
+		ReleaseFile( g_modelname );
+
+		for ( i = 0; i < g_data.model.numSurfaces; i++ ) {
+			pSurf = &g_data.surfData[i];
+			for ( j = 0; j < g_data.model.numSkins; j++ ) {
+				ReleaseShader( pSurf->shaders[j].name );
+			}
+		}		
+		return;
+	}
+	
+	//
+	// write the model output file
+	//
+	printf ("saving to %s\n", name);
+	CreatePath (name);
+	modelouthandle = SafeOpenWrite (name);
+
+	WriteModelFile (modelouthandle);
+	
+	printf ("%4d surfaces\n", g_data.model.numSurfaces);
+	printf ("%4d frames\n", g_data.model.numFrames);
+	printf ("%4d tags\n", g_data.model.numTags);
+	printf ("file size: %d\n", (int)ftell (modelouthandle) );
+	printf ("---------------------\n");
+	
+	fclose (modelouthandle);
+}
+
+/*
+** OrderSurfaces
+**
+** Reorders triangles in all the surfaces.
+*/
+static void OrderSurfaces( void )
+{
+	int s;
+	extern qboolean g_stripify;
+
+	// go through each surface and find best strip/fans possible
+	for ( s = 0; s < g_data.model.numSurfaces; s++ )
+	{
+		int mesh[MD3_MAX_TRIANGLES][3];
+		int i;
+
+		printf( "stripifying surface %d/%d with %d tris\n", s, g_data.model.numSurfaces, g_data.surfData[s].header.numTriangles );
+
+		for ( i = 0; i < g_data.surfData[s].header.numTriangles; i++ )
+		{
+			mesh[i][0] = g_data.surfData[s].lodTriangles[i][0];
+			mesh[i][1] = g_data.surfData[s].lodTriangles[i][1];
+			mesh[i][2] = g_data.surfData[s].lodTriangles[i][2];
+		}
+
+		if ( g_stripify )
+		{
+			OrderMesh( mesh,									// input
+					   g_data.surfData[s].orderedTriangles,		// output
+					   g_data.surfData[s].header.numTriangles );
+		}
+		else
+		{
+			memcpy( g_data.surfData[s].orderedTriangles, mesh, sizeof( int ) * 3 * g_data.surfData[s].header.numTriangles );
+		}
+	}
+}
+
+
+/*
+===============================================================
+
+BASE FRAME SETUP
+
+===============================================================
+*/
+/*
+============
+CopyTrianglesToBaseTriangles
+
+============
+*/
+static void CopyTrianglesToBaseTriangles(triangle_t *ptri, int numtri, baseTriangle_t *bTri )
+{
+	int			i;
+//	int			width, height, iwidth, iheight, swidth;
+//	float		s_scale, t_scale;
+//	float		scale;
+//	vec3_t		mins, maxs;
+	float		*pbasevert;
+
+/*
+	//
+	// find bounds of all the verts on the base frame
+	//
+	ClearBounds (mins, maxs);
+	
+	for (i=0 ; i<numtri ; i++)
+		for (j=0 ; j<3 ; j++)
+			AddPointToBounds (ptri[i].verts[j], mins, maxs);
+	
+	for (i=0 ; i<3 ; i++)
+	{
+		mins[i] = floor(mins[i]);
+		maxs[i] = ceil(maxs[i]);
+	}
+	
+	width = maxs[0] - mins[0];
+	height = maxs[2] - mins[2];
+
+	if (!g_data.fixedwidth)
+	{	// old style
+		scale = 8;
+		if (width*scale >= 150)
+			scale = 150.0 / width;	
+		if (height*scale >= 190)
+			scale = 190.0 / height;
+
+		s_scale = t_scale = scale;
+
+		iwidth = ceil(width*s_scale);
+		iheight = ceil(height*t_scale);
+
+		iwidth += 4;
+		iheight += 4;
+	}
+	else
+	{	// new style
+		iwidth = g_data.fixedwidth / 2;
+		iheight = g_data.fixedheight;
+
+		s_scale = (float)(iwidth-4) / width;
+		t_scale = (float)(iheight-4) / height;
+	}
+
+	// make the width a multiple of 4; some hardware requires this, and it ensures
+	// dword alignment for each scan
+	swidth = iwidth*2;
+	g_data.skinwidth = (swidth + 3) & ~3;
+	g_data.skinheight = iheight;
+*/
+
+	for (i=0; i<numtri ; i++, ptri++, bTri++)
+	{
+		int j;
+
+		for (j=0 ; j<3 ; j++) 
+		{
+			pbasevert = ptri->verts[j];
+
+			VectorCopy( ptri->verts[j], bTri->v[j].xyz);
+			VectorCopy( ptri->normals[j], bTri->v[j].normal );
+
+			bTri->v[j].st[0] = ptri->texcoords[j][0];
+			bTri->v[j].st[1] = ptri->texcoords[j][1];
+		}
+	}
+}
+
+static void BuildBaseFrame( const char *filename, ObjectAnimationFrame_t *pOAF )
+{
+	baseTriangle_t	*bTri;
+	baseVertex_t	*bVert;
+	int i, j;
+
+	// calculate the base triangles
+	for ( i = 0; i < g_data.model.numSurfaces; i++ )
+	{
+		CopyTrianglesToBaseTriangles( pOAF->surfaces[i]->triangles, 
+					                pOAF->surfaces[i]->numtriangles,
+									g_data.surfData[i].baseTriangles );
+
+		strcpy( g_data.surfData[i].header.name, pOAF->surfaces[i]->name );
+
+		g_data.surfData[i].header.numTriangles = pOAF->surfaces[i]->numtriangles;
+		g_data.surfData[i].header.numVerts = 0;
+
+/*
+		if ( strstr( filename, gamedir + 1 ) )
+		{
+			strcpy( shaderName, strstr( filename, gamedir + 1 ) + strlen( gamedir ) - 1 );
+		}
+		else
+		{
+			strcpy( shaderName, filename );
+		}
+
+		if ( strrchr( shaderName, '/' ) )
+			*( strrchr( shaderName, '/' ) + 1 ) = 0;
+
+
+		strcpy( shaderName, pOAF->surfaces[i]->materialname );
+*/
+		strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, pOAF->surfaces[i]->materialname );
+
+		g_data.surfData[i].header.numShaders++;
+	}
+
+	//
+	// compute unique vertices for each polyset
+	//
+	for ( i = 0; i < g_data.model.numSurfaces; i++ )
+	{
+		int t;
+
+		for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
+		{
+			bTri = &g_data.surfData[i].baseTriangles[t];
+
+			for (j=0 ; j<3 ; j++)
+			{
+				int k;
+
+				bVert = &bTri->v[j];
+
+				// get the xyz index
+				for ( k = 0; k < g_data.surfData[i].header.numVerts; k++ )
+				{
+					if ( ( g_data.surfData[i].baseVertexes[k].st[0] == bVert->st[0] ) &&
+						 ( g_data.surfData[i].baseVertexes[k].st[1] == bVert->st[1] ) &&
+						 ( VectorCompare (bVert->xyz, g_data.surfData[i].baseVertexes[k].xyz) ) &&
+						 ( VectorCompare (bVert->normal, g_data.surfData[i].baseVertexes[k].normal) ) )
+					{
+						break;	// this vertex is already in the base vertex list
+					}
+				}
+
+				if (k == g_data.surfData[i].header.numVerts)	{ // new index
+					g_data.surfData[i].baseVertexes[g_data.surfData[i].header.numVerts] = *bVert;
+					g_data.surfData[i].header.numVerts++;
+				}
+
+				bVert->index = k;
+
+				g_data.surfData[i].lodTriangles[t][j] = k;
+			}
+		}
+	}
+
+	//
+	// find tags
+	//
+	for ( i = 0; i < g_data.model.numSurfaces; i++ )
+	{
+		if ( strstr( pOAF->surfaces[i]->name, "tag_" ) == pOAF->surfaces[i]->name )
+		{
+			if ( pOAF->surfaces[i]->numtriangles != 1 )
+			{
+				Error( "tag polysets must consist of only one triangle" );
+			}
+			if ( strstr( filename, "_flash.md3" ) && !strcmp( pOAF->surfaces[i]->name, "tag_parent" ) )
+				continue;
+			printf( "found tag '%s'\n", pOAF->surfaces[i]->name );
+			g_data.model.numTags++;
+		}
+	}
+
+}
+
+static int LoadModelFile( const char *filename, polyset_t **psets, int *numpolysets )
+{
+	int			time1;
+	char		file1[1024];
+	const char			*frameFile;
+
+	printf ("---------------------\n");
+	if ( filename[1] != ':' )
+	{
+		frameFile = filename;
+		sprintf( file1, "%s/%s", g_cddir, frameFile );
+	}
+	else
+	{
+		strcpy( file1, filename );
+	}
+
+	time1 = FileTime (file1);
+	if (time1 == -1)
+		Error ("%s doesn't exist", file1);
+
+	//
+	// load the base triangles
+	//
+	*psets = Polyset_LoadSets( file1, numpolysets, g_data.maxSurfaceTris );
+
+	//
+	// snap polysets
+	//
+	Polyset_SnapSets( *psets, *numpolysets );
+
+	if ( strstr( file1, ".3ds" ) || strstr( file1, ".3DS" ) )
+		return MD3_TYPE_BASE3DS;
+
+	Error( "Unknown model file type" );
+
+	return MD3_TYPE_UNKNOWN;
+}
+
+/*
+=================
+Cmd_Base
+=================
+*/
+void Cmd_Base( void )
+{
+	char filename[1024];
+
+	GetToken( qfalse );
+	sprintf( filename, "%s/%s", g_cddir, token );
+	LoadBase( filename );
+}
+
+static void LoadBase( const char *filename )
+{
+	int numpolysets;
+	polyset_t *psets;
+	int			i;
+	ObjectAnimationFrame_t oaf;
+
+	// determine polyset splitting threshold
+	if ( TokenAvailable() )
+	{
+		GetToken( qfalse );
+		g_data.maxSurfaceTris = atoi( token );
+	}
+	else
+	{
+		g_data.maxSurfaceTris = MAX_SURFACE_TRIS - 1;
+	}
+
+	g_data.type = LoadModelFile( filename, &psets, &numpolysets );
+
+	Polyset_ComputeNormals( psets, numpolysets );
+
+	g_data.model.numSurfaces = numpolysets;
+
+	memset( &oaf, 0, sizeof( oaf ) );
+
+	for ( i = 0; i < numpolysets; i++ )
+	{
+		oaf.surfaces[i] = &psets[i];
+		oaf.numSurfaces = numpolysets;
+	}
+
+	BuildBaseFrame( filename, &oaf );
+
+	free( psets[0].triangles );
+	free( psets );
+}
+
+/*
+=================
+Cmd_SpriteBase
+
+$spritebase xorg yorg width height
+
+Generate a single square for the model
+=================
+*/
+void Cmd_SpriteBase (void)
+{
+	float		xl, yl, width, height;
+
+	g_data.type = MD3_TYPE_SPRITE;
+
+	GetToken (qfalse);
+	xl = atof(token);
+	GetToken (qfalse);
+	yl = atof(token);
+	GetToken (qfalse);
+	width = atof(token);
+	GetToken (qfalse);
+	height = atof(token);
+
+//	if (g_skipmodel || g_release || g_archive)
+//		return;
+
+	printf ("---------------------\n");
+
+	g_data.surfData[0].verts[0] = ( float * ) calloc( 1, sizeof( float ) * 6 * 4 );
+
+	g_data.surfData[0].header.numVerts = 4;
+
+	g_data.surfData[0].verts[0][0+0] = 0;
+	g_data.surfData[0].verts[0][0+1] = -xl;
+	g_data.surfData[0].verts[0][0+2] = yl + height;
+
+	g_data.surfData[0].verts[0][0+3] = -1;
+	g_data.surfData[0].verts[0][0+4] = 0;
+	g_data.surfData[0].verts[0][0+5] = 0;
+	g_data.surfData[0].baseVertexes[0].st[0] = 0;
+	g_data.surfData[0].baseVertexes[0].st[1] = 0;
+
+
+	g_data.surfData[0].verts[0][6+0] = 0;
+	g_data.surfData[0].verts[0][6+1] = -xl - width;
+	g_data.surfData[0].verts[0][6+2] = yl + height;
+	
+	g_data.surfData[0].verts[0][6+3] = -1;
+	g_data.surfData[0].verts[0][6+4] = 0;
+	g_data.surfData[0].verts[0][6+5] = 0;
+	g_data.surfData[0].baseVertexes[1].st[0] = 1;
+	g_data.surfData[0].baseVertexes[1].st[1] = 0;
+
+
+	g_data.surfData[0].verts[0][12+0] = 0;
+	g_data.surfData[0].verts[0][12+1] = -xl - width;
+	g_data.surfData[0].verts[0][12+2] = yl;
+
+	g_data.surfData[0].verts[0][12+3] = -1;
+	g_data.surfData[0].verts[0][12+4] = 0;
+	g_data.surfData[0].verts[0][12+5] = 0;
+	g_data.surfData[0].baseVertexes[2].st[0] = 1;
+	g_data.surfData[0].baseVertexes[2].st[1] = 1;
+
+
+	g_data.surfData[0].verts[0][18+0] = 0;
+	g_data.surfData[0].verts[0][18+1] = -xl;
+	g_data.surfData[0].verts[0][18+2] = yl;
+
+	g_data.surfData[0].verts[0][18+3] = -1;
+	g_data.surfData[0].verts[0][18+4] = 0;
+	g_data.surfData[0].verts[0][18+5] = 0;
+	g_data.surfData[0].baseVertexes[3].st[0] = 0;
+	g_data.surfData[0].baseVertexes[3].st[1] = 1;
+
+	g_data.surfData[0].lodTriangles[0][0] = 0;
+	g_data.surfData[0].lodTriangles[0][1] = 1;
+	g_data.surfData[0].lodTriangles[0][2] = 2;
+
+	g_data.surfData[0].lodTriangles[1][0] = 2;
+	g_data.surfData[0].lodTriangles[1][1] = 3;
+	g_data.surfData[0].lodTriangles[1][2] = 0;
+
+	g_data.model.numSurfaces = 1;
+
+	g_data.surfData[0].header.numTriangles = 2;
+	g_data.surfData[0].header.numVerts = 4;
+
+	g_data.model.numFrames = 1;
+}
+
+/*
+===========================================================================
+
+  FRAME GRABBING
+
+===========================================================================
+*/
+
+/*
+===============
+GrabFrame
+===============
+*/
+void GrabFrame (const char *frame)
+{
+	int			i, j, k;
+	char		file1[1024];
+	md3Frame_t		*fr;
+	md3Tag_t		tagParent;
+	float		*frameXyz;
+	float		*frameNormals;
+	const char	*framefile;
+	polyset_t		*psets;
+	qboolean	 parentTagExists = qfalse;
+	int			 numpolysets;
+	int			numtags = 0;
+	int			tagcount;
+
+	// the frame 'run1' will be looked for as either
+	// run.1 or run1.tri, so the new alias sequence save
+	// feature an be used
+	if ( frame[1] != ':' )
+	{
+//		framefile = FindFrameFile (frame);
+		framefile = frame;
+		sprintf (file1, "%s/%s",g_cddir, framefile);
+	}
+	else
+	{
+		strcpy( file1, frame );
+	}
+	printf ("grabbing %s\n", file1);
+
+	if (g_data.model.numFrames >= MD3_MAX_FRAMES)
+		Error ("model.numFrames >= MD3_MAX_FRAMES");
+	fr = &g_data.frames[g_data.model.numFrames];
+
+	strcpy (fr->name, frame);
+
+	psets = Polyset_LoadSets( file1, &numpolysets, g_data.maxSurfaceTris );
+
+	//
+	// snap polysets
+	//
+	Polyset_SnapSets( psets, numpolysets );
+
+	//
+	// compute vertex normals
+	//
+	Polyset_ComputeNormals( psets, numpolysets );
+
+	//
+	// flip everything to compensate for the alias coordinate system
+	// and perform global scale and adjust
+	//
+	for ( i = 0; i < g_data.model.numSurfaces; i++ )
+	{
+		triangle_t *ptri = psets[i].triangles;
+		int t;
+
+		for ( t = 0; t < psets[i].numtriangles; t++ )
+		{
+
+			for ( j = 0; j < 3; j++ )
+			{
+
+				// scale and adjust
+				for ( k = 0 ; k < 3 ; k++ ) {
+					ptri[t].verts[j][k] = ptri[t].verts[j][k] * g_data.scale_up +
+						g_data.adjust[k];
+
+					if ( ptri[t].verts[j][k] > 1023 ||
+						 ptri[t].verts[j][k] < -1023 )
+					{
+						Error( "Model extents too large" );
+					}
+				}
+			}
+		}
+	}
+
+	//
+	// find and count tags, locate parent tag
+	//
+	for ( i = 0; i < numpolysets; i++ )
+	{
+		if ( strstr( psets[i].name, "tag_" ) == psets[i].name )
+		{
+			if ( strstr( psets[i].name, "tag_parent" ) == psets[i].name )
+			{
+				if ( strstr( psets[i].name, "tag_parent" ) )
+				{
+					float tri[3][3];
+
+					if ( parentTagExists )
+						Error( "Multiple parent tags not allowed" );
+
+					memcpy( tri[0], psets[i].triangles[0].verts[0], sizeof( float ) * 3 );
+					memcpy( tri[1], psets[i].triangles[0].verts[1], sizeof( float ) * 3 );
+					memcpy( tri[2], psets[i].triangles[0].verts[2], sizeof( float ) * 3 );
+
+					MD3_ComputeTagFromTri( &tagParent, tri );
+					strcpy( tagParent.name, psets[i].name );
+					g_data.tags[g_data.model.numFrames][numtags] = tagParent;
+					parentTagExists = qtrue;
+
+				}
+			}
+			numtags++;
+		}
+
+		if ( strcmp( psets[i].name, g_data.surfData[i].header.name ) )
+		{
+			Error( "Mismatched surfaces from base('%s') to frame('%s') in model '%s'\n", g_data.surfData[i].header.name, psets[i].name, g_modelname );
+		}
+	}
+
+	if ( numtags != g_data.model.numTags )
+	{
+		Error( "mismatched number of tags in frame(%d) vs. base(%d)", numtags, g_data.model.numTags );
+	}
+
+	if ( numpolysets != g_data.model.numSurfaces )
+	{
+		Error( "mismatched number of surfaces in frame(%d) vs. base(%d)", numpolysets-numtags, g_data.model.numSurfaces );
+	}
+	
+	//
+	// prepare to accumulate bounds and normals
+	//
+	ClearBounds( fr->bounds[0], fr->bounds[1] );
+
+	//
+	// store the frame's vertices in the same order as the base. This assumes the
+	// triangles and vertices in this frame are in exactly the same order as in the
+	// base
+	//
+	for ( i = 0, tagcount = 0; i < numpolysets; i++ )
+	{
+		int t;
+		triangle_t *pTris = psets[i].triangles;
+
+		strcpy( g_data.surfData[i].header.name, psets[i].name );
+
+		//
+		// parent tag adjust
+		//
+		if ( parentTagExists ) {
+			for ( t = 0; t < psets[i].numtriangles; t++ )
+			{
+				for ( j = 0; j < 3 ; j++ )
+				{
+					vec3_t tmp;
+					
+					VectorSubtract( pTris[t].verts[j], tagParent.origin, tmp );
+
+					pTris[t].verts[j][0] = DotProduct( tmp, tagParent.axis[0] );
+					pTris[t].verts[j][1] = DotProduct( tmp, tagParent.axis[1] );
+					pTris[t].verts[j][2] = DotProduct( tmp, tagParent.axis[2] );
+
+					VectorCopy( pTris[t].normals[j], tmp );
+					pTris[t].normals[j][0] = DotProduct( tmp, tagParent.axis[0] );
+					pTris[t].normals[j][1] = DotProduct( tmp, tagParent.axis[1] );
+					pTris[t].normals[j][2] = DotProduct( tmp, tagParent.axis[2] );
+				}
+			}
+		}
+
+		//
+		// compute tag data
+		//
+		if ( strstr( psets[i].name, "tag_" ) == psets[i].name )
+		{
+			md3Tag_t *pTag = &g_data.tags[g_data.model.numFrames][tagcount];
+			float tri[3][3];
+
+			strcpy( pTag->name, psets[i].name );
+
+			memcpy( tri[0], pTris[0].verts[0], sizeof( float ) * 3 );
+			memcpy( tri[1], pTris[0].verts[1], sizeof( float ) * 3 );
+			memcpy( tri[2], pTris[0].verts[2], sizeof( float ) * 3 );
+
+			MD3_ComputeTagFromTri( pTag, tri );
+			tagcount++;
+		}
+		else
+		{
+			if ( g_data.surfData[i].verts[g_data.model.numFrames] )
+				free( g_data.surfData[i].verts[g_data.model.numFrames] );
+			frameXyz = g_data.surfData[i].verts[g_data.model.numFrames] = calloc( 1, sizeof( float ) * 6 * g_data.surfData[i].header.numVerts );
+			frameNormals = frameXyz + 3;
+
+			for ( t = 0; t < psets[i].numtriangles; t++ )
+			{
+				for ( j = 0; j < 3 ; j++ )
+				{
+					int index;
+
+					index = g_data.surfData[i].baseTriangles[t].v[j].index;
+					frameXyz[index*6+0] = pTris[t].verts[j][0];
+					frameXyz[index*6+1] = pTris[t].verts[j][1];
+					frameXyz[index*6+2] = pTris[t].verts[j][2];
+					frameNormals[index*6+0] =  pTris[t].normals[j][0];
+					frameNormals[index*6+1] =  pTris[t].normals[j][1];
+					frameNormals[index*6+2] =  pTris[t].normals[j][2];
+					AddPointToBounds (&frameXyz[index*6], fr->bounds[0], fr->bounds[1] );
+				}
+			}
+		}
+	}
+
+	g_data.model.numFrames++;
+
+	// only free the first triangle array, all of the psets in this array share the
+	// same triangle pool!!!
+//	free( psets[0].triangles );
+//	free( psets );
+}
+
+//===========================================================================
+
+
+
+/*
+===============
+Cmd_Frame	
+===============
+*/
+void Cmd_Frame (void)
+{
+	while (TokenAvailable())
+	{
+		GetToken (qfalse);
+		if (g_skipmodel)
+			continue;
+		if (g_release || g_archive)
+		{
+			g_data.model.numFrames = 1;	// don't skip the writeout
+			continue;
+		}
+
+		GrabFrame( token );
+	}
+}
+
+
+/*
+===============
+Cmd_Skin
+
+===============
+*/
+void SkinFrom3DS( const char *filename )
+{
+	polyset_t *psets;
+	char name[1024];
+	int numPolysets;
+	int i;
+
+	_3DS_LoadPolysets( filename, &psets, &numPolysets, g_verbose );
+
+	for ( i = 0; i < numPolysets; i++ )
+	{
+/*
+		if ( strstr( filename, gamedir + 1 ) )
+		{
+			strcpy( name, strstr( filename, gamedir + 1 ) + strlen( gamedir ) - 1 );
+		}
+		else
+		{
+			strcpy( name, filename );
+		}
+
+		if ( strrchr( name, '/' ) )
+			*( strrchr( name, '/' ) + 1 ) = 0;
+*/
+		strcpy( name, psets[i].materialname );
+		strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, name );
+
+		g_data.surfData[i].header.numShaders++;
+	}
+
+	free( psets[0].triangles );
+	free( psets );
+}
+
+void Cmd_Skin (void)
+{
+	char skinfile[1024];
+
+	if ( g_data.type == MD3_TYPE_BASE3DS )
+	{
+		GetToken( qfalse );
+
+		sprintf( skinfile, "%s/%s", g_cddir, token );
+
+		if ( strstr( token, ".3ds" ) || strstr( token, ".3DS" ) )
+		{
+			SkinFrom3DS( skinfile );
+		}
+		else
+		{
+			Error( "Unknown file format for $skin '%s'\n", skinfile );
+		}
+	}
+	else
+	{
+		Error( "invalid model type while processing $skin" );
+	}
+
+	g_data.model.numSkins++;
+}
+
+/*
+=================
+Cmd_SpriteShader
+=================
+
+This routine is also called for $oldskin
+
+*/
+void Cmd_SpriteShader()
+{
+	GetToken( qfalse );
+	strcpy( g_data.surfData[0].shaders[g_data.surfData[0].header.numShaders].name, token );
+	g_data.surfData[0].header.numShaders++;
+	g_data.model.numSkins++;
+}
+
+/*
+=================
+Cmd_Origin
+=================
+*/
+void Cmd_Origin (void)
+{
+	// rotate points into frame of reference so model points down the
+	// positive x axis
+	// FIXME: use alias native coordinate system
+	GetToken (qfalse);
+	g_data.adjust[1] = -atof (token);
+
+	GetToken (qfalse);
+	g_data.adjust[0] = atof (token);
+
+	GetToken (qfalse);
+	g_data.adjust[2] = -atof (token);
+}
+
+
+/*
+=================
+Cmd_ScaleUp
+=================
+*/
+void Cmd_ScaleUp (void)
+{
+	GetToken (qfalse);
+	g_data.scale_up = atof (token);
+	if (g_skipmodel || g_release || g_archive)
+		return;
+
+	printf ("Scale up: %f\n", g_data.scale_up);
+}
+
+
+/*
+=================
+Cmd_Skinsize
+
+Set a skin size other than the default
+QUAKE3: not needed
+=================
+*/
+void Cmd_Skinsize (void)
+{
+	GetToken (qfalse);
+	g_data.fixedwidth = atoi(token);
+	GetToken (qfalse);
+	g_data.fixedheight = atoi(token);
+}
+
+/*
+=================
+Cmd_Modelname
+
+Begin creating a model of the given name
+=================
+*/
+void Cmd_Modelname (void)
+{
+	FinishModel ( TYPE_UNKNOWN );
+	ClearModel ();
+
+	GetToken (qfalse);
+	strcpy (g_modelname, token);
+	StripExtension (g_modelname);
+	strcat (g_modelname, ".md3");
+	strcpy (g_data.model.name, g_modelname);
+}
+
+/*
+===============
+fCmd_Cd
+===============
+*/
+void Cmd_Cd (void)
+{
+	if ( g_cddir[0]) {
+		Error ("$cd command without a $modelname");
+	}
+
+	GetToken (qfalse);
+
+	sprintf ( g_cddir, "%s%s", gamedir, token);
+
+	// if -only was specified and this cd doesn't match,
+	// skip the model (you only need to match leading chars,
+	// so you could regrab all monsters with -only models/monsters)
+	if (!g_only[0])
+		return;
+	if (strncmp(token, g_only, strlen(g_only)))
+	{
+		g_skipmodel = qtrue;
+		printf ("skipping %s\n", token);
+	}
+}
+
+void Convert3DStoMD3( const char *file )
+{
+	LoadBase( file );
+	GrabFrame( file );
+	SkinFrom3DS( file );
+
+	strcpy( g_data.model.name, g_modelname );
+
+	FinishModel( TYPE_UNKNOWN );
+	ClearModel();
+}
+
+/*
+** Cmd_3DSConvert
+*/
+void Cmd_3DSConvert()
+{
+	char file[1024];
+
+	FinishModel( TYPE_UNKNOWN );
+	ClearModel();
+
+	GetToken( qfalse );
+
+	sprintf( file, "%s%s", gamedir, token );
+	strcpy( g_modelname, token );
+	if ( strrchr( g_modelname, '.' ) )
+		*strrchr( g_modelname, '.' ) = 0;
+	strcat( g_modelname, ".md3" );
+
+	if ( FileTime( file ) == -1 )
+		Error( "%s doesn't exist", file );
+
+	if ( TokenAvailable() )
+	{
+		GetToken( qfalse );
+		g_data.scale_up = atof( token );
+	}
+
+	Convert3DStoMD3( file );
+}
+
+static void ConvertASE( const char *filename, int type, qboolean grabAnims );
+
+/*
+** Cmd_ASEConvert
+*/
+void Cmd_ASEConvert( qboolean grabAnims )
+{
+	char filename[1024];
+	int type = TYPE_ITEM;
+
+	FinishModel( TYPE_UNKNOWN );
+	ClearModel();
+
+	GetToken( qfalse );
+	sprintf( filename, "%s%s", gamedir, token );
+
+	strcpy (g_modelname, token);
+	StripExtension (g_modelname);
+	strcat (g_modelname, ".md3");
+	strcpy (g_data.model.name, g_modelname);
+
+	if ( !strstr( filename, ".ase" ) && !strstr( filename, ".ASE" ) )
+		strcat( filename, ".ASE" );
+
+	g_data.maxSurfaceTris = MAX_SURFACE_TRIS - 1;
+
+	while ( TokenAvailable() )
+	{
+		GetToken( qfalse );
+		if ( !strcmp( token, "-origin" ) )
+		{
+			if ( !TokenAvailable() )
+				Error( "missing parameter for -origin" );
+			GetToken( qfalse );
+			g_data.aseAdjust[1] = -atof( token );
+
+			if ( !TokenAvailable() )
+				Error( "missing parameter for -origin" );
+			GetToken( qfalse );
+			g_data.aseAdjust[0] = atof (token);
+
+			if ( !TokenAvailable() )
+				Error( "missing parameter for -origin" );
+			GetToken( qfalse );
+			g_data.aseAdjust[2] = -atof (token);
+		}
+		else if ( !strcmp( token, "-lod" ) )
+		{
+			if ( !TokenAvailable() )
+				Error( "No parameter for -lod" );
+			GetToken( qfalse );
+			g_data.currentLod = atoi( token );
+			if ( g_data.currentLod > MD3_MAX_LODS - 1 )
+			{
+				Error( "-lod parameter too large! (%d)\n", g_data.currentLod );
+			}
+
+			if ( !TokenAvailable() )
+				Error( "No second parameter for -lod" );
+			GetToken( qfalse );
+			g_data.lodBias = atof( token );
+		}
+		else if ( !strcmp( token, "-maxtris" ) )
+		{
+			if ( !TokenAvailable() )
+				Error( "No parameter for -maxtris" );
+			GetToken( qfalse );
+			g_data.maxSurfaceTris = atoi( token );
+		}
+		else if ( !strcmp( token, "-playerparms" ) )
+		{
+			if ( !TokenAvailable() )
+				Error( "missing skip start parameter for -playerparms" );
+			GetToken( qfalse );
+			g_data.lowerSkipFrameStart = atoi( token );
+
+#if 0
+			if ( !TokenAvailable() )
+				Error( "missing skip end parameter for -playerparms" );
+			GetToken( qfalse );
+			g_data.lowerSkipFrameEnd = atoi( token );
+#endif
+
+			if ( !TokenAvailable() )
+				Error( "missing upper parameter for -playerparms" );
+			GetToken( qfalse );
+			g_data.maxUpperFrames = atoi( token );
+
+			g_data.lowerSkipFrameEnd = g_data.maxUpperFrames - 1;
+
+#if 0
+			if ( !TokenAvailable() )
+				Error( "missing head parameter for -playerparms" );
+			GetToken( qfalse );
+			g_data.maxHeadFrames = atoi( token );
+#endif
+			g_data.maxHeadFrames = 1;
+
+			if ( type != TYPE_ITEM )
+				Error( "invalid argument" );
+
+			type = TYPE_PLAYER;
+		}
+		else if ( !strcmp( token, "-weapon" ) )
+		{
+			if ( type != TYPE_ITEM )
+				Error( "invalid argument" );
+
+			type = TYPE_WEAPON;
+		}
+	}
+
+	g_data.type = MD3_TYPE_ASE;
+
+	if ( type == TYPE_WEAPON && grabAnims )
+	{
+		Error( "can't grab anims with weapon models" );
+	}
+	if ( type == TYPE_PLAYER && !grabAnims )
+	{
+		Error( "player models must be converted with $aseanimconvert" );
+	}
+
+	if ( type == TYPE_WEAPON )
+	{
+		ConvertASE( filename, type, qfalse );
+		ConvertASE( filename, TYPE_HAND, qtrue );
+	}
+	else
+	{
+		ConvertASE( filename, type, grabAnims );
+	}
+}
+
+static int GetSurfaceAnimations( SurfaceAnimation_t sanims[MAX_ANIM_SURFACES], 
+								  const char *part,
+								  int skipFrameStart,
+								  int skipFrameEnd,
+								  int maxFrames )
+
+{
+	int numSurfaces;
+	int numValidSurfaces;
+	int i;
+	int numFrames = -1;
+
+	if ( ( numSurfaces = ASE_GetNumSurfaces() ) > MAX_ANIM_SURFACES )
+	{
+		Error( "Too many surfaces in ASE" );
+	}
+
+	for ( numValidSurfaces = 0, i = 0; i < numSurfaces; i++ )
+	{
+		polyset_t *splitSets;
+		int numNewFrames;
+		const char *surfaceName = ASE_GetSurfaceName( i );
+
+		if ( !surfaceName )
+		{
+			continue;
+//			Error( "Missing animation frames in model" );
+		}
+
+		if ( strstr( surfaceName, "tag_" ) || 
+			 !strcmp( part, "any" ) || 
+			 ( strstr( surfaceName, part ) == surfaceName ) )
+		{
+
+			// skip this if it's an inappropriate tag
+			if ( strcmp( part, "any" ) )
+			{
+				// ignore non-"tag_head" tags if this is the head
+				if ( !strcmp( part, "h_" ) && strstr( surfaceName, "tag_" ) && strcmp( surfaceName, "tag_head" ) )
+					continue;
+				// ignore "tag_head" if this is the legs
+				if ( !strcmp( part, "l_" ) && !strcmp( surfaceName, "tag_head" ) )
+					continue;
+				// ignore "tag_weapon" if this is the legs
+				if ( !strcmp( part, "l_" ) && !strcmp( surfaceName, "tag_weapon" ) )
+					continue;
+			}
+
+			if ( ( sanims[numValidSurfaces].frames = ASE_GetSurfaceAnimation( i, &sanims[numValidSurfaces].numFrames, skipFrameStart, skipFrameEnd, maxFrames ) ) != 0 )
+			{
+				splitSets = Polyset_SplitSets( sanims[numValidSurfaces].frames, sanims[numValidSurfaces].numFrames, &numNewFrames, g_data.maxSurfaceTris );
+				
+				if ( numFrames == -1 )
+					numFrames = sanims[numValidSurfaces].numFrames;
+				else if ( numFrames != sanims[numValidSurfaces].numFrames )
+					Error( "Different number of animation frames on surfaces" );
+				
+				if ( sanims[numValidSurfaces].frames != splitSets )
+				{
+					int j;
+
+					// free old data if we split the surfaces
+					for ( j = 0; j < sanims[numValidSurfaces].numFrames; j++ )
+					{
+						free( sanims[numValidSurfaces].frames[j].triangles );
+						free( sanims[numValidSurfaces].frames );
+					}
+					
+					sanims[numValidSurfaces].frames = splitSets;
+					sanims[numValidSurfaces].numFrames = numNewFrames;
+				}
+				Polyset_SnapSets( sanims[numValidSurfaces].frames, sanims[numValidSurfaces].numFrames );
+				Polyset_ComputeNormals( sanims[numValidSurfaces].frames, sanims[numValidSurfaces].numFrames );
+
+				numValidSurfaces++;
+			}
+		}
+	}
+
+	return numValidSurfaces;
+}
+
+static int SurfaceOrderToFrameOrder( SurfaceAnimation_t sanims[], ObjectAnimationFrame_t oanims[], int numSurfaces )
+{
+	int i, s;
+	int numFrames = -1;
+
+	/*
+	** we have the data here arranged in surface order, now we need to convert it to 
+	** frame order
+	*/
+	for ( i = 0, s = 0; i < numSurfaces; i++ )
+	{
+		int j;
+		
+		if ( sanims[i].frames )
+		{
+			if ( numFrames == -1 )
+				numFrames = sanims[i].numFrames;
+			else if ( numFrames != sanims[i].numFrames )
+				Error( "numFrames != sanims[i].numFrames (%d != %d)\n", numFrames, sanims[i].numFrames );
+
+			for ( j = 0; j < sanims[i].numFrames; j++ )
+			{
+				oanims[j].surfaces[s] = &sanims[i].frames[j];
+				oanims[j].numSurfaces = numSurfaces;
+			}
+			s++;
+		}
+	}
+
+	return numFrames;
+}
+
+static void WriteMD3( const char *_filename, ObjectAnimationFrame_t oanims[], int numFrames )
+{
+	char filename[1024];
+
+	strcpy( filename, _filename );
+	if ( strchr( filename, '.' ) )
+		*strchr( filename, '.' ) = 0;
+	strcat( filename, ".md3" );
+}
+
+static void BuildAnimationFromOAFs( const char *filename, ObjectAnimationFrame_t oanims[], int numFrames, int type )
+{
+	int f, i, j, tagcount;
+	float *frameXyz;
+	float *frameNormals;
+
+	g_data.model.numSurfaces = oanims[0].numSurfaces;
+	g_data.model.numFrames = numFrames;
+	if ( g_data.model.numFrames < 0)
+		Error ("model.numFrames < 0");
+	if ( g_data.model.numFrames >= MD3_MAX_FRAMES)
+		Error ("model.numFrames >= MD3_MAX_FRAMES");
+
+	// build base frame
+	BuildBaseFrame( filename, &oanims[0] );
+	
+	// build animation frames
+	for ( f = 0; f < numFrames; f++ )
+	{
+		ObjectAnimationFrame_t *pOAF = &oanims[f];
+		qboolean	parentTagExists = qfalse;
+		md3Tag_t	tagParent;
+		int			numtags = 0;
+		md3Frame_t		*fr;
+		
+		fr = &g_data.frames[f];
+		
+		strcpy( fr->name, "(from ASE)" );
+		
+		// scale and adjust frame
+		for ( i = 0; i < pOAF->numSurfaces; i++ )
+		{
+			triangle_t *pTris = pOAF->surfaces[i]->triangles;
+			int t;
+			
+			for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
+			{
+				for ( j = 0; j < 3; j++ )
+				{
+					int k;
+					
+					// scale and adjust
+					for ( k = 0 ; k < 3 ; k++ ) {
+						pTris[t].verts[j][k] = pTris[t].verts[j][k] * g_data.scale_up +
+							g_data.aseAdjust[k];
+						
+						if ( pTris[t].verts[j][k] > 1023 ||
+							pTris[t].verts[j][k] < -1023 )
+						{
+							Error( "Model extents too large" );
+						}
+					}
+				}
+			}
+		}
+		
+		//
+		// find and count tags, locate parent tag
+		//
+		for ( i = 0; i < pOAF->numSurfaces; i++ )
+		{
+			if ( strstr( pOAF->surfaces[i]->name, "tag_" ) == pOAF->surfaces[i]->name )
+			{
+				// ignore parent tags when grabbing a weapon model and this is the flash portion
+				if ( !strcmp( pOAF->surfaces[i]->name, "tag_parent" ) && strstr( filename, "_flash.md3" ) )
+				{
+					continue;
+				}
+				else if ( !strstr( filename, "_hand.md3" ) && (
+					 ( !strcmp( pOAF->surfaces[i]->name, "tag_parent" ) && !strstr( filename, "_flash.md3" ) ) ||
+					 ( !strcmp( pOAF->surfaces[i]->name, "tag_torso" ) && ( strstr( filename, "upper_" ) || strstr( filename, "upper.md3" ) ) ) ||
+					 ( !strcmp( pOAF->surfaces[i]->name, "tag_head" ) && ( strstr( filename, "head.md3" ) || strstr( filename, "head_" ) ) ) ||
+					 ( !strcmp( pOAF->surfaces[i]->name, "tag_flash" ) && strstr( filename, "_flash.md3" ) )|| 
+					 ( !strcmp( pOAF->surfaces[i]->name, "tag_weapon" ) && type == TYPE_WEAPON ) ) )
+				{
+					float tri[3][3];
+					
+					if ( parentTagExists )
+						Error( "Multiple parent tags not allowed" );
+					
+					memcpy( tri[0], pOAF->surfaces[i]->triangles[0].verts[0], sizeof( float ) * 3 );
+					memcpy( tri[1], pOAF->surfaces[i]->triangles[0].verts[1], sizeof( float ) * 3 );
+					memcpy( tri[2], pOAF->surfaces[i]->triangles[0].verts[2], sizeof( float ) * 3 );
+					
+					MD3_ComputeTagFromTri( &tagParent, tri );
+					strcpy( tagParent.name, "tag_parent" );
+					g_data.tags[f][numtags] = tagParent;
+					parentTagExists = qtrue;
+				}
+				else
+				{
+					float tri[3][3];
+				
+					memcpy( tri[0], pOAF->surfaces[i]->triangles[0].verts[0], sizeof( float ) * 3 );
+					memcpy( tri[1], pOAF->surfaces[i]->triangles[0].verts[1], sizeof( float ) * 3 );
+					memcpy( tri[2], pOAF->surfaces[i]->triangles[0].verts[2], sizeof( float ) * 3 );
+					
+					MD3_ComputeTagFromTri( &g_data.tags[f][numtags], tri );
+					strcpy( g_data.tags[f][numtags].name, pOAF->surfaces[i]->name );
+					if ( strstr( g_data.tags[f][numtags].name, "tag_flash" ) )
+						* ( strstr( g_data.tags[f][numtags].name, "tag_flash" ) + strlen( "tag_flash" ) ) = 0;
+				}
+
+				numtags++;
+			}
+			
+			if ( strcmp( pOAF->surfaces[i]->name, g_data.surfData[i].header.name ) )
+			{
+				Error( "Mismatched surfaces from base('%s') to frame('%s') in model '%s'\n", g_data.surfData[i].header.name, pOAF->surfaces[i]->name, filename );
+			}
+		}
+		
+		if ( numtags != g_data.model.numTags )
+		{
+			Error( "mismatched number of tags in frame(%d) vs. base(%d)", numtags, g_data.model.numTags );
+		}
+		
+		//
+		// prepare to accumulate bounds and normals
+		//
+		ClearBounds( fr->bounds[0], fr->bounds[1] );
+		
+		//
+		// store the frame's vertices in the same order as the base. This assumes the
+		// triangles and vertices in this frame are in exactly the same order as in the
+		// base
+		//
+		for ( i = 0, tagcount = 0; i < pOAF->numSurfaces; i++ )
+		{
+			int t;
+			triangle_t *pTris = pOAF->surfaces[i]->triangles;
+			
+			//
+			// parent tag adjust
+			//
+			if ( parentTagExists ) 
+			{
+				for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
+				{
+					for ( j = 0; j < 3 ; j++ )
+					{
+						vec3_t tmp;
+						
+						VectorSubtract( pTris[t].verts[j], tagParent.origin, tmp );
+						
+						pTris[t].verts[j][0] = DotProduct( tmp, tagParent.axis[0] );
+						pTris[t].verts[j][1] = DotProduct( tmp, tagParent.axis[1] );
+						pTris[t].verts[j][2] = DotProduct( tmp, tagParent.axis[2] );
+						
+						VectorCopy( pTris[t].normals[j], tmp );
+						pTris[t].normals[j][0] = DotProduct( tmp, tagParent.axis[0] );
+						pTris[t].normals[j][1] = DotProduct( tmp, tagParent.axis[1] );
+						pTris[t].normals[j][2] = DotProduct( tmp, tagParent.axis[2] );
+					}
+				}
+			}
+			
+			//
+			// compute tag data
+			//
+			if ( strstr( pOAF->surfaces[i]->name, "tag_" ) == pOAF->surfaces[i]->name )
+			{
+				md3Tag_t *pTag = &g_data.tags[f][tagcount];
+				float tri[3][3];
+				
+				strcpy( pTag->name, pOAF->surfaces[i]->name );
+				
+				memcpy( tri[0], pTris[0].verts[0], sizeof( float ) * 3 );
+				memcpy( tri[1], pTris[0].verts[1], sizeof( float ) * 3 );
+				memcpy( tri[2], pTris[0].verts[2], sizeof( float ) * 3 );
+				
+				MD3_ComputeTagFromTri( pTag, tri );
+				tagcount++;
+			}
+			else
+			{
+				if ( g_data.surfData[i].verts[f] )
+					free( g_data.surfData[i].verts[f] );
+				frameXyz = g_data.surfData[i].verts[f] = calloc( 1, sizeof( float ) * 6 * g_data.surfData[i].header.numVerts );
+				frameNormals = frameXyz + 3;
+				
+				for ( t = 0; t < pOAF->surfaces[i]->numtriangles; t++ )
+				{
+					for ( j = 0; j < 3 ; j++ )
+					{
+						int index;
+						
+						index = g_data.surfData[i].baseTriangles[t].v[j].index;
+						frameXyz[index*6+0] = pTris[t].verts[j][0];
+						frameXyz[index*6+1] = pTris[t].verts[j][1];
+						frameXyz[index*6+2] = pTris[t].verts[j][2];
+						frameNormals[index*6+0] =  pTris[t].normals[j][0];
+						frameNormals[index*6+1] =  pTris[t].normals[j][1];
+						frameNormals[index*6+2] =  pTris[t].normals[j][2];
+						AddPointToBounds (&frameXyz[index*6], fr->bounds[0], fr->bounds[1] );
+					}
+				}
+			}
+		}
+	}
+
+	if ( strstr( filename, gamedir + 1 ) )
+	{
+		strcpy( g_modelname, strstr( filename, gamedir + 1 ) + strlen( gamedir ) - 1 );
+	}
+	else
+	{
+		strcpy( g_modelname, filename );
+	}
+
+	FinishModel( type );
+	ClearModel();
+}
+
+static void ConvertASE( const char *filename, int type, qboolean grabAnims )
+{
+	int i, j;
+	int numSurfaces;
+	int numFrames = -1;
+	SurfaceAnimation_t surfaceAnimations[MAX_ANIM_SURFACES];
+	ObjectAnimationFrame_t objectAnimationFrames[MAX_ANIM_FRAMES];
+	char outfilename[1024];
+
+	/*
+	** load ASE into memory
+	*/
+	ASE_Load( filename, g_verbose, grabAnims );
+
+	/*
+	** process parts
+	*/
+	if ( type == TYPE_ITEM )
+	{
+		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "any", -1, -1, -1 );
+
+		if ( numSurfaces <= 0 )
+			Error( "numSurfaces <= 0" );
+
+		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
+
+		if ( numFrames <= 0 )
+			Error( "numFrames <= 0" );
+
+		strcpy( outfilename, filename );
+		if ( strrchr( outfilename, '.' ) )
+			*( strrchr( outfilename, '.' ) + 1 ) = 0;
+		strcat( outfilename, "md3" );
+		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
+
+		// free memory
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( surfaceAnimations[i].frames )
+			{
+				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
+				{
+					free( surfaceAnimations[i].frames[j].triangles );
+				}
+				free( surfaceAnimations[i].frames );
+				surfaceAnimations[i].frames = 0;
+			}
+		}
+	}
+	else if ( type == TYPE_PLAYER )
+	{
+		qboolean tagTorso = qfalse;
+		qboolean tagHead = qfalse;
+		qboolean tagWeapon = qfalse;
+
+		//
+		// verify that all necessary tags exist
+		//
+		numSurfaces = ASE_GetNumSurfaces();
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( !strcmp( ASE_GetSurfaceName( i ), "tag_head" ) )
+			{
+				tagHead = qtrue;
+			}
+			if ( !strcmp( ASE_GetSurfaceName( i ), "tag_torso" ) )
+			{
+				tagTorso = qtrue;
+			}
+			if ( !strcmp( ASE_GetSurfaceName( i ), "tag_weapon" ) )
+			{
+				tagWeapon = qtrue;
+			}
+		}
+
+		if ( !tagWeapon )
+		{
+			Error( "Missing tag_weapon!" );
+		}
+		if ( !tagTorso )
+		{
+			Error( "Missing tag_torso!" );
+		}
+		if ( !tagWeapon )
+		{
+			Error( "Missing tag_weapon!" );
+		}
+
+		// get all upper body surfaces
+		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "u_", -1, -1, g_data.maxUpperFrames );
+		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
+		strcpy( outfilename, filename );
+		if ( strrchr( outfilename, '/' ) )
+			*( strrchr( outfilename, '/' ) + 1 ) = 0;
+
+		if ( g_data.currentLod == 0 )
+		{
+			strcat( outfilename, "upper.md3" );
+		}
+		else
+		{
+			char temp[128];
+
+			sprintf( temp, "upper_%d.md3", g_data.currentLod );
+			strcat( outfilename, temp );
+		}
+		
+		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
+
+		// free memory
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( surfaceAnimations[i].frames )
+			{
+				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
+				{
+					free( surfaceAnimations[i].frames[j].triangles );
+				}
+				free( surfaceAnimations[i].frames );
+				surfaceAnimations[i].frames = 0;
+			}
+		}
+
+		// get lower body surfaces
+		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "l_", g_data.lowerSkipFrameStart, g_data.lowerSkipFrameEnd, -1 );
+		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
+		strcpy( outfilename, filename );
+		if ( strrchr( outfilename, '/' ) )
+			*( strrchr( outfilename, '/' ) + 1 ) = 0;
+
+		if ( g_data.currentLod == 0 )
+		{
+			strcat( outfilename, "lower.md3" );
+		}
+		else
+		{
+			char temp[128];
+
+			sprintf( temp, "lower_%d.md3", g_data.currentLod );
+			strcat( outfilename, temp );
+		}
+		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
+
+		// free memory
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( surfaceAnimations[i].frames )
+			{
+				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
+				{
+					free( surfaceAnimations[i].frames[j].triangles );
+				}
+				free( surfaceAnimations[i].frames );
+				surfaceAnimations[i].frames = 0;
+			}
+		}
+
+		// get head surfaces
+		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "h_", -1, -1, g_data.maxHeadFrames );
+		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
+		strcpy( outfilename, filename );
+		if ( strrchr( outfilename, '/' ) )
+			*( strrchr( outfilename, '/' ) + 1 ) = 0;
+
+		if ( g_data.currentLod == 0 )
+		{
+			strcat( outfilename, "head.md3" );
+		}
+		else
+		{
+			char temp[128];
+
+			sprintf( temp, "head_%d.md3", g_data.currentLod );
+			strcat( outfilename, temp );
+		}
+		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
+
+		// free memory
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( surfaceAnimations[i].frames )
+			{
+				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
+				{
+					free( surfaceAnimations[i].frames[j].triangles );
+				}
+				free( surfaceAnimations[i].frames );
+				surfaceAnimations[i].frames = 0;
+			}
+		}
+	}
+	else if ( type == TYPE_WEAPON )
+	{
+		// get the weapon surfaces
+		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "w_", -1, -1, -1 );
+		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
+
+		strcpy( outfilename, filename );
+		if ( strrchr( outfilename, '.' ) )
+			*( strrchr( outfilename, '.' ) + 1 ) = 0;
+		strcat( outfilename, "md3" );
+		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, type );
+
+		// free memory
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( surfaceAnimations[i].frames )
+			{
+				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
+				{
+					free( surfaceAnimations[i].frames[j].triangles );
+				}
+				free( surfaceAnimations[i].frames );
+				surfaceAnimations[i].frames = 0;
+			}
+		}
+
+		// get the flash surfaces
+		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "f_", -1, -1, -1 );
+		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
+
+		strcpy( outfilename, filename );
+		if ( strrchr( outfilename, '.' ) )
+			*strrchr( outfilename, '.' ) = 0;
+		strcat( outfilename, "_flash.md3" );
+		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, TYPE_ITEM );
+
+		// free memory
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( surfaceAnimations[i].frames )
+			{
+				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
+				{
+					free( surfaceAnimations[i].frames[j].triangles );
+				}
+				free( surfaceAnimations[i].frames );
+				surfaceAnimations[i].frames = 0;
+			}
+		}
+	}
+	else if ( type == TYPE_HAND )
+	{
+		// get the hand tags
+		numSurfaces = GetSurfaceAnimations( surfaceAnimations, "tag_", -1, -1, -1 );
+		numFrames = SurfaceOrderToFrameOrder( surfaceAnimations, objectAnimationFrames, numSurfaces );
+
+		strcpy( outfilename, filename );
+		if ( strrchr( outfilename, '.' ) )
+			*strrchr( outfilename, '.' ) = 0;
+		strcat( outfilename, "_hand.md3" );
+		BuildAnimationFromOAFs( outfilename, objectAnimationFrames, numFrames, TYPE_HAND );
+
+		// free memory
+		for ( i = 0; i < numSurfaces; i++ )
+		{
+			if ( surfaceAnimations[i].frames )
+			{
+				for ( j = 0; j < surfaceAnimations[i].numFrames; j++ )
+				{
+					free( surfaceAnimations[i].frames[j].triangles );
+				}
+				free( surfaceAnimations[i].frames );
+				surfaceAnimations[i].frames = 0;
+			}
+		}
+	}
+	else
+	{
+		Error( "Unknown type passed to ConvertASE()" );
+	}
+
+	g_data.currentLod = 0;
+	g_data.lodBias = 0;
+	g_data.maxHeadFrames = 0;
+	g_data.maxUpperFrames = 0;
+	g_data.lowerSkipFrameStart = 0;
+	g_data.lowerSkipFrameEnd = 0;
+	VectorCopy( vec3_origin, g_data.aseAdjust );
+
+	// unload ASE from memory
+	ASE_Free();
+}
diff --git a/tools/quake3/q3data/oldstuff.c b/tools/quake3/q3data/oldstuff.c
index 2444f95e..c6083cf5 100644
--- a/tools/quake3/q3data/oldstuff.c
+++ b/tools/quake3/q3data/oldstuff.c
@@ -1,130 +1,130 @@
-#if 0
-
-/*
-** ReindexTriangle
-**
-** Given a triangle_t, find which indices match into the associated
-** surface's base triangles.
-*/
-static void ReindexTriangle( int surfno, triangle_t *pTri, int indices[3] )
-{
-	int t, i;
-	md3SurfaceData_t *pSurfData = &g_data.surfData[surfno];
-	int matches[3][3];
-	int numMatches = 0;
-		
-
-	indices[0] = -1;
-	indices[1] = -1;
-	indices[2] = -1;
-
-	for ( i = 0; i < 3; i++ )
-	{
-		numMatches = 0;
-
-		matches[i][0] = -1;
-		matches[i][1] = -1;
-		matches[i][2] = -1;
-
-		for ( t = 0; t < pSurfData->header.numVerts; t++ )
-		{
-			if ( !VectorCompare( pTri->verts[i], pSurfData->baseVertexes[t].xyz ) )
-				continue;
-
-/*				 
-			if ( !VectorCompare( pTri->normals[i], pSurfData->baseVertexes[t].normal ) )
-				continue;
-			if ( pTri->texcoords[i][0] != pSurfData->baseVertexes[t].st[0] )
-				continue;
-			if ( pTri->texcoords[i][1] != pSurfData->baseVertexes[t].st[1] ) 
-				continue;
-*/
-
-			matches[i][numMatches++] = t;
-		}
-
-		if ( indices[i] == -1 )
-		{
-//			Error( "Could not ReindexTriangle, vertex not found" );
-		}
-	}
-
-#if 0
-		for ( t = 0; t < psets[i].numtriangles; t++ )
-		{
-			int b;
-
-			bTri = &g_data.surfData[i].baseTriangles[t];
-
-			for (j=0 ; j<3 ; j++)
-			{
-				bVert = &bTri->v[j];
-
-				// get the xyz index
-				for ( k = 0; k < g_data.surfData[i].header.numVerts; k++ )
-				{
-					if ( ( g_data.surfData[i].baseVertexes[k].st[0] == bVert->st[0] ) &&
-						 ( g_data.surfData[i].baseVertexes[k].st[1] == bVert->st[1] ) &&
-						 ( VectorCompare (bVert->xyz, g_data.surfData[i].baseVertexes[k].xyz) ) &&
-						 ( VectorCompare (bVert->normal, g_data.surfData[i].baseVertexes[k].normal) ) )
-					{
-						break;	// this vertex is already in the base vertex list
-					}
-				}
-
-				if (k == g_data.surfData[i].header.numVerts)	{ // new index
-					g_data.surfData[i].baseVertexes[g_data.surfData[i].header.numVerts] = *bVert;
-					g_data.surfData[i].header.numVerts++;
-				}
-
-				bVert->index = k;
-			}
-		}
-#endif
-}
-
-const char	*FindFrameFile (const char *frame)
-{
-	int			time1;
-	char	file1[1024];
-	static char	retname[1024];
-	char	base[32];
-	char	suffix[32];
-	const char	*s;
-
-	if (strstr (frame, "."))
-		return frame;		// allready in dot format
-
-	// split 'run1' into 'run' and '1'
-	s = frame + strlen(frame)-1;
-
-	while (s != frame && *s >= '0' && *s <= '9')
-		s--;
-
-	strcpy (suffix, s+1);
-	strcpy (base, frame);
-	base[s-frame+1] = 0;
-
-	// check for 'run1.tri'
-	sprintf (file1, "%s/%s%s.tri", g_cddir, base, suffix);
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s%s.tri", base, suffix);
-		return retname;
-	}
-
-	// check for 'run.1'
-	sprintf (file1, "%s/%s.%s",g_cddir, base, suffix);
-	time1 = FileTime (file1);
-	if (time1 != -1)
-	{
-		sprintf (retname, "%s.%s", base, suffix);
-		return retname;
-	}
-
-	Error ("frame %s could not be found",frame);
-	return NULL;
-}
-
-#endif
+#if 0
+
+/*
+** ReindexTriangle
+**
+** Given a triangle_t, find which indices match into the associated
+** surface's base triangles.
+*/
+static void ReindexTriangle( int surfno, triangle_t *pTri, int indices[3] )
+{
+	int t, i;
+	md3SurfaceData_t *pSurfData = &g_data.surfData[surfno];
+	int matches[3][3];
+	int numMatches = 0;
+		
+
+	indices[0] = -1;
+	indices[1] = -1;
+	indices[2] = -1;
+
+	for ( i = 0; i < 3; i++ )
+	{
+		numMatches = 0;
+
+		matches[i][0] = -1;
+		matches[i][1] = -1;
+		matches[i][2] = -1;
+
+		for ( t = 0; t < pSurfData->header.numVerts; t++ )
+		{
+			if ( !VectorCompare( pTri->verts[i], pSurfData->baseVertexes[t].xyz ) )
+				continue;
+
+/*				 
+			if ( !VectorCompare( pTri->normals[i], pSurfData->baseVertexes[t].normal ) )
+				continue;
+			if ( pTri->texcoords[i][0] != pSurfData->baseVertexes[t].st[0] )
+				continue;
+			if ( pTri->texcoords[i][1] != pSurfData->baseVertexes[t].st[1] ) 
+				continue;
+*/
+
+			matches[i][numMatches++] = t;
+		}
+
+		if ( indices[i] == -1 )
+		{
+//			Error( "Could not ReindexTriangle, vertex not found" );
+		}
+	}
+
+#if 0
+		for ( t = 0; t < psets[i].numtriangles; t++ )
+		{
+			int b;
+
+			bTri = &g_data.surfData[i].baseTriangles[t];
+
+			for (j=0 ; j<3 ; j++)
+			{
+				bVert = &bTri->v[j];
+
+				// get the xyz index
+				for ( k = 0; k < g_data.surfData[i].header.numVerts; k++ )
+				{
+					if ( ( g_data.surfData[i].baseVertexes[k].st[0] == bVert->st[0] ) &&
+						 ( g_data.surfData[i].baseVertexes[k].st[1] == bVert->st[1] ) &&
+						 ( VectorCompare (bVert->xyz, g_data.surfData[i].baseVertexes[k].xyz) ) &&
+						 ( VectorCompare (bVert->normal, g_data.surfData[i].baseVertexes[k].normal) ) )
+					{
+						break;	// this vertex is already in the base vertex list
+					}
+				}
+
+				if (k == g_data.surfData[i].header.numVerts)	{ // new index
+					g_data.surfData[i].baseVertexes[g_data.surfData[i].header.numVerts] = *bVert;
+					g_data.surfData[i].header.numVerts++;
+				}
+
+				bVert->index = k;
+			}
+		}
+#endif
+}
+
+const char	*FindFrameFile (const char *frame)
+{
+	int			time1;
+	char	file1[1024];
+	static char	retname[1024];
+	char	base[32];
+	char	suffix[32];
+	const char	*s;
+
+	if (strstr (frame, "."))
+		return frame;		// allready in dot format
+
+	// split 'run1' into 'run' and '1'
+	s = frame + strlen(frame)-1;
+
+	while (s != frame && *s >= '0' && *s <= '9')
+		s--;
+
+	strcpy (suffix, s+1);
+	strcpy (base, frame);
+	base[s-frame+1] = 0;
+
+	// check for 'run1.tri'
+	sprintf (file1, "%s/%s%s.tri", g_cddir, base, suffix);
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s%s.tri", base, suffix);
+		return retname;
+	}
+
+	// check for 'run.1'
+	sprintf (file1, "%s/%s.%s",g_cddir, base, suffix);
+	time1 = FileTime (file1);
+	if (time1 != -1)
+	{
+		sprintf (retname, "%s.%s", base, suffix);
+		return retname;
+	}
+
+	Error ("frame %s could not be found",frame);
+	return NULL;
+}
+
+#endif
diff --git a/tools/quake3/q3data/p3dlib.c b/tools/quake3/q3data/p3dlib.c
index 6afc3491..0c3b6026 100644
--- a/tools/quake3/q3data/p3dlib.c
+++ b/tools/quake3/q3data/p3dlib.c
@@ -1,324 +1,324 @@
-#include "p3dlib.h"
-
-#ifdef _WIN32
-#include <io.h>
-#endif
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-
-#define MAX_POLYSETS 64
-
-#if defined (__linux__) || defined (__APPLE__)
-#define _strcmpi Q_stricmp
-#define filelength Q_filelength
-#define strlwr strlower
-#endif
-typedef struct
-{
-	long len;
-
-	int	 numPairs;
-	char polysetNames[MAX_POLYSETS][256];
-	char shaders[MAX_POLYSETS][256];
-
-	char *buffer, *curpos;
-} p3d_t;
-
-static p3d_t p3d;
-
-static int P3DProcess();
-static int P3DGetToken( int restOfLine );
-
-static char s_token[1024];
-static int	s_curpair;
-
-/*
-** P3DLoad
-**
-*/
-int P3DLoad( const char *filename )
-{
-	FILE *fp = fopen( filename, "rb" );
-
-	if ( !fp )
-		return 0;
-
-	memset( &p3d, 0, sizeof( p3d ) );
-
-	p3d.len = filelength( fileno( fp ) );
-
-	p3d.curpos = p3d.buffer = malloc( p3d.len );
-
-	if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 )
-	{
-		fclose( fp );
-		return 0;
-	}
-
-	fclose( fp );
-
-	return P3DProcess();
-}
-
-/*
-** P3DClose
-**
-*/
-void P3DClose()
-{
-	if ( p3d.buffer )
-	{
-		free( p3d.buffer );
-		p3d.buffer = 0;
-	}
-}
-
-int CharIsTokenDelimiter( int ch )
-{
-	if ( ch <= 32 )
-		return 1;
-	return 0;
-}
-
-int P3DSkipToToken( const char *name )
-{
-	while ( P3DGetToken( 0 ) )
-	{
-		if ( !_strcmpi( s_token, name ) )
-			return 1;
-	}
-
-	return 0;
-}
-
-/*
-** P3DGetToken
-**
-*/
-int P3DGetToken( int restOfLine )
-{
-	int i = 0;
-
-	if ( p3d.buffer == 0 )
-		return 0;
-
-	if ( ( p3d.curpos - p3d.buffer ) == p3d.len )
-		return 0;
-
-	// skip over crap
-	while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
-		    ( *p3d.curpos <= 32 ) )
-	{
-		p3d.curpos++;
-	}
-
-	while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
-	{
-		s_token[i] = *p3d.curpos;
-
-		p3d.curpos++;
-		i++;
-
-		if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
-			 ( ( s_token[i-1] == '\n' ) ) )
-		{
-			s_token[i-1] = 0;
-			break;
-		}
-	}
-
-	s_token[i] = 0;
-
-	return 1;
-}
-
-int P3DGetNextPair( char **psetName, char **associatedShader )
-{
-	if ( s_curpair < p3d.numPairs )
-	{
-		*psetName = p3d.polysetNames[s_curpair];
-		*associatedShader = p3d.shaders[s_curpair];
-		s_curpair++;
-		return 1;
-	}
-
-	return 0;
-}
-
-int P3DSkipToTokenInBlock( const char *name )
-{
-	int iLevel = 0;
-
-	while ( P3DGetToken( 0 ) ) 
-	{
-		if ( !_strcmpi( s_token, "}" ) )
-			iLevel--;
-		else if ( !_strcmpi( s_token, "{" ) )
-			iLevel++;
-
-		if ( !_strcmpi( s_token, name ) )
-			return 1;
-
-		if ( iLevel == 0 )
-		{
-			return 0;
-		}
-	}
-
-	return 0;
-}
-
-/*
-** P3DProcess
-**
-** Nothing fancy here.
-*/
-int P3DProcess()
-{
-
-	s_curpair = 0;
-
-	// first token should be a string
-	P3DGetToken( 1 );		// Voodoo Ascii File
-
-	// skip to the first Obj declaration
-	while ( P3DGetToken( 0 ) )
-	{
-		if ( !_strcmpi( s_token, "Obj" ) )
-		{
-			int j = 0, k = 0;
-
-			if ( P3DSkipToToken( "Text" ) )
-			{
-				if ( P3DSkipToTokenInBlock( "TMap" ) )
-				{
-					char *p;
-
-					if ( !P3DSkipToToken( "Path" ) )
-						return 0;
-
-					if ( !P3DGetToken( 1 ) )
-						return 0;
-
-					while ( s_token[j] != 0 )
-					{
-						if ( s_token[j] == '\\' )
-						{
-							j++;
-							p3d.shaders[p3d.numPairs][k] = '/';
-						}
-						else
-						{
-							p3d.shaders[p3d.numPairs][k] = s_token[j];
-						}
-						j++;
-						k++;
-					}
-					p3d.shaders[p3d.numPairs][k] = 0;
-
-					//
-					// strip off any explicit extensions
-					//
-					if ( ( p = strrchr( p3d.shaders[p3d.numPairs], '/' ) ) != 0 )
-					{
-						while ( *p )
-						{
-							if ( *p == '.' ) 
-							{
-								*p = 0;
-								break;
-							}
-							p++;
-						}
-					}
-
-					//
-					// skip to the end of the Object and grab its name
-					//
-					if ( !P3DSkipToToken( "Name" ) )
-						return 0;
-
-					if ( P3DGetToken( 0 ) )
-					{
-						// strip off leading 'Obj_' if it exists
-						if ( strstr( s_token, "Obj_" ) == s_token )
-							strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
-						else
-							strcpy( p3d.polysetNames[p3d.numPairs], s_token );
-
-						// strip off trailing unused color information
-//						if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
-//							*strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
-
-						p3d.numPairs++;
-					}
-					else
-					{
-						return 0;
-					}
-				}
-			}
-		}
-	}
-
-	s_curpair = 0;
-
-	return 1;
-}
-
-#if 0
-void SkinFromP3D( const char *file )
-{
-	char filename[1024];
-	char *psetName, *associatedShader;
-
-	/*
-	** a P3D file contains a list of polysets, each with a list of associated
-	** texture names that constitute it's
-	**
-	** Thus:
-	**
-	** P3D file -> skin
-	** polyset  -> polyset
-	**   texture -> texture.SHADER becomes polyset's shader
-	*/
-	sprintf( filename, "%s/%s", g_cddir, file );
-
-	if ( !P3DLoad( filename ) )
-		Error( "unable to load '%s'", filename );
-
-	while ( P3DGetNextPair( &psetName, &associatedShader ) )
-	{
-		int i;
-
-		// find the polyset in the object that this particular pset/shader pair
-		// corresponds to and append the shader to it
-		for ( i = 0; i < g_data.model.numSurfaces; i++ )
-		{
-			if ( !_strcmpi( g_data.surfData[i].header.name, psetName) )
-			{
-				char *p;
-
-				if ( strstr( associatedShader, gamedir + 1 ) )
-				{
-					p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
-				}
-				else
-				{
-					p = associatedShader;
-				}
-
-				strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
-
-				g_data.surfData[i].header.numShaders++;
-			}
-		}
-
-	}
-
-	P3DClose();
-}
-#endif
-
-
+#include "p3dlib.h"
+
+#ifdef _WIN32
+#include <io.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+
+#define MAX_POLYSETS 64
+
+#if defined (__linux__) || defined (__APPLE__)
+#define _strcmpi Q_stricmp
+#define filelength Q_filelength
+#define strlwr strlower
+#endif
+typedef struct
+{
+	long len;
+
+	int	 numPairs;
+	char polysetNames[MAX_POLYSETS][256];
+	char shaders[MAX_POLYSETS][256];
+
+	char *buffer, *curpos;
+} p3d_t;
+
+static p3d_t p3d;
+
+static int P3DProcess();
+static int P3DGetToken( int restOfLine );
+
+static char s_token[1024];
+static int	s_curpair;
+
+/*
+** P3DLoad
+**
+*/
+int P3DLoad( const char *filename )
+{
+	FILE *fp = fopen( filename, "rb" );
+
+	if ( !fp )
+		return 0;
+
+	memset( &p3d, 0, sizeof( p3d ) );
+
+	p3d.len = filelength( fileno( fp ) );
+
+	p3d.curpos = p3d.buffer = malloc( p3d.len );
+
+	if ( fread( p3d.buffer, p3d.len, 1, fp ) != 1 )
+	{
+		fclose( fp );
+		return 0;
+	}
+
+	fclose( fp );
+
+	return P3DProcess();
+}
+
+/*
+** P3DClose
+**
+*/
+void P3DClose()
+{
+	if ( p3d.buffer )
+	{
+		free( p3d.buffer );
+		p3d.buffer = 0;
+	}
+}
+
+int CharIsTokenDelimiter( int ch )
+{
+	if ( ch <= 32 )
+		return 1;
+	return 0;
+}
+
+int P3DSkipToToken( const char *name )
+{
+	while ( P3DGetToken( 0 ) )
+	{
+		if ( !_strcmpi( s_token, name ) )
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+** P3DGetToken
+**
+*/
+int P3DGetToken( int restOfLine )
+{
+	int i = 0;
+
+	if ( p3d.buffer == 0 )
+		return 0;
+
+	if ( ( p3d.curpos - p3d.buffer ) == p3d.len )
+		return 0;
+
+	// skip over crap
+	while ( ( ( p3d.curpos - p3d.buffer ) < p3d.len ) &&
+		    ( *p3d.curpos <= 32 ) )
+	{
+		p3d.curpos++;
+	}
+
+	while ( ( p3d.curpos - p3d.buffer ) < p3d.len )
+	{
+		s_token[i] = *p3d.curpos;
+
+		p3d.curpos++;
+		i++;
+
+		if ( ( CharIsTokenDelimiter( s_token[i-1] ) && !restOfLine ) ||
+			 ( ( s_token[i-1] == '\n' ) ) )
+		{
+			s_token[i-1] = 0;
+			break;
+		}
+	}
+
+	s_token[i] = 0;
+
+	return 1;
+}
+
+int P3DGetNextPair( char **psetName, char **associatedShader )
+{
+	if ( s_curpair < p3d.numPairs )
+	{
+		*psetName = p3d.polysetNames[s_curpair];
+		*associatedShader = p3d.shaders[s_curpair];
+		s_curpair++;
+		return 1;
+	}
+
+	return 0;
+}
+
+int P3DSkipToTokenInBlock( const char *name )
+{
+	int iLevel = 0;
+
+	while ( P3DGetToken( 0 ) ) 
+	{
+		if ( !_strcmpi( s_token, "}" ) )
+			iLevel--;
+		else if ( !_strcmpi( s_token, "{" ) )
+			iLevel++;
+
+		if ( !_strcmpi( s_token, name ) )
+			return 1;
+
+		if ( iLevel == 0 )
+		{
+			return 0;
+		}
+	}
+
+	return 0;
+}
+
+/*
+** P3DProcess
+**
+** Nothing fancy here.
+*/
+int P3DProcess()
+{
+
+	s_curpair = 0;
+
+	// first token should be a string
+	P3DGetToken( 1 );		// Voodoo Ascii File
+
+	// skip to the first Obj declaration
+	while ( P3DGetToken( 0 ) )
+	{
+		if ( !_strcmpi( s_token, "Obj" ) )
+		{
+			int j = 0, k = 0;
+
+			if ( P3DSkipToToken( "Text" ) )
+			{
+				if ( P3DSkipToTokenInBlock( "TMap" ) )
+				{
+					char *p;
+
+					if ( !P3DSkipToToken( "Path" ) )
+						return 0;
+
+					if ( !P3DGetToken( 1 ) )
+						return 0;
+
+					while ( s_token[j] != 0 )
+					{
+						if ( s_token[j] == '\\' )
+						{
+							j++;
+							p3d.shaders[p3d.numPairs][k] = '/';
+						}
+						else
+						{
+							p3d.shaders[p3d.numPairs][k] = s_token[j];
+						}
+						j++;
+						k++;
+					}
+					p3d.shaders[p3d.numPairs][k] = 0;
+
+					//
+					// strip off any explicit extensions
+					//
+					if ( ( p = strrchr( p3d.shaders[p3d.numPairs], '/' ) ) != 0 )
+					{
+						while ( *p )
+						{
+							if ( *p == '.' ) 
+							{
+								*p = 0;
+								break;
+							}
+							p++;
+						}
+					}
+
+					//
+					// skip to the end of the Object and grab its name
+					//
+					if ( !P3DSkipToToken( "Name" ) )
+						return 0;
+
+					if ( P3DGetToken( 0 ) )
+					{
+						// strip off leading 'Obj_' if it exists
+						if ( strstr( s_token, "Obj_" ) == s_token )
+							strcpy( p3d.polysetNames[p3d.numPairs], s_token + strlen( "Obj_" ) );
+						else
+							strcpy( p3d.polysetNames[p3d.numPairs], s_token );
+
+						// strip off trailing unused color information
+//						if ( strrchr( p3d.polysetNames[p3d.numPairs], '_' ) != 0 )
+//							*strrchr( p3d.polysetNames[p3d.numPairs], '_' ) = 0;
+
+						p3d.numPairs++;
+					}
+					else
+					{
+						return 0;
+					}
+				}
+			}
+		}
+	}
+
+	s_curpair = 0;
+
+	return 1;
+}
+
+#if 0
+void SkinFromP3D( const char *file )
+{
+	char filename[1024];
+	char *psetName, *associatedShader;
+
+	/*
+	** a P3D file contains a list of polysets, each with a list of associated
+	** texture names that constitute it's
+	**
+	** Thus:
+	**
+	** P3D file -> skin
+	** polyset  -> polyset
+	**   texture -> texture.SHADER becomes polyset's shader
+	*/
+	sprintf( filename, "%s/%s", g_cddir, file );
+
+	if ( !P3DLoad( filename ) )
+		Error( "unable to load '%s'", filename );
+
+	while ( P3DGetNextPair( &psetName, &associatedShader ) )
+	{
+		int i;
+
+		// find the polyset in the object that this particular pset/shader pair
+		// corresponds to and append the shader to it
+		for ( i = 0; i < g_data.model.numSurfaces; i++ )
+		{
+			if ( !_strcmpi( g_data.surfData[i].header.name, psetName) )
+			{
+				char *p;
+
+				if ( strstr( associatedShader, gamedir + 1 ) )
+				{
+					p = strstr( associatedShader, gamedir + 1 ) + strlen( gamedir ) - 1;
+				}
+				else
+				{
+					p = associatedShader;
+				}
+
+				strcpy( g_data.surfData[i].shaders[g_data.surfData[i].header.numShaders].name, p );
+
+				g_data.surfData[i].header.numShaders++;
+			}
+		}
+
+	}
+
+	P3DClose();
+}
+#endif
+
+
diff --git a/tools/quake3/q3data/p3dlib.h b/tools/quake3/q3data/p3dlib.h
index a6c0320d..24e446d1 100644
--- a/tools/quake3/q3data/p3dlib.h
+++ b/tools/quake3/q3data/p3dlib.h
@@ -1,8 +1,8 @@
-
-#define P3D_GET_CROSSLINE		1
-#define P3D_GET_RESTOFLINE		2
-
-int P3DLoad( const char *filename );
-void P3DClose();
-
-int P3DGetNextPair( char **name, char **associatedShader );
+
+#define P3D_GET_CROSSLINE		1
+#define P3D_GET_RESTOFLINE		2
+
+int P3DLoad( const char *filename );
+void P3DClose();
+
+int P3DGetNextPair( char **name, char **associatedShader );
diff --git a/tools/quake3/q3data/polyset.c b/tools/quake3/q3data/polyset.c
index 794fc026..f89a8cc0 100644
--- a/tools/quake3/q3data/polyset.c
+++ b/tools/quake3/q3data/polyset.c
@@ -1,252 +1,252 @@
-#include <assert.h>
-#include "q3data.h"
-
-polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris )
-{
-	int p, np, op;
-	int numNewPolysets = 0;
-	int numSplitPolysets = 0;
-	polyset_t *newpsets;
-	int sumTriangles = 0;
-
-	for ( p = 0; p < numpolysets; p++ )
-	{
-		numNewPolysets += psets[p].numtriangles / maxTris + 1;
-	}
-
-	if ( numNewPolysets == numpolysets )
-		return psets;
-
-	printf( "Warning: creating %d polysets from input of %d polysets\n", numNewPolysets, numpolysets );
-
-	newpsets = calloc( sizeof( polyset_t ) * numNewPolysets, 1 );
-
-	for ( np = 0, op = 0; op < numpolysets; op++ )
-	{
-		numSplitPolysets = ( psets[op].numtriangles / ( maxTris + 1 ) ) + 1;
-		if (  numSplitPolysets == 1 )
-		{
-			memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
-			np++;
-		}
-		else
-		{
-			sumTriangles = 0;
-
-			// split this pset into multiple smaller psets
-			for ( p = 0; p < numSplitPolysets; p++, np++ )
-			{
-				memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
-
-				newpsets[np].triangles = psets[op].triangles + sumTriangles;
-
-				if ( sumTriangles + maxTris > psets[op].numtriangles )
-					newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;
-				else
-					newpsets[np].numtriangles = maxTris;
-
-				sumTriangles += newpsets[np].numtriangles;
-			}
-		}
-	}
-
-	*pNumNewPolysets = numNewPolysets;
-
-	return newpsets;
-}
-
-polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet )
-{
-	polyset_t *psets;
-	polyset_t *finalpsets;
-
-	//
-	// load the frame
-	//
-	if ( strstr( file, ".3DS" ) || strstr( file, ".3ds" ) )
-		_3DS_LoadPolysets( file, &psets, numpolysets, g_verbose );
-	else 
-		Error( "TRI files no longer supported" );
-//		TRI_LoadPolysets( file, &psets, numpolysets );
-
-/*
-	//
-	// scale polysets
-	//
-	for ( i = 0; i < psets; i++ )
-	{
-		int j;
-
-		for ( j = 0; j < psets[i].numtriangles; j++ )
-		{
-		}
-	}
-*/
-
-	//
-	// split polysets if necessary
-	//
-	finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );
-
-	return finalpsets;
-}
-
-polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets )
-{
-	int p;
-	int sumtriangles = 0;
-
-	polyset_t *oldpsets = psets;
-
-	//
-	// no tag checking because this is an $oldbase and thus shouldn't have any
-	// tags
-	//
-	for ( p = 0; p < numpolysets; p++ )
-	{
-		sumtriangles += oldpsets[p].numtriangles;
-	}
-
-	psets = calloc( 1, sizeof( polyset_t ) );
-	psets[0].numtriangles = sumtriangles;
-	psets[0].triangles = malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );
-
-	// each call to "LoadPolysets" only allocates a single large chunk of
-	// triangle memory that is utilized by all the polysets loaded by
-	// that one call
-	memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );
-
-	free( oldpsets[0].triangles );
-	free( oldpsets );
-
-	return psets;
-}
-
-static float SnapFloat( float x )
-{
-	int ix;
-
-	x *= 1.0f / MD3_XYZ_SCALE;
-	ix = ( int ) x;
-	x = ( float ) ix;
-	x *= MD3_XYZ_SCALE;
-
-	return x;
-}
-
-void Polyset_SnapSets( polyset_t *psets, int numpolysets )
-{
-	int p;
-
-	for ( p = 0; p < numpolysets; p++ )
-	{
-		int t;
-
-		for ( t = 0; t < psets[p].numtriangles; t++ )
-		{
-			int v;
-
-			for ( v = 0; v < 3; v++ )
-			{
-				psets[p].triangles[t].verts[v][0] = SnapFloat( psets[p].triangles[t].verts[v][0] );
-				psets[p].triangles[t].verts[v][1] = SnapFloat( psets[p].triangles[t].verts[v][1] );
-				psets[p].triangles[t].verts[v][2] = SnapFloat( psets[p].triangles[t].verts[v][2] );
-			}
-		}
-	}
-}
-
-void Polyset_ComputeNormals( polyset_t *psets, int numpolysets )
-{
-	int p;
-	int i, t;
-	int vertexIndex[MD3_MAX_TRIANGLES][3];
-	vec3_t verts[MD3_MAX_VERTS];
-	vec3_t normals[MD3_MAX_VERTS];
-	vec3_t faceNormals[MD3_MAX_TRIANGLES];
-
-	//
-	// iterate through polysets
-	//
-	for ( p = 0; p < numpolysets; p++ )
-	{
-		int numUniqueVertices = 0;
-
-		assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );
-
-		memset( vertexIndex, 0xff, sizeof( vertexIndex ) );
-		memset( verts, 0, sizeof( verts ) );
-		memset( normals, 0, sizeof( normals ) );
-
-		//
-		// unique vertices
-		//
-		for ( t = 0; t < psets[p].numtriangles; t++ )
-		{
-			int j;
-
-			for ( j = 0; j < 3; j++ )
-			{
-				for ( i = 0; i < numUniqueVertices; i++ )
-				{
-					if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) )
-					{
-						break;
-					}
-				}
-				if ( i == numUniqueVertices )
-				{
-					vertexIndex[t][j] = numUniqueVertices;
-					VectorCopy( (psets[p].triangles[t].verts[j]), (verts[numUniqueVertices]) );
-					numUniqueVertices++;
-				}
-				else
-				{
-					vertexIndex[t][j] = i;
-				}
-			}
-		}
-
-		//
-		// compute face normals
-		//
-		for ( t = 0; t < psets[p].numtriangles; t++ )
-		{
-			vec3_t side0, side1, facenormal;
-
-			VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );
-			VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1);
-
-			CrossProduct( side0, side1, facenormal );
-			VectorNormalize( facenormal, faceNormals[t] );
-		}
-
-		//
-		// sum normals and copy them back
-		//
-		for ( i = 0; i < numUniqueVertices; i++ )
-		{
-			for ( t = 0; t < psets[p].numtriangles; t++ )
-			{
-				if ( vertexIndex[t][0] == i ||
-					 vertexIndex[t][1] == i ||
-					 vertexIndex[t][2] == i )
-				{
-					normals[i][0] += faceNormals[t][0];
-					normals[i][1] += faceNormals[t][1];
-					normals[i][2] += faceNormals[t][2];
-				}
-			}
-			VectorNormalize( normals[i], normals[i] );
-		}
-
-
-		for ( t = 0; t < psets[p].numtriangles; t++ )
-		{
-			VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );
-			VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );
-			VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );
-		}
-	}
-}
-
+#include <assert.h>
+#include "q3data.h"
+
+polyset_t *Polyset_SplitSets( polyset_t *psets, int numpolysets, int *pNumNewPolysets, int maxTris )
+{
+	int p, np, op;
+	int numNewPolysets = 0;
+	int numSplitPolysets = 0;
+	polyset_t *newpsets;
+	int sumTriangles = 0;
+
+	for ( p = 0; p < numpolysets; p++ )
+	{
+		numNewPolysets += psets[p].numtriangles / maxTris + 1;
+	}
+
+	if ( numNewPolysets == numpolysets )
+		return psets;
+
+	printf( "Warning: creating %d polysets from input of %d polysets\n", numNewPolysets, numpolysets );
+
+	newpsets = calloc( sizeof( polyset_t ) * numNewPolysets, 1 );
+
+	for ( np = 0, op = 0; op < numpolysets; op++ )
+	{
+		numSplitPolysets = ( psets[op].numtriangles / ( maxTris + 1 ) ) + 1;
+		if (  numSplitPolysets == 1 )
+		{
+			memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
+			np++;
+		}
+		else
+		{
+			sumTriangles = 0;
+
+			// split this pset into multiple smaller psets
+			for ( p = 0; p < numSplitPolysets; p++, np++ )
+			{
+				memcpy( &newpsets[np], &psets[op], sizeof( polyset_t ) );
+
+				newpsets[np].triangles = psets[op].triangles + sumTriangles;
+
+				if ( sumTriangles + maxTris > psets[op].numtriangles )
+					newpsets[np].numtriangles = psets[op].numtriangles - sumTriangles;
+				else
+					newpsets[np].numtriangles = maxTris;
+
+				sumTriangles += newpsets[np].numtriangles;
+			}
+		}
+	}
+
+	*pNumNewPolysets = numNewPolysets;
+
+	return newpsets;
+}
+
+polyset_t *Polyset_LoadSets( const char *file, int *numpolysets, int maxTrisPerSet )
+{
+	polyset_t *psets;
+	polyset_t *finalpsets;
+
+	//
+	// load the frame
+	//
+	if ( strstr( file, ".3DS" ) || strstr( file, ".3ds" ) )
+		_3DS_LoadPolysets( file, &psets, numpolysets, g_verbose );
+	else 
+		Error( "TRI files no longer supported" );
+//		TRI_LoadPolysets( file, &psets, numpolysets );
+
+/*
+	//
+	// scale polysets
+	//
+	for ( i = 0; i < psets; i++ )
+	{
+		int j;
+
+		for ( j = 0; j < psets[i].numtriangles; j++ )
+		{
+		}
+	}
+*/
+
+	//
+	// split polysets if necessary
+	//
+	finalpsets = Polyset_SplitSets( psets, *numpolysets, numpolysets, maxTrisPerSet );
+
+	return finalpsets;
+}
+
+polyset_t *Polyset_CollapseSets( polyset_t *psets, int numpolysets )
+{
+	int p;
+	int sumtriangles = 0;
+
+	polyset_t *oldpsets = psets;
+
+	//
+	// no tag checking because this is an $oldbase and thus shouldn't have any
+	// tags
+	//
+	for ( p = 0; p < numpolysets; p++ )
+	{
+		sumtriangles += oldpsets[p].numtriangles;
+	}
+
+	psets = calloc( 1, sizeof( polyset_t ) );
+	psets[0].numtriangles = sumtriangles;
+	psets[0].triangles = malloc( MD3_MAX_TRIANGLES * sizeof( triangle_t ) );
+
+	// each call to "LoadPolysets" only allocates a single large chunk of
+	// triangle memory that is utilized by all the polysets loaded by
+	// that one call
+	memcpy( psets[0].triangles, oldpsets[0].triangles, sizeof( triangle_t ) * sumtriangles );
+
+	free( oldpsets[0].triangles );
+	free( oldpsets );
+
+	return psets;
+}
+
+static float SnapFloat( float x )
+{
+	int ix;
+
+	x *= 1.0f / MD3_XYZ_SCALE;
+	ix = ( int ) x;
+	x = ( float ) ix;
+	x *= MD3_XYZ_SCALE;
+
+	return x;
+}
+
+void Polyset_SnapSets( polyset_t *psets, int numpolysets )
+{
+	int p;
+
+	for ( p = 0; p < numpolysets; p++ )
+	{
+		int t;
+
+		for ( t = 0; t < psets[p].numtriangles; t++ )
+		{
+			int v;
+
+			for ( v = 0; v < 3; v++ )
+			{
+				psets[p].triangles[t].verts[v][0] = SnapFloat( psets[p].triangles[t].verts[v][0] );
+				psets[p].triangles[t].verts[v][1] = SnapFloat( psets[p].triangles[t].verts[v][1] );
+				psets[p].triangles[t].verts[v][2] = SnapFloat( psets[p].triangles[t].verts[v][2] );
+			}
+		}
+	}
+}
+
+void Polyset_ComputeNormals( polyset_t *psets, int numpolysets )
+{
+	int p;
+	int i, t;
+	int vertexIndex[MD3_MAX_TRIANGLES][3];
+	vec3_t verts[MD3_MAX_VERTS];
+	vec3_t normals[MD3_MAX_VERTS];
+	vec3_t faceNormals[MD3_MAX_TRIANGLES];
+
+	//
+	// iterate through polysets
+	//
+	for ( p = 0; p < numpolysets; p++ )
+	{
+		int numUniqueVertices = 0;
+
+		assert( psets[p].numtriangles < MD3_MAX_TRIANGLES );
+
+		memset( vertexIndex, 0xff, sizeof( vertexIndex ) );
+		memset( verts, 0, sizeof( verts ) );
+		memset( normals, 0, sizeof( normals ) );
+
+		//
+		// unique vertices
+		//
+		for ( t = 0; t < psets[p].numtriangles; t++ )
+		{
+			int j;
+
+			for ( j = 0; j < 3; j++ )
+			{
+				for ( i = 0; i < numUniqueVertices; i++ )
+				{
+					if ( VectorCompare( psets[p].triangles[t].verts[j], verts[i] ) )
+					{
+						break;
+					}
+				}
+				if ( i == numUniqueVertices )
+				{
+					vertexIndex[t][j] = numUniqueVertices;
+					VectorCopy( (psets[p].triangles[t].verts[j]), (verts[numUniqueVertices]) );
+					numUniqueVertices++;
+				}
+				else
+				{
+					vertexIndex[t][j] = i;
+				}
+			}
+		}
+
+		//
+		// compute face normals
+		//
+		for ( t = 0; t < psets[p].numtriangles; t++ )
+		{
+			vec3_t side0, side1, facenormal;
+
+			VectorSubtract( psets[p].triangles[t].verts[0], psets[p].triangles[t].verts[1], side0 );
+			VectorSubtract( psets[p].triangles[t].verts[2], psets[p].triangles[t].verts[1], side1);
+
+			CrossProduct( side0, side1, facenormal );
+			VectorNormalize( facenormal, faceNormals[t] );
+		}
+
+		//
+		// sum normals and copy them back
+		//
+		for ( i = 0; i < numUniqueVertices; i++ )
+		{
+			for ( t = 0; t < psets[p].numtriangles; t++ )
+			{
+				if ( vertexIndex[t][0] == i ||
+					 vertexIndex[t][1] == i ||
+					 vertexIndex[t][2] == i )
+				{
+					normals[i][0] += faceNormals[t][0];
+					normals[i][1] += faceNormals[t][1];
+					normals[i][2] += faceNormals[t][2];
+				}
+			}
+			VectorNormalize( normals[i], normals[i] );
+		}
+
+
+		for ( t = 0; t < psets[p].numtriangles; t++ )
+		{
+			VectorCopy( normals[vertexIndex[t][0]], psets[p].triangles[t].normals[0] );
+			VectorCopy( normals[vertexIndex[t][1]], psets[p].triangles[t].normals[1] );
+			VectorCopy( normals[vertexIndex[t][2]], psets[p].triangles[t].normals[2] );
+		}
+	}
+}
+
diff --git a/tools/quake3/q3data/q3data.c b/tools/quake3/q3data/q3data.c
index 05ff9220..202f21dd 100644
--- a/tools/quake3/q3data/q3data.c
+++ b/tools/quake3/q3data/q3data.c
@@ -1,643 +1,643 @@
-#ifdef _WIN32
-#include <io.h>
-#endif
-#include "q3data.h"
-#include "md3lib.h"
-
-#include "vfs.h"
-
-qboolean	g_verbose;
-qboolean	g_stripify = qtrue;
-qboolean	g_release;			// don't grab, copy output data to new tree
-char		g_releasedir[1024];	// c:\quake2\baseq2, etc
-qboolean	g_archive;			// don't grab, copy source data to new tree
-char		g_only[256];		// if set, only grab this cd
-qboolean	g_skipmodel;		// set true when a cd is not g_only
-
-// bogus externs for some TA hacks (common/ using them against q3map)
-char *moddir = NULL;
-// some old defined that was in cmdlib lost during merge
-char writedir[1024];
-
-#if defined (__linux__) || defined (__APPLE__)
-#define strlwr strlower
-#endif
-
-/*
-=======================================================
-
-  PAK FILES
-
-=======================================================
-*/
-
-typedef struct
-{
-	char	name[56];
-	int		filepos, filelen;
-} packfile_t;
-
-typedef struct
-{
-	char	id[4];
-	int		dirofs;
-	int		dirlen;
-} packheader_t;
-
-packfile_t		pfiles[16384];
-FILE			*pakfile;
-packfile_t		*pf;
-packheader_t	pakheader;
-
-/*
-==============
-ReleaseFile
-
-Filename should be gamedir reletive.
-Either copies the file to the release dir, or adds it to
-the pak file.
-==============
-*/
-void ReleaseFile (char *filename)
-{
-	char	source[1024];
-	char	dest[1024];
-
-	if (!g_release)
-		return;
-
-	sprintf (source, "%s%s", gamedir, filename);
-	sprintf (dest, "%s/%s", g_releasedir, filename);
-	printf ("copying to %s\n", dest);
-  QCopyFile (source, dest);
-  return;
-}
-
-typedef struct
-{
-	// shader
-	// opaque
-	// opaque 2
-	// blend 
-	// blend 2
-	char names[5][1024];
-	int	 num;
-} ShaderFiles_t;
-
-ShaderFiles_t s_shaderFiles;
-
-void FindShaderFiles( char *filename )
-{
-	char buffer[1024];
-	char stripped[1024];
-	char linebuffer[1024];
-	int len, i;
-	char *buf;
-	char *diffuseExtensions[] =
-	{
-		".TGA",
-		".WAL",
-		".PCX",
-		0
-	};
-	char *otherExtensions[] =
-	{
-		".specular.TGA",
-		".blend.TGA",
-		".alpha.TGA",
-		0
-	};
-
-	s_shaderFiles.num = 0;
-
-	strcpy( stripped, filename );
-	if ( strrchr( stripped, '.' ) )
-		*strrchr( stripped, '.' ) = 0;
-	strcat( stripped, ".shader" );
-
-	if ( FileExists( stripped ) )
-	{
-		char *p;
-		char mapa[512], mapb[512];
-
-		strcpy( s_shaderFiles.names[s_shaderFiles.num], stripped );
-		s_shaderFiles.num++;
-
-		// load and parse
-		len = LoadFile( stripped, (void **)&buf);
-
-		p = buf;
-
-		while ( p - buf < len )
-		{
-			i = 0;
-
-			// skip spaces
-			while ( *p == ' ' || *p == '\n' || *p == '\t' )
-				p++;
-
-			// grab rest of the line
-			while ( *p != 0 && *p != '\n' )
-			{
-				linebuffer[i] = *p;
-				i++;
-				p++;
-			}
-			if ( *p == '\n' )
-				p++;
-			linebuffer[i] = 0;
-
-			strlwr( linebuffer );
-
-			// see if the line specifies an opaque map or blendmap
-			if ( strstr( linebuffer, "opaquemap" ) == linebuffer ||
-				 strstr( linebuffer, "blendmap" ) == linebuffer )
-			{
-				int j;
-
-				i = 0;
-
-				mapa[0] = mapb[0] = 0;
-
-				// skip past the keyword
-				while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
-					i++;
-				// skip past spaces
-				while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
-					i++;
-
-				// grab first map name
-				j = 0;
-				while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
-				{
-					mapa[j] = linebuffer[i];
-					j++;
-					i++;
-				}
-				mapa[j] = 0;
-
-				// skip past spaces
-				while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
-					i++;
-
-				// grab second map name
-				j = 0;
-				while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
-				{
-					mapb[j] = linebuffer[i];
-					j++;
-					i++;
-				}
-				mapb[j] = 0;
-
-				// store map names
-				if ( mapa[0] != 0 && mapa[0] != '-' )
-				{
-					sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapa );
-					s_shaderFiles.num++;
-				}
-				if ( mapb[0] != 0 && mapb[0] != '-' && mapb[0] != '^' && mapb[0] != '*' )
-				{
-					sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapb );
-					s_shaderFiles.num++;
-				}
-			}
-		}
-	}
-	else
-	{
-		if ( strrchr( stripped, '.' ) )
-			*strrchr( stripped, '.' ) = 0;
-
-		// look for diffuse maps
-		for ( i = 0; i < 3; i++ )
-		{
-			strcpy( buffer, stripped );
-			strcat( buffer, diffuseExtensions[i] );
-			if ( FileExists( buffer ) )
-			{
-				strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
-				s_shaderFiles.num++;
-				break;
-			}
-		}
-		for ( i = 0; i < 3; i++ )
-		{
-			strcpy( buffer, stripped );
-			strcat( buffer, otherExtensions[i] );
-			if ( FileExists( buffer ) )
-			{
-				strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
-				s_shaderFiles.num++;
-			}
-		}
-	}
-}
-
-/*
-==============
-ReleaseShader
-
-Copies all needed files for a shader to the release directory
-==============
-*/
-void ReleaseShader( char *filename ) 
-{
-	char fullpath[1024];
-	char dest[1024];
-	char stripped[1024];
-	int i;
-
-	sprintf( fullpath, "%s%s", gamedir, filename );
-
-	FindShaderFiles( fullpath );
-
-	for ( i = 0; i < s_shaderFiles.num; i++ )
-	{
-		strcpy( stripped, s_shaderFiles.names[i] );
-		if ( strstr( stripped, gamedir ) )
-		{
-			memmove( stripped, stripped+ strlen( gamedir ), strlen( stripped ) );
-		}
-		sprintf( dest, "%s/%s", g_releasedir, stripped );
-		printf ("copying to %s\n", dest );
-		QCopyFile( s_shaderFiles.names[i], dest );
-  }
-}
-
-/*
-===============
-Cmd_File
-
-This is only used to cause a file to be copied during a release
-build (default.cfg, maps, etc)
-===============
-*/
-void Cmd_File (void)
-{
-	GetToken (qfalse);
-	ReleaseFile (token);
-}
-
-/*
-===============
-PackDirectory_r
-
-===============
-*/
-#ifdef _WIN32
-#include "io.h"
-void PackDirectory_r (char *dir)
-{
-	struct _finddata_t fileinfo;
-	int		handle;
-	char	dirstring[1024];
-	char	filename[1024];
-
-	sprintf (dirstring, "%s%s/*.*", gamedir, dir);
-
-	handle = _findfirst (dirstring, &fileinfo);
-	if (handle == -1)
-		return;
-
-	do
-	{
-		sprintf (filename, "%s/%s", dir, fileinfo.name);
-		if (fileinfo.attrib & _A_SUBDIR)
-		{	// directory
-			if (fileinfo.name[0] != '.')	// don't pak . and ..
-				PackDirectory_r (filename);
-			continue;
-		}
-		// copy or pack the file
-		ReleaseFile (filename);		
-	} while (_findnext( handle, &fileinfo ) != -1);
-
-	_findclose (handle);
-}
-#else
-
-#include <sys/types.h>
-#ifndef WIN32
-#include <sys/dir.h>
-#else
-#include <sys/dirent.h>
-#endif
-
-void PackDirectory_r (char *dir)
-{
-#ifdef NeXT
-	struct direct **namelist, *ent;
-#else
-	struct dirent **namelist, *ent;
-#endif
-	int		count;
-	struct stat st;
-	int			i;
-	int			len;
-	char		fullname[1024];
-	char		dirstring[1024];
-	char		*name;
-	
-	sprintf (dirstring, "%s%s", gamedir, dir);
-	count = scandir(dirstring, &namelist, NULL, NULL);
-	
-	for (i=0 ; i<count ; i++)
-	{
-		ent = namelist[i];	
-		name = ent->d_name;
-
-		if (name[0] == '.')
-			continue;
-	
-		sprintf (fullname, "%s/%s", dir, name);
-		sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
-		
-		if (stat (dirstring, &st) == -1)
-			Error ("fstating %s", pf->name);
-		if (st.st_mode & S_IFDIR)
-		{	// directory
-			PackDirectory_r (fullname);
-			continue;
-		}
-
-		// copy or pack the file
-		ReleaseFile (fullname);		
-	}
-}
-#endif
-
-
-/*
-===============
-Cmd_Dir
-
-This is only used to cause a directory to be copied during a
-release build (sounds, etc)
-===============
-*/
-void Cmd_Dir (void)
-{
-	GetToken (qfalse);
-	PackDirectory_r (token);	
-}
-
-//========================================================================
-
-#define	MAX_RTEX	16384
-int		numrtex;
-char	rtex[MAX_RTEX][64];
-
-void ReleaseTexture (char *name)
-{
-	int		i;
-	char	path[1024];
-
-	for (i=0 ; i<numrtex ; i++)
-		if (!Q_stricmp(name, rtex[i]))
-			return;
-
-	if (numrtex == MAX_RTEX)
-		Error ("numrtex == MAX_RTEX");
-
-	strcpy (rtex[i], name);
-	numrtex++;
-
-	sprintf (path, "textures/%s.wal", name);
-	ReleaseFile (path);
-}
-
-/*
-===============
-Cmd_Maps
-
-Only relevent for release and pak files.
-Releases the .bsp files for the maps, and scans all of the files to
-build a list of all textures used, which are then released.
-===============
-*/
-void Cmd_Maps (void)
-{
-	char	map[1024];
-
-	while (TokenAvailable ())
-	{
-		GetToken (qfalse);
-		sprintf (map, "maps/%s.bsp", token);
-		ReleaseFile (map);
-
-		if (!g_release)
-			continue;
-
-		// get all the texture references
-		sprintf (map, "%smaps/%s.bsp", gamedir, token);
-		LoadBSPFile( map );
-	}
-}
-
-
-//==============================================================
-
-/*
-===============
-ParseScript
-===============
-*/
-void ParseScript (void)
-{
-	while (1)
-	{
-		do
-		{	// look for a line starting with a $ command
-			GetToken (qtrue);
-			if (endofscript)
-				return;
-			if (token[0] == '$')
-				break;				
-			while (TokenAvailable())
-				GetToken (qfalse);
-		} while (1);
-	
-		//
-		// model commands
-		//
-		if (!strcmp (token, "$modelname"))
-			Cmd_Modelname ();
-		else if (!strcmp (token, "$base"))
-			Cmd_Base ();
-		else if ( !strcmp( token, "$exit" ) )
-			break;
-		else if ( !strcmp( token, "$3dsconvert" ) )
-			Cmd_3DSConvert();
-		else if (!strcmp (token, "$spritebase"))
-			Cmd_SpriteBase ();
-		else if (!strcmp (token, "$cd"))
-			Cmd_Cd ();
-		else if (!strcmp (token, "$origin"))
-			Cmd_Origin ();
-		else if (!strcmp (token, "$scale"))
-			Cmd_ScaleUp ();
-		else if (!strcmp (token, "$frame"))
-			Cmd_Frame ();
-		else if (!strcmp (token, "$skin" ))
-			Cmd_Skin();
-		else if (!strcmp (token, "$spriteshader"))
-			Cmd_SpriteShader();
-		else if (!strcmp( token, "$aseconvert" ))
-			Cmd_ASEConvert( qfalse );
-		else if (!strcmp( token, "$aseanimconvert" ) )
-			Cmd_ASEConvert( qtrue );
-
-		//
-		// image commands
-		//
-		else if (!strcmp (token, "$grab"))
-			Cmd_Grab ();
-		else if (!strcmp (token, "$raw"))
-			Cmd_Raw ();
-		else if (!strcmp (token, "$colormap"))
-			Cmd_Colormap ();
-		else if (!strcmp (token, "$environment"))
-			Cmd_Environment ();
-
-		//
-		// video
-		//
-		else if (!strcmp (token, "$video"))
-			Cmd_Video ();
-		//
-		// misc
-		//
-		else if (!strcmp (token, "$file"))
-			Cmd_File ();
-		else if (!strcmp (token, "$dir"))
-			Cmd_Dir ();
-		else if (!strcmp (token, "$maps"))
-			Cmd_Maps ();
-		else
-			Error ("bad command %s\n", token);
-	}
-}
-
-//=======================================================
-
-#include "version.h"
-
-/*
-==============
-main
-==============
-*/
-int main (int argc, char **argv)
-{
-	static	int		i;		// VC4.2 compiler bug if auto...
-	char	path[1024];
-
-  // using GtkRadiant's versioning next to Id's versioning
-  printf ("Q3Data      - (c) 1999 Id Software Inc.\n");
-  printf ("GtkRadiant  - v" RADIANT_VERSION " " __DATE__ "\n");
-
-	ExpandWildcards (&argc, &argv);
-
-	for (i=1 ; i<argc ; i++)
-	{
-		if (!strcmp(argv[i], "-archive"))
-		{
-			archive = qtrue;
-			strcpy (archivedir, argv[i+1]);
-			printf ("Archiving source to: %s\n", archivedir);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-release"))
-		{
-			g_release = qtrue;
-			strcpy (g_releasedir, argv[i+1]);
-			printf ("Copy output to: %s\n", g_releasedir);
-			i++;
-		}
-		else if ( !strcmp( argv[i], "-nostrips" ) )
-		{
-			g_stripify = qfalse;
-			printf( "Not optimizing for strips\n" );
-		}
-		else if ( !strcmp( argv[i], "-writedir" ) )
-		{
-			strcpy( writedir, argv[i+1] );
-			printf( "Write output to: %s\n", writedir );
-			i++;
-		}
-		else if ( !strcmp( argv[i], "-verbose" ) )
-		{
-			g_verbose = qtrue;
-		}
-		else if ( !strcmp( argv[i], "-dump" ) )
-		{
-			printf( "Dumping contents of: '%s'\n", argv[i+1] );
-			if ( strstr( argv[i+1], ".md3" ) )
-			{
-				MD3_Dump( argv[i+1] );
-			}
-			else
-			{
-				Error( "Do not know how to dump the contents of '%s'\n", argv[i+1] );
-			}
-			i++;
-		}
-		else if ( !strcmp( argv[i], "-3dsconvert" ) )
-		{
-      // NOTE TTimo this is broken, tried on a sample .3ds
-      // what happens .. it calls the Convert3DStoMD3,
-      // which calls the scriptlib function in non initialized state .. and crashes
-			printf( "Converting %s.3DS to %s.MD3\n", argv[i+1], argv[i+1] );
-			SetQdirFromPath( argv[i+1] );
-      vfsInitDirectory( gamedir );
-			Convert3DStoMD3( argv[i+1] );
-			i++;
-		}
-		else if (!strcmp(argv[i], "-only"))
-		{
-			strcpy (g_only, argv[i+1]);
-			printf ("Only grabbing %s\n", g_only);
-			i++;
-		}
-		else if (!strcmp(argv[i], "-gamedir"))
-		{
-			strcpy(gamedir, argv[i+1]);
-			i++;
-		}
-		else if (argv[i][0] == '-')
-			Error ("Unknown option \"%s\"", argv[i]);
-		else
-			break;
-	}
-
-	if (i == argc)
-		Error ("usage: q3data [-archive <directory>] [-dump <file.md3>] [-release <directory>] [-only <model>] [-3dsconvert <file.3ds>] [-verbose] [file.qdt]");
-
-	for ( ; i<argc ; i++)
-	{
-		printf ("--------------- %s ---------------\n", argv[i]);
-		// load the script
-		strcpy (path, argv[i]);
-		DefaultExtension (path, ".qdt");
-		if(!gamedir[0])
-			SetQdirFromPath (path);
-    // NOTE TTimo
-    // q3data went through a partial conversion to use the vfs
-    // it was never actually tested before 1.1.1
-    // the code is still mostly using direct file access calls
-    vfsInitDirectory( gamedir );
-		LoadScriptFile (ExpandArg(path), -1);
-		
-		//
-		// parse it
-		//
-		ParseScript ();
-
-		// write out the last model
-		FinishModel ( TYPE_UNKNOWN );
-	}
-
-	return 0;
-}
-
+#ifdef _WIN32
+#include <io.h>
+#endif
+#include "q3data.h"
+#include "md3lib.h"
+
+#include "vfs.h"
+
+qboolean	g_verbose;
+qboolean	g_stripify = qtrue;
+qboolean	g_release;			// don't grab, copy output data to new tree
+char		g_releasedir[1024];	// c:\quake2\baseq2, etc
+qboolean	g_archive;			// don't grab, copy source data to new tree
+char		g_only[256];		// if set, only grab this cd
+qboolean	g_skipmodel;		// set true when a cd is not g_only
+
+// bogus externs for some TA hacks (common/ using them against q3map)
+char *moddir = NULL;
+// some old defined that was in cmdlib lost during merge
+char writedir[1024];
+
+#if defined (__linux__) || defined (__APPLE__)
+#define strlwr strlower
+#endif
+
+/*
+=======================================================
+
+  PAK FILES
+
+=======================================================
+*/
+
+typedef struct
+{
+	char	name[56];
+	int		filepos, filelen;
+} packfile_t;
+
+typedef struct
+{
+	char	id[4];
+	int		dirofs;
+	int		dirlen;
+} packheader_t;
+
+packfile_t		pfiles[16384];
+FILE			*pakfile;
+packfile_t		*pf;
+packheader_t	pakheader;
+
+/*
+==============
+ReleaseFile
+
+Filename should be gamedir reletive.
+Either copies the file to the release dir, or adds it to
+the pak file.
+==============
+*/
+void ReleaseFile (char *filename)
+{
+	char	source[1024];
+	char	dest[1024];
+
+	if (!g_release)
+		return;
+
+	sprintf (source, "%s%s", gamedir, filename);
+	sprintf (dest, "%s/%s", g_releasedir, filename);
+	printf ("copying to %s\n", dest);
+  QCopyFile (source, dest);
+  return;
+}
+
+typedef struct
+{
+	// shader
+	// opaque
+	// opaque 2
+	// blend 
+	// blend 2
+	char names[5][1024];
+	int	 num;
+} ShaderFiles_t;
+
+ShaderFiles_t s_shaderFiles;
+
+void FindShaderFiles( char *filename )
+{
+	char buffer[1024];
+	char stripped[1024];
+	char linebuffer[1024];
+	int len, i;
+	char *buf;
+	char *diffuseExtensions[] =
+	{
+		".TGA",
+		".WAL",
+		".PCX",
+		0
+	};
+	char *otherExtensions[] =
+	{
+		".specular.TGA",
+		".blend.TGA",
+		".alpha.TGA",
+		0
+	};
+
+	s_shaderFiles.num = 0;
+
+	strcpy( stripped, filename );
+	if ( strrchr( stripped, '.' ) )
+		*strrchr( stripped, '.' ) = 0;
+	strcat( stripped, ".shader" );
+
+	if ( FileExists( stripped ) )
+	{
+		char *p;
+		char mapa[512], mapb[512];
+
+		strcpy( s_shaderFiles.names[s_shaderFiles.num], stripped );
+		s_shaderFiles.num++;
+
+		// load and parse
+		len = LoadFile( stripped, (void **)&buf);
+
+		p = buf;
+
+		while ( p - buf < len )
+		{
+			i = 0;
+
+			// skip spaces
+			while ( *p == ' ' || *p == '\n' || *p == '\t' )
+				p++;
+
+			// grab rest of the line
+			while ( *p != 0 && *p != '\n' )
+			{
+				linebuffer[i] = *p;
+				i++;
+				p++;
+			}
+			if ( *p == '\n' )
+				p++;
+			linebuffer[i] = 0;
+
+			strlwr( linebuffer );
+
+			// see if the line specifies an opaque map or blendmap
+			if ( strstr( linebuffer, "opaquemap" ) == linebuffer ||
+				 strstr( linebuffer, "blendmap" ) == linebuffer )
+			{
+				int j;
+
+				i = 0;
+
+				mapa[0] = mapb[0] = 0;
+
+				// skip past the keyword
+				while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
+					i++;
+				// skip past spaces
+				while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
+					i++;
+
+				// grab first map name
+				j = 0;
+				while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
+				{
+					mapa[j] = linebuffer[i];
+					j++;
+					i++;
+				}
+				mapa[j] = 0;
+
+				// skip past spaces
+				while ( ( linebuffer[i] == ' ' || linebuffer[i] == '\t' ) && linebuffer[i] )
+					i++;
+
+				// grab second map name
+				j = 0;
+				while ( linebuffer[i] != ' ' && linebuffer[i] != '\t' && linebuffer[i] )
+				{
+					mapb[j] = linebuffer[i];
+					j++;
+					i++;
+				}
+				mapb[j] = 0;
+
+				// store map names
+				if ( mapa[0] != 0 && mapa[0] != '-' )
+				{
+					sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapa );
+					s_shaderFiles.num++;
+				}
+				if ( mapb[0] != 0 && mapb[0] != '-' && mapb[0] != '^' && mapb[0] != '*' )
+				{
+					sprintf( s_shaderFiles.names[s_shaderFiles.num], "%s%s", gamedir, mapb );
+					s_shaderFiles.num++;
+				}
+			}
+		}
+	}
+	else
+	{
+		if ( strrchr( stripped, '.' ) )
+			*strrchr( stripped, '.' ) = 0;
+
+		// look for diffuse maps
+		for ( i = 0; i < 3; i++ )
+		{
+			strcpy( buffer, stripped );
+			strcat( buffer, diffuseExtensions[i] );
+			if ( FileExists( buffer ) )
+			{
+				strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
+				s_shaderFiles.num++;
+				break;
+			}
+		}
+		for ( i = 0; i < 3; i++ )
+		{
+			strcpy( buffer, stripped );
+			strcat( buffer, otherExtensions[i] );
+			if ( FileExists( buffer ) )
+			{
+				strcpy( s_shaderFiles.names[s_shaderFiles.num], buffer );
+				s_shaderFiles.num++;
+			}
+		}
+	}
+}
+
+/*
+==============
+ReleaseShader
+
+Copies all needed files for a shader to the release directory
+==============
+*/
+void ReleaseShader( char *filename ) 
+{
+	char fullpath[1024];
+	char dest[1024];
+	char stripped[1024];
+	int i;
+
+	sprintf( fullpath, "%s%s", gamedir, filename );
+
+	FindShaderFiles( fullpath );
+
+	for ( i = 0; i < s_shaderFiles.num; i++ )
+	{
+		strcpy( stripped, s_shaderFiles.names[i] );
+		if ( strstr( stripped, gamedir ) )
+		{
+			memmove( stripped, stripped+ strlen( gamedir ), strlen( stripped ) );
+		}
+		sprintf( dest, "%s/%s", g_releasedir, stripped );
+		printf ("copying to %s\n", dest );
+		QCopyFile( s_shaderFiles.names[i], dest );
+  }
+}
+
+/*
+===============
+Cmd_File
+
+This is only used to cause a file to be copied during a release
+build (default.cfg, maps, etc)
+===============
+*/
+void Cmd_File (void)
+{
+	GetToken (qfalse);
+	ReleaseFile (token);
+}
+
+/*
+===============
+PackDirectory_r
+
+===============
+*/
+#ifdef _WIN32
+#include "io.h"
+void PackDirectory_r (char *dir)
+{
+	struct _finddata_t fileinfo;
+	int		handle;
+	char	dirstring[1024];
+	char	filename[1024];
+
+	sprintf (dirstring, "%s%s/*.*", gamedir, dir);
+
+	handle = _findfirst (dirstring, &fileinfo);
+	if (handle == -1)
+		return;
+
+	do
+	{
+		sprintf (filename, "%s/%s", dir, fileinfo.name);
+		if (fileinfo.attrib & _A_SUBDIR)
+		{	// directory
+			if (fileinfo.name[0] != '.')	// don't pak . and ..
+				PackDirectory_r (filename);
+			continue;
+		}
+		// copy or pack the file
+		ReleaseFile (filename);		
+	} while (_findnext( handle, &fileinfo ) != -1);
+
+	_findclose (handle);
+}
+#else
+
+#include <sys/types.h>
+#ifndef WIN32
+#include <sys/dir.h>
+#else
+#include <sys/dirent.h>
+#endif
+
+void PackDirectory_r (char *dir)
+{
+#ifdef NeXT
+	struct direct **namelist, *ent;
+#else
+	struct dirent **namelist, *ent;
+#endif
+	int		count;
+	struct stat st;
+	int			i;
+	int			len;
+	char		fullname[1024];
+	char		dirstring[1024];
+	char		*name;
+	
+	sprintf (dirstring, "%s%s", gamedir, dir);
+	count = scandir(dirstring, &namelist, NULL, NULL);
+	
+	for (i=0 ; i<count ; i++)
+	{
+		ent = namelist[i];	
+		name = ent->d_name;
+
+		if (name[0] == '.')
+			continue;
+	
+		sprintf (fullname, "%s/%s", dir, name);
+		sprintf (dirstring, "%s%s/%s", gamedir, dir, name);
+		
+		if (stat (dirstring, &st) == -1)
+			Error ("fstating %s", pf->name);
+		if (st.st_mode & S_IFDIR)
+		{	// directory
+			PackDirectory_r (fullname);
+			continue;
+		}
+
+		// copy or pack the file
+		ReleaseFile (fullname);		
+	}
+}
+#endif
+
+
+/*
+===============
+Cmd_Dir
+
+This is only used to cause a directory to be copied during a
+release build (sounds, etc)
+===============
+*/
+void Cmd_Dir (void)
+{
+	GetToken (qfalse);
+	PackDirectory_r (token);	
+}
+
+//========================================================================
+
+#define	MAX_RTEX	16384
+int		numrtex;
+char	rtex[MAX_RTEX][64];
+
+void ReleaseTexture (char *name)
+{
+	int		i;
+	char	path[1024];
+
+	for (i=0 ; i<numrtex ; i++)
+		if (!Q_stricmp(name, rtex[i]))
+			return;
+
+	if (numrtex == MAX_RTEX)
+		Error ("numrtex == MAX_RTEX");
+
+	strcpy (rtex[i], name);
+	numrtex++;
+
+	sprintf (path, "textures/%s.wal", name);
+	ReleaseFile (path);
+}
+
+/*
+===============
+Cmd_Maps
+
+Only relevent for release and pak files.
+Releases the .bsp files for the maps, and scans all of the files to
+build a list of all textures used, which are then released.
+===============
+*/
+void Cmd_Maps (void)
+{
+	char	map[1024];
+
+	while (TokenAvailable ())
+	{
+		GetToken (qfalse);
+		sprintf (map, "maps/%s.bsp", token);
+		ReleaseFile (map);
+
+		if (!g_release)
+			continue;
+
+		// get all the texture references
+		sprintf (map, "%smaps/%s.bsp", gamedir, token);
+		LoadBSPFile( map );
+	}
+}
+
+
+//==============================================================
+
+/*
+===============
+ParseScript
+===============
+*/
+void ParseScript (void)
+{
+	while (1)
+	{
+		do
+		{	// look for a line starting with a $ command
+			GetToken (qtrue);
+			if (endofscript)
+				return;
+			if (token[0] == '$')
+				break;				
+			while (TokenAvailable())
+				GetToken (qfalse);
+		} while (1);
+	
+		//
+		// model commands
+		//
+		if (!strcmp (token, "$modelname"))
+			Cmd_Modelname ();
+		else if (!strcmp (token, "$base"))
+			Cmd_Base ();
+		else if ( !strcmp( token, "$exit" ) )
+			break;
+		else if ( !strcmp( token, "$3dsconvert" ) )
+			Cmd_3DSConvert();
+		else if (!strcmp (token, "$spritebase"))
+			Cmd_SpriteBase ();
+		else if (!strcmp (token, "$cd"))
+			Cmd_Cd ();
+		else if (!strcmp (token, "$origin"))
+			Cmd_Origin ();
+		else if (!strcmp (token, "$scale"))
+			Cmd_ScaleUp ();
+		else if (!strcmp (token, "$frame"))
+			Cmd_Frame ();
+		else if (!strcmp (token, "$skin" ))
+			Cmd_Skin();
+		else if (!strcmp (token, "$spriteshader"))
+			Cmd_SpriteShader();
+		else if (!strcmp( token, "$aseconvert" ))
+			Cmd_ASEConvert( qfalse );
+		else if (!strcmp( token, "$aseanimconvert" ) )
+			Cmd_ASEConvert( qtrue );
+
+		//
+		// image commands
+		//
+		else if (!strcmp (token, "$grab"))
+			Cmd_Grab ();
+		else if (!strcmp (token, "$raw"))
+			Cmd_Raw ();
+		else if (!strcmp (token, "$colormap"))
+			Cmd_Colormap ();
+		else if (!strcmp (token, "$environment"))
+			Cmd_Environment ();
+
+		//
+		// video
+		//
+		else if (!strcmp (token, "$video"))
+			Cmd_Video ();
+		//
+		// misc
+		//
+		else if (!strcmp (token, "$file"))
+			Cmd_File ();
+		else if (!strcmp (token, "$dir"))
+			Cmd_Dir ();
+		else if (!strcmp (token, "$maps"))
+			Cmd_Maps ();
+		else
+			Error ("bad command %s\n", token);
+	}
+}
+
+//=======================================================
+
+#include "version.h"
+
+/*
+==============
+main
+==============
+*/
+int main (int argc, char **argv)
+{
+	static	int		i;		// VC4.2 compiler bug if auto...
+	char	path[1024];
+
+  // using GtkRadiant's versioning next to Id's versioning
+  printf ("Q3Data      - (c) 1999 Id Software Inc.\n");
+  printf ("GtkRadiant  - v" RADIANT_VERSION " " __DATE__ "\n");
+
+	ExpandWildcards (&argc, &argv);
+
+	for (i=1 ; i<argc ; i++)
+	{
+		if (!strcmp(argv[i], "-archive"))
+		{
+			archive = qtrue;
+			strcpy (archivedir, argv[i+1]);
+			printf ("Archiving source to: %s\n", archivedir);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-release"))
+		{
+			g_release = qtrue;
+			strcpy (g_releasedir, argv[i+1]);
+			printf ("Copy output to: %s\n", g_releasedir);
+			i++;
+		}
+		else if ( !strcmp( argv[i], "-nostrips" ) )
+		{
+			g_stripify = qfalse;
+			printf( "Not optimizing for strips\n" );
+		}
+		else if ( !strcmp( argv[i], "-writedir" ) )
+		{
+			strcpy( writedir, argv[i+1] );
+			printf( "Write output to: %s\n", writedir );
+			i++;
+		}
+		else if ( !strcmp( argv[i], "-verbose" ) )
+		{
+			g_verbose = qtrue;
+		}
+		else if ( !strcmp( argv[i], "-dump" ) )
+		{
+			printf( "Dumping contents of: '%s'\n", argv[i+1] );
+			if ( strstr( argv[i+1], ".md3" ) )
+			{
+				MD3_Dump( argv[i+1] );
+			}
+			else
+			{
+				Error( "Do not know how to dump the contents of '%s'\n", argv[i+1] );
+			}
+			i++;
+		}
+		else if ( !strcmp( argv[i], "-3dsconvert" ) )
+		{
+      // NOTE TTimo this is broken, tried on a sample .3ds
+      // what happens .. it calls the Convert3DStoMD3,
+      // which calls the scriptlib function in non initialized state .. and crashes
+			printf( "Converting %s.3DS to %s.MD3\n", argv[i+1], argv[i+1] );
+			SetQdirFromPath( argv[i+1] );
+      vfsInitDirectory( gamedir );
+			Convert3DStoMD3( argv[i+1] );
+			i++;
+		}
+		else if (!strcmp(argv[i], "-only"))
+		{
+			strcpy (g_only, argv[i+1]);
+			printf ("Only grabbing %s\n", g_only);
+			i++;
+		}
+		else if (!strcmp(argv[i], "-gamedir"))
+		{
+			strcpy(gamedir, argv[i+1]);
+			i++;
+		}
+		else if (argv[i][0] == '-')
+			Error ("Unknown option \"%s\"", argv[i]);
+		else
+			break;
+	}
+
+	if (i == argc)
+		Error ("usage: q3data [-archive <directory>] [-dump <file.md3>] [-release <directory>] [-only <model>] [-3dsconvert <file.3ds>] [-verbose] [file.qdt]");
+
+	for ( ; i<argc ; i++)
+	{
+		printf ("--------------- %s ---------------\n", argv[i]);
+		// load the script
+		strcpy (path, argv[i]);
+		DefaultExtension (path, ".qdt");
+		if(!gamedir[0])
+			SetQdirFromPath (path);
+    // NOTE TTimo
+    // q3data went through a partial conversion to use the vfs
+    // it was never actually tested before 1.1.1
+    // the code is still mostly using direct file access calls
+    vfsInitDirectory( gamedir );
+		LoadScriptFile (ExpandArg(path), -1);
+		
+		//
+		// parse it
+		//
+		ParseScript ();
+
+		// write out the last model
+		FinishModel ( TYPE_UNKNOWN );
+	}
+
+	return 0;
+}
+
diff --git a/tools/quake3/q3data/q3data.h b/tools/quake3/q3data/q3data.h
index a8939513..458d4ed6 100644
--- a/tools/quake3/q3data/q3data.h
+++ b/tools/quake3/q3data/q3data.h
@@ -1,78 +1,78 @@
-// q3data.h
-
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <math.h>
-#include <string.h>
-#include <sys/stat.h>
-
-#include "../common/cmdlib.h"
-#include "scriplib.h"
-#include "mathlib.h"
-#include "polyset.h"
-#include "trilib.h"
-#include "imagelib.h"
-#include "qthreads.h"
-#include "l3dslib.h"
-#include "bspfile.h"
-#include "p3dlib.h"
-#include "3dslib.h"
-#include "aselib.h"
-#include "md3lib.h"
-
-void Cmd_ASEConvert( qboolean grabAnims );
-void Cmd_3DSConvert( void );
-void Cmd_Modelname (void);
-void Cmd_SpriteBase (void);
-void Cmd_Base (void);
-void Cmd_Cd (void);
-void Cmd_Origin (void);
-void Cmd_ScaleUp (void);
-void Cmd_Frame (void);
-void Cmd_Modelname (void);
-void Cmd_SpriteShader(void);
-void Cmd_Skin(void);
-void Cmd_Skinsize (void);
-void FinishModel (int type);
-
-void Cmd_Grab (void);
-void Cmd_Raw (void);
-void Cmd_Mip (void);
-void Cmd_Environment (void);
-void Cmd_Colormap (void);
-
-void Cmd_File (void);
-void Cmd_Dir (void);
-void Cmd_StartWad (void);
-void Cmd_EndWad (void);
-void Cmd_Mippal (void);
-void Cmd_Mipdir (void);
-
-void Cmd_Video (void);
-
-void ReleaseFile (char *filename);
-void ReleaseShader( char *filename );
-
-void Convert3DStoMD3( const char *filename );
-
-void OrderMesh( int input[][3], int output[][3], int numTris );
-
-extern	byte		*byteimage, *lbmpalette;
-extern	int			byteimagewidth, byteimageheight;
-
-extern	qboolean	g_release;			// don't grab, copy output data to new tree
-extern	char		g_releasedir[1024];	// c:\quake2\baseq2, etc
-extern	qboolean	g_archive;			// don't grab, copy source data to new tree
-extern	qboolean	do3ds;
-extern	char		g_only[256];		// if set, only grab this cd
-extern	qboolean	g_skipmodel;		// set true when a cd is not g_only
-extern	qboolean	g_verbose;
-
-extern	char		*trifileext;
-
-#define TYPE_ITEM		0
-#define TYPE_PLAYER		1
-#define TYPE_WEAPON		2
-#define TYPE_HAND		3
-#define TYPE_UNKNOWN	4
+// q3data.h
+
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <math.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#include "../common/cmdlib.h"
+#include "scriplib.h"
+#include "mathlib.h"
+#include "polyset.h"
+#include "trilib.h"
+#include "imagelib.h"
+#include "qthreads.h"
+#include "l3dslib.h"
+#include "bspfile.h"
+#include "p3dlib.h"
+#include "3dslib.h"
+#include "aselib.h"
+#include "md3lib.h"
+
+void Cmd_ASEConvert( qboolean grabAnims );
+void Cmd_3DSConvert( void );
+void Cmd_Modelname (void);
+void Cmd_SpriteBase (void);
+void Cmd_Base (void);
+void Cmd_Cd (void);
+void Cmd_Origin (void);
+void Cmd_ScaleUp (void);
+void Cmd_Frame (void);
+void Cmd_Modelname (void);
+void Cmd_SpriteShader(void);
+void Cmd_Skin(void);
+void Cmd_Skinsize (void);
+void FinishModel (int type);
+
+void Cmd_Grab (void);
+void Cmd_Raw (void);
+void Cmd_Mip (void);
+void Cmd_Environment (void);
+void Cmd_Colormap (void);
+
+void Cmd_File (void);
+void Cmd_Dir (void);
+void Cmd_StartWad (void);
+void Cmd_EndWad (void);
+void Cmd_Mippal (void);
+void Cmd_Mipdir (void);
+
+void Cmd_Video (void);
+
+void ReleaseFile (char *filename);
+void ReleaseShader( char *filename );
+
+void Convert3DStoMD3( const char *filename );
+
+void OrderMesh( int input[][3], int output[][3], int numTris );
+
+extern	byte		*byteimage, *lbmpalette;
+extern	int			byteimagewidth, byteimageheight;
+
+extern	qboolean	g_release;			// don't grab, copy output data to new tree
+extern	char		g_releasedir[1024];	// c:\quake2\baseq2, etc
+extern	qboolean	g_archive;			// don't grab, copy source data to new tree
+extern	qboolean	do3ds;
+extern	char		g_only[256];		// if set, only grab this cd
+extern	qboolean	g_skipmodel;		// set true when a cd is not g_only
+extern	qboolean	g_verbose;
+
+extern	char		*trifileext;
+
+#define TYPE_ITEM		0
+#define TYPE_PLAYER		1
+#define TYPE_WEAPON		2
+#define TYPE_HAND		3
+#define TYPE_UNKNOWN	4
diff --git a/tools/quake3/q3data/stripper.c b/tools/quake3/q3data/stripper.c
index 8229aba3..c42d4420 100644
--- a/tools/quake3/q3data/stripper.c
+++ b/tools/quake3/q3data/stripper.c
@@ -1,282 +1,282 @@
-#include <stdio.h>
-#include <string.h>
-#include <stdlib.h>
-
-static int s_used[8192];		// same as MD3_MAX_TRIANGLES
-
-/*
-** FindNextTriangleInStrip
-**
-** Given a surface and triangle this tries to find the next triangle 
-** in the strip that would continue the strip.  The next triangle in
-** the strip should have the same winding as this triangle.
-*/
-static int FindNextTriangleInStripOrFan( int mesh[][3], int tri, int orientation, int numTris, int odd )
-{
-	int t;
-	int sum = 0;
-	int currentTri[3];
-	int side;
-	int a, b, c;
-	int refa, refb;
-
-	currentTri[0] = mesh[tri][(0+orientation)%3];
-	currentTri[1] = mesh[tri][(1+orientation)%3];
-	currentTri[2] = mesh[tri][(2+orientation)%3];
-
-	if ( odd )
-	{
-		refa = currentTri[1];
-		refb = currentTri[2];
-	}
-	else
-	{
-		refa = currentTri[2];
-		refb = currentTri[0];
-	}
-
-	// go through all triangles and look for sides that match
-	// this triangle's
-	for ( t = 0; t < numTris; t++ )
-	{
-		// don't check against self or against previously used triangles
-		if ( t == tri )
-			continue;
-		if ( s_used[t] )
-			continue;
-
-		// check all three sides of the candidate triangle
-		for ( side = 0; side < 3; side++ )
-		{
-			// check only the second (abutting) side
-			if ( ( refa == mesh[t][(side+1)%3] ) &&
-				 ( refb == mesh[t][side] ) )
-			{
-
-				a = mesh[t][0];
-				b = mesh[t][1];
-				c = mesh[t][2];
-
-				// rotate the candidate triangle to align it properly in the strip
-				if ( side == 1 )
-				{
-					mesh[t][0] = b;
-					mesh[t][1] = c;
-					mesh[t][2] = a;
-				}
-				else if ( side == 2 )
-				{
-					mesh[t][0] = c;
-					mesh[t][1] = a;
-					mesh[t][2] = b;
-				}
-
-				return t;
-			}
-/*
-			else
-			{
-				Error( "fans not implemented yet" );
-
-				// check only the third (abutting) side
-				if ( ( currentTri[2] == pSurf->baseTriangles[t].v[side].index ) &&
-					( currentTri[0] == pSurf->baseTriangles[t].v[(side+1)%3].index ) )
-				{
-					return t;
-				}
-			}
-*/
-		}
-	}
-
-	return -1;
-}
-
-/*
-** StripLength
-*/
-static int StripLength( int mesh[][3], int strip[][3], int tri, int orientation, int numInputTris, int fillNo )
-{
-	int stripIndex = 0;
-	int next;
-
-	int odd = 1;
-
-	strip[stripIndex][0] = mesh[tri][(0+orientation)%3];
-	strip[stripIndex][1] = mesh[tri][(1+orientation)%3];
-	strip[stripIndex][2] = mesh[tri][(2+orientation)%3];
-	s_used[tri] = fillNo;
-	stripIndex++;
-
-	next = tri;
-
-	while ( ( next = FindNextTriangleInStripOrFan( mesh, next, orientation, numInputTris, odd ) ) != -1 )
-	{
-		s_used[next] = fillNo;
-		odd = !odd;
-		strip[stripIndex][0] = mesh[next][0];
-		strip[stripIndex][1] = mesh[next][1];
-		strip[stripIndex][2] = mesh[next][2];
-		stripIndex++;
-
-		// all iterations after first need to be with an unrotated reference triangle
-		orientation = 0;
-	}
-
-	return stripIndex;
-}
-
-/*
-** BuildOptimizedList
-**
-** Attempts to build the longest strip/fan possible.  Does not adhere
-** to pure strip or fan, will intermix between the two so long as some
-** type of connectivity can be maintained.
-*/
-#define MAX_ORIENTATIONS		3
-#define MAX_MATCHED_SIDES		4
-#define MAX_SEED_TRIANGLES		16
-
-static int BuildOptimizedList( int mesh[][3], int strip[][3], int numInputTris )
-{
-	int t;
-	int stripLen = 0;
-	int startTri = -1;
-	int bestTri = -1, bestLength = 0, bestOrientation = -1;
-	int matchedSides = 0;
-	int orientation = 0;
-	int seedTriangles[MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
-	int seedLengths[MAX_ORIENTATIONS][MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
-	int numSeeds[MAX_MATCHED_SIDES] = { 0, 0, 0 };
-	int i;
-
-	// build a ranked list of candidate seed triangles based on 
-	// number of offshoot strips.  Precedence goes to orphans,
-	// then corners, then edges, and interiors.
-	memset( seedTriangles, 0xff, sizeof( seedTriangles ) );
-	memset( seedLengths, 0xff, sizeof( seedLengths ) );
-
-	for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
-	{
-		// find the triangle with lowest number of child strips
-		for ( t = 0; t < numInputTris; t++ )
-		{
-			int orientation;
-			int n;
-
-			if ( s_used[t] )
-				continue;
-
-			// try the candidate triangle in three different orientations
-			matchedSides = 0;
-			for ( orientation = 0; orientation < 3; orientation++ )
-			{
-				if ( ( n = FindNextTriangleInStripOrFan( mesh, t, orientation, numInputTris, 1 ) ) != -1 )
-				{
-					matchedSides++;
-				}
-			}
-
-			if ( matchedSides == i )
-			{
-				seedTriangles[i][numSeeds[i]] = t;
-				numSeeds[i]++;
-				if ( numSeeds[i] == MAX_SEED_TRIANGLES )
-					break;
-			}
-		}
-	}
-
-	// we have a list of potential seed triangles, so we now go through each 
-	// potential candidate and look to see which produces the longest strip
-	// and select our startTri based on this
-	for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
-	{
-		int j;
-
-		for ( j = 0; j < numSeeds[i]; j++ )
-		{
-			for ( orientation = 0; orientation < 3; orientation++ )
-			{
-				int k;
-
-				seedLengths[orientation][i][j] = StripLength( mesh, strip, seedTriangles[i][j], orientation, numInputTris, 2 );
-
-				if ( seedLengths[orientation][i][j] > bestLength )
-				{
-					bestTri = seedTriangles[i][j];
-					bestLength = seedLengths[orientation][i][j];
-					bestOrientation = orientation;
-				}
-
-				for ( k = 0; k < numInputTris; k++ )
-				{
-					if ( s_used[k] == 2 )
-						s_used[k] = 0;
-				}
-			}
-		}
-
-		if ( bestTri != -1 )
-		{
-			break;
-		}
-	}
-
-	// build the strip for real
-	if ( bestTri != -1 )
-	{
-		stripLen = StripLength( mesh, strip, bestTri, bestOrientation, numInputTris, 1 );
-	}
-
-	return stripLen;
-}
-
-/*
-** OrderMesh
-**
-** Given an input mesh and an output mesh, this routine will reorder 
-** the triangles within the mesh into strips/fans.
-*/
-void OrderMesh( int input[][3], int output[][3], int numTris )
-{
-	int i;
-	int sumStrippedTriangles = 0;
-	int strippedTriangles;
-	int totalStrips = 0;
-	int strip[8192][3];					// could dump directly into 'output', but 
-										// this helps with debugging
-
-	memset( s_used, 0, sizeof( s_used ) );
-
-#if 0
-	FILE *fp = fopen( "strip.txt", "wt" );
-
-	for ( i = 0; i < numTris; i++ )
-	{
-		fprintf( fp, "%4d: %3d %3d %3d\n", i, input[i][0], input[i][1], input[i][2] );
-	}
-	fclose( fp );
-#endif
-
-	// while there are still triangles that are not part of a strip
-	while ( sumStrippedTriangles < numTris )
-	{
-		// build a strip
-		strippedTriangles = BuildOptimizedList( input, strip, numTris );
-
-		for ( i = 0; i < strippedTriangles; i++ )
-		{
-			output[sumStrippedTriangles+i][0] = strip[i][0];
-			output[sumStrippedTriangles+i][1] = strip[i][1];
-			output[sumStrippedTriangles+i][2] = strip[i][2];
-		}
-
-		sumStrippedTriangles += strippedTriangles;
-		totalStrips++;
-	}
-
-	printf( "Triangles on surface:		%d\n", sumStrippedTriangles );
-	printf( "Total strips from surface: %d\n", totalStrips );
-	printf( "Average strip length:      %f\n", ( float ) sumStrippedTriangles / totalStrips );
-}
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+static int s_used[8192];		// same as MD3_MAX_TRIANGLES
+
+/*
+** FindNextTriangleInStrip
+**
+** Given a surface and triangle this tries to find the next triangle 
+** in the strip that would continue the strip.  The next triangle in
+** the strip should have the same winding as this triangle.
+*/
+static int FindNextTriangleInStripOrFan( int mesh[][3], int tri, int orientation, int numTris, int odd )
+{
+	int t;
+	int sum = 0;
+	int currentTri[3];
+	int side;
+	int a, b, c;
+	int refa, refb;
+
+	currentTri[0] = mesh[tri][(0+orientation)%3];
+	currentTri[1] = mesh[tri][(1+orientation)%3];
+	currentTri[2] = mesh[tri][(2+orientation)%3];
+
+	if ( odd )
+	{
+		refa = currentTri[1];
+		refb = currentTri[2];
+	}
+	else
+	{
+		refa = currentTri[2];
+		refb = currentTri[0];
+	}
+
+	// go through all triangles and look for sides that match
+	// this triangle's
+	for ( t = 0; t < numTris; t++ )
+	{
+		// don't check against self or against previously used triangles
+		if ( t == tri )
+			continue;
+		if ( s_used[t] )
+			continue;
+
+		// check all three sides of the candidate triangle
+		for ( side = 0; side < 3; side++ )
+		{
+			// check only the second (abutting) side
+			if ( ( refa == mesh[t][(side+1)%3] ) &&
+				 ( refb == mesh[t][side] ) )
+			{
+
+				a = mesh[t][0];
+				b = mesh[t][1];
+				c = mesh[t][2];
+
+				// rotate the candidate triangle to align it properly in the strip
+				if ( side == 1 )
+				{
+					mesh[t][0] = b;
+					mesh[t][1] = c;
+					mesh[t][2] = a;
+				}
+				else if ( side == 2 )
+				{
+					mesh[t][0] = c;
+					mesh[t][1] = a;
+					mesh[t][2] = b;
+				}
+
+				return t;
+			}
+/*
+			else
+			{
+				Error( "fans not implemented yet" );
+
+				// check only the third (abutting) side
+				if ( ( currentTri[2] == pSurf->baseTriangles[t].v[side].index ) &&
+					( currentTri[0] == pSurf->baseTriangles[t].v[(side+1)%3].index ) )
+				{
+					return t;
+				}
+			}
+*/
+		}
+	}
+
+	return -1;
+}
+
+/*
+** StripLength
+*/
+static int StripLength( int mesh[][3], int strip[][3], int tri, int orientation, int numInputTris, int fillNo )
+{
+	int stripIndex = 0;
+	int next;
+
+	int odd = 1;
+
+	strip[stripIndex][0] = mesh[tri][(0+orientation)%3];
+	strip[stripIndex][1] = mesh[tri][(1+orientation)%3];
+	strip[stripIndex][2] = mesh[tri][(2+orientation)%3];
+	s_used[tri] = fillNo;
+	stripIndex++;
+
+	next = tri;
+
+	while ( ( next = FindNextTriangleInStripOrFan( mesh, next, orientation, numInputTris, odd ) ) != -1 )
+	{
+		s_used[next] = fillNo;
+		odd = !odd;
+		strip[stripIndex][0] = mesh[next][0];
+		strip[stripIndex][1] = mesh[next][1];
+		strip[stripIndex][2] = mesh[next][2];
+		stripIndex++;
+
+		// all iterations after first need to be with an unrotated reference triangle
+		orientation = 0;
+	}
+
+	return stripIndex;
+}
+
+/*
+** BuildOptimizedList
+**
+** Attempts to build the longest strip/fan possible.  Does not adhere
+** to pure strip or fan, will intermix between the two so long as some
+** type of connectivity can be maintained.
+*/
+#define MAX_ORIENTATIONS		3
+#define MAX_MATCHED_SIDES		4
+#define MAX_SEED_TRIANGLES		16
+
+static int BuildOptimizedList( int mesh[][3], int strip[][3], int numInputTris )
+{
+	int t;
+	int stripLen = 0;
+	int startTri = -1;
+	int bestTri = -1, bestLength = 0, bestOrientation = -1;
+	int matchedSides = 0;
+	int orientation = 0;
+	int seedTriangles[MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
+	int seedLengths[MAX_ORIENTATIONS][MAX_MATCHED_SIDES][MAX_SEED_TRIANGLES];
+	int numSeeds[MAX_MATCHED_SIDES] = { 0, 0, 0 };
+	int i;
+
+	// build a ranked list of candidate seed triangles based on 
+	// number of offshoot strips.  Precedence goes to orphans,
+	// then corners, then edges, and interiors.
+	memset( seedTriangles, 0xff, sizeof( seedTriangles ) );
+	memset( seedLengths, 0xff, sizeof( seedLengths ) );
+
+	for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
+	{
+		// find the triangle with lowest number of child strips
+		for ( t = 0; t < numInputTris; t++ )
+		{
+			int orientation;
+			int n;
+
+			if ( s_used[t] )
+				continue;
+
+			// try the candidate triangle in three different orientations
+			matchedSides = 0;
+			for ( orientation = 0; orientation < 3; orientation++ )
+			{
+				if ( ( n = FindNextTriangleInStripOrFan( mesh, t, orientation, numInputTris, 1 ) ) != -1 )
+				{
+					matchedSides++;
+				}
+			}
+
+			if ( matchedSides == i )
+			{
+				seedTriangles[i][numSeeds[i]] = t;
+				numSeeds[i]++;
+				if ( numSeeds[i] == MAX_SEED_TRIANGLES )
+					break;
+			}
+		}
+	}
+
+	// we have a list of potential seed triangles, so we now go through each 
+	// potential candidate and look to see which produces the longest strip
+	// and select our startTri based on this
+	for ( i = 0; i < MAX_MATCHED_SIDES; i++ )
+	{
+		int j;
+
+		for ( j = 0; j < numSeeds[i]; j++ )
+		{
+			for ( orientation = 0; orientation < 3; orientation++ )
+			{
+				int k;
+
+				seedLengths[orientation][i][j] = StripLength( mesh, strip, seedTriangles[i][j], orientation, numInputTris, 2 );
+
+				if ( seedLengths[orientation][i][j] > bestLength )
+				{
+					bestTri = seedTriangles[i][j];
+					bestLength = seedLengths[orientation][i][j];
+					bestOrientation = orientation;
+				}
+
+				for ( k = 0; k < numInputTris; k++ )
+				{
+					if ( s_used[k] == 2 )
+						s_used[k] = 0;
+				}
+			}
+		}
+
+		if ( bestTri != -1 )
+		{
+			break;
+		}
+	}
+
+	// build the strip for real
+	if ( bestTri != -1 )
+	{
+		stripLen = StripLength( mesh, strip, bestTri, bestOrientation, numInputTris, 1 );
+	}
+
+	return stripLen;
+}
+
+/*
+** OrderMesh
+**
+** Given an input mesh and an output mesh, this routine will reorder 
+** the triangles within the mesh into strips/fans.
+*/
+void OrderMesh( int input[][3], int output[][3], int numTris )
+{
+	int i;
+	int sumStrippedTriangles = 0;
+	int strippedTriangles;
+	int totalStrips = 0;
+	int strip[8192][3];					// could dump directly into 'output', but 
+										// this helps with debugging
+
+	memset( s_used, 0, sizeof( s_used ) );
+
+#if 0
+	FILE *fp = fopen( "strip.txt", "wt" );
+
+	for ( i = 0; i < numTris; i++ )
+	{
+		fprintf( fp, "%4d: %3d %3d %3d\n", i, input[i][0], input[i][1], input[i][2] );
+	}
+	fclose( fp );
+#endif
+
+	// while there are still triangles that are not part of a strip
+	while ( sumStrippedTriangles < numTris )
+	{
+		// build a strip
+		strippedTriangles = BuildOptimizedList( input, strip, numTris );
+
+		for ( i = 0; i < strippedTriangles; i++ )
+		{
+			output[sumStrippedTriangles+i][0] = strip[i][0];
+			output[sumStrippedTriangles+i][1] = strip[i][1];
+			output[sumStrippedTriangles+i][2] = strip[i][2];
+		}
+
+		sumStrippedTriangles += strippedTriangles;
+		totalStrips++;
+	}
+
+	printf( "Triangles on surface:		%d\n", sumStrippedTriangles );
+	printf( "Total strips from surface: %d\n", totalStrips );
+	printf( "Average strip length:      %f\n", ( float ) sumStrippedTriangles / totalStrips );
+}
diff --git a/tools/quake3/q3data/video.c b/tools/quake3/q3data/video.c
index 35e097bf..9054d5e9 100644
--- a/tools/quake3/q3data/video.c
+++ b/tools/quake3/q3data/video.c
@@ -1,1132 +1,1132 @@
-#include <assert.h>
-#include "q3data.h"
-
-static int s_resample_width = 256;
-static int s_resample_height = 256;
-
-#define OUTPUT_TGAS			1
-
-#define UNCOMPRESSED		0
-#define BTC_COMPRESSION		1
-
-static int s_compression_method = BTC_COMPRESSION;
-
-static const char *CIN_EXTENSION = "cn2";
-static const int CIN_SIGNATURE = ( 'C' << 24 ) | ( 'I' << 16 ) | ( 'N' << 8 ) | ( '2' );
-
-static byte	*s_soundtrack;
-static char	s_base[32];
-static char	s_output_base[32];
-
-/*
-===============================================================================
-
-WAV loading
-
-===============================================================================
-*/
-
-typedef struct
-{
-	int			rate;
-	int			width;
-	int			channels;
-	int			loopstart;
-	int			samples;
-	int			dataofs;		// chunk starts this many bytes from file start
-} wavinfo_t;
-
-
-byte	*data_p;
-byte 	*iff_end;
-byte 	*last_chunk;
-byte 	*iff_data;
-int 	iff_chunk_len;
-
-
-static int			s_samplecounts[0x10000];
-static wavinfo_t	s_wavinfo;
-
-short GetLittleShort(void)
-{
-	short val = 0;
-	val = *data_p;
-	val = val + (*(data_p+1)<<8);
-	data_p += 2;
-	return val;
-}
-
-int GetLittleLong(void)
-{
-	int val = 0;
-	val = *data_p;
-	val = val + (*(data_p+1)<<8);
-	val = val + (*(data_p+2)<<16);
-	val = val + (*(data_p+3)<<24);
-	data_p += 4;
-	return val;
-}
-
-void FindNextChunk(char *name)
-{
-	while (1)
-	{
-		data_p=last_chunk;
-
-		if (data_p >= iff_end)
-		{	// didn't find the chunk
-			data_p = NULL;
-			return;
-		}
-		
-		data_p += 4;
-		iff_chunk_len = GetLittleLong();
-		if (iff_chunk_len < 0)
-		{
-			data_p = NULL;
-			return;
-		}
-//		if (iff_chunk_len > 1024*1024)
-//			Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
-		data_p -= 8;
-		last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
-		if (!strncmp(data_p, name, 4))
-			return;
-	}
-}
-
-void FindChunk(char *name)
-{
-	last_chunk = iff_data;
-	FindNextChunk (name);
-}
-
-
-void DumpChunks(void)
-{
-	char	str[5];
-	
-	str[4] = 0;
-	data_p=iff_data;
-	do
-	{
-		memcpy (str, data_p, 4);
-		data_p += 4;
-		iff_chunk_len = GetLittleLong();
-		printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
-		data_p += (iff_chunk_len + 1) & ~1;
-	} while (data_p < iff_end);
-}
-
-/*
-============
-GetWavinfo
-============
-*/
-wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
-{
-	wavinfo_t	info;
-	int     i;
-	int     format;
-	int		samples;
-
-	memset (&info, 0, sizeof(info));
-
-	if (!wav)
-		return info;
-		
-	iff_data = wav;
-	iff_end = wav + wavlength;
-
-// find "RIFF" chunk
-	FindChunk("RIFF");
-	if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
-	{
-		printf("Missing RIFF/WAVE chunks\n");
-		return info;
-	}
-
-// get "fmt " chunk
-	iff_data = data_p + 12;
-// DumpChunks ();
-
-	FindChunk("fmt ");
-	if (!data_p)
-	{
-		printf("Missing fmt chunk\n");
-		return info;
-	}
-	data_p += 8;
-	format = GetLittleShort();
-	if (format != 1)
-	{
-		printf("Microsoft PCM format only\n");
-		return info;
-	}
-
-	info.channels = GetLittleShort();
-	info.rate = GetLittleLong();
-	data_p += 4+2;
-	info.width = GetLittleShort() / 8;
-
-// get cue chunk
-	FindChunk("cue ");
-	if (data_p)
-	{
-		data_p += 32;
-		info.loopstart = GetLittleLong();
-//		Com_Printf("loopstart=%d\n", sfx->loopstart);
-
-	// if the next chunk is a LIST chunk, look for a cue length marker
-		FindNextChunk ("LIST");
-		if (data_p)
-		{
-			if (!strncmp (data_p + 28, "mark", 4))
-			{	// this is not a proper parse, but it works with cooledit...
-				data_p += 24;
-				i = GetLittleLong ();	// samples in loop
-				info.samples = info.loopstart + i;
-			}
-		}
-	}
-	else
-		info.loopstart = -1;
-
-// find data chunk
-	FindChunk("data");
-	if (!data_p)
-	{
-		printf("Missing data chunk\n");
-		return info;
-	}
-
-	data_p += 4;
-	samples = GetLittleLong ();
-
-	if (info.samples)
-	{
-		if (samples < info.samples)
-			Error ("Sound %s has a bad loop length", name);
-	}
-	else
-		info.samples = samples;
-
-	info.dataofs = data_p - wav;
-
-	return info;
-}
-
-//=====================================================================
-
-/*
-==============
-LoadSoundtrack
-==============
-*/
-void LoadSoundtrack (void)
-{
-	char	name[1024];
-	FILE	*f;
-	int		len;
-	int     i, val, j;
-
-	s_soundtrack = NULL;
-	sprintf (name, "%svideo/%s/%s.wav", gamedir, s_base, s_base);
-	printf ("WAV: %s\n", name);
-	f = fopen (name, "rb");
-	if (!f)
-	{
-		printf ("no soundtrack for %s\n", s_base);
-		return;
-	}
-	len = Q_filelength(f);
-	s_soundtrack = malloc(len);
-	fread (s_soundtrack, 1, len, f);
-	fclose (f);
-
-	s_wavinfo = GetWavinfo (name, s_soundtrack, len);
-
-	// count samples for compression
-	memset (s_samplecounts, 0, sizeof(s_samplecounts));
-
-	j = s_wavinfo.samples/2;
-	for (i=0 ; i<j ; i++)
-	{
-		val = ((unsigned short *)( s_soundtrack + s_wavinfo.dataofs))[i];
-		s_samplecounts[val]++;
-	}
-	val = 0;
-	for (i=0 ; i<0x10000 ; i++)
-		if (s_samplecounts[i])
-			val++;
-
-	printf ("%i unique sample values\n", val);
-}
-
-/*
-==================
-WriteSound
-==================
-*/
-void WriteSound (FILE *output, int frame)
-{
-	int		start, end;
-	int		count;
-	int		empty = 0;
-	int		i;
-	int		sample;
-	int		width;
-
-	width = s_wavinfo.width * s_wavinfo.channels;
-
-	start = frame*s_wavinfo.rate/14;
-	end = (frame+1)*s_wavinfo.rate/14;
-	count = end - start;
-
-	for (i=0 ; i<count ; i++)
-	{
-		sample = start+i;
-		if (sample > s_wavinfo.samples || !s_soundtrack)
-			fwrite (&empty, 1, width, output);
-		else
-			fwrite (s_soundtrack + s_wavinfo.dataofs + sample*width, 1, width,output);
-	}
-}
-
-//==========================================================================
-
-static float s_resampleXRatio;
-static float s_resampleYRatio;
-
-static void BoxFilterHorizontalElements( unsigned char *dst, unsigned char *src, float s0, float s1 )
-{
-	float w;
-	float rSum = 0, gSum = 0, bSum = 0;
-	float x = s0;
-	float sumWeight = 0;
-
-	for ( x = s0; x < s1; x++, src += 4 )
-	{
-		if ( x == s0 )
-		{
-			w = ( int ) ( s0 + 1 ) - x;
-		}
-		else if ( x + 1 >= s1 )
-		{
-			w = s1 - ( int ) x;
-		}
-		else
-		{
-			w = 1.0f;
-		}
-
-		rSum += src[0] * w;
-		gSum += src[1] * w;
-		bSum += src[2] * w;
-		sumWeight += w;
-	}
-
-	rSum /= sumWeight;
-	gSum /= sumWeight;
-	bSum /= sumWeight;
-
-	dst[0] = ( unsigned char ) ( rSum + 0.5 );
-	dst[1] = ( unsigned char ) ( gSum + 0.5 );
-	dst[2] = ( unsigned char ) ( bSum + 0.5 );
-}
-
-static void BoxFilterVerticalElements( unsigned char *dst, // destination of the filter process
-									   unsigned char *src, // source pixels
-									   int srcStep,		   // stride of the source pixels
-									   float s0, float s1 )
-{
-	float w;
-	float rSum = 0, gSum = 0, bSum = 0;
-	float y = s0;
-	float sumWeight = 0;
-
-	for ( y = s0; y < ( int ) ( s1 + 1 ) ; y++, src += srcStep )
-	{
-		if ( y == s0 )
-		{
-			w = ( int ) ( s0 + 1 ) - y;
-		}
-		else if ( y + 1 >= s1 )
-		{
-			w = s1 - ( int ) y;
-		}
-		else
-		{
-			w = 1.0f;
-		}
-
-		rSum += src[0] * w;
-		gSum += src[1] * w;
-		bSum += src[2] * w;
-		sumWeight += w;
-	}
-
-	rSum /= sumWeight;
-	gSum /= sumWeight;
-	bSum /= sumWeight;
-
-	dst[0] = ( unsigned char ) ( rSum + 0.5 );
-	dst[1] = ( unsigned char ) ( gSum + 0.5 );
-	dst[2] = ( unsigned char ) ( bSum + 0.5 );
-	dst[3] = 0xff;
-
-}
-
-static void BoxFilterRow( unsigned char *dstStart, cblock_t *in, int dstRow, int rowWidth )
-{
-	int i;
-	unsigned char *indata = ( unsigned char * ) in->data;
-
-	indata += 4 * dstRow * in->width;
-
-	for ( i = 0; i < rowWidth; i++ )
-	{
-		float c0 = i * s_resampleXRatio;
-		float c1 = ( i + 1 ) * s_resampleXRatio;
-
-		BoxFilterHorizontalElements( &dstStart[i*4], &indata[( ( int ) c0 ) * 4], c0, c1 );
-	}
-}
-
-static void BoxFilterColumn( unsigned char *dstStart, unsigned char *srcStart, int dstCol, int dstRowWidth, int dstColHeight, int srcRowWidthInPels )
-{
-	float c0, c1;
-	int i;
-
-	for ( i = 0; i < dstColHeight; i++ )
-	{
-		c0 = i * s_resampleYRatio;
-		c1 = ( i + 1 ) * s_resampleYRatio;
-
-		BoxFilterVerticalElements( &dstStart[i*4*dstRowWidth], &srcStart[(int)c0*srcRowWidthInPels*4], srcRowWidthInPels*4, c0, c1 );
-	}
-}
-
-#define DROP_SAMPLE		0
-#define BOX_FILTER		1
-
-static void ResampleFrame( cblock_t *in, unsigned char *out, int method, int outWidth, int outHeight )
-{
-	int row, column;
-	unsigned char *indata = ( unsigned char * ) in->data;
-
-	s_resampleXRatio = in->width / ( float ) outWidth;
-	s_resampleYRatio = in->height / ( float ) outHeight;
-
-	if ( method == DROP_SAMPLE )
-	{
-		for ( row = 0; row < outHeight; row++ )
-		{
-			int r = ( int ) ( row * s_resampleYRatio );
-
-			for ( column = 0; column < outWidth; column++ )
-			{
-				int c = ( int ) ( column * s_resampleXRatio );
-
-				out[(row*outWidth+column)*4+0] = indata[(r*in->width+c)*4+0];
-				out[(row*outWidth+column)*4+1] = indata[(r*in->width+c)*4+1];
-				out[(row*outWidth+column)*4+2] = indata[(r*in->width+c)*4+2];
-				out[(row*outWidth+column)*4+3] = 0xff;
-			}
-		}
-	}
-	else if ( method == BOX_FILTER )
-	{
-		unsigned char intermediate[1024*1024*4];
-
-		assert( in->height <= 1024 );
-		assert( in->width <= 1024 );
-
-		//
-		// filter our M x N source image into a RESAMPLE_WIDTH x N horizontally filtered image
-		//
-		for ( row = 0; row < in->height; row++ )
-		{
-			BoxFilterRow( &intermediate[row*4*outWidth], in, row, outWidth );
-		}
-
-		//
-		// filter our RESAMPLE_WIDTH x N horizontally filtered image into a RESAMPLE_WIDTH x RESAMPLE_HEIGHT filtered image
-		//
-		for ( column = 0; column < outWidth; column++ )
-		{
-			BoxFilterColumn( &out[column*4], &intermediate[column*4], column, outWidth, outHeight, s_resample_width );
-		}
-	}
-}
-
-static float BTCDistanceSquared( float a[3], float b[3] )
-{
-	return ( b[0] - a[0] ) * ( b[0] - a[0] ) + 
-		   ( b[1] - a[1] ) * ( b[1] - a[1] ) +
-		   ( b[2] - a[2] ) * ( b[2] - a[2] );
-}
-
-static void BTCFindEndpoints( float inBlock[4][4][3], unsigned int endPoints[2][2] )
-{
-	float longestDistance = -1;
-
-	int bX, bY;
-
-	//
-	// find the two points farthest from each other
-	//
-	for ( bY = 0; bY < 4; bY++ )
-	{
-		for ( bX = 0; bX < 4; bX++ )
-		{
-			int cX, cY;
-			float d;
-
-			//
-			// check the rest of the current row
-			//
-			for ( cX = bX + 1; cX < 4; cX++ )
-			{
-				if ( ( d = BTCDistanceSquared( inBlock[bY][bX], inBlock[bY][cX] ) ) > longestDistance )
-				{
-					longestDistance = d;
-					endPoints[0][0] = bX;
-					endPoints[0][1] = bY;
-					endPoints[1][0] = cX;
-					endPoints[1][1] = bY;
-				}
-			}
-
-			//
-			// check remaining rows and columns
-			//
-			for ( cY = bY+1; cY < 4; cY++ )
-			{
-				for ( cX = 0; cX < 4; cX++ )
-				{
-					if ( ( d = BTCDistanceSquared( inBlock[bY][bX], inBlock[cY][cX] ) ) > longestDistance )
-					{
-						longestDistance = d;
-						endPoints[0][0] = bX;
-						endPoints[0][1] = bY;
-						endPoints[1][0] = cX;
-						endPoints[1][1] = cY;
-					}
-				}
-			}
-		}
-	}
-}
-
-static float BTCQuantizeBlock( float inBlock[4][4][3], unsigned long endPoints[2][2], int btcQuantizedBlock[4][4], float bestError )
-{
-	int i;
-	int blockY, blockX;
-	float dR, dG, dB;
-	float R, G, B;
-	float error = 0;
-	float colorLine[4][3];
-
-	//
-	// build the color line
-	//
-	dR = inBlock[endPoints[1][1]][endPoints[1][0]][0] -
-		 inBlock[endPoints[0][1]][endPoints[0][0]][0];
-	dG = inBlock[endPoints[1][1]][endPoints[1][0]][1] -
-		 inBlock[endPoints[0][1]][endPoints[0][0]][1];
-	dB = inBlock[endPoints[1][1]][endPoints[1][0]][2] -
-		 inBlock[endPoints[0][1]][endPoints[0][0]][2];
-
-	dR *= 0.33f;
-	dG *= 0.33f;
-	dB *= 0.33f;
-
-	R = inBlock[endPoints[0][1]][endPoints[0][0]][0];
-	G = inBlock[endPoints[0][1]][endPoints[0][0]][1];
-	B = inBlock[endPoints[0][1]][endPoints[0][0]][2];
-
-	for ( i = 0; i < 4; i++ )
-	{
-		colorLine[i][0] = R;
-		colorLine[i][1] = G;
-		colorLine[i][2] = B;
-
-		R += dR;
-		G += dG;
-		B += dB;
-	}
-
-	//
-	// quantize each pixel into the appropriate range
-	//
-	for ( blockY = 0; blockY < 4; blockY++ )
-	{
-		for ( blockX = 0; blockX < 4; blockX++ )
-		{
-			float distance = 10000000000;
-			int shortest = -1;
-
-			for ( i = 0; i < 4; i++ )
-			{
-				float d;
-
-				if ( ( d = BTCDistanceSquared( inBlock[blockY][blockX], colorLine[i] ) ) < distance )
-				{
-					distance = d;
-					shortest = i;
-				}
-			}
-
-			error += distance;
-
-			//
-			// if bestError is not -1 then that means this is a speculative quantization
-			//
-			if ( bestError != -1 )
-			{
-				if ( error > bestError )
-					return error;
-			}
-
-			btcQuantizedBlock[blockY][blockX] = shortest;
-		}
-	}
-
-	return error;
-}
-
-/*
-** float BTCCompressBlock
-*/
-static float BTCCompressBlock( float inBlock[4][4][3], unsigned long out[2] )
-{
-	int i;
-	int btcQuantizedBlock[4][4];	// values should be [0..3]
-	unsigned long encodedEndPoints, encodedBitmap;
-	unsigned int endPoints[2][2];		// endPoints[0] = color start, endPoints[1] = color end
-	int blockY, blockX;
-	float error = 0;
-	float bestError = 10000000000;
-	unsigned int bestEndPoints[2][2];
-
-#if 0
-	//
-	// find the "ideal" end points for the color vector 
-	//
-	BTCFindEndpoints( inBlock, endPoints );
-	error = BTCQuantizeBlock( inBlock, endPoints, btcQuantizedBlock );
-	memcpy( bestEndPoints, endPoints, sizeof( bestEndPoints ) );
-#else
-	for ( blockY = 0; blockY < 4; blockY++ )
-	{
-		for ( blockX = 0; blockX < 4; blockX++ )
-		{
-			int x2, y2;
-
-			for ( y2 = 0; y2 < 4; y2++ )
-			{
-				for ( x2 = 0; x2 < 4; x2++ )
-				{
-					if ( ( x2 == blockX ) && ( y2 == blockY ) )
-						continue;
-
-					endPoints[0][0] = blockX;
-					endPoints[0][1] = blockY;
-					endPoints[1][0] = x2;
-					endPoints[1][1] = y2;
-
-					error = BTCQuantizeBlock( inBlock, endPoints, btcQuantizedBlock, -1 ); //bestError );
-
-					if ( error < bestError )
-					{
-						bestError = error;
-						memcpy( bestEndPoints, endPoints, sizeof( bestEndPoints ) );
-					}
-				}
-			}
-		}
-	}
-
-	error = BTCQuantizeBlock( inBlock, bestEndPoints, btcQuantizedBlock, -1.0f );
-#endif
-
-	//
-	// encode the results
-	//
-	encodedBitmap = 0;
-	for ( blockY = 0; blockY < 4; blockY++ )
-	{
-		for ( blockX = 0; blockX < 4; blockX++ )
-		{
-			int shift = ( blockX + blockY * 4 ) * 2;
-			encodedBitmap |= btcQuantizedBlock[blockY][blockX] << shift;
-		}
-	}
-
-	//
-	// encode endpoints
-	//
-	encodedEndPoints = 0;
-	for ( i = 0; i < 2; i++ )
-	{
-		int iR, iG, iB;
-
-		iR = ( ( int ) inBlock[bestEndPoints[i][1]][bestEndPoints[i][0]][0] );
-		if ( iR > 255 ) 
-			iR = 255;
-		else if ( iR < 0 ) 
-			iR = 0;
-		iR >>= 3;
-
-		iG = ( ( int ) inBlock[bestEndPoints[i][1]][bestEndPoints[i][0]][1] );
-		if ( iG > 255 )
-			iG = 255;
-		else if ( iG < 0 )
-			iG = 0;
-		iG >>= 2;
-
-		iB = ( ( int ) inBlock[bestEndPoints[i][1]][bestEndPoints[i][0]][2] );
-		if ( iB > 255 )
-			iB = 255;
-		else if ( iB < 0 )
-			iB = 0;
-		iB >>= 3;
-
-
-		encodedEndPoints |= ( ( ( iR << 11 ) | ( iG << 5 ) | ( iB ) ) << ( i * 16 ) );
-	}
-
-	//
-	// store 
-	//
-	out[0] = encodedBitmap;
-	out[1] = encodedEndPoints;
-
-	return error;
-}
-
-/*
-** void BTCDecompressFrame
-*/
-static void BTCDecompressFrame( unsigned long *src, unsigned char *dst )
-{
-	int x, y;
-	int iR, iG, iB;
-	int dstX, dstY;
-	float colorStart[3], colorEnd[3];
-	unsigned char colorRampABGR[4][4];
-	unsigned encoded;
-
-	memset( colorRampABGR, 0xff, sizeof( colorRampABGR ) );
-
-	for ( y = 0; y < s_resample_height / 4; y++ )
-	{
-		for ( x = 0; x < s_resample_width / 4; x++ )
-		{
-			unsigned colorStartPacked = src[(y*s_resample_width/4 + x)*2 + 1] & 0xffff;
-			unsigned colorEndPacked = src[(y*s_resample_width/4 + x)*2 + 1] >> 16;
-
-			//
-			// grab the end points
-			//   0 = color start
-			//   1 = color end
-			//
-			iR = ( ( colorStartPacked >> 11 ) & ( ( 1 << 5 ) - 1 ) );
-			iR = ( iR << 3 ) | ( iR >> 2 );
-			iG = ( ( colorStartPacked >> 5 ) & ( ( 1 << 6 )  - 1 ) );
-			iG = ( iG << 2 ) | ( iG >> 4 );
-			iB = ( ( colorStartPacked ) & ( ( 1 << 5  ) - 1 ) );
-			iB = ( iB << 3 ) | ( iB >> 2 );
-
-			colorStart[0] = iR;
-			colorStart[1] = iG;
-			colorStart[2] = iB;
-			colorRampABGR[0][0] = iR;
-			colorRampABGR[0][1] = iG;
-			colorRampABGR[0][2] = iB;
-
-			iR = ( ( colorEndPacked >> 11 ) & ( ( 1 << 5 ) - 1 ) );
-			iR = ( iR << 3 ) | ( iR >> 2 );
-			iG = ( ( colorEndPacked >> 5 ) & ( ( 1 << 6 )  - 1 ) );
-			iG = ( iG << 2 ) | ( iG >> 4 );
-			iB = ( colorEndPacked & ( ( 1 << 5  ) - 1 ) );
-			iB = ( iB << 3 ) | ( iB >> 2 );
-
-			colorEnd[0] = iR;
-			colorEnd[1] = iG;
-			colorEnd[2] = iB;
-			colorRampABGR[3][0] = iR;
-			colorRampABGR[3][1] = iG;
-			colorRampABGR[3][2] = iB;
-			
-			//
-			// compute this block's color ramp
-			// FIXME: This needs to be reversed on big-endian machines
-			//
-			
-			colorRampABGR[1][0] = colorStart[0] * 0.66f + colorEnd[0] * 0.33f;
-			colorRampABGR[1][1] = colorStart[1] * 0.66f + colorEnd[1] * 0.33f;
-			colorRampABGR[1][2] = colorStart[2] * 0.66f + colorEnd[2] * 0.33f;
-
-			colorRampABGR[2][0] = colorStart[0] * 0.33f + colorEnd[0] * 0.66f;
-			colorRampABGR[2][1] = colorStart[1] * 0.33f + colorEnd[1] * 0.66f;
-			colorRampABGR[2][2] = colorStart[2] * 0.33f + colorEnd[2] * 0.66f;
-
-			//
-			// decode the color data
-			// information is encoded in 2-bit pixels, with low order bits corresponding
-			// to upper left pixels.  These 2-bit values are indexed into the block's
-			// computer color ramp.
-			//
-			encoded = src[(y*s_resample_width/4 + x)*2 + 0];
-
-			for ( dstY = 0; dstY < 4; dstY++ )
-			{
-				for ( dstX = 0; dstX < 4; dstX++ )
-				{
-					memcpy( &dst[(y*4+dstY)*s_resample_width*4+x*4*4+dstX*4], colorRampABGR[encoded&3], sizeof( colorRampABGR[0] ) );
-					encoded >>= 2;
-				}
-			}
-		}
-	}
-}
-
-/*
-** BTCCompressFrame
-**
-** Perform a BTC compression using a 2-bit encoding at each pixel.  This
-** compression method is performed by decomposing the incoming image into
-** a sequence of 4x4 blocks.  At each block two color values are computed
-** that define the endpoints of a vector in color space that represent
-** the two colors "farthest apart".
-*/
-static float BTCCompressFrame( unsigned char *src, unsigned long *dst )
-{
-	int x, y;
-	int bX, bY;
-	float btcBlock[4][4][3];
-
-	float error = 0;
-	
-	for ( y = 0; y < s_resample_height / 4; y++ )
-	{
-		for ( x = 0; x < s_resample_width / 4; x++ )
-		{
-			//
-			// fill in the BTC block with raw values
-			//
-			for ( bY = 0; bY < 4; bY++ )
-			{
-				for ( bX = 0; bX < 4; bX++ )
-				{
-					btcBlock[bY][bX][0] = src[(y*4+bY)*s_resample_width*4 + (x*4+bX)*4 + 0];
-					btcBlock[bY][bX][1] = src[(y*4+bY)*s_resample_width*4 + (x*4+bX)*4 + 1];
-					btcBlock[bY][bX][2] = src[(y*4+bY)*s_resample_width*4 + (x*4+bX)*4 + 2];
-				}
-			}
-
-			error += BTCCompressBlock( btcBlock, &dst[(y*s_resample_width/4+x)*2] );
-		}
-	}
-
-	return error / ( ( s_resample_width / 4 ) * ( s_resample_height / 4 ) );
-}
-
-/*
-===================
-LoadFrame
-===================
-*/
-cblock_t LoadFrame (char *base, int frame, int digits, byte **palette)
-{
-	int			ten3, ten2, ten1, ten0;
-	cblock_t	in;
-	int			width, height;
-	char		name[1024];
-	FILE		*f;
-
-	in.data = NULL;
-	in.count = -1;
-
-	ten3 = frame/1000;
-	ten2 = (frame-ten3*1000)/100;
-	ten1 = (frame-ten3*1000-ten2*100)/10;
-	ten0 = frame%10;
-
-	if (digits == 4)
-		sprintf (name, "%svideo/%s/%s%i%i%i%i.tga", gamedir, base, base, ten3, ten2, ten1, ten0);
-	else
-		sprintf (name, "%svideo/%s/%s%i%i%i.tga", gamedir, base, base, ten2, ten1, ten0);
-
-	f = fopen(name, "rb");
-	if (!f)
-	{
-		in.data = NULL;
-		return in;
-	}
-	fclose (f);
-
-	printf ("%s", name);
-	LoadTGA( name, ( unsigned char ** ) &in.data, &width, &height );
-	if ( palette )
-		*palette = 0;
-//	Load256Image (name, &in.data, palette, &width, &height);
-	in.count = width*height;
-	in.width = width;
-	in.height = height;
-// FIXME: map 0 and 255!
-
-#if 0
-	// rle compress
-	rle = RLE(in);
-	free (in.data);
-
-	return rle;
-#endif
-
-	return in;
-}
-
-/*
-===============
-Cmd_Video
-
-video <directory> <framedigits>
-===============
-*/
-void Cmd_Video (void)
-{
-	float sumError = 0, error = 0, maxError = 0;
-	char	savename[1024];
-	char	name[1024];
-	FILE	*output;
-	int		startframe, frame;
-	int		width, height;
-	int		i;
-	int		digits;
-	int		minutes;
-	float	fseconds;
-	int		remSeconds;
-	cblock_t	in;
-	unsigned char *resampled;
-	unsigned long *compressed;
-	clock_t start, stop;
-
-	GetToken (qfalse);
-	strcpy (s_base, token);
-	if (g_release)
-	{
-//		sprintf (savename, "video/%s.cin", token);
-//		ReleaseFile (savename);
-		return;
-	}
-
-	GetToken( qfalse );
-	strcpy( s_output_base, token );
-
-	GetToken (qfalse);
-	digits = atoi(token);
-
-	GetToken( qfalse );
-
-	if ( !strcmp( token, "btc" ) )
-	{
-		s_compression_method = BTC_COMPRESSION;
-		printf( "Compression: BTC\n" );
-	}
-	else if ( !strcmp( token, "uc" ) )
-	{
-		s_compression_method = UNCOMPRESSED;
-		printf( "Compression: none\n" );
-	}
-	else
-	{
-		Error( "Uknown compression method '%s'\n", token );
-	}
-
-	GetToken( qfalse );
-	s_resample_width = atoi( token );
-
-	GetToken( qfalse );
-	s_resample_height = atoi( token );
-
-	resampled = malloc( sizeof( unsigned char ) * 4 * s_resample_width * s_resample_height );
-	compressed = malloc( sizeof( long ) * 2 * ( s_resample_width / 4 ) * ( s_resample_height / 4 ) );
-
-	printf( "Resample width: %d\n", s_resample_width );
-	printf( "Resample height: %d\n", s_resample_height );
-
-	// optionally skip frames
-	if (TokenAvailable ())
-	{
-		GetToken (qfalse);
-		startframe = atoi(token);
-	}
-	else
-		startframe=0;
-
-	sprintf (savename, "%svideo/%s.%s", writedir, s_output_base, CIN_EXTENSION );
-
-	// load the entire sound wav file if present
-	LoadSoundtrack ();
-
-	if (digits == 4)
-		sprintf (name, "%svideo/%s/%s0000.tga", gamedir, s_base, s_base);
-	else
-		sprintf (name, "%svideo/%s/%s000.tga", gamedir, s_base, s_base);
-
-	printf ("%s\n", name);
-	LoadTGA( name, NULL, &width, &height);
-
-	output = fopen (savename, "wb");
-	if (!output)
-		Error ("Can't open %s", savename);
-
-	// write header info
-	i = LittleLong( CIN_SIGNATURE );
-	fwrite (&i, 4, 1, output );
-	i = LittleLong (s_resample_width);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (s_resample_height);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (s_wavinfo.rate);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (s_wavinfo.width);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong (s_wavinfo.channels);
-	fwrite (&i, 4, 1, output);
-	i = LittleLong ( s_compression_method );
-	fwrite (&i, 4, 1, output );
-
-	start = clock();
-
-	// perform compression on a per frame basis
-	for ( frame=startframe ;  ; frame++)
-	{
-		printf ("%02d: ", frame);
-		in = LoadFrame (s_base, frame, digits, 0 );
-		if (!in.data)
-			break;
-
-		ResampleFrame( &in, ( unsigned char * ) resampled, BOX_FILTER, s_resample_width, s_resample_height );
-
-		if ( s_compression_method == UNCOMPRESSED )
-		{
-			printf( "\n" );
-			fwrite( resampled, 1, sizeof( unsigned char ) * s_resample_width * s_resample_height * 4, output );
-
-#if OUTPUT_TGAS
-			{
-				int x, y;
-				char buffer[1000];
-
-				for ( y = 0; y < s_resample_height/2; y++ )
-				{
-					for ( x = 0; x < s_resample_width; x++ )
-					{
-						unsigned char tmp[4];
-
-						tmp[0] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0];
-						tmp[1] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1];
-						tmp[2] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2];
-						tmp[3] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3];
-
-						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0] = resampled[y*s_resample_width*4 + x*4 + 0];
-						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1] = resampled[y*s_resample_width*4 + x*4 + 1];
-						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2] = resampled[y*s_resample_width*4 + x*4 + 2];
-						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3] = resampled[y*s_resample_width*4 + x*4 + 3];
-
-						resampled[y*s_resample_width*4 + x*4 + 0] = tmp[0];
-						resampled[y*s_resample_width*4 + x*4 + 1] = tmp[1];
-						resampled[y*s_resample_width*4 + x*4 + 2] = tmp[2];
-						resampled[y*s_resample_width*4 + x*4 + 3] = tmp[3];
-					}
-				}
-
-				sprintf( buffer, "%svideo/%s/uc%04d.tga", gamedir, s_base, frame );
-				WriteTGA( buffer, resampled, s_resample_width, s_resample_height );
-			}
-#endif
-		}
-		else if ( s_compression_method == BTC_COMPRESSION )
-		{
-			error = BTCCompressFrame( resampled, compressed );
-
-			sumError += error;
-
-			if ( error > maxError ) 
-				maxError = error;
-
-			printf( " (error = %f)\n", error );
-			fwrite( compressed, 1, 2 * sizeof( long ) * ( s_resample_width / 4 ) * ( s_resample_height / 4 ), output );
-
-#if OUTPUT_TGAS
-			{
-				int x, y;
-				unsigned char *uncompressed;
-				char buffer[1000];
-
-				uncompressed = malloc( sizeof( unsigned char ) * 4 * s_resample_width * s_resample_height );
-				BTCDecompressFrame( compressed, uncompressed );
-
-				for ( y = 0; y < s_resample_height/2; y++ )
-				{
-					for ( x = 0; x < s_resample_width; x++ )
-					{
-						unsigned char tmp[4];
-
-						tmp[0] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0];
-						tmp[1] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1];
-						tmp[2] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2];
-						tmp[3] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3];
-
-						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0] = uncompressed[y*s_resample_width*4 + x*4 + 0];
-						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1] = uncompressed[y*s_resample_width*4 + x*4 + 1];
-						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2] = uncompressed[y*s_resample_width*4 + x*4 + 2];
-						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3] = uncompressed[y*s_resample_width*4 + x*4 + 3];
-
-						uncompressed[y*s_resample_width*4 + x*4 + 0] = tmp[0];
-						uncompressed[y*s_resample_width*4 + x*4 + 1] = tmp[1];
-						uncompressed[y*s_resample_width*4 + x*4 + 2] = tmp[2];
-						uncompressed[y*s_resample_width*4 + x*4 + 3] = tmp[3];
-					}
-				}
-
-
-				sprintf( buffer, "%svideo/%s/btc%04d.tga", gamedir, s_base, frame );
-				WriteTGA( buffer, uncompressed, s_resample_width, s_resample_height );
-
-				free( uncompressed );
-			}
-#endif
-		}
-
-		WriteSound( output, frame );
-
-		free (in.data);
-	}
-	stop = clock();
-
-	printf ("\n");
-
-	printf ("Total size: %i\n", ftell( output ) );
-	printf ("Average error: %f\n", sumError / ( frame - startframe ) );
-	printf ("Max error: %f\n", maxError );
-
-	fseconds = ( stop - start ) / 1000.0f;
-	minutes = fseconds / 60;
-	remSeconds = fseconds - minutes * 60;
-
-	printf ("Total time: %d s (%d m %d s)\n", ( int ) fseconds, minutes, remSeconds );
-	printf ("Time/frame: %.2f seconds\n", fseconds / ( frame - startframe ) );
-
-	fclose (output);
-
-	if ( s_soundtrack )
-	{
-		free( s_soundtrack );
-		s_soundtrack = 0;
-	}
-}
+#include <assert.h>
+#include "q3data.h"
+
+static int s_resample_width = 256;
+static int s_resample_height = 256;
+
+#define OUTPUT_TGAS			1
+
+#define UNCOMPRESSED		0
+#define BTC_COMPRESSION		1
+
+static int s_compression_method = BTC_COMPRESSION;
+
+static const char *CIN_EXTENSION = "cn2";
+static const int CIN_SIGNATURE = ( 'C' << 24 ) | ( 'I' << 16 ) | ( 'N' << 8 ) | ( '2' );
+
+static byte	*s_soundtrack;
+static char	s_base[32];
+static char	s_output_base[32];
+
+/*
+===============================================================================
+
+WAV loading
+
+===============================================================================
+*/
+
+typedef struct
+{
+	int			rate;
+	int			width;
+	int			channels;
+	int			loopstart;
+	int			samples;
+	int			dataofs;		// chunk starts this many bytes from file start
+} wavinfo_t;
+
+
+byte	*data_p;
+byte 	*iff_end;
+byte 	*last_chunk;
+byte 	*iff_data;
+int 	iff_chunk_len;
+
+
+static int			s_samplecounts[0x10000];
+static wavinfo_t	s_wavinfo;
+
+short GetLittleShort(void)
+{
+	short val = 0;
+	val = *data_p;
+	val = val + (*(data_p+1)<<8);
+	data_p += 2;
+	return val;
+}
+
+int GetLittleLong(void)
+{
+	int val = 0;
+	val = *data_p;
+	val = val + (*(data_p+1)<<8);
+	val = val + (*(data_p+2)<<16);
+	val = val + (*(data_p+3)<<24);
+	data_p += 4;
+	return val;
+}
+
+void FindNextChunk(char *name)
+{
+	while (1)
+	{
+		data_p=last_chunk;
+
+		if (data_p >= iff_end)
+		{	// didn't find the chunk
+			data_p = NULL;
+			return;
+		}
+		
+		data_p += 4;
+		iff_chunk_len = GetLittleLong();
+		if (iff_chunk_len < 0)
+		{
+			data_p = NULL;
+			return;
+		}
+//		if (iff_chunk_len > 1024*1024)
+//			Sys_Error ("FindNextChunk: %i length is past the 1 meg sanity limit", iff_chunk_len);
+		data_p -= 8;
+		last_chunk = data_p + 8 + ( (iff_chunk_len + 1) & ~1 );
+		if (!strncmp(data_p, name, 4))
+			return;
+	}
+}
+
+void FindChunk(char *name)
+{
+	last_chunk = iff_data;
+	FindNextChunk (name);
+}
+
+
+void DumpChunks(void)
+{
+	char	str[5];
+	
+	str[4] = 0;
+	data_p=iff_data;
+	do
+	{
+		memcpy (str, data_p, 4);
+		data_p += 4;
+		iff_chunk_len = GetLittleLong();
+		printf ("0x%x : %s (%d)\n", (int)(data_p - 4), str, iff_chunk_len);
+		data_p += (iff_chunk_len + 1) & ~1;
+	} while (data_p < iff_end);
+}
+
+/*
+============
+GetWavinfo
+============
+*/
+wavinfo_t GetWavinfo (char *name, byte *wav, int wavlength)
+{
+	wavinfo_t	info;
+	int     i;
+	int     format;
+	int		samples;
+
+	memset (&info, 0, sizeof(info));
+
+	if (!wav)
+		return info;
+		
+	iff_data = wav;
+	iff_end = wav + wavlength;
+
+// find "RIFF" chunk
+	FindChunk("RIFF");
+	if (!(data_p && !strncmp(data_p+8, "WAVE", 4)))
+	{
+		printf("Missing RIFF/WAVE chunks\n");
+		return info;
+	}
+
+// get "fmt " chunk
+	iff_data = data_p + 12;
+// DumpChunks ();
+
+	FindChunk("fmt ");
+	if (!data_p)
+	{
+		printf("Missing fmt chunk\n");
+		return info;
+	}
+	data_p += 8;
+	format = GetLittleShort();
+	if (format != 1)
+	{
+		printf("Microsoft PCM format only\n");
+		return info;
+	}
+
+	info.channels = GetLittleShort();
+	info.rate = GetLittleLong();
+	data_p += 4+2;
+	info.width = GetLittleShort() / 8;
+
+// get cue chunk
+	FindChunk("cue ");
+	if (data_p)
+	{
+		data_p += 32;
+		info.loopstart = GetLittleLong();
+//		Com_Printf("loopstart=%d\n", sfx->loopstart);
+
+	// if the next chunk is a LIST chunk, look for a cue length marker
+		FindNextChunk ("LIST");
+		if (data_p)
+		{
+			if (!strncmp (data_p + 28, "mark", 4))
+			{	// this is not a proper parse, but it works with cooledit...
+				data_p += 24;
+				i = GetLittleLong ();	// samples in loop
+				info.samples = info.loopstart + i;
+			}
+		}
+	}
+	else
+		info.loopstart = -1;
+
+// find data chunk
+	FindChunk("data");
+	if (!data_p)
+	{
+		printf("Missing data chunk\n");
+		return info;
+	}
+
+	data_p += 4;
+	samples = GetLittleLong ();
+
+	if (info.samples)
+	{
+		if (samples < info.samples)
+			Error ("Sound %s has a bad loop length", name);
+	}
+	else
+		info.samples = samples;
+
+	info.dataofs = data_p - wav;
+
+	return info;
+}
+
+//=====================================================================
+
+/*
+==============
+LoadSoundtrack
+==============
+*/
+void LoadSoundtrack (void)
+{
+	char	name[1024];
+	FILE	*f;
+	int		len;
+	int     i, val, j;
+
+	s_soundtrack = NULL;
+	sprintf (name, "%svideo/%s/%s.wav", gamedir, s_base, s_base);
+	printf ("WAV: %s\n", name);
+	f = fopen (name, "rb");
+	if (!f)
+	{
+		printf ("no soundtrack for %s\n", s_base);
+		return;
+	}
+	len = Q_filelength(f);
+	s_soundtrack = malloc(len);
+	fread (s_soundtrack, 1, len, f);
+	fclose (f);
+
+	s_wavinfo = GetWavinfo (name, s_soundtrack, len);
+
+	// count samples for compression
+	memset (s_samplecounts, 0, sizeof(s_samplecounts));
+
+	j = s_wavinfo.samples/2;
+	for (i=0 ; i<j ; i++)
+	{
+		val = ((unsigned short *)( s_soundtrack + s_wavinfo.dataofs))[i];
+		s_samplecounts[val]++;
+	}
+	val = 0;
+	for (i=0 ; i<0x10000 ; i++)
+		if (s_samplecounts[i])
+			val++;
+
+	printf ("%i unique sample values\n", val);
+}
+
+/*
+==================
+WriteSound
+==================
+*/
+void WriteSound (FILE *output, int frame)
+{
+	int		start, end;
+	int		count;
+	int		empty = 0;
+	int		i;
+	int		sample;
+	int		width;
+
+	width = s_wavinfo.width * s_wavinfo.channels;
+
+	start = frame*s_wavinfo.rate/14;
+	end = (frame+1)*s_wavinfo.rate/14;
+	count = end - start;
+
+	for (i=0 ; i<count ; i++)
+	{
+		sample = start+i;
+		if (sample > s_wavinfo.samples || !s_soundtrack)
+			fwrite (&empty, 1, width, output);
+		else
+			fwrite (s_soundtrack + s_wavinfo.dataofs + sample*width, 1, width,output);
+	}
+}
+
+//==========================================================================
+
+static float s_resampleXRatio;
+static float s_resampleYRatio;
+
+static void BoxFilterHorizontalElements( unsigned char *dst, unsigned char *src, float s0, float s1 )
+{
+	float w;
+	float rSum = 0, gSum = 0, bSum = 0;
+	float x = s0;
+	float sumWeight = 0;
+
+	for ( x = s0; x < s1; x++, src += 4 )
+	{
+		if ( x == s0 )
+		{
+			w = ( int ) ( s0 + 1 ) - x;
+		}
+		else if ( x + 1 >= s1 )
+		{
+			w = s1 - ( int ) x;
+		}
+		else
+		{
+			w = 1.0f;
+		}
+
+		rSum += src[0] * w;
+		gSum += src[1] * w;
+		bSum += src[2] * w;
+		sumWeight += w;
+	}
+
+	rSum /= sumWeight;
+	gSum /= sumWeight;
+	bSum /= sumWeight;
+
+	dst[0] = ( unsigned char ) ( rSum + 0.5 );
+	dst[1] = ( unsigned char ) ( gSum + 0.5 );
+	dst[2] = ( unsigned char ) ( bSum + 0.5 );
+}
+
+static void BoxFilterVerticalElements( unsigned char *dst, // destination of the filter process
+									   unsigned char *src, // source pixels
+									   int srcStep,		   // stride of the source pixels
+									   float s0, float s1 )
+{
+	float w;
+	float rSum = 0, gSum = 0, bSum = 0;
+	float y = s0;
+	float sumWeight = 0;
+
+	for ( y = s0; y < ( int ) ( s1 + 1 ) ; y++, src += srcStep )
+	{
+		if ( y == s0 )
+		{
+			w = ( int ) ( s0 + 1 ) - y;
+		}
+		else if ( y + 1 >= s1 )
+		{
+			w = s1 - ( int ) y;
+		}
+		else
+		{
+			w = 1.0f;
+		}
+
+		rSum += src[0] * w;
+		gSum += src[1] * w;
+		bSum += src[2] * w;
+		sumWeight += w;
+	}
+
+	rSum /= sumWeight;
+	gSum /= sumWeight;
+	bSum /= sumWeight;
+
+	dst[0] = ( unsigned char ) ( rSum + 0.5 );
+	dst[1] = ( unsigned char ) ( gSum + 0.5 );
+	dst[2] = ( unsigned char ) ( bSum + 0.5 );
+	dst[3] = 0xff;
+
+}
+
+static void BoxFilterRow( unsigned char *dstStart, cblock_t *in, int dstRow, int rowWidth )
+{
+	int i;
+	unsigned char *indata = ( unsigned char * ) in->data;
+
+	indata += 4 * dstRow * in->width;
+
+	for ( i = 0; i < rowWidth; i++ )
+	{
+		float c0 = i * s_resampleXRatio;
+		float c1 = ( i + 1 ) * s_resampleXRatio;
+
+		BoxFilterHorizontalElements( &dstStart[i*4], &indata[( ( int ) c0 ) * 4], c0, c1 );
+	}
+}
+
+static void BoxFilterColumn( unsigned char *dstStart, unsigned char *srcStart, int dstCol, int dstRowWidth, int dstColHeight, int srcRowWidthInPels )
+{
+	float c0, c1;
+	int i;
+
+	for ( i = 0; i < dstColHeight; i++ )
+	{
+		c0 = i * s_resampleYRatio;
+		c1 = ( i + 1 ) * s_resampleYRatio;
+
+		BoxFilterVerticalElements( &dstStart[i*4*dstRowWidth], &srcStart[(int)c0*srcRowWidthInPels*4], srcRowWidthInPels*4, c0, c1 );
+	}
+}
+
+#define DROP_SAMPLE		0
+#define BOX_FILTER		1
+
+static void ResampleFrame( cblock_t *in, unsigned char *out, int method, int outWidth, int outHeight )
+{
+	int row, column;
+	unsigned char *indata = ( unsigned char * ) in->data;
+
+	s_resampleXRatio = in->width / ( float ) outWidth;
+	s_resampleYRatio = in->height / ( float ) outHeight;
+
+	if ( method == DROP_SAMPLE )
+	{
+		for ( row = 0; row < outHeight; row++ )
+		{
+			int r = ( int ) ( row * s_resampleYRatio );
+
+			for ( column = 0; column < outWidth; column++ )
+			{
+				int c = ( int ) ( column * s_resampleXRatio );
+
+				out[(row*outWidth+column)*4+0] = indata[(r*in->width+c)*4+0];
+				out[(row*outWidth+column)*4+1] = indata[(r*in->width+c)*4+1];
+				out[(row*outWidth+column)*4+2] = indata[(r*in->width+c)*4+2];
+				out[(row*outWidth+column)*4+3] = 0xff;
+			}
+		}
+	}
+	else if ( method == BOX_FILTER )
+	{
+		unsigned char intermediate[1024*1024*4];
+
+		assert( in->height <= 1024 );
+		assert( in->width <= 1024 );
+
+		//
+		// filter our M x N source image into a RESAMPLE_WIDTH x N horizontally filtered image
+		//
+		for ( row = 0; row < in->height; row++ )
+		{
+			BoxFilterRow( &intermediate[row*4*outWidth], in, row, outWidth );
+		}
+
+		//
+		// filter our RESAMPLE_WIDTH x N horizontally filtered image into a RESAMPLE_WIDTH x RESAMPLE_HEIGHT filtered image
+		//
+		for ( column = 0; column < outWidth; column++ )
+		{
+			BoxFilterColumn( &out[column*4], &intermediate[column*4], column, outWidth, outHeight, s_resample_width );
+		}
+	}
+}
+
+static float BTCDistanceSquared( float a[3], float b[3] )
+{
+	return ( b[0] - a[0] ) * ( b[0] - a[0] ) + 
+		   ( b[1] - a[1] ) * ( b[1] - a[1] ) +
+		   ( b[2] - a[2] ) * ( b[2] - a[2] );
+}
+
+static void BTCFindEndpoints( float inBlock[4][4][3], unsigned int endPoints[2][2] )
+{
+	float longestDistance = -1;
+
+	int bX, bY;
+
+	//
+	// find the two points farthest from each other
+	//
+	for ( bY = 0; bY < 4; bY++ )
+	{
+		for ( bX = 0; bX < 4; bX++ )
+		{
+			int cX, cY;
+			float d;
+
+			//
+			// check the rest of the current row
+			//
+			for ( cX = bX + 1; cX < 4; cX++ )
+			{
+				if ( ( d = BTCDistanceSquared( inBlock[bY][bX], inBlock[bY][cX] ) ) > longestDistance )
+				{
+					longestDistance = d;
+					endPoints[0][0] = bX;
+					endPoints[0][1] = bY;
+					endPoints[1][0] = cX;
+					endPoints[1][1] = bY;
+				}
+			}
+
+			//
+			// check remaining rows and columns
+			//
+			for ( cY = bY+1; cY < 4; cY++ )
+			{
+				for ( cX = 0; cX < 4; cX++ )
+				{
+					if ( ( d = BTCDistanceSquared( inBlock[bY][bX], inBlock[cY][cX] ) ) > longestDistance )
+					{
+						longestDistance = d;
+						endPoints[0][0] = bX;
+						endPoints[0][1] = bY;
+						endPoints[1][0] = cX;
+						endPoints[1][1] = cY;
+					}
+				}
+			}
+		}
+	}
+}
+
+static float BTCQuantizeBlock( float inBlock[4][4][3], unsigned long endPoints[2][2], int btcQuantizedBlock[4][4], float bestError )
+{
+	int i;
+	int blockY, blockX;
+	float dR, dG, dB;
+	float R, G, B;
+	float error = 0;
+	float colorLine[4][3];
+
+	//
+	// build the color line
+	//
+	dR = inBlock[endPoints[1][1]][endPoints[1][0]][0] -
+		 inBlock[endPoints[0][1]][endPoints[0][0]][0];
+	dG = inBlock[endPoints[1][1]][endPoints[1][0]][1] -
+		 inBlock[endPoints[0][1]][endPoints[0][0]][1];
+	dB = inBlock[endPoints[1][1]][endPoints[1][0]][2] -
+		 inBlock[endPoints[0][1]][endPoints[0][0]][2];
+
+	dR *= 0.33f;
+	dG *= 0.33f;
+	dB *= 0.33f;
+
+	R = inBlock[endPoints[0][1]][endPoints[0][0]][0];
+	G = inBlock[endPoints[0][1]][endPoints[0][0]][1];
+	B = inBlock[endPoints[0][1]][endPoints[0][0]][2];
+
+	for ( i = 0; i < 4; i++ )
+	{
+		colorLine[i][0] = R;
+		colorLine[i][1] = G;
+		colorLine[i][2] = B;
+
+		R += dR;
+		G += dG;
+		B += dB;
+	}
+
+	//
+	// quantize each pixel into the appropriate range
+	//
+	for ( blockY = 0; blockY < 4; blockY++ )
+	{
+		for ( blockX = 0; blockX < 4; blockX++ )
+		{
+			float distance = 10000000000;
+			int shortest = -1;
+
+			for ( i = 0; i < 4; i++ )
+			{
+				float d;
+
+				if ( ( d = BTCDistanceSquared( inBlock[blockY][blockX], colorLine[i] ) ) < distance )
+				{
+					distance = d;
+					shortest = i;
+				}
+			}
+
+			error += distance;
+
+			//
+			// if bestError is not -1 then that means this is a speculative quantization
+			//
+			if ( bestError != -1 )
+			{
+				if ( error > bestError )
+					return error;
+			}
+
+			btcQuantizedBlock[blockY][blockX] = shortest;
+		}
+	}
+
+	return error;
+}
+
+/*
+** float BTCCompressBlock
+*/
+static float BTCCompressBlock( float inBlock[4][4][3], unsigned long out[2] )
+{
+	int i;
+	int btcQuantizedBlock[4][4];	// values should be [0..3]
+	unsigned long encodedEndPoints, encodedBitmap;
+	unsigned int endPoints[2][2];		// endPoints[0] = color start, endPoints[1] = color end
+	int blockY, blockX;
+	float error = 0;
+	float bestError = 10000000000;
+	unsigned int bestEndPoints[2][2];
+
+#if 0
+	//
+	// find the "ideal" end points for the color vector 
+	//
+	BTCFindEndpoints( inBlock, endPoints );
+	error = BTCQuantizeBlock( inBlock, endPoints, btcQuantizedBlock );
+	memcpy( bestEndPoints, endPoints, sizeof( bestEndPoints ) );
+#else
+	for ( blockY = 0; blockY < 4; blockY++ )
+	{
+		for ( blockX = 0; blockX < 4; blockX++ )
+		{
+			int x2, y2;
+
+			for ( y2 = 0; y2 < 4; y2++ )
+			{
+				for ( x2 = 0; x2 < 4; x2++ )
+				{
+					if ( ( x2 == blockX ) && ( y2 == blockY ) )
+						continue;
+
+					endPoints[0][0] = blockX;
+					endPoints[0][1] = blockY;
+					endPoints[1][0] = x2;
+					endPoints[1][1] = y2;
+
+					error = BTCQuantizeBlock( inBlock, endPoints, btcQuantizedBlock, -1 ); //bestError );
+
+					if ( error < bestError )
+					{
+						bestError = error;
+						memcpy( bestEndPoints, endPoints, sizeof( bestEndPoints ) );
+					}
+				}
+			}
+		}
+	}
+
+	error = BTCQuantizeBlock( inBlock, bestEndPoints, btcQuantizedBlock, -1.0f );
+#endif
+
+	//
+	// encode the results
+	//
+	encodedBitmap = 0;
+	for ( blockY = 0; blockY < 4; blockY++ )
+	{
+		for ( blockX = 0; blockX < 4; blockX++ )
+		{
+			int shift = ( blockX + blockY * 4 ) * 2;
+			encodedBitmap |= btcQuantizedBlock[blockY][blockX] << shift;
+		}
+	}
+
+	//
+	// encode endpoints
+	//
+	encodedEndPoints = 0;
+	for ( i = 0; i < 2; i++ )
+	{
+		int iR, iG, iB;
+
+		iR = ( ( int ) inBlock[bestEndPoints[i][1]][bestEndPoints[i][0]][0] );
+		if ( iR > 255 ) 
+			iR = 255;
+		else if ( iR < 0 ) 
+			iR = 0;
+		iR >>= 3;
+
+		iG = ( ( int ) inBlock[bestEndPoints[i][1]][bestEndPoints[i][0]][1] );
+		if ( iG > 255 )
+			iG = 255;
+		else if ( iG < 0 )
+			iG = 0;
+		iG >>= 2;
+
+		iB = ( ( int ) inBlock[bestEndPoints[i][1]][bestEndPoints[i][0]][2] );
+		if ( iB > 255 )
+			iB = 255;
+		else if ( iB < 0 )
+			iB = 0;
+		iB >>= 3;
+
+
+		encodedEndPoints |= ( ( ( iR << 11 ) | ( iG << 5 ) | ( iB ) ) << ( i * 16 ) );
+	}
+
+	//
+	// store 
+	//
+	out[0] = encodedBitmap;
+	out[1] = encodedEndPoints;
+
+	return error;
+}
+
+/*
+** void BTCDecompressFrame
+*/
+static void BTCDecompressFrame( unsigned long *src, unsigned char *dst )
+{
+	int x, y;
+	int iR, iG, iB;
+	int dstX, dstY;
+	float colorStart[3], colorEnd[3];
+	unsigned char colorRampABGR[4][4];
+	unsigned encoded;
+
+	memset( colorRampABGR, 0xff, sizeof( colorRampABGR ) );
+
+	for ( y = 0; y < s_resample_height / 4; y++ )
+	{
+		for ( x = 0; x < s_resample_width / 4; x++ )
+		{
+			unsigned colorStartPacked = src[(y*s_resample_width/4 + x)*2 + 1] & 0xffff;
+			unsigned colorEndPacked = src[(y*s_resample_width/4 + x)*2 + 1] >> 16;
+
+			//
+			// grab the end points
+			//   0 = color start
+			//   1 = color end
+			//
+			iR = ( ( colorStartPacked >> 11 ) & ( ( 1 << 5 ) - 1 ) );
+			iR = ( iR << 3 ) | ( iR >> 2 );
+			iG = ( ( colorStartPacked >> 5 ) & ( ( 1 << 6 )  - 1 ) );
+			iG = ( iG << 2 ) | ( iG >> 4 );
+			iB = ( ( colorStartPacked ) & ( ( 1 << 5  ) - 1 ) );
+			iB = ( iB << 3 ) | ( iB >> 2 );
+
+			colorStart[0] = iR;
+			colorStart[1] = iG;
+			colorStart[2] = iB;
+			colorRampABGR[0][0] = iR;
+			colorRampABGR[0][1] = iG;
+			colorRampABGR[0][2] = iB;
+
+			iR = ( ( colorEndPacked >> 11 ) & ( ( 1 << 5 ) - 1 ) );
+			iR = ( iR << 3 ) | ( iR >> 2 );
+			iG = ( ( colorEndPacked >> 5 ) & ( ( 1 << 6 )  - 1 ) );
+			iG = ( iG << 2 ) | ( iG >> 4 );
+			iB = ( colorEndPacked & ( ( 1 << 5  ) - 1 ) );
+			iB = ( iB << 3 ) | ( iB >> 2 );
+
+			colorEnd[0] = iR;
+			colorEnd[1] = iG;
+			colorEnd[2] = iB;
+			colorRampABGR[3][0] = iR;
+			colorRampABGR[3][1] = iG;
+			colorRampABGR[3][2] = iB;
+			
+			//
+			// compute this block's color ramp
+			// FIXME: This needs to be reversed on big-endian machines
+			//
+			
+			colorRampABGR[1][0] = colorStart[0] * 0.66f + colorEnd[0] * 0.33f;
+			colorRampABGR[1][1] = colorStart[1] * 0.66f + colorEnd[1] * 0.33f;
+			colorRampABGR[1][2] = colorStart[2] * 0.66f + colorEnd[2] * 0.33f;
+
+			colorRampABGR[2][0] = colorStart[0] * 0.33f + colorEnd[0] * 0.66f;
+			colorRampABGR[2][1] = colorStart[1] * 0.33f + colorEnd[1] * 0.66f;
+			colorRampABGR[2][2] = colorStart[2] * 0.33f + colorEnd[2] * 0.66f;
+
+			//
+			// decode the color data
+			// information is encoded in 2-bit pixels, with low order bits corresponding
+			// to upper left pixels.  These 2-bit values are indexed into the block's
+			// computer color ramp.
+			//
+			encoded = src[(y*s_resample_width/4 + x)*2 + 0];
+
+			for ( dstY = 0; dstY < 4; dstY++ )
+			{
+				for ( dstX = 0; dstX < 4; dstX++ )
+				{
+					memcpy( &dst[(y*4+dstY)*s_resample_width*4+x*4*4+dstX*4], colorRampABGR[encoded&3], sizeof( colorRampABGR[0] ) );
+					encoded >>= 2;
+				}
+			}
+		}
+	}
+}
+
+/*
+** BTCCompressFrame
+**
+** Perform a BTC compression using a 2-bit encoding at each pixel.  This
+** compression method is performed by decomposing the incoming image into
+** a sequence of 4x4 blocks.  At each block two color values are computed
+** that define the endpoints of a vector in color space that represent
+** the two colors "farthest apart".
+*/
+static float BTCCompressFrame( unsigned char *src, unsigned long *dst )
+{
+	int x, y;
+	int bX, bY;
+	float btcBlock[4][4][3];
+
+	float error = 0;
+	
+	for ( y = 0; y < s_resample_height / 4; y++ )
+	{
+		for ( x = 0; x < s_resample_width / 4; x++ )
+		{
+			//
+			// fill in the BTC block with raw values
+			//
+			for ( bY = 0; bY < 4; bY++ )
+			{
+				for ( bX = 0; bX < 4; bX++ )
+				{
+					btcBlock[bY][bX][0] = src[(y*4+bY)*s_resample_width*4 + (x*4+bX)*4 + 0];
+					btcBlock[bY][bX][1] = src[(y*4+bY)*s_resample_width*4 + (x*4+bX)*4 + 1];
+					btcBlock[bY][bX][2] = src[(y*4+bY)*s_resample_width*4 + (x*4+bX)*4 + 2];
+				}
+			}
+
+			error += BTCCompressBlock( btcBlock, &dst[(y*s_resample_width/4+x)*2] );
+		}
+	}
+
+	return error / ( ( s_resample_width / 4 ) * ( s_resample_height / 4 ) );
+}
+
+/*
+===================
+LoadFrame
+===================
+*/
+cblock_t LoadFrame (char *base, int frame, int digits, byte **palette)
+{
+	int			ten3, ten2, ten1, ten0;
+	cblock_t	in;
+	int			width, height;
+	char		name[1024];
+	FILE		*f;
+
+	in.data = NULL;
+	in.count = -1;
+
+	ten3 = frame/1000;
+	ten2 = (frame-ten3*1000)/100;
+	ten1 = (frame-ten3*1000-ten2*100)/10;
+	ten0 = frame%10;
+
+	if (digits == 4)
+		sprintf (name, "%svideo/%s/%s%i%i%i%i.tga", gamedir, base, base, ten3, ten2, ten1, ten0);
+	else
+		sprintf (name, "%svideo/%s/%s%i%i%i.tga", gamedir, base, base, ten2, ten1, ten0);
+
+	f = fopen(name, "rb");
+	if (!f)
+	{
+		in.data = NULL;
+		return in;
+	}
+	fclose (f);
+
+	printf ("%s", name);
+	LoadTGA( name, ( unsigned char ** ) &in.data, &width, &height );
+	if ( palette )
+		*palette = 0;
+//	Load256Image (name, &in.data, palette, &width, &height);
+	in.count = width*height;
+	in.width = width;
+	in.height = height;
+// FIXME: map 0 and 255!
+
+#if 0
+	// rle compress
+	rle = RLE(in);
+	free (in.data);
+
+	return rle;
+#endif
+
+	return in;
+}
+
+/*
+===============
+Cmd_Video
+
+video <directory> <framedigits>
+===============
+*/
+void Cmd_Video (void)
+{
+	float sumError = 0, error = 0, maxError = 0;
+	char	savename[1024];
+	char	name[1024];
+	FILE	*output;
+	int		startframe, frame;
+	int		width, height;
+	int		i;
+	int		digits;
+	int		minutes;
+	float	fseconds;
+	int		remSeconds;
+	cblock_t	in;
+	unsigned char *resampled;
+	unsigned long *compressed;
+	clock_t start, stop;
+
+	GetToken (qfalse);
+	strcpy (s_base, token);
+	if (g_release)
+	{
+//		sprintf (savename, "video/%s.cin", token);
+//		ReleaseFile (savename);
+		return;
+	}
+
+	GetToken( qfalse );
+	strcpy( s_output_base, token );
+
+	GetToken (qfalse);
+	digits = atoi(token);
+
+	GetToken( qfalse );
+
+	if ( !strcmp( token, "btc" ) )
+	{
+		s_compression_method = BTC_COMPRESSION;
+		printf( "Compression: BTC\n" );
+	}
+	else if ( !strcmp( token, "uc" ) )
+	{
+		s_compression_method = UNCOMPRESSED;
+		printf( "Compression: none\n" );
+	}
+	else
+	{
+		Error( "Uknown compression method '%s'\n", token );
+	}
+
+	GetToken( qfalse );
+	s_resample_width = atoi( token );
+
+	GetToken( qfalse );
+	s_resample_height = atoi( token );
+
+	resampled = malloc( sizeof( unsigned char ) * 4 * s_resample_width * s_resample_height );
+	compressed = malloc( sizeof( long ) * 2 * ( s_resample_width / 4 ) * ( s_resample_height / 4 ) );
+
+	printf( "Resample width: %d\n", s_resample_width );
+	printf( "Resample height: %d\n", s_resample_height );
+
+	// optionally skip frames
+	if (TokenAvailable ())
+	{
+		GetToken (qfalse);
+		startframe = atoi(token);
+	}
+	else
+		startframe=0;
+
+	sprintf (savename, "%svideo/%s.%s", writedir, s_output_base, CIN_EXTENSION );
+
+	// load the entire sound wav file if present
+	LoadSoundtrack ();
+
+	if (digits == 4)
+		sprintf (name, "%svideo/%s/%s0000.tga", gamedir, s_base, s_base);
+	else
+		sprintf (name, "%svideo/%s/%s000.tga", gamedir, s_base, s_base);
+
+	printf ("%s\n", name);
+	LoadTGA( name, NULL, &width, &height);
+
+	output = fopen (savename, "wb");
+	if (!output)
+		Error ("Can't open %s", savename);
+
+	// write header info
+	i = LittleLong( CIN_SIGNATURE );
+	fwrite (&i, 4, 1, output );
+	i = LittleLong (s_resample_width);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (s_resample_height);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (s_wavinfo.rate);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (s_wavinfo.width);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong (s_wavinfo.channels);
+	fwrite (&i, 4, 1, output);
+	i = LittleLong ( s_compression_method );
+	fwrite (&i, 4, 1, output );
+
+	start = clock();
+
+	// perform compression on a per frame basis
+	for ( frame=startframe ;  ; frame++)
+	{
+		printf ("%02d: ", frame);
+		in = LoadFrame (s_base, frame, digits, 0 );
+		if (!in.data)
+			break;
+
+		ResampleFrame( &in, ( unsigned char * ) resampled, BOX_FILTER, s_resample_width, s_resample_height );
+
+		if ( s_compression_method == UNCOMPRESSED )
+		{
+			printf( "\n" );
+			fwrite( resampled, 1, sizeof( unsigned char ) * s_resample_width * s_resample_height * 4, output );
+
+#if OUTPUT_TGAS
+			{
+				int x, y;
+				char buffer[1000];
+
+				for ( y = 0; y < s_resample_height/2; y++ )
+				{
+					for ( x = 0; x < s_resample_width; x++ )
+					{
+						unsigned char tmp[4];
+
+						tmp[0] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0];
+						tmp[1] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1];
+						tmp[2] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2];
+						tmp[3] = resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3];
+
+						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0] = resampled[y*s_resample_width*4 + x*4 + 0];
+						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1] = resampled[y*s_resample_width*4 + x*4 + 1];
+						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2] = resampled[y*s_resample_width*4 + x*4 + 2];
+						resampled[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3] = resampled[y*s_resample_width*4 + x*4 + 3];
+
+						resampled[y*s_resample_width*4 + x*4 + 0] = tmp[0];
+						resampled[y*s_resample_width*4 + x*4 + 1] = tmp[1];
+						resampled[y*s_resample_width*4 + x*4 + 2] = tmp[2];
+						resampled[y*s_resample_width*4 + x*4 + 3] = tmp[3];
+					}
+				}
+
+				sprintf( buffer, "%svideo/%s/uc%04d.tga", gamedir, s_base, frame );
+				WriteTGA( buffer, resampled, s_resample_width, s_resample_height );
+			}
+#endif
+		}
+		else if ( s_compression_method == BTC_COMPRESSION )
+		{
+			error = BTCCompressFrame( resampled, compressed );
+
+			sumError += error;
+
+			if ( error > maxError ) 
+				maxError = error;
+
+			printf( " (error = %f)\n", error );
+			fwrite( compressed, 1, 2 * sizeof( long ) * ( s_resample_width / 4 ) * ( s_resample_height / 4 ), output );
+
+#if OUTPUT_TGAS
+			{
+				int x, y;
+				unsigned char *uncompressed;
+				char buffer[1000];
+
+				uncompressed = malloc( sizeof( unsigned char ) * 4 * s_resample_width * s_resample_height );
+				BTCDecompressFrame( compressed, uncompressed );
+
+				for ( y = 0; y < s_resample_height/2; y++ )
+				{
+					for ( x = 0; x < s_resample_width; x++ )
+					{
+						unsigned char tmp[4];
+
+						tmp[0] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0];
+						tmp[1] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1];
+						tmp[2] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2];
+						tmp[3] = uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3];
+
+						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 0] = uncompressed[y*s_resample_width*4 + x*4 + 0];
+						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 1] = uncompressed[y*s_resample_width*4 + x*4 + 1];
+						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 2] = uncompressed[y*s_resample_width*4 + x*4 + 2];
+						uncompressed[(s_resample_height-1-y)*s_resample_width*4 + x*4 + 3] = uncompressed[y*s_resample_width*4 + x*4 + 3];
+
+						uncompressed[y*s_resample_width*4 + x*4 + 0] = tmp[0];
+						uncompressed[y*s_resample_width*4 + x*4 + 1] = tmp[1];
+						uncompressed[y*s_resample_width*4 + x*4 + 2] = tmp[2];
+						uncompressed[y*s_resample_width*4 + x*4 + 3] = tmp[3];
+					}
+				}
+
+
+				sprintf( buffer, "%svideo/%s/btc%04d.tga", gamedir, s_base, frame );
+				WriteTGA( buffer, uncompressed, s_resample_width, s_resample_height );
+
+				free( uncompressed );
+			}
+#endif
+		}
+
+		WriteSound( output, frame );
+
+		free (in.data);
+	}
+	stop = clock();
+
+	printf ("\n");
+
+	printf ("Total size: %i\n", ftell( output ) );
+	printf ("Average error: %f\n", sumError / ( frame - startframe ) );
+	printf ("Max error: %f\n", maxError );
+
+	fseconds = ( stop - start ) / 1000.0f;
+	minutes = fseconds / 60;
+	remSeconds = fseconds - minutes * 60;
+
+	printf ("Total time: %d s (%d m %d s)\n", ( int ) fseconds, minutes, remSeconds );
+	printf ("Time/frame: %.2f seconds\n", fseconds / ( frame - startframe ) );
+
+	fclose (output);
+
+	if ( s_soundtrack )
+	{
+		free( s_soundtrack );
+		s_soundtrack = 0;
+	}
+}
diff --git a/tools/quake3/q3map2/brush.c b/tools/quake3/q3map2/brush.c
index eebc097f..28ade081 100644
--- a/tools/quake3/q3map2/brush.c
+++ b/tools/quake3/q3map2/brush.c
@@ -1,982 +1,982 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define BRUSH_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* -------------------------------------------------------------------------------
-
-functions
-
-------------------------------------------------------------------------------- */
-
-/*
-AllocSideRef() - ydnar
-allocates and assigns a brush side reference
-*/
-
-sideRef_t *AllocSideRef( side_t *side, sideRef_t *next )
-{
-	sideRef_t *sideRef;
-	
-	
-	/* dummy check */
-	if( side == NULL )
-		return next;
-	
-	/* allocate and return */
-	sideRef = safe_malloc( sizeof( *sideRef ) );
-	sideRef->side = side;
-	sideRef->next = next;
-	return sideRef;
-}
-
-
-
-/*
-CountBrushList()
-counts the number of brushes in a brush linked list
-*/
-
-int	CountBrushList( brush_t *brushes )
-{
-	int	c = 0;
-	
-	
-	/* count brushes */
-	for( brushes; brushes != NULL; brushes = brushes->next )
-		c++;
-	return c;
-}
-
-
-
-/*
-AllocBrush()
-allocates a new brush
-*/
-
-brush_t *AllocBrush( int numSides )
-{
-	brush_t		*bb;
-	int			c;
-	
-	
-	/* allocate and clear */
-	if( numSides <= 0 )
-		Error( "AllocBrush called with numsides = %d", numSides );
-	c = (int) &(((brush_t*) 0)->sides[ numSides ]);
-	bb = safe_malloc( c );
-	memset( bb, 0, c );
-	if( numthreads == 1 )
-		numActiveBrushes++;
-	
-	/* return it */
-	return bb;
-}
-
-
-
-/*
-FreeBrush()
-frees a single brush and all sides/windings
-*/
-
-void FreeBrush( brush_t *b )
-{
-	int			i;
-	
-	
-	/* error check */
-	if( *((int*) b) == 0xFEFEFEFE )
-	{
-		Sys_FPrintf( SYS_VRB, "WARNING: Attempt to free an already freed brush!\n" );
-		return;
-	}
-	
-	/* free brush sides */
-	for( i = 0; i < b->numsides; i++ )
-		if( b->sides[i].winding != NULL )
-			FreeWinding( b->sides[ i ].winding );
-	
-	/* ydnar: overwrite it */
-	memset( b, 0xFE, (int) &(((brush_t*) 0)->sides[ b->numsides ]) );
-	*((int*) b) = 0xFEFEFEFE;
-	
-	/* free it */
-	free( b );
-	if( numthreads == 1 )
-		numActiveBrushes--;
-}
-
-
-
-/*
-FreeBrushList()
-frees a linked list of brushes
-*/
-
-void FreeBrushList( brush_t *brushes )
-{
-	brush_t		*next;
-	
-	
-	/* walk brush list */
-	for( brushes; brushes != NULL; brushes = next )
-	{
-		next = brushes->next;
-		FreeBrush( brushes );
-	}		
-}
-
-
-
-/*
-CopyBrush()
-duplicates the brush, sides, and windings
-*/
-
-brush_t *CopyBrush( brush_t *brush )
-{
-	brush_t		*newBrush;
-	int			size;
-	int			i;
-	
-	
-	/* copy brush */
-	size = (int) &(((brush_t*) 0)->sides[ brush->numsides ]);
-	newBrush = AllocBrush( brush->numsides );
-	memcpy( newBrush, brush, size );
-	
-	/* ydnar: nuke linked list */
-	newBrush->next = NULL;
-	
-	/* copy sides */
-	for( i = 0; i < brush->numsides; i++ )
-	{
-		if( brush->sides[ i ].winding != NULL )
-			newBrush->sides[ i ].winding = CopyWinding( brush->sides[ i ].winding );
-	}
-	
-	/* return it */
-	return newBrush;
-}
-
-
-
-
-/*
-BoundBrush()
-sets the mins/maxs based on the windings
-returns false if the brush doesn't enclose a valid volume
-*/
-
-qboolean BoundBrush( brush_t *brush )
-{
-	int			i, j;
-	winding_t	*w;
-	
-	
-	ClearBounds( brush->mins, brush->maxs );
-	for( i = 0; i < brush->numsides; i++ )
-	{
-		w = brush->sides[ i ].winding;
-		if( w == NULL )
-			continue;
-		for( j = 0; j < w->numpoints; j++ )
-			AddPointToBounds( w->p[ j ], brush->mins, brush->maxs );
-	}
-	
-	for( i = 0; i < 3; i++ )
-	{
-		if( brush->mins[ i ] < MIN_WORLD_COORD || brush->maxs[ i ] > MAX_WORLD_COORD || brush->mins[i] >= brush->maxs[ i ] )
-			return qfalse;
-	}
-	
-	return qtrue;
-}
-
-
-
-
-/*
-SnapWeldVector() - ydnar
-welds two vec3_t's into a third, taking into account nearest-to-integer
-instead of averaging
-*/
-
-#define SNAP_EPSILON	0.01
-
-void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out )
-{
-	int		i;
-	vec_t	ai, bi, outi;
-	
-	
-	/* dummy check */
-	if( a == NULL || b == NULL || out == NULL )
-		return;
-	
-	/* do each element */
-	for( i = 0; i < 3; i++ )
-	{
-		/* round to integer */
-		ai = Q_rint( a[ i ] );
-		bi = Q_rint( a[ i ] );
-		
-		/* prefer exact integer */
-		if( ai == a[ i ] )
-			out[ i ] = a[ i ];
-		else if( bi == b[ i ] )
-			out[ i ] = b[ i ];
-
-		/* use nearest */
-		else if( fabs( ai - a[ i ] ) < fabs( bi < b[ i ] ) )
-			out[ i ] = a[ i ];
-		else
-			out[ i ] = b[ i ];
-		
-		/* snap */
-		outi = Q_rint( out[ i ] );
-		if( fabs( outi - out[ i ] ) <= SNAP_EPSILON )
-			out[ i ] = outi;
-	}
-}
-
-
-
-/*
-FixWinding() - ydnar
-removes degenerate edges from a winding
-returns qtrue if the winding is valid
-*/
-
-#define DEGENERATE_EPSILON	0.1
-
-qboolean FixWinding( winding_t *w )
-{
-	qboolean	valid = qtrue;
-	int			i, j, k;
-	vec3_t		vec;
-	float		dist;
-	
-	
-	/* dummy check */
-	if( !w )
-		return qfalse;
-	
-	/* check all verts */
-	for( i = 0; i < w->numpoints; i++ )
-	{
-		/* don't remove points if winding is a triangle */
-		if( w->numpoints == 3 )
-			return valid;
-		
-		/* get second point index */
-		j = (i + 1) % w->numpoints;
-		
-		/* degenerate edge? */
-		VectorSubtract( w->p[ i ], w->p[ j ], vec );
-		dist = VectorLength( vec );
-		if( dist < DEGENERATE_EPSILON )
-		{
-			valid = qfalse;
-			//Sys_FPrintf( SYS_VRB, "WARNING: Degenerate winding edge found, fixing...\n" );
-			
-			/* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
-			SnapWeldVector( w->p[ i ], w->p[ j ], vec );
-			VectorCopy( vec, w->p[ i ] );
-			//VectorAdd( w->p[ i ], w->p[ j ], vec );
-			//VectorScale( vec, 0.5, w->p[ i ] );
-			
-			/* move the remaining verts */
-			for( k = i + 2; k < w->numpoints; k++ )
-			{
-				VectorCopy( w->p[ k ], w->p[ k - 1 ] );
-			}
-			w->numpoints--;
-		}
-	}
-	
-	/* one last check and return */
-	if( w->numpoints < 3 )
-		valid = qfalse;
-	return valid;
-}
-
-
-
-
-
-
-
-/*
-CreateBrushWindings()
-makes basewindigs for sides and mins/maxs for the brush
-returns false if the brush doesn't enclose a valid volume
-*/
-
-qboolean CreateBrushWindings( brush_t *brush )
-{
-	int			i, j;
-	winding_t	*w;
-	side_t		*side;
-	plane_t		*plane;
-	
-	
-	/* walk the list of brush sides */
-	for( i = 0; i < brush->numsides; i++ )
-	{
-		/* get side and plane */
-		side = &brush->sides[ i ];
-		plane = &mapplanes[ side->planenum ];
-		
-		/* make huge winding */
-		w = BaseWindingForPlane( plane->normal, plane->dist );
-		
-		/* walk the list of brush sides */
-		for( j = 0; j < brush->numsides && w != NULL; j++ )
-		{
-			if( i == j )
-				continue;
-			if( brush->sides[ j ].planenum == (brush->sides[ i ].planenum ^ 1) )
-				continue;		/* back side clipaway */
-			if( brush->sides[ j ].bevel )
-				continue;
-			if( brush->sides[ j ].backSide )
-				continue;
-			plane = &mapplanes[ brush->sides[ j ].planenum ^ 1 ];
-			ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON );
-			
-			/* ydnar: fix broken windings that would generate trifans */
-			FixWinding( w );
-		}
-		
-		/* set side winding */
-		side->winding = w;
-	}
-	
-	/* find brush bounds */
-	return BoundBrush( brush );
-}
-
-
-
-
-/*
-==================
-BrushFromBounds
-
-Creates a new axial brush
-==================
-*/
-brush_t	*BrushFromBounds (vec3_t mins, vec3_t maxs)
-{
-	brush_t		*b;
-	int			i;
-	vec3_t		normal;
-	vec_t		dist;
-
-	b = AllocBrush (6);
-	b->numsides = 6;
-	for (i=0 ; i<3 ; i++)
-	{
-		VectorClear (normal);
-		normal[i] = 1;
-		dist = maxs[i];
-		b->sides[i].planenum = FindFloatPlane (normal, dist, 1, (vec3_t*) &maxs );
-
-		normal[i] = -1;
-		dist = -mins[i];
-		b->sides[3+i].planenum = FindFloatPlane (normal, dist, 1, (vec3_t*) &mins );
-	}
-
-	CreateBrushWindings (b);
-
-	return b;
-}
-
-/*
-==================
-BrushVolume
-
-==================
-*/
-vec_t BrushVolume (brush_t *brush)
-{
-	int			i;
-	winding_t	*w;
-	vec3_t		corner;
-	vec_t		d, area, volume;
-	plane_t		*plane;
-
-	if (!brush)
-		return 0;
-
-	// grab the first valid point as the corner
-
-	w = NULL;
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (w)
-			break;
-	}
-	if (!w)
-		return 0;
-	VectorCopy (w->p[0], corner);
-
-	// make tetrahedrons to all other faces
-
-	volume = 0;
-	for ( ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		plane = &mapplanes[brush->sides[i].planenum];
-		d = -(DotProduct (corner, plane->normal) - plane->dist);
-		area = WindingArea (w);
-		volume += d*area;
-	}
-
-	volume /= 3;
-	return volume;
-}
-
-
-
-/*
-WriteBSPBrushMap()
-writes a map with the split bsp brushes
-*/
-
-void WriteBSPBrushMap( char *name, brush_t *list )
-{
-	FILE		*f;
-	side_t		*s;
-	int			i;
-	winding_t	*w;
-	
-	
-	/* note it */
-	Sys_Printf( "Writing %s\n", name );
-	
-	/* open the map file */
-	f = fopen( name, "wb" );
-	if( f == NULL )
-		Error( "Can't write %s\b", name );
-
-	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
-
-	for ( ; list ; list=list->next )
-	{
-		fprintf (f, "{\n");
-		for (i=0,s=list->sides ; i<list->numsides ; i++,s++)
-		{
-			w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist);
-
-			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
-			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
-			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
-
-			fprintf (f, "notexture 0 0 0 1 1\n" );
-			FreeWinding (w);
-		}
-		fprintf (f, "}\n");
-	}
-	fprintf (f, "}\n");
-
-	fclose (f);
-
-}
-
-
-
-/*
-FilterBrushIntoTree_r()
-adds brush reference to any intersecting bsp leafnode
-*/
-
-int FilterBrushIntoTree_r( brush_t *b, node_t *node )
-{
-	brush_t		*front, *back;
-	int			c;
-	
-	
-	/* dummy check */
-	if( b == NULL )
-		return 0;
-	
-	/* add it to the leaf list */
-	if( node->planenum == PLANENUM_LEAF )
-	{
-		/* something somewhere is hammering brushlist */
-		b->next = node->brushlist;
-		node->brushlist = b;
-		
-		/* classify the leaf by the structural brush */
-		if( !b->detail )
-		{
-			if( b->opaque )
-			{
-				node->opaque = qtrue;
-				node->areaportal = qfalse;
-			}
-			else if( b->compileFlags & C_AREAPORTAL )
-			{
-				if( !node->opaque )
-					node->areaportal = qtrue;
-			}
-		}
-		
-		return 1;
-	}
-	
-	/* split it by the node plane */
-	c = b->numsides;
-	SplitBrush( b, node->planenum, &front, &back );
-	FreeBrush( b );
-	
-	c = 0;
-	c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
-	c += FilterBrushIntoTree_r( back, node->children[ 1 ] );
-	
-	return c;
-}
-
-
-
-/*
-FilterDetailBrushesIntoTree
-fragment all the detail brushes into the structural leafs
-*/
-
-void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree )
-{
-	brush_t				*b, *newb;
-	int					r;
-	int					c_unique, c_clusters;
-	int					i;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB,  "--- FilterDetailBrushesIntoTree ---\n" );
-	
-	/* walk the list of brushes */
-	c_unique = 0;
-	c_clusters = 0;
-	for( b = e->brushes; b; b = b->next )
-	{
-		if( !b->detail )
-			continue;
-		c_unique++;
-		newb = CopyBrush( b );
-		r = FilterBrushIntoTree_r( newb, tree->headnode );
-		c_clusters += r;
-		
-		/* mark all sides as visible so drawsurfs are created */
-		if( r )
-		{
-			for( i = 0; i < b->numsides; i++ )
-			{
-				if( b->sides[ i ].winding )
-					b->sides[ i ].visible = qtrue;
-			}
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d detail brushes\n", c_unique );
-	Sys_FPrintf( SYS_VRB, "%9d cluster references\n", c_clusters );
-}
-
-/*
-=====================
-FilterStructuralBrushesIntoTree
-
-Mark the leafs as opaque and areaportals
-=====================
-*/
-void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
-	brush_t			*b, *newb;
-	int					r;
-	int					c_unique, c_clusters;
-	int					i;
-
-	Sys_FPrintf (SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n");
-
-	c_unique = 0;
-	c_clusters = 0;
-	for ( b = e->brushes ; b ; b = b->next ) {
-		if ( b->detail ) {
-			continue;
-		}
-		c_unique++;
-		newb = CopyBrush( b );
-		r = FilterBrushIntoTree_r( newb, tree->headnode );
-		c_clusters += r;
-
-		// mark all sides as visible so drawsurfs are created
-		if ( r ) {
-			for ( i = 0 ; i < b->numsides ; i++ ) {
-				if ( b->sides[i].winding ) {
-					b->sides[i].visible = qtrue;
-				}
-			}
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d structural brushes\n", c_unique );
-	Sys_FPrintf( SYS_VRB, "%9d cluster references\n", c_clusters );
-}
-
-
-
-/*
-================
-AllocTree
-================
-*/
-tree_t *AllocTree (void)
-{
-	tree_t	*tree;
-
-	tree = safe_malloc(sizeof(*tree));
-	memset (tree, 0, sizeof(*tree));
-	ClearBounds (tree->mins, tree->maxs);
-
-	return tree;
-}
-
-/*
-================
-AllocNode
-================
-*/
-node_t *AllocNode (void)
-{
-	node_t	*node;
-
-	node = safe_malloc(sizeof(*node));
-	memset (node, 0, sizeof(*node));
-
-	return node;
-}
-
-
-/*
-================
-WindingIsTiny
-
-Returns true if the winding would be crunched out of
-existance by the vertex snapping.
-================
-*/
-#define	EDGE_LENGTH	0.2
-qboolean WindingIsTiny (winding_t *w)
-{
-/*
-	if (WindingArea (w) < 1)
-		return qtrue;
-	return qfalse;
-*/
-	int		i, j;
-	vec_t	len;
-	vec3_t	delta;
-	int		edges;
-
-	edges = 0;
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		j = i == w->numpoints - 1 ? 0 : i+1;
-		VectorSubtract (w->p[j], w->p[i], delta);
-		len = VectorLength (delta);
-		if (len > EDGE_LENGTH)
-		{
-			if (++edges == 3)
-				return qfalse;
-		}
-	}
-	return qtrue;
-}
-
-/*
-================
-WindingIsHuge
-
-Returns true if the winding still has one of the points
-from basewinding for plane
-================
-*/
-qboolean WindingIsHuge (winding_t *w)
-{
-	int		i, j;
-
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		for (j=0 ; j<3 ; j++)
-			if (w->p[i][j] <= MIN_WORLD_COORD || w->p[i][j] >= MAX_WORLD_COORD)
-				return qtrue;
-	}
-	return qfalse;
-}
-
-//============================================================
-
-/*
-==================
-BrushMostlyOnSide
-
-==================
-*/
-int BrushMostlyOnSide (brush_t *brush, plane_t *plane)
-{
-	int			i, j;
-	winding_t	*w;
-	vec_t		d, max;
-	int			side;
-
-	max = 0;
-	side = PSIDE_FRONT;
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			d = DotProduct (w->p[j], plane->normal) - plane->dist;
-			if (d > max)
-			{
-				max = d;
-				side = PSIDE_FRONT;
-			}
-			if (-d > max)
-			{
-				max = -d;
-				side = PSIDE_BACK;
-			}
-		}
-	}
-	return side;
-}
-
-
-
-/*
-SplitBrush()
-generates two new brushes, leaving the original unchanged
-*/
-
-void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
-{
-	brush_t		*b[2];
-	int			i, j;
-	winding_t	*w, *cw[2], *midwinding;
-	plane_t		*plane, *plane2;
-	side_t		*s, *cs;
-	float		d, d_front, d_back;
-	
-	
-	*front = NULL;
-	*back = NULL;
-	plane = &mapplanes[planenum];
-	
-	// check all points
-	d_front = d_back = 0;
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		w = brush->sides[i].winding;
-		if (!w)
-			continue;
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			d = DotProduct (w->p[j], plane->normal) - plane->dist;
-			if (d > 0 && d > d_front)
-				d_front = d;
-			if (d < 0 && d < d_back)
-				d_back = d;
-		}
-	}
-	
-	if (d_front < 0.1) // PLANESIDE_EPSILON)
-	{	// only on back
-		*back = CopyBrush( brush );
-		return;
-	}
-	
-	if (d_back > -0.1) // PLANESIDE_EPSILON)
-	{	// only on front
-		*front = CopyBrush( brush );
-		return;
-	}
-	
-	// create a new winding from the split plane
-	w = BaseWindingForPlane (plane->normal, plane->dist);
-	for (i=0 ; i<brush->numsides && w ; i++)
-	{
-		if ( brush->sides[i].backSide ) {
-			continue;	// fake back-sided polygons never split
-		}
-		plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
-		ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
-	}
-
-	if (!w || WindingIsTiny (w) )
-	{	// the brush isn't really split
-		int		side;
-
-		side = BrushMostlyOnSide (brush, plane);
-		if (side == PSIDE_FRONT)
-			*front = CopyBrush (brush);
-		if (side == PSIDE_BACK)
-			*back = CopyBrush (brush);
-		return;
-	}
-	
-	if( WindingIsHuge( w ) )
-		Sys_FPrintf( SYS_VRB,"WARNING: huge winding\n" );
-
-	midwinding = w;
-
-	// split it for real
-
-	for (i=0 ; i<2 ; i++)
-	{
-		b[i] = AllocBrush (brush->numsides+1);
-		memcpy( b[i], brush, sizeof( brush_t ) - sizeof( brush->sides ) );
-		b[i]->numsides = 0;
-		b[i]->next = NULL;
-		b[i]->original = brush->original;
-	}
-
-	// split all the current windings
-
-	for (i=0 ; i<brush->numsides ; i++)
-	{
-		s = &brush->sides[i];
-		w = s->winding;
-		if (!w)
-			continue;
-		ClipWindingEpsilon (w, plane->normal, plane->dist,
-			0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
-		for (j=0 ; j<2 ; j++)
-		{
-			if (!cw[j])
-				continue;
-			cs = &b[j]->sides[b[j]->numsides];
-			b[j]->numsides++;
-			*cs = *s;
-			cs->winding = cw[j];
-		}
-	}
-
-
-	// see if we have valid polygons on both sides
-	for (i=0 ; i<2 ; i++)
-	{
-		BoundBrush (b[i]);
-		for (j=0 ; j<3 ; j++)
-		{
-			if (b[i]->mins[j] < MIN_WORLD_COORD || b[i]->maxs[j] > MAX_WORLD_COORD)
-			{
-				Sys_FPrintf (SYS_VRB,"bogus brush after clip\n");
-				break;
-			}
-		}
-
-		if (b[i]->numsides < 3 || j < 3)
-		{
-			FreeBrush (b[i]);
-			b[i] = NULL;
-		}
-	}
-	
-	if ( !(b[0] && b[1]) )
-	{
-		if (!b[0] && !b[1])
-			Sys_FPrintf (SYS_VRB,"split removed brush\n");
-		else
-			Sys_FPrintf (SYS_VRB,"split not on both sides\n");
-		if (b[0])
-		{
-			FreeBrush (b[0]);
-			*front = CopyBrush (brush);
-		}
-		if (b[1])
-		{
-			FreeBrush (b[1]);
-			*back = CopyBrush (brush);
-		}
-		return;
-	}
-	
-	// add the midwinding to both sides
-	for (i=0 ; i<2 ; i++)
-	{
-		cs = &b[i]->sides[b[i]->numsides];
-		b[i]->numsides++;
-
-		cs->planenum = planenum^i^1;
-		cs->shaderInfo = NULL;
-		if (i==0)
-			cs->winding = CopyWinding (midwinding);
-		else
-			cs->winding = midwinding;
-	}
-	
-	{
-		vec_t	v1;
-		int		i;
-		
-		
-		for (i=0 ; i<2 ; i++)
-		{
-			v1 = BrushVolume (b[i]);
-			if (v1 < 1.0)
-			{
-				FreeBrush (b[i]);
-				b[i] = NULL;
-	//			Sys_FPrintf (SYS_VRB,"tiny volume after clip\n");
-			}
-		}
-	}
-	
-	*front = b[0];
-	*back = b[1];
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define BRUSH_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* -------------------------------------------------------------------------------
+
+functions
+
+------------------------------------------------------------------------------- */
+
+/*
+AllocSideRef() - ydnar
+allocates and assigns a brush side reference
+*/
+
+sideRef_t *AllocSideRef( side_t *side, sideRef_t *next )
+{
+	sideRef_t *sideRef;
+	
+	
+	/* dummy check */
+	if( side == NULL )
+		return next;
+	
+	/* allocate and return */
+	sideRef = safe_malloc( sizeof( *sideRef ) );
+	sideRef->side = side;
+	sideRef->next = next;
+	return sideRef;
+}
+
+
+
+/*
+CountBrushList()
+counts the number of brushes in a brush linked list
+*/
+
+int	CountBrushList( brush_t *brushes )
+{
+	int	c = 0;
+	
+	
+	/* count brushes */
+	for( brushes; brushes != NULL; brushes = brushes->next )
+		c++;
+	return c;
+}
+
+
+
+/*
+AllocBrush()
+allocates a new brush
+*/
+
+brush_t *AllocBrush( int numSides )
+{
+	brush_t		*bb;
+	int			c;
+	
+	
+	/* allocate and clear */
+	if( numSides <= 0 )
+		Error( "AllocBrush called with numsides = %d", numSides );
+	c = (int) &(((brush_t*) 0)->sides[ numSides ]);
+	bb = safe_malloc( c );
+	memset( bb, 0, c );
+	if( numthreads == 1 )
+		numActiveBrushes++;
+	
+	/* return it */
+	return bb;
+}
+
+
+
+/*
+FreeBrush()
+frees a single brush and all sides/windings
+*/
+
+void FreeBrush( brush_t *b )
+{
+	int			i;
+	
+	
+	/* error check */
+	if( *((int*) b) == 0xFEFEFEFE )
+	{
+		Sys_FPrintf( SYS_VRB, "WARNING: Attempt to free an already freed brush!\n" );
+		return;
+	}
+	
+	/* free brush sides */
+	for( i = 0; i < b->numsides; i++ )
+		if( b->sides[i].winding != NULL )
+			FreeWinding( b->sides[ i ].winding );
+	
+	/* ydnar: overwrite it */
+	memset( b, 0xFE, (int) &(((brush_t*) 0)->sides[ b->numsides ]) );
+	*((int*) b) = 0xFEFEFEFE;
+	
+	/* free it */
+	free( b );
+	if( numthreads == 1 )
+		numActiveBrushes--;
+}
+
+
+
+/*
+FreeBrushList()
+frees a linked list of brushes
+*/
+
+void FreeBrushList( brush_t *brushes )
+{
+	brush_t		*next;
+	
+	
+	/* walk brush list */
+	for( brushes; brushes != NULL; brushes = next )
+	{
+		next = brushes->next;
+		FreeBrush( brushes );
+	}		
+}
+
+
+
+/*
+CopyBrush()
+duplicates the brush, sides, and windings
+*/
+
+brush_t *CopyBrush( brush_t *brush )
+{
+	brush_t		*newBrush;
+	int			size;
+	int			i;
+	
+	
+	/* copy brush */
+	size = (int) &(((brush_t*) 0)->sides[ brush->numsides ]);
+	newBrush = AllocBrush( brush->numsides );
+	memcpy( newBrush, brush, size );
+	
+	/* ydnar: nuke linked list */
+	newBrush->next = NULL;
+	
+	/* copy sides */
+	for( i = 0; i < brush->numsides; i++ )
+	{
+		if( brush->sides[ i ].winding != NULL )
+			newBrush->sides[ i ].winding = CopyWinding( brush->sides[ i ].winding );
+	}
+	
+	/* return it */
+	return newBrush;
+}
+
+
+
+
+/*
+BoundBrush()
+sets the mins/maxs based on the windings
+returns false if the brush doesn't enclose a valid volume
+*/
+
+qboolean BoundBrush( brush_t *brush )
+{
+	int			i, j;
+	winding_t	*w;
+	
+	
+	ClearBounds( brush->mins, brush->maxs );
+	for( i = 0; i < brush->numsides; i++ )
+	{
+		w = brush->sides[ i ].winding;
+		if( w == NULL )
+			continue;
+		for( j = 0; j < w->numpoints; j++ )
+			AddPointToBounds( w->p[ j ], brush->mins, brush->maxs );
+	}
+	
+	for( i = 0; i < 3; i++ )
+	{
+		if( brush->mins[ i ] < MIN_WORLD_COORD || brush->maxs[ i ] > MAX_WORLD_COORD || brush->mins[i] >= brush->maxs[ i ] )
+			return qfalse;
+	}
+	
+	return qtrue;
+}
+
+
+
+
+/*
+SnapWeldVector() - ydnar
+welds two vec3_t's into a third, taking into account nearest-to-integer
+instead of averaging
+*/
+
+#define SNAP_EPSILON	0.01
+
+void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out )
+{
+	int		i;
+	vec_t	ai, bi, outi;
+	
+	
+	/* dummy check */
+	if( a == NULL || b == NULL || out == NULL )
+		return;
+	
+	/* do each element */
+	for( i = 0; i < 3; i++ )
+	{
+		/* round to integer */
+		ai = Q_rint( a[ i ] );
+		bi = Q_rint( a[ i ] );
+		
+		/* prefer exact integer */
+		if( ai == a[ i ] )
+			out[ i ] = a[ i ];
+		else if( bi == b[ i ] )
+			out[ i ] = b[ i ];
+
+		/* use nearest */
+		else if( fabs( ai - a[ i ] ) < fabs( bi < b[ i ] ) )
+			out[ i ] = a[ i ];
+		else
+			out[ i ] = b[ i ];
+		
+		/* snap */
+		outi = Q_rint( out[ i ] );
+		if( fabs( outi - out[ i ] ) <= SNAP_EPSILON )
+			out[ i ] = outi;
+	}
+}
+
+
+
+/*
+FixWinding() - ydnar
+removes degenerate edges from a winding
+returns qtrue if the winding is valid
+*/
+
+#define DEGENERATE_EPSILON	0.1
+
+qboolean FixWinding( winding_t *w )
+{
+	qboolean	valid = qtrue;
+	int			i, j, k;
+	vec3_t		vec;
+	float		dist;
+	
+	
+	/* dummy check */
+	if( !w )
+		return qfalse;
+	
+	/* check all verts */
+	for( i = 0; i < w->numpoints; i++ )
+	{
+		/* don't remove points if winding is a triangle */
+		if( w->numpoints == 3 )
+			return valid;
+		
+		/* get second point index */
+		j = (i + 1) % w->numpoints;
+		
+		/* degenerate edge? */
+		VectorSubtract( w->p[ i ], w->p[ j ], vec );
+		dist = VectorLength( vec );
+		if( dist < DEGENERATE_EPSILON )
+		{
+			valid = qfalse;
+			//Sys_FPrintf( SYS_VRB, "WARNING: Degenerate winding edge found, fixing...\n" );
+			
+			/* create an average point (ydnar 2002-01-26: using nearest-integer weld preference) */
+			SnapWeldVector( w->p[ i ], w->p[ j ], vec );
+			VectorCopy( vec, w->p[ i ] );
+			//VectorAdd( w->p[ i ], w->p[ j ], vec );
+			//VectorScale( vec, 0.5, w->p[ i ] );
+			
+			/* move the remaining verts */
+			for( k = i + 2; k < w->numpoints; k++ )
+			{
+				VectorCopy( w->p[ k ], w->p[ k - 1 ] );
+			}
+			w->numpoints--;
+		}
+	}
+	
+	/* one last check and return */
+	if( w->numpoints < 3 )
+		valid = qfalse;
+	return valid;
+}
+
+
+
+
+
+
+
+/*
+CreateBrushWindings()
+makes basewindigs for sides and mins/maxs for the brush
+returns false if the brush doesn't enclose a valid volume
+*/
+
+qboolean CreateBrushWindings( brush_t *brush )
+{
+	int			i, j;
+	winding_t	*w;
+	side_t		*side;
+	plane_t		*plane;
+	
+	
+	/* walk the list of brush sides */
+	for( i = 0; i < brush->numsides; i++ )
+	{
+		/* get side and plane */
+		side = &brush->sides[ i ];
+		plane = &mapplanes[ side->planenum ];
+		
+		/* make huge winding */
+		w = BaseWindingForPlane( plane->normal, plane->dist );
+		
+		/* walk the list of brush sides */
+		for( j = 0; j < brush->numsides && w != NULL; j++ )
+		{
+			if( i == j )
+				continue;
+			if( brush->sides[ j ].planenum == (brush->sides[ i ].planenum ^ 1) )
+				continue;		/* back side clipaway */
+			if( brush->sides[ j ].bevel )
+				continue;
+			if( brush->sides[ j ].backSide )
+				continue;
+			plane = &mapplanes[ brush->sides[ j ].planenum ^ 1 ];
+			ChopWindingInPlace( &w, plane->normal, plane->dist, 0 ); // CLIP_EPSILON );
+			
+			/* ydnar: fix broken windings that would generate trifans */
+			FixWinding( w );
+		}
+		
+		/* set side winding */
+		side->winding = w;
+	}
+	
+	/* find brush bounds */
+	return BoundBrush( brush );
+}
+
+
+
+
+/*
+==================
+BrushFromBounds
+
+Creates a new axial brush
+==================
+*/
+brush_t	*BrushFromBounds (vec3_t mins, vec3_t maxs)
+{
+	brush_t		*b;
+	int			i;
+	vec3_t		normal;
+	vec_t		dist;
+
+	b = AllocBrush (6);
+	b->numsides = 6;
+	for (i=0 ; i<3 ; i++)
+	{
+		VectorClear (normal);
+		normal[i] = 1;
+		dist = maxs[i];
+		b->sides[i].planenum = FindFloatPlane (normal, dist, 1, (vec3_t*) &maxs );
+
+		normal[i] = -1;
+		dist = -mins[i];
+		b->sides[3+i].planenum = FindFloatPlane (normal, dist, 1, (vec3_t*) &mins );
+	}
+
+	CreateBrushWindings (b);
+
+	return b;
+}
+
+/*
+==================
+BrushVolume
+
+==================
+*/
+vec_t BrushVolume (brush_t *brush)
+{
+	int			i;
+	winding_t	*w;
+	vec3_t		corner;
+	vec_t		d, area, volume;
+	plane_t		*plane;
+
+	if (!brush)
+		return 0;
+
+	// grab the first valid point as the corner
+
+	w = NULL;
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (w)
+			break;
+	}
+	if (!w)
+		return 0;
+	VectorCopy (w->p[0], corner);
+
+	// make tetrahedrons to all other faces
+
+	volume = 0;
+	for ( ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		plane = &mapplanes[brush->sides[i].planenum];
+		d = -(DotProduct (corner, plane->normal) - plane->dist);
+		area = WindingArea (w);
+		volume += d*area;
+	}
+
+	volume /= 3;
+	return volume;
+}
+
+
+
+/*
+WriteBSPBrushMap()
+writes a map with the split bsp brushes
+*/
+
+void WriteBSPBrushMap( char *name, brush_t *list )
+{
+	FILE		*f;
+	side_t		*s;
+	int			i;
+	winding_t	*w;
+	
+	
+	/* note it */
+	Sys_Printf( "Writing %s\n", name );
+	
+	/* open the map file */
+	f = fopen( name, "wb" );
+	if( f == NULL )
+		Error( "Can't write %s\b", name );
+
+	fprintf (f, "{\n\"classname\" \"worldspawn\"\n");
+
+	for ( ; list ; list=list->next )
+	{
+		fprintf (f, "{\n");
+		for (i=0,s=list->sides ; i<list->numsides ; i++,s++)
+		{
+			w = BaseWindingForPlane (mapplanes[s->planenum].normal, mapplanes[s->planenum].dist);
+
+			fprintf (f,"( %i %i %i ) ", (int)w->p[0][0], (int)w->p[0][1], (int)w->p[0][2]);
+			fprintf (f,"( %i %i %i ) ", (int)w->p[1][0], (int)w->p[1][1], (int)w->p[1][2]);
+			fprintf (f,"( %i %i %i ) ", (int)w->p[2][0], (int)w->p[2][1], (int)w->p[2][2]);
+
+			fprintf (f, "notexture 0 0 0 1 1\n" );
+			FreeWinding (w);
+		}
+		fprintf (f, "}\n");
+	}
+	fprintf (f, "}\n");
+
+	fclose (f);
+
+}
+
+
+
+/*
+FilterBrushIntoTree_r()
+adds brush reference to any intersecting bsp leafnode
+*/
+
+int FilterBrushIntoTree_r( brush_t *b, node_t *node )
+{
+	brush_t		*front, *back;
+	int			c;
+	
+	
+	/* dummy check */
+	if( b == NULL )
+		return 0;
+	
+	/* add it to the leaf list */
+	if( node->planenum == PLANENUM_LEAF )
+	{
+		/* something somewhere is hammering brushlist */
+		b->next = node->brushlist;
+		node->brushlist = b;
+		
+		/* classify the leaf by the structural brush */
+		if( !b->detail )
+		{
+			if( b->opaque )
+			{
+				node->opaque = qtrue;
+				node->areaportal = qfalse;
+			}
+			else if( b->compileFlags & C_AREAPORTAL )
+			{
+				if( !node->opaque )
+					node->areaportal = qtrue;
+			}
+		}
+		
+		return 1;
+	}
+	
+	/* split it by the node plane */
+	c = b->numsides;
+	SplitBrush( b, node->planenum, &front, &back );
+	FreeBrush( b );
+	
+	c = 0;
+	c += FilterBrushIntoTree_r( front, node->children[ 0 ] );
+	c += FilterBrushIntoTree_r( back, node->children[ 1 ] );
+	
+	return c;
+}
+
+
+
+/*
+FilterDetailBrushesIntoTree
+fragment all the detail brushes into the structural leafs
+*/
+
+void FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree )
+{
+	brush_t				*b, *newb;
+	int					r;
+	int					c_unique, c_clusters;
+	int					i;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB,  "--- FilterDetailBrushesIntoTree ---\n" );
+	
+	/* walk the list of brushes */
+	c_unique = 0;
+	c_clusters = 0;
+	for( b = e->brushes; b; b = b->next )
+	{
+		if( !b->detail )
+			continue;
+		c_unique++;
+		newb = CopyBrush( b );
+		r = FilterBrushIntoTree_r( newb, tree->headnode );
+		c_clusters += r;
+		
+		/* mark all sides as visible so drawsurfs are created */
+		if( r )
+		{
+			for( i = 0; i < b->numsides; i++ )
+			{
+				if( b->sides[ i ].winding )
+					b->sides[ i ].visible = qtrue;
+			}
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d detail brushes\n", c_unique );
+	Sys_FPrintf( SYS_VRB, "%9d cluster references\n", c_clusters );
+}
+
+/*
+=====================
+FilterStructuralBrushesIntoTree
+
+Mark the leafs as opaque and areaportals
+=====================
+*/
+void FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree ) {
+	brush_t			*b, *newb;
+	int					r;
+	int					c_unique, c_clusters;
+	int					i;
+
+	Sys_FPrintf (SYS_VRB, "--- FilterStructuralBrushesIntoTree ---\n");
+
+	c_unique = 0;
+	c_clusters = 0;
+	for ( b = e->brushes ; b ; b = b->next ) {
+		if ( b->detail ) {
+			continue;
+		}
+		c_unique++;
+		newb = CopyBrush( b );
+		r = FilterBrushIntoTree_r( newb, tree->headnode );
+		c_clusters += r;
+
+		// mark all sides as visible so drawsurfs are created
+		if ( r ) {
+			for ( i = 0 ; i < b->numsides ; i++ ) {
+				if ( b->sides[i].winding ) {
+					b->sides[i].visible = qtrue;
+				}
+			}
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d structural brushes\n", c_unique );
+	Sys_FPrintf( SYS_VRB, "%9d cluster references\n", c_clusters );
+}
+
+
+
+/*
+================
+AllocTree
+================
+*/
+tree_t *AllocTree (void)
+{
+	tree_t	*tree;
+
+	tree = safe_malloc(sizeof(*tree));
+	memset (tree, 0, sizeof(*tree));
+	ClearBounds (tree->mins, tree->maxs);
+
+	return tree;
+}
+
+/*
+================
+AllocNode
+================
+*/
+node_t *AllocNode (void)
+{
+	node_t	*node;
+
+	node = safe_malloc(sizeof(*node));
+	memset (node, 0, sizeof(*node));
+
+	return node;
+}
+
+
+/*
+================
+WindingIsTiny
+
+Returns true if the winding would be crunched out of
+existance by the vertex snapping.
+================
+*/
+#define	EDGE_LENGTH	0.2
+qboolean WindingIsTiny (winding_t *w)
+{
+/*
+	if (WindingArea (w) < 1)
+		return qtrue;
+	return qfalse;
+*/
+	int		i, j;
+	vec_t	len;
+	vec3_t	delta;
+	int		edges;
+
+	edges = 0;
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		j = i == w->numpoints - 1 ? 0 : i+1;
+		VectorSubtract (w->p[j], w->p[i], delta);
+		len = VectorLength (delta);
+		if (len > EDGE_LENGTH)
+		{
+			if (++edges == 3)
+				return qfalse;
+		}
+	}
+	return qtrue;
+}
+
+/*
+================
+WindingIsHuge
+
+Returns true if the winding still has one of the points
+from basewinding for plane
+================
+*/
+qboolean WindingIsHuge (winding_t *w)
+{
+	int		i, j;
+
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		for (j=0 ; j<3 ; j++)
+			if (w->p[i][j] <= MIN_WORLD_COORD || w->p[i][j] >= MAX_WORLD_COORD)
+				return qtrue;
+	}
+	return qfalse;
+}
+
+//============================================================
+
+/*
+==================
+BrushMostlyOnSide
+
+==================
+*/
+int BrushMostlyOnSide (brush_t *brush, plane_t *plane)
+{
+	int			i, j;
+	winding_t	*w;
+	vec_t		d, max;
+	int			side;
+
+	max = 0;
+	side = PSIDE_FRONT;
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			d = DotProduct (w->p[j], plane->normal) - plane->dist;
+			if (d > max)
+			{
+				max = d;
+				side = PSIDE_FRONT;
+			}
+			if (-d > max)
+			{
+				max = -d;
+				side = PSIDE_BACK;
+			}
+		}
+	}
+	return side;
+}
+
+
+
+/*
+SplitBrush()
+generates two new brushes, leaving the original unchanged
+*/
+
+void SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back )
+{
+	brush_t		*b[2];
+	int			i, j;
+	winding_t	*w, *cw[2], *midwinding;
+	plane_t		*plane, *plane2;
+	side_t		*s, *cs;
+	float		d, d_front, d_back;
+	
+	
+	*front = NULL;
+	*back = NULL;
+	plane = &mapplanes[planenum];
+	
+	// check all points
+	d_front = d_back = 0;
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		w = brush->sides[i].winding;
+		if (!w)
+			continue;
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			d = DotProduct (w->p[j], plane->normal) - plane->dist;
+			if (d > 0 && d > d_front)
+				d_front = d;
+			if (d < 0 && d < d_back)
+				d_back = d;
+		}
+	}
+	
+	if (d_front < 0.1) // PLANESIDE_EPSILON)
+	{	// only on back
+		*back = CopyBrush( brush );
+		return;
+	}
+	
+	if (d_back > -0.1) // PLANESIDE_EPSILON)
+	{	// only on front
+		*front = CopyBrush( brush );
+		return;
+	}
+	
+	// create a new winding from the split plane
+	w = BaseWindingForPlane (plane->normal, plane->dist);
+	for (i=0 ; i<brush->numsides && w ; i++)
+	{
+		if ( brush->sides[i].backSide ) {
+			continue;	// fake back-sided polygons never split
+		}
+		plane2 = &mapplanes[brush->sides[i].planenum ^ 1];
+		ChopWindingInPlace (&w, plane2->normal, plane2->dist, 0); // PLANESIDE_EPSILON);
+	}
+
+	if (!w || WindingIsTiny (w) )
+	{	// the brush isn't really split
+		int		side;
+
+		side = BrushMostlyOnSide (brush, plane);
+		if (side == PSIDE_FRONT)
+			*front = CopyBrush (brush);
+		if (side == PSIDE_BACK)
+			*back = CopyBrush (brush);
+		return;
+	}
+	
+	if( WindingIsHuge( w ) )
+		Sys_FPrintf( SYS_VRB,"WARNING: huge winding\n" );
+
+	midwinding = w;
+
+	// split it for real
+
+	for (i=0 ; i<2 ; i++)
+	{
+		b[i] = AllocBrush (brush->numsides+1);
+		memcpy( b[i], brush, sizeof( brush_t ) - sizeof( brush->sides ) );
+		b[i]->numsides = 0;
+		b[i]->next = NULL;
+		b[i]->original = brush->original;
+	}
+
+	// split all the current windings
+
+	for (i=0 ; i<brush->numsides ; i++)
+	{
+		s = &brush->sides[i];
+		w = s->winding;
+		if (!w)
+			continue;
+		ClipWindingEpsilon (w, plane->normal, plane->dist,
+			0 /*PLANESIDE_EPSILON*/, &cw[0], &cw[1]);
+		for (j=0 ; j<2 ; j++)
+		{
+			if (!cw[j])
+				continue;
+			cs = &b[j]->sides[b[j]->numsides];
+			b[j]->numsides++;
+			*cs = *s;
+			cs->winding = cw[j];
+		}
+	}
+
+
+	// see if we have valid polygons on both sides
+	for (i=0 ; i<2 ; i++)
+	{
+		BoundBrush (b[i]);
+		for (j=0 ; j<3 ; j++)
+		{
+			if (b[i]->mins[j] < MIN_WORLD_COORD || b[i]->maxs[j] > MAX_WORLD_COORD)
+			{
+				Sys_FPrintf (SYS_VRB,"bogus brush after clip\n");
+				break;
+			}
+		}
+
+		if (b[i]->numsides < 3 || j < 3)
+		{
+			FreeBrush (b[i]);
+			b[i] = NULL;
+		}
+	}
+	
+	if ( !(b[0] && b[1]) )
+	{
+		if (!b[0] && !b[1])
+			Sys_FPrintf (SYS_VRB,"split removed brush\n");
+		else
+			Sys_FPrintf (SYS_VRB,"split not on both sides\n");
+		if (b[0])
+		{
+			FreeBrush (b[0]);
+			*front = CopyBrush (brush);
+		}
+		if (b[1])
+		{
+			FreeBrush (b[1]);
+			*back = CopyBrush (brush);
+		}
+		return;
+	}
+	
+	// add the midwinding to both sides
+	for (i=0 ; i<2 ; i++)
+	{
+		cs = &b[i]->sides[b[i]->numsides];
+		b[i]->numsides++;
+
+		cs->planenum = planenum^i^1;
+		cs->shaderInfo = NULL;
+		if (i==0)
+			cs->winding = CopyWinding (midwinding);
+		else
+			cs->winding = midwinding;
+	}
+	
+	{
+		vec_t	v1;
+		int		i;
+		
+		
+		for (i=0 ; i<2 ; i++)
+		{
+			v1 = BrushVolume (b[i]);
+			if (v1 < 1.0)
+			{
+				FreeBrush (b[i]);
+				b[i] = NULL;
+	//			Sys_FPrintf (SYS_VRB,"tiny volume after clip\n");
+			}
+		}
+	}
+	
+	*front = b[0];
+	*back = b[1];
+}
diff --git a/tools/quake3/q3map2/brush_primit.c b/tools/quake3/q3map2/brush_primit.c
index ae0110d6..9bc2ab62 100644
--- a/tools/quake3/q3map2/brush_primit.c
+++ b/tools/quake3/q3map2/brush_primit.c
@@ -1,80 +1,80 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define BRUSH_PRIMIT_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* -------------------------------------------------------------------------------
-
-functions
-
-------------------------------------------------------------------------------- */
-
-/*
-ComputeAxisBase()
-computes the base texture axis for brush primitive texturing
-note: ComputeAxisBase here and in editor code must always BE THE SAME!
-warning: special case behaviour of atan2( y, x ) <-> atan( y / x ) might not be the same everywhere when x == 0
-rotation by (0,RotY,RotZ) assigns X to normal
-*/
-
-void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY )
-{
-	vec_t	RotY, RotZ;
-	
-	
-	/* do some cleaning */
-	if( fabs( normal[ 0 ] ) < 1e-6 )
-		normal[ 0 ]= 0.0f;
-	if( fabs( normal[ 1 ] ) < 1e-6 )
-		normal[ 1 ]=0.0f;
-	if( fabs( normal[ 2 ] ) < 1e-6 )
-		normal[ 2 ] = 0.0f;
-	
-	/* compute the two rotations around y and z to rotate x to normal */
-	RotY = -atan2( normal[ 2 ], sqrt( normal[ 1 ] * normal[ 1 ] + normal[ 0 ] * normal[ 0 ]) );
-	RotZ = atan2( normal[ 1 ], normal[ 0 ] );
-	
-	/* rotate (0,1,0) and (0,0,1) to compute texX and texY */
-	texX[ 0 ] = -sin( RotZ );
-	texX[ 1 ] = cos( RotZ );
-	texX[ 2 ] = 0;
-	
-	/* the texY vector is along -z (t texture coorinates axis) */
-	texY[ 0 ] = -sin( RotY ) * cos( RotZ );
-	texY[ 1 ] = -sin( RotY ) * sin( RotZ );
-	texY[ 2 ] = -cos( RotY );
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define BRUSH_PRIMIT_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* -------------------------------------------------------------------------------
+
+functions
+
+------------------------------------------------------------------------------- */
+
+/*
+ComputeAxisBase()
+computes the base texture axis for brush primitive texturing
+note: ComputeAxisBase here and in editor code must always BE THE SAME!
+warning: special case behaviour of atan2( y, x ) <-> atan( y / x ) might not be the same everywhere when x == 0
+rotation by (0,RotY,RotZ) assigns X to normal
+*/
+
+void ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY )
+{
+	vec_t	RotY, RotZ;
+	
+	
+	/* do some cleaning */
+	if( fabs( normal[ 0 ] ) < 1e-6 )
+		normal[ 0 ]= 0.0f;
+	if( fabs( normal[ 1 ] ) < 1e-6 )
+		normal[ 1 ]=0.0f;
+	if( fabs( normal[ 2 ] ) < 1e-6 )
+		normal[ 2 ] = 0.0f;
+	
+	/* compute the two rotations around y and z to rotate x to normal */
+	RotY = -atan2( normal[ 2 ], sqrt( normal[ 1 ] * normal[ 1 ] + normal[ 0 ] * normal[ 0 ]) );
+	RotZ = atan2( normal[ 1 ], normal[ 0 ] );
+	
+	/* rotate (0,1,0) and (0,0,1) to compute texX and texY */
+	texX[ 0 ] = -sin( RotZ );
+	texX[ 1 ] = cos( RotZ );
+	texX[ 2 ] = 0;
+	
+	/* the texY vector is along -z (t texture coorinates axis) */
+	texY[ 0 ] = -sin( RotY ) * cos( RotZ );
+	texY[ 1 ] = -sin( RotY ) * sin( RotZ );
+	texY[ 2 ] = -cos( RotY );
+}
diff --git a/tools/quake3/q3map2/bsp.c b/tools/quake3/q3map2/bsp.c
index c73242da..ed3d2430 100644
--- a/tools/quake3/q3map2/bsp.c
+++ b/tools/quake3/q3map2/bsp.c
@@ -1,853 +1,853 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define BSP_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* -------------------------------------------------------------------------------
-
-functions
-
-------------------------------------------------------------------------------- */
-
-
-
-/*
-SetCloneModelNumbers() - ydnar
-sets the model numbers for brush entities
-*/
-
-static void SetCloneModelNumbers( void )
-{
-	int			i, j;
-	int			models;
-	char		modelValue[ 10 ];
-	const char	*value, *value2, *value3;
-	
-	
-	/* start with 1 (worldspawn is model 0) */
-	models = 1;
-	for( i = 1; i < numEntities; i++ )
-	{
-		/* only entities with brushes or patches get a model number */
-		if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
-			continue;
-		
-		/* is this a clone? */
-		value = ValueForKey( &entities[ i ], "_clone" );
-		if( value[ 0 ] != '\0' )
-			continue;
-		
-		/* add the model key */
-		sprintf( modelValue, "*%d", models );
-		SetKeyValue( &entities[ i ], "model", modelValue );
-		
-		/* increment model count */
-		models++;
-	}
-	
-	/* fix up clones */
-	for( i = 1; i < numEntities; i++ )
-	{
-		/* only entities with brushes or patches get a model number */
-		if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
-			continue;
-		
-		/* is this a clone? */
-		value = ValueForKey( &entities[ i ], "_ins" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( &entities[ i ], "_instance" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( &entities[ i ], "_clone" );
-		if( value[ 0 ] == '\0' )
-			continue;
-		
-		/* find an entity with matching clone name */
-		for( j = 0; j < numEntities; j++ )
-		{
-			/* is this a clone parent? */
-			value2 = ValueForKey( &entities[ j ], "_clonename" );
-			if( value2[ 0 ] == '\0' )
-				continue;
-			
-			/* do they match? */
-			if( strcmp( value, value2 ) == 0 )
-			{
-				/* get the model num */
-				value3 = ValueForKey( &entities[ j ], "model" );
-				if( value3[ 0 ] == '\0' )
-				{
-					Sys_Printf( "WARNING: Cloned entity %s referenced entity without model\n", value2 );
-					continue;
-				}
-				models = atoi( &value2[ 1 ] );
-				
-				/* add the model key */
-				sprintf( modelValue, "*%d", models );
-				SetKeyValue( &entities[ i ], "model", modelValue );
-				
-				/* nuke the brushes/patches for this entity (fixme: leak!) */
-				entities[ i ].brushes = NULL;
-				entities[ i ].patches = NULL;
-			}
-		}
-	}
-}
-
-
-
-/*
-FixBrushSides() - ydnar
-matches brushsides back to their appropriate drawsurface and shader
-*/
-
-static void FixBrushSides( entity_t *e )
-{
-	int					i;
-	mapDrawSurface_t	*ds;
-	sideRef_t			*sideRef;
-	bspBrushSide_t		*side;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- FixBrushSides ---\n" );
-	
-	/* walk list of drawsurfaces */
-	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
-	{
-		/* get surface and try to early out */
-		ds = &mapDrawSurfs[ i ];
-		if( ds->outputNum < 0 )
-			continue;
-		
-		/* walk sideref list */
-		for( sideRef = ds->sideRef; sideRef != NULL; sideRef = sideRef->next )
-		{
-			/* get bsp brush side */
-			if( sideRef->side == NULL || sideRef->side->outputNum < 0 )
-				continue;
-			side = &bspBrushSides[ sideRef->side->outputNum ];
-			
-			/* set drawsurface */
-			side->surfaceNum = ds->outputNum;
-			//%	Sys_FPrintf( SYS_VRB, "DS: %7d Side: %7d     ", ds->outputNum, sideRef->side->outputNum );
-			
-			/* set shader */
-			if( strcmp( bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader ) )
-			{
-				//%	Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader );
-				side->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
-			}
-		}
-	}
-}
-
-
-
-/*
-ProcessWorldModel()
-creates a full bsp + surfaces for the worldspawn entity
-*/
-
-void ProcessWorldModel( void )
-{
-	int			i, s;
-	entity_t	*e;
-	tree_t		*tree;
-	face_t		*faces;
-	qboolean	ignoreLeaks, leaked;
-	xmlNodePtr	polyline, leaknode;
-	char		level[ 2 ], shader[ 1024 ];
-	const char	*value;
-	
-	
-	/* sets integer blockSize from worldspawn "_blocksize" key if it exists */
-	value = ValueForKey( &entities[ 0 ], "_blocksize" );
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( &entities[ 0 ], "blocksize" );
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( &entities[ 0 ], "chopsize" );	/* sof2 */
-	if( value[ 0 ] != '\0' )
-	{
-		/* scan 3 numbers */
-		s = sscanf( value, "%d %d %d", &blockSize[ 0 ], &blockSize[ 1 ], &blockSize[ 2 ] );
-		
-		/* handle legacy case */
-		if( s == 1 )
-		{
-			blockSize[ 1 ] = blockSize[ 0 ];
-			blockSize[ 2 ] = blockSize[ 0 ];
-		}
-	}
-	Sys_Printf( "block size = { %d %d %d }\n", blockSize[ 0 ], blockSize[ 1 ], blockSize[ 2 ] );
-	
-	/* sof2: ignore leaks? */
-	value = ValueForKey( &entities[ 0 ], "_ignoreleaks" );	/* ydnar */
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( &entities[ 0 ], "ignoreleaks" );
-	if( value[ 0 ] == '1' )
-		ignoreLeaks = qtrue;
-	else
-		ignoreLeaks = qfalse;
-	
-	/* begin worldspawn model */
-	BeginModel();
-	e = &entities[ 0 ];
-	e->firstDrawSurf = 0;
-	
-	/* ydnar: gs mods */
-	ClearMetaTriangles();
-
-	/* check for patches with adjacent edges that need to lod together */
-	PatchMapDrawSurfs( e );
-
-	/* build an initial bsp tree using all of the sides of all of the structural brushes */
-	faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
-	tree = FaceBSP( faces );
-	MakeTreePortals( tree );
-	FilterStructuralBrushesIntoTree( e, tree );
-	
-	/* see if the bsp is completely enclosed */
-	if( FloodEntities( tree ) || ignoreLeaks )
-	{
-		/* rebuild a better bsp tree using only the sides that are visible from the inside */
-		FillOutside( tree->headnode );
-
-		/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
-		ClipSidesIntoTree( e, tree );
-		
-		/* build a visible face tree */
-		faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes );
-		FreeTree( tree );
-		tree = FaceBSP( faces );
-		MakeTreePortals( tree );
-		FilterStructuralBrushesIntoTree( e, tree );
-		leaked = qfalse;
-		
-		/* ydnar: flood again for skybox */
-		if( skyboxPresent )
-			FloodEntities( tree );
-	}
-	else
-	{
-		Sys_FPrintf( SYS_NOXML, "**********************\n" );
-		Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
-		Sys_FPrintf( SYS_NOXML, "**********************\n" );
-		polyline = LeakFile( tree );
-		leaknode = xmlNewNode( NULL, "message" );
-		xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
-		xmlAddChild( leaknode, polyline );
-		level[0] = (int) '0' + SYS_ERR;
-		level[1] = 0;
-		xmlSetProp( leaknode, "level", (char*) &level );
-		xml_SendNode( leaknode );
-		if( leaktest )
-		{
-			Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
-			exit( 0 );
-		}
-		leaked = qtrue;
-		
-		/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
-		ClipSidesIntoTree( e, tree );
-	}
-	
-	/* save out information for visibility processing */
-	NumberClusters( tree );
-	if( !leaked )
-		WritePortalFile( tree );
-	
-	/* flood from entities */
-	FloodAreas( tree );
-	
-	/* create drawsurfs for triangle models */
-	AddTriangleModels( e );
-	
-	/* create drawsurfs for surface models */
-	AddEntitySurfaceModels( e );
-	
-	/* generate bsp brushes from map brushes */
-	EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
-	
-	/* add references to the detail brushes */
-	FilterDetailBrushesIntoTree( e, tree );
-	
-	/* drawsurfs that cross fog boundaries will need to be split along the fog boundary */
-	if( !nofog )
-		FogDrawSurfaces( e );
-	
-	/* subdivide each drawsurf as required by shader tesselation */
-	if( !nosubdivide )
-		SubdivideFaceSurfaces( e, tree );
-	
-	/* add in any vertexes required to fix t-junctions */
-	if( !notjunc )
-		FixTJunctions( e );
-	
-	/* ydnar: classify the surfaces */
-	ClassifyEntitySurfaces( e );
-	
-	/* ydnar: project decals */
-	MakeEntityDecals( e );
-	
-	/* ydnar: meta surfaces */
-	MakeEntityMetaTriangles( e );
-	SmoothMetaTriangles();
-	FixMetaTJunctions();
-	MergeMetaTriangles();
-	
-	/* ydnar: debug portals */
-	if( debugPortals )
-		MakeDebugPortalSurfs( tree );
-	
-	/* ydnar: fog hull */
-	value = ValueForKey( &entities[ 0 ], "_foghull" );
-	if( value[ 0 ] != '\0' )
-	{
-		sprintf( shader, "textures/%s", value );
-		MakeFogHullSurfs( e, tree, shader );
-	}
-	
-	/* ydnar: bug 645: do flares for lights */
-	for( i = 0; i < numEntities && emitFlares; i++ )
-	{
-		entity_t	*light, *target;
-		const char	*value, *flareShader;
-		vec3_t		origin, targetOrigin, normal, color;
-		int			lightStyle;
-		
-		
-		/* get light */
-		light = &entities[ i ];
-		value = ValueForKey( light, "classname" );
-		if( !strcmp( value, "light" ) )
-		{
-			/* get flare shader */
-			flareShader = ValueForKey( light, "_flareshader" );
-			value = ValueForKey( light, "_flare" );
-			if( flareShader[ 0 ] != '\0' || value[ 0 ] != '\0' )
-			{
-				/* get specifics */
-				GetVectorForKey( light, "origin", origin );
-				GetVectorForKey( light, "_color", color );
-				lightStyle = IntForKey( light, "_style" );
-				if( lightStyle == 0 )
-					lightStyle = IntForKey( light, "style" );
-				
-				/* handle directional spotlights */
-				value = ValueForKey( light, "target" );
-				if( value[ 0 ] != '\0' )
-				{
-					/* get target light */
-					target = FindTargetEntity( value );
-					if( target != NULL )
-					{
-						GetVectorForKey( target, "origin", targetOrigin );
-						VectorSubtract( targetOrigin, origin, normal );
-						VectorNormalize( normal, normal );
-					}
-				}
-				else
-					//%	VectorClear( normal );
-					VectorSet( normal, 0, 0, -1 );
-				
-				/* create the flare surface (note shader defaults automatically) */
-				DrawSurfaceForFlare( mapEntityNum, origin, normal, color, (char*) flareShader, lightStyle );
-			}
-		}
-	}
-	
-	/* add references to the final drawsurfs in the apropriate clusters */
-	FilterDrawsurfsIntoTree( e, tree );
-	
-	/* match drawsurfaces back to original brushsides (sof2) */
-	FixBrushSides( e );
-	
-	/* finish */
-	EndModel( e, tree->headnode );
-	FreeTree( tree );
-}
-
-
-
-/*
-ProcessSubModel()
-creates bsp + surfaces for other brush models
-*/
-
-void ProcessSubModel( void )
-{
-	entity_t	*e;
-	tree_t		*tree;
-	brush_t		*b, *bc;
-	node_t		*node;
-	
-	
-	/* start a brush model */
-	BeginModel();
-	e = &entities[ mapEntityNum ];
-	e->firstDrawSurf = numMapDrawSurfs;
-	
-	/* ydnar: gs mods */
-	ClearMetaTriangles();
-	
-	/* check for patches with adjacent edges that need to lod together */
-	PatchMapDrawSurfs( e );
-	
-	/* allocate a tree */
-	node = AllocNode();
-	node->planenum = PLANENUM_LEAF;
-	tree = AllocTree();
-	tree->headnode = node;
-	
-	/* add the sides to the tree */
-	ClipSidesIntoTree( e, tree );
-	
-	/* ydnar: create drawsurfs for triangle models */
-	AddTriangleModels( e );
-	
-	/* create drawsurfs for surface models */
-	AddEntitySurfaceModels( e );
-	
-	/* generate bsp brushes from map brushes */
-	EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
-
-	/* just put all the brushes in headnode */
-	for( b = e->brushes; b; b = b->next )
-	{
-		bc = CopyBrush( b );
-		bc->next = node->brushlist;
-		node->brushlist = bc;
-	}
-	
-	/* subdivide each drawsurf as required by shader tesselation */
-	if( !nosubdivide )
-		SubdivideFaceSurfaces( e, tree );
-	
-	/* add in any vertexes required to fix t-junctions */
-	if( !notjunc )
-		FixTJunctions( e );
-	
-	/* ydnar: classify the surfaces and project lightmaps */
-	ClassifyEntitySurfaces( e );
-	
-	/* ydnar: project decals */
-	MakeEntityDecals( e );
-	
-	/* ydnar: meta surfaces */
-	MakeEntityMetaTriangles( e );
-	SmoothMetaTriangles();
-	FixMetaTJunctions();
-	MergeMetaTriangles();
-	
-	/* add references to the final drawsurfs in the apropriate clusters */
-	FilterDrawsurfsIntoTree( e, tree );
-	
-	/* match drawsurfaces back to original brushsides (sof2) */
-	FixBrushSides( e );
-	
-	/* finish */
-	EndModel( e, node );
-	FreeTree( tree );
-}
-
-
-
-/*
-ProcessModels()
-process world + other models into the bsp
-*/
-
-void ProcessModels( void )
-{
-	qboolean	oldVerbose;
-	entity_t	*entity;
-	
-	
-	/* preserve -v setting */
-	oldVerbose = verbose;
-	
-	/* start a new bsp */
-	BeginBSPFile();
-	
-	/* create map fogs */
-	CreateMapFogs();
-	
-	/* walk entity list */
-	for( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
-	{
-		/* get entity */
-		entity = &entities[ mapEntityNum ];
-		if( entity->brushes == NULL && entity->patches == NULL )
-			continue;
-		
-		/* process the model */
-		Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
-		if( mapEntityNum == 0 )
-			ProcessWorldModel();
-		else
-			ProcessSubModel();
-		
-		/* potentially turn off the deluge of text */
-		verbose = verboseEntities;
-	}
-	
-	/* restore -v setting */
-	verbose = oldVerbose;
-	
-	/* write fogs */
-	EmitFogs();
-}
-
-
-
-/*
-OnlyEnts()
-this is probably broken unless teamed with a radiant version that preserves entity order
-*/
-
-void OnlyEnts( void )
-{
-	char out[ 1024 ];
-
-	
-	/* note it */
-	Sys_Printf( "--- OnlyEnts ---\n" );
-	
-	sprintf( out, "%s.bsp", source );
-	LoadBSPFile( out );
-	numEntities = 0;
-
-	LoadShaderInfo();
-	LoadMapFile( name, qfalse );
-	SetModelNumbers();
-	SetLightStyles();
-	
-	numBSPEntities = numEntities;
-	UnparseEntities();
-	
-	WriteBSPFile( out );
-}
-
-
-
-/*
-BSPMain() - ydnar
-handles creation of a bsp from a map file
-*/
-
-int BSPMain( int argc, char **argv )
-{
-	int			i;
-	char		path[ 1024 ], tempSource[ 1024 ];
-	qboolean	onlyents = qfalse;
-	
-	
-	/* note it */
-	Sys_Printf( "--- BSP ---\n" );
-	
-	SetDrawSurfacesBuffer();
-	mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
-	memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
-	numMapDrawSurfs = 0;
-	
-	tempSource[ 0 ] = '\0';
-	
-	/* set flares flag */
-	emitFlares = game->emitFlares;
-	
-	/* process arguments */
-	for( i = 1; i < (argc - 1); i++ )
-	{
-		if( !strcmp( argv[ i ], "-onlyents" ) )
-		{
-			Sys_Printf( "Running entity-only compile\n" );
-			onlyents = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-tempname" ) )
-			strcpy( tempSource, argv[ ++i ] );
-		else if( !strcmp( argv[ i ], "-tmpout" ) )
-			strcpy( outbase, "/tmp" );
-		else if( !strcmp( argv[ i ],  "-nowater" ) )
-		{
-			Sys_Printf( "Disabling water\n" );
-			nowater = qtrue;
-		}
-		else if( !strcmp( argv[ i ],  "-nodetail" ) )
-		{
-			Sys_Printf( "Ignoring detail brushes\n") ;
-			nodetail = qtrue;
-		}
-		else if( !strcmp( argv[ i ],  "-fulldetail" ) )
-		{
-			Sys_Printf( "Turning detail brushes into structural brushes\n" );
-			fulldetail = qtrue;
-		}
-		else if( !strcmp( argv[ i ],  "-nofog" ) )
-		{
-			Sys_Printf( "Fog volumes disabled\n" );
-			nofog = qtrue;
-		}
-		else if( !strcmp( argv[ i ],  "-nosubdivide" ) )
-		{
-			Sys_Printf( "Disabling brush face subdivision\n" );
-			nosubdivide = qtrue;
-		}
-		else if( !strcmp( argv[ i ],  "-leaktest" ) )
-		{
-			Sys_Printf( "Leaktest enabled\n" );
-			leaktest = qtrue;
-		}
-		else if( !strcmp( argv[ i ],  "-verboseentities" ) )
-		{
-			Sys_Printf( "Verbose entities enabled\n" );
-			verboseEntities = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-nocurves" ) )
-		{
-			Sys_Printf( "Ignoring curved surfaces (patches)\n" );
-			noCurveBrushes = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-notjunc" ) )
-		{
-			Sys_Printf( "T-junction fixing disabled\n" );
-			notjunc = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-fakemap" ) )
-		{
-			Sys_Printf( "Generating fakemap.map\n" );
-			fakemap = qtrue;
-		}
-		else if( !strcmp( argv[ i ],  "-samplesize" ) )
- 		{
-			sampleSize = atoi( argv[ i + 1 ] );
-			if( sampleSize < 1 )
-				sampleSize = 1;
- 			i++;
-			Sys_Printf( "Lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
- 		}
-		else if( !strcmp( argv[ i ],  "-custinfoparms") )
-		{
-			Sys_Printf( "Custom info parms enabled\n" );
-			useCustomInfoParms = qtrue;
-		}
-		
-		/* sof2 args */
-		else if( !strcmp( argv[ i ], "-rename" ) )
-		{
-			Sys_Printf( "Appending _bsp suffix to misc_model shaders (SOF2)\n" );
-			renameModelShaders = qtrue;
-		}
-		
-		/* ydnar args */
-		else if( !strcmp( argv[ i ],  "-ne" ) )
- 		{
-			normalEpsilon = atof( argv[ i + 1 ] );
- 			i++;
-			Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
- 		}
-		else if( !strcmp( argv[ i ],  "-de" ) )
- 		{
-			distanceEpsilon = atof( argv[ i + 1 ] );
- 			i++;
-			Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
- 		}
-		else if( !strcmp( argv[ i ],  "-mv" ) )
- 		{
-			maxSurfaceVerts = atoi( argv[ i + 1 ] );
-			if( maxSurfaceVerts < 3 )
-				maxSurfaceVerts = 3;
- 			i++;
-			Sys_Printf( "Maximum per-surface vertex count set to %d\n", maxSurfaceVerts );
- 		}
-		else if( !strcmp( argv[ i ],  "-mi" ) )
- 		{
-			maxSurfaceIndexes = atoi( argv[ i + 1 ] );
-			if( maxSurfaceIndexes < 3 )
-				maxSurfaceIndexes = 3;
- 			i++;
-			Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
- 		}
-		else if( !strcmp( argv[ i ], "-np" ) )
-		{
-			npDegrees = atof( argv[ i + 1 ] );
-			if( npDegrees < 0.0f )
-				shadeAngleDegrees = 0.0f;
-			else if( npDegrees > 0.0f )
-				Sys_Printf( "Forcing nonplanar surfaces with a breaking angle of %f degrees\n", npDegrees );
-			i++;
-		}
-		else if( !strcmp( argv[ i ],  "-snap" ) )
- 		{
-			bevelSnap = atoi( argv[ i + 1 ]);
-			if( bevelSnap < 0 )
-				bevelSnap = 0;
- 			i++;
-			if( bevelSnap > 0 )
-				Sys_Printf( "Snapping brush bevel planes to %d units\n", bevelSnap );
- 		}
-		else if( !strcmp( argv[ i ],  "-texrange" ) )
- 		{
-			texRange = atoi( argv[ i + 1 ]);
-			if( texRange < 0 )
-				texRange = 0;
- 			i++;
-			Sys_Printf( "Limiting per-surface texture range to %d texels\n", texRange );
- 		}
-		else if( !strcmp( argv[ i ], "-nohint" ) )
-		{
-			Sys_Printf( "Hint brushes disabled\n" );
-			noHint = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-flat" ) )
-		{
-			Sys_Printf( "Flatshading enabled\n" );
-			flat = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-meta" ) )
-		{
-			Sys_Printf( "Creating meta surfaces from brush faces\n" );
-			meta = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-patchmeta" ) )
-		{
-			Sys_Printf( "Creating meta surfaces from patches\n" );
-			patchMeta = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-flares" ) )
-		{
-			Sys_Printf( "Flare surfaces enabled\n" );
-			emitFlares = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-noflares" ) )
-		{
-			Sys_Printf( "Flare surfaces disabled\n" );
-			emitFlares = qfalse;
-		}
-		else if( !strcmp( argv[ i ], "-skyfix" ) )
-		{
-			Sys_Printf( "GL_CLAMP sky fix/hack/workaround enabled\n" );
-			skyFixHack = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-debugsurfaces" ) )
-		{
-			Sys_Printf( "emitting debug surfaces\n" );
-			debugSurfaces = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-debuginset" ) )
-		{
-			Sys_Printf( "Debug surface triangle insetting enabled\n" );
-			debugInset = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-debugportals" ) )
-		{
-			Sys_Printf( "Debug portal surfaces enabled\n" );
-			debugPortals = qtrue;
-		}
-		else if( !strcmp( argv[ i ], "-bsp" ) )
-			Sys_Printf( "-bsp argument unnecessary\n" );
-		else
-			Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
-	}
-	
-	/* fixme: print more useful usage here */
-	if( i != (argc - 1) )
-		Error( "usage: q3map [options] mapfile" );
-	
-	/* copy source name */
-	strcpy( source, ExpandArg( argv[ i ] ) );
-	StripExtension( source );
-	
-	/* ydnar: set default sample size */
-	SetDefaultSampleSize( sampleSize );
-	
-	/* delete portal, line and surface files */
-	sprintf( path, "%s.prt", source );
-	remove( path );
-	sprintf( path, "%s.lin", source );
-	remove( path );
-	//%	sprintf( path, "%s.srf", source );	/* ydnar */
-	//%	remove( path );
-	
-	/* expand mapname */
-	strcpy( name, ExpandArg( argv[ i ] ) );	
-	if( strcmp( name + strlen( name ) - 4, ".reg" ) )
-	{
-		/* if we are doing a full map, delete the last saved region map */
-		sprintf( path, "%s.reg", source );
-		remove( path );
-		DefaultExtension( name, ".map" );	/* might be .reg */
-	}
-	
-	/* if onlyents, just grab the entites and resave */
-	if( onlyents )
-	{
-		OnlyEnts();
-		return 0;
-	}
-	
-	/* load shaders */
-	LoadShaderInfo();
-	
-	/* load original file from temp spot in case it was renamed by the editor on the way in */
-	if( strlen( tempSource ) > 0 )
-		LoadMapFile( tempSource, qfalse );
-	else
-		LoadMapFile( name, qfalse );
-	
-	/* ydnar: decal setup */
-	ProcessDecals();
-	
-	/* ydnar: cloned brush model entities */
-	SetCloneModelNumbers();
-	
-	/* process world and submodels */
-	ProcessModels();
-	
-	/* set light styles from targetted light entities */
-	SetLightStyles();
-	
-	/* finish and write bsp */
-	EndBSPFile();
-	
-	/* remove temp map source file if appropriate */
-	if( strlen( tempSource ) > 0)
-		remove( tempSource );
-	
-	/* return to sender */
-	return 0;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define BSP_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* -------------------------------------------------------------------------------
+
+functions
+
+------------------------------------------------------------------------------- */
+
+
+
+/*
+SetCloneModelNumbers() - ydnar
+sets the model numbers for brush entities
+*/
+
+static void SetCloneModelNumbers( void )
+{
+	int			i, j;
+	int			models;
+	char		modelValue[ 10 ];
+	const char	*value, *value2, *value3;
+	
+	
+	/* start with 1 (worldspawn is model 0) */
+	models = 1;
+	for( i = 1; i < numEntities; i++ )
+	{
+		/* only entities with brushes or patches get a model number */
+		if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
+			continue;
+		
+		/* is this a clone? */
+		value = ValueForKey( &entities[ i ], "_clone" );
+		if( value[ 0 ] != '\0' )
+			continue;
+		
+		/* add the model key */
+		sprintf( modelValue, "*%d", models );
+		SetKeyValue( &entities[ i ], "model", modelValue );
+		
+		/* increment model count */
+		models++;
+	}
+	
+	/* fix up clones */
+	for( i = 1; i < numEntities; i++ )
+	{
+		/* only entities with brushes or patches get a model number */
+		if( entities[ i ].brushes == NULL && entities[ i ].patches == NULL )
+			continue;
+		
+		/* is this a clone? */
+		value = ValueForKey( &entities[ i ], "_ins" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( &entities[ i ], "_instance" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( &entities[ i ], "_clone" );
+		if( value[ 0 ] == '\0' )
+			continue;
+		
+		/* find an entity with matching clone name */
+		for( j = 0; j < numEntities; j++ )
+		{
+			/* is this a clone parent? */
+			value2 = ValueForKey( &entities[ j ], "_clonename" );
+			if( value2[ 0 ] == '\0' )
+				continue;
+			
+			/* do they match? */
+			if( strcmp( value, value2 ) == 0 )
+			{
+				/* get the model num */
+				value3 = ValueForKey( &entities[ j ], "model" );
+				if( value3[ 0 ] == '\0' )
+				{
+					Sys_Printf( "WARNING: Cloned entity %s referenced entity without model\n", value2 );
+					continue;
+				}
+				models = atoi( &value2[ 1 ] );
+				
+				/* add the model key */
+				sprintf( modelValue, "*%d", models );
+				SetKeyValue( &entities[ i ], "model", modelValue );
+				
+				/* nuke the brushes/patches for this entity (fixme: leak!) */
+				entities[ i ].brushes = NULL;
+				entities[ i ].patches = NULL;
+			}
+		}
+	}
+}
+
+
+
+/*
+FixBrushSides() - ydnar
+matches brushsides back to their appropriate drawsurface and shader
+*/
+
+static void FixBrushSides( entity_t *e )
+{
+	int					i;
+	mapDrawSurface_t	*ds;
+	sideRef_t			*sideRef;
+	bspBrushSide_t		*side;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- FixBrushSides ---\n" );
+	
+	/* walk list of drawsurfaces */
+	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
+	{
+		/* get surface and try to early out */
+		ds = &mapDrawSurfs[ i ];
+		if( ds->outputNum < 0 )
+			continue;
+		
+		/* walk sideref list */
+		for( sideRef = ds->sideRef; sideRef != NULL; sideRef = sideRef->next )
+		{
+			/* get bsp brush side */
+			if( sideRef->side == NULL || sideRef->side->outputNum < 0 )
+				continue;
+			side = &bspBrushSides[ sideRef->side->outputNum ];
+			
+			/* set drawsurface */
+			side->surfaceNum = ds->outputNum;
+			//%	Sys_FPrintf( SYS_VRB, "DS: %7d Side: %7d     ", ds->outputNum, sideRef->side->outputNum );
+			
+			/* set shader */
+			if( strcmp( bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader ) )
+			{
+				//%	Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", bspShaders[ side->shaderNum ].shader, ds->shaderInfo->shader );
+				side->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
+			}
+		}
+	}
+}
+
+
+
+/*
+ProcessWorldModel()
+creates a full bsp + surfaces for the worldspawn entity
+*/
+
+void ProcessWorldModel( void )
+{
+	int			i, s;
+	entity_t	*e;
+	tree_t		*tree;
+	face_t		*faces;
+	qboolean	ignoreLeaks, leaked;
+	xmlNodePtr	polyline, leaknode;
+	char		level[ 2 ], shader[ 1024 ];
+	const char	*value;
+	
+	
+	/* sets integer blockSize from worldspawn "_blocksize" key if it exists */
+	value = ValueForKey( &entities[ 0 ], "_blocksize" );
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( &entities[ 0 ], "blocksize" );
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( &entities[ 0 ], "chopsize" );	/* sof2 */
+	if( value[ 0 ] != '\0' )
+	{
+		/* scan 3 numbers */
+		s = sscanf( value, "%d %d %d", &blockSize[ 0 ], &blockSize[ 1 ], &blockSize[ 2 ] );
+		
+		/* handle legacy case */
+		if( s == 1 )
+		{
+			blockSize[ 1 ] = blockSize[ 0 ];
+			blockSize[ 2 ] = blockSize[ 0 ];
+		}
+	}
+	Sys_Printf( "block size = { %d %d %d }\n", blockSize[ 0 ], blockSize[ 1 ], blockSize[ 2 ] );
+	
+	/* sof2: ignore leaks? */
+	value = ValueForKey( &entities[ 0 ], "_ignoreleaks" );	/* ydnar */
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( &entities[ 0 ], "ignoreleaks" );
+	if( value[ 0 ] == '1' )
+		ignoreLeaks = qtrue;
+	else
+		ignoreLeaks = qfalse;
+	
+	/* begin worldspawn model */
+	BeginModel();
+	e = &entities[ 0 ];
+	e->firstDrawSurf = 0;
+	
+	/* ydnar: gs mods */
+	ClearMetaTriangles();
+
+	/* check for patches with adjacent edges that need to lod together */
+	PatchMapDrawSurfs( e );
+
+	/* build an initial bsp tree using all of the sides of all of the structural brushes */
+	faces = MakeStructuralBSPFaceList( entities[ 0 ].brushes );
+	tree = FaceBSP( faces );
+	MakeTreePortals( tree );
+	FilterStructuralBrushesIntoTree( e, tree );
+	
+	/* see if the bsp is completely enclosed */
+	if( FloodEntities( tree ) || ignoreLeaks )
+	{
+		/* rebuild a better bsp tree using only the sides that are visible from the inside */
+		FillOutside( tree->headnode );
+
+		/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
+		ClipSidesIntoTree( e, tree );
+		
+		/* build a visible face tree */
+		faces = MakeVisibleBSPFaceList( entities[ 0 ].brushes );
+		FreeTree( tree );
+		tree = FaceBSP( faces );
+		MakeTreePortals( tree );
+		FilterStructuralBrushesIntoTree( e, tree );
+		leaked = qfalse;
+		
+		/* ydnar: flood again for skybox */
+		if( skyboxPresent )
+			FloodEntities( tree );
+	}
+	else
+	{
+		Sys_FPrintf( SYS_NOXML, "**********************\n" );
+		Sys_FPrintf( SYS_NOXML, "******* leaked *******\n" );
+		Sys_FPrintf( SYS_NOXML, "**********************\n" );
+		polyline = LeakFile( tree );
+		leaknode = xmlNewNode( NULL, "message" );
+		xmlNodeSetContent( leaknode, "MAP LEAKED\n" );
+		xmlAddChild( leaknode, polyline );
+		level[0] = (int) '0' + SYS_ERR;
+		level[1] = 0;
+		xmlSetProp( leaknode, "level", (char*) &level );
+		xml_SendNode( leaknode );
+		if( leaktest )
+		{
+			Sys_Printf ("--- MAP LEAKED, ABORTING LEAKTEST ---\n");
+			exit( 0 );
+		}
+		leaked = qtrue;
+		
+		/* chop the sides to the convex hull of their visible fragments, giving us the smallest polygons */
+		ClipSidesIntoTree( e, tree );
+	}
+	
+	/* save out information for visibility processing */
+	NumberClusters( tree );
+	if( !leaked )
+		WritePortalFile( tree );
+	
+	/* flood from entities */
+	FloodAreas( tree );
+	
+	/* create drawsurfs for triangle models */
+	AddTriangleModels( e );
+	
+	/* create drawsurfs for surface models */
+	AddEntitySurfaceModels( e );
+	
+	/* generate bsp brushes from map brushes */
+	EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
+	
+	/* add references to the detail brushes */
+	FilterDetailBrushesIntoTree( e, tree );
+	
+	/* drawsurfs that cross fog boundaries will need to be split along the fog boundary */
+	if( !nofog )
+		FogDrawSurfaces( e );
+	
+	/* subdivide each drawsurf as required by shader tesselation */
+	if( !nosubdivide )
+		SubdivideFaceSurfaces( e, tree );
+	
+	/* add in any vertexes required to fix t-junctions */
+	if( !notjunc )
+		FixTJunctions( e );
+	
+	/* ydnar: classify the surfaces */
+	ClassifyEntitySurfaces( e );
+	
+	/* ydnar: project decals */
+	MakeEntityDecals( e );
+	
+	/* ydnar: meta surfaces */
+	MakeEntityMetaTriangles( e );
+	SmoothMetaTriangles();
+	FixMetaTJunctions();
+	MergeMetaTriangles();
+	
+	/* ydnar: debug portals */
+	if( debugPortals )
+		MakeDebugPortalSurfs( tree );
+	
+	/* ydnar: fog hull */
+	value = ValueForKey( &entities[ 0 ], "_foghull" );
+	if( value[ 0 ] != '\0' )
+	{
+		sprintf( shader, "textures/%s", value );
+		MakeFogHullSurfs( e, tree, shader );
+	}
+	
+	/* ydnar: bug 645: do flares for lights */
+	for( i = 0; i < numEntities && emitFlares; i++ )
+	{
+		entity_t	*light, *target;
+		const char	*value, *flareShader;
+		vec3_t		origin, targetOrigin, normal, color;
+		int			lightStyle;
+		
+		
+		/* get light */
+		light = &entities[ i ];
+		value = ValueForKey( light, "classname" );
+		if( !strcmp( value, "light" ) )
+		{
+			/* get flare shader */
+			flareShader = ValueForKey( light, "_flareshader" );
+			value = ValueForKey( light, "_flare" );
+			if( flareShader[ 0 ] != '\0' || value[ 0 ] != '\0' )
+			{
+				/* get specifics */
+				GetVectorForKey( light, "origin", origin );
+				GetVectorForKey( light, "_color", color );
+				lightStyle = IntForKey( light, "_style" );
+				if( lightStyle == 0 )
+					lightStyle = IntForKey( light, "style" );
+				
+				/* handle directional spotlights */
+				value = ValueForKey( light, "target" );
+				if( value[ 0 ] != '\0' )
+				{
+					/* get target light */
+					target = FindTargetEntity( value );
+					if( target != NULL )
+					{
+						GetVectorForKey( target, "origin", targetOrigin );
+						VectorSubtract( targetOrigin, origin, normal );
+						VectorNormalize( normal, normal );
+					}
+				}
+				else
+					//%	VectorClear( normal );
+					VectorSet( normal, 0, 0, -1 );
+				
+				/* create the flare surface (note shader defaults automatically) */
+				DrawSurfaceForFlare( mapEntityNum, origin, normal, color, (char*) flareShader, lightStyle );
+			}
+		}
+	}
+	
+	/* add references to the final drawsurfs in the apropriate clusters */
+	FilterDrawsurfsIntoTree( e, tree );
+	
+	/* match drawsurfaces back to original brushsides (sof2) */
+	FixBrushSides( e );
+	
+	/* finish */
+	EndModel( e, tree->headnode );
+	FreeTree( tree );
+}
+
+
+
+/*
+ProcessSubModel()
+creates bsp + surfaces for other brush models
+*/
+
+void ProcessSubModel( void )
+{
+	entity_t	*e;
+	tree_t		*tree;
+	brush_t		*b, *bc;
+	node_t		*node;
+	
+	
+	/* start a brush model */
+	BeginModel();
+	e = &entities[ mapEntityNum ];
+	e->firstDrawSurf = numMapDrawSurfs;
+	
+	/* ydnar: gs mods */
+	ClearMetaTriangles();
+	
+	/* check for patches with adjacent edges that need to lod together */
+	PatchMapDrawSurfs( e );
+	
+	/* allocate a tree */
+	node = AllocNode();
+	node->planenum = PLANENUM_LEAF;
+	tree = AllocTree();
+	tree->headnode = node;
+	
+	/* add the sides to the tree */
+	ClipSidesIntoTree( e, tree );
+	
+	/* ydnar: create drawsurfs for triangle models */
+	AddTriangleModels( e );
+	
+	/* create drawsurfs for surface models */
+	AddEntitySurfaceModels( e );
+	
+	/* generate bsp brushes from map brushes */
+	EmitBrushes( e->brushes, &e->firstBrush, &e->numBrushes );
+
+	/* just put all the brushes in headnode */
+	for( b = e->brushes; b; b = b->next )
+	{
+		bc = CopyBrush( b );
+		bc->next = node->brushlist;
+		node->brushlist = bc;
+	}
+	
+	/* subdivide each drawsurf as required by shader tesselation */
+	if( !nosubdivide )
+		SubdivideFaceSurfaces( e, tree );
+	
+	/* add in any vertexes required to fix t-junctions */
+	if( !notjunc )
+		FixTJunctions( e );
+	
+	/* ydnar: classify the surfaces and project lightmaps */
+	ClassifyEntitySurfaces( e );
+	
+	/* ydnar: project decals */
+	MakeEntityDecals( e );
+	
+	/* ydnar: meta surfaces */
+	MakeEntityMetaTriangles( e );
+	SmoothMetaTriangles();
+	FixMetaTJunctions();
+	MergeMetaTriangles();
+	
+	/* add references to the final drawsurfs in the apropriate clusters */
+	FilterDrawsurfsIntoTree( e, tree );
+	
+	/* match drawsurfaces back to original brushsides (sof2) */
+	FixBrushSides( e );
+	
+	/* finish */
+	EndModel( e, node );
+	FreeTree( tree );
+}
+
+
+
+/*
+ProcessModels()
+process world + other models into the bsp
+*/
+
+void ProcessModels( void )
+{
+	qboolean	oldVerbose;
+	entity_t	*entity;
+	
+	
+	/* preserve -v setting */
+	oldVerbose = verbose;
+	
+	/* start a new bsp */
+	BeginBSPFile();
+	
+	/* create map fogs */
+	CreateMapFogs();
+	
+	/* walk entity list */
+	for( mapEntityNum = 0; mapEntityNum < numEntities; mapEntityNum++ )
+	{
+		/* get entity */
+		entity = &entities[ mapEntityNum ];
+		if( entity->brushes == NULL && entity->patches == NULL )
+			continue;
+		
+		/* process the model */
+		Sys_FPrintf( SYS_VRB, "############### model %i ###############\n", numBSPModels );
+		if( mapEntityNum == 0 )
+			ProcessWorldModel();
+		else
+			ProcessSubModel();
+		
+		/* potentially turn off the deluge of text */
+		verbose = verboseEntities;
+	}
+	
+	/* restore -v setting */
+	verbose = oldVerbose;
+	
+	/* write fogs */
+	EmitFogs();
+}
+
+
+
+/*
+OnlyEnts()
+this is probably broken unless teamed with a radiant version that preserves entity order
+*/
+
+void OnlyEnts( void )
+{
+	char out[ 1024 ];
+
+	
+	/* note it */
+	Sys_Printf( "--- OnlyEnts ---\n" );
+	
+	sprintf( out, "%s.bsp", source );
+	LoadBSPFile( out );
+	numEntities = 0;
+
+	LoadShaderInfo();
+	LoadMapFile( name, qfalse );
+	SetModelNumbers();
+	SetLightStyles();
+	
+	numBSPEntities = numEntities;
+	UnparseEntities();
+	
+	WriteBSPFile( out );
+}
+
+
+
+/*
+BSPMain() - ydnar
+handles creation of a bsp from a map file
+*/
+
+int BSPMain( int argc, char **argv )
+{
+	int			i;
+	char		path[ 1024 ], tempSource[ 1024 ];
+	qboolean	onlyents = qfalse;
+	
+	
+	/* note it */
+	Sys_Printf( "--- BSP ---\n" );
+	
+	SetDrawSurfacesBuffer();
+	mapDrawSurfs = safe_malloc( sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
+	memset( mapDrawSurfs, 0, sizeof( mapDrawSurface_t ) * MAX_MAP_DRAW_SURFS );
+	numMapDrawSurfs = 0;
+	
+	tempSource[ 0 ] = '\0';
+	
+	/* set flares flag */
+	emitFlares = game->emitFlares;
+	
+	/* process arguments */
+	for( i = 1; i < (argc - 1); i++ )
+	{
+		if( !strcmp( argv[ i ], "-onlyents" ) )
+		{
+			Sys_Printf( "Running entity-only compile\n" );
+			onlyents = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-tempname" ) )
+			strcpy( tempSource, argv[ ++i ] );
+		else if( !strcmp( argv[ i ], "-tmpout" ) )
+			strcpy( outbase, "/tmp" );
+		else if( !strcmp( argv[ i ],  "-nowater" ) )
+		{
+			Sys_Printf( "Disabling water\n" );
+			nowater = qtrue;
+		}
+		else if( !strcmp( argv[ i ],  "-nodetail" ) )
+		{
+			Sys_Printf( "Ignoring detail brushes\n") ;
+			nodetail = qtrue;
+		}
+		else if( !strcmp( argv[ i ],  "-fulldetail" ) )
+		{
+			Sys_Printf( "Turning detail brushes into structural brushes\n" );
+			fulldetail = qtrue;
+		}
+		else if( !strcmp( argv[ i ],  "-nofog" ) )
+		{
+			Sys_Printf( "Fog volumes disabled\n" );
+			nofog = qtrue;
+		}
+		else if( !strcmp( argv[ i ],  "-nosubdivide" ) )
+		{
+			Sys_Printf( "Disabling brush face subdivision\n" );
+			nosubdivide = qtrue;
+		}
+		else if( !strcmp( argv[ i ],  "-leaktest" ) )
+		{
+			Sys_Printf( "Leaktest enabled\n" );
+			leaktest = qtrue;
+		}
+		else if( !strcmp( argv[ i ],  "-verboseentities" ) )
+		{
+			Sys_Printf( "Verbose entities enabled\n" );
+			verboseEntities = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-nocurves" ) )
+		{
+			Sys_Printf( "Ignoring curved surfaces (patches)\n" );
+			noCurveBrushes = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-notjunc" ) )
+		{
+			Sys_Printf( "T-junction fixing disabled\n" );
+			notjunc = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-fakemap" ) )
+		{
+			Sys_Printf( "Generating fakemap.map\n" );
+			fakemap = qtrue;
+		}
+		else if( !strcmp( argv[ i ],  "-samplesize" ) )
+ 		{
+			sampleSize = atoi( argv[ i + 1 ] );
+			if( sampleSize < 1 )
+				sampleSize = 1;
+ 			i++;
+			Sys_Printf( "Lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
+ 		}
+		else if( !strcmp( argv[ i ],  "-custinfoparms") )
+		{
+			Sys_Printf( "Custom info parms enabled\n" );
+			useCustomInfoParms = qtrue;
+		}
+		
+		/* sof2 args */
+		else if( !strcmp( argv[ i ], "-rename" ) )
+		{
+			Sys_Printf( "Appending _bsp suffix to misc_model shaders (SOF2)\n" );
+			renameModelShaders = qtrue;
+		}
+		
+		/* ydnar args */
+		else if( !strcmp( argv[ i ],  "-ne" ) )
+ 		{
+			normalEpsilon = atof( argv[ i + 1 ] );
+ 			i++;
+			Sys_Printf( "Normal epsilon set to %f\n", normalEpsilon );
+ 		}
+		else if( !strcmp( argv[ i ],  "-de" ) )
+ 		{
+			distanceEpsilon = atof( argv[ i + 1 ] );
+ 			i++;
+			Sys_Printf( "Distance epsilon set to %f\n", distanceEpsilon );
+ 		}
+		else if( !strcmp( argv[ i ],  "-mv" ) )
+ 		{
+			maxSurfaceVerts = atoi( argv[ i + 1 ] );
+			if( maxSurfaceVerts < 3 )
+				maxSurfaceVerts = 3;
+ 			i++;
+			Sys_Printf( "Maximum per-surface vertex count set to %d\n", maxSurfaceVerts );
+ 		}
+		else if( !strcmp( argv[ i ],  "-mi" ) )
+ 		{
+			maxSurfaceIndexes = atoi( argv[ i + 1 ] );
+			if( maxSurfaceIndexes < 3 )
+				maxSurfaceIndexes = 3;
+ 			i++;
+			Sys_Printf( "Maximum per-surface index count set to %d\n", maxSurfaceIndexes );
+ 		}
+		else if( !strcmp( argv[ i ], "-np" ) )
+		{
+			npDegrees = atof( argv[ i + 1 ] );
+			if( npDegrees < 0.0f )
+				shadeAngleDegrees = 0.0f;
+			else if( npDegrees > 0.0f )
+				Sys_Printf( "Forcing nonplanar surfaces with a breaking angle of %f degrees\n", npDegrees );
+			i++;
+		}
+		else if( !strcmp( argv[ i ],  "-snap" ) )
+ 		{
+			bevelSnap = atoi( argv[ i + 1 ]);
+			if( bevelSnap < 0 )
+				bevelSnap = 0;
+ 			i++;
+			if( bevelSnap > 0 )
+				Sys_Printf( "Snapping brush bevel planes to %d units\n", bevelSnap );
+ 		}
+		else if( !strcmp( argv[ i ],  "-texrange" ) )
+ 		{
+			texRange = atoi( argv[ i + 1 ]);
+			if( texRange < 0 )
+				texRange = 0;
+ 			i++;
+			Sys_Printf( "Limiting per-surface texture range to %d texels\n", texRange );
+ 		}
+		else if( !strcmp( argv[ i ], "-nohint" ) )
+		{
+			Sys_Printf( "Hint brushes disabled\n" );
+			noHint = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-flat" ) )
+		{
+			Sys_Printf( "Flatshading enabled\n" );
+			flat = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-meta" ) )
+		{
+			Sys_Printf( "Creating meta surfaces from brush faces\n" );
+			meta = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-patchmeta" ) )
+		{
+			Sys_Printf( "Creating meta surfaces from patches\n" );
+			patchMeta = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-flares" ) )
+		{
+			Sys_Printf( "Flare surfaces enabled\n" );
+			emitFlares = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-noflares" ) )
+		{
+			Sys_Printf( "Flare surfaces disabled\n" );
+			emitFlares = qfalse;
+		}
+		else if( !strcmp( argv[ i ], "-skyfix" ) )
+		{
+			Sys_Printf( "GL_CLAMP sky fix/hack/workaround enabled\n" );
+			skyFixHack = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-debugsurfaces" ) )
+		{
+			Sys_Printf( "emitting debug surfaces\n" );
+			debugSurfaces = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-debuginset" ) )
+		{
+			Sys_Printf( "Debug surface triangle insetting enabled\n" );
+			debugInset = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-debugportals" ) )
+		{
+			Sys_Printf( "Debug portal surfaces enabled\n" );
+			debugPortals = qtrue;
+		}
+		else if( !strcmp( argv[ i ], "-bsp" ) )
+			Sys_Printf( "-bsp argument unnecessary\n" );
+		else
+			Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
+	}
+	
+	/* fixme: print more useful usage here */
+	if( i != (argc - 1) )
+		Error( "usage: q3map [options] mapfile" );
+	
+	/* copy source name */
+	strcpy( source, ExpandArg( argv[ i ] ) );
+	StripExtension( source );
+	
+	/* ydnar: set default sample size */
+	SetDefaultSampleSize( sampleSize );
+	
+	/* delete portal, line and surface files */
+	sprintf( path, "%s.prt", source );
+	remove( path );
+	sprintf( path, "%s.lin", source );
+	remove( path );
+	//%	sprintf( path, "%s.srf", source );	/* ydnar */
+	//%	remove( path );
+	
+	/* expand mapname */
+	strcpy( name, ExpandArg( argv[ i ] ) );	
+	if( strcmp( name + strlen( name ) - 4, ".reg" ) )
+	{
+		/* if we are doing a full map, delete the last saved region map */
+		sprintf( path, "%s.reg", source );
+		remove( path );
+		DefaultExtension( name, ".map" );	/* might be .reg */
+	}
+	
+	/* if onlyents, just grab the entites and resave */
+	if( onlyents )
+	{
+		OnlyEnts();
+		return 0;
+	}
+	
+	/* load shaders */
+	LoadShaderInfo();
+	
+	/* load original file from temp spot in case it was renamed by the editor on the way in */
+	if( strlen( tempSource ) > 0 )
+		LoadMapFile( tempSource, qfalse );
+	else
+		LoadMapFile( name, qfalse );
+	
+	/* ydnar: decal setup */
+	ProcessDecals();
+	
+	/* ydnar: cloned brush model entities */
+	SetCloneModelNumbers();
+	
+	/* process world and submodels */
+	ProcessModels();
+	
+	/* set light styles from targetted light entities */
+	SetLightStyles();
+	
+	/* finish and write bsp */
+	EndBSPFile();
+	
+	/* remove temp map source file if appropriate */
+	if( strlen( tempSource ) > 0)
+		remove( tempSource );
+	
+	/* return to sender */
+	return 0;
+}
+
diff --git a/tools/quake3/q3map2/bspfile_abstract.c b/tools/quake3/q3map2/bspfile_abstract.c
index db34dd61..ae2fec30 100644
--- a/tools/quake3/q3map2/bspfile_abstract.c
+++ b/tools/quake3/q3map2/bspfile_abstract.c
@@ -1,834 +1,834 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define BSPFILE_ABSTRACT_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-/* -------------------------------------------------------------------------------
-
-this file was copied out of the common directory in order to not break
-compatibility with the q3map 1.x tree. it was moved out in order to support
-the raven bsp format (RBSP) used in soldier of fortune 2 and jedi knight 2.
-
-since each game has its own set of particular features, the data structures
-below no longer directly correspond to the binary format of a particular game.
-
-the translation will be done at bsp load/save time to keep any sort of
-special-case code messiness out of the rest of the program.
-
-------------------------------------------------------------------------------- */
-
-
-
-/* FIXME: remove the functions below that handle memory management of bsp file chunks */
-
-int numBSPDrawVertsBuffer = 0;
-void IncDrawVerts()
-{
-	numBSPDrawVerts++;
-
-	if(bspDrawVerts == 0)
-	{
-		numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
-		
-		bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
-
-	}
-	else if(numBSPDrawVerts > numBSPDrawVertsBuffer)
-	{
-		numBSPDrawVertsBuffer *= 3; // multiply by 1.5
-		numBSPDrawVertsBuffer /= 2;
-
-		if(numBSPDrawVertsBuffer > MAX_MAP_DRAW_VERTS)
-			numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
-
-		bspDrawVerts = realloc(bspDrawVerts, sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer);
-
-		if(!bspDrawVerts)
-			Error( "realloc() failed (IncDrawVerts)");
-	}
-
-	memset(bspDrawVerts + (numBSPDrawVerts - 1), 0, sizeof(bspDrawVert_t));
-}
-
-void SetDrawVerts(int n)
-{
-	if(bspDrawVerts != 0)
-		free(bspDrawVerts);
-
-	numBSPDrawVerts = n;
-	numBSPDrawVertsBuffer = numBSPDrawVerts;
-
-	bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
-
-	memset(bspDrawVerts, 0, n * sizeof(bspDrawVert_t));
-}
-
-int numBSPDrawSurfacesBuffer = 0;
-void SetDrawSurfacesBuffer()
-{
-	if(bspDrawSurfaces != 0)
-		free(bspDrawSurfaces);
-
-	numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
-
-	bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
-
-	memset(bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof(bspDrawVert_t));
-}
-
-void SetDrawSurfaces(int n)
-{
-	if(bspDrawSurfaces != 0)
-		free(bspDrawSurfaces);
-
-	numBSPDrawSurfaces = n;
-	numBSPDrawSurfacesBuffer = numBSPDrawSurfaces;
-
-	bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
-
-	memset(bspDrawSurfaces, 0, n * sizeof(bspDrawVert_t));
-}
-
-void BSPFilesCleanup()
-{
-	if(bspDrawVerts != 0)
-		free(bspDrawVerts);
-	if(bspDrawSurfaces != 0)
-		free(bspDrawSurfaces);
-	if(bspLightBytes != 0)
-		free(bspLightBytes);
-	if(bspGridPoints != 0)
-		free(bspGridPoints);
-}
-
-
-
-
-
-
-/*
-SwapBlock()
-if all values are 32 bits, this can be used to swap everything
-*/
-
-void SwapBlock( int *block, int size )
-{
-	int		i;
-	
-	
-	/* dummy check */
-	if( block == NULL )
-		return;
-	
-	/* swap */
-	size >>= 2;
-	for( i = 0; i < size; i++ )
-		block[ i ] = LittleLong( block[ i ] );
-}
-
-
-
-/*
-SwapBSPFile()
-byte swaps all data in the abstract bsp
-*/
-
-void SwapBSPFile( void )
-{
-	int		i, j;
-	
-	
-	/* models */
-	SwapBlock( (int*) bspModels, numBSPModels * sizeof( bspModels[ 0 ] ) );
-
-	/* shaders (don't swap the name) */
-	for( i = 0; i < numBSPShaders ; i++ )
-	{
-		bspShaders[ i ].contentFlags = LittleLong( bspShaders[ i ].contentFlags );
-		bspShaders[ i ].surfaceFlags = LittleLong( bspShaders[ i ].surfaceFlags );
-	}
-
-	/* planes */
-	SwapBlock( (int*) bspPlanes, numBSPPlanes * sizeof( bspPlanes[ 0 ] ) );
-	
-	/* nodes */
-	SwapBlock( (int*) bspNodes, numBSPNodes * sizeof( bspNodes[ 0 ] ) );
-
-	/* leafs */
-	SwapBlock( (int*) bspLeafs, numBSPLeafs * sizeof( bspLeafs[ 0 ] ) );
-
-	/* leaffaces */
-	SwapBlock( (int*) bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
-
-	/* leafbrushes */
-	SwapBlock( (int*) bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
-
-	// brushes
-	SwapBlock( (int*) bspBrushes, numBSPBrushes * sizeof( bspBrushes[ 0 ] ) );
-
-	// brushsides
-	SwapBlock( (int*) bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
-
-	// vis
-	((int*) &bspVisBytes)[ 0 ] = LittleLong( ((int*) &bspVisBytes)[ 0 ] );
-	((int*) &bspVisBytes)[ 1 ] = LittleLong( ((int*) &bspVisBytes)[ 1 ] );
-
-	/* drawverts (don't swap colors) */
-	for( i = 0; i < numBSPDrawVerts; i++ )
-	{
-		bspDrawVerts[ i ].xyz[ 0 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 0 ] );
-		bspDrawVerts[ i ].xyz[ 1 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 1 ] );
-		bspDrawVerts[ i ].xyz[ 2 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 2 ] );
-		bspDrawVerts[ i ].normal[ 0 ] = LittleFloat( bspDrawVerts[ i ].normal[ 0 ] );
-		bspDrawVerts[ i ].normal[ 1 ] = LittleFloat( bspDrawVerts[ i ].normal[ 1 ] );
-		bspDrawVerts[ i ].normal[ 2 ] = LittleFloat( bspDrawVerts[ i ].normal[ 2 ] );
-		bspDrawVerts[ i ].st[ 0 ] = LittleFloat( bspDrawVerts[ i ].st[ 0 ] );
-		bspDrawVerts[ i ].st[ 1 ] = LittleFloat( bspDrawVerts[ i ].st[ 1 ] );
-		for( j = 0; j < MAX_LIGHTMAPS; j++ )
-		{
-			bspDrawVerts[ i ].lightmap[ j ][ 0 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 0 ] );
-			bspDrawVerts[ i ].lightmap[ j ][ 1 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 1 ] );
-		}
-	}
-	
-	/* drawindexes */
-	SwapBlock( (int*) bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[0] ) );
-
-	/* drawsurfs */
-	/* note: rbsp files (and hence q3map2 abstract bsp) have byte lightstyles index arrays, this follows sof2map convention */
-	SwapBlock( (int*) bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
-
-	/* fogs */
-	for( i = 0; i < numBSPFogs; i++ )
-	{
-		bspFogs[ i ].brushNum = LittleLong( bspFogs[ i ].brushNum );
-		bspFogs[ i ].visibleSide = LittleLong( bspFogs[ i ].visibleSide );
-	}
-}
-
-
-
-/*
-GetLumpElements()
-gets the number of elements in a bsp lump
-*/
-
-int GetLumpElements( bspHeader_t *header, int lump, int size )
-{
-	/* check for odd size */
-	if( header->lumps[ lump ].length % size )
-	{
-		if( force )
-		{
-			Sys_Printf( "WARNING: GetLumpElements: odd lump size (%d) in lump %d\n", header->lumps[ lump ].length, lump );
-			return 0;
-		}
-		else
-			Error( "GetLumpElements: odd lump size (%d) in lump %d", header->lumps[ lump ].length, lump );
-	}
-	
-	/* return element count */
-	return header->lumps[ lump ].length / size;
-}
-
-
-
-/*
-GetLump()
-returns a pointer to the specified lump
-*/
-
-void *GetLump( bspHeader_t *header, int lump )
-{
-	return (void*)( (byte*) header + header->lumps[ lump ].offset);
-}
-
-
-
-/*
-CopyLump()
-copies a bsp file lump into a destination buffer
-*/
-
-int CopyLump( bspHeader_t *header, int lump, void *dest, int size )
-{
-	int		length, offset;
-	
-	
-	/* get lump length and offset */
-	length = header->lumps[ lump ].length;
-	offset = header->lumps[ lump ].offset;
-	
-	/* handle erroneous cases */
-	if( length == 0 )
-		return 0;
-	if( length % size )
-	{
-		if( force )
-		{
-			Sys_Printf( "WARNING: CopyLump: odd lump size (%d) in lump %d\n", length, lump );
-			return 0;
-		}
-		else
-			Error( "CopyLump: odd lump size (%d) in lump %d", length, lump );
-	}
-	
-	/* copy block of memory and return */
-	memcpy( dest, (byte*) header + offset, length );
-	return length / size;
-}
-
-
-
-/*
-AddLump()
-adds a lump to an outgoing bsp file
-*/
-
-void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length )
-{
-	bspLump_t	*lump;
-	
-	
-	/* add lump to bsp file header */
-	lump = &header->lumps[ lumpNum ];
-	lump->offset = LittleLong( ftell( file ) );
-	lump->length = LittleLong( length );
-	
-	/* write lump to file */
-	SafeWrite( file, data, (length + 3) & ~3 );
-}
-
-
-
-/*
-LoadBSPFile()
-loads a bsp file into memory
-*/
-
-void LoadBSPFile( const char *filename )
-{
-	/* dummy check */
-	if( game == NULL || game->load == NULL )
-		Error( "LoadBSPFile: unsupported BSP file format" );
-	
-	/* load it, then byte swap the in-memory version */
-	game->load( filename );
-	SwapBSPFile();
-}
-
-
-
-/*
-WriteBSPFile()
-writes a bsp file
-*/
-
-void WriteBSPFile( const char *filename )
-{
-	char	tempname[ 1024 ];
-	time_t	tm;
-	
-	
-	/* dummy check */
-	if( game == NULL || game->write == NULL )
-		Error( "WriteBSPFile: unsupported BSP file format" );
-	
-	/* make fake temp name so existing bsp file isn't damaged in case write process fails */
-	time( &tm );
-	sprintf( tempname, "%s.%08X", filename, (int) tm );
-	
-	/* byteswap, write the bsp, then swap back so it can be manipulated further */
-	SwapBSPFile();
-	game->write( tempname );
-	SwapBSPFile();
-	
-	/* replace existing bsp file */
-	remove( filename );
-	rename( tempname, filename );
-}
-
-
-
-/*
-PrintBSPFileSizes()
-dumps info about current file
-*/
-
-void PrintBSPFileSizes( void )
-{
-	/* parse entities first */
-	if( numEntities <= 0 )
-		ParseEntities();
-	
-	/* note that this is abstracted */
-	Sys_Printf( "Abstracted BSP file components (*actual sizes may differ)\n" );
-	
-	/* print various and sundry bits */
-	Sys_Printf( "%9d models        %9d\n",
-		numBSPModels, (int) (numBSPModels * sizeof( bspModel_t )) );
-	Sys_Printf( "%9d shaders       %9d\n",
-		numBSPShaders, (int) (numBSPShaders * sizeof( bspShader_t )) );
-	Sys_Printf( "%9d brushes       %9d\n",
-		numBSPBrushes, (int) (numBSPBrushes * sizeof( bspBrush_t )) );
-	Sys_Printf( "%9d brushsides    %9d *\n",
-		numBSPBrushSides, (int) (numBSPBrushSides * sizeof( bspBrushSide_t )) );
-	Sys_Printf( "%9d fogs          %9d\n",
-		numBSPFogs, (int) (numBSPFogs * sizeof( bspFog_t ) ) );
-	Sys_Printf( "%9d planes        %9d\n",
-		numBSPPlanes, (int) (numBSPPlanes * sizeof( bspPlane_t )) );
-	Sys_Printf( "%9d entdata       %9d\n",
-		numEntities, bspEntDataSize );
-	Sys_Printf( "\n");
-	
-	Sys_Printf( "%9d nodes         %9d\n",
-		numBSPNodes, (int) (numBSPNodes * sizeof( bspNode_t)) );
-	Sys_Printf( "%9d leafs         %9d\n",
-		numBSPLeafs, (int) (numBSPLeafs * sizeof( bspLeaf_t )) );
-	Sys_Printf( "%9d leafsurfaces  %9d\n",
-		numBSPLeafSurfaces, (int) (numBSPLeafSurfaces * sizeof( *bspLeafSurfaces )) );
-	Sys_Printf( "%9d leafbrushes   %9d\n",
-		numBSPLeafBrushes, (int) (numBSPLeafBrushes * sizeof( *bspLeafBrushes )) );
-	Sys_Printf( "\n");
-	
-	Sys_Printf( "%9d drawsurfaces  %9d *\n",
-		numBSPDrawSurfaces, (int) (numBSPDrawSurfaces * sizeof( *bspDrawSurfaces )) );
-	Sys_Printf( "%9d drawverts     %9d *\n",
-		numBSPDrawVerts, (int) (numBSPDrawVerts * sizeof( *bspDrawVerts )) );
-	Sys_Printf( "%9d drawindexes   %9d\n",
-		numBSPDrawIndexes, (int) (numBSPDrawIndexes * sizeof( *bspDrawIndexes )) );
-	Sys_Printf( "\n");
-	
-	Sys_Printf( "%9d lightmaps     %9d\n",
-		numBSPLightBytes / (LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3), numBSPLightBytes );
-	Sys_Printf( "%9d lightgrid     %9d *\n",
-		numBSPGridPoints, (int) (numBSPGridPoints * sizeof( *bspGridPoints )) );
-	Sys_Printf( "          visibility    %9d\n",
-		numBSPVisBytes );
-}
-
-
-
-/* -------------------------------------------------------------------------------
-
-entity data handling
-
-------------------------------------------------------------------------------- */
-
-
-/*
-StripTrailing()
-strips low byte chars off the end of a string
-*/
-
-void StripTrailing( char *e )
-{
-	char	*s;
-	
-	
-	s = e + strlen( e ) - 1;
-	while( s >= e && *s <= 32 )
-	{
-		*s = 0;
-		s--;
-	}
-}
-
-
-
-/*
-ParseEpair()
-parses a single quoted "key" "value" pair into an epair struct
-*/
-
-epair_t *ParseEPair( void )
-{
-	epair_t		*e;
-	
-	
-	/* allocate and clear new epair */
-	e = safe_malloc( sizeof( epair_t ) );
-	memset( e, 0, sizeof( epair_t ) );
-	
-	/* handle key */
-	if( strlen( token ) >= (MAX_KEY - 1) )
-		Error( "ParseEPair: token too long" );
-	
-	e->key = copystring( token );
-	GetToken( qfalse );
-	
-	/* handle value */
-	if( strlen( token ) >= MAX_VALUE - 1 )
-		Error( "ParseEpar: token too long" );
-	e->value = copystring( token );
-	
-	/* strip trailing spaces that sometimes get accidentally added in the editor */
-	StripTrailing( e->key );
-	StripTrailing( e->value );
-	
-	/* return it */
-	return e;
-}
-
-
-
-/*
-ParseEntity()
-parses an entity's epairs
-*/
-
-qboolean ParseEntity( void )
-{
-	epair_t		*e;
-	
-	
-	/* dummy check */
-	if( !GetToken( qtrue ) )
-		return qfalse;
-	if( strcmp( token, "{" ) )
-		Error( "ParseEntity: { not found" );
-	if( numEntities == MAX_MAP_ENTITIES )
-		Error( "numEntities == MAX_MAP_ENTITIES" );
-	
-	/* create new entity */
-	mapEnt = &entities[ numEntities ];
-	numEntities++;
-	
-	/* parse */
-	while( 1 )
-	{
-		if( !GetToken( qtrue ) )
-			Error( "ParseEntity: EOF without closing brace" );
-		if( !EPAIR_STRCMP( token, "}" ) )
-			break;
-		e = ParseEPair();
-		e->next = mapEnt->epairs;
-		mapEnt->epairs = e;
-	}
-	
-	/* return to sender */
-	return qtrue;
-}
-
-
-
-/*
-ParseEntities()
-parses the bsp entity data string into entities
-*/
-
-void ParseEntities( void )
-{
-	numEntities = 0;
-	ParseFromMemory( bspEntData, bspEntDataSize );
-	while( ParseEntity() );
-	
-	/* ydnar: set number of bsp entities in case a map is loaded on top */
-	numBSPEntities = numEntities;
-}
-
-
-
-/*
-UnparseEntities()
-generates the dentdata string from all the entities.
-this allows the utilities to add or remove key/value
-pairs to the data created by the map editor
-*/
-
-void UnparseEntities( void )
-{
-	int			i;
-	char		*buf, *end;
-	epair_t		*ep;
-	char		line[ 2048 ];
-	char		key[ 1024 ], value[ 1024 ];
-	const char	*value2;
-	
-	
-	/* setup */
-	buf = bspEntData;
-	end = buf;
-	*end = 0;
-	
-	/* run through entity list */
-	for( i = 0; i < numBSPEntities && i < numEntities; i++ )
-	{
-		/* get epair */
-		ep = entities[ i ].epairs;
-		if( ep == NULL )
-			continue;	/* ent got removed */
-		
-		/* ydnar: certain entities get stripped from bsp file */
-		value2 = ValueForKey( &entities[ i ], "classname" );
-		if( !Q_stricmp( value2, "misc_model" ) ||
-			!Q_stricmp( value2, "_decal" ) ||
-			!Q_stricmp( value2, "_skybox" ) )
-			continue;
-		
-		/* add beginning brace */
-		strcat( end, "{\n" );
-		end += 2;
-		
-		/* walk epair list */
-		for( ep = entities[ i ].epairs; ep != NULL; ep = ep->next )
-		{
-			/* copy and clean */
-			strcpy( key, ep->key );
-			StripTrailing( key );
-			strcpy( value, ep->value );
-			StripTrailing( value );
-			
-			/* add to buffer */
-			sprintf( line, "\"%s\" \"%s\"\n", key, value );
-			strcat( end, line );
-			end += strlen( line );
-		}
-		
-		/* add trailing brace */
-		strcat( end,"}\n" );
-		end += 2;
-		
-		/* check for overflow */
-		if( end > buf + MAX_MAP_ENTSTRING )
-			Error( "Entity text too long" );
-	}
-	
-	/* set size */
-	bspEntDataSize = end - buf + 1;
-}
-
-
-
-/*
-PrintEntity()
-prints an entity's epairs to the console
-*/
-
-void PrintEntity( const entity_t *ent )
-{
-	epair_t	*ep;
-	
-
-	Sys_Printf( "------- entity %p -------\n", ent );
-	for( ep = ent->epairs; ep != NULL; ep = ep->next )
-		Sys_Printf( "%s = %s\n", ep->key, ep->value );
-
-}
-
-
-
-/*
-SetKeyValue()
-sets an epair in an entity
-*/
-
-void SetKeyValue( entity_t *ent, const char *key, const char *value )
-{
-	epair_t	*ep;
-	
-	
-	/* check for existing epair */
-	for( ep = ent->epairs; ep != NULL; ep = ep->next )
-	{
-		if( !EPAIR_STRCMP( ep->key, key ) )
-		{
-			free( ep->value );
-			ep->value = copystring( value );
-			return;
-		}
-	}
-	
-	/* create new epair */
-	ep = safe_malloc( sizeof( *ep ) );
-	ep->next = ent->epairs;
-	ent->epairs = ep;
-	ep->key = copystring( key );
-	ep->value = copystring( value );
-}
-
-
-
-/*
-ValueForKey()
-gets the value for an entity key
-*/
-
-const char *ValueForKey( const entity_t *ent, const char *key )
-{
-	epair_t	*ep;
-	
-	
-	/* dummy check */
-	if( ent == NULL )
-		return "";
-	
-	/* walk epair list */
-	for( ep = ent->epairs; ep != NULL; ep = ep->next )
-	{
-		if( !EPAIR_STRCMP( ep->key, key ) )
-			return ep->value;
-	}
-	
-	/* if no match, return empty string */
-	return "";
-}
-
-
-
-/*
-IntForKey()
-gets the integer point value for an entity key
-*/
-
-int IntForKey( const entity_t *ent, const char *key )
-{
-	const char	*k;
-	
-	
-	k = ValueForKey( ent, key );
-	return atoi( k );
-}
-
-
-
-/*
-FloatForKey()
-gets the floating point value for an entity key
-*/
-
-vec_t FloatForKey( const entity_t *ent, const char *key )
-{
-	const char	*k;
-	
-	
-	k = ValueForKey( ent, key );
-	return atof( k );
-}
-
-
-
-/*
-GetVectorForKey()
-gets a 3-element vector value for an entity key
-*/
-
-void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec )
-{
-	const char	*k;
-	double		v1, v2, v3;
-	
-
-	/* get value */
-	k = ValueForKey( ent, key );
-	
-	/* scanf into doubles, then assign, so it is vec_t size independent */
-	v1 = v2 = v3 = 0.0;
-	sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
-	vec[ 0 ] = v1;
-	vec[ 1 ] = v2;
-	vec[ 2 ] = v3;
-}
-
-
-
-/*
-FindTargetEntity()
-finds an entity target
-*/
-
-entity_t *FindTargetEntity( const char *target )
-{
-	int			i;
-	const char	*n;
-
-	
-	/* walk entity list */
-	for( i = 0; i < numEntities; i++ )
-	{
-		n = ValueForKey( &entities[ i ], "targetname" );
-		if ( !strcmp( n, target ) )
-			return &entities[ i ];
-	}
-	
-	/* nada */
-	return NULL;
-}
-
-
-
-/*
-GetEntityShadowFlags() - ydnar
-gets an entity's shadow flags
-note: does not set them to defaults if the keys are not found!
-*/
-
-void GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows )
-{
-	const char	*value;
-	
-	
-	/* get cast shadows */
-	if( castShadows != NULL )
-	{
-		value = ValueForKey( ent, "_castShadows" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( ent, "_cs" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( ent2, "_castShadows" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( ent2, "_cs" );
-		if( value[ 0 ] != '\0' )
-			*castShadows = atoi( value );
-	}
-	
-	/* receive */
-	if( recvShadows != NULL )
-	{
-		value = ValueForKey( ent, "_receiveShadows" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( ent, "_rs" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( ent2, "_receiveShadows" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( ent2, "_rs" );
-		if( value[ 0 ] != '\0' )
-			*recvShadows = atoi( value );
-	}
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define BSPFILE_ABSTRACT_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+/* -------------------------------------------------------------------------------
+
+this file was copied out of the common directory in order to not break
+compatibility with the q3map 1.x tree. it was moved out in order to support
+the raven bsp format (RBSP) used in soldier of fortune 2 and jedi knight 2.
+
+since each game has its own set of particular features, the data structures
+below no longer directly correspond to the binary format of a particular game.
+
+the translation will be done at bsp load/save time to keep any sort of
+special-case code messiness out of the rest of the program.
+
+------------------------------------------------------------------------------- */
+
+
+
+/* FIXME: remove the functions below that handle memory management of bsp file chunks */
+
+int numBSPDrawVertsBuffer = 0;
+void IncDrawVerts()
+{
+	numBSPDrawVerts++;
+
+	if(bspDrawVerts == 0)
+	{
+		numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS / 37;
+		
+		bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
+
+	}
+	else if(numBSPDrawVerts > numBSPDrawVertsBuffer)
+	{
+		numBSPDrawVertsBuffer *= 3; // multiply by 1.5
+		numBSPDrawVertsBuffer /= 2;
+
+		if(numBSPDrawVertsBuffer > MAX_MAP_DRAW_VERTS)
+			numBSPDrawVertsBuffer = MAX_MAP_DRAW_VERTS;
+
+		bspDrawVerts = realloc(bspDrawVerts, sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer);
+
+		if(!bspDrawVerts)
+			Error( "realloc() failed (IncDrawVerts)");
+	}
+
+	memset(bspDrawVerts + (numBSPDrawVerts - 1), 0, sizeof(bspDrawVert_t));
+}
+
+void SetDrawVerts(int n)
+{
+	if(bspDrawVerts != 0)
+		free(bspDrawVerts);
+
+	numBSPDrawVerts = n;
+	numBSPDrawVertsBuffer = numBSPDrawVerts;
+
+	bspDrawVerts = safe_malloc_info(sizeof(bspDrawVert_t) * numBSPDrawVertsBuffer, "IncDrawVerts");
+
+	memset(bspDrawVerts, 0, n * sizeof(bspDrawVert_t));
+}
+
+int numBSPDrawSurfacesBuffer = 0;
+void SetDrawSurfacesBuffer()
+{
+	if(bspDrawSurfaces != 0)
+		free(bspDrawSurfaces);
+
+	numBSPDrawSurfacesBuffer = MAX_MAP_DRAW_SURFS;
+
+	bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
+
+	memset(bspDrawSurfaces, 0, MAX_MAP_DRAW_SURFS * sizeof(bspDrawVert_t));
+}
+
+void SetDrawSurfaces(int n)
+{
+	if(bspDrawSurfaces != 0)
+		free(bspDrawSurfaces);
+
+	numBSPDrawSurfaces = n;
+	numBSPDrawSurfacesBuffer = numBSPDrawSurfaces;
+
+	bspDrawSurfaces = safe_malloc_info(sizeof(bspDrawSurface_t) * numBSPDrawSurfacesBuffer, "IncDrawSurfaces");
+
+	memset(bspDrawSurfaces, 0, n * sizeof(bspDrawVert_t));
+}
+
+void BSPFilesCleanup()
+{
+	if(bspDrawVerts != 0)
+		free(bspDrawVerts);
+	if(bspDrawSurfaces != 0)
+		free(bspDrawSurfaces);
+	if(bspLightBytes != 0)
+		free(bspLightBytes);
+	if(bspGridPoints != 0)
+		free(bspGridPoints);
+}
+
+
+
+
+
+
+/*
+SwapBlock()
+if all values are 32 bits, this can be used to swap everything
+*/
+
+void SwapBlock( int *block, int size )
+{
+	int		i;
+	
+	
+	/* dummy check */
+	if( block == NULL )
+		return;
+	
+	/* swap */
+	size >>= 2;
+	for( i = 0; i < size; i++ )
+		block[ i ] = LittleLong( block[ i ] );
+}
+
+
+
+/*
+SwapBSPFile()
+byte swaps all data in the abstract bsp
+*/
+
+void SwapBSPFile( void )
+{
+	int		i, j;
+	
+	
+	/* models */
+	SwapBlock( (int*) bspModels, numBSPModels * sizeof( bspModels[ 0 ] ) );
+
+	/* shaders (don't swap the name) */
+	for( i = 0; i < numBSPShaders ; i++ )
+	{
+		bspShaders[ i ].contentFlags = LittleLong( bspShaders[ i ].contentFlags );
+		bspShaders[ i ].surfaceFlags = LittleLong( bspShaders[ i ].surfaceFlags );
+	}
+
+	/* planes */
+	SwapBlock( (int*) bspPlanes, numBSPPlanes * sizeof( bspPlanes[ 0 ] ) );
+	
+	/* nodes */
+	SwapBlock( (int*) bspNodes, numBSPNodes * sizeof( bspNodes[ 0 ] ) );
+
+	/* leafs */
+	SwapBlock( (int*) bspLeafs, numBSPLeafs * sizeof( bspLeafs[ 0 ] ) );
+
+	/* leaffaces */
+	SwapBlock( (int*) bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
+
+	/* leafbrushes */
+	SwapBlock( (int*) bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
+
+	// brushes
+	SwapBlock( (int*) bspBrushes, numBSPBrushes * sizeof( bspBrushes[ 0 ] ) );
+
+	// brushsides
+	SwapBlock( (int*) bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
+
+	// vis
+	((int*) &bspVisBytes)[ 0 ] = LittleLong( ((int*) &bspVisBytes)[ 0 ] );
+	((int*) &bspVisBytes)[ 1 ] = LittleLong( ((int*) &bspVisBytes)[ 1 ] );
+
+	/* drawverts (don't swap colors) */
+	for( i = 0; i < numBSPDrawVerts; i++ )
+	{
+		bspDrawVerts[ i ].xyz[ 0 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 0 ] );
+		bspDrawVerts[ i ].xyz[ 1 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 1 ] );
+		bspDrawVerts[ i ].xyz[ 2 ] = LittleFloat( bspDrawVerts[ i ].xyz[ 2 ] );
+		bspDrawVerts[ i ].normal[ 0 ] = LittleFloat( bspDrawVerts[ i ].normal[ 0 ] );
+		bspDrawVerts[ i ].normal[ 1 ] = LittleFloat( bspDrawVerts[ i ].normal[ 1 ] );
+		bspDrawVerts[ i ].normal[ 2 ] = LittleFloat( bspDrawVerts[ i ].normal[ 2 ] );
+		bspDrawVerts[ i ].st[ 0 ] = LittleFloat( bspDrawVerts[ i ].st[ 0 ] );
+		bspDrawVerts[ i ].st[ 1 ] = LittleFloat( bspDrawVerts[ i ].st[ 1 ] );
+		for( j = 0; j < MAX_LIGHTMAPS; j++ )
+		{
+			bspDrawVerts[ i ].lightmap[ j ][ 0 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 0 ] );
+			bspDrawVerts[ i ].lightmap[ j ][ 1 ] = LittleFloat( bspDrawVerts[ i ].lightmap[ j ][ 1 ] );
+		}
+	}
+	
+	/* drawindexes */
+	SwapBlock( (int*) bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[0] ) );
+
+	/* drawsurfs */
+	/* note: rbsp files (and hence q3map2 abstract bsp) have byte lightstyles index arrays, this follows sof2map convention */
+	SwapBlock( (int*) bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
+
+	/* fogs */
+	for( i = 0; i < numBSPFogs; i++ )
+	{
+		bspFogs[ i ].brushNum = LittleLong( bspFogs[ i ].brushNum );
+		bspFogs[ i ].visibleSide = LittleLong( bspFogs[ i ].visibleSide );
+	}
+}
+
+
+
+/*
+GetLumpElements()
+gets the number of elements in a bsp lump
+*/
+
+int GetLumpElements( bspHeader_t *header, int lump, int size )
+{
+	/* check for odd size */
+	if( header->lumps[ lump ].length % size )
+	{
+		if( force )
+		{
+			Sys_Printf( "WARNING: GetLumpElements: odd lump size (%d) in lump %d\n", header->lumps[ lump ].length, lump );
+			return 0;
+		}
+		else
+			Error( "GetLumpElements: odd lump size (%d) in lump %d", header->lumps[ lump ].length, lump );
+	}
+	
+	/* return element count */
+	return header->lumps[ lump ].length / size;
+}
+
+
+
+/*
+GetLump()
+returns a pointer to the specified lump
+*/
+
+void *GetLump( bspHeader_t *header, int lump )
+{
+	return (void*)( (byte*) header + header->lumps[ lump ].offset);
+}
+
+
+
+/*
+CopyLump()
+copies a bsp file lump into a destination buffer
+*/
+
+int CopyLump( bspHeader_t *header, int lump, void *dest, int size )
+{
+	int		length, offset;
+	
+	
+	/* get lump length and offset */
+	length = header->lumps[ lump ].length;
+	offset = header->lumps[ lump ].offset;
+	
+	/* handle erroneous cases */
+	if( length == 0 )
+		return 0;
+	if( length % size )
+	{
+		if( force )
+		{
+			Sys_Printf( "WARNING: CopyLump: odd lump size (%d) in lump %d\n", length, lump );
+			return 0;
+		}
+		else
+			Error( "CopyLump: odd lump size (%d) in lump %d", length, lump );
+	}
+	
+	/* copy block of memory and return */
+	memcpy( dest, (byte*) header + offset, length );
+	return length / size;
+}
+
+
+
+/*
+AddLump()
+adds a lump to an outgoing bsp file
+*/
+
+void AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length )
+{
+	bspLump_t	*lump;
+	
+	
+	/* add lump to bsp file header */
+	lump = &header->lumps[ lumpNum ];
+	lump->offset = LittleLong( ftell( file ) );
+	lump->length = LittleLong( length );
+	
+	/* write lump to file */
+	SafeWrite( file, data, (length + 3) & ~3 );
+}
+
+
+
+/*
+LoadBSPFile()
+loads a bsp file into memory
+*/
+
+void LoadBSPFile( const char *filename )
+{
+	/* dummy check */
+	if( game == NULL || game->load == NULL )
+		Error( "LoadBSPFile: unsupported BSP file format" );
+	
+	/* load it, then byte swap the in-memory version */
+	game->load( filename );
+	SwapBSPFile();
+}
+
+
+
+/*
+WriteBSPFile()
+writes a bsp file
+*/
+
+void WriteBSPFile( const char *filename )
+{
+	char	tempname[ 1024 ];
+	time_t	tm;
+	
+	
+	/* dummy check */
+	if( game == NULL || game->write == NULL )
+		Error( "WriteBSPFile: unsupported BSP file format" );
+	
+	/* make fake temp name so existing bsp file isn't damaged in case write process fails */
+	time( &tm );
+	sprintf( tempname, "%s.%08X", filename, (int) tm );
+	
+	/* byteswap, write the bsp, then swap back so it can be manipulated further */
+	SwapBSPFile();
+	game->write( tempname );
+	SwapBSPFile();
+	
+	/* replace existing bsp file */
+	remove( filename );
+	rename( tempname, filename );
+}
+
+
+
+/*
+PrintBSPFileSizes()
+dumps info about current file
+*/
+
+void PrintBSPFileSizes( void )
+{
+	/* parse entities first */
+	if( numEntities <= 0 )
+		ParseEntities();
+	
+	/* note that this is abstracted */
+	Sys_Printf( "Abstracted BSP file components (*actual sizes may differ)\n" );
+	
+	/* print various and sundry bits */
+	Sys_Printf( "%9d models        %9d\n",
+		numBSPModels, (int) (numBSPModels * sizeof( bspModel_t )) );
+	Sys_Printf( "%9d shaders       %9d\n",
+		numBSPShaders, (int) (numBSPShaders * sizeof( bspShader_t )) );
+	Sys_Printf( "%9d brushes       %9d\n",
+		numBSPBrushes, (int) (numBSPBrushes * sizeof( bspBrush_t )) );
+	Sys_Printf( "%9d brushsides    %9d *\n",
+		numBSPBrushSides, (int) (numBSPBrushSides * sizeof( bspBrushSide_t )) );
+	Sys_Printf( "%9d fogs          %9d\n",
+		numBSPFogs, (int) (numBSPFogs * sizeof( bspFog_t ) ) );
+	Sys_Printf( "%9d planes        %9d\n",
+		numBSPPlanes, (int) (numBSPPlanes * sizeof( bspPlane_t )) );
+	Sys_Printf( "%9d entdata       %9d\n",
+		numEntities, bspEntDataSize );
+	Sys_Printf( "\n");
+	
+	Sys_Printf( "%9d nodes         %9d\n",
+		numBSPNodes, (int) (numBSPNodes * sizeof( bspNode_t)) );
+	Sys_Printf( "%9d leafs         %9d\n",
+		numBSPLeafs, (int) (numBSPLeafs * sizeof( bspLeaf_t )) );
+	Sys_Printf( "%9d leafsurfaces  %9d\n",
+		numBSPLeafSurfaces, (int) (numBSPLeafSurfaces * sizeof( *bspLeafSurfaces )) );
+	Sys_Printf( "%9d leafbrushes   %9d\n",
+		numBSPLeafBrushes, (int) (numBSPLeafBrushes * sizeof( *bspLeafBrushes )) );
+	Sys_Printf( "\n");
+	
+	Sys_Printf( "%9d drawsurfaces  %9d *\n",
+		numBSPDrawSurfaces, (int) (numBSPDrawSurfaces * sizeof( *bspDrawSurfaces )) );
+	Sys_Printf( "%9d drawverts     %9d *\n",
+		numBSPDrawVerts, (int) (numBSPDrawVerts * sizeof( *bspDrawVerts )) );
+	Sys_Printf( "%9d drawindexes   %9d\n",
+		numBSPDrawIndexes, (int) (numBSPDrawIndexes * sizeof( *bspDrawIndexes )) );
+	Sys_Printf( "\n");
+	
+	Sys_Printf( "%9d lightmaps     %9d\n",
+		numBSPLightBytes / (LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3), numBSPLightBytes );
+	Sys_Printf( "%9d lightgrid     %9d *\n",
+		numBSPGridPoints, (int) (numBSPGridPoints * sizeof( *bspGridPoints )) );
+	Sys_Printf( "          visibility    %9d\n",
+		numBSPVisBytes );
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+entity data handling
+
+------------------------------------------------------------------------------- */
+
+
+/*
+StripTrailing()
+strips low byte chars off the end of a string
+*/
+
+void StripTrailing( char *e )
+{
+	char	*s;
+	
+	
+	s = e + strlen( e ) - 1;
+	while( s >= e && *s <= 32 )
+	{
+		*s = 0;
+		s--;
+	}
+}
+
+
+
+/*
+ParseEpair()
+parses a single quoted "key" "value" pair into an epair struct
+*/
+
+epair_t *ParseEPair( void )
+{
+	epair_t		*e;
+	
+	
+	/* allocate and clear new epair */
+	e = safe_malloc( sizeof( epair_t ) );
+	memset( e, 0, sizeof( epair_t ) );
+	
+	/* handle key */
+	if( strlen( token ) >= (MAX_KEY - 1) )
+		Error( "ParseEPair: token too long" );
+	
+	e->key = copystring( token );
+	GetToken( qfalse );
+	
+	/* handle value */
+	if( strlen( token ) >= MAX_VALUE - 1 )
+		Error( "ParseEpar: token too long" );
+	e->value = copystring( token );
+	
+	/* strip trailing spaces that sometimes get accidentally added in the editor */
+	StripTrailing( e->key );
+	StripTrailing( e->value );
+	
+	/* return it */
+	return e;
+}
+
+
+
+/*
+ParseEntity()
+parses an entity's epairs
+*/
+
+qboolean ParseEntity( void )
+{
+	epair_t		*e;
+	
+	
+	/* dummy check */
+	if( !GetToken( qtrue ) )
+		return qfalse;
+	if( strcmp( token, "{" ) )
+		Error( "ParseEntity: { not found" );
+	if( numEntities == MAX_MAP_ENTITIES )
+		Error( "numEntities == MAX_MAP_ENTITIES" );
+	
+	/* create new entity */
+	mapEnt = &entities[ numEntities ];
+	numEntities++;
+	
+	/* parse */
+	while( 1 )
+	{
+		if( !GetToken( qtrue ) )
+			Error( "ParseEntity: EOF without closing brace" );
+		if( !EPAIR_STRCMP( token, "}" ) )
+			break;
+		e = ParseEPair();
+		e->next = mapEnt->epairs;
+		mapEnt->epairs = e;
+	}
+	
+	/* return to sender */
+	return qtrue;
+}
+
+
+
+/*
+ParseEntities()
+parses the bsp entity data string into entities
+*/
+
+void ParseEntities( void )
+{
+	numEntities = 0;
+	ParseFromMemory( bspEntData, bspEntDataSize );
+	while( ParseEntity() );
+	
+	/* ydnar: set number of bsp entities in case a map is loaded on top */
+	numBSPEntities = numEntities;
+}
+
+
+
+/*
+UnparseEntities()
+generates the dentdata string from all the entities.
+this allows the utilities to add or remove key/value
+pairs to the data created by the map editor
+*/
+
+void UnparseEntities( void )
+{
+	int			i;
+	char		*buf, *end;
+	epair_t		*ep;
+	char		line[ 2048 ];
+	char		key[ 1024 ], value[ 1024 ];
+	const char	*value2;
+	
+	
+	/* setup */
+	buf = bspEntData;
+	end = buf;
+	*end = 0;
+	
+	/* run through entity list */
+	for( i = 0; i < numBSPEntities && i < numEntities; i++ )
+	{
+		/* get epair */
+		ep = entities[ i ].epairs;
+		if( ep == NULL )
+			continue;	/* ent got removed */
+		
+		/* ydnar: certain entities get stripped from bsp file */
+		value2 = ValueForKey( &entities[ i ], "classname" );
+		if( !Q_stricmp( value2, "misc_model" ) ||
+			!Q_stricmp( value2, "_decal" ) ||
+			!Q_stricmp( value2, "_skybox" ) )
+			continue;
+		
+		/* add beginning brace */
+		strcat( end, "{\n" );
+		end += 2;
+		
+		/* walk epair list */
+		for( ep = entities[ i ].epairs; ep != NULL; ep = ep->next )
+		{
+			/* copy and clean */
+			strcpy( key, ep->key );
+			StripTrailing( key );
+			strcpy( value, ep->value );
+			StripTrailing( value );
+			
+			/* add to buffer */
+			sprintf( line, "\"%s\" \"%s\"\n", key, value );
+			strcat( end, line );
+			end += strlen( line );
+		}
+		
+		/* add trailing brace */
+		strcat( end,"}\n" );
+		end += 2;
+		
+		/* check for overflow */
+		if( end > buf + MAX_MAP_ENTSTRING )
+			Error( "Entity text too long" );
+	}
+	
+	/* set size */
+	bspEntDataSize = end - buf + 1;
+}
+
+
+
+/*
+PrintEntity()
+prints an entity's epairs to the console
+*/
+
+void PrintEntity( const entity_t *ent )
+{
+	epair_t	*ep;
+	
+
+	Sys_Printf( "------- entity %p -------\n", ent );
+	for( ep = ent->epairs; ep != NULL; ep = ep->next )
+		Sys_Printf( "%s = %s\n", ep->key, ep->value );
+
+}
+
+
+
+/*
+SetKeyValue()
+sets an epair in an entity
+*/
+
+void SetKeyValue( entity_t *ent, const char *key, const char *value )
+{
+	epair_t	*ep;
+	
+	
+	/* check for existing epair */
+	for( ep = ent->epairs; ep != NULL; ep = ep->next )
+	{
+		if( !EPAIR_STRCMP( ep->key, key ) )
+		{
+			free( ep->value );
+			ep->value = copystring( value );
+			return;
+		}
+	}
+	
+	/* create new epair */
+	ep = safe_malloc( sizeof( *ep ) );
+	ep->next = ent->epairs;
+	ent->epairs = ep;
+	ep->key = copystring( key );
+	ep->value = copystring( value );
+}
+
+
+
+/*
+ValueForKey()
+gets the value for an entity key
+*/
+
+const char *ValueForKey( const entity_t *ent, const char *key )
+{
+	epair_t	*ep;
+	
+	
+	/* dummy check */
+	if( ent == NULL )
+		return "";
+	
+	/* walk epair list */
+	for( ep = ent->epairs; ep != NULL; ep = ep->next )
+	{
+		if( !EPAIR_STRCMP( ep->key, key ) )
+			return ep->value;
+	}
+	
+	/* if no match, return empty string */
+	return "";
+}
+
+
+
+/*
+IntForKey()
+gets the integer point value for an entity key
+*/
+
+int IntForKey( const entity_t *ent, const char *key )
+{
+	const char	*k;
+	
+	
+	k = ValueForKey( ent, key );
+	return atoi( k );
+}
+
+
+
+/*
+FloatForKey()
+gets the floating point value for an entity key
+*/
+
+vec_t FloatForKey( const entity_t *ent, const char *key )
+{
+	const char	*k;
+	
+	
+	k = ValueForKey( ent, key );
+	return atof( k );
+}
+
+
+
+/*
+GetVectorForKey()
+gets a 3-element vector value for an entity key
+*/
+
+void GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec )
+{
+	const char	*k;
+	double		v1, v2, v3;
+	
+
+	/* get value */
+	k = ValueForKey( ent, key );
+	
+	/* scanf into doubles, then assign, so it is vec_t size independent */
+	v1 = v2 = v3 = 0.0;
+	sscanf( k, "%lf %lf %lf", &v1, &v2, &v3 );
+	vec[ 0 ] = v1;
+	vec[ 1 ] = v2;
+	vec[ 2 ] = v3;
+}
+
+
+
+/*
+FindTargetEntity()
+finds an entity target
+*/
+
+entity_t *FindTargetEntity( const char *target )
+{
+	int			i;
+	const char	*n;
+
+	
+	/* walk entity list */
+	for( i = 0; i < numEntities; i++ )
+	{
+		n = ValueForKey( &entities[ i ], "targetname" );
+		if ( !strcmp( n, target ) )
+			return &entities[ i ];
+	}
+	
+	/* nada */
+	return NULL;
+}
+
+
+
+/*
+GetEntityShadowFlags() - ydnar
+gets an entity's shadow flags
+note: does not set them to defaults if the keys are not found!
+*/
+
+void GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows )
+{
+	const char	*value;
+	
+	
+	/* get cast shadows */
+	if( castShadows != NULL )
+	{
+		value = ValueForKey( ent, "_castShadows" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( ent, "_cs" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( ent2, "_castShadows" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( ent2, "_cs" );
+		if( value[ 0 ] != '\0' )
+			*castShadows = atoi( value );
+	}
+	
+	/* receive */
+	if( recvShadows != NULL )
+	{
+		value = ValueForKey( ent, "_receiveShadows" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( ent, "_rs" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( ent2, "_receiveShadows" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( ent2, "_rs" );
+		if( value[ 0 ] != '\0' )
+			*recvShadows = atoi( value );
+	}
+}
+
diff --git a/tools/quake3/q3map2/bspfile_ibsp.c b/tools/quake3/q3map2/bspfile_ibsp.c
index dddf63ca..71b982da 100644
--- a/tools/quake3/q3map2/bspfile_ibsp.c
+++ b/tools/quake3/q3map2/bspfile_ibsp.c
@@ -1,584 +1,584 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define BSPFILE_IBSP_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-/* -------------------------------------------------------------------------------
-
-this file handles translating the bsp file format used by quake 3, rtcw, and ef
-into the abstracted bsp file used by q3map2.
-
-------------------------------------------------------------------------------- */
-
-/* constants */
-#define	LUMP_ENTITIES		0
-#define	LUMP_SHADERS		1
-#define	LUMP_PLANES			2
-#define	LUMP_NODES			3
-#define	LUMP_LEAFS			4
-#define	LUMP_LEAFSURFACES	5
-#define	LUMP_LEAFBRUSHES	6
-#define	LUMP_MODELS			7
-#define	LUMP_BRUSHES		8
-#define	LUMP_BRUSHSIDES		9
-#define	LUMP_DRAWVERTS		10
-#define	LUMP_DRAWINDEXES	11
-#define	LUMP_FOGS			12
-#define	LUMP_SURFACES		13
-#define	LUMP_LIGHTMAPS		14
-#define	LUMP_LIGHTGRID		15
-#define	LUMP_VISIBILITY		16
-#define	HEADER_LUMPS		17
-
-
-/* types */
-typedef struct
-{
-	char		ident[ 4 ];
-	int			version;
-	
-	bspLump_t	lumps[ HEADER_LUMPS ];
-}
-ibspHeader_t;
-
-
-
-/* brush sides */
-typedef struct
-{
-	int			planeNum;
-	int			shaderNum;
-}
-ibspBrushSide_t;
-
-
-static void CopyBrushSidesLump( ibspHeader_t *header )
-{
-	int				i;
-	ibspBrushSide_t	*in;
-	bspBrushSide_t	*out;
-	
-	
-	/* get count */
-	numBSPBrushSides = GetLumpElements( (bspHeader_t*) header, LUMP_BRUSHSIDES, sizeof( *in ) );
-	
-	/* copy */
-	in = GetLump( (bspHeader_t*) header, LUMP_BRUSHSIDES );
-	out = bspBrushSides;
-	for( i = 0; i < numBSPBrushSides; i++ )
-	{
-		out->planeNum = in->planeNum;
-		out->shaderNum = in->shaderNum;
-		out->surfaceNum = -1;
-		in++;
-		out++;
-	}
-}
-
-
-static void AddBrushSidesLump( FILE *file, ibspHeader_t *header )
-{
-	int				i, size;
-	bspBrushSide_t	*in;
-	ibspBrushSide_t	*buffer, *out;
-	
-	
-	/* allocate output buffer */
-	size = numBSPBrushSides * sizeof( *buffer );
-	buffer = safe_malloc( size );
-	memset( buffer, 0, size );
-	
-	/* convert */
-	in = bspBrushSides;
-	out = buffer;
-	for( i = 0; i < numBSPBrushSides; i++ )
-	{
-		out->planeNum = in->planeNum;
-		out->shaderNum = in->shaderNum;
-		in++;
-		out++;
-	}
-	
-	/* write lump */
-	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, buffer, size );
-	
-	/* free buffer */
-	free( buffer );
-}
-
-
-
-/* drawsurfaces */
-typedef struct ibspDrawSurface_s
-{
-	int			shaderNum;
-	int			fogNum;
-	int			surfaceType;
-	
-	int			firstVert;
-	int			numVerts;
-	
-	int			firstIndex;
-	int			numIndexes;
-	
-	int			lightmapNum;
-	int			lightmapX, lightmapY;
-	int			lightmapWidth, lightmapHeight;
-	
-	vec3_t		lightmapOrigin;
-	vec3_t		lightmapVecs[ 3 ];
-	
-	int			patchWidth;
-	int			patchHeight;
-}
-ibspDrawSurface_t;
-
-
-static void CopyDrawSurfacesLump( ibspHeader_t *header )
-{
-	int					i, j;
-	ibspDrawSurface_t	*in;
-	bspDrawSurface_t	*out;
-	
-	
-	/* get count */
-	numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
-	SetDrawSurfaces( numBSPDrawSurfaces );
-	
-	/* copy */
-	in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
-	out = bspDrawSurfaces;
-	for( i = 0; i < numBSPDrawSurfaces; i++ )
-	{
-		out->shaderNum = in->shaderNum;
-		out->fogNum = in->fogNum;
-		out->surfaceType = in->surfaceType;
-		out->firstVert = in->firstVert;
-		out->numVerts = in->numVerts;
-		out->firstIndex = in->firstIndex;
-		out->numIndexes = in->numIndexes;
-		
-		out->lightmapStyles[ 0 ] = LS_NORMAL;
-		out->vertexStyles[ 0 ] = LS_NORMAL;
-		out->lightmapNum[ 0 ] = in->lightmapNum;
-		out->lightmapX[ 0 ] = in->lightmapX;
-		out->lightmapY[ 0 ] = in->lightmapY;
-		
-		for( j = 1; j < MAX_LIGHTMAPS; j++ )
-		{
-			out->lightmapStyles[ j ] = LS_NONE;
-			out->vertexStyles[ j ] = LS_NONE;
-			out->lightmapNum[ j ] = -3;
-			out->lightmapX[ j ] = 0;
-			out->lightmapY[ j ] = 0;
-		}
-		
-		out->lightmapWidth = in->lightmapWidth;
-		out->lightmapHeight = in->lightmapHeight;
-		
-		VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
-		VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
-		VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
-		VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
-		
-		out->patchWidth = in->patchWidth;
-		out->patchHeight = in->patchHeight;
-		
-		in++;
-		out++;
-	}
-}
-
-
-static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header )
-{
-	int					i, size;
-	bspDrawSurface_t	*in;
-	ibspDrawSurface_t	*buffer, *out;
-	
-	
-	/* allocate output buffer */
-	size = numBSPDrawSurfaces * sizeof( *buffer );
-	buffer = safe_malloc( size );
-	memset( buffer, 0, size );
-	
-	/* convert */
-	in = bspDrawSurfaces;
-	out = buffer;
-	for( i = 0; i < numBSPDrawSurfaces; i++ )
-	{
-		out->shaderNum = in->shaderNum;
-		out->fogNum = in->fogNum;
-		out->surfaceType = in->surfaceType;
-		out->firstVert = in->firstVert;
-		out->numVerts = in->numVerts;
-		out->firstIndex = in->firstIndex;
-		out->numIndexes = in->numIndexes;
-		
-		out->lightmapNum = in->lightmapNum[ 0 ];
-		out->lightmapX = in->lightmapX[ 0 ];
-		out->lightmapY = in->lightmapY[ 0 ];
-		out->lightmapWidth = in->lightmapWidth;
-		out->lightmapHeight = in->lightmapHeight;
-		
-		VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
-		VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
-		VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
-		VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
-		
-		out->patchWidth = in->patchWidth;
-		out->patchHeight = in->patchHeight;
-		
-		in++;
-		out++;
-	}
-	
-	/* write lump */
-	AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
-	
-	/* free buffer */
-	free( buffer );
-}
-
-
-
-/* drawverts */
-typedef struct
-{
-	vec3_t		xyz;
-	float		st[ 2 ];
-	float		lightmap[ 2 ];
-	vec3_t		normal;
-	byte		color[ 4 ];
-}
-ibspDrawVert_t;
-
-
-static void CopyDrawVertsLump( ibspHeader_t *header )
-{
-	int				i;
-	ibspDrawVert_t	*in;
-	bspDrawVert_t	*out;
-	
-	
-	/* get count */
-	numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
-	SetDrawVerts( numBSPDrawVerts );
-	
-	/* copy */
-	in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
-	out = bspDrawVerts;
-	for( i = 0; i < numBSPDrawVerts; i++ )
-	{
-		VectorCopy( in->xyz, out->xyz );
-		out->st[ 0 ] = in->st[ 0 ];
-		out->st[ 1 ] = in->st[ 1 ];
-		
-		out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
-		out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
-		
-		VectorCopy( in->normal, out->normal );
-		
-		out->color[ 0 ][ 0 ] = in->color[ 0 ];
-		out->color[ 0 ][ 1 ] = in->color[ 1 ];
-		out->color[ 0 ][ 2 ] = in->color[ 2 ];
-		out->color[ 0 ][ 3 ] = in->color[ 3 ];
-		
-		in++;
-		out++;
-	}
-}
-
-
-static void AddDrawVertsLump( FILE *file, ibspHeader_t *header )
-{
-	int				i, size;
-	bspDrawVert_t	*in;
-	ibspDrawVert_t	*buffer, *out;
-	
-	
-	/* allocate output buffer */
-	size = numBSPDrawVerts * sizeof( *buffer );
-	buffer = safe_malloc( size );
-	memset( buffer, 0, size );
-	
-	/* convert */
-	in = bspDrawVerts;
-	out = buffer;
-	for( i = 0; i < numBSPDrawVerts; i++ )
-	{
-		VectorCopy( in->xyz, out->xyz );
-		out->st[ 0 ] = in->st[ 0 ];
-		out->st[ 1 ] = in->st[ 1 ];
-		
-		out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
-		out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
-		
-		VectorCopy( in->normal, out->normal );
-		
-		out->color[ 0 ] = in->color[ 0 ][ 0 ];
-		out->color[ 1 ] = in->color[ 0 ][ 1 ];
-		out->color[ 2 ] = in->color[ 0 ][ 2 ];
-		out->color[ 3 ] = in->color[ 0 ][ 3 ];
-		
-		in++;
-		out++;
-	}
-	
-	/* write lump */
-	AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
-	
-	/* free buffer */
-	free( buffer );
-}
-
-
-
-/* light grid */
-typedef struct
-{
-	byte		ambient[ 3 ];
-	byte		directed[ 3 ];
-	byte		latLong[ 2 ];
-}
-ibspGridPoint_t;
-
-
-static void CopyLightGridLumps( ibspHeader_t *header )
-{
-	int				i, j;
-	ibspGridPoint_t	*in;
-	bspGridPoint_t	*out;
-	
-	
-	/* get count */
-	numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
-	
-	/* allocate buffer */
-	bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
-	memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
-	
-	/* copy */
-	in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
-	out = bspGridPoints;
-	for( i = 0; i < numBSPGridPoints; i++ )
-	{
-		for( j = 0; j < MAX_LIGHTMAPS; j++ )
-		{
-			VectorCopy( in->ambient, out->ambient[ j ] );
-			VectorCopy( in->directed, out->directed[ j ] );
-			out->styles[ j ] = LS_NONE;
-		}
-		
-		out->styles[ 0 ] = LS_NORMAL;
-		
-		out->latLong[ 0 ] = in->latLong[ 0 ];
-		out->latLong[ 1 ] = in->latLong[ 1 ];
-		
-		in++;
-		out++;
-	}
-}
-
-
-static void AddLightGridLumps( FILE *file, ibspHeader_t *header )
-{
-	int				i;
-	bspGridPoint_t	*in;
-	ibspGridPoint_t	*buffer, *out;
-	
-	
-	/* dummy check */
-	if( bspGridPoints == NULL )
-		return;
-	
-	/* allocate temporary buffer */
-	buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
-	
-	/* convert */
-	in = bspGridPoints;
-	out = buffer;
-	for( i = 0; i < numBSPGridPoints; i++ )
-	{
-		VectorCopy( in->ambient[ 0 ], out->ambient );
-		VectorCopy( in->directed[ 0 ], out->directed );
-		
-		out->latLong[ 0 ] = in->latLong[ 0 ];
-		out->latLong[ 1 ] = in->latLong[ 1 ];
-		
-		in++;
-		out++;
-	}
-	
-	/* write lumps */
-	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, (numBSPGridPoints * sizeof( *out )) );
-	
-	/* free buffer (ydnar 2002-10-22: [bug 641] thanks Rap70r! */
-	free( buffer );
-}
-
-
-
-/*
-LoadIBSPFile()
-loads a quake 3 bsp file into memory
-*/
-
-void LoadIBSPFile( const char *filename )
-{
-	ibspHeader_t	*header;
-	
-	
-	/* load the file header */
-	LoadFile( filename, (void**) &header );
-
-	/* swap the header (except the first 4 bytes) */
-	SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
-	
-	/* make sure it matches the format we're trying to load */
-	if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
-		Error( "%s is not a %s file", filename, game->bspIdent );
-	if( force == qfalse && header->version != game->bspVersion )
-		Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
-	
-	/* load/convert lumps */
-	numBSPShaders = CopyLump( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
-	
-	numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
-	
-	numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
-	
-	numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
-	
-	numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
-	
-	numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
-	
-	numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
-	
-	numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
-	
-	CopyBrushSidesLump( header );
-
-	CopyDrawVertsLump( header );
-	
-	CopyDrawSurfacesLump( header );
-	
-	numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) );
-	
-	numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
-	
-	numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
-	
-	numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
-		bspLightBytes = safe_malloc( numBSPLightBytes );
-		CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
-	
-	bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
-	
-	CopyLightGridLumps( header );
-	
-	/* free the file buffer */
-	free( header );
-}
-
-
-
-/*
-WriteIBSPFile()
-writes an id bsp file
-*/
-
-void WriteIBSPFile( const char *filename )
-{		
-	ibspHeader_t	outheader, *header;
-	FILE			*file;
-	time_t			t;
-	char			marker[ 1024 ];
-	int				size;
-	
-	
-	/* set header */
-	header = &outheader;
-	memset( header, 0, sizeof( *header ) );
-	
-	//%	Swapfile();
-	
-	/* set up header */
-	*((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
-	header->version = LittleLong( game->bspVersion );
-	
-	/* write initial header */
-	file = SafeOpenWrite( filename );
-	SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );	/* overwritten later */
-	
-	/* add marker lump */
-	time( &t );
-	sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
-	AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
-	
-	/* add lumps */
-	AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
-	AddBrushSidesLump( file, header );
-	AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
-	AddDrawVertsLump( file, header );
-	AddDrawSurfacesLump( file, header );
-	AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
-	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
-	AddLightGridLumps( file, header );
-	AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
-	AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
-	
-	/* emit bsp size */
-	size = ftell( file );
-	Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
-	
-	/* write the completed header */
-	fseek( file, 0, SEEK_SET );
-	SafeWrite( file, header, sizeof( *header ) );
-	
-	/* close the file */
-	fclose( file );	
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define BSPFILE_IBSP_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+/* -------------------------------------------------------------------------------
+
+this file handles translating the bsp file format used by quake 3, rtcw, and ef
+into the abstracted bsp file used by q3map2.
+
+------------------------------------------------------------------------------- */
+
+/* constants */
+#define	LUMP_ENTITIES		0
+#define	LUMP_SHADERS		1
+#define	LUMP_PLANES			2
+#define	LUMP_NODES			3
+#define	LUMP_LEAFS			4
+#define	LUMP_LEAFSURFACES	5
+#define	LUMP_LEAFBRUSHES	6
+#define	LUMP_MODELS			7
+#define	LUMP_BRUSHES		8
+#define	LUMP_BRUSHSIDES		9
+#define	LUMP_DRAWVERTS		10
+#define	LUMP_DRAWINDEXES	11
+#define	LUMP_FOGS			12
+#define	LUMP_SURFACES		13
+#define	LUMP_LIGHTMAPS		14
+#define	LUMP_LIGHTGRID		15
+#define	LUMP_VISIBILITY		16
+#define	HEADER_LUMPS		17
+
+
+/* types */
+typedef struct
+{
+	char		ident[ 4 ];
+	int			version;
+	
+	bspLump_t	lumps[ HEADER_LUMPS ];
+}
+ibspHeader_t;
+
+
+
+/* brush sides */
+typedef struct
+{
+	int			planeNum;
+	int			shaderNum;
+}
+ibspBrushSide_t;
+
+
+static void CopyBrushSidesLump( ibspHeader_t *header )
+{
+	int				i;
+	ibspBrushSide_t	*in;
+	bspBrushSide_t	*out;
+	
+	
+	/* get count */
+	numBSPBrushSides = GetLumpElements( (bspHeader_t*) header, LUMP_BRUSHSIDES, sizeof( *in ) );
+	
+	/* copy */
+	in = GetLump( (bspHeader_t*) header, LUMP_BRUSHSIDES );
+	out = bspBrushSides;
+	for( i = 0; i < numBSPBrushSides; i++ )
+	{
+		out->planeNum = in->planeNum;
+		out->shaderNum = in->shaderNum;
+		out->surfaceNum = -1;
+		in++;
+		out++;
+	}
+}
+
+
+static void AddBrushSidesLump( FILE *file, ibspHeader_t *header )
+{
+	int				i, size;
+	bspBrushSide_t	*in;
+	ibspBrushSide_t	*buffer, *out;
+	
+	
+	/* allocate output buffer */
+	size = numBSPBrushSides * sizeof( *buffer );
+	buffer = safe_malloc( size );
+	memset( buffer, 0, size );
+	
+	/* convert */
+	in = bspBrushSides;
+	out = buffer;
+	for( i = 0; i < numBSPBrushSides; i++ )
+	{
+		out->planeNum = in->planeNum;
+		out->shaderNum = in->shaderNum;
+		in++;
+		out++;
+	}
+	
+	/* write lump */
+	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, buffer, size );
+	
+	/* free buffer */
+	free( buffer );
+}
+
+
+
+/* drawsurfaces */
+typedef struct ibspDrawSurface_s
+{
+	int			shaderNum;
+	int			fogNum;
+	int			surfaceType;
+	
+	int			firstVert;
+	int			numVerts;
+	
+	int			firstIndex;
+	int			numIndexes;
+	
+	int			lightmapNum;
+	int			lightmapX, lightmapY;
+	int			lightmapWidth, lightmapHeight;
+	
+	vec3_t		lightmapOrigin;
+	vec3_t		lightmapVecs[ 3 ];
+	
+	int			patchWidth;
+	int			patchHeight;
+}
+ibspDrawSurface_t;
+
+
+static void CopyDrawSurfacesLump( ibspHeader_t *header )
+{
+	int					i, j;
+	ibspDrawSurface_t	*in;
+	bspDrawSurface_t	*out;
+	
+	
+	/* get count */
+	numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( *in ) );
+	SetDrawSurfaces( numBSPDrawSurfaces );
+	
+	/* copy */
+	in = GetLump( (bspHeader_t*) header, LUMP_SURFACES );
+	out = bspDrawSurfaces;
+	for( i = 0; i < numBSPDrawSurfaces; i++ )
+	{
+		out->shaderNum = in->shaderNum;
+		out->fogNum = in->fogNum;
+		out->surfaceType = in->surfaceType;
+		out->firstVert = in->firstVert;
+		out->numVerts = in->numVerts;
+		out->firstIndex = in->firstIndex;
+		out->numIndexes = in->numIndexes;
+		
+		out->lightmapStyles[ 0 ] = LS_NORMAL;
+		out->vertexStyles[ 0 ] = LS_NORMAL;
+		out->lightmapNum[ 0 ] = in->lightmapNum;
+		out->lightmapX[ 0 ] = in->lightmapX;
+		out->lightmapY[ 0 ] = in->lightmapY;
+		
+		for( j = 1; j < MAX_LIGHTMAPS; j++ )
+		{
+			out->lightmapStyles[ j ] = LS_NONE;
+			out->vertexStyles[ j ] = LS_NONE;
+			out->lightmapNum[ j ] = -3;
+			out->lightmapX[ j ] = 0;
+			out->lightmapY[ j ] = 0;
+		}
+		
+		out->lightmapWidth = in->lightmapWidth;
+		out->lightmapHeight = in->lightmapHeight;
+		
+		VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
+		VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
+		VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
+		VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
+		
+		out->patchWidth = in->patchWidth;
+		out->patchHeight = in->patchHeight;
+		
+		in++;
+		out++;
+	}
+}
+
+
+static void AddDrawSurfacesLump( FILE *file, ibspHeader_t *header )
+{
+	int					i, size;
+	bspDrawSurface_t	*in;
+	ibspDrawSurface_t	*buffer, *out;
+	
+	
+	/* allocate output buffer */
+	size = numBSPDrawSurfaces * sizeof( *buffer );
+	buffer = safe_malloc( size );
+	memset( buffer, 0, size );
+	
+	/* convert */
+	in = bspDrawSurfaces;
+	out = buffer;
+	for( i = 0; i < numBSPDrawSurfaces; i++ )
+	{
+		out->shaderNum = in->shaderNum;
+		out->fogNum = in->fogNum;
+		out->surfaceType = in->surfaceType;
+		out->firstVert = in->firstVert;
+		out->numVerts = in->numVerts;
+		out->firstIndex = in->firstIndex;
+		out->numIndexes = in->numIndexes;
+		
+		out->lightmapNum = in->lightmapNum[ 0 ];
+		out->lightmapX = in->lightmapX[ 0 ];
+		out->lightmapY = in->lightmapY[ 0 ];
+		out->lightmapWidth = in->lightmapWidth;
+		out->lightmapHeight = in->lightmapHeight;
+		
+		VectorCopy( in->lightmapOrigin, out->lightmapOrigin );
+		VectorCopy( in->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
+		VectorCopy( in->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
+		VectorCopy( in->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
+		
+		out->patchWidth = in->patchWidth;
+		out->patchHeight = in->patchHeight;
+		
+		in++;
+		out++;
+	}
+	
+	/* write lump */
+	AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, buffer, size );
+	
+	/* free buffer */
+	free( buffer );
+}
+
+
+
+/* drawverts */
+typedef struct
+{
+	vec3_t		xyz;
+	float		st[ 2 ];
+	float		lightmap[ 2 ];
+	vec3_t		normal;
+	byte		color[ 4 ];
+}
+ibspDrawVert_t;
+
+
+static void CopyDrawVertsLump( ibspHeader_t *header )
+{
+	int				i;
+	ibspDrawVert_t	*in;
+	bspDrawVert_t	*out;
+	
+	
+	/* get count */
+	numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( *in ) );
+	SetDrawVerts( numBSPDrawVerts );
+	
+	/* copy */
+	in = GetLump( (bspHeader_t*) header, LUMP_DRAWVERTS );
+	out = bspDrawVerts;
+	for( i = 0; i < numBSPDrawVerts; i++ )
+	{
+		VectorCopy( in->xyz, out->xyz );
+		out->st[ 0 ] = in->st[ 0 ];
+		out->st[ 1 ] = in->st[ 1 ];
+		
+		out->lightmap[ 0 ][ 0 ] = in->lightmap[ 0 ];
+		out->lightmap[ 0 ][ 1 ] = in->lightmap[ 1 ];
+		
+		VectorCopy( in->normal, out->normal );
+		
+		out->color[ 0 ][ 0 ] = in->color[ 0 ];
+		out->color[ 0 ][ 1 ] = in->color[ 1 ];
+		out->color[ 0 ][ 2 ] = in->color[ 2 ];
+		out->color[ 0 ][ 3 ] = in->color[ 3 ];
+		
+		in++;
+		out++;
+	}
+}
+
+
+static void AddDrawVertsLump( FILE *file, ibspHeader_t *header )
+{
+	int				i, size;
+	bspDrawVert_t	*in;
+	ibspDrawVert_t	*buffer, *out;
+	
+	
+	/* allocate output buffer */
+	size = numBSPDrawVerts * sizeof( *buffer );
+	buffer = safe_malloc( size );
+	memset( buffer, 0, size );
+	
+	/* convert */
+	in = bspDrawVerts;
+	out = buffer;
+	for( i = 0; i < numBSPDrawVerts; i++ )
+	{
+		VectorCopy( in->xyz, out->xyz );
+		out->st[ 0 ] = in->st[ 0 ];
+		out->st[ 1 ] = in->st[ 1 ];
+		
+		out->lightmap[ 0 ] = in->lightmap[ 0 ][ 0 ];
+		out->lightmap[ 1 ] = in->lightmap[ 0 ][ 1 ];
+		
+		VectorCopy( in->normal, out->normal );
+		
+		out->color[ 0 ] = in->color[ 0 ][ 0 ];
+		out->color[ 1 ] = in->color[ 0 ][ 1 ];
+		out->color[ 2 ] = in->color[ 0 ][ 2 ];
+		out->color[ 3 ] = in->color[ 0 ][ 3 ];
+		
+		in++;
+		out++;
+	}
+	
+	/* write lump */
+	AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, buffer, size );
+	
+	/* free buffer */
+	free( buffer );
+}
+
+
+
+/* light grid */
+typedef struct
+{
+	byte		ambient[ 3 ];
+	byte		directed[ 3 ];
+	byte		latLong[ 2 ];
+}
+ibspGridPoint_t;
+
+
+static void CopyLightGridLumps( ibspHeader_t *header )
+{
+	int				i, j;
+	ibspGridPoint_t	*in;
+	bspGridPoint_t	*out;
+	
+	
+	/* get count */
+	numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTGRID, sizeof( *in ) );
+	
+	/* allocate buffer */
+	bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
+	memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
+	
+	/* copy */
+	in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
+	out = bspGridPoints;
+	for( i = 0; i < numBSPGridPoints; i++ )
+	{
+		for( j = 0; j < MAX_LIGHTMAPS; j++ )
+		{
+			VectorCopy( in->ambient, out->ambient[ j ] );
+			VectorCopy( in->directed, out->directed[ j ] );
+			out->styles[ j ] = LS_NONE;
+		}
+		
+		out->styles[ 0 ] = LS_NORMAL;
+		
+		out->latLong[ 0 ] = in->latLong[ 0 ];
+		out->latLong[ 1 ] = in->latLong[ 1 ];
+		
+		in++;
+		out++;
+	}
+}
+
+
+static void AddLightGridLumps( FILE *file, ibspHeader_t *header )
+{
+	int				i;
+	bspGridPoint_t	*in;
+	ibspGridPoint_t	*buffer, *out;
+	
+	
+	/* dummy check */
+	if( bspGridPoints == NULL )
+		return;
+	
+	/* allocate temporary buffer */
+	buffer = safe_malloc( numBSPGridPoints * sizeof( *out ) );
+	
+	/* convert */
+	in = bspGridPoints;
+	out = buffer;
+	for( i = 0; i < numBSPGridPoints; i++ )
+	{
+		VectorCopy( in->ambient[ 0 ], out->ambient );
+		VectorCopy( in->directed[ 0 ], out->directed );
+		
+		out->latLong[ 0 ] = in->latLong[ 0 ];
+		out->latLong[ 1 ] = in->latLong[ 1 ];
+		
+		in++;
+		out++;
+	}
+	
+	/* write lumps */
+	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, buffer, (numBSPGridPoints * sizeof( *out )) );
+	
+	/* free buffer (ydnar 2002-10-22: [bug 641] thanks Rap70r! */
+	free( buffer );
+}
+
+
+
+/*
+LoadIBSPFile()
+loads a quake 3 bsp file into memory
+*/
+
+void LoadIBSPFile( const char *filename )
+{
+	ibspHeader_t	*header;
+	
+	
+	/* load the file header */
+	LoadFile( filename, (void**) &header );
+
+	/* swap the header (except the first 4 bytes) */
+	SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
+	
+	/* make sure it matches the format we're trying to load */
+	if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
+		Error( "%s is not a %s file", filename, game->bspIdent );
+	if( force == qfalse && header->version != game->bspVersion )
+		Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
+	
+	/* load/convert lumps */
+	numBSPShaders = CopyLump( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
+	
+	numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
+	
+	numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
+	
+	numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
+	
+	numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
+	
+	numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
+	
+	numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
+	
+	numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
+	
+	CopyBrushSidesLump( header );
+
+	CopyDrawVertsLump( header );
+	
+	CopyDrawSurfacesLump( header );
+	
+	numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFog_t ) );
+	
+	numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
+	
+	numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
+	
+	numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
+		bspLightBytes = safe_malloc( numBSPLightBytes );
+		CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
+	
+	bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
+	
+	CopyLightGridLumps( header );
+	
+	/* free the file buffer */
+	free( header );
+}
+
+
+
+/*
+WriteIBSPFile()
+writes an id bsp file
+*/
+
+void WriteIBSPFile( const char *filename )
+{		
+	ibspHeader_t	outheader, *header;
+	FILE			*file;
+	time_t			t;
+	char			marker[ 1024 ];
+	int				size;
+	
+	
+	/* set header */
+	header = &outheader;
+	memset( header, 0, sizeof( *header ) );
+	
+	//%	Swapfile();
+	
+	/* set up header */
+	*((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
+	header->version = LittleLong( game->bspVersion );
+	
+	/* write initial header */
+	file = SafeOpenWrite( filename );
+	SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );	/* overwritten later */
+	
+	/* add marker lump */
+	time( &t );
+	sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
+	AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
+	
+	/* add lumps */
+	AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
+	AddBrushSidesLump( file, header );
+	AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
+	AddDrawVertsLump( file, header );
+	AddDrawSurfacesLump( file, header );
+	AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
+	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
+	AddLightGridLumps( file, header );
+	AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
+	AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
+	
+	/* emit bsp size */
+	size = ftell( file );
+	Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
+	
+	/* write the completed header */
+	fseek( file, 0, SEEK_SET );
+	SafeWrite( file, header, sizeof( *header ) );
+	
+	/* close the file */
+	fclose( file );	
+}
diff --git a/tools/quake3/q3map2/bspfile_rbsp.c b/tools/quake3/q3map2/bspfile_rbsp.c
index 2e09510c..1f4f1f77 100644
--- a/tools/quake3/q3map2/bspfile_rbsp.c
+++ b/tools/quake3/q3map2/bspfile_rbsp.c
@@ -1,339 +1,339 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define BSPFILE_RBSP_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-/* -------------------------------------------------------------------------------
-
-this file handles translating the bsp file format used by quake 3, rtcw, and ef
-into the abstracted bsp file used by q3map2.
-
-------------------------------------------------------------------------------- */
-
-/* constants */
-#define	LUMP_ENTITIES		0
-#define	LUMP_SHADERS		1
-#define	LUMP_PLANES			2
-#define	LUMP_NODES			3
-#define	LUMP_LEAFS			4
-#define	LUMP_LEAFSURFACES	5
-#define	LUMP_LEAFBRUSHES	6
-#define	LUMP_MODELS			7
-#define	LUMP_BRUSHES		8
-#define	LUMP_BRUSHSIDES		9
-#define	LUMP_DRAWVERTS		10
-#define	LUMP_DRAWINDEXES	11
-#define	LUMP_FOGS			12
-#define	LUMP_SURFACES		13
-#define	LUMP_LIGHTMAPS		14
-#define	LUMP_LIGHTGRID		15
-#define	LUMP_VISIBILITY		16
-#define LUMP_LIGHTARRAY		17
-#define	HEADER_LUMPS		18
-
-
-/* types */
-typedef struct
-{
-	char		ident[ 4 ];
-	int			version;
-	
-	bspLump_t	lumps[ HEADER_LUMPS ];
-}
-rbspHeader_t;
-
-
-
-/* light grid */
-#define MAX_MAP_GRID		0xffff
-#define MAX_MAP_GRIDARRAY	0x100000
-#define LG_EPSILON			4
-
-
-static void CopyLightGridLumps( rbspHeader_t *header )
-{
-	int				i;
-	unsigned short	*inArray;
-	bspGridPoint_t	*in, *out;
-	
-	
-	/* get count */
-	numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTARRAY, sizeof( *inArray ) );
-	
-	/* allocate buffer */
-	bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
-	memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
-	
-	/* copy */
-	inArray = GetLump( (bspHeader_t*) header, LUMP_LIGHTARRAY );
-	in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
-	out = bspGridPoints;
-	for( i = 0; i < numBSPGridPoints; i++ )
-	{
-		memcpy( out, &in[ *inArray ], sizeof( *in ) );
-		inArray++;
-		out++;
-	}
-}
-
-
-static void AddLightGridLumps( FILE *file, rbspHeader_t *header )
-{
-	int				i, j, k, c, d;
-	int				numGridPoints, maxGridPoints;
-	bspGridPoint_t	*gridPoints, *in, *out;
-	int				numGridArray;
-	unsigned short	*gridArray;
-	qboolean		bad;
-	
-	
-	/* allocate temporary buffers */
-	maxGridPoints = (numBSPGridPoints < MAX_MAP_GRID) ? numBSPGridPoints : MAX_MAP_GRID;
-	gridPoints = safe_malloc( maxGridPoints * sizeof( *gridPoints ) );
-	gridArray = safe_malloc( numBSPGridPoints * sizeof( *gridArray ) );
-	
-	/* zero out */
-	numGridPoints = 0;
-	numGridArray = numBSPGridPoints;
-	
-	/* for each bsp grid point, find an approximate twin */
-	Sys_Printf( "Storing lightgrid: %d points\n", numBSPGridPoints );
-	for( i = 0; i < numGridArray; i++ )
-	{
-		/* get points */
-		in = &bspGridPoints[ i ];
-		
-		/* walk existing list */
-		for( j = 0; j < numGridPoints; j++ )
-		{
-			/* get point */
-			out = &gridPoints[ j ];
-			
-			/* compare styles */
-			if( *((unsigned int*) in->styles) != *((unsigned int*) out->styles) )
-				continue;
-			
-			/* compare direction */
-			d = abs( in->latLong[ 0 ] - out->latLong[ 0 ] );
-			if( d < (255 - LG_EPSILON) && d > LG_EPSILON )
-				continue;
-			d = abs( in->latLong[ 1 ] - out->latLong[ 1 ] );
-			if( d < 255 - LG_EPSILON && d > LG_EPSILON )
-				continue;
-			
-			/* compare light */
-			bad = qfalse;
-			for( k = 0; (k < MAX_LIGHTMAPS && bad == qfalse); k++ )
-			{
-				for( c = 0; c < 3; c++ )
-				{
-					if( abs( (int) in->ambient[ k ][ c ] - (int) out->ambient[ k ][ c ]) > LG_EPSILON ||
-						abs( (int) in->directed[ k ][ c ] - (int) out->directed[ k ][ c ]) > LG_EPSILON )
-					{
-						bad = qtrue;
-						break;
-					}
-				}
-			}
-			
-			/* failure */
-			if( bad )
-				continue;
-			
-			/* this sample is ok */
-			break;
-		}
-		
-		/* set sample index */
-		gridArray[ i ] = (unsigned short) j;
-		
-		/* if no sample found, add a new one */
-		if( j >= numGridPoints && numGridPoints < maxGridPoints )
-		{
-			out = &gridPoints[ numGridPoints++ ];
-			memcpy( out, in, sizeof( *in ) );
-		}
-	}
-	
-	/* swap array */
-	for( i = 0; i < numGridArray; i++ )
-		gridArray[ i ] = LittleShort( gridArray[ i ] );
-	
-	/* write lumps */
-	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, gridPoints, (numGridPoints * sizeof( *gridPoints )) );
-	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTARRAY, gridArray, (numGridArray * sizeof( *gridArray )) );
-	
-	/* free buffers */
-	free( gridPoints );
-	free( gridArray );
-}
-
-
-
-/*
-LoadRBSPFile()
-loads a raven bsp file into memory
-*/
-
-void LoadRBSPFile( const char *filename )
-{
-	rbspHeader_t	*header;
-	
-	
-	/* load the file header */
-	LoadFile( filename, (void**) &header );
-
-	/* swap the header (except the first 4 bytes) */
-	SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
-	
-	/* make sure it matches the format we're trying to load */
-	if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
-		Error( "%s is not a %s file", filename, game->bspIdent );
-	if( force == qfalse && header->version != game->bspVersion )
-		Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
-	
-	/* load/convert lumps */
-	numBSPShaders = CopyLump( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
-	
-	numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
-	
-	numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
-	
-	numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
-	
-	numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
-	
-	numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
-	
-	numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
-	
-	numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
-	
-	numBSPBrushSides = CopyLump( (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, sizeof( bspBrushSide_t ) );
-	
-	numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( bspDrawVerts[ 0 ] ) );
-		SetDrawVerts( numBSPDrawVerts );
-		CopyLump( (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, sizeof( bspDrawVerts[ 0 ] ) );
-	
-	numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( bspDrawSurfaces[ 0 ] ) );
-		SetDrawSurfaces( numBSPDrawSurfaces );
-		CopyLump( (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, sizeof( bspDrawSurfaces[ 0 ] ) );
-	
-	numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFogs[ 0 ] ) );
-	
-	numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
-	
-	numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
-	
-	numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
-		bspLightBytes = safe_malloc( numBSPLightBytes );
-		CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
-	
-	bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
-	
-	CopyLightGridLumps( header );
-	
-	/* free the file buffer */
-	free( header );
-}
-
-
-
-/*
-WriteRBSPFile()
-writes a raven bsp file
-*/
-
-void WriteRBSPFile( const char *filename )
-{		
-	rbspHeader_t	outheader, *header;
-	FILE			*file;
-	time_t			t;
-	char			marker[ 1024 ];
-	int				size;
-	
-	
-	/* set header */
-	header = &outheader;
-	memset( header, 0, sizeof( *header ) );
-	
-	//%	Swapfile();
-	
-	/* set up header */
-	*((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
-	header->version = LittleLong( game->bspVersion );
-	
-	/* write initial header */
-	file = SafeOpenWrite( filename );
-	SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );	/* overwritten later */
-	
-	/* add marker lump */
-	time( &t );
-	sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
-	AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
-	
-	/* add lumps */
-	AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, numBSPDrawVerts * sizeof( bspDrawVerts[ 0 ] ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
-	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
-	AddLightGridLumps( file, header );
-	AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
-	AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
-	AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
-	
-	/* emit bsp size */
-	size = ftell( file );
-	Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
-	
-	/* write the completed header */
-	fseek( file, 0, SEEK_SET );
-	SafeWrite( file, header, sizeof( *header ) );
-	
-	/* close the file */
-	fclose( file );	
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define BSPFILE_RBSP_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+/* -------------------------------------------------------------------------------
+
+this file handles translating the bsp file format used by quake 3, rtcw, and ef
+into the abstracted bsp file used by q3map2.
+
+------------------------------------------------------------------------------- */
+
+/* constants */
+#define	LUMP_ENTITIES		0
+#define	LUMP_SHADERS		1
+#define	LUMP_PLANES			2
+#define	LUMP_NODES			3
+#define	LUMP_LEAFS			4
+#define	LUMP_LEAFSURFACES	5
+#define	LUMP_LEAFBRUSHES	6
+#define	LUMP_MODELS			7
+#define	LUMP_BRUSHES		8
+#define	LUMP_BRUSHSIDES		9
+#define	LUMP_DRAWVERTS		10
+#define	LUMP_DRAWINDEXES	11
+#define	LUMP_FOGS			12
+#define	LUMP_SURFACES		13
+#define	LUMP_LIGHTMAPS		14
+#define	LUMP_LIGHTGRID		15
+#define	LUMP_VISIBILITY		16
+#define LUMP_LIGHTARRAY		17
+#define	HEADER_LUMPS		18
+
+
+/* types */
+typedef struct
+{
+	char		ident[ 4 ];
+	int			version;
+	
+	bspLump_t	lumps[ HEADER_LUMPS ];
+}
+rbspHeader_t;
+
+
+
+/* light grid */
+#define MAX_MAP_GRID		0xffff
+#define MAX_MAP_GRIDARRAY	0x100000
+#define LG_EPSILON			4
+
+
+static void CopyLightGridLumps( rbspHeader_t *header )
+{
+	int				i;
+	unsigned short	*inArray;
+	bspGridPoint_t	*in, *out;
+	
+	
+	/* get count */
+	numBSPGridPoints = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTARRAY, sizeof( *inArray ) );
+	
+	/* allocate buffer */
+	bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
+	memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
+	
+	/* copy */
+	inArray = GetLump( (bspHeader_t*) header, LUMP_LIGHTARRAY );
+	in = GetLump( (bspHeader_t*) header, LUMP_LIGHTGRID );
+	out = bspGridPoints;
+	for( i = 0; i < numBSPGridPoints; i++ )
+	{
+		memcpy( out, &in[ *inArray ], sizeof( *in ) );
+		inArray++;
+		out++;
+	}
+}
+
+
+static void AddLightGridLumps( FILE *file, rbspHeader_t *header )
+{
+	int				i, j, k, c, d;
+	int				numGridPoints, maxGridPoints;
+	bspGridPoint_t	*gridPoints, *in, *out;
+	int				numGridArray;
+	unsigned short	*gridArray;
+	qboolean		bad;
+	
+	
+	/* allocate temporary buffers */
+	maxGridPoints = (numBSPGridPoints < MAX_MAP_GRID) ? numBSPGridPoints : MAX_MAP_GRID;
+	gridPoints = safe_malloc( maxGridPoints * sizeof( *gridPoints ) );
+	gridArray = safe_malloc( numBSPGridPoints * sizeof( *gridArray ) );
+	
+	/* zero out */
+	numGridPoints = 0;
+	numGridArray = numBSPGridPoints;
+	
+	/* for each bsp grid point, find an approximate twin */
+	Sys_Printf( "Storing lightgrid: %d points\n", numBSPGridPoints );
+	for( i = 0; i < numGridArray; i++ )
+	{
+		/* get points */
+		in = &bspGridPoints[ i ];
+		
+		/* walk existing list */
+		for( j = 0; j < numGridPoints; j++ )
+		{
+			/* get point */
+			out = &gridPoints[ j ];
+			
+			/* compare styles */
+			if( *((unsigned int*) in->styles) != *((unsigned int*) out->styles) )
+				continue;
+			
+			/* compare direction */
+			d = abs( in->latLong[ 0 ] - out->latLong[ 0 ] );
+			if( d < (255 - LG_EPSILON) && d > LG_EPSILON )
+				continue;
+			d = abs( in->latLong[ 1 ] - out->latLong[ 1 ] );
+			if( d < 255 - LG_EPSILON && d > LG_EPSILON )
+				continue;
+			
+			/* compare light */
+			bad = qfalse;
+			for( k = 0; (k < MAX_LIGHTMAPS && bad == qfalse); k++ )
+			{
+				for( c = 0; c < 3; c++ )
+				{
+					if( abs( (int) in->ambient[ k ][ c ] - (int) out->ambient[ k ][ c ]) > LG_EPSILON ||
+						abs( (int) in->directed[ k ][ c ] - (int) out->directed[ k ][ c ]) > LG_EPSILON )
+					{
+						bad = qtrue;
+						break;
+					}
+				}
+			}
+			
+			/* failure */
+			if( bad )
+				continue;
+			
+			/* this sample is ok */
+			break;
+		}
+		
+		/* set sample index */
+		gridArray[ i ] = (unsigned short) j;
+		
+		/* if no sample found, add a new one */
+		if( j >= numGridPoints && numGridPoints < maxGridPoints )
+		{
+			out = &gridPoints[ numGridPoints++ ];
+			memcpy( out, in, sizeof( *in ) );
+		}
+	}
+	
+	/* swap array */
+	for( i = 0; i < numGridArray; i++ )
+		gridArray[ i ] = LittleShort( gridArray[ i ] );
+	
+	/* write lumps */
+	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTGRID, gridPoints, (numGridPoints * sizeof( *gridPoints )) );
+	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTARRAY, gridArray, (numGridArray * sizeof( *gridArray )) );
+	
+	/* free buffers */
+	free( gridPoints );
+	free( gridArray );
+}
+
+
+
+/*
+LoadRBSPFile()
+loads a raven bsp file into memory
+*/
+
+void LoadRBSPFile( const char *filename )
+{
+	rbspHeader_t	*header;
+	
+	
+	/* load the file header */
+	LoadFile( filename, (void**) &header );
+
+	/* swap the header (except the first 4 bytes) */
+	SwapBlock( (int*) ((byte*) header + sizeof( int )), sizeof( *header ) - sizeof( int ) );
+	
+	/* make sure it matches the format we're trying to load */
+	if( force == qfalse && *((int*) header->ident) != *((int*) game->bspIdent) )
+		Error( "%s is not a %s file", filename, game->bspIdent );
+	if( force == qfalse && header->version != game->bspVersion )
+		Error( "%s is version %d, not %d", filename, header->version, game->bspVersion );
+	
+	/* load/convert lumps */
+	numBSPShaders = CopyLump( (bspHeader_t*) header, LUMP_SHADERS, bspShaders, sizeof( bspShader_t ) );
+	
+	numBSPModels = CopyLump( (bspHeader_t*) header, LUMP_MODELS, bspModels, sizeof( bspModel_t ) );
+	
+	numBSPPlanes = CopyLump( (bspHeader_t*) header, LUMP_PLANES, bspPlanes, sizeof( bspPlane_t ) );
+	
+	numBSPLeafs = CopyLump( (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, sizeof( bspLeaf_t ) );
+	
+	numBSPNodes = CopyLump( (bspHeader_t*) header, LUMP_NODES, bspNodes, sizeof( bspNode_t ) );
+	
+	numBSPLeafSurfaces = CopyLump( (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, sizeof( bspLeafSurfaces[ 0 ] ) );
+	
+	numBSPLeafBrushes = CopyLump( (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, sizeof( bspLeafBrushes[ 0 ] ) );
+	
+	numBSPBrushes = CopyLump( (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, sizeof( bspBrush_t ) );
+	
+	numBSPBrushSides = CopyLump( (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, sizeof( bspBrushSide_t ) );
+	
+	numBSPDrawVerts = GetLumpElements( (bspHeader_t*) header, LUMP_DRAWVERTS, sizeof( bspDrawVerts[ 0 ] ) );
+		SetDrawVerts( numBSPDrawVerts );
+		CopyLump( (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, sizeof( bspDrawVerts[ 0 ] ) );
+	
+	numBSPDrawSurfaces = GetLumpElements( (bspHeader_t*) header, LUMP_SURFACES, sizeof( bspDrawSurfaces[ 0 ] ) );
+		SetDrawSurfaces( numBSPDrawSurfaces );
+		CopyLump( (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, sizeof( bspDrawSurfaces[ 0 ] ) );
+	
+	numBSPFogs = CopyLump( (bspHeader_t*) header, LUMP_FOGS, bspFogs, sizeof( bspFogs[ 0 ] ) );
+	
+	numBSPDrawIndexes = CopyLump( (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, sizeof( bspDrawIndexes[ 0 ] ) );
+	
+	numBSPVisBytes = CopyLump( (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, 1 );
+	
+	numBSPLightBytes = GetLumpElements( (bspHeader_t*) header, LUMP_LIGHTMAPS, 1 );
+		bspLightBytes = safe_malloc( numBSPLightBytes );
+		CopyLump( (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, 1 );
+	
+	bspEntDataSize = CopyLump( (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, 1);
+	
+	CopyLightGridLumps( header );
+	
+	/* free the file buffer */
+	free( header );
+}
+
+
+
+/*
+WriteRBSPFile()
+writes a raven bsp file
+*/
+
+void WriteRBSPFile( const char *filename )
+{		
+	rbspHeader_t	outheader, *header;
+	FILE			*file;
+	time_t			t;
+	char			marker[ 1024 ];
+	int				size;
+	
+	
+	/* set header */
+	header = &outheader;
+	memset( header, 0, sizeof( *header ) );
+	
+	//%	Swapfile();
+	
+	/* set up header */
+	*((int*) (bspHeader_t*) header->ident) = *((int*) game->bspIdent);
+	header->version = LittleLong( game->bspVersion );
+	
+	/* write initial header */
+	file = SafeOpenWrite( filename );
+	SafeWrite( file, (bspHeader_t*) header, sizeof( *header ) );	/* overwritten later */
+	
+	/* add marker lump */
+	time( &t );
+	sprintf( marker, "I LOVE MY Q3MAP2 %s on %s)", Q3MAP_VERSION, asctime( localtime( &t ) ) );
+	AddLump( file, (bspHeader_t*) header, 0, marker, strlen( marker ) + 1 );
+	
+	/* add lumps */
+	AddLump( file, (bspHeader_t*) header, LUMP_SHADERS, bspShaders, numBSPShaders * sizeof( bspShader_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_PLANES, bspPlanes, numBSPPlanes * sizeof( bspPlane_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_LEAFS, bspLeafs, numBSPLeafs * sizeof( bspLeaf_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_NODES, bspNodes, numBSPNodes * sizeof( bspNode_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHES, bspBrushes, numBSPBrushes*sizeof( bspBrush_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_BRUSHSIDES, bspBrushSides, numBSPBrushSides * sizeof( bspBrushSides[ 0 ] ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_LEAFSURFACES, bspLeafSurfaces, numBSPLeafSurfaces * sizeof( bspLeafSurfaces[ 0 ] ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_LEAFBRUSHES, bspLeafBrushes, numBSPLeafBrushes * sizeof( bspLeafBrushes[ 0 ] ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_MODELS, bspModels, numBSPModels * sizeof( bspModel_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_DRAWVERTS, bspDrawVerts, numBSPDrawVerts * sizeof( bspDrawVerts[ 0 ] ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_SURFACES, bspDrawSurfaces, numBSPDrawSurfaces * sizeof( bspDrawSurfaces[ 0 ] ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_VISIBILITY, bspVisBytes, numBSPVisBytes );
+	AddLump( file, (bspHeader_t*) header, LUMP_LIGHTMAPS, bspLightBytes, numBSPLightBytes );
+	AddLightGridLumps( file, header );
+	AddLump( file, (bspHeader_t*) header, LUMP_ENTITIES, bspEntData, bspEntDataSize );
+	AddLump( file, (bspHeader_t*) header, LUMP_FOGS, bspFogs, numBSPFogs * sizeof( bspFog_t ) );
+	AddLump( file, (bspHeader_t*) header, LUMP_DRAWINDEXES, bspDrawIndexes, numBSPDrawIndexes * sizeof( bspDrawIndexes[ 0 ] ) );
+	
+	/* emit bsp size */
+	size = ftell( file );
+	Sys_Printf( "Wrote %.1f MB (%d bytes)\n", (float) size / (1024 * 1024), size );
+	
+	/* write the completed header */
+	fseek( file, 0, SEEK_SET );
+	SafeWrite( file, header, sizeof( *header ) );
+	
+	/* close the file */
+	fclose( file );	
+}
diff --git a/tools/quake3/q3map2/convert_ase.c b/tools/quake3/q3map2/convert_ase.c
index 1d937c76..f0ac6df5 100644
--- a/tools/quake3/q3map2/convert_ase.c
+++ b/tools/quake3/q3map2/convert_ase.c
@@ -1,374 +1,374 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define CONVERT_ASE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-ConvertSurface()
-converts a bsp drawsurface to an ase chunk
-*/
-
-static void ConvertSurface( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, vec3_t origin )
-{
-	int				i, v, face, a, b, c;
-	bspDrawVert_t	*dv;
-	vec3_t			normal;
-	char			name[ 1024 ];
-	
-	
-	/* ignore patches for now */
-	if( ds->surfaceType != MST_PLANAR && ds->surfaceType != MST_TRIANGLE_SOUP )
-		return;
-	
-	/* print object header for each dsurf */
-	sprintf( name, "mat%dmodel%dsurf%d", ds->shaderNum, modelNum, surfaceNum );
-	fprintf( f, "*GEOMOBJECT\t{\r\n" );
-	fprintf( f, "\t*NODE_NAME\t\"%s\"\r\n", name );
-	fprintf( f, "\t*NODE_TM\t{\r\n" );
-	fprintf( f, "\t\t*NODE_NAME\t\"%s\"\r\n", name );
-	fprintf( f, "\t\t*INHERIT_POS\t0\t0\t0\r\n" );
-	fprintf( f, "\t\t*INHERIT_ROT\t0\t0\t0\r\n" );
-	fprintf( f, "\t\t*INHERIT_SCL\t0\t0\t0\r\n" );
-	fprintf( f, "\t\t*TM_ROW0\t1.0\t0\t0\r\n" );
-	fprintf( f, "\t\t*TM_ROW1\t0\t1.0\t0\r\n" );
-	fprintf( f, "\t\t*TM_ROW2\t0\t0\t1.0\r\n" );
-	fprintf( f, "\t\t*TM_ROW3\t0\t0\t0\r\n" );
-	fprintf( f, "\t\t*TM_POS\t%f\t%f\t%f\r\n", origin[ 0 ], origin[ 1 ], origin[ 2 ] );
-	fprintf( f, "\t}\r\n" );
-	
-	/* print mesh header */
-	fprintf( f, "\t*MESH\t{\r\n" );
-	fprintf( f, "\t\t*TIMEVALUE\t0\r\n" );
-	fprintf( f, "\t\t*MESH_NUMVERTEX\t%d\r\n", ds->numVerts );
-	fprintf( f, "\t\t*MESH_NUMFACES\t%d\r\n", ds->numIndexes / 3 );
-	switch( ds->surfaceType )
-	{
-		case MST_PLANAR:
-			fprintf( f, "\t\t*COMMENT\t\"SURFACETYPE\tMST_PLANAR\"\r\n" );
-			break;
-		case MST_TRIANGLE_SOUP:
-			fprintf( f, "\t\t*COMMENT\t\"SURFACETYPE\tMST_TRIANGLE_SOUP\"\r\n" );
-			break;
-	}
-	
-	/* export vertex xyz */
-	fprintf( f, "\t\t*MESH_VERTEX_LIST\t{\r\n" );
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		v = i + ds->firstVert;
-		dv = &bspDrawVerts[ v ];
-		fprintf( f, "\t\t\t*MESH_VERTEX\t%d\t%f\t%f\t%f\r\n", i, dv->xyz[ 0 ], dv->xyz[ 1 ], dv->xyz[ 2 ] );
-	}
-	fprintf( f, "\t\t}\r\n" );
-
-	/* export vertex normals */
-	fprintf( f, "\t\t*MESH_NORMALS\t{\r\n" );
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		face = (i / 3);
-		a = bspDrawIndexes[ i + ds->firstIndex ];
-		b = bspDrawIndexes[ i + ds->firstIndex + 1 ];
-		c = bspDrawIndexes[ i + ds->firstIndex + 2 ];
-		VectorCopy( bspDrawVerts[ a ].normal, normal );
-		VectorAdd( normal, bspDrawVerts[ b ].normal, normal );
-		VectorAdd( normal, bspDrawVerts[ c ].normal, normal );
-		if( VectorNormalize( normal, normal ) )
-			fprintf( f, "\t\t\t*MESH_FACENORMAL\t%d\t%f\t%f\t%f\r\n", face, normal[ 0 ], normal[ 1 ], normal[ 2 ] );
-	}
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		v = i + ds->firstVert;
-		dv = &bspDrawVerts[ v ];
-		fprintf( f, "\t\t\t*MESH_VERTEXNORMAL\t%d\t%f\t%f\t%f\r\n", i, dv->normal[ 0 ], dv->normal[ 1 ], dv->normal[ 2 ] );
-	}
-	fprintf( f, "\t\t}\r\n" );
-	
-	/* export faces */
-	fprintf( f, "\t\t*MESH_FACE_LIST\t{\r\n" );
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		face = (i / 3);
-		a = bspDrawIndexes[ i + ds->firstIndex ];
-		c = bspDrawIndexes[ i + ds->firstIndex + 1 ];
-		b = bspDrawIndexes[ i + ds->firstIndex + 2 ];
-		fprintf( f, "\t\t\t*MESH_FACE\t%d\tA:\t%d\tB:\t%d\tC:\t%d\tAB:\t1\tBC:\t1\tCA:\t1\t*MESH_SMOOTHING\t0\t*MESH_MTLID\t0\r\n",
-			face, a, b, c );
-	}
-	fprintf( f, "\t\t}\r\n" );
-	
-	/* export vertex st */
-	fprintf( f, "\t\t*MESH_NUMTVERTEX\t%d\r\n", ds->numVerts );
-	fprintf( f, "\t\t*MESH_TVERTLIST\t{\r\n" );
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		v = i + ds->firstVert;
-		dv = &bspDrawVerts[ v ];
-		fprintf( f, "\t\t\t*MESH_TVERT\t%d\t%f\t%f\t%f\r\n", i, dv->st[ 0 ], (1.0 - dv->st[ 1 ]), 1.0f );
-	}
-	fprintf( f, "\t\t}\r\n" );
-	
-	/* export texture faces */
-	fprintf( f, "\t\t*MESH_NUMTVFACES\t%d\r\n", ds->numIndexes / 3 );
-	fprintf( f, "\t\t*MESH_TFACELIST\t{\r\n" );
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		face = (i / 3);
-		a = bspDrawIndexes[ i + ds->firstIndex ];
-		c = bspDrawIndexes[ i + ds->firstIndex + 1 ];
-		b = bspDrawIndexes[ i + ds->firstIndex + 2 ];
-		fprintf( f, "\t\t\t*MESH_TFACE\t%d\t%d\t%d\t%d\r\n", face, a, b, c );
-	}
-	fprintf( f, "\t\t}\r\n" );
-	
-	/* print mesh footer */
-	fprintf( f, "\t}\r\n" );
-
-	/* print object footer */
-	fprintf( f, "\t*PROP_MOTIONBLUR\t0\r\n" );
-	fprintf( f, "\t*PROP_CASTSHADOW\t1\r\n" );
-	fprintf( f, "\t*PROP_RECVSHADOW\t1\r\n" );
-	fprintf( f, "\t*MATERIAL_REF\t%d\r\n", ds->shaderNum );
-	fprintf( f, "}\r\n" );
-}
-
-
-
-/*
-ConvertModel()
-exports a bsp model to an ase chunk
-*/
-
-static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
-{
-	int					i, s;
-	bspDrawSurface_t	*ds;
-	
-	
-	/* go through each drawsurf in the model */
-	for( i = 0; i < model->numBSPSurfaces; i++ )
-	{
-		s = i + model->firstBSPSurface;
-		ds = &bspDrawSurfaces[ s ];
-		ConvertSurface( f, model, modelNum, ds, s, origin );
-	}
-}
-
-
-
-/*
-ConvertShader()
-exports a bsp shader to an ase chunk
-*/
-
-/*
-	*MATERIAL 0 {
-		*MATERIAL_NAME "models/test/rock16l"
-		*MATERIAL_CLASS "Standard"
-		*MATERIAL_AMBIENT 0.5882	0.5882	0.5882
-		*MATERIAL_DIFFUSE 0.5882	0.5882	0.5882
-		*MATERIAL_SPECULAR 0.5882	0.5882	0.5882
-		*MATERIAL_SHINE 0.0000
-		*MATERIAL_SHINESTRENGTH 0.0000
-		*MATERIAL_TRANSPARENCY 0.0000
-		*MATERIAL_WIRESIZE 1.0000
-		*MATERIAL_SHADING Phong
-		*MATERIAL_XP_FALLOFF 0.0000
-		*MATERIAL_SELFILLUM 0.0000
-		*MATERIAL_FALLOFF In
-		*MATERIAL_XP_TYPE Filter
-		*MAP_DIFFUSE {
-			*MAP_NAME "Map #2"
-			*MAP_CLASS "Bitmap"
-			*MAP_SUBNO 1
-			*MAP_AMOUNT 1.0000
-			*BITMAP "models/test/rock16l"
-			*MAP_TYPE Screen
-			*UVW_U_OFFSET 0.0000
-			*UVW_V_OFFSET 0.0000
-			*UVW_U_TILING 1.0000
-			*UVW_V_TILING 1.0000
-			*UVW_ANGLE 0.0000
-			*UVW_BLUR 1.0000
-			*UVW_BLUR_OFFSET 0.0000
-			*UVW_NOUSE_AMT 1.0000
-			*UVW_NOISE_SIZE 1.0000
-			*UVW_NOISE_LEVEL 1
-			*UVW_NOISE_PHASE 0.0000
-			*BITMAP_FILTER Pyramidal
-		}
-	}
-*/
-
-static void ConvertShader( FILE *f, bspShader_t *shader, int shaderNum )
-{
-	shaderInfo_t	*si;
-	char			*c, filename[ 1024 ];
-	
-	
-	/* get shader */
-	si = ShaderInfoForShader( shader->shader );
-	if( si == NULL )
-	{
-		Sys_Printf( "WARNING: NULL shader in BSP\n" );
-		return;
-	}
-	
-	/* set bitmap filename */
-	if( si->shaderImage->filename[ 0 ] != '*' )
-		strcpy( filename, si->shaderImage->filename );
-	else
-		sprintf( filename, "%s.tga", si->shader );
-	for( c = filename; *c != '\0'; c++ )
-		if( *c == '/' )
-			*c = '\\';
-	
-	/* print shader info */
-	fprintf( f, "\t*MATERIAL\t%d\t{\r\n", shaderNum );
-	fprintf( f, "\t\t*MATERIAL_NAME\t\"%s\"\r\n", shader->shader );
-	fprintf( f, "\t\t*MATERIAL_CLASS\t\"Standard\"\r\n" );
-	fprintf( f, "\t\t*MATERIAL_DIFFUSE\t%f\t%f\t%f\r\n", si->color[ 0 ], si->color[ 1 ], si->color[ 2 ] );
-	fprintf( f, "\t\t*MATERIAL_SHADING Phong\r\n" );
-	
-	/* print map info */
-	fprintf( f, "\t\t*MAP_DIFFUSE\t{\r\n" );
-	fprintf( f, "\t\t\t*MAP_NAME\t\"%s\"\r\n", shader->shader );
-	fprintf( f, "\t\t\t*MAP_CLASS\t\"Bitmap\"\r\n");
-	fprintf( f, "\t\t\t*MAP_SUBNO\t1\r\n" );
-	fprintf( f, "\t\t\t*MAP_AMOUNT\t1.0\r\n" );
-	fprintf( f, "\t\t\t*MAP_TYPE\tScreen\r\n" );
-	fprintf( f, "\t\t\t*BITMAP\t\"..\\%s\"\r\n", filename );
-	fprintf( f, "\t\t\t*BITMAP_FILTER\tPyramidal\r\n" );
-	fprintf( f, "\t\t}\r\n" );
-	
-	fprintf( f, "\t}\r\n" );
-}
-
-
-
-/*
-ConvertBSPToASE()
-exports an 3d studio ase file from the bsp
-*/
-
-int ConvertBSPToASE( char *bspName )
-{
-	int				i, modelNum;
-	FILE			*f;
-	bspShader_t		*shader;
-	bspModel_t		*model;
-	entity_t		*e;
-	vec3_t			origin;
-	const char		*key;
-	char			name[ 1024 ], base[ 1024 ];
-	
-	
-	/* note it */
-	Sys_Printf( "--- Convert BSP to ASE ---\n" );
-
-	/* create the ase filename from the bsp name */
-	strcpy( name, bspName );
-	StripExtension( name );
-	strcat( name, ".ase" );
-	Sys_Printf( "writing %s\n", name );
-	
-	ExtractFileBase( bspName, base );
-	strcat( base, ".bsp" );
-	
-	/* open it */
-	f = fopen( name, "wb" );
-	if( f == NULL )
-		Error( "Open failed on %s\n", name );
-	
-	/* print header */
-	fprintf( f, "*3DSMAX_ASCIIEXPORT\t200\r\n" );
-	fprintf( f, "*COMMENT\t\"Generated by Q3Map2 (ydnar) -convert -format ase\"\r\n" );
-	fprintf( f, "*SCENE\t{\r\n" );
-	fprintf( f, "\t*SCENE_FILENAME\t\"%s\"\r\n", base );
-	fprintf( f, "\t*SCENE_FIRSTFRAME\t0\r\n" );
-	fprintf( f, "\t*SCENE_LASTFRAME\t100\r\n" );
-	fprintf( f, "\t*SCENE_FRAMESPEED\t30\r\n" );
-	fprintf( f, "\t*SCENE_TICKSPERFRAME\t160\r\n" );
-	fprintf( f, "\t*SCENE_BACKGROUND_STATIC\t0.0000\t0.0000\t0.0000\r\n" );
-	fprintf( f, "\t*SCENE_AMBIENT_STATIC\t0.0000\t0.0000\t0.0000\r\n" );
-	fprintf( f, "}\r\n" );
-	
-	/* print materials */
-	fprintf( f, "*MATERIAL_LIST\t{\r\n" );
-	fprintf( f, "\t*MATERIAL_COUNT\t%d\r\n", numBSPShaders );
-	for( i = 0; i < numBSPShaders; i++ )
-	{
-		shader = &bspShaders[ i ];
-		ConvertShader( f, shader, i );
-	}
-	fprintf( f, "}\r\n" );
-	
-	/* walk entity list */
-	for( i = 0; i < numEntities; i++ )
-	{
-		/* get entity and model */
-		e = &entities[ i ];
-		if( i == 0 )
-			modelNum = 0;
-		else
-		{
-			key = ValueForKey( e, "model" );
-			if( key[ 0 ] != '*' )
-				continue;
-			modelNum = atoi( key + 1 );
-		}
-		model = &bspModels[ modelNum ];
-		
-		/* get entity origin */
-		key = ValueForKey( e, "origin" );
-		if( key[ 0 ] == '\0' )
-			VectorClear( origin );
-		else
-			GetVectorForKey( e, "origin", origin );
-		
-		/* convert model */
-		ConvertModel( f, model, modelNum, origin );
-	}
-	
-	/* close the file and return */
-	fclose( f );
-	
-	/* return to sender */
-	return 0;
-}
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define CONVERT_ASE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+ConvertSurface()
+converts a bsp drawsurface to an ase chunk
+*/
+
+static void ConvertSurface( FILE *f, bspModel_t *model, int modelNum, bspDrawSurface_t *ds, int surfaceNum, vec3_t origin )
+{
+	int				i, v, face, a, b, c;
+	bspDrawVert_t	*dv;
+	vec3_t			normal;
+	char			name[ 1024 ];
+	
+	
+	/* ignore patches for now */
+	if( ds->surfaceType != MST_PLANAR && ds->surfaceType != MST_TRIANGLE_SOUP )
+		return;
+	
+	/* print object header for each dsurf */
+	sprintf( name, "mat%dmodel%dsurf%d", ds->shaderNum, modelNum, surfaceNum );
+	fprintf( f, "*GEOMOBJECT\t{\r\n" );
+	fprintf( f, "\t*NODE_NAME\t\"%s\"\r\n", name );
+	fprintf( f, "\t*NODE_TM\t{\r\n" );
+	fprintf( f, "\t\t*NODE_NAME\t\"%s\"\r\n", name );
+	fprintf( f, "\t\t*INHERIT_POS\t0\t0\t0\r\n" );
+	fprintf( f, "\t\t*INHERIT_ROT\t0\t0\t0\r\n" );
+	fprintf( f, "\t\t*INHERIT_SCL\t0\t0\t0\r\n" );
+	fprintf( f, "\t\t*TM_ROW0\t1.0\t0\t0\r\n" );
+	fprintf( f, "\t\t*TM_ROW1\t0\t1.0\t0\r\n" );
+	fprintf( f, "\t\t*TM_ROW2\t0\t0\t1.0\r\n" );
+	fprintf( f, "\t\t*TM_ROW3\t0\t0\t0\r\n" );
+	fprintf( f, "\t\t*TM_POS\t%f\t%f\t%f\r\n", origin[ 0 ], origin[ 1 ], origin[ 2 ] );
+	fprintf( f, "\t}\r\n" );
+	
+	/* print mesh header */
+	fprintf( f, "\t*MESH\t{\r\n" );
+	fprintf( f, "\t\t*TIMEVALUE\t0\r\n" );
+	fprintf( f, "\t\t*MESH_NUMVERTEX\t%d\r\n", ds->numVerts );
+	fprintf( f, "\t\t*MESH_NUMFACES\t%d\r\n", ds->numIndexes / 3 );
+	switch( ds->surfaceType )
+	{
+		case MST_PLANAR:
+			fprintf( f, "\t\t*COMMENT\t\"SURFACETYPE\tMST_PLANAR\"\r\n" );
+			break;
+		case MST_TRIANGLE_SOUP:
+			fprintf( f, "\t\t*COMMENT\t\"SURFACETYPE\tMST_TRIANGLE_SOUP\"\r\n" );
+			break;
+	}
+	
+	/* export vertex xyz */
+	fprintf( f, "\t\t*MESH_VERTEX_LIST\t{\r\n" );
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		v = i + ds->firstVert;
+		dv = &bspDrawVerts[ v ];
+		fprintf( f, "\t\t\t*MESH_VERTEX\t%d\t%f\t%f\t%f\r\n", i, dv->xyz[ 0 ], dv->xyz[ 1 ], dv->xyz[ 2 ] );
+	}
+	fprintf( f, "\t\t}\r\n" );
+
+	/* export vertex normals */
+	fprintf( f, "\t\t*MESH_NORMALS\t{\r\n" );
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		face = (i / 3);
+		a = bspDrawIndexes[ i + ds->firstIndex ];
+		b = bspDrawIndexes[ i + ds->firstIndex + 1 ];
+		c = bspDrawIndexes[ i + ds->firstIndex + 2 ];
+		VectorCopy( bspDrawVerts[ a ].normal, normal );
+		VectorAdd( normal, bspDrawVerts[ b ].normal, normal );
+		VectorAdd( normal, bspDrawVerts[ c ].normal, normal );
+		if( VectorNormalize( normal, normal ) )
+			fprintf( f, "\t\t\t*MESH_FACENORMAL\t%d\t%f\t%f\t%f\r\n", face, normal[ 0 ], normal[ 1 ], normal[ 2 ] );
+	}
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		v = i + ds->firstVert;
+		dv = &bspDrawVerts[ v ];
+		fprintf( f, "\t\t\t*MESH_VERTEXNORMAL\t%d\t%f\t%f\t%f\r\n", i, dv->normal[ 0 ], dv->normal[ 1 ], dv->normal[ 2 ] );
+	}
+	fprintf( f, "\t\t}\r\n" );
+	
+	/* export faces */
+	fprintf( f, "\t\t*MESH_FACE_LIST\t{\r\n" );
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		face = (i / 3);
+		a = bspDrawIndexes[ i + ds->firstIndex ];
+		c = bspDrawIndexes[ i + ds->firstIndex + 1 ];
+		b = bspDrawIndexes[ i + ds->firstIndex + 2 ];
+		fprintf( f, "\t\t\t*MESH_FACE\t%d\tA:\t%d\tB:\t%d\tC:\t%d\tAB:\t1\tBC:\t1\tCA:\t1\t*MESH_SMOOTHING\t0\t*MESH_MTLID\t0\r\n",
+			face, a, b, c );
+	}
+	fprintf( f, "\t\t}\r\n" );
+	
+	/* export vertex st */
+	fprintf( f, "\t\t*MESH_NUMTVERTEX\t%d\r\n", ds->numVerts );
+	fprintf( f, "\t\t*MESH_TVERTLIST\t{\r\n" );
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		v = i + ds->firstVert;
+		dv = &bspDrawVerts[ v ];
+		fprintf( f, "\t\t\t*MESH_TVERT\t%d\t%f\t%f\t%f\r\n", i, dv->st[ 0 ], (1.0 - dv->st[ 1 ]), 1.0f );
+	}
+	fprintf( f, "\t\t}\r\n" );
+	
+	/* export texture faces */
+	fprintf( f, "\t\t*MESH_NUMTVFACES\t%d\r\n", ds->numIndexes / 3 );
+	fprintf( f, "\t\t*MESH_TFACELIST\t{\r\n" );
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		face = (i / 3);
+		a = bspDrawIndexes[ i + ds->firstIndex ];
+		c = bspDrawIndexes[ i + ds->firstIndex + 1 ];
+		b = bspDrawIndexes[ i + ds->firstIndex + 2 ];
+		fprintf( f, "\t\t\t*MESH_TFACE\t%d\t%d\t%d\t%d\r\n", face, a, b, c );
+	}
+	fprintf( f, "\t\t}\r\n" );
+	
+	/* print mesh footer */
+	fprintf( f, "\t}\r\n" );
+
+	/* print object footer */
+	fprintf( f, "\t*PROP_MOTIONBLUR\t0\r\n" );
+	fprintf( f, "\t*PROP_CASTSHADOW\t1\r\n" );
+	fprintf( f, "\t*PROP_RECVSHADOW\t1\r\n" );
+	fprintf( f, "\t*MATERIAL_REF\t%d\r\n", ds->shaderNum );
+	fprintf( f, "}\r\n" );
+}
+
+
+
+/*
+ConvertModel()
+exports a bsp model to an ase chunk
+*/
+
+static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
+{
+	int					i, s;
+	bspDrawSurface_t	*ds;
+	
+	
+	/* go through each drawsurf in the model */
+	for( i = 0; i < model->numBSPSurfaces; i++ )
+	{
+		s = i + model->firstBSPSurface;
+		ds = &bspDrawSurfaces[ s ];
+		ConvertSurface( f, model, modelNum, ds, s, origin );
+	}
+}
+
+
+
+/*
+ConvertShader()
+exports a bsp shader to an ase chunk
+*/
+
+/*
+	*MATERIAL 0 {
+		*MATERIAL_NAME "models/test/rock16l"
+		*MATERIAL_CLASS "Standard"
+		*MATERIAL_AMBIENT 0.5882	0.5882	0.5882
+		*MATERIAL_DIFFUSE 0.5882	0.5882	0.5882
+		*MATERIAL_SPECULAR 0.5882	0.5882	0.5882
+		*MATERIAL_SHINE 0.0000
+		*MATERIAL_SHINESTRENGTH 0.0000
+		*MATERIAL_TRANSPARENCY 0.0000
+		*MATERIAL_WIRESIZE 1.0000
+		*MATERIAL_SHADING Phong
+		*MATERIAL_XP_FALLOFF 0.0000
+		*MATERIAL_SELFILLUM 0.0000
+		*MATERIAL_FALLOFF In
+		*MATERIAL_XP_TYPE Filter
+		*MAP_DIFFUSE {
+			*MAP_NAME "Map #2"
+			*MAP_CLASS "Bitmap"
+			*MAP_SUBNO 1
+			*MAP_AMOUNT 1.0000
+			*BITMAP "models/test/rock16l"
+			*MAP_TYPE Screen
+			*UVW_U_OFFSET 0.0000
+			*UVW_V_OFFSET 0.0000
+			*UVW_U_TILING 1.0000
+			*UVW_V_TILING 1.0000
+			*UVW_ANGLE 0.0000
+			*UVW_BLUR 1.0000
+			*UVW_BLUR_OFFSET 0.0000
+			*UVW_NOUSE_AMT 1.0000
+			*UVW_NOISE_SIZE 1.0000
+			*UVW_NOISE_LEVEL 1
+			*UVW_NOISE_PHASE 0.0000
+			*BITMAP_FILTER Pyramidal
+		}
+	}
+*/
+
+static void ConvertShader( FILE *f, bspShader_t *shader, int shaderNum )
+{
+	shaderInfo_t	*si;
+	char			*c, filename[ 1024 ];
+	
+	
+	/* get shader */
+	si = ShaderInfoForShader( shader->shader );
+	if( si == NULL )
+	{
+		Sys_Printf( "WARNING: NULL shader in BSP\n" );
+		return;
+	}
+	
+	/* set bitmap filename */
+	if( si->shaderImage->filename[ 0 ] != '*' )
+		strcpy( filename, si->shaderImage->filename );
+	else
+		sprintf( filename, "%s.tga", si->shader );
+	for( c = filename; *c != '\0'; c++ )
+		if( *c == '/' )
+			*c = '\\';
+	
+	/* print shader info */
+	fprintf( f, "\t*MATERIAL\t%d\t{\r\n", shaderNum );
+	fprintf( f, "\t\t*MATERIAL_NAME\t\"%s\"\r\n", shader->shader );
+	fprintf( f, "\t\t*MATERIAL_CLASS\t\"Standard\"\r\n" );
+	fprintf( f, "\t\t*MATERIAL_DIFFUSE\t%f\t%f\t%f\r\n", si->color[ 0 ], si->color[ 1 ], si->color[ 2 ] );
+	fprintf( f, "\t\t*MATERIAL_SHADING Phong\r\n" );
+	
+	/* print map info */
+	fprintf( f, "\t\t*MAP_DIFFUSE\t{\r\n" );
+	fprintf( f, "\t\t\t*MAP_NAME\t\"%s\"\r\n", shader->shader );
+	fprintf( f, "\t\t\t*MAP_CLASS\t\"Bitmap\"\r\n");
+	fprintf( f, "\t\t\t*MAP_SUBNO\t1\r\n" );
+	fprintf( f, "\t\t\t*MAP_AMOUNT\t1.0\r\n" );
+	fprintf( f, "\t\t\t*MAP_TYPE\tScreen\r\n" );
+	fprintf( f, "\t\t\t*BITMAP\t\"..\\%s\"\r\n", filename );
+	fprintf( f, "\t\t\t*BITMAP_FILTER\tPyramidal\r\n" );
+	fprintf( f, "\t\t}\r\n" );
+	
+	fprintf( f, "\t}\r\n" );
+}
+
+
+
+/*
+ConvertBSPToASE()
+exports an 3d studio ase file from the bsp
+*/
+
+int ConvertBSPToASE( char *bspName )
+{
+	int				i, modelNum;
+	FILE			*f;
+	bspShader_t		*shader;
+	bspModel_t		*model;
+	entity_t		*e;
+	vec3_t			origin;
+	const char		*key;
+	char			name[ 1024 ], base[ 1024 ];
+	
+	
+	/* note it */
+	Sys_Printf( "--- Convert BSP to ASE ---\n" );
+
+	/* create the ase filename from the bsp name */
+	strcpy( name, bspName );
+	StripExtension( name );
+	strcat( name, ".ase" );
+	Sys_Printf( "writing %s\n", name );
+	
+	ExtractFileBase( bspName, base );
+	strcat( base, ".bsp" );
+	
+	/* open it */
+	f = fopen( name, "wb" );
+	if( f == NULL )
+		Error( "Open failed on %s\n", name );
+	
+	/* print header */
+	fprintf( f, "*3DSMAX_ASCIIEXPORT\t200\r\n" );
+	fprintf( f, "*COMMENT\t\"Generated by Q3Map2 (ydnar) -convert -format ase\"\r\n" );
+	fprintf( f, "*SCENE\t{\r\n" );
+	fprintf( f, "\t*SCENE_FILENAME\t\"%s\"\r\n", base );
+	fprintf( f, "\t*SCENE_FIRSTFRAME\t0\r\n" );
+	fprintf( f, "\t*SCENE_LASTFRAME\t100\r\n" );
+	fprintf( f, "\t*SCENE_FRAMESPEED\t30\r\n" );
+	fprintf( f, "\t*SCENE_TICKSPERFRAME\t160\r\n" );
+	fprintf( f, "\t*SCENE_BACKGROUND_STATIC\t0.0000\t0.0000\t0.0000\r\n" );
+	fprintf( f, "\t*SCENE_AMBIENT_STATIC\t0.0000\t0.0000\t0.0000\r\n" );
+	fprintf( f, "}\r\n" );
+	
+	/* print materials */
+	fprintf( f, "*MATERIAL_LIST\t{\r\n" );
+	fprintf( f, "\t*MATERIAL_COUNT\t%d\r\n", numBSPShaders );
+	for( i = 0; i < numBSPShaders; i++ )
+	{
+		shader = &bspShaders[ i ];
+		ConvertShader( f, shader, i );
+	}
+	fprintf( f, "}\r\n" );
+	
+	/* walk entity list */
+	for( i = 0; i < numEntities; i++ )
+	{
+		/* get entity and model */
+		e = &entities[ i ];
+		if( i == 0 )
+			modelNum = 0;
+		else
+		{
+			key = ValueForKey( e, "model" );
+			if( key[ 0 ] != '*' )
+				continue;
+			modelNum = atoi( key + 1 );
+		}
+		model = &bspModels[ modelNum ];
+		
+		/* get entity origin */
+		key = ValueForKey( e, "origin" );
+		if( key[ 0 ] == '\0' )
+			VectorClear( origin );
+		else
+			GetVectorForKey( e, "origin", origin );
+		
+		/* convert model */
+		ConvertModel( f, model, modelNum, origin );
+	}
+	
+	/* close the file and return */
+	fclose( f );
+	
+	/* return to sender */
+	return 0;
+}
+
+
+
diff --git a/tools/quake3/q3map2/convert_map.c b/tools/quake3/q3map2/convert_map.c
index ff69c8a5..ca0ba7fb 100644
--- a/tools/quake3/q3map2/convert_map.c
+++ b/tools/quake3/q3map2/convert_map.c
@@ -1,443 +1,443 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define CONVERT_MAP_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-ConvertBrush()
-exports a map brush
-*/
-
-#define	SNAP_FLOAT_TO_INT	4
-#define	SNAP_INT_TO_FLOAT	(1.0 / SNAP_FLOAT_TO_INT)
-
-static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
-{
-	int				i, j;
-	bspBrushSide_t	*side;
-	side_t			*buildSide;
-	bspShader_t		*shader;
-	char			*texture;
-	bspPlane_t		*plane;
-	vec3_t			pts[ 3 ];
-	
-	
-	/* start brush */
-	fprintf( f, "\t// brush %d\n", num );
-	fprintf( f, "\t{\n" );
-	
-	/* clear out build brush */
-	for( i = 0; i < buildBrush->numsides; i++ )
-	{
-		buildSide = &buildBrush->sides[ i ];
-		if( buildSide->winding != NULL )
-		{
-			FreeWinding( buildSide->winding );
-			buildSide->winding = NULL;
-		}
-	}
-	buildBrush->numsides = 0;
-	
-	/* iterate through bsp brush sides */
-	for( i = 0; i < brush->numSides; i++ )
-	{
-		/* get side */
-		side = &bspBrushSides[ brush->firstSide + i ];
-		
-		/* get shader */
-		if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
-			continue;
-		shader = &bspShaders[ side->shaderNum ];
-		if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
-			continue;
-		
-		/* get plane */
-		plane = &bspPlanes[ side->planeNum ];
-		
-		/* add build side */
-		buildSide = &buildBrush->sides[ buildBrush->numsides ];
-		buildBrush->numsides++;
-		
-		/* tag it */
-		buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
-		buildSide->planenum = side->planeNum;
-		buildSide->winding = NULL;
-	}
-	
-	/* make brush windings */
-	if( !CreateBrushWindings( buildBrush ) )
-		return;
-	
-	/* iterate through build brush sides */
-	for( i = 0; i < buildBrush->numsides; i++ )
-	{
-		/* get build side */
-		buildSide = &buildBrush->sides[ i ];
-		
-		/* dummy check */
-		if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
-			continue;
-		
-		/* get texture name */
-		if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
-			texture = buildSide->shaderInfo->shader + 9;
-		else
-			texture = buildSide->shaderInfo->shader;
-		
-		/* get plane points and offset by origin */
-		for( j = 0; j < 3; j++ )
-		{
-			VectorAdd( buildSide->winding->p[ j ], origin, pts[ j ] );
-			//%	pts[ j ][ 0 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 0 ] * SNAP_FLOAT_TO_INT + 0.5f );
-			//%	pts[ j ][ 1 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 1 ] * SNAP_FLOAT_TO_INT + 0.5f );
-			//%	pts[ j ][ 2 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 2 ] * SNAP_FLOAT_TO_INT + 0.5f );
-		}
-		
-		/* print brush side */
-		/* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
-		fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s 0 0 0 0.5 0.5 0 0 0\n",
-			pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
-			pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
-			pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
-			texture );
-	}
-	
-	/* end brush */
-	fprintf( f, "\t}\n\n" );
-}
-
-#if 0
-	/* iterate through the brush sides (ignore the first 6 bevel planes) */
-	for( i = 0; i < brush->numSides; i++ )
-	{
-		/* get side */
-		side = &bspBrushSides[ brush->firstSide + i ];
-		
-		/* get shader */
-		if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
-			continue;
-		shader = &bspShaders[ side->shaderNum ];
-		if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
-			continue;
-		
-		/* get texture name */
-		if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
-			texture = shader->shader + 9;
-		else
-			texture = shader->shader;
-		
-		/* get plane */
-		plane = &bspPlanes[ side->planeNum ];
-
-		/* make plane points */
-		{
-			vec3_t	vecs[ 2 ];
-
-			
-			MakeNormalVectors( plane->normal, vecs[ 0 ], vecs[ 1 ] );
-			VectorMA( vec3_origin, plane->dist, plane->normal, pts[ 0 ] );
-			VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
-			VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
-		}
-
-		/* offset by origin */
-		for( j = 0; j < 3; j++ )
-			VectorAdd( pts[ j ], origin, pts[ j ] );
-		
-		/* print brush side */
-		/* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
-		fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s 0 0 0 0.5 0.5 0 0 0\n",
-			pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
-			pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
-			pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
-			texture );
-	}
-#endif
-
-
-
-/*
-ConvertPatch()
-converts a bsp patch to a map patch
-
-	{
-		patchDef2
-		{
-			base_wall/concrete
-			( 9 3 0 0 0 )
-			(
-				( ( 168 168 -192 0 2 ) ( 168 168 -64 0 1 ) ( 168 168 64 0 0 ) ... )
-				...
-			)
-		}
-	}
-
-*/
-
-static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin )
-{
-	int				x, y;
-	bspShader_t		*shader;
-	char			*texture;
-	bspDrawVert_t	*dv;
-	vec3_t			xyz;
-	
-	
-	/* only patches */
-	if( ds->surfaceType != MST_PATCH )
-		return;
-	
-	/* get shader */
-	if( ds->shaderNum < 0 || ds->shaderNum >= numBSPShaders )
-		return;
-	shader = &bspShaders[ ds->shaderNum ];
-	
-	/* get texture name */
-	if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
-		texture = shader->shader + 9;
-	else
-		texture = shader->shader;
-	
-	/* start patch */
-	fprintf( f, "\t// patch %d\n", num );
-	fprintf( f, "\t{\n" );
-	fprintf( f, "\t\tpatchDef2\n" );
-	fprintf( f, "\t\t{\n" );
-	fprintf( f, "\t\t\t%s\n", texture );
-	fprintf( f, "\t\t\t( %d %d 0 0 0 )\n", ds->patchWidth, ds->patchHeight );
-	fprintf( f, "\t\t\t(\n" );
-	
-	/* iterate through the verts */
-	for( x = 0; x < ds->patchWidth; x++ )
-	{
-		/* start row */
-		fprintf( f, "\t\t\t\t(" );
-		
-		/* iterate through the row */
-		for( y = 0; y < ds->patchHeight; y++ )
-		{
-			/* get vert */
-			dv = &bspDrawVerts[ ds->firstVert + (y * ds->patchWidth) + x ];
-			
-			/* offset it */
-			VectorAdd( origin, dv->xyz, xyz );
-			
-			/* print vertex */
-			fprintf( f, " ( %f %f %f %f %f )", xyz[ 0 ], xyz[ 1 ], xyz[ 2 ], dv->st[ 0 ], dv->st[ 1 ] );
-		}
-		
-		/* end row */
-		fprintf( f, " )\n" );
-	}
-	
-	/* end patch */
-	fprintf( f, "\t\t\t)\n" );
-	fprintf( f, "\t\t}\n" );
-	fprintf( f, "\t}\n\n" );
-}
-
-
-
-/*
-ConvertModel()
-exports a bsp model to a map file
-*/
-
-static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
-{
-	int					i, num;
-	bspBrush_t			*brush;
-	bspDrawSurface_t	*ds;
-	
-	
-	/* convert bsp planes to map planes */
-	nummapplanes = numBSPPlanes;
-	for( i = 0; i < numBSPPlanes; i++ )
-	{
-		VectorCopy( bspPlanes[ i ].normal, mapplanes[ i ].normal );
-		mapplanes[ i ].dist = bspPlanes[ i ].dist;
-		mapplanes[ i ].type = PlaneTypeForNormal( mapplanes[ i ].normal );
-		mapplanes[ i ].hash_chain = NULL;
-	}
-	
-	/* allocate a build brush */
-	buildBrush = AllocBrush( 512 );
-	buildBrush->entityNum = 0;
-	buildBrush->original = buildBrush;
-	
-	/* go through each brush in the model */
-	for( i = 0; i < model->numBSPBrushes; i++ )
-	{
-		num = i + model->firstBSPBrush;
-		brush = &bspBrushes[ num ];
-		ConvertBrush( f, num, brush, origin );
-	}
-	
-	/* free the build brush */
-	free( buildBrush );
-	
-	/* go through each drawsurf in the model */
-	for( i = 0; i < model->numBSPSurfaces; i++ )
-	{
-		num = i + model->firstBSPSurface;
-		ds = &bspDrawSurfaces[ num ];
-		
-		/* we only love patches */
-		if( ds->surfaceType == MST_PATCH )
-			ConvertPatch( f, num, ds, origin );
-	}
-}
-
-
-
-/*
-ConvertEPairs()
-exports entity key/value pairs to a map file
-*/
-
-static void ConvertEPairs( FILE *f, entity_t *e )
-{
-	epair_t	*ep;
-	
-	
-	/* walk epairs */
-	for( ep = e->epairs; ep != NULL; ep = ep->next )
-	{
-		/* ignore empty keys/values */
-		if( ep->key[ 0 ] == '\0' || ep->value[ 0 ] == '\0' )
-			continue;
-
-		/* ignore model keys with * prefixed values */
-		if( !Q_stricmp( ep->key, "model" ) && ep->value[ 0 ] == '*' )
-			continue;
-		
-		/* emit the epair */
-		fprintf( f, "\t\"%s\" \"%s\"\n", ep->key, ep->value );
-	}
-}
-
-
-
-/*
-ConvertBSPToMap()
-exports an quake map file from the bsp
-*/
-
-int ConvertBSPToMap( char *bspName )
-{
-	int				i, modelNum;
-	FILE			*f;
-	bspModel_t		*model;
-	entity_t		*e;
-	vec3_t			origin;
-	const char		*value;
-	char			name[ 1024 ], base[ 1024 ];
-	
-	
-	/* note it */
-	Sys_Printf( "--- Convert BSP to MAP ---\n" );
-	
-	/* create the bsp filename from the bsp name */
-	strcpy( name, bspName );
-	StripExtension( name );
-	strcat( name, "_converted.map" );
-	Sys_Printf( "writing %s\n", name );
-	
-	ExtractFileBase( bspName, base );
-	strcat( base, ".bsp" );
-	
-	/* open it */
-	f = fopen( name, "wb" );
-	if( f == NULL )
-		Error( "Open failed on %s\n", name );
-	
-	/* print header */
-	fprintf( f, "// Generated by Q3Map2 (ydnar) -convert -format map\n" );
-	
-	/* walk entity list */
-	for( i = 0; i < numEntities; i++ )
-	{
-		/* get entity */
-		e = &entities[ i ];
-		
-		/* start entity */
-		fprintf( f, "// entity %d\n", i );
-		fprintf( f, "{\n" );
-		
-		/* export keys */
-		ConvertEPairs( f, e );
-		fprintf( f, "\n" );
-		
-		/* get model num */
-		if( i == 0 )
-			modelNum = 0;
-		else
-		{
-			value = ValueForKey( e, "model" );
-			if( value[ 0 ] == '*' )
-				modelNum = atoi( value + 1 );
-			else
-				modelNum = -1;
-		}
-		
-		/* only handle bsp models */
-		if( modelNum >= 0 )
-		{
-			/* get model */
-			model = &bspModels[ modelNum ];
-			
-			/* get entity origin */
-			value = ValueForKey( e, "origin" );
-			if( value[ 0 ] == '\0' )
-				VectorClear( origin );
-			else
-				GetVectorForKey( e, "origin", origin );
-			
-			/* convert model */
-			ConvertModel( f, model, modelNum, origin );
-		}
-		
-		/* end entity */
-		fprintf( f, "}\n\n" );
-	}
-	
-	/* close the file and return */
-	fclose( f );
-	
-	/* return to sender */
-	return 0;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define CONVERT_MAP_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+ConvertBrush()
+exports a map brush
+*/
+
+#define	SNAP_FLOAT_TO_INT	4
+#define	SNAP_INT_TO_FLOAT	(1.0 / SNAP_FLOAT_TO_INT)
+
+static void ConvertBrush( FILE *f, int num, bspBrush_t *brush, vec3_t origin )
+{
+	int				i, j;
+	bspBrushSide_t	*side;
+	side_t			*buildSide;
+	bspShader_t		*shader;
+	char			*texture;
+	bspPlane_t		*plane;
+	vec3_t			pts[ 3 ];
+	
+	
+	/* start brush */
+	fprintf( f, "\t// brush %d\n", num );
+	fprintf( f, "\t{\n" );
+	
+	/* clear out build brush */
+	for( i = 0; i < buildBrush->numsides; i++ )
+	{
+		buildSide = &buildBrush->sides[ i ];
+		if( buildSide->winding != NULL )
+		{
+			FreeWinding( buildSide->winding );
+			buildSide->winding = NULL;
+		}
+	}
+	buildBrush->numsides = 0;
+	
+	/* iterate through bsp brush sides */
+	for( i = 0; i < brush->numSides; i++ )
+	{
+		/* get side */
+		side = &bspBrushSides[ brush->firstSide + i ];
+		
+		/* get shader */
+		if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
+			continue;
+		shader = &bspShaders[ side->shaderNum ];
+		if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
+			continue;
+		
+		/* get plane */
+		plane = &bspPlanes[ side->planeNum ];
+		
+		/* add build side */
+		buildSide = &buildBrush->sides[ buildBrush->numsides ];
+		buildBrush->numsides++;
+		
+		/* tag it */
+		buildSide->shaderInfo = ShaderInfoForShader( shader->shader );
+		buildSide->planenum = side->planeNum;
+		buildSide->winding = NULL;
+	}
+	
+	/* make brush windings */
+	if( !CreateBrushWindings( buildBrush ) )
+		return;
+	
+	/* iterate through build brush sides */
+	for( i = 0; i < buildBrush->numsides; i++ )
+	{
+		/* get build side */
+		buildSide = &buildBrush->sides[ i ];
+		
+		/* dummy check */
+		if( buildSide->shaderInfo == NULL || buildSide->winding == NULL )
+			continue;
+		
+		/* get texture name */
+		if( !Q_strncasecmp( buildSide->shaderInfo->shader, "textures/", 9 ) )
+			texture = buildSide->shaderInfo->shader + 9;
+		else
+			texture = buildSide->shaderInfo->shader;
+		
+		/* get plane points and offset by origin */
+		for( j = 0; j < 3; j++ )
+		{
+			VectorAdd( buildSide->winding->p[ j ], origin, pts[ j ] );
+			//%	pts[ j ][ 0 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 0 ] * SNAP_FLOAT_TO_INT + 0.5f );
+			//%	pts[ j ][ 1 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 1 ] * SNAP_FLOAT_TO_INT + 0.5f );
+			//%	pts[ j ][ 2 ] = SNAP_INT_TO_FLOAT * floor( pts[ j ][ 2 ] * SNAP_FLOAT_TO_INT + 0.5f );
+		}
+		
+		/* print brush side */
+		/* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
+		fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s 0 0 0 0.5 0.5 0 0 0\n",
+			pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
+			pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
+			pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
+			texture );
+	}
+	
+	/* end brush */
+	fprintf( f, "\t}\n\n" );
+}
+
+#if 0
+	/* iterate through the brush sides (ignore the first 6 bevel planes) */
+	for( i = 0; i < brush->numSides; i++ )
+	{
+		/* get side */
+		side = &bspBrushSides[ brush->firstSide + i ];
+		
+		/* get shader */
+		if( side->shaderNum < 0 || side->shaderNum >= numBSPShaders )
+			continue;
+		shader = &bspShaders[ side->shaderNum ];
+		if( !Q_stricmp( shader->shader, "default" ) || !Q_stricmp( shader->shader, "noshader" ) )
+			continue;
+		
+		/* get texture name */
+		if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
+			texture = shader->shader + 9;
+		else
+			texture = shader->shader;
+		
+		/* get plane */
+		plane = &bspPlanes[ side->planeNum ];
+
+		/* make plane points */
+		{
+			vec3_t	vecs[ 2 ];
+
+			
+			MakeNormalVectors( plane->normal, vecs[ 0 ], vecs[ 1 ] );
+			VectorMA( vec3_origin, plane->dist, plane->normal, pts[ 0 ] );
+			VectorMA( pts[ 0 ], 256.0f, vecs[ 0 ], pts[ 1 ] );
+			VectorMA( pts[ 0 ], 256.0f, vecs[ 1 ], pts[ 2 ] );
+		}
+
+		/* offset by origin */
+		for( j = 0; j < 3; j++ )
+			VectorAdd( pts[ j ], origin, pts[ j ] );
+		
+		/* print brush side */
+		/* ( 640 24 -224 ) ( 448 24 -224 ) ( 448 -232 -224 ) common/caulk 0 48 0 0.500000 0.500000 0 0 0 */
+		fprintf( f, "\t\t( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) ( %.3f %.3f %.3f ) %s 0 0 0 0.5 0.5 0 0 0\n",
+			pts[ 0 ][ 0 ], pts[ 0 ][ 1 ], pts[ 0 ][ 2 ],
+			pts[ 1 ][ 0 ], pts[ 1 ][ 1 ], pts[ 1 ][ 2 ],
+			pts[ 2 ][ 0 ], pts[ 2 ][ 1 ], pts[ 2 ][ 2 ],
+			texture );
+	}
+#endif
+
+
+
+/*
+ConvertPatch()
+converts a bsp patch to a map patch
+
+	{
+		patchDef2
+		{
+			base_wall/concrete
+			( 9 3 0 0 0 )
+			(
+				( ( 168 168 -192 0 2 ) ( 168 168 -64 0 1 ) ( 168 168 64 0 0 ) ... )
+				...
+			)
+		}
+	}
+
+*/
+
+static void ConvertPatch( FILE *f, int num, bspDrawSurface_t *ds, vec3_t origin )
+{
+	int				x, y;
+	bspShader_t		*shader;
+	char			*texture;
+	bspDrawVert_t	*dv;
+	vec3_t			xyz;
+	
+	
+	/* only patches */
+	if( ds->surfaceType != MST_PATCH )
+		return;
+	
+	/* get shader */
+	if( ds->shaderNum < 0 || ds->shaderNum >= numBSPShaders )
+		return;
+	shader = &bspShaders[ ds->shaderNum ];
+	
+	/* get texture name */
+	if( !Q_strncasecmp( shader->shader, "textures/", 9 ) )
+		texture = shader->shader + 9;
+	else
+		texture = shader->shader;
+	
+	/* start patch */
+	fprintf( f, "\t// patch %d\n", num );
+	fprintf( f, "\t{\n" );
+	fprintf( f, "\t\tpatchDef2\n" );
+	fprintf( f, "\t\t{\n" );
+	fprintf( f, "\t\t\t%s\n", texture );
+	fprintf( f, "\t\t\t( %d %d 0 0 0 )\n", ds->patchWidth, ds->patchHeight );
+	fprintf( f, "\t\t\t(\n" );
+	
+	/* iterate through the verts */
+	for( x = 0; x < ds->patchWidth; x++ )
+	{
+		/* start row */
+		fprintf( f, "\t\t\t\t(" );
+		
+		/* iterate through the row */
+		for( y = 0; y < ds->patchHeight; y++ )
+		{
+			/* get vert */
+			dv = &bspDrawVerts[ ds->firstVert + (y * ds->patchWidth) + x ];
+			
+			/* offset it */
+			VectorAdd( origin, dv->xyz, xyz );
+			
+			/* print vertex */
+			fprintf( f, " ( %f %f %f %f %f )", xyz[ 0 ], xyz[ 1 ], xyz[ 2 ], dv->st[ 0 ], dv->st[ 1 ] );
+		}
+		
+		/* end row */
+		fprintf( f, " )\n" );
+	}
+	
+	/* end patch */
+	fprintf( f, "\t\t\t)\n" );
+	fprintf( f, "\t\t}\n" );
+	fprintf( f, "\t}\n\n" );
+}
+
+
+
+/*
+ConvertModel()
+exports a bsp model to a map file
+*/
+
+static void ConvertModel( FILE *f, bspModel_t *model, int modelNum, vec3_t origin )
+{
+	int					i, num;
+	bspBrush_t			*brush;
+	bspDrawSurface_t	*ds;
+	
+	
+	/* convert bsp planes to map planes */
+	nummapplanes = numBSPPlanes;
+	for( i = 0; i < numBSPPlanes; i++ )
+	{
+		VectorCopy( bspPlanes[ i ].normal, mapplanes[ i ].normal );
+		mapplanes[ i ].dist = bspPlanes[ i ].dist;
+		mapplanes[ i ].type = PlaneTypeForNormal( mapplanes[ i ].normal );
+		mapplanes[ i ].hash_chain = NULL;
+	}
+	
+	/* allocate a build brush */
+	buildBrush = AllocBrush( 512 );
+	buildBrush->entityNum = 0;
+	buildBrush->original = buildBrush;
+	
+	/* go through each brush in the model */
+	for( i = 0; i < model->numBSPBrushes; i++ )
+	{
+		num = i + model->firstBSPBrush;
+		brush = &bspBrushes[ num ];
+		ConvertBrush( f, num, brush, origin );
+	}
+	
+	/* free the build brush */
+	free( buildBrush );
+	
+	/* go through each drawsurf in the model */
+	for( i = 0; i < model->numBSPSurfaces; i++ )
+	{
+		num = i + model->firstBSPSurface;
+		ds = &bspDrawSurfaces[ num ];
+		
+		/* we only love patches */
+		if( ds->surfaceType == MST_PATCH )
+			ConvertPatch( f, num, ds, origin );
+	}
+}
+
+
+
+/*
+ConvertEPairs()
+exports entity key/value pairs to a map file
+*/
+
+static void ConvertEPairs( FILE *f, entity_t *e )
+{
+	epair_t	*ep;
+	
+	
+	/* walk epairs */
+	for( ep = e->epairs; ep != NULL; ep = ep->next )
+	{
+		/* ignore empty keys/values */
+		if( ep->key[ 0 ] == '\0' || ep->value[ 0 ] == '\0' )
+			continue;
+
+		/* ignore model keys with * prefixed values */
+		if( !Q_stricmp( ep->key, "model" ) && ep->value[ 0 ] == '*' )
+			continue;
+		
+		/* emit the epair */
+		fprintf( f, "\t\"%s\" \"%s\"\n", ep->key, ep->value );
+	}
+}
+
+
+
+/*
+ConvertBSPToMap()
+exports an quake map file from the bsp
+*/
+
+int ConvertBSPToMap( char *bspName )
+{
+	int				i, modelNum;
+	FILE			*f;
+	bspModel_t		*model;
+	entity_t		*e;
+	vec3_t			origin;
+	const char		*value;
+	char			name[ 1024 ], base[ 1024 ];
+	
+	
+	/* note it */
+	Sys_Printf( "--- Convert BSP to MAP ---\n" );
+	
+	/* create the bsp filename from the bsp name */
+	strcpy( name, bspName );
+	StripExtension( name );
+	strcat( name, "_converted.map" );
+	Sys_Printf( "writing %s\n", name );
+	
+	ExtractFileBase( bspName, base );
+	strcat( base, ".bsp" );
+	
+	/* open it */
+	f = fopen( name, "wb" );
+	if( f == NULL )
+		Error( "Open failed on %s\n", name );
+	
+	/* print header */
+	fprintf( f, "// Generated by Q3Map2 (ydnar) -convert -format map\n" );
+	
+	/* walk entity list */
+	for( i = 0; i < numEntities; i++ )
+	{
+		/* get entity */
+		e = &entities[ i ];
+		
+		/* start entity */
+		fprintf( f, "// entity %d\n", i );
+		fprintf( f, "{\n" );
+		
+		/* export keys */
+		ConvertEPairs( f, e );
+		fprintf( f, "\n" );
+		
+		/* get model num */
+		if( i == 0 )
+			modelNum = 0;
+		else
+		{
+			value = ValueForKey( e, "model" );
+			if( value[ 0 ] == '*' )
+				modelNum = atoi( value + 1 );
+			else
+				modelNum = -1;
+		}
+		
+		/* only handle bsp models */
+		if( modelNum >= 0 )
+		{
+			/* get model */
+			model = &bspModels[ modelNum ];
+			
+			/* get entity origin */
+			value = ValueForKey( e, "origin" );
+			if( value[ 0 ] == '\0' )
+				VectorClear( origin );
+			else
+				GetVectorForKey( e, "origin", origin );
+			
+			/* convert model */
+			ConvertModel( f, model, modelNum, origin );
+		}
+		
+		/* end entity */
+		fprintf( f, "}\n\n" );
+	}
+	
+	/* close the file and return */
+	fclose( f );
+	
+	/* return to sender */
+	return 0;
+}
diff --git a/tools/quake3/q3map2/decals.c b/tools/quake3/q3map2/decals.c
index d7b01d64..5260437d 100644
--- a/tools/quake3/q3map2/decals.c
+++ b/tools/quake3/q3map2/decals.c
@@ -1,908 +1,908 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define DECALS_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-#define MAX_PROJECTORS		1024
-
-typedef struct decalProjector_s
-{
-	shaderInfo_t			*si;
-	vec3_t					mins, maxs;
-	vec3_t					center;
-	float					radius, radius2;
-	int						numPlanes;	/* either 5 or 6, for quad or triangle projectors */
-	vec4_t					planes[ 6 ];
-	vec4_t					texMat[ 2 ];
-}
-decalProjector_t;
-
-static int					numProjectors = 0;
-static decalProjector_t		projectors[ MAX_PROJECTORS ];
-
-static int					numDecalSurfaces = 0;
-
-static vec3_t				entityOrigin;
-
-
-
-/*
-DVectorNormalize()
-normalizes a vector, returns the length, operates using doubles
-*/
-
-typedef double	dvec_t;
-typedef dvec_t	dvec3_t[ 3 ];
-
-dvec_t DVectorNormalize( dvec3_t in, dvec3_t out )
-{
-	dvec_t	len, ilen;
-	
-	
-	len = (dvec_t) sqrt( in[ 0 ] * in[ 0 ] + in[ 1 ] * in[ 1 ] + in[ 2 ] * in[ 2 ] );
-	if( len == 0.0 )
-	{
-		VectorClear( out );
-		return 0.0;
-	}
-	
-	ilen = 1.0 / len;
-	out[ 0 ] = in[ 0 ] * ilen;
-	out[ 1 ] = in[ 1 ] * ilen;
-	out[ 2 ] = in[ 2 ] * ilen;
-	
-	return len;
-}
-
-
-
-/*
-MakeTextureMatrix()
-generates a texture projection matrix for a triangle
-returns qfalse if a texture matrix cannot be created
-*/
-
-#define Vector2Subtract(a,b,c)	((c)[ 0 ] = (a)[ 0 ] - (b)[ 0 ], (c)[ 1 ] = (a)[ 1 ] - (b)[ 1 ])
-
-static qboolean MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c )
-{
-	int			i, j;
-	double		bb, s, t, d;
-	dvec3_t		pa, pb, pc;
-	dvec3_t		bary, xyz;
-	dvec3_t		vecs[ 3 ], axis[ 3 ], lengths;
-	
-	
-	/* project triangle onto plane of projection */
-	d = DotProduct( a->xyz, projection ) - projection[ 3 ];
-	VectorMA( a->xyz, -d, projection, pa );
-	d = DotProduct( b->xyz, projection ) - projection[ 3 ];
-	VectorMA( b->xyz, -d, projection, pb );
-	d = DotProduct( c->xyz, projection ) - projection[ 3 ];
-	VectorMA( c->xyz, -d, projection, pc );
-	
-	/* two methods */
-	#if 1
-	{
-		/* old code */
-		
-		/* calculate barycentric basis for the triangle */
-		bb = (b->st[ 0 ] - a->st[ 0 ]) * (c->st[ 1 ] - a->st[ 1 ]) - (c->st[ 0 ] - a->st[ 0 ]) * (b->st[ 1 ] - a->st[ 1 ]);
-		if( fabs( bb ) < 0.00000001 )
-			return qfalse;
-		
-		/* calculate texture origin */
-		#if 0
-		s = 0.0;
-		t = 0.0;
-		bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb;
-		bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb;
-		bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb;
-		
-		origin[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ];
-		origin[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
-		origin[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
-		#endif
-		
-		/* calculate s vector */
-		s = a->st[ 0 ] + 1.0;
-		t = a->st[ 1 ] + 0.0;
-		bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb;
-		bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb;
-		bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb;
-		
-		xyz[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ];
-		xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
-		xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
-		
-		//%	VectorSubtract( xyz, origin, vecs[ 0 ] );
-		VectorSubtract( xyz, pa, vecs[ 0 ] );
-		
-		/* calculate t vector */
-		s = a->st[ 0 ] + 0.0;
-		t = a->st[ 1 ] + 1.0;
-		bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb;
-		bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb;
-		bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb;
-		
-		xyz[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ];
-		xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
-		xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
-		
-		//%	VectorSubtract( xyz, origin, vecs[ 1 ] );
-		VectorSubtract( xyz, pa, vecs[ 1 ] );
-		
-		/* calcuate r vector */
-		VectorScale( projection, -1.0, vecs[ 2 ] );
-		
-		/* calculate transform axis */
-		for( i = 0; i < 3; i++ )
-			lengths[ i ] = DVectorNormalize( vecs[ i ], axis[ i ] );
-		for( i = 0; i < 2; i++ )
-			for( j = 0; j < 3; j++ )
-				dp->texMat[ i ][ j ] = lengths[ i ] > 0.0 ? (axis[ i ][ j ] / lengths[ i ]) : 0.0;
-				//%	dp->texMat[ i ][ j ] = fabs( vecs[ i ][ j ] ) > 0.0 ? (1.0 / vecs[ i ][ j ]) : 0.0;
-				//%	dp->texMat[ i ][ j ] = axis[ i ][ j ] > 0.0 ? (1.0 / axis[ i ][ j ]) : 0.0;
-		
-		/* calculalate translation component */
-		dp->texMat[ 0 ][ 3 ] = a->st[ 0 ] - DotProduct( a->xyz, dp->texMat[ 0 ] );
-		dp->texMat[ 1 ][ 3 ] = a->st[ 1 ] - DotProduct( a->xyz, dp->texMat[ 1 ] );
-	}
-	#else
-	{
-		int			k;
-		dvec3_t		origin, deltas[ 3 ];
-		double		texDeltas[ 3 ][ 2 ];
-		double		delta, texDelta;
-		
-		
-		/* new code */
-		
-		/* calculate deltas */
-		VectorSubtract( pa, pb, deltas[ 0 ] );
-		VectorSubtract( pa, pc, deltas[ 1 ] );
-		VectorSubtract( pb, pc, deltas[ 2 ] );
-		Vector2Subtract( a->st, b->st, texDeltas[ 0 ] );
-		Vector2Subtract( a->st, c->st, texDeltas[ 1 ] );
-		Vector2Subtract( b->st, c->st, texDeltas[ 2 ] );
-		
-		/* walk st */
-		for( i = 0; i < 2; i++ )
-		{
-			/* walk xyz */
-			for( j = 0; j < 3; j++ )
-			{
-				/* clear deltas */
-				delta = 0.0;
-				texDelta = 0.0;
-				
-				/* walk deltas */
-				for( k = 0; k < 3; k++ )
-				{
-					if( fabs( deltas[ k ][ j ] ) > delta &&
-						fabs( texDeltas[ k ][ i ] ) > texDelta  )
-					{
-						delta = deltas[ k ][ j ];
-						texDelta = texDeltas[ k ][ i ];
-					}
-				}
-				
-				/* set texture matrix component */
-				if( fabs( delta ) > 0.0 )
-					dp->texMat[ i ][ j ] = texDelta / delta;
-				else
-					dp->texMat[ i ][ j ] = 0.0;
-			}
-		
-			/* set translation component */
-			dp->texMat[ i ][ 3 ] = a->st[ i ] - DotProduct( pa, dp->texMat[ i ] );
-		}
-	}
-	#endif
-	
-	/* debug code */
-	#if 1
-		Sys_Printf( "Mat: [ %f %f %f %f ] [ %f %f %f %f ] Theta: %f (%f)\n",
-			dp->texMat[ 0 ][ 0 ], dp->texMat[ 0 ][ 1 ], dp->texMat[ 0 ][ 2 ], dp->texMat[ 0 ][ 3 ], 
-			dp->texMat[ 1 ][ 0 ], dp->texMat[ 1 ][ 1 ], dp->texMat[ 1 ][ 2 ], dp->texMat[ 1 ][ 3 ],
-			RAD2DEG( acos( DotProduct( dp->texMat[ 0 ], dp->texMat[ 1 ] ) ) ),
-			RAD2DEG( acos( DotProduct( axis[ 0 ], axis[ 1 ] ) ) ) );
-		
-		Sys_Printf( "XYZ: %f %f %f ST: %f %f ST(t): %f %f\n",
-			a->xyz[ 0 ], a->xyz[ 1 ], a->xyz[ 2 ],
-			a->st[ 0 ], a->st[ 1 ],
-			DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ], DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ] );
-	#endif
-	
-	/* test texture matrix */
-	s = DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
-	t = DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
-	if( fabs( s - a->st[ 0 ] ) > 0.01 || fabs( t - a->st[ 1 ] ) > 0.01 )
-	{
-		Sys_Printf( "Bad texture matrix! (A) (%f, %f) != (%f, %f)\n",
-			s, t, a->st[ 0 ], a->st[ 1 ] );
-		//%	return qfalse;
-	}
-	s = DotProduct( b->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
-	t = DotProduct( b->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
-	if( fabs( s - b->st[ 0 ] ) > 0.01 || fabs( t - b->st[ 1 ] ) > 0.01 )
-	{
-		Sys_Printf( "Bad texture matrix! (B) (%f, %f) != (%f, %f)\n",
-			s, t, b->st[ 0 ], b->st[ 1 ] );
-		//%	return qfalse;
-	}
-	s = DotProduct( c->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
-	t = DotProduct( c->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
-	if( fabs( s - c->st[ 0 ] ) > 0.01 || fabs( t - c->st[ 1 ] ) > 0.01 )
-	{
-		Sys_Printf( "Bad texture matrix! (C) (%f, %f) != (%f, %f)\n",
-			s, t, c->st[ 0 ], c->st[ 1 ] );
-		//%	return qfalse;
-	}
-	
-	/* disco */
-	return qtrue;
-}
-
-
-
-/*
-TransformDecalProjector()
-transforms a decal projector
-note: non-normalized axes will screw up the plane transform
-*/
-
-static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec3_t origin, decalProjector_t *out )
-{
-	int		i;
-	
-	
-	/* copy misc stuff */
-	out->si = in->si;
-	out->numPlanes = in->numPlanes;
-	
-	/* translate bounding box and sphere (note: rotated projector bounding box will be invalid!) */
-	VectorSubtract( in->mins, origin, out->mins );
-	VectorSubtract( in->maxs, origin, out->maxs );
-	VectorSubtract( in->center, origin, out->center );
-	out->radius = in->radius;
-	out->radius2 = in->radius2;
-	
-	/* translate planes */
-	for( i = 0; i < in->numPlanes; i++ )
-	{
-		out->planes[ i ][ 0 ] = DotProduct( in->planes[ i ], axis[ 0 ] );
-		out->planes[ i ][ 1 ] = DotProduct( in->planes[ i ], axis[ 1 ] );
-		out->planes[ i ][ 2 ] = DotProduct( in->planes[ i ], axis[ 2 ] );
-		out->planes[ i ][ 3 ] = in->planes[ i ][ 3 ] - DotProduct( out->planes[ i ], origin );
-	}
-	
-	/* translate texture matrix */
-	for( i = 0; i < 2; i++ )
-	{
-		out->texMat[ i ][ 0 ] = DotProduct( in->texMat[ i ], axis[ 0 ] );
-		out->texMat[ i ][ 1 ] = DotProduct( in->texMat[ i ], axis[ 1 ] );
-		out->texMat[ i ][ 2 ] = DotProduct( in->texMat[ i ], axis[ 2 ] );
-		out->texMat[ i ][ 3 ] = in->texMat[ i ][ 3 ] + DotProduct( out->texMat[ i ], origin );
-	}
-}
-
-
-
-/*
-MakeDecalProjector()
-creates a new decal projector from a triangle
-*/
-
-static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distance, int numVerts, bspDrawVert_t **dv )
-{
-	int					i, j;
-	decalProjector_t	*dp;
-	vec3_t				xyz;
-	
-	
-	/* dummy check */
-	if( numVerts != 3 && numVerts != 4 )
-		return -1;
-	
-	/* limit check */
-	if( numProjectors >= MAX_PROJECTORS )
-	{
-		Sys_Printf( "WARNING: MAX_PROJECTORS (%d) exceeded, no more decal projectors available.\n", MAX_PROJECTORS );
-		return -2;
-	}
-	
-	/* create a new projector */
-	dp = &projectors[ numProjectors ];
-	memset( dp, 0, sizeof( *dp ) );
-	
-	/* basic setup */
-	dp->si = si;
-	dp->numPlanes = numVerts + 2;
-	
-	/* make texture matrix */
-	if( !MakeTextureMatrix( dp, projection, dv[ 0 ], dv[ 1 ], dv[ 2 ] ) )
-		return -1;
-	
-	/* bound the projector */
-	ClearBounds( dp->mins, dp->maxs );
-	for( i = 0; i < numVerts; i++ )
-	{
-		AddPointToBounds( dv[ i ]->xyz, dp->mins, dp->maxs );
-		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
-		AddPointToBounds( xyz, dp->mins, dp->maxs );
-	}
-	
-	/* make bouding sphere */
-	VectorAdd( dp->mins, dp->maxs, dp->center );
-	VectorScale( dp->center, 0.5f, dp->center );
-	VectorSubtract( dp->maxs, dp->center, xyz );
-	dp->radius = VectorLength( xyz );
-	dp->radius2 = dp->radius * dp->radius;
-	
-	/* make the front plane */
-	if( !PlaneFromPoints( dp->planes[ 0 ], dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) )
-		return -1;
-	
-	/* make the back plane */
-	VectorSubtract( vec3_origin, dp->planes[ 0 ], dp->planes[ 1 ] );
-	VectorMA( dv[ 0 ]->xyz, distance, projection, xyz );
-	dp->planes[ 1 ][ 3 ] = DotProduct( xyz, dp->planes[ 1 ] );
-	
-	/* make the side planes */
-	for( i = 0; i < numVerts; i++ )
-	{
-		j = (i + 1) % numVerts;
-		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
-		if( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, xyz ) )
-			return -1;
-	}
-	
-	/* return ok */
-	numProjectors++;
-	return numProjectors - 1;
-}
-
-
-
-/*
-ProcessDecals()
-finds all decal entities and creates decal projectors
-*/
-
-#define PLANAR_EPSILON	0.5f
-
-void ProcessDecals( void )
-{
-	int					i, j, x, y, pw[ 5 ], r, iterations;
-	float				distance;
-	vec4_t				projection, plane;
-	vec3_t				origin, target, delta;
-	entity_t			*e, *e2;
-	parseMesh_t			*p;
-	mesh_t				*mesh, *subdivided;
-	bspDrawVert_t		*dv[ 4 ];
-	const char			*value;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- ProcessDecals ---\n" );
-	
-	/* walk entity list */
-	for( i = 0; i < numEntities; i++ )
-	{
-		/* get entity */
-		e = &entities[ i ];
-		value = ValueForKey( e, "classname" );
-		if( Q_stricmp( value, "_decal" ) )
-			continue;
-		
-		/* any patches? */
-		if( e->patches == NULL )
-		{
-			Sys_Printf( "WARNING: Decal entity without any patch meshes, ignoring.\n" );
-			e->epairs = NULL;	/* fixme: leak! */
-			continue;
-		}
-		
-		/* find target */
-		value = ValueForKey( e, "target" );
-		e2 = FindTargetEntity( value );
-		
-		/* no target? */
-		if( e2 == NULL )
-		{
-			Sys_Printf( "WARNING: Decal entity without a valid target, ignoring.\n" );
-			continue;
-		}
-		
-		/* walk entity patches */
-		for( p = e->patches; p != NULL; p = e->patches )
-		{
-			/* setup projector */
-			if( VectorCompare( e->origin, vec3_origin ) )
-			{
-				VectorAdd( p->eMins, p->eMaxs, origin );
-				VectorScale( origin, 0.5f, origin );
-			}
-			else
-				VectorCopy( e->origin, origin );
-			
-			VectorCopy( e2->origin, target );
-			VectorSubtract( target, origin, delta );
-			
-			/* setup projection plane */
-			distance = VectorNormalize( delta, projection );
-			projection[ 3 ] = DotProduct( origin, projection );
-			
-			/* create projectors */
-			if( distance > 0.125f )
-			{
-				/* tesselate the patch */
-				iterations = IterationsForCurve( p->longestCurve, patchSubdivisions );
-				subdivided = SubdivideMesh2( p->mesh, iterations );
-				
-				/* fit it to the curve and remove colinear verts on rows/columns */
-				PutMeshOnCurve( *subdivided );
-				mesh = RemoveLinearMeshColumnsRows( subdivided );
-				FreeMesh( subdivided );
-				
-				/* offset by projector origin */
-				for( j = 0; j < (mesh->width * mesh->height); j++ )
-					VectorAdd( mesh->verts[ j ].xyz, e->origin, mesh->verts[ j ].xyz );
-				
-				/* iterate through the mesh quads */
-				for( y = 0; y < (mesh->height - 1); y++ )
-				{
-					for( x = 0; x < (mesh->width - 1); x++ )
-					{
-						/* set indexes */
-						pw[ 0 ] = x + (y * mesh->width);
-						pw[ 1 ] = x + ((y + 1) * mesh->width);
-						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-						pw[ 3 ] = x + 1 + (y * mesh->width);
-						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-						
-						/* set radix */
-						r = (x + y) & 1;
-						
-						/* get drawverts */
-						dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
-						dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
-						dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
-						dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
-						
-						/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
-						plane[ 0 ] = 0.0f;	/* stupid msvc */
-						if( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) &&
-							fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON )
-						{
-							/* make a quad projector */
-							MakeDecalProjector( p->shaderInfo, projection, distance, 4, dv );
-						}
-						else
-						{
-							/* make first triangle */
-							MakeDecalProjector( p->shaderInfo, projection, distance, 3, dv );
-							
-							/* make second triangle */
-							dv[ 1 ] = dv[ 2 ];
-							dv[ 2 ] = dv[ 3 ];
-							MakeDecalProjector( p->shaderInfo, projection, distance, 3, dv );
-						}
-					}
-				}
-				
-				/* clean up */
-				free( mesh );
-			}
-			
-			/* remove patch from entity (fixme: leak!) */
-			e->patches = p->next;
-			
-			/* push patch to worldspawn (enable this to debug projectors) */
-			#if 0
-				p->next = entities[ 0 ].patches;
-				entities[ 0 ].patches = p;
-			#endif
-		}
-	}
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d decal projectors\n", numProjectors );
-}
-
-
-
-/*
-ProjectDecalOntoWinding()
-projects a decal onto a winding
-*/
-
-static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t *w )
-{
-	int					i, j;
-	float				d, d2, alpha;
-	winding_t			*front, *back;
-	mapDrawSurface_t	*ds2;
-	bspDrawVert_t		*dv;
-	vec4_t				plane;
-	
-	
-	/* dummy check */
-	if( w->numpoints < 3 )
-	{
-		FreeWinding( w );
-		return;
-	}
-	
-	/* offset by entity origin */
-	for( i = 0; i < w->numpoints; i++ )
-		VectorAdd( w->p[ i ], entityOrigin, w->p[ i ] );
-	
-	/* make a plane from the winding */
-	if( !PlaneFromPoints( plane, w->p[ 0 ], w->p[ 1 ], w->p[ 2 ] ) )
-	{
-		FreeWinding( w );
-		return;
-	}
-	
-	/* backface check */
-	d = DotProduct( dp->planes[ 0 ], plane );
-	if( d < -0.0001f )
-	{
-		FreeWinding( w );
-		return;
-	}
-	
-	/* walk list of planes */
-	for( i = 0; i < dp->numPlanes; i++ )
-	{
-		/* chop winding by the plane */
-		ClipWindingEpsilon( w, dp->planes[ i ], dp->planes[ i ][ 3 ], 0.0625f, &front, &back );
-		FreeWinding( w );
-		
-		/* lose the front fragment */
-		if( front != NULL )
-			FreeWinding( front );
-		
-		/* if nothing left in back, then bail */
-		if( back == NULL )
-			return;
-		
-		/* reset winding */
-		w = back;
-	}
-	
-	/* nothing left? */
-	if( w == NULL || w->numpoints < 3 )
-		return;
-	
-	/* add to counts */
-	numDecalSurfaces++;
-	
-	/* make a new surface */
-	ds2 = AllocDrawSurface( SURFACE_DECAL );
-	
-	/* set it up */
-	ds2->entityNum = ds->entityNum;
-	ds2->castShadows = ds->castShadows;
-	ds2->recvShadows = ds->recvShadows;
-	ds2->shaderInfo = dp->si;
-	ds2->fogNum = ds->fogNum;	/* why was this -1? */
-	ds2->lightmapScale = ds->lightmapScale;
-	ds2->numVerts = w->numpoints;
-	ds2->verts = safe_malloc( ds2->numVerts * sizeof( *ds2->verts ) );
-	memset( ds2->verts, 0, ds2->numVerts * sizeof( *ds2->verts ) );
-	
-	/* set vertexes */
-	for( i = 0; i < ds2->numVerts; i++ )
-	{
-		/* get vertex */
-		dv = &ds2->verts[ i ];
-		
-		/* set alpha */
-		d = DotProduct( w->p[ i ], dp->planes[ 0 ] ) - dp->planes[ 0 ][ 3 ];
-		d2 = DotProduct( w->p[ i ], dp->planes[ 1 ] ) - dp->planes[ 1 ][ 3 ];
-		alpha = 255.0f * d2 / (d + d2);
-		if( alpha > 255 )
-			alpha = 255;
-		else if( alpha < 0 )
-			alpha = 0;
-		
-		/* set misc */
-		VectorSubtract( w->p[ i ], entityOrigin, dv->xyz );
-		VectorCopy( plane, dv->normal );
-		dv->st[ 0 ] = DotProduct( dv->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
-		dv->st[ 1 ] = DotProduct( dv->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
-		
-		/* set color */
-		for( j = 0; j < MAX_LIGHTMAPS; j++ )
-		{
-			dv->color[ j ][ 0 ] = 255;
-			dv->color[ j ][ 1 ] = 255;
-			dv->color[ j ][ 2 ] = 255;
-			dv->color[ j ][ 3 ] = alpha;
-		}
-	}
-	
-	/* ydnar: finish the surface */
-	FinishSurface( ds2 );
-}
-
-
-
-/*
-ProjectDecalOntoFace()
-projects a decal onto a brushface surface
-*/
-
-static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds )
-{
-	vec4_t		plane;
-	float		d;
-	winding_t	*w;
-	
-	
-	/* dummy check */
-	if( ds->sideRef == NULL || ds->sideRef->side == NULL )
-		return;
-	
-	/* backface check */
-	if( ds->planar )
-	{
-		VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
-		plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
-		d = DotProduct( dp->planes[ 0 ], plane );
-		if( d < -0.0001f )
-			return;
-	}
-	
-	/* generate decal */
-	w = WindingFromDrawSurf( ds );
-	ProjectDecalOntoWinding( dp, ds, w );
-}
-
-
-
-/*
-ProjectDecalOntoPatch()
-projects a decal onto a patch surface
-*/
-
-static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds )
-{
-	int			x, y, pw[ 5 ], r, iterations;
-	vec4_t		plane;
-	float		d;
-	mesh_t		src, *mesh, *subdivided;
-	winding_t	*w;
-	
-	
-	/* backface check */
-	if( ds->planar )
-	{
-		VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
-		plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
-		d = DotProduct( dp->planes[ 0 ], plane );
-		if( d < -0.0001f )
-			return;
-	}
-	
-	/* tesselate the patch */
-	src.width = ds->patchWidth;
-	src.height = ds->patchHeight;
-	src.verts = ds->verts;
-	iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
-	subdivided = SubdivideMesh2( src, iterations );
-	
-	/* fit it to the curve and remove colinear verts on rows/columns */
-	PutMeshOnCurve( *subdivided );
-	mesh = RemoveLinearMeshColumnsRows( subdivided );
-	FreeMesh( subdivided );
-	
-	/* iterate through the mesh quads */
-	for( y = 0; y < (mesh->height - 1); y++ )
-	{
-		for( x = 0; x < (mesh->width - 1); x++ )
-		{
-			/* set indexes */
-			pw[ 0 ] = x + (y * mesh->width);
-			pw[ 1 ] = x + ((y + 1) * mesh->width);
-			pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-			pw[ 3 ] = x + 1 + (y * mesh->width);
-			pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-			
-			/* set radix */
-			r = (x + y) & 1;
-			
-			/* generate decal for first triangle */
-			w = AllocWinding( 3 );
-			w->numpoints = 3;
-			VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
-			VectorCopy( mesh->verts[ pw[ r + 1 ] ].xyz, w->p[ 1 ] );
-			VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 2 ] );
-			ProjectDecalOntoWinding( dp, ds, w );
-			
-			/* generate decal for second triangle */
-			w = AllocWinding( 3 );
-			w->numpoints = 3;
-			VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
-			VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 1 ] );
-			VectorCopy( mesh->verts[ pw[ r + 3 ] ].xyz, w->p[ 2 ] );
-			ProjectDecalOntoWinding( dp, ds, w );
-		}
-	}
-	
-	/* clean up */
-	free( mesh );
-}
-
-
-
-/*
-ProjectDecalOntoTriangles()
-projects a decal onto a triangle surface
-*/
-
-static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *ds )
-{
-	int			i;
-	vec4_t		plane;
-	float		d;
-	winding_t	*w;
-	
-	
-	/* triangle surfaces without shaders don't get marks by default */
-	if( (ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FORCED_META) &&
-		ds->shaderInfo->shaderText == NULL )
-		return;
-	
-	/* backface check */
-	if( ds->planar )
-	{
-		VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
-		plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
-		d = DotProduct( dp->planes[ 0 ], plane );
-		if( d < -0.0001f )
-			return;
-	}
-	
-	/* iterate through triangles */
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		/* generate decal */
-		w = AllocWinding( 3 );
-		w->numpoints = 3;
-		VectorCopy( ds->verts[ ds->indexes[ i ] ].xyz, w->p[ 0 ] );
-		VectorCopy( ds->verts[ ds->indexes[ i + 1 ] ].xyz, w->p[ 1 ] );
-		VectorCopy( ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] );
-		ProjectDecalOntoWinding( dp, ds, w );
-	}
-}
-
-
-
-/*
-MakeEntityDecals()
-projects decals onto world surfaces
-*/
-
-void MakeEntityDecals( entity_t *e )
-{
-	int					i, j, k, f, fOld, start;
-	decalProjector_t	dp;
-	mapDrawSurface_t	*ds;
-	vec3_t				identityAxis[ 3 ] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- MakeEntityDecals ---\n" );
-	
-	/* set entity origin */
-	VectorCopy( e->origin, entityOrigin );
-	
-	/* transform projector instead of geometry */
-	VectorClear( entityOrigin );
-	
-	/* init pacifier */
-	fOld = -1;
-	start = I_FloatTime();
-	
-	/* walk the list of decal projectors */
-	for( i = 0; i < numProjectors; i++ )
-	{
-		/* print pacifier */
-		f = 10 * i / numProjectors;
-		if( f != fOld )
-		{
-			fOld = f;
-			Sys_FPrintf( SYS_VRB, "%d...", f );
-		}
-		
-		/* get projector */
-		TransformDecalProjector( &projectors[ i ], identityAxis, e->origin, &dp );
-		
-		/* walk the list of surfaces in the entity */
-		for( j = e->firstDrawSurf; j < numMapDrawSurfs; j++ )
-		{
-			/* get surface */
-			ds = &mapDrawSurfs[ j ];
-			if( ds->numVerts <= 0 )
-				continue;
-			
-			/* ignore autosprite or nomarks */
-			if( ds->shaderInfo->autosprite || (ds->shaderInfo->compileFlags & C_NOMARKS) )
-				continue;
-			
-			/* bounds check */
-			for( k = 0; k < 3; k++ )
-				if( ds->mins[ k ] >= (dp.center[ k ] + dp.radius) ||
-					ds->maxs[ k ] <= (dp.center[ k ] - dp.radius) )
-					break;
-			if( k < 3 )
-				continue;
-			
-			/* switch on type */
-			switch( ds->type )
-			{
-				case SURFACE_FACE:
-					ProjectDecalOntoFace( &dp, ds );
-					break;
-				
-				case SURFACE_PATCH:
-					ProjectDecalOntoPatch( &dp, ds );
-					break;
-				
-				case SURFACE_TRIANGLES:
-				case SURFACE_FORCED_META:
-				case SURFACE_META:
-					ProjectDecalOntoTriangles( &dp, ds );
-					break;
-				
-				default:
-					break;
-			}
-		}
-	}
-	
-	/* print time */
-	Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d decal surfaces\n", numDecalSurfaces );
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define DECALS_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+#define MAX_PROJECTORS		1024
+
+typedef struct decalProjector_s
+{
+	shaderInfo_t			*si;
+	vec3_t					mins, maxs;
+	vec3_t					center;
+	float					radius, radius2;
+	int						numPlanes;	/* either 5 or 6, for quad or triangle projectors */
+	vec4_t					planes[ 6 ];
+	vec4_t					texMat[ 2 ];
+}
+decalProjector_t;
+
+static int					numProjectors = 0;
+static decalProjector_t		projectors[ MAX_PROJECTORS ];
+
+static int					numDecalSurfaces = 0;
+
+static vec3_t				entityOrigin;
+
+
+
+/*
+DVectorNormalize()
+normalizes a vector, returns the length, operates using doubles
+*/
+
+typedef double	dvec_t;
+typedef dvec_t	dvec3_t[ 3 ];
+
+dvec_t DVectorNormalize( dvec3_t in, dvec3_t out )
+{
+	dvec_t	len, ilen;
+	
+	
+	len = (dvec_t) sqrt( in[ 0 ] * in[ 0 ] + in[ 1 ] * in[ 1 ] + in[ 2 ] * in[ 2 ] );
+	if( len == 0.0 )
+	{
+		VectorClear( out );
+		return 0.0;
+	}
+	
+	ilen = 1.0 / len;
+	out[ 0 ] = in[ 0 ] * ilen;
+	out[ 1 ] = in[ 1 ] * ilen;
+	out[ 2 ] = in[ 2 ] * ilen;
+	
+	return len;
+}
+
+
+
+/*
+MakeTextureMatrix()
+generates a texture projection matrix for a triangle
+returns qfalse if a texture matrix cannot be created
+*/
+
+#define Vector2Subtract(a,b,c)	((c)[ 0 ] = (a)[ 0 ] - (b)[ 0 ], (c)[ 1 ] = (a)[ 1 ] - (b)[ 1 ])
+
+static qboolean MakeTextureMatrix( decalProjector_t *dp, vec4_t projection, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c )
+{
+	int			i, j;
+	double		bb, s, t, d;
+	dvec3_t		pa, pb, pc;
+	dvec3_t		bary, xyz;
+	dvec3_t		vecs[ 3 ], axis[ 3 ], lengths;
+	
+	
+	/* project triangle onto plane of projection */
+	d = DotProduct( a->xyz, projection ) - projection[ 3 ];
+	VectorMA( a->xyz, -d, projection, pa );
+	d = DotProduct( b->xyz, projection ) - projection[ 3 ];
+	VectorMA( b->xyz, -d, projection, pb );
+	d = DotProduct( c->xyz, projection ) - projection[ 3 ];
+	VectorMA( c->xyz, -d, projection, pc );
+	
+	/* two methods */
+	#if 1
+	{
+		/* old code */
+		
+		/* calculate barycentric basis for the triangle */
+		bb = (b->st[ 0 ] - a->st[ 0 ]) * (c->st[ 1 ] - a->st[ 1 ]) - (c->st[ 0 ] - a->st[ 0 ]) * (b->st[ 1 ] - a->st[ 1 ]);
+		if( fabs( bb ) < 0.00000001 )
+			return qfalse;
+		
+		/* calculate texture origin */
+		#if 0
+		s = 0.0;
+		t = 0.0;
+		bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb;
+		bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb;
+		bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb;
+		
+		origin[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ];
+		origin[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
+		origin[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
+		#endif
+		
+		/* calculate s vector */
+		s = a->st[ 0 ] + 1.0;
+		t = a->st[ 1 ] + 0.0;
+		bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb;
+		bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb;
+		bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb;
+		
+		xyz[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ];
+		xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
+		xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
+		
+		//%	VectorSubtract( xyz, origin, vecs[ 0 ] );
+		VectorSubtract( xyz, pa, vecs[ 0 ] );
+		
+		/* calculate t vector */
+		s = a->st[ 0 ] + 0.0;
+		t = a->st[ 1 ] + 1.0;
+		bary[ 0 ] = ((b->st[ 0 ] - s) * (c->st[ 1 ] - t) - (c->st[ 0 ] - s) * (b->st[ 1 ] - t)) / bb;
+		bary[ 1 ] = ((c->st[ 0 ] - s) * (a->st[ 1 ] - t) - (a->st[ 0 ] - s) * (c->st[ 1 ] - t)) / bb;
+		bary[ 2 ] = ((a->st[ 0 ] - s) * (b->st[ 1 ] - t) - (b->st[ 0 ] - s) * (a->st[ 1 ] - t)) / bb;
+		
+		xyz[ 0 ] = bary[ 0 ] * pa[ 0 ] + bary[ 1 ] * pb[ 0 ] + bary[ 2 ] * pc[ 0 ];
+		xyz[ 1 ] = bary[ 0 ] * pa[ 1 ] + bary[ 1 ] * pb[ 1 ] + bary[ 2 ] * pc[ 1 ];
+		xyz[ 2 ] = bary[ 0 ] * pa[ 2 ] + bary[ 1 ] * pb[ 2 ] + bary[ 2 ] * pc[ 2 ];
+		
+		//%	VectorSubtract( xyz, origin, vecs[ 1 ] );
+		VectorSubtract( xyz, pa, vecs[ 1 ] );
+		
+		/* calcuate r vector */
+		VectorScale( projection, -1.0, vecs[ 2 ] );
+		
+		/* calculate transform axis */
+		for( i = 0; i < 3; i++ )
+			lengths[ i ] = DVectorNormalize( vecs[ i ], axis[ i ] );
+		for( i = 0; i < 2; i++ )
+			for( j = 0; j < 3; j++ )
+				dp->texMat[ i ][ j ] = lengths[ i ] > 0.0 ? (axis[ i ][ j ] / lengths[ i ]) : 0.0;
+				//%	dp->texMat[ i ][ j ] = fabs( vecs[ i ][ j ] ) > 0.0 ? (1.0 / vecs[ i ][ j ]) : 0.0;
+				//%	dp->texMat[ i ][ j ] = axis[ i ][ j ] > 0.0 ? (1.0 / axis[ i ][ j ]) : 0.0;
+		
+		/* calculalate translation component */
+		dp->texMat[ 0 ][ 3 ] = a->st[ 0 ] - DotProduct( a->xyz, dp->texMat[ 0 ] );
+		dp->texMat[ 1 ][ 3 ] = a->st[ 1 ] - DotProduct( a->xyz, dp->texMat[ 1 ] );
+	}
+	#else
+	{
+		int			k;
+		dvec3_t		origin, deltas[ 3 ];
+		double		texDeltas[ 3 ][ 2 ];
+		double		delta, texDelta;
+		
+		
+		/* new code */
+		
+		/* calculate deltas */
+		VectorSubtract( pa, pb, deltas[ 0 ] );
+		VectorSubtract( pa, pc, deltas[ 1 ] );
+		VectorSubtract( pb, pc, deltas[ 2 ] );
+		Vector2Subtract( a->st, b->st, texDeltas[ 0 ] );
+		Vector2Subtract( a->st, c->st, texDeltas[ 1 ] );
+		Vector2Subtract( b->st, c->st, texDeltas[ 2 ] );
+		
+		/* walk st */
+		for( i = 0; i < 2; i++ )
+		{
+			/* walk xyz */
+			for( j = 0; j < 3; j++ )
+			{
+				/* clear deltas */
+				delta = 0.0;
+				texDelta = 0.0;
+				
+				/* walk deltas */
+				for( k = 0; k < 3; k++ )
+				{
+					if( fabs( deltas[ k ][ j ] ) > delta &&
+						fabs( texDeltas[ k ][ i ] ) > texDelta  )
+					{
+						delta = deltas[ k ][ j ];
+						texDelta = texDeltas[ k ][ i ];
+					}
+				}
+				
+				/* set texture matrix component */
+				if( fabs( delta ) > 0.0 )
+					dp->texMat[ i ][ j ] = texDelta / delta;
+				else
+					dp->texMat[ i ][ j ] = 0.0;
+			}
+		
+			/* set translation component */
+			dp->texMat[ i ][ 3 ] = a->st[ i ] - DotProduct( pa, dp->texMat[ i ] );
+		}
+	}
+	#endif
+	
+	/* debug code */
+	#if 1
+		Sys_Printf( "Mat: [ %f %f %f %f ] [ %f %f %f %f ] Theta: %f (%f)\n",
+			dp->texMat[ 0 ][ 0 ], dp->texMat[ 0 ][ 1 ], dp->texMat[ 0 ][ 2 ], dp->texMat[ 0 ][ 3 ], 
+			dp->texMat[ 1 ][ 0 ], dp->texMat[ 1 ][ 1 ], dp->texMat[ 1 ][ 2 ], dp->texMat[ 1 ][ 3 ],
+			RAD2DEG( acos( DotProduct( dp->texMat[ 0 ], dp->texMat[ 1 ] ) ) ),
+			RAD2DEG( acos( DotProduct( axis[ 0 ], axis[ 1 ] ) ) ) );
+		
+		Sys_Printf( "XYZ: %f %f %f ST: %f %f ST(t): %f %f\n",
+			a->xyz[ 0 ], a->xyz[ 1 ], a->xyz[ 2 ],
+			a->st[ 0 ], a->st[ 1 ],
+			DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ], DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ] );
+	#endif
+	
+	/* test texture matrix */
+	s = DotProduct( a->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
+	t = DotProduct( a->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
+	if( fabs( s - a->st[ 0 ] ) > 0.01 || fabs( t - a->st[ 1 ] ) > 0.01 )
+	{
+		Sys_Printf( "Bad texture matrix! (A) (%f, %f) != (%f, %f)\n",
+			s, t, a->st[ 0 ], a->st[ 1 ] );
+		//%	return qfalse;
+	}
+	s = DotProduct( b->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
+	t = DotProduct( b->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
+	if( fabs( s - b->st[ 0 ] ) > 0.01 || fabs( t - b->st[ 1 ] ) > 0.01 )
+	{
+		Sys_Printf( "Bad texture matrix! (B) (%f, %f) != (%f, %f)\n",
+			s, t, b->st[ 0 ], b->st[ 1 ] );
+		//%	return qfalse;
+	}
+	s = DotProduct( c->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
+	t = DotProduct( c->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
+	if( fabs( s - c->st[ 0 ] ) > 0.01 || fabs( t - c->st[ 1 ] ) > 0.01 )
+	{
+		Sys_Printf( "Bad texture matrix! (C) (%f, %f) != (%f, %f)\n",
+			s, t, c->st[ 0 ], c->st[ 1 ] );
+		//%	return qfalse;
+	}
+	
+	/* disco */
+	return qtrue;
+}
+
+
+
+/*
+TransformDecalProjector()
+transforms a decal projector
+note: non-normalized axes will screw up the plane transform
+*/
+
+static void TransformDecalProjector( decalProjector_t *in, vec3_t axis[ 3 ], vec3_t origin, decalProjector_t *out )
+{
+	int		i;
+	
+	
+	/* copy misc stuff */
+	out->si = in->si;
+	out->numPlanes = in->numPlanes;
+	
+	/* translate bounding box and sphere (note: rotated projector bounding box will be invalid!) */
+	VectorSubtract( in->mins, origin, out->mins );
+	VectorSubtract( in->maxs, origin, out->maxs );
+	VectorSubtract( in->center, origin, out->center );
+	out->radius = in->radius;
+	out->radius2 = in->radius2;
+	
+	/* translate planes */
+	for( i = 0; i < in->numPlanes; i++ )
+	{
+		out->planes[ i ][ 0 ] = DotProduct( in->planes[ i ], axis[ 0 ] );
+		out->planes[ i ][ 1 ] = DotProduct( in->planes[ i ], axis[ 1 ] );
+		out->planes[ i ][ 2 ] = DotProduct( in->planes[ i ], axis[ 2 ] );
+		out->planes[ i ][ 3 ] = in->planes[ i ][ 3 ] - DotProduct( out->planes[ i ], origin );
+	}
+	
+	/* translate texture matrix */
+	for( i = 0; i < 2; i++ )
+	{
+		out->texMat[ i ][ 0 ] = DotProduct( in->texMat[ i ], axis[ 0 ] );
+		out->texMat[ i ][ 1 ] = DotProduct( in->texMat[ i ], axis[ 1 ] );
+		out->texMat[ i ][ 2 ] = DotProduct( in->texMat[ i ], axis[ 2 ] );
+		out->texMat[ i ][ 3 ] = in->texMat[ i ][ 3 ] + DotProduct( out->texMat[ i ], origin );
+	}
+}
+
+
+
+/*
+MakeDecalProjector()
+creates a new decal projector from a triangle
+*/
+
+static int MakeDecalProjector( shaderInfo_t *si, vec4_t projection, float distance, int numVerts, bspDrawVert_t **dv )
+{
+	int					i, j;
+	decalProjector_t	*dp;
+	vec3_t				xyz;
+	
+	
+	/* dummy check */
+	if( numVerts != 3 && numVerts != 4 )
+		return -1;
+	
+	/* limit check */
+	if( numProjectors >= MAX_PROJECTORS )
+	{
+		Sys_Printf( "WARNING: MAX_PROJECTORS (%d) exceeded, no more decal projectors available.\n", MAX_PROJECTORS );
+		return -2;
+	}
+	
+	/* create a new projector */
+	dp = &projectors[ numProjectors ];
+	memset( dp, 0, sizeof( *dp ) );
+	
+	/* basic setup */
+	dp->si = si;
+	dp->numPlanes = numVerts + 2;
+	
+	/* make texture matrix */
+	if( !MakeTextureMatrix( dp, projection, dv[ 0 ], dv[ 1 ], dv[ 2 ] ) )
+		return -1;
+	
+	/* bound the projector */
+	ClearBounds( dp->mins, dp->maxs );
+	for( i = 0; i < numVerts; i++ )
+	{
+		AddPointToBounds( dv[ i ]->xyz, dp->mins, dp->maxs );
+		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
+		AddPointToBounds( xyz, dp->mins, dp->maxs );
+	}
+	
+	/* make bouding sphere */
+	VectorAdd( dp->mins, dp->maxs, dp->center );
+	VectorScale( dp->center, 0.5f, dp->center );
+	VectorSubtract( dp->maxs, dp->center, xyz );
+	dp->radius = VectorLength( xyz );
+	dp->radius2 = dp->radius * dp->radius;
+	
+	/* make the front plane */
+	if( !PlaneFromPoints( dp->planes[ 0 ], dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) )
+		return -1;
+	
+	/* make the back plane */
+	VectorSubtract( vec3_origin, dp->planes[ 0 ], dp->planes[ 1 ] );
+	VectorMA( dv[ 0 ]->xyz, distance, projection, xyz );
+	dp->planes[ 1 ][ 3 ] = DotProduct( xyz, dp->planes[ 1 ] );
+	
+	/* make the side planes */
+	for( i = 0; i < numVerts; i++ )
+	{
+		j = (i + 1) % numVerts;
+		VectorMA( dv[ i ]->xyz, distance, projection, xyz );
+		if( !PlaneFromPoints( dp->planes[ i + 2 ], dv[ j ]->xyz, dv[ i ]->xyz, xyz ) )
+			return -1;
+	}
+	
+	/* return ok */
+	numProjectors++;
+	return numProjectors - 1;
+}
+
+
+
+/*
+ProcessDecals()
+finds all decal entities and creates decal projectors
+*/
+
+#define PLANAR_EPSILON	0.5f
+
+void ProcessDecals( void )
+{
+	int					i, j, x, y, pw[ 5 ], r, iterations;
+	float				distance;
+	vec4_t				projection, plane;
+	vec3_t				origin, target, delta;
+	entity_t			*e, *e2;
+	parseMesh_t			*p;
+	mesh_t				*mesh, *subdivided;
+	bspDrawVert_t		*dv[ 4 ];
+	const char			*value;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- ProcessDecals ---\n" );
+	
+	/* walk entity list */
+	for( i = 0; i < numEntities; i++ )
+	{
+		/* get entity */
+		e = &entities[ i ];
+		value = ValueForKey( e, "classname" );
+		if( Q_stricmp( value, "_decal" ) )
+			continue;
+		
+		/* any patches? */
+		if( e->patches == NULL )
+		{
+			Sys_Printf( "WARNING: Decal entity without any patch meshes, ignoring.\n" );
+			e->epairs = NULL;	/* fixme: leak! */
+			continue;
+		}
+		
+		/* find target */
+		value = ValueForKey( e, "target" );
+		e2 = FindTargetEntity( value );
+		
+		/* no target? */
+		if( e2 == NULL )
+		{
+			Sys_Printf( "WARNING: Decal entity without a valid target, ignoring.\n" );
+			continue;
+		}
+		
+		/* walk entity patches */
+		for( p = e->patches; p != NULL; p = e->patches )
+		{
+			/* setup projector */
+			if( VectorCompare( e->origin, vec3_origin ) )
+			{
+				VectorAdd( p->eMins, p->eMaxs, origin );
+				VectorScale( origin, 0.5f, origin );
+			}
+			else
+				VectorCopy( e->origin, origin );
+			
+			VectorCopy( e2->origin, target );
+			VectorSubtract( target, origin, delta );
+			
+			/* setup projection plane */
+			distance = VectorNormalize( delta, projection );
+			projection[ 3 ] = DotProduct( origin, projection );
+			
+			/* create projectors */
+			if( distance > 0.125f )
+			{
+				/* tesselate the patch */
+				iterations = IterationsForCurve( p->longestCurve, patchSubdivisions );
+				subdivided = SubdivideMesh2( p->mesh, iterations );
+				
+				/* fit it to the curve and remove colinear verts on rows/columns */
+				PutMeshOnCurve( *subdivided );
+				mesh = RemoveLinearMeshColumnsRows( subdivided );
+				FreeMesh( subdivided );
+				
+				/* offset by projector origin */
+				for( j = 0; j < (mesh->width * mesh->height); j++ )
+					VectorAdd( mesh->verts[ j ].xyz, e->origin, mesh->verts[ j ].xyz );
+				
+				/* iterate through the mesh quads */
+				for( y = 0; y < (mesh->height - 1); y++ )
+				{
+					for( x = 0; x < (mesh->width - 1); x++ )
+					{
+						/* set indexes */
+						pw[ 0 ] = x + (y * mesh->width);
+						pw[ 1 ] = x + ((y + 1) * mesh->width);
+						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+						pw[ 3 ] = x + 1 + (y * mesh->width);
+						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+						
+						/* set radix */
+						r = (x + y) & 1;
+						
+						/* get drawverts */
+						dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
+						dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
+						dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
+						dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
+						
+						/* planar? (nuking this optimization as it doesn't work on non-rectangular quads) */
+						plane[ 0 ] = 0.0f;	/* stupid msvc */
+						if( 0 && PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) &&
+							fabs( DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ] ) <= PLANAR_EPSILON )
+						{
+							/* make a quad projector */
+							MakeDecalProjector( p->shaderInfo, projection, distance, 4, dv );
+						}
+						else
+						{
+							/* make first triangle */
+							MakeDecalProjector( p->shaderInfo, projection, distance, 3, dv );
+							
+							/* make second triangle */
+							dv[ 1 ] = dv[ 2 ];
+							dv[ 2 ] = dv[ 3 ];
+							MakeDecalProjector( p->shaderInfo, projection, distance, 3, dv );
+						}
+					}
+				}
+				
+				/* clean up */
+				free( mesh );
+			}
+			
+			/* remove patch from entity (fixme: leak!) */
+			e->patches = p->next;
+			
+			/* push patch to worldspawn (enable this to debug projectors) */
+			#if 0
+				p->next = entities[ 0 ].patches;
+				entities[ 0 ].patches = p;
+			#endif
+		}
+	}
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d decal projectors\n", numProjectors );
+}
+
+
+
+/*
+ProjectDecalOntoWinding()
+projects a decal onto a winding
+*/
+
+static void ProjectDecalOntoWinding( decalProjector_t *dp, mapDrawSurface_t *ds, winding_t *w )
+{
+	int					i, j;
+	float				d, d2, alpha;
+	winding_t			*front, *back;
+	mapDrawSurface_t	*ds2;
+	bspDrawVert_t		*dv;
+	vec4_t				plane;
+	
+	
+	/* dummy check */
+	if( w->numpoints < 3 )
+	{
+		FreeWinding( w );
+		return;
+	}
+	
+	/* offset by entity origin */
+	for( i = 0; i < w->numpoints; i++ )
+		VectorAdd( w->p[ i ], entityOrigin, w->p[ i ] );
+	
+	/* make a plane from the winding */
+	if( !PlaneFromPoints( plane, w->p[ 0 ], w->p[ 1 ], w->p[ 2 ] ) )
+	{
+		FreeWinding( w );
+		return;
+	}
+	
+	/* backface check */
+	d = DotProduct( dp->planes[ 0 ], plane );
+	if( d < -0.0001f )
+	{
+		FreeWinding( w );
+		return;
+	}
+	
+	/* walk list of planes */
+	for( i = 0; i < dp->numPlanes; i++ )
+	{
+		/* chop winding by the plane */
+		ClipWindingEpsilon( w, dp->planes[ i ], dp->planes[ i ][ 3 ], 0.0625f, &front, &back );
+		FreeWinding( w );
+		
+		/* lose the front fragment */
+		if( front != NULL )
+			FreeWinding( front );
+		
+		/* if nothing left in back, then bail */
+		if( back == NULL )
+			return;
+		
+		/* reset winding */
+		w = back;
+	}
+	
+	/* nothing left? */
+	if( w == NULL || w->numpoints < 3 )
+		return;
+	
+	/* add to counts */
+	numDecalSurfaces++;
+	
+	/* make a new surface */
+	ds2 = AllocDrawSurface( SURFACE_DECAL );
+	
+	/* set it up */
+	ds2->entityNum = ds->entityNum;
+	ds2->castShadows = ds->castShadows;
+	ds2->recvShadows = ds->recvShadows;
+	ds2->shaderInfo = dp->si;
+	ds2->fogNum = ds->fogNum;	/* why was this -1? */
+	ds2->lightmapScale = ds->lightmapScale;
+	ds2->numVerts = w->numpoints;
+	ds2->verts = safe_malloc( ds2->numVerts * sizeof( *ds2->verts ) );
+	memset( ds2->verts, 0, ds2->numVerts * sizeof( *ds2->verts ) );
+	
+	/* set vertexes */
+	for( i = 0; i < ds2->numVerts; i++ )
+	{
+		/* get vertex */
+		dv = &ds2->verts[ i ];
+		
+		/* set alpha */
+		d = DotProduct( w->p[ i ], dp->planes[ 0 ] ) - dp->planes[ 0 ][ 3 ];
+		d2 = DotProduct( w->p[ i ], dp->planes[ 1 ] ) - dp->planes[ 1 ][ 3 ];
+		alpha = 255.0f * d2 / (d + d2);
+		if( alpha > 255 )
+			alpha = 255;
+		else if( alpha < 0 )
+			alpha = 0;
+		
+		/* set misc */
+		VectorSubtract( w->p[ i ], entityOrigin, dv->xyz );
+		VectorCopy( plane, dv->normal );
+		dv->st[ 0 ] = DotProduct( dv->xyz, dp->texMat[ 0 ] ) + dp->texMat[ 0 ][ 3 ];
+		dv->st[ 1 ] = DotProduct( dv->xyz, dp->texMat[ 1 ] ) + dp->texMat[ 1 ][ 3 ];
+		
+		/* set color */
+		for( j = 0; j < MAX_LIGHTMAPS; j++ )
+		{
+			dv->color[ j ][ 0 ] = 255;
+			dv->color[ j ][ 1 ] = 255;
+			dv->color[ j ][ 2 ] = 255;
+			dv->color[ j ][ 3 ] = alpha;
+		}
+	}
+	
+	/* ydnar: finish the surface */
+	FinishSurface( ds2 );
+}
+
+
+
+/*
+ProjectDecalOntoFace()
+projects a decal onto a brushface surface
+*/
+
+static void ProjectDecalOntoFace( decalProjector_t *dp, mapDrawSurface_t *ds )
+{
+	vec4_t		plane;
+	float		d;
+	winding_t	*w;
+	
+	
+	/* dummy check */
+	if( ds->sideRef == NULL || ds->sideRef->side == NULL )
+		return;
+	
+	/* backface check */
+	if( ds->planar )
+	{
+		VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
+		plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
+		d = DotProduct( dp->planes[ 0 ], plane );
+		if( d < -0.0001f )
+			return;
+	}
+	
+	/* generate decal */
+	w = WindingFromDrawSurf( ds );
+	ProjectDecalOntoWinding( dp, ds, w );
+}
+
+
+
+/*
+ProjectDecalOntoPatch()
+projects a decal onto a patch surface
+*/
+
+static void ProjectDecalOntoPatch( decalProjector_t *dp, mapDrawSurface_t *ds )
+{
+	int			x, y, pw[ 5 ], r, iterations;
+	vec4_t		plane;
+	float		d;
+	mesh_t		src, *mesh, *subdivided;
+	winding_t	*w;
+	
+	
+	/* backface check */
+	if( ds->planar )
+	{
+		VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
+		plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
+		d = DotProduct( dp->planes[ 0 ], plane );
+		if( d < -0.0001f )
+			return;
+	}
+	
+	/* tesselate the patch */
+	src.width = ds->patchWidth;
+	src.height = ds->patchHeight;
+	src.verts = ds->verts;
+	iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
+	subdivided = SubdivideMesh2( src, iterations );
+	
+	/* fit it to the curve and remove colinear verts on rows/columns */
+	PutMeshOnCurve( *subdivided );
+	mesh = RemoveLinearMeshColumnsRows( subdivided );
+	FreeMesh( subdivided );
+	
+	/* iterate through the mesh quads */
+	for( y = 0; y < (mesh->height - 1); y++ )
+	{
+		for( x = 0; x < (mesh->width - 1); x++ )
+		{
+			/* set indexes */
+			pw[ 0 ] = x + (y * mesh->width);
+			pw[ 1 ] = x + ((y + 1) * mesh->width);
+			pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+			pw[ 3 ] = x + 1 + (y * mesh->width);
+			pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+			
+			/* set radix */
+			r = (x + y) & 1;
+			
+			/* generate decal for first triangle */
+			w = AllocWinding( 3 );
+			w->numpoints = 3;
+			VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
+			VectorCopy( mesh->verts[ pw[ r + 1 ] ].xyz, w->p[ 1 ] );
+			VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 2 ] );
+			ProjectDecalOntoWinding( dp, ds, w );
+			
+			/* generate decal for second triangle */
+			w = AllocWinding( 3 );
+			w->numpoints = 3;
+			VectorCopy( mesh->verts[ pw[ r + 0 ] ].xyz, w->p[ 0 ] );
+			VectorCopy( mesh->verts[ pw[ r + 2 ] ].xyz, w->p[ 1 ] );
+			VectorCopy( mesh->verts[ pw[ r + 3 ] ].xyz, w->p[ 2 ] );
+			ProjectDecalOntoWinding( dp, ds, w );
+		}
+	}
+	
+	/* clean up */
+	free( mesh );
+}
+
+
+
+/*
+ProjectDecalOntoTriangles()
+projects a decal onto a triangle surface
+*/
+
+static void ProjectDecalOntoTriangles( decalProjector_t *dp, mapDrawSurface_t *ds )
+{
+	int			i;
+	vec4_t		plane;
+	float		d;
+	winding_t	*w;
+	
+	
+	/* triangle surfaces without shaders don't get marks by default */
+	if( (ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FORCED_META) &&
+		ds->shaderInfo->shaderText == NULL )
+		return;
+	
+	/* backface check */
+	if( ds->planar )
+	{
+		VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
+		plane[ 3 ] = mapplanes[ ds->planeNum ].dist + DotProduct( plane, entityOrigin );
+		d = DotProduct( dp->planes[ 0 ], plane );
+		if( d < -0.0001f )
+			return;
+	}
+	
+	/* iterate through triangles */
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		/* generate decal */
+		w = AllocWinding( 3 );
+		w->numpoints = 3;
+		VectorCopy( ds->verts[ ds->indexes[ i ] ].xyz, w->p[ 0 ] );
+		VectorCopy( ds->verts[ ds->indexes[ i + 1 ] ].xyz, w->p[ 1 ] );
+		VectorCopy( ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] );
+		ProjectDecalOntoWinding( dp, ds, w );
+	}
+}
+
+
+
+/*
+MakeEntityDecals()
+projects decals onto world surfaces
+*/
+
+void MakeEntityDecals( entity_t *e )
+{
+	int					i, j, k, f, fOld, start;
+	decalProjector_t	dp;
+	mapDrawSurface_t	*ds;
+	vec3_t				identityAxis[ 3 ] = { { 1, 0, 0 }, { 0, 1, 0 }, { 0, 0, 1 } };
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- MakeEntityDecals ---\n" );
+	
+	/* set entity origin */
+	VectorCopy( e->origin, entityOrigin );
+	
+	/* transform projector instead of geometry */
+	VectorClear( entityOrigin );
+	
+	/* init pacifier */
+	fOld = -1;
+	start = I_FloatTime();
+	
+	/* walk the list of decal projectors */
+	for( i = 0; i < numProjectors; i++ )
+	{
+		/* print pacifier */
+		f = 10 * i / numProjectors;
+		if( f != fOld )
+		{
+			fOld = f;
+			Sys_FPrintf( SYS_VRB, "%d...", f );
+		}
+		
+		/* get projector */
+		TransformDecalProjector( &projectors[ i ], identityAxis, e->origin, &dp );
+		
+		/* walk the list of surfaces in the entity */
+		for( j = e->firstDrawSurf; j < numMapDrawSurfs; j++ )
+		{
+			/* get surface */
+			ds = &mapDrawSurfs[ j ];
+			if( ds->numVerts <= 0 )
+				continue;
+			
+			/* ignore autosprite or nomarks */
+			if( ds->shaderInfo->autosprite || (ds->shaderInfo->compileFlags & C_NOMARKS) )
+				continue;
+			
+			/* bounds check */
+			for( k = 0; k < 3; k++ )
+				if( ds->mins[ k ] >= (dp.center[ k ] + dp.radius) ||
+					ds->maxs[ k ] <= (dp.center[ k ] - dp.radius) )
+					break;
+			if( k < 3 )
+				continue;
+			
+			/* switch on type */
+			switch( ds->type )
+			{
+				case SURFACE_FACE:
+					ProjectDecalOntoFace( &dp, ds );
+					break;
+				
+				case SURFACE_PATCH:
+					ProjectDecalOntoPatch( &dp, ds );
+					break;
+				
+				case SURFACE_TRIANGLES:
+				case SURFACE_FORCED_META:
+				case SURFACE_META:
+					ProjectDecalOntoTriangles( &dp, ds );
+					break;
+				
+				default:
+					break;
+			}
+		}
+	}
+	
+	/* print time */
+	Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d decal surfaces\n", numDecalSurfaces );
+}
diff --git a/tools/quake3/q3map2/facebsp.c b/tools/quake3/q3map2/facebsp.c
index b92facc4..484a7489 100644
--- a/tools/quake3/q3map2/facebsp.c
+++ b/tools/quake3/q3map2/facebsp.c
@@ -1,453 +1,453 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define FACEBSP_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-int			c_faceLeafs;
-
-
-/*
-================
-AllocBspFace
-================
-*/
-face_t	*AllocBspFace( void ) {
-	face_t	*f;
-
-	f = safe_malloc(sizeof(*f));
-	memset( f, 0, sizeof(*f) );
-
-	return f;
-}
-
-
-
-/*
-================
-FreeBspFace
-================
-*/
-void	FreeBspFace( face_t *f ) {
-	if ( f->w ) {
-		FreeWinding( f->w );
-	}
-	free( f );
-}
-
-
-
-/*
-SelectSplitPlaneNum()
-finds the best split plane for this node
-*/
-
-static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, int *compileFlags )
-{
-	face_t		*split;
-	face_t		*check;
-	face_t		*bestSplit;
-	int			splits, facing, front, back;
-	int			side;
-	plane_t		*plane;
-	int			value, bestValue;
-	int			i;
-	vec3_t		normal;
-	float		dist;
-	int			planenum;
-	
-	
-	/* ydnar: set some defaults */
-	*splitPlaneNum = -1; /* leaf */
-	*compileFlags = 0;
-	
-	/* ydnar 2002-06-24: changed this to split on z-axis as well */
-	/* ydnar 2002-09-21: changed blocksize to be a vector, so mappers can specify a 3 element value */
-	
-	/* if it is crossing a block boundary, force a split */
-	for( i = 0; i < 3; i++ )
-	{
-		if( blockSize[ i ] <= 0 )
-			continue;
-		dist = blockSize[ i ] * (floor( node->mins[ i ] / blockSize[ i ] ) + 1);
-		if( node->maxs[ i ] > dist )
-		{
-			VectorClear( normal );
-			normal[ i ] = 1;
-			planenum = FindFloatPlane( normal, dist, 0, NULL );
-			*splitPlaneNum = planenum;
-			return;
-		}
-	}
-	
-	/* pick one of the face planes */
-	bestValue = -99999;
-	bestSplit = list;
-	
-	for( split = list; split; split = split->next )
-		split->checked = qfalse;
-	
-	for( split = list; split; split = split->next )
-	{
-		if ( split->checked )
-			continue;
-		
-		plane = &mapplanes[ split->planenum ];
-		splits = 0;
-		facing = 0;
-		front = 0;
-		back = 0;
-		for ( check = list ; check ; check = check->next ) {
-			if ( check->planenum == split->planenum ) {
-				facing++;
-				check->checked = qtrue;	// won't need to test this plane again
-				continue;
-			}
-			side = WindingOnPlaneSide( check->w, plane->normal, plane->dist );
-			if ( side == SIDE_CROSS ) {
-				splits++;
-			} else if ( side == SIDE_FRONT ) {
-				front++;
-			} else if ( side == SIDE_BACK ) {
-				back++;
-			}
-		}
-		value =  5*facing - 5*splits; // - abs(front-back);
-		if ( plane->type < 3 ) {
-			value+=5;		// axial is better
-		}
-		value += split->priority;		// prioritize hints higher
-
-		if ( value > bestValue ) {
-			bestValue = value;
-			bestSplit = split;
-		}
-	}
-	
-	/* nothing, we have a leaf */
-	if( bestValue == -99999 )
-		return;
-	
-	/* set best split data */
-	*splitPlaneNum = bestSplit->planenum;
-	*compileFlags = bestSplit->compileFlags;
-}
-
-
-
-/*
-CountFaceList()
-counts bsp faces in the linked list
-*/
-
-int	CountFaceList( face_t *list )
-{
-	int		c;
-	
-
-	c = 0;
-	for( list; list != NULL; list = list->next )
-		c++;
-	return c;
-}
-
-
-
-/*
-BuildFaceTree_r()
-recursively builds the bsp, splitting on face planes
-*/
-
-void BuildFaceTree_r( node_t *node, face_t *list )
-{
-	face_t		*split;
-	face_t		*next;
-	int			side;
-	plane_t		*plane;
-	face_t		*newFace;
-	face_t		*childLists[2];
-	winding_t	*frontWinding, *backWinding;
-	int			i;
-	int			splitPlaneNum, compileFlags;
-	
-	
-	/* count faces left */
-	i = CountFaceList( list );
-	
-	/* select the best split plane */
-	SelectSplitPlaneNum( node, list, &splitPlaneNum, &compileFlags );
-	
-	/* if we don't have any more faces, this is a node */
-	if ( splitPlaneNum == -1 )
-	{
-		node->planenum = PLANENUM_LEAF;
-		c_faceLeafs++;
-		return;
-	}
-	
-	/* partition the list */
-	node->planenum = splitPlaneNum;
-	node->compileFlags = compileFlags;
-	plane = &mapplanes[ splitPlaneNum ];
-	childLists[0] = NULL;
-	childLists[1] = NULL;
-	for( split = list; split; split = next )
-	{
-		/* set next */
-		next = split->next;
-		
-		/* don't split by identical plane */
-		if( split->planenum == node->planenum )
-		{
-			FreeBspFace( split );
-			continue;
-		}
-		
-		/* determine which side the face falls on */
-		side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
-		
-		/* switch on side */
-		if( side == SIDE_CROSS )
-		{
-			ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
-				&frontWinding, &backWinding );
-			if( frontWinding ) {
-				newFace = AllocBspFace();
-				newFace->w = frontWinding;
-				newFace->next = childLists[0];
-				newFace->planenum = split->planenum;
-				newFace->priority = split->priority;
-				newFace->compileFlags = split->compileFlags;
-				childLists[0] = newFace;
-			}
-			if( backWinding ) {
-				newFace = AllocBspFace();
-				newFace->w = backWinding;
-				newFace->next = childLists[1];
-				newFace->planenum = split->planenum;
-				newFace->priority = split->priority;
-				newFace->compileFlags = split->compileFlags;
-				childLists[1] = newFace;
-			}
-			FreeBspFace( split );
-		} else if ( side == SIDE_FRONT ) {
-			split->next = childLists[0];
-			childLists[0] = split;
-		} else if ( side == SIDE_BACK ) {
-			split->next = childLists[1];
-			childLists[1] = split;
-		}
-	}
-
-
-	// recursively process children
-	for ( i = 0 ; i < 2 ; i++ ) {
-		node->children[i] = AllocNode();
-		node->children[i]->parent = node;
-		VectorCopy( node->mins, node->children[i]->mins );
-		VectorCopy( node->maxs, node->children[i]->maxs );
-	}
-
-	for ( i = 0 ; i < 3 ; i++ ) {
-		if ( plane->normal[i] == 1 ) {
-			node->children[0]->mins[i] = plane->dist;
-			node->children[1]->maxs[i] = plane->dist;
-			break;
-		}
-	}
-
-	for ( i = 0 ; i < 2 ; i++ ) {
-		BuildFaceTree_r ( node->children[i], childLists[i]);
-	}
-}
-
-
-/*
-================
-FaceBSP
-
-List will be freed before returning
-================
-*/
-tree_t *FaceBSP( face_t *list ) {
-	tree_t		*tree;
-	face_t	*face;
-	int			i;
-	int			count;
-
-	Sys_FPrintf (SYS_VRB, "--- FaceBSP ---\n" );
-
-	tree = AllocTree ();
-
-	count = 0;
-	for( face = list; face != NULL; face = face->next )
-	{
-		count++;
-		for( i = 0; i < face->w->numpoints; i++ )
-		{
-			AddPointToBounds( face->w->p[ i ], tree->mins, tree->maxs );
-		}
-	}
-	Sys_FPrintf( SYS_VRB, "%9d faces\n", count );
-
-	tree->headnode = AllocNode();
-	VectorCopy( tree->mins, tree->headnode->mins );
-	VectorCopy( tree->maxs, tree->headnode->maxs );
-	c_faceLeafs = 0;
-
-	BuildFaceTree_r ( tree->headnode, list );
-
-	Sys_FPrintf( SYS_VRB, "%9d leafs\n", c_faceLeafs );
-
-	return tree;
-}
-
-
-
-/*
-MakeStructuralBSPFaceList()
-get structural brush faces
-*/
-
-face_t *MakeStructuralBSPFaceList( brush_t *list )
-{
-	brush_t		*b;
-	int			i;
-	side_t		*s;
-	winding_t	*w;
-	face_t		*f, *flist;
-	
-	
-	flist = NULL;
-	for( b = list; b != NULL; b = b->next )
-	{
-		if( b->detail )
-			continue;
-		
-		for( i = 0; i < b->numsides; i++ )
-		{
-			/* get side and winding */
-			s = &b->sides[ i ];
-			w = s->winding;
-			if( w == NULL )
-				continue;
-			
-			/* ydnar: skip certain faces */
-			if( s->compileFlags & C_SKIP )
-				continue;
-			
-			/* allocate a face */
-			f = AllocBspFace();
-			f->w = CopyWinding( w );
-			f->planenum = s->planenum & ~1;
-			f->compileFlags = s->compileFlags;	/* ydnar */
-			
-			/* ydnar: set priority */
-			f->priority = 0;
-			if( f->compileFlags & C_HINT )
-				f->priority += HINT_PRIORITY;
-			if( f->compileFlags & C_ANTIPORTAL )
-				f->priority += ANTIPORTAL_PRIORITY;
-			if( f->compileFlags & C_AREAPORTAL )
-				f->priority += AREAPORTAL_PRIORITY;
-			
-			/* get next face */
-			f->next = flist;
-			flist = f;
-		}
-	}
-	
-	return flist;
-}
-
-
-
-/*
-MakeVisibleBSPFaceList()
-get visible brush faces
-*/
-
-face_t *MakeVisibleBSPFaceList( brush_t *list )
-{
-	brush_t		*b;
-	int			i;
-	side_t		*s;
-	winding_t	*w;
-	face_t		*f, *flist;
-	
-	
-	flist = NULL;
-	for( b = list; b != NULL; b = b->next )
-	{
-		if( b->detail )
-			continue;
-		
-		for( i = 0; i < b->numsides; i++ )
-		{
-			/* get side and winding */
-			s = &b->sides[ i ];
-			w = s->visibleHull;
-			if( w == NULL )
-				continue;
-			
-			/* ydnar: skip certain faces */
-			if( s->compileFlags & C_SKIP )
-				continue;
-			
-			/* allocate a face */
-			f = AllocBspFace();
-			f->w = CopyWinding( w );
-			f->planenum = s->planenum & ~1;
-			f->compileFlags = s->compileFlags;	/* ydnar */
-			
-			/* ydnar: set priority */
-			f->priority = 0;
-			if( f->compileFlags & C_HINT )
-				f->priority += HINT_PRIORITY;
-			if( f->compileFlags & C_ANTIPORTAL )
-				f->priority += ANTIPORTAL_PRIORITY;
-			if( f->compileFlags & C_AREAPORTAL )
-				f->priority += AREAPORTAL_PRIORITY;
-			
-			/* get next face */
-			f->next = flist;
-			flist = f;
-		}
-	}
-	
-	return flist;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define FACEBSP_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+int			c_faceLeafs;
+
+
+/*
+================
+AllocBspFace
+================
+*/
+face_t	*AllocBspFace( void ) {
+	face_t	*f;
+
+	f = safe_malloc(sizeof(*f));
+	memset( f, 0, sizeof(*f) );
+
+	return f;
+}
+
+
+
+/*
+================
+FreeBspFace
+================
+*/
+void	FreeBspFace( face_t *f ) {
+	if ( f->w ) {
+		FreeWinding( f->w );
+	}
+	free( f );
+}
+
+
+
+/*
+SelectSplitPlaneNum()
+finds the best split plane for this node
+*/
+
+static void SelectSplitPlaneNum( node_t *node, face_t *list, int *splitPlaneNum, int *compileFlags )
+{
+	face_t		*split;
+	face_t		*check;
+	face_t		*bestSplit;
+	int			splits, facing, front, back;
+	int			side;
+	plane_t		*plane;
+	int			value, bestValue;
+	int			i;
+	vec3_t		normal;
+	float		dist;
+	int			planenum;
+	
+	
+	/* ydnar: set some defaults */
+	*splitPlaneNum = -1; /* leaf */
+	*compileFlags = 0;
+	
+	/* ydnar 2002-06-24: changed this to split on z-axis as well */
+	/* ydnar 2002-09-21: changed blocksize to be a vector, so mappers can specify a 3 element value */
+	
+	/* if it is crossing a block boundary, force a split */
+	for( i = 0; i < 3; i++ )
+	{
+		if( blockSize[ i ] <= 0 )
+			continue;
+		dist = blockSize[ i ] * (floor( node->mins[ i ] / blockSize[ i ] ) + 1);
+		if( node->maxs[ i ] > dist )
+		{
+			VectorClear( normal );
+			normal[ i ] = 1;
+			planenum = FindFloatPlane( normal, dist, 0, NULL );
+			*splitPlaneNum = planenum;
+			return;
+		}
+	}
+	
+	/* pick one of the face planes */
+	bestValue = -99999;
+	bestSplit = list;
+	
+	for( split = list; split; split = split->next )
+		split->checked = qfalse;
+	
+	for( split = list; split; split = split->next )
+	{
+		if ( split->checked )
+			continue;
+		
+		plane = &mapplanes[ split->planenum ];
+		splits = 0;
+		facing = 0;
+		front = 0;
+		back = 0;
+		for ( check = list ; check ; check = check->next ) {
+			if ( check->planenum == split->planenum ) {
+				facing++;
+				check->checked = qtrue;	// won't need to test this plane again
+				continue;
+			}
+			side = WindingOnPlaneSide( check->w, plane->normal, plane->dist );
+			if ( side == SIDE_CROSS ) {
+				splits++;
+			} else if ( side == SIDE_FRONT ) {
+				front++;
+			} else if ( side == SIDE_BACK ) {
+				back++;
+			}
+		}
+		value =  5*facing - 5*splits; // - abs(front-back);
+		if ( plane->type < 3 ) {
+			value+=5;		// axial is better
+		}
+		value += split->priority;		// prioritize hints higher
+
+		if ( value > bestValue ) {
+			bestValue = value;
+			bestSplit = split;
+		}
+	}
+	
+	/* nothing, we have a leaf */
+	if( bestValue == -99999 )
+		return;
+	
+	/* set best split data */
+	*splitPlaneNum = bestSplit->planenum;
+	*compileFlags = bestSplit->compileFlags;
+}
+
+
+
+/*
+CountFaceList()
+counts bsp faces in the linked list
+*/
+
+int	CountFaceList( face_t *list )
+{
+	int		c;
+	
+
+	c = 0;
+	for( list; list != NULL; list = list->next )
+		c++;
+	return c;
+}
+
+
+
+/*
+BuildFaceTree_r()
+recursively builds the bsp, splitting on face planes
+*/
+
+void BuildFaceTree_r( node_t *node, face_t *list )
+{
+	face_t		*split;
+	face_t		*next;
+	int			side;
+	plane_t		*plane;
+	face_t		*newFace;
+	face_t		*childLists[2];
+	winding_t	*frontWinding, *backWinding;
+	int			i;
+	int			splitPlaneNum, compileFlags;
+	
+	
+	/* count faces left */
+	i = CountFaceList( list );
+	
+	/* select the best split plane */
+	SelectSplitPlaneNum( node, list, &splitPlaneNum, &compileFlags );
+	
+	/* if we don't have any more faces, this is a node */
+	if ( splitPlaneNum == -1 )
+	{
+		node->planenum = PLANENUM_LEAF;
+		c_faceLeafs++;
+		return;
+	}
+	
+	/* partition the list */
+	node->planenum = splitPlaneNum;
+	node->compileFlags = compileFlags;
+	plane = &mapplanes[ splitPlaneNum ];
+	childLists[0] = NULL;
+	childLists[1] = NULL;
+	for( split = list; split; split = next )
+	{
+		/* set next */
+		next = split->next;
+		
+		/* don't split by identical plane */
+		if( split->planenum == node->planenum )
+		{
+			FreeBspFace( split );
+			continue;
+		}
+		
+		/* determine which side the face falls on */
+		side = WindingOnPlaneSide( split->w, plane->normal, plane->dist );
+		
+		/* switch on side */
+		if( side == SIDE_CROSS )
+		{
+			ClipWindingEpsilon( split->w, plane->normal, plane->dist, CLIP_EPSILON * 2,
+				&frontWinding, &backWinding );
+			if( frontWinding ) {
+				newFace = AllocBspFace();
+				newFace->w = frontWinding;
+				newFace->next = childLists[0];
+				newFace->planenum = split->planenum;
+				newFace->priority = split->priority;
+				newFace->compileFlags = split->compileFlags;
+				childLists[0] = newFace;
+			}
+			if( backWinding ) {
+				newFace = AllocBspFace();
+				newFace->w = backWinding;
+				newFace->next = childLists[1];
+				newFace->planenum = split->planenum;
+				newFace->priority = split->priority;
+				newFace->compileFlags = split->compileFlags;
+				childLists[1] = newFace;
+			}
+			FreeBspFace( split );
+		} else if ( side == SIDE_FRONT ) {
+			split->next = childLists[0];
+			childLists[0] = split;
+		} else if ( side == SIDE_BACK ) {
+			split->next = childLists[1];
+			childLists[1] = split;
+		}
+	}
+
+
+	// recursively process children
+	for ( i = 0 ; i < 2 ; i++ ) {
+		node->children[i] = AllocNode();
+		node->children[i]->parent = node;
+		VectorCopy( node->mins, node->children[i]->mins );
+		VectorCopy( node->maxs, node->children[i]->maxs );
+	}
+
+	for ( i = 0 ; i < 3 ; i++ ) {
+		if ( plane->normal[i] == 1 ) {
+			node->children[0]->mins[i] = plane->dist;
+			node->children[1]->maxs[i] = plane->dist;
+			break;
+		}
+	}
+
+	for ( i = 0 ; i < 2 ; i++ ) {
+		BuildFaceTree_r ( node->children[i], childLists[i]);
+	}
+}
+
+
+/*
+================
+FaceBSP
+
+List will be freed before returning
+================
+*/
+tree_t *FaceBSP( face_t *list ) {
+	tree_t		*tree;
+	face_t	*face;
+	int			i;
+	int			count;
+
+	Sys_FPrintf (SYS_VRB, "--- FaceBSP ---\n" );
+
+	tree = AllocTree ();
+
+	count = 0;
+	for( face = list; face != NULL; face = face->next )
+	{
+		count++;
+		for( i = 0; i < face->w->numpoints; i++ )
+		{
+			AddPointToBounds( face->w->p[ i ], tree->mins, tree->maxs );
+		}
+	}
+	Sys_FPrintf( SYS_VRB, "%9d faces\n", count );
+
+	tree->headnode = AllocNode();
+	VectorCopy( tree->mins, tree->headnode->mins );
+	VectorCopy( tree->maxs, tree->headnode->maxs );
+	c_faceLeafs = 0;
+
+	BuildFaceTree_r ( tree->headnode, list );
+
+	Sys_FPrintf( SYS_VRB, "%9d leafs\n", c_faceLeafs );
+
+	return tree;
+}
+
+
+
+/*
+MakeStructuralBSPFaceList()
+get structural brush faces
+*/
+
+face_t *MakeStructuralBSPFaceList( brush_t *list )
+{
+	brush_t		*b;
+	int			i;
+	side_t		*s;
+	winding_t	*w;
+	face_t		*f, *flist;
+	
+	
+	flist = NULL;
+	for( b = list; b != NULL; b = b->next )
+	{
+		if( b->detail )
+			continue;
+		
+		for( i = 0; i < b->numsides; i++ )
+		{
+			/* get side and winding */
+			s = &b->sides[ i ];
+			w = s->winding;
+			if( w == NULL )
+				continue;
+			
+			/* ydnar: skip certain faces */
+			if( s->compileFlags & C_SKIP )
+				continue;
+			
+			/* allocate a face */
+			f = AllocBspFace();
+			f->w = CopyWinding( w );
+			f->planenum = s->planenum & ~1;
+			f->compileFlags = s->compileFlags;	/* ydnar */
+			
+			/* ydnar: set priority */
+			f->priority = 0;
+			if( f->compileFlags & C_HINT )
+				f->priority += HINT_PRIORITY;
+			if( f->compileFlags & C_ANTIPORTAL )
+				f->priority += ANTIPORTAL_PRIORITY;
+			if( f->compileFlags & C_AREAPORTAL )
+				f->priority += AREAPORTAL_PRIORITY;
+			
+			/* get next face */
+			f->next = flist;
+			flist = f;
+		}
+	}
+	
+	return flist;
+}
+
+
+
+/*
+MakeVisibleBSPFaceList()
+get visible brush faces
+*/
+
+face_t *MakeVisibleBSPFaceList( brush_t *list )
+{
+	brush_t		*b;
+	int			i;
+	side_t		*s;
+	winding_t	*w;
+	face_t		*f, *flist;
+	
+	
+	flist = NULL;
+	for( b = list; b != NULL; b = b->next )
+	{
+		if( b->detail )
+			continue;
+		
+		for( i = 0; i < b->numsides; i++ )
+		{
+			/* get side and winding */
+			s = &b->sides[ i ];
+			w = s->visibleHull;
+			if( w == NULL )
+				continue;
+			
+			/* ydnar: skip certain faces */
+			if( s->compileFlags & C_SKIP )
+				continue;
+			
+			/* allocate a face */
+			f = AllocBspFace();
+			f->w = CopyWinding( w );
+			f->planenum = s->planenum & ~1;
+			f->compileFlags = s->compileFlags;	/* ydnar */
+			
+			/* ydnar: set priority */
+			f->priority = 0;
+			if( f->compileFlags & C_HINT )
+				f->priority += HINT_PRIORITY;
+			if( f->compileFlags & C_ANTIPORTAL )
+				f->priority += ANTIPORTAL_PRIORITY;
+			if( f->compileFlags & C_AREAPORTAL )
+				f->priority += AREAPORTAL_PRIORITY;
+			
+			/* get next face */
+			f->next = flist;
+			flist = f;
+		}
+	}
+	
+	return flist;
+}
+
diff --git a/tools/quake3/q3map2/fog.c b/tools/quake3/q3map2/fog.c
index 70348099..0cfdc924 100644
--- a/tools/quake3/q3map2/fog.c
+++ b/tools/quake3/q3map2/fog.c
@@ -1,804 +1,804 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define FOG_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-int			numFogFragments;
-int			numFogPatchFragments;
-
-
-
-/*
-DrawSurfToMesh()
-converts a patch drawsurface to a mesh_t
-*/
-
-mesh_t *DrawSurfToMesh( mapDrawSurface_t *ds )
-{
-	mesh_t		*m;
-	
-	
-	m = safe_malloc( sizeof( *m ) );
-	m->width = ds->patchWidth;
-	m->height = ds->patchHeight;
-	m->verts = safe_malloc( sizeof(m->verts[ 0 ]) * m->width * m->height );
-	memcpy( m->verts, ds->verts, sizeof(m->verts[ 0 ]) * m->width * m->height );
-	
-	return m;
-}
-
-
-
-/*
-SplitMeshByPlane()
-chops a mesh by a plane
-*/
-
-void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back )
-{
-	int		w, h, split;
-	float	d[MAX_PATCH_SIZE][MAX_PATCH_SIZE];
-	bspDrawVert_t	*dv, *v1, *v2;
-	int		c_front, c_back, c_on;
-	mesh_t	*f, *b;
-	int		i;
-	float	frac;
-	int		frontAprox, backAprox;
-
-	for ( i = 0 ; i < 2 ; i++ ) {
-		dv = in->verts;
-		c_front = 0;
-		c_back = 0;
-		c_on = 0;
-		for ( h = 0 ; h < in->height ; h++ ) {
-			for ( w = 0 ; w < in->width ; w++, dv++ ) {
-				d[h][w] = DotProduct( dv->xyz, normal ) - dist;
-				if ( d[h][w] > ON_EPSILON ) {
-					c_front++;
-				} else if ( d[h][w] < -ON_EPSILON ) {
-					c_back++;
-				} else {
-					c_on++;
-				}
-			}
-		}
-
-		*front = NULL;
-		*back = NULL;
-
-		if ( !c_front ) {
-			*back = in;
-			return;
-		}
-		if ( !c_back ) {
-			*front = in;
-			return;
-		}
-
-		// find a split point
-		split = -1;
-		for ( w = 0 ; w < in->width -1 ; w++ ) {
-			if ( ( d[0][w] < 0 ) != ( d[0][w+1] < 0 ) ) {
-				if ( split == -1 ) {
-					split = w;
-					break;
-				}
-			}
-		}
-
-		if ( split == -1 ) {
-			if ( i == 1 ) {
-				Sys_FPrintf (SYS_VRB, "No crossing points in patch\n");
-				*front = in;
-				return;
-			}
-
-			in = TransposeMesh( in );
-			InvertMesh( in );
-			continue;
-		}
-
-		// make sure the split point stays the same for all other rows
-		for ( h = 1 ; h < in->height ; h++ ) {
-			for ( w = 0 ; w < in->width -1 ; w++ ) {
-				if ( ( d[h][w] < 0 ) != ( d[h][w+1] < 0 ) ) {
-					if ( w != split ) {
-						Sys_Printf( "multiple crossing points for patch -- can't clip\n");
-						*front = in;
-						return;
-					}
-				}
-			}
-			if ( ( d[h][split] < 0 ) == ( d[h][split+1] < 0 ) ) {
-				Sys_Printf( "differing crossing points for patch -- can't clip\n");
-				*front = in;
-				return;
-			}
-		}
-
-		break;
-	}
-
-
-	// create two new meshes
-	f = safe_malloc( sizeof( *f ) );
-	f->width = split + 2;
-	if ( ! (f->width & 1) ) {
-		f->width++;
-		frontAprox = 1;
-	} else {
-		frontAprox = 0;
-	}
-	if ( f->width > MAX_PATCH_SIZE ) {
-		Error( "MAX_PATCH_SIZE after split");
-	}
-	f->height = in->height;
-	f->verts = safe_malloc( sizeof(f->verts[0]) * f->width * f->height );
-
-	b = safe_malloc( sizeof( *b ) );
-	b->width = in->width - split;
-	if ( ! (b->width & 1) ) {
-		b->width++;
-		backAprox = 1;
-	} else {
-		backAprox = 0;
-	}
-	if ( b->width > MAX_PATCH_SIZE ) {
-		Error( "MAX_PATCH_SIZE after split");
-	}
-	b->height = in->height;
-	b->verts = safe_malloc( sizeof(b->verts[0]) * b->width * b->height );
-
-	if ( d[0][0] > 0 ) {
-		*front = f;
-		*back = b;
-	} else {
-		*front = b;
-		*back = f;
-	}
-
-	// distribute the points
-	for ( w = 0 ; w < in->width ; w++ ) {
-		for ( h = 0 ; h < in->height ; h++ ) {
-			if ( w <= split ) {
-				f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ];
-			} else {
-				b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ];
-			}
-		}
-	}
-
-	// clip the crossing line
-	for ( h = 0; h < in->height; h++ )
-	{
-		dv = &f->verts[ h * f->width + split + 1 ];
-		v1 = &in->verts[ h * in->width + split ];
-		v2 = &in->verts[ h * in->width + split + 1 ];
-
-		frac = d[h][split] / ( d[h][split] - d[h][split+1] );
-		
-		/* interpolate */
-		//%	for( i = 0; i < 10; i++ )
-		//%		dv->xyz[ i ] = v1->xyz[ i ] + frac * (v2->xyz[ i ] - v1->xyz[ i ]);
-		//%	dv->xyz[10] = 0;	// set all 4 colors to 0 
-		LerpDrawVertAmount( v1, v2, frac, dv );
-		
-		if ( frontAprox ) {
-			f->verts[ h * f->width + split + 2 ] = *dv;
-		}
-		b->verts[ h * b->width ] = *dv;
-		if ( backAprox ) {
-			b->verts[ h * b->width + 1 ] = *dv;
-		}
-	}
-
-	/*
-PrintMesh( in );
-Sys_Printf("\n");
-PrintMesh( f );
-Sys_Printf("\n");
-PrintMesh( b );
-Sys_Printf("\n");
-	*/
-
-	FreeMesh( in );
-}
-
-
-/*
-ChopPatchSurfaceByBrush()
-chops a patch up by a fog brush
-*/
-
-qboolean ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b )
-{
-	int			i, j;
-	side_t		*s;
-	plane_t		*plane;
-	mesh_t		*outside[MAX_BRUSH_SIDES];
-	int			numOutside;
-	mesh_t		*m, *front, *back;
-	mapDrawSurface_t	*newds;
-
-	m = DrawSurfToMesh( ds );
-	numOutside = 0;
-	
-	// only split by the top and bottom planes to avoid
-	// some messy patch clipping issues
-	
-	for ( i = 4 ; i <= 5 ; i++ ) {
-		s = &b->sides[ i ];
-		plane = &mapplanes[ s->planenum ];
-
-		SplitMeshByPlane( m, plane->normal, plane->dist, &front, &back );
-
-		if ( !back ) {
-			// nothing actually contained inside
-			for ( j = 0 ; j < numOutside ; j++ ) {
-				FreeMesh( outside[j] );
-			}
-			return qfalse;
-		}
-		m = back;
-
-		if ( front ) {
-			if ( numOutside == MAX_BRUSH_SIDES ) {
-				Error( "MAX_BRUSH_SIDES" );
-			}
-			outside[ numOutside ] = front;
-			numOutside++;
-		}
-	}
-
-	/* all of outside fragments become seperate drawsurfs */
-	numFogPatchFragments += numOutside;
-	for( i = 0; i < numOutside; i++ )
-	{
-		/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
-		outside[ i ] = TransposeMesh( outside[ i ] );
-		InvertMesh( outside[ i ] );
-		
-		/* ydnar: do this the hacky right way */
-		newds = AllocDrawSurface( SURFACE_PATCH );
-		memcpy( newds, ds, sizeof( *ds ) );
-		newds->patchWidth = outside[ i ]->width;
-		newds->patchHeight = outside[ i ]->height;
-		newds->numVerts = outside[ i ]->width * outside[ i ]->height;
-		newds->verts = safe_malloc( newds->numVerts * sizeof( *newds->verts ) );
-		memcpy( newds->verts, outside[ i ]->verts, newds->numVerts * sizeof( *newds->verts ) );
-		
-		/* free the source mesh */
-		FreeMesh( outside[ i ] );
-	}
-	
-	/* only rejigger this patch if it was chopped */
-	//%	Sys_Printf( "Inside: %d x %d\n", m->width, m->height );
-	if( numOutside > 0 )
-	{
-		/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
-		m = TransposeMesh( m );
-		InvertMesh( m );
-		
-		/* replace ds with m */
-		ds->patchWidth = m->width;
-		ds->patchHeight = m->height;
-		ds->numVerts = m->width * m->height;
-		free( ds->verts );
-		ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-		memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
-	}
-	
-	/* free the source mesh and return */
-	FreeMesh( m );
-	return qtrue;
-}
-
-
-
-/*
-WindingFromDrawSurf()
-creates a winding from a surface's verts
-*/
-
-winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds )
-{
-	winding_t	*w;
-	int			i;
-
-	// we use the first point of the surface, maybe something more clever would be useful
-	// (actually send the whole draw surface would be cool?)
-	if( ds->numVerts >= MAX_POINTS_ON_WINDING )
-	{
-		int max = ds->numVerts;
-		vec3_t p[256];
-
-		if(max > 256)
-			max = 256;
-
-		for ( i = 0 ; i < max ; i++ ) {
-			VectorCopy( ds->verts[i].xyz, p[i] );
-		}
-
-		xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, qtrue );
-	}
-
-	w = AllocWinding( ds->numVerts );
-	w->numpoints = ds->numVerts;
-	for ( i = 0 ; i < ds->numVerts ; i++ ) {
-		VectorCopy( ds->verts[i].xyz, w->p[i] );
-	}
-	return w;
-}
-
-
-
-/*
-ChopFaceSurfaceByBrush()
-chops up a face drawsurface by a fog brush, with a potential fragment left inside
-*/
-
-qboolean ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b )
-{
-	int					i, j;
-	side_t				*s;
-	plane_t				*plane;
-	winding_t			*w;
-	winding_t			*front, *back;
-	winding_t			*outside[ MAX_BRUSH_SIDES ];
-	int					numOutside;
-	mapDrawSurface_t	*newds;
-	
-	
-	/* dummy check */
-	if( ds->sideRef == NULL || ds->sideRef->side == NULL )
-		return qfalse;
-	
-	/* initial setup */
-	w = WindingFromDrawSurf( ds );
-	numOutside = 0;
-	
-	/* chop by each brush side */
-	for( i = 0; i < b->numsides; i++ )
-	{
-		/* get brush side and plane */
-		s = &b->sides[ i ];
-		if( s->backSide )
-			continue;
-		plane = &mapplanes[ s->planenum ];
-		
-		/* handle coplanar outfacing (don't fog) */
-		if( ds->sideRef->side->planenum == s->planenum )
-			return qfalse;
-		
-		/* handle coplanar infacing (keep inside) */
-		if( (ds->sideRef->side->planenum ^ 1) == s->planenum )
-			continue;
-		
-		/* general case */
-		ClipWindingEpsilon( w, plane->normal, plane->dist, ON_EPSILON, &front, &back );
-		FreeWinding( w );
-		
-		if( back == NULL )
-		{
-			/* nothing actually contained inside */
-			for( j = 0; j < numOutside; j++ )
-				FreeWinding( outside[ j ] );
-			return qfalse;
-		}
-		
-		if( front != NULL )
-		{
-			if( numOutside == MAX_BRUSH_SIDES )
-				Error( "MAX_BRUSH_SIDES" );
-			outside[ numOutside ] = front;
-			numOutside++;
-		}
-		
-		w = back;
-	}
-	
-	/* fixme: celshaded surface fragment errata */
-	
-	/* all of outside fragments become seperate drawsurfs */
-	numFogFragments += numOutside;
-	s = ds->sideRef->side;
-	for( i = 0; i < numOutside; i++ )
-	{
-		newds = DrawSurfaceForSide( e, ds->mapBrush, s, outside[ i ] );
-		newds->fogNum = ds->fogNum;
-		FreeWinding( outside[ i ] );
-	}
-	
-	/* ydnar: the old code neglected to snap to 0.125 for the fragment
-	          inside the fog brush, leading to sparklies. this new code does
-			  the right thing and uses the original surface's brush side */
-	
-	/* build a drawsurf for it */
-	newds = DrawSurfaceForSide( e, ds->mapBrush, s, w );
-	if( newds == NULL )
-		return qfalse;
-	
-	/* copy new to original */
-	ClearSurface( ds );
-	memcpy( ds, newds, sizeof( mapDrawSurface_t ) );
-	
-	/* didn't really add a new drawsurface... :) */
-	numMapDrawSurfs--;
-	
-	/* return ok */
-	return qtrue;
-}
-
-
-
-/*
-FogDrawSurfaces()
-call after the surface list has been pruned, before tjunction fixing
-*/
-
-void FogDrawSurfaces( entity_t *e )
-{
-	int					i, j, k, fogNum;
-	fog_t				*fog;
-	mapDrawSurface_t	*ds;
-	vec3_t				mins, maxs;
-	int					fogged, numFogged;
-	int					numBaseDrawSurfs;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "----- FogDrawSurfs -----\n" );
-	
-	/* reset counters */
-	numFogged = 0;
-	numFogFragments = 0;
-	
-	/* walk fog list */
-	for( fogNum = 0; fogNum < numMapFogs; fogNum++ )
-	{
-		/* get fog */
-		fog = &mapFogs[ fogNum ];
-		
-		/* clip each surface into this, but don't clip any of the resulting fragments to the same brush */
-		numBaseDrawSurfs = numMapDrawSurfs;
-		for( i = 0; i < numBaseDrawSurfs; i++ )
-		{
-			/* get the drawsurface */
-			ds = &mapDrawSurfs[ i ];
-			
-			/* no fog? */
-			if( ds->shaderInfo->noFog )
-				continue;
-			
-			/* global fog doesn't have a brush */
-			if( fog->brush == NULL )
-			{
-				/* don't re-fog already fogged surfaces */
-				if( ds->fogNum >= 0 )
-					continue;
-				fogged = 1;
-			}
-			else
-			{
-				/* find drawsurface bounds */
-				ClearBounds( mins, maxs );
-				for( j = 0; j < ds->numVerts; j++ )
-					AddPointToBounds( ds->verts[ j ].xyz, mins, maxs );
-
-				/* check against the fog brush */
-				for( k = 0; k < 3; k++ )
-				{
-					if( mins[ k ] > fog->brush->maxs[ k ] )
-						break;
-					if( maxs[ k ] < fog->brush->mins[ k ] )
-						break;
-				}
-				
-				/* no intersection? */
-				if( k < 3 )
-					continue;
-				
-				/* ydnar: gs mods: handle the various types of surfaces */
-				switch( ds->type )
-				{
-					/* handle brush faces */
-					case SURFACE_FACE:
-						fogged = ChopFaceSurfaceByBrush( e, ds, fog->brush );
-						break;
-					
-					/* handle patches */
-					case SURFACE_PATCH:
-						fogged = ChopPatchSurfaceByBrush( e, ds, fog->brush );
-						break;
-					
-					/* handle triangle surfaces (fixme: split triangle surfaces) */
-					case SURFACE_TRIANGLES:
-					case SURFACE_FORCED_META:
-					case SURFACE_META:
-						fogged = 1;
-						break;
-
-					/* no fogging */
-					default:
-						fogged = 0;
-						break;
-				}
-			}
-			
-			/* is this surface fogged? */
-			if( fogged )
-			{
-				numFogged += fogged;
-				ds->fogNum = fogNum;
-			}
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d fog polygon fragments\n", numFogFragments );
-	Sys_FPrintf( SYS_VRB, "%9d fog patch fragments\n", numFogPatchFragments );
-	Sys_FPrintf( SYS_VRB, "%9d fogged drawsurfs\n", numFogged );
-}
-
-
-
-/*
-FogForPoint() - ydnar
-gets the fog number for a point in space
-*/
-
-int FogForPoint( vec3_t point, float epsilon )
-{
-	int				fogNum, i, j;
-	float			dot;
-	qboolean		inside;
-	brush_t			*brush;
-	plane_t			*plane;
-	
-	
-	/* start with bogus fog num */
-	fogNum = defaultFogNum;
-	
-	/* walk the list of fog volumes */
-	for( i = 0; i < numMapFogs; i++ )
-	{
-		/* sof2: global fog doesn't reference a brush */
-		if( mapFogs[ i ].brush == NULL )
-		{
-			fogNum = i;
-			continue;
-		}
-		
-		/* get fog brush */
-		brush = mapFogs[ i ].brush;
-		
-		/* check point against all planes */
-		inside = qtrue;
-		for( j = 0; j < brush->numsides && inside; j++ )
-		{
-			plane = &mapplanes[ brush->sides[ j ].planenum ];	/* note usage of map planes here */
-			dot = DotProduct( point, plane->normal );
-			dot -= plane->dist;
-			if( dot > epsilon )
-				inside = qfalse;
-		}
-		
-		/* if inside, return the fog num */
-		if( inside )
-		{
-			//%	Sys_Printf( "FogForPoint: %f, %f, %f in fog %d\n", point[ 0 ], point[ 1 ], point[ 2 ], i );
-			return i;
-		}
-	}
-	
-	/* if the point made it this far, it's not inside any fog volumes (or inside global fog) */
-	return fogNum;
-}
-
-
-
-/*
-FogForBounds() - ydnar
-gets the fog number for a bounding box
-*/
-
-int FogForBounds( vec3_t mins, vec3_t maxs, float epsilon )
-{
-	int				fogNum, i, j;
-	float			highMin, lowMax, volume, bestVolume;
-	vec3_t			fogMins, fogMaxs, overlap;
-	brush_t			*brush;
-	
-	
-	/* start with bogus fog num */
-	fogNum = defaultFogNum;
-	
-	/* init */
-	bestVolume = 0.0f;
-	
-	/* walk the list of fog volumes */
-	for( i = 0; i < numMapFogs; i++ )
-	{
-		/* sof2: global fog doesn't reference a brush */
-		if( mapFogs[ i ].brush == NULL )
-		{
-			fogNum = i;
-			continue;
-		}
-		
-		/* get fog brush */
-		brush = mapFogs[ i ].brush;
-		
-		/* get bounds */
-		fogMins[ 0 ] = brush->mins[ 0 ] - epsilon;
-		fogMins[ 1 ] = brush->mins[ 1 ] - epsilon;
-		fogMins[ 2 ] = brush->mins[ 2 ] - epsilon;
-		fogMaxs[ 0 ] = brush->maxs[ 0 ] + epsilon;
-		fogMaxs[ 1 ] = brush->maxs[ 1 ] + epsilon;
-		fogMaxs[ 2 ] = brush->maxs[ 2 ] + epsilon;
-		
-		/* check against bounds */
-		for( j = 0; j < 3; j++ )
-		{
-			if( mins[ j ] > fogMaxs[ j ] || maxs[ j ] < fogMins[ j ] )
-				break;
-			highMin = mins[ j ] > fogMins[ j ] ? mins[ j ] : fogMins[ j ];
-			lowMax = maxs[ j ] < fogMaxs[ j ] ? maxs[ j ] : fogMaxs[ j ];
-			overlap[ j ] = lowMax - highMin;
-			if( overlap[ j ] < 1.0f )
-				overlap[ j ] = 1.0f;
-		}
-		
-		/* no overlap */
-		if( j < 3 )
-			continue;
-		
-		/* get volume */
-		volume = overlap[ 0 ] * overlap[ 1 ] * overlap[ 2 ];
-		
-		/* test against best volume */
-		if( volume > bestVolume )
-		{
-			bestVolume = volume;
-			fogNum = i;
-		}
-	}
-	
-	/* if the point made it this far, it's not inside any fog volumes (or inside global fog) */
-	return fogNum;
-}
-
-
-
-/*
-CreateMapFogs() - ydnar
-generates a list of map fogs
-*/
-
-void CreateMapFogs( void )
-{
-	int			i;
-	entity_t	*entity;
-	brush_t		*brush;
-	fog_t		*fog;
-	vec3_t		invFogDir;
-	const char	*globalFog;
-	
-	
-	/* skip? */
-	if( nofog )
-		return;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- CreateMapFogs ---\n" );
-	
-	/* walk entities */
-	for( i = 0; i < numEntities; i++ )
-	{
-		/* get entity */
-		entity = &entities[ i ];
-		
-		/* walk entity brushes */
-		for( brush = entity->brushes; brush != NULL; brush = brush->next )
-		{
-			/* ignore non-fog brushes */
-			if( brush->contentShader->fogParms == qfalse )
-				continue;
-			
-			/* test limit */
-			if( numMapFogs >= MAX_MAP_FOGS )
-				Error( "Exceeded MAX_MAP_FOGS (%d)", MAX_MAP_FOGS );
-			
-			/* set up fog */
-			fog = &mapFogs[ numMapFogs++ ];
-			fog->si = brush->contentShader;
-			fog->brush = brush;
-			fog->visibleSide = -1;
-			
-			/* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */
-			if( VectorLength( fog->si->fogDir ) )
-			{
-				/* flip it */
-				VectorScale( fog->si->fogDir, -1.0f, invFogDir );
-				
-				/* find the brush side */
-				for( i = 0; i < brush->numsides; i++ )
-				{
-					if( VectorCompare( invFogDir, mapplanes[ brush->sides[ i ].planenum ].normal ) )
-					{
-						fog->visibleSide = i;
-						//%	Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide );
-						break;
-					}
-				}
-			}
-		}
-	}
-	
-	/* ydnar: global fog */
-	globalFog = ValueForKey( &entities[ 0 ], "_fog" );
-	if( globalFog[ 0 ] == '\0' )
-		globalFog = ValueForKey( &entities[ 0 ], "fog" );
-	if( globalFog[ 0 ] != '\0' )
-	{
-		/* test limit */
-		if( numMapFogs >= MAX_MAP_FOGS )
-			Error( "Exceeded MAX_MAP_FOGS (%d) trying to add global fog", MAX_MAP_FOGS );
-		
-		/* note it */
-		Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog );
-		
-		/* set up fog */
-		fog = &mapFogs[ numMapFogs++ ];
-		fog->si = ShaderInfoForShader( globalFog );
-		if( fog->si == NULL )
-			Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog );
-		fog->brush = NULL;
-		fog->visibleSide = -1;
-		
-		/* set as default fog */
-		defaultFogNum = numMapFogs - 1;
-		
-		/* mark all worldspawn brushes as fogged */
-		for( brush = entities[ 0 ].brushes; brush != NULL; brush = brush->next )
-			ApplySurfaceParm( "fog", &brush->contentFlags, NULL, &brush->compileFlags );
-	}
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d fogs\n", numMapFogs );
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define FOG_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+int			numFogFragments;
+int			numFogPatchFragments;
+
+
+
+/*
+DrawSurfToMesh()
+converts a patch drawsurface to a mesh_t
+*/
+
+mesh_t *DrawSurfToMesh( mapDrawSurface_t *ds )
+{
+	mesh_t		*m;
+	
+	
+	m = safe_malloc( sizeof( *m ) );
+	m->width = ds->patchWidth;
+	m->height = ds->patchHeight;
+	m->verts = safe_malloc( sizeof(m->verts[ 0 ]) * m->width * m->height );
+	memcpy( m->verts, ds->verts, sizeof(m->verts[ 0 ]) * m->width * m->height );
+	
+	return m;
+}
+
+
+
+/*
+SplitMeshByPlane()
+chops a mesh by a plane
+*/
+
+void SplitMeshByPlane( mesh_t *in, vec3_t normal, float dist, mesh_t **front, mesh_t **back )
+{
+	int		w, h, split;
+	float	d[MAX_PATCH_SIZE][MAX_PATCH_SIZE];
+	bspDrawVert_t	*dv, *v1, *v2;
+	int		c_front, c_back, c_on;
+	mesh_t	*f, *b;
+	int		i;
+	float	frac;
+	int		frontAprox, backAprox;
+
+	for ( i = 0 ; i < 2 ; i++ ) {
+		dv = in->verts;
+		c_front = 0;
+		c_back = 0;
+		c_on = 0;
+		for ( h = 0 ; h < in->height ; h++ ) {
+			for ( w = 0 ; w < in->width ; w++, dv++ ) {
+				d[h][w] = DotProduct( dv->xyz, normal ) - dist;
+				if ( d[h][w] > ON_EPSILON ) {
+					c_front++;
+				} else if ( d[h][w] < -ON_EPSILON ) {
+					c_back++;
+				} else {
+					c_on++;
+				}
+			}
+		}
+
+		*front = NULL;
+		*back = NULL;
+
+		if ( !c_front ) {
+			*back = in;
+			return;
+		}
+		if ( !c_back ) {
+			*front = in;
+			return;
+		}
+
+		// find a split point
+		split = -1;
+		for ( w = 0 ; w < in->width -1 ; w++ ) {
+			if ( ( d[0][w] < 0 ) != ( d[0][w+1] < 0 ) ) {
+				if ( split == -1 ) {
+					split = w;
+					break;
+				}
+			}
+		}
+
+		if ( split == -1 ) {
+			if ( i == 1 ) {
+				Sys_FPrintf (SYS_VRB, "No crossing points in patch\n");
+				*front = in;
+				return;
+			}
+
+			in = TransposeMesh( in );
+			InvertMesh( in );
+			continue;
+		}
+
+		// make sure the split point stays the same for all other rows
+		for ( h = 1 ; h < in->height ; h++ ) {
+			for ( w = 0 ; w < in->width -1 ; w++ ) {
+				if ( ( d[h][w] < 0 ) != ( d[h][w+1] < 0 ) ) {
+					if ( w != split ) {
+						Sys_Printf( "multiple crossing points for patch -- can't clip\n");
+						*front = in;
+						return;
+					}
+				}
+			}
+			if ( ( d[h][split] < 0 ) == ( d[h][split+1] < 0 ) ) {
+				Sys_Printf( "differing crossing points for patch -- can't clip\n");
+				*front = in;
+				return;
+			}
+		}
+
+		break;
+	}
+
+
+	// create two new meshes
+	f = safe_malloc( sizeof( *f ) );
+	f->width = split + 2;
+	if ( ! (f->width & 1) ) {
+		f->width++;
+		frontAprox = 1;
+	} else {
+		frontAprox = 0;
+	}
+	if ( f->width > MAX_PATCH_SIZE ) {
+		Error( "MAX_PATCH_SIZE after split");
+	}
+	f->height = in->height;
+	f->verts = safe_malloc( sizeof(f->verts[0]) * f->width * f->height );
+
+	b = safe_malloc( sizeof( *b ) );
+	b->width = in->width - split;
+	if ( ! (b->width & 1) ) {
+		b->width++;
+		backAprox = 1;
+	} else {
+		backAprox = 0;
+	}
+	if ( b->width > MAX_PATCH_SIZE ) {
+		Error( "MAX_PATCH_SIZE after split");
+	}
+	b->height = in->height;
+	b->verts = safe_malloc( sizeof(b->verts[0]) * b->width * b->height );
+
+	if ( d[0][0] > 0 ) {
+		*front = f;
+		*back = b;
+	} else {
+		*front = b;
+		*back = f;
+	}
+
+	// distribute the points
+	for ( w = 0 ; w < in->width ; w++ ) {
+		for ( h = 0 ; h < in->height ; h++ ) {
+			if ( w <= split ) {
+				f->verts[ h * f->width + w ] = in->verts[ h * in->width + w ];
+			} else {
+				b->verts[ h * b->width + w - split + backAprox ] = in->verts[ h * in->width + w ];
+			}
+		}
+	}
+
+	// clip the crossing line
+	for ( h = 0; h < in->height; h++ )
+	{
+		dv = &f->verts[ h * f->width + split + 1 ];
+		v1 = &in->verts[ h * in->width + split ];
+		v2 = &in->verts[ h * in->width + split + 1 ];
+
+		frac = d[h][split] / ( d[h][split] - d[h][split+1] );
+		
+		/* interpolate */
+		//%	for( i = 0; i < 10; i++ )
+		//%		dv->xyz[ i ] = v1->xyz[ i ] + frac * (v2->xyz[ i ] - v1->xyz[ i ]);
+		//%	dv->xyz[10] = 0;	// set all 4 colors to 0 
+		LerpDrawVertAmount( v1, v2, frac, dv );
+		
+		if ( frontAprox ) {
+			f->verts[ h * f->width + split + 2 ] = *dv;
+		}
+		b->verts[ h * b->width ] = *dv;
+		if ( backAprox ) {
+			b->verts[ h * b->width + 1 ] = *dv;
+		}
+	}
+
+	/*
+PrintMesh( in );
+Sys_Printf("\n");
+PrintMesh( f );
+Sys_Printf("\n");
+PrintMesh( b );
+Sys_Printf("\n");
+	*/
+
+	FreeMesh( in );
+}
+
+
+/*
+ChopPatchSurfaceByBrush()
+chops a patch up by a fog brush
+*/
+
+qboolean ChopPatchSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b )
+{
+	int			i, j;
+	side_t		*s;
+	plane_t		*plane;
+	mesh_t		*outside[MAX_BRUSH_SIDES];
+	int			numOutside;
+	mesh_t		*m, *front, *back;
+	mapDrawSurface_t	*newds;
+
+	m = DrawSurfToMesh( ds );
+	numOutside = 0;
+	
+	// only split by the top and bottom planes to avoid
+	// some messy patch clipping issues
+	
+	for ( i = 4 ; i <= 5 ; i++ ) {
+		s = &b->sides[ i ];
+		plane = &mapplanes[ s->planenum ];
+
+		SplitMeshByPlane( m, plane->normal, plane->dist, &front, &back );
+
+		if ( !back ) {
+			// nothing actually contained inside
+			for ( j = 0 ; j < numOutside ; j++ ) {
+				FreeMesh( outside[j] );
+			}
+			return qfalse;
+		}
+		m = back;
+
+		if ( front ) {
+			if ( numOutside == MAX_BRUSH_SIDES ) {
+				Error( "MAX_BRUSH_SIDES" );
+			}
+			outside[ numOutside ] = front;
+			numOutside++;
+		}
+	}
+
+	/* all of outside fragments become seperate drawsurfs */
+	numFogPatchFragments += numOutside;
+	for( i = 0; i < numOutside; i++ )
+	{
+		/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
+		outside[ i ] = TransposeMesh( outside[ i ] );
+		InvertMesh( outside[ i ] );
+		
+		/* ydnar: do this the hacky right way */
+		newds = AllocDrawSurface( SURFACE_PATCH );
+		memcpy( newds, ds, sizeof( *ds ) );
+		newds->patchWidth = outside[ i ]->width;
+		newds->patchHeight = outside[ i ]->height;
+		newds->numVerts = outside[ i ]->width * outside[ i ]->height;
+		newds->verts = safe_malloc( newds->numVerts * sizeof( *newds->verts ) );
+		memcpy( newds->verts, outside[ i ]->verts, newds->numVerts * sizeof( *newds->verts ) );
+		
+		/* free the source mesh */
+		FreeMesh( outside[ i ] );
+	}
+	
+	/* only rejigger this patch if it was chopped */
+	//%	Sys_Printf( "Inside: %d x %d\n", m->width, m->height );
+	if( numOutside > 0 )
+	{
+		/* transpose and invert the chopped patch (fixes potential crash. fixme: why?) */
+		m = TransposeMesh( m );
+		InvertMesh( m );
+		
+		/* replace ds with m */
+		ds->patchWidth = m->width;
+		ds->patchHeight = m->height;
+		ds->numVerts = m->width * m->height;
+		free( ds->verts );
+		ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
+		memcpy( ds->verts, m->verts, ds->numVerts * sizeof( *ds->verts ) );
+	}
+	
+	/* free the source mesh and return */
+	FreeMesh( m );
+	return qtrue;
+}
+
+
+
+/*
+WindingFromDrawSurf()
+creates a winding from a surface's verts
+*/
+
+winding_t *WindingFromDrawSurf( mapDrawSurface_t *ds )
+{
+	winding_t	*w;
+	int			i;
+
+	// we use the first point of the surface, maybe something more clever would be useful
+	// (actually send the whole draw surface would be cool?)
+	if( ds->numVerts >= MAX_POINTS_ON_WINDING )
+	{
+		int max = ds->numVerts;
+		vec3_t p[256];
+
+		if(max > 256)
+			max = 256;
+
+		for ( i = 0 ; i < max ; i++ ) {
+			VectorCopy( ds->verts[i].xyz, p[i] );
+		}
+
+		xml_Winding( "WindingFromDrawSurf failed: MAX_POINTS_ON_WINDING exceeded", p, max, qtrue );
+	}
+
+	w = AllocWinding( ds->numVerts );
+	w->numpoints = ds->numVerts;
+	for ( i = 0 ; i < ds->numVerts ; i++ ) {
+		VectorCopy( ds->verts[i].xyz, w->p[i] );
+	}
+	return w;
+}
+
+
+
+/*
+ChopFaceSurfaceByBrush()
+chops up a face drawsurface by a fog brush, with a potential fragment left inside
+*/
+
+qboolean ChopFaceSurfaceByBrush( entity_t *e, mapDrawSurface_t *ds, brush_t *b )
+{
+	int					i, j;
+	side_t				*s;
+	plane_t				*plane;
+	winding_t			*w;
+	winding_t			*front, *back;
+	winding_t			*outside[ MAX_BRUSH_SIDES ];
+	int					numOutside;
+	mapDrawSurface_t	*newds;
+	
+	
+	/* dummy check */
+	if( ds->sideRef == NULL || ds->sideRef->side == NULL )
+		return qfalse;
+	
+	/* initial setup */
+	w = WindingFromDrawSurf( ds );
+	numOutside = 0;
+	
+	/* chop by each brush side */
+	for( i = 0; i < b->numsides; i++ )
+	{
+		/* get brush side and plane */
+		s = &b->sides[ i ];
+		if( s->backSide )
+			continue;
+		plane = &mapplanes[ s->planenum ];
+		
+		/* handle coplanar outfacing (don't fog) */
+		if( ds->sideRef->side->planenum == s->planenum )
+			return qfalse;
+		
+		/* handle coplanar infacing (keep inside) */
+		if( (ds->sideRef->side->planenum ^ 1) == s->planenum )
+			continue;
+		
+		/* general case */
+		ClipWindingEpsilon( w, plane->normal, plane->dist, ON_EPSILON, &front, &back );
+		FreeWinding( w );
+		
+		if( back == NULL )
+		{
+			/* nothing actually contained inside */
+			for( j = 0; j < numOutside; j++ )
+				FreeWinding( outside[ j ] );
+			return qfalse;
+		}
+		
+		if( front != NULL )
+		{
+			if( numOutside == MAX_BRUSH_SIDES )
+				Error( "MAX_BRUSH_SIDES" );
+			outside[ numOutside ] = front;
+			numOutside++;
+		}
+		
+		w = back;
+	}
+	
+	/* fixme: celshaded surface fragment errata */
+	
+	/* all of outside fragments become seperate drawsurfs */
+	numFogFragments += numOutside;
+	s = ds->sideRef->side;
+	for( i = 0; i < numOutside; i++ )
+	{
+		newds = DrawSurfaceForSide( e, ds->mapBrush, s, outside[ i ] );
+		newds->fogNum = ds->fogNum;
+		FreeWinding( outside[ i ] );
+	}
+	
+	/* ydnar: the old code neglected to snap to 0.125 for the fragment
+	          inside the fog brush, leading to sparklies. this new code does
+			  the right thing and uses the original surface's brush side */
+	
+	/* build a drawsurf for it */
+	newds = DrawSurfaceForSide( e, ds->mapBrush, s, w );
+	if( newds == NULL )
+		return qfalse;
+	
+	/* copy new to original */
+	ClearSurface( ds );
+	memcpy( ds, newds, sizeof( mapDrawSurface_t ) );
+	
+	/* didn't really add a new drawsurface... :) */
+	numMapDrawSurfs--;
+	
+	/* return ok */
+	return qtrue;
+}
+
+
+
+/*
+FogDrawSurfaces()
+call after the surface list has been pruned, before tjunction fixing
+*/
+
+void FogDrawSurfaces( entity_t *e )
+{
+	int					i, j, k, fogNum;
+	fog_t				*fog;
+	mapDrawSurface_t	*ds;
+	vec3_t				mins, maxs;
+	int					fogged, numFogged;
+	int					numBaseDrawSurfs;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "----- FogDrawSurfs -----\n" );
+	
+	/* reset counters */
+	numFogged = 0;
+	numFogFragments = 0;
+	
+	/* walk fog list */
+	for( fogNum = 0; fogNum < numMapFogs; fogNum++ )
+	{
+		/* get fog */
+		fog = &mapFogs[ fogNum ];
+		
+		/* clip each surface into this, but don't clip any of the resulting fragments to the same brush */
+		numBaseDrawSurfs = numMapDrawSurfs;
+		for( i = 0; i < numBaseDrawSurfs; i++ )
+		{
+			/* get the drawsurface */
+			ds = &mapDrawSurfs[ i ];
+			
+			/* no fog? */
+			if( ds->shaderInfo->noFog )
+				continue;
+			
+			/* global fog doesn't have a brush */
+			if( fog->brush == NULL )
+			{
+				/* don't re-fog already fogged surfaces */
+				if( ds->fogNum >= 0 )
+					continue;
+				fogged = 1;
+			}
+			else
+			{
+				/* find drawsurface bounds */
+				ClearBounds( mins, maxs );
+				for( j = 0; j < ds->numVerts; j++ )
+					AddPointToBounds( ds->verts[ j ].xyz, mins, maxs );
+
+				/* check against the fog brush */
+				for( k = 0; k < 3; k++ )
+				{
+					if( mins[ k ] > fog->brush->maxs[ k ] )
+						break;
+					if( maxs[ k ] < fog->brush->mins[ k ] )
+						break;
+				}
+				
+				/* no intersection? */
+				if( k < 3 )
+					continue;
+				
+				/* ydnar: gs mods: handle the various types of surfaces */
+				switch( ds->type )
+				{
+					/* handle brush faces */
+					case SURFACE_FACE:
+						fogged = ChopFaceSurfaceByBrush( e, ds, fog->brush );
+						break;
+					
+					/* handle patches */
+					case SURFACE_PATCH:
+						fogged = ChopPatchSurfaceByBrush( e, ds, fog->brush );
+						break;
+					
+					/* handle triangle surfaces (fixme: split triangle surfaces) */
+					case SURFACE_TRIANGLES:
+					case SURFACE_FORCED_META:
+					case SURFACE_META:
+						fogged = 1;
+						break;
+
+					/* no fogging */
+					default:
+						fogged = 0;
+						break;
+				}
+			}
+			
+			/* is this surface fogged? */
+			if( fogged )
+			{
+				numFogged += fogged;
+				ds->fogNum = fogNum;
+			}
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d fog polygon fragments\n", numFogFragments );
+	Sys_FPrintf( SYS_VRB, "%9d fog patch fragments\n", numFogPatchFragments );
+	Sys_FPrintf( SYS_VRB, "%9d fogged drawsurfs\n", numFogged );
+}
+
+
+
+/*
+FogForPoint() - ydnar
+gets the fog number for a point in space
+*/
+
+int FogForPoint( vec3_t point, float epsilon )
+{
+	int				fogNum, i, j;
+	float			dot;
+	qboolean		inside;
+	brush_t			*brush;
+	plane_t			*plane;
+	
+	
+	/* start with bogus fog num */
+	fogNum = defaultFogNum;
+	
+	/* walk the list of fog volumes */
+	for( i = 0; i < numMapFogs; i++ )
+	{
+		/* sof2: global fog doesn't reference a brush */
+		if( mapFogs[ i ].brush == NULL )
+		{
+			fogNum = i;
+			continue;
+		}
+		
+		/* get fog brush */
+		brush = mapFogs[ i ].brush;
+		
+		/* check point against all planes */
+		inside = qtrue;
+		for( j = 0; j < brush->numsides && inside; j++ )
+		{
+			plane = &mapplanes[ brush->sides[ j ].planenum ];	/* note usage of map planes here */
+			dot = DotProduct( point, plane->normal );
+			dot -= plane->dist;
+			if( dot > epsilon )
+				inside = qfalse;
+		}
+		
+		/* if inside, return the fog num */
+		if( inside )
+		{
+			//%	Sys_Printf( "FogForPoint: %f, %f, %f in fog %d\n", point[ 0 ], point[ 1 ], point[ 2 ], i );
+			return i;
+		}
+	}
+	
+	/* if the point made it this far, it's not inside any fog volumes (or inside global fog) */
+	return fogNum;
+}
+
+
+
+/*
+FogForBounds() - ydnar
+gets the fog number for a bounding box
+*/
+
+int FogForBounds( vec3_t mins, vec3_t maxs, float epsilon )
+{
+	int				fogNum, i, j;
+	float			highMin, lowMax, volume, bestVolume;
+	vec3_t			fogMins, fogMaxs, overlap;
+	brush_t			*brush;
+	
+	
+	/* start with bogus fog num */
+	fogNum = defaultFogNum;
+	
+	/* init */
+	bestVolume = 0.0f;
+	
+	/* walk the list of fog volumes */
+	for( i = 0; i < numMapFogs; i++ )
+	{
+		/* sof2: global fog doesn't reference a brush */
+		if( mapFogs[ i ].brush == NULL )
+		{
+			fogNum = i;
+			continue;
+		}
+		
+		/* get fog brush */
+		brush = mapFogs[ i ].brush;
+		
+		/* get bounds */
+		fogMins[ 0 ] = brush->mins[ 0 ] - epsilon;
+		fogMins[ 1 ] = brush->mins[ 1 ] - epsilon;
+		fogMins[ 2 ] = brush->mins[ 2 ] - epsilon;
+		fogMaxs[ 0 ] = brush->maxs[ 0 ] + epsilon;
+		fogMaxs[ 1 ] = brush->maxs[ 1 ] + epsilon;
+		fogMaxs[ 2 ] = brush->maxs[ 2 ] + epsilon;
+		
+		/* check against bounds */
+		for( j = 0; j < 3; j++ )
+		{
+			if( mins[ j ] > fogMaxs[ j ] || maxs[ j ] < fogMins[ j ] )
+				break;
+			highMin = mins[ j ] > fogMins[ j ] ? mins[ j ] : fogMins[ j ];
+			lowMax = maxs[ j ] < fogMaxs[ j ] ? maxs[ j ] : fogMaxs[ j ];
+			overlap[ j ] = lowMax - highMin;
+			if( overlap[ j ] < 1.0f )
+				overlap[ j ] = 1.0f;
+		}
+		
+		/* no overlap */
+		if( j < 3 )
+			continue;
+		
+		/* get volume */
+		volume = overlap[ 0 ] * overlap[ 1 ] * overlap[ 2 ];
+		
+		/* test against best volume */
+		if( volume > bestVolume )
+		{
+			bestVolume = volume;
+			fogNum = i;
+		}
+	}
+	
+	/* if the point made it this far, it's not inside any fog volumes (or inside global fog) */
+	return fogNum;
+}
+
+
+
+/*
+CreateMapFogs() - ydnar
+generates a list of map fogs
+*/
+
+void CreateMapFogs( void )
+{
+	int			i;
+	entity_t	*entity;
+	brush_t		*brush;
+	fog_t		*fog;
+	vec3_t		invFogDir;
+	const char	*globalFog;
+	
+	
+	/* skip? */
+	if( nofog )
+		return;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- CreateMapFogs ---\n" );
+	
+	/* walk entities */
+	for( i = 0; i < numEntities; i++ )
+	{
+		/* get entity */
+		entity = &entities[ i ];
+		
+		/* walk entity brushes */
+		for( brush = entity->brushes; brush != NULL; brush = brush->next )
+		{
+			/* ignore non-fog brushes */
+			if( brush->contentShader->fogParms == qfalse )
+				continue;
+			
+			/* test limit */
+			if( numMapFogs >= MAX_MAP_FOGS )
+				Error( "Exceeded MAX_MAP_FOGS (%d)", MAX_MAP_FOGS );
+			
+			/* set up fog */
+			fog = &mapFogs[ numMapFogs++ ];
+			fog->si = brush->contentShader;
+			fog->brush = brush;
+			fog->visibleSide = -1;
+			
+			/* if shader specifies an explicit direction, then find a matching brush side with an opposed normal */
+			if( VectorLength( fog->si->fogDir ) )
+			{
+				/* flip it */
+				VectorScale( fog->si->fogDir, -1.0f, invFogDir );
+				
+				/* find the brush side */
+				for( i = 0; i < brush->numsides; i++ )
+				{
+					if( VectorCompare( invFogDir, mapplanes[ brush->sides[ i ].planenum ].normal ) )
+					{
+						fog->visibleSide = i;
+						//%	Sys_Printf( "Brush num: %d Side num: %d\n", fog->brushNum, fog->visibleSide );
+						break;
+					}
+				}
+			}
+		}
+	}
+	
+	/* ydnar: global fog */
+	globalFog = ValueForKey( &entities[ 0 ], "_fog" );
+	if( globalFog[ 0 ] == '\0' )
+		globalFog = ValueForKey( &entities[ 0 ], "fog" );
+	if( globalFog[ 0 ] != '\0' )
+	{
+		/* test limit */
+		if( numMapFogs >= MAX_MAP_FOGS )
+			Error( "Exceeded MAX_MAP_FOGS (%d) trying to add global fog", MAX_MAP_FOGS );
+		
+		/* note it */
+		Sys_FPrintf( SYS_VRB, "Map has global fog shader %s\n", globalFog );
+		
+		/* set up fog */
+		fog = &mapFogs[ numMapFogs++ ];
+		fog->si = ShaderInfoForShader( globalFog );
+		if( fog->si == NULL )
+			Error( "Invalid shader \"%s\" referenced trying to add global fog", globalFog );
+		fog->brush = NULL;
+		fog->visibleSide = -1;
+		
+		/* set as default fog */
+		defaultFogNum = numMapFogs - 1;
+		
+		/* mark all worldspawn brushes as fogged */
+		for( brush = entities[ 0 ].brushes; brush != NULL; brush = brush->next )
+			ApplySurfaceParm( "fog", &brush->contentFlags, NULL, &brush->compileFlags );
+	}
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d fogs\n", numMapFogs );
+}
+
diff --git a/tools/quake3/q3map2/game_ef.h b/tools/quake3/q3map2/game_ef.h
index 6b1c7bfa..8d15c732 100644
--- a/tools/quake3/q3map2/game_ef.h
+++ b/tools/quake3/q3map2/game_ef.h
@@ -1,186 +1,186 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_EF_H
-#define GAME_EF_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* game flags */
-#define E_CONT_SOLID				1			/* an eye is never valid in a solid */
-#define E_CONT_LAVA					8
-#define E_CONT_SLIME				16
-#define E_CONT_WATER				32
-#define E_CONT_FOG					64
-#define E_CONT_LADDER				128			/* elite force ladder contents */
-
-#define E_CONT_AREAPORTAL			0x8000
-
-#define E_CONT_PLAYERCLIP			0x10000
-#define E_CONT_MONSTERCLIP			0x20000
-#define E_CONT_SHOTCLIP				0x40000		/* elite force shot clip */
-#define E_CONT_ITEM					0x80000
-#define E_CONT_CLUSTERPORTAL		0x100000
-#define E_CONT_DONOTENTER			0x200000
-#define E_CONT_BOTCLIP				0x400000
-
-#define E_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
-
-#define E_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
-#define E_CONT_CORPSE				0x4000000
-#define E_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
-#define E_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
-#define E_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
-#define E_CONT_TRIGGER				0x40000000
-#define E_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
-
-#define E_SURF_NODAMAGE				0x1			/* never give falling damage */
-#define E_SURF_SLICK				0x2			/* effects game physics */
-#define E_SURF_SKY					0x4			/* lighting from environment map */
-#define E_SURF_LADDER				0x8
-#define E_SURF_NOIMPACT				0x10		/* don't make missile explosions */
-#define E_SURF_NOMARKS				0x20		/* don't leave missile marks */
-#define E_SURF_FLESH				0x40		/* make flesh sounds and effects */
-#define E_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
-#define E_SURF_HINT					0x100		/* make a primary bsp splitter */
-#define E_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
-#define E_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
-#define E_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
-#define E_SURF_METALSTEPS			0x1000		/* clanking footsteps */
-#define E_SURF_NOSTEPS				0x2000		/* no footstep sounds */
-#define E_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
-#define E_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
-#define E_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
-#define E_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
-#define E_SURF_FORCEFIELD			0x40000		/* elite force forcefield brushes */
-
-/* ydnar flags */
-#define E_SURF_VERTEXLIT			(E_SURF_POINTLIGHT | E_SURF_NOLIGHTMAP)
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"ef",				/* -game x */
-	"baseef",			/* default base game data dir */
-	".ef",				/* unix home sub-dir */
-	"elite",			/* magic path word */
-	"scripts",			/* shader directory */
-	qfalse,				/* wolf lighting model? */
-	qfalse,				/* flares */
-	"flareshader",		/* default flare shader */
-	"IBSP",				/* bsp file prefix */
-	46,					/* bsp file version */
-	LoadIBSPFile,		/* bsp load function */
-	WriteIBSPFile,		/* bsp write function */
-	
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		E_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			E_CONT_ORIGIN,				E_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		E_CONT_AREAPORTAL,			E_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			E_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			E_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		E_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							E_SURF_HINT,				0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							E_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							E_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							E_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							E_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							E_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							E_CONT_SOLID,				E_SURF_NONSOLID,			0,							0,							C_SOLID },
-		
-		{ "trigger",		E_CONT_TRIGGER,				E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			E_CONT_WATER,				E_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slime",			E_CONT_SLIME,				E_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			E_CONT_LAVA,				E_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "playerclip",		E_CONT_PLAYERCLIP,			E_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	E_CONT_MONSTERCLIP,			E_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "shotclip",		E_CONT_SHOTCLIP,			E_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			E_CONT_NODROP,				E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "clusterportal",	E_CONT_CLUSTERPORTAL,		E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "donotenter",		E_CONT_DONOTENTER,			E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "botclip",		E_CONT_BOTCLIP,				E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "fog",			E_CONT_FOG,					E_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
-		{ "sky",			0,							0,							E_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							E_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							E_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							E_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "ladder",			E_CONT_LADDER,				E_CONT_SOLID,				E_SURF_LADDER,				0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodamage",		0,							0,							E_SURF_NODAMAGE,			0,							0,							0 },
-		{ "metalsteps",		0,							0,							E_SURF_METALSTEPS,			0,							0,							0 },
-		{ "flesh",			0,							0,							E_SURF_FLESH,				0,							0,							0 },
-		{ "nosteps",		0,							0,							E_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							E_SURF_NODLIGHT,			0,							0,							0 },
-		{ "forcefield",		0,							0,							E_SURF_FORCEFIELD,			0,							0,							0 },
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_EF_H
+#define GAME_EF_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* game flags */
+#define E_CONT_SOLID				1			/* an eye is never valid in a solid */
+#define E_CONT_LAVA					8
+#define E_CONT_SLIME				16
+#define E_CONT_WATER				32
+#define E_CONT_FOG					64
+#define E_CONT_LADDER				128			/* elite force ladder contents */
+
+#define E_CONT_AREAPORTAL			0x8000
+
+#define E_CONT_PLAYERCLIP			0x10000
+#define E_CONT_MONSTERCLIP			0x20000
+#define E_CONT_SHOTCLIP				0x40000		/* elite force shot clip */
+#define E_CONT_ITEM					0x80000
+#define E_CONT_CLUSTERPORTAL		0x100000
+#define E_CONT_DONOTENTER			0x200000
+#define E_CONT_BOTCLIP				0x400000
+
+#define E_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
+
+#define E_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
+#define E_CONT_CORPSE				0x4000000
+#define E_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
+#define E_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
+#define E_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
+#define E_CONT_TRIGGER				0x40000000
+#define E_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
+
+#define E_SURF_NODAMAGE				0x1			/* never give falling damage */
+#define E_SURF_SLICK				0x2			/* effects game physics */
+#define E_SURF_SKY					0x4			/* lighting from environment map */
+#define E_SURF_LADDER				0x8
+#define E_SURF_NOIMPACT				0x10		/* don't make missile explosions */
+#define E_SURF_NOMARKS				0x20		/* don't leave missile marks */
+#define E_SURF_FLESH				0x40		/* make flesh sounds and effects */
+#define E_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
+#define E_SURF_HINT					0x100		/* make a primary bsp splitter */
+#define E_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
+#define E_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
+#define E_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
+#define E_SURF_METALSTEPS			0x1000		/* clanking footsteps */
+#define E_SURF_NOSTEPS				0x2000		/* no footstep sounds */
+#define E_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
+#define E_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
+#define E_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
+#define E_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
+#define E_SURF_FORCEFIELD			0x40000		/* elite force forcefield brushes */
+
+/* ydnar flags */
+#define E_SURF_VERTEXLIT			(E_SURF_POINTLIGHT | E_SURF_NOLIGHTMAP)
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"ef",				/* -game x */
+	"baseef",			/* default base game data dir */
+	".ef",				/* unix home sub-dir */
+	"elite",			/* magic path word */
+	"scripts",			/* shader directory */
+	qfalse,				/* wolf lighting model? */
+	qfalse,				/* flares */
+	"flareshader",		/* default flare shader */
+	"IBSP",				/* bsp file prefix */
+	46,					/* bsp file version */
+	LoadIBSPFile,		/* bsp load function */
+	WriteIBSPFile,		/* bsp write function */
+	
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		E_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			E_CONT_ORIGIN,				E_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		E_CONT_AREAPORTAL,			E_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			E_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			E_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		E_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							E_SURF_HINT,				0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							E_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							E_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							E_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							E_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							E_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							E_CONT_SOLID,				E_SURF_NONSOLID,			0,							0,							C_SOLID },
+		
+		{ "trigger",		E_CONT_TRIGGER,				E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			E_CONT_WATER,				E_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slime",			E_CONT_SLIME,				E_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			E_CONT_LAVA,				E_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "playerclip",		E_CONT_PLAYERCLIP,			E_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	E_CONT_MONSTERCLIP,			E_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "shotclip",		E_CONT_SHOTCLIP,			E_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			E_CONT_NODROP,				E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "clusterportal",	E_CONT_CLUSTERPORTAL,		E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "donotenter",		E_CONT_DONOTENTER,			E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "botclip",		E_CONT_BOTCLIP,				E_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "fog",			E_CONT_FOG,					E_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
+		{ "sky",			0,							0,							E_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							E_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							E_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							E_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "ladder",			E_CONT_LADDER,				E_CONT_SOLID,				E_SURF_LADDER,				0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodamage",		0,							0,							E_SURF_NODAMAGE,			0,							0,							0 },
+		{ "metalsteps",		0,							0,							E_SURF_METALSTEPS,			0,							0,							0 },
+		{ "flesh",			0,							0,							E_SURF_FLESH,				0,							0,							0 },
+		{ "nosteps",		0,							0,							E_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							E_SURF_NODLIGHT,			0,							0,							0 },
+		{ "forcefield",		0,							0,							E_SURF_FORCEFIELD,			0,							0,							0 },
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
+
diff --git a/tools/quake3/q3map2/game_ja.h b/tools/quake3/q3map2/game_ja.h
index f0f8b276..d7b39762 100644
--- a/tools/quake3/q3map2/game_ja.h
+++ b/tools/quake3/q3map2/game_ja.h
@@ -1,180 +1,180 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_JA_H
-#define GAME_JA_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* this file must be included *after* game_sof2.h and game_jk2.h because they share defines! */
-
-#define	JA_CONT_INSIDE			0x10000000	/* jedi academy 'inside' */
-#define	JA_SURF_FORCESIGHT		0x02000000	/* jedi academy 'forcesight' */
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"ja",				/* -game x */
-	"base",				/* default base game data dir */
-	".ja",				/* unix home sub-dir */
-	"GameData",			/* magic path word */
-	"shaders",			/* shader directory */
-	qfalse,				/* wolf lighting model? */
-	qtrue,				/* flares */
-	"gfx/misc/flare",	/* default flare shader */
-	"RBSP",				/* bsp file prefix */
-	1,					/* bsp file version */
-	LoadRBSPFile,		/* bsp load function */
-	WriteRBSPFile,		/* bsp write function */
-	
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		S_CONT_SOLID | S_CONT_OPAQUE,	-1,						0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			0,							S_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		S_CONT_TRANSLUCENT,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			S_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			S_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		0,							0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							0,							0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							S_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							0,							0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							0,							0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							S_CONT_SOLID,				0,							0,							0,							C_SOLID },
-		{ "nonopaque",		0,							S_CONT_OPAQUE,				0,							0,							C_TRANSLUCENT,				0 },		/* setting trans ok? */
-		
-		{ "trigger",		S_CONT_TRIGGER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			S_CONT_WATER,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slime",			S_CONT_SLIME,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			S_CONT_LAVA,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-
-		{ "shotclip",		S_CONT_SHOTCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* setting trans/detail ok? */
-		{ "playerclip",		S_CONT_PLAYERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	S_CONT_MONSTERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			S_CONT_NODROP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "terrain",		S_CONT_TERRAIN,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "ladder",			S_CONT_LADDER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "abseil",			S_CONT_ABSEIL,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "outside",		S_CONT_OUTSIDE,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "botclip",		S_CONT_BOTCLIP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "fog",			S_CONT_FOG,					S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_FOG | C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* nonopaque? */
-		{ "sky",			0,							0,							S_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							S_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							S_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							S_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "nodamage",		0,							0,							S_SURF_NODAMAGE,			0,							0,							0 },
-		{ "metalsteps",		0,							0,							S_SURF_METALSTEPS,			0,							0,							0 },
-		{ "nosteps",		0,							0,							S_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							S_SURF_NODLIGHT,			0,							0,							0 },
-		{ "nomiscents",		0,							0,							S_SURF_NOMISCENTS,			0,							0,							0 },
-		{ "forcefield",		0,							0,							S_SURF_FORCEFIELD,			0,							0,							0 },
-		
-		/* jedi academy */
-		{ "inside",			JA_CONT_INSIDE,				0,							0,							0,							0,							0 },
-		{ "forcesight",		0,							0,							JA_SURF_FORCESIGHT,			0,							0,							0 },
-		
-		/* materials */
-		{ "*mat_none",		0,							0,							S_MAT_NONE,					S_MAT_MASK,					0,							0 },
-		{ "*mat_solidwood",	0,							0,							S_MAT_SOLIDWOOD,			S_MAT_MASK,					0,							0 },
-		{ "*mat_hollowwood",	0,						0,							S_MAT_HOLLOWWOOD,			S_MAT_MASK,					0,							0 },
-		{ "*mat_solidmetal",	0,						0,							S_MAT_SOLIDMETAL,			S_MAT_MASK,					0,							0 },
-		{ "*mat_hollowmetal",	0,						0,							S_MAT_HOLLOWMETAL,			S_MAT_MASK,					0,							0 },
-		{ "*mat_shortgrass",	0,						0,							S_MAT_SHORTGRASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_longgrass",		0,						0,							S_MAT_LONGGRASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_dirt",		0,							0,							S_MAT_DIRT,					S_MAT_MASK,					0,							0 },
-		{ "*mat_sand",		0,							0,							S_MAT_SAND,					S_MAT_MASK,					0,							0 },
-		{ "*mat_gravel",	0,							0,							S_MAT_GRAVEL,				S_MAT_MASK,					0,							0 },
-		{ "*mat_glass",		0,							0,							S_MAT_GLASS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_concrete",	0,							0,							S_MAT_CONCRETE,				S_MAT_MASK,					0,							0 },
-		{ "*mat_marble",	0,							0,							S_MAT_MARBLE,				S_MAT_MASK,					0,							0 },
-		{ "*mat_water",		0,							0,							S_MAT_WATER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_snow",		0,							0,							S_MAT_SNOW,					S_MAT_MASK,					0,							0 },
-		{ "*mat_ice",		0,							0,							S_MAT_ICE,					S_MAT_MASK,					0,							0 },
-		{ "*mat_flesh",		0,							0,							S_MAT_FLESH,				S_MAT_MASK,					0,							0 },
-		{ "*mat_mud",		0,							0,							S_MAT_MUD,					S_MAT_MASK,					0,							0 },
-		{ "*mat_bpglass",	0,							0,							S_MAT_BPGLASS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_dryleaves",	0,							0,							S_MAT_DRYLEAVES,			S_MAT_MASK,					0,							0 },
-		{ "*mat_greenleaves",	0,						0,							S_MAT_GREENLEAVES,			S_MAT_MASK,					0,							0 },
-		{ "*mat_fabric",	0,							0,							S_MAT_FABRIC,				S_MAT_MASK,					0,							0 },
-		{ "*mat_canvas",	0,							0,							S_MAT_CANVAS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_rock",		0,							0,							S_MAT_ROCK,					S_MAT_MASK,					0,							0 },
-		{ "*mat_rubber",	0,							0,							S_MAT_RUBBER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_plastic",	0,							0,							S_MAT_PLASTIC,				S_MAT_MASK,					0,							0 },
-		{ "*mat_tiles",		0,							0,							S_MAT_TILES,				S_MAT_MASK,					0,							0 },
-		{ "*mat_carpet",	0,							0,							S_MAT_CARPET,				S_MAT_MASK,					0,							0 },
-		{ "*mat_plaster",	0,							0,							S_MAT_PLASTER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_shatterglass",	0,						0,							S_MAT_SHATTERGLASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_armor",		0,							0,							S_MAT_ARMOR,				S_MAT_MASK,					0,							0 },
-		{ "*mat_computer",	0,							0,							S_MAT_COMPUTER,				S_MAT_MASK,					0,							0 },	
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_JA_H
+#define GAME_JA_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* this file must be included *after* game_sof2.h and game_jk2.h because they share defines! */
+
+#define	JA_CONT_INSIDE			0x10000000	/* jedi academy 'inside' */
+#define	JA_SURF_FORCESIGHT		0x02000000	/* jedi academy 'forcesight' */
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"ja",				/* -game x */
+	"base",				/* default base game data dir */
+	".ja",				/* unix home sub-dir */
+	"GameData",			/* magic path word */
+	"shaders",			/* shader directory */
+	qfalse,				/* wolf lighting model? */
+	qtrue,				/* flares */
+	"gfx/misc/flare",	/* default flare shader */
+	"RBSP",				/* bsp file prefix */
+	1,					/* bsp file version */
+	LoadRBSPFile,		/* bsp load function */
+	WriteRBSPFile,		/* bsp write function */
+	
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		S_CONT_SOLID | S_CONT_OPAQUE,	-1,						0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			0,							S_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		S_CONT_TRANSLUCENT,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			S_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			S_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		0,							0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							0,							0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							S_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							0,							0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							0,							0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							S_CONT_SOLID,				0,							0,							0,							C_SOLID },
+		{ "nonopaque",		0,							S_CONT_OPAQUE,				0,							0,							C_TRANSLUCENT,				0 },		/* setting trans ok? */
+		
+		{ "trigger",		S_CONT_TRIGGER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			S_CONT_WATER,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slime",			S_CONT_SLIME,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			S_CONT_LAVA,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+
+		{ "shotclip",		S_CONT_SHOTCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* setting trans/detail ok? */
+		{ "playerclip",		S_CONT_PLAYERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	S_CONT_MONSTERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			S_CONT_NODROP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "terrain",		S_CONT_TERRAIN,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "ladder",			S_CONT_LADDER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "abseil",			S_CONT_ABSEIL,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "outside",		S_CONT_OUTSIDE,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "botclip",		S_CONT_BOTCLIP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "fog",			S_CONT_FOG,					S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_FOG | C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* nonopaque? */
+		{ "sky",			0,							0,							S_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							S_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							S_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							S_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "nodamage",		0,							0,							S_SURF_NODAMAGE,			0,							0,							0 },
+		{ "metalsteps",		0,							0,							S_SURF_METALSTEPS,			0,							0,							0 },
+		{ "nosteps",		0,							0,							S_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							S_SURF_NODLIGHT,			0,							0,							0 },
+		{ "nomiscents",		0,							0,							S_SURF_NOMISCENTS,			0,							0,							0 },
+		{ "forcefield",		0,							0,							S_SURF_FORCEFIELD,			0,							0,							0 },
+		
+		/* jedi academy */
+		{ "inside",			JA_CONT_INSIDE,				0,							0,							0,							0,							0 },
+		{ "forcesight",		0,							0,							JA_SURF_FORCESIGHT,			0,							0,							0 },
+		
+		/* materials */
+		{ "*mat_none",		0,							0,							S_MAT_NONE,					S_MAT_MASK,					0,							0 },
+		{ "*mat_solidwood",	0,							0,							S_MAT_SOLIDWOOD,			S_MAT_MASK,					0,							0 },
+		{ "*mat_hollowwood",	0,						0,							S_MAT_HOLLOWWOOD,			S_MAT_MASK,					0,							0 },
+		{ "*mat_solidmetal",	0,						0,							S_MAT_SOLIDMETAL,			S_MAT_MASK,					0,							0 },
+		{ "*mat_hollowmetal",	0,						0,							S_MAT_HOLLOWMETAL,			S_MAT_MASK,					0,							0 },
+		{ "*mat_shortgrass",	0,						0,							S_MAT_SHORTGRASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_longgrass",		0,						0,							S_MAT_LONGGRASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_dirt",		0,							0,							S_MAT_DIRT,					S_MAT_MASK,					0,							0 },
+		{ "*mat_sand",		0,							0,							S_MAT_SAND,					S_MAT_MASK,					0,							0 },
+		{ "*mat_gravel",	0,							0,							S_MAT_GRAVEL,				S_MAT_MASK,					0,							0 },
+		{ "*mat_glass",		0,							0,							S_MAT_GLASS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_concrete",	0,							0,							S_MAT_CONCRETE,				S_MAT_MASK,					0,							0 },
+		{ "*mat_marble",	0,							0,							S_MAT_MARBLE,				S_MAT_MASK,					0,							0 },
+		{ "*mat_water",		0,							0,							S_MAT_WATER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_snow",		0,							0,							S_MAT_SNOW,					S_MAT_MASK,					0,							0 },
+		{ "*mat_ice",		0,							0,							S_MAT_ICE,					S_MAT_MASK,					0,							0 },
+		{ "*mat_flesh",		0,							0,							S_MAT_FLESH,				S_MAT_MASK,					0,							0 },
+		{ "*mat_mud",		0,							0,							S_MAT_MUD,					S_MAT_MASK,					0,							0 },
+		{ "*mat_bpglass",	0,							0,							S_MAT_BPGLASS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_dryleaves",	0,							0,							S_MAT_DRYLEAVES,			S_MAT_MASK,					0,							0 },
+		{ "*mat_greenleaves",	0,						0,							S_MAT_GREENLEAVES,			S_MAT_MASK,					0,							0 },
+		{ "*mat_fabric",	0,							0,							S_MAT_FABRIC,				S_MAT_MASK,					0,							0 },
+		{ "*mat_canvas",	0,							0,							S_MAT_CANVAS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_rock",		0,							0,							S_MAT_ROCK,					S_MAT_MASK,					0,							0 },
+		{ "*mat_rubber",	0,							0,							S_MAT_RUBBER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_plastic",	0,							0,							S_MAT_PLASTIC,				S_MAT_MASK,					0,							0 },
+		{ "*mat_tiles",		0,							0,							S_MAT_TILES,				S_MAT_MASK,					0,							0 },
+		{ "*mat_carpet",	0,							0,							S_MAT_CARPET,				S_MAT_MASK,					0,							0 },
+		{ "*mat_plaster",	0,							0,							S_MAT_PLASTER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_shatterglass",	0,						0,							S_MAT_SHATTERGLASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_armor",		0,							0,							S_MAT_ARMOR,				S_MAT_MASK,					0,							0 },
+		{ "*mat_computer",	0,							0,							S_MAT_COMPUTER,				S_MAT_MASK,					0,							0 },	
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
diff --git a/tools/quake3/q3map2/game_jk2.h b/tools/quake3/q3map2/game_jk2.h
index 8fbf7202..086eaced 100644
--- a/tools/quake3/q3map2/game_jk2.h
+++ b/tools/quake3/q3map2/game_jk2.h
@@ -1,174 +1,174 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_JK2_H
-#define GAME_JK2_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* this file must be included *after* game_sof2.h because it shares defines! */
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"jk2",				/* -game x */
-	"base",				/* default base game data dir */
-	".jk2",				/* unix home sub-dir */
-	"GameData",			/* magic path word */
-	"shaders",			/* shader directory */
-	qfalse,				/* wolf lighting model? */
-	qtrue,				/* flares */
-	"gfx/misc/flare",	/* default flare shader */
-	"RBSP",				/* bsp file prefix */
-	1,					/* bsp file version */
-	LoadRBSPFile,		/* bsp load function */
-	WriteRBSPFile,		/* bsp write function */
-	
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		S_CONT_SOLID | S_CONT_OPAQUE,	-1,						0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			0,							S_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		S_CONT_TRANSLUCENT,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			S_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			S_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		0,							0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							0,							0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							S_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							0,							0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							0,							0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							S_CONT_SOLID,				0,							0,							0,							C_SOLID },
-		{ "nonopaque",		0,							S_CONT_OPAQUE,				0,							0,							C_TRANSLUCENT,				0 },		/* setting trans ok? */
-		
-		{ "trigger",		S_CONT_TRIGGER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			S_CONT_WATER,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slime",			S_CONT_SLIME,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			S_CONT_LAVA,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-
-		{ "shotclip",		S_CONT_SHOTCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* setting trans/detail ok? */
-		{ "playerclip",		S_CONT_PLAYERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	S_CONT_MONSTERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			S_CONT_NODROP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "terrain",		S_CONT_TERRAIN,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "ladder",			S_CONT_LADDER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "abseil",			S_CONT_ABSEIL,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "outside",		S_CONT_OUTSIDE,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "botclip",		S_CONT_BOTCLIP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "fog",			S_CONT_FOG,					S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_FOG | C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* nonopaque? */
-		{ "sky",			0,							0,							S_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							S_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							S_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							S_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "nodamage",		0,							0,							S_SURF_NODAMAGE,			0,							0,							0 },
-		{ "metalsteps",		0,							0,							S_SURF_METALSTEPS,			0,							0,							0 },
-		{ "nosteps",		0,							0,							S_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							S_SURF_NODLIGHT,			0,							0,							0 },
-		{ "nomiscents",		0,							0,							S_SURF_NOMISCENTS,			0,							0,							0 },
-		{ "forcefield",		0,							0,							S_SURF_FORCEFIELD,			0,							0,							0 },
-		
-		
-		/* materials */
-		{ "*mat_none",		0,							0,							S_MAT_NONE,					S_MAT_MASK,					0,							0 },
-		{ "*mat_solidwood",	0,							0,							S_MAT_SOLIDWOOD,			S_MAT_MASK,					0,							0 },
-		{ "*mat_hollowwood",	0,						0,							S_MAT_HOLLOWWOOD,			S_MAT_MASK,					0,							0 },
-		{ "*mat_solidmetal",	0,						0,							S_MAT_SOLIDMETAL,			S_MAT_MASK,					0,							0 },
-		{ "*mat_hollowmetal",	0,						0,							S_MAT_HOLLOWMETAL,			S_MAT_MASK,					0,							0 },
-		{ "*mat_shortgrass",	0,						0,							S_MAT_SHORTGRASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_longgrass",		0,						0,							S_MAT_LONGGRASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_dirt",		0,							0,							S_MAT_DIRT,					S_MAT_MASK,					0,							0 },
-		{ "*mat_sand",		0,							0,							S_MAT_SAND,					S_MAT_MASK,					0,							0 },
-		{ "*mat_gravel",	0,							0,							S_MAT_GRAVEL,				S_MAT_MASK,					0,							0 },
-		{ "*mat_glass",		0,							0,							S_MAT_GLASS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_concrete",	0,							0,							S_MAT_CONCRETE,				S_MAT_MASK,					0,							0 },
-		{ "*mat_marble",	0,							0,							S_MAT_MARBLE,				S_MAT_MASK,					0,							0 },
-		{ "*mat_water",		0,							0,							S_MAT_WATER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_snow",		0,							0,							S_MAT_SNOW,					S_MAT_MASK,					0,							0 },
-		{ "*mat_ice",		0,							0,							S_MAT_ICE,					S_MAT_MASK,					0,							0 },
-		{ "*mat_flesh",		0,							0,							S_MAT_FLESH,				S_MAT_MASK,					0,							0 },
-		{ "*mat_mud",		0,							0,							S_MAT_MUD,					S_MAT_MASK,					0,							0 },
-		{ "*mat_bpglass",	0,							0,							S_MAT_BPGLASS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_dryleaves",	0,							0,							S_MAT_DRYLEAVES,			S_MAT_MASK,					0,							0 },
-		{ "*mat_greenleaves",	0,						0,							S_MAT_GREENLEAVES,			S_MAT_MASK,					0,							0 },
-		{ "*mat_fabric",	0,							0,							S_MAT_FABRIC,				S_MAT_MASK,					0,							0 },
-		{ "*mat_canvas",	0,							0,							S_MAT_CANVAS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_rock",		0,							0,							S_MAT_ROCK,					S_MAT_MASK,					0,							0 },
-		{ "*mat_rubber",	0,							0,							S_MAT_RUBBER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_plastic",	0,							0,							S_MAT_PLASTIC,				S_MAT_MASK,					0,							0 },
-		{ "*mat_tiles",		0,							0,							S_MAT_TILES,				S_MAT_MASK,					0,							0 },
-		{ "*mat_carpet",	0,							0,							S_MAT_CARPET,				S_MAT_MASK,					0,							0 },
-		{ "*mat_plaster",	0,							0,							S_MAT_PLASTER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_shatterglass",	0,						0,							S_MAT_SHATTERGLASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_armor",		0,							0,							S_MAT_ARMOR,				S_MAT_MASK,					0,							0 },
-		{ "*mat_computer",	0,							0,							S_MAT_COMPUTER,				S_MAT_MASK,					0,							0 },	
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_JK2_H
+#define GAME_JK2_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* this file must be included *after* game_sof2.h because it shares defines! */
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"jk2",				/* -game x */
+	"base",				/* default base game data dir */
+	".jk2",				/* unix home sub-dir */
+	"GameData",			/* magic path word */
+	"shaders",			/* shader directory */
+	qfalse,				/* wolf lighting model? */
+	qtrue,				/* flares */
+	"gfx/misc/flare",	/* default flare shader */
+	"RBSP",				/* bsp file prefix */
+	1,					/* bsp file version */
+	LoadRBSPFile,		/* bsp load function */
+	WriteRBSPFile,		/* bsp write function */
+	
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		S_CONT_SOLID | S_CONT_OPAQUE,	-1,						0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			0,							S_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		S_CONT_TRANSLUCENT,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			S_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			S_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		0,							0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							0,							0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							S_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							0,							0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							0,							0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							S_CONT_SOLID,				0,							0,							0,							C_SOLID },
+		{ "nonopaque",		0,							S_CONT_OPAQUE,				0,							0,							C_TRANSLUCENT,				0 },		/* setting trans ok? */
+		
+		{ "trigger",		S_CONT_TRIGGER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			S_CONT_WATER,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slime",			S_CONT_SLIME,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			S_CONT_LAVA,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+
+		{ "shotclip",		S_CONT_SHOTCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* setting trans/detail ok? */
+		{ "playerclip",		S_CONT_PLAYERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	S_CONT_MONSTERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			S_CONT_NODROP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "terrain",		S_CONT_TERRAIN,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "ladder",			S_CONT_LADDER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "abseil",			S_CONT_ABSEIL,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "outside",		S_CONT_OUTSIDE,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "botclip",		S_CONT_BOTCLIP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "fog",			S_CONT_FOG,					S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_FOG | C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* nonopaque? */
+		{ "sky",			0,							0,							S_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							S_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							S_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							S_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "nodamage",		0,							0,							S_SURF_NODAMAGE,			0,							0,							0 },
+		{ "metalsteps",		0,							0,							S_SURF_METALSTEPS,			0,							0,							0 },
+		{ "nosteps",		0,							0,							S_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							S_SURF_NODLIGHT,			0,							0,							0 },
+		{ "nomiscents",		0,							0,							S_SURF_NOMISCENTS,			0,							0,							0 },
+		{ "forcefield",		0,							0,							S_SURF_FORCEFIELD,			0,							0,							0 },
+		
+		
+		/* materials */
+		{ "*mat_none",		0,							0,							S_MAT_NONE,					S_MAT_MASK,					0,							0 },
+		{ "*mat_solidwood",	0,							0,							S_MAT_SOLIDWOOD,			S_MAT_MASK,					0,							0 },
+		{ "*mat_hollowwood",	0,						0,							S_MAT_HOLLOWWOOD,			S_MAT_MASK,					0,							0 },
+		{ "*mat_solidmetal",	0,						0,							S_MAT_SOLIDMETAL,			S_MAT_MASK,					0,							0 },
+		{ "*mat_hollowmetal",	0,						0,							S_MAT_HOLLOWMETAL,			S_MAT_MASK,					0,							0 },
+		{ "*mat_shortgrass",	0,						0,							S_MAT_SHORTGRASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_longgrass",		0,						0,							S_MAT_LONGGRASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_dirt",		0,							0,							S_MAT_DIRT,					S_MAT_MASK,					0,							0 },
+		{ "*mat_sand",		0,							0,							S_MAT_SAND,					S_MAT_MASK,					0,							0 },
+		{ "*mat_gravel",	0,							0,							S_MAT_GRAVEL,				S_MAT_MASK,					0,							0 },
+		{ "*mat_glass",		0,							0,							S_MAT_GLASS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_concrete",	0,							0,							S_MAT_CONCRETE,				S_MAT_MASK,					0,							0 },
+		{ "*mat_marble",	0,							0,							S_MAT_MARBLE,				S_MAT_MASK,					0,							0 },
+		{ "*mat_water",		0,							0,							S_MAT_WATER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_snow",		0,							0,							S_MAT_SNOW,					S_MAT_MASK,					0,							0 },
+		{ "*mat_ice",		0,							0,							S_MAT_ICE,					S_MAT_MASK,					0,							0 },
+		{ "*mat_flesh",		0,							0,							S_MAT_FLESH,				S_MAT_MASK,					0,							0 },
+		{ "*mat_mud",		0,							0,							S_MAT_MUD,					S_MAT_MASK,					0,							0 },
+		{ "*mat_bpglass",	0,							0,							S_MAT_BPGLASS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_dryleaves",	0,							0,							S_MAT_DRYLEAVES,			S_MAT_MASK,					0,							0 },
+		{ "*mat_greenleaves",	0,						0,							S_MAT_GREENLEAVES,			S_MAT_MASK,					0,							0 },
+		{ "*mat_fabric",	0,							0,							S_MAT_FABRIC,				S_MAT_MASK,					0,							0 },
+		{ "*mat_canvas",	0,							0,							S_MAT_CANVAS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_rock",		0,							0,							S_MAT_ROCK,					S_MAT_MASK,					0,							0 },
+		{ "*mat_rubber",	0,							0,							S_MAT_RUBBER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_plastic",	0,							0,							S_MAT_PLASTIC,				S_MAT_MASK,					0,							0 },
+		{ "*mat_tiles",		0,							0,							S_MAT_TILES,				S_MAT_MASK,					0,							0 },
+		{ "*mat_carpet",	0,							0,							S_MAT_CARPET,				S_MAT_MASK,					0,							0 },
+		{ "*mat_plaster",	0,							0,							S_MAT_PLASTER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_shatterglass",	0,						0,							S_MAT_SHATTERGLASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_armor",		0,							0,							S_MAT_ARMOR,				S_MAT_MASK,					0,							0 },
+		{ "*mat_computer",	0,							0,							S_MAT_COMPUTER,				S_MAT_MASK,					0,							0 },	
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
diff --git a/tools/quake3/q3map2/game_quake3.h b/tools/quake3/q3map2/game_quake3.h
index 27910473..9b55787d 100644
--- a/tools/quake3/q3map2/game_quake3.h
+++ b/tools/quake3/q3map2/game_quake3.h
@@ -1,184 +1,184 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_QUAKE3_H
-#define GAME_QUAKE3_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* game flags */
-#define Q_CONT_SOLID				1			/* an eye is never valid in a solid */
-#define Q_CONT_LAVA					8
-#define Q_CONT_SLIME				16
-#define Q_CONT_WATER				32
-#define Q_CONT_FOG					64
-
-#define Q_CONT_AREAPORTAL			0x8000
-
-#define Q_CONT_PLAYERCLIP			0x10000
-#define Q_CONT_MONSTERCLIP			0x20000
-#define Q_CONT_TELEPORTER			0x40000
-#define Q_CONT_JUMPPAD				0x80000
-#define Q_CONT_CLUSTERPORTAL		0x100000
-#define Q_CONT_DONOTENTER			0x200000
-#define Q_CONT_BOTCLIP				0x400000
-
-#define Q_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
-
-#define Q_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
-#define Q_CONT_CORPSE				0x4000000
-#define Q_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
-#define Q_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
-#define Q_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
-#define Q_CONT_TRIGGER				0x40000000
-#define Q_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
-
-#define Q_SURF_NODAMAGE				0x1			/* never give falling damage */
-#define Q_SURF_SLICK				0x2			/* effects game physics */
-#define Q_SURF_SKY					0x4			/* lighting from environment map */
-#define Q_SURF_LADDER				0x8
-#define Q_SURF_NOIMPACT				0x10		/* don't make missile explosions */
-#define Q_SURF_NOMARKS				0x20		/* don't leave missile marks */
-#define Q_SURF_FLESH				0x40		/* make flesh sounds and effects */
-#define Q_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
-#define Q_SURF_HINT					0x100		/* make a primary bsp splitter */
-#define Q_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
-#define Q_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
-#define Q_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
-#define Q_SURF_METALSTEPS			0x1000		/* clanking footsteps */
-#define Q_SURF_NOSTEPS				0x2000		/* no footstep sounds */
-#define Q_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
-#define Q_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
-#define Q_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
-#define Q_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
-#define Q_SURF_DUST					0x40000		/* leave a dust trail when walking on this surface */
-
-/* ydnar flags */
-#define Q_SURF_VERTEXLIT			(Q_SURF_POINTLIGHT | Q_SURF_NOLIGHTMAP)
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"quake3",			/* -game x */
-	"baseq3",			/* default base game data dir */
-	".q3a",				/* unix home sub-dir */
-	"quake",			/* magic path word */
-	"scripts",			/* shader directory */
-	qfalse,				/* wolf lighting model? */
-	qfalse,				/* flares */
-	"flareshader",		/* default flare shader */
-	"IBSP",				/* bsp file prefix */
-	46,					/* bsp file version */
-	LoadIBSPFile,		/* bsp load function */
-	WriteIBSPFile,		/* bsp write function */
-
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		Q_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			Q_CONT_ORIGIN,				Q_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		Q_CONT_AREAPORTAL,			Q_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			Q_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			Q_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		Q_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							Q_SURF_HINT,				0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							Q_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							Q_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							Q_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							Q_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							Q_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							Q_CONT_SOLID,				Q_SURF_NONSOLID,			0,							0,							C_SOLID },
-		
-		{ "trigger",		Q_CONT_TRIGGER,				Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			Q_CONT_WATER,				Q_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slime",			Q_CONT_SLIME,				Q_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			Q_CONT_LAVA,				Q_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "playerclip",		Q_CONT_PLAYERCLIP,			Q_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	Q_CONT_MONSTERCLIP,			Q_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			Q_CONT_NODROP,				Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "clusterportal",	Q_CONT_CLUSTERPORTAL,		Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "donotenter",		Q_CONT_DONOTENTER,			Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "botclip",		Q_CONT_BOTCLIP,				Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "fog",			Q_CONT_FOG,					Q_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
-		{ "sky",			0,							0,							Q_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							Q_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							Q_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							Q_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "ladder",			0,							0,							Q_SURF_LADDER,				0,							0,							0 },
-		{ "nodamage",		0,							0,							Q_SURF_NODAMAGE,			0,							0,							0 },
-		{ "metalsteps",		0,							0,							Q_SURF_METALSTEPS,			0,							0,							0 },
-		{ "flesh",			0,							0,							Q_SURF_FLESH,				0,							0,							0 },
-		{ "nosteps",		0,							0,							Q_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							Q_SURF_NODLIGHT,			0,							0,							0 },
-		{ "dust",			0,							0,							Q_SURF_DUST,				0,							0,							0 },
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_QUAKE3_H
+#define GAME_QUAKE3_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* game flags */
+#define Q_CONT_SOLID				1			/* an eye is never valid in a solid */
+#define Q_CONT_LAVA					8
+#define Q_CONT_SLIME				16
+#define Q_CONT_WATER				32
+#define Q_CONT_FOG					64
+
+#define Q_CONT_AREAPORTAL			0x8000
+
+#define Q_CONT_PLAYERCLIP			0x10000
+#define Q_CONT_MONSTERCLIP			0x20000
+#define Q_CONT_TELEPORTER			0x40000
+#define Q_CONT_JUMPPAD				0x80000
+#define Q_CONT_CLUSTERPORTAL		0x100000
+#define Q_CONT_DONOTENTER			0x200000
+#define Q_CONT_BOTCLIP				0x400000
+
+#define Q_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
+
+#define Q_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
+#define Q_CONT_CORPSE				0x4000000
+#define Q_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
+#define Q_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
+#define Q_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
+#define Q_CONT_TRIGGER				0x40000000
+#define Q_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
+
+#define Q_SURF_NODAMAGE				0x1			/* never give falling damage */
+#define Q_SURF_SLICK				0x2			/* effects game physics */
+#define Q_SURF_SKY					0x4			/* lighting from environment map */
+#define Q_SURF_LADDER				0x8
+#define Q_SURF_NOIMPACT				0x10		/* don't make missile explosions */
+#define Q_SURF_NOMARKS				0x20		/* don't leave missile marks */
+#define Q_SURF_FLESH				0x40		/* make flesh sounds and effects */
+#define Q_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
+#define Q_SURF_HINT					0x100		/* make a primary bsp splitter */
+#define Q_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
+#define Q_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
+#define Q_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
+#define Q_SURF_METALSTEPS			0x1000		/* clanking footsteps */
+#define Q_SURF_NOSTEPS				0x2000		/* no footstep sounds */
+#define Q_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
+#define Q_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
+#define Q_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
+#define Q_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
+#define Q_SURF_DUST					0x40000		/* leave a dust trail when walking on this surface */
+
+/* ydnar flags */
+#define Q_SURF_VERTEXLIT			(Q_SURF_POINTLIGHT | Q_SURF_NOLIGHTMAP)
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"quake3",			/* -game x */
+	"baseq3",			/* default base game data dir */
+	".q3a",				/* unix home sub-dir */
+	"quake",			/* magic path word */
+	"scripts",			/* shader directory */
+	qfalse,				/* wolf lighting model? */
+	qfalse,				/* flares */
+	"flareshader",		/* default flare shader */
+	"IBSP",				/* bsp file prefix */
+	46,					/* bsp file version */
+	LoadIBSPFile,		/* bsp load function */
+	WriteIBSPFile,		/* bsp write function */
+
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		Q_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			Q_CONT_ORIGIN,				Q_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		Q_CONT_AREAPORTAL,			Q_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			Q_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			Q_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		Q_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							Q_SURF_HINT,				0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							Q_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							Q_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							Q_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							Q_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							Q_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							Q_CONT_SOLID,				Q_SURF_NONSOLID,			0,							0,							C_SOLID },
+		
+		{ "trigger",		Q_CONT_TRIGGER,				Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			Q_CONT_WATER,				Q_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slime",			Q_CONT_SLIME,				Q_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			Q_CONT_LAVA,				Q_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "playerclip",		Q_CONT_PLAYERCLIP,			Q_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	Q_CONT_MONSTERCLIP,			Q_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			Q_CONT_NODROP,				Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "clusterportal",	Q_CONT_CLUSTERPORTAL,		Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "donotenter",		Q_CONT_DONOTENTER,			Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "botclip",		Q_CONT_BOTCLIP,				Q_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "fog",			Q_CONT_FOG,					Q_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
+		{ "sky",			0,							0,							Q_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							Q_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							Q_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							Q_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "ladder",			0,							0,							Q_SURF_LADDER,				0,							0,							0 },
+		{ "nodamage",		0,							0,							Q_SURF_NODAMAGE,			0,							0,							0 },
+		{ "metalsteps",		0,							0,							Q_SURF_METALSTEPS,			0,							0,							0 },
+		{ "flesh",			0,							0,							Q_SURF_FLESH,				0,							0,							0 },
+		{ "nosteps",		0,							0,							Q_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							Q_SURF_NODLIGHT,			0,							0,							0 },
+		{ "dust",			0,							0,							Q_SURF_DUST,				0,							0,							0 },
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
+
diff --git a/tools/quake3/q3map2/game_sof2.h b/tools/quake3/q3map2/game_sof2.h
index cd3c7a38..5d12d07d 100644
--- a/tools/quake3/q3map2/game_sof2.h
+++ b/tools/quake3/q3map2/game_sof2.h
@@ -1,249 +1,249 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_SOF2_H
-#define GAME_SOF2_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* thanks to the gracious fellows at raven */
-#define	S_CONT_SOLID				0x00000001	/* Default setting. An eye is never valid in a solid */
-#define	S_CONT_LAVA					0x00000002
-#define	S_CONT_WATER				0x00000004
-#define	S_CONT_FOG					0x00000008
-#define	S_CONT_PLAYERCLIP			0x00000010
-#define	S_CONT_MONSTERCLIP			0x00000020
-#define S_CONT_BOTCLIP				0x00000040
-#define S_CONT_SHOTCLIP				0x00000080
-#define	S_CONT_BODY					0x00000100	/* should never be on a brush, only in game */
-#define	S_CONT_CORPSE				0x00000200	/* should never be on a brush, only in game */
-#define	S_CONT_TRIGGER				0x00000400
-#define	S_CONT_NODROP				0x00000800	/* don't leave bodies or items (death fog, lava) */
-#define S_CONT_TERRAIN				0x00001000	/* volume contains terrain data */
-#define S_CONT_LADDER				0x00002000
-#define S_CONT_ABSEIL				0x00004000  /* used like ladder to define where an NPC can abseil */
-#define S_CONT_OPAQUE				0x00008000	/* defaults to on, when off, solid can be seen through */
-#define S_CONT_OUTSIDE				0x00010000	/* volume is considered to be in the outside (i.e. not indoors) */
-#define S_CONT_SLIME				0x00020000	/* don't be fooled. it may SAY "slime" but it really means "projectileclip" */
-#define S_CONT_LIGHTSABER			0x00040000
-#define S_CONT_TELEPORTER			0x00080000
-#define S_CONT_ITEM					0x00100000
-#define	S_CONT_DETAIL				0x08000000	/* brushes not used for the bsp */
-#define	S_CONT_TRANSLUCENT			0x80000000	/* don't consume surface fragments inside */
-
-#define	S_SURF_SKY					0x00002000	/* lighting from environment map */
-#define	S_SURF_SLICK				0x00004000	/* affects game physics */
-#define	S_SURF_METALSTEPS			0x00008000	/* chc needs this since we use same tools */
-#define S_SURF_FORCEFIELD			0x00010000	/* chc */
-#define	S_SURF_NODAMAGE				0x00040000	/* never give falling damage */
-#define	S_SURF_NOIMPACT				0x00080000	/* don't make missile explosions */
-#define	S_SURF_NOMARKS				0x00100000	/* don't leave missile marks */
-#define	S_SURF_NODRAW				0x00200000	/* don't generate a drawsurface at all */
-#define	S_SURF_NOSTEPS				0x00400000	/* no footstep sounds */
-#define	S_SURF_NODLIGHT				0x00800000	/* don't dlight even if solid (solid lava, skies) */
-#define	S_SURF_NOMISCENTS			0x01000000	/* no client models allowed on this surface */
-
-#define S_SURF_PATCH				0x80000000	/* mark this face as a patch(editor only) */
-
-/* materials */
-#define S_MAT_BITS					5
-#define S_MAT_MASK					0x1f		/* mask to get the material type */
-
-#define S_MAT_NONE					0			/* for when the artist hasn't set anything up =) */
-#define S_MAT_SOLIDWOOD				1			/* freshly cut timber */
-#define S_MAT_HOLLOWWOOD			2			/* termite infested creaky wood */
-#define S_MAT_SOLIDMETAL			3			/* solid girders */
-#define S_MAT_HOLLOWMETAL			4			/* hollow metal machines */
-#define S_MAT_SHORTGRASS			5			/* manicured lawn */
-#define S_MAT_LONGGRASS				6			/* long jungle grass */
-#define S_MAT_DIRT					7			/* hard mud */
-#define S_MAT_SAND					8			/* sandy beach */
-#define S_MAT_GRAVEL				9			/* lots of small stones */
-#define S_MAT_GLASS					10
-#define S_MAT_CONCRETE				11			/* hardened concrete pavement */
-#define S_MAT_MARBLE				12			/* marble floors */
-#define S_MAT_WATER					13			/* light covering of water on a surface */
-#define S_MAT_SNOW					14			/* freshly laid snow */
-#define S_MAT_ICE					15			/* packed snow/solid ice */
-#define S_MAT_FLESH					16			/* hung meat, corpses in the world */
-#define S_MAT_MUD					17			/* wet soil */
-#define S_MAT_BPGLASS				18			/* bulletproof glass */
-#define S_MAT_DRYLEAVES				19			/* dried up leaves on the floor */
-#define S_MAT_GREENLEAVES			20			/* fresh leaves still on a tree */
-#define S_MAT_FABRIC				21			/* Cotton sheets */
-#define S_MAT_CANVAS				22			/* tent material */
-#define S_MAT_ROCK					23
-#define S_MAT_RUBBER				24			/* hard tire like rubber */
-#define S_MAT_PLASTIC				25
-#define S_MAT_TILES					26			/* tiled floor */
-#define S_MAT_CARPET				27			/* lush carpet */
-#define S_MAT_PLASTER				28			/* drywall style plaster */
-#define S_MAT_SHATTERGLASS			29			/* glass with the Crisis Zone style shattering */
-#define S_MAT_ARMOR					30			/* body armor */
-#define S_MAT_COMPUTER				31			/* computers/electronic equipment */
-#define S_MAT_LAST					32			/* number of materials */
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"sof2",					/* -game x */
-	"base",					/* default base game data dir */
-	".sof2",				/* unix home sub-dir */
-	"soldier",				/* magic path word */
-	"shaders",				/* shader directory */
-	qfalse,					/* wolf lighting model? */
-	qtrue,					/* flares */
-	"gfx/misc/lens_flare",	/* default flare shader */
-	"RBSP",					/* bsp file prefix */
-	1,						/* bsp file version */
-	LoadRBSPFile,			/* bsp load function */
-	WriteRBSPFile,			/* bsp write function */
-	
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		S_CONT_SOLID | S_CONT_OPAQUE,	-1,						0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			0,							S_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		S_CONT_TRANSLUCENT,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			S_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			S_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		0,							0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							0,							0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							S_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							0,							0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							0,							0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							S_CONT_SOLID,				0,							0,							0,							C_SOLID },
-		{ "nonopaque",		0,							S_CONT_OPAQUE,				0,							0,							C_TRANSLUCENT,				0 },		/* setting trans ok? */
-		
-		{ "trigger",		S_CONT_TRIGGER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			S_CONT_WATER,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slime",			S_CONT_SLIME,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			S_CONT_LAVA,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-
-		{ "shotclip",		S_CONT_SHOTCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* setting trans/detail ok? */
-		{ "playerclip",		S_CONT_PLAYERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	S_CONT_MONSTERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			S_CONT_NODROP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "terrain",		S_CONT_TERRAIN,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "ladder",			S_CONT_LADDER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "abseil",			S_CONT_ABSEIL,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "outside",		S_CONT_OUTSIDE,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "botclip",		S_CONT_BOTCLIP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "fog",			S_CONT_FOG,					S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_FOG | C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* nonopaque? */
-		{ "sky",			0,							0,							S_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							S_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							S_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							S_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "nodamage",		0,							0,							S_SURF_NODAMAGE,			0,							0,							0 },
-		{ "metalsteps",		0,							0,							S_SURF_METALSTEPS,			0,							0,							0 },
-		{ "nosteps",		0,							0,							S_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							S_SURF_NODLIGHT,			0,							0,							0 },
-		{ "nomiscents",		0,							0,							S_SURF_NOMISCENTS,			0,							0,							0 },
-		{ "forcefield",		0,							0,							S_SURF_FORCEFIELD,			0,							0,							0 },
-		
-		
-		/* materials */
-		{ "*mat_none",		0,							0,							S_MAT_NONE,					S_MAT_MASK,					0,							0 },
-		{ "*mat_solidwood",	0,							0,							S_MAT_SOLIDWOOD,			S_MAT_MASK,					0,							0 },
-		{ "*mat_hollowwood",	0,						0,							S_MAT_HOLLOWWOOD,			S_MAT_MASK,					0,							0 },
-		{ "*mat_solidmetal",	0,						0,							S_MAT_SOLIDMETAL,			S_MAT_MASK,					0,							0 },
-		{ "*mat_hollowmetal",	0,						0,							S_MAT_HOLLOWMETAL,			S_MAT_MASK,					0,							0 },
-		{ "*mat_shortgrass",	0,						0,							S_MAT_SHORTGRASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_longgrass",		0,						0,							S_MAT_LONGGRASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_dirt",		0,							0,							S_MAT_DIRT,					S_MAT_MASK,					0,							0 },
-		{ "*mat_sand",		0,							0,							S_MAT_SAND,					S_MAT_MASK,					0,							0 },
-		{ "*mat_gravel",	0,							0,							S_MAT_GRAVEL,				S_MAT_MASK,					0,							0 },
-		{ "*mat_glass",		0,							0,							S_MAT_GLASS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_concrete",	0,							0,							S_MAT_CONCRETE,				S_MAT_MASK,					0,							0 },
-		{ "*mat_marble",	0,							0,							S_MAT_MARBLE,				S_MAT_MASK,					0,							0 },
-		{ "*mat_water",		0,							0,							S_MAT_WATER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_snow",		0,							0,							S_MAT_SNOW,					S_MAT_MASK,					0,							0 },
-		{ "*mat_ice",		0,							0,							S_MAT_ICE,					S_MAT_MASK,					0,							0 },
-		{ "*mat_flesh",		0,							0,							S_MAT_FLESH,				S_MAT_MASK,					0,							0 },
-		{ "*mat_mud",		0,							0,							S_MAT_MUD,					S_MAT_MASK,					0,							0 },
-		{ "*mat_bpglass",	0,							0,							S_MAT_BPGLASS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_dryleaves",	0,							0,							S_MAT_DRYLEAVES,			S_MAT_MASK,					0,							0 },
-		{ "*mat_greenleaves",	0,						0,							S_MAT_GREENLEAVES,			S_MAT_MASK,					0,							0 },
-		{ "*mat_fabric",	0,							0,							S_MAT_FABRIC,				S_MAT_MASK,					0,							0 },
-		{ "*mat_canvas",	0,							0,							S_MAT_CANVAS,				S_MAT_MASK,					0,							0 },
-		{ "*mat_rock",		0,							0,							S_MAT_ROCK,					S_MAT_MASK,					0,							0 },
-		{ "*mat_rubber",	0,							0,							S_MAT_RUBBER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_plastic",	0,							0,							S_MAT_PLASTIC,				S_MAT_MASK,					0,							0 },
-		{ "*mat_tiles",		0,							0,							S_MAT_TILES,				S_MAT_MASK,					0,							0 },
-		{ "*mat_carpet",	0,							0,							S_MAT_CARPET,				S_MAT_MASK,					0,							0 },
-		{ "*mat_plaster",	0,							0,							S_MAT_PLASTER,				S_MAT_MASK,					0,							0 },
-		{ "*mat_shatterglass",	0,						0,							S_MAT_SHATTERGLASS,			S_MAT_MASK,					0,							0 },
-		{ "*mat_armor",		0,							0,							S_MAT_ARMOR,				S_MAT_MASK,					0,							0 },
-		{ "*mat_computer",	0,							0,							S_MAT_COMPUTER,				S_MAT_MASK,					0,							0 },	
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_SOF2_H
+#define GAME_SOF2_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* thanks to the gracious fellows at raven */
+#define	S_CONT_SOLID				0x00000001	/* Default setting. An eye is never valid in a solid */
+#define	S_CONT_LAVA					0x00000002
+#define	S_CONT_WATER				0x00000004
+#define	S_CONT_FOG					0x00000008
+#define	S_CONT_PLAYERCLIP			0x00000010
+#define	S_CONT_MONSTERCLIP			0x00000020
+#define S_CONT_BOTCLIP				0x00000040
+#define S_CONT_SHOTCLIP				0x00000080
+#define	S_CONT_BODY					0x00000100	/* should never be on a brush, only in game */
+#define	S_CONT_CORPSE				0x00000200	/* should never be on a brush, only in game */
+#define	S_CONT_TRIGGER				0x00000400
+#define	S_CONT_NODROP				0x00000800	/* don't leave bodies or items (death fog, lava) */
+#define S_CONT_TERRAIN				0x00001000	/* volume contains terrain data */
+#define S_CONT_LADDER				0x00002000
+#define S_CONT_ABSEIL				0x00004000  /* used like ladder to define where an NPC can abseil */
+#define S_CONT_OPAQUE				0x00008000	/* defaults to on, when off, solid can be seen through */
+#define S_CONT_OUTSIDE				0x00010000	/* volume is considered to be in the outside (i.e. not indoors) */
+#define S_CONT_SLIME				0x00020000	/* don't be fooled. it may SAY "slime" but it really means "projectileclip" */
+#define S_CONT_LIGHTSABER			0x00040000
+#define S_CONT_TELEPORTER			0x00080000
+#define S_CONT_ITEM					0x00100000
+#define	S_CONT_DETAIL				0x08000000	/* brushes not used for the bsp */
+#define	S_CONT_TRANSLUCENT			0x80000000	/* don't consume surface fragments inside */
+
+#define	S_SURF_SKY					0x00002000	/* lighting from environment map */
+#define	S_SURF_SLICK				0x00004000	/* affects game physics */
+#define	S_SURF_METALSTEPS			0x00008000	/* chc needs this since we use same tools */
+#define S_SURF_FORCEFIELD			0x00010000	/* chc */
+#define	S_SURF_NODAMAGE				0x00040000	/* never give falling damage */
+#define	S_SURF_NOIMPACT				0x00080000	/* don't make missile explosions */
+#define	S_SURF_NOMARKS				0x00100000	/* don't leave missile marks */
+#define	S_SURF_NODRAW				0x00200000	/* don't generate a drawsurface at all */
+#define	S_SURF_NOSTEPS				0x00400000	/* no footstep sounds */
+#define	S_SURF_NODLIGHT				0x00800000	/* don't dlight even if solid (solid lava, skies) */
+#define	S_SURF_NOMISCENTS			0x01000000	/* no client models allowed on this surface */
+
+#define S_SURF_PATCH				0x80000000	/* mark this face as a patch(editor only) */
+
+/* materials */
+#define S_MAT_BITS					5
+#define S_MAT_MASK					0x1f		/* mask to get the material type */
+
+#define S_MAT_NONE					0			/* for when the artist hasn't set anything up =) */
+#define S_MAT_SOLIDWOOD				1			/* freshly cut timber */
+#define S_MAT_HOLLOWWOOD			2			/* termite infested creaky wood */
+#define S_MAT_SOLIDMETAL			3			/* solid girders */
+#define S_MAT_HOLLOWMETAL			4			/* hollow metal machines */
+#define S_MAT_SHORTGRASS			5			/* manicured lawn */
+#define S_MAT_LONGGRASS				6			/* long jungle grass */
+#define S_MAT_DIRT					7			/* hard mud */
+#define S_MAT_SAND					8			/* sandy beach */
+#define S_MAT_GRAVEL				9			/* lots of small stones */
+#define S_MAT_GLASS					10
+#define S_MAT_CONCRETE				11			/* hardened concrete pavement */
+#define S_MAT_MARBLE				12			/* marble floors */
+#define S_MAT_WATER					13			/* light covering of water on a surface */
+#define S_MAT_SNOW					14			/* freshly laid snow */
+#define S_MAT_ICE					15			/* packed snow/solid ice */
+#define S_MAT_FLESH					16			/* hung meat, corpses in the world */
+#define S_MAT_MUD					17			/* wet soil */
+#define S_MAT_BPGLASS				18			/* bulletproof glass */
+#define S_MAT_DRYLEAVES				19			/* dried up leaves on the floor */
+#define S_MAT_GREENLEAVES			20			/* fresh leaves still on a tree */
+#define S_MAT_FABRIC				21			/* Cotton sheets */
+#define S_MAT_CANVAS				22			/* tent material */
+#define S_MAT_ROCK					23
+#define S_MAT_RUBBER				24			/* hard tire like rubber */
+#define S_MAT_PLASTIC				25
+#define S_MAT_TILES					26			/* tiled floor */
+#define S_MAT_CARPET				27			/* lush carpet */
+#define S_MAT_PLASTER				28			/* drywall style plaster */
+#define S_MAT_SHATTERGLASS			29			/* glass with the Crisis Zone style shattering */
+#define S_MAT_ARMOR					30			/* body armor */
+#define S_MAT_COMPUTER				31			/* computers/electronic equipment */
+#define S_MAT_LAST					32			/* number of materials */
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"sof2",					/* -game x */
+	"base",					/* default base game data dir */
+	".sof2",				/* unix home sub-dir */
+	"soldier",				/* magic path word */
+	"shaders",				/* shader directory */
+	qfalse,					/* wolf lighting model? */
+	qtrue,					/* flares */
+	"gfx/misc/lens_flare",	/* default flare shader */
+	"RBSP",					/* bsp file prefix */
+	1,						/* bsp file version */
+	LoadRBSPFile,			/* bsp load function */
+	WriteRBSPFile,			/* bsp write function */
+	
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		S_CONT_SOLID | S_CONT_OPAQUE,	-1,						0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			0,							S_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		S_CONT_TRANSLUCENT,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			S_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			S_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		0,							0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							0,							0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							S_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							0,							0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							0,							0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							0,							0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							S_CONT_SOLID,				0,							0,							0,							C_SOLID },
+		{ "nonopaque",		0,							S_CONT_OPAQUE,				0,							0,							C_TRANSLUCENT,				0 },		/* setting trans ok? */
+		
+		{ "trigger",		S_CONT_TRIGGER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			S_CONT_WATER,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slime",			S_CONT_SLIME,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			S_CONT_LAVA,				S_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+
+		{ "shotclip",		S_CONT_SHOTCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* setting trans/detail ok? */
+		{ "playerclip",		S_CONT_PLAYERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	S_CONT_MONSTERCLIP,			S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			S_CONT_NODROP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "terrain",		S_CONT_TERRAIN,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "ladder",			S_CONT_LADDER,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "abseil",			S_CONT_ABSEIL,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "outside",		S_CONT_OUTSIDE,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "botclip",		S_CONT_BOTCLIP,				S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "fog",			S_CONT_FOG,					S_CONT_SOLID | S_CONT_OPAQUE,	0,						0,							C_FOG | C_DETAIL | C_TRANSLUCENT,	C_SOLID },	/* nonopaque? */
+		{ "sky",			0,							0,							S_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							S_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							S_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							S_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "nodamage",		0,							0,							S_SURF_NODAMAGE,			0,							0,							0 },
+		{ "metalsteps",		0,							0,							S_SURF_METALSTEPS,			0,							0,							0 },
+		{ "nosteps",		0,							0,							S_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							S_SURF_NODLIGHT,			0,							0,							0 },
+		{ "nomiscents",		0,							0,							S_SURF_NOMISCENTS,			0,							0,							0 },
+		{ "forcefield",		0,							0,							S_SURF_FORCEFIELD,			0,							0,							0 },
+		
+		
+		/* materials */
+		{ "*mat_none",		0,							0,							S_MAT_NONE,					S_MAT_MASK,					0,							0 },
+		{ "*mat_solidwood",	0,							0,							S_MAT_SOLIDWOOD,			S_MAT_MASK,					0,							0 },
+		{ "*mat_hollowwood",	0,						0,							S_MAT_HOLLOWWOOD,			S_MAT_MASK,					0,							0 },
+		{ "*mat_solidmetal",	0,						0,							S_MAT_SOLIDMETAL,			S_MAT_MASK,					0,							0 },
+		{ "*mat_hollowmetal",	0,						0,							S_MAT_HOLLOWMETAL,			S_MAT_MASK,					0,							0 },
+		{ "*mat_shortgrass",	0,						0,							S_MAT_SHORTGRASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_longgrass",		0,						0,							S_MAT_LONGGRASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_dirt",		0,							0,							S_MAT_DIRT,					S_MAT_MASK,					0,							0 },
+		{ "*mat_sand",		0,							0,							S_MAT_SAND,					S_MAT_MASK,					0,							0 },
+		{ "*mat_gravel",	0,							0,							S_MAT_GRAVEL,				S_MAT_MASK,					0,							0 },
+		{ "*mat_glass",		0,							0,							S_MAT_GLASS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_concrete",	0,							0,							S_MAT_CONCRETE,				S_MAT_MASK,					0,							0 },
+		{ "*mat_marble",	0,							0,							S_MAT_MARBLE,				S_MAT_MASK,					0,							0 },
+		{ "*mat_water",		0,							0,							S_MAT_WATER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_snow",		0,							0,							S_MAT_SNOW,					S_MAT_MASK,					0,							0 },
+		{ "*mat_ice",		0,							0,							S_MAT_ICE,					S_MAT_MASK,					0,							0 },
+		{ "*mat_flesh",		0,							0,							S_MAT_FLESH,				S_MAT_MASK,					0,							0 },
+		{ "*mat_mud",		0,							0,							S_MAT_MUD,					S_MAT_MASK,					0,							0 },
+		{ "*mat_bpglass",	0,							0,							S_MAT_BPGLASS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_dryleaves",	0,							0,							S_MAT_DRYLEAVES,			S_MAT_MASK,					0,							0 },
+		{ "*mat_greenleaves",	0,						0,							S_MAT_GREENLEAVES,			S_MAT_MASK,					0,							0 },
+		{ "*mat_fabric",	0,							0,							S_MAT_FABRIC,				S_MAT_MASK,					0,							0 },
+		{ "*mat_canvas",	0,							0,							S_MAT_CANVAS,				S_MAT_MASK,					0,							0 },
+		{ "*mat_rock",		0,							0,							S_MAT_ROCK,					S_MAT_MASK,					0,							0 },
+		{ "*mat_rubber",	0,							0,							S_MAT_RUBBER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_plastic",	0,							0,							S_MAT_PLASTIC,				S_MAT_MASK,					0,							0 },
+		{ "*mat_tiles",		0,							0,							S_MAT_TILES,				S_MAT_MASK,					0,							0 },
+		{ "*mat_carpet",	0,							0,							S_MAT_CARPET,				S_MAT_MASK,					0,							0 },
+		{ "*mat_plaster",	0,							0,							S_MAT_PLASTER,				S_MAT_MASK,					0,							0 },
+		{ "*mat_shatterglass",	0,						0,							S_MAT_SHATTERGLASS,			S_MAT_MASK,					0,							0 },
+		{ "*mat_armor",		0,							0,							S_MAT_ARMOR,				S_MAT_MASK,					0,							0 },
+		{ "*mat_computer",	0,							0,							S_MAT_COMPUTER,				S_MAT_MASK,					0,							0 },	
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
diff --git a/tools/quake3/q3map2/game_t.h b/tools/quake3/q3map2/game_t.h
index 319b1f78..5eec9063 100644
--- a/tools/quake3/q3map2/game_t.h
+++ b/tools/quake3/q3map2/game_t.h
@@ -1,34 +1,34 @@
-
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-/* ydnar: for -game support */
-typedef struct game_s
-{
-	char		*arg;			/* -game matches this */
-	char		*gamePath;		/* main game data dir */
-	char		*homeBasePath;	/* home sub-dir on unix */
-	char		*magic;			/* magic word for figuring out base path */
-	qboolean	wolfLight;		/* when true, lights work like wolf q3map  */
-	int			bspVersion;		/* BSP version to use */
-}
-game_t;
-
+
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+/* ydnar: for -game support */
+typedef struct game_s
+{
+	char		*arg;			/* -game matches this */
+	char		*gamePath;		/* main game data dir */
+	char		*homeBasePath;	/* home sub-dir on unix */
+	char		*magic;			/* magic word for figuring out base path */
+	qboolean	wolfLight;		/* when true, lights work like wolf q3map  */
+	int			bspVersion;		/* BSP version to use */
+}
+game_t;
+
diff --git a/tools/quake3/q3map2/game_tenebrae.h b/tools/quake3/q3map2/game_tenebrae.h
index bfa2f031..a639288f 100644
--- a/tools/quake3/q3map2/game_tenebrae.h
+++ b/tools/quake3/q3map2/game_tenebrae.h
@@ -1,184 +1,184 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_TENEBRAE_H
-#define GAME_TENEBRAE_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* game flags */
-#define T_CONT_SOLID				1			/* an eye is never valid in a solid */
-#define T_CONT_LAVA					8
-#define T_CONT_SLIME				16
-#define T_CONT_WATER				32
-#define T_CONT_FOG					64
-
-#define T_CONT_AREAPORTAL			0x8000
-
-#define T_CONT_PLAYERCLIP			0x10000
-#define T_CONT_MONSTERCLIP			0x20000
-#define T_CONT_TELEPORTER			0x40000
-#define T_CONT_JUMPPAD				0x80000
-#define T_CONT_CLUSTERPORTAL		0x100000
-#define T_CONT_DONOTENTER			0x200000
-#define T_CONT_BOTCLIP				0x400000
-
-#define T_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
-
-#define T_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
-#define T_CONT_CORPSE				0x4000000
-#define T_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
-#define T_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
-#define T_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
-#define T_CONT_TRIGGER				0x40000000
-#define T_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
-
-#define T_SURF_NODAMAGE				0x1			/* never give falling damage */
-#define T_SURF_SLICK				0x2			/* effects game physics */
-#define T_SURF_SKY					0x4			/* lighting from environment map */
-#define T_SURF_LADDER				0x8
-#define T_SURF_NOIMPACT				0x10		/* don't make missile explosions */
-#define T_SURF_NOMARKS				0x20		/* don't leave missile marks */
-#define T_SURF_FLESH				0x40		/* make flesh sounds and effects */
-#define T_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
-#define T_SURF_HINT					0x100		/* make a primary bsp splitter */
-#define T_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
-#define T_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
-#define T_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
-#define T_SURF_METALSTEPS			0x1000		/* clanking footsteps */
-#define T_SURF_NOSTEPS				0x2000		/* no footstep sounds */
-#define T_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
-#define T_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
-#define T_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
-#define T_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
-#define T_SURF_DUST					0x40000		/* leave a dust trail when walking on this surface */
-
-/* ydnar flags */
-#define T_SURF_VERTEXLIT			(T_SURF_POINTLIGHT | T_SURF_NOLIGHTMAP)
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"tenebrae",			/* -game x */
-	"base",				/* default base game data dir */
-	".tenebrae",		/* unix home sub-dir */
-	"tenebrae",			/* magic path word */
-	"scripts",			/* shader directory */
-	qfalse,				/* wolf lighting model? */
-	qfalse,				/* flares */
-	"flareshader",		/* default flare shader */
-	"IBSP",				/* bsp file prefix */
-	46,					/* bsp file version */
-	LoadIBSPFile,		/* bsp load function */
-	WriteIBSPFile,		/* bsp write function */
-
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		T_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			T_CONT_ORIGIN,				T_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		T_CONT_AREAPORTAL,			T_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			T_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			T_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		T_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							T_SURF_HINT,				0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							T_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							T_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							T_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							T_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							T_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							T_CONT_SOLID,				T_SURF_NONSOLID,			0,							0,							C_SOLID },
-		
-		{ "trigger",		T_CONT_TRIGGER,				T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			T_CONT_WATER,				T_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slime",			T_CONT_SLIME,				T_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			T_CONT_LAVA,				T_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "playerclip",		T_CONT_PLAYERCLIP,			T_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	T_CONT_MONSTERCLIP,			T_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			T_CONT_NODROP,				T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "clusterportal",	T_CONT_CLUSTERPORTAL,		T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "donotenter",		T_CONT_DONOTENTER,			T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "botclip",		T_CONT_BOTCLIP,				T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "fog",			T_CONT_FOG,					T_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
-		{ "sky",			0,							0,							T_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							T_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							T_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							T_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "ladder",			0,							0,							T_SURF_LADDER,				0,							0,							0 },
-		{ "nodamage",		0,							0,							T_SURF_NODAMAGE,			0,							0,							0 },
-		{ "metalsteps",		0,							0,							T_SURF_METALSTEPS,			0,							0,							0 },
-		{ "flesh",			0,							0,							T_SURF_FLESH,				0,							0,							0 },
-		{ "nosteps",		0,							0,							T_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							T_SURF_NODLIGHT,			0,							0,							0 },
-		{ "dust",			0,							0,							T_SURF_DUST,				0,							0,							0 },
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_TENEBRAE_H
+#define GAME_TENEBRAE_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* game flags */
+#define T_CONT_SOLID				1			/* an eye is never valid in a solid */
+#define T_CONT_LAVA					8
+#define T_CONT_SLIME				16
+#define T_CONT_WATER				32
+#define T_CONT_FOG					64
+
+#define T_CONT_AREAPORTAL			0x8000
+
+#define T_CONT_PLAYERCLIP			0x10000
+#define T_CONT_MONSTERCLIP			0x20000
+#define T_CONT_TELEPORTER			0x40000
+#define T_CONT_JUMPPAD				0x80000
+#define T_CONT_CLUSTERPORTAL		0x100000
+#define T_CONT_DONOTENTER			0x200000
+#define T_CONT_BOTCLIP				0x400000
+
+#define T_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
+
+#define T_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
+#define T_CONT_CORPSE				0x4000000
+#define T_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
+#define T_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
+#define T_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
+#define T_CONT_TRIGGER				0x40000000
+#define T_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
+
+#define T_SURF_NODAMAGE				0x1			/* never give falling damage */
+#define T_SURF_SLICK				0x2			/* effects game physics */
+#define T_SURF_SKY					0x4			/* lighting from environment map */
+#define T_SURF_LADDER				0x8
+#define T_SURF_NOIMPACT				0x10		/* don't make missile explosions */
+#define T_SURF_NOMARKS				0x20		/* don't leave missile marks */
+#define T_SURF_FLESH				0x40		/* make flesh sounds and effects */
+#define T_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
+#define T_SURF_HINT					0x100		/* make a primary bsp splitter */
+#define T_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
+#define T_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
+#define T_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
+#define T_SURF_METALSTEPS			0x1000		/* clanking footsteps */
+#define T_SURF_NOSTEPS				0x2000		/* no footstep sounds */
+#define T_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
+#define T_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
+#define T_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
+#define T_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
+#define T_SURF_DUST					0x40000		/* leave a dust trail when walking on this surface */
+
+/* ydnar flags */
+#define T_SURF_VERTEXLIT			(T_SURF_POINTLIGHT | T_SURF_NOLIGHTMAP)
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"tenebrae",			/* -game x */
+	"base",				/* default base game data dir */
+	".tenebrae",		/* unix home sub-dir */
+	"tenebrae",			/* magic path word */
+	"scripts",			/* shader directory */
+	qfalse,				/* wolf lighting model? */
+	qfalse,				/* flares */
+	"flareshader",		/* default flare shader */
+	"IBSP",				/* bsp file prefix */
+	46,					/* bsp file version */
+	LoadIBSPFile,		/* bsp load function */
+	WriteIBSPFile,		/* bsp write function */
+
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		T_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			T_CONT_ORIGIN,				T_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		T_CONT_AREAPORTAL,			T_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			T_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			T_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		T_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							T_SURF_HINT,				0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							T_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							T_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							T_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							T_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							T_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							T_CONT_SOLID,				T_SURF_NONSOLID,			0,							0,							C_SOLID },
+		
+		{ "trigger",		T_CONT_TRIGGER,				T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			T_CONT_WATER,				T_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slime",			T_CONT_SLIME,				T_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			T_CONT_LAVA,				T_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "playerclip",		T_CONT_PLAYERCLIP,			T_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	T_CONT_MONSTERCLIP,			T_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			T_CONT_NODROP,				T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "clusterportal",	T_CONT_CLUSTERPORTAL,		T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "donotenter",		T_CONT_DONOTENTER,			T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "botclip",		T_CONT_BOTCLIP,				T_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "fog",			T_CONT_FOG,					T_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
+		{ "sky",			0,							0,							T_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							T_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							T_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							T_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "ladder",			0,							0,							T_SURF_LADDER,				0,							0,							0 },
+		{ "nodamage",		0,							0,							T_SURF_NODAMAGE,			0,							0,							0 },
+		{ "metalsteps",		0,							0,							T_SURF_METALSTEPS,			0,							0,							0 },
+		{ "flesh",			0,							0,							T_SURF_FLESH,				0,							0,							0 },
+		{ "nosteps",		0,							0,							T_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							T_SURF_NODLIGHT,			0,							0,							0 },
+		{ "dust",			0,							0,							T_SURF_DUST,				0,							0,							0 },
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
+
diff --git a/tools/quake3/q3map2/game_wolf.h b/tools/quake3/q3map2/game_wolf.h
index b1184a3e..0e882868 100644
--- a/tools/quake3/q3map2/game_wolf.h
+++ b/tools/quake3/q3map2/game_wolf.h
@@ -1,230 +1,230 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_WOLF_H
-#define GAME_WOLF_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* game flags */
-#define W_CONT_SOLID				1			/* an eye is never valid in a solid */
-#define W_CONT_LAVA					8
-#define W_CONT_SLIME				16
-#define W_CONT_WATER				32
-#define W_CONT_FOG					64
-
-#define	W_CONT_MISSILECLIP			0x80		/* wolf ranged missile blocking */
-#define W_CONT_ITEM					0x100		/* wolf item contents */
-#define	W_CONT_AI_NOSIGHT			0x1000		/* wolf ai sight blocking */
-#define	W_CONT_CLIPSHOT				0x2000		/* wolf shot clip */
-#define W_CONT_AREAPORTAL			0x8000
-
-#define W_CONT_PLAYERCLIP			0x10000
-#define W_CONT_MONSTERCLIP			0x20000
-#define W_CONT_TELEPORTER			0x40000
-#define W_CONT_JUMPPAD				0x80000
-#define W_CONT_CLUSTERPORTAL		0x100000
-#define W_CONT_DONOTENTER			0x200000
-#define W_CONT_DONOTENTER_LARGE		0x400000	/* wolf dne */
-
-#define W_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
-
-#define W_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
-#define W_CONT_CORPSE				0x4000000
-#define W_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
-#define W_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
-#define W_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
-#define W_CONT_TRIGGER				0x40000000
-#define W_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
-
-#define W_SURF_NODAMAGE				0x1			/* never give falling damage */
-#define W_SURF_SLICK				0x2			/* effects game physics */
-#define W_SURF_SKY					0x4			/* lighting from environment map */
-#define W_SURF_LADDER				0x8
-#define W_SURF_NOIMPACT				0x10		/* don't make missile explosions */
-#define W_SURF_NOMARKS				0x20		/* don't leave missile marks */
-#define W_SURF_CERAMIC				0x40		/* wolf ceramic material */
-#define W_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
-#define W_SURF_HINT					0x100		/* make a primary bsp splitter */
-#define W_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
-#define W_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
-#define W_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
-#define W_SURF_METAL				0x1000		/* wolf metal material */
-#define W_SURF_NOSTEPS				0x2000		/* no footstep sounds */
-#define W_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
-#define W_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
-#define W_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
-#define W_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
-#define W_SURF_WOOD					0x40000		/* wolf wood material */
-#define	W_SURF_GRASS				0x80000		/* wolf grass material */
-#define W_SURF_GRAVEL				0x100000	/* wolf gravel material */
-#define W_SURF_GLASS				0x200000	/* wolf glass material */
-#define W_SURF_SNOW					0x400000	/* wolf snow material */
-#define W_SURF_ROOF					0x800000	/* wolf roof material */
-#define	W_SURF_RUBBLE				0x1000000	/* wolf rubble material */
-#define	W_SURF_CARPET				0x2000000	/* wolf carpet material */
-
-#define W_SURF_MONSTERSLICK			0x4000000	/* wolf npc slick surface */
-#define W_SURF_MONSLICK_W			0x8000000	/* wolf slide bodies west */
-#define W_SURF_MONSLICK_N			0x10000000	/* wolf slide bodies north */
-#define W_SURF_MONSLICK_E			0x20000000	/* wolf slide bodies east */
-#define W_SURF_MONSLICK_S			0x40000000	/* wolf slide bodies south */
-
-/* ydnar flags */
-#define W_SURF_VERTEXLIT			(W_SURF_POINTLIGHT | W_SURF_NOLIGHTMAP)
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"wolf",				/* -game x */
-	"main",				/* default base game data dir */
-	".wolf",			/* unix home sub-dir */
-	"wolf",				/* magic path word */
-	"scripts",			/* shader directory */
-	qtrue,				/* wolf lighting model? */
-	qfalse,				/* flares */
-	"flareshader",		/* default flare shader */
-	"IBSP",				/* bsp file prefix */
-	47,					/* bsp file version */
-	LoadIBSPFile,		/* bsp load function */
-	WriteIBSPFile,		/* bsp write function */
-	
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		W_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			W_CONT_ORIGIN,				W_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		W_CONT_AREAPORTAL,			W_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			W_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			W_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		W_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							W_SURF_HINT,				0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							W_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							W_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							W_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							W_CONT_SOLID,				W_SURF_NONSOLID,			0,							0,							C_SOLID },
-		
-		{ "trigger",		W_CONT_TRIGGER,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			W_CONT_WATER,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slag",			W_CONT_SLIME,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			W_CONT_LAVA,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "playerclip",		W_CONT_PLAYERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	W_CONT_MONSTERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "clipmissile",	W_CONT_MISSILECLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "clipshot",		W_CONT_CLIPSHOT,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			W_CONT_NODROP,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "clusterportal",	W_CONT_CLUSTERPORTAL,		W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "donotenter",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "nonotenterlarge",W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "fog",			W_CONT_FOG,					W_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
-		{ "sky",			0,							0,							W_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							W_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							W_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							W_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "ladder",			0,							0,							W_SURF_LADDER,				0,							0,							0 },
-		{ "nodamage",		0,							0,							W_SURF_NODAMAGE,			0,							0,							0 },
-		{ "nosteps",		0,							0,							W_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							W_SURF_NODLIGHT,			0,							0,							0 },
-		
-		
-		/* materials */
-		{ "metal",			0,							0,							W_SURF_METAL,				0,							0,							0 },
-		{ "metalsteps",		0,							0,							W_SURF_METAL,				0,							0,							0 },
-		{ "glass",			0,							0,							W_SURF_GLASS,				0,							0,							0 },
-		{ "ceramic",		0,							0,							W_SURF_CERAMIC,				0,							0,							0 },
-		{ "woodsteps",		0,							0,							W_SURF_WOOD,				0,							0,							0 },
-		{ "grasssteps",		0,							0,							W_SURF_GRASS,				0,							0,							0 },
-		{ "gravelsteps",	0,							0,							W_SURF_GRAVEL,				0,							0,							0 },
-		{ "rubble",			0,							0,							W_SURF_RUBBLE,				0,							0,							0 },
-		{ "carpetsteps",	0,							0,							W_SURF_CARPET,				0,							0,							0 },
-		{ "snowsteps",		0,							0,							W_SURF_SNOW,				0,							0,							0 },
-		{ "roofsteps",		0,							0,							W_SURF_ROOF,				0,							0,							0 },
-		
-		
-		/* ai */
-		{ "ai_nosight",		W_CONT_AI_NOSIGHT,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		/* ydnar: experimental until bits are confirmed! */
-		{ "ai_nopass",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "ai_nopasslarge",	W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		
-		/* sliding bodies */
-		{ "monsterslick",	0,							0,							W_SURF_MONSTERSLICK,		0,							C_TRANSLUCENT,				0 },
-		{ "monsterslicknorth",	0,						0,							W_SURF_MONSLICK_N,			0,							C_TRANSLUCENT,				0 },
-		{ "monsterslickeast",	0,						0,							W_SURF_MONSLICK_E,			0,							C_TRANSLUCENT,				0 },
-		{ "monsterslicksouth",	0,						0,							W_SURF_MONSLICK_S,			0,							C_TRANSLUCENT,				0 },
-		{ "monsterslickwest",	0,						0,							W_SURF_MONSLICK_W,			0,							C_TRANSLUCENT,				0 },
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_WOLF_H
+#define GAME_WOLF_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* game flags */
+#define W_CONT_SOLID				1			/* an eye is never valid in a solid */
+#define W_CONT_LAVA					8
+#define W_CONT_SLIME				16
+#define W_CONT_WATER				32
+#define W_CONT_FOG					64
+
+#define	W_CONT_MISSILECLIP			0x80		/* wolf ranged missile blocking */
+#define W_CONT_ITEM					0x100		/* wolf item contents */
+#define	W_CONT_AI_NOSIGHT			0x1000		/* wolf ai sight blocking */
+#define	W_CONT_CLIPSHOT				0x2000		/* wolf shot clip */
+#define W_CONT_AREAPORTAL			0x8000
+
+#define W_CONT_PLAYERCLIP			0x10000
+#define W_CONT_MONSTERCLIP			0x20000
+#define W_CONT_TELEPORTER			0x40000
+#define W_CONT_JUMPPAD				0x80000
+#define W_CONT_CLUSTERPORTAL		0x100000
+#define W_CONT_DONOTENTER			0x200000
+#define W_CONT_DONOTENTER_LARGE		0x400000	/* wolf dne */
+
+#define W_CONT_ORIGIN				0x1000000	/* removed before bsping an entity */
+
+#define W_CONT_BODY					0x2000000	/* should never be on a brush, only in game */
+#define W_CONT_CORPSE				0x4000000
+#define W_CONT_DETAIL				0x8000000	/* brushes not used for the bsp */
+#define W_CONT_STRUCTURAL			0x10000000	/* brushes used for the bsp */
+#define W_CONT_TRANSLUCENT			0x20000000	/* don't consume surface fragments inside */
+#define W_CONT_TRIGGER				0x40000000
+#define W_CONT_NODROP				0x80000000	/* don't leave bodies or items (death fog, lava) */
+
+#define W_SURF_NODAMAGE				0x1			/* never give falling damage */
+#define W_SURF_SLICK				0x2			/* effects game physics */
+#define W_SURF_SKY					0x4			/* lighting from environment map */
+#define W_SURF_LADDER				0x8
+#define W_SURF_NOIMPACT				0x10		/* don't make missile explosions */
+#define W_SURF_NOMARKS				0x20		/* don't leave missile marks */
+#define W_SURF_CERAMIC				0x40		/* wolf ceramic material */
+#define W_SURF_NODRAW				0x80		/* don't generate a drawsurface at all */
+#define W_SURF_HINT					0x100		/* make a primary bsp splitter */
+#define W_SURF_SKIP					0x200		/* completely ignore, allowing non-closed brushes */
+#define W_SURF_NOLIGHTMAP			0x400		/* surface doesn't need a lightmap */
+#define W_SURF_POINTLIGHT			0x800		/* generate lighting info at vertexes */
+#define W_SURF_METAL				0x1000		/* wolf metal material */
+#define W_SURF_NOSTEPS				0x2000		/* no footstep sounds */
+#define W_SURF_NONSOLID				0x4000		/* don't collide against curves with this set */
+#define W_SURF_LIGHTFILTER			0x8000		/* act as a light filter during q3map -light */
+#define W_SURF_ALPHASHADOW			0x10000		/* do per-pixel light shadow casting in q3map */
+#define W_SURF_NODLIGHT				0x20000		/* don't dlight even if solid (solid lava, skies) */
+#define W_SURF_WOOD					0x40000		/* wolf wood material */
+#define	W_SURF_GRASS				0x80000		/* wolf grass material */
+#define W_SURF_GRAVEL				0x100000	/* wolf gravel material */
+#define W_SURF_GLASS				0x200000	/* wolf glass material */
+#define W_SURF_SNOW					0x400000	/* wolf snow material */
+#define W_SURF_ROOF					0x800000	/* wolf roof material */
+#define	W_SURF_RUBBLE				0x1000000	/* wolf rubble material */
+#define	W_SURF_CARPET				0x2000000	/* wolf carpet material */
+
+#define W_SURF_MONSTERSLICK			0x4000000	/* wolf npc slick surface */
+#define W_SURF_MONSLICK_W			0x8000000	/* wolf slide bodies west */
+#define W_SURF_MONSLICK_N			0x10000000	/* wolf slide bodies north */
+#define W_SURF_MONSLICK_E			0x20000000	/* wolf slide bodies east */
+#define W_SURF_MONSLICK_S			0x40000000	/* wolf slide bodies south */
+
+/* ydnar flags */
+#define W_SURF_VERTEXLIT			(W_SURF_POINTLIGHT | W_SURF_NOLIGHTMAP)
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"wolf",				/* -game x */
+	"main",				/* default base game data dir */
+	".wolf",			/* unix home sub-dir */
+	"wolf",				/* magic path word */
+	"scripts",			/* shader directory */
+	qtrue,				/* wolf lighting model? */
+	qfalse,				/* flares */
+	"flareshader",		/* default flare shader */
+	"IBSP",				/* bsp file prefix */
+	47,					/* bsp file version */
+	LoadIBSPFile,		/* bsp load function */
+	WriteIBSPFile,		/* bsp write function */
+	
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		W_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			W_CONT_ORIGIN,				W_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		W_CONT_AREAPORTAL,			W_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			W_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			W_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		W_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							W_SURF_HINT,				0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							W_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							W_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							W_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							W_CONT_SOLID,				W_SURF_NONSOLID,			0,							0,							C_SOLID },
+		
+		{ "trigger",		W_CONT_TRIGGER,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			W_CONT_WATER,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slag",			W_CONT_SLIME,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			W_CONT_LAVA,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "playerclip",		W_CONT_PLAYERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	W_CONT_MONSTERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "clipmissile",	W_CONT_MISSILECLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "clipshot",		W_CONT_CLIPSHOT,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			W_CONT_NODROP,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "clusterportal",	W_CONT_CLUSTERPORTAL,		W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "donotenter",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "nonotenterlarge",W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "fog",			W_CONT_FOG,					W_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
+		{ "sky",			0,							0,							W_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							W_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							W_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							W_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "ladder",			0,							0,							W_SURF_LADDER,				0,							0,							0 },
+		{ "nodamage",		0,							0,							W_SURF_NODAMAGE,			0,							0,							0 },
+		{ "nosteps",		0,							0,							W_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							W_SURF_NODLIGHT,			0,							0,							0 },
+		
+		
+		/* materials */
+		{ "metal",			0,							0,							W_SURF_METAL,				0,							0,							0 },
+		{ "metalsteps",		0,							0,							W_SURF_METAL,				0,							0,							0 },
+		{ "glass",			0,							0,							W_SURF_GLASS,				0,							0,							0 },
+		{ "ceramic",		0,							0,							W_SURF_CERAMIC,				0,							0,							0 },
+		{ "woodsteps",		0,							0,							W_SURF_WOOD,				0,							0,							0 },
+		{ "grasssteps",		0,							0,							W_SURF_GRASS,				0,							0,							0 },
+		{ "gravelsteps",	0,							0,							W_SURF_GRAVEL,				0,							0,							0 },
+		{ "rubble",			0,							0,							W_SURF_RUBBLE,				0,							0,							0 },
+		{ "carpetsteps",	0,							0,							W_SURF_CARPET,				0,							0,							0 },
+		{ "snowsteps",		0,							0,							W_SURF_SNOW,				0,							0,							0 },
+		{ "roofsteps",		0,							0,							W_SURF_ROOF,				0,							0,							0 },
+		
+		
+		/* ai */
+		{ "ai_nosight",		W_CONT_AI_NOSIGHT,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		/* ydnar: experimental until bits are confirmed! */
+		{ "ai_nopass",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "ai_nopasslarge",	W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		
+		/* sliding bodies */
+		{ "monsterslick",	0,							0,							W_SURF_MONSTERSLICK,		0,							C_TRANSLUCENT,				0 },
+		{ "monsterslicknorth",	0,						0,							W_SURF_MONSLICK_N,			0,							C_TRANSLUCENT,				0 },
+		{ "monsterslickeast",	0,						0,							W_SURF_MONSLICK_E,			0,							C_TRANSLUCENT,				0 },
+		{ "monsterslicksouth",	0,						0,							W_SURF_MONSLICK_S,			0,							C_TRANSLUCENT,				0 },
+		{ "monsterslickwest",	0,						0,							W_SURF_MONSLICK_W,			0,							C_TRANSLUCENT,				0 },
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
+
diff --git a/tools/quake3/q3map2/game_wolfet.h b/tools/quake3/q3map2/game_wolfet.h
index 080e7fc9..fdc5b7e8 100644
--- a/tools/quake3/q3map2/game_wolfet.h
+++ b/tools/quake3/q3map2/game_wolfet.h
@@ -1,169 +1,169 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-Support for Wolfenstein: Enemy Territory by ydnar@splashdamage.com
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef GAME_WOLFET_H
-#define GAME_WOLFET_H
-
-
-
-/* -------------------------------------------------------------------------------
-
-content and surface flags
-
-------------------------------------------------------------------------------- */
-
-/* this file must be included *after* game_wolf.h because it shares defines! */
-
-#define W_SURF_SPLASH				0x00000040	/* enemy territory water splash surface */
-#define W_SURF_LANDMINE				0x80000000	/* enemy territory 'landminable' surface */
-
-
-
-/* -------------------------------------------------------------------------------
-
-game_t struct
-
-------------------------------------------------------------------------------- */
-
-{
-	"et",				/* -game x */
-	"etmain",			/* default base game data dir */
-	".etwolf",			/* unix home sub-dir */
-	"et",				/* magic path word */
-	"scripts",			/* shader directory */
-	qtrue,				/* wolf lighting model? */
-	qfalse,				/* flares */
-	"flareshader",		/* default flare shader */
-	"IBSP",				/* bsp file prefix */
-	47,					/* bsp file version */
-	LoadIBSPFile,		/* bsp load function */
-	WriteIBSPFile,		/* bsp write function */
-	
-	{
-		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
-		
-		/* default */
-		{ "default",		W_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
-		
-		
-		/* ydnar */
-		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
-		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
-		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
-		
-		
-		/* compiler */
-		{ "origin",			W_CONT_ORIGIN,				W_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
-		{ "areaportal",		W_CONT_AREAPORTAL,			W_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
-		{ "trans",			W_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
-		{ "detail",			W_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
-		{ "structural",		W_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
-		{ "hint",			0,							0,							W_SURF_HINT,				0,							C_HINT,						0 },
-		{ "nodraw",			0,							0,							W_SURF_NODRAW,				0,							C_NODRAW,					0 },
-		
-		{ "alphashadow",	0,							0,							W_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
-		{ "lightfilter",	0,							0,							W_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
-		{ "nolightmap",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		{ "pointlight",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
-		
-		
-		/* game */
-		{ "nonsolid",		0,							W_CONT_SOLID,				W_SURF_NONSOLID,			0,							0,							C_SOLID },
-		
-		{ "trigger",		W_CONT_TRIGGER,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "water",			W_CONT_WATER,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "slag",			W_CONT_SLIME,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		{ "lava",			W_CONT_LAVA,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
-		
-		{ "playerclip",		W_CONT_PLAYERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "monsterclip",	W_CONT_MONSTERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "clipmissile",	W_CONT_MISSILECLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "clipshot",		W_CONT_CLIPSHOT,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
-		{ "nodrop",			W_CONT_NODROP,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "clusterportal",	W_CONT_CLUSTERPORTAL,		W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "donotenter",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "nonotenterlarge",W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		{ "fog",			W_CONT_FOG,					W_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
-		{ "sky",			0,							0,							W_SURF_SKY,					0,							C_SKY,						0 },
-		
-		{ "slick",			0,							0,							W_SURF_SLICK,				0,							0,							0 },
-		
-		{ "noimpact",		0,							0,							W_SURF_NOIMPACT,			0,							0,							0 },
-		{ "nomarks",		0,							0,							W_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
-		{ "ladder",			0,							0,							W_SURF_LADDER,				0,							0,							0 },
-		{ "nodamage",		0,							0,							W_SURF_NODAMAGE,			0,							0,							0 },
-		{ "nosteps",		0,							0,							W_SURF_NOSTEPS,				0,							0,							0 },
-		{ "nodlight",		0,							0,							W_SURF_NODLIGHT,			0,							0,							0 },
-		
-		/* wolf et landmine-able surface */
-		{ "landmine",		0,							0,							W_SURF_LANDMINE,			0,							0,							0 },
-		
-		/* materials */
-		{ "metal",			0,							0,							W_SURF_METAL,				0,							0,							0 },
-		{ "metalsteps",		0,							0,							W_SURF_METAL,				0,							0,							0 },
-		{ "glass",			0,							0,							W_SURF_GLASS,				0,							0,							0 },
-		{ "splash",			0,							0,							W_SURF_SPLASH,				0,							0,							0 },
-		{ "woodsteps",		0,							0,							W_SURF_WOOD,				0,							0,							0 },
-		{ "grasssteps",		0,							0,							W_SURF_GRASS,				0,							0,							0 },
-		{ "gravelsteps",	0,							0,							W_SURF_GRAVEL,				0,							0,							0 },
-		{ "rubble",			0,							0,							W_SURF_RUBBLE,				0,							0,							0 },
-		{ "carpetsteps",	0,							0,							W_SURF_CARPET,				0,							0,							0 },
-		{ "snowsteps",		0,							0,							W_SURF_SNOW,				0,							0,							0 },
-		{ "roofsteps",		0,							0,							W_SURF_ROOF,				0,							0,							0 },
-		
-		
-		/* ai */
-		{ "ai_nosight",		W_CONT_AI_NOSIGHT,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		/* ydnar: experimental until bits are confirmed! */
-		{ "ai_nopass",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		{ "ai_nopasslarge",	W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
-		
-		
-		/* sliding bodies */
-		{ "monsterslick",	0,							0,							W_SURF_MONSTERSLICK,		0,							C_TRANSLUCENT,				0 },
-		{ "monsterslicknorth",	0,						0,							W_SURF_MONSLICK_N,			0,							C_TRANSLUCENT,				0 },
-		{ "monsterslickeast",	0,						0,							W_SURF_MONSLICK_E,			0,							C_TRANSLUCENT,				0 },
-		{ "monsterslicksouth",	0,						0,							W_SURF_MONSLICK_S,			0,							C_TRANSLUCENT,				0 },
-		{ "monsterslickwest",	0,						0,							W_SURF_MONSLICK_W,			0,							C_TRANSLUCENT,				0 },
-		
-		
-		/* null */
-		{ NULL, 0, 0, 0, 0, 0, 0 }
-	}
-}
-
-
-
-/* end marker */
-#endif
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+Support for Wolfenstein: Enemy Territory by ydnar@splashdamage.com
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef GAME_WOLFET_H
+#define GAME_WOLFET_H
+
+
+
+/* -------------------------------------------------------------------------------
+
+content and surface flags
+
+------------------------------------------------------------------------------- */
+
+/* this file must be included *after* game_wolf.h because it shares defines! */
+
+#define W_SURF_SPLASH				0x00000040	/* enemy territory water splash surface */
+#define W_SURF_LANDMINE				0x80000000	/* enemy territory 'landminable' surface */
+
+
+
+/* -------------------------------------------------------------------------------
+
+game_t struct
+
+------------------------------------------------------------------------------- */
+
+{
+	"et",				/* -game x */
+	"etmain",			/* default base game data dir */
+	".etwolf",			/* unix home sub-dir */
+	"et",				/* magic path word */
+	"scripts",			/* shader directory */
+	qtrue,				/* wolf lighting model? */
+	qfalse,				/* flares */
+	"flareshader",		/* default flare shader */
+	"IBSP",				/* bsp file prefix */
+	47,					/* bsp file version */
+	LoadIBSPFile,		/* bsp load function */
+	WriteIBSPFile,		/* bsp write function */
+	
+	{
+		/* name				contentFlags				contentFlagsClear			surfaceFlags				surfaceFlagsClear			compileFlags				compileFlagsClear */
+		
+		/* default */
+		{ "default",		W_CONT_SOLID,				-1,							0,							-1,							C_SOLID,					-1 },
+		
+		
+		/* ydnar */
+		{ "lightgrid",		0,							0,							0,							0,							C_LIGHTGRID,				0 },
+		{ "antiportal",		0,							0,							0,							0,							C_ANTIPORTAL,				0 },
+		{ "skip",			0,							0,							0,							0,							C_SKIP,						0 },
+		
+		
+		/* compiler */
+		{ "origin",			W_CONT_ORIGIN,				W_CONT_SOLID,				0,							0,							C_ORIGIN | C_TRANSLUCENT,	C_SOLID },
+		{ "areaportal",		W_CONT_AREAPORTAL,			W_CONT_SOLID,				0,							0,							C_AREAPORTAL | C_TRANSLUCENT,	C_SOLID },
+		{ "trans",			W_CONT_TRANSLUCENT,			0,							0,							0,							C_TRANSLUCENT,				0 },
+		{ "detail",			W_CONT_DETAIL,				0,							0,							0,							C_DETAIL,					0 },
+		{ "structural",		W_CONT_STRUCTURAL,			0,							0,							0,							C_STRUCTURAL,				0 },
+		{ "hint",			0,							0,							W_SURF_HINT,				0,							C_HINT,						0 },
+		{ "nodraw",			0,							0,							W_SURF_NODRAW,				0,							C_NODRAW,					0 },
+		
+		{ "alphashadow",	0,							0,							W_SURF_ALPHASHADOW,			0,							C_ALPHASHADOW | C_TRANSLUCENT,	0 },
+		{ "lightfilter",	0,							0,							W_SURF_LIGHTFILTER,			0,							C_LIGHTFILTER | C_TRANSLUCENT,	0 },
+		{ "nolightmap",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		{ "pointlight",		0,							0,							W_SURF_VERTEXLIT,			0,							C_VERTEXLIT,				0 },
+		
+		
+		/* game */
+		{ "nonsolid",		0,							W_CONT_SOLID,				W_SURF_NONSOLID,			0,							0,							C_SOLID },
+		
+		{ "trigger",		W_CONT_TRIGGER,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "water",			W_CONT_WATER,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "slag",			W_CONT_SLIME,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		{ "lava",			W_CONT_LAVA,				W_CONT_SOLID,				0,							0,							C_LIQUID | C_TRANSLUCENT,	C_SOLID },
+		
+		{ "playerclip",		W_CONT_PLAYERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "monsterclip",	W_CONT_MONSTERCLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "clipmissile",	W_CONT_MISSILECLIP,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "clipshot",		W_CONT_CLIPSHOT,			W_CONT_SOLID,				0,							0,							C_DETAIL | C_TRANSLUCENT,	C_SOLID },
+		{ "nodrop",			W_CONT_NODROP,				W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "clusterportal",	W_CONT_CLUSTERPORTAL,		W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "donotenter",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "nonotenterlarge",W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		{ "fog",			W_CONT_FOG,					W_CONT_SOLID,				0,							0,							C_FOG,						C_SOLID },
+		{ "sky",			0,							0,							W_SURF_SKY,					0,							C_SKY,						0 },
+		
+		{ "slick",			0,							0,							W_SURF_SLICK,				0,							0,							0 },
+		
+		{ "noimpact",		0,							0,							W_SURF_NOIMPACT,			0,							0,							0 },
+		{ "nomarks",		0,							0,							W_SURF_NOMARKS,				0,							C_NOMARKS,					0 },
+		{ "ladder",			0,							0,							W_SURF_LADDER,				0,							0,							0 },
+		{ "nodamage",		0,							0,							W_SURF_NODAMAGE,			0,							0,							0 },
+		{ "nosteps",		0,							0,							W_SURF_NOSTEPS,				0,							0,							0 },
+		{ "nodlight",		0,							0,							W_SURF_NODLIGHT,			0,							0,							0 },
+		
+		/* wolf et landmine-able surface */
+		{ "landmine",		0,							0,							W_SURF_LANDMINE,			0,							0,							0 },
+		
+		/* materials */
+		{ "metal",			0,							0,							W_SURF_METAL,				0,							0,							0 },
+		{ "metalsteps",		0,							0,							W_SURF_METAL,				0,							0,							0 },
+		{ "glass",			0,							0,							W_SURF_GLASS,				0,							0,							0 },
+		{ "splash",			0,							0,							W_SURF_SPLASH,				0,							0,							0 },
+		{ "woodsteps",		0,							0,							W_SURF_WOOD,				0,							0,							0 },
+		{ "grasssteps",		0,							0,							W_SURF_GRASS,				0,							0,							0 },
+		{ "gravelsteps",	0,							0,							W_SURF_GRAVEL,				0,							0,							0 },
+		{ "rubble",			0,							0,							W_SURF_RUBBLE,				0,							0,							0 },
+		{ "carpetsteps",	0,							0,							W_SURF_CARPET,				0,							0,							0 },
+		{ "snowsteps",		0,							0,							W_SURF_SNOW,				0,							0,							0 },
+		{ "roofsteps",		0,							0,							W_SURF_ROOF,				0,							0,							0 },
+		
+		
+		/* ai */
+		{ "ai_nosight",		W_CONT_AI_NOSIGHT,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		/* ydnar: experimental until bits are confirmed! */
+		{ "ai_nopass",		W_CONT_DONOTENTER,			W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		{ "ai_nopasslarge",	W_CONT_DONOTENTER_LARGE,	W_CONT_SOLID,				0,							0,							C_TRANSLUCENT,				C_SOLID },
+		
+		
+		/* sliding bodies */
+		{ "monsterslick",	0,							0,							W_SURF_MONSTERSLICK,		0,							C_TRANSLUCENT,				0 },
+		{ "monsterslicknorth",	0,						0,							W_SURF_MONSLICK_N,			0,							C_TRANSLUCENT,				0 },
+		{ "monsterslickeast",	0,						0,							W_SURF_MONSLICK_E,			0,							C_TRANSLUCENT,				0 },
+		{ "monsterslicksouth",	0,						0,							W_SURF_MONSLICK_S,			0,							C_TRANSLUCENT,				0 },
+		{ "monsterslickwest",	0,						0,							W_SURF_MONSLICK_W,			0,							C_TRANSLUCENT,				0 },
+		
+		
+		/* null */
+		{ NULL, 0, 0, 0, 0, 0, 0 }
+	}
+}
+
+
+
+/* end marker */
+#endif
+
diff --git a/tools/quake3/q3map2/image.c b/tools/quake3/q3map2/image.c
index 26e0e24f..fec9f6f5 100644
--- a/tools/quake3/q3map2/image.c
+++ b/tools/quake3/q3map2/image.c
@@ -1,467 +1,467 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define IMAGE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* -------------------------------------------------------------------------------
-
-this file contains image pool management with reference counting. note: it isn't
-reentrant, so only call it from init/shutdown code or wrap calls in a mutex
-
-------------------------------------------------------------------------------- */
-
-/*
-LoadDDSBuffer()
-loads a dxtc (1, 3, 5) dds buffer into a valid rgba image
-*/
-
-static void LoadDDSBuffer( byte *buffer, int size, byte **pixels, int *width, int *height )
-{
-	int		w, h;
-	ddsPF_t	pf;
-	
-	
-	/* dummy check */
-	if( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL )
-		return;
-	
-	/* null out */
-	*pixels = 0;
-	*width = 0;
-	*height = 0;
-	
-	/* get dds info */
-	if( DDSGetInfo( (ddsBuffer_t*) buffer, &w, &h, &pf ) )
-	{
-		Sys_Printf( "WARNING: Invalid DDS texture\n" );
-		return;
-	}
-	
-	/* only certain types of dds textures are supported */
-	if( pf != DDS_PF_ARGB8888 && pf != DDS_PF_DXT1 && pf != DDS_PF_DXT3 && pf != DDS_PF_DXT5 )
-	{
-		Sys_Printf( "WARNING: Only DDS texture formats ARGB8888, DXT1, DXT3, and DXT5 are supported (%d)\n", pf );
-		return;
-	}
-	
-	/* create image pixel buffer */
-	*width = w;
-	*height = h;
-	*pixels = safe_malloc( w * h * 4 );
-	
-	/* decompress the dds texture */
-	DDSDecompress( (ddsBuffer_t*) buffer, *pixels );
-}
-
-
-
-/*
-PNGReadData()
-callback function for libpng to read from a memory buffer
-note: this function is a total hack, as it reads/writes the png struct directly!
-*/
-
-typedef struct pngBuffer_s
-{
-	byte	*buffer;
-	int		size, offset;
-}
-pngBuffer_t;
-
-void PNGReadData( png_struct *png, png_byte *buffer, png_size_t size )
-{
-	pngBuffer_t		*pb = (pngBuffer_t*) png_get_io_ptr( png );
-	
-	
-	if( (pb->offset + size) > pb->size )
-		size = (pb->size - pb->offset);
-	memcpy( buffer, &pb->buffer[ pb->offset ], size );
-	pb->offset += size;
-	//%	Sys_Printf( "Copying %d bytes from 0x%08X to 0x%08X (offset: %d of %d)\n", size, &pb->buffer[ pb->offset ], buffer, pb->offset, pb->size );
-}
-
-
-
-/*
-LoadPNGBuffer()
-loads a png file buffer into a valid rgba image
-*/
-
-static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, int *height )
-{
-	png_struct	*png;
-	png_info	*info, *end;
-	pngBuffer_t	pb;
-	int			i, bitDepth, colorType, channels;
-	png_uint_32	w, h;
-	byte		**rowPointers;
-	
-	
-	/* dummy check */
-	if( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL )
-		return;
-	
-	/* null out */
-	*pixels = 0;
-	*width = 0;
-	*height = 0;
-	
-	/* determine if this is a png file */
-	if( png_sig_cmp( buffer, 0, 8 ) != 0 )
-	{
-		Sys_Printf( "WARNING: Invalid PNG file\n" );
-		return;
-	}
-	
-	/* create png structs */
-	png = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
-	if( png == NULL )
-	{
-		Sys_Printf( "WARNING: Unable to create PNG read struct\n" );
-		return;
-	}
-	
-	info = png_create_info_struct( png );
-	if( info == NULL )
-	{
-		Sys_Printf( "WARNING: Unable to create PNG info struct\n" );
-		png_destroy_read_struct( &png, NULL, NULL );
-		return;
-	}
-	
-	end = png_create_info_struct( png );
-	if( end == NULL )
-	{
-		Sys_Printf( "WARNING: Unable to create PNG end info struct\n" );
-		png_destroy_read_struct( &png, &info, NULL );
-		return;
-	}
-	
-	/* set read callback */
-	pb.buffer = buffer;
-	pb.size = size;
-	pb.offset = 0;
-	png_set_read_fn( png, &pb, PNGReadData );
-	png->io_ptr = &pb; /* hack! */
-	
-	/* set error longjmp */
-	if( setjmp( png->jmpbuf ) )
-	{
-		Sys_Printf( "WARNING: An error occurred reading PNG image\n" );
-		png_destroy_read_struct( &png, &info, &end );
-		return;
-	}
-	
-	/* fixme: add proper i/o stuff here */
-
-	/* read png info */
-	png_read_info( png, info );
-	
-	/* read image header chunk */
-	png_get_IHDR( png, info,
-		&w, &h, &bitDepth, &colorType, NULL, NULL, NULL );
-	
-	/* read number of channels */
-	channels = png_get_channels( png, info );
-	
-	/* the following will probably bork on certain types of png images, but hey... */
-
-	/* force indexed/gray/trans chunk to rgb */
-	if( (colorType == PNG_COLOR_TYPE_PALETTE && bitDepth <= 8) ||
-		(colorType == PNG_COLOR_TYPE_GRAY && bitDepth <= 8) ||
-		png_get_valid( png, info, PNG_INFO_tRNS ) )
-		png_set_expand( png );
-	
-	/* strip 16bpc -> 8bpc */
-	if( bitDepth == 16 )
-		png_set_strip_16( png );
-	
-	/* pad rgb to rgba */
-	if( bitDepth == 8 && colorType == PNG_COLOR_TYPE_RGB)
-		png_set_filler( png, 255, PNG_FILLER_AFTER );
-	
-	/* create image pixel buffer */
-	*width = w;
-	*height = h;
-	*pixels = safe_malloc( w * h * 4 );
-	
-	/* create row pointers */
-	rowPointers = safe_malloc( h * sizeof( byte* ) );
-	for( i = 0; i < h; i++ )
-		rowPointers[ i ] = *pixels + (i * w * 4);
-	
-	/* read the png */
-	png_read_image( png, rowPointers );
-	
-	/* clean up */
-	free( rowPointers );
-	png_destroy_read_struct( &png, &info, &end );
-	
-}
-
-
-
-/*
-ImageInit()
-implicitly called by every function to set up image list
-*/
-
-static void ImageInit( void )
-{
-	int		i;
-	
-	
-	if( numImages <= 0 )
-	{
-		/* clear images (fixme: this could theoretically leak) */
-		memset( images, 0, sizeof( images ) );
-		
-		/* generate *bogus image */
-		images[ 0 ].name = safe_malloc( strlen( DEFAULT_IMAGE ) + 1 );
-		strcpy( images[ 0 ].name, DEFAULT_IMAGE );
-		images[ 0 ].filename = safe_malloc( strlen( DEFAULT_IMAGE ) + 1 );
-		strcpy( images[ 0 ].filename, DEFAULT_IMAGE );
-		images[ 0 ].width = 64;
-		images[ 0 ].height = 64;
-		images[ 0 ].refCount = 1;
-		images[ 0 ].pixels = safe_malloc( 64 * 64 * 4 );
-		for( i = 0; i < (64 * 64 * 4); i++ )
-			images[ 0 ].pixels[ i ] = 255;
-	}
-}
-
-
-
-/*
-ImageFree()
-frees an rgba image
-*/
-
-void ImageFree( image_t *image )
-{
-	/* dummy check */
-	if( image == NULL )
-		return;
-	
-	/* decrement refcount */
-	image->refCount--;
-	
-	/* free? */
-	if( image->refCount <= 0 )
-	{
-		if( image->name != NULL )
-			free( image->name );
-		image->name = NULL;
-		if( image->filename != NULL )
-			free( image->filename );
-		image->filename = NULL;
-		free( image->pixels );
-		image->width = 0;
-		image->height = 0;
-		numImages--;
-	}
-}
-
-
-
-/*
-ImageFind()
-finds an existing rgba image and returns a pointer to the image_t struct or NULL if not found
-*/
-
-image_t *ImageFind( const char *filename )
-{
-	int			i;
-	char		name[ 1024 ];
-	
-	
-	/* init */
-	ImageInit();
-	
-	/* dummy check */
-	if( filename == NULL || filename[ 0 ] == '\0' )
-		return NULL;
-	
-	/* strip file extension off name */
-	strcpy( name, filename );
-	StripExtension( name );
-	
-	/* search list */
-	for( i = 0; i < MAX_IMAGES; i++ )
-	{
-		if( images[ i ].name != NULL && !strcmp( name, images[ i ].name ) )
-			return &images[ i ];
-	}
-	
-	/* no matching image found */
-	return NULL;
-}
-
-
-
-/*
-ImageLoad()
-loads an rgba image and returns a pointer to the image_t struct or NULL if not found
-*/
-
-image_t *ImageLoad( const char *filename )
-{
-	int			i;
-	image_t		*image;
-	char		name[ 1024 ];
-	int			size;
-	byte		*buffer = NULL;
-
-	
-	/* init */
-	ImageInit();
-	
-	/* dummy check */
-	if( filename == NULL || filename[ 0 ] == '\0' )
-		return NULL;
-	
-	/* strip file extension off name */
-	strcpy( name, filename );
-	StripExtension( name );
-	
-	/* try to find existing image */
-	image = ImageFind( name );
-	if( image != NULL )
-	{
-		image->refCount++;
-		return image;
-	}
-	
-	/* none found, so find first non-null image */
-	image = NULL;
-	for( i = 0; i < MAX_IMAGES; i++ )
-	{
-		if( images[ i ].name == NULL )
-		{
-			image = &images[ i ];
-			break;
-		}
-	}
-	
-	/* too many images? */
-	if( image == NULL )
-		Error( "MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES );
-	
-	/* set it up */
-	image->name = safe_malloc( strlen( name ) + 1 );
-	strcpy( image->name, name );
-	
-	/* attempt to load tga */
-	StripExtension( name );
-	strcat( name, ".tga" );
-	size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-	if( size > 0 )
-		LoadTGABuffer( buffer, &image->pixels, &image->width, &image->height );
-	else
-	{
-		/* attempt to load png */
-		StripExtension( name );
-		strcat( name, ".png" );
-		size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-		if( size > 0 )
-			LoadPNGBuffer( buffer, size, &image->pixels, &image->width, &image->height );
-		else
-		{
-			/* attempt to load jpg */
-			StripExtension( name );
-			strcat( name, ".jpg" );
-			size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-			if( size > 0 )
-			{
-				if( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL )
-					Sys_Printf( "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels );
-			}
-			else
-			{
-				/* attempt to load dds */
-				StripExtension( name );
-				strcat( name, ".dds" );
-				size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
-				if( size > 0 )
-				{
-					LoadDDSBuffer( buffer, size, &image->pixels, &image->width, &image->height );
-					
-					/* debug code */
-					#if 1
-					{
-						ddsPF_t	pf;
-						DDSGetInfo( (ddsBuffer_t*) buffer, NULL, NULL, &pf );
-						Sys_Printf( "pf = %d\n", pf );
-						if( image->width > 0 )
-						{
-							StripExtension( name );
-							strcat( name, "_converted.tga" );
-							WriteTGA( "C:\\games\\quake3\\baseq3\\textures\\rad\\dds_converted.tga", image->pixels, image->width, image->height );
-						}
-					}
-					#endif
-				}
-			}
-		}
-	}
-	
-	/* free file buffer */
-	free( buffer );
-	
-	/* make sure everything's kosher */
-	if( size <= 0 || image->width <= 0 || image->height <= 0 || image->pixels == NULL )
-	{
-		//%	Sys_Printf( "size = %d  width = %d  height = %d  pixels = 0x%08x (%s)\n",
-		//%		size, image->width, image->height, image->pixels, name );
-		free( image->name );
-		image->name = NULL;
-		return NULL;
-	}
-	
-	/* set filename */
-	image->filename = safe_malloc( strlen( name ) + 1 );
-	strcpy( image->filename, name );
-	
-	/* set count */
-	image->refCount = 1;
-	numImages++;
-	
-	/* return the image */
-	return image;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define IMAGE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* -------------------------------------------------------------------------------
+
+this file contains image pool management with reference counting. note: it isn't
+reentrant, so only call it from init/shutdown code or wrap calls in a mutex
+
+------------------------------------------------------------------------------- */
+
+/*
+LoadDDSBuffer()
+loads a dxtc (1, 3, 5) dds buffer into a valid rgba image
+*/
+
+static void LoadDDSBuffer( byte *buffer, int size, byte **pixels, int *width, int *height )
+{
+	int		w, h;
+	ddsPF_t	pf;
+	
+	
+	/* dummy check */
+	if( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL )
+		return;
+	
+	/* null out */
+	*pixels = 0;
+	*width = 0;
+	*height = 0;
+	
+	/* get dds info */
+	if( DDSGetInfo( (ddsBuffer_t*) buffer, &w, &h, &pf ) )
+	{
+		Sys_Printf( "WARNING: Invalid DDS texture\n" );
+		return;
+	}
+	
+	/* only certain types of dds textures are supported */
+	if( pf != DDS_PF_ARGB8888 && pf != DDS_PF_DXT1 && pf != DDS_PF_DXT3 && pf != DDS_PF_DXT5 )
+	{
+		Sys_Printf( "WARNING: Only DDS texture formats ARGB8888, DXT1, DXT3, and DXT5 are supported (%d)\n", pf );
+		return;
+	}
+	
+	/* create image pixel buffer */
+	*width = w;
+	*height = h;
+	*pixels = safe_malloc( w * h * 4 );
+	
+	/* decompress the dds texture */
+	DDSDecompress( (ddsBuffer_t*) buffer, *pixels );
+}
+
+
+
+/*
+PNGReadData()
+callback function for libpng to read from a memory buffer
+note: this function is a total hack, as it reads/writes the png struct directly!
+*/
+
+typedef struct pngBuffer_s
+{
+	byte	*buffer;
+	int		size, offset;
+}
+pngBuffer_t;
+
+void PNGReadData( png_struct *png, png_byte *buffer, png_size_t size )
+{
+	pngBuffer_t		*pb = (pngBuffer_t*) png_get_io_ptr( png );
+	
+	
+	if( (pb->offset + size) > pb->size )
+		size = (pb->size - pb->offset);
+	memcpy( buffer, &pb->buffer[ pb->offset ], size );
+	pb->offset += size;
+	//%	Sys_Printf( "Copying %d bytes from 0x%08X to 0x%08X (offset: %d of %d)\n", size, &pb->buffer[ pb->offset ], buffer, pb->offset, pb->size );
+}
+
+
+
+/*
+LoadPNGBuffer()
+loads a png file buffer into a valid rgba image
+*/
+
+static void LoadPNGBuffer( byte *buffer, int size, byte **pixels, int *width, int *height )
+{
+	png_struct	*png;
+	png_info	*info, *end;
+	pngBuffer_t	pb;
+	int			i, bitDepth, colorType, channels;
+	png_uint_32	w, h;
+	byte		**rowPointers;
+	
+	
+	/* dummy check */
+	if( buffer == NULL || size <= 0 || pixels == NULL || width == NULL || height == NULL )
+		return;
+	
+	/* null out */
+	*pixels = 0;
+	*width = 0;
+	*height = 0;
+	
+	/* determine if this is a png file */
+	if( png_sig_cmp( buffer, 0, 8 ) != 0 )
+	{
+		Sys_Printf( "WARNING: Invalid PNG file\n" );
+		return;
+	}
+	
+	/* create png structs */
+	png = png_create_read_struct( PNG_LIBPNG_VER_STRING, NULL, NULL, NULL );
+	if( png == NULL )
+	{
+		Sys_Printf( "WARNING: Unable to create PNG read struct\n" );
+		return;
+	}
+	
+	info = png_create_info_struct( png );
+	if( info == NULL )
+	{
+		Sys_Printf( "WARNING: Unable to create PNG info struct\n" );
+		png_destroy_read_struct( &png, NULL, NULL );
+		return;
+	}
+	
+	end = png_create_info_struct( png );
+	if( end == NULL )
+	{
+		Sys_Printf( "WARNING: Unable to create PNG end info struct\n" );
+		png_destroy_read_struct( &png, &info, NULL );
+		return;
+	}
+	
+	/* set read callback */
+	pb.buffer = buffer;
+	pb.size = size;
+	pb.offset = 0;
+	png_set_read_fn( png, &pb, PNGReadData );
+	png->io_ptr = &pb; /* hack! */
+	
+	/* set error longjmp */
+	if( setjmp( png->jmpbuf ) )
+	{
+		Sys_Printf( "WARNING: An error occurred reading PNG image\n" );
+		png_destroy_read_struct( &png, &info, &end );
+		return;
+	}
+	
+	/* fixme: add proper i/o stuff here */
+
+	/* read png info */
+	png_read_info( png, info );
+	
+	/* read image header chunk */
+	png_get_IHDR( png, info,
+		&w, &h, &bitDepth, &colorType, NULL, NULL, NULL );
+	
+	/* read number of channels */
+	channels = png_get_channels( png, info );
+	
+	/* the following will probably bork on certain types of png images, but hey... */
+
+	/* force indexed/gray/trans chunk to rgb */
+	if( (colorType == PNG_COLOR_TYPE_PALETTE && bitDepth <= 8) ||
+		(colorType == PNG_COLOR_TYPE_GRAY && bitDepth <= 8) ||
+		png_get_valid( png, info, PNG_INFO_tRNS ) )
+		png_set_expand( png );
+	
+	/* strip 16bpc -> 8bpc */
+	if( bitDepth == 16 )
+		png_set_strip_16( png );
+	
+	/* pad rgb to rgba */
+	if( bitDepth == 8 && colorType == PNG_COLOR_TYPE_RGB)
+		png_set_filler( png, 255, PNG_FILLER_AFTER );
+	
+	/* create image pixel buffer */
+	*width = w;
+	*height = h;
+	*pixels = safe_malloc( w * h * 4 );
+	
+	/* create row pointers */
+	rowPointers = safe_malloc( h * sizeof( byte* ) );
+	for( i = 0; i < h; i++ )
+		rowPointers[ i ] = *pixels + (i * w * 4);
+	
+	/* read the png */
+	png_read_image( png, rowPointers );
+	
+	/* clean up */
+	free( rowPointers );
+	png_destroy_read_struct( &png, &info, &end );
+	
+}
+
+
+
+/*
+ImageInit()
+implicitly called by every function to set up image list
+*/
+
+static void ImageInit( void )
+{
+	int		i;
+	
+	
+	if( numImages <= 0 )
+	{
+		/* clear images (fixme: this could theoretically leak) */
+		memset( images, 0, sizeof( images ) );
+		
+		/* generate *bogus image */
+		images[ 0 ].name = safe_malloc( strlen( DEFAULT_IMAGE ) + 1 );
+		strcpy( images[ 0 ].name, DEFAULT_IMAGE );
+		images[ 0 ].filename = safe_malloc( strlen( DEFAULT_IMAGE ) + 1 );
+		strcpy( images[ 0 ].filename, DEFAULT_IMAGE );
+		images[ 0 ].width = 64;
+		images[ 0 ].height = 64;
+		images[ 0 ].refCount = 1;
+		images[ 0 ].pixels = safe_malloc( 64 * 64 * 4 );
+		for( i = 0; i < (64 * 64 * 4); i++ )
+			images[ 0 ].pixels[ i ] = 255;
+	}
+}
+
+
+
+/*
+ImageFree()
+frees an rgba image
+*/
+
+void ImageFree( image_t *image )
+{
+	/* dummy check */
+	if( image == NULL )
+		return;
+	
+	/* decrement refcount */
+	image->refCount--;
+	
+	/* free? */
+	if( image->refCount <= 0 )
+	{
+		if( image->name != NULL )
+			free( image->name );
+		image->name = NULL;
+		if( image->filename != NULL )
+			free( image->filename );
+		image->filename = NULL;
+		free( image->pixels );
+		image->width = 0;
+		image->height = 0;
+		numImages--;
+	}
+}
+
+
+
+/*
+ImageFind()
+finds an existing rgba image and returns a pointer to the image_t struct or NULL if not found
+*/
+
+image_t *ImageFind( const char *filename )
+{
+	int			i;
+	char		name[ 1024 ];
+	
+	
+	/* init */
+	ImageInit();
+	
+	/* dummy check */
+	if( filename == NULL || filename[ 0 ] == '\0' )
+		return NULL;
+	
+	/* strip file extension off name */
+	strcpy( name, filename );
+	StripExtension( name );
+	
+	/* search list */
+	for( i = 0; i < MAX_IMAGES; i++ )
+	{
+		if( images[ i ].name != NULL && !strcmp( name, images[ i ].name ) )
+			return &images[ i ];
+	}
+	
+	/* no matching image found */
+	return NULL;
+}
+
+
+
+/*
+ImageLoad()
+loads an rgba image and returns a pointer to the image_t struct or NULL if not found
+*/
+
+image_t *ImageLoad( const char *filename )
+{
+	int			i;
+	image_t		*image;
+	char		name[ 1024 ];
+	int			size;
+	byte		*buffer = NULL;
+
+	
+	/* init */
+	ImageInit();
+	
+	/* dummy check */
+	if( filename == NULL || filename[ 0 ] == '\0' )
+		return NULL;
+	
+	/* strip file extension off name */
+	strcpy( name, filename );
+	StripExtension( name );
+	
+	/* try to find existing image */
+	image = ImageFind( name );
+	if( image != NULL )
+	{
+		image->refCount++;
+		return image;
+	}
+	
+	/* none found, so find first non-null image */
+	image = NULL;
+	for( i = 0; i < MAX_IMAGES; i++ )
+	{
+		if( images[ i ].name == NULL )
+		{
+			image = &images[ i ];
+			break;
+		}
+	}
+	
+	/* too many images? */
+	if( image == NULL )
+		Error( "MAX_IMAGES (%d) exceeded, there are too many image files referenced by the map.", MAX_IMAGES );
+	
+	/* set it up */
+	image->name = safe_malloc( strlen( name ) + 1 );
+	strcpy( image->name, name );
+	
+	/* attempt to load tga */
+	StripExtension( name );
+	strcat( name, ".tga" );
+	size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+	if( size > 0 )
+		LoadTGABuffer( buffer, &image->pixels, &image->width, &image->height );
+	else
+	{
+		/* attempt to load png */
+		StripExtension( name );
+		strcat( name, ".png" );
+		size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+		if( size > 0 )
+			LoadPNGBuffer( buffer, size, &image->pixels, &image->width, &image->height );
+		else
+		{
+			/* attempt to load jpg */
+			StripExtension( name );
+			strcat( name, ".jpg" );
+			size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+			if( size > 0 )
+			{
+				if( LoadJPGBuff( buffer, size, &image->pixels, &image->width, &image->height ) == -1 && image->pixels != NULL )
+					Sys_Printf( "WARNING: LoadJPGBuff: %s\n", (unsigned char*) image->pixels );
+			}
+			else
+			{
+				/* attempt to load dds */
+				StripExtension( name );
+				strcat( name, ".dds" );
+				size = vfsLoadFile( (const char*) name, (void**) &buffer, 0 );
+				if( size > 0 )
+				{
+					LoadDDSBuffer( buffer, size, &image->pixels, &image->width, &image->height );
+					
+					/* debug code */
+					#if 1
+					{
+						ddsPF_t	pf;
+						DDSGetInfo( (ddsBuffer_t*) buffer, NULL, NULL, &pf );
+						Sys_Printf( "pf = %d\n", pf );
+						if( image->width > 0 )
+						{
+							StripExtension( name );
+							strcat( name, "_converted.tga" );
+							WriteTGA( "C:\\games\\quake3\\baseq3\\textures\\rad\\dds_converted.tga", image->pixels, image->width, image->height );
+						}
+					}
+					#endif
+				}
+			}
+		}
+	}
+	
+	/* free file buffer */
+	free( buffer );
+	
+	/* make sure everything's kosher */
+	if( size <= 0 || image->width <= 0 || image->height <= 0 || image->pixels == NULL )
+	{
+		//%	Sys_Printf( "size = %d  width = %d  height = %d  pixels = 0x%08x (%s)\n",
+		//%		size, image->width, image->height, image->pixels, name );
+		free( image->name );
+		image->name = NULL;
+		return NULL;
+	}
+	
+	/* set filename */
+	image->filename = safe_malloc( strlen( name ) + 1 );
+	strcpy( image->filename, name );
+	
+	/* set count */
+	image->refCount = 1;
+	numImages++;
+	
+	/* return the image */
+	return image;
+}
+
+
diff --git a/tools/quake3/q3map2/leakfile.c b/tools/quake3/q3map2/leakfile.c
index e8108c6f..1d72604b 100644
--- a/tools/quake3/q3map2/leakfile.c
+++ b/tools/quake3/q3map2/leakfile.c
@@ -1,126 +1,126 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define LEAKFILE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-==============================================================================
-
-LEAK FILE GENERATION
-
-Save out name.line for qe3 to read
-==============================================================================
-*/
-
-
-/*
-=============
-LeakFile
-
-Finds the shortest possible chain of portals
-that leads from the outside leaf to a specifically
-occupied leaf
-
-TTimo: builds a polyline xml node
-=============
-*/
-xmlNodePtr LeakFile (tree_t *tree)
-{
-	vec3_t	mid;
-	FILE	*linefile;
-	char	filename[1024];
-	node_t	*node;
-	int		count;
-	xmlNodePtr xml_node, point;
-
-	if (!tree->outside_node.occupied)
-		return NULL;
-
-	Sys_FPrintf (SYS_VRB,"--- LeakFile ---\n");
-
-	//
-	// write the points to the file
-	//
-	sprintf (filename, "%s.lin", source);
-	linefile = fopen (filename, "w");
-	if (!linefile)
-		Error ("Couldn't open %s\n", filename);
-
-  xml_node = xmlNewNode (NULL, "polyline");
-
-	count = 0;
-	node = &tree->outside_node;
-	while (node->occupied > 1)
-	{
-		int			next;
-		portal_t	*p, *nextportal;
-		node_t		*nextnode;
-		int			s;
-
-		// find the best portal exit
-		next = node->occupied;
-		for (p=node->portals ; p ; p = p->next[!s])
-		{
-			s = (p->nodes[0] == node);
-			if (p->nodes[s]->occupied
-				&& p->nodes[s]->occupied < next)
-			{
-				nextportal = p;
-				nextnode = p->nodes[s];
-				next = nextnode->occupied;
-			}
-		}
-		node = nextnode;
-		WindingCenter (nextportal->winding, mid);
-		fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
-		point = xml_NodeForVec(mid);
-		xmlAddChild(xml_node, point);
-		count++;
-	}
-	// add the occupant center
-	GetVectorForKey (node->occupant, "origin", mid);
-
-	fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
-	point = xml_NodeForVec(mid);
-	xmlAddChild(xml_node, point);
-	Sys_FPrintf( SYS_VRB, "%9d point linefile\n", count+1);
-
-	fclose (linefile);
-	
-	return xml_node;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define LEAKFILE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+==============================================================================
+
+LEAK FILE GENERATION
+
+Save out name.line for qe3 to read
+==============================================================================
+*/
+
+
+/*
+=============
+LeakFile
+
+Finds the shortest possible chain of portals
+that leads from the outside leaf to a specifically
+occupied leaf
+
+TTimo: builds a polyline xml node
+=============
+*/
+xmlNodePtr LeakFile (tree_t *tree)
+{
+	vec3_t	mid;
+	FILE	*linefile;
+	char	filename[1024];
+	node_t	*node;
+	int		count;
+	xmlNodePtr xml_node, point;
+
+	if (!tree->outside_node.occupied)
+		return NULL;
+
+	Sys_FPrintf (SYS_VRB,"--- LeakFile ---\n");
+
+	//
+	// write the points to the file
+	//
+	sprintf (filename, "%s.lin", source);
+	linefile = fopen (filename, "w");
+	if (!linefile)
+		Error ("Couldn't open %s\n", filename);
+
+  xml_node = xmlNewNode (NULL, "polyline");
+
+	count = 0;
+	node = &tree->outside_node;
+	while (node->occupied > 1)
+	{
+		int			next;
+		portal_t	*p, *nextportal;
+		node_t		*nextnode;
+		int			s;
+
+		// find the best portal exit
+		next = node->occupied;
+		for (p=node->portals ; p ; p = p->next[!s])
+		{
+			s = (p->nodes[0] == node);
+			if (p->nodes[s]->occupied
+				&& p->nodes[s]->occupied < next)
+			{
+				nextportal = p;
+				nextnode = p->nodes[s];
+				next = nextnode->occupied;
+			}
+		}
+		node = nextnode;
+		WindingCenter (nextportal->winding, mid);
+		fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
+		point = xml_NodeForVec(mid);
+		xmlAddChild(xml_node, point);
+		count++;
+	}
+	// add the occupant center
+	GetVectorForKey (node->occupant, "origin", mid);
+
+	fprintf (linefile, "%f %f %f\n", mid[0], mid[1], mid[2]);
+	point = xml_NodeForVec(mid);
+	xmlAddChild(xml_node, point);
+	Sys_FPrintf( SYS_VRB, "%9d point linefile\n", count+1);
+
+	fclose (linefile);
+	
+	return xml_node;
+}
+
diff --git a/tools/quake3/q3map2/light.c b/tools/quake3/q3map2/light.c
index 9ee61bea..670c9a0e 100644
--- a/tools/quake3/q3map2/light.c
+++ b/tools/quake3/q3map2/light.c
@@ -1,2182 +1,2182 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define LIGHT_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-CreateSunLight() - ydnar
-this creates a sun light
-*/
-
-static void CreateSunLight( sun_t *sun )
-{
-	int			i;
-	float		photons, d, angle, elevation, da, de;
-	vec3_t		direction;
-	light_t		*light;
-	
-	
-	/* dummy check */
-	if( sun == NULL )
-		return;
-	
-	/* fixup */
-	if( sun->numSamples < 1 )
-		sun->numSamples = 1;
-	
-	/* set photons */
-	photons = sun->photons / sun->numSamples;
-	
-	/* create the right number of suns */
-	for( i = 0; i < sun->numSamples; i++ )
-	{
-		/* calculate sun direction */
-		if( i == 0 )
-			VectorCopy( sun->direction, direction );
-		else
-		{
-			/*
-				sun->direction[ 0 ] = cos( angle ) * cos( elevation );
-				sun->direction[ 1 ] = sin( angle ) * cos( elevation );
-				sun->direction[ 2 ] = sin( elevation );
-				
-				xz_dist   = sqrt( x*x + z*z )
-				latitude  = atan2( xz_dist, y ) * RADIANS
-				longitude = atan2( x,       z ) * RADIANS
-			*/
-			
-			d = sqrt( sun->direction[ 0 ] * sun->direction[ 0 ] + sun->direction[ 1 ] * sun->direction[ 1 ] );
-			angle = atan2( sun->direction[ 1 ], sun->direction[ 0 ] );
-			elevation = atan2( sun->direction[ 2 ], d );
-			
-			/* jitter the angles (loop to keep random sample within sun->deviance steridians) */
-			do
-			{
-				da = (Random() * 2.0f - 1.0f) * sun->deviance;
-				de = (Random() * 2.0f - 1.0f) * sun->deviance;
-			}
-			while( (da * da + de * de) > (sun->deviance * sun->deviance) );
-			angle += da;
-			elevation += de;
-			
-			/* debug code */
-			//%	Sys_Printf( "%d: Angle: %3.4f Elevation: %3.3f\n", sun->numSamples, (angle / Q_PI * 180.0f), (elevation / Q_PI * 180.0f) );
-			
-			/* create new vector */
-			direction[ 0 ] = cos( angle ) * cos( elevation );
-			direction[ 1 ] = sin( angle ) * cos( elevation );
-			direction[ 2 ] = sin( elevation );
-		}
-		
-		/* create a light */
-		numSunLights++;
-		light = safe_malloc( sizeof( *light ) );
-		memset( light, 0, sizeof( *light ) );
-		light->next = lights;
-		lights = light;
-		
-		/* initialize the light */
-		light->flags = LIGHT_SUN_DEFAULT;
-		light->type = EMIT_SUN;
-		light->fade = 1.0f;
-		light->falloffTolerance = falloffTolerance;
-		light->filterRadius = sun->filterRadius / sun->numSamples;
-		
-		/* set the light's position out to infinity */
-		VectorMA( vec3_origin, (MAX_WORLD_COORD * 8.0f), direction, light->origin );	/* MAX_WORLD_COORD * 2.0f */
-		
-		/* set the facing to be the inverse of the sun direction */
-		VectorScale( direction, -1.0, light->normal );
-		light->dist = DotProduct( light->origin, light->normal );
-		
-		/* set color and photons */
-		VectorCopy( sun->color, light->color );
-		light->photons = photons * skyScale;
-	}
-
-	/* another sun? */
-	if( sun->next != NULL )
-		CreateSunLight( sun->next );
-}
-
-
-
-/*
-CreateSkyLights() - ydnar
-simulates sky light with multiple suns
-*/
-
-static void CreateSkyLights( vec3_t color, float value, int iterations, float filterRadius )
-{
-	int			c, i, j, k, numSuns;
-	float		step, start;
-	vec3_t		in;
-	sun_t		sun;
-	
-	
-	/* dummy check */
-	if( value <= 0.0f || iterations < 2 )
-		return;
-	
-	/* calculate some stuff */
-	step = 2.0f / (iterations - 1);
-	start = -1.0f;
-	
-	/* basic sun setup */
-	VectorCopy( color, sun.color );
-	sun.deviance = 0.0f;
-	sun.filterRadius = filterRadius;
-	sun.numSamples = 1;
-	sun.next = NULL;
-	
-	/* iterate */
-	numSuns = 0;
-	for( c = 0; c < 2; c++ )
-	{
-		for( k = 0, in[ 2 ] = start; k < iterations; k++, in[ 2 ] += step )
-		{
-			/* don't create sky light below the horizon */
-			if( in[ 2 ] <= 0.0f )
-				continue;
-			
-			for( j = 0, in[ 1 ] = start; j < iterations; j++, in[ 1 ] += step )
-			{
-				for( i = 0, in[ 0 ] = start; i < iterations; i++, in[ 0 ] += step )
-				{
-					if( VectorNormalize( in, sun.direction ) )
-					{
-						if( c > 0 && numSuns > 0 )
-						{
-							sun.photons = value / numSuns;
-							CreateSunLight( &sun );
-						}
-						else
-							numSuns++;
-					}
-				}
-			}
-		}
-	}
-}
-
-
-
-/*
-CreateEntityLights()
-creates lights from light entities
-*/
-
-void CreateEntityLights( void )
-{
-	int				i, j;
-	light_t			*light, *light2;
-	entity_t		*e, *e2;
-	const char		*name;
-	const char		*target;
-	vec3_t			dest;
-	const char		*_color;
-	float			intensity, scale, deviance, filterRadius;
-	int				spawnflags, flags, numSamples;
-	qboolean		junior;
-
-	
-	/* go throught entity list and find lights */
-	for( i = 0; i < numEntities; i++ )
-	{
-		/* get entity */
-		e = &entities[ i ];
-		name = ValueForKey( e, "classname" );
-		
-		/* ydnar: check for lightJunior */
-		if( Q_strncasecmp( name, "lightJunior", 11 ) == 0 )
-			junior = qtrue;
-		else if( Q_strncasecmp( name, "light", 5 ) == 0 )
-			junior = qfalse;
-		else
-			continue;
-		
-		/* lights with target names (and therefore styles) are only parsed from BSP */
-		target = ValueForKey( e, "targetname" );
-		if( target[ 0 ] != '\0' && i >= numBSPEntities )
-			continue;
-		
-		/* create a light */
-		numPointLights++;
-		light = safe_malloc( sizeof( *light ) );
-		memset( light, 0, sizeof( *light ) );
-		light->next = lights;
-		lights = light;
-		
-		/* handle spawnflags */
-		spawnflags = IntForKey( e, "spawnflags" );
-		
-		/* ydnar: quake 3+ light behavior */
-		if( game->wolfLight == qfalse )
-		{
-			/* set default flags */
-			flags = LIGHT_Q3A_DEFAULT;
-			
-			/* linear attenuation? */
-			if( spawnflags & 1 )
-			{
-				flags |= LIGHT_ATTEN_LINEAR;
-				flags &= ~LIGHT_ATTEN_ANGLE;
-			}
-			
-			/* no angle attenuate? */
-			if( spawnflags & 2 )
-				flags &= ~LIGHT_ATTEN_ANGLE;
-		}
-		
-		/* ydnar: wolf light behavior */
-		else
-		{
-			/* set default flags */
-			flags = LIGHT_WOLF_DEFAULT;
-			
-			/* inverse distance squared attenuation? */
-			if( spawnflags & 1 )
-			{
-				flags &= ~LIGHT_ATTEN_LINEAR;
-				flags |= LIGHT_ATTEN_ANGLE;
-			}
-			
-			/* angle attenuate? */
-			if( spawnflags & 2 )
-				flags |= LIGHT_ATTEN_ANGLE;
-		}
-		
-		/* other flags (borrowed from wolf) */
-		
-		/* wolf dark light? */
-		if( (spawnflags & 4) || (spawnflags & 8) )
-			flags |= LIGHT_DARK;
-		
-		/* nogrid? */
-		if( spawnflags & 16 )
-			flags &= ~LIGHT_GRID;
-		
-		/* junior? */
-		if( junior )
-		{
-			flags |= LIGHT_GRID;
-			flags &= ~LIGHT_SURFACES;
-		}
-		
-		/* store the flags */
-		light->flags = flags;
-		
-		/* ydnar: set fade key (from wolf) */
-		light->fade = 1.0f;
-		if( light->flags & LIGHT_ATTEN_LINEAR )
-		{
-			light->fade = FloatForKey( e, "fade" );
-			if( light->fade == 0.0f )
-				light->fade = 1.0f;
-		}
-		
-		/* ydnar: set angle scaling (from vlight) */
-		light->angleScale = FloatForKey( e, "_anglescale" );
-		if( light->angleScale != 0.0f )
-			light->flags |= LIGHT_ATTEN_ANGLE;
-		
-		/* set origin */
-		GetVectorForKey( e, "origin", light->origin);
-		light->style = IntForKey( e, "_style" );
-		if( light->style == 0 )
-			light->style = IntForKey( e, "style" );
-		if( light->style < LS_NORMAL || light->style >= LS_NONE )
-			Error( "Invalid lightstyle (%d) on entity %d", light->style, i );
-		
-		/* set light intensity */
-		intensity = FloatForKey( e, "_light" );
-		if( intensity == 0.0f )
-			intensity = FloatForKey( e, "light" );
-		if( intensity == 0.0f)
-			intensity = 300.0f;
-		
-		/* ydnar: set light scale (sof2) */
-		scale = FloatForKey( e, "scale" );
-		if( scale == 0.0f )
-			scale = 1.0f;
-		intensity *= scale;
-		
-		/* ydnar: get deviance and samples */
-		deviance = FloatForKey( e, "_deviance" );
-		if( deviance == 0.0f )
-			deviance = FloatForKey( e, "_deviation" );
-		if( deviance == 0.0f )
-			deviance = FloatForKey( e, "_jitter" );
-		numSamples = IntForKey( e, "_samples" );
-		if( deviance < 0.0f || numSamples < 1 )
-		{
-			deviance = 0.0f;
-			numSamples = 1;
-		}
-		intensity /= numSamples;
-		
-		/* ydnar: get filter radius */
-		filterRadius = FloatForKey( e, "_filterradius" );
-		if( filterRadius == 0.0f )
-			filterRadius = FloatForKey( e, "_filteradius" );
-		if( filterRadius == 0.0f )
-			filterRadius = FloatForKey( e, "_filter" );
-		if( filterRadius < 0.0f )
-			filterRadius = 0.0f;
-		light->filterRadius = filterRadius;
-		
-		/* set light color */
-		_color = ValueForKey( e, "_color" );
-		if( _color && _color[ 0 ] )
-		{
-			sscanf( _color, "%f %f %f", &light->color[ 0 ], &light->color[ 1 ], &light->color[ 2 ] );
-			ColorNormalize( light->color, light->color );
-		}
-		else
-			light->color[ 0 ] = light->color[ 1 ] = light->color[ 2 ] = 1.0f;
-		
-		intensity = intensity * pointScale;
-		light->photons = intensity;
-		
-		light->type = EMIT_POINT;
-		
-		/* set falloff threshold */
-		light->falloffTolerance = falloffTolerance / numSamples;
-		
-		/* lights with a target will be spotlights */
-		target = ValueForKey( e, "target" );
-		if( target[ 0 ] )
-		{
-			float		radius;
-			float		dist;
-			sun_t		sun;
-			const char	*_sun;
-			
-			
-			/* get target */
-			e2 = FindTargetEntity( target );
-			if( e2 == NULL )
-			{
-				Sys_Printf( "WARNING: light at (%i %i %i) has missing target\n",
-					(int) light->origin[ 0 ], (int) light->origin[ 1 ], (int) light->origin[ 2 ] );
-			}
-			else
-			{
-				/* not a point light */
-				numPointLights--;
-				numSpotLights++;
-				
-				/* make a spotlight */
-				GetVectorForKey( e2, "origin", dest );
-				VectorSubtract( dest, light->origin, light->normal );
-				dist = VectorNormalize( light->normal, light->normal );
-				radius = FloatForKey( e, "radius" );
-				if( !radius )
-					radius = 64;
-				if( !dist )
-					dist = 64;
-				light->radiusByDist = (radius + 16) / dist;
-				light->type = EMIT_SPOT;
-				
-				/* ydnar: wolf mods: spotlights always use nonlinear + angle attenuation */
-				light->flags &= ~LIGHT_ATTEN_LINEAR;
-				light->flags |= LIGHT_ATTEN_ANGLE;
-				light->fade = 1.0f;
-				
-				/* ydnar: is this a sun? */
-				_sun = ValueForKey( e, "_sun" );
-				if( _sun[ 0 ] == '1' )
-				{
-					/* not a spot light */
-					numSpotLights--;
-					
-					/* unlink this light */
-					lights = light->next;
-					
-					/* make a sun */
-					VectorScale( light->normal, -1.0f, sun.direction );
-					VectorCopy( light->color, sun.color );
-					sun.photons = (intensity / pointScale);
-					sun.deviance = deviance / 180.0f * Q_PI;
-					sun.numSamples = numSamples;
-					sun.next = NULL;
-					
-					/* make a sun light */
-					CreateSunLight( &sun );
-					
-					/* free original light */
-					free( light );
-					light = NULL;
-					
-					/* skip the rest of this love story */
-					continue;
-				}
-			}
-		}
-		
-		/* jitter the light */
-		for( j = 1; j < numSamples; j++ )
-		{
-			/* create a light */
-			light2 = safe_malloc( sizeof( *light ) );
-			memcpy( light2, light, sizeof( *light ) );
-			light2->next = lights;
-			lights = light2;
-			
-			/* add to counts */
-			if( light->type == EMIT_SPOT )
-				numSpotLights++;
-			else
-				numPointLights++;
-			
-			/* jitter it */
-			light2->origin[ 0 ] = light->origin[ 0 ] + (Random() * 2.0f - 1.0f) * deviance;
-			light2->origin[ 1 ] = light->origin[ 1 ] + (Random() * 2.0f - 1.0f) * deviance;
-			light2->origin[ 2 ] = light->origin[ 2 ] + (Random() * 2.0f - 1.0f) * deviance;
-		}
-	}
-}
-
-
-
-/*
-CreateSurfaceLights() - ydnar
-this hijacks the radiosity code to generate surface lights for first pass
-*/
-
-#define APPROX_BOUNCE	1.0f
-
-void CreateSurfaceLights( void )
-{
-	int					i;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	shaderInfo_t		*si;
-	light_t				*light;
-	float				subdivide;
-	vec3_t				origin;
-	clipWork_t			cw;
-	const char			*nss;
-	
-	
-	/* get sun shader supressor */
-	nss = ValueForKey( &entities[ 0 ], "_noshadersun" );
-	
-	/* walk the list of surfaces */
-	for( i = 0; i < numBSPDrawSurfaces; i++ )
-	{
-		/* get surface and other bits */
-		ds = &bspDrawSurfaces[ i ];
-		info = &surfaceInfos[ i ];
-		si = info->si;
-		
-		/* sunlight? */
-		if( si->sun != NULL && nss[ 0 ] != '1' )
-		{
-			Sys_FPrintf( SYS_VRB, "Sun: %s\n", si->shader );
-			CreateSunLight( si->sun );
-			si->sun = NULL; /* FIXME: leak! */
-		}
-		
-		/* sky light? */
-		if( si->skyLightValue > 0.0f )
-		{
-			Sys_FPrintf( SYS_VRB, "Sky: %s\n", si->shader );
-			CreateSkyLights( si->color, si->skyLightValue, si->skyLightIterations, si->lightFilterRadius );
-			si->skyLightValue = 0.0f;	/* FIXME: hack! */
-		}
-		
-		/* try to early out */
-		if( si->value <= 0 )
-			continue;
-		
-		/* autosprite shaders become point lights */
-		if( si->autosprite )
-		{
-			/* create an average xyz */
-			VectorAdd( info->mins, info->maxs, origin );
-			VectorScale( origin, 0.5f, origin );
-			
-			/* create a light */
-			light = safe_malloc( sizeof( *light ) );
-			memset( light, 0, sizeof( *light ) );
-			light->next = lights;
-			lights = light;
-			
-			/* set it up */
-			light->flags = LIGHT_Q3A_DEFAULT;
-			light->type = EMIT_POINT;
-			light->photons = si->value * pointScale;
-			light->fade = 1.0f;
-			light->si = si;
-			VectorCopy( origin, light->origin );
-			VectorCopy( si->color, light->color );
-			light->falloffTolerance = falloffTolerance;
-			light->style = light->style;
-			
-			/* add to point light count and continue */
-			numPointLights++;
-			continue;
-		}
-		
-		/* get subdivision amount */
-		if( si->lightSubdivide > 0 )
-			subdivide = si->lightSubdivide;
-		else
-			subdivide = defaultLightSubdivide;
-		
-		/* switch on type */
-		switch( ds->surfaceType )
-		{
-			case MST_PLANAR:
-			case MST_TRIANGLE_SOUP:
-				RadLightForTriangles( i, 0, info->lm, si, APPROX_BOUNCE, subdivide, &cw );
-				break;
-			
-			case MST_PATCH:
-				RadLightForPatch( i, 0, info->lm, si, APPROX_BOUNCE, subdivide, &cw );
-				break;
-			
-			default:
-				break;
-		}
-	}
-}
-
-
-
-/*
-SetEntityOrigins()
-find the offset values for inline models
-*/
-
-void SetEntityOrigins( void )
-{
-	int					i, j, k, f;
-	entity_t			*e;
-	vec3_t				origin;
-	const char			*key;
-	int					modelnum;
-	bspModel_t			*dm;
-	bspDrawSurface_t	*ds;
-	
-	
-	/* ydnar: copy drawverts into private storage for nefarious purposes */
-	yDrawVerts = safe_malloc( numBSPDrawVerts * sizeof( bspDrawVert_t ) );
-	memcpy( yDrawVerts, bspDrawVerts, numBSPDrawVerts * sizeof( bspDrawVert_t ) );
-	
-	/* set the entity origins */
-	for( i = 0; i < numEntities; i++ )
-	{
-		/* get entity and model */
-		e = &entities[ i ];
-		key = ValueForKey( e, "model" );
-		if( key[ 0 ] != '*' )
-			continue;
-		modelnum = atoi( key + 1 );
-		dm = &bspModels[ modelnum ];
-		
-		/* get entity origin */
-		key = ValueForKey( e, "origin" );
-		if( key[ 0 ] == '\0' )
-			continue;
-		GetVectorForKey( e, "origin", origin );
-		
-		/* set origin for all surfaces for this model */
-		for( j = 0; j < dm->numBSPSurfaces; j++ )
-		{
-			/* get drawsurf */
-			ds = &bspDrawSurfaces[ dm->firstBSPSurface + j ];
-			
-			/* set its verts */
-			for( k = 0; k < ds->numVerts; k++ )
-			{
-				f = ds->firstVert + k;
-				VectorAdd( origin, bspDrawVerts[ f ].xyz, yDrawVerts[ f ].xyz );
-			}
-		}
-	}
-}
-
-
-
-/*
-PointToPolygonFormFactor()
-calculates the area over a point/normal hemisphere a winding covers
-ydnar: fixme: there has to be a faster way to calculate this
-without the expensive per-vert sqrts and transcendental functions
-ydnar 2002-09-30: added -faster switch because only 19% deviance > 10%
-between this and the approximation
-*/
-
-#define ONE_OVER_2PI	0.159154942f	//% (1.0f / (2.0f * 3.141592657f))
-
-float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w )
-{
-	vec3_t		triVector, triNormal;
-	int			i, j;
-	vec3_t		dirs[ MAX_POINTS_ON_WINDING ];
-	float		total;
-	float		dot, angle, facing;
-	
-	
-	/* this is expensive */
-	for( i = 0; i < w->numpoints; i++ )
-	{
-		VectorSubtract( w->p[ i ], point, dirs[ i ] );
-		VectorNormalize( dirs[ i ], dirs[ i ] );
-	}
-	
-	/* duplicate first vertex to avoid mod operation */
-	VectorCopy( dirs[ 0 ], dirs[ i ] );
-	
-	/* calculcate relative area */
-	total = 0.0f;
-	for( i = 0; i < w->numpoints; i++ )
-	{
-		/* get a triangle */
-		j = i + 1;
-		dot = DotProduct( dirs[ i ], dirs[ j ] );
-		
-		/* roundoff can cause slight creep, which gives an IND from acos */
-		if( dot > 1.0f )
-			dot = 1.0f;
-		else if( dot < -1.0f )
-			dot = -1.0f;
-		
-		/* get the angle */
-		angle = acos( dot );
-		
-		CrossProduct( dirs[ i ], dirs[ j ], triVector );
-		if( VectorNormalize( triVector, triNormal ) < 0.0001f )
-			continue;
-		
-		facing = DotProduct( normal, triNormal );
-		total += facing * angle;
-		
-		/* ydnar: this was throwing too many errors with radiosity + crappy maps. ignoring it. */
-		if( total > 6.3f || total < -6.3f )
-			return 0.0f;
-	}
-	
-	/* now in the range of 0 to 1 over the entire incoming hemisphere */
-	//%	total /= (2.0f * 3.141592657f);
-	total *= ONE_OVER_2PI;
-	return total;
-}
-
-
-
-/*
-LightContributionTosample()
-determines the amount of light reaching a sample (luxel or vertex) from a given light
-*/
-
-int LightContributionToSample( trace_t *trace )
-{
-	light_t			*light;
-	float			angle;
-	float			add;
-	float			dist;
-	
-	
-	/* get light */
-	light = trace->light;
-	
-	/* clear color */
-	VectorClear( trace->color );
-	
-	/* ydnar: early out */
-	if( !(light->flags & LIGHT_SURFACES) || light->envelope <= 0.0f )
-		return 0;
-	
-	/* do some culling checks */
-	if( light->type != EMIT_SUN )
-	{
-		/* MrE: if the light is behind the surface */
-		if( trace->twoSided == qfalse )
-			if( DotProduct( light->origin, trace->normal ) - DotProduct( trace->origin, trace->normal ) < 0.0f )
-				return 0;
-		
-		/* ydnar: test pvs */
-		if( !ClusterVisible( trace->cluster, light->cluster ) )
-			return 0;
-	}
-	
-	/* ptpff approximation */
-	if( light->type == EMIT_AREA && faster )
-	{
-		/* get direction and distance */
-		VectorCopy( light->origin, trace->end );
-		dist = SetupTrace( trace );
-		if( dist >= light->envelope )
-			return 0;
-		
-		/* clamp the distance to prevent super hot spots */
-		if( dist < 16.0f )
-			dist = 16.0f;
-		
-		/* angle attenuation */
-		angle = DotProduct( trace->normal, trace->direction );
-		
-		/* twosided lighting */
-		if( trace->twoSided )
-			angle = fabs( angle );
-		
-		/* attenuate */
-		angle *= -DotProduct( light->normal, trace->direction );
-		if( angle <= 0.0f )
-			return 0;
-		add = light->photons / (dist * dist) * angle;
-	}
-	
-	/* exact point to polygon form factor */
-	else if( light->type == EMIT_AREA )
-	{
-		float		factor;
-		float		d;
-		vec3_t		pushedOrigin;
-		
-		
-		/* project sample point into light plane */
-		d = DotProduct( trace->origin, light->normal ) - light->dist;
-		//%	if( !(light->flags & LIGHT_TWOSIDED) && d < -1.0f )
-		//%		return 0;
-		if( d < 3.0f )
-		{
-			/* sample point behind plane? */
-			if( !(light->flags & LIGHT_TWOSIDED) && d < -1.0f )
-				return 0;
-			
-			/* sample plane coincident? */
-			if( d > -3.0f && DotProduct( trace->normal, light->normal ) > 0.9f )
-				return 0;
-		}
-		
-		/* nudge the point so that it is clearly forward of the light */
-		/* so that surfaces meeting a light emiter don't get black edges */
-		if( d > -8.0f && d < 8.0f )
-			VectorMA( trace->origin, (8.0f - d), light->normal, pushedOrigin );				
-		else
-			VectorCopy( trace->origin, pushedOrigin );
-		
-		/* get direction and distance */
-		VectorCopy( light->origin, trace->end );
-		dist = SetupTrace( trace );
-		if( dist >= light->envelope )
-			return 0;
-		
-		/* calculate the contribution */
-		factor = PointToPolygonFormFactor( pushedOrigin, trace->normal, light->w );
-		if( factor == 0.0f )
-			return 0;
-		else if( factor < 0.0f )
-		{
-			/* twosided lighting */
-			if( trace->twoSided || (light->flags & LIGHT_TWOSIDED) )
-			{
-				factor = -factor;
-
-				/* push light origin to other side of the plane */
-				VectorMA( light->origin, -2.0f, light->normal, trace->end );
-				dist = SetupTrace( trace );
-				if( dist >= light->envelope )
-					return 0;
-			}
-			else
-				return 0;
-		}
-		
-		/* ydnar: moved to here */
-		add = factor * light->add;
-	}
-	
-	/* point/spot lights */
-	else if( light->type == EMIT_POINT || light->type == EMIT_SPOT )
-	{
-		/* get direction and distance */
-		VectorCopy( light->origin, trace->end );
-		dist = SetupTrace( trace );
-		if( dist >= light->envelope )
-			return 0;
-		
-		/* clamp the distance to prevent super hot spots */
-		if( dist < 16.0f )
-			dist = 16.0f;
-		
-		/* angle attenuation */
-		angle = (light->flags & LIGHT_ATTEN_ANGLE) ? DotProduct( trace->normal, trace->direction ) : 1.0f;
-		if( light->angleScale != 0.0f )
-		{
-			angle /= light->angleScale;
-			if( angle > 1.0f )
-				angle = 1.0f;
-		}
-		
-		/* twosided lighting */
-		if( trace->twoSided )
-			angle = fabs( angle );
-		
-		/* attenuate */
-		if( light->flags & LIGHT_ATTEN_LINEAR )
-		{
-			add = angle * light->photons * linearScale - (dist * light->fade);
-			if( add < 0.0f )
-				add = 0.0f;
-		}
-		else
-			add = light->photons / (dist * dist) * angle;
-		
-		/* handle spotlights */
-		if( light->type == EMIT_SPOT )
-		{
-			float	distByNormal, radiusAtDist, sampleRadius;
-			vec3_t	pointAtDist, distToSample;
-			
-			
-			/* do cone calculation */
-			distByNormal = -DotProduct( trace->displacement, light->normal );
-			if( distByNormal < 0.0f )
-				return 0;
-			VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
-			radiusAtDist = light->radiusByDist * distByNormal;
-			VectorSubtract( trace->origin, pointAtDist, distToSample );
-			sampleRadius = VectorLength( distToSample );
-			
-			/* outside the cone */
-			if( sampleRadius >= radiusAtDist )
-				return 0;
-			
-			/* attenuate */
-			if( sampleRadius > (radiusAtDist - 32.0f) )
-				add *= ((radiusAtDist - sampleRadius) / 32.0f);
-		}
-	}
-	
-	/* ydnar: sunlight */
-	else if( light->type == EMIT_SUN )
-	{
-		/* get origin and direction */
-		VectorAdd( trace->origin, light->origin, trace->end );
-		dist = SetupTrace( trace );
-		
-		/* angle attenuation */
-		angle = (light->flags & LIGHT_ATTEN_ANGLE)
-			? DotProduct( trace->normal, trace->direction )
-			: 1.0f;
-		
-		/* twosided lighting */
-		if( trace->twoSided )
-			angle = fabs( angle );
-		
-		/* attenuate */
-		add = light->photons * angle;
-		if( add <= 0.0f )
-			return 0;
-		
-		/* setup trace */
-		trace->testAll = qtrue;
-		VectorScale( light->color, add, trace->color );
-		
-		/* trace to point */
-		if( trace->testOcclusion && !trace->forceSunlight )
-		{
-			/* trace */
-			TraceLine( trace );
-			if( !(trace->compileFlags & C_SKY) || trace->opaque )
-			{
-				VectorClear( trace->color );
-				return -1;
-			}
-		}
-		
-		/* return to sender */
-		return 1;
-	}
-	
-	/* ydnar: changed to a variable number */
-	if( add <= 0.0f || (add <= light->falloffTolerance && (light->flags & LIGHT_FAST_ACTUAL)) )
-		return 0;
-	
-	/* setup trace */
-	trace->testAll = qfalse;
-	VectorScale( light->color, add, trace->color );
-	
-	/* raytrace */
-	TraceLine( trace );
-	if( trace->passSolid || trace->opaque )
-	{
-		VectorClear( trace->color );
-		return -1;
-	}
-	
-	/* return to sender */
-	return 1;
-}
-
-
-
-/*
-LightingAtSample()
-determines the amount of light reaching a sample (luxel or vertex)
-*/
-
-void LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colors[ MAX_LIGHTMAPS ] )
-{
-	int				i, lightmapNum;
-	
-	
-	/* clear colors */
-	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		VectorClear( colors[ lightmapNum ] );
-	
-	/* ydnar: normalmap */
-	if( normalmap )
-	{
-		colors[ 0 ][ 0 ] = (trace->normal[ 0 ] + 1.0f) * 127.5f;
-		colors[ 0 ][ 1 ] = (trace->normal[ 1 ] + 1.0f) * 127.5f;
-		colors[ 0 ][ 2 ] = (trace->normal[ 2 ] + 1.0f) * 127.5f;
-		return;
-	}
-	
-	/* ydnar: don't bounce ambient all the time */
-	if( !bouncing )
-		VectorCopy( ambientColor, colors[ 0 ] );
-	
-	/* ydnar: trace to all the list of lights pre-stored in tw */
-	for( i = 0; i < trace->numLights && trace->lights[ i ] != NULL; i++ )
-	{
-		/* set light */
-		trace->light = trace->lights[ i ];
-		
-		/* style check */
-		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		{
-			if( styles[ lightmapNum ] == trace->light->style ||
-				styles[ lightmapNum ] == LS_NONE )
-				break;
-		}
-		
-		/* max of MAX_LIGHTMAPS (4) styles allowed to hit a sample */
-		if( lightmapNum >= MAX_LIGHTMAPS )
-			continue;
-		
-		/* sample light */
-		LightContributionToSample( trace );
-		if( trace->color[ 0 ] == 0.0f && trace->color[ 1 ] == 0.0f && trace->color[ 2 ] == 0.0f )
-			continue;
-		
-		/* handle negative light */
-		if( trace->light->flags & LIGHT_NEGATIVE )
-			VectorScale( trace->color, -1.0f, trace->color );
-		
-		/* set style */
-		styles[ lightmapNum ] = trace->light->style;
-		
-		/* add it */
-		VectorAdd( colors[ lightmapNum ], trace->color, colors[ lightmapNum ] );
-		
-		/* cheap mode */
-		if( cheap &&
-			colors[ 0 ][ 0 ] >= 255.0f &&
-			colors[ 0 ][ 1 ] >= 255.0f &&
-			colors[ 0 ][ 2 ] >= 255.0f )
-			break;
-	}
-}
-
-
-
-/*
-LightContributionToPoint()
-for a given light, how much light/color reaches a given point in space (with no facing)
-note: this is similar to LightContributionToSample() but optimized for omnidirectional sampling
-*/
-
-int LightContributionToPoint( trace_t *trace )
-{
-	light_t		*light;
-	float		add, dist;
-	
-	
-	/* get light */
-	light = trace->light;
-	
-	/* clear color */
-	VectorClear( trace->color );
-	
-	/* ydnar: early out */
-	if( !(light->flags & LIGHT_GRID) || light->envelope <= 0.0f )
-		return qfalse;
-	
-	/* is this a sun? */
-	if( light->type != EMIT_SUN )
-	{
-		/* sun only? */
-		if( sunOnly )
-			return qfalse;
-		
-		/* test pvs */
-		if( !ClusterVisible( trace->cluster, light->cluster ) )
-			return qfalse;
-	}
-	
-	/* ydnar: check origin against light's pvs envelope */
-	if( trace->origin[ 0 ] > light->maxs[ 0 ] || trace->origin[ 0 ] < light->mins[ 0 ] ||
-		trace->origin[ 1 ] > light->maxs[ 1 ] || trace->origin[ 1 ] < light->mins[ 1 ] ||
-		trace->origin[ 2 ] > light->maxs[ 2 ] || trace->origin[ 2 ] < light->mins[ 2 ] )
-	{
-		gridBoundsCulled++;
-		return qfalse;
-	}
-	
-	/* set light origin */
-	if( light->type == EMIT_SUN )
-		VectorAdd( trace->origin, light->origin, trace->end );
-	else
-		VectorCopy( light->origin, trace->end );
-	
-	/* set direction */
-	dist = SetupTrace( trace );
-	
-	/* test envelope */
-	if( dist > light->envelope )
-	{
-		gridEnvelopeCulled++;
-		return qfalse;
-	}
-	
-	/* ptpff approximation */
-	if( light->type == EMIT_AREA && faster )
-	{
-		/* clamp the distance to prevent super hot spots */
-		if( dist < 16.0f )
-			dist = 16.0f;
-		
-		/* attenuate */
-		add = light->photons / (dist * dist);
-	}
-	
-	/* exact point to polygon form factor */
-	else if( light->type == EMIT_AREA )
-	{
-		float		factor, d;
-		vec3_t		pushedOrigin;
-		
-		
-		/* see if the point is behind the light */
-		d = DotProduct( trace->origin, light->normal ) - light->dist;
-		if( !(light->flags & LIGHT_TWOSIDED) && d < -1.0f )
-			return qfalse;
-		
-		/* nudge the point so that it is clearly forward of the light */
-		/* so that surfaces meeting a light emiter don't get black edges */
-		if( d > -8.0f && d < 8.0f )
-			VectorMA( trace->origin, (8.0f - d), light->normal, pushedOrigin );				
-		else
-			VectorCopy( trace->origin, pushedOrigin );
-		
-		/* calculate the contribution (ydnar 2002-10-21: [bug 642] bad normal calc) */
-		factor = PointToPolygonFormFactor( pushedOrigin, trace->direction, light->w );
-		if( factor == 0.0f )
-			return qfalse;
-		else if( factor < 0.0f )
-		{
-			if( light->flags & LIGHT_TWOSIDED )
-				factor = -factor;
-			else
-				return qfalse;
-		}
-		
-		/* ydnar: moved to here */
-		add = factor * light->add;
-	}
-	
-	/* point/spot lights */
-	else if( light->type == EMIT_POINT || light->type == EMIT_SPOT )
-	{
-		/* clamp the distance to prevent super hot spots */
-		if( dist < 16.0f )
-			dist = 16.0f;
-		
-		/* attenuate */
-		if( light->flags & LIGHT_ATTEN_LINEAR )
-		{
-			add = light->photons * linearScale - (dist * light->fade);
-			if( add < 0.0f )
-				add = 0.0f;
-		}
-		else
-			add = light->photons / (dist * dist);
-		
-		/* handle spotlights */
-		if( light->type == EMIT_SPOT )
-		{
-			float	distByNormal, radiusAtDist, sampleRadius;
-			vec3_t	pointAtDist, distToSample;
-			
-			
-			/* do cone calculation */
-			distByNormal = -DotProduct( trace->displacement, light->normal );
-			if( distByNormal < 0.0f )
-				return qfalse;
-			VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
-			radiusAtDist = light->radiusByDist * distByNormal;
-			VectorSubtract( trace->origin, pointAtDist, distToSample );
-			sampleRadius = VectorLength( distToSample );
-			
-			/* outside the cone */
-			if( sampleRadius >= radiusAtDist )
-				return qfalse;
-			
-			/* attenuate */
-			if( sampleRadius > (radiusAtDist - 32.0f) )
-				add *= ((radiusAtDist - sampleRadius) / 32.0f);
-		}
-	}
-	
-	/* ydnar: sunlight */
-	else if( light->type == EMIT_SUN )
-	{
-		/* attenuate */
-		add = light->photons;
-		if( add <= 0.0f )
-			return qfalse;
-		
-		/* setup trace */
-		trace->testAll = qtrue;
-		VectorScale( light->color, add, trace->color );
-		
-		/* trace to point */
-		if( trace->testOcclusion && !trace->forceSunlight )
-		{
-			/* trace */
-			TraceLine( trace );
-			if( !(trace->compileFlags & C_SKY) || trace->opaque )
-			{
-				VectorClear( trace->color );
-				return -1;
-			}
-		}
-		
-		/* return to sender */
-		return qtrue;
-	}
-	
-	/* unknown light type */
-	else
-		return qfalse;
-	
-	/* ydnar: changed to a variable number */
-	if( add <= 0.0f || (add <= light->falloffTolerance && (light->flags & LIGHT_FAST_ACTUAL)) )
-		return qfalse;
-	
-	/* setup trace */
-	trace->testAll = qfalse;
-	VectorScale( light->color, add, trace->color );
-	
-	/* trace */
-	TraceLine( trace );
-	if( trace->passSolid )
-	{
-		VectorClear( trace->color );
-		return qfalse;
-	}
-	
-	/* we have a valid sample */
-	return qtrue;
-}
-
-
-
-/*
-TraceGrid()
-grid samples are for quickly determining the lighting
-of dynamically placed entities in the world
-*/
-
-#define	MAX_CONTRIBUTIONS	1024
-
-typedef struct
-{
-	vec3_t		dir;
-	vec3_t		color;
-	int			style;
-}
-contribution_t;
-
-void TraceGrid( int num )
-{
-	int						i, j, x, y, z, mod, step, numCon, numStyles;
-	float					d;
-	vec3_t					baseOrigin, cheapColor, color;
-	rawGridPoint_t			*gp;
-	bspGridPoint_t			*bgp;
-	contribution_t			contributions[ MAX_CONTRIBUTIONS ];
-	trace_t					trace;
-	
-	
-	/* get grid points */
-	gp = &rawGridPoints[ num ];
-	bgp = &bspGridPoints[ num ];
-	
-	/* get grid origin */
-	mod = num;
-	z = mod / (gridBounds[ 0 ] * gridBounds[ 1 ]);
-	mod -= z * (gridBounds[ 0 ] * gridBounds[ 1 ]);
-	y = mod / gridBounds[ 0 ];
-	mod -= y * gridBounds[ 0 ];
-	x = mod;
-	
-	trace.origin[ 0 ] = gridMins[ 0 ] + x * gridSize[ 0 ];
-	trace.origin[ 1 ] = gridMins[ 1 ] + y * gridSize[ 1 ];
-	trace.origin[ 2 ] = gridMins[ 2 ] + z * gridSize[ 2 ];
-	
-	/* set inhibit sphere */
-	if( gridSize[ 0 ] > gridSize[ 1 ] && gridSize[ 0 ] > gridSize[ 2 ] )
-		trace.inhibitRadius = gridSize[ 0 ] * 0.5f;
-	else if( gridSize[ 1 ] > gridSize[ 0 ] && gridSize[ 1 ] > gridSize[ 2 ] )
-		trace.inhibitRadius = gridSize[ 1 ] * 0.5f;
-	else
-		trace.inhibitRadius = gridSize[ 2 ] * 0.5f;
-	
-	/* find point cluster */
-	trace.cluster = ClusterForPointExt( trace.origin, GRID_EPSILON );
-	if( trace.cluster < 0 )
-	{
-		/* try to nudge the origin around to find a valid point */
-		VectorCopy( trace.origin, baseOrigin );
-		for( step = 9; step <= 18; step += 9 )
-		{
-			for( i = 0; i < 8; i++ )
-			{
-				VectorCopy( baseOrigin, trace.origin );
-				if( i & 1 )
-					trace.origin[ 0 ] += step;
-				else
-					trace.origin[ 0 ] -= step;
-				
-				if( i & 2 )
-					trace.origin[ 1 ] += step;
-				else
-					trace.origin[ 1 ] -= step;
-				
-				if( i & 4 )
-					trace.origin[ 2 ] += step;
-				else
-					trace.origin[ 2 ] -= step;
-				
-				/* ydnar: changed to find cluster num */
-				trace.cluster = ClusterForPointExt( trace.origin, VERTEX_EPSILON );
-				if( trace.cluster >= 0 )
-					break;
-			}
-			
-			if( i != 8 )
-				break;
-		}
-		
-		/* can't find a valid point at all */
-		if( step > 18 )
-			return;
-	}
-	
-	/* setup trace */
-	trace.testOcclusion = !noTrace;
-	trace.forceSunlight = qfalse;
-	trace.recvShadows = WORLDSPAWN_RECV_SHADOWS;
-	trace.numSurfaces = 0;
-	trace.surfaces = NULL;
-	trace.numLights = 0;
-	trace.lights = NULL;
-	
-	/* clear */
-	numCon = 0;
-	VectorClear( cheapColor );
-	
-	/* trace to all the lights, find the major light direction, and divide the
-	   total light between that along the direction and the remaining in the ambient */
-	for( trace.light = lights; trace.light != NULL; trace.light = trace.light->next )
-	{
-		float		addSize;
-		
-		
-		/* sample light */
-		if( !LightContributionToPoint( &trace ) )
-			continue;
-		
-		/* handle negative light */
-		if( trace.light->flags & LIGHT_NEGATIVE )
-			VectorScale( trace.color, -1.0f, trace.color );
-		
-		/* add a contribution */
-		VectorCopy( trace.color, contributions[ numCon ].color );
-		VectorCopy( trace.direction, contributions[ numCon ].dir );
-		contributions[ numCon ].style = trace.light->style;
-		numCon++;
-		
-		/* push average direction around */
-		addSize = VectorLength( trace.color );
-		VectorMA( gp->dir, addSize, trace.direction, gp->dir );
-		
-		/* stop after a while */
-		if( numCon >= (MAX_CONTRIBUTIONS - 1) )
-			break;
-		
-		/* ydnar: cheap mode */
-		VectorAdd( cheapColor, trace.color, cheapColor );
-		if( cheapgrid && cheapColor[ 0 ] >= 255.0f && cheapColor[ 1 ] >= 255.0f && cheapColor[ 2 ] >= 255.0f )
-			break;
-	}
-	
-	/* normalize to get primary light direction */
-	VectorNormalize( gp->dir, gp->dir );
-	
-	/* now that we have identified the primary light direction,
-	   go back and separate all the light into directed and ambient */
-	numStyles = 1;
-	for( i = 0; i < numCon; i++ )
-	{
-		/* get relative directed strength */
-		d = DotProduct( contributions[ i ].dir, gp->dir );
-		if( d < 0.0f )
-			d = 0.0f;
-		
-		/* find appropriate style */
-		for( j = 0; j < numStyles; j++ )
-		{
-			if( gp->styles[ j ] == contributions[ i ].style )
-				break;
-		}
-		
-		/* style not found? */
-		if( j >= numStyles )
-		{
-			/* add a new style */
-			if( numStyles < MAX_LIGHTMAPS )
-			{
-				gp->styles[ numStyles ] = contributions[ i ].style;
-				bgp->styles[ numStyles ] = contributions[ i ].style;
-				numStyles++;
-				//%	Sys_Printf( "(%d, %d) ", num, contributions[ i ].style );
-			}
-			
-			/* fallback */
-			else
-				j = 0;
-		}
-		
-		/* add the directed color */
-		VectorMA( gp->directed[ j ], d, contributions[ i ].color, gp->directed[ j ] );
-		
-		/* ambient light will be at 1/4 the value of directed light */
-		/* (ydnar: nuke this in favor of more dramatic lighting?) */
-		d = 0.25f * (1.0f - d);
-		VectorMA( gp->ambient[ j ], d, contributions[ i ].color, gp->ambient[ j ] );
-	}
-	
-	
-	/* store off sample */
-	for( i = 0; i < MAX_LIGHTMAPS; i++ )
-	{
-		/* do some fudging to keep the ambient from being too low (2003-07-05: 0.25 -> 0.125) */
-		if( !bouncing )
-			VectorMA( gp->ambient[ i ], 0.125f, gp->directed[ i ], gp->ambient[ i ] );
-		
-		/* set minimum light and copy off to bytes */
-		VectorCopy( gp->ambient[ i ], color );
-		for( j = 0; j < 3; j++ )
-			if( color[ j ] < minGridLight[ j ] )
-				color[ j ] = minGridLight[ j ];
-		ColorToBytes( color, bgp->ambient[ i ], 1.0f );
-		ColorToBytes( gp->directed[ i ], bgp->directed[ i ], 1.0f );
-	}
-	
-	/* debug code */
-	#if 0
-		//%	Sys_FPrintf( SYS_VRB, "%10d %10d %10d ", &gp->ambient[ 0 ][ 0 ], &gp->ambient[ 0 ][ 1 ], &gp->ambient[ 0 ][ 2 ] );
-		Sys_FPrintf( SYS_VRB, "%9d Amb: (%03.1f %03.1f %03.1f) Dir: (%03.1f %03.1f %03.1f)\n",
-			num,
-			gp->ambient[ 0 ][ 0 ], gp->ambient[ 0 ][ 1 ], gp->ambient[ 0 ][ 2 ],
-			gp->directed[ 0 ][ 0 ], gp->directed[ 0 ][ 1 ], gp->directed[ 0 ][ 2 ] );
-	#endif
-	
-	/* store direction */
-	NormalToLatLong( gp->dir, bgp->latLong );
-}
-
-
-
-/*
-SetupGrid()
-calculates the size of the lightgrid and allocates memory
-*/
-
-void SetupGrid( void )
-{
-	int			i, j;
-	vec3_t		maxs, oldGridSize;
-	const char	*value;
-	char		temp[ 64 ];
-	
-	 
-	/* don't do this if not grid lighting */
-	if( noGridLighting )
-		return;
-	
-	/* ydnar: set grid size */
-	value = ValueForKey( &entities[ 0 ], "gridsize" );
-	if( value[ 0 ] != '\0' )
-		sscanf( value, "%f %f %f", &gridSize[ 0 ], &gridSize[ 1 ], &gridSize[ 2 ] );
-	
-	/* quantize it */
-	VectorCopy( gridSize, oldGridSize );
-	for( i = 0; i < 3; i++ )
-		gridSize[ i ] = gridSize[ i ] >= 8.0f ? floor( gridSize[ i ] ) : 8.0f;
-	
-	/* ydnar: increase gridSize until grid count is smaller than max allowed */
-	numRawGridPoints = MAX_MAP_LIGHTGRID + 1;
-	j = 0;
-	while( numRawGridPoints > MAX_MAP_LIGHTGRID )
-	{
-		/* get world bounds */
-		for( i = 0; i < 3; i++ )
-		{
-			gridMins[ i ] = gridSize[ i ] * ceil( bspModels[ 0 ].mins[ i ] / gridSize[ i ] );
-			maxs[ i ] = gridSize[ i ] * floor( bspModels[ 0 ].maxs[ i ] / gridSize[ i ] );
-			gridBounds[ i ] = (maxs[ i ] - gridMins[ i ]) / gridSize[ i ] + 1;
-		}
-	
-		/* set grid size */
-		numRawGridPoints = gridBounds[ 0 ] * gridBounds[ 1 ] * gridBounds[ 2 ];
-		
-		/* increase grid size a bit */
-		if( numRawGridPoints > MAX_MAP_LIGHTGRID )
-			gridSize[ j++ % 3 ] += 16.0f;
-	}
-	
-	/* print it */
-	Sys_Printf( "Grid size = { %1.0f, %1.0f, %1.0f }\n", gridSize[ 0 ], gridSize[ 1 ], gridSize[ 2 ] );
-	
-	/* different? */
-	if( !VectorCompare( gridSize, oldGridSize ) )
-	{
-		sprintf( temp, "%.0f %.0f %.0f", gridSize[ 0 ], gridSize[ 1 ], gridSize[ 2 ] );
-		SetKeyValue( &entities[ 0 ], "gridsize", (const char*) temp );
-		Sys_FPrintf( SYS_VRB, "Storing adjusted grid size\n" );
-	}
-	
-	/* 2nd variable. fixme: is this silly? */
-	numBSPGridPoints = numRawGridPoints;
-	
-	/* allocate lightgrid */
-	rawGridPoints = safe_malloc( numRawGridPoints * sizeof( *rawGridPoints ) );
-	memset( rawGridPoints, 0, numRawGridPoints * sizeof( *rawGridPoints ) );
-	
-	if( bspGridPoints != NULL )
-		free( bspGridPoints );
-	bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
-	memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
-	
-	/* clear lightgrid */
-	for( i = 0; i < numRawGridPoints; i++ )
-	{
-		VectorCopy( ambientColor, rawGridPoints[ i ].ambient[ j ] );
-		rawGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
-		bspGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
-		for( j = 1; j < MAX_LIGHTMAPS; j++ )
-		{
-			rawGridPoints[ i ].styles[ j ] = LS_NONE;
-			bspGridPoints[ i ].styles[ j ] = LS_NONE;
-		}
-	}
-	
-	/* note it */
-	Sys_Printf( "%9d grid points\n", numRawGridPoints );
-}
-
-
-
-/*
-LightWorld()
-does what it says...
-*/
-
-void LightWorld( void )
-{
-	vec3_t		color;
-	float		f;
-	int			b, bt;
-	qboolean	minVertex, minGrid;
-	const char	*value;
-	
-
-	/* ydnar: smooth normals */
-	if( shade )
-	{
-		Sys_Printf( "--- SmoothNormals ---\n" );
-		SmoothNormals();
-	}
-	
-	/* determine the number of grid points */
-	Sys_Printf( "--- SetupGrid ---\n" );
-	SetupGrid();
-	
-	/* find the optional minimum lighting values */
-	GetVectorForKey( &entities[ 0 ], "_color", color );
-	if( VectorLength( color ) == 0.0f )
-		VectorSet( color, 1.0, 1.0, 1.0 );
-	
-	/* ambient */
-	f = FloatForKey( &entities[ 0 ], "_ambient" );
-	if( f == 0.0f )
-		f = FloatForKey( &entities[ 0 ], "ambient" );
-	VectorScale( color, f, ambientColor );
-	
-	/* minvertexlight */
-	minVertex = qfalse;
-	value = ValueForKey( &entities[ 0 ], "_minvertexlight" );
-	if( value[ 0 ] != '\0' )
-	{
-		minVertex = qtrue;
-		f = atof( value );
-		VectorScale( color, f, minVertexLight );
-	}
-	
-	/* mingridlight */
-	minGrid = qfalse;
-	value = ValueForKey( &entities[ 0 ], "_mingridlight" );
-	if( value[ 0 ] != '\0' )
-	{
-		minGrid = qtrue;
-		f = atof( value );
-		VectorScale( color, f, minGridLight );
-	}
-	
-	/* minlight */
-	value = ValueForKey( &entities[ 0 ], "_minlight" );
-	if( value[ 0 ] != '\0' )
-	{
-		f = atof( value );
-		VectorScale( color, f, minLight );
-		if( minVertex == qfalse )
-			VectorScale( color, f, minVertexLight );
-		if( minGrid == qfalse )
-			VectorScale( color, f, minGridLight );
-	}
-	
-	/* create world lights */
-	Sys_FPrintf( SYS_VRB, "--- CreateLights ---\n" );
-	CreateEntityLights();
-	CreateSurfaceLights();
-	Sys_Printf( "%9d point lights\n", numPointLights );
-	Sys_Printf( "%9d spotlights\n", numSpotLights );
-	Sys_Printf( "%9d diffuse (area) lights\n", numDiffuseLights );
-	Sys_Printf( "%9d sun/sky lights\n", numSunLights );
-	
-	/* calculate lightgrid */
-	if( !noGridLighting )
-	{
-		/* ydnar: set up light envelopes */
-		SetupEnvelopes( qtrue, fastgrid );
-		
-		Sys_Printf( "--- TraceGrid ---\n" );
-		RunThreadsOnIndividual( numRawGridPoints, qtrue, TraceGrid );
-		Sys_Printf( "%d x %d x %d = %d grid\n",
-			gridBounds[ 0 ], gridBounds[ 1 ], gridBounds[ 2 ], numBSPGridPoints );
-		
-		/* ydnar: emit statistics on light culling */
-		Sys_FPrintf( SYS_VRB, "%9d grid points envelope culled\n", gridEnvelopeCulled );
-		Sys_FPrintf( SYS_VRB, "%9d grid points bounds culled\n", gridBoundsCulled );
-	}
-	
-	/* slight optimization to remove a sqrt */
-	subdivideThreshold *= subdivideThreshold;
-	
-	/* map the world luxels */
-	Sys_Printf( "--- MapRawLightmap ---\n" );
-	RunThreadsOnIndividual( numRawLightmaps, qtrue, MapRawLightmap );
-	Sys_Printf( "%9d luxels\n", numLuxels );
-	Sys_Printf( "%9d luxels mapped\n", numLuxelsMapped );
-	Sys_Printf( "%9d luxels occluded\n", numLuxelsOccluded );
-
-	/* ydnar: set up light envelopes */
-	SetupEnvelopes( qfalse, fast );
-	
-	/* light up my world */
-	lightsPlaneCulled = 0;
-	lightsEnvelopeCulled = 0;
-	lightsBoundsCulled = 0;
-	lightsClusterCulled = 0;
-	
-	Sys_Printf( "--- IlluminateRawLightmap ---\n" );
-	RunThreadsOnIndividual( numRawLightmaps, qtrue, IlluminateRawLightmap );
-	Sys_Printf( "%9d luxels illuminated\n", numLuxelsIlluminated );
-	
-	StitchSurfaceLightmaps();
-	
-	Sys_Printf( "--- IlluminateVertexes ---\n" );
-	RunThreadsOnIndividual( numBSPDrawSurfaces, qtrue, IlluminateVertexes );
-	Sys_Printf( "%9d vertexes illuminated\n", numVertsIlluminated );
-	
-	/* ydnar: emit statistics on light culling */
-	Sys_FPrintf( SYS_VRB, "%9d lights plane culled\n", lightsPlaneCulled );
-	Sys_FPrintf( SYS_VRB, "%9d lights envelope culled\n", lightsEnvelopeCulled );
-	Sys_FPrintf( SYS_VRB, "%9d lights bounds culled\n", lightsBoundsCulled );
-	Sys_FPrintf( SYS_VRB, "%9d lights cluster culled\n", lightsClusterCulled );
-	
-	/* radiosity */
-	b = 1;
-	bt = bounce;
-	while( bounce > 0 )
-	{
-		/* store off the bsp between bounces */
-		StoreSurfaceLightmaps();
-		Sys_Printf( "Writing %s\n", source );
-		WriteBSPFile( source );
-		
-		/* note it */
-		Sys_Printf( "\n--- Radiosity (bounce %d of %d) ---\n", b, bt );
-		
-		/* flag bouncing */
-		bouncing = qtrue;
-		VectorClear( ambientColor );
-		
-		/* generate diffuse lights */
-		RadFreeLights();
-		RadCreateDiffuseLights();
-		
-		/* setup light envelopes */
-		SetupEnvelopes( qfalse, fastbounce );
-		if( numLights == 0 )
-		{
-			Sys_Printf( "No diffuse light to calculate, ending radiosity.\n" );
-			break;
-		}
-		
-		/* add to lightgrid */
-		if( bouncegrid )
-		{
-			gridEnvelopeCulled = 0;
-			gridBoundsCulled = 0;
-			
-			Sys_Printf( "--- BounceGrid ---\n" );
-			RunThreadsOnIndividual( numRawGridPoints, qtrue, TraceGrid );
-			Sys_FPrintf( SYS_VRB, "%9d grid points envelope culled\n", gridEnvelopeCulled );
-			Sys_FPrintf( SYS_VRB, "%9d grid points bounds culled\n", gridBoundsCulled );
-		}
-		
-		/* light up my world */
-		lightsPlaneCulled = 0;
-		lightsEnvelopeCulled = 0;
-		lightsBoundsCulled = 0;
-		lightsClusterCulled = 0;
-		
-		Sys_Printf( "--- IlluminateRawLightmap ---\n" );
-		RunThreadsOnIndividual( numRawLightmaps, qtrue, IlluminateRawLightmap );
-		Sys_Printf( "%9d luxels illuminated\n", numLuxelsIlluminated );
-		Sys_Printf( "%9d vertexes illuminated\n", numVertsIlluminated );
-		
-		StitchSurfaceLightmaps();
-		
-		Sys_Printf( "--- IlluminateVertexes ---\n" );
-		RunThreadsOnIndividual( numBSPDrawSurfaces, qtrue, IlluminateVertexes );
-		Sys_Printf( "%9d vertexes illuminated\n", numVertsIlluminated );
-		
-		/* ydnar: emit statistics on light culling */
-		Sys_FPrintf( SYS_VRB, "%9d lights plane culled\n", lightsPlaneCulled );
-		Sys_FPrintf( SYS_VRB, "%9d lights envelope culled\n", lightsEnvelopeCulled );
-		Sys_FPrintf( SYS_VRB, "%9d lights bounds culled\n", lightsBoundsCulled );
-		Sys_FPrintf( SYS_VRB, "%9d lights cluster culled\n", lightsClusterCulled );
-		
-		/* interate */
-		bounce--;
-		b++;
-	}
-}
-
-
-
-/*
-LightMain()
-main routine for light processing
-*/
-
-int LightMain( int argc, char **argv )
-{
-	int			i;
-	float		f;
-	char		mapSource[ 1024 ];
-	const char	*value;
-	
-	
-	/* note it */
-	Sys_Printf( "--- Light ---\n" );
-	
-	/* process commandline arguments */
-	for( i = 1; i < (argc - 1); i++ )
-	{
-		/* lightsource scaling */
-		if( !strcmp( argv[ i ], "-point" ) || !strcmp( argv[ i ], "-pointscale" ) )
-		{
-			f = atof( argv[ i + 1 ] );
-			pointScale *= f;
-			Sys_Printf( "Point (entity) light scaled by %f to %f\n", f, pointScale );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-area" ) || !strcmp( argv[ i ], "-areascale" ) )
-		{
-			f = atof( argv[ i + 1 ] );
-			areaScale *= f;
-			Sys_Printf( "Area (shader) light scaled by %f to %f\n", f, areaScale );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-sky" ) || !strcmp( argv[ i ], "-skyscale" ) )
-		{
-			f = atof( argv[ i + 1 ] );
-			skyScale *= f;
-			Sys_Printf( "Sky/sun light scaled by %f to %f\n", f, skyScale );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-bouncescale" ) )
-		{
-			f = atof( argv[ i + 1 ] );
-			bounceScale *= f;
-			Sys_Printf( "Bounce (radiosity) light scaled by %f to %f\n", f, bounceScale );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-scale" ) )
-		{
-			f = atof( argv[ i + 1 ] );
-			pointScale *= f;
-			areaScale *= f;
-			skyScale *= f;
-			bounceScale *= f;
-			Sys_Printf( "All light scaled by %f\n", f );
-			i++;
-		}
-		
-		/* ydnar switches */
-		else if( !strcmp( argv[ i ], "-bounce" ) )
-		{
-			bounce = atoi( argv[ i + 1 ] );
-			if( bounce < 0 )
-				bounce = 0;
-			else if( bounce > 0 )
-				Sys_Printf( "Radiosity enabled with %d bounce(s)\n", bounce );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-supersample" ) || !strcmp( argv[ i ], "-super" ) )
-		{
-			superSample = atoi( argv[ i + 1 ] );
-			if( superSample < 1 )
-				superSample = 1;
-			else if( superSample > 1 )
-				Sys_Printf( "Ordered-grid supersampling enabled with %d sample(s) per lightmap texel\n", (superSample * superSample) );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-samples" ) )
-		{
-			lightSamples = atoi( argv[ i + 1 ] );
-			if( lightSamples < 1 )
-				lightSamples = 1;
-			else if( lightSamples > 1 )
-				Sys_Printf( "Adaptive supersampling enabled with %d sample(s) per lightmap texel\n", lightSamples );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-filter" ) )
-		{
-			filter = qtrue;
-			Sys_Printf( "Lightmap filtering enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-shadeangle" ) )
-		{
-			shadeAngleDegrees = atof( argv[ i + 1 ] );
-			if( shadeAngleDegrees < 0.0f )
-				shadeAngleDegrees = 0.0f;
-			else if( shadeAngleDegrees > 0.0f )
-			{
-				shade = qtrue;
-				Sys_Printf( "Phong shading enabled with a breaking angle of %f degrees\n", shadeAngleDegrees );
-			}
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-thresh" ) )
-		{
-			subdivideThreshold = atof( argv[ i + 1 ] );
-			if( subdivideThreshold < 0 )
-				subdivideThreshold = DEFAULT_SUBDIVIDE_THRESHOLD;
-			else
-				Sys_Printf( "Subdivision threshold set at %.3f\n", subdivideThreshold );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-approx" ) )
-		{
-			approximateTolerance = atoi( argv[ i + 1 ] );
-			if( approximateTolerance < 0 )
-				approximateTolerance = 0;
-			else if( approximateTolerance > 0 )
-				Sys_Printf( "Approximating lightmaps within a byte tolerance of %d\n", approximateTolerance );
-			i++;
-		}
-		
-		else if( !strcmp( argv[ i ], "-deluxe" ) || !strcmp( argv[ i ], "-deluxemap" ) )
-		{
-			deluxemap = qtrue;
-			Sys_Printf( "Generating deluxemaps for average light direction\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-external" ) )
-		{
-			externalLightmaps = qtrue;
-			Sys_Printf( "Storing all lightmaps externally\n" );
-		}
-
-		else if( !strcmp( argv[ i ], "-lightmapsize" ) )
-		{
-			lmCustomSize = atoi( argv[ i + 1 ] );
-			
-			/* must be a power of 2 and greater than 2 */
-			if( ((lmCustomSize - 1) & lmCustomSize) || lmCustomSize < 2 )
-			{
-				Sys_Printf( "WARNING: Lightmap size must be a power of 2, greater or equal to 2 pixels.\n" );
-				lmCustomSize = LIGHTMAP_WIDTH;
-			}
-			i++;
-			Sys_Printf( "Default lightmap size set to %d x %d pixels\n", lmCustomSize, lmCustomSize );
-			
-			/* enable external lightmaps */
-			if( lmCustomSize != LIGHTMAP_WIDTH )
-			{
-				externalLightmaps = qtrue;
-				Sys_Printf( "Storing all lightmaps externally\n" );
-			}
-		}
-		
-		/* ydnar: add this to suppress warnings */
-		else if( !strcmp( argv[ i ],  "-custinfoparms") )
-		{
-			Sys_Printf( "Custom info parms enabled\n" );
-			useCustomInfoParms = qtrue;
-		}
-		
-		else if( !strcmp( argv[ i ], "-wolf" ) )
-		{
-			/* -game should already be set */
-			game->wolfLight = qtrue;
-			Sys_Printf( "Enabling Wolf lighting model\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-sunonly" ) )
-		{
-			sunOnly = qtrue;
-			Sys_Printf( "Only computing sunlight\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-bounceonly" ) )
-		{
-			bounceOnly = qtrue;
-			Sys_Printf( "Storing bounced light (radiosity) only\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-nocollapse" ) )
-		{
-			noCollapse = qtrue;
-			Sys_Printf( "Identical lightmap collapsing disabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-shade" ) )
-		{
-			shade = qtrue;
-			Sys_Printf( "Phong shading enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-bouncegrid") )
-		{
-			bouncegrid = qtrue;
-			if( bounce > 0 )
-				Sys_Printf( "Grid lighting with radiosity enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-smooth" ) )
-		{
-			smooth = qtrue;
-			lightSamples = EXTRA_SCALE;
-			Sys_Printf( "The -smooth argument is deprecated, use \"-samples 2\" instead\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-fast" ) )
-		{
-			fast = qtrue;
-			fastgrid = qtrue;
-			fastbounce = qtrue;
-			Sys_Printf( "Fast mode enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-faster" ) )
-		{
-			faster = qtrue;
-			fast = qtrue;
-			fastgrid = qtrue;
-			fastbounce = qtrue;
-			Sys_Printf( "Faster mode enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-fastgrid" ) )
-		{
-			fastgrid = qtrue;
-			Sys_Printf( "Fast grid lighting enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-fastbounce" ) )
-		{
-			fastbounce = qtrue;
-			Sys_Printf( "Fast bounce mode enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-cheap" ) )
-		{
-			cheap = qtrue;
-			cheapgrid = qtrue;
-			Sys_Printf( "Cheap mode enabled\n" );
-		}
-
-		else if( !strcmp( argv[ i ], "-cheapgrid" ) )
-		{
-			cheapgrid = qtrue;
-			Sys_Printf( "Cheap grid mode enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-normalmap" ) )
-		{
-			normalmap = qtrue;
-			Sys_Printf( "Storing normal map instead of lightmap\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-trisoup" ) )
-		{
-			trisoup = qtrue;
-			Sys_Printf( "Converting brush faces to triangle soup\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-debug" ) )
-		{
-			debug = qtrue;
-			Sys_Printf( "Lightmap debugging enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-debugsurfaces" ) || !strcmp( argv[ i ], "-debugsurface" ) )
-		{
-			debugSurfaces = qtrue;
-			Sys_Printf( "Lightmap surface debugging enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-debugunused" ) )
-		{
-			debugUnused = qtrue;
-			Sys_Printf( "Unused luxel debugging enabled\n" );
-		}
-
-		else if( !strcmp( argv[ i ], "-debugaxis" ) )
-		{
-			debugAxis = qtrue;
-			Sys_Printf( "Lightmap axis debugging enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-debugcluster" ) )
-		{
-			debugCluster = qtrue;
-			Sys_Printf( "Luxel cluster debugging enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-debugorigin" ) )
-		{
-			debugOrigin = qtrue;
-			Sys_Printf( "Luxel origin debugging enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-debugdeluxe" ) )
-		{
-			deluxemap = qtrue;
-			debugDeluxemap = qtrue;
-			Sys_Printf( "Deluxemap debugging enabled\n" );
-		}
-		
-		else if( !strcmp( argv[ i ], "-export" ) )
-		{
-			exportLightmaps = qtrue;
-			Sys_Printf( "Exporting lightmaps\n" );
-		}
-		
-		else if( !strcmp(argv[ i ], "-notrace" )) 
-		{
-			noTrace = qtrue;
-			Sys_Printf( "Shadow occlusion disabled\n" );
-		}
-		else if( !strcmp(argv[ i ], "-patchshadows" ) )
-		{
-			patchShadows = qtrue;
-			Sys_Printf( "Patch shadow casting enabled\n" );
-		}
-		else if( !strcmp( argv[ i ], "-extra" ) )
-		{
-			extra = qtrue;
-			superSample = EXTRA_SCALE;		/* ydnar */
-			Sys_Printf( "The -extra argument is deprecated, use \"-super 2\" instead\n" );
-		}
-		else if( !strcmp( argv[ i ], "-extrawide" ) )
-		{
-			extra = qtrue;
-			extraWide = qtrue;
-			superSample = EXTRAWIDE_SCALE;	/* ydnar */
-			filter = qtrue;					/* ydnar */
-			Sys_Printf( "The -extrawide argument is deprecated, use \"-filter [-super 2]\" instead\n");
-		}
-		else if( !strcmp( argv[ i ], "-samplesize" ) )
-		{
-			sampleSize = atoi( argv[ i + 1 ] );
-			if( sampleSize < 1 )
-				sampleSize = 1;
-			i++;
-			Sys_Printf( "Default lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
-		}
-		else if( !strcmp( argv[ i ], "-novertex" ) )
-		{
-			noVertexLighting = qtrue;
-			Sys_Printf( "Disabling vertex lighting\n" );
-		}
-		else if( !strcmp( argv[ i ], "-nogrid" ) )
-		{
-			noGridLighting = qtrue;
-			Sys_Printf( "Disabling grid lighting\n" );
-		}
-		else if( !strcmp( argv[ i ], "-border" ) )
-		{
-			lightmapBorder = qtrue;
-			Sys_Printf( "Adding debug border to lightmaps\n" );
-		}
-		else if( !strcmp( argv[ i ], "-nosurf" ) )
-		{
-			noSurfaces = qtrue;
-			Sys_Printf( "Not tracing against surfaces\n" );
-		}
-		else if( !strcmp( argv[ i ], "-dump" ) )
-		{
-			dump = qtrue;
-			Sys_Printf( "Dumping radiosity lights into numbered prefabs\n" );
-		}
-		else if( !strcmp( argv[ i ], "-lomem" ) )
-		{
-			loMem = qtrue;
-			Sys_Printf( "Enabling low-memory (potentially slower) lighting mode\n" );
-		}
-		
-		else
-			Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
-	}
-	
-	/* clean up map name */
-	strcpy( source, ExpandArg( argv[ i ] ) );
-	StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	strcpy( mapSource, ExpandArg( argv[ i ] ) );
-	StripExtension( mapSource );
-	DefaultExtension( mapSource, ".map" );
-	
-	/* ydnar: set default sample size */
-	SetDefaultSampleSize( sampleSize );
-	
-	/* ydnar: handle shaders */
-	BeginMapShaderFile( source );
-	LoadShaderInfo();
-	
-	/* note loading */
-	Sys_Printf( "Loading %s\n", source );
-	
-	/* ydnar: load surface file */
-	LoadSurfaceExtraFile( source );
-	
-	/* load bsp file */
-	LoadBSPFile( source );
-	
-	/* parse bsp entities */
-	ParseEntities();
-	
-	/* load map file */
-	value = ValueForKey( &entities[ 0 ], "_keepLights" );
-	if( value[ 0 ] != '1' )
-		LoadMapFile( mapSource, qtrue );
-	
-	/* set the entity/model origins and init yDrawVerts */
-	SetEntityOrigins();
-	
-	/* ydnar: set up optimization */
-	SetupBrushes();
-	SetupSurfaceLightmaps();
-	
-	/* initialize the surface facet tracing */
-	SetupTraceNodes();
-	
-	/* light the world */
-	LightWorld();
-	
-	/* ydnar: store off lightmaps */
-	StoreSurfaceLightmaps();
-	
-	/* write out the bsp */
-	UnparseEntities();
-	Sys_Printf( "Writing %s\n", source );
-	WriteBSPFile( source );
-	
-	/* ydnar: export lightmaps */
-	if( exportLightmaps && !externalLightmaps )
-		ExportLightmaps();
-	
-	/* return to sender */
-	return 0;
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define LIGHT_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+CreateSunLight() - ydnar
+this creates a sun light
+*/
+
+static void CreateSunLight( sun_t *sun )
+{
+	int			i;
+	float		photons, d, angle, elevation, da, de;
+	vec3_t		direction;
+	light_t		*light;
+	
+	
+	/* dummy check */
+	if( sun == NULL )
+		return;
+	
+	/* fixup */
+	if( sun->numSamples < 1 )
+		sun->numSamples = 1;
+	
+	/* set photons */
+	photons = sun->photons / sun->numSamples;
+	
+	/* create the right number of suns */
+	for( i = 0; i < sun->numSamples; i++ )
+	{
+		/* calculate sun direction */
+		if( i == 0 )
+			VectorCopy( sun->direction, direction );
+		else
+		{
+			/*
+				sun->direction[ 0 ] = cos( angle ) * cos( elevation );
+				sun->direction[ 1 ] = sin( angle ) * cos( elevation );
+				sun->direction[ 2 ] = sin( elevation );
+				
+				xz_dist   = sqrt( x*x + z*z )
+				latitude  = atan2( xz_dist, y ) * RADIANS
+				longitude = atan2( x,       z ) * RADIANS
+			*/
+			
+			d = sqrt( sun->direction[ 0 ] * sun->direction[ 0 ] + sun->direction[ 1 ] * sun->direction[ 1 ] );
+			angle = atan2( sun->direction[ 1 ], sun->direction[ 0 ] );
+			elevation = atan2( sun->direction[ 2 ], d );
+			
+			/* jitter the angles (loop to keep random sample within sun->deviance steridians) */
+			do
+			{
+				da = (Random() * 2.0f - 1.0f) * sun->deviance;
+				de = (Random() * 2.0f - 1.0f) * sun->deviance;
+			}
+			while( (da * da + de * de) > (sun->deviance * sun->deviance) );
+			angle += da;
+			elevation += de;
+			
+			/* debug code */
+			//%	Sys_Printf( "%d: Angle: %3.4f Elevation: %3.3f\n", sun->numSamples, (angle / Q_PI * 180.0f), (elevation / Q_PI * 180.0f) );
+			
+			/* create new vector */
+			direction[ 0 ] = cos( angle ) * cos( elevation );
+			direction[ 1 ] = sin( angle ) * cos( elevation );
+			direction[ 2 ] = sin( elevation );
+		}
+		
+		/* create a light */
+		numSunLights++;
+		light = safe_malloc( sizeof( *light ) );
+		memset( light, 0, sizeof( *light ) );
+		light->next = lights;
+		lights = light;
+		
+		/* initialize the light */
+		light->flags = LIGHT_SUN_DEFAULT;
+		light->type = EMIT_SUN;
+		light->fade = 1.0f;
+		light->falloffTolerance = falloffTolerance;
+		light->filterRadius = sun->filterRadius / sun->numSamples;
+		
+		/* set the light's position out to infinity */
+		VectorMA( vec3_origin, (MAX_WORLD_COORD * 8.0f), direction, light->origin );	/* MAX_WORLD_COORD * 2.0f */
+		
+		/* set the facing to be the inverse of the sun direction */
+		VectorScale( direction, -1.0, light->normal );
+		light->dist = DotProduct( light->origin, light->normal );
+		
+		/* set color and photons */
+		VectorCopy( sun->color, light->color );
+		light->photons = photons * skyScale;
+	}
+
+	/* another sun? */
+	if( sun->next != NULL )
+		CreateSunLight( sun->next );
+}
+
+
+
+/*
+CreateSkyLights() - ydnar
+simulates sky light with multiple suns
+*/
+
+static void CreateSkyLights( vec3_t color, float value, int iterations, float filterRadius )
+{
+	int			c, i, j, k, numSuns;
+	float		step, start;
+	vec3_t		in;
+	sun_t		sun;
+	
+	
+	/* dummy check */
+	if( value <= 0.0f || iterations < 2 )
+		return;
+	
+	/* calculate some stuff */
+	step = 2.0f / (iterations - 1);
+	start = -1.0f;
+	
+	/* basic sun setup */
+	VectorCopy( color, sun.color );
+	sun.deviance = 0.0f;
+	sun.filterRadius = filterRadius;
+	sun.numSamples = 1;
+	sun.next = NULL;
+	
+	/* iterate */
+	numSuns = 0;
+	for( c = 0; c < 2; c++ )
+	{
+		for( k = 0, in[ 2 ] = start; k < iterations; k++, in[ 2 ] += step )
+		{
+			/* don't create sky light below the horizon */
+			if( in[ 2 ] <= 0.0f )
+				continue;
+			
+			for( j = 0, in[ 1 ] = start; j < iterations; j++, in[ 1 ] += step )
+			{
+				for( i = 0, in[ 0 ] = start; i < iterations; i++, in[ 0 ] += step )
+				{
+					if( VectorNormalize( in, sun.direction ) )
+					{
+						if( c > 0 && numSuns > 0 )
+						{
+							sun.photons = value / numSuns;
+							CreateSunLight( &sun );
+						}
+						else
+							numSuns++;
+					}
+				}
+			}
+		}
+	}
+}
+
+
+
+/*
+CreateEntityLights()
+creates lights from light entities
+*/
+
+void CreateEntityLights( void )
+{
+	int				i, j;
+	light_t			*light, *light2;
+	entity_t		*e, *e2;
+	const char		*name;
+	const char		*target;
+	vec3_t			dest;
+	const char		*_color;
+	float			intensity, scale, deviance, filterRadius;
+	int				spawnflags, flags, numSamples;
+	qboolean		junior;
+
+	
+	/* go throught entity list and find lights */
+	for( i = 0; i < numEntities; i++ )
+	{
+		/* get entity */
+		e = &entities[ i ];
+		name = ValueForKey( e, "classname" );
+		
+		/* ydnar: check for lightJunior */
+		if( Q_strncasecmp( name, "lightJunior", 11 ) == 0 )
+			junior = qtrue;
+		else if( Q_strncasecmp( name, "light", 5 ) == 0 )
+			junior = qfalse;
+		else
+			continue;
+		
+		/* lights with target names (and therefore styles) are only parsed from BSP */
+		target = ValueForKey( e, "targetname" );
+		if( target[ 0 ] != '\0' && i >= numBSPEntities )
+			continue;
+		
+		/* create a light */
+		numPointLights++;
+		light = safe_malloc( sizeof( *light ) );
+		memset( light, 0, sizeof( *light ) );
+		light->next = lights;
+		lights = light;
+		
+		/* handle spawnflags */
+		spawnflags = IntForKey( e, "spawnflags" );
+		
+		/* ydnar: quake 3+ light behavior */
+		if( game->wolfLight == qfalse )
+		{
+			/* set default flags */
+			flags = LIGHT_Q3A_DEFAULT;
+			
+			/* linear attenuation? */
+			if( spawnflags & 1 )
+			{
+				flags |= LIGHT_ATTEN_LINEAR;
+				flags &= ~LIGHT_ATTEN_ANGLE;
+			}
+			
+			/* no angle attenuate? */
+			if( spawnflags & 2 )
+				flags &= ~LIGHT_ATTEN_ANGLE;
+		}
+		
+		/* ydnar: wolf light behavior */
+		else
+		{
+			/* set default flags */
+			flags = LIGHT_WOLF_DEFAULT;
+			
+			/* inverse distance squared attenuation? */
+			if( spawnflags & 1 )
+			{
+				flags &= ~LIGHT_ATTEN_LINEAR;
+				flags |= LIGHT_ATTEN_ANGLE;
+			}
+			
+			/* angle attenuate? */
+			if( spawnflags & 2 )
+				flags |= LIGHT_ATTEN_ANGLE;
+		}
+		
+		/* other flags (borrowed from wolf) */
+		
+		/* wolf dark light? */
+		if( (spawnflags & 4) || (spawnflags & 8) )
+			flags |= LIGHT_DARK;
+		
+		/* nogrid? */
+		if( spawnflags & 16 )
+			flags &= ~LIGHT_GRID;
+		
+		/* junior? */
+		if( junior )
+		{
+			flags |= LIGHT_GRID;
+			flags &= ~LIGHT_SURFACES;
+		}
+		
+		/* store the flags */
+		light->flags = flags;
+		
+		/* ydnar: set fade key (from wolf) */
+		light->fade = 1.0f;
+		if( light->flags & LIGHT_ATTEN_LINEAR )
+		{
+			light->fade = FloatForKey( e, "fade" );
+			if( light->fade == 0.0f )
+				light->fade = 1.0f;
+		}
+		
+		/* ydnar: set angle scaling (from vlight) */
+		light->angleScale = FloatForKey( e, "_anglescale" );
+		if( light->angleScale != 0.0f )
+			light->flags |= LIGHT_ATTEN_ANGLE;
+		
+		/* set origin */
+		GetVectorForKey( e, "origin", light->origin);
+		light->style = IntForKey( e, "_style" );
+		if( light->style == 0 )
+			light->style = IntForKey( e, "style" );
+		if( light->style < LS_NORMAL || light->style >= LS_NONE )
+			Error( "Invalid lightstyle (%d) on entity %d", light->style, i );
+		
+		/* set light intensity */
+		intensity = FloatForKey( e, "_light" );
+		if( intensity == 0.0f )
+			intensity = FloatForKey( e, "light" );
+		if( intensity == 0.0f)
+			intensity = 300.0f;
+		
+		/* ydnar: set light scale (sof2) */
+		scale = FloatForKey( e, "scale" );
+		if( scale == 0.0f )
+			scale = 1.0f;
+		intensity *= scale;
+		
+		/* ydnar: get deviance and samples */
+		deviance = FloatForKey( e, "_deviance" );
+		if( deviance == 0.0f )
+			deviance = FloatForKey( e, "_deviation" );
+		if( deviance == 0.0f )
+			deviance = FloatForKey( e, "_jitter" );
+		numSamples = IntForKey( e, "_samples" );
+		if( deviance < 0.0f || numSamples < 1 )
+		{
+			deviance = 0.0f;
+			numSamples = 1;
+		}
+		intensity /= numSamples;
+		
+		/* ydnar: get filter radius */
+		filterRadius = FloatForKey( e, "_filterradius" );
+		if( filterRadius == 0.0f )
+			filterRadius = FloatForKey( e, "_filteradius" );
+		if( filterRadius == 0.0f )
+			filterRadius = FloatForKey( e, "_filter" );
+		if( filterRadius < 0.0f )
+			filterRadius = 0.0f;
+		light->filterRadius = filterRadius;
+		
+		/* set light color */
+		_color = ValueForKey( e, "_color" );
+		if( _color && _color[ 0 ] )
+		{
+			sscanf( _color, "%f %f %f", &light->color[ 0 ], &light->color[ 1 ], &light->color[ 2 ] );
+			ColorNormalize( light->color, light->color );
+		}
+		else
+			light->color[ 0 ] = light->color[ 1 ] = light->color[ 2 ] = 1.0f;
+		
+		intensity = intensity * pointScale;
+		light->photons = intensity;
+		
+		light->type = EMIT_POINT;
+		
+		/* set falloff threshold */
+		light->falloffTolerance = falloffTolerance / numSamples;
+		
+		/* lights with a target will be spotlights */
+		target = ValueForKey( e, "target" );
+		if( target[ 0 ] )
+		{
+			float		radius;
+			float		dist;
+			sun_t		sun;
+			const char	*_sun;
+			
+			
+			/* get target */
+			e2 = FindTargetEntity( target );
+			if( e2 == NULL )
+			{
+				Sys_Printf( "WARNING: light at (%i %i %i) has missing target\n",
+					(int) light->origin[ 0 ], (int) light->origin[ 1 ], (int) light->origin[ 2 ] );
+			}
+			else
+			{
+				/* not a point light */
+				numPointLights--;
+				numSpotLights++;
+				
+				/* make a spotlight */
+				GetVectorForKey( e2, "origin", dest );
+				VectorSubtract( dest, light->origin, light->normal );
+				dist = VectorNormalize( light->normal, light->normal );
+				radius = FloatForKey( e, "radius" );
+				if( !radius )
+					radius = 64;
+				if( !dist )
+					dist = 64;
+				light->radiusByDist = (radius + 16) / dist;
+				light->type = EMIT_SPOT;
+				
+				/* ydnar: wolf mods: spotlights always use nonlinear + angle attenuation */
+				light->flags &= ~LIGHT_ATTEN_LINEAR;
+				light->flags |= LIGHT_ATTEN_ANGLE;
+				light->fade = 1.0f;
+				
+				/* ydnar: is this a sun? */
+				_sun = ValueForKey( e, "_sun" );
+				if( _sun[ 0 ] == '1' )
+				{
+					/* not a spot light */
+					numSpotLights--;
+					
+					/* unlink this light */
+					lights = light->next;
+					
+					/* make a sun */
+					VectorScale( light->normal, -1.0f, sun.direction );
+					VectorCopy( light->color, sun.color );
+					sun.photons = (intensity / pointScale);
+					sun.deviance = deviance / 180.0f * Q_PI;
+					sun.numSamples = numSamples;
+					sun.next = NULL;
+					
+					/* make a sun light */
+					CreateSunLight( &sun );
+					
+					/* free original light */
+					free( light );
+					light = NULL;
+					
+					/* skip the rest of this love story */
+					continue;
+				}
+			}
+		}
+		
+		/* jitter the light */
+		for( j = 1; j < numSamples; j++ )
+		{
+			/* create a light */
+			light2 = safe_malloc( sizeof( *light ) );
+			memcpy( light2, light, sizeof( *light ) );
+			light2->next = lights;
+			lights = light2;
+			
+			/* add to counts */
+			if( light->type == EMIT_SPOT )
+				numSpotLights++;
+			else
+				numPointLights++;
+			
+			/* jitter it */
+			light2->origin[ 0 ] = light->origin[ 0 ] + (Random() * 2.0f - 1.0f) * deviance;
+			light2->origin[ 1 ] = light->origin[ 1 ] + (Random() * 2.0f - 1.0f) * deviance;
+			light2->origin[ 2 ] = light->origin[ 2 ] + (Random() * 2.0f - 1.0f) * deviance;
+		}
+	}
+}
+
+
+
+/*
+CreateSurfaceLights() - ydnar
+this hijacks the radiosity code to generate surface lights for first pass
+*/
+
+#define APPROX_BOUNCE	1.0f
+
+void CreateSurfaceLights( void )
+{
+	int					i;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	shaderInfo_t		*si;
+	light_t				*light;
+	float				subdivide;
+	vec3_t				origin;
+	clipWork_t			cw;
+	const char			*nss;
+	
+	
+	/* get sun shader supressor */
+	nss = ValueForKey( &entities[ 0 ], "_noshadersun" );
+	
+	/* walk the list of surfaces */
+	for( i = 0; i < numBSPDrawSurfaces; i++ )
+	{
+		/* get surface and other bits */
+		ds = &bspDrawSurfaces[ i ];
+		info = &surfaceInfos[ i ];
+		si = info->si;
+		
+		/* sunlight? */
+		if( si->sun != NULL && nss[ 0 ] != '1' )
+		{
+			Sys_FPrintf( SYS_VRB, "Sun: %s\n", si->shader );
+			CreateSunLight( si->sun );
+			si->sun = NULL; /* FIXME: leak! */
+		}
+		
+		/* sky light? */
+		if( si->skyLightValue > 0.0f )
+		{
+			Sys_FPrintf( SYS_VRB, "Sky: %s\n", si->shader );
+			CreateSkyLights( si->color, si->skyLightValue, si->skyLightIterations, si->lightFilterRadius );
+			si->skyLightValue = 0.0f;	/* FIXME: hack! */
+		}
+		
+		/* try to early out */
+		if( si->value <= 0 )
+			continue;
+		
+		/* autosprite shaders become point lights */
+		if( si->autosprite )
+		{
+			/* create an average xyz */
+			VectorAdd( info->mins, info->maxs, origin );
+			VectorScale( origin, 0.5f, origin );
+			
+			/* create a light */
+			light = safe_malloc( sizeof( *light ) );
+			memset( light, 0, sizeof( *light ) );
+			light->next = lights;
+			lights = light;
+			
+			/* set it up */
+			light->flags = LIGHT_Q3A_DEFAULT;
+			light->type = EMIT_POINT;
+			light->photons = si->value * pointScale;
+			light->fade = 1.0f;
+			light->si = si;
+			VectorCopy( origin, light->origin );
+			VectorCopy( si->color, light->color );
+			light->falloffTolerance = falloffTolerance;
+			light->style = light->style;
+			
+			/* add to point light count and continue */
+			numPointLights++;
+			continue;
+		}
+		
+		/* get subdivision amount */
+		if( si->lightSubdivide > 0 )
+			subdivide = si->lightSubdivide;
+		else
+			subdivide = defaultLightSubdivide;
+		
+		/* switch on type */
+		switch( ds->surfaceType )
+		{
+			case MST_PLANAR:
+			case MST_TRIANGLE_SOUP:
+				RadLightForTriangles( i, 0, info->lm, si, APPROX_BOUNCE, subdivide, &cw );
+				break;
+			
+			case MST_PATCH:
+				RadLightForPatch( i, 0, info->lm, si, APPROX_BOUNCE, subdivide, &cw );
+				break;
+			
+			default:
+				break;
+		}
+	}
+}
+
+
+
+/*
+SetEntityOrigins()
+find the offset values for inline models
+*/
+
+void SetEntityOrigins( void )
+{
+	int					i, j, k, f;
+	entity_t			*e;
+	vec3_t				origin;
+	const char			*key;
+	int					modelnum;
+	bspModel_t			*dm;
+	bspDrawSurface_t	*ds;
+	
+	
+	/* ydnar: copy drawverts into private storage for nefarious purposes */
+	yDrawVerts = safe_malloc( numBSPDrawVerts * sizeof( bspDrawVert_t ) );
+	memcpy( yDrawVerts, bspDrawVerts, numBSPDrawVerts * sizeof( bspDrawVert_t ) );
+	
+	/* set the entity origins */
+	for( i = 0; i < numEntities; i++ )
+	{
+		/* get entity and model */
+		e = &entities[ i ];
+		key = ValueForKey( e, "model" );
+		if( key[ 0 ] != '*' )
+			continue;
+		modelnum = atoi( key + 1 );
+		dm = &bspModels[ modelnum ];
+		
+		/* get entity origin */
+		key = ValueForKey( e, "origin" );
+		if( key[ 0 ] == '\0' )
+			continue;
+		GetVectorForKey( e, "origin", origin );
+		
+		/* set origin for all surfaces for this model */
+		for( j = 0; j < dm->numBSPSurfaces; j++ )
+		{
+			/* get drawsurf */
+			ds = &bspDrawSurfaces[ dm->firstBSPSurface + j ];
+			
+			/* set its verts */
+			for( k = 0; k < ds->numVerts; k++ )
+			{
+				f = ds->firstVert + k;
+				VectorAdd( origin, bspDrawVerts[ f ].xyz, yDrawVerts[ f ].xyz );
+			}
+		}
+	}
+}
+
+
+
+/*
+PointToPolygonFormFactor()
+calculates the area over a point/normal hemisphere a winding covers
+ydnar: fixme: there has to be a faster way to calculate this
+without the expensive per-vert sqrts and transcendental functions
+ydnar 2002-09-30: added -faster switch because only 19% deviance > 10%
+between this and the approximation
+*/
+
+#define ONE_OVER_2PI	0.159154942f	//% (1.0f / (2.0f * 3.141592657f))
+
+float PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w )
+{
+	vec3_t		triVector, triNormal;
+	int			i, j;
+	vec3_t		dirs[ MAX_POINTS_ON_WINDING ];
+	float		total;
+	float		dot, angle, facing;
+	
+	
+	/* this is expensive */
+	for( i = 0; i < w->numpoints; i++ )
+	{
+		VectorSubtract( w->p[ i ], point, dirs[ i ] );
+		VectorNormalize( dirs[ i ], dirs[ i ] );
+	}
+	
+	/* duplicate first vertex to avoid mod operation */
+	VectorCopy( dirs[ 0 ], dirs[ i ] );
+	
+	/* calculcate relative area */
+	total = 0.0f;
+	for( i = 0; i < w->numpoints; i++ )
+	{
+		/* get a triangle */
+		j = i + 1;
+		dot = DotProduct( dirs[ i ], dirs[ j ] );
+		
+		/* roundoff can cause slight creep, which gives an IND from acos */
+		if( dot > 1.0f )
+			dot = 1.0f;
+		else if( dot < -1.0f )
+			dot = -1.0f;
+		
+		/* get the angle */
+		angle = acos( dot );
+		
+		CrossProduct( dirs[ i ], dirs[ j ], triVector );
+		if( VectorNormalize( triVector, triNormal ) < 0.0001f )
+			continue;
+		
+		facing = DotProduct( normal, triNormal );
+		total += facing * angle;
+		
+		/* ydnar: this was throwing too many errors with radiosity + crappy maps. ignoring it. */
+		if( total > 6.3f || total < -6.3f )
+			return 0.0f;
+	}
+	
+	/* now in the range of 0 to 1 over the entire incoming hemisphere */
+	//%	total /= (2.0f * 3.141592657f);
+	total *= ONE_OVER_2PI;
+	return total;
+}
+
+
+
+/*
+LightContributionTosample()
+determines the amount of light reaching a sample (luxel or vertex) from a given light
+*/
+
+int LightContributionToSample( trace_t *trace )
+{
+	light_t			*light;
+	float			angle;
+	float			add;
+	float			dist;
+	
+	
+	/* get light */
+	light = trace->light;
+	
+	/* clear color */
+	VectorClear( trace->color );
+	
+	/* ydnar: early out */
+	if( !(light->flags & LIGHT_SURFACES) || light->envelope <= 0.0f )
+		return 0;
+	
+	/* do some culling checks */
+	if( light->type != EMIT_SUN )
+	{
+		/* MrE: if the light is behind the surface */
+		if( trace->twoSided == qfalse )
+			if( DotProduct( light->origin, trace->normal ) - DotProduct( trace->origin, trace->normal ) < 0.0f )
+				return 0;
+		
+		/* ydnar: test pvs */
+		if( !ClusterVisible( trace->cluster, light->cluster ) )
+			return 0;
+	}
+	
+	/* ptpff approximation */
+	if( light->type == EMIT_AREA && faster )
+	{
+		/* get direction and distance */
+		VectorCopy( light->origin, trace->end );
+		dist = SetupTrace( trace );
+		if( dist >= light->envelope )
+			return 0;
+		
+		/* clamp the distance to prevent super hot spots */
+		if( dist < 16.0f )
+			dist = 16.0f;
+		
+		/* angle attenuation */
+		angle = DotProduct( trace->normal, trace->direction );
+		
+		/* twosided lighting */
+		if( trace->twoSided )
+			angle = fabs( angle );
+		
+		/* attenuate */
+		angle *= -DotProduct( light->normal, trace->direction );
+		if( angle <= 0.0f )
+			return 0;
+		add = light->photons / (dist * dist) * angle;
+	}
+	
+	/* exact point to polygon form factor */
+	else if( light->type == EMIT_AREA )
+	{
+		float		factor;
+		float		d;
+		vec3_t		pushedOrigin;
+		
+		
+		/* project sample point into light plane */
+		d = DotProduct( trace->origin, light->normal ) - light->dist;
+		//%	if( !(light->flags & LIGHT_TWOSIDED) && d < -1.0f )
+		//%		return 0;
+		if( d < 3.0f )
+		{
+			/* sample point behind plane? */
+			if( !(light->flags & LIGHT_TWOSIDED) && d < -1.0f )
+				return 0;
+			
+			/* sample plane coincident? */
+			if( d > -3.0f && DotProduct( trace->normal, light->normal ) > 0.9f )
+				return 0;
+		}
+		
+		/* nudge the point so that it is clearly forward of the light */
+		/* so that surfaces meeting a light emiter don't get black edges */
+		if( d > -8.0f && d < 8.0f )
+			VectorMA( trace->origin, (8.0f - d), light->normal, pushedOrigin );				
+		else
+			VectorCopy( trace->origin, pushedOrigin );
+		
+		/* get direction and distance */
+		VectorCopy( light->origin, trace->end );
+		dist = SetupTrace( trace );
+		if( dist >= light->envelope )
+			return 0;
+		
+		/* calculate the contribution */
+		factor = PointToPolygonFormFactor( pushedOrigin, trace->normal, light->w );
+		if( factor == 0.0f )
+			return 0;
+		else if( factor < 0.0f )
+		{
+			/* twosided lighting */
+			if( trace->twoSided || (light->flags & LIGHT_TWOSIDED) )
+			{
+				factor = -factor;
+
+				/* push light origin to other side of the plane */
+				VectorMA( light->origin, -2.0f, light->normal, trace->end );
+				dist = SetupTrace( trace );
+				if( dist >= light->envelope )
+					return 0;
+			}
+			else
+				return 0;
+		}
+		
+		/* ydnar: moved to here */
+		add = factor * light->add;
+	}
+	
+	/* point/spot lights */
+	else if( light->type == EMIT_POINT || light->type == EMIT_SPOT )
+	{
+		/* get direction and distance */
+		VectorCopy( light->origin, trace->end );
+		dist = SetupTrace( trace );
+		if( dist >= light->envelope )
+			return 0;
+		
+		/* clamp the distance to prevent super hot spots */
+		if( dist < 16.0f )
+			dist = 16.0f;
+		
+		/* angle attenuation */
+		angle = (light->flags & LIGHT_ATTEN_ANGLE) ? DotProduct( trace->normal, trace->direction ) : 1.0f;
+		if( light->angleScale != 0.0f )
+		{
+			angle /= light->angleScale;
+			if( angle > 1.0f )
+				angle = 1.0f;
+		}
+		
+		/* twosided lighting */
+		if( trace->twoSided )
+			angle = fabs( angle );
+		
+		/* attenuate */
+		if( light->flags & LIGHT_ATTEN_LINEAR )
+		{
+			add = angle * light->photons * linearScale - (dist * light->fade);
+			if( add < 0.0f )
+				add = 0.0f;
+		}
+		else
+			add = light->photons / (dist * dist) * angle;
+		
+		/* handle spotlights */
+		if( light->type == EMIT_SPOT )
+		{
+			float	distByNormal, radiusAtDist, sampleRadius;
+			vec3_t	pointAtDist, distToSample;
+			
+			
+			/* do cone calculation */
+			distByNormal = -DotProduct( trace->displacement, light->normal );
+			if( distByNormal < 0.0f )
+				return 0;
+			VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
+			radiusAtDist = light->radiusByDist * distByNormal;
+			VectorSubtract( trace->origin, pointAtDist, distToSample );
+			sampleRadius = VectorLength( distToSample );
+			
+			/* outside the cone */
+			if( sampleRadius >= radiusAtDist )
+				return 0;
+			
+			/* attenuate */
+			if( sampleRadius > (radiusAtDist - 32.0f) )
+				add *= ((radiusAtDist - sampleRadius) / 32.0f);
+		}
+	}
+	
+	/* ydnar: sunlight */
+	else if( light->type == EMIT_SUN )
+	{
+		/* get origin and direction */
+		VectorAdd( trace->origin, light->origin, trace->end );
+		dist = SetupTrace( trace );
+		
+		/* angle attenuation */
+		angle = (light->flags & LIGHT_ATTEN_ANGLE)
+			? DotProduct( trace->normal, trace->direction )
+			: 1.0f;
+		
+		/* twosided lighting */
+		if( trace->twoSided )
+			angle = fabs( angle );
+		
+		/* attenuate */
+		add = light->photons * angle;
+		if( add <= 0.0f )
+			return 0;
+		
+		/* setup trace */
+		trace->testAll = qtrue;
+		VectorScale( light->color, add, trace->color );
+		
+		/* trace to point */
+		if( trace->testOcclusion && !trace->forceSunlight )
+		{
+			/* trace */
+			TraceLine( trace );
+			if( !(trace->compileFlags & C_SKY) || trace->opaque )
+			{
+				VectorClear( trace->color );
+				return -1;
+			}
+		}
+		
+		/* return to sender */
+		return 1;
+	}
+	
+	/* ydnar: changed to a variable number */
+	if( add <= 0.0f || (add <= light->falloffTolerance && (light->flags & LIGHT_FAST_ACTUAL)) )
+		return 0;
+	
+	/* setup trace */
+	trace->testAll = qfalse;
+	VectorScale( light->color, add, trace->color );
+	
+	/* raytrace */
+	TraceLine( trace );
+	if( trace->passSolid || trace->opaque )
+	{
+		VectorClear( trace->color );
+		return -1;
+	}
+	
+	/* return to sender */
+	return 1;
+}
+
+
+
+/*
+LightingAtSample()
+determines the amount of light reaching a sample (luxel or vertex)
+*/
+
+void LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colors[ MAX_LIGHTMAPS ] )
+{
+	int				i, lightmapNum;
+	
+	
+	/* clear colors */
+	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		VectorClear( colors[ lightmapNum ] );
+	
+	/* ydnar: normalmap */
+	if( normalmap )
+	{
+		colors[ 0 ][ 0 ] = (trace->normal[ 0 ] + 1.0f) * 127.5f;
+		colors[ 0 ][ 1 ] = (trace->normal[ 1 ] + 1.0f) * 127.5f;
+		colors[ 0 ][ 2 ] = (trace->normal[ 2 ] + 1.0f) * 127.5f;
+		return;
+	}
+	
+	/* ydnar: don't bounce ambient all the time */
+	if( !bouncing )
+		VectorCopy( ambientColor, colors[ 0 ] );
+	
+	/* ydnar: trace to all the list of lights pre-stored in tw */
+	for( i = 0; i < trace->numLights && trace->lights[ i ] != NULL; i++ )
+	{
+		/* set light */
+		trace->light = trace->lights[ i ];
+		
+		/* style check */
+		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		{
+			if( styles[ lightmapNum ] == trace->light->style ||
+				styles[ lightmapNum ] == LS_NONE )
+				break;
+		}
+		
+		/* max of MAX_LIGHTMAPS (4) styles allowed to hit a sample */
+		if( lightmapNum >= MAX_LIGHTMAPS )
+			continue;
+		
+		/* sample light */
+		LightContributionToSample( trace );
+		if( trace->color[ 0 ] == 0.0f && trace->color[ 1 ] == 0.0f && trace->color[ 2 ] == 0.0f )
+			continue;
+		
+		/* handle negative light */
+		if( trace->light->flags & LIGHT_NEGATIVE )
+			VectorScale( trace->color, -1.0f, trace->color );
+		
+		/* set style */
+		styles[ lightmapNum ] = trace->light->style;
+		
+		/* add it */
+		VectorAdd( colors[ lightmapNum ], trace->color, colors[ lightmapNum ] );
+		
+		/* cheap mode */
+		if( cheap &&
+			colors[ 0 ][ 0 ] >= 255.0f &&
+			colors[ 0 ][ 1 ] >= 255.0f &&
+			colors[ 0 ][ 2 ] >= 255.0f )
+			break;
+	}
+}
+
+
+
+/*
+LightContributionToPoint()
+for a given light, how much light/color reaches a given point in space (with no facing)
+note: this is similar to LightContributionToSample() but optimized for omnidirectional sampling
+*/
+
+int LightContributionToPoint( trace_t *trace )
+{
+	light_t		*light;
+	float		add, dist;
+	
+	
+	/* get light */
+	light = trace->light;
+	
+	/* clear color */
+	VectorClear( trace->color );
+	
+	/* ydnar: early out */
+	if( !(light->flags & LIGHT_GRID) || light->envelope <= 0.0f )
+		return qfalse;
+	
+	/* is this a sun? */
+	if( light->type != EMIT_SUN )
+	{
+		/* sun only? */
+		if( sunOnly )
+			return qfalse;
+		
+		/* test pvs */
+		if( !ClusterVisible( trace->cluster, light->cluster ) )
+			return qfalse;
+	}
+	
+	/* ydnar: check origin against light's pvs envelope */
+	if( trace->origin[ 0 ] > light->maxs[ 0 ] || trace->origin[ 0 ] < light->mins[ 0 ] ||
+		trace->origin[ 1 ] > light->maxs[ 1 ] || trace->origin[ 1 ] < light->mins[ 1 ] ||
+		trace->origin[ 2 ] > light->maxs[ 2 ] || trace->origin[ 2 ] < light->mins[ 2 ] )
+	{
+		gridBoundsCulled++;
+		return qfalse;
+	}
+	
+	/* set light origin */
+	if( light->type == EMIT_SUN )
+		VectorAdd( trace->origin, light->origin, trace->end );
+	else
+		VectorCopy( light->origin, trace->end );
+	
+	/* set direction */
+	dist = SetupTrace( trace );
+	
+	/* test envelope */
+	if( dist > light->envelope )
+	{
+		gridEnvelopeCulled++;
+		return qfalse;
+	}
+	
+	/* ptpff approximation */
+	if( light->type == EMIT_AREA && faster )
+	{
+		/* clamp the distance to prevent super hot spots */
+		if( dist < 16.0f )
+			dist = 16.0f;
+		
+		/* attenuate */
+		add = light->photons / (dist * dist);
+	}
+	
+	/* exact point to polygon form factor */
+	else if( light->type == EMIT_AREA )
+	{
+		float		factor, d;
+		vec3_t		pushedOrigin;
+		
+		
+		/* see if the point is behind the light */
+		d = DotProduct( trace->origin, light->normal ) - light->dist;
+		if( !(light->flags & LIGHT_TWOSIDED) && d < -1.0f )
+			return qfalse;
+		
+		/* nudge the point so that it is clearly forward of the light */
+		/* so that surfaces meeting a light emiter don't get black edges */
+		if( d > -8.0f && d < 8.0f )
+			VectorMA( trace->origin, (8.0f - d), light->normal, pushedOrigin );				
+		else
+			VectorCopy( trace->origin, pushedOrigin );
+		
+		/* calculate the contribution (ydnar 2002-10-21: [bug 642] bad normal calc) */
+		factor = PointToPolygonFormFactor( pushedOrigin, trace->direction, light->w );
+		if( factor == 0.0f )
+			return qfalse;
+		else if( factor < 0.0f )
+		{
+			if( light->flags & LIGHT_TWOSIDED )
+				factor = -factor;
+			else
+				return qfalse;
+		}
+		
+		/* ydnar: moved to here */
+		add = factor * light->add;
+	}
+	
+	/* point/spot lights */
+	else if( light->type == EMIT_POINT || light->type == EMIT_SPOT )
+	{
+		/* clamp the distance to prevent super hot spots */
+		if( dist < 16.0f )
+			dist = 16.0f;
+		
+		/* attenuate */
+		if( light->flags & LIGHT_ATTEN_LINEAR )
+		{
+			add = light->photons * linearScale - (dist * light->fade);
+			if( add < 0.0f )
+				add = 0.0f;
+		}
+		else
+			add = light->photons / (dist * dist);
+		
+		/* handle spotlights */
+		if( light->type == EMIT_SPOT )
+		{
+			float	distByNormal, radiusAtDist, sampleRadius;
+			vec3_t	pointAtDist, distToSample;
+			
+			
+			/* do cone calculation */
+			distByNormal = -DotProduct( trace->displacement, light->normal );
+			if( distByNormal < 0.0f )
+				return qfalse;
+			VectorMA( light->origin, distByNormal, light->normal, pointAtDist );
+			radiusAtDist = light->radiusByDist * distByNormal;
+			VectorSubtract( trace->origin, pointAtDist, distToSample );
+			sampleRadius = VectorLength( distToSample );
+			
+			/* outside the cone */
+			if( sampleRadius >= radiusAtDist )
+				return qfalse;
+			
+			/* attenuate */
+			if( sampleRadius > (radiusAtDist - 32.0f) )
+				add *= ((radiusAtDist - sampleRadius) / 32.0f);
+		}
+	}
+	
+	/* ydnar: sunlight */
+	else if( light->type == EMIT_SUN )
+	{
+		/* attenuate */
+		add = light->photons;
+		if( add <= 0.0f )
+			return qfalse;
+		
+		/* setup trace */
+		trace->testAll = qtrue;
+		VectorScale( light->color, add, trace->color );
+		
+		/* trace to point */
+		if( trace->testOcclusion && !trace->forceSunlight )
+		{
+			/* trace */
+			TraceLine( trace );
+			if( !(trace->compileFlags & C_SKY) || trace->opaque )
+			{
+				VectorClear( trace->color );
+				return -1;
+			}
+		}
+		
+		/* return to sender */
+		return qtrue;
+	}
+	
+	/* unknown light type */
+	else
+		return qfalse;
+	
+	/* ydnar: changed to a variable number */
+	if( add <= 0.0f || (add <= light->falloffTolerance && (light->flags & LIGHT_FAST_ACTUAL)) )
+		return qfalse;
+	
+	/* setup trace */
+	trace->testAll = qfalse;
+	VectorScale( light->color, add, trace->color );
+	
+	/* trace */
+	TraceLine( trace );
+	if( trace->passSolid )
+	{
+		VectorClear( trace->color );
+		return qfalse;
+	}
+	
+	/* we have a valid sample */
+	return qtrue;
+}
+
+
+
+/*
+TraceGrid()
+grid samples are for quickly determining the lighting
+of dynamically placed entities in the world
+*/
+
+#define	MAX_CONTRIBUTIONS	1024
+
+typedef struct
+{
+	vec3_t		dir;
+	vec3_t		color;
+	int			style;
+}
+contribution_t;
+
+void TraceGrid( int num )
+{
+	int						i, j, x, y, z, mod, step, numCon, numStyles;
+	float					d;
+	vec3_t					baseOrigin, cheapColor, color;
+	rawGridPoint_t			*gp;
+	bspGridPoint_t			*bgp;
+	contribution_t			contributions[ MAX_CONTRIBUTIONS ];
+	trace_t					trace;
+	
+	
+	/* get grid points */
+	gp = &rawGridPoints[ num ];
+	bgp = &bspGridPoints[ num ];
+	
+	/* get grid origin */
+	mod = num;
+	z = mod / (gridBounds[ 0 ] * gridBounds[ 1 ]);
+	mod -= z * (gridBounds[ 0 ] * gridBounds[ 1 ]);
+	y = mod / gridBounds[ 0 ];
+	mod -= y * gridBounds[ 0 ];
+	x = mod;
+	
+	trace.origin[ 0 ] = gridMins[ 0 ] + x * gridSize[ 0 ];
+	trace.origin[ 1 ] = gridMins[ 1 ] + y * gridSize[ 1 ];
+	trace.origin[ 2 ] = gridMins[ 2 ] + z * gridSize[ 2 ];
+	
+	/* set inhibit sphere */
+	if( gridSize[ 0 ] > gridSize[ 1 ] && gridSize[ 0 ] > gridSize[ 2 ] )
+		trace.inhibitRadius = gridSize[ 0 ] * 0.5f;
+	else if( gridSize[ 1 ] > gridSize[ 0 ] && gridSize[ 1 ] > gridSize[ 2 ] )
+		trace.inhibitRadius = gridSize[ 1 ] * 0.5f;
+	else
+		trace.inhibitRadius = gridSize[ 2 ] * 0.5f;
+	
+	/* find point cluster */
+	trace.cluster = ClusterForPointExt( trace.origin, GRID_EPSILON );
+	if( trace.cluster < 0 )
+	{
+		/* try to nudge the origin around to find a valid point */
+		VectorCopy( trace.origin, baseOrigin );
+		for( step = 9; step <= 18; step += 9 )
+		{
+			for( i = 0; i < 8; i++ )
+			{
+				VectorCopy( baseOrigin, trace.origin );
+				if( i & 1 )
+					trace.origin[ 0 ] += step;
+				else
+					trace.origin[ 0 ] -= step;
+				
+				if( i & 2 )
+					trace.origin[ 1 ] += step;
+				else
+					trace.origin[ 1 ] -= step;
+				
+				if( i & 4 )
+					trace.origin[ 2 ] += step;
+				else
+					trace.origin[ 2 ] -= step;
+				
+				/* ydnar: changed to find cluster num */
+				trace.cluster = ClusterForPointExt( trace.origin, VERTEX_EPSILON );
+				if( trace.cluster >= 0 )
+					break;
+			}
+			
+			if( i != 8 )
+				break;
+		}
+		
+		/* can't find a valid point at all */
+		if( step > 18 )
+			return;
+	}
+	
+	/* setup trace */
+	trace.testOcclusion = !noTrace;
+	trace.forceSunlight = qfalse;
+	trace.recvShadows = WORLDSPAWN_RECV_SHADOWS;
+	trace.numSurfaces = 0;
+	trace.surfaces = NULL;
+	trace.numLights = 0;
+	trace.lights = NULL;
+	
+	/* clear */
+	numCon = 0;
+	VectorClear( cheapColor );
+	
+	/* trace to all the lights, find the major light direction, and divide the
+	   total light between that along the direction and the remaining in the ambient */
+	for( trace.light = lights; trace.light != NULL; trace.light = trace.light->next )
+	{
+		float		addSize;
+		
+		
+		/* sample light */
+		if( !LightContributionToPoint( &trace ) )
+			continue;
+		
+		/* handle negative light */
+		if( trace.light->flags & LIGHT_NEGATIVE )
+			VectorScale( trace.color, -1.0f, trace.color );
+		
+		/* add a contribution */
+		VectorCopy( trace.color, contributions[ numCon ].color );
+		VectorCopy( trace.direction, contributions[ numCon ].dir );
+		contributions[ numCon ].style = trace.light->style;
+		numCon++;
+		
+		/* push average direction around */
+		addSize = VectorLength( trace.color );
+		VectorMA( gp->dir, addSize, trace.direction, gp->dir );
+		
+		/* stop after a while */
+		if( numCon >= (MAX_CONTRIBUTIONS - 1) )
+			break;
+		
+		/* ydnar: cheap mode */
+		VectorAdd( cheapColor, trace.color, cheapColor );
+		if( cheapgrid && cheapColor[ 0 ] >= 255.0f && cheapColor[ 1 ] >= 255.0f && cheapColor[ 2 ] >= 255.0f )
+			break;
+	}
+	
+	/* normalize to get primary light direction */
+	VectorNormalize( gp->dir, gp->dir );
+	
+	/* now that we have identified the primary light direction,
+	   go back and separate all the light into directed and ambient */
+	numStyles = 1;
+	for( i = 0; i < numCon; i++ )
+	{
+		/* get relative directed strength */
+		d = DotProduct( contributions[ i ].dir, gp->dir );
+		if( d < 0.0f )
+			d = 0.0f;
+		
+		/* find appropriate style */
+		for( j = 0; j < numStyles; j++ )
+		{
+			if( gp->styles[ j ] == contributions[ i ].style )
+				break;
+		}
+		
+		/* style not found? */
+		if( j >= numStyles )
+		{
+			/* add a new style */
+			if( numStyles < MAX_LIGHTMAPS )
+			{
+				gp->styles[ numStyles ] = contributions[ i ].style;
+				bgp->styles[ numStyles ] = contributions[ i ].style;
+				numStyles++;
+				//%	Sys_Printf( "(%d, %d) ", num, contributions[ i ].style );
+			}
+			
+			/* fallback */
+			else
+				j = 0;
+		}
+		
+		/* add the directed color */
+		VectorMA( gp->directed[ j ], d, contributions[ i ].color, gp->directed[ j ] );
+		
+		/* ambient light will be at 1/4 the value of directed light */
+		/* (ydnar: nuke this in favor of more dramatic lighting?) */
+		d = 0.25f * (1.0f - d);
+		VectorMA( gp->ambient[ j ], d, contributions[ i ].color, gp->ambient[ j ] );
+	}
+	
+	
+	/* store off sample */
+	for( i = 0; i < MAX_LIGHTMAPS; i++ )
+	{
+		/* do some fudging to keep the ambient from being too low (2003-07-05: 0.25 -> 0.125) */
+		if( !bouncing )
+			VectorMA( gp->ambient[ i ], 0.125f, gp->directed[ i ], gp->ambient[ i ] );
+		
+		/* set minimum light and copy off to bytes */
+		VectorCopy( gp->ambient[ i ], color );
+		for( j = 0; j < 3; j++ )
+			if( color[ j ] < minGridLight[ j ] )
+				color[ j ] = minGridLight[ j ];
+		ColorToBytes( color, bgp->ambient[ i ], 1.0f );
+		ColorToBytes( gp->directed[ i ], bgp->directed[ i ], 1.0f );
+	}
+	
+	/* debug code */
+	#if 0
+		//%	Sys_FPrintf( SYS_VRB, "%10d %10d %10d ", &gp->ambient[ 0 ][ 0 ], &gp->ambient[ 0 ][ 1 ], &gp->ambient[ 0 ][ 2 ] );
+		Sys_FPrintf( SYS_VRB, "%9d Amb: (%03.1f %03.1f %03.1f) Dir: (%03.1f %03.1f %03.1f)\n",
+			num,
+			gp->ambient[ 0 ][ 0 ], gp->ambient[ 0 ][ 1 ], gp->ambient[ 0 ][ 2 ],
+			gp->directed[ 0 ][ 0 ], gp->directed[ 0 ][ 1 ], gp->directed[ 0 ][ 2 ] );
+	#endif
+	
+	/* store direction */
+	NormalToLatLong( gp->dir, bgp->latLong );
+}
+
+
+
+/*
+SetupGrid()
+calculates the size of the lightgrid and allocates memory
+*/
+
+void SetupGrid( void )
+{
+	int			i, j;
+	vec3_t		maxs, oldGridSize;
+	const char	*value;
+	char		temp[ 64 ];
+	
+	 
+	/* don't do this if not grid lighting */
+	if( noGridLighting )
+		return;
+	
+	/* ydnar: set grid size */
+	value = ValueForKey( &entities[ 0 ], "gridsize" );
+	if( value[ 0 ] != '\0' )
+		sscanf( value, "%f %f %f", &gridSize[ 0 ], &gridSize[ 1 ], &gridSize[ 2 ] );
+	
+	/* quantize it */
+	VectorCopy( gridSize, oldGridSize );
+	for( i = 0; i < 3; i++ )
+		gridSize[ i ] = gridSize[ i ] >= 8.0f ? floor( gridSize[ i ] ) : 8.0f;
+	
+	/* ydnar: increase gridSize until grid count is smaller than max allowed */
+	numRawGridPoints = MAX_MAP_LIGHTGRID + 1;
+	j = 0;
+	while( numRawGridPoints > MAX_MAP_LIGHTGRID )
+	{
+		/* get world bounds */
+		for( i = 0; i < 3; i++ )
+		{
+			gridMins[ i ] = gridSize[ i ] * ceil( bspModels[ 0 ].mins[ i ] / gridSize[ i ] );
+			maxs[ i ] = gridSize[ i ] * floor( bspModels[ 0 ].maxs[ i ] / gridSize[ i ] );
+			gridBounds[ i ] = (maxs[ i ] - gridMins[ i ]) / gridSize[ i ] + 1;
+		}
+	
+		/* set grid size */
+		numRawGridPoints = gridBounds[ 0 ] * gridBounds[ 1 ] * gridBounds[ 2 ];
+		
+		/* increase grid size a bit */
+		if( numRawGridPoints > MAX_MAP_LIGHTGRID )
+			gridSize[ j++ % 3 ] += 16.0f;
+	}
+	
+	/* print it */
+	Sys_Printf( "Grid size = { %1.0f, %1.0f, %1.0f }\n", gridSize[ 0 ], gridSize[ 1 ], gridSize[ 2 ] );
+	
+	/* different? */
+	if( !VectorCompare( gridSize, oldGridSize ) )
+	{
+		sprintf( temp, "%.0f %.0f %.0f", gridSize[ 0 ], gridSize[ 1 ], gridSize[ 2 ] );
+		SetKeyValue( &entities[ 0 ], "gridsize", (const char*) temp );
+		Sys_FPrintf( SYS_VRB, "Storing adjusted grid size\n" );
+	}
+	
+	/* 2nd variable. fixme: is this silly? */
+	numBSPGridPoints = numRawGridPoints;
+	
+	/* allocate lightgrid */
+	rawGridPoints = safe_malloc( numRawGridPoints * sizeof( *rawGridPoints ) );
+	memset( rawGridPoints, 0, numRawGridPoints * sizeof( *rawGridPoints ) );
+	
+	if( bspGridPoints != NULL )
+		free( bspGridPoints );
+	bspGridPoints = safe_malloc( numBSPGridPoints * sizeof( *bspGridPoints ) );
+	memset( bspGridPoints, 0, numBSPGridPoints * sizeof( *bspGridPoints ) );
+	
+	/* clear lightgrid */
+	for( i = 0; i < numRawGridPoints; i++ )
+	{
+		VectorCopy( ambientColor, rawGridPoints[ i ].ambient[ j ] );
+		rawGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
+		bspGridPoints[ i ].styles[ 0 ] = LS_NORMAL;
+		for( j = 1; j < MAX_LIGHTMAPS; j++ )
+		{
+			rawGridPoints[ i ].styles[ j ] = LS_NONE;
+			bspGridPoints[ i ].styles[ j ] = LS_NONE;
+		}
+	}
+	
+	/* note it */
+	Sys_Printf( "%9d grid points\n", numRawGridPoints );
+}
+
+
+
+/*
+LightWorld()
+does what it says...
+*/
+
+void LightWorld( void )
+{
+	vec3_t		color;
+	float		f;
+	int			b, bt;
+	qboolean	minVertex, minGrid;
+	const char	*value;
+	
+
+	/* ydnar: smooth normals */
+	if( shade )
+	{
+		Sys_Printf( "--- SmoothNormals ---\n" );
+		SmoothNormals();
+	}
+	
+	/* determine the number of grid points */
+	Sys_Printf( "--- SetupGrid ---\n" );
+	SetupGrid();
+	
+	/* find the optional minimum lighting values */
+	GetVectorForKey( &entities[ 0 ], "_color", color );
+	if( VectorLength( color ) == 0.0f )
+		VectorSet( color, 1.0, 1.0, 1.0 );
+	
+	/* ambient */
+	f = FloatForKey( &entities[ 0 ], "_ambient" );
+	if( f == 0.0f )
+		f = FloatForKey( &entities[ 0 ], "ambient" );
+	VectorScale( color, f, ambientColor );
+	
+	/* minvertexlight */
+	minVertex = qfalse;
+	value = ValueForKey( &entities[ 0 ], "_minvertexlight" );
+	if( value[ 0 ] != '\0' )
+	{
+		minVertex = qtrue;
+		f = atof( value );
+		VectorScale( color, f, minVertexLight );
+	}
+	
+	/* mingridlight */
+	minGrid = qfalse;
+	value = ValueForKey( &entities[ 0 ], "_mingridlight" );
+	if( value[ 0 ] != '\0' )
+	{
+		minGrid = qtrue;
+		f = atof( value );
+		VectorScale( color, f, minGridLight );
+	}
+	
+	/* minlight */
+	value = ValueForKey( &entities[ 0 ], "_minlight" );
+	if( value[ 0 ] != '\0' )
+	{
+		f = atof( value );
+		VectorScale( color, f, minLight );
+		if( minVertex == qfalse )
+			VectorScale( color, f, minVertexLight );
+		if( minGrid == qfalse )
+			VectorScale( color, f, minGridLight );
+	}
+	
+	/* create world lights */
+	Sys_FPrintf( SYS_VRB, "--- CreateLights ---\n" );
+	CreateEntityLights();
+	CreateSurfaceLights();
+	Sys_Printf( "%9d point lights\n", numPointLights );
+	Sys_Printf( "%9d spotlights\n", numSpotLights );
+	Sys_Printf( "%9d diffuse (area) lights\n", numDiffuseLights );
+	Sys_Printf( "%9d sun/sky lights\n", numSunLights );
+	
+	/* calculate lightgrid */
+	if( !noGridLighting )
+	{
+		/* ydnar: set up light envelopes */
+		SetupEnvelopes( qtrue, fastgrid );
+		
+		Sys_Printf( "--- TraceGrid ---\n" );
+		RunThreadsOnIndividual( numRawGridPoints, qtrue, TraceGrid );
+		Sys_Printf( "%d x %d x %d = %d grid\n",
+			gridBounds[ 0 ], gridBounds[ 1 ], gridBounds[ 2 ], numBSPGridPoints );
+		
+		/* ydnar: emit statistics on light culling */
+		Sys_FPrintf( SYS_VRB, "%9d grid points envelope culled\n", gridEnvelopeCulled );
+		Sys_FPrintf( SYS_VRB, "%9d grid points bounds culled\n", gridBoundsCulled );
+	}
+	
+	/* slight optimization to remove a sqrt */
+	subdivideThreshold *= subdivideThreshold;
+	
+	/* map the world luxels */
+	Sys_Printf( "--- MapRawLightmap ---\n" );
+	RunThreadsOnIndividual( numRawLightmaps, qtrue, MapRawLightmap );
+	Sys_Printf( "%9d luxels\n", numLuxels );
+	Sys_Printf( "%9d luxels mapped\n", numLuxelsMapped );
+	Sys_Printf( "%9d luxels occluded\n", numLuxelsOccluded );
+
+	/* ydnar: set up light envelopes */
+	SetupEnvelopes( qfalse, fast );
+	
+	/* light up my world */
+	lightsPlaneCulled = 0;
+	lightsEnvelopeCulled = 0;
+	lightsBoundsCulled = 0;
+	lightsClusterCulled = 0;
+	
+	Sys_Printf( "--- IlluminateRawLightmap ---\n" );
+	RunThreadsOnIndividual( numRawLightmaps, qtrue, IlluminateRawLightmap );
+	Sys_Printf( "%9d luxels illuminated\n", numLuxelsIlluminated );
+	
+	StitchSurfaceLightmaps();
+	
+	Sys_Printf( "--- IlluminateVertexes ---\n" );
+	RunThreadsOnIndividual( numBSPDrawSurfaces, qtrue, IlluminateVertexes );
+	Sys_Printf( "%9d vertexes illuminated\n", numVertsIlluminated );
+	
+	/* ydnar: emit statistics on light culling */
+	Sys_FPrintf( SYS_VRB, "%9d lights plane culled\n", lightsPlaneCulled );
+	Sys_FPrintf( SYS_VRB, "%9d lights envelope culled\n", lightsEnvelopeCulled );
+	Sys_FPrintf( SYS_VRB, "%9d lights bounds culled\n", lightsBoundsCulled );
+	Sys_FPrintf( SYS_VRB, "%9d lights cluster culled\n", lightsClusterCulled );
+	
+	/* radiosity */
+	b = 1;
+	bt = bounce;
+	while( bounce > 0 )
+	{
+		/* store off the bsp between bounces */
+		StoreSurfaceLightmaps();
+		Sys_Printf( "Writing %s\n", source );
+		WriteBSPFile( source );
+		
+		/* note it */
+		Sys_Printf( "\n--- Radiosity (bounce %d of %d) ---\n", b, bt );
+		
+		/* flag bouncing */
+		bouncing = qtrue;
+		VectorClear( ambientColor );
+		
+		/* generate diffuse lights */
+		RadFreeLights();
+		RadCreateDiffuseLights();
+		
+		/* setup light envelopes */
+		SetupEnvelopes( qfalse, fastbounce );
+		if( numLights == 0 )
+		{
+			Sys_Printf( "No diffuse light to calculate, ending radiosity.\n" );
+			break;
+		}
+		
+		/* add to lightgrid */
+		if( bouncegrid )
+		{
+			gridEnvelopeCulled = 0;
+			gridBoundsCulled = 0;
+			
+			Sys_Printf( "--- BounceGrid ---\n" );
+			RunThreadsOnIndividual( numRawGridPoints, qtrue, TraceGrid );
+			Sys_FPrintf( SYS_VRB, "%9d grid points envelope culled\n", gridEnvelopeCulled );
+			Sys_FPrintf( SYS_VRB, "%9d grid points bounds culled\n", gridBoundsCulled );
+		}
+		
+		/* light up my world */
+		lightsPlaneCulled = 0;
+		lightsEnvelopeCulled = 0;
+		lightsBoundsCulled = 0;
+		lightsClusterCulled = 0;
+		
+		Sys_Printf( "--- IlluminateRawLightmap ---\n" );
+		RunThreadsOnIndividual( numRawLightmaps, qtrue, IlluminateRawLightmap );
+		Sys_Printf( "%9d luxels illuminated\n", numLuxelsIlluminated );
+		Sys_Printf( "%9d vertexes illuminated\n", numVertsIlluminated );
+		
+		StitchSurfaceLightmaps();
+		
+		Sys_Printf( "--- IlluminateVertexes ---\n" );
+		RunThreadsOnIndividual( numBSPDrawSurfaces, qtrue, IlluminateVertexes );
+		Sys_Printf( "%9d vertexes illuminated\n", numVertsIlluminated );
+		
+		/* ydnar: emit statistics on light culling */
+		Sys_FPrintf( SYS_VRB, "%9d lights plane culled\n", lightsPlaneCulled );
+		Sys_FPrintf( SYS_VRB, "%9d lights envelope culled\n", lightsEnvelopeCulled );
+		Sys_FPrintf( SYS_VRB, "%9d lights bounds culled\n", lightsBoundsCulled );
+		Sys_FPrintf( SYS_VRB, "%9d lights cluster culled\n", lightsClusterCulled );
+		
+		/* interate */
+		bounce--;
+		b++;
+	}
+}
+
+
+
+/*
+LightMain()
+main routine for light processing
+*/
+
+int LightMain( int argc, char **argv )
+{
+	int			i;
+	float		f;
+	char		mapSource[ 1024 ];
+	const char	*value;
+	
+	
+	/* note it */
+	Sys_Printf( "--- Light ---\n" );
+	
+	/* process commandline arguments */
+	for( i = 1; i < (argc - 1); i++ )
+	{
+		/* lightsource scaling */
+		if( !strcmp( argv[ i ], "-point" ) || !strcmp( argv[ i ], "-pointscale" ) )
+		{
+			f = atof( argv[ i + 1 ] );
+			pointScale *= f;
+			Sys_Printf( "Point (entity) light scaled by %f to %f\n", f, pointScale );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-area" ) || !strcmp( argv[ i ], "-areascale" ) )
+		{
+			f = atof( argv[ i + 1 ] );
+			areaScale *= f;
+			Sys_Printf( "Area (shader) light scaled by %f to %f\n", f, areaScale );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-sky" ) || !strcmp( argv[ i ], "-skyscale" ) )
+		{
+			f = atof( argv[ i + 1 ] );
+			skyScale *= f;
+			Sys_Printf( "Sky/sun light scaled by %f to %f\n", f, skyScale );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-bouncescale" ) )
+		{
+			f = atof( argv[ i + 1 ] );
+			bounceScale *= f;
+			Sys_Printf( "Bounce (radiosity) light scaled by %f to %f\n", f, bounceScale );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-scale" ) )
+		{
+			f = atof( argv[ i + 1 ] );
+			pointScale *= f;
+			areaScale *= f;
+			skyScale *= f;
+			bounceScale *= f;
+			Sys_Printf( "All light scaled by %f\n", f );
+			i++;
+		}
+		
+		/* ydnar switches */
+		else if( !strcmp( argv[ i ], "-bounce" ) )
+		{
+			bounce = atoi( argv[ i + 1 ] );
+			if( bounce < 0 )
+				bounce = 0;
+			else if( bounce > 0 )
+				Sys_Printf( "Radiosity enabled with %d bounce(s)\n", bounce );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-supersample" ) || !strcmp( argv[ i ], "-super" ) )
+		{
+			superSample = atoi( argv[ i + 1 ] );
+			if( superSample < 1 )
+				superSample = 1;
+			else if( superSample > 1 )
+				Sys_Printf( "Ordered-grid supersampling enabled with %d sample(s) per lightmap texel\n", (superSample * superSample) );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-samples" ) )
+		{
+			lightSamples = atoi( argv[ i + 1 ] );
+			if( lightSamples < 1 )
+				lightSamples = 1;
+			else if( lightSamples > 1 )
+				Sys_Printf( "Adaptive supersampling enabled with %d sample(s) per lightmap texel\n", lightSamples );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-filter" ) )
+		{
+			filter = qtrue;
+			Sys_Printf( "Lightmap filtering enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-shadeangle" ) )
+		{
+			shadeAngleDegrees = atof( argv[ i + 1 ] );
+			if( shadeAngleDegrees < 0.0f )
+				shadeAngleDegrees = 0.0f;
+			else if( shadeAngleDegrees > 0.0f )
+			{
+				shade = qtrue;
+				Sys_Printf( "Phong shading enabled with a breaking angle of %f degrees\n", shadeAngleDegrees );
+			}
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-thresh" ) )
+		{
+			subdivideThreshold = atof( argv[ i + 1 ] );
+			if( subdivideThreshold < 0 )
+				subdivideThreshold = DEFAULT_SUBDIVIDE_THRESHOLD;
+			else
+				Sys_Printf( "Subdivision threshold set at %.3f\n", subdivideThreshold );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-approx" ) )
+		{
+			approximateTolerance = atoi( argv[ i + 1 ] );
+			if( approximateTolerance < 0 )
+				approximateTolerance = 0;
+			else if( approximateTolerance > 0 )
+				Sys_Printf( "Approximating lightmaps within a byte tolerance of %d\n", approximateTolerance );
+			i++;
+		}
+		
+		else if( !strcmp( argv[ i ], "-deluxe" ) || !strcmp( argv[ i ], "-deluxemap" ) )
+		{
+			deluxemap = qtrue;
+			Sys_Printf( "Generating deluxemaps for average light direction\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-external" ) )
+		{
+			externalLightmaps = qtrue;
+			Sys_Printf( "Storing all lightmaps externally\n" );
+		}
+
+		else if( !strcmp( argv[ i ], "-lightmapsize" ) )
+		{
+			lmCustomSize = atoi( argv[ i + 1 ] );
+			
+			/* must be a power of 2 and greater than 2 */
+			if( ((lmCustomSize - 1) & lmCustomSize) || lmCustomSize < 2 )
+			{
+				Sys_Printf( "WARNING: Lightmap size must be a power of 2, greater or equal to 2 pixels.\n" );
+				lmCustomSize = LIGHTMAP_WIDTH;
+			}
+			i++;
+			Sys_Printf( "Default lightmap size set to %d x %d pixels\n", lmCustomSize, lmCustomSize );
+			
+			/* enable external lightmaps */
+			if( lmCustomSize != LIGHTMAP_WIDTH )
+			{
+				externalLightmaps = qtrue;
+				Sys_Printf( "Storing all lightmaps externally\n" );
+			}
+		}
+		
+		/* ydnar: add this to suppress warnings */
+		else if( !strcmp( argv[ i ],  "-custinfoparms") )
+		{
+			Sys_Printf( "Custom info parms enabled\n" );
+			useCustomInfoParms = qtrue;
+		}
+		
+		else if( !strcmp( argv[ i ], "-wolf" ) )
+		{
+			/* -game should already be set */
+			game->wolfLight = qtrue;
+			Sys_Printf( "Enabling Wolf lighting model\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-sunonly" ) )
+		{
+			sunOnly = qtrue;
+			Sys_Printf( "Only computing sunlight\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-bounceonly" ) )
+		{
+			bounceOnly = qtrue;
+			Sys_Printf( "Storing bounced light (radiosity) only\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-nocollapse" ) )
+		{
+			noCollapse = qtrue;
+			Sys_Printf( "Identical lightmap collapsing disabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-shade" ) )
+		{
+			shade = qtrue;
+			Sys_Printf( "Phong shading enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-bouncegrid") )
+		{
+			bouncegrid = qtrue;
+			if( bounce > 0 )
+				Sys_Printf( "Grid lighting with radiosity enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-smooth" ) )
+		{
+			smooth = qtrue;
+			lightSamples = EXTRA_SCALE;
+			Sys_Printf( "The -smooth argument is deprecated, use \"-samples 2\" instead\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-fast" ) )
+		{
+			fast = qtrue;
+			fastgrid = qtrue;
+			fastbounce = qtrue;
+			Sys_Printf( "Fast mode enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-faster" ) )
+		{
+			faster = qtrue;
+			fast = qtrue;
+			fastgrid = qtrue;
+			fastbounce = qtrue;
+			Sys_Printf( "Faster mode enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-fastgrid" ) )
+		{
+			fastgrid = qtrue;
+			Sys_Printf( "Fast grid lighting enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-fastbounce" ) )
+		{
+			fastbounce = qtrue;
+			Sys_Printf( "Fast bounce mode enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-cheap" ) )
+		{
+			cheap = qtrue;
+			cheapgrid = qtrue;
+			Sys_Printf( "Cheap mode enabled\n" );
+		}
+
+		else if( !strcmp( argv[ i ], "-cheapgrid" ) )
+		{
+			cheapgrid = qtrue;
+			Sys_Printf( "Cheap grid mode enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-normalmap" ) )
+		{
+			normalmap = qtrue;
+			Sys_Printf( "Storing normal map instead of lightmap\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-trisoup" ) )
+		{
+			trisoup = qtrue;
+			Sys_Printf( "Converting brush faces to triangle soup\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-debug" ) )
+		{
+			debug = qtrue;
+			Sys_Printf( "Lightmap debugging enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-debugsurfaces" ) || !strcmp( argv[ i ], "-debugsurface" ) )
+		{
+			debugSurfaces = qtrue;
+			Sys_Printf( "Lightmap surface debugging enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-debugunused" ) )
+		{
+			debugUnused = qtrue;
+			Sys_Printf( "Unused luxel debugging enabled\n" );
+		}
+
+		else if( !strcmp( argv[ i ], "-debugaxis" ) )
+		{
+			debugAxis = qtrue;
+			Sys_Printf( "Lightmap axis debugging enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-debugcluster" ) )
+		{
+			debugCluster = qtrue;
+			Sys_Printf( "Luxel cluster debugging enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-debugorigin" ) )
+		{
+			debugOrigin = qtrue;
+			Sys_Printf( "Luxel origin debugging enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-debugdeluxe" ) )
+		{
+			deluxemap = qtrue;
+			debugDeluxemap = qtrue;
+			Sys_Printf( "Deluxemap debugging enabled\n" );
+		}
+		
+		else if( !strcmp( argv[ i ], "-export" ) )
+		{
+			exportLightmaps = qtrue;
+			Sys_Printf( "Exporting lightmaps\n" );
+		}
+		
+		else if( !strcmp(argv[ i ], "-notrace" )) 
+		{
+			noTrace = qtrue;
+			Sys_Printf( "Shadow occlusion disabled\n" );
+		}
+		else if( !strcmp(argv[ i ], "-patchshadows" ) )
+		{
+			patchShadows = qtrue;
+			Sys_Printf( "Patch shadow casting enabled\n" );
+		}
+		else if( !strcmp( argv[ i ], "-extra" ) )
+		{
+			extra = qtrue;
+			superSample = EXTRA_SCALE;		/* ydnar */
+			Sys_Printf( "The -extra argument is deprecated, use \"-super 2\" instead\n" );
+		}
+		else if( !strcmp( argv[ i ], "-extrawide" ) )
+		{
+			extra = qtrue;
+			extraWide = qtrue;
+			superSample = EXTRAWIDE_SCALE;	/* ydnar */
+			filter = qtrue;					/* ydnar */
+			Sys_Printf( "The -extrawide argument is deprecated, use \"-filter [-super 2]\" instead\n");
+		}
+		else if( !strcmp( argv[ i ], "-samplesize" ) )
+		{
+			sampleSize = atoi( argv[ i + 1 ] );
+			if( sampleSize < 1 )
+				sampleSize = 1;
+			i++;
+			Sys_Printf( "Default lightmap sample size set to %dx%d units\n", sampleSize, sampleSize );
+		}
+		else if( !strcmp( argv[ i ], "-novertex" ) )
+		{
+			noVertexLighting = qtrue;
+			Sys_Printf( "Disabling vertex lighting\n" );
+		}
+		else if( !strcmp( argv[ i ], "-nogrid" ) )
+		{
+			noGridLighting = qtrue;
+			Sys_Printf( "Disabling grid lighting\n" );
+		}
+		else if( !strcmp( argv[ i ], "-border" ) )
+		{
+			lightmapBorder = qtrue;
+			Sys_Printf( "Adding debug border to lightmaps\n" );
+		}
+		else if( !strcmp( argv[ i ], "-nosurf" ) )
+		{
+			noSurfaces = qtrue;
+			Sys_Printf( "Not tracing against surfaces\n" );
+		}
+		else if( !strcmp( argv[ i ], "-dump" ) )
+		{
+			dump = qtrue;
+			Sys_Printf( "Dumping radiosity lights into numbered prefabs\n" );
+		}
+		else if( !strcmp( argv[ i ], "-lomem" ) )
+		{
+			loMem = qtrue;
+			Sys_Printf( "Enabling low-memory (potentially slower) lighting mode\n" );
+		}
+		
+		else
+			Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
+	}
+	
+	/* clean up map name */
+	strcpy( source, ExpandArg( argv[ i ] ) );
+	StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	strcpy( mapSource, ExpandArg( argv[ i ] ) );
+	StripExtension( mapSource );
+	DefaultExtension( mapSource, ".map" );
+	
+	/* ydnar: set default sample size */
+	SetDefaultSampleSize( sampleSize );
+	
+	/* ydnar: handle shaders */
+	BeginMapShaderFile( source );
+	LoadShaderInfo();
+	
+	/* note loading */
+	Sys_Printf( "Loading %s\n", source );
+	
+	/* ydnar: load surface file */
+	LoadSurfaceExtraFile( source );
+	
+	/* load bsp file */
+	LoadBSPFile( source );
+	
+	/* parse bsp entities */
+	ParseEntities();
+	
+	/* load map file */
+	value = ValueForKey( &entities[ 0 ], "_keepLights" );
+	if( value[ 0 ] != '1' )
+		LoadMapFile( mapSource, qtrue );
+	
+	/* set the entity/model origins and init yDrawVerts */
+	SetEntityOrigins();
+	
+	/* ydnar: set up optimization */
+	SetupBrushes();
+	SetupSurfaceLightmaps();
+	
+	/* initialize the surface facet tracing */
+	SetupTraceNodes();
+	
+	/* light the world */
+	LightWorld();
+	
+	/* ydnar: store off lightmaps */
+	StoreSurfaceLightmaps();
+	
+	/* write out the bsp */
+	UnparseEntities();
+	Sys_Printf( "Writing %s\n", source );
+	WriteBSPFile( source );
+	
+	/* ydnar: export lightmaps */
+	if( exportLightmaps && !externalLightmaps )
+		ExportLightmaps();
+	
+	/* return to sender */
+	return 0;
+}
+
diff --git a/tools/quake3/q3map2/light_bounce.c b/tools/quake3/q3map2/light_bounce.c
index e4d23da3..4181ce53 100644
--- a/tools/quake3/q3map2/light_bounce.c
+++ b/tools/quake3/q3map2/light_bounce.c
@@ -1,954 +1,954 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define LIGHT_BOUNCE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* functions */
-
-/*
-RadFreeLights()
-deletes any existing lights, freeing up memory for the next bounce
-*/
-
-void RadFreeLights( void )
-{
-	light_t		*light, *next;
-	
-	
-	/* delete lights */
-	for( light = lights; light; light = next )
-	{
-		next = light->next;
-		if( light->w != NULL )
-			FreeWinding( light->w );
-		free( light );
-	}
-	numLights = 0;
-	lights = NULL;
-}
-
-
-
-/*
-RadClipWindingEpsilon()
-clips a rad winding by a plane
-based off the regular clip winding code
-*/
-
-static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
-	vec_t epsilon, radWinding_t *front, radWinding_t *back, clipWork_t *cw )
-{
-	vec_t			*dists;
-	int				*sides;
-	int				counts[ 3 ];
-	vec_t			dot;		/* ydnar: changed from static b/c of threading */ /* VC 4.2 optimizer bug if not static? */
-	int				i, j, k;
-	radVert_t		*v1, *v2, mid;
-	int				maxPoints;
-	
-	
-	/* crutch */
-	dists = cw->dists;
-	sides = cw->sides;
-	
-	/* clear counts */
-	counts[ 0 ] = counts[ 1 ] = counts[ 2 ] = 0;
-
-	/* determine sides for each point */
-	for( i = 0; i < in->numVerts; i++ )
-	{
-		dot = DotProduct( in->verts[ i ].xyz, normal );
-		dot -= dist;
-		dists[ i ] = dot;
-		if( dot > epsilon )
-			sides[ i ] = SIDE_FRONT;
-		else if( dot < -epsilon )
-			sides[ i ] = SIDE_BACK;
-		else
-			sides[ i ] = SIDE_ON;
-		counts[ sides[ i ] ]++;
-	}
-	sides[ i ] = sides[ 0 ];
-	dists[ i ] = dists[ 0 ];
-	
-	/* clear front and back */
-	front->numVerts = back->numVerts = 0;
-	
-	/* handle all on one side cases */
-	if( counts[ 0 ] == 0 )
-	{
-		memcpy( back, in, sizeof( radWinding_t ) );
-		return;
-	}
-	if( counts[ 1 ] == 0 )
-	{
-		memcpy( front, in, sizeof( radWinding_t ) );
-		return;
-	}
-	
-	/* setup windings */
-	maxPoints = in->numVerts + 4;
-	
-	/* do individual verts */
-	for( i = 0; i < in->numVerts; i++ )
-	{
-		/* do simple vertex copies first */
-		v1 = &in->verts[ i ];
-		
-		if( sides[ i ] == SIDE_ON )
-		{
-			memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) );
-			memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) );
-			continue;
-		}
-	
-		if( sides[ i ] == SIDE_FRONT )
-			memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) );
-		
-		if( sides[ i ] == SIDE_BACK )
-			memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) );
-		
-		if( sides[ i + 1 ] == SIDE_ON || sides[ i + 1 ] == sides[ i ] )
-			continue;
-			
-		/* generate a split vertex */
-		v2 = &in->verts[ (i + 1) % in->numVerts ];
-		
-		dot = dists[ i ] / (dists[ i ] - dists[ i + 1 ]);
-
-		/* average vertex values */
-		for( j = 0; j < 4; j++ )
-		{
-			/* color */
-			if( j < 4 )
-			{
-				for( k = 0; k < MAX_LIGHTMAPS; k++ )
-					mid.color[ k ][ j ] = v1->color[ k ][ j ] + dot * (v2->color[ k ][ j ] - v1->color[ k ][ j ]);
-			}
-			
-			/* xyz, normal */
-			if( j < 3 )
-			{
-				mid.xyz[ j ] = v1->xyz[ j ] + dot * (v2->xyz[ j ] - v1->xyz[ j ]);
-				mid.normal[ j ] = v1->normal[ j ] + dot * (v2->normal[ j ] - v1->normal[ j ]);
-			}
-			
-			/* st, lightmap */
-			if( j < 2 )
-			{
-				mid.st[ j ] = v1->st[ j ] + dot * (v2->st[ j ] - v1->st[ j ]);
-				for( k = 0; k < MAX_LIGHTMAPS; k++ )
-					mid.lightmap[ k ][ j ] = v1->lightmap[ k ][ j ] + dot * (v2->lightmap[ k ][ j ] - v1->lightmap[ k ][ j ]);
-			}
-		}
-		
-		/* normalize the averaged normal */
-		VectorNormalize( mid.normal, mid.normal );
-
-		/* copy the midpoint to both windings */
-		memcpy( &front->verts[ front->numVerts++ ], &mid, sizeof( radVert_t ) );
-		memcpy( &back->verts[ back->numVerts++ ], &mid, sizeof( radVert_t ) );
-	}
-	
-	/* error check */
-	if( front->numVerts > maxPoints || front->numVerts > maxPoints )
-		Error( "RadClipWindingEpsilon: points exceeded estimate" );
-	if( front->numVerts > MAX_POINTS_ON_WINDING || front->numVerts > MAX_POINTS_ON_WINDING )
-		Error( "RadClipWindingEpsilon: MAX_POINTS_ON_WINDING" );
-}
-
-
-
-
-
-/*
-RadSampleImage()
-samples a texture image for a given color
-returns qfalse if pixels are bad
-*/
-
-qboolean RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] )
-{
-	float	sto[ 2 ];
-	int		x, y;
-	
-	
-	/* clear color first */
-	color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 255;
-	
-	/* dummy check */
-	if( pixels == NULL || width < 1 || height < 1 )
-		return qfalse;
-	
-	/* bias st */
-	sto[ 0 ] = st[ 0 ];
-	while( sto[ 0 ] < 0.0f )
-		sto[ 0 ] += 1.0f;
-	sto[ 1 ] = st[ 1 ];
-	while( sto[ 1 ] < 0.0f )
-		sto[ 1 ] += 1.0f;
-
-	/* get offsets */
-	x = ((float) width * sto[ 0 ]) + 0.5f;
-	x %= width;
-	y = ((float) height * sto[ 1 ])  + 0.5f;
-	y %= height;
-	
-	/* get pixel */
-	pixels += (y * width * 4) + (x * 4);
-	VectorCopy( pixels, color );
-	color[ 3 ] = pixels[ 3 ];
-	return qtrue;
-}
-
-
-
-/*
-RadSample()
-samples a fragment's lightmap or vertex color and returns an
-average color and a color gradient for the sample
-*/
-
-#define MAX_SAMPLES			150
-#define SAMPLE_GRANULARITY	6
-
-static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si, radWinding_t *rw, vec3_t average, vec3_t gradient, int *style )
-{
-	int			i, j, k, l, v, x, y, samples;
-	vec3_t		color, mins, maxs;
-	vec4_t		textureColor;
-	float		alpha, alphaI, bf;
-	vec3_t		blend;
-	float		st[ 2 ], lightmap[ 2 ], *radLuxel;
-	radVert_t	*rv[ 3 ];
-	
-	
-	/* initial setup */
-	ClearBounds( mins, maxs );
-	VectorClear( average );
-	VectorClear( gradient );
-	alpha = 0;
-	
-	/* dummy check */
-	if( rw == NULL || rw->numVerts < 3 )
-		return;
-	
-	/* start sampling */
-	samples = 0;
-	
-	/* sample vertex colors if no lightmap or this is the initial pass */
-	if( lm == NULL || lm->radLuxels[ lightmapNum ] == NULL || bouncing == qfalse )
-	{
-		for( samples = 0; samples < rw->numVerts; samples++ )
-		{
-			/* multiply by texture color */
-			if( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, rw->verts[ samples ].st, textureColor ) )
-			{
-				VectorCopy( si->averageColor, textureColor );
-				textureColor[ 4 ] = 255.0f;
-			}
-			for( i = 0; i < 3; i++ )
-				color[ i ] = (textureColor[ i ] / 255) * (rw->verts[ samples ].color[ lightmapNum ][ i ] / 255.0f);
-			
-			AddPointToBounds( color, mins, maxs );
-			VectorAdd( average, color, average );
-			
-			/* get alpha */
-			alpha += (textureColor[ 3 ] / 255.0f) * (rw->verts[ samples ].color[ lightmapNum ][ 3 ] / 255.0f);
-		}
-		
-		/* set style */
-		*style = ds->vertexStyles[ lightmapNum ];
-	}
-	
-	/* sample lightmap */
-	else
-	{
-		/* fracture the winding into a fan (including degenerate tris) */
-		for( v = 1; v < (rw->numVerts - 1) && samples < MAX_SAMPLES; v++ )
-		{
-			/* get a triangle */
-			rv[ 0 ] = &rw->verts[ 0 ];
-			rv[ 1 ] = &rw->verts[ v ];
-			rv[ 2 ] = &rw->verts[ v + 1 ];
-			
-			/* this code is embarassing (really should just rasterize the triangle) */
-			for( i = 1; i < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; i++ )
-			{
-				for( j = 1; j < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; j++ )
-				{
-					for( k = 1; k < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; k++ )
-					{
-						/* create a blend vector (barycentric coordinates) */
-						blend[ 0 ] = i;
-						blend[ 1 ] = j;
-						blend[ 2 ] = k;
-						bf = (1.0 / (blend[ 0 ] + blend[ 1 ] + blend[ 2 ]));
-						VectorScale( blend, bf, blend );
-						
-						/* create a blended sample */
-						st[ 0 ] = st[ 1 ] = 0.0f;
-						lightmap[ 0 ] = lightmap[ 1 ] = 0.0f;
-						alphaI = 0.0f;
-						for( l = 0; l < 3; l++ )
-						{
-							st[ 0 ] += (rv[ l ]->st[ 0 ] * blend[ l ]);
-							st[ 1 ] += (rv[ l ]->st[ 1 ] * blend[ l ]);
-							lightmap[ 0 ] += (rv[ l ]->lightmap[ lightmapNum ][ 0 ] * blend[ l ]);
-							lightmap[ 1 ] += (rv[ l ]->lightmap[ lightmapNum ][ 1 ] * blend[ l ]);
-							alphaI += (rv[ l ]->color[ lightmapNum ][ 3 ] * blend[ l ]);
-						}
-						
-						/* get lightmap xy coords */
-						x = lightmap[ 0 ] / (float) superSample;
-						y = lightmap[ 1 ] / (float) superSample;
-						if( x < 0 )
-							x = 0;
-						else if ( x >= lm->w )
-							x = lm->w - 1;
-						if( y < 0 )
-							y = 0;
-						else if ( y >= lm->h )
-							y = lm->h - 1;
-						
-						/* get radiosity luxel */
-						radLuxel = RAD_LUXEL( lightmapNum, x, y );
-						
-						/* ignore unlit/unused luxels */
-						if( radLuxel[ 0 ] < 0.0f )
-							continue;
-						
-						/* inc samples */
-						samples++;
-						
-						/* multiply by texture color */
-						if( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, st, textureColor ) )
-						{
-							VectorCopy( si->averageColor, textureColor );
-							textureColor[ 4 ] = 255;
-						}
-						for( i = 0; i < 3; i++ )
-							color[ i ] = (textureColor[ i ] / 255) * (radLuxel[ i ] / 255);
-						
-						AddPointToBounds( color, mins, maxs );
-						VectorAdd( average, color, average );
-						
-						/* get alpha */
-						alpha += (textureColor[ 3 ] / 255) * (alphaI / 255);
-					}
-				}
-			}
-		}
-		
-		/* set style */
-		*style = ds->lightmapStyles[ lightmapNum ];
-	}
-	
-	/* any samples? */
-	if( samples <= 0 )
-		return;
-	
-	/* average the color */
-	VectorScale( average, (1.0 / samples), average );
-	
-	/* create the color gradient */
-	//%	VectorSubtract( maxs, mins, delta );
-	
-	/* new: color gradient will always be 0-1.0, expressed as the range of light relative to overall light */
-	//%	gradient[ 0 ] = maxs[ 0 ] > 0.0f ? (maxs[ 0 ] - mins[ 0 ]) / maxs[ 0 ] : 0.0f;
-	//%	gradient[ 1 ] = maxs[ 1 ] > 0.0f ? (maxs[ 1 ] - mins[ 1 ]) / maxs[ 1 ] : 0.0f;
-	//%	gradient[ 2 ] = maxs[ 2 ] > 0.0f ? (maxs[ 2 ] - mins[ 2 ]) / maxs[ 2 ] : 0.0f;
-	
-	/* newer: another contrast function */
-	for( i = 0; i < 3; i++ )
-		gradient[ i ] = (maxs[ i ] - mins[ i ]) * maxs[ i ];
-}
-
-
-
-/*
-RadSubdivideDiffuseLight()
-subdivides a radiosity winding until it is smaller than subdivide, then generates an area light
-*/
-
-#define RADIOSITY_MAX_GRADIENT		0.75f	//%	0.25f
-#define RADIOSITY_VALUE				500.0f
-#define RADIOSITY_MIN				0.0001f
-#define RADIOSITY_CLIP_EPSILON		0.125f
-
-static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si,
-	float scale, float subdivide, qboolean original, radWinding_t *rw, clipWork_t *cw )
-{
-	int				i, style;
-	float			dist, area, value;
-	vec3_t			mins, maxs, normal, d1, d2, cross, color, gradient;
-	light_t			*light, *splash;
-	winding_t		*w;
-	
-	
-	/* dummy check */
-	if( rw == NULL || rw->numVerts < 3 )
-		return;
-	
-	/* get bounds for winding */
-	ClearBounds( mins, maxs );
-	for( i = 0; i < rw->numVerts; i++ )
-		AddPointToBounds( rw->verts[ i ].xyz, mins, maxs );
-	
-	/* subdivide if necessary */
-	for( i = 0; i < 3; i++ )
-	{
-		if( maxs[ i ] - mins[ i ] > subdivide )
-		{
-			radWinding_t	front, back;
-			
-			
-			/* make axial plane */
-			VectorClear( normal );
-			normal[ i ] = 1;
-			dist = (maxs[ i ] + mins[ i ]) * 0.5f;
-			
-			/* clip the winding */
-			RadClipWindingEpsilon( rw, normal, dist, RADIOSITY_CLIP_EPSILON, &front, &back, cw );
-			
-			/* recurse */
-			RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &front, cw );
-			RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &back, cw );
-			return;
-		}
-	}
-	
-	/* check area */
-	area = 0.0f;
-	for( i = 2; i < rw->numVerts; i++ )
-	{
-		VectorSubtract( rw->verts[ i - 1 ].xyz, rw->verts[ 0 ].xyz, d1 );
-		VectorSubtract( rw->verts[ i ].xyz, rw->verts[ 0 ].xyz, d2 );
-		CrossProduct( d1, d2, cross );
-		area += 0.5f * VectorLength( cross );
-	}
-	if( area < 1.0f || area > 20000000.0f )
-		return;
-	
-	/* more subdivision may be necessary */
-	if( bouncing )
-	{
-		/* get color sample for the surface fragment */
-		RadSample( lightmapNum, ds, lm, si, rw, color, gradient, &style );
-		
-		/* if color gradient is too high, subdivide again */
-		if( subdivide > minDiffuseSubdivide && 
-			(gradient[ 0 ] > RADIOSITY_MAX_GRADIENT || gradient[ 1 ] > RADIOSITY_MAX_GRADIENT || gradient[ 2 ] > RADIOSITY_MAX_GRADIENT) )
-		{
-			RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, (subdivide / 2.0f), qfalse, rw, cw );
-			return;
-		}
-	}
-	
-	/* create a regular winding and an average normal */
-	w = AllocWinding( rw->numVerts );
-	w->numpoints = rw->numVerts;
-	VectorClear( normal );
-	for( i = 0; i < rw->numVerts; i++ )
-	{
-		VectorCopy( rw->verts[ i ].xyz, w->p[ i ] );
-		VectorAdd( normal, rw->verts[ i ].normal, normal );
-	}
-	VectorScale( normal, (1.0f / rw->numVerts), normal );
-	if( VectorNormalize( normal, normal ) == 0.0f )
-		return;
-	
-	/* early out? */
-	if( bouncing && VectorLength( color ) < RADIOSITY_MIN )
-		return;
-	
-	/* debug code */
-	//%	Sys_Printf( "Size: %d %d %d\n", (int) (maxs[ 0 ] - mins[ 0 ]), (int) (maxs[ 1 ] - mins[ 1 ]), (int) (maxs[ 2 ] - mins[ 2 ]) );
-	//%	Sys_Printf( "Grad: %f %f %f\n", gradient[ 0 ], gradient[ 1 ], gradient[ 2 ] );
-	
-	/* increment counts */
-	numDiffuseLights++;
-	switch( ds->surfaceType )
-	{
-		case MST_PLANAR:
-			numBrushDiffuseLights++;
-			break;
-		
-		case MST_TRIANGLE_SOUP:
-			numTriangleDiffuseLights;
-			break;
-		
-		case MST_PATCH:
-			numPatchDiffuseLights++;
-			break;
-	}
-	
-	/* create a light */
-	light = safe_malloc( sizeof( *light ) );
-	memset( light, 0, sizeof( *light ) );
-	
-	/* attach it */
-	ThreadLock();
-	light->next = lights;
-	lights = light;
-	ThreadUnlock();
-	
-	/* initialize the light */
-	light->flags = LIGHT_AREA_DEFAULT;
-	light->type = EMIT_AREA;
-	light->si = si;
-	light->fade = 1.0f;
-	light->w = w;
-	
-	/* set falloff threshold */
-	light->falloffTolerance = falloffTolerance;
-	
-	/* bouncing light? */
-	if( bouncing == qfalse )
-	{
-		/* handle first-pass lights in normal q3a style */
-		value = si->value;
-		light->photons = value * area * areaScale;
-		light->add = value * formFactorValueScale * areaScale;
-		VectorCopy( si->color, light->color );
-		VectorScale( light->color, light->add, light->emitColor );
-		light->style = si->lightStyle;
-		if( light->style < 0 || light->style >= LS_NONE )
-			light->style = 0;
-		
-		/* set origin */
-		VectorAdd( mins, maxs, light->origin );
-		VectorScale( light->origin, 0.5f, light->origin );
-		
-		/* nudge it off the plane a bit */
-		VectorCopy( normal, light->normal );
-		VectorMA( light->origin, 1.0f, light->normal, light->origin );
-		light->dist = DotProduct( light->origin, normal );
-		
-		/* optionally create a point splashsplash light for first pass */
-		if( original && si->backsplashFraction > 0 )
-		{
-			/* allocate a new point light */
-			splash = safe_malloc( sizeof( *splash ) );
-			memset( splash, 0, sizeof( *splash ) );
-			splash->next = lights;
-			lights = splash;
-			
-			/* set it up */
-			splash->flags = LIGHT_Q3A_DEFAULT;
-			splash->type = EMIT_POINT;
-			splash->photons = light->photons * si->backsplashFraction;
-			splash->fade = 1.0f;
-			splash->si = si;
-			VectorMA( light->origin, si->backsplashDistance, normal, splash->origin );
-			VectorCopy( si->color, splash->color );
-			splash->falloffTolerance = falloffTolerance;
-			splash->style = light->style;
-			
-			/* add to counts */
-			numPointLights++;
-		}
-	}
-	else
-	{
-		/* handle bounced light (radiosity) a little differently */
-		value = RADIOSITY_VALUE * si->bounceScale * 0.375f;
-		light->photons = value * area * bounceScale;
-		light->add = value * formFactorValueScale * bounceScale;
-		VectorCopy( color, light->color );
-		VectorScale( light->color, light->add, light->emitColor );
-		light->style = style;
-		if( light->style < 0 || light->style >= LS_NONE )
-			light->style = 0;
-		
-		/* set origin */
-		WindingCenter( w, light->origin );
-		
-		/* nudge it off the plane a bit */
-		VectorCopy( normal, light->normal );
-		VectorMA( light->origin, 1.0f, light->normal, light->origin );
-		light->dist = DotProduct( light->origin, normal );
-	}
-	
-	/* emit light from both sides? */
-	if( si->compileFlags & C_FOG || si->twoSided )
-		light->flags |= LIGHT_TWOSIDED;
-	
-	//%	Sys_Printf( "\nAL: C: (%6f, %6f, %6f) [%6f] N: (%6f, %6f, %6f) %s\n",
-	//%		light->color[ 0 ], light->color[ 1 ], light->color[ 2 ], light->add,
-	//%		light->normal[ 0 ], light->normal[ 1 ], light->normal[ 2 ],
-	//%		light->si->shader );
-}
-
-
-
-/*
-RadLightForTriangles()
-creates unbounced diffuse lights for triangle soup (misc_models, etc)
-*/
-
-void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw )
-{
-	int					i, j, k, v;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	float				*radVertexLuxel;
-	radWinding_t		rw;
-	
-	
-	/* get surface */
-	ds = &bspDrawSurfaces[ num ];
-	info = &surfaceInfos[ num ];
-	
-	/* each triangle is a potential emitter */
-	rw.numVerts = 3;
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		/* copy each vert */
-		for( j = 0; j < 3; j++ )
-		{
-			/* get vertex index and rad vertex luxel */
-			v = ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ];
-			
-			/* get most everything */
-			memcpy( &rw.verts[ j ], &yDrawVerts[ v ], sizeof( bspDrawVert_t ) );
-			
-			/* fix colors */
-			for( k = 0; k < MAX_LIGHTMAPS; k++ )
-			{
-				radVertexLuxel = RAD_VERTEX_LUXEL( k, ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ] );
-				VectorCopy( radVertexLuxel, rw.verts[ j ].color[ k ] );
-				rw.verts[ j ].color[ k ][ 3 ] = yDrawVerts[ v ].color[ k ][ 3 ];
-			}
-		}
-		
-		/* subdivide into area lights */
-		RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
-	}
-}
-
-
-
-/*
-RadLightForPatch()
-creates unbounced diffuse lights for patches
-*/
-
-#define	PLANAR_EPSILON	0.1f
-
-void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw )
-{
-	int					i, x, y, v, t, pw[ 5 ], r;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	bspDrawVert_t		*bogus;
-	bspDrawVert_t		*dv[ 4 ];
-	mesh_t				src, *subdivided, *mesh;
-	float				*radVertexLuxel;
-	float				dist;
-	vec4_t				plane;
-	qboolean			planar;
-	radWinding_t		rw;
-	
-	
-	/* get surface */
-	ds = &bspDrawSurfaces[ num ];
-	info = &surfaceInfos[ num ];
-	
-	/* construct a bogus vert list with color index stuffed into color[ 0 ] */
-	bogus = safe_malloc( ds->numVerts * sizeof( bspDrawVert_t ) );
-	memcpy( bogus, &yDrawVerts[ ds->firstVert ], ds->numVerts * sizeof( bspDrawVert_t ) );
-	for( i = 0; i < ds->numVerts; i++ )
-		bogus[ i ].color[ 0 ][ 0 ] = i;
-	
-	/* build a subdivided mesh identical to shadow facets for this patch */
-	/* this MUST MATCH FacetsForPatch() identically! */
-	src.width = ds->patchWidth;
-	src.height = ds->patchHeight;
-	src.verts = bogus;
-	//%	subdivided = SubdivideMesh( src, 8, 512 );
-	subdivided = SubdivideMesh2( src, info->patchIterations );
-	PutMeshOnCurve( *subdivided );
-	//%	MakeMeshNormals( *subdivided );
-	mesh = RemoveLinearMeshColumnsRows( subdivided );
-	FreeMesh( subdivided );
-	free( bogus );
-	
-	/* FIXME: build interpolation table into color[ 1 ] */
-	
-	/* fix up color indexes */
-	for( i = 0; i < (mesh->width * mesh->height); i++ )
-	{
-		dv[ 0 ] = &mesh->verts[ i ];
-		if( dv[ 0 ]->color[ 0 ][ 0 ] >= ds->numVerts )
-			dv[ 0 ]->color[ 0 ][ 0 ] = ds->numVerts - 1;
-	}
-	
-	/* iterate through the mesh quads */
-	for( y = 0; y < (mesh->height - 1); y++ )
-	{
-		for( x = 0; x < (mesh->width - 1); x++ )
-		{
-			/* set indexes */
-			pw[ 0 ] = x + (y * mesh->width);
-			pw[ 1 ] = x + ((y + 1) * mesh->width);
-			pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-			pw[ 3 ] = x + 1 + (y * mesh->width);
-			pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-			
-			/* set radix */
-			r = (x + y) & 1;
-			
-			/* get drawverts */
-			dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
-			dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
-			dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
-			dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
-			
-			/* planar? */
-			planar = PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz );
-			if( planar )
-			{
-				dist = DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ];
-				if( fabs( dist ) > PLANAR_EPSILON )
-					planar = qfalse;
-			}
-			
-			/* generate a quad */
-			if( planar )
-			{
-				rw.numVerts = 4;
-				for( v = 0; v < 4; v++ )
-				{
-					/* get most everything */
-					memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
-					
-					/* fix colors */
-					for( i = 0; i < MAX_LIGHTMAPS; i++ )
-					{
-						radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
-						VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
-						rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
-					}
-				}
-				
-				/* subdivide into area lights */
-				RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
-			}
-			
-			/* generate 2 tris */
-			else
-			{
-				rw.numVerts = 3;
-				for( t = 0; t < 2; t++ )
-				{
-					for( v = 0; v < 3 + t; v++ )
-					{
-						/* get "other" triangle (stupid hacky logic, but whatevah) */
-						if( v == 1 && t == 1 )
-							v++;
-
-						/* get most everything */
-						memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
-						
-						/* fix colors */
-						for( i = 0; i < MAX_LIGHTMAPS; i++ )
-						{
-							radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
-							VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
-							rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
-						}
-					}
-					
-					/* subdivide into area lights */
-					RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
-				}
-			}
-		}
-	}
-	
-	/* free the mesh */
-	FreeMesh( mesh );
-}
-
-
-
-
-/*
-RadLight()
-creates unbounced diffuse lights for a given surface
-*/
-
-void RadLight( int num )
-{
-	int					lightmapNum;
-	float				scale, subdivide;
-	int					contentFlags, surfaceFlags, compileFlags;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	rawLightmap_t		*lm;
-	shaderInfo_t		*si;
-	clipWork_t			cw;
-	
-	
-	/* get drawsurface, lightmap, and shader info */
-	ds = &bspDrawSurfaces[ num ];
-	info = &surfaceInfos[ num ];
-	lm = info->lm;
-	si = info->si;
-	scale = si->bounceScale;
-	
-	/* find nodraw bit */
-	contentFlags = surfaceFlags = compileFlags = 0;
-	ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, &compileFlags );
-	
-	/* early outs? */
-	if( scale <= 0.0f || (si->compileFlags & C_SKY) || si->autosprite ||
-		(bspShaders[ ds->shaderNum ].contentFlags & contentFlags) || (bspShaders[ ds->shaderNum ].surfaceFlags & surfaceFlags) ||
-		(si->compileFlags & compileFlags) )
-		return;
-	
-	/* determine how much we need to chop up the surface */
-	if( si->lightSubdivide )
-		subdivide = si->lightSubdivide;
-	else
-		subdivide = diffuseSubdivide;
-	
-	/* inc counts */
-	numDiffuseSurfaces++;
-	
-	/* iterate through styles (this could be more efficient, yes) */
-	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-	{
-		/* switch on type */
-		if( ds->lightmapStyles[ lightmapNum ] != LS_NONE && ds->lightmapStyles[ lightmapNum ] != LS_UNUSED )
-		{
-			switch( ds->surfaceType )
-			{
-				case MST_PLANAR:
-				case MST_TRIANGLE_SOUP:
-					RadLightForTriangles( num, lightmapNum, lm, si, scale, subdivide, &cw );
-					break;
-				
-				case MST_PATCH:
-					RadLightForPatch( num, lightmapNum, lm, si, scale, subdivide, &cw );
-					break;
-				
-				default:
-					break;
-			}
-		}
-	}
-}
-
-
-
-/*
-RadCreateDiffuseLights()
-creates lights for unbounced light on surfaces in the bsp
-*/
-
-int	iterations = 0;
-
-void RadCreateDiffuseLights( void )
-{
-	/* startup */
-	Sys_FPrintf( SYS_VRB, "--- RadCreateDiffuseLights ---\n" );
-	numDiffuseSurfaces = 0;
-	numDiffuseLights = 0;
-	numBrushDiffuseLights = 0;
-	numTriangleDiffuseLights = 0;
-	numPatchDiffuseLights = 0;
-	numAreaLights = 0;
-	
-	/* hit every surface (threaded) */
-	RunThreadsOnIndividual( numBSPDrawSurfaces, qtrue, RadLight );
-	
-	/* dump the lights generated to a file */
-	if( dump )
-	{
-		char	dumpName[ 1024 ], ext[ 64 ];
-		FILE	*file;
-		light_t	*light;
-		
-		strcpy( dumpName, source );
-		StripExtension( dumpName );
-		sprintf( ext, "_bounce_%03d.map", iterations );
-		strcat( dumpName, ext );
-		file = fopen( dumpName, "wb" );
-		Sys_Printf( "Writing %s...\n", dumpName );
-		if( file )
-		{
-			for( light = lights; light; light = light->next )
-			{
-				fprintf( file,
-					"{\n"
-					"\"classname\" \"light\"\n"
-					"\"light\" \"%d\"\n"
-					"\"origin\" \"%.0f %.0f %.0f\"\n"
-					"\"_color\" \"%.3f %.3f %.3f\"\n"
-					"}\n",
-					
-					(int) light->add,
-					
-					light->origin[ 0 ],
-					light->origin[ 1 ],
-					light->origin[ 2 ],
-					
-					light->color[ 0 ],
-					light->color[ 1 ],
-					light->color[ 2 ] );
-			}
-			fclose( file );
-		}
-	}
-	
-	/* increment */
-	iterations++;
-	
-	/* print counts */
-	Sys_Printf( "%8d diffuse surfaces\n", numDiffuseSurfaces );
-	Sys_FPrintf( SYS_VRB, "%8d total diffuse lights\n", numDiffuseLights );
-	Sys_FPrintf( SYS_VRB, "%8d brush diffuse lights\n", numBrushDiffuseLights );
-	Sys_FPrintf( SYS_VRB, "%8d patch diffuse lights\n", numPatchDiffuseLights );
-	Sys_FPrintf( SYS_VRB, "%8d triangle diffuse lights\n", numTriangleDiffuseLights );
-}
-
-
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define LIGHT_BOUNCE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* functions */
+
+/*
+RadFreeLights()
+deletes any existing lights, freeing up memory for the next bounce
+*/
+
+void RadFreeLights( void )
+{
+	light_t		*light, *next;
+	
+	
+	/* delete lights */
+	for( light = lights; light; light = next )
+	{
+		next = light->next;
+		if( light->w != NULL )
+			FreeWinding( light->w );
+		free( light );
+	}
+	numLights = 0;
+	lights = NULL;
+}
+
+
+
+/*
+RadClipWindingEpsilon()
+clips a rad winding by a plane
+based off the regular clip winding code
+*/
+
+static void RadClipWindingEpsilon( radWinding_t *in, vec3_t normal, vec_t dist,
+	vec_t epsilon, radWinding_t *front, radWinding_t *back, clipWork_t *cw )
+{
+	vec_t			*dists;
+	int				*sides;
+	int				counts[ 3 ];
+	vec_t			dot;		/* ydnar: changed from static b/c of threading */ /* VC 4.2 optimizer bug if not static? */
+	int				i, j, k;
+	radVert_t		*v1, *v2, mid;
+	int				maxPoints;
+	
+	
+	/* crutch */
+	dists = cw->dists;
+	sides = cw->sides;
+	
+	/* clear counts */
+	counts[ 0 ] = counts[ 1 ] = counts[ 2 ] = 0;
+
+	/* determine sides for each point */
+	for( i = 0; i < in->numVerts; i++ )
+	{
+		dot = DotProduct( in->verts[ i ].xyz, normal );
+		dot -= dist;
+		dists[ i ] = dot;
+		if( dot > epsilon )
+			sides[ i ] = SIDE_FRONT;
+		else if( dot < -epsilon )
+			sides[ i ] = SIDE_BACK;
+		else
+			sides[ i ] = SIDE_ON;
+		counts[ sides[ i ] ]++;
+	}
+	sides[ i ] = sides[ 0 ];
+	dists[ i ] = dists[ 0 ];
+	
+	/* clear front and back */
+	front->numVerts = back->numVerts = 0;
+	
+	/* handle all on one side cases */
+	if( counts[ 0 ] == 0 )
+	{
+		memcpy( back, in, sizeof( radWinding_t ) );
+		return;
+	}
+	if( counts[ 1 ] == 0 )
+	{
+		memcpy( front, in, sizeof( radWinding_t ) );
+		return;
+	}
+	
+	/* setup windings */
+	maxPoints = in->numVerts + 4;
+	
+	/* do individual verts */
+	for( i = 0; i < in->numVerts; i++ )
+	{
+		/* do simple vertex copies first */
+		v1 = &in->verts[ i ];
+		
+		if( sides[ i ] == SIDE_ON )
+		{
+			memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) );
+			memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) );
+			continue;
+		}
+	
+		if( sides[ i ] == SIDE_FRONT )
+			memcpy( &front->verts[ front->numVerts++ ], v1, sizeof( radVert_t ) );
+		
+		if( sides[ i ] == SIDE_BACK )
+			memcpy( &back->verts[ back->numVerts++ ], v1, sizeof( radVert_t ) );
+		
+		if( sides[ i + 1 ] == SIDE_ON || sides[ i + 1 ] == sides[ i ] )
+			continue;
+			
+		/* generate a split vertex */
+		v2 = &in->verts[ (i + 1) % in->numVerts ];
+		
+		dot = dists[ i ] / (dists[ i ] - dists[ i + 1 ]);
+
+		/* average vertex values */
+		for( j = 0; j < 4; j++ )
+		{
+			/* color */
+			if( j < 4 )
+			{
+				for( k = 0; k < MAX_LIGHTMAPS; k++ )
+					mid.color[ k ][ j ] = v1->color[ k ][ j ] + dot * (v2->color[ k ][ j ] - v1->color[ k ][ j ]);
+			}
+			
+			/* xyz, normal */
+			if( j < 3 )
+			{
+				mid.xyz[ j ] = v1->xyz[ j ] + dot * (v2->xyz[ j ] - v1->xyz[ j ]);
+				mid.normal[ j ] = v1->normal[ j ] + dot * (v2->normal[ j ] - v1->normal[ j ]);
+			}
+			
+			/* st, lightmap */
+			if( j < 2 )
+			{
+				mid.st[ j ] = v1->st[ j ] + dot * (v2->st[ j ] - v1->st[ j ]);
+				for( k = 0; k < MAX_LIGHTMAPS; k++ )
+					mid.lightmap[ k ][ j ] = v1->lightmap[ k ][ j ] + dot * (v2->lightmap[ k ][ j ] - v1->lightmap[ k ][ j ]);
+			}
+		}
+		
+		/* normalize the averaged normal */
+		VectorNormalize( mid.normal, mid.normal );
+
+		/* copy the midpoint to both windings */
+		memcpy( &front->verts[ front->numVerts++ ], &mid, sizeof( radVert_t ) );
+		memcpy( &back->verts[ back->numVerts++ ], &mid, sizeof( radVert_t ) );
+	}
+	
+	/* error check */
+	if( front->numVerts > maxPoints || front->numVerts > maxPoints )
+		Error( "RadClipWindingEpsilon: points exceeded estimate" );
+	if( front->numVerts > MAX_POINTS_ON_WINDING || front->numVerts > MAX_POINTS_ON_WINDING )
+		Error( "RadClipWindingEpsilon: MAX_POINTS_ON_WINDING" );
+}
+
+
+
+
+
+/*
+RadSampleImage()
+samples a texture image for a given color
+returns qfalse if pixels are bad
+*/
+
+qboolean RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] )
+{
+	float	sto[ 2 ];
+	int		x, y;
+	
+	
+	/* clear color first */
+	color[ 0 ] = color[ 1 ] = color[ 2 ] = color[ 3 ] = 255;
+	
+	/* dummy check */
+	if( pixels == NULL || width < 1 || height < 1 )
+		return qfalse;
+	
+	/* bias st */
+	sto[ 0 ] = st[ 0 ];
+	while( sto[ 0 ] < 0.0f )
+		sto[ 0 ] += 1.0f;
+	sto[ 1 ] = st[ 1 ];
+	while( sto[ 1 ] < 0.0f )
+		sto[ 1 ] += 1.0f;
+
+	/* get offsets */
+	x = ((float) width * sto[ 0 ]) + 0.5f;
+	x %= width;
+	y = ((float) height * sto[ 1 ])  + 0.5f;
+	y %= height;
+	
+	/* get pixel */
+	pixels += (y * width * 4) + (x * 4);
+	VectorCopy( pixels, color );
+	color[ 3 ] = pixels[ 3 ];
+	return qtrue;
+}
+
+
+
+/*
+RadSample()
+samples a fragment's lightmap or vertex color and returns an
+average color and a color gradient for the sample
+*/
+
+#define MAX_SAMPLES			150
+#define SAMPLE_GRANULARITY	6
+
+static void RadSample( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si, radWinding_t *rw, vec3_t average, vec3_t gradient, int *style )
+{
+	int			i, j, k, l, v, x, y, samples;
+	vec3_t		color, mins, maxs;
+	vec4_t		textureColor;
+	float		alpha, alphaI, bf;
+	vec3_t		blend;
+	float		st[ 2 ], lightmap[ 2 ], *radLuxel;
+	radVert_t	*rv[ 3 ];
+	
+	
+	/* initial setup */
+	ClearBounds( mins, maxs );
+	VectorClear( average );
+	VectorClear( gradient );
+	alpha = 0;
+	
+	/* dummy check */
+	if( rw == NULL || rw->numVerts < 3 )
+		return;
+	
+	/* start sampling */
+	samples = 0;
+	
+	/* sample vertex colors if no lightmap or this is the initial pass */
+	if( lm == NULL || lm->radLuxels[ lightmapNum ] == NULL || bouncing == qfalse )
+	{
+		for( samples = 0; samples < rw->numVerts; samples++ )
+		{
+			/* multiply by texture color */
+			if( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, rw->verts[ samples ].st, textureColor ) )
+			{
+				VectorCopy( si->averageColor, textureColor );
+				textureColor[ 4 ] = 255.0f;
+			}
+			for( i = 0; i < 3; i++ )
+				color[ i ] = (textureColor[ i ] / 255) * (rw->verts[ samples ].color[ lightmapNum ][ i ] / 255.0f);
+			
+			AddPointToBounds( color, mins, maxs );
+			VectorAdd( average, color, average );
+			
+			/* get alpha */
+			alpha += (textureColor[ 3 ] / 255.0f) * (rw->verts[ samples ].color[ lightmapNum ][ 3 ] / 255.0f);
+		}
+		
+		/* set style */
+		*style = ds->vertexStyles[ lightmapNum ];
+	}
+	
+	/* sample lightmap */
+	else
+	{
+		/* fracture the winding into a fan (including degenerate tris) */
+		for( v = 1; v < (rw->numVerts - 1) && samples < MAX_SAMPLES; v++ )
+		{
+			/* get a triangle */
+			rv[ 0 ] = &rw->verts[ 0 ];
+			rv[ 1 ] = &rw->verts[ v ];
+			rv[ 2 ] = &rw->verts[ v + 1 ];
+			
+			/* this code is embarassing (really should just rasterize the triangle) */
+			for( i = 1; i < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; i++ )
+			{
+				for( j = 1; j < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; j++ )
+				{
+					for( k = 1; k < SAMPLE_GRANULARITY && samples < MAX_SAMPLES; k++ )
+					{
+						/* create a blend vector (barycentric coordinates) */
+						blend[ 0 ] = i;
+						blend[ 1 ] = j;
+						blend[ 2 ] = k;
+						bf = (1.0 / (blend[ 0 ] + blend[ 1 ] + blend[ 2 ]));
+						VectorScale( blend, bf, blend );
+						
+						/* create a blended sample */
+						st[ 0 ] = st[ 1 ] = 0.0f;
+						lightmap[ 0 ] = lightmap[ 1 ] = 0.0f;
+						alphaI = 0.0f;
+						for( l = 0; l < 3; l++ )
+						{
+							st[ 0 ] += (rv[ l ]->st[ 0 ] * blend[ l ]);
+							st[ 1 ] += (rv[ l ]->st[ 1 ] * blend[ l ]);
+							lightmap[ 0 ] += (rv[ l ]->lightmap[ lightmapNum ][ 0 ] * blend[ l ]);
+							lightmap[ 1 ] += (rv[ l ]->lightmap[ lightmapNum ][ 1 ] * blend[ l ]);
+							alphaI += (rv[ l ]->color[ lightmapNum ][ 3 ] * blend[ l ]);
+						}
+						
+						/* get lightmap xy coords */
+						x = lightmap[ 0 ] / (float) superSample;
+						y = lightmap[ 1 ] / (float) superSample;
+						if( x < 0 )
+							x = 0;
+						else if ( x >= lm->w )
+							x = lm->w - 1;
+						if( y < 0 )
+							y = 0;
+						else if ( y >= lm->h )
+							y = lm->h - 1;
+						
+						/* get radiosity luxel */
+						radLuxel = RAD_LUXEL( lightmapNum, x, y );
+						
+						/* ignore unlit/unused luxels */
+						if( radLuxel[ 0 ] < 0.0f )
+							continue;
+						
+						/* inc samples */
+						samples++;
+						
+						/* multiply by texture color */
+						if( !RadSampleImage( si->lightImage->pixels, si->lightImage->width, si->lightImage->height, st, textureColor ) )
+						{
+							VectorCopy( si->averageColor, textureColor );
+							textureColor[ 4 ] = 255;
+						}
+						for( i = 0; i < 3; i++ )
+							color[ i ] = (textureColor[ i ] / 255) * (radLuxel[ i ] / 255);
+						
+						AddPointToBounds( color, mins, maxs );
+						VectorAdd( average, color, average );
+						
+						/* get alpha */
+						alpha += (textureColor[ 3 ] / 255) * (alphaI / 255);
+					}
+				}
+			}
+		}
+		
+		/* set style */
+		*style = ds->lightmapStyles[ lightmapNum ];
+	}
+	
+	/* any samples? */
+	if( samples <= 0 )
+		return;
+	
+	/* average the color */
+	VectorScale( average, (1.0 / samples), average );
+	
+	/* create the color gradient */
+	//%	VectorSubtract( maxs, mins, delta );
+	
+	/* new: color gradient will always be 0-1.0, expressed as the range of light relative to overall light */
+	//%	gradient[ 0 ] = maxs[ 0 ] > 0.0f ? (maxs[ 0 ] - mins[ 0 ]) / maxs[ 0 ] : 0.0f;
+	//%	gradient[ 1 ] = maxs[ 1 ] > 0.0f ? (maxs[ 1 ] - mins[ 1 ]) / maxs[ 1 ] : 0.0f;
+	//%	gradient[ 2 ] = maxs[ 2 ] > 0.0f ? (maxs[ 2 ] - mins[ 2 ]) / maxs[ 2 ] : 0.0f;
+	
+	/* newer: another contrast function */
+	for( i = 0; i < 3; i++ )
+		gradient[ i ] = (maxs[ i ] - mins[ i ]) * maxs[ i ];
+}
+
+
+
+/*
+RadSubdivideDiffuseLight()
+subdivides a radiosity winding until it is smaller than subdivide, then generates an area light
+*/
+
+#define RADIOSITY_MAX_GRADIENT		0.75f	//%	0.25f
+#define RADIOSITY_VALUE				500.0f
+#define RADIOSITY_MIN				0.0001f
+#define RADIOSITY_CLIP_EPSILON		0.125f
+
+static void RadSubdivideDiffuseLight( int lightmapNum, bspDrawSurface_t *ds, rawLightmap_t *lm, shaderInfo_t *si,
+	float scale, float subdivide, qboolean original, radWinding_t *rw, clipWork_t *cw )
+{
+	int				i, style;
+	float			dist, area, value;
+	vec3_t			mins, maxs, normal, d1, d2, cross, color, gradient;
+	light_t			*light, *splash;
+	winding_t		*w;
+	
+	
+	/* dummy check */
+	if( rw == NULL || rw->numVerts < 3 )
+		return;
+	
+	/* get bounds for winding */
+	ClearBounds( mins, maxs );
+	for( i = 0; i < rw->numVerts; i++ )
+		AddPointToBounds( rw->verts[ i ].xyz, mins, maxs );
+	
+	/* subdivide if necessary */
+	for( i = 0; i < 3; i++ )
+	{
+		if( maxs[ i ] - mins[ i ] > subdivide )
+		{
+			radWinding_t	front, back;
+			
+			
+			/* make axial plane */
+			VectorClear( normal );
+			normal[ i ] = 1;
+			dist = (maxs[ i ] + mins[ i ]) * 0.5f;
+			
+			/* clip the winding */
+			RadClipWindingEpsilon( rw, normal, dist, RADIOSITY_CLIP_EPSILON, &front, &back, cw );
+			
+			/* recurse */
+			RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &front, cw );
+			RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qfalse, &back, cw );
+			return;
+		}
+	}
+	
+	/* check area */
+	area = 0.0f;
+	for( i = 2; i < rw->numVerts; i++ )
+	{
+		VectorSubtract( rw->verts[ i - 1 ].xyz, rw->verts[ 0 ].xyz, d1 );
+		VectorSubtract( rw->verts[ i ].xyz, rw->verts[ 0 ].xyz, d2 );
+		CrossProduct( d1, d2, cross );
+		area += 0.5f * VectorLength( cross );
+	}
+	if( area < 1.0f || area > 20000000.0f )
+		return;
+	
+	/* more subdivision may be necessary */
+	if( bouncing )
+	{
+		/* get color sample for the surface fragment */
+		RadSample( lightmapNum, ds, lm, si, rw, color, gradient, &style );
+		
+		/* if color gradient is too high, subdivide again */
+		if( subdivide > minDiffuseSubdivide && 
+			(gradient[ 0 ] > RADIOSITY_MAX_GRADIENT || gradient[ 1 ] > RADIOSITY_MAX_GRADIENT || gradient[ 2 ] > RADIOSITY_MAX_GRADIENT) )
+		{
+			RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, (subdivide / 2.0f), qfalse, rw, cw );
+			return;
+		}
+	}
+	
+	/* create a regular winding and an average normal */
+	w = AllocWinding( rw->numVerts );
+	w->numpoints = rw->numVerts;
+	VectorClear( normal );
+	for( i = 0; i < rw->numVerts; i++ )
+	{
+		VectorCopy( rw->verts[ i ].xyz, w->p[ i ] );
+		VectorAdd( normal, rw->verts[ i ].normal, normal );
+	}
+	VectorScale( normal, (1.0f / rw->numVerts), normal );
+	if( VectorNormalize( normal, normal ) == 0.0f )
+		return;
+	
+	/* early out? */
+	if( bouncing && VectorLength( color ) < RADIOSITY_MIN )
+		return;
+	
+	/* debug code */
+	//%	Sys_Printf( "Size: %d %d %d\n", (int) (maxs[ 0 ] - mins[ 0 ]), (int) (maxs[ 1 ] - mins[ 1 ]), (int) (maxs[ 2 ] - mins[ 2 ]) );
+	//%	Sys_Printf( "Grad: %f %f %f\n", gradient[ 0 ], gradient[ 1 ], gradient[ 2 ] );
+	
+	/* increment counts */
+	numDiffuseLights++;
+	switch( ds->surfaceType )
+	{
+		case MST_PLANAR:
+			numBrushDiffuseLights++;
+			break;
+		
+		case MST_TRIANGLE_SOUP:
+			numTriangleDiffuseLights;
+			break;
+		
+		case MST_PATCH:
+			numPatchDiffuseLights++;
+			break;
+	}
+	
+	/* create a light */
+	light = safe_malloc( sizeof( *light ) );
+	memset( light, 0, sizeof( *light ) );
+	
+	/* attach it */
+	ThreadLock();
+	light->next = lights;
+	lights = light;
+	ThreadUnlock();
+	
+	/* initialize the light */
+	light->flags = LIGHT_AREA_DEFAULT;
+	light->type = EMIT_AREA;
+	light->si = si;
+	light->fade = 1.0f;
+	light->w = w;
+	
+	/* set falloff threshold */
+	light->falloffTolerance = falloffTolerance;
+	
+	/* bouncing light? */
+	if( bouncing == qfalse )
+	{
+		/* handle first-pass lights in normal q3a style */
+		value = si->value;
+		light->photons = value * area * areaScale;
+		light->add = value * formFactorValueScale * areaScale;
+		VectorCopy( si->color, light->color );
+		VectorScale( light->color, light->add, light->emitColor );
+		light->style = si->lightStyle;
+		if( light->style < 0 || light->style >= LS_NONE )
+			light->style = 0;
+		
+		/* set origin */
+		VectorAdd( mins, maxs, light->origin );
+		VectorScale( light->origin, 0.5f, light->origin );
+		
+		/* nudge it off the plane a bit */
+		VectorCopy( normal, light->normal );
+		VectorMA( light->origin, 1.0f, light->normal, light->origin );
+		light->dist = DotProduct( light->origin, normal );
+		
+		/* optionally create a point splashsplash light for first pass */
+		if( original && si->backsplashFraction > 0 )
+		{
+			/* allocate a new point light */
+			splash = safe_malloc( sizeof( *splash ) );
+			memset( splash, 0, sizeof( *splash ) );
+			splash->next = lights;
+			lights = splash;
+			
+			/* set it up */
+			splash->flags = LIGHT_Q3A_DEFAULT;
+			splash->type = EMIT_POINT;
+			splash->photons = light->photons * si->backsplashFraction;
+			splash->fade = 1.0f;
+			splash->si = si;
+			VectorMA( light->origin, si->backsplashDistance, normal, splash->origin );
+			VectorCopy( si->color, splash->color );
+			splash->falloffTolerance = falloffTolerance;
+			splash->style = light->style;
+			
+			/* add to counts */
+			numPointLights++;
+		}
+	}
+	else
+	{
+		/* handle bounced light (radiosity) a little differently */
+		value = RADIOSITY_VALUE * si->bounceScale * 0.375f;
+		light->photons = value * area * bounceScale;
+		light->add = value * formFactorValueScale * bounceScale;
+		VectorCopy( color, light->color );
+		VectorScale( light->color, light->add, light->emitColor );
+		light->style = style;
+		if( light->style < 0 || light->style >= LS_NONE )
+			light->style = 0;
+		
+		/* set origin */
+		WindingCenter( w, light->origin );
+		
+		/* nudge it off the plane a bit */
+		VectorCopy( normal, light->normal );
+		VectorMA( light->origin, 1.0f, light->normal, light->origin );
+		light->dist = DotProduct( light->origin, normal );
+	}
+	
+	/* emit light from both sides? */
+	if( si->compileFlags & C_FOG || si->twoSided )
+		light->flags |= LIGHT_TWOSIDED;
+	
+	//%	Sys_Printf( "\nAL: C: (%6f, %6f, %6f) [%6f] N: (%6f, %6f, %6f) %s\n",
+	//%		light->color[ 0 ], light->color[ 1 ], light->color[ 2 ], light->add,
+	//%		light->normal[ 0 ], light->normal[ 1 ], light->normal[ 2 ],
+	//%		light->si->shader );
+}
+
+
+
+/*
+RadLightForTriangles()
+creates unbounced diffuse lights for triangle soup (misc_models, etc)
+*/
+
+void RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw )
+{
+	int					i, j, k, v;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	float				*radVertexLuxel;
+	radWinding_t		rw;
+	
+	
+	/* get surface */
+	ds = &bspDrawSurfaces[ num ];
+	info = &surfaceInfos[ num ];
+	
+	/* each triangle is a potential emitter */
+	rw.numVerts = 3;
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		/* copy each vert */
+		for( j = 0; j < 3; j++ )
+		{
+			/* get vertex index and rad vertex luxel */
+			v = ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ];
+			
+			/* get most everything */
+			memcpy( &rw.verts[ j ], &yDrawVerts[ v ], sizeof( bspDrawVert_t ) );
+			
+			/* fix colors */
+			for( k = 0; k < MAX_LIGHTMAPS; k++ )
+			{
+				radVertexLuxel = RAD_VERTEX_LUXEL( k, ds->firstVert + bspDrawIndexes[ ds->firstIndex + i + j ] );
+				VectorCopy( radVertexLuxel, rw.verts[ j ].color[ k ] );
+				rw.verts[ j ].color[ k ][ 3 ] = yDrawVerts[ v ].color[ k ][ 3 ];
+			}
+		}
+		
+		/* subdivide into area lights */
+		RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
+	}
+}
+
+
+
+/*
+RadLightForPatch()
+creates unbounced diffuse lights for patches
+*/
+
+#define	PLANAR_EPSILON	0.1f
+
+void RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw )
+{
+	int					i, x, y, v, t, pw[ 5 ], r;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	bspDrawVert_t		*bogus;
+	bspDrawVert_t		*dv[ 4 ];
+	mesh_t				src, *subdivided, *mesh;
+	float				*radVertexLuxel;
+	float				dist;
+	vec4_t				plane;
+	qboolean			planar;
+	radWinding_t		rw;
+	
+	
+	/* get surface */
+	ds = &bspDrawSurfaces[ num ];
+	info = &surfaceInfos[ num ];
+	
+	/* construct a bogus vert list with color index stuffed into color[ 0 ] */
+	bogus = safe_malloc( ds->numVerts * sizeof( bspDrawVert_t ) );
+	memcpy( bogus, &yDrawVerts[ ds->firstVert ], ds->numVerts * sizeof( bspDrawVert_t ) );
+	for( i = 0; i < ds->numVerts; i++ )
+		bogus[ i ].color[ 0 ][ 0 ] = i;
+	
+	/* build a subdivided mesh identical to shadow facets for this patch */
+	/* this MUST MATCH FacetsForPatch() identically! */
+	src.width = ds->patchWidth;
+	src.height = ds->patchHeight;
+	src.verts = bogus;
+	//%	subdivided = SubdivideMesh( src, 8, 512 );
+	subdivided = SubdivideMesh2( src, info->patchIterations );
+	PutMeshOnCurve( *subdivided );
+	//%	MakeMeshNormals( *subdivided );
+	mesh = RemoveLinearMeshColumnsRows( subdivided );
+	FreeMesh( subdivided );
+	free( bogus );
+	
+	/* FIXME: build interpolation table into color[ 1 ] */
+	
+	/* fix up color indexes */
+	for( i = 0; i < (mesh->width * mesh->height); i++ )
+	{
+		dv[ 0 ] = &mesh->verts[ i ];
+		if( dv[ 0 ]->color[ 0 ][ 0 ] >= ds->numVerts )
+			dv[ 0 ]->color[ 0 ][ 0 ] = ds->numVerts - 1;
+	}
+	
+	/* iterate through the mesh quads */
+	for( y = 0; y < (mesh->height - 1); y++ )
+	{
+		for( x = 0; x < (mesh->width - 1); x++ )
+		{
+			/* set indexes */
+			pw[ 0 ] = x + (y * mesh->width);
+			pw[ 1 ] = x + ((y + 1) * mesh->width);
+			pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+			pw[ 3 ] = x + 1 + (y * mesh->width);
+			pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+			
+			/* set radix */
+			r = (x + y) & 1;
+			
+			/* get drawverts */
+			dv[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
+			dv[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
+			dv[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
+			dv[ 3 ] = &mesh->verts[ pw[ r + 3 ] ];
+			
+			/* planar? */
+			planar = PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz );
+			if( planar )
+			{
+				dist = DotProduct( dv[ 1 ]->xyz, plane ) - plane[ 3 ];
+				if( fabs( dist ) > PLANAR_EPSILON )
+					planar = qfalse;
+			}
+			
+			/* generate a quad */
+			if( planar )
+			{
+				rw.numVerts = 4;
+				for( v = 0; v < 4; v++ )
+				{
+					/* get most everything */
+					memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
+					
+					/* fix colors */
+					for( i = 0; i < MAX_LIGHTMAPS; i++ )
+					{
+						radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
+						VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
+						rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
+					}
+				}
+				
+				/* subdivide into area lights */
+				RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
+			}
+			
+			/* generate 2 tris */
+			else
+			{
+				rw.numVerts = 3;
+				for( t = 0; t < 2; t++ )
+				{
+					for( v = 0; v < 3 + t; v++ )
+					{
+						/* get "other" triangle (stupid hacky logic, but whatevah) */
+						if( v == 1 && t == 1 )
+							v++;
+
+						/* get most everything */
+						memcpy( &rw.verts[ v ], dv[ v ], sizeof( bspDrawVert_t ) );
+						
+						/* fix colors */
+						for( i = 0; i < MAX_LIGHTMAPS; i++ )
+						{
+							radVertexLuxel = RAD_VERTEX_LUXEL( i, ds->firstVert + dv[ v ]->color[ 0 ][ 0 ] );
+							VectorCopy( radVertexLuxel, rw.verts[ v ].color[ i ] );
+							rw.verts[ v ].color[ i ][ 3 ] = dv[ v ]->color[ i ][ 3 ];
+						}
+					}
+					
+					/* subdivide into area lights */
+					RadSubdivideDiffuseLight( lightmapNum, ds, lm, si, scale, subdivide, qtrue, &rw, cw );
+				}
+			}
+		}
+	}
+	
+	/* free the mesh */
+	FreeMesh( mesh );
+}
+
+
+
+
+/*
+RadLight()
+creates unbounced diffuse lights for a given surface
+*/
+
+void RadLight( int num )
+{
+	int					lightmapNum;
+	float				scale, subdivide;
+	int					contentFlags, surfaceFlags, compileFlags;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	rawLightmap_t		*lm;
+	shaderInfo_t		*si;
+	clipWork_t			cw;
+	
+	
+	/* get drawsurface, lightmap, and shader info */
+	ds = &bspDrawSurfaces[ num ];
+	info = &surfaceInfos[ num ];
+	lm = info->lm;
+	si = info->si;
+	scale = si->bounceScale;
+	
+	/* find nodraw bit */
+	contentFlags = surfaceFlags = compileFlags = 0;
+	ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, &compileFlags );
+	
+	/* early outs? */
+	if( scale <= 0.0f || (si->compileFlags & C_SKY) || si->autosprite ||
+		(bspShaders[ ds->shaderNum ].contentFlags & contentFlags) || (bspShaders[ ds->shaderNum ].surfaceFlags & surfaceFlags) ||
+		(si->compileFlags & compileFlags) )
+		return;
+	
+	/* determine how much we need to chop up the surface */
+	if( si->lightSubdivide )
+		subdivide = si->lightSubdivide;
+	else
+		subdivide = diffuseSubdivide;
+	
+	/* inc counts */
+	numDiffuseSurfaces++;
+	
+	/* iterate through styles (this could be more efficient, yes) */
+	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+	{
+		/* switch on type */
+		if( ds->lightmapStyles[ lightmapNum ] != LS_NONE && ds->lightmapStyles[ lightmapNum ] != LS_UNUSED )
+		{
+			switch( ds->surfaceType )
+			{
+				case MST_PLANAR:
+				case MST_TRIANGLE_SOUP:
+					RadLightForTriangles( num, lightmapNum, lm, si, scale, subdivide, &cw );
+					break;
+				
+				case MST_PATCH:
+					RadLightForPatch( num, lightmapNum, lm, si, scale, subdivide, &cw );
+					break;
+				
+				default:
+					break;
+			}
+		}
+	}
+}
+
+
+
+/*
+RadCreateDiffuseLights()
+creates lights for unbounced light on surfaces in the bsp
+*/
+
+int	iterations = 0;
+
+void RadCreateDiffuseLights( void )
+{
+	/* startup */
+	Sys_FPrintf( SYS_VRB, "--- RadCreateDiffuseLights ---\n" );
+	numDiffuseSurfaces = 0;
+	numDiffuseLights = 0;
+	numBrushDiffuseLights = 0;
+	numTriangleDiffuseLights = 0;
+	numPatchDiffuseLights = 0;
+	numAreaLights = 0;
+	
+	/* hit every surface (threaded) */
+	RunThreadsOnIndividual( numBSPDrawSurfaces, qtrue, RadLight );
+	
+	/* dump the lights generated to a file */
+	if( dump )
+	{
+		char	dumpName[ 1024 ], ext[ 64 ];
+		FILE	*file;
+		light_t	*light;
+		
+		strcpy( dumpName, source );
+		StripExtension( dumpName );
+		sprintf( ext, "_bounce_%03d.map", iterations );
+		strcat( dumpName, ext );
+		file = fopen( dumpName, "wb" );
+		Sys_Printf( "Writing %s...\n", dumpName );
+		if( file )
+		{
+			for( light = lights; light; light = light->next )
+			{
+				fprintf( file,
+					"{\n"
+					"\"classname\" \"light\"\n"
+					"\"light\" \"%d\"\n"
+					"\"origin\" \"%.0f %.0f %.0f\"\n"
+					"\"_color\" \"%.3f %.3f %.3f\"\n"
+					"}\n",
+					
+					(int) light->add,
+					
+					light->origin[ 0 ],
+					light->origin[ 1 ],
+					light->origin[ 2 ],
+					
+					light->color[ 0 ],
+					light->color[ 1 ],
+					light->color[ 2 ] );
+			}
+			fclose( file );
+		}
+	}
+	
+	/* increment */
+	iterations++;
+	
+	/* print counts */
+	Sys_Printf( "%8d diffuse surfaces\n", numDiffuseSurfaces );
+	Sys_FPrintf( SYS_VRB, "%8d total diffuse lights\n", numDiffuseLights );
+	Sys_FPrintf( SYS_VRB, "%8d brush diffuse lights\n", numBrushDiffuseLights );
+	Sys_FPrintf( SYS_VRB, "%8d patch diffuse lights\n", numPatchDiffuseLights );
+	Sys_FPrintf( SYS_VRB, "%8d triangle diffuse lights\n", numTriangleDiffuseLights );
+}
+
+
+
+
+
diff --git a/tools/quake3/q3map2/light_shadows.c b/tools/quake3/q3map2/light_shadows.c
index 14a18d95..df7cdd82 100644
--- a/tools/quake3/q3map2/light_shadows.c
+++ b/tools/quake3/q3map2/light_shadows.c
@@ -1,124 +1,124 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#define LIGHT_SHADOWS_C
-
-#include "light.h"
-#include "inout.h"
-
-
-
-/* -------------------------------------------------------------------------------
-
-ydnar: this code deals with shadow volume bsps
-
-------------------------------------------------------------------------------- */
-
-typedef struct shadowNode_s
-{
-	vec4_t	plane;
-	int		children[ 2 ];
-}
-shadowNode_t;
-
-int				numShadowNodes;
-shadowNode_t	*shadowNodes;
-
-
-
-/*
-AddShadow()
-adds a shadow, returning the index into the shadow list
-*/
-
-
-
-/*
-MakeShadowFromPoints()
-creates a shadow volume from 4 points (the first being the light origin)
-*/
-
-
-
-/*
-SetupShadows()
-sets up the shadow volumes for all lights in the world
-*/
-
-void SetupShadows( void )
-{
-	int				i, j, s;
-	light_t			*light;
-	dleaf_t			*leaf;
-	dsurface_t		*ds;
-	surfaceInfo_t	*info;
-	shaderInfo_t	*si;
-	byte			*tested;
-
-	
-	/* early out for weird cases where there are no lights */
-	if( lights == NULL )
-		return;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- SetupShadows ---\n" );
-	
-	/* allocate a surface test list */
-	tested = safe_malloc( numDrawSurfaces / 8 + 1 );
-	
-	/* walk the list of lights */
-	for( light = lights; light != NULL; light = light->next )
-	{
-		/* do some early out testing */
-		if( light->cluster < 0 )
-			continue;
-		
-		/* clear surfacetest list */
-		memset( tested, 0, numDrawSurfaces / 8 + 1 );
-		
-		/* walk the bsp leaves */
-		for( i = 0, leaf = dleafs; i < numleafs; i++, leaf++ )
-		{
-			/* in pvs? */
-			if( ClusterVisible( light->cluster, leaf->cluster ) == qfalse )
-				continue;
-			
-			/* walk the surface list for this leaf */
-			for( j = 0; j < leaf->numLeafSurfaces; j++ )
-			{
-				/* don't filter a surface more than once */
-				s = dleafsurfaces[ leaf->firstLeafSurface + j ];
-				if( tested[ s >> 3 ] & (1 << (s & 7)) )
-					continue;
-				tested[ s >> 3 ] |= (1 << (s & 7));
-				
-				/* get surface and info */
-				ds = &drawSurfaces[ s ];
-				info = &surfaceInfos[ s ];
-				si = info->si;
-				
-				/* don't create shadow volumes from translucent surfaces */
-				if( si->contents & CONTENTS_TRANSLUCENT )
-					continue;
-			}
-		}
-	}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#define LIGHT_SHADOWS_C
+
+#include "light.h"
+#include "inout.h"
+
+
+
+/* -------------------------------------------------------------------------------
+
+ydnar: this code deals with shadow volume bsps
+
+------------------------------------------------------------------------------- */
+
+typedef struct shadowNode_s
+{
+	vec4_t	plane;
+	int		children[ 2 ];
+}
+shadowNode_t;
+
+int				numShadowNodes;
+shadowNode_t	*shadowNodes;
+
+
+
+/*
+AddShadow()
+adds a shadow, returning the index into the shadow list
+*/
+
+
+
+/*
+MakeShadowFromPoints()
+creates a shadow volume from 4 points (the first being the light origin)
+*/
+
+
+
+/*
+SetupShadows()
+sets up the shadow volumes for all lights in the world
+*/
+
+void SetupShadows( void )
+{
+	int				i, j, s;
+	light_t			*light;
+	dleaf_t			*leaf;
+	dsurface_t		*ds;
+	surfaceInfo_t	*info;
+	shaderInfo_t	*si;
+	byte			*tested;
+
+	
+	/* early out for weird cases where there are no lights */
+	if( lights == NULL )
+		return;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- SetupShadows ---\n" );
+	
+	/* allocate a surface test list */
+	tested = safe_malloc( numDrawSurfaces / 8 + 1 );
+	
+	/* walk the list of lights */
+	for( light = lights; light != NULL; light = light->next )
+	{
+		/* do some early out testing */
+		if( light->cluster < 0 )
+			continue;
+		
+		/* clear surfacetest list */
+		memset( tested, 0, numDrawSurfaces / 8 + 1 );
+		
+		/* walk the bsp leaves */
+		for( i = 0, leaf = dleafs; i < numleafs; i++, leaf++ )
+		{
+			/* in pvs? */
+			if( ClusterVisible( light->cluster, leaf->cluster ) == qfalse )
+				continue;
+			
+			/* walk the surface list for this leaf */
+			for( j = 0; j < leaf->numLeafSurfaces; j++ )
+			{
+				/* don't filter a surface more than once */
+				s = dleafsurfaces[ leaf->firstLeafSurface + j ];
+				if( tested[ s >> 3 ] & (1 << (s & 7)) )
+					continue;
+				tested[ s >> 3 ] |= (1 << (s & 7));
+				
+				/* get surface and info */
+				ds = &drawSurfaces[ s ];
+				info = &surfaceInfos[ s ];
+				si = info->si;
+				
+				/* don't create shadow volumes from translucent surfaces */
+				if( si->contents & CONTENTS_TRANSLUCENT )
+					continue;
+			}
+		}
+	}
 }
\ No newline at end of file
diff --git a/tools/quake3/q3map2/light_trace.c b/tools/quake3/q3map2/light_trace.c
index 91fc25ec..287b22dd 100644
--- a/tools/quake3/q3map2/light_trace.c
+++ b/tools/quake3/q3map2/light_trace.c
@@ -1,1754 +1,1754 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define LIGHT_TRACE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-#define Vector2Copy( a, b )		((b)[ 0 ] = (a)[ 0 ], (b)[ 1 ] = (a)[ 1 ])
-#define Vector4Copy( a, b )		((b)[ 0 ] = (a)[ 0 ], (b)[ 1 ] = (a)[ 1 ], (b)[ 2 ] = (a)[ 2 ], (b)[ 3 ] = (a)[ 3 ])
-
-#define MAX_NODE_ITEMS			5
-#define MAX_NODE_TRIANGLES		5
-#define MAX_TRACE_DEPTH			32
-#define MIN_NODE_SIZE			32.0f
-
-#define GROW_TRACE_INFOS		32768		//%	4096
-#define GROW_TRACE_WINDINGS		65536		//%	32768
-#define GROW_TRACE_TRIANGLES	131072		//%	32768
-#define GROW_TRACE_NODES		16384		//%	16384
-#define GROW_NODE_ITEMS			16			//%	256
-
-#define MAX_TW_VERTS			12
-
-#define	TRACE_ON_EPSILON		0.1f
-
-#define TRACE_LEAF				-1
-#define TRACE_LEAF_SOLID		-2
-
-typedef struct traceVert_s
-{
-	vec3_t						xyz;
-	float						st[ 2 ];
-}
-traceVert_t;
-
-typedef struct traceInfo_s
-{
-	shaderInfo_t				*si;
-	int							surfaceNum, castShadows, padding;
-}
-traceInfo_t;
-
-typedef struct traceWinding_s
-{
-	vec4_t						plane;
-	int							infoNum, numVerts;
-	traceVert_t					v[ MAX_TW_VERTS ];
-}
-traceWinding_t;
-
-typedef struct traceTriangle_s
-{
-	vec3_t						edge1, edge2;
-	int							infoNum, padding;
-	traceVert_t					v[ 3 ];
-}
-traceTriangle_t;
-
-typedef struct traceNode_s
-{
-	int							type;
-	vec4_t						plane;
-	vec3_t						mins, maxs;
-	int							children[ 2 ];
-	int							numItems, maxItems;
-	int							*items;
-}
-traceNode_t;
-
-
-int								noDrawContentFlags, noDrawSurfaceFlags, noDrawCompileFlags;
-
-int								numTraceInfos = 0, maxTraceInfos = 0, firstTraceInfo = 0;
-traceInfo_t						*traceInfos = NULL;
-
-int								numTraceWindings = 0, maxTraceWindings = 0, deadWinding = -1;
-traceWinding_t					*traceWindings = NULL;
-
-int								numTraceTriangles = 0, maxTraceTriangles = 0, deadTriangle = -1;
-traceTriangle_t					*traceTriangles = NULL;
-
-int								headNodeNum = 0, skyboxNodeNum = 0, maxTraceDepth = 0, numTraceLeafNodes = 0;
-int								numTraceNodes = 0, maxTraceNodes = 0;
-traceNode_t						*traceNodes = NULL;
-
-
-
-/* -------------------------------------------------------------------------------
-
-allocation and list management
-
-------------------------------------------------------------------------------- */
-
-/*
-AddTraceInfo() - ydnar
-adds a trace info structure to the pool
-*/
-
-static int AddTraceInfo( traceInfo_t *ti )
-{
-	int		num;
-	void	*temp;
-	
-	
-	/* find an existing info */
-	for( num = firstTraceInfo; num < numTraceInfos; num++ )
-	{
-		if( traceInfos[ num ].si == ti->si &&
-			traceInfos[ num ].surfaceNum == ti->surfaceNum &&
-			traceInfos[ num ].castShadows == ti->castShadows )
-			return num;
-	}
-	
-	/* enough space? */
-	if( numTraceInfos >= maxTraceInfos )
-	{
-		/* allocate more room */
-		maxTraceInfos += GROW_TRACE_INFOS;
-		temp = safe_malloc( maxTraceInfos * sizeof( *traceInfos ) );
-		if( traceInfos != NULL )
-		{
-			memcpy( temp, traceInfos, numTraceInfos * sizeof( *traceInfos ) );
-			free( traceInfos );
-		}
-		traceInfos = (traceInfo_t*) temp;
-	}
-	
-	/* add the info */
-	memcpy( &traceInfos[ num ], ti, sizeof( *traceInfos ) );
-	if( num == numTraceInfos )
-		numTraceInfos++;
-	
-	/* return the ti number */
-	return num;
-}
-
-
-
-/*
-AllocTraceNode() - ydnar
-allocates a new trace node
-*/
-
-static int AllocTraceNode( void )
-{
-	traceNode_t	*temp;
-	
-	
-	/* enough space? */
-	if( numTraceNodes >= maxTraceNodes )
-	{
-		/* reallocate more room */
-		maxTraceNodes += GROW_TRACE_NODES;
-		temp = safe_malloc( maxTraceNodes * sizeof( traceNode_t ) );
-		if( traceNodes != NULL )
-		{
-			memcpy( temp, traceNodes, numTraceNodes * sizeof( traceNode_t ) );
-			free( traceNodes );
-		}
-		traceNodes = temp;
-	}
-	
-	/* add the node */
-	memset( &traceNodes[ numTraceNodes ], 0, sizeof( traceNode_t ) );
-	traceNodes[ numTraceNodes ].type = TRACE_LEAF;
-	ClearBounds( traceNodes[ numTraceNodes ].mins, traceNodes[ numTraceNodes ].maxs );
-	numTraceNodes++;
-	
-	/* return the count */
-	return (numTraceNodes - 1);
-}
-
-
-
-/*
-AddTraceWinding() - ydnar
-adds a winding to the raytracing pool
-*/
-
-static int AddTraceWinding( traceWinding_t *tw )
-{
-	int		num;
-	void	*temp;
-	
-	
-	/* check for a dead winding */
-	if( deadWinding >= 0 && deadWinding < numTraceWindings )
-		num = deadWinding;
-	else
-	{
-		/* put winding at the end of the list */
-		num = numTraceWindings;
-		
-		/* enough space? */
-		if( numTraceWindings >= maxTraceWindings )
-		{
-			/* allocate more room */
-			maxTraceWindings += GROW_TRACE_WINDINGS;
-			temp = safe_malloc( maxTraceWindings * sizeof( *traceWindings ) );
-			if( traceWindings != NULL )
-			{
-				memcpy( temp, traceWindings, numTraceWindings * sizeof( *traceWindings ) );
-				free( traceWindings );
-			}
-			traceWindings = (traceWinding_t*) temp;
-		}
-	}
-	
-	/* add the winding */
-	memcpy( &traceWindings[ num ], tw, sizeof( *traceWindings ) );
-	if( num == numTraceWindings )
-		numTraceWindings++;
-	deadWinding = -1;
-	
-	/* return the winding number */
-	return num;
-}
-
-
-
-/*
-AddTraceTriangle() - ydnar
-adds a triangle to the raytracing pool
-*/
-
-static int AddTraceTriangle( traceTriangle_t *tt )
-{
-	int		num;
-	void	*temp;
-	
-	
-	/* check for a dead triangle */
-	if( deadTriangle >= 0 && deadTriangle < numTraceTriangles )
-		num = deadTriangle;
-	else
-	{
-		/* put triangle at the end of the list */
-		num = numTraceTriangles;
-		
-		/* enough space? */
-		if( numTraceTriangles >= maxTraceTriangles )
-		{
-			/* allocate more room */
-			maxTraceTriangles += GROW_TRACE_TRIANGLES;
-			temp = safe_malloc( maxTraceTriangles * sizeof( *traceTriangles ) );
-			if( traceTriangles != NULL )
-			{
-				memcpy( temp, traceTriangles, numTraceTriangles * sizeof( *traceTriangles ) );
-				free( traceTriangles );
-			}
-			traceTriangles = (traceTriangle_t*) temp;
-		}
-	}
-	
-	/* find vectors for two edges sharing the first vert */
-	VectorSubtract( tt->v[ 1 ].xyz, tt->v[ 0 ].xyz, tt->edge1 );
-	VectorSubtract( tt->v[ 2 ].xyz, tt->v[ 0 ].xyz, tt->edge2 );
-	
-	/* add the triangle */
-	memcpy( &traceTriangles[ num ], tt, sizeof( *traceTriangles ) );
-	if( num == numTraceTriangles )
-		numTraceTriangles++;
-	deadTriangle = -1;
-	
-	/* return the triangle number */
-	return num;
-}
-
-
-
-/*
-AddItemToTraceNode() - ydnar
-adds an item reference (winding or triangle) to a trace node
-*/
-
-static int AddItemToTraceNode( traceNode_t *node, int num )
-{
-	void			*temp;
-	
-	
-	/* dummy check */
-	if( num < 0 )
-		return -1;
-	
-	/* enough space? */
-	if( node->numItems >= node->maxItems )
-	{
-		/* allocate more room */
-		if( node == traceNodes )
-			node->maxItems *= 2;
-		else
-			node->maxItems += GROW_NODE_ITEMS;
-		temp = safe_malloc( node->maxItems * sizeof( *node->items ) );
-		if( node->items != NULL )
-		{
-			memcpy( temp, node->items, node->numItems * sizeof( *node->items ) );
-			free( node->items );
-		}
-		node->items = (int*) temp;
-	}
-	
-	/* add the poly */
-	node->items[ node->numItems ] = num;
-	node->numItems++;
-	
-	/* return the count */
-	return (node->numItems - 1);
-}
-
-
-
-
-/* -------------------------------------------------------------------------------
-
-trace node setup
-
-------------------------------------------------------------------------------- */
-
-/*
-SetupTraceNodes_r() - ydnar
-recursively create the initial trace node structure from the bsp tree
-*/
-
-static int SetupTraceNodes_r( int bspNodeNum )
-{
-	int				i, nodeNum, bspLeafNum;
-	bspPlane_t		*plane;
-	bspNode_t 		*bspNode;
-	
-	
-	/* get bsp node and plane */
-	bspNode = &bspNodes[ bspNodeNum ];
-	plane = &bspPlanes[ bspNode->planeNum ];
-	
-	/* allocate a new trace node */
-	nodeNum = AllocTraceNode();
-	
-	/* setup trace node */
-	traceNodes[ nodeNum ].type = PlaneTypeForNormal( plane->normal );
-	VectorCopy( plane->normal, traceNodes[ nodeNum ].plane );
-	traceNodes[ nodeNum ].plane[ 3 ] = plane->dist;
-	
-	/* setup children */
-	for( i = 0; i < 2; i++ )
-	{
-		/* leafnode */
-		if( bspNode->children[ i ] < 0 )
-		{
-			bspLeafNum = -bspNode->children[ i ] - 1;
-			
-			#if 0
-			/* solid leaf */
-			if( bspLeafs[ bspLeafNum ].cluster == -1 )
-				traceNodes[ nodeNum ].children[ i ] = -1;
-			
-			/* passable leaf */
-			else
-				traceNodes[ nodeNum ].children[ i ] = AllocTraceNode();
-			#endif
-			
-			/* new code */
-			traceNodes[ nodeNum ].children[ i ] = AllocTraceNode();
-			if( bspLeafs[ bspLeafNum ].cluster == -1 )
-				traceNodes[ traceNodes[ nodeNum ].children[ i ] ].type = TRACE_LEAF_SOLID;
-		}
-		
-		/* normal node */
-		else
-			traceNodes[ nodeNum ].children[ i ] = SetupTraceNodes_r( bspNode->children[ i ] );
-	}
-	
-	/* return node number */
-	return nodeNum;
-}
-
-
-
-/*
-ClipTraceWinding() - ydnar
-clips a trace winding against a plane into one or two parts
-*/
-
-#define TW_ON_EPSILON	0.25f
-
-void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front, traceWinding_t *back )
-{
-	int				i, j, k;
-	int				sides[ MAX_TW_VERTS ], counts[ 3 ] = { 0, 0, 0 };
-	float			dists[ MAX_TW_VERTS ];
-	float			frac;
-	traceVert_t		*a, *b, mid;
-	
-	
-	/* clear front and back */
-	front->numVerts = 0;
-	back->numVerts = 0;
-	
-	/* classify points */
-	for( i = 0; i < tw->numVerts; i++ )
-	{
-		dists[ i ] = DotProduct( tw->v[ i ].xyz, plane ) - plane[ 3 ];
-		if( dists[ i ] < -TW_ON_EPSILON )
-			sides[ i ] = SIDE_BACK;
-		else if( dists[ i ] > TW_ON_EPSILON )
-			sides[ i ] = SIDE_FRONT;
-		else
-			sides[ i ] = SIDE_ON;
-		counts[ sides[ i ] ]++;
-	}
-	
-	/* entirely on front? */
-	if( counts[ SIDE_BACK ] == 0 )
-		memcpy( front, tw, sizeof( *front ) );
-	
-	/* entirely on back? */
-	else if( counts[ SIDE_FRONT ] == 0 )
-		memcpy( back, tw, sizeof( *back ) );
-	
-	/* straddles the plane */
-	else
-	{
-		/* setup front and back */
-		memcpy( front, tw, sizeof( *front ) );
-		front->numVerts = 0;
-		memcpy( back, tw, sizeof( *back ) ); 
-		back->numVerts = 0;
-		
-		/* split the winding */
-		for( i = 0; i < tw->numVerts; i++ )
-		{
-			/* radix */
-			j = (i + 1) % tw->numVerts;
-			
-			/* get verts */
-			a = &tw->v[ i ];
-			b = &tw->v[ j ];
-			
-			/* handle points on the splitting plane */
-			switch( sides[ i ] )
-			{
-				case SIDE_FRONT:
-					if( front->numVerts >= MAX_TW_VERTS )
-						Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
-					front->v[ front->numVerts++ ] = *a;
-					break;
-				
-				case SIDE_BACK:
-					if( back->numVerts >= MAX_TW_VERTS )
-						Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
-					back->v[ back->numVerts++ ] = *a;
-					break;
-				
-				case SIDE_ON:
-					if( front->numVerts >= MAX_TW_VERTS || back->numVerts >= MAX_TW_VERTS )
-						Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
-					front->v[ front->numVerts++ ] = *a;
-					back->v[ back->numVerts++ ] = *a;
-					continue;
-			}
-			
-			/* check next point to see if we need to split the edge */
-			if( sides[ j ] == SIDE_ON || sides[ j ] == sides[ i ] )
-				continue;
-			
-			/* check limit */
-			if( front->numVerts >= MAX_TW_VERTS || back->numVerts >= MAX_TW_VERTS )
-				Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
-			
-			/* generate a split point */
-			frac = dists[ i ] / (dists[ i ] - dists[ j ]);
-			for( k = 0; k < 3; k++ )
-			{
-				/* minimize fp precision errors */
-				if( plane[ k ] == 1.0f )
-					mid.xyz[ k ] = plane[ 3 ];
-				else if( plane[ k ] == -1.0f )
-					mid.xyz[ k ] = -plane[ 3 ];
-				else
-					mid.xyz[ k ] = a->xyz[ k ] + frac * (b->xyz[ k ] - a->xyz[ k ]);
-				
-				/* set texture coordinates */
-				if( k > 1 )
-					continue;
-				mid.st[ 0 ] = a->st[ 0 ] + frac * (b->st[ 0 ] - a->st[ 0 ]);
-				mid.st[ 1 ] = a->st[ 1 ] + frac * (b->st[ 1 ] - a->st[ 1 ]);
-			}
-			
-			/* copy midpoint to front and back polygons */
-			front->v[ front->numVerts++ ] = mid;
-			back->v[ back->numVerts++ ] = mid;
-		}
-	}
-}
-
-
-
-/*
-FilterPointToTraceNodes_r() - ydnar
-debugging tool
-*/
-
-static int FilterPointToTraceNodes_r( vec3_t pt, int nodeNum )
-{
-	float			dot;
-	traceNode_t		*node;
-	
-	
-	if( nodeNum < 0 || nodeNum >= numTraceNodes )
-		return -1;
-	
-	node = &traceNodes[ nodeNum ];
-	
-	if( node->type >= 0 )
-	{
-		dot = DotProduct( pt, node->plane ) - node->plane[ 3 ];
-		if( dot > -0.001f )
-			FilterPointToTraceNodes_r( pt, node->children[ 0 ] );
-		if( dot < 0.001f )
-			FilterPointToTraceNodes_r( pt, node->children[ 1 ] );
-		return -1;
-	}
-	
-	Sys_Printf( "%d ", nodeNum );
-	
-	return nodeNum;
-}
-
-
-
-/*
-FilterTraceWindingIntoNodes_r() - ydnar
-filters a trace winding into the raytracing tree
-*/
-
-static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum )
-{
-	int				num;
-	vec4_t			plane1, plane2, reverse;
-	traceNode_t		*node;
-	traceWinding_t	front, back;
-	
-	
-	/* don't filter if passed a bogus node (solid, etc) */
-	if( nodeNum < 0 || nodeNum >= numTraceNodes )
-		return;
-	
-	/* get node */
-	node = &traceNodes[ nodeNum ];
-	
-	/* is this a decision node? */
-	if( node->type >= 0 )
-	{	
-		/* create winding plane if necessary, filtering out bogus windings as well */
-		if( nodeNum == headNodeNum )
-		{
-			if( !PlaneFromPoints( tw->plane, tw->v[ 0 ].xyz, tw->v[ 1 ].xyz, tw->v[ 2 ].xyz ) )
-				return;
-		}
-	
-		/* validate the node */
-		if( node->children[ 0 ] == 0 || node->children[ 1 ] == 0 )
-			Error( "Invalid tracenode: %d", nodeNum );
-		
-		/* get node plane */
-		Vector4Copy( node->plane, plane1 );
-		
-		/* get winding plane */
-		Vector4Copy( tw->plane, plane2 );
-		
-		/* invert surface plane */
-		VectorSubtract( vec3_origin, plane2, reverse );
-		reverse[ 3 ] = -plane2[ 3 ];
-		
-		/* front only */
-		if( DotProduct( plane1, plane2 ) > 0.999f && fabs( plane1[ 3 ] - plane2[ 3 ] ) < 0.001f )
-		{
-			FilterTraceWindingIntoNodes_r( tw, node->children[ 0 ] );
-			return;
-		}
-		
-		/* back only */
-		if( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f )
-		{
-			FilterTraceWindingIntoNodes_r( tw, node->children[ 1 ] );
-			return;
-		}
-		
-		/* clip the winding by node plane */
-		ClipTraceWinding( tw, plane1, &front, &back );
-		
-		/* filter by node plane */
-		if( front.numVerts >= 3 )
-			FilterTraceWindingIntoNodes_r( &front, node->children[ 0 ] );
-		if( back.numVerts >= 3 )
-			FilterTraceWindingIntoNodes_r( &back, node->children[ 1 ] );
-		
-		/* return to caller */
-		return;
-	}
-	
-	/* add winding to leaf node */
-	num = AddTraceWinding( tw );
-	AddItemToTraceNode( node, num );
-}
-
-
-
-/*
-SubdivideTraceNode_r() - ydnar
-recursively subdivides a tracing node until it meets certain size and complexity criteria
-*/
-
-static void SubdivideTraceNode_r( int nodeNum, int depth )
-{
-	int				i, j, count, num, frontNum, backNum, type;
-	vec3_t			size;
-	float			dist;
-	double			average[ 3 ];
-	traceNode_t		*node, *frontNode, *backNode;
-	traceWinding_t	*tw, front, back;
-	
-	
-	/* dummy check */
-	if( nodeNum < 0 || nodeNum >= numTraceNodes )
-		return;
-	
-	/* get node */
-	node = &traceNodes[ nodeNum ];
-	
-	/* runaway recursion check */
-	if( depth >= MAX_TRACE_DEPTH )
-	{
-		//%	Sys_Printf( "Depth: (%d items)\n", node->numItems );
-		numTraceLeafNodes++;
-		return;
-	}
-	depth++;
-	
-	/* is this a decision node? */
-	if( node->type >= 0 )
-	{
-		/* subdivide children */
-		frontNum = node->children[ 0 ];
-		backNum = node->children[ 1 ];
-		SubdivideTraceNode_r( frontNum, depth );
-		SubdivideTraceNode_r( backNum, depth );
-		return;
-	}
-	
-	/* bound the node */
-	ClearBounds( node->mins, node->maxs );
-	VectorClear( average );
-	count = 0;
-	for( i = 0; i < node->numItems; i++ )
-	{
-		/* get winding */
-		tw = &traceWindings[ node->items[ i ] ];
-		
-		/* walk its verts */
-		for( j = 0; j < tw->numVerts; j++ )
-		{
-			AddPointToBounds( tw->v[ j ].xyz, node->mins, node->maxs );
-			average[ 0 ] += tw->v[ j ].xyz[ 0 ];
-			average[ 1 ] += tw->v[ j ].xyz[ 1 ];
-			average[ 2 ] += tw->v[ j ].xyz[ 2 ];
-			count++;
-		}
-	}
-	
-	/* check triangle limit */
-	//%	if( node->numItems <= MAX_NODE_ITEMS )
-	if( (count - (node->numItems * 2)) < MAX_NODE_TRIANGLES )
-	{
-		//%	Sys_Printf( "Limit: (%d triangles)\n", (count - (node->numItems * 2)) );
-		numTraceLeafNodes++;
-		return;
-	}
-	
-	/* the largest dimension of the bounding box will be the split axis */
-	VectorSubtract( node->maxs, node->mins, size );
-	if( size[ 0 ] >= size[ 1 ] && size[ 0 ] >= size[ 2 ] )
-		type = PLANE_X;
-	else if( size[ 1 ] >= size[ 0 ] && size[ 1 ] >= size[ 2 ] )
-		type = PLANE_Y;
-	else
-		type = PLANE_Z;
-	
-	/* don't split small nodes */
-	if( size[ type ] <= MIN_NODE_SIZE )
-	{
-		//%	Sys_Printf( "Limit: %f %f %f (%d items)\n", size[ 0 ], size[ 1 ], size[ 2 ], node->numItems );
-		numTraceLeafNodes++;
-		return;
-	}
-	
-	/* set max trace depth */
-	if( depth > maxTraceDepth )
-		maxTraceDepth = depth;
-	
-	/* snap the average */
-	dist = floor( average[ type ] / count );
-	
-	/* dummy check it */
-	if( dist <= node->mins[ type ] || dist >= node->maxs[ type ] )
-		dist = floor( 0.5f * (node->mins[ type ] + node->maxs[ type ]) );
-	
-	/* allocate child nodes */
-	frontNum = AllocTraceNode();
-	backNum = AllocTraceNode();
-	
-	/* reset pointers */
-	node = &traceNodes[ nodeNum ];
-	frontNode = &traceNodes[ frontNum ];
-	backNode = &traceNodes[ backNum ];
-	
-	/* attach children */
-	node->type = type;
-	node->plane[ type ] = 1.0f;
-	node->plane[ 3 ] = dist;
-	node->children[ 0 ] = frontNum;
-	node->children[ 1 ] = backNum;
-	
-	/* setup front node */
-	frontNode->maxItems = (node->maxItems >> 1);
-	frontNode->items = safe_malloc( frontNode->maxItems * sizeof( *frontNode->items ) );
-	
-	/* setup back node */
-	backNode->maxItems = (node->maxItems >> 1);
-	backNode->items = safe_malloc( backNode->maxItems * sizeof( *backNode->items ) );
-	
-	/* filter windings into child nodes */
-	for( i = 0; i < node->numItems; i++ )
-	{
-		/* get winding */
-		tw = &traceWindings[ node->items[ i ] ];
-		
-		/* clip the winding by the new split plane */
-		ClipTraceWinding( tw, node->plane, &front, &back );
-		
-		/* kill the existing winding */
-		if( front.numVerts >= 3 || back.numVerts >= 3 )
-			deadWinding = node->items[ i ];
-		
-		/* add front winding */
-		if( front.numVerts >= 3 )
-		{
-			num = AddTraceWinding( &front );
-			AddItemToTraceNode( frontNode, num );
-		}
-		
-		/* add back winding */
-		if( back.numVerts >= 3 )
-		{
-			num = AddTraceWinding( &back );
-			AddItemToTraceNode( backNode, num );
-		}
-	}
-	
-	/* free original node winding list */
-	node->numItems = 0;
-	node->maxItems = 0;
-	free( node->items );
-	node->items = NULL;
-	
-	/* check children */
-	if( frontNode->numItems <= 0 )
-	{
-		frontNode->maxItems = 0;
-		free( frontNode->items );
-		frontNode->items = NULL;
-	}
-	
-	if( backNode->numItems <= 0 )
-	{
-		backNode->maxItems = 0;
-		free( backNode->items );
-		backNode->items = NULL;
-	}
-	
-	/* subdivide children */
-	SubdivideTraceNode_r( frontNum, depth );
-	SubdivideTraceNode_r( backNum, depth );
-}
-
-
-
-/*
-TriangulateTraceNode_r()
-optimizes the tracing data by changing trace windings into triangles
-*/
-
-static int TriangulateTraceNode_r( int nodeNum )
-{
-	int				i, j, num, frontNum, backNum, numWindings, *windings;
-	traceNode_t		*node;
-	traceWinding_t	*tw;
-	traceTriangle_t	tt;
-	
-	
-	/* dummy check */
-	if( nodeNum < 0 || nodeNum >= numTraceNodes )
-		return 0;
-	
-	/* get node */
-	node = &traceNodes[ nodeNum ];
-	
-	/* is this a decision node? */
-	if( node->type >= 0 )
-	{
-		/* triangulate children */
-		frontNum = node->children[ 0 ];
-		backNum = node->children[ 1 ];
-		node->numItems = TriangulateTraceNode_r( frontNum );
-		node->numItems += TriangulateTraceNode_r( backNum );
-		return node->numItems;
-	}
-	
-	/* empty node? */
-	if( node->numItems == 0 )
-	{
-		node->maxItems = 0;
-		if( node->items != NULL )
-			free( node->items );
-		return node->numItems;
-	}
-	
-	/* store off winding data */
-	numWindings = node->numItems;
-	windings = node->items;
-	
-	/* clear it */
-	node->numItems = 0;
-	node->maxItems = numWindings * 2;
-	node->items = safe_malloc( node->maxItems * sizeof( tt ) );
-	
-	/* walk winding list */
-	for( i = 0; i < numWindings; i++ )
-	{
-		/* get winding */
-		tw = &traceWindings[ windings[ i ] ];
-		
-		/* initial setup */
-		tt.infoNum = tw->infoNum;
-		tt.v[ 0 ] = tw->v[ 0 ];
-		
-		/* walk vertex list */
-		for( j = 1; j + 1 < tw->numVerts; j++ )
-		{
-			/* set verts */
-			tt.v[ 1 ] = tw->v[ j ];
-			tt.v[ 2 ] = tw->v[ j + 1 ];
-			
-			/* find vectors for two edges sharing the first vert */
-			VectorSubtract( tt.v[ 1 ].xyz, tt.v[ 0 ].xyz, tt.edge1 );
-			VectorSubtract( tt.v[ 2 ].xyz, tt.v[ 0 ].xyz, tt.edge2 );
-			
-			/* add it to the node */
-			num = AddTraceTriangle( &tt );
-			AddItemToTraceNode( node, num );
-		}
-	}
-	
-	/* free windings */
-	if( windings != NULL )
-		free( windings );
-	
-	/* return item count */
-	return node->numItems;
-}
-
-
-
-/* -------------------------------------------------------------------------------
-
-shadow casting item setup (triangles, patches, entities)
-
-------------------------------------------------------------------------------- */
-
-/*
-PopulateWithBSPModel() - ydnar
-filters a bsp model's surfaces into the raytracing tree
-*/
-
-static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform )
-{
-	int					i, j, x, y, pw[ 5 ], r, nodeNum;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	bspDrawVert_t		*verts;
-	int					*indexes;
-	mesh_t				srcMesh, *mesh, *subdivided;
-	traceInfo_t			ti;
-	traceWinding_t		tw;
-	
-	
-	/* dummy check */
-	if( model == NULL || transform == NULL )
-		return;
-	
-	/* walk the list of surfaces in this model and fill out the info structs */
-	for( i = 0; i < model->numBSPSurfaces; i++ )
-	{
-		/* get surface and info */
-		ds = &bspDrawSurfaces[ model->firstBSPSurface + i ];
-		info = &surfaceInfos[ model->firstBSPSurface + i ];
-		if( info->si == NULL )
-			continue;
-		
-		/* no shadows */
-		if( !info->castShadows )
-			continue;
-		
-		/* patchshadows? */
-		if( ds->surfaceType == MST_PATCH && patchShadows == qfalse )
-			continue;
-		
-		/* some surfaces in the bsp might have been tagged as nodraw, with a bogus shader */
-		if( (bspShaders[ ds->shaderNum ].contentFlags & noDrawContentFlags) || 
-			(bspShaders[ ds->shaderNum ].surfaceFlags & noDrawSurfaceFlags) )
-			continue;
-		
-		/* translucent surfaces that are neither alphashadow or lightfilter don't cast shadows */
-		if( (info->si->compileFlags & C_NODRAW) )
-			continue;
-		if( (info->si->compileFlags & C_TRANSLUCENT) &&
-			!(info->si->compileFlags & C_ALPHASHADOW) && 
-			!(info->si->compileFlags & C_LIGHTFILTER) )
-			continue;
-		
-		/* setup trace info */
-		ti.si = info->si;
-		ti.castShadows = info->castShadows;
-		ti.surfaceNum = model->firstBSPBrush + i;
-		
-		/* setup trace winding */
-		memset( &tw, 0, sizeof( tw ) );
-		tw.infoNum = AddTraceInfo( &ti );
-		tw.numVerts = 3;
-		
-		/* choose which node (normal or skybox) */
-		if( info->parentSurfaceNum >= 0 )
-			nodeNum = skyboxNodeNum;
-		else
-			nodeNum = headNodeNum;
-		
-		/* switch on type */
-		switch( ds->surfaceType )
-		{
-			/* handle patches */
-			case MST_PATCH:
-				/* subdivide the surface */
-				srcMesh.width = ds->patchWidth;
-				srcMesh.height = ds->patchHeight;
-				srcMesh.verts = &bspDrawVerts[ ds->firstVert ];
-				//%	subdivided = SubdivideMesh( srcMesh, 8, 512 );
-				subdivided = SubdivideMesh2( srcMesh, info->patchIterations );
-				
-				/* fit it to the curve and remove colinear verts on rows/columns */
-				PutMeshOnCurve( *subdivided );
-				mesh = RemoveLinearMeshColumnsRows( subdivided );
-				FreeMesh( subdivided );
-				
-				/* set verts */
-				verts = mesh->verts;
-				
-				/* subdivide each quad to place the models */
-				for( y = 0; y < (mesh->height - 1); y++ )
-				{
-					for( x = 0; x < (mesh->width - 1); x++ )
-					{
-						/* set indexes */
-						pw[ 0 ] = x + (y * mesh->width);
-						pw[ 1 ] = x + ((y + 1) * mesh->width);
-						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-						pw[ 3 ] = x + 1 + (y * mesh->width);
-						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-						
-						/* set radix */
-						r = (x + y) & 1;
-						
-						/* make first triangle */
-						VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz );
-						Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st );
-						VectorCopy( verts[ pw[ r + 1 ] ].xyz, tw.v[ 1 ].xyz );
-						Vector2Copy( verts[ pw[ r + 1 ] ].st, tw.v[ 1 ].st );
-						VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 2 ].xyz );
-						Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 2 ].st );
-						m4x4_transform_point( transform, tw.v[ 0 ].xyz );
-						m4x4_transform_point( transform, tw.v[ 1 ].xyz );
-						m4x4_transform_point( transform, tw.v[ 2 ].xyz );
-						FilterTraceWindingIntoNodes_r( &tw, nodeNum );
-						
-						/* make second triangle */
-						VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz );
-						Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st );
-						VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 1 ].xyz );
-						Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 1 ].st );
-						VectorCopy( verts[ pw[ r + 3 ] ].xyz, tw.v[ 2 ].xyz );
-						Vector2Copy( verts[ pw[ r + 3 ] ].st, tw.v[ 2 ].st );
-						m4x4_transform_point( transform, tw.v[ 0 ].xyz );
-						m4x4_transform_point( transform, tw.v[ 1 ].xyz );
-						m4x4_transform_point( transform, tw.v[ 2 ].xyz );
-						FilterTraceWindingIntoNodes_r( &tw, nodeNum );
-					}
-				}
-				
-				/* free the subdivided mesh */
-				FreeMesh( mesh );
-				break;
-			
-			/* handle triangle surfaces */
-			case MST_TRIANGLE_SOUP:
-			case MST_PLANAR:
-				/* set verts and indexes */
-				verts = &bspDrawVerts[ ds->firstVert ];
-				indexes = &bspDrawIndexes[ ds->firstIndex ];
-				
-				/* walk the triangle list */
-				for( j = 0; j < ds->numIndexes; j += 3 )
-				{
-					VectorCopy( verts[ indexes[ j ] ].xyz, tw.v[ 0 ].xyz );
-					Vector2Copy( verts[ indexes[ j ] ].st, tw.v[ 0 ].st );
-					VectorCopy( verts[ indexes[ j + 1 ] ].xyz, tw.v[ 1 ].xyz );
-					Vector2Copy( verts[ indexes[ j + 1 ] ].st, tw.v[ 1 ].st );
-					VectorCopy( verts[ indexes[ j + 2 ] ].xyz, tw.v[ 2 ].xyz );
-					Vector2Copy( verts[ indexes[ j + 2 ] ].st, tw.v[ 2 ].st );
-					m4x4_transform_point( transform, tw.v[ 0 ].xyz );
-					m4x4_transform_point( transform, tw.v[ 1 ].xyz );
-					m4x4_transform_point( transform, tw.v[ 2 ].xyz );
-					FilterTraceWindingIntoNodes_r( &tw, nodeNum );
-				}
-				break;
-			
-			/* other surface types do not cast shadows */
-			default:
-				break;
-		}
-	}
-}
-
-
-
-/*
-PopulateWithPicoModel() - ydnar
-filters a picomodel's surfaces into the raytracing tree
-*/
-
-static void PopulateWithPicoModel( int castShadows, picoModel_t *model, m4x4_t transform )
-{
-	int					i, j, k, numSurfaces, numIndexes;
-	picoSurface_t		*surface;
-	picoShader_t		*shader;
-	picoVec_t			*xyz, *st;
-	picoIndex_t			*indexes;
-	traceInfo_t			ti;
-	traceWinding_t		tw;
-	
-	
-	/* dummy check */
-	if( model == NULL || transform == NULL )
-		return;
-	
-	/* get info */
-	numSurfaces = PicoGetModelNumSurfaces( model );
-	
-	/* walk the list of surfaces in this model and fill out the info structs */
-	for( i = 0; i < numSurfaces; i++ )
-	{
-		/* get surface */
-		surface = PicoGetModelSurface( model, i );
-		if( surface == NULL )
-			continue;
-		
-		/* only handle triangle surfaces initially (fixme: support patches) */
-		if( PicoGetSurfaceType( surface ) != PICO_TRIANGLES )
-			continue;
-		
-		/* get shader (fixme: support shader remapping) */
-		shader = PicoGetSurfaceShader( surface );
-		if( shader == NULL )
-			continue;
-		ti.si = ShaderInfoForShader( PicoGetShaderName( shader ) );
-		if( ti.si == NULL )
-			continue;
-		
-		/* translucent surfaces that are neither alphashadow or lightfilter don't cast shadows */
-		if( (ti.si->compileFlags & C_NODRAW) )
-			continue;
-		if( (ti.si->compileFlags & C_TRANSLUCENT) &&
-			!(ti.si->compileFlags & C_ALPHASHADOW) && 
-			!(ti.si->compileFlags & C_LIGHTFILTER) )
-			continue;
-		
-		/* setup trace info */
-		ti.castShadows = castShadows;
-		ti.surfaceNum = -1;
-		
-		/* setup trace winding */
-		memset( &tw, 0, sizeof( tw ) );
-		tw.infoNum = AddTraceInfo( &ti );
-		tw.numVerts = 3;
-		
-		/* get info */
-		numIndexes = PicoGetSurfaceNumIndexes( surface );
-		indexes = PicoGetSurfaceIndexes( surface, 0 );
-		
-		/* walk the triangle list */
-		for( j = 0; j < numIndexes; j += 3, indexes += 3 )
-		{
-			for( k = 0; k < 3; k++ )
-			{
-				xyz = PicoGetSurfaceXYZ( surface, indexes[ k ] );
-				st = PicoGetSurfaceST( surface, 0, indexes[ k ] );
-				VectorCopy( xyz, tw.v[ k ].xyz );
-				Vector2Copy( st, tw.v[ k ].st );
-				m4x4_transform_point( transform, tw.v[ k ].xyz );
-			}
-			FilterTraceWindingIntoNodes_r( &tw, headNodeNum );
-		}
-	}
-}
-
-
-
-/*
-PopulateTraceNodes() - ydnar
-fills the raytracing tree with world and entity occluders
-*/
-
-static void PopulateTraceNodes( void )
-{
-	int				i, m, frame, castShadows;
-	float			temp;
-	entity_t		*e;
-	const char		*value;
-	picoModel_t		*model;
-	vec3_t			origin, scale, angles;
-	m4x4_t			transform;
-
-	
-	/* add worldspawn triangles */
-	m4x4_identity( transform );
-	PopulateWithBSPModel( &bspModels[ 0 ], transform );
-	
-	/* walk each entity list */
-	for( i = 1; i < numEntities; i++ )
-	{
-		/* get entity */
-		e = &entities[ i ];
-		
-		/* get shadow flags */
-		castShadows = ENTITY_CAST_SHADOWS;
-		GetEntityShadowFlags( e, NULL, &castShadows, NULL );
-		
-		/* early out? */
-		if( !castShadows )
-			continue;
-		
-		/* get entity origin */
-		GetVectorForKey( e, "origin", origin );
-		
-		/* get scale */
-		scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = 1.0f;
-		temp = FloatForKey( e, "modelscale" );
-		if( temp != 0.0f )
-			scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = temp;
-		value = ValueForKey( e, "modelscale_vec" );
-		if( value[ 0 ] != '\0' )
-			sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
-		
-		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
-		angles[ 0 ] = angles[ 1 ] = angles[ 2 ] = 0.0f;
-		angles[ 2 ] = FloatForKey( e, "angle" );
-		value = ValueForKey( e, "angles" );
-		if( value[ 0 ] != '\0' )
-			sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
-		
-		/* set transform matrix (thanks spog) */
-		m4x4_identity( transform );
-		m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
-		
-		/* hack: Stable-1_2 and trunk have differing row/column major matrix order
-		   this transpose is necessary with Stable-1_2
-		   uncomment the following line with old m4x4_t (non 1.3/spog_branch) code */
-		//%	m4x4_transpose( transform );
-		
-		/* get model */
-		value = ValueForKey( e, "model" );
-		
-		/* switch on model type */
-		switch( value[ 0 ] )
-		{
-			/* no model */
-			case '\0':
-				break;
-			
-			/* bsp model */
-			case '*':
-				m = atoi( &value[ 1 ] );
-				if( m <= 0 || m >= numBSPModels )
-					continue;
-				PopulateWithBSPModel( &bspModels[ m ], transform );
-				break;
-			
-			/* external model */
-			default:
-				frame = IntForKey( e, "_frame" );
-				model = LoadModel( (char*) value, frame );
-				if( model == NULL )
-					continue;
-				PopulateWithPicoModel( castShadows, model, transform );
-				continue;
-		}
-		
-		/* get model2 */
-		value = ValueForKey( e, "model2" );
-		
-		/* switch on model type */
-		switch( value[ 0 ] )
-		{
-			/* no model */
-			case '\0':
-				break;
-			
-			/* bsp model */
-			case '*':
-				m = atoi( &value[ 1 ] );
-				if( m <= 0 || m >= numBSPModels )
-					continue;
-				PopulateWithBSPModel( &bspModels[ m ], transform );
-				break;
-			
-			/* external model */
-			default:
-				frame = IntForKey( e, "_frame2" );
-				model = LoadModel( (char*) value, frame );
-				if( model == NULL )
-					continue;
-				PopulateWithPicoModel( castShadows, model, transform );
-				continue;
-		}
-	}
-}
-
-
-
-
-/* -------------------------------------------------------------------------------
-
-trace initialization
-
-------------------------------------------------------------------------------- */
-
-/*
-SetupTraceNodes() - ydnar
-creates a balanced bsp with axis-aligned splits for efficient raytracing
-*/
-
-void SetupTraceNodes( void )
-{
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- SetupTraceNodes ---\n" );
-	
-	/* find nodraw bit */
-	noDrawContentFlags = noDrawSurfaceFlags = noDrawCompileFlags = 0;
-	ApplySurfaceParm( "nodraw", &noDrawContentFlags, &noDrawSurfaceFlags, &noDrawCompileFlags );
-	
-	/* create the baseline raytracing tree from the bsp tree */
-	headNodeNum = SetupTraceNodes_r( 0 );
-	
-	/* create outside node for skybox surfaces */
-	skyboxNodeNum = AllocTraceNode();
-	
-	/* populate the tree with triangles from the world and shadow casting entities */
-	PopulateTraceNodes();
-	
-	/* create the raytracing bsp */
-	if( loMem == qfalse )
-	{
-		SubdivideTraceNode_r( headNodeNum, 0 );
-		SubdivideTraceNode_r( skyboxNodeNum, 0 );
-	}
-	
-	/* create triangles from the trace windings */
-	TriangulateTraceNode_r( headNodeNum );
-	TriangulateTraceNode_r( skyboxNodeNum );
-	
-	/* emit some stats */
-	//%	Sys_FPrintf( SYS_VRB, "%9d original triangles\n", numOriginalTriangles );
-	Sys_FPrintf( SYS_VRB, "%9d trace windings (%.2fMB)\n", numTraceWindings, (float) (numTraceWindings * sizeof( *traceWindings )) / (1024.0f * 1024.0f) );
-	Sys_FPrintf( SYS_VRB, "%9d trace triangles (%.2fMB)\n", numTraceTriangles, (float) (numTraceTriangles * sizeof( *traceTriangles )) / (1024.0f * 1024.0f) );
-	Sys_FPrintf( SYS_VRB, "%9d trace nodes (%.2fMB)\n", numTraceNodes, (float) (numTraceNodes * sizeof( *traceNodes )) / (1024.0f * 1024.0f) );
-	Sys_FPrintf( SYS_VRB, "%9d leaf nodes (%.2fMB)\n", numTraceLeafNodes, (float) (numTraceLeafNodes * sizeof( *traceNodes )) / (1024.0f * 1024.0f) );
-	//%	Sys_FPrintf( SYS_VRB, "%9d average triangles per leaf node\n", numTraceTriangles / numTraceLeafNodes );
-	Sys_FPrintf( SYS_VRB, "%9d average windings per leaf node\n", numTraceWindings / (numTraceLeafNodes + 1) );
-	Sys_FPrintf( SYS_VRB, "%9d max trace depth\n", maxTraceDepth );
-	
-	/* free trace windings */
-	free( traceWindings );
-	numTraceWindings = 0;
-	maxTraceWindings = 0;
-	deadWinding = -1;
-	
-	/* debug code: write out trace triangles to an alias obj file */
-	#if 0
-	{
-		int				i, j;
-		FILE			*file;
-		char			filename[ 1024 ];
-		traceWinding_t	*tw;
-		
-		
-		/* open the file */
-		strcpy( filename, source );
-		StripExtension( filename );
-		strcat( filename, ".lin" );
-		Sys_Printf( "Opening light trace file %s...\n", filename );
-		file = fopen( filename, "w" );
-		if( file == NULL )
-			Error( "Error opening %s for writing", filename );
-		
-		/* walk node list */
-		for( i = 0; i < numTraceWindings; i++ )
-		{
-			tw = &traceWindings[ i ];
-			for( j = 0; j < tw->numVerts + 1; j++ )
-				fprintf( file, "%f %f %f\n",
-					tw->v[ j % tw->numVerts ].xyz[ 0 ], tw->v[ j % tw->numVerts ].xyz[ 1 ], tw->v[ j % tw->numVerts ].xyz[ 2 ] );
-		}
-		
-		/* close it */
-		fclose( file );
-	}
-	#endif
-}
-
-
-
-/* -------------------------------------------------------------------------------
-
-raytracer
-
-------------------------------------------------------------------------------- */
-
-/*
-TraceTriangle()
-based on code written by william 'spog' joseph
-based on code originally written by tomas moller and ben trumbore, journal of graphics tools, 2(1):21-28, 1997
-*/
-
-#define BARY_EPSILON			0.01f
-#define ASLF_EPSILON			0.0001f	/* so to not get double shadows */
-#define COPLANAR_EPSILON		0.25f	//%	0.000001f
-#define NEAR_SHADOW_EPSILON		1.5f	//%	1.25f
-#define SELF_SHADOW_EPSILON		0.5f
-
-qboolean TraceTriangle( traceInfo_t *ti, traceTriangle_t *tt, trace_t *trace )
-{
-	int				i;
-	float			tvec[ 3 ], pvec[ 3 ], qvec[ 3 ];
-	float			det, invDet, depth;
-	float			u, v, w, s, t;
-	int				is, it;
-	byte			*pixel;
-	float			shadow;
-	shaderInfo_t	*si;
-	
-	
-	/* don't double-trace against sky */
-	si = ti->si;
-	if( trace->compileFlags & si->compileFlags & C_SKY )
-		return qfalse;
-	
-	/* receive shadows from worldspawn group only */
-	if( trace->recvShadows == 1 )
-	{
-		if( ti->castShadows != 1 )
-			return qfalse;
-	}
-	
-	/* receive shadows from same group and worldspawn group */
-	else if( trace->recvShadows > 1 )
-	{
-		if( ti->castShadows != 1 && abs( ti->castShadows ) != abs( trace->recvShadows ) )
-			return qfalse;
-		//%	Sys_Printf( "%d:%d ", tt->castShadows, trace->recvShadows );
-	}
-	
-	/* receive shadows from the same group only (< 0) */
-	else
-	{
-		if( abs( ti->castShadows ) != abs( trace->recvShadows ) )
-			return qfalse;
-	}
-	
-	/* begin calculating determinant - also used to calculate u parameter */
-	CrossProduct( trace->direction, tt->edge2, pvec );
-	
-	/* if determinant is near zero, trace lies in plane of triangle */
-	det = DotProduct( tt->edge1, pvec );
-	
-	/* the non-culling branch */
-	if( det > -COPLANAR_EPSILON && det < COPLANAR_EPSILON )
-		return qfalse;
-	invDet = 1.0f / det;
-	
-	/* calculate distance from first vertex to ray origin */
-	VectorSubtract( trace->origin, tt->v[ 0 ].xyz, tvec );
-	
-	/* calculate u parameter and test bounds */
-	u = DotProduct( tvec, pvec ) * invDet;
-	if( u < -BARY_EPSILON || u > (1.0f + BARY_EPSILON) )
-		return qfalse;
-	
-	/* prepare to test v parameter */
-	CrossProduct( tvec, tt->edge1, qvec );
-	
-	/* calculate v parameter and test bounds */
-	v = DotProduct( trace->direction, qvec ) * invDet;
-	if( v < -BARY_EPSILON || (u + v) > (1.0f + BARY_EPSILON) )
-		return qfalse;
-	
-	/* calculate t (depth) */
-	depth = DotProduct( tt->edge2, qvec ) * invDet;
-	//%	if( depth <= SELF_SHADOW_EPSILON || depth >= (trace->dist - SELF_SHADOW_EPSILON) )
-	//%		return qfalse;
-	if( depth <= trace->inhibitRadius || depth >= trace->distance )
-		return qfalse;
-	
-	/* if hitpoint is really close to trace origin (sample point), then check for self-shadowing */
-	if( depth <= SELF_SHADOW_EPSILON )
-	{
-		/* don't self-shadow */
-		for( i = 0; i < trace->numSurfaces; i++ )
-		{
-			if( ti->surfaceNum == trace->surfaces[ i ] )
-				return qfalse;
-		}
-	}
-	
-	/* stack compile flags */
-	trace->compileFlags |= si->compileFlags;
-	
-	/* don't trace against sky */
-	if( si->compileFlags & C_SKY )
-		return qfalse;
-	
-	/* most surfaces are completely opaque */
-	if( !(si->compileFlags & (C_ALPHASHADOW | C_LIGHTFILTER)) ||
-		si->lightImage == NULL || si->lightImage->pixels == NULL )
-	{
-		VectorClear( trace->color );
-		trace->opaque = qtrue;
-		return qtrue;
-	}
-	
-	/* try to avoid double shadows near triangle seams */
-	if( u < -ASLF_EPSILON || u > (1.0f + ASLF_EPSILON) ||
-		v < -ASLF_EPSILON || (u + v) > (1.0f + ASLF_EPSILON) )
-		return qfalse;
-	
-	/* calculate w parameter */
-	w = 1.0f - (u + v);
-	
-	/* calculate st from uvw (barycentric) coordinates */
-	s = w * tt->v[ 0 ].st[ 0 ] + u * tt->v[ 1 ].st[ 0 ] + v * tt->v[ 2 ].st[ 0 ];
-	t = w * tt->v[ 0 ].st[ 1 ] + u * tt->v[ 1 ].st[ 1 ] + v * tt->v[ 2 ].st[ 1 ];
-	s = s - floor( s );
-	t = t - floor( t );
-	is = s * si->lightImage->width;
-	it = t * si->lightImage->height;
-	
-	/* get pixel */
-	pixel = si->lightImage->pixels + 4 * (it * si->lightImage->width + is);
-	
-	/* ydnar: color filter */
-	if( si->compileFlags & C_LIGHTFILTER )
-	{
-		/* filter by texture color */
-		trace->color[ 0 ] *= ((1.0f / 255.0f) * pixel[ 0 ]);
-		trace->color[ 1 ] *= ((1.0f / 255.0f) * pixel[ 1 ]);
-		trace->color[ 2 ] *= ((1.0f / 255.0f) * pixel[ 2 ]);
-	}
-	
-	/* ydnar: alpha filter */
-	if( si->compileFlags & C_ALPHASHADOW )
-	{
-		/* filter by inverse texture alpha */
-		shadow = (1.0f / 255.0f) * (255 - pixel[ 3 ]);
-		trace->color[ 0 ] *= shadow;
-		trace->color[ 1 ] *= shadow;
-		trace->color[ 2 ] *= shadow;
-	}
-	
-	/* check filter for opaque */
-	if( trace->color[ 0 ] <= 0.001f && trace->color[ 1 ] <= 0.001f && trace->color[ 2 ] <= 0.001f )
-	{
-		trace->opaque = qtrue;
-		return qtrue;
-	}
-	
-	/* continue tracing */
-	return qfalse;
-}
-
-
-
-/*
-TraceWinding() - ydnar
-temporary hack
-*/
-
-qboolean TraceWinding( traceWinding_t *tw, trace_t *trace )
-{
-	int				i;
-	traceTriangle_t	tt;
-	
-	
-	/* initial setup */
-	tt.infoNum = tw->infoNum;
-	tt.v[ 0 ] = tw->v[ 0 ];
-	
-	/* walk vertex list */
-	for( i = 1; i + 1 < tw->numVerts; i++ )
-	{
-		/* set verts */
-		tt.v[ 1 ] = tw->v[ i ];
-		tt.v[ 2 ] = tw->v[ i + 1 ];
-		
-		/* find vectors for two edges sharing the first vert */
-		VectorSubtract( tt.v[ 1 ].xyz, tt.v[ 0 ].xyz, tt.edge1 );
-		VectorSubtract( tt.v[ 2 ].xyz, tt.v[ 0 ].xyz, tt.edge2 );
-		
-		/* trace it */
-		if( TraceTriangle( &traceInfos[ tt.infoNum ], &tt, trace ) )
-			return qtrue;
-	}
-	
-	/* done */
-	return qfalse;
-}
-
-
-
-
-/*
-TraceLine_r()
-returns qtrue if something is hit and tracing can stop
-*/
-
-static qboolean TraceLine_r( int nodeNum, vec3_t origin, vec3_t end, trace_t *trace )
-{
-	traceNode_t		*node;
-	int				side;
-	float			front, back, frac;
-	vec3_t			mid;
-	qboolean		r;
-
-	
-	/* bogus node number means solid, end tracing unless testing all */
-	if( nodeNum < 0 )
-	{
-		trace->passSolid = qtrue;
-		return qtrue;
-	}
-	
-	/* get node */
-	node = &traceNodes[ nodeNum ];
-	
-	/* solid? */
-	if( node->type == TRACE_LEAF_SOLID )
-	{
-		trace->passSolid = qtrue;
-		return qtrue;
-	}
-	
-	/* leafnode? */
-	if( node->type < 0 )
-	{
-		/* note leaf and return */	
-		if( node->numItems > 0 && trace->numTestNodes < MAX_TRACE_TEST_NODES )
-			trace->testNodes[ trace->numTestNodes++ ] = nodeNum;
-		return qfalse;
-	}
-	
-	/* ydnar 2003-09-07: don't test branches of the bsp with nothing in them when testall is enabled */
-	if( trace->testAll && node->numItems == 0 )
-		return qfalse;
-	
-	/* classify beginning and end points */
-	switch( node->type )
-	{
-		case PLANE_X:
-			front = origin[ 0 ] - node->plane[ 3 ];
-			back = end[ 0 ] - node->plane[ 3 ];
-			break;
-		
-		case PLANE_Y:
-			front = origin[ 1 ] - node->plane[ 3 ];
-			back = end[ 1 ] - node->plane[ 3 ];
-			break;
-		
-		case PLANE_Z:
-			front = origin[ 2 ] - node->plane[ 3 ];
-			back = end[ 2 ] - node->plane[ 3 ];
-			break;
-		
-		default:
-			front = DotProduct( origin, node->plane ) - node->plane[ 3 ];
-			back = DotProduct( end, node->plane ) - node->plane[ 3 ];
-			break;
-	}
-	
-	/* entirely in front side? */
-	if( front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON )
-		return TraceLine_r( node->children[ 0 ], origin, end, trace );
-	
-	/* entirely on back side? */
-	if( front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON )
-		return TraceLine_r( node->children[ 1 ], origin, end, trace );
-	
-	/* select side */
-	side = front < 0;
-	
-	/* calculate intercept point */
-	frac = front / (front - back);
-	mid[ 0 ] = origin[ 0 ] + (end[ 0 ] - origin[ 0 ]) * frac;
-	mid[ 1 ] = origin[ 1 ] + (end[ 1 ] - origin[ 1 ]) * frac;
-	mid[ 2 ] = origin[ 2 ] + (end[ 2 ] - origin[ 2 ]) * frac;
-	
-	/* fixme: check inhibit radius, then solid nodes and ignore */
-	
-	/* trace first side */
-	r = TraceLine_r( node->children[ side ], origin, mid, trace );
-	if( r )
-		return r;
-	
-	/* trace other side */
-	return TraceLine_r( node->children[ !side ], mid, end, trace );
-}
-
-
-
-/*
-TraceLine() - ydnar
-rewrote this function a bit :)
-*/
-
-void TraceLine( trace_t *trace )
-{
-	int				i, j;
-	traceNode_t		*node;
-	traceTriangle_t	*tt;
-	traceInfo_t		*ti;
-	
-	
-	/* setup output (note: this code assumes the input data is completely filled out) */
-	trace->passSolid = qfalse;
-	trace->opaque = qfalse;
-	trace->compileFlags = 0;
-	trace->numTestNodes = 0;
-	
-	/* early outs */
-	if( !trace->recvShadows || !trace->testOcclusion || trace->distance <= 0.00001f )
-		return;
-	
-	/* trace through nodes */
-	TraceLine_r( headNodeNum, trace->origin, trace->end, trace );
-	if( (trace->passSolid && !trace->testAll) )
-	{
-		trace->opaque = qtrue;
-		return;
-	}
-	
-	/* skip surfaces? */
-	if( noSurfaces )
-		return;
-	
-	/* testall means trace through sky */	
-	if( trace->testAll && trace->numTestNodes < MAX_TRACE_TEST_NODES &&
-		(trace->numSurfaces == 0 || surfaceInfos[ trace->surfaces[ 0 ] ].childSurfaceNum < 0) )
-	{
-		//%	trace->testNodes[ trace->numTestNodes++ ] = skyboxNodeNum;
-		TraceLine_r( skyboxNodeNum, trace->origin, trace->end, trace );
-	}
-	
-	/* walk node list */
-	for( i = 0; i < trace->numTestNodes; i++ )
-	{
-		/* get node */
-		node = &traceNodes[ trace->testNodes[ i ] ];
-		
-		/* walk node item list */
-		for( j = 0; j < node->numItems; j++ )
-		{
-			tt = &traceTriangles[ node->items[ j ] ];
-			ti = &traceInfos[ tt->infoNum ];
-			if( TraceTriangle( ti, tt, trace ) )
-				return;
-			//%	if( TraceWinding( &traceWindings[ node->items[ j ] ], trace ) )
-			//%		return;
-		}
-	}
-}
-
-
-
-/*
-SetupTrace() - ydnar
-sets up certain trace values
-*/
-
-float SetupTrace( trace_t *trace )
-{
-	VectorSubtract( trace->end, trace->origin, trace->displacement );
-	trace->distance = VectorNormalize( trace->displacement, trace->direction );
-	return trace->distance;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define LIGHT_TRACE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+#define Vector2Copy( a, b )		((b)[ 0 ] = (a)[ 0 ], (b)[ 1 ] = (a)[ 1 ])
+#define Vector4Copy( a, b )		((b)[ 0 ] = (a)[ 0 ], (b)[ 1 ] = (a)[ 1 ], (b)[ 2 ] = (a)[ 2 ], (b)[ 3 ] = (a)[ 3 ])
+
+#define MAX_NODE_ITEMS			5
+#define MAX_NODE_TRIANGLES		5
+#define MAX_TRACE_DEPTH			32
+#define MIN_NODE_SIZE			32.0f
+
+#define GROW_TRACE_INFOS		32768		//%	4096
+#define GROW_TRACE_WINDINGS		65536		//%	32768
+#define GROW_TRACE_TRIANGLES	131072		//%	32768
+#define GROW_TRACE_NODES		16384		//%	16384
+#define GROW_NODE_ITEMS			16			//%	256
+
+#define MAX_TW_VERTS			12
+
+#define	TRACE_ON_EPSILON		0.1f
+
+#define TRACE_LEAF				-1
+#define TRACE_LEAF_SOLID		-2
+
+typedef struct traceVert_s
+{
+	vec3_t						xyz;
+	float						st[ 2 ];
+}
+traceVert_t;
+
+typedef struct traceInfo_s
+{
+	shaderInfo_t				*si;
+	int							surfaceNum, castShadows, padding;
+}
+traceInfo_t;
+
+typedef struct traceWinding_s
+{
+	vec4_t						plane;
+	int							infoNum, numVerts;
+	traceVert_t					v[ MAX_TW_VERTS ];
+}
+traceWinding_t;
+
+typedef struct traceTriangle_s
+{
+	vec3_t						edge1, edge2;
+	int							infoNum, padding;
+	traceVert_t					v[ 3 ];
+}
+traceTriangle_t;
+
+typedef struct traceNode_s
+{
+	int							type;
+	vec4_t						plane;
+	vec3_t						mins, maxs;
+	int							children[ 2 ];
+	int							numItems, maxItems;
+	int							*items;
+}
+traceNode_t;
+
+
+int								noDrawContentFlags, noDrawSurfaceFlags, noDrawCompileFlags;
+
+int								numTraceInfos = 0, maxTraceInfos = 0, firstTraceInfo = 0;
+traceInfo_t						*traceInfos = NULL;
+
+int								numTraceWindings = 0, maxTraceWindings = 0, deadWinding = -1;
+traceWinding_t					*traceWindings = NULL;
+
+int								numTraceTriangles = 0, maxTraceTriangles = 0, deadTriangle = -1;
+traceTriangle_t					*traceTriangles = NULL;
+
+int								headNodeNum = 0, skyboxNodeNum = 0, maxTraceDepth = 0, numTraceLeafNodes = 0;
+int								numTraceNodes = 0, maxTraceNodes = 0;
+traceNode_t						*traceNodes = NULL;
+
+
+
+/* -------------------------------------------------------------------------------
+
+allocation and list management
+
+------------------------------------------------------------------------------- */
+
+/*
+AddTraceInfo() - ydnar
+adds a trace info structure to the pool
+*/
+
+static int AddTraceInfo( traceInfo_t *ti )
+{
+	int		num;
+	void	*temp;
+	
+	
+	/* find an existing info */
+	for( num = firstTraceInfo; num < numTraceInfos; num++ )
+	{
+		if( traceInfos[ num ].si == ti->si &&
+			traceInfos[ num ].surfaceNum == ti->surfaceNum &&
+			traceInfos[ num ].castShadows == ti->castShadows )
+			return num;
+	}
+	
+	/* enough space? */
+	if( numTraceInfos >= maxTraceInfos )
+	{
+		/* allocate more room */
+		maxTraceInfos += GROW_TRACE_INFOS;
+		temp = safe_malloc( maxTraceInfos * sizeof( *traceInfos ) );
+		if( traceInfos != NULL )
+		{
+			memcpy( temp, traceInfos, numTraceInfos * sizeof( *traceInfos ) );
+			free( traceInfos );
+		}
+		traceInfos = (traceInfo_t*) temp;
+	}
+	
+	/* add the info */
+	memcpy( &traceInfos[ num ], ti, sizeof( *traceInfos ) );
+	if( num == numTraceInfos )
+		numTraceInfos++;
+	
+	/* return the ti number */
+	return num;
+}
+
+
+
+/*
+AllocTraceNode() - ydnar
+allocates a new trace node
+*/
+
+static int AllocTraceNode( void )
+{
+	traceNode_t	*temp;
+	
+	
+	/* enough space? */
+	if( numTraceNodes >= maxTraceNodes )
+	{
+		/* reallocate more room */
+		maxTraceNodes += GROW_TRACE_NODES;
+		temp = safe_malloc( maxTraceNodes * sizeof( traceNode_t ) );
+		if( traceNodes != NULL )
+		{
+			memcpy( temp, traceNodes, numTraceNodes * sizeof( traceNode_t ) );
+			free( traceNodes );
+		}
+		traceNodes = temp;
+	}
+	
+	/* add the node */
+	memset( &traceNodes[ numTraceNodes ], 0, sizeof( traceNode_t ) );
+	traceNodes[ numTraceNodes ].type = TRACE_LEAF;
+	ClearBounds( traceNodes[ numTraceNodes ].mins, traceNodes[ numTraceNodes ].maxs );
+	numTraceNodes++;
+	
+	/* return the count */
+	return (numTraceNodes - 1);
+}
+
+
+
+/*
+AddTraceWinding() - ydnar
+adds a winding to the raytracing pool
+*/
+
+static int AddTraceWinding( traceWinding_t *tw )
+{
+	int		num;
+	void	*temp;
+	
+	
+	/* check for a dead winding */
+	if( deadWinding >= 0 && deadWinding < numTraceWindings )
+		num = deadWinding;
+	else
+	{
+		/* put winding at the end of the list */
+		num = numTraceWindings;
+		
+		/* enough space? */
+		if( numTraceWindings >= maxTraceWindings )
+		{
+			/* allocate more room */
+			maxTraceWindings += GROW_TRACE_WINDINGS;
+			temp = safe_malloc( maxTraceWindings * sizeof( *traceWindings ) );
+			if( traceWindings != NULL )
+			{
+				memcpy( temp, traceWindings, numTraceWindings * sizeof( *traceWindings ) );
+				free( traceWindings );
+			}
+			traceWindings = (traceWinding_t*) temp;
+		}
+	}
+	
+	/* add the winding */
+	memcpy( &traceWindings[ num ], tw, sizeof( *traceWindings ) );
+	if( num == numTraceWindings )
+		numTraceWindings++;
+	deadWinding = -1;
+	
+	/* return the winding number */
+	return num;
+}
+
+
+
+/*
+AddTraceTriangle() - ydnar
+adds a triangle to the raytracing pool
+*/
+
+static int AddTraceTriangle( traceTriangle_t *tt )
+{
+	int		num;
+	void	*temp;
+	
+	
+	/* check for a dead triangle */
+	if( deadTriangle >= 0 && deadTriangle < numTraceTriangles )
+		num = deadTriangle;
+	else
+	{
+		/* put triangle at the end of the list */
+		num = numTraceTriangles;
+		
+		/* enough space? */
+		if( numTraceTriangles >= maxTraceTriangles )
+		{
+			/* allocate more room */
+			maxTraceTriangles += GROW_TRACE_TRIANGLES;
+			temp = safe_malloc( maxTraceTriangles * sizeof( *traceTriangles ) );
+			if( traceTriangles != NULL )
+			{
+				memcpy( temp, traceTriangles, numTraceTriangles * sizeof( *traceTriangles ) );
+				free( traceTriangles );
+			}
+			traceTriangles = (traceTriangle_t*) temp;
+		}
+	}
+	
+	/* find vectors for two edges sharing the first vert */
+	VectorSubtract( tt->v[ 1 ].xyz, tt->v[ 0 ].xyz, tt->edge1 );
+	VectorSubtract( tt->v[ 2 ].xyz, tt->v[ 0 ].xyz, tt->edge2 );
+	
+	/* add the triangle */
+	memcpy( &traceTriangles[ num ], tt, sizeof( *traceTriangles ) );
+	if( num == numTraceTriangles )
+		numTraceTriangles++;
+	deadTriangle = -1;
+	
+	/* return the triangle number */
+	return num;
+}
+
+
+
+/*
+AddItemToTraceNode() - ydnar
+adds an item reference (winding or triangle) to a trace node
+*/
+
+static int AddItemToTraceNode( traceNode_t *node, int num )
+{
+	void			*temp;
+	
+	
+	/* dummy check */
+	if( num < 0 )
+		return -1;
+	
+	/* enough space? */
+	if( node->numItems >= node->maxItems )
+	{
+		/* allocate more room */
+		if( node == traceNodes )
+			node->maxItems *= 2;
+		else
+			node->maxItems += GROW_NODE_ITEMS;
+		temp = safe_malloc( node->maxItems * sizeof( *node->items ) );
+		if( node->items != NULL )
+		{
+			memcpy( temp, node->items, node->numItems * sizeof( *node->items ) );
+			free( node->items );
+		}
+		node->items = (int*) temp;
+	}
+	
+	/* add the poly */
+	node->items[ node->numItems ] = num;
+	node->numItems++;
+	
+	/* return the count */
+	return (node->numItems - 1);
+}
+
+
+
+
+/* -------------------------------------------------------------------------------
+
+trace node setup
+
+------------------------------------------------------------------------------- */
+
+/*
+SetupTraceNodes_r() - ydnar
+recursively create the initial trace node structure from the bsp tree
+*/
+
+static int SetupTraceNodes_r( int bspNodeNum )
+{
+	int				i, nodeNum, bspLeafNum;
+	bspPlane_t		*plane;
+	bspNode_t 		*bspNode;
+	
+	
+	/* get bsp node and plane */
+	bspNode = &bspNodes[ bspNodeNum ];
+	plane = &bspPlanes[ bspNode->planeNum ];
+	
+	/* allocate a new trace node */
+	nodeNum = AllocTraceNode();
+	
+	/* setup trace node */
+	traceNodes[ nodeNum ].type = PlaneTypeForNormal( plane->normal );
+	VectorCopy( plane->normal, traceNodes[ nodeNum ].plane );
+	traceNodes[ nodeNum ].plane[ 3 ] = plane->dist;
+	
+	/* setup children */
+	for( i = 0; i < 2; i++ )
+	{
+		/* leafnode */
+		if( bspNode->children[ i ] < 0 )
+		{
+			bspLeafNum = -bspNode->children[ i ] - 1;
+			
+			#if 0
+			/* solid leaf */
+			if( bspLeafs[ bspLeafNum ].cluster == -1 )
+				traceNodes[ nodeNum ].children[ i ] = -1;
+			
+			/* passable leaf */
+			else
+				traceNodes[ nodeNum ].children[ i ] = AllocTraceNode();
+			#endif
+			
+			/* new code */
+			traceNodes[ nodeNum ].children[ i ] = AllocTraceNode();
+			if( bspLeafs[ bspLeafNum ].cluster == -1 )
+				traceNodes[ traceNodes[ nodeNum ].children[ i ] ].type = TRACE_LEAF_SOLID;
+		}
+		
+		/* normal node */
+		else
+			traceNodes[ nodeNum ].children[ i ] = SetupTraceNodes_r( bspNode->children[ i ] );
+	}
+	
+	/* return node number */
+	return nodeNum;
+}
+
+
+
+/*
+ClipTraceWinding() - ydnar
+clips a trace winding against a plane into one or two parts
+*/
+
+#define TW_ON_EPSILON	0.25f
+
+void ClipTraceWinding( traceWinding_t *tw, vec4_t plane, traceWinding_t *front, traceWinding_t *back )
+{
+	int				i, j, k;
+	int				sides[ MAX_TW_VERTS ], counts[ 3 ] = { 0, 0, 0 };
+	float			dists[ MAX_TW_VERTS ];
+	float			frac;
+	traceVert_t		*a, *b, mid;
+	
+	
+	/* clear front and back */
+	front->numVerts = 0;
+	back->numVerts = 0;
+	
+	/* classify points */
+	for( i = 0; i < tw->numVerts; i++ )
+	{
+		dists[ i ] = DotProduct( tw->v[ i ].xyz, plane ) - plane[ 3 ];
+		if( dists[ i ] < -TW_ON_EPSILON )
+			sides[ i ] = SIDE_BACK;
+		else if( dists[ i ] > TW_ON_EPSILON )
+			sides[ i ] = SIDE_FRONT;
+		else
+			sides[ i ] = SIDE_ON;
+		counts[ sides[ i ] ]++;
+	}
+	
+	/* entirely on front? */
+	if( counts[ SIDE_BACK ] == 0 )
+		memcpy( front, tw, sizeof( *front ) );
+	
+	/* entirely on back? */
+	else if( counts[ SIDE_FRONT ] == 0 )
+		memcpy( back, tw, sizeof( *back ) );
+	
+	/* straddles the plane */
+	else
+	{
+		/* setup front and back */
+		memcpy( front, tw, sizeof( *front ) );
+		front->numVerts = 0;
+		memcpy( back, tw, sizeof( *back ) ); 
+		back->numVerts = 0;
+		
+		/* split the winding */
+		for( i = 0; i < tw->numVerts; i++ )
+		{
+			/* radix */
+			j = (i + 1) % tw->numVerts;
+			
+			/* get verts */
+			a = &tw->v[ i ];
+			b = &tw->v[ j ];
+			
+			/* handle points on the splitting plane */
+			switch( sides[ i ] )
+			{
+				case SIDE_FRONT:
+					if( front->numVerts >= MAX_TW_VERTS )
+						Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
+					front->v[ front->numVerts++ ] = *a;
+					break;
+				
+				case SIDE_BACK:
+					if( back->numVerts >= MAX_TW_VERTS )
+						Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
+					back->v[ back->numVerts++ ] = *a;
+					break;
+				
+				case SIDE_ON:
+					if( front->numVerts >= MAX_TW_VERTS || back->numVerts >= MAX_TW_VERTS )
+						Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
+					front->v[ front->numVerts++ ] = *a;
+					back->v[ back->numVerts++ ] = *a;
+					continue;
+			}
+			
+			/* check next point to see if we need to split the edge */
+			if( sides[ j ] == SIDE_ON || sides[ j ] == sides[ i ] )
+				continue;
+			
+			/* check limit */
+			if( front->numVerts >= MAX_TW_VERTS || back->numVerts >= MAX_TW_VERTS )
+				Error( "MAX_TW_VERTS (%d) exceeded", MAX_TW_VERTS );
+			
+			/* generate a split point */
+			frac = dists[ i ] / (dists[ i ] - dists[ j ]);
+			for( k = 0; k < 3; k++ )
+			{
+				/* minimize fp precision errors */
+				if( plane[ k ] == 1.0f )
+					mid.xyz[ k ] = plane[ 3 ];
+				else if( plane[ k ] == -1.0f )
+					mid.xyz[ k ] = -plane[ 3 ];
+				else
+					mid.xyz[ k ] = a->xyz[ k ] + frac * (b->xyz[ k ] - a->xyz[ k ]);
+				
+				/* set texture coordinates */
+				if( k > 1 )
+					continue;
+				mid.st[ 0 ] = a->st[ 0 ] + frac * (b->st[ 0 ] - a->st[ 0 ]);
+				mid.st[ 1 ] = a->st[ 1 ] + frac * (b->st[ 1 ] - a->st[ 1 ]);
+			}
+			
+			/* copy midpoint to front and back polygons */
+			front->v[ front->numVerts++ ] = mid;
+			back->v[ back->numVerts++ ] = mid;
+		}
+	}
+}
+
+
+
+/*
+FilterPointToTraceNodes_r() - ydnar
+debugging tool
+*/
+
+static int FilterPointToTraceNodes_r( vec3_t pt, int nodeNum )
+{
+	float			dot;
+	traceNode_t		*node;
+	
+	
+	if( nodeNum < 0 || nodeNum >= numTraceNodes )
+		return -1;
+	
+	node = &traceNodes[ nodeNum ];
+	
+	if( node->type >= 0 )
+	{
+		dot = DotProduct( pt, node->plane ) - node->plane[ 3 ];
+		if( dot > -0.001f )
+			FilterPointToTraceNodes_r( pt, node->children[ 0 ] );
+		if( dot < 0.001f )
+			FilterPointToTraceNodes_r( pt, node->children[ 1 ] );
+		return -1;
+	}
+	
+	Sys_Printf( "%d ", nodeNum );
+	
+	return nodeNum;
+}
+
+
+
+/*
+FilterTraceWindingIntoNodes_r() - ydnar
+filters a trace winding into the raytracing tree
+*/
+
+static void FilterTraceWindingIntoNodes_r( traceWinding_t *tw, int nodeNum )
+{
+	int				num;
+	vec4_t			plane1, plane2, reverse;
+	traceNode_t		*node;
+	traceWinding_t	front, back;
+	
+	
+	/* don't filter if passed a bogus node (solid, etc) */
+	if( nodeNum < 0 || nodeNum >= numTraceNodes )
+		return;
+	
+	/* get node */
+	node = &traceNodes[ nodeNum ];
+	
+	/* is this a decision node? */
+	if( node->type >= 0 )
+	{	
+		/* create winding plane if necessary, filtering out bogus windings as well */
+		if( nodeNum == headNodeNum )
+		{
+			if( !PlaneFromPoints( tw->plane, tw->v[ 0 ].xyz, tw->v[ 1 ].xyz, tw->v[ 2 ].xyz ) )
+				return;
+		}
+	
+		/* validate the node */
+		if( node->children[ 0 ] == 0 || node->children[ 1 ] == 0 )
+			Error( "Invalid tracenode: %d", nodeNum );
+		
+		/* get node plane */
+		Vector4Copy( node->plane, plane1 );
+		
+		/* get winding plane */
+		Vector4Copy( tw->plane, plane2 );
+		
+		/* invert surface plane */
+		VectorSubtract( vec3_origin, plane2, reverse );
+		reverse[ 3 ] = -plane2[ 3 ];
+		
+		/* front only */
+		if( DotProduct( plane1, plane2 ) > 0.999f && fabs( plane1[ 3 ] - plane2[ 3 ] ) < 0.001f )
+		{
+			FilterTraceWindingIntoNodes_r( tw, node->children[ 0 ] );
+			return;
+		}
+		
+		/* back only */
+		if( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f )
+		{
+			FilterTraceWindingIntoNodes_r( tw, node->children[ 1 ] );
+			return;
+		}
+		
+		/* clip the winding by node plane */
+		ClipTraceWinding( tw, plane1, &front, &back );
+		
+		/* filter by node plane */
+		if( front.numVerts >= 3 )
+			FilterTraceWindingIntoNodes_r( &front, node->children[ 0 ] );
+		if( back.numVerts >= 3 )
+			FilterTraceWindingIntoNodes_r( &back, node->children[ 1 ] );
+		
+		/* return to caller */
+		return;
+	}
+	
+	/* add winding to leaf node */
+	num = AddTraceWinding( tw );
+	AddItemToTraceNode( node, num );
+}
+
+
+
+/*
+SubdivideTraceNode_r() - ydnar
+recursively subdivides a tracing node until it meets certain size and complexity criteria
+*/
+
+static void SubdivideTraceNode_r( int nodeNum, int depth )
+{
+	int				i, j, count, num, frontNum, backNum, type;
+	vec3_t			size;
+	float			dist;
+	double			average[ 3 ];
+	traceNode_t		*node, *frontNode, *backNode;
+	traceWinding_t	*tw, front, back;
+	
+	
+	/* dummy check */
+	if( nodeNum < 0 || nodeNum >= numTraceNodes )
+		return;
+	
+	/* get node */
+	node = &traceNodes[ nodeNum ];
+	
+	/* runaway recursion check */
+	if( depth >= MAX_TRACE_DEPTH )
+	{
+		//%	Sys_Printf( "Depth: (%d items)\n", node->numItems );
+		numTraceLeafNodes++;
+		return;
+	}
+	depth++;
+	
+	/* is this a decision node? */
+	if( node->type >= 0 )
+	{
+		/* subdivide children */
+		frontNum = node->children[ 0 ];
+		backNum = node->children[ 1 ];
+		SubdivideTraceNode_r( frontNum, depth );
+		SubdivideTraceNode_r( backNum, depth );
+		return;
+	}
+	
+	/* bound the node */
+	ClearBounds( node->mins, node->maxs );
+	VectorClear( average );
+	count = 0;
+	for( i = 0; i < node->numItems; i++ )
+	{
+		/* get winding */
+		tw = &traceWindings[ node->items[ i ] ];
+		
+		/* walk its verts */
+		for( j = 0; j < tw->numVerts; j++ )
+		{
+			AddPointToBounds( tw->v[ j ].xyz, node->mins, node->maxs );
+			average[ 0 ] += tw->v[ j ].xyz[ 0 ];
+			average[ 1 ] += tw->v[ j ].xyz[ 1 ];
+			average[ 2 ] += tw->v[ j ].xyz[ 2 ];
+			count++;
+		}
+	}
+	
+	/* check triangle limit */
+	//%	if( node->numItems <= MAX_NODE_ITEMS )
+	if( (count - (node->numItems * 2)) < MAX_NODE_TRIANGLES )
+	{
+		//%	Sys_Printf( "Limit: (%d triangles)\n", (count - (node->numItems * 2)) );
+		numTraceLeafNodes++;
+		return;
+	}
+	
+	/* the largest dimension of the bounding box will be the split axis */
+	VectorSubtract( node->maxs, node->mins, size );
+	if( size[ 0 ] >= size[ 1 ] && size[ 0 ] >= size[ 2 ] )
+		type = PLANE_X;
+	else if( size[ 1 ] >= size[ 0 ] && size[ 1 ] >= size[ 2 ] )
+		type = PLANE_Y;
+	else
+		type = PLANE_Z;
+	
+	/* don't split small nodes */
+	if( size[ type ] <= MIN_NODE_SIZE )
+	{
+		//%	Sys_Printf( "Limit: %f %f %f (%d items)\n", size[ 0 ], size[ 1 ], size[ 2 ], node->numItems );
+		numTraceLeafNodes++;
+		return;
+	}
+	
+	/* set max trace depth */
+	if( depth > maxTraceDepth )
+		maxTraceDepth = depth;
+	
+	/* snap the average */
+	dist = floor( average[ type ] / count );
+	
+	/* dummy check it */
+	if( dist <= node->mins[ type ] || dist >= node->maxs[ type ] )
+		dist = floor( 0.5f * (node->mins[ type ] + node->maxs[ type ]) );
+	
+	/* allocate child nodes */
+	frontNum = AllocTraceNode();
+	backNum = AllocTraceNode();
+	
+	/* reset pointers */
+	node = &traceNodes[ nodeNum ];
+	frontNode = &traceNodes[ frontNum ];
+	backNode = &traceNodes[ backNum ];
+	
+	/* attach children */
+	node->type = type;
+	node->plane[ type ] = 1.0f;
+	node->plane[ 3 ] = dist;
+	node->children[ 0 ] = frontNum;
+	node->children[ 1 ] = backNum;
+	
+	/* setup front node */
+	frontNode->maxItems = (node->maxItems >> 1);
+	frontNode->items = safe_malloc( frontNode->maxItems * sizeof( *frontNode->items ) );
+	
+	/* setup back node */
+	backNode->maxItems = (node->maxItems >> 1);
+	backNode->items = safe_malloc( backNode->maxItems * sizeof( *backNode->items ) );
+	
+	/* filter windings into child nodes */
+	for( i = 0; i < node->numItems; i++ )
+	{
+		/* get winding */
+		tw = &traceWindings[ node->items[ i ] ];
+		
+		/* clip the winding by the new split plane */
+		ClipTraceWinding( tw, node->plane, &front, &back );
+		
+		/* kill the existing winding */
+		if( front.numVerts >= 3 || back.numVerts >= 3 )
+			deadWinding = node->items[ i ];
+		
+		/* add front winding */
+		if( front.numVerts >= 3 )
+		{
+			num = AddTraceWinding( &front );
+			AddItemToTraceNode( frontNode, num );
+		}
+		
+		/* add back winding */
+		if( back.numVerts >= 3 )
+		{
+			num = AddTraceWinding( &back );
+			AddItemToTraceNode( backNode, num );
+		}
+	}
+	
+	/* free original node winding list */
+	node->numItems = 0;
+	node->maxItems = 0;
+	free( node->items );
+	node->items = NULL;
+	
+	/* check children */
+	if( frontNode->numItems <= 0 )
+	{
+		frontNode->maxItems = 0;
+		free( frontNode->items );
+		frontNode->items = NULL;
+	}
+	
+	if( backNode->numItems <= 0 )
+	{
+		backNode->maxItems = 0;
+		free( backNode->items );
+		backNode->items = NULL;
+	}
+	
+	/* subdivide children */
+	SubdivideTraceNode_r( frontNum, depth );
+	SubdivideTraceNode_r( backNum, depth );
+}
+
+
+
+/*
+TriangulateTraceNode_r()
+optimizes the tracing data by changing trace windings into triangles
+*/
+
+static int TriangulateTraceNode_r( int nodeNum )
+{
+	int				i, j, num, frontNum, backNum, numWindings, *windings;
+	traceNode_t		*node;
+	traceWinding_t	*tw;
+	traceTriangle_t	tt;
+	
+	
+	/* dummy check */
+	if( nodeNum < 0 || nodeNum >= numTraceNodes )
+		return 0;
+	
+	/* get node */
+	node = &traceNodes[ nodeNum ];
+	
+	/* is this a decision node? */
+	if( node->type >= 0 )
+	{
+		/* triangulate children */
+		frontNum = node->children[ 0 ];
+		backNum = node->children[ 1 ];
+		node->numItems = TriangulateTraceNode_r( frontNum );
+		node->numItems += TriangulateTraceNode_r( backNum );
+		return node->numItems;
+	}
+	
+	/* empty node? */
+	if( node->numItems == 0 )
+	{
+		node->maxItems = 0;
+		if( node->items != NULL )
+			free( node->items );
+		return node->numItems;
+	}
+	
+	/* store off winding data */
+	numWindings = node->numItems;
+	windings = node->items;
+	
+	/* clear it */
+	node->numItems = 0;
+	node->maxItems = numWindings * 2;
+	node->items = safe_malloc( node->maxItems * sizeof( tt ) );
+	
+	/* walk winding list */
+	for( i = 0; i < numWindings; i++ )
+	{
+		/* get winding */
+		tw = &traceWindings[ windings[ i ] ];
+		
+		/* initial setup */
+		tt.infoNum = tw->infoNum;
+		tt.v[ 0 ] = tw->v[ 0 ];
+		
+		/* walk vertex list */
+		for( j = 1; j + 1 < tw->numVerts; j++ )
+		{
+			/* set verts */
+			tt.v[ 1 ] = tw->v[ j ];
+			tt.v[ 2 ] = tw->v[ j + 1 ];
+			
+			/* find vectors for two edges sharing the first vert */
+			VectorSubtract( tt.v[ 1 ].xyz, tt.v[ 0 ].xyz, tt.edge1 );
+			VectorSubtract( tt.v[ 2 ].xyz, tt.v[ 0 ].xyz, tt.edge2 );
+			
+			/* add it to the node */
+			num = AddTraceTriangle( &tt );
+			AddItemToTraceNode( node, num );
+		}
+	}
+	
+	/* free windings */
+	if( windings != NULL )
+		free( windings );
+	
+	/* return item count */
+	return node->numItems;
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+shadow casting item setup (triangles, patches, entities)
+
+------------------------------------------------------------------------------- */
+
+/*
+PopulateWithBSPModel() - ydnar
+filters a bsp model's surfaces into the raytracing tree
+*/
+
+static void PopulateWithBSPModel( bspModel_t *model, m4x4_t transform )
+{
+	int					i, j, x, y, pw[ 5 ], r, nodeNum;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	bspDrawVert_t		*verts;
+	int					*indexes;
+	mesh_t				srcMesh, *mesh, *subdivided;
+	traceInfo_t			ti;
+	traceWinding_t		tw;
+	
+	
+	/* dummy check */
+	if( model == NULL || transform == NULL )
+		return;
+	
+	/* walk the list of surfaces in this model and fill out the info structs */
+	for( i = 0; i < model->numBSPSurfaces; i++ )
+	{
+		/* get surface and info */
+		ds = &bspDrawSurfaces[ model->firstBSPSurface + i ];
+		info = &surfaceInfos[ model->firstBSPSurface + i ];
+		if( info->si == NULL )
+			continue;
+		
+		/* no shadows */
+		if( !info->castShadows )
+			continue;
+		
+		/* patchshadows? */
+		if( ds->surfaceType == MST_PATCH && patchShadows == qfalse )
+			continue;
+		
+		/* some surfaces in the bsp might have been tagged as nodraw, with a bogus shader */
+		if( (bspShaders[ ds->shaderNum ].contentFlags & noDrawContentFlags) || 
+			(bspShaders[ ds->shaderNum ].surfaceFlags & noDrawSurfaceFlags) )
+			continue;
+		
+		/* translucent surfaces that are neither alphashadow or lightfilter don't cast shadows */
+		if( (info->si->compileFlags & C_NODRAW) )
+			continue;
+		if( (info->si->compileFlags & C_TRANSLUCENT) &&
+			!(info->si->compileFlags & C_ALPHASHADOW) && 
+			!(info->si->compileFlags & C_LIGHTFILTER) )
+			continue;
+		
+		/* setup trace info */
+		ti.si = info->si;
+		ti.castShadows = info->castShadows;
+		ti.surfaceNum = model->firstBSPBrush + i;
+		
+		/* setup trace winding */
+		memset( &tw, 0, sizeof( tw ) );
+		tw.infoNum = AddTraceInfo( &ti );
+		tw.numVerts = 3;
+		
+		/* choose which node (normal or skybox) */
+		if( info->parentSurfaceNum >= 0 )
+			nodeNum = skyboxNodeNum;
+		else
+			nodeNum = headNodeNum;
+		
+		/* switch on type */
+		switch( ds->surfaceType )
+		{
+			/* handle patches */
+			case MST_PATCH:
+				/* subdivide the surface */
+				srcMesh.width = ds->patchWidth;
+				srcMesh.height = ds->patchHeight;
+				srcMesh.verts = &bspDrawVerts[ ds->firstVert ];
+				//%	subdivided = SubdivideMesh( srcMesh, 8, 512 );
+				subdivided = SubdivideMesh2( srcMesh, info->patchIterations );
+				
+				/* fit it to the curve and remove colinear verts on rows/columns */
+				PutMeshOnCurve( *subdivided );
+				mesh = RemoveLinearMeshColumnsRows( subdivided );
+				FreeMesh( subdivided );
+				
+				/* set verts */
+				verts = mesh->verts;
+				
+				/* subdivide each quad to place the models */
+				for( y = 0; y < (mesh->height - 1); y++ )
+				{
+					for( x = 0; x < (mesh->width - 1); x++ )
+					{
+						/* set indexes */
+						pw[ 0 ] = x + (y * mesh->width);
+						pw[ 1 ] = x + ((y + 1) * mesh->width);
+						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+						pw[ 3 ] = x + 1 + (y * mesh->width);
+						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+						
+						/* set radix */
+						r = (x + y) & 1;
+						
+						/* make first triangle */
+						VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz );
+						Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st );
+						VectorCopy( verts[ pw[ r + 1 ] ].xyz, tw.v[ 1 ].xyz );
+						Vector2Copy( verts[ pw[ r + 1 ] ].st, tw.v[ 1 ].st );
+						VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 2 ].xyz );
+						Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 2 ].st );
+						m4x4_transform_point( transform, tw.v[ 0 ].xyz );
+						m4x4_transform_point( transform, tw.v[ 1 ].xyz );
+						m4x4_transform_point( transform, tw.v[ 2 ].xyz );
+						FilterTraceWindingIntoNodes_r( &tw, nodeNum );
+						
+						/* make second triangle */
+						VectorCopy( verts[ pw[ r + 0 ] ].xyz, tw.v[ 0 ].xyz );
+						Vector2Copy( verts[ pw[ r + 0 ] ].st, tw.v[ 0 ].st );
+						VectorCopy( verts[ pw[ r + 2 ] ].xyz, tw.v[ 1 ].xyz );
+						Vector2Copy( verts[ pw[ r + 2 ] ].st, tw.v[ 1 ].st );
+						VectorCopy( verts[ pw[ r + 3 ] ].xyz, tw.v[ 2 ].xyz );
+						Vector2Copy( verts[ pw[ r + 3 ] ].st, tw.v[ 2 ].st );
+						m4x4_transform_point( transform, tw.v[ 0 ].xyz );
+						m4x4_transform_point( transform, tw.v[ 1 ].xyz );
+						m4x4_transform_point( transform, tw.v[ 2 ].xyz );
+						FilterTraceWindingIntoNodes_r( &tw, nodeNum );
+					}
+				}
+				
+				/* free the subdivided mesh */
+				FreeMesh( mesh );
+				break;
+			
+			/* handle triangle surfaces */
+			case MST_TRIANGLE_SOUP:
+			case MST_PLANAR:
+				/* set verts and indexes */
+				verts = &bspDrawVerts[ ds->firstVert ];
+				indexes = &bspDrawIndexes[ ds->firstIndex ];
+				
+				/* walk the triangle list */
+				for( j = 0; j < ds->numIndexes; j += 3 )
+				{
+					VectorCopy( verts[ indexes[ j ] ].xyz, tw.v[ 0 ].xyz );
+					Vector2Copy( verts[ indexes[ j ] ].st, tw.v[ 0 ].st );
+					VectorCopy( verts[ indexes[ j + 1 ] ].xyz, tw.v[ 1 ].xyz );
+					Vector2Copy( verts[ indexes[ j + 1 ] ].st, tw.v[ 1 ].st );
+					VectorCopy( verts[ indexes[ j + 2 ] ].xyz, tw.v[ 2 ].xyz );
+					Vector2Copy( verts[ indexes[ j + 2 ] ].st, tw.v[ 2 ].st );
+					m4x4_transform_point( transform, tw.v[ 0 ].xyz );
+					m4x4_transform_point( transform, tw.v[ 1 ].xyz );
+					m4x4_transform_point( transform, tw.v[ 2 ].xyz );
+					FilterTraceWindingIntoNodes_r( &tw, nodeNum );
+				}
+				break;
+			
+			/* other surface types do not cast shadows */
+			default:
+				break;
+		}
+	}
+}
+
+
+
+/*
+PopulateWithPicoModel() - ydnar
+filters a picomodel's surfaces into the raytracing tree
+*/
+
+static void PopulateWithPicoModel( int castShadows, picoModel_t *model, m4x4_t transform )
+{
+	int					i, j, k, numSurfaces, numIndexes;
+	picoSurface_t		*surface;
+	picoShader_t		*shader;
+	picoVec_t			*xyz, *st;
+	picoIndex_t			*indexes;
+	traceInfo_t			ti;
+	traceWinding_t		tw;
+	
+	
+	/* dummy check */
+	if( model == NULL || transform == NULL )
+		return;
+	
+	/* get info */
+	numSurfaces = PicoGetModelNumSurfaces( model );
+	
+	/* walk the list of surfaces in this model and fill out the info structs */
+	for( i = 0; i < numSurfaces; i++ )
+	{
+		/* get surface */
+		surface = PicoGetModelSurface( model, i );
+		if( surface == NULL )
+			continue;
+		
+		/* only handle triangle surfaces initially (fixme: support patches) */
+		if( PicoGetSurfaceType( surface ) != PICO_TRIANGLES )
+			continue;
+		
+		/* get shader (fixme: support shader remapping) */
+		shader = PicoGetSurfaceShader( surface );
+		if( shader == NULL )
+			continue;
+		ti.si = ShaderInfoForShader( PicoGetShaderName( shader ) );
+		if( ti.si == NULL )
+			continue;
+		
+		/* translucent surfaces that are neither alphashadow or lightfilter don't cast shadows */
+		if( (ti.si->compileFlags & C_NODRAW) )
+			continue;
+		if( (ti.si->compileFlags & C_TRANSLUCENT) &&
+			!(ti.si->compileFlags & C_ALPHASHADOW) && 
+			!(ti.si->compileFlags & C_LIGHTFILTER) )
+			continue;
+		
+		/* setup trace info */
+		ti.castShadows = castShadows;
+		ti.surfaceNum = -1;
+		
+		/* setup trace winding */
+		memset( &tw, 0, sizeof( tw ) );
+		tw.infoNum = AddTraceInfo( &ti );
+		tw.numVerts = 3;
+		
+		/* get info */
+		numIndexes = PicoGetSurfaceNumIndexes( surface );
+		indexes = PicoGetSurfaceIndexes( surface, 0 );
+		
+		/* walk the triangle list */
+		for( j = 0; j < numIndexes; j += 3, indexes += 3 )
+		{
+			for( k = 0; k < 3; k++ )
+			{
+				xyz = PicoGetSurfaceXYZ( surface, indexes[ k ] );
+				st = PicoGetSurfaceST( surface, 0, indexes[ k ] );
+				VectorCopy( xyz, tw.v[ k ].xyz );
+				Vector2Copy( st, tw.v[ k ].st );
+				m4x4_transform_point( transform, tw.v[ k ].xyz );
+			}
+			FilterTraceWindingIntoNodes_r( &tw, headNodeNum );
+		}
+	}
+}
+
+
+
+/*
+PopulateTraceNodes() - ydnar
+fills the raytracing tree with world and entity occluders
+*/
+
+static void PopulateTraceNodes( void )
+{
+	int				i, m, frame, castShadows;
+	float			temp;
+	entity_t		*e;
+	const char		*value;
+	picoModel_t		*model;
+	vec3_t			origin, scale, angles;
+	m4x4_t			transform;
+
+	
+	/* add worldspawn triangles */
+	m4x4_identity( transform );
+	PopulateWithBSPModel( &bspModels[ 0 ], transform );
+	
+	/* walk each entity list */
+	for( i = 1; i < numEntities; i++ )
+	{
+		/* get entity */
+		e = &entities[ i ];
+		
+		/* get shadow flags */
+		castShadows = ENTITY_CAST_SHADOWS;
+		GetEntityShadowFlags( e, NULL, &castShadows, NULL );
+		
+		/* early out? */
+		if( !castShadows )
+			continue;
+		
+		/* get entity origin */
+		GetVectorForKey( e, "origin", origin );
+		
+		/* get scale */
+		scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = 1.0f;
+		temp = FloatForKey( e, "modelscale" );
+		if( temp != 0.0f )
+			scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = temp;
+		value = ValueForKey( e, "modelscale_vec" );
+		if( value[ 0 ] != '\0' )
+			sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
+		
+		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
+		angles[ 0 ] = angles[ 1 ] = angles[ 2 ] = 0.0f;
+		angles[ 2 ] = FloatForKey( e, "angle" );
+		value = ValueForKey( e, "angles" );
+		if( value[ 0 ] != '\0' )
+			sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
+		
+		/* set transform matrix (thanks spog) */
+		m4x4_identity( transform );
+		m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
+		
+		/* hack: Stable-1_2 and trunk have differing row/column major matrix order
+		   this transpose is necessary with Stable-1_2
+		   uncomment the following line with old m4x4_t (non 1.3/spog_branch) code */
+		//%	m4x4_transpose( transform );
+		
+		/* get model */
+		value = ValueForKey( e, "model" );
+		
+		/* switch on model type */
+		switch( value[ 0 ] )
+		{
+			/* no model */
+			case '\0':
+				break;
+			
+			/* bsp model */
+			case '*':
+				m = atoi( &value[ 1 ] );
+				if( m <= 0 || m >= numBSPModels )
+					continue;
+				PopulateWithBSPModel( &bspModels[ m ], transform );
+				break;
+			
+			/* external model */
+			default:
+				frame = IntForKey( e, "_frame" );
+				model = LoadModel( (char*) value, frame );
+				if( model == NULL )
+					continue;
+				PopulateWithPicoModel( castShadows, model, transform );
+				continue;
+		}
+		
+		/* get model2 */
+		value = ValueForKey( e, "model2" );
+		
+		/* switch on model type */
+		switch( value[ 0 ] )
+		{
+			/* no model */
+			case '\0':
+				break;
+			
+			/* bsp model */
+			case '*':
+				m = atoi( &value[ 1 ] );
+				if( m <= 0 || m >= numBSPModels )
+					continue;
+				PopulateWithBSPModel( &bspModels[ m ], transform );
+				break;
+			
+			/* external model */
+			default:
+				frame = IntForKey( e, "_frame2" );
+				model = LoadModel( (char*) value, frame );
+				if( model == NULL )
+					continue;
+				PopulateWithPicoModel( castShadows, model, transform );
+				continue;
+		}
+	}
+}
+
+
+
+
+/* -------------------------------------------------------------------------------
+
+trace initialization
+
+------------------------------------------------------------------------------- */
+
+/*
+SetupTraceNodes() - ydnar
+creates a balanced bsp with axis-aligned splits for efficient raytracing
+*/
+
+void SetupTraceNodes( void )
+{
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- SetupTraceNodes ---\n" );
+	
+	/* find nodraw bit */
+	noDrawContentFlags = noDrawSurfaceFlags = noDrawCompileFlags = 0;
+	ApplySurfaceParm( "nodraw", &noDrawContentFlags, &noDrawSurfaceFlags, &noDrawCompileFlags );
+	
+	/* create the baseline raytracing tree from the bsp tree */
+	headNodeNum = SetupTraceNodes_r( 0 );
+	
+	/* create outside node for skybox surfaces */
+	skyboxNodeNum = AllocTraceNode();
+	
+	/* populate the tree with triangles from the world and shadow casting entities */
+	PopulateTraceNodes();
+	
+	/* create the raytracing bsp */
+	if( loMem == qfalse )
+	{
+		SubdivideTraceNode_r( headNodeNum, 0 );
+		SubdivideTraceNode_r( skyboxNodeNum, 0 );
+	}
+	
+	/* create triangles from the trace windings */
+	TriangulateTraceNode_r( headNodeNum );
+	TriangulateTraceNode_r( skyboxNodeNum );
+	
+	/* emit some stats */
+	//%	Sys_FPrintf( SYS_VRB, "%9d original triangles\n", numOriginalTriangles );
+	Sys_FPrintf( SYS_VRB, "%9d trace windings (%.2fMB)\n", numTraceWindings, (float) (numTraceWindings * sizeof( *traceWindings )) / (1024.0f * 1024.0f) );
+	Sys_FPrintf( SYS_VRB, "%9d trace triangles (%.2fMB)\n", numTraceTriangles, (float) (numTraceTriangles * sizeof( *traceTriangles )) / (1024.0f * 1024.0f) );
+	Sys_FPrintf( SYS_VRB, "%9d trace nodes (%.2fMB)\n", numTraceNodes, (float) (numTraceNodes * sizeof( *traceNodes )) / (1024.0f * 1024.0f) );
+	Sys_FPrintf( SYS_VRB, "%9d leaf nodes (%.2fMB)\n", numTraceLeafNodes, (float) (numTraceLeafNodes * sizeof( *traceNodes )) / (1024.0f * 1024.0f) );
+	//%	Sys_FPrintf( SYS_VRB, "%9d average triangles per leaf node\n", numTraceTriangles / numTraceLeafNodes );
+	Sys_FPrintf( SYS_VRB, "%9d average windings per leaf node\n", numTraceWindings / (numTraceLeafNodes + 1) );
+	Sys_FPrintf( SYS_VRB, "%9d max trace depth\n", maxTraceDepth );
+	
+	/* free trace windings */
+	free( traceWindings );
+	numTraceWindings = 0;
+	maxTraceWindings = 0;
+	deadWinding = -1;
+	
+	/* debug code: write out trace triangles to an alias obj file */
+	#if 0
+	{
+		int				i, j;
+		FILE			*file;
+		char			filename[ 1024 ];
+		traceWinding_t	*tw;
+		
+		
+		/* open the file */
+		strcpy( filename, source );
+		StripExtension( filename );
+		strcat( filename, ".lin" );
+		Sys_Printf( "Opening light trace file %s...\n", filename );
+		file = fopen( filename, "w" );
+		if( file == NULL )
+			Error( "Error opening %s for writing", filename );
+		
+		/* walk node list */
+		for( i = 0; i < numTraceWindings; i++ )
+		{
+			tw = &traceWindings[ i ];
+			for( j = 0; j < tw->numVerts + 1; j++ )
+				fprintf( file, "%f %f %f\n",
+					tw->v[ j % tw->numVerts ].xyz[ 0 ], tw->v[ j % tw->numVerts ].xyz[ 1 ], tw->v[ j % tw->numVerts ].xyz[ 2 ] );
+		}
+		
+		/* close it */
+		fclose( file );
+	}
+	#endif
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+raytracer
+
+------------------------------------------------------------------------------- */
+
+/*
+TraceTriangle()
+based on code written by william 'spog' joseph
+based on code originally written by tomas moller and ben trumbore, journal of graphics tools, 2(1):21-28, 1997
+*/
+
+#define BARY_EPSILON			0.01f
+#define ASLF_EPSILON			0.0001f	/* so to not get double shadows */
+#define COPLANAR_EPSILON		0.25f	//%	0.000001f
+#define NEAR_SHADOW_EPSILON		1.5f	//%	1.25f
+#define SELF_SHADOW_EPSILON		0.5f
+
+qboolean TraceTriangle( traceInfo_t *ti, traceTriangle_t *tt, trace_t *trace )
+{
+	int				i;
+	float			tvec[ 3 ], pvec[ 3 ], qvec[ 3 ];
+	float			det, invDet, depth;
+	float			u, v, w, s, t;
+	int				is, it;
+	byte			*pixel;
+	float			shadow;
+	shaderInfo_t	*si;
+	
+	
+	/* don't double-trace against sky */
+	si = ti->si;
+	if( trace->compileFlags & si->compileFlags & C_SKY )
+		return qfalse;
+	
+	/* receive shadows from worldspawn group only */
+	if( trace->recvShadows == 1 )
+	{
+		if( ti->castShadows != 1 )
+			return qfalse;
+	}
+	
+	/* receive shadows from same group and worldspawn group */
+	else if( trace->recvShadows > 1 )
+	{
+		if( ti->castShadows != 1 && abs( ti->castShadows ) != abs( trace->recvShadows ) )
+			return qfalse;
+		//%	Sys_Printf( "%d:%d ", tt->castShadows, trace->recvShadows );
+	}
+	
+	/* receive shadows from the same group only (< 0) */
+	else
+	{
+		if( abs( ti->castShadows ) != abs( trace->recvShadows ) )
+			return qfalse;
+	}
+	
+	/* begin calculating determinant - also used to calculate u parameter */
+	CrossProduct( trace->direction, tt->edge2, pvec );
+	
+	/* if determinant is near zero, trace lies in plane of triangle */
+	det = DotProduct( tt->edge1, pvec );
+	
+	/* the non-culling branch */
+	if( det > -COPLANAR_EPSILON && det < COPLANAR_EPSILON )
+		return qfalse;
+	invDet = 1.0f / det;
+	
+	/* calculate distance from first vertex to ray origin */
+	VectorSubtract( trace->origin, tt->v[ 0 ].xyz, tvec );
+	
+	/* calculate u parameter and test bounds */
+	u = DotProduct( tvec, pvec ) * invDet;
+	if( u < -BARY_EPSILON || u > (1.0f + BARY_EPSILON) )
+		return qfalse;
+	
+	/* prepare to test v parameter */
+	CrossProduct( tvec, tt->edge1, qvec );
+	
+	/* calculate v parameter and test bounds */
+	v = DotProduct( trace->direction, qvec ) * invDet;
+	if( v < -BARY_EPSILON || (u + v) > (1.0f + BARY_EPSILON) )
+		return qfalse;
+	
+	/* calculate t (depth) */
+	depth = DotProduct( tt->edge2, qvec ) * invDet;
+	//%	if( depth <= SELF_SHADOW_EPSILON || depth >= (trace->dist - SELF_SHADOW_EPSILON) )
+	//%		return qfalse;
+	if( depth <= trace->inhibitRadius || depth >= trace->distance )
+		return qfalse;
+	
+	/* if hitpoint is really close to trace origin (sample point), then check for self-shadowing */
+	if( depth <= SELF_SHADOW_EPSILON )
+	{
+		/* don't self-shadow */
+		for( i = 0; i < trace->numSurfaces; i++ )
+		{
+			if( ti->surfaceNum == trace->surfaces[ i ] )
+				return qfalse;
+		}
+	}
+	
+	/* stack compile flags */
+	trace->compileFlags |= si->compileFlags;
+	
+	/* don't trace against sky */
+	if( si->compileFlags & C_SKY )
+		return qfalse;
+	
+	/* most surfaces are completely opaque */
+	if( !(si->compileFlags & (C_ALPHASHADOW | C_LIGHTFILTER)) ||
+		si->lightImage == NULL || si->lightImage->pixels == NULL )
+	{
+		VectorClear( trace->color );
+		trace->opaque = qtrue;
+		return qtrue;
+	}
+	
+	/* try to avoid double shadows near triangle seams */
+	if( u < -ASLF_EPSILON || u > (1.0f + ASLF_EPSILON) ||
+		v < -ASLF_EPSILON || (u + v) > (1.0f + ASLF_EPSILON) )
+		return qfalse;
+	
+	/* calculate w parameter */
+	w = 1.0f - (u + v);
+	
+	/* calculate st from uvw (barycentric) coordinates */
+	s = w * tt->v[ 0 ].st[ 0 ] + u * tt->v[ 1 ].st[ 0 ] + v * tt->v[ 2 ].st[ 0 ];
+	t = w * tt->v[ 0 ].st[ 1 ] + u * tt->v[ 1 ].st[ 1 ] + v * tt->v[ 2 ].st[ 1 ];
+	s = s - floor( s );
+	t = t - floor( t );
+	is = s * si->lightImage->width;
+	it = t * si->lightImage->height;
+	
+	/* get pixel */
+	pixel = si->lightImage->pixels + 4 * (it * si->lightImage->width + is);
+	
+	/* ydnar: color filter */
+	if( si->compileFlags & C_LIGHTFILTER )
+	{
+		/* filter by texture color */
+		trace->color[ 0 ] *= ((1.0f / 255.0f) * pixel[ 0 ]);
+		trace->color[ 1 ] *= ((1.0f / 255.0f) * pixel[ 1 ]);
+		trace->color[ 2 ] *= ((1.0f / 255.0f) * pixel[ 2 ]);
+	}
+	
+	/* ydnar: alpha filter */
+	if( si->compileFlags & C_ALPHASHADOW )
+	{
+		/* filter by inverse texture alpha */
+		shadow = (1.0f / 255.0f) * (255 - pixel[ 3 ]);
+		trace->color[ 0 ] *= shadow;
+		trace->color[ 1 ] *= shadow;
+		trace->color[ 2 ] *= shadow;
+	}
+	
+	/* check filter for opaque */
+	if( trace->color[ 0 ] <= 0.001f && trace->color[ 1 ] <= 0.001f && trace->color[ 2 ] <= 0.001f )
+	{
+		trace->opaque = qtrue;
+		return qtrue;
+	}
+	
+	/* continue tracing */
+	return qfalse;
+}
+
+
+
+/*
+TraceWinding() - ydnar
+temporary hack
+*/
+
+qboolean TraceWinding( traceWinding_t *tw, trace_t *trace )
+{
+	int				i;
+	traceTriangle_t	tt;
+	
+	
+	/* initial setup */
+	tt.infoNum = tw->infoNum;
+	tt.v[ 0 ] = tw->v[ 0 ];
+	
+	/* walk vertex list */
+	for( i = 1; i + 1 < tw->numVerts; i++ )
+	{
+		/* set verts */
+		tt.v[ 1 ] = tw->v[ i ];
+		tt.v[ 2 ] = tw->v[ i + 1 ];
+		
+		/* find vectors for two edges sharing the first vert */
+		VectorSubtract( tt.v[ 1 ].xyz, tt.v[ 0 ].xyz, tt.edge1 );
+		VectorSubtract( tt.v[ 2 ].xyz, tt.v[ 0 ].xyz, tt.edge2 );
+		
+		/* trace it */
+		if( TraceTriangle( &traceInfos[ tt.infoNum ], &tt, trace ) )
+			return qtrue;
+	}
+	
+	/* done */
+	return qfalse;
+}
+
+
+
+
+/*
+TraceLine_r()
+returns qtrue if something is hit and tracing can stop
+*/
+
+static qboolean TraceLine_r( int nodeNum, vec3_t origin, vec3_t end, trace_t *trace )
+{
+	traceNode_t		*node;
+	int				side;
+	float			front, back, frac;
+	vec3_t			mid;
+	qboolean		r;
+
+	
+	/* bogus node number means solid, end tracing unless testing all */
+	if( nodeNum < 0 )
+	{
+		trace->passSolid = qtrue;
+		return qtrue;
+	}
+	
+	/* get node */
+	node = &traceNodes[ nodeNum ];
+	
+	/* solid? */
+	if( node->type == TRACE_LEAF_SOLID )
+	{
+		trace->passSolid = qtrue;
+		return qtrue;
+	}
+	
+	/* leafnode? */
+	if( node->type < 0 )
+	{
+		/* note leaf and return */	
+		if( node->numItems > 0 && trace->numTestNodes < MAX_TRACE_TEST_NODES )
+			trace->testNodes[ trace->numTestNodes++ ] = nodeNum;
+		return qfalse;
+	}
+	
+	/* ydnar 2003-09-07: don't test branches of the bsp with nothing in them when testall is enabled */
+	if( trace->testAll && node->numItems == 0 )
+		return qfalse;
+	
+	/* classify beginning and end points */
+	switch( node->type )
+	{
+		case PLANE_X:
+			front = origin[ 0 ] - node->plane[ 3 ];
+			back = end[ 0 ] - node->plane[ 3 ];
+			break;
+		
+		case PLANE_Y:
+			front = origin[ 1 ] - node->plane[ 3 ];
+			back = end[ 1 ] - node->plane[ 3 ];
+			break;
+		
+		case PLANE_Z:
+			front = origin[ 2 ] - node->plane[ 3 ];
+			back = end[ 2 ] - node->plane[ 3 ];
+			break;
+		
+		default:
+			front = DotProduct( origin, node->plane ) - node->plane[ 3 ];
+			back = DotProduct( end, node->plane ) - node->plane[ 3 ];
+			break;
+	}
+	
+	/* entirely in front side? */
+	if( front >= -TRACE_ON_EPSILON && back >= -TRACE_ON_EPSILON )
+		return TraceLine_r( node->children[ 0 ], origin, end, trace );
+	
+	/* entirely on back side? */
+	if( front < TRACE_ON_EPSILON && back < TRACE_ON_EPSILON )
+		return TraceLine_r( node->children[ 1 ], origin, end, trace );
+	
+	/* select side */
+	side = front < 0;
+	
+	/* calculate intercept point */
+	frac = front / (front - back);
+	mid[ 0 ] = origin[ 0 ] + (end[ 0 ] - origin[ 0 ]) * frac;
+	mid[ 1 ] = origin[ 1 ] + (end[ 1 ] - origin[ 1 ]) * frac;
+	mid[ 2 ] = origin[ 2 ] + (end[ 2 ] - origin[ 2 ]) * frac;
+	
+	/* fixme: check inhibit radius, then solid nodes and ignore */
+	
+	/* trace first side */
+	r = TraceLine_r( node->children[ side ], origin, mid, trace );
+	if( r )
+		return r;
+	
+	/* trace other side */
+	return TraceLine_r( node->children[ !side ], mid, end, trace );
+}
+
+
+
+/*
+TraceLine() - ydnar
+rewrote this function a bit :)
+*/
+
+void TraceLine( trace_t *trace )
+{
+	int				i, j;
+	traceNode_t		*node;
+	traceTriangle_t	*tt;
+	traceInfo_t		*ti;
+	
+	
+	/* setup output (note: this code assumes the input data is completely filled out) */
+	trace->passSolid = qfalse;
+	trace->opaque = qfalse;
+	trace->compileFlags = 0;
+	trace->numTestNodes = 0;
+	
+	/* early outs */
+	if( !trace->recvShadows || !trace->testOcclusion || trace->distance <= 0.00001f )
+		return;
+	
+	/* trace through nodes */
+	TraceLine_r( headNodeNum, trace->origin, trace->end, trace );
+	if( (trace->passSolid && !trace->testAll) )
+	{
+		trace->opaque = qtrue;
+		return;
+	}
+	
+	/* skip surfaces? */
+	if( noSurfaces )
+		return;
+	
+	/* testall means trace through sky */	
+	if( trace->testAll && trace->numTestNodes < MAX_TRACE_TEST_NODES &&
+		(trace->numSurfaces == 0 || surfaceInfos[ trace->surfaces[ 0 ] ].childSurfaceNum < 0) )
+	{
+		//%	trace->testNodes[ trace->numTestNodes++ ] = skyboxNodeNum;
+		TraceLine_r( skyboxNodeNum, trace->origin, trace->end, trace );
+	}
+	
+	/* walk node list */
+	for( i = 0; i < trace->numTestNodes; i++ )
+	{
+		/* get node */
+		node = &traceNodes[ trace->testNodes[ i ] ];
+		
+		/* walk node item list */
+		for( j = 0; j < node->numItems; j++ )
+		{
+			tt = &traceTriangles[ node->items[ j ] ];
+			ti = &traceInfos[ tt->infoNum ];
+			if( TraceTriangle( ti, tt, trace ) )
+				return;
+			//%	if( TraceWinding( &traceWindings[ node->items[ j ] ], trace ) )
+			//%		return;
+		}
+	}
+}
+
+
+
+/*
+SetupTrace() - ydnar
+sets up certain trace values
+*/
+
+float SetupTrace( trace_t *trace )
+{
+	VectorSubtract( trace->end, trace->origin, trace->displacement );
+	trace->distance = VectorNormalize( trace->displacement, trace->direction );
+	return trace->distance;
+}
diff --git a/tools/quake3/q3map2/light_ydnar.c b/tools/quake3/q3map2/light_ydnar.c
index 33be2071..6a292156 100644
--- a/tools/quake3/q3map2/light_ydnar.c
+++ b/tools/quake3/q3map2/light_ydnar.c
@@ -1,3129 +1,3129 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define LIGHT_YDNAR_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-/*
-ColorToBytes()
-ydnar: moved to here 2001-02-04
-*/
-
-void ColorToBytes( const float *color, byte *colorBytes, float scale )
-{
-	float	max;
-	vec3_t	sample;
-	
-	
-	/* ydnar: scaling necessary for simulating r_overbrightBits on external lightmaps */
-	if( scale <= 0.0f )
-		scale = 1.0f;
-	
-	/* make a local copy */
-	VectorScale( color, scale, sample );
-	
-	/* handle negative light */
-	if( sample[ 0 ] < 0.0f )
-		sample[ 0 ] = 0.0f;
-	if( sample[ 1 ] < 0.0f )
-		sample[ 1 ] = 0.0f;
-	if( sample[ 2 ] < 0.0f )
-		sample[ 2 ] = 0.0f;
-	
-	/* clamp with color normalization */
-	max = sample[ 0 ];
-	if( sample[ 1 ] > max )
-		max = sample[ 1 ];
-	if( sample[ 2 ] > max )
-		max = sample[ 2 ];
-	if( max > 255.0f )
-		VectorScale( sample, (255.0f / max), sample );
-	
-	/* store it off */
-	colorBytes[ 0 ] = sample[ 0 ];
-	colorBytes[ 1 ] = sample[ 1 ];
-	colorBytes[ 2 ] = sample[ 2 ];
-}
-
-
-
-/* -------------------------------------------------------------------------------
-
-this section deals with phong shading (normal interpolation across brush faces)
-
-------------------------------------------------------------------------------- */
-
-/*
-SmoothNormals()
-smooths together coincident vertex normals across the bsp
-*/
-
-#define MAX_SAMPLES				256
-#define THETA_EPSILON			0.000001
-#define EQUAL_NORMAL_EPSILON	0.01
-
-void SmoothNormals( void )
-{
-	int					i, j, k, f, cs, numVerts, numVotes, fOld, start;
-	float				shadeAngle, defaultShadeAngle, maxShadeAngle, dot, testAngle;
-	bspDrawSurface_t	*ds;
-	shaderInfo_t		*si;
-	float				*shadeAngles;
-	byte				*smoothed;
-	vec3_t				average, diff;
-	int					indexes[ MAX_SAMPLES ];
-	vec3_t				votes[ MAX_SAMPLES ];
-	
-	
-	/* allocate shade angle table */
-	shadeAngles = safe_malloc( numBSPDrawVerts * sizeof( float ) );
-	memset( shadeAngles, 0, numBSPDrawVerts * sizeof( float ) );
-	
-	/* allocate smoothed table */
-	cs = (numBSPDrawVerts / 8) + 1;
-	smoothed = safe_malloc( cs );
-	memset( smoothed, 0, cs );
-	
-	/* set default shade angle */
-	defaultShadeAngle = DEG2RAD( shadeAngleDegrees );
-	maxShadeAngle = 0;
-	
-	/* run through every surface and flag verts belonging to non-lightmapped surfaces
-	   and set per-vertex smoothing angle */
-	for( i = 0; i < numBSPDrawSurfaces; i++ )
-	{
-		/* get drawsurf */
-		ds = &bspDrawSurfaces[ i ];
-		
-		/* get shader for shade angle */
-		si = surfaceInfos[ i ].si;
-		if( si->shadeAngleDegrees )
-			shadeAngle = DEG2RAD( si->shadeAngleDegrees );
-		else
-			shadeAngle = defaultShadeAngle;
-		if( shadeAngle > maxShadeAngle )
-			maxShadeAngle = shadeAngle;
-		
-		/* flag its verts */
-		for( j = 0; j < ds->numVerts; j++ )
-		{
-			f = ds->firstVert + j;
-			shadeAngles[ f ] = shadeAngle;
-			if( ds->surfaceType == MST_TRIANGLE_SOUP )
-				smoothed[ f >> 3 ] |= (1 << (f & 7));
-		}
-		
-		/* ydnar: optional force-to-trisoup */
-		if( trisoup && ds->surfaceType == MST_PLANAR )
-		{
-			ds->surfaceType = MST_TRIANGLE_SOUP;
-			ds->lightmapNum[ 0 ] = -3;
-		}
-	}
-	
-	/* bail if no surfaces have a shade angle */
-	if( maxShadeAngle == 0 )
-	{
-		free( shadeAngles );
-		free( smoothed );
-		return;
-	}
-	
-	/* init pacifier */
-	fOld = -1;
-	start = I_FloatTime();
-	
-	/* go through the list of vertexes */
-	for( i = 0; i < numBSPDrawVerts; i++ )
-	{
-		/* print pacifier */
-		f = 10 * i / numBSPDrawVerts;
-		if( f != fOld )
-		{
-			fOld = f;
-			Sys_Printf( "%i...", f );
-		}
-		
-		/* already smoothed? */
-		if( smoothed[ i >> 3 ] & (1 << (i & 7)) )
-			continue;
-		
-		/* clear */
-		VectorClear( average );
-		numVerts = 0;
-		numVotes = 0;
-		
-		/* build a table of coincident vertexes */
-		for( j = i; j < numBSPDrawVerts && numVerts < MAX_SAMPLES; j++ )
-		{
-			/* already smoothed? */
-			if( smoothed[ j >> 3 ] & (1 << (j & 7)) )
-				continue;
-			
-			/* test vertexes */
-			if( VectorCompare( yDrawVerts[ i ].xyz, yDrawVerts[ j ].xyz ) == qfalse )
-				continue;
-			
-			/* use smallest shade angle */
-			shadeAngle = (shadeAngles[ i ] < shadeAngles[ j ] ? shadeAngles[ i ] : shadeAngles[ j ]);
-			
-			/* check shade angle */
-			dot = DotProduct( bspDrawVerts[ i ].normal, bspDrawVerts[ j ].normal );
-			if( dot > 1.0 )
-				dot = 1.0;
-			else if( dot < -1.0 )
-				dot = -1.0;
-			testAngle = acos( dot ) + THETA_EPSILON;
-			if( testAngle >= shadeAngle )
-			{
-				//Sys_Printf( "F(%3.3f >= %3.3f) ", RAD2DEG( testAngle ), RAD2DEG( shadeAngle ) );
-				continue;
-			}
-			//Sys_Printf( "P(%3.3f < %3.3f) ", RAD2DEG( testAngle ), RAD2DEG( shadeAngle ) );
-			
-			/* add to the list */
-			indexes[ numVerts++ ] = j;
-			
-			/* flag vertex */
-			smoothed[ j >> 3 ] |= (1 << (j & 7));
-			
-			/* see if this normal has already been voted */
-			for( k = 0; k < numVotes; k++ )
-			{
-				VectorSubtract( bspDrawVerts[ j ].normal, votes[ k ], diff );
-				if( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
-					fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
-					fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON )
-					break;
-			}
-			
-			/* add a new vote? */
-			if( k == numVotes && numVotes < MAX_SAMPLES )
-			{
-				VectorAdd( average, bspDrawVerts[ j ].normal, average );
-				VectorCopy( bspDrawVerts[ j ].normal, votes[ numVotes ] );
-				numVotes++;
-			}
-		}
-		
-		/* don't average for less than 2 verts */
-		if( numVerts < 2 )
-			continue;
-		
-		/* average normal */
-		if( VectorNormalize( average, average ) > 0 )
-		{
-			/* smooth */
-			for( j = 0; j < numVerts; j++ )
-				VectorCopy( average, yDrawVerts[ indexes[ j ] ].normal );
-		}
-	}
-	
-	/* free the tables */
-	free( shadeAngles );
-	free( smoothed );
-	
-	/* print time */
-	Sys_Printf( " (%i)\n", (int) (I_FloatTime() - start) );
-}
-
-
-
-/* -------------------------------------------------------------------------------
-
-this section deals with phong shaded lightmap tracing
-
-------------------------------------------------------------------------------- */
-
-/* 9th rewrite (recursive subdivision of a lightmap triangle) */
-
-/*
-CalcTangentVectors()
-calculates the st tangent vectors for normalmapping
-*/
-
-static qboolean CalcTangentVectors( int numVerts, bspDrawVert_t **dv, vec3_t *stv, vec3_t *ttv )
-{
-	int			i;
-	float		bb, s, t;
-	vec3_t		bary;
-	
-	
-	/* calculate barycentric basis for the triangle */
-	bb = (dv[ 1 ]->st[ 0 ] - dv[ 0 ]->st[ 0 ]) * (dv[ 2 ]->st[ 1 ] - dv[ 0 ]->st[ 1 ]) - (dv[ 2 ]->st[ 0 ] - dv[ 0 ]->st[ 0 ]) * (dv[ 1 ]->st[ 1 ] - dv[ 0 ]->st[ 1 ]);
-	if( fabs( bb ) < 0.00000001f )
-		return qfalse;
-	
-	/* do each vertex */
-	for( i = 0; i < numVerts; i++ )
-	{
-		/* calculate s tangent vector */
-		s = dv[ i ]->st[ 0 ] + 10.0f;
-		t = dv[ i ]->st[ 1 ];
-		bary[ 0 ] = ((dv[ 1 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t) - (dv[ 2 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t)) / bb;
-		bary[ 1 ] = ((dv[ 2 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t) - (dv[ 0 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t)) / bb;
-		bary[ 2 ] = ((dv[ 0 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t) - (dv[ 1 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t)) / bb;
-		
-		stv[ i ][ 0 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 0 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 0 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 0 ];
-		stv[ i ][ 1 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 1 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 1 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 1 ];
-		stv[ i ][ 2 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 2 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 2 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 2 ];
-		
-		VectorSubtract( stv[ i ], dv[ i ]->xyz, stv[ i ] );
-		VectorNormalize( stv[ i ], stv[ i ] );
-		
-		/* calculate t tangent vector */
-		s = dv[ i ]->st[ 0 ];
-		t = dv[ i ]->st[ 1 ] + 10.0f;
-		bary[ 0 ] = ((dv[ 1 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t) - (dv[ 2 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t)) / bb;
-		bary[ 1 ] = ((dv[ 2 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t) - (dv[ 0 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t)) / bb;
-		bary[ 2 ] = ((dv[ 0 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t) - (dv[ 1 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t)) / bb;
-		
-		ttv[ i ][ 0 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 0 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 0 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 0 ];
-		ttv[ i ][ 1 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 1 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 1 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 1 ];
-		ttv[ i ][ 2 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 2 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 2 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 2 ];
-		
-		VectorSubtract( ttv[ i ], dv[ i ]->xyz, ttv[ i ] );
-		VectorNormalize( ttv[ i ], ttv[ i ] );
-		
-		/* debug code */
-		//%	Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
-		//%		stv[ i ][ 0 ], stv[ i ][ 1 ], stv[ i ][ 2 ], ttv[ i ][ 0 ], ttv[ i ][ 1 ], ttv[ i ][ 2 ] );
-	}
-	
-	/* return to caller */
-	return qtrue;
-}
-
-
-
-
-/*
-PerturbNormal()
-perterbs the normal by the shader's normalmap in tangent space
-*/
-
-static void PerturbNormal( bspDrawVert_t *dv, shaderInfo_t *si, vec3_t pNormal, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
-{
-	int			i;
-	vec4_t		bump;
-	
-	
-	/* passthrough */
-	VectorCopy( dv->normal, pNormal );
-	
-	/* sample normalmap */
-	if( RadSampleImage( si->normalImage->pixels, si->normalImage->width, si->normalImage->height, dv->st, bump ) == qfalse )
-		return;
-	
-	/* remap sampled normal from [0,255] to [-1,-1] */
-	for( i = 0; i < 3; i++ )
-		bump[ i ] = (bump[ i ] - 127.0f) * (1.0f / 127.5f);
-	
-	/* scale tangent vectors and add to original normal */
-	VectorMA( dv->normal, bump[ 0 ], stv[ 0 ], pNormal );
-	VectorMA( pNormal, bump[ 1 ], ttv[ 0 ], pNormal );
-	VectorMA( pNormal, bump[ 2 ], dv->normal, pNormal );
-	
-	/* renormalize and return */
-	VectorNormalize( pNormal, pNormal );
-}
-
-
-
-/*
-MapSingleLuxel()
-maps a luxel for triangle bv at
-*/
-
-#define NUDGE			0.5f
-#define BOGUS_NUDGE		-99999.0f
-
-static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
-{
-	int				i, x, y, numClusters, *clusters, pointCluster, *cluster;
-	float			*luxel, *origin, *normal, d, lightmapSampleOffset;
-	shaderInfo_t	*si;
-	vec3_t			pNormal;
-	vec3_t			vecs[ 3 ];
-	vec3_t			nudged;
-	float			*nudge;
-	static float	nudges[][ 2 ] =
-					{
-						//%{ 0, 0 },		/* try center first */
-						{ -NUDGE, 0 },		/* left */
-						{ NUDGE, 0 },		/* right */
-						{ 0, NUDGE },		/* up */
-						{ 0, -NUDGE },		/* down */
-						{ -NUDGE, NUDGE },	/* left/up */
-						{ NUDGE, -NUDGE },	/* right/down */
-						{ NUDGE, NUDGE },	/* right/up */
-						{ -NUDGE, -NUDGE },	/* left/down */
-						{ BOGUS_NUDGE, BOGUS_NUDGE }
-					};
-	
-	
-	/* find luxel xy coords (fixme: subtract 0.5?) */
-	x = dv->lightmap[ 0 ][ 0 ];
-	y = dv->lightmap[ 0 ][ 1 ];
-	if( x < 0 )
-		x = 0;
-	else if( x >= lm->sw )
-		x = lm->sw - 1;
-	if( y < 0 )
-		y = 0;
-	else if( y >= lm->sh )
-		y = lm->sh - 1;
-	
-	/* set shader and cluster list */
-	if( info != NULL )
-	{
-		si = info->si;
-		numClusters = info->numSurfaceClusters;
-		clusters = &surfaceClusters[ info->firstSurfaceCluster ];
-	}
-	else
-	{
-		si = NULL;
-		numClusters = 0;
-		clusters = NULL;
-	}
-	
-	/* get luxel, origin, cluster, and normal */
-	luxel = SUPER_LUXEL( 0, x, y );
-	origin = SUPER_ORIGIN( x, y );
-	normal = SUPER_NORMAL( x, y );
-	cluster = SUPER_CLUSTER( x, y );
-	
-	/* don't attempt to remap occluded luxels for planar surfaces */
-	if( (*cluster) == CLUSTER_OCCLUDED && lm->plane != NULL )
-		return (*cluster);
-	
-	/* only average the normal for premapped luxels */
-	else if( (*cluster) >= 0 )
-	{
-		/* do bumpmap calculations */
-		if( stv != NULL )
-			PerturbNormal( dv, si, pNormal, stv, ttv );
-		else
-			VectorCopy( dv->normal, pNormal );
-		
-		/* add the additional normal data */
-		VectorAdd( normal, pNormal, normal );
-		luxel[ 3 ] += 1.0f;
-		return (*cluster);
-	}
-	
-	/* otherwise, unmapped luxels (*cluster == CLUSTER_UNMAPPED) will have their full attributes calculated */
-	
-	/* get origin */
-	
-	/* axial lightmap projection */
-	if( lm->vecs != NULL )
-	{
-		/* calculate an origin for the sample from the lightmap vectors */
-		VectorCopy( lm->origin, origin );
-		for( i = 0; i < 3; i++ )
-		{
-			/* add unless it's the axis, which is taken care of later */
-			if( i == lm->axisNum )
-				continue;
-			origin[ i ] += (x * lm->vecs[ 0 ][ i ]) + (y * lm->vecs[ 1 ][ i ]);
-		}
-		
-		/* project the origin onto the plane */
-		d = DotProduct( origin, plane ) - plane[ 3 ];
-		d /= plane[ lm->axisNum ];
-		origin[ lm->axisNum ] -= d;
-	}
-	
-	/* non axial lightmap projection (explicit xyz) */
-	else
-		VectorCopy( dv->xyz, origin );
-	
-	/* planar surfaces have precalculated lightmap vectors for nudging */
-	if( lm->plane != NULL )
-	{
-		VectorCopy( lm->vecs[ 0 ], vecs[ 0 ] );
-		VectorCopy( lm->vecs[ 1 ], vecs[ 1 ] );
-		VectorCopy( lm->plane, vecs[ 2 ] );
-	}
-	
-	/* non-planar surfaces must calculate them */
-	else
-	{
-		if( plane != NULL )
-			VectorCopy( plane, vecs[ 2 ] );
-		else
-			VectorCopy( dv->normal, vecs[ 2 ] );
-		MakeNormalVectors( vecs[ 2 ], vecs[ 0 ], vecs[ 1 ] );
-	}
-	
-	/* push the origin off the surface a bit */
-	if( si != NULL )
-		lightmapSampleOffset = si->lightmapSampleOffset;
-	else
-		lightmapSampleOffset = DEFAULT_LIGHTMAP_SAMPLE_OFFSET;
-	if( lm->axisNum < 0 )
-		VectorMA( origin, lightmapSampleOffset, vecs[ 2 ], origin );
-	else if( vecs[ 2 ][ lm->axisNum ] < 0.0f )
-		origin[ lm->axisNum ] -= lightmapSampleOffset;
-	else
-		origin[ lm->axisNum ] += lightmapSampleOffset;
-	
-	/* get cluster */
-	pointCluster = ClusterForPointExtFilter( origin, LUXEL_EPSILON, numClusters, clusters );
-	
-	/* another retarded hack, storing nudge count in luxel[ 1 ] */
-	luxel[ 1 ] = 0.0f;	
-	
-	/* point in solid? */
-	if( pointCluster < 0 )
-	{
-		/* nudge the the location around */
-		nudge = nudges[ 0 ];
-		while( nudge[ 0 ] > BOGUS_NUDGE && pointCluster < 0 )
-		{
-			/* nudge the vector around a bit */
-			for( i = 0; i < 3; i++ )
-			{
-				/* set nudged point*/
-				nudged[ i ] = origin[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
-			}
-			nudge += 2;
-			
-			/* get pvs cluster */
-			pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters ); //% + 0.625 );
-			if( pointCluster >= 0 )	
-				VectorCopy( nudged, origin );
-			luxel[ 1 ] += 1.0f;
-		}
-	}
-	
-	/* as a last resort, if still in solid, try drawvert origin offset by normal */
-	if( pointCluster < 0 && si != NULL )
-	{
-		VectorMA( dv->xyz, lightmapSampleOffset, dv->normal, nudged );
-		pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters );
-		if( pointCluster >= 0 )
-			VectorCopy( nudged, origin );
-		luxel[ 1 ] += 1.0f;
-	}
-	
-	/* valid? */
-	if( pointCluster < 0 )
-	{
-		(*cluster) = CLUSTER_OCCLUDED;
-		VectorClear( origin );
-		VectorClear( normal );
-		numLuxelsOccluded++;
-		return (*cluster);
-	}
-	
-	/* debug code */
-	//%	Sys_Printf( "%f %f %f\n", origin[ 0 ], origin[ 1 ], origin[ 2 ] );
-	
-	/* do bumpmap calculations */
-	if( stv )
-		PerturbNormal( dv, si, pNormal, stv, ttv );
-	else
-		VectorCopy( dv->normal, pNormal );
-	
-	/* store the cluster and normal */
-	(*cluster) = pointCluster;
-	VectorCopy( pNormal, normal );
-	
-	/* store explicit mapping pass and implicit mapping pass */
-	luxel[ 0 ] = pass;
-	luxel[ 3 ] = 1.0f;
-	
-	/* add to count */
-	numLuxelsMapped++;
-	
-	/* return ok */
-	return (*cluster);
-}
-
-
-
-/*
-MapTriangle_r()
-recursively subdivides a triangle until its edges are shorter
-than the distance between two luxels (thanks jc :)
-*/
-
-static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
-{
-	bspDrawVert_t	mid, *dv2[ 3 ];
-	int				max;
-	
-	
-	/* map the vertexes */
-	#if 0
-	MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
-	#endif
-	
-	/* subdivide calc */
-	{
-		int			i;
-		float		*a, *b, dx, dy, dist, maxDist;
-		
-		
-		/* find the longest edge and split it */
-		max = -1;
-		maxDist = 0;
-		for( i = 0; i < 3; i++ )
-		{
-			/* get verts */
-			a = dv[ i ]->lightmap[ 0 ];
-			b = dv[ (i + 1) % 3 ]->lightmap[ 0 ];
-			
-			/* get dists */
-			dx = a[ 0 ] - b[ 0 ];
-			dy = a[ 1 ] - b[ 1 ];
-			dist = (dx * dx) + (dy * dy);	//% sqrt( (dx * dx) + (dy * dy) );
-			
-			/* longer? */
-			if( dist > maxDist )
-			{
-				maxDist = dist;
-				max = i;
-			}
-		}
-		
-		/* try to early out */
-		if( max < 0 || maxDist <= subdivideThreshold )	/* ydnar: was i < 0 instead of max < 0 (?) */
-			return;
-	}
-	
-	/* split the longest edge and map it */
-	LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
-	MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv );
-	
-	/* push the point up a little bit to account for fp creep (fixme: revisit this) */
-	//%	VectorMA( mid.xyz, 2.0f, mid.normal, mid.xyz );
-	
-	/* recurse to first triangle */
-	VectorCopy( dv, dv2 );
-	dv2[ max ] = &mid;
-	MapTriangle_r( lm, info, dv2, plane, stv, ttv );
-	
-	/* recurse to second triangle */
-	VectorCopy( dv, dv2 );
-	dv2[ (max + 1) % 3 ] = &mid;
-	MapTriangle_r( lm, info, dv2, plane, stv, ttv );
-}
-
-
-
-/*
-MapTriangle()
-seed function for MapTriangle_r()
-requires a cw ordered triangle
-*/
-
-static qboolean MapTriangle( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], qboolean mapNonAxial )
-{
-	int				i;
-	vec4_t			plane;
-	vec3_t			*stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
-	
-	
-	/* get plane if possible */
-	if( lm->plane != NULL )
-	{
-		VectorCopy( lm->plane, plane );
-		plane[ 3 ] = lm->plane[ 3 ];
-	}
-	
-	/* otherwise make one from the points */
-	else if( PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) == qfalse )
-		return qfalse;
-	
-	/* check to see if we need to calculate texture->world tangent vectors */
-	if( info->si->normalImage != NULL && CalcTangentVectors( 3, dv, stvStatic, ttvStatic ) )
-	{
-		stv = stvStatic;
-		ttv = ttvStatic;
-	}
-	else
-	{
-		stv = NULL;
-		ttv = NULL;
-	}
-	
-	/* map the vertexes */
-	MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
-	
-	/* 2002-11-20: prefer axial triangle edges */
-	if( mapNonAxial )
-	{
-		/* subdivide the triangle */
-		MapTriangle_r( lm, info, dv, plane, stv, ttv );
-		return qtrue;
-	}
-	
-	for( i = 0; i < 3; i++ )
-	{
-		float			*a, *b;
-		bspDrawVert_t	*dv2[ 3 ];
-		
-		
-		/* get verts */
-		a = dv[ i ]->lightmap[ 0 ];
-		b = dv[ (i + 1) % 3 ]->lightmap[ 0 ];
-		
-		/* make degenerate triangles for mapping edges */
-		if( fabs( a[ 0 ] - b[ 0 ] ) < 0.01f || fabs( a[ 1 ] - b[ 1 ] ) < 0.01f )
-		{
-			dv2[ 0 ] = dv[ i ];
-			dv2[ 1 ] = dv[ (i + 1) % 3 ];
-			dv2[ 2 ] = dv[ (i + 1) % 3 ];
-			
-			/* map the degenerate triangle */
-			MapTriangle_r( lm, info, dv2, plane, stv, ttv );
-		}
-	}
-	
-	return qtrue;
-}
-
-
-
-/*
-MapQuad_r()
-recursively subdivides a quad until its edges are shorter
-than the distance between two luxels
-*/
-
-static void MapQuad_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 4 ], vec4_t plane, vec3_t stv[ 4 ], vec3_t ttv[ 4 ] )
-{
-	bspDrawVert_t	mid[ 2 ], *dv2[ 4 ];
-	int				max;
-	
-	
-	/* subdivide calc */
-	{
-		int			i;
-		float		*a, *b, dx, dy, dist, maxDist;
-		
-		
-		/* find the longest edge and split it */
-		max = -1;
-		maxDist = 0;
-		for( i = 0; i < 4; i++ )
-		{
-			/* get verts */
-			a = dv[ i ]->lightmap[ 0 ];
-			b = dv[ (i + 1) % 4 ]->lightmap[ 0 ];
-			
-			/* get dists */
-			dx = a[ 0 ] - b[ 0 ];
-			dy = a[ 1 ] - b[ 1 ];
-			dist = (dx * dx) + (dy * dy);	//% sqrt( (dx * dx) + (dy * dy) );
-			
-			/* longer? */
-			if( dist > maxDist )
-			{
-				maxDist = dist;
-				max = i;
-			}
-		}
-		
-		/* try to early out */
-		if( max < 0 || maxDist <= subdivideThreshold )
-			return;
-	}
-	
-	/* we only care about even/odd edges */
-	max &= 1;
-	
-	/* split the longest edges */
-	LerpDrawVert( dv[ max ], dv[ (max + 1) % 4 ], &mid[ 0 ] );
-	LerpDrawVert( dv[ max + 2 ], dv[ (max + 3) % 4 ], &mid[ 1 ] );
-	
-	/* map the vertexes */
-	MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv );
-	
-	/* 0 and 2 */
-	if( max == 0 )
-	{
-		/* recurse to first quad */
-		dv2[ 0 ] = dv[ 0 ];
-		dv2[ 1 ] = &mid[ 0 ];
-		dv2[ 2 ] = &mid[ 1 ];
-		dv2[ 3 ] = dv[ 3 ];
-		MapQuad_r( lm, info, dv2, plane, stv, ttv );
-		
-		/* recurse to second quad */
-		dv2[ 0 ] = &mid[ 0 ];
-		dv2[ 1 ] = dv[ 1 ];
-		dv2[ 2 ] = dv[ 2 ];
-		dv2[ 3 ] = &mid[ 1 ];
-		MapQuad_r( lm, info, dv2, plane, stv, ttv );
-	}
-	
-	/* 1 and 3 */
-	else
-	{
-		/* recurse to first quad */
-		dv2[ 0 ] = dv[ 0 ];
-		dv2[ 1 ] = dv[ 1 ];
-		dv2[ 2 ] = &mid[ 0 ];
-		dv2[ 3 ] = &mid[ 1 ];
-		MapQuad_r( lm, info, dv2, plane, stv, ttv );
-		
-		/* recurse to second quad */
-		dv2[ 0 ] = &mid[ 1 ];
-		dv2[ 1 ] = &mid[ 0 ];
-		dv2[ 2 ] = dv[ 2 ];
-		dv2[ 3 ] = dv[ 3 ];
-		MapQuad_r( lm, info, dv2, plane, stv, ttv );
-	}
-}
-
-
-
-/*
-MapQuad()
-seed function for MapQuad_r()
-requires a cw ordered triangle quad
-*/
-
-#define QUAD_PLANAR_EPSILON		0.5f
-
-static qboolean MapQuad( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 4 ] )
-{
-	float			dist;
-	vec4_t			plane;
-	vec3_t			*stv, *ttv, stvStatic[ 4 ], ttvStatic[ 4 ];
-	
-	
-	/* get plane if possible */
-	if( lm->plane != NULL )
-	{
-		VectorCopy( lm->plane, plane );
-		plane[ 3 ] = lm->plane[ 3 ];
-	}
-	
-	/* otherwise make one from the points */
-	else if( PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) == qfalse )
-		return qfalse;
-	
-	/* 4th point must fall on the plane */
-	dist = DotProduct( plane, dv[ 3 ]->xyz ) - plane[ 3 ];
-	if( fabs( dist ) > QUAD_PLANAR_EPSILON )
-		return qfalse;
-	
-	/* check to see if we need to calculate texture->world tangent vectors */
-	if( info->si->normalImage != NULL && CalcTangentVectors( 4, dv, stvStatic, ttvStatic ) )
-	{
-		stv = stvStatic;
-		ttv = ttvStatic;
-	}
-	else
-	{
-		stv = NULL;
-		ttv = NULL;
-	}
-	
-	/* map the vertexes */
-	MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
-	MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv );
-	
-	/* subdivide the quad */
-	MapQuad_r( lm, info, dv, plane, stv, ttv );
-	return qtrue;
-}
-
-
-
-/*
-MapRawLightmap()
-maps the locations, normals, and pvs clusters for a raw lightmap
-*/
-
-#define VectorDivide( in, d, out )	VectorScale( in, (1.0f / (d)), out )	//%	(out)[ 0 ] = (in)[ 0 ] / (d), (out)[ 1 ] = (in)[ 1 ] / (d), (out)[ 2 ] = (in)[ 2 ] / (d)
-
-void MapRawLightmap( int rawLightmapNum )
-{
-	int					n, num, i, x, y, sx, sy, pw[ 5 ], r, *cluster, mapNonAxial;
-	float				*luxel, *origin, *normal, samples, radius, pass;
-	rawLightmap_t		*lm;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	mesh_t				src, *subdivided, *mesh;
-	bspDrawVert_t		*verts, *dv[ 4 ], fake;
-	
-	
-	/* bail if this number exceeds the number of raw lightmaps */
-	if( rawLightmapNum >= numRawLightmaps )
-		return;
-	
-	/* get lightmap */
-	lm = &rawLightmaps[ rawLightmapNum ];
-	
-	/* -----------------------------------------------------------------
-	   map referenced surfaces onto the raw lightmap
-	   ----------------------------------------------------------------- */
-	
-	/* walk the list of surfaces on this raw lightmap */
-	for( n = 0; n < lm->numLightSurfaces; n++ )
-	{
-		/* with > 1 surface per raw lightmap, clear occluded */
-		if( n > 0 )
-		{
-			for( y = 0; y < lm->sh; y++ )
-			{
-				for( x = 0; x < lm->sw; x++ )
-				{
-					/* get cluster */
-					cluster = SUPER_CLUSTER( x, y );
-					if( *cluster < 0 )
-						*cluster = CLUSTER_UNMAPPED;
-				}
-			}
-		}
-		
-		/* get surface */
-		num = lightSurfaces[ lm->firstLightSurface + n ];
-		ds = &bspDrawSurfaces[ num ];
-		info = &surfaceInfos[ num ];
-		
-		/* bail if no lightmap to calculate */
-		if( info->lm != lm )
-		{
-			Sys_Printf( "!" );
-			continue;
-		}
-		
-		/* map the surface onto the lightmap origin/cluster/normal buffers */
-		switch( ds->surfaceType )
-		{
-			case MST_PLANAR:
-				/* get verts */
-				verts = yDrawVerts + ds->firstVert;
-				
-				/* map the triangles */
-				for( mapNonAxial = 0; mapNonAxial < 2; mapNonAxial++ )
-				{
-					for( i = 0; i < ds->numIndexes; i += 3 )
-					{
-						dv[ 0 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i ] ];
-						dv[ 1 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 1 ] ];
-						dv[ 2 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 2 ] ];
-						MapTriangle( lm, info, dv, mapNonAxial );
-					}
-				}
-				break;
-			
-			case MST_PATCH:
-				/* make a mesh from the drawsurf */ 
-				src.width = ds->patchWidth;
-				src.height = ds->patchHeight;
-				src.verts = &yDrawVerts[ ds->firstVert ];
-				//%	subdivided = SubdivideMesh( src, 8, 512 );
-				subdivided = SubdivideMesh2( src, info->patchIterations );
-				
-				/* fit it to the curve and remove colinear verts on rows/columns */
-				PutMeshOnCurve( *subdivided );
-				mesh = RemoveLinearMeshColumnsRows( subdivided );
-				FreeMesh( subdivided );
-				
-				/* get verts */
-				verts = mesh->verts;
-				
-				/* debug code */
-				#if 0
-					if( lm->plane )
-					{
-						Sys_Printf( "Planar patch: [%1.3f %1.3f %1.3f] [%1.3f %1.3f %1.3f] [%1.3f %1.3f %1.3f]\n",
-							lm->plane[ 0 ], lm->plane[ 1 ], lm->plane[ 2 ],
-							lm->vecs[ 0 ][ 0 ], lm->vecs[ 0 ][ 1 ], lm->vecs[ 0 ][ 2 ],
-							lm->vecs[ 1 ][ 0 ], lm->vecs[ 1 ][ 1 ], lm->vecs[ 1 ][ 2 ] );
-					}
-				#endif
-				
-				/* map the mesh quads */
-				#if 0
-
-				for( mapNonAxial = 0; mapNonAxial < 2; mapNonAxial++ )
-				{
-					for( y = 0; y < (mesh->height - 1); y++ )
-					{
-						for( x = 0; x < (mesh->width - 1); x++ )
-						{
-							/* set indexes */
-							pw[ 0 ] = x + (y * mesh->width);
-							pw[ 1 ] = x + ((y + 1) * mesh->width);
-							pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-							pw[ 3 ] = x + 1 + (y * mesh->width);
-							pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-							
-							/* set radix */
-							r = (x + y) & 1;
-							
-							/* get drawverts and map first triangle */
-							dv[ 0 ] = &verts[ pw[ r + 0 ] ];
-							dv[ 1 ] = &verts[ pw[ r + 1 ] ];
-							dv[ 2 ] = &verts[ pw[ r + 2 ] ];
-							MapTriangle( lm, info, dv, mapNonAxial );
-							
-							/* get drawverts and map second triangle */
-							dv[ 0 ] = &verts[ pw[ r + 0 ] ];
-							dv[ 1 ] = &verts[ pw[ r + 2 ] ];
-							dv[ 2 ] = &verts[ pw[ r + 3 ] ];
-							MapTriangle( lm, info, dv, mapNonAxial );
-						}
-					}
-				}
-				
-				#else
-				
-				for( y = 0; y < (mesh->height - 1); y++ )
-				{
-					for( x = 0; x < (mesh->width - 1); x++ )
-					{
-						/* set indexes */
-						pw[ 0 ] = x + (y * mesh->width);
-						pw[ 1 ] = x + ((y + 1) * mesh->width);
-						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-						pw[ 3 ] = x + 1 + (y * mesh->width);
-						pw[ 4 ] = pw[ 0 ];
-						
-						/* set radix */
-						r = (x + y) & 1;
-						
-						/* attempt to map quad first */
-						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
-						dv[ 1 ] = &verts[ pw[ r + 1 ] ];
-						dv[ 2 ] = &verts[ pw[ r + 2 ] ];
-						dv[ 3 ] = &verts[ pw[ r + 3 ] ];
-						if( MapQuad( lm, info, dv ) )
-							continue;
-						
-						/* get drawverts and map first triangle */
-						MapTriangle( lm, info, dv, mapNonAxial );
-						
-						/* get drawverts and map second triangle */
-						dv[ 1 ] = &verts[ pw[ r + 2 ] ];
-						dv[ 2 ] = &verts[ pw[ r + 3 ] ];
-						MapTriangle( lm, info, dv, mapNonAxial );
-					}
-				}
-				
-				#endif
-				
-				/* free the mesh */
-				FreeMesh( mesh );
-				break;
-			
-			default:
-				break;
-		}
-	}
-	
-	/* -----------------------------------------------------------------
-	   average and clean up luxel normals
-	   ----------------------------------------------------------------- */
-	
-	/* walk the luxels */
-	for( y = 0; y < lm->sh; y++ )
-	{
-		for( x = 0; x < lm->sw; x++ )
-		{
-			/* get luxel */
-			luxel = SUPER_LUXEL( 0, x, y );
-			normal = SUPER_NORMAL( x, y );
-			cluster = SUPER_CLUSTER( x, y );
-
-			/* only look at mapped luxels */
-			if( *cluster < 0 )
-				continue;
-			
-			/* the normal data could be the sum of multiple samples */
-			if( luxel[ 3 ] > 1.0f )
-				VectorNormalize( normal, normal );
-			
-			/* mark this luxel as having only one normal */
-			luxel[ 3 ] = 1.0f;
-		}
-	}
-	
-	/* non-planar surfaces stop here */
-	if( lm->plane == NULL )
-		return;
-	
-	/* -----------------------------------------------------------------
-	   map occluded or unuxed luxels
-	   ----------------------------------------------------------------- */
-	
-	/* walk the luxels */
-	radius = floor( superSample / 2 );
-	radius = radius > 0 ? radius : 1.0f;
-	radius += 1.0f;
-	for( pass = 2.0f; pass <= radius; pass += 1.0f )
-	{
-		for( y = 0; y < lm->sh; y++ )
-		{
-			for( x = 0; x < lm->sw; x++ )
-			{
-				/* get luxel */
-				luxel = SUPER_LUXEL( 0, x, y );
-				normal = SUPER_NORMAL( x, y );
-				cluster = SUPER_CLUSTER( x, y );
-				
-				/* only look at unmapped luxels */
-				if( *cluster != CLUSTER_UNMAPPED )
-					continue;
-				
-				/* divine a normal and origin from neighboring luxels */
-				VectorClear( fake.xyz );
-				VectorClear( fake.normal );
-				fake.lightmap[ 0 ][ 0 ] = x;	//% 0.0001 + x;
-				fake.lightmap[ 0 ][ 1 ] = y;	//% 0.0001 + y;
-				samples = 0.0f;
-				for( sy = (y - 1); sy <= (y + 1); sy++ )
-				{
-					if( sy < 0 || sy >= lm->sh )
-						continue;
-					
-					for( sx = (x - 1); sx <= (x + 1); sx++ )
-					{
-						if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
-							continue;
-						
-						/* get neighboring luxel */
-						luxel = SUPER_LUXEL( 0, sx, sy );
-						origin = SUPER_ORIGIN( sx, sy );
-						normal = SUPER_NORMAL( sx, sy );
-						cluster = SUPER_CLUSTER( sx, sy );
-						
-						/* only consider luxels mapped in previous passes */
-						if( *cluster < 0 || luxel[ 0 ] >= pass )
-							continue;
-						
-						/* add its distinctiveness to our own */
-						VectorAdd( fake.xyz, origin, fake.xyz );
-						VectorAdd( fake.normal, normal, fake.normal );
-						samples += luxel[ 3 ];
-					}
-				}
-				
-				/* any samples? */
-				if( samples == 0.0f )
-					continue;
-				
-				/* average */
-				VectorDivide( fake.xyz, samples, fake.xyz );
-				//%	VectorDivide( fake.normal, samples, fake.normal );
-				if( VectorNormalize( fake.normal, fake.normal ) == 0.0f )
-					continue;
-				
-				/* map the fake vert */
-				MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
-			}
-		}
-	}
-	
-	/* -----------------------------------------------------------------
-	   average and clean up luxel normals
-	   ----------------------------------------------------------------- */
-	
-	/* walk the luxels */
-	for( y = 0; y < lm->sh; y++ )
-	{
-		for( x = 0; x < lm->sw; x++ )
-		{
-			/* get luxel */
-			luxel = SUPER_LUXEL( 0, x, y );
-			normal = SUPER_NORMAL( x, y );
-			cluster = SUPER_CLUSTER( x, y );
-			
-			/* only look at mapped luxels */
-			if( *cluster < 0 )
-				continue;
-			
-			/* the normal data could be the sum of multiple samples */
-			if( luxel[ 3 ] > 1.0f )
-				VectorNormalize( normal, normal );
-			
-			/* mark this luxel as having only one normal */
-			luxel[ 3 ] = 1.0f;
-		}
-	}
-	
-	/* debug code */
-	#if 0
-		Sys_Printf( "\n" );
-		for( y = 0; y < lm->sh; y++ )
-		{
-			for( x = 0; x < lm->sw; x++ )
-			{
-				vec3_t	mins, maxs;
-				
-
-				cluster = SUPER_CLUSTER( x, y );
-				origin = SUPER_ORIGIN( x, y );
-				normal = SUPER_NORMAL( x, y );
-				luxel = SUPER_LUXEL( x, y );
-				
-				if( *cluster < 0 )
-					continue;
-				
-				/* check if within the bounding boxes of all surfaces referenced */
-				ClearBounds( mins, maxs );
-				for( n = 0; n < lm->numLightSurfaces; n++ )
-				{
-					int TOL;
-					info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + n ] ];
-					TOL = info->sampleSize + 2;
-					AddPointToBounds( info->mins, mins, maxs );
-					AddPointToBounds( info->maxs, mins, maxs );
-					if( origin[ 0 ] > (info->mins[ 0 ] - TOL) && origin[ 0 ] < (info->maxs[ 0 ] + TOL) &&
-						origin[ 1 ] > (info->mins[ 1 ] - TOL) && origin[ 1 ] < (info->maxs[ 1 ] + TOL) &&
-						origin[ 2 ] > (info->mins[ 2 ] - TOL) && origin[ 2 ] < (info->maxs[ 2 ] + TOL) )
-						break;
-				}
-				
-				/* inside? */
-				if( n < lm->numLightSurfaces )
-					continue;
-				
-				/* report bogus origin */
-				Sys_Printf( "%6d [%2d,%2d] (%4d): XYZ(%+4.1f %+4.1f %+4.1f) LO(%+4.1f %+4.1f %+4.1f) HI(%+4.1f %+4.1f %+4.1f) <%3.0f>\n",
-					rawLightmapNum, x, y, *cluster,
-					origin[ 0 ], origin[ 1 ], origin[ 2 ],
-					mins[ 0 ], mins[ 1 ], mins[ 2 ],
-					maxs[ 0 ], maxs[ 1 ], maxs[ 2 ],
-					luxel[ 3 ] );
-			}
-		}
-	#endif
-}
-
-
-
-/*
-SubmapRawLuxel()
-calculates the pvs cluster, origin, normal of a sub-luxel
-*/
-
-static qboolean SubmapRawLuxel( rawLightmap_t *lm, int x, int y, float bx, float by, int *sampleCluster, vec3_t sampleOrigin, vec3_t sampleNormal )
-{
-	int			i, *cluster, *cluster2;
-	float		*origin, *origin2, *normal;	//%	, *normal2;
-	vec3_t		originVecs[ 2 ];			//%	, normalVecs[ 2 ];
-	
-	
-	/* calulate x vector */
-	if( (x < (lm->sw - 1) && bx >= 0.0f) || (x == 0 && bx <= 0.0f) )
-	{
-		cluster = SUPER_CLUSTER( x, y );
-		origin = SUPER_ORIGIN( x, y );
-		//%	normal = SUPER_NORMAL( x, y );
-		cluster2 = SUPER_CLUSTER( x + 1, y );
-		origin2 = *cluster2 < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x + 1, y );
-		//%	normal2 = *cluster2 < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x + 1, y );
-	}
-	else if( (x > 0 && bx <= 0.0f) || (x == (lm->sw - 1) && bx >= 0.0f) )
-	{
-		cluster = SUPER_CLUSTER( x - 1, y );
-		origin = *cluster < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x - 1, y );
-		//%	normal = *cluster < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x - 1, y );
-		cluster2 = SUPER_CLUSTER( x, y );
-		origin2 = SUPER_ORIGIN( x, y );
-		//%	normal2 = SUPER_NORMAL( x, y );
-	}
-	else
-		Sys_Printf( "WARNING: Spurious lightmap S vector\n" );
-	
-	VectorSubtract( origin2, origin, originVecs[ 0 ] );
-	//%	VectorSubtract( normal2, normal, normalVecs[ 0 ] );
-	
-	/* calulate y vector */
-	if( (y < (lm->sh - 1) && bx >= 0.0f) || (y == 0 && bx <= 0.0f) )
-	{
-		cluster = SUPER_CLUSTER( x, y );
-		origin = SUPER_ORIGIN( x, y );
-		//%	normal = SUPER_NORMAL( x, y );
-		cluster2 = SUPER_CLUSTER( x, y + 1 );
-		origin2 = *cluster2 < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x, y + 1 );
-		//%	normal2 = *cluster2 < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x, y + 1 );
-	}
-	else if( (y > 0 && bx <= 0.0f) || (y == (lm->sh - 1) && bx >= 0.0f) )
-	{
-		cluster = SUPER_CLUSTER( x, y - 1 );
-		origin = *cluster < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x, y - 1 );
-		//%	normal = *cluster < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x, y - 1 );
-		cluster2 = SUPER_CLUSTER( x, y );
-		origin2 = SUPER_ORIGIN( x, y );
-		//%	normal2 = SUPER_NORMAL( x, y );
-	}
-	else
-		Sys_Printf( "WARNING: Spurious lightmap T vector\n" );
-	
-	VectorSubtract( origin2, origin, originVecs[ 1 ] );
-	//%	VectorSubtract( normal2, normal, normalVecs[ 1 ] );
-	
-	/* calculate new origin */
-	//%	VectorMA( origin, bx, originVecs[ 0 ], sampleOrigin );
-	//%	VectorMA( sampleOrigin, by, originVecs[ 1 ], sampleOrigin );
-	for( i = 0; i < 3; i++ )
-		sampleOrigin[ i ] = sampleOrigin[ i ] + (bx * originVecs[ 0 ][ i ]) + (by * originVecs[ 1 ][ i ]);
-	
-	/* get cluster */
-	*sampleCluster = ClusterForPointExtFilter( sampleOrigin, (LUXEL_EPSILON * 2), lm->numLightClusters, lm->lightClusters );
-	if( *sampleCluster < 0 )
-		return qfalse;
-	
-	/* calculate new normal */
-	//%	VectorMA( normal, bx, normalVecs[ 0 ], sampleNormal );
-	//%	VectorMA( sampleNormal, by, normalVecs[ 1 ], sampleNormal );
-	//%	if( VectorNormalize( sampleNormal, sampleNormal ) <= 0.0f )
-	//%		return qfalse;
-	normal = SUPER_NORMAL( x, y );
-	VectorCopy( normal, sampleNormal );
-	
-	/* return ok */
-	return qtrue;
-}
-
-
-/*
-SubsampleRawLuxel_r()
-recursively subsamples a luxel until its color gradient is low enough or subsampling limit is reached
-*/
-
-void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampleOrigin, int x, int y, float bias, float *lightLuxel )
-{
-	int			b, samples, mapped, lighted;
-	int			cluster[ 4 ];
-	vec4_t		luxel[ 4 ];
-	vec3_t		origin[ 4 ], normal[ 4 ];
-	float		biasDirs[ 4 ][ 2 ] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { -1.0f, 1.0f }, { 1.0f, 1.0f } };
-	vec3_t		color, total;
-	
-	
-	/* limit check */
-	if( lightLuxel[ 3 ] >= lightSamples )
-		return;
-	
-	/* setup */
-	VectorClear( total );
-	mapped = 0;
-	lighted = 0;
-	
-	/* make 2x2 subsample stamp */
-	for( b = 0; b < 4; b++ )
-	{
-		/* set origin */
-		VectorCopy( sampleOrigin, origin[ b ] );
-		
-		/* calculate position */
-		if( !SubmapRawLuxel( lm, x, y, (bias * biasDirs[ b ][ 0 ]), (bias * biasDirs[ b ][ 1 ]), &cluster[ b ], origin[ b ], normal[ b ] ) )
-		{
-			cluster[ b ] = -1;
-			continue;
-		}
-		mapped++;
-		
-		/* increment sample count */
-		luxel[ b ][ 3 ] = lightLuxel[ 3 ] + 1.0f;
-		
-		/* setup trace */
-		trace->cluster = *cluster;
-		VectorCopy( origin[ b ], trace->origin );
-		VectorCopy( normal[ b ], trace->normal );
-		
-		/* sample light */
-		//%	LightContributionToSample( light, cluster[ b ], origin[ b ], normal[ b ], luxel[ b ], qtrue, qfalse, lm->numLightSurfaces, &lightSurfaces[ lm->firstLightSurface ] );
-		LightContributionToSample( trace );
-		
-		/* add to totals (fixme: make contrast function) */
-		VectorCopy( trace->color, luxel[ b ] );
-		VectorAdd( total, trace->color, total );
-		if( (luxel[ b ][ 0 ] + luxel[ b ][ 1 ] + luxel[ b ][ 2 ]) > 0.0f )
-			lighted++;
-	}
-	
-	/* subsample further? */
-	if( (lightLuxel[ 3 ] + 1.0f) < lightSamples &&
-		(total[ 0 ] > 4.0f || total[ 1 ] > 4.0f || total[ 2 ] > 4.0f) &&
-		lighted != 0 && lighted != mapped )
-	{
-		for( b = 0; b < 4; b++ )
-		{
-			if( cluster[ b ] < 0 )
-				continue;
-			SubsampleRawLuxel_r( lm, trace, origin[ b ], x, y, (bias * 0.25f), luxel[ b ] );
-		}
-	}
-	
-	/* average */
-	//%	VectorClear( color );
-	//%	samples = 0;
-	VectorCopy( lightLuxel, color );
-	samples = 1;
-	for( b = 0; b < 4; b++ )
-	{
-		if( cluster[ b ] < 0 )
-			continue;
-		VectorAdd( color, luxel[ b ], color );
-		samples++;
-	}
-	
-	/* add to luxel */
-	if( samples > 0 )
-	{
-		/* average */
-		color[ 0 ] /= samples;
-		color[ 1 ] /= samples;
-		color[ 2 ] /= samples;
-		
-		/* add to color */
-		VectorCopy( color, lightLuxel );
-		lightLuxel[ 3 ] += 1.0f;
-	}
-}
-
-
-
-/*
-IlluminateRawLightmap()
-illuminates the luxels
-*/
-
-#define LIGHT_LUXEL( x, y )		(lightLuxels + ((((y) * lm->sw) + (x)) * SUPER_LUXEL_SIZE))
-
-void IlluminateRawLightmap( int rawLightmapNum )
-{
-	int					i, t, x, y, sx, sy, size, llSize, luxelFilterRadius, lightmapNum;
-	int					*cluster, *cluster2, mapped, lighted, totalLighted;
-	rawLightmap_t		*lm;
-	surfaceInfo_t		*info;
-	qboolean			filterColor, filterDir;
-	float				brightness;
-	float				*origin, *normal, *luxel, *luxel2, *deluxel, *deluxel2;
-	float				*lightLuxels, *lightLuxel, samples, filterRadius, weight;
-	vec3_t				color, averageColor, averageDir, total, temp, temp2;
-	float				tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
-	trace_t				trace;
-	
-	
-	/* bail if this number exceeds the number of raw lightmaps */
-	if( rawLightmapNum >= numRawLightmaps )
-		return;
-	
-	/* get lightmap */
-	lm = &rawLightmaps[ rawLightmapNum ];
-	
-	/* setup trace */
-	trace.testOcclusion = !noTrace;
-	trace.forceSunlight = qfalse;
-	trace.recvShadows = lm->recvShadows;
-	trace.numSurfaces = lm->numLightSurfaces;
-	trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
-	trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
-	
-	/* twosided lighting (may or may not be a good idea for lightmapped stuff) */
-	trace.twoSided = qfalse;
-	for( i = 0; i < trace.numSurfaces; i++ )
-	{
-		/* get surface */
-		info = &surfaceInfos[ trace.surfaces[ i ] ];
-		
-		/* check twosidedness */
-		if( info->si->twoSided )
-		{
-			trace.twoSided = qtrue;
-			break;
-		}
-	}
-	
-	/* create a culled light list for this raw lightmap */
-	CreateTraceLightsForBounds( lm->mins, lm->maxs, lm->plane, lm->numLightClusters, lm->lightClusters, LIGHT_SURFACES, &trace );
-	
-	/* -----------------------------------------------------------------
-	   fill pass
-	   ----------------------------------------------------------------- */
-	
-	/* test debugging state */
-	if( debugSurfaces || debugAxis || debugCluster || debugOrigin || normalmap )
-	{
-		/* debug fill the luxels */
-		for( y = 0; y < lm->sh; y++ )
-		{
-			for( x = 0; x < lm->sw; x++ )
-			{
-				/* get cluster */
-				cluster = SUPER_CLUSTER( x, y );
-
-				/* only fill mapped luxels */
-				if( *cluster < 0 )
-					continue;
-				
-				/* get particulars */
-				luxel = SUPER_LUXEL( 0, x, y );
-				origin = SUPER_ORIGIN( x, y );
-				normal = SUPER_NORMAL( x, y );
-				
-				/* color the luxel with raw lightmap num? */
-				if( debugSurfaces )
-					VectorCopy( debugColors[ rawLightmapNum % 12 ], luxel );
-				
-				/* color the luxel with lightmap axis? */
-				else if( debugAxis )
-				{
-					luxel[ 0 ] = (lm->axis[ 0 ] + 1.0f) * 127.5f;
-					luxel[ 1 ] = (lm->axis[ 1 ] + 1.0f) * 127.5f;
-					luxel[ 2 ] = (lm->axis[ 2 ] + 1.0f) * 127.5f;
-				}
-				
-				/* color the luxel with luxel cluster? */
-				else if( debugCluster )
-					VectorCopy( debugColors[ *cluster % 12 ], luxel );
-				
-				/* color the luxel with luxel origin? */
-				else if( debugOrigin )
-				{
-					VectorSubtract( lm->maxs, lm->mins, temp );
-					VectorScale( temp, (1.0f / 255.0f), temp );
-					VectorSubtract( origin, lm->mins, temp2 );
-					luxel[ 0 ] = lm->mins[ 0 ] + (temp[ 0 ] * temp2[ 0 ]);
-					luxel[ 1 ] = lm->mins[ 1 ] + (temp[ 1 ] * temp2[ 1 ]);
-					luxel[ 2 ] = lm->mins[ 2 ] + (temp[ 2 ] * temp2[ 2 ]);
-				}
-				
-				/* color the luxel with the normal */
-				else if( normalmap )
-				{
-					luxel[ 0 ] = (normal[ 0 ] + 1.0f) * 127.5f;
-					luxel[ 1 ] = (normal[ 1 ] + 1.0f) * 127.5f;
-					luxel[ 2 ] = (normal[ 2 ] + 1.0f) * 127.5f;
-				}
-				
-				/* add to counts */
-				numLuxelsIlluminated++;
-				luxel[ 3 ] = 1.0f;
-			}
-		}
-	}
-	else
-	{
-		/* allocate temporary per-light luxel storage */
-		llSize = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
-		lightLuxels = safe_malloc( llSize );
-		
-		/* clear luxels */
-		//%	memset( lm->superLuxels[ 0 ], 0, llSize );
-		
-		/* set ambient color */
-		for( y = 0; y < lm->sh; y++ )
-		{
-			for( x = 0; x < lm->sw; x++ )
-			{
-				/* get cluster */
-				cluster = SUPER_CLUSTER( x, y );
-				luxel = SUPER_LUXEL( 0, x, y );
-				normal = SUPER_NORMAL( x, y );
-				deluxel = SUPER_DELUXEL( x, y );
-				
-				/* blacken unmapped clusters */
-				if( *cluster < 0 )
-					VectorClear( luxel );
-				
-				/* set ambient */
-				else
-				{
-					VectorCopy( ambientColor, luxel );
-					if( deluxemap )
-						VectorScale( normal, 0.00390625f, deluxel );
-					luxel[ 3 ] = 1.0f;
-				}
-			}
-		}
-		
-		/* clear styled lightmaps */
-		size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
-		for( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		{
-			if( lm->superLuxels[ lightmapNum ] != NULL )
-				memset( lm->superLuxels[ lightmapNum ], 0, size );
-		}
-		
-		/* debugging code */
-		//%	if( trace.numLights <= 0 )
-		//%		Sys_Printf( "Lightmap %9d: 0 lights, axis: %.2f, %.2f, %.2f\n", rawLightmapNum, lm->axis[ 0 ], lm->axis[ 1 ], lm->axis[ 2 ] );
-		
-		/* walk light list */
-		for( i = 0; i < trace.numLights; i++ )
-		{
-			/* setup trace */
-			trace.light = trace.lights[ i ];
-			
-			/* style check */
-			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				if( lm->styles[ lightmapNum ] == trace.light->style ||
-					lm->styles[ lightmapNum ] == LS_NONE )
-					break;
-			}
-			
-			/* max of MAX_LIGHTMAPS (4) styles allowed to hit a surface/lightmap */
-			if( lightmapNum >= MAX_LIGHTMAPS )
-			{
-				Sys_Printf( "WARNING: Hit per-surface style limit (%d)\n", MAX_LIGHTMAPS );
-				continue;
-			}
-			
-			/* setup */
-			memset( lightLuxels, 0, llSize );
-			totalLighted = 0;
-			
-			/* initial pass, one sample per luxel */
-			for( y = 0; y < lm->sh; y++ )
-			{
-				for( x = 0; x < lm->sw; x++ )
-				{
-					/* get cluster */
-					cluster = SUPER_CLUSTER( x, y );
-					if( *cluster < 0 )
-						continue;
-					
-					/* get particulars */
-					lightLuxel = LIGHT_LUXEL( x, y );
-					deluxel = SUPER_DELUXEL( x, y );
-					origin = SUPER_ORIGIN( x, y );
-					normal = SUPER_NORMAL( x, y );
-					
-					/* set contribution count */
-					lightLuxel[ 3 ] = 1.0f;
-					
-					/* setup trace */
-					trace.cluster = *cluster;
-					VectorCopy( origin, trace.origin );
-					VectorCopy( normal, trace.normal );
-					
-					/* get light for this sample */
-					LightContributionToSample( &trace );
-					VectorCopy( trace.color, lightLuxel );
-					
-					/* add to count */
-					if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
-						totalLighted++;
-					
-					/* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
-					if( deluxemap )
-					{
-						/* color to grayscale (photoshop rgb weighting) */
-						brightness = trace.color[ 0 ] * 0.3f + trace.color[ 1 ] * 0.59f + trace.color[ 2 ] * 0.11f;
-						brightness *= (1.0 / 255.0);
-						VectorScale( trace.direction, brightness, trace.direction );
-						VectorAdd( deluxel, trace.direction, deluxel );
-					}
-				}
-			}
-			
-			/* don't even bother with everything else if nothing was lit */
-			if( totalLighted == 0 )
-				continue;
-			
-			/* determine filter radius */
-			filterRadius = lm->filterRadius > trace.light->filterRadius
-				? lm->filterRadius
-				: trace.light->filterRadius;
-			if( filterRadius < 0.0f )
-				filterRadius = 0.0f;
-			
-			/* set luxel filter radius */
-			luxelFilterRadius = superSample * filterRadius / lm->sampleSize;
-			if( luxelFilterRadius == 0 && (filterRadius > 0.0f || filter) )
-				luxelFilterRadius = 1;
-			
-			/* secondary pass, adaptive supersampling (fixme: use a contrast function to determine if subsampling is necessary) */
-			/* 2003-09-27: changed it so filtering disamples supersampling, as it would waste time */
-			if( lightSamples > 1 && luxelFilterRadius == 0 )
-			{
-				/* walk luxels */
-				for( y = 0; y < (lm->sh - 1); y++ )
-				{
-					for( x = 0; x < (lm->sw - 1); x++ )
-					{
-						/* setup */
-						mapped = 0;
-						lighted = 0;
-						VectorClear( total );
-						
-						/* test 2x2 stamp */
-						for( t = 0; t < 4; t++ )
-						{
-							/* set sample coords */
-							sx = x + tests[ t ][ 0 ];
-							sy = y + tests[ t ][ 1 ];
-							
-							/* get cluster */
-							cluster = SUPER_CLUSTER( sx, sy );
-							if( *cluster < 0 )
-								continue;
-							mapped++;
-							
-							/* get luxel */
-							lightLuxel = LIGHT_LUXEL( sx, sy );
-							VectorAdd( total, lightLuxel, total );
-							if( (lightLuxel[ 0 ] + lightLuxel[ 1 ] + lightLuxel[ 2 ]) > 0.0f )
-								lighted++;
-						}
-						
-						/* if total color is under a certain amount, then don't bother subsampling */
-						if( total[ 0 ] <= 4.0f && total[ 1 ] <= 4.0f && total[ 2 ] <= 4.0f )
-							continue;
-						
-						/* if all 4 pixels are either in shadow or light, then don't subsample */
-						if( lighted != 0 && lighted != mapped )
-						{
-							for( t = 0; t < 4; t++ )
-							{
-								/* set sample coords */
-								sx = x + tests[ t ][ 0 ];
-								sy = y + tests[ t ][ 1 ];
-								
-								/* get luxel */
-								cluster = SUPER_CLUSTER( sx, sy );
-								if( *cluster < 0 )
-									continue;
-								lightLuxel = LIGHT_LUXEL( sx, sy );
-								origin = SUPER_ORIGIN( sx, sy );
-								
-								/* only subsample shadowed luxels */
-								//%	if( (lightLuxel[ 0 ] + lightLuxel[ 1 ] + lightLuxel[ 2 ]) <= 0.0f )
-								//%		continue;
-								
-								/* subsample it */
-								SubsampleRawLuxel_r( lm, &trace, origin, sx, sy, 0.25f, lightLuxel );
-								
-								/* debug code to colorize subsampled areas to yellow */
-								//%	luxel = SUPER_LUXEL( lightmapNum, sx, sy );
-								//%	VectorSet( luxel, 255, 204, 0 );
-							}
-						}
-					}
-				}
-			}
-			
-			/* allocate sampling lightmap storage */
-			if( lm->superLuxels[ lightmapNum ] == NULL )
-			{
-				/* allocate sampling lightmap storage */
-				size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
-				lm->superLuxels[ lightmapNum ] = safe_malloc( size );
-				memset( lm->superLuxels[ lightmapNum ], 0, size );
-			}
-			
-			/* set style */
-			if( lightmapNum > 0 )
-			{
-				lm->styles[ lightmapNum ] = trace.light->style;
-				//%	Sys_Printf( "Surface %6d has lightstyle %d\n", rawLightmapNum, trace.light->style );
-			}
-			
-			/* copy to permanent luxels */
-			for( y = 0; y < lm->sh; y++ )
-			{
-				for( x = 0; x < lm->sw; x++ )
-				{
-					/* get cluster and origin */
-					cluster = SUPER_CLUSTER( x, y );
-					if( *cluster < 0 )
-						continue;
-					origin = SUPER_ORIGIN( x, y );
-					
-					/* filter? */
-					if( luxelFilterRadius )
-					{
-						/* setup */
-						VectorClear( averageColor );
-						samples = 0.0f;
-						
-						/* cheaper distance-based filtering */
-						for( sy = (y - luxelFilterRadius); sy <= (y + luxelFilterRadius); sy++ )
-						{
-							if( sy < 0 || sy >= lm->sh )
-								continue;
-							
-							for( sx = (x - luxelFilterRadius); sx <= (x + luxelFilterRadius); sx++ )
-							{
-								if( sx < 0 || sx >= lm->sw )
-									continue;
-								
-								/* get particulars */
-								cluster = SUPER_CLUSTER( sx, sy );
-								if( *cluster < 0 )
-									continue;
-								lightLuxel = LIGHT_LUXEL( sx, sy );
-								
-								/* create weight */
-								weight = (abs( sx - x ) == luxelFilterRadius ? 0.5f : 1.0f);
-								weight *= (abs( sy - y ) == luxelFilterRadius ? 0.5f : 1.0f);
-								
-								/* scale luxel by filter weight */
-								VectorScale( lightLuxel, weight, color );
-								VectorAdd( averageColor, color, averageColor );
-								samples += weight;
-							}
-						}
-						
-						/* any samples? */
-						if( samples <= 0.0f	)
-							continue;
-						
-						/* scale into luxel */
-						luxel = SUPER_LUXEL( lightmapNum, x, y );
-						luxel[ 3 ] = 1.0f;
-						
-						/* handle negative light */
-						if( trace.light->flags & LIGHT_NEGATIVE )
-						{ 
-							luxel[ 0 ] -= averageColor[ 0 ] / samples;
-							luxel[ 1 ] -= averageColor[ 1 ] / samples;
-							luxel[ 2 ] -= averageColor[ 2 ] / samples;
-						}
-						
-						/* handle normal light */
-						else
-						{ 
-							luxel[ 0 ] += averageColor[ 0 ] / samples;
-							luxel[ 1 ] += averageColor[ 1 ] / samples;
-							luxel[ 2 ] += averageColor[ 2 ] / samples;
-						}
-					}
-					
-					/* single sample */
-					else
-					{
-						/* get particulars */
-						lightLuxel = LIGHT_LUXEL( x, y );
-						luxel = SUPER_LUXEL( lightmapNum, x, y );
-						
-						/* handle negative light */
-						if( trace.light->flags & LIGHT_NEGATIVE )
-							VectorScale( averageColor, -1.0f, averageColor );
-
-						/* add color */
-						luxel[ 3 ] = 1.0f;
-						
-						/* handle negative light */
-						if( trace.light->flags & LIGHT_NEGATIVE )
-							VectorSubtract( luxel, lightLuxel, luxel );
-						
-						/* handle normal light */
-						else
-							VectorAdd( luxel, lightLuxel, luxel );
-					}
-				}
-			}
-		}
-		
-		/* free temporary luxels */
-		free( lightLuxels );
-	}
-	
-	/* free light list */
-	FreeTraceLights( &trace );
-	
-	/* -----------------------------------------------------------------
-	   filter pass
-	   ----------------------------------------------------------------- */
-	
-	/* walk lightmaps */
-	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-	{
-		/* early out */
-		if( lm->superLuxels[ lightmapNum ] == NULL )
-			continue;
-		
-		/* average occluded luxels from neighbors */
-		for( y = 0; y < lm->sh; y++ )
-		{
-			for( x = 0; x < lm->sw; x++ )
-			{
-				/* get particulars */
-				cluster = SUPER_CLUSTER( x, y );
-				luxel = SUPER_LUXEL( lightmapNum, x, y );
-				deluxel = SUPER_DELUXEL( x, y );
-				normal = SUPER_NORMAL( x, y );
-				
-				/* determine if filtering is necessary */
-				filterColor = qfalse;
-				filterDir = qfalse;
-				if( *cluster < 0 ||
-					(lm->splotchFix && (luxel[ 0 ] <= ambientColor[ 0 ] || luxel[ 1 ] <= ambientColor[ 1 ] || luxel[ 2 ] <= ambientColor[ 2 ])) )
-					filterColor = qtrue;
-				if( deluxemap && lightmapNum == 0 && (*cluster < 0 || filter) )
-					filterDir = qtrue;
-				
-				if( !filterColor && !filterDir )
-					continue;
-				
-				/* choose seed amount */
-				VectorClear( averageColor );
-				VectorClear( averageDir );
-				samples = 0;
-				
-				/* walk 3x3 matrix */
-				for( sy = (y - 1); sy <= (y + 1); sy++ )
-				{
-					if( sy < 0 || sy >= lm->sh )
-						continue;
-					
-					for( sx = (x - 1); sx <= (x + 1); sx++ )
-					{
-						if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
-							continue;
-						
-						/* get neighbor's particulars */
-						cluster2 = SUPER_CLUSTER( sx, sy );
-						luxel2 = SUPER_LUXEL( lightmapNum, sx, sy );
-						deluxel2 = SUPER_DELUXEL( sx, sy );
-						
-						/* ignore unmapped/unlit luxels */
-						if( *cluster2 < 0 || luxel2[ 3 ] == 0.0f ||
-							(lm->splotchFix && VectorCompare( luxel2, ambientColor )) )
-							continue;
-						
-						/* add its distinctiveness to our own */
-						VectorAdd( averageColor, luxel2, averageColor );
-						samples += luxel2[ 3 ];
-						if( filterDir )
-							VectorAdd( averageDir, deluxel2, averageDir );
-					}
-				}
-				
-				/* fall through */
-				if( samples == 0.0f )
-					continue;
-				
-				/* average it */
-				if( filterColor )
-				{
-					VectorDivide( averageColor, samples, luxel );
-					luxel[ 3 ] = 1.0f;
-				}
-				if( filterDir )
-					VectorDivide( averageDir, samples, deluxel );
-				
-				/* set cluster to -3 */
-				if( *cluster < 0 )
-					*cluster = CLUSTER_FLOODED;
-			}
-		}
-	}
-}
-
-
-
-/*
-IlluminateVertexes()
-light the surface vertexes
-*/
-
-#define VERTEX_NUDGE	2.0f
-
-void IlluminateVertexes( int num )
-{
-	int					i, x, y, z, x1, y1, z1, sx, sy, radius, maxRadius, *cluster;
-	int					lightmapNum;
-	float				samples, *vertLuxel, *radVertLuxel, *luxel;
-	vec3_t				origin, temp, temp2, colors[ MAX_LIGHTMAPS ];
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	rawLightmap_t		*lm;
-	bspDrawVert_t		*verts;
-	trace_t				trace;
-	
-	
-	/* der... */
-	if( noVertexLighting )
-		return;
-	
-	/* get surface, info, and raw lightmap */
-	ds = &bspDrawSurfaces[ num ];
-	info = &surfaceInfos[ num ];
-	lm = info->lm;
-	
-	/* -----------------------------------------------------------------
-	   illuminate the vertexes
-	   ----------------------------------------------------------------- */
-	
-	/* calculate vertex lighting for surfaces without lightmaps */
-	if( lm == NULL )
-	{
-		/* setup trace */
-		trace.testOcclusion = !noTrace;
-		trace.forceSunlight = info->si->forceSunlight;
-		trace.recvShadows = info->recvShadows;
-		trace.numSurfaces = 1;
-		trace.surfaces = &num;
-		trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
-		
-		/* twosided lighting */
-		trace.twoSided = info->si->twoSided;
-		
-		/* make light list for this surface */
-		CreateTraceLightsForSurface( num, &trace );
-		
-		/* walk the surface verts */
-		verts = yDrawVerts + ds->firstVert;
-		for( i = 0; i < ds->numVerts; i++ )
-		{
-			/* get vertex luxel */
-			radVertLuxel = RAD_VERTEX_LUXEL( 0, ds->firstVert + i );
-			
-			/* color the luxel with raw lightmap num? */
-			if( debugSurfaces )
-				VectorCopy( debugColors[ num % 12 ], radVertLuxel );
-			
-			/* color the luxel with luxel origin? */
-			else if( debugOrigin )
-			{
-				VectorSubtract( info->maxs, info->mins, temp );
-				VectorScale( temp, (1.0f / 255.0f), temp );
-				VectorSubtract( origin, lm->mins, temp2 );
-				radVertLuxel[ 0 ] = info->mins[ 0 ] + (temp[ 0 ] * temp2[ 0 ]);
-				radVertLuxel[ 1 ] = info->mins[ 1 ] + (temp[ 1 ] * temp2[ 1 ]);
-				radVertLuxel[ 2 ] = info->mins[ 2 ] + (temp[ 2 ] * temp2[ 2 ]);
-			}
-			
-			/* color the luxel with the normal */
-			else if( normalmap )
-			{
-				radVertLuxel[ 0 ] = (verts[ i ].normal[ 0 ] + 1.0f) * 127.5f;
-				radVertLuxel[ 1 ] = (verts[ i ].normal[ 1 ] + 1.0f) * 127.5f;
-				radVertLuxel[ 2 ] = (verts[ i ].normal[ 2 ] + 1.0f) * 127.5f;
-			}
-			
-			/* illuminate the vertex */
-			else
-			{
-				/* clear vertex luxel */
-				VectorCopy( ambientColor, radVertLuxel );
-				
-				/* try at initial origin */
-				trace.cluster = ClusterForPointExtFilter( verts[ i ].xyz, VERTEX_EPSILON, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ] );
-				if( trace.cluster >= 0 )
-				{
-					/* setup trace */
-					VectorCopy( verts[ i ].xyz, trace.origin );
-					VectorCopy( verts[ i ].normal, trace.normal );
-					
-					/* trace */
-					LightingAtSample( &trace, ds->vertexStyles, colors );
-					
-					/* store */
-					for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-					{
-						radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
-						VectorCopy( colors[ lightmapNum ], radVertLuxel );
-					}
-				}
-				
-				/* is this sample bright enough? */
-				if( radVertLuxel[ 0 ] <= ambientColor[ 0 ] &&
-					radVertLuxel[ 1 ] <= ambientColor[ 1 ] &&
-					radVertLuxel[ 2 ] <= ambientColor[ 2 ] )
-				{
-					/* nudge the sample point around a bit */
-					for( x = 0; x < 4; x++ )
-					{
-						/* two's complement 0, 1, -1, 2, -2, etc */
-						x1 = ((x >> 1) ^ (x & 1 ? -1 : 0)) + (x & 1);
-						
-						for( y = 0; y < 4; y++ )
-						{
-							y1 = ((y >> 1) ^ (y & 1 ? -1 : 0)) + (y & 1);
-							
-							for( z = 0; z < 4; z++ )
-							{
-								z1 = ((z >> 1) ^ (z & 1 ? -1 : 0)) + (z & 1);
-								
-								/* nudge origin */
-								trace.origin[ 0 ] = verts[ i ].xyz[ 0 ] + (VERTEX_NUDGE * x1);
-								trace.origin[ 1 ] = verts[ i ].xyz[ 1 ] + (VERTEX_NUDGE * y1);
-								trace.origin[ 2 ] = verts[ i ].xyz[ 2 ] + (VERTEX_NUDGE * z1);
-								
-								/* try at nudged origin */
-								trace.cluster = ClusterForPointExtFilter( origin, VERTEX_EPSILON, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ] );
-								if( trace.cluster < 0 )
-									continue;
-															
-								/* trace */
-								LightingAtSample( &trace, ds->vertexStyles, colors );
-								
-								/* store */
-								for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-								{
-									radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
-									VectorCopy( colors[ lightmapNum ], radVertLuxel );
-								}
-								
-								/* bright enough? */
-								radVertLuxel = RAD_VERTEX_LUXEL( 0, ds->firstVert + i );
-								if( radVertLuxel[ 0 ] > ambientColor[ 0 ] ||
-									radVertLuxel[ 1 ] > ambientColor[ 1 ] ||
-									radVertLuxel[ 2 ] > ambientColor[ 2 ] )
-									x = y = z = 1000;
-							}
-						}
-					}
-				}
-			}
-			
-			/* another happy customer */
-			numVertsIlluminated++;
-			
-			/* store it */
-			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				/* get luxels */
-				vertLuxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
-				radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
-				
-				/* store */
-				if( bouncing || bounce == 0 || !bounceOnly )
-					VectorAdd( vertLuxel, radVertLuxel, vertLuxel );
-				ColorToBytes( vertLuxel, verts[ i ].color[ lightmapNum ], info->si->vertexScale );
-			}
-		}
-		
-		/* free light list */
-		FreeTraceLights( &trace );
-		
-		/* return to sender */
-		return;
-	}
-	
-	/* -----------------------------------------------------------------
-	   reconstitute vertex lighting from the luxels
-	   ----------------------------------------------------------------- */
-	
-	/* set styles from lightmap */
-	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		ds->vertexStyles[ lightmapNum ] = lm->styles[ lightmapNum ];
-	
-	/* get max search radius */
-	maxRadius = lm->sw;
-	maxRadius = maxRadius > lm->sh ? maxRadius : lm->sh;
-	
-	/* walk the surface verts */
-	verts = yDrawVerts + ds->firstVert;
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		/* do each lightmap */
-		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		{
-			/* early out */
-			if( lm->superLuxels[ lightmapNum ] == NULL )
-				continue;
-			
-			/* get luxel coords */
-			x = verts[ i ].lightmap[ lightmapNum ][ 0 ];
-			y = verts[ i ].lightmap[ lightmapNum ][ 1 ];
-			if( x < 0 )
-				x = 0;
-			else if( x >= lm->sw )
-				x = lm->sw - 1;
-			if( y < 0 )
-				y = 0;
-			else if( y >= lm->sh )
-				y = lm->sh - 1;
-			
-			/* get vertex luxels */
-			vertLuxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
-			radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
-			
-			/* color the luxel with the normal? */
-			if( normalmap )
-			{
-				radVertLuxel[ 0 ] = (verts[ i ].normal[ 0 ] + 1.0f) * 127.5f;
-				radVertLuxel[ 1 ] = (verts[ i ].normal[ 1 ] + 1.0f) * 127.5f;
-				radVertLuxel[ 2 ] = (verts[ i ].normal[ 2 ] + 1.0f) * 127.5f;
-			}
-			
-			/* color the luxel with surface num? */
-			else if( debugSurfaces )
-				VectorCopy( debugColors[ num % 12 ], radVertLuxel );
-			
-			/* divine color from the superluxels */
-			else
-			{
-				/* increasing radius */
-				VectorClear( radVertLuxel );
-				samples = 0.0f;
-				for( radius = 0; radius < maxRadius && samples <= 0.0f; radius++ )
-				{
-					/* sample within radius */
-					for( sy = (y - radius); sy <= (y + radius); sy++ )
-					{
-						if( sy < 0 || sy >= lm->sh )
-							continue;
-						
-						for( sx = (x - radius); sx <= (x + radius); sx++ )
-						{
-							if( sx < 0 || sx >= lm->sw )
-								continue;
-							
-							/* get luxel particulars */
-							luxel = SUPER_LUXEL( lightmapNum, sx, sy );
-							cluster = SUPER_CLUSTER( sx, sy );
-							if( *cluster < 0 )
-								continue;
-							
-							/* testing: must be brigher than ambient color */
-							//%	if( luxel[ 0 ] <= ambientColor[ 0 ] || luxel[ 1 ] <= ambientColor[ 1 ] || luxel[ 2 ] <= ambientColor[ 2 ] )
-							//%		continue;
-							
-							/* add its distinctiveness to our own */
-							VectorAdd( radVertLuxel, luxel, radVertLuxel );
-							samples += luxel[ 3 ];
-						}
-					}
-				}
-				
-				/* any color? */
-				if( samples > 0.0f )
-					VectorDivide( radVertLuxel, samples, radVertLuxel );
-				else
-					VectorCopy( ambientColor, radVertLuxel );
-			}
-			
-			/* store into floating point storage */
-			VectorAdd( vertLuxel, radVertLuxel, vertLuxel );
-			numVertsIlluminated++;
-			
-			/* store into bytes (for vertex approximation) */
-			ColorToBytes( vertLuxel, verts[ i ].color[ lightmapNum ], 1.0f );
-		}
-	}
-}
-
-
-
-/* -------------------------------------------------------------------------------
-
-light optimization (-fast)
-
-creates a list of lights that will affect a surface and stores it in tw
-this is to optimize surface lighting by culling out as many of the
-lights in the world as possible from further calculation
-
-------------------------------------------------------------------------------- */
-
-/*
-SetupBrushes()
-determines opaque brushes in the world and find sky shaders for sunlight calculations
-*/
-
-void SetupBrushes( void )
-{
-	int				i, j, b, compileFlags;
-	qboolean		inside;
-	bspBrush_t		*brush;
-	bspBrushSide_t	*side;
-	bspShader_t		*shader;
-	shaderInfo_t	*si;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- SetupBrushes ---\n" );
-	
-	/* allocate */
-	if( opaqueBrushes == NULL )
-		opaqueBrushes = safe_malloc( numBSPBrushes / 8 + 1 );
-	
-	/* clear */
-	memset( opaqueBrushes, 0, numBSPBrushes / 8 + 1 );
-	numOpaqueBrushes = 0;
-	
-	/* walk the list of worldspawn brushes */
-	for( i = 0; i < bspModels[ 0 ].numBSPBrushes; i++ )
-	{
-		/* get brush */
-		b = bspModels[ 0 ].firstBSPBrush + i;
-		brush = &bspBrushes[ b ];
-		
-		/* check all sides */
-		inside = qtrue;
-		compileFlags = 0;
-		for( j = 0; j < brush->numSides && inside; j++ )
-		{
-			/* do bsp shader calculations */
-			side = &bspBrushSides[ brush->firstSide + j ];
-			shader = &bspShaders[ side->shaderNum ];
-			
-			/* get shader info */
-			si = ShaderInfoForShader( shader->shader );
-			if( si == NULL )
-				continue;
-			
-			/* or together compile flags */
-			compileFlags |= si->compileFlags;
-		}
-		
-		/* determine if this brush is opaque to light */
-		if( !(compileFlags & C_TRANSLUCENT) )
-		{
-			opaqueBrushes[ b >> 3 ] |= (1 << (b & 7));
-			numOpaqueBrushes++;
-			maxOpaqueBrush = i;
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d opaque brushes\n", numOpaqueBrushes );
-}
-
-
-
-/*
-ClusterVisible()
-determines if two clusters are visible to each other using the PVS
-*/
-
-qboolean ClusterVisible( int a, int b )
-{
-	int			portalClusters, leafBytes;
-	byte		*pvs;
-	
-	
-	/* dummy check */
-	if( a < 0 || b < 0 )
-		return qfalse;
-	
-	/* early out */
-	if( a == b )
-		return qtrue;
-	
-	/* not vised? */
-	if( numBSPVisBytes <=8 )
-		return qtrue;
-	
-	/* get pvs data */
-	portalClusters = ((int *) bspVisBytes)[ 0 ];
-	leafBytes = ((int*) bspVisBytes)[ 1 ];
-	pvs = bspVisBytes + VIS_HEADER_SIZE + (a * leafBytes);
-	
-	/* check */
-	if( (pvs[ b >> 3 ] & (1 << (b & 7))) )
-		return qtrue;
-	return qfalse;
-}
-
-
-
-/*
-PointInLeafNum_r()
-borrowed from vlight.c
-*/
-
-int	PointInLeafNum_r( vec3_t point, int nodenum )
-{
-	int			leafnum;
-	vec_t		dist;
-	bspNode_t		*node;
-	bspPlane_t	*plane;
-	
-	
-	while( nodenum >= 0 )
-	{
-		node = &bspNodes[ nodenum ];
-		plane = &bspPlanes[ node->planeNum ];
-		dist = DotProduct( point, plane->normal ) - plane->dist;
-		if( dist > 0.1 )
-			nodenum = node->children[ 0 ];
-		else if( dist < -0.1 )
-			nodenum = node->children[ 1 ];
-		else
-		{
-			leafnum = PointInLeafNum_r( point, node->children[ 0 ] );
-			if( bspLeafs[ leafnum ].cluster != -1 )
-				return leafnum;
-			nodenum = node->children[ 1 ];
-		}
-	}
-	
-	leafnum = -nodenum - 1;
-	return leafnum;
-}
-
-
-
-/*
-PointInLeafnum()
-borrowed from vlight.c
-*/
-
-int	PointInLeafNum( vec3_t point )
-{
-	return PointInLeafNum_r( point, 0 );
-}
-
-
-
-/*
-ClusterVisibleToPoint() - ydnar
-returns qtrue if point can "see" cluster
-*/
-
-qboolean ClusterVisibleToPoint( vec3_t point, int cluster )
-{
-	int		pointCluster;
-	
-
-	/* get leafNum for point */
-	pointCluster = ClusterForPoint( point );
-	if( pointCluster < 0 )
-		return qfalse;
-	
-	/* check pvs */
-	return ClusterVisible( pointCluster, cluster );
-}
-
-
-
-/*
-ClusterForPoint() - ydnar
-returns the pvs cluster for point
-*/
-
-int ClusterForPoint( vec3_t point )
-{
-	int		leafNum;
-	
-
-	/* get leafNum for point */
-	leafNum = PointInLeafNum( point );
-	if( leafNum < 0 )
-		return -1;
-	
-	/* return the cluster */
-	return bspLeafs[ leafNum ].cluster;
-}
-
-
-
-/*
-ClusterForPointExt() - ydnar
-also takes brushes into account for occlusion testing
-*/
-
-int ClusterForPointExt( vec3_t point, float epsilon )
-{
-	int				i, j, b, leafNum, cluster;
-	float			dot;
-	qboolean		inside;
-	int				*brushes, numBSPBrushes;
-	bspLeaf_t		*leaf;
-	bspBrush_t		*brush;
-	bspPlane_t		*plane;
-	
-	
-	/* get leaf for point */
-	leafNum = PointInLeafNum( point );
-	if( leafNum < 0 )
-		return -1;
-	leaf = &bspLeafs[ leafNum ];
-	
-	/* get the cluster */
-	cluster = leaf->cluster;
-	if( cluster < 0 )
-		return -1;
-	
-	/* transparent leaf, so check point against all brushes in the leaf */
-	brushes = &bspLeafBrushes[ leaf->firstBSPLeafBrush ];
-	numBSPBrushes = leaf->numBSPLeafBrushes;
-	for( i = 0; i < numBSPBrushes; i++ )
-	{
-		/* get parts */
-		b = brushes[ i ];
-		if( b > maxOpaqueBrush )
-			continue;
-		brush = &bspBrushes[ b ];
-		if( !(opaqueBrushes[ b >> 3 ] & (1 << (b & 7))) )
-			continue;
-		
-		/* check point against all planes */
-		inside = qtrue;
-		for( j = 0; j < brush->numSides && inside; j++ )
-		{
-			plane = &bspPlanes[ bspBrushSides[ brush->firstSide + j ].planeNum ];
-			dot = DotProduct( point, plane->normal );
-			dot -= plane->dist;
-			if( dot > epsilon )
-				inside = qfalse;
-		}
-		
-		/* if inside, return bogus cluster */
-		if( inside )
-			return -1 - b;
-	}
-	
-	/* if the point made it this far, it's not inside any opaque brushes */
-	return cluster;
-}
-
-
-
-/*
-ClusterForPointExtFilter() - ydnar
-adds cluster checking against a list of known valid clusters
-*/
-
-int ClusterForPointExtFilter( vec3_t point, float epsilon, int numClusters, int *clusters )
-{
-	int		i, cluster;
-	
-	
-	/* get cluster for point */
-	cluster = ClusterForPointExt( point, epsilon );
-	
-	/* check if filtering is necessary */
-	if( cluster < 0 || numClusters <= 0 || clusters == NULL )
-		return cluster;
-	
-	/* filter */
-	for( i = 0; i < numClusters; i++ )
-	{
-		if( cluster == clusters[ i ] || ClusterVisible( cluster, clusters[ i ] ) )
-			return cluster;
-	}
-	
-	/* failed */
-	return -1;
-}
-
-
-
-/*
-ShaderForPointInLeaf() - ydnar
-checks a point against all brushes in a leaf, returning the shader of the brush
-also sets the cumulative surface and content flags for the brush hit
-*/
-
-int ShaderForPointInLeaf( vec3_t point, int leafNum, float epsilon, int wantContentFlags, int wantSurfaceFlags, int *contentFlags, int *surfaceFlags )
-{
-	int				i, j;
-	float			dot;
-	qboolean		inside;
-	int				*brushes, numBSPBrushes;
-	bspLeaf_t			*leaf;
-	bspBrush_t		*brush;
-	bspBrushSide_t	*side;
-	bspPlane_t		*plane;
-	bspShader_t		*shader;
-	int				allSurfaceFlags, allContentFlags;
-
-	
-	/* clear things out first */
-	*surfaceFlags = 0;
-	*contentFlags = 0;
-	
-	/* get leaf */
-	if( leafNum < 0 )
-		return -1;
-	leaf = &bspLeafs[ leafNum ];
-	
-	/* transparent leaf, so check point against all brushes in the leaf */
-	brushes = &bspLeafBrushes[ leaf->firstBSPLeafBrush ];
-	numBSPBrushes = leaf->numBSPLeafBrushes;
-	for( i = 0; i < numBSPBrushes; i++ )
-	{
-		/* get parts */
-		brush = &bspBrushes[ brushes[ i ] ];
-		
-		/* check point against all planes */
-		inside = qtrue;
-		allSurfaceFlags = 0;
-		allContentFlags = 0;
-		for( j = 0; j < brush->numSides && inside; j++ )
-		{
-			side = &bspBrushSides[ brush->firstSide + j ];
-			plane = &bspPlanes[ side->planeNum ];
-			dot = DotProduct( point, plane->normal );
-			dot -= plane->dist;
-			if( dot > epsilon )
-				inside = qfalse;
-			else
-			{
-				shader = &bspShaders[ side->shaderNum ];
-				allSurfaceFlags |= shader->surfaceFlags;
-				allContentFlags |= shader->contentFlags;
-			}
-		}
-		
-		/* handle if inside */
-		if( inside )
-		{
-			/* if there are desired flags, check for same and continue if they aren't matched */
-			if( wantContentFlags && !(wantContentFlags & allContentFlags) )
-				continue;
-			if( wantSurfaceFlags && !(wantSurfaceFlags & allSurfaceFlags) )
-				continue;
-			
-			/* store the cumulative flags and return the brush shader (which is mostly useless) */
-			*surfaceFlags = allSurfaceFlags;
-			*contentFlags = allContentFlags;
-			return brush->shaderNum;
-		}
-	}
-	
-	/* if the point made it this far, it's not inside any brushes */
-	return -1;
-}
-
-
-
-/*
-ChopBounds()
-chops a bounding box by the plane defined by origin and normal
-returns qfalse if the bounds is entirely clipped away
-
-this is not exactly the fastest way to do this...
-*/
-
-qboolean ChopBounds( vec3_t mins, vec3_t maxs, vec3_t origin, vec3_t normal )
-{
-	/* FIXME: rewrite this so it doesn't use bloody brushes */
-	return qtrue;
-}
-
-
-
-/*
-SetupEnvelopes()
-calculates each light's effective envelope,
-taking into account brightness, type, and pvs.
-*/
-
-#define LIGHT_EPSILON	0.125f
-#define LIGHT_NUDGE		2.0f
-
-void SetupEnvelopes( qboolean forGrid, qboolean fastFlag )
-{
-	int			i, x, y, z, x1, y1, z1;
-	light_t		*light, *light2, **owner;
-	bspLeaf_t	*leaf;
-	vec3_t		origin, dir, mins, maxs, nullVector = { 0, 0, 0 };
-	float		radius, intensity;
-	light_t		*buckets[ 256 ];
-	
-	
-	/* early out for weird cases where there are no lights */
-	if( lights == NULL )
-		return;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- SetupEnvelopes%s ---\n", fastFlag ? " (fast)" : "" );
-	
-	/* count lights */
-	numLights = 0;
-	numCulledLights = 0;
-	owner = &lights;
-	while( *owner != NULL )
-	{
-		/* get light */
-		light = *owner;
-		
-		/* handle negative lights */
-		if( light->photons < 0.0f || light->add < 0.0f )
-		{
-			light->photons *= -1.0f;
-			light->add *= -1.0f;
-			light->flags |= LIGHT_NEGATIVE;
-		}
-		
-		/* sunlight? */
-		if( light->type == EMIT_SUN )
-		{
-			/* special cased */
-			light->cluster = 0;
-			light->envelope = MAX_WORLD_COORD * 8.0f;
-			VectorSet( light->mins, MIN_WORLD_COORD * 8.0f, MIN_WORLD_COORD * 8.0f, MIN_WORLD_COORD * 8.0f );
-			VectorSet( light->maxs, MAX_WORLD_COORD * 8.0f, MAX_WORLD_COORD * 8.0f, MAX_WORLD_COORD * 8.0f );
-		}
-		
-		/* everything else */
-		else
-		{
-			/* get pvs cluster for light */
-			light->cluster = ClusterForPointExt( light->origin, LIGHT_EPSILON );
-			
-			/* invalid cluster? */
-			if( light->cluster < 0 )
-			{
-				/* nudge the sample point around a bit */
-				for( x = 0; x < 4; x++ )
-				{
-					/* two's complement 0, 1, -1, 2, -2, etc */
-					x1 = ((x >> 1) ^ (x & 1 ? -1 : 0)) + (x & 1);
-					
-					for( y = 0; y < 4; y++ )
-					{
-						y1 = ((y >> 1) ^ (y & 1 ? -1 : 0)) + (y & 1);
-						
-						for( z = 0; z < 4; z++ )
-						{
-							z1 = ((z >> 1) ^ (z & 1 ? -1 : 0)) + (z & 1);
-							
-							/* nudge origin */
-							origin[ 0 ] = light->origin[ 0 ] + (LIGHT_NUDGE * x1);
-							origin[ 1 ] = light->origin[ 1 ] + (LIGHT_NUDGE * y1);
-							origin[ 2 ] = light->origin[ 2 ] + (LIGHT_NUDGE * z1);
-							
-							/* try at nudged origin */
-							light->cluster = ClusterForPointExt( origin, LIGHT_EPSILON );
-							if( light->cluster < 0 )
-								continue;
-									
-							/* set origin */
-							VectorCopy( origin, light->origin );
-						}
-					}
-				}
-			}
-			
-			/* only calculate for lights in pvs and outside of opaque brushes */
-			if( light->cluster >= 0 )
-			{
-				/* set light fast flag */
-				if( fastFlag )
-					light->flags |= LIGHT_FAST_TEMP;
-				else
-					light->flags &= ~LIGHT_FAST_TEMP;
-				if( light->si && light->si->noFast )
-					light->flags &= ~(LIGHT_FAST | LIGHT_FAST_TEMP);
-				
-				/* clear light envelope */
-				light->envelope = 0;
-				
-				/* handle area lights */
-				if( exactPointToPolygon && light->type == EMIT_AREA && light->w != NULL )
-				{
-					/* ugly hack to calculate extent for area lights, but only done once */
-					VectorScale( light->normal, -1.0f, dir );
-					for( radius = 100.0f; radius < 130000.0f && light->envelope == 0; radius += 10.0f )
-					{
-						float	factor;
-						
-						VectorMA( light->origin, radius, light->normal, origin );
-						factor = PointToPolygonFormFactor( origin, dir, light->w );
-						if( factor < 0.0f )
-							factor *= -1.0f;
-						if( (factor * light->add) <= light->falloffTolerance )
-							light->envelope = radius;
-					}
-					
-					/* check for fast mode */
-					if( !(light->flags & LIGHT_FAST) && !(light->flags & LIGHT_FAST_TEMP) )
-						light->envelope = MAX_WORLD_COORD * 8.0f;
-				}
-				else
-				{
-					radius = 0.0f;
-					intensity = light->photons;
-				}
-				
-				/* other calcs */
-				if( light->envelope <= 0.0f )
-				{
-					/* solve distance for non-distance lights */
-					if( !(light->flags & LIGHT_ATTEN_DISTANCE) )
-						light->envelope = MAX_WORLD_COORD * 8.0f;
-					
-					/* solve distance for linear lights */
-					else if( (light->flags & LIGHT_ATTEN_LINEAR ) )
-						//% light->envelope = ((intensity / light->falloffTolerance) * linearScale - 1 + radius) / light->fade;
-						light->envelope = ((intensity * linearScale) - light->falloffTolerance) / light->fade;
-
-						/*
-						add = angle * light->photons * linearScale - (dist * light->fade);
-						T = (light->photons * linearScale) - (dist * light->fade);
-						T + (dist * light->fade) = (light->photons * linearScale);
-						dist * light->fade = (light->photons * linearScale) - T;
-						dist = ((light->photons * linearScale) - T) / light->fade;
-						*/
-					
-					/* solve for inverse square falloff */
-					else
-						light->envelope = sqrt( intensity / light->falloffTolerance ) + radius;
-						
-						/*
-						add = light->photons / (dist * dist);
-						T = light->photons / (dist * dist);
-						T * (dist * dist) = light->photons;
-						dist = sqrt( light->photons / T );
-						*/
-				}
-				
-				/* chop radius against pvs */
-				{
-					/* clear bounds */
-					ClearBounds( mins, maxs );
-					
-					/* check all leaves */
-					for( i = 0; i < numBSPLeafs; i++ )
-					{
-						/* get test leaf */
-						leaf = &bspLeafs[ i ];
-						
-						/* in pvs? */
-						if( leaf->cluster < 0 )
-							continue;
-						if( ClusterVisible( light->cluster, leaf->cluster ) == qfalse )	/* ydnar: thanks Arnout for exposing my stupid error (this never failed before) */
-							continue;
-						
-						/* add this leafs bbox to the bounds */
-						VectorCopy( leaf->mins, origin );
-						AddPointToBounds( origin, mins, maxs );
-						VectorCopy( leaf->maxs, origin );
-						AddPointToBounds( origin, mins, maxs );
-					}
-					
-					/* test to see if bounds encompass light */
-					for( i = 0; i < 3; i++ )
-					{
-						if( mins[ i ] > light->origin[ i ] || maxs[ i ] < light->origin[ i ] )
-						{
-							//% Sys_Printf( "WARNING: Light PVS bounds (%.0f, %.0f, %.0f) -> (%.0f, %.0f, %.0f)\ndo not encompass light %d (%f, %f, %f)\n",
-							//% 	mins[ 0 ], mins[ 1 ], mins[ 2 ],
-							//% 	maxs[ 0 ], maxs[ 1 ], maxs[ 2 ],
-							//% 	numLights, light->origin[ 0 ], light->origin[ 1 ], light->origin[ 2 ] );
-							AddPointToBounds( light->origin, mins, maxs );
-						}
-					}
-					
-					/* chop the bounds by a plane for area lights and spotlights */
-					if( light->type == EMIT_AREA || light->type == EMIT_SPOT )
-						ChopBounds( mins, maxs, light->origin, light->normal );
-					
-					/* copy bounds */
-					VectorCopy( mins, light->mins );
-					VectorCopy( maxs, light->maxs );
-					
-					/* reflect bounds around light origin */
-					//%	VectorMA( light->origin, -1.0f, origin, origin );
-					VectorScale( light->origin, 2, origin );
-					VectorSubtract( origin, maxs, origin );
-					AddPointToBounds( origin, mins, maxs );
-					//%	VectorMA( light->origin, -1.0f, mins, origin );
-					VectorScale( light->origin, 2, origin );
-					VectorSubtract( origin, mins, origin );
-					AddPointToBounds( origin, mins, maxs );
-					 
-					/* calculate spherical bounds */
-					VectorSubtract( maxs, light->origin, dir );
-					radius = (float) VectorLength( dir );
-					
-					/* if this radius is smaller than the envelope, then set the envelope to it */
-					if( radius < light->envelope )
-					{
-						light->envelope = radius;
-						//%	Sys_FPrintf( SYS_VRB, "PVS Cull (%d): culled\n", numLights );
-					}
-					//%	else
-					//%		Sys_FPrintf( SYS_VRB, "PVS Cull (%d): failed (%8.0f > %8.0f)\n", numLights, radius, light->envelope );
-				}
-				
-				/* add grid/surface only check */
-				if( forGrid )
-				{
-					if( !(light->flags & LIGHT_GRID) )
-						light->envelope = 0.0f;
-				}
-				else
-				{
-					if( !(light->flags & LIGHT_SURFACES) )
-						light->envelope = 0.0f;
-				}
-			}
-			
-			/* culled? */
-			if( light->cluster < 0 || light->envelope <= 0.0f )
-			{
-				/* debug code */
-				//%	Sys_Printf( "Culling light: Cluster: %d Envelope: %f\n", light->cluster, light->envelope );
-				
-				/* delete the light */
-				numCulledLights++;
-				*owner = light->next;
-				if( light->w != NULL )
-					free( light->w );
-				free( light );
-				continue;
-			}
-		}
-		
-		/* square envelope */
-		light->envelope2 = (light->envelope * light->envelope);
-		
-		/* increment light count */
-		numLights++;
-		
-		/* set next light */
-		owner = &((**owner).next);
-	}
-	
-	/* bucket sort lights by style */
-	memset( buckets, 0, sizeof( buckets ) );
-	light2 = NULL;
-	for( light = lights; light != NULL; light = light2 )
-	{
-		/* get next light */
-		light2 = light->next;
-		
-		/* filter into correct bucket */
-		light->next = buckets[ light->style ];
-		buckets[ light->style ] = light;
-	}
-	
-	/* filter back into light list */
-	lights = NULL;
-	for( i = 255; i >= 0; i-- )
-	{
-		light2 = NULL;
-		for( light = buckets[ i ]; light != NULL; light = light2 )
-		{
-			light2 = light->next;
-			light->next = lights;
-			lights = light;
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_Printf( "%9d total lights\n", numLights );
-	Sys_Printf( "%9d culled lights\n", numCulledLights );
-}
-
-
-
-/*
-CreateTraceLightsForBounds()
-creates a list of lights that affect the given bounding box and pvs clusters (bsp leaves)
-*/
-
-void CreateTraceLightsForBounds( vec3_t mins, vec3_t maxs, vec3_t normal, int numClusters, int *clusters, int flags, trace_t *trace )
-{
-	int			i;
-	light_t		*light;
-	vec3_t		origin, dir, nullVector = { 0.0f, 0.0f, 0.0f };
-	float		radius, dist, length;
-	
-	
-	/* potential pre-setup  */
-	if( numLights == 0 )
-		SetupEnvelopes( qfalse, fast );
-	
-	/* debug code */
-	//% Sys_Printf( "CTWLFB: (%4.1f %4.1f %4.1f) (%4.1f %4.1f %4.1f)\n", mins[ 0 ], mins[ 1 ], mins[ 2 ], maxs[ 0 ], maxs[ 1 ], maxs[ 2 ] );
-	
-	/* allocate the light list */
-	trace->lights = safe_malloc( sizeof( light_t* ) * (numLights + 1) );
-	trace->numLights = 0;
-	
-	/* calculate spherical bounds */
-	VectorAdd( mins, maxs, origin );
-	VectorScale( origin, 0.5f, origin );
-	VectorSubtract( maxs, origin, dir );
-	radius = (float) VectorLength( dir );
-	
-	/* get length of normal vector */
-	if( normal != NULL )
-		length = VectorLength( normal );
-	else
-	{
-		normal = nullVector;
-		length = 0;
-	}
-	
-	/* test each light and see if it reaches the sphere */
-	/* note: the attenuation code MUST match LightingAtSample() */
-	for( light = lights; light; light = light->next )
-	{
-		/* check zero sized envelope */
-		if( light->envelope <= 0 )
-		{
-			lightsEnvelopeCulled++;
-			continue;
-		}
-		
-		/* check flags */
-		if( !(light->flags & flags) )
-			continue;
-		
-		/* sunlight skips all this nonsense */
-		if( light->type != EMIT_SUN )
-		{
-			/* sun only? */
-			if( sunOnly )
-				continue;
-			
-			/* check against pvs cluster */
-			if( numClusters > 0 && clusters != NULL )
-			{
-				for( i = 0; i < numClusters; i++ )
-				{
-					if( ClusterVisible( light->cluster, clusters[ i ] ) )
-						break;
-				}
-				
-				/* fixme! */
-				if( i == numClusters )
-				{
-					lightsClusterCulled++;
-					continue;
-				}
-			}
-			
-			/* if the light's bounding sphere intersects with the bounding sphere then this light needs to be tested */
-			VectorSubtract( light->origin, origin, dir );
-			dist = VectorLength( dir );
-			dist -= light->envelope;
-			dist -= radius;
-			if( dist > 0 )
-			{
-				lightsEnvelopeCulled++;
-				continue;
-			}
-			
-			/* check bounding box against light's pvs envelope (note: this code never eliminated any lights, so disabling it) */
-			#if 0
-			skip = qfalse;
-			for( i = 0; i < 3; i++ )
-			{
-				if( mins[ i ] > light->maxs[ i ] || maxs[ i ] < light->mins[ i ] )
-					skip = qtrue;
-			}
-			if( skip )
-			{
-				lightsBoundsCulled++;
-				continue;
-			}
-			#endif
-		}
-		
-		/* planar surfaces (except twosided surfaces) have a couple more checks */
-		if( length > 0.0f && trace->twoSided == qfalse )
-		{
-			/* lights coplanar with a surface won't light it */
-			if( !(light->flags & LIGHT_TWOSIDED) && DotProduct( light->normal, normal ) > 0.999f )
-			{
-				lightsPlaneCulled++;
-				continue;
-			}
-			
-			/* check to see if light is behind the plane */
-			if( DotProduct( light->origin, normal ) - DotProduct( origin, normal ) < -1.0f )
-			{
-				lightsPlaneCulled++;
-				continue;
-			}
-		}
-		
-		/* add this light */
-		trace->lights[ trace->numLights++ ] = light;
-	}
-	
-	/* make last night null */
-	trace->lights[ trace->numLights ] = NULL;
-}
-
-
-
-void FreeTraceLights( trace_t *trace )
-{
-	if( trace->lights != NULL )
-		free( trace->lights );
-}
-
-
-
-/*
-CreateTraceLightsForSurface()
-creates a list of lights that can potentially affect a drawsurface
-*/
-
-void CreateTraceLightsForSurface( int num, trace_t *trace )
-{
-	int					i;
-	vec3_t				mins, maxs, normal;
-	bspDrawVert_t		*dv;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	
-	
-	/* dummy check */
-	if( num < 0 )
-		return;
-	
-	/* get drawsurface and info */
-	ds = &bspDrawSurfaces[ num ];
-	info = &surfaceInfos[ num ];
-	
-	/* get the mins/maxs for the dsurf */
-	ClearBounds( mins, maxs );
-	VectorCopy( bspDrawVerts[ ds->firstVert ].normal, normal );
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		dv = &yDrawVerts[ ds->firstVert + i ];
-		AddPointToBounds( dv->xyz, mins, maxs );
-		if( !VectorCompare( dv->normal, normal ) )
-			VectorClear( normal );
-	}
-	
-	/* create the lights for the bounding box */
-	CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
-}
-
-
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define LIGHT_YDNAR_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+/*
+ColorToBytes()
+ydnar: moved to here 2001-02-04
+*/
+
+void ColorToBytes( const float *color, byte *colorBytes, float scale )
+{
+	float	max;
+	vec3_t	sample;
+	
+	
+	/* ydnar: scaling necessary for simulating r_overbrightBits on external lightmaps */
+	if( scale <= 0.0f )
+		scale = 1.0f;
+	
+	/* make a local copy */
+	VectorScale( color, scale, sample );
+	
+	/* handle negative light */
+	if( sample[ 0 ] < 0.0f )
+		sample[ 0 ] = 0.0f;
+	if( sample[ 1 ] < 0.0f )
+		sample[ 1 ] = 0.0f;
+	if( sample[ 2 ] < 0.0f )
+		sample[ 2 ] = 0.0f;
+	
+	/* clamp with color normalization */
+	max = sample[ 0 ];
+	if( sample[ 1 ] > max )
+		max = sample[ 1 ];
+	if( sample[ 2 ] > max )
+		max = sample[ 2 ];
+	if( max > 255.0f )
+		VectorScale( sample, (255.0f / max), sample );
+	
+	/* store it off */
+	colorBytes[ 0 ] = sample[ 0 ];
+	colorBytes[ 1 ] = sample[ 1 ];
+	colorBytes[ 2 ] = sample[ 2 ];
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+this section deals with phong shading (normal interpolation across brush faces)
+
+------------------------------------------------------------------------------- */
+
+/*
+SmoothNormals()
+smooths together coincident vertex normals across the bsp
+*/
+
+#define MAX_SAMPLES				256
+#define THETA_EPSILON			0.000001
+#define EQUAL_NORMAL_EPSILON	0.01
+
+void SmoothNormals( void )
+{
+	int					i, j, k, f, cs, numVerts, numVotes, fOld, start;
+	float				shadeAngle, defaultShadeAngle, maxShadeAngle, dot, testAngle;
+	bspDrawSurface_t	*ds;
+	shaderInfo_t		*si;
+	float				*shadeAngles;
+	byte				*smoothed;
+	vec3_t				average, diff;
+	int					indexes[ MAX_SAMPLES ];
+	vec3_t				votes[ MAX_SAMPLES ];
+	
+	
+	/* allocate shade angle table */
+	shadeAngles = safe_malloc( numBSPDrawVerts * sizeof( float ) );
+	memset( shadeAngles, 0, numBSPDrawVerts * sizeof( float ) );
+	
+	/* allocate smoothed table */
+	cs = (numBSPDrawVerts / 8) + 1;
+	smoothed = safe_malloc( cs );
+	memset( smoothed, 0, cs );
+	
+	/* set default shade angle */
+	defaultShadeAngle = DEG2RAD( shadeAngleDegrees );
+	maxShadeAngle = 0;
+	
+	/* run through every surface and flag verts belonging to non-lightmapped surfaces
+	   and set per-vertex smoothing angle */
+	for( i = 0; i < numBSPDrawSurfaces; i++ )
+	{
+		/* get drawsurf */
+		ds = &bspDrawSurfaces[ i ];
+		
+		/* get shader for shade angle */
+		si = surfaceInfos[ i ].si;
+		if( si->shadeAngleDegrees )
+			shadeAngle = DEG2RAD( si->shadeAngleDegrees );
+		else
+			shadeAngle = defaultShadeAngle;
+		if( shadeAngle > maxShadeAngle )
+			maxShadeAngle = shadeAngle;
+		
+		/* flag its verts */
+		for( j = 0; j < ds->numVerts; j++ )
+		{
+			f = ds->firstVert + j;
+			shadeAngles[ f ] = shadeAngle;
+			if( ds->surfaceType == MST_TRIANGLE_SOUP )
+				smoothed[ f >> 3 ] |= (1 << (f & 7));
+		}
+		
+		/* ydnar: optional force-to-trisoup */
+		if( trisoup && ds->surfaceType == MST_PLANAR )
+		{
+			ds->surfaceType = MST_TRIANGLE_SOUP;
+			ds->lightmapNum[ 0 ] = -3;
+		}
+	}
+	
+	/* bail if no surfaces have a shade angle */
+	if( maxShadeAngle == 0 )
+	{
+		free( shadeAngles );
+		free( smoothed );
+		return;
+	}
+	
+	/* init pacifier */
+	fOld = -1;
+	start = I_FloatTime();
+	
+	/* go through the list of vertexes */
+	for( i = 0; i < numBSPDrawVerts; i++ )
+	{
+		/* print pacifier */
+		f = 10 * i / numBSPDrawVerts;
+		if( f != fOld )
+		{
+			fOld = f;
+			Sys_Printf( "%i...", f );
+		}
+		
+		/* already smoothed? */
+		if( smoothed[ i >> 3 ] & (1 << (i & 7)) )
+			continue;
+		
+		/* clear */
+		VectorClear( average );
+		numVerts = 0;
+		numVotes = 0;
+		
+		/* build a table of coincident vertexes */
+		for( j = i; j < numBSPDrawVerts && numVerts < MAX_SAMPLES; j++ )
+		{
+			/* already smoothed? */
+			if( smoothed[ j >> 3 ] & (1 << (j & 7)) )
+				continue;
+			
+			/* test vertexes */
+			if( VectorCompare( yDrawVerts[ i ].xyz, yDrawVerts[ j ].xyz ) == qfalse )
+				continue;
+			
+			/* use smallest shade angle */
+			shadeAngle = (shadeAngles[ i ] < shadeAngles[ j ] ? shadeAngles[ i ] : shadeAngles[ j ]);
+			
+			/* check shade angle */
+			dot = DotProduct( bspDrawVerts[ i ].normal, bspDrawVerts[ j ].normal );
+			if( dot > 1.0 )
+				dot = 1.0;
+			else if( dot < -1.0 )
+				dot = -1.0;
+			testAngle = acos( dot ) + THETA_EPSILON;
+			if( testAngle >= shadeAngle )
+			{
+				//Sys_Printf( "F(%3.3f >= %3.3f) ", RAD2DEG( testAngle ), RAD2DEG( shadeAngle ) );
+				continue;
+			}
+			//Sys_Printf( "P(%3.3f < %3.3f) ", RAD2DEG( testAngle ), RAD2DEG( shadeAngle ) );
+			
+			/* add to the list */
+			indexes[ numVerts++ ] = j;
+			
+			/* flag vertex */
+			smoothed[ j >> 3 ] |= (1 << (j & 7));
+			
+			/* see if this normal has already been voted */
+			for( k = 0; k < numVotes; k++ )
+			{
+				VectorSubtract( bspDrawVerts[ j ].normal, votes[ k ], diff );
+				if( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
+					fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
+					fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON )
+					break;
+			}
+			
+			/* add a new vote? */
+			if( k == numVotes && numVotes < MAX_SAMPLES )
+			{
+				VectorAdd( average, bspDrawVerts[ j ].normal, average );
+				VectorCopy( bspDrawVerts[ j ].normal, votes[ numVotes ] );
+				numVotes++;
+			}
+		}
+		
+		/* don't average for less than 2 verts */
+		if( numVerts < 2 )
+			continue;
+		
+		/* average normal */
+		if( VectorNormalize( average, average ) > 0 )
+		{
+			/* smooth */
+			for( j = 0; j < numVerts; j++ )
+				VectorCopy( average, yDrawVerts[ indexes[ j ] ].normal );
+		}
+	}
+	
+	/* free the tables */
+	free( shadeAngles );
+	free( smoothed );
+	
+	/* print time */
+	Sys_Printf( " (%i)\n", (int) (I_FloatTime() - start) );
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+this section deals with phong shaded lightmap tracing
+
+------------------------------------------------------------------------------- */
+
+/* 9th rewrite (recursive subdivision of a lightmap triangle) */
+
+/*
+CalcTangentVectors()
+calculates the st tangent vectors for normalmapping
+*/
+
+static qboolean CalcTangentVectors( int numVerts, bspDrawVert_t **dv, vec3_t *stv, vec3_t *ttv )
+{
+	int			i;
+	float		bb, s, t;
+	vec3_t		bary;
+	
+	
+	/* calculate barycentric basis for the triangle */
+	bb = (dv[ 1 ]->st[ 0 ] - dv[ 0 ]->st[ 0 ]) * (dv[ 2 ]->st[ 1 ] - dv[ 0 ]->st[ 1 ]) - (dv[ 2 ]->st[ 0 ] - dv[ 0 ]->st[ 0 ]) * (dv[ 1 ]->st[ 1 ] - dv[ 0 ]->st[ 1 ]);
+	if( fabs( bb ) < 0.00000001f )
+		return qfalse;
+	
+	/* do each vertex */
+	for( i = 0; i < numVerts; i++ )
+	{
+		/* calculate s tangent vector */
+		s = dv[ i ]->st[ 0 ] + 10.0f;
+		t = dv[ i ]->st[ 1 ];
+		bary[ 0 ] = ((dv[ 1 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t) - (dv[ 2 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t)) / bb;
+		bary[ 1 ] = ((dv[ 2 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t) - (dv[ 0 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t)) / bb;
+		bary[ 2 ] = ((dv[ 0 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t) - (dv[ 1 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t)) / bb;
+		
+		stv[ i ][ 0 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 0 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 0 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 0 ];
+		stv[ i ][ 1 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 1 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 1 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 1 ];
+		stv[ i ][ 2 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 2 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 2 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 2 ];
+		
+		VectorSubtract( stv[ i ], dv[ i ]->xyz, stv[ i ] );
+		VectorNormalize( stv[ i ], stv[ i ] );
+		
+		/* calculate t tangent vector */
+		s = dv[ i ]->st[ 0 ];
+		t = dv[ i ]->st[ 1 ] + 10.0f;
+		bary[ 0 ] = ((dv[ 1 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t) - (dv[ 2 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t)) / bb;
+		bary[ 1 ] = ((dv[ 2 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t) - (dv[ 0 ]->st[ 0 ] - s) * (dv[ 2 ]->st[ 1 ] - t)) / bb;
+		bary[ 2 ] = ((dv[ 0 ]->st[ 0 ] - s) * (dv[ 1 ]->st[ 1 ] - t) - (dv[ 1 ]->st[ 0 ] - s) * (dv[ 0 ]->st[ 1 ] - t)) / bb;
+		
+		ttv[ i ][ 0 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 0 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 0 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 0 ];
+		ttv[ i ][ 1 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 1 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 1 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 1 ];
+		ttv[ i ][ 2 ] = bary[ 0 ] * dv[ 0 ]->xyz[ 2 ] + bary[ 1 ] * dv[ 1 ]->xyz[ 2 ] + bary[ 2 ] * dv[ 2 ]->xyz[ 2 ];
+		
+		VectorSubtract( ttv[ i ], dv[ i ]->xyz, ttv[ i ] );
+		VectorNormalize( ttv[ i ], ttv[ i ] );
+		
+		/* debug code */
+		//%	Sys_FPrintf( SYS_VRB, "%d S: (%f %f %f) T: (%f %f %f)\n", i,
+		//%		stv[ i ][ 0 ], stv[ i ][ 1 ], stv[ i ][ 2 ], ttv[ i ][ 0 ], ttv[ i ][ 1 ], ttv[ i ][ 2 ] );
+	}
+	
+	/* return to caller */
+	return qtrue;
+}
+
+
+
+
+/*
+PerturbNormal()
+perterbs the normal by the shader's normalmap in tangent space
+*/
+
+static void PerturbNormal( bspDrawVert_t *dv, shaderInfo_t *si, vec3_t pNormal, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
+{
+	int			i;
+	vec4_t		bump;
+	
+	
+	/* passthrough */
+	VectorCopy( dv->normal, pNormal );
+	
+	/* sample normalmap */
+	if( RadSampleImage( si->normalImage->pixels, si->normalImage->width, si->normalImage->height, dv->st, bump ) == qfalse )
+		return;
+	
+	/* remap sampled normal from [0,255] to [-1,-1] */
+	for( i = 0; i < 3; i++ )
+		bump[ i ] = (bump[ i ] - 127.0f) * (1.0f / 127.5f);
+	
+	/* scale tangent vectors and add to original normal */
+	VectorMA( dv->normal, bump[ 0 ], stv[ 0 ], pNormal );
+	VectorMA( pNormal, bump[ 1 ], ttv[ 0 ], pNormal );
+	VectorMA( pNormal, bump[ 2 ], dv->normal, pNormal );
+	
+	/* renormalize and return */
+	VectorNormalize( pNormal, pNormal );
+}
+
+
+
+/*
+MapSingleLuxel()
+maps a luxel for triangle bv at
+*/
+
+#define NUDGE			0.5f
+#define BOGUS_NUDGE		-99999.0f
+
+static int MapSingleLuxel( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv, vec4_t plane, float pass, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
+{
+	int				i, x, y, numClusters, *clusters, pointCluster, *cluster;
+	float			*luxel, *origin, *normal, d, lightmapSampleOffset;
+	shaderInfo_t	*si;
+	vec3_t			pNormal;
+	vec3_t			vecs[ 3 ];
+	vec3_t			nudged;
+	float			*nudge;
+	static float	nudges[][ 2 ] =
+					{
+						//%{ 0, 0 },		/* try center first */
+						{ -NUDGE, 0 },		/* left */
+						{ NUDGE, 0 },		/* right */
+						{ 0, NUDGE },		/* up */
+						{ 0, -NUDGE },		/* down */
+						{ -NUDGE, NUDGE },	/* left/up */
+						{ NUDGE, -NUDGE },	/* right/down */
+						{ NUDGE, NUDGE },	/* right/up */
+						{ -NUDGE, -NUDGE },	/* left/down */
+						{ BOGUS_NUDGE, BOGUS_NUDGE }
+					};
+	
+	
+	/* find luxel xy coords (fixme: subtract 0.5?) */
+	x = dv->lightmap[ 0 ][ 0 ];
+	y = dv->lightmap[ 0 ][ 1 ];
+	if( x < 0 )
+		x = 0;
+	else if( x >= lm->sw )
+		x = lm->sw - 1;
+	if( y < 0 )
+		y = 0;
+	else if( y >= lm->sh )
+		y = lm->sh - 1;
+	
+	/* set shader and cluster list */
+	if( info != NULL )
+	{
+		si = info->si;
+		numClusters = info->numSurfaceClusters;
+		clusters = &surfaceClusters[ info->firstSurfaceCluster ];
+	}
+	else
+	{
+		si = NULL;
+		numClusters = 0;
+		clusters = NULL;
+	}
+	
+	/* get luxel, origin, cluster, and normal */
+	luxel = SUPER_LUXEL( 0, x, y );
+	origin = SUPER_ORIGIN( x, y );
+	normal = SUPER_NORMAL( x, y );
+	cluster = SUPER_CLUSTER( x, y );
+	
+	/* don't attempt to remap occluded luxels for planar surfaces */
+	if( (*cluster) == CLUSTER_OCCLUDED && lm->plane != NULL )
+		return (*cluster);
+	
+	/* only average the normal for premapped luxels */
+	else if( (*cluster) >= 0 )
+	{
+		/* do bumpmap calculations */
+		if( stv != NULL )
+			PerturbNormal( dv, si, pNormal, stv, ttv );
+		else
+			VectorCopy( dv->normal, pNormal );
+		
+		/* add the additional normal data */
+		VectorAdd( normal, pNormal, normal );
+		luxel[ 3 ] += 1.0f;
+		return (*cluster);
+	}
+	
+	/* otherwise, unmapped luxels (*cluster == CLUSTER_UNMAPPED) will have their full attributes calculated */
+	
+	/* get origin */
+	
+	/* axial lightmap projection */
+	if( lm->vecs != NULL )
+	{
+		/* calculate an origin for the sample from the lightmap vectors */
+		VectorCopy( lm->origin, origin );
+		for( i = 0; i < 3; i++ )
+		{
+			/* add unless it's the axis, which is taken care of later */
+			if( i == lm->axisNum )
+				continue;
+			origin[ i ] += (x * lm->vecs[ 0 ][ i ]) + (y * lm->vecs[ 1 ][ i ]);
+		}
+		
+		/* project the origin onto the plane */
+		d = DotProduct( origin, plane ) - plane[ 3 ];
+		d /= plane[ lm->axisNum ];
+		origin[ lm->axisNum ] -= d;
+	}
+	
+	/* non axial lightmap projection (explicit xyz) */
+	else
+		VectorCopy( dv->xyz, origin );
+	
+	/* planar surfaces have precalculated lightmap vectors for nudging */
+	if( lm->plane != NULL )
+	{
+		VectorCopy( lm->vecs[ 0 ], vecs[ 0 ] );
+		VectorCopy( lm->vecs[ 1 ], vecs[ 1 ] );
+		VectorCopy( lm->plane, vecs[ 2 ] );
+	}
+	
+	/* non-planar surfaces must calculate them */
+	else
+	{
+		if( plane != NULL )
+			VectorCopy( plane, vecs[ 2 ] );
+		else
+			VectorCopy( dv->normal, vecs[ 2 ] );
+		MakeNormalVectors( vecs[ 2 ], vecs[ 0 ], vecs[ 1 ] );
+	}
+	
+	/* push the origin off the surface a bit */
+	if( si != NULL )
+		lightmapSampleOffset = si->lightmapSampleOffset;
+	else
+		lightmapSampleOffset = DEFAULT_LIGHTMAP_SAMPLE_OFFSET;
+	if( lm->axisNum < 0 )
+		VectorMA( origin, lightmapSampleOffset, vecs[ 2 ], origin );
+	else if( vecs[ 2 ][ lm->axisNum ] < 0.0f )
+		origin[ lm->axisNum ] -= lightmapSampleOffset;
+	else
+		origin[ lm->axisNum ] += lightmapSampleOffset;
+	
+	/* get cluster */
+	pointCluster = ClusterForPointExtFilter( origin, LUXEL_EPSILON, numClusters, clusters );
+	
+	/* another retarded hack, storing nudge count in luxel[ 1 ] */
+	luxel[ 1 ] = 0.0f;	
+	
+	/* point in solid? */
+	if( pointCluster < 0 )
+	{
+		/* nudge the the location around */
+		nudge = nudges[ 0 ];
+		while( nudge[ 0 ] > BOGUS_NUDGE && pointCluster < 0 )
+		{
+			/* nudge the vector around a bit */
+			for( i = 0; i < 3; i++ )
+			{
+				/* set nudged point*/
+				nudged[ i ] = origin[ i ] + (nudge[ 0 ] * vecs[ 0 ][ i ]) + (nudge[ 1 ] * vecs[ 1 ][ i ]);
+			}
+			nudge += 2;
+			
+			/* get pvs cluster */
+			pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters ); //% + 0.625 );
+			if( pointCluster >= 0 )	
+				VectorCopy( nudged, origin );
+			luxel[ 1 ] += 1.0f;
+		}
+	}
+	
+	/* as a last resort, if still in solid, try drawvert origin offset by normal */
+	if( pointCluster < 0 && si != NULL )
+	{
+		VectorMA( dv->xyz, lightmapSampleOffset, dv->normal, nudged );
+		pointCluster = ClusterForPointExtFilter( nudged, LUXEL_EPSILON, numClusters, clusters );
+		if( pointCluster >= 0 )
+			VectorCopy( nudged, origin );
+		luxel[ 1 ] += 1.0f;
+	}
+	
+	/* valid? */
+	if( pointCluster < 0 )
+	{
+		(*cluster) = CLUSTER_OCCLUDED;
+		VectorClear( origin );
+		VectorClear( normal );
+		numLuxelsOccluded++;
+		return (*cluster);
+	}
+	
+	/* debug code */
+	//%	Sys_Printf( "%f %f %f\n", origin[ 0 ], origin[ 1 ], origin[ 2 ] );
+	
+	/* do bumpmap calculations */
+	if( stv )
+		PerturbNormal( dv, si, pNormal, stv, ttv );
+	else
+		VectorCopy( dv->normal, pNormal );
+	
+	/* store the cluster and normal */
+	(*cluster) = pointCluster;
+	VectorCopy( pNormal, normal );
+	
+	/* store explicit mapping pass and implicit mapping pass */
+	luxel[ 0 ] = pass;
+	luxel[ 3 ] = 1.0f;
+	
+	/* add to count */
+	numLuxelsMapped++;
+	
+	/* return ok */
+	return (*cluster);
+}
+
+
+
+/*
+MapTriangle_r()
+recursively subdivides a triangle until its edges are shorter
+than the distance between two luxels (thanks jc :)
+*/
+
+static void MapTriangle_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], vec4_t plane, vec3_t stv[ 3 ], vec3_t ttv[ 3 ] )
+{
+	bspDrawVert_t	mid, *dv2[ 3 ];
+	int				max;
+	
+	
+	/* map the vertexes */
+	#if 0
+	MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
+	#endif
+	
+	/* subdivide calc */
+	{
+		int			i;
+		float		*a, *b, dx, dy, dist, maxDist;
+		
+		
+		/* find the longest edge and split it */
+		max = -1;
+		maxDist = 0;
+		for( i = 0; i < 3; i++ )
+		{
+			/* get verts */
+			a = dv[ i ]->lightmap[ 0 ];
+			b = dv[ (i + 1) % 3 ]->lightmap[ 0 ];
+			
+			/* get dists */
+			dx = a[ 0 ] - b[ 0 ];
+			dy = a[ 1 ] - b[ 1 ];
+			dist = (dx * dx) + (dy * dy);	//% sqrt( (dx * dx) + (dy * dy) );
+			
+			/* longer? */
+			if( dist > maxDist )
+			{
+				maxDist = dist;
+				max = i;
+			}
+		}
+		
+		/* try to early out */
+		if( max < 0 || maxDist <= subdivideThreshold )	/* ydnar: was i < 0 instead of max < 0 (?) */
+			return;
+	}
+	
+	/* split the longest edge and map it */
+	LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
+	MapSingleLuxel( lm, info, &mid, plane, 1, stv, ttv );
+	
+	/* push the point up a little bit to account for fp creep (fixme: revisit this) */
+	//%	VectorMA( mid.xyz, 2.0f, mid.normal, mid.xyz );
+	
+	/* recurse to first triangle */
+	VectorCopy( dv, dv2 );
+	dv2[ max ] = &mid;
+	MapTriangle_r( lm, info, dv2, plane, stv, ttv );
+	
+	/* recurse to second triangle */
+	VectorCopy( dv, dv2 );
+	dv2[ (max + 1) % 3 ] = &mid;
+	MapTriangle_r( lm, info, dv2, plane, stv, ttv );
+}
+
+
+
+/*
+MapTriangle()
+seed function for MapTriangle_r()
+requires a cw ordered triangle
+*/
+
+static qboolean MapTriangle( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 3 ], qboolean mapNonAxial )
+{
+	int				i;
+	vec4_t			plane;
+	vec3_t			*stv, *ttv, stvStatic[ 3 ], ttvStatic[ 3 ];
+	
+	
+	/* get plane if possible */
+	if( lm->plane != NULL )
+	{
+		VectorCopy( lm->plane, plane );
+		plane[ 3 ] = lm->plane[ 3 ];
+	}
+	
+	/* otherwise make one from the points */
+	else if( PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) == qfalse )
+		return qfalse;
+	
+	/* check to see if we need to calculate texture->world tangent vectors */
+	if( info->si->normalImage != NULL && CalcTangentVectors( 3, dv, stvStatic, ttvStatic ) )
+	{
+		stv = stvStatic;
+		ttv = ttvStatic;
+	}
+	else
+	{
+		stv = NULL;
+		ttv = NULL;
+	}
+	
+	/* map the vertexes */
+	MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
+	
+	/* 2002-11-20: prefer axial triangle edges */
+	if( mapNonAxial )
+	{
+		/* subdivide the triangle */
+		MapTriangle_r( lm, info, dv, plane, stv, ttv );
+		return qtrue;
+	}
+	
+	for( i = 0; i < 3; i++ )
+	{
+		float			*a, *b;
+		bspDrawVert_t	*dv2[ 3 ];
+		
+		
+		/* get verts */
+		a = dv[ i ]->lightmap[ 0 ];
+		b = dv[ (i + 1) % 3 ]->lightmap[ 0 ];
+		
+		/* make degenerate triangles for mapping edges */
+		if( fabs( a[ 0 ] - b[ 0 ] ) < 0.01f || fabs( a[ 1 ] - b[ 1 ] ) < 0.01f )
+		{
+			dv2[ 0 ] = dv[ i ];
+			dv2[ 1 ] = dv[ (i + 1) % 3 ];
+			dv2[ 2 ] = dv[ (i + 1) % 3 ];
+			
+			/* map the degenerate triangle */
+			MapTriangle_r( lm, info, dv2, plane, stv, ttv );
+		}
+	}
+	
+	return qtrue;
+}
+
+
+
+/*
+MapQuad_r()
+recursively subdivides a quad until its edges are shorter
+than the distance between two luxels
+*/
+
+static void MapQuad_r( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 4 ], vec4_t plane, vec3_t stv[ 4 ], vec3_t ttv[ 4 ] )
+{
+	bspDrawVert_t	mid[ 2 ], *dv2[ 4 ];
+	int				max;
+	
+	
+	/* subdivide calc */
+	{
+		int			i;
+		float		*a, *b, dx, dy, dist, maxDist;
+		
+		
+		/* find the longest edge and split it */
+		max = -1;
+		maxDist = 0;
+		for( i = 0; i < 4; i++ )
+		{
+			/* get verts */
+			a = dv[ i ]->lightmap[ 0 ];
+			b = dv[ (i + 1) % 4 ]->lightmap[ 0 ];
+			
+			/* get dists */
+			dx = a[ 0 ] - b[ 0 ];
+			dy = a[ 1 ] - b[ 1 ];
+			dist = (dx * dx) + (dy * dy);	//% sqrt( (dx * dx) + (dy * dy) );
+			
+			/* longer? */
+			if( dist > maxDist )
+			{
+				maxDist = dist;
+				max = i;
+			}
+		}
+		
+		/* try to early out */
+		if( max < 0 || maxDist <= subdivideThreshold )
+			return;
+	}
+	
+	/* we only care about even/odd edges */
+	max &= 1;
+	
+	/* split the longest edges */
+	LerpDrawVert( dv[ max ], dv[ (max + 1) % 4 ], &mid[ 0 ] );
+	LerpDrawVert( dv[ max + 2 ], dv[ (max + 3) % 4 ], &mid[ 1 ] );
+	
+	/* map the vertexes */
+	MapSingleLuxel( lm, info, &mid[ 0 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, &mid[ 1 ], plane, 1, stv, ttv );
+	
+	/* 0 and 2 */
+	if( max == 0 )
+	{
+		/* recurse to first quad */
+		dv2[ 0 ] = dv[ 0 ];
+		dv2[ 1 ] = &mid[ 0 ];
+		dv2[ 2 ] = &mid[ 1 ];
+		dv2[ 3 ] = dv[ 3 ];
+		MapQuad_r( lm, info, dv2, plane, stv, ttv );
+		
+		/* recurse to second quad */
+		dv2[ 0 ] = &mid[ 0 ];
+		dv2[ 1 ] = dv[ 1 ];
+		dv2[ 2 ] = dv[ 2 ];
+		dv2[ 3 ] = &mid[ 1 ];
+		MapQuad_r( lm, info, dv2, plane, stv, ttv );
+	}
+	
+	/* 1 and 3 */
+	else
+	{
+		/* recurse to first quad */
+		dv2[ 0 ] = dv[ 0 ];
+		dv2[ 1 ] = dv[ 1 ];
+		dv2[ 2 ] = &mid[ 0 ];
+		dv2[ 3 ] = &mid[ 1 ];
+		MapQuad_r( lm, info, dv2, plane, stv, ttv );
+		
+		/* recurse to second quad */
+		dv2[ 0 ] = &mid[ 1 ];
+		dv2[ 1 ] = &mid[ 0 ];
+		dv2[ 2 ] = dv[ 2 ];
+		dv2[ 3 ] = dv[ 3 ];
+		MapQuad_r( lm, info, dv2, plane, stv, ttv );
+	}
+}
+
+
+
+/*
+MapQuad()
+seed function for MapQuad_r()
+requires a cw ordered triangle quad
+*/
+
+#define QUAD_PLANAR_EPSILON		0.5f
+
+static qboolean MapQuad( rawLightmap_t *lm, surfaceInfo_t *info, bspDrawVert_t *dv[ 4 ] )
+{
+	float			dist;
+	vec4_t			plane;
+	vec3_t			*stv, *ttv, stvStatic[ 4 ], ttvStatic[ 4 ];
+	
+	
+	/* get plane if possible */
+	if( lm->plane != NULL )
+	{
+		VectorCopy( lm->plane, plane );
+		plane[ 3 ] = lm->plane[ 3 ];
+	}
+	
+	/* otherwise make one from the points */
+	else if( PlaneFromPoints( plane, dv[ 0 ]->xyz, dv[ 1 ]->xyz, dv[ 2 ]->xyz ) == qfalse )
+		return qfalse;
+	
+	/* 4th point must fall on the plane */
+	dist = DotProduct( plane, dv[ 3 ]->xyz ) - plane[ 3 ];
+	if( fabs( dist ) > QUAD_PLANAR_EPSILON )
+		return qfalse;
+	
+	/* check to see if we need to calculate texture->world tangent vectors */
+	if( info->si->normalImage != NULL && CalcTangentVectors( 4, dv, stvStatic, ttvStatic ) )
+	{
+		stv = stvStatic;
+		ttv = ttvStatic;
+	}
+	else
+	{
+		stv = NULL;
+		ttv = NULL;
+	}
+	
+	/* map the vertexes */
+	MapSingleLuxel( lm, info, dv[ 0 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, dv[ 1 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, dv[ 2 ], plane, 1, stv, ttv );
+	MapSingleLuxel( lm, info, dv[ 3 ], plane, 1, stv, ttv );
+	
+	/* subdivide the quad */
+	MapQuad_r( lm, info, dv, plane, stv, ttv );
+	return qtrue;
+}
+
+
+
+/*
+MapRawLightmap()
+maps the locations, normals, and pvs clusters for a raw lightmap
+*/
+
+#define VectorDivide( in, d, out )	VectorScale( in, (1.0f / (d)), out )	//%	(out)[ 0 ] = (in)[ 0 ] / (d), (out)[ 1 ] = (in)[ 1 ] / (d), (out)[ 2 ] = (in)[ 2 ] / (d)
+
+void MapRawLightmap( int rawLightmapNum )
+{
+	int					n, num, i, x, y, sx, sy, pw[ 5 ], r, *cluster, mapNonAxial;
+	float				*luxel, *origin, *normal, samples, radius, pass;
+	rawLightmap_t		*lm;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	mesh_t				src, *subdivided, *mesh;
+	bspDrawVert_t		*verts, *dv[ 4 ], fake;
+	
+	
+	/* bail if this number exceeds the number of raw lightmaps */
+	if( rawLightmapNum >= numRawLightmaps )
+		return;
+	
+	/* get lightmap */
+	lm = &rawLightmaps[ rawLightmapNum ];
+	
+	/* -----------------------------------------------------------------
+	   map referenced surfaces onto the raw lightmap
+	   ----------------------------------------------------------------- */
+	
+	/* walk the list of surfaces on this raw lightmap */
+	for( n = 0; n < lm->numLightSurfaces; n++ )
+	{
+		/* with > 1 surface per raw lightmap, clear occluded */
+		if( n > 0 )
+		{
+			for( y = 0; y < lm->sh; y++ )
+			{
+				for( x = 0; x < lm->sw; x++ )
+				{
+					/* get cluster */
+					cluster = SUPER_CLUSTER( x, y );
+					if( *cluster < 0 )
+						*cluster = CLUSTER_UNMAPPED;
+				}
+			}
+		}
+		
+		/* get surface */
+		num = lightSurfaces[ lm->firstLightSurface + n ];
+		ds = &bspDrawSurfaces[ num ];
+		info = &surfaceInfos[ num ];
+		
+		/* bail if no lightmap to calculate */
+		if( info->lm != lm )
+		{
+			Sys_Printf( "!" );
+			continue;
+		}
+		
+		/* map the surface onto the lightmap origin/cluster/normal buffers */
+		switch( ds->surfaceType )
+		{
+			case MST_PLANAR:
+				/* get verts */
+				verts = yDrawVerts + ds->firstVert;
+				
+				/* map the triangles */
+				for( mapNonAxial = 0; mapNonAxial < 2; mapNonAxial++ )
+				{
+					for( i = 0; i < ds->numIndexes; i += 3 )
+					{
+						dv[ 0 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i ] ];
+						dv[ 1 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 1 ] ];
+						dv[ 2 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 2 ] ];
+						MapTriangle( lm, info, dv, mapNonAxial );
+					}
+				}
+				break;
+			
+			case MST_PATCH:
+				/* make a mesh from the drawsurf */ 
+				src.width = ds->patchWidth;
+				src.height = ds->patchHeight;
+				src.verts = &yDrawVerts[ ds->firstVert ];
+				//%	subdivided = SubdivideMesh( src, 8, 512 );
+				subdivided = SubdivideMesh2( src, info->patchIterations );
+				
+				/* fit it to the curve and remove colinear verts on rows/columns */
+				PutMeshOnCurve( *subdivided );
+				mesh = RemoveLinearMeshColumnsRows( subdivided );
+				FreeMesh( subdivided );
+				
+				/* get verts */
+				verts = mesh->verts;
+				
+				/* debug code */
+				#if 0
+					if( lm->plane )
+					{
+						Sys_Printf( "Planar patch: [%1.3f %1.3f %1.3f] [%1.3f %1.3f %1.3f] [%1.3f %1.3f %1.3f]\n",
+							lm->plane[ 0 ], lm->plane[ 1 ], lm->plane[ 2 ],
+							lm->vecs[ 0 ][ 0 ], lm->vecs[ 0 ][ 1 ], lm->vecs[ 0 ][ 2 ],
+							lm->vecs[ 1 ][ 0 ], lm->vecs[ 1 ][ 1 ], lm->vecs[ 1 ][ 2 ] );
+					}
+				#endif
+				
+				/* map the mesh quads */
+				#if 0
+
+				for( mapNonAxial = 0; mapNonAxial < 2; mapNonAxial++ )
+				{
+					for( y = 0; y < (mesh->height - 1); y++ )
+					{
+						for( x = 0; x < (mesh->width - 1); x++ )
+						{
+							/* set indexes */
+							pw[ 0 ] = x + (y * mesh->width);
+							pw[ 1 ] = x + ((y + 1) * mesh->width);
+							pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+							pw[ 3 ] = x + 1 + (y * mesh->width);
+							pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+							
+							/* set radix */
+							r = (x + y) & 1;
+							
+							/* get drawverts and map first triangle */
+							dv[ 0 ] = &verts[ pw[ r + 0 ] ];
+							dv[ 1 ] = &verts[ pw[ r + 1 ] ];
+							dv[ 2 ] = &verts[ pw[ r + 2 ] ];
+							MapTriangle( lm, info, dv, mapNonAxial );
+							
+							/* get drawverts and map second triangle */
+							dv[ 0 ] = &verts[ pw[ r + 0 ] ];
+							dv[ 1 ] = &verts[ pw[ r + 2 ] ];
+							dv[ 2 ] = &verts[ pw[ r + 3 ] ];
+							MapTriangle( lm, info, dv, mapNonAxial );
+						}
+					}
+				}
+				
+				#else
+				
+				for( y = 0; y < (mesh->height - 1); y++ )
+				{
+					for( x = 0; x < (mesh->width - 1); x++ )
+					{
+						/* set indexes */
+						pw[ 0 ] = x + (y * mesh->width);
+						pw[ 1 ] = x + ((y + 1) * mesh->width);
+						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+						pw[ 3 ] = x + 1 + (y * mesh->width);
+						pw[ 4 ] = pw[ 0 ];
+						
+						/* set radix */
+						r = (x + y) & 1;
+						
+						/* attempt to map quad first */
+						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
+						dv[ 1 ] = &verts[ pw[ r + 1 ] ];
+						dv[ 2 ] = &verts[ pw[ r + 2 ] ];
+						dv[ 3 ] = &verts[ pw[ r + 3 ] ];
+						if( MapQuad( lm, info, dv ) )
+							continue;
+						
+						/* get drawverts and map first triangle */
+						MapTriangle( lm, info, dv, mapNonAxial );
+						
+						/* get drawverts and map second triangle */
+						dv[ 1 ] = &verts[ pw[ r + 2 ] ];
+						dv[ 2 ] = &verts[ pw[ r + 3 ] ];
+						MapTriangle( lm, info, dv, mapNonAxial );
+					}
+				}
+				
+				#endif
+				
+				/* free the mesh */
+				FreeMesh( mesh );
+				break;
+			
+			default:
+				break;
+		}
+	}
+	
+	/* -----------------------------------------------------------------
+	   average and clean up luxel normals
+	   ----------------------------------------------------------------- */
+	
+	/* walk the luxels */
+	for( y = 0; y < lm->sh; y++ )
+	{
+		for( x = 0; x < lm->sw; x++ )
+		{
+			/* get luxel */
+			luxel = SUPER_LUXEL( 0, x, y );
+			normal = SUPER_NORMAL( x, y );
+			cluster = SUPER_CLUSTER( x, y );
+
+			/* only look at mapped luxels */
+			if( *cluster < 0 )
+				continue;
+			
+			/* the normal data could be the sum of multiple samples */
+			if( luxel[ 3 ] > 1.0f )
+				VectorNormalize( normal, normal );
+			
+			/* mark this luxel as having only one normal */
+			luxel[ 3 ] = 1.0f;
+		}
+	}
+	
+	/* non-planar surfaces stop here */
+	if( lm->plane == NULL )
+		return;
+	
+	/* -----------------------------------------------------------------
+	   map occluded or unuxed luxels
+	   ----------------------------------------------------------------- */
+	
+	/* walk the luxels */
+	radius = floor( superSample / 2 );
+	radius = radius > 0 ? radius : 1.0f;
+	radius += 1.0f;
+	for( pass = 2.0f; pass <= radius; pass += 1.0f )
+	{
+		for( y = 0; y < lm->sh; y++ )
+		{
+			for( x = 0; x < lm->sw; x++ )
+			{
+				/* get luxel */
+				luxel = SUPER_LUXEL( 0, x, y );
+				normal = SUPER_NORMAL( x, y );
+				cluster = SUPER_CLUSTER( x, y );
+				
+				/* only look at unmapped luxels */
+				if( *cluster != CLUSTER_UNMAPPED )
+					continue;
+				
+				/* divine a normal and origin from neighboring luxels */
+				VectorClear( fake.xyz );
+				VectorClear( fake.normal );
+				fake.lightmap[ 0 ][ 0 ] = x;	//% 0.0001 + x;
+				fake.lightmap[ 0 ][ 1 ] = y;	//% 0.0001 + y;
+				samples = 0.0f;
+				for( sy = (y - 1); sy <= (y + 1); sy++ )
+				{
+					if( sy < 0 || sy >= lm->sh )
+						continue;
+					
+					for( sx = (x - 1); sx <= (x + 1); sx++ )
+					{
+						if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
+							continue;
+						
+						/* get neighboring luxel */
+						luxel = SUPER_LUXEL( 0, sx, sy );
+						origin = SUPER_ORIGIN( sx, sy );
+						normal = SUPER_NORMAL( sx, sy );
+						cluster = SUPER_CLUSTER( sx, sy );
+						
+						/* only consider luxels mapped in previous passes */
+						if( *cluster < 0 || luxel[ 0 ] >= pass )
+							continue;
+						
+						/* add its distinctiveness to our own */
+						VectorAdd( fake.xyz, origin, fake.xyz );
+						VectorAdd( fake.normal, normal, fake.normal );
+						samples += luxel[ 3 ];
+					}
+				}
+				
+				/* any samples? */
+				if( samples == 0.0f )
+					continue;
+				
+				/* average */
+				VectorDivide( fake.xyz, samples, fake.xyz );
+				//%	VectorDivide( fake.normal, samples, fake.normal );
+				if( VectorNormalize( fake.normal, fake.normal ) == 0.0f )
+					continue;
+				
+				/* map the fake vert */
+				MapSingleLuxel( lm, NULL, &fake, lm->plane, pass, NULL, NULL );
+			}
+		}
+	}
+	
+	/* -----------------------------------------------------------------
+	   average and clean up luxel normals
+	   ----------------------------------------------------------------- */
+	
+	/* walk the luxels */
+	for( y = 0; y < lm->sh; y++ )
+	{
+		for( x = 0; x < lm->sw; x++ )
+		{
+			/* get luxel */
+			luxel = SUPER_LUXEL( 0, x, y );
+			normal = SUPER_NORMAL( x, y );
+			cluster = SUPER_CLUSTER( x, y );
+			
+			/* only look at mapped luxels */
+			if( *cluster < 0 )
+				continue;
+			
+			/* the normal data could be the sum of multiple samples */
+			if( luxel[ 3 ] > 1.0f )
+				VectorNormalize( normal, normal );
+			
+			/* mark this luxel as having only one normal */
+			luxel[ 3 ] = 1.0f;
+		}
+	}
+	
+	/* debug code */
+	#if 0
+		Sys_Printf( "\n" );
+		for( y = 0; y < lm->sh; y++ )
+		{
+			for( x = 0; x < lm->sw; x++ )
+			{
+				vec3_t	mins, maxs;
+				
+
+				cluster = SUPER_CLUSTER( x, y );
+				origin = SUPER_ORIGIN( x, y );
+				normal = SUPER_NORMAL( x, y );
+				luxel = SUPER_LUXEL( x, y );
+				
+				if( *cluster < 0 )
+					continue;
+				
+				/* check if within the bounding boxes of all surfaces referenced */
+				ClearBounds( mins, maxs );
+				for( n = 0; n < lm->numLightSurfaces; n++ )
+				{
+					int TOL;
+					info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + n ] ];
+					TOL = info->sampleSize + 2;
+					AddPointToBounds( info->mins, mins, maxs );
+					AddPointToBounds( info->maxs, mins, maxs );
+					if( origin[ 0 ] > (info->mins[ 0 ] - TOL) && origin[ 0 ] < (info->maxs[ 0 ] + TOL) &&
+						origin[ 1 ] > (info->mins[ 1 ] - TOL) && origin[ 1 ] < (info->maxs[ 1 ] + TOL) &&
+						origin[ 2 ] > (info->mins[ 2 ] - TOL) && origin[ 2 ] < (info->maxs[ 2 ] + TOL) )
+						break;
+				}
+				
+				/* inside? */
+				if( n < lm->numLightSurfaces )
+					continue;
+				
+				/* report bogus origin */
+				Sys_Printf( "%6d [%2d,%2d] (%4d): XYZ(%+4.1f %+4.1f %+4.1f) LO(%+4.1f %+4.1f %+4.1f) HI(%+4.1f %+4.1f %+4.1f) <%3.0f>\n",
+					rawLightmapNum, x, y, *cluster,
+					origin[ 0 ], origin[ 1 ], origin[ 2 ],
+					mins[ 0 ], mins[ 1 ], mins[ 2 ],
+					maxs[ 0 ], maxs[ 1 ], maxs[ 2 ],
+					luxel[ 3 ] );
+			}
+		}
+	#endif
+}
+
+
+
+/*
+SubmapRawLuxel()
+calculates the pvs cluster, origin, normal of a sub-luxel
+*/
+
+static qboolean SubmapRawLuxel( rawLightmap_t *lm, int x, int y, float bx, float by, int *sampleCluster, vec3_t sampleOrigin, vec3_t sampleNormal )
+{
+	int			i, *cluster, *cluster2;
+	float		*origin, *origin2, *normal;	//%	, *normal2;
+	vec3_t		originVecs[ 2 ];			//%	, normalVecs[ 2 ];
+	
+	
+	/* calulate x vector */
+	if( (x < (lm->sw - 1) && bx >= 0.0f) || (x == 0 && bx <= 0.0f) )
+	{
+		cluster = SUPER_CLUSTER( x, y );
+		origin = SUPER_ORIGIN( x, y );
+		//%	normal = SUPER_NORMAL( x, y );
+		cluster2 = SUPER_CLUSTER( x + 1, y );
+		origin2 = *cluster2 < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x + 1, y );
+		//%	normal2 = *cluster2 < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x + 1, y );
+	}
+	else if( (x > 0 && bx <= 0.0f) || (x == (lm->sw - 1) && bx >= 0.0f) )
+	{
+		cluster = SUPER_CLUSTER( x - 1, y );
+		origin = *cluster < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x - 1, y );
+		//%	normal = *cluster < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x - 1, y );
+		cluster2 = SUPER_CLUSTER( x, y );
+		origin2 = SUPER_ORIGIN( x, y );
+		//%	normal2 = SUPER_NORMAL( x, y );
+	}
+	else
+		Sys_Printf( "WARNING: Spurious lightmap S vector\n" );
+	
+	VectorSubtract( origin2, origin, originVecs[ 0 ] );
+	//%	VectorSubtract( normal2, normal, normalVecs[ 0 ] );
+	
+	/* calulate y vector */
+	if( (y < (lm->sh - 1) && bx >= 0.0f) || (y == 0 && bx <= 0.0f) )
+	{
+		cluster = SUPER_CLUSTER( x, y );
+		origin = SUPER_ORIGIN( x, y );
+		//%	normal = SUPER_NORMAL( x, y );
+		cluster2 = SUPER_CLUSTER( x, y + 1 );
+		origin2 = *cluster2 < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x, y + 1 );
+		//%	normal2 = *cluster2 < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x, y + 1 );
+	}
+	else if( (y > 0 && bx <= 0.0f) || (y == (lm->sh - 1) && bx >= 0.0f) )
+	{
+		cluster = SUPER_CLUSTER( x, y - 1 );
+		origin = *cluster < 0 ? SUPER_ORIGIN( x, y ) : SUPER_ORIGIN( x, y - 1 );
+		//%	normal = *cluster < 0 ? SUPER_NORMAL( x, y ) : SUPER_NORMAL( x, y - 1 );
+		cluster2 = SUPER_CLUSTER( x, y );
+		origin2 = SUPER_ORIGIN( x, y );
+		//%	normal2 = SUPER_NORMAL( x, y );
+	}
+	else
+		Sys_Printf( "WARNING: Spurious lightmap T vector\n" );
+	
+	VectorSubtract( origin2, origin, originVecs[ 1 ] );
+	//%	VectorSubtract( normal2, normal, normalVecs[ 1 ] );
+	
+	/* calculate new origin */
+	//%	VectorMA( origin, bx, originVecs[ 0 ], sampleOrigin );
+	//%	VectorMA( sampleOrigin, by, originVecs[ 1 ], sampleOrigin );
+	for( i = 0; i < 3; i++ )
+		sampleOrigin[ i ] = sampleOrigin[ i ] + (bx * originVecs[ 0 ][ i ]) + (by * originVecs[ 1 ][ i ]);
+	
+	/* get cluster */
+	*sampleCluster = ClusterForPointExtFilter( sampleOrigin, (LUXEL_EPSILON * 2), lm->numLightClusters, lm->lightClusters );
+	if( *sampleCluster < 0 )
+		return qfalse;
+	
+	/* calculate new normal */
+	//%	VectorMA( normal, bx, normalVecs[ 0 ], sampleNormal );
+	//%	VectorMA( sampleNormal, by, normalVecs[ 1 ], sampleNormal );
+	//%	if( VectorNormalize( sampleNormal, sampleNormal ) <= 0.0f )
+	//%		return qfalse;
+	normal = SUPER_NORMAL( x, y );
+	VectorCopy( normal, sampleNormal );
+	
+	/* return ok */
+	return qtrue;
+}
+
+
+/*
+SubsampleRawLuxel_r()
+recursively subsamples a luxel until its color gradient is low enough or subsampling limit is reached
+*/
+
+void SubsampleRawLuxel_r( rawLightmap_t *lm, trace_t *trace, vec3_t sampleOrigin, int x, int y, float bias, float *lightLuxel )
+{
+	int			b, samples, mapped, lighted;
+	int			cluster[ 4 ];
+	vec4_t		luxel[ 4 ];
+	vec3_t		origin[ 4 ], normal[ 4 ];
+	float		biasDirs[ 4 ][ 2 ] = { { -1.0f, -1.0f }, { 1.0f, -1.0f }, { -1.0f, 1.0f }, { 1.0f, 1.0f } };
+	vec3_t		color, total;
+	
+	
+	/* limit check */
+	if( lightLuxel[ 3 ] >= lightSamples )
+		return;
+	
+	/* setup */
+	VectorClear( total );
+	mapped = 0;
+	lighted = 0;
+	
+	/* make 2x2 subsample stamp */
+	for( b = 0; b < 4; b++ )
+	{
+		/* set origin */
+		VectorCopy( sampleOrigin, origin[ b ] );
+		
+		/* calculate position */
+		if( !SubmapRawLuxel( lm, x, y, (bias * biasDirs[ b ][ 0 ]), (bias * biasDirs[ b ][ 1 ]), &cluster[ b ], origin[ b ], normal[ b ] ) )
+		{
+			cluster[ b ] = -1;
+			continue;
+		}
+		mapped++;
+		
+		/* increment sample count */
+		luxel[ b ][ 3 ] = lightLuxel[ 3 ] + 1.0f;
+		
+		/* setup trace */
+		trace->cluster = *cluster;
+		VectorCopy( origin[ b ], trace->origin );
+		VectorCopy( normal[ b ], trace->normal );
+		
+		/* sample light */
+		//%	LightContributionToSample( light, cluster[ b ], origin[ b ], normal[ b ], luxel[ b ], qtrue, qfalse, lm->numLightSurfaces, &lightSurfaces[ lm->firstLightSurface ] );
+		LightContributionToSample( trace );
+		
+		/* add to totals (fixme: make contrast function) */
+		VectorCopy( trace->color, luxel[ b ] );
+		VectorAdd( total, trace->color, total );
+		if( (luxel[ b ][ 0 ] + luxel[ b ][ 1 ] + luxel[ b ][ 2 ]) > 0.0f )
+			lighted++;
+	}
+	
+	/* subsample further? */
+	if( (lightLuxel[ 3 ] + 1.0f) < lightSamples &&
+		(total[ 0 ] > 4.0f || total[ 1 ] > 4.0f || total[ 2 ] > 4.0f) &&
+		lighted != 0 && lighted != mapped )
+	{
+		for( b = 0; b < 4; b++ )
+		{
+			if( cluster[ b ] < 0 )
+				continue;
+			SubsampleRawLuxel_r( lm, trace, origin[ b ], x, y, (bias * 0.25f), luxel[ b ] );
+		}
+	}
+	
+	/* average */
+	//%	VectorClear( color );
+	//%	samples = 0;
+	VectorCopy( lightLuxel, color );
+	samples = 1;
+	for( b = 0; b < 4; b++ )
+	{
+		if( cluster[ b ] < 0 )
+			continue;
+		VectorAdd( color, luxel[ b ], color );
+		samples++;
+	}
+	
+	/* add to luxel */
+	if( samples > 0 )
+	{
+		/* average */
+		color[ 0 ] /= samples;
+		color[ 1 ] /= samples;
+		color[ 2 ] /= samples;
+		
+		/* add to color */
+		VectorCopy( color, lightLuxel );
+		lightLuxel[ 3 ] += 1.0f;
+	}
+}
+
+
+
+/*
+IlluminateRawLightmap()
+illuminates the luxels
+*/
+
+#define LIGHT_LUXEL( x, y )		(lightLuxels + ((((y) * lm->sw) + (x)) * SUPER_LUXEL_SIZE))
+
+void IlluminateRawLightmap( int rawLightmapNum )
+{
+	int					i, t, x, y, sx, sy, size, llSize, luxelFilterRadius, lightmapNum;
+	int					*cluster, *cluster2, mapped, lighted, totalLighted;
+	rawLightmap_t		*lm;
+	surfaceInfo_t		*info;
+	qboolean			filterColor, filterDir;
+	float				brightness;
+	float				*origin, *normal, *luxel, *luxel2, *deluxel, *deluxel2;
+	float				*lightLuxels, *lightLuxel, samples, filterRadius, weight;
+	vec3_t				color, averageColor, averageDir, total, temp, temp2;
+	float				tests[ 4 ][ 2 ] = { { 0.0f, 0 }, { 1, 0 }, { 0, 1 }, { 1, 1 } };
+	trace_t				trace;
+	
+	
+	/* bail if this number exceeds the number of raw lightmaps */
+	if( rawLightmapNum >= numRawLightmaps )
+		return;
+	
+	/* get lightmap */
+	lm = &rawLightmaps[ rawLightmapNum ];
+	
+	/* setup trace */
+	trace.testOcclusion = !noTrace;
+	trace.forceSunlight = qfalse;
+	trace.recvShadows = lm->recvShadows;
+	trace.numSurfaces = lm->numLightSurfaces;
+	trace.surfaces = &lightSurfaces[ lm->firstLightSurface ];
+	trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
+	
+	/* twosided lighting (may or may not be a good idea for lightmapped stuff) */
+	trace.twoSided = qfalse;
+	for( i = 0; i < trace.numSurfaces; i++ )
+	{
+		/* get surface */
+		info = &surfaceInfos[ trace.surfaces[ i ] ];
+		
+		/* check twosidedness */
+		if( info->si->twoSided )
+		{
+			trace.twoSided = qtrue;
+			break;
+		}
+	}
+	
+	/* create a culled light list for this raw lightmap */
+	CreateTraceLightsForBounds( lm->mins, lm->maxs, lm->plane, lm->numLightClusters, lm->lightClusters, LIGHT_SURFACES, &trace );
+	
+	/* -----------------------------------------------------------------
+	   fill pass
+	   ----------------------------------------------------------------- */
+	
+	/* test debugging state */
+	if( debugSurfaces || debugAxis || debugCluster || debugOrigin || normalmap )
+	{
+		/* debug fill the luxels */
+		for( y = 0; y < lm->sh; y++ )
+		{
+			for( x = 0; x < lm->sw; x++ )
+			{
+				/* get cluster */
+				cluster = SUPER_CLUSTER( x, y );
+
+				/* only fill mapped luxels */
+				if( *cluster < 0 )
+					continue;
+				
+				/* get particulars */
+				luxel = SUPER_LUXEL( 0, x, y );
+				origin = SUPER_ORIGIN( x, y );
+				normal = SUPER_NORMAL( x, y );
+				
+				/* color the luxel with raw lightmap num? */
+				if( debugSurfaces )
+					VectorCopy( debugColors[ rawLightmapNum % 12 ], luxel );
+				
+				/* color the luxel with lightmap axis? */
+				else if( debugAxis )
+				{
+					luxel[ 0 ] = (lm->axis[ 0 ] + 1.0f) * 127.5f;
+					luxel[ 1 ] = (lm->axis[ 1 ] + 1.0f) * 127.5f;
+					luxel[ 2 ] = (lm->axis[ 2 ] + 1.0f) * 127.5f;
+				}
+				
+				/* color the luxel with luxel cluster? */
+				else if( debugCluster )
+					VectorCopy( debugColors[ *cluster % 12 ], luxel );
+				
+				/* color the luxel with luxel origin? */
+				else if( debugOrigin )
+				{
+					VectorSubtract( lm->maxs, lm->mins, temp );
+					VectorScale( temp, (1.0f / 255.0f), temp );
+					VectorSubtract( origin, lm->mins, temp2 );
+					luxel[ 0 ] = lm->mins[ 0 ] + (temp[ 0 ] * temp2[ 0 ]);
+					luxel[ 1 ] = lm->mins[ 1 ] + (temp[ 1 ] * temp2[ 1 ]);
+					luxel[ 2 ] = lm->mins[ 2 ] + (temp[ 2 ] * temp2[ 2 ]);
+				}
+				
+				/* color the luxel with the normal */
+				else if( normalmap )
+				{
+					luxel[ 0 ] = (normal[ 0 ] + 1.0f) * 127.5f;
+					luxel[ 1 ] = (normal[ 1 ] + 1.0f) * 127.5f;
+					luxel[ 2 ] = (normal[ 2 ] + 1.0f) * 127.5f;
+				}
+				
+				/* add to counts */
+				numLuxelsIlluminated++;
+				luxel[ 3 ] = 1.0f;
+			}
+		}
+	}
+	else
+	{
+		/* allocate temporary per-light luxel storage */
+		llSize = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
+		lightLuxels = safe_malloc( llSize );
+		
+		/* clear luxels */
+		//%	memset( lm->superLuxels[ 0 ], 0, llSize );
+		
+		/* set ambient color */
+		for( y = 0; y < lm->sh; y++ )
+		{
+			for( x = 0; x < lm->sw; x++ )
+			{
+				/* get cluster */
+				cluster = SUPER_CLUSTER( x, y );
+				luxel = SUPER_LUXEL( 0, x, y );
+				normal = SUPER_NORMAL( x, y );
+				deluxel = SUPER_DELUXEL( x, y );
+				
+				/* blacken unmapped clusters */
+				if( *cluster < 0 )
+					VectorClear( luxel );
+				
+				/* set ambient */
+				else
+				{
+					VectorCopy( ambientColor, luxel );
+					if( deluxemap )
+						VectorScale( normal, 0.00390625f, deluxel );
+					luxel[ 3 ] = 1.0f;
+				}
+			}
+		}
+		
+		/* clear styled lightmaps */
+		size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
+		for( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		{
+			if( lm->superLuxels[ lightmapNum ] != NULL )
+				memset( lm->superLuxels[ lightmapNum ], 0, size );
+		}
+		
+		/* debugging code */
+		//%	if( trace.numLights <= 0 )
+		//%		Sys_Printf( "Lightmap %9d: 0 lights, axis: %.2f, %.2f, %.2f\n", rawLightmapNum, lm->axis[ 0 ], lm->axis[ 1 ], lm->axis[ 2 ] );
+		
+		/* walk light list */
+		for( i = 0; i < trace.numLights; i++ )
+		{
+			/* setup trace */
+			trace.light = trace.lights[ i ];
+			
+			/* style check */
+			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				if( lm->styles[ lightmapNum ] == trace.light->style ||
+					lm->styles[ lightmapNum ] == LS_NONE )
+					break;
+			}
+			
+			/* max of MAX_LIGHTMAPS (4) styles allowed to hit a surface/lightmap */
+			if( lightmapNum >= MAX_LIGHTMAPS )
+			{
+				Sys_Printf( "WARNING: Hit per-surface style limit (%d)\n", MAX_LIGHTMAPS );
+				continue;
+			}
+			
+			/* setup */
+			memset( lightLuxels, 0, llSize );
+			totalLighted = 0;
+			
+			/* initial pass, one sample per luxel */
+			for( y = 0; y < lm->sh; y++ )
+			{
+				for( x = 0; x < lm->sw; x++ )
+				{
+					/* get cluster */
+					cluster = SUPER_CLUSTER( x, y );
+					if( *cluster < 0 )
+						continue;
+					
+					/* get particulars */
+					lightLuxel = LIGHT_LUXEL( x, y );
+					deluxel = SUPER_DELUXEL( x, y );
+					origin = SUPER_ORIGIN( x, y );
+					normal = SUPER_NORMAL( x, y );
+					
+					/* set contribution count */
+					lightLuxel[ 3 ] = 1.0f;
+					
+					/* setup trace */
+					trace.cluster = *cluster;
+					VectorCopy( origin, trace.origin );
+					VectorCopy( normal, trace.normal );
+					
+					/* get light for this sample */
+					LightContributionToSample( &trace );
+					VectorCopy( trace.color, lightLuxel );
+					
+					/* add to count */
+					if( trace.color[ 0 ] || trace.color[ 1 ] || trace.color[ 2 ] )
+						totalLighted++;
+					
+					/* add to light direction map (fixme: use luxel normal as starting point for deluxel?) */
+					if( deluxemap )
+					{
+						/* color to grayscale (photoshop rgb weighting) */
+						brightness = trace.color[ 0 ] * 0.3f + trace.color[ 1 ] * 0.59f + trace.color[ 2 ] * 0.11f;
+						brightness *= (1.0 / 255.0);
+						VectorScale( trace.direction, brightness, trace.direction );
+						VectorAdd( deluxel, trace.direction, deluxel );
+					}
+				}
+			}
+			
+			/* don't even bother with everything else if nothing was lit */
+			if( totalLighted == 0 )
+				continue;
+			
+			/* determine filter radius */
+			filterRadius = lm->filterRadius > trace.light->filterRadius
+				? lm->filterRadius
+				: trace.light->filterRadius;
+			if( filterRadius < 0.0f )
+				filterRadius = 0.0f;
+			
+			/* set luxel filter radius */
+			luxelFilterRadius = superSample * filterRadius / lm->sampleSize;
+			if( luxelFilterRadius == 0 && (filterRadius > 0.0f || filter) )
+				luxelFilterRadius = 1;
+			
+			/* secondary pass, adaptive supersampling (fixme: use a contrast function to determine if subsampling is necessary) */
+			/* 2003-09-27: changed it so filtering disamples supersampling, as it would waste time */
+			if( lightSamples > 1 && luxelFilterRadius == 0 )
+			{
+				/* walk luxels */
+				for( y = 0; y < (lm->sh - 1); y++ )
+				{
+					for( x = 0; x < (lm->sw - 1); x++ )
+					{
+						/* setup */
+						mapped = 0;
+						lighted = 0;
+						VectorClear( total );
+						
+						/* test 2x2 stamp */
+						for( t = 0; t < 4; t++ )
+						{
+							/* set sample coords */
+							sx = x + tests[ t ][ 0 ];
+							sy = y + tests[ t ][ 1 ];
+							
+							/* get cluster */
+							cluster = SUPER_CLUSTER( sx, sy );
+							if( *cluster < 0 )
+								continue;
+							mapped++;
+							
+							/* get luxel */
+							lightLuxel = LIGHT_LUXEL( sx, sy );
+							VectorAdd( total, lightLuxel, total );
+							if( (lightLuxel[ 0 ] + lightLuxel[ 1 ] + lightLuxel[ 2 ]) > 0.0f )
+								lighted++;
+						}
+						
+						/* if total color is under a certain amount, then don't bother subsampling */
+						if( total[ 0 ] <= 4.0f && total[ 1 ] <= 4.0f && total[ 2 ] <= 4.0f )
+							continue;
+						
+						/* if all 4 pixels are either in shadow or light, then don't subsample */
+						if( lighted != 0 && lighted != mapped )
+						{
+							for( t = 0; t < 4; t++ )
+							{
+								/* set sample coords */
+								sx = x + tests[ t ][ 0 ];
+								sy = y + tests[ t ][ 1 ];
+								
+								/* get luxel */
+								cluster = SUPER_CLUSTER( sx, sy );
+								if( *cluster < 0 )
+									continue;
+								lightLuxel = LIGHT_LUXEL( sx, sy );
+								origin = SUPER_ORIGIN( sx, sy );
+								
+								/* only subsample shadowed luxels */
+								//%	if( (lightLuxel[ 0 ] + lightLuxel[ 1 ] + lightLuxel[ 2 ]) <= 0.0f )
+								//%		continue;
+								
+								/* subsample it */
+								SubsampleRawLuxel_r( lm, &trace, origin, sx, sy, 0.25f, lightLuxel );
+								
+								/* debug code to colorize subsampled areas to yellow */
+								//%	luxel = SUPER_LUXEL( lightmapNum, sx, sy );
+								//%	VectorSet( luxel, 255, 204, 0 );
+							}
+						}
+					}
+				}
+			}
+			
+			/* allocate sampling lightmap storage */
+			if( lm->superLuxels[ lightmapNum ] == NULL )
+			{
+				/* allocate sampling lightmap storage */
+				size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
+				lm->superLuxels[ lightmapNum ] = safe_malloc( size );
+				memset( lm->superLuxels[ lightmapNum ], 0, size );
+			}
+			
+			/* set style */
+			if( lightmapNum > 0 )
+			{
+				lm->styles[ lightmapNum ] = trace.light->style;
+				//%	Sys_Printf( "Surface %6d has lightstyle %d\n", rawLightmapNum, trace.light->style );
+			}
+			
+			/* copy to permanent luxels */
+			for( y = 0; y < lm->sh; y++ )
+			{
+				for( x = 0; x < lm->sw; x++ )
+				{
+					/* get cluster and origin */
+					cluster = SUPER_CLUSTER( x, y );
+					if( *cluster < 0 )
+						continue;
+					origin = SUPER_ORIGIN( x, y );
+					
+					/* filter? */
+					if( luxelFilterRadius )
+					{
+						/* setup */
+						VectorClear( averageColor );
+						samples = 0.0f;
+						
+						/* cheaper distance-based filtering */
+						for( sy = (y - luxelFilterRadius); sy <= (y + luxelFilterRadius); sy++ )
+						{
+							if( sy < 0 || sy >= lm->sh )
+								continue;
+							
+							for( sx = (x - luxelFilterRadius); sx <= (x + luxelFilterRadius); sx++ )
+							{
+								if( sx < 0 || sx >= lm->sw )
+									continue;
+								
+								/* get particulars */
+								cluster = SUPER_CLUSTER( sx, sy );
+								if( *cluster < 0 )
+									continue;
+								lightLuxel = LIGHT_LUXEL( sx, sy );
+								
+								/* create weight */
+								weight = (abs( sx - x ) == luxelFilterRadius ? 0.5f : 1.0f);
+								weight *= (abs( sy - y ) == luxelFilterRadius ? 0.5f : 1.0f);
+								
+								/* scale luxel by filter weight */
+								VectorScale( lightLuxel, weight, color );
+								VectorAdd( averageColor, color, averageColor );
+								samples += weight;
+							}
+						}
+						
+						/* any samples? */
+						if( samples <= 0.0f	)
+							continue;
+						
+						/* scale into luxel */
+						luxel = SUPER_LUXEL( lightmapNum, x, y );
+						luxel[ 3 ] = 1.0f;
+						
+						/* handle negative light */
+						if( trace.light->flags & LIGHT_NEGATIVE )
+						{ 
+							luxel[ 0 ] -= averageColor[ 0 ] / samples;
+							luxel[ 1 ] -= averageColor[ 1 ] / samples;
+							luxel[ 2 ] -= averageColor[ 2 ] / samples;
+						}
+						
+						/* handle normal light */
+						else
+						{ 
+							luxel[ 0 ] += averageColor[ 0 ] / samples;
+							luxel[ 1 ] += averageColor[ 1 ] / samples;
+							luxel[ 2 ] += averageColor[ 2 ] / samples;
+						}
+					}
+					
+					/* single sample */
+					else
+					{
+						/* get particulars */
+						lightLuxel = LIGHT_LUXEL( x, y );
+						luxel = SUPER_LUXEL( lightmapNum, x, y );
+						
+						/* handle negative light */
+						if( trace.light->flags & LIGHT_NEGATIVE )
+							VectorScale( averageColor, -1.0f, averageColor );
+
+						/* add color */
+						luxel[ 3 ] = 1.0f;
+						
+						/* handle negative light */
+						if( trace.light->flags & LIGHT_NEGATIVE )
+							VectorSubtract( luxel, lightLuxel, luxel );
+						
+						/* handle normal light */
+						else
+							VectorAdd( luxel, lightLuxel, luxel );
+					}
+				}
+			}
+		}
+		
+		/* free temporary luxels */
+		free( lightLuxels );
+	}
+	
+	/* free light list */
+	FreeTraceLights( &trace );
+	
+	/* -----------------------------------------------------------------
+	   filter pass
+	   ----------------------------------------------------------------- */
+	
+	/* walk lightmaps */
+	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+	{
+		/* early out */
+		if( lm->superLuxels[ lightmapNum ] == NULL )
+			continue;
+		
+		/* average occluded luxels from neighbors */
+		for( y = 0; y < lm->sh; y++ )
+		{
+			for( x = 0; x < lm->sw; x++ )
+			{
+				/* get particulars */
+				cluster = SUPER_CLUSTER( x, y );
+				luxel = SUPER_LUXEL( lightmapNum, x, y );
+				deluxel = SUPER_DELUXEL( x, y );
+				normal = SUPER_NORMAL( x, y );
+				
+				/* determine if filtering is necessary */
+				filterColor = qfalse;
+				filterDir = qfalse;
+				if( *cluster < 0 ||
+					(lm->splotchFix && (luxel[ 0 ] <= ambientColor[ 0 ] || luxel[ 1 ] <= ambientColor[ 1 ] || luxel[ 2 ] <= ambientColor[ 2 ])) )
+					filterColor = qtrue;
+				if( deluxemap && lightmapNum == 0 && (*cluster < 0 || filter) )
+					filterDir = qtrue;
+				
+				if( !filterColor && !filterDir )
+					continue;
+				
+				/* choose seed amount */
+				VectorClear( averageColor );
+				VectorClear( averageDir );
+				samples = 0;
+				
+				/* walk 3x3 matrix */
+				for( sy = (y - 1); sy <= (y + 1); sy++ )
+				{
+					if( sy < 0 || sy >= lm->sh )
+						continue;
+					
+					for( sx = (x - 1); sx <= (x + 1); sx++ )
+					{
+						if( sx < 0 || sx >= lm->sw || (sx == x && sy == y) )
+							continue;
+						
+						/* get neighbor's particulars */
+						cluster2 = SUPER_CLUSTER( sx, sy );
+						luxel2 = SUPER_LUXEL( lightmapNum, sx, sy );
+						deluxel2 = SUPER_DELUXEL( sx, sy );
+						
+						/* ignore unmapped/unlit luxels */
+						if( *cluster2 < 0 || luxel2[ 3 ] == 0.0f ||
+							(lm->splotchFix && VectorCompare( luxel2, ambientColor )) )
+							continue;
+						
+						/* add its distinctiveness to our own */
+						VectorAdd( averageColor, luxel2, averageColor );
+						samples += luxel2[ 3 ];
+						if( filterDir )
+							VectorAdd( averageDir, deluxel2, averageDir );
+					}
+				}
+				
+				/* fall through */
+				if( samples == 0.0f )
+					continue;
+				
+				/* average it */
+				if( filterColor )
+				{
+					VectorDivide( averageColor, samples, luxel );
+					luxel[ 3 ] = 1.0f;
+				}
+				if( filterDir )
+					VectorDivide( averageDir, samples, deluxel );
+				
+				/* set cluster to -3 */
+				if( *cluster < 0 )
+					*cluster = CLUSTER_FLOODED;
+			}
+		}
+	}
+}
+
+
+
+/*
+IlluminateVertexes()
+light the surface vertexes
+*/
+
+#define VERTEX_NUDGE	2.0f
+
+void IlluminateVertexes( int num )
+{
+	int					i, x, y, z, x1, y1, z1, sx, sy, radius, maxRadius, *cluster;
+	int					lightmapNum;
+	float				samples, *vertLuxel, *radVertLuxel, *luxel;
+	vec3_t				origin, temp, temp2, colors[ MAX_LIGHTMAPS ];
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	rawLightmap_t		*lm;
+	bspDrawVert_t		*verts;
+	trace_t				trace;
+	
+	
+	/* der... */
+	if( noVertexLighting )
+		return;
+	
+	/* get surface, info, and raw lightmap */
+	ds = &bspDrawSurfaces[ num ];
+	info = &surfaceInfos[ num ];
+	lm = info->lm;
+	
+	/* -----------------------------------------------------------------
+	   illuminate the vertexes
+	   ----------------------------------------------------------------- */
+	
+	/* calculate vertex lighting for surfaces without lightmaps */
+	if( lm == NULL )
+	{
+		/* setup trace */
+		trace.testOcclusion = !noTrace;
+		trace.forceSunlight = info->si->forceSunlight;
+		trace.recvShadows = info->recvShadows;
+		trace.numSurfaces = 1;
+		trace.surfaces = &num;
+		trace.inhibitRadius = DEFAULT_INHIBIT_RADIUS;
+		
+		/* twosided lighting */
+		trace.twoSided = info->si->twoSided;
+		
+		/* make light list for this surface */
+		CreateTraceLightsForSurface( num, &trace );
+		
+		/* walk the surface verts */
+		verts = yDrawVerts + ds->firstVert;
+		for( i = 0; i < ds->numVerts; i++ )
+		{
+			/* get vertex luxel */
+			radVertLuxel = RAD_VERTEX_LUXEL( 0, ds->firstVert + i );
+			
+			/* color the luxel with raw lightmap num? */
+			if( debugSurfaces )
+				VectorCopy( debugColors[ num % 12 ], radVertLuxel );
+			
+			/* color the luxel with luxel origin? */
+			else if( debugOrigin )
+			{
+				VectorSubtract( info->maxs, info->mins, temp );
+				VectorScale( temp, (1.0f / 255.0f), temp );
+				VectorSubtract( origin, lm->mins, temp2 );
+				radVertLuxel[ 0 ] = info->mins[ 0 ] + (temp[ 0 ] * temp2[ 0 ]);
+				radVertLuxel[ 1 ] = info->mins[ 1 ] + (temp[ 1 ] * temp2[ 1 ]);
+				radVertLuxel[ 2 ] = info->mins[ 2 ] + (temp[ 2 ] * temp2[ 2 ]);
+			}
+			
+			/* color the luxel with the normal */
+			else if( normalmap )
+			{
+				radVertLuxel[ 0 ] = (verts[ i ].normal[ 0 ] + 1.0f) * 127.5f;
+				radVertLuxel[ 1 ] = (verts[ i ].normal[ 1 ] + 1.0f) * 127.5f;
+				radVertLuxel[ 2 ] = (verts[ i ].normal[ 2 ] + 1.0f) * 127.5f;
+			}
+			
+			/* illuminate the vertex */
+			else
+			{
+				/* clear vertex luxel */
+				VectorCopy( ambientColor, radVertLuxel );
+				
+				/* try at initial origin */
+				trace.cluster = ClusterForPointExtFilter( verts[ i ].xyz, VERTEX_EPSILON, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ] );
+				if( trace.cluster >= 0 )
+				{
+					/* setup trace */
+					VectorCopy( verts[ i ].xyz, trace.origin );
+					VectorCopy( verts[ i ].normal, trace.normal );
+					
+					/* trace */
+					LightingAtSample( &trace, ds->vertexStyles, colors );
+					
+					/* store */
+					for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+					{
+						radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
+						VectorCopy( colors[ lightmapNum ], radVertLuxel );
+					}
+				}
+				
+				/* is this sample bright enough? */
+				if( radVertLuxel[ 0 ] <= ambientColor[ 0 ] &&
+					radVertLuxel[ 1 ] <= ambientColor[ 1 ] &&
+					radVertLuxel[ 2 ] <= ambientColor[ 2 ] )
+				{
+					/* nudge the sample point around a bit */
+					for( x = 0; x < 4; x++ )
+					{
+						/* two's complement 0, 1, -1, 2, -2, etc */
+						x1 = ((x >> 1) ^ (x & 1 ? -1 : 0)) + (x & 1);
+						
+						for( y = 0; y < 4; y++ )
+						{
+							y1 = ((y >> 1) ^ (y & 1 ? -1 : 0)) + (y & 1);
+							
+							for( z = 0; z < 4; z++ )
+							{
+								z1 = ((z >> 1) ^ (z & 1 ? -1 : 0)) + (z & 1);
+								
+								/* nudge origin */
+								trace.origin[ 0 ] = verts[ i ].xyz[ 0 ] + (VERTEX_NUDGE * x1);
+								trace.origin[ 1 ] = verts[ i ].xyz[ 1 ] + (VERTEX_NUDGE * y1);
+								trace.origin[ 2 ] = verts[ i ].xyz[ 2 ] + (VERTEX_NUDGE * z1);
+								
+								/* try at nudged origin */
+								trace.cluster = ClusterForPointExtFilter( origin, VERTEX_EPSILON, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ] );
+								if( trace.cluster < 0 )
+									continue;
+															
+								/* trace */
+								LightingAtSample( &trace, ds->vertexStyles, colors );
+								
+								/* store */
+								for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+								{
+									radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
+									VectorCopy( colors[ lightmapNum ], radVertLuxel );
+								}
+								
+								/* bright enough? */
+								radVertLuxel = RAD_VERTEX_LUXEL( 0, ds->firstVert + i );
+								if( radVertLuxel[ 0 ] > ambientColor[ 0 ] ||
+									radVertLuxel[ 1 ] > ambientColor[ 1 ] ||
+									radVertLuxel[ 2 ] > ambientColor[ 2 ] )
+									x = y = z = 1000;
+							}
+						}
+					}
+				}
+			}
+			
+			/* another happy customer */
+			numVertsIlluminated++;
+			
+			/* store it */
+			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				/* get luxels */
+				vertLuxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
+				radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
+				
+				/* store */
+				if( bouncing || bounce == 0 || !bounceOnly )
+					VectorAdd( vertLuxel, radVertLuxel, vertLuxel );
+				ColorToBytes( vertLuxel, verts[ i ].color[ lightmapNum ], info->si->vertexScale );
+			}
+		}
+		
+		/* free light list */
+		FreeTraceLights( &trace );
+		
+		/* return to sender */
+		return;
+	}
+	
+	/* -----------------------------------------------------------------
+	   reconstitute vertex lighting from the luxels
+	   ----------------------------------------------------------------- */
+	
+	/* set styles from lightmap */
+	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		ds->vertexStyles[ lightmapNum ] = lm->styles[ lightmapNum ];
+	
+	/* get max search radius */
+	maxRadius = lm->sw;
+	maxRadius = maxRadius > lm->sh ? maxRadius : lm->sh;
+	
+	/* walk the surface verts */
+	verts = yDrawVerts + ds->firstVert;
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		/* do each lightmap */
+		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		{
+			/* early out */
+			if( lm->superLuxels[ lightmapNum ] == NULL )
+				continue;
+			
+			/* get luxel coords */
+			x = verts[ i ].lightmap[ lightmapNum ][ 0 ];
+			y = verts[ i ].lightmap[ lightmapNum ][ 1 ];
+			if( x < 0 )
+				x = 0;
+			else if( x >= lm->sw )
+				x = lm->sw - 1;
+			if( y < 0 )
+				y = 0;
+			else if( y >= lm->sh )
+				y = lm->sh - 1;
+			
+			/* get vertex luxels */
+			vertLuxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
+			radVertLuxel = RAD_VERTEX_LUXEL( lightmapNum, ds->firstVert + i );
+			
+			/* color the luxel with the normal? */
+			if( normalmap )
+			{
+				radVertLuxel[ 0 ] = (verts[ i ].normal[ 0 ] + 1.0f) * 127.5f;
+				radVertLuxel[ 1 ] = (verts[ i ].normal[ 1 ] + 1.0f) * 127.5f;
+				radVertLuxel[ 2 ] = (verts[ i ].normal[ 2 ] + 1.0f) * 127.5f;
+			}
+			
+			/* color the luxel with surface num? */
+			else if( debugSurfaces )
+				VectorCopy( debugColors[ num % 12 ], radVertLuxel );
+			
+			/* divine color from the superluxels */
+			else
+			{
+				/* increasing radius */
+				VectorClear( radVertLuxel );
+				samples = 0.0f;
+				for( radius = 0; radius < maxRadius && samples <= 0.0f; radius++ )
+				{
+					/* sample within radius */
+					for( sy = (y - radius); sy <= (y + radius); sy++ )
+					{
+						if( sy < 0 || sy >= lm->sh )
+							continue;
+						
+						for( sx = (x - radius); sx <= (x + radius); sx++ )
+						{
+							if( sx < 0 || sx >= lm->sw )
+								continue;
+							
+							/* get luxel particulars */
+							luxel = SUPER_LUXEL( lightmapNum, sx, sy );
+							cluster = SUPER_CLUSTER( sx, sy );
+							if( *cluster < 0 )
+								continue;
+							
+							/* testing: must be brigher than ambient color */
+							//%	if( luxel[ 0 ] <= ambientColor[ 0 ] || luxel[ 1 ] <= ambientColor[ 1 ] || luxel[ 2 ] <= ambientColor[ 2 ] )
+							//%		continue;
+							
+							/* add its distinctiveness to our own */
+							VectorAdd( radVertLuxel, luxel, radVertLuxel );
+							samples += luxel[ 3 ];
+						}
+					}
+				}
+				
+				/* any color? */
+				if( samples > 0.0f )
+					VectorDivide( radVertLuxel, samples, radVertLuxel );
+				else
+					VectorCopy( ambientColor, radVertLuxel );
+			}
+			
+			/* store into floating point storage */
+			VectorAdd( vertLuxel, radVertLuxel, vertLuxel );
+			numVertsIlluminated++;
+			
+			/* store into bytes (for vertex approximation) */
+			ColorToBytes( vertLuxel, verts[ i ].color[ lightmapNum ], 1.0f );
+		}
+	}
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+light optimization (-fast)
+
+creates a list of lights that will affect a surface and stores it in tw
+this is to optimize surface lighting by culling out as many of the
+lights in the world as possible from further calculation
+
+------------------------------------------------------------------------------- */
+
+/*
+SetupBrushes()
+determines opaque brushes in the world and find sky shaders for sunlight calculations
+*/
+
+void SetupBrushes( void )
+{
+	int				i, j, b, compileFlags;
+	qboolean		inside;
+	bspBrush_t		*brush;
+	bspBrushSide_t	*side;
+	bspShader_t		*shader;
+	shaderInfo_t	*si;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- SetupBrushes ---\n" );
+	
+	/* allocate */
+	if( opaqueBrushes == NULL )
+		opaqueBrushes = safe_malloc( numBSPBrushes / 8 + 1 );
+	
+	/* clear */
+	memset( opaqueBrushes, 0, numBSPBrushes / 8 + 1 );
+	numOpaqueBrushes = 0;
+	
+	/* walk the list of worldspawn brushes */
+	for( i = 0; i < bspModels[ 0 ].numBSPBrushes; i++ )
+	{
+		/* get brush */
+		b = bspModels[ 0 ].firstBSPBrush + i;
+		brush = &bspBrushes[ b ];
+		
+		/* check all sides */
+		inside = qtrue;
+		compileFlags = 0;
+		for( j = 0; j < brush->numSides && inside; j++ )
+		{
+			/* do bsp shader calculations */
+			side = &bspBrushSides[ brush->firstSide + j ];
+			shader = &bspShaders[ side->shaderNum ];
+			
+			/* get shader info */
+			si = ShaderInfoForShader( shader->shader );
+			if( si == NULL )
+				continue;
+			
+			/* or together compile flags */
+			compileFlags |= si->compileFlags;
+		}
+		
+		/* determine if this brush is opaque to light */
+		if( !(compileFlags & C_TRANSLUCENT) )
+		{
+			opaqueBrushes[ b >> 3 ] |= (1 << (b & 7));
+			numOpaqueBrushes++;
+			maxOpaqueBrush = i;
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d opaque brushes\n", numOpaqueBrushes );
+}
+
+
+
+/*
+ClusterVisible()
+determines if two clusters are visible to each other using the PVS
+*/
+
+qboolean ClusterVisible( int a, int b )
+{
+	int			portalClusters, leafBytes;
+	byte		*pvs;
+	
+	
+	/* dummy check */
+	if( a < 0 || b < 0 )
+		return qfalse;
+	
+	/* early out */
+	if( a == b )
+		return qtrue;
+	
+	/* not vised? */
+	if( numBSPVisBytes <=8 )
+		return qtrue;
+	
+	/* get pvs data */
+	portalClusters = ((int *) bspVisBytes)[ 0 ];
+	leafBytes = ((int*) bspVisBytes)[ 1 ];
+	pvs = bspVisBytes + VIS_HEADER_SIZE + (a * leafBytes);
+	
+	/* check */
+	if( (pvs[ b >> 3 ] & (1 << (b & 7))) )
+		return qtrue;
+	return qfalse;
+}
+
+
+
+/*
+PointInLeafNum_r()
+borrowed from vlight.c
+*/
+
+int	PointInLeafNum_r( vec3_t point, int nodenum )
+{
+	int			leafnum;
+	vec_t		dist;
+	bspNode_t		*node;
+	bspPlane_t	*plane;
+	
+	
+	while( nodenum >= 0 )
+	{
+		node = &bspNodes[ nodenum ];
+		plane = &bspPlanes[ node->planeNum ];
+		dist = DotProduct( point, plane->normal ) - plane->dist;
+		if( dist > 0.1 )
+			nodenum = node->children[ 0 ];
+		else if( dist < -0.1 )
+			nodenum = node->children[ 1 ];
+		else
+		{
+			leafnum = PointInLeafNum_r( point, node->children[ 0 ] );
+			if( bspLeafs[ leafnum ].cluster != -1 )
+				return leafnum;
+			nodenum = node->children[ 1 ];
+		}
+	}
+	
+	leafnum = -nodenum - 1;
+	return leafnum;
+}
+
+
+
+/*
+PointInLeafnum()
+borrowed from vlight.c
+*/
+
+int	PointInLeafNum( vec3_t point )
+{
+	return PointInLeafNum_r( point, 0 );
+}
+
+
+
+/*
+ClusterVisibleToPoint() - ydnar
+returns qtrue if point can "see" cluster
+*/
+
+qboolean ClusterVisibleToPoint( vec3_t point, int cluster )
+{
+	int		pointCluster;
+	
+
+	/* get leafNum for point */
+	pointCluster = ClusterForPoint( point );
+	if( pointCluster < 0 )
+		return qfalse;
+	
+	/* check pvs */
+	return ClusterVisible( pointCluster, cluster );
+}
+
+
+
+/*
+ClusterForPoint() - ydnar
+returns the pvs cluster for point
+*/
+
+int ClusterForPoint( vec3_t point )
+{
+	int		leafNum;
+	
+
+	/* get leafNum for point */
+	leafNum = PointInLeafNum( point );
+	if( leafNum < 0 )
+		return -1;
+	
+	/* return the cluster */
+	return bspLeafs[ leafNum ].cluster;
+}
+
+
+
+/*
+ClusterForPointExt() - ydnar
+also takes brushes into account for occlusion testing
+*/
+
+int ClusterForPointExt( vec3_t point, float epsilon )
+{
+	int				i, j, b, leafNum, cluster;
+	float			dot;
+	qboolean		inside;
+	int				*brushes, numBSPBrushes;
+	bspLeaf_t		*leaf;
+	bspBrush_t		*brush;
+	bspPlane_t		*plane;
+	
+	
+	/* get leaf for point */
+	leafNum = PointInLeafNum( point );
+	if( leafNum < 0 )
+		return -1;
+	leaf = &bspLeafs[ leafNum ];
+	
+	/* get the cluster */
+	cluster = leaf->cluster;
+	if( cluster < 0 )
+		return -1;
+	
+	/* transparent leaf, so check point against all brushes in the leaf */
+	brushes = &bspLeafBrushes[ leaf->firstBSPLeafBrush ];
+	numBSPBrushes = leaf->numBSPLeafBrushes;
+	for( i = 0; i < numBSPBrushes; i++ )
+	{
+		/* get parts */
+		b = brushes[ i ];
+		if( b > maxOpaqueBrush )
+			continue;
+		brush = &bspBrushes[ b ];
+		if( !(opaqueBrushes[ b >> 3 ] & (1 << (b & 7))) )
+			continue;
+		
+		/* check point against all planes */
+		inside = qtrue;
+		for( j = 0; j < brush->numSides && inside; j++ )
+		{
+			plane = &bspPlanes[ bspBrushSides[ brush->firstSide + j ].planeNum ];
+			dot = DotProduct( point, plane->normal );
+			dot -= plane->dist;
+			if( dot > epsilon )
+				inside = qfalse;
+		}
+		
+		/* if inside, return bogus cluster */
+		if( inside )
+			return -1 - b;
+	}
+	
+	/* if the point made it this far, it's not inside any opaque brushes */
+	return cluster;
+}
+
+
+
+/*
+ClusterForPointExtFilter() - ydnar
+adds cluster checking against a list of known valid clusters
+*/
+
+int ClusterForPointExtFilter( vec3_t point, float epsilon, int numClusters, int *clusters )
+{
+	int		i, cluster;
+	
+	
+	/* get cluster for point */
+	cluster = ClusterForPointExt( point, epsilon );
+	
+	/* check if filtering is necessary */
+	if( cluster < 0 || numClusters <= 0 || clusters == NULL )
+		return cluster;
+	
+	/* filter */
+	for( i = 0; i < numClusters; i++ )
+	{
+		if( cluster == clusters[ i ] || ClusterVisible( cluster, clusters[ i ] ) )
+			return cluster;
+	}
+	
+	/* failed */
+	return -1;
+}
+
+
+
+/*
+ShaderForPointInLeaf() - ydnar
+checks a point against all brushes in a leaf, returning the shader of the brush
+also sets the cumulative surface and content flags for the brush hit
+*/
+
+int ShaderForPointInLeaf( vec3_t point, int leafNum, float epsilon, int wantContentFlags, int wantSurfaceFlags, int *contentFlags, int *surfaceFlags )
+{
+	int				i, j;
+	float			dot;
+	qboolean		inside;
+	int				*brushes, numBSPBrushes;
+	bspLeaf_t			*leaf;
+	bspBrush_t		*brush;
+	bspBrushSide_t	*side;
+	bspPlane_t		*plane;
+	bspShader_t		*shader;
+	int				allSurfaceFlags, allContentFlags;
+
+	
+	/* clear things out first */
+	*surfaceFlags = 0;
+	*contentFlags = 0;
+	
+	/* get leaf */
+	if( leafNum < 0 )
+		return -1;
+	leaf = &bspLeafs[ leafNum ];
+	
+	/* transparent leaf, so check point against all brushes in the leaf */
+	brushes = &bspLeafBrushes[ leaf->firstBSPLeafBrush ];
+	numBSPBrushes = leaf->numBSPLeafBrushes;
+	for( i = 0; i < numBSPBrushes; i++ )
+	{
+		/* get parts */
+		brush = &bspBrushes[ brushes[ i ] ];
+		
+		/* check point against all planes */
+		inside = qtrue;
+		allSurfaceFlags = 0;
+		allContentFlags = 0;
+		for( j = 0; j < brush->numSides && inside; j++ )
+		{
+			side = &bspBrushSides[ brush->firstSide + j ];
+			plane = &bspPlanes[ side->planeNum ];
+			dot = DotProduct( point, plane->normal );
+			dot -= plane->dist;
+			if( dot > epsilon )
+				inside = qfalse;
+			else
+			{
+				shader = &bspShaders[ side->shaderNum ];
+				allSurfaceFlags |= shader->surfaceFlags;
+				allContentFlags |= shader->contentFlags;
+			}
+		}
+		
+		/* handle if inside */
+		if( inside )
+		{
+			/* if there are desired flags, check for same and continue if they aren't matched */
+			if( wantContentFlags && !(wantContentFlags & allContentFlags) )
+				continue;
+			if( wantSurfaceFlags && !(wantSurfaceFlags & allSurfaceFlags) )
+				continue;
+			
+			/* store the cumulative flags and return the brush shader (which is mostly useless) */
+			*surfaceFlags = allSurfaceFlags;
+			*contentFlags = allContentFlags;
+			return brush->shaderNum;
+		}
+	}
+	
+	/* if the point made it this far, it's not inside any brushes */
+	return -1;
+}
+
+
+
+/*
+ChopBounds()
+chops a bounding box by the plane defined by origin and normal
+returns qfalse if the bounds is entirely clipped away
+
+this is not exactly the fastest way to do this...
+*/
+
+qboolean ChopBounds( vec3_t mins, vec3_t maxs, vec3_t origin, vec3_t normal )
+{
+	/* FIXME: rewrite this so it doesn't use bloody brushes */
+	return qtrue;
+}
+
+
+
+/*
+SetupEnvelopes()
+calculates each light's effective envelope,
+taking into account brightness, type, and pvs.
+*/
+
+#define LIGHT_EPSILON	0.125f
+#define LIGHT_NUDGE		2.0f
+
+void SetupEnvelopes( qboolean forGrid, qboolean fastFlag )
+{
+	int			i, x, y, z, x1, y1, z1;
+	light_t		*light, *light2, **owner;
+	bspLeaf_t	*leaf;
+	vec3_t		origin, dir, mins, maxs, nullVector = { 0, 0, 0 };
+	float		radius, intensity;
+	light_t		*buckets[ 256 ];
+	
+	
+	/* early out for weird cases where there are no lights */
+	if( lights == NULL )
+		return;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- SetupEnvelopes%s ---\n", fastFlag ? " (fast)" : "" );
+	
+	/* count lights */
+	numLights = 0;
+	numCulledLights = 0;
+	owner = &lights;
+	while( *owner != NULL )
+	{
+		/* get light */
+		light = *owner;
+		
+		/* handle negative lights */
+		if( light->photons < 0.0f || light->add < 0.0f )
+		{
+			light->photons *= -1.0f;
+			light->add *= -1.0f;
+			light->flags |= LIGHT_NEGATIVE;
+		}
+		
+		/* sunlight? */
+		if( light->type == EMIT_SUN )
+		{
+			/* special cased */
+			light->cluster = 0;
+			light->envelope = MAX_WORLD_COORD * 8.0f;
+			VectorSet( light->mins, MIN_WORLD_COORD * 8.0f, MIN_WORLD_COORD * 8.0f, MIN_WORLD_COORD * 8.0f );
+			VectorSet( light->maxs, MAX_WORLD_COORD * 8.0f, MAX_WORLD_COORD * 8.0f, MAX_WORLD_COORD * 8.0f );
+		}
+		
+		/* everything else */
+		else
+		{
+			/* get pvs cluster for light */
+			light->cluster = ClusterForPointExt( light->origin, LIGHT_EPSILON );
+			
+			/* invalid cluster? */
+			if( light->cluster < 0 )
+			{
+				/* nudge the sample point around a bit */
+				for( x = 0; x < 4; x++ )
+				{
+					/* two's complement 0, 1, -1, 2, -2, etc */
+					x1 = ((x >> 1) ^ (x & 1 ? -1 : 0)) + (x & 1);
+					
+					for( y = 0; y < 4; y++ )
+					{
+						y1 = ((y >> 1) ^ (y & 1 ? -1 : 0)) + (y & 1);
+						
+						for( z = 0; z < 4; z++ )
+						{
+							z1 = ((z >> 1) ^ (z & 1 ? -1 : 0)) + (z & 1);
+							
+							/* nudge origin */
+							origin[ 0 ] = light->origin[ 0 ] + (LIGHT_NUDGE * x1);
+							origin[ 1 ] = light->origin[ 1 ] + (LIGHT_NUDGE * y1);
+							origin[ 2 ] = light->origin[ 2 ] + (LIGHT_NUDGE * z1);
+							
+							/* try at nudged origin */
+							light->cluster = ClusterForPointExt( origin, LIGHT_EPSILON );
+							if( light->cluster < 0 )
+								continue;
+									
+							/* set origin */
+							VectorCopy( origin, light->origin );
+						}
+					}
+				}
+			}
+			
+			/* only calculate for lights in pvs and outside of opaque brushes */
+			if( light->cluster >= 0 )
+			{
+				/* set light fast flag */
+				if( fastFlag )
+					light->flags |= LIGHT_FAST_TEMP;
+				else
+					light->flags &= ~LIGHT_FAST_TEMP;
+				if( light->si && light->si->noFast )
+					light->flags &= ~(LIGHT_FAST | LIGHT_FAST_TEMP);
+				
+				/* clear light envelope */
+				light->envelope = 0;
+				
+				/* handle area lights */
+				if( exactPointToPolygon && light->type == EMIT_AREA && light->w != NULL )
+				{
+					/* ugly hack to calculate extent for area lights, but only done once */
+					VectorScale( light->normal, -1.0f, dir );
+					for( radius = 100.0f; radius < 130000.0f && light->envelope == 0; radius += 10.0f )
+					{
+						float	factor;
+						
+						VectorMA( light->origin, radius, light->normal, origin );
+						factor = PointToPolygonFormFactor( origin, dir, light->w );
+						if( factor < 0.0f )
+							factor *= -1.0f;
+						if( (factor * light->add) <= light->falloffTolerance )
+							light->envelope = radius;
+					}
+					
+					/* check for fast mode */
+					if( !(light->flags & LIGHT_FAST) && !(light->flags & LIGHT_FAST_TEMP) )
+						light->envelope = MAX_WORLD_COORD * 8.0f;
+				}
+				else
+				{
+					radius = 0.0f;
+					intensity = light->photons;
+				}
+				
+				/* other calcs */
+				if( light->envelope <= 0.0f )
+				{
+					/* solve distance for non-distance lights */
+					if( !(light->flags & LIGHT_ATTEN_DISTANCE) )
+						light->envelope = MAX_WORLD_COORD * 8.0f;
+					
+					/* solve distance for linear lights */
+					else if( (light->flags & LIGHT_ATTEN_LINEAR ) )
+						//% light->envelope = ((intensity / light->falloffTolerance) * linearScale - 1 + radius) / light->fade;
+						light->envelope = ((intensity * linearScale) - light->falloffTolerance) / light->fade;
+
+						/*
+						add = angle * light->photons * linearScale - (dist * light->fade);
+						T = (light->photons * linearScale) - (dist * light->fade);
+						T + (dist * light->fade) = (light->photons * linearScale);
+						dist * light->fade = (light->photons * linearScale) - T;
+						dist = ((light->photons * linearScale) - T) / light->fade;
+						*/
+					
+					/* solve for inverse square falloff */
+					else
+						light->envelope = sqrt( intensity / light->falloffTolerance ) + radius;
+						
+						/*
+						add = light->photons / (dist * dist);
+						T = light->photons / (dist * dist);
+						T * (dist * dist) = light->photons;
+						dist = sqrt( light->photons / T );
+						*/
+				}
+				
+				/* chop radius against pvs */
+				{
+					/* clear bounds */
+					ClearBounds( mins, maxs );
+					
+					/* check all leaves */
+					for( i = 0; i < numBSPLeafs; i++ )
+					{
+						/* get test leaf */
+						leaf = &bspLeafs[ i ];
+						
+						/* in pvs? */
+						if( leaf->cluster < 0 )
+							continue;
+						if( ClusterVisible( light->cluster, leaf->cluster ) == qfalse )	/* ydnar: thanks Arnout for exposing my stupid error (this never failed before) */
+							continue;
+						
+						/* add this leafs bbox to the bounds */
+						VectorCopy( leaf->mins, origin );
+						AddPointToBounds( origin, mins, maxs );
+						VectorCopy( leaf->maxs, origin );
+						AddPointToBounds( origin, mins, maxs );
+					}
+					
+					/* test to see if bounds encompass light */
+					for( i = 0; i < 3; i++ )
+					{
+						if( mins[ i ] > light->origin[ i ] || maxs[ i ] < light->origin[ i ] )
+						{
+							//% Sys_Printf( "WARNING: Light PVS bounds (%.0f, %.0f, %.0f) -> (%.0f, %.0f, %.0f)\ndo not encompass light %d (%f, %f, %f)\n",
+							//% 	mins[ 0 ], mins[ 1 ], mins[ 2 ],
+							//% 	maxs[ 0 ], maxs[ 1 ], maxs[ 2 ],
+							//% 	numLights, light->origin[ 0 ], light->origin[ 1 ], light->origin[ 2 ] );
+							AddPointToBounds( light->origin, mins, maxs );
+						}
+					}
+					
+					/* chop the bounds by a plane for area lights and spotlights */
+					if( light->type == EMIT_AREA || light->type == EMIT_SPOT )
+						ChopBounds( mins, maxs, light->origin, light->normal );
+					
+					/* copy bounds */
+					VectorCopy( mins, light->mins );
+					VectorCopy( maxs, light->maxs );
+					
+					/* reflect bounds around light origin */
+					//%	VectorMA( light->origin, -1.0f, origin, origin );
+					VectorScale( light->origin, 2, origin );
+					VectorSubtract( origin, maxs, origin );
+					AddPointToBounds( origin, mins, maxs );
+					//%	VectorMA( light->origin, -1.0f, mins, origin );
+					VectorScale( light->origin, 2, origin );
+					VectorSubtract( origin, mins, origin );
+					AddPointToBounds( origin, mins, maxs );
+					 
+					/* calculate spherical bounds */
+					VectorSubtract( maxs, light->origin, dir );
+					radius = (float) VectorLength( dir );
+					
+					/* if this radius is smaller than the envelope, then set the envelope to it */
+					if( radius < light->envelope )
+					{
+						light->envelope = radius;
+						//%	Sys_FPrintf( SYS_VRB, "PVS Cull (%d): culled\n", numLights );
+					}
+					//%	else
+					//%		Sys_FPrintf( SYS_VRB, "PVS Cull (%d): failed (%8.0f > %8.0f)\n", numLights, radius, light->envelope );
+				}
+				
+				/* add grid/surface only check */
+				if( forGrid )
+				{
+					if( !(light->flags & LIGHT_GRID) )
+						light->envelope = 0.0f;
+				}
+				else
+				{
+					if( !(light->flags & LIGHT_SURFACES) )
+						light->envelope = 0.0f;
+				}
+			}
+			
+			/* culled? */
+			if( light->cluster < 0 || light->envelope <= 0.0f )
+			{
+				/* debug code */
+				//%	Sys_Printf( "Culling light: Cluster: %d Envelope: %f\n", light->cluster, light->envelope );
+				
+				/* delete the light */
+				numCulledLights++;
+				*owner = light->next;
+				if( light->w != NULL )
+					free( light->w );
+				free( light );
+				continue;
+			}
+		}
+		
+		/* square envelope */
+		light->envelope2 = (light->envelope * light->envelope);
+		
+		/* increment light count */
+		numLights++;
+		
+		/* set next light */
+		owner = &((**owner).next);
+	}
+	
+	/* bucket sort lights by style */
+	memset( buckets, 0, sizeof( buckets ) );
+	light2 = NULL;
+	for( light = lights; light != NULL; light = light2 )
+	{
+		/* get next light */
+		light2 = light->next;
+		
+		/* filter into correct bucket */
+		light->next = buckets[ light->style ];
+		buckets[ light->style ] = light;
+	}
+	
+	/* filter back into light list */
+	lights = NULL;
+	for( i = 255; i >= 0; i-- )
+	{
+		light2 = NULL;
+		for( light = buckets[ i ]; light != NULL; light = light2 )
+		{
+			light2 = light->next;
+			light->next = lights;
+			lights = light;
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_Printf( "%9d total lights\n", numLights );
+	Sys_Printf( "%9d culled lights\n", numCulledLights );
+}
+
+
+
+/*
+CreateTraceLightsForBounds()
+creates a list of lights that affect the given bounding box and pvs clusters (bsp leaves)
+*/
+
+void CreateTraceLightsForBounds( vec3_t mins, vec3_t maxs, vec3_t normal, int numClusters, int *clusters, int flags, trace_t *trace )
+{
+	int			i;
+	light_t		*light;
+	vec3_t		origin, dir, nullVector = { 0.0f, 0.0f, 0.0f };
+	float		radius, dist, length;
+	
+	
+	/* potential pre-setup  */
+	if( numLights == 0 )
+		SetupEnvelopes( qfalse, fast );
+	
+	/* debug code */
+	//% Sys_Printf( "CTWLFB: (%4.1f %4.1f %4.1f) (%4.1f %4.1f %4.1f)\n", mins[ 0 ], mins[ 1 ], mins[ 2 ], maxs[ 0 ], maxs[ 1 ], maxs[ 2 ] );
+	
+	/* allocate the light list */
+	trace->lights = safe_malloc( sizeof( light_t* ) * (numLights + 1) );
+	trace->numLights = 0;
+	
+	/* calculate spherical bounds */
+	VectorAdd( mins, maxs, origin );
+	VectorScale( origin, 0.5f, origin );
+	VectorSubtract( maxs, origin, dir );
+	radius = (float) VectorLength( dir );
+	
+	/* get length of normal vector */
+	if( normal != NULL )
+		length = VectorLength( normal );
+	else
+	{
+		normal = nullVector;
+		length = 0;
+	}
+	
+	/* test each light and see if it reaches the sphere */
+	/* note: the attenuation code MUST match LightingAtSample() */
+	for( light = lights; light; light = light->next )
+	{
+		/* check zero sized envelope */
+		if( light->envelope <= 0 )
+		{
+			lightsEnvelopeCulled++;
+			continue;
+		}
+		
+		/* check flags */
+		if( !(light->flags & flags) )
+			continue;
+		
+		/* sunlight skips all this nonsense */
+		if( light->type != EMIT_SUN )
+		{
+			/* sun only? */
+			if( sunOnly )
+				continue;
+			
+			/* check against pvs cluster */
+			if( numClusters > 0 && clusters != NULL )
+			{
+				for( i = 0; i < numClusters; i++ )
+				{
+					if( ClusterVisible( light->cluster, clusters[ i ] ) )
+						break;
+				}
+				
+				/* fixme! */
+				if( i == numClusters )
+				{
+					lightsClusterCulled++;
+					continue;
+				}
+			}
+			
+			/* if the light's bounding sphere intersects with the bounding sphere then this light needs to be tested */
+			VectorSubtract( light->origin, origin, dir );
+			dist = VectorLength( dir );
+			dist -= light->envelope;
+			dist -= radius;
+			if( dist > 0 )
+			{
+				lightsEnvelopeCulled++;
+				continue;
+			}
+			
+			/* check bounding box against light's pvs envelope (note: this code never eliminated any lights, so disabling it) */
+			#if 0
+			skip = qfalse;
+			for( i = 0; i < 3; i++ )
+			{
+				if( mins[ i ] > light->maxs[ i ] || maxs[ i ] < light->mins[ i ] )
+					skip = qtrue;
+			}
+			if( skip )
+			{
+				lightsBoundsCulled++;
+				continue;
+			}
+			#endif
+		}
+		
+		/* planar surfaces (except twosided surfaces) have a couple more checks */
+		if( length > 0.0f && trace->twoSided == qfalse )
+		{
+			/* lights coplanar with a surface won't light it */
+			if( !(light->flags & LIGHT_TWOSIDED) && DotProduct( light->normal, normal ) > 0.999f )
+			{
+				lightsPlaneCulled++;
+				continue;
+			}
+			
+			/* check to see if light is behind the plane */
+			if( DotProduct( light->origin, normal ) - DotProduct( origin, normal ) < -1.0f )
+			{
+				lightsPlaneCulled++;
+				continue;
+			}
+		}
+		
+		/* add this light */
+		trace->lights[ trace->numLights++ ] = light;
+	}
+	
+	/* make last night null */
+	trace->lights[ trace->numLights ] = NULL;
+}
+
+
+
+void FreeTraceLights( trace_t *trace )
+{
+	if( trace->lights != NULL )
+		free( trace->lights );
+}
+
+
+
+/*
+CreateTraceLightsForSurface()
+creates a list of lights that can potentially affect a drawsurface
+*/
+
+void CreateTraceLightsForSurface( int num, trace_t *trace )
+{
+	int					i;
+	vec3_t				mins, maxs, normal;
+	bspDrawVert_t		*dv;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	
+	
+	/* dummy check */
+	if( num < 0 )
+		return;
+	
+	/* get drawsurface and info */
+	ds = &bspDrawSurfaces[ num ];
+	info = &surfaceInfos[ num ];
+	
+	/* get the mins/maxs for the dsurf */
+	ClearBounds( mins, maxs );
+	VectorCopy( bspDrawVerts[ ds->firstVert ].normal, normal );
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		dv = &yDrawVerts[ ds->firstVert + i ];
+		AddPointToBounds( dv->xyz, mins, maxs );
+		if( !VectorCompare( dv->normal, normal ) )
+			VectorClear( normal );
+	}
+	
+	/* create the lights for the bounding box */
+	CreateTraceLightsForBounds( mins, maxs, normal, info->numSurfaceClusters, &surfaceClusters[ info->firstSurfaceCluster ], LIGHT_SURFACES, trace );
+}
+
+
+
+
+
diff --git a/tools/quake3/q3map2/lightmaps.c b/tools/quake3/q3map2/lightmaps.c
index c79dfb40..62977ddf 100644
--- a/tools/quake3/q3map2/lightmaps.c
+++ b/tools/quake3/q3map2/lightmaps.c
@@ -1,496 +1,496 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-*/
-
-#include "qbsp.h"
-
-
-/*
-
-  Lightmap allocation has to be done after all flood filling and
-  visible surface determination.
-
-*/
-
-int					numSortShaders;
-mapDrawSurface_t	*surfsOnShader[ MAX_MAP_SHADERS ];
-
-
-int		allocated[ LIGHTMAP_WIDTH ];
-
-int		numLightmaps = 1;
-int		c_exactLightmap = 0;
-int		c_planarPatch = 0;
-int		c_nonplanarLightmap = 0;
-
-
-void PrepareNewLightmap( void ) {
-	memset( allocated, 0, sizeof( allocated ) );
-	numLightmaps++;
-}
-
-/*
-===============
-AllocLMBlock
-
-returns a texture number and the position inside it
-===============
-*/
-qboolean AllocLMBlock (int w, int h, int *x, int *y)
-{
-	int		i, j;
-	int		best, best2;
-
-	best = LIGHTMAP_HEIGHT;
-
-	for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) {
-		best2 = 0;
-
-		for (j=0 ; j<w ; j++) {
-			if (allocated[i+j] >= best) {
-				break;
-			}
-			if (allocated[i+j] > best2) {
-				best2 = allocated[i+j];
-			}
-		}
-		if (j == w)	{	// this is a valid spot
-			*x = i;
-			*y = best = best2;
-		}
-	}
-
-	if (best + h > LIGHTMAP_HEIGHT) {
-		return qfalse;
-	}
-
-	for (i=0 ; i<w ; i++) {
-		allocated[*x + i] = best + h;
-	}
-
-	return qtrue;
-}
-
-
-/*
-===================
-AllocateLightmapForPatch
-===================
-*/
-//#define LIGHTMAP_PATCHSHIFT
-
-void AllocateLightmapForPatch( mapDrawSurface_t *ds )
-{
-	int			i, j, k;
-	drawVert_t	*verts;
-	int			w, h;
-	int			x, y;
-	float		s, t;
-	mesh_t		mesh, *subdividedMesh, *tempMesh, *newmesh;
-	int			widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;
-
-	verts = ds->verts;
-
-	mesh.width = ds->patchWidth;
-	mesh.height = ds->patchHeight;
-	mesh.verts = verts;
-	newmesh = SubdivideMesh( mesh, 8, 999 );
-
-	PutMeshOnCurve( *newmesh );
-	tempMesh = RemoveLinearMeshColumnsRows( newmesh );
-	FreeMesh(newmesh);
-	
-	/* get sample size */
- 	ssize = ds->sampleSize;
-	
-	
-#ifdef LIGHTMAP_PATCHSHIFT
- 	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable );
-#else
- 	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable );
-#endif
-
-	w = subdividedMesh->width;
-	h = subdividedMesh->height;
-
-#ifdef LIGHTMAP_PATCHSHIFT
-	w++;
-	h++;
-#endif
-
-	FreeMesh(subdividedMesh);
-
-	// allocate the lightmap
-	c_exactLightmap += w * h;
-
-	if ( !AllocLMBlock( w, h, &x, &y ) ) {
-		PrepareNewLightmap();
-		if ( !AllocLMBlock( w, h, &x, &y ) )
-		{
-			Error("Entity %i, brush %i: Lightmap allocation failed", 
-				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
-		}
-	}
-
-#ifdef LIGHTMAP_PATCHSHIFT
-	w--;
-	h--;
-#endif
-
-	// set the lightmap texture coordinates in the drawVerts
-	ds->lightmapNum = numLightmaps - 1;
-	ds->lightmapWidth = w;
-	ds->lightmapHeight = h;
-	ds->lightmapX = x;
-	ds->lightmapY = y;
-
-	for ( i = 0 ; i < ds->patchWidth ; i++ ) {
-		for ( k = 0 ; k < w ; k++ ) {
-			if ( originalWidths[k] >= i ) {
-				break;
-			}
-		}
-		if (k >= w)
-			k = w-1;
-		s = x + k;
-		for ( j = 0 ; j < ds->patchHeight ; j++ ) {
-			for ( k = 0 ; k < h ; k++ ) {
-				if ( originalHeights[k] >= j ) {
-					break;
-				}
-			}
-			if (k >= h)
-				k = h-1;
-			t = y + k;
-			verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
-			verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
-		}
-	}
-}
-
-
-/*
-===================
-AllocateLightmapForSurface
-===================
-*/
-
-//#define	LIGHTMAP_BLOCK	16
-
-void AllocateLightmapForSurface( mapDrawSurface_t *ds )
-{
-	vec3_t		mins, maxs, size, exactSize, delta;
-	int			i;
-	drawVert_t	*verts;
-	int			w, h;
- 	int			x, y, ssize;
-	int			axis;
-	vec3_t		vecs[ 2 ];
-	float		s, t;
-	vec3_t		origin;
-	vec4_t		plane;
-	float		d;
-	
-	
-	/* debug code */
-	#if 0
-		if( ds->type == SURF_META && ds->planar == qfalse )
-			Sys_Printf( "NPMS: %3d vertexes, %s\n", ds->numVerts, ds->shaderInfo->shader );
-		else if( ds->type == SURF_META && ds->planar == qtrue )
-			Sys_Printf( "PMS:  %3d vertexes, %s\n", ds->numVerts, ds->shaderInfo->shader );
-	#endif
-	
-	/* ydnar: handle planar patches */
-	if( noPatchFix == qtrue || (ds->type == SURF_PATCH && ds->planeNum < 0) )
-	{
-		AllocateLightmapForPatch( ds );
-		return;
-	}
-	
-	/* get sample size */
- 	ssize = ds->sampleSize;
-	
-	/* bound the surface */
-	ClearBounds( mins, maxs );
-	verts = ds->verts;
-	for ( i = 0 ; i < ds->numVerts ; i++ )
-		AddPointToBounds( verts[i].xyz, mins, maxs );
-	
-	/* round to the lightmap resolution */
-	for( i = 0; i < 3; i++ )
-	{
-		exactSize[i] = maxs[i] - mins[i];
- 		mins[i] = ssize * floor( mins[i] / ssize );
- 		maxs[i] = ssize * ceil( maxs[i] / ssize );
- 		size[i] = (maxs[i] - mins[i]) / ssize + 1;
-	}
-	
-	/* ydnar: lightmap projection axis is already stored */
-	memset( vecs, 0, sizeof( vecs ) );
-	
-	/* classify the plane (x y or z major) (ydnar: biased to z axis projection) */
-	if( ds->lightmapAxis[ 2 ] >= ds->lightmapAxis[ 0 ] && ds->lightmapAxis[ 2 ] >= ds->lightmapAxis[ 1 ] )
-	{
-		w = size[ 0 ];
-		h = size[ 1 ];
-		axis = 2;
-		vecs[ 0 ][ 0 ] = 1.0 / ssize;
-		vecs[ 1 ][ 1 ] = 1.0 / ssize;
-	}
-	else if( ds->lightmapAxis[ 0 ] >= ds->lightmapAxis[ 1 ] && ds->lightmapAxis[ 0 ] >= ds->lightmapAxis[ 2 ] )
-	{
-		w = size[ 1 ];
-		h = size[ 2 ];
-		axis = 0;
-		vecs[ 0 ][ 1 ] = 1.0 / ssize;
-		vecs[ 1 ][ 2 ] = 1.0 / ssize;
-	}
-	else
-	{
-		w = size[ 0 ];
-		h = size[ 2 ];
-		axis = 1;
-		vecs[ 0 ][ 0 ] = 1.0 / ssize;
-		vecs[ 1 ][ 2 ] = 1.0 / ssize;
-	}
-	
-	/* odd check, given projection is now precalculated */
-	if( ds->lightmapAxis[ axis ] == 0 )
-		Error( "Chose a 0 valued axis" );
-	
-	/* clamp to lightmap texture resolution */
-	if( w > LIGHTMAP_WIDTH )
-	{
-		VectorScale ( vecs[0], (float) LIGHTMAP_WIDTH / w, vecs[0] );
-		w = LIGHTMAP_WIDTH;
-	}
-	if( h > LIGHTMAP_HEIGHT )
-	{
-		VectorScale ( vecs[1], (float) LIGHTMAP_HEIGHT / h, vecs[1] );
-		h = LIGHTMAP_HEIGHT;
-	}
-	
-	
-	/* ydnar */
-	if( ds->planar == qfalse )
-		c_nonplanarLightmap += w * h;
-	c_exactLightmap += w * h;
-	
-	
-	if( !AllocLMBlock( w, h, &x, &y ) )
-	{
-		PrepareNewLightmap();
-		if ( !AllocLMBlock( w, h, &x, &y ) )
-		{
-			Error( "Entity %i, brush %i: Lightmap allocation failed", 
-				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
-		}
-	}
-
-	/* set the lightmap texture coordinates in the drawVerts */
-	ds->lightmapNum = numLightmaps - 1;
-	ds->lightmapWidth = w;
-	ds->lightmapHeight = h;
-	ds->lightmapX = x;
-	ds->lightmapY = y;
-	for ( i = 0 ; i < ds->numVerts ; i++ )
-	{
-		VectorSubtract( verts[i].xyz, mins, delta );
-		s = DotProduct( delta, vecs[0] ) + x + 0.5;
-		t = DotProduct( delta, vecs[1] ) + y + 0.5;
-		verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
-		verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
-	}
-
-	/* calculate the world coordinates of the lightmap samples */
-	
-	/* construct a plane from the first vert and clear bounding box */
-	
-	/* project mins onto plane to get origin */
-	VectorCopy( ds->lightmapVecs[ 2 ], plane );
-	plane[ 3 ] = DotProduct( ds->verts[ 0 ].xyz, plane );
-	d = DotProduct( mins, plane ) - plane[ 3 ];
-	d /= plane[ axis ];
-	
-	//% d = DotProduct( mins, plane->normal ) - plane->dist;
-	//% d /= plane->normal[ axis ];
-	VectorCopy( mins, origin );
-	origin[ axis ] -= d;
-
-	/* project stepped lightmap blocks and subtract to get planevecs */
-	for( i = 0; i < 2; i++ )
-	{
-		vec3_t	normalized;
-		float	len;
-
-		len = VectorNormalize( vecs[i], normalized );
-		VectorScale( normalized, (1.0/len), vecs[i] );
-		d = DotProduct( vecs[i], plane );
-		d /= plane[ axis ];
-		//%d = DotProduct( vecs[i], plane->normal );
-		//%d /= plane->normal[ axis ];
-		vecs[i][axis] -= d;
-	}
-	
-	/* store lightmap origin and vectors (fixme: make this work right) */
-	VectorCopy( origin, ds->lightmapOrigin );
-	//% VectorCopy( plane->normal, ds->lightmapVecs[ 2 ] );
-	
-	/* ydnar: lightmap vectors 0 and 1 are used for lod bounds, so don't overwrite */
-	if( ds->type == SURF_PATCH )
-		c_planarPatch++;
-	
-	/* store lightmap vectors */
-	VectorCopy( vecs[ 0 ], ds->lightmapVecs[ 0 ] );
-	VectorCopy( vecs[ 1 ], ds->lightmapVecs[ 1 ] );
-	
-	/* ydnar: print some stats */
-	//Sys_FPrintf( SYS_VRB, "Lightmap block %3d (%3d, %3d) (%3d x %3d) emitted\n", (numLightmaps - 1), x, y, w, h );
-}
-
-
-/*
-===================
-AllocateLightmaps
-===================
-*/
-void AllocateLightmaps( entity_t *e )
-{
-	int					i, j;
-	mapDrawSurface_t	*ds;
-	shaderInfo_t		*si;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB,"--- AllocateLightmaps ---\n" );
-	
-	
-	/* sort all surfaces by shader so common shaders will usually be in the same lightmap */
-	/* ydnar: this is done in two passes, because of an odd bug with lightmapped terrain */
-	numSortShaders = 0;
-	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
-	{
-		/* get surface and early out if possible */
-		ds = &mapDrawSurfs[ i ];
-		si = ds->shaderInfo;
-		if( si->surfaceFlags & SURF_VERTEXLIT )
-			continue;
-		if( ds->numVerts <= 0 )
-			continue;
-		
-		/* ydnar: handle brush faces and patches first */
-		if( ds->type != SURF_FACE && ds->type != SURF_PATCH )
-			continue;
-		
-		/* ydnar: this is unecessary because it should already be set */
-		//% VectorCopy( ds->plane.normal, ds->lightmapVecs[ 2 ] );
-
-		/* search for this shader */
-		for( j = 0 ; j < numSortShaders; j++ )
-		{
-			if( ds->shaderInfo == surfsOnShader[ j ]->shaderInfo )
-			{
-				ds->nextOnShader = surfsOnShader[ j ];
-				surfsOnShader[ j ] = ds;
-				break;
-			}
-		} 
-		
-		/* new shader */
-		if( j == numSortShaders )
-		{
-			if( numSortShaders >= MAX_MAP_SHADERS )
-				Error( "MAX_MAP_SHADERS" );
-			surfsOnShader[ j ] = ds;
-			ds->nextOnShader = NULL;
-			numSortShaders++;
-		}
-	}
-	
-	/* second pass, to allocate lightmapped terrain last */
-	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
-	{
-		/* get surface and early out if possible */
-		ds = &mapDrawSurfs[ i ];
-		si = ds->shaderInfo;
-		if( si->surfaceFlags & SURF_VERTEXLIT )
-			continue;
-		if( ds->numVerts <= 0 )
-			continue;
-		
-		/* ydnar: this only handles metasurfaces and terrain */
-		if( ds->type != SURF_TERRAIN && ds->type != SURF_META )
-			continue;
-		
-		/* ydnar: a lightmap projection should be pre-stored for anything but excessively curved patches */
-		if( VectorLength( ds->lightmapAxis ) <= 0 )
-			continue;
-		
-		/* search for this shader */
-		for( j = 0; j < numSortShaders; j++ )
-		{
-			if( ds->shaderInfo == surfsOnShader[ j ]->shaderInfo )
-			{
-				ds->nextOnShader = surfsOnShader[ j ];
-				surfsOnShader[ j ] = ds;
-				break;
-			}
-		}
-		
-		/* new shader */
-		if( j == numSortShaders )
-		{
-			if( numSortShaders >= MAX_MAP_SHADERS )
-				Error( "MAX_MAP_SHADERS" );
-			surfsOnShader[ j ] = ds;
-			ds->nextOnShader = NULL;
-			numSortShaders++;
-		}
-	}
-	
-	/* tot up shader count */
-	Sys_FPrintf( SYS_VRB, "%9d unique shaders\n", numSortShaders );
-	
-	/* for each shader, allocate lightmaps for each surface */
-	for( i = 0; i < numSortShaders; i++ )
-	{
-		si = surfsOnShader[ i ]->shaderInfo;
-		for( ds = surfsOnShader[ i ]; ds; ds = ds->nextOnShader )
-		{
-			/* ydnar: promoting pointlight above nolightmap */
-			if( si->surfaceFlags & SURF_POINTLIGHT )
-				ds->lightmapNum = -3;
-			else if( si->surfaceFlags & SURF_NOLIGHTMAP )
-				ds->lightmapNum = -1;
-			else
-				AllocateLightmapForSurface( ds );
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d exact lightmap texels\n", c_exactLightmap );
-	Sys_FPrintf( SYS_VRB, "%9d block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT );
-	Sys_FPrintf( SYS_VRB, "%9d non-planar or terrain lightmap texels\n", c_nonplanarLightmap );
-	Sys_FPrintf( SYS_VRB, "%9d planar patch lightmaps\n", c_planarPatch );
-	Sys_FPrintf( SYS_VRB, "%9d lightmap textures, size: %d Kbytes\n", numLightmaps, (numLightmaps * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3) / 1024 );
-}
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+*/
+
+#include "qbsp.h"
+
+
+/*
+
+  Lightmap allocation has to be done after all flood filling and
+  visible surface determination.
+
+*/
+
+int					numSortShaders;
+mapDrawSurface_t	*surfsOnShader[ MAX_MAP_SHADERS ];
+
+
+int		allocated[ LIGHTMAP_WIDTH ];
+
+int		numLightmaps = 1;
+int		c_exactLightmap = 0;
+int		c_planarPatch = 0;
+int		c_nonplanarLightmap = 0;
+
+
+void PrepareNewLightmap( void ) {
+	memset( allocated, 0, sizeof( allocated ) );
+	numLightmaps++;
+}
+
+/*
+===============
+AllocLMBlock
+
+returns a texture number and the position inside it
+===============
+*/
+qboolean AllocLMBlock (int w, int h, int *x, int *y)
+{
+	int		i, j;
+	int		best, best2;
+
+	best = LIGHTMAP_HEIGHT;
+
+	for ( i=0 ; i <= LIGHTMAP_WIDTH-w ; i++ ) {
+		best2 = 0;
+
+		for (j=0 ; j<w ; j++) {
+			if (allocated[i+j] >= best) {
+				break;
+			}
+			if (allocated[i+j] > best2) {
+				best2 = allocated[i+j];
+			}
+		}
+		if (j == w)	{	// this is a valid spot
+			*x = i;
+			*y = best = best2;
+		}
+	}
+
+	if (best + h > LIGHTMAP_HEIGHT) {
+		return qfalse;
+	}
+
+	for (i=0 ; i<w ; i++) {
+		allocated[*x + i] = best + h;
+	}
+
+	return qtrue;
+}
+
+
+/*
+===================
+AllocateLightmapForPatch
+===================
+*/
+//#define LIGHTMAP_PATCHSHIFT
+
+void AllocateLightmapForPatch( mapDrawSurface_t *ds )
+{
+	int			i, j, k;
+	drawVert_t	*verts;
+	int			w, h;
+	int			x, y;
+	float		s, t;
+	mesh_t		mesh, *subdividedMesh, *tempMesh, *newmesh;
+	int			widthtable[LIGHTMAP_WIDTH], heighttable[LIGHTMAP_HEIGHT], ssize;
+
+	verts = ds->verts;
+
+	mesh.width = ds->patchWidth;
+	mesh.height = ds->patchHeight;
+	mesh.verts = verts;
+	newmesh = SubdivideMesh( mesh, 8, 999 );
+
+	PutMeshOnCurve( *newmesh );
+	tempMesh = RemoveLinearMeshColumnsRows( newmesh );
+	FreeMesh(newmesh);
+	
+	/* get sample size */
+ 	ssize = ds->sampleSize;
+	
+	
+#ifdef LIGHTMAP_PATCHSHIFT
+ 	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH-1, widthtable, heighttable );
+#else
+ 	subdividedMesh = SubdivideMeshQuads( tempMesh, ssize, LIGHTMAP_WIDTH, widthtable, heighttable );
+#endif
+
+	w = subdividedMesh->width;
+	h = subdividedMesh->height;
+
+#ifdef LIGHTMAP_PATCHSHIFT
+	w++;
+	h++;
+#endif
+
+	FreeMesh(subdividedMesh);
+
+	// allocate the lightmap
+	c_exactLightmap += w * h;
+
+	if ( !AllocLMBlock( w, h, &x, &y ) ) {
+		PrepareNewLightmap();
+		if ( !AllocLMBlock( w, h, &x, &y ) )
+		{
+			Error("Entity %i, brush %i: Lightmap allocation failed", 
+				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
+		}
+	}
+
+#ifdef LIGHTMAP_PATCHSHIFT
+	w--;
+	h--;
+#endif
+
+	// set the lightmap texture coordinates in the drawVerts
+	ds->lightmapNum = numLightmaps - 1;
+	ds->lightmapWidth = w;
+	ds->lightmapHeight = h;
+	ds->lightmapX = x;
+	ds->lightmapY = y;
+
+	for ( i = 0 ; i < ds->patchWidth ; i++ ) {
+		for ( k = 0 ; k < w ; k++ ) {
+			if ( originalWidths[k] >= i ) {
+				break;
+			}
+		}
+		if (k >= w)
+			k = w-1;
+		s = x + k;
+		for ( j = 0 ; j < ds->patchHeight ; j++ ) {
+			for ( k = 0 ; k < h ; k++ ) {
+				if ( originalHeights[k] >= j ) {
+					break;
+				}
+			}
+			if (k >= h)
+				k = h-1;
+			t = y + k;
+			verts[i + j * ds->patchWidth].lightmap[0] = ( s + 0.5 ) / LIGHTMAP_WIDTH;
+			verts[i + j * ds->patchWidth].lightmap[1] = ( t + 0.5 ) / LIGHTMAP_HEIGHT;
+		}
+	}
+}
+
+
+/*
+===================
+AllocateLightmapForSurface
+===================
+*/
+
+//#define	LIGHTMAP_BLOCK	16
+
+void AllocateLightmapForSurface( mapDrawSurface_t *ds )
+{
+	vec3_t		mins, maxs, size, exactSize, delta;
+	int			i;
+	drawVert_t	*verts;
+	int			w, h;
+ 	int			x, y, ssize;
+	int			axis;
+	vec3_t		vecs[ 2 ];
+	float		s, t;
+	vec3_t		origin;
+	vec4_t		plane;
+	float		d;
+	
+	
+	/* debug code */
+	#if 0
+		if( ds->type == SURF_META && ds->planar == qfalse )
+			Sys_Printf( "NPMS: %3d vertexes, %s\n", ds->numVerts, ds->shaderInfo->shader );
+		else if( ds->type == SURF_META && ds->planar == qtrue )
+			Sys_Printf( "PMS:  %3d vertexes, %s\n", ds->numVerts, ds->shaderInfo->shader );
+	#endif
+	
+	/* ydnar: handle planar patches */
+	if( noPatchFix == qtrue || (ds->type == SURF_PATCH && ds->planeNum < 0) )
+	{
+		AllocateLightmapForPatch( ds );
+		return;
+	}
+	
+	/* get sample size */
+ 	ssize = ds->sampleSize;
+	
+	/* bound the surface */
+	ClearBounds( mins, maxs );
+	verts = ds->verts;
+	for ( i = 0 ; i < ds->numVerts ; i++ )
+		AddPointToBounds( verts[i].xyz, mins, maxs );
+	
+	/* round to the lightmap resolution */
+	for( i = 0; i < 3; i++ )
+	{
+		exactSize[i] = maxs[i] - mins[i];
+ 		mins[i] = ssize * floor( mins[i] / ssize );
+ 		maxs[i] = ssize * ceil( maxs[i] / ssize );
+ 		size[i] = (maxs[i] - mins[i]) / ssize + 1;
+	}
+	
+	/* ydnar: lightmap projection axis is already stored */
+	memset( vecs, 0, sizeof( vecs ) );
+	
+	/* classify the plane (x y or z major) (ydnar: biased to z axis projection) */
+	if( ds->lightmapAxis[ 2 ] >= ds->lightmapAxis[ 0 ] && ds->lightmapAxis[ 2 ] >= ds->lightmapAxis[ 1 ] )
+	{
+		w = size[ 0 ];
+		h = size[ 1 ];
+		axis = 2;
+		vecs[ 0 ][ 0 ] = 1.0 / ssize;
+		vecs[ 1 ][ 1 ] = 1.0 / ssize;
+	}
+	else if( ds->lightmapAxis[ 0 ] >= ds->lightmapAxis[ 1 ] && ds->lightmapAxis[ 0 ] >= ds->lightmapAxis[ 2 ] )
+	{
+		w = size[ 1 ];
+		h = size[ 2 ];
+		axis = 0;
+		vecs[ 0 ][ 1 ] = 1.0 / ssize;
+		vecs[ 1 ][ 2 ] = 1.0 / ssize;
+	}
+	else
+	{
+		w = size[ 0 ];
+		h = size[ 2 ];
+		axis = 1;
+		vecs[ 0 ][ 0 ] = 1.0 / ssize;
+		vecs[ 1 ][ 2 ] = 1.0 / ssize;
+	}
+	
+	/* odd check, given projection is now precalculated */
+	if( ds->lightmapAxis[ axis ] == 0 )
+		Error( "Chose a 0 valued axis" );
+	
+	/* clamp to lightmap texture resolution */
+	if( w > LIGHTMAP_WIDTH )
+	{
+		VectorScale ( vecs[0], (float) LIGHTMAP_WIDTH / w, vecs[0] );
+		w = LIGHTMAP_WIDTH;
+	}
+	if( h > LIGHTMAP_HEIGHT )
+	{
+		VectorScale ( vecs[1], (float) LIGHTMAP_HEIGHT / h, vecs[1] );
+		h = LIGHTMAP_HEIGHT;
+	}
+	
+	
+	/* ydnar */
+	if( ds->planar == qfalse )
+		c_nonplanarLightmap += w * h;
+	c_exactLightmap += w * h;
+	
+	
+	if( !AllocLMBlock( w, h, &x, &y ) )
+	{
+		PrepareNewLightmap();
+		if ( !AllocLMBlock( w, h, &x, &y ) )
+		{
+			Error( "Entity %i, brush %i: Lightmap allocation failed", 
+				ds->mapBrush->entitynum, ds->mapBrush->brushnum );
+		}
+	}
+
+	/* set the lightmap texture coordinates in the drawVerts */
+	ds->lightmapNum = numLightmaps - 1;
+	ds->lightmapWidth = w;
+	ds->lightmapHeight = h;
+	ds->lightmapX = x;
+	ds->lightmapY = y;
+	for ( i = 0 ; i < ds->numVerts ; i++ )
+	{
+		VectorSubtract( verts[i].xyz, mins, delta );
+		s = DotProduct( delta, vecs[0] ) + x + 0.5;
+		t = DotProduct( delta, vecs[1] ) + y + 0.5;
+		verts[i].lightmap[0] = s / LIGHTMAP_WIDTH;
+		verts[i].lightmap[1] = t / LIGHTMAP_HEIGHT;
+	}
+
+	/* calculate the world coordinates of the lightmap samples */
+	
+	/* construct a plane from the first vert and clear bounding box */
+	
+	/* project mins onto plane to get origin */
+	VectorCopy( ds->lightmapVecs[ 2 ], plane );
+	plane[ 3 ] = DotProduct( ds->verts[ 0 ].xyz, plane );
+	d = DotProduct( mins, plane ) - plane[ 3 ];
+	d /= plane[ axis ];
+	
+	//% d = DotProduct( mins, plane->normal ) - plane->dist;
+	//% d /= plane->normal[ axis ];
+	VectorCopy( mins, origin );
+	origin[ axis ] -= d;
+
+	/* project stepped lightmap blocks and subtract to get planevecs */
+	for( i = 0; i < 2; i++ )
+	{
+		vec3_t	normalized;
+		float	len;
+
+		len = VectorNormalize( vecs[i], normalized );
+		VectorScale( normalized, (1.0/len), vecs[i] );
+		d = DotProduct( vecs[i], plane );
+		d /= plane[ axis ];
+		//%d = DotProduct( vecs[i], plane->normal );
+		//%d /= plane->normal[ axis ];
+		vecs[i][axis] -= d;
+	}
+	
+	/* store lightmap origin and vectors (fixme: make this work right) */
+	VectorCopy( origin, ds->lightmapOrigin );
+	//% VectorCopy( plane->normal, ds->lightmapVecs[ 2 ] );
+	
+	/* ydnar: lightmap vectors 0 and 1 are used for lod bounds, so don't overwrite */
+	if( ds->type == SURF_PATCH )
+		c_planarPatch++;
+	
+	/* store lightmap vectors */
+	VectorCopy( vecs[ 0 ], ds->lightmapVecs[ 0 ] );
+	VectorCopy( vecs[ 1 ], ds->lightmapVecs[ 1 ] );
+	
+	/* ydnar: print some stats */
+	//Sys_FPrintf( SYS_VRB, "Lightmap block %3d (%3d, %3d) (%3d x %3d) emitted\n", (numLightmaps - 1), x, y, w, h );
+}
+
+
+/*
+===================
+AllocateLightmaps
+===================
+*/
+void AllocateLightmaps( entity_t *e )
+{
+	int					i, j;
+	mapDrawSurface_t	*ds;
+	shaderInfo_t		*si;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB,"--- AllocateLightmaps ---\n" );
+	
+	
+	/* sort all surfaces by shader so common shaders will usually be in the same lightmap */
+	/* ydnar: this is done in two passes, because of an odd bug with lightmapped terrain */
+	numSortShaders = 0;
+	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
+	{
+		/* get surface and early out if possible */
+		ds = &mapDrawSurfs[ i ];
+		si = ds->shaderInfo;
+		if( si->surfaceFlags & SURF_VERTEXLIT )
+			continue;
+		if( ds->numVerts <= 0 )
+			continue;
+		
+		/* ydnar: handle brush faces and patches first */
+		if( ds->type != SURF_FACE && ds->type != SURF_PATCH )
+			continue;
+		
+		/* ydnar: this is unecessary because it should already be set */
+		//% VectorCopy( ds->plane.normal, ds->lightmapVecs[ 2 ] );
+
+		/* search for this shader */
+		for( j = 0 ; j < numSortShaders; j++ )
+		{
+			if( ds->shaderInfo == surfsOnShader[ j ]->shaderInfo )
+			{
+				ds->nextOnShader = surfsOnShader[ j ];
+				surfsOnShader[ j ] = ds;
+				break;
+			}
+		} 
+		
+		/* new shader */
+		if( j == numSortShaders )
+		{
+			if( numSortShaders >= MAX_MAP_SHADERS )
+				Error( "MAX_MAP_SHADERS" );
+			surfsOnShader[ j ] = ds;
+			ds->nextOnShader = NULL;
+			numSortShaders++;
+		}
+	}
+	
+	/* second pass, to allocate lightmapped terrain last */
+	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
+	{
+		/* get surface and early out if possible */
+		ds = &mapDrawSurfs[ i ];
+		si = ds->shaderInfo;
+		if( si->surfaceFlags & SURF_VERTEXLIT )
+			continue;
+		if( ds->numVerts <= 0 )
+			continue;
+		
+		/* ydnar: this only handles metasurfaces and terrain */
+		if( ds->type != SURF_TERRAIN && ds->type != SURF_META )
+			continue;
+		
+		/* ydnar: a lightmap projection should be pre-stored for anything but excessively curved patches */
+		if( VectorLength( ds->lightmapAxis ) <= 0 )
+			continue;
+		
+		/* search for this shader */
+		for( j = 0; j < numSortShaders; j++ )
+		{
+			if( ds->shaderInfo == surfsOnShader[ j ]->shaderInfo )
+			{
+				ds->nextOnShader = surfsOnShader[ j ];
+				surfsOnShader[ j ] = ds;
+				break;
+			}
+		}
+		
+		/* new shader */
+		if( j == numSortShaders )
+		{
+			if( numSortShaders >= MAX_MAP_SHADERS )
+				Error( "MAX_MAP_SHADERS" );
+			surfsOnShader[ j ] = ds;
+			ds->nextOnShader = NULL;
+			numSortShaders++;
+		}
+	}
+	
+	/* tot up shader count */
+	Sys_FPrintf( SYS_VRB, "%9d unique shaders\n", numSortShaders );
+	
+	/* for each shader, allocate lightmaps for each surface */
+	for( i = 0; i < numSortShaders; i++ )
+	{
+		si = surfsOnShader[ i ]->shaderInfo;
+		for( ds = surfsOnShader[ i ]; ds; ds = ds->nextOnShader )
+		{
+			/* ydnar: promoting pointlight above nolightmap */
+			if( si->surfaceFlags & SURF_POINTLIGHT )
+				ds->lightmapNum = -3;
+			else if( si->surfaceFlags & SURF_NOLIGHTMAP )
+				ds->lightmapNum = -1;
+			else
+				AllocateLightmapForSurface( ds );
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d exact lightmap texels\n", c_exactLightmap );
+	Sys_FPrintf( SYS_VRB, "%9d block lightmap texels\n", numLightmaps * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT );
+	Sys_FPrintf( SYS_VRB, "%9d non-planar or terrain lightmap texels\n", c_nonplanarLightmap );
+	Sys_FPrintf( SYS_VRB, "%9d planar patch lightmaps\n", c_planarPatch );
+	Sys_FPrintf( SYS_VRB, "%9d lightmap textures, size: %d Kbytes\n", numLightmaps, (numLightmaps * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3) / 1024 );
+}
+
+
+
diff --git a/tools/quake3/q3map2/lightmaps_ydnar.c b/tools/quake3/q3map2/lightmaps_ydnar.c
index 22b6e376..df169351 100644
--- a/tools/quake3/q3map2/lightmaps_ydnar.c
+++ b/tools/quake3/q3map2/lightmaps_ydnar.c
@@ -1,2997 +1,2997 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define LIGHTMAPS_YDNAR_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-/* -------------------------------------------------------------------------------
-
-this file contains code that doe lightmap allocation and projection that
-runs in the -light phase.
-
-this is handled here rather than in the bsp phase for a few reasons--
-surfaces are no longer necessarily convex polygons, patches may or may not be
-planar or have lightmaps projected directly onto control points.
-
-also, this allows lightmaps to be calculated before being allocated and stored
-in the bsp. lightmaps that have little high-frequency information are candidates
-for having their resolutions scaled down.
-
-------------------------------------------------------------------------------- */
-
-/*
-WriteTGA24()
-based on WriteTGA() from imagelib.c
-*/
-
-void WriteTGA24( char *filename, byte *data, int width, int height, qboolean flip )
-{
-	int		i, c;
-	byte	*buffer, *in;
-	FILE	*file;
-	
-	
-	/* allocate a buffer and set it up */
-	buffer = safe_malloc( width * height * 3 + 18 );
-	memset( buffer, 0, 18 );
-	buffer[ 2 ] = 2;
-	buffer[ 12 ] = width & 255;
-	buffer[ 13 ] = width >> 8;
-	buffer[ 14 ] = height & 255;
-	buffer[ 15 ] = height >> 8;
-	buffer[ 16 ] = 24;
-
-	/* swap rgb to bgr */
-	c = (width * height * 3) + 18;
-	for( i = 18; i < c; i += 3 )
-	{
-		buffer[ i ] = data[ i - 18 + 2 ];		/* blue */
-		buffer[ i + 1 ] = data[ i - 18 + 1 ];	/* green */
-		buffer[ i + 2 ] = data[ i - 18 + 0 ];	/* red */
-	}
-	
-	/* write it and free the buffer */
-	file = fopen( filename, "wb" );
-	if( file == NULL )
-		Error( "Unable to open %s for writing", filename );
-	
-	/* flip vertically? */
-	if( flip )
-	{
-		fwrite( buffer, 1, 18, file );
-		for( in = buffer + ((height - 1) * width * 3) + 18; in >= buffer; in -= (width * 3) )
-			fwrite( in, 1, (width * 3), file );
-	}
-	else
-		fwrite( buffer, 1, c, file );
-	
-	/* close the file */
-	fclose( file );
-	free( buffer );
-}
-
-
-
-/*
-ExportLightmaps()
-exports the lightmaps as a list of numbered tga images
-*/
-
-void ExportLightmaps( void )
-{
-	int			i;
-	char		dirname[ 1024 ], filename[ 1024 ];
-	byte		*lightmap;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- ExportLightmaps ---\n");
-	
-	/* do some path mangling */
-	strcpy( dirname, source );
-	StripExtension( dirname );
-	
-	/* sanity check */
-	if( bspLightBytes == NULL )
-	{
-		Sys_Printf( "WARNING: No BSP lightmap data\n" );
-		return;
-	}
-	
-	/* make a directory for the lightmaps */
-	Q_mkdir( dirname );
-	
-	/* iterate through the lightmaps */
-	for( i = 0, lightmap = bspLightBytes; lightmap < (bspLightBytes + numBSPLightBytes); i++, lightmap += (LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3) )
-	{
-		/* write a tga image out */
-		sprintf( filename, "%s/lightmap_%04d.tga", dirname, i );
-		Sys_Printf( "Writing %s\n", filename );
-		WriteTGA24( filename, lightmap, LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT, qfalse );
-	}
-}
-
-
-
-/*
-ExportLightmapsMain()
-exports the lightmaps as a list of numbered tga images
-*/
-
-int ExportLightmapsMain( int argc, char **argv )
-{
-	/* arg checking */
-	if( argc < 1 )
-	{
-		Sys_Printf( "Usage: q3map -export [-v] <mapname>\n" );
-		return 0;
-	}
-	
-	/* do some path mangling */
-	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
-	StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	
-	/* load the bsp */
-	Sys_Printf( "Loading %s\n", source );
-	LoadBSPFile( source );
-	
-	/* export the lightmaps */
-	ExportLightmaps();
-	
-	/* return to sender */
-	return 0;
-}
-
-
-
-/*
-ImportLightmapsMain()
-imports the lightmaps from a list of numbered tga images
-*/
-
-int ImportLightmapsMain( int argc, char **argv )
-{
-	int			i, x, y, len, width, height;
-	char		dirname[ 1024 ], filename[ 1024 ];
-	byte		*lightmap, *buffer, *pixels, *in, *out;
-	
-	
-	/* arg checking */
-	if( argc < 1 )
-	{
-		Sys_Printf( "Usage: q3map -import [-v] <mapname>\n" );
-		return 0;
-	}
-	
-	/* do some path mangling */
-	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
-	StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	
-	/* load the bsp */
-	Sys_Printf( "Loading %s\n", source );
-	LoadBSPFile( source );
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- ImportLightmaps ---\n");
-	
-	/* do some path mangling */
-	strcpy( dirname, source );
-	StripExtension( dirname );
-	
-	/* sanity check */
-	if( bspLightBytes == NULL )
-		Error( "No lightmap data" );
-	
-	/* make a directory for the lightmaps */
-	Q_mkdir( dirname );
-	
-	/* iterate through the lightmaps */
-	for( i = 0, lightmap = bspLightBytes; lightmap < (bspLightBytes + numBSPLightBytes); i++, lightmap += (LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3) )
-	{
-		/* read a tga image */
-		sprintf( filename, "%s/lightmap_%04d.tga", dirname, i );
-		Sys_Printf( "Loading %s\n", filename );
-		buffer = NULL;
-		len = vfsLoadFile( filename, (void*) &buffer, -1 );
-		if( len < 0 )
-		{
-			Sys_Printf( "WARNING: Unable to load image %s\n", filename );
-			continue;
-		}
-		
-		/* parse file into an image */
-		pixels = NULL;
-		LoadTGABuffer( buffer, &pixels, &width, &height );
-		free( buffer );
-		
-		/* sanity check it */
-		if( pixels == NULL )
-		{
-			Sys_Printf( "WARNING: Unable to load image %s\n", filename );
-			continue;
-		}
-		if( width != LIGHTMAP_WIDTH || height != LIGHTMAP_HEIGHT )
-			Sys_Printf( "WARNING: Image %s is not the right size (%d, %d) != (%d, %d)\n",
-				filename, width, height, LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT );
-		
-		/* copy the pixels */
-		in = pixels;
-		for( y = 1; y <= LIGHTMAP_HEIGHT; y++ )
-		{
-			out = lightmap + ((LIGHTMAP_HEIGHT - y) * LIGHTMAP_WIDTH * 3);
-			for( x = 0; x < LIGHTMAP_WIDTH; x++, in += 4, out += 3 )
-				VectorCopy( in, out );
-		}
-		
-		/* free the image */
-		free( pixels );
-	}
-	
-	/* write the bsp */
-	Sys_Printf( "writing %s\n", source );
-	WriteBSPFile( source );
-	
-	/* return to sender */
-	return 0;
-}
-
-
-
-/* -------------------------------------------------------------------------------
-
-this section deals with projecting a lightmap onto a raw drawsurface
-
-------------------------------------------------------------------------------- */
-
-/*
-CompareLightSurface()
-compare function for qsort()
-*/
-
-static int CompareLightSurface( const void *a, const void *b )
-{
-	shaderInfo_t	*asi, *bsi;
-	
-	
-	/* get shaders */
-	asi = surfaceInfos[ *((int*) a) ].si;
-	bsi = surfaceInfos[ *((int*) b) ].si;
-	
-	/* dummy check */
-	if( asi == NULL )
-		return -1;
-	if( bsi == NULL )
-		return 1;
-	
-	/* compare shader names */
-	return strcmp( asi->shader, bsi->shader );
-}
-
-
-
-/*
-FinishRawLightmap()
-allocates a raw lightmap's necessary buffers
-*/
-
-void FinishRawLightmap( rawLightmap_t *lm )
-{
-	int					i, j, c, size, *sc;
-	float				is;
-	surfaceInfo_t		*info;
-	
-	
-	/* sort light surfaces by shader name */
-	qsort( &lightSurfaces[ lm->firstLightSurface ], lm->numLightSurfaces, sizeof( int ), CompareLightSurface );
-	
-	/* count clusters */
-	lm->numLightClusters = 0;
-	for( i = 0; i < lm->numLightSurfaces; i++ )
-	{
-		/* get surface info */
-		info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + i ] ];
-		
-		/* add surface clusters */
-		lm->numLightClusters += info->numSurfaceClusters;
-	}
-	
-	/* allocate buffer for clusters and copy */
-	lm->lightClusters = safe_malloc( lm->numLightClusters * sizeof( *lm->lightClusters ) );
-	c = 0;
-	for( i = 0; i < lm->numLightSurfaces; i++ )
-	{
-		/* get surface info */
-		info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + i ] ];
-		
-		/* add surface clusters */
-		for( j = 0; j < info->numSurfaceClusters; j++ )
-			lm->lightClusters[ c++ ] = surfaceClusters[ info->firstSurfaceCluster + j ];
-	}
-	
-	/* set styles */
-	lm->styles[ 0 ] = LS_NORMAL;
-	for( i = 1; i < MAX_LIGHTMAPS; i++ )
-		lm->styles[ i ] = LS_NONE;
-	
-	/* set supersampling size */
-	lm->sw = lm->w * superSample;
-	lm->sh = lm->h * superSample;
-	
-	/* add to super luxel count */
-	numRawSuperLuxels += (lm->sw * lm->sh);
-	
-	/* manipulate origin/vecs for supersampling */
-	if( superSample > 1 && lm->vecs != NULL )
-	{
-		/* calc inverse supersample */
-		is = 1.0f / superSample;
-		
-		/* scale the vectors and shift the origin */
-		#if 1
-			/* new code that works for arbitrary supersampling values */
-			VectorMA( lm->origin, -0.5, lm->vecs[ 0 ], lm->origin );
-			VectorMA( lm->origin, -0.5, lm->vecs[ 1 ], lm->origin );
-			VectorScale( lm->vecs[ 0 ], is, lm->vecs[ 0 ] );
-			VectorScale( lm->vecs[ 1 ], is, lm->vecs[ 1 ] );
-			VectorMA( lm->origin, is, lm->vecs[ 0 ], lm->origin );
-			VectorMA( lm->origin, is, lm->vecs[ 1 ], lm->origin );
-		#else
-			/* old code that only worked with a value of 2 */
-			VectorScale( lm->vecs[ 0 ], is, lm->vecs[ 0 ] );
-			VectorScale( lm->vecs[ 1 ], is, lm->vecs[ 1 ] );
-			VectorMA( lm->origin, -is, lm->vecs[ 0 ], lm->origin );
-			VectorMA( lm->origin, -is, lm->vecs[ 1 ], lm->origin );
-		#endif
-	}
-	
-	/* allocate bsp lightmap storage */
-	size = lm->w * lm->h * BSP_LUXEL_SIZE * sizeof( float );
-	if( lm->bspLuxels[ 0 ] == NULL )
-		lm->bspLuxels[ 0 ] = safe_malloc( size );
-	memset( lm->bspLuxels[ 0 ], 0, size );
-	
-	/* allocate radiosity lightmap storage */
-	if( bounce )
-	{
-		size = lm->w * lm->h * RAD_LUXEL_SIZE * sizeof( float );
-		if( lm->radLuxels[ 0 ] == NULL )
-			lm->radLuxels[ 0 ] = safe_malloc( size );
-		memset( lm->radLuxels[ 0 ], 0, size );
-	}
-	
-	/* allocate sampling lightmap storage */
-	size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
-	if( lm->superLuxels[ 0 ] == NULL )
-		lm->superLuxels[ 0 ] = safe_malloc( size );
-	memset( lm->superLuxels[ 0 ], 0, size );
-	
-	/* allocate origin map storage */
-	size = lm->sw * lm->sh * SUPER_ORIGIN_SIZE * sizeof( float );
-	if( lm->superOrigins == NULL )
-		lm->superOrigins = safe_malloc( size );
-	memset( lm->superOrigins, 0, size );
-	
-	/* allocate normal map storage */
-	size = lm->sw * lm->sh * SUPER_NORMAL_SIZE * sizeof( float );
-	if( lm->superNormals == NULL )
-		lm->superNormals = safe_malloc( size );
-	memset( lm->superNormals, 0, size );
-	
-	/* allocate cluster map storage */
-	size = lm->sw * lm->sh * sizeof( int );
-	if( lm->superClusters == NULL )
-		lm->superClusters = safe_malloc( size );
-	size = lm->sw * lm->sh;
-	sc = lm->superClusters;
-	for( i = 0; i < size; i++ )
-		(*sc++) = CLUSTER_UNMAPPED;
-	
-	/* deluxemap allocation */
-	if( deluxemap )
-	{
-		/* allocate sampling deluxel storage */
-		size = lm->sw * lm->sh * SUPER_DELUXEL_SIZE * sizeof( float );
-		if( lm->superDeluxels == NULL )
-			lm->superDeluxels = safe_malloc( size );
-		memset( lm->superDeluxels, 0, size );
-		
-		/* allocate bsp deluxel storage */
-		size = lm->w * lm->h * BSP_DELUXEL_SIZE * sizeof( float );
-		if( lm->bspDeluxels == NULL )
-			lm->bspDeluxels = safe_malloc( size );
-		memset( lm->bspDeluxels, 0, size );
-	}
-	
-	/* add to count */
-	numLuxels += (lm->sw * lm->sh);
-}
-
-
-
-/*
-AddPatchToRawLightmap()
-projects a lightmap for a patch surface
-since lightmap calculation for surfaces is now handled in a general way (light_ydnar.c),
-it is no longer necessary for patch verts to fall exactly on a lightmap sample
-based on AllocateLightmapForPatch()
-*/
-
-qboolean AddPatchToRawLightmap( int num, rawLightmap_t *lm )
-{
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	int					x, y;
-	bspDrawVert_t		*verts, *a, *b;
-	vec3_t				delta;
-	mesh_t				src, *subdivided, *mesh;
-	float				sBasis, tBasis, s, t;
-	float				length, widthTable[ MAX_EXPANDED_AXIS ], heightTable[ MAX_EXPANDED_AXIS ];
-	
-	
-	/* patches finish a raw lightmap */
-	lm->finished = qtrue;
-	
-	/* get surface and info  */
-	ds = &bspDrawSurfaces[ num ];
-	info = &surfaceInfos[ num ];
-	
-	/* make a temporary mesh from the drawsurf */ 
-	src.width = ds->patchWidth;
-	src.height = ds->patchHeight;
-	src.verts = &yDrawVerts[ ds->firstVert ];
-	//%	subdivided = SubdivideMesh( src, 8, 512 );
-	subdivided = SubdivideMesh2( src, info->patchIterations );
-	
-	/* fit it to the curve and remove colinear verts on rows/columns */
-	PutMeshOnCurve( *subdivided );
-	mesh = RemoveLinearMeshColumnsRows( subdivided );
-	FreeMesh( subdivided );
-	
-	/* find the longest distance on each row/column */
-	verts = mesh->verts;
-	memset( widthTable, 0, sizeof( widthTable ) );
-	memset( heightTable, 0, sizeof( heightTable ) );
-	for( y = 0; y < mesh->height; y++ )
-	{
-		for( x = 0; x < mesh->width; x++ )
-		{
-			/* get width */
-			if( x + 1 < mesh->width )
-			{
-				a = &verts[ (y * mesh->width) + x ];
-				b = &verts[ (y * mesh->width) + x + 1 ];
-				VectorSubtract( a->xyz, b->xyz, delta );
-				length = VectorLength( delta );
-				if( length > widthTable[ x ] )
-					widthTable[ x ] = length;
-			}
-			
-			/* get height */
-			if( y + 1 < mesh->height )
-			{
-				a = &verts[ (y * mesh->width) + x ];
-				b = &verts[ ((y + 1) * mesh->width) + x ];
-				VectorSubtract( a->xyz, b->xyz, delta );
-				length = VectorLength( delta );
-				if( length > heightTable[ y ] )
-					heightTable[ y ] = length;
-			}
-		}
-	}
-	
-	/* determine lightmap width */
-	length = 0;
-	for( x = 0; x < (mesh->width - 1); x++ )
-		length += widthTable[ x ];
-	lm->w = ceil( length / lm->sampleSize ) + 1;
-	if( lm->w < ds->patchWidth )
-		lm->w = ds->patchWidth;
-	if( lm->w > lm->customWidth )
-		lm->w = lm->customWidth;
-	sBasis = (float) (lm->w - 1) / (float) (ds->patchWidth - 1);
-	
-	/* determine lightmap height */
-	length = 0;
-	for( y = 0; y < (mesh->height - 1); y++ )
-		length += heightTable[ y ];
-	lm->h = ceil( length / lm->sampleSize ) + 1;
-	if( lm->h < ds->patchHeight )
-		lm->h = ds->patchHeight;
-	if( lm->h > lm->customHeight )
-		lm->h = lm->customHeight;
-	tBasis = (float) (lm->h - 1) / (float) (ds->patchHeight - 1);
-	
-	/* free the temporary mesh */
-	FreeMesh( mesh );
-	
-	/* set the lightmap texture coordinates in yDrawVerts */
-	lm->wrap[ 0 ] = qtrue;
-	lm->wrap[ 1 ] = qtrue;
-	verts = &yDrawVerts[ ds->firstVert ];
-	for( y = 0; y < ds->patchHeight; y++ )
-	{
-		t = (tBasis * y) + 0.5f;
-		for( x = 0; x < ds->patchWidth; x++ )
-		{
-			s = (sBasis * x) + 0.5f;
-			verts[ (y * ds->patchWidth) + x ].lightmap[ 0 ][ 0 ] = s * superSample;
-			verts[ (y * ds->patchWidth) + x ].lightmap[ 0 ][ 1 ] = t * superSample;
-			
-			if( y == 0 && !VectorCompare( verts[ x ].xyz, verts[ ((ds->patchHeight - 1) * ds->patchWidth) + x ].xyz ) )
-				lm->wrap[ 1 ] = qfalse;
-		}
-		
-		if( !VectorCompare( verts[ (y * ds->patchWidth) ].xyz, verts[ (y * ds->patchWidth) + (ds->patchWidth - 1) ].xyz ) )
-			lm->wrap[ 0 ] = qfalse;
-	}
-	
-	/* debug code: */
-	//%	Sys_Printf( "wrap S: %d wrap T: %d\n", lm->wrap[ 0 ], lm->wrap[ 1 ] );
-	//% if( lm->w > (ds->lightmapWidth & 0xFF) || lm->h > (ds->lightmapHeight & 0xFF) )
-	//%		Sys_Printf( "Patch lightmap: (%3d %3d) > (%3d, %3d)\n", lm->w, lm->h, ds->lightmapWidth & 0xFF, ds->lightmapHeight & 0xFF );
-	//% ds->lightmapWidth = lm->w | (ds->lightmapWidth & 0xFFFF0000);
-	//% ds->lightmapHeight = lm->h | (ds->lightmapHeight & 0xFFFF0000);
-	
-	/* add to counts */
-	numPatchesLightmapped++;
-	
-	/* return */
-	return qtrue;
-}
-
-
-
-/*
-AddSurfaceToRawLightmap()
-projects a lightmap for a surface
-based on AllocateLightmapForSurface()
-*/
-
-qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm )
-{
-	bspDrawSurface_t	*ds, *ds2;
-	surfaceInfo_t		*info, *info2;
-	int					num2, n, i, axisNum;
-	float				s, t, d, len, sampleSize;
-	vec3_t				mins, maxs, origin, faxis, size, exactSize, delta, normalized, vecs[ 2 ];
-	vec4_t				plane;
-	bspDrawVert_t		*verts;
-	
-	
-	/* get surface and info  */
-	ds = &bspDrawSurfaces[ num ];
-	info = &surfaceInfos[ num ];
-	
-	/* add the surface to the raw lightmap */
-	lightSurfaces[ numLightSurfaces++ ] = num;
-	lm->numLightSurfaces++;
-	
-	/* does this raw lightmap already have any surfaces? */
-	if( lm->numLightSurfaces > 1 )
-	{
-		/* surface and raw lightmap must have the same lightmap projection axis */
-		if( VectorCompare( info->axis, lm->axis ) == qfalse )
-			return qfalse;
-		
-		/* match identical attributes */
-		if( info->sampleSize != lm->sampleSize ||
-			info->entityNum != lm->entityNum ||
-			info->recvShadows != lm->recvShadows ||
-			info->si->lmCustomWidth != lm->customWidth ||
-			info->si->lmCustomHeight != lm->customHeight ||
-			info->si->lmGamma != lm->gamma ||
-			info->si->lmFilterRadius != lm->filterRadius ||
-			info->si->splotchFix != lm->splotchFix )
-			return qfalse;
-		
-		/* surface bounds must intersect with raw lightmap bounds */
-		for( i = 0; i < 3; i++ )
-		{
-			if( info->mins[ i ] > lm->maxs[ i ] )
-				return qfalse;
-			if( info->maxs[ i ] < lm->mins[ i ] )
-				return qfalse;
-		}
-		
-		/* plane check (fixme: allow merging of nonplanars) */
-		if( info->si->lmMergable == qfalse )
-		{
-			if( info->plane == NULL || lm->plane == NULL )
-				return qfalse;
-			
-			/* compare planes */
-			for( i = 0; i < 4; i++ )
-				if( fabs( info->plane[ i ] - lm->plane[ i ] ) > EQUAL_EPSILON )
-					return qfalse;
-		}
-		
-		/* debug code hacking */
-		//%	if( lm->numLightSurfaces > 1 )
-		//%		return qfalse;
-	}
-	
-	/* set plane */
-	if( info->plane == NULL )
-		lm->plane = NULL;
-	
-	/* add surface to lightmap bounds */
-	AddPointToBounds( info->mins, lm->mins, lm->maxs );
-	AddPointToBounds( info->maxs, lm->mins, lm->maxs );
-	
-	/* check to see if this is a non-planar patch */
-	if( ds->surfaceType == MST_PATCH &&
-		lm->axis[ 0 ] == 0.0f && lm->axis[ 1 ] == 0.0f && lm->axis[ 2 ] == 0.0f )
-		return AddPatchToRawLightmap( num, lm );
-	
-	/* start with initially requested sample size */
-	sampleSize = lm->sampleSize;
-	
-	/* round to the lightmap resolution */
-	for( i = 0; i < 3; i++ )
-	{
-		exactSize[ i ] = lm->maxs[ i ] - lm->mins[ i ];
- 		mins[ i ] = sampleSize * floor( lm->mins[ i ] / sampleSize );
- 		maxs[ i ] = sampleSize * ceil( lm->maxs[ i ] / sampleSize );
- 		size[ i ] = (maxs[ i ] - mins[ i ]) / sampleSize + 1.0f;
-		
-		/* hack (god this sucks) */
-		if( size[ i ] > lm->customWidth || size[ i ] > lm->customHeight )
-		{
-			i = -1;
-			sampleSize += 1.0f;
-		}
-	}
-	
-	/* set actual sample size */
-	lm->actualSampleSize = sampleSize;
-	
-	/* fixme: copy rounded mins/maxes to lightmap record? */
-	if( lm->plane == NULL )
-	{
-		VectorCopy( mins, lm->mins );
-		VectorCopy( maxs, lm->maxs );
-		VectorCopy( mins, origin );
-	}
-	
-	/* set lightmap origin */
-	VectorCopy( lm->mins, origin );
-	
-	/* make absolute axis */
-	faxis[ 0 ] = fabs( lm->axis[ 0 ] );
-	faxis[ 1 ] = fabs( lm->axis[ 1 ] );
-	faxis[ 2 ] = fabs( lm->axis[ 2 ] );
-	
-	/* clear out lightmap vectors */
-	memset( vecs, 0, sizeof( vecs ) );
-	
-	/* classify the plane (x y or z major) (ydnar: biased to z axis projection) */
-	if( faxis[ 2 ] >= faxis[ 0 ] && faxis[ 2 ] >= faxis[ 1 ] )
-	{
-		axisNum = 2;
-		lm->w = size[ 0 ];
-		lm->h = size[ 1 ];
-		vecs[ 0 ][ 0 ] = 1.0f / sampleSize;
-		vecs[ 1 ][ 1 ] = 1.0f / sampleSize;
-	}
-	else if( faxis[ 0 ] >= faxis[ 1 ] && faxis[ 0 ] >= faxis[ 2 ] )
-	{
-		axisNum = 0;
-		lm->w = size[ 1 ];
-		lm->h = size[ 2 ];
-		vecs[ 0 ][ 1 ] = 1.0f / sampleSize;
-		vecs[ 1 ][ 2 ] = 1.0f / sampleSize;
-	}
-	else
-	{
-		axisNum = 1;
-		lm->w = size[ 0 ];
-		lm->h = size[ 2 ];
-		vecs[ 0 ][ 0 ] = 1.0f / sampleSize;
-		vecs[ 1 ][ 2 ] = 1.0f / sampleSize;
-	}
-	
-	/* check for bogus axis */
-	if( faxis[ axisNum ] == 0.0f )
-	{
-		Sys_Printf( "WARNING: ProjectSurfaceLightmap: Chose a 0 valued axis\n" );
-		lm->w = lm->h = 0;
-		return qfalse;
-	}
-	
-	/* store the axis number in the lightmap */
-	lm->axisNum = axisNum;
-	
-	/* walk the list of surfaces on this raw lightmap */
-	for( n = 0; n < lm->numLightSurfaces; n++ )
-	{
-		/* get surface */
-		num2 = lightSurfaces[ lm->firstLightSurface + n ];
-		ds2 = &bspDrawSurfaces[ num2 ];
-		info2 = &surfaceInfos[ num2 ];
-		verts = &yDrawVerts[ ds2->firstVert ];
-		
-		/* set the lightmap texture coordinates in yDrawVerts in [0, superSample * lm->customWidth] space */
-		for( i = 0; i < ds2->numVerts; i++ )
-		{
-			VectorSubtract( verts[ i ].xyz, origin, delta );
-			s = DotProduct( delta, vecs[ 0 ] ) + 0.5f;
-			t = DotProduct( delta, vecs[ 1 ] ) + 0.5f;
-			verts[ i ].lightmap[ 0 ][ 0 ] = s * superSample;
-			verts[ i ].lightmap[ 0 ][ 1 ] = t * superSample;
-			
-			if( s > (float) lm->w || t > (float) lm->h )
-			{
-				Sys_FPrintf( SYS_VRB, "WARNING: Lightmap texture coords out of range: S %1.4f > %3d || T %1.4f > %3d\n",
-					s, lm->w, t, lm->h );
-			}
-		}
-	}
-	
-	/* get first drawsurface */
-	num2 = lightSurfaces[ lm->firstLightSurface ];
-	ds2 = &bspDrawSurfaces[ num2 ];
-	info2 = &surfaceInfos[ num2 ];
-	verts = &yDrawVerts[ ds2->firstVert ];
-	
-	/* calculate lightmap origin */
-	if( VectorLength( ds2->lightmapVecs[ 2 ] ) )
-		VectorCopy( ds2->lightmapVecs[ 2 ], plane );
-	else
-		VectorCopy( lm->axis, plane );
-	plane[ 3 ] = DotProduct( verts[ 0 ].xyz, plane );
-	
-	VectorCopy( origin, lm->origin );
-	d = DotProduct( lm->origin, plane ) - plane[ 3 ];
-	d /= plane[ axisNum ];
-	lm->origin[ axisNum ] -= d;
-	
-	/* legacy support */
-	VectorCopy( lm->origin, ds->lightmapOrigin );
-	
-	/* for planar surfaces, create lightmap vectors for st->xyz conversion */
-	if( VectorLength( ds->lightmapVecs[ 2 ] ) || 1 )	/* ydnar: can't remember what exactly i was thinking here... */
-	{
-		/* allocate space for the vectors */
-		lm->vecs = safe_malloc( 3 * sizeof( vec3_t ) );
-		memset( lm->vecs, 0, 3 * sizeof( vec3_t ) );
-		VectorCopy( ds->lightmapVecs[ 2 ], lm->vecs[ 2 ] );
-		
-		/* project stepped lightmap blocks and subtract to get planevecs */
-		for( i = 0; i < 2; i++ )
-		{
-			len = VectorNormalize( vecs[ i ], normalized );
-			VectorScale( normalized, (1.0 / len), lm->vecs[ i ] );
-			d = DotProduct( lm->vecs[ i ], plane );
-			d /= plane[ axisNum ];
-			lm->vecs[ i ][ axisNum ] -= d;
-		}
-	}
-	else
-	{
-		/* lightmap vectors are useless on a non-planar surface */
-		lm->vecs = NULL;
-	}
-	
-	/* add to counts */
-	if( ds->surfaceType == MST_PATCH )
-	{
-		numPatchesLightmapped++;
-		if( lm->plane != NULL )
-			numPlanarPatchesLightmapped++;
-	}
-	else
-	{
-		if( lm->plane != NULL )
-			numPlanarsLightmapped++;
-		else
-			numNonPlanarsLightmapped++;
-	}
-	
-	/* return */
-	return qtrue;
-}
-
-
-
-/*
-CompareSurfaceInfo()
-compare function for qsort()
-*/
-
-static int CompareSurfaceInfo( const void *a, const void *b )
-{
-	surfaceInfo_t	*aInfo, *bInfo;
-	int				i;
-	
-
-	/* get surface info */
-	aInfo = &surfaceInfos[ *((int*) a) ];
-	bInfo = &surfaceInfos[ *((int*) b) ];
-	
-	/* model first */
-	if( aInfo->model < bInfo->model )
-		return 1;
-	else if( aInfo->model > bInfo->model )
-		return -1;
-	
-	/* then lightmap status */
-	if( aInfo->hasLightmap < bInfo->hasLightmap )
-		return 1;
-	else if( aInfo->hasLightmap > bInfo->hasLightmap )
-		return -1;
-	
-	/* then lightmap sample size */
-	if( aInfo->sampleSize < bInfo->sampleSize )
-		return 1;
-	else if( aInfo->sampleSize > bInfo->sampleSize )
-		return -1;
-	
-	/* then lightmap axis */
-	for( i = 0; i < 3; i++ )
-	{
-		if( aInfo->axis[ i ] < bInfo->axis[ i ] )
-			return 1;
-		else if( aInfo->axis[ i ] > bInfo->axis[ i ] )
-			return -1;
-	}
-	
-	/* then plane */
-	if( aInfo->plane == NULL && bInfo->plane != NULL )
-		return 1;
-	else if( aInfo->plane != NULL && bInfo->plane == NULL )
-		return -1;
-	else if( aInfo->plane != NULL && bInfo->plane != NULL )
-	{
-		for( i = 0; i < 4; i++ )
-		{
-			if( aInfo->plane[ i ] < bInfo->plane[ i ] )
-				return 1;
-			else if( aInfo->plane[ i ] > bInfo->plane[ i ] )
-				return -1;
-		}
-	}
-	
-	/* then position in world */
-	for( i = 0; i < 3; i++ )
-	{
-		if( aInfo->mins[ i ] < bInfo->mins[ i ] )
-			return 1;
-		else if( aInfo->mins[ i ] > bInfo->mins[ i ] )
-			return -1;
-	}
-	
-	/* these are functionally identical (this should almost never happen) */
-	return 0;
-}
-
-
-
-/*
-SetupSurfaceLightmaps()
-allocates lightmaps for every surface in the bsp that needs one
-this depends on yDrawVerts being allocated
-*/
-
-void SetupSurfaceLightmaps( void )
-{
-	int					i, j, k, s,num, num2;
-	bspModel_t			*model;
-	bspLeaf_t			*leaf;
-	bspDrawSurface_t	*ds, *ds2;
-	surfaceInfo_t		*info, *info2;
-	rawLightmap_t		*lm;
-	qboolean			added;
-	vec3_t				mapSize, entityOrigin;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- SetupSurfaceLightmaps ---\n");
-	
-	/* determine supersample amount */
-	if( superSample < 1 )
-		superSample = 1;
-	else if( superSample > 8 )
-	{
-		Sys_Printf( "WARNING: Insane supersampling amount (%d) detected.\n", superSample );
-		superSample = 8;
-	}
-	
-	/* clear map bounds */
-	ClearBounds( mapMins, mapMaxs );
-	
-	/* allocate a list of surface clusters */
-	numSurfaceClusters = 0;
-	maxSurfaceClusters = numBSPLeafSurfaces;
-	surfaceClusters = safe_malloc( maxSurfaceClusters * sizeof( *surfaceClusters ) );
-	memset( surfaceClusters, 0, maxSurfaceClusters * sizeof( *surfaceClusters ) );
-	
-	/* allocate a list for per-surface info */
-	surfaceInfos = safe_malloc( numBSPDrawSurfaces * sizeof( *surfaceInfos ) );
-	memset( surfaceInfos, 0, numBSPDrawSurfaces * sizeof( *surfaceInfos ) );
-	for( i = 0; i < numBSPDrawSurfaces; i++ )
-		surfaceInfos[ i ].childSurfaceNum = -1;
-	
-	/* allocate a list of surface indexes to be sorted */
-	sortSurfaces = safe_malloc( numBSPDrawSurfaces * sizeof( int ) );
-	memset( sortSurfaces, 0, numBSPDrawSurfaces * sizeof( int ) );
-	
-	/* walk each model in the bsp */
-	for( i = 0; i < numBSPModels; i++ )
-	{
-		/* get model */
-		model = &bspModels[ i ];
-		
-		/* walk the list of surfaces in this model and fill out the info structs */
-		for( j = 0; j < model->numBSPSurfaces; j++ )
-		{
-			/* make surface index */
-			num = model->firstBSPSurface + j;
-			
-			/* copy index to sort list */
-			sortSurfaces[ num ] = num;
-			
-			/* get surface and info */
-			ds = &bspDrawSurfaces[ num ];
-			info = &surfaceInfos[ num ];
-			
-			/* set entity origin */
-			if( ds->numVerts > 0 )
-				VectorSubtract( yDrawVerts[ ds->firstVert ].xyz, bspDrawVerts[ ds->firstVert ].xyz, entityOrigin );
-			else
-				VectorClear( entityOrigin );
-			
-			/* basic setup */
-			info->model = model;
-			info->lm = NULL;
-			info->plane = NULL;
-			info->firstSurfaceCluster = numSurfaceClusters;
-			
-			/* get extra data */
-			info->si = GetSurfaceExtraShaderInfo( num );
-			if( info->si == NULL )
-				info->si = ShaderInfoForShader( bspShaders[ ds->shaderNum ].shader );
-			info->parentSurfaceNum = GetSurfaceExtraParentSurfaceNum( num );
-			info->entityNum = GetSurfaceExtraEntityNum( num );
-			info->castShadows = GetSurfaceExtraCastShadows( num );
-			info->recvShadows = GetSurfaceExtraRecvShadows( num );
-			info->sampleSize = GetSurfaceExtraSampleSize( num );
-			info->longestCurve = GetSurfaceExtraLongestCurve( num );
-			info->patchIterations = IterationsForCurve( info->longestCurve, patchSubdivisions );
-			GetSurfaceExtraLightmapAxis( num, info->axis );
-			
-			/* mark parent */
-			if( info->parentSurfaceNum >= 0 )
-				surfaceInfos[ info->parentSurfaceNum ].childSurfaceNum = j;
-			
-			/* determine surface bounds */
-			ClearBounds( info->mins, info->maxs );
-			for( k = 0; k < ds->numVerts; k++ )
-			{
-				AddPointToBounds( yDrawVerts[ ds->firstVert + k ].xyz, mapMins, mapMaxs );
-				AddPointToBounds( yDrawVerts[ ds->firstVert + k ].xyz, info->mins, info->maxs );
-			}
-			
-			/* find all the bsp clusters the surface falls into */
-			for( k = 0; k < numBSPLeafs; k++ )
-			{
-				/* get leaf */
-				leaf = &bspLeafs[ k ];
-				
-				/* test bbox */
-				if( leaf->mins[ 0 ] > info->maxs[ 0 ] || leaf->maxs[ 0 ] < info->mins[ 0 ] ||
-					leaf->mins[ 1 ] > info->maxs[ 1 ] || leaf->maxs[ 1 ] < info->mins[ 1 ] ||
-					leaf->mins[ 2 ] > info->maxs[ 2 ] || leaf->maxs[ 2 ] < info->mins[ 2 ] )
-					continue;
-				
-				/* test leaf surfaces */
-				for( s = 0; s < leaf->numBSPLeafSurfaces; s++ )
-				{
-					if( bspLeafSurfaces[ leaf->firstBSPLeafSurface + s ] == num )
-					{
-						if( numSurfaceClusters >= maxSurfaceClusters )
-							Error( "maxSurfaceClusters exceeded" );
-						surfaceClusters[ numSurfaceClusters ] = leaf->cluster;
-						numSurfaceClusters++;
-						info->numSurfaceClusters++;
-					}
-				}
-			}
-			
-			/* determine if surface is planar */
-			if( VectorLength( ds->lightmapVecs[ 2 ] ) > 0.0f )
-			{
-				/* make a plane */
-				info->plane = safe_malloc( 4 * sizeof( float ) );
-				VectorCopy( ds->lightmapVecs[ 2 ], info->plane );
-				info->plane[ 3 ] = DotProduct( yDrawVerts[ ds->firstVert ].xyz, info->plane );
-			}
-			
-			/* determine if surface requires a lightmap */
-			if( ds->surfaceType == MST_TRIANGLE_SOUP ||
-				ds->surfaceType == MST_FOLIAGE ||
-				(info->si->compileFlags & C_VERTEXLIT) )
-				numSurfsVertexLit++;
-			else
-			{
-				numSurfsLightmapped++;
-				info->hasLightmap = qtrue;
-			}
-		}
-	}
-	
-	/* find longest map distance */
-	VectorSubtract( mapMaxs, mapMins, mapSize );
-	maxMapDistance = VectorLength( mapSize );
-	
-	/* sort the surfaces info list */
-	qsort( sortSurfaces, numBSPDrawSurfaces, sizeof( int ), CompareSurfaceInfo );
-	
-	/* allocate a list of surfaces that would go into raw lightmaps */
-	numLightSurfaces = 0;
-	lightSurfaces = safe_malloc( numSurfsLightmapped * sizeof( int ) );
-	memset( lightSurfaces, 0, numSurfsLightmapped * sizeof( int ) );
-	
-	/* allocate a list of raw lightmaps */
-	numRawSuperLuxels = 0;
-	numRawLightmaps = 0;
-	rawLightmaps = safe_malloc( numSurfsLightmapped * sizeof( *rawLightmaps ) );
-	memset( rawLightmaps, 0, numSurfsLightmapped * sizeof( *rawLightmaps ) );
-	
-	/* walk the list of sorted surfaces */
-	for( i = 0; i < numBSPDrawSurfaces; i++ )
-	{
-		/* get info and attempt early out */
-		num = sortSurfaces[ i ];
-		ds = &bspDrawSurfaces[ num ];
-		info = &surfaceInfos[ num ];
-		if( info->hasLightmap == qfalse || info->lm != NULL || info->parentSurfaceNum >= 0 )
-			continue;
-		
-		/* allocate a new raw lightmap */
-		lm = &rawLightmaps[ numRawLightmaps ];
-		numRawLightmaps++;
-		
-		/* set it up */
-		lm->splotchFix = info->si->splotchFix;
-		lm->firstLightSurface = numLightSurfaces;
-		lm->numLightSurfaces = 0;
-		lm->sampleSize = info->sampleSize;
-		lm->actualSampleSize = info->sampleSize;
-		lm->entityNum = info->entityNum;
-		lm->recvShadows = info->recvShadows;
-		lm->gamma = info->si->lmGamma;
-		lm->filterRadius = info->si->lmFilterRadius;
-		VectorCopy( info->axis, lm->axis );
-		lm->plane = info->plane;	
-		VectorCopy( info->mins, lm->mins );
-		VectorCopy( info->maxs, lm->maxs );
-		
-		lm->customWidth = info->si->lmCustomWidth;
-		lm->customHeight = info->si->lmCustomHeight;
-		
-		/* add the surface to the raw lightmap */
-		AddSurfaceToRawLightmap( num, lm );
-		info->lm = lm;
-		
-		/* do an exhaustive merge */
-		added = qtrue;
-		while( added )
-		{
-			/* walk the list of surfaces again */
-			added = qfalse;
-			for( j = i + 1; j < numBSPDrawSurfaces && lm->finished == qfalse; j++ )
-			{
-				/* get info and attempt early out */
-				num2 = sortSurfaces[ j ];
-				ds2 = &bspDrawSurfaces[ num2 ];
-				info2 = &surfaceInfos[ num2 ];
-				if( info2->hasLightmap == qfalse || info2->lm != NULL )
-					continue;
-				
-				/* add the surface to the raw lightmap */
-				if( AddSurfaceToRawLightmap( num2, lm ) )
-				{
-					info2->lm = lm;
-					added = qtrue;
-				}
-				else
-				{
-					/* back up one */
-					lm->numLightSurfaces--;
-					numLightSurfaces--;
-				}
-			}
-		}
-		
-		/* finish the lightmap and allocate the various buffers */
-		FinishRawLightmap( lm );
-	}
-	
-	/* allocate vertex luxel storage */
-	for( k = 0; k < MAX_LIGHTMAPS; k++ )
-	{
-		vertexLuxels[ k ] = safe_malloc( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) ); 
-		memset( vertexLuxels[ k ], 0, numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
-		radVertexLuxels[ k ] = safe_malloc( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
-		memset( radVertexLuxels[ k ], 0, numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
-	}
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d surfaces\n", numBSPDrawSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d raw lightmaps\n", numRawLightmaps );
-	Sys_FPrintf( SYS_VRB, "%9d surfaces vertex lit\n", numSurfsVertexLit );
-	Sys_FPrintf( SYS_VRB, "%9d surfaces lightmapped\n", numSurfsLightmapped );
-	Sys_FPrintf( SYS_VRB, "%9d planar surfaces lightmapped\n", numPlanarsLightmapped );
-	Sys_FPrintf( SYS_VRB, "%9d non-planar surfaces lightmapped\n", numNonPlanarsLightmapped );
-	Sys_FPrintf( SYS_VRB, "%9d patches lightmapped\n", numPatchesLightmapped );
-	Sys_FPrintf( SYS_VRB, "%9d planar patches lightmapped\n", numPlanarPatchesLightmapped );
-}
-
-
-
-/*
-StitchSurfaceLightmaps()
-stitches lightmap edges
-2002-11-20 update: use this func only for stitching nonplanar patch lightmap seams
-*/
-
-#define MAX_STITCH_CANDIDATES	32
-#define MAX_STITCH_LUXELS		64
-
-void StitchSurfaceLightmaps( void )
-{
-	int				i, j, x, y, x2, y2, *cluster, *cluster2,
-					numStitched, numCandidates, numLuxels, f, fOld, start;
-	rawLightmap_t	*lm, *a, *b, *c[ MAX_STITCH_CANDIDATES ];
-	float			*luxel, *luxel2, *origin, *origin2, *normal, *normal2, 
-					sampleSize, average[ 3 ], totalColor, ootc, *luxels[ MAX_STITCH_LUXELS ];
-	
-	
-	/* disabled for now */
-	return;
-	
-	/* note it */
-	Sys_Printf( "--- StitchSurfaceLightmaps ---\n");
-
-	/* init pacifier */
-	fOld = -1;
-	start = I_FloatTime();
-	
-	/* walk the list of raw lightmaps */
-	numStitched = 0;
-	for( i = 0; i < numRawLightmaps; i++ )
-	{
-		/* print pacifier */
-		f = 10 * i / numRawLightmaps;
-		if( f != fOld )
-		{
-			fOld = f;
-			Sys_Printf( "%i...", f );
-		}
-		
-		/* get lightmap a */
-		a = &rawLightmaps[ i ];
-		
-		/* walk rest of lightmaps */
-		numCandidates = 0;
-		for( j = i + 1; j < numRawLightmaps && numCandidates < MAX_STITCH_CANDIDATES; j++ )
-		{
-			/* get lightmap b */
-			b = &rawLightmaps[ j ];
-			
-			/* test bounding box */
-			if( a->mins[ 0 ] > b->maxs[ 0 ] || a->maxs[ 0 ] < b->mins[ 0 ] ||
-				a->mins[ 1 ] > b->maxs[ 1 ] || a->maxs[ 1 ] < b->mins[ 1 ] ||
-				a->mins[ 2 ] > b->maxs[ 2 ] || a->maxs[ 2 ] < b->mins[ 2 ] )
-				continue;
-			
-			/* add candidate */
-			c[ numCandidates++ ] = b;
-		}
-		
-		/* walk luxels */
-		for( y = 0; y < a->sh; y++ )
-		{
-			for( x = 0; x < a->sw; x++ )
-			{
-				/* ignore unmapped/unlit luxels */
-				lm = a;
-				cluster = SUPER_CLUSTER( x, y );
-				if( *cluster == CLUSTER_UNMAPPED )
-					continue;
-				luxel = SUPER_LUXEL( 0, x, y );
-				if( luxel[ 3 ] <= 0.0f )
-					continue;
-				
-				/* get particulars */
-				origin = SUPER_ORIGIN( x, y );
-				normal = SUPER_NORMAL( x, y );
-				
-				/* walk candidate list */
-				for( j = 0; j < numCandidates; j++ )
-				{
-					/* get candidate */
-					b = c[ j ];
-					lm = b;
-					
-					/* set samplesize to the smaller of the pair */
-					sampleSize = 0.5f * (a->actualSampleSize < b->actualSampleSize ? a->actualSampleSize : b->actualSampleSize);
-					
-					/* test bounding box */
-					if( origin[ 0 ] < (b->mins[ 0 ] - sampleSize) || (origin[ 0 ] > b->maxs[ 0 ] + sampleSize) ||
-						origin[ 1 ] < (b->mins[ 1 ] - sampleSize) || (origin[ 1 ] > b->maxs[ 1 ] + sampleSize) ||
-						origin[ 2 ] < (b->mins[ 2 ] - sampleSize) || (origin[ 2 ] > b->maxs[ 2 ] + sampleSize) )
-						continue;
-					
-					/* walk candidate luxels */
-					VectorClear( average );
-					numLuxels = 0;
-					totalColor = 0.0f;
-					for( y2 = 0; y2 < b->sh && numLuxels < MAX_STITCH_LUXELS; y2++ )
-					{
-						for( x2 = 0; x2 < b->sw && numLuxels < MAX_STITCH_LUXELS; x2++ )
-						{
-							/* ignore same luxels */
-							if( a == b && abs( x - x2 ) <= 1 && abs( y - y2 ) <= 1 )
-								continue;
-							
-							/* ignore unmapped/unlit luxels */
-							cluster2 = SUPER_CLUSTER( x2, y2 );
-							if( *cluster2 == CLUSTER_UNMAPPED )
-								continue;
-							luxel2 = SUPER_LUXEL( 0, x2, y2 );
-							if( luxel2[ 3 ] <= 0.0f )
-								continue;
-							
-							/* get particulars */
-							origin2 = SUPER_ORIGIN( x2, y2 );
-							normal2 = SUPER_NORMAL( x2, y2 );
-							
-							/* test normal */
-							if( DotProduct( normal, normal2 ) < 0.5f )
-								continue;
-							
-							/* test bounds */
-							if( fabs( origin[ 0 ] - origin2[ 0 ] ) > sampleSize ||
-								fabs( origin[ 1 ] - origin2[ 1 ] ) > sampleSize ||
-								fabs( origin[ 2 ] - origin2[ 2 ] ) > sampleSize )
-								continue;
-							
-							/* add luxel */
-							//%	VectorSet( luxel2, 255, 0, 255 );
-							luxels[ numLuxels++ ] = luxel2;
-							VectorAdd( average, luxel2, average );
-							totalColor += luxel2[ 3 ];
-						}
-					}
-					
-					/* early out */
-					if( numLuxels == 0 )
-						continue;
-					
-					/* scale average */
-					ootc = 1.0f / totalColor;
-					VectorScale( average, ootc, luxel );
-					luxel[ 3 ] = 1.0f;
-					numStitched++;
-				}
-			}
-		}
-	}
-	
-	/* emit statistics */
-	Sys_Printf( " (%i)\n", (int) (I_FloatTime() - start) );
-	Sys_FPrintf( SYS_VRB, "%9d luxels stitched\n", numStitched );
-}
-
-
-
-/*
-CompareBSPLuxels()
-compares two surface lightmaps' bsp luxels, ignoring occluded luxels
-*/
-
-#define LUXEL_TOLERANCE		0.0025
-#define LUXEL_COLOR_FRAC	0.001302083	/* 1 / 3 / 256 */
-
-static qboolean CompareBSPLuxels( rawLightmap_t *a, int aNum, rawLightmap_t *b, int bNum )
-{
-	rawLightmap_t	*lm;
-	int				x, y;
-	double			delta, total, rd, gd, bd;
-	float			*aLuxel, *bLuxel;
-	
-	
-	/* styled lightmaps will never be collapsed to non-styled lightmaps when there is _minlight */
-	if( (minLight[ 0 ] || minLight[ 1 ] || minLight[ 2 ]) &&
-		((aNum == 0 && bNum != 0) || (aNum != 0 && bNum == 0)) )
-		return qfalse;
-	
-	/* compare */
-	if( a->w != b->w || a->h != b->h ||
-		a->customWidth != b->customWidth || a->customHeight != b->customHeight ||
-		a->gamma != b->gamma ||
-		a->bspLuxels[ aNum ] == NULL || b->bspLuxels[ bNum ] == NULL )
-		return qfalse;
-	
-	/* compare luxels */
-	delta = 0.0;
-	total = 0.0;
-	for( y = 0; y < a->h; y++ )
-	{
-		for( x = 0; x < a->w; x++ )
-		{
-			/* increment total */
-			total += 1.0;
-			
-			/* get luxels */
-			lm = a;	aLuxel = BSP_LUXEL( aNum, x, y );
-			lm = b;	bLuxel = BSP_LUXEL( bNum, x, y );
-			
-			/* ignore unused luxels */
-			if( aLuxel[ 0 ] < 0 || bLuxel[ 0 ] < 0 )
-				continue;
-			
-			/* get deltas */
-			rd = fabs( aLuxel[ 0 ] - bLuxel[ 0 ] );
-			gd = fabs( aLuxel[ 1 ] - bLuxel[ 1 ] );
-			bd = fabs( aLuxel[ 2 ] - bLuxel[ 2 ] );
-			
-			/* 2003-09-27: compare individual luxels */
-			if( rd > 3.0 || gd > 3.0 || bd > 3.0 )
-				return qfalse;
-			
-			/* compare (fixme: take into account perceptual differences) */
-			delta += rd * LUXEL_COLOR_FRAC;
-			delta += gd * LUXEL_COLOR_FRAC;
-			delta += bd * LUXEL_COLOR_FRAC;
-			
-			/* is the change too high? */
-			if( total > 0.0 && ((delta / total) > LUXEL_TOLERANCE) )
-				return qfalse;
-		}
-	}
-	
-	/* made it this far, they must be identical (or close enough) */
-	return qtrue;
-}
-
-
-
-/*
-MergeBSPLuxels()
-merges two surface lightmaps' bsp luxels, overwriting occluded luxels
-*/
-
-static void MergeBSPLuxels( rawLightmap_t *a, int aNum, rawLightmap_t *b, int bNum )
-{
-	rawLightmap_t	*lm;
-	int				x, y;
-	float			luxel[ 3 ], *aLuxel, *bLuxel;
-	
-	
-	/* compare */
-	if( a->w != b->w || a->h != b->h ||
-		a->customWidth != b->customWidth || a->customHeight != b->customHeight ||
-		a->gamma != b->gamma ||
-		a->bspLuxels[ aNum ] == NULL || b->bspLuxels[ bNum ] == NULL )
-		return;
-	
-	/* merge luxels */
-	for( y = 0; y < a->h; y++ )
-	{
-		for( x = 0; x < a->w; x++ )
-		{
-			/* get luxels */
-			lm = a;	aLuxel = BSP_LUXEL( aNum, x, y );
-			lm = b;	bLuxel = BSP_LUXEL( bNum, x, y );
-			
-			/* handle occlusion mismatch */
-			if( aLuxel[ 0 ] < 0.0f )
-				VectorCopy( bLuxel, aLuxel );
-			else if( bLuxel[ 0 ] < 0.0f )
-				VectorCopy( aLuxel, bLuxel );
-			else
-			{
-				/* average */
-				VectorAdd( aLuxel, bLuxel, luxel );
-				VectorScale( luxel, 0.5f, luxel );
-				
-				/* debugging code */
-				//%	luxel[ 2 ] += 64.0f;
-				
-				/* copy to both */
-				VectorCopy( luxel, aLuxel );
-				VectorCopy( luxel, bLuxel );
-			}
-		}
-	}
-}
-
-
-
-/*
-ApproximateLuxel()
-determines if a single luxel is can be approximated with the interpolated vertex rgba
-*/
-
-static qboolean ApproximateLuxel( rawLightmap_t *lm, bspDrawVert_t *dv )
-{
-	int		i, x, y, d, lightmapNum;
-	float	*luxel;
-	vec3_t	color, vertexColor;
-	byte	cb[ 4 ], vcb[ 4 ];
-	
-	
-	/* find luxel xy coords */
-	x = dv->lightmap[ 0 ][ 0 ] / superSample;
-	y = dv->lightmap[ 0 ][ 1 ] / superSample;
-	if( x < 0 )
-		x = 0;
-	else if( x >= lm->w )
-		x = lm->w - 1;
-	if( y < 0 )
-		y = 0;
-	else if( y >= lm->h )
-		y = lm->h - 1;
-	
-	/* walk list */
-	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-	{
-		/* early out */
-		if( lm->styles[ lightmapNum ] == LS_NONE )
-			continue;
-		
-		/* get luxel */
-		luxel = BSP_LUXEL( lightmapNum, x, y );
-		
-		/* ignore occluded luxels */
-		if( luxel[ 0 ] < 0.0f || luxel[ 1 ] < 0.0f || luxel[ 2 ] < 0.0f )
-			return qtrue;
-		
-		/* copy, set min color and compare */
-		VectorCopy( luxel, color );
-		VectorCopy( dv->color[ 0 ], vertexColor );
-
-		/* styles are not affected by minlight */
-		if( lightmapNum == 0 )
-		{
-			for( i = 0; i < 3; i++ )
-			{
-				/* set min color */
-				if( color[ i ] < minLight[ i ] )
-					color[ i ] = minLight[ i ];
-				if( vertexColor[ i ] < minLight[ i ] )	/* note NOT minVertexLight */
-					vertexColor[ i ] = minLight[ i ];
-			}
-		}
-		
-		/* set to bytes */
-		ColorToBytes( color, cb, 1.0f );
-		ColorToBytes( vertexColor, vcb, 1.0f );
-		
-		/* compare */
-		for( i = 0; i < 3; i++ )
-		{
-			d = cb[ i ] - vcb[ i ];
-			if( d < 0 )
-				d *= -1;
-			if( d > approximateTolerance )
-				return qfalse;
-		}
-	}
-	
-	/* close enough for the girls i date */
-	return qtrue;
-}
-
-
-
-/*
-ApproximateTriangle()
-determines if a single triangle can be approximated with vertex rgba
-*/
-
-static qboolean ApproximateTriangle_r( rawLightmap_t *lm, bspDrawVert_t *dv[ 3 ] )
-{
-	bspDrawVert_t	mid, *dv2[ 3 ];
-	int				max;
-	
-	
-	/* approximate the vertexes */
-	if( ApproximateLuxel( lm, dv[ 0 ] ) == qfalse )
-		return qfalse;
-	if( ApproximateLuxel( lm, dv[ 1 ] ) == qfalse )
-		return qfalse;
-	if( ApproximateLuxel( lm, dv[ 2 ] ) == qfalse )
-		return qfalse;
-	
-	/* subdivide calc */
-	{
-		int			i;
-		float		dx, dy, dist, maxDist;
-		
-		
-		/* find the longest edge and split it */
-		max = -1;
-		maxDist = 0;
-		for( i = 0; i < 3; i++ )
-		{
-			dx = dv[ i ]->lightmap[ 0 ][ 0 ] - dv[ (i + 1) % 3 ]->lightmap[ 0 ][ 0 ];
-			dy = dv[ i ]->lightmap[ 0 ][ 1 ] - dv[ (i + 1) % 3 ]->lightmap[ 0 ][ 1 ];
-			dist = sqrt( (dx * dx) + (dy * dy) );
-			if( dist > maxDist )
-			{
-				maxDist = dist;
-				max = i;
-			}
-		}
-		
-		/* try to early out */
-		if( i < 0 || maxDist < subdivideThreshold )
-			return qtrue;
-	}
-
-	/* split the longest edge and map it */
-	LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
-	if( ApproximateLuxel( lm, &mid ) == qfalse )
-		return qfalse;
-	
-	/* recurse to first triangle */
-	VectorCopy( dv, dv2 );
-	dv2[ max ] = &mid;
-	if( ApproximateTriangle_r( lm, dv2 ) == qfalse )
-		return qfalse;
-	
-	/* recurse to second triangle */
-	VectorCopy( dv, dv2 );
-	dv2[ (max + 1) % 3 ] = &mid;
-	return ApproximateTriangle_r( lm, dv2 );
-}
-
-
-
-/*
-ApproximateLightmap()
-determines if a raw lightmap can be approximated sufficiently with vertex colors
-*/
-
-static qboolean ApproximateLightmap( rawLightmap_t *lm )
-{
-	int					n, num, i, x, y, pw[ 5 ], r;
-	bspDrawSurface_t	*ds;
-	surfaceInfo_t		*info;
-	mesh_t				src, *subdivided, *mesh;
-	bspDrawVert_t		*verts, *dv[ 3 ];
-	qboolean			approximated;
-	
-	
-	/* approximating? */
-	if( approximateTolerance <= 0 )
-		return qfalse;
-	
-	/* test for jmonroe */
-	#if 0
-		/* don't approx lightmaps with styled twins */
-		if( lm->numStyledTwins > 0 )
-			return qfalse;
-		
-		/* don't approx lightmaps with styles */
-		for( i = 1; i < MAX_LIGHTMAPS; i++ )
-		{
-			if( lm->styles[ i ] != LS_NONE )
-				return qfalse;
-		}
-	#endif
-	
-	/* assume reduced until shadow detail is found */
-	approximated = qtrue;
-	
-	/* walk the list of surfaces on this raw lightmap */
-	for( n = 0; n < lm->numLightSurfaces; n++ )
-	{
-		/* get surface */
-		num = lightSurfaces[ lm->firstLightSurface + n ];
-		ds = &bspDrawSurfaces[ num ];
-		info = &surfaceInfos[ num ];
-		
-		/* bail if lightmap doesn't match up */
-		if( info->lm != lm )
-			continue;
-		
-		/* assume reduced initially */
-		info->approximated = qtrue;
-		
-		/* assume that surfaces whose bounding boxes is smaller than 2x samplesize will be forced to vertex */
-		if( (info->maxs[ 0 ] - info->mins[ 0 ]) <= (2.0f * info->sampleSize) &&
-			(info->maxs[ 1 ] - info->mins[ 1 ]) <= (2.0f * info->sampleSize) &&
-			(info->maxs[ 2 ] - info->mins[ 2 ]) <= (2.0f * info->sampleSize) )
-		{
-			numSurfsVertexForced++;
-			continue;
-		}
-		
-		/* handle the triangles */
-		switch( ds->surfaceType )
-		{
-			case MST_PLANAR:
-				/* get verts */
-				verts = yDrawVerts + ds->firstVert;
-				
-				/* map the triangles */
-				for( i = 0; i < ds->numIndexes && info->approximated; i += 3 )
-				{
-					dv[ 0 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i ] ];
-					dv[ 1 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 1 ] ];
-					dv[ 2 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 2 ] ];
-					info->approximated = ApproximateTriangle_r( lm, dv );
-				}
-				break;
-			
-			case MST_PATCH:
-				/* make a mesh from the drawsurf */ 
-				src.width = ds->patchWidth;
-				src.height = ds->patchHeight;
-				src.verts = &yDrawVerts[ ds->firstVert ];
-				//%	subdivided = SubdivideMesh( src, 8, 512 );
-				subdivided = SubdivideMesh2( src, info->patchIterations );
-
-				/* fit it to the curve and remove colinear verts on rows/columns */
-				PutMeshOnCurve( *subdivided );
-				mesh = RemoveLinearMeshColumnsRows( subdivided );
-				FreeMesh( subdivided );
-				
-				/* get verts */
-				verts = mesh->verts;
-				
-				/* map the mesh quads */
-				for( y = 0; y < (mesh->height - 1) && info->approximated; y++ )
-				{
-					for( x = 0; x < (mesh->width - 1) && info->approximated; x++ )
-					{
-						/* set indexes */
-						pw[ 0 ] = x + (y * mesh->width);
-						pw[ 1 ] = x + ((y + 1) * mesh->width);
-						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-						pw[ 3 ] = x + 1 + (y * mesh->width);
-						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-						
-						/* set radix */
-						r = (x + y) & 1;
-
-						/* get drawverts and map first triangle */
-						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
-						dv[ 1 ] = &verts[ pw[ r + 1 ] ];
-						dv[ 2 ] = &verts[ pw[ r + 2 ] ];
-						info->approximated = ApproximateTriangle_r( lm, dv );
-						
-						/* get drawverts and map second triangle */
-						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
-						dv[ 1 ] = &verts[ pw[ r + 2 ] ];
-						dv[ 2 ] = &verts[ pw[ r + 3 ] ];
-						if( info->approximated )
-							info->approximated = ApproximateTriangle_r( lm, dv );
-					}
-				}
-				
-				/* free the mesh */
-				FreeMesh( mesh );
-				break;
-			
-			default:
-				break;
-		}
-		
-		/* reduced? */
-		if( info->approximated == qfalse )
-			approximated = qfalse;
-		else
-			numSurfsVertexApproximated++;
-	}
-	
-	/* return */
-	return approximated;
-}
-
-
-
-/*
-TestOutLightmapStamp()
-tests a stamp on a given lightmap for validity
-*/
-
-static qboolean TestOutLightmapStamp( rawLightmap_t *lm, int lightmapNum, outLightmap_t *olm, int x, int y )
-{
-	int			sx, sy, ox, oy, offset;
-	float		*luxel;
-
-	
-	/* bounds check */
-	if( x < 0 || y < 0 || (x + lm->w) > olm->customWidth || (y + lm->h) > olm->customHeight )
-		return qfalse;
-	
-	/* test the stamp */
-	for( sy = 0; sy < lm->h; sy++ )
-	{
-		for( sx = 0; sx < lm->w; sx++ )
-		{
-			/* get luxel */
-			luxel = BSP_LUXEL( lightmapNum, sx, sy );
-			if( luxel[ 0 ] < 0.0f )
-				continue;
-			
-			/* get bsp lightmap coords and test */
-			ox = x + sx;
-			oy = y + sy;
-			offset = (oy * olm->customWidth) + ox;
-			if( olm->lightBits[ offset >> 3 ] & (1 << (offset & 7)) )
-				return qfalse;
-		}
-	}
-	
-	/* stamp is empty */
-	return qtrue;
-}
-
-
-
-/*
-SetupOutLightmap()
-sets up an output lightmap
-*/
-
-static void SetupOutLightmap( rawLightmap_t *lm, outLightmap_t *olm )
-{
-	/* dummy check */
-	if( lm == NULL || olm == NULL )
-		return;
-	
-	/* is this a "normal" bsp-stored lightmap? */
-	if( (lm->customWidth == LIGHTMAP_WIDTH && lm->customHeight == LIGHTMAP_HEIGHT) || externalLightmaps )
-	{
-		olm->lightmapNum = numBSPLightmaps;
-		numBSPLightmaps++;
-		
-		/* lightmaps are interleaved with light direction maps */
-		if( deluxemap )
-			numBSPLightmaps++;
-	}
-	else
-		olm->lightmapNum = -3;
-	
-	/* set external lightmap number */
-	olm->extLightmapNum = -1;
-	
-	/* set it up */
-	olm->numLightmaps = 0;
-	olm->customWidth = lm->customWidth;
-	olm->customHeight = lm->customHeight;
-	olm->freeLuxels = olm->customWidth * olm->customHeight;
-	olm->numShaders = 0;
-	
-	/* allocate buffers */
-	olm->lightBits = safe_malloc( (olm->customWidth * olm->customHeight / 8) + 8 );
-	memset( olm->lightBits, 0, (olm->customWidth * olm->customHeight / 8) + 8 );
-	olm->bspLightBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 );
-	memset( olm->bspLightBytes, 0, olm->customWidth * olm->customHeight * 3 );
-	if( deluxemap )
-	{
-		olm->bspDirBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 );
-		memset( olm->bspDirBytes, 0, olm->customWidth * olm->customHeight * 3 );
-	}
-}
-
-
-
-/*
-FindOutLightmaps()
-for a given surface lightmap, find output lightmap pages and positions for it
-*/
-
-static void FindOutLightmaps( rawLightmap_t *lm )
-{
-	int					i, j, lightmapNum, xMax, yMax, x, y, sx, sy, ox, oy, offset, temp;
-	outLightmap_t		*olm;
-	surfaceInfo_t		*info;
-	float				*luxel, *deluxel;
-	vec3_t				color, direction;
-	byte				*pixel;
-	qboolean			ok;
-	
-	
-	/* set default lightmap number (-3 = LIGHTMAP_BY_VERTEX) */
-	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		lm->outLightmapNums[ lightmapNum ] = -3;
-		
-	/* can this lightmap be approximated with vertex color? */
-	if( ApproximateLightmap( lm ) )
-		return;
-	
-	/* walk list */
-	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-	{
-		/* early out */
-		if( lm->styles[ lightmapNum ] == LS_NONE )
-			continue;
-		
-		/* don't store twinned lightmaps */
-		if( lm->twins[ lightmapNum ] != NULL )
-			continue;
-		
-		/* if this is a styled lightmap, try some normalized locations first */
-		ok = qfalse;
-		if( lightmapNum > 0 && outLightmaps != NULL )
-		{
-			/* loop twice */
-			for( j = 0; j < 2; j++ )
-			{
-				/* try identical position */
-				for( i = 0; i < numOutLightmaps; i++ )
-				{
-					/* get the output lightmap */
-					olm = &outLightmaps[ i ];
-					
-					/* simple early out test */
-					if( olm->freeLuxels < lm->used )
-						continue;
-					
-					/* don't store non-custom raw lightmaps on custom bsp lightmaps */
-					if( olm->customWidth != lm->customWidth ||
-						olm->customHeight != lm->customHeight )
-						continue;
-					
-					/* try identical */
-					if( j == 0 )
-					{
-						x = lm->lightmapX[ 0 ];
-						y = lm->lightmapY[ 0 ];
-						ok = TestOutLightmapStamp( lm, lightmapNum, olm, x, y );
-					}
-					
-					/* try shifting */
-					else
-					{
-						for( sy = -1; sy <= 1; sy++ )
-						{
-							for( sx = -1; sx <= 1; sx++ )
-							{
-								x = lm->lightmapX[ 0 ] + sx * (olm->customWidth >> 1);	//%	lm->w;
-								y = lm->lightmapY[ 0 ] + sy * (olm->customHeight >> 1);	//%	lm->h;
-								ok = TestOutLightmapStamp( lm, lightmapNum, olm, x, y );
-
-								if( ok )
-									break;
-							}
-							
-							if( ok )
-								break;
-						}
-					}
-					
-					if( ok )
-						break;
-				}
-				
-				if( ok )
-					break;
-			}
-		}
-		
-		/* try normal placement algorithm */
-		if( ok == qfalse )
-		{
-			/* reset origin */
-			x = 0;
-			y = 0;
-			
-			/* walk the list of lightmap pages */
-			for( i = 0; i < numOutLightmaps; i++ )
-			{
-				/* get the output lightmap */
-				olm = &outLightmaps[ i ];
-				
-				/* simple early out test */
-				if( olm->freeLuxels < lm->used )
-					continue;
-				
-				/* don't store non-custom raw lightmaps on custom bsp lightmaps */
-				if( olm->customWidth != lm->customWidth ||
-					olm->customHeight != lm->customHeight )
-					continue;
-				
-				/* set maxs */
-				xMax = (olm->customWidth - lm->w) + 1;
-				yMax = (olm->customHeight - lm->h) + 1;
-				
-				/* walk the origin around the lightmap */
-				for( y = 0; y < yMax; y++ )
-				{
-					for( x = 0; x < xMax; x++ )
-					{
-						/* find a fine tract of lauhnd */
-						ok = TestOutLightmapStamp( lm, lightmapNum, olm, x, y );
-						
-						if( ok )
-							break;
-					}
-					
-					if( ok )
-						break;
-				}
-				
-				if( ok )
-					break;
-				
-				/* reset x and y */
-				x = 0;
-				y = 0;
-			}
-		}
-		
-		/* no match? */
-		if( ok == qfalse )
-		{
-			/* allocate two new output lightmaps */
-			numOutLightmaps += 2;
-			olm = safe_malloc( numOutLightmaps * sizeof( outLightmap_t ) );
-			if( outLightmaps != NULL && numOutLightmaps > 2 )
-			{
-				memcpy( olm, outLightmaps, (numOutLightmaps - 2) * sizeof( outLightmap_t ) );
-				free( outLightmaps );
-			}
-			outLightmaps = olm;
-			
-			/* initialize both out lightmaps */
-			SetupOutLightmap( lm, &outLightmaps[ numOutLightmaps - 2 ] );
-			SetupOutLightmap( lm, &outLightmaps[ numOutLightmaps - 1 ] );
-			
-			/* set out lightmap */
-			i = numOutLightmaps - 2;
-			olm = &outLightmaps[ i ];
-			
-			/* set stamp xy origin to the first surface lightmap */
-			if( lightmapNum > 0 )
-			{
-				x = lm->lightmapX[ 0 ];
-				y = lm->lightmapY[ 0 ];
-			}
-		}
-		
-		/* if this is a style-using lightmap, it must be exported */
-		if( lightmapNum > 0 )
-			olm->extLightmapNum = 0;
-		
-		/* add the surface lightmap to the bsp lightmap */
-		lm->outLightmapNums[ lightmapNum ] = i;
-		lm->lightmapX[ lightmapNum ] = x;
-		lm->lightmapY[ lightmapNum ] = y;
-		olm->numLightmaps++;
-		
-		/* add shaders */
-		for( i = 0; i < lm->numLightSurfaces; i++ )
-		{
-			/* get surface info */
-			info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + i ] ];
-			
-			/* test for shader */
-			for( j = 0; j < olm->numShaders; j++ )
-			{
-				if( olm->shaders[ j ] == info->si )
-					break;
-			}
-			
-			/* if it doesn't exist, add it */
-			if( j >= olm->numShaders && olm->numShaders < MAX_LIGHTMAP_SHADERS )
-			{
-				olm->shaders[ olm->numShaders ] = info->si;
-				olm->numShaders++;
-				numLightmapShaders++;
-			}
-		}
-		
-		/* mark the bits used */
-		for( y = 0; y < lm->h; y++ )
-		{
-			for( x = 0; x < lm->w; x++ )
-			{
-				/* get luxel */
-				luxel = BSP_LUXEL( lightmapNum, x, y );
-				deluxel = BSP_DELUXEL( x, y );
-				if( luxel[ 0 ] < 0.0f )
-					continue;
-				
-				/* set minimum light */
-				VectorCopy( luxel, color );
-
-				/* styles are not affected by minlight */
-				if( lightmapNum == 0 )
-				{
-					for( i = 0; i < 3; i++ )
-					{
-						if( color[ i ] < minLight[ i ] )
-							color[ i ] = minLight[ i ];
-					}
-				}
-				
-				/* get bsp lightmap coords  */
-				ox = x + lm->lightmapX[ lightmapNum ];
-				oy = y + lm->lightmapY[ lightmapNum ];
-				offset = (oy * olm->customWidth) + ox;
-				
-				/* flag pixel as used */
-				olm->lightBits[ offset >> 3 ] |= (1 << (offset & 7));
-				olm->freeLuxels--;
-				
-				/* store color */
-				pixel = olm->bspLightBytes + (((oy * olm->customWidth) + ox) * 3);
-				ColorToBytes( color, pixel, lm->gamma );
-				
-				/* store direction */
-				if( deluxemap )
-				{
-					/* normalize average light direction */
-					if( VectorNormalize( deluxel, direction ) )
-					{
-						/* encode [-1,1] in [0,255] */
-						pixel = olm->bspDirBytes + (((oy * olm->customWidth) + ox) * 3);
-						for( i = 0; i < 3; i++ )
-						{
-							temp = (direction[ i ] + 1.0f) * 127.5f;
-							if( temp < 0 )
-								pixel[ i ] = 0;
-							else if( temp > 255 )
-								pixel[ i ] = 255;
-							else
-								pixel[ i ] = temp;
-						}
-					}
-				}
-			}
-		}
-	}
-}
-
-
-
-/*
-CompareRawLightmap()
-compare function for qsort()
-*/
-
-static int CompareRawLightmap( const void *a, const void *b )
-{
-	rawLightmap_t	*alm, *blm;
-	surfaceInfo_t	*aInfo, *bInfo;
-	int				i, min, diff;
-	
-	
-	/* get lightmaps */
-	alm = &rawLightmaps[ *((int*) a) ];
-	blm = &rawLightmaps[ *((int*) b) ];
-	
-	/* get min number of surfaces */
-	min = (alm->numLightSurfaces < blm->numLightSurfaces ? alm->numLightSurfaces : blm->numLightSurfaces);
-	
-	/* iterate */
-	for( i = 0; i < min; i++ )
-	{
-		/* get surface info */
-		aInfo = &surfaceInfos[ lightSurfaces[ alm->firstLightSurface + i ] ];
-		bInfo = &surfaceInfos[ lightSurfaces[ blm->firstLightSurface + i ] ];
-		
-		/* compare shader names */
-		diff = strcmp( aInfo->si->shader, bInfo->si->shader );
-		if( diff != 0 )
-			return diff;
-	}
-
-	/* test style count */
-	diff = 0;
-	for( i = 0; i < MAX_LIGHTMAPS; i++ )
-		diff += blm->styles[ i ] - alm->styles[ i ];
-	if( diff )
-		return diff;
-	
-	/* compare size */
-	diff = (blm->w * blm->h) - (alm->w * alm->h);
-	if( diff != 0 )
-		return diff;
-	
-	/* must be equivalent */
-	return 0;
-}
-
-
-
-/*
-StoreSurfaceLightmaps()
-stores the surface lightmaps into the bsp as byte rgb triplets
-*/
-
-void StoreSurfaceLightmaps( void )
-{
-	int					i, j, k, x, y, lx, ly, sx, sy, *cluster, mappedSamples;
-	int					style, size, lightmapNum, lightmapNum2;
-	float				*normal, *luxel, *bspLuxel, *bspLuxel2, *radLuxel, samples, occludedSamples;
-	vec3_t				sample, occludedSample, dirSample;
-	float				*deluxel, *bspDeluxel, *bspDeluxel2;
-	byte				*lb;
-	int					numUsed, numTwins, numTwinLuxels, numStored;
-	float				lmx, lmy, efficiency;
-	vec3_t				color;
-	bspDrawSurface_t	*ds, *parent, dsTemp;
-	surfaceInfo_t		*info;
-	rawLightmap_t		*lm, *lm2;
-	outLightmap_t		*olm;
-	bspDrawVert_t		*dv, *ydv, *dvParent;
-	char				dirname[ 1024 ], filename[ 1024 ];
-	shaderInfo_t		*csi;
-	char				lightmapName[ 128 ];
-	char				*rgbGenValues[ 256 ];
-	char				*alphaGenValues[ 256 ];
-	
-	
-	/* note it */
-	Sys_Printf( "--- StoreSurfaceLightmaps ---\n");
-	
-	/* setup */
-	strcpy( dirname, source );
-	StripExtension( dirname );
-	memset( rgbGenValues, 0, sizeof( rgbGenValues ) );
-	memset( alphaGenValues, 0, sizeof( alphaGenValues ) );
-	
-	/* -----------------------------------------------------------------
-	   average the sampled luxels into the bsp luxels
-	   ----------------------------------------------------------------- */
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "Subsampling..." );
-	
-	/* walk the list of raw lightmaps */
-	numUsed = 0;
-	numTwins = 0;
-	numTwinLuxels = 0;
-	for( i = 0; i < numRawLightmaps; i++ )
-	{
-		/* get lightmap */
-		lm = &rawLightmaps[ i ];
-		
-		/* walk individual lightmaps */
-		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		{
-			/* early outs */
-			if( lm->superLuxels[ lightmapNum ] == NULL )
-				continue;
-			
-			/* allocate bsp luxel storage */
-			if( lm->bspLuxels[ lightmapNum ] == NULL )
-			{
-				size = lm->w * lm->h * BSP_LUXEL_SIZE * sizeof( float );
-				lm->bspLuxels[ lightmapNum ] = safe_malloc( size );
-				memset( lm->bspLuxels[ lightmapNum ], 0, size );
-			}
-
-			/* allocate radiosity lightmap storage */
-			if( bounce )
-			{
-				size = lm->w * lm->h * RAD_LUXEL_SIZE * sizeof( float );
-				if( lm->radLuxels[ lightmapNum ] == NULL )
-					lm->radLuxels[ lightmapNum ] = safe_malloc( size );
-				memset( lm->radLuxels[ lightmapNum ], 0, size );
-			}
-			
-			/* average supersampled luxels */
-			for( y = 0; y < lm->h; y++ )
-			{
-				for( x = 0; x < lm->w; x++ )
-				{
-					/* subsample */
-					samples = 0.0f;
-					occludedSamples = 0.0f;
-					mappedSamples = 0;
-					VectorClear( sample );
-					VectorClear( occludedSample );
-					VectorClear( dirSample );
-					for( ly = 0; ly < superSample; ly++ )
-					{
-						for( lx = 0; lx < superSample; lx++ )
-						{
-							/* sample luxel */
-							sx = x * superSample + lx;
-							sy = y * superSample + ly;
-							luxel = SUPER_LUXEL( lightmapNum, sx, sy );
-							deluxel = SUPER_DELUXEL( sx, sy );
-							normal = SUPER_NORMAL( sx, sy );
-							cluster = SUPER_CLUSTER( sx, sy );
-							
-							/* sample deluxemap */
-							if( deluxemap && lightmapNum == 0 )
-								VectorAdd( dirSample, deluxel, dirSample );
-							
-							/* keep track of used/occluded samples */
-							if( *cluster != CLUSTER_UNMAPPED )
-								mappedSamples++;
-							
-							/* handle lightmap border? */
-							if( lightmapBorder && (sx == 0 || sx == (lm->sw - 1) || sy == 0 || sy == (lm->sh - 1) ) && luxel[ 3 ] > 0.0f )
-							{
-								VectorSet( sample, 255.0f, 0.0f, 0.0f );
-								samples += 1.0f;
-							}
-							
-							/* handle debug */
-							else if( debug && *cluster < 0 )
-							{
-								if( *cluster == CLUSTER_UNMAPPED )
-									VectorSet( luxel, 255, 204, 0 );
-								else if( *cluster == CLUSTER_OCCLUDED )
-									VectorSet( luxel, 255, 0, 255 );
-								else if( *cluster == CLUSTER_FLOODED )
-									VectorSet( luxel, 0, 32, 255 );
-								VectorAdd( occludedSample, luxel, occludedSample );
-								occludedSamples += 1.0f;
-							}
-							
-							/* normal luxel handling */
-							else if( luxel[ 3 ] > 0.0f )
-							{
-								/* handle lit or flooded luxels */
-								if( *cluster > 0 || *cluster == CLUSTER_FLOODED )
-								{
-									VectorAdd( sample, luxel, sample );
-									samples += luxel[ 3 ];
-								}
-								
-								/* handle occluded or unmapped luxels */
-								else
-								{
-									VectorAdd( occludedSample, luxel, occludedSample );
-									occludedSamples += luxel[ 3 ];
-								}
-								
-								/* handle style debugging */
-								if( debug && lightmapNum > 0 && x < 2 && y < 2 )
-								{
-									VectorCopy( debugColors[ 0 ], sample );
-									samples = 1;
-								}
-							}
-						}
-					}
-					
-					/* only use occluded samples if necessary */
-					if( samples <= 0.0f )
-					{
-						VectorCopy( occludedSample, sample );
-						samples = occludedSamples;
-					}
-					
-					/* get luxels */
-					luxel = SUPER_LUXEL( lightmapNum, x, y );
-					deluxel = SUPER_DELUXEL( x, y );
-					
-					/* store light direction */
-					if( deluxemap && lightmapNum == 0 )
-						VectorCopy( dirSample, deluxel );
-					
-					/* store the sample back in super luxels */
-					if( samples > 0.01f )
-					{
-						VectorScale( sample, (1.0f / samples), luxel );
-						luxel[ 3 ] = 1.0f;
-					}
-					
-					/* if any samples were mapped in any way, store ambient color */
-					else if( mappedSamples > 0 )
-					{
-						if( lightmapNum == 0 )
-							VectorCopy( ambientColor, luxel );
-						else
-							VectorClear( luxel );
-						luxel[ 3 ] = 1.0f;
-					}
-					
-					/* store a bogus value to be fixed later */	
-					else
-					{
-						VectorClear( luxel );
-						luxel[ 3 ] = -1.0f;
-					}
-				}
-			}
-			
-			/* clean up and store into bsp luxels */
-			lm->used = 0;
-			for( y = 0; y < lm->h; y++ )
-			{
-				for( x = 0; x < lm->w; x++ )
-				{
-					/* get luxels */
-					luxel = SUPER_LUXEL( lightmapNum, x, y );
-					deluxel = SUPER_DELUXEL( x, y );
-					
-					/* copy light direction */
-					if( deluxemap && lightmapNum == 0 )
-						VectorCopy( deluxel, dirSample );
-					
-					/* is this a valid sample? */
-					if( luxel[ 3 ] > 0.0f )
-					{
-						VectorCopy( luxel, sample );
-						samples = luxel[ 3 ];
-						numUsed++;
-						lm->used++;
-						
-						/* fix negative samples */
-						for( j = 0; j < 3; j++ )
-						{
-							if( sample[ j ] < 0.0f )
-								sample[ j ] = 0.0f;
-						}
-					}
-					else
-					{
-						/* nick an average value from the neighbors */
-						VectorClear( sample );
-						VectorClear( dirSample );
-						samples = 0.0f;
-						
-						/* fixme: why is this disabled?? */
-						for( sy = (y - 1); sy <= (y + 1); sy++ )
-						{
-							if( sy < 0 || sy >= lm->h )
-								continue;
-							
-							for( sx = (x - 1); sx <= (x + 1); sx++ )
-							{
-								if( sx < 0 || sx >= lm->w || (sx == x && sy == y) )
-									continue;
-								
-								/* get neighbor's particulars */
-								luxel = SUPER_LUXEL( lightmapNum, sx, sy );
-								if( luxel[ 3 ] < 0.0f )
-									continue;
-								VectorAdd( sample, luxel, sample );
-								samples += luxel[ 3 ];
-							}
-						}
-						
-						/* no samples? */
-						if( samples == 0.0f )
-						{
-							VectorSet( sample, -1.0f, -1.0f, -1.0f );
-							samples = 1.0f;
-						}
-						else
-						{
-							numUsed++;
-							lm->used++;
-							
-							/* fix negative samples */
-							for( j = 0; j < 3; j++ )
-							{
-								if( sample[ j ] < 0.0f )
-									sample[ j ] = 0.0f;
-							}
-						}
-					}
-					
-					/* scale the sample */
-					VectorScale( sample, (1.0f / samples), sample );
-					
-					/* store the sample in the radiosity luxels */
-					if( bounce > 0 )
-					{
-						radLuxel = RAD_LUXEL( lightmapNum, x, y );
-						VectorCopy( sample, radLuxel );
-						
-						/* if only storing bounced light, early out here */
-						if( bounceOnly && !bouncing )
-							continue;
-					}
-					
-					/* store the sample in the bsp luxels */
-					bspLuxel = BSP_LUXEL( lightmapNum, x, y );
-					bspDeluxel = BSP_DELUXEL( x, y );
-					
-					VectorAdd( bspLuxel, sample, bspLuxel );
-					if( deluxemap && lightmapNum == 0 )
-						VectorAdd( bspDeluxel, dirSample, bspDeluxel );
-				}
-			}
-			
-			/* wrap bsp luxels if necessary */
-			if( lm->wrap[ 0 ] )
-			{
-				for( y = 0; y < lm->h; y++ )
-				{
-					bspLuxel = BSP_LUXEL( lightmapNum, 0, y );
-					bspLuxel2 = BSP_LUXEL( lightmapNum, lm->w - 1, y );
-					VectorAdd( bspLuxel, bspLuxel2, bspLuxel );
-					VectorScale( bspLuxel, 0.5f, bspLuxel );
-					VectorCopy( bspLuxel, bspLuxel2 );
-					if( deluxemap && lightmapNum == 0 )
-					{
-						bspDeluxel = BSP_DELUXEL( 0, y );
-						bspDeluxel2 = BSP_DELUXEL( lm->w - 1, y );
-						VectorAdd( bspDeluxel, bspDeluxel2, bspDeluxel );
-						VectorScale( bspDeluxel, 0.5f, bspDeluxel );
-						VectorCopy( bspDeluxel, bspDeluxel2 );
-					}
-				}
-			}
-			if( lm->wrap[ 1 ] )
-			{
-				for( x = 0; x < lm->w; x++ )
-				{
-					bspLuxel = BSP_LUXEL( lightmapNum, x, 0 );
-					bspLuxel2 = BSP_LUXEL( lightmapNum, x, lm->h - 1 );
-					VectorAdd( bspLuxel, bspLuxel2, bspLuxel );
-					VectorScale( bspLuxel, 0.5f, bspLuxel );
-					VectorCopy( bspLuxel, bspLuxel2 );
-					if( deluxemap && lightmapNum == 0 )
-					{
-						bspDeluxel = BSP_DELUXEL( x, 0 );
-						bspDeluxel2 = BSP_DELUXEL( x, lm->h - 1 );
-						VectorAdd( bspDeluxel, bspDeluxel2, bspDeluxel );
-						VectorScale( bspDeluxel, 0.5f, bspDeluxel );
-						VectorCopy( bspDeluxel, bspDeluxel2 );
-					}
-				}
-			}
-		}
-	}
-	
-	/* -----------------------------------------------------------------
-	   collapse non-unique lightmaps
-	   ----------------------------------------------------------------- */
-	
-	if( noCollapse == qfalse && deluxemap == qfalse )
-	{
-		/* note it */
-		Sys_FPrintf( SYS_VRB, "collapsing..." );
-		
-		/* set all twin refs to null */
-		for( i = 0; i < numRawLightmaps; i++ )
-		{
-			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				rawLightmaps[ i ].twins[ lightmapNum ] = NULL;
-				rawLightmaps[ i ].twinNums[ lightmapNum ] = -1;
-				rawLightmaps[ i ].numStyledTwins = 0;
-			}
-		}
-		
-		/* walk the list of raw lightmaps */
-		for( i = 0; i < numRawLightmaps; i++ )
-		{
-			/* get lightmap */
-			lm = &rawLightmaps[ i ];
-			
-			/* walk lightmaps */
-			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				/* early outs */
-				if( lm->bspLuxels[ lightmapNum ] == NULL ||
-					lm->twins[ lightmapNum ] != NULL )
-					continue;
-				
-				/* find all lightmaps that are virtually identical to this one */
-				for( j = i + 1; j < numRawLightmaps; j++ )
-				{
-					/* get lightmap */
-					lm2 = &rawLightmaps[ j ];
-					
-					/* walk lightmaps */
-					for( lightmapNum2 = 0; lightmapNum2 < MAX_LIGHTMAPS; lightmapNum2++ )
-					{
-						/* early outs */
-						if( lm2->bspLuxels[ lightmapNum2 ] == NULL ||
-							lm2->twins[ lightmapNum2 ] != NULL )
-							continue;
-						
-						/* compare them */
-						if( CompareBSPLuxels( lm, lightmapNum, lm2, lightmapNum2 ) )
-						{
-							/* merge and set twin */
-							MergeBSPLuxels( lm, lightmapNum, lm2, lightmapNum2 );
-							lm2->twins[ lightmapNum2 ] = lm;
-							lm2->twinNums[ lightmapNum2 ] = lightmapNum;
-							numTwins++;
-							numTwinLuxels += (lm->w * lm->h);
-							
-							/* count styled twins */
-							if( lightmapNum > 0 )
-								lm->numStyledTwins++;
-						}
-					}
-				}
-			}
-		}
-	}
-	
-	/* -----------------------------------------------------------------
-	   sort raw lightmaps by shader
-	   ----------------------------------------------------------------- */
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "sorting..." );
-	
-	/* allocate a new sorted list */
-	if( sortLightmaps == NULL )
-		sortLightmaps = safe_malloc( numRawLightmaps * sizeof( int ) );
-	
-	/* fill it out and sort it */
-	for( i = 0; i < numRawLightmaps; i++ )
-		sortLightmaps[ i ] = i;
-	qsort( sortLightmaps, numRawLightmaps, sizeof( int ), CompareRawLightmap );
-	
-	/* -----------------------------------------------------------------
-	   allocate output lightmaps
-	   ----------------------------------------------------------------- */
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "allocating..." );
-	
-	/* kill all existing output lightmaps */
-	if( outLightmaps != NULL )
-	{
-		for( i = 0; i < numOutLightmaps; i++ )
-		{
-			free( outLightmaps[ i ].lightBits );
-			free( outLightmaps[ i ].bspLightBytes );
-		}
-		free( outLightmaps );
-		outLightmaps = NULL;
-	}
-	
-	numLightmapShaders = 0;
-	numOutLightmaps = 0;
-	numBSPLightmaps = 0;
-	numExtLightmaps = 0;
-	
-	/* find output lightmap */
-	for( i = 0; i < numRawLightmaps; i++ )
-	{
-		lm = &rawLightmaps[ sortLightmaps[ i ] ];
-		FindOutLightmaps( lm );
-	}
-	
-	/* set output numbers in twinned lightmaps */
-	for( i = 0; i < numRawLightmaps; i++ )
-	{
-		/* get lightmap */
-		lm = &rawLightmaps[ sortLightmaps[ i ] ];
-		
-		/* walk lightmaps */
-		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-		{
-			/* get twin */
-			lm2 = lm->twins[ lightmapNum ];
-			if( lm2 == NULL )
-				continue;
-			lightmapNum2 = lm->twinNums[ lightmapNum ];
-			
-			/* find output lightmap from twin */
-			lm->outLightmapNums[ lightmapNum ] = lm2->outLightmapNums[ lightmapNum2 ];
-			lm->lightmapX[ lightmapNum ] = lm2->lightmapX[ lightmapNum2 ];
-			lm->lightmapY[ lightmapNum ] = lm2->lightmapY[ lightmapNum2 ];
-		}
-	}
-	
-	/* -----------------------------------------------------------------
-	   store output lightmaps
-	   ----------------------------------------------------------------- */
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "storing..." );
-	
-	/* count the bsp lightmaps and allocate space */
-	if( bspLightBytes != NULL )
-		free( bspLightBytes );
-	if( numBSPLightmaps == 0 || externalLightmaps )
-	{
-		numBSPLightBytes = 0;
-		bspLightBytes = NULL;
-	}
-	else
-	{
-		numBSPLightBytes = (numBSPLightmaps * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3);
-		bspLightBytes = safe_malloc( numBSPLightBytes );
-		memset( bspLightBytes, 0, numBSPLightBytes );
-	}
-	
-	/* walk the list of output lightmaps */
-	for( i = 0; i < numOutLightmaps; i++ )
-	{
-		/* get output lightmap */
-		olm = &outLightmaps[ i ];
-		
-		/* is this a valid bsp lightmap? */
-		if( olm->lightmapNum >= 0 && !externalLightmaps )
-		{
-			/* copy lighting data */
-			lb = bspLightBytes + (olm->lightmapNum * LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3);
-			memcpy( lb, olm->bspLightBytes, LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3 );
-			
-			/* copy direction data */
-			if( deluxemap )
-			{
-				lb = bspLightBytes + ((olm->lightmapNum + 1) * LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3);
-				memcpy( lb, olm->bspDirBytes, LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3 );
-			}
-		}
-		
-		/* external lightmap? */
-		if( olm->lightmapNum < 0 || olm->extLightmapNum >= 0 || externalLightmaps )
-		{
-			/* make a directory for the lightmaps */
-			Q_mkdir( dirname );
-			
-			/* set external lightmap number */
-			olm->extLightmapNum = numExtLightmaps;
-			
-			/* write lightmap */
-			sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps );
-			Sys_FPrintf( SYS_VRB, "\nwriting %s", filename );
-			WriteTGA24( filename, olm->bspLightBytes, olm->customWidth, olm->customHeight, qtrue );
-			numExtLightmaps++;
-			
-			/* write deluxemap */
-			if( deluxemap )
-			{
-				sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps );
-				Sys_FPrintf( SYS_VRB, "\nwriting %s", filename );
-				WriteTGA24( filename, olm->bspDirBytes, olm->customWidth, olm->customHeight, qtrue );
-				numExtLightmaps++;
-				
-				if( debugDeluxemap )
-					olm->extLightmapNum++;
-			}
-		}
-	}
-	
-	if( numExtLightmaps > 0 )
-		Sys_FPrintf( SYS_VRB, "\n" );
-	
-	/* delete unused external lightmaps */
-	for( i = numExtLightmaps; i; i++ )
-	{
-		/* determine if file exists */
-		sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i );
-		if( !FileExists( filename ) )
-			break;
-		
-		/* delete it */
-		remove( filename );
-	}
-	
-	/* -----------------------------------------------------------------
-	   project the lightmaps onto the bsp surfaces
-	   ----------------------------------------------------------------- */
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "projecting..." );
-	
-	/* walk the list of surfaces */
-	for( i = 0; i < numBSPDrawSurfaces; i++ )
-	{
-		/* get the surface and info */
-		ds = &bspDrawSurfaces[ i ];
-		info = &surfaceInfos[ i ];
-		lm = info->lm;
-		olm = NULL;
-		
-		/* handle surfaces with identical parent */
-		if( info->parentSurfaceNum >= 0 )
-		{
-			/* preserve original data and get parent */
-			parent = &bspDrawSurfaces[ info->parentSurfaceNum ];
-			memcpy( &dsTemp, ds, sizeof( *ds ) );
-			
-			/* overwrite child with parent data */
-			memcpy( ds, parent, sizeof( *ds ) );
-			
-			/* restore key parts */
-			ds->fogNum = dsTemp.fogNum;
-			ds->firstVert = dsTemp.firstVert;
-			ds->firstIndex = dsTemp.firstIndex;
-			memcpy( ds->lightmapVecs, dsTemp.lightmapVecs, sizeof( dsTemp.lightmapVecs ) );
-			
-			/* set vertex data */
-			dv = &bspDrawVerts[ ds->firstVert ];
-			dvParent = &bspDrawVerts[ parent->firstVert ];
-			for( j = 0; j < ds->numVerts; j++ )
-			{
-				memcpy( dv[ j ].lightmap, dvParent[ j ].lightmap, sizeof( dv[ j ].lightmap ) );
-				memcpy( dv[ j ].color, dvParent[ j ].color, sizeof( dv[ j ].color ) );
-			}
-			
-			/* skip the rest */
-			continue;
-		}
-		
-		/* handle vertex lit or approximated surfaces */
-		else if( lm == NULL || lm->outLightmapNums[ 0 ] < 0 )
-		{
-			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				ds->lightmapNum[ lightmapNum ] = -3;
-				ds->lightmapStyles[ lightmapNum ] = ds->vertexStyles[ lightmapNum ];
-			}
-		}
-		
-		/* handle lightmapped surfaces */
-		else
-		{
-			/* walk lightmaps */
-			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				/* set style */
-				ds->lightmapStyles[ lightmapNum ] = lm->styles[ lightmapNum ];
-				
-				/* handle unused style */
-				if( lm->styles[ lightmapNum ] == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 )
-				{
-					ds->lightmapNum[ lightmapNum ] = -3;
-					continue;
-				}
-				
-				/* get output lightmap */
-				olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
-				
-				/* set bsp lightmap number */
-				ds->lightmapNum[ lightmapNum ] = olm->lightmapNum;
-				
-				/* deluxemap debugging makes the deluxemap visible */
-				if( deluxemap && debugDeluxemap && lightmapNum == 0 )
-					ds->lightmapNum[ lightmapNum ]++;
-				
-				/* calc lightmap origin in texture space */
-				lmx = (float) lm->lightmapX[ lightmapNum ] / (float) olm->customWidth;
-				lmy = (float) lm->lightmapY[ lightmapNum ] / (float) olm->customHeight;
-				
-				/* calc lightmap st coords and store lighting values */
-				dv = &bspDrawVerts[ ds->firstVert ];
-				ydv = &yDrawVerts[ ds->firstVert ];
-				for( j = 0; j < ds->numVerts; j++ )
-				{
-					dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + (ydv[ j ].lightmap[ 0 ][ 0 ] / (superSample * olm->customWidth));
-					dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + (ydv[ j ].lightmap[ 0 ][ 1 ] / (superSample * olm->customHeight));
-				}
-			}
-		}
-		
-		/* store vertex colors */
-		dv = &bspDrawVerts[ ds->firstVert ];
-		for( j = 0; j < ds->numVerts; j++ )
-		{
-			/* walk lightmaps */
-			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				/* handle unused style */
-				if( ds->vertexStyles[ lightmapNum ] == LS_NONE )
-					VectorClear( color );
-				else
-				{
-					/* get vertex color */
-					luxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + j );
-					VectorCopy( luxel, color );
-					
-					/* set minimum light */
-					if( lightmapNum == 0 )
-					{
-						for( k = 0; k < 3; k++ )
-							if( color[ k ] < minVertexLight[ k ] )
-								color[ k ] = minVertexLight[ k ];
-					}
-				}
-				
-				/* store to bytes */
-				ColorToBytes( color, dv[ j ].color[ lightmapNum ], info->si->vertexScale );
-			}
-		}
-		
-		/* surfaces with styled lightmaps and a style marker get a custom generated shader (fixme: make this work with external lightmaps) */
-		if( olm != NULL && lm != NULL && lm->styles[ 1 ] != LS_NONE && game->load != LoadRBSPFile )	//%	info->si->styleMarker > 0 )
-		{
-			qboolean	dfEqual;
-			char		key[ 32 ], styleStage[ 512 ], styleStages[ 4096 ], rgbGen[ 128 ], alphaGen[ 128 ];
-			
-			
-			/* setup */
-			sprintf( styleStages, "\n\t// Q3Map2 custom lightstyle stage(s)\n" );
-			dv = &bspDrawVerts[ ds->firstVert ];
-			
-			/* depthFunc equal? */
-			if( info->si->styleMarker == 2 || info->si->implicitMap == IM_MASKED )
-				dfEqual = qtrue;
-			else
-				dfEqual = qfalse;
-			
-			/* generate stages for styled lightmaps */
-			for( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
-			{
-				/* early out */
-				style = lm->styles[ lightmapNum ];
-				if( style == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 )
-					continue;
-				
-				/* get output lightmap */
-				olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
-				
-				/* lightmap name */
-				if( lm->outLightmapNums[ lightmapNum ] == lm->outLightmapNums[ 0 ] )
-					strcpy( lightmapName, "$lightmap" );
-				else
-					sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
-				
-				/* get rgbgen string */
-				if( rgbGenValues[ style ] == NULL )
-				{
-					sprintf( key, "_style%drgbgen", style );
-					rgbGenValues[ style ] = (char*) ValueForKey( &entities[ 0 ], key );
-					if( rgbGenValues[ style ][ 0 ] == '\0' )
-						rgbGenValues[ style ] = "wave noise 0.5 1 0 5.37";
-				}
-				rgbGen[ 0 ] = '\0';
-				if( rgbGenValues[ style ][ 0 ] != '\0' )
-					sprintf( rgbGen, "\t\trgbGen %s // style %d\n", rgbGenValues[ style ], style );
-				else
-					rgbGen[ 0 ] = '\0';
-				
-				/* get alphagen string */
-				if( alphaGenValues[ style ] == NULL )
-				{
-					sprintf( key, "_style%dalphagen", style );
-					alphaGenValues[ style ] = (char*) ValueForKey( &entities[ 0 ], key );
-				}
-				if( alphaGenValues[ style ][ 0 ] != '\0' )
-					sprintf( alphaGen, "\t\talphaGen %s // style %d\n", alphaGenValues[ style ], style );
-				else
-					alphaGen[ 0 ] = '\0';
-				
-				/* calculate st offset */
-				lmx = dv[ 0 ].lightmap[ lightmapNum ][ 0 ] - dv[ 0 ].lightmap[ 0 ][ 0 ];
-				lmy = dv[ 0 ].lightmap[ lightmapNum ][ 1 ] - dv[ 0 ].lightmap[ 0 ][ 1 ];
-				
-				/* create additional stage */
-				if( lmx == 0.0f && lmy == 0.0f )
-				{
-					sprintf( styleStage,	"\t{\n"
-											"\t\tmap %s\n"										/* lightmap */
-											"\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
-											"%s"												/* depthFunc equal */
-											"%s"												/* rgbGen */
-											"%s"												/* alphaGen */
-											"\t\ttcGen lightmap\n"
-											"\t}\n",
-						lightmapName,
-						(dfEqual ? "\t\tdepthFunc equal\n" : ""),
-						rgbGen,
-						alphaGen );
-				}
-				else
-				{
-					sprintf( styleStage,	"\t{\n"
-											"\t\tmap %s\n"										/* lightmap */
-											"\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
-											"%s"												/* depthFunc equal */
-											"%s"												/* rgbGen */
-											"%s"												/* alphaGen */
-											"\t\ttcGen lightmap\n"
-											"\t\ttcMod transform 1 0 0 1 %1.5f %1.5f\n"			/* st offset */
-											"\t}\n",
-						lightmapName,
-						(dfEqual ? "\t\tdepthFunc equal\n" : ""),
-						rgbGen,
-						alphaGen,
-						lmx, lmy );
-					
-				}
-				
-				/* concatenate */
-				strcat( styleStages, styleStage );
-			}
-			
-			/* create custom shader */
-			if( info->si->styleMarker == 2 )
-				csi = CustomShader( info->si, "q3map_styleMarker2", styleStages );
-			else
-				csi = CustomShader( info->si, "q3map_styleMarker", styleStages );
-			
-			/* emit remap command */
-			//%	EmitVertexRemapShader( csi->shader, info->si->shader );
-			
-			/* store it */
-			//%	Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
-			ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
-			//%	Sys_Printf( ")\n" );
-		}
-		
-		/* devise a custom shader for this surface (fixme: make this work with light styles) */
-		else if( olm != NULL && lm != NULL && !externalLightmaps &&
-			(olm->customWidth != LIGHTMAP_WIDTH || olm->customHeight != LIGHTMAP_HEIGHT) )
-		{
-			/* get output lightmap */
-			olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ];
-			
-			/* do some name mangling */
-			sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
-			
-			/* create custom shader */
-			csi = CustomShader( info->si, "$lightmap", lightmapName );
-			
-			/* store it */
-			//%	Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
-			ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
-			//%	Sys_Printf( ")\n" );
-		}
-		
-		/* use the normal plain-jane shader */
-		else
-			ds->shaderNum = EmitShader( info->si->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
-	}
-	
-	/* finish */
-	Sys_FPrintf( SYS_VRB, "done.\n" );
-	
-	/* calc num stored */
-	numStored = numBSPLightBytes / 3;
-	efficiency = (numStored <= 0)
-		? 0
-		: (float) numUsed / (float) numStored;
-	
-	/* print stats */
-	Sys_Printf( "%9d luxels used\n", numUsed );
-	Sys_Printf( "%9d luxels stored (%3.2f percent efficiency)\n", numStored, efficiency * 100.0f );
-	Sys_Printf( "%9d identical surface lightmaps, using %d luxels\n", numTwins, numTwinLuxels );
-	Sys_Printf( "%9d vertex forced surfaces\n", numSurfsVertexForced );
-	Sys_Printf( "%9d vertex approximated surfaces\n", numSurfsVertexApproximated );
-	Sys_Printf( "%9d BSP lightmaps\n", numBSPLightmaps );
-	Sys_Printf( "%9d total lightmaps\n", numOutLightmaps );
-	Sys_Printf( "%9d unique lightmap/shader combinations\n", numLightmapShaders );
-	
-	/* write map shader file */
-	WriteMapShaderFile();
-}
-
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define LIGHTMAPS_YDNAR_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+/* -------------------------------------------------------------------------------
+
+this file contains code that doe lightmap allocation and projection that
+runs in the -light phase.
+
+this is handled here rather than in the bsp phase for a few reasons--
+surfaces are no longer necessarily convex polygons, patches may or may not be
+planar or have lightmaps projected directly onto control points.
+
+also, this allows lightmaps to be calculated before being allocated and stored
+in the bsp. lightmaps that have little high-frequency information are candidates
+for having their resolutions scaled down.
+
+------------------------------------------------------------------------------- */
+
+/*
+WriteTGA24()
+based on WriteTGA() from imagelib.c
+*/
+
+void WriteTGA24( char *filename, byte *data, int width, int height, qboolean flip )
+{
+	int		i, c;
+	byte	*buffer, *in;
+	FILE	*file;
+	
+	
+	/* allocate a buffer and set it up */
+	buffer = safe_malloc( width * height * 3 + 18 );
+	memset( buffer, 0, 18 );
+	buffer[ 2 ] = 2;
+	buffer[ 12 ] = width & 255;
+	buffer[ 13 ] = width >> 8;
+	buffer[ 14 ] = height & 255;
+	buffer[ 15 ] = height >> 8;
+	buffer[ 16 ] = 24;
+
+	/* swap rgb to bgr */
+	c = (width * height * 3) + 18;
+	for( i = 18; i < c; i += 3 )
+	{
+		buffer[ i ] = data[ i - 18 + 2 ];		/* blue */
+		buffer[ i + 1 ] = data[ i - 18 + 1 ];	/* green */
+		buffer[ i + 2 ] = data[ i - 18 + 0 ];	/* red */
+	}
+	
+	/* write it and free the buffer */
+	file = fopen( filename, "wb" );
+	if( file == NULL )
+		Error( "Unable to open %s for writing", filename );
+	
+	/* flip vertically? */
+	if( flip )
+	{
+		fwrite( buffer, 1, 18, file );
+		for( in = buffer + ((height - 1) * width * 3) + 18; in >= buffer; in -= (width * 3) )
+			fwrite( in, 1, (width * 3), file );
+	}
+	else
+		fwrite( buffer, 1, c, file );
+	
+	/* close the file */
+	fclose( file );
+	free( buffer );
+}
+
+
+
+/*
+ExportLightmaps()
+exports the lightmaps as a list of numbered tga images
+*/
+
+void ExportLightmaps( void )
+{
+	int			i;
+	char		dirname[ 1024 ], filename[ 1024 ];
+	byte		*lightmap;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- ExportLightmaps ---\n");
+	
+	/* do some path mangling */
+	strcpy( dirname, source );
+	StripExtension( dirname );
+	
+	/* sanity check */
+	if( bspLightBytes == NULL )
+	{
+		Sys_Printf( "WARNING: No BSP lightmap data\n" );
+		return;
+	}
+	
+	/* make a directory for the lightmaps */
+	Q_mkdir( dirname );
+	
+	/* iterate through the lightmaps */
+	for( i = 0, lightmap = bspLightBytes; lightmap < (bspLightBytes + numBSPLightBytes); i++, lightmap += (LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3) )
+	{
+		/* write a tga image out */
+		sprintf( filename, "%s/lightmap_%04d.tga", dirname, i );
+		Sys_Printf( "Writing %s\n", filename );
+		WriteTGA24( filename, lightmap, LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT, qfalse );
+	}
+}
+
+
+
+/*
+ExportLightmapsMain()
+exports the lightmaps as a list of numbered tga images
+*/
+
+int ExportLightmapsMain( int argc, char **argv )
+{
+	/* arg checking */
+	if( argc < 1 )
+	{
+		Sys_Printf( "Usage: q3map -export [-v] <mapname>\n" );
+		return 0;
+	}
+	
+	/* do some path mangling */
+	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
+	StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	
+	/* load the bsp */
+	Sys_Printf( "Loading %s\n", source );
+	LoadBSPFile( source );
+	
+	/* export the lightmaps */
+	ExportLightmaps();
+	
+	/* return to sender */
+	return 0;
+}
+
+
+
+/*
+ImportLightmapsMain()
+imports the lightmaps from a list of numbered tga images
+*/
+
+int ImportLightmapsMain( int argc, char **argv )
+{
+	int			i, x, y, len, width, height;
+	char		dirname[ 1024 ], filename[ 1024 ];
+	byte		*lightmap, *buffer, *pixels, *in, *out;
+	
+	
+	/* arg checking */
+	if( argc < 1 )
+	{
+		Sys_Printf( "Usage: q3map -import [-v] <mapname>\n" );
+		return 0;
+	}
+	
+	/* do some path mangling */
+	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
+	StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	
+	/* load the bsp */
+	Sys_Printf( "Loading %s\n", source );
+	LoadBSPFile( source );
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- ImportLightmaps ---\n");
+	
+	/* do some path mangling */
+	strcpy( dirname, source );
+	StripExtension( dirname );
+	
+	/* sanity check */
+	if( bspLightBytes == NULL )
+		Error( "No lightmap data" );
+	
+	/* make a directory for the lightmaps */
+	Q_mkdir( dirname );
+	
+	/* iterate through the lightmaps */
+	for( i = 0, lightmap = bspLightBytes; lightmap < (bspLightBytes + numBSPLightBytes); i++, lightmap += (LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3) )
+	{
+		/* read a tga image */
+		sprintf( filename, "%s/lightmap_%04d.tga", dirname, i );
+		Sys_Printf( "Loading %s\n", filename );
+		buffer = NULL;
+		len = vfsLoadFile( filename, (void*) &buffer, -1 );
+		if( len < 0 )
+		{
+			Sys_Printf( "WARNING: Unable to load image %s\n", filename );
+			continue;
+		}
+		
+		/* parse file into an image */
+		pixels = NULL;
+		LoadTGABuffer( buffer, &pixels, &width, &height );
+		free( buffer );
+		
+		/* sanity check it */
+		if( pixels == NULL )
+		{
+			Sys_Printf( "WARNING: Unable to load image %s\n", filename );
+			continue;
+		}
+		if( width != LIGHTMAP_WIDTH || height != LIGHTMAP_HEIGHT )
+			Sys_Printf( "WARNING: Image %s is not the right size (%d, %d) != (%d, %d)\n",
+				filename, width, height, LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT );
+		
+		/* copy the pixels */
+		in = pixels;
+		for( y = 1; y <= LIGHTMAP_HEIGHT; y++ )
+		{
+			out = lightmap + ((LIGHTMAP_HEIGHT - y) * LIGHTMAP_WIDTH * 3);
+			for( x = 0; x < LIGHTMAP_WIDTH; x++, in += 4, out += 3 )
+				VectorCopy( in, out );
+		}
+		
+		/* free the image */
+		free( pixels );
+	}
+	
+	/* write the bsp */
+	Sys_Printf( "writing %s\n", source );
+	WriteBSPFile( source );
+	
+	/* return to sender */
+	return 0;
+}
+
+
+
+/* -------------------------------------------------------------------------------
+
+this section deals with projecting a lightmap onto a raw drawsurface
+
+------------------------------------------------------------------------------- */
+
+/*
+CompareLightSurface()
+compare function for qsort()
+*/
+
+static int CompareLightSurface( const void *a, const void *b )
+{
+	shaderInfo_t	*asi, *bsi;
+	
+	
+	/* get shaders */
+	asi = surfaceInfos[ *((int*) a) ].si;
+	bsi = surfaceInfos[ *((int*) b) ].si;
+	
+	/* dummy check */
+	if( asi == NULL )
+		return -1;
+	if( bsi == NULL )
+		return 1;
+	
+	/* compare shader names */
+	return strcmp( asi->shader, bsi->shader );
+}
+
+
+
+/*
+FinishRawLightmap()
+allocates a raw lightmap's necessary buffers
+*/
+
+void FinishRawLightmap( rawLightmap_t *lm )
+{
+	int					i, j, c, size, *sc;
+	float				is;
+	surfaceInfo_t		*info;
+	
+	
+	/* sort light surfaces by shader name */
+	qsort( &lightSurfaces[ lm->firstLightSurface ], lm->numLightSurfaces, sizeof( int ), CompareLightSurface );
+	
+	/* count clusters */
+	lm->numLightClusters = 0;
+	for( i = 0; i < lm->numLightSurfaces; i++ )
+	{
+		/* get surface info */
+		info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + i ] ];
+		
+		/* add surface clusters */
+		lm->numLightClusters += info->numSurfaceClusters;
+	}
+	
+	/* allocate buffer for clusters and copy */
+	lm->lightClusters = safe_malloc( lm->numLightClusters * sizeof( *lm->lightClusters ) );
+	c = 0;
+	for( i = 0; i < lm->numLightSurfaces; i++ )
+	{
+		/* get surface info */
+		info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + i ] ];
+		
+		/* add surface clusters */
+		for( j = 0; j < info->numSurfaceClusters; j++ )
+			lm->lightClusters[ c++ ] = surfaceClusters[ info->firstSurfaceCluster + j ];
+	}
+	
+	/* set styles */
+	lm->styles[ 0 ] = LS_NORMAL;
+	for( i = 1; i < MAX_LIGHTMAPS; i++ )
+		lm->styles[ i ] = LS_NONE;
+	
+	/* set supersampling size */
+	lm->sw = lm->w * superSample;
+	lm->sh = lm->h * superSample;
+	
+	/* add to super luxel count */
+	numRawSuperLuxels += (lm->sw * lm->sh);
+	
+	/* manipulate origin/vecs for supersampling */
+	if( superSample > 1 && lm->vecs != NULL )
+	{
+		/* calc inverse supersample */
+		is = 1.0f / superSample;
+		
+		/* scale the vectors and shift the origin */
+		#if 1
+			/* new code that works for arbitrary supersampling values */
+			VectorMA( lm->origin, -0.5, lm->vecs[ 0 ], lm->origin );
+			VectorMA( lm->origin, -0.5, lm->vecs[ 1 ], lm->origin );
+			VectorScale( lm->vecs[ 0 ], is, lm->vecs[ 0 ] );
+			VectorScale( lm->vecs[ 1 ], is, lm->vecs[ 1 ] );
+			VectorMA( lm->origin, is, lm->vecs[ 0 ], lm->origin );
+			VectorMA( lm->origin, is, lm->vecs[ 1 ], lm->origin );
+		#else
+			/* old code that only worked with a value of 2 */
+			VectorScale( lm->vecs[ 0 ], is, lm->vecs[ 0 ] );
+			VectorScale( lm->vecs[ 1 ], is, lm->vecs[ 1 ] );
+			VectorMA( lm->origin, -is, lm->vecs[ 0 ], lm->origin );
+			VectorMA( lm->origin, -is, lm->vecs[ 1 ], lm->origin );
+		#endif
+	}
+	
+	/* allocate bsp lightmap storage */
+	size = lm->w * lm->h * BSP_LUXEL_SIZE * sizeof( float );
+	if( lm->bspLuxels[ 0 ] == NULL )
+		lm->bspLuxels[ 0 ] = safe_malloc( size );
+	memset( lm->bspLuxels[ 0 ], 0, size );
+	
+	/* allocate radiosity lightmap storage */
+	if( bounce )
+	{
+		size = lm->w * lm->h * RAD_LUXEL_SIZE * sizeof( float );
+		if( lm->radLuxels[ 0 ] == NULL )
+			lm->radLuxels[ 0 ] = safe_malloc( size );
+		memset( lm->radLuxels[ 0 ], 0, size );
+	}
+	
+	/* allocate sampling lightmap storage */
+	size = lm->sw * lm->sh * SUPER_LUXEL_SIZE * sizeof( float );
+	if( lm->superLuxels[ 0 ] == NULL )
+		lm->superLuxels[ 0 ] = safe_malloc( size );
+	memset( lm->superLuxels[ 0 ], 0, size );
+	
+	/* allocate origin map storage */
+	size = lm->sw * lm->sh * SUPER_ORIGIN_SIZE * sizeof( float );
+	if( lm->superOrigins == NULL )
+		lm->superOrigins = safe_malloc( size );
+	memset( lm->superOrigins, 0, size );
+	
+	/* allocate normal map storage */
+	size = lm->sw * lm->sh * SUPER_NORMAL_SIZE * sizeof( float );
+	if( lm->superNormals == NULL )
+		lm->superNormals = safe_malloc( size );
+	memset( lm->superNormals, 0, size );
+	
+	/* allocate cluster map storage */
+	size = lm->sw * lm->sh * sizeof( int );
+	if( lm->superClusters == NULL )
+		lm->superClusters = safe_malloc( size );
+	size = lm->sw * lm->sh;
+	sc = lm->superClusters;
+	for( i = 0; i < size; i++ )
+		(*sc++) = CLUSTER_UNMAPPED;
+	
+	/* deluxemap allocation */
+	if( deluxemap )
+	{
+		/* allocate sampling deluxel storage */
+		size = lm->sw * lm->sh * SUPER_DELUXEL_SIZE * sizeof( float );
+		if( lm->superDeluxels == NULL )
+			lm->superDeluxels = safe_malloc( size );
+		memset( lm->superDeluxels, 0, size );
+		
+		/* allocate bsp deluxel storage */
+		size = lm->w * lm->h * BSP_DELUXEL_SIZE * sizeof( float );
+		if( lm->bspDeluxels == NULL )
+			lm->bspDeluxels = safe_malloc( size );
+		memset( lm->bspDeluxels, 0, size );
+	}
+	
+	/* add to count */
+	numLuxels += (lm->sw * lm->sh);
+}
+
+
+
+/*
+AddPatchToRawLightmap()
+projects a lightmap for a patch surface
+since lightmap calculation for surfaces is now handled in a general way (light_ydnar.c),
+it is no longer necessary for patch verts to fall exactly on a lightmap sample
+based on AllocateLightmapForPatch()
+*/
+
+qboolean AddPatchToRawLightmap( int num, rawLightmap_t *lm )
+{
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	int					x, y;
+	bspDrawVert_t		*verts, *a, *b;
+	vec3_t				delta;
+	mesh_t				src, *subdivided, *mesh;
+	float				sBasis, tBasis, s, t;
+	float				length, widthTable[ MAX_EXPANDED_AXIS ], heightTable[ MAX_EXPANDED_AXIS ];
+	
+	
+	/* patches finish a raw lightmap */
+	lm->finished = qtrue;
+	
+	/* get surface and info  */
+	ds = &bspDrawSurfaces[ num ];
+	info = &surfaceInfos[ num ];
+	
+	/* make a temporary mesh from the drawsurf */ 
+	src.width = ds->patchWidth;
+	src.height = ds->patchHeight;
+	src.verts = &yDrawVerts[ ds->firstVert ];
+	//%	subdivided = SubdivideMesh( src, 8, 512 );
+	subdivided = SubdivideMesh2( src, info->patchIterations );
+	
+	/* fit it to the curve and remove colinear verts on rows/columns */
+	PutMeshOnCurve( *subdivided );
+	mesh = RemoveLinearMeshColumnsRows( subdivided );
+	FreeMesh( subdivided );
+	
+	/* find the longest distance on each row/column */
+	verts = mesh->verts;
+	memset( widthTable, 0, sizeof( widthTable ) );
+	memset( heightTable, 0, sizeof( heightTable ) );
+	for( y = 0; y < mesh->height; y++ )
+	{
+		for( x = 0; x < mesh->width; x++ )
+		{
+			/* get width */
+			if( x + 1 < mesh->width )
+			{
+				a = &verts[ (y * mesh->width) + x ];
+				b = &verts[ (y * mesh->width) + x + 1 ];
+				VectorSubtract( a->xyz, b->xyz, delta );
+				length = VectorLength( delta );
+				if( length > widthTable[ x ] )
+					widthTable[ x ] = length;
+			}
+			
+			/* get height */
+			if( y + 1 < mesh->height )
+			{
+				a = &verts[ (y * mesh->width) + x ];
+				b = &verts[ ((y + 1) * mesh->width) + x ];
+				VectorSubtract( a->xyz, b->xyz, delta );
+				length = VectorLength( delta );
+				if( length > heightTable[ y ] )
+					heightTable[ y ] = length;
+			}
+		}
+	}
+	
+	/* determine lightmap width */
+	length = 0;
+	for( x = 0; x < (mesh->width - 1); x++ )
+		length += widthTable[ x ];
+	lm->w = ceil( length / lm->sampleSize ) + 1;
+	if( lm->w < ds->patchWidth )
+		lm->w = ds->patchWidth;
+	if( lm->w > lm->customWidth )
+		lm->w = lm->customWidth;
+	sBasis = (float) (lm->w - 1) / (float) (ds->patchWidth - 1);
+	
+	/* determine lightmap height */
+	length = 0;
+	for( y = 0; y < (mesh->height - 1); y++ )
+		length += heightTable[ y ];
+	lm->h = ceil( length / lm->sampleSize ) + 1;
+	if( lm->h < ds->patchHeight )
+		lm->h = ds->patchHeight;
+	if( lm->h > lm->customHeight )
+		lm->h = lm->customHeight;
+	tBasis = (float) (lm->h - 1) / (float) (ds->patchHeight - 1);
+	
+	/* free the temporary mesh */
+	FreeMesh( mesh );
+	
+	/* set the lightmap texture coordinates in yDrawVerts */
+	lm->wrap[ 0 ] = qtrue;
+	lm->wrap[ 1 ] = qtrue;
+	verts = &yDrawVerts[ ds->firstVert ];
+	for( y = 0; y < ds->patchHeight; y++ )
+	{
+		t = (tBasis * y) + 0.5f;
+		for( x = 0; x < ds->patchWidth; x++ )
+		{
+			s = (sBasis * x) + 0.5f;
+			verts[ (y * ds->patchWidth) + x ].lightmap[ 0 ][ 0 ] = s * superSample;
+			verts[ (y * ds->patchWidth) + x ].lightmap[ 0 ][ 1 ] = t * superSample;
+			
+			if( y == 0 && !VectorCompare( verts[ x ].xyz, verts[ ((ds->patchHeight - 1) * ds->patchWidth) + x ].xyz ) )
+				lm->wrap[ 1 ] = qfalse;
+		}
+		
+		if( !VectorCompare( verts[ (y * ds->patchWidth) ].xyz, verts[ (y * ds->patchWidth) + (ds->patchWidth - 1) ].xyz ) )
+			lm->wrap[ 0 ] = qfalse;
+	}
+	
+	/* debug code: */
+	//%	Sys_Printf( "wrap S: %d wrap T: %d\n", lm->wrap[ 0 ], lm->wrap[ 1 ] );
+	//% if( lm->w > (ds->lightmapWidth & 0xFF) || lm->h > (ds->lightmapHeight & 0xFF) )
+	//%		Sys_Printf( "Patch lightmap: (%3d %3d) > (%3d, %3d)\n", lm->w, lm->h, ds->lightmapWidth & 0xFF, ds->lightmapHeight & 0xFF );
+	//% ds->lightmapWidth = lm->w | (ds->lightmapWidth & 0xFFFF0000);
+	//% ds->lightmapHeight = lm->h | (ds->lightmapHeight & 0xFFFF0000);
+	
+	/* add to counts */
+	numPatchesLightmapped++;
+	
+	/* return */
+	return qtrue;
+}
+
+
+
+/*
+AddSurfaceToRawLightmap()
+projects a lightmap for a surface
+based on AllocateLightmapForSurface()
+*/
+
+qboolean AddSurfaceToRawLightmap( int num, rawLightmap_t *lm )
+{
+	bspDrawSurface_t	*ds, *ds2;
+	surfaceInfo_t		*info, *info2;
+	int					num2, n, i, axisNum;
+	float				s, t, d, len, sampleSize;
+	vec3_t				mins, maxs, origin, faxis, size, exactSize, delta, normalized, vecs[ 2 ];
+	vec4_t				plane;
+	bspDrawVert_t		*verts;
+	
+	
+	/* get surface and info  */
+	ds = &bspDrawSurfaces[ num ];
+	info = &surfaceInfos[ num ];
+	
+	/* add the surface to the raw lightmap */
+	lightSurfaces[ numLightSurfaces++ ] = num;
+	lm->numLightSurfaces++;
+	
+	/* does this raw lightmap already have any surfaces? */
+	if( lm->numLightSurfaces > 1 )
+	{
+		/* surface and raw lightmap must have the same lightmap projection axis */
+		if( VectorCompare( info->axis, lm->axis ) == qfalse )
+			return qfalse;
+		
+		/* match identical attributes */
+		if( info->sampleSize != lm->sampleSize ||
+			info->entityNum != lm->entityNum ||
+			info->recvShadows != lm->recvShadows ||
+			info->si->lmCustomWidth != lm->customWidth ||
+			info->si->lmCustomHeight != lm->customHeight ||
+			info->si->lmGamma != lm->gamma ||
+			info->si->lmFilterRadius != lm->filterRadius ||
+			info->si->splotchFix != lm->splotchFix )
+			return qfalse;
+		
+		/* surface bounds must intersect with raw lightmap bounds */
+		for( i = 0; i < 3; i++ )
+		{
+			if( info->mins[ i ] > lm->maxs[ i ] )
+				return qfalse;
+			if( info->maxs[ i ] < lm->mins[ i ] )
+				return qfalse;
+		}
+		
+		/* plane check (fixme: allow merging of nonplanars) */
+		if( info->si->lmMergable == qfalse )
+		{
+			if( info->plane == NULL || lm->plane == NULL )
+				return qfalse;
+			
+			/* compare planes */
+			for( i = 0; i < 4; i++ )
+				if( fabs( info->plane[ i ] - lm->plane[ i ] ) > EQUAL_EPSILON )
+					return qfalse;
+		}
+		
+		/* debug code hacking */
+		//%	if( lm->numLightSurfaces > 1 )
+		//%		return qfalse;
+	}
+	
+	/* set plane */
+	if( info->plane == NULL )
+		lm->plane = NULL;
+	
+	/* add surface to lightmap bounds */
+	AddPointToBounds( info->mins, lm->mins, lm->maxs );
+	AddPointToBounds( info->maxs, lm->mins, lm->maxs );
+	
+	/* check to see if this is a non-planar patch */
+	if( ds->surfaceType == MST_PATCH &&
+		lm->axis[ 0 ] == 0.0f && lm->axis[ 1 ] == 0.0f && lm->axis[ 2 ] == 0.0f )
+		return AddPatchToRawLightmap( num, lm );
+	
+	/* start with initially requested sample size */
+	sampleSize = lm->sampleSize;
+	
+	/* round to the lightmap resolution */
+	for( i = 0; i < 3; i++ )
+	{
+		exactSize[ i ] = lm->maxs[ i ] - lm->mins[ i ];
+ 		mins[ i ] = sampleSize * floor( lm->mins[ i ] / sampleSize );
+ 		maxs[ i ] = sampleSize * ceil( lm->maxs[ i ] / sampleSize );
+ 		size[ i ] = (maxs[ i ] - mins[ i ]) / sampleSize + 1.0f;
+		
+		/* hack (god this sucks) */
+		if( size[ i ] > lm->customWidth || size[ i ] > lm->customHeight )
+		{
+			i = -1;
+			sampleSize += 1.0f;
+		}
+	}
+	
+	/* set actual sample size */
+	lm->actualSampleSize = sampleSize;
+	
+	/* fixme: copy rounded mins/maxes to lightmap record? */
+	if( lm->plane == NULL )
+	{
+		VectorCopy( mins, lm->mins );
+		VectorCopy( maxs, lm->maxs );
+		VectorCopy( mins, origin );
+	}
+	
+	/* set lightmap origin */
+	VectorCopy( lm->mins, origin );
+	
+	/* make absolute axis */
+	faxis[ 0 ] = fabs( lm->axis[ 0 ] );
+	faxis[ 1 ] = fabs( lm->axis[ 1 ] );
+	faxis[ 2 ] = fabs( lm->axis[ 2 ] );
+	
+	/* clear out lightmap vectors */
+	memset( vecs, 0, sizeof( vecs ) );
+	
+	/* classify the plane (x y or z major) (ydnar: biased to z axis projection) */
+	if( faxis[ 2 ] >= faxis[ 0 ] && faxis[ 2 ] >= faxis[ 1 ] )
+	{
+		axisNum = 2;
+		lm->w = size[ 0 ];
+		lm->h = size[ 1 ];
+		vecs[ 0 ][ 0 ] = 1.0f / sampleSize;
+		vecs[ 1 ][ 1 ] = 1.0f / sampleSize;
+	}
+	else if( faxis[ 0 ] >= faxis[ 1 ] && faxis[ 0 ] >= faxis[ 2 ] )
+	{
+		axisNum = 0;
+		lm->w = size[ 1 ];
+		lm->h = size[ 2 ];
+		vecs[ 0 ][ 1 ] = 1.0f / sampleSize;
+		vecs[ 1 ][ 2 ] = 1.0f / sampleSize;
+	}
+	else
+	{
+		axisNum = 1;
+		lm->w = size[ 0 ];
+		lm->h = size[ 2 ];
+		vecs[ 0 ][ 0 ] = 1.0f / sampleSize;
+		vecs[ 1 ][ 2 ] = 1.0f / sampleSize;
+	}
+	
+	/* check for bogus axis */
+	if( faxis[ axisNum ] == 0.0f )
+	{
+		Sys_Printf( "WARNING: ProjectSurfaceLightmap: Chose a 0 valued axis\n" );
+		lm->w = lm->h = 0;
+		return qfalse;
+	}
+	
+	/* store the axis number in the lightmap */
+	lm->axisNum = axisNum;
+	
+	/* walk the list of surfaces on this raw lightmap */
+	for( n = 0; n < lm->numLightSurfaces; n++ )
+	{
+		/* get surface */
+		num2 = lightSurfaces[ lm->firstLightSurface + n ];
+		ds2 = &bspDrawSurfaces[ num2 ];
+		info2 = &surfaceInfos[ num2 ];
+		verts = &yDrawVerts[ ds2->firstVert ];
+		
+		/* set the lightmap texture coordinates in yDrawVerts in [0, superSample * lm->customWidth] space */
+		for( i = 0; i < ds2->numVerts; i++ )
+		{
+			VectorSubtract( verts[ i ].xyz, origin, delta );
+			s = DotProduct( delta, vecs[ 0 ] ) + 0.5f;
+			t = DotProduct( delta, vecs[ 1 ] ) + 0.5f;
+			verts[ i ].lightmap[ 0 ][ 0 ] = s * superSample;
+			verts[ i ].lightmap[ 0 ][ 1 ] = t * superSample;
+			
+			if( s > (float) lm->w || t > (float) lm->h )
+			{
+				Sys_FPrintf( SYS_VRB, "WARNING: Lightmap texture coords out of range: S %1.4f > %3d || T %1.4f > %3d\n",
+					s, lm->w, t, lm->h );
+			}
+		}
+	}
+	
+	/* get first drawsurface */
+	num2 = lightSurfaces[ lm->firstLightSurface ];
+	ds2 = &bspDrawSurfaces[ num2 ];
+	info2 = &surfaceInfos[ num2 ];
+	verts = &yDrawVerts[ ds2->firstVert ];
+	
+	/* calculate lightmap origin */
+	if( VectorLength( ds2->lightmapVecs[ 2 ] ) )
+		VectorCopy( ds2->lightmapVecs[ 2 ], plane );
+	else
+		VectorCopy( lm->axis, plane );
+	plane[ 3 ] = DotProduct( verts[ 0 ].xyz, plane );
+	
+	VectorCopy( origin, lm->origin );
+	d = DotProduct( lm->origin, plane ) - plane[ 3 ];
+	d /= plane[ axisNum ];
+	lm->origin[ axisNum ] -= d;
+	
+	/* legacy support */
+	VectorCopy( lm->origin, ds->lightmapOrigin );
+	
+	/* for planar surfaces, create lightmap vectors for st->xyz conversion */
+	if( VectorLength( ds->lightmapVecs[ 2 ] ) || 1 )	/* ydnar: can't remember what exactly i was thinking here... */
+	{
+		/* allocate space for the vectors */
+		lm->vecs = safe_malloc( 3 * sizeof( vec3_t ) );
+		memset( lm->vecs, 0, 3 * sizeof( vec3_t ) );
+		VectorCopy( ds->lightmapVecs[ 2 ], lm->vecs[ 2 ] );
+		
+		/* project stepped lightmap blocks and subtract to get planevecs */
+		for( i = 0; i < 2; i++ )
+		{
+			len = VectorNormalize( vecs[ i ], normalized );
+			VectorScale( normalized, (1.0 / len), lm->vecs[ i ] );
+			d = DotProduct( lm->vecs[ i ], plane );
+			d /= plane[ axisNum ];
+			lm->vecs[ i ][ axisNum ] -= d;
+		}
+	}
+	else
+	{
+		/* lightmap vectors are useless on a non-planar surface */
+		lm->vecs = NULL;
+	}
+	
+	/* add to counts */
+	if( ds->surfaceType == MST_PATCH )
+	{
+		numPatchesLightmapped++;
+		if( lm->plane != NULL )
+			numPlanarPatchesLightmapped++;
+	}
+	else
+	{
+		if( lm->plane != NULL )
+			numPlanarsLightmapped++;
+		else
+			numNonPlanarsLightmapped++;
+	}
+	
+	/* return */
+	return qtrue;
+}
+
+
+
+/*
+CompareSurfaceInfo()
+compare function for qsort()
+*/
+
+static int CompareSurfaceInfo( const void *a, const void *b )
+{
+	surfaceInfo_t	*aInfo, *bInfo;
+	int				i;
+	
+
+	/* get surface info */
+	aInfo = &surfaceInfos[ *((int*) a) ];
+	bInfo = &surfaceInfos[ *((int*) b) ];
+	
+	/* model first */
+	if( aInfo->model < bInfo->model )
+		return 1;
+	else if( aInfo->model > bInfo->model )
+		return -1;
+	
+	/* then lightmap status */
+	if( aInfo->hasLightmap < bInfo->hasLightmap )
+		return 1;
+	else if( aInfo->hasLightmap > bInfo->hasLightmap )
+		return -1;
+	
+	/* then lightmap sample size */
+	if( aInfo->sampleSize < bInfo->sampleSize )
+		return 1;
+	else if( aInfo->sampleSize > bInfo->sampleSize )
+		return -1;
+	
+	/* then lightmap axis */
+	for( i = 0; i < 3; i++ )
+	{
+		if( aInfo->axis[ i ] < bInfo->axis[ i ] )
+			return 1;
+		else if( aInfo->axis[ i ] > bInfo->axis[ i ] )
+			return -1;
+	}
+	
+	/* then plane */
+	if( aInfo->plane == NULL && bInfo->plane != NULL )
+		return 1;
+	else if( aInfo->plane != NULL && bInfo->plane == NULL )
+		return -1;
+	else if( aInfo->plane != NULL && bInfo->plane != NULL )
+	{
+		for( i = 0; i < 4; i++ )
+		{
+			if( aInfo->plane[ i ] < bInfo->plane[ i ] )
+				return 1;
+			else if( aInfo->plane[ i ] > bInfo->plane[ i ] )
+				return -1;
+		}
+	}
+	
+	/* then position in world */
+	for( i = 0; i < 3; i++ )
+	{
+		if( aInfo->mins[ i ] < bInfo->mins[ i ] )
+			return 1;
+		else if( aInfo->mins[ i ] > bInfo->mins[ i ] )
+			return -1;
+	}
+	
+	/* these are functionally identical (this should almost never happen) */
+	return 0;
+}
+
+
+
+/*
+SetupSurfaceLightmaps()
+allocates lightmaps for every surface in the bsp that needs one
+this depends on yDrawVerts being allocated
+*/
+
+void SetupSurfaceLightmaps( void )
+{
+	int					i, j, k, s,num, num2;
+	bspModel_t			*model;
+	bspLeaf_t			*leaf;
+	bspDrawSurface_t	*ds, *ds2;
+	surfaceInfo_t		*info, *info2;
+	rawLightmap_t		*lm;
+	qboolean			added;
+	vec3_t				mapSize, entityOrigin;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- SetupSurfaceLightmaps ---\n");
+	
+	/* determine supersample amount */
+	if( superSample < 1 )
+		superSample = 1;
+	else if( superSample > 8 )
+	{
+		Sys_Printf( "WARNING: Insane supersampling amount (%d) detected.\n", superSample );
+		superSample = 8;
+	}
+	
+	/* clear map bounds */
+	ClearBounds( mapMins, mapMaxs );
+	
+	/* allocate a list of surface clusters */
+	numSurfaceClusters = 0;
+	maxSurfaceClusters = numBSPLeafSurfaces;
+	surfaceClusters = safe_malloc( maxSurfaceClusters * sizeof( *surfaceClusters ) );
+	memset( surfaceClusters, 0, maxSurfaceClusters * sizeof( *surfaceClusters ) );
+	
+	/* allocate a list for per-surface info */
+	surfaceInfos = safe_malloc( numBSPDrawSurfaces * sizeof( *surfaceInfos ) );
+	memset( surfaceInfos, 0, numBSPDrawSurfaces * sizeof( *surfaceInfos ) );
+	for( i = 0; i < numBSPDrawSurfaces; i++ )
+		surfaceInfos[ i ].childSurfaceNum = -1;
+	
+	/* allocate a list of surface indexes to be sorted */
+	sortSurfaces = safe_malloc( numBSPDrawSurfaces * sizeof( int ) );
+	memset( sortSurfaces, 0, numBSPDrawSurfaces * sizeof( int ) );
+	
+	/* walk each model in the bsp */
+	for( i = 0; i < numBSPModels; i++ )
+	{
+		/* get model */
+		model = &bspModels[ i ];
+		
+		/* walk the list of surfaces in this model and fill out the info structs */
+		for( j = 0; j < model->numBSPSurfaces; j++ )
+		{
+			/* make surface index */
+			num = model->firstBSPSurface + j;
+			
+			/* copy index to sort list */
+			sortSurfaces[ num ] = num;
+			
+			/* get surface and info */
+			ds = &bspDrawSurfaces[ num ];
+			info = &surfaceInfos[ num ];
+			
+			/* set entity origin */
+			if( ds->numVerts > 0 )
+				VectorSubtract( yDrawVerts[ ds->firstVert ].xyz, bspDrawVerts[ ds->firstVert ].xyz, entityOrigin );
+			else
+				VectorClear( entityOrigin );
+			
+			/* basic setup */
+			info->model = model;
+			info->lm = NULL;
+			info->plane = NULL;
+			info->firstSurfaceCluster = numSurfaceClusters;
+			
+			/* get extra data */
+			info->si = GetSurfaceExtraShaderInfo( num );
+			if( info->si == NULL )
+				info->si = ShaderInfoForShader( bspShaders[ ds->shaderNum ].shader );
+			info->parentSurfaceNum = GetSurfaceExtraParentSurfaceNum( num );
+			info->entityNum = GetSurfaceExtraEntityNum( num );
+			info->castShadows = GetSurfaceExtraCastShadows( num );
+			info->recvShadows = GetSurfaceExtraRecvShadows( num );
+			info->sampleSize = GetSurfaceExtraSampleSize( num );
+			info->longestCurve = GetSurfaceExtraLongestCurve( num );
+			info->patchIterations = IterationsForCurve( info->longestCurve, patchSubdivisions );
+			GetSurfaceExtraLightmapAxis( num, info->axis );
+			
+			/* mark parent */
+			if( info->parentSurfaceNum >= 0 )
+				surfaceInfos[ info->parentSurfaceNum ].childSurfaceNum = j;
+			
+			/* determine surface bounds */
+			ClearBounds( info->mins, info->maxs );
+			for( k = 0; k < ds->numVerts; k++ )
+			{
+				AddPointToBounds( yDrawVerts[ ds->firstVert + k ].xyz, mapMins, mapMaxs );
+				AddPointToBounds( yDrawVerts[ ds->firstVert + k ].xyz, info->mins, info->maxs );
+			}
+			
+			/* find all the bsp clusters the surface falls into */
+			for( k = 0; k < numBSPLeafs; k++ )
+			{
+				/* get leaf */
+				leaf = &bspLeafs[ k ];
+				
+				/* test bbox */
+				if( leaf->mins[ 0 ] > info->maxs[ 0 ] || leaf->maxs[ 0 ] < info->mins[ 0 ] ||
+					leaf->mins[ 1 ] > info->maxs[ 1 ] || leaf->maxs[ 1 ] < info->mins[ 1 ] ||
+					leaf->mins[ 2 ] > info->maxs[ 2 ] || leaf->maxs[ 2 ] < info->mins[ 2 ] )
+					continue;
+				
+				/* test leaf surfaces */
+				for( s = 0; s < leaf->numBSPLeafSurfaces; s++ )
+				{
+					if( bspLeafSurfaces[ leaf->firstBSPLeafSurface + s ] == num )
+					{
+						if( numSurfaceClusters >= maxSurfaceClusters )
+							Error( "maxSurfaceClusters exceeded" );
+						surfaceClusters[ numSurfaceClusters ] = leaf->cluster;
+						numSurfaceClusters++;
+						info->numSurfaceClusters++;
+					}
+				}
+			}
+			
+			/* determine if surface is planar */
+			if( VectorLength( ds->lightmapVecs[ 2 ] ) > 0.0f )
+			{
+				/* make a plane */
+				info->plane = safe_malloc( 4 * sizeof( float ) );
+				VectorCopy( ds->lightmapVecs[ 2 ], info->plane );
+				info->plane[ 3 ] = DotProduct( yDrawVerts[ ds->firstVert ].xyz, info->plane );
+			}
+			
+			/* determine if surface requires a lightmap */
+			if( ds->surfaceType == MST_TRIANGLE_SOUP ||
+				ds->surfaceType == MST_FOLIAGE ||
+				(info->si->compileFlags & C_VERTEXLIT) )
+				numSurfsVertexLit++;
+			else
+			{
+				numSurfsLightmapped++;
+				info->hasLightmap = qtrue;
+			}
+		}
+	}
+	
+	/* find longest map distance */
+	VectorSubtract( mapMaxs, mapMins, mapSize );
+	maxMapDistance = VectorLength( mapSize );
+	
+	/* sort the surfaces info list */
+	qsort( sortSurfaces, numBSPDrawSurfaces, sizeof( int ), CompareSurfaceInfo );
+	
+	/* allocate a list of surfaces that would go into raw lightmaps */
+	numLightSurfaces = 0;
+	lightSurfaces = safe_malloc( numSurfsLightmapped * sizeof( int ) );
+	memset( lightSurfaces, 0, numSurfsLightmapped * sizeof( int ) );
+	
+	/* allocate a list of raw lightmaps */
+	numRawSuperLuxels = 0;
+	numRawLightmaps = 0;
+	rawLightmaps = safe_malloc( numSurfsLightmapped * sizeof( *rawLightmaps ) );
+	memset( rawLightmaps, 0, numSurfsLightmapped * sizeof( *rawLightmaps ) );
+	
+	/* walk the list of sorted surfaces */
+	for( i = 0; i < numBSPDrawSurfaces; i++ )
+	{
+		/* get info and attempt early out */
+		num = sortSurfaces[ i ];
+		ds = &bspDrawSurfaces[ num ];
+		info = &surfaceInfos[ num ];
+		if( info->hasLightmap == qfalse || info->lm != NULL || info->parentSurfaceNum >= 0 )
+			continue;
+		
+		/* allocate a new raw lightmap */
+		lm = &rawLightmaps[ numRawLightmaps ];
+		numRawLightmaps++;
+		
+		/* set it up */
+		lm->splotchFix = info->si->splotchFix;
+		lm->firstLightSurface = numLightSurfaces;
+		lm->numLightSurfaces = 0;
+		lm->sampleSize = info->sampleSize;
+		lm->actualSampleSize = info->sampleSize;
+		lm->entityNum = info->entityNum;
+		lm->recvShadows = info->recvShadows;
+		lm->gamma = info->si->lmGamma;
+		lm->filterRadius = info->si->lmFilterRadius;
+		VectorCopy( info->axis, lm->axis );
+		lm->plane = info->plane;	
+		VectorCopy( info->mins, lm->mins );
+		VectorCopy( info->maxs, lm->maxs );
+		
+		lm->customWidth = info->si->lmCustomWidth;
+		lm->customHeight = info->si->lmCustomHeight;
+		
+		/* add the surface to the raw lightmap */
+		AddSurfaceToRawLightmap( num, lm );
+		info->lm = lm;
+		
+		/* do an exhaustive merge */
+		added = qtrue;
+		while( added )
+		{
+			/* walk the list of surfaces again */
+			added = qfalse;
+			for( j = i + 1; j < numBSPDrawSurfaces && lm->finished == qfalse; j++ )
+			{
+				/* get info and attempt early out */
+				num2 = sortSurfaces[ j ];
+				ds2 = &bspDrawSurfaces[ num2 ];
+				info2 = &surfaceInfos[ num2 ];
+				if( info2->hasLightmap == qfalse || info2->lm != NULL )
+					continue;
+				
+				/* add the surface to the raw lightmap */
+				if( AddSurfaceToRawLightmap( num2, lm ) )
+				{
+					info2->lm = lm;
+					added = qtrue;
+				}
+				else
+				{
+					/* back up one */
+					lm->numLightSurfaces--;
+					numLightSurfaces--;
+				}
+			}
+		}
+		
+		/* finish the lightmap and allocate the various buffers */
+		FinishRawLightmap( lm );
+	}
+	
+	/* allocate vertex luxel storage */
+	for( k = 0; k < MAX_LIGHTMAPS; k++ )
+	{
+		vertexLuxels[ k ] = safe_malloc( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) ); 
+		memset( vertexLuxels[ k ], 0, numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
+		radVertexLuxels[ k ] = safe_malloc( numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
+		memset( radVertexLuxels[ k ], 0, numBSPDrawVerts * VERTEX_LUXEL_SIZE * sizeof( float ) );
+	}
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d surfaces\n", numBSPDrawSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d raw lightmaps\n", numRawLightmaps );
+	Sys_FPrintf( SYS_VRB, "%9d surfaces vertex lit\n", numSurfsVertexLit );
+	Sys_FPrintf( SYS_VRB, "%9d surfaces lightmapped\n", numSurfsLightmapped );
+	Sys_FPrintf( SYS_VRB, "%9d planar surfaces lightmapped\n", numPlanarsLightmapped );
+	Sys_FPrintf( SYS_VRB, "%9d non-planar surfaces lightmapped\n", numNonPlanarsLightmapped );
+	Sys_FPrintf( SYS_VRB, "%9d patches lightmapped\n", numPatchesLightmapped );
+	Sys_FPrintf( SYS_VRB, "%9d planar patches lightmapped\n", numPlanarPatchesLightmapped );
+}
+
+
+
+/*
+StitchSurfaceLightmaps()
+stitches lightmap edges
+2002-11-20 update: use this func only for stitching nonplanar patch lightmap seams
+*/
+
+#define MAX_STITCH_CANDIDATES	32
+#define MAX_STITCH_LUXELS		64
+
+void StitchSurfaceLightmaps( void )
+{
+	int				i, j, x, y, x2, y2, *cluster, *cluster2,
+					numStitched, numCandidates, numLuxels, f, fOld, start;
+	rawLightmap_t	*lm, *a, *b, *c[ MAX_STITCH_CANDIDATES ];
+	float			*luxel, *luxel2, *origin, *origin2, *normal, *normal2, 
+					sampleSize, average[ 3 ], totalColor, ootc, *luxels[ MAX_STITCH_LUXELS ];
+	
+	
+	/* disabled for now */
+	return;
+	
+	/* note it */
+	Sys_Printf( "--- StitchSurfaceLightmaps ---\n");
+
+	/* init pacifier */
+	fOld = -1;
+	start = I_FloatTime();
+	
+	/* walk the list of raw lightmaps */
+	numStitched = 0;
+	for( i = 0; i < numRawLightmaps; i++ )
+	{
+		/* print pacifier */
+		f = 10 * i / numRawLightmaps;
+		if( f != fOld )
+		{
+			fOld = f;
+			Sys_Printf( "%i...", f );
+		}
+		
+		/* get lightmap a */
+		a = &rawLightmaps[ i ];
+		
+		/* walk rest of lightmaps */
+		numCandidates = 0;
+		for( j = i + 1; j < numRawLightmaps && numCandidates < MAX_STITCH_CANDIDATES; j++ )
+		{
+			/* get lightmap b */
+			b = &rawLightmaps[ j ];
+			
+			/* test bounding box */
+			if( a->mins[ 0 ] > b->maxs[ 0 ] || a->maxs[ 0 ] < b->mins[ 0 ] ||
+				a->mins[ 1 ] > b->maxs[ 1 ] || a->maxs[ 1 ] < b->mins[ 1 ] ||
+				a->mins[ 2 ] > b->maxs[ 2 ] || a->maxs[ 2 ] < b->mins[ 2 ] )
+				continue;
+			
+			/* add candidate */
+			c[ numCandidates++ ] = b;
+		}
+		
+		/* walk luxels */
+		for( y = 0; y < a->sh; y++ )
+		{
+			for( x = 0; x < a->sw; x++ )
+			{
+				/* ignore unmapped/unlit luxels */
+				lm = a;
+				cluster = SUPER_CLUSTER( x, y );
+				if( *cluster == CLUSTER_UNMAPPED )
+					continue;
+				luxel = SUPER_LUXEL( 0, x, y );
+				if( luxel[ 3 ] <= 0.0f )
+					continue;
+				
+				/* get particulars */
+				origin = SUPER_ORIGIN( x, y );
+				normal = SUPER_NORMAL( x, y );
+				
+				/* walk candidate list */
+				for( j = 0; j < numCandidates; j++ )
+				{
+					/* get candidate */
+					b = c[ j ];
+					lm = b;
+					
+					/* set samplesize to the smaller of the pair */
+					sampleSize = 0.5f * (a->actualSampleSize < b->actualSampleSize ? a->actualSampleSize : b->actualSampleSize);
+					
+					/* test bounding box */
+					if( origin[ 0 ] < (b->mins[ 0 ] - sampleSize) || (origin[ 0 ] > b->maxs[ 0 ] + sampleSize) ||
+						origin[ 1 ] < (b->mins[ 1 ] - sampleSize) || (origin[ 1 ] > b->maxs[ 1 ] + sampleSize) ||
+						origin[ 2 ] < (b->mins[ 2 ] - sampleSize) || (origin[ 2 ] > b->maxs[ 2 ] + sampleSize) )
+						continue;
+					
+					/* walk candidate luxels */
+					VectorClear( average );
+					numLuxels = 0;
+					totalColor = 0.0f;
+					for( y2 = 0; y2 < b->sh && numLuxels < MAX_STITCH_LUXELS; y2++ )
+					{
+						for( x2 = 0; x2 < b->sw && numLuxels < MAX_STITCH_LUXELS; x2++ )
+						{
+							/* ignore same luxels */
+							if( a == b && abs( x - x2 ) <= 1 && abs( y - y2 ) <= 1 )
+								continue;
+							
+							/* ignore unmapped/unlit luxels */
+							cluster2 = SUPER_CLUSTER( x2, y2 );
+							if( *cluster2 == CLUSTER_UNMAPPED )
+								continue;
+							luxel2 = SUPER_LUXEL( 0, x2, y2 );
+							if( luxel2[ 3 ] <= 0.0f )
+								continue;
+							
+							/* get particulars */
+							origin2 = SUPER_ORIGIN( x2, y2 );
+							normal2 = SUPER_NORMAL( x2, y2 );
+							
+							/* test normal */
+							if( DotProduct( normal, normal2 ) < 0.5f )
+								continue;
+							
+							/* test bounds */
+							if( fabs( origin[ 0 ] - origin2[ 0 ] ) > sampleSize ||
+								fabs( origin[ 1 ] - origin2[ 1 ] ) > sampleSize ||
+								fabs( origin[ 2 ] - origin2[ 2 ] ) > sampleSize )
+								continue;
+							
+							/* add luxel */
+							//%	VectorSet( luxel2, 255, 0, 255 );
+							luxels[ numLuxels++ ] = luxel2;
+							VectorAdd( average, luxel2, average );
+							totalColor += luxel2[ 3 ];
+						}
+					}
+					
+					/* early out */
+					if( numLuxels == 0 )
+						continue;
+					
+					/* scale average */
+					ootc = 1.0f / totalColor;
+					VectorScale( average, ootc, luxel );
+					luxel[ 3 ] = 1.0f;
+					numStitched++;
+				}
+			}
+		}
+	}
+	
+	/* emit statistics */
+	Sys_Printf( " (%i)\n", (int) (I_FloatTime() - start) );
+	Sys_FPrintf( SYS_VRB, "%9d luxels stitched\n", numStitched );
+}
+
+
+
+/*
+CompareBSPLuxels()
+compares two surface lightmaps' bsp luxels, ignoring occluded luxels
+*/
+
+#define LUXEL_TOLERANCE		0.0025
+#define LUXEL_COLOR_FRAC	0.001302083	/* 1 / 3 / 256 */
+
+static qboolean CompareBSPLuxels( rawLightmap_t *a, int aNum, rawLightmap_t *b, int bNum )
+{
+	rawLightmap_t	*lm;
+	int				x, y;
+	double			delta, total, rd, gd, bd;
+	float			*aLuxel, *bLuxel;
+	
+	
+	/* styled lightmaps will never be collapsed to non-styled lightmaps when there is _minlight */
+	if( (minLight[ 0 ] || minLight[ 1 ] || minLight[ 2 ]) &&
+		((aNum == 0 && bNum != 0) || (aNum != 0 && bNum == 0)) )
+		return qfalse;
+	
+	/* compare */
+	if( a->w != b->w || a->h != b->h ||
+		a->customWidth != b->customWidth || a->customHeight != b->customHeight ||
+		a->gamma != b->gamma ||
+		a->bspLuxels[ aNum ] == NULL || b->bspLuxels[ bNum ] == NULL )
+		return qfalse;
+	
+	/* compare luxels */
+	delta = 0.0;
+	total = 0.0;
+	for( y = 0; y < a->h; y++ )
+	{
+		for( x = 0; x < a->w; x++ )
+		{
+			/* increment total */
+			total += 1.0;
+			
+			/* get luxels */
+			lm = a;	aLuxel = BSP_LUXEL( aNum, x, y );
+			lm = b;	bLuxel = BSP_LUXEL( bNum, x, y );
+			
+			/* ignore unused luxels */
+			if( aLuxel[ 0 ] < 0 || bLuxel[ 0 ] < 0 )
+				continue;
+			
+			/* get deltas */
+			rd = fabs( aLuxel[ 0 ] - bLuxel[ 0 ] );
+			gd = fabs( aLuxel[ 1 ] - bLuxel[ 1 ] );
+			bd = fabs( aLuxel[ 2 ] - bLuxel[ 2 ] );
+			
+			/* 2003-09-27: compare individual luxels */
+			if( rd > 3.0 || gd > 3.0 || bd > 3.0 )
+				return qfalse;
+			
+			/* compare (fixme: take into account perceptual differences) */
+			delta += rd * LUXEL_COLOR_FRAC;
+			delta += gd * LUXEL_COLOR_FRAC;
+			delta += bd * LUXEL_COLOR_FRAC;
+			
+			/* is the change too high? */
+			if( total > 0.0 && ((delta / total) > LUXEL_TOLERANCE) )
+				return qfalse;
+		}
+	}
+	
+	/* made it this far, they must be identical (or close enough) */
+	return qtrue;
+}
+
+
+
+/*
+MergeBSPLuxels()
+merges two surface lightmaps' bsp luxels, overwriting occluded luxels
+*/
+
+static void MergeBSPLuxels( rawLightmap_t *a, int aNum, rawLightmap_t *b, int bNum )
+{
+	rawLightmap_t	*lm;
+	int				x, y;
+	float			luxel[ 3 ], *aLuxel, *bLuxel;
+	
+	
+	/* compare */
+	if( a->w != b->w || a->h != b->h ||
+		a->customWidth != b->customWidth || a->customHeight != b->customHeight ||
+		a->gamma != b->gamma ||
+		a->bspLuxels[ aNum ] == NULL || b->bspLuxels[ bNum ] == NULL )
+		return;
+	
+	/* merge luxels */
+	for( y = 0; y < a->h; y++ )
+	{
+		for( x = 0; x < a->w; x++ )
+		{
+			/* get luxels */
+			lm = a;	aLuxel = BSP_LUXEL( aNum, x, y );
+			lm = b;	bLuxel = BSP_LUXEL( bNum, x, y );
+			
+			/* handle occlusion mismatch */
+			if( aLuxel[ 0 ] < 0.0f )
+				VectorCopy( bLuxel, aLuxel );
+			else if( bLuxel[ 0 ] < 0.0f )
+				VectorCopy( aLuxel, bLuxel );
+			else
+			{
+				/* average */
+				VectorAdd( aLuxel, bLuxel, luxel );
+				VectorScale( luxel, 0.5f, luxel );
+				
+				/* debugging code */
+				//%	luxel[ 2 ] += 64.0f;
+				
+				/* copy to both */
+				VectorCopy( luxel, aLuxel );
+				VectorCopy( luxel, bLuxel );
+			}
+		}
+	}
+}
+
+
+
+/*
+ApproximateLuxel()
+determines if a single luxel is can be approximated with the interpolated vertex rgba
+*/
+
+static qboolean ApproximateLuxel( rawLightmap_t *lm, bspDrawVert_t *dv )
+{
+	int		i, x, y, d, lightmapNum;
+	float	*luxel;
+	vec3_t	color, vertexColor;
+	byte	cb[ 4 ], vcb[ 4 ];
+	
+	
+	/* find luxel xy coords */
+	x = dv->lightmap[ 0 ][ 0 ] / superSample;
+	y = dv->lightmap[ 0 ][ 1 ] / superSample;
+	if( x < 0 )
+		x = 0;
+	else if( x >= lm->w )
+		x = lm->w - 1;
+	if( y < 0 )
+		y = 0;
+	else if( y >= lm->h )
+		y = lm->h - 1;
+	
+	/* walk list */
+	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+	{
+		/* early out */
+		if( lm->styles[ lightmapNum ] == LS_NONE )
+			continue;
+		
+		/* get luxel */
+		luxel = BSP_LUXEL( lightmapNum, x, y );
+		
+		/* ignore occluded luxels */
+		if( luxel[ 0 ] < 0.0f || luxel[ 1 ] < 0.0f || luxel[ 2 ] < 0.0f )
+			return qtrue;
+		
+		/* copy, set min color and compare */
+		VectorCopy( luxel, color );
+		VectorCopy( dv->color[ 0 ], vertexColor );
+
+		/* styles are not affected by minlight */
+		if( lightmapNum == 0 )
+		{
+			for( i = 0; i < 3; i++ )
+			{
+				/* set min color */
+				if( color[ i ] < minLight[ i ] )
+					color[ i ] = minLight[ i ];
+				if( vertexColor[ i ] < minLight[ i ] )	/* note NOT minVertexLight */
+					vertexColor[ i ] = minLight[ i ];
+			}
+		}
+		
+		/* set to bytes */
+		ColorToBytes( color, cb, 1.0f );
+		ColorToBytes( vertexColor, vcb, 1.0f );
+		
+		/* compare */
+		for( i = 0; i < 3; i++ )
+		{
+			d = cb[ i ] - vcb[ i ];
+			if( d < 0 )
+				d *= -1;
+			if( d > approximateTolerance )
+				return qfalse;
+		}
+	}
+	
+	/* close enough for the girls i date */
+	return qtrue;
+}
+
+
+
+/*
+ApproximateTriangle()
+determines if a single triangle can be approximated with vertex rgba
+*/
+
+static qboolean ApproximateTriangle_r( rawLightmap_t *lm, bspDrawVert_t *dv[ 3 ] )
+{
+	bspDrawVert_t	mid, *dv2[ 3 ];
+	int				max;
+	
+	
+	/* approximate the vertexes */
+	if( ApproximateLuxel( lm, dv[ 0 ] ) == qfalse )
+		return qfalse;
+	if( ApproximateLuxel( lm, dv[ 1 ] ) == qfalse )
+		return qfalse;
+	if( ApproximateLuxel( lm, dv[ 2 ] ) == qfalse )
+		return qfalse;
+	
+	/* subdivide calc */
+	{
+		int			i;
+		float		dx, dy, dist, maxDist;
+		
+		
+		/* find the longest edge and split it */
+		max = -1;
+		maxDist = 0;
+		for( i = 0; i < 3; i++ )
+		{
+			dx = dv[ i ]->lightmap[ 0 ][ 0 ] - dv[ (i + 1) % 3 ]->lightmap[ 0 ][ 0 ];
+			dy = dv[ i ]->lightmap[ 0 ][ 1 ] - dv[ (i + 1) % 3 ]->lightmap[ 0 ][ 1 ];
+			dist = sqrt( (dx * dx) + (dy * dy) );
+			if( dist > maxDist )
+			{
+				maxDist = dist;
+				max = i;
+			}
+		}
+		
+		/* try to early out */
+		if( i < 0 || maxDist < subdivideThreshold )
+			return qtrue;
+	}
+
+	/* split the longest edge and map it */
+	LerpDrawVert( dv[ max ], dv[ (max + 1) % 3 ], &mid );
+	if( ApproximateLuxel( lm, &mid ) == qfalse )
+		return qfalse;
+	
+	/* recurse to first triangle */
+	VectorCopy( dv, dv2 );
+	dv2[ max ] = &mid;
+	if( ApproximateTriangle_r( lm, dv2 ) == qfalse )
+		return qfalse;
+	
+	/* recurse to second triangle */
+	VectorCopy( dv, dv2 );
+	dv2[ (max + 1) % 3 ] = &mid;
+	return ApproximateTriangle_r( lm, dv2 );
+}
+
+
+
+/*
+ApproximateLightmap()
+determines if a raw lightmap can be approximated sufficiently with vertex colors
+*/
+
+static qboolean ApproximateLightmap( rawLightmap_t *lm )
+{
+	int					n, num, i, x, y, pw[ 5 ], r;
+	bspDrawSurface_t	*ds;
+	surfaceInfo_t		*info;
+	mesh_t				src, *subdivided, *mesh;
+	bspDrawVert_t		*verts, *dv[ 3 ];
+	qboolean			approximated;
+	
+	
+	/* approximating? */
+	if( approximateTolerance <= 0 )
+		return qfalse;
+	
+	/* test for jmonroe */
+	#if 0
+		/* don't approx lightmaps with styled twins */
+		if( lm->numStyledTwins > 0 )
+			return qfalse;
+		
+		/* don't approx lightmaps with styles */
+		for( i = 1; i < MAX_LIGHTMAPS; i++ )
+		{
+			if( lm->styles[ i ] != LS_NONE )
+				return qfalse;
+		}
+	#endif
+	
+	/* assume reduced until shadow detail is found */
+	approximated = qtrue;
+	
+	/* walk the list of surfaces on this raw lightmap */
+	for( n = 0; n < lm->numLightSurfaces; n++ )
+	{
+		/* get surface */
+		num = lightSurfaces[ lm->firstLightSurface + n ];
+		ds = &bspDrawSurfaces[ num ];
+		info = &surfaceInfos[ num ];
+		
+		/* bail if lightmap doesn't match up */
+		if( info->lm != lm )
+			continue;
+		
+		/* assume reduced initially */
+		info->approximated = qtrue;
+		
+		/* assume that surfaces whose bounding boxes is smaller than 2x samplesize will be forced to vertex */
+		if( (info->maxs[ 0 ] - info->mins[ 0 ]) <= (2.0f * info->sampleSize) &&
+			(info->maxs[ 1 ] - info->mins[ 1 ]) <= (2.0f * info->sampleSize) &&
+			(info->maxs[ 2 ] - info->mins[ 2 ]) <= (2.0f * info->sampleSize) )
+		{
+			numSurfsVertexForced++;
+			continue;
+		}
+		
+		/* handle the triangles */
+		switch( ds->surfaceType )
+		{
+			case MST_PLANAR:
+				/* get verts */
+				verts = yDrawVerts + ds->firstVert;
+				
+				/* map the triangles */
+				for( i = 0; i < ds->numIndexes && info->approximated; i += 3 )
+				{
+					dv[ 0 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i ] ];
+					dv[ 1 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 1 ] ];
+					dv[ 2 ] = &verts[ bspDrawIndexes[ ds->firstIndex + i + 2 ] ];
+					info->approximated = ApproximateTriangle_r( lm, dv );
+				}
+				break;
+			
+			case MST_PATCH:
+				/* make a mesh from the drawsurf */ 
+				src.width = ds->patchWidth;
+				src.height = ds->patchHeight;
+				src.verts = &yDrawVerts[ ds->firstVert ];
+				//%	subdivided = SubdivideMesh( src, 8, 512 );
+				subdivided = SubdivideMesh2( src, info->patchIterations );
+
+				/* fit it to the curve and remove colinear verts on rows/columns */
+				PutMeshOnCurve( *subdivided );
+				mesh = RemoveLinearMeshColumnsRows( subdivided );
+				FreeMesh( subdivided );
+				
+				/* get verts */
+				verts = mesh->verts;
+				
+				/* map the mesh quads */
+				for( y = 0; y < (mesh->height - 1) && info->approximated; y++ )
+				{
+					for( x = 0; x < (mesh->width - 1) && info->approximated; x++ )
+					{
+						/* set indexes */
+						pw[ 0 ] = x + (y * mesh->width);
+						pw[ 1 ] = x + ((y + 1) * mesh->width);
+						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+						pw[ 3 ] = x + 1 + (y * mesh->width);
+						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+						
+						/* set radix */
+						r = (x + y) & 1;
+
+						/* get drawverts and map first triangle */
+						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
+						dv[ 1 ] = &verts[ pw[ r + 1 ] ];
+						dv[ 2 ] = &verts[ pw[ r + 2 ] ];
+						info->approximated = ApproximateTriangle_r( lm, dv );
+						
+						/* get drawverts and map second triangle */
+						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
+						dv[ 1 ] = &verts[ pw[ r + 2 ] ];
+						dv[ 2 ] = &verts[ pw[ r + 3 ] ];
+						if( info->approximated )
+							info->approximated = ApproximateTriangle_r( lm, dv );
+					}
+				}
+				
+				/* free the mesh */
+				FreeMesh( mesh );
+				break;
+			
+			default:
+				break;
+		}
+		
+		/* reduced? */
+		if( info->approximated == qfalse )
+			approximated = qfalse;
+		else
+			numSurfsVertexApproximated++;
+	}
+	
+	/* return */
+	return approximated;
+}
+
+
+
+/*
+TestOutLightmapStamp()
+tests a stamp on a given lightmap for validity
+*/
+
+static qboolean TestOutLightmapStamp( rawLightmap_t *lm, int lightmapNum, outLightmap_t *olm, int x, int y )
+{
+	int			sx, sy, ox, oy, offset;
+	float		*luxel;
+
+	
+	/* bounds check */
+	if( x < 0 || y < 0 || (x + lm->w) > olm->customWidth || (y + lm->h) > olm->customHeight )
+		return qfalse;
+	
+	/* test the stamp */
+	for( sy = 0; sy < lm->h; sy++ )
+	{
+		for( sx = 0; sx < lm->w; sx++ )
+		{
+			/* get luxel */
+			luxel = BSP_LUXEL( lightmapNum, sx, sy );
+			if( luxel[ 0 ] < 0.0f )
+				continue;
+			
+			/* get bsp lightmap coords and test */
+			ox = x + sx;
+			oy = y + sy;
+			offset = (oy * olm->customWidth) + ox;
+			if( olm->lightBits[ offset >> 3 ] & (1 << (offset & 7)) )
+				return qfalse;
+		}
+	}
+	
+	/* stamp is empty */
+	return qtrue;
+}
+
+
+
+/*
+SetupOutLightmap()
+sets up an output lightmap
+*/
+
+static void SetupOutLightmap( rawLightmap_t *lm, outLightmap_t *olm )
+{
+	/* dummy check */
+	if( lm == NULL || olm == NULL )
+		return;
+	
+	/* is this a "normal" bsp-stored lightmap? */
+	if( (lm->customWidth == LIGHTMAP_WIDTH && lm->customHeight == LIGHTMAP_HEIGHT) || externalLightmaps )
+	{
+		olm->lightmapNum = numBSPLightmaps;
+		numBSPLightmaps++;
+		
+		/* lightmaps are interleaved with light direction maps */
+		if( deluxemap )
+			numBSPLightmaps++;
+	}
+	else
+		olm->lightmapNum = -3;
+	
+	/* set external lightmap number */
+	olm->extLightmapNum = -1;
+	
+	/* set it up */
+	olm->numLightmaps = 0;
+	olm->customWidth = lm->customWidth;
+	olm->customHeight = lm->customHeight;
+	olm->freeLuxels = olm->customWidth * olm->customHeight;
+	olm->numShaders = 0;
+	
+	/* allocate buffers */
+	olm->lightBits = safe_malloc( (olm->customWidth * olm->customHeight / 8) + 8 );
+	memset( olm->lightBits, 0, (olm->customWidth * olm->customHeight / 8) + 8 );
+	olm->bspLightBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 );
+	memset( olm->bspLightBytes, 0, olm->customWidth * olm->customHeight * 3 );
+	if( deluxemap )
+	{
+		olm->bspDirBytes = safe_malloc( olm->customWidth * olm->customHeight * 3 );
+		memset( olm->bspDirBytes, 0, olm->customWidth * olm->customHeight * 3 );
+	}
+}
+
+
+
+/*
+FindOutLightmaps()
+for a given surface lightmap, find output lightmap pages and positions for it
+*/
+
+static void FindOutLightmaps( rawLightmap_t *lm )
+{
+	int					i, j, lightmapNum, xMax, yMax, x, y, sx, sy, ox, oy, offset, temp;
+	outLightmap_t		*olm;
+	surfaceInfo_t		*info;
+	float				*luxel, *deluxel;
+	vec3_t				color, direction;
+	byte				*pixel;
+	qboolean			ok;
+	
+	
+	/* set default lightmap number (-3 = LIGHTMAP_BY_VERTEX) */
+	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		lm->outLightmapNums[ lightmapNum ] = -3;
+		
+	/* can this lightmap be approximated with vertex color? */
+	if( ApproximateLightmap( lm ) )
+		return;
+	
+	/* walk list */
+	for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+	{
+		/* early out */
+		if( lm->styles[ lightmapNum ] == LS_NONE )
+			continue;
+		
+		/* don't store twinned lightmaps */
+		if( lm->twins[ lightmapNum ] != NULL )
+			continue;
+		
+		/* if this is a styled lightmap, try some normalized locations first */
+		ok = qfalse;
+		if( lightmapNum > 0 && outLightmaps != NULL )
+		{
+			/* loop twice */
+			for( j = 0; j < 2; j++ )
+			{
+				/* try identical position */
+				for( i = 0; i < numOutLightmaps; i++ )
+				{
+					/* get the output lightmap */
+					olm = &outLightmaps[ i ];
+					
+					/* simple early out test */
+					if( olm->freeLuxels < lm->used )
+						continue;
+					
+					/* don't store non-custom raw lightmaps on custom bsp lightmaps */
+					if( olm->customWidth != lm->customWidth ||
+						olm->customHeight != lm->customHeight )
+						continue;
+					
+					/* try identical */
+					if( j == 0 )
+					{
+						x = lm->lightmapX[ 0 ];
+						y = lm->lightmapY[ 0 ];
+						ok = TestOutLightmapStamp( lm, lightmapNum, olm, x, y );
+					}
+					
+					/* try shifting */
+					else
+					{
+						for( sy = -1; sy <= 1; sy++ )
+						{
+							for( sx = -1; sx <= 1; sx++ )
+							{
+								x = lm->lightmapX[ 0 ] + sx * (olm->customWidth >> 1);	//%	lm->w;
+								y = lm->lightmapY[ 0 ] + sy * (olm->customHeight >> 1);	//%	lm->h;
+								ok = TestOutLightmapStamp( lm, lightmapNum, olm, x, y );
+
+								if( ok )
+									break;
+							}
+							
+							if( ok )
+								break;
+						}
+					}
+					
+					if( ok )
+						break;
+				}
+				
+				if( ok )
+					break;
+			}
+		}
+		
+		/* try normal placement algorithm */
+		if( ok == qfalse )
+		{
+			/* reset origin */
+			x = 0;
+			y = 0;
+			
+			/* walk the list of lightmap pages */
+			for( i = 0; i < numOutLightmaps; i++ )
+			{
+				/* get the output lightmap */
+				olm = &outLightmaps[ i ];
+				
+				/* simple early out test */
+				if( olm->freeLuxels < lm->used )
+					continue;
+				
+				/* don't store non-custom raw lightmaps on custom bsp lightmaps */
+				if( olm->customWidth != lm->customWidth ||
+					olm->customHeight != lm->customHeight )
+					continue;
+				
+				/* set maxs */
+				xMax = (olm->customWidth - lm->w) + 1;
+				yMax = (olm->customHeight - lm->h) + 1;
+				
+				/* walk the origin around the lightmap */
+				for( y = 0; y < yMax; y++ )
+				{
+					for( x = 0; x < xMax; x++ )
+					{
+						/* find a fine tract of lauhnd */
+						ok = TestOutLightmapStamp( lm, lightmapNum, olm, x, y );
+						
+						if( ok )
+							break;
+					}
+					
+					if( ok )
+						break;
+				}
+				
+				if( ok )
+					break;
+				
+				/* reset x and y */
+				x = 0;
+				y = 0;
+			}
+		}
+		
+		/* no match? */
+		if( ok == qfalse )
+		{
+			/* allocate two new output lightmaps */
+			numOutLightmaps += 2;
+			olm = safe_malloc( numOutLightmaps * sizeof( outLightmap_t ) );
+			if( outLightmaps != NULL && numOutLightmaps > 2 )
+			{
+				memcpy( olm, outLightmaps, (numOutLightmaps - 2) * sizeof( outLightmap_t ) );
+				free( outLightmaps );
+			}
+			outLightmaps = olm;
+			
+			/* initialize both out lightmaps */
+			SetupOutLightmap( lm, &outLightmaps[ numOutLightmaps - 2 ] );
+			SetupOutLightmap( lm, &outLightmaps[ numOutLightmaps - 1 ] );
+			
+			/* set out lightmap */
+			i = numOutLightmaps - 2;
+			olm = &outLightmaps[ i ];
+			
+			/* set stamp xy origin to the first surface lightmap */
+			if( lightmapNum > 0 )
+			{
+				x = lm->lightmapX[ 0 ];
+				y = lm->lightmapY[ 0 ];
+			}
+		}
+		
+		/* if this is a style-using lightmap, it must be exported */
+		if( lightmapNum > 0 )
+			olm->extLightmapNum = 0;
+		
+		/* add the surface lightmap to the bsp lightmap */
+		lm->outLightmapNums[ lightmapNum ] = i;
+		lm->lightmapX[ lightmapNum ] = x;
+		lm->lightmapY[ lightmapNum ] = y;
+		olm->numLightmaps++;
+		
+		/* add shaders */
+		for( i = 0; i < lm->numLightSurfaces; i++ )
+		{
+			/* get surface info */
+			info = &surfaceInfos[ lightSurfaces[ lm->firstLightSurface + i ] ];
+			
+			/* test for shader */
+			for( j = 0; j < olm->numShaders; j++ )
+			{
+				if( olm->shaders[ j ] == info->si )
+					break;
+			}
+			
+			/* if it doesn't exist, add it */
+			if( j >= olm->numShaders && olm->numShaders < MAX_LIGHTMAP_SHADERS )
+			{
+				olm->shaders[ olm->numShaders ] = info->si;
+				olm->numShaders++;
+				numLightmapShaders++;
+			}
+		}
+		
+		/* mark the bits used */
+		for( y = 0; y < lm->h; y++ )
+		{
+			for( x = 0; x < lm->w; x++ )
+			{
+				/* get luxel */
+				luxel = BSP_LUXEL( lightmapNum, x, y );
+				deluxel = BSP_DELUXEL( x, y );
+				if( luxel[ 0 ] < 0.0f )
+					continue;
+				
+				/* set minimum light */
+				VectorCopy( luxel, color );
+
+				/* styles are not affected by minlight */
+				if( lightmapNum == 0 )
+				{
+					for( i = 0; i < 3; i++ )
+					{
+						if( color[ i ] < minLight[ i ] )
+							color[ i ] = minLight[ i ];
+					}
+				}
+				
+				/* get bsp lightmap coords  */
+				ox = x + lm->lightmapX[ lightmapNum ];
+				oy = y + lm->lightmapY[ lightmapNum ];
+				offset = (oy * olm->customWidth) + ox;
+				
+				/* flag pixel as used */
+				olm->lightBits[ offset >> 3 ] |= (1 << (offset & 7));
+				olm->freeLuxels--;
+				
+				/* store color */
+				pixel = olm->bspLightBytes + (((oy * olm->customWidth) + ox) * 3);
+				ColorToBytes( color, pixel, lm->gamma );
+				
+				/* store direction */
+				if( deluxemap )
+				{
+					/* normalize average light direction */
+					if( VectorNormalize( deluxel, direction ) )
+					{
+						/* encode [-1,1] in [0,255] */
+						pixel = olm->bspDirBytes + (((oy * olm->customWidth) + ox) * 3);
+						for( i = 0; i < 3; i++ )
+						{
+							temp = (direction[ i ] + 1.0f) * 127.5f;
+							if( temp < 0 )
+								pixel[ i ] = 0;
+							else if( temp > 255 )
+								pixel[ i ] = 255;
+							else
+								pixel[ i ] = temp;
+						}
+					}
+				}
+			}
+		}
+	}
+}
+
+
+
+/*
+CompareRawLightmap()
+compare function for qsort()
+*/
+
+static int CompareRawLightmap( const void *a, const void *b )
+{
+	rawLightmap_t	*alm, *blm;
+	surfaceInfo_t	*aInfo, *bInfo;
+	int				i, min, diff;
+	
+	
+	/* get lightmaps */
+	alm = &rawLightmaps[ *((int*) a) ];
+	blm = &rawLightmaps[ *((int*) b) ];
+	
+	/* get min number of surfaces */
+	min = (alm->numLightSurfaces < blm->numLightSurfaces ? alm->numLightSurfaces : blm->numLightSurfaces);
+	
+	/* iterate */
+	for( i = 0; i < min; i++ )
+	{
+		/* get surface info */
+		aInfo = &surfaceInfos[ lightSurfaces[ alm->firstLightSurface + i ] ];
+		bInfo = &surfaceInfos[ lightSurfaces[ blm->firstLightSurface + i ] ];
+		
+		/* compare shader names */
+		diff = strcmp( aInfo->si->shader, bInfo->si->shader );
+		if( diff != 0 )
+			return diff;
+	}
+
+	/* test style count */
+	diff = 0;
+	for( i = 0; i < MAX_LIGHTMAPS; i++ )
+		diff += blm->styles[ i ] - alm->styles[ i ];
+	if( diff )
+		return diff;
+	
+	/* compare size */
+	diff = (blm->w * blm->h) - (alm->w * alm->h);
+	if( diff != 0 )
+		return diff;
+	
+	/* must be equivalent */
+	return 0;
+}
+
+
+
+/*
+StoreSurfaceLightmaps()
+stores the surface lightmaps into the bsp as byte rgb triplets
+*/
+
+void StoreSurfaceLightmaps( void )
+{
+	int					i, j, k, x, y, lx, ly, sx, sy, *cluster, mappedSamples;
+	int					style, size, lightmapNum, lightmapNum2;
+	float				*normal, *luxel, *bspLuxel, *bspLuxel2, *radLuxel, samples, occludedSamples;
+	vec3_t				sample, occludedSample, dirSample;
+	float				*deluxel, *bspDeluxel, *bspDeluxel2;
+	byte				*lb;
+	int					numUsed, numTwins, numTwinLuxels, numStored;
+	float				lmx, lmy, efficiency;
+	vec3_t				color;
+	bspDrawSurface_t	*ds, *parent, dsTemp;
+	surfaceInfo_t		*info;
+	rawLightmap_t		*lm, *lm2;
+	outLightmap_t		*olm;
+	bspDrawVert_t		*dv, *ydv, *dvParent;
+	char				dirname[ 1024 ], filename[ 1024 ];
+	shaderInfo_t		*csi;
+	char				lightmapName[ 128 ];
+	char				*rgbGenValues[ 256 ];
+	char				*alphaGenValues[ 256 ];
+	
+	
+	/* note it */
+	Sys_Printf( "--- StoreSurfaceLightmaps ---\n");
+	
+	/* setup */
+	strcpy( dirname, source );
+	StripExtension( dirname );
+	memset( rgbGenValues, 0, sizeof( rgbGenValues ) );
+	memset( alphaGenValues, 0, sizeof( alphaGenValues ) );
+	
+	/* -----------------------------------------------------------------
+	   average the sampled luxels into the bsp luxels
+	   ----------------------------------------------------------------- */
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "Subsampling..." );
+	
+	/* walk the list of raw lightmaps */
+	numUsed = 0;
+	numTwins = 0;
+	numTwinLuxels = 0;
+	for( i = 0; i < numRawLightmaps; i++ )
+	{
+		/* get lightmap */
+		lm = &rawLightmaps[ i ];
+		
+		/* walk individual lightmaps */
+		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		{
+			/* early outs */
+			if( lm->superLuxels[ lightmapNum ] == NULL )
+				continue;
+			
+			/* allocate bsp luxel storage */
+			if( lm->bspLuxels[ lightmapNum ] == NULL )
+			{
+				size = lm->w * lm->h * BSP_LUXEL_SIZE * sizeof( float );
+				lm->bspLuxels[ lightmapNum ] = safe_malloc( size );
+				memset( lm->bspLuxels[ lightmapNum ], 0, size );
+			}
+
+			/* allocate radiosity lightmap storage */
+			if( bounce )
+			{
+				size = lm->w * lm->h * RAD_LUXEL_SIZE * sizeof( float );
+				if( lm->radLuxels[ lightmapNum ] == NULL )
+					lm->radLuxels[ lightmapNum ] = safe_malloc( size );
+				memset( lm->radLuxels[ lightmapNum ], 0, size );
+			}
+			
+			/* average supersampled luxels */
+			for( y = 0; y < lm->h; y++ )
+			{
+				for( x = 0; x < lm->w; x++ )
+				{
+					/* subsample */
+					samples = 0.0f;
+					occludedSamples = 0.0f;
+					mappedSamples = 0;
+					VectorClear( sample );
+					VectorClear( occludedSample );
+					VectorClear( dirSample );
+					for( ly = 0; ly < superSample; ly++ )
+					{
+						for( lx = 0; lx < superSample; lx++ )
+						{
+							/* sample luxel */
+							sx = x * superSample + lx;
+							sy = y * superSample + ly;
+							luxel = SUPER_LUXEL( lightmapNum, sx, sy );
+							deluxel = SUPER_DELUXEL( sx, sy );
+							normal = SUPER_NORMAL( sx, sy );
+							cluster = SUPER_CLUSTER( sx, sy );
+							
+							/* sample deluxemap */
+							if( deluxemap && lightmapNum == 0 )
+								VectorAdd( dirSample, deluxel, dirSample );
+							
+							/* keep track of used/occluded samples */
+							if( *cluster != CLUSTER_UNMAPPED )
+								mappedSamples++;
+							
+							/* handle lightmap border? */
+							if( lightmapBorder && (sx == 0 || sx == (lm->sw - 1) || sy == 0 || sy == (lm->sh - 1) ) && luxel[ 3 ] > 0.0f )
+							{
+								VectorSet( sample, 255.0f, 0.0f, 0.0f );
+								samples += 1.0f;
+							}
+							
+							/* handle debug */
+							else if( debug && *cluster < 0 )
+							{
+								if( *cluster == CLUSTER_UNMAPPED )
+									VectorSet( luxel, 255, 204, 0 );
+								else if( *cluster == CLUSTER_OCCLUDED )
+									VectorSet( luxel, 255, 0, 255 );
+								else if( *cluster == CLUSTER_FLOODED )
+									VectorSet( luxel, 0, 32, 255 );
+								VectorAdd( occludedSample, luxel, occludedSample );
+								occludedSamples += 1.0f;
+							}
+							
+							/* normal luxel handling */
+							else if( luxel[ 3 ] > 0.0f )
+							{
+								/* handle lit or flooded luxels */
+								if( *cluster > 0 || *cluster == CLUSTER_FLOODED )
+								{
+									VectorAdd( sample, luxel, sample );
+									samples += luxel[ 3 ];
+								}
+								
+								/* handle occluded or unmapped luxels */
+								else
+								{
+									VectorAdd( occludedSample, luxel, occludedSample );
+									occludedSamples += luxel[ 3 ];
+								}
+								
+								/* handle style debugging */
+								if( debug && lightmapNum > 0 && x < 2 && y < 2 )
+								{
+									VectorCopy( debugColors[ 0 ], sample );
+									samples = 1;
+								}
+							}
+						}
+					}
+					
+					/* only use occluded samples if necessary */
+					if( samples <= 0.0f )
+					{
+						VectorCopy( occludedSample, sample );
+						samples = occludedSamples;
+					}
+					
+					/* get luxels */
+					luxel = SUPER_LUXEL( lightmapNum, x, y );
+					deluxel = SUPER_DELUXEL( x, y );
+					
+					/* store light direction */
+					if( deluxemap && lightmapNum == 0 )
+						VectorCopy( dirSample, deluxel );
+					
+					/* store the sample back in super luxels */
+					if( samples > 0.01f )
+					{
+						VectorScale( sample, (1.0f / samples), luxel );
+						luxel[ 3 ] = 1.0f;
+					}
+					
+					/* if any samples were mapped in any way, store ambient color */
+					else if( mappedSamples > 0 )
+					{
+						if( lightmapNum == 0 )
+							VectorCopy( ambientColor, luxel );
+						else
+							VectorClear( luxel );
+						luxel[ 3 ] = 1.0f;
+					}
+					
+					/* store a bogus value to be fixed later */	
+					else
+					{
+						VectorClear( luxel );
+						luxel[ 3 ] = -1.0f;
+					}
+				}
+			}
+			
+			/* clean up and store into bsp luxels */
+			lm->used = 0;
+			for( y = 0; y < lm->h; y++ )
+			{
+				for( x = 0; x < lm->w; x++ )
+				{
+					/* get luxels */
+					luxel = SUPER_LUXEL( lightmapNum, x, y );
+					deluxel = SUPER_DELUXEL( x, y );
+					
+					/* copy light direction */
+					if( deluxemap && lightmapNum == 0 )
+						VectorCopy( deluxel, dirSample );
+					
+					/* is this a valid sample? */
+					if( luxel[ 3 ] > 0.0f )
+					{
+						VectorCopy( luxel, sample );
+						samples = luxel[ 3 ];
+						numUsed++;
+						lm->used++;
+						
+						/* fix negative samples */
+						for( j = 0; j < 3; j++ )
+						{
+							if( sample[ j ] < 0.0f )
+								sample[ j ] = 0.0f;
+						}
+					}
+					else
+					{
+						/* nick an average value from the neighbors */
+						VectorClear( sample );
+						VectorClear( dirSample );
+						samples = 0.0f;
+						
+						/* fixme: why is this disabled?? */
+						for( sy = (y - 1); sy <= (y + 1); sy++ )
+						{
+							if( sy < 0 || sy >= lm->h )
+								continue;
+							
+							for( sx = (x - 1); sx <= (x + 1); sx++ )
+							{
+								if( sx < 0 || sx >= lm->w || (sx == x && sy == y) )
+									continue;
+								
+								/* get neighbor's particulars */
+								luxel = SUPER_LUXEL( lightmapNum, sx, sy );
+								if( luxel[ 3 ] < 0.0f )
+									continue;
+								VectorAdd( sample, luxel, sample );
+								samples += luxel[ 3 ];
+							}
+						}
+						
+						/* no samples? */
+						if( samples == 0.0f )
+						{
+							VectorSet( sample, -1.0f, -1.0f, -1.0f );
+							samples = 1.0f;
+						}
+						else
+						{
+							numUsed++;
+							lm->used++;
+							
+							/* fix negative samples */
+							for( j = 0; j < 3; j++ )
+							{
+								if( sample[ j ] < 0.0f )
+									sample[ j ] = 0.0f;
+							}
+						}
+					}
+					
+					/* scale the sample */
+					VectorScale( sample, (1.0f / samples), sample );
+					
+					/* store the sample in the radiosity luxels */
+					if( bounce > 0 )
+					{
+						radLuxel = RAD_LUXEL( lightmapNum, x, y );
+						VectorCopy( sample, radLuxel );
+						
+						/* if only storing bounced light, early out here */
+						if( bounceOnly && !bouncing )
+							continue;
+					}
+					
+					/* store the sample in the bsp luxels */
+					bspLuxel = BSP_LUXEL( lightmapNum, x, y );
+					bspDeluxel = BSP_DELUXEL( x, y );
+					
+					VectorAdd( bspLuxel, sample, bspLuxel );
+					if( deluxemap && lightmapNum == 0 )
+						VectorAdd( bspDeluxel, dirSample, bspDeluxel );
+				}
+			}
+			
+			/* wrap bsp luxels if necessary */
+			if( lm->wrap[ 0 ] )
+			{
+				for( y = 0; y < lm->h; y++ )
+				{
+					bspLuxel = BSP_LUXEL( lightmapNum, 0, y );
+					bspLuxel2 = BSP_LUXEL( lightmapNum, lm->w - 1, y );
+					VectorAdd( bspLuxel, bspLuxel2, bspLuxel );
+					VectorScale( bspLuxel, 0.5f, bspLuxel );
+					VectorCopy( bspLuxel, bspLuxel2 );
+					if( deluxemap && lightmapNum == 0 )
+					{
+						bspDeluxel = BSP_DELUXEL( 0, y );
+						bspDeluxel2 = BSP_DELUXEL( lm->w - 1, y );
+						VectorAdd( bspDeluxel, bspDeluxel2, bspDeluxel );
+						VectorScale( bspDeluxel, 0.5f, bspDeluxel );
+						VectorCopy( bspDeluxel, bspDeluxel2 );
+					}
+				}
+			}
+			if( lm->wrap[ 1 ] )
+			{
+				for( x = 0; x < lm->w; x++ )
+				{
+					bspLuxel = BSP_LUXEL( lightmapNum, x, 0 );
+					bspLuxel2 = BSP_LUXEL( lightmapNum, x, lm->h - 1 );
+					VectorAdd( bspLuxel, bspLuxel2, bspLuxel );
+					VectorScale( bspLuxel, 0.5f, bspLuxel );
+					VectorCopy( bspLuxel, bspLuxel2 );
+					if( deluxemap && lightmapNum == 0 )
+					{
+						bspDeluxel = BSP_DELUXEL( x, 0 );
+						bspDeluxel2 = BSP_DELUXEL( x, lm->h - 1 );
+						VectorAdd( bspDeluxel, bspDeluxel2, bspDeluxel );
+						VectorScale( bspDeluxel, 0.5f, bspDeluxel );
+						VectorCopy( bspDeluxel, bspDeluxel2 );
+					}
+				}
+			}
+		}
+	}
+	
+	/* -----------------------------------------------------------------
+	   collapse non-unique lightmaps
+	   ----------------------------------------------------------------- */
+	
+	if( noCollapse == qfalse && deluxemap == qfalse )
+	{
+		/* note it */
+		Sys_FPrintf( SYS_VRB, "collapsing..." );
+		
+		/* set all twin refs to null */
+		for( i = 0; i < numRawLightmaps; i++ )
+		{
+			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				rawLightmaps[ i ].twins[ lightmapNum ] = NULL;
+				rawLightmaps[ i ].twinNums[ lightmapNum ] = -1;
+				rawLightmaps[ i ].numStyledTwins = 0;
+			}
+		}
+		
+		/* walk the list of raw lightmaps */
+		for( i = 0; i < numRawLightmaps; i++ )
+		{
+			/* get lightmap */
+			lm = &rawLightmaps[ i ];
+			
+			/* walk lightmaps */
+			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				/* early outs */
+				if( lm->bspLuxels[ lightmapNum ] == NULL ||
+					lm->twins[ lightmapNum ] != NULL )
+					continue;
+				
+				/* find all lightmaps that are virtually identical to this one */
+				for( j = i + 1; j < numRawLightmaps; j++ )
+				{
+					/* get lightmap */
+					lm2 = &rawLightmaps[ j ];
+					
+					/* walk lightmaps */
+					for( lightmapNum2 = 0; lightmapNum2 < MAX_LIGHTMAPS; lightmapNum2++ )
+					{
+						/* early outs */
+						if( lm2->bspLuxels[ lightmapNum2 ] == NULL ||
+							lm2->twins[ lightmapNum2 ] != NULL )
+							continue;
+						
+						/* compare them */
+						if( CompareBSPLuxels( lm, lightmapNum, lm2, lightmapNum2 ) )
+						{
+							/* merge and set twin */
+							MergeBSPLuxels( lm, lightmapNum, lm2, lightmapNum2 );
+							lm2->twins[ lightmapNum2 ] = lm;
+							lm2->twinNums[ lightmapNum2 ] = lightmapNum;
+							numTwins++;
+							numTwinLuxels += (lm->w * lm->h);
+							
+							/* count styled twins */
+							if( lightmapNum > 0 )
+								lm->numStyledTwins++;
+						}
+					}
+				}
+			}
+		}
+	}
+	
+	/* -----------------------------------------------------------------
+	   sort raw lightmaps by shader
+	   ----------------------------------------------------------------- */
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "sorting..." );
+	
+	/* allocate a new sorted list */
+	if( sortLightmaps == NULL )
+		sortLightmaps = safe_malloc( numRawLightmaps * sizeof( int ) );
+	
+	/* fill it out and sort it */
+	for( i = 0; i < numRawLightmaps; i++ )
+		sortLightmaps[ i ] = i;
+	qsort( sortLightmaps, numRawLightmaps, sizeof( int ), CompareRawLightmap );
+	
+	/* -----------------------------------------------------------------
+	   allocate output lightmaps
+	   ----------------------------------------------------------------- */
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "allocating..." );
+	
+	/* kill all existing output lightmaps */
+	if( outLightmaps != NULL )
+	{
+		for( i = 0; i < numOutLightmaps; i++ )
+		{
+			free( outLightmaps[ i ].lightBits );
+			free( outLightmaps[ i ].bspLightBytes );
+		}
+		free( outLightmaps );
+		outLightmaps = NULL;
+	}
+	
+	numLightmapShaders = 0;
+	numOutLightmaps = 0;
+	numBSPLightmaps = 0;
+	numExtLightmaps = 0;
+	
+	/* find output lightmap */
+	for( i = 0; i < numRawLightmaps; i++ )
+	{
+		lm = &rawLightmaps[ sortLightmaps[ i ] ];
+		FindOutLightmaps( lm );
+	}
+	
+	/* set output numbers in twinned lightmaps */
+	for( i = 0; i < numRawLightmaps; i++ )
+	{
+		/* get lightmap */
+		lm = &rawLightmaps[ sortLightmaps[ i ] ];
+		
+		/* walk lightmaps */
+		for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+		{
+			/* get twin */
+			lm2 = lm->twins[ lightmapNum ];
+			if( lm2 == NULL )
+				continue;
+			lightmapNum2 = lm->twinNums[ lightmapNum ];
+			
+			/* find output lightmap from twin */
+			lm->outLightmapNums[ lightmapNum ] = lm2->outLightmapNums[ lightmapNum2 ];
+			lm->lightmapX[ lightmapNum ] = lm2->lightmapX[ lightmapNum2 ];
+			lm->lightmapY[ lightmapNum ] = lm2->lightmapY[ lightmapNum2 ];
+		}
+	}
+	
+	/* -----------------------------------------------------------------
+	   store output lightmaps
+	   ----------------------------------------------------------------- */
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "storing..." );
+	
+	/* count the bsp lightmaps and allocate space */
+	if( bspLightBytes != NULL )
+		free( bspLightBytes );
+	if( numBSPLightmaps == 0 || externalLightmaps )
+	{
+		numBSPLightBytes = 0;
+		bspLightBytes = NULL;
+	}
+	else
+	{
+		numBSPLightBytes = (numBSPLightmaps * LIGHTMAP_WIDTH * LIGHTMAP_HEIGHT * 3);
+		bspLightBytes = safe_malloc( numBSPLightBytes );
+		memset( bspLightBytes, 0, numBSPLightBytes );
+	}
+	
+	/* walk the list of output lightmaps */
+	for( i = 0; i < numOutLightmaps; i++ )
+	{
+		/* get output lightmap */
+		olm = &outLightmaps[ i ];
+		
+		/* is this a valid bsp lightmap? */
+		if( olm->lightmapNum >= 0 && !externalLightmaps )
+		{
+			/* copy lighting data */
+			lb = bspLightBytes + (olm->lightmapNum * LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3);
+			memcpy( lb, olm->bspLightBytes, LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3 );
+			
+			/* copy direction data */
+			if( deluxemap )
+			{
+				lb = bspLightBytes + ((olm->lightmapNum + 1) * LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3);
+				memcpy( lb, olm->bspDirBytes, LIGHTMAP_HEIGHT * LIGHTMAP_WIDTH * 3 );
+			}
+		}
+		
+		/* external lightmap? */
+		if( olm->lightmapNum < 0 || olm->extLightmapNum >= 0 || externalLightmaps )
+		{
+			/* make a directory for the lightmaps */
+			Q_mkdir( dirname );
+			
+			/* set external lightmap number */
+			olm->extLightmapNum = numExtLightmaps;
+			
+			/* write lightmap */
+			sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps );
+			Sys_FPrintf( SYS_VRB, "\nwriting %s", filename );
+			WriteTGA24( filename, olm->bspLightBytes, olm->customWidth, olm->customHeight, qtrue );
+			numExtLightmaps++;
+			
+			/* write deluxemap */
+			if( deluxemap )
+			{
+				sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, numExtLightmaps );
+				Sys_FPrintf( SYS_VRB, "\nwriting %s", filename );
+				WriteTGA24( filename, olm->bspDirBytes, olm->customWidth, olm->customHeight, qtrue );
+				numExtLightmaps++;
+				
+				if( debugDeluxemap )
+					olm->extLightmapNum++;
+			}
+		}
+	}
+	
+	if( numExtLightmaps > 0 )
+		Sys_FPrintf( SYS_VRB, "\n" );
+	
+	/* delete unused external lightmaps */
+	for( i = numExtLightmaps; i; i++ )
+	{
+		/* determine if file exists */
+		sprintf( filename, "%s/" EXTERNAL_LIGHTMAP, dirname, i );
+		if( !FileExists( filename ) )
+			break;
+		
+		/* delete it */
+		remove( filename );
+	}
+	
+	/* -----------------------------------------------------------------
+	   project the lightmaps onto the bsp surfaces
+	   ----------------------------------------------------------------- */
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "projecting..." );
+	
+	/* walk the list of surfaces */
+	for( i = 0; i < numBSPDrawSurfaces; i++ )
+	{
+		/* get the surface and info */
+		ds = &bspDrawSurfaces[ i ];
+		info = &surfaceInfos[ i ];
+		lm = info->lm;
+		olm = NULL;
+		
+		/* handle surfaces with identical parent */
+		if( info->parentSurfaceNum >= 0 )
+		{
+			/* preserve original data and get parent */
+			parent = &bspDrawSurfaces[ info->parentSurfaceNum ];
+			memcpy( &dsTemp, ds, sizeof( *ds ) );
+			
+			/* overwrite child with parent data */
+			memcpy( ds, parent, sizeof( *ds ) );
+			
+			/* restore key parts */
+			ds->fogNum = dsTemp.fogNum;
+			ds->firstVert = dsTemp.firstVert;
+			ds->firstIndex = dsTemp.firstIndex;
+			memcpy( ds->lightmapVecs, dsTemp.lightmapVecs, sizeof( dsTemp.lightmapVecs ) );
+			
+			/* set vertex data */
+			dv = &bspDrawVerts[ ds->firstVert ];
+			dvParent = &bspDrawVerts[ parent->firstVert ];
+			for( j = 0; j < ds->numVerts; j++ )
+			{
+				memcpy( dv[ j ].lightmap, dvParent[ j ].lightmap, sizeof( dv[ j ].lightmap ) );
+				memcpy( dv[ j ].color, dvParent[ j ].color, sizeof( dv[ j ].color ) );
+			}
+			
+			/* skip the rest */
+			continue;
+		}
+		
+		/* handle vertex lit or approximated surfaces */
+		else if( lm == NULL || lm->outLightmapNums[ 0 ] < 0 )
+		{
+			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				ds->lightmapNum[ lightmapNum ] = -3;
+				ds->lightmapStyles[ lightmapNum ] = ds->vertexStyles[ lightmapNum ];
+			}
+		}
+		
+		/* handle lightmapped surfaces */
+		else
+		{
+			/* walk lightmaps */
+			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				/* set style */
+				ds->lightmapStyles[ lightmapNum ] = lm->styles[ lightmapNum ];
+				
+				/* handle unused style */
+				if( lm->styles[ lightmapNum ] == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 )
+				{
+					ds->lightmapNum[ lightmapNum ] = -3;
+					continue;
+				}
+				
+				/* get output lightmap */
+				olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
+				
+				/* set bsp lightmap number */
+				ds->lightmapNum[ lightmapNum ] = olm->lightmapNum;
+				
+				/* deluxemap debugging makes the deluxemap visible */
+				if( deluxemap && debugDeluxemap && lightmapNum == 0 )
+					ds->lightmapNum[ lightmapNum ]++;
+				
+				/* calc lightmap origin in texture space */
+				lmx = (float) lm->lightmapX[ lightmapNum ] / (float) olm->customWidth;
+				lmy = (float) lm->lightmapY[ lightmapNum ] / (float) olm->customHeight;
+				
+				/* calc lightmap st coords and store lighting values */
+				dv = &bspDrawVerts[ ds->firstVert ];
+				ydv = &yDrawVerts[ ds->firstVert ];
+				for( j = 0; j < ds->numVerts; j++ )
+				{
+					dv[ j ].lightmap[ lightmapNum ][ 0 ] = lmx + (ydv[ j ].lightmap[ 0 ][ 0 ] / (superSample * olm->customWidth));
+					dv[ j ].lightmap[ lightmapNum ][ 1 ] = lmy + (ydv[ j ].lightmap[ 0 ][ 1 ] / (superSample * olm->customHeight));
+				}
+			}
+		}
+		
+		/* store vertex colors */
+		dv = &bspDrawVerts[ ds->firstVert ];
+		for( j = 0; j < ds->numVerts; j++ )
+		{
+			/* walk lightmaps */
+			for( lightmapNum = 0; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				/* handle unused style */
+				if( ds->vertexStyles[ lightmapNum ] == LS_NONE )
+					VectorClear( color );
+				else
+				{
+					/* get vertex color */
+					luxel = VERTEX_LUXEL( lightmapNum, ds->firstVert + j );
+					VectorCopy( luxel, color );
+					
+					/* set minimum light */
+					if( lightmapNum == 0 )
+					{
+						for( k = 0; k < 3; k++ )
+							if( color[ k ] < minVertexLight[ k ] )
+								color[ k ] = minVertexLight[ k ];
+					}
+				}
+				
+				/* store to bytes */
+				ColorToBytes( color, dv[ j ].color[ lightmapNum ], info->si->vertexScale );
+			}
+		}
+		
+		/* surfaces with styled lightmaps and a style marker get a custom generated shader (fixme: make this work with external lightmaps) */
+		if( olm != NULL && lm != NULL && lm->styles[ 1 ] != LS_NONE && game->load != LoadRBSPFile )	//%	info->si->styleMarker > 0 )
+		{
+			qboolean	dfEqual;
+			char		key[ 32 ], styleStage[ 512 ], styleStages[ 4096 ], rgbGen[ 128 ], alphaGen[ 128 ];
+			
+			
+			/* setup */
+			sprintf( styleStages, "\n\t// Q3Map2 custom lightstyle stage(s)\n" );
+			dv = &bspDrawVerts[ ds->firstVert ];
+			
+			/* depthFunc equal? */
+			if( info->si->styleMarker == 2 || info->si->implicitMap == IM_MASKED )
+				dfEqual = qtrue;
+			else
+				dfEqual = qfalse;
+			
+			/* generate stages for styled lightmaps */
+			for( lightmapNum = 1; lightmapNum < MAX_LIGHTMAPS; lightmapNum++ )
+			{
+				/* early out */
+				style = lm->styles[ lightmapNum ];
+				if( style == LS_NONE || lm->outLightmapNums[ lightmapNum ] < 0 )
+					continue;
+				
+				/* get output lightmap */
+				olm = &outLightmaps[ lm->outLightmapNums[ lightmapNum ] ];
+				
+				/* lightmap name */
+				if( lm->outLightmapNums[ lightmapNum ] == lm->outLightmapNums[ 0 ] )
+					strcpy( lightmapName, "$lightmap" );
+				else
+					sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
+				
+				/* get rgbgen string */
+				if( rgbGenValues[ style ] == NULL )
+				{
+					sprintf( key, "_style%drgbgen", style );
+					rgbGenValues[ style ] = (char*) ValueForKey( &entities[ 0 ], key );
+					if( rgbGenValues[ style ][ 0 ] == '\0' )
+						rgbGenValues[ style ] = "wave noise 0.5 1 0 5.37";
+				}
+				rgbGen[ 0 ] = '\0';
+				if( rgbGenValues[ style ][ 0 ] != '\0' )
+					sprintf( rgbGen, "\t\trgbGen %s // style %d\n", rgbGenValues[ style ], style );
+				else
+					rgbGen[ 0 ] = '\0';
+				
+				/* get alphagen string */
+				if( alphaGenValues[ style ] == NULL )
+				{
+					sprintf( key, "_style%dalphagen", style );
+					alphaGenValues[ style ] = (char*) ValueForKey( &entities[ 0 ], key );
+				}
+				if( alphaGenValues[ style ][ 0 ] != '\0' )
+					sprintf( alphaGen, "\t\talphaGen %s // style %d\n", alphaGenValues[ style ], style );
+				else
+					alphaGen[ 0 ] = '\0';
+				
+				/* calculate st offset */
+				lmx = dv[ 0 ].lightmap[ lightmapNum ][ 0 ] - dv[ 0 ].lightmap[ 0 ][ 0 ];
+				lmy = dv[ 0 ].lightmap[ lightmapNum ][ 1 ] - dv[ 0 ].lightmap[ 0 ][ 1 ];
+				
+				/* create additional stage */
+				if( lmx == 0.0f && lmy == 0.0f )
+				{
+					sprintf( styleStage,	"\t{\n"
+											"\t\tmap %s\n"										/* lightmap */
+											"\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
+											"%s"												/* depthFunc equal */
+											"%s"												/* rgbGen */
+											"%s"												/* alphaGen */
+											"\t\ttcGen lightmap\n"
+											"\t}\n",
+						lightmapName,
+						(dfEqual ? "\t\tdepthFunc equal\n" : ""),
+						rgbGen,
+						alphaGen );
+				}
+				else
+				{
+					sprintf( styleStage,	"\t{\n"
+											"\t\tmap %s\n"										/* lightmap */
+											"\t\tblendFunc GL_SRC_ALPHA GL_ONE\n"
+											"%s"												/* depthFunc equal */
+											"%s"												/* rgbGen */
+											"%s"												/* alphaGen */
+											"\t\ttcGen lightmap\n"
+											"\t\ttcMod transform 1 0 0 1 %1.5f %1.5f\n"			/* st offset */
+											"\t}\n",
+						lightmapName,
+						(dfEqual ? "\t\tdepthFunc equal\n" : ""),
+						rgbGen,
+						alphaGen,
+						lmx, lmy );
+					
+				}
+				
+				/* concatenate */
+				strcat( styleStages, styleStage );
+			}
+			
+			/* create custom shader */
+			if( info->si->styleMarker == 2 )
+				csi = CustomShader( info->si, "q3map_styleMarker2", styleStages );
+			else
+				csi = CustomShader( info->si, "q3map_styleMarker", styleStages );
+			
+			/* emit remap command */
+			//%	EmitVertexRemapShader( csi->shader, info->si->shader );
+			
+			/* store it */
+			//%	Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
+			ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
+			//%	Sys_Printf( ")\n" );
+		}
+		
+		/* devise a custom shader for this surface (fixme: make this work with light styles) */
+		else if( olm != NULL && lm != NULL && !externalLightmaps &&
+			(olm->customWidth != LIGHTMAP_WIDTH || olm->customHeight != LIGHTMAP_HEIGHT) )
+		{
+			/* get output lightmap */
+			olm = &outLightmaps[ lm->outLightmapNums[ 0 ] ];
+			
+			/* do some name mangling */
+			sprintf( lightmapName, "maps/%s/" EXTERNAL_LIGHTMAP, mapName, olm->extLightmapNum );
+			
+			/* create custom shader */
+			csi = CustomShader( info->si, "$lightmap", lightmapName );
+			
+			/* store it */
+			//%	Sys_Printf( "Emitting: %s (%d", csi->shader, strlen( csi->shader ) );
+			ds->shaderNum = EmitShader( csi->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
+			//%	Sys_Printf( ")\n" );
+		}
+		
+		/* use the normal plain-jane shader */
+		else
+			ds->shaderNum = EmitShader( info->si->shader, &bspShaders[ ds->shaderNum ].contentFlags, &bspShaders[ ds->shaderNum ].surfaceFlags );
+	}
+	
+	/* finish */
+	Sys_FPrintf( SYS_VRB, "done.\n" );
+	
+	/* calc num stored */
+	numStored = numBSPLightBytes / 3;
+	efficiency = (numStored <= 0)
+		? 0
+		: (float) numUsed / (float) numStored;
+	
+	/* print stats */
+	Sys_Printf( "%9d luxels used\n", numUsed );
+	Sys_Printf( "%9d luxels stored (%3.2f percent efficiency)\n", numStored, efficiency * 100.0f );
+	Sys_Printf( "%9d identical surface lightmaps, using %d luxels\n", numTwins, numTwinLuxels );
+	Sys_Printf( "%9d vertex forced surfaces\n", numSurfsVertexForced );
+	Sys_Printf( "%9d vertex approximated surfaces\n", numSurfsVertexApproximated );
+	Sys_Printf( "%9d BSP lightmaps\n", numBSPLightmaps );
+	Sys_Printf( "%9d total lightmaps\n", numOutLightmaps );
+	Sys_Printf( "%9d unique lightmap/shader combinations\n", numLightmapShaders );
+	
+	/* write map shader file */
+	WriteMapShaderFile();
+}
+
+
+
+
diff --git a/tools/quake3/q3map2/main.c b/tools/quake3/q3map2/main.c
index 40fd5c8c..4da3bcf8 100644
--- a/tools/quake3/q3map2/main.c
+++ b/tools/quake3/q3map2/main.c
@@ -1,456 +1,456 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
--------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define MAIN_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-Random()
-returns a pseudorandom number between 0 and 1
-*/
-
-vec_t Random( void )
-{
-	return (vec_t) rand() / RAND_MAX;
-}
-
-
-
-/*
-ExitQ3Map()
-cleanup routine
-*/
-
-static void ExitQ3Map( void )
-{
-	BSPFilesCleanup();
-	if( mapDrawSurfs != NULL )
-		free( mapDrawSurfs );
-}
-
-
-
-/*
-BSPInfo()
-emits statistics about the bsp file
-*/
-
-int BSPInfo( int count, char **fileNames )
-{
-	int			i;
-	char		source[ 1024 ], ext[ 64 ];
-	int			size;
-	FILE		*f;
-	
-	
-	/* dummy check */
-	if( count < 1 )
-	{
-		Sys_Printf( "No files to dump info for.\n");
-		return -1;
-	}
-	
-	/* enable info mode */
-	infoMode = qtrue;
-	
-	/* walk file list */
-	for( i = 0; i < count; i++ )
-	{
-		Sys_Printf( "---------------------------------\n" );
-		
-		/* mangle filename and get size */
-		strcpy( source, fileNames[ i ] );
-		ExtractFileExtension( source, ext );
-		if( !Q_stricmp( ext, "map" ) )
-			StripExtension( source );
-		DefaultExtension( source, ".bsp" );
-		f = fopen( source, "rb" );
-		if( f )
-		{
-			size = Q_filelength (f);
-			fclose( f );
-		}
-		else
-			size = 0;
-		
-		/* load the bsp file and print lump sizes */
-		Sys_Printf( "%s\n", source );
-		LoadBSPFile( source );		
-		PrintBSPFileSizes();
-		
-		/* print sizes */
-		Sys_Printf( "\n" );
-		Sys_Printf( "          total         %9d\n", size );
-		Sys_Printf( "                        %9d KB\n", size / 1024 );
-		Sys_Printf( "                        %9d MB\n", size / (1024 * 1024) );
-		
-		Sys_Printf( "---------------------------------\n" );
-	}
-	
-	/* return count */
-	return i;
-}
-
-
-
-/*
-ScaleBSPMain()
-amaze and confuse your enemies with wierd scaled maps!
-*/
-
-int ScaleBSPMain( int argc, char **argv )
-{
-	int			i;
-	float		f, scale;
-	vec3_t		vec;
-	char		str[ 1024 ];
-	
-	
-	/* arg checking */
-	if( argc < 2 )
-	{
-		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
-		return 0;
-	}
-	
-	/* get scale */
-	scale = atof( argv[ argc - 2 ] );
-	if( scale == 0.0f )
-	{
-		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
-		Sys_Printf( "Non-zero scale value required.\n" );
-		return 0;
-	}
-	
-	/* do some path mangling */
-	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
-	StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	
-	/* load the bsp */
-	Sys_Printf( "Loading %s\n", source );
-	LoadBSPFile( source );
-	ParseEntities();
-	
-	/* note it */
-	Sys_Printf( "--- ScaleBSP ---\n" );
-	Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
-	
-	/* scale entity keys */
-	for( i = 0; i < numBSPEntities && i < numEntities; i++ )
-	{
-		/* scale origin */
-		GetVectorForKey( &entities[ i ], "origin", vec );
-		if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )
-		{
-			VectorScale( vec, scale, vec );
-			sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
-			SetKeyValue( &entities[ i ], "origin", str );
-		}
-		
-		/* scale door lip */
-		f = FloatForKey( &entities[ i ], "lip" );
-		if( f )
-		{
-			f *= scale;
-			sprintf( str, "%f", f );
-			SetKeyValue( &entities[ i ], "lip", str );
-		}
-	}
-	
-	/* scale models */
-	for( i = 0; i < numBSPModels; i++ )
-	{
-		VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
-		VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
-	}
-	
-	/* scale nodes */
-	for( i = 0; i < numBSPNodes; i++ )
-	{
-		VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
-		VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
-	}
-	
-	/* scale leafs */
-	for( i = 0; i < numBSPLeafs; i++ )
-	{
-		VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
-		VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
-	}
-	
-	/* scale drawverts */
-	for( i = 0; i < numBSPDrawVerts; i++ )
-		VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
-	
-	/* scale planes */
-	for( i = 0; i < numBSPPlanes; i++ )
-		bspPlanes[ i ].dist *= scale;
-	
-	/* scale gridsize */
-	GetVectorForKey( &entities[ 0 ], "gridsize", vec );
-	if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )
-		VectorCopy( gridSize, vec );
-	VectorScale( vec, scale, vec );
-	sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
-	SetKeyValue( &entities[ 0 ], "gridsize", str );
-	
-	/* write the bsp */
-	UnparseEntities();
-	StripExtension( source );
-	DefaultExtension( source, "_s.bsp" );
-	Sys_Printf( "Writing %s\n", source );
-	WriteBSPFile( source );
-	
-	/* return to sender */
-	return 0;
-}
-
-
-
-/*
-ConvertBSPMain()
-main argument processing function for bsp conversion
-*/
-
-int ConvertBSPMain( int argc, char **argv )
-{
-	int		i;
-	int		(*convertFunc)( char * );
-	
-	
-	/* set default */
-	convertFunc = ConvertBSPToASE;
-	
-	/* arg checking */
-	if( argc < 1 )
-	{
-		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
-		return 0;
-	}
-	
-	/* process arguments */
-	for( i = 1; i < (argc - 1); i++ )
-	{
-		/* -format map|ase|... */
-		if( !strcmp( argv[ i ],  "-format" ) )
- 		{
-			i++;
-			if( !Q_stricmp( argv[ i ], "ase" ) )
-				convertFunc = ConvertBSPToASE;
-			else if( !Q_stricmp( argv[ i ], "map" ) )
-				convertFunc = ConvertBSPToMap;
-			else
-				Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
- 		}
-	}
-	
-	/* clean up map name */
-	strcpy( source, ExpandArg( argv[ i ] ) );
-	StripExtension( source );
-	DefaultExtension( source, ".bsp" );
-	
-	LoadShaderInfo();
-	
-	Sys_Printf( "Loading %s\n", source );
-	
-	/* ydnar: load surface file */
-	//%	LoadSurfaceExtraFile( source );
-	
-	LoadBSPFile( source );
-	
-	/* parse bsp entities */
-	ParseEntities();
-	
-	/* convert */
-	return convertFunc( source );
-}
-
-
-
-/*
-main()
-q3map mojo...
-*/
-
-int main( int argc, char **argv )
-{
-	int		i, r;
-	double	start, end;
-	
-	
-	/* we want consistent 'randomness' */
-	srand( 0 );
-	
-	/* start timer */
-	start = I_FloatTime();
-
-	/* this was changed to emit version number over the network */
-	printf( Q3MAP_VERSION "\n" );
-	
-	/* set exit call */
-	atexit( ExitQ3Map );
-	
-	/* read general options first */
-	for( i = 1; i < argc; i++ )
-	{
-		/* -connect */
-		if( !strcmp( argv[ i ], "-connect" ) )
-		{
-			argv[ i ] = NULL;
-			i++;
-			Broadcast_Setup( argv[ i ] );
-			argv[ i ] = NULL;
-		}
-		
-		/* verbose */
-		else if( !strcmp( argv[ i ], "-v" ) )
-		{
-			verbose = qtrue;
-			argv[ i ] = NULL;
-		}
-		
-		/* force */
-		else if( !strcmp( argv[ i ], "-force" ) )
-		{
-			force = qtrue;
-			argv[ i ] = NULL;
-		}
-		
-		/* patch subdivisions */
-		else if( !strcmp( argv[ i ], "-subdivisions" ) )
-		{
-			argv[ i ] = NULL;
-			i++;
-			patchSubdivisions = atoi( argv[ i ] );
-			argv[ i ] = NULL;
-			if( patchSubdivisions <= 0 )
-				patchSubdivisions = 1;
-		}
-		
-		/* threads */
-		else if( !strcmp( argv[ i ], "-threads" ) )
-		{
-			argv[ i ] = NULL;
-			i++;
-			numthreads = atoi( argv[ i ] );
-			argv[ i ] = NULL;
-		}
-	}
-	
-	/* init model library */
-	PicoInit();
-	PicoSetMallocFunc( safe_malloc );
-	PicoSetFreeFunc( free );
-	PicoSetPrintFunc( PicoPrintFunc );
-	PicoSetLoadFileFunc( PicoLoadFileFunc );
-	PicoSetFreeFileFunc( free );
-	
-	/* set number of threads */
-	ThreadSetDefault();
-	
-	/* generate sinusoid jitter table */
-	for( i = 0; i < MAX_JITTERS; i++ )
-	{
-		jitters[ i ] = sin( i * 139.54152147 );
-		//%	Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );
-	}
-	
-	/* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)
-	   and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */
-	
-	Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
-	Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
-	Sys_Printf( "GtkRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
-	Sys_Printf( "%s\n", Q3MAP_MOTD );
-	
-	/* ydnar: new path initialization */
-	InitPaths( &argc, argv );
-	
-	/* check if we have enough options left to attempt something */
-	if( argc < 2 )
-		Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
-	
-	/* info */
-	if( !strcmp( argv[ 1 ], "-info" ) )
-		r = BSPInfo( argc - 2, argv + 2 );
-	
-	/* vis */
-	else if( !strcmp( argv[ 1 ], "-vis" ) )
-		r = VisMain( argc - 1, argv + 1 );
-	
-	/* light */
-	else if( !strcmp( argv[ 1 ], "-light" ) )
-		r = LightMain( argc - 1, argv + 1 );
-	
-	/* vlight */
-	else if( !strcmp( argv[ 1 ], "-vlight" ) )
-	{
-		Sys_Printf( "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );
-		argv[ 1 ] = "-fast";	/* eek a hack */
-		r = LightMain( argc, argv );
-	}
-	
-	/* ydnar: lightmap export */
-	else if( !strcmp( argv[ 1 ], "-export" ) )
-		r = ExportLightmapsMain( argc - 1, argv + 1 );
-	
-	/* ydnar: lightmap import */
-	else if( !strcmp( argv[ 1 ], "-import" ) )
-		r = ImportLightmapsMain( argc - 1, argv + 1 );
-	
-	/* ydnar: bsp scaling */
-	else if( !strcmp( argv[ 1 ], "-scale" ) )
-		r = ScaleBSPMain( argc - 1, argv + 1 );
-	
-	/* ydnar: bsp conversion */
-	else if( !strcmp( argv[ 1 ], "-convert" ) )
-		r = ConvertBSPMain( argc - 1, argv + 1 );
-	
-	/* ydnar: otherwise create a bsp */
-	else
-		r = BSPMain( argc, argv );
-	
-	/* emit time */
-	end = I_FloatTime();
-	Sys_Printf( "%9.0f seconds elapsed\n", end - start );
-	
-	/* shut down connection */
-	Broadcast_Shutdown();
-	
-	/* return any error code */
-	return r;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+-------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define MAIN_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+Random()
+returns a pseudorandom number between 0 and 1
+*/
+
+vec_t Random( void )
+{
+	return (vec_t) rand() / RAND_MAX;
+}
+
+
+
+/*
+ExitQ3Map()
+cleanup routine
+*/
+
+static void ExitQ3Map( void )
+{
+	BSPFilesCleanup();
+	if( mapDrawSurfs != NULL )
+		free( mapDrawSurfs );
+}
+
+
+
+/*
+BSPInfo()
+emits statistics about the bsp file
+*/
+
+int BSPInfo( int count, char **fileNames )
+{
+	int			i;
+	char		source[ 1024 ], ext[ 64 ];
+	int			size;
+	FILE		*f;
+	
+	
+	/* dummy check */
+	if( count < 1 )
+	{
+		Sys_Printf( "No files to dump info for.\n");
+		return -1;
+	}
+	
+	/* enable info mode */
+	infoMode = qtrue;
+	
+	/* walk file list */
+	for( i = 0; i < count; i++ )
+	{
+		Sys_Printf( "---------------------------------\n" );
+		
+		/* mangle filename and get size */
+		strcpy( source, fileNames[ i ] );
+		ExtractFileExtension( source, ext );
+		if( !Q_stricmp( ext, "map" ) )
+			StripExtension( source );
+		DefaultExtension( source, ".bsp" );
+		f = fopen( source, "rb" );
+		if( f )
+		{
+			size = Q_filelength (f);
+			fclose( f );
+		}
+		else
+			size = 0;
+		
+		/* load the bsp file and print lump sizes */
+		Sys_Printf( "%s\n", source );
+		LoadBSPFile( source );		
+		PrintBSPFileSizes();
+		
+		/* print sizes */
+		Sys_Printf( "\n" );
+		Sys_Printf( "          total         %9d\n", size );
+		Sys_Printf( "                        %9d KB\n", size / 1024 );
+		Sys_Printf( "                        %9d MB\n", size / (1024 * 1024) );
+		
+		Sys_Printf( "---------------------------------\n" );
+	}
+	
+	/* return count */
+	return i;
+}
+
+
+
+/*
+ScaleBSPMain()
+amaze and confuse your enemies with wierd scaled maps!
+*/
+
+int ScaleBSPMain( int argc, char **argv )
+{
+	int			i;
+	float		f, scale;
+	vec3_t		vec;
+	char		str[ 1024 ];
+	
+	
+	/* arg checking */
+	if( argc < 2 )
+	{
+		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+		return 0;
+	}
+	
+	/* get scale */
+	scale = atof( argv[ argc - 2 ] );
+	if( scale == 0.0f )
+	{
+		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+		Sys_Printf( "Non-zero scale value required.\n" );
+		return 0;
+	}
+	
+	/* do some path mangling */
+	strcpy( source, ExpandArg( argv[ argc - 1 ] ) );
+	StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	
+	/* load the bsp */
+	Sys_Printf( "Loading %s\n", source );
+	LoadBSPFile( source );
+	ParseEntities();
+	
+	/* note it */
+	Sys_Printf( "--- ScaleBSP ---\n" );
+	Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
+	
+	/* scale entity keys */
+	for( i = 0; i < numBSPEntities && i < numEntities; i++ )
+	{
+		/* scale origin */
+		GetVectorForKey( &entities[ i ], "origin", vec );
+		if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) )
+		{
+			VectorScale( vec, scale, vec );
+			sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
+			SetKeyValue( &entities[ i ], "origin", str );
+		}
+		
+		/* scale door lip */
+		f = FloatForKey( &entities[ i ], "lip" );
+		if( f )
+		{
+			f *= scale;
+			sprintf( str, "%f", f );
+			SetKeyValue( &entities[ i ], "lip", str );
+		}
+	}
+	
+	/* scale models */
+	for( i = 0; i < numBSPModels; i++ )
+	{
+		VectorScale( bspModels[ i ].mins, scale, bspModels[ i ].mins );
+		VectorScale( bspModels[ i ].maxs, scale, bspModels[ i ].maxs );
+	}
+	
+	/* scale nodes */
+	for( i = 0; i < numBSPNodes; i++ )
+	{
+		VectorScale( bspNodes[ i ].mins, scale, bspNodes[ i ].mins );
+		VectorScale( bspNodes[ i ].maxs, scale, bspNodes[ i ].maxs );
+	}
+	
+	/* scale leafs */
+	for( i = 0; i < numBSPLeafs; i++ )
+	{
+		VectorScale( bspLeafs[ i ].mins, scale, bspLeafs[ i ].mins );
+		VectorScale( bspLeafs[ i ].maxs, scale, bspLeafs[ i ].maxs );
+	}
+	
+	/* scale drawverts */
+	for( i = 0; i < numBSPDrawVerts; i++ )
+		VectorScale( bspDrawVerts[ i ].xyz, scale, bspDrawVerts[ i ].xyz );
+	
+	/* scale planes */
+	for( i = 0; i < numBSPPlanes; i++ )
+		bspPlanes[ i ].dist *= scale;
+	
+	/* scale gridsize */
+	GetVectorForKey( &entities[ 0 ], "gridsize", vec );
+	if( (vec[ 0 ] + vec[ 1 ] + vec[ 2 ]) == 0.0f )
+		VectorCopy( gridSize, vec );
+	VectorScale( vec, scale, vec );
+	sprintf( str, "%f %f %f", vec[ 0 ], vec[ 1 ], vec[ 2 ] );
+	SetKeyValue( &entities[ 0 ], "gridsize", str );
+	
+	/* write the bsp */
+	UnparseEntities();
+	StripExtension( source );
+	DefaultExtension( source, "_s.bsp" );
+	Sys_Printf( "Writing %s\n", source );
+	WriteBSPFile( source );
+	
+	/* return to sender */
+	return 0;
+}
+
+
+
+/*
+ConvertBSPMain()
+main argument processing function for bsp conversion
+*/
+
+int ConvertBSPMain( int argc, char **argv )
+{
+	int		i;
+	int		(*convertFunc)( char * );
+	
+	
+	/* set default */
+	convertFunc = ConvertBSPToASE;
+	
+	/* arg checking */
+	if( argc < 1 )
+	{
+		Sys_Printf( "Usage: q3map -scale <value> [-v] <mapname>\n" );
+		return 0;
+	}
+	
+	/* process arguments */
+	for( i = 1; i < (argc - 1); i++ )
+	{
+		/* -format map|ase|... */
+		if( !strcmp( argv[ i ],  "-format" ) )
+ 		{
+			i++;
+			if( !Q_stricmp( argv[ i ], "ase" ) )
+				convertFunc = ConvertBSPToASE;
+			else if( !Q_stricmp( argv[ i ], "map" ) )
+				convertFunc = ConvertBSPToMap;
+			else
+				Sys_Printf( "Unknown conversion format \"%s\". Defaulting to ASE.\n", argv[ i ] );
+ 		}
+	}
+	
+	/* clean up map name */
+	strcpy( source, ExpandArg( argv[ i ] ) );
+	StripExtension( source );
+	DefaultExtension( source, ".bsp" );
+	
+	LoadShaderInfo();
+	
+	Sys_Printf( "Loading %s\n", source );
+	
+	/* ydnar: load surface file */
+	//%	LoadSurfaceExtraFile( source );
+	
+	LoadBSPFile( source );
+	
+	/* parse bsp entities */
+	ParseEntities();
+	
+	/* convert */
+	return convertFunc( source );
+}
+
+
+
+/*
+main()
+q3map mojo...
+*/
+
+int main( int argc, char **argv )
+{
+	int		i, r;
+	double	start, end;
+	
+	
+	/* we want consistent 'randomness' */
+	srand( 0 );
+	
+	/* start timer */
+	start = I_FloatTime();
+
+	/* this was changed to emit version number over the network */
+	printf( Q3MAP_VERSION "\n" );
+	
+	/* set exit call */
+	atexit( ExitQ3Map );
+	
+	/* read general options first */
+	for( i = 1; i < argc; i++ )
+	{
+		/* -connect */
+		if( !strcmp( argv[ i ], "-connect" ) )
+		{
+			argv[ i ] = NULL;
+			i++;
+			Broadcast_Setup( argv[ i ] );
+			argv[ i ] = NULL;
+		}
+		
+		/* verbose */
+		else if( !strcmp( argv[ i ], "-v" ) )
+		{
+			verbose = qtrue;
+			argv[ i ] = NULL;
+		}
+		
+		/* force */
+		else if( !strcmp( argv[ i ], "-force" ) )
+		{
+			force = qtrue;
+			argv[ i ] = NULL;
+		}
+		
+		/* patch subdivisions */
+		else if( !strcmp( argv[ i ], "-subdivisions" ) )
+		{
+			argv[ i ] = NULL;
+			i++;
+			patchSubdivisions = atoi( argv[ i ] );
+			argv[ i ] = NULL;
+			if( patchSubdivisions <= 0 )
+				patchSubdivisions = 1;
+		}
+		
+		/* threads */
+		else if( !strcmp( argv[ i ], "-threads" ) )
+		{
+			argv[ i ] = NULL;
+			i++;
+			numthreads = atoi( argv[ i ] );
+			argv[ i ] = NULL;
+		}
+	}
+	
+	/* init model library */
+	PicoInit();
+	PicoSetMallocFunc( safe_malloc );
+	PicoSetFreeFunc( free );
+	PicoSetPrintFunc( PicoPrintFunc );
+	PicoSetLoadFileFunc( PicoLoadFileFunc );
+	PicoSetFreeFileFunc( free );
+	
+	/* set number of threads */
+	ThreadSetDefault();
+	
+	/* generate sinusoid jitter table */
+	for( i = 0; i < MAX_JITTERS; i++ )
+	{
+		jitters[ i ] = sin( i * 139.54152147 );
+		//%	Sys_Printf( "Jitter %4d: %f\n", i, jitters[ i ] );
+	}
+	
+	/* we print out two versions, q3map's main version (since it evolves a bit out of GtkRadiant)
+	   and we put the GtkRadiant version to make it easy to track with what version of Radiant it was built with */
+	
+	Sys_Printf( "Q3Map         - v1.0r (c) 1999 Id Software Inc.\n" );
+	Sys_Printf( "Q3Map (ydnar) - v" Q3MAP_VERSION "\n" );
+	Sys_Printf( "GtkRadiant    - v" RADIANT_VERSION " " __DATE__ " " __TIME__ "\n" );
+	Sys_Printf( "%s\n", Q3MAP_MOTD );
+	
+	/* ydnar: new path initialization */
+	InitPaths( &argc, argv );
+	
+	/* check if we have enough options left to attempt something */
+	if( argc < 2 )
+		Error( "Usage: %s [general options] [options] mapfile", argv[ 0 ] );
+	
+	/* info */
+	if( !strcmp( argv[ 1 ], "-info" ) )
+		r = BSPInfo( argc - 2, argv + 2 );
+	
+	/* vis */
+	else if( !strcmp( argv[ 1 ], "-vis" ) )
+		r = VisMain( argc - 1, argv + 1 );
+	
+	/* light */
+	else if( !strcmp( argv[ 1 ], "-light" ) )
+		r = LightMain( argc - 1, argv + 1 );
+	
+	/* vlight */
+	else if( !strcmp( argv[ 1 ], "-vlight" ) )
+	{
+		Sys_Printf( "WARNING: VLight is no longer supported, defaulting to -light -fast instead\n\n" );
+		argv[ 1 ] = "-fast";	/* eek a hack */
+		r = LightMain( argc, argv );
+	}
+	
+	/* ydnar: lightmap export */
+	else if( !strcmp( argv[ 1 ], "-export" ) )
+		r = ExportLightmapsMain( argc - 1, argv + 1 );
+	
+	/* ydnar: lightmap import */
+	else if( !strcmp( argv[ 1 ], "-import" ) )
+		r = ImportLightmapsMain( argc - 1, argv + 1 );
+	
+	/* ydnar: bsp scaling */
+	else if( !strcmp( argv[ 1 ], "-scale" ) )
+		r = ScaleBSPMain( argc - 1, argv + 1 );
+	
+	/* ydnar: bsp conversion */
+	else if( !strcmp( argv[ 1 ], "-convert" ) )
+		r = ConvertBSPMain( argc - 1, argv + 1 );
+	
+	/* ydnar: otherwise create a bsp */
+	else
+		r = BSPMain( argc, argv );
+	
+	/* emit time */
+	end = I_FloatTime();
+	Sys_Printf( "%9.0f seconds elapsed\n", end - start );
+	
+	/* shut down connection */
+	Broadcast_Shutdown();
+	
+	/* return any error code */
+	return r;
+}
diff --git a/tools/quake3/q3map2/map.c b/tools/quake3/q3map2/map.c
index dbc71f14..633d327a 100644
--- a/tools/quake3/q3map2/map.c
+++ b/tools/quake3/q3map2/map.c
@@ -1,1649 +1,1649 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define MAP_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* FIXME: remove these vars */
-
-/* undefine to make plane finding use linear sort (note: really slow) */
-#define	USE_HASHING
-#define	PLANE_HASHES	8192
-
-plane_t					*planehash[ PLANE_HASHES ];
-
-int						c_boxbevels;
-int						c_edgebevels;
-int						c_areaportals;
-int						c_detail;
-int						c_structural;
-
-
-
-/*
-PlaneEqual()
-ydnar: replaced with variable epsilon for djbob
-*/
-
-#define	NORMAL_EPSILON	0.00001
-#define	DIST_EPSILON	0.01
-
-qboolean PlaneEqual( plane_t *p, vec3_t normal, vec_t dist )
-{
-	float	ne, de;
-	
-	
-	/* get local copies */
-	ne = normalEpsilon;
-	de = distanceEpsilon;
-	
-	/* compare */
-	if( fabs( p->dist - dist ) <= de &&
-		fabs( p->normal[ 0 ] - normal[ 0 ] ) <= ne &&
-		fabs( p->normal[ 1 ] - normal[ 1 ] ) <= ne &&
-		fabs( p->normal[ 2 ] - normal[ 2 ] ) <= ne )
-		return qtrue;
-	
-	/* different */
-	return qfalse;
-}
-
-
-
-/*
-AddPlaneToHash()
-*/
-
-void AddPlaneToHash( plane_t *p )
-{
-	int		hash;
-
-	
-	hash = (PLANE_HASHES - 1) & (int) fabs( p->dist );
-
-	p->hash_chain = planehash[hash];
-	planehash[hash] = p;
-}
-
-/*
-================
-CreateNewFloatPlane
-================
-*/
-int CreateNewFloatPlane (vec3_t normal, vec_t dist)
-{
-	plane_t	*p, temp;
-
-	if (VectorLength(normal) < 0.5)
-	{
-		Sys_Printf( "FloatPlane: bad normal\n");
-		return -1;
-	}
-
-	// create a new plane
-	if (nummapplanes+2 > MAX_MAP_PLANES)
-		Error ("MAX_MAP_PLANES");
-
-	p = &mapplanes[nummapplanes];
-	VectorCopy (normal, p->normal);
-	p->dist = dist;
-	p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
-
-	VectorSubtract (vec3_origin, normal, (p+1)->normal);
-	(p+1)->dist = -dist;
-
-	nummapplanes += 2;
-
-	// allways put axial planes facing positive first
-	if (p->type < 3)
-	{
-		if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
-		{
-			// flip order
-			temp = *p;
-			*p = *(p+1);
-			*(p+1) = temp;
-
-			AddPlaneToHash (p);
-			AddPlaneToHash (p+1);
-			return nummapplanes - 1;
-		}
-	}
-
-	AddPlaneToHash (p);
-	AddPlaneToHash (p+1);
-	return nummapplanes - 2;
-}
-
-
-
-/*
-SnapNormal()
-snaps a near-axial normal vector
-*/
-
-void SnapNormal( vec3_t normal )
-{
-	int		i;
-
-	for( i = 0; i < 3; i++ )
-	{
-		if( fabs( normal[ i ] - 1 ) < normalEpsilon )
-		{
-			VectorClear( normal );
-			normal[ i ] = 1;
-			break;
-		}
-		if( fabs( normal[ i ] - -1 ) < normalEpsilon )
-		{
-			VectorClear( normal );
-			normal[ i ] = -1;
-			break;
-		}
-	}
-}
-
-
-
-/*
-SnapPlane()
-snaps a plane to normal/distance epsilons
-*/
-
-void SnapPlane( vec3_t normal, vec_t *dist )
-{
-	SnapNormal( normal );
-
-	if( fabs( *dist - Q_rint( *dist ) ) < distanceEpsilon )
-		*dist = Q_rint( *dist );
-}
-
-
-
-/*
-FindFloatPlane()
-ydnar: changed to allow a number of test points to be supplied that
-must be within an epsilon distance of the plane
-*/
-
-int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
-
-#ifdef USE_HASHING
-
-{
-	int		i, j, hash, h;
-	plane_t	*p;
-	vec_t	d;
-	
-	
-	/* hash the plane */
-	SnapPlane( normal, &dist );
-	hash = (PLANE_HASHES - 1) & (int) fabs( dist );
-	
-	/* search the border bins as well */
-	for( i = -1; i <= 1; i++ )
-	{
-		h = (hash + i) & (PLANE_HASHES - 1);
-		for( p = planehash[ h ]; p != NULL; p = p->hash_chain )
-		{
-			/* do standard plane compare */
-			if( !PlaneEqual( p, normal, dist ) )
-				continue;
-			
-			/* ydnar: uncomment the following line for old-style plane finding */
-			//%	return p - mapplanes;
-			
-			/* ydnar: test supplied points against this plane */
-			for( j = 0; j < numPoints; j++ )
-			{
-				d = DotProduct( points[ j ], normal ) - dist;
-				if( fabs( d ) > distanceEpsilon )
-					break;
-			}
-			
-			/* found a matching plane */
-			if( j >= numPoints )
-				return p - mapplanes;
-		}
-	}
-	
-	/* none found, so create a new one */
-	return CreateNewFloatPlane( normal, dist );
-}
-
-#else
-
-{
-	int		i;
-	plane_t	*p;
-	
-
-	SnapPlane( normal, &dist );
-	for( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
-	{
-		if( PlaneEqual( p, normal, dist ) )
-			return i;
-	}
-	
-	return CreateNewFloatPlane( normal, dist );
-}
-
-#endif
-
-
-
-/*
-MapPlaneFromPoints()
-takes 3 points and finds the plane they lie in
-*/
-
-int MapPlaneFromPoints( vec3_t *p )
-{
-	vec3_t	t1, t2, normal;
-	vec_t	dist;
-	
-	
-	/* calc plane normal */
-	VectorSubtract( p[ 0 ], p[ 1 ], t1 );
-	VectorSubtract( p[ 2 ], p[ 1 ], t2 );
-	CrossProduct( t1, t2, normal );
-	VectorNormalize( normal, normal );
-	
-	/* calc plane distance */
-	dist = DotProduct( p[ 0 ], normal );
-	
-	/* store the plane */
-	return FindFloatPlane( normal, dist, 3, p );
-}
-
-
-
-/*
-SetBrushContents()
-the content flags and compile flags on all sides of a brush should be the same
-*/
-
-void SetBrushContents( brush_t *b )
-{
-	int			contentFlags, compileFlags;
-	side_t		*s;
-	int			i;
-	qboolean	mixed;
-	
-	
-	/* get initial compile flags from first side */
-	s = &b->sides[ 0 ];
-	contentFlags = s->contentFlags;
-	compileFlags = s->compileFlags;
-	b->contentShader = s->shaderInfo;
-	mixed = qfalse;
-	
-	/* get the content/compile flags for every side in the brush */
-	for( i = 1; i < b->numsides; i++, s++ )
-	{
-		s = &b->sides[ i ];
-		if( s->shaderInfo == NULL )
-			continue;
-		if( s->contentFlags != contentFlags || s->compileFlags != compileFlags )
-			mixed = qtrue;
-	}
-	
-	/* ydnar: getting rid of this stupid warning */
-	//%	if( mixed )
-	//%		Sys_FPrintf( SYS_VRB,"Entity %i, Brush %i: mixed face contentFlags\n", b->entitynum, b->brushnum );
-
-	/* check for detail & structural */
-	if( (compileFlags & C_DETAIL) && (compileFlags & C_STRUCTURAL) )
-	{
-		xml_Select( "Mixed detail and structural (defaulting to structural)", mapEnt->mapEntityNum, entitySourceBrushes, qfalse );
-		compileFlags &= ~C_DETAIL;
-	}
-	
-	/* the fulldetail flag will cause detail brushes to be treated like normal brushes */
-	if( fulldetail )
-		compileFlags &= ~C_DETAIL;
-	
-	/* all translucent brushes that aren't specifically made structural will be detail */
-	if( (compileFlags & C_TRANSLUCENT) && !(compileFlags & C_STRUCTURAL) )
-		compileFlags |= C_DETAIL;
-	
-	/* detail? */
-	if( compileFlags & C_DETAIL )
-	{
-		c_detail++;
-		b->detail = qtrue;
-	}
-	else
-	{
-		c_structural++;
-		b->detail = qfalse;
-	}
-	
-	/* opaque? */
-	if( compileFlags & C_TRANSLUCENT )
-		b->opaque = qfalse;
-	else
-		b->opaque = qtrue;
-	
-	/* areaportal? */
-	if( compileFlags & C_AREAPORTAL )
-		c_areaportals++;
-	
-	/* set brush flags */
-	b->contentFlags = contentFlags;
-	b->compileFlags = compileFlags;
-}
-
-
-
-/*
-AddBrushBevels()
-adds any additional planes necessary to allow the brush being
-built to be expanded against axial bounding boxes
-ydnar 2003-01-20: added mrelusive fixes
-*/
-
-void AddBrushBevels( void )
-{
-	int			axis, dir;
-	int			i, j, k, l, order;
-	side_t		sidetemp;
-	side_t		*s, *s2;
-	winding_t	*w, *w2;
-	vec3_t		normal;
-	float		dist;
-	vec3_t		vec, vec2;
-	float		d, minBack;
-
-	//
-	// add the axial planes
-	//
-	order = 0;
-	for ( axis = 0; axis < 3; axis++ ) {
-		for ( dir = -1; dir <= 1; dir += 2, order++ ) {
-			// see if the plane is allready present
-			for ( i = 0, s = buildBrush->sides; i < buildBrush->numsides; i++, s++ )
-			{
-				/* ydnar: testing disabling of mre code */
-				#if 0
-					if ( dir > 0 ) {
-						if ( mapplanes[s->planenum].normal[axis] >= 0.9999f ) {
-							break;
-						}
-					}
-					else {
-						if ( mapplanes[s->planenum].normal[axis] <= -0.9999f ) {
-							break;
-						}
-					}
-				#else
-					if( (dir > 0 && mapplanes[ s->planenum ].normal[ axis ] == 1.0f ) ||
-						(dir < 0 && mapplanes[ s->planenum ].normal[ axis ] == -1.0f) )
-						break;
-				#endif
-			}
-
-			if ( i == buildBrush->numsides ) {
-				// add a new side
-				if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
-					xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, qtrue);
-				}
-				memset( s, 0, sizeof( *s ) );
-				buildBrush->numsides++;
-				VectorClear (normal);
-				normal[axis] = dir;
-
-				if( dir == 1 )
-				{
-					/* ydnar: adding bevel plane snapping for fewer bsp planes */
-					if( bevelSnap > 0 )
-						dist = floor( buildBrush->maxs[ axis ] / bevelSnap ) * bevelSnap;
-					else
-						dist = buildBrush->maxs[ axis ];
-				}
-				else
-				{
-					/* ydnar: adding bevel plane snapping for fewer bsp planes */
-					if( bevelSnap > 0 )
-						dist = -ceil( buildBrush->mins[ axis ] / bevelSnap ) * bevelSnap;
-					else
-						dist = -buildBrush->mins[ axis ];
-				}
-
-				s->planenum = FindFloatPlane( normal, dist, 0, NULL );
-				s->contentFlags = buildBrush->sides[ 0 ].contentFlags;
-				s->bevel = qtrue;
-				c_boxbevels++;
-			}
-
-			// if the plane is not in it canonical order, swap it
-			if ( i != order ) {
-				sidetemp = buildBrush->sides[order];
-				buildBrush->sides[order] = buildBrush->sides[i];
-				buildBrush->sides[i] = sidetemp;
-			}
-		}
-	}
-
-	//
-	// add the edge bevels
-	//
-	if ( buildBrush->numsides == 6 ) {
-		return;		// pure axial
-	}
-
-	// test the non-axial plane edges
-	for ( i = 6; i < buildBrush->numsides; i++ ) {
-		s = buildBrush->sides + i;
-		w = s->winding;
-		if ( !w ) {
-			continue;
-		}
-		for ( j = 0; j < w->numpoints; j++) {
-			k = (j+1)%w->numpoints;
-			VectorSubtract( w->p[j], w->p[k], vec );
-			if ( VectorNormalize( vec, vec ) < 0.5f ) {
-				continue;
-			}
-			SnapNormal( vec );
-			for ( k = 0; k < 3; k++ ) {
-				if ( vec[k] == -1.0f || vec[k] == 1.0f || (vec[k] == 0.0f && vec[(k+1)%3] == 0.0f) ) {
-					break;	// axial
-				}
-			}
-			if ( k != 3 ) {
-				continue;	// only test non-axial edges
-			}
-
-			/* debug code */
-			//%	Sys_Printf( "-------------\n" );
-
-			// try the six possible slanted axials from this edge
-			for ( axis = 0; axis < 3; axis++ ) {
-				for ( dir = -1; dir <= 1; dir += 2 ) {
-					// construct a plane
-					VectorClear( vec2 );
-					vec2[axis] = dir;
-					CrossProduct( vec, vec2, normal );
-					if ( VectorNormalize( normal, normal ) < 0.5f ) {
-						continue;
-					}
-					dist = DotProduct( w->p[j], normal );
-					
-					// if all the points on all the sides are
-					// behind this plane, it is a proper edge bevel
-					for ( k = 0; k < buildBrush->numsides; k++ ) {
-
-						// if this plane has allready been used, skip it
-						if ( PlaneEqual( &mapplanes[buildBrush->sides[k].planenum], normal, dist ) ) {
-							break;
-						}
-
-						w2 = buildBrush->sides[k].winding;
-						if ( !w2 ) {
-							continue;
-						}
-						minBack = 0.0f;
-						for ( l = 0; l < w2->numpoints; l++ ) {
-							d = DotProduct( w2->p[l], normal ) - dist;
-							if ( d > 0.1f ) {
-								break;	// point in front
-							}
-							if ( d < minBack ) {
-								minBack = d;
-							}
-						}
-						// if some point was at the front
-						if ( l != w2->numpoints ) {
-							break;
-						}
-
-						// if no points at the back then the winding is on the bevel plane
-						if ( minBack > -0.1f ) {
-							//%	Sys_Printf( "On bevel plane\n" );
-							break;
-						}
-					}
-
-					if ( k != buildBrush->numsides ) {
-						continue;	// wasn't part of the outer hull
-					}
-					
-					/* debug code */
-					//%	Sys_Printf( "n = %f %f %f\n", normal[ 0 ], normal[ 1 ], normal[ 2 ] );
-					
-					// add this plane
-					if( buildBrush->numsides == MAX_BUILD_SIDES ) {
-						xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, qtrue);
-					}
-					s2 = &buildBrush->sides[buildBrush->numsides];
-					buildBrush->numsides++;
-					memset( s2, 0, sizeof( *s2 ) );
-
-					s2->planenum = FindFloatPlane( normal, dist, 1, &w->p[ j ] );
-					s2->contentFlags = buildBrush->sides[0].contentFlags;
-					s2->bevel = qtrue;
-					c_edgebevels++;
-				}
-			}
-		}
-	}
-}
-
-
-
-/*
-FinishBrush()
-produces a final brush based on the buildBrush->sides array
-and links it to the current entity
-*/
-
-brush_t *FinishBrush( void )
-{
-	brush_t	*b;
-	
-	
-	/* create windings for sides and bounds for brush */
-	if ( !CreateBrushWindings( buildBrush ) )
-		return NULL;
-
-	/* origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity.
-	   after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush */
-	if( buildBrush->compileFlags & C_ORIGIN )
-	{
-		char	string[ 32 ];
-		vec3_t	origin;
-
-		if( numEntities == 1 )
-		{
-			Sys_Printf( "Entity %i, Brush %i: origin brushes not allowed in world\n", 
-				mapEnt->mapEntityNum, entitySourceBrushes );
-			return NULL;
-		}
-		
-		VectorAdd (buildBrush->mins, buildBrush->maxs, origin);
-		VectorScale (origin, 0.5, origin);
-
-		sprintf( string, "%i %i %i", (int) origin[ 0 ], (int) origin[ 1 ], (int) origin[ 2 ] );
-		SetKeyValue( &entities[ numEntities - 1 ], "origin", string);
-
-		VectorCopy( origin, entities[ numEntities - 1 ].origin);
-
-		/* don't keep this brush */
-		return NULL;
-	}
-	
-	/* determine if the brush is an area portal */
-	if( buildBrush->compileFlags & C_AREAPORTAL )
-	{
-		if( numEntities != 1 )
-		{
-			Sys_Printf ("Entity %i, Brush %i: areaportals only allowed in world\n", numEntities - 1, entitySourceBrushes );
-			return NULL;
-		}
-	}
-	
-	/* add bevel planes */
-	AddBrushBevels();
-	
-	/* keep it */
-	b = CopyBrush( buildBrush );
-	
-	/* set map entity and brush numbering */
-	b->entityNum = mapEnt->mapEntityNum;
-	b->brushNum = entitySourceBrushes;
-	
-	/* set original */
-	b->original = b;
-	
-	/* link opaque brushes to head of list, translucent brushes to end */
-	if( b->opaque || mapEnt->lastBrush == NULL )
-	{
-		b->next = mapEnt->brushes;
-		mapEnt->brushes = b;
-		if( mapEnt->lastBrush == NULL )
-			mapEnt->lastBrush = b;
-	}
-	else
-	{
-		b->next = NULL;
-		mapEnt->lastBrush->next = b;
-		mapEnt->lastBrush = b;
-	}
-	
-	/* return to sender */
-	return b;
-}
-
-
-
-/*
-TextureAxisFromPlane()
-determines best orthagonal axis to project a texture onto a wall
-(must be identical in radiant!)
-*/
-
-vec3_t	baseaxis[18] =
-{
-	{0,0,1}, {1,0,0}, {0,-1,0},			// floor
-	{0,0,-1}, {1,0,0}, {0,-1,0},		// ceiling
-	{1,0,0}, {0,1,0}, {0,0,-1},			// west wall
-	{-1,0,0}, {0,1,0}, {0,0,-1},		// east wall
-	{0,1,0}, {1,0,0}, {0,0,-1},			// south wall
-	{0,-1,0}, {1,0,0}, {0,0,-1}			// north wall
-};
-
-void TextureAxisFromPlane( plane_t *pln, vec3_t xv, vec3_t yv )
-{
-	int		bestaxis;
-	vec_t	dot,best;
-	int		i;
-	
-	best = 0;
-	bestaxis = 0;
-	
-	for (i=0 ; i<6 ; i++)
-	{
-		dot = DotProduct (pln->normal, baseaxis[i*3]);
-		if( dot > best + 0.0001f )	/* ydnar: bug 637 fix, suggested by jmonroe */
-		{
-			best = dot;
-			bestaxis = i;
-		}
-	}
-	
-	VectorCopy (baseaxis[bestaxis*3+1], xv);
-	VectorCopy (baseaxis[bestaxis*3+2], yv);
-}
-
-
-
-/*
-QuakeTextureVecs()
-creates world-to-texture mapping vecs for crappy quake plane arrangements
-*/
-
-void QuakeTextureVecs( plane_t *plane, vec_t shift[ 2 ], vec_t rotate, vec_t scale[ 2 ], vec_t mappingVecs[ 2 ][ 4 ] )
-{
-	vec3_t	vecs[2];
-	int		sv, tv;
-	vec_t	ang, sinv, cosv;
-	vec_t	ns, nt;
-	int		i, j;
-	
-	
-	TextureAxisFromPlane(plane, vecs[0], vecs[1]);
-	
-	if (!scale[0])
-		scale[0] = 1;
-	if (!scale[1])
-		scale[1] = 1;
-
-	// rotate axis
-	if (rotate == 0)
-		{ sinv = 0 ; cosv = 1; }
-	else if (rotate == 90)
-		{ sinv = 1 ; cosv = 0; }
-	else if (rotate == 180)
-		{ sinv = 0 ; cosv = -1; }
-	else if (rotate == 270)
-		{ sinv = -1 ; cosv = 0; }
-	else
-	{	
-		ang = rotate / 180 * Q_PI;
-		sinv = sin(ang);
-		cosv = cos(ang);
-	}
-
-	if (vecs[0][0])
-		sv = 0;
-	else if (vecs[0][1])
-		sv = 1;
-	else
-		sv = 2;
-				
-	if (vecs[1][0])
-		tv = 0;
-	else if (vecs[1][1])
-		tv = 1;
-	else
-		tv = 2;
-					
-	for (i=0 ; i<2 ; i++) {
-		ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
-		nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
-		vecs[i][sv] = ns;
-		vecs[i][tv] = nt;
-	}
-
-	for (i=0 ; i<2 ; i++)
-		for (j=0 ; j<3 ; j++)
-			mappingVecs[i][j] = vecs[i][j] / scale[i];
-
-	mappingVecs[0][3] = shift[0];
-	mappingVecs[1][3] = shift[1];
-}
-
-
-
-/*
-ParseRawBrush()
-parses the sides into buildBrush->sides[], nothing else.
-no validation, back plane removal, etc.
-
-Timo - 08/26/99
-added brush epairs parsing ( ignoring actually )
-Timo - 08/04/99
-added exclusive brush primitive parsing
-Timo - 08/08/99
-support for old brush format back in
-NOTE: it would be "cleaner" to have seperate functions to parse between old and new brushes
-*/
-
-static void ParseRawBrush( qboolean onlyLights )
-{
-	side_t			*side;
-	vec3_t			planePoints[ 3 ];
-	int				planenum;
-	shaderInfo_t	*si;
-	vec_t			shift[ 2 ];
-	vec_t			rotate;
-	vec_t			scale[ 2 ];
-	char			name[ MAX_QPATH ];
-	char			shader[ MAX_QPATH ];
-	int				flags;
-	
-	
-	/* initial setup */
-	buildBrush->numsides = 0;
-	buildBrush->detail = qfalse;
-	
-	/* bp */
-	if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
-		MatchToken( "{" );
-	
-	/* parse sides */
-	while( 1 )
-	{
-		if( !GetToken( qtrue ) )
-			break;
-		if( !strcmp( token, "}" ) )
-			break;
-		 
-		/* ttimo : bp: here we may have to jump over brush epairs (only used in editor) */
-		if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
-		{
-			while( 1 )
-			{
-				if( strcmp( token, "(" ) )
-					GetToken( qfalse );
-				else
-					break;
-				GetToken( qtrue );
-			}
-		}
-		UnGetToken();
-		
-		/* test side count */
-		if( buildBrush->numsides >= MAX_BUILD_SIDES )
-			xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, qtrue );
-		
-		/* add side */
-		side = &buildBrush->sides[ buildBrush->numsides ];
-		memset( side, 0, sizeof( *side ) );
-		buildBrush->numsides++;
-		
-		/* read the three point plane definition */
-		Parse1DMatrix( 3, planePoints[ 0 ] );
-		Parse1DMatrix( 3, planePoints[ 1 ] );
-		Parse1DMatrix( 3, planePoints[ 2 ] );
-		
-		/* bp: read the texture matrix */
-		if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
-			Parse2DMatrix( 2, 3, (float*) side->texMat );
-		
-		/* read shader name */
-		GetToken( qfalse );
-		strcpy( name, token );
-		
-		/* bp */
-		if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
-		{
-			GetToken( qfalse );
-			shift[ 0 ] = atof( token );
-			GetToken( qfalse );
-			shift[ 1 ] = atof( token );
-			GetToken( qfalse );
-			rotate = atof( token );	
-			GetToken( qfalse );
-			scale[ 0 ] = atof( token );
-			GetToken( qfalse );
-			scale[ 1 ] = atof( token );
-		}
-		
-		/* set default flags and values */
-		sprintf( shader, "textures/%s", name );
-		if( onlyLights )
-			si = &shaderInfo[ 0 ];
-		else
-			si = ShaderInfoForShader( shader );
-		side->shaderInfo = si;
-		side->surfaceFlags = si->surfaceFlags;
-		side->contentFlags = si->contentFlags;
-		side->compileFlags = si->compileFlags;
-		side->value = si->value;
-		
-		/* ydnar: gs mods: bias texture shift */
-		if( si->globalTexture == qfalse )
-		{
-			shift[ 0 ] -= (floor( shift[ 0 ] / si->shaderWidth ) * si->shaderWidth);
-			shift[ 1 ] -= (floor( shift[ 1 ] / si->shaderHeight ) * si->shaderHeight);
-		}
-		
-		/*
-			historically, there are 3 integer values at the end of a brushside line in a .map file.
-			in quake 3, the only thing that mattered was the first of these three values, which
-			was previously the content flags. and only then did a single bit matter, the detail
-			bit. because every game has its own special flags for specifying detail, the
-			traditionally game-specified CONTENTS_DETAIL flag was overridden for Q3Map 2.3.0
-			by C_DETAIL, defined in q3map2.h. the value is exactly as it was before, but
-			is stored in compileFlags, as opposed to contentFlags, for multiple-game
-			portability. :sigh:
-		*/
-		
-		if( TokenAvailable() )
-		{
-			/* get detail bit from map content flags */
-			GetToken( qfalse );
-			flags = atoi( token );
-			if( flags & C_DETAIL )
-				side->compileFlags |= C_DETAIL;
-			
-			/* historical */
-			GetToken( qfalse );
-			//% td.flags = atoi( token );
-			GetToken( qfalse );
-			//% td.value = atoi( token );
-		}
-		
-		/* find the plane number */
-		planenum = MapPlaneFromPoints( planePoints );
-		side->planenum = planenum;
-		
-		/* bp: get the texture mapping for this texturedef / plane combination */
-		if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
-			QuakeTextureVecs( &mapplanes[ planenum ], shift, rotate, scale, side->vecs );
-	}
-	
-	/* bp */
-	if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
-	{
-		UnGetToken();
-		MatchToken( "}" );
-		MatchToken( "}" );
-	}
-}
-
-
-
-/*
-RemoveDuplicateBrushPlanes
-returns false if the brush has a mirrored set of planes,
-meaning it encloses no volume.
-also removes planes without any normal
-*/
-
-qboolean RemoveDuplicateBrushPlanes( brush_t *b )
-{
-	int			i, j, k;
-	side_t		*sides;
-
-	sides = b->sides;
-
-	for ( i = 1 ; i < b->numsides ; i++ ) {
-
-		// check for a degenerate plane
-		if ( sides[i].planenum == -1) {
-		  xml_Select( "degenerate plane", b->entityNum, b->brushNum, qfalse );
-			// remove it
-			for ( k = i + 1 ; k < b->numsides ; k++ ) {
-				sides[k-1] = sides[k];
-			}
-			b->numsides--;
-			i--;
-			continue;
-		}
-
-		// check for duplication and mirroring
-		for ( j = 0 ; j < i ; j++ ) {
-			if ( sides[i].planenum == sides[j].planenum ) {
-			  xml_Select( "duplicate plane", b->entityNum, b->brushNum, qfalse );
-				// remove the second duplicate
-				for ( k = i + 1 ; k < b->numsides ; k++ ) {
-					sides[k-1] = sides[k];
-				}
-				b->numsides--;
-				i--;
-				break;
-			}
-
-			if ( sides[i].planenum == (sides[j].planenum ^ 1) ) {
-				// mirror plane, brush is invalid
-			  xml_Select( "mirrored plane", b->entityNum, b->brushNum, qfalse );
-				return qfalse;
-			}
-		}
-	}
-	return qtrue;
-}
-
-
-
-/*
-ParseBrush()
-parses a brush out of a map file and sets it up
-*/
-
-static void ParseBrush( qboolean onlyLights )
-{
-	brush_t	*b;
-	
-	
-	/* parse the brush out of the map */
-	ParseRawBrush( onlyLights );
-	
-	/* only go this far? */
-	if( onlyLights )
-		return;
-	
-	/* set some defaults */
-	buildBrush->portalareas[ 0 ] = -1;
-	buildBrush->portalareas[ 1 ] = -1;
-	buildBrush->entityNum = numMapEntities - 1;
-	buildBrush->brushNum = entitySourceBrushes;
-	
-	/* if there are mirrored planes, the entire brush is invalid */
-	if( !RemoveDuplicateBrushPlanes( buildBrush ) )
-		return;
-	
-	/* get the content for the entire brush */
-	SetBrushContents( buildBrush );
-	
-	/* allow detail brushes to be removed */
-	if( nodetail && (buildBrush->compileFlags & C_DETAIL) )
-	{
-		//%	FreeBrush( buildBrush );
-		return;
-	}
-	
-	/* allow liquid brushes to be removed */
-	if( nowater && (buildBrush->compileFlags & C_LIQUID ) )
-	{
-		//%	FreeBrush( buildBrush );
-		return;
-	}
-	
-	/* ydnar: allow hint brushes to be removed */
-	if( noHint && (buildBrush->compileFlags & C_HINT) )
-	{
-		//%	FreeBrush( buildBrush );
-		return;
-	}
-	
-	/* finish the brush */
-	b = FinishBrush();
-}
-
-
-
-/*
-MoveBrushesToWorld()
-takes all of the brushes from the current entity and
-adds them to the world's brush list
-(used by func_group)
-*/
-
-void MoveBrushesToWorld( entity_t *ent )
-{
-	brush_t		*b, *next;
-	parseMesh_t	*pm;
-
-	
-	/* move brushes */
-	for( b = ent->brushes; b != NULL; b = next )
-	{
-		/* get next brush */
-		next = b->next;
-		
-		/* link opaque brushes to head of list, translucent brushes to end */
-		if( b->opaque || entities[ 0 ].lastBrush == NULL )
-		{
-			b->next = entities[ 0 ].brushes;
-			entities[ 0 ].brushes = b;
-			if( entities[ 0 ].lastBrush == NULL )
-				entities[ 0 ].lastBrush = b;
-		}
-		else
-		{
-			b->next = NULL;
-			entities[ 0 ].lastBrush->next = b;
-			entities[ 0 ].lastBrush = b;
-		}
-		
-		//%	b->next = entities[ 0 ].brushes;
-		//%	entities[ 0 ].brushes = b;
-	}
-	ent->brushes = NULL;
-	
-	/* move patches */
-	if( ent->patches != NULL )
-	{
-		for( pm = ent->patches; pm->next; pm = pm->next );
-		
-		pm->next = entities[ 0 ].patches;
-		entities[ 0 ].patches = ent->patches;
-		
-		ent->patches = NULL;
-	}
-}
-
-
-
-/*
-AdjustBrushesForOrigin()
-*/
-
-void AdjustBrushesForOrigin( entity_t *ent )
-{
-	
-	int			i;
-	side_t		*s;
-	vec_t		newdist;
-	brush_t		*b;
-	parseMesh_t	*p;
-	
-	
-	/* walk brush list */
-	for( b = ent->brushes; b != NULL; b = b->next )
-	{
-		/* offset brush planes */
-		for( i = 0; i < b->numsides; i++)
-		{
-			/* get brush side */
-			s = &b->sides[ i ];
-			
-			/* offset side plane */
-			newdist = mapplanes[ s->planenum ].dist - DotProduct( mapplanes[ s->planenum ].normal, ent->origin );
-			
-			/* find a new plane */
-			s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal, newdist, 0, NULL );
-		}
-		
-		/* rebuild brush windings (ydnar: just offsetting the winding above should be fine) */
-		CreateBrushWindings( b );
-	}
-	
-	/* walk patch list */
-	for( p = ent->patches; p != NULL; p = p->next )
-	{
-		for( i = 0; i < (p->mesh.width * p->mesh.height); i++ )
-			VectorSubtract( p->mesh.verts[ i ].xyz, ent->origin, p->mesh.verts[ i ].xyz );
-	}
-}
-
-
-
-/*
-SetEntityBounds() - ydnar
-finds the bounds of an entity's brushes (necessary for terrain-style generic metashaders)
-*/
-
-void SetEntityBounds( entity_t *e )
-{
-	int			i;
-	brush_t	*b;
-	parseMesh_t	*p;
-	vec3_t		mins, maxs;
-	const char	*value;
-
-	
-	
-
-	/* walk the entity's brushes/patches and determine bounds */
-	ClearBounds( mins, maxs );
-	for( b = e->brushes; b; b = b->next )
-	{
-		AddPointToBounds( b->mins, mins, maxs );
-		AddPointToBounds( b->maxs, mins, maxs );
-	}
-	for( p = e->patches; p; p = p->next )
-	{
-		for( i = 0; i < (p->mesh.width * p->mesh.height); i++ )
-			AddPointToBounds( p->mesh.verts[ i ].xyz, mins, maxs );
-	}
-	
-	/* try to find explicit min/max key */
-	value = ValueForKey( e, "min" ); 
-	if( value[ 0 ] != '\0' )
-		GetVectorForKey( e, "min", mins );
-	value = ValueForKey( e, "max" ); 
-	if( value[ 0 ] != '\0' )
-		GetVectorForKey( e, "max", maxs );
-	
-	/* store the bounds */
-	for( b = e->brushes; b; b = b->next )
-	{
-		VectorCopy( mins, b->eMins );
-		VectorCopy( maxs, b->eMaxs );
-	}
-	for( p = e->patches; p; p = p->next )
-	{
-		VectorCopy( mins, p->eMins );
-		VectorCopy( maxs, p->eMaxs );
-	}
-}
-
-
-
-/*
-LoadEntityIndexMap() - ydnar
-based on LoadAlphaMap() from terrain.c, a little more generic
-*/
-
-void LoadEntityIndexMap( entity_t *e )
-{
-	int				i, size, numLayers, w, h;
-	const char		*value, *indexMapFilename, *shader;
-	char			ext[ MAX_QPATH ], offset[ 4096 ], *search, *space;
-	byte			*pixels;
-	unsigned int	*pixels32;
-	indexMap_t		*im;
-	brush_t			*b;
-	parseMesh_t		*p;
-	
-	
-	/* this only works with bmodel ents */
-	if( e->brushes == NULL && e->patches == NULL )
-		return;
-	
-	/* determine if there is an index map (support legacy "alphamap" key as well) */
-	value = ValueForKey( e, "_indexmap" );
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( e, "alphamap" );
-	if( value[ 0 ] == '\0' )
-		return;
-	indexMapFilename = value;
-	
-	/* get number of layers (support legacy "layers" key as well) */
-	value = ValueForKey( e, "_layers" );
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( e, "layers" );
-	if( value[ 0 ] == '\0' )
-	{
-		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" has missing \"_layers\" or \"layers\" key\n", indexMapFilename );
-		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
-		return;
-	}
-	numLayers = atoi( value );
-	if( numLayers < 1 )
-	{
-		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" has < 1 layer (%d)\n", indexMapFilename, numLayers );
-		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
-		return;
-	}
-	
-	/* get base shader name (support legacy "shader" key as well) */
-	value = ValueForKey( mapEnt, "_shader" );
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( e, "shader" );
-	if( value[ 0 ] == '\0' )
-	{
-		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" has missing \"_shader\" or \"shader\" key\n", indexMapFilename );
-		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
-		return;
-	}
-	shader = value;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "Entity %d (%s) has shader index map \"%s\"\n",  mapEnt->mapEntityNum, ValueForKey( e, "classname" ), indexMapFilename );
-	
-	/* get index map file extension */
-	ExtractFileExtension( indexMapFilename, ext );
-	
-	/* handle tga image */
-	if( !Q_stricmp( ext, "tga" ) )
-	{
-		/* load it */
-		Load32BitImage( indexMapFilename, &pixels32, &w, &h );
-		
-		/* convert to bytes */
-		size = w * h;
-		pixels = safe_malloc( size );
-		for( i = 0; i < size; i++ )
-		{
-			pixels[ i ] = ((pixels32[ i ] & 0xFF) * numLayers) / 256;
-			if( pixels[ i ] >= numLayers )
-				pixels[ i ] = numLayers - 1;
-		}
-		
-		/* free the 32 bit image */
-		free( pixels32 );
-	}
-	else
-	{
-		/* load it */
-		Load256Image( indexMapFilename, &pixels, NULL, &w, &h );
-		
-		/* debug code */
-		//%	Sys_Printf( "-------------------------------" );
-		
-		/* fix up out-of-range values */
-		size = w * h;
-		for( i = 0; i < size; i++ )
-		{
-			if( pixels[ i ] >= numLayers )
-				pixels[ i ] = numLayers - 1;
-			
-			/* debug code */
-			//%	if( (i % w) == 0 )
-			//%		Sys_Printf( "\n" );
-			//%	Sys_Printf( "%c", pixels[ i ] + '0' );
-		}
-		
-		/* debug code */
-		//%	Sys_Printf( "\n-------------------------------\n" );
-	}
-	
-	/* the index map must be at least 2x2 pixels */
-	if( w < 2 || h < 2 )
-	{
-		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" is smaller than 2x2 pixels\n", indexMapFilename );
-		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
-		free( pixels );
-		return;
-	}
-
-	/* create a new index map */
-	im = safe_malloc( sizeof( *im ) );
-	memset( im, 0, sizeof( *im ) );
-	
-	/* set it up */
-	im->w = w;
-	im->h = h;
-	im->numLayers = numLayers;
-	strcpy( im->name, indexMapFilename );
-	strcpy( im->shader, shader );
-	im->pixels = pixels;
-	
-	/* get height offsets */
-	value = ValueForKey( mapEnt, "_offsets" );
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( e, "offsets" );
-	if( value[ 0 ] != '\0' )
-	{
-		/* value is a space-seperated set of numbers */
-		strcpy( offset, value );
-		search = offset;
-		
-		/* get each value */
-		for( i = 0; i < 256 && *search != '\0'; i++ )
-		{
-			space = strstr( search, " " );
-			if( space != NULL )
-				*space = '\0';
-			im->offsets[ i ] = atof( search );
-			if( space == NULL )
-				break;
-			search = space + 1;
-		}
-	}
-	
-	/* store the index map in every brush/patch in the entity */
-	for( b = e->brushes; b != NULL; b = b->next )
-		b->im = im;
-	for( p = e->patches; p != NULL; p = p->next )
-		p->im = im;
-}
-
-
-
-
-
-
-
-/*
-ParseMapEntity()
-parses a single entity out of a map file
-*/
-
-static qboolean ParseMapEntity( qboolean onlyLights )
-{
-	epair_t			*ep;
-	const char		*classname, *value;
-	float			lightmapScale;
-	char			shader[ MAX_QPATH ];
-	shaderInfo_t	*celShader = NULL;
-	brush_t			*brush;
-	parseMesh_t		*patch;
-	qboolean		funcGroup;
-	int				castShadows, recvShadows;
-	
-	
-	/* eof check */
-	if( !GetToken( qtrue ) )
-		return qfalse;
-	
-	/* conformance check */
-	if( strcmp( token, "{" ) )
-	{
-		Sys_Printf( "WARNING: ParseEntity: { not found, found %s on line %d - last entity was at: <%4.2f, %4.2f, %4.2f>...\n"
-			"Continuing to process map, but resulting BSP may be invalid.\n",
-			token, scriptline, entities[ numEntities ].origin[ 0 ], entities[ numEntities ].origin[ 1 ], entities[ numEntities ].origin[ 2 ] );
-		return qfalse;
-	}
-	
-	/* range check */
-	if( numEntities >= MAX_MAP_ENTITIES )
-		Error( "numEntities == MAX_MAP_ENTITIES" );
-	
-	/* setup */
-	entitySourceBrushes = 0;
-	mapEnt = &entities[ numEntities ];
-	numEntities++;
-	memset( mapEnt, 0, sizeof( *mapEnt ) );
-	
-	/* ydnar: true entity numbering */
-	mapEnt->mapEntityNum = numMapEntities;
-	numMapEntities++;
-	
-	/* loop */
-	while( 1 )
-	{
-		/* get initial token */
-		if( !GetToken( qtrue ) )
-		{
-			Sys_Printf( "WARNING: ParseEntity: EOF without closing brace\n"
-				"Continuing to process map, but resulting BSP may be invalid.\n" );
-			return qfalse;
-		}
-		
-		if( !strcmp( token, "}" ) )
-			break;
-		
-		if( !strcmp( token, "{" ) )
-		{
-			/* parse a brush or patch */
-			if( !GetToken( qtrue ) )
-				break;
-			
-			/* check */
-			if( !strcmp( token, "patchDef2" ) )
-			{
-				numMapPatches++;
-				ParsePatch( onlyLights );
-			}
-			else if( !strcmp( token, "terrainDef" ) )
-			{
-				//% ParseTerrain();
-				Sys_Printf( "WARNING: Terrain entity parsing not supported in this build.\n" );	/* ydnar */
-			}
-			else if( !strcmp( token, "brushDef" ) )
-			{
-				if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
-					Error( "Old brush format not allowed in new brush format map" );
-				g_bBrushPrimit = BPRIMIT_NEWBRUSHES;
-				
-				/* parse brush primitive */
-				ParseBrush( onlyLights );
-			}
-			else
-			{
-				if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
-					Error( "New brush format not allowed in old brush format map" );
-				g_bBrushPrimit = BPRIMIT_OLDBRUSHES;
-				
-				/* parse old brush format */
-				UnGetToken();
-				ParseBrush( onlyLights );
-			}
-			entitySourceBrushes++;
-		}
-		else
-		{
-			/* parse a key / value pair */
-			ep = ParseEPair();
-			
-			/* ydnar: 2002-07-06 fixed wolf bug with empty epairs */
-			if( ep->key[ 0 ] != '\0' && ep->value[ 0 ] != '\0' )
-			{
-				ep->next = mapEnt->epairs;
-				mapEnt->epairs = ep;
-			}
-		}
-	}
-	
-	/* ydnar: get classname */
-	classname = ValueForKey( mapEnt, "classname" );
-	
-	/* ydnar: only lights? */
-	if( onlyLights && Q_strncasecmp( classname, "light", 5 ) )
-	{
-		numEntities--;
-		return qtrue;
-	}
-	
-	/* ydnar: determine if this is a func_group */
-	if( !Q_stricmp( "func_group", classname ) )
-		funcGroup = qtrue;
-	else
-		funcGroup = qfalse;
-	
-	/* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
-	if( funcGroup || mapEnt->mapEntityNum == 0 )
-	{
-		//%	Sys_Printf( "World:  %d\n", mapEnt->mapEntityNum );
-		castShadows = WORLDSPAWN_CAST_SHADOWS;
-		recvShadows = WORLDSPAWN_RECV_SHADOWS;
-	}
-	
-	/* other entities don't cast any shadows, but recv worldspawn shadows */
-	else
-	{
-		//%	Sys_Printf( "Entity: %d\n", mapEnt->mapEntityNum );
-		castShadows = ENTITY_CAST_SHADOWS;
-		recvShadows = ENTITY_RECV_SHADOWS;
-	}
-	
-	/* get explicit shadow flags */
-	GetEntityShadowFlags( mapEnt, NULL, &castShadows, &recvShadows );
-	
-	/* ydnar: get lightmap scaling value for this entity */
-	if( strcmp( "", ValueForKey( mapEnt, "lightmapscale" ) ) ||
-		strcmp( "", ValueForKey( mapEnt, "_lightmapscale" ) ) )
-	{
-		/* get lightmap scale from entity */
-		lightmapScale = FloatForKey( mapEnt, "lightmapscale" );
-		if( lightmapScale <= 0.0f )
-			lightmapScale = FloatForKey( mapEnt, "_lightmapscale" );
-		if( lightmapScale > 0.0f )
-			Sys_Printf( "Entity %d (%s) has lightmap scale of %.4f\n", mapEnt->mapEntityNum, classname, lightmapScale );
-	}
-	else
-		lightmapScale = 0.0f;
-	
-	/* ydnar: get cel shader :) for this entity */
-	value = ValueForKey( mapEnt, "_celshader" );
-	if( value[ 0 ] == '\0' )	
-		value = ValueForKey( &entities[ 0 ], "_celshader" );
-	if( value[ 0 ] != '\0' )
-	{
-		sprintf( shader, "textures/%s", value );
-		celShader = ShaderInfoForShader( shader );
-		Sys_Printf( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader );
-	}
-	else
-		celShader = NULL;
-	
-	/* attach stuff to everything in the entity */
-	for( brush = mapEnt->brushes; brush != NULL; brush = brush->next )
-	{
-		brush->entityNum = mapEnt->mapEntityNum;
-		brush->castShadows = castShadows;
-		brush->recvShadows = recvShadows;
-		brush->lightmapScale = lightmapScale;
-		brush->celShader = celShader;
-	}
-	
-	for( patch = mapEnt->patches; patch != NULL; patch = patch->next )
-	{
-		patch->entityNum = mapEnt->mapEntityNum;
-		patch->castShadows = castShadows;
-		patch->recvShadows = recvShadows;
-		patch->lightmapScale = lightmapScale;
-		patch->celShader = celShader;
-	}
-	
-	/* ydnar: gs mods: set entity bounds */
-	SetEntityBounds( mapEnt );
-	
-	/* ydnar: gs mods: load shader index map (equivalent to old terrain alphamap) */
-	LoadEntityIndexMap( mapEnt );
-	
-	/* get entity origin and adjust brushes */
-	GetVectorForKey( mapEnt, "origin", mapEnt->origin );
-	if( mapEnt->origin[ 0 ] || mapEnt->origin[ 1 ] || mapEnt->origin[ 2 ] )
-		AdjustBrushesForOrigin( mapEnt );
-
-	/* group_info entities are just for editor grouping (fixme: leak!) */
-	if( !Q_stricmp( "group_info", classname ) )
-	{
-		numEntities--;
-		return qtrue;
-	}
-	
-	/* group entities are just for editor convenience, toss all brushes into worldspawn */
-	if( funcGroup )
-	{
-		MoveBrushesToWorld( mapEnt );
-		numEntities--;
-		return qtrue;
-	}
-	
-	/* done */
-	return qtrue;
-}
-
-
-
-/*
-LoadMapFile()
-loads a map file into a list of entities
-*/
-
-void LoadMapFile( char *filename, qboolean onlyLights )
-{		
-	FILE		*file;
-	brush_t		*b;
-	int			oldNumEntities, numMapBrushes;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- LoadMapFile ---\n" );
-	Sys_Printf( "Loading %s\n", filename );
-	
-	/* hack */
-	file = SafeOpenRead( filename );
-	fclose( file );
-	
-	/* load the map file */
-	LoadScriptFile( filename, -1 );
-	
-	/* setup */
-	if( onlyLights )
-		oldNumEntities = numEntities;
-	else
-		numEntities = 0;
-	
-	/* initial setup */
-	numMapDrawSurfs = 0;
-	c_detail = 0;
-	g_bBrushPrimit = BPRIMIT_UNDEFINED;
-	
-	/* allocate a very large temporary brush for building the brushes as they are loaded */
-	buildBrush = AllocBrush( MAX_BUILD_SIDES );
-	
-	/* parse the map file */
-	while( ParseMapEntity( onlyLights ) );
-	
-	/* light loading */
-	if( onlyLights )
-	{
-		/* emit some statistics */
-		Sys_FPrintf( SYS_VRB, "%9d light entities\n", numEntities - oldNumEntities );
-	}
-	else
-	{
-		/* set map bounds */
-		ClearBounds( mapMins, mapMaxs );
-		for( b = entities[ 0 ].brushes; b; b = b->next )
-		{
-			AddPointToBounds( b->mins, mapMins, mapMaxs );
-			AddPointToBounds( b->maxs, mapMins, mapMaxs );
-		}
-		
-		/* get brush counts */
-		numMapBrushes = CountBrushList( entities[ 0 ].brushes );
-		if( (float) c_detail / (float) numMapBrushes < 0.10f && numMapBrushes > 500 )
-			Sys_Printf( "WARNING: Over 90 percent structural map detected. Compile time may be adversely affected.\n" );
-		
-		/* emit some statistics */
-		Sys_FPrintf( SYS_VRB, "%9d total world brushes\n", numMapBrushes );
-		Sys_FPrintf( SYS_VRB, "%9d detail brushes\n", c_detail );
-		Sys_FPrintf( SYS_VRB, "%9d patches\n", numMapPatches);
-		Sys_FPrintf( SYS_VRB, "%9d boxbevels\n", c_boxbevels);
-		Sys_FPrintf( SYS_VRB, "%9d edgebevels\n", c_edgebevels);
-		Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
-		Sys_FPrintf( SYS_VRB, "%9d planes\n", nummapplanes);
-		Sys_Printf( "%9d areaportals\n", c_areaportals);
-		Sys_Printf( "Size: %5.0f, %5.0f, %5.0f to %5.0f, %5.0f, %5.0f\n",
-			mapMins[ 0 ], mapMins[ 1 ], mapMins[ 2 ],
-			mapMaxs[ 0 ], mapMaxs[ 1 ], mapMaxs[ 2 ]);
-		
-		/* write bogus map */
-		if( fakemap )
-			WriteBSPBrushMap( "fakemap.map", entities[ 0 ].brushes );
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define MAP_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* FIXME: remove these vars */
+
+/* undefine to make plane finding use linear sort (note: really slow) */
+#define	USE_HASHING
+#define	PLANE_HASHES	8192
+
+plane_t					*planehash[ PLANE_HASHES ];
+
+int						c_boxbevels;
+int						c_edgebevels;
+int						c_areaportals;
+int						c_detail;
+int						c_structural;
+
+
+
+/*
+PlaneEqual()
+ydnar: replaced with variable epsilon for djbob
+*/
+
+#define	NORMAL_EPSILON	0.00001
+#define	DIST_EPSILON	0.01
+
+qboolean PlaneEqual( plane_t *p, vec3_t normal, vec_t dist )
+{
+	float	ne, de;
+	
+	
+	/* get local copies */
+	ne = normalEpsilon;
+	de = distanceEpsilon;
+	
+	/* compare */
+	if( fabs( p->dist - dist ) <= de &&
+		fabs( p->normal[ 0 ] - normal[ 0 ] ) <= ne &&
+		fabs( p->normal[ 1 ] - normal[ 1 ] ) <= ne &&
+		fabs( p->normal[ 2 ] - normal[ 2 ] ) <= ne )
+		return qtrue;
+	
+	/* different */
+	return qfalse;
+}
+
+
+
+/*
+AddPlaneToHash()
+*/
+
+void AddPlaneToHash( plane_t *p )
+{
+	int		hash;
+
+	
+	hash = (PLANE_HASHES - 1) & (int) fabs( p->dist );
+
+	p->hash_chain = planehash[hash];
+	planehash[hash] = p;
+}
+
+/*
+================
+CreateNewFloatPlane
+================
+*/
+int CreateNewFloatPlane (vec3_t normal, vec_t dist)
+{
+	plane_t	*p, temp;
+
+	if (VectorLength(normal) < 0.5)
+	{
+		Sys_Printf( "FloatPlane: bad normal\n");
+		return -1;
+	}
+
+	// create a new plane
+	if (nummapplanes+2 > MAX_MAP_PLANES)
+		Error ("MAX_MAP_PLANES");
+
+	p = &mapplanes[nummapplanes];
+	VectorCopy (normal, p->normal);
+	p->dist = dist;
+	p->type = (p+1)->type = PlaneTypeForNormal (p->normal);
+
+	VectorSubtract (vec3_origin, normal, (p+1)->normal);
+	(p+1)->dist = -dist;
+
+	nummapplanes += 2;
+
+	// allways put axial planes facing positive first
+	if (p->type < 3)
+	{
+		if (p->normal[0] < 0 || p->normal[1] < 0 || p->normal[2] < 0)
+		{
+			// flip order
+			temp = *p;
+			*p = *(p+1);
+			*(p+1) = temp;
+
+			AddPlaneToHash (p);
+			AddPlaneToHash (p+1);
+			return nummapplanes - 1;
+		}
+	}
+
+	AddPlaneToHash (p);
+	AddPlaneToHash (p+1);
+	return nummapplanes - 2;
+}
+
+
+
+/*
+SnapNormal()
+snaps a near-axial normal vector
+*/
+
+void SnapNormal( vec3_t normal )
+{
+	int		i;
+
+	for( i = 0; i < 3; i++ )
+	{
+		if( fabs( normal[ i ] - 1 ) < normalEpsilon )
+		{
+			VectorClear( normal );
+			normal[ i ] = 1;
+			break;
+		}
+		if( fabs( normal[ i ] - -1 ) < normalEpsilon )
+		{
+			VectorClear( normal );
+			normal[ i ] = -1;
+			break;
+		}
+	}
+}
+
+
+
+/*
+SnapPlane()
+snaps a plane to normal/distance epsilons
+*/
+
+void SnapPlane( vec3_t normal, vec_t *dist )
+{
+	SnapNormal( normal );
+
+	if( fabs( *dist - Q_rint( *dist ) ) < distanceEpsilon )
+		*dist = Q_rint( *dist );
+}
+
+
+
+/*
+FindFloatPlane()
+ydnar: changed to allow a number of test points to be supplied that
+must be within an epsilon distance of the plane
+*/
+
+int FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points )
+
+#ifdef USE_HASHING
+
+{
+	int		i, j, hash, h;
+	plane_t	*p;
+	vec_t	d;
+	
+	
+	/* hash the plane */
+	SnapPlane( normal, &dist );
+	hash = (PLANE_HASHES - 1) & (int) fabs( dist );
+	
+	/* search the border bins as well */
+	for( i = -1; i <= 1; i++ )
+	{
+		h = (hash + i) & (PLANE_HASHES - 1);
+		for( p = planehash[ h ]; p != NULL; p = p->hash_chain )
+		{
+			/* do standard plane compare */
+			if( !PlaneEqual( p, normal, dist ) )
+				continue;
+			
+			/* ydnar: uncomment the following line for old-style plane finding */
+			//%	return p - mapplanes;
+			
+			/* ydnar: test supplied points against this plane */
+			for( j = 0; j < numPoints; j++ )
+			{
+				d = DotProduct( points[ j ], normal ) - dist;
+				if( fabs( d ) > distanceEpsilon )
+					break;
+			}
+			
+			/* found a matching plane */
+			if( j >= numPoints )
+				return p - mapplanes;
+		}
+	}
+	
+	/* none found, so create a new one */
+	return CreateNewFloatPlane( normal, dist );
+}
+
+#else
+
+{
+	int		i;
+	plane_t	*p;
+	
+
+	SnapPlane( normal, &dist );
+	for( i = 0, p = mapplanes; i < nummapplanes; i++, p++ )
+	{
+		if( PlaneEqual( p, normal, dist ) )
+			return i;
+	}
+	
+	return CreateNewFloatPlane( normal, dist );
+}
+
+#endif
+
+
+
+/*
+MapPlaneFromPoints()
+takes 3 points and finds the plane they lie in
+*/
+
+int MapPlaneFromPoints( vec3_t *p )
+{
+	vec3_t	t1, t2, normal;
+	vec_t	dist;
+	
+	
+	/* calc plane normal */
+	VectorSubtract( p[ 0 ], p[ 1 ], t1 );
+	VectorSubtract( p[ 2 ], p[ 1 ], t2 );
+	CrossProduct( t1, t2, normal );
+	VectorNormalize( normal, normal );
+	
+	/* calc plane distance */
+	dist = DotProduct( p[ 0 ], normal );
+	
+	/* store the plane */
+	return FindFloatPlane( normal, dist, 3, p );
+}
+
+
+
+/*
+SetBrushContents()
+the content flags and compile flags on all sides of a brush should be the same
+*/
+
+void SetBrushContents( brush_t *b )
+{
+	int			contentFlags, compileFlags;
+	side_t		*s;
+	int			i;
+	qboolean	mixed;
+	
+	
+	/* get initial compile flags from first side */
+	s = &b->sides[ 0 ];
+	contentFlags = s->contentFlags;
+	compileFlags = s->compileFlags;
+	b->contentShader = s->shaderInfo;
+	mixed = qfalse;
+	
+	/* get the content/compile flags for every side in the brush */
+	for( i = 1; i < b->numsides; i++, s++ )
+	{
+		s = &b->sides[ i ];
+		if( s->shaderInfo == NULL )
+			continue;
+		if( s->contentFlags != contentFlags || s->compileFlags != compileFlags )
+			mixed = qtrue;
+	}
+	
+	/* ydnar: getting rid of this stupid warning */
+	//%	if( mixed )
+	//%		Sys_FPrintf( SYS_VRB,"Entity %i, Brush %i: mixed face contentFlags\n", b->entitynum, b->brushnum );
+
+	/* check for detail & structural */
+	if( (compileFlags & C_DETAIL) && (compileFlags & C_STRUCTURAL) )
+	{
+		xml_Select( "Mixed detail and structural (defaulting to structural)", mapEnt->mapEntityNum, entitySourceBrushes, qfalse );
+		compileFlags &= ~C_DETAIL;
+	}
+	
+	/* the fulldetail flag will cause detail brushes to be treated like normal brushes */
+	if( fulldetail )
+		compileFlags &= ~C_DETAIL;
+	
+	/* all translucent brushes that aren't specifically made structural will be detail */
+	if( (compileFlags & C_TRANSLUCENT) && !(compileFlags & C_STRUCTURAL) )
+		compileFlags |= C_DETAIL;
+	
+	/* detail? */
+	if( compileFlags & C_DETAIL )
+	{
+		c_detail++;
+		b->detail = qtrue;
+	}
+	else
+	{
+		c_structural++;
+		b->detail = qfalse;
+	}
+	
+	/* opaque? */
+	if( compileFlags & C_TRANSLUCENT )
+		b->opaque = qfalse;
+	else
+		b->opaque = qtrue;
+	
+	/* areaportal? */
+	if( compileFlags & C_AREAPORTAL )
+		c_areaportals++;
+	
+	/* set brush flags */
+	b->contentFlags = contentFlags;
+	b->compileFlags = compileFlags;
+}
+
+
+
+/*
+AddBrushBevels()
+adds any additional planes necessary to allow the brush being
+built to be expanded against axial bounding boxes
+ydnar 2003-01-20: added mrelusive fixes
+*/
+
+void AddBrushBevels( void )
+{
+	int			axis, dir;
+	int			i, j, k, l, order;
+	side_t		sidetemp;
+	side_t		*s, *s2;
+	winding_t	*w, *w2;
+	vec3_t		normal;
+	float		dist;
+	vec3_t		vec, vec2;
+	float		d, minBack;
+
+	//
+	// add the axial planes
+	//
+	order = 0;
+	for ( axis = 0; axis < 3; axis++ ) {
+		for ( dir = -1; dir <= 1; dir += 2, order++ ) {
+			// see if the plane is allready present
+			for ( i = 0, s = buildBrush->sides; i < buildBrush->numsides; i++, s++ )
+			{
+				/* ydnar: testing disabling of mre code */
+				#if 0
+					if ( dir > 0 ) {
+						if ( mapplanes[s->planenum].normal[axis] >= 0.9999f ) {
+							break;
+						}
+					}
+					else {
+						if ( mapplanes[s->planenum].normal[axis] <= -0.9999f ) {
+							break;
+						}
+					}
+				#else
+					if( (dir > 0 && mapplanes[ s->planenum ].normal[ axis ] == 1.0f ) ||
+						(dir < 0 && mapplanes[ s->planenum ].normal[ axis ] == -1.0f) )
+						break;
+				#endif
+			}
+
+			if ( i == buildBrush->numsides ) {
+				// add a new side
+				if ( buildBrush->numsides == MAX_BUILD_SIDES ) {
+					xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, qtrue);
+				}
+				memset( s, 0, sizeof( *s ) );
+				buildBrush->numsides++;
+				VectorClear (normal);
+				normal[axis] = dir;
+
+				if( dir == 1 )
+				{
+					/* ydnar: adding bevel plane snapping for fewer bsp planes */
+					if( bevelSnap > 0 )
+						dist = floor( buildBrush->maxs[ axis ] / bevelSnap ) * bevelSnap;
+					else
+						dist = buildBrush->maxs[ axis ];
+				}
+				else
+				{
+					/* ydnar: adding bevel plane snapping for fewer bsp planes */
+					if( bevelSnap > 0 )
+						dist = -ceil( buildBrush->mins[ axis ] / bevelSnap ) * bevelSnap;
+					else
+						dist = -buildBrush->mins[ axis ];
+				}
+
+				s->planenum = FindFloatPlane( normal, dist, 0, NULL );
+				s->contentFlags = buildBrush->sides[ 0 ].contentFlags;
+				s->bevel = qtrue;
+				c_boxbevels++;
+			}
+
+			// if the plane is not in it canonical order, swap it
+			if ( i != order ) {
+				sidetemp = buildBrush->sides[order];
+				buildBrush->sides[order] = buildBrush->sides[i];
+				buildBrush->sides[i] = sidetemp;
+			}
+		}
+	}
+
+	//
+	// add the edge bevels
+	//
+	if ( buildBrush->numsides == 6 ) {
+		return;		// pure axial
+	}
+
+	// test the non-axial plane edges
+	for ( i = 6; i < buildBrush->numsides; i++ ) {
+		s = buildBrush->sides + i;
+		w = s->winding;
+		if ( !w ) {
+			continue;
+		}
+		for ( j = 0; j < w->numpoints; j++) {
+			k = (j+1)%w->numpoints;
+			VectorSubtract( w->p[j], w->p[k], vec );
+			if ( VectorNormalize( vec, vec ) < 0.5f ) {
+				continue;
+			}
+			SnapNormal( vec );
+			for ( k = 0; k < 3; k++ ) {
+				if ( vec[k] == -1.0f || vec[k] == 1.0f || (vec[k] == 0.0f && vec[(k+1)%3] == 0.0f) ) {
+					break;	// axial
+				}
+			}
+			if ( k != 3 ) {
+				continue;	// only test non-axial edges
+			}
+
+			/* debug code */
+			//%	Sys_Printf( "-------------\n" );
+
+			// try the six possible slanted axials from this edge
+			for ( axis = 0; axis < 3; axis++ ) {
+				for ( dir = -1; dir <= 1; dir += 2 ) {
+					// construct a plane
+					VectorClear( vec2 );
+					vec2[axis] = dir;
+					CrossProduct( vec, vec2, normal );
+					if ( VectorNormalize( normal, normal ) < 0.5f ) {
+						continue;
+					}
+					dist = DotProduct( w->p[j], normal );
+					
+					// if all the points on all the sides are
+					// behind this plane, it is a proper edge bevel
+					for ( k = 0; k < buildBrush->numsides; k++ ) {
+
+						// if this plane has allready been used, skip it
+						if ( PlaneEqual( &mapplanes[buildBrush->sides[k].planenum], normal, dist ) ) {
+							break;
+						}
+
+						w2 = buildBrush->sides[k].winding;
+						if ( !w2 ) {
+							continue;
+						}
+						minBack = 0.0f;
+						for ( l = 0; l < w2->numpoints; l++ ) {
+							d = DotProduct( w2->p[l], normal ) - dist;
+							if ( d > 0.1f ) {
+								break;	// point in front
+							}
+							if ( d < minBack ) {
+								minBack = d;
+							}
+						}
+						// if some point was at the front
+						if ( l != w2->numpoints ) {
+							break;
+						}
+
+						// if no points at the back then the winding is on the bevel plane
+						if ( minBack > -0.1f ) {
+							//%	Sys_Printf( "On bevel plane\n" );
+							break;
+						}
+					}
+
+					if ( k != buildBrush->numsides ) {
+						continue;	// wasn't part of the outer hull
+					}
+					
+					/* debug code */
+					//%	Sys_Printf( "n = %f %f %f\n", normal[ 0 ], normal[ 1 ], normal[ 2 ] );
+					
+					// add this plane
+					if( buildBrush->numsides == MAX_BUILD_SIDES ) {
+						xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, qtrue);
+					}
+					s2 = &buildBrush->sides[buildBrush->numsides];
+					buildBrush->numsides++;
+					memset( s2, 0, sizeof( *s2 ) );
+
+					s2->planenum = FindFloatPlane( normal, dist, 1, &w->p[ j ] );
+					s2->contentFlags = buildBrush->sides[0].contentFlags;
+					s2->bevel = qtrue;
+					c_edgebevels++;
+				}
+			}
+		}
+	}
+}
+
+
+
+/*
+FinishBrush()
+produces a final brush based on the buildBrush->sides array
+and links it to the current entity
+*/
+
+brush_t *FinishBrush( void )
+{
+	brush_t	*b;
+	
+	
+	/* create windings for sides and bounds for brush */
+	if ( !CreateBrushWindings( buildBrush ) )
+		return NULL;
+
+	/* origin brushes are removed, but they set the rotation origin for the rest of the brushes in the entity.
+	   after the entire entity is parsed, the planenums and texinfos will be adjusted for the origin brush */
+	if( buildBrush->compileFlags & C_ORIGIN )
+	{
+		char	string[ 32 ];
+		vec3_t	origin;
+
+		if( numEntities == 1 )
+		{
+			Sys_Printf( "Entity %i, Brush %i: origin brushes not allowed in world\n", 
+				mapEnt->mapEntityNum, entitySourceBrushes );
+			return NULL;
+		}
+		
+		VectorAdd (buildBrush->mins, buildBrush->maxs, origin);
+		VectorScale (origin, 0.5, origin);
+
+		sprintf( string, "%i %i %i", (int) origin[ 0 ], (int) origin[ 1 ], (int) origin[ 2 ] );
+		SetKeyValue( &entities[ numEntities - 1 ], "origin", string);
+
+		VectorCopy( origin, entities[ numEntities - 1 ].origin);
+
+		/* don't keep this brush */
+		return NULL;
+	}
+	
+	/* determine if the brush is an area portal */
+	if( buildBrush->compileFlags & C_AREAPORTAL )
+	{
+		if( numEntities != 1 )
+		{
+			Sys_Printf ("Entity %i, Brush %i: areaportals only allowed in world\n", numEntities - 1, entitySourceBrushes );
+			return NULL;
+		}
+	}
+	
+	/* add bevel planes */
+	AddBrushBevels();
+	
+	/* keep it */
+	b = CopyBrush( buildBrush );
+	
+	/* set map entity and brush numbering */
+	b->entityNum = mapEnt->mapEntityNum;
+	b->brushNum = entitySourceBrushes;
+	
+	/* set original */
+	b->original = b;
+	
+	/* link opaque brushes to head of list, translucent brushes to end */
+	if( b->opaque || mapEnt->lastBrush == NULL )
+	{
+		b->next = mapEnt->brushes;
+		mapEnt->brushes = b;
+		if( mapEnt->lastBrush == NULL )
+			mapEnt->lastBrush = b;
+	}
+	else
+	{
+		b->next = NULL;
+		mapEnt->lastBrush->next = b;
+		mapEnt->lastBrush = b;
+	}
+	
+	/* return to sender */
+	return b;
+}
+
+
+
+/*
+TextureAxisFromPlane()
+determines best orthagonal axis to project a texture onto a wall
+(must be identical in radiant!)
+*/
+
+vec3_t	baseaxis[18] =
+{
+	{0,0,1}, {1,0,0}, {0,-1,0},			// floor
+	{0,0,-1}, {1,0,0}, {0,-1,0},		// ceiling
+	{1,0,0}, {0,1,0}, {0,0,-1},			// west wall
+	{-1,0,0}, {0,1,0}, {0,0,-1},		// east wall
+	{0,1,0}, {1,0,0}, {0,0,-1},			// south wall
+	{0,-1,0}, {1,0,0}, {0,0,-1}			// north wall
+};
+
+void TextureAxisFromPlane( plane_t *pln, vec3_t xv, vec3_t yv )
+{
+	int		bestaxis;
+	vec_t	dot,best;
+	int		i;
+	
+	best = 0;
+	bestaxis = 0;
+	
+	for (i=0 ; i<6 ; i++)
+	{
+		dot = DotProduct (pln->normal, baseaxis[i*3]);
+		if( dot > best + 0.0001f )	/* ydnar: bug 637 fix, suggested by jmonroe */
+		{
+			best = dot;
+			bestaxis = i;
+		}
+	}
+	
+	VectorCopy (baseaxis[bestaxis*3+1], xv);
+	VectorCopy (baseaxis[bestaxis*3+2], yv);
+}
+
+
+
+/*
+QuakeTextureVecs()
+creates world-to-texture mapping vecs for crappy quake plane arrangements
+*/
+
+void QuakeTextureVecs( plane_t *plane, vec_t shift[ 2 ], vec_t rotate, vec_t scale[ 2 ], vec_t mappingVecs[ 2 ][ 4 ] )
+{
+	vec3_t	vecs[2];
+	int		sv, tv;
+	vec_t	ang, sinv, cosv;
+	vec_t	ns, nt;
+	int		i, j;
+	
+	
+	TextureAxisFromPlane(plane, vecs[0], vecs[1]);
+	
+	if (!scale[0])
+		scale[0] = 1;
+	if (!scale[1])
+		scale[1] = 1;
+
+	// rotate axis
+	if (rotate == 0)
+		{ sinv = 0 ; cosv = 1; }
+	else if (rotate == 90)
+		{ sinv = 1 ; cosv = 0; }
+	else if (rotate == 180)
+		{ sinv = 0 ; cosv = -1; }
+	else if (rotate == 270)
+		{ sinv = -1 ; cosv = 0; }
+	else
+	{	
+		ang = rotate / 180 * Q_PI;
+		sinv = sin(ang);
+		cosv = cos(ang);
+	}
+
+	if (vecs[0][0])
+		sv = 0;
+	else if (vecs[0][1])
+		sv = 1;
+	else
+		sv = 2;
+				
+	if (vecs[1][0])
+		tv = 0;
+	else if (vecs[1][1])
+		tv = 1;
+	else
+		tv = 2;
+					
+	for (i=0 ; i<2 ; i++) {
+		ns = cosv * vecs[i][sv] - sinv * vecs[i][tv];
+		nt = sinv * vecs[i][sv] +  cosv * vecs[i][tv];
+		vecs[i][sv] = ns;
+		vecs[i][tv] = nt;
+	}
+
+	for (i=0 ; i<2 ; i++)
+		for (j=0 ; j<3 ; j++)
+			mappingVecs[i][j] = vecs[i][j] / scale[i];
+
+	mappingVecs[0][3] = shift[0];
+	mappingVecs[1][3] = shift[1];
+}
+
+
+
+/*
+ParseRawBrush()
+parses the sides into buildBrush->sides[], nothing else.
+no validation, back plane removal, etc.
+
+Timo - 08/26/99
+added brush epairs parsing ( ignoring actually )
+Timo - 08/04/99
+added exclusive brush primitive parsing
+Timo - 08/08/99
+support for old brush format back in
+NOTE: it would be "cleaner" to have seperate functions to parse between old and new brushes
+*/
+
+static void ParseRawBrush( qboolean onlyLights )
+{
+	side_t			*side;
+	vec3_t			planePoints[ 3 ];
+	int				planenum;
+	shaderInfo_t	*si;
+	vec_t			shift[ 2 ];
+	vec_t			rotate;
+	vec_t			scale[ 2 ];
+	char			name[ MAX_QPATH ];
+	char			shader[ MAX_QPATH ];
+	int				flags;
+	
+	
+	/* initial setup */
+	buildBrush->numsides = 0;
+	buildBrush->detail = qfalse;
+	
+	/* bp */
+	if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
+		MatchToken( "{" );
+	
+	/* parse sides */
+	while( 1 )
+	{
+		if( !GetToken( qtrue ) )
+			break;
+		if( !strcmp( token, "}" ) )
+			break;
+		 
+		/* ttimo : bp: here we may have to jump over brush epairs (only used in editor) */
+		if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
+		{
+			while( 1 )
+			{
+				if( strcmp( token, "(" ) )
+					GetToken( qfalse );
+				else
+					break;
+				GetToken( qtrue );
+			}
+		}
+		UnGetToken();
+		
+		/* test side count */
+		if( buildBrush->numsides >= MAX_BUILD_SIDES )
+			xml_Select( "MAX_BUILD_SIDES", buildBrush->entityNum, buildBrush->brushNum, qtrue );
+		
+		/* add side */
+		side = &buildBrush->sides[ buildBrush->numsides ];
+		memset( side, 0, sizeof( *side ) );
+		buildBrush->numsides++;
+		
+		/* read the three point plane definition */
+		Parse1DMatrix( 3, planePoints[ 0 ] );
+		Parse1DMatrix( 3, planePoints[ 1 ] );
+		Parse1DMatrix( 3, planePoints[ 2 ] );
+		
+		/* bp: read the texture matrix */
+		if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
+			Parse2DMatrix( 2, 3, (float*) side->texMat );
+		
+		/* read shader name */
+		GetToken( qfalse );
+		strcpy( name, token );
+		
+		/* bp */
+		if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
+		{
+			GetToken( qfalse );
+			shift[ 0 ] = atof( token );
+			GetToken( qfalse );
+			shift[ 1 ] = atof( token );
+			GetToken( qfalse );
+			rotate = atof( token );	
+			GetToken( qfalse );
+			scale[ 0 ] = atof( token );
+			GetToken( qfalse );
+			scale[ 1 ] = atof( token );
+		}
+		
+		/* set default flags and values */
+		sprintf( shader, "textures/%s", name );
+		if( onlyLights )
+			si = &shaderInfo[ 0 ];
+		else
+			si = ShaderInfoForShader( shader );
+		side->shaderInfo = si;
+		side->surfaceFlags = si->surfaceFlags;
+		side->contentFlags = si->contentFlags;
+		side->compileFlags = si->compileFlags;
+		side->value = si->value;
+		
+		/* ydnar: gs mods: bias texture shift */
+		if( si->globalTexture == qfalse )
+		{
+			shift[ 0 ] -= (floor( shift[ 0 ] / si->shaderWidth ) * si->shaderWidth);
+			shift[ 1 ] -= (floor( shift[ 1 ] / si->shaderHeight ) * si->shaderHeight);
+		}
+		
+		/*
+			historically, there are 3 integer values at the end of a brushside line in a .map file.
+			in quake 3, the only thing that mattered was the first of these three values, which
+			was previously the content flags. and only then did a single bit matter, the detail
+			bit. because every game has its own special flags for specifying detail, the
+			traditionally game-specified CONTENTS_DETAIL flag was overridden for Q3Map 2.3.0
+			by C_DETAIL, defined in q3map2.h. the value is exactly as it was before, but
+			is stored in compileFlags, as opposed to contentFlags, for multiple-game
+			portability. :sigh:
+		*/
+		
+		if( TokenAvailable() )
+		{
+			/* get detail bit from map content flags */
+			GetToken( qfalse );
+			flags = atoi( token );
+			if( flags & C_DETAIL )
+				side->compileFlags |= C_DETAIL;
+			
+			/* historical */
+			GetToken( qfalse );
+			//% td.flags = atoi( token );
+			GetToken( qfalse );
+			//% td.value = atoi( token );
+		}
+		
+		/* find the plane number */
+		planenum = MapPlaneFromPoints( planePoints );
+		side->planenum = planenum;
+		
+		/* bp: get the texture mapping for this texturedef / plane combination */
+		if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
+			QuakeTextureVecs( &mapplanes[ planenum ], shift, rotate, scale, side->vecs );
+	}
+	
+	/* bp */
+	if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
+	{
+		UnGetToken();
+		MatchToken( "}" );
+		MatchToken( "}" );
+	}
+}
+
+
+
+/*
+RemoveDuplicateBrushPlanes
+returns false if the brush has a mirrored set of planes,
+meaning it encloses no volume.
+also removes planes without any normal
+*/
+
+qboolean RemoveDuplicateBrushPlanes( brush_t *b )
+{
+	int			i, j, k;
+	side_t		*sides;
+
+	sides = b->sides;
+
+	for ( i = 1 ; i < b->numsides ; i++ ) {
+
+		// check for a degenerate plane
+		if ( sides[i].planenum == -1) {
+		  xml_Select( "degenerate plane", b->entityNum, b->brushNum, qfalse );
+			// remove it
+			for ( k = i + 1 ; k < b->numsides ; k++ ) {
+				sides[k-1] = sides[k];
+			}
+			b->numsides--;
+			i--;
+			continue;
+		}
+
+		// check for duplication and mirroring
+		for ( j = 0 ; j < i ; j++ ) {
+			if ( sides[i].planenum == sides[j].planenum ) {
+			  xml_Select( "duplicate plane", b->entityNum, b->brushNum, qfalse );
+				// remove the second duplicate
+				for ( k = i + 1 ; k < b->numsides ; k++ ) {
+					sides[k-1] = sides[k];
+				}
+				b->numsides--;
+				i--;
+				break;
+			}
+
+			if ( sides[i].planenum == (sides[j].planenum ^ 1) ) {
+				// mirror plane, brush is invalid
+			  xml_Select( "mirrored plane", b->entityNum, b->brushNum, qfalse );
+				return qfalse;
+			}
+		}
+	}
+	return qtrue;
+}
+
+
+
+/*
+ParseBrush()
+parses a brush out of a map file and sets it up
+*/
+
+static void ParseBrush( qboolean onlyLights )
+{
+	brush_t	*b;
+	
+	
+	/* parse the brush out of the map */
+	ParseRawBrush( onlyLights );
+	
+	/* only go this far? */
+	if( onlyLights )
+		return;
+	
+	/* set some defaults */
+	buildBrush->portalareas[ 0 ] = -1;
+	buildBrush->portalareas[ 1 ] = -1;
+	buildBrush->entityNum = numMapEntities - 1;
+	buildBrush->brushNum = entitySourceBrushes;
+	
+	/* if there are mirrored planes, the entire brush is invalid */
+	if( !RemoveDuplicateBrushPlanes( buildBrush ) )
+		return;
+	
+	/* get the content for the entire brush */
+	SetBrushContents( buildBrush );
+	
+	/* allow detail brushes to be removed */
+	if( nodetail && (buildBrush->compileFlags & C_DETAIL) )
+	{
+		//%	FreeBrush( buildBrush );
+		return;
+	}
+	
+	/* allow liquid brushes to be removed */
+	if( nowater && (buildBrush->compileFlags & C_LIQUID ) )
+	{
+		//%	FreeBrush( buildBrush );
+		return;
+	}
+	
+	/* ydnar: allow hint brushes to be removed */
+	if( noHint && (buildBrush->compileFlags & C_HINT) )
+	{
+		//%	FreeBrush( buildBrush );
+		return;
+	}
+	
+	/* finish the brush */
+	b = FinishBrush();
+}
+
+
+
+/*
+MoveBrushesToWorld()
+takes all of the brushes from the current entity and
+adds them to the world's brush list
+(used by func_group)
+*/
+
+void MoveBrushesToWorld( entity_t *ent )
+{
+	brush_t		*b, *next;
+	parseMesh_t	*pm;
+
+	
+	/* move brushes */
+	for( b = ent->brushes; b != NULL; b = next )
+	{
+		/* get next brush */
+		next = b->next;
+		
+		/* link opaque brushes to head of list, translucent brushes to end */
+		if( b->opaque || entities[ 0 ].lastBrush == NULL )
+		{
+			b->next = entities[ 0 ].brushes;
+			entities[ 0 ].brushes = b;
+			if( entities[ 0 ].lastBrush == NULL )
+				entities[ 0 ].lastBrush = b;
+		}
+		else
+		{
+			b->next = NULL;
+			entities[ 0 ].lastBrush->next = b;
+			entities[ 0 ].lastBrush = b;
+		}
+		
+		//%	b->next = entities[ 0 ].brushes;
+		//%	entities[ 0 ].brushes = b;
+	}
+	ent->brushes = NULL;
+	
+	/* move patches */
+	if( ent->patches != NULL )
+	{
+		for( pm = ent->patches; pm->next; pm = pm->next );
+		
+		pm->next = entities[ 0 ].patches;
+		entities[ 0 ].patches = ent->patches;
+		
+		ent->patches = NULL;
+	}
+}
+
+
+
+/*
+AdjustBrushesForOrigin()
+*/
+
+void AdjustBrushesForOrigin( entity_t *ent )
+{
+	
+	int			i;
+	side_t		*s;
+	vec_t		newdist;
+	brush_t		*b;
+	parseMesh_t	*p;
+	
+	
+	/* walk brush list */
+	for( b = ent->brushes; b != NULL; b = b->next )
+	{
+		/* offset brush planes */
+		for( i = 0; i < b->numsides; i++)
+		{
+			/* get brush side */
+			s = &b->sides[ i ];
+			
+			/* offset side plane */
+			newdist = mapplanes[ s->planenum ].dist - DotProduct( mapplanes[ s->planenum ].normal, ent->origin );
+			
+			/* find a new plane */
+			s->planenum = FindFloatPlane( mapplanes[ s->planenum ].normal, newdist, 0, NULL );
+		}
+		
+		/* rebuild brush windings (ydnar: just offsetting the winding above should be fine) */
+		CreateBrushWindings( b );
+	}
+	
+	/* walk patch list */
+	for( p = ent->patches; p != NULL; p = p->next )
+	{
+		for( i = 0; i < (p->mesh.width * p->mesh.height); i++ )
+			VectorSubtract( p->mesh.verts[ i ].xyz, ent->origin, p->mesh.verts[ i ].xyz );
+	}
+}
+
+
+
+/*
+SetEntityBounds() - ydnar
+finds the bounds of an entity's brushes (necessary for terrain-style generic metashaders)
+*/
+
+void SetEntityBounds( entity_t *e )
+{
+	int			i;
+	brush_t	*b;
+	parseMesh_t	*p;
+	vec3_t		mins, maxs;
+	const char	*value;
+
+	
+	
+
+	/* walk the entity's brushes/patches and determine bounds */
+	ClearBounds( mins, maxs );
+	for( b = e->brushes; b; b = b->next )
+	{
+		AddPointToBounds( b->mins, mins, maxs );
+		AddPointToBounds( b->maxs, mins, maxs );
+	}
+	for( p = e->patches; p; p = p->next )
+	{
+		for( i = 0; i < (p->mesh.width * p->mesh.height); i++ )
+			AddPointToBounds( p->mesh.verts[ i ].xyz, mins, maxs );
+	}
+	
+	/* try to find explicit min/max key */
+	value = ValueForKey( e, "min" ); 
+	if( value[ 0 ] != '\0' )
+		GetVectorForKey( e, "min", mins );
+	value = ValueForKey( e, "max" ); 
+	if( value[ 0 ] != '\0' )
+		GetVectorForKey( e, "max", maxs );
+	
+	/* store the bounds */
+	for( b = e->brushes; b; b = b->next )
+	{
+		VectorCopy( mins, b->eMins );
+		VectorCopy( maxs, b->eMaxs );
+	}
+	for( p = e->patches; p; p = p->next )
+	{
+		VectorCopy( mins, p->eMins );
+		VectorCopy( maxs, p->eMaxs );
+	}
+}
+
+
+
+/*
+LoadEntityIndexMap() - ydnar
+based on LoadAlphaMap() from terrain.c, a little more generic
+*/
+
+void LoadEntityIndexMap( entity_t *e )
+{
+	int				i, size, numLayers, w, h;
+	const char		*value, *indexMapFilename, *shader;
+	char			ext[ MAX_QPATH ], offset[ 4096 ], *search, *space;
+	byte			*pixels;
+	unsigned int	*pixels32;
+	indexMap_t		*im;
+	brush_t			*b;
+	parseMesh_t		*p;
+	
+	
+	/* this only works with bmodel ents */
+	if( e->brushes == NULL && e->patches == NULL )
+		return;
+	
+	/* determine if there is an index map (support legacy "alphamap" key as well) */
+	value = ValueForKey( e, "_indexmap" );
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( e, "alphamap" );
+	if( value[ 0 ] == '\0' )
+		return;
+	indexMapFilename = value;
+	
+	/* get number of layers (support legacy "layers" key as well) */
+	value = ValueForKey( e, "_layers" );
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( e, "layers" );
+	if( value[ 0 ] == '\0' )
+	{
+		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" has missing \"_layers\" or \"layers\" key\n", indexMapFilename );
+		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
+		return;
+	}
+	numLayers = atoi( value );
+	if( numLayers < 1 )
+	{
+		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" has < 1 layer (%d)\n", indexMapFilename, numLayers );
+		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
+		return;
+	}
+	
+	/* get base shader name (support legacy "shader" key as well) */
+	value = ValueForKey( mapEnt, "_shader" );
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( e, "shader" );
+	if( value[ 0 ] == '\0' )
+	{
+		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" has missing \"_shader\" or \"shader\" key\n", indexMapFilename );
+		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
+		return;
+	}
+	shader = value;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "Entity %d (%s) has shader index map \"%s\"\n",  mapEnt->mapEntityNum, ValueForKey( e, "classname" ), indexMapFilename );
+	
+	/* get index map file extension */
+	ExtractFileExtension( indexMapFilename, ext );
+	
+	/* handle tga image */
+	if( !Q_stricmp( ext, "tga" ) )
+	{
+		/* load it */
+		Load32BitImage( indexMapFilename, &pixels32, &w, &h );
+		
+		/* convert to bytes */
+		size = w * h;
+		pixels = safe_malloc( size );
+		for( i = 0; i < size; i++ )
+		{
+			pixels[ i ] = ((pixels32[ i ] & 0xFF) * numLayers) / 256;
+			if( pixels[ i ] >= numLayers )
+				pixels[ i ] = numLayers - 1;
+		}
+		
+		/* free the 32 bit image */
+		free( pixels32 );
+	}
+	else
+	{
+		/* load it */
+		Load256Image( indexMapFilename, &pixels, NULL, &w, &h );
+		
+		/* debug code */
+		//%	Sys_Printf( "-------------------------------" );
+		
+		/* fix up out-of-range values */
+		size = w * h;
+		for( i = 0; i < size; i++ )
+		{
+			if( pixels[ i ] >= numLayers )
+				pixels[ i ] = numLayers - 1;
+			
+			/* debug code */
+			//%	if( (i % w) == 0 )
+			//%		Sys_Printf( "\n" );
+			//%	Sys_Printf( "%c", pixels[ i ] + '0' );
+		}
+		
+		/* debug code */
+		//%	Sys_Printf( "\n-------------------------------\n" );
+	}
+	
+	/* the index map must be at least 2x2 pixels */
+	if( w < 2 || h < 2 )
+	{
+		Sys_Printf( "WARNING: Entity with index/alpha map \"%s\" is smaller than 2x2 pixels\n", indexMapFilename );
+		Sys_Printf( "Entity will not be textured properly. Check your keys/values.\n" );
+		free( pixels );
+		return;
+	}
+
+	/* create a new index map */
+	im = safe_malloc( sizeof( *im ) );
+	memset( im, 0, sizeof( *im ) );
+	
+	/* set it up */
+	im->w = w;
+	im->h = h;
+	im->numLayers = numLayers;
+	strcpy( im->name, indexMapFilename );
+	strcpy( im->shader, shader );
+	im->pixels = pixels;
+	
+	/* get height offsets */
+	value = ValueForKey( mapEnt, "_offsets" );
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( e, "offsets" );
+	if( value[ 0 ] != '\0' )
+	{
+		/* value is a space-seperated set of numbers */
+		strcpy( offset, value );
+		search = offset;
+		
+		/* get each value */
+		for( i = 0; i < 256 && *search != '\0'; i++ )
+		{
+			space = strstr( search, " " );
+			if( space != NULL )
+				*space = '\0';
+			im->offsets[ i ] = atof( search );
+			if( space == NULL )
+				break;
+			search = space + 1;
+		}
+	}
+	
+	/* store the index map in every brush/patch in the entity */
+	for( b = e->brushes; b != NULL; b = b->next )
+		b->im = im;
+	for( p = e->patches; p != NULL; p = p->next )
+		p->im = im;
+}
+
+
+
+
+
+
+
+/*
+ParseMapEntity()
+parses a single entity out of a map file
+*/
+
+static qboolean ParseMapEntity( qboolean onlyLights )
+{
+	epair_t			*ep;
+	const char		*classname, *value;
+	float			lightmapScale;
+	char			shader[ MAX_QPATH ];
+	shaderInfo_t	*celShader = NULL;
+	brush_t			*brush;
+	parseMesh_t		*patch;
+	qboolean		funcGroup;
+	int				castShadows, recvShadows;
+	
+	
+	/* eof check */
+	if( !GetToken( qtrue ) )
+		return qfalse;
+	
+	/* conformance check */
+	if( strcmp( token, "{" ) )
+	{
+		Sys_Printf( "WARNING: ParseEntity: { not found, found %s on line %d - last entity was at: <%4.2f, %4.2f, %4.2f>...\n"
+			"Continuing to process map, but resulting BSP may be invalid.\n",
+			token, scriptline, entities[ numEntities ].origin[ 0 ], entities[ numEntities ].origin[ 1 ], entities[ numEntities ].origin[ 2 ] );
+		return qfalse;
+	}
+	
+	/* range check */
+	if( numEntities >= MAX_MAP_ENTITIES )
+		Error( "numEntities == MAX_MAP_ENTITIES" );
+	
+	/* setup */
+	entitySourceBrushes = 0;
+	mapEnt = &entities[ numEntities ];
+	numEntities++;
+	memset( mapEnt, 0, sizeof( *mapEnt ) );
+	
+	/* ydnar: true entity numbering */
+	mapEnt->mapEntityNum = numMapEntities;
+	numMapEntities++;
+	
+	/* loop */
+	while( 1 )
+	{
+		/* get initial token */
+		if( !GetToken( qtrue ) )
+		{
+			Sys_Printf( "WARNING: ParseEntity: EOF without closing brace\n"
+				"Continuing to process map, but resulting BSP may be invalid.\n" );
+			return qfalse;
+		}
+		
+		if( !strcmp( token, "}" ) )
+			break;
+		
+		if( !strcmp( token, "{" ) )
+		{
+			/* parse a brush or patch */
+			if( !GetToken( qtrue ) )
+				break;
+			
+			/* check */
+			if( !strcmp( token, "patchDef2" ) )
+			{
+				numMapPatches++;
+				ParsePatch( onlyLights );
+			}
+			else if( !strcmp( token, "terrainDef" ) )
+			{
+				//% ParseTerrain();
+				Sys_Printf( "WARNING: Terrain entity parsing not supported in this build.\n" );	/* ydnar */
+			}
+			else if( !strcmp( token, "brushDef" ) )
+			{
+				if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
+					Error( "Old brush format not allowed in new brush format map" );
+				g_bBrushPrimit = BPRIMIT_NEWBRUSHES;
+				
+				/* parse brush primitive */
+				ParseBrush( onlyLights );
+			}
+			else
+			{
+				if( g_bBrushPrimit == BPRIMIT_NEWBRUSHES )
+					Error( "New brush format not allowed in old brush format map" );
+				g_bBrushPrimit = BPRIMIT_OLDBRUSHES;
+				
+				/* parse old brush format */
+				UnGetToken();
+				ParseBrush( onlyLights );
+			}
+			entitySourceBrushes++;
+		}
+		else
+		{
+			/* parse a key / value pair */
+			ep = ParseEPair();
+			
+			/* ydnar: 2002-07-06 fixed wolf bug with empty epairs */
+			if( ep->key[ 0 ] != '\0' && ep->value[ 0 ] != '\0' )
+			{
+				ep->next = mapEnt->epairs;
+				mapEnt->epairs = ep;
+			}
+		}
+	}
+	
+	/* ydnar: get classname */
+	classname = ValueForKey( mapEnt, "classname" );
+	
+	/* ydnar: only lights? */
+	if( onlyLights && Q_strncasecmp( classname, "light", 5 ) )
+	{
+		numEntities--;
+		return qtrue;
+	}
+	
+	/* ydnar: determine if this is a func_group */
+	if( !Q_stricmp( "func_group", classname ) )
+		funcGroup = qtrue;
+	else
+		funcGroup = qfalse;
+	
+	/* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
+	if( funcGroup || mapEnt->mapEntityNum == 0 )
+	{
+		//%	Sys_Printf( "World:  %d\n", mapEnt->mapEntityNum );
+		castShadows = WORLDSPAWN_CAST_SHADOWS;
+		recvShadows = WORLDSPAWN_RECV_SHADOWS;
+	}
+	
+	/* other entities don't cast any shadows, but recv worldspawn shadows */
+	else
+	{
+		//%	Sys_Printf( "Entity: %d\n", mapEnt->mapEntityNum );
+		castShadows = ENTITY_CAST_SHADOWS;
+		recvShadows = ENTITY_RECV_SHADOWS;
+	}
+	
+	/* get explicit shadow flags */
+	GetEntityShadowFlags( mapEnt, NULL, &castShadows, &recvShadows );
+	
+	/* ydnar: get lightmap scaling value for this entity */
+	if( strcmp( "", ValueForKey( mapEnt, "lightmapscale" ) ) ||
+		strcmp( "", ValueForKey( mapEnt, "_lightmapscale" ) ) )
+	{
+		/* get lightmap scale from entity */
+		lightmapScale = FloatForKey( mapEnt, "lightmapscale" );
+		if( lightmapScale <= 0.0f )
+			lightmapScale = FloatForKey( mapEnt, "_lightmapscale" );
+		if( lightmapScale > 0.0f )
+			Sys_Printf( "Entity %d (%s) has lightmap scale of %.4f\n", mapEnt->mapEntityNum, classname, lightmapScale );
+	}
+	else
+		lightmapScale = 0.0f;
+	
+	/* ydnar: get cel shader :) for this entity */
+	value = ValueForKey( mapEnt, "_celshader" );
+	if( value[ 0 ] == '\0' )	
+		value = ValueForKey( &entities[ 0 ], "_celshader" );
+	if( value[ 0 ] != '\0' )
+	{
+		sprintf( shader, "textures/%s", value );
+		celShader = ShaderInfoForShader( shader );
+		Sys_Printf( "Entity %d (%s) has cel shader %s\n", mapEnt->mapEntityNum, classname, celShader->shader );
+	}
+	else
+		celShader = NULL;
+	
+	/* attach stuff to everything in the entity */
+	for( brush = mapEnt->brushes; brush != NULL; brush = brush->next )
+	{
+		brush->entityNum = mapEnt->mapEntityNum;
+		brush->castShadows = castShadows;
+		brush->recvShadows = recvShadows;
+		brush->lightmapScale = lightmapScale;
+		brush->celShader = celShader;
+	}
+	
+	for( patch = mapEnt->patches; patch != NULL; patch = patch->next )
+	{
+		patch->entityNum = mapEnt->mapEntityNum;
+		patch->castShadows = castShadows;
+		patch->recvShadows = recvShadows;
+		patch->lightmapScale = lightmapScale;
+		patch->celShader = celShader;
+	}
+	
+	/* ydnar: gs mods: set entity bounds */
+	SetEntityBounds( mapEnt );
+	
+	/* ydnar: gs mods: load shader index map (equivalent to old terrain alphamap) */
+	LoadEntityIndexMap( mapEnt );
+	
+	/* get entity origin and adjust brushes */
+	GetVectorForKey( mapEnt, "origin", mapEnt->origin );
+	if( mapEnt->origin[ 0 ] || mapEnt->origin[ 1 ] || mapEnt->origin[ 2 ] )
+		AdjustBrushesForOrigin( mapEnt );
+
+	/* group_info entities are just for editor grouping (fixme: leak!) */
+	if( !Q_stricmp( "group_info", classname ) )
+	{
+		numEntities--;
+		return qtrue;
+	}
+	
+	/* group entities are just for editor convenience, toss all brushes into worldspawn */
+	if( funcGroup )
+	{
+		MoveBrushesToWorld( mapEnt );
+		numEntities--;
+		return qtrue;
+	}
+	
+	/* done */
+	return qtrue;
+}
+
+
+
+/*
+LoadMapFile()
+loads a map file into a list of entities
+*/
+
+void LoadMapFile( char *filename, qboolean onlyLights )
+{		
+	FILE		*file;
+	brush_t		*b;
+	int			oldNumEntities, numMapBrushes;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- LoadMapFile ---\n" );
+	Sys_Printf( "Loading %s\n", filename );
+	
+	/* hack */
+	file = SafeOpenRead( filename );
+	fclose( file );
+	
+	/* load the map file */
+	LoadScriptFile( filename, -1 );
+	
+	/* setup */
+	if( onlyLights )
+		oldNumEntities = numEntities;
+	else
+		numEntities = 0;
+	
+	/* initial setup */
+	numMapDrawSurfs = 0;
+	c_detail = 0;
+	g_bBrushPrimit = BPRIMIT_UNDEFINED;
+	
+	/* allocate a very large temporary brush for building the brushes as they are loaded */
+	buildBrush = AllocBrush( MAX_BUILD_SIDES );
+	
+	/* parse the map file */
+	while( ParseMapEntity( onlyLights ) );
+	
+	/* light loading */
+	if( onlyLights )
+	{
+		/* emit some statistics */
+		Sys_FPrintf( SYS_VRB, "%9d light entities\n", numEntities - oldNumEntities );
+	}
+	else
+	{
+		/* set map bounds */
+		ClearBounds( mapMins, mapMaxs );
+		for( b = entities[ 0 ].brushes; b; b = b->next )
+		{
+			AddPointToBounds( b->mins, mapMins, mapMaxs );
+			AddPointToBounds( b->maxs, mapMins, mapMaxs );
+		}
+		
+		/* get brush counts */
+		numMapBrushes = CountBrushList( entities[ 0 ].brushes );
+		if( (float) c_detail / (float) numMapBrushes < 0.10f && numMapBrushes > 500 )
+			Sys_Printf( "WARNING: Over 90 percent structural map detected. Compile time may be adversely affected.\n" );
+		
+		/* emit some statistics */
+		Sys_FPrintf( SYS_VRB, "%9d total world brushes\n", numMapBrushes );
+		Sys_FPrintf( SYS_VRB, "%9d detail brushes\n", c_detail );
+		Sys_FPrintf( SYS_VRB, "%9d patches\n", numMapPatches);
+		Sys_FPrintf( SYS_VRB, "%9d boxbevels\n", c_boxbevels);
+		Sys_FPrintf( SYS_VRB, "%9d edgebevels\n", c_edgebevels);
+		Sys_FPrintf( SYS_VRB, "%9d entities\n", numEntities );
+		Sys_FPrintf( SYS_VRB, "%9d planes\n", nummapplanes);
+		Sys_Printf( "%9d areaportals\n", c_areaportals);
+		Sys_Printf( "Size: %5.0f, %5.0f, %5.0f to %5.0f, %5.0f, %5.0f\n",
+			mapMins[ 0 ], mapMins[ 1 ], mapMins[ 2 ],
+			mapMaxs[ 0 ], mapMaxs[ 1 ], mapMaxs[ 2 ]);
+		
+		/* write bogus map */
+		if( fakemap )
+			WriteBSPBrushMap( "fakemap.map", entities[ 0 ].brushes );
+	}
+}
diff --git a/tools/quake3/q3map2/mesh.c b/tools/quake3/q3map2/mesh.c
index f1cccf04..6348d577 100644
--- a/tools/quake3/q3map2/mesh.c
+++ b/tools/quake3/q3map2/mesh.c
@@ -1,825 +1,825 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define MESH_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-LerpDrawVert()
-returns an 50/50 interpolated vert
-*/
-
-void LerpDrawVert( bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *out )
-{
-	int		k;
-	
-	
-	out->xyz[ 0 ] = 0.5 * (a->xyz[ 0 ] + b->xyz[ 0 ]);
-	out->xyz[ 1 ] = 0.5 * (a->xyz[ 1 ] + b->xyz[ 1 ]);
-	out->xyz[ 2 ] = 0.5 * (a->xyz[ 2 ] + b->xyz[ 2 ]);
-
-	out->st[ 0 ] = 0.5 * (a->st[ 0 ] + b->st[ 0 ]);
-	out->st[ 1 ] = 0.5 * (a->st[ 1 ] + b->st[ 1 ]);
-	
-	for( k = 0; k < MAX_LIGHTMAPS; k++ )
-	{
-		out->lightmap[ k ][ 0 ] = 0.5f * (a->lightmap[ k ][ 0 ] + b->lightmap[ k ][ 0 ]);
-		out->lightmap[ k ][ 1 ] = 0.5f * (a->lightmap[ k ][ 1 ] + b->lightmap[ k ][ 1 ]);
-		out->color[ k ][ 0 ] = (a->color[ k ][ 0 ] + b->color[ k ][ 0 ]) >> 1;
-		out->color[ k ][ 1 ] = (a->color[ k ][ 1 ] + b->color[ k ][ 1 ]) >> 1;
-		out->color[ k ][ 2 ] = (a->color[ k ][ 2 ] + b->color[ k ][ 2 ]) >> 1;
-		out->color[ k ][ 3 ] = (a->color[ k ][ 3 ] + b->color[ k ][ 3 ]) >> 1;
-	}
-	
-	/* ydnar: added normal interpolation */
-	out->normal[ 0 ] = 0.5f * (a->normal[ 0 ] + b->normal[ 0 ]);
-	out->normal[ 1 ] = 0.5f * (a->normal[ 1 ] + b->normal[ 1 ]);
-	out->normal[ 2 ] = 0.5f * (a->normal[ 2 ] + b->normal[ 2 ]);
-	
-	/* if the interpolant created a bogus normal, just copy the normal from a */
-	if( VectorNormalize( out->normal, out->normal ) == 0 )
-		VectorCopy( a->normal, out->normal );
-}
-
-
-
-/*
-LerpDrawVertAmount()
-returns a biased interpolated vert
-*/
-
-void LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDrawVert_t *out )
-{
-	int		k;
-	
-	
-	out->xyz[ 0 ] = a->xyz[ 0 ] + amount * (b->xyz[ 0 ] - a->xyz[ 0 ]);
-	out->xyz[ 1 ] = a->xyz[ 1 ] + amount * (b->xyz[ 1 ] - a->xyz[ 1 ]);
-	out->xyz[ 2 ] = a->xyz[ 2 ] + amount * (b->xyz[ 2 ] - a->xyz[ 2 ]);
-	
-	out->st[ 0 ] = a->st[ 0 ] + amount * (b->st[ 0 ] - a->st[ 0 ]);
-	out->st[ 1 ] = a->st[ 1 ] + amount * (b->st[ 1 ] - a->st[ 1 ]);
-	
-	for( k = 0; k < MAX_LIGHTMAPS; k++ )
-	{
-		out->lightmap[ k ][ 0 ] = a->lightmap[ k ][ 0 ] + amount * (b->lightmap[ k ][ 0 ] - a->lightmap[ k ][ 0 ]);
-		out->lightmap[ k ][ 1 ] = a->lightmap[ k ][ 1 ] + amount * (b->lightmap[ k ][ 1 ] - a->lightmap[ k ][ 1 ]);
-		out->color[ k ][ 0 ] = a->color[ k ][ 0 ] + amount * (b->color[ k ][ 0 ] - a->color[ k ][ 0 ]);
-		out->color[ k ][ 1 ] = a->color[ k ][ 1 ] + amount * (b->color[ k ][ 1 ] - a->color[ k ][ 1 ]);
-		out->color[ k ][ 2 ] = a->color[ k ][ 2 ] + amount * (b->color[ k ][ 2 ] - a->color[ k ][ 2 ]);
-		out->color[ k ][ 3 ] = a->color[ k ][ 3 ] + amount * (b->color[ k ][ 3 ] - a->color[ k ][ 3 ]);
-	}
-
-	out->normal[ 0 ] = a->normal[ 0 ] + amount * (b->normal[ 0 ] - a->normal[ 0 ]);
-	out->normal[ 1 ] = a->normal[ 1 ] + amount * (b->normal[ 1 ] - a->normal[ 1 ]);
-	out->normal[ 2 ] = a->normal[ 2 ] + amount * (b->normal[ 2 ] - a->normal[ 2 ]);
-	
-	/* if the interpolant created a bogus normal, just copy the normal from a */
-	if( VectorNormalize( out->normal, out->normal ) == 0 )
-		VectorCopy( a->normal, out->normal );
-}
-
-
-void FreeMesh( mesh_t *m ) {
-	free( m->verts );
-	free( m );
-}
-
-void PrintMesh( mesh_t *m ) {
-	int		i, j;
-
-	for ( i = 0 ; i < m->height ; i++ ) {
-		for ( j = 0 ; j < m->width ; j++ ) {
-			Sys_Printf("(%5.2f %5.2f %5.2f) "
-				, m->verts[i*m->width+j].xyz[0]
-				, m->verts[i*m->width+j].xyz[1]
-				, m->verts[i*m->width+j].xyz[2] );
-		}
-		Sys_Printf("\n");
-	}
-}
-
-
-mesh_t *CopyMesh( mesh_t *mesh ) {
-	mesh_t	*out;
-	int		size;
-
-	out = safe_malloc( sizeof( *out ) );
-	out->width = mesh->width;
-	out->height = mesh->height;
-
-	size = out->width * out->height * sizeof( *out->verts );
-	out->verts = safe_malloc( size );
-	memcpy( out->verts, mesh->verts, size );
-
-	return out;
-}
-
-
-/*
-TransposeMesh()
-returns a transposed copy of the mesh, freeing the original
-*/
-
-mesh_t *TransposeMesh( mesh_t *in ) {
-	int			w, h;
-	mesh_t		*out;
-
-	out = safe_malloc( sizeof( *out ) );
-	out->width = in->height;
-	out->height = in->width;
-	out->verts = safe_malloc( out->width * out->height * sizeof( bspDrawVert_t ) );
-
-	for ( h = 0 ; h < in->height ; h++ ) {
-		for ( w = 0 ; w < in->width ; w++ ) {
-			out->verts[ w * in->height + h ] = in->verts[ h * in->width + w ];
-		}
-	}
-
-	FreeMesh( in );
-
-	return out;
-}
-
-void InvertMesh( mesh_t *in ) {
-	int			w, h;
-	bspDrawVert_t	temp;
-
-	for ( h = 0 ; h < in->height ; h++ ) {
-		for ( w = 0 ; w < in->width / 2 ; w++ ) {
-			temp = in->verts[ h * in->width + w ];
-			in->verts[ h * in->width + w ] = in->verts[ h * in->width + in->width - 1 - w ];
-			in->verts[ h * in->width + in->width - 1 - w ] = temp;
-		}
-	}
-}
-
-/*
-=================
-MakeMeshNormals
-
-=================
-*/
-void MakeMeshNormals( mesh_t in )
-{
-	int		i, j, k, dist;
-	vec3_t	normal;
-	vec3_t	sum;
-	int		count;
-	vec3_t	base;
-	vec3_t	delta;
-	int		x, y;
-	bspDrawVert_t	*dv;
-	vec3_t		around[8], temp;
-	qboolean	good[8];
-	qboolean	wrapWidth, wrapHeight;
-	float		len;
-	int				neighbors[8][2] =
-					{
-						{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
-					};
-	
-	
-	wrapWidth = qfalse;
-	for ( i = 0 ; i < in.height ; i++ ) {
-		VectorSubtract( in.verts[i*in.width].xyz, 
-			in.verts[i*in.width+in.width-1].xyz, delta );
-		len = VectorLength( delta );
-		if ( len > 1.0 ) {
-			break;
-		}
-	}
-	if ( i == in.height ) {
-		wrapWidth = qtrue;
-	}
-
-	wrapHeight = qfalse;
-	for ( i = 0 ; i < in.width ; i++ ) {
-		VectorSubtract( in.verts[i].xyz, 
-			in.verts[i + (in.height-1)*in.width].xyz, delta );
-		len = VectorLength( delta );
-		if ( len > 1.0 ) {
-			break;
-		}
-	}
-	if ( i == in.width) {
-		wrapHeight = qtrue;
-	}
-
-
-	for ( i = 0 ; i < in.width ; i++ ) {
-		for ( j = 0 ; j < in.height ; j++ ) {
-			count = 0;
-			dv = &in.verts[j*in.width+i];
-			VectorCopy( dv->xyz, base );
-			for ( k = 0 ; k < 8 ; k++ ) {
-				VectorClear( around[k] );
-				good[k] = qfalse;
-
-				for ( dist = 1 ; dist <= 3 ; dist++ ) {
-					x = i + neighbors[k][0] * dist;
-					y = j + neighbors[k][1] * dist;
-					if ( wrapWidth ) {
-						if ( x < 0 ) {
-							x = in.width - 1 + x;
-						} else if ( x >= in.width ) {
-							x = 1 + x - in.width;
-						}
-					}
-					if ( wrapHeight ) {
-						if ( y < 0 ) {
-							y = in.height - 1 + y;
-						} else if ( y >= in.height ) {
-							y = 1 + y - in.height;
-						}
-					}
-
-					if ( x < 0 || x >= in.width || y < 0 || y >= in.height ) {
-						break;					// edge of patch
-					}
-					VectorSubtract( in.verts[y*in.width+x].xyz, base, temp );
-					if ( VectorNormalize( temp, temp ) == 0 ) {
-						continue;				// degenerate edge, get more dist
-					} else {
-						good[k] = qtrue;
-						VectorCopy( temp, around[k] );
-						break;					// good edge
-					}
-				}
-			}
-
-			VectorClear( sum );
-			for ( k = 0 ; k < 8 ; k++ ) {
-				if ( !good[k] || !good[(k+1)&7] ) {
-					continue;	// didn't get two points
-				}
-				CrossProduct( around[(k+1)&7], around[k], normal );
-				if ( VectorNormalize( normal, normal ) == 0 ) {
-					continue;
-				}
-				VectorAdd( normal, sum, sum );
-				count++;
-			}
-			if ( count == 0 ) {
-//Sys_Printf("bad normal\n");
-				count = 1;
-			}
-			VectorNormalize( sum, dv->normal );
-		}
-	}
-}
-
-/*
-PutMeshOnCurve()
-drops the aproximating points onto the curve
-ydnar: fixme: make this use LerpDrawVert() rather than this complicated mess
-*/
-
-void PutMeshOnCurve( mesh_t in ) {
-	int		i, j, l, m;
-	float	prev, next;
-	
-	
-	// put all the aproximating points on the curve
-	for ( i = 0 ; i < in.width ; i++ ) {
-		for ( j = 1 ; j < in.height ; j += 2 ) {
-			for ( l = 0 ; l < 3 ; l++ ) {
-				prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j+1)*in.width+i].xyz[l] ) * 0.5;
-				next = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j-1)*in.width+i].xyz[l] ) * 0.5;
-				in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5;
-				
-				/* ydnar: interpolating st coords */
-				if( l < 2 )
-				{
-					prev = ( in.verts[j*in.width+i].st[l] + in.verts[(j+1)*in.width+i].st[l] ) * 0.5;
-					next = ( in.verts[j*in.width+i].st[l] + in.verts[(j-1)*in.width+i].st[l] ) * 0.5;
-					in.verts[j*in.width+i].st[l] = ( prev + next ) * 0.5;
-					
-					for( m = 0; m < MAX_LIGHTMAPS; m++ )
-					{
-						prev = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[(j+1)*in.width+i].lightmap[ m ][l] ) * 0.5;
-						next = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[(j-1)*in.width+i].lightmap[ m ][l] ) * 0.5;
-						in.verts[j*in.width+i].lightmap[ m ][l] = ( prev + next ) * 0.5;
-					}
-				}
-			}
-		}
-	}
-	
-	for ( j = 0 ; j < in.height ; j++ ) {
-		for ( i = 1 ; i < in.width ; i += 2 ) {
-			for ( l = 0 ; l < 3 ; l++ ) {
-				prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i+1].xyz[l] ) * 0.5;
-				next = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i-1].xyz[l] ) * 0.5;
-				in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5;
-				
-				/* ydnar: interpolating st coords */
-				if( l < 2 )
-				{
-					prev = ( in.verts[j*in.width+i].st[l] + in.verts[j*in.width+i+1].st[l] ) * 0.5;
-					next = ( in.verts[j*in.width+i].st[l] + in.verts[j*in.width+i-1].st[l] ) * 0.5;
-					in.verts[j*in.width+i].st[l] = ( prev + next ) * 0.5;
-					
-					for( m = 0; m < MAX_LIGHTMAPS; m++ )
-					{
-						prev = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[j*in.width+i+1].lightmap[ m ][l] ) * 0.5;
-						next = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[j*in.width+i-1].lightmap[ m ][l] ) * 0.5;
-						in.verts[j*in.width+i].lightmap[ m ][l] = ( prev + next ) * 0.5;
-					}
-				}
-			}
-		}
-	}
-}
-
-
-/*
-=================
-SubdivideMesh
-
-=================
-*/
-mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength )
-{
-	int							i, j, k, l;
-	bspDrawVert_t				prev, next, mid;
-	vec3_t						prevxyz, nextxyz, midxyz;
-	vec3_t						delta;
-	float						len;
-	mesh_t						out;
-	
-	/* ydnar: static for os x */
-	MAC_STATIC bspDrawVert_t	expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
-	
-	
-	out.width = in.width;
-	out.height = in.height;
-
-	for ( i = 0 ; i < in.width ; i++ ) {
-		for ( j = 0 ; j < in.height ; j++ ) {
-			expand[j][i] = in.verts[j*in.width+i];
-		}
-	}
-
-	// horizontal subdivisions
-	for ( j = 0 ; j + 2 < out.width ; j += 2 ) {
-		// check subdivided midpoints against control points
-		for ( i = 0 ; i < out.height ; i++ ) {
-			for ( l = 0 ; l < 3 ; l++ ) {
-				prevxyz[l] = expand[i][j+1].xyz[l] - expand[i][j].xyz[l]; 
-				nextxyz[l] = expand[i][j+2].xyz[l] - expand[i][j+1].xyz[l]; 
-				midxyz[l] = (expand[i][j].xyz[l] + expand[i][j+1].xyz[l] * 2
-						+ expand[i][j+2].xyz[l] ) * 0.25;
-			}
-
-			// if the span length is too long, force a subdivision
-			if ( VectorLength( prevxyz ) > minLength 
-				|| VectorLength( nextxyz ) > minLength ) {
-				break;
-			}
-
-			// see if this midpoint is off far enough to subdivide
-			VectorSubtract( expand[i][j+1].xyz, midxyz, delta );
-			len = VectorLength( delta );
-			if ( len > maxError ) {
-				break;
-			}
-		}
-
-		if ( out.width + 2 >= MAX_EXPANDED_AXIS ) {
-			break;	// can't subdivide any more
-		}
-
-		if ( i == out.height ) {
-			continue;	// didn't need subdivision
-		}
-
-		// insert two columns and replace the peak
-		out.width += 2;
-
-		for ( i = 0 ; i < out.height ; i++ ) {
-			LerpDrawVert( &expand[i][j], &expand[i][j+1], &prev );
-			LerpDrawVert( &expand[i][j+1], &expand[i][j+2], &next );
-			LerpDrawVert( &prev, &next, &mid );
-
-			for ( k = out.width - 1 ; k > j + 3 ; k-- ) {
-				expand[i][k] = expand[i][k-2];
-			}
-			expand[i][j + 1] = prev;
-			expand[i][j + 2] = mid;
-			expand[i][j + 3] = next;
-		}
-
-		// back up and recheck this set again, it may need more subdivision
-		j -= 2;
-
-	}
-
-	// vertical subdivisions
-	for ( j = 0 ; j + 2 < out.height ; j += 2 ) {
-		// check subdivided midpoints against control points
-		for ( i = 0 ; i < out.width ; i++ ) {
-			for ( l = 0 ; l < 3 ; l++ ) {
-				prevxyz[l] = expand[j+1][i].xyz[l] - expand[j][i].xyz[l]; 
-				nextxyz[l] = expand[j+2][i].xyz[l] - expand[j+1][i].xyz[l]; 
-				midxyz[l] = (expand[j][i].xyz[l] + expand[j+1][i].xyz[l] * 2
-						+ expand[j+2][i].xyz[l] ) * 0.25;
-			}
-
-			// if the span length is too long, force a subdivision
-			if ( VectorLength( prevxyz ) > minLength 
-				|| VectorLength( nextxyz ) > minLength ) {
-				break;
-			}
-			// see if this midpoint is off far enough to subdivide
-			VectorSubtract( expand[j+1][i].xyz, midxyz, delta );
-			len = VectorLength( delta );
-			if ( len > maxError ) {
-				break;
-			}
-		}
-
-		if ( out.height + 2 >= MAX_EXPANDED_AXIS ) {
-			break;	// can't subdivide any more
-		}
-
-		if ( i == out.width ) {
-			continue;	// didn't need subdivision
-		}
-
-		// insert two columns and replace the peak
-		out.height += 2;
-
-		for ( i = 0 ; i < out.width ; i++ ) {
-			LerpDrawVert( &expand[j][i], &expand[j+1][i], &prev );
-			LerpDrawVert( &expand[j+1][i], &expand[j+2][i], &next );
-			LerpDrawVert( &prev, &next, &mid );
-
-			for ( k = out.height - 1 ; k > j + 3 ; k-- ) {
-				expand[k][i] = expand[k-2][i];
-			}
-			expand[j+1][i] = prev;
-			expand[j+2][i] = mid;
-			expand[j+3][i] = next;
-		}
-
-		// back up and recheck this set again, it may need more subdivision
-		j -= 2;
-
-	}
-
-	// collapse the verts
-
-	out.verts = &expand[0][0];
-	for ( i = 1 ; i < out.height ; i++ ) {
-		memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) );
-	}
-
-	return CopyMesh(&out);
-}
-
-
-
-/*
-IterationsForCurve() - ydnar
-given a curve of a certain length, return the number of subdivision iterations
-note: this is affected by subdivision amount
-*/
-
-int IterationsForCurve( float len, int subdivisions )
-{
-	int		iterations, facets;
-	
-	
-	/* calculate the number of subdivisions */
-	for( iterations = 0; iterations < 3; iterations++ )
-	{
-		facets = subdivisions * 16 * pow( 2, iterations );
-		if( facets >= len )
-			break;
-	}
-	
-	/* return to caller */
-	return iterations;
-}
-
-
-/*
-SubdivideMesh2() - ydnar
-subdivides each mesh quad a specified number of times
-*/
-
-mesh_t *SubdivideMesh2( mesh_t in, int iterations )
-{
-	int							i, j, k;
-	bspDrawVert_t				prev, next, mid;
-	mesh_t						out;
-	
-	/* ydnar: static for os x */
-	MAC_STATIC bspDrawVert_t	expand[ MAX_EXPANDED_AXIS ][ MAX_EXPANDED_AXIS ];
-	
-	
-	/* initial setup */
-	out.width = in.width;
-	out.height = in.height;
-	for( i = 0; i < in.width; i++ )
-	{
-		for( j = 0; j < in.height; j++ )
-			expand[ j ][ i ] = in.verts[ j * in.width + i ];
-	}
-	
-	/* keep chopping */
-	for( iterations; iterations > 0; iterations-- )
-	{
-		/* horizontal subdivisions */
-		for( j = 0; j + 2 < out.width; j += 4 )
-		{
-			/* check size limit */
-			if( out.width + 2 >= MAX_EXPANDED_AXIS )
-				break;
-			
-			/* insert two columns and replace the peak */
-			out.width += 2;
-			for( i = 0; i < out.height; i++ )
-			{
-				LerpDrawVert( &expand[ i ][ j ], &expand[ i ][ j + 1 ], &prev );
-				LerpDrawVert( &expand[ i ][ j + 1 ], &expand[ i ][ j + 2 ], &next );
-				LerpDrawVert( &prev, &next, &mid );
-
-				for ( k = out.width - 1 ; k > j + 3; k-- )
-					expand [ i ][ k ] = expand[ i ][ k - 2 ];
-				expand[ i ][ j + 1 ] = prev;
-				expand[ i ][ j + 2 ] = mid;
-				expand[ i ][ j + 3 ] = next;
-			}
-			
-		}
-
-		/* vertical subdivisions */
-		for ( j = 0; j + 2 < out.height; j += 4 )
-		{
-			/* check size limit */
-			if( out.height + 2 >= MAX_EXPANDED_AXIS )
-				break;
-			
-			/* insert two columns and replace the peak */
-			out.height += 2;
-			for( i = 0; i < out.width; i++ )
-			{
-				LerpDrawVert( &expand[ j ][ i ], &expand[ j + 1 ][ i ], &prev );
-				LerpDrawVert( &expand[ j + 1 ][ i ], &expand[ j + 2 ][ i ], &next );
-				LerpDrawVert( &prev, &next, &mid );
-				
-				for( k = out.height - 1; k > j  +  3; k-- )
-					expand[ k ][ i ] = expand[ k - 2 ][ i ];
-				expand[ j + 1 ][ i ] = prev;
-				expand[ j + 2 ][ i ] = mid;
-				expand[ j + 3 ][ i ] = next;
-			}
-		}
-	}
-	
-	/* collapse the verts */
-	out.verts = &expand[ 0 ][ 0 ];
-	for( i = 1; i < out.height; i++ )
-		memmove( &out.verts[ i * out.width ], expand[ i ], out.width * sizeof( bspDrawVert_t ) );
-	
-	/* return to sender */
-	return CopyMesh( &out );
-}
-
-
-
-
-
-
-
-/*
-================
-ProjectPointOntoVector
-================
-*/
-void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
-{
-	vec3_t pVec, vec;
-
-	VectorSubtract( point, vStart, pVec );
-	VectorSubtract( vEnd, vStart, vec );
-	VectorNormalize( vec, vec );
-	// project onto the directional vector for this segment
-	VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
-}
-
-/*
-================
-RemoveLinearMeshColumsRows
-================
-*/
-mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
-	int							i, j, k;
-	float						len, maxLength;
-	vec3_t						proj, dir;
-	mesh_t						out;
-	
-	/* ydnar: static for os x */
-	MAC_STATIC bspDrawVert_t	expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
-	
-
-	out.width = in->width;
-	out.height = in->height;
-
-	for ( i = 0 ; i < in->width ; i++ ) {
-		for ( j = 0 ; j < in->height ; j++ ) {
-			expand[j][i] = in->verts[j*in->width+i];
-		}
-	}
-
-	for ( j = 1 ; j < out.width - 1; j++ ) {
-		maxLength = 0;
-		for ( i = 0 ; i < out.height ; i++ ) {
-			ProjectPointOntoVector(expand[i][j].xyz, expand[i][j-1].xyz, expand[i][j+1].xyz, proj);
-			VectorSubtract(expand[i][j].xyz, proj, dir);
-			len = VectorLength(dir);
-			if (len > maxLength) {
-				maxLength = len;
-			}
-		}
-		if (maxLength < 0.1)
-		{
-			out.width--;
-			for ( i = 0 ; i < out.height ; i++ ) {
-				for (k = j; k < out.width; k++) {
-					expand[i][k] = expand[i][k+1];
-				}
-			}
-			j--;
-		}
-	}
-	for ( j = 1 ; j < out.height - 1; j++ ) {
-		maxLength = 0;
-		for ( i = 0 ; i < out.width ; i++ ) {
-			ProjectPointOntoVector(expand[j][i].xyz, expand[j-1][i].xyz, expand[j+1][i].xyz, proj);
-			VectorSubtract(expand[j][i].xyz, proj, dir);
-			len = VectorLength(dir);
-			if (len > maxLength) {
-				maxLength = len;
-			}
-		}
-		if (maxLength < 0.1)
-		{
-			out.height--;
-			for ( i = 0 ; i < out.width ; i++ ) {
-				for (k = j; k < out.height; k++) {
-					expand[k][i] = expand[k+1][i];
-				}
-			}
-			j--;
-		}
-	}
-	// collapse the verts
-	out.verts = &expand[0][0];
-	for ( i = 1 ; i < out.height ; i++ ) {
-		memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) );
-	}
-
-	return CopyMesh(&out);
-}
-
-
-
-/*
-=================
-SubdivideMeshQuads
-=================
-*/
-mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable )
-{
-	int				i, j, k, w, h, maxsubdivisions, subdivisions;
-	vec3_t			dir;
-	float			length, maxLength, amount;
-	mesh_t			out;
-	bspDrawVert_t	expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
-
-	out.width = in->width;
-	out.height = in->height;
-
-	for ( i = 0 ; i < in->width ; i++ ) {
-		for ( j = 0 ; j < in->height ; j++ ) {
-			expand[j][i] = in->verts[j*in->width+i];
-		}
-	}
-
-	if (maxsize > MAX_EXPANDED_AXIS)
-		Error("SubdivideMeshQuads: maxsize > MAX_EXPANDED_AXIS");
-
-	// horizontal subdivisions
-
-	maxsubdivisions = (maxsize - in->width) / (in->width - 1);
-
-	for ( w = 0, j = 0 ; w < in->width - 1; w++, j += subdivisions + 1) {
-		maxLength = 0;
-		for ( i = 0 ; i < out.height ; i++ ) {
-			VectorSubtract(expand[i][j+1].xyz, expand[i][j].xyz, dir);
-			length = VectorLength( dir );
-			if (length > maxLength) {
-				maxLength = length;
-			}
-		}
-		
-		subdivisions = (int) (maxLength / minLength);
-		if (subdivisions > maxsubdivisions)
-			subdivisions = maxsubdivisions;
-
-		widthtable[w] = subdivisions + 1;
-		if (subdivisions <= 0)
-			continue;
-
-		out.width += subdivisions;
-
-		for ( i = 0 ; i < out.height ; i++ ) {
-			for ( k = out.width - 1 ; k > j + subdivisions; k-- ) {
-				expand[i][k] = expand[i][k-subdivisions];
-			}
-			for (k = 1; k <= subdivisions; k++)
-			{
-				amount = (float) k / (subdivisions + 1);
-				LerpDrawVertAmount(&expand[i][j], &expand[i][j+subdivisions+1], amount, &expand[i][j+k]);
-			}
-		}
-	}
-
-	maxsubdivisions = (maxsize - in->height) / (in->height - 1);
-
-	for ( h = 0, j = 0 ; h < in->height - 1; h++, j += subdivisions + 1) {
-		maxLength = 0;
-		for ( i = 0 ; i < out.width ; i++ ) {
-			VectorSubtract(expand[j+1][i].xyz, expand[j][i].xyz, dir);
-			length = VectorLength( dir );
-			if (length  > maxLength) {
-				maxLength = length;
-			}
-		}
-		
-		subdivisions = (int) (maxLength / minLength);
-		if (subdivisions > maxsubdivisions)
-			subdivisions = maxsubdivisions;
-
-		heighttable[h] = subdivisions + 1;
-		if (subdivisions <= 0)
-			continue;
-
-		out.height += subdivisions;
-
-		for ( i = 0 ; i < out.width ; i++ ) {
-			for ( k = out.height - 1 ; k > j + subdivisions; k-- ) {
-				expand[k][i] = expand[k-subdivisions][i];
-			}
-			for (k = 1; k <= subdivisions; k++)
-			{
-				amount = (float) k / (subdivisions + 1);
-				LerpDrawVertAmount(&expand[j][i], &expand[j+subdivisions+1][i], amount, &expand[j+k][i]);
-			}
-		}
-	}
-
-	// collapse the verts
-	out.verts = &expand[0][0];
-	for ( i = 1 ; i < out.height ; i++ ) {
-		memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) );
-	}
-
-	return CopyMesh(&out);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define MESH_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+LerpDrawVert()
+returns an 50/50 interpolated vert
+*/
+
+void LerpDrawVert( bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *out )
+{
+	int		k;
+	
+	
+	out->xyz[ 0 ] = 0.5 * (a->xyz[ 0 ] + b->xyz[ 0 ]);
+	out->xyz[ 1 ] = 0.5 * (a->xyz[ 1 ] + b->xyz[ 1 ]);
+	out->xyz[ 2 ] = 0.5 * (a->xyz[ 2 ] + b->xyz[ 2 ]);
+
+	out->st[ 0 ] = 0.5 * (a->st[ 0 ] + b->st[ 0 ]);
+	out->st[ 1 ] = 0.5 * (a->st[ 1 ] + b->st[ 1 ]);
+	
+	for( k = 0; k < MAX_LIGHTMAPS; k++ )
+	{
+		out->lightmap[ k ][ 0 ] = 0.5f * (a->lightmap[ k ][ 0 ] + b->lightmap[ k ][ 0 ]);
+		out->lightmap[ k ][ 1 ] = 0.5f * (a->lightmap[ k ][ 1 ] + b->lightmap[ k ][ 1 ]);
+		out->color[ k ][ 0 ] = (a->color[ k ][ 0 ] + b->color[ k ][ 0 ]) >> 1;
+		out->color[ k ][ 1 ] = (a->color[ k ][ 1 ] + b->color[ k ][ 1 ]) >> 1;
+		out->color[ k ][ 2 ] = (a->color[ k ][ 2 ] + b->color[ k ][ 2 ]) >> 1;
+		out->color[ k ][ 3 ] = (a->color[ k ][ 3 ] + b->color[ k ][ 3 ]) >> 1;
+	}
+	
+	/* ydnar: added normal interpolation */
+	out->normal[ 0 ] = 0.5f * (a->normal[ 0 ] + b->normal[ 0 ]);
+	out->normal[ 1 ] = 0.5f * (a->normal[ 1 ] + b->normal[ 1 ]);
+	out->normal[ 2 ] = 0.5f * (a->normal[ 2 ] + b->normal[ 2 ]);
+	
+	/* if the interpolant created a bogus normal, just copy the normal from a */
+	if( VectorNormalize( out->normal, out->normal ) == 0 )
+		VectorCopy( a->normal, out->normal );
+}
+
+
+
+/*
+LerpDrawVertAmount()
+returns a biased interpolated vert
+*/
+
+void LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDrawVert_t *out )
+{
+	int		k;
+	
+	
+	out->xyz[ 0 ] = a->xyz[ 0 ] + amount * (b->xyz[ 0 ] - a->xyz[ 0 ]);
+	out->xyz[ 1 ] = a->xyz[ 1 ] + amount * (b->xyz[ 1 ] - a->xyz[ 1 ]);
+	out->xyz[ 2 ] = a->xyz[ 2 ] + amount * (b->xyz[ 2 ] - a->xyz[ 2 ]);
+	
+	out->st[ 0 ] = a->st[ 0 ] + amount * (b->st[ 0 ] - a->st[ 0 ]);
+	out->st[ 1 ] = a->st[ 1 ] + amount * (b->st[ 1 ] - a->st[ 1 ]);
+	
+	for( k = 0; k < MAX_LIGHTMAPS; k++ )
+	{
+		out->lightmap[ k ][ 0 ] = a->lightmap[ k ][ 0 ] + amount * (b->lightmap[ k ][ 0 ] - a->lightmap[ k ][ 0 ]);
+		out->lightmap[ k ][ 1 ] = a->lightmap[ k ][ 1 ] + amount * (b->lightmap[ k ][ 1 ] - a->lightmap[ k ][ 1 ]);
+		out->color[ k ][ 0 ] = a->color[ k ][ 0 ] + amount * (b->color[ k ][ 0 ] - a->color[ k ][ 0 ]);
+		out->color[ k ][ 1 ] = a->color[ k ][ 1 ] + amount * (b->color[ k ][ 1 ] - a->color[ k ][ 1 ]);
+		out->color[ k ][ 2 ] = a->color[ k ][ 2 ] + amount * (b->color[ k ][ 2 ] - a->color[ k ][ 2 ]);
+		out->color[ k ][ 3 ] = a->color[ k ][ 3 ] + amount * (b->color[ k ][ 3 ] - a->color[ k ][ 3 ]);
+	}
+
+	out->normal[ 0 ] = a->normal[ 0 ] + amount * (b->normal[ 0 ] - a->normal[ 0 ]);
+	out->normal[ 1 ] = a->normal[ 1 ] + amount * (b->normal[ 1 ] - a->normal[ 1 ]);
+	out->normal[ 2 ] = a->normal[ 2 ] + amount * (b->normal[ 2 ] - a->normal[ 2 ]);
+	
+	/* if the interpolant created a bogus normal, just copy the normal from a */
+	if( VectorNormalize( out->normal, out->normal ) == 0 )
+		VectorCopy( a->normal, out->normal );
+}
+
+
+void FreeMesh( mesh_t *m ) {
+	free( m->verts );
+	free( m );
+}
+
+void PrintMesh( mesh_t *m ) {
+	int		i, j;
+
+	for ( i = 0 ; i < m->height ; i++ ) {
+		for ( j = 0 ; j < m->width ; j++ ) {
+			Sys_Printf("(%5.2f %5.2f %5.2f) "
+				, m->verts[i*m->width+j].xyz[0]
+				, m->verts[i*m->width+j].xyz[1]
+				, m->verts[i*m->width+j].xyz[2] );
+		}
+		Sys_Printf("\n");
+	}
+}
+
+
+mesh_t *CopyMesh( mesh_t *mesh ) {
+	mesh_t	*out;
+	int		size;
+
+	out = safe_malloc( sizeof( *out ) );
+	out->width = mesh->width;
+	out->height = mesh->height;
+
+	size = out->width * out->height * sizeof( *out->verts );
+	out->verts = safe_malloc( size );
+	memcpy( out->verts, mesh->verts, size );
+
+	return out;
+}
+
+
+/*
+TransposeMesh()
+returns a transposed copy of the mesh, freeing the original
+*/
+
+mesh_t *TransposeMesh( mesh_t *in ) {
+	int			w, h;
+	mesh_t		*out;
+
+	out = safe_malloc( sizeof( *out ) );
+	out->width = in->height;
+	out->height = in->width;
+	out->verts = safe_malloc( out->width * out->height * sizeof( bspDrawVert_t ) );
+
+	for ( h = 0 ; h < in->height ; h++ ) {
+		for ( w = 0 ; w < in->width ; w++ ) {
+			out->verts[ w * in->height + h ] = in->verts[ h * in->width + w ];
+		}
+	}
+
+	FreeMesh( in );
+
+	return out;
+}
+
+void InvertMesh( mesh_t *in ) {
+	int			w, h;
+	bspDrawVert_t	temp;
+
+	for ( h = 0 ; h < in->height ; h++ ) {
+		for ( w = 0 ; w < in->width / 2 ; w++ ) {
+			temp = in->verts[ h * in->width + w ];
+			in->verts[ h * in->width + w ] = in->verts[ h * in->width + in->width - 1 - w ];
+			in->verts[ h * in->width + in->width - 1 - w ] = temp;
+		}
+	}
+}
+
+/*
+=================
+MakeMeshNormals
+
+=================
+*/
+void MakeMeshNormals( mesh_t in )
+{
+	int		i, j, k, dist;
+	vec3_t	normal;
+	vec3_t	sum;
+	int		count;
+	vec3_t	base;
+	vec3_t	delta;
+	int		x, y;
+	bspDrawVert_t	*dv;
+	vec3_t		around[8], temp;
+	qboolean	good[8];
+	qboolean	wrapWidth, wrapHeight;
+	float		len;
+	int				neighbors[8][2] =
+					{
+						{0,1}, {1,1}, {1,0}, {1,-1}, {0,-1}, {-1,-1}, {-1,0}, {-1,1}
+					};
+	
+	
+	wrapWidth = qfalse;
+	for ( i = 0 ; i < in.height ; i++ ) {
+		VectorSubtract( in.verts[i*in.width].xyz, 
+			in.verts[i*in.width+in.width-1].xyz, delta );
+		len = VectorLength( delta );
+		if ( len > 1.0 ) {
+			break;
+		}
+	}
+	if ( i == in.height ) {
+		wrapWidth = qtrue;
+	}
+
+	wrapHeight = qfalse;
+	for ( i = 0 ; i < in.width ; i++ ) {
+		VectorSubtract( in.verts[i].xyz, 
+			in.verts[i + (in.height-1)*in.width].xyz, delta );
+		len = VectorLength( delta );
+		if ( len > 1.0 ) {
+			break;
+		}
+	}
+	if ( i == in.width) {
+		wrapHeight = qtrue;
+	}
+
+
+	for ( i = 0 ; i < in.width ; i++ ) {
+		for ( j = 0 ; j < in.height ; j++ ) {
+			count = 0;
+			dv = &in.verts[j*in.width+i];
+			VectorCopy( dv->xyz, base );
+			for ( k = 0 ; k < 8 ; k++ ) {
+				VectorClear( around[k] );
+				good[k] = qfalse;
+
+				for ( dist = 1 ; dist <= 3 ; dist++ ) {
+					x = i + neighbors[k][0] * dist;
+					y = j + neighbors[k][1] * dist;
+					if ( wrapWidth ) {
+						if ( x < 0 ) {
+							x = in.width - 1 + x;
+						} else if ( x >= in.width ) {
+							x = 1 + x - in.width;
+						}
+					}
+					if ( wrapHeight ) {
+						if ( y < 0 ) {
+							y = in.height - 1 + y;
+						} else if ( y >= in.height ) {
+							y = 1 + y - in.height;
+						}
+					}
+
+					if ( x < 0 || x >= in.width || y < 0 || y >= in.height ) {
+						break;					// edge of patch
+					}
+					VectorSubtract( in.verts[y*in.width+x].xyz, base, temp );
+					if ( VectorNormalize( temp, temp ) == 0 ) {
+						continue;				// degenerate edge, get more dist
+					} else {
+						good[k] = qtrue;
+						VectorCopy( temp, around[k] );
+						break;					// good edge
+					}
+				}
+			}
+
+			VectorClear( sum );
+			for ( k = 0 ; k < 8 ; k++ ) {
+				if ( !good[k] || !good[(k+1)&7] ) {
+					continue;	// didn't get two points
+				}
+				CrossProduct( around[(k+1)&7], around[k], normal );
+				if ( VectorNormalize( normal, normal ) == 0 ) {
+					continue;
+				}
+				VectorAdd( normal, sum, sum );
+				count++;
+			}
+			if ( count == 0 ) {
+//Sys_Printf("bad normal\n");
+				count = 1;
+			}
+			VectorNormalize( sum, dv->normal );
+		}
+	}
+}
+
+/*
+PutMeshOnCurve()
+drops the aproximating points onto the curve
+ydnar: fixme: make this use LerpDrawVert() rather than this complicated mess
+*/
+
+void PutMeshOnCurve( mesh_t in ) {
+	int		i, j, l, m;
+	float	prev, next;
+	
+	
+	// put all the aproximating points on the curve
+	for ( i = 0 ; i < in.width ; i++ ) {
+		for ( j = 1 ; j < in.height ; j += 2 ) {
+			for ( l = 0 ; l < 3 ; l++ ) {
+				prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j+1)*in.width+i].xyz[l] ) * 0.5;
+				next = ( in.verts[j*in.width+i].xyz[l] + in.verts[(j-1)*in.width+i].xyz[l] ) * 0.5;
+				in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5;
+				
+				/* ydnar: interpolating st coords */
+				if( l < 2 )
+				{
+					prev = ( in.verts[j*in.width+i].st[l] + in.verts[(j+1)*in.width+i].st[l] ) * 0.5;
+					next = ( in.verts[j*in.width+i].st[l] + in.verts[(j-1)*in.width+i].st[l] ) * 0.5;
+					in.verts[j*in.width+i].st[l] = ( prev + next ) * 0.5;
+					
+					for( m = 0; m < MAX_LIGHTMAPS; m++ )
+					{
+						prev = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[(j+1)*in.width+i].lightmap[ m ][l] ) * 0.5;
+						next = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[(j-1)*in.width+i].lightmap[ m ][l] ) * 0.5;
+						in.verts[j*in.width+i].lightmap[ m ][l] = ( prev + next ) * 0.5;
+					}
+				}
+			}
+		}
+	}
+	
+	for ( j = 0 ; j < in.height ; j++ ) {
+		for ( i = 1 ; i < in.width ; i += 2 ) {
+			for ( l = 0 ; l < 3 ; l++ ) {
+				prev = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i+1].xyz[l] ) * 0.5;
+				next = ( in.verts[j*in.width+i].xyz[l] + in.verts[j*in.width+i-1].xyz[l] ) * 0.5;
+				in.verts[j*in.width+i].xyz[l] = ( prev + next ) * 0.5;
+				
+				/* ydnar: interpolating st coords */
+				if( l < 2 )
+				{
+					prev = ( in.verts[j*in.width+i].st[l] + in.verts[j*in.width+i+1].st[l] ) * 0.5;
+					next = ( in.verts[j*in.width+i].st[l] + in.verts[j*in.width+i-1].st[l] ) * 0.5;
+					in.verts[j*in.width+i].st[l] = ( prev + next ) * 0.5;
+					
+					for( m = 0; m < MAX_LIGHTMAPS; m++ )
+					{
+						prev = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[j*in.width+i+1].lightmap[ m ][l] ) * 0.5;
+						next = ( in.verts[j*in.width+i].lightmap[ m ][l] + in.verts[j*in.width+i-1].lightmap[ m ][l] ) * 0.5;
+						in.verts[j*in.width+i].lightmap[ m ][l] = ( prev + next ) * 0.5;
+					}
+				}
+			}
+		}
+	}
+}
+
+
+/*
+=================
+SubdivideMesh
+
+=================
+*/
+mesh_t *SubdivideMesh( mesh_t in, float maxError, float minLength )
+{
+	int							i, j, k, l;
+	bspDrawVert_t				prev, next, mid;
+	vec3_t						prevxyz, nextxyz, midxyz;
+	vec3_t						delta;
+	float						len;
+	mesh_t						out;
+	
+	/* ydnar: static for os x */
+	MAC_STATIC bspDrawVert_t	expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
+	
+	
+	out.width = in.width;
+	out.height = in.height;
+
+	for ( i = 0 ; i < in.width ; i++ ) {
+		for ( j = 0 ; j < in.height ; j++ ) {
+			expand[j][i] = in.verts[j*in.width+i];
+		}
+	}
+
+	// horizontal subdivisions
+	for ( j = 0 ; j + 2 < out.width ; j += 2 ) {
+		// check subdivided midpoints against control points
+		for ( i = 0 ; i < out.height ; i++ ) {
+			for ( l = 0 ; l < 3 ; l++ ) {
+				prevxyz[l] = expand[i][j+1].xyz[l] - expand[i][j].xyz[l]; 
+				nextxyz[l] = expand[i][j+2].xyz[l] - expand[i][j+1].xyz[l]; 
+				midxyz[l] = (expand[i][j].xyz[l] + expand[i][j+1].xyz[l] * 2
+						+ expand[i][j+2].xyz[l] ) * 0.25;
+			}
+
+			// if the span length is too long, force a subdivision
+			if ( VectorLength( prevxyz ) > minLength 
+				|| VectorLength( nextxyz ) > minLength ) {
+				break;
+			}
+
+			// see if this midpoint is off far enough to subdivide
+			VectorSubtract( expand[i][j+1].xyz, midxyz, delta );
+			len = VectorLength( delta );
+			if ( len > maxError ) {
+				break;
+			}
+		}
+
+		if ( out.width + 2 >= MAX_EXPANDED_AXIS ) {
+			break;	// can't subdivide any more
+		}
+
+		if ( i == out.height ) {
+			continue;	// didn't need subdivision
+		}
+
+		// insert two columns and replace the peak
+		out.width += 2;
+
+		for ( i = 0 ; i < out.height ; i++ ) {
+			LerpDrawVert( &expand[i][j], &expand[i][j+1], &prev );
+			LerpDrawVert( &expand[i][j+1], &expand[i][j+2], &next );
+			LerpDrawVert( &prev, &next, &mid );
+
+			for ( k = out.width - 1 ; k > j + 3 ; k-- ) {
+				expand[i][k] = expand[i][k-2];
+			}
+			expand[i][j + 1] = prev;
+			expand[i][j + 2] = mid;
+			expand[i][j + 3] = next;
+		}
+
+		// back up and recheck this set again, it may need more subdivision
+		j -= 2;
+
+	}
+
+	// vertical subdivisions
+	for ( j = 0 ; j + 2 < out.height ; j += 2 ) {
+		// check subdivided midpoints against control points
+		for ( i = 0 ; i < out.width ; i++ ) {
+			for ( l = 0 ; l < 3 ; l++ ) {
+				prevxyz[l] = expand[j+1][i].xyz[l] - expand[j][i].xyz[l]; 
+				nextxyz[l] = expand[j+2][i].xyz[l] - expand[j+1][i].xyz[l]; 
+				midxyz[l] = (expand[j][i].xyz[l] + expand[j+1][i].xyz[l] * 2
+						+ expand[j+2][i].xyz[l] ) * 0.25;
+			}
+
+			// if the span length is too long, force a subdivision
+			if ( VectorLength( prevxyz ) > minLength 
+				|| VectorLength( nextxyz ) > minLength ) {
+				break;
+			}
+			// see if this midpoint is off far enough to subdivide
+			VectorSubtract( expand[j+1][i].xyz, midxyz, delta );
+			len = VectorLength( delta );
+			if ( len > maxError ) {
+				break;
+			}
+		}
+
+		if ( out.height + 2 >= MAX_EXPANDED_AXIS ) {
+			break;	// can't subdivide any more
+		}
+
+		if ( i == out.width ) {
+			continue;	// didn't need subdivision
+		}
+
+		// insert two columns and replace the peak
+		out.height += 2;
+
+		for ( i = 0 ; i < out.width ; i++ ) {
+			LerpDrawVert( &expand[j][i], &expand[j+1][i], &prev );
+			LerpDrawVert( &expand[j+1][i], &expand[j+2][i], &next );
+			LerpDrawVert( &prev, &next, &mid );
+
+			for ( k = out.height - 1 ; k > j + 3 ; k-- ) {
+				expand[k][i] = expand[k-2][i];
+			}
+			expand[j+1][i] = prev;
+			expand[j+2][i] = mid;
+			expand[j+3][i] = next;
+		}
+
+		// back up and recheck this set again, it may need more subdivision
+		j -= 2;
+
+	}
+
+	// collapse the verts
+
+	out.verts = &expand[0][0];
+	for ( i = 1 ; i < out.height ; i++ ) {
+		memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) );
+	}
+
+	return CopyMesh(&out);
+}
+
+
+
+/*
+IterationsForCurve() - ydnar
+given a curve of a certain length, return the number of subdivision iterations
+note: this is affected by subdivision amount
+*/
+
+int IterationsForCurve( float len, int subdivisions )
+{
+	int		iterations, facets;
+	
+	
+	/* calculate the number of subdivisions */
+	for( iterations = 0; iterations < 3; iterations++ )
+	{
+		facets = subdivisions * 16 * pow( 2, iterations );
+		if( facets >= len )
+			break;
+	}
+	
+	/* return to caller */
+	return iterations;
+}
+
+
+/*
+SubdivideMesh2() - ydnar
+subdivides each mesh quad a specified number of times
+*/
+
+mesh_t *SubdivideMesh2( mesh_t in, int iterations )
+{
+	int							i, j, k;
+	bspDrawVert_t				prev, next, mid;
+	mesh_t						out;
+	
+	/* ydnar: static for os x */
+	MAC_STATIC bspDrawVert_t	expand[ MAX_EXPANDED_AXIS ][ MAX_EXPANDED_AXIS ];
+	
+	
+	/* initial setup */
+	out.width = in.width;
+	out.height = in.height;
+	for( i = 0; i < in.width; i++ )
+	{
+		for( j = 0; j < in.height; j++ )
+			expand[ j ][ i ] = in.verts[ j * in.width + i ];
+	}
+	
+	/* keep chopping */
+	for( iterations; iterations > 0; iterations-- )
+	{
+		/* horizontal subdivisions */
+		for( j = 0; j + 2 < out.width; j += 4 )
+		{
+			/* check size limit */
+			if( out.width + 2 >= MAX_EXPANDED_AXIS )
+				break;
+			
+			/* insert two columns and replace the peak */
+			out.width += 2;
+			for( i = 0; i < out.height; i++ )
+			{
+				LerpDrawVert( &expand[ i ][ j ], &expand[ i ][ j + 1 ], &prev );
+				LerpDrawVert( &expand[ i ][ j + 1 ], &expand[ i ][ j + 2 ], &next );
+				LerpDrawVert( &prev, &next, &mid );
+
+				for ( k = out.width - 1 ; k > j + 3; k-- )
+					expand [ i ][ k ] = expand[ i ][ k - 2 ];
+				expand[ i ][ j + 1 ] = prev;
+				expand[ i ][ j + 2 ] = mid;
+				expand[ i ][ j + 3 ] = next;
+			}
+			
+		}
+
+		/* vertical subdivisions */
+		for ( j = 0; j + 2 < out.height; j += 4 )
+		{
+			/* check size limit */
+			if( out.height + 2 >= MAX_EXPANDED_AXIS )
+				break;
+			
+			/* insert two columns and replace the peak */
+			out.height += 2;
+			for( i = 0; i < out.width; i++ )
+			{
+				LerpDrawVert( &expand[ j ][ i ], &expand[ j + 1 ][ i ], &prev );
+				LerpDrawVert( &expand[ j + 1 ][ i ], &expand[ j + 2 ][ i ], &next );
+				LerpDrawVert( &prev, &next, &mid );
+				
+				for( k = out.height - 1; k > j  +  3; k-- )
+					expand[ k ][ i ] = expand[ k - 2 ][ i ];
+				expand[ j + 1 ][ i ] = prev;
+				expand[ j + 2 ][ i ] = mid;
+				expand[ j + 3 ][ i ] = next;
+			}
+		}
+	}
+	
+	/* collapse the verts */
+	out.verts = &expand[ 0 ][ 0 ];
+	for( i = 1; i < out.height; i++ )
+		memmove( &out.verts[ i * out.width ], expand[ i ], out.width * sizeof( bspDrawVert_t ) );
+	
+	/* return to sender */
+	return CopyMesh( &out );
+}
+
+
+
+
+
+
+
+/*
+================
+ProjectPointOntoVector
+================
+*/
+void ProjectPointOntoVector( vec3_t point, vec3_t vStart, vec3_t vEnd, vec3_t vProj )
+{
+	vec3_t pVec, vec;
+
+	VectorSubtract( point, vStart, pVec );
+	VectorSubtract( vEnd, vStart, vec );
+	VectorNormalize( vec, vec );
+	// project onto the directional vector for this segment
+	VectorMA( vStart, DotProduct( pVec, vec ), vec, vProj );
+}
+
+/*
+================
+RemoveLinearMeshColumsRows
+================
+*/
+mesh_t *RemoveLinearMeshColumnsRows( mesh_t *in ) {
+	int							i, j, k;
+	float						len, maxLength;
+	vec3_t						proj, dir;
+	mesh_t						out;
+	
+	/* ydnar: static for os x */
+	MAC_STATIC bspDrawVert_t	expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
+	
+
+	out.width = in->width;
+	out.height = in->height;
+
+	for ( i = 0 ; i < in->width ; i++ ) {
+		for ( j = 0 ; j < in->height ; j++ ) {
+			expand[j][i] = in->verts[j*in->width+i];
+		}
+	}
+
+	for ( j = 1 ; j < out.width - 1; j++ ) {
+		maxLength = 0;
+		for ( i = 0 ; i < out.height ; i++ ) {
+			ProjectPointOntoVector(expand[i][j].xyz, expand[i][j-1].xyz, expand[i][j+1].xyz, proj);
+			VectorSubtract(expand[i][j].xyz, proj, dir);
+			len = VectorLength(dir);
+			if (len > maxLength) {
+				maxLength = len;
+			}
+		}
+		if (maxLength < 0.1)
+		{
+			out.width--;
+			for ( i = 0 ; i < out.height ; i++ ) {
+				for (k = j; k < out.width; k++) {
+					expand[i][k] = expand[i][k+1];
+				}
+			}
+			j--;
+		}
+	}
+	for ( j = 1 ; j < out.height - 1; j++ ) {
+		maxLength = 0;
+		for ( i = 0 ; i < out.width ; i++ ) {
+			ProjectPointOntoVector(expand[j][i].xyz, expand[j-1][i].xyz, expand[j+1][i].xyz, proj);
+			VectorSubtract(expand[j][i].xyz, proj, dir);
+			len = VectorLength(dir);
+			if (len > maxLength) {
+				maxLength = len;
+			}
+		}
+		if (maxLength < 0.1)
+		{
+			out.height--;
+			for ( i = 0 ; i < out.width ; i++ ) {
+				for (k = j; k < out.height; k++) {
+					expand[k][i] = expand[k+1][i];
+				}
+			}
+			j--;
+		}
+	}
+	// collapse the verts
+	out.verts = &expand[0][0];
+	for ( i = 1 ; i < out.height ; i++ ) {
+		memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) );
+	}
+
+	return CopyMesh(&out);
+}
+
+
+
+/*
+=================
+SubdivideMeshQuads
+=================
+*/
+mesh_t *SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable )
+{
+	int				i, j, k, w, h, maxsubdivisions, subdivisions;
+	vec3_t			dir;
+	float			length, maxLength, amount;
+	mesh_t			out;
+	bspDrawVert_t	expand[MAX_EXPANDED_AXIS][MAX_EXPANDED_AXIS];
+
+	out.width = in->width;
+	out.height = in->height;
+
+	for ( i = 0 ; i < in->width ; i++ ) {
+		for ( j = 0 ; j < in->height ; j++ ) {
+			expand[j][i] = in->verts[j*in->width+i];
+		}
+	}
+
+	if (maxsize > MAX_EXPANDED_AXIS)
+		Error("SubdivideMeshQuads: maxsize > MAX_EXPANDED_AXIS");
+
+	// horizontal subdivisions
+
+	maxsubdivisions = (maxsize - in->width) / (in->width - 1);
+
+	for ( w = 0, j = 0 ; w < in->width - 1; w++, j += subdivisions + 1) {
+		maxLength = 0;
+		for ( i = 0 ; i < out.height ; i++ ) {
+			VectorSubtract(expand[i][j+1].xyz, expand[i][j].xyz, dir);
+			length = VectorLength( dir );
+			if (length > maxLength) {
+				maxLength = length;
+			}
+		}
+		
+		subdivisions = (int) (maxLength / minLength);
+		if (subdivisions > maxsubdivisions)
+			subdivisions = maxsubdivisions;
+
+		widthtable[w] = subdivisions + 1;
+		if (subdivisions <= 0)
+			continue;
+
+		out.width += subdivisions;
+
+		for ( i = 0 ; i < out.height ; i++ ) {
+			for ( k = out.width - 1 ; k > j + subdivisions; k-- ) {
+				expand[i][k] = expand[i][k-subdivisions];
+			}
+			for (k = 1; k <= subdivisions; k++)
+			{
+				amount = (float) k / (subdivisions + 1);
+				LerpDrawVertAmount(&expand[i][j], &expand[i][j+subdivisions+1], amount, &expand[i][j+k]);
+			}
+		}
+	}
+
+	maxsubdivisions = (maxsize - in->height) / (in->height - 1);
+
+	for ( h = 0, j = 0 ; h < in->height - 1; h++, j += subdivisions + 1) {
+		maxLength = 0;
+		for ( i = 0 ; i < out.width ; i++ ) {
+			VectorSubtract(expand[j+1][i].xyz, expand[j][i].xyz, dir);
+			length = VectorLength( dir );
+			if (length  > maxLength) {
+				maxLength = length;
+			}
+		}
+		
+		subdivisions = (int) (maxLength / minLength);
+		if (subdivisions > maxsubdivisions)
+			subdivisions = maxsubdivisions;
+
+		heighttable[h] = subdivisions + 1;
+		if (subdivisions <= 0)
+			continue;
+
+		out.height += subdivisions;
+
+		for ( i = 0 ; i < out.width ; i++ ) {
+			for ( k = out.height - 1 ; k > j + subdivisions; k-- ) {
+				expand[k][i] = expand[k-subdivisions][i];
+			}
+			for (k = 1; k <= subdivisions; k++)
+			{
+				amount = (float) k / (subdivisions + 1);
+				LerpDrawVertAmount(&expand[j][i], &expand[j+subdivisions+1][i], amount, &expand[j+k][i]);
+			}
+		}
+	}
+
+	// collapse the verts
+	out.verts = &expand[0][0];
+	for ( i = 1 ; i < out.height ; i++ ) {
+		memmove( &out.verts[i*out.width], expand[i], out.width * sizeof(bspDrawVert_t) );
+	}
+
+	return CopyMesh(&out);
+}
diff --git a/tools/quake3/q3map2/model.c b/tools/quake3/q3map2/model.c
index 15192e2a..f303df75 100644
--- a/tools/quake3/q3map2/model.c
+++ b/tools/quake3/q3map2/model.c
@@ -1,706 +1,706 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define MODEL_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* 
-PicoPrintFunc()
-callback for picomodel.lib
-*/
-
-void PicoPrintFunc( int level, const char *str )
-{
-	if( str == NULL )
-		return;
-	switch( level )
-	{
-		case PICO_NORMAL:
-			Sys_Printf( "%s\n", str );
-			break;
-		
-		case PICO_VERBOSE:
-			Sys_FPrintf( SYS_VRB, "%s\n", str );
-			break;
-		
-		case PICO_WARNING:
-			Sys_Printf( "WARNING: %s\n", str );
-			break;
-		
-		case PICO_ERROR:
-			Sys_Printf( "ERROR: %s\n", str );
-			break;
-		
-		case PICO_FATAL:
-			Error( "ERROR: %s\n", str );
-			break;
-	}
-}
-
-
-
-/* 
-PicoLoadFileFunc()
-callback for picomodel.lib
-*/
-
-void PicoLoadFileFunc( char *name, byte **buffer, int *bufSize )
-{
-	*bufSize = vfsLoadFile( (const char*) name, (void**) buffer, 0 );
-}
-
-
-
-/*
-FindModel() - ydnar
-finds an existing picoModel and returns a pointer to the picoModel_t struct or NULL if not found
-*/
-
-picoModel_t *FindModel( char *name, int frame )
-{
-	int			i;
-	
-	
-	/* init */
-	if( numPicoModels <= 0 )
-		memset( picoModels, 0, sizeof( picoModels ) );
-	
-	/* dummy check */
-	if( name == NULL || name[ 0 ] == '\0' )
-		return NULL;
-	
-	/* search list */
-	for( i = 0; i < MAX_MODELS; i++ )
-	{
-		if( picoModels[ i ] != NULL &&
-			!strcmp( PicoGetModelName( picoModels[ i ] ), name ) &&
-			PicoGetModelFrameNum( picoModels[ i ] ) == frame )
-			return picoModels[ i ];
-	}
-	
-	/* no matching picoModel found */
-	return NULL;
-}
-
-
-
-/*
-LoadModel() - ydnar
-loads a picoModel and returns a pointer to the picoModel_t struct or NULL if not found
-*/
-
-picoModel_t *LoadModel( char *name, int frame )
-{
-	int				i;
-	picoModel_t		*model, **pm;
-	
-	
-	/* init */
-	if( numPicoModels <= 0 )
-		memset( picoModels, 0, sizeof( picoModels ) );
-	
-	/* dummy check */
-	if( name == NULL || name[ 0 ] == '\0' )
-		return NULL;
-	
-	/* try to find existing picoModel */
-	model = FindModel( name, frame );
-	if( model != NULL )
-		return model;
-	
-	/* none found, so find first non-null picoModel */
-	pm = NULL;
-	for( i = 0; i < MAX_MODELS; i++ )
-	{
-		if( picoModels[ i ] == NULL )
-		{
-			pm = &picoModels[ i ];
-			break;
-		}
-	}
-	
-	/* too many picoModels? */
-	if( pm == NULL )
-		Error( "MAX_MODELS (%d) exceeded, there are too many model files referenced by the map.", MAX_MODELS );
-	
-	/* attempt to parse model */
-	*pm = PicoLoadModel( (char*) name, frame );
-	
-	/* if loading failed, make a bogus model to silence the rest of the warnings */
-	if( *pm == NULL )
-	{
-		/* allocate a new model */
-		*pm = PicoNewModel();
-		if( *pm == NULL )
-			return NULL;
-		
-		/* set data */
-		PicoSetModelName( *pm, name );
-		PicoSetModelFrameNum( *pm, frame );
-	}
-	
-	/* debug code */
-	#if 0
-	{
-		int				numSurfaces, numVertexes;
-		picoSurface_t	*ps;
-		
-		
-		Sys_Printf( "Model %s\n", name );
-		numSurfaces = PicoGetModelNumSurfaces( *pm );
-		for( i = 0; i < numSurfaces; i++ )
-		{
-			ps = PicoGetModelSurface( *pm, i );
-			numVertexes = PicoGetSurfaceNumVertexes( ps );
-			Sys_Printf( "Surface %d has %d vertexes\n", i, numVertexes );
-		}
-	}
-	#endif
-	
-	/* set count */
-	if( *pm != NULL )
-		numPicoModels++;
-	
-	/* return the picoModel */
-	return *pm;
-}
-
-
-
-/*
-InsertModel() - ydnar
-adds a picomodel into the bsp
-*/
-
-void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale )
-{
-	int					i, j, k, s, numSurfaces;
-	m4x4_t				identity, nTransform;
-	picoModel_t			*model;
-	picoShader_t		*shader;
-	picoSurface_t		*surface;
-	shaderInfo_t		*si;
-	mapDrawSurface_t	*ds;
-	bspDrawVert_t		*dv;
-	char				*picoShaderName;
-	char				shaderName[ MAX_QPATH ];
-	picoVec_t			*xyz, *normal, *st;
-	byte				*color;
-	picoIndex_t			*indexes;
-	remap_t				*rm, *glob;
-	
-	
-	/* get model */
-	model = LoadModel( name, frame );
-	if( model == NULL )
-		return;
-	
-	/* handle null matrix */
-	if( transform == NULL )
-	{
-		m4x4_identity( identity );
-		transform = identity;
-	}
-	
-	/* hack: Stable-1_2 and trunk have differing row/column major matrix order
-	   this transpose is necessary with Stable-1_2
-	   uncomment the following line with old m4x4_t (non 1.3/spog_branch) code */
-	//%	m4x4_transpose( transform );
-	
-	/* create transform matrix for normals */
-	memcpy( nTransform, transform, sizeof( m4x4_t ) );
-	if( m4x4_invert( nTransform ) )
-		Sys_FPrintf( SYS_VRB, "WARNING: Can't invert model transform matrix, using transpose instead\n" );
-	m4x4_transpose( nTransform );
-	
-	/* fix bogus lightmap scale */
-	if( lightmapScale <= 0.0f )
-		lightmapScale = 1.0f;
-	
-	/* each surface on the model will become a new map drawsurface */
-	numSurfaces = PicoGetModelNumSurfaces( model );
-	//%	Sys_FPrintf( SYS_VRB, "Model %s has %d surfaces\n", name, numSurfaces );
-	for( s = 0; s < numSurfaces; s++ )
-	{
-		/* get surface */
-		surface = PicoGetModelSurface( model, s );
-		if( surface == NULL )
-			continue;
-		
-		/* only handle triangle surfaces initially (fixme: support patches) */
-		if( PicoGetSurfaceType( surface ) != PICO_TRIANGLES )
-			continue;
-		
-		/* fix the surface's normals */
-		PicoFixSurfaceNormals( surface );
-		
-		/* allocate a surface (ydnar: gs mods) */
-		ds = AllocDrawSurface( SURFACE_TRIANGLES );
-		ds->entityNum = eNum;
-		ds->castShadows = castShadows;
-		ds->recvShadows = recvShadows;
-		
-		/* get shader name */
-        shader = PicoGetSurfaceShader( surface );
-		if( shader == NULL )
-			picoShaderName = "";
-		else
-			picoShaderName = PicoGetShaderName( shader );
-		
-		/* handle shader remapping */
-		glob = NULL;
-		for( rm = remap; rm != NULL; rm = rm->next )
-		{
-			if( rm->from[ 0 ] == '*' && rm->from[ 1 ] == '\0' )
-				glob = rm;
-			else if( !Q_stricmp( picoShaderName, rm->from ) )
-			{
-				Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", picoShaderName, rm->to );
-				picoShaderName = rm->to;
-				glob = NULL;
-				break;
-			}
-		}
-		
-		if( glob != NULL )
-		{
-			Sys_FPrintf( SYS_VRB, "Globbing %s to %s\n", picoShaderName, glob->to );
-			picoShaderName = glob->to;
-		}
-		
-		/* shader renaming for sof2 */
-		if( renameModelShaders )
-		{
-			strcpy( shaderName, picoShaderName );
-			StripExtension( shaderName );
-			if( spawnFlags & 1 )
-				strcat( shaderName, "_RMG_BSP" );
-			else
-				strcat( shaderName, "_BSP" );
-			si = ShaderInfoForShader( shaderName );
-		}
-		else
-			si = ShaderInfoForShader( picoShaderName );
-		
-		/* set shader */
-		ds->shaderInfo = si;
-		
-		/* set lightmap scale */
-		ds->lightmapScale = lightmapScale;
-		
-		/* force to meta? */
-		if( si != NULL && si->forceMeta )
-			ds->type = SURFACE_FORCED_META;
-		
-		/* set particulars */
-		ds->numVerts = PicoGetSurfaceNumVertexes( surface );
-		ds->verts = safe_malloc( ds->numVerts * sizeof( ds->verts[ 0 ] ) );
-		memset( ds->verts, 0, ds->numVerts * sizeof( ds->verts[ 0 ] ) );
-		
-		ds->numIndexes = PicoGetSurfaceNumIndexes( surface );
-		ds->indexes = safe_malloc( ds->numIndexes * sizeof( ds->indexes[ 0 ] ) );
-		memset( ds->indexes, 0, ds->numIndexes * sizeof( ds->indexes[ 0 ] ) );
-		
-		/* copy vertexes */
-		for( i = 0; i < ds->numVerts; i++ )
-		{
-			/* get vertex */
-			dv = &ds->verts[ i ];
-			
-			/* xyz and normal */
-			xyz = PicoGetSurfaceXYZ( surface, i );
-			VectorCopy( xyz, dv->xyz );
-			m4x4_transform_point( transform, dv->xyz );
-			
-			normal = PicoGetSurfaceNormal( surface, i );
-			VectorCopy( normal, dv->normal );
-			m4x4_transform_normal( nTransform, dv->normal );
-			VectorNormalize( dv->normal, dv->normal );
-
-			/* ydnar: tek-fu celshading support for flat shaded shit */
-			if( flat )
-			{
-				dv->st[ 0 ] = si->stFlat[ 0 ];
-				dv->st[ 1 ] = si->stFlat[ 1 ];
-			}
-			
-			/* ydnar: gs mods: added support for explicit shader texcoord generation */
-			else if( si->tcGen )
-			{
-				/* project the texture */
-				dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], dv->xyz );
-				dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], dv->xyz );
-			}
-			
-			/* normal texture coordinates */
-			{
-				st = PicoGetSurfaceST( surface, 0, i );
-				dv->st[ 0 ] = st[ 0 ];
-				dv->st[ 1 ] = st[ 1 ];
-			}
-			
-			/* set lightmap/color bits */
-			color = PicoGetSurfaceColor( surface, 0, i );
-			for( j = 0; j < MAX_LIGHTMAPS; j++ )
-			{
-				dv->lightmap[ j ][ 0 ] = 0.0f;
-				dv->lightmap[ j ][ 1 ] = 0.0f;
-				dv->color[ j ][ 0 ] = color[ 0 ];
-				dv->color[ j ][ 1 ] = color[ 1 ];
-				dv->color[ j ][ 2 ] = color[ 2 ];
-				dv->color[ j ][ 3 ] = color[ 3 ];
-			}
-		}
-		
-		/* copy indexes */
-		indexes = PicoGetSurfaceIndexes( surface, 0 );
-		for( i = 0; i < ds->numIndexes; i++ )
-			ds->indexes[ i ] = indexes[ i ];
-		
-		/* set cel shader */
-		ds->celShader = celShader;
-		
-		/* finish surface */
-		FinishSurface( ds );
-		
-		/* ydnar: giant hack land: generate clipping brushes for model triangles */
-		if( si->clipModel || (spawnFlags & 2) )	/* 2nd bit */
-		{
-			vec3_t		points[ 3 ], backs[ 3 ];
-			vec4_t		plane, reverse, pa, pb, pc;
-			vec3_t		nadir;
-			
-			
-			/* temp hack */
-			if( (si->compileFlags & C_TRANSLUCENT) || !(si->compileFlags & C_SOLID) )
-				continue;
-			
-			/* overflow check */
-			if( (nummapplanes + 64) >= (MAX_MAP_PLANES >> 1) )
-				continue;
-			
-			/* walk triangle list */
-			for( i = 0; i < ds->numIndexes; i += 3 )
-			{
-				/* overflow hack */
-				if( (nummapplanes + 64) >= (MAX_MAP_PLANES >> 1) )
-				{
-					Sys_Printf( "WARNING: MAX_MAP_PLANES (%d) hit generating clip brushes for model %s.\n",
-						MAX_MAP_PLANES, name );
-					break;
-				}
-				
-				/* make points and back points */
-				for( j = 0; j < 3; j++ )
-				{
-					/* get vertex */
-					dv = &ds->verts[ ds->indexes[ i + j ] ];
-					
-					/* copy xyz */
-					VectorCopy( dv->xyz, points[ j ] );
-					VectorCopy( dv->xyz, backs[ j ] );
-					
-					/* find nearest axial to normal and push back points opposite */
-					/* note: this doesn't work as well as simply using the plane of the triangle, below */
-					for( k = 0; k < 3; k++ )
-					{
-						if( fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 1) % 3 ] ) &&
-							fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 2) % 3 ] ) )
-						{
-							backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
-							break;
-						}
-					}
-				}
-				
-				/* make plane for triangle */
-				if( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) )
-				{
-					/* regenerate back points */
-					for( j = 0; j < 3; j++ )
-					{
-						/* get vertex */
-						dv = &ds->verts[ ds->indexes[ i + j ] ];
-						
-						/* copy xyz */
-						VectorCopy( dv->xyz, backs[ j ] );
-						
-						/* find nearest axial to plane normal and push back points opposite */
-						for( k = 0; k < 3; k++ )
-						{
-							if( fabs( plane[ k ] ) > fabs( plane[ (k + 1) % 3 ] ) &&
-								fabs( plane[ k ] ) > fabs( plane[ (k + 2) % 3 ] ) )
-							{
-								backs[ j ][ k ] += plane[ k ] < 0.0f ? 64.0f : -64.0f;
-								break;
-							}
-						}
-					}
-					
-					/* make back plane */
-					VectorScale( plane, -1.0f, reverse );
-					reverse[ 3 ] = -(plane[ 3 ] - 1);
-					
-					/* make back pyramid point */
-					VectorCopy( points[ 0 ], nadir );
-					VectorAdd( nadir, points[ 1 ], nadir );
-					VectorAdd( nadir, points[ 2 ], nadir );
-					VectorScale( nadir, 0.3333333333333f, nadir );
-					VectorMA( nadir, -2.0f, plane, nadir );
-					
-					/* make 3 more planes */
-					//%	if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], nadir ) &&
-					//%		PlaneFromPoints( pb, points[ 1 ], points[ 0 ], nadir ) &&
-					//%		PlaneFromPoints( pc, points[ 0 ], points[ 2 ], nadir ) )
-					if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) &&
-						PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
-						PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
-					{
-						/* build a brush */
-						buildBrush = AllocBrush( 48 );
-						
-						buildBrush->entityNum = mapEntityNum;
-						buildBrush->original = buildBrush;
-						buildBrush->contentShader = si;
-						buildBrush->compileFlags = si->compileFlags;
-						buildBrush->contentFlags = si->contentFlags;
-						buildBrush->detail = qtrue;
-						
-						/* set up brush sides */
-						buildBrush->numsides = 5;
-						for( j = 0; j < buildBrush->numsides; j++ )
-							buildBrush->sides[ j ].shaderInfo = si;
-						buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
-						buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 1, &points[ 2 ] );
-						buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 1, &points[ 1 ] );
-						buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 1, &points[ 0 ] );
-						buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, points );
-						
-						/* add to entity */
-						if( CreateBrushWindings( buildBrush ) )
-						{
-							AddBrushBevels();
-							//%	EmitBrushes( buildBrush, NULL, NULL );
-							buildBrush->next = entities[ mapEntityNum ].brushes;
-							entities[ mapEntityNum ].brushes = buildBrush;
-							entities[ mapEntityNum ].numBrushes++;
-						}
-						else
-							free( buildBrush );
-					}
-				}
-			}
-		}
-	}
-}
-
-
-
-/*
-AddTriangleModels()
-adds misc_model surfaces to the bsp
-*/
-
-void AddTriangleModels( entity_t *e )
-{
-	int				num, frame, castShadows, recvShadows, spawnFlags;
-	entity_t		*e2;
-	const char		*targetName;
-	const char		*target, *model, *value;
-	char			shader[ MAX_QPATH ];
-	shaderInfo_t	*celShader;
-	float			temp, baseLightmapScale, lightmapScale;
-	vec3_t			origin, scale, angles;
-	m4x4_t			transform;
-	epair_t			*ep;
-	remap_t			*remap, *remap2;
-	char			*split;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- AddTriangleModels ---\n" );
-	
-	/* get current brush entity targetname */
-	if( e == entities )
-		targetName = "";
-	else
-	{
-		targetName = ValueForKey( e, "targetname" );
-	
-		/* misc_model entities target non-worldspawn brush model entities */
-		if( targetName[ 0 ] == '\0' )
-			return;
-	}
-	
-	/* get lightmap scale */
-	baseLightmapScale = FloatForKey( e, "_lightmapscale" );
-	if( baseLightmapScale <= 0.0f )
-		baseLightmapScale = 0.0f;
-	
-	/* walk the entity list */
-	for( num = 1; num < numEntities; num++ )
-	{
-		/* get e2 */
-		e2 = &entities[ num ];
-		
-		/* convert misc_models into raw geometry */
-		if( Q_stricmp( "misc_model", ValueForKey( e2, "classname" ) ) )
-			continue;
-
-		/* ydnar: added support for md3 models on non-worldspawn models */
-		target = ValueForKey( e2, "target" );
-		if( strcmp( target, targetName ) )
-			continue;
-		
-		/* get model name */
-		model = ValueForKey( e2, "model" );
-		if( model[ 0 ] == '\0' )
-		{
-			Sys_Printf( "WARNING: misc_model at %i %i %i without a model key\n",
-				(int) origin[ 0 ], (int) origin[ 1 ], (int) origin[ 2 ] );
-			continue;
-		}
-		
-		/* get model frame */
-		frame = IntForKey( e2, "_frame" );
-		
-		/* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
-		if( e == entities )
-		{
-			castShadows = WORLDSPAWN_CAST_SHADOWS;
-			recvShadows = WORLDSPAWN_RECV_SHADOWS;
-		}
-		
-		/* other entities don't cast any shadows, but recv worldspawn shadows */
-		else
-		{
-			castShadows = ENTITY_CAST_SHADOWS;
-			recvShadows = ENTITY_RECV_SHADOWS;
-		}
-		
-		/* get explicit shadow flags */
-		GetEntityShadowFlags( e2, e, &castShadows, &recvShadows );
-		
-		/* get spawnflags */
-		spawnFlags = IntForKey( e2, "spawnflags" );
-		
-		/* get origin */
-		GetVectorForKey( e2, "origin", origin );
-		VectorSubtract( origin, e->origin, origin );	/* offset by parent */
-		
-		/* get scale */
-		scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = 1.0f;
-		temp = FloatForKey( e2, "modelscale" );
-		if( temp != 0.0f )
-			scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = temp;
-		value = ValueForKey( e2, "modelscale_vec" );
-		if( value[ 0 ] != '\0' )
-			sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
-		
-		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
-		angles[ 0 ] = angles[ 1 ] = angles[ 2 ] = 0.0f;
-		angles[ 2 ] = FloatForKey( e2, "angle" );
-		value = ValueForKey( e2, "angles" );
-		if( value[ 0 ] != '\0' )
-			sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
-		
-		/* set transform matrix (thanks spog) */
-		m4x4_identity( transform );
-		m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
-		
-		/* get shader remappings */
-		remap = NULL;
-		for( ep = e2->epairs; ep != NULL; ep = ep->next )
-		{
-			/* look for keys prefixed with "_remap" */
-			if( ep->key != NULL && ep->value != NULL &&
-				ep->key[ 0 ] != '\0' && ep->value[ 0 ] != '\0' &&
-				!Q_strncasecmp( ep->key, "_remap", 6 ) )
-			{
-				/* create new remapping */
-				remap2 = remap;
-				remap = safe_malloc( sizeof( *remap ) );
-				remap->next = remap2;
-				strcpy( remap->from, ep->value );
-				
-				/* split the string */
-				split = strchr( remap->from, ';' );
-				if( split == NULL )
-				{
-					Sys_Printf( "WARNING: Shader _remap key found in misc_model without a ; character\n" );
-					free( remap );
-					remap = remap2;
-					continue;
-				}
-				
-				/* store the split */
-				*split = '\0';
-				strcpy( remap->to, (split + 1) );
-				
-				/* note it */
-				//%	Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", remap->from, remap->to );
-			}
-		}
-		
-		/* ydnar: cel shader support */
-		value = ValueForKey( e2, "_celshader" );
-		if( value[ 0 ] == '\0' )
-			value = ValueForKey( &entities[ 0 ], "_celshader" );
-		if( value[ 0 ] != '\0' )
-		{
-			sprintf( shader, "textures/%s", value );
-			celShader = ShaderInfoForShader( shader );
-		}
-		else
-			celShader = NULL;
-		
-		/* get lightmap scale */
-		lightmapScale = FloatForKey( e2, "_lightmapscale" );
-		if( lightmapScale <= 0.0f )
-			lightmapScale = baseLightmapScale;
-		
-		/* insert the model */
-		InsertModel( (char*) model, frame, transform, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags, lightmapScale );
-		
-		/* free shader remappings */
-		while( remap != NULL )
-		{
-			remap2 = remap->next;
-			free( remap );
-			remap = remap2;
-		}
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define MODEL_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* 
+PicoPrintFunc()
+callback for picomodel.lib
+*/
+
+void PicoPrintFunc( int level, const char *str )
+{
+	if( str == NULL )
+		return;
+	switch( level )
+	{
+		case PICO_NORMAL:
+			Sys_Printf( "%s\n", str );
+			break;
+		
+		case PICO_VERBOSE:
+			Sys_FPrintf( SYS_VRB, "%s\n", str );
+			break;
+		
+		case PICO_WARNING:
+			Sys_Printf( "WARNING: %s\n", str );
+			break;
+		
+		case PICO_ERROR:
+			Sys_Printf( "ERROR: %s\n", str );
+			break;
+		
+		case PICO_FATAL:
+			Error( "ERROR: %s\n", str );
+			break;
+	}
+}
+
+
+
+/* 
+PicoLoadFileFunc()
+callback for picomodel.lib
+*/
+
+void PicoLoadFileFunc( char *name, byte **buffer, int *bufSize )
+{
+	*bufSize = vfsLoadFile( (const char*) name, (void**) buffer, 0 );
+}
+
+
+
+/*
+FindModel() - ydnar
+finds an existing picoModel and returns a pointer to the picoModel_t struct or NULL if not found
+*/
+
+picoModel_t *FindModel( char *name, int frame )
+{
+	int			i;
+	
+	
+	/* init */
+	if( numPicoModels <= 0 )
+		memset( picoModels, 0, sizeof( picoModels ) );
+	
+	/* dummy check */
+	if( name == NULL || name[ 0 ] == '\0' )
+		return NULL;
+	
+	/* search list */
+	for( i = 0; i < MAX_MODELS; i++ )
+	{
+		if( picoModels[ i ] != NULL &&
+			!strcmp( PicoGetModelName( picoModels[ i ] ), name ) &&
+			PicoGetModelFrameNum( picoModels[ i ] ) == frame )
+			return picoModels[ i ];
+	}
+	
+	/* no matching picoModel found */
+	return NULL;
+}
+
+
+
+/*
+LoadModel() - ydnar
+loads a picoModel and returns a pointer to the picoModel_t struct or NULL if not found
+*/
+
+picoModel_t *LoadModel( char *name, int frame )
+{
+	int				i;
+	picoModel_t		*model, **pm;
+	
+	
+	/* init */
+	if( numPicoModels <= 0 )
+		memset( picoModels, 0, sizeof( picoModels ) );
+	
+	/* dummy check */
+	if( name == NULL || name[ 0 ] == '\0' )
+		return NULL;
+	
+	/* try to find existing picoModel */
+	model = FindModel( name, frame );
+	if( model != NULL )
+		return model;
+	
+	/* none found, so find first non-null picoModel */
+	pm = NULL;
+	for( i = 0; i < MAX_MODELS; i++ )
+	{
+		if( picoModels[ i ] == NULL )
+		{
+			pm = &picoModels[ i ];
+			break;
+		}
+	}
+	
+	/* too many picoModels? */
+	if( pm == NULL )
+		Error( "MAX_MODELS (%d) exceeded, there are too many model files referenced by the map.", MAX_MODELS );
+	
+	/* attempt to parse model */
+	*pm = PicoLoadModel( (char*) name, frame );
+	
+	/* if loading failed, make a bogus model to silence the rest of the warnings */
+	if( *pm == NULL )
+	{
+		/* allocate a new model */
+		*pm = PicoNewModel();
+		if( *pm == NULL )
+			return NULL;
+		
+		/* set data */
+		PicoSetModelName( *pm, name );
+		PicoSetModelFrameNum( *pm, frame );
+	}
+	
+	/* debug code */
+	#if 0
+	{
+		int				numSurfaces, numVertexes;
+		picoSurface_t	*ps;
+		
+		
+		Sys_Printf( "Model %s\n", name );
+		numSurfaces = PicoGetModelNumSurfaces( *pm );
+		for( i = 0; i < numSurfaces; i++ )
+		{
+			ps = PicoGetModelSurface( *pm, i );
+			numVertexes = PicoGetSurfaceNumVertexes( ps );
+			Sys_Printf( "Surface %d has %d vertexes\n", i, numVertexes );
+		}
+	}
+	#endif
+	
+	/* set count */
+	if( *pm != NULL )
+		numPicoModels++;
+	
+	/* return the picoModel */
+	return *pm;
+}
+
+
+
+/*
+InsertModel() - ydnar
+adds a picomodel into the bsp
+*/
+
+void InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale )
+{
+	int					i, j, k, s, numSurfaces;
+	m4x4_t				identity, nTransform;
+	picoModel_t			*model;
+	picoShader_t		*shader;
+	picoSurface_t		*surface;
+	shaderInfo_t		*si;
+	mapDrawSurface_t	*ds;
+	bspDrawVert_t		*dv;
+	char				*picoShaderName;
+	char				shaderName[ MAX_QPATH ];
+	picoVec_t			*xyz, *normal, *st;
+	byte				*color;
+	picoIndex_t			*indexes;
+	remap_t				*rm, *glob;
+	
+	
+	/* get model */
+	model = LoadModel( name, frame );
+	if( model == NULL )
+		return;
+	
+	/* handle null matrix */
+	if( transform == NULL )
+	{
+		m4x4_identity( identity );
+		transform = identity;
+	}
+	
+	/* hack: Stable-1_2 and trunk have differing row/column major matrix order
+	   this transpose is necessary with Stable-1_2
+	   uncomment the following line with old m4x4_t (non 1.3/spog_branch) code */
+	//%	m4x4_transpose( transform );
+	
+	/* create transform matrix for normals */
+	memcpy( nTransform, transform, sizeof( m4x4_t ) );
+	if( m4x4_invert( nTransform ) )
+		Sys_FPrintf( SYS_VRB, "WARNING: Can't invert model transform matrix, using transpose instead\n" );
+	m4x4_transpose( nTransform );
+	
+	/* fix bogus lightmap scale */
+	if( lightmapScale <= 0.0f )
+		lightmapScale = 1.0f;
+	
+	/* each surface on the model will become a new map drawsurface */
+	numSurfaces = PicoGetModelNumSurfaces( model );
+	//%	Sys_FPrintf( SYS_VRB, "Model %s has %d surfaces\n", name, numSurfaces );
+	for( s = 0; s < numSurfaces; s++ )
+	{
+		/* get surface */
+		surface = PicoGetModelSurface( model, s );
+		if( surface == NULL )
+			continue;
+		
+		/* only handle triangle surfaces initially (fixme: support patches) */
+		if( PicoGetSurfaceType( surface ) != PICO_TRIANGLES )
+			continue;
+		
+		/* fix the surface's normals */
+		PicoFixSurfaceNormals( surface );
+		
+		/* allocate a surface (ydnar: gs mods) */
+		ds = AllocDrawSurface( SURFACE_TRIANGLES );
+		ds->entityNum = eNum;
+		ds->castShadows = castShadows;
+		ds->recvShadows = recvShadows;
+		
+		/* get shader name */
+        shader = PicoGetSurfaceShader( surface );
+		if( shader == NULL )
+			picoShaderName = "";
+		else
+			picoShaderName = PicoGetShaderName( shader );
+		
+		/* handle shader remapping */
+		glob = NULL;
+		for( rm = remap; rm != NULL; rm = rm->next )
+		{
+			if( rm->from[ 0 ] == '*' && rm->from[ 1 ] == '\0' )
+				glob = rm;
+			else if( !Q_stricmp( picoShaderName, rm->from ) )
+			{
+				Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", picoShaderName, rm->to );
+				picoShaderName = rm->to;
+				glob = NULL;
+				break;
+			}
+		}
+		
+		if( glob != NULL )
+		{
+			Sys_FPrintf( SYS_VRB, "Globbing %s to %s\n", picoShaderName, glob->to );
+			picoShaderName = glob->to;
+		}
+		
+		/* shader renaming for sof2 */
+		if( renameModelShaders )
+		{
+			strcpy( shaderName, picoShaderName );
+			StripExtension( shaderName );
+			if( spawnFlags & 1 )
+				strcat( shaderName, "_RMG_BSP" );
+			else
+				strcat( shaderName, "_BSP" );
+			si = ShaderInfoForShader( shaderName );
+		}
+		else
+			si = ShaderInfoForShader( picoShaderName );
+		
+		/* set shader */
+		ds->shaderInfo = si;
+		
+		/* set lightmap scale */
+		ds->lightmapScale = lightmapScale;
+		
+		/* force to meta? */
+		if( si != NULL && si->forceMeta )
+			ds->type = SURFACE_FORCED_META;
+		
+		/* set particulars */
+		ds->numVerts = PicoGetSurfaceNumVertexes( surface );
+		ds->verts = safe_malloc( ds->numVerts * sizeof( ds->verts[ 0 ] ) );
+		memset( ds->verts, 0, ds->numVerts * sizeof( ds->verts[ 0 ] ) );
+		
+		ds->numIndexes = PicoGetSurfaceNumIndexes( surface );
+		ds->indexes = safe_malloc( ds->numIndexes * sizeof( ds->indexes[ 0 ] ) );
+		memset( ds->indexes, 0, ds->numIndexes * sizeof( ds->indexes[ 0 ] ) );
+		
+		/* copy vertexes */
+		for( i = 0; i < ds->numVerts; i++ )
+		{
+			/* get vertex */
+			dv = &ds->verts[ i ];
+			
+			/* xyz and normal */
+			xyz = PicoGetSurfaceXYZ( surface, i );
+			VectorCopy( xyz, dv->xyz );
+			m4x4_transform_point( transform, dv->xyz );
+			
+			normal = PicoGetSurfaceNormal( surface, i );
+			VectorCopy( normal, dv->normal );
+			m4x4_transform_normal( nTransform, dv->normal );
+			VectorNormalize( dv->normal, dv->normal );
+
+			/* ydnar: tek-fu celshading support for flat shaded shit */
+			if( flat )
+			{
+				dv->st[ 0 ] = si->stFlat[ 0 ];
+				dv->st[ 1 ] = si->stFlat[ 1 ];
+			}
+			
+			/* ydnar: gs mods: added support for explicit shader texcoord generation */
+			else if( si->tcGen )
+			{
+				/* project the texture */
+				dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], dv->xyz );
+				dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], dv->xyz );
+			}
+			
+			/* normal texture coordinates */
+			{
+				st = PicoGetSurfaceST( surface, 0, i );
+				dv->st[ 0 ] = st[ 0 ];
+				dv->st[ 1 ] = st[ 1 ];
+			}
+			
+			/* set lightmap/color bits */
+			color = PicoGetSurfaceColor( surface, 0, i );
+			for( j = 0; j < MAX_LIGHTMAPS; j++ )
+			{
+				dv->lightmap[ j ][ 0 ] = 0.0f;
+				dv->lightmap[ j ][ 1 ] = 0.0f;
+				dv->color[ j ][ 0 ] = color[ 0 ];
+				dv->color[ j ][ 1 ] = color[ 1 ];
+				dv->color[ j ][ 2 ] = color[ 2 ];
+				dv->color[ j ][ 3 ] = color[ 3 ];
+			}
+		}
+		
+		/* copy indexes */
+		indexes = PicoGetSurfaceIndexes( surface, 0 );
+		for( i = 0; i < ds->numIndexes; i++ )
+			ds->indexes[ i ] = indexes[ i ];
+		
+		/* set cel shader */
+		ds->celShader = celShader;
+		
+		/* finish surface */
+		FinishSurface( ds );
+		
+		/* ydnar: giant hack land: generate clipping brushes for model triangles */
+		if( si->clipModel || (spawnFlags & 2) )	/* 2nd bit */
+		{
+			vec3_t		points[ 3 ], backs[ 3 ];
+			vec4_t		plane, reverse, pa, pb, pc;
+			vec3_t		nadir;
+			
+			
+			/* temp hack */
+			if( (si->compileFlags & C_TRANSLUCENT) || !(si->compileFlags & C_SOLID) )
+				continue;
+			
+			/* overflow check */
+			if( (nummapplanes + 64) >= (MAX_MAP_PLANES >> 1) )
+				continue;
+			
+			/* walk triangle list */
+			for( i = 0; i < ds->numIndexes; i += 3 )
+			{
+				/* overflow hack */
+				if( (nummapplanes + 64) >= (MAX_MAP_PLANES >> 1) )
+				{
+					Sys_Printf( "WARNING: MAX_MAP_PLANES (%d) hit generating clip brushes for model %s.\n",
+						MAX_MAP_PLANES, name );
+					break;
+				}
+				
+				/* make points and back points */
+				for( j = 0; j < 3; j++ )
+				{
+					/* get vertex */
+					dv = &ds->verts[ ds->indexes[ i + j ] ];
+					
+					/* copy xyz */
+					VectorCopy( dv->xyz, points[ j ] );
+					VectorCopy( dv->xyz, backs[ j ] );
+					
+					/* find nearest axial to normal and push back points opposite */
+					/* note: this doesn't work as well as simply using the plane of the triangle, below */
+					for( k = 0; k < 3; k++ )
+					{
+						if( fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 1) % 3 ] ) &&
+							fabs( dv->normal[ k ] ) > fabs( dv->normal[ (k + 2) % 3 ] ) )
+						{
+							backs[ j ][ k ] += dv->normal[ k ] < 0.0f ? 64.0f : -64.0f;
+							break;
+						}
+					}
+				}
+				
+				/* make plane for triangle */
+				if( PlaneFromPoints( plane, points[ 0 ], points[ 1 ], points[ 2 ] ) )
+				{
+					/* regenerate back points */
+					for( j = 0; j < 3; j++ )
+					{
+						/* get vertex */
+						dv = &ds->verts[ ds->indexes[ i + j ] ];
+						
+						/* copy xyz */
+						VectorCopy( dv->xyz, backs[ j ] );
+						
+						/* find nearest axial to plane normal and push back points opposite */
+						for( k = 0; k < 3; k++ )
+						{
+							if( fabs( plane[ k ] ) > fabs( plane[ (k + 1) % 3 ] ) &&
+								fabs( plane[ k ] ) > fabs( plane[ (k + 2) % 3 ] ) )
+							{
+								backs[ j ][ k ] += plane[ k ] < 0.0f ? 64.0f : -64.0f;
+								break;
+							}
+						}
+					}
+					
+					/* make back plane */
+					VectorScale( plane, -1.0f, reverse );
+					reverse[ 3 ] = -(plane[ 3 ] - 1);
+					
+					/* make back pyramid point */
+					VectorCopy( points[ 0 ], nadir );
+					VectorAdd( nadir, points[ 1 ], nadir );
+					VectorAdd( nadir, points[ 2 ], nadir );
+					VectorScale( nadir, 0.3333333333333f, nadir );
+					VectorMA( nadir, -2.0f, plane, nadir );
+					
+					/* make 3 more planes */
+					//%	if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], nadir ) &&
+					//%		PlaneFromPoints( pb, points[ 1 ], points[ 0 ], nadir ) &&
+					//%		PlaneFromPoints( pc, points[ 0 ], points[ 2 ], nadir ) )
+					if( PlaneFromPoints( pa, points[ 2 ], points[ 1 ], backs[ 1 ] ) &&
+						PlaneFromPoints( pb, points[ 1 ], points[ 0 ], backs[ 0 ] ) &&
+						PlaneFromPoints( pc, points[ 0 ], points[ 2 ], backs[ 2 ] ) )
+					{
+						/* build a brush */
+						buildBrush = AllocBrush( 48 );
+						
+						buildBrush->entityNum = mapEntityNum;
+						buildBrush->original = buildBrush;
+						buildBrush->contentShader = si;
+						buildBrush->compileFlags = si->compileFlags;
+						buildBrush->contentFlags = si->contentFlags;
+						buildBrush->detail = qtrue;
+						
+						/* set up brush sides */
+						buildBrush->numsides = 5;
+						for( j = 0; j < buildBrush->numsides; j++ )
+							buildBrush->sides[ j ].shaderInfo = si;
+						buildBrush->sides[ 0 ].planenum = FindFloatPlane( plane, plane[ 3 ], 3, points );
+						buildBrush->sides[ 1 ].planenum = FindFloatPlane( pa, pa[ 3 ], 1, &points[ 2 ] );
+						buildBrush->sides[ 2 ].planenum = FindFloatPlane( pb, pb[ 3 ], 1, &points[ 1 ] );
+						buildBrush->sides[ 3 ].planenum = FindFloatPlane( pc, pc[ 3 ], 1, &points[ 0 ] );
+						buildBrush->sides[ 4 ].planenum = FindFloatPlane( reverse, reverse[ 3 ], 3, points );
+						
+						/* add to entity */
+						if( CreateBrushWindings( buildBrush ) )
+						{
+							AddBrushBevels();
+							//%	EmitBrushes( buildBrush, NULL, NULL );
+							buildBrush->next = entities[ mapEntityNum ].brushes;
+							entities[ mapEntityNum ].brushes = buildBrush;
+							entities[ mapEntityNum ].numBrushes++;
+						}
+						else
+							free( buildBrush );
+					}
+				}
+			}
+		}
+	}
+}
+
+
+
+/*
+AddTriangleModels()
+adds misc_model surfaces to the bsp
+*/
+
+void AddTriangleModels( entity_t *e )
+{
+	int				num, frame, castShadows, recvShadows, spawnFlags;
+	entity_t		*e2;
+	const char		*targetName;
+	const char		*target, *model, *value;
+	char			shader[ MAX_QPATH ];
+	shaderInfo_t	*celShader;
+	float			temp, baseLightmapScale, lightmapScale;
+	vec3_t			origin, scale, angles;
+	m4x4_t			transform;
+	epair_t			*ep;
+	remap_t			*remap, *remap2;
+	char			*split;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- AddTriangleModels ---\n" );
+	
+	/* get current brush entity targetname */
+	if( e == entities )
+		targetName = "";
+	else
+	{
+		targetName = ValueForKey( e, "targetname" );
+	
+		/* misc_model entities target non-worldspawn brush model entities */
+		if( targetName[ 0 ] == '\0' )
+			return;
+	}
+	
+	/* get lightmap scale */
+	baseLightmapScale = FloatForKey( e, "_lightmapscale" );
+	if( baseLightmapScale <= 0.0f )
+		baseLightmapScale = 0.0f;
+	
+	/* walk the entity list */
+	for( num = 1; num < numEntities; num++ )
+	{
+		/* get e2 */
+		e2 = &entities[ num ];
+		
+		/* convert misc_models into raw geometry */
+		if( Q_stricmp( "misc_model", ValueForKey( e2, "classname" ) ) )
+			continue;
+
+		/* ydnar: added support for md3 models on non-worldspawn models */
+		target = ValueForKey( e2, "target" );
+		if( strcmp( target, targetName ) )
+			continue;
+		
+		/* get model name */
+		model = ValueForKey( e2, "model" );
+		if( model[ 0 ] == '\0' )
+		{
+			Sys_Printf( "WARNING: misc_model at %i %i %i without a model key\n",
+				(int) origin[ 0 ], (int) origin[ 1 ], (int) origin[ 2 ] );
+			continue;
+		}
+		
+		/* get model frame */
+		frame = IntForKey( e2, "_frame" );
+		
+		/* worldspawn (and func_groups) default to cast/recv shadows in worldspawn group */
+		if( e == entities )
+		{
+			castShadows = WORLDSPAWN_CAST_SHADOWS;
+			recvShadows = WORLDSPAWN_RECV_SHADOWS;
+		}
+		
+		/* other entities don't cast any shadows, but recv worldspawn shadows */
+		else
+		{
+			castShadows = ENTITY_CAST_SHADOWS;
+			recvShadows = ENTITY_RECV_SHADOWS;
+		}
+		
+		/* get explicit shadow flags */
+		GetEntityShadowFlags( e2, e, &castShadows, &recvShadows );
+		
+		/* get spawnflags */
+		spawnFlags = IntForKey( e2, "spawnflags" );
+		
+		/* get origin */
+		GetVectorForKey( e2, "origin", origin );
+		VectorSubtract( origin, e->origin, origin );	/* offset by parent */
+		
+		/* get scale */
+		scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = 1.0f;
+		temp = FloatForKey( e2, "modelscale" );
+		if( temp != 0.0f )
+			scale[ 0 ] = scale[ 1 ] = scale[ 2 ] = temp;
+		value = ValueForKey( e2, "modelscale_vec" );
+		if( value[ 0 ] != '\0' )
+			sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
+		
+		/* get "angle" (yaw) or "angles" (pitch yaw roll) */
+		angles[ 0 ] = angles[ 1 ] = angles[ 2 ] = 0.0f;
+		angles[ 2 ] = FloatForKey( e2, "angle" );
+		value = ValueForKey( e2, "angles" );
+		if( value[ 0 ] != '\0' )
+			sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
+		
+		/* set transform matrix (thanks spog) */
+		m4x4_identity( transform );
+		m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
+		
+		/* get shader remappings */
+		remap = NULL;
+		for( ep = e2->epairs; ep != NULL; ep = ep->next )
+		{
+			/* look for keys prefixed with "_remap" */
+			if( ep->key != NULL && ep->value != NULL &&
+				ep->key[ 0 ] != '\0' && ep->value[ 0 ] != '\0' &&
+				!Q_strncasecmp( ep->key, "_remap", 6 ) )
+			{
+				/* create new remapping */
+				remap2 = remap;
+				remap = safe_malloc( sizeof( *remap ) );
+				remap->next = remap2;
+				strcpy( remap->from, ep->value );
+				
+				/* split the string */
+				split = strchr( remap->from, ';' );
+				if( split == NULL )
+				{
+					Sys_Printf( "WARNING: Shader _remap key found in misc_model without a ; character\n" );
+					free( remap );
+					remap = remap2;
+					continue;
+				}
+				
+				/* store the split */
+				*split = '\0';
+				strcpy( remap->to, (split + 1) );
+				
+				/* note it */
+				//%	Sys_FPrintf( SYS_VRB, "Remapping %s to %s\n", remap->from, remap->to );
+			}
+		}
+		
+		/* ydnar: cel shader support */
+		value = ValueForKey( e2, "_celshader" );
+		if( value[ 0 ] == '\0' )
+			value = ValueForKey( &entities[ 0 ], "_celshader" );
+		if( value[ 0 ] != '\0' )
+		{
+			sprintf( shader, "textures/%s", value );
+			celShader = ShaderInfoForShader( shader );
+		}
+		else
+			celShader = NULL;
+		
+		/* get lightmap scale */
+		lightmapScale = FloatForKey( e2, "_lightmapscale" );
+		if( lightmapScale <= 0.0f )
+			lightmapScale = baseLightmapScale;
+		
+		/* insert the model */
+		InsertModel( (char*) model, frame, transform, remap, celShader, mapEntityNum, castShadows, recvShadows, spawnFlags, lightmapScale );
+		
+		/* free shader remappings */
+		while( remap != NULL )
+		{
+			remap2 = remap->next;
+			free( remap );
+			remap = remap2;
+		}
+	}
+}
diff --git a/tools/quake3/q3map2/patch.c b/tools/quake3/q3map2/patch.c
index a9542004..a1134db3 100644
--- a/tools/quake3/q3map2/patch.c
+++ b/tools/quake3/q3map2/patch.c
@@ -1,524 +1,524 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define PATCH_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-ExpandLongestCurve() - ydnar
-finds length of quadratic curve specified and determines if length is longer than the supplied max
-*/
-
-#define APPROX_SUBDIVISION	8
-
-static void ExpandLongestCurve( float *longestCurve, vec3_t a, vec3_t b, vec3_t c )
-{
-	int		i;
-	float	t, len;
-	vec3_t	ab, bc, ac, pt, last, delta;
-	
-	
-	/* calc vectors */
-	VectorSubtract( b, a, ab );
-	if( VectorNormalize( ab, ab ) < 0.125f )
-		return;
-	VectorSubtract( c, b, bc );
-	if( VectorNormalize( bc, bc ) < 0.125f )
-		return;
-	VectorSubtract( c, a, ac );
-	if( VectorNormalize( ac, ac ) < 0.125f )
-		return;
-	
-	/* if all 3 vectors are the same direction, then this edge is linear, so we ignore it */
-	if( DotProduct( ab, bc ) > 0.99f && DotProduct( ab, ac ) > 0.99f )
-		return;
-	
-	/* recalculate vectors */
-	VectorSubtract( b, a, ab );
-	VectorSubtract( c, b, bc );
-	
-	/* determine length */
-	VectorCopy( a, last );
-	for( i = 0, len = 0.0f, t = 0.0f; i < APPROX_SUBDIVISION; i++, t += (1.0f / APPROX_SUBDIVISION) )
-	{
-		/* calculate delta */
-		delta[ 0 ] = ((1.0f - t) * ab[ 0 ]) + (t * bc[ 0 ]);
-		delta[ 1 ] = ((1.0f - t) * ab[ 1 ]) + (t * bc[ 1 ]);
-		delta[ 2 ] = ((1.0f - t) * ab[ 2 ]) + (t * bc[ 2 ]);
-		
-		/* add to first point and calculate pt-pt delta */
-		VectorAdd( a, delta, pt );
-		VectorSubtract( pt, last, delta );
-		
-		/* add it to length and store last point */
-		len += VectorLength( delta );
-		VectorCopy( pt, last );
-	}
-	
-	/* longer? */
-	if( len > *longestCurve )
-		*longestCurve = len;
-}
-
-
-
-/*
-ExpandMaxIterations() - ydnar
-determines how many iterations a quadratic curve needs to be subdivided with to fit the specified error
-*/
-
-static void ExpandMaxIterations( int *maxIterations, int maxError, vec3_t a, vec3_t b, vec3_t c )
-{
-	int				i, j;
-	vec3_t			prev, next, mid, delta, delta2;
-	float			len, len2;
-	int				numPoints, iterations;
-	vec3_t			points[ MAX_EXPANDED_AXIS ];
-	
-	
-	/* initial setup */
-	numPoints = 3;
-	VectorCopy( a, points[ 0 ] );
-	VectorCopy( b, points[ 1 ] );
-	VectorCopy( c, points[ 2 ] );
-
-	/* subdivide */
-	for( i = 0; i + 2 < numPoints; i += 2 )
-	{
-		/* check subdivision limit */
-		if( numPoints + 2 >= MAX_EXPANDED_AXIS )
-			break;
-		
-		/* calculate new curve deltas */
-		for( j = 0; j < 3; j++ )
-		{
-			prev[ j ] = points[ i + 1 ][ j ] - points[ i ][ j ]; 
-			next[ j ] = points[ i + 2 ][ j ] - points[ i + 1 ][ j ]; 
-			mid[ j ] = (points[ i ][ j ] + points[ i + 1 ][ j ] * 2.0f + points[ i + 2 ][ j ]) * 0.25f;
-		}
-		
-		/* see if this midpoint is off far enough to subdivide */
-		VectorSubtract( points[ i + 1 ], mid, delta );
-		len = VectorLength( delta );
-		if( len < maxError )
-			continue;
-		
-		/* subdivide */
-		numPoints += 2;
-		
-		/* create new points */
-		for( j = 0; j < 3; j++ )
-		{
-			prev[ j ] = 0.5f * (points[ i ][ j ] + points[ i + 1 ][ j ]);
-			next[ j ] = 0.5f * (points[ i + 1 ][ j ] + points[ i + 2 ][ j ]);
-			mid[ j ] = 0.5f * (prev[ j ] + next[ j ]);
-		}
-		
-		/* push points out */
-		for( j = numPoints - 1; j > i + 3; j-- )
-			VectorCopy( points[ j - 2 ], points[ j ] );
-		
-		/* insert new points */
-		VectorCopy( prev, points[ i + 1 ] );
-		VectorCopy( mid, points[ i + 2 ] );
-		VectorCopy( next, points[ i + 3 ] );
-
-		/* back up and recheck this set again, it may need more subdivision */
-		i -= 2;
-	}
-	
-	/* put the line on the curve */
-	for( i = 1; i < numPoints; i += 2 )
-	{
-		for( j = 0; j < 3; j++ )
-		{
-			prev[ j ] = 0.5f * (points[ i ][ j ] + points[ i + 1 ][ j ] );
-			next[ j ] = 0.5f * (points[ i ][ j ] + points[ i - 1 ][ j ] );
-			points[ i ][ j ] = 0.5f * (prev[ j ] + next[ j ]);
-		}
-	}
-	
-	/* eliminate linear sections */
-	for( i = 0; i + 2 < numPoints; i++ )
-	{
-		/* create vectors */
-		VectorSubtract( points[ i + 1 ], points[ i ], delta );
-		len = VectorNormalize( delta, delta );
-		VectorSubtract( points[ i + 2 ], points[ i + 1 ], delta2 );
-		len2 = VectorNormalize( delta2, delta2 );
-		
-		/* if either edge is degenerate, then eliminate it */
-		if( len < 0.0625f || len2 < 0.0625f || DotProduct( delta, delta2 ) >= 1.0f )
-		{
-			for( j = i + 1; j + 1 < numPoints; j++ )
-				VectorCopy( points[ j + 1 ], points[ j ] );
-			numPoints--;
-			continue;
-		}
-	}
-	
-	/* the number of iterations is 2^(points - 1) - 1 */
-	numPoints >>= 1;
-	iterations = 0;
-	while( numPoints > 1 )
-	{
-		numPoints >>= 1;
-		iterations++;
-	}
-	
-	/* more? */
-	if( iterations > *maxIterations )
-		*maxIterations = iterations;
-}
-
-
-
-/*
-ParsePatch()
-creates a mapDrawSurface_t from the patch text
-*/
-
-void ParsePatch( qboolean onlyLights )
-{
-	vec_t			info[ 5 ];
-	int				i, j, k;
-	parseMesh_t		*pm;
-	char			texture[ MAX_QPATH ];
-	char			shader[ MAX_QPATH ];
-	mesh_t			m;
-	bspDrawVert_t	*verts;
-	epair_t			*ep;
-	vec4_t			delta, delta2, delta3;
-	qboolean		degenerate;
-	float			longestCurve;
-	int				maxIterations;
-	
-	
-	MatchToken( "{" );
-	
-	/* get texture */
-	GetToken( qtrue );
-	strcpy( texture, token );
-	
-	Parse1DMatrix( 5, info );
-	m.width = info[0];
-	m.height = info[1];
-	m.verts = verts = safe_malloc( m.width * m.height * sizeof( m.verts[0] ) );
-	
-	if( m.width < 0 || m.width > MAX_PATCH_SIZE || m.height < 0 || m.height > MAX_PATCH_SIZE )
-		Error( "ParsePatch: bad size" );
-	
-	MatchToken( "(" );
-	for( j = 0; j < m.width ; j++ )
-	{
-		MatchToken( "(" );
-		for( i = 0; i < m.height ; i++ )
-		{
-			Parse1DMatrix( 5, verts[ i * m.width + j ].xyz );
-			
-			/* ydnar: fix colors */
-			for( k = 0; k < MAX_LIGHTMAPS; k++ )
-			{
-				verts[ i * m.width + j ].color[ k ][ 0 ] = 255;
-				verts[ i * m.width + j ].color[ k ][ 1 ] = 255;
-				verts[ i * m.width + j ].color[ k ][ 2 ] = 255;
-				verts[ i * m.width + j ].color[ k ][ 3 ] = 255;
-			}
-		}
-		MatchToken( ")" );
-	}
-	MatchToken( ")" );
-
-	// if brush primitives format, we may have some epairs to ignore here
-	GetToken(qtrue);
-	if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
-	{
-		// NOTE: we leak that!
-		ep = ParseEPair();
-	}
-	else
-		UnGetToken();
-
-	MatchToken( "}" );
-	MatchToken( "}" );
-	
-	/* short circuit */
-	if( noCurveBrushes || onlyLights )
-		return;
-	
-	
-	/* ydnar: delete and warn about degenerate patches */
-	j = (m.width * m.height);
-	VectorClear( delta );
-	delta[ 3 ] = 0;
-	degenerate = qtrue;
-	
-	/* find first valid vector */
-	for( i = 1; i < j && delta[ 3 ] == 0; i++ )
-	{
-		VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta );
-		delta[ 3 ] = VectorNormalize( delta, delta );
-	}
-	
-	/* secondary degenerate test */
-	if( delta[ 3 ] == 0 )
-		degenerate = qtrue;
-	else
-	{
-		/* if all vectors match this or are zero, then this is a degenerate patch */
-		for( i = 1; i < j && degenerate == qtrue; i++ )
-		{
-			VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta2 );
-			delta2[ 3 ] = VectorNormalize( delta2, delta2 );
-			if( delta2[ 3 ] != 0 )
-			{
-				/* create inverse vector */
-				VectorCopy( delta2, delta3 );
-				delta3[ 3 ] = delta2[ 3 ];
-				VectorInverse( delta3 );
-				
-				/* compare */
-				if( VectorCompare( delta, delta2 ) == qfalse && VectorCompare( delta, delta3 ) == qfalse )
-					degenerate = qfalse;
-			}
-		}
-	}
-	
-	/* warn and select degenerate patch */
-	if( degenerate )
-	{
-		xml_Select( "degenerate patch", mapEnt->mapEntityNum, entitySourceBrushes, qfalse );
-		free( m.verts );
-		return;
-	}
-	
-	/* find longest curve on the mesh */
-	longestCurve = 0.0f;
-	maxIterations = 0;
-	for( j = 0; j + 2 < m.width; j += 2 )
-	{
-		for( i = 0; i + 2 < m.height; i += 2 )
-		{
-			ExpandLongestCurve( &longestCurve, verts[ i * m.width + j ].xyz, verts[ i * m.width + (j + 1) ].xyz, verts[ i * m.width + (j + 2) ].xyz );		/* row */
-			ExpandLongestCurve( &longestCurve, verts[ i * m.width + j ].xyz, verts[ (i + 1) * m.width + j ].xyz, verts[ (i + 2) * m.width + j ].xyz );		/* col */
-			ExpandMaxIterations( &maxIterations, patchSubdivisions, verts[ i * m.width + j ].xyz, verts[ i * m.width + (j + 1) ].xyz, verts[ i * m.width + (j + 2) ].xyz );		/* row */
-			ExpandMaxIterations( &maxIterations, patchSubdivisions, verts[ i * m.width + j ].xyz, verts[ (i + 1) * m.width + j ].xyz, verts[ (i + 2) * m.width + j ].xyz  );	/* col */
-		}
-	}
-	
-	/* allocate patch mesh */
-	pm = safe_malloc( sizeof( *pm ) );
-	memset( pm, 0, sizeof( *pm ) );
-	
-	/* ydnar: add entity/brush numbering */
-	pm->entityNum = mapEnt->mapEntityNum;
-	pm->brushNum = entitySourceBrushes;
-	
-	/* set shader */
-	sprintf( shader, "textures/%s", texture );
-	pm->shaderInfo = ShaderInfoForShader( shader );
-	
-	/* set mesh */
-	pm->mesh = m;
-	
-	/* set longest curve */
-	pm->longestCurve = longestCurve;
-	pm->maxIterations = maxIterations;
-	
-	/* link to the entity */
-	pm->next = mapEnt->patches;
-	mapEnt->patches = pm;
-}
-
-
-
-/*
-GrowGroup_r()
-recursively adds patches to a lod group
-*/
-
-static void GrowGroup_r( parseMesh_t *pm, int patchNum, int patchCount, parseMesh_t **meshes, byte *bordering, byte *group )
-{
-	int			i;
-	const byte	*row;
-	
-	
-	/* early out check */
-	if( group[ patchNum ] )
-		return;
-	
-	
-	/* set it */
-	group[ patchNum ] = 1;
-	row = bordering + patchNum * patchCount;
-	
-	/* check maximums */
-	if( meshes[ patchNum ]->longestCurve > pm->longestCurve )
-		pm->longestCurve = meshes[ patchNum ]->longestCurve;
-	if( meshes[ patchNum ]->maxIterations > pm->maxIterations )
-		pm->maxIterations = meshes[ patchNum ]->maxIterations;
-	
-	/* walk other patches */
-	for( i = 0; i < patchCount; i++ )
-	{
-		if( row[ i ] )
-			GrowGroup_r( pm, i, patchCount, meshes, bordering, group );
-	}
-}
-
-
-/*
-PatchMapDrawSurfs()
-any patches that share an edge need to choose their
-level of detail as a unit, otherwise the edges would
-pull apart.
-*/
-
-void PatchMapDrawSurfs( entity_t *e )
-{
-	int						i, j, k, l, c1, c2;
-	parseMesh_t				*pm;
-	parseMesh_t				*check, *scan;
-	mapDrawSurface_t		*ds;
-	int						patchCount, groupCount;
-	bspDrawVert_t			*v1, *v2;
-	vec3_t					bounds[ 2 ];
-	byte					*bordering;
-	
-	/* ydnar: mac os x fails with these if not static */
-	MAC_STATIC parseMesh_t	*meshes[ MAX_MAP_DRAW_SURFS ];
-	MAC_STATIC qb_t			grouped[ MAX_MAP_DRAW_SURFS ];
-	MAC_STATIC byte			group[ MAX_MAP_DRAW_SURFS ];
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- PatchMapDrawSurfs ---\n" );
-
-	patchCount = 0;
-	for ( pm = e->patches ; pm ; pm = pm->next  ) {
-		meshes[patchCount] = pm;
-		patchCount++;
-	}
-
-	if ( !patchCount ) {
-		return;
-	}
-	bordering = safe_malloc( patchCount * patchCount );
-	memset( bordering, 0, patchCount * patchCount );
-
-	// build the bordering matrix
-	for ( k = 0 ; k < patchCount ; k++ ) {
-		bordering[k*patchCount+k] = 1;
-
-		for ( l = k+1 ; l < patchCount ; l++ ) {
-			check = meshes[k];
-			scan = meshes[l];
-			c1 = scan->mesh.width * scan->mesh.height;
-			v1 = scan->mesh.verts;
-
-			for ( i = 0 ; i < c1 ; i++, v1++ ) {
-				c2 = check->mesh.width * check->mesh.height;
-				v2 = check->mesh.verts;
-				for ( j = 0 ; j < c2 ; j++, v2++ ) {
-					if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
-						&& fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
-						&& fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
-						break;
-					}
-				}
-				if ( j != c2 ) {
-					break;
-				}
-			}
-			if ( i != c1 ) {
-				// we have a connection
-				bordering[k*patchCount+l] =
-				bordering[l*patchCount+k] = 1;
-			} else {
-				// no connection
-				bordering[k*patchCount+l] =
-				bordering[l*patchCount+k] = 0;
-			}
-
-		}
-	}
-
-	/* build groups */
-	memset( grouped, 0, patchCount );
-	groupCount = 0;
-	for ( i = 0; i < patchCount; i++ )
-	{
-		/* get patch */
-		scan = meshes[ i ];
-		
-		/* start a new group */
-		if( !grouped[ i ] )
-			groupCount++;
-		
-		/* recursively find all patches that belong in the same group */
-		memset( group, 0, patchCount );
-		GrowGroup_r( scan, i, patchCount, meshes, bordering, group );
-		
-		/* bound them */
-		ClearBounds( bounds[ 0 ], bounds[ 1 ] );
-		for( j = 0; j < patchCount; j++ )
-		{
-			if ( group[ j ] )
-			{
-				grouped[ j ] = qtrue;
-				check = meshes[ j ];
-				c1 = check->mesh.width * check->mesh.height;
-				v1 = check->mesh.verts;
-				for( k = 0; k < c1; k++, v1++ )
-					AddPointToBounds( v1->xyz, bounds[ 0 ], bounds[ 1 ] );
-			}
-		}
-		
-		/* debug code */
-		//%	Sys_Printf( "Longest curve: %f Iterations: %d\n", scan->longestCurve, scan->maxIterations );
-		
-		/* create drawsurf */
-		scan->grouped = qtrue;
-		ds = DrawSurfaceForMesh( e, scan, NULL );	/* ydnar */
-		VectorCopy( bounds[ 0 ], ds->bounds[ 0 ] );
-		VectorCopy( bounds[ 1 ], ds->bounds[ 1 ] );
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d patches\n", patchCount );
-	Sys_FPrintf( SYS_VRB, "%9d patch LOD groups\n", groupCount );
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PATCH_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+ExpandLongestCurve() - ydnar
+finds length of quadratic curve specified and determines if length is longer than the supplied max
+*/
+
+#define APPROX_SUBDIVISION	8
+
+static void ExpandLongestCurve( float *longestCurve, vec3_t a, vec3_t b, vec3_t c )
+{
+	int		i;
+	float	t, len;
+	vec3_t	ab, bc, ac, pt, last, delta;
+	
+	
+	/* calc vectors */
+	VectorSubtract( b, a, ab );
+	if( VectorNormalize( ab, ab ) < 0.125f )
+		return;
+	VectorSubtract( c, b, bc );
+	if( VectorNormalize( bc, bc ) < 0.125f )
+		return;
+	VectorSubtract( c, a, ac );
+	if( VectorNormalize( ac, ac ) < 0.125f )
+		return;
+	
+	/* if all 3 vectors are the same direction, then this edge is linear, so we ignore it */
+	if( DotProduct( ab, bc ) > 0.99f && DotProduct( ab, ac ) > 0.99f )
+		return;
+	
+	/* recalculate vectors */
+	VectorSubtract( b, a, ab );
+	VectorSubtract( c, b, bc );
+	
+	/* determine length */
+	VectorCopy( a, last );
+	for( i = 0, len = 0.0f, t = 0.0f; i < APPROX_SUBDIVISION; i++, t += (1.0f / APPROX_SUBDIVISION) )
+	{
+		/* calculate delta */
+		delta[ 0 ] = ((1.0f - t) * ab[ 0 ]) + (t * bc[ 0 ]);
+		delta[ 1 ] = ((1.0f - t) * ab[ 1 ]) + (t * bc[ 1 ]);
+		delta[ 2 ] = ((1.0f - t) * ab[ 2 ]) + (t * bc[ 2 ]);
+		
+		/* add to first point and calculate pt-pt delta */
+		VectorAdd( a, delta, pt );
+		VectorSubtract( pt, last, delta );
+		
+		/* add it to length and store last point */
+		len += VectorLength( delta );
+		VectorCopy( pt, last );
+	}
+	
+	/* longer? */
+	if( len > *longestCurve )
+		*longestCurve = len;
+}
+
+
+
+/*
+ExpandMaxIterations() - ydnar
+determines how many iterations a quadratic curve needs to be subdivided with to fit the specified error
+*/
+
+static void ExpandMaxIterations( int *maxIterations, int maxError, vec3_t a, vec3_t b, vec3_t c )
+{
+	int				i, j;
+	vec3_t			prev, next, mid, delta, delta2;
+	float			len, len2;
+	int				numPoints, iterations;
+	vec3_t			points[ MAX_EXPANDED_AXIS ];
+	
+	
+	/* initial setup */
+	numPoints = 3;
+	VectorCopy( a, points[ 0 ] );
+	VectorCopy( b, points[ 1 ] );
+	VectorCopy( c, points[ 2 ] );
+
+	/* subdivide */
+	for( i = 0; i + 2 < numPoints; i += 2 )
+	{
+		/* check subdivision limit */
+		if( numPoints + 2 >= MAX_EXPANDED_AXIS )
+			break;
+		
+		/* calculate new curve deltas */
+		for( j = 0; j < 3; j++ )
+		{
+			prev[ j ] = points[ i + 1 ][ j ] - points[ i ][ j ]; 
+			next[ j ] = points[ i + 2 ][ j ] - points[ i + 1 ][ j ]; 
+			mid[ j ] = (points[ i ][ j ] + points[ i + 1 ][ j ] * 2.0f + points[ i + 2 ][ j ]) * 0.25f;
+		}
+		
+		/* see if this midpoint is off far enough to subdivide */
+		VectorSubtract( points[ i + 1 ], mid, delta );
+		len = VectorLength( delta );
+		if( len < maxError )
+			continue;
+		
+		/* subdivide */
+		numPoints += 2;
+		
+		/* create new points */
+		for( j = 0; j < 3; j++ )
+		{
+			prev[ j ] = 0.5f * (points[ i ][ j ] + points[ i + 1 ][ j ]);
+			next[ j ] = 0.5f * (points[ i + 1 ][ j ] + points[ i + 2 ][ j ]);
+			mid[ j ] = 0.5f * (prev[ j ] + next[ j ]);
+		}
+		
+		/* push points out */
+		for( j = numPoints - 1; j > i + 3; j-- )
+			VectorCopy( points[ j - 2 ], points[ j ] );
+		
+		/* insert new points */
+		VectorCopy( prev, points[ i + 1 ] );
+		VectorCopy( mid, points[ i + 2 ] );
+		VectorCopy( next, points[ i + 3 ] );
+
+		/* back up and recheck this set again, it may need more subdivision */
+		i -= 2;
+	}
+	
+	/* put the line on the curve */
+	for( i = 1; i < numPoints; i += 2 )
+	{
+		for( j = 0; j < 3; j++ )
+		{
+			prev[ j ] = 0.5f * (points[ i ][ j ] + points[ i + 1 ][ j ] );
+			next[ j ] = 0.5f * (points[ i ][ j ] + points[ i - 1 ][ j ] );
+			points[ i ][ j ] = 0.5f * (prev[ j ] + next[ j ]);
+		}
+	}
+	
+	/* eliminate linear sections */
+	for( i = 0; i + 2 < numPoints; i++ )
+	{
+		/* create vectors */
+		VectorSubtract( points[ i + 1 ], points[ i ], delta );
+		len = VectorNormalize( delta, delta );
+		VectorSubtract( points[ i + 2 ], points[ i + 1 ], delta2 );
+		len2 = VectorNormalize( delta2, delta2 );
+		
+		/* if either edge is degenerate, then eliminate it */
+		if( len < 0.0625f || len2 < 0.0625f || DotProduct( delta, delta2 ) >= 1.0f )
+		{
+			for( j = i + 1; j + 1 < numPoints; j++ )
+				VectorCopy( points[ j + 1 ], points[ j ] );
+			numPoints--;
+			continue;
+		}
+	}
+	
+	/* the number of iterations is 2^(points - 1) - 1 */
+	numPoints >>= 1;
+	iterations = 0;
+	while( numPoints > 1 )
+	{
+		numPoints >>= 1;
+		iterations++;
+	}
+	
+	/* more? */
+	if( iterations > *maxIterations )
+		*maxIterations = iterations;
+}
+
+
+
+/*
+ParsePatch()
+creates a mapDrawSurface_t from the patch text
+*/
+
+void ParsePatch( qboolean onlyLights )
+{
+	vec_t			info[ 5 ];
+	int				i, j, k;
+	parseMesh_t		*pm;
+	char			texture[ MAX_QPATH ];
+	char			shader[ MAX_QPATH ];
+	mesh_t			m;
+	bspDrawVert_t	*verts;
+	epair_t			*ep;
+	vec4_t			delta, delta2, delta3;
+	qboolean		degenerate;
+	float			longestCurve;
+	int				maxIterations;
+	
+	
+	MatchToken( "{" );
+	
+	/* get texture */
+	GetToken( qtrue );
+	strcpy( texture, token );
+	
+	Parse1DMatrix( 5, info );
+	m.width = info[0];
+	m.height = info[1];
+	m.verts = verts = safe_malloc( m.width * m.height * sizeof( m.verts[0] ) );
+	
+	if( m.width < 0 || m.width > MAX_PATCH_SIZE || m.height < 0 || m.height > MAX_PATCH_SIZE )
+		Error( "ParsePatch: bad size" );
+	
+	MatchToken( "(" );
+	for( j = 0; j < m.width ; j++ )
+	{
+		MatchToken( "(" );
+		for( i = 0; i < m.height ; i++ )
+		{
+			Parse1DMatrix( 5, verts[ i * m.width + j ].xyz );
+			
+			/* ydnar: fix colors */
+			for( k = 0; k < MAX_LIGHTMAPS; k++ )
+			{
+				verts[ i * m.width + j ].color[ k ][ 0 ] = 255;
+				verts[ i * m.width + j ].color[ k ][ 1 ] = 255;
+				verts[ i * m.width + j ].color[ k ][ 2 ] = 255;
+				verts[ i * m.width + j ].color[ k ][ 3 ] = 255;
+			}
+		}
+		MatchToken( ")" );
+	}
+	MatchToken( ")" );
+
+	// if brush primitives format, we may have some epairs to ignore here
+	GetToken(qtrue);
+	if (g_bBrushPrimit!=BPRIMIT_OLDBRUSHES && strcmp(token,"}"))
+	{
+		// NOTE: we leak that!
+		ep = ParseEPair();
+	}
+	else
+		UnGetToken();
+
+	MatchToken( "}" );
+	MatchToken( "}" );
+	
+	/* short circuit */
+	if( noCurveBrushes || onlyLights )
+		return;
+	
+	
+	/* ydnar: delete and warn about degenerate patches */
+	j = (m.width * m.height);
+	VectorClear( delta );
+	delta[ 3 ] = 0;
+	degenerate = qtrue;
+	
+	/* find first valid vector */
+	for( i = 1; i < j && delta[ 3 ] == 0; i++ )
+	{
+		VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta );
+		delta[ 3 ] = VectorNormalize( delta, delta );
+	}
+	
+	/* secondary degenerate test */
+	if( delta[ 3 ] == 0 )
+		degenerate = qtrue;
+	else
+	{
+		/* if all vectors match this or are zero, then this is a degenerate patch */
+		for( i = 1; i < j && degenerate == qtrue; i++ )
+		{
+			VectorSubtract( m.verts[ 0 ].xyz, m.verts[ i ].xyz, delta2 );
+			delta2[ 3 ] = VectorNormalize( delta2, delta2 );
+			if( delta2[ 3 ] != 0 )
+			{
+				/* create inverse vector */
+				VectorCopy( delta2, delta3 );
+				delta3[ 3 ] = delta2[ 3 ];
+				VectorInverse( delta3 );
+				
+				/* compare */
+				if( VectorCompare( delta, delta2 ) == qfalse && VectorCompare( delta, delta3 ) == qfalse )
+					degenerate = qfalse;
+			}
+		}
+	}
+	
+	/* warn and select degenerate patch */
+	if( degenerate )
+	{
+		xml_Select( "degenerate patch", mapEnt->mapEntityNum, entitySourceBrushes, qfalse );
+		free( m.verts );
+		return;
+	}
+	
+	/* find longest curve on the mesh */
+	longestCurve = 0.0f;
+	maxIterations = 0;
+	for( j = 0; j + 2 < m.width; j += 2 )
+	{
+		for( i = 0; i + 2 < m.height; i += 2 )
+		{
+			ExpandLongestCurve( &longestCurve, verts[ i * m.width + j ].xyz, verts[ i * m.width + (j + 1) ].xyz, verts[ i * m.width + (j + 2) ].xyz );		/* row */
+			ExpandLongestCurve( &longestCurve, verts[ i * m.width + j ].xyz, verts[ (i + 1) * m.width + j ].xyz, verts[ (i + 2) * m.width + j ].xyz );		/* col */
+			ExpandMaxIterations( &maxIterations, patchSubdivisions, verts[ i * m.width + j ].xyz, verts[ i * m.width + (j + 1) ].xyz, verts[ i * m.width + (j + 2) ].xyz );		/* row */
+			ExpandMaxIterations( &maxIterations, patchSubdivisions, verts[ i * m.width + j ].xyz, verts[ (i + 1) * m.width + j ].xyz, verts[ (i + 2) * m.width + j ].xyz  );	/* col */
+		}
+	}
+	
+	/* allocate patch mesh */
+	pm = safe_malloc( sizeof( *pm ) );
+	memset( pm, 0, sizeof( *pm ) );
+	
+	/* ydnar: add entity/brush numbering */
+	pm->entityNum = mapEnt->mapEntityNum;
+	pm->brushNum = entitySourceBrushes;
+	
+	/* set shader */
+	sprintf( shader, "textures/%s", texture );
+	pm->shaderInfo = ShaderInfoForShader( shader );
+	
+	/* set mesh */
+	pm->mesh = m;
+	
+	/* set longest curve */
+	pm->longestCurve = longestCurve;
+	pm->maxIterations = maxIterations;
+	
+	/* link to the entity */
+	pm->next = mapEnt->patches;
+	mapEnt->patches = pm;
+}
+
+
+
+/*
+GrowGroup_r()
+recursively adds patches to a lod group
+*/
+
+static void GrowGroup_r( parseMesh_t *pm, int patchNum, int patchCount, parseMesh_t **meshes, byte *bordering, byte *group )
+{
+	int			i;
+	const byte	*row;
+	
+	
+	/* early out check */
+	if( group[ patchNum ] )
+		return;
+	
+	
+	/* set it */
+	group[ patchNum ] = 1;
+	row = bordering + patchNum * patchCount;
+	
+	/* check maximums */
+	if( meshes[ patchNum ]->longestCurve > pm->longestCurve )
+		pm->longestCurve = meshes[ patchNum ]->longestCurve;
+	if( meshes[ patchNum ]->maxIterations > pm->maxIterations )
+		pm->maxIterations = meshes[ patchNum ]->maxIterations;
+	
+	/* walk other patches */
+	for( i = 0; i < patchCount; i++ )
+	{
+		if( row[ i ] )
+			GrowGroup_r( pm, i, patchCount, meshes, bordering, group );
+	}
+}
+
+
+/*
+PatchMapDrawSurfs()
+any patches that share an edge need to choose their
+level of detail as a unit, otherwise the edges would
+pull apart.
+*/
+
+void PatchMapDrawSurfs( entity_t *e )
+{
+	int						i, j, k, l, c1, c2;
+	parseMesh_t				*pm;
+	parseMesh_t				*check, *scan;
+	mapDrawSurface_t		*ds;
+	int						patchCount, groupCount;
+	bspDrawVert_t			*v1, *v2;
+	vec3_t					bounds[ 2 ];
+	byte					*bordering;
+	
+	/* ydnar: mac os x fails with these if not static */
+	MAC_STATIC parseMesh_t	*meshes[ MAX_MAP_DRAW_SURFS ];
+	MAC_STATIC qb_t			grouped[ MAX_MAP_DRAW_SURFS ];
+	MAC_STATIC byte			group[ MAX_MAP_DRAW_SURFS ];
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- PatchMapDrawSurfs ---\n" );
+
+	patchCount = 0;
+	for ( pm = e->patches ; pm ; pm = pm->next  ) {
+		meshes[patchCount] = pm;
+		patchCount++;
+	}
+
+	if ( !patchCount ) {
+		return;
+	}
+	bordering = safe_malloc( patchCount * patchCount );
+	memset( bordering, 0, patchCount * patchCount );
+
+	// build the bordering matrix
+	for ( k = 0 ; k < patchCount ; k++ ) {
+		bordering[k*patchCount+k] = 1;
+
+		for ( l = k+1 ; l < patchCount ; l++ ) {
+			check = meshes[k];
+			scan = meshes[l];
+			c1 = scan->mesh.width * scan->mesh.height;
+			v1 = scan->mesh.verts;
+
+			for ( i = 0 ; i < c1 ; i++, v1++ ) {
+				c2 = check->mesh.width * check->mesh.height;
+				v2 = check->mesh.verts;
+				for ( j = 0 ; j < c2 ; j++, v2++ ) {
+					if ( fabs( v1->xyz[0] - v2->xyz[0] ) < 1.0
+						&& fabs( v1->xyz[1] - v2->xyz[1] ) < 1.0
+						&& fabs( v1->xyz[2] - v2->xyz[2] ) < 1.0 ) {
+						break;
+					}
+				}
+				if ( j != c2 ) {
+					break;
+				}
+			}
+			if ( i != c1 ) {
+				// we have a connection
+				bordering[k*patchCount+l] =
+				bordering[l*patchCount+k] = 1;
+			} else {
+				// no connection
+				bordering[k*patchCount+l] =
+				bordering[l*patchCount+k] = 0;
+			}
+
+		}
+	}
+
+	/* build groups */
+	memset( grouped, 0, patchCount );
+	groupCount = 0;
+	for ( i = 0; i < patchCount; i++ )
+	{
+		/* get patch */
+		scan = meshes[ i ];
+		
+		/* start a new group */
+		if( !grouped[ i ] )
+			groupCount++;
+		
+		/* recursively find all patches that belong in the same group */
+		memset( group, 0, patchCount );
+		GrowGroup_r( scan, i, patchCount, meshes, bordering, group );
+		
+		/* bound them */
+		ClearBounds( bounds[ 0 ], bounds[ 1 ] );
+		for( j = 0; j < patchCount; j++ )
+		{
+			if ( group[ j ] )
+			{
+				grouped[ j ] = qtrue;
+				check = meshes[ j ];
+				c1 = check->mesh.width * check->mesh.height;
+				v1 = check->mesh.verts;
+				for( k = 0; k < c1; k++, v1++ )
+					AddPointToBounds( v1->xyz, bounds[ 0 ], bounds[ 1 ] );
+			}
+		}
+		
+		/* debug code */
+		//%	Sys_Printf( "Longest curve: %f Iterations: %d\n", scan->longestCurve, scan->maxIterations );
+		
+		/* create drawsurf */
+		scan->grouped = qtrue;
+		ds = DrawSurfaceForMesh( e, scan, NULL );	/* ydnar */
+		VectorCopy( bounds[ 0 ], ds->bounds[ 0 ] );
+		VectorCopy( bounds[ 1 ], ds->bounds[ 1 ] );
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d patches\n", patchCount );
+	Sys_FPrintf( SYS_VRB, "%9d patch LOD groups\n", groupCount );
+}
+
diff --git a/tools/quake3/q3map2/path_init.c b/tools/quake3/q3map2/path_init.c
index e90b382d..80e3c6d3 100644
--- a/tools/quake3/q3map2/path_init.c
+++ b/tools/quake3/q3map2/path_init.c
@@ -1,456 +1,456 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define PATH_INIT_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* path support */
-#define MAX_BASE_PATHS	10
-#define MAX_GAME_PATHS	10
-
-char					*homePath;
-char					installPath[ MAX_OS_PATH ];
-
-int						numBasePaths;
-char					*basePaths[ MAX_BASE_PATHS ];
-int						numGamePaths;
-char					*gamePaths[ MAX_GAME_PATHS ];
-
-
-
-/*
-some of this code is based off the original q3map port from loki
-and finds various paths. moved here from bsp.c for clarity.
-*/
-
-/*
-PathLokiGetHomeDir()
-gets the user's home dir (for ~/.q3a)
-*/
-
-char *LokiGetHomeDir( void )
-{
-	#ifndef Q_UNIX
-		return NULL;
-	#else
-		char			*home;
-		uid_t			id;
-		struct passwd	*pwd;
-		
-		
-		/* get the home environment variable */
-		home = getenv( "HOME" );
-		if( home == NULL )
-		{
-			/* do some more digging */
-			id = getuid();
-			setpwent();
-			while( (pwd = getpwent()) != NULL )
-			{
-				if( pwd->pw_uid == id )
-				{
-					home = pwd->pw_dir;
-					break;
-				}
-			}
-			endpwent();
-		}
-		
-		/* return it */
-		return home;
-	#endif
-}
-
-
-
-/*
-PathLokiInitPaths()
-initializes some paths on linux/os x
-*/
-
-void LokiInitPaths( char *argv0 )
-{
-	#ifndef Q_UNIX
-		/* this is kinda crap, but hey */
-		strcpy( installPath, "../" );
-	#else
-		char		temp[ MAX_OS_PATH ];
-		char		*home;
-		char		*path;
-		char		*last;
-		qboolean	found;
-		
-		
-		/* get home dir */
-		home = LokiGetHomeDir();
-		if( home == NULL )
-			home = ".";
-		
-		/* do some path divining */
-		strcpy( temp, argv0 );
-		if( strrchr( temp, '/' ) )
-			argv0 = strrchr( argv0, '/' ) + 1;
-		else
-		{
-			/* get path environment variable */
-			path = getenv( "PATH" );
-			
-			/* minor setup */
-			last[ 0 ] = path[ 0 ];
-			last[ 1 ] = '\0';
-			found = qfalse;
-			
-			/* go through each : segment of path */
-			while( last[ 0 ] != '\0' && found == qfalse )
-			{
-				/* null out temp */
-				temp[ 0 ] = '\0';
-				
-				/* find next chunk */
-				last = strchr( path, ':' );
-				if( last == NULL )
-					last = path + strlen( path );
-				
-				/* found home dir candidate */
-				if( *path == '~' )
-				{
-					strcpy( temp, home );
-					path++;
-				}
-				
-				/* concatenate */
-				if( last > (path + 1) )
-				{
-					strncat( temp, path, (last - path) );
-					strcat( temp, "/" );
-				}
-				strcat( temp, "./" );
-				strcat( temp, argv0 );
-				
-				/* verify the path */
-				if( access( temp, X_OK ) == 0 )
-					found++;
-				path = last + 1;
-			}
-		}
-		
-		/* flake */
-		if( realpath( temp, installPath ) )
-		{
-			/* q3map is in "tools/" */
-			*(strrchr( installPath, '/' )) = '\0';
-			*(strrchr( installPath, '/' ) + 1) = '\0';
-		}
-		
-		/* set home path */
-		homePath = home;
-	#endif
-}
-
-
-
-/*
-CleanPath() - ydnar
-cleans a dos path \ -> /
-*/
-
-void CleanPath( char *path )
-{
-	while( *path )
-	{
-		if( *path == '\\' )
-			*path = '/';
-		path++;
-	}
-}
-
-
-
-/*
-SetGame() - ydnar
-sets the game based on a -game argument
-doesn't set it if the game doesn't match any known games
-*/
-
-void SetGame( char *arg )
-{
-	int	i;
-	
-	
-	/* dummy check */
-	if( arg == NULL || arg[ 0 ] == '\0' )
-		return;
-	
-	/* joke */
-	if( !Q_stricmp( arg, "quake1" ) ||
-		!Q_stricmp( arg, "quake2" ) ||
-		!Q_stricmp( arg, "unreal" ) ||
-		!Q_stricmp( arg, "ut2k3" ) ||
-		!Q_stricmp( arg, "dn3d" ) ||
-		!Q_stricmp( arg, "dnf" ) ||
-		!Q_stricmp( arg, "hl" ) )
-	{
-		Sys_Printf( "April fools, silly rabbit!\n" );
-		exit( 0 );
-	}
-	
-	/* test it */
-	i = 0;
-	while( games[ i ].arg != NULL )
-	{
-		if( Q_stricmp( arg, games[ i ].arg ) == 0 )
-			game = &games[ i ];
-		i++;
-	}
-}
-
-
-
-/*
-AddBasePath() - ydnar
-adds a base path to the list
-*/
-
-void AddBasePath( char *path )
-{
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
-		return;
-	
-	/* add it to the list */
-	basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
-	strcpy( basePaths[ numBasePaths ], path );
-	CleanPath( basePaths[ numBasePaths ] );
-	numBasePaths++;
-}
-
-
-
-/*
-AddHomeBasePath() - ydnar
-adds a base path to the beginning of the list, prefixed by ~/
-*/
-
-void AddHomeBasePath( char *path )
-{
-	#ifdef Q_UNIX
-		int		i;
-		char	temp[ MAX_OS_PATH ];
-		
-		
-		/* dummy check */
-		if( path == NULL || path[ 0 ] == '\0' )
-			return;
-
-		/* make a hole */
-		for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
-			basePaths[ i + 1 ] = basePaths[ i ];
-		
-		/* concatenate home dir and path */
-		sprintf( temp, "%s/%s", homePath, path );
-		
-		/* add it to the list */
-		basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
-		strcpy( basePaths[ 0 ], temp );
-		CleanPath( basePaths[ 0 ] );
-		numBasePaths++;
-	#endif
-}
-
-
-
-/*
-AddGamePath() - ydnar
-adds a game path to the list
-*/
-
-void AddGamePath( char *path )
-{
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
-		return;
-	
-	/* add it to the list */
-	gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
-	strcpy( gamePaths[ numGamePaths ], path );
-	CleanPath( gamePaths[ numGamePaths ] );
-	numGamePaths++;
-}
-
-
-
-
-/*
-InitPaths() - ydnar
-cleaned up some of the path initialization code from bsp.c
-will remove any arguments it uses
-*/
-
-void InitPaths( int *argc, char **argv )
-{
-	int		i, j, k, len, len2;
-	char	temp[ MAX_OS_PATH ];
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
-	
-	/* get the install path for backup */
-	LokiInitPaths( argv[ 0 ] );
-	
-	/* set game to default (q3a) */
-	game = &games[ 0 ];
-	numBasePaths = 0;
-	numGamePaths = 0;
-	
-	/* parse through the arguments and extract those relevant to paths */
-	for( i = 0; i < *argc; i++ )
-	{
-		/* check for null */
-		if( argv[ i ] == NULL )
-			continue;
-		
-		/* -game */
-		if( strcmp( argv[ i ], "-game" ) == 0 )
-		{
-			if( ++i >= *argc )
-				Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
-			argv[ i - 1 ] = NULL;
-			SetGame( argv[ i ] );
-			argv[ i ] = NULL;
-		}
-
-		/* -fs_basepath */
-		else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
-		{
-			if( ++i >= *argc )
-				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
-			argv[ i - 1 ] = NULL;
-			AddBasePath( argv[ i ] );
-			argv[ i ] = NULL;
-		}
-		
-		/* -fs_game */
-		else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
-		{
-			if( ++i >= *argc )
-				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
-			argv[ i - 1 ] = NULL;
-			AddGamePath( argv[ i ] );
-			argv[ i ] = NULL;
-		}
-	}
-	
-	/* remove processed arguments */
-	for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
-	{
-		for( j; j < *argc && argv[ j ] == NULL; j++ );
-		argv[ i ] = argv[ j ];
-		if( argv[ i ] != NULL )
-			k++;
-	}
-	*argc = k;
-	
-	/* add standard game path */
-	AddGamePath( game->gamePath );
-	
-	/* if there is no base path set, figure it out */
-	if( numBasePaths == 0 )
-	{
-		/* this is another crappy replacement for SetQdirFromPath() */
-		len2 = strlen( game->magic );
-		for( i = 0; i < *argc && numBasePaths == 0; i++ )
-		{
-			/* extract the arg */
-			strcpy( temp, argv[ i ] );
-			CleanPath( temp );
-			len = strlen( temp );
-			Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
-			
-			/* this is slow, but only done once */
-			for( j = 0; j < (len - len2); j++ )
-			{
-				/* check for the game's magic word */
-				if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
-				{
-					/* now find the next slash and nuke everything after it */
-					while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
-					temp[ j ] = '\0';
-					
-					/* add this as a base path */
-					AddBasePath( temp );
-					break;
-				}
-			}
-		}
-		
-		/* add install path */
-		if( numBasePaths == 0 )
-			AddBasePath( installPath );
-		
-		/* check again */
-		if( numBasePaths == 0 )
-			Error( "Failed to find a valid base path." );
-	}
-	
-	/* this only affects unix */
-	AddHomeBasePath( game->homeBasePath );
-	
-	/* initialize vfs paths */
-	if( numBasePaths > MAX_BASE_PATHS )
-		numBasePaths = MAX_BASE_PATHS;
-	if( numGamePaths > MAX_GAME_PATHS )
-		numGamePaths = MAX_GAME_PATHS;
-	
-	/* walk the list of game paths */
-	for( j = 0; j < numGamePaths; j++ )
-	{
-		/* walk the list of base paths */
-		for( i = 0; i < numBasePaths; i++ )
-		{
-			/* create a full path and initialize it */
-			sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
-			vfsInitDirectory( temp );
-		}
-	}
-	
-	/* done */
-	Sys_Printf( "\n" );
-}
-
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PATH_INIT_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* path support */
+#define MAX_BASE_PATHS	10
+#define MAX_GAME_PATHS	10
+
+char					*homePath;
+char					installPath[ MAX_OS_PATH ];
+
+int						numBasePaths;
+char					*basePaths[ MAX_BASE_PATHS ];
+int						numGamePaths;
+char					*gamePaths[ MAX_GAME_PATHS ];
+
+
+
+/*
+some of this code is based off the original q3map port from loki
+and finds various paths. moved here from bsp.c for clarity.
+*/
+
+/*
+PathLokiGetHomeDir()
+gets the user's home dir (for ~/.q3a)
+*/
+
+char *LokiGetHomeDir( void )
+{
+	#ifndef Q_UNIX
+		return NULL;
+	#else
+		char			*home;
+		uid_t			id;
+		struct passwd	*pwd;
+		
+		
+		/* get the home environment variable */
+		home = getenv( "HOME" );
+		if( home == NULL )
+		{
+			/* do some more digging */
+			id = getuid();
+			setpwent();
+			while( (pwd = getpwent()) != NULL )
+			{
+				if( pwd->pw_uid == id )
+				{
+					home = pwd->pw_dir;
+					break;
+				}
+			}
+			endpwent();
+		}
+		
+		/* return it */
+		return home;
+	#endif
+}
+
+
+
+/*
+PathLokiInitPaths()
+initializes some paths on linux/os x
+*/
+
+void LokiInitPaths( char *argv0 )
+{
+	#ifndef Q_UNIX
+		/* this is kinda crap, but hey */
+		strcpy( installPath, "../" );
+	#else
+		char		temp[ MAX_OS_PATH ];
+		char		*home;
+		char		*path;
+		char		*last;
+		qboolean	found;
+		
+		
+		/* get home dir */
+		home = LokiGetHomeDir();
+		if( home == NULL )
+			home = ".";
+		
+		/* do some path divining */
+		strcpy( temp, argv0 );
+		if( strrchr( temp, '/' ) )
+			argv0 = strrchr( argv0, '/' ) + 1;
+		else
+		{
+			/* get path environment variable */
+			path = getenv( "PATH" );
+			
+			/* minor setup */
+			last[ 0 ] = path[ 0 ];
+			last[ 1 ] = '\0';
+			found = qfalse;
+			
+			/* go through each : segment of path */
+			while( last[ 0 ] != '\0' && found == qfalse )
+			{
+				/* null out temp */
+				temp[ 0 ] = '\0';
+				
+				/* find next chunk */
+				last = strchr( path, ':' );
+				if( last == NULL )
+					last = path + strlen( path );
+				
+				/* found home dir candidate */
+				if( *path == '~' )
+				{
+					strcpy( temp, home );
+					path++;
+				}
+				
+				/* concatenate */
+				if( last > (path + 1) )
+				{
+					strncat( temp, path, (last - path) );
+					strcat( temp, "/" );
+				}
+				strcat( temp, "./" );
+				strcat( temp, argv0 );
+				
+				/* verify the path */
+				if( access( temp, X_OK ) == 0 )
+					found++;
+				path = last + 1;
+			}
+		}
+		
+		/* flake */
+		if( realpath( temp, installPath ) )
+		{
+			/* q3map is in "tools/" */
+			*(strrchr( installPath, '/' )) = '\0';
+			*(strrchr( installPath, '/' ) + 1) = '\0';
+		}
+		
+		/* set home path */
+		homePath = home;
+	#endif
+}
+
+
+
+/*
+CleanPath() - ydnar
+cleans a dos path \ -> /
+*/
+
+void CleanPath( char *path )
+{
+	while( *path )
+	{
+		if( *path == '\\' )
+			*path = '/';
+		path++;
+	}
+}
+
+
+
+/*
+SetGame() - ydnar
+sets the game based on a -game argument
+doesn't set it if the game doesn't match any known games
+*/
+
+void SetGame( char *arg )
+{
+	int	i;
+	
+	
+	/* dummy check */
+	if( arg == NULL || arg[ 0 ] == '\0' )
+		return;
+	
+	/* joke */
+	if( !Q_stricmp( arg, "quake1" ) ||
+		!Q_stricmp( arg, "quake2" ) ||
+		!Q_stricmp( arg, "unreal" ) ||
+		!Q_stricmp( arg, "ut2k3" ) ||
+		!Q_stricmp( arg, "dn3d" ) ||
+		!Q_stricmp( arg, "dnf" ) ||
+		!Q_stricmp( arg, "hl" ) )
+	{
+		Sys_Printf( "April fools, silly rabbit!\n" );
+		exit( 0 );
+	}
+	
+	/* test it */
+	i = 0;
+	while( games[ i ].arg != NULL )
+	{
+		if( Q_stricmp( arg, games[ i ].arg ) == 0 )
+			game = &games[ i ];
+		i++;
+	}
+}
+
+
+
+/*
+AddBasePath() - ydnar
+adds a base path to the list
+*/
+
+void AddBasePath( char *path )
+{
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' || numBasePaths >= MAX_BASE_PATHS )
+		return;
+	
+	/* add it to the list */
+	basePaths[ numBasePaths ] = safe_malloc( strlen( path ) + 1 );
+	strcpy( basePaths[ numBasePaths ], path );
+	CleanPath( basePaths[ numBasePaths ] );
+	numBasePaths++;
+}
+
+
+
+/*
+AddHomeBasePath() - ydnar
+adds a base path to the beginning of the list, prefixed by ~/
+*/
+
+void AddHomeBasePath( char *path )
+{
+	#ifdef Q_UNIX
+		int		i;
+		char	temp[ MAX_OS_PATH ];
+		
+		
+		/* dummy check */
+		if( path == NULL || path[ 0 ] == '\0' )
+			return;
+
+		/* make a hole */
+		for( i = 0; i < (MAX_BASE_PATHS - 1); i++ )
+			basePaths[ i + 1 ] = basePaths[ i ];
+		
+		/* concatenate home dir and path */
+		sprintf( temp, "%s/%s", homePath, path );
+		
+		/* add it to the list */
+		basePaths[ 0 ] = safe_malloc( strlen( temp ) + 1 );
+		strcpy( basePaths[ 0 ], temp );
+		CleanPath( basePaths[ 0 ] );
+		numBasePaths++;
+	#endif
+}
+
+
+
+/*
+AddGamePath() - ydnar
+adds a game path to the list
+*/
+
+void AddGamePath( char *path )
+{
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' || numGamePaths >= MAX_GAME_PATHS )
+		return;
+	
+	/* add it to the list */
+	gamePaths[ numGamePaths ] = safe_malloc( strlen( path ) + 1 );
+	strcpy( gamePaths[ numGamePaths ], path );
+	CleanPath( gamePaths[ numGamePaths ] );
+	numGamePaths++;
+}
+
+
+
+
+/*
+InitPaths() - ydnar
+cleaned up some of the path initialization code from bsp.c
+will remove any arguments it uses
+*/
+
+void InitPaths( int *argc, char **argv )
+{
+	int		i, j, k, len, len2;
+	char	temp[ MAX_OS_PATH ];
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- InitPaths ---\n" );
+	
+	/* get the install path for backup */
+	LokiInitPaths( argv[ 0 ] );
+	
+	/* set game to default (q3a) */
+	game = &games[ 0 ];
+	numBasePaths = 0;
+	numGamePaths = 0;
+	
+	/* parse through the arguments and extract those relevant to paths */
+	for( i = 0; i < *argc; i++ )
+	{
+		/* check for null */
+		if( argv[ i ] == NULL )
+			continue;
+		
+		/* -game */
+		if( strcmp( argv[ i ], "-game" ) == 0 )
+		{
+			if( ++i >= *argc )
+				Error( "Out of arguments: No game specified after %s", argv[ i - 1 ] );
+			argv[ i - 1 ] = NULL;
+			SetGame( argv[ i ] );
+			argv[ i ] = NULL;
+		}
+
+		/* -fs_basepath */
+		else if( strcmp( argv[ i ], "-fs_basepath" ) == 0 )
+		{
+			if( ++i >= *argc )
+				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+			argv[ i - 1 ] = NULL;
+			AddBasePath( argv[ i ] );
+			argv[ i ] = NULL;
+		}
+		
+		/* -fs_game */
+		else if( strcmp( argv[ i ], "-fs_game" ) == 0 )
+		{
+			if( ++i >= *argc )
+				Error( "Out of arguments: No path specified after %s.", argv[ i - 1 ] );
+			argv[ i - 1 ] = NULL;
+			AddGamePath( argv[ i ] );
+			argv[ i ] = NULL;
+		}
+	}
+	
+	/* remove processed arguments */
+	for( i = 0, j = 0, k = 0; i < *argc && j < *argc; i++, j++ )
+	{
+		for( j; j < *argc && argv[ j ] == NULL; j++ );
+		argv[ i ] = argv[ j ];
+		if( argv[ i ] != NULL )
+			k++;
+	}
+	*argc = k;
+	
+	/* add standard game path */
+	AddGamePath( game->gamePath );
+	
+	/* if there is no base path set, figure it out */
+	if( numBasePaths == 0 )
+	{
+		/* this is another crappy replacement for SetQdirFromPath() */
+		len2 = strlen( game->magic );
+		for( i = 0; i < *argc && numBasePaths == 0; i++ )
+		{
+			/* extract the arg */
+			strcpy( temp, argv[ i ] );
+			CleanPath( temp );
+			len = strlen( temp );
+			Sys_FPrintf( SYS_VRB, "Searching for \"%s\" in \"%s\" (%d)...\n", game->magic, temp, i );
+			
+			/* this is slow, but only done once */
+			for( j = 0; j < (len - len2); j++ )
+			{
+				/* check for the game's magic word */
+				if( Q_strncasecmp( &temp[ j ], game->magic, len2 ) == 0 )
+				{
+					/* now find the next slash and nuke everything after it */
+					while( temp[ ++j ] != '/' && temp[ j ] != '\0' );
+					temp[ j ] = '\0';
+					
+					/* add this as a base path */
+					AddBasePath( temp );
+					break;
+				}
+			}
+		}
+		
+		/* add install path */
+		if( numBasePaths == 0 )
+			AddBasePath( installPath );
+		
+		/* check again */
+		if( numBasePaths == 0 )
+			Error( "Failed to find a valid base path." );
+	}
+	
+	/* this only affects unix */
+	AddHomeBasePath( game->homeBasePath );
+	
+	/* initialize vfs paths */
+	if( numBasePaths > MAX_BASE_PATHS )
+		numBasePaths = MAX_BASE_PATHS;
+	if( numGamePaths > MAX_GAME_PATHS )
+		numGamePaths = MAX_GAME_PATHS;
+	
+	/* walk the list of game paths */
+	for( j = 0; j < numGamePaths; j++ )
+	{
+		/* walk the list of base paths */
+		for( i = 0; i < numBasePaths; i++ )
+		{
+			/* create a full path and initialize it */
+			sprintf( temp, "%s/%s/", basePaths[ i ], gamePaths[ j ] );
+			vfsInitDirectory( temp );
+		}
+	}
+	
+	/* done */
+	Sys_Printf( "\n" );
+}
+
+
+
+
diff --git a/tools/quake3/q3map2/portals.c b/tools/quake3/q3map2/portals.c
index 0b3cdfd3..59ed6daf 100644
--- a/tools/quake3/q3map2/portals.c
+++ b/tools/quake3/q3map2/portals.c
@@ -1,970 +1,970 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define PORTALS_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* ydnar: to fix broken portal windings */
-extern qboolean FixWinding( winding_t *w );
-
-
-int		c_active_portals;
-int		c_peak_portals;
-int		c_boundary;
-int		c_boundary_sides;
-
-/*
-===========
-AllocPortal
-===========
-*/
-portal_t *AllocPortal (void)
-{
-	portal_t	*p;
-	
-	if (numthreads == 1)
-		c_active_portals++;
-	if (c_active_portals > c_peak_portals)
-		c_peak_portals = c_active_portals;
-	
-	p = safe_malloc (sizeof(portal_t));
-	memset (p, 0, sizeof(portal_t));
-	
-	return p;
-}
-
-void FreePortal (portal_t *p)
-{
-	if (p->winding)
-		FreeWinding (p->winding);
-	if (numthreads == 1)
-		c_active_portals--;
-	free (p);
-}
-
-
-
-/*
-PortalPassable
-returns true if the portal has non-opaque leafs on both sides
-*/
-
-qboolean PortalPassable( portal_t *p )
-{
-	/* is this to global outside leaf? */
-	if( !p->onnode )
-		return qfalse;
-	
-	/* this should never happen */
-	if( p->nodes[ 0 ]->planenum != PLANENUM_LEAF ||
-		p->nodes[ 1 ]->planenum != PLANENUM_LEAF )
-		Error( "Portal_EntityFlood: not a leaf" );
-	
-	/* ydnar: added antiportal to supress portal generation for visibility blocking */
-	if( p->compileFlags & C_ANTIPORTAL )
-		return qfalse;
-	
-	/* both leaves on either side of the portal must be passable */
-	if( p->nodes[ 0 ]->opaque == qfalse && p->nodes[ 1 ]->opaque == qfalse )
-		return qtrue;
-	
-	/* otherwise this isn't a passable portal */
-	return qfalse;
-}
-
-
-
-
-int		c_tinyportals;
-int		c_badportals;	/* ydnar */
-
-/*
-=============
-AddPortalToNodes
-=============
-*/
-void AddPortalToNodes (portal_t *p, node_t *front, node_t *back)
-{
-	if (p->nodes[0] || p->nodes[1])
-		Error ("AddPortalToNode: allready included");
-
-	p->nodes[0] = front;
-	p->next[0] = front->portals;
-	front->portals = p;
-	
-	p->nodes[1] = back;
-	p->next[1] = back->portals;
-	back->portals = p;
-}
-
-
-/*
-=============
-RemovePortalFromNode
-=============
-*/
-void RemovePortalFromNode (portal_t *portal, node_t *l)
-{
-	portal_t	**pp, *t;
-	
-// remove reference to the current portal
-	pp = &l->portals;
-	while (1)
-	{
-		t = *pp;
-		if (!t)
-			Error ("RemovePortalFromNode: portal not in leaf");	
-
-		if ( t == portal )
-			break;
-
-		if (t->nodes[0] == l)
-			pp = &t->next[0];
-		else if (t->nodes[1] == l)
-			pp = &t->next[1];
-		else
-			Error ("RemovePortalFromNode: portal not bounding leaf");
-	}
-	
-	if (portal->nodes[0] == l)
-	{
-		*pp = portal->next[0];
-		portal->nodes[0] = NULL;
-	}
-	else if (portal->nodes[1] == l)
-	{
-		*pp = portal->next[1];	
-		portal->nodes[1] = NULL;
-	}
-}
-
-//============================================================================
-
-void PrintPortal (portal_t *p)
-{
-	int			i;
-	winding_t	*w;
-	
-	w = p->winding;
-	for (i=0 ; i<w->numpoints ; i++)
-		Sys_Printf ("(%5.0f,%5.0f,%5.0f)\n",w->p[i][0]
-		, w->p[i][1], w->p[i][2]);
-}
-
-/*
-================
-MakeHeadnodePortals
-
-The created portals will face the global outside_node
-================
-*/
-#define	SIDESPACE	8
-void MakeHeadnodePortals (tree_t *tree)
-{
-	vec3_t		bounds[2];
-	int			i, j, n;
-	portal_t	*p, *portals[6];
-	plane_t		bplanes[6], *pl;
-	node_t *node;
-
-	node = tree->headnode;
-
-// pad with some space so there will never be null volume leafs
-	for (i=0 ; i<3 ; i++)
-	{
-		bounds[0][i] = tree->mins[i] - SIDESPACE;
-		bounds[1][i] = tree->maxs[i] + SIDESPACE;
-		if ( bounds[0][i] >= bounds[1][i] ) {
-			Error( "Backwards tree volume" );
-		}
-	}
-	
-	tree->outside_node.planenum = PLANENUM_LEAF;
-	tree->outside_node.brushlist = NULL;
-	tree->outside_node.portals = NULL;
-	tree->outside_node.opaque = qfalse;
-
-	for (i=0 ; i<3 ; i++)
-		for (j=0 ; j<2 ; j++)
-		{
-			n = j*3 + i;
-
-			p = AllocPortal ();
-			portals[n] = p;
-			
-			pl = &bplanes[n];
-			memset (pl, 0, sizeof(*pl));
-			if (j)
-			{
-				pl->normal[i] = -1;
-				pl->dist = -bounds[j][i];
-			}
-			else
-			{
-				pl->normal[i] = 1;
-				pl->dist = bounds[j][i];
-			}
-			p->plane = *pl;
-			p->winding = BaseWindingForPlane (pl->normal, pl->dist);
-			AddPortalToNodes (p, node, &tree->outside_node);
-		}
-		
-// clip the basewindings by all the other planes
-	for (i=0 ; i<6 ; i++)
-	{
-		for (j=0 ; j<6 ; j++)
-		{
-			if (j == i)
-				continue;
-			ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON);
-		}
-	}
-}
-
-//===================================================
-
-
-/*
-================
-BaseWindingForNode
-================
-*/
-#define	BASE_WINDING_EPSILON	0.001
-#define	SPLIT_WINDING_EPSILON	0.001
-
-winding_t	*BaseWindingForNode (node_t *node)
-{
-	winding_t	*w;
-	node_t		*n;
-	plane_t		*plane;
-	vec3_t		normal;
-	vec_t		dist;
-
-	w = BaseWindingForPlane (mapplanes[node->planenum].normal
-		, mapplanes[node->planenum].dist);
-
-	// clip by all the parents
-	for (n=node->parent ; n && w ; )
-	{
-		plane = &mapplanes[n->planenum];
-
-		if (n->children[0] == node)
-		{	// take front
-			ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON);
-		}
-		else
-		{	// take back
-			VectorSubtract (vec3_origin, plane->normal, normal);
-			dist = -plane->dist;
-			ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON);
-		}
-		node = n;
-		n = n->parent;
-	}
-
-	return w;
-}
-
-//============================================================
-
-/*
-==================
-MakeNodePortal
-
-create the new portal by taking the full plane winding for the cutting plane
-and clipping it by all of parents of this node
-==================
-*/
-void MakeNodePortal (node_t *node)
-{
-	portal_t	*new_portal, *p;
-	winding_t	*w;
-	vec3_t		normal;
-	float		dist;
-	int			side;
-
-	w = BaseWindingForNode (node);
-
-	// clip the portal by all the other portals in the node
-	for (p = node->portals ; p && w; p = p->next[side])	
-	{
-		if (p->nodes[0] == node)
-		{
-			side = 0;
-			VectorCopy (p->plane.normal, normal);
-			dist = p->plane.dist;
-		}
-		else if (p->nodes[1] == node)
-		{
-			side = 1;
-			VectorSubtract (vec3_origin, p->plane.normal, normal);
-			dist = -p->plane.dist;
-		}
-		else
-			Error ("CutNodePortals_r: mislinked portal");
-
-		ChopWindingInPlace (&w, normal, dist, CLIP_EPSILON);
-	}
-
-	if (!w)
-	{
-		return;
-	}
-	
-	
-	/* ydnar: adding this here to fix degenerate windings */
-	#if 0
-	if( FixWinding( w ) == qfalse )
-	{
-		c_badportals++;
-		FreeWinding( w );
-		return;
-	}
-	#endif
-	
-	if (WindingIsTiny (w))
-	{
-		c_tinyportals++;
-		FreeWinding (w);
-		return;
-	}
-
-	new_portal = AllocPortal ();
-	new_portal->plane = mapplanes[node->planenum];
-	new_portal->onnode = node;
-	new_portal->winding = w;
-	new_portal->compileFlags = node->compileFlags;
-	AddPortalToNodes (new_portal, node->children[0], node->children[1]);
-}
-
-
-/*
-==============
-SplitNodePortals
-
-Move or split the portals that bound node so that the node's
-children have portals instead of node.
-==============
-*/
-void SplitNodePortals (node_t *node)
-{
-	portal_t	*p, *next_portal, *new_portal;
-	node_t		*f, *b, *other_node;
-	int			side;
-	plane_t		*plane;
-	winding_t	*frontwinding, *backwinding;
-
-	plane = &mapplanes[node->planenum];
-	f = node->children[0];
-	b = node->children[1];
-
-	for (p = node->portals ; p ; p = next_portal)	
-	{
-		if (p->nodes[0] == node)
-			side = 0;
-		else if (p->nodes[1] == node)
-			side = 1;
-		else
-			Error ("SplitNodePortals: mislinked portal");
-		next_portal = p->next[side];
-
-		other_node = p->nodes[!side];
-		RemovePortalFromNode (p, p->nodes[0]);
-		RemovePortalFromNode (p, p->nodes[1]);
-
-//
-// cut the portal into two portals, one on each side of the cut plane
-//
-		ClipWindingEpsilon (p->winding, plane->normal, plane->dist,
-			SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);
-
-		if (frontwinding && WindingIsTiny(frontwinding))
-		{
-			if (!f->tinyportals)
-				VectorCopy(frontwinding->p[0], f->referencepoint);
-			f->tinyportals++;
-			if (!other_node->tinyportals)
-				VectorCopy(frontwinding->p[0], other_node->referencepoint);
-			other_node->tinyportals++;
-
-			FreeWinding (frontwinding);
-			frontwinding = NULL;
-			c_tinyportals++;
-		}
-
-		if (backwinding && WindingIsTiny(backwinding))
-		{
-			if (!b->tinyportals)
-				VectorCopy(backwinding->p[0], b->referencepoint);
-			b->tinyportals++;
-			if (!other_node->tinyportals)
-				VectorCopy(backwinding->p[0], other_node->referencepoint);
-			other_node->tinyportals++;
-
-			FreeWinding (backwinding);
-			backwinding = NULL;
-			c_tinyportals++;
-		}
-
-		if (!frontwinding && !backwinding)
-		{	// tiny windings on both sides
-			continue;
-		}
-
-		if (!frontwinding)
-		{
-			FreeWinding (backwinding);
-			if (side == 0)
-				AddPortalToNodes (p, b, other_node);
-			else
-				AddPortalToNodes (p, other_node, b);
-			continue;
-		}
-		if (!backwinding)
-		{
-			FreeWinding (frontwinding);
-			if (side == 0)
-				AddPortalToNodes (p, f, other_node);
-			else
-				AddPortalToNodes (p, other_node, f);
-			continue;
-		}
-		
-	// the winding is split
-		new_portal = AllocPortal ();
-		*new_portal = *p;
-		new_portal->winding = backwinding;
-		FreeWinding (p->winding);
-		p->winding = frontwinding;
-
-		if (side == 0)
-		{
-			AddPortalToNodes (p, f, other_node);
-			AddPortalToNodes (new_portal, b, other_node);
-		}
-		else
-		{
-			AddPortalToNodes (p, other_node, f);
-			AddPortalToNodes (new_portal, other_node, b);
-		}
-	}
-
-	node->portals = NULL;
-}
-
-
-/*
-================
-CalcNodeBounds
-================
-*/
-void CalcNodeBounds (node_t *node)
-{
-	portal_t	*p;
-	int			s;
-	int			i;
-
-	// calc mins/maxs for both leafs and nodes
-	ClearBounds (node->mins, node->maxs);
-	for (p = node->portals ; p ; p = p->next[s])	
-	{
-		s = (p->nodes[1] == node);
-		for (i=0 ; i<p->winding->numpoints ; i++)
-			AddPointToBounds (p->winding->p[i], node->mins, node->maxs);
-	}
-}
-
-/*
-==================
-MakeTreePortals_r
-==================
-*/
-void MakeTreePortals_r (node_t *node)
-{
-	int		i;
-
-	CalcNodeBounds (node);
-	if (node->mins[0] >= node->maxs[0])
-	{
-		Sys_Printf ("WARNING: node without a volume\n");
-		Sys_Printf("node has %d tiny portals\n", node->tinyportals);
-		Sys_Printf("node reference point %1.2f %1.2f %1.2f\n", node->referencepoint[0],
-															node->referencepoint[1],
-															node->referencepoint[2]);
-	}
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if (node->mins[i] < MIN_WORLD_COORD || node->maxs[i] > MAX_WORLD_COORD)
-		{
-      if(node->portals && node->portals->winding)
-        xml_Winding("WARNING: Node With Unbounded Volume", node->portals->winding->p, node->portals->winding->numpoints, qfalse);
-
-			break;
-		}
-	}
-	if (node->planenum == PLANENUM_LEAF)
-		return;
-
-	MakeNodePortal (node);
-	SplitNodePortals (node);
-
-	MakeTreePortals_r (node->children[0]);
-	MakeTreePortals_r (node->children[1]);
-}
-
-/*
-==================
-MakeTreePortals
-==================
-*/
-void MakeTreePortals (tree_t *tree)
-{
-	Sys_FPrintf (SYS_VRB, "--- MakeTreePortals ---\n");
-	MakeHeadnodePortals (tree);
-	MakeTreePortals_r (tree->headnode);
-	Sys_FPrintf( SYS_VRB, "%9d tiny portals\n", c_tinyportals );
-	Sys_FPrintf( SYS_VRB, "%9d bad portals\n", c_badportals );	/* ydnar */
-}
-
-/*
-=========================================================
-
-FLOOD ENTITIES
-
-=========================================================
-*/
-
-int		c_floodedleafs;
-
-/*
-=============
-FloodPortals_r
-=============
-*/
-
-void FloodPortals_r( node_t *node, int dist, qboolean skybox )
-{
-	int			s;
-	portal_t	*p;
-	
-	
-	if( skybox )
-		node->skybox = skybox;
-	
-	if( node->occupied || node->opaque )
-		return;
-	
-	c_floodedleafs++;
-	node->occupied = dist;
-	
-	for( p = node->portals; p; p = p->next[ s ] )
-	{
-		s = (p->nodes[ 1 ] == node);
-		FloodPortals_r( p->nodes[ !s ], dist + 1, skybox );
-	}
-}
-
-
-
-/*
-=============
-PlaceOccupant
-=============
-*/
-
-qboolean PlaceOccupant( node_t *headnode, vec3_t origin, entity_t *occupant, qboolean skybox )
-{
-	vec_t	d;
-	node_t	*node;
-	plane_t	*plane;
-	
-	
-	// find the leaf to start in
-	node = headnode;
-	while( node->planenum != PLANENUM_LEAF )
-	{
-		plane = &mapplanes[ node->planenum ];
-		d = DotProduct( origin, plane->normal ) - plane->dist;
-		if( d >= 0 )
-			node = node->children[ 0 ];
-		else
-			node = node->children[ 1 ];
-	}
-	
-	if( node->opaque )
-		return qfalse;
-	node->occupant = occupant;
-	node->skybox = skybox;
-	
-	FloodPortals_r( node, 1, skybox );
-	
-	return qtrue;
-}
-
-/*
-=============
-FloodEntities
-
-Marks all nodes that can be reached by entites
-=============
-*/
-
-qboolean FloodEntities( tree_t *tree )
-{
-	int			i, s;
-	vec3_t		origin, offset, scale, angles;
-	qboolean	r, inside, tripped, skybox;
-	node_t		*headnode;
-	entity_t	*e;
-	const char	*value;
-	
-	
-	headnode = tree->headnode;
-	Sys_FPrintf( SYS_VRB,"--- FloodEntities ---\n" );
-	inside = qfalse;
-	tree->outside_node.occupied = 0;
-	
-	tripped = qfalse;
-	c_floodedleafs = 0;
-	for( i = 1; i < numEntities; i++ )
-	{
-		/* get entity */
-		e = &entities[ i ];
-		
-		/* get origin */
-		GetVectorForKey( e, "origin", origin );
-		if( VectorCompare( origin, vec3_origin ) ) 
-			continue;
-		
-		/* handle skybox entities */
-		value = ValueForKey( e, "classname" );
-		if( !Q_stricmp( value, "_skybox" ) )
-		{
-			skybox = qtrue;
-			skyboxPresent = qtrue;
-			
-			/* invert origin */
-			VectorScale( origin, -1.0f, offset );
-			
-			/* get scale */
-			VectorSet( scale, 64.0f, 64.0f, 64.0f );
-			value = ValueForKey( e, "_scale" );
-			if( value[ 0 ] != '\0' )
-			{
-				s = sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
-				if( s == 1 )
-				{
-					scale[ 1 ] = scale[ 0 ];
-					scale[ 2 ] = scale[ 0 ];
-				}
-			}
-			
-			/* get "angle" (yaw) or "angles" (pitch yaw roll) */
-			VectorClear( angles );
-			angles[ 2 ] = FloatForKey( e, "angle" );
-			value = ValueForKey( e, "angles" );
-			if( value[ 0 ] != '\0' )
-				sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
-			
-			/* set transform matrix (thanks spog) */
-			m4x4_identity( skyboxTransform );
-			m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin );
-		}
-		else
-			skybox = qfalse;
-		
-		/* nudge off floor */
-		origin[ 2 ] += 1;
-		
-		/* debugging code */
-		//%	if( i == 1 )
-		//%		origin[ 2 ] += 4096;
-		
-		/* find leaf */
-		r = PlaceOccupant( headnode, origin, e, skybox );
-		if( r )
-			inside = qtrue;
-		if( (!r || tree->outside_node.occupied) && !tripped )
-		{
-			xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse );
-			tripped = qtrue;
-		}
-	}
-	
-	Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );
-	
-	if( !inside )
-		Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" );
-	else if( tree->outside_node.occupied )
-		Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" );
-	
-	return (qboolean) (inside && !tree->outside_node.occupied);
-}
-
-/*
-=========================================================
-
-FLOOD AREAS
-
-=========================================================
-*/
-
-int		c_areas;
-
-
-
-/*
-FloodAreas_r()
-floods through leaf portals to tag leafs with an area
-*/
-
-void FloodAreas_r( node_t *node )
-{
-	int			s;
-	portal_t	*p;
-	brush_t		*b;
-	
-	
-	if( node->areaportal )
-	{
-		if( node->area == -1 )
-			node->area = c_areas;
-		
-		/* this node is part of an area portal brush */
-		b = node->brushlist->original;
-
-		/* if the current area has already touched this portal, we are done */
-		if( b->portalareas[ 0 ] == c_areas || b->portalareas[ 1 ] == c_areas )
-			return;
-		
-		// note the current area as bounding the portal
-		if( b->portalareas[ 1 ] != -1 )
-		{
-			Sys_Printf( "WARNING: areaportal brush %i touches > 2 areas\n", b->brushNum );
-			return;
-		}
-		if( b->portalareas[ 0 ] != -1 )
-			b->portalareas[ 1 ] = c_areas;
-		else
-			b->portalareas[ 0 ] = c_areas;
-		
-		return;
-	}
-
-	if( node->area != -1 )
-		return;	
-	if( node->cluster == -1 )
-		return;
-
-	node->area = c_areas;
-	
-	/* ydnar: skybox nodes set the skybox area */
-	if( node->skybox )
-		skyboxArea = c_areas;
-	
-	for( p = node->portals; p; p = p->next[ s ] )
-	{
-		s = (p->nodes[1] == node);
-		
-		/* ydnar: allow areaportal portals to block area flow */
-		if( p->compileFlags & C_AREAPORTAL )
-			continue;
-		
-		if( !PortalPassable( p ) )
-			continue;
-		
-		FloodAreas_r( p->nodes[ !s ] );
-	}
-}
-
-/*
-=============
-FindAreas_r
-
-Just decend the tree, and for each node that hasn't had an
-area set, flood fill out from there
-=============
-*/
-void FindAreas_r( node_t *node )
-{
-	if( node->planenum != PLANENUM_LEAF )
-	{
-		FindAreas_r( node->children[ 0 ] );
-		FindAreas_r( node->children[ 1 ] );
-		return;
-	}
-	
-	if( node->opaque || node->areaportal || node->area != -1 )
-		return;
-	
-	FloodAreas_r( node );
-	c_areas++;
-}
-
-/*
-=============
-CheckAreas_r
-=============
-*/
-void CheckAreas_r (node_t *node)
-{
-	brush_t	*b;
-
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		CheckAreas_r (node->children[0]);
-		CheckAreas_r (node->children[1]);
-		return;
-	}
-
-	if (node->opaque)
-		return;
-
-	if (node->cluster != -1)
-		if (node->area == -1)
-			Sys_Printf("WARNING: cluster %d has area set to -1\n", node->cluster);
-	if (node->areaportal)
-	{
-		b = node->brushlist->original;
-
-		// check if the areaportal touches two areas
-		if (b->portalareas[0] == -1 || b->portalareas[1] == -1)
-			Sys_Printf ("WARNING: areaportal brush %i doesn't touch two areas\n", b->brushNum);
-	}
-}
-
-
-
-/*
-FloodSkyboxArea_r() - ydnar
-sets all nodes with the skybox area to skybox
-*/
-
-void FloodSkyboxArea_r( node_t *node )
-{
-	if( skyboxArea < 0 )
-		return;
-	
-	if( node->planenum != PLANENUM_LEAF )
-	{
-		FloodSkyboxArea_r( node->children[ 0 ] );
-		FloodSkyboxArea_r( node->children[ 1 ] );
-		return;
-	}
-	
-	if( node->opaque || node->area != skyboxArea )
-		return;
-	
-	node->skybox = qtrue;
-}
-
-
-
-/*
-FloodAreas()
-mark each leaf with an area, bounded by C_AREAPORTAL
-*/
-
-void FloodAreas( tree_t *tree )
-{
-	Sys_FPrintf( SYS_VRB,"--- FloodAreas ---\n" );
-	FindAreas_r( tree->headnode );
-	
-	/* ydnar: flood all skybox nodes */
-	FloodSkyboxArea_r( tree->headnode );
-	
-	/* check for areaportal brushes that don't touch two areas */
-	/* ydnar: fix this rather than just silence the warnings */
-	//%	CheckAreas_r( tree->headnode );
-
-	Sys_FPrintf( SYS_VRB, "%9d areas\n", c_areas );
-}
-
-
-
-//======================================================
-
-int		c_outside;
-int		c_inside;
-int		c_solid;
-
-void FillOutside_r (node_t *node)
-{
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		FillOutside_r (node->children[0]);
-		FillOutside_r (node->children[1]);
-		return;
-	}
-
-	// anything not reachable by an entity
-	// can be filled away
-	if (!node->occupied) {
-		if ( !node->opaque ) {
-			c_outside++;
-			node->opaque = qtrue;
-		} else {
-			c_solid++;
-		}
-	} else {
-		c_inside++;
-	}
-
-}
-
-/*
-=============
-FillOutside
-
-Fill all nodes that can't be reached by entities
-=============
-*/
-void FillOutside (node_t *headnode)
-{
-	c_outside = 0;
-	c_inside = 0;
-	c_solid = 0;
-	Sys_FPrintf( SYS_VRB,"--- FillOutside ---\n" );
-	FillOutside_r( headnode );
-	Sys_FPrintf( SYS_VRB,"%9d solid leafs\n", c_solid );
-	Sys_Printf( "%9d leafs filled\n", c_outside );
-	Sys_FPrintf( SYS_VRB, "%9d inside leafs\n", c_inside );
-}
-
-
-//==============================================================
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PORTALS_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* ydnar: to fix broken portal windings */
+extern qboolean FixWinding( winding_t *w );
+
+
+int		c_active_portals;
+int		c_peak_portals;
+int		c_boundary;
+int		c_boundary_sides;
+
+/*
+===========
+AllocPortal
+===========
+*/
+portal_t *AllocPortal (void)
+{
+	portal_t	*p;
+	
+	if (numthreads == 1)
+		c_active_portals++;
+	if (c_active_portals > c_peak_portals)
+		c_peak_portals = c_active_portals;
+	
+	p = safe_malloc (sizeof(portal_t));
+	memset (p, 0, sizeof(portal_t));
+	
+	return p;
+}
+
+void FreePortal (portal_t *p)
+{
+	if (p->winding)
+		FreeWinding (p->winding);
+	if (numthreads == 1)
+		c_active_portals--;
+	free (p);
+}
+
+
+
+/*
+PortalPassable
+returns true if the portal has non-opaque leafs on both sides
+*/
+
+qboolean PortalPassable( portal_t *p )
+{
+	/* is this to global outside leaf? */
+	if( !p->onnode )
+		return qfalse;
+	
+	/* this should never happen */
+	if( p->nodes[ 0 ]->planenum != PLANENUM_LEAF ||
+		p->nodes[ 1 ]->planenum != PLANENUM_LEAF )
+		Error( "Portal_EntityFlood: not a leaf" );
+	
+	/* ydnar: added antiportal to supress portal generation for visibility blocking */
+	if( p->compileFlags & C_ANTIPORTAL )
+		return qfalse;
+	
+	/* both leaves on either side of the portal must be passable */
+	if( p->nodes[ 0 ]->opaque == qfalse && p->nodes[ 1 ]->opaque == qfalse )
+		return qtrue;
+	
+	/* otherwise this isn't a passable portal */
+	return qfalse;
+}
+
+
+
+
+int		c_tinyportals;
+int		c_badportals;	/* ydnar */
+
+/*
+=============
+AddPortalToNodes
+=============
+*/
+void AddPortalToNodes (portal_t *p, node_t *front, node_t *back)
+{
+	if (p->nodes[0] || p->nodes[1])
+		Error ("AddPortalToNode: allready included");
+
+	p->nodes[0] = front;
+	p->next[0] = front->portals;
+	front->portals = p;
+	
+	p->nodes[1] = back;
+	p->next[1] = back->portals;
+	back->portals = p;
+}
+
+
+/*
+=============
+RemovePortalFromNode
+=============
+*/
+void RemovePortalFromNode (portal_t *portal, node_t *l)
+{
+	portal_t	**pp, *t;
+	
+// remove reference to the current portal
+	pp = &l->portals;
+	while (1)
+	{
+		t = *pp;
+		if (!t)
+			Error ("RemovePortalFromNode: portal not in leaf");	
+
+		if ( t == portal )
+			break;
+
+		if (t->nodes[0] == l)
+			pp = &t->next[0];
+		else if (t->nodes[1] == l)
+			pp = &t->next[1];
+		else
+			Error ("RemovePortalFromNode: portal not bounding leaf");
+	}
+	
+	if (portal->nodes[0] == l)
+	{
+		*pp = portal->next[0];
+		portal->nodes[0] = NULL;
+	}
+	else if (portal->nodes[1] == l)
+	{
+		*pp = portal->next[1];	
+		portal->nodes[1] = NULL;
+	}
+}
+
+//============================================================================
+
+void PrintPortal (portal_t *p)
+{
+	int			i;
+	winding_t	*w;
+	
+	w = p->winding;
+	for (i=0 ; i<w->numpoints ; i++)
+		Sys_Printf ("(%5.0f,%5.0f,%5.0f)\n",w->p[i][0]
+		, w->p[i][1], w->p[i][2]);
+}
+
+/*
+================
+MakeHeadnodePortals
+
+The created portals will face the global outside_node
+================
+*/
+#define	SIDESPACE	8
+void MakeHeadnodePortals (tree_t *tree)
+{
+	vec3_t		bounds[2];
+	int			i, j, n;
+	portal_t	*p, *portals[6];
+	plane_t		bplanes[6], *pl;
+	node_t *node;
+
+	node = tree->headnode;
+
+// pad with some space so there will never be null volume leafs
+	for (i=0 ; i<3 ; i++)
+	{
+		bounds[0][i] = tree->mins[i] - SIDESPACE;
+		bounds[1][i] = tree->maxs[i] + SIDESPACE;
+		if ( bounds[0][i] >= bounds[1][i] ) {
+			Error( "Backwards tree volume" );
+		}
+	}
+	
+	tree->outside_node.planenum = PLANENUM_LEAF;
+	tree->outside_node.brushlist = NULL;
+	tree->outside_node.portals = NULL;
+	tree->outside_node.opaque = qfalse;
+
+	for (i=0 ; i<3 ; i++)
+		for (j=0 ; j<2 ; j++)
+		{
+			n = j*3 + i;
+
+			p = AllocPortal ();
+			portals[n] = p;
+			
+			pl = &bplanes[n];
+			memset (pl, 0, sizeof(*pl));
+			if (j)
+			{
+				pl->normal[i] = -1;
+				pl->dist = -bounds[j][i];
+			}
+			else
+			{
+				pl->normal[i] = 1;
+				pl->dist = bounds[j][i];
+			}
+			p->plane = *pl;
+			p->winding = BaseWindingForPlane (pl->normal, pl->dist);
+			AddPortalToNodes (p, node, &tree->outside_node);
+		}
+		
+// clip the basewindings by all the other planes
+	for (i=0 ; i<6 ; i++)
+	{
+		for (j=0 ; j<6 ; j++)
+		{
+			if (j == i)
+				continue;
+			ChopWindingInPlace (&portals[i]->winding, bplanes[j].normal, bplanes[j].dist, ON_EPSILON);
+		}
+	}
+}
+
+//===================================================
+
+
+/*
+================
+BaseWindingForNode
+================
+*/
+#define	BASE_WINDING_EPSILON	0.001
+#define	SPLIT_WINDING_EPSILON	0.001
+
+winding_t	*BaseWindingForNode (node_t *node)
+{
+	winding_t	*w;
+	node_t		*n;
+	plane_t		*plane;
+	vec3_t		normal;
+	vec_t		dist;
+
+	w = BaseWindingForPlane (mapplanes[node->planenum].normal
+		, mapplanes[node->planenum].dist);
+
+	// clip by all the parents
+	for (n=node->parent ; n && w ; )
+	{
+		plane = &mapplanes[n->planenum];
+
+		if (n->children[0] == node)
+		{	// take front
+			ChopWindingInPlace (&w, plane->normal, plane->dist, BASE_WINDING_EPSILON);
+		}
+		else
+		{	// take back
+			VectorSubtract (vec3_origin, plane->normal, normal);
+			dist = -plane->dist;
+			ChopWindingInPlace (&w, normal, dist, BASE_WINDING_EPSILON);
+		}
+		node = n;
+		n = n->parent;
+	}
+
+	return w;
+}
+
+//============================================================
+
+/*
+==================
+MakeNodePortal
+
+create the new portal by taking the full plane winding for the cutting plane
+and clipping it by all of parents of this node
+==================
+*/
+void MakeNodePortal (node_t *node)
+{
+	portal_t	*new_portal, *p;
+	winding_t	*w;
+	vec3_t		normal;
+	float		dist;
+	int			side;
+
+	w = BaseWindingForNode (node);
+
+	// clip the portal by all the other portals in the node
+	for (p = node->portals ; p && w; p = p->next[side])	
+	{
+		if (p->nodes[0] == node)
+		{
+			side = 0;
+			VectorCopy (p->plane.normal, normal);
+			dist = p->plane.dist;
+		}
+		else if (p->nodes[1] == node)
+		{
+			side = 1;
+			VectorSubtract (vec3_origin, p->plane.normal, normal);
+			dist = -p->plane.dist;
+		}
+		else
+			Error ("CutNodePortals_r: mislinked portal");
+
+		ChopWindingInPlace (&w, normal, dist, CLIP_EPSILON);
+	}
+
+	if (!w)
+	{
+		return;
+	}
+	
+	
+	/* ydnar: adding this here to fix degenerate windings */
+	#if 0
+	if( FixWinding( w ) == qfalse )
+	{
+		c_badportals++;
+		FreeWinding( w );
+		return;
+	}
+	#endif
+	
+	if (WindingIsTiny (w))
+	{
+		c_tinyportals++;
+		FreeWinding (w);
+		return;
+	}
+
+	new_portal = AllocPortal ();
+	new_portal->plane = mapplanes[node->planenum];
+	new_portal->onnode = node;
+	new_portal->winding = w;
+	new_portal->compileFlags = node->compileFlags;
+	AddPortalToNodes (new_portal, node->children[0], node->children[1]);
+}
+
+
+/*
+==============
+SplitNodePortals
+
+Move or split the portals that bound node so that the node's
+children have portals instead of node.
+==============
+*/
+void SplitNodePortals (node_t *node)
+{
+	portal_t	*p, *next_portal, *new_portal;
+	node_t		*f, *b, *other_node;
+	int			side;
+	plane_t		*plane;
+	winding_t	*frontwinding, *backwinding;
+
+	plane = &mapplanes[node->planenum];
+	f = node->children[0];
+	b = node->children[1];
+
+	for (p = node->portals ; p ; p = next_portal)	
+	{
+		if (p->nodes[0] == node)
+			side = 0;
+		else if (p->nodes[1] == node)
+			side = 1;
+		else
+			Error ("SplitNodePortals: mislinked portal");
+		next_portal = p->next[side];
+
+		other_node = p->nodes[!side];
+		RemovePortalFromNode (p, p->nodes[0]);
+		RemovePortalFromNode (p, p->nodes[1]);
+
+//
+// cut the portal into two portals, one on each side of the cut plane
+//
+		ClipWindingEpsilon (p->winding, plane->normal, plane->dist,
+			SPLIT_WINDING_EPSILON, &frontwinding, &backwinding);
+
+		if (frontwinding && WindingIsTiny(frontwinding))
+		{
+			if (!f->tinyportals)
+				VectorCopy(frontwinding->p[0], f->referencepoint);
+			f->tinyportals++;
+			if (!other_node->tinyportals)
+				VectorCopy(frontwinding->p[0], other_node->referencepoint);
+			other_node->tinyportals++;
+
+			FreeWinding (frontwinding);
+			frontwinding = NULL;
+			c_tinyportals++;
+		}
+
+		if (backwinding && WindingIsTiny(backwinding))
+		{
+			if (!b->tinyportals)
+				VectorCopy(backwinding->p[0], b->referencepoint);
+			b->tinyportals++;
+			if (!other_node->tinyportals)
+				VectorCopy(backwinding->p[0], other_node->referencepoint);
+			other_node->tinyportals++;
+
+			FreeWinding (backwinding);
+			backwinding = NULL;
+			c_tinyportals++;
+		}
+
+		if (!frontwinding && !backwinding)
+		{	// tiny windings on both sides
+			continue;
+		}
+
+		if (!frontwinding)
+		{
+			FreeWinding (backwinding);
+			if (side == 0)
+				AddPortalToNodes (p, b, other_node);
+			else
+				AddPortalToNodes (p, other_node, b);
+			continue;
+		}
+		if (!backwinding)
+		{
+			FreeWinding (frontwinding);
+			if (side == 0)
+				AddPortalToNodes (p, f, other_node);
+			else
+				AddPortalToNodes (p, other_node, f);
+			continue;
+		}
+		
+	// the winding is split
+		new_portal = AllocPortal ();
+		*new_portal = *p;
+		new_portal->winding = backwinding;
+		FreeWinding (p->winding);
+		p->winding = frontwinding;
+
+		if (side == 0)
+		{
+			AddPortalToNodes (p, f, other_node);
+			AddPortalToNodes (new_portal, b, other_node);
+		}
+		else
+		{
+			AddPortalToNodes (p, other_node, f);
+			AddPortalToNodes (new_portal, other_node, b);
+		}
+	}
+
+	node->portals = NULL;
+}
+
+
+/*
+================
+CalcNodeBounds
+================
+*/
+void CalcNodeBounds (node_t *node)
+{
+	portal_t	*p;
+	int			s;
+	int			i;
+
+	// calc mins/maxs for both leafs and nodes
+	ClearBounds (node->mins, node->maxs);
+	for (p = node->portals ; p ; p = p->next[s])	
+	{
+		s = (p->nodes[1] == node);
+		for (i=0 ; i<p->winding->numpoints ; i++)
+			AddPointToBounds (p->winding->p[i], node->mins, node->maxs);
+	}
+}
+
+/*
+==================
+MakeTreePortals_r
+==================
+*/
+void MakeTreePortals_r (node_t *node)
+{
+	int		i;
+
+	CalcNodeBounds (node);
+	if (node->mins[0] >= node->maxs[0])
+	{
+		Sys_Printf ("WARNING: node without a volume\n");
+		Sys_Printf("node has %d tiny portals\n", node->tinyportals);
+		Sys_Printf("node reference point %1.2f %1.2f %1.2f\n", node->referencepoint[0],
+															node->referencepoint[1],
+															node->referencepoint[2]);
+	}
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (node->mins[i] < MIN_WORLD_COORD || node->maxs[i] > MAX_WORLD_COORD)
+		{
+      if(node->portals && node->portals->winding)
+        xml_Winding("WARNING: Node With Unbounded Volume", node->portals->winding->p, node->portals->winding->numpoints, qfalse);
+
+			break;
+		}
+	}
+	if (node->planenum == PLANENUM_LEAF)
+		return;
+
+	MakeNodePortal (node);
+	SplitNodePortals (node);
+
+	MakeTreePortals_r (node->children[0]);
+	MakeTreePortals_r (node->children[1]);
+}
+
+/*
+==================
+MakeTreePortals
+==================
+*/
+void MakeTreePortals (tree_t *tree)
+{
+	Sys_FPrintf (SYS_VRB, "--- MakeTreePortals ---\n");
+	MakeHeadnodePortals (tree);
+	MakeTreePortals_r (tree->headnode);
+	Sys_FPrintf( SYS_VRB, "%9d tiny portals\n", c_tinyportals );
+	Sys_FPrintf( SYS_VRB, "%9d bad portals\n", c_badportals );	/* ydnar */
+}
+
+/*
+=========================================================
+
+FLOOD ENTITIES
+
+=========================================================
+*/
+
+int		c_floodedleafs;
+
+/*
+=============
+FloodPortals_r
+=============
+*/
+
+void FloodPortals_r( node_t *node, int dist, qboolean skybox )
+{
+	int			s;
+	portal_t	*p;
+	
+	
+	if( skybox )
+		node->skybox = skybox;
+	
+	if( node->occupied || node->opaque )
+		return;
+	
+	c_floodedleafs++;
+	node->occupied = dist;
+	
+	for( p = node->portals; p; p = p->next[ s ] )
+	{
+		s = (p->nodes[ 1 ] == node);
+		FloodPortals_r( p->nodes[ !s ], dist + 1, skybox );
+	}
+}
+
+
+
+/*
+=============
+PlaceOccupant
+=============
+*/
+
+qboolean PlaceOccupant( node_t *headnode, vec3_t origin, entity_t *occupant, qboolean skybox )
+{
+	vec_t	d;
+	node_t	*node;
+	plane_t	*plane;
+	
+	
+	// find the leaf to start in
+	node = headnode;
+	while( node->planenum != PLANENUM_LEAF )
+	{
+		plane = &mapplanes[ node->planenum ];
+		d = DotProduct( origin, plane->normal ) - plane->dist;
+		if( d >= 0 )
+			node = node->children[ 0 ];
+		else
+			node = node->children[ 1 ];
+	}
+	
+	if( node->opaque )
+		return qfalse;
+	node->occupant = occupant;
+	node->skybox = skybox;
+	
+	FloodPortals_r( node, 1, skybox );
+	
+	return qtrue;
+}
+
+/*
+=============
+FloodEntities
+
+Marks all nodes that can be reached by entites
+=============
+*/
+
+qboolean FloodEntities( tree_t *tree )
+{
+	int			i, s;
+	vec3_t		origin, offset, scale, angles;
+	qboolean	r, inside, tripped, skybox;
+	node_t		*headnode;
+	entity_t	*e;
+	const char	*value;
+	
+	
+	headnode = tree->headnode;
+	Sys_FPrintf( SYS_VRB,"--- FloodEntities ---\n" );
+	inside = qfalse;
+	tree->outside_node.occupied = 0;
+	
+	tripped = qfalse;
+	c_floodedleafs = 0;
+	for( i = 1; i < numEntities; i++ )
+	{
+		/* get entity */
+		e = &entities[ i ];
+		
+		/* get origin */
+		GetVectorForKey( e, "origin", origin );
+		if( VectorCompare( origin, vec3_origin ) ) 
+			continue;
+		
+		/* handle skybox entities */
+		value = ValueForKey( e, "classname" );
+		if( !Q_stricmp( value, "_skybox" ) )
+		{
+			skybox = qtrue;
+			skyboxPresent = qtrue;
+			
+			/* invert origin */
+			VectorScale( origin, -1.0f, offset );
+			
+			/* get scale */
+			VectorSet( scale, 64.0f, 64.0f, 64.0f );
+			value = ValueForKey( e, "_scale" );
+			if( value[ 0 ] != '\0' )
+			{
+				s = sscanf( value, "%f %f %f", &scale[ 0 ], &scale[ 1 ], &scale[ 2 ] );
+				if( s == 1 )
+				{
+					scale[ 1 ] = scale[ 0 ];
+					scale[ 2 ] = scale[ 0 ];
+				}
+			}
+			
+			/* get "angle" (yaw) or "angles" (pitch yaw roll) */
+			VectorClear( angles );
+			angles[ 2 ] = FloatForKey( e, "angle" );
+			value = ValueForKey( e, "angles" );
+			if( value[ 0 ] != '\0' )
+				sscanf( value, "%f %f %f", &angles[ 1 ], &angles[ 2 ], &angles[ 0 ] );
+			
+			/* set transform matrix (thanks spog) */
+			m4x4_identity( skyboxTransform );
+			m4x4_pivoted_transform_by_vec3( skyboxTransform, offset, angles, eXYZ, scale, origin );
+		}
+		else
+			skybox = qfalse;
+		
+		/* nudge off floor */
+		origin[ 2 ] += 1;
+		
+		/* debugging code */
+		//%	if( i == 1 )
+		//%		origin[ 2 ] += 4096;
+		
+		/* find leaf */
+		r = PlaceOccupant( headnode, origin, e, skybox );
+		if( r )
+			inside = qtrue;
+		if( (!r || tree->outside_node.occupied) && !tripped )
+		{
+			xml_Select( "Entity leaked", e->mapEntityNum, 0, qfalse );
+			tripped = qtrue;
+		}
+	}
+	
+	Sys_FPrintf( SYS_VRB, "%9d flooded leafs\n", c_floodedleafs );
+	
+	if( !inside )
+		Sys_FPrintf( SYS_VRB, "no entities in open -- no filling\n" );
+	else if( tree->outside_node.occupied )
+		Sys_FPrintf( SYS_VRB, "entity reached from outside -- no filling\n" );
+	
+	return (qboolean) (inside && !tree->outside_node.occupied);
+}
+
+/*
+=========================================================
+
+FLOOD AREAS
+
+=========================================================
+*/
+
+int		c_areas;
+
+
+
+/*
+FloodAreas_r()
+floods through leaf portals to tag leafs with an area
+*/
+
+void FloodAreas_r( node_t *node )
+{
+	int			s;
+	portal_t	*p;
+	brush_t		*b;
+	
+	
+	if( node->areaportal )
+	{
+		if( node->area == -1 )
+			node->area = c_areas;
+		
+		/* this node is part of an area portal brush */
+		b = node->brushlist->original;
+
+		/* if the current area has already touched this portal, we are done */
+		if( b->portalareas[ 0 ] == c_areas || b->portalareas[ 1 ] == c_areas )
+			return;
+		
+		// note the current area as bounding the portal
+		if( b->portalareas[ 1 ] != -1 )
+		{
+			Sys_Printf( "WARNING: areaportal brush %i touches > 2 areas\n", b->brushNum );
+			return;
+		}
+		if( b->portalareas[ 0 ] != -1 )
+			b->portalareas[ 1 ] = c_areas;
+		else
+			b->portalareas[ 0 ] = c_areas;
+		
+		return;
+	}
+
+	if( node->area != -1 )
+		return;	
+	if( node->cluster == -1 )
+		return;
+
+	node->area = c_areas;
+	
+	/* ydnar: skybox nodes set the skybox area */
+	if( node->skybox )
+		skyboxArea = c_areas;
+	
+	for( p = node->portals; p; p = p->next[ s ] )
+	{
+		s = (p->nodes[1] == node);
+		
+		/* ydnar: allow areaportal portals to block area flow */
+		if( p->compileFlags & C_AREAPORTAL )
+			continue;
+		
+		if( !PortalPassable( p ) )
+			continue;
+		
+		FloodAreas_r( p->nodes[ !s ] );
+	}
+}
+
+/*
+=============
+FindAreas_r
+
+Just decend the tree, and for each node that hasn't had an
+area set, flood fill out from there
+=============
+*/
+void FindAreas_r( node_t *node )
+{
+	if( node->planenum != PLANENUM_LEAF )
+	{
+		FindAreas_r( node->children[ 0 ] );
+		FindAreas_r( node->children[ 1 ] );
+		return;
+	}
+	
+	if( node->opaque || node->areaportal || node->area != -1 )
+		return;
+	
+	FloodAreas_r( node );
+	c_areas++;
+}
+
+/*
+=============
+CheckAreas_r
+=============
+*/
+void CheckAreas_r (node_t *node)
+{
+	brush_t	*b;
+
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		CheckAreas_r (node->children[0]);
+		CheckAreas_r (node->children[1]);
+		return;
+	}
+
+	if (node->opaque)
+		return;
+
+	if (node->cluster != -1)
+		if (node->area == -1)
+			Sys_Printf("WARNING: cluster %d has area set to -1\n", node->cluster);
+	if (node->areaportal)
+	{
+		b = node->brushlist->original;
+
+		// check if the areaportal touches two areas
+		if (b->portalareas[0] == -1 || b->portalareas[1] == -1)
+			Sys_Printf ("WARNING: areaportal brush %i doesn't touch two areas\n", b->brushNum);
+	}
+}
+
+
+
+/*
+FloodSkyboxArea_r() - ydnar
+sets all nodes with the skybox area to skybox
+*/
+
+void FloodSkyboxArea_r( node_t *node )
+{
+	if( skyboxArea < 0 )
+		return;
+	
+	if( node->planenum != PLANENUM_LEAF )
+	{
+		FloodSkyboxArea_r( node->children[ 0 ] );
+		FloodSkyboxArea_r( node->children[ 1 ] );
+		return;
+	}
+	
+	if( node->opaque || node->area != skyboxArea )
+		return;
+	
+	node->skybox = qtrue;
+}
+
+
+
+/*
+FloodAreas()
+mark each leaf with an area, bounded by C_AREAPORTAL
+*/
+
+void FloodAreas( tree_t *tree )
+{
+	Sys_FPrintf( SYS_VRB,"--- FloodAreas ---\n" );
+	FindAreas_r( tree->headnode );
+	
+	/* ydnar: flood all skybox nodes */
+	FloodSkyboxArea_r( tree->headnode );
+	
+	/* check for areaportal brushes that don't touch two areas */
+	/* ydnar: fix this rather than just silence the warnings */
+	//%	CheckAreas_r( tree->headnode );
+
+	Sys_FPrintf( SYS_VRB, "%9d areas\n", c_areas );
+}
+
+
+
+//======================================================
+
+int		c_outside;
+int		c_inside;
+int		c_solid;
+
+void FillOutside_r (node_t *node)
+{
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		FillOutside_r (node->children[0]);
+		FillOutside_r (node->children[1]);
+		return;
+	}
+
+	// anything not reachable by an entity
+	// can be filled away
+	if (!node->occupied) {
+		if ( !node->opaque ) {
+			c_outside++;
+			node->opaque = qtrue;
+		} else {
+			c_solid++;
+		}
+	} else {
+		c_inside++;
+	}
+
+}
+
+/*
+=============
+FillOutside
+
+Fill all nodes that can't be reached by entities
+=============
+*/
+void FillOutside (node_t *headnode)
+{
+	c_outside = 0;
+	c_inside = 0;
+	c_solid = 0;
+	Sys_FPrintf( SYS_VRB,"--- FillOutside ---\n" );
+	FillOutside_r( headnode );
+	Sys_FPrintf( SYS_VRB,"%9d solid leafs\n", c_solid );
+	Sys_Printf( "%9d leafs filled\n", c_outside );
+	Sys_FPrintf( SYS_VRB, "%9d inside leafs\n", c_inside );
+}
+
+
+//==============================================================
+
diff --git a/tools/quake3/q3map2/prtfile.c b/tools/quake3/q3map2/prtfile.c
index ab7c5304..43fcbb03 100644
--- a/tools/quake3/q3map2/prtfile.c
+++ b/tools/quake3/q3map2/prtfile.c
@@ -1,291 +1,291 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define PRTFILE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-==============================================================================
-
-PORTAL FILE GENERATION
-
-Save out name.prt for qvis to read
-==============================================================================
-*/
-
-
-#define	PORTALFILE	"PRT1"
-
-FILE	*pf;
-int		num_visclusters;				// clusters the player can be in
-int		num_visportals;
-int		num_solidfaces;
-
-void WriteFloat (FILE *f, vec_t v)
-{
-	if ( fabs(v - Q_rint(v)) < 0.001 )
-		fprintf (f,"%i ",(int)Q_rint(v));
-	else
-		fprintf (f,"%f ",v);
-}
-
-/*
-=================
-WritePortalFile_r
-=================
-*/
-void WritePortalFile_r (node_t *node)
-{
-	int			i, s;	
-	portal_t	*p;
-	winding_t	*w;
-	vec3_t		normal;
-	vec_t		dist;
-
-	// decision node
-	if (node->planenum != PLANENUM_LEAF) {
-		WritePortalFile_r (node->children[0]);
-		WritePortalFile_r (node->children[1]);
-		return;
-	}
-	
-	if (node->opaque) {
-		return;
-	}
-
-	for (p = node->portals ; p ; p=p->next[s])
-	{
-		w = p->winding;
-		s = (p->nodes[1] == node);
-		if (w && p->nodes[0] == node)
-		{
-			if (!PortalPassable(p))
-				continue;
-			// write out to the file
-			
-			// sometimes planes get turned around when they are very near
-			// the changeover point between different axis.  interpret the
-			// plane the same way vis will, and flip the side orders if needed
-			// FIXME: is this still relevent?
-			WindingPlane (w, normal, &dist);
-			if ( DotProduct (p->plane.normal, normal) < 0.99 )
-			{	// backwards...
-				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
-			}
-			else
-				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
-			
-			/* ydnar: added this change to make antiportals work */
-			if( p->compileFlags & C_HINT )
-				fprintf( pf, "1 " );
-			else
-				fprintf( pf, "0 " );
-			
-			/* write the winding */
-			for (i=0 ; i<w->numpoints ; i++)
-			{
-				fprintf (pf,"(");
-				WriteFloat (pf, w->p[i][0]);
-				WriteFloat (pf, w->p[i][1]);
-				WriteFloat (pf, w->p[i][2]);
-				fprintf (pf,") ");
-			}
-			fprintf (pf,"\n");
-		}
-	}
-
-}
-
-/*
-=================
-WriteFaceFile_r
-=================
-*/
-void WriteFaceFile_r (node_t *node)
-{
-	int			i, s;	
-	portal_t	*p;
-	winding_t	*w;
-
-	// decision node
-	if (node->planenum != PLANENUM_LEAF) {
-		WriteFaceFile_r (node->children[0]);
-		WriteFaceFile_r (node->children[1]);
-		return;
-	}
-	
-	if (node->opaque) {
-		return;
-	}
-
-	for (p = node->portals ; p ; p=p->next[s])
-	{
-		w = p->winding;
-		s = (p->nodes[1] == node);
-		if (w)
-		{
-			if (PortalPassable(p))
-				continue;
-			// write out to the file
-
-			if (p->nodes[0] == node)
-			{
-				fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
-				for (i=0 ; i<w->numpoints ; i++)
-				{
-					fprintf (pf,"(");
-					WriteFloat (pf, w->p[i][0]);
-					WriteFloat (pf, w->p[i][1]);
-					WriteFloat (pf, w->p[i][2]);
-					fprintf (pf,") ");
-				}
-				fprintf (pf,"\n");
-			}
-			else
-			{
-				fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
-				for (i = w->numpoints-1; i >= 0; i--)
-				{
-					fprintf (pf,"(");
-					WriteFloat (pf, w->p[i][0]);
-					WriteFloat (pf, w->p[i][1]);
-					WriteFloat (pf, w->p[i][2]);
-					fprintf (pf,") ");
-				}
-				fprintf (pf,"\n");
-			}
-		}
-	}
-}
-
-/*
-================
-NumberLeafs_r
-================
-*/
-void NumberLeafs_r (node_t *node)
-{
-	portal_t	*p;
-
-	if ( node->planenum != PLANENUM_LEAF ) {
-		// decision node
-		node->cluster = -99;
-		NumberLeafs_r (node->children[0]);
-		NumberLeafs_r (node->children[1]);
-		return;
-	}
-	
-	node->area = -1;
-
-	if ( node->opaque ) {
-		// solid block, viewpoint never inside
-		node->cluster = -1;
-		return;
-	}
-
-	node->cluster = num_visclusters;
-	num_visclusters++;
-
-	// count the portals
-	for (p = node->portals ; p ; )
-	{
-		if (p->nodes[0] == node)		// only write out from first leaf
-		{
-			if (PortalPassable(p))
-				num_visportals++;
-			else
-				num_solidfaces++;
-			p = p->next[0];
-		}
-		else
-		{
-			if (!PortalPassable(p))
-				num_solidfaces++;
-			p = p->next[1];		
-		}
-	}
-}
-
-
-/*
-================
-NumberClusters
-================
-*/
-void NumberClusters(tree_t *tree) {
-	num_visclusters = 0;
-	num_visportals = 0;
-	num_solidfaces = 0;
-
-	Sys_FPrintf (SYS_VRB,"--- NumberClusters ---\n");
-	
-	// set the cluster field in every leaf and count the total number of portals
-	NumberLeafs_r (tree->headnode);
-
-	Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
-	Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
-	Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
-}
-
-/*
-================
-WritePortalFile
-================
-*/
-void WritePortalFile (tree_t *tree)
-{
-	char	filename[1024];
-
-	Sys_FPrintf (SYS_VRB,"--- WritePortalFile ---\n");
-	
-	// write the file
-	sprintf (filename, "%s.prt", source);
-	Sys_Printf ("writing %s\n", filename);
-	pf = fopen (filename, "w");
-	if (!pf)
-		Error ("Error opening %s", filename);
-		
-	fprintf (pf, "%s\n", PORTALFILE);
-	fprintf (pf, "%i\n", num_visclusters);
-	fprintf (pf, "%i\n", num_visportals);
-	fprintf (pf, "%i\n", num_solidfaces);
-
-	WritePortalFile_r(tree->headnode);
-	WriteFaceFile_r(tree->headnode);
-
-	fclose (pf);
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define PRTFILE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+==============================================================================
+
+PORTAL FILE GENERATION
+
+Save out name.prt for qvis to read
+==============================================================================
+*/
+
+
+#define	PORTALFILE	"PRT1"
+
+FILE	*pf;
+int		num_visclusters;				// clusters the player can be in
+int		num_visportals;
+int		num_solidfaces;
+
+void WriteFloat (FILE *f, vec_t v)
+{
+	if ( fabs(v - Q_rint(v)) < 0.001 )
+		fprintf (f,"%i ",(int)Q_rint(v));
+	else
+		fprintf (f,"%f ",v);
+}
+
+/*
+=================
+WritePortalFile_r
+=================
+*/
+void WritePortalFile_r (node_t *node)
+{
+	int			i, s;	
+	portal_t	*p;
+	winding_t	*w;
+	vec3_t		normal;
+	vec_t		dist;
+
+	// decision node
+	if (node->planenum != PLANENUM_LEAF) {
+		WritePortalFile_r (node->children[0]);
+		WritePortalFile_r (node->children[1]);
+		return;
+	}
+	
+	if (node->opaque) {
+		return;
+	}
+
+	for (p = node->portals ; p ; p=p->next[s])
+	{
+		w = p->winding;
+		s = (p->nodes[1] == node);
+		if (w && p->nodes[0] == node)
+		{
+			if (!PortalPassable(p))
+				continue;
+			// write out to the file
+			
+			// sometimes planes get turned around when they are very near
+			// the changeover point between different axis.  interpret the
+			// plane the same way vis will, and flip the side orders if needed
+			// FIXME: is this still relevent?
+			WindingPlane (w, normal, &dist);
+			if ( DotProduct (p->plane.normal, normal) < 0.99 )
+			{	// backwards...
+				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[1]->cluster, p->nodes[0]->cluster);
+			}
+			else
+				fprintf (pf,"%i %i %i ",w->numpoints, p->nodes[0]->cluster, p->nodes[1]->cluster);
+			
+			/* ydnar: added this change to make antiportals work */
+			if( p->compileFlags & C_HINT )
+				fprintf( pf, "1 " );
+			else
+				fprintf( pf, "0 " );
+			
+			/* write the winding */
+			for (i=0 ; i<w->numpoints ; i++)
+			{
+				fprintf (pf,"(");
+				WriteFloat (pf, w->p[i][0]);
+				WriteFloat (pf, w->p[i][1]);
+				WriteFloat (pf, w->p[i][2]);
+				fprintf (pf,") ");
+			}
+			fprintf (pf,"\n");
+		}
+	}
+
+}
+
+/*
+=================
+WriteFaceFile_r
+=================
+*/
+void WriteFaceFile_r (node_t *node)
+{
+	int			i, s;	
+	portal_t	*p;
+	winding_t	*w;
+
+	// decision node
+	if (node->planenum != PLANENUM_LEAF) {
+		WriteFaceFile_r (node->children[0]);
+		WriteFaceFile_r (node->children[1]);
+		return;
+	}
+	
+	if (node->opaque) {
+		return;
+	}
+
+	for (p = node->portals ; p ; p=p->next[s])
+	{
+		w = p->winding;
+		s = (p->nodes[1] == node);
+		if (w)
+		{
+			if (PortalPassable(p))
+				continue;
+			// write out to the file
+
+			if (p->nodes[0] == node)
+			{
+				fprintf (pf,"%i %i ",w->numpoints, p->nodes[0]->cluster);
+				for (i=0 ; i<w->numpoints ; i++)
+				{
+					fprintf (pf,"(");
+					WriteFloat (pf, w->p[i][0]);
+					WriteFloat (pf, w->p[i][1]);
+					WriteFloat (pf, w->p[i][2]);
+					fprintf (pf,") ");
+				}
+				fprintf (pf,"\n");
+			}
+			else
+			{
+				fprintf (pf,"%i %i ",w->numpoints, p->nodes[1]->cluster);
+				for (i = w->numpoints-1; i >= 0; i--)
+				{
+					fprintf (pf,"(");
+					WriteFloat (pf, w->p[i][0]);
+					WriteFloat (pf, w->p[i][1]);
+					WriteFloat (pf, w->p[i][2]);
+					fprintf (pf,") ");
+				}
+				fprintf (pf,"\n");
+			}
+		}
+	}
+}
+
+/*
+================
+NumberLeafs_r
+================
+*/
+void NumberLeafs_r (node_t *node)
+{
+	portal_t	*p;
+
+	if ( node->planenum != PLANENUM_LEAF ) {
+		// decision node
+		node->cluster = -99;
+		NumberLeafs_r (node->children[0]);
+		NumberLeafs_r (node->children[1]);
+		return;
+	}
+	
+	node->area = -1;
+
+	if ( node->opaque ) {
+		// solid block, viewpoint never inside
+		node->cluster = -1;
+		return;
+	}
+
+	node->cluster = num_visclusters;
+	num_visclusters++;
+
+	// count the portals
+	for (p = node->portals ; p ; )
+	{
+		if (p->nodes[0] == node)		// only write out from first leaf
+		{
+			if (PortalPassable(p))
+				num_visportals++;
+			else
+				num_solidfaces++;
+			p = p->next[0];
+		}
+		else
+		{
+			if (!PortalPassable(p))
+				num_solidfaces++;
+			p = p->next[1];		
+		}
+	}
+}
+
+
+/*
+================
+NumberClusters
+================
+*/
+void NumberClusters(tree_t *tree) {
+	num_visclusters = 0;
+	num_visportals = 0;
+	num_solidfaces = 0;
+
+	Sys_FPrintf (SYS_VRB,"--- NumberClusters ---\n");
+	
+	// set the cluster field in every leaf and count the total number of portals
+	NumberLeafs_r (tree->headnode);
+
+	Sys_FPrintf( SYS_VRB, "%9d visclusters\n", num_visclusters );
+	Sys_FPrintf( SYS_VRB, "%9d visportals\n", num_visportals );
+	Sys_FPrintf( SYS_VRB, "%9d solidfaces\n", num_solidfaces );
+}
+
+/*
+================
+WritePortalFile
+================
+*/
+void WritePortalFile (tree_t *tree)
+{
+	char	filename[1024];
+
+	Sys_FPrintf (SYS_VRB,"--- WritePortalFile ---\n");
+	
+	// write the file
+	sprintf (filename, "%s.prt", source);
+	Sys_Printf ("writing %s\n", filename);
+	pf = fopen (filename, "w");
+	if (!pf)
+		Error ("Error opening %s", filename);
+		
+	fprintf (pf, "%s\n", PORTALFILE);
+	fprintf (pf, "%i\n", num_visclusters);
+	fprintf (pf, "%i\n", num_visportals);
+	fprintf (pf, "%i\n", num_solidfaces);
+
+	WritePortalFile_r(tree->headnode);
+	WriteFaceFile_r(tree->headnode);
+
+	fclose (pf);
+}
+
diff --git a/tools/quake3/q3map2/q3map2.h b/tools/quake3/q3map2/q3map2.h
index 68ea5f6d..b3402c71 100644
--- a/tools/quake3/q3map2/q3map2.h
+++ b/tools/quake3/q3map2/q3map2.h
@@ -1,2276 +1,2276 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#ifndef Q3MAP2_H
-#define Q3MAP2_H
-
-
-
-/* version */
-#define Q3MAP_VERSION	"2.5.11"
-#define Q3MAP_MOTD		"A well-oiled toaster oven"
-
-
-
-/* -------------------------------------------------------------------------------
-
-dependencies
-
-------------------------------------------------------------------------------- */
-
-/* platform-specific */
-#if defined( __linux__ ) || defined( __APPLE__ )
-	#define Q_UNIX
-#endif
-
-#ifdef Q_UNIX
-	#include <unistd.h>
-	#include <pwd.h>
-	#include <limits.h>
-#endif
-
-#ifdef _WIN32
-	#include <windows.h>
-#endif
-
-
-/* general */
-#include "version.h"			/* ttimo: might want to guard that if built outside of the GtkRadiant tree */
-
-#include "cmdlib.h"
-#include "mathlib.h"
-#include "md5lib.h"
-#include "ddslib.h"
-
-#include "picomodel.h"
-
-#include "scriplib.h"
-#include "polylib.h"
-#include "imagelib.h"
-#include "qthreads.h"
-#include "inout.h"
-#include "vfs.h"
-#include "png.h"
-#include "radiant_jpeglib.h"
-
-#include <stdlib.h>
-
-
-
-/* -------------------------------------------------------------------------------
-
-port-related hacks
-
-------------------------------------------------------------------------------- */
-
-#define MAC_STATIC_HACK			0
-#if defined( __APPLE__ ) && MAC_STATIC_HACK 
-	#define MAC_STATIC			static
-#else
-	#define MAC_STATIC			
-#endif
-
-#if 1
-	#ifdef _WIN32
-		#define Q_stricmp			stricmp
-		#define Q_strncasecmp		strnicmp
-	#else
-		#define Q_stricmp			strcasecmp
-		#define Q_strncasecmp		strncasecmp
-	#endif
-#endif
-
-/* macro version */
-#define VectorMA( a, s, b, c )	((c)[ 0 ] = (a)[ 0 ] + (s) * (b)[ 0 ], (c)[ 1 ] = (a)[ 1 ] + (s) * (b)[ 1 ], (c)[ 2 ] = (a)[ 2 ] + (s) * (b)[ 2 ])
-
-
-
-/* -------------------------------------------------------------------------------
-
-constants
-
-------------------------------------------------------------------------------- */
-
-/* general */
-#define MAX_QPATH				64
-
-#define MAX_IMAGES				512
-#define DEFAULT_IMAGE			"*default"
-
-#define MAX_MODELS				512
-
-#define	DEF_BACKSPLASH_FRACTION	0.05f	/* 5% backsplash by default */
-#define	DEF_BACKSPLASH_DISTANCE	23
-
-#define DEF_RADIOSITY_BOUNCE	1.0f	/* ydnar: default to 100% re-emitted light */
-
-#define	MAX_SHADER_INFO			8192
-#define MAX_CUST_SURFACEPARMS	64
-
-#define	SHADER_MAX_VERTEXES		1000
-#define	SHADER_MAX_INDEXES		(6 * SHADER_MAX_VERTEXES)
-
-#define MAX_JITTERS				256
-
-
-/* epair parsing (note case-sensitivity directive) */
-#define CASE_INSENSITIVE_EPAIRS	1
-
-#if CASE_INSENSITIVE_EPAIRS
-	#define EPAIR_STRCMP		Q_stricmp
-#else
-	#define EPAIR_STRCMP		strcmp
-#endif
-
-
-/* ydnar: compiler flags, because games have widely varying content/surface flags */
-#define C_SOLID					0x00000001
-#define C_TRANSLUCENT			0x00000002
-#define C_STRUCTURAL			0x00000004
-#define C_HINT					0x00000008
-#define C_NODRAW				0x00000010
-#define C_LIGHTGRID				0x00000020
-#define C_ALPHASHADOW			0x00000040
-#define C_LIGHTFILTER			0x00000080
-#define C_VERTEXLIT				0x00000100
-#define C_LIQUID				0x00000200
-#define C_FOG					0x00000400
-#define C_SKY					0x00000800
-#define C_ORIGIN				0x00001000
-#define C_AREAPORTAL			0x00002000
-#define C_ANTIPORTAL			0x00004000	/* like hint, but doesn't generate portals */
-#define C_SKIP					0x00008000	/* like hint, but skips this face (doesn't split bsp) */
-#define C_NOMARKS				0x00010000	/* no decals */
-
-#define C_DETAIL				0x08000000	/* THIS MUST BE THE SAME AS IN RADIANT! */
-
-
-/* shadow flags */
-#define WORLDSPAWN_CAST_SHADOWS	1
-#define WORLDSPAWN_RECV_SHADOWS	1
-#define ENTITY_CAST_SHADOWS		0
-#define ENTITY_RECV_SHADOWS		1
-
-
-/* bsp */
-#define	MAX_PATCH_SIZE			32
-#define	MAX_BRUSH_SIDES			1024
-#define MAX_BUILD_SIDES			300
-
-#define	MAX_EXPANDED_AXIS		128
-
-#define	CLIP_EPSILON			0.1f
-#define	PLANESIDE_EPSILON		0.001f
-#define	PLANENUM_LEAF			-1
-
-#define	HINT_PRIORITY			1000		/* ydnar: force hint splits first and antiportal/areaportal splits last */
-#define ANTIPORTAL_PRIORITY		-1000
-#define AREAPORTAL_PRIORITY		-1000
-
-#define	PSIDE_FRONT				1
-#define	PSIDE_BACK				2
-#define	PSIDE_BOTH				(PSIDE_FRONT | PSIDE_BACK)
-#define	PSIDE_FACING			4
-
-#define BPRIMIT_UNDEFINED		0
-#define BPRIMIT_OLDBRUSHES		1
-#define BPRIMIT_NEWBRUSHES		2
-
-
-/* vis */
-#define	VIS_HEADER_SIZE			8
-
-#define SEPERATORCACHE			/* seperator caching helps a bit */
-
-#define	PORTALFILE				"PRT1"
-
-#define	MAX_PORTALS				32768
-#define MAX_SEPERATORS			MAX_POINTS_ON_WINDING
-#define	MAX_POINTS_ON_FIXED_WINDING	24	/* ydnar: increased this from 12 at the expense of more memory */
-#define	MAX_PORTALS_ON_LEAF		128
-
-
-/* light */
-#define EMIT_POINT				0
-#define EMIT_AREA				1
-#define EMIT_SPOT				2
-#define EMIT_SUN				3
-
-#define LIGHT_ATTEN_LINEAR		1
-#define LIGHT_ATTEN_ANGLE		2
-#define LIGHT_ATTEN_DISTANCE	4
-#define LIGHT_TWOSIDED			8
-#define LIGHT_GRID				16
-#define LIGHT_SURFACES			32
-#define LIGHT_DARK				64		/* probably never use this */
-#define LIGHT_FAST				256
-#define LIGHT_FAST_TEMP			512
-#define LIGHT_FAST_ACTUAL		(LIGHT_FAST | LIGHT_FAST_TEMP)
-#define LIGHT_NEGATIVE			1024
-
-#define LIGHT_SUN_DEFAULT		(LIGHT_ATTEN_ANGLE | LIGHT_GRID | LIGHT_SURFACES)
-#define LIGHT_AREA_DEFAULT		(LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES)	/* q3a and wolf are the same */
-#define LIGHT_Q3A_DEFAULT		(LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES | LIGHT_FAST)
-#define LIGHT_WOLF_DEFAULT		(LIGHT_ATTEN_LINEAR | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES | LIGHT_FAST)
-
-#define MAX_TRACE_TEST_NODES	256
-#define DEFAULT_INHIBIT_RADIUS	1.5f
-
-#define LUXEL_EPSILON			0.125f
-#define VERTEX_EPSILON			-0.125f
-#define GRID_EPSILON			0.0f
-
-#define DEFAULT_LIGHTMAP_SAMPLE_SIZE	16
-#define DEFAULT_LIGHTMAP_SAMPLE_OFFSET	1.0f
-#define DEFAULT_SUBDIVIDE_THRESHOLD		1.0f
-
-#define	EXTRA_SCALE				2	/* -extrawide = -super 2 */
-#define	EXTRAWIDE_SCALE			2	/* -extrawide = -super 2 -filter */
-
-#define CLUSTER_UNMAPPED		-1
-#define CLUSTER_OCCLUDED		-2
-#define CLUSTER_FLOODED			-3
-
-#define VERTEX_LUXEL_SIZE		3
-#define BSP_LUXEL_SIZE			3
-#define RAD_LUXEL_SIZE			3
-#define SUPER_LUXEL_SIZE		4
-#define SUPER_ORIGIN_SIZE		3
-#define SUPER_NORMAL_SIZE		3
-#define SUPER_DELUXEL_SIZE		3
-#define BSP_DELUXEL_SIZE		3
-
-#define VERTEX_LUXEL( s, v )	(vertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
-#define RAD_VERTEX_LUXEL( s, v )(radVertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
-#define BSP_LUXEL( s, x, y )	(lm->bspLuxels[ s ] + ((((y) * lm->w) + (x)) * BSP_LUXEL_SIZE))
-#define RAD_LUXEL( s, x, y )	(lm->radLuxels[ s ] + ((((y) * lm->w) + (x)) * RAD_LUXEL_SIZE))
-#define SUPER_LUXEL( s, x, y )	(lm->superLuxels[ s ] + ((((y) * lm->sw) + (x)) * SUPER_LUXEL_SIZE))
-#define SUPER_ORIGIN( x, y )	(lm->superOrigins + ((((y) * lm->sw) + (x)) * SUPER_ORIGIN_SIZE))
-#define SUPER_NORMAL( x, y )	(lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE))
-#define SUPER_CLUSTER( x, y )	(lm->superClusters + (((y) * lm->sw) + (x)))
-#define SUPER_DELUXEL( x, y )	(lm->superDeluxels + ((((y) * lm->sw) + (x)) * SUPER_DELUXEL_SIZE))
-#define BSP_DELUXEL( x, y )		(lm->bspDeluxels + ((((y) * lm->w) + (x)) * BSP_DELUXEL_SIZE))
-
-
-
-/* -------------------------------------------------------------------------------
-
-abstracted bsp file
-
-------------------------------------------------------------------------------- */
-
-#define EXTERNAL_LIGHTMAP		"lm_%04d.tga"
-
-#define MAX_LIGHTMAPS			4			/* RBSP */
-#define MAX_LIGHT_STYLES		64
-#define	MAX_SWITCHED_LIGHTS		32
-#define LS_NORMAL				0x00
-#define LS_UNUSED				0xFE
-#define	LS_NONE					0xFF
-
-#define MAX_LIGHTMAP_SHADERS	256
-
-/* ok to increase these at the expense of more memory */
-#define	MAX_MAP_MODELS			0x400
-#define	MAX_MAP_BRUSHES			0x8000
-#define	MAX_MAP_ENTITIES		0x1000		//%	0x800	/* ydnar */
-#define	MAX_MAP_ENTSTRING		0x80000		//%	0x40000	/* ydnar */
-#define	MAX_MAP_SHADERS			0x400
-
-#define	MAX_MAP_AREAS			0x100		/* MAX_MAP_AREA_BYTES in q_shared must match! */
-#define	MAX_MAP_FOGS			30			//& 0x100	/* RBSP (32 - world fog - goggles) */
-#define	MAX_MAP_PLANES			0x100000	//%	0x20000	/* ydnar for md */
-#define	MAX_MAP_NODES			0x20000
-#define	MAX_MAP_BRUSHSIDES		0x100000	//%	0x20000	/* ydnar */
-#define	MAX_MAP_LEAFS			0x20000
-#define	MAX_MAP_LEAFFACES		0x20000
-#define	MAX_MAP_LEAFBRUSHES		0x40000
-#define	MAX_MAP_PORTALS			0x20000
-#define	MAX_MAP_LIGHTING		0x800000
-#define	MAX_MAP_LIGHTGRID		0x100000	//%	0x800000 /* ydnar: set to points, not bytes */
-#define	MAX_MAP_VISIBILITY		0x200000
-
-#define	MAX_MAP_DRAW_SURFS		0x20000
-#define	MAX_MAP_DRAW_VERTS		0x80000
-#define	MAX_MAP_DRAW_INDEXES	0x80000
-
-
-/* key / value pair sizes in the entities lump */
-#define	MAX_KEY					32
-#define	MAX_VALUE				1024
-
-/* the editor uses these predefined yaw angles to orient entities up or down */
-#define	ANGLE_UP				-1
-#define	ANGLE_DOWN				-2
-
-#define	LIGHTMAP_WIDTH			128
-#define	LIGHTMAP_HEIGHT			128
-
-#define MIN_WORLD_COORD			(-65536)
-#define	MAX_WORLD_COORD			(65536)
-#define WORLD_SIZE				(MAX_WORLD_COORD - MIN_WORLD_COORD)
-
-
-typedef void					(*bspFunc)( const char * );
-
-
-typedef struct
-{
-	int		offset, length;
-}
-bspLump_t;
-
-
-typedef struct
-{
-	char		ident[ 4 ];
-	int			version;
-	
-	bspLump_t	lumps[ 100 ];	/* theoretical maximum # of bsp lumps */
-}
-bspHeader_t;
-
-
-typedef struct
-{
-	float		mins[ 3 ], maxs[ 3 ];
-	int			firstBSPSurface, numBSPSurfaces;
-	int			firstBSPBrush, numBSPBrushes;
-}
-bspModel_t;
-
-
-typedef struct
-{
-	char		shader[ MAX_QPATH ];
-	int			surfaceFlags;
-	int			contentFlags;
-}
-bspShader_t;
-
-
-/* planes x^1 is allways the opposite of plane x */
-
-typedef struct
-{
-	float		normal[ 3 ];
-	float		dist;
-}
-bspPlane_t;
-
-
-typedef struct
-{
-	int			planeNum;
-	int			children[ 2 ];		/* negative numbers are -(leafs+1), not nodes */
-	int			mins[ 3 ];			/* for frustom culling */
-	int			maxs[ 3 ];
-}
-bspNode_t;
-
-
-typedef struct
-{
-	int			cluster;			/* -1 = opaque cluster (do I still store these?) */
-	int			area;
-	
-	int			mins[ 3 ];			/* for frustum culling */
-	int			maxs[ 3 ];
-	
-	int			firstBSPLeafSurface;
-	int			numBSPLeafSurfaces;
-	
-	int			firstBSPLeafBrush;
-	int			numBSPLeafBrushes;
-}
-bspLeaf_t;
-
-
-typedef struct
-{
-	int			planeNum;			/* positive plane side faces out of the leaf */
-	int			shaderNum;
-	int			surfaceNum;			/* RBSP */
-}
-bspBrushSide_t;
-
-
-typedef struct
-{
-	int			firstSide;
-	int			numSides;
-	int			shaderNum;			/* the shader that determines the content flags */
-}
-bspBrush_t;
-
-
-typedef struct
-{
-	char		shader[ MAX_QPATH ];
-	int			brushNum;
-	int			visibleSide;		/* the brush side that ray tests need to clip against (-1 == none) */
-}
-bspFog_t;
-
-
-typedef struct
-{
-	vec3_t		xyz;
-	float		st[ 2 ];
-	float		lightmap[ MAX_LIGHTMAPS ][ 2 ];	/* RBSP */
-	vec3_t		normal;
-	byte		color[ MAX_LIGHTMAPS ][ 4 ];	/* RBSP */
-}
-bspDrawVert_t;
-
-
-typedef enum
-{
-	MST_BAD,
-	MST_PLANAR,
-	MST_PATCH,
-	MST_TRIANGLE_SOUP,
-	MST_FLARE,
-	MST_FOLIAGE
-}
-bspSurfaceType_t;
-
-
-typedef struct bspGridPoint_s
-{
-	byte		ambient[ MAX_LIGHTMAPS ][ 3 ];
-	byte		directed[ MAX_LIGHTMAPS ][ 3 ];
-	byte		styles[ MAX_LIGHTMAPS ];
-	byte		latLong[ 2 ];
-}
-bspGridPoint_t;
-
-
-typedef struct
-{
-	int			shaderNum;
-	int			fogNum;
-	int			surfaceType;
-	
-	int			firstVert;
-	int			numVerts;
-	
-	int			firstIndex;
-	int			numIndexes;
-	
-	byte		lightmapStyles[ MAX_LIGHTMAPS ];						/* RBSP */
-	byte		vertexStyles[ MAX_LIGHTMAPS ];							/* RBSP */
-	int			lightmapNum[ MAX_LIGHTMAPS ];							/* RBSP */
-	int			lightmapX[ MAX_LIGHTMAPS ], lightmapY[ MAX_LIGHTMAPS ];	/* RBSP */
-	int			lightmapWidth, lightmapHeight;
-	
-	vec3_t		lightmapOrigin;
-	vec3_t		lightmapVecs[ 3 ];	/* on patches, [ 0 ] and [ 1 ] are lodbounds */
-	
-	int			patchWidth;
-	int			patchHeight;
-}
-bspDrawSurface_t;
-
-
-
-/* -------------------------------------------------------------------------------
-
-general types
-
-------------------------------------------------------------------------------- */
-
-/* ydnar: for smaller structs */
-typedef char	qb_t;
-
-
-/* ydnar: for q3map_tcMod */
-typedef float	tcMod_t[ 3 ][ 3 ];
-
-
-/* ydnar: for multiple game support */
-typedef struct surfaceParm_s
-{
-	char		*name;
-	int			contentFlags, contentFlagsClear;
-	int			surfaceFlags, surfaceFlagsClear;
-	int			compileFlags, compileFlagsClear;
-}
-surfaceParm_t;
-
-
-typedef struct game_s
-{
-	char				*arg;							/* -game matches this */
-	char				*gamePath;						/* main game data dir */
-	char				*homeBasePath;					/* home sub-dir on unix */
-	char				*magic;							/* magic word for figuring out base path */
-	char				*shaderPath;					/* shader directory */
-	qboolean			wolfLight;						/* when true, lights work like wolf q3map  */
-	qboolean			emitFlares;						/* when true, emit flare surfaces */
-	char				*flareShader;					/* default flare shader (MUST BE SET) */
-	char				*bspIdent;						/* 4-letter bsp file prefix */
-	int					bspVersion;						/* BSP version to use */
-	bspFunc				load, write;					/* load/write function pointers */
-	surfaceParm_t		surfaceParms[ 128 ];			/* surfaceparm array */
-}
-game_t;
-
-
-typedef struct image_s
-{
-	char				*name, *filename;
-	int					refCount;
-	int					width, height;
-	byte				*pixels;
-}
-image_t;
-
-
-typedef struct sun_s
-{
-	struct sun_s		*next;
-	vec3_t				direction, color;
-	float				photons, deviance, filterRadius;
-	int					numSamples;
-}
-sun_t;
-
-
-typedef struct surfaceModel_s 
-{
-	struct surfaceModel_s	*next;
-	char				model[ MAX_QPATH ];
-	float				density, odds;
-	float				minScale, maxScale;
-	float				minAngle, maxAngle;
-	qboolean			oriented;
-}
-surfaceModel_t;
-
-
-/* ydnar/sd: foliage stuff for wolf et (engine-supported optimization of the above) */
-typedef struct foliage_s 
-{
-	struct foliage_s	*next;
-	char				model[ MAX_QPATH ];
-	float				scale, density, odds;
-	qboolean			inverseAlpha;
-}
-foliage_t;
-
-typedef struct foliageInstance_s
-{
-	vec3_t				xyz, normal;
-}
-foliageInstance_t;
-
-
-typedef struct remap_s
-{
-	struct remap_s		*next;
-	char				from[ 1024 ];
-	char				to[ MAX_QPATH ];
-}
-remap_t;
-
-
-typedef enum
-{
-	AM_NONE,
-	AM_DOT_PRODUCT
-}
-alphaModType_t;
-
-
-typedef struct alphaMod_s
-{
-	struct alphaMod_s	*next;
-	alphaModType_t		type;
-	vec_t				data[ 16 ];
-}
-alphaMod_t;
-
-
-typedef enum
-{
-	IM_NONE,
-	IM_OPAQUE,
-	IM_MASKED,
-	IM_BLEND
-}
-implicitMap_t;
-
-
-typedef struct shaderInfo_s
-{
-	char				shader[ MAX_QPATH ];
-	int					surfaceFlags;
-	int					contentFlags;
-	int					compileFlags;
-	float				value;							/* light value */
-	
-	char				backShader[ MAX_QPATH ];		/* for surfaces that generate different front and back passes */
-	char				flareShader[ MAX_QPATH ];		/* for light flares */
-	char				cloneShader[ MAX_QPATH ];		/* ydnar: for cloning of a surface */
-	char				damageShader[ MAX_QPATH ];		/* ydnar: sof2 damage shader name */
-
-	surfaceModel_t		*surfaceModel;					/* ydnar: for distribution of models */
-	foliage_t			*foliage;						/* ydnar/splash damage: wolf et foliage */
-	
-	float				subdivisions;					/* from a "tesssize xxx" */
-	float				backsplashFraction;				/* floating point value, usually 0.05 */
-	float				backsplashDistance;				/* default 16 */
-	float				lightSubdivide;					/* default 999 */
-	float				lightFilterRadius;				/* ydnar: lightmap filtering/blurring radius for lights created by this shader (default: 0) */
-	
-	int					lightmapSampleSize;				/* lightmap sample size */
-	float				lightmapSampleOffset;			/* ydnar: lightmap sample offset (default: 1.0) */
-	
-	float				bounceScale;					/* ydnar: radiosity re-emission [0,1.0+] */
-	float				offset;							/* ydnar: offset in units */
-	float				shadeAngleDegrees;				/* ydnar: breaking angle for smooth shading (degrees) */
-	
-	vec3_t				mins, maxs;						/* ydnar: for particle studio vertexDeform move support */
-	
-	qb_t				legacyTerrain;					/* ydnar: enable legacy terrain crutches */
-	qb_t				indexed;						/* ydnar: attempt to use indexmap (terrain alphamap style) */
-	qb_t				forceMeta;						/* ydnar: force metasurface path */
-	qb_t				noClip;							/* ydnar: don't clip into bsp, preserve original face winding */
-	qb_t				noFast;							/* ydnar: supress fast lighting for surfaces with this shader */
-	qb_t				invert;							/* ydnar: reverse facing */
-	qb_t				nonplanar;						/* ydnar: for nonplanar meta surface merging */
-	qb_t				tcGen;							/* ydnar: has explicit texcoord generation */
-	vec3_t				vecs[ 2 ];						/* ydnar: explicit texture vectors for [0,1] texture space */
-	tcMod_t				mod;							/* ydnar: q3map_tcMod matrix for djbob :) */
-	vec3_t				lightmapAxis;					/* ydnar: explicit lightmap axis projection */
-	alphaMod_t			*alphaMod;						/* ydnar: q3map_alphaMod support */
-	
-	int					furNumLayers;					/* ydnar: number of fur layers */
-	float				furOffset;						/* ydnar: offset of each layer */
-	float				furFade;						/* ydnar: alpha fade amount per layer */
-
-	qb_t				splotchFix;						/* ydnar: filter splotches on lightmaps */
-	
-	qb_t				hasPasses;						/* false if the shader doesn't define any rendering passes */
-	qb_t				globalTexture;					/* don't normalize texture repeats */
-	qb_t				twoSided;						/* cull none */
-	qb_t				autosprite;						/* autosprite shaders will become point lights instead of area lights */
-	qb_t				polygonOffset;					/* ydnar: don't face cull this or against this */
-	qb_t				patchShadows;					/* have patches casting shadows when using -light for this surface */
-	qb_t				vertexShadows;					/* shadows will be casted at this surface even when vertex lit */
-	qb_t				forceSunlight;					/* force sun light at this surface even tho we might not calculate shadows in vertex lighting */
-	qb_t				notjunc;						/* don't use this surface for tjunction fixing */
-	qb_t				fogParms;						/* ydnar: has fogparms */
-	qb_t				noFog;							/* ydnar: supress fogging */
-	
-	qb_t				clipModel;						/* ydnar: solid model hack */
-	
-	byte				styleMarker;					/* ydnar: light styles hack */
-	
-	float				vertexScale;					/* vertex light scale */
-	
-	char				skyParmsImageBase[ MAX_QPATH ];	/* ydnar: for skies */
-	
-	char				editorImagePath[ MAX_QPATH ];	/* use this image to generate texture coordinates */
-	char				lightImagePath[ MAX_QPATH ];	/* use this image to generate color / averageColor */
-	char				normalImagePath[ MAX_QPATH ];	/* ydnar: normalmap image for bumpmapping */
-	
-	implicitMap_t		implicitMap;					/* ydnar: enemy territory implicit shaders */
-	char				implicitImagePath[ MAX_QPATH ];
-	
-	image_t				*shaderImage;
-	image_t				*lightImage;
-	image_t				*normalImage;
-	
-	float				skyLightValue;					/* ydnar */
-	int					skyLightIterations;				/* ydnar */
-	sun_t				*sun;							/* ydnar */
-	
-	vec3_t				color;							/* normalized color */
-	vec3_t				averageColor;
-	byte				lightStyle;
-	
-	qb_t				lmMergable;						/* ydnar */
-	int					lmCustomWidth, lmCustomHeight;	/* ydnar */
-	float				lmGamma;						/* ydnar */
-	float				lmFilterRadius;					/* ydnar: lightmap filtering/blurring radius for this shader (default: 0) */
-	
-	int					shaderWidth, shaderHeight;		/* ydnar */
-	float				stFlat[ 2 ];
-	
-	vec3_t				fogDir;							/* ydnar */
-	
-	char				*shaderText;					/* ydnar */
-	qb_t				custom;
-	qb_t				finished;
-}
-shaderInfo_t;
-
-
-
-/* -------------------------------------------------------------------------------
-
-bsp structures
-
-------------------------------------------------------------------------------- */
-
-typedef struct face_s
-{
-	struct face_s		*next;
-	int					planenum;
-	int					priority;
-	qboolean			checked;
-	int					compileFlags;
-	winding_t			*w;
-}
-face_t;
-
-
-typedef struct plane_s
-{
-	vec3_t				normal;
-	vec_t				dist;
-	int					type;
-	struct plane_s		*hash_chain;
-}
-plane_t;
-
-
-typedef struct side_s
-{
-	int					planenum;
-	
-	int					outputNum;			/* set when the side is written to the file list */
-	
-	float				texMat[ 2 ][ 3 ];	/* brush primitive texture matrix */
-	float				vecs[ 2 ][ 4 ];		/* old-style texture coordinate mapping */
-
-	winding_t			*winding;
-	winding_t			*visibleHull;		/* convex hull of all visible fragments */
-
-	shaderInfo_t		*shaderInfo;
-
-	int					contentFlags;		/* from shaderInfo */
-	int					surfaceFlags;		/* from shaderInfo */
-	int					compileFlags;		/* from shaderInfo */
-	int					value;				/* from shaderInfo */
-
-	qboolean			visible;			/* choose visble planes first */
-	qboolean			bevel;				/* don't ever use for bsp splitting, and don't bother making windings for it */
-	qboolean			backSide;			/* generated side for a q3map_backShader */
-	
-	qboolean			culled;				/* ydnar: face culling */
-}
-side_t;
-
-
-typedef struct sideRef_s
-{
-	struct sideRef_s	*next;
-	side_t				*side;
-}
-sideRef_t;
-
-
-/* ydnar: generic index mapping for entities (natural extension of terrain texturing) */
-typedef struct indexMap_s
-{
-	int					w, h, numLayers;
-	char				name[ MAX_QPATH ], shader[ MAX_QPATH ];
-	float				offsets[ 256 ];
-	byte				*pixels;
-}
-indexMap_t;
-
-
-typedef struct brush_s
-{
-	struct brush_s		*next;
-	struct brush_s		*original;			/* chopped up brushes will reference the originals */
-	
-	int					entityNum, brushNum;/* editor numbering */
-	int					outputNum;			/* set when the brush is written to the file list */
-	
-	/* ydnar: for shadowcasting entities */
-	int					castShadows;
-	int					recvShadows;
-	
-	shaderInfo_t		*contentShader;
-	shaderInfo_t		*celShader;			/* :) */
-	
-	/* ydnar: gs mods */
-	float				lightmapScale;
-	vec3_t				eMins, eMaxs;
-	indexMap_t			*im;
-
-	int					contentFlags;
-	int					compileFlags;		/* ydnar */
-	qboolean			detail;
-	qboolean			opaque;
-
-	int					portalareas[ 2 ];
-
-	vec3_t				mins, maxs;
-	int					numsides;
-	
-	side_t				sides[ 6 ];			/* variably sized */
-}
-brush_t;
-
-
-typedef struct fog_s
-{
-	shaderInfo_t		*si;
-	brush_t				*brush;
-	int					visibleSide;		/* the brush side that ray tests need to clip against (-1 == none) */
-}
-fog_t;
-
-
-typedef struct
-{
-	int					width, height;
-	bspDrawVert_t		*verts;
-}
-mesh_t;
-
-
-typedef struct parseMesh_s
-{
-	struct parseMesh_s	*next;
-	
-	int					entityNum, brushNum;	/* ydnar: editor numbering */
-	
-	/* ydnar: for shadowcasting entities */
-	int					castShadows;
-	int					recvShadows;
-	
-	mesh_t				mesh;
-	shaderInfo_t		*shaderInfo;
-	shaderInfo_t		*celShader;				/* :) */
-	
-	/* ydnar: gs mods */
-	float				lightmapScale;
-	vec3_t				eMins, eMaxs;
-	indexMap_t			*im;
-	
-	/* grouping */
-	qboolean			grouped;
-	float				longestCurve;
-	int					maxIterations;
-}
-parseMesh_t;
-
-
-/*
-	ydnar: the drawsurf struct was extended to allow for:
-	- non-convex planar surfaces
-	- non-planar brushface surfaces
-	- lightmapped terrain
-	- planar patches
-*/
-
-typedef enum
-{
-	/* ydnar: these match up exactly with bspSurfaceType_t */
-	SURFACE_BAD,
-	SURFACE_FACE,
-	SURFACE_PATCH,
-	SURFACE_TRIANGLES,
-	SURFACE_FLARE,
-	SURFACE_FOLIAGE,	/* wolf et */
-	
-	/* ydnar: compiler-relevant surface types */
-	SURFACE_FORCED_META,
-	SURFACE_META,
-	SURFACE_FOGHULL,
-	SURFACE_DECAL,
-	SURFACE_SHADER,
-	
-	NUM_SURFACE_TYPES
-}
-surfaceType_t;
-
-char			*surfaceTypes[ NUM_SURFACE_TYPES ]
-#ifndef MAIN_C
-				;
-#else
-				=
-				{
-					"SURFACE_BAD",
-					"SURFACE_FACE",
-					"SURFACE_PATCH",
-					"SURFACE_TRIANGLES",
-					"SURFACE_FLARE",
-					"SURFACE_FOLIAGE",
-					"SURFACE_FORCED_META",
-					"SURFACE_META",
-					"SURFACE_FOGHULL",
-					"SURFACE_DECAL",
-					"SURFACE_SHADER"
-				};
-#endif
-
-
-/* ydnar: this struct needs an overhaul (again, heh) */
-typedef struct mapDrawSurface_s
-{
-	surfaceType_t		type;
-	qboolean			planar;
-	int					outputNum;			/* ydnar: to match this sort of thing up */
-	
-	qboolean			fur;				/* ydnar: this is kind of a hack, but hey... */
-	qboolean			skybox;				/* ydnar: yet another fun hack */
-	
-	struct mapDrawSurface_s	*parent;		/* ydnar: for cloned (skybox) surfaces to share lighting data */
-	
-	shaderInfo_t		*shaderInfo;
-	shaderInfo_t		*celShader;
-	brush_t				*mapBrush;
-	parseMesh_t			*mapMesh;
-	sideRef_t			*sideRef;
-	
-	int					fogNum;
-	
-	int					numVerts;			/* vertexes and triangles */
-	bspDrawVert_t		*verts;
-	int					numIndexes;
-	int					*indexes;
-	
-	int					planeNum;
-	vec3_t				lightmapOrigin;		/* also used for flares */
-	vec3_t				lightmapVecs[ 3 ];	/* also used for flares */
-	int					lightStyle;			/* used for flares */
-	
-	/* ydnar: per-surface (per-entity, actually) lightmap sample size scaling */
-	float				lightmapScale;
-	
-	/* ydnar: surface classification */
-	vec3_t				mins, maxs;
-	vec3_t				lightmapAxis;
-	int					sampleSize;
-	
-	/* ydnar: shadow group support */
-	int					castShadows, recvShadows;
-	
-	/* ydnar: texture coordinate range monitoring for hardware with limited texcoord precision (in texel space) */
-	float				bias[ 2 ];
-	int					texMins[ 2 ], texMaxs[ 2 ], texRange[ 2 ];
-		
-	/* ydnar: for patches */
-	float				longestCurve;
-	int					maxIterations;
-	int					patchWidth, patchHeight;
-	vec3_t				bounds[ 2 ];
-	
-	/* ydnar/sd: for foliage */
-	int					numFoliageInstances;
-	
-	/* ydnar: editor/useful numbering */
-	int					entityNum;
-	int					surfaceNum;
-}
-mapDrawSurface_t;
-
-
-typedef struct drawSurfRef_s
-{
-	struct drawSurfRef_s	*nextRef;
-	int					outputNum;
-}
-drawSurfRef_t;
-
-
-/* ydnar: metasurfaces are constructed from lists of metatriangles so they can be merged in the best way */
-typedef struct metaTriangle_s
-{
-	shaderInfo_t		*si;
-	side_t				*side;
-	int					entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
-	vec4_t				plane;
-	vec3_t				lightmapAxis;
-	int					indexes[ 3 ];
-}
-metaTriangle_t;
-
-
-typedef struct epair_s
-{
-	struct epair_s		*next;
-	char				*key, *value;
-}
-epair_t;
-
-
-typedef struct
-{
-	vec3_t				origin;
-	brush_t				*brushes, *lastBrush;
-	parseMesh_t			*patches;
-	int					mapEntityNum, firstDrawSurf;
-	int					firstBrush, numBrushes;		/* only valid during BSP compile */
-	epair_t				*epairs;
-}
-entity_t;
-
-
-typedef struct node_s
-{
-	/* both leafs and nodes */
-	int					planenum;		/* -1 = leaf node */
-	struct node_s		*parent;
-	vec3_t				mins, maxs;		/* valid after portalization */
-	brush_t				*volume;		/* one for each leaf/node */
-
-	/* nodes only */
-	side_t				*side;			/* the side that created the node */
-	struct node_s		*children[ 2 ];
-	int					compileFlags;	/* ydnar: hint, antiportal */
-	int					tinyportals;
-	vec3_t				referencepoint;
-
-	/* leafs only */
-	qboolean			opaque;			/* view can never be inside */
-	qboolean			areaportal;
-	qboolean			skybox;			/* ydnar: a skybox leaf */
-	qboolean			sky;			/* ydnar: a sky leaf */
-	int					cluster;		/* for portalfile writing */
-	int					area;			/* for areaportals */
-	brush_t				*brushlist;		/* fragments of all brushes in this leaf */
-	drawSurfRef_t		*drawSurfReferences;
-
-	int					occupied;		/* 1 or greater can reach entity */
-	entity_t			*occupant;		/* for leak file testing */
-
-	struct portal_s		*portals;		/* also on nodes during construction */
-}
-node_t;
-
-
-typedef struct portal_s
-{
-	plane_t				plane;
-	node_t				*onnode;		/* NULL = outside box */
-	node_t				*nodes[ 2 ];	/* [ 0 ] = front side of plane */
-	struct portal_s		*next[ 2 ];
-	winding_t			*winding;
-
-	qboolean			sidefound;		/* false if ->side hasn't been checked */
-	int					compileFlags;	/* from original face that caused the split */
-	side_t				*side;			/* NULL = non-visible */
-}
-portal_t;
-
-
-typedef struct
-{
-	node_t				*headnode;
-	node_t				outside_node;
-	vec3_t				mins, maxs;
-}
-tree_t;
-
-
-
-/* -------------------------------------------------------------------------------
-
-vis structures
-
-------------------------------------------------------------------------------- */
-
-typedef struct
-{
-	vec3_t				normal;
-	float				dist;
-}
-visPlane_t;
-
-
-typedef struct
-{
-	int					numpoints;
-	vec3_t				points[	MAX_POINTS_ON_FIXED_WINDING	];		/* variable sized */
-} 
-fixedWinding_t;
-
-
-typedef struct passage_s
-{
-	struct passage_s	*next;
-	byte				cansee[ 1 ];	/* all portals that can be seen through this passage */
-} passage_t;
-
-
-typedef enum
-{
-	stat_none,
-	stat_working,
-	stat_done
-}
-vstatus_t;
-
-
-typedef struct
-{
-	int					num;
-	qboolean			hint;			/* true if this portal was created from a hint splitter */
-	qboolean			removed;
-	visPlane_t			plane;			/* normal pointing into neighbor */
-	int					leaf;			/* neighbor */
-	
-	vec3_t				origin;			/* for fast clip testing */
-	float				radius;
-
-	fixedWinding_t		*winding;
-	vstatus_t			status;
-	byte				*portalfront;	/* [portals], preliminary */
-	byte				*portalflood;	/* [portals], intermediate */
-	byte				*portalvis;		/* [portals], final */
-
-	int					nummightsee;	/* bit count on portalflood for sort */
-	passage_t			*passages;		/* there are just as many passages as there */
-										/* are portals in the leaf this portal leads */
-}
-vportal_t;
-
-
-typedef struct leaf_s
-{
-	int					numportals;
-	int					merged;
-	vportal_t			*portals[MAX_PORTALS_ON_LEAF];
-}
-leaf_t;
-
-	
-typedef struct pstack_s
-{
-	byte				mightsee[ MAX_PORTALS / 8 ];
-	struct pstack_s		*next;
-	leaf_t				*leaf;
-	vportal_t			*portal;		/* portal exiting */
-	fixedWinding_t		*source;
-	fixedWinding_t		*pass;
-
-	fixedWinding_t		windings[ 3 ];	/* source, pass, temp in any order */
-	int					freewindings[ 3 ];
-
-	visPlane_t			portalplane;
-	int depth;
-#ifdef SEPERATORCACHE
-	visPlane_t			seperators[ 2 ][ MAX_SEPERATORS ];
-	int					numseperators[ 2 ];
-#endif
-}
-pstack_t;
-
-
-typedef struct
-{
-	vportal_t			*base;
-	int					c_chains;
-	pstack_t			pstack_head;
-}
-threaddata_t;
-
-
-
-/* -------------------------------------------------------------------------------
-
-light structures
-
-------------------------------------------------------------------------------- */
-
-/* ydnar: new light struct with flags */
-typedef struct light_s
-{
-	struct light_s		*next;
-	
-	int					type;
-	int					flags;			/* ydnar: condensed all the booleans into one flags int */
-	shaderInfo_t		*si;
-	
-	vec3_t				origin;
-	vec3_t				normal;			/* for surfaces, spotlights, and suns */
-	float				dist;			/* plane location along normal */
-	
-	float				photons;
-	int					style;
-	vec3_t				color;
-	float				radiusByDist;	/* for spotlights */
-	float				fade;			/* ydnar: from wolf, for linear lights */
-	float				angleScale;		/* ydnar: stolen from vlight for K */
-
-	float				add;			/* ydnar: used for area lights */
-	float				envelope;		/* ydnar: units until falloff < tolerance */
-	float				envelope2;		/* ydnar: envelope squared (tiny optimization) */
-	vec3_t				mins, maxs;		/* ydnar: pvs envelope */
-	int					cluster;		/* ydnar: cluster light falls into */
-	
-	winding_t			*w;
-	vec3_t				emitColor;		/* full out-of-gamut value */
-	
-	float				falloffTolerance;	/* ydnar: minimum attenuation threshold */
-	float				filterRadius;	/* ydnar: lightmap filter radius in world units, 0 == default */
-}
-light_t;
-
-
-typedef struct
-{
-	/* constant input */
-	qboolean			testOcclusion, forceSunlight, testAll;
-	int					recvShadows;
-	
-	int					numSurfaces;
-	int					*surfaces;
-	
-	int					numLights;
-	light_t				**lights;
-	
-	qboolean			twoSided;
-	
-	/* per-sample input */
-	int					cluster;
-	vec3_t				origin, normal;
-	vec_t				inhibitRadius;	/* sphere in which occluding geometry is ignored */
-	
-	/* per-light input */
-	light_t				*light;
-	vec3_t				end;
-	
-	/* calculated input */
-	vec3_t				displacement, direction;
-	vec_t				distance;
-	
-	/* input and output */
-	vec3_t				color;			/* starts out at full color, may be reduced if transparent surfaces are crossed */
-	
-	/* output */
-	int					compileFlags;	/* for determining surface compile flags traced through */
-	qboolean			passSolid;
-	qboolean			opaque;
-	
-	/* working data */
-	int					numTestNodes;
-	int					testNodes[ MAX_TRACE_TEST_NODES ]; 
-}
-trace_t;
-
-
-
-/* must be identical to bspDrawVert_t except for float color! */
-typedef struct
-{
-	vec3_t				xyz;
-	float				st[ 2 ];
-	float				lightmap[ MAX_LIGHTMAPS ][ 2 ];
-	vec3_t				normal;
-	float				color[ MAX_LIGHTMAPS ][ 4 ];
-}
-radVert_t;
-
-
-typedef struct
-{
-	int					numVerts;
-	radVert_t			verts[ MAX_POINTS_ON_WINDING ];
-}
-radWinding_t;
-
-
-/* crutch for poor local allocations in win32 smp */
-typedef struct
-{
-	vec_t				dists[ MAX_POINTS_ON_WINDING + 4 ];
-	int					sides[ MAX_POINTS_ON_WINDING + 4 ];
-}
-clipWork_t;
-
-
-/* ydnar: new lightmap handling code */
-typedef struct outLightmap_s
-{
-	int					lightmapNum, extLightmapNum;
-	int					customWidth, customHeight;
-	int					numLightmaps;
-	int					freeLuxels;
-	int					numShaders;
-	shaderInfo_t		*shaders[ MAX_LIGHTMAP_SHADERS ];
-	byte				*lightBits;
-	byte				*bspLightBytes;
-	byte				*bspDirBytes;
-}
-outLightmap_t;
-
-
-typedef struct rawLightmap_s
-{
-	qboolean				finished, splotchFix, wrap[ 2 ];
-	int						customWidth, customHeight;
-	float					gamma;
-	float					filterRadius;
-	
-	int						firstLightSurface, numLightSurfaces;	/* index into lightSurfaces */
-	int						numLightClusters, *lightClusters;
-	
-	int						sampleSize, actualSampleSize, axisNum;
-	int						entityNum;
-	int						recvShadows;
-	vec3_t					mins, maxs, axis, origin, *vecs;
-	float					*plane;
-	int						w, h, sw, sh, used;
-	
-	int						numStyledTwins;
-	struct rawLightmap_s	*twins[ MAX_LIGHTMAPS ];
-
-	int						outLightmapNums[ MAX_LIGHTMAPS ];
-	int						twinNums[ MAX_LIGHTMAPS ];
-	int						lightmapX[ MAX_LIGHTMAPS ], lightmapY[ MAX_LIGHTMAPS ];
-	byte					styles[ MAX_LIGHTMAPS ];
-	float					*bspLuxels[ MAX_LIGHTMAPS ];
-	float					*radLuxels[ MAX_LIGHTMAPS ];
-	float					*superLuxels[ MAX_LIGHTMAPS ];
-	float					*superOrigins;
-	float					*superNormals;
-	int						*superClusters;
-	
-	float					*superDeluxels;	/* average light direction */
-	float					*bspDeluxels;
-}
-rawLightmap_t;
-
-
-typedef struct rawGridPoint_s
-{
-	vec3_t				ambient[ MAX_LIGHTMAPS ];
-	vec3_t				directed[ MAX_LIGHTMAPS ];
-	vec3_t				dir;
-	byte				styles[ MAX_LIGHTMAPS ];
-}
-rawGridPoint_t;
-
-
-typedef struct surfaceInfo_s
-{
-	bspModel_t			*model;
-	shaderInfo_t		*si;
-	rawLightmap_t		*lm;
-	int					parentSurfaceNum, childSurfaceNum;
-	int					entityNum, castShadows, recvShadows, sampleSize, patchIterations;
-	float				longestCurve;
-	float				*plane;
-	vec3_t				axis, mins, maxs;
-	qboolean			hasLightmap, approximated;
-	int					firstSurfaceCluster, numSurfaceClusters;
-}
-surfaceInfo_t;
-
-
-
-/* -------------------------------------------------------------------------------
-
-prototypes
-
-------------------------------------------------------------------------------- */
-
-/* main.c */
-vec_t						Random( void );
-int							BSPInfo( int count, char **fileNames );
-int							ScaleBSPMain( int argc, char **argv );
-int							ConvertMain( int argc, char **argv );
-
-
-/* path_init.c */
-void						InitPaths( int *argc, char **argv );
-
-
-/* bsp.c */
-int							BSPMain( int argc, char **argv );
-
-
-/* convert_map.c */
-int							ConvertBSPToMap( char *bspName );
-
-
-/* convert_ase.c */
-int							ConvertBSPToASE( char *bspName );
-
-
-/* brush.c */
-sideRef_t					*AllocSideRef( side_t *side, sideRef_t *next );
-int							CountBrushList( brush_t *brushes );
-brush_t						*AllocBrush( int numsides );
-void						FreeBrush( brush_t *brushes );
-void						FreeBrushList( brush_t *brushes );
-brush_t						*CopyBrush( brush_t *brush );
-qboolean					BoundBrush( brush_t *brush );
-qboolean					CreateBrushWindings( brush_t *brush );
-brush_t						*BrushFromBounds( vec3_t mins, vec3_t maxs );
-vec_t						BrushVolume( brush_t *brush );
-void						WriteBSPBrushMap( char *name, brush_t *list );
-
-void						FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree );
-void						FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree );
-
-int							BoxOnPlaneSide( vec3_t mins, vec3_t maxs, plane_t *plane );
-qboolean					WindingIsTiny( winding_t *w );
-
-void						SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back);
-
-tree_t						*AllocTree( void );
-node_t						*AllocNode( void );
-
-
-/* mesh.c */
-void						LerpDrawVert( bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *out );
-void						LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDrawVert_t *out );
-void						FreeMesh( mesh_t *m );
-mesh_t						*CopyMesh( mesh_t *mesh );
-void						PrintMesh( mesh_t *m );
-mesh_t						*TransposeMesh( mesh_t *in );
-void						InvertMesh( mesh_t *m );
-mesh_t						*SubdivideMesh( mesh_t in, float maxError, float minLength );
-int							IterationsForCurve( float len, int subdivisions );
-mesh_t						*SubdivideMesh2( mesh_t in, int iterations );
-mesh_t						*SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable );
-mesh_t						*RemoveLinearMeshColumnsRows( mesh_t *in );
-void						MakeMeshNormals( mesh_t in );
-void						PutMeshOnCurve( mesh_t in );
-
-void						MakeNormalVectors( vec3_t forward, vec3_t right, vec3_t up );
-
-
-/* map.c */
-void 						LoadMapFile( char *filename, qboolean onlyLights );
-int							FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points );
-int							PlaneTypeForNormal( vec3_t normal );
-void						AddBrushBevels( void );
-brush_t						*FinishBrush( void );
-
-
-/* portals.c */
-void						MakeHeadnodePortals( tree_t *tree );
-void						MakeNodePortal( node_t *node );
-void						SplitNodePortals( node_t *node );
-
-qboolean					PortalPassable( portal_t *p );
-
-qboolean					FloodEntities( tree_t *tree );
-void						FillOutside( node_t *headnode);
-void						FloodAreas( tree_t *tree);
-face_t						*VisibleFaces( entity_t *e, tree_t *tree );
-void						FreePortal( portal_t *p );
-
-void						MakeTreePortals( tree_t *tree );
-
-
-/* leakfile.c */
-xmlNodePtr					LeakFile( tree_t *tree );
-
-
-/* prtfile.c */
-void						NumberClusters( tree_t *tree );
-void						WritePortalFile( tree_t *tree );
-
-
-/* writebsp.c */
-void						SetModelNumbers( void );
-void						SetLightStyles( void );
-
-int							EmitShader( const char *shader, int *contentFlags, int *surfaceFlags );
-
-void						BeginBSPFile( void );
-void						EndBSPFile( void );
-void						EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes );
-void						EmitFogs( void );
-
-void						BeginModel( void );
-void						EndModel( entity_t *e, node_t *headnode );
-
-
-/* tree.c */
-void						FreeTree( tree_t *tree );
-void						FreeTree_r( node_t *node );
-void						PrintTree_r( node_t *node, int depth );
-void						FreeTreePortals_r( node_t *node );
-
-
-/* patch.c */
-void						ParsePatch( qboolean onlyLights );
-mesh_t						*SubdivideMesh( mesh_t in, float maxError, float minLength );
-void						PatchMapDrawSurfs( entity_t *e );
-
-
-/* tjunction.c */
-void						FixTJunctions( entity_t *e );
-
-
-/* fog.c */
-winding_t					*WindingFromDrawSurf( mapDrawSurface_t *ds );
-void						FogDrawSurfaces( entity_t *e );
-int							FogForPoint( vec3_t point, float epsilon );
-int							FogForBounds( vec3_t mins, vec3_t maxs, float epsilon );
-void						CreateMapFogs( void );
-
-
-/* facebsp.c */
-face_t						*MakeStructuralBSPFaceList( brush_t *list );
-face_t						*MakeVisibleBSPFaceList( brush_t *list );
-tree_t						*FaceBSP( face_t *list );
-
-
-/* model.c */
-void						PicoPrintFunc( int level, const char *str );
-void						PicoLoadFileFunc( char *name, byte **buffer, int *bufSize );
-picoModel_t					*FindModel( char *name, int frame );
-picoModel_t					*LoadModel( char *name, int frame );
-void						InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale );
-void						AddTriangleModels( entity_t *e );
-
-
-/* surface.c */
-mapDrawSurface_t			*AllocDrawSurface( surfaceType_t type );
-void						FinishSurface( mapDrawSurface_t *ds );
-void						StripFaceSurface( mapDrawSurface_t *ds );
-qboolean					CalcSurfaceTextureRange( mapDrawSurface_t *ds );
-qboolean					CalcLightmapAxis( vec3_t normal, vec3_t axis );
-void						ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds );
-void						ClassifyEntitySurfaces( entity_t *e );
-void						TidyEntitySurfaces( entity_t *e );
-mapDrawSurface_t			*CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si );
-mapDrawSurface_t			*MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si );
-qboolean					IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c );
-void						ClearSurface( mapDrawSurface_t *ds );
-void						AddEntitySurfaceModels( entity_t *e );
-mapDrawSurface_t			*DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w );
-mapDrawSurface_t			*DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
-mapDrawSurface_t			*DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, char *flareShader, int lightStyle );
-mapDrawSurface_t			*DrawSurfaceForShader( char *shader );
-void						ClipSidesIntoTree( entity_t *e, tree_t *tree );
-void						MakeDebugPortalSurfs( tree_t *tree );
-void						MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader );
-void						SubdivideFaceSurfaces( entity_t *e, tree_t *tree );
-void						AddEntitySurfaceModels( entity_t *e );
-int							AddSurfaceModels( mapDrawSurface_t *ds );
-void						FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
-
-
-/* surface_fur.c */
-void						Fur( mapDrawSurface_t *src );
-
-
-/* surface_foliage.c */
-void						Foliage( mapDrawSurface_t *src );
-
-
-/* ydnar: surface_meta.c */
-void						ClearMetaTriangles( void );
-int							FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum );
-void						MakeEntityMetaTriangles( entity_t *e );
-void						FixMetaTJunctions( void );
-void						SmoothMetaTriangles( void );
-void						MergeMetaTriangles( void );
-
-
-/* surface_extra.c */
-void						SetDefaultSampleSize( int sampleSize );
-
-void						SetSurfaceExtra( mapDrawSurface_t *ds, int num );
-
-shaderInfo_t				*GetSurfaceExtraShaderInfo( int num );
-int							GetSurfaceExtraParentSurfaceNum( int num );
-int							GetSurfaceExtraEntityNum( int num );
-int							GetSurfaceExtraCastShadows( int num );
-int							GetSurfaceExtraRecvShadows( int num );
-int							GetSurfaceExtraSampleSize( int num );
-float						GetSurfaceExtraLongestCurve( int num );
-void						GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis );
-
-void						WriteSurfaceExtraFile( const char *path );
-void						LoadSurfaceExtraFile( const char *path );
-
-
-/* decals.c */
-void						ProcessDecals( void );
-void						MakeEntityDecals( entity_t *e );
-
-
-/* brush_primit.c */
-void						ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY);
-
-
-/* vis.c */
-fixedWinding_t				*NewFixedWinding( int points );
-int							VisMain( int argc, char **argv );
-
-/* visflow.c */
-int							CountBits( byte *bits, int numbits );
-void						PassageFlow( int portalnum );
-void						CreatePassages( int portalnum );
-void						PassageMemory( void );
-void						BasePortalVis( int portalnum );
-void						BetterPortalVis( int portalnum );
-void						PortalFlow( int portalnum );
-void						PassagePortalFlow( int portalnum );
-
-
-
-/* light.c  */
-float						PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w );
-int							LightContributionToSample( trace_t *trace );
-void						LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colors[ MAX_LIGHTMAPS ] );
-int							LightContributionToPoint( trace_t *trace );
-int							LightMain( int argc, char **argv );
-
-
-/* light_trace.c */
-void						SetupTraceNodes( void );
-void						TraceLine( trace_t *trace );
-float						SetupTrace( trace_t *trace );
-
-
-/* light_bounce.c */
-qboolean					RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] );
-void						RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw );
-void						RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw );
-void						RadCreateDiffuseLights( void );
-void						RadFreeLights();
-
-
-/* light_ydnar.c */
-void						ColorToBytes( const float *color, byte *colorBytes, float scale );
-void						SmoothNormals( void );
-
-void						MapRawLightmap( int num );
-void						IlluminateRawLightmap( int num );
-void						IlluminateVertexes( int num );
-
-void						SetupBrushes( void );
-void						SetupClusters( void );
-qboolean					ClusterVisible( int a, int b );
-qboolean					ClusterVisibleToPoint( vec3_t point, int cluster );
-int							ClusterForPoint( vec3_t point );
-int							ClusterForPointExt( vec3_t point, float epsilon );
-int							ClusterForPointExtFilter( vec3_t point, float epsilon, int numClusters, int *clusters );
-int							ShaderForPointInLeaf( vec3_t point, int leafNum, float epsilon, int wantContentFlags, int wantSurfaceFlags, int *contentFlags, int *surfaceFlags );
-void						SetupEnvelopes( qboolean forGrid, qboolean fastFlag );
-void						FreeTraceLights( trace_t *trace );
-void						CreateTraceLightsForBounds( vec3_t mins, vec3_t maxs, vec3_t normal, int numClusters, int *clusters, int flags, trace_t *trace );
-void						CreateTraceLightsForSurface( int num, trace_t *trace );
-
-
-/* lightmaps_ydnar.c */
-void						ExportLightmaps( void );
-
-int							ExportLightmapsMain( int argc, char **argv );
-int							ImportLightmapsMain( int argc, char **argv );
-
-void						SetupSurfaceLightmaps( void );
-void						StitchSurfaceLightmaps( void );
-void						StoreSurfaceLightmaps( void );
-
-
-/* image.c */
-void						ImageFree( image_t *image );
-image_t						*ImageFind( const char *filename );
-image_t						*ImageLoad( const char *filename );
-
-
-/* shaders.c */
-void						AlphaMod( alphaMod_t *am, int numVerts, bspDrawVert_t *drawVerts );
-
-void						TcMod( tcMod_t mod, float st[ 2 ] );
-void						TcModIdentity( tcMod_t mod );
-void						TcModMultiply( tcMod_t a, tcMod_t b, tcMod_t out );
-void						TcModTranslate( tcMod_t mod, float s, float t );
-void						TcModScale( tcMod_t mod, float s, float t );
-void						TcModRotate( tcMod_t mod, float euler );
-
-qboolean					ApplySurfaceParm( char *name, int *contentFlags, int *surfaceFlags, int *compileFlags );
-
-void						BeginMapShaderFile( const char *mapFile );
-void						WriteMapShaderFile( void );
-shaderInfo_t				*CustomShader( shaderInfo_t *si, char *find, char *replace );
-void						EmitVertexRemapShader( char *from, char *to );
-
-void						LoadShaderInfo( void );
-shaderInfo_t				*ShaderInfoForShader( const char *shader );
-
-
-/* bspfile_abstract.c */
-void						SetGridPoints( int n );
-void						SetDrawVerts( int n );
-void						IncDrawVerts();
-void						SetDrawSurfaces(int n);
-void						SetDrawSurfacesBuffer();
-void						BSPFilesCleanup();
-
-void						SwapBlock( int *block, int size );
-
-int							GetLumpElements( bspHeader_t *header, int lump, int size );
-void						*GetLump( bspHeader_t *header, int lump );
-int							CopyLump( bspHeader_t *header, int lump, void *dest, int size );
-void						AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length );
-
-void						LoadBSPFile( const char *filename );
-void						WriteBSPFile( const char *filename );
-void						PrintBSPFileSizes( void );
-
-epair_t						*ParseEPair( void );
-void						ParseEntities( void );
-void						UnparseEntities( void );
-void						PrintEntity( const entity_t *ent );
-void						SetKeyValue( entity_t *ent, const char *key, const char *value );
-const char					*ValueForKey( const entity_t *ent, const char *key );
-int							IntForKey( const entity_t *ent, const char *key );
-vec_t						FloatForKey( const entity_t *ent, const char *key );
-void						GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec );
-entity_t					*FindTargetEntity( const char *target );
-void						GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows );
-
-
-/* bspfile_ibsp.c */
-void						LoadIBSPFile( const char *filename );
-void						WriteIBSPFile( const char *filename );
-
-
-/* bspfile_rbsp.c */
-void						LoadRBSPFile( const char *filename );
-void						WriteRBSPFile( const char *filename );
-
-
-
-/* -------------------------------------------------------------------------------
-
-bsp/general global variables
-
-------------------------------------------------------------------------------- */
-
-#ifdef MAIN_C
-	#define Q_EXTERN
-	#define Q_ASSIGN( a )	= a
-#else
-	#define Q_EXTERN extern
-	#define Q_ASSIGN( a )	
-#endif
-
-/* game support */
-Q_EXTERN game_t				games[]
-#ifndef MAIN_C
-							;
-#else
-							=
-							{
-								#include "game_quake3.h"
-								,
-								#include "game_tenebrae.h"
-								,
-								#include "game_wolf.h"
-								,
-								#include "game_wolfet.h"/* most be after game_wolf.h as they share defines! */
-								,
-								#include "game_ef.h"
-								,
-								#include "game_sof2.h"
-								,
-								#include "game_jk2.h"	/* most be after game_sof2.h as they share defines! */
-								,
-								#include "game_ja.h"	/* most be after game_jk2.h as they share defines! */
-								,
-								{ NULL, NULL, NULL, NULL, NULL, qfalse, 0, 0, NULL }	/* null game */
-							};
-#endif
-Q_EXTERN game_t				*game Q_ASSIGN( &games[ 0 ] );
-
-
-/* general */
-Q_EXTERN int				numImages Q_ASSIGN( 0 );
-Q_EXTERN image_t			images[ MAX_IMAGES ];
-
-Q_EXTERN int				numPicoModels Q_ASSIGN( 0 );
-Q_EXTERN picoModel_t		*picoModels[ MAX_MODELS ];
-
-Q_EXTERN shaderInfo_t		*shaderInfo Q_ASSIGN( NULL );
-Q_EXTERN int				numShaderInfo Q_ASSIGN( 0 );
-Q_EXTERN int				numVertexRemaps Q_ASSIGN( 0 );
-
-Q_EXTERN surfaceParm_t		custSurfaceParms[ MAX_CUST_SURFACEPARMS ];
-Q_EXTERN int				numCustSurfaceParms Q_ASSIGN( 0 );
-
-Q_EXTERN char				mapName[ MAX_QPATH ];	/* ydnar: per-map custom shaders for larger lightmaps */
-Q_EXTERN char				mapShaderFile[ 1024 ];
-Q_EXTERN qboolean			warnImage Q_ASSIGN( qtrue );
-
-/* ydnar: sinusoid samples */
-Q_EXTERN float				jitters[ MAX_JITTERS ];
-
-
-/* commandline arguments */
-Q_EXTERN qboolean			verbose;
-Q_EXTERN qboolean			verboseEntities Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			force Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			infoMode Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			useCustomInfoParms Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			noprune Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			leaktest Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			nodetail Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			nosubdivide Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			notjunc Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			fulldetail Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			nowater Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			noCurveBrushes Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			fakemap Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			coplanar Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			nofog Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			noHint Q_ASSIGN( qfalse );				/* ydnar */
-Q_EXTERN qboolean			renameModelShaders Q_ASSIGN( qfalse );	/* ydnar */
-Q_EXTERN qboolean			skyFixHack Q_ASSIGN( qfalse );			/* ydnar */
-
-Q_EXTERN int				patchSubdivisions Q_ASSIGN( 8 );		/* ydnar: -patchmeta subdivisions */
-
-Q_EXTERN int				maxSurfaceVerts Q_ASSIGN( 64 );			/* ydnar */
-Q_EXTERN int				maxSurfaceIndexes Q_ASSIGN( 1000 );		/* ydnar */
-Q_EXTERN float				npDegrees Q_ASSIGN( 0.0f );				/* ydnar: nonplanar degrees */
-Q_EXTERN int				bevelSnap Q_ASSIGN( 0 );				/* ydnar: bevel plane snap */
-Q_EXTERN int				texRange Q_ASSIGN( 0 );
-Q_EXTERN qboolean			flat Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			meta Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			patchMeta Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			emitFlares Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			debugSurfaces Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			debugInset Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			debugPortals Q_ASSIGN( qfalse );
-
-Q_EXTERN double				normalEpsilon Q_ASSIGN( 0.00001 );
-Q_EXTERN double				distanceEpsilon Q_ASSIGN( 0.01 );
-
-
-/* bsp */
-Q_EXTERN int				numMapEntities Q_ASSIGN( 0 );
-
-Q_EXTERN int				blockSize[ 3 ]					/* should be the same as in radiant */
-#ifndef MAIN_C
-							;
-#else
-							= { 1024, 1024, 1024 };
-#endif
-
-Q_EXTERN char				name[ 1024 ];
-Q_EXTERN char				source[ 1024 ];
-Q_EXTERN char				outbase[ 32 ];
-
-Q_EXTERN int				sampleSize;						/* lightmap sample size in units */
-
-Q_EXTERN int				mapEntityNum Q_ASSIGN( 0 );
-
-Q_EXTERN int				entitySourceBrushes;
-
-Q_EXTERN plane_t			mapplanes[ MAX_MAP_PLANES ];	/* mapplanes[ num ^ 1 ] will always be the mirror or mapplanes[ num ] */
-Q_EXTERN int				nummapplanes;					/* nummapplanes will always be even */
-Q_EXTERN int				numMapPatches;
-Q_EXTERN vec3_t				mapMins, mapMaxs;
-
-Q_EXTERN int				defaultFogNum Q_ASSIGN( -1 );	/* ydnar: cleaner fog handling */
-Q_EXTERN int				numMapFogs Q_ASSIGN( 0 );
-Q_EXTERN fog_t				mapFogs[ MAX_MAP_FOGS ];
-
-Q_EXTERN entity_t			*mapEnt;
-Q_EXTERN brush_t			*buildBrush;
-Q_EXTERN int				numActiveBrushes;
-Q_EXTERN int				g_bBrushPrimit;
-
-Q_EXTERN int				numStrippedLights Q_ASSIGN( 0 );
-
-
-/* surface stuff */
-Q_EXTERN mapDrawSurface_t	*mapDrawSurfs Q_ASSIGN( NULL );
-Q_EXTERN int				numMapDrawSurfs;
-
-Q_EXTERN int				numSurfacesByType[ NUM_SURFACE_TYPES ];
-Q_EXTERN int				numClearedSurfaces;
-Q_EXTERN int				numStripSurfaces;
-Q_EXTERN int				numFanSurfaces;
-Q_EXTERN int				numMergedSurfaces;
-Q_EXTERN int				numMergedVerts;
-
-Q_EXTERN int				numRedundantIndexes;
-
-Q_EXTERN int				numSurfaceModels Q_ASSIGN( 0 );
-
-Q_EXTERN byte				debugColors[ 12 ][ 3 ]
-#ifndef MAIN_C
-							;
-#else
-							=
-							{
-								{ 255, 0, 0 },
-								{ 192, 128, 128 },
-								{ 255, 255, 0 },
-								{ 192, 192, 128 },
-								{ 0, 255, 255 },
-								{ 128, 192, 192 },
-								{ 0, 0, 255 },
-								{ 128, 128, 192 },
-								{ 255, 0, 255 },
-								{ 192, 128, 192 },
-								{ 0, 255, 0 },
-								{ 128, 192, 128 }
-							};
-#endif
-
-Q_EXTERN qboolean			skyboxPresent Q_ASSIGN( qfalse );
-Q_EXTERN int				skyboxArea Q_ASSIGN( -1 );
-Q_EXTERN m4x4_t				skyboxTransform;
-
-
-
-/* -------------------------------------------------------------------------------
-
-vis global variables
-
-------------------------------------------------------------------------------- */
-
-/* commandline arguments */
-Q_EXTERN qboolean			fastvis;
-Q_EXTERN qboolean			noPassageVis;
-Q_EXTERN qboolean			passageVisOnly;
-Q_EXTERN qboolean			mergevis;
-Q_EXTERN qboolean			nosort;
-Q_EXTERN qboolean			saveprt;
-Q_EXTERN qboolean			hint;	/* ydnar */
-Q_EXTERN char				inbase[ MAX_QPATH ];
-
-/* other bits */
-Q_EXTERN int				totalvis;
-
-Q_EXTERN float				farPlaneDist;	/* rr2do2, rf, mre, ydnar all contributed to this one... */
-
-Q_EXTERN int				numportals;
-Q_EXTERN int				portalclusters;
-
-Q_EXTERN vportal_t			*portals;
-Q_EXTERN leaf_t				*leafs;
-
-Q_EXTERN vportal_t			*faces;
-Q_EXTERN leaf_t				*faceleafs;
-
-Q_EXTERN int				numfaces;
-
-Q_EXTERN int				c_portaltest, c_portalpass, c_portalcheck;
-Q_EXTERN int				c_portalskip, c_leafskip;
-Q_EXTERN int				c_vistest, c_mighttest;
-Q_EXTERN int				c_chains;
-
-Q_EXTERN byte				*vismap, *vismap_p, *vismap_end;
-
-Q_EXTERN int				testlevel;
-
-Q_EXTERN byte				*uncompressed;
-
-Q_EXTERN int				leafbytes, leaflongs;
-Q_EXTERN int				portalbytes, portallongs;
-
-Q_EXTERN vportal_t			*sorted_portals[ MAX_MAP_PORTALS * 2 ];
-
-
-
-/* -------------------------------------------------------------------------------
-
-light global variables
-
-------------------------------------------------------------------------------- */
-
-/* commandline arguments */
-Q_EXTERN qboolean			noSurfaces;
-
-Q_EXTERN qboolean			deluxemap;
-Q_EXTERN qboolean			debugDeluxemap;
-
-Q_EXTERN qboolean			loMem Q_ASSIGN( qfalse );
-
-Q_EXTERN qboolean			fast;
-Q_EXTERN qboolean			faster;
-Q_EXTERN qboolean			fastgrid;
-Q_EXTERN qboolean			fastbounce;
-Q_EXTERN qboolean			cheap;
-Q_EXTERN qboolean			cheapgrid;
-Q_EXTERN qboolean			smooth;
-Q_EXTERN int				bounce;
-Q_EXTERN qboolean			bounceOnly;
-Q_EXTERN qboolean			bouncing;
-Q_EXTERN qboolean			bouncegrid;
-Q_EXTERN qboolean			normalmap;
-Q_EXTERN qboolean			trisoup;
-Q_EXTERN qboolean			shade;
-Q_EXTERN float				shadeAngleDegrees Q_ASSIGN( 0.0f );
-Q_EXTERN int				superSample Q_ASSIGN( 0 );
-Q_EXTERN int				lightSamples Q_ASSIGN( 1 );
-Q_EXTERN qboolean			filter;
-Q_EXTERN qboolean			sunOnly;
-Q_EXTERN int				approximateTolerance Q_ASSIGN( 0 );
-Q_EXTERN qboolean			noCollapse;
-Q_EXTERN qboolean			debug;
-Q_EXTERN qboolean			debugSurfaces;
-Q_EXTERN qboolean			debugUnused;
-Q_EXTERN qboolean			debugAxis;
-Q_EXTERN qboolean			debugCluster;
-Q_EXTERN qboolean			debugOrigin;
-Q_EXTERN qboolean			exportLightmaps;
-Q_EXTERN qboolean			externalLightmaps;
-Q_EXTERN int				lmCustomSize Q_ASSIGN( LIGHTMAP_WIDTH );
-
-/* standard flags */
-Q_EXTERN qboolean			noTrace;
-Q_EXTERN qboolean			patchShadows;
-Q_EXTERN qboolean			dump;
-Q_EXTERN qboolean			extra;
-Q_EXTERN qboolean			extraWide;
-Q_EXTERN qboolean			lightmapBorder;
-
-Q_EXTERN qboolean			noSurfaces;
-
-Q_EXTERN int				sampleSize Q_ASSIGN( DEFAULT_LIGHTMAP_SAMPLE_SIZE );
-Q_EXTERN qboolean			noVertexLighting Q_ASSIGN( qfalse );
-Q_EXTERN qboolean			noGridLighting Q_ASSIGN( qfalse );
-
-/* longest distance across the map */
-Q_EXTERN float				maxMapDistance Q_ASSIGN( 0 );
-
-/* for run time tweaking of light sources */
-Q_EXTERN float				pointScale Q_ASSIGN( 7500.0f );
-Q_EXTERN float				areaScale Q_ASSIGN( 0.25f );
-Q_EXTERN float				skyScale Q_ASSIGN( 1.0f );
-Q_EXTERN float				bounceScale Q_ASSIGN( 0.25f );
-
-/* ydnar: for runtime tweaking of falloff tolerance */
-Q_EXTERN float				falloffTolerance Q_ASSIGN( 1.0f );
-
-Q_EXTERN qboolean			exactPointToPolygon Q_ASSIGN( qtrue );
-
-Q_EXTERN float				formFactorValueScale Q_ASSIGN( 3.0f );
-
-Q_EXTERN float				linearScale Q_ASSIGN( 1.0f / 8000.0f );
-
-Q_EXTERN light_t			*lights;
-Q_EXTERN int				numPointLights;
-Q_EXTERN int				numSpotLights;
-Q_EXTERN int				numSunLights;
-Q_EXTERN int				numAreaLights;
-
-/* ydnar: for luxel placement */
-Q_EXTERN int				numSurfaceClusters, maxSurfaceClusters;
-Q_EXTERN int				*surfaceClusters;
-
-/* ydnar: for radiosity */
-Q_EXTERN int				numDiffuseLights;
-Q_EXTERN int				numBrushDiffuseLights;
-Q_EXTERN int				numTriangleDiffuseLights;
-Q_EXTERN int				numPatchDiffuseLights;
-
-/* ydnar: general purpose extra copy of drawvert list */
-Q_EXTERN bspDrawVert_t		*yDrawVerts;
-
-/* ydnar: for tracing statistics */
-Q_EXTERN int				minSurfacesTested;
-Q_EXTERN int				maxSurfacesTested;
-Q_EXTERN int				totalSurfacesTested;
-Q_EXTERN int				totalTraces;
-
-Q_EXTERN FILE				*dumpFile;
-
-Q_EXTERN int				c_visible, c_occluded;
-Q_EXTERN int				c_subsampled;	/* ydnar */
-
-Q_EXTERN int				defaultLightSubdivide Q_ASSIGN( 999 );
-
-Q_EXTERN vec3_t				ambientColor;
-Q_EXTERN vec3_t				minLight, minVertexLight, minGridLight;
-
-Q_EXTERN int				*entitySurface;
-Q_EXTERN vec3_t				*surfaceOrigin;
-
-Q_EXTERN vec3_t				sunDirection;
-Q_EXTERN vec3_t				sunLight;
-
-/* tracing */
-Q_EXTERN int				c_totalTrace;
-Q_EXTERN int				c_cullTrace, c_testTrace;
-Q_EXTERN int				c_testFacets;
-
-/* ydnar: light optimization */
-Q_EXTERN float				subdivideThreshold Q_ASSIGN( DEFAULT_SUBDIVIDE_THRESHOLD );
-
-Q_EXTERN int				numOpaqueBrushes, maxOpaqueBrush;
-Q_EXTERN byte				*opaqueBrushes;
-
-Q_EXTERN int				numLights;
-Q_EXTERN int				numCulledLights;
-
-Q_EXTERN int				gridBoundsCulled;
-Q_EXTERN int				gridEnvelopeCulled;
-
-Q_EXTERN int				lightsBoundsCulled;
-Q_EXTERN int				lightsEnvelopeCulled;
-Q_EXTERN int				lightsPlaneCulled;
-Q_EXTERN int				lightsClusterCulled;
-
-/* ydnar: radiosity */
-Q_EXTERN float				diffuseSubdivide Q_ASSIGN( 256.0f );
-Q_EXTERN float				minDiffuseSubdivide Q_ASSIGN( 64.0f );
-Q_EXTERN int				numDiffuseSurfaces Q_ASSIGN( 0 );
-
-/* ydnar: list of surface information necessary for lightmap calculation */
-Q_EXTERN surfaceInfo_t		*surfaceInfos Q_ASSIGN( NULL );
-
-/* ydnar: sorted list of surfaces */
-Q_EXTERN int				*sortSurfaces Q_ASSIGN( NULL );
-
-/* clumps of surfaces that share a raw lightmap */
-Q_EXTERN int				numLightSurfaces Q_ASSIGN( 0 );
-Q_EXTERN int				*lightSurfaces Q_ASSIGN( NULL );
-
-/* raw lightmaps */
-Q_EXTERN int				numRawSuperLuxels Q_ASSIGN( 0 );
-Q_EXTERN int				numRawLightmaps Q_ASSIGN( 0 );
-Q_EXTERN rawLightmap_t		*rawLightmaps Q_ASSIGN( NULL );
-Q_EXTERN int				*sortLightmaps Q_ASSIGN( NULL );
-
-/* vertex luxels */
-Q_EXTERN float				*vertexLuxels[ MAX_LIGHTMAPS ];
-Q_EXTERN float				*radVertexLuxels[ MAX_LIGHTMAPS ];
-
-/* bsp lightmaps */
-Q_EXTERN int				numLightmapShaders Q_ASSIGN( 0 );
-Q_EXTERN int				numOutLightmaps Q_ASSIGN( 0 );
-Q_EXTERN int				numBSPLightmaps Q_ASSIGN( 0 );
-Q_EXTERN int				numExtLightmaps Q_ASSIGN( 0 );
-Q_EXTERN outLightmap_t		*outLightmaps Q_ASSIGN( NULL );
-
-/* grid points */
-Q_EXTERN int				numRawGridPoints Q_ASSIGN( 0 );
-Q_EXTERN rawGridPoint_t		*rawGridPoints Q_ASSIGN( NULL );
-
-Q_EXTERN int				numSurfsVertexLit Q_ASSIGN( 0 );
-Q_EXTERN int				numSurfsVertexForced Q_ASSIGN( 0 );
-Q_EXTERN int				numSurfsVertexApproximated Q_ASSIGN( 0 );
-Q_EXTERN int				numSurfsLightmapped Q_ASSIGN( 0 );
-Q_EXTERN int				numPlanarsLightmapped Q_ASSIGN( 0 );
-Q_EXTERN int				numNonPlanarsLightmapped Q_ASSIGN( 0 );
-Q_EXTERN int				numPatchesLightmapped Q_ASSIGN( 0 );
-Q_EXTERN int				numPlanarPatchesLightmapped Q_ASSIGN( 0 );
-
-Q_EXTERN int				numLuxels Q_ASSIGN( 0 );
-Q_EXTERN int				numLuxelsMapped Q_ASSIGN( 0 );
-Q_EXTERN int				numLuxelsOccluded Q_ASSIGN( 0 );
-Q_EXTERN int				numLuxelsIlluminated Q_ASSIGN( 0 );
-Q_EXTERN int				numVertsIlluminated Q_ASSIGN( 0 );
-
-/* lightgrid */
-Q_EXTERN vec3_t				gridMins;
-Q_EXTERN int				gridBounds[ 3 ];
-Q_EXTERN vec3_t				gridSize
-#ifndef MAIN_C
-							;
-#else
-							= { 64, 64, 128 };
-#endif
-
-
-
-/* -------------------------------------------------------------------------------
-
-abstracted bsp globals
-
-------------------------------------------------------------------------------- */
-
-Q_EXTERN int				numEntities Q_ASSIGN( 0 );
-Q_EXTERN int				numBSPEntities Q_ASSIGN( 0 );
-Q_EXTERN entity_t			entities[ MAX_MAP_ENTITIES ];
-
-Q_EXTERN int				numBSPModels Q_ASSIGN( 0 );
-Q_EXTERN bspModel_t			bspModels[ MAX_MAP_MODELS ];
-
-Q_EXTERN int				numBSPShaders Q_ASSIGN( 0 );
-Q_EXTERN bspShader_t		bspShaders[ MAX_MAP_MODELS ];
-
-Q_EXTERN int				bspEntDataSize Q_ASSIGN( 0 );
-Q_EXTERN char				bspEntData[ MAX_MAP_ENTSTRING ];
-
-Q_EXTERN int				numBSPLeafs Q_ASSIGN( 0 );
-Q_EXTERN bspLeaf_t			bspLeafs[ MAX_MAP_LEAFS ];
-
-Q_EXTERN int				numBSPPlanes Q_ASSIGN( 0 );
-Q_EXTERN bspPlane_t			bspPlanes[ MAX_MAP_PLANES ];
-
-Q_EXTERN int				numBSPNodes Q_ASSIGN( 0 );
-Q_EXTERN bspNode_t			bspNodes[ MAX_MAP_NODES ];
-
-Q_EXTERN int				numBSPLeafSurfaces Q_ASSIGN( 0 );
-Q_EXTERN int				bspLeafSurfaces[ MAX_MAP_LEAFFACES ];
-
-Q_EXTERN int				numBSPLeafBrushes Q_ASSIGN( 0 );
-Q_EXTERN int				bspLeafBrushes[ MAX_MAP_LEAFBRUSHES ];
-
-Q_EXTERN int				numBSPBrushes Q_ASSIGN( 0 );
-Q_EXTERN bspBrush_t			bspBrushes[ MAX_MAP_BRUSHES ];
-
-Q_EXTERN int				numBSPBrushSides Q_ASSIGN( 0 );
-Q_EXTERN bspBrushSide_t		bspBrushSides[ MAX_MAP_BRUSHSIDES ];
-
-Q_EXTERN int				numBSPLightBytes Q_ASSIGN( 0 );
-Q_EXTERN byte				*bspLightBytes Q_ASSIGN( NULL );
-
-//%	Q_EXTERN int				numBSPGridPoints Q_ASSIGN( 0 );
-//%	Q_EXTERN byte				*bspGridPoints Q_ASSIGN( NULL );
-
-Q_EXTERN int				numBSPGridPoints Q_ASSIGN( 0 );
-Q_EXTERN bspGridPoint_t		*bspGridPoints Q_ASSIGN( NULL );
-
-Q_EXTERN int				numBSPVisBytes Q_ASSIGN( 0 );
-Q_EXTERN byte				bspVisBytes[ MAX_MAP_VISIBILITY ];
-
-Q_EXTERN int				numBSPDrawVerts Q_ASSIGN( 0 );
-Q_EXTERN bspDrawVert_t		*bspDrawVerts Q_ASSIGN( NULL );
-
-Q_EXTERN int				numBSPDrawIndexes Q_ASSIGN( 0 );
-Q_EXTERN int				bspDrawIndexes[ MAX_MAP_DRAW_INDEXES ];
-
-Q_EXTERN int				numBSPDrawSurfaces Q_ASSIGN( 0 );
-Q_EXTERN bspDrawSurface_t	*bspDrawSurfaces Q_ASSIGN( NULL );
-
-Q_EXTERN int				numBSPFogs Q_ASSIGN( 0 );
-Q_EXTERN bspFog_t			bspFogs[ MAX_MAP_FOGS ];
-
-
-
-/* end marker */
-#endif
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#ifndef Q3MAP2_H
+#define Q3MAP2_H
+
+
+
+/* version */
+#define Q3MAP_VERSION	"2.5.11"
+#define Q3MAP_MOTD		"A well-oiled toaster oven"
+
+
+
+/* -------------------------------------------------------------------------------
+
+dependencies
+
+------------------------------------------------------------------------------- */
+
+/* platform-specific */
+#if defined( __linux__ ) || defined( __APPLE__ )
+	#define Q_UNIX
+#endif
+
+#ifdef Q_UNIX
+	#include <unistd.h>
+	#include <pwd.h>
+	#include <limits.h>
+#endif
+
+#ifdef _WIN32
+	#include <windows.h>
+#endif
+
+
+/* general */
+#include "version.h"			/* ttimo: might want to guard that if built outside of the GtkRadiant tree */
+
+#include "cmdlib.h"
+#include "mathlib.h"
+#include "md5lib.h"
+#include "ddslib.h"
+
+#include "picomodel.h"
+
+#include "scriplib.h"
+#include "polylib.h"
+#include "imagelib.h"
+#include "qthreads.h"
+#include "inout.h"
+#include "vfs.h"
+#include "png.h"
+#include "radiant_jpeglib.h"
+
+#include <stdlib.h>
+
+
+
+/* -------------------------------------------------------------------------------
+
+port-related hacks
+
+------------------------------------------------------------------------------- */
+
+#define MAC_STATIC_HACK			0
+#if defined( __APPLE__ ) && MAC_STATIC_HACK 
+	#define MAC_STATIC			static
+#else
+	#define MAC_STATIC			
+#endif
+
+#if 1
+	#ifdef _WIN32
+		#define Q_stricmp			stricmp
+		#define Q_strncasecmp		strnicmp
+	#else
+		#define Q_stricmp			strcasecmp
+		#define Q_strncasecmp		strncasecmp
+	#endif
+#endif
+
+/* macro version */
+#define VectorMA( a, s, b, c )	((c)[ 0 ] = (a)[ 0 ] + (s) * (b)[ 0 ], (c)[ 1 ] = (a)[ 1 ] + (s) * (b)[ 1 ], (c)[ 2 ] = (a)[ 2 ] + (s) * (b)[ 2 ])
+
+
+
+/* -------------------------------------------------------------------------------
+
+constants
+
+------------------------------------------------------------------------------- */
+
+/* general */
+#define MAX_QPATH				64
+
+#define MAX_IMAGES				512
+#define DEFAULT_IMAGE			"*default"
+
+#define MAX_MODELS				512
+
+#define	DEF_BACKSPLASH_FRACTION	0.05f	/* 5% backsplash by default */
+#define	DEF_BACKSPLASH_DISTANCE	23
+
+#define DEF_RADIOSITY_BOUNCE	1.0f	/* ydnar: default to 100% re-emitted light */
+
+#define	MAX_SHADER_INFO			8192
+#define MAX_CUST_SURFACEPARMS	64
+
+#define	SHADER_MAX_VERTEXES		1000
+#define	SHADER_MAX_INDEXES		(6 * SHADER_MAX_VERTEXES)
+
+#define MAX_JITTERS				256
+
+
+/* epair parsing (note case-sensitivity directive) */
+#define CASE_INSENSITIVE_EPAIRS	1
+
+#if CASE_INSENSITIVE_EPAIRS
+	#define EPAIR_STRCMP		Q_stricmp
+#else
+	#define EPAIR_STRCMP		strcmp
+#endif
+
+
+/* ydnar: compiler flags, because games have widely varying content/surface flags */
+#define C_SOLID					0x00000001
+#define C_TRANSLUCENT			0x00000002
+#define C_STRUCTURAL			0x00000004
+#define C_HINT					0x00000008
+#define C_NODRAW				0x00000010
+#define C_LIGHTGRID				0x00000020
+#define C_ALPHASHADOW			0x00000040
+#define C_LIGHTFILTER			0x00000080
+#define C_VERTEXLIT				0x00000100
+#define C_LIQUID				0x00000200
+#define C_FOG					0x00000400
+#define C_SKY					0x00000800
+#define C_ORIGIN				0x00001000
+#define C_AREAPORTAL			0x00002000
+#define C_ANTIPORTAL			0x00004000	/* like hint, but doesn't generate portals */
+#define C_SKIP					0x00008000	/* like hint, but skips this face (doesn't split bsp) */
+#define C_NOMARKS				0x00010000	/* no decals */
+
+#define C_DETAIL				0x08000000	/* THIS MUST BE THE SAME AS IN RADIANT! */
+
+
+/* shadow flags */
+#define WORLDSPAWN_CAST_SHADOWS	1
+#define WORLDSPAWN_RECV_SHADOWS	1
+#define ENTITY_CAST_SHADOWS		0
+#define ENTITY_RECV_SHADOWS		1
+
+
+/* bsp */
+#define	MAX_PATCH_SIZE			32
+#define	MAX_BRUSH_SIDES			1024
+#define MAX_BUILD_SIDES			300
+
+#define	MAX_EXPANDED_AXIS		128
+
+#define	CLIP_EPSILON			0.1f
+#define	PLANESIDE_EPSILON		0.001f
+#define	PLANENUM_LEAF			-1
+
+#define	HINT_PRIORITY			1000		/* ydnar: force hint splits first and antiportal/areaportal splits last */
+#define ANTIPORTAL_PRIORITY		-1000
+#define AREAPORTAL_PRIORITY		-1000
+
+#define	PSIDE_FRONT				1
+#define	PSIDE_BACK				2
+#define	PSIDE_BOTH				(PSIDE_FRONT | PSIDE_BACK)
+#define	PSIDE_FACING			4
+
+#define BPRIMIT_UNDEFINED		0
+#define BPRIMIT_OLDBRUSHES		1
+#define BPRIMIT_NEWBRUSHES		2
+
+
+/* vis */
+#define	VIS_HEADER_SIZE			8
+
+#define SEPERATORCACHE			/* seperator caching helps a bit */
+
+#define	PORTALFILE				"PRT1"
+
+#define	MAX_PORTALS				32768
+#define MAX_SEPERATORS			MAX_POINTS_ON_WINDING
+#define	MAX_POINTS_ON_FIXED_WINDING	24	/* ydnar: increased this from 12 at the expense of more memory */
+#define	MAX_PORTALS_ON_LEAF		128
+
+
+/* light */
+#define EMIT_POINT				0
+#define EMIT_AREA				1
+#define EMIT_SPOT				2
+#define EMIT_SUN				3
+
+#define LIGHT_ATTEN_LINEAR		1
+#define LIGHT_ATTEN_ANGLE		2
+#define LIGHT_ATTEN_DISTANCE	4
+#define LIGHT_TWOSIDED			8
+#define LIGHT_GRID				16
+#define LIGHT_SURFACES			32
+#define LIGHT_DARK				64		/* probably never use this */
+#define LIGHT_FAST				256
+#define LIGHT_FAST_TEMP			512
+#define LIGHT_FAST_ACTUAL		(LIGHT_FAST | LIGHT_FAST_TEMP)
+#define LIGHT_NEGATIVE			1024
+
+#define LIGHT_SUN_DEFAULT		(LIGHT_ATTEN_ANGLE | LIGHT_GRID | LIGHT_SURFACES)
+#define LIGHT_AREA_DEFAULT		(LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES)	/* q3a and wolf are the same */
+#define LIGHT_Q3A_DEFAULT		(LIGHT_ATTEN_ANGLE | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES | LIGHT_FAST)
+#define LIGHT_WOLF_DEFAULT		(LIGHT_ATTEN_LINEAR | LIGHT_ATTEN_DISTANCE | LIGHT_GRID | LIGHT_SURFACES | LIGHT_FAST)
+
+#define MAX_TRACE_TEST_NODES	256
+#define DEFAULT_INHIBIT_RADIUS	1.5f
+
+#define LUXEL_EPSILON			0.125f
+#define VERTEX_EPSILON			-0.125f
+#define GRID_EPSILON			0.0f
+
+#define DEFAULT_LIGHTMAP_SAMPLE_SIZE	16
+#define DEFAULT_LIGHTMAP_SAMPLE_OFFSET	1.0f
+#define DEFAULT_SUBDIVIDE_THRESHOLD		1.0f
+
+#define	EXTRA_SCALE				2	/* -extrawide = -super 2 */
+#define	EXTRAWIDE_SCALE			2	/* -extrawide = -super 2 -filter */
+
+#define CLUSTER_UNMAPPED		-1
+#define CLUSTER_OCCLUDED		-2
+#define CLUSTER_FLOODED			-3
+
+#define VERTEX_LUXEL_SIZE		3
+#define BSP_LUXEL_SIZE			3
+#define RAD_LUXEL_SIZE			3
+#define SUPER_LUXEL_SIZE		4
+#define SUPER_ORIGIN_SIZE		3
+#define SUPER_NORMAL_SIZE		3
+#define SUPER_DELUXEL_SIZE		3
+#define BSP_DELUXEL_SIZE		3
+
+#define VERTEX_LUXEL( s, v )	(vertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
+#define RAD_VERTEX_LUXEL( s, v )(radVertexLuxels[ s ] + ((v) * VERTEX_LUXEL_SIZE))
+#define BSP_LUXEL( s, x, y )	(lm->bspLuxels[ s ] + ((((y) * lm->w) + (x)) * BSP_LUXEL_SIZE))
+#define RAD_LUXEL( s, x, y )	(lm->radLuxels[ s ] + ((((y) * lm->w) + (x)) * RAD_LUXEL_SIZE))
+#define SUPER_LUXEL( s, x, y )	(lm->superLuxels[ s ] + ((((y) * lm->sw) + (x)) * SUPER_LUXEL_SIZE))
+#define SUPER_ORIGIN( x, y )	(lm->superOrigins + ((((y) * lm->sw) + (x)) * SUPER_ORIGIN_SIZE))
+#define SUPER_NORMAL( x, y )	(lm->superNormals + ((((y) * lm->sw) + (x)) * SUPER_NORMAL_SIZE))
+#define SUPER_CLUSTER( x, y )	(lm->superClusters + (((y) * lm->sw) + (x)))
+#define SUPER_DELUXEL( x, y )	(lm->superDeluxels + ((((y) * lm->sw) + (x)) * SUPER_DELUXEL_SIZE))
+#define BSP_DELUXEL( x, y )		(lm->bspDeluxels + ((((y) * lm->w) + (x)) * BSP_DELUXEL_SIZE))
+
+
+
+/* -------------------------------------------------------------------------------
+
+abstracted bsp file
+
+------------------------------------------------------------------------------- */
+
+#define EXTERNAL_LIGHTMAP		"lm_%04d.tga"
+
+#define MAX_LIGHTMAPS			4			/* RBSP */
+#define MAX_LIGHT_STYLES		64
+#define	MAX_SWITCHED_LIGHTS		32
+#define LS_NORMAL				0x00
+#define LS_UNUSED				0xFE
+#define	LS_NONE					0xFF
+
+#define MAX_LIGHTMAP_SHADERS	256
+
+/* ok to increase these at the expense of more memory */
+#define	MAX_MAP_MODELS			0x400
+#define	MAX_MAP_BRUSHES			0x8000
+#define	MAX_MAP_ENTITIES		0x1000		//%	0x800	/* ydnar */
+#define	MAX_MAP_ENTSTRING		0x80000		//%	0x40000	/* ydnar */
+#define	MAX_MAP_SHADERS			0x400
+
+#define	MAX_MAP_AREAS			0x100		/* MAX_MAP_AREA_BYTES in q_shared must match! */
+#define	MAX_MAP_FOGS			30			//& 0x100	/* RBSP (32 - world fog - goggles) */
+#define	MAX_MAP_PLANES			0x100000	//%	0x20000	/* ydnar for md */
+#define	MAX_MAP_NODES			0x20000
+#define	MAX_MAP_BRUSHSIDES		0x100000	//%	0x20000	/* ydnar */
+#define	MAX_MAP_LEAFS			0x20000
+#define	MAX_MAP_LEAFFACES		0x20000
+#define	MAX_MAP_LEAFBRUSHES		0x40000
+#define	MAX_MAP_PORTALS			0x20000
+#define	MAX_MAP_LIGHTING		0x800000
+#define	MAX_MAP_LIGHTGRID		0x100000	//%	0x800000 /* ydnar: set to points, not bytes */
+#define	MAX_MAP_VISIBILITY		0x200000
+
+#define	MAX_MAP_DRAW_SURFS		0x20000
+#define	MAX_MAP_DRAW_VERTS		0x80000
+#define	MAX_MAP_DRAW_INDEXES	0x80000
+
+
+/* key / value pair sizes in the entities lump */
+#define	MAX_KEY					32
+#define	MAX_VALUE				1024
+
+/* the editor uses these predefined yaw angles to orient entities up or down */
+#define	ANGLE_UP				-1
+#define	ANGLE_DOWN				-2
+
+#define	LIGHTMAP_WIDTH			128
+#define	LIGHTMAP_HEIGHT			128
+
+#define MIN_WORLD_COORD			(-65536)
+#define	MAX_WORLD_COORD			(65536)
+#define WORLD_SIZE				(MAX_WORLD_COORD - MIN_WORLD_COORD)
+
+
+typedef void					(*bspFunc)( const char * );
+
+
+typedef struct
+{
+	int		offset, length;
+}
+bspLump_t;
+
+
+typedef struct
+{
+	char		ident[ 4 ];
+	int			version;
+	
+	bspLump_t	lumps[ 100 ];	/* theoretical maximum # of bsp lumps */
+}
+bspHeader_t;
+
+
+typedef struct
+{
+	float		mins[ 3 ], maxs[ 3 ];
+	int			firstBSPSurface, numBSPSurfaces;
+	int			firstBSPBrush, numBSPBrushes;
+}
+bspModel_t;
+
+
+typedef struct
+{
+	char		shader[ MAX_QPATH ];
+	int			surfaceFlags;
+	int			contentFlags;
+}
+bspShader_t;
+
+
+/* planes x^1 is allways the opposite of plane x */
+
+typedef struct
+{
+	float		normal[ 3 ];
+	float		dist;
+}
+bspPlane_t;
+
+
+typedef struct
+{
+	int			planeNum;
+	int			children[ 2 ];		/* negative numbers are -(leafs+1), not nodes */
+	int			mins[ 3 ];			/* for frustom culling */
+	int			maxs[ 3 ];
+}
+bspNode_t;
+
+
+typedef struct
+{
+	int			cluster;			/* -1 = opaque cluster (do I still store these?) */
+	int			area;
+	
+	int			mins[ 3 ];			/* for frustum culling */
+	int			maxs[ 3 ];
+	
+	int			firstBSPLeafSurface;
+	int			numBSPLeafSurfaces;
+	
+	int			firstBSPLeafBrush;
+	int			numBSPLeafBrushes;
+}
+bspLeaf_t;
+
+
+typedef struct
+{
+	int			planeNum;			/* positive plane side faces out of the leaf */
+	int			shaderNum;
+	int			surfaceNum;			/* RBSP */
+}
+bspBrushSide_t;
+
+
+typedef struct
+{
+	int			firstSide;
+	int			numSides;
+	int			shaderNum;			/* the shader that determines the content flags */
+}
+bspBrush_t;
+
+
+typedef struct
+{
+	char		shader[ MAX_QPATH ];
+	int			brushNum;
+	int			visibleSide;		/* the brush side that ray tests need to clip against (-1 == none) */
+}
+bspFog_t;
+
+
+typedef struct
+{
+	vec3_t		xyz;
+	float		st[ 2 ];
+	float		lightmap[ MAX_LIGHTMAPS ][ 2 ];	/* RBSP */
+	vec3_t		normal;
+	byte		color[ MAX_LIGHTMAPS ][ 4 ];	/* RBSP */
+}
+bspDrawVert_t;
+
+
+typedef enum
+{
+	MST_BAD,
+	MST_PLANAR,
+	MST_PATCH,
+	MST_TRIANGLE_SOUP,
+	MST_FLARE,
+	MST_FOLIAGE
+}
+bspSurfaceType_t;
+
+
+typedef struct bspGridPoint_s
+{
+	byte		ambient[ MAX_LIGHTMAPS ][ 3 ];
+	byte		directed[ MAX_LIGHTMAPS ][ 3 ];
+	byte		styles[ MAX_LIGHTMAPS ];
+	byte		latLong[ 2 ];
+}
+bspGridPoint_t;
+
+
+typedef struct
+{
+	int			shaderNum;
+	int			fogNum;
+	int			surfaceType;
+	
+	int			firstVert;
+	int			numVerts;
+	
+	int			firstIndex;
+	int			numIndexes;
+	
+	byte		lightmapStyles[ MAX_LIGHTMAPS ];						/* RBSP */
+	byte		vertexStyles[ MAX_LIGHTMAPS ];							/* RBSP */
+	int			lightmapNum[ MAX_LIGHTMAPS ];							/* RBSP */
+	int			lightmapX[ MAX_LIGHTMAPS ], lightmapY[ MAX_LIGHTMAPS ];	/* RBSP */
+	int			lightmapWidth, lightmapHeight;
+	
+	vec3_t		lightmapOrigin;
+	vec3_t		lightmapVecs[ 3 ];	/* on patches, [ 0 ] and [ 1 ] are lodbounds */
+	
+	int			patchWidth;
+	int			patchHeight;
+}
+bspDrawSurface_t;
+
+
+
+/* -------------------------------------------------------------------------------
+
+general types
+
+------------------------------------------------------------------------------- */
+
+/* ydnar: for smaller structs */
+typedef char	qb_t;
+
+
+/* ydnar: for q3map_tcMod */
+typedef float	tcMod_t[ 3 ][ 3 ];
+
+
+/* ydnar: for multiple game support */
+typedef struct surfaceParm_s
+{
+	char		*name;
+	int			contentFlags, contentFlagsClear;
+	int			surfaceFlags, surfaceFlagsClear;
+	int			compileFlags, compileFlagsClear;
+}
+surfaceParm_t;
+
+
+typedef struct game_s
+{
+	char				*arg;							/* -game matches this */
+	char				*gamePath;						/* main game data dir */
+	char				*homeBasePath;					/* home sub-dir on unix */
+	char				*magic;							/* magic word for figuring out base path */
+	char				*shaderPath;					/* shader directory */
+	qboolean			wolfLight;						/* when true, lights work like wolf q3map  */
+	qboolean			emitFlares;						/* when true, emit flare surfaces */
+	char				*flareShader;					/* default flare shader (MUST BE SET) */
+	char				*bspIdent;						/* 4-letter bsp file prefix */
+	int					bspVersion;						/* BSP version to use */
+	bspFunc				load, write;					/* load/write function pointers */
+	surfaceParm_t		surfaceParms[ 128 ];			/* surfaceparm array */
+}
+game_t;
+
+
+typedef struct image_s
+{
+	char				*name, *filename;
+	int					refCount;
+	int					width, height;
+	byte				*pixels;
+}
+image_t;
+
+
+typedef struct sun_s
+{
+	struct sun_s		*next;
+	vec3_t				direction, color;
+	float				photons, deviance, filterRadius;
+	int					numSamples;
+}
+sun_t;
+
+
+typedef struct surfaceModel_s 
+{
+	struct surfaceModel_s	*next;
+	char				model[ MAX_QPATH ];
+	float				density, odds;
+	float				minScale, maxScale;
+	float				minAngle, maxAngle;
+	qboolean			oriented;
+}
+surfaceModel_t;
+
+
+/* ydnar/sd: foliage stuff for wolf et (engine-supported optimization of the above) */
+typedef struct foliage_s 
+{
+	struct foliage_s	*next;
+	char				model[ MAX_QPATH ];
+	float				scale, density, odds;
+	qboolean			inverseAlpha;
+}
+foliage_t;
+
+typedef struct foliageInstance_s
+{
+	vec3_t				xyz, normal;
+}
+foliageInstance_t;
+
+
+typedef struct remap_s
+{
+	struct remap_s		*next;
+	char				from[ 1024 ];
+	char				to[ MAX_QPATH ];
+}
+remap_t;
+
+
+typedef enum
+{
+	AM_NONE,
+	AM_DOT_PRODUCT
+}
+alphaModType_t;
+
+
+typedef struct alphaMod_s
+{
+	struct alphaMod_s	*next;
+	alphaModType_t		type;
+	vec_t				data[ 16 ];
+}
+alphaMod_t;
+
+
+typedef enum
+{
+	IM_NONE,
+	IM_OPAQUE,
+	IM_MASKED,
+	IM_BLEND
+}
+implicitMap_t;
+
+
+typedef struct shaderInfo_s
+{
+	char				shader[ MAX_QPATH ];
+	int					surfaceFlags;
+	int					contentFlags;
+	int					compileFlags;
+	float				value;							/* light value */
+	
+	char				backShader[ MAX_QPATH ];		/* for surfaces that generate different front and back passes */
+	char				flareShader[ MAX_QPATH ];		/* for light flares */
+	char				cloneShader[ MAX_QPATH ];		/* ydnar: for cloning of a surface */
+	char				damageShader[ MAX_QPATH ];		/* ydnar: sof2 damage shader name */
+
+	surfaceModel_t		*surfaceModel;					/* ydnar: for distribution of models */
+	foliage_t			*foliage;						/* ydnar/splash damage: wolf et foliage */
+	
+	float				subdivisions;					/* from a "tesssize xxx" */
+	float				backsplashFraction;				/* floating point value, usually 0.05 */
+	float				backsplashDistance;				/* default 16 */
+	float				lightSubdivide;					/* default 999 */
+	float				lightFilterRadius;				/* ydnar: lightmap filtering/blurring radius for lights created by this shader (default: 0) */
+	
+	int					lightmapSampleSize;				/* lightmap sample size */
+	float				lightmapSampleOffset;			/* ydnar: lightmap sample offset (default: 1.0) */
+	
+	float				bounceScale;					/* ydnar: radiosity re-emission [0,1.0+] */
+	float				offset;							/* ydnar: offset in units */
+	float				shadeAngleDegrees;				/* ydnar: breaking angle for smooth shading (degrees) */
+	
+	vec3_t				mins, maxs;						/* ydnar: for particle studio vertexDeform move support */
+	
+	qb_t				legacyTerrain;					/* ydnar: enable legacy terrain crutches */
+	qb_t				indexed;						/* ydnar: attempt to use indexmap (terrain alphamap style) */
+	qb_t				forceMeta;						/* ydnar: force metasurface path */
+	qb_t				noClip;							/* ydnar: don't clip into bsp, preserve original face winding */
+	qb_t				noFast;							/* ydnar: supress fast lighting for surfaces with this shader */
+	qb_t				invert;							/* ydnar: reverse facing */
+	qb_t				nonplanar;						/* ydnar: for nonplanar meta surface merging */
+	qb_t				tcGen;							/* ydnar: has explicit texcoord generation */
+	vec3_t				vecs[ 2 ];						/* ydnar: explicit texture vectors for [0,1] texture space */
+	tcMod_t				mod;							/* ydnar: q3map_tcMod matrix for djbob :) */
+	vec3_t				lightmapAxis;					/* ydnar: explicit lightmap axis projection */
+	alphaMod_t			*alphaMod;						/* ydnar: q3map_alphaMod support */
+	
+	int					furNumLayers;					/* ydnar: number of fur layers */
+	float				furOffset;						/* ydnar: offset of each layer */
+	float				furFade;						/* ydnar: alpha fade amount per layer */
+
+	qb_t				splotchFix;						/* ydnar: filter splotches on lightmaps */
+	
+	qb_t				hasPasses;						/* false if the shader doesn't define any rendering passes */
+	qb_t				globalTexture;					/* don't normalize texture repeats */
+	qb_t				twoSided;						/* cull none */
+	qb_t				autosprite;						/* autosprite shaders will become point lights instead of area lights */
+	qb_t				polygonOffset;					/* ydnar: don't face cull this or against this */
+	qb_t				patchShadows;					/* have patches casting shadows when using -light for this surface */
+	qb_t				vertexShadows;					/* shadows will be casted at this surface even when vertex lit */
+	qb_t				forceSunlight;					/* force sun light at this surface even tho we might not calculate shadows in vertex lighting */
+	qb_t				notjunc;						/* don't use this surface for tjunction fixing */
+	qb_t				fogParms;						/* ydnar: has fogparms */
+	qb_t				noFog;							/* ydnar: supress fogging */
+	
+	qb_t				clipModel;						/* ydnar: solid model hack */
+	
+	byte				styleMarker;					/* ydnar: light styles hack */
+	
+	float				vertexScale;					/* vertex light scale */
+	
+	char				skyParmsImageBase[ MAX_QPATH ];	/* ydnar: for skies */
+	
+	char				editorImagePath[ MAX_QPATH ];	/* use this image to generate texture coordinates */
+	char				lightImagePath[ MAX_QPATH ];	/* use this image to generate color / averageColor */
+	char				normalImagePath[ MAX_QPATH ];	/* ydnar: normalmap image for bumpmapping */
+	
+	implicitMap_t		implicitMap;					/* ydnar: enemy territory implicit shaders */
+	char				implicitImagePath[ MAX_QPATH ];
+	
+	image_t				*shaderImage;
+	image_t				*lightImage;
+	image_t				*normalImage;
+	
+	float				skyLightValue;					/* ydnar */
+	int					skyLightIterations;				/* ydnar */
+	sun_t				*sun;							/* ydnar */
+	
+	vec3_t				color;							/* normalized color */
+	vec3_t				averageColor;
+	byte				lightStyle;
+	
+	qb_t				lmMergable;						/* ydnar */
+	int					lmCustomWidth, lmCustomHeight;	/* ydnar */
+	float				lmGamma;						/* ydnar */
+	float				lmFilterRadius;					/* ydnar: lightmap filtering/blurring radius for this shader (default: 0) */
+	
+	int					shaderWidth, shaderHeight;		/* ydnar */
+	float				stFlat[ 2 ];
+	
+	vec3_t				fogDir;							/* ydnar */
+	
+	char				*shaderText;					/* ydnar */
+	qb_t				custom;
+	qb_t				finished;
+}
+shaderInfo_t;
+
+
+
+/* -------------------------------------------------------------------------------
+
+bsp structures
+
+------------------------------------------------------------------------------- */
+
+typedef struct face_s
+{
+	struct face_s		*next;
+	int					planenum;
+	int					priority;
+	qboolean			checked;
+	int					compileFlags;
+	winding_t			*w;
+}
+face_t;
+
+
+typedef struct plane_s
+{
+	vec3_t				normal;
+	vec_t				dist;
+	int					type;
+	struct plane_s		*hash_chain;
+}
+plane_t;
+
+
+typedef struct side_s
+{
+	int					planenum;
+	
+	int					outputNum;			/* set when the side is written to the file list */
+	
+	float				texMat[ 2 ][ 3 ];	/* brush primitive texture matrix */
+	float				vecs[ 2 ][ 4 ];		/* old-style texture coordinate mapping */
+
+	winding_t			*winding;
+	winding_t			*visibleHull;		/* convex hull of all visible fragments */
+
+	shaderInfo_t		*shaderInfo;
+
+	int					contentFlags;		/* from shaderInfo */
+	int					surfaceFlags;		/* from shaderInfo */
+	int					compileFlags;		/* from shaderInfo */
+	int					value;				/* from shaderInfo */
+
+	qboolean			visible;			/* choose visble planes first */
+	qboolean			bevel;				/* don't ever use for bsp splitting, and don't bother making windings for it */
+	qboolean			backSide;			/* generated side for a q3map_backShader */
+	
+	qboolean			culled;				/* ydnar: face culling */
+}
+side_t;
+
+
+typedef struct sideRef_s
+{
+	struct sideRef_s	*next;
+	side_t				*side;
+}
+sideRef_t;
+
+
+/* ydnar: generic index mapping for entities (natural extension of terrain texturing) */
+typedef struct indexMap_s
+{
+	int					w, h, numLayers;
+	char				name[ MAX_QPATH ], shader[ MAX_QPATH ];
+	float				offsets[ 256 ];
+	byte				*pixels;
+}
+indexMap_t;
+
+
+typedef struct brush_s
+{
+	struct brush_s		*next;
+	struct brush_s		*original;			/* chopped up brushes will reference the originals */
+	
+	int					entityNum, brushNum;/* editor numbering */
+	int					outputNum;			/* set when the brush is written to the file list */
+	
+	/* ydnar: for shadowcasting entities */
+	int					castShadows;
+	int					recvShadows;
+	
+	shaderInfo_t		*contentShader;
+	shaderInfo_t		*celShader;			/* :) */
+	
+	/* ydnar: gs mods */
+	float				lightmapScale;
+	vec3_t				eMins, eMaxs;
+	indexMap_t			*im;
+
+	int					contentFlags;
+	int					compileFlags;		/* ydnar */
+	qboolean			detail;
+	qboolean			opaque;
+
+	int					portalareas[ 2 ];
+
+	vec3_t				mins, maxs;
+	int					numsides;
+	
+	side_t				sides[ 6 ];			/* variably sized */
+}
+brush_t;
+
+
+typedef struct fog_s
+{
+	shaderInfo_t		*si;
+	brush_t				*brush;
+	int					visibleSide;		/* the brush side that ray tests need to clip against (-1 == none) */
+}
+fog_t;
+
+
+typedef struct
+{
+	int					width, height;
+	bspDrawVert_t		*verts;
+}
+mesh_t;
+
+
+typedef struct parseMesh_s
+{
+	struct parseMesh_s	*next;
+	
+	int					entityNum, brushNum;	/* ydnar: editor numbering */
+	
+	/* ydnar: for shadowcasting entities */
+	int					castShadows;
+	int					recvShadows;
+	
+	mesh_t				mesh;
+	shaderInfo_t		*shaderInfo;
+	shaderInfo_t		*celShader;				/* :) */
+	
+	/* ydnar: gs mods */
+	float				lightmapScale;
+	vec3_t				eMins, eMaxs;
+	indexMap_t			*im;
+	
+	/* grouping */
+	qboolean			grouped;
+	float				longestCurve;
+	int					maxIterations;
+}
+parseMesh_t;
+
+
+/*
+	ydnar: the drawsurf struct was extended to allow for:
+	- non-convex planar surfaces
+	- non-planar brushface surfaces
+	- lightmapped terrain
+	- planar patches
+*/
+
+typedef enum
+{
+	/* ydnar: these match up exactly with bspSurfaceType_t */
+	SURFACE_BAD,
+	SURFACE_FACE,
+	SURFACE_PATCH,
+	SURFACE_TRIANGLES,
+	SURFACE_FLARE,
+	SURFACE_FOLIAGE,	/* wolf et */
+	
+	/* ydnar: compiler-relevant surface types */
+	SURFACE_FORCED_META,
+	SURFACE_META,
+	SURFACE_FOGHULL,
+	SURFACE_DECAL,
+	SURFACE_SHADER,
+	
+	NUM_SURFACE_TYPES
+}
+surfaceType_t;
+
+char			*surfaceTypes[ NUM_SURFACE_TYPES ]
+#ifndef MAIN_C
+				;
+#else
+				=
+				{
+					"SURFACE_BAD",
+					"SURFACE_FACE",
+					"SURFACE_PATCH",
+					"SURFACE_TRIANGLES",
+					"SURFACE_FLARE",
+					"SURFACE_FOLIAGE",
+					"SURFACE_FORCED_META",
+					"SURFACE_META",
+					"SURFACE_FOGHULL",
+					"SURFACE_DECAL",
+					"SURFACE_SHADER"
+				};
+#endif
+
+
+/* ydnar: this struct needs an overhaul (again, heh) */
+typedef struct mapDrawSurface_s
+{
+	surfaceType_t		type;
+	qboolean			planar;
+	int					outputNum;			/* ydnar: to match this sort of thing up */
+	
+	qboolean			fur;				/* ydnar: this is kind of a hack, but hey... */
+	qboolean			skybox;				/* ydnar: yet another fun hack */
+	
+	struct mapDrawSurface_s	*parent;		/* ydnar: for cloned (skybox) surfaces to share lighting data */
+	
+	shaderInfo_t		*shaderInfo;
+	shaderInfo_t		*celShader;
+	brush_t				*mapBrush;
+	parseMesh_t			*mapMesh;
+	sideRef_t			*sideRef;
+	
+	int					fogNum;
+	
+	int					numVerts;			/* vertexes and triangles */
+	bspDrawVert_t		*verts;
+	int					numIndexes;
+	int					*indexes;
+	
+	int					planeNum;
+	vec3_t				lightmapOrigin;		/* also used for flares */
+	vec3_t				lightmapVecs[ 3 ];	/* also used for flares */
+	int					lightStyle;			/* used for flares */
+	
+	/* ydnar: per-surface (per-entity, actually) lightmap sample size scaling */
+	float				lightmapScale;
+	
+	/* ydnar: surface classification */
+	vec3_t				mins, maxs;
+	vec3_t				lightmapAxis;
+	int					sampleSize;
+	
+	/* ydnar: shadow group support */
+	int					castShadows, recvShadows;
+	
+	/* ydnar: texture coordinate range monitoring for hardware with limited texcoord precision (in texel space) */
+	float				bias[ 2 ];
+	int					texMins[ 2 ], texMaxs[ 2 ], texRange[ 2 ];
+		
+	/* ydnar: for patches */
+	float				longestCurve;
+	int					maxIterations;
+	int					patchWidth, patchHeight;
+	vec3_t				bounds[ 2 ];
+	
+	/* ydnar/sd: for foliage */
+	int					numFoliageInstances;
+	
+	/* ydnar: editor/useful numbering */
+	int					entityNum;
+	int					surfaceNum;
+}
+mapDrawSurface_t;
+
+
+typedef struct drawSurfRef_s
+{
+	struct drawSurfRef_s	*nextRef;
+	int					outputNum;
+}
+drawSurfRef_t;
+
+
+/* ydnar: metasurfaces are constructed from lists of metatriangles so they can be merged in the best way */
+typedef struct metaTriangle_s
+{
+	shaderInfo_t		*si;
+	side_t				*side;
+	int					entityNum, surfaceNum, planeNum, fogNum, sampleSize, castShadows, recvShadows;
+	vec4_t				plane;
+	vec3_t				lightmapAxis;
+	int					indexes[ 3 ];
+}
+metaTriangle_t;
+
+
+typedef struct epair_s
+{
+	struct epair_s		*next;
+	char				*key, *value;
+}
+epair_t;
+
+
+typedef struct
+{
+	vec3_t				origin;
+	brush_t				*brushes, *lastBrush;
+	parseMesh_t			*patches;
+	int					mapEntityNum, firstDrawSurf;
+	int					firstBrush, numBrushes;		/* only valid during BSP compile */
+	epair_t				*epairs;
+}
+entity_t;
+
+
+typedef struct node_s
+{
+	/* both leafs and nodes */
+	int					planenum;		/* -1 = leaf node */
+	struct node_s		*parent;
+	vec3_t				mins, maxs;		/* valid after portalization */
+	brush_t				*volume;		/* one for each leaf/node */
+
+	/* nodes only */
+	side_t				*side;			/* the side that created the node */
+	struct node_s		*children[ 2 ];
+	int					compileFlags;	/* ydnar: hint, antiportal */
+	int					tinyportals;
+	vec3_t				referencepoint;
+
+	/* leafs only */
+	qboolean			opaque;			/* view can never be inside */
+	qboolean			areaportal;
+	qboolean			skybox;			/* ydnar: a skybox leaf */
+	qboolean			sky;			/* ydnar: a sky leaf */
+	int					cluster;		/* for portalfile writing */
+	int					area;			/* for areaportals */
+	brush_t				*brushlist;		/* fragments of all brushes in this leaf */
+	drawSurfRef_t		*drawSurfReferences;
+
+	int					occupied;		/* 1 or greater can reach entity */
+	entity_t			*occupant;		/* for leak file testing */
+
+	struct portal_s		*portals;		/* also on nodes during construction */
+}
+node_t;
+
+
+typedef struct portal_s
+{
+	plane_t				plane;
+	node_t				*onnode;		/* NULL = outside box */
+	node_t				*nodes[ 2 ];	/* [ 0 ] = front side of plane */
+	struct portal_s		*next[ 2 ];
+	winding_t			*winding;
+
+	qboolean			sidefound;		/* false if ->side hasn't been checked */
+	int					compileFlags;	/* from original face that caused the split */
+	side_t				*side;			/* NULL = non-visible */
+}
+portal_t;
+
+
+typedef struct
+{
+	node_t				*headnode;
+	node_t				outside_node;
+	vec3_t				mins, maxs;
+}
+tree_t;
+
+
+
+/* -------------------------------------------------------------------------------
+
+vis structures
+
+------------------------------------------------------------------------------- */
+
+typedef struct
+{
+	vec3_t				normal;
+	float				dist;
+}
+visPlane_t;
+
+
+typedef struct
+{
+	int					numpoints;
+	vec3_t				points[	MAX_POINTS_ON_FIXED_WINDING	];		/* variable sized */
+} 
+fixedWinding_t;
+
+
+typedef struct passage_s
+{
+	struct passage_s	*next;
+	byte				cansee[ 1 ];	/* all portals that can be seen through this passage */
+} passage_t;
+
+
+typedef enum
+{
+	stat_none,
+	stat_working,
+	stat_done
+}
+vstatus_t;
+
+
+typedef struct
+{
+	int					num;
+	qboolean			hint;			/* true if this portal was created from a hint splitter */
+	qboolean			removed;
+	visPlane_t			plane;			/* normal pointing into neighbor */
+	int					leaf;			/* neighbor */
+	
+	vec3_t				origin;			/* for fast clip testing */
+	float				radius;
+
+	fixedWinding_t		*winding;
+	vstatus_t			status;
+	byte				*portalfront;	/* [portals], preliminary */
+	byte				*portalflood;	/* [portals], intermediate */
+	byte				*portalvis;		/* [portals], final */
+
+	int					nummightsee;	/* bit count on portalflood for sort */
+	passage_t			*passages;		/* there are just as many passages as there */
+										/* are portals in the leaf this portal leads */
+}
+vportal_t;
+
+
+typedef struct leaf_s
+{
+	int					numportals;
+	int					merged;
+	vportal_t			*portals[MAX_PORTALS_ON_LEAF];
+}
+leaf_t;
+
+	
+typedef struct pstack_s
+{
+	byte				mightsee[ MAX_PORTALS / 8 ];
+	struct pstack_s		*next;
+	leaf_t				*leaf;
+	vportal_t			*portal;		/* portal exiting */
+	fixedWinding_t		*source;
+	fixedWinding_t		*pass;
+
+	fixedWinding_t		windings[ 3 ];	/* source, pass, temp in any order */
+	int					freewindings[ 3 ];
+
+	visPlane_t			portalplane;
+	int depth;
+#ifdef SEPERATORCACHE
+	visPlane_t			seperators[ 2 ][ MAX_SEPERATORS ];
+	int					numseperators[ 2 ];
+#endif
+}
+pstack_t;
+
+
+typedef struct
+{
+	vportal_t			*base;
+	int					c_chains;
+	pstack_t			pstack_head;
+}
+threaddata_t;
+
+
+
+/* -------------------------------------------------------------------------------
+
+light structures
+
+------------------------------------------------------------------------------- */
+
+/* ydnar: new light struct with flags */
+typedef struct light_s
+{
+	struct light_s		*next;
+	
+	int					type;
+	int					flags;			/* ydnar: condensed all the booleans into one flags int */
+	shaderInfo_t		*si;
+	
+	vec3_t				origin;
+	vec3_t				normal;			/* for surfaces, spotlights, and suns */
+	float				dist;			/* plane location along normal */
+	
+	float				photons;
+	int					style;
+	vec3_t				color;
+	float				radiusByDist;	/* for spotlights */
+	float				fade;			/* ydnar: from wolf, for linear lights */
+	float				angleScale;		/* ydnar: stolen from vlight for K */
+
+	float				add;			/* ydnar: used for area lights */
+	float				envelope;		/* ydnar: units until falloff < tolerance */
+	float				envelope2;		/* ydnar: envelope squared (tiny optimization) */
+	vec3_t				mins, maxs;		/* ydnar: pvs envelope */
+	int					cluster;		/* ydnar: cluster light falls into */
+	
+	winding_t			*w;
+	vec3_t				emitColor;		/* full out-of-gamut value */
+	
+	float				falloffTolerance;	/* ydnar: minimum attenuation threshold */
+	float				filterRadius;	/* ydnar: lightmap filter radius in world units, 0 == default */
+}
+light_t;
+
+
+typedef struct
+{
+	/* constant input */
+	qboolean			testOcclusion, forceSunlight, testAll;
+	int					recvShadows;
+	
+	int					numSurfaces;
+	int					*surfaces;
+	
+	int					numLights;
+	light_t				**lights;
+	
+	qboolean			twoSided;
+	
+	/* per-sample input */
+	int					cluster;
+	vec3_t				origin, normal;
+	vec_t				inhibitRadius;	/* sphere in which occluding geometry is ignored */
+	
+	/* per-light input */
+	light_t				*light;
+	vec3_t				end;
+	
+	/* calculated input */
+	vec3_t				displacement, direction;
+	vec_t				distance;
+	
+	/* input and output */
+	vec3_t				color;			/* starts out at full color, may be reduced if transparent surfaces are crossed */
+	
+	/* output */
+	int					compileFlags;	/* for determining surface compile flags traced through */
+	qboolean			passSolid;
+	qboolean			opaque;
+	
+	/* working data */
+	int					numTestNodes;
+	int					testNodes[ MAX_TRACE_TEST_NODES ]; 
+}
+trace_t;
+
+
+
+/* must be identical to bspDrawVert_t except for float color! */
+typedef struct
+{
+	vec3_t				xyz;
+	float				st[ 2 ];
+	float				lightmap[ MAX_LIGHTMAPS ][ 2 ];
+	vec3_t				normal;
+	float				color[ MAX_LIGHTMAPS ][ 4 ];
+}
+radVert_t;
+
+
+typedef struct
+{
+	int					numVerts;
+	radVert_t			verts[ MAX_POINTS_ON_WINDING ];
+}
+radWinding_t;
+
+
+/* crutch for poor local allocations in win32 smp */
+typedef struct
+{
+	vec_t				dists[ MAX_POINTS_ON_WINDING + 4 ];
+	int					sides[ MAX_POINTS_ON_WINDING + 4 ];
+}
+clipWork_t;
+
+
+/* ydnar: new lightmap handling code */
+typedef struct outLightmap_s
+{
+	int					lightmapNum, extLightmapNum;
+	int					customWidth, customHeight;
+	int					numLightmaps;
+	int					freeLuxels;
+	int					numShaders;
+	shaderInfo_t		*shaders[ MAX_LIGHTMAP_SHADERS ];
+	byte				*lightBits;
+	byte				*bspLightBytes;
+	byte				*bspDirBytes;
+}
+outLightmap_t;
+
+
+typedef struct rawLightmap_s
+{
+	qboolean				finished, splotchFix, wrap[ 2 ];
+	int						customWidth, customHeight;
+	float					gamma;
+	float					filterRadius;
+	
+	int						firstLightSurface, numLightSurfaces;	/* index into lightSurfaces */
+	int						numLightClusters, *lightClusters;
+	
+	int						sampleSize, actualSampleSize, axisNum;
+	int						entityNum;
+	int						recvShadows;
+	vec3_t					mins, maxs, axis, origin, *vecs;
+	float					*plane;
+	int						w, h, sw, sh, used;
+	
+	int						numStyledTwins;
+	struct rawLightmap_s	*twins[ MAX_LIGHTMAPS ];
+
+	int						outLightmapNums[ MAX_LIGHTMAPS ];
+	int						twinNums[ MAX_LIGHTMAPS ];
+	int						lightmapX[ MAX_LIGHTMAPS ], lightmapY[ MAX_LIGHTMAPS ];
+	byte					styles[ MAX_LIGHTMAPS ];
+	float					*bspLuxels[ MAX_LIGHTMAPS ];
+	float					*radLuxels[ MAX_LIGHTMAPS ];
+	float					*superLuxels[ MAX_LIGHTMAPS ];
+	float					*superOrigins;
+	float					*superNormals;
+	int						*superClusters;
+	
+	float					*superDeluxels;	/* average light direction */
+	float					*bspDeluxels;
+}
+rawLightmap_t;
+
+
+typedef struct rawGridPoint_s
+{
+	vec3_t				ambient[ MAX_LIGHTMAPS ];
+	vec3_t				directed[ MAX_LIGHTMAPS ];
+	vec3_t				dir;
+	byte				styles[ MAX_LIGHTMAPS ];
+}
+rawGridPoint_t;
+
+
+typedef struct surfaceInfo_s
+{
+	bspModel_t			*model;
+	shaderInfo_t		*si;
+	rawLightmap_t		*lm;
+	int					parentSurfaceNum, childSurfaceNum;
+	int					entityNum, castShadows, recvShadows, sampleSize, patchIterations;
+	float				longestCurve;
+	float				*plane;
+	vec3_t				axis, mins, maxs;
+	qboolean			hasLightmap, approximated;
+	int					firstSurfaceCluster, numSurfaceClusters;
+}
+surfaceInfo_t;
+
+
+
+/* -------------------------------------------------------------------------------
+
+prototypes
+
+------------------------------------------------------------------------------- */
+
+/* main.c */
+vec_t						Random( void );
+int							BSPInfo( int count, char **fileNames );
+int							ScaleBSPMain( int argc, char **argv );
+int							ConvertMain( int argc, char **argv );
+
+
+/* path_init.c */
+void						InitPaths( int *argc, char **argv );
+
+
+/* bsp.c */
+int							BSPMain( int argc, char **argv );
+
+
+/* convert_map.c */
+int							ConvertBSPToMap( char *bspName );
+
+
+/* convert_ase.c */
+int							ConvertBSPToASE( char *bspName );
+
+
+/* brush.c */
+sideRef_t					*AllocSideRef( side_t *side, sideRef_t *next );
+int							CountBrushList( brush_t *brushes );
+brush_t						*AllocBrush( int numsides );
+void						FreeBrush( brush_t *brushes );
+void						FreeBrushList( brush_t *brushes );
+brush_t						*CopyBrush( brush_t *brush );
+qboolean					BoundBrush( brush_t *brush );
+qboolean					CreateBrushWindings( brush_t *brush );
+brush_t						*BrushFromBounds( vec3_t mins, vec3_t maxs );
+vec_t						BrushVolume( brush_t *brush );
+void						WriteBSPBrushMap( char *name, brush_t *list );
+
+void						FilterDetailBrushesIntoTree( entity_t *e, tree_t *tree );
+void						FilterStructuralBrushesIntoTree( entity_t *e, tree_t *tree );
+
+int							BoxOnPlaneSide( vec3_t mins, vec3_t maxs, plane_t *plane );
+qboolean					WindingIsTiny( winding_t *w );
+
+void						SplitBrush( brush_t *brush, int planenum, brush_t **front, brush_t **back);
+
+tree_t						*AllocTree( void );
+node_t						*AllocNode( void );
+
+
+/* mesh.c */
+void						LerpDrawVert( bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *out );
+void						LerpDrawVertAmount( bspDrawVert_t *a, bspDrawVert_t *b, float amount, bspDrawVert_t *out );
+void						FreeMesh( mesh_t *m );
+mesh_t						*CopyMesh( mesh_t *mesh );
+void						PrintMesh( mesh_t *m );
+mesh_t						*TransposeMesh( mesh_t *in );
+void						InvertMesh( mesh_t *m );
+mesh_t						*SubdivideMesh( mesh_t in, float maxError, float minLength );
+int							IterationsForCurve( float len, int subdivisions );
+mesh_t						*SubdivideMesh2( mesh_t in, int iterations );
+mesh_t						*SubdivideMeshQuads( mesh_t *in, float minLength, int maxsize, int *widthtable, int *heighttable );
+mesh_t						*RemoveLinearMeshColumnsRows( mesh_t *in );
+void						MakeMeshNormals( mesh_t in );
+void						PutMeshOnCurve( mesh_t in );
+
+void						MakeNormalVectors( vec3_t forward, vec3_t right, vec3_t up );
+
+
+/* map.c */
+void 						LoadMapFile( char *filename, qboolean onlyLights );
+int							FindFloatPlane( vec3_t normal, vec_t dist, int numPoints, vec3_t *points );
+int							PlaneTypeForNormal( vec3_t normal );
+void						AddBrushBevels( void );
+brush_t						*FinishBrush( void );
+
+
+/* portals.c */
+void						MakeHeadnodePortals( tree_t *tree );
+void						MakeNodePortal( node_t *node );
+void						SplitNodePortals( node_t *node );
+
+qboolean					PortalPassable( portal_t *p );
+
+qboolean					FloodEntities( tree_t *tree );
+void						FillOutside( node_t *headnode);
+void						FloodAreas( tree_t *tree);
+face_t						*VisibleFaces( entity_t *e, tree_t *tree );
+void						FreePortal( portal_t *p );
+
+void						MakeTreePortals( tree_t *tree );
+
+
+/* leakfile.c */
+xmlNodePtr					LeakFile( tree_t *tree );
+
+
+/* prtfile.c */
+void						NumberClusters( tree_t *tree );
+void						WritePortalFile( tree_t *tree );
+
+
+/* writebsp.c */
+void						SetModelNumbers( void );
+void						SetLightStyles( void );
+
+int							EmitShader( const char *shader, int *contentFlags, int *surfaceFlags );
+
+void						BeginBSPFile( void );
+void						EndBSPFile( void );
+void						EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes );
+void						EmitFogs( void );
+
+void						BeginModel( void );
+void						EndModel( entity_t *e, node_t *headnode );
+
+
+/* tree.c */
+void						FreeTree( tree_t *tree );
+void						FreeTree_r( node_t *node );
+void						PrintTree_r( node_t *node, int depth );
+void						FreeTreePortals_r( node_t *node );
+
+
+/* patch.c */
+void						ParsePatch( qboolean onlyLights );
+mesh_t						*SubdivideMesh( mesh_t in, float maxError, float minLength );
+void						PatchMapDrawSurfs( entity_t *e );
+
+
+/* tjunction.c */
+void						FixTJunctions( entity_t *e );
+
+
+/* fog.c */
+winding_t					*WindingFromDrawSurf( mapDrawSurface_t *ds );
+void						FogDrawSurfaces( entity_t *e );
+int							FogForPoint( vec3_t point, float epsilon );
+int							FogForBounds( vec3_t mins, vec3_t maxs, float epsilon );
+void						CreateMapFogs( void );
+
+
+/* facebsp.c */
+face_t						*MakeStructuralBSPFaceList( brush_t *list );
+face_t						*MakeVisibleBSPFaceList( brush_t *list );
+tree_t						*FaceBSP( face_t *list );
+
+
+/* model.c */
+void						PicoPrintFunc( int level, const char *str );
+void						PicoLoadFileFunc( char *name, byte **buffer, int *bufSize );
+picoModel_t					*FindModel( char *name, int frame );
+picoModel_t					*LoadModel( char *name, int frame );
+void						InsertModel( char *name, int frame, m4x4_t transform, remap_t *remap, shaderInfo_t *celShader, int eNum, int castShadows, int recvShadows, int spawnFlags, float lightmapScale );
+void						AddTriangleModels( entity_t *e );
+
+
+/* surface.c */
+mapDrawSurface_t			*AllocDrawSurface( surfaceType_t type );
+void						FinishSurface( mapDrawSurface_t *ds );
+void						StripFaceSurface( mapDrawSurface_t *ds );
+qboolean					CalcSurfaceTextureRange( mapDrawSurface_t *ds );
+qboolean					CalcLightmapAxis( vec3_t normal, vec3_t axis );
+void						ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds );
+void						ClassifyEntitySurfaces( entity_t *e );
+void						TidyEntitySurfaces( entity_t *e );
+mapDrawSurface_t			*CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si );
+mapDrawSurface_t			*MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si );
+qboolean					IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c );
+void						ClearSurface( mapDrawSurface_t *ds );
+void						AddEntitySurfaceModels( entity_t *e );
+mapDrawSurface_t			*DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w );
+mapDrawSurface_t			*DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh );
+mapDrawSurface_t			*DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, char *flareShader, int lightStyle );
+mapDrawSurface_t			*DrawSurfaceForShader( char *shader );
+void						ClipSidesIntoTree( entity_t *e, tree_t *tree );
+void						MakeDebugPortalSurfs( tree_t *tree );
+void						MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader );
+void						SubdivideFaceSurfaces( entity_t *e, tree_t *tree );
+void						AddEntitySurfaceModels( entity_t *e );
+int							AddSurfaceModels( mapDrawSurface_t *ds );
+void						FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree );
+
+
+/* surface_fur.c */
+void						Fur( mapDrawSurface_t *src );
+
+
+/* surface_foliage.c */
+void						Foliage( mapDrawSurface_t *src );
+
+
+/* ydnar: surface_meta.c */
+void						ClearMetaTriangles( void );
+int							FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum );
+void						MakeEntityMetaTriangles( entity_t *e );
+void						FixMetaTJunctions( void );
+void						SmoothMetaTriangles( void );
+void						MergeMetaTriangles( void );
+
+
+/* surface_extra.c */
+void						SetDefaultSampleSize( int sampleSize );
+
+void						SetSurfaceExtra( mapDrawSurface_t *ds, int num );
+
+shaderInfo_t				*GetSurfaceExtraShaderInfo( int num );
+int							GetSurfaceExtraParentSurfaceNum( int num );
+int							GetSurfaceExtraEntityNum( int num );
+int							GetSurfaceExtraCastShadows( int num );
+int							GetSurfaceExtraRecvShadows( int num );
+int							GetSurfaceExtraSampleSize( int num );
+float						GetSurfaceExtraLongestCurve( int num );
+void						GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis );
+
+void						WriteSurfaceExtraFile( const char *path );
+void						LoadSurfaceExtraFile( const char *path );
+
+
+/* decals.c */
+void						ProcessDecals( void );
+void						MakeEntityDecals( entity_t *e );
+
+
+/* brush_primit.c */
+void						ComputeAxisBase( vec3_t normal, vec3_t texX, vec3_t texY);
+
+
+/* vis.c */
+fixedWinding_t				*NewFixedWinding( int points );
+int							VisMain( int argc, char **argv );
+
+/* visflow.c */
+int							CountBits( byte *bits, int numbits );
+void						PassageFlow( int portalnum );
+void						CreatePassages( int portalnum );
+void						PassageMemory( void );
+void						BasePortalVis( int portalnum );
+void						BetterPortalVis( int portalnum );
+void						PortalFlow( int portalnum );
+void						PassagePortalFlow( int portalnum );
+
+
+
+/* light.c  */
+float						PointToPolygonFormFactor( const vec3_t point, const vec3_t normal, const winding_t *w );
+int							LightContributionToSample( trace_t *trace );
+void						LightingAtSample( trace_t *trace, byte styles[ MAX_LIGHTMAPS ], vec3_t colors[ MAX_LIGHTMAPS ] );
+int							LightContributionToPoint( trace_t *trace );
+int							LightMain( int argc, char **argv );
+
+
+/* light_trace.c */
+void						SetupTraceNodes( void );
+void						TraceLine( trace_t *trace );
+float						SetupTrace( trace_t *trace );
+
+
+/* light_bounce.c */
+qboolean					RadSampleImage( byte *pixels, int width, int height, float st[ 2 ], float color[ 4 ] );
+void						RadLightForTriangles( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw );
+void						RadLightForPatch( int num, int lightmapNum, rawLightmap_t *lm, shaderInfo_t *si, float scale, float subdivide, clipWork_t *cw );
+void						RadCreateDiffuseLights( void );
+void						RadFreeLights();
+
+
+/* light_ydnar.c */
+void						ColorToBytes( const float *color, byte *colorBytes, float scale );
+void						SmoothNormals( void );
+
+void						MapRawLightmap( int num );
+void						IlluminateRawLightmap( int num );
+void						IlluminateVertexes( int num );
+
+void						SetupBrushes( void );
+void						SetupClusters( void );
+qboolean					ClusterVisible( int a, int b );
+qboolean					ClusterVisibleToPoint( vec3_t point, int cluster );
+int							ClusterForPoint( vec3_t point );
+int							ClusterForPointExt( vec3_t point, float epsilon );
+int							ClusterForPointExtFilter( vec3_t point, float epsilon, int numClusters, int *clusters );
+int							ShaderForPointInLeaf( vec3_t point, int leafNum, float epsilon, int wantContentFlags, int wantSurfaceFlags, int *contentFlags, int *surfaceFlags );
+void						SetupEnvelopes( qboolean forGrid, qboolean fastFlag );
+void						FreeTraceLights( trace_t *trace );
+void						CreateTraceLightsForBounds( vec3_t mins, vec3_t maxs, vec3_t normal, int numClusters, int *clusters, int flags, trace_t *trace );
+void						CreateTraceLightsForSurface( int num, trace_t *trace );
+
+
+/* lightmaps_ydnar.c */
+void						ExportLightmaps( void );
+
+int							ExportLightmapsMain( int argc, char **argv );
+int							ImportLightmapsMain( int argc, char **argv );
+
+void						SetupSurfaceLightmaps( void );
+void						StitchSurfaceLightmaps( void );
+void						StoreSurfaceLightmaps( void );
+
+
+/* image.c */
+void						ImageFree( image_t *image );
+image_t						*ImageFind( const char *filename );
+image_t						*ImageLoad( const char *filename );
+
+
+/* shaders.c */
+void						AlphaMod( alphaMod_t *am, int numVerts, bspDrawVert_t *drawVerts );
+
+void						TcMod( tcMod_t mod, float st[ 2 ] );
+void						TcModIdentity( tcMod_t mod );
+void						TcModMultiply( tcMod_t a, tcMod_t b, tcMod_t out );
+void						TcModTranslate( tcMod_t mod, float s, float t );
+void						TcModScale( tcMod_t mod, float s, float t );
+void						TcModRotate( tcMod_t mod, float euler );
+
+qboolean					ApplySurfaceParm( char *name, int *contentFlags, int *surfaceFlags, int *compileFlags );
+
+void						BeginMapShaderFile( const char *mapFile );
+void						WriteMapShaderFile( void );
+shaderInfo_t				*CustomShader( shaderInfo_t *si, char *find, char *replace );
+void						EmitVertexRemapShader( char *from, char *to );
+
+void						LoadShaderInfo( void );
+shaderInfo_t				*ShaderInfoForShader( const char *shader );
+
+
+/* bspfile_abstract.c */
+void						SetGridPoints( int n );
+void						SetDrawVerts( int n );
+void						IncDrawVerts();
+void						SetDrawSurfaces(int n);
+void						SetDrawSurfacesBuffer();
+void						BSPFilesCleanup();
+
+void						SwapBlock( int *block, int size );
+
+int							GetLumpElements( bspHeader_t *header, int lump, int size );
+void						*GetLump( bspHeader_t *header, int lump );
+int							CopyLump( bspHeader_t *header, int lump, void *dest, int size );
+void						AddLump( FILE *file, bspHeader_t *header, int lumpNum, const void *data, int length );
+
+void						LoadBSPFile( const char *filename );
+void						WriteBSPFile( const char *filename );
+void						PrintBSPFileSizes( void );
+
+epair_t						*ParseEPair( void );
+void						ParseEntities( void );
+void						UnparseEntities( void );
+void						PrintEntity( const entity_t *ent );
+void						SetKeyValue( entity_t *ent, const char *key, const char *value );
+const char					*ValueForKey( const entity_t *ent, const char *key );
+int							IntForKey( const entity_t *ent, const char *key );
+vec_t						FloatForKey( const entity_t *ent, const char *key );
+void						GetVectorForKey( const entity_t *ent, const char *key, vec3_t vec );
+entity_t					*FindTargetEntity( const char *target );
+void						GetEntityShadowFlags( const entity_t *ent, const entity_t *ent2, int *castShadows, int *recvShadows );
+
+
+/* bspfile_ibsp.c */
+void						LoadIBSPFile( const char *filename );
+void						WriteIBSPFile( const char *filename );
+
+
+/* bspfile_rbsp.c */
+void						LoadRBSPFile( const char *filename );
+void						WriteRBSPFile( const char *filename );
+
+
+
+/* -------------------------------------------------------------------------------
+
+bsp/general global variables
+
+------------------------------------------------------------------------------- */
+
+#ifdef MAIN_C
+	#define Q_EXTERN
+	#define Q_ASSIGN( a )	= a
+#else
+	#define Q_EXTERN extern
+	#define Q_ASSIGN( a )	
+#endif
+
+/* game support */
+Q_EXTERN game_t				games[]
+#ifndef MAIN_C
+							;
+#else
+							=
+							{
+								#include "game_quake3.h"
+								,
+								#include "game_tenebrae.h"
+								,
+								#include "game_wolf.h"
+								,
+								#include "game_wolfet.h"/* most be after game_wolf.h as they share defines! */
+								,
+								#include "game_ef.h"
+								,
+								#include "game_sof2.h"
+								,
+								#include "game_jk2.h"	/* most be after game_sof2.h as they share defines! */
+								,
+								#include "game_ja.h"	/* most be after game_jk2.h as they share defines! */
+								,
+								{ NULL, NULL, NULL, NULL, NULL, qfalse, 0, 0, NULL }	/* null game */
+							};
+#endif
+Q_EXTERN game_t				*game Q_ASSIGN( &games[ 0 ] );
+
+
+/* general */
+Q_EXTERN int				numImages Q_ASSIGN( 0 );
+Q_EXTERN image_t			images[ MAX_IMAGES ];
+
+Q_EXTERN int				numPicoModels Q_ASSIGN( 0 );
+Q_EXTERN picoModel_t		*picoModels[ MAX_MODELS ];
+
+Q_EXTERN shaderInfo_t		*shaderInfo Q_ASSIGN( NULL );
+Q_EXTERN int				numShaderInfo Q_ASSIGN( 0 );
+Q_EXTERN int				numVertexRemaps Q_ASSIGN( 0 );
+
+Q_EXTERN surfaceParm_t		custSurfaceParms[ MAX_CUST_SURFACEPARMS ];
+Q_EXTERN int				numCustSurfaceParms Q_ASSIGN( 0 );
+
+Q_EXTERN char				mapName[ MAX_QPATH ];	/* ydnar: per-map custom shaders for larger lightmaps */
+Q_EXTERN char				mapShaderFile[ 1024 ];
+Q_EXTERN qboolean			warnImage Q_ASSIGN( qtrue );
+
+/* ydnar: sinusoid samples */
+Q_EXTERN float				jitters[ MAX_JITTERS ];
+
+
+/* commandline arguments */
+Q_EXTERN qboolean			verbose;
+Q_EXTERN qboolean			verboseEntities Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			force Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			infoMode Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			useCustomInfoParms Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			noprune Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			leaktest Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			nodetail Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			nosubdivide Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			notjunc Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			fulldetail Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			nowater Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			noCurveBrushes Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			fakemap Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			coplanar Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			nofog Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			noHint Q_ASSIGN( qfalse );				/* ydnar */
+Q_EXTERN qboolean			renameModelShaders Q_ASSIGN( qfalse );	/* ydnar */
+Q_EXTERN qboolean			skyFixHack Q_ASSIGN( qfalse );			/* ydnar */
+
+Q_EXTERN int				patchSubdivisions Q_ASSIGN( 8 );		/* ydnar: -patchmeta subdivisions */
+
+Q_EXTERN int				maxSurfaceVerts Q_ASSIGN( 64 );			/* ydnar */
+Q_EXTERN int				maxSurfaceIndexes Q_ASSIGN( 1000 );		/* ydnar */
+Q_EXTERN float				npDegrees Q_ASSIGN( 0.0f );				/* ydnar: nonplanar degrees */
+Q_EXTERN int				bevelSnap Q_ASSIGN( 0 );				/* ydnar: bevel plane snap */
+Q_EXTERN int				texRange Q_ASSIGN( 0 );
+Q_EXTERN qboolean			flat Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			meta Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			patchMeta Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			emitFlares Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			debugSurfaces Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			debugInset Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			debugPortals Q_ASSIGN( qfalse );
+
+Q_EXTERN double				normalEpsilon Q_ASSIGN( 0.00001 );
+Q_EXTERN double				distanceEpsilon Q_ASSIGN( 0.01 );
+
+
+/* bsp */
+Q_EXTERN int				numMapEntities Q_ASSIGN( 0 );
+
+Q_EXTERN int				blockSize[ 3 ]					/* should be the same as in radiant */
+#ifndef MAIN_C
+							;
+#else
+							= { 1024, 1024, 1024 };
+#endif
+
+Q_EXTERN char				name[ 1024 ];
+Q_EXTERN char				source[ 1024 ];
+Q_EXTERN char				outbase[ 32 ];
+
+Q_EXTERN int				sampleSize;						/* lightmap sample size in units */
+
+Q_EXTERN int				mapEntityNum Q_ASSIGN( 0 );
+
+Q_EXTERN int				entitySourceBrushes;
+
+Q_EXTERN plane_t			mapplanes[ MAX_MAP_PLANES ];	/* mapplanes[ num ^ 1 ] will always be the mirror or mapplanes[ num ] */
+Q_EXTERN int				nummapplanes;					/* nummapplanes will always be even */
+Q_EXTERN int				numMapPatches;
+Q_EXTERN vec3_t				mapMins, mapMaxs;
+
+Q_EXTERN int				defaultFogNum Q_ASSIGN( -1 );	/* ydnar: cleaner fog handling */
+Q_EXTERN int				numMapFogs Q_ASSIGN( 0 );
+Q_EXTERN fog_t				mapFogs[ MAX_MAP_FOGS ];
+
+Q_EXTERN entity_t			*mapEnt;
+Q_EXTERN brush_t			*buildBrush;
+Q_EXTERN int				numActiveBrushes;
+Q_EXTERN int				g_bBrushPrimit;
+
+Q_EXTERN int				numStrippedLights Q_ASSIGN( 0 );
+
+
+/* surface stuff */
+Q_EXTERN mapDrawSurface_t	*mapDrawSurfs Q_ASSIGN( NULL );
+Q_EXTERN int				numMapDrawSurfs;
+
+Q_EXTERN int				numSurfacesByType[ NUM_SURFACE_TYPES ];
+Q_EXTERN int				numClearedSurfaces;
+Q_EXTERN int				numStripSurfaces;
+Q_EXTERN int				numFanSurfaces;
+Q_EXTERN int				numMergedSurfaces;
+Q_EXTERN int				numMergedVerts;
+
+Q_EXTERN int				numRedundantIndexes;
+
+Q_EXTERN int				numSurfaceModels Q_ASSIGN( 0 );
+
+Q_EXTERN byte				debugColors[ 12 ][ 3 ]
+#ifndef MAIN_C
+							;
+#else
+							=
+							{
+								{ 255, 0, 0 },
+								{ 192, 128, 128 },
+								{ 255, 255, 0 },
+								{ 192, 192, 128 },
+								{ 0, 255, 255 },
+								{ 128, 192, 192 },
+								{ 0, 0, 255 },
+								{ 128, 128, 192 },
+								{ 255, 0, 255 },
+								{ 192, 128, 192 },
+								{ 0, 255, 0 },
+								{ 128, 192, 128 }
+							};
+#endif
+
+Q_EXTERN qboolean			skyboxPresent Q_ASSIGN( qfalse );
+Q_EXTERN int				skyboxArea Q_ASSIGN( -1 );
+Q_EXTERN m4x4_t				skyboxTransform;
+
+
+
+/* -------------------------------------------------------------------------------
+
+vis global variables
+
+------------------------------------------------------------------------------- */
+
+/* commandline arguments */
+Q_EXTERN qboolean			fastvis;
+Q_EXTERN qboolean			noPassageVis;
+Q_EXTERN qboolean			passageVisOnly;
+Q_EXTERN qboolean			mergevis;
+Q_EXTERN qboolean			nosort;
+Q_EXTERN qboolean			saveprt;
+Q_EXTERN qboolean			hint;	/* ydnar */
+Q_EXTERN char				inbase[ MAX_QPATH ];
+
+/* other bits */
+Q_EXTERN int				totalvis;
+
+Q_EXTERN float				farPlaneDist;	/* rr2do2, rf, mre, ydnar all contributed to this one... */
+
+Q_EXTERN int				numportals;
+Q_EXTERN int				portalclusters;
+
+Q_EXTERN vportal_t			*portals;
+Q_EXTERN leaf_t				*leafs;
+
+Q_EXTERN vportal_t			*faces;
+Q_EXTERN leaf_t				*faceleafs;
+
+Q_EXTERN int				numfaces;
+
+Q_EXTERN int				c_portaltest, c_portalpass, c_portalcheck;
+Q_EXTERN int				c_portalskip, c_leafskip;
+Q_EXTERN int				c_vistest, c_mighttest;
+Q_EXTERN int				c_chains;
+
+Q_EXTERN byte				*vismap, *vismap_p, *vismap_end;
+
+Q_EXTERN int				testlevel;
+
+Q_EXTERN byte				*uncompressed;
+
+Q_EXTERN int				leafbytes, leaflongs;
+Q_EXTERN int				portalbytes, portallongs;
+
+Q_EXTERN vportal_t			*sorted_portals[ MAX_MAP_PORTALS * 2 ];
+
+
+
+/* -------------------------------------------------------------------------------
+
+light global variables
+
+------------------------------------------------------------------------------- */
+
+/* commandline arguments */
+Q_EXTERN qboolean			noSurfaces;
+
+Q_EXTERN qboolean			deluxemap;
+Q_EXTERN qboolean			debugDeluxemap;
+
+Q_EXTERN qboolean			loMem Q_ASSIGN( qfalse );
+
+Q_EXTERN qboolean			fast;
+Q_EXTERN qboolean			faster;
+Q_EXTERN qboolean			fastgrid;
+Q_EXTERN qboolean			fastbounce;
+Q_EXTERN qboolean			cheap;
+Q_EXTERN qboolean			cheapgrid;
+Q_EXTERN qboolean			smooth;
+Q_EXTERN int				bounce;
+Q_EXTERN qboolean			bounceOnly;
+Q_EXTERN qboolean			bouncing;
+Q_EXTERN qboolean			bouncegrid;
+Q_EXTERN qboolean			normalmap;
+Q_EXTERN qboolean			trisoup;
+Q_EXTERN qboolean			shade;
+Q_EXTERN float				shadeAngleDegrees Q_ASSIGN( 0.0f );
+Q_EXTERN int				superSample Q_ASSIGN( 0 );
+Q_EXTERN int				lightSamples Q_ASSIGN( 1 );
+Q_EXTERN qboolean			filter;
+Q_EXTERN qboolean			sunOnly;
+Q_EXTERN int				approximateTolerance Q_ASSIGN( 0 );
+Q_EXTERN qboolean			noCollapse;
+Q_EXTERN qboolean			debug;
+Q_EXTERN qboolean			debugSurfaces;
+Q_EXTERN qboolean			debugUnused;
+Q_EXTERN qboolean			debugAxis;
+Q_EXTERN qboolean			debugCluster;
+Q_EXTERN qboolean			debugOrigin;
+Q_EXTERN qboolean			exportLightmaps;
+Q_EXTERN qboolean			externalLightmaps;
+Q_EXTERN int				lmCustomSize Q_ASSIGN( LIGHTMAP_WIDTH );
+
+/* standard flags */
+Q_EXTERN qboolean			noTrace;
+Q_EXTERN qboolean			patchShadows;
+Q_EXTERN qboolean			dump;
+Q_EXTERN qboolean			extra;
+Q_EXTERN qboolean			extraWide;
+Q_EXTERN qboolean			lightmapBorder;
+
+Q_EXTERN qboolean			noSurfaces;
+
+Q_EXTERN int				sampleSize Q_ASSIGN( DEFAULT_LIGHTMAP_SAMPLE_SIZE );
+Q_EXTERN qboolean			noVertexLighting Q_ASSIGN( qfalse );
+Q_EXTERN qboolean			noGridLighting Q_ASSIGN( qfalse );
+
+/* longest distance across the map */
+Q_EXTERN float				maxMapDistance Q_ASSIGN( 0 );
+
+/* for run time tweaking of light sources */
+Q_EXTERN float				pointScale Q_ASSIGN( 7500.0f );
+Q_EXTERN float				areaScale Q_ASSIGN( 0.25f );
+Q_EXTERN float				skyScale Q_ASSIGN( 1.0f );
+Q_EXTERN float				bounceScale Q_ASSIGN( 0.25f );
+
+/* ydnar: for runtime tweaking of falloff tolerance */
+Q_EXTERN float				falloffTolerance Q_ASSIGN( 1.0f );
+
+Q_EXTERN qboolean			exactPointToPolygon Q_ASSIGN( qtrue );
+
+Q_EXTERN float				formFactorValueScale Q_ASSIGN( 3.0f );
+
+Q_EXTERN float				linearScale Q_ASSIGN( 1.0f / 8000.0f );
+
+Q_EXTERN light_t			*lights;
+Q_EXTERN int				numPointLights;
+Q_EXTERN int				numSpotLights;
+Q_EXTERN int				numSunLights;
+Q_EXTERN int				numAreaLights;
+
+/* ydnar: for luxel placement */
+Q_EXTERN int				numSurfaceClusters, maxSurfaceClusters;
+Q_EXTERN int				*surfaceClusters;
+
+/* ydnar: for radiosity */
+Q_EXTERN int				numDiffuseLights;
+Q_EXTERN int				numBrushDiffuseLights;
+Q_EXTERN int				numTriangleDiffuseLights;
+Q_EXTERN int				numPatchDiffuseLights;
+
+/* ydnar: general purpose extra copy of drawvert list */
+Q_EXTERN bspDrawVert_t		*yDrawVerts;
+
+/* ydnar: for tracing statistics */
+Q_EXTERN int				minSurfacesTested;
+Q_EXTERN int				maxSurfacesTested;
+Q_EXTERN int				totalSurfacesTested;
+Q_EXTERN int				totalTraces;
+
+Q_EXTERN FILE				*dumpFile;
+
+Q_EXTERN int				c_visible, c_occluded;
+Q_EXTERN int				c_subsampled;	/* ydnar */
+
+Q_EXTERN int				defaultLightSubdivide Q_ASSIGN( 999 );
+
+Q_EXTERN vec3_t				ambientColor;
+Q_EXTERN vec3_t				minLight, minVertexLight, minGridLight;
+
+Q_EXTERN int				*entitySurface;
+Q_EXTERN vec3_t				*surfaceOrigin;
+
+Q_EXTERN vec3_t				sunDirection;
+Q_EXTERN vec3_t				sunLight;
+
+/* tracing */
+Q_EXTERN int				c_totalTrace;
+Q_EXTERN int				c_cullTrace, c_testTrace;
+Q_EXTERN int				c_testFacets;
+
+/* ydnar: light optimization */
+Q_EXTERN float				subdivideThreshold Q_ASSIGN( DEFAULT_SUBDIVIDE_THRESHOLD );
+
+Q_EXTERN int				numOpaqueBrushes, maxOpaqueBrush;
+Q_EXTERN byte				*opaqueBrushes;
+
+Q_EXTERN int				numLights;
+Q_EXTERN int				numCulledLights;
+
+Q_EXTERN int				gridBoundsCulled;
+Q_EXTERN int				gridEnvelopeCulled;
+
+Q_EXTERN int				lightsBoundsCulled;
+Q_EXTERN int				lightsEnvelopeCulled;
+Q_EXTERN int				lightsPlaneCulled;
+Q_EXTERN int				lightsClusterCulled;
+
+/* ydnar: radiosity */
+Q_EXTERN float				diffuseSubdivide Q_ASSIGN( 256.0f );
+Q_EXTERN float				minDiffuseSubdivide Q_ASSIGN( 64.0f );
+Q_EXTERN int				numDiffuseSurfaces Q_ASSIGN( 0 );
+
+/* ydnar: list of surface information necessary for lightmap calculation */
+Q_EXTERN surfaceInfo_t		*surfaceInfos Q_ASSIGN( NULL );
+
+/* ydnar: sorted list of surfaces */
+Q_EXTERN int				*sortSurfaces Q_ASSIGN( NULL );
+
+/* clumps of surfaces that share a raw lightmap */
+Q_EXTERN int				numLightSurfaces Q_ASSIGN( 0 );
+Q_EXTERN int				*lightSurfaces Q_ASSIGN( NULL );
+
+/* raw lightmaps */
+Q_EXTERN int				numRawSuperLuxels Q_ASSIGN( 0 );
+Q_EXTERN int				numRawLightmaps Q_ASSIGN( 0 );
+Q_EXTERN rawLightmap_t		*rawLightmaps Q_ASSIGN( NULL );
+Q_EXTERN int				*sortLightmaps Q_ASSIGN( NULL );
+
+/* vertex luxels */
+Q_EXTERN float				*vertexLuxels[ MAX_LIGHTMAPS ];
+Q_EXTERN float				*radVertexLuxels[ MAX_LIGHTMAPS ];
+
+/* bsp lightmaps */
+Q_EXTERN int				numLightmapShaders Q_ASSIGN( 0 );
+Q_EXTERN int				numOutLightmaps Q_ASSIGN( 0 );
+Q_EXTERN int				numBSPLightmaps Q_ASSIGN( 0 );
+Q_EXTERN int				numExtLightmaps Q_ASSIGN( 0 );
+Q_EXTERN outLightmap_t		*outLightmaps Q_ASSIGN( NULL );
+
+/* grid points */
+Q_EXTERN int				numRawGridPoints Q_ASSIGN( 0 );
+Q_EXTERN rawGridPoint_t		*rawGridPoints Q_ASSIGN( NULL );
+
+Q_EXTERN int				numSurfsVertexLit Q_ASSIGN( 0 );
+Q_EXTERN int				numSurfsVertexForced Q_ASSIGN( 0 );
+Q_EXTERN int				numSurfsVertexApproximated Q_ASSIGN( 0 );
+Q_EXTERN int				numSurfsLightmapped Q_ASSIGN( 0 );
+Q_EXTERN int				numPlanarsLightmapped Q_ASSIGN( 0 );
+Q_EXTERN int				numNonPlanarsLightmapped Q_ASSIGN( 0 );
+Q_EXTERN int				numPatchesLightmapped Q_ASSIGN( 0 );
+Q_EXTERN int				numPlanarPatchesLightmapped Q_ASSIGN( 0 );
+
+Q_EXTERN int				numLuxels Q_ASSIGN( 0 );
+Q_EXTERN int				numLuxelsMapped Q_ASSIGN( 0 );
+Q_EXTERN int				numLuxelsOccluded Q_ASSIGN( 0 );
+Q_EXTERN int				numLuxelsIlluminated Q_ASSIGN( 0 );
+Q_EXTERN int				numVertsIlluminated Q_ASSIGN( 0 );
+
+/* lightgrid */
+Q_EXTERN vec3_t				gridMins;
+Q_EXTERN int				gridBounds[ 3 ];
+Q_EXTERN vec3_t				gridSize
+#ifndef MAIN_C
+							;
+#else
+							= { 64, 64, 128 };
+#endif
+
+
+
+/* -------------------------------------------------------------------------------
+
+abstracted bsp globals
+
+------------------------------------------------------------------------------- */
+
+Q_EXTERN int				numEntities Q_ASSIGN( 0 );
+Q_EXTERN int				numBSPEntities Q_ASSIGN( 0 );
+Q_EXTERN entity_t			entities[ MAX_MAP_ENTITIES ];
+
+Q_EXTERN int				numBSPModels Q_ASSIGN( 0 );
+Q_EXTERN bspModel_t			bspModels[ MAX_MAP_MODELS ];
+
+Q_EXTERN int				numBSPShaders Q_ASSIGN( 0 );
+Q_EXTERN bspShader_t		bspShaders[ MAX_MAP_MODELS ];
+
+Q_EXTERN int				bspEntDataSize Q_ASSIGN( 0 );
+Q_EXTERN char				bspEntData[ MAX_MAP_ENTSTRING ];
+
+Q_EXTERN int				numBSPLeafs Q_ASSIGN( 0 );
+Q_EXTERN bspLeaf_t			bspLeafs[ MAX_MAP_LEAFS ];
+
+Q_EXTERN int				numBSPPlanes Q_ASSIGN( 0 );
+Q_EXTERN bspPlane_t			bspPlanes[ MAX_MAP_PLANES ];
+
+Q_EXTERN int				numBSPNodes Q_ASSIGN( 0 );
+Q_EXTERN bspNode_t			bspNodes[ MAX_MAP_NODES ];
+
+Q_EXTERN int				numBSPLeafSurfaces Q_ASSIGN( 0 );
+Q_EXTERN int				bspLeafSurfaces[ MAX_MAP_LEAFFACES ];
+
+Q_EXTERN int				numBSPLeafBrushes Q_ASSIGN( 0 );
+Q_EXTERN int				bspLeafBrushes[ MAX_MAP_LEAFBRUSHES ];
+
+Q_EXTERN int				numBSPBrushes Q_ASSIGN( 0 );
+Q_EXTERN bspBrush_t			bspBrushes[ MAX_MAP_BRUSHES ];
+
+Q_EXTERN int				numBSPBrushSides Q_ASSIGN( 0 );
+Q_EXTERN bspBrushSide_t		bspBrushSides[ MAX_MAP_BRUSHSIDES ];
+
+Q_EXTERN int				numBSPLightBytes Q_ASSIGN( 0 );
+Q_EXTERN byte				*bspLightBytes Q_ASSIGN( NULL );
+
+//%	Q_EXTERN int				numBSPGridPoints Q_ASSIGN( 0 );
+//%	Q_EXTERN byte				*bspGridPoints Q_ASSIGN( NULL );
+
+Q_EXTERN int				numBSPGridPoints Q_ASSIGN( 0 );
+Q_EXTERN bspGridPoint_t		*bspGridPoints Q_ASSIGN( NULL );
+
+Q_EXTERN int				numBSPVisBytes Q_ASSIGN( 0 );
+Q_EXTERN byte				bspVisBytes[ MAX_MAP_VISIBILITY ];
+
+Q_EXTERN int				numBSPDrawVerts Q_ASSIGN( 0 );
+Q_EXTERN bspDrawVert_t		*bspDrawVerts Q_ASSIGN( NULL );
+
+Q_EXTERN int				numBSPDrawIndexes Q_ASSIGN( 0 );
+Q_EXTERN int				bspDrawIndexes[ MAX_MAP_DRAW_INDEXES ];
+
+Q_EXTERN int				numBSPDrawSurfaces Q_ASSIGN( 0 );
+Q_EXTERN bspDrawSurface_t	*bspDrawSurfaces Q_ASSIGN( NULL );
+
+Q_EXTERN int				numBSPFogs Q_ASSIGN( 0 );
+Q_EXTERN bspFog_t			bspFogs[ MAX_MAP_FOGS ];
+
+
+
+/* end marker */
+#endif
diff --git a/tools/quake3/q3map2/shaders.c b/tools/quake3/q3map2/shaders.c
index abeada6d..a0988938 100644
--- a/tools/quake3/q3map2/shaders.c
+++ b/tools/quake3/q3map2/shaders.c
@@ -1,1926 +1,1926 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define SHADERS_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-AlphaMod()
-routines for dealing with vertex alpha modification
-*/
-
-void AlphaMod( alphaMod_t *am, int numVerts, bspDrawVert_t *drawVerts )
-{
-	int				i, j;
-	float			mult, add, a;
-	bspDrawVert_t	*dv;
-	alphaMod_t		*am2;
-	
-	
-	/* dummy check */
-	if( am == NULL || numVerts < 1 || drawVerts == NULL )
-		return;
-	
-	
-	/* walk vertex list */
-	for( i = 0; i < numVerts; i++ )
-	{
-		/* get vertex */
-		dv = &drawVerts[ i ];
-		
-		/* walk alphamod list */
-		for( am2 = am; am2 != NULL; am2 = am2->next )
-		{
-			/* switch on type */
-			switch( am->type )
-			{
-				case AM_DOT_PRODUCT:
-					mult = DotProduct( dv->normal, am2->data );
-					add = 0.0f;
-					break;
-				
-				default:
-					mult = 1.0f;
-					add = 0.0f;
-					break;
-			}
-			
-			/* apply mod */
-			for( j = 0; j < MAX_LIGHTMAPS; j++ )
-			{
-				a = (mult * dv->color[ j ][ 3 ]) + add;
-				if( a < 0 )
-					a = 0;
-				else if( a > 255 )
-					a = 255;
-				dv->color[ j ][ 3 ] = a;
-			}
-		}
-	}
-}
-
-
-
-/*
-TcMod*()
-routines for dealing with a 3x3 texture mod matrix
-*/
-
-void TcMod( tcMod_t mod, float st[ 2 ] )
-{
-	float	old[ 2 ];
-	
-	
-	old[ 0 ] = st[ 0 ];
-	old[ 1 ] = st[ 1 ];
-	st[ 0 ] = (mod[ 0 ][ 0 ] * old[ 0 ]) + (mod[ 0 ][ 1 ] * old[ 1 ]) + mod[ 0 ][ 2 ];
-	st[ 1 ] = (mod[ 1 ][ 0 ] * old[ 0 ]) + (mod[ 1 ][ 1 ] * old[ 1 ]) + mod[ 1 ][ 2 ];
-}
-
-
-void TcModIdentity( tcMod_t mod )
-{
-	mod[ 0 ][ 0 ] = 1.0f;	mod[ 0 ][ 1 ] = 0.0f;	mod[ 0 ][ 2 ] = 0.0f;
-	mod[ 1 ][ 0 ] = 0.0f;	mod[ 1 ][ 1 ] = 1.0f;	mod[ 1 ][ 2 ] = 0.0f;
-	mod[ 2 ][ 0 ] = 0.0f;	mod[ 2 ][ 1 ] = 0.0f;	mod[ 2 ][ 2 ] = 1.0f;	/* this row is only used for multiples, not transformation */
-}
-
-
-void TcModMultiply( tcMod_t a, tcMod_t b, tcMod_t out )
-{
-	int		i;
-	
-	
-	for( i = 0; i < 3; i++ )
-	{
-		out[ i ][ 0 ] = (a[ i ][ 0 ] * b[ 0 ][ 0 ]) + (a[ i ][ 1 ] * b[ 1 ][ 0 ]) + (a[ i ][ 2 ] * b[ 2 ][ 0 ]);
-		out[ i ][ 1 ] = (a[ i ][ 0 ] * b[ 0 ][ 1 ]) + (a[ i ][ 1 ] * b[ 1 ][ 1 ]) + (a[ i ][ 2 ] * b[ 2 ][ 1 ]);
-		out[ i ][ 2 ] = (a[ i ][ 0 ] * b[ 0 ][ 2 ]) + (a[ i ][ 1 ] * b[ 1 ][ 2 ]) + (a[ i ][ 2 ] * b[ 2 ][ 2 ]);
-	}
-}
-
-
-void TcModTranslate( tcMod_t mod, float s, float t )
-{
-	mod[ 0 ][ 2 ] += s;
-	mod[ 1 ][ 2 ] += t;
-}
-
-
-void TcModScale( tcMod_t mod, float s, float t )
-{
-	mod[ 0 ][ 0 ] *= s;
-	mod[ 1 ][ 1 ] *= t;
-}
-
-
-void TcModRotate( tcMod_t mod, float euler )
-{
-	tcMod_t	old, temp;
-	float	radians, sinv, cosv;
-	
-	
-	memcpy( old, mod, sizeof( tcMod_t ) );
-	TcModIdentity( temp );
-
-	radians = euler / 180 * Q_PI;
-	sinv = sin( radians );
-	cosv = cos( radians );
-
-	temp[ 0 ][ 0 ] = cosv;	temp[ 0 ][ 1 ] = -sinv;
-	temp[ 1 ][ 0 ] = sinv;	temp[ 1 ][ 1 ] = cosv;
-	
-	TcModMultiply( old, temp, mod );
-}
-
-
-
-/*
-ApplySurfaceParm() - ydnar
-applies a named surfaceparm to the supplied flags
-*/
-
-qboolean ApplySurfaceParm( char *name, int *contentFlags, int *surfaceFlags, int *compileFlags )
-{
-	int				i, fake;
-	surfaceParm_t	*sp;
-	
-	
-	/* dummy check */
-	if( name == NULL )
-		name = "";
-	if( contentFlags == NULL )
-		contentFlags = &fake;
-	if( surfaceFlags == NULL )
-		surfaceFlags = &fake;
-	if( compileFlags == NULL )
-		compileFlags = &fake;
-	
-	/* walk the current game's surfaceparms */
-	sp = game->surfaceParms;
-	while( sp->name != NULL )
-	{
-		/* match? */
-		if( !Q_stricmp( name, sp->name ) )
-		{
-			/* clear and set flags */
-			*contentFlags &= ~(sp->contentFlagsClear);
-			*contentFlags |= sp->contentFlags;
-			*surfaceFlags &= ~(sp->surfaceFlagsClear);
-			*surfaceFlags |= sp->surfaceFlags;
-			*compileFlags &= ~(sp->compileFlagsClear);
-			*compileFlags |= sp->compileFlags;
-			
-			/* return ok */
-			return qtrue;
-		}
-		
-		/* next */
-		sp++;
-	}
-	
-	/* check custom info parms */
-	for( i = 0; i < numCustSurfaceParms; i++ )
-	{
-		/* get surfaceparm */
-		sp = &custSurfaceParms[ i ];
-		
-		/* match? */
-		if( !Q_stricmp( name, sp->name ) )
-		{
-			/* clear and set flags */
-			*contentFlags &= ~(sp->contentFlagsClear);
-			*contentFlags |= sp->contentFlags;
-			*surfaceFlags &= ~(sp->surfaceFlagsClear);
-			*surfaceFlags |= sp->surfaceFlags;
-			*compileFlags &= ~(sp->compileFlagsClear);
-			*compileFlags |= sp->compileFlags;
-			
-			/* return ok */
-			return qtrue;
-		}
-	}
-	
-	/* no matching surfaceparm found */
-	return qfalse;
-}
-
-
-
-/*
-BeginMapShaderFile() - ydnar
-erases and starts a new map shader script
-*/
-
-void BeginMapShaderFile( const char *mapFile )
-{
-	char	base[ 1024 ];
-	int		len;
-	
-
-	/* dummy check */
-	mapName[ 0 ] = '\0';
-	mapShaderFile[ 0 ] = '\0';
-	if( mapFile == NULL || mapFile[ 0 ] == '\0' )
-		return;
-	
-	/* copy map name */
-	strcpy( base, mapFile );
-	StripExtension( base );
-	
-	/* extract map name */
-	len = strlen( base ) - 1;
-	while( len > 0 && base[ len ] != '/' && base[ len ] != '\\' )
-		len--;
-	strcpy( mapName, &base[ len + 1 ] );
-	base[ len ] = '\0';
-	if( len <= 0 )
-		return;
-	
-	/* append ../scripts/q3map2_<mapname>.shader */
-	sprintf( mapShaderFile, "%s/../%s/q3map2_%s.shader", base, game->shaderPath, mapName );
-	Sys_FPrintf( SYS_VRB, "Map has shader script %s\n", mapShaderFile );
-	
-	/* remove it */
-	remove( mapShaderFile );
-	
-	/* stop making warnings about missing images */
-	warnImage = qfalse;
-}
-
-
-
-/*
-WriteMapShaderFile() - ydnar
-writes a shader to the map shader script
-*/
-
-void WriteMapShaderFile( void )
-{
-	FILE			*file;
-	shaderInfo_t	*si;
-	int				i, num;
-	
-	
-	/* dummy check */
-	if( mapShaderFile[ 0 ] == '\0' )
-		return;
-	
-	/* are there any custom shaders? */
-	for( i = 0, num = 0; i < numShaderInfo; i++ )
-	{
-		if( shaderInfo[ i ].custom ) 
-			break;
-	}
-	if( i == numShaderInfo )
-		return;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- WriteMapShaderFile ---\n");
-	Sys_FPrintf( SYS_VRB, "Writing %s", mapShaderFile );
-	
-	/* open shader file */
-	file = fopen( mapShaderFile, "w" );
-	if( file == NULL )
-	{
-		Sys_Printf( "WARNING: Unable to open map shader file %s for writing\n", mapShaderFile );
-		return;
-	}
-	
-	/* print header */
-	fprintf( file,
-		"// Custom shader file for %s.bsp\n"
-		"// Generated by Q3Map2 (ydnar)\n"
-		"// Do not edit! This file is overwritten on recompiles.\n\n",
-		mapName );
-	
-	/* walk the shader list */
-	for( i = 0, num = 0; i < numShaderInfo; i++ )
-	{
-		/* get the shader and print it */
-		si = &shaderInfo[ i ];
-		if( si->custom == qfalse || si->shaderText == NULL || si->shaderText[ 0 ] == '\0' )
-			continue;
-		num++;
-
-		/* print it to the file */
-		fprintf( file, "%s%s\n", si->shader, si->shaderText );
-		//%	Sys_Printf( "%s%s\n", si->shader, si->shaderText ); /* FIXME: remove debugging code */
-		
-		Sys_FPrintf( SYS_VRB, "." );
-	}
-	
-	/* close the shader */
-	fclose( file );
-	
-	Sys_FPrintf( SYS_VRB, "\n" );
-	
-	/* print some stats */
-	Sys_Printf( "%9d custom shaders emitted\n", num );
-}
-
-
-
-/*
-CustomShader() - ydnar
-sets up a custom map shader
-*/
-
-shaderInfo_t *CustomShader( shaderInfo_t *si, char *find, char *replace )
-{
-	shaderInfo_t	*csi;
-	char			shader[ MAX_QPATH ];
-	char			*s;
-	int				loc;
-	md5_state_t		md5;
-	byte			digest[ 16 ];
-	char			*srcShaderText, temp[ 8192 ], shaderText[ 8192 ];	/* ydnar: fixme (make this bigger?) */
-	
-	
-	/* dummy check */
-	if( si == NULL )
-		return ShaderInfoForShader( "default" );
-	
-	/* default shader text source */
-	srcShaderText = si->shaderText;
-	
-	/* et: implicitMap */
-	if( si->implicitMap == IM_OPAQUE )
-	{
-		srcShaderText = temp;
-		sprintf( temp, "\n"
-			"{ // Q3Map2 defaulted (implicitMap)\n"
-			"\t{\n"
-			"\t\tmap $lightmap\n"
-			"\t\trgbGen identity\n"
-			"\t}\n"
-			"\tq3map_styleMarker\n"
-			"\t{\n"
-			"\t\tmap %s\n"
-			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
-			"\t\trgbGen identity\n"
-			"\t}\n"
-			"}\n",
-			si->implicitImagePath );
-	}
-	
-	/* et: implicitMask */
-	else if( si->implicitMap == IM_MASKED )
-	{
-		srcShaderText = temp;
-		sprintf( temp, "\n"
-			"{ // Q3Map2 defaulted (implicitMask)\n"
-			"\tcull none\n"
-			"\t{\n"
-			"\t\tmap %s\n"
-			"\t\talphaFunc GE128\n"
-			"\t\tdepthWrite\n"
-			"\t}\n"
-			"\t{\n"
-			"\t\tmap $lightmap\n"
-			"\t\trgbGen identity\n"
-			"\t\tdepthFunc equal\n"
-			"\t}\n"
-			"\tq3map_styleMarker\n"
-			"\t{\n"
-			"\t\tmap %s\n"
-			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
-			"\t\tdepthFunc equal\n"
-			"\t\trgbGen identity\n"
-			"\t}\n"
-			"}\n",
-			si->implicitImagePath,
-			si->implicitImagePath );
-	}
-	
-	/* et: implicitBlend */
-	else if( si->implicitMap == IM_BLEND )
-	{
-		srcShaderText = temp;
-		sprintf( temp, "\n"
-			"{ // Q3Map2 defaulted (implicitBlend)\n"
-			"\tcull none\n"
-			"\t{\n"
-			"\t\tmap %s\n"
-			"\t\tblendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA\n"
-			"\t}\n"
-			"\t{\n"
-			"\t\tmap $lightmap\n"
-			"\t\trgbGen identity\n"
-			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
-			"\t}\n"
-			"\tq3map_styleMarker\n"
-			"}\n",
-			si->implicitImagePath );
-	}
-	
-	/* default shader text */
-	else if( srcShaderText == NULL )
-	{
-		srcShaderText = temp;
-		sprintf( temp, "\n"
-			"{ // Q3Map2 defaulted\n"
-			"\t{\n"
-			"\t\tmap $lightmap\n"
-			"\t\trgbGen identity\n"
-			"\t}\n"
-			"\tq3map_styleMarker\n"
-			"\t{\n"
-			"\t\tmap %s.tga\n"
-			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
-			"\t\trgbGen identity\n"
-			"\t}\n"
-			"}\n",
-			si->shader );
-	}
-	
-	/* error check */
-	if( (strlen( mapName ) + 1 + 32) > MAX_QPATH )
-		Error( "Custom shader name length (%d) exceeded. Shorten your map name.\n", MAX_QPATH );
-	
-	/* do some bad find-replace */
-	s = strstr( srcShaderText, find );
-	if( s == NULL )
-		//%	strcpy( shaderText, srcShaderText );
-		return si;	/* testing just using the existing shader if this fails */
-	else
-	{
-		/* substitute 'find' with 'replace' */
-		loc = s - srcShaderText;
-		strcpy( shaderText, srcShaderText );
-		shaderText[ loc ] = '\0';
-		strcat( shaderText, replace );
-		strcat( shaderText, &srcShaderText[ loc + strlen( find ) ] );
-	}
-	
-	/* make md5 hash of the shader text */
-	md5_init( &md5 );
-	md5_append( &md5, shaderText, strlen( shaderText ) );
-	md5_finish( &md5, digest );
-	
-	/* mangle hash into a shader name */
-	sprintf( shader, "%s/%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", mapName,
-		digest[ 0 ], digest[ 1 ], digest[ 2 ], digest[ 3 ], digest[ 4 ], digest[ 5 ], digest[ 6 ], digest[ 7 ], 
-		digest[ 8 ], digest[ 9 ], digest[ 10 ], digest[ 11 ], digest[ 12 ], digest[ 13 ], digest[ 14 ], digest[ 15 ] );
-	
-	/* get shader */
-	csi = ShaderInfoForShader( shader );
-	
-	/* might be a preexisting shader */
-	if( csi->custom )
-		return csi;
-	
-	/* clone the existing shader and rename */
-	memcpy( csi, si, sizeof( shaderInfo_t ) );
-	strcpy( csi->shader, shader );
-	csi->custom = qtrue;
-	
-	/* store new shader text */
-	csi->shaderText = safe_malloc( strlen( shaderText ) + 1 );
-	strcpy( csi->shaderText, shaderText );	/* LEAK! */
-	
-	/* return it */
-	return csi;
-}
-
-
-
-/*
-EmitVertexRemapShader()
-adds a vertexremapshader key/value pair to worldspawn
-*/
-
-void EmitVertexRemapShader( char *from, char *to )
-{
-	md5_state_t		md5;
-	byte			digest[ 16 ];
-	char			key[ 64 ], value[ 256 ];
-	
-	
-	/* dummy check */
-	if( from == NULL || from[ 0 ] == '\0' ||
-		to == NULL || to[ 0 ] == '\0' )
-		return;
-	
-	/* build value */
-	sprintf( value, "%s;%s", from, to );
-	
-	/* make md5 hash */
-	md5_init( &md5 );
-	md5_append( &md5, value, strlen( value ) );
-	md5_finish( &md5, digest );
-
-	/* make key (this is annoying, as vertexremapshader is precisely 17 characters,
-	   which is one too long, so we leave off the last byte of the md5 digest) */
-	sprintf( key, "vertexremapshader%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
-		digest[ 0 ], digest[ 1 ], digest[ 2 ], digest[ 3 ], digest[ 4 ], digest[ 5 ], digest[ 6 ], digest[ 7 ], 
-		digest[ 8 ], digest[ 9 ], digest[ 10 ], digest[ 11 ], digest[ 12 ], digest[ 13 ], digest[ 14 ] );	/* no: digest[ 15 ] */
-	
-	/* add key/value pair to worldspawn */
-	SetKeyValue( &entities[ 0 ], key, value );
-}
-
-
-
-/*
-AllocShaderInfo()
-allocates and initializes a new shader
-*/
-
-static shaderInfo_t	*AllocShaderInfo( void )
-{
-	shaderInfo_t	*si;
-	
-	
-	/* allocate? */
-	if( shaderInfo == NULL )
-	{
-		shaderInfo = safe_malloc( sizeof( shaderInfo_t ) * MAX_SHADER_INFO );
-		numShaderInfo = 0;
-	}
-	
-	/* bounds check */
-	if( numShaderInfo == MAX_SHADER_INFO )
-		Error( "MAX_SHADER_INFO exceeded. Remove some PK3 files or shader scripts from shaderlist.txt and try again." );
-	si = &shaderInfo[ numShaderInfo ];
-	numShaderInfo++;
-	
-	/* ydnar: clear to 0 first */
-	memset( si, 0, sizeof( shaderInfo_t ) );
-	
-	/* set defaults */
-	ApplySurfaceParm( "default", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
-	
-	si->backsplashFraction = DEF_BACKSPLASH_FRACTION;
-	si->backsplashDistance = DEF_BACKSPLASH_DISTANCE;
-	
-	si->bounceScale = DEF_RADIOSITY_BOUNCE;
-	
-	si->lightStyle = LS_NORMAL;
-	
-	si->polygonOffset = qfalse;
-	
-	si->shadeAngleDegrees = 0.0f;
-	si->lightmapSampleSize = 0;
-	si->lightmapSampleOffset = DEFAULT_LIGHTMAP_SAMPLE_OFFSET;
-	si->patchShadows = qfalse;
-	si->vertexShadows = qtrue;	/* ydnar: changed default behavior */
-	si->forceSunlight = qfalse;
-	si->vertexScale = 1.0;
-	si->notjunc = qfalse;
-	
-	/* ydnar: set texture coordinate transform matrix to identity */
-	TcModIdentity( si->mod );
-	
-	/* ydnar: lightmaps can now be > 128x128 in an externally generated tga */
-	si->lmCustomWidth = lmCustomSize;	//%	LIGHTMAP_WIDTH;
-	si->lmCustomHeight = lmCustomSize;	//%	LIGHTMAP_HEIGHT;
-	
-	/* return to sender */
-	return si;
-}
-
-
-
-/*
-FinishShader() - ydnar
-sets a shader's width and height among other things
-*/
-
-void FinishShader( shaderInfo_t *si )
-{
-	int		x, y;
-	float	st[ 2 ], o[ 2 ], dist, bestDist;
-	vec4_t	color, bestColor, delta;
-	
-
-	/* don't double-dip */
-	if( si->finished )
-		return;
-	
-	/* if they're explicitly set, copy from image size */
-	if( si->shaderWidth == 0 && si->shaderHeight == 0 )
-	{
-		si->shaderWidth = si->shaderImage->width;
-		si->shaderHeight = si->shaderImage->height;
-	}
-	
-	/* legacy terrain has explicit image-sized texture projection */
-	if( si->legacyTerrain && si->tcGen == qfalse )
-	{
-		/* set xy texture projection */
-		si->tcGen = qtrue;
-		VectorSet( si->vecs[ 0 ], (1.0f / (si->shaderWidth * 0.5f)), 0, 0 );
-		VectorSet( si->vecs[ 1 ], 0, (1.0f / (si->shaderHeight * 0.5f)), 0 );
-	}
-	
-	/* find pixel coordinates best matching the average color of the image */
-	bestDist = 99999999;
-	o[ 0 ] = 1.0f / si->shaderImage->width;
-	o[ 1 ] = 1.0f / si->shaderImage->height;
-	for( y = 0, st[ 1 ] = 0.0f; y < si->shaderImage->height; y++, st[ 1 ] += o[ 1 ] )
-	{
-		for( x = 0, st[ 0 ] = 0.0f; x < si->shaderImage->width; x++, st[ 0 ] += o[ 0 ] )
-		{
-			/* sample the shader image */
-			RadSampleImage( si->shaderImage->pixels, si->shaderImage->width, si->shaderImage->height, st, color );
-			
-			/* determine error squared */
-			VectorSubtract( color, si->averageColor, delta );
-			delta[ 3 ] = color[ 3 ] - si->averageColor[ 3 ];
-			dist = delta[ 0 ] * delta[ 0 ] + delta[ 1 ] * delta[ 1 ] + delta[ 2 ] * delta[ 2 ] + delta[ 3 ] * delta[ 3 ];
-			if( dist < bestDist )
-			{
-				VectorCopy( color, bestColor );
-				bestColor[ 3 ] = color[ 3 ];
-				si->stFlat[ 0 ] = st[ 0 ];
-				si->stFlat[ 1 ] = st[ 1 ];
-			}
-		}
-	}
-	
-	/* set to finished */
-	si->finished = qtrue;
-}
-
-
-
-/*
-LoadShaderImages()
-loads a shader's images
-ydnar: image.c made this a bit simpler
-*/
-
-static void LoadShaderImages( shaderInfo_t *si )
-{
-	int			i, count;
-	float		color[ 4 ];
-	
-	
-	/* nodraw shaders don't need images */
-	if( si->compileFlags & C_NODRAW )
-		si->shaderImage = ImageLoad( DEFAULT_IMAGE );
-	else
-	{
-		/* try to load editor image first */
-		si->shaderImage = ImageLoad( si->editorImagePath );
-		
-		/* then try shadername */
-		if( si->shaderImage == NULL )
-			si->shaderImage = ImageLoad( si->shader );
-		
-		/* then try implicit image path (note: new behavior!) */
-		if( si->shaderImage == NULL )
-			si->shaderImage = ImageLoad( si->implicitImagePath );
-		
-		/* then try lightimage (note: new behavior!) */
-		if( si->shaderImage == NULL )
-			si->shaderImage = ImageLoad( si->lightImagePath );
-		
-		/* otherwise, use default image */
-		if( si->shaderImage == NULL )
-		{
-			si->shaderImage = ImageLoad( DEFAULT_IMAGE );
-			if( warnImage && strcmp( si->shader, "noshader" ) )
-				Sys_Printf( "WARNING: Couldn't find image for shader %s\n", si->shader );
-		}
-		
-		/* load light image */
-		si->lightImage = ImageLoad( si->lightImagePath );
-		
-		/* load normalmap image (ok if this is NULL) */
-		si->normalImage = ImageLoad( si->normalImagePath );
-		if( si->normalImage != NULL )
-		{
-			Sys_FPrintf( SYS_VRB, "Shader %s has\n"
-								  "    NM %s\n", si->shader, si->normalImagePath );
-		}
-	}
-	
-	/* if no light image, use shader image */
-	if( si->lightImage == NULL )
-		si->lightImage = ImageLoad( si->shaderImage->name );
-	
-	/* create default and average colors */
-	count = si->lightImage->width * si->lightImage->height;
-	VectorClear( color );
-	color[ 3 ] = 0.0f;
-	for( i = 0; i < count; i++ )
-	{
-		color[ 0 ] += si->lightImage->pixels[ i * 4 + 0 ];
-		color[ 1 ] += si->lightImage->pixels[ i * 4 + 1 ];
-		color[ 2 ] += si->lightImage->pixels[ i * 4 + 2 ];
-		color[ 3 ] += si->lightImage->pixels[ i * 4 + 3 ];
-	}
-	
-	if( VectorLength( si->color ) <= 0.0f )
-		ColorNormalize( color, si->color );
-	VectorScale( color, (1.0f / count), si->averageColor );
-}
-
-
-
-/*
-ShaderInfoForShader()
-finds a shaderinfo for a named shader
-*/
-
-shaderInfo_t *ShaderInfoForShader( const char *shaderName )
-{
-	int				i;
-	shaderInfo_t	*si;
-	char			shader[ MAX_QPATH ];
-	
-	
-	/* dummy check */
-	if( shaderName == NULL || shaderName[ 0 ] == '\0' )
-	{
-		Sys_Printf( "WARNING: Null or empty shader name\n" );
-		shaderName = "missing";
-	}
-	
-	/* strip off extension */
-	strcpy( shader, shaderName );
-	StripExtension( shader );
-	
-	/* search for it */
-	for( i = 0; i < numShaderInfo; i++ )
-	{
-		si = &shaderInfo[ i ];
-		if( !Q_stricmp( shader, si->shader ) )
-		{
-			/* load image if necessary */
-			if( si->shaderImage == NULL )
-			{
-				LoadShaderImages( si );
-				FinishShader( si );
-			}
-			
-			/* return it */
-			return si;
-		}
-	}
-	
-	/* allocate a default shader */
-	si = AllocShaderInfo();
-	strcpy( si->shader, shader );
-	LoadShaderImages( si );
-	FinishShader( si );
-	
-	/* return it */
-	return si;
-}
-
-
-
-/*
-GetTokenAppend() - ydnar
-gets a token and appends its text to the specified buffer
-*/
-
-static int	oldScriptLine = 0;
-static int	tabDepth = 0;
-
-qboolean GetTokenAppend( char *buffer, qboolean crossline )
-{
-	qboolean	r;
-	int			i;
-	
-	
-	/* get the token */
-	r = GetToken( crossline );
-	if( r == qfalse || buffer == NULL || token[ 0 ] == '\0' )
-		return r;
-	
-	/* pre-tabstops */
-	if( token[ 0 ] == '}' )
-		tabDepth--;
-	
-	/* append? */
-	if( oldScriptLine != scriptline )
-	{
-		strcat( buffer, "\n" );
-		for( i = 0; i < tabDepth; i++ )
-			strcat( buffer, "\t" );
-	}
-	else
-		strcat( buffer, " " );
-	oldScriptLine = scriptline;
-	strcat( buffer, token );
-	
-	/* post-tabstops */
-	if( token[ 0 ] == '{' )
-		tabDepth++;
-	
-	/* return */
-	return r;
-}
-
-
-void Parse1DMatrixAppend( char *buffer, int x, vec_t *m )
-{
-	int		i;
-	
-	
-	if( !GetTokenAppend( buffer, qtrue ) || strcmp( token, "(" ) )
-		Error( "Parse1DMatrixAppend(): line %d: ( not found!", scriptline );
-	for( i = 0; i < x; i++ )
-	{
-		if( !GetTokenAppend( buffer, qfalse ) )
-			Error( "Parse1DMatrixAppend(): line %d: Number not found!", scriptline );
-		m[ i ] = atof( token );
-	}
-	if( !GetTokenAppend( buffer, qtrue ) || strcmp( token, ")" ) )
-		Error( "Parse1DMatrixAppend(): line %d: ) not found!", scriptline );
-}
-
-
-
-
-/*
-ParseShaderFile()
-parses a shader file into discrete shaderInfo_t
-*/
-
-static void ParseShaderFile( const char *filename )
-{
-	int				i, val;
-	shaderInfo_t	*si;
-	char			*suffix, temp[ 1024 ];
-	char			shaderText[ 8192 ];	/* ydnar: fixme (make this bigger?) */
-	
-	
-	/* init */
-	si = NULL;
-	shaderText[ 0 ] = '\0';
-	
-	/* load the shader */
-	LoadScriptFile( filename, 0 );
-	
-	/* tokenize it */
-	while( 1 )
-	{
-		/* copy shader text to the shaderinfo */
-		if( si != NULL && shaderText[ 0 ] != '\0' )
-		{
-			strcat( shaderText, "\n" );
-			si->shaderText = safe_malloc( strlen( shaderText ) + 1 );
-			strcpy( si->shaderText, shaderText );
-			//%	if( VectorLength( si->vecs[ 0 ] ) )
-			//%		Sys_Printf( "%s\n", shaderText );
-		}
-		
-		/* ydnar: clear shader text buffer */
-		shaderText[ 0 ] = '\0';
-		
-		/* test for end of file */
-		if( !GetToken( qtrue ) )
-			break;
-		
-		/* shader name is initial token */
-		si = AllocShaderInfo();
-		strcpy( si->shader, token );
-		
-		/* ignore ":q3map" suffix */
-		suffix = strstr( si->shader, ":q3map" );
-		if( suffix != NULL )
-			*suffix = '\0';
-		
-		/* handle { } section */
-		if( !GetTokenAppend( shaderText, qtrue ) )
-			break;
-		if( strcmp( token, "{" ) )
-		{
-			if( si != NULL )
-				Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nLast known shader: %s",
-					filename, scriptline, token, si->shader );
-			else
-				Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s",
-					filename, scriptline, token );
-		}
-		
-		while( 1 )
-		{
-			/* get the next token */
-			if( !GetTokenAppend( shaderText, qtrue ) )
-				break;
-			if( !strcmp( token, "}" ) )
-				break;
-			
-			
-			/* -----------------------------------------------------------------
-			   shader stages (passes)
-			   ----------------------------------------------------------------- */
-			
-			/* parse stage directives */
-			if( !strcmp( token, "{" ) )
-			{
-				si->hasPasses = qtrue;
-				while( 1 )
-				{
-					if( !GetTokenAppend( shaderText, qtrue ) )
-						break;
-					if( !strcmp( token, "}" ) )
-						break;
-					
-					/* only care about images if we don't have a editor/light image */
-					if( si->editorImagePath[ 0 ] == '\0' && si->lightImagePath[ 0 ] == '\0' && si->implicitImagePath[ 0 ] == '\0' )
-					{
-						/* digest any images */
-						if( !Q_stricmp( token, "map" ) ||
-							!Q_stricmp( token, "clampMap" ) ||
-							!Q_stricmp( token, "animMap" ) ||
-							!Q_stricmp( token, "clampAnimMap" ) ||
-							!Q_stricmp( token, "clampMap" ) ||
-							!Q_stricmp( token, "mapComp" ) ||
-							!Q_stricmp( token, "mapNoComp" ) )
-						{
-							/* skip one token for animated stages */
-							if( !Q_stricmp( token, "animMap" ) || !Q_stricmp( token, "clampAnimMap" ) )
-								GetTokenAppend( shaderText, qfalse );
-							
-							/* get an image */
-							GetTokenAppend( shaderText, qfalse );
-							if( token[ 0 ] != '*' && token[ 0 ] != '$' )
-							{
-								strcpy( si->lightImagePath, token );
-								DefaultExtension( si->lightImagePath, ".tga" );
-								
-								/* debug code */
-								//%	Sys_FPrintf( SYS_VRB, "Deduced shader image: %s\n", si->lightImagePath );
-							}
-						}
-					}
-				}
-			}
-			
-			
-			/* -----------------------------------------------------------------
-			   surfaceparm * directives
-			   ----------------------------------------------------------------- */
-			
-			/* match surfaceparm */
-			else if( !Q_stricmp( token, "surfaceparm" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				if( ApplySurfaceParm( token, &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
-					Sys_Printf( "WARNING: Unknown surfaceparm: \"%s\"\n", token );
-			}
-			
-			
-			/* -----------------------------------------------------------------
-			   game-related shader directives
-			   ----------------------------------------------------------------- */
-			
-			/* ydnar: fogparms (for determining fog volumes) */
-			else if( !Q_stricmp( token, "fogparms" ) )
-				si->fogParms = qtrue;
-			
-			/* ydnar: polygonoffset (for no culling) */
-			else if( !Q_stricmp( token, "polygonoffset" ) )
-				si->polygonOffset = qtrue;
-			
-			/* tesssize is used to force liquid surfaces to subdivide */
-			else if( !Q_stricmp( token, "tessSize" ) || !Q_stricmp( token, "q3map_tessSize" ) /* sof2 */ )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				si->subdivisions = atof( token );
-			}
-			
-			/* cull none will set twoSided (ydnar: added disable too) */
-			else if ( !Q_stricmp( token, "cull" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				if( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "disable" ) || !Q_stricmp( token, "twosided" ) )
-					si->twoSided = qtrue;
-			}
-			
-			/* deformVertexes autosprite[ 2 ]
-			   we catch this so autosprited surfaces become point
-			   lights instead of area lights */
-			else if( !Q_stricmp( token, "deformVertexes" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				
-				/* deformVertexes autosprite(2) */
-				if( !Q_strncasecmp( token, "autosprite", 10 ) )
-				{
-					/* set it as autosprite and detail */
-					si->autosprite = qtrue;
-					ApplySurfaceParm( "detail", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
-					
-					/* ydnar: gs mods: added these useful things */
-					si->noClip = qtrue;
-					si->notjunc = qtrue;
-				}
-				
-				/* deformVertexes move <x> <y> <z> <func> <base> <amplitude> <phase> <freq> (ydnar: for particle studio support) */
-				if( !Q_stricmp( token, "move") )
-				{
-					vec3_t	amt, mins, maxs;
-					float	base, amp;
-					
-					
-					/* get move amount */
-					GetTokenAppend( shaderText, qfalse );	amt[ 0 ] = atof( token );
-					GetTokenAppend( shaderText, qfalse );	amt[ 1 ] = atof( token );
-					GetTokenAppend( shaderText, qfalse );	amt[ 2 ] = atof( token );
-					
-					/* skip func */
-					GetTokenAppend( shaderText, qfalse );
-					
-					/* get base and amplitude */
-					GetTokenAppend( shaderText, qfalse );	base = atof( token );
-					GetTokenAppend( shaderText, qfalse );	amp = atof( token );
-					
-					/* calculate */
-					VectorScale( amt, base, mins );
-					VectorMA( mins, amp, amt, maxs );
-					VectorAdd( si->mins, mins, si->mins );
-					VectorAdd( si->maxs, maxs, si->maxs );
-				} 
-			}
-			
-			/* light <value> (old-style flare specification) */
-			else if( !Q_stricmp( token, "light" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				strcpy( si->flareShader, "flareshader" );
-			}
-			
-			/* ydnar: damageShader <shader> <health> (sof2 mods) */
-			else if( !Q_stricmp( token, "damageShader" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				strcpy( si->damageShader, token );
-				GetTokenAppend( shaderText, qfalse );	/* don't do anything with health */
-			}
-
-			/* ydnar: enemy territory implicit shaders */
-			else if( !Q_stricmp( token, "implicitMap" ) )
-			{
-				si->implicitMap = IM_OPAQUE;
-				GetTokenAppend( shaderText, qfalse );
-				if( token[ 0 ] == '-' && token[ 1 ] == '\0' )
-					sprintf( si->implicitImagePath, "%s.tga", si->shader );
-				else
-					strcpy( si->implicitImagePath, token );
-			}
-
-			else if( !Q_stricmp( token, "implicitMask" ) )
-			{
-				si->implicitMap = IM_MASKED;
-				GetTokenAppend( shaderText, qfalse );
-				if( token[ 0 ] == '-' && token[ 1 ] == '\0' )
-					sprintf( si->implicitImagePath, "%s.tga", si->shader );
-				else
-					strcpy( si->implicitImagePath, token );
-			}
-
-			else if( !Q_stricmp( token, "implicitBlend" ) )
-			{
-				si->implicitMap = IM_MASKED;
-				GetTokenAppend( shaderText, qfalse );
-				if( token[ 0 ] == '-' && token[ 1 ] == '\0' )
-					sprintf( si->implicitImagePath, "%s.tga", si->shader );
-				else
-					strcpy( si->implicitImagePath, token );
-			}
-			
-			
-			/* -----------------------------------------------------------------
-			   image directives
-			   ----------------------------------------------------------------- */
-			
-			/* qer_editorimage <image> */
-			else if( !Q_stricmp( token, "qer_editorImage" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				strcpy( si->editorImagePath, token );
-				DefaultExtension( si->editorImagePath, ".tga" );
-			}
-			
-			/* ydnar: q3map_normalimage <image> (bumpmapping normal map) */
-			else if( !Q_stricmp( token, "q3map_normalImage" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				strcpy( si->normalImagePath, token );
-				DefaultExtension( si->normalImagePath, ".tga" );
-			}
-			
-			/* q3map_lightimage <image> */
-			else if( !Q_stricmp( token, "q3map_lightImage" ) )
-			{
-				GetTokenAppend( shaderText, qfalse );
-				strcpy( si->lightImagePath, token );
-				DefaultExtension( si->lightImagePath, ".tga" );
-			}
-			
-			/* ydnar: skyparms <outer image> <cloud height> <inner image> */
-			else if( !Q_stricmp( token, "skyParms" ) )
-			{
-				/* get image base */
-				GetTokenAppend( shaderText, qfalse );
-				
-				/* ignore bogus paths */
-				if( Q_stricmp( token, "-" ) && Q_stricmp( token, "full" ) )
-				{
-					strcpy( si->skyParmsImageBase, token );
-					
-					/* use top image as sky light image */
-					if( si->lightImagePath[ 0 ] == '\0' )
-						sprintf( si->lightImagePath, "%s_up.tga", si->skyParmsImageBase );
-				}
-				
-				/* skip rest of line */
-				GetTokenAppend( shaderText, qfalse );
-				GetTokenAppend( shaderText, qfalse );
-			}
-			
-			/* -----------------------------------------------------------------
-			   q3map_* directives
-			   ----------------------------------------------------------------- */
-			
-			/* q3map_sun <red> <green> <blue> <intensity> <degrees> <elevation>
-			   color will be normalized, so it doesn't matter what range you use
-			   intensity falls off with angle but not distance 100 is a fairly bright sun
-			   degree of 0 = from the east, 90 = north, etc.  altitude of 0 = sunrise/set, 90 = noon
-			   ydnar: sof2map has bareword 'sun' token, so we support that as well */
-			else if( !Q_stricmp( token, "sun" ) /* sof2 */ || !Q_stricmp( token, "q3map_sun" ) || !Q_stricmp( token, "q3map_sunExt" ) )
-			{
-				float		a, b;
-				sun_t		*sun;
-				qboolean	ext;
-				
-				
-				/* ydnar: extended sun directive? */
-				if( !Q_stricmp( token, "q3map_sunext" ) )
-					ext = qtrue;
-				
-				/* allocate sun */
-				sun = safe_malloc( sizeof( *sun ) );
-				memset( sun, 0, sizeof( *sun ) );
-				
-				/* get color */
-				GetTokenAppend( shaderText, qfalse );
-				sun->color[ 0 ] = atof( token );
-				GetTokenAppend( shaderText, qfalse );
-				sun->color[ 1 ] = atof( token );
-				GetTokenAppend( shaderText, qfalse );
-				sun->color[ 2 ] = atof( token );
-				
-				/* normalize it */
-				VectorNormalize( sun->color, sun->color );
-				
-				/* scale color by brightness */
-				GetTokenAppend( shaderText, qfalse );
-				sun->photons = atof( token );
-				
-				/* get sun angle/elevation */
-				GetTokenAppend( shaderText, qfalse );
-				a = atof( token );
-				a = a / 180.0f * Q_PI;
-				
-				GetTokenAppend( shaderText, qfalse );
-				b = atof( token );
-				b = b / 180.0f * Q_PI;
-				
-				sun->direction[ 0 ] = cos( a ) * cos( b );
-				sun->direction[ 1 ] = sin( a ) * cos( b );
-				sun->direction[ 2 ] = sin( b );
-				
-				/* get filter radius from shader */
-				sun->filterRadius = si->lightFilterRadius;
-				
-				/* ydnar: get sun angular deviance/samples */
-				if( ext && TokenAvailable() )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					sun->deviance = atof( token );
-					sun->deviance = sun->deviance / 180.0f * Q_PI;
-					
-					GetTokenAppend( shaderText, qfalse );
-					sun->numSamples = atoi( token );
-				}
-				
-				/* store sun */
-				sun->next = si->sun;
-				si->sun = sun;
-				
-				/* apply sky surfaceparm */
-				ApplySurfaceParm( "sky", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
-				
-				/* don't process any more tokens on this line */
-				continue;
-			}
-
-			/* match q3map_ */
-			else if( !Q_strncasecmp( token, "q3map_", 6 ) )
-			{
-				/* ydnar: q3map_baseShader <shader> (inherit this shader's parameters) */
-				if( !Q_stricmp( token, "q3map_baseShader" ) )
-				{
-					shaderInfo_t	*si2;
-					qboolean		oldWarnImage;
-					
-					
-					/* get shader */
-					GetTokenAppend( shaderText, qfalse );
-					//%	Sys_FPrintf( SYS_VRB, "Shader %s has base shader %s\n", si->shader, token );
-					oldWarnImage = warnImage;
-					warnImage = qfalse;
-					si2 = ShaderInfoForShader( token );
-					warnImage = oldWarnImage;
-					
-					/* subclass it */
-					if( si2 != NULL )
-					{
-						/* preserve name */
-						strcpy( temp, si->shader );
-						
-						/* copy shader */
-						memcpy( si, si2, sizeof( *si ) );
-						
-						/* restore name and set to unfinished */
-						strcpy( si->shader, temp );
-						si->finished = qfalse;
-					}
-				}
-				
-				/* ydnar: q3map_surfacemodel <path to model> <density> <min scale> <max scale> <min angle> <max angle> <oriented (0 or 1)> */
-				else if( !Q_stricmp( token, "q3map_surfacemodel" ) )
-				{
-					surfaceModel_t	*model;
-					
-					
-					/* allocate new model and attach it */
-					model = safe_malloc( sizeof( *model ) );
-					memset( model, 0, sizeof( *model ) );
-					model->next = si->surfaceModel;
-					si->surfaceModel = model;
-						
-					/* get parameters */
-					GetTokenAppend( shaderText, qfalse );
-					strcpy( model->model, token );
-					
-					GetTokenAppend( shaderText, qfalse );
-					model->density = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					model->odds = atof( token );
-					
-					GetTokenAppend( shaderText, qfalse );
-					model->minScale = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					model->maxScale = atof( token );
-					
-					GetTokenAppend( shaderText, qfalse );
-					model->minAngle = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					model->maxAngle = atof( token );
-					
-					GetTokenAppend( shaderText, qfalse );
-					model->oriented = (token[ 0 ] == '1' ? qtrue : qfalse);
-				}
-				
-				/* ydnar/sd: q3map_foliage <path to model> <scale> <density> <odds> <invert alpha (1 or 0)> */
-				else if( !Q_stricmp( token, "q3map_foliage" ) )
-				{
-					foliage_t	*foliage;
-					
-					
-					/* allocate new foliage struct and attach it */
-					foliage = safe_malloc( sizeof( *foliage ) );
-					memset( foliage, 0, sizeof( *foliage ) );
-					foliage->next = si->foliage;
-					si->foliage = foliage;
-					
-					/* get parameters */
-					GetTokenAppend( shaderText, qfalse );
-					strcpy( foliage->model, token );
-					
-					GetTokenAppend( shaderText, qfalse );
-					foliage->scale = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					foliage->density = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					foliage->odds = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					foliage->inverseAlpha = atoi( token );
-				}
-				
-				/* ydnar: q3map_bounce <value> (fraction of light to re-emit during radiosity passes) */
-				else if( !Q_stricmp( token, "q3map_bounce" ) || !Q_stricmp( token, "q3map_bounceScale" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->bounceScale = atof( token );
-				}
-
-				/* ydnar/splashdamage: q3map_skylight <value> <iterations> */
-				else if( !Q_stricmp( token, "q3map_skylight" )  )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->skyLightValue = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->skyLightIterations = atoi( token );
-					
-					/* clamp */
-					if( si->skyLightValue < 0.0f )
-						si->skyLightValue = 0.0f;
-					if( si->skyLightIterations < 2 )
-						si->skyLightIterations = 2;
-				}
-				
-				/* q3map_surfacelight <value> */
-				else if( !Q_stricmp( token, "q3map_surfacelight" )  )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->value = atof( token );
-				}
-				
-				
-				/* q3map_lightStyle (sof2/jk2 lightstyle) */
-				else if( !Q_stricmp( token, "q3map_lightStyle" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					val = atoi( token );
-					if( val < 0 )
-						val = 0;
-					else if( val > LS_NONE )
-						val = LS_NONE;
-					si->lightStyle = val;
-				}
-				
-				/* wolf: q3map_lightRGB <red> <green> <blue> */
-				else if( !Q_stricmp( token, "q3map_lightRGB" ) )
-				{
-					VectorClear( si->color );
-					GetTokenAppend( shaderText, qfalse );
-					si->color[ 0 ] = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->color[ 1 ] = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->color[ 2 ] = atof( token );
-					ColorNormalize( si->color, si->color );
-				}
-				
-				/* q3map_lightSubdivide <value> */
-				else if( !Q_stricmp( token, "q3map_lightSubdivide" )  )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->lightSubdivide = atoi( token );
-				}
-				
-				/* q3map_backsplash <percent> <distance> */
-				else if( !Q_stricmp( token, "q3map_backsplash" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->backsplashFraction = atof( token ) * 0.01f;
-					GetTokenAppend( shaderText, qfalse );
-					si->backsplashDistance = atof( token );
-				}
-				
-				/* q3map_lightmapSampleSize <value> */
-				else if( !Q_stricmp( token, "q3map_lightmapSampleSize" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->lightmapSampleSize = atoi( token );
-				}
-				
-				/* q3map_lightmapSampleSffset <value> */
-				else if( !Q_stricmp( token, "q3map_lightmapSampleOffset" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->lightmapSampleOffset = atof( token );
-				}
-				
-				/* ydnar: q3map_lightmapFilterRadius <self> <other> */
-				else if( !Q_stricmp( token, "q3map_lightmapFilterRadius" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->lmFilterRadius = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->lightFilterRadius = atof( token );
-				}
-				
-				/* ydnar: q3map_lightmapAxis [xyz] */
-				else if( !Q_stricmp( token, "q3map_lightmapAxis" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					if( !Q_stricmp( token, "x" ) )
-						VectorSet( si->lightmapAxis, 1, 0, 0 );
-					else if( !Q_stricmp( token, "y" ) )
-						VectorSet( si->lightmapAxis, 0, 1, 0 );
-					else if( !Q_stricmp( token, "z" ) )
-						VectorSet( si->lightmapAxis, 0, 0, 1 );
-					else
-					{
-						Sys_Printf( "WARNING: Unknown value for lightmap axis: %s\n", token );
-						VectorClear( si->lightmapAxis );
-					}
-				}
-				
-				/* ydnar: q3map_lightmapSize <width> <height> (for autogenerated shaders + external tga lightmaps) */
-				else if( !Q_stricmp( token, "q3map_lightmapSize" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->lmCustomWidth = atoi( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->lmCustomHeight = atoi( token );
-					
-					/* must be a power of 2 */
-					if( ((si->lmCustomWidth - 1) & si->lmCustomWidth) ||
-						((si->lmCustomHeight - 1) & si->lmCustomHeight) )
-					{
-						Sys_Printf( "WARNING: Non power-of-two lightmap size specified (%d, %d)\n",
-							 si->lmCustomWidth, si->lmCustomHeight );
-						si->lmCustomWidth = LIGHTMAP_WIDTH;
-						si->lmCustomHeight = LIGHTMAP_HEIGHT;
-					}
-				}
-
-				/* ydnar: q3map_lightmapGamma N (for autogenerated shaders + external tga lightmaps) */
-				else if( !Q_stricmp( token, "q3map_lightmapGamma" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->lmGamma = atof( token );
-					if( si->lmGamma < 0 )
-						si->lmGamma = 1.0;
-				}
-				
-				/* q3map_vertexScale (scale vertex lighting by this fraction) */
-				else if( !Q_stricmp( token, "q3map_vertexScale" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->vertexScale = atof( token );
-				}
-				
-				/* q3map_flare <shader> */
-				else if( !Q_stricmp( token, "q3map_flare" ) || !Q_stricmp( token, "q3map_flareShader" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					strcpy( si->flareShader, token );
-				}
-				
-				/* q3map_backShader <shader> */
-				else if( !Q_stricmp( token, "q3map_backShader" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					strcpy( si->backShader, token );
-				}
-				
-				/* ydnar: q3map_offset <value> */
-				else if( !Q_stricmp( token, "q3map_offset" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->offset = atof( token );
-				}
-				
-				/* ydnar: q3map_cloneShader <shader> */
-				else if ( !Q_stricmp( token, "q3map_cloneShader" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					strcpy( si->cloneShader, token );
-				}
-				
-				/* ydnar: q3map_textureSize <width> <height> (substitute for q3map_lightimage derivation for terrain) */
-				else if( !Q_stricmp( token, "q3map_fur" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->furNumLayers = atoi( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->furOffset = atof( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->furFade = atof( token );
-				}
-				
-				/* ydnar: gs mods: legacy support for terrain/terrain2 shaders */
-				else if( !Q_stricmp( token, "q3map_terrain" ) )
-				{
-					/* team arena terrain is assumed to be nonplanar, with full normal averaging,
-					   passed through the metatriangle surface pipeline, with a lightmap axis on z */
-					si->legacyTerrain = qtrue;
-					si->noClip = qtrue;
-					si->notjunc = qtrue;
-					si->indexed = qtrue;
-					si->nonplanar = qtrue;
-					si->forceMeta = qtrue;
-					si->shadeAngleDegrees = 179.0f;
-					//%	VectorSet( si->lightmapAxis, 0, 0, 1 );	/* ydnar 2002-09-21: turning this off for better lightmapping of cliff faces */
-				}
-				
-				/* ydnar: picomodel: q3map_forceMeta (forces brush faces and/or triangle models to go through the metasurface pipeline) */
-				else if( !Q_stricmp( token, "q3map_forceMeta" ) )
-				{
-					si->forceMeta = qtrue;
-				}
-				
-				/* ydnar: gs mods: q3map_shadeAngle <degrees> */
-				else if( !Q_stricmp( token, "q3map_shadeAngle" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->shadeAngleDegrees = atof( token );
-				}
-				
-				/* ydnar: q3map_textureSize <width> <height> (substitute for q3map_lightimage derivation for terrain) */
-				else if( !Q_stricmp( token, "q3map_textureSize" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					si->shaderWidth = atoi( token );
-					GetTokenAppend( shaderText, qfalse );
-					si->shaderHeight = atoi( token );
-				}
-				
-				/* ydnar: gs mods: q3map_tcGen <style> <parameters> */
-				else if( !Q_stricmp( token, "q3map_tcGen" ) )
-				{
-					si->tcGen = qtrue;
-					GetTokenAppend( shaderText, qfalse );
-					
-					/* q3map_tcGen vector <s vector> <t vector> */
-					if( !Q_stricmp( token, "vector" ) )
-					{
-						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ] );
-						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ] );
-					}
-					
-					/* q3map_tcGen ivector <1.0/s vector> <1.0/t vector> (inverse vector, easier for mappers to understand) */
-					else if( !Q_stricmp( token, "ivector" ) )
-					{
-						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ] );
-						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ] );
-						for( i = 0; i < 3; i++ )
-						{
-							si->vecs[ 0 ][ i ] = si->vecs[ 0 ][ i ] ? 1.0 / si->vecs[ 0 ][ i ] : 0;
-							si->vecs[ 1 ][ i ] = si->vecs[ 1 ][ i ] ? 1.0 / si->vecs[ 1 ][ i ] : 0;
-						}
-					}
-					else
-					{
-						Sys_Printf( "WARNING: Unknown q3map_tcGen method: %s\n", token );
-						VectorClear( si->vecs[ 0 ] );
-						VectorClear( si->vecs[ 1 ] );
-					}
-				}
-				
-				/* ydnar: gs mods: q3map_alphaMod <style> <parameters> */
-				else if( !Q_stricmp( token, "q3map_alphaMod" ) )
-				{
-					alphaMod_t	*am, *am2;
-					
-					
-					/* allocate new alpha mod */
-					am = safe_malloc( sizeof( *am ) );
-					memset( am, 0, sizeof( *am ) );
-					
-					/* attach to shader */
-					if( si->alphaMod == NULL )
-						si->alphaMod = am;
-					else
-					{
-						for( am2 = si->alphaMod; am2 != NULL; am2 = am2->next )
-						{
-							if( am2->next == NULL )
-							{
-								am2->next = am;
-								break;
-							}
-						}
-					}
-					
-					/* get type */
-					GetTokenAppend( shaderText, qfalse );
-					
-					/* q3map_alphaMod dotproduct ( X Y Z ) */
-					if( !Q_stricmp( token, "dotproduct" ) )
-					{
-						am->type = AM_DOT_PRODUCT;
-						Parse1DMatrixAppend( shaderText, 3, am->data );
-					}
-					else
-						Sys_Printf( "WARNING: Unknown q3map_alphaMod method: %s\n", token );
-				}
-				
-				/* ydnar: gs mods: q3map_tcMod <style> <parameters> */
-				else if( !Q_stricmp( token, "q3map_tcMod" ) )
-				{
-					float	a, b;
-					
-					
-					GetTokenAppend( shaderText, qfalse );
-					
-					/* q3map_tcMod [translate | shift | offset] <s> <t> */
-					if( !Q_stricmp( token, "translate" ) || !Q_stricmp( token, "shift" ) || !Q_stricmp( token, "offset" ) )
-					{
-						GetTokenAppend( shaderText, qfalse );
-						a = atof( token );
-						GetTokenAppend( shaderText, qfalse );
-						b = atof( token );
-						
-						TcModTranslate( si->mod, a, b );
-					}
-
-					/* q3map_tcMod scale <s> <t> */
-					else if( !Q_stricmp( token, "scale" ) )
-					{
-						GetTokenAppend( shaderText, qfalse );
-						a = atof( token );
-						GetTokenAppend( shaderText, qfalse );
-						b = atof( token );
-						
-						TcModScale( si->mod, a, b );
-					}
-					
-					/* q3map_tcMod rotate <s> <t> (fixme: make this communitive) */
-					else if( !Q_stricmp( token, "rotate" ) )
-					{
-						GetTokenAppend( shaderText, qfalse );
-						a = atof( token );
-						TcModRotate( si->mod, a );
-					}
-					else
-						Sys_Printf( "WARNING: Unknown q3map_tcMod method: %s\n", token );
-				}
-				
-				/* q3map_fogDir (direction a fog shader fades from transparent to opaque) */
-				else if( !Q_stricmp( token, "q3map_fogDir" ) )
-				{
-					Parse1DMatrixAppend( shaderText, 3, si->fogDir );
-					VectorNormalize( si->fogDir, si->fogDir );
-				}
-				
-				/* q3map_globaltexture */
-				else if( !Q_stricmp( token, "q3map_globaltexture" )  )
-					si->globalTexture = qtrue;
-				
-				/* ydnar: gs mods: q3map_nonplanar (make it a nonplanar merge candidate for meta surfaces) */
-				else if( !Q_stricmp( token, "q3map_nonplanar" ) )
-					si->nonplanar = qtrue;
-				
-				/* ydnar: gs mods: q3map_noclip (preserve original face winding, don't clip by bsp tree) */
-				else if( !Q_stricmp( token, "q3map_noclip" ) )
-					si->noClip = qtrue;
-				
-				/* q3map_notjunc */
-				else if( !Q_stricmp( token, "q3map_notjunc" ) )
-					si->notjunc = qtrue;
-				
-				/* q3map_nofog */
-				else if( !Q_stricmp( token, "q3map_nofog" ) )
-					si->noFog = qtrue;
-				
-				/* ydnar: gs mods: q3map_indexed (for explicit terrain-style indexed mapping) */
-				else if( !Q_stricmp( token, "q3map_indexed" ) )
-					si->indexed = qtrue;
-				
-				/* ydnar: q3map_invert (inverts a drawsurface's facing) */
-				else if( !Q_stricmp( token, "q3map_invert" ) )
-					si->invert = qtrue;
-				
-				/* ydnar: gs mods: q3map_lightmapMergable (ok to merge non-planar */
-				else if( !Q_stricmp( token, "q3map_lightmapMergable" ) )
-					si->lmMergable = qtrue;
-				
-				/* ydnar: q3map_nofast */
-				else if( !Q_stricmp( token, "q3map_noFast" ) )
-					si->noFast = qtrue;
-				
-				/* q3map_patchshadows */
-				else if( !Q_stricmp( token, "q3map_patchShadows" ) )
-					si->patchShadows = qtrue;
-				
-				/* q3map_vertexshadows */
-				else if( !Q_stricmp( token, "q3map_vertexShadows" ) )
-					si->vertexShadows = qtrue;	/* ydnar */
-				
-				/* q3map_novertexshadows */
-				else if( !Q_stricmp( token, "q3map_noVertexShadows" ) )
-					si->vertexShadows = qfalse;	/* ydnar */
-				
-				/* q3map_splotchfix (filter dark lightmap luxels on lightmapped models) */
-				else if( !Q_stricmp( token, "q3map_splotchfix" ) )
-					si->splotchFix = qtrue;	/* ydnar */
-				
-				/* q3map_forcesunlight */
-				else if( !Q_stricmp( token, "q3map_forceSunlight" ) )
-					si->forceSunlight = qtrue;
-				
-				/* q3map_onlyvertexlighting (sof2) */
-				else if( !Q_stricmp( token, "q3map_onlyVertexLighting" ) )
-					ApplySurfaceParm( "pointlight", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
-				
-				/* q3map_material (sof2) */
-				else if( !Q_stricmp( token, "q3map_material" ) )
-				{
-					GetTokenAppend( shaderText, qfalse );
-					sprintf( temp, "*mat_%s", token );
-					if( ApplySurfaceParm( temp, &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
-						Sys_Printf( "WARNING: Unknown material \"%s\"\n", token );
-				}
-				
-				/* ydnar: q3map_clipmodel (autogenerate clip brushes for model triangles using this shader) */
-				else if( !Q_stricmp( token, "q3map_clipmodel" )  )
-					si->clipModel = qtrue;
-				
-				/* ydnar: q3map_styleMarker[2] */
-				else if( !Q_stricmp( token, "q3map_styleMarker" ) )
-					si->styleMarker = 1;
-				else if( !Q_stricmp( token, "q3map_styleMarker2" ) )	/* uses depthFunc equal */
-					si->styleMarker = 2;
-				
-				/* ydnar: default to searching for q3map_<surfaceparm> */
-				else
-				{
-					//%	Sys_FPrintf( SYS_VRB, "Attempting to match %s with a known surfaceparm\n", token );
-					if( ApplySurfaceParm( &token[ 6 ], &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
-						;//%	Sys_Printf( "WARNING: Unknown q3map_* directive \"%s\"\n", token );
-				}
-			}
-			
-			
-			/* -----------------------------------------------------------------
-			   skip
-			   ----------------------------------------------------------------- */
-			
-			/* ignore all other tokens on the line */
-			while( TokenAvailable() && GetTokenAppend( shaderText, qfalse ) );
-		}			
-	}
-}
-
-
-
-/*
-ParseCustomInfoParms() - rr2do2
-loads custom info parms file for mods
-*/
-
-static void ParseCustomInfoParms( void )
-{
-	qboolean parsedContent, parsedSurface;
-	
-	
-	/* file exists? */
-	if( vfsGetFileCount( "scripts/custinfoparms.txt" ) == 0 )
-		return;
-	
-	/* load it */
-	LoadScriptFile( "scripts/custinfoparms.txt", 0 );
-	
-	/* clear the array */
-	memset( custSurfaceParms, 0, sizeof( custSurfaceParms ) );
-	numCustSurfaceParms = 0;
-	parsedContent = parsedSurface = qfalse;
-	
-	/* parse custom contentflags */
-	MatchToken( "{" );
-	while ( 1 )
-	{
-		if ( !GetToken( qtrue ) )
-			break;
-
-		if ( !strcmp( token, "}" ) ) {
-			parsedContent = qtrue;
-			break;
-		}
-
-		custSurfaceParms[ numCustSurfaceParms ].name = safe_malloc( MAX_OS_PATH );
-		strcpy( custSurfaceParms[ numCustSurfaceParms ].name, token );
-		GetToken( qfalse );
-		sscanf( token, "%x", &custSurfaceParms[ numCustSurfaceParms ].contentFlags );
-		numCustSurfaceParms++;
-	}
-	
-	/* any content? */
-	if( !parsedContent )
-	{
-		Sys_Printf( "WARNING: Couldn't find valid custom contentsflag section\n" );
-		return;
-	}
-	
-	/* parse custom surfaceflags */
-	MatchToken( "{" );
-	while( 1 )
-	{
-		if( !GetToken( qtrue ) )
-			break;
-
-		if( !strcmp( token, "}" ) )
-		{
-			parsedSurface = qtrue;
-			break;
-		}
-
-		custSurfaceParms[ numCustSurfaceParms ].name = safe_malloc( MAX_OS_PATH );
-		strcpy( custSurfaceParms[ numCustSurfaceParms ].name, token );
-		GetToken( qfalse );
-		sscanf( token, "%x", &custSurfaceParms[ numCustSurfaceParms ].surfaceFlags );
-		numCustSurfaceParms++;
-	}
-	
-	/* any content? */
-	if( !parsedContent )
-		Sys_Printf( "WARNING: Couldn't find valid custom surfaceflag section\n" );
-}
-
-	
-
-/*
-LoadShaderInfo()
-the shaders are parsed out of shaderlist.txt from a main directory
-that is, if using -fs_game we ignore the shader scripts that might be in baseq3/
-on linux there's an additional twist, we actually merge the stuff from ~/.q3a/ and from the base dir
-*/
-
-#define	MAX_SHADER_FILES	1024
-
-void LoadShaderInfo( void )
-{
-	int				i, j, numShaderFiles, count;
-	char			filename[ 1024 ];
-	char			*shaderFiles[ MAX_SHADER_FILES ];
-	
-	
-	/* rr2do2: parse custom infoparms first */
-	if( useCustomInfoParms )
-		ParseCustomInfoParms();
-	
-	/* start with zero */
-	numShaderFiles = 0;
-	
-	/* we can pile up several shader files, the one in baseq3 and ones in the mod dir or other spots */
-	sprintf( filename, "%s/shaderlist.txt", game->shaderPath );
-	count = vfsGetFileCount( filename );
-	
-	/* load them all */
-	for( i = 0; i < count; i++ )
-	{
-		/* load shader list */
-		sprintf( filename, "%s/shaderlist.txt", game->shaderPath );
-		LoadScriptFile( filename, i );
-		
-		/* parse it */
-		while( GetToken( qtrue ) )
-		{
-			/* check for duplicate entries */
-			for( j = 0; j < numShaderFiles; j++ )
-				if( !strcmp( shaderFiles[ j ], token ) )
-					break;
-			
-			/* test limit */
-			if( j >= MAX_SHADER_FILES )
-				Error( "MAX_SHADER_FILES (%d) reached, trim your shaderlist.txt!", (int) MAX_SHADER_FILES );
-			
-			/* new shader file */
-			if( j == numShaderFiles )
-			{
-				shaderFiles[ numShaderFiles ] = safe_malloc( MAX_OS_PATH );
-				strcpy( shaderFiles[ numShaderFiles ], token );
-				numShaderFiles++;
-			}
-		}
-	}
-	
-	/* parse the shader files */
-	for( i = 0; i < numShaderFiles; i++ )
-	{
-		sprintf( filename, "%s/%s.shader", game->shaderPath, shaderFiles[ i ] );
-		ParseShaderFile( filename );
-		free( shaderFiles[ i ] );
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d shaderInfo\n", numShaderInfo );
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define SHADERS_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+AlphaMod()
+routines for dealing with vertex alpha modification
+*/
+
+void AlphaMod( alphaMod_t *am, int numVerts, bspDrawVert_t *drawVerts )
+{
+	int				i, j;
+	float			mult, add, a;
+	bspDrawVert_t	*dv;
+	alphaMod_t		*am2;
+	
+	
+	/* dummy check */
+	if( am == NULL || numVerts < 1 || drawVerts == NULL )
+		return;
+	
+	
+	/* walk vertex list */
+	for( i = 0; i < numVerts; i++ )
+	{
+		/* get vertex */
+		dv = &drawVerts[ i ];
+		
+		/* walk alphamod list */
+		for( am2 = am; am2 != NULL; am2 = am2->next )
+		{
+			/* switch on type */
+			switch( am->type )
+			{
+				case AM_DOT_PRODUCT:
+					mult = DotProduct( dv->normal, am2->data );
+					add = 0.0f;
+					break;
+				
+				default:
+					mult = 1.0f;
+					add = 0.0f;
+					break;
+			}
+			
+			/* apply mod */
+			for( j = 0; j < MAX_LIGHTMAPS; j++ )
+			{
+				a = (mult * dv->color[ j ][ 3 ]) + add;
+				if( a < 0 )
+					a = 0;
+				else if( a > 255 )
+					a = 255;
+				dv->color[ j ][ 3 ] = a;
+			}
+		}
+	}
+}
+
+
+
+/*
+TcMod*()
+routines for dealing with a 3x3 texture mod matrix
+*/
+
+void TcMod( tcMod_t mod, float st[ 2 ] )
+{
+	float	old[ 2 ];
+	
+	
+	old[ 0 ] = st[ 0 ];
+	old[ 1 ] = st[ 1 ];
+	st[ 0 ] = (mod[ 0 ][ 0 ] * old[ 0 ]) + (mod[ 0 ][ 1 ] * old[ 1 ]) + mod[ 0 ][ 2 ];
+	st[ 1 ] = (mod[ 1 ][ 0 ] * old[ 0 ]) + (mod[ 1 ][ 1 ] * old[ 1 ]) + mod[ 1 ][ 2 ];
+}
+
+
+void TcModIdentity( tcMod_t mod )
+{
+	mod[ 0 ][ 0 ] = 1.0f;	mod[ 0 ][ 1 ] = 0.0f;	mod[ 0 ][ 2 ] = 0.0f;
+	mod[ 1 ][ 0 ] = 0.0f;	mod[ 1 ][ 1 ] = 1.0f;	mod[ 1 ][ 2 ] = 0.0f;
+	mod[ 2 ][ 0 ] = 0.0f;	mod[ 2 ][ 1 ] = 0.0f;	mod[ 2 ][ 2 ] = 1.0f;	/* this row is only used for multiples, not transformation */
+}
+
+
+void TcModMultiply( tcMod_t a, tcMod_t b, tcMod_t out )
+{
+	int		i;
+	
+	
+	for( i = 0; i < 3; i++ )
+	{
+		out[ i ][ 0 ] = (a[ i ][ 0 ] * b[ 0 ][ 0 ]) + (a[ i ][ 1 ] * b[ 1 ][ 0 ]) + (a[ i ][ 2 ] * b[ 2 ][ 0 ]);
+		out[ i ][ 1 ] = (a[ i ][ 0 ] * b[ 0 ][ 1 ]) + (a[ i ][ 1 ] * b[ 1 ][ 1 ]) + (a[ i ][ 2 ] * b[ 2 ][ 1 ]);
+		out[ i ][ 2 ] = (a[ i ][ 0 ] * b[ 0 ][ 2 ]) + (a[ i ][ 1 ] * b[ 1 ][ 2 ]) + (a[ i ][ 2 ] * b[ 2 ][ 2 ]);
+	}
+}
+
+
+void TcModTranslate( tcMod_t mod, float s, float t )
+{
+	mod[ 0 ][ 2 ] += s;
+	mod[ 1 ][ 2 ] += t;
+}
+
+
+void TcModScale( tcMod_t mod, float s, float t )
+{
+	mod[ 0 ][ 0 ] *= s;
+	mod[ 1 ][ 1 ] *= t;
+}
+
+
+void TcModRotate( tcMod_t mod, float euler )
+{
+	tcMod_t	old, temp;
+	float	radians, sinv, cosv;
+	
+	
+	memcpy( old, mod, sizeof( tcMod_t ) );
+	TcModIdentity( temp );
+
+	radians = euler / 180 * Q_PI;
+	sinv = sin( radians );
+	cosv = cos( radians );
+
+	temp[ 0 ][ 0 ] = cosv;	temp[ 0 ][ 1 ] = -sinv;
+	temp[ 1 ][ 0 ] = sinv;	temp[ 1 ][ 1 ] = cosv;
+	
+	TcModMultiply( old, temp, mod );
+}
+
+
+
+/*
+ApplySurfaceParm() - ydnar
+applies a named surfaceparm to the supplied flags
+*/
+
+qboolean ApplySurfaceParm( char *name, int *contentFlags, int *surfaceFlags, int *compileFlags )
+{
+	int				i, fake;
+	surfaceParm_t	*sp;
+	
+	
+	/* dummy check */
+	if( name == NULL )
+		name = "";
+	if( contentFlags == NULL )
+		contentFlags = &fake;
+	if( surfaceFlags == NULL )
+		surfaceFlags = &fake;
+	if( compileFlags == NULL )
+		compileFlags = &fake;
+	
+	/* walk the current game's surfaceparms */
+	sp = game->surfaceParms;
+	while( sp->name != NULL )
+	{
+		/* match? */
+		if( !Q_stricmp( name, sp->name ) )
+		{
+			/* clear and set flags */
+			*contentFlags &= ~(sp->contentFlagsClear);
+			*contentFlags |= sp->contentFlags;
+			*surfaceFlags &= ~(sp->surfaceFlagsClear);
+			*surfaceFlags |= sp->surfaceFlags;
+			*compileFlags &= ~(sp->compileFlagsClear);
+			*compileFlags |= sp->compileFlags;
+			
+			/* return ok */
+			return qtrue;
+		}
+		
+		/* next */
+		sp++;
+	}
+	
+	/* check custom info parms */
+	for( i = 0; i < numCustSurfaceParms; i++ )
+	{
+		/* get surfaceparm */
+		sp = &custSurfaceParms[ i ];
+		
+		/* match? */
+		if( !Q_stricmp( name, sp->name ) )
+		{
+			/* clear and set flags */
+			*contentFlags &= ~(sp->contentFlagsClear);
+			*contentFlags |= sp->contentFlags;
+			*surfaceFlags &= ~(sp->surfaceFlagsClear);
+			*surfaceFlags |= sp->surfaceFlags;
+			*compileFlags &= ~(sp->compileFlagsClear);
+			*compileFlags |= sp->compileFlags;
+			
+			/* return ok */
+			return qtrue;
+		}
+	}
+	
+	/* no matching surfaceparm found */
+	return qfalse;
+}
+
+
+
+/*
+BeginMapShaderFile() - ydnar
+erases and starts a new map shader script
+*/
+
+void BeginMapShaderFile( const char *mapFile )
+{
+	char	base[ 1024 ];
+	int		len;
+	
+
+	/* dummy check */
+	mapName[ 0 ] = '\0';
+	mapShaderFile[ 0 ] = '\0';
+	if( mapFile == NULL || mapFile[ 0 ] == '\0' )
+		return;
+	
+	/* copy map name */
+	strcpy( base, mapFile );
+	StripExtension( base );
+	
+	/* extract map name */
+	len = strlen( base ) - 1;
+	while( len > 0 && base[ len ] != '/' && base[ len ] != '\\' )
+		len--;
+	strcpy( mapName, &base[ len + 1 ] );
+	base[ len ] = '\0';
+	if( len <= 0 )
+		return;
+	
+	/* append ../scripts/q3map2_<mapname>.shader */
+	sprintf( mapShaderFile, "%s/../%s/q3map2_%s.shader", base, game->shaderPath, mapName );
+	Sys_FPrintf( SYS_VRB, "Map has shader script %s\n", mapShaderFile );
+	
+	/* remove it */
+	remove( mapShaderFile );
+	
+	/* stop making warnings about missing images */
+	warnImage = qfalse;
+}
+
+
+
+/*
+WriteMapShaderFile() - ydnar
+writes a shader to the map shader script
+*/
+
+void WriteMapShaderFile( void )
+{
+	FILE			*file;
+	shaderInfo_t	*si;
+	int				i, num;
+	
+	
+	/* dummy check */
+	if( mapShaderFile[ 0 ] == '\0' )
+		return;
+	
+	/* are there any custom shaders? */
+	for( i = 0, num = 0; i < numShaderInfo; i++ )
+	{
+		if( shaderInfo[ i ].custom ) 
+			break;
+	}
+	if( i == numShaderInfo )
+		return;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- WriteMapShaderFile ---\n");
+	Sys_FPrintf( SYS_VRB, "Writing %s", mapShaderFile );
+	
+	/* open shader file */
+	file = fopen( mapShaderFile, "w" );
+	if( file == NULL )
+	{
+		Sys_Printf( "WARNING: Unable to open map shader file %s for writing\n", mapShaderFile );
+		return;
+	}
+	
+	/* print header */
+	fprintf( file,
+		"// Custom shader file for %s.bsp\n"
+		"// Generated by Q3Map2 (ydnar)\n"
+		"// Do not edit! This file is overwritten on recompiles.\n\n",
+		mapName );
+	
+	/* walk the shader list */
+	for( i = 0, num = 0; i < numShaderInfo; i++ )
+	{
+		/* get the shader and print it */
+		si = &shaderInfo[ i ];
+		if( si->custom == qfalse || si->shaderText == NULL || si->shaderText[ 0 ] == '\0' )
+			continue;
+		num++;
+
+		/* print it to the file */
+		fprintf( file, "%s%s\n", si->shader, si->shaderText );
+		//%	Sys_Printf( "%s%s\n", si->shader, si->shaderText ); /* FIXME: remove debugging code */
+		
+		Sys_FPrintf( SYS_VRB, "." );
+	}
+	
+	/* close the shader */
+	fclose( file );
+	
+	Sys_FPrintf( SYS_VRB, "\n" );
+	
+	/* print some stats */
+	Sys_Printf( "%9d custom shaders emitted\n", num );
+}
+
+
+
+/*
+CustomShader() - ydnar
+sets up a custom map shader
+*/
+
+shaderInfo_t *CustomShader( shaderInfo_t *si, char *find, char *replace )
+{
+	shaderInfo_t	*csi;
+	char			shader[ MAX_QPATH ];
+	char			*s;
+	int				loc;
+	md5_state_t		md5;
+	byte			digest[ 16 ];
+	char			*srcShaderText, temp[ 8192 ], shaderText[ 8192 ];	/* ydnar: fixme (make this bigger?) */
+	
+	
+	/* dummy check */
+	if( si == NULL )
+		return ShaderInfoForShader( "default" );
+	
+	/* default shader text source */
+	srcShaderText = si->shaderText;
+	
+	/* et: implicitMap */
+	if( si->implicitMap == IM_OPAQUE )
+	{
+		srcShaderText = temp;
+		sprintf( temp, "\n"
+			"{ // Q3Map2 defaulted (implicitMap)\n"
+			"\t{\n"
+			"\t\tmap $lightmap\n"
+			"\t\trgbGen identity\n"
+			"\t}\n"
+			"\tq3map_styleMarker\n"
+			"\t{\n"
+			"\t\tmap %s\n"
+			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
+			"\t\trgbGen identity\n"
+			"\t}\n"
+			"}\n",
+			si->implicitImagePath );
+	}
+	
+	/* et: implicitMask */
+	else if( si->implicitMap == IM_MASKED )
+	{
+		srcShaderText = temp;
+		sprintf( temp, "\n"
+			"{ // Q3Map2 defaulted (implicitMask)\n"
+			"\tcull none\n"
+			"\t{\n"
+			"\t\tmap %s\n"
+			"\t\talphaFunc GE128\n"
+			"\t\tdepthWrite\n"
+			"\t}\n"
+			"\t{\n"
+			"\t\tmap $lightmap\n"
+			"\t\trgbGen identity\n"
+			"\t\tdepthFunc equal\n"
+			"\t}\n"
+			"\tq3map_styleMarker\n"
+			"\t{\n"
+			"\t\tmap %s\n"
+			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
+			"\t\tdepthFunc equal\n"
+			"\t\trgbGen identity\n"
+			"\t}\n"
+			"}\n",
+			si->implicitImagePath,
+			si->implicitImagePath );
+	}
+	
+	/* et: implicitBlend */
+	else if( si->implicitMap == IM_BLEND )
+	{
+		srcShaderText = temp;
+		sprintf( temp, "\n"
+			"{ // Q3Map2 defaulted (implicitBlend)\n"
+			"\tcull none\n"
+			"\t{\n"
+			"\t\tmap %s\n"
+			"\t\tblendFunc GL_SRC_ALPHA GL_ONE_MINUS_SRC_ALPHA\n"
+			"\t}\n"
+			"\t{\n"
+			"\t\tmap $lightmap\n"
+			"\t\trgbGen identity\n"
+			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
+			"\t}\n"
+			"\tq3map_styleMarker\n"
+			"}\n",
+			si->implicitImagePath );
+	}
+	
+	/* default shader text */
+	else if( srcShaderText == NULL )
+	{
+		srcShaderText = temp;
+		sprintf( temp, "\n"
+			"{ // Q3Map2 defaulted\n"
+			"\t{\n"
+			"\t\tmap $lightmap\n"
+			"\t\trgbGen identity\n"
+			"\t}\n"
+			"\tq3map_styleMarker\n"
+			"\t{\n"
+			"\t\tmap %s.tga\n"
+			"\t\tblendFunc GL_DST_COLOR GL_ZERO\n"
+			"\t\trgbGen identity\n"
+			"\t}\n"
+			"}\n",
+			si->shader );
+	}
+	
+	/* error check */
+	if( (strlen( mapName ) + 1 + 32) > MAX_QPATH )
+		Error( "Custom shader name length (%d) exceeded. Shorten your map name.\n", MAX_QPATH );
+	
+	/* do some bad find-replace */
+	s = strstr( srcShaderText, find );
+	if( s == NULL )
+		//%	strcpy( shaderText, srcShaderText );
+		return si;	/* testing just using the existing shader if this fails */
+	else
+	{
+		/* substitute 'find' with 'replace' */
+		loc = s - srcShaderText;
+		strcpy( shaderText, srcShaderText );
+		shaderText[ loc ] = '\0';
+		strcat( shaderText, replace );
+		strcat( shaderText, &srcShaderText[ loc + strlen( find ) ] );
+	}
+	
+	/* make md5 hash of the shader text */
+	md5_init( &md5 );
+	md5_append( &md5, shaderText, strlen( shaderText ) );
+	md5_finish( &md5, digest );
+	
+	/* mangle hash into a shader name */
+	sprintf( shader, "%s/%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X", mapName,
+		digest[ 0 ], digest[ 1 ], digest[ 2 ], digest[ 3 ], digest[ 4 ], digest[ 5 ], digest[ 6 ], digest[ 7 ], 
+		digest[ 8 ], digest[ 9 ], digest[ 10 ], digest[ 11 ], digest[ 12 ], digest[ 13 ], digest[ 14 ], digest[ 15 ] );
+	
+	/* get shader */
+	csi = ShaderInfoForShader( shader );
+	
+	/* might be a preexisting shader */
+	if( csi->custom )
+		return csi;
+	
+	/* clone the existing shader and rename */
+	memcpy( csi, si, sizeof( shaderInfo_t ) );
+	strcpy( csi->shader, shader );
+	csi->custom = qtrue;
+	
+	/* store new shader text */
+	csi->shaderText = safe_malloc( strlen( shaderText ) + 1 );
+	strcpy( csi->shaderText, shaderText );	/* LEAK! */
+	
+	/* return it */
+	return csi;
+}
+
+
+
+/*
+EmitVertexRemapShader()
+adds a vertexremapshader key/value pair to worldspawn
+*/
+
+void EmitVertexRemapShader( char *from, char *to )
+{
+	md5_state_t		md5;
+	byte			digest[ 16 ];
+	char			key[ 64 ], value[ 256 ];
+	
+	
+	/* dummy check */
+	if( from == NULL || from[ 0 ] == '\0' ||
+		to == NULL || to[ 0 ] == '\0' )
+		return;
+	
+	/* build value */
+	sprintf( value, "%s;%s", from, to );
+	
+	/* make md5 hash */
+	md5_init( &md5 );
+	md5_append( &md5, value, strlen( value ) );
+	md5_finish( &md5, digest );
+
+	/* make key (this is annoying, as vertexremapshader is precisely 17 characters,
+	   which is one too long, so we leave off the last byte of the md5 digest) */
+	sprintf( key, "vertexremapshader%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X%02X",
+		digest[ 0 ], digest[ 1 ], digest[ 2 ], digest[ 3 ], digest[ 4 ], digest[ 5 ], digest[ 6 ], digest[ 7 ], 
+		digest[ 8 ], digest[ 9 ], digest[ 10 ], digest[ 11 ], digest[ 12 ], digest[ 13 ], digest[ 14 ] );	/* no: digest[ 15 ] */
+	
+	/* add key/value pair to worldspawn */
+	SetKeyValue( &entities[ 0 ], key, value );
+}
+
+
+
+/*
+AllocShaderInfo()
+allocates and initializes a new shader
+*/
+
+static shaderInfo_t	*AllocShaderInfo( void )
+{
+	shaderInfo_t	*si;
+	
+	
+	/* allocate? */
+	if( shaderInfo == NULL )
+	{
+		shaderInfo = safe_malloc( sizeof( shaderInfo_t ) * MAX_SHADER_INFO );
+		numShaderInfo = 0;
+	}
+	
+	/* bounds check */
+	if( numShaderInfo == MAX_SHADER_INFO )
+		Error( "MAX_SHADER_INFO exceeded. Remove some PK3 files or shader scripts from shaderlist.txt and try again." );
+	si = &shaderInfo[ numShaderInfo ];
+	numShaderInfo++;
+	
+	/* ydnar: clear to 0 first */
+	memset( si, 0, sizeof( shaderInfo_t ) );
+	
+	/* set defaults */
+	ApplySurfaceParm( "default", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
+	
+	si->backsplashFraction = DEF_BACKSPLASH_FRACTION;
+	si->backsplashDistance = DEF_BACKSPLASH_DISTANCE;
+	
+	si->bounceScale = DEF_RADIOSITY_BOUNCE;
+	
+	si->lightStyle = LS_NORMAL;
+	
+	si->polygonOffset = qfalse;
+	
+	si->shadeAngleDegrees = 0.0f;
+	si->lightmapSampleSize = 0;
+	si->lightmapSampleOffset = DEFAULT_LIGHTMAP_SAMPLE_OFFSET;
+	si->patchShadows = qfalse;
+	si->vertexShadows = qtrue;	/* ydnar: changed default behavior */
+	si->forceSunlight = qfalse;
+	si->vertexScale = 1.0;
+	si->notjunc = qfalse;
+	
+	/* ydnar: set texture coordinate transform matrix to identity */
+	TcModIdentity( si->mod );
+	
+	/* ydnar: lightmaps can now be > 128x128 in an externally generated tga */
+	si->lmCustomWidth = lmCustomSize;	//%	LIGHTMAP_WIDTH;
+	si->lmCustomHeight = lmCustomSize;	//%	LIGHTMAP_HEIGHT;
+	
+	/* return to sender */
+	return si;
+}
+
+
+
+/*
+FinishShader() - ydnar
+sets a shader's width and height among other things
+*/
+
+void FinishShader( shaderInfo_t *si )
+{
+	int		x, y;
+	float	st[ 2 ], o[ 2 ], dist, bestDist;
+	vec4_t	color, bestColor, delta;
+	
+
+	/* don't double-dip */
+	if( si->finished )
+		return;
+	
+	/* if they're explicitly set, copy from image size */
+	if( si->shaderWidth == 0 && si->shaderHeight == 0 )
+	{
+		si->shaderWidth = si->shaderImage->width;
+		si->shaderHeight = si->shaderImage->height;
+	}
+	
+	/* legacy terrain has explicit image-sized texture projection */
+	if( si->legacyTerrain && si->tcGen == qfalse )
+	{
+		/* set xy texture projection */
+		si->tcGen = qtrue;
+		VectorSet( si->vecs[ 0 ], (1.0f / (si->shaderWidth * 0.5f)), 0, 0 );
+		VectorSet( si->vecs[ 1 ], 0, (1.0f / (si->shaderHeight * 0.5f)), 0 );
+	}
+	
+	/* find pixel coordinates best matching the average color of the image */
+	bestDist = 99999999;
+	o[ 0 ] = 1.0f / si->shaderImage->width;
+	o[ 1 ] = 1.0f / si->shaderImage->height;
+	for( y = 0, st[ 1 ] = 0.0f; y < si->shaderImage->height; y++, st[ 1 ] += o[ 1 ] )
+	{
+		for( x = 0, st[ 0 ] = 0.0f; x < si->shaderImage->width; x++, st[ 0 ] += o[ 0 ] )
+		{
+			/* sample the shader image */
+			RadSampleImage( si->shaderImage->pixels, si->shaderImage->width, si->shaderImage->height, st, color );
+			
+			/* determine error squared */
+			VectorSubtract( color, si->averageColor, delta );
+			delta[ 3 ] = color[ 3 ] - si->averageColor[ 3 ];
+			dist = delta[ 0 ] * delta[ 0 ] + delta[ 1 ] * delta[ 1 ] + delta[ 2 ] * delta[ 2 ] + delta[ 3 ] * delta[ 3 ];
+			if( dist < bestDist )
+			{
+				VectorCopy( color, bestColor );
+				bestColor[ 3 ] = color[ 3 ];
+				si->stFlat[ 0 ] = st[ 0 ];
+				si->stFlat[ 1 ] = st[ 1 ];
+			}
+		}
+	}
+	
+	/* set to finished */
+	si->finished = qtrue;
+}
+
+
+
+/*
+LoadShaderImages()
+loads a shader's images
+ydnar: image.c made this a bit simpler
+*/
+
+static void LoadShaderImages( shaderInfo_t *si )
+{
+	int			i, count;
+	float		color[ 4 ];
+	
+	
+	/* nodraw shaders don't need images */
+	if( si->compileFlags & C_NODRAW )
+		si->shaderImage = ImageLoad( DEFAULT_IMAGE );
+	else
+	{
+		/* try to load editor image first */
+		si->shaderImage = ImageLoad( si->editorImagePath );
+		
+		/* then try shadername */
+		if( si->shaderImage == NULL )
+			si->shaderImage = ImageLoad( si->shader );
+		
+		/* then try implicit image path (note: new behavior!) */
+		if( si->shaderImage == NULL )
+			si->shaderImage = ImageLoad( si->implicitImagePath );
+		
+		/* then try lightimage (note: new behavior!) */
+		if( si->shaderImage == NULL )
+			si->shaderImage = ImageLoad( si->lightImagePath );
+		
+		/* otherwise, use default image */
+		if( si->shaderImage == NULL )
+		{
+			si->shaderImage = ImageLoad( DEFAULT_IMAGE );
+			if( warnImage && strcmp( si->shader, "noshader" ) )
+				Sys_Printf( "WARNING: Couldn't find image for shader %s\n", si->shader );
+		}
+		
+		/* load light image */
+		si->lightImage = ImageLoad( si->lightImagePath );
+		
+		/* load normalmap image (ok if this is NULL) */
+		si->normalImage = ImageLoad( si->normalImagePath );
+		if( si->normalImage != NULL )
+		{
+			Sys_FPrintf( SYS_VRB, "Shader %s has\n"
+								  "    NM %s\n", si->shader, si->normalImagePath );
+		}
+	}
+	
+	/* if no light image, use shader image */
+	if( si->lightImage == NULL )
+		si->lightImage = ImageLoad( si->shaderImage->name );
+	
+	/* create default and average colors */
+	count = si->lightImage->width * si->lightImage->height;
+	VectorClear( color );
+	color[ 3 ] = 0.0f;
+	for( i = 0; i < count; i++ )
+	{
+		color[ 0 ] += si->lightImage->pixels[ i * 4 + 0 ];
+		color[ 1 ] += si->lightImage->pixels[ i * 4 + 1 ];
+		color[ 2 ] += si->lightImage->pixels[ i * 4 + 2 ];
+		color[ 3 ] += si->lightImage->pixels[ i * 4 + 3 ];
+	}
+	
+	if( VectorLength( si->color ) <= 0.0f )
+		ColorNormalize( color, si->color );
+	VectorScale( color, (1.0f / count), si->averageColor );
+}
+
+
+
+/*
+ShaderInfoForShader()
+finds a shaderinfo for a named shader
+*/
+
+shaderInfo_t *ShaderInfoForShader( const char *shaderName )
+{
+	int				i;
+	shaderInfo_t	*si;
+	char			shader[ MAX_QPATH ];
+	
+	
+	/* dummy check */
+	if( shaderName == NULL || shaderName[ 0 ] == '\0' )
+	{
+		Sys_Printf( "WARNING: Null or empty shader name\n" );
+		shaderName = "missing";
+	}
+	
+	/* strip off extension */
+	strcpy( shader, shaderName );
+	StripExtension( shader );
+	
+	/* search for it */
+	for( i = 0; i < numShaderInfo; i++ )
+	{
+		si = &shaderInfo[ i ];
+		if( !Q_stricmp( shader, si->shader ) )
+		{
+			/* load image if necessary */
+			if( si->shaderImage == NULL )
+			{
+				LoadShaderImages( si );
+				FinishShader( si );
+			}
+			
+			/* return it */
+			return si;
+		}
+	}
+	
+	/* allocate a default shader */
+	si = AllocShaderInfo();
+	strcpy( si->shader, shader );
+	LoadShaderImages( si );
+	FinishShader( si );
+	
+	/* return it */
+	return si;
+}
+
+
+
+/*
+GetTokenAppend() - ydnar
+gets a token and appends its text to the specified buffer
+*/
+
+static int	oldScriptLine = 0;
+static int	tabDepth = 0;
+
+qboolean GetTokenAppend( char *buffer, qboolean crossline )
+{
+	qboolean	r;
+	int			i;
+	
+	
+	/* get the token */
+	r = GetToken( crossline );
+	if( r == qfalse || buffer == NULL || token[ 0 ] == '\0' )
+		return r;
+	
+	/* pre-tabstops */
+	if( token[ 0 ] == '}' )
+		tabDepth--;
+	
+	/* append? */
+	if( oldScriptLine != scriptline )
+	{
+		strcat( buffer, "\n" );
+		for( i = 0; i < tabDepth; i++ )
+			strcat( buffer, "\t" );
+	}
+	else
+		strcat( buffer, " " );
+	oldScriptLine = scriptline;
+	strcat( buffer, token );
+	
+	/* post-tabstops */
+	if( token[ 0 ] == '{' )
+		tabDepth++;
+	
+	/* return */
+	return r;
+}
+
+
+void Parse1DMatrixAppend( char *buffer, int x, vec_t *m )
+{
+	int		i;
+	
+	
+	if( !GetTokenAppend( buffer, qtrue ) || strcmp( token, "(" ) )
+		Error( "Parse1DMatrixAppend(): line %d: ( not found!", scriptline );
+	for( i = 0; i < x; i++ )
+	{
+		if( !GetTokenAppend( buffer, qfalse ) )
+			Error( "Parse1DMatrixAppend(): line %d: Number not found!", scriptline );
+		m[ i ] = atof( token );
+	}
+	if( !GetTokenAppend( buffer, qtrue ) || strcmp( token, ")" ) )
+		Error( "Parse1DMatrixAppend(): line %d: ) not found!", scriptline );
+}
+
+
+
+
+/*
+ParseShaderFile()
+parses a shader file into discrete shaderInfo_t
+*/
+
+static void ParseShaderFile( const char *filename )
+{
+	int				i, val;
+	shaderInfo_t	*si;
+	char			*suffix, temp[ 1024 ];
+	char			shaderText[ 8192 ];	/* ydnar: fixme (make this bigger?) */
+	
+	
+	/* init */
+	si = NULL;
+	shaderText[ 0 ] = '\0';
+	
+	/* load the shader */
+	LoadScriptFile( filename, 0 );
+	
+	/* tokenize it */
+	while( 1 )
+	{
+		/* copy shader text to the shaderinfo */
+		if( si != NULL && shaderText[ 0 ] != '\0' )
+		{
+			strcat( shaderText, "\n" );
+			si->shaderText = safe_malloc( strlen( shaderText ) + 1 );
+			strcpy( si->shaderText, shaderText );
+			//%	if( VectorLength( si->vecs[ 0 ] ) )
+			//%		Sys_Printf( "%s\n", shaderText );
+		}
+		
+		/* ydnar: clear shader text buffer */
+		shaderText[ 0 ] = '\0';
+		
+		/* test for end of file */
+		if( !GetToken( qtrue ) )
+			break;
+		
+		/* shader name is initial token */
+		si = AllocShaderInfo();
+		strcpy( si->shader, token );
+		
+		/* ignore ":q3map" suffix */
+		suffix = strstr( si->shader, ":q3map" );
+		if( suffix != NULL )
+			*suffix = '\0';
+		
+		/* handle { } section */
+		if( !GetTokenAppend( shaderText, qtrue ) )
+			break;
+		if( strcmp( token, "{" ) )
+		{
+			if( si != NULL )
+				Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s\nLast known shader: %s",
+					filename, scriptline, token, si->shader );
+			else
+				Error( "ParseShaderFile(): %s, line %d: { not found!\nFound instead: %s",
+					filename, scriptline, token );
+		}
+		
+		while( 1 )
+		{
+			/* get the next token */
+			if( !GetTokenAppend( shaderText, qtrue ) )
+				break;
+			if( !strcmp( token, "}" ) )
+				break;
+			
+			
+			/* -----------------------------------------------------------------
+			   shader stages (passes)
+			   ----------------------------------------------------------------- */
+			
+			/* parse stage directives */
+			if( !strcmp( token, "{" ) )
+			{
+				si->hasPasses = qtrue;
+				while( 1 )
+				{
+					if( !GetTokenAppend( shaderText, qtrue ) )
+						break;
+					if( !strcmp( token, "}" ) )
+						break;
+					
+					/* only care about images if we don't have a editor/light image */
+					if( si->editorImagePath[ 0 ] == '\0' && si->lightImagePath[ 0 ] == '\0' && si->implicitImagePath[ 0 ] == '\0' )
+					{
+						/* digest any images */
+						if( !Q_stricmp( token, "map" ) ||
+							!Q_stricmp( token, "clampMap" ) ||
+							!Q_stricmp( token, "animMap" ) ||
+							!Q_stricmp( token, "clampAnimMap" ) ||
+							!Q_stricmp( token, "clampMap" ) ||
+							!Q_stricmp( token, "mapComp" ) ||
+							!Q_stricmp( token, "mapNoComp" ) )
+						{
+							/* skip one token for animated stages */
+							if( !Q_stricmp( token, "animMap" ) || !Q_stricmp( token, "clampAnimMap" ) )
+								GetTokenAppend( shaderText, qfalse );
+							
+							/* get an image */
+							GetTokenAppend( shaderText, qfalse );
+							if( token[ 0 ] != '*' && token[ 0 ] != '$' )
+							{
+								strcpy( si->lightImagePath, token );
+								DefaultExtension( si->lightImagePath, ".tga" );
+								
+								/* debug code */
+								//%	Sys_FPrintf( SYS_VRB, "Deduced shader image: %s\n", si->lightImagePath );
+							}
+						}
+					}
+				}
+			}
+			
+			
+			/* -----------------------------------------------------------------
+			   surfaceparm * directives
+			   ----------------------------------------------------------------- */
+			
+			/* match surfaceparm */
+			else if( !Q_stricmp( token, "surfaceparm" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				if( ApplySurfaceParm( token, &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
+					Sys_Printf( "WARNING: Unknown surfaceparm: \"%s\"\n", token );
+			}
+			
+			
+			/* -----------------------------------------------------------------
+			   game-related shader directives
+			   ----------------------------------------------------------------- */
+			
+			/* ydnar: fogparms (for determining fog volumes) */
+			else if( !Q_stricmp( token, "fogparms" ) )
+				si->fogParms = qtrue;
+			
+			/* ydnar: polygonoffset (for no culling) */
+			else if( !Q_stricmp( token, "polygonoffset" ) )
+				si->polygonOffset = qtrue;
+			
+			/* tesssize is used to force liquid surfaces to subdivide */
+			else if( !Q_stricmp( token, "tessSize" ) || !Q_stricmp( token, "q3map_tessSize" ) /* sof2 */ )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				si->subdivisions = atof( token );
+			}
+			
+			/* cull none will set twoSided (ydnar: added disable too) */
+			else if ( !Q_stricmp( token, "cull" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				if( !Q_stricmp( token, "none" ) || !Q_stricmp( token, "disable" ) || !Q_stricmp( token, "twosided" ) )
+					si->twoSided = qtrue;
+			}
+			
+			/* deformVertexes autosprite[ 2 ]
+			   we catch this so autosprited surfaces become point
+			   lights instead of area lights */
+			else if( !Q_stricmp( token, "deformVertexes" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				
+				/* deformVertexes autosprite(2) */
+				if( !Q_strncasecmp( token, "autosprite", 10 ) )
+				{
+					/* set it as autosprite and detail */
+					si->autosprite = qtrue;
+					ApplySurfaceParm( "detail", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
+					
+					/* ydnar: gs mods: added these useful things */
+					si->noClip = qtrue;
+					si->notjunc = qtrue;
+				}
+				
+				/* deformVertexes move <x> <y> <z> <func> <base> <amplitude> <phase> <freq> (ydnar: for particle studio support) */
+				if( !Q_stricmp( token, "move") )
+				{
+					vec3_t	amt, mins, maxs;
+					float	base, amp;
+					
+					
+					/* get move amount */
+					GetTokenAppend( shaderText, qfalse );	amt[ 0 ] = atof( token );
+					GetTokenAppend( shaderText, qfalse );	amt[ 1 ] = atof( token );
+					GetTokenAppend( shaderText, qfalse );	amt[ 2 ] = atof( token );
+					
+					/* skip func */
+					GetTokenAppend( shaderText, qfalse );
+					
+					/* get base and amplitude */
+					GetTokenAppend( shaderText, qfalse );	base = atof( token );
+					GetTokenAppend( shaderText, qfalse );	amp = atof( token );
+					
+					/* calculate */
+					VectorScale( amt, base, mins );
+					VectorMA( mins, amp, amt, maxs );
+					VectorAdd( si->mins, mins, si->mins );
+					VectorAdd( si->maxs, maxs, si->maxs );
+				} 
+			}
+			
+			/* light <value> (old-style flare specification) */
+			else if( !Q_stricmp( token, "light" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				strcpy( si->flareShader, "flareshader" );
+			}
+			
+			/* ydnar: damageShader <shader> <health> (sof2 mods) */
+			else if( !Q_stricmp( token, "damageShader" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				strcpy( si->damageShader, token );
+				GetTokenAppend( shaderText, qfalse );	/* don't do anything with health */
+			}
+
+			/* ydnar: enemy territory implicit shaders */
+			else if( !Q_stricmp( token, "implicitMap" ) )
+			{
+				si->implicitMap = IM_OPAQUE;
+				GetTokenAppend( shaderText, qfalse );
+				if( token[ 0 ] == '-' && token[ 1 ] == '\0' )
+					sprintf( si->implicitImagePath, "%s.tga", si->shader );
+				else
+					strcpy( si->implicitImagePath, token );
+			}
+
+			else if( !Q_stricmp( token, "implicitMask" ) )
+			{
+				si->implicitMap = IM_MASKED;
+				GetTokenAppend( shaderText, qfalse );
+				if( token[ 0 ] == '-' && token[ 1 ] == '\0' )
+					sprintf( si->implicitImagePath, "%s.tga", si->shader );
+				else
+					strcpy( si->implicitImagePath, token );
+			}
+
+			else if( !Q_stricmp( token, "implicitBlend" ) )
+			{
+				si->implicitMap = IM_MASKED;
+				GetTokenAppend( shaderText, qfalse );
+				if( token[ 0 ] == '-' && token[ 1 ] == '\0' )
+					sprintf( si->implicitImagePath, "%s.tga", si->shader );
+				else
+					strcpy( si->implicitImagePath, token );
+			}
+			
+			
+			/* -----------------------------------------------------------------
+			   image directives
+			   ----------------------------------------------------------------- */
+			
+			/* qer_editorimage <image> */
+			else if( !Q_stricmp( token, "qer_editorImage" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				strcpy( si->editorImagePath, token );
+				DefaultExtension( si->editorImagePath, ".tga" );
+			}
+			
+			/* ydnar: q3map_normalimage <image> (bumpmapping normal map) */
+			else if( !Q_stricmp( token, "q3map_normalImage" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				strcpy( si->normalImagePath, token );
+				DefaultExtension( si->normalImagePath, ".tga" );
+			}
+			
+			/* q3map_lightimage <image> */
+			else if( !Q_stricmp( token, "q3map_lightImage" ) )
+			{
+				GetTokenAppend( shaderText, qfalse );
+				strcpy( si->lightImagePath, token );
+				DefaultExtension( si->lightImagePath, ".tga" );
+			}
+			
+			/* ydnar: skyparms <outer image> <cloud height> <inner image> */
+			else if( !Q_stricmp( token, "skyParms" ) )
+			{
+				/* get image base */
+				GetTokenAppend( shaderText, qfalse );
+				
+				/* ignore bogus paths */
+				if( Q_stricmp( token, "-" ) && Q_stricmp( token, "full" ) )
+				{
+					strcpy( si->skyParmsImageBase, token );
+					
+					/* use top image as sky light image */
+					if( si->lightImagePath[ 0 ] == '\0' )
+						sprintf( si->lightImagePath, "%s_up.tga", si->skyParmsImageBase );
+				}
+				
+				/* skip rest of line */
+				GetTokenAppend( shaderText, qfalse );
+				GetTokenAppend( shaderText, qfalse );
+			}
+			
+			/* -----------------------------------------------------------------
+			   q3map_* directives
+			   ----------------------------------------------------------------- */
+			
+			/* q3map_sun <red> <green> <blue> <intensity> <degrees> <elevation>
+			   color will be normalized, so it doesn't matter what range you use
+			   intensity falls off with angle but not distance 100 is a fairly bright sun
+			   degree of 0 = from the east, 90 = north, etc.  altitude of 0 = sunrise/set, 90 = noon
+			   ydnar: sof2map has bareword 'sun' token, so we support that as well */
+			else if( !Q_stricmp( token, "sun" ) /* sof2 */ || !Q_stricmp( token, "q3map_sun" ) || !Q_stricmp( token, "q3map_sunExt" ) )
+			{
+				float		a, b;
+				sun_t		*sun;
+				qboolean	ext;
+				
+				
+				/* ydnar: extended sun directive? */
+				if( !Q_stricmp( token, "q3map_sunext" ) )
+					ext = qtrue;
+				
+				/* allocate sun */
+				sun = safe_malloc( sizeof( *sun ) );
+				memset( sun, 0, sizeof( *sun ) );
+				
+				/* get color */
+				GetTokenAppend( shaderText, qfalse );
+				sun->color[ 0 ] = atof( token );
+				GetTokenAppend( shaderText, qfalse );
+				sun->color[ 1 ] = atof( token );
+				GetTokenAppend( shaderText, qfalse );
+				sun->color[ 2 ] = atof( token );
+				
+				/* normalize it */
+				VectorNormalize( sun->color, sun->color );
+				
+				/* scale color by brightness */
+				GetTokenAppend( shaderText, qfalse );
+				sun->photons = atof( token );
+				
+				/* get sun angle/elevation */
+				GetTokenAppend( shaderText, qfalse );
+				a = atof( token );
+				a = a / 180.0f * Q_PI;
+				
+				GetTokenAppend( shaderText, qfalse );
+				b = atof( token );
+				b = b / 180.0f * Q_PI;
+				
+				sun->direction[ 0 ] = cos( a ) * cos( b );
+				sun->direction[ 1 ] = sin( a ) * cos( b );
+				sun->direction[ 2 ] = sin( b );
+				
+				/* get filter radius from shader */
+				sun->filterRadius = si->lightFilterRadius;
+				
+				/* ydnar: get sun angular deviance/samples */
+				if( ext && TokenAvailable() )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					sun->deviance = atof( token );
+					sun->deviance = sun->deviance / 180.0f * Q_PI;
+					
+					GetTokenAppend( shaderText, qfalse );
+					sun->numSamples = atoi( token );
+				}
+				
+				/* store sun */
+				sun->next = si->sun;
+				si->sun = sun;
+				
+				/* apply sky surfaceparm */
+				ApplySurfaceParm( "sky", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
+				
+				/* don't process any more tokens on this line */
+				continue;
+			}
+
+			/* match q3map_ */
+			else if( !Q_strncasecmp( token, "q3map_", 6 ) )
+			{
+				/* ydnar: q3map_baseShader <shader> (inherit this shader's parameters) */
+				if( !Q_stricmp( token, "q3map_baseShader" ) )
+				{
+					shaderInfo_t	*si2;
+					qboolean		oldWarnImage;
+					
+					
+					/* get shader */
+					GetTokenAppend( shaderText, qfalse );
+					//%	Sys_FPrintf( SYS_VRB, "Shader %s has base shader %s\n", si->shader, token );
+					oldWarnImage = warnImage;
+					warnImage = qfalse;
+					si2 = ShaderInfoForShader( token );
+					warnImage = oldWarnImage;
+					
+					/* subclass it */
+					if( si2 != NULL )
+					{
+						/* preserve name */
+						strcpy( temp, si->shader );
+						
+						/* copy shader */
+						memcpy( si, si2, sizeof( *si ) );
+						
+						/* restore name and set to unfinished */
+						strcpy( si->shader, temp );
+						si->finished = qfalse;
+					}
+				}
+				
+				/* ydnar: q3map_surfacemodel <path to model> <density> <min scale> <max scale> <min angle> <max angle> <oriented (0 or 1)> */
+				else if( !Q_stricmp( token, "q3map_surfacemodel" ) )
+				{
+					surfaceModel_t	*model;
+					
+					
+					/* allocate new model and attach it */
+					model = safe_malloc( sizeof( *model ) );
+					memset( model, 0, sizeof( *model ) );
+					model->next = si->surfaceModel;
+					si->surfaceModel = model;
+						
+					/* get parameters */
+					GetTokenAppend( shaderText, qfalse );
+					strcpy( model->model, token );
+					
+					GetTokenAppend( shaderText, qfalse );
+					model->density = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					model->odds = atof( token );
+					
+					GetTokenAppend( shaderText, qfalse );
+					model->minScale = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					model->maxScale = atof( token );
+					
+					GetTokenAppend( shaderText, qfalse );
+					model->minAngle = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					model->maxAngle = atof( token );
+					
+					GetTokenAppend( shaderText, qfalse );
+					model->oriented = (token[ 0 ] == '1' ? qtrue : qfalse);
+				}
+				
+				/* ydnar/sd: q3map_foliage <path to model> <scale> <density> <odds> <invert alpha (1 or 0)> */
+				else if( !Q_stricmp( token, "q3map_foliage" ) )
+				{
+					foliage_t	*foliage;
+					
+					
+					/* allocate new foliage struct and attach it */
+					foliage = safe_malloc( sizeof( *foliage ) );
+					memset( foliage, 0, sizeof( *foliage ) );
+					foliage->next = si->foliage;
+					si->foliage = foliage;
+					
+					/* get parameters */
+					GetTokenAppend( shaderText, qfalse );
+					strcpy( foliage->model, token );
+					
+					GetTokenAppend( shaderText, qfalse );
+					foliage->scale = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					foliage->density = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					foliage->odds = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					foliage->inverseAlpha = atoi( token );
+				}
+				
+				/* ydnar: q3map_bounce <value> (fraction of light to re-emit during radiosity passes) */
+				else if( !Q_stricmp( token, "q3map_bounce" ) || !Q_stricmp( token, "q3map_bounceScale" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->bounceScale = atof( token );
+				}
+
+				/* ydnar/splashdamage: q3map_skylight <value> <iterations> */
+				else if( !Q_stricmp( token, "q3map_skylight" )  )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->skyLightValue = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->skyLightIterations = atoi( token );
+					
+					/* clamp */
+					if( si->skyLightValue < 0.0f )
+						si->skyLightValue = 0.0f;
+					if( si->skyLightIterations < 2 )
+						si->skyLightIterations = 2;
+				}
+				
+				/* q3map_surfacelight <value> */
+				else if( !Q_stricmp( token, "q3map_surfacelight" )  )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->value = atof( token );
+				}
+				
+				
+				/* q3map_lightStyle (sof2/jk2 lightstyle) */
+				else if( !Q_stricmp( token, "q3map_lightStyle" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					val = atoi( token );
+					if( val < 0 )
+						val = 0;
+					else if( val > LS_NONE )
+						val = LS_NONE;
+					si->lightStyle = val;
+				}
+				
+				/* wolf: q3map_lightRGB <red> <green> <blue> */
+				else if( !Q_stricmp( token, "q3map_lightRGB" ) )
+				{
+					VectorClear( si->color );
+					GetTokenAppend( shaderText, qfalse );
+					si->color[ 0 ] = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->color[ 1 ] = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->color[ 2 ] = atof( token );
+					ColorNormalize( si->color, si->color );
+				}
+				
+				/* q3map_lightSubdivide <value> */
+				else if( !Q_stricmp( token, "q3map_lightSubdivide" )  )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->lightSubdivide = atoi( token );
+				}
+				
+				/* q3map_backsplash <percent> <distance> */
+				else if( !Q_stricmp( token, "q3map_backsplash" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->backsplashFraction = atof( token ) * 0.01f;
+					GetTokenAppend( shaderText, qfalse );
+					si->backsplashDistance = atof( token );
+				}
+				
+				/* q3map_lightmapSampleSize <value> */
+				else if( !Q_stricmp( token, "q3map_lightmapSampleSize" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->lightmapSampleSize = atoi( token );
+				}
+				
+				/* q3map_lightmapSampleSffset <value> */
+				else if( !Q_stricmp( token, "q3map_lightmapSampleOffset" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->lightmapSampleOffset = atof( token );
+				}
+				
+				/* ydnar: q3map_lightmapFilterRadius <self> <other> */
+				else if( !Q_stricmp( token, "q3map_lightmapFilterRadius" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->lmFilterRadius = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->lightFilterRadius = atof( token );
+				}
+				
+				/* ydnar: q3map_lightmapAxis [xyz] */
+				else if( !Q_stricmp( token, "q3map_lightmapAxis" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					if( !Q_stricmp( token, "x" ) )
+						VectorSet( si->lightmapAxis, 1, 0, 0 );
+					else if( !Q_stricmp( token, "y" ) )
+						VectorSet( si->lightmapAxis, 0, 1, 0 );
+					else if( !Q_stricmp( token, "z" ) )
+						VectorSet( si->lightmapAxis, 0, 0, 1 );
+					else
+					{
+						Sys_Printf( "WARNING: Unknown value for lightmap axis: %s\n", token );
+						VectorClear( si->lightmapAxis );
+					}
+				}
+				
+				/* ydnar: q3map_lightmapSize <width> <height> (for autogenerated shaders + external tga lightmaps) */
+				else if( !Q_stricmp( token, "q3map_lightmapSize" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->lmCustomWidth = atoi( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->lmCustomHeight = atoi( token );
+					
+					/* must be a power of 2 */
+					if( ((si->lmCustomWidth - 1) & si->lmCustomWidth) ||
+						((si->lmCustomHeight - 1) & si->lmCustomHeight) )
+					{
+						Sys_Printf( "WARNING: Non power-of-two lightmap size specified (%d, %d)\n",
+							 si->lmCustomWidth, si->lmCustomHeight );
+						si->lmCustomWidth = LIGHTMAP_WIDTH;
+						si->lmCustomHeight = LIGHTMAP_HEIGHT;
+					}
+				}
+
+				/* ydnar: q3map_lightmapGamma N (for autogenerated shaders + external tga lightmaps) */
+				else if( !Q_stricmp( token, "q3map_lightmapGamma" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->lmGamma = atof( token );
+					if( si->lmGamma < 0 )
+						si->lmGamma = 1.0;
+				}
+				
+				/* q3map_vertexScale (scale vertex lighting by this fraction) */
+				else if( !Q_stricmp( token, "q3map_vertexScale" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->vertexScale = atof( token );
+				}
+				
+				/* q3map_flare <shader> */
+				else if( !Q_stricmp( token, "q3map_flare" ) || !Q_stricmp( token, "q3map_flareShader" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					strcpy( si->flareShader, token );
+				}
+				
+				/* q3map_backShader <shader> */
+				else if( !Q_stricmp( token, "q3map_backShader" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					strcpy( si->backShader, token );
+				}
+				
+				/* ydnar: q3map_offset <value> */
+				else if( !Q_stricmp( token, "q3map_offset" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->offset = atof( token );
+				}
+				
+				/* ydnar: q3map_cloneShader <shader> */
+				else if ( !Q_stricmp( token, "q3map_cloneShader" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					strcpy( si->cloneShader, token );
+				}
+				
+				/* ydnar: q3map_textureSize <width> <height> (substitute for q3map_lightimage derivation for terrain) */
+				else if( !Q_stricmp( token, "q3map_fur" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->furNumLayers = atoi( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->furOffset = atof( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->furFade = atof( token );
+				}
+				
+				/* ydnar: gs mods: legacy support for terrain/terrain2 shaders */
+				else if( !Q_stricmp( token, "q3map_terrain" ) )
+				{
+					/* team arena terrain is assumed to be nonplanar, with full normal averaging,
+					   passed through the metatriangle surface pipeline, with a lightmap axis on z */
+					si->legacyTerrain = qtrue;
+					si->noClip = qtrue;
+					si->notjunc = qtrue;
+					si->indexed = qtrue;
+					si->nonplanar = qtrue;
+					si->forceMeta = qtrue;
+					si->shadeAngleDegrees = 179.0f;
+					//%	VectorSet( si->lightmapAxis, 0, 0, 1 );	/* ydnar 2002-09-21: turning this off for better lightmapping of cliff faces */
+				}
+				
+				/* ydnar: picomodel: q3map_forceMeta (forces brush faces and/or triangle models to go through the metasurface pipeline) */
+				else if( !Q_stricmp( token, "q3map_forceMeta" ) )
+				{
+					si->forceMeta = qtrue;
+				}
+				
+				/* ydnar: gs mods: q3map_shadeAngle <degrees> */
+				else if( !Q_stricmp( token, "q3map_shadeAngle" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->shadeAngleDegrees = atof( token );
+				}
+				
+				/* ydnar: q3map_textureSize <width> <height> (substitute for q3map_lightimage derivation for terrain) */
+				else if( !Q_stricmp( token, "q3map_textureSize" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					si->shaderWidth = atoi( token );
+					GetTokenAppend( shaderText, qfalse );
+					si->shaderHeight = atoi( token );
+				}
+				
+				/* ydnar: gs mods: q3map_tcGen <style> <parameters> */
+				else if( !Q_stricmp( token, "q3map_tcGen" ) )
+				{
+					si->tcGen = qtrue;
+					GetTokenAppend( shaderText, qfalse );
+					
+					/* q3map_tcGen vector <s vector> <t vector> */
+					if( !Q_stricmp( token, "vector" ) )
+					{
+						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ] );
+						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ] );
+					}
+					
+					/* q3map_tcGen ivector <1.0/s vector> <1.0/t vector> (inverse vector, easier for mappers to understand) */
+					else if( !Q_stricmp( token, "ivector" ) )
+					{
+						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 0 ] );
+						Parse1DMatrixAppend( shaderText, 3, si->vecs[ 1 ] );
+						for( i = 0; i < 3; i++ )
+						{
+							si->vecs[ 0 ][ i ] = si->vecs[ 0 ][ i ] ? 1.0 / si->vecs[ 0 ][ i ] : 0;
+							si->vecs[ 1 ][ i ] = si->vecs[ 1 ][ i ] ? 1.0 / si->vecs[ 1 ][ i ] : 0;
+						}
+					}
+					else
+					{
+						Sys_Printf( "WARNING: Unknown q3map_tcGen method: %s\n", token );
+						VectorClear( si->vecs[ 0 ] );
+						VectorClear( si->vecs[ 1 ] );
+					}
+				}
+				
+				/* ydnar: gs mods: q3map_alphaMod <style> <parameters> */
+				else if( !Q_stricmp( token, "q3map_alphaMod" ) )
+				{
+					alphaMod_t	*am, *am2;
+					
+					
+					/* allocate new alpha mod */
+					am = safe_malloc( sizeof( *am ) );
+					memset( am, 0, sizeof( *am ) );
+					
+					/* attach to shader */
+					if( si->alphaMod == NULL )
+						si->alphaMod = am;
+					else
+					{
+						for( am2 = si->alphaMod; am2 != NULL; am2 = am2->next )
+						{
+							if( am2->next == NULL )
+							{
+								am2->next = am;
+								break;
+							}
+						}
+					}
+					
+					/* get type */
+					GetTokenAppend( shaderText, qfalse );
+					
+					/* q3map_alphaMod dotproduct ( X Y Z ) */
+					if( !Q_stricmp( token, "dotproduct" ) )
+					{
+						am->type = AM_DOT_PRODUCT;
+						Parse1DMatrixAppend( shaderText, 3, am->data );
+					}
+					else
+						Sys_Printf( "WARNING: Unknown q3map_alphaMod method: %s\n", token );
+				}
+				
+				/* ydnar: gs mods: q3map_tcMod <style> <parameters> */
+				else if( !Q_stricmp( token, "q3map_tcMod" ) )
+				{
+					float	a, b;
+					
+					
+					GetTokenAppend( shaderText, qfalse );
+					
+					/* q3map_tcMod [translate | shift | offset] <s> <t> */
+					if( !Q_stricmp( token, "translate" ) || !Q_stricmp( token, "shift" ) || !Q_stricmp( token, "offset" ) )
+					{
+						GetTokenAppend( shaderText, qfalse );
+						a = atof( token );
+						GetTokenAppend( shaderText, qfalse );
+						b = atof( token );
+						
+						TcModTranslate( si->mod, a, b );
+					}
+
+					/* q3map_tcMod scale <s> <t> */
+					else if( !Q_stricmp( token, "scale" ) )
+					{
+						GetTokenAppend( shaderText, qfalse );
+						a = atof( token );
+						GetTokenAppend( shaderText, qfalse );
+						b = atof( token );
+						
+						TcModScale( si->mod, a, b );
+					}
+					
+					/* q3map_tcMod rotate <s> <t> (fixme: make this communitive) */
+					else if( !Q_stricmp( token, "rotate" ) )
+					{
+						GetTokenAppend( shaderText, qfalse );
+						a = atof( token );
+						TcModRotate( si->mod, a );
+					}
+					else
+						Sys_Printf( "WARNING: Unknown q3map_tcMod method: %s\n", token );
+				}
+				
+				/* q3map_fogDir (direction a fog shader fades from transparent to opaque) */
+				else if( !Q_stricmp( token, "q3map_fogDir" ) )
+				{
+					Parse1DMatrixAppend( shaderText, 3, si->fogDir );
+					VectorNormalize( si->fogDir, si->fogDir );
+				}
+				
+				/* q3map_globaltexture */
+				else if( !Q_stricmp( token, "q3map_globaltexture" )  )
+					si->globalTexture = qtrue;
+				
+				/* ydnar: gs mods: q3map_nonplanar (make it a nonplanar merge candidate for meta surfaces) */
+				else if( !Q_stricmp( token, "q3map_nonplanar" ) )
+					si->nonplanar = qtrue;
+				
+				/* ydnar: gs mods: q3map_noclip (preserve original face winding, don't clip by bsp tree) */
+				else if( !Q_stricmp( token, "q3map_noclip" ) )
+					si->noClip = qtrue;
+				
+				/* q3map_notjunc */
+				else if( !Q_stricmp( token, "q3map_notjunc" ) )
+					si->notjunc = qtrue;
+				
+				/* q3map_nofog */
+				else if( !Q_stricmp( token, "q3map_nofog" ) )
+					si->noFog = qtrue;
+				
+				/* ydnar: gs mods: q3map_indexed (for explicit terrain-style indexed mapping) */
+				else if( !Q_stricmp( token, "q3map_indexed" ) )
+					si->indexed = qtrue;
+				
+				/* ydnar: q3map_invert (inverts a drawsurface's facing) */
+				else if( !Q_stricmp( token, "q3map_invert" ) )
+					si->invert = qtrue;
+				
+				/* ydnar: gs mods: q3map_lightmapMergable (ok to merge non-planar */
+				else if( !Q_stricmp( token, "q3map_lightmapMergable" ) )
+					si->lmMergable = qtrue;
+				
+				/* ydnar: q3map_nofast */
+				else if( !Q_stricmp( token, "q3map_noFast" ) )
+					si->noFast = qtrue;
+				
+				/* q3map_patchshadows */
+				else if( !Q_stricmp( token, "q3map_patchShadows" ) )
+					si->patchShadows = qtrue;
+				
+				/* q3map_vertexshadows */
+				else if( !Q_stricmp( token, "q3map_vertexShadows" ) )
+					si->vertexShadows = qtrue;	/* ydnar */
+				
+				/* q3map_novertexshadows */
+				else if( !Q_stricmp( token, "q3map_noVertexShadows" ) )
+					si->vertexShadows = qfalse;	/* ydnar */
+				
+				/* q3map_splotchfix (filter dark lightmap luxels on lightmapped models) */
+				else if( !Q_stricmp( token, "q3map_splotchfix" ) )
+					si->splotchFix = qtrue;	/* ydnar */
+				
+				/* q3map_forcesunlight */
+				else if( !Q_stricmp( token, "q3map_forceSunlight" ) )
+					si->forceSunlight = qtrue;
+				
+				/* q3map_onlyvertexlighting (sof2) */
+				else if( !Q_stricmp( token, "q3map_onlyVertexLighting" ) )
+					ApplySurfaceParm( "pointlight", &si->contentFlags, &si->surfaceFlags, &si->compileFlags );
+				
+				/* q3map_material (sof2) */
+				else if( !Q_stricmp( token, "q3map_material" ) )
+				{
+					GetTokenAppend( shaderText, qfalse );
+					sprintf( temp, "*mat_%s", token );
+					if( ApplySurfaceParm( temp, &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
+						Sys_Printf( "WARNING: Unknown material \"%s\"\n", token );
+				}
+				
+				/* ydnar: q3map_clipmodel (autogenerate clip brushes for model triangles using this shader) */
+				else if( !Q_stricmp( token, "q3map_clipmodel" )  )
+					si->clipModel = qtrue;
+				
+				/* ydnar: q3map_styleMarker[2] */
+				else if( !Q_stricmp( token, "q3map_styleMarker" ) )
+					si->styleMarker = 1;
+				else if( !Q_stricmp( token, "q3map_styleMarker2" ) )	/* uses depthFunc equal */
+					si->styleMarker = 2;
+				
+				/* ydnar: default to searching for q3map_<surfaceparm> */
+				else
+				{
+					//%	Sys_FPrintf( SYS_VRB, "Attempting to match %s with a known surfaceparm\n", token );
+					if( ApplySurfaceParm( &token[ 6 ], &si->contentFlags, &si->surfaceFlags, &si->compileFlags ) == qfalse )
+						;//%	Sys_Printf( "WARNING: Unknown q3map_* directive \"%s\"\n", token );
+				}
+			}
+			
+			
+			/* -----------------------------------------------------------------
+			   skip
+			   ----------------------------------------------------------------- */
+			
+			/* ignore all other tokens on the line */
+			while( TokenAvailable() && GetTokenAppend( shaderText, qfalse ) );
+		}			
+	}
+}
+
+
+
+/*
+ParseCustomInfoParms() - rr2do2
+loads custom info parms file for mods
+*/
+
+static void ParseCustomInfoParms( void )
+{
+	qboolean parsedContent, parsedSurface;
+	
+	
+	/* file exists? */
+	if( vfsGetFileCount( "scripts/custinfoparms.txt" ) == 0 )
+		return;
+	
+	/* load it */
+	LoadScriptFile( "scripts/custinfoparms.txt", 0 );
+	
+	/* clear the array */
+	memset( custSurfaceParms, 0, sizeof( custSurfaceParms ) );
+	numCustSurfaceParms = 0;
+	parsedContent = parsedSurface = qfalse;
+	
+	/* parse custom contentflags */
+	MatchToken( "{" );
+	while ( 1 )
+	{
+		if ( !GetToken( qtrue ) )
+			break;
+
+		if ( !strcmp( token, "}" ) ) {
+			parsedContent = qtrue;
+			break;
+		}
+
+		custSurfaceParms[ numCustSurfaceParms ].name = safe_malloc( MAX_OS_PATH );
+		strcpy( custSurfaceParms[ numCustSurfaceParms ].name, token );
+		GetToken( qfalse );
+		sscanf( token, "%x", &custSurfaceParms[ numCustSurfaceParms ].contentFlags );
+		numCustSurfaceParms++;
+	}
+	
+	/* any content? */
+	if( !parsedContent )
+	{
+		Sys_Printf( "WARNING: Couldn't find valid custom contentsflag section\n" );
+		return;
+	}
+	
+	/* parse custom surfaceflags */
+	MatchToken( "{" );
+	while( 1 )
+	{
+		if( !GetToken( qtrue ) )
+			break;
+
+		if( !strcmp( token, "}" ) )
+		{
+			parsedSurface = qtrue;
+			break;
+		}
+
+		custSurfaceParms[ numCustSurfaceParms ].name = safe_malloc( MAX_OS_PATH );
+		strcpy( custSurfaceParms[ numCustSurfaceParms ].name, token );
+		GetToken( qfalse );
+		sscanf( token, "%x", &custSurfaceParms[ numCustSurfaceParms ].surfaceFlags );
+		numCustSurfaceParms++;
+	}
+	
+	/* any content? */
+	if( !parsedContent )
+		Sys_Printf( "WARNING: Couldn't find valid custom surfaceflag section\n" );
+}
+
+	
+
+/*
+LoadShaderInfo()
+the shaders are parsed out of shaderlist.txt from a main directory
+that is, if using -fs_game we ignore the shader scripts that might be in baseq3/
+on linux there's an additional twist, we actually merge the stuff from ~/.q3a/ and from the base dir
+*/
+
+#define	MAX_SHADER_FILES	1024
+
+void LoadShaderInfo( void )
+{
+	int				i, j, numShaderFiles, count;
+	char			filename[ 1024 ];
+	char			*shaderFiles[ MAX_SHADER_FILES ];
+	
+	
+	/* rr2do2: parse custom infoparms first */
+	if( useCustomInfoParms )
+		ParseCustomInfoParms();
+	
+	/* start with zero */
+	numShaderFiles = 0;
+	
+	/* we can pile up several shader files, the one in baseq3 and ones in the mod dir or other spots */
+	sprintf( filename, "%s/shaderlist.txt", game->shaderPath );
+	count = vfsGetFileCount( filename );
+	
+	/* load them all */
+	for( i = 0; i < count; i++ )
+	{
+		/* load shader list */
+		sprintf( filename, "%s/shaderlist.txt", game->shaderPath );
+		LoadScriptFile( filename, i );
+		
+		/* parse it */
+		while( GetToken( qtrue ) )
+		{
+			/* check for duplicate entries */
+			for( j = 0; j < numShaderFiles; j++ )
+				if( !strcmp( shaderFiles[ j ], token ) )
+					break;
+			
+			/* test limit */
+			if( j >= MAX_SHADER_FILES )
+				Error( "MAX_SHADER_FILES (%d) reached, trim your shaderlist.txt!", (int) MAX_SHADER_FILES );
+			
+			/* new shader file */
+			if( j == numShaderFiles )
+			{
+				shaderFiles[ numShaderFiles ] = safe_malloc( MAX_OS_PATH );
+				strcpy( shaderFiles[ numShaderFiles ], token );
+				numShaderFiles++;
+			}
+		}
+	}
+	
+	/* parse the shader files */
+	for( i = 0; i < numShaderFiles; i++ )
+	{
+		sprintf( filename, "%s/%s.shader", game->shaderPath, shaderFiles[ i ] );
+		ParseShaderFile( filename );
+		free( shaderFiles[ i ] );
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d shaderInfo\n", numShaderInfo );
+}
diff --git a/tools/quake3/q3map2/surface.c b/tools/quake3/q3map2/surface.c
index dfd5c6e5..79649c89 100644
--- a/tools/quake3/q3map2/surface.c
+++ b/tools/quake3/q3map2/surface.c
@@ -1,3533 +1,3533 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define SURFACE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-
-this section handles drawsurface allocation and creation
-
-*/
-
-/*
-AllocDrawSurface()
-ydnar: gs mods: changed to force an explicit type when allocating
-*/
-
-mapDrawSurface_t *AllocDrawSurface( surfaceType_t type )
-{
-	mapDrawSurface_t	*ds;
-	
-	
-	/* ydnar: gs mods: only allocate valid types */
-	if( type <= SURFACE_BAD || type >= NUM_SURFACE_TYPES )
-		Error( "AllocDrawSurface: Invalid surface type %d specified", type );
-	
-	/* bounds check */
-	if( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS )
-		Error( "MAX_MAP_DRAW_SURFS (%d) exceeded", MAX_MAP_DRAW_SURFS );
-	ds = &mapDrawSurfs[ numMapDrawSurfs ];
-	numMapDrawSurfs++;
-	
-	/* ydnar: do initial surface setup */
-	memset( ds, 0, sizeof( mapDrawSurface_t ) );
-	ds->type = type;
-	ds->planeNum = -1;
-	ds->fogNum = defaultFogNum;				/* ydnar 2003-02-12 */
-	ds->outputNum = -1;						/* ydnar 2002-08-13 */
-	ds->surfaceNum = numMapDrawSurfs - 1;	/* ydnar 2003-02-16 */
-	
-	return ds;
-}
-
-
-
-/*
-FinishSurface()
-ydnar: general surface finish pass
-*/
-
-void FinishSurface( mapDrawSurface_t *ds )
-{
-	/* dummy check */
-	if( ds == NULL || ds->shaderInfo == NULL )
-		return;
-	
-	/* ydnar: rocking tek-fu celshading */
-	if( ds->celShader != NULL )
-		MakeCelSurface( ds, ds->celShader );
-	
-	/* ydnar: rocking surface cloning (fur baby yeah!) */
-	if( ds->shaderInfo->cloneShader[ 0 ] != '\0' )
-		CloneSurface( ds, ShaderInfoForShader( ds->shaderInfo->cloneShader ) );
-}
-
-
-
-/*
-CloneSurface()
-clones a map drawsurface, using the specified shader
-*/
-
-mapDrawSurface_t *CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si )
-{
-	mapDrawSurface_t	*ds;
-	
-	
-	/* dummy check */
-	if( src == NULL || si == NULL )
-		return NULL;
-	
-	/* allocate a new surface */
-	ds = AllocDrawSurface( src->type );
-	if( ds == NULL )
-		return NULL;
-	
-	/* copy it */
-	memcpy( ds, src, sizeof( *ds ) );
-	
-	/* destroy side reference */
-	ds->sideRef = NULL;
-	
-	/* set shader */
-	ds->shaderInfo = si;
-	
-	/* copy verts */
-	if( ds->numVerts > 0 )
-	{
-		ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-		memcpy( ds->verts, src->verts, ds->numVerts * sizeof( *ds->verts ) );
-	}
-	
-	/* copy indexes */
-	if( ds->numIndexes <= 0 )
-		return ds;
-	ds->indexes = safe_malloc( ds->numIndexes * sizeof( *ds->indexes ) );
-	memcpy( ds->indexes, src->indexes, ds->numIndexes * sizeof( *ds->indexes ) );
-	
-	/* return the surface */
-	return ds;
-}
-
-
-
-/*
-MakeCelSurface() - ydnar
-makes a copy of a surface, but specific to cel shading
-*/
-
-mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si )
-{
-	mapDrawSurface_t	*ds;
-	
-	
-	/* dummy check */
-	if( src == NULL || si == NULL )
-		return NULL;
-	
-	/* don't create cel surfaces for certain types of shaders */
-	if( (src->shaderInfo->compileFlags & C_TRANSLUCENT) ||
-		(src->shaderInfo->compileFlags & C_SKY) )
-		return NULL;
-	
-	/* make a copy */
-	ds = CloneSurface( src, si );
-	if( ds == NULL )
-		return NULL;
-	
-	/* do some fixups for celshading */
-	ds->planar = qfalse;
-	ds->planeNum = -1;
-	
-	/* return the surface */
-	return ds;
-}
-
-
-
-/*
-MakeSkyboxSurface() - ydnar
-generates a skybox surface, viewable from everywhere there is sky
-*/
-
-mapDrawSurface_t *MakeSkyboxSurface( mapDrawSurface_t *src )
-{
-	int					i;
-	mapDrawSurface_t	*ds;
-	
-	
-	/* dummy check */
-	if( src == NULL )
-		return NULL;
-	
-	/* make a copy */
-	ds = CloneSurface( src, src->shaderInfo );
-	if( ds == NULL )
-		return NULL;
-	
-	/* set parent */
-	ds->parent = src;
-	
-	/* scale the surface vertexes */
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		m4x4_transform_point( skyboxTransform, ds->verts[ i ].xyz );
-		
-		/* debug code */
-		//%	bspDrawVerts[ bspDrawSurfaces[ ds->outputNum ].firstVert + i ].color[ 0 ][ 1 ] = 0;
-		//%	bspDrawVerts[ bspDrawSurfaces[ ds->outputNum ].firstVert + i ].color[ 0 ][ 2 ] = 0;
-	}
-	
-	/* so backface culling creep doesn't bork the surface */
-	VectorClear( ds->lightmapVecs[ 2 ] );
-	
-	/* return the surface */
-	return ds;
-}
-
-
-
-/*
-IsTriangleDegenerate
-returns qtrue if all three points are colinear, backwards, or the triangle is just plain bogus
-*/
-
-#define	TINY_AREA	1.0f
-
-qboolean IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c )
-{
-	vec3_t		v1, v2, v3;
-	float		d;
-	
-	
-	/* calcuate the area of the triangle */
-	VectorSubtract( points[ b ].xyz, points[ a ].xyz, v1 );
-	VectorSubtract( points[ c ].xyz, points[ a ].xyz, v2 );
-	CrossProduct( v1, v2, v3 );
-	d = VectorLength( v3 );
-	
-	/* assume all very small or backwards triangles will cause problems */
-	if( d < TINY_AREA )
-		return qtrue;
-	
-	/* must be a good triangle */
-	return qfalse;
-}
-
-
-
-/*
-ClearSurface() - ydnar
-clears a surface and frees any allocated memory
-*/
-
-void ClearSurface( mapDrawSurface_t *ds )
-{
-	ds->type = SURFACE_BAD;
-	ds->planar = qfalse;
-	ds->planeNum = -1;
-	ds->numVerts = 0;
-	if( ds->verts != NULL )
-		free( ds->verts );
-	ds->verts = NULL;
-	ds->numIndexes = 0;
-	if( ds->indexes != NULL )
-		free( ds->indexes );
-	ds->indexes = NULL;
-	numClearedSurfaces++;
-}
-
-
-
-/*
-TidyEntitySurfaces() - ydnar
-deletes all empty or bad surfaces from the surface list
-*/
-
-void TidyEntitySurfaces( entity_t *e )
-{
-	int					i, j, deleted;
-	mapDrawSurface_t	*out, *in;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- TidyEntitySurfaces ---\n" );
-	
-	/* walk the surface list */
-	deleted = 0;
-	for( i = e->firstDrawSurf, j = e->firstDrawSurf; j < numMapDrawSurfs; i++, j++ )
-	{
-		/* get out surface */
-		out = &mapDrawSurfs[ i ];
-		
-		/* walk the surface list again until a proper surface is found */
-		for( j; j < numMapDrawSurfs; j++ )
-		{
-			/* get in surface */
-			in = &mapDrawSurfs[ j ];
-			
-			/* this surface ok? */
-			if( in->type == SURFACE_FLARE || in->type == SURFACE_SHADER ||
-				(in->type != SURFACE_BAD && in->numVerts > 0) )
-				break;
-			
-			/* nuke it */
-			ClearSurface( in );
-			deleted++;
-		}
-		
-		/* copy if necessary */
-		if( i != j )
-			memcpy( out, in, sizeof( mapDrawSurface_t ) );
-	}
-	
-	/* set the new number of drawsurfs */
-	numMapDrawSurfs = i;
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d empty or malformed surfaces deleted\n", deleted );
-}
-
-
-
-/*
-CalcSurfaceTextureRange() - ydnar
-calculates the clamped texture range for a given surface, returns qtrue if it's within [-texRange,texRange]
-*/
-
-qboolean CalcSurfaceTextureRange( mapDrawSurface_t *ds )
-{
-	int		i, j, v, size[ 2 ];
-	float	mins[ 2 ], maxs[ 2 ];
-	
-	
-	/* try to early out */
-	if( ds->numVerts <= 0 )
-		return qtrue;
-	
-	/* walk the verts and determine min/max st values */
-	mins[ 0 ] = 999999;
-	mins[ 1 ] = 999999;
-	maxs[ 0 ] = -999999;
-	maxs[ 1 ] = -999999;
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		for( j = 0; j < 2; j++ )
-		{
-			if( ds->verts[ i ].st[ j ] < mins[ j ] )
-				mins[ j ] = ds->verts[ i ].st[ j ];
-			if( ds->verts[ i ].st[ j ] > maxs[ j ] )
-				maxs[ j ] = ds->verts[ i ].st[ j ];
-		}
-	}
-	
-	/* clamp to integer range and calculate surface bias values */
-	for( j = 0; j < 2; j++ )
-		ds->bias[ j ] = -floor( 0.5f * (mins[ j ] + maxs[ j ]) );
-	
-	/* find biased texture coordinate mins/maxs */
-	size[ 0 ] = ds->shaderInfo->shaderWidth;
-	size[ 1 ] = ds->shaderInfo->shaderHeight;
-	ds->texMins[ 0 ] = 999999;
-	ds->texMins[ 1 ] = 999999;
-	ds->texMaxs[ 0 ] = -999999;
-	ds->texMaxs[ 1 ] = -999999;
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		for( j = 0; j < 2; j++ )
-		{
-			v = ((float) ds->verts[ i ].st[ j ] + ds->bias[ j ]) * size[ j ];
-			if( v < ds->texMins[ j ] )
-				ds->texMins[ j ] = v;
-			if( v > ds->texMaxs[ j ] )
-				ds->texMaxs[ j ] = v;
-		}
-	}
-	
-	/* calc ranges */
-	for( j = 0; j < 2; j++ )
-		ds->texRange[ j ] = (ds->texMaxs[ j ] - ds->texMins[ j ]);
-	
-	/* if range is zero, then assume unlimited precision */
-	if( texRange == 0 )
-		return qtrue;
-	
-	/* within range? */
-	for( j = 0; j < 2; j++ )
-	{
-		if( ds->texMins[ j ] < -texRange || ds->texMaxs[ j ] > texRange )
-			return qfalse;
-	}
-	
-	/* within range */
-	return qtrue;
-}
-
-
-
-/*
-CalcLightmapAxis() - ydnar
-gives closed lightmap axis for a plane normal
-*/
-
-qboolean CalcLightmapAxis( vec3_t normal, vec3_t axis )
-{
-	vec3_t	absolute;
-		
-	
-	/* test */
-	if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f && normal[ 2 ] == 0.0f )
-	{
-		VectorClear( axis );
-		return qfalse;
-	}
-	
-	/* get absolute normal */
-	absolute[ 0 ] = fabs( normal[ 0 ] );
-	absolute[ 1 ] = fabs( normal[ 1 ] );
-	absolute[ 2 ] = fabs( normal[ 2 ] );
-	
-	/* test and set */
-	if( absolute[ 2 ] > absolute[ 0 ] - 0.0001f && absolute[ 2 ] > absolute[ 1 ] - 0.0001f )
-	{
-		if( normal[ 2 ] > 0.0f )
-			VectorSet( axis, 0.0f, 0.0f, 1.0f );
-		else
-			VectorSet( axis, 0.0f, 0.0f, -1.0f );
-	}
-	else if( absolute[ 0 ] > absolute[ 1 ] - 0.0001f && absolute[ 0 ] > absolute[ 2 ] - 0.0001f )
-	{
-		if( normal[ 0 ] > 0.0f )
-			VectorSet( axis, 1.0f, 0.0f, 0.0f );
-		else
-			VectorSet( axis, -1.0f, 0.0f, 0.0f );
-	}
-	else
-	{
-		if( normal[ 1 ] > 0.0f )
-			VectorSet( axis, 0.0f, 1.0f, 0.0f );
-		else
-			VectorSet( axis, 0.0f, -1.0f, 0.0f );
-	}
-	
-	/* return ok */
-	return qtrue;
-}
-
-
-
-/*
-ClassifySurfaces() - ydnar
-fills out a bunch of info in the surfaces, including planar status, lightmap projection, and bounding box
-*/
-
-#define PLANAR_EPSILON	0.5f	//% 0.126f 0.25f
-
-void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds )
-{
-	int					i, bestAxis;
-	float				dist;
-	vec4_t				plane;
-	shaderInfo_t		*si;
-	static vec3_t		axii[ 6 ] =
-						{
-							{ 0, 0, -1 },
-							{ 0, 0, 1 },
-							{ -1, 0, 0 },
-							{ 1, 0, 0 },
-							{ 0, -1, 0 },
-							{ 0, 1, 0 }
-						};
-	
-	
-	/* walk the list of surfaces */
-	for( numSurfs; numSurfs > 0; numSurfs--, ds++ )
-	{
-		/* ignore bogus (or flare) surfaces */
-		if( ds->type == SURFACE_BAD || ds->numVerts <= 0 )
-			continue;
-		
-		/* get shader */
-		si = ds->shaderInfo;
-		
-		/* -----------------------------------------------------------------
-		   force meta if vertex count is too high or shader requires it
-		   ----------------------------------------------------------------- */
-		
-		if( ds->type != SURFACE_PATCH && ds->type != SURFACE_FACE )
-		{
-			if( ds->numVerts > SHADER_MAX_VERTEXES )
-				ds->type = SURFACE_FORCED_META;
-		}
-		
-		/* -----------------------------------------------------------------
-		   plane and bounding box classification 
-		   ----------------------------------------------------------------- */
-		
-		/* set surface bounding box */
-		ClearBounds( ds->mins, ds->maxs );
-		for( i = 0; i < ds->numVerts; i++ )
-			AddPointToBounds( ds->verts[ i ].xyz, ds->mins, ds->maxs );
-		
-		/* try to get an existing plane */
-		if( ds->planeNum >= 0 )
-		{
-			VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
-			plane[ 3 ] = mapplanes[ ds->planeNum ].dist;
-		}
-		
-		/* construct one from the first vert with a valid normal */
-		else
-		{
-			VectorClear( plane );
-			plane[ 3 ] = 0.0f;
-			for( i = 0; i < ds->numVerts; i++ )
-			{
-				if( ds->verts[ i ].normal[ 0 ] != 0.0f && ds->verts[ i ].normal[ 1 ] != 0.0f && ds->verts[ i ].normal[ 2 ] != 0.0f )
-				{
-					VectorCopy( ds->verts[ i ].normal, plane );
-					plane[ 3 ] = DotProduct( ds->verts[ i ].xyz, plane );
-					break;
-				}
-			}
-		}
-		
-		/* test for bogus plane */
-		if( VectorLength( plane ) <= 0.0f )
-		{
-			ds->planar = qfalse;
-			ds->planeNum = -1;
-		}
-		else
-		{
-			/* determine if surface is planar */
-			ds->planar = qtrue;
-			
-			/* test each vert */
-			for( i = 0; i < ds->numVerts; i++ )
-			{
-				/* point-plane test */
-				dist = DotProduct( ds->verts[ i ].xyz, plane ) - plane[ 3 ];
-				if( fabs( dist ) > PLANAR_EPSILON )
-				{
-					//%	if( ds->planeNum >= 0 )
-					//%	{
-					//%		Sys_Printf( "WARNING: Planar surface marked unplanar (%f > %f)\n", fabs( dist ), PLANAR_EPSILON );
-					//%		ds->verts[ i ].color[ 0 ][ 0 ] = ds->verts[ i ].color[ 0 ][ 2 ] = 0;
-					//%	}
-					ds->planar = qfalse;
-					break;
-				}
-			}
-		}
-		
-		/* find map plane if necessary */
-		if( ds->planar )
-		{
-			if( ds->planeNum < 0 )
-				ds->planeNum = FindFloatPlane( plane, plane[ 3 ], 1, &ds->verts[ 0 ].xyz );
-			VectorCopy( plane, ds->lightmapVecs[ 2 ] );
-		}
-		else
-		{
-			ds->planeNum = -1;
-			VectorClear( ds->lightmapVecs[ 2 ] );
-			//% if( ds->type == SURF_META || ds->type == SURF_FACE )
-			//%		Sys_Printf( "WARNING: Non-planar face (%d): %s\n", ds->planeNum, ds->shaderInfo->shader );
-		}
-		
-		/* -----------------------------------------------------------------
-		   lightmap bounds and axis projection
-		   ----------------------------------------------------------------- */
-		
-		/* vertex lit surfaces don't need this information */
-		if( si->compileFlags & C_VERTEXLIT || ds->type == SURFACE_TRIANGLES )
-		{
-			VectorClear( ds->lightmapAxis );
-			//%	VectorClear( ds->lightmapVecs[ 2 ] );
-			ds->sampleSize = 0;
-			continue;
-		}
-		
-		/* the shader can specify an explicit lightmap axis */
-		if( si->lightmapAxis[ 0 ] || si->lightmapAxis[ 1 ] || si->lightmapAxis[ 2 ] )
-			VectorCopy( si->lightmapAxis, ds->lightmapAxis );
-		else if( ds->type == SURFACE_FORCED_META )
-			VectorClear( ds->lightmapAxis );
-		else if( ds->planar )
-			CalcLightmapAxis( plane, ds->lightmapAxis );
-		else
-		{
-			/* find best lightmap axis */
-			for( bestAxis = 0; bestAxis < 6; bestAxis++ )
-			{
-				for( i = 0; i < ds->numVerts && bestAxis < 6; i++ )
-				{
-					//% Sys_Printf( "Comparing %1.3f %1.3f %1.3f to %1.3f %1.3f %1.3f\n",
-					//% 	ds->verts[ i ].normal[ 0 ], ds->verts[ i ].normal[ 1 ], ds->verts[ i ].normal[ 2 ],
-					//% 	axii[ bestAxis ][ 0 ], axii[ bestAxis ][ 1 ], axii[ bestAxis ][ 2 ] );
-					if( DotProduct( ds->verts[ i ].normal, axii[ bestAxis ] ) < 0.25f )	/* fixme: adjust this tolerance to taste */
-						break;
-				}
-				
-				if( i == ds->numVerts )
-					break;
-			}
-			
-			/* set axis if possible */
-			if( bestAxis < 6 )
-			{
-				//% if( ds->type == SURFACE_PATCH )
-				//% 	Sys_Printf( "Mapped axis %d onto patch\n", bestAxis );
-				VectorCopy( axii[ bestAxis ], ds->lightmapAxis );
-			}
-			
-			/* debug code */
-			//% if( ds->type == SURFACE_PATCH )
-			//% 	Sys_Printf( "Failed to map axis %d onto patch\n", bestAxis );
-		}
-		
-		/* get lightmap sample size */
-		if( ds->sampleSize <= 0 )
-		{
- 			ds->sampleSize = sampleSize;
- 			if( ds->shaderInfo->lightmapSampleSize )
- 				ds->sampleSize = ds->shaderInfo->lightmapSampleSize;
-			if( ds->lightmapScale > 0 )
-				ds->sampleSize *= ds->lightmapScale;
-			if( ds->sampleSize <= 0 )
-				ds->sampleSize = 1;
-			else if( ds->sampleSize > 16384 )	/* powers of 2 are preferred */
-				ds->sampleSize = 16384;
-		}
-	}
-}
-
-
-
-/*
-ClassifyEntitySurfaces() - ydnar
-classifies all surfaces in an entity
-*/
-
-void ClassifyEntitySurfaces( entity_t *e )
-{
-	int		i;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- ClassifyEntitySurfaces ---\n" );
-	
-	/* walk the surface list */
-	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
-		ClassifySurfaces( 1, &mapDrawSurfs[ i ] );
-	
-	/* tidy things up */
-	TidyEntitySurfaces( e );
-}
-
-
-
-/*
-GetShaderIndexForPoint() - ydnar
-for shader-indexed surfaces (terrain), find a matching index from the indexmap
-*/
-
-byte GetShaderIndexForPoint( indexMap_t *im, vec3_t eMins, vec3_t eMaxs, vec3_t point )
-{
-	int			i, x, y;
-	float		s, t;
-	vec3_t		mins, maxs, size;
-	
-	
-	/* early out if no indexmap */
-	if( im == NULL )
-		return 0;
-	
-	/* this code is really broken */
-	#if 0
-		/* legacy precision fudges for terrain */
-		for( i = 0; i < 3; i++ )
-		{
-			mins[ i ] = floor( eMins[ i ] + 0.1 );
-			maxs[ i ] = floor( eMaxs[ i ] + 0.1 );
-			size[ i ] = maxs[ i ] - mins[ i ];
-		}
-		
-		/* find st (fixme: support more than just z-axis projection) */
-		s = floor( point[ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ];
-		t = floor( maxs[ 1 ] - point[ 1 ] + 0.1f ) / size[ 1 ];
-		if( s < 0.0f )
-			s = 0.0f;
-		else if( s > 1.0f )
-			s = 1.0f;
-		if( t < 0.0f )
-			t = 0.0f;
-		else if( t > 1.0f )
-			t = 1.0f;
-		
-		/* make xy */
-		x = (im->w - 1) * s;
-		y = (im->h - 1) * t;
-	#else
-		/* get size */
-		for( i = 0; i < 3; i++ )
-		{
-			mins[ i ] = eMins[ i ];
-			maxs[ i ] = eMaxs[ i ];
-			size[ i ] = maxs[ i ] - mins[ i ];
-		}
-		
-		/* calc st */
-		s = (point[ 0 ] - mins[ 0 ]) / size[ 0 ];
-		t = (maxs[ 1 ] - point[ 1 ]) / size[ 1 ];
-		
-		/* calc xy */
-		x = s * im->w;
-		y = t * im->h;
-		if( x < 0 )
-			x = 0;
-		else if( x > (im->w - 1) )
-			x = (im->w - 1);
-		if( y < 0 )
-			y = 0;
-		else if( y > (im->h - 1) )
-			y = (im->h - 1);
-	#endif
-	
-	/* return index */
-	return im->pixels[ y * im->w + x ];
-}
-
-
-
-/*
-GetIndexedShader() - ydnar
-for a given set of indexes and an indexmap, get a shader and set the vertex alpha in-place
-this combines a couple different functions from terrain.c
-*/
-
-shaderInfo_t *GetIndexedShader( shaderInfo_t *parent, indexMap_t *im, int numPoints, byte *shaderIndexes )
-{
-	int				i;
-	byte			minShaderIndex, maxShaderIndex;
-	char			shader[ MAX_QPATH ];
-	shaderInfo_t	*si;
-	
-	
-	/* early out if bad data */
-	if( im == NULL || numPoints <= 0 || shaderIndexes == NULL )
-		return ShaderInfoForShader( "default" );
-	
-	/* determine min/max index */
-	minShaderIndex = 255;
-	maxShaderIndex = 0;
-	for( i = 0; i < numPoints; i++ )
-	{
-		if( shaderIndexes[ i ] < minShaderIndex )
-			minShaderIndex = shaderIndexes[ i ];
-		if( shaderIndexes[ i ] > maxShaderIndex )
-			maxShaderIndex = shaderIndexes[ i ];
-	}
-	
-	/* set alpha inline */
-	for( i = 0; i < numPoints; i++ )
-	{
-		/* straight rip from terrain.c */
-		if( shaderIndexes[ i ] < maxShaderIndex )
-			shaderIndexes[ i ] = 0;
-		else
-			shaderIndexes[ i ] = 255;
-	}
-	
-	/* make a shader name */
-	if( minShaderIndex == maxShaderIndex )
-		sprintf( shader, "textures/%s_%d", im->shader, maxShaderIndex );
-	else
-		sprintf( shader, "textures/%s_%dto%d", im->shader, minShaderIndex, maxShaderIndex );
-	
-	/* get the shader */
-	si = ShaderInfoForShader( shader );
-	
-	/* inherit a few things from parent shader */
-	if( parent->globalTexture )
-		si->globalTexture = qtrue;
-	if( parent->forceMeta )
-		si->forceMeta = qtrue;
-	if( parent->nonplanar )
-		si->nonplanar = qtrue;
-	if( si->shadeAngleDegrees == 0.0 )
-		si->shadeAngleDegrees = parent->shadeAngleDegrees;
-	if( parent->tcGen && si->tcGen == qfalse )
-	{
-		/* set xy texture projection */
-		si->tcGen = qtrue;
-		VectorCopy( parent->vecs[ 0 ], si->vecs[ 0 ] );
-		VectorCopy( parent->vecs[ 1 ], si->vecs[ 1 ] );
-	}
-	if( VectorLength( parent->lightmapAxis ) > 0.0f && VectorLength( si->lightmapAxis ) <= 0.0f )
-	{
-		/* set lightmap projection axis */
-		VectorCopy( parent->lightmapAxis, si->lightmapAxis );
-	}
-	
-	/* return the shader */
-	return si;
-}
-
-
-
-
-/*
-DrawSurfaceForSide()
-creates a SURF_FACE drawsurface from a given brush side and winding
-*/
-
-#define	SNAP_FLOAT_TO_INT	8
-#define	SNAP_INT_TO_FLOAT	(1.0 / SNAP_FLOAT_TO_INT)
-
-mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w )
-{
-	int					i, j, k;
-	mapDrawSurface_t	*ds;
-	shaderInfo_t		*si, *parent;
-	bspDrawVert_t		*dv;
-	vec3_t				texX, texY;
-	vec_t				x, y;
-	vec3_t				vTranslated;
-	qboolean			indexed;
-	byte				shaderIndexes[ 256 ];
-	float				offsets[ 256 ];
-	char				tempShader[ MAX_QPATH ];
-
-	
-	/* ydnar: don't make a drawsurf for culled sides */
-	if( s->culled )
-		return NULL;
-	
-	/* range check */
-	if( w->numpoints > MAX_POINTS_ON_WINDING )
-		Error( "DrawSurfaceForSide: w->numpoints = %d (> %d)", w->numpoints, MAX_POINTS_ON_WINDING );
-	
-	/* get shader */
-	si = s->shaderInfo;
-	
-	/* ydnar: gs mods: check for indexed shader */
-	if( si->indexed && b->im != NULL )
-	{
-		/* indexed */
-		indexed = qtrue;
-		
-		/* get shader indexes for each point */
-		for( i = 0; i < w->numpoints; i++ )
-		{
-			shaderIndexes[ i ] = GetShaderIndexForPoint( b->im, b->eMins, b->eMaxs, w->p[ i ] );
-			offsets[ i ] = b->im->offsets[ shaderIndexes[ i ] ];
-			//%	Sys_Printf( "%f ", offsets[ i ] );
-		}
-		
-		/* get matching shader and set alpha */
-		parent = si;
-		si = GetIndexedShader( parent, b->im, w->numpoints, shaderIndexes );
-	}
-	else
-		indexed = qfalse;
-	
-	/* ydnar: sky hack/fix for GL_CLAMP borders on ati cards */
-	if( skyFixHack && si->skyParmsImageBase[ 0 ] != '\0' )
-	{
-		//%	Sys_FPrintf( SYS_VRB, "Enabling sky hack for shader %s using env %s\n", si->shader, si->skyParmsImageBase );
-		sprintf( tempShader, "%s_lf", si->skyParmsImageBase );
-		DrawSurfaceForShader( tempShader );
-		sprintf( tempShader, "%s_rt", si->skyParmsImageBase );
-		DrawSurfaceForShader( tempShader );
-		sprintf( tempShader, "%s_ft", si->skyParmsImageBase );
-		DrawSurfaceForShader( tempShader );
-		sprintf( tempShader, "%s_bk", si->skyParmsImageBase );
-		DrawSurfaceForShader( tempShader );
-		sprintf( tempShader, "%s_up", si->skyParmsImageBase );
-		DrawSurfaceForShader( tempShader );
-		sprintf( tempShader, "%s_dn", si->skyParmsImageBase );
-		DrawSurfaceForShader( tempShader );
-	}
-	
-	/* ydnar: gs mods */
-	ds = AllocDrawSurface( SURFACE_FACE );
-	ds->entityNum = b->entityNum;
-	ds->castShadows = b->castShadows;
-	ds->recvShadows = b->recvShadows;
-	
-	ds->planar = qtrue;
-	ds->planeNum = s->planenum;
-	VectorCopy( mapplanes[ s->planenum ].normal, ds->lightmapVecs[ 2 ] );
-	
-	ds->shaderInfo = si;
-	ds->mapBrush = b;
-	ds->sideRef = AllocSideRef( s, NULL );
-	ds->fogNum = -1;
-	ds->lightmapScale = b->lightmapScale;
-	ds->numVerts = w->numpoints;
-	ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-	memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
-	
-	/* compute s/t coordinates from brush primitive texture matrix (compute axis base) */
-	ComputeAxisBase( mapplanes[ s->planenum ].normal, texX, texY );
-	
-	/* create the vertexes */
-	for( j = 0; j < w->numpoints; j++ )
-	{
-		/* get the drawvert */
-		dv = ds->verts + j;
-		
-		/* copy xyz and do potential z offset */
-		VectorCopy( w->p[ j ], dv->xyz );
-		if( indexed )
-			dv->xyz[ 2 ] += offsets[ j ];
-		
-		/* round the xyz to a given precision and translate by origin */
-		for( i = 0 ; i < 3 ; i++ )
-			dv->xyz[ i ] = SNAP_INT_TO_FLOAT * floor( dv->xyz[ i ] * SNAP_FLOAT_TO_INT + 0.5f );
-		VectorAdd( dv->xyz, e->origin, vTranslated );
-		
-		/* ydnar: tek-fu celshading support for flat shaded shit */
-		if( flat )
-		{
-			dv->st[ 0 ] = si->stFlat[ 0 ];
-			dv->st[ 1 ] = si->stFlat[ 1 ];
-		}
-		
-		/* ydnar: gs mods: added support for explicit shader texcoord generation */
-		else if( si->tcGen )
-		{
-			dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], vTranslated );
-			dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], vTranslated );
-		}
-		
-		/* old quake-style texturing */
-		else if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
-		{
-			/* nearest-axial projection */
-			dv->st[ 0 ] = s->vecs[ 0 ][ 3 ] + DotProduct( s->vecs[ 0 ], vTranslated );
-			dv->st[ 1 ] = s->vecs[ 1 ][ 3 ] + DotProduct( s->vecs[ 1 ], vTranslated );
-			dv->st[ 0 ] /= si->shaderWidth;
-			dv->st[ 1 ] /= si->shaderHeight;
-		}
-		
-		/* brush primitive texturing */
-		else
-		{
-			/* calculate texture s/t from brush primitive texture matrix */
-			x = DotProduct( vTranslated, texX );
-			y = DotProduct( vTranslated, texY );
-			dv->st[ 0 ] = s->texMat[ 0 ][ 0 ] * x + s->texMat[ 0 ][ 1 ] * y + s->texMat[ 0 ][ 2 ];
-			dv->st[ 1 ] = s->texMat[ 1 ][ 0 ] * x + s->texMat[ 1 ][ 1 ] * y + s->texMat[ 1 ][ 2 ];
-		}
-		
-		/* copy normal */
-		VectorCopy( mapplanes[ s->planenum ].normal, dv->normal );
-		
-		/* ydnar: set color */
-		for( k = 0; k < MAX_LIGHTMAPS; k++ )
-		{
-			dv->color[ k ][ 0 ] = 255;
-			dv->color[ k ][ 1 ] = 255;
-			dv->color[ k ][ 2 ] = 255;
-			
-			/* ydnar: gs mods: handle indexed shader blending */
-			dv->color[ k ][ 3 ] = (indexed ? shaderIndexes[ j ] : 255);
-		}
-	}
-	
-	/* set cel shader */
-	ds->celShader = b->celShader;
-	
-	/* finish surface */
-	FinishSurface( ds );
-	
-	/* ydnar: gs mods: moved st biasing elsewhere */
-	return ds;
-}
-
-
-
-/*
-DrawSurfaceForMesh()
-moved here from patch.c
-*/
-
-#define YDNAR_NORMAL_EPSILON 0.50f
-
-qboolean VectorCompareExt( vec3_t n1, vec3_t n2, float epsilon )
-{
-	int		i;
-	
-	
-	/* test */
-	for( i= 0; i < 3; i++ )
-		if( fabs( n1[ i ] - n2[ i ]) > epsilon )
-			return qfalse;
-	return qtrue;
-}
-
-mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh )
-{
-	int					i, k, numVerts;
-	vec4_t				plane;
-	qboolean			planar;
-	float				dist;
-	mapDrawSurface_t	*ds;
-	shaderInfo_t		*si, *parent;
-	bspDrawVert_t		*dv;
-	vec3_t				vTranslated;
-	mesh_t				*copy;
-	qboolean			indexed;
-	byte				shaderIndexes[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ];
-	float				offsets[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ];
-	
-	
-	/* get mesh and shader shader */
-	if( mesh == NULL )
-		mesh = &p->mesh;
-	si = p->shaderInfo;
-	if( mesh == NULL || si == NULL )
-		return NULL;
-	
-	/* get vertex count */
-	numVerts = mesh->width * mesh->height;
-	
-	/* to make valid normals for patches with degenerate edges,
-	   we need to make a copy of the mesh and put the aproximating
-	   points onto the curve */
-	
-	/* create a copy of the mesh */
-	copy = CopyMesh( mesh );
-	
-	/* store off the original (potentially bad) normals */
-	MakeMeshNormals( *copy );
-	for( i = 0; i < numVerts; i++ )
-		VectorCopy( copy->verts[ i ].normal, mesh->verts[ i ].normal );
-	
-	/* put the mesh on the curve */
-	PutMeshOnCurve( *copy );
-
-	/* find new normals (to take into account degenerate/flipped edges */
-	MakeMeshNormals( *copy );
-	for( i = 0; i < numVerts; i++ )
-	{
-		/* ydnar: only copy normals that are significantly different from the originals */
-		if( DotProduct( copy->verts[ i ].normal, mesh->verts[ i ].normal ) < 0.75f )
-			VectorCopy( copy->verts[ i ].normal, mesh->verts[ i ].normal );
-	}
-	
-	/* free the old mesh */
-	FreeMesh( copy );
-	
-	/* ydnar: gs mods: check for indexed shader */
-	if( si->indexed && p->im != NULL )
-	{
-		/* indexed */
-		indexed = qtrue;
-
-		/* get shader indexes for each point */
-		for( i = 0; i < numVerts; i++ )
-		{
-			shaderIndexes[ i ] = GetShaderIndexForPoint( p->im, p->eMins, p->eMaxs, mesh->verts[ i ].xyz );
-			offsets[ i ] = p->im->offsets[ shaderIndexes[ i ] ];
-		}
-		
-		/* get matching shader and set alpha */
-		parent = si;
-		si = GetIndexedShader( parent, p->im, numVerts, shaderIndexes );
-	}
-	else
-		indexed = qfalse;
-	
-	
-	/* ydnar: gs mods */
-	ds = AllocDrawSurface( SURFACE_PATCH );
-	ds->entityNum = p->entityNum;
-	ds->castShadows = p->castShadows;
-	ds->recvShadows = p->recvShadows;
-	
-	ds->shaderInfo = si;
-	ds->mapMesh = p;
-	ds->lightmapScale = p->lightmapScale;	/* ydnar */
-	ds->patchWidth = mesh->width;
-	ds->patchHeight = mesh->height;
-	ds->numVerts = ds->patchWidth * ds->patchHeight;
-	ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-	memcpy( ds->verts, mesh->verts, ds->numVerts * sizeof( *ds->verts ) );
-	
-	ds->fogNum = -1;
-	ds->planeNum = -1;
-	
-	ds->longestCurve = p->longestCurve;
-	ds->maxIterations = p->maxIterations;
-	
-	/* construct a plane from the first vert */
-	VectorCopy( mesh->verts[ 0 ].normal, plane );
-	plane[ 3 ] = DotProduct( mesh->verts[ 0 ].xyz, plane );
-	planar = qtrue;
-	
-	/* spew forth errors */
-	if( VectorLength( plane ) < 0.001f )
-		Sys_Printf( "BOGUS " );
-	
-	/* test each vert */
-	for( i = 1; i < ds->numVerts && planar; i++ )
-	{
-		/* normal test */
-		if( VectorCompare( plane, mesh->verts[ i ].normal ) == qfalse )
-			planar = qfalse;
-		
-		/* point-plane test */
-		dist = DotProduct( mesh->verts[ i ].xyz, plane ) - plane[ 3 ];
-		if( fabs( dist ) > EQUAL_EPSILON )
-			planar = qfalse;
-	}
-	
-	/* add a map plane */
-	if( planar )
-	{
-		/* make a map plane */
-		ds->planeNum = FindFloatPlane( plane, plane[ 3 ], 1, &mesh->verts[ 0 ].xyz );
-		VectorCopy( plane, ds->lightmapVecs[ 2 ] );
-		
-		/* push this normal to all verts (ydnar 2003-02-14: bad idea, small patches get screwed up) */
-		for( i = 0; i < ds->numVerts; i++ )
-			VectorCopy( plane, ds->verts[ i ].normal );
-	}
-	
-	/* walk the verts to do special stuff */
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		/* get the drawvert */
-		dv = &ds->verts[ i ];
-		
-		/* ydnar: tek-fu celshading support for flat shaded shit */
-		if( flat )
-		{
-			dv->st[ 0 ] = si->stFlat[ 0 ];
-			dv->st[ 1 ] = si->stFlat[ 1 ];
-		}
-		
-		/* ydnar: gs mods: added support for explicit shader texcoord generation */
-		else if( si->tcGen )
-		{
-			/* translate by origin and project the texture */
-			VectorAdd( dv->xyz, e->origin, vTranslated );
-			dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], vTranslated );
-			dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], vTranslated );
-		}
-		
-		/* ydnar: set color */
-		for( k = 0; k < MAX_LIGHTMAPS; k++ )
-		{
-			dv->color[ k ][ 0 ] = 255;
-			dv->color[ k ][ 1 ] = 255;
-			dv->color[ k ][ 2 ] = 255;
-			
-			/* ydnar: gs mods: handle indexed shader blending */
-			dv->color[ k ][ 3 ] = (indexed ? shaderIndexes[ i ] : 255);
-		}
-		
-		/* ydnar: offset */
-		if( indexed )
-			dv->xyz[ 2 ] += offsets[ i ];
-	}
-	
-	/* set cel shader */
-	ds->celShader = p->celShader;
-	
-	/* finish surface */
-	FinishSurface( ds );
-	
-	/* return the drawsurface */
-	return ds;
-}
-
-
-
-/*
-DrawSurfaceForFlare() - ydnar
-creates a flare draw surface
-*/
-
-mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, char *flareShader, int lightStyle )
-{
-	mapDrawSurface_t	*ds;
-	
-	
-	/* emit flares? */
-	if( emitFlares == qfalse )
-		return NULL;
-	
-	/* allocate drawsurface */
-	ds = AllocDrawSurface( SURFACE_FLARE );
-	ds->entityNum = entNum;
-	
-	/* set it up */
-	if( flareShader != NULL && flareShader[ 0 ] != '\0' )
-		ds->shaderInfo = ShaderInfoForShader( flareShader );
-	else
-		ds->shaderInfo = ShaderInfoForShader( game->flareShader );
-	if( origin != NULL )
-		VectorCopy( origin, ds->lightmapOrigin );
-	if( normal != NULL )
-		VectorCopy( normal, ds->lightmapVecs[ 2 ] );
-	if( color != NULL )
-		VectorCopy( color, ds->lightmapVecs[ 0 ] );
-	
-	/* store light style */
-	ds->lightStyle = lightStyle;
-	if( ds->lightStyle < 0 || ds->lightStyle >= LS_NONE )
-		ds->lightStyle = LS_NORMAL;
-	
-	/* fixme: fog */
-	
-	/* return to sender */
-	return ds;
-}
-
-
-
-/*
-DrawSurfaceForShader() - ydnar
-creates a bogus surface to forcing the game to load a shader
-*/
-
-mapDrawSurface_t *DrawSurfaceForShader( char *shader )
-{
-	int					i;
-	shaderInfo_t		*si;
-	mapDrawSurface_t	*ds;
-	
-	
-	/* get shader */
-	si = ShaderInfoForShader( shader );
-
-	/* find existing surface */
-	for( i = 0; i < numMapDrawSurfs; i++ )
-	{
-		/* get surface */
-		ds = &mapDrawSurfs[ i ];
-		
-		/* check it */
-		if( ds->shaderInfo == si )
-			return ds;
-	}
-	
-	/* create a new surface */
-	ds = AllocDrawSurface( SURFACE_SHADER );
-	ds->entityNum = 0;
-	ds->shaderInfo = ShaderInfoForShader( shader );
-	
-	/* return to sender */
-	return ds;
-}
-
-
-
-/*
-AddSurfaceFlare() - ydnar
-creates flares (coronas) centered on surfaces
-*/
-
-static void AddSurfaceFlare( mapDrawSurface_t *ds, vec3_t entityOrigin )
-{
-	vec3_t				origin;
-	int					i;
-	
-	
-	/* find centroid */
-	VectorClear( origin );
-	for ( i = 0; i < ds->numVerts; i++ )
-		VectorAdd( origin, ds->verts[ i ].xyz, origin );
-	VectorScale( origin, (1.0f / ds->numVerts), origin );
-	if( entityOrigin != NULL )
-		VectorAdd( origin, entityOrigin, origin );
-	
-	/* push origin off surface a bit */
-	VectorMA( origin, 2.0f,  ds->lightmapVecs[ 2 ], origin );
-	
-	/* create the drawsurface */
-	DrawSurfaceForFlare( ds->entityNum, origin, ds->lightmapVecs[ 2 ], ds->shaderInfo->color, ds->shaderInfo->flareShader, ds->shaderInfo->lightStyle );
-}
-
-
-
-/*
-SubdivideFace()
-subdivides a face surface until it is smaller than the specified size (subdivisions)
-*/
-
-static void SubdivideFace( entity_t *e, brush_t *brush, side_t *side, winding_t *w, int fogNum, float subdivisions )
-{
-	int					i;
-	int					axis;
-	vec3_t				bounds[ 2 ];
-	const float			epsilon = 0.1;
-	int					subFloor, subCeil;
-	winding_t			*frontWinding, *backWinding;
-	mapDrawSurface_t	*ds;
-	
-	
-	/* dummy check */
-	if( w == NULL )
-		return;
-	if( w->numpoints < 3 )
-		Error( "SubdivideFaceSurface: Bad w->numpoints" );
-	
-	/* determine surface bounds */
-	ClearBounds( bounds[ 0 ], bounds[ 1 ] );
-	for( i = 0; i < w->numpoints; i++ )
-		AddPointToBounds( w->p[ i ], bounds[ 0 ], bounds[ 1 ] );
-	
-	/* split the face */
-	for( axis = 0; axis < 3; axis++ )
-	{
-		vec3_t			planePoint = { 0, 0, 0 };
-		vec3_t			planeNormal = { 0, 0, 0 };
-		float			d;
-		
-		
-		/* create an axial clipping plane */
-		subFloor = floor( bounds[ 0 ][ axis ] / subdivisions) * subdivisions;
-		subCeil = ceil( bounds[ 1 ][ axis ] / subdivisions) * subdivisions;
-		planePoint[ axis ] = subFloor + subdivisions;
-		planeNormal[ axis ] = -1;
-		d = DotProduct( planePoint, planeNormal );
-
-		/* subdivide if necessary */
-		if( (subCeil - subFloor) > subdivisions )
-		{
-			/* clip the winding */
-			ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding );
-
-			/* the clip may not produce two polygons if it was epsilon close */
-			if( frontWinding == NULL )
-				w = backWinding;
-			else if( backWinding == NULL )
-				w = frontWinding;
-			else
-			{
-				SubdivideFace( e, brush, side, frontWinding, fogNum, subdivisions );
-				SubdivideFace( e, brush, side, backWinding, fogNum, subdivisions );
-				return;
-			}
-		}
-	}
-	
-	/* create a face surface */
-	ds = DrawSurfaceForSide( e, brush, side, w );
-	
-	/* set correct fog num */
-	ds->fogNum = fogNum;
-}
-
-
-
-/*
-SubdivideFaceSurfaces()
-chop up brush face surfaces that have subdivision attributes
-ydnar: and subdivide surfaces that exceed specified texture coordinate range
-*/
-
-void SubdivideFaceSurfaces( entity_t *e, tree_t *tree )
-{
-	int					i, j, numBaseDrawSurfs, fogNum;
-	mapDrawSurface_t	*ds;
-	brush_t				*brush;
-	side_t				*side;
-	shaderInfo_t		*si;
-	winding_t			*w;
-	float				range, size, subdivisions, s2;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- SubdivideFaceSurfaces ---\n" );
-	
-	/* walk the list of surfaces */
-	numBaseDrawSurfs = numMapDrawSurfs;
-	for( i = e->firstDrawSurf; i < numBaseDrawSurfs; i++ )
-	{
-		/* get surface */
-		ds = &mapDrawSurfs[ i ];
-
-		/* only subdivide brush sides */
-		if( ds->type != SURFACE_FACE || ds->mapBrush == NULL || ds->sideRef == NULL || ds->sideRef->side == NULL )
-			continue;
-		
-		/* get bits */
-		brush = ds->mapBrush;
-		side = ds->sideRef->side;
-		
-		/* check subdivision for shader */
-		si = side->shaderInfo;
-		if( si == NULL )
-			continue;
-		
-		/* ydnar: don't subdivide sky surfaces */
-		if( si->compileFlags & C_SKY )
-			continue;
-		
-		/* do texture coordinate range check */
-		ClassifySurfaces( 1, ds );
-		if( CalcSurfaceTextureRange( ds ) == qfalse )
-		{
-			/* calculate subdivisions texture range (this code is shit) */
-			range = (ds->texRange[ 0 ] > ds->texRange[ 1 ] ? ds->texRange[ 0 ] : ds->texRange[ 1 ]);
-			size = ds->maxs[ 0 ] - ds->mins[ 0 ];
-			for( j = 1; j < 3; j++ )
-				if( (ds->maxs[ j ] - ds->mins[ j ]) > size )
-					size = ds->maxs[ j ] - ds->mins[ j ];
-			subdivisions = (size / range) * texRange;
-			subdivisions = ceil( subdivisions / 2 ) * 2;
-			for( j = 1; j < 8; j++ )
-			{
-				s2 = ceil( (float) texRange / j );
-				if( fabs( subdivisions - s2 ) <= 4.0 )
-				{
-					subdivisions = s2;
-					break;
-				}
-			}
-		}
-		else
-			subdivisions = si->subdivisions;
-		
-		/* get subdivisions from shader */
-		if(	si->subdivisions > 0 && si->subdivisions < subdivisions )
-			subdivisions = si->subdivisions;
-		if( subdivisions < 1.0f )
-			continue;
-		
-		/* preserve fog num */
-		fogNum = ds->fogNum;
-		
-		/* make a winding and free the surface */
-		w = WindingFromDrawSurf( ds );
-		ClearSurface( ds );
-		
-		/* subdivide it */
-		SubdivideFace( e, brush, side, w, fogNum, subdivisions );
-	}
-}
-
-
-
-/*
-====================
-ClipSideIntoTree_r
-
-Adds non-opaque leaf fragments to the convex hull
-====================
-*/
-
-void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node )
-{
-	plane_t			*plane;
-	winding_t		*front, *back;
-
-	if ( !w ) {
-		return;
-	}
-
-	if ( node->planenum != PLANENUM_LEAF ) {
-		if ( side->planenum == node->planenum ) {
-			ClipSideIntoTree_r( w, side, node->children[0] );
-			return;
-		}
-		if ( side->planenum == ( node->planenum ^ 1) ) {
-			ClipSideIntoTree_r( w, side, node->children[1] );
-			return;
-		}
-
-		plane = &mapplanes[ node->planenum ];
-		ClipWindingEpsilon ( w, plane->normal, plane->dist,
-				ON_EPSILON, &front, &back );
-		FreeWinding( w );
-
-		ClipSideIntoTree_r( front, side, node->children[0] );
-		ClipSideIntoTree_r( back, side, node->children[1] );
-
-		return;
-	}
-
-	// if opaque leaf, don't add
-	if ( !node->opaque ) {
-		AddWindingToConvexHull( w, &side->visibleHull, mapplanes[ side->planenum ].normal );
-	}
-
-	FreeWinding( w );
-	return;
-}
-
-
-
-
-
-static int g_numHiddenFaces, g_numCoinFaces;
-
-
-
-/*
-CullVectorCompare() - ydnar
-compares two vectors with an epsilon
-*/
-
-#define CULL_EPSILON 0.1f
-
-qboolean CullVectorCompare( const vec3_t v1, const vec3_t v2 )
-{
-	int		i;
-	
-	
-	for( i = 0; i < 3; i++ )
-		if( fabs( v1[ i ] - v2[ i ] ) > CULL_EPSILON )
-			return qfalse;
-	return qtrue;
-}
-
-
-
-/*
-SideInBrush() - ydnar
-determines if a brushside lies inside another brush
-*/
-
-qboolean SideInBrush( side_t *side, brush_t *b )
-{
-	int			i, s;
-	plane_t		*plane;
-	
-	
-	/* ignore sides w/o windings or shaders */
-	if( side->winding == NULL || side->shaderInfo == NULL )
-		return qtrue;
-
-	/* ignore culled sides and translucent brushes */
-	if( side->culled == qtrue || (b->compileFlags & C_TRANSLUCENT) )
-		return qfalse;
-
-	/* side iterator */
-	for( i = 0; i < b->numsides; i++ )
-	{
-		/* fail if any sides are caulk */
-		if( b->sides[ i ].compileFlags & C_NODRAW )
-			return qfalse;
-
-		/* check if side's winding is on or behind the plane */
-		plane = &mapplanes[ b->sides[ i ].planenum ];
-		s = WindingOnPlaneSide( side->winding, plane->normal, plane->dist );
-		if( s == SIDE_FRONT || s == SIDE_CROSS )
-			return qfalse;
-	}
-	
-	/* don't cull autosprite or polygonoffset surfaces */
-	if( side->shaderInfo )
-	{
-		if( side->shaderInfo->autosprite || side->shaderInfo->polygonOffset )
-			return qfalse;
-	}
-	
-	/* inside */
-	side->culled = qtrue;
-	g_numHiddenFaces++;
-	return qtrue;
-}
-
-
-/*
-CullSides() - ydnar
-culls obscured or buried brushsides from the map
-*/
-
-void CullSides( entity_t *e )
-{
-	int			numPoints;
-	int			i, j, k, l, first, second, dir;
-	winding_t	*w1, *w2;
-	brush_t	*b1, *b2;
-	side_t		*side1, *side2;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- CullSides ---\n" );
-	
-	g_numHiddenFaces = 0;
-	g_numCoinFaces = 0;
-	
-	/* brush interator 1 */
-	for( b1 = e->brushes; b1; b1 = b1->next )
-	{
-		/* sides check */
-		if( b1->numsides < 1 )
-			continue;
-
-		/* brush iterator 2 */
-		for( b2 = b1->next; b2; b2 = b2->next )
-		{
-			/* sides check */
-			if( b2->numsides < 1 )
-				continue;
-			
-			/* original check */
-			if( b1->original == b2->original && b1->original != NULL )
-				continue;
-			
-			/* bbox check */
-			j = 0;
-			for( i = 0; i < 3; i++ )
-				if( b1->mins[ i ] > b2->maxs[ i ] || b1->maxs[ i ] < b2->mins[ i ] )
-					j++;
-			if( j )
-				continue;
-
-			/* cull inside sides */
-			for( i = 0; i < b1->numsides; i++ )
-				SideInBrush( &b1->sides[ i ], b2 );
-			for( i = 0; i < b2->numsides; i++ )
-				SideInBrush( &b2->sides[ i ], b1 );
-			
-			/* side iterator 1 */
-			for( i = 0; i < b1->numsides; i++ )
-			{
-				/* winding check */
-				side1 = &b1->sides[ i ];
-				w1 = side1->winding;
-				if( w1 == NULL )
-					continue;
-				numPoints = w1->numpoints;
-				if( side1->shaderInfo == NULL )
-					continue;
-				
-				/* side iterator 2 */
-				for( j = 0; j < b2->numsides; j++ )
-				{
-					/* winding check */
-					side2 = &b2->sides[ j ];
-					w2 = side2->winding;
-					if( w2 == NULL )
-						continue;
-					if( side2->shaderInfo == NULL )
-						continue;
-					if( w1->numpoints != w2->numpoints )
-						continue;
-					if( side1->culled == qtrue && side2->culled == qtrue )
-						continue;
-					
-					/* compare planes */
-					if( (side1->planenum & ~0x00000001) != (side2->planenum & ~0x00000001) )
-						continue;
-					
-					/* get autosprite and polygonoffset status */
-					if( side1->shaderInfo &&
-						(side1->shaderInfo->autosprite || side1->shaderInfo->polygonOffset) )
-						continue;
-					if( side2->shaderInfo &&
-						(side2->shaderInfo->autosprite || side2->shaderInfo->polygonOffset) )
-						continue;
-					
-					/* find first common point */
-					first = -1;
-					for( k = 0; k < numPoints; k++ )
-					{
-						if( VectorCompare( w1->p[ 0 ], w2->p[ k ] ) )
-						{
-							first = k;
-							k = numPoints;
-						}
-					}
-					if( first == -1 )
-						continue;
-					
-					/* find second common point (regardless of winding order) */
-					second = -1;
-					dir = 0;
-					if( (first + 1) < numPoints )
-						second = first + 1;
-					else
-						second = 0;
-					if( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) )
-						dir = 1;
-					else
-					{
-						if( first > 0 )
-							second = first - 1;
-						else
-							second = numPoints - 1;
-						if( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) )
-							dir = -1;
-					}
-					if( dir == 0 )
-						continue;
-					
-					/* compare the rest of the points */
-					l = first;
-					for( k = 0; k < numPoints; k++ )
-					{
-						if( !CullVectorCompare( w1->p[ k ], w2->p[ l ] ) )
-							k = 100000;
-						
-						l += dir;
-						if( l < 0 )
-							l = numPoints - 1;
-						else if( l >= numPoints )
-							l = 0;
-					}
-					if( k >= 100000 )
-						continue;
-					
-					/* cull face 1 */
-					if( !side2->culled && !(side2->compileFlags & C_TRANSLUCENT) && !(side2->compileFlags & C_NODRAW) )
-					{
-						side1->culled = qtrue;
-						g_numCoinFaces++;
-					}
-					
-					if( side1->planenum == side2->planenum && side1->culled == qtrue )
-						continue;
-					
-					/* cull face 2 */
-					if( !side1->culled && !(side1->compileFlags & C_TRANSLUCENT) && !(side1->compileFlags & C_NODRAW) )
-					{
-						side2->culled = qtrue;
-						g_numCoinFaces++;
-					}
-				}
-			}
-		}
-	}
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d hidden faces culled\n", g_numHiddenFaces );
-	Sys_FPrintf( SYS_VRB, "%9d coincident faces culled\n", g_numCoinFaces );
-}
-
-
-
-
-/*
-ClipSidesIntoTree()
-
-creates side->visibleHull for all visible sides
-
-the drawsurf for a side will consist of the convex hull of
-all points in non-opaque clusters, which allows overlaps
-to be trimmed off automatically.
-*/
-
-void ClipSidesIntoTree( entity_t *e, tree_t *tree )
-{
-	brush_t		*b;
-	int				i;
-	winding_t		*w;
-	side_t			*side, *newSide;
-	shaderInfo_t	*si;
-  
-	
-	/* ydnar: cull brush sides */
-	CullSides( e );
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" );
-	
-	/* walk the brush list */
-	for( b = e->brushes; b; b = b->next )
-	{
-		/* walk the brush sides */
-		for( i = 0; i < b->numsides; i++ )
-		{
-			/* get side */
-			side = &b->sides[ i ];
-			if( side->winding == NULL )
-				continue;
-			
-			/* copy the winding */
-			w = CopyWinding( side->winding );
-			side->visibleHull = NULL;
-			ClipSideIntoTree_r( w, side, tree->headnode );
-			
-			/* anything left? */
-			w = side->visibleHull;
-			if( w == NULL )
-				continue;
-			
-			/* shader? */
-			si = side->shaderInfo;
-			if( si == NULL )
-				continue;
-			
-			/* don't create faces for non-visible sides */
-			/* ydnar: except indexed shaders, like common/terrain and nodraw fog surfaces */
-			if( (si->compileFlags & C_NODRAW) && si->indexed == qfalse && !(si->compileFlags & C_FOG) )
-				continue;
-			
-			/* always use the original winding for autosprites and noclip faces */
-			if( si->autosprite || si->noClip )
-				w = side->winding;
-			
-			/* save this winding as a visible surface */
-			DrawSurfaceForSide( e, b, side, w );
-
-			/* make a back side for fog */
-			if( !(si->compileFlags & C_FOG) )
-				continue;
-			
-			/* duplicate the up-facing side */
-			w = ReverseWinding( w );
-			newSide = safe_malloc( sizeof( *side ) );
-			*newSide = *side;
-			newSide->visibleHull = w;
-			newSide->planenum ^= 1;
-			
-			/* save this winding as a visible surface */
-			DrawSurfaceForSide( e, b, newSide, w );
-		}
-	}
-}
-
-
-
-/*
-
-this section deals with filtering drawsurfaces into the bsp tree,
-adding references to each leaf a surface touches
-
-*/
-
-/*
-AddReferenceToLeaf() - ydnar
-adds a reference to surface ds in the bsp leaf node
-*/
-
-int AddReferenceToLeaf( mapDrawSurface_t *ds, node_t *node )
-{
-	drawSurfRef_t	*dsr;
-	
-	
-	/* dummy check */
-	if( node->planenum != PLANENUM_LEAF || node->opaque )
-		return 0;
-	
-	/* try to find an existing reference */
-	for( dsr = node->drawSurfReferences; dsr; dsr = dsr->nextRef )
-	{
-		if( dsr->outputNum == numBSPDrawSurfaces )
-			return 0;
-	}
-	
-	/* add a new reference */
-	dsr = safe_malloc( sizeof( *dsr ) );
-	dsr->outputNum = numBSPDrawSurfaces;
-	dsr->nextRef = node->drawSurfReferences;
-	node->drawSurfReferences = dsr;
-	
-	/* ydnar: sky/skybox surfaces */
-	if( node->skybox )
-		ds->skybox = qtrue;
-	if( ds->shaderInfo->compileFlags & C_SKY )
-		node->sky = qtrue;
-	
-	/* return */
-	return 1;
-}
-
-
-
-/*
-AddReferenceToTree_r() - ydnar
-adds a reference to the specified drawsurface to every leaf in the tree
-*/
-
-int AddReferenceToTree_r( mapDrawSurface_t *ds, node_t *node, qboolean skybox )
-{
-	int		i, refs = 0;
-	
-	
-	/* dummy check */
-	if( node == NULL )
-		return 0;
-	
-	/* is this a decision node? */
-	if( node->planenum != PLANENUM_LEAF )
-	{
-		/* add to child nodes and return */
-		refs += AddReferenceToTree_r( ds, node->children[ 0 ], skybox );
-		refs += AddReferenceToTree_r( ds, node->children[ 1 ], skybox );
-		return refs;
-	}
-	
-	/* ydnar */
-	if( skybox )
-	{
-		/* skybox surfaces only get added to sky leaves */
-		if( !node->sky )
-			return 0;
-		
-		/* increase the leaf bounds */
-		for( i = 0; i < ds->numVerts; i++ )
-			AddPointToBounds( ds->verts[ i ].xyz, node->mins, node->maxs );
-	}
-	
-	/* add a reference */
-	return AddReferenceToLeaf( ds, node );
-}
-
-
-
-/*
-FilterPointIntoTree_r() - ydnar
-filters a single point from a surface into the tree
-*/
-
-int FilterPointIntoTree_r( vec3_t point, mapDrawSurface_t *ds, node_t *node )
-{
-	float			d;
-	plane_t			*plane;
-	int				refs = 0;
-	
-	
-	/* is this a decision node? */
-	if( node->planenum != PLANENUM_LEAF )
-	{
-		/* classify the point in relation to the plane */
-		plane = &mapplanes[ node->planenum ];
-		d = DotProduct( point, plane->normal ) - plane->dist;
-		
-		/* filter by this plane */
-		refs = 0;
-		if( d >= -ON_EPSILON )
-			refs += FilterPointIntoTree_r( point, ds, node->children[ 0 ] );
-		if( d <= ON_EPSILON )
-			refs += FilterPointIntoTree_r( point, ds, node->children[ 1 ] );
-		
-		/* return */
-		return refs;
-	}
-	
-	/* add a reference */
-	return AddReferenceToLeaf( ds, node );
-}
-
-
-
-/*
-FilterWindingIntoTree_r() - ydnar
-filters a winding from a drawsurface into the tree
-*/
-
-int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node )
-{
-	int				i, refs = 0;
-	plane_t			*p1, *p2;
-	vec4_t			plane1, plane2, reverse;
-	winding_t		*fat, *front, *back;
-	shaderInfo_t	*si;
-	
-	
-	/* get shaderinfo */
-	si = ds->shaderInfo;
-	
-	/* ydnar: is this the head node? */
-	if( node->parent == NULL && si != NULL &&
-		(si->mins[ 0 ] != 0.0f || si->maxs[ 0 ] != 0.0f ||
-		si->mins[ 1 ] != 0.0f || si->maxs[ 1 ] != 0.0f ||
-		si->mins[ 2 ] != 0.0f || si->maxs[ 2 ] != 0.0f) )
-	{
-		/* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */
-		/* note this winding is completely invalid (concave, nonplanar, etc) */
-		fat = AllocWinding( w->numpoints * 3 );
-		fat->numpoints = w->numpoints * 3;
-		for( i = 0; i < w->numpoints; i++ )
-		{
-			VectorCopy( w->p[ i ], fat->p[ i ] );
-			VectorAdd( w->p[ i ], si->mins, fat->p[ i * 2 ] );
-			VectorAdd( w->p[ i ], si->maxs, fat->p[ i * 3 ] );
-		}
-		
-		FreeWinding( w );
-		w = fat;
-	}
-	
-	/* is this a decision node? */
-	if( node->planenum != PLANENUM_LEAF )
-	{	
-		/* get node plane */
-		p1 = &mapplanes[ node->planenum ];
-		VectorCopy( p1->normal, plane1 );
-		plane1[ 3 ] = p1->dist;
-		
-		/* check if surface is planar */
-		if( ds->planeNum >= 0 )
-		{
-			/* get surface plane */
-			p2 = &mapplanes[ ds->planeNum ];
-			VectorCopy( p2->normal, plane2 );
-			plane2[ 3 ] = p2->dist;
-			
-			#if 1
-				/* invert surface plane */
-				VectorSubtract( vec3_origin, plane2, reverse );
-				reverse[ 3 ] = -plane2[ 3 ];
-				
-				/* compare planes */
-				if( DotProduct( plane1, plane2 ) > 0.999f && fabs( plane1[ 3 ] - plane2[ 3 ] ) < 0.001f )
-					return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] );
-				if( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f )
-					return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] );
-			#else
-				/* the drawsurf might have an associated plane, if so, force a filter here */
-				if( ds->planeNum == node->planenum )
-					return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] );
-				if( ds->planeNum == (node->planenum ^ 1) )
-					return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] );
-			#endif
-		}
-		
-		/* clip the winding by this plane */
-		ClipWindingEpsilon( w, plane1, plane1[ 3 ], ON_EPSILON, &front, &back );
-		
-		/* filter by this plane */
-		refs = 0;
-		if( front != NULL )
-			refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] );
-		if( back != NULL )
-			refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] );
-		FreeWinding( w );
-		
-		/* return */
-		return refs;
-	}
-	
-	/* add a reference */
-	return AddReferenceToLeaf( ds, node );
-}
-
-
-
-/*
-FilterFaceIntoTree()
-filters a planar winding face drawsurface into the bsp tree
-*/
-
-int	FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree )
-{
-	winding_t	*w;
-	int			refs = 0;
-	
-	
-	/* make a winding and filter it into the tree */
-	w = WindingFromDrawSurf( ds );
-	refs = FilterWindingIntoTree_r( w, ds, tree->headnode );
-	
-	/* return */
-	return refs;
-}
-
-
-
-/*
-FilterPatchIntoTree()
-subdivides a patch into an approximate curve and filters it into the tree
-*/
-
-#define	FILTER_SUBDIVISION		8
-
-static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree )
-{
-	int					i, x, y, refs;
-	mesh_t				src, *mesh;
-	winding_t			*w;
-	
-	
-	/* subdivide the surface */
-	src.width = ds->patchWidth;
-	src.height = ds->patchHeight;
-	src.verts = ds->verts;
-	mesh = SubdivideMesh( src, FILTER_SUBDIVISION, 32 );
-	
-	
-	/* filter each quad into the tree (fixme: use new patch x-triangulation code?) */
-	refs = 0;
-	for( y = 0; y < (mesh->height - 1); y++ )
-	{
-		for( x = 0; x < (mesh->width - 1); x++ )
-		{
-			/* triangle 1 */
-			w = AllocWinding( 3 );
-			w->numpoints = 3;
-			VectorCopy( mesh->verts[ y * mesh->width + x ].xyz, w->p[ 0 ] );
-			VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 1 ] );
-			VectorCopy( mesh->verts[ (y + 1) * mesh->width + x ].xyz, w->p[ 2 ] );
-			refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
-			
-			/* triangle 2 */
-			w = AllocWinding( 3 );
-			w->numpoints = 3;
-			VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 0 ] );
-			VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x + 1 ].xyz, w->p[ 1 ] );
-			VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x ].xyz, w->p[ 2 ] );
-			refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
-		}
-	}
-	
-	/* use point filtering as well */
-	for( i = 0; i < (mesh->width * mesh->height); i++ )
-		refs += FilterPointIntoTree_r( mesh->verts[ i ].xyz, ds, tree->headnode );
-	
-	/* free the subdivided mesh and return */
-	FreeMesh( mesh );
-	return refs;
-}
-
-
-
-/*
-FilterTrianglesIntoTree()
-filters a triangle surface (meta, model) into the bsp
-*/
-
-static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree )
-{
-	int			i, refs;
-	winding_t	*w;
-	
-	
-	/* ydnar: gs mods: this was creating bogus triangles before */
-	refs = 0;
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		/* error check */
-		if( ds->indexes[ i ] >= ds->numVerts ||
-			ds->indexes[ i + 1 ] >= ds->numVerts ||
-			ds->indexes[ i + 2 ] >= ds->numVerts )
-			Error( "Index %d greater than vertex count %d", ds->indexes[ i ], ds->numVerts );
-		
-		/* make a triangle winding and filter it into the tree */
-		w = AllocWinding( 3 );
-		w->numpoints = 3;
-		VectorCopy( ds->verts[ ds->indexes[ i ] ].xyz, w->p[ 0 ] );
-		VectorCopy( ds->verts[ ds->indexes[ i + 1 ] ].xyz, w->p[ 1 ] );
-		VectorCopy( ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] );
-		refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
-	}
-	
-	/* use point filtering as well */
-	for( i = 0; i < ds->numVerts; i++ )
-		refs += FilterPointIntoTree_r( ds->verts[ i ].xyz, ds, tree->headnode );
-
-	return refs;
-}
-
-
-
-/*
-FilterFoliageIntoTree()
-filters a foliage surface (wolf et/splash damage)
-*/
-
-static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree )
-{
-	int				f, i, refs;
-	bspDrawVert_t	*instance;
-	vec3_t			xyz;
-	winding_t		*w;
-	
-	
-	/* walk origin list */
-	refs = 0;
-	for( f = 0; f < ds->numFoliageInstances; f++ )
-	{
-		/* get instance */
-		instance = ds->verts + ds->patchHeight + f;
-		
-		/* walk triangle list */
-		for( i = 0; i < ds->numIndexes; i += 3 )
-		{
-			/* error check */
-			if( ds->indexes[ i ] >= ds->numVerts ||
-				ds->indexes[ i + 1 ] >= ds->numVerts ||
-				ds->indexes[ i + 2 ] >= ds->numVerts )
-				Error( "Index %d greater than vertex count %d", ds->indexes[ i ], ds->numVerts );
-			
-			/* make a triangle winding and filter it into the tree */
-			w = AllocWinding( 3 );
-			w->numpoints = 3;
-			VectorAdd( instance->xyz, ds->verts[ ds->indexes[ i ] ].xyz, w->p[ 0 ] );
-			VectorAdd( instance->xyz, ds->verts[ ds->indexes[ i + 1 ] ].xyz, w->p[ 1 ] );
-			VectorAdd( instance->xyz, ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] );
-			refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
-		}
-		
-		/* use point filtering as well */
-		for( i = 0; i < (ds->numVerts - ds->numFoliageInstances); i++ )
-		{
-			VectorAdd( instance->xyz, ds->verts[ i ].xyz, xyz );
-			refs += FilterPointIntoTree_r( xyz, ds, tree->headnode );
-		}
-	}
-	
-	return refs;
-}
-
-
-
-/*
-FilterFlareIntoTree()
-simple point filtering for flare surfaces
-*/
-static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree )
-{
-	return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree->headnode );
-}
-
-
-
-/*
-EmitDrawVerts() - ydnar
-emits bsp drawverts from a map drawsurface
-*/
-
-void EmitDrawVerts( mapDrawSurface_t *ds, bspDrawSurface_t *out )
-{
-	int				i, k;
-	bspDrawVert_t	*dv;
-	shaderInfo_t	*si;
-	float			offset;
-	
-	
-	/* get stuff */
-	si = ds->shaderInfo;
-	offset = si->offset;
-	
-	/* copy the verts */
-	out->firstVert = numBSPDrawVerts;
-	out->numVerts = ds->numVerts;
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		/* allocate a new vert */
-		if( numBSPDrawVerts == MAX_MAP_DRAW_VERTS )
-			Error( "MAX_MAP_DRAW_VERTS" );
-		IncDrawVerts();
-		dv = &bspDrawVerts[ numBSPDrawVerts - 1 ];
-		
-		/* copy it */
-		memcpy( dv, &ds->verts[ i ], sizeof( *dv ) );
-		
-		/* offset? */
-		if( offset != 0.0f )
-			VectorMA( dv->xyz, offset, dv->normal, dv->xyz );
-		
-		/* expand model bounds
-		   necessary because of misc_model surfaces on entities
-		   note: does not happen on worldspawn as its bounds is only used for determining lightgrid bounds */
-		if( numBSPModels > 0 )
-			AddPointToBounds( dv->xyz, bspModels[ numBSPModels ].mins, bspModels[ numBSPModels ].maxs );
-		
-		/* debug color? */
-		if( debugSurfaces )
-		{
-			for( k = 0; k < MAX_LIGHTMAPS; k++ )
-				VectorCopy( debugColors[ (ds - mapDrawSurfs) % 12 ], dv->color[ k ] );
-		}
-	}
-}
-
-
-
-/*
-FindDrawIndexes() - ydnar
-this attempts to find a run of indexes in the bsp that match the given indexes
-this tends to reduce the size of the bsp index pool by 1/3 or more
-returns numIndexes + 1 if the search failed
-*/
-
-int FindDrawIndexes( int numIndexes, int *indexes )
-{
-	int		i, j, numTestIndexes;
-	
-	
-	/* dummy check */
-	if( numIndexes < 3 || numBSPDrawIndexes < numIndexes || indexes == NULL )
-		return numBSPDrawIndexes;
-	
-	/* set limit */
-	numTestIndexes = 1 + numBSPDrawIndexes - numIndexes;
-	
-	/* handle 3 indexes as a special case for performance */
-	if( numIndexes == 3 )
-	{
-		/* run through all indexes */
-		for( i = 0; i < numTestIndexes; i++ )
-		{
-			/* test 3 indexes */
-			if( indexes[ 0 ] == bspDrawIndexes[ i ] &&
-				indexes[ 1 ] == bspDrawIndexes[ i + 1 ] &&
-				indexes[ 2 ] == bspDrawIndexes[ i + 2 ] )
-			{
-				numRedundantIndexes += numIndexes;
-				return i;
-			}
-		}
-		
-		/* failed */
-		return numBSPDrawIndexes;
-	}
-	
-	/* handle 4 or more indexes */
-	for( i = 0; i < numTestIndexes; i++ )
-	{
-		/* test first 4 indexes */
-		if( indexes[ 0 ] == bspDrawIndexes[ i ] &&
-			indexes[ 1 ] == bspDrawIndexes[ i + 1 ] &&
-			indexes[ 2 ] == bspDrawIndexes[ i + 2 ] &&
-			indexes[ 3 ] == bspDrawIndexes[ i + 3 ] )
-		{
-			/* handle 4 indexes */
-			if( numIndexes == 4 )
-				return i;
-			
-			/* test the remainder */
-			for( j = 4; j < numIndexes; j++ )
-			{
-				if( indexes[ j ] != bspDrawIndexes[ i + j ] )
-					break;
-				else if( j == (numIndexes - 1) )
-				{
-					numRedundantIndexes += numIndexes;
-					return i;
-				}
-			}
-		}
-	}
-	
-	/* failed */
-	return numBSPDrawIndexes;
-}
-
-
-
-/*
-EmitDrawIndexes() - ydnar
-attempts to find an existing run of drawindexes before adding new ones
-*/
-
-void EmitDrawIndexes( mapDrawSurface_t *ds, bspDrawSurface_t *out )
-{
-	int			i;
-	
-	
-	/* attempt to use redundant indexing */
-	out->firstIndex = FindDrawIndexes( ds->numIndexes, ds->indexes );
-	out->numIndexes = ds->numIndexes;
-	if( out->firstIndex == numBSPDrawIndexes )
-	{
-		/* copy new unique indexes */
-		for( i = 0; i < ds->numIndexes; i++ )
-		{
-			if( numBSPDrawIndexes == MAX_MAP_DRAW_INDEXES )
-				Error( "MAX_MAP_DRAW_INDEXES" );
-			bspDrawIndexes[ numBSPDrawIndexes ] = ds->indexes[ i ];
-
-			/* validate the index */
-			if( ds->type != SURFACE_PATCH )
-			{
-				if( bspDrawIndexes[ numBSPDrawIndexes ] < 0 || bspDrawIndexes[ numBSPDrawIndexes ] >= ds->numVerts )
-				{
-					Sys_Printf( "WARNING: %d %s has invalid index %d (%d)\n",
-						numBSPDrawSurfaces,
-						ds->shaderInfo->shader,
-						bspDrawIndexes[ numBSPDrawIndexes ],
-						i );
-					bspDrawIndexes[ numBSPDrawIndexes ] = 0;
-				}
-			}
-			
-			/* increment index count */
-			numBSPDrawIndexes++;
-		}
-	}
-}
-
-
-
-
-/*
-EmitFlareSurface()
-emits a bsp flare drawsurface
-*/
-
-void EmitFlareSurface( mapDrawSurface_t *ds )
-{
-	int						i;
-	bspDrawSurface_t		*out;
-	
-	
-	/* ydnar: nuking useless flare drawsurfaces */
-	if( emitFlares == qfalse && ds->type != SURFACE_SHADER )
-		return;
-	
-	/* limit check */
-	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
-		Error( "MAX_MAP_DRAW_SURFS" );
-	
-	/* allocate a new surface */
-	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
-		Error( "MAX_MAP_DRAW_SURFS" );
-	out = &bspDrawSurfaces[ numBSPDrawSurfaces ];
-	ds->outputNum = numBSPDrawSurfaces;
-	numBSPDrawSurfaces++;
-	memset( out, 0, sizeof( *out ) );
-	
-	/* set it up */
-	out->surfaceType = MST_FLARE;
-	out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
-	out->fogNum = ds->fogNum;
-	
-	/* RBSP */
-	for( i = 0; i < MAX_LIGHTMAPS; i++ )
-	{
-		out->lightmapNum[ i ] = -3;
-		out->lightmapStyles[ i ] = LS_NONE;
-		out->vertexStyles[ i ] = LS_NONE;
-	}
-	out->lightmapStyles[ 0 ] = ds->lightStyle;
-	out->vertexStyles[ 0 ] = ds->lightStyle;
-	
-	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );			/* origin */
-	VectorCopy( ds->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );	/* color */
-	VectorCopy( ds->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
-	VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );	/* normal */
-	
-	/* add to count */
-	numSurfacesByType[ ds->type ]++;
-}
-
-
-
-/*
-EmitPatchSurface()
-emits a bsp patch drawsurface
-*/
-
-void EmitPatchSurface( mapDrawSurface_t *ds )
-{
-	int					i, j;
-	bspDrawSurface_t	*out;
-	int					surfaceFlags, contentFlags;
-	
-	
-	/* invert the surface if necessary */
-	if( ds->shaderInfo->invert )
-	{
-		bspDrawVert_t	*dv1, *dv2, temp;
-		
-
-		/* walk the verts, flip the normal */
-		for( i = 0; i < ds->numVerts; i++ )
-			VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal );
-		
-		/* walk the verts again, but this time reverse their order */
-		for( j = 0; j < ds->patchHeight; j++ )
-		{
-			for( i = 0; i < (ds->patchWidth / 2); i++ )
-			{
-				dv1 = &ds->verts[ j * ds->patchWidth + i ];
-				dv2 = &ds->verts[ j * ds->patchWidth + (ds->patchWidth - i - 1) ];
-				memcpy( &temp, dv1, sizeof( bspDrawVert_t ) );
-				memcpy( dv1, dv2, sizeof( bspDrawVert_t ) );
-				memcpy( dv2, &temp, sizeof( bspDrawVert_t ) );
-			}
-		}
-		
-		/* invert facing */
-		VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
-	}
-	
-	/* allocate a new surface */
-	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
-		Error( "MAX_MAP_DRAW_SURFS" );
-	out = &bspDrawSurfaces[ numBSPDrawSurfaces ];
-	ds->outputNum = numBSPDrawSurfaces;
-	numBSPDrawSurfaces++;
-	memset( out, 0, sizeof( *out ) );
-	
-	/* set it up */
-	out->surfaceType = MST_PATCH;
-	if( debugSurfaces )
-		out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL );
-	else if( patchMeta )
-	{
-		/* patch meta requires that we have nodraw patches for collision */
-		surfaceFlags = ds->shaderInfo->surfaceFlags;
-		contentFlags = ds->shaderInfo->contentFlags;
-		ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, NULL );
-		ApplySurfaceParm( "pointlight", &contentFlags, &surfaceFlags, NULL );
-		
-		/* we don't want this patch getting lightmapped */
-		VectorClear( ds->lightmapVecs[ 2 ] );
-		VectorClear( ds->lightmapAxis );
-		ds->sampleSize = 0;
-
-		/* emit the new fake shader */
-		out->shaderNum = EmitShader( ds->shaderInfo->shader, &contentFlags, &surfaceFlags );
-	}
-	else
-		out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
-	out->patchWidth = ds->patchWidth;
-	out->patchHeight = ds->patchHeight;
-	out->fogNum = ds->fogNum;
-	
-	/* RBSP */
-	for( i = 0; i < MAX_LIGHTMAPS; i++ )
-	{
-		out->lightmapNum[ i ] = -3;
-		out->lightmapStyles[ i ] = LS_NONE;
-		out->vertexStyles[ i ] = LS_NONE;
-	}
-	out->lightmapStyles[ 0 ] = LS_NORMAL;
-	out->vertexStyles[ 0 ] = LS_NORMAL;
-	
-	/* ydnar: gs mods: previously, the lod bounds were stored in lightmapVecs[ 0 ] and [ 1 ], moved to bounds[ 0 ] and [ 1 ] */
-	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
-	VectorCopy( ds->bounds[ 0 ], out->lightmapVecs[ 0 ] );
-	VectorCopy( ds->bounds[ 1 ], out->lightmapVecs[ 1 ] );
-	VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
-	
-	/* ydnar: gs mods: clear out the plane normal */
-	if( ds->planar == qfalse )
-		VectorClear( out->lightmapVecs[ 2 ] );
-	
-	/* emit the verts and indexes */
-	EmitDrawVerts( ds, out );
-	EmitDrawIndexes( ds, out );
-	
-	/* add to count */
-	numSurfacesByType[ ds->type ]++;
-}
-
-
-
-/*
-OptimizeTriangleSurface() - ydnar
-optimizes the vertex/index data in a triangle surface
-*/
-
-#define VERTEX_CACHE_SIZE	16
-
-static void OptimizeTriangleSurface( mapDrawSurface_t *ds )
-{
-	int		i, j, k, temp, first, best, bestScore, score;
-	int		vertexCache[ VERTEX_CACHE_SIZE + 1 ];	/* one more for optimizing insert */
-	int		*indexes;
-	
-	
-	/* certain surfaces don't get optimized */
-	if( ds->numIndexes <= VERTEX_CACHE_SIZE ||
-		ds->shaderInfo->autosprite )
-		return;
-	
-	/* create index scratch pad */
-	indexes = safe_malloc( ds->numIndexes * sizeof( *indexes ) );
-	memcpy( indexes, ds->indexes, ds->numIndexes * sizeof( *indexes ) );
-	
-	/* setup */
-	for( i = 0; i <= VERTEX_CACHE_SIZE && i < ds->numIndexes; i++ )
-		vertexCache[ i ] = indexes[ i ];
-	
-	/* add triangles in a vertex cache-aware order */
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		/* find best triangle given the current vertex cache */
-		first = -1;
-		best = -1;
-		bestScore = -1;
-		for( j = 0; j < ds->numIndexes; j += 3 )
-		{
-			/* valid triangle? */
-			if( indexes[ j ] != -1 )
-			{
-				/* set first if necessary */
-				if( first < 0 )
-					first = j;
-				
-				/* score the triangle */
-				score = 0;
-				for( k = 0; k < VERTEX_CACHE_SIZE; k++ )
-				{
-					if( indexes[ j ] == vertexCache[ k ] || indexes[ j + 1 ] == vertexCache[ k ] || indexes[ j + 2 ] == vertexCache[ k ] )
-						score++;
-				}
-				
-				/* better triangle? */
-				if( score > bestScore )
-				{
-					bestScore = score;
-					best = j;
-				}
-				
-				/* a perfect score of 3 means this triangle's verts are already present in the vertex cache */
-				if( score == 3 )
-					break;
-			}
-		}
-		
-		/* check if no decent triangle was found, and use first available */
-		if( best < 0 )
-			best = first;
-		
-		/* valid triangle? */
-		if( best >= 0 )
-		{
-			/* add triangle to vertex cache */
-			for( j = 0; j < 3; j++ )
-			{
-				for( k = 0; k < VERTEX_CACHE_SIZE; k++ )
-				{
-					if( indexes[ best + j ] == vertexCache[ k ] )
-						break;
-				}
-				
-				if( k >= VERTEX_CACHE_SIZE )
-				{
-					/* pop off top of vertex cache */
-					for( k = VERTEX_CACHE_SIZE; k > 0; k-- )
-						vertexCache[ k ] = vertexCache[ k - 1 ];
-					
-					/* add vertex */
-					vertexCache[ 0 ] = indexes[ best + j ];
-				}
-			}
-			
-			/* add triangle to surface */
-			ds->indexes[ i ] = indexes[ best ];
-			ds->indexes[ i + 1 ] = indexes[ best + 1 ];
-			ds->indexes[ i + 2 ] = indexes[ best + 2 ];
-			
-			/* clear from input pool */
-			indexes[ best ] = -1;
-			indexes[ best + 1 ] = -1;
-			indexes[ best + 2 ] = -1;
-			
-			/* sort triangle windings (312 -> 123) */
-			while( ds->indexes[ i ] > ds->indexes[ i + 1 ] || ds->indexes[ i ] > ds->indexes[ i + 2 ] )
-			{
-				temp = ds->indexes[ i ];
-				ds->indexes[ i ] = ds->indexes[ i + 1 ];
-				ds->indexes[ i + 1 ] = ds->indexes[ i + 2 ];
-				ds->indexes[ i + 2 ] = temp;
-			}
-		}
-	}
-	
-	/* clean up */
-	free( indexes );
-}
-
-
-
-/*
-EmitTriangleSurface()
-creates a bsp drawsurface from arbitrary triangle surfaces
-*/
-
-static void EmitTriangleSurface( mapDrawSurface_t *ds )
-{
-	int						i, temp;
-	bspDrawSurface_t		*out;
-	
-	
-	/* invert the surface if necessary */
-	if( ds->shaderInfo->invert )
-	{
-		/* walk the indexes, reverse the triangle order */
-		for( i = 0; i < ds->numIndexes; i += 3 )
-		{
-			temp = ds->indexes[ i ];
-			ds->indexes[ i ] = ds->indexes[ i + 1 ];
-			ds->indexes[ i + 1 ] = temp;
-		}
-		
-		/* walk the verts, flip the normal */
-		for( i = 0; i < ds->numVerts; i++ )
-			VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal );
-		
-		/* invert facing */
-		VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
-	}
-	
-	/* allocate a new surface */
-	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
-		Error( "MAX_MAP_DRAW_SURFS" );
-	out = &bspDrawSurfaces[ numBSPDrawSurfaces ];
-	ds->outputNum = numBSPDrawSurfaces;
-	numBSPDrawSurfaces++;
-	memset( out, 0, sizeof( *out ) );
-	
-	/* ydnar/sd: handle wolf et foliage surfaces */
-	if( ds->type == SURFACE_FOLIAGE )
-		out->surfaceType = MST_FOLIAGE;
-	
-	/* ydnar: gs mods: handle lightmapped terrain (force to planar type) */
-	//%	else if( VectorLength( ds->lightmapAxis ) <= 0.0f || ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FOGHULL || debugSurfaces )
-	else if( (VectorLength( ds->lightmapAxis ) <= 0.0f && ds->planar == qfalse) || ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FOGHULL || debugSurfaces )
-		out->surfaceType = MST_TRIANGLE_SOUP;
-	
-	/* set to a planar face */
-	else
-		out->surfaceType = MST_PLANAR;
-	
-	/* set it up */
-	if( debugSurfaces )
-		out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL );
-	else
-		out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
-	out->patchWidth = ds->patchWidth;
-	out->patchHeight = ds->patchHeight;
-	out->fogNum = ds->fogNum;
-	
-	/* debug inset (push each triangle vertex towards the center of each triangle it is on */
-	if( debugInset )
-	{
-		bspDrawVert_t	*a, *b, *c;
-		vec3_t			cent, dir;
-
-		
-		/* walk triangle list */
-		for( i = 0; i < ds->numIndexes; i += 3 )
-		{
-			/* get verts */
-			a = &ds->verts[ ds->indexes[ i ] ];
-			b = &ds->verts[ ds->indexes[ i + 1 ] ];
-			c = &ds->verts[ ds->indexes[ i + 2 ] ];
-			
-			/* calculate centroid */
-			VectorCopy( a->xyz, cent );
-			VectorAdd( cent, b->xyz, cent );
-			VectorAdd( cent, c->xyz, cent );
-			VectorScale( cent, 1.0f / 3.0f, cent );
-			
-			/* offset each vertex */
-			VectorSubtract( cent, a->xyz, dir );
-			VectorNormalize( dir, dir );
-			VectorAdd( a->xyz, dir, a->xyz );
-			VectorSubtract( cent, b->xyz, dir );
-			VectorNormalize( dir, dir );
-			VectorAdd( b->xyz, dir, b->xyz );
-			VectorSubtract( cent, c->xyz, dir );
-			VectorNormalize( dir, dir );
-			VectorAdd( c->xyz, dir, c->xyz );
-		}
-	}
-	
-	/* RBSP */
-	for( i = 0; i < MAX_LIGHTMAPS; i++ )
-	{
-		out->lightmapNum[ i ] = -3;
-		out->lightmapStyles[ i ] = LS_NONE;
-		out->vertexStyles[ i ] = LS_NONE;
-	}
-	out->lightmapStyles[ 0 ] = LS_NORMAL;
-	out->vertexStyles[ 0 ] = LS_NORMAL;
-	
-	/* lightmap vectors (lod bounds for patches */
-	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
-	VectorCopy( ds->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
-	VectorCopy( ds->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
-	VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
-	
-	/* ydnar: gs mods: clear out the plane normal */
-	if( ds->planar == qfalse )
-		VectorClear( out->lightmapVecs[ 2 ] );
-	
-	/* optimize the surface's triangles */
-	OptimizeTriangleSurface( ds );
-	
-	/* emit the verts and indexes */
-	EmitDrawVerts( ds, out );
-	EmitDrawIndexes( ds, out );
-	
-	/* add to count */
-	numSurfacesByType[ ds->type ]++;
-}
-
-
-
-/*
-EmitFaceSurface()
-emits a bsp planar winding (brush face) drawsurface
-*/
-
-static void EmitFaceSurface( mapDrawSurface_t *ds )
-{
-	/* strip/fan finding was moved elsewhere */
-	StripFaceSurface( ds );
-	EmitTriangleSurface( ds );
-}
-
-
-
-/*
-MakeDebugPortalSurfs_r() - ydnar
-generates drawsurfaces for passable portals in the bsp
-*/
-
-static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si )
-{
-	int					i, k, c, s;	
-	portal_t			*p;
-	winding_t			*w;
-	mapDrawSurface_t	*ds;
-	bspDrawVert_t		*dv;
-	
-	
-	/* recurse if decision node */
-	if( node->planenum != PLANENUM_LEAF)
-	{
-		MakeDebugPortalSurfs_r( node->children[ 0 ], si );
-		MakeDebugPortalSurfs_r( node->children[ 1 ], si );
-		return;
-	}
-	
-	/* don't bother with opaque leaves */
-	if( node->opaque )
-		return;
-	
-	/* walk the list of portals */
-	for( c = 0, p = node->portals; p != NULL; c++, p = p->next[ s ] )
-	{
-		/* get winding and side even/odd */
-		w = p->winding;
-		s = (p->nodes[ 1 ] == node);
-		
-		/* is this a valid portal for this leaf? */
-		if( w && p->nodes[ 0 ] == node )
-		{
-			/* is this portal passable? */
-			if( PortalPassable( p ) == qfalse )
-				continue;
-			
-			/* check max points */
-			if( w->numpoints > 64 )
-				Error( "MakePortalSurfs_r: w->numpoints = %d", w->numpoints );
-			
-			/* allocate a drawsurface */
-			ds = AllocDrawSurface( SURFACE_FACE );
-			ds->shaderInfo = si;
-			ds->planar = qtrue;
-			ds->sideRef = AllocSideRef( p->side, NULL );
-			ds->planeNum = FindFloatPlane( p->plane.normal, p->plane.dist, 0, NULL );
-			VectorCopy( p->plane.normal, ds->lightmapVecs[ 2 ] );
-			ds->fogNum = -1;
-			ds->numVerts = w->numpoints;
-			ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-			memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
-			
-			/* walk the winding */
-			for( i = 0; i < ds->numVerts; i++ )
-			{
-				/* get vert */
-				dv = ds->verts + i;
-				
-				/* set it */
-				VectorCopy( w->p[ i ], dv->xyz );
-				VectorCopy( p->plane.normal, dv->normal );
-				dv->st[ 0 ] = 0;
-				dv->st[ 1 ] = 0;
-				for( k = 0; k < MAX_LIGHTMAPS; k++ )
-				{
-					VectorCopy( debugColors[ c % 12 ], dv->color[ k ] );
-					dv->color[ k ][ 3 ] = 32;
-				}
-			}
-		}
-	}
-}
-
-
-
-/*
-MakeDebugPortalSurfs() - ydnar
-generates drawsurfaces for passable portals in the bsp
-*/
-
-void MakeDebugPortalSurfs( tree_t *tree )
-{
-	shaderInfo_t	*si;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- MakeDebugPortalSurfs ---\n" );
-	
-	/* get portal debug shader */
-	si = ShaderInfoForShader( "debugportals" );
-	
-	/* walk the tree */
-	MakeDebugPortalSurfs_r( tree->headnode, si );
-}
-
-
-
-/*
-MakeFogHullSurfs()
-generates drawsurfaces for a foghull (this MUST use a sky shader)
-*/
-
-void MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader )
-{
-	shaderInfo_t		*si;
-	mapDrawSurface_t	*ds;
-	vec3_t				fogMins, fogMaxs;
-	int					i, indexes[] =
-						{
-							0, 1, 2, 0, 2, 3,
-							4, 7, 5, 5, 7, 6,
-							1, 5, 6, 1, 6, 2,
-							0, 4, 5, 0, 5, 1,
-							2, 6, 7, 2, 7, 3,
-							3, 7, 4, 3, 4, 0
-						};
-
-	
-	/* dummy check */
-	if( shader == NULL || shader[ 0 ] == '\0' )
-		return;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- MakeFogHullSurfs ---\n" );
-	
-	/* get hull bounds */
-	VectorCopy( mapMins, fogMins );
-	VectorCopy( mapMaxs, fogMaxs );
-	for( i = 0; i < 3; i++ )
-	{
-		fogMins[ i ] -= 128;
-		fogMaxs[ i ] += 128;
-	}
-	
-	/* get foghull shader */
-	si = ShaderInfoForShader( shader );
-	
-	/* allocate a drawsurface */
-	ds = AllocDrawSurface( SURFACE_FOGHULL );
-	ds->shaderInfo = si;
-	ds->fogNum = -1;
-	ds->numVerts = 8;
-	ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
-	memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
-	ds->numIndexes = 36;
-	ds->indexes = safe_malloc( ds->numIndexes * sizeof( *ds->indexes ) );
-	memset( ds->indexes, 0, ds->numIndexes * sizeof( *ds->indexes ) );
-	
-	/* set verts */
-	VectorSet( ds->verts[ 0 ].xyz, fogMins[ 0 ], fogMins[ 1 ], fogMins[ 2 ] );
-	VectorSet( ds->verts[ 1 ].xyz, fogMins[ 0 ], fogMaxs[ 1 ], fogMins[ 2 ] );
-	VectorSet( ds->verts[ 2 ].xyz, fogMaxs[ 0 ], fogMaxs[ 1 ], fogMins[ 2 ] );
-	VectorSet( ds->verts[ 3 ].xyz, fogMaxs[ 0 ], fogMins[ 1 ], fogMins[ 2 ] );
-	
-	VectorSet( ds->verts[ 4 ].xyz, fogMins[ 0 ], fogMins[ 1 ], fogMaxs[ 2 ] );
-	VectorSet( ds->verts[ 5 ].xyz, fogMins[ 0 ], fogMaxs[ 1 ], fogMaxs[ 2 ] );
-	VectorSet( ds->verts[ 6 ].xyz, fogMaxs[ 0 ], fogMaxs[ 1 ], fogMaxs[ 2 ] );
-	VectorSet( ds->verts[ 7 ].xyz, fogMaxs[ 0 ], fogMins[ 1 ], fogMaxs[ 2 ] );
-	
-	/* set indexes */
-	memcpy( ds->indexes, indexes, ds->numIndexes * sizeof( *ds->indexes ) );
-}
-
-
-
-/*
-BiasSurfaceTextures()
-biases a surface's texcoords as close to 0 as possible
-*/
-
-void BiasSurfaceTextures( mapDrawSurface_t *ds )
-{
-	int		i;
-	
-	
-	/* calculate the surface texture bias */
-	CalcSurfaceTextureRange( ds );
-	
-	/* don't bias globaltextured shaders */
-	if( ds->shaderInfo->globalTexture )
-		return;
-	
-	/* bias the texture coordinates */
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		ds->verts[ i ].st[ 0 ] += ds->bias[ 0 ];
-		ds->verts[ i ].st[ 1 ] += ds->bias[ 1 ];
-	}
-}
-
-
-
-/*
-AddSurfaceModelsToTriangle_r()
-adds models to a specified triangle, returns the number of models added
-*/
-
-int AddSurfaceModelsToTriangle_r( mapDrawSurface_t *ds, surfaceModel_t *model, bspDrawVert_t **tri )
-{
-	bspDrawVert_t	mid, *tri2[ 3 ];
-	int				max, n, localNumSurfaceModels;
-	
-	
-	/* init */
-	localNumSurfaceModels = 0;
-	
-	/* subdivide calc */
-	{
-		int			i;
-		float		*a, *b, dx, dy, dz, dist, maxDist;
-		
-		
-		/* find the longest edge and split it */
-		max = -1;
-		maxDist = 0.0f;
-		for( i = 0; i < 3; i++ )
-		{
-			/* get verts */
-			a = tri[ i ]->xyz;
-			b = tri[ (i + 1) % 3 ]->xyz;
-			
-			/* get dists */
-			dx = a[ 0 ] - b[ 0 ];
-			dy = a[ 1 ] - b[ 1 ];
-			dz = a[ 2 ] - b[ 2 ];
-			dist = (dx * dx) + (dy * dy) + (dz * dz);
-			
-			/* longer? */
-			if( dist > maxDist )
-			{
-				maxDist = dist;
-				max = i;
-			}
-		}
-		
-		/* is the triangle small enough? */
-		if( max < 0 || maxDist <= (model->density * model->density) )
-		{
-			float	odds, r, angle;
-			vec3_t	origin, normal, scale, axis[ 3 ], angles;
-			m4x4_t	transform, temp;
-
-			
-			/* roll the dice (model's odds scaled by vertex alpha) */
-			odds = model->odds * (tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ]) / 765.0f;
-			r = Random();
-			if( r > model->odds )
-				return 0;
-			
-			/* calculate scale */
-			r = model->minScale + Random() * (model->maxScale - model->minScale);
-			VectorSet( scale, r, r, r );
-			
-			/* calculate angle */
-			angle = model->minAngle + Random() * (model->maxAngle - model->minAngle);
-			
-			/* calculate average origin */
-			VectorCopy( tri[ 0 ]->xyz, origin );
-			VectorAdd( origin, tri[ 1 ]->xyz, origin );
-			VectorAdd( origin, tri[ 2 ]->xyz, origin );
-			VectorScale( origin, (1.0f / 3.0f), origin );
-			
-			/* clear transform matrix */
-			m4x4_identity( transform );
-
-			/* handle oriented models */
-			if( model->oriented )
-			{
-				/* set angles */
-				VectorSet( angles, 0.0f, 0.0f, angle );
-				
-				/* calculate average normal */
-				VectorCopy( tri[ 0 ]->normal, normal );
-				VectorAdd( normal, tri[ 1 ]->normal, normal );
-				VectorAdd( normal, tri[ 2 ]->normal, normal );
-				if( VectorNormalize( normal, axis[ 2 ] ) == 0.0f )
-					VectorCopy( tri[ 0 ]->normal, axis[ 2 ] );
-				
-				/* make perpendicular vectors */
-				MakeNormalVectors( axis[ 2 ], axis[ 1 ], axis[ 0 ] );
-				
-				/* copy to matrix */
-				m4x4_identity( temp );
-				temp[ 0 ] = axis[ 0 ][ 0 ];	temp[ 1 ] = axis[ 0 ][ 1 ];	temp[ 2 ] = axis[ 0 ][ 2 ];
-				temp[ 4 ] = axis[ 1 ][ 0 ];	temp[ 5 ] = axis[ 1 ][ 1 ];	temp[ 6 ] = axis[ 1 ][ 2 ];
-				temp[ 8 ] = axis[ 2 ][ 0 ];	temp[ 9 ] = axis[ 2 ][ 1 ];	temp[ 10 ] = axis[ 2 ][ 2 ];
-				
-				/* scale */
-				m4x4_scale_by_vec3( temp, scale );
-				
-				/* rotate around z axis */
-				m4x4_rotate_by_vec3( temp, angles, eXYZ );
-				
-				/* translate */
-				m4x4_translate_by_vec3( transform, origin );
-				
-				/* tranform into axis space */
-				m4x4_multiply_by_m4x4( transform, temp );
-			}
-			
-			/* handle z-up models */
-			else
-			{
-				/* set angles */
-				VectorSet( angles, 0.0f, 0.0f, angle );
-				
-				/* set matrix */
-				m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
-			}
-			
-			/* insert the model */
-			InsertModel( (char *) model->model, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale );
-			
-			/* return to sender */
-			return 1;
-		}
-	}
-	
-	/* split the longest edge and map it */
-	LerpDrawVert( tri[ max ], tri[ (max + 1) % 3 ], &mid );
-	
-	/* recurse to first triangle */
-	VectorCopy( tri, tri2 );
-	tri2[ max ] = &mid;
-	n = AddSurfaceModelsToTriangle_r( ds, model, tri2 );
-	if( n < 0 )
-		return n;
-	localNumSurfaceModels += n;
-	
-	/* recurse to second triangle */
-	VectorCopy( tri, tri2 );
-	tri2[ (max + 1) % 3 ] = &mid;
-	n = AddSurfaceModelsToTriangle_r( ds, model, tri2 );
-	if( n < 0 )
-		return n;
-	localNumSurfaceModels += n;
-	
-	/* return count */
-	return localNumSurfaceModels;
-}
-
-
-
-/*
-AddSurfaceModels()
-adds a surface's shader models to the surface
-*/
-
-int AddSurfaceModels( mapDrawSurface_t *ds )
-{
-	surfaceModel_t	*model;
-	int				i, x, y, n, pw[ 5 ], r, localNumSurfaceModels, iterations;
-	mesh_t			src, *mesh, *subdivided;
-	bspDrawVert_t	centroid, *tri[ 3 ];
-	float			alpha;
-	
-	
-	/* dummy check */
-	if( ds == NULL || ds->shaderInfo == NULL || ds->shaderInfo->surfaceModel == NULL )
-		return 0;
-	
-	/* init */
-	localNumSurfaceModels = 0;
-	
-	/* walk the model list */
-	for( model = ds->shaderInfo->surfaceModel; model != NULL; model = model->next )
-	{
-		/* switch on type */
-		switch( ds->type )
-		{
-			/* handle brush faces and decals */
-			case SURFACE_FACE:
-			case SURFACE_DECAL:
-				/* calculate centroid */
-				memset( &centroid, 0, sizeof( centroid ) );
-				alpha = 0.0f;
-				
-				/* walk verts */
-				for( i = 0; i < ds->numVerts; i++ )
-				{
-					VectorAdd( centroid.xyz, ds->verts[ i ].xyz, centroid.xyz );
-					VectorAdd( centroid.normal, ds->verts[ i ].normal, centroid.normal );
-					centroid.st[ 0 ] += ds->verts[ i ].st[ 0 ];
-					centroid.st[ 1 ] += ds->verts[ i ].st[ 1 ];
-					alpha += ds->verts[ i ].color[ 0 ][ 3 ];
-				}
-				
-				/* average */
-				centroid.xyz[ 0 ] /= ds->numVerts;
-				centroid.xyz[ 1 ] /= ds->numVerts;
-				centroid.xyz[ 2 ] /= ds->numVerts;
-				if( VectorNormalize( centroid.normal, centroid.normal ) == 0.0f )
-					VectorCopy( ds->verts[ 0 ].normal, centroid.normal );
-				centroid.st[ 0 ]  /= ds->numVerts;
-				centroid.st[ 1 ]  /= ds->numVerts;
-				alpha /= ds->numVerts;
-				centroid.color[ 0 ][ 0 ] = 0xFF;
-				centroid.color[ 0 ][ 1 ] = 0xFF;
-				centroid.color[ 0 ][ 2 ] = 0xFF;
-				centroid.color[ 0 ][ 2 ] = (alpha > 255.0f ? 0xFF : alpha);
-				
-				/* head vert is centroid */
-				tri[ 0 ] = &centroid;
-				
-				/* walk fanned triangles */
-				for( i = 0; i < ds->numVerts; i++ )
-				{
-					/* set triangle */
-					tri[ 1 ] = &ds->verts[ i ];
-					tri[ 2 ] = &ds->verts[ (i + 1) % ds->numVerts ];
-					
-					/* create models */
-					n = AddSurfaceModelsToTriangle_r( ds, model, tri );
-					if( n < 0 )
-						return n;
-					localNumSurfaceModels += n;
-				}
-				break;
-			
-			/* handle patches */
-			case SURFACE_PATCH:
-				/* subdivide the surface */
-				src.width = ds->patchWidth;
-				src.height = ds->patchHeight;
-				src.verts = ds->verts;
-				//%	subdivided = SubdivideMesh( src, 8.0f, 512 );
-				iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
-				subdivided = SubdivideMesh2( src, iterations );
-				
-				/* fit it to the curve and remove colinear verts on rows/columns */
-				PutMeshOnCurve( *subdivided );
-				mesh = RemoveLinearMeshColumnsRows( subdivided );
-				FreeMesh( subdivided );
-				
-				/* subdivide each quad to place the models */
-				for( y = 0; y < (mesh->height - 1); y++ )
-				{
-					for( x = 0; x < (mesh->width - 1); x++ )
-					{
-						/* set indexes */
-						pw[ 0 ] = x + (y * mesh->width);
-						pw[ 1 ] = x + ((y + 1) * mesh->width);
-						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-						pw[ 3 ] = x + 1 + (y * mesh->width);
-						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-						
-						/* set radix */
-						r = (x + y) & 1;
-						
-						/* triangle 1 */
-						tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
-						tri[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
-						tri[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
-						n = AddSurfaceModelsToTriangle_r( ds, model, tri );
-						if( n < 0 )
-							return n;
-						localNumSurfaceModels += n;
-						
-						/* triangle 2 */
-						tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
-						tri[ 1 ] = &mesh->verts[ pw[ r + 2 ] ];
-						tri[ 2 ] = &mesh->verts[ pw[ r + 3 ] ];
-						n = AddSurfaceModelsToTriangle_r( ds, model, tri );
-						if( n < 0 )
-							return n;
-						localNumSurfaceModels += n;
-					}
-				}
-				
-				/* free the subdivided mesh */
-				FreeMesh( mesh );
-				break;
-			
-			/* handle triangle surfaces */
-			case SURFACE_TRIANGLES:
-			case SURFACE_FORCED_META:
-			case SURFACE_META:
-				/* walk the triangle list */
-				for( i = 0; i < ds->numIndexes; i += 3 )
-				{
-					tri[ 0 ] = &ds->verts[ ds->indexes[ i ] ];
-					tri[ 1 ] = &ds->verts[ ds->indexes[ i + 1 ] ];
-					tri[ 2 ] = &ds->verts[ ds->indexes[ i + 2 ] ];
-					n = AddSurfaceModelsToTriangle_r( ds, model, tri );
-					if( n < 0 )
-						return n;
-					localNumSurfaceModels += n;
-				}
-				break;
-			
-			/* no support for flares, foghull, etc */
-			default:
-				break;
-		}
-	}
-	
-	/* return count */
-	return localNumSurfaceModels;
-}
-
-
-
-/*
-AddEntitySurfaceModels() - ydnar
-adds surfacemodels to an entity's surfaces
-*/
-
-void AddEntitySurfaceModels( entity_t *e )
-{
-	int		i;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- AddEntitySurfaceModels ---\n" );
-	
-	/* walk the surface list */
-	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
-		numSurfaceModels += AddSurfaceModels( &mapDrawSurfs[ i ] );
-}
-
-
-
-/*
-FilterDrawsurfsIntoTree()
-upon completion, all drawsurfs that actually generate a reference
-will have been emited to the bspfile arrays, and the references
-will have valid final indexes
-*/
-
-void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree )
-{
-	int					i, j;
-	mapDrawSurface_t	*ds;
-	shaderInfo_t		*si;
-	vec3_t				origin, mins, maxs;
-	int					refs;
-	int					numSurfs, numRefs, numSkyboxSurfaces;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- FilterDrawsurfsIntoTree ---\n" );
-	
-	/* filter surfaces into the tree */
-	numSurfs = 0;
-	numRefs = 0;
-	numSkyboxSurfaces = 0;
-	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
-	{
-		/* get surface and try to early out */
-		ds = &mapDrawSurfs[ i ];
-		if( ds->numVerts == 0 && ds->type != SURFACE_FLARE && ds->type != SURFACE_SHADER )
-			continue;
-		
-		/* get shader */
-		si = ds->shaderInfo;
-		
-		/* ydnar: skybox surfaces are special */
-		if( ds->skybox )
-		{
-			refs = AddReferenceToTree_r( ds, tree->headnode, qtrue );
-			ds->skybox = qfalse;
-		}
-		else
-		{
-			/* refs initially zero */
-			refs = 0;
-			
-			/* ydnar: apply alphamod */
-			AlphaMod( ds->shaderInfo->alphaMod, ds->numVerts, ds->verts );
-			
-			/* apply texture coordinate mods */
-			for( j = 0; j < ds->numVerts; j++ )
-				TcMod( si->mod, ds->verts[ j ].st );
-			
-			/* ydnar: make fur surfaces */
-			if( si->furNumLayers > 0 )
-				Fur( ds );
-			
-			/* ydnar/sd: make foliage surfaces */
-			if( si->foliage != NULL )
-				Foliage( ds );
-			
-			/* create a flare surface if necessary */
-			if( si->flareShader[ 0 ] )
-				AddSurfaceFlare( ds, e->origin );
-			
-			/* ydnar: don't emit nodraw surfaces (like nodraw fog) */
-			if( si != NULL && (si->compileFlags & C_NODRAW) && ds->type != SURFACE_PATCH )
-				continue;
-			
-			/* ydnar: bias the surface textures */
-			BiasSurfaceTextures( ds );
-			
-			/* ydnar: globalizing of fog volume handling (eek a hack) */
-			if( e != entities && si->noFog == qfalse )
-			{
-				/* find surface origin and offset by entity origin */
-				VectorAdd( ds->mins, ds->maxs, origin );
-				VectorScale( origin, 0.5f, origin );
-				VectorAdd( origin, e->origin, origin );
-				
-				VectorAdd( ds->mins, e->origin, mins );
-				VectorAdd( ds->maxs, e->origin, maxs );
-				
-				/* set the fog number for this surface */
-				ds->fogNum = FogForBounds( mins, maxs, 1.0f );	//%	FogForPoint( origin, 0.0f );
-			}
-		}
-		
-		/* ydnar: gs mods: handle the various types of surfaces */
-		switch( ds->type )
-		{
-			/* handle brush faces */
-			case SURFACE_FACE:
-			case SURFACE_DECAL:
-				if( refs == 0 )
-					refs = FilterFaceIntoTree( ds, tree );
-				if( refs > 0 )
-					EmitFaceSurface( ds );
-				break;
-			
-			/* handle patches */
-			case SURFACE_PATCH:
-				if( refs == 0 )
-					refs = FilterPatchIntoTree( ds, tree );
-				if( refs > 0 )
-					EmitPatchSurface( ds );
-				break;
-			
-			/* handle triangle surfaces */
-			case SURFACE_TRIANGLES:
-			case SURFACE_FORCED_META:
-			case SURFACE_META:
-				//%	Sys_FPrintf( SYS_VRB, "Surface %4d: [%1d] %4d verts %s\n", numSurfs, ds->planar, ds->numVerts, si->shader );
-				if( refs == 0 )
-					refs = FilterTrianglesIntoTree( ds, tree );
-				if( refs > 0 )
-					EmitTriangleSurface( ds );
-				break;
-			
-			/* handle foliage surfaces (splash damage/wolf et) */
-			case SURFACE_FOLIAGE:
-				//%	Sys_FPrintf( SYS_VRB, "Surface %4d: [%d] %4d verts %s\n", numSurfs, ds->numFoliageInstances, ds->numVerts, si->shader );
-				if( refs == 0 )
-					refs = FilterFoliageIntoTree( ds, tree );
-				if( refs > 0 )
-					EmitTriangleSurface( ds );
-				break;
-			
-			/* handle foghull surfaces */
-			case SURFACE_FOGHULL:
-				if( refs == 0 )
-					refs = AddReferenceToTree_r( ds, tree->headnode, qfalse );
-				if( refs > 0 )
-					EmitTriangleSurface( ds );
-				break;
-			
-			/* handle flares */
-			case SURFACE_FLARE:
-				if( refs == 0 )
-					refs = FilterFlareSurfIntoTree( ds, tree );
-				if( refs > 0 )
-					EmitFlareSurface( ds );
-				break;
-			
-			/* handle shader-only surfaces */
-			case SURFACE_SHADER:
-				refs = 1;
-				EmitFlareSurface( ds );
-				break;
-			
-			/* no references */
-			default:
-				refs = 0;
-				break;
-		}
-		
-		/* tot up the references */
-		if( refs > 0 )
-		{
-			/* tot up counts */
-			numSurfs++;
-			numRefs += refs;
-			
-			/* emit extra surface data */
-			SetSurfaceExtra( ds, numBSPDrawSurfaces - 1 );
-			//%	Sys_FPrintf( SYS_VRB, "%d verts %d indexes\n", ds->numVerts, ds->numIndexes );
-			
-			/* one last sanity check */
-			{
-				bspDrawSurface_t	*out;
-				out = &bspDrawSurfaces[ numBSPDrawSurfaces - 1 ];
-				if( out->numVerts == 3 && out->numIndexes > 3 )
-				{
-					Sys_Printf( "\nWARNING: Potentially bad %s surface (%d: %d, %d)\n     %s\n",
-						surfaceTypes[ ds->type ],
-						numBSPDrawSurfaces - 1, out->numVerts, out->numIndexes, si->shader );
-				}
-			}
-			
-			/* ydnar: handle skybox surfaces */
-			if( ds->skybox )
-			{
-				MakeSkyboxSurface( ds );
-				numSkyboxSurfaces++;
-			}
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d references\n", numRefs );
-	Sys_FPrintf( SYS_VRB, "%9d (%d) emitted drawsurfs\n", numSurfs, numBSPDrawSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d stripped face surfaces\n", numStripSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d fanned face surfaces\n", numFanSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d surface models generated\n", numSurfaceModels );
-	Sys_FPrintf( SYS_VRB, "%9d skybox surfaces generated\n", numSkyboxSurfaces );
-	for( i = 0; i < NUM_SURFACE_TYPES; i++ )
-		Sys_FPrintf( SYS_VRB, "%9d %s surfaces\n", numSurfacesByType[ i ], surfaceTypes[ i ] );
-	
-	Sys_FPrintf( SYS_VRB, "%9d redundant indexes supressed, saving %d Kbytes\n", numRedundantIndexes, (numRedundantIndexes * 4 / 1024) );
-}
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define SURFACE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+
+this section handles drawsurface allocation and creation
+
+*/
+
+/*
+AllocDrawSurface()
+ydnar: gs mods: changed to force an explicit type when allocating
+*/
+
+mapDrawSurface_t *AllocDrawSurface( surfaceType_t type )
+{
+	mapDrawSurface_t	*ds;
+	
+	
+	/* ydnar: gs mods: only allocate valid types */
+	if( type <= SURFACE_BAD || type >= NUM_SURFACE_TYPES )
+		Error( "AllocDrawSurface: Invalid surface type %d specified", type );
+	
+	/* bounds check */
+	if( numMapDrawSurfs >= MAX_MAP_DRAW_SURFS )
+		Error( "MAX_MAP_DRAW_SURFS (%d) exceeded", MAX_MAP_DRAW_SURFS );
+	ds = &mapDrawSurfs[ numMapDrawSurfs ];
+	numMapDrawSurfs++;
+	
+	/* ydnar: do initial surface setup */
+	memset( ds, 0, sizeof( mapDrawSurface_t ) );
+	ds->type = type;
+	ds->planeNum = -1;
+	ds->fogNum = defaultFogNum;				/* ydnar 2003-02-12 */
+	ds->outputNum = -1;						/* ydnar 2002-08-13 */
+	ds->surfaceNum = numMapDrawSurfs - 1;	/* ydnar 2003-02-16 */
+	
+	return ds;
+}
+
+
+
+/*
+FinishSurface()
+ydnar: general surface finish pass
+*/
+
+void FinishSurface( mapDrawSurface_t *ds )
+{
+	/* dummy check */
+	if( ds == NULL || ds->shaderInfo == NULL )
+		return;
+	
+	/* ydnar: rocking tek-fu celshading */
+	if( ds->celShader != NULL )
+		MakeCelSurface( ds, ds->celShader );
+	
+	/* ydnar: rocking surface cloning (fur baby yeah!) */
+	if( ds->shaderInfo->cloneShader[ 0 ] != '\0' )
+		CloneSurface( ds, ShaderInfoForShader( ds->shaderInfo->cloneShader ) );
+}
+
+
+
+/*
+CloneSurface()
+clones a map drawsurface, using the specified shader
+*/
+
+mapDrawSurface_t *CloneSurface( mapDrawSurface_t *src, shaderInfo_t *si )
+{
+	mapDrawSurface_t	*ds;
+	
+	
+	/* dummy check */
+	if( src == NULL || si == NULL )
+		return NULL;
+	
+	/* allocate a new surface */
+	ds = AllocDrawSurface( src->type );
+	if( ds == NULL )
+		return NULL;
+	
+	/* copy it */
+	memcpy( ds, src, sizeof( *ds ) );
+	
+	/* destroy side reference */
+	ds->sideRef = NULL;
+	
+	/* set shader */
+	ds->shaderInfo = si;
+	
+	/* copy verts */
+	if( ds->numVerts > 0 )
+	{
+		ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
+		memcpy( ds->verts, src->verts, ds->numVerts * sizeof( *ds->verts ) );
+	}
+	
+	/* copy indexes */
+	if( ds->numIndexes <= 0 )
+		return ds;
+	ds->indexes = safe_malloc( ds->numIndexes * sizeof( *ds->indexes ) );
+	memcpy( ds->indexes, src->indexes, ds->numIndexes * sizeof( *ds->indexes ) );
+	
+	/* return the surface */
+	return ds;
+}
+
+
+
+/*
+MakeCelSurface() - ydnar
+makes a copy of a surface, but specific to cel shading
+*/
+
+mapDrawSurface_t *MakeCelSurface( mapDrawSurface_t *src, shaderInfo_t *si )
+{
+	mapDrawSurface_t	*ds;
+	
+	
+	/* dummy check */
+	if( src == NULL || si == NULL )
+		return NULL;
+	
+	/* don't create cel surfaces for certain types of shaders */
+	if( (src->shaderInfo->compileFlags & C_TRANSLUCENT) ||
+		(src->shaderInfo->compileFlags & C_SKY) )
+		return NULL;
+	
+	/* make a copy */
+	ds = CloneSurface( src, si );
+	if( ds == NULL )
+		return NULL;
+	
+	/* do some fixups for celshading */
+	ds->planar = qfalse;
+	ds->planeNum = -1;
+	
+	/* return the surface */
+	return ds;
+}
+
+
+
+/*
+MakeSkyboxSurface() - ydnar
+generates a skybox surface, viewable from everywhere there is sky
+*/
+
+mapDrawSurface_t *MakeSkyboxSurface( mapDrawSurface_t *src )
+{
+	int					i;
+	mapDrawSurface_t	*ds;
+	
+	
+	/* dummy check */
+	if( src == NULL )
+		return NULL;
+	
+	/* make a copy */
+	ds = CloneSurface( src, src->shaderInfo );
+	if( ds == NULL )
+		return NULL;
+	
+	/* set parent */
+	ds->parent = src;
+	
+	/* scale the surface vertexes */
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		m4x4_transform_point( skyboxTransform, ds->verts[ i ].xyz );
+		
+		/* debug code */
+		//%	bspDrawVerts[ bspDrawSurfaces[ ds->outputNum ].firstVert + i ].color[ 0 ][ 1 ] = 0;
+		//%	bspDrawVerts[ bspDrawSurfaces[ ds->outputNum ].firstVert + i ].color[ 0 ][ 2 ] = 0;
+	}
+	
+	/* so backface culling creep doesn't bork the surface */
+	VectorClear( ds->lightmapVecs[ 2 ] );
+	
+	/* return the surface */
+	return ds;
+}
+
+
+
+/*
+IsTriangleDegenerate
+returns qtrue if all three points are colinear, backwards, or the triangle is just plain bogus
+*/
+
+#define	TINY_AREA	1.0f
+
+qboolean IsTriangleDegenerate( bspDrawVert_t *points, int a, int b, int c )
+{
+	vec3_t		v1, v2, v3;
+	float		d;
+	
+	
+	/* calcuate the area of the triangle */
+	VectorSubtract( points[ b ].xyz, points[ a ].xyz, v1 );
+	VectorSubtract( points[ c ].xyz, points[ a ].xyz, v2 );
+	CrossProduct( v1, v2, v3 );
+	d = VectorLength( v3 );
+	
+	/* assume all very small or backwards triangles will cause problems */
+	if( d < TINY_AREA )
+		return qtrue;
+	
+	/* must be a good triangle */
+	return qfalse;
+}
+
+
+
+/*
+ClearSurface() - ydnar
+clears a surface and frees any allocated memory
+*/
+
+void ClearSurface( mapDrawSurface_t *ds )
+{
+	ds->type = SURFACE_BAD;
+	ds->planar = qfalse;
+	ds->planeNum = -1;
+	ds->numVerts = 0;
+	if( ds->verts != NULL )
+		free( ds->verts );
+	ds->verts = NULL;
+	ds->numIndexes = 0;
+	if( ds->indexes != NULL )
+		free( ds->indexes );
+	ds->indexes = NULL;
+	numClearedSurfaces++;
+}
+
+
+
+/*
+TidyEntitySurfaces() - ydnar
+deletes all empty or bad surfaces from the surface list
+*/
+
+void TidyEntitySurfaces( entity_t *e )
+{
+	int					i, j, deleted;
+	mapDrawSurface_t	*out, *in;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- TidyEntitySurfaces ---\n" );
+	
+	/* walk the surface list */
+	deleted = 0;
+	for( i = e->firstDrawSurf, j = e->firstDrawSurf; j < numMapDrawSurfs; i++, j++ )
+	{
+		/* get out surface */
+		out = &mapDrawSurfs[ i ];
+		
+		/* walk the surface list again until a proper surface is found */
+		for( j; j < numMapDrawSurfs; j++ )
+		{
+			/* get in surface */
+			in = &mapDrawSurfs[ j ];
+			
+			/* this surface ok? */
+			if( in->type == SURFACE_FLARE || in->type == SURFACE_SHADER ||
+				(in->type != SURFACE_BAD && in->numVerts > 0) )
+				break;
+			
+			/* nuke it */
+			ClearSurface( in );
+			deleted++;
+		}
+		
+		/* copy if necessary */
+		if( i != j )
+			memcpy( out, in, sizeof( mapDrawSurface_t ) );
+	}
+	
+	/* set the new number of drawsurfs */
+	numMapDrawSurfs = i;
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d empty or malformed surfaces deleted\n", deleted );
+}
+
+
+
+/*
+CalcSurfaceTextureRange() - ydnar
+calculates the clamped texture range for a given surface, returns qtrue if it's within [-texRange,texRange]
+*/
+
+qboolean CalcSurfaceTextureRange( mapDrawSurface_t *ds )
+{
+	int		i, j, v, size[ 2 ];
+	float	mins[ 2 ], maxs[ 2 ];
+	
+	
+	/* try to early out */
+	if( ds->numVerts <= 0 )
+		return qtrue;
+	
+	/* walk the verts and determine min/max st values */
+	mins[ 0 ] = 999999;
+	mins[ 1 ] = 999999;
+	maxs[ 0 ] = -999999;
+	maxs[ 1 ] = -999999;
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		for( j = 0; j < 2; j++ )
+		{
+			if( ds->verts[ i ].st[ j ] < mins[ j ] )
+				mins[ j ] = ds->verts[ i ].st[ j ];
+			if( ds->verts[ i ].st[ j ] > maxs[ j ] )
+				maxs[ j ] = ds->verts[ i ].st[ j ];
+		}
+	}
+	
+	/* clamp to integer range and calculate surface bias values */
+	for( j = 0; j < 2; j++ )
+		ds->bias[ j ] = -floor( 0.5f * (mins[ j ] + maxs[ j ]) );
+	
+	/* find biased texture coordinate mins/maxs */
+	size[ 0 ] = ds->shaderInfo->shaderWidth;
+	size[ 1 ] = ds->shaderInfo->shaderHeight;
+	ds->texMins[ 0 ] = 999999;
+	ds->texMins[ 1 ] = 999999;
+	ds->texMaxs[ 0 ] = -999999;
+	ds->texMaxs[ 1 ] = -999999;
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		for( j = 0; j < 2; j++ )
+		{
+			v = ((float) ds->verts[ i ].st[ j ] + ds->bias[ j ]) * size[ j ];
+			if( v < ds->texMins[ j ] )
+				ds->texMins[ j ] = v;
+			if( v > ds->texMaxs[ j ] )
+				ds->texMaxs[ j ] = v;
+		}
+	}
+	
+	/* calc ranges */
+	for( j = 0; j < 2; j++ )
+		ds->texRange[ j ] = (ds->texMaxs[ j ] - ds->texMins[ j ]);
+	
+	/* if range is zero, then assume unlimited precision */
+	if( texRange == 0 )
+		return qtrue;
+	
+	/* within range? */
+	for( j = 0; j < 2; j++ )
+	{
+		if( ds->texMins[ j ] < -texRange || ds->texMaxs[ j ] > texRange )
+			return qfalse;
+	}
+	
+	/* within range */
+	return qtrue;
+}
+
+
+
+/*
+CalcLightmapAxis() - ydnar
+gives closed lightmap axis for a plane normal
+*/
+
+qboolean CalcLightmapAxis( vec3_t normal, vec3_t axis )
+{
+	vec3_t	absolute;
+		
+	
+	/* test */
+	if( normal[ 0 ] == 0.0f && normal[ 1 ] == 0.0f && normal[ 2 ] == 0.0f )
+	{
+		VectorClear( axis );
+		return qfalse;
+	}
+	
+	/* get absolute normal */
+	absolute[ 0 ] = fabs( normal[ 0 ] );
+	absolute[ 1 ] = fabs( normal[ 1 ] );
+	absolute[ 2 ] = fabs( normal[ 2 ] );
+	
+	/* test and set */
+	if( absolute[ 2 ] > absolute[ 0 ] - 0.0001f && absolute[ 2 ] > absolute[ 1 ] - 0.0001f )
+	{
+		if( normal[ 2 ] > 0.0f )
+			VectorSet( axis, 0.0f, 0.0f, 1.0f );
+		else
+			VectorSet( axis, 0.0f, 0.0f, -1.0f );
+	}
+	else if( absolute[ 0 ] > absolute[ 1 ] - 0.0001f && absolute[ 0 ] > absolute[ 2 ] - 0.0001f )
+	{
+		if( normal[ 0 ] > 0.0f )
+			VectorSet( axis, 1.0f, 0.0f, 0.0f );
+		else
+			VectorSet( axis, -1.0f, 0.0f, 0.0f );
+	}
+	else
+	{
+		if( normal[ 1 ] > 0.0f )
+			VectorSet( axis, 0.0f, 1.0f, 0.0f );
+		else
+			VectorSet( axis, 0.0f, -1.0f, 0.0f );
+	}
+	
+	/* return ok */
+	return qtrue;
+}
+
+
+
+/*
+ClassifySurfaces() - ydnar
+fills out a bunch of info in the surfaces, including planar status, lightmap projection, and bounding box
+*/
+
+#define PLANAR_EPSILON	0.5f	//% 0.126f 0.25f
+
+void ClassifySurfaces( int numSurfs, mapDrawSurface_t *ds )
+{
+	int					i, bestAxis;
+	float				dist;
+	vec4_t				plane;
+	shaderInfo_t		*si;
+	static vec3_t		axii[ 6 ] =
+						{
+							{ 0, 0, -1 },
+							{ 0, 0, 1 },
+							{ -1, 0, 0 },
+							{ 1, 0, 0 },
+							{ 0, -1, 0 },
+							{ 0, 1, 0 }
+						};
+	
+	
+	/* walk the list of surfaces */
+	for( numSurfs; numSurfs > 0; numSurfs--, ds++ )
+	{
+		/* ignore bogus (or flare) surfaces */
+		if( ds->type == SURFACE_BAD || ds->numVerts <= 0 )
+			continue;
+		
+		/* get shader */
+		si = ds->shaderInfo;
+		
+		/* -----------------------------------------------------------------
+		   force meta if vertex count is too high or shader requires it
+		   ----------------------------------------------------------------- */
+		
+		if( ds->type != SURFACE_PATCH && ds->type != SURFACE_FACE )
+		{
+			if( ds->numVerts > SHADER_MAX_VERTEXES )
+				ds->type = SURFACE_FORCED_META;
+		}
+		
+		/* -----------------------------------------------------------------
+		   plane and bounding box classification 
+		   ----------------------------------------------------------------- */
+		
+		/* set surface bounding box */
+		ClearBounds( ds->mins, ds->maxs );
+		for( i = 0; i < ds->numVerts; i++ )
+			AddPointToBounds( ds->verts[ i ].xyz, ds->mins, ds->maxs );
+		
+		/* try to get an existing plane */
+		if( ds->planeNum >= 0 )
+		{
+			VectorCopy( mapplanes[ ds->planeNum ].normal, plane );
+			plane[ 3 ] = mapplanes[ ds->planeNum ].dist;
+		}
+		
+		/* construct one from the first vert with a valid normal */
+		else
+		{
+			VectorClear( plane );
+			plane[ 3 ] = 0.0f;
+			for( i = 0; i < ds->numVerts; i++ )
+			{
+				if( ds->verts[ i ].normal[ 0 ] != 0.0f && ds->verts[ i ].normal[ 1 ] != 0.0f && ds->verts[ i ].normal[ 2 ] != 0.0f )
+				{
+					VectorCopy( ds->verts[ i ].normal, plane );
+					plane[ 3 ] = DotProduct( ds->verts[ i ].xyz, plane );
+					break;
+				}
+			}
+		}
+		
+		/* test for bogus plane */
+		if( VectorLength( plane ) <= 0.0f )
+		{
+			ds->planar = qfalse;
+			ds->planeNum = -1;
+		}
+		else
+		{
+			/* determine if surface is planar */
+			ds->planar = qtrue;
+			
+			/* test each vert */
+			for( i = 0; i < ds->numVerts; i++ )
+			{
+				/* point-plane test */
+				dist = DotProduct( ds->verts[ i ].xyz, plane ) - plane[ 3 ];
+				if( fabs( dist ) > PLANAR_EPSILON )
+				{
+					//%	if( ds->planeNum >= 0 )
+					//%	{
+					//%		Sys_Printf( "WARNING: Planar surface marked unplanar (%f > %f)\n", fabs( dist ), PLANAR_EPSILON );
+					//%		ds->verts[ i ].color[ 0 ][ 0 ] = ds->verts[ i ].color[ 0 ][ 2 ] = 0;
+					//%	}
+					ds->planar = qfalse;
+					break;
+				}
+			}
+		}
+		
+		/* find map plane if necessary */
+		if( ds->planar )
+		{
+			if( ds->planeNum < 0 )
+				ds->planeNum = FindFloatPlane( plane, plane[ 3 ], 1, &ds->verts[ 0 ].xyz );
+			VectorCopy( plane, ds->lightmapVecs[ 2 ] );
+		}
+		else
+		{
+			ds->planeNum = -1;
+			VectorClear( ds->lightmapVecs[ 2 ] );
+			//% if( ds->type == SURF_META || ds->type == SURF_FACE )
+			//%		Sys_Printf( "WARNING: Non-planar face (%d): %s\n", ds->planeNum, ds->shaderInfo->shader );
+		}
+		
+		/* -----------------------------------------------------------------
+		   lightmap bounds and axis projection
+		   ----------------------------------------------------------------- */
+		
+		/* vertex lit surfaces don't need this information */
+		if( si->compileFlags & C_VERTEXLIT || ds->type == SURFACE_TRIANGLES )
+		{
+			VectorClear( ds->lightmapAxis );
+			//%	VectorClear( ds->lightmapVecs[ 2 ] );
+			ds->sampleSize = 0;
+			continue;
+		}
+		
+		/* the shader can specify an explicit lightmap axis */
+		if( si->lightmapAxis[ 0 ] || si->lightmapAxis[ 1 ] || si->lightmapAxis[ 2 ] )
+			VectorCopy( si->lightmapAxis, ds->lightmapAxis );
+		else if( ds->type == SURFACE_FORCED_META )
+			VectorClear( ds->lightmapAxis );
+		else if( ds->planar )
+			CalcLightmapAxis( plane, ds->lightmapAxis );
+		else
+		{
+			/* find best lightmap axis */
+			for( bestAxis = 0; bestAxis < 6; bestAxis++ )
+			{
+				for( i = 0; i < ds->numVerts && bestAxis < 6; i++ )
+				{
+					//% Sys_Printf( "Comparing %1.3f %1.3f %1.3f to %1.3f %1.3f %1.3f\n",
+					//% 	ds->verts[ i ].normal[ 0 ], ds->verts[ i ].normal[ 1 ], ds->verts[ i ].normal[ 2 ],
+					//% 	axii[ bestAxis ][ 0 ], axii[ bestAxis ][ 1 ], axii[ bestAxis ][ 2 ] );
+					if( DotProduct( ds->verts[ i ].normal, axii[ bestAxis ] ) < 0.25f )	/* fixme: adjust this tolerance to taste */
+						break;
+				}
+				
+				if( i == ds->numVerts )
+					break;
+			}
+			
+			/* set axis if possible */
+			if( bestAxis < 6 )
+			{
+				//% if( ds->type == SURFACE_PATCH )
+				//% 	Sys_Printf( "Mapped axis %d onto patch\n", bestAxis );
+				VectorCopy( axii[ bestAxis ], ds->lightmapAxis );
+			}
+			
+			/* debug code */
+			//% if( ds->type == SURFACE_PATCH )
+			//% 	Sys_Printf( "Failed to map axis %d onto patch\n", bestAxis );
+		}
+		
+		/* get lightmap sample size */
+		if( ds->sampleSize <= 0 )
+		{
+ 			ds->sampleSize = sampleSize;
+ 			if( ds->shaderInfo->lightmapSampleSize )
+ 				ds->sampleSize = ds->shaderInfo->lightmapSampleSize;
+			if( ds->lightmapScale > 0 )
+				ds->sampleSize *= ds->lightmapScale;
+			if( ds->sampleSize <= 0 )
+				ds->sampleSize = 1;
+			else if( ds->sampleSize > 16384 )	/* powers of 2 are preferred */
+				ds->sampleSize = 16384;
+		}
+	}
+}
+
+
+
+/*
+ClassifyEntitySurfaces() - ydnar
+classifies all surfaces in an entity
+*/
+
+void ClassifyEntitySurfaces( entity_t *e )
+{
+	int		i;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- ClassifyEntitySurfaces ---\n" );
+	
+	/* walk the surface list */
+	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
+		ClassifySurfaces( 1, &mapDrawSurfs[ i ] );
+	
+	/* tidy things up */
+	TidyEntitySurfaces( e );
+}
+
+
+
+/*
+GetShaderIndexForPoint() - ydnar
+for shader-indexed surfaces (terrain), find a matching index from the indexmap
+*/
+
+byte GetShaderIndexForPoint( indexMap_t *im, vec3_t eMins, vec3_t eMaxs, vec3_t point )
+{
+	int			i, x, y;
+	float		s, t;
+	vec3_t		mins, maxs, size;
+	
+	
+	/* early out if no indexmap */
+	if( im == NULL )
+		return 0;
+	
+	/* this code is really broken */
+	#if 0
+		/* legacy precision fudges for terrain */
+		for( i = 0; i < 3; i++ )
+		{
+			mins[ i ] = floor( eMins[ i ] + 0.1 );
+			maxs[ i ] = floor( eMaxs[ i ] + 0.1 );
+			size[ i ] = maxs[ i ] - mins[ i ];
+		}
+		
+		/* find st (fixme: support more than just z-axis projection) */
+		s = floor( point[ 0 ] + 0.1f - mins[ 0 ] ) / size[ 0 ];
+		t = floor( maxs[ 1 ] - point[ 1 ] + 0.1f ) / size[ 1 ];
+		if( s < 0.0f )
+			s = 0.0f;
+		else if( s > 1.0f )
+			s = 1.0f;
+		if( t < 0.0f )
+			t = 0.0f;
+		else if( t > 1.0f )
+			t = 1.0f;
+		
+		/* make xy */
+		x = (im->w - 1) * s;
+		y = (im->h - 1) * t;
+	#else
+		/* get size */
+		for( i = 0; i < 3; i++ )
+		{
+			mins[ i ] = eMins[ i ];
+			maxs[ i ] = eMaxs[ i ];
+			size[ i ] = maxs[ i ] - mins[ i ];
+		}
+		
+		/* calc st */
+		s = (point[ 0 ] - mins[ 0 ]) / size[ 0 ];
+		t = (maxs[ 1 ] - point[ 1 ]) / size[ 1 ];
+		
+		/* calc xy */
+		x = s * im->w;
+		y = t * im->h;
+		if( x < 0 )
+			x = 0;
+		else if( x > (im->w - 1) )
+			x = (im->w - 1);
+		if( y < 0 )
+			y = 0;
+		else if( y > (im->h - 1) )
+			y = (im->h - 1);
+	#endif
+	
+	/* return index */
+	return im->pixels[ y * im->w + x ];
+}
+
+
+
+/*
+GetIndexedShader() - ydnar
+for a given set of indexes and an indexmap, get a shader and set the vertex alpha in-place
+this combines a couple different functions from terrain.c
+*/
+
+shaderInfo_t *GetIndexedShader( shaderInfo_t *parent, indexMap_t *im, int numPoints, byte *shaderIndexes )
+{
+	int				i;
+	byte			minShaderIndex, maxShaderIndex;
+	char			shader[ MAX_QPATH ];
+	shaderInfo_t	*si;
+	
+	
+	/* early out if bad data */
+	if( im == NULL || numPoints <= 0 || shaderIndexes == NULL )
+		return ShaderInfoForShader( "default" );
+	
+	/* determine min/max index */
+	minShaderIndex = 255;
+	maxShaderIndex = 0;
+	for( i = 0; i < numPoints; i++ )
+	{
+		if( shaderIndexes[ i ] < minShaderIndex )
+			minShaderIndex = shaderIndexes[ i ];
+		if( shaderIndexes[ i ] > maxShaderIndex )
+			maxShaderIndex = shaderIndexes[ i ];
+	}
+	
+	/* set alpha inline */
+	for( i = 0; i < numPoints; i++ )
+	{
+		/* straight rip from terrain.c */
+		if( shaderIndexes[ i ] < maxShaderIndex )
+			shaderIndexes[ i ] = 0;
+		else
+			shaderIndexes[ i ] = 255;
+	}
+	
+	/* make a shader name */
+	if( minShaderIndex == maxShaderIndex )
+		sprintf( shader, "textures/%s_%d", im->shader, maxShaderIndex );
+	else
+		sprintf( shader, "textures/%s_%dto%d", im->shader, minShaderIndex, maxShaderIndex );
+	
+	/* get the shader */
+	si = ShaderInfoForShader( shader );
+	
+	/* inherit a few things from parent shader */
+	if( parent->globalTexture )
+		si->globalTexture = qtrue;
+	if( parent->forceMeta )
+		si->forceMeta = qtrue;
+	if( parent->nonplanar )
+		si->nonplanar = qtrue;
+	if( si->shadeAngleDegrees == 0.0 )
+		si->shadeAngleDegrees = parent->shadeAngleDegrees;
+	if( parent->tcGen && si->tcGen == qfalse )
+	{
+		/* set xy texture projection */
+		si->tcGen = qtrue;
+		VectorCopy( parent->vecs[ 0 ], si->vecs[ 0 ] );
+		VectorCopy( parent->vecs[ 1 ], si->vecs[ 1 ] );
+	}
+	if( VectorLength( parent->lightmapAxis ) > 0.0f && VectorLength( si->lightmapAxis ) <= 0.0f )
+	{
+		/* set lightmap projection axis */
+		VectorCopy( parent->lightmapAxis, si->lightmapAxis );
+	}
+	
+	/* return the shader */
+	return si;
+}
+
+
+
+
+/*
+DrawSurfaceForSide()
+creates a SURF_FACE drawsurface from a given brush side and winding
+*/
+
+#define	SNAP_FLOAT_TO_INT	8
+#define	SNAP_INT_TO_FLOAT	(1.0 / SNAP_FLOAT_TO_INT)
+
+mapDrawSurface_t *DrawSurfaceForSide( entity_t *e, brush_t *b, side_t *s, winding_t *w )
+{
+	int					i, j, k;
+	mapDrawSurface_t	*ds;
+	shaderInfo_t		*si, *parent;
+	bspDrawVert_t		*dv;
+	vec3_t				texX, texY;
+	vec_t				x, y;
+	vec3_t				vTranslated;
+	qboolean			indexed;
+	byte				shaderIndexes[ 256 ];
+	float				offsets[ 256 ];
+	char				tempShader[ MAX_QPATH ];
+
+	
+	/* ydnar: don't make a drawsurf for culled sides */
+	if( s->culled )
+		return NULL;
+	
+	/* range check */
+	if( w->numpoints > MAX_POINTS_ON_WINDING )
+		Error( "DrawSurfaceForSide: w->numpoints = %d (> %d)", w->numpoints, MAX_POINTS_ON_WINDING );
+	
+	/* get shader */
+	si = s->shaderInfo;
+	
+	/* ydnar: gs mods: check for indexed shader */
+	if( si->indexed && b->im != NULL )
+	{
+		/* indexed */
+		indexed = qtrue;
+		
+		/* get shader indexes for each point */
+		for( i = 0; i < w->numpoints; i++ )
+		{
+			shaderIndexes[ i ] = GetShaderIndexForPoint( b->im, b->eMins, b->eMaxs, w->p[ i ] );
+			offsets[ i ] = b->im->offsets[ shaderIndexes[ i ] ];
+			//%	Sys_Printf( "%f ", offsets[ i ] );
+		}
+		
+		/* get matching shader and set alpha */
+		parent = si;
+		si = GetIndexedShader( parent, b->im, w->numpoints, shaderIndexes );
+	}
+	else
+		indexed = qfalse;
+	
+	/* ydnar: sky hack/fix for GL_CLAMP borders on ati cards */
+	if( skyFixHack && si->skyParmsImageBase[ 0 ] != '\0' )
+	{
+		//%	Sys_FPrintf( SYS_VRB, "Enabling sky hack for shader %s using env %s\n", si->shader, si->skyParmsImageBase );
+		sprintf( tempShader, "%s_lf", si->skyParmsImageBase );
+		DrawSurfaceForShader( tempShader );
+		sprintf( tempShader, "%s_rt", si->skyParmsImageBase );
+		DrawSurfaceForShader( tempShader );
+		sprintf( tempShader, "%s_ft", si->skyParmsImageBase );
+		DrawSurfaceForShader( tempShader );
+		sprintf( tempShader, "%s_bk", si->skyParmsImageBase );
+		DrawSurfaceForShader( tempShader );
+		sprintf( tempShader, "%s_up", si->skyParmsImageBase );
+		DrawSurfaceForShader( tempShader );
+		sprintf( tempShader, "%s_dn", si->skyParmsImageBase );
+		DrawSurfaceForShader( tempShader );
+	}
+	
+	/* ydnar: gs mods */
+	ds = AllocDrawSurface( SURFACE_FACE );
+	ds->entityNum = b->entityNum;
+	ds->castShadows = b->castShadows;
+	ds->recvShadows = b->recvShadows;
+	
+	ds->planar = qtrue;
+	ds->planeNum = s->planenum;
+	VectorCopy( mapplanes[ s->planenum ].normal, ds->lightmapVecs[ 2 ] );
+	
+	ds->shaderInfo = si;
+	ds->mapBrush = b;
+	ds->sideRef = AllocSideRef( s, NULL );
+	ds->fogNum = -1;
+	ds->lightmapScale = b->lightmapScale;
+	ds->numVerts = w->numpoints;
+	ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
+	memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
+	
+	/* compute s/t coordinates from brush primitive texture matrix (compute axis base) */
+	ComputeAxisBase( mapplanes[ s->planenum ].normal, texX, texY );
+	
+	/* create the vertexes */
+	for( j = 0; j < w->numpoints; j++ )
+	{
+		/* get the drawvert */
+		dv = ds->verts + j;
+		
+		/* copy xyz and do potential z offset */
+		VectorCopy( w->p[ j ], dv->xyz );
+		if( indexed )
+			dv->xyz[ 2 ] += offsets[ j ];
+		
+		/* round the xyz to a given precision and translate by origin */
+		for( i = 0 ; i < 3 ; i++ )
+			dv->xyz[ i ] = SNAP_INT_TO_FLOAT * floor( dv->xyz[ i ] * SNAP_FLOAT_TO_INT + 0.5f );
+		VectorAdd( dv->xyz, e->origin, vTranslated );
+		
+		/* ydnar: tek-fu celshading support for flat shaded shit */
+		if( flat )
+		{
+			dv->st[ 0 ] = si->stFlat[ 0 ];
+			dv->st[ 1 ] = si->stFlat[ 1 ];
+		}
+		
+		/* ydnar: gs mods: added support for explicit shader texcoord generation */
+		else if( si->tcGen )
+		{
+			dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], vTranslated );
+			dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], vTranslated );
+		}
+		
+		/* old quake-style texturing */
+		else if( g_bBrushPrimit == BPRIMIT_OLDBRUSHES )
+		{
+			/* nearest-axial projection */
+			dv->st[ 0 ] = s->vecs[ 0 ][ 3 ] + DotProduct( s->vecs[ 0 ], vTranslated );
+			dv->st[ 1 ] = s->vecs[ 1 ][ 3 ] + DotProduct( s->vecs[ 1 ], vTranslated );
+			dv->st[ 0 ] /= si->shaderWidth;
+			dv->st[ 1 ] /= si->shaderHeight;
+		}
+		
+		/* brush primitive texturing */
+		else
+		{
+			/* calculate texture s/t from brush primitive texture matrix */
+			x = DotProduct( vTranslated, texX );
+			y = DotProduct( vTranslated, texY );
+			dv->st[ 0 ] = s->texMat[ 0 ][ 0 ] * x + s->texMat[ 0 ][ 1 ] * y + s->texMat[ 0 ][ 2 ];
+			dv->st[ 1 ] = s->texMat[ 1 ][ 0 ] * x + s->texMat[ 1 ][ 1 ] * y + s->texMat[ 1 ][ 2 ];
+		}
+		
+		/* copy normal */
+		VectorCopy( mapplanes[ s->planenum ].normal, dv->normal );
+		
+		/* ydnar: set color */
+		for( k = 0; k < MAX_LIGHTMAPS; k++ )
+		{
+			dv->color[ k ][ 0 ] = 255;
+			dv->color[ k ][ 1 ] = 255;
+			dv->color[ k ][ 2 ] = 255;
+			
+			/* ydnar: gs mods: handle indexed shader blending */
+			dv->color[ k ][ 3 ] = (indexed ? shaderIndexes[ j ] : 255);
+		}
+	}
+	
+	/* set cel shader */
+	ds->celShader = b->celShader;
+	
+	/* finish surface */
+	FinishSurface( ds );
+	
+	/* ydnar: gs mods: moved st biasing elsewhere */
+	return ds;
+}
+
+
+
+/*
+DrawSurfaceForMesh()
+moved here from patch.c
+*/
+
+#define YDNAR_NORMAL_EPSILON 0.50f
+
+qboolean VectorCompareExt( vec3_t n1, vec3_t n2, float epsilon )
+{
+	int		i;
+	
+	
+	/* test */
+	for( i= 0; i < 3; i++ )
+		if( fabs( n1[ i ] - n2[ i ]) > epsilon )
+			return qfalse;
+	return qtrue;
+}
+
+mapDrawSurface_t *DrawSurfaceForMesh( entity_t *e, parseMesh_t *p, mesh_t *mesh )
+{
+	int					i, k, numVerts;
+	vec4_t				plane;
+	qboolean			planar;
+	float				dist;
+	mapDrawSurface_t	*ds;
+	shaderInfo_t		*si, *parent;
+	bspDrawVert_t		*dv;
+	vec3_t				vTranslated;
+	mesh_t				*copy;
+	qboolean			indexed;
+	byte				shaderIndexes[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ];
+	float				offsets[ MAX_EXPANDED_AXIS * MAX_EXPANDED_AXIS ];
+	
+	
+	/* get mesh and shader shader */
+	if( mesh == NULL )
+		mesh = &p->mesh;
+	si = p->shaderInfo;
+	if( mesh == NULL || si == NULL )
+		return NULL;
+	
+	/* get vertex count */
+	numVerts = mesh->width * mesh->height;
+	
+	/* to make valid normals for patches with degenerate edges,
+	   we need to make a copy of the mesh and put the aproximating
+	   points onto the curve */
+	
+	/* create a copy of the mesh */
+	copy = CopyMesh( mesh );
+	
+	/* store off the original (potentially bad) normals */
+	MakeMeshNormals( *copy );
+	for( i = 0; i < numVerts; i++ )
+		VectorCopy( copy->verts[ i ].normal, mesh->verts[ i ].normal );
+	
+	/* put the mesh on the curve */
+	PutMeshOnCurve( *copy );
+
+	/* find new normals (to take into account degenerate/flipped edges */
+	MakeMeshNormals( *copy );
+	for( i = 0; i < numVerts; i++ )
+	{
+		/* ydnar: only copy normals that are significantly different from the originals */
+		if( DotProduct( copy->verts[ i ].normal, mesh->verts[ i ].normal ) < 0.75f )
+			VectorCopy( copy->verts[ i ].normal, mesh->verts[ i ].normal );
+	}
+	
+	/* free the old mesh */
+	FreeMesh( copy );
+	
+	/* ydnar: gs mods: check for indexed shader */
+	if( si->indexed && p->im != NULL )
+	{
+		/* indexed */
+		indexed = qtrue;
+
+		/* get shader indexes for each point */
+		for( i = 0; i < numVerts; i++ )
+		{
+			shaderIndexes[ i ] = GetShaderIndexForPoint( p->im, p->eMins, p->eMaxs, mesh->verts[ i ].xyz );
+			offsets[ i ] = p->im->offsets[ shaderIndexes[ i ] ];
+		}
+		
+		/* get matching shader and set alpha */
+		parent = si;
+		si = GetIndexedShader( parent, p->im, numVerts, shaderIndexes );
+	}
+	else
+		indexed = qfalse;
+	
+	
+	/* ydnar: gs mods */
+	ds = AllocDrawSurface( SURFACE_PATCH );
+	ds->entityNum = p->entityNum;
+	ds->castShadows = p->castShadows;
+	ds->recvShadows = p->recvShadows;
+	
+	ds->shaderInfo = si;
+	ds->mapMesh = p;
+	ds->lightmapScale = p->lightmapScale;	/* ydnar */
+	ds->patchWidth = mesh->width;
+	ds->patchHeight = mesh->height;
+	ds->numVerts = ds->patchWidth * ds->patchHeight;
+	ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
+	memcpy( ds->verts, mesh->verts, ds->numVerts * sizeof( *ds->verts ) );
+	
+	ds->fogNum = -1;
+	ds->planeNum = -1;
+	
+	ds->longestCurve = p->longestCurve;
+	ds->maxIterations = p->maxIterations;
+	
+	/* construct a plane from the first vert */
+	VectorCopy( mesh->verts[ 0 ].normal, plane );
+	plane[ 3 ] = DotProduct( mesh->verts[ 0 ].xyz, plane );
+	planar = qtrue;
+	
+	/* spew forth errors */
+	if( VectorLength( plane ) < 0.001f )
+		Sys_Printf( "BOGUS " );
+	
+	/* test each vert */
+	for( i = 1; i < ds->numVerts && planar; i++ )
+	{
+		/* normal test */
+		if( VectorCompare( plane, mesh->verts[ i ].normal ) == qfalse )
+			planar = qfalse;
+		
+		/* point-plane test */
+		dist = DotProduct( mesh->verts[ i ].xyz, plane ) - plane[ 3 ];
+		if( fabs( dist ) > EQUAL_EPSILON )
+			planar = qfalse;
+	}
+	
+	/* add a map plane */
+	if( planar )
+	{
+		/* make a map plane */
+		ds->planeNum = FindFloatPlane( plane, plane[ 3 ], 1, &mesh->verts[ 0 ].xyz );
+		VectorCopy( plane, ds->lightmapVecs[ 2 ] );
+		
+		/* push this normal to all verts (ydnar 2003-02-14: bad idea, small patches get screwed up) */
+		for( i = 0; i < ds->numVerts; i++ )
+			VectorCopy( plane, ds->verts[ i ].normal );
+	}
+	
+	/* walk the verts to do special stuff */
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		/* get the drawvert */
+		dv = &ds->verts[ i ];
+		
+		/* ydnar: tek-fu celshading support for flat shaded shit */
+		if( flat )
+		{
+			dv->st[ 0 ] = si->stFlat[ 0 ];
+			dv->st[ 1 ] = si->stFlat[ 1 ];
+		}
+		
+		/* ydnar: gs mods: added support for explicit shader texcoord generation */
+		else if( si->tcGen )
+		{
+			/* translate by origin and project the texture */
+			VectorAdd( dv->xyz, e->origin, vTranslated );
+			dv->st[ 0 ] = DotProduct( si->vecs[ 0 ], vTranslated );
+			dv->st[ 1 ] = DotProduct( si->vecs[ 1 ], vTranslated );
+		}
+		
+		/* ydnar: set color */
+		for( k = 0; k < MAX_LIGHTMAPS; k++ )
+		{
+			dv->color[ k ][ 0 ] = 255;
+			dv->color[ k ][ 1 ] = 255;
+			dv->color[ k ][ 2 ] = 255;
+			
+			/* ydnar: gs mods: handle indexed shader blending */
+			dv->color[ k ][ 3 ] = (indexed ? shaderIndexes[ i ] : 255);
+		}
+		
+		/* ydnar: offset */
+		if( indexed )
+			dv->xyz[ 2 ] += offsets[ i ];
+	}
+	
+	/* set cel shader */
+	ds->celShader = p->celShader;
+	
+	/* finish surface */
+	FinishSurface( ds );
+	
+	/* return the drawsurface */
+	return ds;
+}
+
+
+
+/*
+DrawSurfaceForFlare() - ydnar
+creates a flare draw surface
+*/
+
+mapDrawSurface_t *DrawSurfaceForFlare( int entNum, vec3_t origin, vec3_t normal, vec3_t color, char *flareShader, int lightStyle )
+{
+	mapDrawSurface_t	*ds;
+	
+	
+	/* emit flares? */
+	if( emitFlares == qfalse )
+		return NULL;
+	
+	/* allocate drawsurface */
+	ds = AllocDrawSurface( SURFACE_FLARE );
+	ds->entityNum = entNum;
+	
+	/* set it up */
+	if( flareShader != NULL && flareShader[ 0 ] != '\0' )
+		ds->shaderInfo = ShaderInfoForShader( flareShader );
+	else
+		ds->shaderInfo = ShaderInfoForShader( game->flareShader );
+	if( origin != NULL )
+		VectorCopy( origin, ds->lightmapOrigin );
+	if( normal != NULL )
+		VectorCopy( normal, ds->lightmapVecs[ 2 ] );
+	if( color != NULL )
+		VectorCopy( color, ds->lightmapVecs[ 0 ] );
+	
+	/* store light style */
+	ds->lightStyle = lightStyle;
+	if( ds->lightStyle < 0 || ds->lightStyle >= LS_NONE )
+		ds->lightStyle = LS_NORMAL;
+	
+	/* fixme: fog */
+	
+	/* return to sender */
+	return ds;
+}
+
+
+
+/*
+DrawSurfaceForShader() - ydnar
+creates a bogus surface to forcing the game to load a shader
+*/
+
+mapDrawSurface_t *DrawSurfaceForShader( char *shader )
+{
+	int					i;
+	shaderInfo_t		*si;
+	mapDrawSurface_t	*ds;
+	
+	
+	/* get shader */
+	si = ShaderInfoForShader( shader );
+
+	/* find existing surface */
+	for( i = 0; i < numMapDrawSurfs; i++ )
+	{
+		/* get surface */
+		ds = &mapDrawSurfs[ i ];
+		
+		/* check it */
+		if( ds->shaderInfo == si )
+			return ds;
+	}
+	
+	/* create a new surface */
+	ds = AllocDrawSurface( SURFACE_SHADER );
+	ds->entityNum = 0;
+	ds->shaderInfo = ShaderInfoForShader( shader );
+	
+	/* return to sender */
+	return ds;
+}
+
+
+
+/*
+AddSurfaceFlare() - ydnar
+creates flares (coronas) centered on surfaces
+*/
+
+static void AddSurfaceFlare( mapDrawSurface_t *ds, vec3_t entityOrigin )
+{
+	vec3_t				origin;
+	int					i;
+	
+	
+	/* find centroid */
+	VectorClear( origin );
+	for ( i = 0; i < ds->numVerts; i++ )
+		VectorAdd( origin, ds->verts[ i ].xyz, origin );
+	VectorScale( origin, (1.0f / ds->numVerts), origin );
+	if( entityOrigin != NULL )
+		VectorAdd( origin, entityOrigin, origin );
+	
+	/* push origin off surface a bit */
+	VectorMA( origin, 2.0f,  ds->lightmapVecs[ 2 ], origin );
+	
+	/* create the drawsurface */
+	DrawSurfaceForFlare( ds->entityNum, origin, ds->lightmapVecs[ 2 ], ds->shaderInfo->color, ds->shaderInfo->flareShader, ds->shaderInfo->lightStyle );
+}
+
+
+
+/*
+SubdivideFace()
+subdivides a face surface until it is smaller than the specified size (subdivisions)
+*/
+
+static void SubdivideFace( entity_t *e, brush_t *brush, side_t *side, winding_t *w, int fogNum, float subdivisions )
+{
+	int					i;
+	int					axis;
+	vec3_t				bounds[ 2 ];
+	const float			epsilon = 0.1;
+	int					subFloor, subCeil;
+	winding_t			*frontWinding, *backWinding;
+	mapDrawSurface_t	*ds;
+	
+	
+	/* dummy check */
+	if( w == NULL )
+		return;
+	if( w->numpoints < 3 )
+		Error( "SubdivideFaceSurface: Bad w->numpoints" );
+	
+	/* determine surface bounds */
+	ClearBounds( bounds[ 0 ], bounds[ 1 ] );
+	for( i = 0; i < w->numpoints; i++ )
+		AddPointToBounds( w->p[ i ], bounds[ 0 ], bounds[ 1 ] );
+	
+	/* split the face */
+	for( axis = 0; axis < 3; axis++ )
+	{
+		vec3_t			planePoint = { 0, 0, 0 };
+		vec3_t			planeNormal = { 0, 0, 0 };
+		float			d;
+		
+		
+		/* create an axial clipping plane */
+		subFloor = floor( bounds[ 0 ][ axis ] / subdivisions) * subdivisions;
+		subCeil = ceil( bounds[ 1 ][ axis ] / subdivisions) * subdivisions;
+		planePoint[ axis ] = subFloor + subdivisions;
+		planeNormal[ axis ] = -1;
+		d = DotProduct( planePoint, planeNormal );
+
+		/* subdivide if necessary */
+		if( (subCeil - subFloor) > subdivisions )
+		{
+			/* clip the winding */
+			ClipWindingEpsilon( w, planeNormal, d, epsilon, &frontWinding, &backWinding );
+
+			/* the clip may not produce two polygons if it was epsilon close */
+			if( frontWinding == NULL )
+				w = backWinding;
+			else if( backWinding == NULL )
+				w = frontWinding;
+			else
+			{
+				SubdivideFace( e, brush, side, frontWinding, fogNum, subdivisions );
+				SubdivideFace( e, brush, side, backWinding, fogNum, subdivisions );
+				return;
+			}
+		}
+	}
+	
+	/* create a face surface */
+	ds = DrawSurfaceForSide( e, brush, side, w );
+	
+	/* set correct fog num */
+	ds->fogNum = fogNum;
+}
+
+
+
+/*
+SubdivideFaceSurfaces()
+chop up brush face surfaces that have subdivision attributes
+ydnar: and subdivide surfaces that exceed specified texture coordinate range
+*/
+
+void SubdivideFaceSurfaces( entity_t *e, tree_t *tree )
+{
+	int					i, j, numBaseDrawSurfs, fogNum;
+	mapDrawSurface_t	*ds;
+	brush_t				*brush;
+	side_t				*side;
+	shaderInfo_t		*si;
+	winding_t			*w;
+	float				range, size, subdivisions, s2;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- SubdivideFaceSurfaces ---\n" );
+	
+	/* walk the list of surfaces */
+	numBaseDrawSurfs = numMapDrawSurfs;
+	for( i = e->firstDrawSurf; i < numBaseDrawSurfs; i++ )
+	{
+		/* get surface */
+		ds = &mapDrawSurfs[ i ];
+
+		/* only subdivide brush sides */
+		if( ds->type != SURFACE_FACE || ds->mapBrush == NULL || ds->sideRef == NULL || ds->sideRef->side == NULL )
+			continue;
+		
+		/* get bits */
+		brush = ds->mapBrush;
+		side = ds->sideRef->side;
+		
+		/* check subdivision for shader */
+		si = side->shaderInfo;
+		if( si == NULL )
+			continue;
+		
+		/* ydnar: don't subdivide sky surfaces */
+		if( si->compileFlags & C_SKY )
+			continue;
+		
+		/* do texture coordinate range check */
+		ClassifySurfaces( 1, ds );
+		if( CalcSurfaceTextureRange( ds ) == qfalse )
+		{
+			/* calculate subdivisions texture range (this code is shit) */
+			range = (ds->texRange[ 0 ] > ds->texRange[ 1 ] ? ds->texRange[ 0 ] : ds->texRange[ 1 ]);
+			size = ds->maxs[ 0 ] - ds->mins[ 0 ];
+			for( j = 1; j < 3; j++ )
+				if( (ds->maxs[ j ] - ds->mins[ j ]) > size )
+					size = ds->maxs[ j ] - ds->mins[ j ];
+			subdivisions = (size / range) * texRange;
+			subdivisions = ceil( subdivisions / 2 ) * 2;
+			for( j = 1; j < 8; j++ )
+			{
+				s2 = ceil( (float) texRange / j );
+				if( fabs( subdivisions - s2 ) <= 4.0 )
+				{
+					subdivisions = s2;
+					break;
+				}
+			}
+		}
+		else
+			subdivisions = si->subdivisions;
+		
+		/* get subdivisions from shader */
+		if(	si->subdivisions > 0 && si->subdivisions < subdivisions )
+			subdivisions = si->subdivisions;
+		if( subdivisions < 1.0f )
+			continue;
+		
+		/* preserve fog num */
+		fogNum = ds->fogNum;
+		
+		/* make a winding and free the surface */
+		w = WindingFromDrawSurf( ds );
+		ClearSurface( ds );
+		
+		/* subdivide it */
+		SubdivideFace( e, brush, side, w, fogNum, subdivisions );
+	}
+}
+
+
+
+/*
+====================
+ClipSideIntoTree_r
+
+Adds non-opaque leaf fragments to the convex hull
+====================
+*/
+
+void ClipSideIntoTree_r( winding_t *w, side_t *side, node_t *node )
+{
+	plane_t			*plane;
+	winding_t		*front, *back;
+
+	if ( !w ) {
+		return;
+	}
+
+	if ( node->planenum != PLANENUM_LEAF ) {
+		if ( side->planenum == node->planenum ) {
+			ClipSideIntoTree_r( w, side, node->children[0] );
+			return;
+		}
+		if ( side->planenum == ( node->planenum ^ 1) ) {
+			ClipSideIntoTree_r( w, side, node->children[1] );
+			return;
+		}
+
+		plane = &mapplanes[ node->planenum ];
+		ClipWindingEpsilon ( w, plane->normal, plane->dist,
+				ON_EPSILON, &front, &back );
+		FreeWinding( w );
+
+		ClipSideIntoTree_r( front, side, node->children[0] );
+		ClipSideIntoTree_r( back, side, node->children[1] );
+
+		return;
+	}
+
+	// if opaque leaf, don't add
+	if ( !node->opaque ) {
+		AddWindingToConvexHull( w, &side->visibleHull, mapplanes[ side->planenum ].normal );
+	}
+
+	FreeWinding( w );
+	return;
+}
+
+
+
+
+
+static int g_numHiddenFaces, g_numCoinFaces;
+
+
+
+/*
+CullVectorCompare() - ydnar
+compares two vectors with an epsilon
+*/
+
+#define CULL_EPSILON 0.1f
+
+qboolean CullVectorCompare( const vec3_t v1, const vec3_t v2 )
+{
+	int		i;
+	
+	
+	for( i = 0; i < 3; i++ )
+		if( fabs( v1[ i ] - v2[ i ] ) > CULL_EPSILON )
+			return qfalse;
+	return qtrue;
+}
+
+
+
+/*
+SideInBrush() - ydnar
+determines if a brushside lies inside another brush
+*/
+
+qboolean SideInBrush( side_t *side, brush_t *b )
+{
+	int			i, s;
+	plane_t		*plane;
+	
+	
+	/* ignore sides w/o windings or shaders */
+	if( side->winding == NULL || side->shaderInfo == NULL )
+		return qtrue;
+
+	/* ignore culled sides and translucent brushes */
+	if( side->culled == qtrue || (b->compileFlags & C_TRANSLUCENT) )
+		return qfalse;
+
+	/* side iterator */
+	for( i = 0; i < b->numsides; i++ )
+	{
+		/* fail if any sides are caulk */
+		if( b->sides[ i ].compileFlags & C_NODRAW )
+			return qfalse;
+
+		/* check if side's winding is on or behind the plane */
+		plane = &mapplanes[ b->sides[ i ].planenum ];
+		s = WindingOnPlaneSide( side->winding, plane->normal, plane->dist );
+		if( s == SIDE_FRONT || s == SIDE_CROSS )
+			return qfalse;
+	}
+	
+	/* don't cull autosprite or polygonoffset surfaces */
+	if( side->shaderInfo )
+	{
+		if( side->shaderInfo->autosprite || side->shaderInfo->polygonOffset )
+			return qfalse;
+	}
+	
+	/* inside */
+	side->culled = qtrue;
+	g_numHiddenFaces++;
+	return qtrue;
+}
+
+
+/*
+CullSides() - ydnar
+culls obscured or buried brushsides from the map
+*/
+
+void CullSides( entity_t *e )
+{
+	int			numPoints;
+	int			i, j, k, l, first, second, dir;
+	winding_t	*w1, *w2;
+	brush_t	*b1, *b2;
+	side_t		*side1, *side2;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- CullSides ---\n" );
+	
+	g_numHiddenFaces = 0;
+	g_numCoinFaces = 0;
+	
+	/* brush interator 1 */
+	for( b1 = e->brushes; b1; b1 = b1->next )
+	{
+		/* sides check */
+		if( b1->numsides < 1 )
+			continue;
+
+		/* brush iterator 2 */
+		for( b2 = b1->next; b2; b2 = b2->next )
+		{
+			/* sides check */
+			if( b2->numsides < 1 )
+				continue;
+			
+			/* original check */
+			if( b1->original == b2->original && b1->original != NULL )
+				continue;
+			
+			/* bbox check */
+			j = 0;
+			for( i = 0; i < 3; i++ )
+				if( b1->mins[ i ] > b2->maxs[ i ] || b1->maxs[ i ] < b2->mins[ i ] )
+					j++;
+			if( j )
+				continue;
+
+			/* cull inside sides */
+			for( i = 0; i < b1->numsides; i++ )
+				SideInBrush( &b1->sides[ i ], b2 );
+			for( i = 0; i < b2->numsides; i++ )
+				SideInBrush( &b2->sides[ i ], b1 );
+			
+			/* side iterator 1 */
+			for( i = 0; i < b1->numsides; i++ )
+			{
+				/* winding check */
+				side1 = &b1->sides[ i ];
+				w1 = side1->winding;
+				if( w1 == NULL )
+					continue;
+				numPoints = w1->numpoints;
+				if( side1->shaderInfo == NULL )
+					continue;
+				
+				/* side iterator 2 */
+				for( j = 0; j < b2->numsides; j++ )
+				{
+					/* winding check */
+					side2 = &b2->sides[ j ];
+					w2 = side2->winding;
+					if( w2 == NULL )
+						continue;
+					if( side2->shaderInfo == NULL )
+						continue;
+					if( w1->numpoints != w2->numpoints )
+						continue;
+					if( side1->culled == qtrue && side2->culled == qtrue )
+						continue;
+					
+					/* compare planes */
+					if( (side1->planenum & ~0x00000001) != (side2->planenum & ~0x00000001) )
+						continue;
+					
+					/* get autosprite and polygonoffset status */
+					if( side1->shaderInfo &&
+						(side1->shaderInfo->autosprite || side1->shaderInfo->polygonOffset) )
+						continue;
+					if( side2->shaderInfo &&
+						(side2->shaderInfo->autosprite || side2->shaderInfo->polygonOffset) )
+						continue;
+					
+					/* find first common point */
+					first = -1;
+					for( k = 0; k < numPoints; k++ )
+					{
+						if( VectorCompare( w1->p[ 0 ], w2->p[ k ] ) )
+						{
+							first = k;
+							k = numPoints;
+						}
+					}
+					if( first == -1 )
+						continue;
+					
+					/* find second common point (regardless of winding order) */
+					second = -1;
+					dir = 0;
+					if( (first + 1) < numPoints )
+						second = first + 1;
+					else
+						second = 0;
+					if( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) )
+						dir = 1;
+					else
+					{
+						if( first > 0 )
+							second = first - 1;
+						else
+							second = numPoints - 1;
+						if( CullVectorCompare( w1->p[ 1 ], w2->p[ second ] ) )
+							dir = -1;
+					}
+					if( dir == 0 )
+						continue;
+					
+					/* compare the rest of the points */
+					l = first;
+					for( k = 0; k < numPoints; k++ )
+					{
+						if( !CullVectorCompare( w1->p[ k ], w2->p[ l ] ) )
+							k = 100000;
+						
+						l += dir;
+						if( l < 0 )
+							l = numPoints - 1;
+						else if( l >= numPoints )
+							l = 0;
+					}
+					if( k >= 100000 )
+						continue;
+					
+					/* cull face 1 */
+					if( !side2->culled && !(side2->compileFlags & C_TRANSLUCENT) && !(side2->compileFlags & C_NODRAW) )
+					{
+						side1->culled = qtrue;
+						g_numCoinFaces++;
+					}
+					
+					if( side1->planenum == side2->planenum && side1->culled == qtrue )
+						continue;
+					
+					/* cull face 2 */
+					if( !side1->culled && !(side1->compileFlags & C_TRANSLUCENT) && !(side1->compileFlags & C_NODRAW) )
+					{
+						side2->culled = qtrue;
+						g_numCoinFaces++;
+					}
+				}
+			}
+		}
+	}
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d hidden faces culled\n", g_numHiddenFaces );
+	Sys_FPrintf( SYS_VRB, "%9d coincident faces culled\n", g_numCoinFaces );
+}
+
+
+
+
+/*
+ClipSidesIntoTree()
+
+creates side->visibleHull for all visible sides
+
+the drawsurf for a side will consist of the convex hull of
+all points in non-opaque clusters, which allows overlaps
+to be trimmed off automatically.
+*/
+
+void ClipSidesIntoTree( entity_t *e, tree_t *tree )
+{
+	brush_t		*b;
+	int				i;
+	winding_t		*w;
+	side_t			*side, *newSide;
+	shaderInfo_t	*si;
+  
+	
+	/* ydnar: cull brush sides */
+	CullSides( e );
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- ClipSidesIntoTree ---\n" );
+	
+	/* walk the brush list */
+	for( b = e->brushes; b; b = b->next )
+	{
+		/* walk the brush sides */
+		for( i = 0; i < b->numsides; i++ )
+		{
+			/* get side */
+			side = &b->sides[ i ];
+			if( side->winding == NULL )
+				continue;
+			
+			/* copy the winding */
+			w = CopyWinding( side->winding );
+			side->visibleHull = NULL;
+			ClipSideIntoTree_r( w, side, tree->headnode );
+			
+			/* anything left? */
+			w = side->visibleHull;
+			if( w == NULL )
+				continue;
+			
+			/* shader? */
+			si = side->shaderInfo;
+			if( si == NULL )
+				continue;
+			
+			/* don't create faces for non-visible sides */
+			/* ydnar: except indexed shaders, like common/terrain and nodraw fog surfaces */
+			if( (si->compileFlags & C_NODRAW) && si->indexed == qfalse && !(si->compileFlags & C_FOG) )
+				continue;
+			
+			/* always use the original winding for autosprites and noclip faces */
+			if( si->autosprite || si->noClip )
+				w = side->winding;
+			
+			/* save this winding as a visible surface */
+			DrawSurfaceForSide( e, b, side, w );
+
+			/* make a back side for fog */
+			if( !(si->compileFlags & C_FOG) )
+				continue;
+			
+			/* duplicate the up-facing side */
+			w = ReverseWinding( w );
+			newSide = safe_malloc( sizeof( *side ) );
+			*newSide = *side;
+			newSide->visibleHull = w;
+			newSide->planenum ^= 1;
+			
+			/* save this winding as a visible surface */
+			DrawSurfaceForSide( e, b, newSide, w );
+		}
+	}
+}
+
+
+
+/*
+
+this section deals with filtering drawsurfaces into the bsp tree,
+adding references to each leaf a surface touches
+
+*/
+
+/*
+AddReferenceToLeaf() - ydnar
+adds a reference to surface ds in the bsp leaf node
+*/
+
+int AddReferenceToLeaf( mapDrawSurface_t *ds, node_t *node )
+{
+	drawSurfRef_t	*dsr;
+	
+	
+	/* dummy check */
+	if( node->planenum != PLANENUM_LEAF || node->opaque )
+		return 0;
+	
+	/* try to find an existing reference */
+	for( dsr = node->drawSurfReferences; dsr; dsr = dsr->nextRef )
+	{
+		if( dsr->outputNum == numBSPDrawSurfaces )
+			return 0;
+	}
+	
+	/* add a new reference */
+	dsr = safe_malloc( sizeof( *dsr ) );
+	dsr->outputNum = numBSPDrawSurfaces;
+	dsr->nextRef = node->drawSurfReferences;
+	node->drawSurfReferences = dsr;
+	
+	/* ydnar: sky/skybox surfaces */
+	if( node->skybox )
+		ds->skybox = qtrue;
+	if( ds->shaderInfo->compileFlags & C_SKY )
+		node->sky = qtrue;
+	
+	/* return */
+	return 1;
+}
+
+
+
+/*
+AddReferenceToTree_r() - ydnar
+adds a reference to the specified drawsurface to every leaf in the tree
+*/
+
+int AddReferenceToTree_r( mapDrawSurface_t *ds, node_t *node, qboolean skybox )
+{
+	int		i, refs = 0;
+	
+	
+	/* dummy check */
+	if( node == NULL )
+		return 0;
+	
+	/* is this a decision node? */
+	if( node->planenum != PLANENUM_LEAF )
+	{
+		/* add to child nodes and return */
+		refs += AddReferenceToTree_r( ds, node->children[ 0 ], skybox );
+		refs += AddReferenceToTree_r( ds, node->children[ 1 ], skybox );
+		return refs;
+	}
+	
+	/* ydnar */
+	if( skybox )
+	{
+		/* skybox surfaces only get added to sky leaves */
+		if( !node->sky )
+			return 0;
+		
+		/* increase the leaf bounds */
+		for( i = 0; i < ds->numVerts; i++ )
+			AddPointToBounds( ds->verts[ i ].xyz, node->mins, node->maxs );
+	}
+	
+	/* add a reference */
+	return AddReferenceToLeaf( ds, node );
+}
+
+
+
+/*
+FilterPointIntoTree_r() - ydnar
+filters a single point from a surface into the tree
+*/
+
+int FilterPointIntoTree_r( vec3_t point, mapDrawSurface_t *ds, node_t *node )
+{
+	float			d;
+	plane_t			*plane;
+	int				refs = 0;
+	
+	
+	/* is this a decision node? */
+	if( node->planenum != PLANENUM_LEAF )
+	{
+		/* classify the point in relation to the plane */
+		plane = &mapplanes[ node->planenum ];
+		d = DotProduct( point, plane->normal ) - plane->dist;
+		
+		/* filter by this plane */
+		refs = 0;
+		if( d >= -ON_EPSILON )
+			refs += FilterPointIntoTree_r( point, ds, node->children[ 0 ] );
+		if( d <= ON_EPSILON )
+			refs += FilterPointIntoTree_r( point, ds, node->children[ 1 ] );
+		
+		/* return */
+		return refs;
+	}
+	
+	/* add a reference */
+	return AddReferenceToLeaf( ds, node );
+}
+
+
+
+/*
+FilterWindingIntoTree_r() - ydnar
+filters a winding from a drawsurface into the tree
+*/
+
+int FilterWindingIntoTree_r( winding_t *w, mapDrawSurface_t *ds, node_t *node )
+{
+	int				i, refs = 0;
+	plane_t			*p1, *p2;
+	vec4_t			plane1, plane2, reverse;
+	winding_t		*fat, *front, *back;
+	shaderInfo_t	*si;
+	
+	
+	/* get shaderinfo */
+	si = ds->shaderInfo;
+	
+	/* ydnar: is this the head node? */
+	if( node->parent == NULL && si != NULL &&
+		(si->mins[ 0 ] != 0.0f || si->maxs[ 0 ] != 0.0f ||
+		si->mins[ 1 ] != 0.0f || si->maxs[ 1 ] != 0.0f ||
+		si->mins[ 2 ] != 0.0f || si->maxs[ 2 ] != 0.0f) )
+	{
+		/* 'fatten' the winding by the shader mins/maxs (parsed from vertexDeform move) */
+		/* note this winding is completely invalid (concave, nonplanar, etc) */
+		fat = AllocWinding( w->numpoints * 3 );
+		fat->numpoints = w->numpoints * 3;
+		for( i = 0; i < w->numpoints; i++ )
+		{
+			VectorCopy( w->p[ i ], fat->p[ i ] );
+			VectorAdd( w->p[ i ], si->mins, fat->p[ i * 2 ] );
+			VectorAdd( w->p[ i ], si->maxs, fat->p[ i * 3 ] );
+		}
+		
+		FreeWinding( w );
+		w = fat;
+	}
+	
+	/* is this a decision node? */
+	if( node->planenum != PLANENUM_LEAF )
+	{	
+		/* get node plane */
+		p1 = &mapplanes[ node->planenum ];
+		VectorCopy( p1->normal, plane1 );
+		plane1[ 3 ] = p1->dist;
+		
+		/* check if surface is planar */
+		if( ds->planeNum >= 0 )
+		{
+			/* get surface plane */
+			p2 = &mapplanes[ ds->planeNum ];
+			VectorCopy( p2->normal, plane2 );
+			plane2[ 3 ] = p2->dist;
+			
+			#if 1
+				/* invert surface plane */
+				VectorSubtract( vec3_origin, plane2, reverse );
+				reverse[ 3 ] = -plane2[ 3 ];
+				
+				/* compare planes */
+				if( DotProduct( plane1, plane2 ) > 0.999f && fabs( plane1[ 3 ] - plane2[ 3 ] ) < 0.001f )
+					return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] );
+				if( DotProduct( plane1, reverse ) > 0.999f && fabs( plane1[ 3 ] - reverse[ 3 ] ) < 0.001f )
+					return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] );
+			#else
+				/* the drawsurf might have an associated plane, if so, force a filter here */
+				if( ds->planeNum == node->planenum )
+					return FilterWindingIntoTree_r( w, ds, node->children[ 0 ] );
+				if( ds->planeNum == (node->planenum ^ 1) )
+					return FilterWindingIntoTree_r( w, ds, node->children[ 1 ] );
+			#endif
+		}
+		
+		/* clip the winding by this plane */
+		ClipWindingEpsilon( w, plane1, plane1[ 3 ], ON_EPSILON, &front, &back );
+		
+		/* filter by this plane */
+		refs = 0;
+		if( front != NULL )
+			refs += FilterWindingIntoTree_r( front, ds, node->children[ 0 ] );
+		if( back != NULL )
+			refs += FilterWindingIntoTree_r( back, ds, node->children[ 1 ] );
+		FreeWinding( w );
+		
+		/* return */
+		return refs;
+	}
+	
+	/* add a reference */
+	return AddReferenceToLeaf( ds, node );
+}
+
+
+
+/*
+FilterFaceIntoTree()
+filters a planar winding face drawsurface into the bsp tree
+*/
+
+int	FilterFaceIntoTree( mapDrawSurface_t *ds, tree_t *tree )
+{
+	winding_t	*w;
+	int			refs = 0;
+	
+	
+	/* make a winding and filter it into the tree */
+	w = WindingFromDrawSurf( ds );
+	refs = FilterWindingIntoTree_r( w, ds, tree->headnode );
+	
+	/* return */
+	return refs;
+}
+
+
+
+/*
+FilterPatchIntoTree()
+subdivides a patch into an approximate curve and filters it into the tree
+*/
+
+#define	FILTER_SUBDIVISION		8
+
+static int FilterPatchIntoTree( mapDrawSurface_t *ds, tree_t *tree )
+{
+	int					i, x, y, refs;
+	mesh_t				src, *mesh;
+	winding_t			*w;
+	
+	
+	/* subdivide the surface */
+	src.width = ds->patchWidth;
+	src.height = ds->patchHeight;
+	src.verts = ds->verts;
+	mesh = SubdivideMesh( src, FILTER_SUBDIVISION, 32 );
+	
+	
+	/* filter each quad into the tree (fixme: use new patch x-triangulation code?) */
+	refs = 0;
+	for( y = 0; y < (mesh->height - 1); y++ )
+	{
+		for( x = 0; x < (mesh->width - 1); x++ )
+		{
+			/* triangle 1 */
+			w = AllocWinding( 3 );
+			w->numpoints = 3;
+			VectorCopy( mesh->verts[ y * mesh->width + x ].xyz, w->p[ 0 ] );
+			VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 1 ] );
+			VectorCopy( mesh->verts[ (y + 1) * mesh->width + x ].xyz, w->p[ 2 ] );
+			refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
+			
+			/* triangle 2 */
+			w = AllocWinding( 3 );
+			w->numpoints = 3;
+			VectorCopy( mesh->verts[ y * mesh->width + x + 1 ].xyz, w->p[ 0 ] );
+			VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x + 1 ].xyz, w->p[ 1 ] );
+			VectorCopy( mesh->verts[ (y + 1 ) * mesh->width + x ].xyz, w->p[ 2 ] );
+			refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
+		}
+	}
+	
+	/* use point filtering as well */
+	for( i = 0; i < (mesh->width * mesh->height); i++ )
+		refs += FilterPointIntoTree_r( mesh->verts[ i ].xyz, ds, tree->headnode );
+	
+	/* free the subdivided mesh and return */
+	FreeMesh( mesh );
+	return refs;
+}
+
+
+
+/*
+FilterTrianglesIntoTree()
+filters a triangle surface (meta, model) into the bsp
+*/
+
+static int FilterTrianglesIntoTree( mapDrawSurface_t *ds, tree_t *tree )
+{
+	int			i, refs;
+	winding_t	*w;
+	
+	
+	/* ydnar: gs mods: this was creating bogus triangles before */
+	refs = 0;
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		/* error check */
+		if( ds->indexes[ i ] >= ds->numVerts ||
+			ds->indexes[ i + 1 ] >= ds->numVerts ||
+			ds->indexes[ i + 2 ] >= ds->numVerts )
+			Error( "Index %d greater than vertex count %d", ds->indexes[ i ], ds->numVerts );
+		
+		/* make a triangle winding and filter it into the tree */
+		w = AllocWinding( 3 );
+		w->numpoints = 3;
+		VectorCopy( ds->verts[ ds->indexes[ i ] ].xyz, w->p[ 0 ] );
+		VectorCopy( ds->verts[ ds->indexes[ i + 1 ] ].xyz, w->p[ 1 ] );
+		VectorCopy( ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] );
+		refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
+	}
+	
+	/* use point filtering as well */
+	for( i = 0; i < ds->numVerts; i++ )
+		refs += FilterPointIntoTree_r( ds->verts[ i ].xyz, ds, tree->headnode );
+
+	return refs;
+}
+
+
+
+/*
+FilterFoliageIntoTree()
+filters a foliage surface (wolf et/splash damage)
+*/
+
+static int FilterFoliageIntoTree( mapDrawSurface_t *ds, tree_t *tree )
+{
+	int				f, i, refs;
+	bspDrawVert_t	*instance;
+	vec3_t			xyz;
+	winding_t		*w;
+	
+	
+	/* walk origin list */
+	refs = 0;
+	for( f = 0; f < ds->numFoliageInstances; f++ )
+	{
+		/* get instance */
+		instance = ds->verts + ds->patchHeight + f;
+		
+		/* walk triangle list */
+		for( i = 0; i < ds->numIndexes; i += 3 )
+		{
+			/* error check */
+			if( ds->indexes[ i ] >= ds->numVerts ||
+				ds->indexes[ i + 1 ] >= ds->numVerts ||
+				ds->indexes[ i + 2 ] >= ds->numVerts )
+				Error( "Index %d greater than vertex count %d", ds->indexes[ i ], ds->numVerts );
+			
+			/* make a triangle winding and filter it into the tree */
+			w = AllocWinding( 3 );
+			w->numpoints = 3;
+			VectorAdd( instance->xyz, ds->verts[ ds->indexes[ i ] ].xyz, w->p[ 0 ] );
+			VectorAdd( instance->xyz, ds->verts[ ds->indexes[ i + 1 ] ].xyz, w->p[ 1 ] );
+			VectorAdd( instance->xyz, ds->verts[ ds->indexes[ i + 2 ] ].xyz, w->p[ 2 ] );
+			refs += FilterWindingIntoTree_r( w, ds, tree->headnode );
+		}
+		
+		/* use point filtering as well */
+		for( i = 0; i < (ds->numVerts - ds->numFoliageInstances); i++ )
+		{
+			VectorAdd( instance->xyz, ds->verts[ i ].xyz, xyz );
+			refs += FilterPointIntoTree_r( xyz, ds, tree->headnode );
+		}
+	}
+	
+	return refs;
+}
+
+
+
+/*
+FilterFlareIntoTree()
+simple point filtering for flare surfaces
+*/
+static int FilterFlareSurfIntoTree( mapDrawSurface_t *ds, tree_t *tree )
+{
+	return FilterPointIntoTree_r( ds->lightmapOrigin, ds, tree->headnode );
+}
+
+
+
+/*
+EmitDrawVerts() - ydnar
+emits bsp drawverts from a map drawsurface
+*/
+
+void EmitDrawVerts( mapDrawSurface_t *ds, bspDrawSurface_t *out )
+{
+	int				i, k;
+	bspDrawVert_t	*dv;
+	shaderInfo_t	*si;
+	float			offset;
+	
+	
+	/* get stuff */
+	si = ds->shaderInfo;
+	offset = si->offset;
+	
+	/* copy the verts */
+	out->firstVert = numBSPDrawVerts;
+	out->numVerts = ds->numVerts;
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		/* allocate a new vert */
+		if( numBSPDrawVerts == MAX_MAP_DRAW_VERTS )
+			Error( "MAX_MAP_DRAW_VERTS" );
+		IncDrawVerts();
+		dv = &bspDrawVerts[ numBSPDrawVerts - 1 ];
+		
+		/* copy it */
+		memcpy( dv, &ds->verts[ i ], sizeof( *dv ) );
+		
+		/* offset? */
+		if( offset != 0.0f )
+			VectorMA( dv->xyz, offset, dv->normal, dv->xyz );
+		
+		/* expand model bounds
+		   necessary because of misc_model surfaces on entities
+		   note: does not happen on worldspawn as its bounds is only used for determining lightgrid bounds */
+		if( numBSPModels > 0 )
+			AddPointToBounds( dv->xyz, bspModels[ numBSPModels ].mins, bspModels[ numBSPModels ].maxs );
+		
+		/* debug color? */
+		if( debugSurfaces )
+		{
+			for( k = 0; k < MAX_LIGHTMAPS; k++ )
+				VectorCopy( debugColors[ (ds - mapDrawSurfs) % 12 ], dv->color[ k ] );
+		}
+	}
+}
+
+
+
+/*
+FindDrawIndexes() - ydnar
+this attempts to find a run of indexes in the bsp that match the given indexes
+this tends to reduce the size of the bsp index pool by 1/3 or more
+returns numIndexes + 1 if the search failed
+*/
+
+int FindDrawIndexes( int numIndexes, int *indexes )
+{
+	int		i, j, numTestIndexes;
+	
+	
+	/* dummy check */
+	if( numIndexes < 3 || numBSPDrawIndexes < numIndexes || indexes == NULL )
+		return numBSPDrawIndexes;
+	
+	/* set limit */
+	numTestIndexes = 1 + numBSPDrawIndexes - numIndexes;
+	
+	/* handle 3 indexes as a special case for performance */
+	if( numIndexes == 3 )
+	{
+		/* run through all indexes */
+		for( i = 0; i < numTestIndexes; i++ )
+		{
+			/* test 3 indexes */
+			if( indexes[ 0 ] == bspDrawIndexes[ i ] &&
+				indexes[ 1 ] == bspDrawIndexes[ i + 1 ] &&
+				indexes[ 2 ] == bspDrawIndexes[ i + 2 ] )
+			{
+				numRedundantIndexes += numIndexes;
+				return i;
+			}
+		}
+		
+		/* failed */
+		return numBSPDrawIndexes;
+	}
+	
+	/* handle 4 or more indexes */
+	for( i = 0; i < numTestIndexes; i++ )
+	{
+		/* test first 4 indexes */
+		if( indexes[ 0 ] == bspDrawIndexes[ i ] &&
+			indexes[ 1 ] == bspDrawIndexes[ i + 1 ] &&
+			indexes[ 2 ] == bspDrawIndexes[ i + 2 ] &&
+			indexes[ 3 ] == bspDrawIndexes[ i + 3 ] )
+		{
+			/* handle 4 indexes */
+			if( numIndexes == 4 )
+				return i;
+			
+			/* test the remainder */
+			for( j = 4; j < numIndexes; j++ )
+			{
+				if( indexes[ j ] != bspDrawIndexes[ i + j ] )
+					break;
+				else if( j == (numIndexes - 1) )
+				{
+					numRedundantIndexes += numIndexes;
+					return i;
+				}
+			}
+		}
+	}
+	
+	/* failed */
+	return numBSPDrawIndexes;
+}
+
+
+
+/*
+EmitDrawIndexes() - ydnar
+attempts to find an existing run of drawindexes before adding new ones
+*/
+
+void EmitDrawIndexes( mapDrawSurface_t *ds, bspDrawSurface_t *out )
+{
+	int			i;
+	
+	
+	/* attempt to use redundant indexing */
+	out->firstIndex = FindDrawIndexes( ds->numIndexes, ds->indexes );
+	out->numIndexes = ds->numIndexes;
+	if( out->firstIndex == numBSPDrawIndexes )
+	{
+		/* copy new unique indexes */
+		for( i = 0; i < ds->numIndexes; i++ )
+		{
+			if( numBSPDrawIndexes == MAX_MAP_DRAW_INDEXES )
+				Error( "MAX_MAP_DRAW_INDEXES" );
+			bspDrawIndexes[ numBSPDrawIndexes ] = ds->indexes[ i ];
+
+			/* validate the index */
+			if( ds->type != SURFACE_PATCH )
+			{
+				if( bspDrawIndexes[ numBSPDrawIndexes ] < 0 || bspDrawIndexes[ numBSPDrawIndexes ] >= ds->numVerts )
+				{
+					Sys_Printf( "WARNING: %d %s has invalid index %d (%d)\n",
+						numBSPDrawSurfaces,
+						ds->shaderInfo->shader,
+						bspDrawIndexes[ numBSPDrawIndexes ],
+						i );
+					bspDrawIndexes[ numBSPDrawIndexes ] = 0;
+				}
+			}
+			
+			/* increment index count */
+			numBSPDrawIndexes++;
+		}
+	}
+}
+
+
+
+
+/*
+EmitFlareSurface()
+emits a bsp flare drawsurface
+*/
+
+void EmitFlareSurface( mapDrawSurface_t *ds )
+{
+	int						i;
+	bspDrawSurface_t		*out;
+	
+	
+	/* ydnar: nuking useless flare drawsurfaces */
+	if( emitFlares == qfalse && ds->type != SURFACE_SHADER )
+		return;
+	
+	/* limit check */
+	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
+		Error( "MAX_MAP_DRAW_SURFS" );
+	
+	/* allocate a new surface */
+	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
+		Error( "MAX_MAP_DRAW_SURFS" );
+	out = &bspDrawSurfaces[ numBSPDrawSurfaces ];
+	ds->outputNum = numBSPDrawSurfaces;
+	numBSPDrawSurfaces++;
+	memset( out, 0, sizeof( *out ) );
+	
+	/* set it up */
+	out->surfaceType = MST_FLARE;
+	out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
+	out->fogNum = ds->fogNum;
+	
+	/* RBSP */
+	for( i = 0; i < MAX_LIGHTMAPS; i++ )
+	{
+		out->lightmapNum[ i ] = -3;
+		out->lightmapStyles[ i ] = LS_NONE;
+		out->vertexStyles[ i ] = LS_NONE;
+	}
+	out->lightmapStyles[ 0 ] = ds->lightStyle;
+	out->vertexStyles[ 0 ] = ds->lightStyle;
+	
+	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );			/* origin */
+	VectorCopy( ds->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );	/* color */
+	VectorCopy( ds->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
+	VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );	/* normal */
+	
+	/* add to count */
+	numSurfacesByType[ ds->type ]++;
+}
+
+
+
+/*
+EmitPatchSurface()
+emits a bsp patch drawsurface
+*/
+
+void EmitPatchSurface( mapDrawSurface_t *ds )
+{
+	int					i, j;
+	bspDrawSurface_t	*out;
+	int					surfaceFlags, contentFlags;
+	
+	
+	/* invert the surface if necessary */
+	if( ds->shaderInfo->invert )
+	{
+		bspDrawVert_t	*dv1, *dv2, temp;
+		
+
+		/* walk the verts, flip the normal */
+		for( i = 0; i < ds->numVerts; i++ )
+			VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal );
+		
+		/* walk the verts again, but this time reverse their order */
+		for( j = 0; j < ds->patchHeight; j++ )
+		{
+			for( i = 0; i < (ds->patchWidth / 2); i++ )
+			{
+				dv1 = &ds->verts[ j * ds->patchWidth + i ];
+				dv2 = &ds->verts[ j * ds->patchWidth + (ds->patchWidth - i - 1) ];
+				memcpy( &temp, dv1, sizeof( bspDrawVert_t ) );
+				memcpy( dv1, dv2, sizeof( bspDrawVert_t ) );
+				memcpy( dv2, &temp, sizeof( bspDrawVert_t ) );
+			}
+		}
+		
+		/* invert facing */
+		VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
+	}
+	
+	/* allocate a new surface */
+	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
+		Error( "MAX_MAP_DRAW_SURFS" );
+	out = &bspDrawSurfaces[ numBSPDrawSurfaces ];
+	ds->outputNum = numBSPDrawSurfaces;
+	numBSPDrawSurfaces++;
+	memset( out, 0, sizeof( *out ) );
+	
+	/* set it up */
+	out->surfaceType = MST_PATCH;
+	if( debugSurfaces )
+		out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL );
+	else if( patchMeta )
+	{
+		/* patch meta requires that we have nodraw patches for collision */
+		surfaceFlags = ds->shaderInfo->surfaceFlags;
+		contentFlags = ds->shaderInfo->contentFlags;
+		ApplySurfaceParm( "nodraw", &contentFlags, &surfaceFlags, NULL );
+		ApplySurfaceParm( "pointlight", &contentFlags, &surfaceFlags, NULL );
+		
+		/* we don't want this patch getting lightmapped */
+		VectorClear( ds->lightmapVecs[ 2 ] );
+		VectorClear( ds->lightmapAxis );
+		ds->sampleSize = 0;
+
+		/* emit the new fake shader */
+		out->shaderNum = EmitShader( ds->shaderInfo->shader, &contentFlags, &surfaceFlags );
+	}
+	else
+		out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
+	out->patchWidth = ds->patchWidth;
+	out->patchHeight = ds->patchHeight;
+	out->fogNum = ds->fogNum;
+	
+	/* RBSP */
+	for( i = 0; i < MAX_LIGHTMAPS; i++ )
+	{
+		out->lightmapNum[ i ] = -3;
+		out->lightmapStyles[ i ] = LS_NONE;
+		out->vertexStyles[ i ] = LS_NONE;
+	}
+	out->lightmapStyles[ 0 ] = LS_NORMAL;
+	out->vertexStyles[ 0 ] = LS_NORMAL;
+	
+	/* ydnar: gs mods: previously, the lod bounds were stored in lightmapVecs[ 0 ] and [ 1 ], moved to bounds[ 0 ] and [ 1 ] */
+	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
+	VectorCopy( ds->bounds[ 0 ], out->lightmapVecs[ 0 ] );
+	VectorCopy( ds->bounds[ 1 ], out->lightmapVecs[ 1 ] );
+	VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
+	
+	/* ydnar: gs mods: clear out the plane normal */
+	if( ds->planar == qfalse )
+		VectorClear( out->lightmapVecs[ 2 ] );
+	
+	/* emit the verts and indexes */
+	EmitDrawVerts( ds, out );
+	EmitDrawIndexes( ds, out );
+	
+	/* add to count */
+	numSurfacesByType[ ds->type ]++;
+}
+
+
+
+/*
+OptimizeTriangleSurface() - ydnar
+optimizes the vertex/index data in a triangle surface
+*/
+
+#define VERTEX_CACHE_SIZE	16
+
+static void OptimizeTriangleSurface( mapDrawSurface_t *ds )
+{
+	int		i, j, k, temp, first, best, bestScore, score;
+	int		vertexCache[ VERTEX_CACHE_SIZE + 1 ];	/* one more for optimizing insert */
+	int		*indexes;
+	
+	
+	/* certain surfaces don't get optimized */
+	if( ds->numIndexes <= VERTEX_CACHE_SIZE ||
+		ds->shaderInfo->autosprite )
+		return;
+	
+	/* create index scratch pad */
+	indexes = safe_malloc( ds->numIndexes * sizeof( *indexes ) );
+	memcpy( indexes, ds->indexes, ds->numIndexes * sizeof( *indexes ) );
+	
+	/* setup */
+	for( i = 0; i <= VERTEX_CACHE_SIZE && i < ds->numIndexes; i++ )
+		vertexCache[ i ] = indexes[ i ];
+	
+	/* add triangles in a vertex cache-aware order */
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		/* find best triangle given the current vertex cache */
+		first = -1;
+		best = -1;
+		bestScore = -1;
+		for( j = 0; j < ds->numIndexes; j += 3 )
+		{
+			/* valid triangle? */
+			if( indexes[ j ] != -1 )
+			{
+				/* set first if necessary */
+				if( first < 0 )
+					first = j;
+				
+				/* score the triangle */
+				score = 0;
+				for( k = 0; k < VERTEX_CACHE_SIZE; k++ )
+				{
+					if( indexes[ j ] == vertexCache[ k ] || indexes[ j + 1 ] == vertexCache[ k ] || indexes[ j + 2 ] == vertexCache[ k ] )
+						score++;
+				}
+				
+				/* better triangle? */
+				if( score > bestScore )
+				{
+					bestScore = score;
+					best = j;
+				}
+				
+				/* a perfect score of 3 means this triangle's verts are already present in the vertex cache */
+				if( score == 3 )
+					break;
+			}
+		}
+		
+		/* check if no decent triangle was found, and use first available */
+		if( best < 0 )
+			best = first;
+		
+		/* valid triangle? */
+		if( best >= 0 )
+		{
+			/* add triangle to vertex cache */
+			for( j = 0; j < 3; j++ )
+			{
+				for( k = 0; k < VERTEX_CACHE_SIZE; k++ )
+				{
+					if( indexes[ best + j ] == vertexCache[ k ] )
+						break;
+				}
+				
+				if( k >= VERTEX_CACHE_SIZE )
+				{
+					/* pop off top of vertex cache */
+					for( k = VERTEX_CACHE_SIZE; k > 0; k-- )
+						vertexCache[ k ] = vertexCache[ k - 1 ];
+					
+					/* add vertex */
+					vertexCache[ 0 ] = indexes[ best + j ];
+				}
+			}
+			
+			/* add triangle to surface */
+			ds->indexes[ i ] = indexes[ best ];
+			ds->indexes[ i + 1 ] = indexes[ best + 1 ];
+			ds->indexes[ i + 2 ] = indexes[ best + 2 ];
+			
+			/* clear from input pool */
+			indexes[ best ] = -1;
+			indexes[ best + 1 ] = -1;
+			indexes[ best + 2 ] = -1;
+			
+			/* sort triangle windings (312 -> 123) */
+			while( ds->indexes[ i ] > ds->indexes[ i + 1 ] || ds->indexes[ i ] > ds->indexes[ i + 2 ] )
+			{
+				temp = ds->indexes[ i ];
+				ds->indexes[ i ] = ds->indexes[ i + 1 ];
+				ds->indexes[ i + 1 ] = ds->indexes[ i + 2 ];
+				ds->indexes[ i + 2 ] = temp;
+			}
+		}
+	}
+	
+	/* clean up */
+	free( indexes );
+}
+
+
+
+/*
+EmitTriangleSurface()
+creates a bsp drawsurface from arbitrary triangle surfaces
+*/
+
+static void EmitTriangleSurface( mapDrawSurface_t *ds )
+{
+	int						i, temp;
+	bspDrawSurface_t		*out;
+	
+	
+	/* invert the surface if necessary */
+	if( ds->shaderInfo->invert )
+	{
+		/* walk the indexes, reverse the triangle order */
+		for( i = 0; i < ds->numIndexes; i += 3 )
+		{
+			temp = ds->indexes[ i ];
+			ds->indexes[ i ] = ds->indexes[ i + 1 ];
+			ds->indexes[ i + 1 ] = temp;
+		}
+		
+		/* walk the verts, flip the normal */
+		for( i = 0; i < ds->numVerts; i++ )
+			VectorScale( ds->verts[ i ].normal, -1.0f, ds->verts[ i ].normal );
+		
+		/* invert facing */
+		VectorScale( ds->lightmapVecs[ 2 ], -1.0f, ds->lightmapVecs[ 2 ] );
+	}
+	
+	/* allocate a new surface */
+	if( numBSPDrawSurfaces == MAX_MAP_DRAW_SURFS )
+		Error( "MAX_MAP_DRAW_SURFS" );
+	out = &bspDrawSurfaces[ numBSPDrawSurfaces ];
+	ds->outputNum = numBSPDrawSurfaces;
+	numBSPDrawSurfaces++;
+	memset( out, 0, sizeof( *out ) );
+	
+	/* ydnar/sd: handle wolf et foliage surfaces */
+	if( ds->type == SURFACE_FOLIAGE )
+		out->surfaceType = MST_FOLIAGE;
+	
+	/* ydnar: gs mods: handle lightmapped terrain (force to planar type) */
+	//%	else if( VectorLength( ds->lightmapAxis ) <= 0.0f || ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FOGHULL || debugSurfaces )
+	else if( (VectorLength( ds->lightmapAxis ) <= 0.0f && ds->planar == qfalse) || ds->type == SURFACE_TRIANGLES || ds->type == SURFACE_FOGHULL || debugSurfaces )
+		out->surfaceType = MST_TRIANGLE_SOUP;
+	
+	/* set to a planar face */
+	else
+		out->surfaceType = MST_PLANAR;
+	
+	/* set it up */
+	if( debugSurfaces )
+		out->shaderNum = EmitShader( "debugsurfaces", NULL, NULL );
+	else
+		out->shaderNum = EmitShader( ds->shaderInfo->shader, &ds->shaderInfo->contentFlags, &ds->shaderInfo->surfaceFlags );
+	out->patchWidth = ds->patchWidth;
+	out->patchHeight = ds->patchHeight;
+	out->fogNum = ds->fogNum;
+	
+	/* debug inset (push each triangle vertex towards the center of each triangle it is on */
+	if( debugInset )
+	{
+		bspDrawVert_t	*a, *b, *c;
+		vec3_t			cent, dir;
+
+		
+		/* walk triangle list */
+		for( i = 0; i < ds->numIndexes; i += 3 )
+		{
+			/* get verts */
+			a = &ds->verts[ ds->indexes[ i ] ];
+			b = &ds->verts[ ds->indexes[ i + 1 ] ];
+			c = &ds->verts[ ds->indexes[ i + 2 ] ];
+			
+			/* calculate centroid */
+			VectorCopy( a->xyz, cent );
+			VectorAdd( cent, b->xyz, cent );
+			VectorAdd( cent, c->xyz, cent );
+			VectorScale( cent, 1.0f / 3.0f, cent );
+			
+			/* offset each vertex */
+			VectorSubtract( cent, a->xyz, dir );
+			VectorNormalize( dir, dir );
+			VectorAdd( a->xyz, dir, a->xyz );
+			VectorSubtract( cent, b->xyz, dir );
+			VectorNormalize( dir, dir );
+			VectorAdd( b->xyz, dir, b->xyz );
+			VectorSubtract( cent, c->xyz, dir );
+			VectorNormalize( dir, dir );
+			VectorAdd( c->xyz, dir, c->xyz );
+		}
+	}
+	
+	/* RBSP */
+	for( i = 0; i < MAX_LIGHTMAPS; i++ )
+	{
+		out->lightmapNum[ i ] = -3;
+		out->lightmapStyles[ i ] = LS_NONE;
+		out->vertexStyles[ i ] = LS_NONE;
+	}
+	out->lightmapStyles[ 0 ] = LS_NORMAL;
+	out->vertexStyles[ 0 ] = LS_NORMAL;
+	
+	/* lightmap vectors (lod bounds for patches */
+	VectorCopy( ds->lightmapOrigin, out->lightmapOrigin );
+	VectorCopy( ds->lightmapVecs[ 0 ], out->lightmapVecs[ 0 ] );
+	VectorCopy( ds->lightmapVecs[ 1 ], out->lightmapVecs[ 1 ] );
+	VectorCopy( ds->lightmapVecs[ 2 ], out->lightmapVecs[ 2 ] );
+	
+	/* ydnar: gs mods: clear out the plane normal */
+	if( ds->planar == qfalse )
+		VectorClear( out->lightmapVecs[ 2 ] );
+	
+	/* optimize the surface's triangles */
+	OptimizeTriangleSurface( ds );
+	
+	/* emit the verts and indexes */
+	EmitDrawVerts( ds, out );
+	EmitDrawIndexes( ds, out );
+	
+	/* add to count */
+	numSurfacesByType[ ds->type ]++;
+}
+
+
+
+/*
+EmitFaceSurface()
+emits a bsp planar winding (brush face) drawsurface
+*/
+
+static void EmitFaceSurface( mapDrawSurface_t *ds )
+{
+	/* strip/fan finding was moved elsewhere */
+	StripFaceSurface( ds );
+	EmitTriangleSurface( ds );
+}
+
+
+
+/*
+MakeDebugPortalSurfs_r() - ydnar
+generates drawsurfaces for passable portals in the bsp
+*/
+
+static void MakeDebugPortalSurfs_r( node_t *node, shaderInfo_t *si )
+{
+	int					i, k, c, s;	
+	portal_t			*p;
+	winding_t			*w;
+	mapDrawSurface_t	*ds;
+	bspDrawVert_t		*dv;
+	
+	
+	/* recurse if decision node */
+	if( node->planenum != PLANENUM_LEAF)
+	{
+		MakeDebugPortalSurfs_r( node->children[ 0 ], si );
+		MakeDebugPortalSurfs_r( node->children[ 1 ], si );
+		return;
+	}
+	
+	/* don't bother with opaque leaves */
+	if( node->opaque )
+		return;
+	
+	/* walk the list of portals */
+	for( c = 0, p = node->portals; p != NULL; c++, p = p->next[ s ] )
+	{
+		/* get winding and side even/odd */
+		w = p->winding;
+		s = (p->nodes[ 1 ] == node);
+		
+		/* is this a valid portal for this leaf? */
+		if( w && p->nodes[ 0 ] == node )
+		{
+			/* is this portal passable? */
+			if( PortalPassable( p ) == qfalse )
+				continue;
+			
+			/* check max points */
+			if( w->numpoints > 64 )
+				Error( "MakePortalSurfs_r: w->numpoints = %d", w->numpoints );
+			
+			/* allocate a drawsurface */
+			ds = AllocDrawSurface( SURFACE_FACE );
+			ds->shaderInfo = si;
+			ds->planar = qtrue;
+			ds->sideRef = AllocSideRef( p->side, NULL );
+			ds->planeNum = FindFloatPlane( p->plane.normal, p->plane.dist, 0, NULL );
+			VectorCopy( p->plane.normal, ds->lightmapVecs[ 2 ] );
+			ds->fogNum = -1;
+			ds->numVerts = w->numpoints;
+			ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
+			memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
+			
+			/* walk the winding */
+			for( i = 0; i < ds->numVerts; i++ )
+			{
+				/* get vert */
+				dv = ds->verts + i;
+				
+				/* set it */
+				VectorCopy( w->p[ i ], dv->xyz );
+				VectorCopy( p->plane.normal, dv->normal );
+				dv->st[ 0 ] = 0;
+				dv->st[ 1 ] = 0;
+				for( k = 0; k < MAX_LIGHTMAPS; k++ )
+				{
+					VectorCopy( debugColors[ c % 12 ], dv->color[ k ] );
+					dv->color[ k ][ 3 ] = 32;
+				}
+			}
+		}
+	}
+}
+
+
+
+/*
+MakeDebugPortalSurfs() - ydnar
+generates drawsurfaces for passable portals in the bsp
+*/
+
+void MakeDebugPortalSurfs( tree_t *tree )
+{
+	shaderInfo_t	*si;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- MakeDebugPortalSurfs ---\n" );
+	
+	/* get portal debug shader */
+	si = ShaderInfoForShader( "debugportals" );
+	
+	/* walk the tree */
+	MakeDebugPortalSurfs_r( tree->headnode, si );
+}
+
+
+
+/*
+MakeFogHullSurfs()
+generates drawsurfaces for a foghull (this MUST use a sky shader)
+*/
+
+void MakeFogHullSurfs( entity_t *e, tree_t *tree, char *shader )
+{
+	shaderInfo_t		*si;
+	mapDrawSurface_t	*ds;
+	vec3_t				fogMins, fogMaxs;
+	int					i, indexes[] =
+						{
+							0, 1, 2, 0, 2, 3,
+							4, 7, 5, 5, 7, 6,
+							1, 5, 6, 1, 6, 2,
+							0, 4, 5, 0, 5, 1,
+							2, 6, 7, 2, 7, 3,
+							3, 7, 4, 3, 4, 0
+						};
+
+	
+	/* dummy check */
+	if( shader == NULL || shader[ 0 ] == '\0' )
+		return;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- MakeFogHullSurfs ---\n" );
+	
+	/* get hull bounds */
+	VectorCopy( mapMins, fogMins );
+	VectorCopy( mapMaxs, fogMaxs );
+	for( i = 0; i < 3; i++ )
+	{
+		fogMins[ i ] -= 128;
+		fogMaxs[ i ] += 128;
+	}
+	
+	/* get foghull shader */
+	si = ShaderInfoForShader( shader );
+	
+	/* allocate a drawsurface */
+	ds = AllocDrawSurface( SURFACE_FOGHULL );
+	ds->shaderInfo = si;
+	ds->fogNum = -1;
+	ds->numVerts = 8;
+	ds->verts = safe_malloc( ds->numVerts * sizeof( *ds->verts ) );
+	memset( ds->verts, 0, ds->numVerts * sizeof( *ds->verts ) );
+	ds->numIndexes = 36;
+	ds->indexes = safe_malloc( ds->numIndexes * sizeof( *ds->indexes ) );
+	memset( ds->indexes, 0, ds->numIndexes * sizeof( *ds->indexes ) );
+	
+	/* set verts */
+	VectorSet( ds->verts[ 0 ].xyz, fogMins[ 0 ], fogMins[ 1 ], fogMins[ 2 ] );
+	VectorSet( ds->verts[ 1 ].xyz, fogMins[ 0 ], fogMaxs[ 1 ], fogMins[ 2 ] );
+	VectorSet( ds->verts[ 2 ].xyz, fogMaxs[ 0 ], fogMaxs[ 1 ], fogMins[ 2 ] );
+	VectorSet( ds->verts[ 3 ].xyz, fogMaxs[ 0 ], fogMins[ 1 ], fogMins[ 2 ] );
+	
+	VectorSet( ds->verts[ 4 ].xyz, fogMins[ 0 ], fogMins[ 1 ], fogMaxs[ 2 ] );
+	VectorSet( ds->verts[ 5 ].xyz, fogMins[ 0 ], fogMaxs[ 1 ], fogMaxs[ 2 ] );
+	VectorSet( ds->verts[ 6 ].xyz, fogMaxs[ 0 ], fogMaxs[ 1 ], fogMaxs[ 2 ] );
+	VectorSet( ds->verts[ 7 ].xyz, fogMaxs[ 0 ], fogMins[ 1 ], fogMaxs[ 2 ] );
+	
+	/* set indexes */
+	memcpy( ds->indexes, indexes, ds->numIndexes * sizeof( *ds->indexes ) );
+}
+
+
+
+/*
+BiasSurfaceTextures()
+biases a surface's texcoords as close to 0 as possible
+*/
+
+void BiasSurfaceTextures( mapDrawSurface_t *ds )
+{
+	int		i;
+	
+	
+	/* calculate the surface texture bias */
+	CalcSurfaceTextureRange( ds );
+	
+	/* don't bias globaltextured shaders */
+	if( ds->shaderInfo->globalTexture )
+		return;
+	
+	/* bias the texture coordinates */
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		ds->verts[ i ].st[ 0 ] += ds->bias[ 0 ];
+		ds->verts[ i ].st[ 1 ] += ds->bias[ 1 ];
+	}
+}
+
+
+
+/*
+AddSurfaceModelsToTriangle_r()
+adds models to a specified triangle, returns the number of models added
+*/
+
+int AddSurfaceModelsToTriangle_r( mapDrawSurface_t *ds, surfaceModel_t *model, bspDrawVert_t **tri )
+{
+	bspDrawVert_t	mid, *tri2[ 3 ];
+	int				max, n, localNumSurfaceModels;
+	
+	
+	/* init */
+	localNumSurfaceModels = 0;
+	
+	/* subdivide calc */
+	{
+		int			i;
+		float		*a, *b, dx, dy, dz, dist, maxDist;
+		
+		
+		/* find the longest edge and split it */
+		max = -1;
+		maxDist = 0.0f;
+		for( i = 0; i < 3; i++ )
+		{
+			/* get verts */
+			a = tri[ i ]->xyz;
+			b = tri[ (i + 1) % 3 ]->xyz;
+			
+			/* get dists */
+			dx = a[ 0 ] - b[ 0 ];
+			dy = a[ 1 ] - b[ 1 ];
+			dz = a[ 2 ] - b[ 2 ];
+			dist = (dx * dx) + (dy * dy) + (dz * dz);
+			
+			/* longer? */
+			if( dist > maxDist )
+			{
+				maxDist = dist;
+				max = i;
+			}
+		}
+		
+		/* is the triangle small enough? */
+		if( max < 0 || maxDist <= (model->density * model->density) )
+		{
+			float	odds, r, angle;
+			vec3_t	origin, normal, scale, axis[ 3 ], angles;
+			m4x4_t	transform, temp;
+
+			
+			/* roll the dice (model's odds scaled by vertex alpha) */
+			odds = model->odds * (tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ] + tri[ 0 ]->color[ 0 ][ 3 ]) / 765.0f;
+			r = Random();
+			if( r > model->odds )
+				return 0;
+			
+			/* calculate scale */
+			r = model->minScale + Random() * (model->maxScale - model->minScale);
+			VectorSet( scale, r, r, r );
+			
+			/* calculate angle */
+			angle = model->minAngle + Random() * (model->maxAngle - model->minAngle);
+			
+			/* calculate average origin */
+			VectorCopy( tri[ 0 ]->xyz, origin );
+			VectorAdd( origin, tri[ 1 ]->xyz, origin );
+			VectorAdd( origin, tri[ 2 ]->xyz, origin );
+			VectorScale( origin, (1.0f / 3.0f), origin );
+			
+			/* clear transform matrix */
+			m4x4_identity( transform );
+
+			/* handle oriented models */
+			if( model->oriented )
+			{
+				/* set angles */
+				VectorSet( angles, 0.0f, 0.0f, angle );
+				
+				/* calculate average normal */
+				VectorCopy( tri[ 0 ]->normal, normal );
+				VectorAdd( normal, tri[ 1 ]->normal, normal );
+				VectorAdd( normal, tri[ 2 ]->normal, normal );
+				if( VectorNormalize( normal, axis[ 2 ] ) == 0.0f )
+					VectorCopy( tri[ 0 ]->normal, axis[ 2 ] );
+				
+				/* make perpendicular vectors */
+				MakeNormalVectors( axis[ 2 ], axis[ 1 ], axis[ 0 ] );
+				
+				/* copy to matrix */
+				m4x4_identity( temp );
+				temp[ 0 ] = axis[ 0 ][ 0 ];	temp[ 1 ] = axis[ 0 ][ 1 ];	temp[ 2 ] = axis[ 0 ][ 2 ];
+				temp[ 4 ] = axis[ 1 ][ 0 ];	temp[ 5 ] = axis[ 1 ][ 1 ];	temp[ 6 ] = axis[ 1 ][ 2 ];
+				temp[ 8 ] = axis[ 2 ][ 0 ];	temp[ 9 ] = axis[ 2 ][ 1 ];	temp[ 10 ] = axis[ 2 ][ 2 ];
+				
+				/* scale */
+				m4x4_scale_by_vec3( temp, scale );
+				
+				/* rotate around z axis */
+				m4x4_rotate_by_vec3( temp, angles, eXYZ );
+				
+				/* translate */
+				m4x4_translate_by_vec3( transform, origin );
+				
+				/* tranform into axis space */
+				m4x4_multiply_by_m4x4( transform, temp );
+			}
+			
+			/* handle z-up models */
+			else
+			{
+				/* set angles */
+				VectorSet( angles, 0.0f, 0.0f, angle );
+				
+				/* set matrix */
+				m4x4_pivoted_transform_by_vec3( transform, origin, angles, eXYZ, scale, vec3_origin );
+			}
+			
+			/* insert the model */
+			InsertModel( (char *) model->model, 0, transform, NULL, ds->celShader, ds->entityNum, ds->castShadows, ds->recvShadows, 0, ds->lightmapScale );
+			
+			/* return to sender */
+			return 1;
+		}
+	}
+	
+	/* split the longest edge and map it */
+	LerpDrawVert( tri[ max ], tri[ (max + 1) % 3 ], &mid );
+	
+	/* recurse to first triangle */
+	VectorCopy( tri, tri2 );
+	tri2[ max ] = &mid;
+	n = AddSurfaceModelsToTriangle_r( ds, model, tri2 );
+	if( n < 0 )
+		return n;
+	localNumSurfaceModels += n;
+	
+	/* recurse to second triangle */
+	VectorCopy( tri, tri2 );
+	tri2[ (max + 1) % 3 ] = &mid;
+	n = AddSurfaceModelsToTriangle_r( ds, model, tri2 );
+	if( n < 0 )
+		return n;
+	localNumSurfaceModels += n;
+	
+	/* return count */
+	return localNumSurfaceModels;
+}
+
+
+
+/*
+AddSurfaceModels()
+adds a surface's shader models to the surface
+*/
+
+int AddSurfaceModels( mapDrawSurface_t *ds )
+{
+	surfaceModel_t	*model;
+	int				i, x, y, n, pw[ 5 ], r, localNumSurfaceModels, iterations;
+	mesh_t			src, *mesh, *subdivided;
+	bspDrawVert_t	centroid, *tri[ 3 ];
+	float			alpha;
+	
+	
+	/* dummy check */
+	if( ds == NULL || ds->shaderInfo == NULL || ds->shaderInfo->surfaceModel == NULL )
+		return 0;
+	
+	/* init */
+	localNumSurfaceModels = 0;
+	
+	/* walk the model list */
+	for( model = ds->shaderInfo->surfaceModel; model != NULL; model = model->next )
+	{
+		/* switch on type */
+		switch( ds->type )
+		{
+			/* handle brush faces and decals */
+			case SURFACE_FACE:
+			case SURFACE_DECAL:
+				/* calculate centroid */
+				memset( &centroid, 0, sizeof( centroid ) );
+				alpha = 0.0f;
+				
+				/* walk verts */
+				for( i = 0; i < ds->numVerts; i++ )
+				{
+					VectorAdd( centroid.xyz, ds->verts[ i ].xyz, centroid.xyz );
+					VectorAdd( centroid.normal, ds->verts[ i ].normal, centroid.normal );
+					centroid.st[ 0 ] += ds->verts[ i ].st[ 0 ];
+					centroid.st[ 1 ] += ds->verts[ i ].st[ 1 ];
+					alpha += ds->verts[ i ].color[ 0 ][ 3 ];
+				}
+				
+				/* average */
+				centroid.xyz[ 0 ] /= ds->numVerts;
+				centroid.xyz[ 1 ] /= ds->numVerts;
+				centroid.xyz[ 2 ] /= ds->numVerts;
+				if( VectorNormalize( centroid.normal, centroid.normal ) == 0.0f )
+					VectorCopy( ds->verts[ 0 ].normal, centroid.normal );
+				centroid.st[ 0 ]  /= ds->numVerts;
+				centroid.st[ 1 ]  /= ds->numVerts;
+				alpha /= ds->numVerts;
+				centroid.color[ 0 ][ 0 ] = 0xFF;
+				centroid.color[ 0 ][ 1 ] = 0xFF;
+				centroid.color[ 0 ][ 2 ] = 0xFF;
+				centroid.color[ 0 ][ 2 ] = (alpha > 255.0f ? 0xFF : alpha);
+				
+				/* head vert is centroid */
+				tri[ 0 ] = &centroid;
+				
+				/* walk fanned triangles */
+				for( i = 0; i < ds->numVerts; i++ )
+				{
+					/* set triangle */
+					tri[ 1 ] = &ds->verts[ i ];
+					tri[ 2 ] = &ds->verts[ (i + 1) % ds->numVerts ];
+					
+					/* create models */
+					n = AddSurfaceModelsToTriangle_r( ds, model, tri );
+					if( n < 0 )
+						return n;
+					localNumSurfaceModels += n;
+				}
+				break;
+			
+			/* handle patches */
+			case SURFACE_PATCH:
+				/* subdivide the surface */
+				src.width = ds->patchWidth;
+				src.height = ds->patchHeight;
+				src.verts = ds->verts;
+				//%	subdivided = SubdivideMesh( src, 8.0f, 512 );
+				iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
+				subdivided = SubdivideMesh2( src, iterations );
+				
+				/* fit it to the curve and remove colinear verts on rows/columns */
+				PutMeshOnCurve( *subdivided );
+				mesh = RemoveLinearMeshColumnsRows( subdivided );
+				FreeMesh( subdivided );
+				
+				/* subdivide each quad to place the models */
+				for( y = 0; y < (mesh->height - 1); y++ )
+				{
+					for( x = 0; x < (mesh->width - 1); x++ )
+					{
+						/* set indexes */
+						pw[ 0 ] = x + (y * mesh->width);
+						pw[ 1 ] = x + ((y + 1) * mesh->width);
+						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+						pw[ 3 ] = x + 1 + (y * mesh->width);
+						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+						
+						/* set radix */
+						r = (x + y) & 1;
+						
+						/* triangle 1 */
+						tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
+						tri[ 1 ] = &mesh->verts[ pw[ r + 1 ] ];
+						tri[ 2 ] = &mesh->verts[ pw[ r + 2 ] ];
+						n = AddSurfaceModelsToTriangle_r( ds, model, tri );
+						if( n < 0 )
+							return n;
+						localNumSurfaceModels += n;
+						
+						/* triangle 2 */
+						tri[ 0 ] = &mesh->verts[ pw[ r + 0 ] ];
+						tri[ 1 ] = &mesh->verts[ pw[ r + 2 ] ];
+						tri[ 2 ] = &mesh->verts[ pw[ r + 3 ] ];
+						n = AddSurfaceModelsToTriangle_r( ds, model, tri );
+						if( n < 0 )
+							return n;
+						localNumSurfaceModels += n;
+					}
+				}
+				
+				/* free the subdivided mesh */
+				FreeMesh( mesh );
+				break;
+			
+			/* handle triangle surfaces */
+			case SURFACE_TRIANGLES:
+			case SURFACE_FORCED_META:
+			case SURFACE_META:
+				/* walk the triangle list */
+				for( i = 0; i < ds->numIndexes; i += 3 )
+				{
+					tri[ 0 ] = &ds->verts[ ds->indexes[ i ] ];
+					tri[ 1 ] = &ds->verts[ ds->indexes[ i + 1 ] ];
+					tri[ 2 ] = &ds->verts[ ds->indexes[ i + 2 ] ];
+					n = AddSurfaceModelsToTriangle_r( ds, model, tri );
+					if( n < 0 )
+						return n;
+					localNumSurfaceModels += n;
+				}
+				break;
+			
+			/* no support for flares, foghull, etc */
+			default:
+				break;
+		}
+	}
+	
+	/* return count */
+	return localNumSurfaceModels;
+}
+
+
+
+/*
+AddEntitySurfaceModels() - ydnar
+adds surfacemodels to an entity's surfaces
+*/
+
+void AddEntitySurfaceModels( entity_t *e )
+{
+	int		i;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- AddEntitySurfaceModels ---\n" );
+	
+	/* walk the surface list */
+	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
+		numSurfaceModels += AddSurfaceModels( &mapDrawSurfs[ i ] );
+}
+
+
+
+/*
+FilterDrawsurfsIntoTree()
+upon completion, all drawsurfs that actually generate a reference
+will have been emited to the bspfile arrays, and the references
+will have valid final indexes
+*/
+
+void FilterDrawsurfsIntoTree( entity_t *e, tree_t *tree )
+{
+	int					i, j;
+	mapDrawSurface_t	*ds;
+	shaderInfo_t		*si;
+	vec3_t				origin, mins, maxs;
+	int					refs;
+	int					numSurfs, numRefs, numSkyboxSurfaces;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- FilterDrawsurfsIntoTree ---\n" );
+	
+	/* filter surfaces into the tree */
+	numSurfs = 0;
+	numRefs = 0;
+	numSkyboxSurfaces = 0;
+	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
+	{
+		/* get surface and try to early out */
+		ds = &mapDrawSurfs[ i ];
+		if( ds->numVerts == 0 && ds->type != SURFACE_FLARE && ds->type != SURFACE_SHADER )
+			continue;
+		
+		/* get shader */
+		si = ds->shaderInfo;
+		
+		/* ydnar: skybox surfaces are special */
+		if( ds->skybox )
+		{
+			refs = AddReferenceToTree_r( ds, tree->headnode, qtrue );
+			ds->skybox = qfalse;
+		}
+		else
+		{
+			/* refs initially zero */
+			refs = 0;
+			
+			/* ydnar: apply alphamod */
+			AlphaMod( ds->shaderInfo->alphaMod, ds->numVerts, ds->verts );
+			
+			/* apply texture coordinate mods */
+			for( j = 0; j < ds->numVerts; j++ )
+				TcMod( si->mod, ds->verts[ j ].st );
+			
+			/* ydnar: make fur surfaces */
+			if( si->furNumLayers > 0 )
+				Fur( ds );
+			
+			/* ydnar/sd: make foliage surfaces */
+			if( si->foliage != NULL )
+				Foliage( ds );
+			
+			/* create a flare surface if necessary */
+			if( si->flareShader[ 0 ] )
+				AddSurfaceFlare( ds, e->origin );
+			
+			/* ydnar: don't emit nodraw surfaces (like nodraw fog) */
+			if( si != NULL && (si->compileFlags & C_NODRAW) && ds->type != SURFACE_PATCH )
+				continue;
+			
+			/* ydnar: bias the surface textures */
+			BiasSurfaceTextures( ds );
+			
+			/* ydnar: globalizing of fog volume handling (eek a hack) */
+			if( e != entities && si->noFog == qfalse )
+			{
+				/* find surface origin and offset by entity origin */
+				VectorAdd( ds->mins, ds->maxs, origin );
+				VectorScale( origin, 0.5f, origin );
+				VectorAdd( origin, e->origin, origin );
+				
+				VectorAdd( ds->mins, e->origin, mins );
+				VectorAdd( ds->maxs, e->origin, maxs );
+				
+				/* set the fog number for this surface */
+				ds->fogNum = FogForBounds( mins, maxs, 1.0f );	//%	FogForPoint( origin, 0.0f );
+			}
+		}
+		
+		/* ydnar: gs mods: handle the various types of surfaces */
+		switch( ds->type )
+		{
+			/* handle brush faces */
+			case SURFACE_FACE:
+			case SURFACE_DECAL:
+				if( refs == 0 )
+					refs = FilterFaceIntoTree( ds, tree );
+				if( refs > 0 )
+					EmitFaceSurface( ds );
+				break;
+			
+			/* handle patches */
+			case SURFACE_PATCH:
+				if( refs == 0 )
+					refs = FilterPatchIntoTree( ds, tree );
+				if( refs > 0 )
+					EmitPatchSurface( ds );
+				break;
+			
+			/* handle triangle surfaces */
+			case SURFACE_TRIANGLES:
+			case SURFACE_FORCED_META:
+			case SURFACE_META:
+				//%	Sys_FPrintf( SYS_VRB, "Surface %4d: [%1d] %4d verts %s\n", numSurfs, ds->planar, ds->numVerts, si->shader );
+				if( refs == 0 )
+					refs = FilterTrianglesIntoTree( ds, tree );
+				if( refs > 0 )
+					EmitTriangleSurface( ds );
+				break;
+			
+			/* handle foliage surfaces (splash damage/wolf et) */
+			case SURFACE_FOLIAGE:
+				//%	Sys_FPrintf( SYS_VRB, "Surface %4d: [%d] %4d verts %s\n", numSurfs, ds->numFoliageInstances, ds->numVerts, si->shader );
+				if( refs == 0 )
+					refs = FilterFoliageIntoTree( ds, tree );
+				if( refs > 0 )
+					EmitTriangleSurface( ds );
+				break;
+			
+			/* handle foghull surfaces */
+			case SURFACE_FOGHULL:
+				if( refs == 0 )
+					refs = AddReferenceToTree_r( ds, tree->headnode, qfalse );
+				if( refs > 0 )
+					EmitTriangleSurface( ds );
+				break;
+			
+			/* handle flares */
+			case SURFACE_FLARE:
+				if( refs == 0 )
+					refs = FilterFlareSurfIntoTree( ds, tree );
+				if( refs > 0 )
+					EmitFlareSurface( ds );
+				break;
+			
+			/* handle shader-only surfaces */
+			case SURFACE_SHADER:
+				refs = 1;
+				EmitFlareSurface( ds );
+				break;
+			
+			/* no references */
+			default:
+				refs = 0;
+				break;
+		}
+		
+		/* tot up the references */
+		if( refs > 0 )
+		{
+			/* tot up counts */
+			numSurfs++;
+			numRefs += refs;
+			
+			/* emit extra surface data */
+			SetSurfaceExtra( ds, numBSPDrawSurfaces - 1 );
+			//%	Sys_FPrintf( SYS_VRB, "%d verts %d indexes\n", ds->numVerts, ds->numIndexes );
+			
+			/* one last sanity check */
+			{
+				bspDrawSurface_t	*out;
+				out = &bspDrawSurfaces[ numBSPDrawSurfaces - 1 ];
+				if( out->numVerts == 3 && out->numIndexes > 3 )
+				{
+					Sys_Printf( "\nWARNING: Potentially bad %s surface (%d: %d, %d)\n     %s\n",
+						surfaceTypes[ ds->type ],
+						numBSPDrawSurfaces - 1, out->numVerts, out->numIndexes, si->shader );
+				}
+			}
+			
+			/* ydnar: handle skybox surfaces */
+			if( ds->skybox )
+			{
+				MakeSkyboxSurface( ds );
+				numSkyboxSurfaces++;
+			}
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d references\n", numRefs );
+	Sys_FPrintf( SYS_VRB, "%9d (%d) emitted drawsurfs\n", numSurfs, numBSPDrawSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d stripped face surfaces\n", numStripSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d fanned face surfaces\n", numFanSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d surface models generated\n", numSurfaceModels );
+	Sys_FPrintf( SYS_VRB, "%9d skybox surfaces generated\n", numSkyboxSurfaces );
+	for( i = 0; i < NUM_SURFACE_TYPES; i++ )
+		Sys_FPrintf( SYS_VRB, "%9d %s surfaces\n", numSurfacesByType[ i ], surfaceTypes[ i ] );
+	
+	Sys_FPrintf( SYS_VRB, "%9d redundant indexes supressed, saving %d Kbytes\n", numRedundantIndexes, (numRedundantIndexes * 4 / 1024) );
+}
+
+
+
diff --git a/tools/quake3/q3map2/surface_extra.c b/tools/quake3/q3map2/surface_extra.c
index d5d47962..ffb8ad9e 100644
--- a/tools/quake3/q3map2/surface_extra.c
+++ b/tools/quake3/q3map2/surface_extra.c
@@ -1,444 +1,444 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define SURFACE_EXTRA_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/* -------------------------------------------------------------------------------
-
-ydnar: srf file module
-
-------------------------------------------------------------------------------- */
-
-typedef struct surfaceExtra_s
-{
-	mapDrawSurface_t		*mds;
-	shaderInfo_t			*si;
-	int						parentSurfaceNum;
-	int						entityNum;
-	int						castShadows, recvShadows;
-	int						sampleSize;
-	float					longestCurve;
-	vec3_t					lightmapAxis;
-}
-surfaceExtra_t;
-
-#define GROW_SURFACE_EXTRAS	1024
-
-int							numSurfaceExtras = 0;
-int							maxSurfaceExtras = 0;
-surfaceExtra_t				*surfaceExtras;
-surfaceExtra_t				seDefault = { NULL, NULL, -1, 0, WORLDSPAWN_CAST_SHADOWS, WORLDSPAWN_RECV_SHADOWS, 0, 0, { 0, 0, 0 } };
-
-
-
-/*
-AllocSurfaceExtra()
-allocates a new extra storage
-*/
-
-static surfaceExtra_t *AllocSurfaceExtra( void )
-{
-	surfaceExtra_t	*se;
-	
-	
-	/* enough space? */
-	if( numSurfaceExtras >= maxSurfaceExtras )
-	{
-		/* reallocate more room */
-		maxSurfaceExtras += GROW_SURFACE_EXTRAS;
-		se = safe_malloc( maxSurfaceExtras * sizeof( surfaceExtra_t ) );
-		if( surfaceExtras != NULL )
-		{
-			memcpy( se, surfaceExtras, numSurfaceExtras * sizeof( surfaceExtra_t ) );
-			free( surfaceExtras );
-		}
-		surfaceExtras = se;
-	}
-	
-	/* add another */
-	se = &surfaceExtras[ numSurfaceExtras ];
-	numSurfaceExtras++;
-	memcpy( se, &seDefault, sizeof( surfaceExtra_t ) );
-	
-	/* return it */
-	return se;
-}
-
-
-
-/*
-SetDefaultSampleSize()
-sets the default lightmap sample size
-*/
-
-void SetDefaultSampleSize( int sampleSize )
-{
-	seDefault.sampleSize = sampleSize;
-}
-
-
-
-/*
-SetSurfaceExtra()
-stores extra (q3map2) data for the specific numbered drawsurface
-*/
-
-void SetSurfaceExtra( mapDrawSurface_t *ds, int num )
-{
-	surfaceExtra_t	*se;
-	
-	
-	/* dummy check */
-	if( ds == NULL || num < 0 )
-		return;
-	
-	/* get a new extra */
-	se = AllocSurfaceExtra();
-	
-	/* copy out the relevant bits */
-	se->mds = ds;
-	se->si = ds->shaderInfo;
-	se->parentSurfaceNum = ds->parent != NULL ? ds->parent->outputNum : -1;
-	se->entityNum = ds->entityNum;
-	se->castShadows = ds->castShadows;
-	se->recvShadows = ds->recvShadows;
-	se->sampleSize = ds->sampleSize;
-	se->longestCurve = ds->longestCurve;
-	VectorCopy( ds->lightmapAxis, se->lightmapAxis );
-	
-	/* debug code */
-	//%	Sys_FPrintf( SYS_VRB, "SetSurfaceExtra(): entityNum = %d\n", ds->entityNum );
-}
-
-
-
-/*
-GetSurfaceExtra*()
-getter functions for extra surface data
-*/
-
-static surfaceExtra_t *GetSurfaceExtra( int num )
-{
-	if( num < 0 || num >= numSurfaceExtras )
-		return &seDefault;
-	return &surfaceExtras[ num ];
-}
-
-
-shaderInfo_t *GetSurfaceExtraShaderInfo( int num )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	return se->si;
-}
-
-
-int GetSurfaceExtraParentSurfaceNum( int num )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	return se->parentSurfaceNum;
-}
-
-
-int GetSurfaceExtraEntityNum( int num )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	return se->entityNum;
-}
-
-
-int GetSurfaceExtraCastShadows( int num )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	return se->castShadows;
-}
-
-
-int GetSurfaceExtraRecvShadows( int num )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	return se->recvShadows;
-}
-
-
-int GetSurfaceExtraSampleSize( int num )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	return se->sampleSize;
-}
-
-
-float GetSurfaceExtraLongestCurve( int num )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	return se->longestCurve;
-}
-
-
-void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis )
-{
-	surfaceExtra_t	*se = GetSurfaceExtra( num );
-	VectorCopy( se->lightmapAxis, lightmapAxis );
-}
-
-
-
-
-/*
-WriteSurfaceExtraFile()
-writes out a surface info file (<map>.srf)
-*/
-
-void WriteSurfaceExtraFile( const char *path )
-{
-	char			srfPath[ 1024 ];
-	FILE			*sf;
-	surfaceExtra_t	*se;
-	int				i;
-	
-	
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' )
-		return;
-	
-	/* note it */
-	Sys_Printf( "--- WriteSurfaceExtraFile ---\n" );
-	
-	/* open the file */
-	strcpy( srfPath, path );
-	StripExtension( srfPath );
-	strcat( srfPath, ".srf" );
-	Sys_Printf( "Writing %s\n", srfPath );
-	sf = fopen( srfPath, "w" );
-	if( sf == NULL )
-		Error( "Error opening %s for writing", srfPath );
-	
-	/* lap through the extras list */
-	for( i = -1; i < numSurfaceExtras; i++ )
-	{
-		/* get extra */
-		se = GetSurfaceExtra( i );
-		
-		/* default or surface num? */
-		if( i < 0 )
-			fprintf( sf, "default" );
-		else
-			fprintf( sf, "%d", i );
-		
-		/* valid map drawsurf? */
-		if( se->mds == NULL )
-			fprintf( sf, "\n" );
-		else
-		{
-			fprintf( sf, " // %s V: %d I: %d %s\n",
-				surfaceTypes[ se->mds->type ],
-				se->mds->numVerts,
-				se->mds->numIndexes,
-				(se->mds->planar ? "planar" : "") );
-		}
-		
-		/* open braces */
-		fprintf( sf, "{\n" );
-		
-			/* shader */
-			if( se->si != NULL )
-				fprintf( sf, "\tshader %s\n", se->si->shader );
-			
-			/* parent surface number */
-			if( se->parentSurfaceNum != seDefault.parentSurfaceNum )
-				fprintf( sf, "\tparent %d\n", se->parentSurfaceNum );
-			
-			/* entity number */
-			if( se->entityNum != seDefault.entityNum )
-				fprintf( sf, "\tentity %d\n", se->entityNum );
-			
-			/* cast shadows */
-			if( se->castShadows != seDefault.castShadows || se == &seDefault )
-				fprintf( sf, "\tcastShadows %d\n", se->castShadows );
-			
-			/* recv shadows */
-			if( se->recvShadows != seDefault.recvShadows || se == &seDefault )
-				fprintf( sf, "\treceiveShadows %d\n", se->recvShadows );
-			
-			/* lightmap sample size */
-			if( se->sampleSize != seDefault.sampleSize || se == &seDefault )
-				fprintf( sf, "\tsampleSize %d\n", se->sampleSize );
-			
-			/* longest curve */
-			if( se->longestCurve != seDefault.longestCurve || se == &seDefault )
-				fprintf( sf, "\tlongestCurve %f\n", se->longestCurve );
-			
-			/* lightmap axis vector */
-			if( VectorCompare( se->lightmapAxis, seDefault.lightmapAxis ) == qfalse )
-				fprintf( sf, "\tlightmapAxis ( %f %f %f )\n", se->lightmapAxis[ 0 ], se->lightmapAxis[ 1 ], se->lightmapAxis[ 2 ] );
-		
-		/* close braces */
-		fprintf( sf, "}\n\n" );
-	}
-	
-	/* close the file */
-	fclose( sf );
-}
-
-
-
-/*
-LoadSurfaceExtraFile()
-reads a surface info file (<map>.srf)
-*/
-
-void LoadSurfaceExtraFile( const char *path )
-{
-	char			srfPath[ 1024 ];
-	surfaceExtra_t	*se;
-	int				surfaceNum, size;
-	byte			*buffer;
-	
-	
-	/* dummy check */
-	if( path == NULL || path[ 0 ] == '\0' )
-		return;
-	
-	/* load the file */
-	strcpy( srfPath, path );
-	StripExtension( srfPath );
-	strcat( srfPath, ".srf" );
-	Sys_Printf( "Loading %s\n", srfPath );
-	size = LoadFile( srfPath, (void**) &buffer );
-	if( size <= 0 )
-	{
-		Sys_Printf( "WARNING: Unable to find surface file %s, using defaults.\n", srfPath );
-		return;
-	}
-	
-	/* parse the file */
-	ParseFromMemory( buffer, size );
-	
-	/* tokenize it */
-	while( 1 )
-	{
-		/* test for end of file */
-		if( !GetToken( qtrue ) )
-			break;
-		
-		/* default? */
-		if( !Q_stricmp( token, "default" ) )
-			se = &seDefault;
-
-		/* surface number */
-		else
-		{
-			surfaceNum = atoi( token );
-			if( surfaceNum < 0 || surfaceNum > MAX_MAP_DRAW_SURFS )
-				Error( "ReadSurfaceExtraFile(): %s, line %d: bogus surface num %d", srfPath, scriptline, surfaceNum );
-			while( surfaceNum >= numSurfaceExtras )
-				se = AllocSurfaceExtra();
-			se = &surfaceExtras[ surfaceNum ];
-		}
-		
-		/* handle { } section */
-		if( !GetToken( qtrue ) || strcmp( token, "{" ) )
-			Error( "ReadSurfaceExtraFile(): %s, line %d: { not found", srfPath, scriptline );
-		while( 1 )
-		{
-			if( !GetToken( qtrue ) )
-				break;
-			if( !strcmp( token, "}" ) )
-				break;
-			
-			/* shader */
-			if( !Q_stricmp( token, "shader" ) )
-			{
-				GetToken( qfalse );
-				se->si = ShaderInfoForShader( token );
-			}
-			
-			/* parent surface number */
-			else if( !Q_stricmp( token, "parent" ) )
-			{
-				GetToken( qfalse );
-				se->parentSurfaceNum = atoi( token );
-			}
-			
-			/* entity number */
-			else if( !Q_stricmp( token, "entity" ) )
-			{
-				GetToken( qfalse );
-				se->entityNum = atoi( token );
-			}
-			
-			/* cast shadows */
-			else if( !Q_stricmp( token, "castShadows" ) )
-			{
-				GetToken( qfalse );
-				se->castShadows = atoi( token );
-			}
-			
-			/* recv shadows */
-			else if( !Q_stricmp( token, "receiveShadows" ) )
-			{
-				GetToken( qfalse );
-				se->recvShadows = atoi( token );
-			}
-			
-			/* lightmap sample size */
-			else if( !Q_stricmp( token, "sampleSize" ) )
-			{
-				GetToken( qfalse );
-				se->sampleSize = atoi( token );
-			}
-			
-			/* longest curve */
-			else if( !Q_stricmp( token, "longestCurve" ) )
-			{
-				GetToken( qfalse );
-				se->longestCurve = atof( token );
-			}
-			
-			/* lightmap axis vector */
-			else if( !Q_stricmp( token, "lightmapAxis" ) )
-				Parse1DMatrix( 3, se->lightmapAxis );
-			
-			/* ignore all other tokens on the line */
-			while( TokenAvailable() )
-				GetToken( qfalse );
-		}
-	}
-	
-	/* free the buffer */
-	free( buffer );
-}
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define SURFACE_EXTRA_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/* -------------------------------------------------------------------------------
+
+ydnar: srf file module
+
+------------------------------------------------------------------------------- */
+
+typedef struct surfaceExtra_s
+{
+	mapDrawSurface_t		*mds;
+	shaderInfo_t			*si;
+	int						parentSurfaceNum;
+	int						entityNum;
+	int						castShadows, recvShadows;
+	int						sampleSize;
+	float					longestCurve;
+	vec3_t					lightmapAxis;
+}
+surfaceExtra_t;
+
+#define GROW_SURFACE_EXTRAS	1024
+
+int							numSurfaceExtras = 0;
+int							maxSurfaceExtras = 0;
+surfaceExtra_t				*surfaceExtras;
+surfaceExtra_t				seDefault = { NULL, NULL, -1, 0, WORLDSPAWN_CAST_SHADOWS, WORLDSPAWN_RECV_SHADOWS, 0, 0, { 0, 0, 0 } };
+
+
+
+/*
+AllocSurfaceExtra()
+allocates a new extra storage
+*/
+
+static surfaceExtra_t *AllocSurfaceExtra( void )
+{
+	surfaceExtra_t	*se;
+	
+	
+	/* enough space? */
+	if( numSurfaceExtras >= maxSurfaceExtras )
+	{
+		/* reallocate more room */
+		maxSurfaceExtras += GROW_SURFACE_EXTRAS;
+		se = safe_malloc( maxSurfaceExtras * sizeof( surfaceExtra_t ) );
+		if( surfaceExtras != NULL )
+		{
+			memcpy( se, surfaceExtras, numSurfaceExtras * sizeof( surfaceExtra_t ) );
+			free( surfaceExtras );
+		}
+		surfaceExtras = se;
+	}
+	
+	/* add another */
+	se = &surfaceExtras[ numSurfaceExtras ];
+	numSurfaceExtras++;
+	memcpy( se, &seDefault, sizeof( surfaceExtra_t ) );
+	
+	/* return it */
+	return se;
+}
+
+
+
+/*
+SetDefaultSampleSize()
+sets the default lightmap sample size
+*/
+
+void SetDefaultSampleSize( int sampleSize )
+{
+	seDefault.sampleSize = sampleSize;
+}
+
+
+
+/*
+SetSurfaceExtra()
+stores extra (q3map2) data for the specific numbered drawsurface
+*/
+
+void SetSurfaceExtra( mapDrawSurface_t *ds, int num )
+{
+	surfaceExtra_t	*se;
+	
+	
+	/* dummy check */
+	if( ds == NULL || num < 0 )
+		return;
+	
+	/* get a new extra */
+	se = AllocSurfaceExtra();
+	
+	/* copy out the relevant bits */
+	se->mds = ds;
+	se->si = ds->shaderInfo;
+	se->parentSurfaceNum = ds->parent != NULL ? ds->parent->outputNum : -1;
+	se->entityNum = ds->entityNum;
+	se->castShadows = ds->castShadows;
+	se->recvShadows = ds->recvShadows;
+	se->sampleSize = ds->sampleSize;
+	se->longestCurve = ds->longestCurve;
+	VectorCopy( ds->lightmapAxis, se->lightmapAxis );
+	
+	/* debug code */
+	//%	Sys_FPrintf( SYS_VRB, "SetSurfaceExtra(): entityNum = %d\n", ds->entityNum );
+}
+
+
+
+/*
+GetSurfaceExtra*()
+getter functions for extra surface data
+*/
+
+static surfaceExtra_t *GetSurfaceExtra( int num )
+{
+	if( num < 0 || num >= numSurfaceExtras )
+		return &seDefault;
+	return &surfaceExtras[ num ];
+}
+
+
+shaderInfo_t *GetSurfaceExtraShaderInfo( int num )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	return se->si;
+}
+
+
+int GetSurfaceExtraParentSurfaceNum( int num )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	return se->parentSurfaceNum;
+}
+
+
+int GetSurfaceExtraEntityNum( int num )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	return se->entityNum;
+}
+
+
+int GetSurfaceExtraCastShadows( int num )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	return se->castShadows;
+}
+
+
+int GetSurfaceExtraRecvShadows( int num )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	return se->recvShadows;
+}
+
+
+int GetSurfaceExtraSampleSize( int num )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	return se->sampleSize;
+}
+
+
+float GetSurfaceExtraLongestCurve( int num )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	return se->longestCurve;
+}
+
+
+void GetSurfaceExtraLightmapAxis( int num, vec3_t lightmapAxis )
+{
+	surfaceExtra_t	*se = GetSurfaceExtra( num );
+	VectorCopy( se->lightmapAxis, lightmapAxis );
+}
+
+
+
+
+/*
+WriteSurfaceExtraFile()
+writes out a surface info file (<map>.srf)
+*/
+
+void WriteSurfaceExtraFile( const char *path )
+{
+	char			srfPath[ 1024 ];
+	FILE			*sf;
+	surfaceExtra_t	*se;
+	int				i;
+	
+	
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' )
+		return;
+	
+	/* note it */
+	Sys_Printf( "--- WriteSurfaceExtraFile ---\n" );
+	
+	/* open the file */
+	strcpy( srfPath, path );
+	StripExtension( srfPath );
+	strcat( srfPath, ".srf" );
+	Sys_Printf( "Writing %s\n", srfPath );
+	sf = fopen( srfPath, "w" );
+	if( sf == NULL )
+		Error( "Error opening %s for writing", srfPath );
+	
+	/* lap through the extras list */
+	for( i = -1; i < numSurfaceExtras; i++ )
+	{
+		/* get extra */
+		se = GetSurfaceExtra( i );
+		
+		/* default or surface num? */
+		if( i < 0 )
+			fprintf( sf, "default" );
+		else
+			fprintf( sf, "%d", i );
+		
+		/* valid map drawsurf? */
+		if( se->mds == NULL )
+			fprintf( sf, "\n" );
+		else
+		{
+			fprintf( sf, " // %s V: %d I: %d %s\n",
+				surfaceTypes[ se->mds->type ],
+				se->mds->numVerts,
+				se->mds->numIndexes,
+				(se->mds->planar ? "planar" : "") );
+		}
+		
+		/* open braces */
+		fprintf( sf, "{\n" );
+		
+			/* shader */
+			if( se->si != NULL )
+				fprintf( sf, "\tshader %s\n", se->si->shader );
+			
+			/* parent surface number */
+			if( se->parentSurfaceNum != seDefault.parentSurfaceNum )
+				fprintf( sf, "\tparent %d\n", se->parentSurfaceNum );
+			
+			/* entity number */
+			if( se->entityNum != seDefault.entityNum )
+				fprintf( sf, "\tentity %d\n", se->entityNum );
+			
+			/* cast shadows */
+			if( se->castShadows != seDefault.castShadows || se == &seDefault )
+				fprintf( sf, "\tcastShadows %d\n", se->castShadows );
+			
+			/* recv shadows */
+			if( se->recvShadows != seDefault.recvShadows || se == &seDefault )
+				fprintf( sf, "\treceiveShadows %d\n", se->recvShadows );
+			
+			/* lightmap sample size */
+			if( se->sampleSize != seDefault.sampleSize || se == &seDefault )
+				fprintf( sf, "\tsampleSize %d\n", se->sampleSize );
+			
+			/* longest curve */
+			if( se->longestCurve != seDefault.longestCurve || se == &seDefault )
+				fprintf( sf, "\tlongestCurve %f\n", se->longestCurve );
+			
+			/* lightmap axis vector */
+			if( VectorCompare( se->lightmapAxis, seDefault.lightmapAxis ) == qfalse )
+				fprintf( sf, "\tlightmapAxis ( %f %f %f )\n", se->lightmapAxis[ 0 ], se->lightmapAxis[ 1 ], se->lightmapAxis[ 2 ] );
+		
+		/* close braces */
+		fprintf( sf, "}\n\n" );
+	}
+	
+	/* close the file */
+	fclose( sf );
+}
+
+
+
+/*
+LoadSurfaceExtraFile()
+reads a surface info file (<map>.srf)
+*/
+
+void LoadSurfaceExtraFile( const char *path )
+{
+	char			srfPath[ 1024 ];
+	surfaceExtra_t	*se;
+	int				surfaceNum, size;
+	byte			*buffer;
+	
+	
+	/* dummy check */
+	if( path == NULL || path[ 0 ] == '\0' )
+		return;
+	
+	/* load the file */
+	strcpy( srfPath, path );
+	StripExtension( srfPath );
+	strcat( srfPath, ".srf" );
+	Sys_Printf( "Loading %s\n", srfPath );
+	size = LoadFile( srfPath, (void**) &buffer );
+	if( size <= 0 )
+	{
+		Sys_Printf( "WARNING: Unable to find surface file %s, using defaults.\n", srfPath );
+		return;
+	}
+	
+	/* parse the file */
+	ParseFromMemory( buffer, size );
+	
+	/* tokenize it */
+	while( 1 )
+	{
+		/* test for end of file */
+		if( !GetToken( qtrue ) )
+			break;
+		
+		/* default? */
+		if( !Q_stricmp( token, "default" ) )
+			se = &seDefault;
+
+		/* surface number */
+		else
+		{
+			surfaceNum = atoi( token );
+			if( surfaceNum < 0 || surfaceNum > MAX_MAP_DRAW_SURFS )
+				Error( "ReadSurfaceExtraFile(): %s, line %d: bogus surface num %d", srfPath, scriptline, surfaceNum );
+			while( surfaceNum >= numSurfaceExtras )
+				se = AllocSurfaceExtra();
+			se = &surfaceExtras[ surfaceNum ];
+		}
+		
+		/* handle { } section */
+		if( !GetToken( qtrue ) || strcmp( token, "{" ) )
+			Error( "ReadSurfaceExtraFile(): %s, line %d: { not found", srfPath, scriptline );
+		while( 1 )
+		{
+			if( !GetToken( qtrue ) )
+				break;
+			if( !strcmp( token, "}" ) )
+				break;
+			
+			/* shader */
+			if( !Q_stricmp( token, "shader" ) )
+			{
+				GetToken( qfalse );
+				se->si = ShaderInfoForShader( token );
+			}
+			
+			/* parent surface number */
+			else if( !Q_stricmp( token, "parent" ) )
+			{
+				GetToken( qfalse );
+				se->parentSurfaceNum = atoi( token );
+			}
+			
+			/* entity number */
+			else if( !Q_stricmp( token, "entity" ) )
+			{
+				GetToken( qfalse );
+				se->entityNum = atoi( token );
+			}
+			
+			/* cast shadows */
+			else if( !Q_stricmp( token, "castShadows" ) )
+			{
+				GetToken( qfalse );
+				se->castShadows = atoi( token );
+			}
+			
+			/* recv shadows */
+			else if( !Q_stricmp( token, "receiveShadows" ) )
+			{
+				GetToken( qfalse );
+				se->recvShadows = atoi( token );
+			}
+			
+			/* lightmap sample size */
+			else if( !Q_stricmp( token, "sampleSize" ) )
+			{
+				GetToken( qfalse );
+				se->sampleSize = atoi( token );
+			}
+			
+			/* longest curve */
+			else if( !Q_stricmp( token, "longestCurve" ) )
+			{
+				GetToken( qfalse );
+				se->longestCurve = atof( token );
+			}
+			
+			/* lightmap axis vector */
+			else if( !Q_stricmp( token, "lightmapAxis" ) )
+				Parse1DMatrix( 3, se->lightmapAxis );
+			
+			/* ignore all other tokens on the line */
+			while( TokenAvailable() )
+				GetToken( qfalse );
+		}
+	}
+	
+	/* free the buffer */
+	free( buffer );
+}
+
diff --git a/tools/quake3/q3map2/surface_foliage.c b/tools/quake3/q3map2/surface_foliage.c
index 5ea77390..e7d5fe8b 100644
--- a/tools/quake3/q3map2/surface_foliage.c
+++ b/tools/quake3/q3map2/surface_foliage.c
@@ -1,327 +1,327 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-Foliage code for Wolfenstein: Enemy Territory by ydnar@splashdamage.com
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define SURFACE_FOLIAGE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-#define MAX_FOLIAGE_INSTANCES	8192
-
-static int						numFoliageInstances;
-static foliageInstance_t		foliageInstances[ MAX_FOLIAGE_INSTANCES ];
-
-
-
-/*
-SubdivideFoliageTriangle_r()
-recursively subdivides a triangle until the triangle is smaller than
-the desired density, then pseudo-randomly sets a point
-*/
-
-static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, foliage_t *foliage, bspDrawVert_t **tri )
-{
-	bspDrawVert_t	mid, *tri2[ 3 ];
-	int				max;
-	
-	
-	/* limit test */
-	if( numFoliageInstances >= MAX_FOLIAGE_INSTANCES )
-		return;
-	
-	/* plane test */
-	{
-		vec4_t		plane;
-		
-		
-		/* make a plane */
-		if( !PlaneFromPoints( plane, tri[ 0 ]->xyz, tri[ 1 ]->xyz, tri[ 2 ]->xyz ) )
-			return;
-		
-		/* if normal is too far off vertical, then don't place an instance */
-		if( plane[ 2 ] < 0.5f )
-			return;
-	}
-	
-	/* subdivide calc */
-	{
-		int					i;
-		float				*a, *b, dx, dy, dz, dist, maxDist;
-		foliageInstance_t	*fi;
-		
-		
-		/* get instance */
-		fi = &foliageInstances[ numFoliageInstances ];
-		
-		/* find the longest edge and split it */
-		max = -1;
-		maxDist = 0.0f;
-		VectorClear( fi->xyz );
-		VectorClear( fi->normal );
-		for( i = 0; i < 3; i++ )
-		{
-			/* get verts */
-			a = tri[ i ]->xyz;
-			b = tri[ (i + 1) % 3 ]->xyz;
-			
-			/* get dists */
-			dx = a[ 0 ] - b[ 0 ];
-			dy = a[ 1 ] - b[ 1 ];
-			dz = a[ 2 ] - b[ 2 ];
-			dist = (dx * dx) + (dy * dy) + (dz * dz);
-			
-			/* longer? */
-			if( dist > maxDist )
-			{
-				maxDist = dist;
-				max = i;
-			}
-			
-			/* add to centroid */
-			VectorAdd( fi->xyz, tri[ i ]->xyz, fi->xyz );
-			VectorAdd( fi->normal, tri[ i ]->normal, fi->normal );
-		}
-		
-		/* is the triangle small enough? */
-		if( maxDist <= (foliage->density * foliage->density) )
-		{
-			float	alpha, odds, r;
-			
-			
-			/* get average alpha */
-			if( foliage->inverseAlpha == 2 )
-				alpha = 1.0f;
-			else
-			{
-				alpha = ((float) tri[ 0 ]->color[ 0 ][ 3 ] + (float) tri[ 1 ]->color[ 0 ][ 3 ] + (float) tri[ 2 ]->color[ 0 ][ 3 ]) / 765.0f;
-				if( foliage->inverseAlpha == 1 )
-					alpha = 1.0f - alpha;
-				if( alpha < 0.75f )
-					return;
-			}
-			
-			/* roll the dice */
-			odds = foliage->odds * alpha;
-			r = Random();
-			if( r > odds )
-				return;
-			
-			/* scale centroid */
-			VectorScale( fi->xyz, 0.33333333f, fi->xyz );
-			if( VectorNormalize( fi->normal, fi->normal ) == 0.0f )
-				return;
-			
-			/* add to count and return */
-			numFoliageInstances++;
-			return;
-		}
-	}
-	
-	/* split the longest edge and map it */
-	LerpDrawVert( tri[ max ], tri[ (max + 1) % 3 ], &mid );
-	
-	/* recurse to first triangle */
-	VectorCopy( tri, tri2 );
-	tri2[ max ] = &mid;
-	SubdivideFoliageTriangle_r( ds, foliage, tri2 );
-	
-	/* recurse to second triangle */
-	VectorCopy( tri, tri2 );
-	tri2[ (max + 1) % 3 ] = &mid;
-	SubdivideFoliageTriangle_r( ds, foliage, tri2 );
-}
-
-
-
-/*
-GenFoliage()
-generates a foliage file for a bsp
-*/
-
-void Foliage( mapDrawSurface_t *src )
-{
-	int					i, j, k, x, y, pw[ 5 ], r, oldNumMapDrawSurfs;
-	mapDrawSurface_t	*ds;
-	shaderInfo_t		*si;
-	foliage_t			*foliage;
-	mesh_t				srcMesh, *subdivided, *mesh;
-	bspDrawVert_t		*verts, *dv[ 3 ], *fi;
-	vec3_t				scale;
-	m4x4_t				transform;
-	
-	
-	/* get shader */
-	si = src->shaderInfo;
-	if( si == NULL || si->foliage == NULL )
-		return;
-	
-	/* do every foliage */
-	for( foliage = si->foliage; foliage != NULL; foliage = foliage->next )
-	{
-		/* zero out */
-		numFoliageInstances = 0;
-		
-		/* map the surface onto the lightmap origin/cluster/normal buffers */
-		switch( src->type )
-		{
-			case SURFACE_META:
-			case SURFACE_FORCED_META:
-			case SURFACE_TRIANGLES:
-				/* get verts */
-				verts = src->verts;
-				
-				/* map the triangles */
-				for( i = 0; i < src->numIndexes; i += 3 )
-				{
-					dv[ 0 ] = &verts[ src->indexes[ i ] ];
-					dv[ 1 ] = &verts[ src->indexes[ i + 1 ] ];
-					dv[ 2 ] = &verts[ src->indexes[ i + 2 ] ];
-					SubdivideFoliageTriangle_r( src, foliage, dv );
-				}
-				break;
-			
-			case SURFACE_PATCH:
-				/* make a mesh from the drawsurf */ 
-				srcMesh.width = src->patchWidth;
-				srcMesh.height = src->patchHeight;
-				srcMesh.verts = src->verts;
-				subdivided = SubdivideMesh( srcMesh, 8, 512 );
-				
-				/* fit it to the curve and remove colinear verts on rows/columns */
-				PutMeshOnCurve( *subdivided );
-				mesh = RemoveLinearMeshColumnsRows( subdivided );
-				FreeMesh( subdivided );
-				
-				/* get verts */
-				verts = mesh->verts;
-				
-				/* map the mesh quads */
-				for( y = 0; y < (mesh->height - 1); y++ )
-				{
-					for( x = 0; x < (mesh->width - 1); x++ )
-					{
-						/* set indexes */
-						pw[ 0 ] = x + (y * mesh->width);
-						pw[ 1 ] = x + ((y + 1) * mesh->width);
-						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-						pw[ 3 ] = x + 1 + (y * mesh->width);
-						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-						
-						/* set radix */
-						r = (x + y) & 1;
-						
-						/* get drawverts and map first triangle */
-						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
-						dv[ 1 ] = &verts[ pw[ r + 1 ] ];
-						dv[ 2 ] = &verts[ pw[ r + 2 ] ];
-						SubdivideFoliageTriangle_r( src, foliage, dv );
-						
-						/* get drawverts and map second triangle */
-						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
-						dv[ 1 ] = &verts[ pw[ r + 2 ] ];
-						dv[ 2 ] = &verts[ pw[ r + 3 ] ];
-						SubdivideFoliageTriangle_r( src, foliage, dv );
-					}
-				}
-				
-				/* free the mesh */
-				FreeMesh( mesh );
-				break;
-			
-			default:
-				break;
-		}
-		
-		/* any origins? */
-		if( numFoliageInstances < 1 )
-			continue;
-		
-		/* remember surface count */
-		oldNumMapDrawSurfs = numMapDrawSurfs;
-		
-		/* set transform matrix */
-		VectorSet( scale, foliage->scale, foliage->scale, foliage->scale );
-		m4x4_scale_for_vec3( transform, scale );
-		
-		/* add the model to the bsp */
-		InsertModel( foliage->model, 0, transform, NULL, NULL, src->entityNum, src->castShadows, src->recvShadows, 0, src->lightmapScale );
-		
-		/* walk each new surface */
-		for( i = oldNumMapDrawSurfs; i < numMapDrawSurfs; i++ )
-		{
-			/* get surface */
-			ds = &mapDrawSurfs[ i ];
-			
-			/* set up */
-			ds->type = SURFACE_FOLIAGE;
-			ds->numFoliageInstances = numFoliageInstances;
-			
-			/* a wee hack */
-			ds->patchWidth = ds->numFoliageInstances;
-			ds->patchHeight = ds->numVerts;
-			
-			/* set fog to be same as source surface */
-			ds->fogNum = src->fogNum;
-			
-			/* add a drawvert for every instance */
-			verts = safe_malloc( (ds->numVerts + ds->numFoliageInstances) * sizeof( *verts ) );
-			memset( verts, 0, (ds->numVerts + ds->numFoliageInstances) * sizeof( *verts ) );
-			memcpy( verts, ds->verts, ds->numVerts * sizeof( *verts ) );
-			free( ds->verts );
-			ds->verts = verts;
-			
-			/* copy the verts */
-			for( j = 0; j < ds->numFoliageInstances; j++ )
-			{
-				/* get vert (foliage instance) */
-				fi = &ds->verts[ ds->numVerts + j ];
-
-				/* copy xyz and normal */
-				VectorCopy( foliageInstances[ j ].xyz, fi->xyz );
-				VectorCopy( foliageInstances[ j ].normal, fi->normal );
-
-				/* ydnar: set color */
-				for( k = 0; k < MAX_LIGHTMAPS; k++ )
-				{
-					fi->color[ k ][ 0 ] = 255;
-					fi->color[ k ][ 1 ] = 255;
-					fi->color[ k ][ 2 ] = 255;
-					fi->color[ k ][ 3 ] = 255;
-				}
-			}
-			
-			/* increment */
-			ds->numVerts += ds->numFoliageInstances;
-		}
-	}
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+Foliage code for Wolfenstein: Enemy Territory by ydnar@splashdamage.com
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define SURFACE_FOLIAGE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+#define MAX_FOLIAGE_INSTANCES	8192
+
+static int						numFoliageInstances;
+static foliageInstance_t		foliageInstances[ MAX_FOLIAGE_INSTANCES ];
+
+
+
+/*
+SubdivideFoliageTriangle_r()
+recursively subdivides a triangle until the triangle is smaller than
+the desired density, then pseudo-randomly sets a point
+*/
+
+static void SubdivideFoliageTriangle_r( mapDrawSurface_t *ds, foliage_t *foliage, bspDrawVert_t **tri )
+{
+	bspDrawVert_t	mid, *tri2[ 3 ];
+	int				max;
+	
+	
+	/* limit test */
+	if( numFoliageInstances >= MAX_FOLIAGE_INSTANCES )
+		return;
+	
+	/* plane test */
+	{
+		vec4_t		plane;
+		
+		
+		/* make a plane */
+		if( !PlaneFromPoints( plane, tri[ 0 ]->xyz, tri[ 1 ]->xyz, tri[ 2 ]->xyz ) )
+			return;
+		
+		/* if normal is too far off vertical, then don't place an instance */
+		if( plane[ 2 ] < 0.5f )
+			return;
+	}
+	
+	/* subdivide calc */
+	{
+		int					i;
+		float				*a, *b, dx, dy, dz, dist, maxDist;
+		foliageInstance_t	*fi;
+		
+		
+		/* get instance */
+		fi = &foliageInstances[ numFoliageInstances ];
+		
+		/* find the longest edge and split it */
+		max = -1;
+		maxDist = 0.0f;
+		VectorClear( fi->xyz );
+		VectorClear( fi->normal );
+		for( i = 0; i < 3; i++ )
+		{
+			/* get verts */
+			a = tri[ i ]->xyz;
+			b = tri[ (i + 1) % 3 ]->xyz;
+			
+			/* get dists */
+			dx = a[ 0 ] - b[ 0 ];
+			dy = a[ 1 ] - b[ 1 ];
+			dz = a[ 2 ] - b[ 2 ];
+			dist = (dx * dx) + (dy * dy) + (dz * dz);
+			
+			/* longer? */
+			if( dist > maxDist )
+			{
+				maxDist = dist;
+				max = i;
+			}
+			
+			/* add to centroid */
+			VectorAdd( fi->xyz, tri[ i ]->xyz, fi->xyz );
+			VectorAdd( fi->normal, tri[ i ]->normal, fi->normal );
+		}
+		
+		/* is the triangle small enough? */
+		if( maxDist <= (foliage->density * foliage->density) )
+		{
+			float	alpha, odds, r;
+			
+			
+			/* get average alpha */
+			if( foliage->inverseAlpha == 2 )
+				alpha = 1.0f;
+			else
+			{
+				alpha = ((float) tri[ 0 ]->color[ 0 ][ 3 ] + (float) tri[ 1 ]->color[ 0 ][ 3 ] + (float) tri[ 2 ]->color[ 0 ][ 3 ]) / 765.0f;
+				if( foliage->inverseAlpha == 1 )
+					alpha = 1.0f - alpha;
+				if( alpha < 0.75f )
+					return;
+			}
+			
+			/* roll the dice */
+			odds = foliage->odds * alpha;
+			r = Random();
+			if( r > odds )
+				return;
+			
+			/* scale centroid */
+			VectorScale( fi->xyz, 0.33333333f, fi->xyz );
+			if( VectorNormalize( fi->normal, fi->normal ) == 0.0f )
+				return;
+			
+			/* add to count and return */
+			numFoliageInstances++;
+			return;
+		}
+	}
+	
+	/* split the longest edge and map it */
+	LerpDrawVert( tri[ max ], tri[ (max + 1) % 3 ], &mid );
+	
+	/* recurse to first triangle */
+	VectorCopy( tri, tri2 );
+	tri2[ max ] = &mid;
+	SubdivideFoliageTriangle_r( ds, foliage, tri2 );
+	
+	/* recurse to second triangle */
+	VectorCopy( tri, tri2 );
+	tri2[ (max + 1) % 3 ] = &mid;
+	SubdivideFoliageTriangle_r( ds, foliage, tri2 );
+}
+
+
+
+/*
+GenFoliage()
+generates a foliage file for a bsp
+*/
+
+void Foliage( mapDrawSurface_t *src )
+{
+	int					i, j, k, x, y, pw[ 5 ], r, oldNumMapDrawSurfs;
+	mapDrawSurface_t	*ds;
+	shaderInfo_t		*si;
+	foliage_t			*foliage;
+	mesh_t				srcMesh, *subdivided, *mesh;
+	bspDrawVert_t		*verts, *dv[ 3 ], *fi;
+	vec3_t				scale;
+	m4x4_t				transform;
+	
+	
+	/* get shader */
+	si = src->shaderInfo;
+	if( si == NULL || si->foliage == NULL )
+		return;
+	
+	/* do every foliage */
+	for( foliage = si->foliage; foliage != NULL; foliage = foliage->next )
+	{
+		/* zero out */
+		numFoliageInstances = 0;
+		
+		/* map the surface onto the lightmap origin/cluster/normal buffers */
+		switch( src->type )
+		{
+			case SURFACE_META:
+			case SURFACE_FORCED_META:
+			case SURFACE_TRIANGLES:
+				/* get verts */
+				verts = src->verts;
+				
+				/* map the triangles */
+				for( i = 0; i < src->numIndexes; i += 3 )
+				{
+					dv[ 0 ] = &verts[ src->indexes[ i ] ];
+					dv[ 1 ] = &verts[ src->indexes[ i + 1 ] ];
+					dv[ 2 ] = &verts[ src->indexes[ i + 2 ] ];
+					SubdivideFoliageTriangle_r( src, foliage, dv );
+				}
+				break;
+			
+			case SURFACE_PATCH:
+				/* make a mesh from the drawsurf */ 
+				srcMesh.width = src->patchWidth;
+				srcMesh.height = src->patchHeight;
+				srcMesh.verts = src->verts;
+				subdivided = SubdivideMesh( srcMesh, 8, 512 );
+				
+				/* fit it to the curve and remove colinear verts on rows/columns */
+				PutMeshOnCurve( *subdivided );
+				mesh = RemoveLinearMeshColumnsRows( subdivided );
+				FreeMesh( subdivided );
+				
+				/* get verts */
+				verts = mesh->verts;
+				
+				/* map the mesh quads */
+				for( y = 0; y < (mesh->height - 1); y++ )
+				{
+					for( x = 0; x < (mesh->width - 1); x++ )
+					{
+						/* set indexes */
+						pw[ 0 ] = x + (y * mesh->width);
+						pw[ 1 ] = x + ((y + 1) * mesh->width);
+						pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+						pw[ 3 ] = x + 1 + (y * mesh->width);
+						pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+						
+						/* set radix */
+						r = (x + y) & 1;
+						
+						/* get drawverts and map first triangle */
+						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
+						dv[ 1 ] = &verts[ pw[ r + 1 ] ];
+						dv[ 2 ] = &verts[ pw[ r + 2 ] ];
+						SubdivideFoliageTriangle_r( src, foliage, dv );
+						
+						/* get drawverts and map second triangle */
+						dv[ 0 ] = &verts[ pw[ r + 0 ] ];
+						dv[ 1 ] = &verts[ pw[ r + 2 ] ];
+						dv[ 2 ] = &verts[ pw[ r + 3 ] ];
+						SubdivideFoliageTriangle_r( src, foliage, dv );
+					}
+				}
+				
+				/* free the mesh */
+				FreeMesh( mesh );
+				break;
+			
+			default:
+				break;
+		}
+		
+		/* any origins? */
+		if( numFoliageInstances < 1 )
+			continue;
+		
+		/* remember surface count */
+		oldNumMapDrawSurfs = numMapDrawSurfs;
+		
+		/* set transform matrix */
+		VectorSet( scale, foliage->scale, foliage->scale, foliage->scale );
+		m4x4_scale_for_vec3( transform, scale );
+		
+		/* add the model to the bsp */
+		InsertModel( foliage->model, 0, transform, NULL, NULL, src->entityNum, src->castShadows, src->recvShadows, 0, src->lightmapScale );
+		
+		/* walk each new surface */
+		for( i = oldNumMapDrawSurfs; i < numMapDrawSurfs; i++ )
+		{
+			/* get surface */
+			ds = &mapDrawSurfs[ i ];
+			
+			/* set up */
+			ds->type = SURFACE_FOLIAGE;
+			ds->numFoliageInstances = numFoliageInstances;
+			
+			/* a wee hack */
+			ds->patchWidth = ds->numFoliageInstances;
+			ds->patchHeight = ds->numVerts;
+			
+			/* set fog to be same as source surface */
+			ds->fogNum = src->fogNum;
+			
+			/* add a drawvert for every instance */
+			verts = safe_malloc( (ds->numVerts + ds->numFoliageInstances) * sizeof( *verts ) );
+			memset( verts, 0, (ds->numVerts + ds->numFoliageInstances) * sizeof( *verts ) );
+			memcpy( verts, ds->verts, ds->numVerts * sizeof( *verts ) );
+			free( ds->verts );
+			ds->verts = verts;
+			
+			/* copy the verts */
+			for( j = 0; j < ds->numFoliageInstances; j++ )
+			{
+				/* get vert (foliage instance) */
+				fi = &ds->verts[ ds->numVerts + j ];
+
+				/* copy xyz and normal */
+				VectorCopy( foliageInstances[ j ].xyz, fi->xyz );
+				VectorCopy( foliageInstances[ j ].normal, fi->normal );
+
+				/* ydnar: set color */
+				for( k = 0; k < MAX_LIGHTMAPS; k++ )
+				{
+					fi->color[ k ][ 0 ] = 255;
+					fi->color[ k ][ 1 ] = 255;
+					fi->color[ k ][ 2 ] = 255;
+					fi->color[ k ][ 3 ] = 255;
+				}
+			}
+			
+			/* increment */
+			ds->numVerts += ds->numFoliageInstances;
+		}
+	}
+}
diff --git a/tools/quake3/q3map2/surface_fur.c b/tools/quake3/q3map2/surface_fur.c
index 4b63e51b..7af5e0dc 100644
--- a/tools/quake3/q3map2/surface_fur.c
+++ b/tools/quake3/q3map2/surface_fur.c
@@ -1,128 +1,128 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define SURFACE_FUR_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-/* -------------------------------------------------------------------------------
-
-ydnar: fur module
-
-------------------------------------------------------------------------------- */
-
-/*
-Fur()
-runs the fur processing algorithm on a map drawsurface
-*/
-
-void Fur( mapDrawSurface_t *ds )
-{
-	int					i, j, k, numLayers;
-	float				offset, fade, a;
-	mapDrawSurface_t	*fur;
-	bspDrawVert_t		*dv;
-	
-	
-	/* dummy check */
-	if( ds == NULL || ds->fur || ds->shaderInfo->furNumLayers < 1 )
-		return;
-	
-	/* get basic info */
-	numLayers = ds->shaderInfo->furNumLayers;
-	offset = ds->shaderInfo->furOffset;
-	fade = ds->shaderInfo->furFade * 255.0f;
-	
-	/* debug code */
-	//%	Sys_FPrintf( SYS_VRB, "Fur():  layers: %d  offset: %f   fade: %f  %s\n",
-	//%		numLayers, offset, fade, ds->shaderInfo->shader );
-	
-	/* initial offset */
-	for( j = 0; j < ds->numVerts; j++ )
-	{
-		/* get surface vert */
-		dv = &ds->verts[ j ];
-			
-		/* offset is scaled by original vertex alpha */
-		a = (float) dv->color[ 0 ][ 3 ] / 255.0;
-		
-		/* offset it */
-		VectorMA( dv->xyz, (offset * a), dv->normal, dv->xyz );
-	}
-	
-	/* wash, rinse, repeat */
-	for( i = 1; i < numLayers; i++ )
-	{
-		/* clone the surface */
-		fur = CloneSurface( ds, ds->shaderInfo );
-		if( fur == NULL )
-			return;
-		
-		/* set it to fur */
-		fur->fur = qtrue;
-		
-		/* walk the verts */
-		for( j = 0; j < fur->numVerts; j++ )
-		{
-			/* get surface vert */
-			dv = &ds->verts[ j ];
-				
-			/* offset is scaled by original vertex alpha */
-			a = (float) dv->color[ 0 ][ 3 ] / 255.0;
-			
-			/* get fur vert */
-			dv = &fur->verts[ j ];
-			
-			/* offset it */
-			VectorMA( dv->xyz, (offset * a * i), dv->normal, dv->xyz );
-			
-			/* fade alpha */
-			for( k = 0; k < MAX_LIGHTMAPS; k++ )
-			{
-				a = (float) dv->color[ k ][ 3 ] - fade;
-				if( a > 255.0f )
-					dv->color[ k ][ 3 ] = 255;
-				else if( a < 0 )
-					dv->color[ k ][ 3 ] = 0;
-				else
-					dv->color[ k ][ 3 ] = a;
-			}
-		}
-	}
-}
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define SURFACE_FUR_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+/* -------------------------------------------------------------------------------
+
+ydnar: fur module
+
+------------------------------------------------------------------------------- */
+
+/*
+Fur()
+runs the fur processing algorithm on a map drawsurface
+*/
+
+void Fur( mapDrawSurface_t *ds )
+{
+	int					i, j, k, numLayers;
+	float				offset, fade, a;
+	mapDrawSurface_t	*fur;
+	bspDrawVert_t		*dv;
+	
+	
+	/* dummy check */
+	if( ds == NULL || ds->fur || ds->shaderInfo->furNumLayers < 1 )
+		return;
+	
+	/* get basic info */
+	numLayers = ds->shaderInfo->furNumLayers;
+	offset = ds->shaderInfo->furOffset;
+	fade = ds->shaderInfo->furFade * 255.0f;
+	
+	/* debug code */
+	//%	Sys_FPrintf( SYS_VRB, "Fur():  layers: %d  offset: %f   fade: %f  %s\n",
+	//%		numLayers, offset, fade, ds->shaderInfo->shader );
+	
+	/* initial offset */
+	for( j = 0; j < ds->numVerts; j++ )
+	{
+		/* get surface vert */
+		dv = &ds->verts[ j ];
+			
+		/* offset is scaled by original vertex alpha */
+		a = (float) dv->color[ 0 ][ 3 ] / 255.0;
+		
+		/* offset it */
+		VectorMA( dv->xyz, (offset * a), dv->normal, dv->xyz );
+	}
+	
+	/* wash, rinse, repeat */
+	for( i = 1; i < numLayers; i++ )
+	{
+		/* clone the surface */
+		fur = CloneSurface( ds, ds->shaderInfo );
+		if( fur == NULL )
+			return;
+		
+		/* set it to fur */
+		fur->fur = qtrue;
+		
+		/* walk the verts */
+		for( j = 0; j < fur->numVerts; j++ )
+		{
+			/* get surface vert */
+			dv = &ds->verts[ j ];
+				
+			/* offset is scaled by original vertex alpha */
+			a = (float) dv->color[ 0 ][ 3 ] / 255.0;
+			
+			/* get fur vert */
+			dv = &fur->verts[ j ];
+			
+			/* offset it */
+			VectorMA( dv->xyz, (offset * a * i), dv->normal, dv->xyz );
+			
+			/* fade alpha */
+			for( k = 0; k < MAX_LIGHTMAPS; k++ )
+			{
+				a = (float) dv->color[ k ][ 3 ] - fade;
+				if( a > 255.0f )
+					dv->color[ k ][ 3 ] = 255;
+				else if( a < 0 )
+					dv->color[ k ][ 3 ] = 0;
+				else
+					dv->color[ k ][ 3 ] = a;
+			}
+		}
+	}
+}
+
+
+
diff --git a/tools/quake3/q3map2/surface_meta.c b/tools/quake3/q3map2/surface_meta.c
index 74307a76..f0c3d0a0 100644
--- a/tools/quake3/q3map2/surface_meta.c
+++ b/tools/quake3/q3map2/surface_meta.c
@@ -1,1626 +1,1626 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define SURFACE_META_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-#define LIGHTMAP_EXCEEDED	-1
-#define S_EXCEEDED			-2
-#define T_EXCEEDED			-3
-#define ST_EXCEEDED			-4
-#define UNSUITABLE_TRIANGLE	-10
-#define VERTS_EXCEEDED		-1000
-#define INDEXES_EXCEEDED	-2000
-
-#define GROW_META_VERTS		1024
-#define GROW_META_TRIANGLES	1024
-
-static int					numMetaSurfaces, numPatchMetaSurfaces;
-
-static int					maxMetaVerts = 0;
-static int					numMetaVerts = 0;
-static int					firstSearchMetaVert = 0;
-static bspDrawVert_t		*metaVerts = NULL;
-
-static int					maxMetaTriangles = 0;
-static int					numMetaTriangles = 0;
-static metaTriangle_t		*metaTriangles = NULL;
-
-
-
-/*
-ClearMetaVertexes()
-called before staring a new entity to clear out the triangle list
-*/
-
-void ClearMetaTriangles( void )
-{
-	numMetaVerts = 0;
-	numMetaTriangles = 0;
-}
-
-
-
-/*
-FindMetaVertex()
-finds a matching metavertex in the global list, returning its index
-*/
-
-static int FindMetaVertex( bspDrawVert_t *src )
-{
-	int			i;
-	bspDrawVert_t	*v, *temp;
-	
-	
-	/* try to find an existing drawvert */
-	for( i = firstSearchMetaVert, v = &metaVerts[ i ]; i < numMetaVerts; i++, v++ )
-	{
-		if( memcmp( src, v, sizeof( bspDrawVert_t ) ) == 0 )
-			return i;
-	}
-	
-	/* enough space? */
-	if( numMetaVerts >= maxMetaVerts )
-	{
-		/* reallocate more room */
-		maxMetaVerts += GROW_META_VERTS;
-		temp = safe_malloc( maxMetaVerts * sizeof( bspDrawVert_t ) );
-		if( metaVerts != NULL )
-		{
-			memcpy( temp, metaVerts, numMetaVerts * sizeof( bspDrawVert_t ) );
-			free( metaVerts );
-		}
-		metaVerts = temp;
-	}
-	
-	/* add the triangle */
-	memcpy( &metaVerts[ numMetaVerts ], src, sizeof( bspDrawVert_t ) );
-	numMetaVerts++;
-	
-	/* return the count */
-	return (numMetaVerts - 1);
-}
-
-
-
-/*
-AddMetaTriangle()
-adds a new meta triangle, allocating more memory if necessary
-*/
-
-static int AddMetaTriangle( void )
-{
-	metaTriangle_t	*temp;
-	
-	
-	/* enough space? */
-	if( numMetaTriangles >= maxMetaTriangles )
-	{
-		/* reallocate more room */
-		maxMetaTriangles += GROW_META_TRIANGLES;
-		temp = safe_malloc( maxMetaTriangles * sizeof( metaTriangle_t ) );
-		if( metaTriangles != NULL )
-		{
-			memcpy( temp, metaTriangles, numMetaTriangles * sizeof( metaTriangle_t ) );
-			free( metaTriangles );
-		}
-		metaTriangles = temp;
-	}
-	
-	/* increment and return */
-	numMetaTriangles++;
-	return numMetaTriangles - 1;
-}
-
-
-
-/*
-FindMetaTriangle()
-finds a matching metatriangle in the global list,
-otherwise adds it and returns the index to the metatriangle
-*/
-
-int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum )
-{
-	int				triIndex;
-	vec3_t			dir;
-
-	
-	
-	/* detect degenerate triangles fixme: do something proper here */
-	VectorSubtract( a->xyz, b->xyz, dir );
-	if( VectorLength( dir ) < 0.125f )
-		return -1;
-	VectorSubtract( b->xyz, c->xyz, dir );
-	if( VectorLength( dir ) < 0.125f )
-		return -1;
-	VectorSubtract( c->xyz, a->xyz, dir );
-	if( VectorLength( dir ) < 0.125f )
-		return -1;
-	
-	/* find plane */
-	if( planeNum >= 0 )
-	{
-		/* because of precision issues with small triangles, try to use the specified plane */
-		src->planeNum = planeNum;
-		VectorCopy( mapplanes[ planeNum ].normal, src->plane );
-		src->plane[ 3 ] = mapplanes[ planeNum ].dist;
-	}
-	else
-	{
-		/* calculate a plane from the triangle's points (and bail if a plane can't be constructed) */
-		src->planeNum = -1;
-		if( PlaneFromPoints( src->plane, a->xyz, b->xyz, c->xyz ) == qfalse )
-			return -1;
-	}
-	
-	/* ydnar 2002-10-03: repair any bogus normals (busted ase import kludge) */
-	if( VectorLength( a->normal ) <= 0.0f )
-		VectorCopy( src->plane, a->normal );
-	if( VectorLength( b->normal ) <= 0.0f )
-		VectorCopy( src->plane, b->normal );
-	if( VectorLength( c->normal ) <= 0.0f )
-		VectorCopy( src->plane, c->normal );
-	
-	/* ydnar 2002-10-04: set lightmap axis if not already set */
-	if( !(src->si->compileFlags & C_VERTEXLIT) &&
-		src->lightmapAxis[ 0 ] == 0.0f && src->lightmapAxis[ 1 ] == 0.0f && src->lightmapAxis[ 2 ] == 0.0f )
-	{
-		/* the shader can specify an explicit lightmap axis */
-		if( src->si->lightmapAxis[ 0 ] || src->si->lightmapAxis[ 1 ] || src->si->lightmapAxis[ 2 ] )
-			VectorCopy( src->si->lightmapAxis, src->lightmapAxis );
-		
-		/* new axis-finding code */
-		else
-			CalcLightmapAxis( src->plane, src->lightmapAxis );
-	}
-	
-	/* fill out the src triangle */
-	src->indexes[ 0 ] = FindMetaVertex( a );
-	src->indexes[ 1 ] = FindMetaVertex( b );
-	src->indexes[ 2 ] = FindMetaVertex( c );
-	
-	/* try to find an existing triangle */
-	#ifdef USE_EXHAUSTIVE_SEARCH
-	{
-		int				i;
-		metaTriangle_t	*tri;
-		
-		
-		for( i = 0, tri = metaTriangles; i < numMetaTriangles; i++, tri++ )
-		{
-			if( memcmp( src, tri, sizeof( metaTriangle_t ) ) == 0 )
-				return i;
-		}
-	}
-	#endif
-	
-	/* get a new triangle */
-	triIndex = AddMetaTriangle();
-	
-	/* add the triangle */
-	memcpy( &metaTriangles[ triIndex ], src, sizeof( metaTriangle_t ) );
-	
-	/* return the triangle index */
-	return triIndex;
-}
-
-
-
-/*
-SurfaceToMetaTriangles()
-converts a classified surface to metatriangles
-*/
-
-static void SurfaceToMetaTriangles( mapDrawSurface_t *ds )
-{
-	int				i;
-	metaTriangle_t	src;
-	bspDrawVert_t	a, b, c;
-	
-	
-	/* only handle certain types of surfaces */
-	if( ds->type != SURFACE_FACE &&
-		ds->type != SURFACE_META &&
-		ds->type != SURFACE_FORCED_META &&
-		ds->type != SURFACE_DECAL )
-		return;
-	
-	/* speed at the expense of memory */
-	firstSearchMetaVert = numMetaVerts;
-	
-	/* only handle valid surfaces */
-	if( ds->type != SURFACE_BAD && ds->numVerts >= 3 && ds->numIndexes >= 3 )
-	{
-		/* walk the indexes and create triangles */
-		for( i = 0; i < ds->numIndexes; i += 3 )
-		{
-			/* sanity check the indexes */
-			if( ds->indexes[ i ] == ds->indexes[ i + 1 ] ||
-				ds->indexes[ i ] == ds->indexes[ i + 2 ] ||
-				ds->indexes[ i + 1 ] == ds->indexes[ i + 2 ] )
-			{
-				//%	Sys_Printf( "%d! ", ds->numVerts );
-				continue;
-			}
-			
-			/* build a metatriangle */
-			src.si = ds->shaderInfo;
-			src.side = (ds->sideRef != NULL ? ds->sideRef->side : NULL);
-			src.entityNum = ds->entityNum;
-			src.surfaceNum = ds->surfaceNum;
-			src.planeNum = ds->planeNum;
-			src.castShadows = ds->castShadows;
-			src.recvShadows = ds->recvShadows;
-			src.fogNum = ds->fogNum;
-			src.sampleSize = ds->sampleSize;
-			VectorCopy( ds->lightmapAxis, src.lightmapAxis );
-			
-			/* copy drawverts */
-			memcpy( &a, &ds->verts[ ds->indexes[ i ] ], sizeof( a ) );
-			memcpy( &b, &ds->verts[ ds->indexes[ i + 1 ] ], sizeof( b ) );
-			memcpy( &c, &ds->verts[ ds->indexes[ i + 2 ] ], sizeof( c ) );
-			FindMetaTriangle( &src, &a, &b, &c, ds->planeNum );
-		}
-		
-		/* add to count */
-		numMetaSurfaces++;
-	}
-	
-	/* clear the surface (free verts and indexes, sets it to SURFACE_BAD) */
-	ClearSurface( ds );
-}
-
-
-
-/*
-TriangulatePatchSurface()
-creates triangles from a patch
-*/
-
-void TriangulatePatchSurface( mapDrawSurface_t *ds )
-{
-	int					iterations, x, y, pw[ 5 ], r;
-	mapDrawSurface_t	*dsNew;
-	mesh_t				src, *subdivided, *mesh;
-	
-	
-	/* try to early out */
-	if( ds->numVerts == 0 || ds->type != SURFACE_PATCH || patchMeta == qfalse )
-		return;
-	
-	/* make a mesh from the drawsurf */ 
-	src.width = ds->patchWidth;
-	src.height = ds->patchHeight;
-	src.verts = ds->verts;
-	//%	subdivided = SubdivideMesh( src, 8, 999 );
-	iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
-	subdivided = SubdivideMesh2( src, iterations );	//%	ds->maxIterations
-	
-	/* fit it to the curve and remove colinear verts on rows/columns */
-	PutMeshOnCurve( *subdivided );
-	mesh = RemoveLinearMeshColumnsRows( subdivided );
-	FreeMesh( subdivided );
-	//% MakeMeshNormals( mesh );
-	
-	/* make a copy of the drawsurface */
-	dsNew = AllocDrawSurface( SURFACE_META );
-	memcpy( dsNew, ds, sizeof( *ds ) );
-	
-	/* if the patch is nonsolid, then discard it */
-	if( !(ds->shaderInfo->compileFlags & C_SOLID) )
-		ClearSurface( ds );
-	
-	/* set new pointer */
-	ds = dsNew;
-	
-	/* basic transmogrification */
-	ds->type = SURFACE_META;
-	ds->numIndexes = 0;
-	ds->indexes = safe_malloc( mesh->width * mesh->height * 6 * sizeof( int ) );
-	
-	/* copy the verts in */
-	ds->numVerts = (mesh->width * mesh->height);
-	ds->verts = mesh->verts;
-	
-	/* iterate through the mesh quads */
-	for( y = 0; y < (mesh->height - 1); y++ )
-	{
-		for( x = 0; x < (mesh->width - 1); x++ )
-		{
-			/* set indexes */
-			pw[ 0 ] = x + (y * mesh->width);
-			pw[ 1 ] = x + ((y + 1) * mesh->width);
-			pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
-			pw[ 3 ] = x + 1 + (y * mesh->width);
-			pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
-			
-			/* set radix */
-			r = (x + y) & 1;
-			
-			/* make first triangle */
-			ds->indexes[ ds->numIndexes++ ] = pw[ r + 0 ];
-			ds->indexes[ ds->numIndexes++ ] = pw[ r + 1 ];
-			ds->indexes[ ds->numIndexes++ ] = pw[ r + 2 ];
-			
-			/* make second triangle */
-			ds->indexes[ ds->numIndexes++ ] = pw[ r + 0 ];
-			ds->indexes[ ds->numIndexes++ ] = pw[ r + 2 ];
-			ds->indexes[ ds->numIndexes++ ] = pw[ r + 3 ];
-		}
-	}
-	
-	/* free the mesh, but not the verts */
-	free( mesh );
-	
-	/* add to count */
-	numPatchMetaSurfaces++;
-	
-	/* classify it */
-	ClassifySurfaces( 1, ds );
-}
-
-
-
-/*
-FanFaceSurface() - ydnar
-creates a tri-fan from a brush face winding
-loosely based on SurfaceAsTriFan()
-*/
-
-void FanFaceSurface( mapDrawSurface_t *ds )
-{
-	int				i, j, k, a, b, c, color[ MAX_LIGHTMAPS ][ 4 ];
-	bspDrawVert_t	*verts, *centroid, *dv;
-	double			iv;
-	
-	
-	/* try to early out */
-	if( !ds->numVerts || (ds->type != SURFACE_FACE && ds->type != SURFACE_DECAL) )
-		return;
-	
-	/* add a new vertex at the beginning of the surface */
-	verts = safe_malloc( (ds->numVerts + 1) * sizeof( bspDrawVert_t ) );
-	memset( verts, 0, sizeof( bspDrawVert_t ) );
-	memcpy( &verts[ 1 ], ds->verts, ds->numVerts * sizeof( bspDrawVert_t ) );
-	free( ds->verts );
-	ds->verts = verts;
-	
-	/* add up the drawverts to create a centroid */
-	centroid = &verts[ 0 ];
-	memset( color, 0,  4 * MAX_LIGHTMAPS * sizeof( int ) );
-	for( i = 1, dv = &verts[ 1 ]; i < (ds->numVerts + 1); i++, dv++ )
-	{
-		VectorAdd( centroid->xyz, dv->xyz, centroid->xyz );
-		VectorAdd( centroid->normal, dv->normal, centroid->normal );
-		for( j = 0; j < 4; j++ )
-		{
-			for( k = 0; k < MAX_LIGHTMAPS; k++ )
-				color[ k ][ j ] += dv->color[ k ][ j ];
-			if( j < 2 )
-			{
-				centroid->st[ j ] += dv->st[ j ];
-				for( k = 0; k < MAX_LIGHTMAPS; k++ )
-					centroid->lightmap[ k ][ j ] += dv->lightmap[ k ][ j ];
-			}
-		}
-	}
-	
-	/* average the centroid */
-	iv = 1.0f / ds->numVerts;
-	VectorScale( centroid->xyz, iv, centroid->xyz );
-	if( VectorNormalize( centroid->normal, centroid->normal ) <= 0 )
-		VectorCopy( verts[ 1 ].normal, centroid->normal );
-	for( j = 0; j < 4; j++ )
-	{
-		for( k = 0; k < MAX_LIGHTMAPS; k++ )
-		{
-			color[ k ][ j ] /= ds->numVerts;
-			centroid->color[ k ][ j ] = (color[ k ][ j ] < 255.0f ? color[ k ][ j ] : 255);
-		}
-		if( j < 2 )
-		{
-			centroid->st[ j ] *= iv;
-			for( k = 0; k < MAX_LIGHTMAPS; k++ )
-				centroid->lightmap[ k ][ j ] *= iv;
-		}
-	}
-	
-	/* add to vert count */
-	ds->numVerts++;
-	
-	/* fill indexes in triangle fan order */
-	ds->numIndexes = 0;
-	ds->indexes = safe_malloc( ds->numVerts * 3 * sizeof( int ) );
-	for( i = 1; i < ds->numVerts; i++ )
-	{
-		a = 0;
-		b = i;
-		c = (i + 1) % ds->numVerts;
-		c = c ? c : 1;
-		ds->indexes[ ds->numIndexes++ ] = a;
-		ds->indexes[ ds->numIndexes++ ] = b;
-		ds->indexes[ ds->numIndexes++ ] = c;
-	}
-	
-	/* add to count */
-	numFanSurfaces++;
-
-	/* classify it */
-	ClassifySurfaces( 1, ds );
-}
-
-
-
-/*
-StripFaceSurface() - ydnar
-attempts to create a valid tri-strip w/o degenerate triangles from a brush face winding
-based on SurfaceAsTriStrip()
-*/
-
-#define MAX_INDEXES		1024
-
-void StripFaceSurface( mapDrawSurface_t *ds ) 
-{
-	int			i, r, least, rotate, numIndexes, ni, a, b, c, indexes[ MAX_INDEXES ];
-	vec_t		*v1, *v2;
-	
-	
-	/* try to early out  */
-	if( !ds->numVerts || (ds->type != SURFACE_FACE && ds->type != SURFACE_DECAL) )
-		return;
-	
-	/* is this a simple triangle? */
-	if( ds->numVerts == 3 )
-	{
-		numIndexes = 3;
-		VectorSet( indexes, 0, 1, 2 );
-	}
-	else
-	{
-		/* ydnar: find smallest coordinate */
-		least = 0;
-		if( ds->shaderInfo != NULL && ds->shaderInfo->autosprite == qfalse )
-		{
-			for( i = 0; i < ds->numVerts; i++ )
-			{
-				/* get points */
-				v1 = ds->verts[ i ].xyz;
-				v2 = ds->verts[ least ].xyz;
-				
-				/* compare */
-				if( v1[ 0 ] < v2[ 0 ] ||
-					(v1[ 0 ] == v2[ 0 ] && v1[ 1 ] < v2[ 1 ]) ||
-					(v1[ 0 ] == v2[ 0 ] && v1[ 1 ] == v2[ 1 ] && v1[ 2 ] < v2[ 2 ]) )
-					least = i;
-			}
-		}
-		
-		/* determine the triangle strip order */
-		numIndexes = (ds->numVerts - 2) * 3;
-		if( numIndexes > MAX_INDEXES )
-			Error( "MAX_INDEXES exceeded for surface (%d > %d) (%d verts)", numIndexes, MAX_INDEXES, ds->numVerts );
-		
-		/* try all possible orderings of the points looking for a non-degenerate strip order */
-		for( r = 0; r < ds->numVerts; r++ )
-		{
-			/* set rotation */
-			rotate = (r + least) % ds->numVerts;
-			
-			/* walk the winding in both directions */
-			for( ni = 0, i = 0; i < ds->numVerts - 2 - i; i++ )
-			{
-				/* make indexes */
-				a = (ds->numVerts - 1 - i + rotate) % ds->numVerts;
-				b = (i + rotate ) % ds->numVerts;
-				c = (ds->numVerts - 2 - i + rotate) % ds->numVerts;
-				
-				/* test this triangle */
-				if( ds->numVerts > 4 && IsTriangleDegenerate( ds->verts, a, b, c ) )
-					break;
-				indexes[ ni++ ] = a;
-				indexes[ ni++ ] = b;
-				indexes[ ni++ ] = c;
-				
-				/* handle end case */
-				if( i + 1 != ds->numVerts - 1 - i )
-				{
-					/* make indexes */
-					a = (ds->numVerts - 2 - i + rotate ) % ds->numVerts;
-					b = (i + rotate ) % ds->numVerts;
-					c = (i + 1 + rotate ) % ds->numVerts;
-					
-					/* test triangle */
-					if( ds->numVerts > 4 && IsTriangleDegenerate( ds->verts, a, b, c ) )
-						break;
-					indexes[ ni++ ] = a;
-					indexes[ ni++ ] = b;
-					indexes[ ni++ ] = c;
-				}
-			}
-			
-			/* valid strip? */
-			if( ni == numIndexes )
-				break;
-		}
-		
-		/* if any triangle in the strip is degenerate, render from a centered fan point instead */
-		if( ni < numIndexes )
-		{
-			FanFaceSurface( ds );
-			return;
-		}
-	}
-	
-	/* copy strip triangle indexes */
-	ds->numIndexes = numIndexes;
-	ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) );
-	memcpy( ds->indexes, indexes, ds->numIndexes * sizeof( int ) );
-	
-	/* add to count */
-	numStripSurfaces++;
-	
-	/* classify it */
-	ClassifySurfaces( 1, ds );
-}
-
-
-
-/*
-MakeEntityMetaTriangles()
-builds meta triangles from brush faces (tristrips and fans)
-*/
-
-void MakeEntityMetaTriangles( entity_t *e )
-{
-	int					i, f, fOld, start;
-	mapDrawSurface_t	*ds;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- MakeEntityMetaTriangles ---\n" );
-	
-	/* init pacifier */
-	fOld = -1;
-	start = I_FloatTime();
-	
-	/* walk the list of surfaces in the entity */
-	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
-	{
-		/* print pacifier */
-		f = 10 * (i - e->firstDrawSurf) / (numMapDrawSurfs - e->firstDrawSurf);
-		if( f != fOld )
-		{
-			fOld = f;
-			Sys_FPrintf( SYS_VRB, "%d...", f );
-		}
-		
-		/* get surface */
-		ds = &mapDrawSurfs[ i ];
-		if( ds->numVerts <= 0 )
-			continue;
-		
-		/* ignore autosprite surfaces */
-		if( ds->shaderInfo->autosprite )
-			continue;
-		
-		/* meta this surface? */
-		if( meta == qfalse && ds->shaderInfo->forceMeta == qfalse )
-			continue;
-		
-		/* switch on type */
-		switch( ds->type )
-		{
-			case SURFACE_FACE:
-			case SURFACE_DECAL:
-				StripFaceSurface( ds );
-				SurfaceToMetaTriangles( ds );
-				break;
-			
-			case SURFACE_PATCH:
-				TriangulatePatchSurface( ds );
-				break;
-			
-			case SURFACE_TRIANGLES:
-				break;
-			
-			case SURFACE_FORCED_META:
-			case SURFACE_META:
-				SurfaceToMetaTriangles( ds );
-				break;
-			
-			default:
-				break;
-		}
-	}
-	
-	/* print time */
-	if( (numMapDrawSurfs - e->firstDrawSurf) )
-		Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d total meta surfaces\n", numMetaSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d stripped surfaces\n", numStripSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d fanned surfaces\n", numFanSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d patch meta surfaces\n", numPatchMetaSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d meta verts\n", numMetaVerts );
-	Sys_FPrintf( SYS_VRB, "%9d meta triangles\n", numMetaTriangles );
-	
-	/* tidy things up */
-	TidyEntitySurfaces( e );
-}
-
-
-
-/*
-PointTriangleIntersect()
-assuming that all points lie in plane, determine if pt
-is inside the triangle abc
-code originally (c) 2001 softSurfer (www.softsurfer.com)
-*/
-
-#define MIN_OUTSIDE_EPSILON		-0.01f
-#define MAX_OUTSIDE_EPSILON		1.01f
-
-static qboolean PointTriangleIntersect( vec3_t pt, vec4_t plane, vec3_t a, vec3_t b, vec3_t c, vec3_t bary )
-{
-	vec3_t	u, v, w;
-	float	uu, uv, vv, wu, wv, d;
-	
-	
-	/* make vectors */
-	VectorSubtract( b, a, u );
-	VectorSubtract( c, a, v );
-	VectorSubtract( pt, a, w );
-	
-	/* more setup */
-	uu = DotProduct( u, u );
-	uv = DotProduct( u, v );
-	vv = DotProduct( v, v );
-	wu = DotProduct( w, u );
-	wv = DotProduct( w, v );
-	d = uv * uv - uu * vv;
-	
-	/* calculate barycentric coordinates */
-	bary[ 1 ] = (uv * wv - vv * wu) / d;
-	if( bary[ 1 ] < MIN_OUTSIDE_EPSILON || bary[ 1 ] > MAX_OUTSIDE_EPSILON )
-		return qfalse;
-	bary[ 2 ] = (uv * wv - uu * wv) / d;
-	if( bary[ 2 ] < MIN_OUTSIDE_EPSILON || bary[ 2 ] > MAX_OUTSIDE_EPSILON )
-		return qfalse;
-	bary[ 0 ] = 1.0f - (bary[ 1 ] + bary[ 2 ]);
-	
-	/* point is in triangle */
-	return qtrue;
-}
-
-
-
-/*
-CreateEdge()
-sets up an edge structure from a plane and 2 points that the edge ab falls lies in
-*/
-
-typedef struct edge_s
-{
-	vec3_t	origin, edge;
-	vec_t	length, kingpinLength;
-	int		kingpin;
-	vec4_t	plane;
-}
-edge_t;
-
-void CreateEdge( vec4_t plane, vec3_t a, vec3_t b, edge_t *edge )
-{
-	/* copy edge origin */
-	VectorCopy( a, edge->origin );
-	
-	/* create vector aligned with winding direction of edge */
-	VectorSubtract( b, a, edge->edge );
-	
-	if( fabs( edge->edge[ 0 ] ) > fabs( edge->edge[ 1 ] ) && fabs( edge->edge[ 0 ] ) > fabs( edge->edge[ 2 ] ) )
-		edge->kingpin = 0;
-	else if( fabs( edge->edge[ 1 ] ) > fabs( edge->edge[ 0 ] ) && fabs( edge->edge[ 1 ] ) > fabs( edge->edge[ 2 ] ) )
-		edge->kingpin = 1;
-	else
-		edge->kingpin = 2;
-	edge->kingpinLength = edge->edge[ edge->kingpin ];
-	
-	VectorNormalize( edge->edge, edge->edge );
-	edge->edge[ 3 ] = DotProduct( a, edge->edge );
-	edge->length = DotProduct( b, edge->edge ) - edge->edge[ 3 ];
-	
-	/* create perpendicular plane that edge lies in */
-	CrossProduct( plane, edge->edge, edge->plane );
-	edge->plane[ 3 ] = DotProduct( a, edge->plane );
-}
-
-
-
-/*
-FixMetaTJunctions()
-fixes t-junctions on meta triangles
-*/
-
-#define TJ_PLANE_EPSILON	(1.0f / 8.0f)
-#define TJ_EDGE_EPSILON		(1.0f / 8.0f)
-#define TJ_POINT_EPSILON	(1.0f / 8.0f)
-
-void FixMetaTJunctions( void )
-{
-	int				i, j, k, f, fOld, start, vertIndex, triIndex, numTJuncs;
-	metaTriangle_t	*tri, *newTri;
-	shaderInfo_t	*si;
-	bspDrawVert_t	*a, *b, *c, junc;
-	float			dist, amount;
-	vec3_t			pt;
-	vec4_t			plane;
-	edge_t			edges[ 3 ];
-	
-	
-	/* this code is crap; revisit later */
-	return;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- FixMetaTJunctions ---\n" );
-	
-	/* init pacifier */
-	fOld = -1;
-	start = I_FloatTime();
-	
-	/* walk triangle list */
-	numTJuncs = 0;
-	for( i = 0; i < numMetaTriangles; i++ )
-	{
-		/* get triangle */
-		tri = &metaTriangles[ i ];
-		
-		/* print pacifier */
-		f = 10 * i / numMetaTriangles;
-		if( f != fOld )
-		{
-			fOld = f;
-			Sys_FPrintf( SYS_VRB, "%d...", f );
-		}
-		
-		/* attempt to early out */
-		si = tri->si;
-		if( (si->compileFlags & C_NODRAW) || si->autosprite || si->notjunc )
-			continue;
-		
-		/* calculate planes */
-		VectorCopy( tri->plane, plane );
-		plane[ 3 ] = tri->plane[ 3 ];
-		CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] );
-		CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] );
-		CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );
-		
-		/* walk meta vert list */
-		for( j = 0; j < numMetaVerts; j++ )
-		{
-			/* get vert */
-			VectorCopy( metaVerts[ j ].xyz, pt );
-
-			/* debug code: darken verts */
-			if( i == 0 )
-				VectorSet( metaVerts[ j ].color[ 0 ], 8, 8, 8 );
-			
-			/* determine if point lies in the triangle's plane */
-			dist = DotProduct( pt, plane ) - plane[ 3 ];
-			if( fabs( dist ) > TJ_PLANE_EPSILON )
-				continue;
-			
-			/* skip this point if it already exists in the triangle */
-			for( k = 0; k < 3; k++ )
-			{
-				if( fabs( pt[ 0 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 0 ] ) <= TJ_POINT_EPSILON &&
-					fabs( pt[ 1 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 1 ] ) <= TJ_POINT_EPSILON &&
-					fabs( pt[ 2 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 2 ] ) <= TJ_POINT_EPSILON )
-					break;
-			}
-			if( k < 3 )
-				continue;
-			
-			/* walk edges */
-			for( k = 0; k < 3; k++ )
-			{
-				/* ignore bogus edges */
-				if( fabs( edges[ k ].kingpinLength ) < TJ_EDGE_EPSILON )
-					continue;
-				
-				/* determine if point lies on the edge */
-				dist = DotProduct( pt, edges[ k ].plane ) - edges[ k ].plane[ 3 ];
-				if( fabs( dist ) > TJ_EDGE_EPSILON )
-					continue;
-				
-				/* determine how far along the edge the point lies */
-				amount = (pt[ edges[ k ].kingpin ] - edges[ k ].origin[ edges[ k ].kingpin ]) / edges[ k ].kingpinLength;
-				if( amount <= 0.0f || amount >= 1.0f )
-					continue;
-				
-				#if 0
-				dist = DotProduct( pt, edges[ k ].edge ) - edges[ k ].edge[ 3 ];
-				if( dist <= -0.0f || dist >= edges[ k ].length )
-					continue;
-				amount = dist / edges[ k ].length;
-				#endif
-				
-				/* debug code: brighten this point */
-				//%	metaVerts[ j ].color[ 0 ][ 0 ] += 5;
-				//%	metaVerts[ j ].color[ 0 ][ 1 ] += 4;
-				VectorSet( metaVerts[ tri->indexes[ k ] ].color[ 0 ], 255, 204, 0 );
-				VectorSet( metaVerts[ tri->indexes[ (k + 1) % 3 ] ].color[ 0 ], 255, 204, 0 );
-				
-
-				/* the edge opposite the zero-weighted vertex was hit, so use that as an amount */
-				a = &metaVerts[ tri->indexes[ k % 3 ] ];
-				b = &metaVerts[ tri->indexes[ (k + 1) % 3 ] ];
-				c = &metaVerts[ tri->indexes[ (k + 2) % 3 ] ];
-				
-				/* make new vert */
-				LerpDrawVertAmount( a, b, amount, &junc );
-				VectorCopy( pt, junc.xyz );
-				
-				/* compare against existing verts */
-				if( VectorCompare( junc.xyz, a->xyz ) || VectorCompare( junc.xyz, b->xyz ) || VectorCompare( junc.xyz, c->xyz ) )
-					continue;
-				
-				/* see if we can just re-use the existing vert */
-				if( !memcmp( &metaVerts[ j ], &junc, sizeof( junc ) ) )
-					vertIndex = j;
-				else
-				{
-					/* find new vertex (note: a and b are invalid pointers after this) */
-					firstSearchMetaVert = numMetaVerts;
-					vertIndex = FindMetaVertex( &junc );
-					if( vertIndex < 0 )
-						continue;
-				}
-						
-				/* make new triangle */
-				triIndex = AddMetaTriangle();
-				if( triIndex < 0 )
-					continue;
-				
-				/* get triangles */
-				tri = &metaTriangles[ i ];
-				newTri = &metaTriangles[ triIndex ];
-				
-				/* copy the triangle */
-				memcpy( newTri, tri, sizeof( *tri ) );
-				
-				/* fix verts */
-				tri->indexes[ (k + 1) % 3 ] = vertIndex;
-				newTri->indexes[ k ] = vertIndex;
-				
-				/* recalculate edges */
-				CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] );
-				CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] );
-				CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );
-				
-				/* debug code */
-				metaVerts[ vertIndex ].color[ 0 ][ 0 ] = 255;
-				metaVerts[ vertIndex ].color[ 0 ][ 1 ] = 204;
-				metaVerts[ vertIndex ].color[ 0 ][ 2 ] = 0;
-				
-				/* add to counter and end processing of this vert */
-				numTJuncs++;
-				break;
-			}
-		}
-	}
-	
-	/* print time */
-	Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d T-junctions added\n", numTJuncs );
-}
-
-
-
-/*
-SmoothMetaTriangles()
-averages coincident vertex normals in the meta triangles
-*/
-
-#define MAX_SAMPLES				256
-#define THETA_EPSILON			0.000001
-#define EQUAL_NORMAL_EPSILON	0.01
-
-void SmoothMetaTriangles( void )
-{
-	int				i, j, k, f, fOld, start, cs, numVerts, numVotes, numSmoothed;
-	float			shadeAngle, defaultShadeAngle, maxShadeAngle, dot, testAngle;
-	metaTriangle_t	*tri;
-	float			*shadeAngles;
-	byte			*smoothed;
-	vec3_t			average, diff;
-	int				indexes[ MAX_SAMPLES ];
-	vec3_t			votes[ MAX_SAMPLES ];
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- SmoothMetaTriangles ---\n" );
-	
-	/* allocate shade angle table */
-	shadeAngles = safe_malloc( numMetaVerts * sizeof( float ) );
-	memset( shadeAngles, 0, numMetaVerts * sizeof( float ) );
-	
-	/* allocate smoothed table */
-	cs = (numMetaVerts / 8) + 1;
-	smoothed = safe_malloc( cs );
-	memset( smoothed, 0, cs );
-	
-	/* set default shade angle */
-	defaultShadeAngle = DEG2RAD( npDegrees );
-	maxShadeAngle = 0.0f;
-	
-	/* run through every surface and flag verts belonging to non-lightmapped surfaces
-	   and set per-vertex smoothing angle */
-	for( i = 0, tri = &metaTriangles[ i ]; i < numMetaTriangles; i++, tri++ )
-	{
-		/* get shader for shade angle */
-		if( tri->si->shadeAngleDegrees > 0.0f )
-			shadeAngle = DEG2RAD( tri->si->shadeAngleDegrees );
-		else
-			shadeAngle = defaultShadeAngle;
-		if( shadeAngle > maxShadeAngle )
-			maxShadeAngle = shadeAngle;
-		
-		/* flag its verts */
-		for( j = 0; j < 3; j++ )
-		{
-			shadeAngles[ tri->indexes[ j ] ] = shadeAngle;
-			if( shadeAngle <= 0 )
-				smoothed[ tri->indexes[ j ] >> 3 ] |= (1 << (tri->indexes[ j ] & 7));
-		}
-	}
-	
-	/* bail if no surfaces have a shade angle */
-	if( maxShadeAngle <= 0 )
-	{
-		Sys_FPrintf( SYS_VRB, "No smoothing angles specified, aborting\n" );
-		free( shadeAngles );
-		free( smoothed );
-		return;
-	}
-	
-	/* init pacifier */
-	fOld = -1;
-	start = I_FloatTime();
-	
-	/* go through the list of vertexes */
-	numSmoothed = 0;
-	for( i = 0; i < numMetaVerts; i++ )
-	{
-		/* print pacifier */
-		f = 10 * i / numMetaVerts;
-		if( f != fOld )
-		{
-			fOld = f;
-			Sys_FPrintf( SYS_VRB, "%d...", f );
-		}
-		
-		/* already smoothed? */
-		if( smoothed[ i >> 3 ] & (1 << (i & 7)) )
-			continue;
-		
-		/* clear */
-		VectorClear( average );
-		numVerts = 0;
-		numVotes = 0;
-		
-		/* build a table of coincident vertexes */
-		for( j = i; j < numMetaVerts && numVerts < MAX_SAMPLES; j++ )
-		{
-			/* already smoothed? */
-			if( smoothed[ j >> 3 ] & (1 << (j & 7)) )
-				continue;
-			
-			/* test vertexes */
-			if( VectorCompare( metaVerts[ i ].xyz, metaVerts[ j ].xyz ) == qfalse )
-				continue;
-			
-			/* use smallest shade angle */
-			shadeAngle = (shadeAngles[ i ] < shadeAngles[ j ] ? shadeAngles[ i ] : shadeAngles[ j ]);
-			
-			/* check shade angle */
-			dot = DotProduct( metaVerts[ i ].normal, metaVerts[ j ].normal );
-			if( dot > 1.0 )
-				dot = 1.0;
-			else if( dot < -1.0 )
-				dot = -1.0;
-			testAngle = acos( dot ) + THETA_EPSILON;
-			if( testAngle >= shadeAngle )
-				continue;
-			
-			/* add to the list */
-			indexes[ numVerts++ ] = j;
-			
-			/* flag vertex */
-			smoothed[ j >> 3 ] |= (1 << (j & 7));
-			
-			/* see if this normal has already been voted */
-			for( k = 0; k < numVotes; k++ )
-			{
-				VectorSubtract( metaVerts[ j ].normal, votes[ k ], diff );
-				if( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
-					fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
-					fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON )
-					break;
-			}
-			
-			/* add a new vote? */
-			if( k == numVotes && numVotes < MAX_SAMPLES )
-			{
-				VectorAdd( average, metaVerts[ j ].normal, average );
-				VectorCopy( metaVerts[ j ].normal, votes[ numVotes ] );
-				numVotes++;
-			}
-		}
-		
-		/* don't average for less than 2 verts */
-		if( numVerts < 2 )
-			continue;
-		
-		/* average normal */
-		if( VectorNormalize( average, average ) > 0 )
-		{
-			/* smooth */
-			for( j = 0; j < numVerts; j++ )
-				VectorCopy( average, metaVerts[ indexes[ j ] ].normal );
-			numSmoothed++;
-		}
-	}
-	
-	/* free the tables */
-	free( shadeAngles );
-	free( smoothed );
-	
-	/* print time */
-	Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
-
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d smoothed vertexes\n", numSmoothed );
-}
-
-
-
-/*
-AddMetaVertToSurface()
-adds a drawvert to a surface unless an existing vert matching already exists
-returns the index of that vert (or < 0 on failure)
-*/
-
-int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincident )
-{
-	int				i;
-	bspDrawVert_t	*dv2;
-	
-	
-	/* go through the verts and find a suitable candidate */
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		/* get test vert */
-		dv2 = &ds->verts[ i ];
-		
-		/* compare xyz and normal */
-		if( VectorCompare( dv1->xyz, dv2->xyz ) == qfalse )
-			continue;
-		if( VectorCompare( dv1->normal, dv2->normal ) == qfalse )
-			continue;
-		
-		/* good enough at this point */
-		(*coincident)++;
-		
-		/* compare texture coordinates and color */
-		if( dv1->st[ 0 ] != dv2->st[ 0 ] || dv1->st[ 1 ] != dv2->st[ 1 ] )
-			continue;
-		if( dv1->color[ 0 ][ 3 ] != dv2->color[ 0 ][ 3 ] )
-			continue;
-		
-		/* found a winner */
-		numMergedVerts++;
-		return i;
-	}
-
-	/* overflow check */
-	if( ds->numVerts >= maxSurfaceVerts )
-		return VERTS_EXCEEDED;
-	
-	/* made it this far, add the vert and return */
-	dv2 = &ds->verts[ ds->numVerts++ ];
-	*dv2 = *dv1;
-	return (ds->numVerts - 1);
-}
-
-
-
-
-/*
-AddMetaTriangleToSurface()
-attempts to add a metatriangle to a surface
-returns the score of the triangle added
-*/
-
-#define AXIS_SCORE			100000
-#define AXIS_MIN			100000
-#define VERT_SCORE			10000
-#define SURFACE_SCORE		1000
-#define ST_SCORE			50
-#define ST_SCORE2			(2 * (ST_SCORE))
-
-#define ADEQUATE_SCORE		((AXIS_MIN) + 1 * (VERT_SCORE))
-#define GOOD_SCORE			((AXIS_MIN) + 2 * (VERT_SCORE) + 4 * (ST_SCORE))
-#define PERFECT_SCORE		((AXIS_MIN) + + 3 * (VERT_SCORE) + (SURFACE_SCORE) + 4 * (ST_SCORE))
-
-static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri, qboolean testAdd )
-{
-	int					i, score, coincident, ai, bi, ci, oldTexRange[ 2 ];
-	float				lmMax;
-	vec3_t				mins, maxs;
-	qboolean			inTexRange, es, et;
-	mapDrawSurface_t	old;
-	
-	
-	/* overflow check */
-	if( ds->numIndexes >= maxSurfaceIndexes )
-		return 0;
-	
-	/* test the triangle */
-	if( ds->entityNum != tri->entityNum )	/* ydnar: added 2002-07-06 */
-		return 0;
-	if( ds->castShadows != tri->castShadows || ds->recvShadows != tri->recvShadows )
-		return 0;
-	if( ds->shaderInfo != tri->si || ds->fogNum != tri->fogNum || ds->sampleSize != tri->sampleSize )
-		return 0;
-	#if 0
-		if( !(ds->shaderInfo->compileFlags & C_VERTEXLIT) &&
-			//% VectorCompare( ds->lightmapAxis, tri->lightmapAxis ) == qfalse )
-			DotProduct( ds->lightmapAxis, tri->plane ) < 0.25f )
-			return 0;
-	#endif
-	
-	/* planar surfaces will only merge with triangles in the same plane */
-	if( npDegrees == 0.0f && ds->shaderInfo->nonplanar == qfalse && ds->planeNum >= 0 )
-	{
-		if( VectorCompare( mapplanes[ ds->planeNum ].normal, tri->plane ) == qfalse || mapplanes[ ds->planeNum ].dist != tri->plane[ 3 ] )
-			return 0;
-		if( tri->planeNum >= 0 && tri->planeNum != ds->planeNum )
-			return 0;
-	}
-	
-	/* set initial score */
-	score = tri->surfaceNum == ds->surfaceNum ? SURFACE_SCORE : 0;
-	
-	/* score the the dot product of lightmap axis to plane */
-	if( (ds->shaderInfo->compileFlags & C_VERTEXLIT) || VectorCompare( ds->lightmapAxis, tri->lightmapAxis ) )
-		score += AXIS_SCORE;
-	else
-		score += AXIS_SCORE * DotProduct( ds->lightmapAxis, tri->plane );
-	
-	/* preserve old drawsurface if this fails */
-	memcpy( &old, ds, sizeof( *ds ) );
-	
-	/* attempt to add the verts */
-	coincident = 0;
-	ai = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 0 ] ], &coincident );
-	bi = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 1 ] ], &coincident );
-	ci = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 2 ] ], &coincident );
-	
-	/* check vertex underflow */
-	if( ai < 0 || bi < 0 || ci < 0 )
-	{
-		memcpy( ds, &old, sizeof( *ds ) );
-		return 0;
-	}
-	
-	/* score coincident vertex count (2003-02-14: changed so this only matters on planar surfaces) */
-	score += (coincident * VERT_SCORE);
-	
-	/* add new vertex bounds to mins/maxs */
-	VectorCopy( ds->mins, mins );
-	VectorCopy( ds->maxs, maxs );
-	AddPointToBounds( metaVerts[ tri->indexes[ 0 ] ].xyz, mins, maxs );
-	AddPointToBounds( metaVerts[ tri->indexes[ 1 ] ].xyz, mins, maxs );
-	AddPointToBounds( metaVerts[ tri->indexes[ 2 ] ].xyz, mins, maxs );
-	
-	/* check lightmap bounds overflow (after at least 1 triangle has been added) */
-	if( !(ds->shaderInfo->compileFlags & C_VERTEXLIT) &&
-		ds->numIndexes > 0 && VectorLength( ds->lightmapAxis ) > 0.0f &&
-		(VectorCompare( ds->mins, mins ) == qfalse || VectorCompare( ds->maxs, maxs ) == qfalse) )
-	{
-		/* set maximum size before lightmap scaling (normally 2032 units) */
-		lmMax = (ds->sampleSize * (ds->shaderInfo->lmCustomWidth - 1));
-		for( i = 0; i < 3; i++ )
-		{
-			if( (maxs[ i ] - mins[ i ]) > lmMax )
-			{
-				memcpy( ds, &old, sizeof( *ds ) );
-				return 0;
-			}
-		}
-	}
-	
-	/* check texture range overflow */
-	oldTexRange[ 0 ] = ds->texRange[ 0 ];
-	oldTexRange[ 1 ] = ds->texRange[ 1 ];
-	inTexRange = CalcSurfaceTextureRange( ds );
-	
-	es = (ds->texRange[ 0 ] > oldTexRange[ 0 ]) ? qtrue : qfalse;
-	et = (ds->texRange[ 1 ] > oldTexRange[ 1 ]) ? qtrue : qfalse;
-	
-	if( inTexRange == qfalse && ds->numIndexes > 0 )
-	{
-		memcpy( ds, &old, sizeof( *ds ) );
-		return UNSUITABLE_TRIANGLE;
-	}
-	
-	/* score texture range */
-	if( ds->texRange[ 0 ] <= oldTexRange[ 0 ] )
-		score += ST_SCORE2;
-	else if( ds->texRange[ 0 ] > oldTexRange[ 0 ] && oldTexRange[ 1 ] > oldTexRange[ 0 ] )
-		score += ST_SCORE;
-	
-	if( ds->texRange[ 1 ] <= oldTexRange[ 1 ] )
-		score += ST_SCORE2;
-	else if( ds->texRange[ 1 ] > oldTexRange[ 1 ] && oldTexRange[ 0 ] > oldTexRange[ 1 ] )
-		score += ST_SCORE;
-	
-	
-	/* go through the indexes and try to find an existing triangle that matches abc */
-	for( i = 0; i < ds->numIndexes; i += 3 )
-	{
-		/* 2002-03-11 (birthday!): rotate the triangle 3x to find an existing triangle */
-		if( (ai == ds->indexes[ i ] && bi == ds->indexes[ i + 1 ] && ci == ds->indexes[ i + 2 ]) ||
-			(bi == ds->indexes[ i ] && ci == ds->indexes[ i + 1 ] && ai == ds->indexes[ i + 2 ]) ||
-			(ci == ds->indexes[ i ] && ai == ds->indexes[ i + 1 ] && bi == ds->indexes[ i + 2 ]) )
-		{
-			/* triangle already present */
-			memcpy( ds, &old, sizeof( *ds ) );
-			tri->si = NULL;
-			return 0;
-		}
-		
-		/* rotate the triangle 3x to find an inverse triangle (error case) */
-		if( (ai == ds->indexes[ i ] && bi == ds->indexes[ i + 2 ] && ci == ds->indexes[ i + 1 ]) ||
-			(bi == ds->indexes[ i ] && ci == ds->indexes[ i + 2 ] && ai == ds->indexes[ i + 1 ]) ||
-			(ci == ds->indexes[ i ] && ai == ds->indexes[ i + 2 ] && bi == ds->indexes[ i + 1 ]) )
-		{
-			/* warn about it */
-			Sys_Printf( "WARNING: Flipped triangle: (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f)\n",
-				ds->verts[ ai ].xyz[ 0 ], ds->verts[ ai ].xyz[ 1 ], ds->verts[ ai ].xyz[ 2 ],
-				ds->verts[ bi ].xyz[ 0 ], ds->verts[ bi ].xyz[ 1 ], ds->verts[ bi ].xyz[ 2 ],
-				ds->verts[ ci ].xyz[ 0 ], ds->verts[ ci ].xyz[ 1 ], ds->verts[ ci ].xyz[ 2 ] );
-			
-			/* reverse triangle already present */
-			memcpy( ds, &old, sizeof( *ds ) );
-			tri->si = NULL;
-			return 0;
-		}
-	}
-	
-	/* add the triangle indexes */
-	if( ds->numIndexes < maxSurfaceIndexes )
-		ds->indexes[ ds->numIndexes++ ] = ai;
-	if( ds->numIndexes < maxSurfaceIndexes )
-		ds->indexes[ ds->numIndexes++ ] = bi;
-	if( ds->numIndexes < maxSurfaceIndexes )
-		ds->indexes[ ds->numIndexes++ ] = ci;
-	
-	/* check index overflow */
-	if( ds->numIndexes >= maxSurfaceIndexes  )
-	{
-		memcpy( ds, &old, sizeof( *ds ) );
-		return 0;
-	}
-	
-	/* sanity check the indexes */
-	if( ds->numIndexes >= 3 &&
-		(ds->indexes[ ds->numIndexes - 3 ] == ds->indexes[ ds->numIndexes - 2 ] ||
-		ds->indexes[ ds->numIndexes - 3 ] == ds->indexes[ ds->numIndexes - 1 ] ||
-		ds->indexes[ ds->numIndexes - 2 ] == ds->indexes[ ds->numIndexes - 1 ]) )
-		Sys_Printf( "DEG:%d! ", ds->numVerts );
-	
-	/* testing only? */
-	if( testAdd )
-		memcpy( ds, &old, sizeof( *ds ) );
-	else
-	{
-		/* copy bounds back to surface */
-		VectorCopy( mins, ds->mins );
-		VectorCopy( maxs, ds->maxs );
-		
-		/* mark triangle as used */
-		tri->si = NULL;
-	}
-	
-	/* add a side reference */
-	ds->sideRef = AllocSideRef( tri->side, ds->sideRef );
-	
-	/* return to sender */
-	return score;
-}
-
-
-
-/*
-MetaTrianglesToSurface()
-creates map drawsurface(s) from the list of possibles
-*/
-
-static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, int *fOld, int *numAdded )
-{
-	int					i, j, f, best, score, bestScore;
-	metaTriangle_t		*seed, *test;
-	mapDrawSurface_t	*ds;
-	bspDrawVert_t		*verts;
-	int					*indexes;
-	qboolean			added;
-	
-	
-	/* allocate arrays */
-	verts = safe_malloc( sizeof( *verts ) * maxSurfaceVerts );
-	indexes = safe_malloc( sizeof( *indexes ) * maxSurfaceIndexes );
-	
-	/* walk the list of triangles */
-	for( i = 0, seed = possibles; i < numPossibles; i++, seed++ )
-	{
-		/* skip this triangle if it has already been merged */
-		if( seed->si == NULL )
-			continue;
-		
-		/* -----------------------------------------------------------------
-		   initial drawsurf construction
-		   ----------------------------------------------------------------- */
-		
-		/* start a new drawsurface */
-		ds = AllocDrawSurface( SURFACE_META );
-		ds->entityNum = seed->entityNum;
-		ds->surfaceNum = seed->surfaceNum;
-		ds->castShadows = seed->castShadows;
-		ds->recvShadows = seed->recvShadows;
-		
-		ds->shaderInfo = seed->si;
-		ds->planeNum = seed->planeNum;
-		ds->fogNum = seed->fogNum;
-		ds->sampleSize = seed->sampleSize;
-		ds->verts = verts;
-		ds->indexes = indexes;
-		VectorCopy( seed->lightmapAxis, ds->lightmapAxis );
-		ds->sideRef = AllocSideRef( seed->side, NULL );
-		
-		ClearBounds( ds->mins, ds->maxs );
-		
-		/* clear verts/indexes */
-		memset( verts, 0, sizeof( verts ) );
-		memset( indexes, 0, sizeof( indexes ) );
-		
-		/* add the first triangle */
-		if( AddMetaTriangleToSurface( ds, seed, qfalse ) )
-			(*numAdded)++;
-		
-		/* -----------------------------------------------------------------
-		   add triangles
-		   ----------------------------------------------------------------- */
-		
-		/* progressively walk the list until no more triangles can be added */
-		added = qtrue;
-		while( added )
-		{
-			/* print pacifier */
-			f = 10 * *numAdded / numMetaTriangles;
-			if( f > *fOld )
-			{
-				*fOld = f;
-				Sys_FPrintf( SYS_VRB, "%d...", f );
-			}
-			
-			/* reset best score */
-			best = -1;
-			bestScore = 0;
-			added = qfalse;
-			
-			/* walk the list of possible candidates for merging */
-			for( j = i + 1, test = &possibles[ j ]; j < numPossibles; j++, test++ )
-			{
-				/* score this triangle */
-				score = AddMetaTriangleToSurface( ds, test, qtrue );
-				if( score > bestScore )
-				{
-					best = j;
-					bestScore = score;
-					
-					/* if we have a score over a certain threshold, just use it */
-					if( bestScore >= GOOD_SCORE )
-					{
-						if( AddMetaTriangleToSurface( ds, &possibles[ best ], qfalse ) )
-							(*numAdded)++;
-						
-						/* reset */
-						best = -1;
-						bestScore = 0;
-						added = qtrue;
-					}
-				}
-			}
-			
-			/* add best candidate */
-			if( best >= 0 && bestScore > ADEQUATE_SCORE )
-			{
-				if( AddMetaTriangleToSurface( ds, &possibles[ best ], qfalse ) )
-					(*numAdded)++;
-				
-				/* reset */
-				added = qtrue;
-			}
-		}
-		
-		/* copy the verts and indexes to the new surface */
-		ds->verts = safe_malloc( ds->numVerts * sizeof( bspDrawVert_t ) );
-		memcpy( ds->verts, verts, ds->numVerts * sizeof( bspDrawVert_t ) );
-		ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) );
-		memcpy( ds->indexes, indexes, ds->numIndexes * sizeof( int ) );
-		
-		/* classify the surface */
-		ClassifySurfaces( 1, ds );
-		
-		/* add to count */
-		numMergedSurfaces++;
-	}
-	
-	/* free arrays */
-	free( verts );
-	free( indexes );
-}
-
-
-
-/*
-CompareMetaTriangles()
-compare function for qsort()
-*/
-
-static int CompareMetaTriangles( const void *a, const void *b )
-{
-	int		i, j, av, bv;
-	vec3_t	aMins, bMins;
-	
-	
-	/* shader first */
-	if( ((metaTriangle_t*) a)->si < ((metaTriangle_t*) b)->si )
-		return 1;
-	else if( ((metaTriangle_t*) a)->si > ((metaTriangle_t*) b)->si )
-		return -1;
-	
-	/* then fog */
-	else if( ((metaTriangle_t*) a)->fogNum < ((metaTriangle_t*) b)->fogNum )
-		return 1;
-	else if( ((metaTriangle_t*) a)->fogNum > ((metaTriangle_t*) b)->fogNum )
-		return -1;
-	
-	/* then position in world */
-	else
-	{
-		/* find mins */
-		VectorSet( aMins, 999999, 999999, 999999 );
-		VectorSet( bMins, 999999, 999999, 999999 );
-		for( i = 0; i < 3; i++ )
-		{
-			av = ((metaTriangle_t*) a)->indexes[ i ];
-			bv = ((metaTriangle_t*) b)->indexes[ i ];
-			for( j = 0; j < 3; j++ )
-			{
-				if( metaVerts[ av ].xyz[ j ] < aMins[ j ] )
-					aMins[ j ] = metaVerts[ av ].xyz[ j ];
-				if( metaVerts[ bv ].xyz[ j ] < bMins[ j ] )
-					bMins[ j ] = metaVerts[ bv ].xyz[ j ];
-			}
-		}
-		
-		/* test it */
-		for( i = 0; i < 3; i++ )
-		{
-			if( aMins[ i ] < bMins[ i ] )
-				return 1;
-			else if( aMins[ i ] > bMins[ i ] )
-				return -1;
-		}
-	}
-	
-	/* functionally equivalent */
-	return 0;
-}
-
-
-
-/*
-MergeMetaTriangles()
-merges meta triangles into drawsurfaces
-*/
-
-void MergeMetaTriangles( void )
-{
-	int					i, j, fOld, start, numAdded;
-	metaTriangle_t		*head, *end;
-	
-	
-	/* only do this if there are meta triangles */
-	if( numMetaTriangles <= 0 )
-		return;
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- MergeMetaTriangles ---\n" );
-	
-	/* sort the triangles by shader major, fognum minor */
-	qsort( metaTriangles, numMetaTriangles, sizeof( metaTriangle_t ), CompareMetaTriangles );
-
-	/* init pacifier */
-	fOld = -1;
-	start = I_FloatTime();
-	numAdded = 0;
-	
-	/* merge */
-	for( i = 0; i < numMetaTriangles; i = j )
-	{
-		/* get head of list */
-		head = &metaTriangles[ i ];
-		
-		/* find end */
-		for( j = i + 1; j < numMetaTriangles; j++ )
-		{
-			/* get end of list */
-			end = &metaTriangles[ j ];
-			if( head->si != end->si || head->fogNum != end->fogNum )
-				break;
-		}
-		
-		/* try to merge this list of possible merge candidates */
-		MetaTrianglesToSurface( (j - i), head, &fOld, &numAdded );
-	}
-	
-	/* clear meta triangle list */
-	ClearMetaTriangles();
-	
-	/* print time */
-	if( i )
-		Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
-	
-	/* emit some stats */
-	Sys_FPrintf( SYS_VRB, "%9d surfaces merged\n", numMergedSurfaces );
-	Sys_FPrintf( SYS_VRB, "%9d vertexes merged\n", numMergedVerts );
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define SURFACE_META_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+#define LIGHTMAP_EXCEEDED	-1
+#define S_EXCEEDED			-2
+#define T_EXCEEDED			-3
+#define ST_EXCEEDED			-4
+#define UNSUITABLE_TRIANGLE	-10
+#define VERTS_EXCEEDED		-1000
+#define INDEXES_EXCEEDED	-2000
+
+#define GROW_META_VERTS		1024
+#define GROW_META_TRIANGLES	1024
+
+static int					numMetaSurfaces, numPatchMetaSurfaces;
+
+static int					maxMetaVerts = 0;
+static int					numMetaVerts = 0;
+static int					firstSearchMetaVert = 0;
+static bspDrawVert_t		*metaVerts = NULL;
+
+static int					maxMetaTriangles = 0;
+static int					numMetaTriangles = 0;
+static metaTriangle_t		*metaTriangles = NULL;
+
+
+
+/*
+ClearMetaVertexes()
+called before staring a new entity to clear out the triangle list
+*/
+
+void ClearMetaTriangles( void )
+{
+	numMetaVerts = 0;
+	numMetaTriangles = 0;
+}
+
+
+
+/*
+FindMetaVertex()
+finds a matching metavertex in the global list, returning its index
+*/
+
+static int FindMetaVertex( bspDrawVert_t *src )
+{
+	int			i;
+	bspDrawVert_t	*v, *temp;
+	
+	
+	/* try to find an existing drawvert */
+	for( i = firstSearchMetaVert, v = &metaVerts[ i ]; i < numMetaVerts; i++, v++ )
+	{
+		if( memcmp( src, v, sizeof( bspDrawVert_t ) ) == 0 )
+			return i;
+	}
+	
+	/* enough space? */
+	if( numMetaVerts >= maxMetaVerts )
+	{
+		/* reallocate more room */
+		maxMetaVerts += GROW_META_VERTS;
+		temp = safe_malloc( maxMetaVerts * sizeof( bspDrawVert_t ) );
+		if( metaVerts != NULL )
+		{
+			memcpy( temp, metaVerts, numMetaVerts * sizeof( bspDrawVert_t ) );
+			free( metaVerts );
+		}
+		metaVerts = temp;
+	}
+	
+	/* add the triangle */
+	memcpy( &metaVerts[ numMetaVerts ], src, sizeof( bspDrawVert_t ) );
+	numMetaVerts++;
+	
+	/* return the count */
+	return (numMetaVerts - 1);
+}
+
+
+
+/*
+AddMetaTriangle()
+adds a new meta triangle, allocating more memory if necessary
+*/
+
+static int AddMetaTriangle( void )
+{
+	metaTriangle_t	*temp;
+	
+	
+	/* enough space? */
+	if( numMetaTriangles >= maxMetaTriangles )
+	{
+		/* reallocate more room */
+		maxMetaTriangles += GROW_META_TRIANGLES;
+		temp = safe_malloc( maxMetaTriangles * sizeof( metaTriangle_t ) );
+		if( metaTriangles != NULL )
+		{
+			memcpy( temp, metaTriangles, numMetaTriangles * sizeof( metaTriangle_t ) );
+			free( metaTriangles );
+		}
+		metaTriangles = temp;
+	}
+	
+	/* increment and return */
+	numMetaTriangles++;
+	return numMetaTriangles - 1;
+}
+
+
+
+/*
+FindMetaTriangle()
+finds a matching metatriangle in the global list,
+otherwise adds it and returns the index to the metatriangle
+*/
+
+int FindMetaTriangle( metaTriangle_t *src, bspDrawVert_t *a, bspDrawVert_t *b, bspDrawVert_t *c, int planeNum )
+{
+	int				triIndex;
+	vec3_t			dir;
+
+	
+	
+	/* detect degenerate triangles fixme: do something proper here */
+	VectorSubtract( a->xyz, b->xyz, dir );
+	if( VectorLength( dir ) < 0.125f )
+		return -1;
+	VectorSubtract( b->xyz, c->xyz, dir );
+	if( VectorLength( dir ) < 0.125f )
+		return -1;
+	VectorSubtract( c->xyz, a->xyz, dir );
+	if( VectorLength( dir ) < 0.125f )
+		return -1;
+	
+	/* find plane */
+	if( planeNum >= 0 )
+	{
+		/* because of precision issues with small triangles, try to use the specified plane */
+		src->planeNum = planeNum;
+		VectorCopy( mapplanes[ planeNum ].normal, src->plane );
+		src->plane[ 3 ] = mapplanes[ planeNum ].dist;
+	}
+	else
+	{
+		/* calculate a plane from the triangle's points (and bail if a plane can't be constructed) */
+		src->planeNum = -1;
+		if( PlaneFromPoints( src->plane, a->xyz, b->xyz, c->xyz ) == qfalse )
+			return -1;
+	}
+	
+	/* ydnar 2002-10-03: repair any bogus normals (busted ase import kludge) */
+	if( VectorLength( a->normal ) <= 0.0f )
+		VectorCopy( src->plane, a->normal );
+	if( VectorLength( b->normal ) <= 0.0f )
+		VectorCopy( src->plane, b->normal );
+	if( VectorLength( c->normal ) <= 0.0f )
+		VectorCopy( src->plane, c->normal );
+	
+	/* ydnar 2002-10-04: set lightmap axis if not already set */
+	if( !(src->si->compileFlags & C_VERTEXLIT) &&
+		src->lightmapAxis[ 0 ] == 0.0f && src->lightmapAxis[ 1 ] == 0.0f && src->lightmapAxis[ 2 ] == 0.0f )
+	{
+		/* the shader can specify an explicit lightmap axis */
+		if( src->si->lightmapAxis[ 0 ] || src->si->lightmapAxis[ 1 ] || src->si->lightmapAxis[ 2 ] )
+			VectorCopy( src->si->lightmapAxis, src->lightmapAxis );
+		
+		/* new axis-finding code */
+		else
+			CalcLightmapAxis( src->plane, src->lightmapAxis );
+	}
+	
+	/* fill out the src triangle */
+	src->indexes[ 0 ] = FindMetaVertex( a );
+	src->indexes[ 1 ] = FindMetaVertex( b );
+	src->indexes[ 2 ] = FindMetaVertex( c );
+	
+	/* try to find an existing triangle */
+	#ifdef USE_EXHAUSTIVE_SEARCH
+	{
+		int				i;
+		metaTriangle_t	*tri;
+		
+		
+		for( i = 0, tri = metaTriangles; i < numMetaTriangles; i++, tri++ )
+		{
+			if( memcmp( src, tri, sizeof( metaTriangle_t ) ) == 0 )
+				return i;
+		}
+	}
+	#endif
+	
+	/* get a new triangle */
+	triIndex = AddMetaTriangle();
+	
+	/* add the triangle */
+	memcpy( &metaTriangles[ triIndex ], src, sizeof( metaTriangle_t ) );
+	
+	/* return the triangle index */
+	return triIndex;
+}
+
+
+
+/*
+SurfaceToMetaTriangles()
+converts a classified surface to metatriangles
+*/
+
+static void SurfaceToMetaTriangles( mapDrawSurface_t *ds )
+{
+	int				i;
+	metaTriangle_t	src;
+	bspDrawVert_t	a, b, c;
+	
+	
+	/* only handle certain types of surfaces */
+	if( ds->type != SURFACE_FACE &&
+		ds->type != SURFACE_META &&
+		ds->type != SURFACE_FORCED_META &&
+		ds->type != SURFACE_DECAL )
+		return;
+	
+	/* speed at the expense of memory */
+	firstSearchMetaVert = numMetaVerts;
+	
+	/* only handle valid surfaces */
+	if( ds->type != SURFACE_BAD && ds->numVerts >= 3 && ds->numIndexes >= 3 )
+	{
+		/* walk the indexes and create triangles */
+		for( i = 0; i < ds->numIndexes; i += 3 )
+		{
+			/* sanity check the indexes */
+			if( ds->indexes[ i ] == ds->indexes[ i + 1 ] ||
+				ds->indexes[ i ] == ds->indexes[ i + 2 ] ||
+				ds->indexes[ i + 1 ] == ds->indexes[ i + 2 ] )
+			{
+				//%	Sys_Printf( "%d! ", ds->numVerts );
+				continue;
+			}
+			
+			/* build a metatriangle */
+			src.si = ds->shaderInfo;
+			src.side = (ds->sideRef != NULL ? ds->sideRef->side : NULL);
+			src.entityNum = ds->entityNum;
+			src.surfaceNum = ds->surfaceNum;
+			src.planeNum = ds->planeNum;
+			src.castShadows = ds->castShadows;
+			src.recvShadows = ds->recvShadows;
+			src.fogNum = ds->fogNum;
+			src.sampleSize = ds->sampleSize;
+			VectorCopy( ds->lightmapAxis, src.lightmapAxis );
+			
+			/* copy drawverts */
+			memcpy( &a, &ds->verts[ ds->indexes[ i ] ], sizeof( a ) );
+			memcpy( &b, &ds->verts[ ds->indexes[ i + 1 ] ], sizeof( b ) );
+			memcpy( &c, &ds->verts[ ds->indexes[ i + 2 ] ], sizeof( c ) );
+			FindMetaTriangle( &src, &a, &b, &c, ds->planeNum );
+		}
+		
+		/* add to count */
+		numMetaSurfaces++;
+	}
+	
+	/* clear the surface (free verts and indexes, sets it to SURFACE_BAD) */
+	ClearSurface( ds );
+}
+
+
+
+/*
+TriangulatePatchSurface()
+creates triangles from a patch
+*/
+
+void TriangulatePatchSurface( mapDrawSurface_t *ds )
+{
+	int					iterations, x, y, pw[ 5 ], r;
+	mapDrawSurface_t	*dsNew;
+	mesh_t				src, *subdivided, *mesh;
+	
+	
+	/* try to early out */
+	if( ds->numVerts == 0 || ds->type != SURFACE_PATCH || patchMeta == qfalse )
+		return;
+	
+	/* make a mesh from the drawsurf */ 
+	src.width = ds->patchWidth;
+	src.height = ds->patchHeight;
+	src.verts = ds->verts;
+	//%	subdivided = SubdivideMesh( src, 8, 999 );
+	iterations = IterationsForCurve( ds->longestCurve, patchSubdivisions );
+	subdivided = SubdivideMesh2( src, iterations );	//%	ds->maxIterations
+	
+	/* fit it to the curve and remove colinear verts on rows/columns */
+	PutMeshOnCurve( *subdivided );
+	mesh = RemoveLinearMeshColumnsRows( subdivided );
+	FreeMesh( subdivided );
+	//% MakeMeshNormals( mesh );
+	
+	/* make a copy of the drawsurface */
+	dsNew = AllocDrawSurface( SURFACE_META );
+	memcpy( dsNew, ds, sizeof( *ds ) );
+	
+	/* if the patch is nonsolid, then discard it */
+	if( !(ds->shaderInfo->compileFlags & C_SOLID) )
+		ClearSurface( ds );
+	
+	/* set new pointer */
+	ds = dsNew;
+	
+	/* basic transmogrification */
+	ds->type = SURFACE_META;
+	ds->numIndexes = 0;
+	ds->indexes = safe_malloc( mesh->width * mesh->height * 6 * sizeof( int ) );
+	
+	/* copy the verts in */
+	ds->numVerts = (mesh->width * mesh->height);
+	ds->verts = mesh->verts;
+	
+	/* iterate through the mesh quads */
+	for( y = 0; y < (mesh->height - 1); y++ )
+	{
+		for( x = 0; x < (mesh->width - 1); x++ )
+		{
+			/* set indexes */
+			pw[ 0 ] = x + (y * mesh->width);
+			pw[ 1 ] = x + ((y + 1) * mesh->width);
+			pw[ 2 ] = x + 1 + ((y + 1) * mesh->width);
+			pw[ 3 ] = x + 1 + (y * mesh->width);
+			pw[ 4 ] = x + (y * mesh->width);	/* same as pw[ 0 ] */
+			
+			/* set radix */
+			r = (x + y) & 1;
+			
+			/* make first triangle */
+			ds->indexes[ ds->numIndexes++ ] = pw[ r + 0 ];
+			ds->indexes[ ds->numIndexes++ ] = pw[ r + 1 ];
+			ds->indexes[ ds->numIndexes++ ] = pw[ r + 2 ];
+			
+			/* make second triangle */
+			ds->indexes[ ds->numIndexes++ ] = pw[ r + 0 ];
+			ds->indexes[ ds->numIndexes++ ] = pw[ r + 2 ];
+			ds->indexes[ ds->numIndexes++ ] = pw[ r + 3 ];
+		}
+	}
+	
+	/* free the mesh, but not the verts */
+	free( mesh );
+	
+	/* add to count */
+	numPatchMetaSurfaces++;
+	
+	/* classify it */
+	ClassifySurfaces( 1, ds );
+}
+
+
+
+/*
+FanFaceSurface() - ydnar
+creates a tri-fan from a brush face winding
+loosely based on SurfaceAsTriFan()
+*/
+
+void FanFaceSurface( mapDrawSurface_t *ds )
+{
+	int				i, j, k, a, b, c, color[ MAX_LIGHTMAPS ][ 4 ];
+	bspDrawVert_t	*verts, *centroid, *dv;
+	double			iv;
+	
+	
+	/* try to early out */
+	if( !ds->numVerts || (ds->type != SURFACE_FACE && ds->type != SURFACE_DECAL) )
+		return;
+	
+	/* add a new vertex at the beginning of the surface */
+	verts = safe_malloc( (ds->numVerts + 1) * sizeof( bspDrawVert_t ) );
+	memset( verts, 0, sizeof( bspDrawVert_t ) );
+	memcpy( &verts[ 1 ], ds->verts, ds->numVerts * sizeof( bspDrawVert_t ) );
+	free( ds->verts );
+	ds->verts = verts;
+	
+	/* add up the drawverts to create a centroid */
+	centroid = &verts[ 0 ];
+	memset( color, 0,  4 * MAX_LIGHTMAPS * sizeof( int ) );
+	for( i = 1, dv = &verts[ 1 ]; i < (ds->numVerts + 1); i++, dv++ )
+	{
+		VectorAdd( centroid->xyz, dv->xyz, centroid->xyz );
+		VectorAdd( centroid->normal, dv->normal, centroid->normal );
+		for( j = 0; j < 4; j++ )
+		{
+			for( k = 0; k < MAX_LIGHTMAPS; k++ )
+				color[ k ][ j ] += dv->color[ k ][ j ];
+			if( j < 2 )
+			{
+				centroid->st[ j ] += dv->st[ j ];
+				for( k = 0; k < MAX_LIGHTMAPS; k++ )
+					centroid->lightmap[ k ][ j ] += dv->lightmap[ k ][ j ];
+			}
+		}
+	}
+	
+	/* average the centroid */
+	iv = 1.0f / ds->numVerts;
+	VectorScale( centroid->xyz, iv, centroid->xyz );
+	if( VectorNormalize( centroid->normal, centroid->normal ) <= 0 )
+		VectorCopy( verts[ 1 ].normal, centroid->normal );
+	for( j = 0; j < 4; j++ )
+	{
+		for( k = 0; k < MAX_LIGHTMAPS; k++ )
+		{
+			color[ k ][ j ] /= ds->numVerts;
+			centroid->color[ k ][ j ] = (color[ k ][ j ] < 255.0f ? color[ k ][ j ] : 255);
+		}
+		if( j < 2 )
+		{
+			centroid->st[ j ] *= iv;
+			for( k = 0; k < MAX_LIGHTMAPS; k++ )
+				centroid->lightmap[ k ][ j ] *= iv;
+		}
+	}
+	
+	/* add to vert count */
+	ds->numVerts++;
+	
+	/* fill indexes in triangle fan order */
+	ds->numIndexes = 0;
+	ds->indexes = safe_malloc( ds->numVerts * 3 * sizeof( int ) );
+	for( i = 1; i < ds->numVerts; i++ )
+	{
+		a = 0;
+		b = i;
+		c = (i + 1) % ds->numVerts;
+		c = c ? c : 1;
+		ds->indexes[ ds->numIndexes++ ] = a;
+		ds->indexes[ ds->numIndexes++ ] = b;
+		ds->indexes[ ds->numIndexes++ ] = c;
+	}
+	
+	/* add to count */
+	numFanSurfaces++;
+
+	/* classify it */
+	ClassifySurfaces( 1, ds );
+}
+
+
+
+/*
+StripFaceSurface() - ydnar
+attempts to create a valid tri-strip w/o degenerate triangles from a brush face winding
+based on SurfaceAsTriStrip()
+*/
+
+#define MAX_INDEXES		1024
+
+void StripFaceSurface( mapDrawSurface_t *ds ) 
+{
+	int			i, r, least, rotate, numIndexes, ni, a, b, c, indexes[ MAX_INDEXES ];
+	vec_t		*v1, *v2;
+	
+	
+	/* try to early out  */
+	if( !ds->numVerts || (ds->type != SURFACE_FACE && ds->type != SURFACE_DECAL) )
+		return;
+	
+	/* is this a simple triangle? */
+	if( ds->numVerts == 3 )
+	{
+		numIndexes = 3;
+		VectorSet( indexes, 0, 1, 2 );
+	}
+	else
+	{
+		/* ydnar: find smallest coordinate */
+		least = 0;
+		if( ds->shaderInfo != NULL && ds->shaderInfo->autosprite == qfalse )
+		{
+			for( i = 0; i < ds->numVerts; i++ )
+			{
+				/* get points */
+				v1 = ds->verts[ i ].xyz;
+				v2 = ds->verts[ least ].xyz;
+				
+				/* compare */
+				if( v1[ 0 ] < v2[ 0 ] ||
+					(v1[ 0 ] == v2[ 0 ] && v1[ 1 ] < v2[ 1 ]) ||
+					(v1[ 0 ] == v2[ 0 ] && v1[ 1 ] == v2[ 1 ] && v1[ 2 ] < v2[ 2 ]) )
+					least = i;
+			}
+		}
+		
+		/* determine the triangle strip order */
+		numIndexes = (ds->numVerts - 2) * 3;
+		if( numIndexes > MAX_INDEXES )
+			Error( "MAX_INDEXES exceeded for surface (%d > %d) (%d verts)", numIndexes, MAX_INDEXES, ds->numVerts );
+		
+		/* try all possible orderings of the points looking for a non-degenerate strip order */
+		for( r = 0; r < ds->numVerts; r++ )
+		{
+			/* set rotation */
+			rotate = (r + least) % ds->numVerts;
+			
+			/* walk the winding in both directions */
+			for( ni = 0, i = 0; i < ds->numVerts - 2 - i; i++ )
+			{
+				/* make indexes */
+				a = (ds->numVerts - 1 - i + rotate) % ds->numVerts;
+				b = (i + rotate ) % ds->numVerts;
+				c = (ds->numVerts - 2 - i + rotate) % ds->numVerts;
+				
+				/* test this triangle */
+				if( ds->numVerts > 4 && IsTriangleDegenerate( ds->verts, a, b, c ) )
+					break;
+				indexes[ ni++ ] = a;
+				indexes[ ni++ ] = b;
+				indexes[ ni++ ] = c;
+				
+				/* handle end case */
+				if( i + 1 != ds->numVerts - 1 - i )
+				{
+					/* make indexes */
+					a = (ds->numVerts - 2 - i + rotate ) % ds->numVerts;
+					b = (i + rotate ) % ds->numVerts;
+					c = (i + 1 + rotate ) % ds->numVerts;
+					
+					/* test triangle */
+					if( ds->numVerts > 4 && IsTriangleDegenerate( ds->verts, a, b, c ) )
+						break;
+					indexes[ ni++ ] = a;
+					indexes[ ni++ ] = b;
+					indexes[ ni++ ] = c;
+				}
+			}
+			
+			/* valid strip? */
+			if( ni == numIndexes )
+				break;
+		}
+		
+		/* if any triangle in the strip is degenerate, render from a centered fan point instead */
+		if( ni < numIndexes )
+		{
+			FanFaceSurface( ds );
+			return;
+		}
+	}
+	
+	/* copy strip triangle indexes */
+	ds->numIndexes = numIndexes;
+	ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) );
+	memcpy( ds->indexes, indexes, ds->numIndexes * sizeof( int ) );
+	
+	/* add to count */
+	numStripSurfaces++;
+	
+	/* classify it */
+	ClassifySurfaces( 1, ds );
+}
+
+
+
+/*
+MakeEntityMetaTriangles()
+builds meta triangles from brush faces (tristrips and fans)
+*/
+
+void MakeEntityMetaTriangles( entity_t *e )
+{
+	int					i, f, fOld, start;
+	mapDrawSurface_t	*ds;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- MakeEntityMetaTriangles ---\n" );
+	
+	/* init pacifier */
+	fOld = -1;
+	start = I_FloatTime();
+	
+	/* walk the list of surfaces in the entity */
+	for( i = e->firstDrawSurf; i < numMapDrawSurfs; i++ )
+	{
+		/* print pacifier */
+		f = 10 * (i - e->firstDrawSurf) / (numMapDrawSurfs - e->firstDrawSurf);
+		if( f != fOld )
+		{
+			fOld = f;
+			Sys_FPrintf( SYS_VRB, "%d...", f );
+		}
+		
+		/* get surface */
+		ds = &mapDrawSurfs[ i ];
+		if( ds->numVerts <= 0 )
+			continue;
+		
+		/* ignore autosprite surfaces */
+		if( ds->shaderInfo->autosprite )
+			continue;
+		
+		/* meta this surface? */
+		if( meta == qfalse && ds->shaderInfo->forceMeta == qfalse )
+			continue;
+		
+		/* switch on type */
+		switch( ds->type )
+		{
+			case SURFACE_FACE:
+			case SURFACE_DECAL:
+				StripFaceSurface( ds );
+				SurfaceToMetaTriangles( ds );
+				break;
+			
+			case SURFACE_PATCH:
+				TriangulatePatchSurface( ds );
+				break;
+			
+			case SURFACE_TRIANGLES:
+				break;
+			
+			case SURFACE_FORCED_META:
+			case SURFACE_META:
+				SurfaceToMetaTriangles( ds );
+				break;
+			
+			default:
+				break;
+		}
+	}
+	
+	/* print time */
+	if( (numMapDrawSurfs - e->firstDrawSurf) )
+		Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d total meta surfaces\n", numMetaSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d stripped surfaces\n", numStripSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d fanned surfaces\n", numFanSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d patch meta surfaces\n", numPatchMetaSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d meta verts\n", numMetaVerts );
+	Sys_FPrintf( SYS_VRB, "%9d meta triangles\n", numMetaTriangles );
+	
+	/* tidy things up */
+	TidyEntitySurfaces( e );
+}
+
+
+
+/*
+PointTriangleIntersect()
+assuming that all points lie in plane, determine if pt
+is inside the triangle abc
+code originally (c) 2001 softSurfer (www.softsurfer.com)
+*/
+
+#define MIN_OUTSIDE_EPSILON		-0.01f
+#define MAX_OUTSIDE_EPSILON		1.01f
+
+static qboolean PointTriangleIntersect( vec3_t pt, vec4_t plane, vec3_t a, vec3_t b, vec3_t c, vec3_t bary )
+{
+	vec3_t	u, v, w;
+	float	uu, uv, vv, wu, wv, d;
+	
+	
+	/* make vectors */
+	VectorSubtract( b, a, u );
+	VectorSubtract( c, a, v );
+	VectorSubtract( pt, a, w );
+	
+	/* more setup */
+	uu = DotProduct( u, u );
+	uv = DotProduct( u, v );
+	vv = DotProduct( v, v );
+	wu = DotProduct( w, u );
+	wv = DotProduct( w, v );
+	d = uv * uv - uu * vv;
+	
+	/* calculate barycentric coordinates */
+	bary[ 1 ] = (uv * wv - vv * wu) / d;
+	if( bary[ 1 ] < MIN_OUTSIDE_EPSILON || bary[ 1 ] > MAX_OUTSIDE_EPSILON )
+		return qfalse;
+	bary[ 2 ] = (uv * wv - uu * wv) / d;
+	if( bary[ 2 ] < MIN_OUTSIDE_EPSILON || bary[ 2 ] > MAX_OUTSIDE_EPSILON )
+		return qfalse;
+	bary[ 0 ] = 1.0f - (bary[ 1 ] + bary[ 2 ]);
+	
+	/* point is in triangle */
+	return qtrue;
+}
+
+
+
+/*
+CreateEdge()
+sets up an edge structure from a plane and 2 points that the edge ab falls lies in
+*/
+
+typedef struct edge_s
+{
+	vec3_t	origin, edge;
+	vec_t	length, kingpinLength;
+	int		kingpin;
+	vec4_t	plane;
+}
+edge_t;
+
+void CreateEdge( vec4_t plane, vec3_t a, vec3_t b, edge_t *edge )
+{
+	/* copy edge origin */
+	VectorCopy( a, edge->origin );
+	
+	/* create vector aligned with winding direction of edge */
+	VectorSubtract( b, a, edge->edge );
+	
+	if( fabs( edge->edge[ 0 ] ) > fabs( edge->edge[ 1 ] ) && fabs( edge->edge[ 0 ] ) > fabs( edge->edge[ 2 ] ) )
+		edge->kingpin = 0;
+	else if( fabs( edge->edge[ 1 ] ) > fabs( edge->edge[ 0 ] ) && fabs( edge->edge[ 1 ] ) > fabs( edge->edge[ 2 ] ) )
+		edge->kingpin = 1;
+	else
+		edge->kingpin = 2;
+	edge->kingpinLength = edge->edge[ edge->kingpin ];
+	
+	VectorNormalize( edge->edge, edge->edge );
+	edge->edge[ 3 ] = DotProduct( a, edge->edge );
+	edge->length = DotProduct( b, edge->edge ) - edge->edge[ 3 ];
+	
+	/* create perpendicular plane that edge lies in */
+	CrossProduct( plane, edge->edge, edge->plane );
+	edge->plane[ 3 ] = DotProduct( a, edge->plane );
+}
+
+
+
+/*
+FixMetaTJunctions()
+fixes t-junctions on meta triangles
+*/
+
+#define TJ_PLANE_EPSILON	(1.0f / 8.0f)
+#define TJ_EDGE_EPSILON		(1.0f / 8.0f)
+#define TJ_POINT_EPSILON	(1.0f / 8.0f)
+
+void FixMetaTJunctions( void )
+{
+	int				i, j, k, f, fOld, start, vertIndex, triIndex, numTJuncs;
+	metaTriangle_t	*tri, *newTri;
+	shaderInfo_t	*si;
+	bspDrawVert_t	*a, *b, *c, junc;
+	float			dist, amount;
+	vec3_t			pt;
+	vec4_t			plane;
+	edge_t			edges[ 3 ];
+	
+	
+	/* this code is crap; revisit later */
+	return;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- FixMetaTJunctions ---\n" );
+	
+	/* init pacifier */
+	fOld = -1;
+	start = I_FloatTime();
+	
+	/* walk triangle list */
+	numTJuncs = 0;
+	for( i = 0; i < numMetaTriangles; i++ )
+	{
+		/* get triangle */
+		tri = &metaTriangles[ i ];
+		
+		/* print pacifier */
+		f = 10 * i / numMetaTriangles;
+		if( f != fOld )
+		{
+			fOld = f;
+			Sys_FPrintf( SYS_VRB, "%d...", f );
+		}
+		
+		/* attempt to early out */
+		si = tri->si;
+		if( (si->compileFlags & C_NODRAW) || si->autosprite || si->notjunc )
+			continue;
+		
+		/* calculate planes */
+		VectorCopy( tri->plane, plane );
+		plane[ 3 ] = tri->plane[ 3 ];
+		CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] );
+		CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] );
+		CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );
+		
+		/* walk meta vert list */
+		for( j = 0; j < numMetaVerts; j++ )
+		{
+			/* get vert */
+			VectorCopy( metaVerts[ j ].xyz, pt );
+
+			/* debug code: darken verts */
+			if( i == 0 )
+				VectorSet( metaVerts[ j ].color[ 0 ], 8, 8, 8 );
+			
+			/* determine if point lies in the triangle's plane */
+			dist = DotProduct( pt, plane ) - plane[ 3 ];
+			if( fabs( dist ) > TJ_PLANE_EPSILON )
+				continue;
+			
+			/* skip this point if it already exists in the triangle */
+			for( k = 0; k < 3; k++ )
+			{
+				if( fabs( pt[ 0 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 0 ] ) <= TJ_POINT_EPSILON &&
+					fabs( pt[ 1 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 1 ] ) <= TJ_POINT_EPSILON &&
+					fabs( pt[ 2 ] - metaVerts[ tri->indexes[ k ] ].xyz[ 2 ] ) <= TJ_POINT_EPSILON )
+					break;
+			}
+			if( k < 3 )
+				continue;
+			
+			/* walk edges */
+			for( k = 0; k < 3; k++ )
+			{
+				/* ignore bogus edges */
+				if( fabs( edges[ k ].kingpinLength ) < TJ_EDGE_EPSILON )
+					continue;
+				
+				/* determine if point lies on the edge */
+				dist = DotProduct( pt, edges[ k ].plane ) - edges[ k ].plane[ 3 ];
+				if( fabs( dist ) > TJ_EDGE_EPSILON )
+					continue;
+				
+				/* determine how far along the edge the point lies */
+				amount = (pt[ edges[ k ].kingpin ] - edges[ k ].origin[ edges[ k ].kingpin ]) / edges[ k ].kingpinLength;
+				if( amount <= 0.0f || amount >= 1.0f )
+					continue;
+				
+				#if 0
+				dist = DotProduct( pt, edges[ k ].edge ) - edges[ k ].edge[ 3 ];
+				if( dist <= -0.0f || dist >= edges[ k ].length )
+					continue;
+				amount = dist / edges[ k ].length;
+				#endif
+				
+				/* debug code: brighten this point */
+				//%	metaVerts[ j ].color[ 0 ][ 0 ] += 5;
+				//%	metaVerts[ j ].color[ 0 ][ 1 ] += 4;
+				VectorSet( metaVerts[ tri->indexes[ k ] ].color[ 0 ], 255, 204, 0 );
+				VectorSet( metaVerts[ tri->indexes[ (k + 1) % 3 ] ].color[ 0 ], 255, 204, 0 );
+				
+
+				/* the edge opposite the zero-weighted vertex was hit, so use that as an amount */
+				a = &metaVerts[ tri->indexes[ k % 3 ] ];
+				b = &metaVerts[ tri->indexes[ (k + 1) % 3 ] ];
+				c = &metaVerts[ tri->indexes[ (k + 2) % 3 ] ];
+				
+				/* make new vert */
+				LerpDrawVertAmount( a, b, amount, &junc );
+				VectorCopy( pt, junc.xyz );
+				
+				/* compare against existing verts */
+				if( VectorCompare( junc.xyz, a->xyz ) || VectorCompare( junc.xyz, b->xyz ) || VectorCompare( junc.xyz, c->xyz ) )
+					continue;
+				
+				/* see if we can just re-use the existing vert */
+				if( !memcmp( &metaVerts[ j ], &junc, sizeof( junc ) ) )
+					vertIndex = j;
+				else
+				{
+					/* find new vertex (note: a and b are invalid pointers after this) */
+					firstSearchMetaVert = numMetaVerts;
+					vertIndex = FindMetaVertex( &junc );
+					if( vertIndex < 0 )
+						continue;
+				}
+						
+				/* make new triangle */
+				triIndex = AddMetaTriangle();
+				if( triIndex < 0 )
+					continue;
+				
+				/* get triangles */
+				tri = &metaTriangles[ i ];
+				newTri = &metaTriangles[ triIndex ];
+				
+				/* copy the triangle */
+				memcpy( newTri, tri, sizeof( *tri ) );
+				
+				/* fix verts */
+				tri->indexes[ (k + 1) % 3 ] = vertIndex;
+				newTri->indexes[ k ] = vertIndex;
+				
+				/* recalculate edges */
+				CreateEdge( plane, metaVerts[ tri->indexes[ 0 ] ].xyz, metaVerts[ tri->indexes[ 1 ] ].xyz, &edges[ 0 ] );
+				CreateEdge( plane, metaVerts[ tri->indexes[ 1 ] ].xyz, metaVerts[ tri->indexes[ 2 ] ].xyz, &edges[ 1 ] );
+				CreateEdge( plane, metaVerts[ tri->indexes[ 2 ] ].xyz, metaVerts[ tri->indexes[ 0 ] ].xyz, &edges[ 2 ] );
+				
+				/* debug code */
+				metaVerts[ vertIndex ].color[ 0 ][ 0 ] = 255;
+				metaVerts[ vertIndex ].color[ 0 ][ 1 ] = 204;
+				metaVerts[ vertIndex ].color[ 0 ][ 2 ] = 0;
+				
+				/* add to counter and end processing of this vert */
+				numTJuncs++;
+				break;
+			}
+		}
+	}
+	
+	/* print time */
+	Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d T-junctions added\n", numTJuncs );
+}
+
+
+
+/*
+SmoothMetaTriangles()
+averages coincident vertex normals in the meta triangles
+*/
+
+#define MAX_SAMPLES				256
+#define THETA_EPSILON			0.000001
+#define EQUAL_NORMAL_EPSILON	0.01
+
+void SmoothMetaTriangles( void )
+{
+	int				i, j, k, f, fOld, start, cs, numVerts, numVotes, numSmoothed;
+	float			shadeAngle, defaultShadeAngle, maxShadeAngle, dot, testAngle;
+	metaTriangle_t	*tri;
+	float			*shadeAngles;
+	byte			*smoothed;
+	vec3_t			average, diff;
+	int				indexes[ MAX_SAMPLES ];
+	vec3_t			votes[ MAX_SAMPLES ];
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- SmoothMetaTriangles ---\n" );
+	
+	/* allocate shade angle table */
+	shadeAngles = safe_malloc( numMetaVerts * sizeof( float ) );
+	memset( shadeAngles, 0, numMetaVerts * sizeof( float ) );
+	
+	/* allocate smoothed table */
+	cs = (numMetaVerts / 8) + 1;
+	smoothed = safe_malloc( cs );
+	memset( smoothed, 0, cs );
+	
+	/* set default shade angle */
+	defaultShadeAngle = DEG2RAD( npDegrees );
+	maxShadeAngle = 0.0f;
+	
+	/* run through every surface and flag verts belonging to non-lightmapped surfaces
+	   and set per-vertex smoothing angle */
+	for( i = 0, tri = &metaTriangles[ i ]; i < numMetaTriangles; i++, tri++ )
+	{
+		/* get shader for shade angle */
+		if( tri->si->shadeAngleDegrees > 0.0f )
+			shadeAngle = DEG2RAD( tri->si->shadeAngleDegrees );
+		else
+			shadeAngle = defaultShadeAngle;
+		if( shadeAngle > maxShadeAngle )
+			maxShadeAngle = shadeAngle;
+		
+		/* flag its verts */
+		for( j = 0; j < 3; j++ )
+		{
+			shadeAngles[ tri->indexes[ j ] ] = shadeAngle;
+			if( shadeAngle <= 0 )
+				smoothed[ tri->indexes[ j ] >> 3 ] |= (1 << (tri->indexes[ j ] & 7));
+		}
+	}
+	
+	/* bail if no surfaces have a shade angle */
+	if( maxShadeAngle <= 0 )
+	{
+		Sys_FPrintf( SYS_VRB, "No smoothing angles specified, aborting\n" );
+		free( shadeAngles );
+		free( smoothed );
+		return;
+	}
+	
+	/* init pacifier */
+	fOld = -1;
+	start = I_FloatTime();
+	
+	/* go through the list of vertexes */
+	numSmoothed = 0;
+	for( i = 0; i < numMetaVerts; i++ )
+	{
+		/* print pacifier */
+		f = 10 * i / numMetaVerts;
+		if( f != fOld )
+		{
+			fOld = f;
+			Sys_FPrintf( SYS_VRB, "%d...", f );
+		}
+		
+		/* already smoothed? */
+		if( smoothed[ i >> 3 ] & (1 << (i & 7)) )
+			continue;
+		
+		/* clear */
+		VectorClear( average );
+		numVerts = 0;
+		numVotes = 0;
+		
+		/* build a table of coincident vertexes */
+		for( j = i; j < numMetaVerts && numVerts < MAX_SAMPLES; j++ )
+		{
+			/* already smoothed? */
+			if( smoothed[ j >> 3 ] & (1 << (j & 7)) )
+				continue;
+			
+			/* test vertexes */
+			if( VectorCompare( metaVerts[ i ].xyz, metaVerts[ j ].xyz ) == qfalse )
+				continue;
+			
+			/* use smallest shade angle */
+			shadeAngle = (shadeAngles[ i ] < shadeAngles[ j ] ? shadeAngles[ i ] : shadeAngles[ j ]);
+			
+			/* check shade angle */
+			dot = DotProduct( metaVerts[ i ].normal, metaVerts[ j ].normal );
+			if( dot > 1.0 )
+				dot = 1.0;
+			else if( dot < -1.0 )
+				dot = -1.0;
+			testAngle = acos( dot ) + THETA_EPSILON;
+			if( testAngle >= shadeAngle )
+				continue;
+			
+			/* add to the list */
+			indexes[ numVerts++ ] = j;
+			
+			/* flag vertex */
+			smoothed[ j >> 3 ] |= (1 << (j & 7));
+			
+			/* see if this normal has already been voted */
+			for( k = 0; k < numVotes; k++ )
+			{
+				VectorSubtract( metaVerts[ j ].normal, votes[ k ], diff );
+				if( fabs( diff[ 0 ] ) < EQUAL_NORMAL_EPSILON &&
+					fabs( diff[ 1 ] ) < EQUAL_NORMAL_EPSILON &&
+					fabs( diff[ 2 ] ) < EQUAL_NORMAL_EPSILON )
+					break;
+			}
+			
+			/* add a new vote? */
+			if( k == numVotes && numVotes < MAX_SAMPLES )
+			{
+				VectorAdd( average, metaVerts[ j ].normal, average );
+				VectorCopy( metaVerts[ j ].normal, votes[ numVotes ] );
+				numVotes++;
+			}
+		}
+		
+		/* don't average for less than 2 verts */
+		if( numVerts < 2 )
+			continue;
+		
+		/* average normal */
+		if( VectorNormalize( average, average ) > 0 )
+		{
+			/* smooth */
+			for( j = 0; j < numVerts; j++ )
+				VectorCopy( average, metaVerts[ indexes[ j ] ].normal );
+			numSmoothed++;
+		}
+	}
+	
+	/* free the tables */
+	free( shadeAngles );
+	free( smoothed );
+	
+	/* print time */
+	Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
+
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d smoothed vertexes\n", numSmoothed );
+}
+
+
+
+/*
+AddMetaVertToSurface()
+adds a drawvert to a surface unless an existing vert matching already exists
+returns the index of that vert (or < 0 on failure)
+*/
+
+int AddMetaVertToSurface( mapDrawSurface_t *ds, bspDrawVert_t *dv1, int *coincident )
+{
+	int				i;
+	bspDrawVert_t	*dv2;
+	
+	
+	/* go through the verts and find a suitable candidate */
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		/* get test vert */
+		dv2 = &ds->verts[ i ];
+		
+		/* compare xyz and normal */
+		if( VectorCompare( dv1->xyz, dv2->xyz ) == qfalse )
+			continue;
+		if( VectorCompare( dv1->normal, dv2->normal ) == qfalse )
+			continue;
+		
+		/* good enough at this point */
+		(*coincident)++;
+		
+		/* compare texture coordinates and color */
+		if( dv1->st[ 0 ] != dv2->st[ 0 ] || dv1->st[ 1 ] != dv2->st[ 1 ] )
+			continue;
+		if( dv1->color[ 0 ][ 3 ] != dv2->color[ 0 ][ 3 ] )
+			continue;
+		
+		/* found a winner */
+		numMergedVerts++;
+		return i;
+	}
+
+	/* overflow check */
+	if( ds->numVerts >= maxSurfaceVerts )
+		return VERTS_EXCEEDED;
+	
+	/* made it this far, add the vert and return */
+	dv2 = &ds->verts[ ds->numVerts++ ];
+	*dv2 = *dv1;
+	return (ds->numVerts - 1);
+}
+
+
+
+
+/*
+AddMetaTriangleToSurface()
+attempts to add a metatriangle to a surface
+returns the score of the triangle added
+*/
+
+#define AXIS_SCORE			100000
+#define AXIS_MIN			100000
+#define VERT_SCORE			10000
+#define SURFACE_SCORE		1000
+#define ST_SCORE			50
+#define ST_SCORE2			(2 * (ST_SCORE))
+
+#define ADEQUATE_SCORE		((AXIS_MIN) + 1 * (VERT_SCORE))
+#define GOOD_SCORE			((AXIS_MIN) + 2 * (VERT_SCORE) + 4 * (ST_SCORE))
+#define PERFECT_SCORE		((AXIS_MIN) + + 3 * (VERT_SCORE) + (SURFACE_SCORE) + 4 * (ST_SCORE))
+
+static int AddMetaTriangleToSurface( mapDrawSurface_t *ds, metaTriangle_t *tri, qboolean testAdd )
+{
+	int					i, score, coincident, ai, bi, ci, oldTexRange[ 2 ];
+	float				lmMax;
+	vec3_t				mins, maxs;
+	qboolean			inTexRange, es, et;
+	mapDrawSurface_t	old;
+	
+	
+	/* overflow check */
+	if( ds->numIndexes >= maxSurfaceIndexes )
+		return 0;
+	
+	/* test the triangle */
+	if( ds->entityNum != tri->entityNum )	/* ydnar: added 2002-07-06 */
+		return 0;
+	if( ds->castShadows != tri->castShadows || ds->recvShadows != tri->recvShadows )
+		return 0;
+	if( ds->shaderInfo != tri->si || ds->fogNum != tri->fogNum || ds->sampleSize != tri->sampleSize )
+		return 0;
+	#if 0
+		if( !(ds->shaderInfo->compileFlags & C_VERTEXLIT) &&
+			//% VectorCompare( ds->lightmapAxis, tri->lightmapAxis ) == qfalse )
+			DotProduct( ds->lightmapAxis, tri->plane ) < 0.25f )
+			return 0;
+	#endif
+	
+	/* planar surfaces will only merge with triangles in the same plane */
+	if( npDegrees == 0.0f && ds->shaderInfo->nonplanar == qfalse && ds->planeNum >= 0 )
+	{
+		if( VectorCompare( mapplanes[ ds->planeNum ].normal, tri->plane ) == qfalse || mapplanes[ ds->planeNum ].dist != tri->plane[ 3 ] )
+			return 0;
+		if( tri->planeNum >= 0 && tri->planeNum != ds->planeNum )
+			return 0;
+	}
+	
+	/* set initial score */
+	score = tri->surfaceNum == ds->surfaceNum ? SURFACE_SCORE : 0;
+	
+	/* score the the dot product of lightmap axis to plane */
+	if( (ds->shaderInfo->compileFlags & C_VERTEXLIT) || VectorCompare( ds->lightmapAxis, tri->lightmapAxis ) )
+		score += AXIS_SCORE;
+	else
+		score += AXIS_SCORE * DotProduct( ds->lightmapAxis, tri->plane );
+	
+	/* preserve old drawsurface if this fails */
+	memcpy( &old, ds, sizeof( *ds ) );
+	
+	/* attempt to add the verts */
+	coincident = 0;
+	ai = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 0 ] ], &coincident );
+	bi = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 1 ] ], &coincident );
+	ci = AddMetaVertToSurface( ds, &metaVerts[ tri->indexes[ 2 ] ], &coincident );
+	
+	/* check vertex underflow */
+	if( ai < 0 || bi < 0 || ci < 0 )
+	{
+		memcpy( ds, &old, sizeof( *ds ) );
+		return 0;
+	}
+	
+	/* score coincident vertex count (2003-02-14: changed so this only matters on planar surfaces) */
+	score += (coincident * VERT_SCORE);
+	
+	/* add new vertex bounds to mins/maxs */
+	VectorCopy( ds->mins, mins );
+	VectorCopy( ds->maxs, maxs );
+	AddPointToBounds( metaVerts[ tri->indexes[ 0 ] ].xyz, mins, maxs );
+	AddPointToBounds( metaVerts[ tri->indexes[ 1 ] ].xyz, mins, maxs );
+	AddPointToBounds( metaVerts[ tri->indexes[ 2 ] ].xyz, mins, maxs );
+	
+	/* check lightmap bounds overflow (after at least 1 triangle has been added) */
+	if( !(ds->shaderInfo->compileFlags & C_VERTEXLIT) &&
+		ds->numIndexes > 0 && VectorLength( ds->lightmapAxis ) > 0.0f &&
+		(VectorCompare( ds->mins, mins ) == qfalse || VectorCompare( ds->maxs, maxs ) == qfalse) )
+	{
+		/* set maximum size before lightmap scaling (normally 2032 units) */
+		lmMax = (ds->sampleSize * (ds->shaderInfo->lmCustomWidth - 1));
+		for( i = 0; i < 3; i++ )
+		{
+			if( (maxs[ i ] - mins[ i ]) > lmMax )
+			{
+				memcpy( ds, &old, sizeof( *ds ) );
+				return 0;
+			}
+		}
+	}
+	
+	/* check texture range overflow */
+	oldTexRange[ 0 ] = ds->texRange[ 0 ];
+	oldTexRange[ 1 ] = ds->texRange[ 1 ];
+	inTexRange = CalcSurfaceTextureRange( ds );
+	
+	es = (ds->texRange[ 0 ] > oldTexRange[ 0 ]) ? qtrue : qfalse;
+	et = (ds->texRange[ 1 ] > oldTexRange[ 1 ]) ? qtrue : qfalse;
+	
+	if( inTexRange == qfalse && ds->numIndexes > 0 )
+	{
+		memcpy( ds, &old, sizeof( *ds ) );
+		return UNSUITABLE_TRIANGLE;
+	}
+	
+	/* score texture range */
+	if( ds->texRange[ 0 ] <= oldTexRange[ 0 ] )
+		score += ST_SCORE2;
+	else if( ds->texRange[ 0 ] > oldTexRange[ 0 ] && oldTexRange[ 1 ] > oldTexRange[ 0 ] )
+		score += ST_SCORE;
+	
+	if( ds->texRange[ 1 ] <= oldTexRange[ 1 ] )
+		score += ST_SCORE2;
+	else if( ds->texRange[ 1 ] > oldTexRange[ 1 ] && oldTexRange[ 0 ] > oldTexRange[ 1 ] )
+		score += ST_SCORE;
+	
+	
+	/* go through the indexes and try to find an existing triangle that matches abc */
+	for( i = 0; i < ds->numIndexes; i += 3 )
+	{
+		/* 2002-03-11 (birthday!): rotate the triangle 3x to find an existing triangle */
+		if( (ai == ds->indexes[ i ] && bi == ds->indexes[ i + 1 ] && ci == ds->indexes[ i + 2 ]) ||
+			(bi == ds->indexes[ i ] && ci == ds->indexes[ i + 1 ] && ai == ds->indexes[ i + 2 ]) ||
+			(ci == ds->indexes[ i ] && ai == ds->indexes[ i + 1 ] && bi == ds->indexes[ i + 2 ]) )
+		{
+			/* triangle already present */
+			memcpy( ds, &old, sizeof( *ds ) );
+			tri->si = NULL;
+			return 0;
+		}
+		
+		/* rotate the triangle 3x to find an inverse triangle (error case) */
+		if( (ai == ds->indexes[ i ] && bi == ds->indexes[ i + 2 ] && ci == ds->indexes[ i + 1 ]) ||
+			(bi == ds->indexes[ i ] && ci == ds->indexes[ i + 2 ] && ai == ds->indexes[ i + 1 ]) ||
+			(ci == ds->indexes[ i ] && ai == ds->indexes[ i + 2 ] && bi == ds->indexes[ i + 1 ]) )
+		{
+			/* warn about it */
+			Sys_Printf( "WARNING: Flipped triangle: (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f) (%6.0f %6.0f %6.0f)\n",
+				ds->verts[ ai ].xyz[ 0 ], ds->verts[ ai ].xyz[ 1 ], ds->verts[ ai ].xyz[ 2 ],
+				ds->verts[ bi ].xyz[ 0 ], ds->verts[ bi ].xyz[ 1 ], ds->verts[ bi ].xyz[ 2 ],
+				ds->verts[ ci ].xyz[ 0 ], ds->verts[ ci ].xyz[ 1 ], ds->verts[ ci ].xyz[ 2 ] );
+			
+			/* reverse triangle already present */
+			memcpy( ds, &old, sizeof( *ds ) );
+			tri->si = NULL;
+			return 0;
+		}
+	}
+	
+	/* add the triangle indexes */
+	if( ds->numIndexes < maxSurfaceIndexes )
+		ds->indexes[ ds->numIndexes++ ] = ai;
+	if( ds->numIndexes < maxSurfaceIndexes )
+		ds->indexes[ ds->numIndexes++ ] = bi;
+	if( ds->numIndexes < maxSurfaceIndexes )
+		ds->indexes[ ds->numIndexes++ ] = ci;
+	
+	/* check index overflow */
+	if( ds->numIndexes >= maxSurfaceIndexes  )
+	{
+		memcpy( ds, &old, sizeof( *ds ) );
+		return 0;
+	}
+	
+	/* sanity check the indexes */
+	if( ds->numIndexes >= 3 &&
+		(ds->indexes[ ds->numIndexes - 3 ] == ds->indexes[ ds->numIndexes - 2 ] ||
+		ds->indexes[ ds->numIndexes - 3 ] == ds->indexes[ ds->numIndexes - 1 ] ||
+		ds->indexes[ ds->numIndexes - 2 ] == ds->indexes[ ds->numIndexes - 1 ]) )
+		Sys_Printf( "DEG:%d! ", ds->numVerts );
+	
+	/* testing only? */
+	if( testAdd )
+		memcpy( ds, &old, sizeof( *ds ) );
+	else
+	{
+		/* copy bounds back to surface */
+		VectorCopy( mins, ds->mins );
+		VectorCopy( maxs, ds->maxs );
+		
+		/* mark triangle as used */
+		tri->si = NULL;
+	}
+	
+	/* add a side reference */
+	ds->sideRef = AllocSideRef( tri->side, ds->sideRef );
+	
+	/* return to sender */
+	return score;
+}
+
+
+
+/*
+MetaTrianglesToSurface()
+creates map drawsurface(s) from the list of possibles
+*/
+
+static void MetaTrianglesToSurface( int numPossibles, metaTriangle_t *possibles, int *fOld, int *numAdded )
+{
+	int					i, j, f, best, score, bestScore;
+	metaTriangle_t		*seed, *test;
+	mapDrawSurface_t	*ds;
+	bspDrawVert_t		*verts;
+	int					*indexes;
+	qboolean			added;
+	
+	
+	/* allocate arrays */
+	verts = safe_malloc( sizeof( *verts ) * maxSurfaceVerts );
+	indexes = safe_malloc( sizeof( *indexes ) * maxSurfaceIndexes );
+	
+	/* walk the list of triangles */
+	for( i = 0, seed = possibles; i < numPossibles; i++, seed++ )
+	{
+		/* skip this triangle if it has already been merged */
+		if( seed->si == NULL )
+			continue;
+		
+		/* -----------------------------------------------------------------
+		   initial drawsurf construction
+		   ----------------------------------------------------------------- */
+		
+		/* start a new drawsurface */
+		ds = AllocDrawSurface( SURFACE_META );
+		ds->entityNum = seed->entityNum;
+		ds->surfaceNum = seed->surfaceNum;
+		ds->castShadows = seed->castShadows;
+		ds->recvShadows = seed->recvShadows;
+		
+		ds->shaderInfo = seed->si;
+		ds->planeNum = seed->planeNum;
+		ds->fogNum = seed->fogNum;
+		ds->sampleSize = seed->sampleSize;
+		ds->verts = verts;
+		ds->indexes = indexes;
+		VectorCopy( seed->lightmapAxis, ds->lightmapAxis );
+		ds->sideRef = AllocSideRef( seed->side, NULL );
+		
+		ClearBounds( ds->mins, ds->maxs );
+		
+		/* clear verts/indexes */
+		memset( verts, 0, sizeof( verts ) );
+		memset( indexes, 0, sizeof( indexes ) );
+		
+		/* add the first triangle */
+		if( AddMetaTriangleToSurface( ds, seed, qfalse ) )
+			(*numAdded)++;
+		
+		/* -----------------------------------------------------------------
+		   add triangles
+		   ----------------------------------------------------------------- */
+		
+		/* progressively walk the list until no more triangles can be added */
+		added = qtrue;
+		while( added )
+		{
+			/* print pacifier */
+			f = 10 * *numAdded / numMetaTriangles;
+			if( f > *fOld )
+			{
+				*fOld = f;
+				Sys_FPrintf( SYS_VRB, "%d...", f );
+			}
+			
+			/* reset best score */
+			best = -1;
+			bestScore = 0;
+			added = qfalse;
+			
+			/* walk the list of possible candidates for merging */
+			for( j = i + 1, test = &possibles[ j ]; j < numPossibles; j++, test++ )
+			{
+				/* score this triangle */
+				score = AddMetaTriangleToSurface( ds, test, qtrue );
+				if( score > bestScore )
+				{
+					best = j;
+					bestScore = score;
+					
+					/* if we have a score over a certain threshold, just use it */
+					if( bestScore >= GOOD_SCORE )
+					{
+						if( AddMetaTriangleToSurface( ds, &possibles[ best ], qfalse ) )
+							(*numAdded)++;
+						
+						/* reset */
+						best = -1;
+						bestScore = 0;
+						added = qtrue;
+					}
+				}
+			}
+			
+			/* add best candidate */
+			if( best >= 0 && bestScore > ADEQUATE_SCORE )
+			{
+				if( AddMetaTriangleToSurface( ds, &possibles[ best ], qfalse ) )
+					(*numAdded)++;
+				
+				/* reset */
+				added = qtrue;
+			}
+		}
+		
+		/* copy the verts and indexes to the new surface */
+		ds->verts = safe_malloc( ds->numVerts * sizeof( bspDrawVert_t ) );
+		memcpy( ds->verts, verts, ds->numVerts * sizeof( bspDrawVert_t ) );
+		ds->indexes = safe_malloc( ds->numIndexes * sizeof( int ) );
+		memcpy( ds->indexes, indexes, ds->numIndexes * sizeof( int ) );
+		
+		/* classify the surface */
+		ClassifySurfaces( 1, ds );
+		
+		/* add to count */
+		numMergedSurfaces++;
+	}
+	
+	/* free arrays */
+	free( verts );
+	free( indexes );
+}
+
+
+
+/*
+CompareMetaTriangles()
+compare function for qsort()
+*/
+
+static int CompareMetaTriangles( const void *a, const void *b )
+{
+	int		i, j, av, bv;
+	vec3_t	aMins, bMins;
+	
+	
+	/* shader first */
+	if( ((metaTriangle_t*) a)->si < ((metaTriangle_t*) b)->si )
+		return 1;
+	else if( ((metaTriangle_t*) a)->si > ((metaTriangle_t*) b)->si )
+		return -1;
+	
+	/* then fog */
+	else if( ((metaTriangle_t*) a)->fogNum < ((metaTriangle_t*) b)->fogNum )
+		return 1;
+	else if( ((metaTriangle_t*) a)->fogNum > ((metaTriangle_t*) b)->fogNum )
+		return -1;
+	
+	/* then position in world */
+	else
+	{
+		/* find mins */
+		VectorSet( aMins, 999999, 999999, 999999 );
+		VectorSet( bMins, 999999, 999999, 999999 );
+		for( i = 0; i < 3; i++ )
+		{
+			av = ((metaTriangle_t*) a)->indexes[ i ];
+			bv = ((metaTriangle_t*) b)->indexes[ i ];
+			for( j = 0; j < 3; j++ )
+			{
+				if( metaVerts[ av ].xyz[ j ] < aMins[ j ] )
+					aMins[ j ] = metaVerts[ av ].xyz[ j ];
+				if( metaVerts[ bv ].xyz[ j ] < bMins[ j ] )
+					bMins[ j ] = metaVerts[ bv ].xyz[ j ];
+			}
+		}
+		
+		/* test it */
+		for( i = 0; i < 3; i++ )
+		{
+			if( aMins[ i ] < bMins[ i ] )
+				return 1;
+			else if( aMins[ i ] > bMins[ i ] )
+				return -1;
+		}
+	}
+	
+	/* functionally equivalent */
+	return 0;
+}
+
+
+
+/*
+MergeMetaTriangles()
+merges meta triangles into drawsurfaces
+*/
+
+void MergeMetaTriangles( void )
+{
+	int					i, j, fOld, start, numAdded;
+	metaTriangle_t		*head, *end;
+	
+	
+	/* only do this if there are meta triangles */
+	if( numMetaTriangles <= 0 )
+		return;
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- MergeMetaTriangles ---\n" );
+	
+	/* sort the triangles by shader major, fognum minor */
+	qsort( metaTriangles, numMetaTriangles, sizeof( metaTriangle_t ), CompareMetaTriangles );
+
+	/* init pacifier */
+	fOld = -1;
+	start = I_FloatTime();
+	numAdded = 0;
+	
+	/* merge */
+	for( i = 0; i < numMetaTriangles; i = j )
+	{
+		/* get head of list */
+		head = &metaTriangles[ i ];
+		
+		/* find end */
+		for( j = i + 1; j < numMetaTriangles; j++ )
+		{
+			/* get end of list */
+			end = &metaTriangles[ j ];
+			if( head->si != end->si || head->fogNum != end->fogNum )
+				break;
+		}
+		
+		/* try to merge this list of possible merge candidates */
+		MetaTrianglesToSurface( (j - i), head, &fOld, &numAdded );
+	}
+	
+	/* clear meta triangle list */
+	ClearMetaTriangles();
+	
+	/* print time */
+	if( i )
+		Sys_FPrintf( SYS_VRB, " (%d)\n", (int) (I_FloatTime() - start) );
+	
+	/* emit some stats */
+	Sys_FPrintf( SYS_VRB, "%9d surfaces merged\n", numMergedSurfaces );
+	Sys_FPrintf( SYS_VRB, "%9d vertexes merged\n", numMergedVerts );
+}
diff --git a/tools/quake3/q3map2/tjunction.c b/tools/quake3/q3map2/tjunction.c
index b3004578..46390dd0 100644
--- a/tools/quake3/q3map2/tjunction.c
+++ b/tools/quake3/q3map2/tjunction.c
@@ -1,727 +1,727 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define TJUNCTION_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-typedef struct edgePoint_s {
-	float		intercept;
-	vec3_t		xyz;
-	struct edgePoint_s	*prev, *next;
-} edgePoint_t;
-
-typedef struct edgeLine_s {
-	vec3_t		normal1;
-	float		dist1;
-	
-	vec3_t		normal2;
-	float		dist2;
-	
-	vec3_t		origin;
-	vec3_t		dir;
-
-	edgePoint_t	chain;		// unused element of doubly linked list
-} edgeLine_t;
-
-typedef struct {
-	float		length;
-	bspDrawVert_t	*dv[2];
-} originalEdge_t;
-
-#define	MAX_ORIGINAL_EDGES	0x10000
-originalEdge_t	originalEdges[MAX_ORIGINAL_EDGES];
-int				numOriginalEdges;
-
-
-#define	MAX_EDGE_LINES		0x10000
-edgeLine_t		edgeLines[MAX_EDGE_LINES];
-int				numEdgeLines;
-
-int				c_degenerateEdges;
-int				c_addedVerts;
-int				c_totalVerts;
-
-int				c_natural, c_rotate, c_cant;
-
-// these should be whatever epsilon we actually expect,
-// plus SNAP_INT_TO_FLOAT 
-#define	LINE_POSITION_EPSILON	0.25
-#define	POINT_ON_LINE_EPSILON	0.25
-
-/*
-====================
-InsertPointOnEdge
-====================
-*/
-void InsertPointOnEdge( vec3_t v, edgeLine_t *e ) {
-	vec3_t		delta;
-	float		d;
-	edgePoint_t	*p, *scan;
-
-	VectorSubtract( v, e->origin, delta );
-	d = DotProduct( delta, e->dir );
-
-	p = safe_malloc( sizeof(edgePoint_t) );
-	p->intercept = d;
-	VectorCopy( v, p->xyz );
-
-	if ( e->chain.next == &e->chain ) {
-		e->chain.next = e->chain.prev = p;
-		p->next = p->prev = &e->chain;
-		return;
-	}
-
-	scan = e->chain.next;
-	for ( ; scan != &e->chain ; scan = scan->next ) {
-		d = p->intercept - scan->intercept;
-		if ( d > -LINE_POSITION_EPSILON && d < LINE_POSITION_EPSILON ) {
-			free( p );
-			return;		// the point is already set
-		}
-
-		if ( p->intercept < scan->intercept ) {
-			// insert here
-			p->prev = scan->prev;
-			p->next = scan;
-			scan->prev->next = p;
-			scan->prev = p;
-			return;
-		}
-	}
-
-	// add at the end
-	p->prev = scan->prev;
-	p->next = scan;
-	scan->prev->next = p;
-	scan->prev = p;
-}
-
-
-/*
-====================
-AddEdge
-====================
-*/
-int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) {
-	int			i;
-	edgeLine_t	*e;
-	float		d;
-	vec3_t		dir;
-
-	VectorSubtract( v2, v1, dir );
-	d = VectorNormalize( dir, dir );
-	if ( d < 0.1 ) {
-		// if we added a 0 length vector, it would make degenerate planes
-		c_degenerateEdges++;
-		return -1;
-	}
-
-	if ( !createNonAxial ) {
-		if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) {
-			if ( numOriginalEdges == MAX_ORIGINAL_EDGES ) {
-				Error( "MAX_ORIGINAL_EDGES" );
-			}
-			originalEdges[ numOriginalEdges ].dv[0] = (bspDrawVert_t *)v1;
-			originalEdges[ numOriginalEdges ].dv[1] = (bspDrawVert_t *)v2;
-			originalEdges[ numOriginalEdges ].length = d;
-			numOriginalEdges++;
-			return -1;
-		}
-	}
-
-	for ( i = 0 ; i < numEdgeLines ; i++ ) {
-		e = &edgeLines[i];
-
-		d = DotProduct( v1, e->normal1 ) - e->dist1;
-		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
-			continue;
-		}
-		d = DotProduct( v1, e->normal2 ) - e->dist2;
-		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
-			continue;
-		}
-
-		d = DotProduct( v2, e->normal1 ) - e->dist1;
-		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
-			continue;
-		}
-		d = DotProduct( v2, e->normal2 ) - e->dist2;
-		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
-			continue;
-		}
-
-		// this is the edge
-		InsertPointOnEdge( v1, e );
-		InsertPointOnEdge( v2, e );
-		return i;
-	}
-
-	// create a new edge
-	if ( numEdgeLines >= MAX_EDGE_LINES ) {
-		Error( "MAX_EDGE_LINES" );
-	}
-
-	e = &edgeLines[ numEdgeLines ];
-	numEdgeLines++;
-
-	e->chain.next = e->chain.prev = &e->chain;
-
-	VectorCopy( v1, e->origin );
-	VectorCopy( dir, e->dir );
-
-	MakeNormalVectors( e->dir, e->normal1, e->normal2 );
-	e->dist1 = DotProduct( e->origin, e->normal1 );
-	e->dist2 = DotProduct( e->origin, e->normal2 );
-
-	InsertPointOnEdge( v1, e );
-	InsertPointOnEdge( v2, e );
-
-	return numEdgeLines - 1;
-}
-
-
-
-/*
-AddSurfaceEdges()
-adds a surface's edges
-*/
-
-void AddSurfaceEdges( mapDrawSurface_t *ds )
-{
-	int		i;
-	
-
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		/* save the edge number in the lightmap field so we don't need to look it up again */
-		ds->verts[i].lightmap[ 0 ][ 0 ] = 
-			AddEdge( ds->verts[ i ].xyz, ds->verts[ (i + 1) % ds->numVerts ].xyz, qfalse );
-	}
-}
-
-
-
-/*
-ColinearEdge()
-determines if an edge is colinear
-*/
-
-qboolean ColinearEdge( vec3_t v1, vec3_t v2, vec3_t v3 )
-{
-	vec3_t	midpoint, dir, offset, on;
-	float	d;
-
-	VectorSubtract( v2, v1, midpoint );
-	VectorSubtract( v3, v1, dir );
-	d = VectorNormalize( dir, dir );
-	if ( d == 0 ) {
-		return qfalse;	// degenerate
-	}
-
-	d = DotProduct( midpoint, dir );
-	VectorScale( dir, d, on );
-	VectorSubtract( midpoint, on, offset );
-	d = VectorLength ( offset );
-
-	if ( d < 0.1 ) {
-		return qtrue;
-	}
-
-	return qfalse;
-}
-
-
-
-/*
-====================
-AddPatchEdges
-
-Add colinear border edges, which will fix some classes of patch to
-brush tjunctions
-====================
-*/
-void AddPatchEdges( mapDrawSurface_t *ds ) {
-	int		i;
-	float	*v1, *v2, *v3;
-
-	for ( i = 0 ; i < ds->patchWidth - 2; i+=2 ) {
-		v1 = ds->verts[ i ].xyz;
-		v2 = ds->verts[ i + 1 ].xyz;
-		v3 = ds->verts[ i + 2 ].xyz;
-
-		// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
-		if ( ColinearEdge( v1, v2, v3 ) ) {
-			AddEdge( v1, v3, qfalse );
-		}
-
-		v1 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i ].xyz;
-		v2 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 1 ].xyz;
-		v3 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 2 ].xyz;
-
-		// if v2 is on the v1 to v3 line, add an edge from v1 to v3
-		if ( ColinearEdge( v1, v2, v3 ) ) {
-			AddEdge( v1, v3, qfalse );
-		}
-	}
-
-	for ( i = 0 ; i < ds->patchHeight - 2 ; i+=2 ) {
-		v1 = ds->verts[ i * ds->patchWidth ].xyz;
-		v2 = ds->verts[ ( i + 1 ) * ds->patchWidth ].xyz;
-		v3 = ds->verts[ ( i + 2 ) * ds->patchWidth ].xyz;
-
-		// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
-		if ( ColinearEdge( v1, v2, v3 ) ) {
-			AddEdge( v1, v3, qfalse );
-		}
-
-		v1 = ds->verts[ ( ds->patchWidth - 1 ) + i * ds->patchWidth ].xyz;
-		v2 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 1 ) * ds->patchWidth ].xyz;
-		v3 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 2 ) * ds->patchWidth ].xyz;
-
-		// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
-		if ( ColinearEdge( v1, v2, v3 ) ) {
-			AddEdge( v1, v3, qfalse );
-		}
-	}
-
-
-}
-
-
-/*
-====================
-FixSurfaceJunctions
-====================
-*/
-#define	MAX_SURFACE_VERTS	256
-void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
-	int			i, j, k;
-	edgeLine_t	*e;
-	edgePoint_t	*p;
-	int			originalVerts;
-	int			counts[MAX_SURFACE_VERTS];
-	int			originals[MAX_SURFACE_VERTS];
-	int			firstVert[MAX_SURFACE_VERTS];
-	bspDrawVert_t	verts[MAX_SURFACE_VERTS], *v1, *v2;
-	int			numVerts;
-	float		start, end, frac, c;
-	vec3_t		delta;
-	
-	
-	originalVerts = ds->numVerts;
-	
-	numVerts = 0;
-	for ( i = 0 ; i < ds->numVerts ; i++ )
-	{
-		counts[i] = 0;
-		firstVert[i] = numVerts;
-
-		// copy first vert
-		if ( numVerts == MAX_SURFACE_VERTS ) {
-			Error( "MAX_SURFACE_VERTS" );
-		}
-		verts[numVerts] = ds->verts[i];
-		originals[numVerts] = i;
-		numVerts++;
-
-		// check to see if there are any t junctions before the next vert
-		v1 = &ds->verts[i];
-		v2 = &ds->verts[ (i+1) % ds->numVerts ];
-
-		j = (int)ds->verts[i].lightmap[ 0 ][ 0 ];
-		if ( j == -1 ) {
-			continue;		// degenerate edge
-		}
-		e = &edgeLines[ j ];
-		
-		VectorSubtract( v1->xyz, e->origin, delta );
-		start = DotProduct( delta, e->dir );
-
-		VectorSubtract( v2->xyz, e->origin, delta );
-		end = DotProduct( delta, e->dir );
-
-
-		if ( start < end ) {
-			p = e->chain.next;
-		} else {
-			p = e->chain.prev;
-		}
-
-		for (  ; p != &e->chain ;  ) {
-			if ( start < end ) {
-				if ( p->intercept > end - ON_EPSILON ) {
-					break;
-				}
-			} else {
-				if ( p->intercept < end + ON_EPSILON ) {
-					break;
-				}
-			}
-
-			if ( 
-				( start < end && p->intercept > start + ON_EPSILON ) ||
-				( start > end && p->intercept < start - ON_EPSILON ) ) {
-				// insert this point
-				if ( numVerts == MAX_SURFACE_VERTS ) {
-					Error( "MAX_SURFACE_VERTS" );
-				}
-				
-				/* take the exact intercept point */
-				VectorCopy( p->xyz, verts[ numVerts ].xyz );
-				
-				/* interpolate the texture coordinates */
-				frac = ( p->intercept - start ) / ( end - start );
-				for ( j = 0 ; j < 2 ; j++ ) {
-					verts[ numVerts ].st[j] = v1->st[j] + 
-						frac * ( v2->st[j] - v1->st[j] );
-				}
-				
-				/* copy the normal (FIXME: what about nonplanar surfaces? */
-				VectorCopy( v1->normal, verts[ numVerts ].normal );
-				
-				/* ydnar: interpolate the color */
-				for( k = 0; k < MAX_LIGHTMAPS; k++ )
-				{
-					for( j = 0; j < 4; j++ )
-					{
-						c = (float) v1->color[ k ][ j ] + frac * ((float) v2->color[ k ][ j ] - (float) v1->color[ k ][ j ]);
-						verts[ numVerts ].color[ k ][ j ] = (byte) (c < 255.0f ? c : 255);
-					}
-				}
-				
-				/* next... */
-				originals[ numVerts ] = i;
-				numVerts++;
-				counts[ i ]++;
-			}
-
-			if ( start < end ) {
-				p = p->next;
-			} else {
-				p = p->prev;
-			}
-		}
-	}
-
-	c_addedVerts += numVerts - ds->numVerts;
-	c_totalVerts += numVerts;
-
-
-	// FIXME: check to see if the entire surface degenerated
-	// after snapping
-
-	// rotate the points so that the initial vertex is between
-	// two non-subdivided edges
-	for ( i = 0 ; i < numVerts ; i++ ) {
-		if ( originals[ (i+1) % numVerts ] == originals[ i ] ) {
-			continue;
-		}
-		j = (i + numVerts - 1 ) % numVerts;
-		k = (i + numVerts - 2 ) % numVerts;
-		if ( originals[ j ] == originals[ k ] ) {
-			continue;
-		}
-		break;
-	}
-
-	if ( i == 0 ) {
-		// fine the way it is
-		c_natural++;
-
-		ds->numVerts = numVerts;
-		ds->verts = safe_malloc( numVerts * sizeof( *ds->verts ) );
-		memcpy( ds->verts, verts, numVerts * sizeof( *ds->verts ) );
-
-		return;
-	}
-	if ( i == numVerts ) {
-		// create a vertex in the middle to start the fan
-		c_cant++;
-
-/*
-		memset ( &verts[numVerts], 0, sizeof( verts[numVerts] ) );
-		for ( i = 0 ; i < numVerts ; i++ ) {
-			for ( j = 0 ; j < 10 ; j++ ) {
-				verts[numVerts].xyz[j] += verts[i].xyz[j];
-			}
-		}
-		for ( j = 0 ; j < 10 ; j++ ) {
-			verts[numVerts].xyz[j] /= numVerts;
-		}
-
-		i = numVerts;
-		numVerts++;
-*/
-	} else {
-		// just rotate the vertexes
-		c_rotate++;
-
-	}
-
-	ds->numVerts = numVerts;
-	ds->verts = safe_malloc( numVerts * sizeof( *ds->verts ) );
-
-	for ( j = 0 ; j < ds->numVerts ; j++ ) {
-		ds->verts[j] = verts[ ( j + i ) % ds->numVerts ];
-	}
-}
-
-
-
-
-
-/*
-FixBrokenSurface() - ydnar
-removes nearly coincident verts from a planar winding surface
-returns qfalse if the surface is broken
-*/
-
-extern void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out );
-
-#define DEGENERATE_EPSILON	0.1
-
-int		c_broken = 0;
-
-qboolean FixBrokenSurface( mapDrawSurface_t *ds )
-{
-	qboolean	valid = qtrue;
-	bspDrawVert_t	*dv1, *dv2, avg;
-	int			i, j, k;
-	float		dist;
-	
-	
-	/* dummy check */
-	if( ds == NULL )
-		return qfalse;
-	if( ds->type != SURFACE_FACE )
-		return qfalse;
-	
-	/* check all verts */
-	for( i = 0; i < ds->numVerts; i++ )
-	{
-		/* don't remove points if winding is a triangle */
-		if( ds->numVerts == 3 )
-			return valid;
-		
-		/* get verts */
-		dv1 = &ds->verts[ i ];
-		dv2 = &ds->verts[ (i + 1) % ds->numVerts ];
-		
-		/* degenerate edge? */
-		VectorSubtract( dv1->xyz, dv2->xyz, avg.xyz );
-		dist = VectorLength( avg.xyz );
-		if( dist < DEGENERATE_EPSILON )
-		{
-			valid = qfalse;
-			Sys_FPrintf( SYS_VRB, "WARNING: Degenerate T-junction edge found, fixing...\n" );
-
-			/* create an average drawvert */
-			/* ydnar 2002-01-26: added nearest-integer welding preference */
-			SnapWeldVector( dv1->xyz, dv2->xyz, avg.xyz );
-			VectorAdd( dv1->normal, dv2->normal, avg.normal );
-			VectorNormalize( avg.normal, avg.normal );
-			avg.st[ 0 ] = (dv1->st[ 0 ] + dv2->st[ 0 ]) * 0.5f;
-			avg.st[ 1 ] = (dv1->st[ 1 ] + dv2->st[ 1 ]) * 0.5f;
-			
-			/* lightmap st/colors */
-			for( k = 0; k < MAX_LIGHTMAPS; k++ )
-			{
-				avg.lightmap[ k ][ 0 ] = (dv1->lightmap[ k ][ 0 ] + dv2->lightmap[ k ][ 0 ]) * 0.5f;
-				avg.lightmap[ k ][ 1 ] = (dv1->lightmap[ k ][ 1 ] + dv2->lightmap[ k ][ 1 ]) * 0.5f;
-				for( j = 0; j < 4; j++ )
-					avg.color[ k ][ j ] = (int) (dv1->color[ k ][ j ] + dv2->color[ k ][ j ]) >> 1;
-			}
-			
-			/* ydnar: der... */
-			memcpy( dv1, &avg, sizeof( avg ) );
-			
-			/* move the remaining verts */
-			for( k = i + 2; k < ds->numVerts; k++ )
-			{
-				/* get verts */
-				dv1 = &ds->verts[ k ];
-				dv2 = &ds->verts[ k - 1 ];
-				
-				/* copy */
-				memcpy( dv2, dv1, sizeof( bspDrawVert_t ) );
-			}
-			ds->numVerts--;
-		}
-	}
-	
-	/* one last check and return */
-	if( ds->numVerts < 3 )
-		valid = qfalse;
-	return valid;
-}
-
-
-
-
-
-
-
-
-
-/*
-================
-EdgeCompare
-================
-*/
-int EdgeCompare( const void *elem1, const void *elem2 ) {
-	float	d1, d2;
-
-	d1 = ((originalEdge_t *)elem1)->length;
-	d2 = ((originalEdge_t *)elem2)->length;
-
-	if ( d1 < d2 ) {
-		return -1;
-	}
-	if ( d2 > d1 ) {
-		return 1;
-	}
-	return 0;
-}
-
-
-
-/*
-FixTJunctions
-call after the surface list has been pruned
-*/
-
-void FixTJunctions( entity_t *ent )
-{
-	int					i;
-	mapDrawSurface_t	*ds;
-	shaderInfo_t		*si;
-	int					axialEdgeLines;
-	originalEdge_t		*e;
-	
-	
-	/* meta mode has its own t-junction code (currently not as good as this code) */
-	//%	if( meta )
-	//%		return; 
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- FixTJunctions ---\n" );
-	numEdgeLines = 0;
-	numOriginalEdges = 0;
-	
-	// add all the edges
-	// this actually creates axial edges, but it
-	// only creates originalEdge_t structures
-	// for non-axial edges
-	for ( i = ent->firstDrawSurf ; i < numMapDrawSurfs ; i++ )
-	{
-		/* get surface and early out if possible */
-		ds = &mapDrawSurfs[ i ];
-		si = ds->shaderInfo;
-		if( (si->compileFlags & C_NODRAW) || si->autosprite || si->notjunc || ds->numVerts == 0 )
-			continue;
-		
-		/* ydnar: gs mods: handle the various types of surfaces */
-		switch( ds->type )
-		{
-			/* handle brush faces */
-			case SURFACE_FACE:
-				AddSurfaceEdges( ds );
-				break;
-			
-			/* handle patches */
-			case SURFACE_PATCH:
-				AddPatchEdges( ds );
-				break;
-			
-			/* fixme: make triangle surfaces t-junction */
-			default:
-				break;
-		}
-	}
-
-	axialEdgeLines = numEdgeLines;
-
-	// sort the non-axial edges by length
-	qsort( originalEdges, numOriginalEdges, sizeof(originalEdges[0]), EdgeCompare );
-
-	// add the non-axial edges, longest first
-	// this gives the most accurate edge description
-	for ( i = 0 ; i < numOriginalEdges ; i++ ) {
-		e = &originalEdges[i];
-		e->dv[ 0 ]->lightmap[ 0 ][ 0 ] = AddEdge( e->dv[ 0 ]->xyz, e->dv[ 1 ]->xyz, qtrue );
-	}
-
-	Sys_FPrintf( SYS_VRB, "%9d axial edge lines\n", axialEdgeLines );
-	Sys_FPrintf( SYS_VRB, "%9d non-axial edge lines\n", numEdgeLines - axialEdgeLines );
-	Sys_FPrintf( SYS_VRB, "%9d degenerate edges\n", c_degenerateEdges );
-
-	// insert any needed vertexes
-	for( i = ent->firstDrawSurf; i < numMapDrawSurfs ; i++ )
-	{
-		/* get surface and early out if possible */
-		ds = &mapDrawSurfs[ i ];
-		si = ds->shaderInfo;
-		if( (si->compileFlags & C_NODRAW) || si->autosprite || si->notjunc || ds->numVerts == 0 || ds->type != SURFACE_FACE )
-			continue;
-		
-		/* ydnar: gs mods: handle the various types of surfaces */
-		switch( ds->type )
-		{
-			/* handle brush faces */
-			case SURFACE_FACE:
-				FixSurfaceJunctions( ds );
-				if( FixBrokenSurface( ds ) == qfalse )
-				{
-					c_broken++;
-					ClearSurface( ds );
-				}
-				break;
-			
-			/* fixme: t-junction triangle models and patches */
-			default:
-				break;
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d verts added for T-junctions\n", c_addedVerts );
-	Sys_FPrintf( SYS_VRB, "%9d total verts\n", c_totalVerts );
-	Sys_FPrintf( SYS_VRB, "%9d naturally ordered\n", c_natural );
-	Sys_FPrintf( SYS_VRB, "%9d rotated orders\n", c_rotate );
-	Sys_FPrintf( SYS_VRB, "%9d can't order\n", c_cant );
-	Sys_FPrintf( SYS_VRB, "%9d broken (degenerate) surfaces removed\n", c_broken );
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define TJUNCTION_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+typedef struct edgePoint_s {
+	float		intercept;
+	vec3_t		xyz;
+	struct edgePoint_s	*prev, *next;
+} edgePoint_t;
+
+typedef struct edgeLine_s {
+	vec3_t		normal1;
+	float		dist1;
+	
+	vec3_t		normal2;
+	float		dist2;
+	
+	vec3_t		origin;
+	vec3_t		dir;
+
+	edgePoint_t	chain;		// unused element of doubly linked list
+} edgeLine_t;
+
+typedef struct {
+	float		length;
+	bspDrawVert_t	*dv[2];
+} originalEdge_t;
+
+#define	MAX_ORIGINAL_EDGES	0x10000
+originalEdge_t	originalEdges[MAX_ORIGINAL_EDGES];
+int				numOriginalEdges;
+
+
+#define	MAX_EDGE_LINES		0x10000
+edgeLine_t		edgeLines[MAX_EDGE_LINES];
+int				numEdgeLines;
+
+int				c_degenerateEdges;
+int				c_addedVerts;
+int				c_totalVerts;
+
+int				c_natural, c_rotate, c_cant;
+
+// these should be whatever epsilon we actually expect,
+// plus SNAP_INT_TO_FLOAT 
+#define	LINE_POSITION_EPSILON	0.25
+#define	POINT_ON_LINE_EPSILON	0.25
+
+/*
+====================
+InsertPointOnEdge
+====================
+*/
+void InsertPointOnEdge( vec3_t v, edgeLine_t *e ) {
+	vec3_t		delta;
+	float		d;
+	edgePoint_t	*p, *scan;
+
+	VectorSubtract( v, e->origin, delta );
+	d = DotProduct( delta, e->dir );
+
+	p = safe_malloc( sizeof(edgePoint_t) );
+	p->intercept = d;
+	VectorCopy( v, p->xyz );
+
+	if ( e->chain.next == &e->chain ) {
+		e->chain.next = e->chain.prev = p;
+		p->next = p->prev = &e->chain;
+		return;
+	}
+
+	scan = e->chain.next;
+	for ( ; scan != &e->chain ; scan = scan->next ) {
+		d = p->intercept - scan->intercept;
+		if ( d > -LINE_POSITION_EPSILON && d < LINE_POSITION_EPSILON ) {
+			free( p );
+			return;		// the point is already set
+		}
+
+		if ( p->intercept < scan->intercept ) {
+			// insert here
+			p->prev = scan->prev;
+			p->next = scan;
+			scan->prev->next = p;
+			scan->prev = p;
+			return;
+		}
+	}
+
+	// add at the end
+	p->prev = scan->prev;
+	p->next = scan;
+	scan->prev->next = p;
+	scan->prev = p;
+}
+
+
+/*
+====================
+AddEdge
+====================
+*/
+int AddEdge( vec3_t v1, vec3_t v2, qboolean createNonAxial ) {
+	int			i;
+	edgeLine_t	*e;
+	float		d;
+	vec3_t		dir;
+
+	VectorSubtract( v2, v1, dir );
+	d = VectorNormalize( dir, dir );
+	if ( d < 0.1 ) {
+		// if we added a 0 length vector, it would make degenerate planes
+		c_degenerateEdges++;
+		return -1;
+	}
+
+	if ( !createNonAxial ) {
+		if ( fabs( dir[0] + dir[1] + dir[2] ) != 1.0 ) {
+			if ( numOriginalEdges == MAX_ORIGINAL_EDGES ) {
+				Error( "MAX_ORIGINAL_EDGES" );
+			}
+			originalEdges[ numOriginalEdges ].dv[0] = (bspDrawVert_t *)v1;
+			originalEdges[ numOriginalEdges ].dv[1] = (bspDrawVert_t *)v2;
+			originalEdges[ numOriginalEdges ].length = d;
+			numOriginalEdges++;
+			return -1;
+		}
+	}
+
+	for ( i = 0 ; i < numEdgeLines ; i++ ) {
+		e = &edgeLines[i];
+
+		d = DotProduct( v1, e->normal1 ) - e->dist1;
+		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
+			continue;
+		}
+		d = DotProduct( v1, e->normal2 ) - e->dist2;
+		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
+			continue;
+		}
+
+		d = DotProduct( v2, e->normal1 ) - e->dist1;
+		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
+			continue;
+		}
+		d = DotProduct( v2, e->normal2 ) - e->dist2;
+		if ( d < -POINT_ON_LINE_EPSILON || d > POINT_ON_LINE_EPSILON ) {
+			continue;
+		}
+
+		// this is the edge
+		InsertPointOnEdge( v1, e );
+		InsertPointOnEdge( v2, e );
+		return i;
+	}
+
+	// create a new edge
+	if ( numEdgeLines >= MAX_EDGE_LINES ) {
+		Error( "MAX_EDGE_LINES" );
+	}
+
+	e = &edgeLines[ numEdgeLines ];
+	numEdgeLines++;
+
+	e->chain.next = e->chain.prev = &e->chain;
+
+	VectorCopy( v1, e->origin );
+	VectorCopy( dir, e->dir );
+
+	MakeNormalVectors( e->dir, e->normal1, e->normal2 );
+	e->dist1 = DotProduct( e->origin, e->normal1 );
+	e->dist2 = DotProduct( e->origin, e->normal2 );
+
+	InsertPointOnEdge( v1, e );
+	InsertPointOnEdge( v2, e );
+
+	return numEdgeLines - 1;
+}
+
+
+
+/*
+AddSurfaceEdges()
+adds a surface's edges
+*/
+
+void AddSurfaceEdges( mapDrawSurface_t *ds )
+{
+	int		i;
+	
+
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		/* save the edge number in the lightmap field so we don't need to look it up again */
+		ds->verts[i].lightmap[ 0 ][ 0 ] = 
+			AddEdge( ds->verts[ i ].xyz, ds->verts[ (i + 1) % ds->numVerts ].xyz, qfalse );
+	}
+}
+
+
+
+/*
+ColinearEdge()
+determines if an edge is colinear
+*/
+
+qboolean ColinearEdge( vec3_t v1, vec3_t v2, vec3_t v3 )
+{
+	vec3_t	midpoint, dir, offset, on;
+	float	d;
+
+	VectorSubtract( v2, v1, midpoint );
+	VectorSubtract( v3, v1, dir );
+	d = VectorNormalize( dir, dir );
+	if ( d == 0 ) {
+		return qfalse;	// degenerate
+	}
+
+	d = DotProduct( midpoint, dir );
+	VectorScale( dir, d, on );
+	VectorSubtract( midpoint, on, offset );
+	d = VectorLength ( offset );
+
+	if ( d < 0.1 ) {
+		return qtrue;
+	}
+
+	return qfalse;
+}
+
+
+
+/*
+====================
+AddPatchEdges
+
+Add colinear border edges, which will fix some classes of patch to
+brush tjunctions
+====================
+*/
+void AddPatchEdges( mapDrawSurface_t *ds ) {
+	int		i;
+	float	*v1, *v2, *v3;
+
+	for ( i = 0 ; i < ds->patchWidth - 2; i+=2 ) {
+		v1 = ds->verts[ i ].xyz;
+		v2 = ds->verts[ i + 1 ].xyz;
+		v3 = ds->verts[ i + 2 ].xyz;
+
+		// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
+		if ( ColinearEdge( v1, v2, v3 ) ) {
+			AddEdge( v1, v3, qfalse );
+		}
+
+		v1 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i ].xyz;
+		v2 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 1 ].xyz;
+		v3 = ds->verts[ ( ds->patchHeight - 1 ) * ds->patchWidth + i + 2 ].xyz;
+
+		// if v2 is on the v1 to v3 line, add an edge from v1 to v3
+		if ( ColinearEdge( v1, v2, v3 ) ) {
+			AddEdge( v1, v3, qfalse );
+		}
+	}
+
+	for ( i = 0 ; i < ds->patchHeight - 2 ; i+=2 ) {
+		v1 = ds->verts[ i * ds->patchWidth ].xyz;
+		v2 = ds->verts[ ( i + 1 ) * ds->patchWidth ].xyz;
+		v3 = ds->verts[ ( i + 2 ) * ds->patchWidth ].xyz;
+
+		// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
+		if ( ColinearEdge( v1, v2, v3 ) ) {
+			AddEdge( v1, v3, qfalse );
+		}
+
+		v1 = ds->verts[ ( ds->patchWidth - 1 ) + i * ds->patchWidth ].xyz;
+		v2 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 1 ) * ds->patchWidth ].xyz;
+		v3 = ds->verts[ ( ds->patchWidth - 1 ) + ( i + 2 ) * ds->patchWidth ].xyz;
+
+		// if v2 is the midpoint of v1 to v3, add an edge from v1 to v3
+		if ( ColinearEdge( v1, v2, v3 ) ) {
+			AddEdge( v1, v3, qfalse );
+		}
+	}
+
+
+}
+
+
+/*
+====================
+FixSurfaceJunctions
+====================
+*/
+#define	MAX_SURFACE_VERTS	256
+void FixSurfaceJunctions( mapDrawSurface_t *ds ) {
+	int			i, j, k;
+	edgeLine_t	*e;
+	edgePoint_t	*p;
+	int			originalVerts;
+	int			counts[MAX_SURFACE_VERTS];
+	int			originals[MAX_SURFACE_VERTS];
+	int			firstVert[MAX_SURFACE_VERTS];
+	bspDrawVert_t	verts[MAX_SURFACE_VERTS], *v1, *v2;
+	int			numVerts;
+	float		start, end, frac, c;
+	vec3_t		delta;
+	
+	
+	originalVerts = ds->numVerts;
+	
+	numVerts = 0;
+	for ( i = 0 ; i < ds->numVerts ; i++ )
+	{
+		counts[i] = 0;
+		firstVert[i] = numVerts;
+
+		// copy first vert
+		if ( numVerts == MAX_SURFACE_VERTS ) {
+			Error( "MAX_SURFACE_VERTS" );
+		}
+		verts[numVerts] = ds->verts[i];
+		originals[numVerts] = i;
+		numVerts++;
+
+		// check to see if there are any t junctions before the next vert
+		v1 = &ds->verts[i];
+		v2 = &ds->verts[ (i+1) % ds->numVerts ];
+
+		j = (int)ds->verts[i].lightmap[ 0 ][ 0 ];
+		if ( j == -1 ) {
+			continue;		// degenerate edge
+		}
+		e = &edgeLines[ j ];
+		
+		VectorSubtract( v1->xyz, e->origin, delta );
+		start = DotProduct( delta, e->dir );
+
+		VectorSubtract( v2->xyz, e->origin, delta );
+		end = DotProduct( delta, e->dir );
+
+
+		if ( start < end ) {
+			p = e->chain.next;
+		} else {
+			p = e->chain.prev;
+		}
+
+		for (  ; p != &e->chain ;  ) {
+			if ( start < end ) {
+				if ( p->intercept > end - ON_EPSILON ) {
+					break;
+				}
+			} else {
+				if ( p->intercept < end + ON_EPSILON ) {
+					break;
+				}
+			}
+
+			if ( 
+				( start < end && p->intercept > start + ON_EPSILON ) ||
+				( start > end && p->intercept < start - ON_EPSILON ) ) {
+				// insert this point
+				if ( numVerts == MAX_SURFACE_VERTS ) {
+					Error( "MAX_SURFACE_VERTS" );
+				}
+				
+				/* take the exact intercept point */
+				VectorCopy( p->xyz, verts[ numVerts ].xyz );
+				
+				/* interpolate the texture coordinates */
+				frac = ( p->intercept - start ) / ( end - start );
+				for ( j = 0 ; j < 2 ; j++ ) {
+					verts[ numVerts ].st[j] = v1->st[j] + 
+						frac * ( v2->st[j] - v1->st[j] );
+				}
+				
+				/* copy the normal (FIXME: what about nonplanar surfaces? */
+				VectorCopy( v1->normal, verts[ numVerts ].normal );
+				
+				/* ydnar: interpolate the color */
+				for( k = 0; k < MAX_LIGHTMAPS; k++ )
+				{
+					for( j = 0; j < 4; j++ )
+					{
+						c = (float) v1->color[ k ][ j ] + frac * ((float) v2->color[ k ][ j ] - (float) v1->color[ k ][ j ]);
+						verts[ numVerts ].color[ k ][ j ] = (byte) (c < 255.0f ? c : 255);
+					}
+				}
+				
+				/* next... */
+				originals[ numVerts ] = i;
+				numVerts++;
+				counts[ i ]++;
+			}
+
+			if ( start < end ) {
+				p = p->next;
+			} else {
+				p = p->prev;
+			}
+		}
+	}
+
+	c_addedVerts += numVerts - ds->numVerts;
+	c_totalVerts += numVerts;
+
+
+	// FIXME: check to see if the entire surface degenerated
+	// after snapping
+
+	// rotate the points so that the initial vertex is between
+	// two non-subdivided edges
+	for ( i = 0 ; i < numVerts ; i++ ) {
+		if ( originals[ (i+1) % numVerts ] == originals[ i ] ) {
+			continue;
+		}
+		j = (i + numVerts - 1 ) % numVerts;
+		k = (i + numVerts - 2 ) % numVerts;
+		if ( originals[ j ] == originals[ k ] ) {
+			continue;
+		}
+		break;
+	}
+
+	if ( i == 0 ) {
+		// fine the way it is
+		c_natural++;
+
+		ds->numVerts = numVerts;
+		ds->verts = safe_malloc( numVerts * sizeof( *ds->verts ) );
+		memcpy( ds->verts, verts, numVerts * sizeof( *ds->verts ) );
+
+		return;
+	}
+	if ( i == numVerts ) {
+		// create a vertex in the middle to start the fan
+		c_cant++;
+
+/*
+		memset ( &verts[numVerts], 0, sizeof( verts[numVerts] ) );
+		for ( i = 0 ; i < numVerts ; i++ ) {
+			for ( j = 0 ; j < 10 ; j++ ) {
+				verts[numVerts].xyz[j] += verts[i].xyz[j];
+			}
+		}
+		for ( j = 0 ; j < 10 ; j++ ) {
+			verts[numVerts].xyz[j] /= numVerts;
+		}
+
+		i = numVerts;
+		numVerts++;
+*/
+	} else {
+		// just rotate the vertexes
+		c_rotate++;
+
+	}
+
+	ds->numVerts = numVerts;
+	ds->verts = safe_malloc( numVerts * sizeof( *ds->verts ) );
+
+	for ( j = 0 ; j < ds->numVerts ; j++ ) {
+		ds->verts[j] = verts[ ( j + i ) % ds->numVerts ];
+	}
+}
+
+
+
+
+
+/*
+FixBrokenSurface() - ydnar
+removes nearly coincident verts from a planar winding surface
+returns qfalse if the surface is broken
+*/
+
+extern void SnapWeldVector( vec3_t a, vec3_t b, vec3_t out );
+
+#define DEGENERATE_EPSILON	0.1
+
+int		c_broken = 0;
+
+qboolean FixBrokenSurface( mapDrawSurface_t *ds )
+{
+	qboolean	valid = qtrue;
+	bspDrawVert_t	*dv1, *dv2, avg;
+	int			i, j, k;
+	float		dist;
+	
+	
+	/* dummy check */
+	if( ds == NULL )
+		return qfalse;
+	if( ds->type != SURFACE_FACE )
+		return qfalse;
+	
+	/* check all verts */
+	for( i = 0; i < ds->numVerts; i++ )
+	{
+		/* don't remove points if winding is a triangle */
+		if( ds->numVerts == 3 )
+			return valid;
+		
+		/* get verts */
+		dv1 = &ds->verts[ i ];
+		dv2 = &ds->verts[ (i + 1) % ds->numVerts ];
+		
+		/* degenerate edge? */
+		VectorSubtract( dv1->xyz, dv2->xyz, avg.xyz );
+		dist = VectorLength( avg.xyz );
+		if( dist < DEGENERATE_EPSILON )
+		{
+			valid = qfalse;
+			Sys_FPrintf( SYS_VRB, "WARNING: Degenerate T-junction edge found, fixing...\n" );
+
+			/* create an average drawvert */
+			/* ydnar 2002-01-26: added nearest-integer welding preference */
+			SnapWeldVector( dv1->xyz, dv2->xyz, avg.xyz );
+			VectorAdd( dv1->normal, dv2->normal, avg.normal );
+			VectorNormalize( avg.normal, avg.normal );
+			avg.st[ 0 ] = (dv1->st[ 0 ] + dv2->st[ 0 ]) * 0.5f;
+			avg.st[ 1 ] = (dv1->st[ 1 ] + dv2->st[ 1 ]) * 0.5f;
+			
+			/* lightmap st/colors */
+			for( k = 0; k < MAX_LIGHTMAPS; k++ )
+			{
+				avg.lightmap[ k ][ 0 ] = (dv1->lightmap[ k ][ 0 ] + dv2->lightmap[ k ][ 0 ]) * 0.5f;
+				avg.lightmap[ k ][ 1 ] = (dv1->lightmap[ k ][ 1 ] + dv2->lightmap[ k ][ 1 ]) * 0.5f;
+				for( j = 0; j < 4; j++ )
+					avg.color[ k ][ j ] = (int) (dv1->color[ k ][ j ] + dv2->color[ k ][ j ]) >> 1;
+			}
+			
+			/* ydnar: der... */
+			memcpy( dv1, &avg, sizeof( avg ) );
+			
+			/* move the remaining verts */
+			for( k = i + 2; k < ds->numVerts; k++ )
+			{
+				/* get verts */
+				dv1 = &ds->verts[ k ];
+				dv2 = &ds->verts[ k - 1 ];
+				
+				/* copy */
+				memcpy( dv2, dv1, sizeof( bspDrawVert_t ) );
+			}
+			ds->numVerts--;
+		}
+	}
+	
+	/* one last check and return */
+	if( ds->numVerts < 3 )
+		valid = qfalse;
+	return valid;
+}
+
+
+
+
+
+
+
+
+
+/*
+================
+EdgeCompare
+================
+*/
+int EdgeCompare( const void *elem1, const void *elem2 ) {
+	float	d1, d2;
+
+	d1 = ((originalEdge_t *)elem1)->length;
+	d2 = ((originalEdge_t *)elem2)->length;
+
+	if ( d1 < d2 ) {
+		return -1;
+	}
+	if ( d2 > d1 ) {
+		return 1;
+	}
+	return 0;
+}
+
+
+
+/*
+FixTJunctions
+call after the surface list has been pruned
+*/
+
+void FixTJunctions( entity_t *ent )
+{
+	int					i;
+	mapDrawSurface_t	*ds;
+	shaderInfo_t		*si;
+	int					axialEdgeLines;
+	originalEdge_t		*e;
+	
+	
+	/* meta mode has its own t-junction code (currently not as good as this code) */
+	//%	if( meta )
+	//%		return; 
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- FixTJunctions ---\n" );
+	numEdgeLines = 0;
+	numOriginalEdges = 0;
+	
+	// add all the edges
+	// this actually creates axial edges, but it
+	// only creates originalEdge_t structures
+	// for non-axial edges
+	for ( i = ent->firstDrawSurf ; i < numMapDrawSurfs ; i++ )
+	{
+		/* get surface and early out if possible */
+		ds = &mapDrawSurfs[ i ];
+		si = ds->shaderInfo;
+		if( (si->compileFlags & C_NODRAW) || si->autosprite || si->notjunc || ds->numVerts == 0 )
+			continue;
+		
+		/* ydnar: gs mods: handle the various types of surfaces */
+		switch( ds->type )
+		{
+			/* handle brush faces */
+			case SURFACE_FACE:
+				AddSurfaceEdges( ds );
+				break;
+			
+			/* handle patches */
+			case SURFACE_PATCH:
+				AddPatchEdges( ds );
+				break;
+			
+			/* fixme: make triangle surfaces t-junction */
+			default:
+				break;
+		}
+	}
+
+	axialEdgeLines = numEdgeLines;
+
+	// sort the non-axial edges by length
+	qsort( originalEdges, numOriginalEdges, sizeof(originalEdges[0]), EdgeCompare );
+
+	// add the non-axial edges, longest first
+	// this gives the most accurate edge description
+	for ( i = 0 ; i < numOriginalEdges ; i++ ) {
+		e = &originalEdges[i];
+		e->dv[ 0 ]->lightmap[ 0 ][ 0 ] = AddEdge( e->dv[ 0 ]->xyz, e->dv[ 1 ]->xyz, qtrue );
+	}
+
+	Sys_FPrintf( SYS_VRB, "%9d axial edge lines\n", axialEdgeLines );
+	Sys_FPrintf( SYS_VRB, "%9d non-axial edge lines\n", numEdgeLines - axialEdgeLines );
+	Sys_FPrintf( SYS_VRB, "%9d degenerate edges\n", c_degenerateEdges );
+
+	// insert any needed vertexes
+	for( i = ent->firstDrawSurf; i < numMapDrawSurfs ; i++ )
+	{
+		/* get surface and early out if possible */
+		ds = &mapDrawSurfs[ i ];
+		si = ds->shaderInfo;
+		if( (si->compileFlags & C_NODRAW) || si->autosprite || si->notjunc || ds->numVerts == 0 || ds->type != SURFACE_FACE )
+			continue;
+		
+		/* ydnar: gs mods: handle the various types of surfaces */
+		switch( ds->type )
+		{
+			/* handle brush faces */
+			case SURFACE_FACE:
+				FixSurfaceJunctions( ds );
+				if( FixBrokenSurface( ds ) == qfalse )
+				{
+					c_broken++;
+					ClearSurface( ds );
+				}
+				break;
+			
+			/* fixme: t-junction triangle models and patches */
+			default:
+				break;
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d verts added for T-junctions\n", c_addedVerts );
+	Sys_FPrintf( SYS_VRB, "%9d total verts\n", c_totalVerts );
+	Sys_FPrintf( SYS_VRB, "%9d naturally ordered\n", c_natural );
+	Sys_FPrintf( SYS_VRB, "%9d rotated orders\n", c_rotate );
+	Sys_FPrintf( SYS_VRB, "%9d can't order\n", c_cant );
+	Sys_FPrintf( SYS_VRB, "%9d broken (degenerate) surfaces removed\n", c_broken );
+}
diff --git a/tools/quake3/q3map2/tree.c b/tools/quake3/q3map2/tree.c
index 022af498..6ed8c49f 100644
--- a/tools/quake3/q3map2/tree.c
+++ b/tools/quake3/q3map2/tree.c
@@ -1,158 +1,158 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define TREE_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-void RemovePortalFromNode (portal_t *portal, node_t *l);
-
-node_t *NodeForPoint (node_t *node, vec3_t origin)
-{
-	plane_t	*plane;
-	vec_t	d;
-
-	while (node->planenum != PLANENUM_LEAF)
-	{
-		plane = &mapplanes[node->planenum];
-		d = DotProduct (origin, plane->normal) - plane->dist;
-		if (d >= 0)
-			node = node->children[0];
-		else
-			node = node->children[1];
-	}
-
-	return node;
-}
-
-
-
-/*
-=============
-FreeTreePortals_r
-=============
-*/
-void FreeTreePortals_r (node_t *node)
-{
-	portal_t	*p, *nextp;
-	int			s;
-
-	// free children
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		FreeTreePortals_r (node->children[0]);
-		FreeTreePortals_r (node->children[1]);
-	}
-
-	// free portals
-	for (p=node->portals ; p ; p=nextp)
-	{
-		s = (p->nodes[1] == node);
-		nextp = p->next[s];
-
-		RemovePortalFromNode (p, p->nodes[!s]);
-		FreePortal (p);
-	}
-	node->portals = NULL;
-}
-
-/*
-=============
-FreeTree_r
-=============
-*/
-void FreeTree_r (node_t *node)
-{
-	// free children
-	if (node->planenum != PLANENUM_LEAF)
-	{
-		FreeTree_r (node->children[0]);
-		FreeTree_r (node->children[1]);
-	}
-
-	// free bspbrushes
-	FreeBrushList (node->brushlist);
-
-	// free the node
-	if (node->volume)
-		FreeBrush (node->volume);
-
-	free (node);
-}
-
-
-/*
-=============
-FreeTree
-=============
-*/
-void FreeTree (tree_t *tree)
-{
-	FreeTreePortals_r (tree->headnode);
-	FreeTree_r (tree->headnode);
-	free (tree);
-}
-
-//===============================================================
-
-void PrintTree_r (node_t *node, int depth)
-{
-	int		i;
-	plane_t	*plane;
-	brush_t	*bb;
-
-	for (i=0 ; i<depth ; i++)
-		Sys_Printf ("  ");
-	if (node->planenum == PLANENUM_LEAF)
-	{
-		if (!node->brushlist)
-			Sys_Printf ("NULL\n");
-		else
-		{
-			for (bb=node->brushlist ; bb ; bb=bb->next)
-				Sys_Printf ("%d ", bb->original->brushNum);
-			Sys_Printf ("\n");
-		}
-		return;
-	}
-
-	plane = &mapplanes[node->planenum];
-	Sys_Printf ("#%d (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum,
-		plane->normal[0], plane->normal[1], plane->normal[2],
-		plane->dist);
-	PrintTree_r (node->children[0], depth+1);
-	PrintTree_r (node->children[1], depth+1);
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define TREE_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+void RemovePortalFromNode (portal_t *portal, node_t *l);
+
+node_t *NodeForPoint (node_t *node, vec3_t origin)
+{
+	plane_t	*plane;
+	vec_t	d;
+
+	while (node->planenum != PLANENUM_LEAF)
+	{
+		plane = &mapplanes[node->planenum];
+		d = DotProduct (origin, plane->normal) - plane->dist;
+		if (d >= 0)
+			node = node->children[0];
+		else
+			node = node->children[1];
+	}
+
+	return node;
+}
+
+
+
+/*
+=============
+FreeTreePortals_r
+=============
+*/
+void FreeTreePortals_r (node_t *node)
+{
+	portal_t	*p, *nextp;
+	int			s;
+
+	// free children
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		FreeTreePortals_r (node->children[0]);
+		FreeTreePortals_r (node->children[1]);
+	}
+
+	// free portals
+	for (p=node->portals ; p ; p=nextp)
+	{
+		s = (p->nodes[1] == node);
+		nextp = p->next[s];
+
+		RemovePortalFromNode (p, p->nodes[!s]);
+		FreePortal (p);
+	}
+	node->portals = NULL;
+}
+
+/*
+=============
+FreeTree_r
+=============
+*/
+void FreeTree_r (node_t *node)
+{
+	// free children
+	if (node->planenum != PLANENUM_LEAF)
+	{
+		FreeTree_r (node->children[0]);
+		FreeTree_r (node->children[1]);
+	}
+
+	// free bspbrushes
+	FreeBrushList (node->brushlist);
+
+	// free the node
+	if (node->volume)
+		FreeBrush (node->volume);
+
+	free (node);
+}
+
+
+/*
+=============
+FreeTree
+=============
+*/
+void FreeTree (tree_t *tree)
+{
+	FreeTreePortals_r (tree->headnode);
+	FreeTree_r (tree->headnode);
+	free (tree);
+}
+
+//===============================================================
+
+void PrintTree_r (node_t *node, int depth)
+{
+	int		i;
+	plane_t	*plane;
+	brush_t	*bb;
+
+	for (i=0 ; i<depth ; i++)
+		Sys_Printf ("  ");
+	if (node->planenum == PLANENUM_LEAF)
+	{
+		if (!node->brushlist)
+			Sys_Printf ("NULL\n");
+		else
+		{
+			for (bb=node->brushlist ; bb ; bb=bb->next)
+				Sys_Printf ("%d ", bb->original->brushNum);
+			Sys_Printf ("\n");
+		}
+		return;
+	}
+
+	plane = &mapplanes[node->planenum];
+	Sys_Printf ("#%d (%5.2f %5.2f %5.2f):%5.2f\n", node->planenum,
+		plane->normal[0], plane->normal[1], plane->normal[2],
+		plane->dist);
+	PrintTree_r (node->children[0], depth+1);
+	PrintTree_r (node->children[1], depth+1);
+}
diff --git a/tools/quake3/q3map2/vis.c b/tools/quake3/q3map2/vis.c
index f3b2f4ae..464b23ec 100644
--- a/tools/quake3/q3map2/vis.c
+++ b/tools/quake3/q3map2/vis.c
@@ -1,1122 +1,1122 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define VIS_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-void PlaneFromWinding (fixedWinding_t *w, visPlane_t *plane)
-{
-	vec3_t		v1, v2;
-
-// calc plane
-	VectorSubtract (w->points[2], w->points[1], v1);
-	VectorSubtract (w->points[0], w->points[1], v2);
-	CrossProduct (v2, v1, plane->normal);
-	VectorNormalize (plane->normal, plane->normal);
-	plane->dist = DotProduct (w->points[0], plane->normal);
-}
-
-
-/*
-NewFixedWinding()
-returns a new fixed winding
-ydnar: altered this a bit to reconcile multiply-defined winding_t
-*/
-
-fixedWinding_t *NewFixedWinding( int points )
-{
-	fixedWinding_t	*w;
-	int			size;
-	
-	if (points > MAX_POINTS_ON_WINDING)
-		Error ("NewWinding: %i points", points);
-	
-	size = (int)((fixedWinding_t *)0)->points[points];
-	w = safe_malloc (size);
-	memset (w, 0, size);
-	
-	return w;
-}
-
-
-
-void prl(leaf_t *l)
-{
-	int			i;
-	vportal_t	*p;
-	visPlane_t	pl;
-	
-	for (i=0 ; i<l->numportals ; i++)
-	{
-		p = l->portals[i];
-		pl = p->plane;
-		Sys_Printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
-	}
-}
-
-
-//=============================================================================
-
-/*
-=============
-SortPortals
-
-Sorts the portals from the least complex, so the later ones can reuse
-the earlier information.
-=============
-*/
-int PComp (const void *a, const void *b)
-{
-	if ( (*(vportal_t **)a)->nummightsee == (*(vportal_t **)b)->nummightsee)
-		return 0;
-	if ( (*(vportal_t **)a)->nummightsee < (*(vportal_t **)b)->nummightsee)
-		return -1;
-	return 1;
-}
-void SortPortals (void)
-{
-	int		i;
-	
-	for (i=0 ; i<numportals*2 ; i++)
-		sorted_portals[i] = &portals[i];
-
-	if (nosort)
-		return;
-	qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
-}
-
-
-/*
-==============
-LeafVectorFromPortalVector
-==============
-*/
-int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
-{
-	int			i, j, leafnum;
-	vportal_t	*p;
-	int			c_leafs;
-
-
-	for (i=0 ; i<numportals*2 ; i++)
-	{
-		if (portalbits[i>>3] & (1<<(i&7)) )
-		{
-			p = portals+i;
-			leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
-		}
-	}
-
-	for (j = 0; j < portalclusters; j++)
-	{
-		leafnum = j;
-		while (leafs[leafnum].merged >= 0)
-			leafnum = leafs[leafnum].merged;
-		//if the merged leaf is visible then the original leaf is visible
-		if (leafbits[leafnum>>3] & (1<<(leafnum&7)))
-		{
-			leafbits[j>>3] |= (1<<(j&7));
-		}
-	}
-
-	c_leafs = CountBits (leafbits, portalclusters);
-
-	return c_leafs;
-}
-
-
-/*
-===============
-ClusterMerge
-
-Merges the portal visibility for a leaf
-===============
-*/
-void ClusterMerge (int leafnum)
-{
-	leaf_t		*leaf;
-	byte		portalvector[MAX_PORTALS/8];
-	byte		uncompressed[MAX_MAP_LEAFS/8];
-	int			i, j;
-	int			numvis, mergedleafnum;
-	vportal_t	*p;
-	int			pnum;
-
-	// OR together all the portalvis bits
-
-	mergedleafnum = leafnum;
-	while(leafs[mergedleafnum].merged >= 0)
-		mergedleafnum = leafs[mergedleafnum].merged;
-
-	memset (portalvector, 0, portalbytes);
-	leaf = &leafs[mergedleafnum];
-	for (i = 0; i < leaf->numportals; i++)
-	{
-		p = leaf->portals[i];
-		if (p->removed)
-			continue;
-
-		if (p->status != stat_done)
-			Error ("portal not done");
-		for (j=0 ; j<portallongs ; j++)
-			((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
-		pnum = p - portals;
-		portalvector[pnum>>3] |= 1<<(pnum&7);
-	}
-
-	memset (uncompressed, 0, leafbytes);
-
-	uncompressed[mergedleafnum>>3] |= (1<<(mergedleafnum&7));
-	// convert portal bits to leaf bits
-	numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
-
-//	if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
-//		Sys_Printf ("WARNING: Leaf portals saw into leaf\n");
-		
-//	uncompressed[leafnum>>3] |= (1<<(leafnum&7));
-
-	numvis++;		// count the leaf itself
-
-	totalvis += numvis;
-
-	Sys_FPrintf (SYS_VRB,"cluster %4i : %4i visible\n", leafnum, numvis);
-
-	memcpy (bspVisBytes + VIS_HEADER_SIZE + leafnum*leafbytes, uncompressed, leafbytes);
-}
-
-/*
-==================
-CalcPortalVis
-==================
-*/
-void CalcPortalVis (void)
-{
-#ifdef MREDEBUG
-	Sys_Printf("%6d portals out of %d", 0, numportals*2);
-	//get rid of the counter
-	RunThreadsOnIndividual (numportals*2, qfalse, PortalFlow);
-#else
-	RunThreadsOnIndividual (numportals*2, qtrue, PortalFlow);
-#endif
-
-}
-
-/*
-==================
-CalcPassageVis
-==================
-*/
-void CalcPassageVis(void)
-{
-	PassageMemory();
-
-#ifdef MREDEBUG
-	_printf("%6d portals out of %d", 0, numportals*2);
-	RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
-	_printf("\n");
-	_printf("%6d portals out of %d", 0, numportals*2);
-	RunThreadsOnIndividual (numportals*2, qfalse, PassageFlow);
-	_printf("\n");
-#else
-	Sys_Printf( "\n--- CreatePassages (%d) ---\n", numportals * 2 );
-	RunThreadsOnIndividual( numportals*2, qtrue, CreatePassages );
-	
-	Sys_Printf( "\n--- PassageFlow (%d) ---\n", numportals * 2 );
-	RunThreadsOnIndividual( numportals * 2, qtrue, PassageFlow );
-#endif
-}
-
-/*
-==================
-CalcPassagePortalVis
-==================
-*/
-void CalcPassagePortalVis(void)
-{
-	PassageMemory();
-
-#ifdef MREDEBUG
-	Sys_Printf("%6d portals out of %d", 0, numportals*2);
-	RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
-	Sys_Printf("\n");
-	Sys_Printf("%6d portals out of %d", 0, numportals*2);
-	RunThreadsOnIndividual (numportals*2, qfalse, PassagePortalFlow);
-	Sys_Printf("\n");
-#else
-	Sys_Printf( "\n--- CreatePassages (%d) ---\n", numportals * 2 );
-	RunThreadsOnIndividual( numportals * 2, qtrue, CreatePassages);
-	
-	Sys_Printf( "\n--- PassagePortalFlow (%d) ---\n", numportals * 2 );
-	RunThreadsOnIndividual( numportals * 2, qtrue, PassagePortalFlow );
-#endif
-}
-
-/*
-==================
-CalcFastVis
-==================
-*/
-void CalcFastVis(void)
-{
-	int		i;
-
-	// fastvis just uses mightsee for a very loose bound
-	for (i=0 ; i<numportals*2 ; i++)
-	{
-		portals[i].portalvis = portals[i].portalflood;
-		portals[i].status = stat_done;
-	}
-}
-
-/*
-==================
-CalcVis
-==================
-*/
-void CalcVis (void)
-{
-	int			i;
-	const char	*value;
-	
-	
-	/* ydnar: rr2do2's farplane code */
-	farPlaneDist = 0.0f;
-	value = ValueForKey( &entities[ 0 ], "_farplanedist" );		/* proper '_' prefixed key */
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( &entities[ 0 ], "fogclip" );		/* wolf compatibility */
-	if( value[ 0 ] == '\0' )
-		value = ValueForKey( &entities[ 0 ], "distancecull" );	/* sof2 compatibility */
-	if( value[ 0 ] != '\0' )
-	{
-		farPlaneDist = atof( value );
-		if( farPlaneDist > 0.0f )
-			Sys_Printf( "farplane distance = %.1f\n", farPlaneDist );
-		else
-			farPlaneDist = 0.0f;
-	}
-	
-	
-	
-	Sys_Printf( "\n--- BasePortalVis (%d) ---\n", numportals * 2 );
-	RunThreadsOnIndividual( numportals * 2, qtrue, BasePortalVis );
-	
-//	RunThreadsOnIndividual (numportals*2, qtrue, BetterPortalVis);
-
-	SortPortals ();
-
-  if (fastvis) {
-    CalcFastVis();
-  }
-  else if ( noPassageVis ) {
-    CalcPortalVis();
-  }
-  else if ( passageVisOnly ) {
-    CalcPassageVis();
-  }
-  else {
-    CalcPassagePortalVis();
-  }
-	//
-	// assemble the leaf vis lists by oring and compressing the portal lists
-	//
-	Sys_Printf("creating leaf vis...\n");
-	for (i=0 ; i<portalclusters ; i++)
-		ClusterMerge (i);
-
-  Sys_Printf( "Total visible clusters: %i\n", totalvis );
-  Sys_Printf( "Average clusters visible: %i\n", totalvis / portalclusters );
-}
-
-/*
-==================
-SetPortalSphere
-==================
-*/
-void SetPortalSphere (vportal_t *p)
-{
-	int		i;
-	vec3_t	total, dist;
-	fixedWinding_t	*w;
-	float	r, bestr;
-
-	w = p->winding;
-	VectorCopy (vec3_origin, total);
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		VectorAdd (total, w->points[i], total);
-	}
-	
-	for (i=0 ; i<3 ; i++)
-		total[i] /= w->numpoints;
-
-	bestr = 0;		
-	for (i=0 ; i<w->numpoints ; i++)
-	{
-		VectorSubtract (w->points[i], total, dist);
-		r = VectorLength (dist);
-		if (r > bestr)
-			bestr = r;
-	}
-	VectorCopy (total, p->origin);
-	p->radius = bestr;
-}
-
-/*
-=============
-Winding_PlanesConcave
-=============
-*/
-#define WCONVEX_EPSILON		0.2
-
-int Winding_PlanesConcave(fixedWinding_t *w1, fixedWinding_t *w2,
-							 vec3_t normal1, vec3_t normal2,
-							 float dist1, float dist2)
-{
-	int i;
-
-	if (!w1 || !w2) return qfalse;
-
-	// check if one of the points of winding 1 is at the front of the plane of winding 2
-	for (i = 0; i < w1->numpoints; i++)
-	{
-		if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return qtrue;
-	}
-	// check if one of the points of winding 2 is at the front of the plane of winding 1
-	for (i = 0; i < w2->numpoints; i++)
-	{
-		if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return qtrue;
-	}
-
-	return qfalse;
-}
-
-/*
-============
-TryMergeLeaves
-============
-*/
-int TryMergeLeaves(int l1num, int l2num)
-{
-	int i, j, k, n, numportals;
-	visPlane_t plane1, plane2;
-	leaf_t *l1, *l2;
-	vportal_t *p1, *p2;
-	vportal_t *portals[MAX_PORTALS_ON_LEAF];
-
-	for (k = 0; k < 2; k++)
-	{
-		if (k) l1 = &leafs[l1num];
-		else l1 = &faceleafs[l1num];
-		for (i = 0; i < l1->numportals; i++)
-		{
-			p1 = l1->portals[i];
-			if (p1->leaf == l2num) continue;
-			for (n = 0; n < 2; n++)
-			{
-				if (n) l2 = &leafs[l2num];
-				else l2 = &faceleafs[l2num];
-				for (j = 0; j < l2->numportals; j++)
-				{
-					p2 = l2->portals[j];
-					if (p2->leaf == l1num) continue;
-					//
-					plane1 = p1->plane;
-					plane2 = p2->plane;
-					if (Winding_PlanesConcave(p1->winding, p2->winding, plane1.normal, plane2.normal, plane1.dist, plane2.dist))
-						return qfalse;
-				}
-			}
-		}
-	}
-	for (k = 0; k < 2; k++)
-	{
-		if (k)
-		{
-			l1 = &leafs[l1num];
-			l2 = &leafs[l2num];
-		}
-		else
-		{
-			l1 = &faceleafs[l1num];
-			l2 = &faceleafs[l2num];
-		}
-		numportals = 0;
-		//the leaves can be merged now
-		for (i = 0; i < l1->numportals; i++)
-		{
-			p1 = l1->portals[i];
-			if (p1->leaf == l2num)
-			{
-				p1->removed = qtrue;
-				continue;
-			}
-			portals[numportals++] = p1;
-		}
-		for (j = 0; j < l2->numportals; j++)
-		{
-			p2 = l2->portals[j];
-			if (p2->leaf == l1num)
-			{
-				p2->removed = qtrue;
-				continue;
-			}
-			portals[numportals++] = p2;
-		}
-		for (i = 0; i < numportals; i++)
-		{
-			l2->portals[i] = portals[i];
-		}
-		l2->numportals = numportals;
-		l1->merged = l2num;
-	}
-	return qtrue;
-}
-
-/*
-============
-UpdatePortals
-============
-*/
-void UpdatePortals(void)
-{
-	int i;
-	vportal_t *p;
-
-	for (i = 0; i < numportals * 2; i++)
-	{
-		p = &portals[i];
-		if (p->removed)
-			continue;
-		while(leafs[p->leaf].merged >= 0)
-			p->leaf = leafs[p->leaf].merged;
-	}
-}
-
-/*
-============
-MergeLeaves
-
-try to merge leaves but don't merge through hint splitters
-============
-*/
-void MergeLeaves(void)
-{
-	int i, j, nummerges, totalnummerges;
-	leaf_t *leaf;
-	vportal_t *p;
-
-	totalnummerges = 0;
-	do
-	{
-		nummerges = 0;
-		for (i = 0; i < portalclusters; i++)
-		{
-			leaf = &leafs[i];
-			//if this leaf is merged already
-
-			/* ydnar: vmods: merge all non-hint portals */
-			if( leaf->merged >= 0 && hint == qfalse )
-				continue;
-
-
-			for (j = 0; j < leaf->numportals; j++)
-			{
-				p = leaf->portals[j];
-				//
-				if (p->removed)
-					continue;
-				//never merge through hint portals
-				if (p->hint)
-					continue;
-				if (TryMergeLeaves(i, p->leaf))
-				{
-					UpdatePortals();
-					nummerges++;
-					break;
-				}
-			}
-		}
-		totalnummerges += nummerges;
-	} while (nummerges);
-	Sys_Printf("%6d leaves merged\n", totalnummerges);
-}
-
-/*
-============
-TryMergeWinding
-============
-*/
-#define	CONTINUOUS_EPSILON	0.005
-
-fixedWinding_t *TryMergeWinding (fixedWinding_t *f1, fixedWinding_t *f2, vec3_t planenormal)
-{
-	vec_t		*p1, *p2, *p3, *p4, *back;
-	fixedWinding_t	*newf;
-	int			i, j, k, l;
-	vec3_t		normal, delta;
-	vec_t		dot;
-	qboolean	keep1, keep2;
-	
-
-	//
-	// find a common edge
-	//	
-	p1 = p2 = NULL;	// stop compiler warning
-	j = 0;			// 
-	
-	for (i = 0; i < f1->numpoints; i++)
-	{
-		p1 = f1->points[i];
-		p2 = f1->points[(i+1) % f1->numpoints];
-		for (j = 0; j < f2->numpoints; j++)
-		{
-			p3 = f2->points[j];
-			p4 = f2->points[(j+1) % f2->numpoints];
-			for (k = 0; k < 3; k++)
-			{
-				if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME
-					break;
-				if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME
-					break;
-			} //end for
-			if (k==3)
-				break;
-		} //end for
-		if (j < f2->numpoints)
-			break;
-	} //end for
-	
-	if (i == f1->numpoints)
-		return NULL;			// no matching edges
-
-	//
-	// check slope of connected lines
-	// if the slopes are colinear, the point can be removed
-	//
-	back = f1->points[(i+f1->numpoints-1)%f1->numpoints];
-	VectorSubtract (p1, back, delta);
-	CrossProduct (planenormal, delta, normal);
-	VectorNormalize (normal, normal);
-	
-	back = f2->points[(j+2)%f2->numpoints];
-	VectorSubtract (back, p1, delta);
-	dot = DotProduct (delta, normal);
-	if (dot > CONTINUOUS_EPSILON)
-		return NULL;			// not a convex polygon
-	keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
-	
-	back = f1->points[(i+2)%f1->numpoints];
-	VectorSubtract (back, p2, delta);
-	CrossProduct (planenormal, delta, normal);
-	VectorNormalize (normal, normal);
-
-	back = f2->points[(j+f2->numpoints-1)%f2->numpoints];
-	VectorSubtract (back, p2, delta);
-	dot = DotProduct (delta, normal);
-	if (dot > CONTINUOUS_EPSILON)
-		return NULL;			// not a convex polygon
-	keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
-
-	//
-	// build the new polygon
-	//
-	newf = NewFixedWinding (f1->numpoints + f2->numpoints);
-	
-	// copy first polygon
-	for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
-	{
-		if (k==(i+1)%f1->numpoints && !keep2)
-			continue;
-		
-		VectorCopy (f1->points[k], newf->points[newf->numpoints]);
-		newf->numpoints++;
-	}
-	
-	// copy second polygon
-	for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
-	{
-		if (l==(j+1)%f2->numpoints && !keep1)
-			continue;
-		VectorCopy (f2->points[l], newf->points[newf->numpoints]);
-		newf->numpoints++;
-	}
-
-	return newf;
-}
-
-/*
-============
-MergeLeafPortals
-============
-*/
-void MergeLeafPortals(void)
-{
-	int i, j, k, nummerges, hintsmerged;
-	leaf_t *leaf;
-	vportal_t *p1, *p2;
-	fixedWinding_t *w;
-
-	nummerges = 0;
-	hintsmerged = 0;
-	for (i = 0; i < portalclusters; i++)
-	{
-		leaf = &leafs[i];
-		if (leaf->merged >= 0) continue;
-		for (j = 0; j < leaf->numportals; j++)
-		{
-			p1 = leaf->portals[j];
-			if (p1->removed)
-				continue;
-			for (k = j+1; k < leaf->numportals; k++)
-			{
-				p2 = leaf->portals[k];
-				if (p2->removed)
-					continue;
-				if (p1->leaf == p2->leaf)
-				{
-					w = TryMergeWinding(p1->winding, p2->winding, p1->plane.normal);
-					if (w)
-					{
-						free( p1->winding );	//% FreeWinding(p1->winding);
-						p1->winding = w;
-						if (p1->hint && p2->hint)
-							hintsmerged++;
-						p1->hint |= p2->hint;
-						SetPortalSphere(p1);
-						p2->removed = qtrue;
-						nummerges++;
-						i--;
-						break;
-					}
-				}
-			}
-			if (k < leaf->numportals)
-				break;
-		}
-	}
-	Sys_Printf("%6d portals merged\n", nummerges);
-	Sys_Printf("%6d hint portals merged\n", hintsmerged);
-}
-
-
-/*
-============
-WritePortals
-============
-*/
-int CountActivePortals(void)
-{
-	int num, hints, j;
-	vportal_t *p;
-
-	num = 0;
-	hints = 0;
-	for (j = 0; j < numportals * 2; j++)
-	{
-		p = portals + j;
-		if (p->removed)
-			continue;
-		if (p->hint)
-			hints++;
-		num++;
-	}
-	Sys_Printf("%6d active portals\n", num);
-	Sys_Printf("%6d hint portals\n", hints);
-	return num;
-}
-
-/*
-============
-WritePortals
-============
-*/
-void WriteFloat (FILE *f, vec_t v);
-
-void WritePortals(char *filename)
-{
-	int i, j, num;
-	FILE *pf;
-	vportal_t *p;
-	fixedWinding_t *w;
-
-	// write the file
-	pf = fopen (filename, "w");
-	if (!pf)
-		Error ("Error opening %s", filename);
-
-	num = 0;
-	for (j = 0; j < numportals * 2; j++)
-	{
-		p = portals + j;
-		if (p->removed)
-			continue;
-//		if (!p->hint)
-//			continue;
-		num++;
-	}
-
-	fprintf (pf, "%s\n", PORTALFILE);
-	fprintf (pf, "%i\n", 0);
-	fprintf (pf, "%i\n", num);// + numfaces);
-	fprintf (pf, "%i\n", 0);
-
-	for (j = 0; j < numportals * 2; j++)
-	{
-		p = portals + j;
-		if (p->removed)
-			continue;
-//		if (!p->hint)
-//			continue;
-		w = p->winding;
-		fprintf (pf,"%i %i %i ",w->numpoints, 0, 0);
-		fprintf (pf, "%d ", p->hint);
-		for (i=0 ; i<w->numpoints ; i++)
-		{
-			fprintf (pf,"(");
-			WriteFloat (pf, w->points[i][0]);
-			WriteFloat (pf, w->points[i][1]);
-			WriteFloat (pf, w->points[i][2]);
-			fprintf (pf,") ");
-		}
-		fprintf (pf,"\n");
-	}
-
-	/*
-	for (j = 0; j < numfaces; j++)
-	{
-		p = faces + j;
-		w = p->winding;
-		fprintf (pf,"%i %i %i ",w->numpoints, 0, 0);
-		fprintf (pf, "0 ");
-		for (i=0 ; i<w->numpoints ; i++)
-		{
-			fprintf (pf,"(");
-			WriteFloat (pf, w->points[i][0]);
-			WriteFloat (pf, w->points[i][1]);
-			WriteFloat (pf, w->points[i][2]);
-			fprintf (pf,") ");
-		}
-		fprintf (pf,"\n");
-	}*/
-
-	fclose (pf);
-}
-
-/*
-============
-LoadPortals
-============
-*/
-void LoadPortals (char *name)
-{
-	int			i, j, hint;
-	vportal_t	*p;
-	leaf_t		*l;
-	char		magic[80];
-	FILE		*f;
-	int			numpoints;
-	fixedWinding_t	*w;
-	int			leafnums[2];
-	visPlane_t	plane;
-	
-	if (!strcmp(name,"-"))
-		f = stdin;
-	else
-	{
-		f = fopen(name, "r");
-		if (!f)
-			Error ("LoadPortals: couldn't read %s\n",name);
-	}
-
-	if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4)
-		Error ("LoadPortals: failed to read header");
-	if (strcmp(magic,PORTALFILE))
-		Error ("LoadPortals: not a portal file");
-
-	Sys_Printf ("%6i portalclusters\n", portalclusters);
-	Sys_Printf ("%6i numportals\n", numportals);
-	Sys_Printf ("%6i numfaces\n", numfaces);
-
-	// these counts should take advantage of 64 bit systems automatically
-	leafbytes = ((portalclusters+63)&~63)>>3;
-	leaflongs = leafbytes/sizeof(long);
-	
-	portalbytes = ((numportals*2+63)&~63)>>3;
-	portallongs = portalbytes/sizeof(long);
-
-	// each file portal is split into two memory portals
-	portals = safe_malloc(2*numportals*sizeof(vportal_t));
-	memset (portals, 0, 2*numportals*sizeof(vportal_t));
-	
-	leafs = safe_malloc(portalclusters*sizeof(leaf_t));
-	memset (leafs, 0, portalclusters*sizeof(leaf_t));
-
-	for (i = 0; i < portalclusters; i++)
-		leafs[i].merged = -1;
-
-	numBSPVisBytes = VIS_HEADER_SIZE + portalclusters*leafbytes;
-
-	if (numBSPVisBytes > MAX_MAP_VISIBILITY)
-	  Error("MAX_MAP_VISIBILITY exceeded");
-
-	((int *)bspVisBytes)[0] = portalclusters;
-	((int *)bspVisBytes)[1] = leafbytes;
-		
-	for (i=0, p=portals ; i<numportals ; i++)
-	{
-		if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3)
-			Error ("LoadPortals: reading portal %i", i);
-		if (numpoints > MAX_POINTS_ON_WINDING)
-			Error ("LoadPortals: portal %i has too many points", i);
-		if ( (unsigned)leafnums[0] > portalclusters
-		|| (unsigned)leafnums[1] > portalclusters)
-			Error ("LoadPortals: reading portal %i", i);
-		if (fscanf (f, "%i ", &hint) != 1)
-			Error ("LoadPortals: reading hint state");
-		
-		w = p->winding = NewFixedWinding (numpoints);
-		w->numpoints = numpoints;
-		
-		for (j=0 ; j<numpoints ; j++)
-		{
-			double	v[3];
-			int		k;
-
-			// scanf into double, then assign to vec_t
-			// so we don't care what size vec_t is
-			if (fscanf (f, "(%lf %lf %lf ) "
-			, &v[0], &v[1], &v[2]) != 3)
-				Error ("LoadPortals: reading portal %i", i);
-			for (k=0 ; k<3 ; k++)
-				w->points[j][k] = v[k];
-		}
-		fscanf (f, "\n");
-		
-		// calc plane
-		PlaneFromWinding (w, &plane);
-
-		// create forward portal
-		l = &leafs[leafnums[0]];
-		if (l->numportals == MAX_PORTALS_ON_LEAF)
-			Error ("Leaf with too many portals");
-		l->portals[l->numportals] = p;
-		l->numportals++;
-		
-		p->num = i+1;
-		p->hint = hint;
-		p->winding = w;
-		VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
-		p->plane.dist = -plane.dist;
-		p->leaf = leafnums[1];
-		SetPortalSphere (p);
-		p++;
-		
-		// create backwards portal
-		l = &leafs[leafnums[1]];
-		if (l->numportals == MAX_PORTALS_ON_LEAF)
-			Error ("Leaf with too many portals");
-		l->portals[l->numportals] = p;
-		l->numportals++;
-		
-		p->num = i+1;
-		p->hint = hint;
-		p->winding = NewFixedWinding(w->numpoints);
-		p->winding->numpoints = w->numpoints;
-		for (j=0 ; j<w->numpoints ; j++)
-		{
-			VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
-		}
-
-		p->plane = plane;
-		p->leaf = leafnums[0];
-		SetPortalSphere (p);
-		p++;
-
-	}
-
-	faces = safe_malloc(2*numfaces*sizeof(vportal_t));
-	memset (faces, 0, 2*numfaces*sizeof(vportal_t));
-
-	faceleafs = safe_malloc(portalclusters*sizeof(leaf_t));
-	memset(faceleafs, 0, portalclusters*sizeof(leaf_t));
-
-	for (i = 0, p = faces; i < numfaces; i++)
-	{
-		if (fscanf (f, "%i %i ", &numpoints, &leafnums[0]) != 2)
-			Error ("LoadPortals: reading portal %i", i);
-
-		w = p->winding = NewFixedWinding (numpoints);
-		w->numpoints = numpoints;
-		
-		for (j=0 ; j<numpoints ; j++)
-		{
-			double	v[3];
-			int		k;
-
-			// scanf into double, then assign to vec_t
-			// so we don't care what size vec_t is
-			if (fscanf (f, "(%lf %lf %lf ) "
-			, &v[0], &v[1], &v[2]) != 3)
-				Error ("LoadPortals: reading portal %i", i);
-			for (k=0 ; k<3 ; k++)
-				w->points[j][k] = v[k];
-		}
-		fscanf (f, "\n");
-		
-		// calc plane
-		PlaneFromWinding (w, &plane);
-
-		l = &faceleafs[leafnums[0]];
-		l->merged = -1;
-		if (l->numportals == MAX_PORTALS_ON_LEAF)
-			Error ("Leaf with too many faces");
-		l->portals[l->numportals] = p;
-		l->numportals++;
-		
-		p->num = i+1;
-		p->winding = w;
-		// normal pointing out of the leaf
-		VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
-		p->plane.dist = -plane.dist;
-		p->leaf = -1;
-		SetPortalSphere (p);
-		p++;
-	}
-	
-	fclose (f);
-}
-
-
-
-/*
-===========
-VisMain
-===========
-*/
-int VisMain (int argc, char **argv)
-{
-	char		portalfile[1024];
-	int			i;
-	
-	
-	/* note it */
-	Sys_Printf( "--- Vis ---\n" );
-	
-	/* process arguments */
-	for (i=1 ; i < (argc - 1) ; i++)
-	{
-		if (!strcmp(argv[i], "-fast")) {
-			Sys_Printf ("fastvis = true\n");
-			fastvis = qtrue;
-		} else if (!strcmp(argv[i], "-merge")) {
-			Sys_Printf ("merge = true\n");
-			mergevis = qtrue;
-		} else if (!strcmp(argv[i], "-nopassage")) {
-			Sys_Printf ("nopassage = true\n");
-			noPassageVis = qtrue;
-		} else if (!strcmp(argv[i], "-passageOnly")) {
-			Sys_Printf ("passageOnly = true\n");
-			passageVisOnly = qtrue;
-		} else if (!strcmp (argv[i],"-nosort")) {
-			Sys_Printf ("nosort = true\n");
-			nosort = qtrue;
-		} else if (!strcmp (argv[i],"-saveprt")) {
-			Sys_Printf ("saveprt = true\n");
-			saveprt = qtrue;
-		} else if (!strcmp (argv[i],"-tmpin")) {
-			strcpy (inbase, "/tmp");
-		} else if (!strcmp (argv[i],"-tmpout")) {
-			strcpy (outbase, "/tmp");
-		}
-		
-	
-		/* ydnar: -hint to merge all but hint portals */
-		else if( !strcmp( argv[ i ], "-hint" ) )
-		{
-			Sys_Printf( "hint = true\n" );
-			hint = qtrue;
-			mergevis = qtrue;
-		}
-		
-		else
-			Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
-	}
-
-	if( i != argc - 1 )
-		Error( "usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile" );
-	
-
-	/* load the bsp */
-	sprintf( source, "%s%s", inbase, ExpandArg( argv[ i ] ) );
-	StripExtension( source );
-	strcat( source, ".bsp" );
-	Sys_Printf( "Loading %s\n", source );
-	LoadBSPFile( source );
-	
-	/* load the portal file */
-	sprintf( portalfile, "%s%s", inbase, ExpandArg( argv[ i ] ) );
-	StripExtension( portalfile );
-	strcat( portalfile, ".prt" );
-	Sys_Printf( "Loading %s\n", portalfile );
-	LoadPortals( portalfile );
-	
-	/* ydnar: for getting far plane */
-	ParseEntities();
-	
-	if( mergevis )
-	{
-		MergeLeaves();
-		MergeLeafPortals();
-	}
-	
-	CountActivePortals();
-	/* WritePortals( "maps/hints.prs" );*/
-	
-	Sys_Printf( "visdatasize:%i\n", numBSPVisBytes );
-	
-	CalcVis();
-	
-	/* delete the prt file */
-	if( !saveprt )
-		remove( portalfile );
-
-	/* write the bsp file */
-	Sys_Printf( "Writing %s\n", source );
-	WriteBSPFile( source );
-
-	return 0;
-}
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define VIS_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+void PlaneFromWinding (fixedWinding_t *w, visPlane_t *plane)
+{
+	vec3_t		v1, v2;
+
+// calc plane
+	VectorSubtract (w->points[2], w->points[1], v1);
+	VectorSubtract (w->points[0], w->points[1], v2);
+	CrossProduct (v2, v1, plane->normal);
+	VectorNormalize (plane->normal, plane->normal);
+	plane->dist = DotProduct (w->points[0], plane->normal);
+}
+
+
+/*
+NewFixedWinding()
+returns a new fixed winding
+ydnar: altered this a bit to reconcile multiply-defined winding_t
+*/
+
+fixedWinding_t *NewFixedWinding( int points )
+{
+	fixedWinding_t	*w;
+	int			size;
+	
+	if (points > MAX_POINTS_ON_WINDING)
+		Error ("NewWinding: %i points", points);
+	
+	size = (int)((fixedWinding_t *)0)->points[points];
+	w = safe_malloc (size);
+	memset (w, 0, size);
+	
+	return w;
+}
+
+
+
+void prl(leaf_t *l)
+{
+	int			i;
+	vportal_t	*p;
+	visPlane_t	pl;
+	
+	for (i=0 ; i<l->numportals ; i++)
+	{
+		p = l->portals[i];
+		pl = p->plane;
+		Sys_Printf ("portal %4i to leaf %4i : %7.1f : (%4.1f, %4.1f, %4.1f)\n",(int)(p-portals),p->leaf,pl.dist, pl.normal[0], pl.normal[1], pl.normal[2]);
+	}
+}
+
+
+//=============================================================================
+
+/*
+=============
+SortPortals
+
+Sorts the portals from the least complex, so the later ones can reuse
+the earlier information.
+=============
+*/
+int PComp (const void *a, const void *b)
+{
+	if ( (*(vportal_t **)a)->nummightsee == (*(vportal_t **)b)->nummightsee)
+		return 0;
+	if ( (*(vportal_t **)a)->nummightsee < (*(vportal_t **)b)->nummightsee)
+		return -1;
+	return 1;
+}
+void SortPortals (void)
+{
+	int		i;
+	
+	for (i=0 ; i<numportals*2 ; i++)
+		sorted_portals[i] = &portals[i];
+
+	if (nosort)
+		return;
+	qsort (sorted_portals, numportals*2, sizeof(sorted_portals[0]), PComp);
+}
+
+
+/*
+==============
+LeafVectorFromPortalVector
+==============
+*/
+int LeafVectorFromPortalVector (byte *portalbits, byte *leafbits)
+{
+	int			i, j, leafnum;
+	vportal_t	*p;
+	int			c_leafs;
+
+
+	for (i=0 ; i<numportals*2 ; i++)
+	{
+		if (portalbits[i>>3] & (1<<(i&7)) )
+		{
+			p = portals+i;
+			leafbits[p->leaf>>3] |= (1<<(p->leaf&7));
+		}
+	}
+
+	for (j = 0; j < portalclusters; j++)
+	{
+		leafnum = j;
+		while (leafs[leafnum].merged >= 0)
+			leafnum = leafs[leafnum].merged;
+		//if the merged leaf is visible then the original leaf is visible
+		if (leafbits[leafnum>>3] & (1<<(leafnum&7)))
+		{
+			leafbits[j>>3] |= (1<<(j&7));
+		}
+	}
+
+	c_leafs = CountBits (leafbits, portalclusters);
+
+	return c_leafs;
+}
+
+
+/*
+===============
+ClusterMerge
+
+Merges the portal visibility for a leaf
+===============
+*/
+void ClusterMerge (int leafnum)
+{
+	leaf_t		*leaf;
+	byte		portalvector[MAX_PORTALS/8];
+	byte		uncompressed[MAX_MAP_LEAFS/8];
+	int			i, j;
+	int			numvis, mergedleafnum;
+	vportal_t	*p;
+	int			pnum;
+
+	// OR together all the portalvis bits
+
+	mergedleafnum = leafnum;
+	while(leafs[mergedleafnum].merged >= 0)
+		mergedleafnum = leafs[mergedleafnum].merged;
+
+	memset (portalvector, 0, portalbytes);
+	leaf = &leafs[mergedleafnum];
+	for (i = 0; i < leaf->numportals; i++)
+	{
+		p = leaf->portals[i];
+		if (p->removed)
+			continue;
+
+		if (p->status != stat_done)
+			Error ("portal not done");
+		for (j=0 ; j<portallongs ; j++)
+			((long *)portalvector)[j] |= ((long *)p->portalvis)[j];
+		pnum = p - portals;
+		portalvector[pnum>>3] |= 1<<(pnum&7);
+	}
+
+	memset (uncompressed, 0, leafbytes);
+
+	uncompressed[mergedleafnum>>3] |= (1<<(mergedleafnum&7));
+	// convert portal bits to leaf bits
+	numvis = LeafVectorFromPortalVector (portalvector, uncompressed);
+
+//	if (uncompressed[leafnum>>3] & (1<<(leafnum&7)))
+//		Sys_Printf ("WARNING: Leaf portals saw into leaf\n");
+		
+//	uncompressed[leafnum>>3] |= (1<<(leafnum&7));
+
+	numvis++;		// count the leaf itself
+
+	totalvis += numvis;
+
+	Sys_FPrintf (SYS_VRB,"cluster %4i : %4i visible\n", leafnum, numvis);
+
+	memcpy (bspVisBytes + VIS_HEADER_SIZE + leafnum*leafbytes, uncompressed, leafbytes);
+}
+
+/*
+==================
+CalcPortalVis
+==================
+*/
+void CalcPortalVis (void)
+{
+#ifdef MREDEBUG
+	Sys_Printf("%6d portals out of %d", 0, numportals*2);
+	//get rid of the counter
+	RunThreadsOnIndividual (numportals*2, qfalse, PortalFlow);
+#else
+	RunThreadsOnIndividual (numportals*2, qtrue, PortalFlow);
+#endif
+
+}
+
+/*
+==================
+CalcPassageVis
+==================
+*/
+void CalcPassageVis(void)
+{
+	PassageMemory();
+
+#ifdef MREDEBUG
+	_printf("%6d portals out of %d", 0, numportals*2);
+	RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
+	_printf("\n");
+	_printf("%6d portals out of %d", 0, numportals*2);
+	RunThreadsOnIndividual (numportals*2, qfalse, PassageFlow);
+	_printf("\n");
+#else
+	Sys_Printf( "\n--- CreatePassages (%d) ---\n", numportals * 2 );
+	RunThreadsOnIndividual( numportals*2, qtrue, CreatePassages );
+	
+	Sys_Printf( "\n--- PassageFlow (%d) ---\n", numportals * 2 );
+	RunThreadsOnIndividual( numportals * 2, qtrue, PassageFlow );
+#endif
+}
+
+/*
+==================
+CalcPassagePortalVis
+==================
+*/
+void CalcPassagePortalVis(void)
+{
+	PassageMemory();
+
+#ifdef MREDEBUG
+	Sys_Printf("%6d portals out of %d", 0, numportals*2);
+	RunThreadsOnIndividual (numportals*2, qfalse, CreatePassages);
+	Sys_Printf("\n");
+	Sys_Printf("%6d portals out of %d", 0, numportals*2);
+	RunThreadsOnIndividual (numportals*2, qfalse, PassagePortalFlow);
+	Sys_Printf("\n");
+#else
+	Sys_Printf( "\n--- CreatePassages (%d) ---\n", numportals * 2 );
+	RunThreadsOnIndividual( numportals * 2, qtrue, CreatePassages);
+	
+	Sys_Printf( "\n--- PassagePortalFlow (%d) ---\n", numportals * 2 );
+	RunThreadsOnIndividual( numportals * 2, qtrue, PassagePortalFlow );
+#endif
+}
+
+/*
+==================
+CalcFastVis
+==================
+*/
+void CalcFastVis(void)
+{
+	int		i;
+
+	// fastvis just uses mightsee for a very loose bound
+	for (i=0 ; i<numportals*2 ; i++)
+	{
+		portals[i].portalvis = portals[i].portalflood;
+		portals[i].status = stat_done;
+	}
+}
+
+/*
+==================
+CalcVis
+==================
+*/
+void CalcVis (void)
+{
+	int			i;
+	const char	*value;
+	
+	
+	/* ydnar: rr2do2's farplane code */
+	farPlaneDist = 0.0f;
+	value = ValueForKey( &entities[ 0 ], "_farplanedist" );		/* proper '_' prefixed key */
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( &entities[ 0 ], "fogclip" );		/* wolf compatibility */
+	if( value[ 0 ] == '\0' )
+		value = ValueForKey( &entities[ 0 ], "distancecull" );	/* sof2 compatibility */
+	if( value[ 0 ] != '\0' )
+	{
+		farPlaneDist = atof( value );
+		if( farPlaneDist > 0.0f )
+			Sys_Printf( "farplane distance = %.1f\n", farPlaneDist );
+		else
+			farPlaneDist = 0.0f;
+	}
+	
+	
+	
+	Sys_Printf( "\n--- BasePortalVis (%d) ---\n", numportals * 2 );
+	RunThreadsOnIndividual( numportals * 2, qtrue, BasePortalVis );
+	
+//	RunThreadsOnIndividual (numportals*2, qtrue, BetterPortalVis);
+
+	SortPortals ();
+
+  if (fastvis) {
+    CalcFastVis();
+  }
+  else if ( noPassageVis ) {
+    CalcPortalVis();
+  }
+  else if ( passageVisOnly ) {
+    CalcPassageVis();
+  }
+  else {
+    CalcPassagePortalVis();
+  }
+	//
+	// assemble the leaf vis lists by oring and compressing the portal lists
+	//
+	Sys_Printf("creating leaf vis...\n");
+	for (i=0 ; i<portalclusters ; i++)
+		ClusterMerge (i);
+
+  Sys_Printf( "Total visible clusters: %i\n", totalvis );
+  Sys_Printf( "Average clusters visible: %i\n", totalvis / portalclusters );
+}
+
+/*
+==================
+SetPortalSphere
+==================
+*/
+void SetPortalSphere (vportal_t *p)
+{
+	int		i;
+	vec3_t	total, dist;
+	fixedWinding_t	*w;
+	float	r, bestr;
+
+	w = p->winding;
+	VectorCopy (vec3_origin, total);
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		VectorAdd (total, w->points[i], total);
+	}
+	
+	for (i=0 ; i<3 ; i++)
+		total[i] /= w->numpoints;
+
+	bestr = 0;		
+	for (i=0 ; i<w->numpoints ; i++)
+	{
+		VectorSubtract (w->points[i], total, dist);
+		r = VectorLength (dist);
+		if (r > bestr)
+			bestr = r;
+	}
+	VectorCopy (total, p->origin);
+	p->radius = bestr;
+}
+
+/*
+=============
+Winding_PlanesConcave
+=============
+*/
+#define WCONVEX_EPSILON		0.2
+
+int Winding_PlanesConcave(fixedWinding_t *w1, fixedWinding_t *w2,
+							 vec3_t normal1, vec3_t normal2,
+							 float dist1, float dist2)
+{
+	int i;
+
+	if (!w1 || !w2) return qfalse;
+
+	// check if one of the points of winding 1 is at the front of the plane of winding 2
+	for (i = 0; i < w1->numpoints; i++)
+	{
+		if (DotProduct(normal2, w1->points[i]) - dist2 > WCONVEX_EPSILON) return qtrue;
+	}
+	// check if one of the points of winding 2 is at the front of the plane of winding 1
+	for (i = 0; i < w2->numpoints; i++)
+	{
+		if (DotProduct(normal1, w2->points[i]) - dist1 > WCONVEX_EPSILON) return qtrue;
+	}
+
+	return qfalse;
+}
+
+/*
+============
+TryMergeLeaves
+============
+*/
+int TryMergeLeaves(int l1num, int l2num)
+{
+	int i, j, k, n, numportals;
+	visPlane_t plane1, plane2;
+	leaf_t *l1, *l2;
+	vportal_t *p1, *p2;
+	vportal_t *portals[MAX_PORTALS_ON_LEAF];
+
+	for (k = 0; k < 2; k++)
+	{
+		if (k) l1 = &leafs[l1num];
+		else l1 = &faceleafs[l1num];
+		for (i = 0; i < l1->numportals; i++)
+		{
+			p1 = l1->portals[i];
+			if (p1->leaf == l2num) continue;
+			for (n = 0; n < 2; n++)
+			{
+				if (n) l2 = &leafs[l2num];
+				else l2 = &faceleafs[l2num];
+				for (j = 0; j < l2->numportals; j++)
+				{
+					p2 = l2->portals[j];
+					if (p2->leaf == l1num) continue;
+					//
+					plane1 = p1->plane;
+					plane2 = p2->plane;
+					if (Winding_PlanesConcave(p1->winding, p2->winding, plane1.normal, plane2.normal, plane1.dist, plane2.dist))
+						return qfalse;
+				}
+			}
+		}
+	}
+	for (k = 0; k < 2; k++)
+	{
+		if (k)
+		{
+			l1 = &leafs[l1num];
+			l2 = &leafs[l2num];
+		}
+		else
+		{
+			l1 = &faceleafs[l1num];
+			l2 = &faceleafs[l2num];
+		}
+		numportals = 0;
+		//the leaves can be merged now
+		for (i = 0; i < l1->numportals; i++)
+		{
+			p1 = l1->portals[i];
+			if (p1->leaf == l2num)
+			{
+				p1->removed = qtrue;
+				continue;
+			}
+			portals[numportals++] = p1;
+		}
+		for (j = 0; j < l2->numportals; j++)
+		{
+			p2 = l2->portals[j];
+			if (p2->leaf == l1num)
+			{
+				p2->removed = qtrue;
+				continue;
+			}
+			portals[numportals++] = p2;
+		}
+		for (i = 0; i < numportals; i++)
+		{
+			l2->portals[i] = portals[i];
+		}
+		l2->numportals = numportals;
+		l1->merged = l2num;
+	}
+	return qtrue;
+}
+
+/*
+============
+UpdatePortals
+============
+*/
+void UpdatePortals(void)
+{
+	int i;
+	vportal_t *p;
+
+	for (i = 0; i < numportals * 2; i++)
+	{
+		p = &portals[i];
+		if (p->removed)
+			continue;
+		while(leafs[p->leaf].merged >= 0)
+			p->leaf = leafs[p->leaf].merged;
+	}
+}
+
+/*
+============
+MergeLeaves
+
+try to merge leaves but don't merge through hint splitters
+============
+*/
+void MergeLeaves(void)
+{
+	int i, j, nummerges, totalnummerges;
+	leaf_t *leaf;
+	vportal_t *p;
+
+	totalnummerges = 0;
+	do
+	{
+		nummerges = 0;
+		for (i = 0; i < portalclusters; i++)
+		{
+			leaf = &leafs[i];
+			//if this leaf is merged already
+
+			/* ydnar: vmods: merge all non-hint portals */
+			if( leaf->merged >= 0 && hint == qfalse )
+				continue;
+
+
+			for (j = 0; j < leaf->numportals; j++)
+			{
+				p = leaf->portals[j];
+				//
+				if (p->removed)
+					continue;
+				//never merge through hint portals
+				if (p->hint)
+					continue;
+				if (TryMergeLeaves(i, p->leaf))
+				{
+					UpdatePortals();
+					nummerges++;
+					break;
+				}
+			}
+		}
+		totalnummerges += nummerges;
+	} while (nummerges);
+	Sys_Printf("%6d leaves merged\n", totalnummerges);
+}
+
+/*
+============
+TryMergeWinding
+============
+*/
+#define	CONTINUOUS_EPSILON	0.005
+
+fixedWinding_t *TryMergeWinding (fixedWinding_t *f1, fixedWinding_t *f2, vec3_t planenormal)
+{
+	vec_t		*p1, *p2, *p3, *p4, *back;
+	fixedWinding_t	*newf;
+	int			i, j, k, l;
+	vec3_t		normal, delta;
+	vec_t		dot;
+	qboolean	keep1, keep2;
+	
+
+	//
+	// find a common edge
+	//	
+	p1 = p2 = NULL;	// stop compiler warning
+	j = 0;			// 
+	
+	for (i = 0; i < f1->numpoints; i++)
+	{
+		p1 = f1->points[i];
+		p2 = f1->points[(i+1) % f1->numpoints];
+		for (j = 0; j < f2->numpoints; j++)
+		{
+			p3 = f2->points[j];
+			p4 = f2->points[(j+1) % f2->numpoints];
+			for (k = 0; k < 3; k++)
+			{
+				if (fabs(p1[k] - p4[k]) > 0.1)//EQUAL_EPSILON) //ME
+					break;
+				if (fabs(p2[k] - p3[k]) > 0.1)//EQUAL_EPSILON) //ME
+					break;
+			} //end for
+			if (k==3)
+				break;
+		} //end for
+		if (j < f2->numpoints)
+			break;
+	} //end for
+	
+	if (i == f1->numpoints)
+		return NULL;			// no matching edges
+
+	//
+	// check slope of connected lines
+	// if the slopes are colinear, the point can be removed
+	//
+	back = f1->points[(i+f1->numpoints-1)%f1->numpoints];
+	VectorSubtract (p1, back, delta);
+	CrossProduct (planenormal, delta, normal);
+	VectorNormalize (normal, normal);
+	
+	back = f2->points[(j+2)%f2->numpoints];
+	VectorSubtract (back, p1, delta);
+	dot = DotProduct (delta, normal);
+	if (dot > CONTINUOUS_EPSILON)
+		return NULL;			// not a convex polygon
+	keep1 = (qboolean)(dot < -CONTINUOUS_EPSILON);
+	
+	back = f1->points[(i+2)%f1->numpoints];
+	VectorSubtract (back, p2, delta);
+	CrossProduct (planenormal, delta, normal);
+	VectorNormalize (normal, normal);
+
+	back = f2->points[(j+f2->numpoints-1)%f2->numpoints];
+	VectorSubtract (back, p2, delta);
+	dot = DotProduct (delta, normal);
+	if (dot > CONTINUOUS_EPSILON)
+		return NULL;			// not a convex polygon
+	keep2 = (qboolean)(dot < -CONTINUOUS_EPSILON);
+
+	//
+	// build the new polygon
+	//
+	newf = NewFixedWinding (f1->numpoints + f2->numpoints);
+	
+	// copy first polygon
+	for (k=(i+1)%f1->numpoints ; k != i ; k=(k+1)%f1->numpoints)
+	{
+		if (k==(i+1)%f1->numpoints && !keep2)
+			continue;
+		
+		VectorCopy (f1->points[k], newf->points[newf->numpoints]);
+		newf->numpoints++;
+	}
+	
+	// copy second polygon
+	for (l= (j+1)%f2->numpoints ; l != j ; l=(l+1)%f2->numpoints)
+	{
+		if (l==(j+1)%f2->numpoints && !keep1)
+			continue;
+		VectorCopy (f2->points[l], newf->points[newf->numpoints]);
+		newf->numpoints++;
+	}
+
+	return newf;
+}
+
+/*
+============
+MergeLeafPortals
+============
+*/
+void MergeLeafPortals(void)
+{
+	int i, j, k, nummerges, hintsmerged;
+	leaf_t *leaf;
+	vportal_t *p1, *p2;
+	fixedWinding_t *w;
+
+	nummerges = 0;
+	hintsmerged = 0;
+	for (i = 0; i < portalclusters; i++)
+	{
+		leaf = &leafs[i];
+		if (leaf->merged >= 0) continue;
+		for (j = 0; j < leaf->numportals; j++)
+		{
+			p1 = leaf->portals[j];
+			if (p1->removed)
+				continue;
+			for (k = j+1; k < leaf->numportals; k++)
+			{
+				p2 = leaf->portals[k];
+				if (p2->removed)
+					continue;
+				if (p1->leaf == p2->leaf)
+				{
+					w = TryMergeWinding(p1->winding, p2->winding, p1->plane.normal);
+					if (w)
+					{
+						free( p1->winding );	//% FreeWinding(p1->winding);
+						p1->winding = w;
+						if (p1->hint && p2->hint)
+							hintsmerged++;
+						p1->hint |= p2->hint;
+						SetPortalSphere(p1);
+						p2->removed = qtrue;
+						nummerges++;
+						i--;
+						break;
+					}
+				}
+			}
+			if (k < leaf->numportals)
+				break;
+		}
+	}
+	Sys_Printf("%6d portals merged\n", nummerges);
+	Sys_Printf("%6d hint portals merged\n", hintsmerged);
+}
+
+
+/*
+============
+WritePortals
+============
+*/
+int CountActivePortals(void)
+{
+	int num, hints, j;
+	vportal_t *p;
+
+	num = 0;
+	hints = 0;
+	for (j = 0; j < numportals * 2; j++)
+	{
+		p = portals + j;
+		if (p->removed)
+			continue;
+		if (p->hint)
+			hints++;
+		num++;
+	}
+	Sys_Printf("%6d active portals\n", num);
+	Sys_Printf("%6d hint portals\n", hints);
+	return num;
+}
+
+/*
+============
+WritePortals
+============
+*/
+void WriteFloat (FILE *f, vec_t v);
+
+void WritePortals(char *filename)
+{
+	int i, j, num;
+	FILE *pf;
+	vportal_t *p;
+	fixedWinding_t *w;
+
+	// write the file
+	pf = fopen (filename, "w");
+	if (!pf)
+		Error ("Error opening %s", filename);
+
+	num = 0;
+	for (j = 0; j < numportals * 2; j++)
+	{
+		p = portals + j;
+		if (p->removed)
+			continue;
+//		if (!p->hint)
+//			continue;
+		num++;
+	}
+
+	fprintf (pf, "%s\n", PORTALFILE);
+	fprintf (pf, "%i\n", 0);
+	fprintf (pf, "%i\n", num);// + numfaces);
+	fprintf (pf, "%i\n", 0);
+
+	for (j = 0; j < numportals * 2; j++)
+	{
+		p = portals + j;
+		if (p->removed)
+			continue;
+//		if (!p->hint)
+//			continue;
+		w = p->winding;
+		fprintf (pf,"%i %i %i ",w->numpoints, 0, 0);
+		fprintf (pf, "%d ", p->hint);
+		for (i=0 ; i<w->numpoints ; i++)
+		{
+			fprintf (pf,"(");
+			WriteFloat (pf, w->points[i][0]);
+			WriteFloat (pf, w->points[i][1]);
+			WriteFloat (pf, w->points[i][2]);
+			fprintf (pf,") ");
+		}
+		fprintf (pf,"\n");
+	}
+
+	/*
+	for (j = 0; j < numfaces; j++)
+	{
+		p = faces + j;
+		w = p->winding;
+		fprintf (pf,"%i %i %i ",w->numpoints, 0, 0);
+		fprintf (pf, "0 ");
+		for (i=0 ; i<w->numpoints ; i++)
+		{
+			fprintf (pf,"(");
+			WriteFloat (pf, w->points[i][0]);
+			WriteFloat (pf, w->points[i][1]);
+			WriteFloat (pf, w->points[i][2]);
+			fprintf (pf,") ");
+		}
+		fprintf (pf,"\n");
+	}*/
+
+	fclose (pf);
+}
+
+/*
+============
+LoadPortals
+============
+*/
+void LoadPortals (char *name)
+{
+	int			i, j, hint;
+	vportal_t	*p;
+	leaf_t		*l;
+	char		magic[80];
+	FILE		*f;
+	int			numpoints;
+	fixedWinding_t	*w;
+	int			leafnums[2];
+	visPlane_t	plane;
+	
+	if (!strcmp(name,"-"))
+		f = stdin;
+	else
+	{
+		f = fopen(name, "r");
+		if (!f)
+			Error ("LoadPortals: couldn't read %s\n",name);
+	}
+
+	if (fscanf (f,"%79s\n%i\n%i\n%i\n",magic, &portalclusters, &numportals, &numfaces) != 4)
+		Error ("LoadPortals: failed to read header");
+	if (strcmp(magic,PORTALFILE))
+		Error ("LoadPortals: not a portal file");
+
+	Sys_Printf ("%6i portalclusters\n", portalclusters);
+	Sys_Printf ("%6i numportals\n", numportals);
+	Sys_Printf ("%6i numfaces\n", numfaces);
+
+	// these counts should take advantage of 64 bit systems automatically
+	leafbytes = ((portalclusters+63)&~63)>>3;
+	leaflongs = leafbytes/sizeof(long);
+	
+	portalbytes = ((numportals*2+63)&~63)>>3;
+	portallongs = portalbytes/sizeof(long);
+
+	// each file portal is split into two memory portals
+	portals = safe_malloc(2*numportals*sizeof(vportal_t));
+	memset (portals, 0, 2*numportals*sizeof(vportal_t));
+	
+	leafs = safe_malloc(portalclusters*sizeof(leaf_t));
+	memset (leafs, 0, portalclusters*sizeof(leaf_t));
+
+	for (i = 0; i < portalclusters; i++)
+		leafs[i].merged = -1;
+
+	numBSPVisBytes = VIS_HEADER_SIZE + portalclusters*leafbytes;
+
+	if (numBSPVisBytes > MAX_MAP_VISIBILITY)
+	  Error("MAX_MAP_VISIBILITY exceeded");
+
+	((int *)bspVisBytes)[0] = portalclusters;
+	((int *)bspVisBytes)[1] = leafbytes;
+		
+	for (i=0, p=portals ; i<numportals ; i++)
+	{
+		if (fscanf (f, "%i %i %i ", &numpoints, &leafnums[0], &leafnums[1]) != 3)
+			Error ("LoadPortals: reading portal %i", i);
+		if (numpoints > MAX_POINTS_ON_WINDING)
+			Error ("LoadPortals: portal %i has too many points", i);
+		if ( (unsigned)leafnums[0] > portalclusters
+		|| (unsigned)leafnums[1] > portalclusters)
+			Error ("LoadPortals: reading portal %i", i);
+		if (fscanf (f, "%i ", &hint) != 1)
+			Error ("LoadPortals: reading hint state");
+		
+		w = p->winding = NewFixedWinding (numpoints);
+		w->numpoints = numpoints;
+		
+		for (j=0 ; j<numpoints ; j++)
+		{
+			double	v[3];
+			int		k;
+
+			// scanf into double, then assign to vec_t
+			// so we don't care what size vec_t is
+			if (fscanf (f, "(%lf %lf %lf ) "
+			, &v[0], &v[1], &v[2]) != 3)
+				Error ("LoadPortals: reading portal %i", i);
+			for (k=0 ; k<3 ; k++)
+				w->points[j][k] = v[k];
+		}
+		fscanf (f, "\n");
+		
+		// calc plane
+		PlaneFromWinding (w, &plane);
+
+		// create forward portal
+		l = &leafs[leafnums[0]];
+		if (l->numportals == MAX_PORTALS_ON_LEAF)
+			Error ("Leaf with too many portals");
+		l->portals[l->numportals] = p;
+		l->numportals++;
+		
+		p->num = i+1;
+		p->hint = hint;
+		p->winding = w;
+		VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
+		p->plane.dist = -plane.dist;
+		p->leaf = leafnums[1];
+		SetPortalSphere (p);
+		p++;
+		
+		// create backwards portal
+		l = &leafs[leafnums[1]];
+		if (l->numportals == MAX_PORTALS_ON_LEAF)
+			Error ("Leaf with too many portals");
+		l->portals[l->numportals] = p;
+		l->numportals++;
+		
+		p->num = i+1;
+		p->hint = hint;
+		p->winding = NewFixedWinding(w->numpoints);
+		p->winding->numpoints = w->numpoints;
+		for (j=0 ; j<w->numpoints ; j++)
+		{
+			VectorCopy (w->points[w->numpoints-1-j], p->winding->points[j]);
+		}
+
+		p->plane = plane;
+		p->leaf = leafnums[0];
+		SetPortalSphere (p);
+		p++;
+
+	}
+
+	faces = safe_malloc(2*numfaces*sizeof(vportal_t));
+	memset (faces, 0, 2*numfaces*sizeof(vportal_t));
+
+	faceleafs = safe_malloc(portalclusters*sizeof(leaf_t));
+	memset(faceleafs, 0, portalclusters*sizeof(leaf_t));
+
+	for (i = 0, p = faces; i < numfaces; i++)
+	{
+		if (fscanf (f, "%i %i ", &numpoints, &leafnums[0]) != 2)
+			Error ("LoadPortals: reading portal %i", i);
+
+		w = p->winding = NewFixedWinding (numpoints);
+		w->numpoints = numpoints;
+		
+		for (j=0 ; j<numpoints ; j++)
+		{
+			double	v[3];
+			int		k;
+
+			// scanf into double, then assign to vec_t
+			// so we don't care what size vec_t is
+			if (fscanf (f, "(%lf %lf %lf ) "
+			, &v[0], &v[1], &v[2]) != 3)
+				Error ("LoadPortals: reading portal %i", i);
+			for (k=0 ; k<3 ; k++)
+				w->points[j][k] = v[k];
+		}
+		fscanf (f, "\n");
+		
+		// calc plane
+		PlaneFromWinding (w, &plane);
+
+		l = &faceleafs[leafnums[0]];
+		l->merged = -1;
+		if (l->numportals == MAX_PORTALS_ON_LEAF)
+			Error ("Leaf with too many faces");
+		l->portals[l->numportals] = p;
+		l->numportals++;
+		
+		p->num = i+1;
+		p->winding = w;
+		// normal pointing out of the leaf
+		VectorSubtract (vec3_origin, plane.normal, p->plane.normal);
+		p->plane.dist = -plane.dist;
+		p->leaf = -1;
+		SetPortalSphere (p);
+		p++;
+	}
+	
+	fclose (f);
+}
+
+
+
+/*
+===========
+VisMain
+===========
+*/
+int VisMain (int argc, char **argv)
+{
+	char		portalfile[1024];
+	int			i;
+	
+	
+	/* note it */
+	Sys_Printf( "--- Vis ---\n" );
+	
+	/* process arguments */
+	for (i=1 ; i < (argc - 1) ; i++)
+	{
+		if (!strcmp(argv[i], "-fast")) {
+			Sys_Printf ("fastvis = true\n");
+			fastvis = qtrue;
+		} else if (!strcmp(argv[i], "-merge")) {
+			Sys_Printf ("merge = true\n");
+			mergevis = qtrue;
+		} else if (!strcmp(argv[i], "-nopassage")) {
+			Sys_Printf ("nopassage = true\n");
+			noPassageVis = qtrue;
+		} else if (!strcmp(argv[i], "-passageOnly")) {
+			Sys_Printf ("passageOnly = true\n");
+			passageVisOnly = qtrue;
+		} else if (!strcmp (argv[i],"-nosort")) {
+			Sys_Printf ("nosort = true\n");
+			nosort = qtrue;
+		} else if (!strcmp (argv[i],"-saveprt")) {
+			Sys_Printf ("saveprt = true\n");
+			saveprt = qtrue;
+		} else if (!strcmp (argv[i],"-tmpin")) {
+			strcpy (inbase, "/tmp");
+		} else if (!strcmp (argv[i],"-tmpout")) {
+			strcpy (outbase, "/tmp");
+		}
+		
+	
+		/* ydnar: -hint to merge all but hint portals */
+		else if( !strcmp( argv[ i ], "-hint" ) )
+		{
+			Sys_Printf( "hint = true\n" );
+			hint = qtrue;
+			mergevis = qtrue;
+		}
+		
+		else
+			Sys_Printf( "WARNING: Unknown option \"%s\"\n", argv[ i ] );
+	}
+
+	if( i != argc - 1 )
+		Error( "usage: vis [-threads #] [-level 0-4] [-fast] [-v] bspfile" );
+	
+
+	/* load the bsp */
+	sprintf( source, "%s%s", inbase, ExpandArg( argv[ i ] ) );
+	StripExtension( source );
+	strcat( source, ".bsp" );
+	Sys_Printf( "Loading %s\n", source );
+	LoadBSPFile( source );
+	
+	/* load the portal file */
+	sprintf( portalfile, "%s%s", inbase, ExpandArg( argv[ i ] ) );
+	StripExtension( portalfile );
+	strcat( portalfile, ".prt" );
+	Sys_Printf( "Loading %s\n", portalfile );
+	LoadPortals( portalfile );
+	
+	/* ydnar: for getting far plane */
+	ParseEntities();
+	
+	if( mergevis )
+	{
+		MergeLeaves();
+		MergeLeafPortals();
+	}
+	
+	CountActivePortals();
+	/* WritePortals( "maps/hints.prs" );*/
+	
+	Sys_Printf( "visdatasize:%i\n", numBSPVisBytes );
+	
+	CalcVis();
+	
+	/* delete the prt file */
+	if( !saveprt )
+		remove( portalfile );
+
+	/* write the bsp file */
+	Sys_Printf( "Writing %s\n", source );
+	WriteBSPFile( source );
+
+	return 0;
+}
diff --git a/tools/quake3/q3map2/visflow.c b/tools/quake3/q3map2/visflow.c
index 636ac5cb..880ab70d 100644
--- a/tools/quake3/q3map2/visflow.c
+++ b/tools/quake3/q3map2/visflow.c
@@ -1,1709 +1,1709 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define VISFLOW_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-
-/*
-
-  each portal will have a list of all possible to see from first portal
-
-  if (!thread->portalmightsee[portalnum])
-
-  portal mightsee
-
-  for p2 = all other portals in leaf
-	get sperating planes
-	for all portals that might be seen by p2
-		mark as unseen if not present in seperating plane
-	flood fill a new mightsee
-	save as passagemightsee
-
-
-  void CalcMightSee (leaf_t *leaf, 
-*/
-
-int CountBits (byte *bits, int numbits)
-{
-	int		i;
-	int		c;
-
-	c = 0;
-	for (i=0 ; i<numbits ; i++)
-		if (bits[i>>3] & (1<<(i&7)) )
-			c++;
-
-	return c;
-}
-
-int		c_fullskip;
-int		c_portalskip, c_leafskip;
-int		c_vistest, c_mighttest;
-
-int		c_chop, c_nochop;
-
-int		active;
-
-void CheckStack (leaf_t *leaf, threaddata_t *thread)
-{
-	pstack_t	*p, *p2;
-
-	for (p=thread->pstack_head.next ; p ; p=p->next)
-	{
-//		Sys_Printf ("=");
-		if (p->leaf == leaf)
-			Error ("CheckStack: leaf recursion");
-		for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
-			if (p2->leaf == p->leaf)
-				Error ("CheckStack: late leaf recursion");
-	}
-//	Sys_Printf ("\n");
-}
-
-
-fixedWinding_t *AllocStackWinding (pstack_t *stack)
-{
-	int		i;
-
-	for (i=0 ; i<3 ; i++)
-	{
-		if (stack->freewindings[i])
-		{
-			stack->freewindings[i] = 0;
-			return &stack->windings[i];
-		}
-	}
-
-	Error ("AllocStackWinding: failed");
-
-	return NULL;
-}
-
-void FreeStackWinding (fixedWinding_t *w, pstack_t *stack)
-{
-	int		i;
-
-	i = w - stack->windings;
-
-	if (i<0 || i>2)
-		return;		// not from local
-
-	if (stack->freewindings[i])
-		Error ("FreeStackWinding: allready free");
-	stack->freewindings[i] = 1;
-}
-
-/*
-==============
-VisChopWinding
-
-==============
-*/
-fixedWinding_t	*VisChopWinding (fixedWinding_t *in, pstack_t *stack, visPlane_t *split)
-{
-	vec_t	dists[128];
-	int		sides[128];
-	int		counts[3];
-	vec_t	dot;
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	fixedWinding_t	*neww;
-
-	counts[0] = counts[1] = counts[2] = 0;
-
-	// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->points[i], split->normal);
-		dot -= split->dist;
-		dists[i] = dot;
-		if (dot > ON_EPSILON)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -ON_EPSILON)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-
-	if (!counts[1])
-		return in;		// completely on front side
-	
-	if (!counts[0])
-	{
-		FreeStackWinding (in, stack);
-		return NULL;
-	}
-
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	neww = AllocStackWinding (stack);
-
-	neww->numpoints = 0;
-
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->points[i];
-
-		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
-		{
-			FreeStackWinding (neww, stack);
-			return in;		// can't chop -- fall back to original
-		}
-
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, neww->points[neww->numpoints]);
-			neww->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, neww->points[neww->numpoints]);
-			neww->numpoints++;
-		}
-		
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
-		{
-			FreeStackWinding (neww, stack);
-			return in;		// can't chop -- fall back to original
-		}
-
-		// generate a split point
-		p2 = in->points[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (split->normal[j] == 1)
-				mid[j] = split->dist;
-			else if (split->normal[j] == -1)
-				mid[j] = -split->dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, neww->points[neww->numpoints]);
-		neww->numpoints++;
-	}
-	
-	// free the original winding
-	FreeStackWinding (in, stack);
-	
-	return neww;
-}
-
-/*
-==============
-ClipToSeperators
-
-Source, pass, and target are an ordering of portals.
-
-Generates seperating planes canidates by taking two points from source and one
-point from pass, and clips target by them.
-
-If target is totally clipped away, that portal can not be seen through.
-
-Normal clip keeps target on the same side as pass, which is correct if the
-order goes source, pass, target.  If the order goes pass, source, target then
-flipclip should be set.
-==============
-*/
-fixedWinding_t	*ClipToSeperators (fixedWinding_t *source, fixedWinding_t *pass, fixedWinding_t *target, qboolean flipclip, pstack_t *stack)
-{
-	int			i, j, k, l;
-	visPlane_t		plane;
-	vec3_t		v1, v2;
-	float		d;
-	vec_t		length;
-	int			counts[3];
-	qboolean		fliptest;
-
-	// check all combinations	
-	for (i=0 ; i<source->numpoints ; i++)
-	{
-		l = (i+1)%source->numpoints;
-		VectorSubtract (source->points[l] , source->points[i], v1);
-
-		// find a vertex of pass that makes a plane that puts all of the
-		// vertexes of pass on the front side and all of the vertexes of
-		// source on the back side
-		for (j=0 ; j<pass->numpoints ; j++)
-		{
-			VectorSubtract (pass->points[j], source->points[i], v2);
-
-			plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
-			plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
-			plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
-			
-			// if points don't make a valid plane, skip it
-
-			length = plane.normal[0] * plane.normal[0]
-			+ plane.normal[1] * plane.normal[1]
-			+ plane.normal[2] * plane.normal[2];
-			
-			if (length < ON_EPSILON)
-				continue;
-
-			length = 1/sqrt(length);
-			
-			plane.normal[0] *= length;
-			plane.normal[1] *= length;
-			plane.normal[2] *= length;
-
-			plane.dist = DotProduct (pass->points[j], plane.normal);
-
-			//
-			// find out which side of the generated seperating plane has the
-			// source portal
-			//
-#if 1
-			fliptest = qfalse;
-			for (k=0 ; k<source->numpoints ; k++)
-			{
-				if (k == i || k == l)
-					continue;
-				d = DotProduct (source->points[k], plane.normal) - plane.dist;
-				if (d < -ON_EPSILON)
-				{	// source is on the negative side, so we want all
-					// pass and target on the positive side
-					fliptest = qfalse;
-					break;
-				}
-				else if (d > ON_EPSILON)
-				{	// source is on the positive side, so we want all
-					// pass and target on the negative side
-					fliptest = qtrue;
-					break;
-				}
-			}
-			if (k == source->numpoints)
-				continue;		// planar with source portal
-#else
-			fliptest = flipclip;
-#endif
-			//
-			// flip the normal if the source portal is backwards
-			//
-			if (fliptest)
-			{
-				VectorSubtract (vec3_origin, plane.normal, plane.normal);
-				plane.dist = -plane.dist;
-			}
-#if 1
-			//
-			// if all of the pass portal points are now on the positive side,
-			// this is the seperating plane
-			//
-			counts[0] = counts[1] = counts[2] = 0;
-			for (k=0 ; k<pass->numpoints ; k++)
-			{
-				if (k==j)
-					continue;
-				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-				if (d < -ON_EPSILON)
-					break;
-				else if (d > ON_EPSILON)
-					counts[0]++;
-				else
-					counts[2]++;
-			}
-			if (k != pass->numpoints)
-				continue;	// points on negative side, not a seperating plane
-				
-			if (!counts[0])
-				continue;	// planar with seperating plane
-#else
-			k = (j+1)%pass->numpoints;
-			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-			if (d < -ON_EPSILON)
-				continue;
-			k = (j+pass->numpoints-1)%pass->numpoints;
-			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-			if (d < -ON_EPSILON)
-				continue;			
-#endif
-			//
-			// flip the normal if we want the back side
-			//
-			if (flipclip)
-			{
-				VectorSubtract (vec3_origin, plane.normal, plane.normal);
-				plane.dist = -plane.dist;
-			}
-
-#ifdef SEPERATORCACHE
-			stack->seperators[flipclip][stack->numseperators[flipclip]] = plane;
-			if (++stack->numseperators[flipclip] >= MAX_SEPERATORS)
-				Error("MAX_SEPERATORS");
-#endif
-			//MrE: fast check first
-			d = DotProduct (stack->portal->origin, plane.normal) - plane.dist;
-			//if completely at the back of the seperator plane
-			if (d < -stack->portal->radius)
-				return NULL;
-			//if completely on the front of the seperator plane
-			if (d > stack->portal->radius)
-				break;
-
-			//
-			// clip target by the seperating plane
-			//
-			target = VisChopWinding (target, stack, &plane);
-			if (!target)
-				return NULL;		// target is not visible
-
-			break;		// optimization by Antony Suter
-		}
-	}
-	
-	return target;
-}
-
-/*
-==================
-RecursiveLeafFlow
-
-Flood fill through the leafs
-If src_portal is NULL, this is the originating leaf
-==================
-*/
-void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
-{
-	pstack_t	stack;
-	vportal_t	*p;
-	visPlane_t		backplane;
-	leaf_t 		*leaf;
-	int			i, j, n;
-	long		*test, *might, *prevmight, *vis, more;
-	int			pnum;
-
-	thread->c_chains++;
-
-	leaf = &leafs[leafnum];
-//	CheckStack (leaf, thread);
-
-	prevstack->next = &stack;
-
-	stack.next = NULL;
-	stack.leaf = leaf;
-	stack.portal = NULL;
-	stack.depth = prevstack->depth + 1;
-
-#ifdef SEPERATORCACHE
-	stack.numseperators[0] = 0;
-	stack.numseperators[1] = 0;
-#endif
-
-	might = (long *)stack.mightsee;
-	vis = (long *)thread->base->portalvis;
-	
-	// check all portals for flowing into other leafs	
-	for (i = 0; i < leaf->numportals; i++)
-	{
-		p = leaf->portals[i];
-		if (p->removed)
-			continue;
-		pnum = p - portals;
-
-		/* MrE: portal trace debug code
-		{
-			int portaltrace[] = {13, 16, 17, 37};
-			pstack_t *s;
-
-			s = &thread->pstack_head;
-			for (j = 0; s->next && j < sizeof(portaltrace)/sizeof(int) - 1; j++, s = s->next)
-			{
-				if (s->portal->num != portaltrace[j])
-					break;
-			}
-			if (j >= sizeof(portaltrace)/sizeof(int) - 1)
-			{
-				if (p->num == portaltrace[j])
-					n = 0; //traced through all the portals
-			}
-		}
-		*/
-
-		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
-		{
-			continue;	// can't possibly see it
-		}
-
-		// if the portal can't see anything we haven't allready seen, skip it
-		if (p->status == stat_done)
-		{
-			test = (long *)p->portalvis;
-		}
-		else
-		{
-			test = (long *)p->portalflood;
-		}
-
-		more = 0;
-		prevmight = (long *)prevstack->mightsee;
-		for (j=0 ; j<portallongs ; j++)
-		{
-			might[j] = prevmight[j] & test[j];
-			more |= (might[j] & ~vis[j]);
-		}
-		
-		if (!more && 
-			(thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
-		{	// can't see anything new
-			continue;
-		}
-
-		// get plane of portal, point normal into the neighbor leaf
-		stack.portalplane = p->plane;
-		VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
-		backplane.dist = -p->plane.dist;
-		
-//		c_portalcheck++;
-		
-		stack.portal = p;
-		stack.next = NULL;
-		stack.freewindings[0] = 1;
-		stack.freewindings[1] = 1;
-		stack.freewindings[2] = 1;
-		
-#if 1
-		{
-			float d;
-
-			d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
-			d -= thread->pstack_head.portalplane.dist;
-			if (d < -p->radius)
-			{
-				continue;
-			}
-			else if (d > p->radius)
-			{
-				stack.pass = p->winding;
-			}
-			else	
-			{
-				stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
-				if (!stack.pass)
-					continue;
-			}
-		}
-#else
-		stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
-		if (!stack.pass)
-			continue;
-#endif
-
-	
-#if 1
-		{
-			float d;
-
-			d = DotProduct (thread->base->origin, p->plane.normal);
-			d -= p->plane.dist;
-			//MrE: vis-bug fix
-			//if (d > p->radius)
-			if (d > thread->base->radius)
-			{
-				continue;
-			}
-			//MrE: vis-bug fix
-			//if (d < -p->radius)
-			else if (d < -thread->base->radius)
-			{
-				stack.source = prevstack->source;
-			}
-			else	
-			{
-				stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
-				//FIXME: shouldn't we create a new source origin and radius for fast checks?
-				if (!stack.source)
-					continue;
-			}
-		}
-#else
-		stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
-		if (!stack.source)
-			continue;
-#endif
-
-		if (!prevstack->pass)
-		{	// the second leaf can only be blocked if coplanar
-
-			// mark the portal as visible
-			thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
-
-			RecursiveLeafFlow (p->leaf, thread, &stack);
-			continue;
-		}
-
-#ifdef SEPERATORCACHE
-		if (stack.numseperators[0])
-		{
-			for (n = 0; n < stack.numseperators[0]; n++)
-			{
-				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
-				if (!stack.pass)
-					break;		// target is not visible
-			}
-			if (n < stack.numseperators[0])
-				continue;
-		}
-		else
-		{
-			stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
-		}
-#else
-		stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
-#endif
-		if (!stack.pass)
-			continue;
-
-#ifdef SEPERATORCACHE
-		if (stack.numseperators[1])
-		{
-			for (n = 0; n < stack.numseperators[1]; n++)
-			{
-				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
-				if (!stack.pass)
-					break;		// target is not visible
-			}
-		}
-		else
-		{
-			stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
-		}
-#else
-		stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
-#endif
-		if (!stack.pass)
-			continue;
-
-		// mark the portal as visible
-		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
-
-		// flow through it for real
-		RecursiveLeafFlow (p->leaf, thread, &stack);
-		//
-		stack.next = NULL;
-	}	
-}
-
-/*
-===============
-PortalFlow
-
-generates the portalvis bit vector
-===============
-*/
-void PortalFlow (int portalnum)
-{
-	threaddata_t	data;
-	int				i;
-	vportal_t		*p;
-	int				c_might, c_can;
-
-#ifdef MREDEBUG
-	Sys_Printf("\r%6d", portalnum);
-#endif
-
-	p = sorted_portals[portalnum];
-
-	if (p->removed)
-	{
-		p->status = stat_done;
-		return;
-	}
-
-	p->status = stat_working;
-
-	c_might = CountBits (p->portalflood, numportals*2);
-
-	memset (&data, 0, sizeof(data));
-	data.base = p;
-	
-	data.pstack_head.portal = p;
-	data.pstack_head.source = p->winding;
-	data.pstack_head.portalplane = p->plane;
-	data.pstack_head.depth = 0;
-	for (i=0 ; i<portallongs ; i++)
-		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
-
-	RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
-
-	p->status = stat_done;
-
-	c_can = CountBits (p->portalvis, numportals*2);
-
-	Sys_FPrintf (SYS_VRB,"portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
-		(int)(p - portals),	c_might, c_can, data.c_chains);
-}
-
-/*
-==================
-RecursivePassageFlow
-==================
-*/
-void RecursivePassageFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
-{
-	pstack_t	stack;
-	vportal_t	*p;
-	leaf_t 		*leaf;
-	passage_t	*passage, *nextpassage;
-	int			i, j;
-	long		*might, *vis, *prevmight, *cansee, *portalvis, more;
-	int			pnum;
-
-	leaf = &leafs[portal->leaf];
-
-	prevstack->next = &stack;
-
-	stack.next = NULL;
-	stack.depth = prevstack->depth + 1;
-
-	vis = (long *)thread->base->portalvis;
-
-	passage = portal->passages;
-	nextpassage = passage;
-	// check all portals for flowing into other leafs	
-	for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
-	{
-		p = leaf->portals[i];
-		if ( p->removed ) {
-			continue;
-		}
-		nextpassage = passage->next;
-		pnum = p - portals;
-
-		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) {
-			continue;	// can't possibly see it
-		}
-
-		// mark the portal as visible
-		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
-
-		prevmight = (long *)prevstack->mightsee;
-		cansee = (long *)passage->cansee;
-		might = (long *)stack.mightsee;
-		memcpy(might, prevmight, portalbytes);
-		if (p->status == stat_done)
-			portalvis = (long *) p->portalvis;
-		else
-			portalvis = (long *) p->portalflood;
-		more = 0;
-		for (j = 0; j < portallongs; j++)
-		{
-			if (*might)
-			{
-				*might &= *cansee++ & *portalvis++;
-				more |= (*might & ~vis[j]);
-			}
-			else
-			{
-				cansee++;
-				portalvis++;
-			}
-			might++;
-		}
-
-		if ( !more ) {
-			// can't see anything new
-			continue;
-		}
-
-		// flow through it for real
-		RecursivePassageFlow(p, thread, &stack);
-
-		stack.next = NULL;
-	}
-}
-
-/*
-===============
-PassageFlow
-===============
-*/
-void PassageFlow (int portalnum)
-{
-	threaddata_t	data;
-	int				i;
-	vportal_t		*p;
-//	int				c_might, c_can;
-
-#ifdef MREDEBUG
-	Sys_Printf("\r%6d", portalnum);
-#endif
-
-	p = sorted_portals[portalnum];
-
-	if (p->removed)
-	{
-		p->status = stat_done;
-		return;
-	}
-
-	p->status = stat_working;
-
-//	c_might = CountBits (p->portalflood, numportals*2);
-
-	memset (&data, 0, sizeof(data));
-	data.base = p;
-	
-	data.pstack_head.portal = p;
-	data.pstack_head.source = p->winding;
-	data.pstack_head.portalplane = p->plane;
-	data.pstack_head.depth = 0;
-	for (i=0 ; i<portallongs ; i++)
-		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
-
-	RecursivePassageFlow (p, &data, &data.pstack_head);
-
-	p->status = stat_done;
-
-	/*
-	c_can = CountBits (p->portalvis, numportals*2);
-
-	Sys_FPrintf (SYS_VRB,"portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
-		(int)(p - portals),	c_might, c_can, data.c_chains);
-	*/
-}
-
-/*
-==================
-RecursivePassagePortalFlow
-==================
-*/
-void RecursivePassagePortalFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
-{
-	pstack_t	stack;
-	vportal_t	*p;
-	leaf_t 		*leaf;
-	visPlane_t		backplane;
-	passage_t	*passage, *nextpassage;
-	int			i, j, n;
-	long		*might, *vis, *prevmight, *cansee, *portalvis, more;
-	int			pnum;
-
-//	thread->c_chains++;
-
-	leaf = &leafs[portal->leaf];
-//	CheckStack (leaf, thread);
-
-	prevstack->next = &stack;
-
-	stack.next = NULL;
-	stack.leaf = leaf;
-	stack.portal = NULL;
-	stack.depth = prevstack->depth + 1;
-
-#ifdef SEPERATORCACHE
-	stack.numseperators[0] = 0;
-	stack.numseperators[1] = 0;
-#endif
-
-	vis = (long *)thread->base->portalvis;
-
-	passage = portal->passages;
-	nextpassage = passage;
-	// check all portals for flowing into other leafs	
-	for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
-	{
-		p = leaf->portals[i];
-		if (p->removed)
-			continue;
-		nextpassage = passage->next;
-		pnum = p - portals;
-
-		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
-			continue;	// can't possibly see it
-
-		prevmight = (long *)prevstack->mightsee;
-		cansee = (long *)passage->cansee;
-		might = (long *)stack.mightsee;
-		memcpy(might, prevmight, portalbytes);
-		if (p->status == stat_done)
-			portalvis = (long *) p->portalvis;
-		else
-			portalvis = (long *) p->portalflood;
-		more = 0;
-		for (j = 0; j < portallongs; j++)
-		{
-			if (*might)
-			{
-				*might &= *cansee++ & *portalvis++;
-				more |= (*might & ~vis[j]);
-			}
-			else
-			{
-				cansee++;
-				portalvis++;
-			}
-			might++;
-		}
-
-		if (!more && (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
-		{	// can't see anything new
-			continue;
-		}
-
-		// get plane of portal, point normal into the neighbor leaf
-		stack.portalplane = p->plane;
-		VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
-		backplane.dist = -p->plane.dist;
-		
-//		c_portalcheck++;
-		
-		stack.portal = p;
-		stack.next = NULL;
-		stack.freewindings[0] = 1;
-		stack.freewindings[1] = 1;
-		stack.freewindings[2] = 1;
-
-#if 1
-		{
-			float d;
-
-			d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
-			d -= thread->pstack_head.portalplane.dist;
-			if (d < -p->radius)
-			{
-				continue;
-			}
-			else if (d > p->radius)
-			{
-				stack.pass = p->winding;
-			}
-			else	
-			{
-				stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
-				if (!stack.pass)
-					continue;
-			}
-		}
-#else
-		stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
-		if (!stack.pass)
-			continue;
-#endif
-
-	
-#if 1
-		{
-			float d;
-
-			d = DotProduct (thread->base->origin, p->plane.normal);
-			d -= p->plane.dist;
-			//MrE: vis-bug fix
-			//if (d > p->radius)
-			if (d > thread->base->radius)
-			{
-				continue;
-			}
-			//MrE: vis-bug fix
-			//if (d < -p->radius)
-			else if (d < -thread->base->radius)
-			{
-				stack.source = prevstack->source;
-			}
-			else	
-			{
-				stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
-				//FIXME: shouldn't we create a new source origin and radius for fast checks?
-				if (!stack.source)
-					continue;
-			}
-		}
-#else
-		stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
-		if (!stack.source)
-			continue;
-#endif
-
-		if (!prevstack->pass)
-		{	// the second leaf can only be blocked if coplanar
-
-			// mark the portal as visible
-			thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
-
-			RecursivePassagePortalFlow (p, thread, &stack);
-			continue;
-		}
-
-#ifdef SEPERATORCACHE
-		if (stack.numseperators[0])
-		{
-			for (n = 0; n < stack.numseperators[0]; n++)
-			{
-				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
-				if (!stack.pass)
-					break;		// target is not visible
-			}
-			if (n < stack.numseperators[0])
-				continue;
-		}
-		else
-		{
-			stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
-		}
-#else
-		stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
-#endif
-		if (!stack.pass)
-			continue;
-
-#ifdef SEPERATORCACHE
-		if (stack.numseperators[1])
-		{
-			for (n = 0; n < stack.numseperators[1]; n++)
-			{
-				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
-				if (!stack.pass)
-					break;		// target is not visible
-			}
-		}
-		else
-		{
-			stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
-		}
-#else
-		stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
-#endif
-		if (!stack.pass)
-			continue;
-
-		// mark the portal as visible
-		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
-
-		// flow through it for real
-		RecursivePassagePortalFlow(p, thread, &stack);
-		//
-		stack.next = NULL;
-	}
-}
-
-/*
-===============
-PassagePortalFlow
-===============
-*/
-void PassagePortalFlow (int portalnum)
-{
-	threaddata_t	data;
-	int				i;
-	vportal_t		*p;
-//	int				c_might, c_can;
-
-#ifdef MREDEBUG
-	Sys_Printf("\r%6d", portalnum);
-#endif
-
-	p = sorted_portals[portalnum];
-
-	if (p->removed)
-	{
-		p->status = stat_done;
-		return;
-	}
-
-	p->status = stat_working;
-
-//	c_might = CountBits (p->portalflood, numportals*2);
-
-	memset (&data, 0, sizeof(data));
-	data.base = p;
-	
-	data.pstack_head.portal = p;
-	data.pstack_head.source = p->winding;
-	data.pstack_head.portalplane = p->plane;
-	data.pstack_head.depth = 0;
-	for (i=0 ; i<portallongs ; i++)
-		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
-
-	RecursivePassagePortalFlow (p, &data, &data.pstack_head);
-
-	p->status = stat_done;
-
-	/*
-	c_can = CountBits (p->portalvis, numportals*2);
-
-	Sys_FPrintf (SYS_VRB,"portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
-		(int)(p - portals),	c_might, c_can, data.c_chains);
-	*/
-}
-
-fixedWinding_t *PassageChopWinding (fixedWinding_t *in, fixedWinding_t *out, visPlane_t *split)
-{
-	vec_t	dists[128];
-	int		sides[128];
-	int		counts[3];
-	vec_t	dot;
-	int		i, j;
-	vec_t	*p1, *p2;
-	vec3_t	mid;
-	fixedWinding_t	*neww;
-
-	counts[0] = counts[1] = counts[2] = 0;
-
-	// determine sides for each point
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		dot = DotProduct (in->points[i], split->normal);
-		dot -= split->dist;
-		dists[i] = dot;
-		if (dot > ON_EPSILON)
-			sides[i] = SIDE_FRONT;
-		else if (dot < -ON_EPSILON)
-			sides[i] = SIDE_BACK;
-		else
-		{
-			sides[i] = SIDE_ON;
-		}
-		counts[sides[i]]++;
-	}
-
-	if (!counts[1])
-		return in;		// completely on front side
-	
-	if (!counts[0])
-	{
-		return NULL;
-	}
-
-	sides[i] = sides[0];
-	dists[i] = dists[0];
-	
-	neww = out;
-
-	neww->numpoints = 0;
-
-	for (i=0 ; i<in->numpoints ; i++)
-	{
-		p1 = in->points[i];
-
-		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
-		{
-			return in;		// can't chop -- fall back to original
-		}
-
-		if (sides[i] == SIDE_ON)
-		{
-			VectorCopy (p1, neww->points[neww->numpoints]);
-			neww->numpoints++;
-			continue;
-		}
-	
-		if (sides[i] == SIDE_FRONT)
-		{
-			VectorCopy (p1, neww->points[neww->numpoints]);
-			neww->numpoints++;
-		}
-		
-		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
-			continue;
-			
-		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
-		{
-			return in;		// can't chop -- fall back to original
-		}
-
-		// generate a split point
-		p2 = in->points[(i+1)%in->numpoints];
-		
-		dot = dists[i] / (dists[i]-dists[i+1]);
-		for (j=0 ; j<3 ; j++)
-		{	// avoid round off error when possible
-			if (split->normal[j] == 1)
-				mid[j] = split->dist;
-			else if (split->normal[j] == -1)
-				mid[j] = -split->dist;
-			else
-				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
-		}
-			
-		VectorCopy (mid, neww->points[neww->numpoints]);
-		neww->numpoints++;
-	}
-	
-	return neww;
-}
-
-/*
-===============
-AddSeperators
-===============
-*/
-int AddSeperators (fixedWinding_t *source, fixedWinding_t *pass, qboolean flipclip, visPlane_t *seperators, int maxseperators)
-{
-	int			i, j, k, l;
-	visPlane_t		plane;
-	vec3_t		v1, v2;
-	float		d;
-	vec_t		length;
-	int			counts[3], numseperators;
-	qboolean	fliptest;
-
-	numseperators = 0;
-	// check all combinations	
-	for (i=0 ; i<source->numpoints ; i++)
-	{
-		l = (i+1)%source->numpoints;
-		VectorSubtract (source->points[l] , source->points[i], v1);
-
-		// find a vertex of pass that makes a plane that puts all of the
-		// vertexes of pass on the front side and all of the vertexes of
-		// source on the back side
-		for (j=0 ; j<pass->numpoints ; j++)
-		{
-			VectorSubtract (pass->points[j], source->points[i], v2);
-
-			plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
-			plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
-			plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
-			
-			// if points don't make a valid plane, skip it
-
-			length = plane.normal[0] * plane.normal[0]
-			+ plane.normal[1] * plane.normal[1]
-			+ plane.normal[2] * plane.normal[2];
-			
-			if (length < ON_EPSILON)
-				continue;
-
-			length = 1/sqrt(length);
-			
-			plane.normal[0] *= length;
-			plane.normal[1] *= length;
-			plane.normal[2] *= length;
-
-			plane.dist = DotProduct (pass->points[j], plane.normal);
-
-			//
-			// find out which side of the generated seperating plane has the
-			// source portal
-			//
-#if 1
-			fliptest = qfalse;
-			for (k=0 ; k<source->numpoints ; k++)
-			{
-				if (k == i || k == l)
-					continue;
-				d = DotProduct (source->points[k], plane.normal) - plane.dist;
-				if (d < -ON_EPSILON)
-				{	// source is on the negative side, so we want all
-					// pass and target on the positive side
-					fliptest = qfalse;
-					break;
-				}
-				else if (d > ON_EPSILON)
-				{	// source is on the positive side, so we want all
-					// pass and target on the negative side
-					fliptest = qtrue;
-					break;
-				}
-			}
-			if (k == source->numpoints)
-				continue;		// planar with source portal
-#else
-			fliptest = flipclip;
-#endif
-			//
-			// flip the normal if the source portal is backwards
-			//
-			if (fliptest)
-			{
-				VectorSubtract (vec3_origin, plane.normal, plane.normal);
-				plane.dist = -plane.dist;
-			}
-#if 1
-			//
-			// if all of the pass portal points are now on the positive side,
-			// this is the seperating plane
-			//
-			counts[0] = counts[1] = counts[2] = 0;
-			for (k=0 ; k<pass->numpoints ; k++)
-			{
-				if (k==j)
-					continue;
-				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-				if (d < -ON_EPSILON)
-					break;
-				else if (d > ON_EPSILON)
-					counts[0]++;
-				else
-					counts[2]++;
-			}
-			if (k != pass->numpoints)
-				continue;	// points on negative side, not a seperating plane
-				
-			if (!counts[0])
-				continue;	// planar with seperating plane
-#else
-			k = (j+1)%pass->numpoints;
-			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-			if (d < -ON_EPSILON)
-				continue;
-			k = (j+pass->numpoints-1)%pass->numpoints;
-			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
-			if (d < -ON_EPSILON)
-				continue;			
-#endif
-			//
-			// flip the normal if we want the back side
-			//
-			if (flipclip)
-			{
-				VectorSubtract (vec3_origin, plane.normal, plane.normal);
-				plane.dist = -plane.dist;
-			}
-
-			if (numseperators >= maxseperators)
-				Error("max seperators");
-			seperators[numseperators] = plane;
-			numseperators++;
-			break;
-		}
-	}
-	return numseperators;
-}
-
-/*
-===============
-CreatePassages
-
-MrE: create passages from one portal to all the portals in the leaf the portal leads to
-	 every passage has a cansee bit string with all the portals that can be
-	 seen through the passage
-===============
-*/
-void CreatePassages(int portalnum)
-{
-	int				i, j, k, n, numseperators, numsee;
-	float			d;
-	vportal_t		*portal, *p, *target;
-	leaf_t			*leaf;
-	passage_t		*passage, *lastpassage;
-	visPlane_t		seperators[MAX_SEPERATORS*2];
-	fixedWinding_t	*w;
-	fixedWinding_t	in, out, *res;
-	
-	
-#ifdef MREDEBUG
-	Sys_Printf("\r%6d", portalnum);
-#endif
-
-	portal = sorted_portals[portalnum];
-
-	if (portal->removed)
-	{
-		portal->status = stat_done;
-		return;
-	}
-
-	lastpassage = NULL;
-	leaf = &leafs[portal->leaf];
-	for (i = 0; i < leaf->numportals; i++)
-	{
-		target = leaf->portals[i];
-		if (target->removed)
-			continue;
-
-		passage = (passage_t *) safe_malloc(sizeof(passage_t) + portalbytes);
-		memset(passage, 0, sizeof(passage_t) + portalbytes);
-		numseperators = AddSeperators(portal->winding, target->winding, qfalse, seperators, MAX_SEPERATORS*2);
-		numseperators += AddSeperators(target->winding, portal->winding, qtrue, &seperators[numseperators], MAX_SEPERATORS*2-numseperators);
-
-		passage->next = NULL;
-		if (lastpassage)
-			lastpassage->next = passage;
-		else
-			portal->passages = passage;
-		lastpassage = passage;
-
-		numsee = 0;
-		//create the passage->cansee
-		for (j = 0; j < numportals * 2; j++)
-		{
-			p = &portals[j];
-			if (p->removed)
-				continue;
-			if ( ! (target->portalflood[j >> 3] & (1<<(j&7)) ) )
-				continue;
-			if ( ! (portal->portalflood[j >> 3] & (1<<(j&7)) ) )
-				continue;
-			for (k = 0; k < numseperators; k++)
-			{
-				//
-				d = DotProduct (p->origin, seperators[k].normal) - seperators[k].dist;
-				//if completely at the back of the seperator plane
-				if (d < -p->radius + ON_EPSILON)
-					break;
-				w = p->winding;
-				for (n = 0; n < w->numpoints; n++)
-				{
-					d = DotProduct (w->points[n], seperators[k].normal) - seperators[k].dist;
-					//if at the front of the seperator
-					if (d > ON_EPSILON)
-						break;
-				}
-				//if no points are at the front of the seperator
-				if (n >= w->numpoints)
-					break;
-			}
-			if (k < numseperators)
-				continue;
-			
-			/* explitive deleted */
-			
-			
-			/* ydnar: prefer correctness to stack overflow  */
-			//% memcpy( &in, p->winding, (int)((fixedWinding_t *)0)->points[p->winding->numpoints] );
-			if( p->winding->numpoints <= MAX_POINTS_ON_FIXED_WINDING )
-				memcpy( &in, p->winding, (int) &(((fixedWinding_t*) 0)->points[ p->winding->numpoints ]) );
-			else
-				memcpy( &in, p->winding, sizeof( fixedWinding_t ) );
-			
-			
-			for( k = 0; k < numseperators; k++ )
-			{
-				/* ydnar: this is a shitty crutch */
-				if( in.numpoints > MAX_POINTS_ON_FIXED_WINDING )
-				{
-					//% Sys_Printf( "[%d]", p->winding->numpoints );
-					in.numpoints = MAX_POINTS_ON_FIXED_WINDING;
-				}
-				
-				res = PassageChopWinding( &in, &out, &seperators[ k ] );
-				if( res == &out )
-					memcpy( &in, &out, sizeof( fixedWinding_t ) );
-
-			
-				if( res == NULL )
-					break;
-			}
-			if (k < numseperators)
-				continue;
-			passage->cansee[j >> 3] |= (1<<(j&7));
-			numsee++;
-		}
-	}
-}
-
-void PassageMemory(void)
-{
-	int i, j, totalmem, totalportals;
-	vportal_t *portal, *target;
-	leaf_t *leaf;
-
-	totalmem = 0;
-	totalportals = 0;
-	for (i = 0; i < numportals; i++)
-	{
-		portal = sorted_portals[i];
-		if (portal->removed)
-			continue;
-		leaf = &leafs[portal->leaf];
-		for (j = 0; j < leaf->numportals; j++)
-		{
-			target = leaf->portals[j];
-			if (target->removed)
-				continue;
-			totalmem += sizeof(passage_t) + portalbytes;
-			totalportals++;
-		}
-	}
-	Sys_Printf("%7i average number of passages per leaf\n", totalportals / numportals);
-	Sys_Printf("%7i MB required passage memory\n", totalmem >> 10 >> 10);
-}
-
-/*
-===============================================================================
-
-This is a rough first-order aproximation that is used to trivially reject some
-of the final calculations.
-
-
-Calculates portalfront and portalflood bit vectors
-
-thinking about:
-
-typedef struct passage_s
-{
-	struct passage_s	*next;
-	struct portal_s		*to;
-	stryct sep_s		*seperators;
-	byte				*mightsee;
-} passage_t;
-
-typedef struct portal_s
-{
-	struct passage_s	*passages;
-	int					leaf;		// leaf portal faces into
-} portal_s;
-
-leaf = portal->leaf
-clear 
-for all portals
-
-
-calc portal visibility
-	clear bit vector
-	for all passages
-		passage visibility
-
-
-for a portal to be visible to a passage, it must be on the front of
-all seperating planes, and both portals must be behind the new portal
-
-===============================================================================
-*/
-
-int		c_flood, c_vis;
-
-
-/*
-==================
-SimpleFlood
-
-==================
-*/
-void SimpleFlood (vportal_t *srcportal, int leafnum)
-{
-	int		i;
-	leaf_t	*leaf;
-	vportal_t	*p;
-	int		pnum;
-
-	leaf = &leafs[leafnum];
-	
-	for (i=0 ; i<leaf->numportals ; i++)
-	{
-		p = leaf->portals[i];
-		if (p->removed)
-			continue;
-		pnum = p - portals;
-		if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) )
-			continue;
-
-		if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) )
-			continue;
-
-		srcportal->portalflood[pnum>>3] |= (1<<(pnum&7));
-		
-		SimpleFlood (srcportal, p->leaf);
-	}
-}
-
-/*
-==============
-BasePortalVis
-==============
-*/
-void BasePortalVis( int portalnum )
-{
-	int			j, k;
-	vportal_t	*tp, *p;
-	float		d;
-	fixedWinding_t	*w;
-	vec3_t		dir;
-	
-
-	p = portals+portalnum;
-
-	if (p->removed)
-		return;
-
-	p->portalfront = safe_malloc (portalbytes);
-	memset (p->portalfront, 0, portalbytes);
-
-	p->portalflood = safe_malloc (portalbytes);
-	memset (p->portalflood, 0, portalbytes);
-	
-	p->portalvis = safe_malloc (portalbytes);
-	memset (p->portalvis, 0, portalbytes);
-	
-	for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
-	{
-		if( j == portalnum )
-			continue;
-		if( tp->removed )
-			continue;
-
-		/* ydnar: this is old farplane vis code from mre */
-		/*
-		if (farplanedist >= 0)
-		{
-			vec3_t dir;
-			VectorSubtract(p->origin, tp->origin, dir);
-			if (VectorLength(dir) > farplanedist - p->radius - tp->radius)
-				continue;
-		}
-		*/
-		
-		/* ydnar: this is known-to-be-working farplane code */
-		if( farPlaneDist > 0.0f )
-		{
-			VectorSubtract( p->origin, tp->origin, dir );
-			if( VectorLength( dir ) - p->radius - tp->radius > farPlaneDist )
-				continue;
-		}
-		
-		
-		w = tp->winding;
-		for (k=0 ; k<w->numpoints ; k++)
-		{
-			d = DotProduct (w->points[k], p->plane.normal)
-				- p->plane.dist;
-			if (d > ON_EPSILON)
-				break;
-		}
-		if (k == w->numpoints)
-			continue;	// no points on front
-
-		w = p->winding;
-		for (k=0 ; k<w->numpoints ; k++)
-		{
-			d = DotProduct (w->points[k], tp->plane.normal)
-				- tp->plane.dist;
-			if (d < -ON_EPSILON)
-				break;
-		}
-		if (k == w->numpoints)
-			continue;	// no points on front
-
-		p->portalfront[j>>3] |= (1<<(j&7));
-	}
-	
-	SimpleFlood (p, p->leaf);
-
-	p->nummightsee = CountBits (p->portalflood, numportals*2);
-//	Sys_Printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
-	c_flood += p->nummightsee;
-}
-
-
-
-
-
-/*
-===============================================================================
-
-This is a second order aproximation 
-
-Calculates portalvis bit vector
-
-WAAAAAAY too slow.
-
-===============================================================================
-*/
-
-/*
-==================
-RecursiveLeafBitFlow
-
-==================
-*/
-void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
-{
-	vportal_t	*p;
-	leaf_t 		*leaf;
-	int			i, j;
-	long		more;
-	int			pnum;
-	byte		newmight[MAX_PORTALS/8];
-
-	leaf = &leafs[leafnum];
-	
-	// check all portals for flowing into other leafs
-	for (i=0 ; i<leaf->numportals ; i++)
-	{
-		p = leaf->portals[i];
-		if (p->removed)
-			continue;
-		pnum = p - portals;
-
-		// if some previous portal can't see it, skip
-		if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) )
-			continue;
-
-		// if this portal can see some portals we mightsee, recurse
-		more = 0;
-		for (j=0 ; j<portallongs ; j++)
-		{
-			((long *)newmight)[j] = ((long *)mightsee)[j] 
-				& ((long *)p->portalflood)[j];
-			more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
-		}
-
-		if (!more)
-			continue;	// can't see anything new
-
-		cansee[pnum>>3] |= (1<<(pnum&7));
-
-		RecursiveLeafBitFlow (p->leaf, newmight, cansee);
-	}	
-}
-
-/*
-==============
-BetterPortalVis
-==============
-*/
-void BetterPortalVis (int portalnum)
-{
-	vportal_t	*p;
-
-	p = portals+portalnum;
-
-	if (p->removed)
-		return;
-
-	RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
-
-	// build leaf vis information
-	p->nummightsee = CountBits (p->portalvis, numportals*2);
-	c_vis += p->nummightsee;
-}
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define VISFLOW_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+
+/*
+
+  each portal will have a list of all possible to see from first portal
+
+  if (!thread->portalmightsee[portalnum])
+
+  portal mightsee
+
+  for p2 = all other portals in leaf
+	get sperating planes
+	for all portals that might be seen by p2
+		mark as unseen if not present in seperating plane
+	flood fill a new mightsee
+	save as passagemightsee
+
+
+  void CalcMightSee (leaf_t *leaf, 
+*/
+
+int CountBits (byte *bits, int numbits)
+{
+	int		i;
+	int		c;
+
+	c = 0;
+	for (i=0 ; i<numbits ; i++)
+		if (bits[i>>3] & (1<<(i&7)) )
+			c++;
+
+	return c;
+}
+
+int		c_fullskip;
+int		c_portalskip, c_leafskip;
+int		c_vistest, c_mighttest;
+
+int		c_chop, c_nochop;
+
+int		active;
+
+void CheckStack (leaf_t *leaf, threaddata_t *thread)
+{
+	pstack_t	*p, *p2;
+
+	for (p=thread->pstack_head.next ; p ; p=p->next)
+	{
+//		Sys_Printf ("=");
+		if (p->leaf == leaf)
+			Error ("CheckStack: leaf recursion");
+		for (p2=thread->pstack_head.next ; p2 != p ; p2=p2->next)
+			if (p2->leaf == p->leaf)
+				Error ("CheckStack: late leaf recursion");
+	}
+//	Sys_Printf ("\n");
+}
+
+
+fixedWinding_t *AllocStackWinding (pstack_t *stack)
+{
+	int		i;
+
+	for (i=0 ; i<3 ; i++)
+	{
+		if (stack->freewindings[i])
+		{
+			stack->freewindings[i] = 0;
+			return &stack->windings[i];
+		}
+	}
+
+	Error ("AllocStackWinding: failed");
+
+	return NULL;
+}
+
+void FreeStackWinding (fixedWinding_t *w, pstack_t *stack)
+{
+	int		i;
+
+	i = w - stack->windings;
+
+	if (i<0 || i>2)
+		return;		// not from local
+
+	if (stack->freewindings[i])
+		Error ("FreeStackWinding: allready free");
+	stack->freewindings[i] = 1;
+}
+
+/*
+==============
+VisChopWinding
+
+==============
+*/
+fixedWinding_t	*VisChopWinding (fixedWinding_t *in, pstack_t *stack, visPlane_t *split)
+{
+	vec_t	dists[128];
+	int		sides[128];
+	int		counts[3];
+	vec_t	dot;
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	fixedWinding_t	*neww;
+
+	counts[0] = counts[1] = counts[2] = 0;
+
+	// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->points[i], split->normal);
+		dot -= split->dist;
+		dists[i] = dot;
+		if (dot > ON_EPSILON)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -ON_EPSILON)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+
+	if (!counts[1])
+		return in;		// completely on front side
+	
+	if (!counts[0])
+	{
+		FreeStackWinding (in, stack);
+		return NULL;
+	}
+
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	neww = AllocStackWinding (stack);
+
+	neww->numpoints = 0;
+
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->points[i];
+
+		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
+		{
+			FreeStackWinding (neww, stack);
+			return in;		// can't chop -- fall back to original
+		}
+
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, neww->points[neww->numpoints]);
+			neww->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, neww->points[neww->numpoints]);
+			neww->numpoints++;
+		}
+		
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
+		{
+			FreeStackWinding (neww, stack);
+			return in;		// can't chop -- fall back to original
+		}
+
+		// generate a split point
+		p2 = in->points[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (split->normal[j] == 1)
+				mid[j] = split->dist;
+			else if (split->normal[j] == -1)
+				mid[j] = -split->dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, neww->points[neww->numpoints]);
+		neww->numpoints++;
+	}
+	
+	// free the original winding
+	FreeStackWinding (in, stack);
+	
+	return neww;
+}
+
+/*
+==============
+ClipToSeperators
+
+Source, pass, and target are an ordering of portals.
+
+Generates seperating planes canidates by taking two points from source and one
+point from pass, and clips target by them.
+
+If target is totally clipped away, that portal can not be seen through.
+
+Normal clip keeps target on the same side as pass, which is correct if the
+order goes source, pass, target.  If the order goes pass, source, target then
+flipclip should be set.
+==============
+*/
+fixedWinding_t	*ClipToSeperators (fixedWinding_t *source, fixedWinding_t *pass, fixedWinding_t *target, qboolean flipclip, pstack_t *stack)
+{
+	int			i, j, k, l;
+	visPlane_t		plane;
+	vec3_t		v1, v2;
+	float		d;
+	vec_t		length;
+	int			counts[3];
+	qboolean		fliptest;
+
+	// check all combinations	
+	for (i=0 ; i<source->numpoints ; i++)
+	{
+		l = (i+1)%source->numpoints;
+		VectorSubtract (source->points[l] , source->points[i], v1);
+
+		// find a vertex of pass that makes a plane that puts all of the
+		// vertexes of pass on the front side and all of the vertexes of
+		// source on the back side
+		for (j=0 ; j<pass->numpoints ; j++)
+		{
+			VectorSubtract (pass->points[j], source->points[i], v2);
+
+			plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
+			plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
+			plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
+			
+			// if points don't make a valid plane, skip it
+
+			length = plane.normal[0] * plane.normal[0]
+			+ plane.normal[1] * plane.normal[1]
+			+ plane.normal[2] * plane.normal[2];
+			
+			if (length < ON_EPSILON)
+				continue;
+
+			length = 1/sqrt(length);
+			
+			plane.normal[0] *= length;
+			plane.normal[1] *= length;
+			plane.normal[2] *= length;
+
+			plane.dist = DotProduct (pass->points[j], plane.normal);
+
+			//
+			// find out which side of the generated seperating plane has the
+			// source portal
+			//
+#if 1
+			fliptest = qfalse;
+			for (k=0 ; k<source->numpoints ; k++)
+			{
+				if (k == i || k == l)
+					continue;
+				d = DotProduct (source->points[k], plane.normal) - plane.dist;
+				if (d < -ON_EPSILON)
+				{	// source is on the negative side, so we want all
+					// pass and target on the positive side
+					fliptest = qfalse;
+					break;
+				}
+				else if (d > ON_EPSILON)
+				{	// source is on the positive side, so we want all
+					// pass and target on the negative side
+					fliptest = qtrue;
+					break;
+				}
+			}
+			if (k == source->numpoints)
+				continue;		// planar with source portal
+#else
+			fliptest = flipclip;
+#endif
+			//
+			// flip the normal if the source portal is backwards
+			//
+			if (fliptest)
+			{
+				VectorSubtract (vec3_origin, plane.normal, plane.normal);
+				plane.dist = -plane.dist;
+			}
+#if 1
+			//
+			// if all of the pass portal points are now on the positive side,
+			// this is the seperating plane
+			//
+			counts[0] = counts[1] = counts[2] = 0;
+			for (k=0 ; k<pass->numpoints ; k++)
+			{
+				if (k==j)
+					continue;
+				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+				if (d < -ON_EPSILON)
+					break;
+				else if (d > ON_EPSILON)
+					counts[0]++;
+				else
+					counts[2]++;
+			}
+			if (k != pass->numpoints)
+				continue;	// points on negative side, not a seperating plane
+				
+			if (!counts[0])
+				continue;	// planar with seperating plane
+#else
+			k = (j+1)%pass->numpoints;
+			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+			if (d < -ON_EPSILON)
+				continue;
+			k = (j+pass->numpoints-1)%pass->numpoints;
+			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+			if (d < -ON_EPSILON)
+				continue;			
+#endif
+			//
+			// flip the normal if we want the back side
+			//
+			if (flipclip)
+			{
+				VectorSubtract (vec3_origin, plane.normal, plane.normal);
+				plane.dist = -plane.dist;
+			}
+
+#ifdef SEPERATORCACHE
+			stack->seperators[flipclip][stack->numseperators[flipclip]] = plane;
+			if (++stack->numseperators[flipclip] >= MAX_SEPERATORS)
+				Error("MAX_SEPERATORS");
+#endif
+			//MrE: fast check first
+			d = DotProduct (stack->portal->origin, plane.normal) - plane.dist;
+			//if completely at the back of the seperator plane
+			if (d < -stack->portal->radius)
+				return NULL;
+			//if completely on the front of the seperator plane
+			if (d > stack->portal->radius)
+				break;
+
+			//
+			// clip target by the seperating plane
+			//
+			target = VisChopWinding (target, stack, &plane);
+			if (!target)
+				return NULL;		// target is not visible
+
+			break;		// optimization by Antony Suter
+		}
+	}
+	
+	return target;
+}
+
+/*
+==================
+RecursiveLeafFlow
+
+Flood fill through the leafs
+If src_portal is NULL, this is the originating leaf
+==================
+*/
+void RecursiveLeafFlow (int leafnum, threaddata_t *thread, pstack_t *prevstack)
+{
+	pstack_t	stack;
+	vportal_t	*p;
+	visPlane_t		backplane;
+	leaf_t 		*leaf;
+	int			i, j, n;
+	long		*test, *might, *prevmight, *vis, more;
+	int			pnum;
+
+	thread->c_chains++;
+
+	leaf = &leafs[leafnum];
+//	CheckStack (leaf, thread);
+
+	prevstack->next = &stack;
+
+	stack.next = NULL;
+	stack.leaf = leaf;
+	stack.portal = NULL;
+	stack.depth = prevstack->depth + 1;
+
+#ifdef SEPERATORCACHE
+	stack.numseperators[0] = 0;
+	stack.numseperators[1] = 0;
+#endif
+
+	might = (long *)stack.mightsee;
+	vis = (long *)thread->base->portalvis;
+	
+	// check all portals for flowing into other leafs	
+	for (i = 0; i < leaf->numportals; i++)
+	{
+		p = leaf->portals[i];
+		if (p->removed)
+			continue;
+		pnum = p - portals;
+
+		/* MrE: portal trace debug code
+		{
+			int portaltrace[] = {13, 16, 17, 37};
+			pstack_t *s;
+
+			s = &thread->pstack_head;
+			for (j = 0; s->next && j < sizeof(portaltrace)/sizeof(int) - 1; j++, s = s->next)
+			{
+				if (s->portal->num != portaltrace[j])
+					break;
+			}
+			if (j >= sizeof(portaltrace)/sizeof(int) - 1)
+			{
+				if (p->num == portaltrace[j])
+					n = 0; //traced through all the portals
+			}
+		}
+		*/
+
+		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
+		{
+			continue;	// can't possibly see it
+		}
+
+		// if the portal can't see anything we haven't allready seen, skip it
+		if (p->status == stat_done)
+		{
+			test = (long *)p->portalvis;
+		}
+		else
+		{
+			test = (long *)p->portalflood;
+		}
+
+		more = 0;
+		prevmight = (long *)prevstack->mightsee;
+		for (j=0 ; j<portallongs ; j++)
+		{
+			might[j] = prevmight[j] & test[j];
+			more |= (might[j] & ~vis[j]);
+		}
+		
+		if (!more && 
+			(thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
+		{	// can't see anything new
+			continue;
+		}
+
+		// get plane of portal, point normal into the neighbor leaf
+		stack.portalplane = p->plane;
+		VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
+		backplane.dist = -p->plane.dist;
+		
+//		c_portalcheck++;
+		
+		stack.portal = p;
+		stack.next = NULL;
+		stack.freewindings[0] = 1;
+		stack.freewindings[1] = 1;
+		stack.freewindings[2] = 1;
+		
+#if 1
+		{
+			float d;
+
+			d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
+			d -= thread->pstack_head.portalplane.dist;
+			if (d < -p->radius)
+			{
+				continue;
+			}
+			else if (d > p->radius)
+			{
+				stack.pass = p->winding;
+			}
+			else	
+			{
+				stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
+				if (!stack.pass)
+					continue;
+			}
+		}
+#else
+		stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
+		if (!stack.pass)
+			continue;
+#endif
+
+	
+#if 1
+		{
+			float d;
+
+			d = DotProduct (thread->base->origin, p->plane.normal);
+			d -= p->plane.dist;
+			//MrE: vis-bug fix
+			//if (d > p->radius)
+			if (d > thread->base->radius)
+			{
+				continue;
+			}
+			//MrE: vis-bug fix
+			//if (d < -p->radius)
+			else if (d < -thread->base->radius)
+			{
+				stack.source = prevstack->source;
+			}
+			else	
+			{
+				stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
+				//FIXME: shouldn't we create a new source origin and radius for fast checks?
+				if (!stack.source)
+					continue;
+			}
+		}
+#else
+		stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
+		if (!stack.source)
+			continue;
+#endif
+
+		if (!prevstack->pass)
+		{	// the second leaf can only be blocked if coplanar
+
+			// mark the portal as visible
+			thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
+
+			RecursiveLeafFlow (p->leaf, thread, &stack);
+			continue;
+		}
+
+#ifdef SEPERATORCACHE
+		if (stack.numseperators[0])
+		{
+			for (n = 0; n < stack.numseperators[0]; n++)
+			{
+				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
+				if (!stack.pass)
+					break;		// target is not visible
+			}
+			if (n < stack.numseperators[0])
+				continue;
+		}
+		else
+		{
+			stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
+		}
+#else
+		stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
+#endif
+		if (!stack.pass)
+			continue;
+
+#ifdef SEPERATORCACHE
+		if (stack.numseperators[1])
+		{
+			for (n = 0; n < stack.numseperators[1]; n++)
+			{
+				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
+				if (!stack.pass)
+					break;		// target is not visible
+			}
+		}
+		else
+		{
+			stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
+		}
+#else
+		stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
+#endif
+		if (!stack.pass)
+			continue;
+
+		// mark the portal as visible
+		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
+
+		// flow through it for real
+		RecursiveLeafFlow (p->leaf, thread, &stack);
+		//
+		stack.next = NULL;
+	}	
+}
+
+/*
+===============
+PortalFlow
+
+generates the portalvis bit vector
+===============
+*/
+void PortalFlow (int portalnum)
+{
+	threaddata_t	data;
+	int				i;
+	vportal_t		*p;
+	int				c_might, c_can;
+
+#ifdef MREDEBUG
+	Sys_Printf("\r%6d", portalnum);
+#endif
+
+	p = sorted_portals[portalnum];
+
+	if (p->removed)
+	{
+		p->status = stat_done;
+		return;
+	}
+
+	p->status = stat_working;
+
+	c_might = CountBits (p->portalflood, numportals*2);
+
+	memset (&data, 0, sizeof(data));
+	data.base = p;
+	
+	data.pstack_head.portal = p;
+	data.pstack_head.source = p->winding;
+	data.pstack_head.portalplane = p->plane;
+	data.pstack_head.depth = 0;
+	for (i=0 ; i<portallongs ; i++)
+		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
+
+	RecursiveLeafFlow (p->leaf, &data, &data.pstack_head);
+
+	p->status = stat_done;
+
+	c_can = CountBits (p->portalvis, numportals*2);
+
+	Sys_FPrintf (SYS_VRB,"portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
+		(int)(p - portals),	c_might, c_can, data.c_chains);
+}
+
+/*
+==================
+RecursivePassageFlow
+==================
+*/
+void RecursivePassageFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
+{
+	pstack_t	stack;
+	vportal_t	*p;
+	leaf_t 		*leaf;
+	passage_t	*passage, *nextpassage;
+	int			i, j;
+	long		*might, *vis, *prevmight, *cansee, *portalvis, more;
+	int			pnum;
+
+	leaf = &leafs[portal->leaf];
+
+	prevstack->next = &stack;
+
+	stack.next = NULL;
+	stack.depth = prevstack->depth + 1;
+
+	vis = (long *)thread->base->portalvis;
+
+	passage = portal->passages;
+	nextpassage = passage;
+	// check all portals for flowing into other leafs	
+	for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
+	{
+		p = leaf->portals[i];
+		if ( p->removed ) {
+			continue;
+		}
+		nextpassage = passage->next;
+		pnum = p - portals;
+
+		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) ) {
+			continue;	// can't possibly see it
+		}
+
+		// mark the portal as visible
+		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
+
+		prevmight = (long *)prevstack->mightsee;
+		cansee = (long *)passage->cansee;
+		might = (long *)stack.mightsee;
+		memcpy(might, prevmight, portalbytes);
+		if (p->status == stat_done)
+			portalvis = (long *) p->portalvis;
+		else
+			portalvis = (long *) p->portalflood;
+		more = 0;
+		for (j = 0; j < portallongs; j++)
+		{
+			if (*might)
+			{
+				*might &= *cansee++ & *portalvis++;
+				more |= (*might & ~vis[j]);
+			}
+			else
+			{
+				cansee++;
+				portalvis++;
+			}
+			might++;
+		}
+
+		if ( !more ) {
+			// can't see anything new
+			continue;
+		}
+
+		// flow through it for real
+		RecursivePassageFlow(p, thread, &stack);
+
+		stack.next = NULL;
+	}
+}
+
+/*
+===============
+PassageFlow
+===============
+*/
+void PassageFlow (int portalnum)
+{
+	threaddata_t	data;
+	int				i;
+	vportal_t		*p;
+//	int				c_might, c_can;
+
+#ifdef MREDEBUG
+	Sys_Printf("\r%6d", portalnum);
+#endif
+
+	p = sorted_portals[portalnum];
+
+	if (p->removed)
+	{
+		p->status = stat_done;
+		return;
+	}
+
+	p->status = stat_working;
+
+//	c_might = CountBits (p->portalflood, numportals*2);
+
+	memset (&data, 0, sizeof(data));
+	data.base = p;
+	
+	data.pstack_head.portal = p;
+	data.pstack_head.source = p->winding;
+	data.pstack_head.portalplane = p->plane;
+	data.pstack_head.depth = 0;
+	for (i=0 ; i<portallongs ; i++)
+		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
+
+	RecursivePassageFlow (p, &data, &data.pstack_head);
+
+	p->status = stat_done;
+
+	/*
+	c_can = CountBits (p->portalvis, numportals*2);
+
+	Sys_FPrintf (SYS_VRB,"portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
+		(int)(p - portals),	c_might, c_can, data.c_chains);
+	*/
+}
+
+/*
+==================
+RecursivePassagePortalFlow
+==================
+*/
+void RecursivePassagePortalFlow (vportal_t *portal, threaddata_t *thread, pstack_t *prevstack)
+{
+	pstack_t	stack;
+	vportal_t	*p;
+	leaf_t 		*leaf;
+	visPlane_t		backplane;
+	passage_t	*passage, *nextpassage;
+	int			i, j, n;
+	long		*might, *vis, *prevmight, *cansee, *portalvis, more;
+	int			pnum;
+
+//	thread->c_chains++;
+
+	leaf = &leafs[portal->leaf];
+//	CheckStack (leaf, thread);
+
+	prevstack->next = &stack;
+
+	stack.next = NULL;
+	stack.leaf = leaf;
+	stack.portal = NULL;
+	stack.depth = prevstack->depth + 1;
+
+#ifdef SEPERATORCACHE
+	stack.numseperators[0] = 0;
+	stack.numseperators[1] = 0;
+#endif
+
+	vis = (long *)thread->base->portalvis;
+
+	passage = portal->passages;
+	nextpassage = passage;
+	// check all portals for flowing into other leafs	
+	for (i = 0; i < leaf->numportals; i++, passage = nextpassage)
+	{
+		p = leaf->portals[i];
+		if (p->removed)
+			continue;
+		nextpassage = passage->next;
+		pnum = p - portals;
+
+		if ( ! (prevstack->mightsee[pnum >> 3] & (1<<(pnum&7)) ) )
+			continue;	// can't possibly see it
+
+		prevmight = (long *)prevstack->mightsee;
+		cansee = (long *)passage->cansee;
+		might = (long *)stack.mightsee;
+		memcpy(might, prevmight, portalbytes);
+		if (p->status == stat_done)
+			portalvis = (long *) p->portalvis;
+		else
+			portalvis = (long *) p->portalflood;
+		more = 0;
+		for (j = 0; j < portallongs; j++)
+		{
+			if (*might)
+			{
+				*might &= *cansee++ & *portalvis++;
+				more |= (*might & ~vis[j]);
+			}
+			else
+			{
+				cansee++;
+				portalvis++;
+			}
+			might++;
+		}
+
+		if (!more && (thread->base->portalvis[pnum>>3] & (1<<(pnum&7))) )
+		{	// can't see anything new
+			continue;
+		}
+
+		// get plane of portal, point normal into the neighbor leaf
+		stack.portalplane = p->plane;
+		VectorSubtract (vec3_origin, p->plane.normal, backplane.normal);
+		backplane.dist = -p->plane.dist;
+		
+//		c_portalcheck++;
+		
+		stack.portal = p;
+		stack.next = NULL;
+		stack.freewindings[0] = 1;
+		stack.freewindings[1] = 1;
+		stack.freewindings[2] = 1;
+
+#if 1
+		{
+			float d;
+
+			d = DotProduct (p->origin, thread->pstack_head.portalplane.normal);
+			d -= thread->pstack_head.portalplane.dist;
+			if (d < -p->radius)
+			{
+				continue;
+			}
+			else if (d > p->radius)
+			{
+				stack.pass = p->winding;
+			}
+			else	
+			{
+				stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
+				if (!stack.pass)
+					continue;
+			}
+		}
+#else
+		stack.pass = VisChopWinding (p->winding, &stack, &thread->pstack_head.portalplane);
+		if (!stack.pass)
+			continue;
+#endif
+
+	
+#if 1
+		{
+			float d;
+
+			d = DotProduct (thread->base->origin, p->plane.normal);
+			d -= p->plane.dist;
+			//MrE: vis-bug fix
+			//if (d > p->radius)
+			if (d > thread->base->radius)
+			{
+				continue;
+			}
+			//MrE: vis-bug fix
+			//if (d < -p->radius)
+			else if (d < -thread->base->radius)
+			{
+				stack.source = prevstack->source;
+			}
+			else	
+			{
+				stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
+				//FIXME: shouldn't we create a new source origin and radius for fast checks?
+				if (!stack.source)
+					continue;
+			}
+		}
+#else
+		stack.source = VisChopWinding (prevstack->source, &stack, &backplane);
+		if (!stack.source)
+			continue;
+#endif
+
+		if (!prevstack->pass)
+		{	// the second leaf can only be blocked if coplanar
+
+			// mark the portal as visible
+			thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
+
+			RecursivePassagePortalFlow (p, thread, &stack);
+			continue;
+		}
+
+#ifdef SEPERATORCACHE
+		if (stack.numseperators[0])
+		{
+			for (n = 0; n < stack.numseperators[0]; n++)
+			{
+				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[0][n]);
+				if (!stack.pass)
+					break;		// target is not visible
+			}
+			if (n < stack.numseperators[0])
+				continue;
+		}
+		else
+		{
+			stack.pass = ClipToSeperators (prevstack->source, prevstack->pass, stack.pass, qfalse, &stack);
+		}
+#else
+		stack.pass = ClipToSeperators (stack.source, prevstack->pass, stack.pass, qfalse, &stack);
+#endif
+		if (!stack.pass)
+			continue;
+
+#ifdef SEPERATORCACHE
+		if (stack.numseperators[1])
+		{
+			for (n = 0; n < stack.numseperators[1]; n++)
+			{
+				stack.pass = VisChopWinding (stack.pass, &stack, &stack.seperators[1][n]);
+				if (!stack.pass)
+					break;		// target is not visible
+			}
+		}
+		else
+		{
+			stack.pass = ClipToSeperators (prevstack->pass, prevstack->source, stack.pass, qtrue, &stack);
+		}
+#else
+		stack.pass = ClipToSeperators (prevstack->pass, stack.source, stack.pass, qtrue, &stack);
+#endif
+		if (!stack.pass)
+			continue;
+
+		// mark the portal as visible
+		thread->base->portalvis[pnum>>3] |= (1<<(pnum&7));
+
+		// flow through it for real
+		RecursivePassagePortalFlow(p, thread, &stack);
+		//
+		stack.next = NULL;
+	}
+}
+
+/*
+===============
+PassagePortalFlow
+===============
+*/
+void PassagePortalFlow (int portalnum)
+{
+	threaddata_t	data;
+	int				i;
+	vportal_t		*p;
+//	int				c_might, c_can;
+
+#ifdef MREDEBUG
+	Sys_Printf("\r%6d", portalnum);
+#endif
+
+	p = sorted_portals[portalnum];
+
+	if (p->removed)
+	{
+		p->status = stat_done;
+		return;
+	}
+
+	p->status = stat_working;
+
+//	c_might = CountBits (p->portalflood, numportals*2);
+
+	memset (&data, 0, sizeof(data));
+	data.base = p;
+	
+	data.pstack_head.portal = p;
+	data.pstack_head.source = p->winding;
+	data.pstack_head.portalplane = p->plane;
+	data.pstack_head.depth = 0;
+	for (i=0 ; i<portallongs ; i++)
+		((long *)data.pstack_head.mightsee)[i] = ((long *)p->portalflood)[i];
+
+	RecursivePassagePortalFlow (p, &data, &data.pstack_head);
+
+	p->status = stat_done;
+
+	/*
+	c_can = CountBits (p->portalvis, numportals*2);
+
+	Sys_FPrintf (SYS_VRB,"portal:%4i  mightsee:%4i  cansee:%4i (%i chains)\n", 
+		(int)(p - portals),	c_might, c_can, data.c_chains);
+	*/
+}
+
+fixedWinding_t *PassageChopWinding (fixedWinding_t *in, fixedWinding_t *out, visPlane_t *split)
+{
+	vec_t	dists[128];
+	int		sides[128];
+	int		counts[3];
+	vec_t	dot;
+	int		i, j;
+	vec_t	*p1, *p2;
+	vec3_t	mid;
+	fixedWinding_t	*neww;
+
+	counts[0] = counts[1] = counts[2] = 0;
+
+	// determine sides for each point
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		dot = DotProduct (in->points[i], split->normal);
+		dot -= split->dist;
+		dists[i] = dot;
+		if (dot > ON_EPSILON)
+			sides[i] = SIDE_FRONT;
+		else if (dot < -ON_EPSILON)
+			sides[i] = SIDE_BACK;
+		else
+		{
+			sides[i] = SIDE_ON;
+		}
+		counts[sides[i]]++;
+	}
+
+	if (!counts[1])
+		return in;		// completely on front side
+	
+	if (!counts[0])
+	{
+		return NULL;
+	}
+
+	sides[i] = sides[0];
+	dists[i] = dists[0];
+	
+	neww = out;
+
+	neww->numpoints = 0;
+
+	for (i=0 ; i<in->numpoints ; i++)
+	{
+		p1 = in->points[i];
+
+		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
+		{
+			return in;		// can't chop -- fall back to original
+		}
+
+		if (sides[i] == SIDE_ON)
+		{
+			VectorCopy (p1, neww->points[neww->numpoints]);
+			neww->numpoints++;
+			continue;
+		}
+	
+		if (sides[i] == SIDE_FRONT)
+		{
+			VectorCopy (p1, neww->points[neww->numpoints]);
+			neww->numpoints++;
+		}
+		
+		if (sides[i+1] == SIDE_ON || sides[i+1] == sides[i])
+			continue;
+			
+		if (neww->numpoints == MAX_POINTS_ON_FIXED_WINDING)
+		{
+			return in;		// can't chop -- fall back to original
+		}
+
+		// generate a split point
+		p2 = in->points[(i+1)%in->numpoints];
+		
+		dot = dists[i] / (dists[i]-dists[i+1]);
+		for (j=0 ; j<3 ; j++)
+		{	// avoid round off error when possible
+			if (split->normal[j] == 1)
+				mid[j] = split->dist;
+			else if (split->normal[j] == -1)
+				mid[j] = -split->dist;
+			else
+				mid[j] = p1[j] + dot*(p2[j]-p1[j]);
+		}
+			
+		VectorCopy (mid, neww->points[neww->numpoints]);
+		neww->numpoints++;
+	}
+	
+	return neww;
+}
+
+/*
+===============
+AddSeperators
+===============
+*/
+int AddSeperators (fixedWinding_t *source, fixedWinding_t *pass, qboolean flipclip, visPlane_t *seperators, int maxseperators)
+{
+	int			i, j, k, l;
+	visPlane_t		plane;
+	vec3_t		v1, v2;
+	float		d;
+	vec_t		length;
+	int			counts[3], numseperators;
+	qboolean	fliptest;
+
+	numseperators = 0;
+	// check all combinations	
+	for (i=0 ; i<source->numpoints ; i++)
+	{
+		l = (i+1)%source->numpoints;
+		VectorSubtract (source->points[l] , source->points[i], v1);
+
+		// find a vertex of pass that makes a plane that puts all of the
+		// vertexes of pass on the front side and all of the vertexes of
+		// source on the back side
+		for (j=0 ; j<pass->numpoints ; j++)
+		{
+			VectorSubtract (pass->points[j], source->points[i], v2);
+
+			plane.normal[0] = v1[1]*v2[2] - v1[2]*v2[1];
+			plane.normal[1] = v1[2]*v2[0] - v1[0]*v2[2];
+			plane.normal[2] = v1[0]*v2[1] - v1[1]*v2[0];
+			
+			// if points don't make a valid plane, skip it
+
+			length = plane.normal[0] * plane.normal[0]
+			+ plane.normal[1] * plane.normal[1]
+			+ plane.normal[2] * plane.normal[2];
+			
+			if (length < ON_EPSILON)
+				continue;
+
+			length = 1/sqrt(length);
+			
+			plane.normal[0] *= length;
+			plane.normal[1] *= length;
+			plane.normal[2] *= length;
+
+			plane.dist = DotProduct (pass->points[j], plane.normal);
+
+			//
+			// find out which side of the generated seperating plane has the
+			// source portal
+			//
+#if 1
+			fliptest = qfalse;
+			for (k=0 ; k<source->numpoints ; k++)
+			{
+				if (k == i || k == l)
+					continue;
+				d = DotProduct (source->points[k], plane.normal) - plane.dist;
+				if (d < -ON_EPSILON)
+				{	// source is on the negative side, so we want all
+					// pass and target on the positive side
+					fliptest = qfalse;
+					break;
+				}
+				else if (d > ON_EPSILON)
+				{	// source is on the positive side, so we want all
+					// pass and target on the negative side
+					fliptest = qtrue;
+					break;
+				}
+			}
+			if (k == source->numpoints)
+				continue;		// planar with source portal
+#else
+			fliptest = flipclip;
+#endif
+			//
+			// flip the normal if the source portal is backwards
+			//
+			if (fliptest)
+			{
+				VectorSubtract (vec3_origin, plane.normal, plane.normal);
+				plane.dist = -plane.dist;
+			}
+#if 1
+			//
+			// if all of the pass portal points are now on the positive side,
+			// this is the seperating plane
+			//
+			counts[0] = counts[1] = counts[2] = 0;
+			for (k=0 ; k<pass->numpoints ; k++)
+			{
+				if (k==j)
+					continue;
+				d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+				if (d < -ON_EPSILON)
+					break;
+				else if (d > ON_EPSILON)
+					counts[0]++;
+				else
+					counts[2]++;
+			}
+			if (k != pass->numpoints)
+				continue;	// points on negative side, not a seperating plane
+				
+			if (!counts[0])
+				continue;	// planar with seperating plane
+#else
+			k = (j+1)%pass->numpoints;
+			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+			if (d < -ON_EPSILON)
+				continue;
+			k = (j+pass->numpoints-1)%pass->numpoints;
+			d = DotProduct (pass->points[k], plane.normal) - plane.dist;
+			if (d < -ON_EPSILON)
+				continue;			
+#endif
+			//
+			// flip the normal if we want the back side
+			//
+			if (flipclip)
+			{
+				VectorSubtract (vec3_origin, plane.normal, plane.normal);
+				plane.dist = -plane.dist;
+			}
+
+			if (numseperators >= maxseperators)
+				Error("max seperators");
+			seperators[numseperators] = plane;
+			numseperators++;
+			break;
+		}
+	}
+	return numseperators;
+}
+
+/*
+===============
+CreatePassages
+
+MrE: create passages from one portal to all the portals in the leaf the portal leads to
+	 every passage has a cansee bit string with all the portals that can be
+	 seen through the passage
+===============
+*/
+void CreatePassages(int portalnum)
+{
+	int				i, j, k, n, numseperators, numsee;
+	float			d;
+	vportal_t		*portal, *p, *target;
+	leaf_t			*leaf;
+	passage_t		*passage, *lastpassage;
+	visPlane_t		seperators[MAX_SEPERATORS*2];
+	fixedWinding_t	*w;
+	fixedWinding_t	in, out, *res;
+	
+	
+#ifdef MREDEBUG
+	Sys_Printf("\r%6d", portalnum);
+#endif
+
+	portal = sorted_portals[portalnum];
+
+	if (portal->removed)
+	{
+		portal->status = stat_done;
+		return;
+	}
+
+	lastpassage = NULL;
+	leaf = &leafs[portal->leaf];
+	for (i = 0; i < leaf->numportals; i++)
+	{
+		target = leaf->portals[i];
+		if (target->removed)
+			continue;
+
+		passage = (passage_t *) safe_malloc(sizeof(passage_t) + portalbytes);
+		memset(passage, 0, sizeof(passage_t) + portalbytes);
+		numseperators = AddSeperators(portal->winding, target->winding, qfalse, seperators, MAX_SEPERATORS*2);
+		numseperators += AddSeperators(target->winding, portal->winding, qtrue, &seperators[numseperators], MAX_SEPERATORS*2-numseperators);
+
+		passage->next = NULL;
+		if (lastpassage)
+			lastpassage->next = passage;
+		else
+			portal->passages = passage;
+		lastpassage = passage;
+
+		numsee = 0;
+		//create the passage->cansee
+		for (j = 0; j < numportals * 2; j++)
+		{
+			p = &portals[j];
+			if (p->removed)
+				continue;
+			if ( ! (target->portalflood[j >> 3] & (1<<(j&7)) ) )
+				continue;
+			if ( ! (portal->portalflood[j >> 3] & (1<<(j&7)) ) )
+				continue;
+			for (k = 0; k < numseperators; k++)
+			{
+				//
+				d = DotProduct (p->origin, seperators[k].normal) - seperators[k].dist;
+				//if completely at the back of the seperator plane
+				if (d < -p->radius + ON_EPSILON)
+					break;
+				w = p->winding;
+				for (n = 0; n < w->numpoints; n++)
+				{
+					d = DotProduct (w->points[n], seperators[k].normal) - seperators[k].dist;
+					//if at the front of the seperator
+					if (d > ON_EPSILON)
+						break;
+				}
+				//if no points are at the front of the seperator
+				if (n >= w->numpoints)
+					break;
+			}
+			if (k < numseperators)
+				continue;
+			
+			/* explitive deleted */
+			
+			
+			/* ydnar: prefer correctness to stack overflow  */
+			//% memcpy( &in, p->winding, (int)((fixedWinding_t *)0)->points[p->winding->numpoints] );
+			if( p->winding->numpoints <= MAX_POINTS_ON_FIXED_WINDING )
+				memcpy( &in, p->winding, (int) &(((fixedWinding_t*) 0)->points[ p->winding->numpoints ]) );
+			else
+				memcpy( &in, p->winding, sizeof( fixedWinding_t ) );
+			
+			
+			for( k = 0; k < numseperators; k++ )
+			{
+				/* ydnar: this is a shitty crutch */
+				if( in.numpoints > MAX_POINTS_ON_FIXED_WINDING )
+				{
+					//% Sys_Printf( "[%d]", p->winding->numpoints );
+					in.numpoints = MAX_POINTS_ON_FIXED_WINDING;
+				}
+				
+				res = PassageChopWinding( &in, &out, &seperators[ k ] );
+				if( res == &out )
+					memcpy( &in, &out, sizeof( fixedWinding_t ) );
+
+			
+				if( res == NULL )
+					break;
+			}
+			if (k < numseperators)
+				continue;
+			passage->cansee[j >> 3] |= (1<<(j&7));
+			numsee++;
+		}
+	}
+}
+
+void PassageMemory(void)
+{
+	int i, j, totalmem, totalportals;
+	vportal_t *portal, *target;
+	leaf_t *leaf;
+
+	totalmem = 0;
+	totalportals = 0;
+	for (i = 0; i < numportals; i++)
+	{
+		portal = sorted_portals[i];
+		if (portal->removed)
+			continue;
+		leaf = &leafs[portal->leaf];
+		for (j = 0; j < leaf->numportals; j++)
+		{
+			target = leaf->portals[j];
+			if (target->removed)
+				continue;
+			totalmem += sizeof(passage_t) + portalbytes;
+			totalportals++;
+		}
+	}
+	Sys_Printf("%7i average number of passages per leaf\n", totalportals / numportals);
+	Sys_Printf("%7i MB required passage memory\n", totalmem >> 10 >> 10);
+}
+
+/*
+===============================================================================
+
+This is a rough first-order aproximation that is used to trivially reject some
+of the final calculations.
+
+
+Calculates portalfront and portalflood bit vectors
+
+thinking about:
+
+typedef struct passage_s
+{
+	struct passage_s	*next;
+	struct portal_s		*to;
+	stryct sep_s		*seperators;
+	byte				*mightsee;
+} passage_t;
+
+typedef struct portal_s
+{
+	struct passage_s	*passages;
+	int					leaf;		// leaf portal faces into
+} portal_s;
+
+leaf = portal->leaf
+clear 
+for all portals
+
+
+calc portal visibility
+	clear bit vector
+	for all passages
+		passage visibility
+
+
+for a portal to be visible to a passage, it must be on the front of
+all seperating planes, and both portals must be behind the new portal
+
+===============================================================================
+*/
+
+int		c_flood, c_vis;
+
+
+/*
+==================
+SimpleFlood
+
+==================
+*/
+void SimpleFlood (vportal_t *srcportal, int leafnum)
+{
+	int		i;
+	leaf_t	*leaf;
+	vportal_t	*p;
+	int		pnum;
+
+	leaf = &leafs[leafnum];
+	
+	for (i=0 ; i<leaf->numportals ; i++)
+	{
+		p = leaf->portals[i];
+		if (p->removed)
+			continue;
+		pnum = p - portals;
+		if ( ! (srcportal->portalfront[pnum>>3] & (1<<(pnum&7)) ) )
+			continue;
+
+		if (srcportal->portalflood[pnum>>3] & (1<<(pnum&7)) )
+			continue;
+
+		srcportal->portalflood[pnum>>3] |= (1<<(pnum&7));
+		
+		SimpleFlood (srcportal, p->leaf);
+	}
+}
+
+/*
+==============
+BasePortalVis
+==============
+*/
+void BasePortalVis( int portalnum )
+{
+	int			j, k;
+	vportal_t	*tp, *p;
+	float		d;
+	fixedWinding_t	*w;
+	vec3_t		dir;
+	
+
+	p = portals+portalnum;
+
+	if (p->removed)
+		return;
+
+	p->portalfront = safe_malloc (portalbytes);
+	memset (p->portalfront, 0, portalbytes);
+
+	p->portalflood = safe_malloc (portalbytes);
+	memset (p->portalflood, 0, portalbytes);
+	
+	p->portalvis = safe_malloc (portalbytes);
+	memset (p->portalvis, 0, portalbytes);
+	
+	for (j=0, tp = portals ; j<numportals*2 ; j++, tp++)
+	{
+		if( j == portalnum )
+			continue;
+		if( tp->removed )
+			continue;
+
+		/* ydnar: this is old farplane vis code from mre */
+		/*
+		if (farplanedist >= 0)
+		{
+			vec3_t dir;
+			VectorSubtract(p->origin, tp->origin, dir);
+			if (VectorLength(dir) > farplanedist - p->radius - tp->radius)
+				continue;
+		}
+		*/
+		
+		/* ydnar: this is known-to-be-working farplane code */
+		if( farPlaneDist > 0.0f )
+		{
+			VectorSubtract( p->origin, tp->origin, dir );
+			if( VectorLength( dir ) - p->radius - tp->radius > farPlaneDist )
+				continue;
+		}
+		
+		
+		w = tp->winding;
+		for (k=0 ; k<w->numpoints ; k++)
+		{
+			d = DotProduct (w->points[k], p->plane.normal)
+				- p->plane.dist;
+			if (d > ON_EPSILON)
+				break;
+		}
+		if (k == w->numpoints)
+			continue;	// no points on front
+
+		w = p->winding;
+		for (k=0 ; k<w->numpoints ; k++)
+		{
+			d = DotProduct (w->points[k], tp->plane.normal)
+				- tp->plane.dist;
+			if (d < -ON_EPSILON)
+				break;
+		}
+		if (k == w->numpoints)
+			continue;	// no points on front
+
+		p->portalfront[j>>3] |= (1<<(j&7));
+	}
+	
+	SimpleFlood (p, p->leaf);
+
+	p->nummightsee = CountBits (p->portalflood, numportals*2);
+//	Sys_Printf ("portal %i: %i mightsee\n", portalnum, p->nummightsee);
+	c_flood += p->nummightsee;
+}
+
+
+
+
+
+/*
+===============================================================================
+
+This is a second order aproximation 
+
+Calculates portalvis bit vector
+
+WAAAAAAY too slow.
+
+===============================================================================
+*/
+
+/*
+==================
+RecursiveLeafBitFlow
+
+==================
+*/
+void RecursiveLeafBitFlow (int leafnum, byte *mightsee, byte *cansee)
+{
+	vportal_t	*p;
+	leaf_t 		*leaf;
+	int			i, j;
+	long		more;
+	int			pnum;
+	byte		newmight[MAX_PORTALS/8];
+
+	leaf = &leafs[leafnum];
+	
+	// check all portals for flowing into other leafs
+	for (i=0 ; i<leaf->numportals ; i++)
+	{
+		p = leaf->portals[i];
+		if (p->removed)
+			continue;
+		pnum = p - portals;
+
+		// if some previous portal can't see it, skip
+		if (! (mightsee[pnum>>3] & (1<<(pnum&7)) ) )
+			continue;
+
+		// if this portal can see some portals we mightsee, recurse
+		more = 0;
+		for (j=0 ; j<portallongs ; j++)
+		{
+			((long *)newmight)[j] = ((long *)mightsee)[j] 
+				& ((long *)p->portalflood)[j];
+			more |= ((long *)newmight)[j] & ~((long *)cansee)[j];
+		}
+
+		if (!more)
+			continue;	// can't see anything new
+
+		cansee[pnum>>3] |= (1<<(pnum&7));
+
+		RecursiveLeafBitFlow (p->leaf, newmight, cansee);
+	}	
+}
+
+/*
+==============
+BetterPortalVis
+==============
+*/
+void BetterPortalVis (int portalnum)
+{
+	vportal_t	*p;
+
+	p = portals+portalnum;
+
+	if (p->removed)
+		return;
+
+	RecursiveLeafBitFlow (p->leaf, p->portalflood, p->portalvis);
+
+	// build leaf vis information
+	p->nummightsee = CountBits (p->portalvis, numportals*2);
+	c_vis += p->nummightsee;
+}
+
+
diff --git a/tools/quake3/q3map2/writebsp.c b/tools/quake3/q3map2/writebsp.c
index 756adb6a..7fb51d83 100644
--- a/tools/quake3/q3map2/writebsp.c
+++ b/tools/quake3/q3map2/writebsp.c
@@ -1,646 +1,646 @@
-/*
-Copyright (C) 1999-2007 id Software, Inc. and contributors.
-For a list of contributors, see the accompanying CONTRIBUTORS file.
-
-This file is part of GtkRadiant.
-
-GtkRadiant 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.
-
-GtkRadiant 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 GtkRadiant; if not, write to the Free Software
-Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
-
-----------------------------------------------------------------------------------
-
-This code has been altered significantly from its original form, to support
-several games based on the Quake III Arena engine, in the form of "Q3Map2."
-
-------------------------------------------------------------------------------- */
-
-
-
-/* marker */
-#define WRITEBSP_C
-
-
-
-/* dependencies */
-#include "q3map2.h"
-
-
-
-/*
-EmitShader()
-emits a bsp shader entry
-*/
-
-int	EmitShader( const char *shader, int *contentFlags, int *surfaceFlags )
-{
-	int				i;
-	shaderInfo_t	*si;
-	
-	
-	/* handle special cases */
-	if( shader == NULL )
-		shader = "noshader";
-	
-	/* try to find an existing shader */
-	for( i = 0; i < numBSPShaders; i++ )
-	{
-		/* ydnar: handle custom surface/content flags */
-		if( surfaceFlags != NULL && bspShaders[ i ].surfaceFlags != *surfaceFlags )
-			continue;
-		if( contentFlags != NULL && bspShaders[ i ].contentFlags != *contentFlags )
-			continue;
-		
-		/* compare name */
-		if( !Q_stricmp( shader, bspShaders[ i ].shader ) )
-			return i;
-	}
-	
-	/* get shaderinfo */
-	si = ShaderInfoForShader( shader );
-	
-	/* emit a new shader */
-	if( i == MAX_MAP_SHADERS )
-		Error( "MAX_MAP_SHADERS" );
-	numBSPShaders++;
-	strcpy( bspShaders[ i ].shader, shader );
-	bspShaders[ i ].surfaceFlags = si->surfaceFlags;
-	bspShaders[ i ].contentFlags = si->contentFlags;
-	
-	/* handle custom content/surface flags */
-	if( surfaceFlags != NULL )
-		bspShaders[ i ].surfaceFlags = *surfaceFlags;
-	if( contentFlags != NULL )
-		bspShaders[ i ].contentFlags = *contentFlags;
-	
-	/* recursively emit any damage shaders */
-	if( si->damageShader[ 0 ] != '\0' )
-	{
-		Sys_FPrintf( SYS_VRB, "Shader %s has damage shader %s\n", si->shader, si->damageShader );
-		EmitShader( si->damageShader, NULL, NULL );
-	}
-	
-	/* return it */
-	return i;
-}
-
-
-
-/*
-EmitPlanes()
-there is no oportunity to discard planes, because all of the original
-brushes will be saved in the map
-*/
-
-void EmitPlanes( void )
-{
-	int			i;
-	bspPlane_t	*bp;
-	plane_t		*mp;
-	
-	
-	/* walk plane list */
-	mp = mapplanes;
-	for( i = 0; i < nummapplanes; i++, mp++ )
-	{
-		bp = &bspPlanes[ numBSPPlanes ];
-		VectorCopy( mp->normal, bp->normal );
-		bp->dist = mp->dist;
-		numBSPPlanes++;
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d BSP planes\n", numBSPPlanes );
-}
-
-
-
-/*
-EmitLeaf()
-emits a leafnode to the bsp file
-*/
-
-void EmitLeaf( node_t *node )
-{
-	bspLeaf_t		*leaf_p;
-	brush_t			*b;
-	drawSurfRef_t	*dsr;
-	int				i = 0;
-
-	
-	/* check limits */
-	if( numBSPLeafs >= MAX_MAP_LEAFS )
-		Error( "MAX_MAP_LEAFS" );
-
-	leaf_p = &bspLeafs[numBSPLeafs];
-	numBSPLeafs++;
-
-	leaf_p->cluster = node->cluster;
-	leaf_p->area = node->area;
-
-	/* emit bounding box */
-	VectorCopy( node->mins, leaf_p->mins );
-	VectorCopy( node->maxs, leaf_p->maxs );
-	
-	/* emit leaf brushes */
-	leaf_p->firstBSPLeafBrush = numBSPLeafBrushes;
-	for( b = node->brushlist; b; b = b->next )
-	{
-		/* something is corrupting brushes */
-		if( (int) b < 256 )
-		{
-			Sys_Printf( "WARNING: Node brush list corrupted (0x%08X)\n", b );
-			break;
-		}
-		//%	if( b->guard != 0xDEADBEEF )
-		//%		Sys_Printf( "Brush %6d: 0x%08X Guard: 0x%08X Next: 0x%08X Original: 0x%08X Sides: %d\n", b->brushNum, b, b, b->next, b->original, b->numsides );
-		
-		if( numBSPLeafBrushes >= MAX_MAP_LEAFBRUSHES )
-			Error( "MAX_MAP_LEAFBRUSHES" );
-		bspLeafBrushes[ numBSPLeafBrushes ] = b->original->outputNum;
-		numBSPLeafBrushes++;
-	}
-	
-	leaf_p->numBSPLeafBrushes = numBSPLeafBrushes - leaf_p->firstBSPLeafBrush;
-	
-	/* emit leaf surfaces */
-	if( node->opaque )
-		return;
-	
-	/* add the drawSurfRef_t drawsurfs */
-	leaf_p->firstBSPLeafSurface = numBSPLeafSurfaces;
-	for ( dsr = node->drawSurfReferences; dsr; dsr = dsr->nextRef )
-	{
-		if( numBSPLeafSurfaces >= MAX_MAP_LEAFFACES )
-			Error( "MAX_MAP_LEAFFACES" );
-		bspLeafSurfaces[ numBSPLeafSurfaces ] = dsr->outputNum;
-		numBSPLeafSurfaces++;			
-	}
-	
-	leaf_p->numBSPLeafSurfaces = numBSPLeafSurfaces - leaf_p->firstBSPLeafSurface;
-}
-
-
-/*
-EmitDrawNode_r()
-recursively emit the bsp nodes
-*/
-
-int EmitDrawNode_r( node_t *node )
-{
-	bspNode_t	*n;
-	int			i;
-	
-	
-	/* check for leafnode */
-	if( node->planenum == PLANENUM_LEAF )
-	{
-		EmitLeaf( node );
-		return -numBSPLeafs;
-	}
-	
-	/* emit a node */
-	if( numBSPNodes == MAX_MAP_NODES )
-		Error( "MAX_MAP_NODES" );
-	n = &bspNodes[ numBSPNodes ];
-	numBSPNodes++;
-	
-	VectorCopy (node->mins, n->mins);
-	VectorCopy (node->maxs, n->maxs);
-
-	if (node->planenum & 1)
-		Error ("WriteDrawNodes_r: odd planenum");
-	n->planeNum = node->planenum;
-
-	//
-	// recursively output the other nodes
-	//	
-	for (i=0 ; i<2 ; i++)
-	{
-		if (node->children[i]->planenum == PLANENUM_LEAF)
-		{
-			n->children[i] = -(numBSPLeafs + 1);
-			EmitLeaf (node->children[i]);
-		}
-		else
-		{
-			n->children[i] = numBSPNodes;	
-			EmitDrawNode_r (node->children[i]);
-		}
-	}
-
-	return n - bspNodes;
-}
-
-
-
-/*
-============
-SetModelNumbers
-============
-*/
-void SetModelNumbers (void)
-{
-	int		i;
-	int		models;
-	char	value[10];
-
-	models = 1;
-	for ( i=1 ; i<numEntities ; i++ ) {
-		if ( entities[i].brushes || entities[i].patches ) {
-			sprintf ( value, "*%i", models );
-			models++;
-			SetKeyValue (&entities[i], "model", value);
-		}
-	}
-
-}
-
-
-
-
-/*
-SetLightStyles()
-sets style keys for entity lights
-*/
-
-void SetLightStyles( void )
-{
-	int			i, j, style, numStyles;
-	qboolean	keepLights;
-	const char	*t;
-	entity_t	*e;
-	epair_t		*ep, *next;
-	char		value[ 10 ];
-	char		lightTargets[ MAX_SWITCHED_LIGHTS ][ 64 ];
-	int			lightStyles[ MAX_SWITCHED_LIGHTS ];
-	
-	
-	/* ydnar: determine if we keep lights in the bsp */
-	t = ValueForKey( &entities[ 0 ], "_keepLights" );
-	keepLights = (t[ 0 ] == '1') ? qtrue : qfalse;
-	
-	/* any light that is controlled (has a targetname) must have a unique style number generated for it */
-	numStyles = 0;
-	for( i = 1; i < numEntities; i++ )
-	{
-		e = &entities[ i ];
-
-		t = ValueForKey( e, "classname" );
-		if( Q_strncasecmp( t, "light", 5 ) )
-			continue;
-		t = ValueForKey( e, "targetname" );
-		if( t[ 0 ] == '\0' )
-		{
-			/* ydnar: strip the light from the BSP file */
-			if( keepLights == qfalse )
-			{
-				ep = e->epairs;
-				while( ep != NULL )
-				{
-					next = ep->next;
-					free( ep->key );
-					free( ep->value );
-					free( ep );
-					ep = next;
-				}
-				e->epairs = NULL;
-				numStrippedLights++;
-			}
-			
-			/* next light */
-			continue;
-		}
-		
-		/* get existing style */
-		style = IntForKey( e, "style" );
-		if( style < LS_NORMAL || style > LS_NONE )
-			Error( "Invalid lightstyle (%d) on entity %d", style, i );
-		
-		/* find this targetname */
-		for( j = 0; j < numStyles; j++ )
-			if( lightStyles[ j ] == style && !strcmp( lightTargets[ j ], t ) )
-				break;
-		
-		/* add a new style */
-		if( j >= numStyles )
-		{
-			if( numStyles == MAX_SWITCHED_LIGHTS )
-				Error( "MAX_SWITCHED_LIGHTS (%d) exceeded, reduce the number of lights with targetnames", MAX_SWITCHED_LIGHTS );
-			strcpy( lightTargets[ j ], t );
-			lightStyles[ j ] = style;
-			numStyles++;
-		}
-		
-		/* set explicit style */
-		sprintf( value, "%d", 32 + j );
-		SetKeyValue( e, "style", value );
-		
-		/* set old style */
-		if( style != LS_NORMAL )
-		{
-			sprintf( value, "%d", style );
-			SetKeyValue( e, "switch_style", value );
-		}
-	}
-	
-	/* emit some statistics */
-	Sys_FPrintf( SYS_VRB, "%9d light entities stripped\n", numStrippedLights );
-}
-
-
-
-/*
-BeginBSPFile()
-starts a new bsp file
-*/
-
-void BeginBSPFile( void )
-{
-	/* these values may actually be initialized if the file existed when loaded, so clear them explicitly */
-	numBSPModels = 0;
-	numBSPNodes = 0;
-	numBSPBrushSides = 0;
-	numBSPLeafSurfaces = 0;
-	numBSPLeafBrushes = 0;
-	
-	/* leave leaf 0 as an error, because leafs are referenced as negative number nodes */
-	numBSPLeafs = 1;
-	
-	
-	/* ydnar: gs mods: set the first 6 drawindexes to 0 1 2 2 1 3 for triangles and quads */
-	numBSPDrawIndexes = 6;
-	bspDrawIndexes[ 0 ] = 0;
-	bspDrawIndexes[ 1 ] = 1;
-	bspDrawIndexes[ 2 ] = 2;
-	bspDrawIndexes[ 3 ] = 0;
-	bspDrawIndexes[ 4 ] = 2;
-	bspDrawIndexes[ 5 ] = 3;
-}
-
-
-
-/*
-EndBSPFile()
-finishes a new bsp and writes to disk
-*/
-
-void EndBSPFile( void )
-{
-	char	path[ 1024 ];
-	
-
-	EmitPlanes();
-	
-	numBSPEntities = numEntities;
-	UnparseEntities();
-	
-	/* write the surface extra file */
-	WriteSurfaceExtraFile( source );
-	
-	/* write the bsp */
-	sprintf( path, "%s.bsp", source );
-	Sys_Printf( "Writing %s\n", path );
-	WriteBSPFile( path );
-}
-
-
-
-/*
-EmitBrushes()
-writes the brush list to the bsp
-*/
-
-void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes )
-{
-	int				j;
-	brush_t			*b;
-	bspBrush_t		*db;
-	bspBrushSide_t	*cp;
-	
-	
-	/* set initial brush */
-	if( firstBrush != NULL )
-		*firstBrush = numBSPBrushes;
-	if( numBrushes != NULL )
-		*numBrushes = 0;
-	
-	/* walk list of brushes */
-	for( b = brushes; b != NULL; b = b->next )
-	{
-		/* check limits */
-		if( numBSPBrushes == MAX_MAP_BRUSHES )
-			Error( "MAX_MAP_BRUSHES (%d)", numBSPBrushes );
-		
-		/* get bsp brush */
-		b->outputNum = numBSPBrushes;
-		db = &bspBrushes[ numBSPBrushes ];
-		numBSPBrushes++;
-		if( numBrushes != NULL )
-			(*numBrushes)++;
-		
-		db->shaderNum = EmitShader( b->contentShader->shader, &b->contentShader->contentFlags, &b->contentShader->surfaceFlags );
-		db->firstSide = numBSPBrushSides;
-		
-		/* walk sides */
-		db->numSides = 0;
-		for( j = 0; j < b->numsides; j++ )
-		{
-			/* set output number to bogus initially */
-			b->sides[ j ].outputNum = -1;
-			
-			/* don't emit generated backSide sides */
-			if ( b->sides[ j ].backSide )
-				continue;
-			
-			/* check count */
-			if( numBSPBrushSides == MAX_MAP_BRUSHSIDES )
-				Error( "MAX_MAP_BRUSHSIDES ");
-			
-			/* emit side */
-			b->sides[ j ].outputNum = numBSPBrushSides;
-			cp = &bspBrushSides[ numBSPBrushSides ];
-			db->numSides++;
-			numBSPBrushSides++;
-			cp->planeNum = b->sides[ j ].planenum;
-			
-			/* emit shader */
-			if( b->sides[ j ].shaderInfo )
-				cp->shaderNum = EmitShader( b->sides[ j ].shaderInfo->shader, &b->sides[ j ].shaderInfo->contentFlags, &b->sides[ j ].shaderInfo->surfaceFlags );
-			else
-				cp->shaderNum = EmitShader( NULL, NULL, NULL );
-		}
-	}
-}
-
-
-
-/*
-EmitFogs() - ydnar
-turns map fogs into bsp fogs
-*/
-
-void EmitFogs( void )
-{
-	int			i, j;
-	
-	
-	/* setup */
-	numBSPFogs = numMapFogs;
-	
-	/* walk list */
-	for( i = 0; i < numMapFogs; i++ )
-	{
-		/* set shader */
-		strcpy( bspFogs[ i ].shader, mapFogs[ i ].si->shader );
-		
-		/* global fog doesn't have an associated brush */
-		if( mapFogs[ i ].brush == NULL )
-		{
-			bspFogs[ i ].brushNum = -1;
-			bspFogs[ i ].visibleSide = -1;
-		}
-		else
-		{
-			/* set brush */
-			bspFogs[ i ].brushNum = mapFogs[ i ].brush->outputNum;
-			
-			/* try to use forced visible side */
-			if( mapFogs[ i ].visibleSide >= 0 )
-			{
-				bspFogs[ i ].visibleSide = mapFogs[ i ].visibleSide;
-				continue;
-			}
-			
-			/* find visible side */
-			for( j = 0; j < 6; j++ )
-			{
-				if( mapFogs[ i ].brush->sides[ j ].visibleHull != NULL )
-				{
-					Sys_Printf( "Fog %d has visible side %d\n", i, j );
-					bspFogs[ i ].visibleSide = j;
-					break;
-				}
-			}
-		}
-	}
-}
-
-
-
-/*
-BeginModel()
-sets up a new brush model
-*/
-
-void BeginModel( void )
-{
-	bspModel_t	*mod;
-	brush_t		*b;
-	entity_t	*e;
-	vec3_t		mins, maxs;
-	vec3_t		lgMins, lgMaxs;		/* ydnar: lightgrid mins/maxs */
-	parseMesh_t	*p;
-	int			i;
-	
-	
-	/* test limits */
-	if( numBSPModels == MAX_MAP_MODELS )
-		Error( "MAX_MAP_MODELS" );
-	
-	/* get model and entity */
-	mod = &bspModels[ numBSPModels ];
-	e = &entities[ mapEntityNum ];
-	
-	/* ydnar: lightgrid mins/maxs */
-	ClearBounds( lgMins, lgMaxs );
-	
-	/* bound the brushes */
-	ClearBounds( mins, maxs );
-	for ( b = e->brushes; b; b = b->next )
-	{
-		/* ignore non-real brushes (origin, etc) */
-		if( b->numsides == 0 )
-			continue;
-		AddPointToBounds( b->mins, mins, maxs );
-		AddPointToBounds( b->maxs, mins, maxs );
-		
-		/* ydnar: lightgrid bounds */
-		if( b->compileFlags & C_LIGHTGRID )
-		{
-			AddPointToBounds( b->mins, lgMins, lgMaxs );
-			AddPointToBounds( b->maxs, lgMins, lgMaxs );
-		}
-	}
-	
-	/* bound patches */
-	for( p = e->patches; p; p = p->next )
-	{
-		for( i = 0; i < (p->mesh.width * p->mesh.height); i++ )
-			AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs );
-	}
-	
-	/* ydnar: lightgrid mins/maxs */
-	if( lgMins[ 0 ] < 99999 )
-	{
-		/* use lightgrid bounds */
-		VectorCopy( lgMins, mod->mins );
-		VectorCopy( lgMaxs, mod->maxs );
-	}
-	else
-	{
-		/* use brush/patch bounds */
-		VectorCopy( mins, mod->mins );
-		VectorCopy( maxs, mod->maxs );
-	}
-	
-	/* note size */
-	Sys_FPrintf( SYS_VRB, "BSP bounds: { %f %f %f } { %f %f %f }\n", mins[ 0 ], mins[ 1 ], mins[ 2 ], maxs[ 0 ], maxs[ 1 ], maxs[ 2 ] );
-	Sys_FPrintf( SYS_VRB, "Lightgrid bounds: { %f %f %f } { %f %f %f }\n", lgMins[ 0 ], lgMins[ 1 ], lgMins[ 2 ], lgMaxs[ 0 ], lgMaxs[ 1 ], lgMaxs[ 2 ] );
-	
-	/* set firsts */
-	mod->firstBSPSurface = numBSPDrawSurfaces;
-	mod->firstBSPBrush = numBSPBrushes;
-}
-
-
-
-
-/*
-EndModel()
-finish a model's processing
-*/
-
-void EndModel( entity_t *e, node_t *headnode )
-{
-	bspModel_t	*mod;
-	
-	
-	/* note it */
-	Sys_FPrintf( SYS_VRB, "--- EndModel ---\n" );
-	
-	/* emit the bsp */
-	mod = &bspModels[ numBSPModels ];
-	EmitDrawNode_r( headnode );
-	
-	/* set surfaces and brushes */
-	mod->numBSPSurfaces = numBSPDrawSurfaces - mod->firstBSPSurface;
-	mod->firstBSPBrush = e->firstBrush;
-	mod->numBSPBrushes = e->numBrushes;
-	
-	/* increment model count */
-	numBSPModels++;
-}
-
-
-
+/*
+Copyright (C) 1999-2007 id Software, Inc. and contributors.
+For a list of contributors, see the accompanying CONTRIBUTORS file.
+
+This file is part of GtkRadiant.
+
+GtkRadiant 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.
+
+GtkRadiant 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 GtkRadiant; if not, write to the Free Software
+Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+
+----------------------------------------------------------------------------------
+
+This code has been altered significantly from its original form, to support
+several games based on the Quake III Arena engine, in the form of "Q3Map2."
+
+------------------------------------------------------------------------------- */
+
+
+
+/* marker */
+#define WRITEBSP_C
+
+
+
+/* dependencies */
+#include "q3map2.h"
+
+
+
+/*
+EmitShader()
+emits a bsp shader entry
+*/
+
+int	EmitShader( const char *shader, int *contentFlags, int *surfaceFlags )
+{
+	int				i;
+	shaderInfo_t	*si;
+	
+	
+	/* handle special cases */
+	if( shader == NULL )
+		shader = "noshader";
+	
+	/* try to find an existing shader */
+	for( i = 0; i < numBSPShaders; i++ )
+	{
+		/* ydnar: handle custom surface/content flags */
+		if( surfaceFlags != NULL && bspShaders[ i ].surfaceFlags != *surfaceFlags )
+			continue;
+		if( contentFlags != NULL && bspShaders[ i ].contentFlags != *contentFlags )
+			continue;
+		
+		/* compare name */
+		if( !Q_stricmp( shader, bspShaders[ i ].shader ) )
+			return i;
+	}
+	
+	/* get shaderinfo */
+	si = ShaderInfoForShader( shader );
+	
+	/* emit a new shader */
+	if( i == MAX_MAP_SHADERS )
+		Error( "MAX_MAP_SHADERS" );
+	numBSPShaders++;
+	strcpy( bspShaders[ i ].shader, shader );
+	bspShaders[ i ].surfaceFlags = si->surfaceFlags;
+	bspShaders[ i ].contentFlags = si->contentFlags;
+	
+	/* handle custom content/surface flags */
+	if( surfaceFlags != NULL )
+		bspShaders[ i ].surfaceFlags = *surfaceFlags;
+	if( contentFlags != NULL )
+		bspShaders[ i ].contentFlags = *contentFlags;
+	
+	/* recursively emit any damage shaders */
+	if( si->damageShader[ 0 ] != '\0' )
+	{
+		Sys_FPrintf( SYS_VRB, "Shader %s has damage shader %s\n", si->shader, si->damageShader );
+		EmitShader( si->damageShader, NULL, NULL );
+	}
+	
+	/* return it */
+	return i;
+}
+
+
+
+/*
+EmitPlanes()
+there is no oportunity to discard planes, because all of the original
+brushes will be saved in the map
+*/
+
+void EmitPlanes( void )
+{
+	int			i;
+	bspPlane_t	*bp;
+	plane_t		*mp;
+	
+	
+	/* walk plane list */
+	mp = mapplanes;
+	for( i = 0; i < nummapplanes; i++, mp++ )
+	{
+		bp = &bspPlanes[ numBSPPlanes ];
+		VectorCopy( mp->normal, bp->normal );
+		bp->dist = mp->dist;
+		numBSPPlanes++;
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d BSP planes\n", numBSPPlanes );
+}
+
+
+
+/*
+EmitLeaf()
+emits a leafnode to the bsp file
+*/
+
+void EmitLeaf( node_t *node )
+{
+	bspLeaf_t		*leaf_p;
+	brush_t			*b;
+	drawSurfRef_t	*dsr;
+	int				i = 0;
+
+	
+	/* check limits */
+	if( numBSPLeafs >= MAX_MAP_LEAFS )
+		Error( "MAX_MAP_LEAFS" );
+
+	leaf_p = &bspLeafs[numBSPLeafs];
+	numBSPLeafs++;
+
+	leaf_p->cluster = node->cluster;
+	leaf_p->area = node->area;
+
+	/* emit bounding box */
+	VectorCopy( node->mins, leaf_p->mins );
+	VectorCopy( node->maxs, leaf_p->maxs );
+	
+	/* emit leaf brushes */
+	leaf_p->firstBSPLeafBrush = numBSPLeafBrushes;
+	for( b = node->brushlist; b; b = b->next )
+	{
+		/* something is corrupting brushes */
+		if( (int) b < 256 )
+		{
+			Sys_Printf( "WARNING: Node brush list corrupted (0x%08X)\n", b );
+			break;
+		}
+		//%	if( b->guard != 0xDEADBEEF )
+		//%		Sys_Printf( "Brush %6d: 0x%08X Guard: 0x%08X Next: 0x%08X Original: 0x%08X Sides: %d\n", b->brushNum, b, b, b->next, b->original, b->numsides );
+		
+		if( numBSPLeafBrushes >= MAX_MAP_LEAFBRUSHES )
+			Error( "MAX_MAP_LEAFBRUSHES" );
+		bspLeafBrushes[ numBSPLeafBrushes ] = b->original->outputNum;
+		numBSPLeafBrushes++;
+	}
+	
+	leaf_p->numBSPLeafBrushes = numBSPLeafBrushes - leaf_p->firstBSPLeafBrush;
+	
+	/* emit leaf surfaces */
+	if( node->opaque )
+		return;
+	
+	/* add the drawSurfRef_t drawsurfs */
+	leaf_p->firstBSPLeafSurface = numBSPLeafSurfaces;
+	for ( dsr = node->drawSurfReferences; dsr; dsr = dsr->nextRef )
+	{
+		if( numBSPLeafSurfaces >= MAX_MAP_LEAFFACES )
+			Error( "MAX_MAP_LEAFFACES" );
+		bspLeafSurfaces[ numBSPLeafSurfaces ] = dsr->outputNum;
+		numBSPLeafSurfaces++;			
+	}
+	
+	leaf_p->numBSPLeafSurfaces = numBSPLeafSurfaces - leaf_p->firstBSPLeafSurface;
+}
+
+
+/*
+EmitDrawNode_r()
+recursively emit the bsp nodes
+*/
+
+int EmitDrawNode_r( node_t *node )
+{
+	bspNode_t	*n;
+	int			i;
+	
+	
+	/* check for leafnode */
+	if( node->planenum == PLANENUM_LEAF )
+	{
+		EmitLeaf( node );
+		return -numBSPLeafs;
+	}
+	
+	/* emit a node */
+	if( numBSPNodes == MAX_MAP_NODES )
+		Error( "MAX_MAP_NODES" );
+	n = &bspNodes[ numBSPNodes ];
+	numBSPNodes++;
+	
+	VectorCopy (node->mins, n->mins);
+	VectorCopy (node->maxs, n->maxs);
+
+	if (node->planenum & 1)
+		Error ("WriteDrawNodes_r: odd planenum");
+	n->planeNum = node->planenum;
+
+	//
+	// recursively output the other nodes
+	//	
+	for (i=0 ; i<2 ; i++)
+	{
+		if (node->children[i]->planenum == PLANENUM_LEAF)
+		{
+			n->children[i] = -(numBSPLeafs + 1);
+			EmitLeaf (node->children[i]);
+		}
+		else
+		{
+			n->children[i] = numBSPNodes;	
+			EmitDrawNode_r (node->children[i]);
+		}
+	}
+
+	return n - bspNodes;
+}
+
+
+
+/*
+============
+SetModelNumbers
+============
+*/
+void SetModelNumbers (void)
+{
+	int		i;
+	int		models;
+	char	value[10];
+
+	models = 1;
+	for ( i=1 ; i<numEntities ; i++ ) {
+		if ( entities[i].brushes || entities[i].patches ) {
+			sprintf ( value, "*%i", models );
+			models++;
+			SetKeyValue (&entities[i], "model", value);
+		}
+	}
+
+}
+
+
+
+
+/*
+SetLightStyles()
+sets style keys for entity lights
+*/
+
+void SetLightStyles( void )
+{
+	int			i, j, style, numStyles;
+	qboolean	keepLights;
+	const char	*t;
+	entity_t	*e;
+	epair_t		*ep, *next;
+	char		value[ 10 ];
+	char		lightTargets[ MAX_SWITCHED_LIGHTS ][ 64 ];
+	int			lightStyles[ MAX_SWITCHED_LIGHTS ];
+	
+	
+	/* ydnar: determine if we keep lights in the bsp */
+	t = ValueForKey( &entities[ 0 ], "_keepLights" );
+	keepLights = (t[ 0 ] == '1') ? qtrue : qfalse;
+	
+	/* any light that is controlled (has a targetname) must have a unique style number generated for it */
+	numStyles = 0;
+	for( i = 1; i < numEntities; i++ )
+	{
+		e = &entities[ i ];
+
+		t = ValueForKey( e, "classname" );
+		if( Q_strncasecmp( t, "light", 5 ) )
+			continue;
+		t = ValueForKey( e, "targetname" );
+		if( t[ 0 ] == '\0' )
+		{
+			/* ydnar: strip the light from the BSP file */
+			if( keepLights == qfalse )
+			{
+				ep = e->epairs;
+				while( ep != NULL )
+				{
+					next = ep->next;
+					free( ep->key );
+					free( ep->value );
+					free( ep );
+					ep = next;
+				}
+				e->epairs = NULL;
+				numStrippedLights++;
+			}
+			
+			/* next light */
+			continue;
+		}
+		
+		/* get existing style */
+		style = IntForKey( e, "style" );
+		if( style < LS_NORMAL || style > LS_NONE )
+			Error( "Invalid lightstyle (%d) on entity %d", style, i );
+		
+		/* find this targetname */
+		for( j = 0; j < numStyles; j++ )
+			if( lightStyles[ j ] == style && !strcmp( lightTargets[ j ], t ) )
+				break;
+		
+		/* add a new style */
+		if( j >= numStyles )
+		{
+			if( numStyles == MAX_SWITCHED_LIGHTS )
+				Error( "MAX_SWITCHED_LIGHTS (%d) exceeded, reduce the number of lights with targetnames", MAX_SWITCHED_LIGHTS );
+			strcpy( lightTargets[ j ], t );
+			lightStyles[ j ] = style;
+			numStyles++;
+		}
+		
+		/* set explicit style */
+		sprintf( value, "%d", 32 + j );
+		SetKeyValue( e, "style", value );
+		
+		/* set old style */
+		if( style != LS_NORMAL )
+		{
+			sprintf( value, "%d", style );
+			SetKeyValue( e, "switch_style", value );
+		}
+	}
+	
+	/* emit some statistics */
+	Sys_FPrintf( SYS_VRB, "%9d light entities stripped\n", numStrippedLights );
+}
+
+
+
+/*
+BeginBSPFile()
+starts a new bsp file
+*/
+
+void BeginBSPFile( void )
+{
+	/* these values may actually be initialized if the file existed when loaded, so clear them explicitly */
+	numBSPModels = 0;
+	numBSPNodes = 0;
+	numBSPBrushSides = 0;
+	numBSPLeafSurfaces = 0;
+	numBSPLeafBrushes = 0;
+	
+	/* leave leaf 0 as an error, because leafs are referenced as negative number nodes */
+	numBSPLeafs = 1;
+	
+	
+	/* ydnar: gs mods: set the first 6 drawindexes to 0 1 2 2 1 3 for triangles and quads */
+	numBSPDrawIndexes = 6;
+	bspDrawIndexes[ 0 ] = 0;
+	bspDrawIndexes[ 1 ] = 1;
+	bspDrawIndexes[ 2 ] = 2;
+	bspDrawIndexes[ 3 ] = 0;
+	bspDrawIndexes[ 4 ] = 2;
+	bspDrawIndexes[ 5 ] = 3;
+}
+
+
+
+/*
+EndBSPFile()
+finishes a new bsp and writes to disk
+*/
+
+void EndBSPFile( void )
+{
+	char	path[ 1024 ];
+	
+
+	EmitPlanes();
+	
+	numBSPEntities = numEntities;
+	UnparseEntities();
+	
+	/* write the surface extra file */
+	WriteSurfaceExtraFile( source );
+	
+	/* write the bsp */
+	sprintf( path, "%s.bsp", source );
+	Sys_Printf( "Writing %s\n", path );
+	WriteBSPFile( path );
+}
+
+
+
+/*
+EmitBrushes()
+writes the brush list to the bsp
+*/
+
+void EmitBrushes( brush_t *brushes, int *firstBrush, int *numBrushes )
+{
+	int				j;
+	brush_t			*b;
+	bspBrush_t		*db;
+	bspBrushSide_t	*cp;
+	
+	
+	/* set initial brush */
+	if( firstBrush != NULL )
+		*firstBrush = numBSPBrushes;
+	if( numBrushes != NULL )
+		*numBrushes = 0;
+	
+	/* walk list of brushes */
+	for( b = brushes; b != NULL; b = b->next )
+	{
+		/* check limits */
+		if( numBSPBrushes == MAX_MAP_BRUSHES )
+			Error( "MAX_MAP_BRUSHES (%d)", numBSPBrushes );
+		
+		/* get bsp brush */
+		b->outputNum = numBSPBrushes;
+		db = &bspBrushes[ numBSPBrushes ];
+		numBSPBrushes++;
+		if( numBrushes != NULL )
+			(*numBrushes)++;
+		
+		db->shaderNum = EmitShader( b->contentShader->shader, &b->contentShader->contentFlags, &b->contentShader->surfaceFlags );
+		db->firstSide = numBSPBrushSides;
+		
+		/* walk sides */
+		db->numSides = 0;
+		for( j = 0; j < b->numsides; j++ )
+		{
+			/* set output number to bogus initially */
+			b->sides[ j ].outputNum = -1;
+			
+			/* don't emit generated backSide sides */
+			if ( b->sides[ j ].backSide )
+				continue;
+			
+			/* check count */
+			if( numBSPBrushSides == MAX_MAP_BRUSHSIDES )
+				Error( "MAX_MAP_BRUSHSIDES ");
+			
+			/* emit side */
+			b->sides[ j ].outputNum = numBSPBrushSides;
+			cp = &bspBrushSides[ numBSPBrushSides ];
+			db->numSides++;
+			numBSPBrushSides++;
+			cp->planeNum = b->sides[ j ].planenum;
+			
+			/* emit shader */
+			if( b->sides[ j ].shaderInfo )
+				cp->shaderNum = EmitShader( b->sides[ j ].shaderInfo->shader, &b->sides[ j ].shaderInfo->contentFlags, &b->sides[ j ].shaderInfo->surfaceFlags );
+			else
+				cp->shaderNum = EmitShader( NULL, NULL, NULL );
+		}
+	}
+}
+
+
+
+/*
+EmitFogs() - ydnar
+turns map fogs into bsp fogs
+*/
+
+void EmitFogs( void )
+{
+	int			i, j;
+	
+	
+	/* setup */
+	numBSPFogs = numMapFogs;
+	
+	/* walk list */
+	for( i = 0; i < numMapFogs; i++ )
+	{
+		/* set shader */
+		strcpy( bspFogs[ i ].shader, mapFogs[ i ].si->shader );
+		
+		/* global fog doesn't have an associated brush */
+		if( mapFogs[ i ].brush == NULL )
+		{
+			bspFogs[ i ].brushNum = -1;
+			bspFogs[ i ].visibleSide = -1;
+		}
+		else
+		{
+			/* set brush */
+			bspFogs[ i ].brushNum = mapFogs[ i ].brush->outputNum;
+			
+			/* try to use forced visible side */
+			if( mapFogs[ i ].visibleSide >= 0 )
+			{
+				bspFogs[ i ].visibleSide = mapFogs[ i ].visibleSide;
+				continue;
+			}
+			
+			/* find visible side */
+			for( j = 0; j < 6; j++ )
+			{
+				if( mapFogs[ i ].brush->sides[ j ].visibleHull != NULL )
+				{
+					Sys_Printf( "Fog %d has visible side %d\n", i, j );
+					bspFogs[ i ].visibleSide = j;
+					break;
+				}
+			}
+		}
+	}
+}
+
+
+
+/*
+BeginModel()
+sets up a new brush model
+*/
+
+void BeginModel( void )
+{
+	bspModel_t	*mod;
+	brush_t		*b;
+	entity_t	*e;
+	vec3_t		mins, maxs;
+	vec3_t		lgMins, lgMaxs;		/* ydnar: lightgrid mins/maxs */
+	parseMesh_t	*p;
+	int			i;
+	
+	
+	/* test limits */
+	if( numBSPModels == MAX_MAP_MODELS )
+		Error( "MAX_MAP_MODELS" );
+	
+	/* get model and entity */
+	mod = &bspModels[ numBSPModels ];
+	e = &entities[ mapEntityNum ];
+	
+	/* ydnar: lightgrid mins/maxs */
+	ClearBounds( lgMins, lgMaxs );
+	
+	/* bound the brushes */
+	ClearBounds( mins, maxs );
+	for ( b = e->brushes; b; b = b->next )
+	{
+		/* ignore non-real brushes (origin, etc) */
+		if( b->numsides == 0 )
+			continue;
+		AddPointToBounds( b->mins, mins, maxs );
+		AddPointToBounds( b->maxs, mins, maxs );
+		
+		/* ydnar: lightgrid bounds */
+		if( b->compileFlags & C_LIGHTGRID )
+		{
+			AddPointToBounds( b->mins, lgMins, lgMaxs );
+			AddPointToBounds( b->maxs, lgMins, lgMaxs );
+		}
+	}
+	
+	/* bound patches */
+	for( p = e->patches; p; p = p->next )
+	{
+		for( i = 0; i < (p->mesh.width * p->mesh.height); i++ )
+			AddPointToBounds( p->mesh.verts[i].xyz, mins, maxs );
+	}
+	
+	/* ydnar: lightgrid mins/maxs */
+	if( lgMins[ 0 ] < 99999 )
+	{
+		/* use lightgrid bounds */
+		VectorCopy( lgMins, mod->mins );
+		VectorCopy( lgMaxs, mod->maxs );
+	}
+	else
+	{
+		/* use brush/patch bounds */
+		VectorCopy( mins, mod->mins );
+		VectorCopy( maxs, mod->maxs );
+	}
+	
+	/* note size */
+	Sys_FPrintf( SYS_VRB, "BSP bounds: { %f %f %f } { %f %f %f }\n", mins[ 0 ], mins[ 1 ], mins[ 2 ], maxs[ 0 ], maxs[ 1 ], maxs[ 2 ] );
+	Sys_FPrintf( SYS_VRB, "Lightgrid bounds: { %f %f %f } { %f %f %f }\n", lgMins[ 0 ], lgMins[ 1 ], lgMins[ 2 ], lgMaxs[ 0 ], lgMaxs[ 1 ], lgMaxs[ 2 ] );
+	
+	/* set firsts */
+	mod->firstBSPSurface = numBSPDrawSurfaces;
+	mod->firstBSPBrush = numBSPBrushes;
+}
+
+
+
+
+/*
+EndModel()
+finish a model's processing
+*/
+
+void EndModel( entity_t *e, node_t *headnode )
+{
+	bspModel_t	*mod;
+	
+	
+	/* note it */
+	Sys_FPrintf( SYS_VRB, "--- EndModel ---\n" );
+	
+	/* emit the bsp */
+	mod = &bspModels[ numBSPModels ];
+	EmitDrawNode_r( headnode );
+	
+	/* set surfaces and brushes */
+	mod->numBSPSurfaces = numBSPDrawSurfaces - mod->firstBSPSurface;
+	mod->firstBSPBrush = e->firstBrush;
+	mod->numBSPBrushes = e->numBrushes;
+	
+	/* increment model count */
+	numBSPModels++;
+}
+
+
+
-- 
2.39.5